Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 11:56:39

0001 // -*- C++ -*-
0002 //
0003 // Package:    MuonGeometrySanityCheck
0004 // Class:      MuonGeometrySanityCheck
0005 //
0006 /**\class MuonGeometrySanityCheck MuonGeometrySanityCheck.cc Alignment/MuonAlignment/plugins/MuonGeometrySanityCheck.cc
0007 
0008  Description: <one line class summary>
0009 
0010  Implementation:
0011      <Notes on implementation>
0012 */
0013 //
0014 // Original Author:  Jim Pivarski
0015 //         Created:  Sat Jul  3 13:33:13 CDT 2010
0016 // $Id: MuonGeometrySanityCheck.cc,v 1.3 2011/10/12 22:13:00 khotilov Exp $
0017 //
0018 //
0019 
0020 // system include files
0021 #include "FWCore/Framework/interface/Frameworkfwd.h"
0022 #include "FWCore/Framework/interface/one/EDAnalyzer.h"
0023 #include "FWCore/Framework/interface/EventSetup.h"
0024 #include "FWCore/Framework/interface/ESHandle.h"
0025 #include "FWCore/Framework/interface/Event.h"
0026 #include "FWCore/Framework/interface/MakerMacros.h"
0027 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0028 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0029 
0030 #include "Geometry/DTGeometry/interface/DTGeometry.h"
0031 #include "Geometry/CSCGeometry/interface/CSCGeometry.h"
0032 #include "Geometry/Records/interface/MuonGeometryRecord.h"
0033 #include "Geometry/CommonDetUnit/interface/GeomDet.h"
0034 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
0035 #include "DataFormats/DetId/interface/DetId.h"
0036 #include "DataFormats/MuonDetId/interface/MuonSubdetId.h"
0037 #include "DataFormats/MuonDetId/interface/DTChamberId.h"
0038 #include "DataFormats/MuonDetId/interface/DTSuperLayerId.h"
0039 #include "DataFormats/MuonDetId/interface/DTLayerId.h"
0040 #include "DataFormats/MuonDetId/interface/CSCDetId.h"
0041 #include "DataFormats/CLHEP/interface/AlgebraicObjects.h"
0042 
0043 //
0044 // class decleration
0045 //
0046 
0047 class MuonGeometrySanityCheckCustomFrame {
0048 public:
0049   MuonGeometrySanityCheckCustomFrame(const edm::ParameterSet &iConfig, std::string name);
0050 
0051   GlobalPoint transform(GlobalPoint point) const;
0052   GlobalPoint transformInverse(GlobalPoint point) const;
0053   AlgebraicMatrix matrix;
0054   AlgebraicMatrix matrixInverse;
0055 };
0056 
0057 class MuonGeometrySanityCheckPoint {
0058 public:
0059   MuonGeometrySanityCheckPoint(const edm::ParameterSet &iConfig,
0060                                const std::map<std::string, const MuonGeometrySanityCheckCustomFrame *> &frames);
0061 
0062   enum { kDTChamber, kDTSuperLayer, kDTLayer, kCSCChamber, kCSCLayer };
0063 
0064   enum { kGlobal, kLocal, kChamber, kCustom };
0065 
0066   std::string detName() const;
0067 
0068   int type;
0069   DetId detector;
0070   int frame;
0071   const MuonGeometrySanityCheckCustomFrame *customFrame;
0072   GlobalPoint displacement;
0073   bool has_expectation;
0074   GlobalPoint expectation;
0075   std::string name;
0076   int outputFrame;
0077   const MuonGeometrySanityCheckCustomFrame *outputCustomFrame;
0078 
0079 private:
0080   bool numeric(std::string s);
0081   int number(std::string s);
0082 };
0083 
0084 class MuonGeometrySanityCheck : public edm::one::EDAnalyzer<> {
0085 public:
0086   explicit MuonGeometrySanityCheck(const edm::ParameterSet &iConfig);
0087   ~MuonGeometrySanityCheck() override;
0088 
0089 private:
0090   void analyze(const edm::Event &, const edm::EventSetup &iConfig) override;
0091 
0092   std::string printout;
0093   double tolerance;
0094   std::string prefix;
0095   std::map<std::string, const MuonGeometrySanityCheckCustomFrame *> m_frames;
0096   std::vector<MuonGeometrySanityCheckPoint> m_points;
0097 
0098   const edm::ESGetToken<DTGeometry, MuonGeometryRecord> dtGeomToken_;
0099   const edm::ESGetToken<CSCGeometry, MuonGeometryRecord> cscGeomToken_;
0100 };
0101 
0102 //
0103 // constants, enums and typedefs
0104 //
0105 
0106 //
0107 // static data member definitions
0108 //
0109 
0110 //
0111 // constructors and destructor
0112 //
0113 
0114 MuonGeometrySanityCheck::MuonGeometrySanityCheck(const edm::ParameterSet &iConfig)
0115     : dtGeomToken_(esConsumes<edm::Transition::BeginRun>()), cscGeomToken_(esConsumes<edm::Transition::BeginRun>()) {
0116   printout = iConfig.getParameter<std::string>("printout");
0117   if (printout != std::string("all") && printout != std::string("bad")) {
0118     throw cms::Exception("BadConfig") << "Printout must be \"all\" or \"bad\"." << std::endl;
0119   }
0120 
0121   tolerance = iConfig.getParameter<double>("tolerance");
0122   if (tolerance <= 0) {
0123     throw cms::Exception("BadConfig") << "Tolerance must be positive." << std::endl;
0124   }
0125 
0126   prefix = iConfig.getParameter<std::string>("prefix");
0127 
0128   std::vector<edm::ParameterSet> frames = iConfig.getParameter<std::vector<edm::ParameterSet> >("frames");
0129   for (std::vector<edm::ParameterSet>::const_iterator frame = frames.begin(); frame != frames.end(); ++frame) {
0130     std::string name = frame->getParameter<std::string>("name");
0131     if (m_frames.find(name) != m_frames.end()) {
0132       throw cms::Exception("BadConfig") << "Custom frame \"" << name << "\" has been defined twice." << std::endl;
0133     }
0134     m_frames[name] = new MuonGeometrySanityCheckCustomFrame(*frame, name);
0135   }
0136 
0137   std::vector<edm::ParameterSet> points = iConfig.getParameter<std::vector<edm::ParameterSet> >("points");
0138   for (std::vector<edm::ParameterSet>::const_iterator point = points.begin(); point != points.end(); ++point) {
0139     m_points.push_back(MuonGeometrySanityCheckPoint(*point, m_frames));
0140   }
0141 }
0142 
0143 MuonGeometrySanityCheck::~MuonGeometrySanityCheck() {
0144   for (std::map<std::string, const MuonGeometrySanityCheckCustomFrame *>::iterator iter = m_frames.begin();
0145        iter != m_frames.end();
0146        ++iter) {
0147     delete iter->second;
0148   }
0149 }
0150 
0151 MuonGeometrySanityCheckCustomFrame::MuonGeometrySanityCheckCustomFrame(const edm::ParameterSet &iConfig,
0152                                                                        std::string name) {
0153   std::vector<double> numbers = iConfig.getParameter<std::vector<double> >("matrix");
0154   if (numbers.size() != 9) {
0155     throw cms::Exception("BadConfig") << "Custom frame \"" << name << "\" has a matrix which is not 3x3." << std::endl;
0156   }
0157 
0158   matrix = AlgebraicMatrix(3, 3);
0159   matrix[0][0] = numbers[0];
0160   matrix[0][1] = numbers[1];
0161   matrix[0][2] = numbers[2];
0162   matrix[1][0] = numbers[3];
0163   matrix[1][1] = numbers[4];
0164   matrix[1][2] = numbers[5];
0165   matrix[2][0] = numbers[6];
0166   matrix[2][1] = numbers[7];
0167   matrix[2][2] = numbers[8];
0168 
0169   int ierr;
0170   matrixInverse = matrix;
0171   matrixInverse.invert(ierr);
0172   if (ierr != 0) {
0173     throw cms::Exception("BadConfig") << "Could not invert matrix for custom frame \"" << name << "\"." << std::endl;
0174   }
0175 }
0176 
0177 GlobalPoint MuonGeometrySanityCheckCustomFrame::transform(GlobalPoint point) const {
0178   AlgebraicVector input(3);
0179   input[0] = point.x();
0180   input[1] = point.x();
0181   input[2] = point.x();
0182   AlgebraicVector output = matrix * input;
0183   return GlobalPoint(output[0], output[1], output[3]);
0184 }
0185 
0186 GlobalPoint MuonGeometrySanityCheckCustomFrame::transformInverse(GlobalPoint point) const {
0187   AlgebraicVector input(3);
0188   input[0] = point.x();
0189   input[1] = point.x();
0190   input[2] = point.x();
0191   AlgebraicVector output = matrixInverse * input;
0192   return GlobalPoint(output[0], output[1], output[3]);
0193 }
0194 
0195 bool MuonGeometrySanityCheckPoint::numeric(std::string s) {
0196   return (s == std::string("0") || s == std::string("1") || s == std::string("2") || s == std::string("3") ||
0197           s == std::string("4") || s == std::string("5") || s == std::string("6") || s == std::string("7") ||
0198           s == std::string("8") || s == std::string("9"));
0199 }
0200 
0201 int MuonGeometrySanityCheckPoint::number(std::string s) {
0202   if (s == std::string("0"))
0203     return 0;
0204   else if (s == std::string("1"))
0205     return 1;
0206   else if (s == std::string("2"))
0207     return 2;
0208   else if (s == std::string("3"))
0209     return 3;
0210   else if (s == std::string("4"))
0211     return 4;
0212   else if (s == std::string("5"))
0213     return 5;
0214   else if (s == std::string("6"))
0215     return 6;
0216   else if (s == std::string("7"))
0217     return 7;
0218   else if (s == std::string("8"))
0219     return 8;
0220   else if (s == std::string("9"))
0221     return 9;
0222   else
0223     assert(false);
0224 }
0225 
0226 MuonGeometrySanityCheckPoint::MuonGeometrySanityCheckPoint(
0227     const edm::ParameterSet &iConfig, const std::map<std::string, const MuonGeometrySanityCheckCustomFrame *> &frames) {
0228   std::string detName = iConfig.getParameter<std::string>("detector");
0229 
0230   bool parsing_error = false;
0231 
0232   bool barrel = (detName.substr(0, 2) == std::string("MB"));
0233   bool endcap = (detName.substr(0, 2) == std::string("ME"));
0234   if (!barrel && !endcap)
0235     parsing_error = true;
0236 
0237   if (!parsing_error && barrel) {
0238     int index = 2;
0239 
0240     bool plus = true;
0241     if (detName.substr(index, 1) == std::string("+")) {
0242       plus = true;
0243       index++;
0244     } else if (detName.substr(index, 1) == std::string("-")) {
0245       plus = false;
0246       index++;
0247     }
0248 
0249     int wheel = 0;
0250     bool wheel_digit = false;
0251     while (!parsing_error && numeric(detName.substr(index, 1))) {
0252       wheel *= 10;
0253       wheel += number(detName.substr(index, 1));
0254       wheel_digit = true;
0255       index++;
0256     }
0257     if (!plus)
0258       wheel *= -1;
0259     if (!wheel_digit)
0260       parsing_error = true;
0261 
0262     if (detName.substr(index, 1) != std::string("/"))
0263       parsing_error = true;
0264     index++;
0265 
0266     int station = 0;
0267     bool station_digit = false;
0268     while (!parsing_error && numeric(detName.substr(index, 1))) {
0269       station *= 10;
0270       station += number(detName.substr(index, 1));
0271       station_digit = true;
0272       index++;
0273     }
0274     if (!station_digit)
0275       parsing_error = true;
0276 
0277     if (detName.substr(index, 1) != std::string("/"))
0278       parsing_error = true;
0279     index++;
0280 
0281     int sector = 0;
0282     bool sector_digit = false;
0283     while (!parsing_error && numeric(detName.substr(index, 1))) {
0284       sector *= 10;
0285       sector += number(detName.substr(index, 1));
0286       sector_digit = true;
0287       index++;
0288     }
0289     if (!sector_digit)
0290       parsing_error = true;
0291 
0292     // these are optional
0293     int superlayer = 0;
0294     bool superlayer_digit = false;
0295     int layer = 0;
0296     if (detName.substr(index, 1) == std::string("/")) {
0297       index++;
0298       while (!parsing_error && numeric(detName.substr(index, 1))) {
0299         superlayer *= 10;
0300         superlayer += number(detName.substr(index, 1));
0301         superlayer_digit = true;
0302         index++;
0303       }
0304       if (!superlayer_digit)
0305         parsing_error = true;
0306 
0307       if (detName.substr(index, 1) == std::string("/")) {
0308         index++;
0309         while (!parsing_error && numeric(detName.substr(index, 1))) {
0310           layer *= 10;
0311           layer += number(detName.substr(index, 1));
0312           index++;
0313         }
0314       }
0315     }
0316 
0317     if (!parsing_error) {
0318       bool no_such_chamber = false;
0319 
0320       if (wheel < -2 || wheel > 2)
0321         no_such_chamber = true;
0322       if (station < 1 || station > 4)
0323         no_such_chamber = true;
0324       if (station == 4 && (sector < 1 || sector > 14))
0325         no_such_chamber = true;
0326       if (station < 4 && (sector < 1 || sector > 12))
0327         no_such_chamber = true;
0328 
0329       if (no_such_chamber) {
0330         throw cms::Exception("BadConfig") << "Chamber doesn't exist: MB" << (plus ? "+" : "-") << wheel << "/"
0331                                           << station << "/" << sector << std::endl;
0332       }
0333 
0334       if (superlayer == 0) {
0335         detector = DTChamberId(wheel, station, sector);
0336         type = kDTChamber;
0337       } else {
0338         bool no_such_superlayer = false;
0339         if (superlayer < 1 || superlayer > 3)
0340           no_such_superlayer = true;
0341         if (station == 4 && superlayer == 2)
0342           no_such_superlayer = true;
0343 
0344         if (no_such_superlayer) {
0345           throw cms::Exception("BadConfig") << "Superlayer doesn't exist: MB" << (plus ? "+" : "-") << wheel << "/"
0346                                             << station << "/" << sector << "/" << superlayer << std::endl;
0347         }
0348 
0349         if (layer == 0) {
0350           detector = DTSuperLayerId(wheel, station, sector, superlayer);
0351           type = kDTSuperLayer;
0352         } else {
0353           bool no_such_layer = false;
0354           if (layer < 1 || layer > 4)
0355             no_such_layer = true;
0356 
0357           if (no_such_layer) {
0358             throw cms::Exception("BadConfig")
0359                 << "Layer doesn't exist: MB" << (plus ? "+" : "-") << wheel << "/" << station << "/" << sector << "/"
0360                 << superlayer << "/" << layer << std::endl;
0361           }
0362 
0363           detector = DTLayerId(wheel, station, sector, superlayer, layer);
0364           type = kDTLayer;
0365         }
0366       }
0367     }
0368   } else if (!parsing_error && endcap) {
0369     int index = 2;
0370 
0371     bool plus = true;
0372     if (detName.substr(index, 1) == std::string("+")) {
0373       plus = true;
0374       index++;
0375     } else if (detName.substr(index, 1) == std::string("-")) {
0376       plus = false;
0377       index++;
0378     } else
0379       parsing_error = true;
0380 
0381     int station = 0;
0382     bool station_digit = false;
0383     while (!parsing_error && numeric(detName.substr(index, 1))) {
0384       station *= 10;
0385       station += number(detName.substr(index, 1));
0386       station_digit = true;
0387       index++;
0388     }
0389     if (!plus)
0390       station *= -1;
0391     if (!station_digit)
0392       parsing_error = true;
0393 
0394     if (detName.substr(index, 1) != std::string("/"))
0395       parsing_error = true;
0396     index++;
0397 
0398     int ring = 0;
0399     bool ring_digit = false;
0400     while (!parsing_error && numeric(detName.substr(index, 1))) {
0401       ring *= 10;
0402       ring += number(detName.substr(index, 1));
0403       ring_digit = true;
0404       index++;
0405     }
0406     if (!ring_digit)
0407       parsing_error = true;
0408 
0409     if (detName.substr(index, 1) != std::string("/"))
0410       parsing_error = true;
0411     index++;
0412 
0413     int chamber = 0;
0414     bool chamber_digit = false;
0415     while (!parsing_error && numeric(detName.substr(index, 1))) {
0416       chamber *= 10;
0417       chamber += number(detName.substr(index, 1));
0418       chamber_digit = true;
0419       index++;
0420     }
0421     if (!chamber_digit)
0422       parsing_error = true;
0423 
0424     // this is optional
0425     int layer = 0;
0426     bool layer_digit = false;
0427     if (detName.substr(index, 1) == std::string("/")) {
0428       index++;
0429       while (!parsing_error && numeric(detName.substr(index, 1))) {
0430         layer *= 10;
0431         layer += number(detName.substr(index, 1));
0432         layer_digit = true;
0433         index++;
0434       }
0435       if (!layer_digit)
0436         parsing_error = true;
0437     }
0438 
0439     if (!parsing_error) {
0440       bool no_such_chamber = false;
0441 
0442       int endcap = (station > 0 ? 1 : 2);
0443       station = abs(station);
0444       if (station < 1 || station > 4)
0445         no_such_chamber = true;
0446       if (station == 1 && (ring < 1 || ring > 4))
0447         no_such_chamber = true;
0448       if (station > 1 && (ring < 1 || ring > 2))
0449         no_such_chamber = true;
0450       if (station == 1 && (chamber < 1 || chamber > 36))
0451         no_such_chamber = true;
0452       if (station > 1 && ring == 1 && (chamber < 1 || chamber > 18))
0453         no_such_chamber = true;
0454       if (station > 1 && ring == 2 && (chamber < 1 || chamber > 36))
0455         no_such_chamber = true;
0456 
0457       if (no_such_chamber) {
0458         throw cms::Exception("BadConfig") << "Chamber doesn't exist: ME" << (endcap == 1 ? "+" : "-") << station << "/"
0459                                           << ring << "/" << chamber << std::endl;
0460       }
0461 
0462       if (layer == 0) {
0463         detector = CSCDetId(endcap, station, ring, chamber);
0464         type = kCSCChamber;
0465       } else {
0466         bool no_such_layer = false;
0467         if (layer < 1 || layer > 6)
0468           no_such_layer = true;
0469 
0470         if (no_such_layer) {
0471           throw cms::Exception("BadConfig") << "Layer doesn't exist: ME" << (endcap == 1 ? "+" : "-") << station << "/"
0472                                             << ring << "/" << chamber << "/" << layer << std::endl;
0473         }
0474 
0475         detector = CSCDetId(endcap, station, ring, chamber, layer);
0476         type = kCSCLayer;
0477       }
0478     }
0479   }
0480 
0481   if (parsing_error) {
0482     throw cms::Exception("BadConfig") << "Detector name is malformed: " << detName << std::endl;
0483   }
0484 
0485   std::string frameName = iConfig.getParameter<std::string>("frame");
0486   const std::map<std::string, const MuonGeometrySanityCheckCustomFrame *>::const_iterator frameIter =
0487       frames.find(frameName);
0488   if (frameName == std::string("global")) {
0489     frame = kGlobal;
0490     customFrame = nullptr;
0491   } else if (frameName == std::string("local")) {
0492     frame = kLocal;
0493     customFrame = nullptr;
0494   } else if (frameName == std::string("chamber")) {
0495     frame = kChamber;
0496     customFrame = nullptr;
0497   } else if (frameIter != frames.end()) {
0498     frame = kCustom;
0499     customFrame = frameIter->second;
0500   } else {
0501     throw cms::Exception("BadConfig") << "Frame \"" << frameName << "\" has not been defined." << std::endl;
0502   }
0503 
0504   std::vector<double> point = iConfig.getParameter<std::vector<double> >("displacement");
0505   if (point.size() != 3) {
0506     throw cms::Exception("BadConfig") << "Displacement relative to detector " << detName
0507                                       << " doesn't have exactly three components." << std::endl;
0508   }
0509 
0510   displacement = GlobalPoint(point[0], point[1], point[2]);
0511 
0512   const edm::Entry *entry = iConfig.retrieveUnknown("expectation");
0513   if (entry != nullptr) {
0514     has_expectation = true;
0515 
0516     point = iConfig.getParameter<std::vector<double> >("expectation");
0517     if (point.size() != 3) {
0518       throw cms::Exception("BadConfig") << "Expectation for detector " << detName << ", displacement " << displacement
0519                                         << " doesn't have exactly three components." << std::endl;
0520     }
0521 
0522     expectation = GlobalPoint(point[0], point[1], point[2]);
0523   } else {
0524     has_expectation = false;
0525   }
0526 
0527   entry = iConfig.retrieveUnknown("name");
0528   if (entry != nullptr) {
0529     name = iConfig.getParameter<std::string>("name");
0530   } else {
0531     name = std::string("anonymous");
0532   }
0533 
0534   entry = iConfig.retrieveUnknown("outputFrame");
0535   if (entry != nullptr) {
0536     frameName = iConfig.getParameter<std::string>("outputFrame");
0537     const std::map<std::string, const MuonGeometrySanityCheckCustomFrame *>::const_iterator frameIter =
0538         frames.find(frameName);
0539     if (frameName == std::string("global")) {
0540       outputFrame = kGlobal;
0541       outputCustomFrame = nullptr;
0542     } else if (frameName == std::string("local")) {
0543       outputFrame = kLocal;
0544       outputCustomFrame = nullptr;
0545     } else if (frameName == std::string("chamber")) {
0546       outputFrame = kChamber;
0547       outputCustomFrame = nullptr;
0548     } else if (frameIter != frames.end()) {
0549       outputFrame = kCustom;
0550       outputCustomFrame = frameIter->second;
0551     } else {
0552       throw cms::Exception("BadConfig") << "Frame \"" << frameName << "\" has not been defined." << std::endl;
0553     }
0554   } else {
0555     outputFrame = kGlobal;
0556     outputCustomFrame = nullptr;
0557   }
0558 }
0559 
0560 std::string MuonGeometrySanityCheckPoint::detName() const {
0561   std::stringstream output;
0562   if (type == kDTChamber) {
0563     DTChamberId id(detector);
0564     output << "MB" << (id.wheel() > 0 ? "+" : "") << id.wheel() << "/" << id.station() << "/" << id.sector();
0565   } else if (type == kDTSuperLayer) {
0566     DTSuperLayerId id(detector);
0567     output << "MB" << (id.wheel() > 0 ? "+" : "") << id.wheel() << "/" << id.station() << "/" << id.sector() << "/"
0568            << id.superlayer();
0569   } else if (type == kDTLayer) {
0570     DTLayerId id(detector);
0571     output << "MB" << (id.wheel() > 0 ? "+" : "") << id.wheel() << "/" << id.station() << "/" << id.sector() << "/"
0572            << id.superlayer() << "/" << id.layer();
0573   } else if (type == kCSCChamber) {
0574     CSCDetId id(detector);
0575     output << "ME" << (id.endcap() == 1 ? "+" : "-") << id.station() << "/" << id.ring() << "/" << id.chamber();
0576   } else if (type == kCSCLayer) {
0577     CSCDetId id(detector);
0578     output << "ME" << (id.endcap() == 1 ? "+" : "-") << id.station() << "/" << id.ring() << "/" << id.chamber() << "/"
0579            << id.layer();
0580   } else
0581     assert(false);
0582   return output.str();
0583 }
0584 
0585 // ------------ method called to for each event  ------------
0586 void MuonGeometrySanityCheck::analyze(const edm::Event &iEvent, const edm::EventSetup &iSetup) {
0587   const DTGeometry *dtGeometry = &iSetup.getData(dtGeomToken_);
0588   const CSCGeometry *cscGeometry = &iSetup.getData(cscGeomToken_);
0589 
0590   int num_transformed = 0;
0591   int num_tested = 0;
0592   int num_bad = 0;
0593   for (std::vector<MuonGeometrySanityCheckPoint>::const_iterator point = m_points.begin(); point != m_points.end();
0594        ++point) {
0595     num_transformed++;
0596 
0597     bool dt = (point->detector.subdetId() == MuonSubdetId::DT);
0598 
0599     // convert the displacement vector into the chosen coordinate system and add it to the chamber's position
0600     GlobalPoint chamberPos;
0601     if (dt)
0602       chamberPos = dtGeometry->idToDet(point->detector)->surface().toGlobal(LocalPoint(0., 0., 0.));
0603     else
0604       chamberPos = cscGeometry->idToDet(point->detector)->surface().toGlobal(LocalPoint(0., 0., 0.));
0605 
0606     GlobalPoint result;
0607     if (point->frame == MuonGeometrySanityCheckPoint::kGlobal) {
0608       result = GlobalPoint(chamberPos.x() + point->displacement.x(),
0609                            chamberPos.y() + point->displacement.y(),
0610                            chamberPos.z() + point->displacement.z());
0611     }
0612 
0613     else if (point->frame == MuonGeometrySanityCheckPoint::kLocal) {
0614       if (dt)
0615         result = dtGeometry->idToDet(point->detector)
0616                      ->surface()
0617                      .toGlobal(LocalPoint(point->displacement.x(), point->displacement.y(), point->displacement.z()));
0618       else
0619         result = cscGeometry->idToDet(point->detector)
0620                      ->surface()
0621                      .toGlobal(LocalPoint(point->displacement.x(), point->displacement.y(), point->displacement.z()));
0622     }
0623 
0624     else if (point->frame == MuonGeometrySanityCheckPoint::kChamber) {
0625       if (point->detector.subdetId() == MuonSubdetId::DT) {
0626         DTChamberId id(point->detector);
0627         if (dt)
0628           result = dtGeometry->idToDet(id)->surface().toGlobal(
0629               LocalPoint(point->displacement.x(), point->displacement.y(), point->displacement.z()));
0630         else
0631           result = cscGeometry->idToDet(id)->surface().toGlobal(
0632               LocalPoint(point->displacement.x(), point->displacement.y(), point->displacement.z()));
0633       } else if (point->detector.subdetId() == MuonSubdetId::CSC) {
0634         CSCDetId cscid(point->detector);
0635         CSCDetId id(cscid.endcap(), cscid.station(), cscid.ring(), cscid.chamber());
0636         if (dt)
0637           result = dtGeometry->idToDet(id)->surface().toGlobal(
0638               LocalPoint(point->displacement.x(), point->displacement.y(), point->displacement.z()));
0639         else
0640           result = cscGeometry->idToDet(id)->surface().toGlobal(
0641               LocalPoint(point->displacement.x(), point->displacement.y(), point->displacement.z()));
0642       } else {
0643         assert(false);
0644       }
0645     }
0646 
0647     else if (point->frame == MuonGeometrySanityCheckPoint::kCustom) {
0648       GlobalPoint transformed = point->customFrame->transform(point->displacement);
0649       result = GlobalPoint(
0650           chamberPos.x() + transformed.x(), chamberPos.y() + transformed.y(), chamberPos.z() + transformed.z());
0651     }
0652 
0653     else {
0654       assert(false);
0655     }
0656 
0657     // convert the result into the chosen output coordinate system
0658     if (point->outputFrame == MuonGeometrySanityCheckPoint::kGlobal) {
0659     }
0660 
0661     else if (point->outputFrame == MuonGeometrySanityCheckPoint::kLocal) {
0662       LocalPoint transformed;
0663       if (dt)
0664         transformed = dtGeometry->idToDet(point->detector)->surface().toLocal(result);
0665       else
0666         transformed = cscGeometry->idToDet(point->detector)->surface().toLocal(result);
0667       result = GlobalPoint(transformed.x(), transformed.y(), transformed.z());
0668     }
0669 
0670     else if (point->outputFrame == MuonGeometrySanityCheckPoint::kChamber) {
0671       if (point->detector.subdetId() == MuonSubdetId::DT) {
0672         DTChamberId id(point->detector);
0673         LocalPoint transformed;
0674         if (dt)
0675           transformed = dtGeometry->idToDet(id)->surface().toLocal(result);
0676         else
0677           transformed = cscGeometry->idToDet(id)->surface().toLocal(result);
0678         result = GlobalPoint(transformed.x(), transformed.y(), transformed.z());
0679       } else if (point->detector.subdetId() == MuonSubdetId::CSC) {
0680         CSCDetId cscid(point->detector);
0681         CSCDetId id(cscid.endcap(), cscid.station(), cscid.ring(), cscid.chamber());
0682         LocalPoint transformed;
0683         if (dt)
0684           transformed = dtGeometry->idToDet(id)->surface().toLocal(result);
0685         else
0686           transformed = cscGeometry->idToDet(id)->surface().toLocal(result);
0687         result = GlobalPoint(transformed.x(), transformed.y(), transformed.z());
0688       } else {
0689         assert(false);
0690       }
0691     }
0692 
0693     else if (point->outputFrame == MuonGeometrySanityCheckPoint::kCustom) {
0694       result = point->outputCustomFrame->transformInverse(result);
0695     }
0696 
0697     std::stringstream output;
0698     output << prefix << " " << point->name << " " << point->detName() << " " << result.x() << " " << result.y() << " "
0699            << result.z();
0700 
0701     bool bad = false;
0702     if (point->has_expectation) {
0703       num_tested++;
0704       double residx = result.x() - point->expectation.x();
0705       double residy = result.y() - point->expectation.y();
0706       double residz = result.z() - point->expectation.z();
0707 
0708       if (fabs(residx) > tolerance || fabs(residy) > tolerance || fabs(residz) > tolerance) {
0709         num_bad++;
0710         bad = true;
0711         output << " BAD " << residx << " " << residy << " " << residz << std::endl;
0712       } else {
0713         output << " GOOD " << residx << " " << residy << " " << residz << std::endl;
0714       }
0715     } else {
0716       output << " UNTESTED 0 0 0" << std::endl;
0717     }
0718 
0719     if (printout == std::string("all") || (printout == std::string("bad") && bad)) {
0720       std::cout << output.str();
0721     }
0722   }
0723 
0724   std::cout << std::endl
0725             << "SUMMARY transformed: " << num_transformed << " tested: " << num_tested << " bad: " << num_bad
0726             << " good: " << (num_tested - num_bad) << std::endl;
0727 }
0728 
0729 //define this as a plug-in
0730 DEFINE_FWK_MODULE(MuonGeometrySanityCheck);