Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #ifndef CONDCORE_SIPIXELPLUGINS_SIPIXELPAYLOADINSPECTORHELPER_H
0002 #define CONDCORE_SIPIXELPLUGINS_SIPIXELPAYLOADINSPECTORHELPER_H
0003 
0004 #include <vector>
0005 #include <numeric>
0006 #include <fstream>  // std::ifstream
0007 #include <string>
0008 #include <bitset>
0009 
0010 #include "TGraph.h"
0011 #include "TH1.h"
0012 #include "TH2.h"
0013 #include "TLatex.h"
0014 #include "TLine.h"
0015 #include "TPave.h"
0016 #include "TPaveStats.h"
0017 #include "TPaveText.h"
0018 #include "TStyle.h"
0019 #include "TCanvas.h"
0020 
0021 #include "CondCore/CondDB/interface/Time.h"
0022 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0023 #include "FWCore/ParameterSet/interface/FileInPath.h"
0024 #include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
0025 #include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h"
0026 #include "DataFormats/TrackerCommon/interface/PixelBarrelName.h"
0027 #include "DataFormats/TrackerCommon/interface/PixelEndcapName.h"
0028 
0029 //#define MMDEBUG
0030 #ifdef MMDEBUG
0031 #include <iostream>
0032 #define COUT std::cout << "MM "
0033 #else
0034 #define COUT edm::LogVerbatim("")
0035 #endif
0036 
0037 namespace SiPixelPI {
0038 
0039   enum phase { zero = 0, one = 1, two = 2, undefined = 999 };
0040 
0041   // size of the phase-0 pixel detID list
0042   static const unsigned int phase0size = 1440;
0043   static const unsigned int phase1size = 1856;
0044   static const unsigned int phase2size = 3892;
0045   static const unsigned int mismatched = 9999;
0046 
0047   //============================================================================
0048   // struct to store info useful to construct topology based on the detid list
0049   struct PhaseInfo {
0050     // construct with det size
0051     PhaseInfo(unsigned int size) : m_detsize(size) {}
0052     // construct passing the phase
0053     PhaseInfo(const phase& thePhase) {
0054       switch (thePhase) {
0055         case phase::zero:
0056           m_detsize = phase0size;
0057           break;
0058         case phase::one:
0059           m_detsize = phase1size;
0060           break;
0061         case phase::two:
0062           m_detsize = phase2size;
0063           break;
0064         default:
0065           m_detsize = 99999;
0066           edm::LogError("PhaseInfo") << "undefined phase: " << thePhase;
0067       }
0068     }
0069     virtual ~PhaseInfo() { edm::LogInfo("PhaseInfo") << "PhaseInfo::~PhaseInfo()\n"; }
0070     const SiPixelPI::phase phase() const {
0071       if (m_detsize == phase0size)
0072         return phase::zero;
0073       else if (m_detsize == phase1size)
0074         return phase::one;
0075       else if (m_detsize > phase1size)
0076         return phase::two;
0077       else {
0078         throw cms::Exception("LogicError") << "this detId list size: " << m_detsize << "should not exist!";
0079       }
0080     }
0081 
0082     const char* pathToTopoXML() {
0083       if (m_detsize == phase0size)
0084         return "Geometry/TrackerCommonData/data/trackerParameters.xml";
0085       else if (m_detsize == phase1size)
0086         return "Geometry/TrackerCommonData/data/PhaseI/trackerParameters.xml";
0087       else if (m_detsize > phase1size)
0088         return "Geometry/TrackerCommonData/data/PhaseII/trackerParameters.xml";
0089       else {
0090         throw cms::Exception("LogicError") << "this detId list size: " << m_detsize << "should not exist!";
0091       }
0092     }
0093 
0094     const void print(std::stringstream& ss) {
0095       ss << "---------------------------------------------------------------\n"
0096          << "                        PhaseInfo Data                       \n\n"
0097          << " Phase :    " << phase() << "\n"
0098          << " DetSide:   " << m_detsize << "\n"
0099          << " pathToXML: " << pathToTopoXML() << "\n"
0100          << "-------------------------------------------------------------\n\n";
0101     }
0102 
0103     const bool isPhase1Comparison(const PhaseInfo& theOtherPhase) const {
0104       if (phase() == phase::one || theOtherPhase.phase() == phase::one)
0105         return true;
0106       else
0107         return false;
0108     }
0109 
0110     const bool isComparedWithPhase2(const PhaseInfo& theOtherPhase) const {
0111       if ((phase() == phase::two && theOtherPhase.phase() != phase::two) ||
0112           (phase() != phase::two && theOtherPhase.phase() == phase::two)) {
0113         return true;
0114       } else {
0115         return false;
0116       }
0117     }
0118 
0119   private:
0120     size_t m_detsize;
0121   };
0122 
0123   //============================================================================
0124   // add ostream for PhaseInfo
0125   inline std::ostream& operator<<(std::ostream& os, PhaseInfo phInfo) {
0126     std::stringstream ss;
0127     phInfo.print(ss);
0128     os << ss.str();
0129     return os;
0130   }
0131 
0132   //============================================================================
0133   inline std::pair<unsigned int, unsigned int> unpack(cond::Time_t since) {
0134     auto kLowMask = 0XFFFFFFFF;
0135     auto run = (since >> 32);
0136     auto lumi = (since & kLowMask);
0137     return std::make_pair(run, lumi);
0138   }
0139 
0140   //============================================================================
0141   // Taken from pixel naming classes
0142   // BmO (-z-x) = 1, BmI (-z+x) = 2 , BpO (+z-x) = 3 , BpI (+z+x) = 4
0143   inline int quadrant(const DetId& detid, const TrackerTopology* tTopo_, bool phase_) {
0144     if (detid.subdetId() == PixelSubdetector::PixelBarrel) {
0145       return PixelBarrelName(detid, tTopo_, phase_).shell();
0146     } else {
0147       return PixelEndcapName(detid, tTopo_, phase_).halfCylinder();
0148     }
0149   }
0150 
0151   //============================================================================
0152   // Online ladder convention taken from pixel naming class for barrel
0153   // Apply sign convention (- sign for BmO and BpO)
0154   inline int signed_ladder(const DetId& detid, const TrackerTopology& tTopo_, bool phase_) {
0155     if (detid.subdetId() != PixelSubdetector::PixelBarrel)
0156       return -9999;
0157     int signed_ladder = PixelBarrelName(detid, &tTopo_, phase_).ladderName();
0158     if (quadrant(detid, &tTopo_, phase_) % 2)
0159       signed_ladder *= -1;
0160     return signed_ladder;
0161   }
0162 
0163   //============================================================================
0164   // Online mdoule convention taken from pixel naming class for barrel
0165   // Apply sign convention (- sign for BmO and BmI)
0166   inline int signed_module(const DetId& detid, const TrackerTopology& tTopo_, bool phase_) {
0167     if (detid.subdetId() != PixelSubdetector::PixelBarrel)
0168       return -9999;
0169     int signed_module = PixelBarrelName(detid, &tTopo_, phase_).moduleName();
0170     if (quadrant(detid, &tTopo_, phase_) < 3)
0171       signed_module *= -1;
0172     return signed_module;
0173   }
0174 
0175   //============================================================================
0176   // Phase 0: Ring was not an existing convention
0177   //   but the 7 plaquettes were split by HV group
0178   //   --> Derive Ring 1/2 for them
0179   //   Panel 1 plq 1-2, Panel 2, plq 1   = Ring 1
0180   //   Panel 1 plq 3-4, Panel 2, plq 2-3 = Ring 2
0181   // Phase 1: Using pixel naming class for endcap
0182   inline int ring(const DetId& detid, const TrackerTopology& tTopo_, bool phase_) {
0183     if (detid.subdetId() != PixelSubdetector::PixelEndcap)
0184       return -9999;
0185     int ring = -9999;
0186     if (phase_ == 0) {
0187       ring = 1 + (tTopo_.pxfPanel(detid) + tTopo_.pxfModule(detid) > 3);
0188     } else if (phase_ == 1) {
0189       ring = PixelEndcapName(detid, &tTopo_, phase_).ringName();
0190     }
0191     return ring;
0192   }
0193 
0194   //============================================================================
0195   // Online blade convention taken from pixel naming class for endcap
0196   // Apply sign convention (- sign for BmO and BpO)
0197   inline int signed_blade(const DetId& detid, const TrackerTopology& tTopo_, bool phase_) {
0198     if (detid.subdetId() != PixelSubdetector::PixelEndcap)
0199       return -9999;
0200     int signed_blade = PixelEndcapName(detid, &tTopo_, phase_).bladeName();
0201     if (quadrant(detid, &tTopo_, phase_) % 2)
0202       signed_blade *= -1;
0203     return signed_blade;
0204   }
0205 
0206   //============================================================================
0207   inline int signed_blade_panel(const DetId& detid, const TrackerTopology& tTopo_, bool phase_) {
0208     if (detid.subdetId() != PixelSubdetector::PixelEndcap)
0209       return -9999;
0210     int signed_blade_panel = signed_blade(detid, tTopo_, phase_) + (tTopo_.pxfPanel(detid) - 1);
0211     return signed_blade_panel;
0212   }
0213 
0214   //============================================================================
0215   // Online disk convention
0216   // Apply sign convention (- sign for BmO and BmI)
0217   inline int signed_disk(const DetId& detid, const TrackerTopology& tTopo_, bool phase_) {
0218     if (detid.subdetId() != PixelSubdetector::PixelEndcap)
0219       return -9999;
0220     int signed_disk = tTopo_.pxfDisk(DetId(detid));
0221     if (quadrant(detid, &tTopo_, phase_) < 3)
0222       signed_disk *= -1;
0223     return signed_disk;
0224   }
0225 
0226   //============================================================================
0227   inline void draw_line(double x1, double x2, double y1, double y2, int width = 2, int style = 1, int color = 1) {
0228     TLine* l = new TLine(x1, y1, x2, y2);
0229     l->SetBit(kCanDelete);
0230     l->SetLineWidth(width);
0231     l->SetLineStyle(style);
0232     l->SetLineColor(color);
0233     l->Draw();
0234   }
0235 
0236   //============================================================================
0237   inline void dress_occup_plot(TCanvas& canv,
0238                                TH2* h,
0239                                int lay,
0240                                int ring = 0,
0241                                int phase = 0,
0242                                bool half_shift = true,
0243                                bool mark_zero = true,
0244                                bool standard_palette = true) {
0245     std::string s_title;
0246 
0247     if (lay > 0) {
0248       canv.cd(lay);
0249       s_title = "Barrel Pixel Layer " + std::to_string(lay);
0250     } else {
0251       canv.cd(ring);
0252       if (ring > 4) {
0253         ring = ring - 4;
0254       }
0255       s_title = "Forward Pixel Ring " + std::to_string(ring);
0256     }
0257 
0258     gStyle->SetPadRightMargin(0.125);
0259 
0260     if (standard_palette) {
0261       gStyle->SetPalette(1);
0262     } else {
0263       // this is the fine gradient palette
0264       const Int_t NRGBs = 5;
0265       const Int_t NCont = 255;
0266 
0267       Double_t stops[NRGBs] = {0.00, 0.34, 0.61, 0.84, 1.00};
0268       Double_t red[NRGBs] = {0.00, 0.00, 0.87, 1.00, 0.51};
0269       Double_t green[NRGBs] = {0.00, 0.81, 1.00, 0.20, 0.00};
0270       Double_t blue[NRGBs] = {0.51, 1.00, 0.12, 0.00, 0.00};
0271       TColor::CreateGradientColorTable(NRGBs, stops, red, green, blue, NCont);
0272       gStyle->SetNumberContours(NCont);
0273     }
0274 
0275     h->SetMarkerSize(0.7);
0276     h->Draw("colz1");
0277 
0278     auto ltx = TLatex();
0279     ltx.SetTextFont(62);
0280     ltx.SetTextColor(1);
0281     ltx.SetTextSize(0.06);
0282     ltx.SetTextAlign(31);
0283     ltx.DrawLatexNDC(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, (s_title).c_str());
0284 
0285     // Draw Lines around modules
0286     if (lay > 0) {
0287       std::vector<std::vector<int>> nladder = {{10, 16, 22}, {6, 14, 22, 32}};
0288       int nlad = nladder[phase][lay - 1];
0289       for (int xsign = -1; xsign <= 1; xsign += 2)
0290         for (int ysign = -1; ysign <= 1; ysign += 2) {
0291           float xlow = xsign * (half_shift * 0.5);
0292           float xhigh = xsign * (half_shift * 0.5 + 4);
0293           float ylow = ysign * (half_shift * 0.5 + (phase == 0) * 0.5);
0294           float yhigh = ysign * (half_shift * 0.5 - (phase == 0) * 0.5 + nlad);
0295           // Outside box
0296           draw_line(xlow, xhigh, ylow, ylow, 1);    // bottom
0297           draw_line(xlow, xhigh, yhigh, yhigh, 1);  // top
0298           draw_line(xlow, xlow, ylow, yhigh, 1);    // left
0299           draw_line(xhigh, xhigh, ylow, yhigh, 1);  // right
0300           // Inner Horizontal lines
0301           for (int lad = 1; lad < nlad; ++lad) {
0302             float y = ysign * (lad + half_shift * 0.5);
0303             draw_line(xlow, xhigh, y, y, 1);
0304           }
0305           for (int lad = 1; lad <= nlad; ++lad)
0306             if (!(phase == 0 && (lad == 1 || lad == nlad))) {
0307               float y = ysign * (lad + half_shift * 0.5 - 0.5);
0308               draw_line(xlow, xhigh, y, y, 1, 3);
0309             }
0310           // Inner Vertical lines
0311           for (int mod = 1; mod < 4; ++mod) {
0312             float x = xsign * (mod + half_shift * 0.5);
0313             draw_line(x, x, ylow, yhigh, 1);
0314           }
0315           // Make a BOX around ROC 0
0316           // Phase 0 - ladder +1 is always non-flipped
0317           // Phase 1 - ladder +1 is always     flipped
0318           if (mark_zero) {
0319             for (int mod = 1; mod <= 4; ++mod)
0320               for (int lad = 1; lad <= nlad; ++lad) {
0321                 bool flipped = ysign == 1 ? lad % 2 == 0 : lad % 2 == 1;
0322                 if (phase == 1)
0323                   flipped = !flipped;
0324                 int roc0_orientation = flipped ? -1 : 1;
0325                 if (xsign == -1)
0326                   roc0_orientation *= -1;
0327                 if (ysign == -1)
0328                   roc0_orientation *= -1;
0329                 float x1 = xsign * (mod + half_shift * 0.5);
0330                 float x2 = xsign * (mod + half_shift * 0.5 - 1. / 8);
0331                 float y1 = ysign * (lad + half_shift * 0.5 - 0.5);
0332                 float y2 = ysign * (lad + half_shift * 0.5 - 0.5 + roc0_orientation * 1. / 2);
0333                 if (!(phase == 0 && (lad == 1 || lad == nlad) && xsign == -1)) {
0334                   if (lay == 1 && xsign <= -1) {
0335                     float x1 = xsign * ((mod - 1) + half_shift * 0.5);
0336                     float x2 = xsign * ((mod - 1) + half_shift * 0.5 + 1. / 8);
0337                     float y1 = ysign * (lad + half_shift * 0.5 - 0.5 + roc0_orientation);
0338                     float y2 = ysign * (lad + half_shift * 0.5 - 0.5 + roc0_orientation * 3. / 2);
0339                     draw_line(x1, x2, y1, y1, 1);
0340                     draw_line(x2, x2, y1, y2, 1);
0341                   } else {
0342                     draw_line(x1, x2, y1, y1, 1);
0343                     //draw_line(x1, x2, y2, y2, 1);
0344                     //draw_line(x1, x1, y1, y2, 1);
0345                     draw_line(x2, x2, y1, y2, 1);
0346                   }
0347                 }
0348               }
0349           }
0350         }
0351     } else {
0352       // FPIX
0353       for (int dsk = 1, ndsk = 2 + (phase == 1); dsk <= ndsk; ++dsk) {
0354         for (int xsign = -1; xsign <= 1; xsign += 2)
0355           for (int ysign = -1; ysign <= 1; ysign += 2) {
0356             if (phase == 0) {
0357               int first_roc = 3, nbin = 16;
0358               for (int bld = 1, nbld = 12; bld <= nbld; ++bld) {
0359                 // Horizontal lines
0360                 for (int plq = 1, nplq = 7; plq <= nplq; ++plq) {
0361                   float xlow =
0362                       xsign * (half_shift * 0.5 + dsk - 1 + (first_roc - 3 + 2 * plq + (plq == 1)) / (float)nbin);
0363                   float xhigh =
0364                       xsign * (half_shift * 0.5 + dsk - 1 + (first_roc - 3 + 2 * (plq + 1) - (plq == 7)) / (float)nbin);
0365                   float ylow = ysign * (half_shift * 0.5 + (bld - 0.5) - (2 + plq / 2) * 0.1);
0366                   float yhigh = ysign * (half_shift * 0.5 + (bld - 0.5) + (2 + plq / 2) * 0.1);
0367                   draw_line(xlow, xhigh, ylow, ylow, 1);    // bottom
0368                   draw_line(xlow, xhigh, yhigh, yhigh, 1);  // top
0369                 }
0370                 // Vertical lines
0371                 for (int plq = 1, nplq = 7 + 1; plq <= nplq; ++plq) {
0372                   float x = xsign * (half_shift * 0.5 + dsk - 1 +
0373                                      (first_roc - 3 + 2 * plq + (plq == 1) - (plq == 8)) / (float)nbin);
0374                   float ylow = ysign * (half_shift * 0.5 + (bld - 0.5) - (2 + (plq - (plq == 8)) / 2) * 0.1);
0375                   float yhigh = ysign * (half_shift * 0.5 + (bld - 0.5) + (2 + (plq - (plq == 8)) / 2) * 0.1);
0376                   draw_line(x, x, ylow, yhigh, 1);
0377                 }
0378                 // Panel 2 has dashed mid-plane
0379                 for (int plq = 2, nplq = 6; plq <= nplq; ++plq)
0380                   if (plq % 2 == 0) {
0381                     float x = xsign * (half_shift * 0.5 + dsk - 1 +
0382                                        (first_roc - 3 + 2 * plq + (plq == 1) - (plq == 8) + 1) / (float)nbin);
0383                     float ylow = ysign * (half_shift * 0.5 + (bld - 0.5) - (2 + (plq - (plq == 8)) / 2) * 0.1);
0384                     float yhigh = ysign * (half_shift * 0.5 + (bld - 0.5) + (2 + (plq - (plq == 8)) / 2) * 0.1);
0385                     draw_line(x, x, ylow, yhigh, 1, 2);
0386                   }
0387                 // Make a BOX around ROC 0
0388                 for (int plq = 1, nplq = 7; plq <= nplq; ++plq) {
0389                   float x1 =
0390                       xsign * (half_shift * 0.5 + dsk - 1 + (first_roc - 3 + 2 * plq + (plq == 1)) / (float)nbin);
0391                   float x2 =
0392                       xsign * (half_shift * 0.5 + dsk - 1 + (first_roc - 3 + 2 * plq + (plq == 1) + 1) / (float)nbin);
0393                   int sign = xsign * ysign * ((plq % 2) ? 1 : -1);
0394                   float y1 = ysign * (half_shift * 0.5 + (bld - 0.5) + sign * (2 + plq / 2) * 0.1);
0395                   float y2 = ysign * (half_shift * 0.5 + (bld - 0.5) + sign * (plq / 2) * 0.1);
0396                   //draw_line(x1, x2, y1, y1, 1);
0397                   draw_line(x1, x2, y2, y2, 1);
0398                   //draw_line(x1, x1, y1, y2, 1);
0399                   draw_line(x2, x2, y1, y2, 1);
0400                 }
0401               }
0402             } else if (phase == 1) {
0403               if (ring == 0) {  // both
0404                 for (int ring = 1; ring <= 2; ++ring)
0405                   for (int bld = 1, nbld = 5 + ring * 6; bld <= nbld; ++bld) {
0406                     float scale = (ring == 1) ? 1.5 : 1;
0407                     Color_t p1_color = 1, p2_color = 1;
0408                     // Horizontal lines
0409                     // Panel 2 has dashed mid-plane
0410                     float x1 = xsign * (half_shift * 0.5 + dsk - 1 + (ring - 1) * 0.5);
0411                     float x2 = xsign * (half_shift * 0.5 + dsk - 1 + ring * 0.5);
0412                     int sign = ysign;
0413                     float y1 = ysign * (half_shift * 0.5 - 0.5 + scale * bld + sign * 0.5);
0414                     //float yp1_mid = ysign * (half_shift*0.5 - 0.5 + scale*bld + sign*0.25);
0415                     float y2 = ysign * (half_shift * 0.5 - 0.5 + scale * bld);
0416                     float yp2_mid = ysign * (half_shift * 0.5 - 0.5 + scale * bld - sign * 0.25);
0417                     float y3 = ysign * (half_shift * 0.5 - 0.5 + scale * bld - sign * 0.5);
0418                     draw_line(x1, x2, y1, y1, 1, 1, p1_color);
0419                     //draw_line(x1, x2, yp1_mid, yp1_mid, 1, 3);
0420                     draw_line(x1, x2, y2, y2, 1, 1, p1_color);
0421                     draw_line(x1, x2, yp2_mid, yp2_mid, 1, 2);
0422                     draw_line(x1, x2, y3, y3, 1, 1, p2_color);
0423                     // Vertical lines
0424                     float x = xsign * (half_shift * 0.5 + dsk - 1 + (ring - 1) * 0.5);
0425                     draw_line(x, x, y1, y2, 1, 1, p1_color);
0426                     draw_line(x, x, y2, y3, 1, 1, p2_color);
0427                     if (ring == 2) {
0428                       //draw_line(x,  x,  y2,  y3, 1, 1, p1_color);
0429                       x = xsign * (half_shift * 0.5 + dsk);
0430                       draw_line(x, x, y1, y2, 1, 1, p1_color);
0431                       draw_line(x, x, y2, y3, 1, 1, p2_color);
0432                     }
0433                     // Make a BOX around ROC 0
0434                     x1 = xsign * (half_shift * 0.5 + dsk - 1 + ring * 0.5 - 1 / 16.);
0435                     x2 = xsign * (half_shift * 0.5 + dsk - 1 + ring * 0.5);
0436                     float y1_p1 = ysign * (half_shift * 0.5 - 0.5 + scale * bld + sign * 0.25);
0437                     float y2_p1 = ysign * (half_shift * 0.5 - 0.5 + scale * bld + sign * 0.25 + xsign * ysign * 0.25);
0438                     draw_line(x1, x2, y1_p1, y1_p1, 1);
0439                     //draw_line(x1, x2, y2_p1, y2_p1, 1);
0440                     draw_line(x1, x1, y1_p1, y2_p1, 1);
0441                     //draw_line(x2, x2, y1_p1, y2_p1, 1);
0442                     float y1_p2 = ysign * (half_shift * 0.5 - 0.5 + scale * bld - sign * 0.25);
0443                     float y2_p2 = ysign * (half_shift * 0.5 - 0.5 + scale * bld - sign * 0.25 - xsign * ysign * 0.25);
0444                     draw_line(x1, x2, y1_p2, y1_p2, 1);
0445                     //draw_line(x1, x2, y2_p2, y2_p2, 1);
0446                     draw_line(x1, x1, y1_p2, y2_p2, 1);
0447                     //draw_line(x2, x2, y1_p2, y2_p2, 1);
0448                   }
0449               } else {  // only one ring, 1 or 2
0450                 for (int bld = 1, nbld = 5 + ring * 6; bld <= nbld; ++bld) {
0451                   Color_t p1_color = 1, p2_color = 1;
0452                   // Horizontal lines
0453                   // Panel 2 has dashed mid-plane
0454                   float x1 = xsign * (half_shift * 0.5 + dsk - 1);
0455                   float x2 = xsign * (half_shift * 0.5 + dsk);
0456                   int sign = ysign;
0457                   float y1 = ysign * (half_shift * 0.5 - 0.5 + bld + sign * 0.5);
0458                   //float yp1_mid = ysign * (half_shift*0.5 - 0.5 + bld + sign*0.25);
0459                   float y2 = ysign * (half_shift * 0.5 - 0.5 + bld);
0460                   float yp2_mid = ysign * (half_shift * 0.5 - 0.5 + bld - sign * 0.25);
0461                   float y3 = ysign * (half_shift * 0.5 - 0.5 + bld - sign * 0.5);
0462                   draw_line(x1, x2, y1, y1, 1, 1, p1_color);
0463                   //draw_line(x1, x2, yp1_mid, yp1_mid, 1, 3);
0464                   draw_line(x1, x2, y2, y2, 1, 1, p1_color);
0465                   draw_line(x1, x2, yp2_mid, yp2_mid, 1, 2);
0466                   draw_line(x1, x2, y3, y3, 1, 1, p2_color);
0467                   // Vertical lines
0468                   float x = xsign * (half_shift * 0.5 + dsk - 1);
0469                   draw_line(x, x, y1, y2, 1, 1, p1_color);
0470                   draw_line(x, x, y2, y3, 1, 1, p2_color);
0471                   if (ring == 2) {
0472                     //draw_line(x,  x,  y2,  y3, 1, 1, p1_color);
0473                     x = xsign * (half_shift * 0.5 + dsk);
0474                     draw_line(x, x, y1, y2, 1, 1, p1_color);
0475                     draw_line(x, x, y2, y3, 1, 1, p2_color);
0476                   }
0477                   // Make a BOX around ROC 0
0478                   x1 = xsign * (half_shift * 0.5 + dsk - 1 / 8.);
0479                   x2 = xsign * (half_shift * 0.5 + dsk);
0480                   float y1_p1 = ysign * (half_shift * 0.5 - 0.5 + bld + sign * 0.25);
0481                   float y2_p1 = ysign * (half_shift * 0.5 - 0.5 + bld + sign * 0.25 + xsign * ysign * 0.25);
0482                   draw_line(x1, x2, y1_p1, y1_p1, 1);
0483                   //draw_line(x1, x2, y2_p1, y2_p1, 1);
0484                   draw_line(x1, x1, y1_p1, y2_p1, 1);
0485                   //draw_line(x2, x2, y1_p1, y2_p1, 1);
0486                   float y1_p2 = ysign * (half_shift * 0.5 - 0.5 + bld - sign * 0.25);
0487                   float y2_p2 = ysign * (half_shift * 0.5 - 0.5 + bld - sign * 0.25 - xsign * ysign * 0.25);
0488                   draw_line(x1, x2, y1_p2, y1_p2, 1);
0489                   //draw_line(x1, x2, y2_p2, y2_p2, 1);
0490                   draw_line(x1, x1, y1_p2, y2_p2, 1);
0491                   //draw_line(x2, x2, y1_p2, y2_p2, 1);
0492                 }
0493               }
0494             }
0495           }
0496       }
0497       // Special shifted "rebin" for Phase 0
0498       // Y axis should always have at least half-roc granularity because
0499       // there are half-ROC size shifts implemented in the coordinates
0500       // To remove this and show full ROC granularity
0501       // We merge bin contents in each pair of bins corresponding to one ROC
0502       // TODO: make sure this works for Profiles
0503       if (phase == 0 && h->GetNbinsY() == 250 && h->GetNbinsX() == 80) {
0504         int nentries = h->GetEntries();
0505         for (int binx = 1; binx <= 80; ++binx) {
0506           double sum = 0;
0507           for (int biny = 1; biny <= 250; ++biny) {
0508             bool odd_nrocy = (binx - 1 < 40) != (((binx - 1) / 4) % 2);
0509             if (biny % 2 == odd_nrocy)
0510               sum += h->GetBinContent(binx, biny);
0511             else {
0512               sum += h->GetBinContent(binx, biny);
0513               if (sum) {
0514                 h->SetBinContent(binx, biny, sum);
0515                 h->SetBinContent(binx, biny - 1, sum);
0516               }
0517               sum = 0;
0518             }
0519           }
0520         }
0521         h->SetEntries(nentries);
0522       }
0523     }
0524   }
0525 
0526   /*--------------------------------------------------------------------*/
0527   inline void adjustCanvasMargins(TVirtualPad* pad, float top, float bottom, float left, float right)
0528   /*--------------------------------------------------------------------*/
0529   {
0530     if (top > 0)
0531       pad->SetTopMargin(top);
0532     if (bottom > 0)
0533       pad->SetBottomMargin(bottom);
0534     if (left > 0)
0535       pad->SetLeftMargin(left);
0536     if (right > 0)
0537       pad->SetRightMargin(right);
0538   }
0539 
0540   /*--------------------------------------------------------------------*/
0541   inline void adjustStats(TPaveStats* stats, float X1, float Y1, float X2, float Y2)
0542   /*--------------------------------------------------------------------*/
0543   {
0544     stats->SetX1NDC(X1);  //new x start position
0545     stats->SetY1NDC(Y1);  //new y start position
0546     stats->SetX2NDC(X2);  //new x end position
0547     stats->SetY2NDC(Y2);  //new y end position
0548   }
0549 
0550   /*--------------------------------------------------------------------*/
0551   inline std::pair<float, float> getExtrema(TH1* h1, TH1* h2)
0552   /*--------------------------------------------------------------------*/
0553   {
0554     float theMax(-9999.);
0555     float theMin(9999.);
0556     theMax = h1->GetMaximum() > h2->GetMaximum() ? h1->GetMaximum() : h2->GetMaximum();
0557     theMin = h1->GetMinimum() < h2->GetMaximum() ? h1->GetMinimum() : h2->GetMinimum();
0558 
0559     float add_min = theMin > 0. ? -0.05 : 0.05;
0560     float add_max = theMax > 0. ? 0.05 : -0.05;
0561 
0562     auto result = std::make_pair(theMin * (1 + add_min), theMax * (1 + add_max));
0563     return result;
0564   }
0565 
0566   /*--------------------------------------------------------------------*/
0567   inline void makeNicePlotStyle(TH1* hist)
0568   /*--------------------------------------------------------------------*/
0569   {
0570     hist->SetStats(kFALSE);
0571     hist->SetLineWidth(2);
0572     hist->GetXaxis()->CenterTitle(true);
0573     hist->GetYaxis()->CenterTitle(true);
0574     hist->GetXaxis()->SetTitleFont(42);
0575     hist->GetYaxis()->SetTitleFont(42);
0576     hist->GetXaxis()->SetTitleSize(0.05);
0577     hist->GetYaxis()->SetTitleSize(0.05);
0578     hist->GetXaxis()->SetTitleOffset(1.1);
0579     hist->GetYaxis()->SetTitleOffset(1.3);
0580     hist->GetXaxis()->SetLabelFont(42);
0581     hist->GetYaxis()->SetLabelFont(42);
0582     hist->GetYaxis()->SetLabelSize(.05);
0583     hist->GetXaxis()->SetLabelSize(.05);
0584 
0585     if (hist->InheritsFrom(TH2::Class())) {
0586       hist->GetZaxis()->SetLabelFont(42);
0587       hist->GetZaxis()->SetLabelFont(42);
0588       hist->GetZaxis()->SetLabelSize(.05);
0589       hist->GetZaxis()->SetLabelSize(.05);
0590     }
0591   }
0592 
0593   enum DetType { t_barrel = 0, t_forward = 1, t_all = 2 };
0594   const std::array<std::string, 3> DetNames = {{"Barrel", "End Caps", "Whole"}};
0595 
0596   enum regions {
0597     BPixL1o,        //0  Barrel Pixel Layer 1 outer
0598     BPixL1i,        //1  Barrel Pixel Layer 1 inner
0599     BPixL2o,        //2  Barrel Pixel Layer 2 outer
0600     BPixL2i,        //3  Barrel Pixel Layer 2 inner
0601     BPixL3o,        //4  Barrel Pixel Layer 3 outer
0602     BPixL3i,        //5  Barrel Pixel Layer 3 inner
0603     BPixL4o,        //6  Barrel Pixel Layer 4 outer
0604     BPixL4i,        //7  Barrel Pixel Layer 4 inner
0605     FPixmL1,        //8  Forward Pixel Minus side Disk 1
0606     FPixmL2,        //9  Forward Pixel Minus side Disk 2
0607     FPixmL3,        //10 Forward Pixel Minus side Disk 3
0608     FPixpL1,        //11 Forward Pixel Plus side Disk 1
0609     FPixpL2,        //12 Forward Pixel Plus side Disk 2
0610     FPixpL3,        //13 Forward Pixel Plus side Disk 3
0611     NUM_OF_REGIONS  //14 -- default
0612   };
0613 
0614   /*--------------------------------------------------------------------*/
0615   inline std::string getStringFromRegionEnum(SiPixelPI::regions e)
0616   /*--------------------------------------------------------------------*/
0617   {
0618     switch (e) {
0619       case SiPixelPI::BPixL1o:
0620         return "BPix L1/o";
0621       case SiPixelPI::BPixL1i:
0622         return "BPix L1/i";
0623       case SiPixelPI::BPixL2o:
0624         return "BPix L2/o";
0625       case SiPixelPI::BPixL2i:
0626         return "BPix L2/i";
0627       case SiPixelPI::BPixL3o:
0628         return "BPix L3/o";
0629       case SiPixelPI::BPixL3i:
0630         return "BPix L3/i";
0631       case SiPixelPI::BPixL4o:
0632         return "BPix L4/o";
0633       case SiPixelPI::BPixL4i:
0634         return "BPix L4/i";
0635       case SiPixelPI::FPixmL1:
0636         return "FPix- D1";
0637       case SiPixelPI::FPixmL2:
0638         return "FPix- D2";
0639       case SiPixelPI::FPixmL3:
0640         return "FPix- D3";
0641       case SiPixelPI::FPixpL1:
0642         return "FPix+ D1";
0643       case SiPixelPI::FPixpL2:
0644         return "FPix+ D2";
0645       case SiPixelPI::FPixpL3:
0646         return "FPix+ D3";
0647       default:
0648         edm::LogWarning("LogicError") << "Unknown partition: " << e;
0649         return "";
0650     }
0651   }
0652 
0653   /*--------------------------------------------------------------------*/
0654   inline bool isBPixOuterLadder(const DetId& detid, const TrackerTopology& tTopo, bool isPhase0)
0655   /*--------------------------------------------------------------------*/
0656   {
0657     // Using TrackerTopology
0658     // Ladders have a staggered structure
0659     // Non-flipped ladders are on the outer radius
0660     // Phase 0: Outer ladders are odd for layer 1,3 and even for layer 2
0661     // Phase 1: Outer ladders are odd for layer 1,2,3 and even for layer 4
0662     bool isOuter = false;
0663     int layer = tTopo.pxbLayer(detid.rawId());
0664     bool odd_ladder = tTopo.pxbLadder(detid.rawId()) % 2;
0665     if (isPhase0) {
0666       if (layer == 2)
0667         isOuter = !odd_ladder;
0668       else
0669         isOuter = odd_ladder;
0670     } else {
0671       if (layer == 4)
0672         isOuter = !odd_ladder;
0673       else
0674         isOuter = odd_ladder;
0675     }
0676     return isOuter;
0677   }
0678 
0679   // ancillary struct to manage the topology
0680   // info in a more compact way
0681 
0682   struct topolInfo {
0683   private:
0684     uint32_t m_rawid;
0685     int m_subdetid;
0686     int m_layer;
0687     int m_side;
0688     int m_ring;
0689     bool m_isInternal;
0690     SiPixelPI::phase m_Phase;
0691 
0692   public:
0693     void init();
0694     void fillGeometryInfo(const DetId& detId, const TrackerTopology& tTopo, const SiPixelPI::phase& ph);
0695     SiPixelPI::regions filterThePartition();
0696     bool sanityCheck();
0697     int subDetId() { return m_subdetid; }
0698     int layer() { return m_layer; }
0699     int side() { return m_side; }
0700     int ring() { return m_ring; }
0701     bool isInternal() { return m_isInternal; }
0702 
0703     void printAll(std::stringstream& ss) const;
0704     virtual ~topolInfo() {}
0705   };
0706 
0707   /*--------------------------------------------------------------------*/
0708   inline void topolInfo::printAll(std::stringstream& ss) const
0709   /*--------------------------------------------------------------------*/
0710   {
0711     ss << " detId: " << m_rawid << " subdetid: " << m_subdetid << " layer: " << m_layer << " side: " << m_side
0712        << " ring: " << m_ring << " isInternal: " << m_isInternal;
0713   }
0714 
0715   /*--------------------------------------------------------------------*/
0716   inline void topolInfo::init()
0717   /*--------------------------------------------------------------------*/
0718   {
0719     m_Phase = SiPixelPI::undefined;
0720     m_rawid = 0;
0721     m_subdetid = -1;
0722     m_layer = -1;
0723     m_side = -1;
0724     m_ring = -1;
0725     m_isInternal = false;
0726   };
0727 
0728   /*--------------------------------------------------------------------*/
0729   inline bool topolInfo::sanityCheck()
0730   /*--------------------------------------------------------------------*/
0731   {
0732     if (m_layer == 0 || (m_subdetid == 1 && m_layer > 4) || (m_subdetid == 2 && m_layer > 3)) {
0733       return false;
0734     } else {
0735       return true;
0736     }
0737   }
0738   /*--------------------------------------------------------------------*/
0739   inline void topolInfo::fillGeometryInfo(const DetId& detId, const TrackerTopology& tTopo, const SiPixelPI::phase& ph)
0740   /*--------------------------------------------------------------------*/
0741   {
0742     // set the phase
0743     m_Phase = ph;
0744     unsigned int subdetId = static_cast<unsigned int>(detId.subdetId());
0745 
0746     m_rawid = detId.rawId();
0747     m_subdetid = subdetId;
0748     if (subdetId == PixelSubdetector::PixelBarrel) {
0749       m_layer = tTopo.pxbLayer(detId.rawId());
0750       m_isInternal = !SiPixelPI::isBPixOuterLadder(detId, tTopo, (ph == SiPixelPI::phase::zero));
0751     } else if (subdetId == PixelSubdetector::PixelEndcap) {
0752       m_layer = tTopo.pxfDisk(detId.rawId());
0753       m_side = tTopo.pxfSide(detId.rawId());
0754     } else
0755       edm::LogWarning("LogicError") << "Unknown subdetid: " << subdetId;
0756   }
0757 
0758   // ------------ method to assign a partition based on the topology struct info ---------------
0759 
0760   /*--------------------------------------------------------------------*/
0761   inline SiPixelPI::regions topolInfo::filterThePartition()
0762   /*--------------------------------------------------------------------*/
0763   {
0764     SiPixelPI::regions ret = SiPixelPI::NUM_OF_REGIONS;
0765 
0766     if (m_Phase == SiPixelPI::undefined) {
0767       throw cms::Exception("LogicError") << "Cannot call filterThePartition BEFORE filling the geometry info!";
0768     }
0769 
0770     // BPix
0771     if (m_subdetid == 1) {
0772       switch (m_layer) {
0773         case 1:
0774           m_isInternal ? ret = SiPixelPI::BPixL1i : ret = SiPixelPI::BPixL1o;
0775           break;
0776         case 2:
0777           m_isInternal ? ret = SiPixelPI::BPixL2i : ret = SiPixelPI::BPixL2o;
0778           break;
0779         case 3:
0780           m_isInternal ? ret = SiPixelPI::BPixL3i : ret = SiPixelPI::BPixL3o;
0781           break;
0782         case 4:
0783           m_isInternal ? ret = SiPixelPI::BPixL4i : ret = SiPixelPI::BPixL4o;
0784           break;
0785         default:
0786           edm::LogWarning("LogicError") << "Unknow BPix layer: " << m_layer;
0787           break;
0788       }
0789       // FPix
0790     } else if (m_subdetid == 2) {
0791       switch (m_layer) {
0792         case 1:
0793           m_side > 1 ? ret = SiPixelPI::FPixpL1 : ret = SiPixelPI::FPixmL1;
0794           break;
0795         case 2:
0796           m_side > 1 ? ret = SiPixelPI::FPixpL2 : ret = SiPixelPI::FPixmL2;
0797           break;
0798         case 3:
0799           m_side > 1 ? ret = SiPixelPI::FPixpL3 : ret = SiPixelPI::FPixmL3;
0800           break;
0801         default:
0802           if (m_Phase < SiPixelPI::phase::two) {
0803             // warning message only if the phase2 is < 2
0804             edm::LogWarning("LogicError") << "Unknow FPix disk: " << m_layer;
0805           }
0806           break;
0807       }
0808     }
0809     return ret;
0810   }
0811 
0812   /*--------------------------------------------------------------------*/
0813   inline void displayNotSupported(TCanvas& canv, const unsigned int size)
0814   /*--------------------------------------------------------------------*/
0815   {
0816     std::string phase = (size < SiPixelPI::phase1size) ? "Phase-0" : "Phase-2";
0817     canv.cd();
0818     TLatex t2;
0819     t2.SetTextAlign(21);
0820     t2.SetTextSize(0.1);
0821     t2.SetTextAngle(45);
0822     t2.SetTextColor(kRed);
0823     if (size != SiPixelPI::mismatched) {
0824       t2.DrawLatexNDC(0.6, 0.50, Form("%s  NOT SUPPORTED!", phase.c_str()));
0825     } else {
0826       t2.DrawLatexNDC(0.6, 0.50, "MISMATCHED PAYLOAD SIZE!");
0827     }
0828   }
0829 
0830   /*--------------------------------------------------------------------*/
0831   template <typename T>
0832   std::pair<T, T> findMinMaxInMap(const std::map<unsigned int, T>& theMap)
0833   /*--------------------------------------------------------------------*/
0834   {
0835     using pairtype = std::pair<unsigned int, T>;
0836     auto max = *std::max_element(
0837         theMap.begin(), theMap.end(), [](const pairtype& p1, const pairtype& p2) { return p1.second < p2.second; });
0838     auto min = *std::min_element(
0839         theMap.begin(), theMap.end(), [](const pairtype& p1, const pairtype& p2) { return p1.second < p2.second; });
0840     return std::make_pair(min.second, max.second);
0841   }
0842 
0843   /*--------------------------------------------------------------------*/
0844   inline bool checkAnswerOK(std::string& answer, bool& result)
0845   /*--------------------------------------------------------------------*/
0846   {
0847     std::transform(answer.begin(), answer.end(), answer.begin(), [](unsigned char x) { return ::tolower(x); });
0848 
0849     bool answer_valid = (answer == "y") || (answer == "n") || (answer == "yes") || (answer == "no") ||
0850                         (answer == "true") || (answer == "false") || (answer == "1") || (answer == "0");
0851 
0852     result = answer_valid && (answer[0] == 'y' || answer[0] == 't' || answer[0] == '1');
0853     return answer_valid;
0854   }
0855 };  // namespace SiPixelPI
0856 #endif