Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-03-08 02:25:55

0001 #ifndef CONDCORE_BEAMSPOTPLUGINS_BEAMSPOTPAYLOADINSPECTORHELPER_H
0002 #define CONDCORE_BEAMSPOTPLUGINS_BEAMSPOTPAYLOADINSPECTORHELPER_H
0003 
0004 // User includes
0005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0006 #include "CondCore/Utilities/interface/PayloadInspectorModule.h"
0007 #include "CondCore/Utilities/interface/PayloadInspector.h"
0008 #include "CondCore/CondDB/interface/Time.h"
0009 #include "CondFormats/BeamSpotObjects/interface/BeamSpotOnlineObjects.h"
0010 
0011 // system includes
0012 #include <fmt/printf.h>
0013 #include <memory>
0014 #include <sstream>
0015 
0016 // ROOT includes
0017 #include "TCanvas.h"
0018 #include "TStyle.h"
0019 #include "TH2F.h"
0020 #include "TLatex.h"
0021 
0022 //#define MMDEBUG  /* to make it verbose */
0023 
0024 namespace BeamSpotPI {
0025 
0026   inline std::pair<unsigned int, unsigned int> unpack(cond::Time_t since) {
0027     auto kLowMask = 0XFFFFFFFF;
0028     auto run = (since >> 32);
0029     auto lumi = (since & kLowMask);
0030     return std::make_pair(run, lumi);
0031   }
0032 
0033   enum parameters {
0034     X = 0,                // 0  regular BS methods
0035     Y = 1,                // 1
0036     Z = 2,                // 2
0037     sigmaX = 3,           // 3
0038     sigmaY = 4,           // 4
0039     sigmaZ = 5,           // 5
0040     dxdz = 6,             // 6
0041     dydz = 7,             // 7
0042     lastLumi = 8,         // 8  additional int's
0043     lastRun = 9,          // 9
0044     lastFill = 10,        // 10
0045     nTracks = 11,         // 11
0046     nPVs = 12,            // 12
0047     nUsedEvents = 13,     // 13
0048     maxPVs = 14,          // 14
0049     meanPV = 15,          // 15 additional float's
0050     meanErrorPV = 16,     // 16
0051     rmsPV = 17,           // 17
0052     rmsErrorPV = 18,      // 18
0053     creationTime = 19,    // 19 additional cond::Time_t
0054     startTimeStamp = 20,  // 20
0055     endTimeStamp = 21,    // 21
0056     startTime = 22,       // 22 additional std::string
0057     endTime = 23,         // 23
0058     lumiRange = 24,       // 24
0059     END_OF_TYPES = 25,
0060   };
0061 
0062   /************************************************/
0063   inline std::string getStringFromParamEnum(const parameters& parameter,
0064                                             const bool addUnits = false /*not used by default*/) {
0065     switch (parameter) {
0066       case X:
0067         return (addUnits ? "X [cm]" : "X");
0068       case Y:
0069         return (addUnits ? "Y [cm]" : "Y");
0070       case Z:
0071         return (addUnits ? "Z [cm]" : "Z");
0072       case sigmaX:
0073         return (addUnits ? "#sigma_{X} [cm]" : "sigmaX");
0074       case sigmaY:
0075         return (addUnits ? "#sigma_{Y} [cm]" : "sigmaY");
0076       case sigmaZ:
0077         return (addUnits ? "#sigma_{Z} [cm]" : "sigmaZ");
0078       case dxdz:
0079         return (addUnits ? "#frac{dX}{dZ} [rad]" : "dx/dz");
0080       case dydz:
0081         return (addUnits ? "#frac{dY}{dZ} [rad]" : "dy/dz");
0082       default:
0083         return "should never be here";
0084     }
0085   }
0086 
0087   /**
0088    * Helper class for operations on the Beam Spot Parameters
0089    * It's a simplified representation of the beamspot
0090    * data used as the underlying type for data transfers and comparisons
0091    */
0092   template <class PayloadType>
0093   class BSParamsHelper {
0094     typedef std::array<double, 8> bshelpdata;
0095 
0096   public:
0097     BSParamsHelper(const std::shared_ptr<PayloadType>& bs) {
0098       // fill in the central values
0099       m_values[0] = bs->x(), m_values[1] = bs->y(), m_values[2] = bs->z();
0100       m_values[3] = bs->beamWidthX(), m_values[4] = bs->beamWidthY(), m_values[5] = bs->sigmaZ();
0101       m_values[6] = bs->dxdz(), m_values[7] = bs->dydz();
0102 
0103       // fill in the errors
0104       m_errors[0] = bs->xError(), m_errors[1] = bs->yError(), m_errors[2] = bs->zError();
0105       m_errors[3] = bs->beamWidthXError(), m_errors[4] = bs->beamWidthYError(), m_errors[5] = bs->sigmaZError();
0106       m_errors[6] = bs->dxdzError(), m_errors[7] = bs->dydzError();
0107     }
0108 
0109     void printDebug(std::stringstream& ss) {
0110       ss << "Dumping BeamSpot parameters Data:" << std::endl;
0111       for (uint i = parameters::X; i <= parameters::dydz; i++) {
0112         parameters par = static_cast<parameters>(i);
0113         ss << getStringFromParamEnum(par) << " : " << m_values[i] << std::endl;
0114         ss << getStringFromParamEnum(par) << " error: " << m_errors[i] << std::endl;
0115         ss << std::endl;
0116       }
0117     }
0118 
0119     inline const bshelpdata centralValues() const { return m_values; }
0120     inline const bshelpdata errors() const { return m_errors; }
0121 
0122     // get the difference in values
0123     const bshelpdata diffCentralValues(const BSParamsHelper& bs2, const bool isPull = false) const {
0124       bshelpdata ret;
0125       for (uint i = parameters::X; i <= parameters::dydz; i++) {
0126         ret[i] = this->centralValues()[i] - bs2.centralValues()[i];
0127         if (isPull)
0128           (this->centralValues()[i] != 0.) ? ret[i] /= this->centralValues()[i] : 0.;
0129       }
0130       return ret;
0131     }
0132 
0133     // get the difference in errors
0134     const bshelpdata diffErrors(const BSParamsHelper& bs2, const bool isPull = false) const {
0135       bshelpdata ret;
0136       for (uint i = parameters::X; i <= parameters::dydz; i++) {
0137         ret[i] = this->errors()[i] - bs2.errors()[i];
0138         if (isPull)
0139           (this->errors()[i] != 0.) ? ret[i] /= this->errors()[i] : 0.;
0140       }
0141       return ret;
0142     }
0143 
0144   private:
0145     bshelpdata m_values; /* central values */
0146     bshelpdata m_errors; /* errors */
0147   };
0148 
0149   /************************************************
0150     template classes (history)
0151   *************************************************/
0152 
0153   template <parameters my_param, class PayloadType>
0154   class BeamSpot_history : public cond::payloadInspector::HistoryPlot<PayloadType, std::pair<double, double> > {
0155   public:
0156     BeamSpot_history()
0157         : cond::payloadInspector::HistoryPlot<PayloadType, std::pair<double, double> >(
0158               getStringFromParamEnum(my_param) + " vs run number", getStringFromParamEnum(my_param)) {}
0159 
0160     std::pair<double, double> getFromPayload(PayloadType& payload) override {
0161       auto ret = std::make_pair<double, double>(-9999., -9999.);
0162 
0163       switch (my_param) {
0164         case X:
0165           return std::make_pair<double, double>(payload.x(), payload.xError());
0166         case Y:
0167           return std::make_pair<double, double>(payload.y(), payload.yError());
0168         case Z:
0169           return std::make_pair<double, double>(payload.z(), payload.zError());
0170         case sigmaX:
0171           return std::make_pair<double, double>(payload.beamWidthX(), payload.beamWidthXError());
0172         case sigmaY:
0173           return std::make_pair<double, double>(payload.beamWidthY(), payload.beamWidthYError());
0174         case sigmaZ:
0175           return std::make_pair<double, double>(payload.sigmaZ(), payload.sigmaZError());
0176         case dxdz:
0177           return std::make_pair<double, double>(payload.dxdz(), payload.dxdzError());
0178         case dydz:
0179           return std::make_pair<double, double>(payload.dydz(), payload.dydzError());
0180         case END_OF_TYPES:
0181           return ret;
0182         default:
0183           return ret;
0184       }
0185     }
0186   };
0187 
0188   /************************************************
0189     template classes (run history)
0190    *************************************************/
0191 
0192   template <parameters my_param, class PayloadType>
0193   class BeamSpot_runhistory : public cond::payloadInspector::RunHistoryPlot<PayloadType, std::pair<double, double> > {
0194   public:
0195     BeamSpot_runhistory()
0196         : cond::payloadInspector::RunHistoryPlot<PayloadType, std::pair<double, double> >(
0197               getStringFromParamEnum(my_param) + " vs run number", getStringFromParamEnum(my_param)) {}
0198 
0199     std::pair<double, double> getFromPayload(PayloadType& payload) override {
0200       auto ret = std::make_pair<double, double>(-9999., -9999.);
0201 
0202       switch (my_param) {
0203         case X:
0204           return std::make_pair<double, double>(payload.x(), payload.xError());
0205         case Y:
0206           return std::make_pair<double, double>(payload.y(), payload.yError());
0207         case Z:
0208           return std::make_pair<double, double>(payload.z(), payload.zError());
0209         case sigmaX:
0210           return std::make_pair<double, double>(payload.beamWidthX(), payload.beamWidthXError());
0211         case sigmaY:
0212           return std::make_pair<double, double>(payload.beamWidthY(), payload.beamWidthYError());
0213         case sigmaZ:
0214           return std::make_pair<double, double>(payload.sigmaZ(), payload.sigmaZError());
0215         case dxdz:
0216           return std::make_pair<double, double>(payload.dxdz(), payload.dxdzError());
0217         case dydz:
0218           return std::make_pair<double, double>(payload.dydz(), payload.dydzError());
0219         case END_OF_TYPES:
0220           return ret;
0221         default:
0222           return ret;
0223       }
0224     }
0225   };
0226 
0227   /************************************************
0228     template classes (time history)
0229   *************************************************/
0230 
0231   template <parameters my_param, class PayloadType>
0232   class BeamSpot_timehistory : public cond::payloadInspector::TimeHistoryPlot<PayloadType, std::pair<double, double> > {
0233   public:
0234     BeamSpot_timehistory()
0235         : cond::payloadInspector::TimeHistoryPlot<PayloadType, std::pair<double, double> >(
0236               getStringFromParamEnum(my_param) + " vs time", getStringFromParamEnum(my_param)) {}
0237 
0238     std::pair<double, double> getFromPayload(PayloadType& payload) override {
0239       auto ret = std::make_pair<double, double>(-9999., -9999.);
0240 
0241       switch (my_param) {
0242         case X:
0243           return std::make_pair<double, double>(payload.x(), payload.xError());
0244         case Y:
0245           return std::make_pair<double, double>(payload.y(), payload.yError());
0246         case Z:
0247           return std::make_pair<double, double>(payload.z(), payload.zError());
0248         case sigmaX:
0249           return std::make_pair<double, double>(payload.beamWidthX(), payload.beamWidthXError());
0250         case sigmaY:
0251           return std::make_pair<double, double>(payload.beamWidthY(), payload.beamWidthYError());
0252         case sigmaZ:
0253           return std::make_pair<double, double>(payload.sigmaZ(), payload.sigmaZError());
0254         case dxdz:
0255           return std::make_pair<double, double>(payload.dxdz(), payload.dxdzError());
0256         case dydz:
0257           return std::make_pair<double, double>(payload.dydz(), payload.dydzError());
0258         case END_OF_TYPES:
0259           return ret;
0260         default:
0261           return ret;
0262       }
0263     }
0264   };
0265 
0266   /************************************************
0267     X-Y correlation plot
0268   *************************************************/
0269   template <class PayloadType>
0270   class xyCorrelation : public cond::payloadInspector::ScatterPlot<PayloadType, double, double> {
0271   public:
0272     xyCorrelation() : cond::payloadInspector::ScatterPlot<PayloadType, double, double>("BeamSpot x vs y", "x", "y") {}
0273 
0274     std::tuple<double, double> getFromPayload(PayloadType& payload) override {
0275       return std::make_tuple(payload.x(), payload.y());
0276     }
0277   };
0278 
0279   /************************************************
0280     Display of Beam Spot parameters
0281   *************************************************/
0282   template <class PayloadType>
0283   class DisplayParameters : public cond::payloadInspector::PlotImage<PayloadType, cond::payloadInspector::SINGLE_IOV> {
0284   public:
0285     DisplayParameters()
0286         : cond::payloadInspector::PlotImage<PayloadType, cond::payloadInspector::SINGLE_IOV>(
0287               "Display of BeamSpot parameters") {
0288       if constexpr (std::is_same_v<PayloadType, BeamSpotOnlineObjects>) {
0289         isOnline_ = true;
0290       } else {
0291         isOnline_ = false;
0292       }
0293     }
0294 
0295     bool fill() override {
0296       auto tag = cond::payloadInspector::PlotBase::getTag<0>();
0297       auto tagname = tag.name;
0298       auto iov = tag.iovs.front();
0299 
0300       gStyle->SetHistMinimumZero(kTRUE);
0301 
0302       m_payload = this->fetchPayload(std::get<1>(iov));
0303 
0304       TCanvas canvas("Beam Spot Parameters Summary", "BeamSpot Parameters summary", isOnline_ ? 1500 : 1000, 1000);
0305       if (isOnline_) {
0306         canvas.Divide(2, 1);
0307       }
0308       canvas.cd(1);
0309 
0310       canvas.cd(1)->SetTopMargin(0.05);
0311       canvas.cd(1)->SetBottomMargin(0.06);
0312       canvas.cd(1)->SetLeftMargin(0.15);
0313       canvas.cd(1)->SetRightMargin(0.01);
0314       canvas.cd(1)->Modified();
0315       canvas.cd(1)->SetGrid();
0316 
0317       auto h2_BSParameters = std::make_unique<TH2F>("Parameters", "", 2, 0.0, 2.0, 8, 0, 8.);
0318       h2_BSParameters->SetStats(false);
0319 
0320       std::function<double(parameters, bool)> cutFunctor = [this](parameters my_param, bool isError) {
0321         double ret(-999.);
0322         if (!isError) {
0323           switch (my_param) {
0324             case X:
0325               return m_payload->x();
0326             case Y:
0327               return m_payload->y();
0328             case Z:
0329               return m_payload->z();
0330             case sigmaX:
0331               return m_payload->beamWidthX();
0332             case sigmaY:
0333               return m_payload->beamWidthY();
0334             case sigmaZ:
0335               return m_payload->sigmaZ();
0336             case dxdz:
0337               return m_payload->dxdz();
0338             case dydz:
0339               return m_payload->dydz();
0340             case END_OF_TYPES:
0341               return ret;
0342             default:
0343               return ret;
0344           }
0345         } else {
0346           switch (my_param) {
0347             case X:
0348               return m_payload->xError();
0349             case Y:
0350               return m_payload->yError();
0351             case Z:
0352               return m_payload->zError();
0353             case sigmaX:
0354               return m_payload->beamWidthXError();
0355             case sigmaY:
0356               return m_payload->beamWidthYError();
0357             case sigmaZ:
0358               return m_payload->sigmaZError();
0359             case dxdz:
0360               return m_payload->dxdzError();
0361             case dydz:
0362               return m_payload->dydzError();
0363             case END_OF_TYPES:
0364               return ret;
0365             default:
0366               return ret;
0367           }
0368         }
0369       };
0370 
0371       h2_BSParameters->GetXaxis()->SetBinLabel(1, "Value");
0372       h2_BSParameters->GetXaxis()->SetBinLabel(2, "Error");
0373 
0374       unsigned int yBin = 8;
0375       for (int foo = parameters::X; foo <= parameters::dydz; foo++) {
0376         parameters param = static_cast<parameters>(foo);
0377         std::string theLabel = getStringFromTypeEnum(param);
0378         h2_BSParameters->GetYaxis()->SetBinLabel(yBin, theLabel.c_str());
0379         h2_BSParameters->SetBinContent(1, yBin, cutFunctor(param, false));
0380         h2_BSParameters->SetBinContent(2, yBin, cutFunctor(param, true));
0381         yBin--;
0382       }
0383 
0384       h2_BSParameters->GetXaxis()->LabelsOption("h");
0385       h2_BSParameters->GetYaxis()->SetLabelSize(0.05);
0386       h2_BSParameters->GetXaxis()->SetLabelSize(0.05);
0387       h2_BSParameters->SetMarkerSize(1.5);
0388       h2_BSParameters->Draw("TEXT");
0389 
0390       auto ltx = TLatex();
0391       ltx.SetTextFont(62);
0392       if (isOnline_) {
0393         ltx.SetTextSize(0.030);
0394       } else {
0395         ltx.SetTextSize(0.025);
0396       }
0397       ltx.SetTextAlign(11);
0398 
0399       auto runLS = BeamSpotPI::unpack(std::get<0>(iov));
0400 
0401       ltx.DrawLatexNDC(
0402           gPad->GetLeftMargin(),
0403           1 - gPad->GetTopMargin() + 0.01,
0404           (tagname + " IOV: #color[4]{" + std::to_string(runLS.first) + "," + std::to_string(runLS.second) + "}")
0405               .c_str());
0406 
0407       if (isOnline_) {
0408         canvas.cd(2);
0409         canvas.cd(2)->SetTopMargin(0.05);
0410         canvas.cd(2)->SetBottomMargin(0.06);
0411         canvas.cd(2)->SetLeftMargin(0.25);
0412         canvas.cd(2)->SetRightMargin(0.01);
0413         canvas.cd(2)->Modified();
0414         canvas.cd(2)->SetGrid();
0415 
0416         auto extras = fillTheExtraHistogram();
0417         if (extras) {
0418           for (int bin = 1; bin <= extras->GetNbinsY(); bin++) {
0419             edm::LogVerbatim("BeamSpotPayloadInspectorHelper")
0420                 << extras->GetYaxis()->GetBinLabel(bin) << ": " << extras->GetBinContent(1, bin) << "\n";
0421           }
0422         }
0423         extras->Draw("TEXT");
0424 
0425         ltx.DrawLatexNDC(
0426             gPad->GetLeftMargin(),
0427             1 - gPad->GetTopMargin() + 0.01,
0428             (tagname + " IOV: #color[4]{" + std::to_string(runLS.first) + "," + std::to_string(runLS.second) + "}")
0429                 .c_str());
0430 
0431         std::string fileName(this->m_imageFileName);
0432         canvas.SaveAs(fileName.c_str());
0433 
0434         return true;
0435       } else {
0436         std::string fileName(this->m_imageFileName);
0437         canvas.SaveAs(fileName.c_str());
0438 
0439         return true;
0440       }
0441     }
0442 
0443   public:
0444     virtual std::shared_ptr<TH2F> fillTheExtraHistogram() const { return nullptr; }
0445 
0446   protected:
0447     bool isOnline_;
0448     std::shared_ptr<PayloadType> m_payload;
0449 
0450     /**
0451      * Can't use BeamSpotPI::getStringFromParamEnum becasue it needs to be overridden
0452      * for the BeamSpotOnlineObjects case.
0453      */
0454     virtual std::string getStringFromTypeEnum(const parameters& parameter) const {
0455       switch (parameter) {
0456         case X:
0457           return "X [cm]";
0458         case Y:
0459           return "Y [cm]";
0460         case Z:
0461           return "Z [cm]";
0462         case sigmaX:
0463           return "#sigma_{X} [cm]";
0464         case sigmaY:
0465           return "#sigma_{Y} [cm]";
0466         case sigmaZ:
0467           return "#sigma_{Z} [cm]";
0468         case dxdz:
0469           return "#frac{dX}{dZ} [rad]";
0470         case dydz:
0471           return "#frac{dY}{dZ} [rad]";
0472         default:
0473           return "should never be here";
0474       }
0475     }
0476   };
0477 
0478   /************************************************
0479     Display of Beam Spot parameters difference
0480   *************************************************/
0481   template <class PayloadType, cond::payloadInspector::IOVMultiplicity nIOVs, int ntags>
0482   class DisplayParametersDiff : public cond::payloadInspector::PlotImage<PayloadType, nIOVs, ntags> {
0483   public:
0484     DisplayParametersDiff()
0485         : cond::payloadInspector::PlotImage<PayloadType, nIOVs, ntags>("Display of BeamSpot parameters differences") {
0486       if constexpr (std::is_same_v<PayloadType, BeamSpotOnlineObjects>) {
0487         isOnline_ = true;
0488       } else {
0489         isOnline_ = false;
0490       }
0491     }
0492 
0493     bool fill() override {
0494       // trick to deal with the multi-ioved tag and two tag case at the same time
0495       auto theIOVs = cond::payloadInspector::PlotBase::getTag<0>().iovs;
0496       auto f_tagname = cond::payloadInspector::PlotBase::getTag<0>().name;
0497       std::string l_tagname = "";
0498       auto firstiov = theIOVs.front();
0499       std::tuple<cond::Time_t, cond::Hash> lastiov;
0500 
0501       // we don't support (yet) comparison with more than 2 tags
0502       assert(this->m_plotAnnotations.ntags < 3);
0503 
0504       if (this->m_plotAnnotations.ntags == 2) {
0505         auto tag2iovs = cond::payloadInspector::PlotBase::getTag<1>().iovs;
0506         l_tagname = cond::payloadInspector::PlotBase::getTag<1>().name;
0507         lastiov = tag2iovs.front();
0508       } else {
0509         lastiov = theIOVs.back();
0510       }
0511 
0512       l_payload = this->fetchPayload(std::get<1>(lastiov));
0513       f_payload = this->fetchPayload(std::get<1>(firstiov));
0514 
0515       std::string lastIOVsince = std::to_string(std::get<0>(lastiov));
0516       std::string firstIOVsince = std::to_string(std::get<0>(firstiov));
0517 
0518       TCanvas canvas("Beam Spot Parameters Difference Summary", "Beam Spot Parameters Difference summary", 1000, 1000);
0519       canvas.cd(1);
0520 
0521       canvas.cd(1)->SetTopMargin(0.08);
0522       canvas.cd(1)->SetBottomMargin(0.06);
0523       canvas.cd(1)->SetLeftMargin(0.14);
0524       canvas.cd(1)->SetRightMargin(0.16);
0525       canvas.cd(1)->Modified();
0526       canvas.cd(1)->SetGrid();
0527 
0528       // for the "text"-filled histogram
0529       auto h2_BSParameters = std::make_unique<TH2F>("Parameters", "", 2, 0.0, 2.0, 8, 0, 8.);
0530       h2_BSParameters->SetStats(false);
0531       h2_BSParameters->GetXaxis()->SetBinLabel(1, "Value");
0532       h2_BSParameters->GetXaxis()->SetBinLabel(2, "Error");
0533       h2_BSParameters->GetXaxis()->LabelsOption("h");
0534       h2_BSParameters->GetYaxis()->SetLabelSize(0.05);
0535       h2_BSParameters->GetXaxis()->SetLabelSize(0.05);
0536       h2_BSParameters->SetMarkerSize(1.5);
0537 
0538       // prepare the arrays to fill the histogram
0539       BeamSpotPI::BSParamsHelper fBS(f_payload);
0540       BeamSpotPI::BSParamsHelper lBS(l_payload);
0541 
0542 #ifdef MM_DEBUG
0543       std::stringstream ss1, ss2;
0544       edm::LogPrint("") << "**** first payload";
0545       fBS.printDebug(ss1);
0546       edm::LogPrint("") << ss1.str();
0547       edm::LogPrint("") << "**** last payload";
0548       lBS.printDebug(ss2);
0549       edm::LogPrint("") << ss2.str();
0550 #endif
0551 
0552       const auto diffPars = fBS.diffCentralValues(lBS);
0553       const auto diffErrors = fBS.diffErrors(lBS);
0554       //const auto pullPars = fBS.diffCentralValues(lBS,true /*normalize*/);
0555       //const auto pullErrors = fBS.diffErrors(lBS,true /*normalize*/);
0556 
0557       unsigned int yBin = 8;
0558       for (int foo = parameters::X; foo <= parameters::dydz; foo++) {
0559         parameters param = static_cast<parameters>(foo);
0560         std::string theLabel = BeamSpotPI::getStringFromParamEnum(param, true /*use units*/);
0561         h2_BSParameters->GetYaxis()->SetBinLabel(yBin, theLabel.c_str());
0562         h2_BSParameters->SetBinContent(1, yBin, diffPars[foo]); /* profiting of the parameters enum indexing */
0563         h2_BSParameters->SetBinContent(2, yBin, diffErrors[foo]);
0564         yBin--;
0565       }
0566 
0567       // for the "colz"-filled histogram (clonde from the text-based one)
0568       auto h2_BSShadow = (TH2F*)(h2_BSParameters->Clone("shadow"));
0569       h2_BSShadow->GetZaxis()->SetTitle("#Delta Parameter(payload A - payload B)");
0570       h2_BSShadow->GetZaxis()->CenterTitle();
0571       h2_BSShadow->GetZaxis()->SetTitleOffset(1.5);
0572 
0573       // this is the fine gradient palette (blue to red)
0574       double max = h2_BSShadow->GetMaximum();
0575       double min = h2_BSShadow->GetMinimum();
0576       double val_white = 0.;
0577       double per_white = (max != min) ? ((val_white - min) / (max - min)) : 0.5;
0578 
0579       const int Number = 3;
0580       double Red[Number] = {0., 1., 1.};
0581       double Green[Number] = {0., 1., 0.};
0582       double Blue[Number] = {1., 1., 0.};
0583       double Stops[Number] = {0., per_white, 1.};
0584       int nb = 256;
0585       h2_BSShadow->SetContour(nb);
0586       TColor::CreateGradientColorTable(Number, Stops, Red, Green, Blue, nb);
0587 
0588       h2_BSShadow->Draw("colz");
0589       h2_BSParameters->Draw("TEXTsame");
0590 
0591       auto ltx = TLatex();
0592       ltx.SetTextFont(62);
0593       ltx.SetTextSize(0.025);
0594       ltx.SetTextAlign(11);
0595 
0596       // compute the (run,LS) pairs
0597       auto l_runLS = BeamSpotPI::unpack(std::get<0>(lastiov));
0598       std::string l_runLSs = "(" + std::to_string(l_runLS.first) + "," + std::to_string(l_runLS.second) + ")";
0599       auto f_runLS = BeamSpotPI::unpack(std::get<0>(firstiov));
0600       std::string f_runLSs = "(" + std::to_string(f_runLS.first) + "," + std::to_string(f_runLS.second) + ")";
0601 
0602       if (this->m_plotAnnotations.ntags == 2) {
0603         ltx.DrawLatexNDC(
0604             gPad->GetLeftMargin() - 0.1,
0605             1 - gPad->GetTopMargin() + 0.015,
0606             (fmt::sprintf(
0607                  "#splitline{A = #color[4]{%s}: %s}{B = #color[4]{%s}: %s}", f_tagname, f_runLSs, l_tagname, l_runLSs))
0608                 .c_str());
0609       } else {
0610         ltx.DrawLatexNDC(
0611             gPad->GetLeftMargin() - 0.1,
0612             1 - gPad->GetTopMargin() + 0.015,
0613             (fmt::sprintf("#splitline{#color[4]{%s}}{A = %s | B = %s}", f_tagname, l_runLSs, f_runLSs)).c_str());
0614       }
0615 
0616       std::string fileName(this->m_imageFileName);
0617       canvas.SaveAs(fileName.c_str());
0618 
0619       return true;
0620     }
0621 
0622   public:
0623     /**
0624      * In case an extension to the BeamSpotOnlineObjects case will be needed in future
0625      */
0626     virtual std::shared_ptr<TH2F> fillTheExtraHistogram() const { return nullptr; }
0627 
0628   protected:
0629     bool isOnline_;
0630     std::shared_ptr<PayloadType> f_payload;
0631     std::shared_ptr<PayloadType> l_payload;
0632   };
0633 }  // namespace BeamSpotPI
0634 
0635 #endif