Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:01:21

0001 #ifndef CONDCORE_ALIGNMENTPLUGINS_ALIGNMENTPAYLOADINSPECTORHELPER_H
0002 #define CONDCORE_ALIGNMENTPLUGINS_ALIGNMENTPAYLOADINSPECTORHELPER_H
0003 
0004 #include <iostream>
0005 #include <algorithm>
0006 #include <vector>
0007 #include <numeric>
0008 #include <string>
0009 #include "TH1.h"
0010 #include "TCanvas.h"
0011 #include "TPaveStats.h"
0012 #include "TStyle.h"
0013 #include "TList.h"
0014 #include "TLatex.h"
0015 #include "Alignment/CommonAlignment/interface/Utilities.h"
0016 #include "CondFormats/Alignment/interface/Alignments.h"
0017 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
0018 #include "DataFormats/Math/interface/Rounding.h"  // for rounding
0019 #include "DataFormats/Math/interface/deltaPhi.h"  // for deltaPhi
0020 #include "DataFormats/SiStripDetId/interface/StripSubdetector.h"
0021 #include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
0022 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0023 
0024 //#define MMDEBUG // uncomment for debugging at compile time
0025 #ifdef MMDEBUG
0026 #include <iostream>
0027 #define COUT std::cout << "MM "
0028 #else
0029 #define COUT edm::LogVerbatim("")
0030 #endif
0031 
0032 namespace AlignmentPI {
0033 
0034   // size of the phase-I Tracker APE payload (including both SS + DS modules)
0035   static const unsigned int phase0size = 19876;
0036   static const unsigned int phase1size = 20292;
0037   static const unsigned int mismatched = 99999;
0038   static const float cmToUm = 10000.f;
0039   static const float tomRad = 1000.f;
0040 
0041   /*--------------------------------------------------------------------*/
0042   inline void displayNotSupported(TCanvas& canv, const unsigned int size)
0043   /*--------------------------------------------------------------------*/
0044   {
0045     std::string phase = (size < AlignmentPI::phase1size) ? "Phase-0" : "Phase-2";
0046     canv.cd();
0047     TLatex t2;
0048     t2.SetTextAlign(21);
0049     t2.SetTextSize(0.1);
0050     t2.SetTextAngle(45);
0051     t2.SetTextColor(kRed);
0052     if (size != AlignmentPI::mismatched) {
0053       t2.DrawLatexNDC(0.6, 0.50, Form("%s  NOT SUPPORTED!", phase.c_str()));
0054     } else {
0055       t2.DrawLatexNDC(0.6, 0.50, "MISMATCHED PAYLOAD SIZE!");
0056     }
0057   }
0058 
0059   // method to zero all elements whose difference from 2Pi
0060   // is less than the tolerance (2*10e-7)
0061   inline double returnZeroIfNear2PI(const double phi) {
0062     const double tol = 2.e-7;  // default tolerance 1.e-7 doesn't account for possible variations
0063     if (cms_rounding::roundIfNear0(std::abs(phi) - 2 * M_PI, tol) == 0.f) {
0064       return 0.f;
0065     } else {
0066       return phi;
0067     }
0068   }
0069 
0070   // method to bring back around 0 all elements whose  difference
0071   // frm 2Pi is is less than the tolerance (in micro-rad)
0072   inline double trim2PIs(const double phi, const double tolerance = 1.f) {
0073     if (std::abs((std::abs(phi) - 2 * M_PI) * tomRad) < tolerance) {
0074       return (std::abs(phi) - 2 * M_PI);
0075     } else {
0076       return phi;
0077     }
0078   }
0079 
0080   enum coordinate {
0081     t_x = 1,
0082     t_y = 2,
0083     t_z = 3,
0084     rot_alpha = 4,
0085     rot_beta = 5,
0086     rot_gamma = 6,
0087   };
0088 
0089   // M.M. 2017/09/12
0090   // As the matrix is symmetric, we map only 6/9 terms
0091   // More terms for the extended APE can be added to the following methods
0092 
0093   enum index { XX = 1, XY = 2, XZ = 3, YZ = 4, YY = 5, ZZ = 6 };
0094 
0095   enum partitions { INVALID = 0, BPix = 1, FPix = 2, TIB = 3, TID = 4, TOB = 5, TEC = 6 };
0096 
0097   enum class PARTITION {
0098     BPIX,   // 0 Barrel Pixel
0099     FPIXp,  // 1 Forward Pixel Plus
0100     FPIXm,  // 2 Forward Pixel Minus
0101     TIB,    // 3 Tracker Inner Barrel
0102     TIDp,   // 4 Tracker Inner Disks Plus
0103     TIDm,   // 5 Tracker Inner Disks Minus
0104     TOB,    // 6 Tracker Outer Barrel
0105     TECp,   // 7 Tracker Endcaps Plus
0106     TECm,   // 8 Tracker Endcaps Minus
0107     LAST = TECm
0108   };
0109 
0110   extern const PARTITION PARTITIONS[(int)PARTITION::LAST + 1];
0111   const PARTITION PARTITIONS[] = {PARTITION::BPIX,
0112                                   PARTITION::FPIXp,
0113                                   PARTITION::FPIXm,
0114                                   PARTITION::TIB,
0115                                   PARTITION::TIDp,
0116                                   PARTITION::TIDm,
0117                                   PARTITION::TOB,
0118                                   PARTITION::TECp,
0119                                   PARTITION::TECm};
0120 
0121   inline std::ostream& operator<<(std::ostream& o, PARTITION x) {
0122     return o << std::underlying_type<PARTITION>::type(x);
0123   }
0124 
0125   enum regions {
0126     BPixL1o,          //0  Barrel Pixel Layer 1 outer
0127     BPixL1i,          //1  Barrel Pixel Layer 1 inner
0128     BPixL2o,          //2  Barrel Pixel Layer 2 outer
0129     BPixL2i,          //3  Barrel Pixel Layer 2 inner
0130     BPixL3o,          //4  Barrel Pixel Layer 3 outer
0131     BPixL3i,          //5  Barrel Pixel Layer 3 inner
0132     BPixL4o,          //6  Barrel Pixel Layer 4 outer
0133     BPixL4i,          //7  Barrel Pixel Layer 4 inner
0134     FPixmL1,          //8  Forward Pixel Minus side Disk 1
0135     FPixmL2,          //9 Forward Pixel Minus side Disk 2
0136     FPixmL3,          //10 Forward Pixel Minus side Disk 3
0137     FPixpL1,          //11 Forward Pixel Plus side Disk 1
0138     FPixpL2,          //12 Forward Pixel Plus side Disk 2
0139     FPixpL3,          //13 Forward Pixel Plus side Disk 3
0140     TIBL1Ro,          //14 Inner Barrel Layer 1 Rphi outer
0141     TIBL1Ri,          //15 Inner Barrel Layer 1 Rphi inner
0142     TIBL1So,          //16 Inner Barrel Layer 1 Stereo outer
0143     TIBL1Si,          //17 Inner Barrel Layer 1 Stereo inner
0144     TIBL2Ro,          //18 Inner Barrel Layer 2 Rphi outer
0145     TIBL2Ri,          //19 Inner Barrel Layer 2 Rphi inner
0146     TIBL2So,          //20 Inner Barrel Layer 2 Stereo outer
0147     TIBL2Si,          //21 Inner Barrel Layer 2 Stereo inner
0148     TIBL3o,           //22 Inner Barrel Layer 3 outer
0149     TIBL3i,           //23 Inner Barrel Layer 3 inner
0150     TIBL4o,           //24 Inner Barrel Layer 4 outer
0151     TIBL4i,           //25 Inner Barrel Layer 4 inner
0152     TOBL1Ro,          //26 Outer Barrel Layer 1 Rphi outer
0153     TOBL1Ri,          //27 Outer Barrel Layer 1 Rphi inner
0154     TOBL1So,          //28 Outer Barrel Layer 1 Stereo outer
0155     TOBL1Si,          //29 Outer Barrel Layer 1 Stereo inner
0156     TOBL2Ro,          //30 Outer Barrel Layer 2 Rphi outer
0157     TOBL2Ri,          //31 Outer Barrel Layer 2 Rphi inner
0158     TOBL2So,          //32 Outer Barrel Layer 2 Stereo outer
0159     TOBL2Si,          //33 Outer Barrel Layer 2 Stereo inner
0160     TOBL3o,           //34 Outer Barrel Layer 3 outer
0161     TOBL3i,           //35 Outer Barrel Layer 3 inner
0162     TOBL4o,           //36 Outer Barrel Layer 4 outer
0163     TOBL4i,           //37 Outer Barrel Layer 4 inner
0164     TOBL5o,           //38 Outer Barrel Layer 5 outer
0165     TOBL5i,           //39 Outer Barrel Layer 5 inner
0166     TOBL6o,           //40 Outer Barrel Layer 6 outer
0167     TOBL6i,           //41 Outer Barrel Layer 6 inner
0168     TIDmR1R,          //42 Inner Disk Minus side Ring 1 Rphi
0169     TIDmR1S,          //43 Inner Disk Minus side Ring 1 Stereo
0170     TIDmR2R,          //44 Inner Disk Minus side Ring 2 Rphi
0171     TIDmR2S,          //45 Inner Disk Minus side Ring 2 Stereo
0172     TIDmR3,           //46 Inner Disk Minus side Ring 3
0173     TIDpR1R,          //47 Inner Disk Plus side Ring 1 Rphi
0174     TIDpR1S,          //48 Inner Disk Plus side Ring 1 Stereo
0175     TIDpR2R,          //49 Inner Disk Plus side Ring 2 Rphi
0176     TIDpR2S,          //50 Inner Disk Plus side Ring 2 Stereo
0177     TIDpR3,           //51 Inner Disk Plus side Ring 3
0178     TECmR1R,          //52 Endcaps Minus side Ring 1 Rphi
0179     TECmR1S,          //53 Endcaps Minus side Ring 1 Stereo
0180     TECmR2R,          //54 Encdaps Minus side Ring 2 Rphi
0181     TECmR2S,          //55 Endcaps Minus side Ring 2 Stereo
0182     TECmR3,           //56 Endcaps Minus side Ring 3
0183     TECmR4,           //57 Endcaps Minus side Ring 4
0184     TECmR5,           //58 Endcaps Minus side Ring 5
0185     TECmR6,           //59 Endcaps Minus side Ring 6
0186     TECmR7,           //60 Endcaps Minus side Ring 7
0187     TECpR1R,          //61 Endcaps Plus side Ring 1 Rphi
0188     TECpR1S,          //62 Endcaps Plus side Ring 1 Stereo
0189     TECpR2R,          //63 Encdaps Plus side Ring 2 Rphi
0190     TECpR2S,          //64 Endcaps Plus side Ring 2 Stereo
0191     TECpR3,           //65 Endcaps Plus side Ring 3
0192     TECpR4,           //66 Endcaps Plus side Ring 4
0193     TECpR5,           //67 Endcaps Plus side Ring 5
0194     TECpR6,           //68 Endcaps Plus side Ring 6
0195     TECpR7,           //67 Endcaps Plus side Ring 7
0196     StripDoubleSide,  // 70 -- not to be considered
0197     NUM_OF_REGIONS    // 71 -- default
0198   };
0199 
0200   /*--------------------------------------------------------------------*/
0201   inline std::string getStringFromRegionEnum(AlignmentPI::regions e)
0202   /*--------------------------------------------------------------------*/
0203   {
0204     switch (e) {
0205       case AlignmentPI::BPixL1o:
0206         return "BPixL1o";
0207       case AlignmentPI::BPixL1i:
0208         return "BPixL1i";
0209       case AlignmentPI::BPixL2o:
0210         return "BPixL2o";
0211       case AlignmentPI::BPixL2i:
0212         return "BPixL2i";
0213       case AlignmentPI::BPixL3o:
0214         return "BPixL3o";
0215       case AlignmentPI::BPixL3i:
0216         return "BPixL3i";
0217       case AlignmentPI::BPixL4o:
0218         return "BPixL4o";
0219       case AlignmentPI::BPixL4i:
0220         return "BPixL4i";
0221       case AlignmentPI::FPixmL1:
0222         return "FPixmL1";
0223       case AlignmentPI::FPixmL2:
0224         return "FPixmL2";
0225       case AlignmentPI::FPixmL3:
0226         return "FPixmL3";
0227       case AlignmentPI::FPixpL1:
0228         return "FPixpL1";
0229       case AlignmentPI::FPixpL2:
0230         return "FPixpL2";
0231       case AlignmentPI::FPixpL3:
0232         return "FPixpL3";
0233       case AlignmentPI::TIBL1Ro:
0234         return "TIBL1Ro";
0235       case AlignmentPI::TIBL1Ri:
0236         return "TIBL1Ri";
0237       case AlignmentPI::TIBL1So:
0238         return "TIBL1So";
0239       case AlignmentPI::TIBL1Si:
0240         return "TIBL1Si";
0241       case AlignmentPI::TIBL2Ro:
0242         return "TIBL2Ro";
0243       case AlignmentPI::TIBL2Ri:
0244         return "TIBL2Ri";
0245       case AlignmentPI::TIBL2So:
0246         return "TIBL2So";
0247       case AlignmentPI::TIBL2Si:
0248         return "TIBL2Si";
0249       case AlignmentPI::TIBL3o:
0250         return "TIBL3o";
0251       case AlignmentPI::TIBL3i:
0252         return "TIBL3i";
0253       case AlignmentPI::TIBL4o:
0254         return "TIBL4o";
0255       case AlignmentPI::TIBL4i:
0256         return "TIBL4i";
0257       case AlignmentPI::TOBL1Ro:
0258         return "TOBL1Ro";
0259       case AlignmentPI::TOBL1Ri:
0260         return "TOBL1Ri";
0261       case AlignmentPI::TOBL1So:
0262         return "TOBL1So";
0263       case AlignmentPI::TOBL1Si:
0264         return "TOBL1Si";
0265       case AlignmentPI::TOBL2Ro:
0266         return "TOBL2Ro";
0267       case AlignmentPI::TOBL2Ri:
0268         return "TOBL2Ri";
0269       case AlignmentPI::TOBL2So:
0270         return "TOBL2So";
0271       case AlignmentPI::TOBL2Si:
0272         return "TOBL2Si";
0273       case AlignmentPI::TOBL3o:
0274         return "TOBL3o";
0275       case AlignmentPI::TOBL3i:
0276         return "TOBL3i";
0277       case AlignmentPI::TOBL4o:
0278         return "TOBL4o";
0279       case AlignmentPI::TOBL4i:
0280         return "TOBL4i";
0281       case AlignmentPI::TOBL5o:
0282         return "TOBL5o";
0283       case AlignmentPI::TOBL5i:
0284         return "TOBL5i";
0285       case AlignmentPI::TOBL6o:
0286         return "TOBL6o";
0287       case AlignmentPI::TOBL6i:
0288         return "TOBL6i";
0289       case AlignmentPI::TIDmR1R:
0290         return "TIDmR1R";
0291       case AlignmentPI::TIDmR1S:
0292         return "TIDmR1S";
0293       case AlignmentPI::TIDmR2R:
0294         return "TIDmR2R";
0295       case AlignmentPI::TIDmR2S:
0296         return "TIDmR2S";
0297       case AlignmentPI::TIDmR3:
0298         return "TIDmR3";
0299       case AlignmentPI::TIDpR1R:
0300         return "TIDpR1R";
0301       case AlignmentPI::TIDpR1S:
0302         return "TIDpR1S";
0303       case AlignmentPI::TIDpR2R:
0304         return "TIDpR2R";
0305       case AlignmentPI::TIDpR2S:
0306         return "TIDpR2S";
0307       case AlignmentPI::TIDpR3:
0308         return "TIDpR3";
0309       case AlignmentPI::TECmR1R:
0310         return "TECmR1R";
0311       case AlignmentPI::TECmR1S:
0312         return "TECmR1S";
0313       case AlignmentPI::TECmR2R:
0314         return "TECmR2R";
0315       case AlignmentPI::TECmR2S:
0316         return "TECmR2S";
0317       case AlignmentPI::TECmR3:
0318         return "TECmR3";
0319       case AlignmentPI::TECmR4:
0320         return "TECmR4";
0321       case AlignmentPI::TECmR5:
0322         return "TECmR5";
0323       case AlignmentPI::TECmR6:
0324         return "TECmR6";
0325       case AlignmentPI::TECmR7:
0326         return "TECmR7";
0327       case AlignmentPI::TECpR1R:
0328         return "TECpR1R";
0329       case AlignmentPI::TECpR1S:
0330         return "TECpR1S";
0331       case AlignmentPI::TECpR2R:
0332         return "TECpR2R";
0333       case AlignmentPI::TECpR2S:
0334         return "TECpR2S";
0335       case AlignmentPI::TECpR3:
0336         return "TECpR3";
0337       case AlignmentPI::TECpR4:
0338         return "TECpR4";
0339       case AlignmentPI::TECpR5:
0340         return "TECpR5";
0341       case AlignmentPI::TECpR6:
0342         return "TECpR6";
0343       case AlignmentPI::TECpR7:
0344         return "TECpR7";
0345       default:
0346         edm::LogWarning("LogicError") << "Unknown partition: " << e;
0347         return "";
0348     }
0349   }
0350 
0351   /*--------------------------------------------------------------------*/
0352   inline bool isBPixOuterLadder(const DetId& detid, const TrackerTopology& tTopo, bool isPhase0)
0353   /*--------------------------------------------------------------------*/
0354   {
0355     // Using TrackerTopology
0356     // Ladders have a staggered structure
0357     // Non-flipped ladders are on the outer radius
0358     // Phase 0: Outer ladders are odd for layer 1,3 and even for layer 2
0359     // Phase 1: Outer ladders are odd for layer 1,2,3 and even for layer 4
0360     bool isOuter = false;
0361     int layer = tTopo.pxbLayer(detid.rawId());
0362     bool odd_ladder = tTopo.pxbLadder(detid.rawId()) % 2;
0363     if (isPhase0) {
0364       if (layer == 2)
0365         isOuter = !odd_ladder;
0366       else
0367         isOuter = odd_ladder;
0368     } else {
0369       if (layer == 4)
0370         isOuter = !odd_ladder;
0371       else
0372         isOuter = odd_ladder;
0373     }
0374     return isOuter;
0375   }
0376 
0377   // ancillary struct to manage the topology
0378   // info in a more compact way
0379 
0380   struct topolInfo {
0381   private:
0382     uint32_t m_rawid;
0383     int m_subdetid;
0384     int m_layer;
0385     int m_side;
0386     int m_ring;
0387     bool m_isRphi;
0388     bool m_isDoubleSide;
0389     bool m_isInternal;
0390 
0391   public:
0392     void init();
0393     void fillGeometryInfo(const DetId& detId, const TrackerTopology& tTopo, bool isPhase0);
0394     AlignmentPI::regions filterThePartition();
0395     bool sanityCheck();
0396     void printAll();
0397     virtual ~topolInfo() {}
0398   };
0399 
0400   /*--------------------------------------------------------------------*/
0401   inline void topolInfo::printAll()
0402   /*--------------------------------------------------------------------*/
0403   {
0404     std::cout << " detId:" << m_rawid << " subdetid: " << m_subdetid << " layer: " << m_layer << " side: " << m_side
0405               << " ring: " << m_ring << " isRphi:" << m_isRphi << " isDoubleSide:" << m_isDoubleSide
0406               << " isInternal:" << m_isInternal << std::endl;
0407   }
0408 
0409   /*--------------------------------------------------------------------*/
0410   inline void topolInfo::init()
0411   /*--------------------------------------------------------------------*/
0412   {
0413     m_rawid = 0;
0414     m_subdetid = -1;
0415     m_layer = -1;
0416     m_side = -1;
0417     m_ring = -1;
0418     m_isRphi = false;
0419     m_isDoubleSide = false;
0420     m_isInternal = false;
0421   };
0422 
0423   /*--------------------------------------------------------------------*/
0424   inline bool topolInfo::sanityCheck()
0425   /*--------------------------------------------------------------------*/
0426   {
0427     if (m_layer == 0 || (m_subdetid == 1 && m_layer > 4) || (m_subdetid == 2 && m_layer > 3)) {
0428       return false;
0429     } else {
0430       return true;
0431     }
0432   }
0433   /*--------------------------------------------------------------------*/
0434   inline void topolInfo::fillGeometryInfo(const DetId& detId, const TrackerTopology& tTopo, bool isPhase0)
0435   /*--------------------------------------------------------------------*/
0436   {
0437     unsigned int subdetId = static_cast<unsigned int>(detId.subdetId());
0438 
0439     m_rawid = detId.rawId();
0440     m_subdetid = subdetId;
0441 
0442     if (subdetId == StripSubdetector::TIB) {
0443       m_layer = tTopo.tibLayer(detId.rawId());
0444       m_side = tTopo.tibSide(detId.rawId());
0445       m_isRphi = tTopo.isRPhi(detId.rawId());
0446       m_isDoubleSide = tTopo.tibIsDoubleSide(detId.rawId());
0447       m_isInternal = tTopo.tibIsInternalString(detId.rawId());
0448     } else if (subdetId == StripSubdetector::TOB) {
0449       m_layer = tTopo.tobLayer(detId.rawId());
0450       m_side = tTopo.tobSide(detId.rawId());
0451       m_isRphi = tTopo.isRPhi(detId.rawId());
0452       m_isDoubleSide = tTopo.tobIsDoubleSide(detId.rawId());
0453       m_isInternal = tTopo.tobModule(detId.rawId()) % 2;
0454     } else if (subdetId == StripSubdetector::TID) {
0455       m_layer = tTopo.tidWheel(detId.rawId());
0456       m_side = tTopo.tidSide(detId.rawId());
0457       m_isRphi = tTopo.isRPhi(detId.rawId());
0458       m_ring = tTopo.tidRing(detId.rawId());
0459       m_isDoubleSide = tTopo.tidIsDoubleSide(detId.rawId());
0460       m_isInternal = tTopo.tidModuleInfo(detId.rawId())[0];
0461     } else if (subdetId == StripSubdetector::TEC) {
0462       m_layer = tTopo.tecWheel(detId.rawId());
0463       m_side = tTopo.tecSide(detId.rawId());
0464       m_isRphi = tTopo.isRPhi(detId.rawId());
0465       m_ring = tTopo.tecRing(detId.rawId());
0466       m_isDoubleSide = tTopo.tecIsDoubleSide(detId.rawId());
0467       m_isInternal = tTopo.tecPetalInfo(detId.rawId())[0];
0468     } else if (subdetId == PixelSubdetector::PixelBarrel) {
0469       m_layer = tTopo.pxbLayer(detId.rawId());
0470       m_isInternal = !AlignmentPI::isBPixOuterLadder(detId, tTopo, isPhase0);
0471     } else if (subdetId == PixelSubdetector::PixelEndcap) {
0472       m_layer = tTopo.pxfDisk(detId.rawId());
0473       m_side = tTopo.pxfSide(detId.rawId());
0474     } else
0475       edm::LogWarning("LogicError") << "Unknown subdetid: " << subdetId;
0476   }
0477 
0478   // ------------ method to assign a partition based on the topology struct info ---------------
0479 
0480   /*--------------------------------------------------------------------*/
0481   inline AlignmentPI::regions topolInfo::filterThePartition()
0482   /*--------------------------------------------------------------------*/
0483   {
0484     AlignmentPI::regions ret = AlignmentPI::NUM_OF_REGIONS;
0485 
0486     if (m_isDoubleSide) {
0487       return AlignmentPI::StripDoubleSide;
0488     }
0489 
0490     // BPix
0491     if (m_subdetid == 1) {
0492       switch (m_layer) {
0493         case 1:
0494           m_isInternal > 0 ? ret = AlignmentPI::BPixL1o : ret = AlignmentPI::BPixL1i;
0495           break;
0496         case 2:
0497           m_isInternal > 0 ? ret = AlignmentPI::BPixL2o : ret = AlignmentPI::BPixL2i;
0498           break;
0499         case 3:
0500           m_isInternal > 0 ? ret = AlignmentPI::BPixL3o : ret = AlignmentPI::BPixL3i;
0501           break;
0502         case 4:
0503           m_isInternal > 0 ? ret = AlignmentPI::BPixL4o : ret = AlignmentPI::BPixL4i;
0504           break;
0505         default:
0506           edm::LogWarning("LogicError") << "Unknow BPix layer: " << m_layer;
0507           break;
0508       }
0509       // FPix
0510     } else if (m_subdetid == 2) {
0511       switch (m_layer) {
0512         case 1:
0513           m_side > 1 ? ret = AlignmentPI::FPixpL1 : ret = AlignmentPI::FPixmL1;
0514           break;
0515         case 2:
0516           m_side > 1 ? ret = AlignmentPI::FPixpL2 : ret = AlignmentPI::FPixmL2;
0517           break;
0518         case 3:
0519           m_side > 1 ? ret = AlignmentPI::FPixpL3 : ret = AlignmentPI::FPixmL3;
0520           break;
0521         default:
0522           edm::LogWarning("LogicError") << "Unknow FPix disk: " << m_layer;
0523           break;
0524       }
0525       // TIB
0526     } else if (m_subdetid == 3) {
0527       switch (m_layer) {
0528         case 1:
0529           if (m_isRphi) {
0530             m_isInternal > 0 ? ret = AlignmentPI::TIBL1Ro : ret = AlignmentPI::TIBL1Ri;
0531           } else {
0532             m_isInternal > 0 ? ret = AlignmentPI::TIBL1So : ret = AlignmentPI::TIBL1Si;
0533           }
0534           break;
0535         case 2:
0536           if (m_isRphi) {
0537             m_isInternal > 0 ? ret = AlignmentPI::TIBL2Ro : ret = AlignmentPI::TIBL2Ri;
0538           } else {
0539             m_isInternal > 0 ? ret = AlignmentPI::TIBL2So : ret = AlignmentPI::TIBL2Si;
0540           }
0541           break;
0542         case 3:
0543           m_isInternal > 0 ? ret = AlignmentPI::TIBL3o : ret = AlignmentPI::TIBL3i;
0544           break;
0545         case 4:
0546           m_isInternal > 0 ? ret = AlignmentPI::TIBL4o : ret = AlignmentPI::TIBL4i;
0547           break;
0548         default:
0549           edm::LogWarning("LogicError") << "Unknow TIB layer: " << m_layer;
0550           break;
0551       }
0552       // TID
0553     } else if (m_subdetid == 4) {
0554       switch (m_ring) {
0555         case 1:
0556           if (m_isRphi) {
0557             m_side > 1 ? ret = AlignmentPI::TIDpR1R : ret = AlignmentPI::TIDmR1R;
0558           } else {
0559             m_side > 1 ? ret = AlignmentPI::TIDpR1S : ret = AlignmentPI::TIDmR1S;
0560           }
0561           break;
0562         case 2:
0563           if (m_isRphi) {
0564             m_side > 1 ? ret = AlignmentPI::TIDpR2R : ret = AlignmentPI::TIDmR2R;
0565           } else {
0566             m_side > 1 ? ret = AlignmentPI::TIDpR2S : ret = AlignmentPI::TIDmR2S;
0567           }
0568           break;
0569         case 3:
0570           m_side > 1 ? ret = AlignmentPI::TIDpR3 : ret = AlignmentPI::TIDmR3;
0571           break;
0572         default:
0573           edm::LogWarning("LogicError") << "Unknow TID wheel: " << m_layer;
0574           break;
0575       }
0576       // TOB
0577     } else if (m_subdetid == 5) {
0578       switch (m_layer) {
0579         case 1:
0580           if (m_isRphi) {
0581             m_isInternal > 0 ? ret = AlignmentPI::TOBL1Ro : ret = AlignmentPI::TOBL1Ri;
0582           } else {
0583             m_isInternal > 0 ? ret = AlignmentPI::TOBL1So : ret = AlignmentPI::TOBL1Si;
0584           }
0585           break;
0586         case 2:
0587           if (m_isRphi) {
0588             m_isInternal > 0 ? ret = AlignmentPI::TOBL2Ro : ret = AlignmentPI::TOBL2Ri;
0589           } else {
0590             m_isInternal > 0 ? ret = AlignmentPI::TOBL2So : ret = AlignmentPI::TOBL2Si;
0591           }
0592           break;
0593         case 3:
0594           m_isInternal > 0 ? ret = AlignmentPI::TOBL3o : ret = AlignmentPI::TOBL3i;
0595           break;
0596         case 4:
0597           m_isInternal > 0 ? ret = AlignmentPI::TOBL4o : ret = AlignmentPI::TOBL4i;
0598           break;
0599         case 5:
0600           m_isInternal > 0 ? ret = AlignmentPI::TOBL5o : ret = AlignmentPI::TOBL5i;
0601           break;
0602         case 6:
0603           m_isInternal > 0 ? ret = AlignmentPI::TOBL6o : ret = AlignmentPI::TOBL6i;
0604           break;
0605         default:
0606           edm::LogWarning("LogicError") << "Unknow TOB layer: " << m_layer;
0607           break;
0608       }
0609       // TEC
0610     } else if (m_subdetid == 6) {
0611       switch (m_ring) {
0612         case 1:
0613           if (m_isRphi) {
0614             m_side > 1 ? ret = AlignmentPI::TECpR1R : ret = AlignmentPI::TECmR1R;
0615           } else {
0616             m_side > 1 ? ret = AlignmentPI::TECpR1S : ret = AlignmentPI::TECmR1S;
0617           }
0618           break;
0619         case 2:
0620           if (m_isRphi) {
0621             m_side > 1 ? ret = AlignmentPI::TECpR2R : ret = AlignmentPI::TECmR2R;
0622           } else {
0623             m_side > 1 ? ret = AlignmentPI::TECpR2S : ret = AlignmentPI::TECmR2S;
0624           }
0625           break;
0626         case 3:
0627           m_side > 1 ? ret = AlignmentPI::TECpR3 : ret = AlignmentPI::TECmR3;
0628           break;
0629         case 4:
0630           m_side > 1 ? ret = AlignmentPI::TECpR4 : ret = AlignmentPI::TECmR4;
0631           break;
0632         case 5:
0633           m_side > 1 ? ret = AlignmentPI::TECpR5 : ret = AlignmentPI::TECmR5;
0634           break;
0635         case 6:
0636           m_side > 1 ? ret = AlignmentPI::TECpR6 : ret = AlignmentPI::TECmR6;
0637           break;
0638         case 7:
0639           m_side > 1 ? ret = AlignmentPI::TECpR7 : ret = AlignmentPI::TECmR7;
0640           break;
0641         default:
0642           edm::LogWarning("LogicError") << "Unknow TEC ring: " << m_ring;
0643           break;
0644       }
0645     }
0646 
0647     return ret;
0648   }
0649 
0650   /*--------------------------------------------------------------------*/
0651   inline std::string getStringFromCoordinate(AlignmentPI::coordinate coord)
0652   /*--------------------------------------------------------------------*/
0653   {
0654     switch (coord) {
0655       case t_x:
0656         return "x-translation";
0657       case t_y:
0658         return "y-translation";
0659       case t_z:
0660         return "z-translation";
0661       case rot_alpha:
0662         return "#alpha angle rotation";
0663       case rot_beta:
0664         return "#beta angle rotation";
0665       case rot_gamma:
0666         return "#gamma angle rotation";
0667       default:
0668         return "should never be here!";
0669     }
0670   }
0671 
0672   /*--------------------------------------------------------------------*/
0673   inline std::string getStringFromIndex(AlignmentPI::index i)
0674   /*--------------------------------------------------------------------*/
0675   {
0676     switch (i) {
0677       case XX:
0678         return "XX";
0679       case XY:
0680         return "XY";
0681       case XZ:
0682         return "XZ";
0683       case YZ:
0684         return "YX";
0685       case YY:
0686         return "YY";
0687       case ZZ:
0688         return "ZZ";
0689       default:
0690         return "should never be here!";
0691     }
0692   }
0693 
0694   /*--------------------------------------------------------------------*/
0695   inline std::string getStringFromPart(AlignmentPI::partitions i, bool isPhase2 = false)
0696   /*--------------------------------------------------------------------*/
0697   {
0698     switch (i) {
0699       case BPix:
0700         return "BPix";
0701       case FPix:
0702         return "FPix";
0703       case TIB:
0704         return (isPhase2 ? "TIB-invalid" : "TIB");
0705       case TID:
0706         return (isPhase2 ? "P2OTEC" : "TID");
0707       case TOB:
0708         return (isPhase2 ? "P2OTB" : "TOB");
0709       case TEC:
0710         return (isPhase2 ? "TEC-invalid" : "TEC");
0711       default:
0712         return "should never be here!";
0713     }
0714   }
0715 
0716   /*--------------------------------------------------------------------*/
0717   inline std::pair<int, int> getIndices(AlignmentPI::index i)
0718   /*--------------------------------------------------------------------*/
0719   {
0720     switch (i) {
0721       case XX:
0722         return std::make_pair(0, 0);
0723       case XY:
0724         return std::make_pair(0, 1);
0725       case XZ:
0726         return std::make_pair(0, 2);
0727       case YZ:
0728         return std::make_pair(1, 0);
0729       case YY:
0730         return std::make_pair(1, 1);
0731       case ZZ:
0732         return std::make_pair(2, 2);
0733       default:
0734         return std::make_pair(-1, -1);
0735     }
0736   }
0737 
0738   /*--------------------------------------------------------------------*/
0739   inline void makeNicePlotStyle(TH1* hist, int color)
0740   /*--------------------------------------------------------------------*/
0741   {
0742     hist->SetStats(kFALSE);
0743 
0744     hist->GetXaxis()->SetTitleColor(color);
0745     hist->SetLineColor(color);
0746     hist->SetTitleSize(0.08);
0747     hist->SetLineWidth(2);
0748     hist->GetXaxis()->CenterTitle(true);
0749     hist->GetYaxis()->CenterTitle(true);
0750     hist->GetXaxis()->SetTitleFont(42);
0751     hist->GetYaxis()->SetTitleFont(42);
0752     hist->GetXaxis()->SetNdivisions(505);
0753     hist->GetXaxis()->SetTitleSize(0.06);
0754     hist->GetYaxis()->SetTitleSize(0.06);
0755     hist->GetXaxis()->SetTitleOffset(1.0);
0756     hist->GetYaxis()->SetTitleOffset(1.3);
0757     hist->GetXaxis()->SetLabelFont(42);
0758     hist->GetYaxis()->SetLabelFont(42);
0759     hist->GetYaxis()->SetLabelSize(.05);
0760     hist->GetXaxis()->SetLabelSize(.05);
0761   }
0762 
0763   /*--------------------------------------------------------------------*/
0764   inline void makeNiceStats(TH1F* hist, AlignmentPI::partitions part, int color)
0765   /*--------------------------------------------------------------------*/
0766   {
0767     char buffer[255];
0768     TPaveText* stat = new TPaveText(0.71, 0.75, 0.95, 0.88, "NDC");
0769     sprintf(buffer, "%s \n", AlignmentPI::getStringFromPart(part).c_str());
0770     stat->AddText(buffer);
0771 
0772     sprintf(buffer, "Entries : %i\n", (int)hist->GetEntries());
0773     stat->AddText(buffer);
0774 
0775     if (std::abs(hist->GetMean()) > 0.01) {
0776       sprintf(buffer, "Mean    : %6.2f\n", hist->GetMean());
0777     } else {
0778       sprintf(buffer, "Mean    : %6.2f e-2\n", 100 * hist->GetMean());
0779     }
0780     stat->AddText(buffer);
0781 
0782     if (std::abs(hist->GetRMS()) > 0.01) {
0783       sprintf(buffer, "RMS     : %6.2f\n", hist->GetRMS());
0784     } else {
0785       sprintf(buffer, "RMS     : %6.2f e-2\n", 100 * hist->GetRMS());
0786     }
0787     stat->AddText(buffer);
0788 
0789     stat->SetLineColor(0);
0790     stat->SetTextColor(color);
0791     stat->SetFillColor(10);
0792     stat->SetShadowColor(10);
0793     stat->Draw();
0794   }
0795 
0796   /*--------------------------------------------------------------------*/
0797   inline std::pair<float, float> getTheRange(std::map<uint32_t, float> values, const float nsigma)
0798   /*--------------------------------------------------------------------*/
0799   {
0800     float sum = std::accumulate(
0801         std::begin(values), std::end(values), 0.0, [](float value, const std::map<uint32_t, float>::value_type& p) {
0802           return value + p.second;
0803         });
0804 
0805     float m = sum / values.size();
0806 
0807     float accum = 0.0;
0808     std::for_each(std::begin(values), std::end(values), [&](const std::map<uint32_t, float>::value_type& p) {
0809       accum += (p.second - m) * (p.second - m);
0810     });
0811 
0812     float stdev = sqrt(accum / (values.size() - 1));
0813 
0814     if (stdev != 0.) {
0815       return std::make_pair(m - nsigma * stdev, m + nsigma * stdev);
0816     } else {
0817       return std::make_pair(m > 0. ? 0.95 * m : 1.05 * m, m > 0 ? 1.05 * m : 0.95 * m);
0818     }
0819   }
0820 
0821   /*--------------------------------------------------------------------*/
0822   inline std::pair<double, double> calculatePosition(TVirtualPad* myPad, int boundary)
0823   /*--------------------------------------------------------------------*/
0824   {
0825     int ix1;
0826     int ix2;
0827     int iw = myPad->GetWw();
0828     int ih = myPad->GetWh();
0829     double x1p, y1p, x2p, y2p;
0830     myPad->GetPadPar(x1p, y1p, x2p, y2p);
0831     ix1 = (int)(iw * x1p);
0832     ix2 = (int)(iw * x2p);
0833     double wndc = std::min(1., (double)iw / (double)ih);
0834     double rw = wndc / (double)iw;
0835     double x1ndc = (double)ix1 * rw;
0836     double x2ndc = (double)ix2 * rw;
0837     double rx1, ry1, rx2, ry2;
0838     myPad->GetRange(rx1, ry1, rx2, ry2);
0839     double rx = (x2ndc - x1ndc) / (rx2 - rx1);
0840     double _sx;
0841     _sx = rx * (boundary - rx1) + x1ndc;
0842     double _dx = _sx + 0.05;
0843 
0844     return std::make_pair(_sx, _dx);
0845   }
0846 
0847   // ancillary struct to manage the barycenters
0848   // info in a more compact way
0849 
0850   struct TkAlBarycenters {
0851     std::map<AlignmentPI::PARTITION, double> Xbarycenters;
0852     std::map<AlignmentPI::PARTITION, double> Ybarycenters;
0853     std::map<AlignmentPI::PARTITION, double> Zbarycenters;
0854     std::map<AlignmentPI::PARTITION, double> nmodules;
0855 
0856   public:
0857     void init();
0858     GlobalPoint getPartitionAvg(AlignmentPI::PARTITION p);
0859     void computeBarycenters(const std::vector<AlignTransform>& input,
0860                             const TrackerTopology& tTopo,
0861                             const std::map<AlignmentPI::coordinate, float>& GPR);
0862     const double getNModules(AlignmentPI::PARTITION p) { return nmodules[p]; };
0863 
0864     // M.M. 2020/01/09
0865     // introduce methods for entire partitions, summing up the two sides of the
0866     // endcap detectors
0867 
0868     /*--------------------------------------------------------------------*/
0869     const std::array<double, 6> getX()
0870     /*--------------------------------------------------------------------*/
0871     {
0872       return {{Xbarycenters[PARTITION::BPIX],
0873                (Xbarycenters[PARTITION::FPIXm] + Xbarycenters[PARTITION::FPIXp]) / 2.,
0874                Xbarycenters[PARTITION::TIB],
0875                (Xbarycenters[PARTITION::TIDm] + Xbarycenters[PARTITION::TIDp]) / 2,
0876                Xbarycenters[PARTITION::TOB],
0877                (Xbarycenters[PARTITION::TECm] + Xbarycenters[PARTITION::TECp]) / 2}};
0878     };
0879 
0880     /*--------------------------------------------------------------------*/
0881     const std::array<double, 6> getY()
0882     /*--------------------------------------------------------------------*/
0883     {
0884       return {{Ybarycenters[PARTITION::BPIX],
0885                (Ybarycenters[PARTITION::FPIXm] + Ybarycenters[PARTITION::FPIXp]) / 2.,
0886                Ybarycenters[PARTITION::TIB],
0887                (Ybarycenters[PARTITION::TIDm] + Ybarycenters[PARTITION::TIDp]) / 2,
0888                Ybarycenters[PARTITION::TOB],
0889                (Ybarycenters[PARTITION::TECm] + Ybarycenters[PARTITION::TECp]) / 2}};
0890     };
0891 
0892     /*--------------------------------------------------------------------*/
0893     const std::array<double, 6> getZ()
0894     /*--------------------------------------------------------------------*/
0895     {
0896       return {{Zbarycenters[PARTITION::BPIX],
0897                (Zbarycenters[PARTITION::FPIXm] + Zbarycenters[PARTITION::FPIXp]) / 2.,
0898                Zbarycenters[PARTITION::TIB],
0899                (Zbarycenters[PARTITION::TIDm] + Zbarycenters[PARTITION::TIDp]) / 2,
0900                Zbarycenters[PARTITION::TOB],
0901                (Zbarycenters[PARTITION::TECm] + Zbarycenters[PARTITION::TECp]) / 2}};
0902     };
0903     virtual ~TkAlBarycenters() {}
0904   };
0905 
0906   /*--------------------------------------------------------------------*/
0907   inline void TkAlBarycenters::init()
0908   /*--------------------------------------------------------------------*/
0909   {
0910     // empty all maps
0911     Xbarycenters.clear();
0912     Ybarycenters.clear();
0913     Zbarycenters.clear();
0914     nmodules.clear();
0915   }
0916 
0917   /*--------------------------------------------------------------------*/
0918   inline GlobalPoint TkAlBarycenters::getPartitionAvg(AlignmentPI::PARTITION p)
0919   /*--------------------------------------------------------------------*/
0920   {
0921     return GlobalPoint(Xbarycenters[p], Ybarycenters[p], Zbarycenters[p]);
0922   }
0923 
0924   /*--------------------------------------------------------------------*/
0925   inline void TkAlBarycenters::computeBarycenters(const std::vector<AlignTransform>& input,
0926                                                   const TrackerTopology& tTopo,
0927                                                   const std::map<AlignmentPI::coordinate, float>& GPR)
0928   /*--------------------------------------------------------------------*/
0929   {
0930     // clear all data members;
0931     init();
0932 
0933     for (const auto& ali : input) {
0934       if (DetId(ali.rawId()).det() != DetId::Tracker) {
0935         edm::LogWarning("TkAlBarycenters::computeBarycenters")
0936             << "Encountered invalid Tracker DetId:" << ali.rawId() << " " << DetId(ali.rawId()).det()
0937             << " is different from " << DetId::Tracker << "  - terminating ";
0938         assert(DetId(ali.rawId()).det() != DetId::Tracker);
0939       }
0940 
0941       int subid = DetId(ali.rawId()).subdetId();
0942       switch (subid) {
0943         case PixelSubdetector::PixelBarrel:
0944           Xbarycenters[PARTITION::BPIX] += (ali.translation().x());
0945           Ybarycenters[PARTITION::BPIX] += (ali.translation().y());
0946           Zbarycenters[PARTITION::BPIX] += (ali.translation().z());
0947           nmodules[PARTITION::BPIX]++;
0948           break;
0949         case PixelSubdetector::PixelEndcap:
0950 
0951           // minus side
0952           if (tTopo.pxfSide(DetId(ali.rawId())) == 1) {
0953             Xbarycenters[PARTITION::FPIXm] += (ali.translation().x());
0954             Ybarycenters[PARTITION::FPIXm] += (ali.translation().y());
0955             Zbarycenters[PARTITION::FPIXm] += (ali.translation().z());
0956             nmodules[PARTITION::FPIXm]++;
0957           }  // plus side
0958           else {
0959             Xbarycenters[PARTITION::FPIXp] += (ali.translation().x());
0960             Ybarycenters[PARTITION::FPIXp] += (ali.translation().y());
0961             Zbarycenters[PARTITION::FPIXp] += (ali.translation().z());
0962             nmodules[PARTITION::FPIXp]++;
0963           }
0964           break;
0965         case StripSubdetector::TIB:
0966           Xbarycenters[PARTITION::TIB] += (ali.translation().x());
0967           Ybarycenters[PARTITION::TIB] += (ali.translation().y());
0968           Zbarycenters[PARTITION::TIB] += (ali.translation().z());
0969           nmodules[PARTITION::TIB]++;
0970           break;
0971         case StripSubdetector::TID:
0972           // minus side
0973           if (tTopo.tidSide(DetId(ali.rawId())) == 1) {
0974             Xbarycenters[PARTITION::TIDm] += (ali.translation().x());
0975             Ybarycenters[PARTITION::TIDm] += (ali.translation().y());
0976             Zbarycenters[PARTITION::TIDm] += (ali.translation().z());
0977             nmodules[PARTITION::TIDm]++;
0978           }  // plus side
0979           else {
0980             Xbarycenters[PARTITION::TIDp] += (ali.translation().x());
0981             Ybarycenters[PARTITION::TIDp] += (ali.translation().y());
0982             Zbarycenters[PARTITION::TIDp] += (ali.translation().z());
0983             nmodules[PARTITION::TIDp]++;
0984           }
0985           break;
0986         case StripSubdetector::TOB:
0987           Xbarycenters[PARTITION::TOB] += (ali.translation().x());
0988           Ybarycenters[PARTITION::TOB] += (ali.translation().y());
0989           Zbarycenters[PARTITION::TOB] += (ali.translation().z());
0990           nmodules[PARTITION::TOB]++;
0991           break;
0992         case StripSubdetector::TEC:
0993           // minus side
0994           if (tTopo.tecSide(DetId(ali.rawId())) == 1) {
0995             Xbarycenters[PARTITION::TECm] += (ali.translation().x());
0996             Ybarycenters[PARTITION::TECm] += (ali.translation().y());
0997             Zbarycenters[PARTITION::TECm] += (ali.translation().z());
0998             nmodules[PARTITION::TECm]++;
0999           }  // plus side
1000           else {
1001             Xbarycenters[PARTITION::TECp] += (ali.translation().x());
1002             Ybarycenters[PARTITION::TECp] += (ali.translation().y());
1003             Zbarycenters[PARTITION::TECp] += (ali.translation().z());
1004             nmodules[PARTITION::TECp]++;
1005           }
1006           break;
1007         default:
1008           edm::LogError("TrackerAlignment_PayloadInspector") << "Unrecognized partition " << subid << std::endl;
1009           break;
1010       }
1011     }
1012 
1013     for (const auto& p : PARTITIONS) {
1014       // take the arithmetic mean
1015       Xbarycenters[p] /= nmodules[p];
1016       Ybarycenters[p] /= nmodules[p];
1017       Zbarycenters[p] /= nmodules[p];
1018 
1019       // add the Tracker Global Position Record
1020       Xbarycenters[p] += GPR.at(AlignmentPI::t_x);
1021       Ybarycenters[p] += GPR.at(AlignmentPI::t_y);
1022       Zbarycenters[p] += GPR.at(AlignmentPI::t_z);
1023 
1024       COUT << "Partition: " << p << " n. modules: " << nmodules[p] << "|"
1025            << " X: " << std::right << std::setw(12) << Xbarycenters[p] << " Y: " << std::right << std::setw(12)
1026            << Ybarycenters[p] << " Z: " << std::right << std::setw(12) << Zbarycenters[p] << std::endl;
1027     }
1028   }
1029 
1030   /*--------------------------------------------------------------------*/
1031   inline void fillComparisonHistogram(const AlignmentPI::coordinate& coord,
1032                                       std::map<int, AlignmentPI::partitions>& boundaries,
1033                                       const std::vector<AlignTransform>& ref_ali,
1034                                       const std::vector<AlignTransform>& target_ali,
1035                                       std::unique_ptr<TH1F>& compare)
1036   /*--------------------------------------------------------------------*/
1037   {
1038     int counter = 0; /* start the counter */
1039     AlignmentPI::partitions currentPart = AlignmentPI::BPix;
1040     for (unsigned int i = 0; i < ref_ali.size(); i++) {
1041       if (ref_ali[i].rawId() == target_ali[i].rawId()) {
1042         counter++;
1043         int subid = DetId(ref_ali[i].rawId()).subdetId();
1044 
1045         auto thePart = static_cast<AlignmentPI::partitions>(subid);
1046         if (thePart != currentPart) {
1047           currentPart = thePart;
1048           boundaries.insert({counter, thePart});
1049         }
1050 
1051         CLHEP::HepRotation target_rot(target_ali[i].rotation());
1052         CLHEP::HepRotation ref_rot(ref_ali[i].rotation());
1053 
1054         align::RotationType target_ROT(target_rot.xx(),
1055                                        target_rot.xy(),
1056                                        target_rot.xz(),
1057                                        target_rot.yx(),
1058                                        target_rot.yy(),
1059                                        target_rot.yz(),
1060                                        target_rot.zx(),
1061                                        target_rot.zy(),
1062                                        target_rot.zz());
1063 
1064         align::RotationType ref_ROT(ref_rot.xx(),
1065                                     ref_rot.xy(),
1066                                     ref_rot.xz(),
1067                                     ref_rot.yx(),
1068                                     ref_rot.yy(),
1069                                     ref_rot.yz(),
1070                                     ref_rot.zx(),
1071                                     ref_rot.zy(),
1072                                     ref_rot.zz());
1073 
1074         const std::vector<double> deltaRot = {::deltaPhi(align::toAngles(target_ROT)[0], align::toAngles(ref_ROT)[0]),
1075                                               ::deltaPhi(align::toAngles(target_ROT)[1], align::toAngles(ref_ROT)[1]),
1076                                               ::deltaPhi(align::toAngles(target_ROT)[2], align::toAngles(ref_ROT)[2])};
1077 
1078         const auto& deltaTrans = target_ali[i].translation() - ref_ali[i].translation();
1079 
1080         switch (coord) {
1081           case AlignmentPI::t_x:
1082             compare->SetBinContent(i + 1, deltaTrans.x() * AlignmentPI::cmToUm);
1083             break;
1084           case AlignmentPI::t_y:
1085             compare->SetBinContent(i + 1, deltaTrans.y() * AlignmentPI::cmToUm);
1086             break;
1087           case AlignmentPI::t_z:
1088             compare->SetBinContent(i + 1, deltaTrans.z() * AlignmentPI::cmToUm);
1089             break;
1090           case AlignmentPI::rot_alpha:
1091             compare->SetBinContent(i + 1, deltaRot[0] * AlignmentPI::tomRad);
1092             break;
1093           case AlignmentPI::rot_beta:
1094             compare->SetBinContent(i + 1, deltaRot[1] * AlignmentPI::tomRad);
1095             break;
1096           case AlignmentPI::rot_gamma:
1097             compare->SetBinContent(i + 1, deltaRot[2] * AlignmentPI::tomRad);
1098             break;
1099           default:
1100             edm::LogError("TrackerAlignment_PayloadInspector") << "Unrecognized coordinate " << coord << std::endl;
1101             break;
1102         }  // switch on the coordinate
1103       }    // check on the same detID
1104     }      // loop on the components
1105   }
1106 
1107   /*--------------------------------------------------------------------*/
1108   inline void fillComparisonHistograms(std::map<int, AlignmentPI::partitions>& boundaries,
1109                                        const std::vector<AlignTransform>& ref_ali,
1110                                        const std::vector<AlignTransform>& target_ali,
1111                                        std::unordered_map<AlignmentPI::coordinate, std::unique_ptr<TH1F> >& compare,
1112                                        bool diff = false,
1113                                        AlignmentPI::partitions checkPart = AlignmentPI::INVALID)
1114   /*--------------------------------------------------------------------*/
1115   {
1116     int counter = 0; /* start the counter */
1117     AlignmentPI::partitions currentPart = AlignmentPI::BPix;
1118     for (unsigned int i = 0; i < ref_ali.size(); i++) {
1119       if (ref_ali[i].rawId() == target_ali[i].rawId()) {
1120         counter++;
1121         int subid = DetId(ref_ali[i].rawId()).subdetId();
1122 
1123         auto thePart = static_cast<AlignmentPI::partitions>(subid);
1124 
1125         // in case it has to be filtered
1126         if (checkPart > 0 && thePart != checkPart) {
1127           continue;
1128         }
1129 
1130         if (thePart != currentPart) {
1131           currentPart = thePart;
1132           boundaries.insert({counter, thePart});
1133         }
1134 
1135         CLHEP::HepRotation target_rot(target_ali[i].rotation());
1136         CLHEP::HepRotation ref_rot(ref_ali[i].rotation());
1137 
1138         align::RotationType target_ROT(target_rot.xx(),
1139                                        target_rot.xy(),
1140                                        target_rot.xz(),
1141                                        target_rot.yx(),
1142                                        target_rot.yy(),
1143                                        target_rot.yz(),
1144                                        target_rot.zx(),
1145                                        target_rot.zy(),
1146                                        target_rot.zz());
1147 
1148         align::RotationType ref_ROT(ref_rot.xx(),
1149                                     ref_rot.xy(),
1150                                     ref_rot.xz(),
1151                                     ref_rot.yx(),
1152                                     ref_rot.yy(),
1153                                     ref_rot.yz(),
1154                                     ref_rot.zx(),
1155                                     ref_rot.zy(),
1156                                     ref_rot.zz());
1157 
1158         const std::vector<double> deltaRot = {::deltaPhi(align::toAngles(target_ROT)[0], align::toAngles(ref_ROT)[0]),
1159                                               ::deltaPhi(align::toAngles(target_ROT)[1], align::toAngles(ref_ROT)[1]),
1160                                               ::deltaPhi(align::toAngles(target_ROT)[2], align::toAngles(ref_ROT)[2])};
1161 
1162         const auto& deltaTrans = target_ali[i].translation() - ref_ali[i].translation();
1163 
1164         // fill the histograms
1165         if (diff) {
1166           compare[AlignmentPI::t_x]->Fill(deltaTrans.x() * AlignmentPI::cmToUm);
1167           compare[AlignmentPI::t_y]->Fill(deltaTrans.y() * AlignmentPI::cmToUm);
1168           compare[AlignmentPI::t_z]->Fill(deltaTrans.z() * AlignmentPI::cmToUm);
1169 
1170           compare[AlignmentPI::rot_alpha]->Fill(deltaRot[0] * AlignmentPI::tomRad);
1171           compare[AlignmentPI::rot_beta]->Fill(deltaRot[1] * AlignmentPI::tomRad);
1172           compare[AlignmentPI::rot_gamma]->Fill(deltaRot[2] * AlignmentPI::tomRad);
1173         } else {
1174           compare[AlignmentPI::t_x]->SetBinContent(i + 1, deltaTrans.x() * AlignmentPI::cmToUm);
1175           compare[AlignmentPI::t_y]->SetBinContent(i + 1, deltaTrans.y() * AlignmentPI::cmToUm);
1176           compare[AlignmentPI::t_z]->SetBinContent(i + 1, deltaTrans.z() * AlignmentPI::cmToUm);
1177 
1178           compare[AlignmentPI::rot_alpha]->SetBinContent(i + 1, deltaRot[0] * AlignmentPI::tomRad);
1179           compare[AlignmentPI::rot_beta]->SetBinContent(i + 1, deltaRot[1] * AlignmentPI::tomRad);
1180           compare[AlignmentPI::rot_gamma]->SetBinContent(i + 1, deltaRot[2] * AlignmentPI::tomRad);
1181         }
1182 
1183       }  // if it's the same detid
1184     }    // loop on detids
1185   }
1186 
1187   /*--------------------------------------------------------------------*/
1188   inline bool isReorderedTFPXTEPX(const std::vector<AlignTransform>& transforms)
1189   /*--------------------------------------------------------------------*/
1190   {
1191     // Lambda function to extract the disk, blade panel and numbers from rawId
1192     auto extractBladePanel = [](const AlignTransform& transform) {
1193       // Extract blade and panel numbers using bitwise operations
1194       uint32_t rawId = transform.rawId();
1195       int subid = DetId(transform.rawId()).subdetId();
1196       if (subid == 2) {
1197         // Tracker with subdisk hierarchy level (additional hierarchy level wrt original)
1198         // see for parameters: Geometry/TrackerCommonData/data/PhaseII/TFPXTEPXReordered/trackerParameters.xml
1199         //
1200         //<Vector name="Subdetector2" type="numeric" nEntries="12">
1201         //  23, 19, 18, 12, 10, 2, 0x3, 0xF, 0x1, 0x3F, 0x3, 0xFF
1202         //</Vector>
1203 
1204         //unsigned int sideStartBit_ = 23;
1205         //unsigned int diskStartBit_ = 19;
1206         //unsigned int subDiskStartBit_ = 18;
1207         //unsigned int bladeStartBit_ = 12;
1208         //unsigned int panelStartBit_ = 10;
1209         //unsigned int moduleStartBit_ = 2;
1210         //unsigned int sideMask_ = 0x3;
1211         //unsigned int diskMask_ = 0xF;
1212         //unsigned int subDiskMask_ = 0x1;
1213         //unsigned int bladeMask_ = 0x3F;
1214         //unsigned int panelMask_ = 0x3;
1215         //unsigned int moduleMask_ = 0xFF;
1216 
1217         // Original Tracker
1218         // see for parameters: Geometry/TrackerCommonData/data/PhaseII/trackerParameters.xml
1219         //
1220         //<Vector name="Subdetector2" type="numeric" nEntries="10">
1221         // 23, 18, 12, 10, 2, 0x3, 0xF, 0x3F, 0x3, 0xFF
1222         //</Vector>
1223 
1224         //unsigned int sideStartBit_   = 23;
1225         unsigned int diskStartBit_ = 18;
1226         unsigned int bladeStartBit_ = 12;
1227         unsigned int panelStartBit_ = 10;
1228         //unsigned int moduleStartBit_ = 2;
1229         //unsigned int sideMask_       = 0x3;
1230         unsigned int diskMask_ = 0xF;
1231         unsigned int bladeMask_ = 0x3F;
1232         unsigned int panelMask_ = 0x3;
1233         //unsigned int moduleMask_     = 0xFF;
1234 
1235         int disk = (rawId >> diskStartBit_) & diskMask_;     // Assuming regular trackerParameters.xml
1236         int blade = (rawId >> bladeStartBit_) & bladeMask_;  // Assuming regular trackerParameters.xml
1237         int panel = (rawId >> panelStartBit_) & panelMask_;  // Assuming regular trackerParameters.xml
1238         return std::make_tuple(disk, blade, panel);
1239       }
1240       return std::make_tuple(-1, -1, -1);  // Return (-1, -1, -1) if subdetId is not 2
1241     };
1242 
1243     bool foundZeroDisk = false;  // Flag to track if a disk with value 0 is found
1244     std::for_each(
1245         transforms.begin(), transforms.end(), [&extractBladePanel, &foundZeroDisk](const AlignTransform& transform) {
1246           auto [disk, blade, panel] = extractBladePanel(transform);
1247           int subid = DetId(transform.rawId()).subdetId();
1248           if (subid == 2) {
1249             if (disk == 0) {
1250               edm::LogInfo("isReorderedTFPXTEPX") << "subid: " << subid << " detid: " << transform.rawId()
1251                                                   << " disk: " << disk << " blade: " << blade << " panel: " << panel;
1252               foundZeroDisk = true;  // Set flag to true if disk value is 0
1253             }
1254           }
1255         });
1256 
1257     return foundZeroDisk;  // Return true if at least one disk with value 0 is found
1258   }
1259 
1260 }  // namespace AlignmentPI
1261 
1262 #endif