Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:03:25

0001 // -*- C++ -*-
0002 //
0003 // Package:    CondTools/SiPixel
0004 // Class:      SiPixelQualityPlotter
0005 //
0006 /**\class SiPixelQualityPlotter SiPixelQualityPlotter.cc CondTools/SiPixel/plugins/SiPixelQualityPlotter.cc
0007 
0008  Description: [one line class summary]
0009 
0010  Implementation:
0011      [Notes on implementation]
0012 */
0013 //
0014 // Original Author:  Marco Musich
0015 //         Created:  Fri, 05 Jun 2020 12:28:51 GMT
0016 //
0017 //
0018 
0019 // user include files
0020 #include "CalibTracker/StandaloneTrackerTopology/interface/StandaloneTrackerTopology.h"
0021 #include "CondCore/CondDB/interface/Time.h"
0022 #include "CondCore/SiPixelPlugins/interface/SiPixelPayloadInspectorHelper.h"
0023 #include "CondFormats/DataRecord/interface/SiPixelFedCablingMapRcd.h"
0024 #include "CondFormats/DataRecord/interface/SiPixelQualityFromDbRcd.h"
0025 #include "CondFormats/SiPixelObjects/interface/CablingPathToDetUnit.h"
0026 #include "CondFormats/SiPixelObjects/interface/PixelROC.h"
0027 #include "CondFormats/SiPixelObjects/interface/SiPixelFEDChannelContainer.h"
0028 #include "CondFormats/SiPixelObjects/interface/SiPixelFedCablingMap.h"
0029 #include "CondFormats/SiPixelObjects/interface/SiPixelFedCablingTree.h"
0030 #include "CondFormats/SiPixelObjects/interface/SiPixelQuality.h"
0031 #include "DataFormats/Luminosity/interface/LumiInfo.h"
0032 #include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
0033 #include "FWCore/Framework/interface/ESWatcher.h"
0034 #include "FWCore/Framework/interface/Event.h"
0035 #include "FWCore/Framework/interface/Frameworkfwd.h"
0036 #include "FWCore/Framework/interface/MakerMacros.h"
0037 #include "FWCore/Framework/interface/one/EDAnalyzer.h"
0038 #include "FWCore/ParameterSet/interface/FileInPath.h"
0039 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0040 #include "FWCore/ServiceRegistry/interface/Service.h"
0041 #include "FWCore/Utilities/interface/InputTag.h"
0042 #include "Geometry/Records/interface/TrackerTopologyRcd.h"
0043 
0044 // system includes
0045 #include <iostream>
0046 #include <fstream>  // std::ifstream
0047 #include <memory>
0048 
0049 // ROOT includes
0050 #include "TH2.h"
0051 #include "TCanvas.h"
0052 
0053 namespace payloadPlotting {
0054 
0055   /*--------------------------------------------------------------------*/
0056   std::vector<std::tuple<int, int, int>> maskedBarrelRocsToBins(
0057       int layer, int ladder, int module, std::bitset<16> bad_rocs, bool isFlipped)
0058   /*--------------------------------------------------------------------*/
0059   {
0060     std::vector<std::tuple<int, int, int>> rocsToMask;
0061 
0062     int nlad_list[4] = {6, 14, 22, 32};
0063     int nlad = nlad_list[layer - 1];
0064 
0065     int start_x = module > 0 ? ((module + 4) * 8) + 1 : ((4 - (std::abs(module))) * 8) + 1;
0066     int start_y = ladder > 0 ? ((ladder + nlad) * 2) + 1 : ((nlad - (std::abs(ladder))) * 2) + 1;
0067 
0068     int roc0_x = ((layer == 1) || (layer > 1 && module > 0)) ? start_x + 7 : start_x;
0069     int roc0_y = start_y - 1;
0070 
0071     size_t idx = 0;
0072     while (idx < bad_rocs.size()) {
0073       if (bad_rocs.test(idx)) {
0074         int roc_x(0), roc_y(0);
0075 
0076         if ((layer == 1) || (layer > 1 && module > 0)) {
0077           if (!isFlipped) {
0078             roc_x = idx < 8 ? roc0_x - idx : (start_x - 8) + idx;
0079             roc_y = idx < 8 ? roc0_y + 1 : roc0_y + 2;
0080           } else {
0081             roc_x = idx < 8 ? roc0_x - idx : (start_x - 8) + idx;
0082             roc_y = idx < 8 ? roc0_y + 2 : roc0_y + 1;
0083           }
0084         } else {
0085           if (!isFlipped) {
0086             roc_x = idx < 8 ? roc0_x + idx : (roc0_x + 7) - (idx - 8);
0087             roc_y = idx < 8 ? roc0_y + 1 : roc0_y + 2;
0088           } else {
0089             roc_x = idx < 8 ? roc0_x + idx : (roc0_x + 7) - (idx - 8);
0090             roc_y = idx < 8 ? roc0_y + 2 : roc0_y + 1;
0091           }
0092         }
0093 
0094         edm::LogInfo("payloadPlotting") << bad_rocs << " : (idx)= " << idx << std::endl;
0095         edm::LogInfo("payloadPlotting") << " layer:  " << layer << std::endl;
0096         edm::LogInfo("payloadPlotting") << "module: " << module << " roc_x:" << roc_x << std::endl;
0097         edm::LogInfo("payloadPlotting") << "ladder: " << ladder << " roc_y:" << roc_y << std::endl;
0098         edm::LogInfo("payloadPlotting") << "=================================================================="
0099                                         << std::endl;
0100 
0101         rocsToMask.push_back(std::make_tuple(roc_x, roc_y, idx));
0102       }
0103       ++idx;
0104     }
0105     return rocsToMask;
0106   }
0107 
0108   /*--------------------------------------------------------------------*/
0109   std::vector<std::tuple<int, int, int>> maskedForwardRocsToBins(
0110       int ring, int blade, int panel, int disk, std::bitset<16> bad_rocs, bool isFlipped)
0111   /*--------------------------------------------------------------------*/
0112   {
0113     std::vector<std::tuple<int, int, int>> rocsToMask;
0114     int nybins_list[2] = {92, 140};
0115     int nybins = nybins_list[ring - 1];
0116 
0117     int start_x = disk > 0 ? ((disk + 3) * 8) + 1 : ((3 - (std::abs(disk))) * 8) + 1;
0118     int start_y = blade > 0 ? (nybins / 2) + (blade * 4) - (panel * 2) + 3
0119                             : ((nybins / 2) - (std::abs(blade) * 4) - panel * 2) + 3;
0120 
0121     int roc0_x = disk > 0 ? start_x + 7 : start_x;
0122     int roc0_y = start_y - 1;
0123 
0124     size_t idx = 0;
0125     while (idx < bad_rocs.size()) {
0126       if (bad_rocs.test(idx)) {
0127         int roc_x(0), roc_y(0);
0128 
0129         if (disk > 0) {
0130           if (!isFlipped) {
0131             roc_x = idx < 8 ? roc0_x - idx : (start_x - 8) + idx;
0132             roc_y = idx < 8 ? roc0_y + 1 : roc0_y + 2;
0133           } else {
0134             roc_x = idx < 8 ? roc0_x - idx : (start_x - 8) + idx;
0135             roc_y = idx < 8 ? roc0_y + 2 : roc0_y + 1;
0136           }
0137         } else {
0138           if (!isFlipped) {
0139             roc_x = idx < 8 ? roc0_x + idx : (roc0_x + 7) - (idx - 8);
0140             roc_y = idx < 8 ? roc0_y + 1 : roc0_y + 2;
0141           } else {
0142             roc_x = idx < 8 ? roc0_x + idx : (roc0_x + 7) - (idx - 8);
0143             roc_y = idx < 8 ? roc0_y + 2 : roc0_y + 1;
0144           }
0145         }
0146 
0147         edm::LogInfo("payloadPlotting") << bad_rocs << " : (idx)= " << idx << std::endl;
0148         edm::LogInfo("payloadPlotting") << " panel: " << panel << " isFlipped: " << isFlipped << std::endl;
0149         edm::LogInfo("payloadPlotting") << " disk:  " << disk << " roc_x:" << roc_x << std::endl;
0150         edm::LogInfo("payloadPlotting") << " blade: " << blade << " roc_y:" << roc_y << std::endl;
0151         edm::LogInfo("payloadPlotting") << "===============================" << std::endl;
0152 
0153         rocsToMask.push_back(std::make_tuple(roc_x, roc_y, idx));
0154       }
0155       ++idx;
0156     }
0157     return rocsToMask;
0158   }
0159 }  // namespace payloadPlotting
0160 
0161 //
0162 // class declaration
0163 //
0164 
0165 class SiPixelQualityPlotter : public edm::one::EDAnalyzer<edm::one::SharedResources> {
0166 public:
0167   explicit SiPixelQualityPlotter(const edm::ParameterSet&);
0168   ~SiPixelQualityPlotter() override;
0169 
0170   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0171   void CMS_lumi(TPad* pad, float lumi);
0172 
0173 private:
0174   void beginJob() override;
0175   void analyze(const edm::Event&, const edm::EventSetup&) override;
0176   void endJob() override;
0177 
0178   // ----------member data ---------------------------
0179   const edm::ESGetToken<TrackerTopology, TrackerTopologyRcd> topoEsToken_;
0180   const edm::ESGetToken<SiPixelQuality, SiPixelQualityFromDbRcd> qualEsToken_;
0181 
0182   const bool useLogScale_;
0183   const bool addLumiInfo_;
0184   const std::string analyzedTag_;
0185   const unsigned int lastRun_;
0186 
0187   const edm::InputTag lumiInputTag_;
0188   const edm::EDGetTokenT<LumiInfo> lumiToken_;
0189 
0190   int IOVcount_;
0191   edm::ESWatcher<SiPixelQualityFromDbRcd> SiPixelQualityWatcher_;
0192 
0193   float totalLumi_;
0194   float lumiSinceLastReset_;
0195   cond::Time_t lastIOVtime_;
0196 
0197   // actual histograms to fill
0198   static const int n_layers = 4;
0199   std::array<TH2D*, n_layers> h_bpix_occ;
0200 
0201   static const int n_rings = 2;
0202   std::array<TH2D*, n_rings> h_fpix_occ;
0203 
0204   // cached payload
0205   std::map<uint32_t, std::bitset<16>> cachedPayload_;
0206 };
0207 
0208 //
0209 // constructors and destructor
0210 //
0211 SiPixelQualityPlotter::SiPixelQualityPlotter(const edm::ParameterSet& iConfig)
0212     : topoEsToken_(esConsumes()),
0213       qualEsToken_(esConsumes()),
0214       useLogScale_(iConfig.getParameter<bool>("useLogScale")),
0215       addLumiInfo_(iConfig.getParameter<bool>("addLumiInfo")),
0216       analyzedTag_(iConfig.getParameter<std::string>("analyzedTag")),
0217       lastRun_(iConfig.getUntrackedParameter<unsigned int>("maxRun", 999999)),
0218       lumiInputTag_(iConfig.getUntrackedParameter<edm::InputTag>("lumiInputTag")),
0219       lumiToken_(consumes<LumiInfo>(lumiInputTag_)) {
0220   // initialize the counters
0221 
0222   IOVcount_ = 0;
0223   totalLumi_ = 0.f;
0224   lumiSinceLastReset_ = 0.f;
0225   lastIOVtime_ = 0;
0226 
0227   // ---------------------    BOOK HISTOGRAMS
0228   // BPIX
0229   int nlad_list[n_layers] = {6, 14, 22, 32};
0230   int divide_roc = 1;
0231 
0232   for (unsigned int lay = 1; lay <= n_layers; lay++) {
0233     int nlad = nlad_list[lay - 1];
0234 
0235     std::string name = "occ_Layer_" + std::to_string(lay);
0236     std::string title = "; BPix Layer " + std::to_string(lay) + " Module # ; BPix Layer " + std::to_string(lay) +
0237                         " Ladder # ; fraction of bad luminosity per component (%)";
0238     h_bpix_occ[lay - 1] = new TH2D(
0239         name.c_str(), title.c_str(), 72 * divide_roc, -4.5, 4.5, (nlad * 4 + 2) * divide_roc, -nlad - 0.5, nlad + 0.5);
0240   }
0241 
0242   // FPIX
0243   for (unsigned int ring = 1; ring <= n_rings; ring++) {
0244     int n = ring == 1 ? 92 : 140;
0245     float y = ring == 1 ? 11.5 : 17.5;
0246     std::string name = "occ_ring_" + std::to_string(ring);
0247     std::string title = "; FPix Ring " + std::to_string(ring) + " Disk # ; FPix Ring " + std::to_string(ring) +
0248                         " Blade/Panel # ; fraction of bad luminosity per component (%)";
0249 
0250     h_fpix_occ[ring - 1] = new TH2D(name.c_str(), title.c_str(), 56 * divide_roc, -3.5, 3.5, n * divide_roc, -y, y);
0251   }
0252 }
0253 
0254 SiPixelQualityPlotter::~SiPixelQualityPlotter() {
0255   // delete the histograms
0256   for (unsigned int lay = 1; lay <= n_layers; lay++) {
0257     delete h_bpix_occ[lay - 1];
0258   }
0259 
0260   for (unsigned int ring = 1; ring <= n_rings; ring++) {
0261     delete h_fpix_occ[ring - 1];
0262   }
0263 }
0264 
0265 //
0266 // member functions
0267 //
0268 
0269 // ------------ method called for each event  ------------
0270 void SiPixelQualityPlotter::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) {
0271   using namespace edm;
0272 
0273   unsigned int RunNumber_ = iEvent.eventAuxiliary().run();
0274   unsigned int LuminosityBlockNumber_ = iEvent.eventAuxiliary().luminosityBlock();
0275 
0276   cond::UnpackedTime localtime = std::make_pair(RunNumber_, LuminosityBlockNumber_);
0277   cond::Time_t packedtime = cond::time::pack(localtime);
0278 
0279   bool hasQualityIOV = SiPixelQualityWatcher_.check(iSetup);
0280 
0281   const auto& m_trackerTopo = iSetup.getData(topoEsToken_);
0282 
0283   if (hasQualityIOV || RunNumber_ > lastRun_) {
0284     IOVcount_++;
0285     lastIOVtime_ = packedtime;
0286 
0287     edm::LogVerbatim("SiPixelQualityPlotter")
0288         << "New IOV, Run: " << RunNumber_ << " LS:" << LuminosityBlockNumber_ << std::endl;
0289     edm::LogVerbatim("SiPixelQualityPlotter")
0290         << "Accumulated Luminosity: " << lumiSinceLastReset_ << " | Total Luminosity: " << totalLumi_ << std::endl;
0291 
0292     for (const auto [mod, payload] : cachedPayload_) {
0293       int subid = DetId(mod).subdetId();
0294       if (subid == PixelSubdetector::PixelBarrel) {
0295         auto layer = m_trackerTopo.pxbLayer(DetId(mod));
0296         auto s_ladder = SiPixelPI::signed_ladder(DetId(mod), m_trackerTopo, true);
0297         auto s_module = SiPixelPI::signed_module(DetId(mod), m_trackerTopo, true);
0298 
0299         bool isFlipped = !SiPixelPI::isBPixOuterLadder(DetId(mod), m_trackerTopo, false);
0300         if ((layer > 1 && s_module < 0))
0301           isFlipped = !isFlipped;
0302 
0303         auto ladder = m_trackerTopo.pxbLadder(DetId(mod));
0304         auto module = m_trackerTopo.pxbModule(DetId(mod));
0305         LogDebug("SiPixelQualityPlotter")
0306             << "layer:" << layer << " ladder:" << ladder << " module:" << module << " signed ladder: " << s_ladder
0307             << " signed module: " << s_module << std::endl;
0308 
0309         auto bpix_rocsToMask = payloadPlotting::maskedBarrelRocsToBins(layer, s_ladder, s_module, payload, isFlipped);
0310         for (const auto& bin : bpix_rocsToMask) {
0311           double x = h_bpix_occ[layer - 1]->GetXaxis()->GetBinCenter(std::get<0>(bin));
0312           double y = h_bpix_occ[layer - 1]->GetYaxis()->GetBinCenter(std::get<1>(bin));
0313           h_bpix_occ[layer - 1]->Fill(x, y, lumiSinceLastReset_);
0314         }
0315       } else if (subid == PixelSubdetector::PixelEndcap) {
0316         auto ring = SiPixelPI::ring(DetId(mod), m_trackerTopo, true);
0317         auto s_blade = SiPixelPI::signed_blade(DetId(mod), m_trackerTopo, true);
0318         auto s_disk = SiPixelPI::signed_disk(DetId(mod), m_trackerTopo, true);
0319         auto s_blade_panel = SiPixelPI::signed_blade_panel(DetId(mod), m_trackerTopo, true);
0320         auto panel = m_trackerTopo.pxfPanel(mod);
0321 
0322         bool isFlipped = (s_disk > 0) ? (panel == 1) : (panel == 2);
0323 
0324         LogDebug("SiPixelQualityPlotter")
0325             << "ring:" << ring << " blade: " << s_blade << " panel: " << panel
0326             << " signed blade/panel: " << s_blade_panel << " disk: " << s_disk << std::endl;
0327 
0328         auto fpix_rocsToMask =
0329             payloadPlotting::maskedForwardRocsToBins(ring, s_blade, panel, s_disk, payload, isFlipped);
0330         for (const auto& bin : fpix_rocsToMask) {
0331           double x = h_fpix_occ[ring - 1]->GetXaxis()->GetBinCenter(std::get<0>(bin));
0332           double y = h_fpix_occ[ring - 1]->GetYaxis()->GetBinCenter(std::get<1>(bin));
0333           h_fpix_occ[ring - 1]->Fill(x, y, lumiSinceLastReset_);
0334         }
0335       } else {
0336         throw cms::Exception("LogicError") << "Unknown Pixel SubDet ID " << std::endl;
0337       }
0338     }
0339 
0340     // clear the chached payload from memory
0341     cachedPayload_.clear();
0342 
0343     //Retrieve the pixel quality from conditions
0344     const SiPixelQuality* siPixelQuality_ = &iSetup.getData(qualEsToken_);
0345 
0346     // cache the new payload
0347     auto theDisabledModules = siPixelQuality_->getBadComponentList();
0348     for (const auto& mod : theDisabledModules) {
0349       int coded_badRocs = mod.BadRocs;
0350       std::bitset<16> bad_rocs(coded_badRocs);
0351       // cache the payload
0352       cachedPayload_.insert(std::make_pair(mod.DetID, bad_rocs));
0353     }
0354     // reset the luminosity count to zero
0355     lumiSinceLastReset_ = 0;
0356   }  // if there has been a new IOV
0357 
0358   if (RunNumber_ > lastRun_)
0359     return;
0360 
0361   // retrieve the luminosity
0362   const LumiInfo& lumi = iEvent.get(lumiToken_);
0363   totalLumi_ += (lumi.integLuminosity() * 1e-9);           // convert /ub to /fb
0364   lumiSinceLastReset_ += (lumi.integLuminosity() * 1e-9);  // convert /ub to /fb
0365 }
0366 
0367 // ------------ method called once each job just before starting event loop  ------------
0368 void SiPixelQualityPlotter::beginJob() {
0369   // please remove this method if not needed
0370 }
0371 
0372 // ------------ method called once each job just after ending the event loop  ------------
0373 void SiPixelQualityPlotter::endJob() {
0374   cond::UnpackedTime unpackedtime = cond::time::unpack(lastIOVtime_);
0375   edm::LogVerbatim("SiPixelQualityPlotter")
0376       << "\n=============================================\n"
0377       << "Last Analyzed LS: " << unpackedtime.first << "," << unpackedtime.second << std::endl;
0378   edm::LogVerbatim("SiPixelQualityPlotter") << "A total of " << IOVcount_ << " IOVs have been analyzed!" << std::endl;
0379 
0380   gStyle->SetOptStat(0);
0381   //=========================
0382   std::vector<TCanvas*> vCanvasBarrel(n_layers);
0383   TCanvas canvasB("SummaryBarrel", "SummaryBarrel", 1400, 1200);
0384   canvasB.Divide(2, 2);
0385   for (unsigned int i = 1; i <= n_layers; i++) {
0386     canvasB.cd(i)->SetTopMargin(0.06);
0387     canvasB.cd(i)->SetBottomMargin(0.11);
0388     canvasB.cd(i)->SetLeftMargin(0.12);
0389     canvasB.cd(i)->SetRightMargin(0.16);
0390     vCanvasBarrel[i - 1] = new TCanvas(Form("Layer_%i", i), Form("Layer_%i", i), 700, 600);
0391     vCanvasBarrel[i - 1]->cd()->SetTopMargin(0.08);
0392     vCanvasBarrel[i - 1]->cd()->SetBottomMargin(0.11);
0393     vCanvasBarrel[i - 1]->cd()->SetLeftMargin(0.12);
0394     vCanvasBarrel[i - 1]->cd()->SetRightMargin(0.16);
0395   }
0396 
0397   for (unsigned int lay = 1; lay <= n_layers; lay++) {
0398     h_bpix_occ[lay - 1]->Scale((100. / totalLumi_));
0399     SiPixelPI::makeNicePlotStyle(h_bpix_occ[lay - 1]);
0400     h_bpix_occ[lay - 1]->GetYaxis()->SetTitleOffset(1.2);
0401     h_bpix_occ[lay - 1]->GetZaxis()->SetTitleOffset(1.3);
0402     h_bpix_occ[lay - 1]->GetZaxis()->SetTitleSize(0.042);
0403     h_bpix_occ[lay - 1]->GetZaxis()->CenterTitle();
0404 
0405     canvasB.cd(lay)->Modified();
0406     SiPixelPI::dress_occup_plot(canvasB, h_bpix_occ[lay - 1], lay, 0, 1, true, true, true);
0407 
0408     if (useLogScale_) {
0409       canvasB.cd(lay)->SetLogz();
0410     }
0411     if (addLumiInfo_) {
0412       TPad* current_pad = static_cast<TPad*>(canvasB.cd(lay));
0413       CMS_lumi(current_pad, totalLumi_);
0414     }
0415 
0416     vCanvasBarrel[lay - 1]->cd()->Modified();
0417     SiPixelPI::dress_occup_plot(*vCanvasBarrel[lay - 1], h_bpix_occ[lay - 1], lay, 0, 1, true, true, true);
0418     if (useLogScale_) {
0419       vCanvasBarrel[lay - 1]->cd()->SetLogz();
0420     }
0421     if (addLumiInfo_) {
0422       TPad* current_pad = static_cast<TPad*>(vCanvasBarrel[lay - 1]->cd());
0423       CMS_lumi(current_pad, totalLumi_);
0424     }
0425   }
0426 
0427   for (unsigned int lay = 1; lay <= n_layers; lay++) {
0428     vCanvasBarrel[lay - 1]->SaveAs(("Barrel_L" + std::to_string(lay) + "_" + analyzedTag_ + ".png").c_str());
0429     vCanvasBarrel[lay - 1]->SaveAs(("Barrel_L" + std::to_string(lay) + "_" + analyzedTag_ + ".pdf").c_str());
0430   }
0431 
0432   canvasB.SaveAs(("SummaryBarrel_" + analyzedTag_ + ".png").c_str());
0433   canvasB.SaveAs(("SummaryBarrel_" + analyzedTag_ + ".pdf").c_str());
0434 
0435   //=========================
0436   std::vector<TCanvas*> vCanvasForward(2);
0437   TCanvas canvasF("SummaryForward", "SummaryForward", 1400, 600);
0438   canvasF.Divide(2, 1);
0439   for (unsigned int i = 1; i <= n_rings; i++) {
0440     canvasF.cd(i)->SetTopMargin(0.06);
0441     canvasF.cd(i)->SetBottomMargin(0.11);
0442     canvasF.cd(i)->SetLeftMargin(0.12);
0443     canvasF.cd(i)->SetRightMargin(0.16);
0444     vCanvasForward[i - 1] = new TCanvas(Form("Ring_%i", i), Form("Ring_%i", i), 700, 600);
0445     vCanvasForward[i - 1]->cd()->SetTopMargin(0.08);
0446     vCanvasForward[i - 1]->cd()->SetBottomMargin(0.11);
0447     vCanvasForward[i - 1]->cd()->SetLeftMargin(0.12);
0448     vCanvasForward[i - 1]->cd()->SetRightMargin(0.16);
0449   }
0450 
0451   for (unsigned int ring = 1; ring <= n_rings; ring++) {
0452     h_fpix_occ[ring - 1]->Scale((100. / totalLumi_));
0453     SiPixelPI::makeNicePlotStyle(h_fpix_occ[ring - 1]);
0454     h_fpix_occ[ring - 1]->GetYaxis()->SetTitleOffset(1.2);
0455     h_fpix_occ[ring - 1]->GetZaxis()->SetTitleOffset(1.3);
0456     h_fpix_occ[ring - 1]->GetZaxis()->SetTitleSize(0.042);
0457     h_fpix_occ[ring - 1]->GetZaxis()->CenterTitle();
0458 
0459     canvasF.cd(ring)->Modified();
0460     SiPixelPI::dress_occup_plot(canvasF, h_fpix_occ[ring - 1], 0, ring, 1, true, true, true);
0461     if (useLogScale_) {
0462       canvasF.cd(ring)->SetLogz();
0463     }
0464     if (addLumiInfo_) {
0465       TPad* current_pad = static_cast<TPad*>(canvasF.cd(ring));
0466       CMS_lumi(current_pad, totalLumi_);
0467     }
0468 
0469     vCanvasForward[ring - 1]->cd()->Modified();
0470     SiPixelPI::dress_occup_plot(*vCanvasForward[ring - 1], h_fpix_occ[ring - 1], 0, ring, 1, true, true, true);
0471 
0472     if (useLogScale_) {
0473       vCanvasForward[ring - 1]->cd()->SetLogz();
0474     }
0475     if (addLumiInfo_) {
0476       TPad* current_pad = static_cast<TPad*>(vCanvasForward[ring - 1]->cd());
0477       CMS_lumi(current_pad, totalLumi_);
0478     }
0479   }
0480 
0481   for (unsigned int ring = 1; ring <= n_rings; ring++) {
0482     vCanvasForward[ring - 1]->SaveAs(("Forward_R" + std::to_string(ring) + "_" + analyzedTag_ + ".png").c_str());
0483     vCanvasForward[ring - 1]->SaveAs(("Forward_R" + std::to_string(ring) + "_" + analyzedTag_ + ".pdf").c_str());
0484   }
0485 
0486   canvasF.SaveAs(("SummaryForward_" + analyzedTag_ + ".png").c_str());
0487   canvasF.SaveAs(("SummaryForward_" + analyzedTag_ + ".pdf").c_str());
0488 }
0489 
0490 // ------------ purely graphics method to embellish plots  ------------
0491 void SiPixelQualityPlotter::CMS_lumi(TPad* pad, float lumi) {
0492   auto ltx = TLatex();
0493   ltx.SetTextColor(1);
0494   ltx.SetTextSize(0.045);
0495   ltx.SetTextAlign(11);
0496   char str[200];
0497   sprintf(str, "#font[42]{L = %.3f fb^{-1}}", lumi);
0498   ltx.DrawLatexNDC(gPad->GetLeftMargin(), 1 - gPad->GetTopMargin() + 0.01, str);
0499 }
0500 
0501 // ------------ method fills 'descriptions' with the allowed parameters for the module  ------------
0502 void SiPixelQualityPlotter::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0503   edm::ParameterSetDescription desc;
0504   desc.add<bool>("useLogScale", false);
0505   desc.add<bool>("addLumiInfo", true);
0506   desc.add<std::string>("analyzedTag", "");
0507   desc.addUntracked<unsigned int>("maxRun", 999999);
0508   desc.addUntracked<edm::InputTag>("lumiInputTag", edm::InputTag(""));
0509   descriptions.add("siPixelQualityPlotter", desc);
0510 }
0511 
0512 //define this as a plug-in
0513 DEFINE_FWK_MODULE(SiPixelQualityPlotter);