Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-09-16 03:23:33

0001 #ifndef CONDCORE_SIPIXELPLUGINS_SIPIXELTEMPLATEHELPER_H
0002 #define CONDCORE_SIPIXELPLUGINS_SIPIXELTEMPLATEHELPER_H
0003 
0004 #include "CondCore/Utilities/interface/PayloadInspectorModule.h"
0005 #include "CondCore/Utilities/interface/PayloadInspector.h"
0006 #include "CondCore/CondDB/interface/Time.h"
0007 #include "CondCore/SiPixelPlugins/interface/SiPixelPayloadInspectorHelper.h"
0008 #include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h"
0009 #include "CondFormats/SiPixelObjects/interface/SiPixelTemplateDBObject.h"
0010 #include "CondFormats/SiPixelObjects/interface/SiPixelGenErrorDBObject.h"
0011 #include "CondFormats/SiPixelTransient/interface/SiPixelTemplate.h"
0012 #include "DQM/TrackerRemapper/interface/Phase1PixelMaps.h"
0013 #include "DQM/TrackerRemapper/interface/Phase1PixelSummaryMap.h"
0014 
0015 #include <type_traits>
0016 #include <memory>
0017 #include <sstream>
0018 #include <fmt/printf.h>
0019 #include <boost/range/adaptor/indexed.hpp>
0020 
0021 // include ROOT
0022 #include "TH2F.h"
0023 #include "TH1F.h"
0024 #include "TLegend.h"
0025 #include "TCanvas.h"
0026 #include "TLine.h"
0027 #include "TStyle.h"
0028 #include "TLatex.h"
0029 #include "TPave.h"
0030 #include "TPaveStats.h"
0031 #include "TGaxis.h"
0032 
0033 namespace templateHelper {
0034 
0035   //************************************************
0036   // Display of Template/GenError Titles
0037   // *************************************************/
0038   template <class PayloadType, class StoreType, class TransientType>
0039   class SiPixelTitles_Display
0040       : public cond::payloadInspector::PlotImage<PayloadType, cond::payloadInspector::SINGLE_IOV> {
0041   public:
0042     SiPixelTitles_Display()
0043         : cond::payloadInspector::PlotImage<PayloadType, cond::payloadInspector::SINGLE_IOV>(
0044               "Table of SiPixelTemplate/GenError titles") {
0045       if constexpr (std::is_same_v<PayloadType, SiPixelGenErrorDBObject>) {
0046         isTemplate_ = false;
0047         label_ = "SiPixelGenErrorDBObject_PayloadInspector";
0048       } else {
0049         isTemplate_ = true;
0050         label_ = "SiPixelTemplateDBObject_PayloadInspector";
0051       }
0052     }
0053 
0054     bool fill() override {
0055       auto tag = cond::payloadInspector::PlotBase::getTag<0>();
0056       auto iov = tag.iovs.front();
0057       auto tagname = tag.name;
0058       std::vector<StoreType> thePixelTemp_;
0059       std::shared_ptr<PayloadType> payload = this->fetchPayload(std::get<1>(iov));
0060 
0061       std::string IOVsince = std::to_string(std::get<0>(iov));
0062 
0063       if (payload.get()) {
0064         if (!TransientType::pushfile(*payload, thePixelTemp_)) {
0065           throw cms::Exception(label_) << "\nERROR:" << (isTemplate_ ? "Templates" : "GenErrors")
0066                                        << " not filled correctly."
0067                                        << " Check the conditions. Using "
0068                                        << (isTemplate_ ? "SiPixelTemplateDBObject" : "SiPixelGenErrorDBObject")
0069                                        << " version " << payload->version() << "\n\n";
0070         }
0071 
0072         unsigned int mapsize = thePixelTemp_.size();
0073         float pitch = 1. / (mapsize * 1.1);
0074 
0075         float y, x1, x2;
0076         std::vector<float> y_x1, y_x2, y_line;
0077         std::vector<std::string> s_x1, s_x2, s_x3;
0078 
0079         // starting table at y=1.0 (top of the canvas)
0080         // first column is at 0.02, second column at 0.32 NDC
0081         y = 1.0;
0082         x1 = 0.02;
0083         x2 = x1 + 0.30;
0084 
0085         y -= pitch;
0086         y_x1.push_back(y);
0087         s_x1.push_back(Form("#scale[1.2]{%s}", (isTemplate_ ? "Template ID" : "GenError ID")));
0088         y_x2.push_back(y);
0089         s_x2.push_back(Form("#scale[1.2]{#color[4]{%s} in IOV: #color[4]{%s}}", tagname.c_str(), IOVsince.c_str()));
0090 
0091         y -= pitch / 2.;
0092         y_line.push_back(y);
0093 
0094         for (const auto& element : thePixelTemp_) {
0095           y -= pitch;
0096           y_x1.push_back(y);
0097           s_x1.push_back(std::to_string(element.head.ID));
0098 
0099           y_x2.push_back(y);
0100           s_x2.push_back(Form("#color[2]{%s}", element.head.title));
0101 
0102           y_line.push_back(y - (pitch / 2.));
0103         }
0104 
0105         const auto& c_title = fmt::sprintf("%s titles", (isTemplate_ ? "Template" : "GenError"));
0106         TCanvas canvas(c_title.c_str(), c_title.c_str(), 2000, std::max(y_x1.size(), y_x2.size()) * 40);
0107         TLatex l;
0108         // Draw the columns titles
0109         l.SetTextAlign(12);
0110 
0111         float newpitch = 1 / (std::max(y_x1.size(), y_x2.size()) * 1.1);
0112         float factor = newpitch / pitch;
0113         l.SetTextSize(newpitch - 0.002);
0114         canvas.cd();
0115         for (unsigned int i = 0; i < y_x1.size(); i++) {
0116           l.DrawLatexNDC(x1, 1 - (1 - y_x1[i]) * factor, s_x1[i].c_str());
0117         }
0118 
0119         for (unsigned int i = 0; i < y_x2.size(); i++) {
0120           l.DrawLatexNDC(x2, 1 - (1 - y_x2[i]) * factor, s_x2[i].c_str());
0121         }
0122 
0123         canvas.cd();
0124         canvas.Update();
0125 
0126         TLine lines[y_line.size()];
0127         unsigned int iL = 0;
0128         for (const auto& line : y_line) {
0129           lines[iL] = TLine(gPad->GetUxmin(), 1 - (1 - line) * factor, gPad->GetUxmax(), 1 - (1 - line) * factor);
0130           lines[iL].SetLineWidth(1);
0131           lines[iL].SetLineStyle(9);
0132           lines[iL].SetLineColor(2);
0133           lines[iL].Draw("same");
0134           iL++;
0135         }
0136 
0137         std::string fileName(this->m_imageFileName);
0138         canvas.SaveAs(fileName.c_str());
0139 
0140       }  // if payload.get()
0141       return true;
0142     }
0143 
0144   protected:
0145     bool isTemplate_;
0146     std::string label_;
0147   };
0148 
0149   /************************************************
0150   // header plotting
0151   *************************************************/
0152   template <class PayloadType, class StoreType, class TransientType>
0153   class SiPixelHeaderTable : public cond::payloadInspector::PlotImage<PayloadType, cond::payloadInspector::SINGLE_IOV> {
0154   public:
0155     SiPixelHeaderTable()
0156         : cond::payloadInspector::PlotImage<PayloadType, cond::payloadInspector::SINGLE_IOV>(
0157               "SiPixel CPE Conditions Header summary") {
0158       if constexpr (std::is_same_v<PayloadType, SiPixelGenErrorDBObject>) {
0159         isTemplate_ = false;
0160         label_ = "SiPixelGenErrorDBObject_PayloadInspector";
0161       } else {
0162         isTemplate_ = true;
0163         label_ = "SiPixelTemplateDBObject_PayloadInspector";
0164       }
0165     }
0166 
0167     bool fill() override {
0168       gStyle->SetHistMinimumZero();  // will display zero as zero in the text map
0169       gStyle->SetPalette(kMint);     // for the ghost plot (colored BPix and FPix bins)
0170 
0171       auto tag = cond::payloadInspector::PlotBase::getTag<0>();
0172       auto iov = tag.iovs.front();
0173       auto tagname = tag.name;
0174       std::vector<StoreType> thePixelTemp_;
0175       std::shared_ptr<PayloadType> payload = this->fetchPayload(std::get<1>(iov));
0176 
0177       if (payload.get()) {
0178         if (!TransientType::pushfile(*payload, thePixelTemp_)) {
0179           throw cms::Exception(label_) << "\nERROR:" << (isTemplate_ ? "Templates" : "GenErrors")
0180                                        << " not filled correctly."
0181                                        << " Check the conditions. Using "
0182                                        << (isTemplate_ ? "SiPixelTemplateDBObject" : "SiPixelGenErrorDBObject")
0183                                        << payload->version() << "\n\n";
0184         }
0185 
0186         // store the map of ID / interesting quantities
0187         TransientType templ(thePixelTemp_);
0188         TCanvas canvas("Header Summary", "Header summary", 1400, 1000);
0189         canvas.cd();
0190 
0191         unsigned int tempSize = thePixelTemp_.size();
0192 
0193         canvas.SetTopMargin(0.07);
0194         canvas.SetBottomMargin(0.06);
0195         canvas.SetLeftMargin(0.17);
0196         canvas.SetRightMargin(0.03);
0197         canvas.Modified();
0198         canvas.SetGrid();
0199 
0200         auto h2_Header = std::make_unique<TH2F>("Header", ";;", tempSize, 0, tempSize, 12, 0., 12.);
0201         auto h2_ghost = std::make_unique<TH2F>("ghost", ";;", tempSize, 0, tempSize, 12, 0., 12.);
0202         h2_Header->SetStats(false);
0203         h2_ghost->SetStats(false);
0204 
0205         int tempVersion = -999;
0206 
0207         for (const auto& theTemp : thePixelTemp_ | boost::adaptors::indexed(1)) {
0208           auto tempValue = theTemp.value();
0209           auto idx = theTemp.index();
0210           float uH = -99.;
0211           if (tempValue.head.Bfield != 0.) {
0212             uH = roundoff(tempValue.head.lorxwidth / tempValue.head.zsize / tempValue.head.Bfield, 4);
0213           }
0214 
0215           // clang-format off
0216           h2_Header->SetBinContent(idx, 12, tempValue.head.ID);     //!< template ID number
0217           h2_Header->SetBinContent(idx, 11, tempValue.head.Bfield); //!< Bfield in Tesla
0218           h2_Header->SetBinContent(idx, 10, uH);                    //!< hall mobility
0219           h2_Header->SetBinContent(idx, 9, tempValue.head.xsize);   //!< pixel size (for future use in upgraded geometry)
0220           h2_Header->SetBinContent(idx, 8, tempValue.head.ysize);   //!< pixel size (for future use in upgraded geometry)
0221           h2_Header->SetBinContent(idx, 7, tempValue.head.zsize);   //!< pixel size (for future use in upgraded geometry)
0222           h2_Header->SetBinContent(idx, 6, tempValue.head.NTy);     //!< number of Template y entries
0223           h2_Header->SetBinContent(idx, 5, tempValue.head.NTyx);    //!< number of Template y-slices of x entries
0224           h2_Header->SetBinContent(idx, 4, tempValue.head.NTxx);    //!< number of Template x-entries in each slice
0225           h2_Header->SetBinContent(idx, 3, tempValue.head.Dtype);   //!< detector type (0=BPix, 1=FPix)
0226           h2_Header->SetBinContent(idx, 2, tempValue.head.qscale);  //!< Charge scaling to match cmssw and pixelav
0227           h2_Header->SetBinContent(idx, 1, tempValue.head.Vbias);   //!< detector bias potential in Volts
0228           // clang-format on
0229 
0230           h2_Header->GetYaxis()->SetBinLabel(12, (isTemplate_ ? "TemplateID" : "GenErrorID"));
0231           h2_Header->GetYaxis()->SetBinLabel(11, "B-field [T]");
0232           h2_Header->GetYaxis()->SetBinLabel(10, "#mu_{H} [1/T]");
0233           h2_Header->GetYaxis()->SetBinLabel(9, "x-size [#mum]");
0234           h2_Header->GetYaxis()->SetBinLabel(8, "y-size [#mum]");
0235           h2_Header->GetYaxis()->SetBinLabel(7, "z-size [#mum]");
0236           h2_Header->GetYaxis()->SetBinLabel(6, "NTy");
0237           h2_Header->GetYaxis()->SetBinLabel(5, "NTyx");
0238           h2_Header->GetYaxis()->SetBinLabel(4, "NTxx");
0239           h2_Header->GetYaxis()->SetBinLabel(3, "DetectorType");
0240           h2_Header->GetYaxis()->SetBinLabel(2, "qScale");
0241           h2_Header->GetYaxis()->SetBinLabel(1, "VBias [V]");
0242           h2_Header->GetXaxis()->SetBinLabel(idx, "");
0243 
0244           for (unsigned int iy = 1; iy <= 12; iy++) {
0245             // Some of the Phase-2 templates have DType = 0 for all partitions (TBPX, TEPX, TFPX)
0246             // so they are distinguished by the uH strength value (<0).
0247             // To avoid changing the behaviour of 0T payload (uH=-99) that case is treated separately
0248             if (tempValue.head.Dtype != 0 || (uH < 0 && uH > -99)) {
0249               h2_ghost->SetBinContent(idx, iy, 1);
0250             } else {
0251               h2_ghost->SetBinContent(idx, iy, -1);
0252             }
0253             h2_ghost->GetYaxis()->SetBinLabel(iy, h2_Header->GetYaxis()->GetBinLabel(iy));
0254             h2_ghost->GetXaxis()->SetBinLabel(idx, "");
0255           }
0256 
0257           if (tempValue.head.templ_version != tempVersion) {
0258             tempVersion = tempValue.head.templ_version;
0259           }
0260         }
0261 
0262         h2_Header->GetXaxis()->LabelsOption("h");
0263         h2_Header->GetXaxis()->SetNdivisions(500 + tempSize, false);
0264         h2_Header->GetYaxis()->SetLabelSize(0.05);
0265         h2_Header->SetMarkerSize(1.5);
0266 
0267         h2_ghost->GetXaxis()->LabelsOption("h");
0268         h2_ghost->GetXaxis()->SetNdivisions(500 + tempSize, false);
0269         h2_ghost->GetYaxis()->SetLabelSize(0.05);
0270 
0271         canvas.cd();
0272         h2_ghost->Draw("col");
0273         h2_Header->Draw("TEXTsame");
0274 
0275         TPaveText ksPt(0, 0, 0.88, 0.04, "NDC");
0276         ksPt.SetBorderSize(0);
0277         ksPt.SetFillColor(0);
0278         const char* textToAdd = Form("%s Version: #color[2]{%i}. Payload hash: #color[2]{%s}",
0279                                      (isTemplate_ ? "Template" : "GenError"),
0280                                      tempVersion,
0281                                      (std::get<1>(iov)).c_str());
0282         ksPt.AddText(textToAdd);
0283         ksPt.Draw();
0284 
0285         auto ltx = TLatex();
0286         ltx.SetTextFont(62);
0287         ltx.SetTextSize(0.040);
0288         ltx.SetTextAlign(11);
0289         ltx.DrawLatexNDC(
0290             gPad->GetLeftMargin(),
0291             1 - gPad->GetTopMargin() + 0.01,
0292             ("#color[4]{" + tagname + "}, IOV: #color[4]{" + std::to_string(std::get<0>(iov)) + "}").c_str());
0293 
0294         std::string fileName(this->m_imageFileName);
0295         canvas.SaveAs(fileName.c_str());
0296       }
0297       return true;
0298     }
0299 
0300     float roundoff(float value, unsigned char prec) {
0301       float pow_10 = pow(10.0f, (float)prec);
0302       return round(value * pow_10) / pow_10;
0303     }
0304 
0305   protected:
0306     bool isTemplate_;
0307     std::string label_;
0308   };
0309 
0310   //***********************************************
0311   // TH2Poly Map of IDs
0312   //***********************************************/
0313   template <class PayloadType, SiPixelPI::DetType myType>
0314   class SiPixelIDs : public cond::payloadInspector::PlotImage<PayloadType, cond::payloadInspector::SINGLE_IOV> {
0315   public:
0316     SiPixelIDs()
0317         : cond::payloadInspector::PlotImage<PayloadType, cond::payloadInspector::SINGLE_IOV>(
0318               "SiPixelMap of Template / GenError ID Values") {
0319       if constexpr (std::is_same_v<PayloadType, SiPixelGenErrorDBObject>) {
0320         isTemplate_ = false;
0321         label_ = "SiPixelGenErrorDBObject_PayloadInspector";
0322       } else {
0323         isTemplate_ = true;
0324         label_ = "SiPixelTemplateDBObject_PayloadInspector";
0325       }
0326     }
0327 
0328     bool fill() override {
0329       gStyle->SetPalette(kRainBow);
0330 
0331       auto tag = cond::payloadInspector::PlotBase::getTag<0>();
0332       auto iov = tag.iovs.front();
0333       std::shared_ptr<PayloadType> payload = this->fetchPayload(std::get<1>(iov));
0334 
0335       std::string barrelName_ = fmt::sprintf("%sIDsBarrel", (isTemplate_ ? "template" : "genError"));
0336       std::string endcapName_ = fmt::sprintf("%sIDsForward", (isTemplate_ ? "template" : "genError"));
0337       std::string title_ = fmt::sprintf("%s IDs", (isTemplate_ ? "template" : "genError"));
0338 
0339       if (payload.get()) {
0340         // Book the TH2Poly
0341         Phase1PixelMaps theMaps("text");
0342         if (myType == SiPixelPI::t_barrel) {
0343           // book the barrel bins of the TH2Poly
0344           theMaps.bookBarrelHistograms(barrelName_, title_.c_str(), title_.c_str());
0345         } else if (myType == SiPixelPI::t_forward) {
0346           // book the forward bins of the TH2Poly
0347           theMaps.bookForwardHistograms(endcapName_, title_.c_str(), title_.c_str());
0348         }
0349 
0350         std::map<unsigned int, short> templMap;
0351         if constexpr (std::is_same_v<PayloadType, SiPixelGenErrorDBObject>) {
0352           templMap = payload->getGenErrorIDs();
0353         } else {
0354           templMap = payload->getTemplateIDs();
0355         }
0356 
0357         if (templMap.size() == SiPixelPI::phase0size || templMap.size() > SiPixelPI::phase1size) {
0358           edm::LogError(label_)
0359               << "There are " << templMap.size()
0360               << " DetIds in this payload. SiPixelIDs maps are not supported for non-Phase1 Pixel geometries !";
0361           TCanvas canvas("Canv", "Canv", 1200, 1000);
0362           SiPixelPI::displayNotSupported(canvas, templMap.size());
0363           std::string fileName(this->m_imageFileName);
0364           canvas.SaveAs(fileName.c_str());
0365           return false;
0366         } else {
0367           if (templMap.size() < SiPixelPI::phase1size) {
0368             edm::LogWarning(label_) << "\n ********* WARNING! ********* \n There are " << templMap.size()
0369                                     << " DetIds in this payload !"
0370                                     << "\n **************************** \n";
0371           }
0372         }
0373 
0374         /*
0375     std::vector<unsigned int> detids;
0376     std::transform(templMap.begin(),
0377                templMap.end(),
0378                std::back_inserter(detids),
0379                [](const std::map<unsigned int, short>::value_type& pair) { return pair.first; });
0380     */
0381 
0382         for (auto const& entry : templMap) {
0383           COUT << "DetID: " << entry.first << fmt::sprintf("%s ID ", (isTemplate_ ? "Template" : "GenError"))
0384                << entry.second << std::endl;
0385           auto detid = DetId(entry.first);
0386           if ((detid.subdetId() == PixelSubdetector::PixelBarrel) && (myType == SiPixelPI::t_barrel)) {
0387             theMaps.fillBarrelBin(barrelName_, entry.first, entry.second);
0388           } else if ((detid.subdetId() == PixelSubdetector::PixelEndcap) && (myType == SiPixelPI::t_forward)) {
0389             theMaps.fillForwardBin(endcapName_, entry.first, entry.second);
0390           }
0391         }
0392 
0393         theMaps.beautifyAllHistograms();
0394 
0395         TCanvas canvas("Canv", "Canv", (myType == SiPixelPI::t_barrel) ? 1200 : 1500, 1000);
0396         if (myType == SiPixelPI::t_barrel) {
0397           theMaps.drawBarrelMaps(barrelName_, canvas);
0398         } else if (myType == SiPixelPI::t_forward) {
0399           theMaps.drawForwardMaps(endcapName_, canvas);
0400         }
0401 
0402         canvas.cd();
0403 
0404         std::string fileName(this->m_imageFileName);
0405         canvas.SaveAs(fileName.c_str());
0406       }
0407       return true;
0408     }
0409 
0410   protected:
0411     bool isTemplate_;
0412     std::string label_;
0413   };
0414 
0415   /************************************************
0416    Full Pixel Tracker Map class
0417   *************************************************/
0418   template <class PayloadType, class StoreType, class TransientType>
0419   class SiPixelFullPixelIDMap
0420       : public cond::payloadInspector::PlotImage<PayloadType, cond::payloadInspector::SINGLE_IOV> {
0421   public:
0422     SiPixelFullPixelIDMap()
0423         : cond::payloadInspector::PlotImage<PayloadType, cond::payloadInspector::SINGLE_IOV>(
0424               "SiPixel CPE conditions Map of IDs") {
0425       if constexpr (std::is_same_v<PayloadType, SiPixelGenErrorDBObject>) {
0426         isTemplate_ = false;
0427         label_ = "SiPixelGenErrorDBObject_PayloadInspector";
0428       } else {
0429         isTemplate_ = true;
0430         label_ = "SiPixelTemplateDBObject_PayloadInspector";
0431       }
0432     }
0433 
0434     bool fill() override {
0435       gStyle->SetPalette(1);
0436       auto tag = cond::payloadInspector::PlotBase::getTag<0>();
0437       auto iov = tag.iovs.front();
0438       std::vector<StoreType> thePixelTemp_;
0439       std::shared_ptr<PayloadType> payload = this->fetchPayload(std::get<1>(iov));
0440 
0441       std::string payloadString = (isTemplate_ ? "Templates" : "GenErrors");
0442 
0443       if (payload.get()) {
0444         if (!TransientType::pushfile(*payload, thePixelTemp_)) {
0445           throw cms::Exception(label_) << "\nERROR: " << payloadString
0446                                        << " not filled correctly. Check the conditions. Using "
0447                                        << (isTemplate_ ? "SiPixelTemplateDBObject" : "SiPixelGenErrorDBObject")
0448                                        << payload->version() << "\n\n";
0449         }
0450 
0451         Phase1PixelSummaryMap fullMap("", fmt::sprintf("%s IDs", payloadString), fmt::sprintf("%s ID", payloadString));
0452         fullMap.createTrackerBaseMap();
0453 
0454         std::map<unsigned int, short> templMap;
0455         if constexpr (std::is_same_v<PayloadType, SiPixelGenErrorDBObject>) {
0456           templMap = payload->getGenErrorIDs();
0457         } else {
0458           templMap = payload->getTemplateIDs();
0459         }
0460 
0461         for (const auto& entry : templMap) {
0462           fullMap.fillTrackerMap(entry.first, entry.second);
0463         }
0464 
0465         if (templMap.size() == SiPixelPI::phase0size || templMap.size() > SiPixelPI::phase1size) {
0466           edm::LogError(label_)
0467               << "There are " << templMap.size()
0468               << " DetIds in this payload. SiPixelIDs maps are not supported for non-Phase1 Pixel geometries !";
0469           TCanvas canvas("Canv", "Canv", 1200, 1000);
0470           SiPixelPI::displayNotSupported(canvas, templMap.size());
0471           std::string fileName(this->m_imageFileName);
0472           canvas.SaveAs(fileName.c_str());
0473           return false;
0474         } else {
0475           if (templMap.size() < SiPixelPI::phase1size) {
0476             edm::LogWarning(label_) << "\n ********* WARNING! ********* \n There are " << templMap.size()
0477                                     << " DetIds in this payload !"
0478                                     << "\n **************************** \n";
0479           }
0480         }
0481 
0482         TCanvas canvas("Canv", "Canv", 3000, 2000);
0483         fullMap.printTrackerMap(canvas);
0484 
0485         //fmt::sprintf("#color[2]{%s, IOV %i}",tag.name,std::get<0>(iov));
0486 
0487         auto ltx = TLatex();
0488         ltx.SetTextFont(62);
0489         ltx.SetTextSize(0.025);
0490         ltx.SetTextAlign(11);
0491         ltx.DrawLatexNDC(
0492             gPad->GetLeftMargin() + 0.01,
0493             gPad->GetBottomMargin() + 0.01,
0494             ("#color[4]{" + tag.name + "}, IOV: #color[4]{" + std::to_string(std::get<0>(iov)) + "}").c_str());
0495 
0496         std::string fileName(this->m_imageFileName);
0497         canvas.SaveAs(fileName.c_str());
0498       }
0499       return true;
0500     }
0501 
0502   protected:
0503     bool isTemplate_;
0504     std::string label_;
0505   };
0506 
0507 }  // namespace templateHelper
0508 
0509 #endif