Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-11-04 00:01:54

0001 #ifndef CONDCORE_BEAMSPOTPLUGINS_BEAMSPOTPAYLOADINSPECTORHELPER_H
0002 #define CONDCORE_BEAMSPOTPLUGINS_BEAMSPOTPAYLOADINSPECTORHELPER_H
0003 
0004 // User includes
0005 #include "CondCore/CondDB/interface/Time.h"
0006 #include "CondCore/Utilities/interface/PayloadInspector.h"
0007 #include "CondCore/Utilities/interface/PayloadInspectorModule.h"
0008 #include "CondFormats/BeamSpotObjects/interface/BeamSpotOnlineObjects.h"
0009 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0010 
0011 // system includes
0012 #include <ctime>
0013 #include <fmt/printf.h>
0014 #include <memory>
0015 #include <sstream>
0016 #include <regex>
0017 
0018 // ROOT includes
0019 #include "TCanvas.h"
0020 #include "TH2F.h"
0021 #include "TLatex.h"
0022 #include "TStyle.h"
0023 
0024 //#define MMDEBUG  /* to make it verbose */
0025 
0026 namespace beamSpotPI {
0027 
0028   inline std::pair<unsigned int, unsigned int> unpack(cond::Time_t since) {
0029     auto kLowMask = 0XFFFFFFFF;
0030     auto run = (since >> 32);
0031     auto lumi = (since & kLowMask);
0032     return std::make_pair(run, lumi);
0033   }
0034 
0035   enum parameters {
0036     X = 0,                // 0  regular BS methods
0037     Y = 1,                // 1
0038     Z = 2,                // 2
0039     sigmaX = 3,           // 3
0040     sigmaY = 4,           // 4
0041     sigmaZ = 5,           // 5
0042     dxdz = 6,             // 6
0043     dydz = 7,             // 7
0044     lastLumi = 8,         // 8  additional int's
0045     lastRun = 9,          // 9
0046     lastFill = 10,        // 10
0047     nTracks = 11,         // 11
0048     nPVs = 12,            // 12
0049     nUsedEvents = 13,     // 13
0050     maxPVs = 14,          // 14
0051     meanPV = 15,          // 15 additional float's
0052     meanErrorPV = 16,     // 16
0053     rmsPV = 17,           // 17
0054     rmsErrorPV = 18,      // 18
0055     creationTime = 19,    // 19 additional cond::Time_t
0056     startTimeStamp = 20,  // 20
0057     endTimeStamp = 21,    // 21
0058     startTime = 22,       // 22 additional std::string
0059     endTime = 23,         // 23
0060     lumiRange = 24,       // 24
0061     END_OF_TYPES = 25,
0062   };
0063 
0064   /************************************************/
0065   // Function to convert cond::Time_t (in microseconds) to human-readable date string
0066   inline std::string convertTimeToDateString(cond::Time_t timeValue, bool hasMicros = false, bool toUTC = true) {
0067     // Convert microseconds to seconds
0068     std::time_t unixTime = static_cast<std::time_t>(hasMicros ? timeValue / 1000000 : timeValue);
0069 
0070     // Convert std::time_t to struct tm (to UTC, or not)
0071     std::tm* timeInfo = toUTC ? std::gmtime(&unixTime) : std::localtime(&unixTime);
0072 
0073     // Convert struct tm to human-readable string format
0074     char buffer[80];
0075     std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", timeInfo);
0076 
0077     // Append microseconds to the string
0078     std::string dateString(buffer);
0079     //dateString += "." + std::to_string(timeValue % 1000000);
0080 
0081     return dateString;
0082   }
0083 
0084   /************************************************/
0085   inline std::string getStringFromParamEnum(const parameters& parameter,
0086                                             const bool addUnits = false /*not used by default*/) {
0087     switch (parameter) {
0088       case X:
0089         return (addUnits ? "X [cm]" : "X");
0090       case Y:
0091         return (addUnits ? "Y [cm]" : "Y");
0092       case Z:
0093         return (addUnits ? "Z [cm]" : "Z");
0094       case sigmaX:
0095         return (addUnits ? "#sigma_{X} [cm]" : "sigmaX");
0096       case sigmaY:
0097         return (addUnits ? "#sigma_{Y} [cm]" : "sigmaY");
0098       case sigmaZ:
0099         return (addUnits ? "#sigma_{Z} [cm]" : "sigmaZ");
0100       case dxdz:
0101         return (addUnits ? "#frac{dX}{dZ} [rad]" : "dx/dz");
0102       case dydz:
0103         return (addUnits ? "#frac{dY}{dZ} [rad]" : "dy/dz");
0104       default:
0105         return "should never be here";
0106     }
0107   }
0108 
0109   /**
0110    * Helper class for operations on the Beam Spot Parameters
0111    * It's a simplified representation of the beamspot
0112    * data used as the underlying type for data transfers and comparisons
0113    */
0114   template <class PayloadType>
0115   class BSParamsHelper {
0116     typedef std::array<double, parameters::lastLumi> bshelpdata;
0117 
0118   public:
0119     BSParamsHelper(const std::shared_ptr<PayloadType>& bs) {
0120       // fill in the central values
0121       m_values[parameters::X] = bs->x(), m_values[parameters::Y] = bs->y(), m_values[parameters::Z] = bs->z();
0122       m_values[parameters::sigmaX] = bs->beamWidthX(), m_values[parameters::sigmaY] = bs->beamWidthY(),
0123       m_values[parameters::sigmaZ] = bs->sigmaZ();
0124       m_values[parameters::dxdz] = bs->dxdz(), m_values[parameters::dydz] = bs->dydz();
0125 
0126       // fill in the errors
0127       m_errors[parameters::X] = bs->xError(), m_errors[parameters::Y] = bs->yError(),
0128       m_errors[parameters::Z] = bs->zError();
0129       m_errors[parameters::sigmaX] = bs->beamWidthXError(), m_errors[parameters::sigmaY] = bs->beamWidthYError(),
0130       m_errors[parameters::sigmaZ] = bs->sigmaZError();
0131       m_errors[parameters::dxdz] = bs->dxdzError(), m_errors[parameters::dydz] = bs->dydzError();
0132     }
0133 
0134     void printDebug(std::stringstream& ss) {
0135       ss << "Dumping BeamSpot parameters Data:" << std::endl;
0136       for (uint i = parameters::X; i <= parameters::dydz; i++) {
0137         parameters par = static_cast<parameters>(i);
0138         ss << getStringFromParamEnum(par) << " : " << m_values[i] << std::endl;
0139         ss << getStringFromParamEnum(par) << " error: " << m_errors[i] << std::endl;
0140         ss << std::endl;
0141       }
0142     }
0143 
0144     inline const bshelpdata centralValues() const { return m_values; }
0145     inline const bshelpdata errors() const { return m_errors; }
0146 
0147     // get the difference in values
0148     const bshelpdata diffCentralValues(const BSParamsHelper& bs2, const bool isPull = false) const {
0149       bshelpdata ret;
0150       for (uint i = parameters::X; i <= parameters::dydz; i++) {
0151         ret[i] = this->centralValues()[i] - bs2.centralValues()[i];
0152         if (isPull)
0153           (this->centralValues()[i] != 0.) ? ret[i] /= this->centralValues()[i] : 0.;
0154       }
0155       return ret;
0156     }
0157 
0158     // get the difference in errors
0159     const bshelpdata diffErrors(const BSParamsHelper& bs2, const bool isPull = false) const {
0160       bshelpdata ret;
0161       for (uint i = parameters::X; i <= parameters::dydz; i++) {
0162         ret[i] = this->errors()[i] - bs2.errors()[i];
0163         if (isPull)
0164           (this->errors()[i] != 0.) ? ret[i] /= this->errors()[i] : 0.;
0165       }
0166       return ret;
0167     }
0168 
0169   private:
0170     bshelpdata m_values; /* central values */
0171     bshelpdata m_errors; /* errors */
0172   };
0173 
0174   /************************************************
0175     template classes (history)
0176   *************************************************/
0177 
0178   template <parameters my_param, class PayloadType>
0179   class BeamSpot_history : public cond::payloadInspector::HistoryPlot<PayloadType, std::pair<double, double> > {
0180   public:
0181     BeamSpot_history()
0182         : cond::payloadInspector::HistoryPlot<PayloadType, std::pair<double, double> >(
0183               getStringFromParamEnum(my_param) + " vs run number", getStringFromParamEnum(my_param)) {}
0184 
0185     std::pair<double, double> getFromPayload(PayloadType& payload) override {
0186       auto ret = std::make_pair<double, double>(-9999., -9999.);
0187 
0188       switch (my_param) {
0189         case X:
0190           return std::make_pair<double, double>(payload.x(), payload.xError());
0191         case Y:
0192           return std::make_pair<double, double>(payload.y(), payload.yError());
0193         case Z:
0194           return std::make_pair<double, double>(payload.z(), payload.zError());
0195         case sigmaX:
0196           return std::make_pair<double, double>(payload.beamWidthX(), payload.beamWidthXError());
0197         case sigmaY:
0198           return std::make_pair<double, double>(payload.beamWidthY(), payload.beamWidthYError());
0199         case sigmaZ:
0200           return std::make_pair<double, double>(payload.sigmaZ(), payload.sigmaZError());
0201         case dxdz:
0202           return std::make_pair<double, double>(payload.dxdz(), payload.dxdzError());
0203         case dydz:
0204           return std::make_pair<double, double>(payload.dydz(), payload.dydzError());
0205         case END_OF_TYPES:
0206           return ret;
0207         default:
0208           return ret;
0209       }
0210     }
0211   };
0212 
0213   /************************************************
0214     template classes (run history)
0215    *************************************************/
0216 
0217   template <parameters my_param, class PayloadType>
0218   class BeamSpot_runhistory : public cond::payloadInspector::RunHistoryPlot<PayloadType, std::pair<double, double> > {
0219   public:
0220     BeamSpot_runhistory()
0221         : cond::payloadInspector::RunHistoryPlot<PayloadType, std::pair<double, double> >(
0222               getStringFromParamEnum(my_param) + " vs run number", getStringFromParamEnum(my_param)) {}
0223 
0224     std::pair<double, double> getFromPayload(PayloadType& payload) override {
0225       auto ret = std::make_pair<double, double>(-9999., -9999.);
0226 
0227       switch (my_param) {
0228         case X:
0229           return std::make_pair<double, double>(payload.x(), payload.xError());
0230         case Y:
0231           return std::make_pair<double, double>(payload.y(), payload.yError());
0232         case Z:
0233           return std::make_pair<double, double>(payload.z(), payload.zError());
0234         case sigmaX:
0235           return std::make_pair<double, double>(payload.beamWidthX(), payload.beamWidthXError());
0236         case sigmaY:
0237           return std::make_pair<double, double>(payload.beamWidthY(), payload.beamWidthYError());
0238         case sigmaZ:
0239           return std::make_pair<double, double>(payload.sigmaZ(), payload.sigmaZError());
0240         case dxdz:
0241           return std::make_pair<double, double>(payload.dxdz(), payload.dxdzError());
0242         case dydz:
0243           return std::make_pair<double, double>(payload.dydz(), payload.dydzError());
0244         case END_OF_TYPES:
0245           return ret;
0246         default:
0247           return ret;
0248       }
0249     }
0250   };
0251 
0252   /************************************************
0253     template classes (time history)
0254   *************************************************/
0255 
0256   template <parameters my_param, class PayloadType>
0257   class BeamSpot_timehistory : public cond::payloadInspector::TimeHistoryPlot<PayloadType, std::pair<double, double> > {
0258   public:
0259     BeamSpot_timehistory()
0260         : cond::payloadInspector::TimeHistoryPlot<PayloadType, std::pair<double, double> >(
0261               getStringFromParamEnum(my_param) + " vs time", getStringFromParamEnum(my_param)) {}
0262 
0263     std::pair<double, double> getFromPayload(PayloadType& payload) override {
0264       auto ret = std::make_pair<double, double>(-9999., -9999.);
0265 
0266       switch (my_param) {
0267         case X:
0268           return std::make_pair<double, double>(payload.x(), payload.xError());
0269         case Y:
0270           return std::make_pair<double, double>(payload.y(), payload.yError());
0271         case Z:
0272           return std::make_pair<double, double>(payload.z(), payload.zError());
0273         case sigmaX:
0274           return std::make_pair<double, double>(payload.beamWidthX(), payload.beamWidthXError());
0275         case sigmaY:
0276           return std::make_pair<double, double>(payload.beamWidthY(), payload.beamWidthYError());
0277         case sigmaZ:
0278           return std::make_pair<double, double>(payload.sigmaZ(), payload.sigmaZError());
0279         case dxdz:
0280           return std::make_pair<double, double>(payload.dxdz(), payload.dxdzError());
0281         case dydz:
0282           return std::make_pair<double, double>(payload.dydz(), payload.dydzError());
0283         case END_OF_TYPES:
0284           return ret;
0285         default:
0286           return ret;
0287       }
0288     }
0289   };
0290 
0291   /************************************************
0292     X-Y correlation plot
0293   *************************************************/
0294   template <class PayloadType>
0295   class xyCorrelation : public cond::payloadInspector::ScatterPlot<PayloadType, double, double> {
0296   public:
0297     xyCorrelation() : cond::payloadInspector::ScatterPlot<PayloadType, double, double>("BeamSpot x vs y", "x", "y") {}
0298 
0299     std::tuple<double, double> getFromPayload(PayloadType& payload) override {
0300       return std::make_tuple(payload.x(), payload.y());
0301     }
0302   };
0303 
0304   /************************************************
0305     Display of Beam Spot parameters
0306   *************************************************/
0307   template <class PayloadType>
0308   class DisplayParameters : public cond::payloadInspector::PlotImage<PayloadType, cond::payloadInspector::SINGLE_IOV> {
0309   public:
0310     DisplayParameters()
0311         : cond::payloadInspector::PlotImage<PayloadType, cond::payloadInspector::SINGLE_IOV>(
0312               "Display of BeamSpot parameters") {
0313       if constexpr (std::is_same_v<PayloadType, BeamSpotOnlineObjects>) {
0314         isOnline_ = true;
0315       } else {
0316         isOnline_ = false;
0317       }
0318     }
0319 
0320     bool fill() override {
0321       auto tag = cond::payloadInspector::PlotBase::getTag<0>();
0322       auto tagname = tag.name;
0323       auto iov = tag.iovs.front();
0324 
0325       gStyle->SetHistMinimumZero(kTRUE);
0326 
0327       m_payload = this->fetchPayload(std::get<1>(iov));
0328 
0329       TCanvas canvas("Beam Spot Parameters Summary", "BeamSpot Parameters summary", isOnline_ ? 1500 : 1000, 1000);
0330       if (isOnline_) {
0331         canvas.Divide(2, 1);
0332       }
0333       canvas.cd(1);
0334 
0335       canvas.cd(1)->SetTopMargin(0.05);
0336       canvas.cd(1)->SetBottomMargin(0.06);
0337       canvas.cd(1)->SetLeftMargin(0.15);
0338       canvas.cd(1)->SetRightMargin(0.01);
0339       canvas.cd(1)->Modified();
0340       canvas.cd(1)->SetGrid();
0341 
0342       auto h2_BSParameters = std::make_unique<TH2F>("Parameters", "", 2, 0.0, 2.0, 8, 0, 8.);
0343       h2_BSParameters->SetStats(false);
0344 
0345       std::function<double(parameters, bool)> cutFunctor = [this](parameters my_param, bool isError) {
0346         double ret(-999.);
0347         if (!isError) {
0348           switch (my_param) {
0349             case X:
0350               return m_payload->x();
0351             case Y:
0352               return m_payload->y();
0353             case Z:
0354               return m_payload->z();
0355             case sigmaX:
0356               return m_payload->beamWidthX();
0357             case sigmaY:
0358               return m_payload->beamWidthY();
0359             case sigmaZ:
0360               return m_payload->sigmaZ();
0361             case dxdz:
0362               return m_payload->dxdz();
0363             case dydz:
0364               return m_payload->dydz();
0365             case END_OF_TYPES:
0366               return ret;
0367             default:
0368               return ret;
0369           }
0370         } else {
0371           switch (my_param) {
0372             case X:
0373               return m_payload->xError();
0374             case Y:
0375               return m_payload->yError();
0376             case Z:
0377               return m_payload->zError();
0378             case sigmaX:
0379               return m_payload->beamWidthXError();
0380             case sigmaY:
0381               return m_payload->beamWidthYError();
0382             case sigmaZ:
0383               return m_payload->sigmaZError();
0384             case dxdz:
0385               return m_payload->dxdzError();
0386             case dydz:
0387               return m_payload->dydzError();
0388             case END_OF_TYPES:
0389               return ret;
0390             default:
0391               return ret;
0392           }
0393         }
0394       };
0395 
0396       h2_BSParameters->GetXaxis()->SetBinLabel(1, "Value");
0397       h2_BSParameters->GetXaxis()->SetBinLabel(2, "Error");
0398 
0399       unsigned int yBin = 8;
0400       for (int foo = parameters::X; foo <= parameters::dydz; foo++) {
0401         parameters param = static_cast<parameters>(foo);
0402         std::string theLabel = getStringFromTypeEnum(param);
0403         h2_BSParameters->GetYaxis()->SetBinLabel(yBin, theLabel.c_str());
0404         h2_BSParameters->SetBinContent(1, yBin, cutFunctor(param, false));
0405         h2_BSParameters->SetBinContent(2, yBin, cutFunctor(param, true));
0406         yBin--;
0407       }
0408 
0409       h2_BSParameters->GetXaxis()->LabelsOption("h");
0410       h2_BSParameters->GetYaxis()->SetLabelSize(0.05);
0411       h2_BSParameters->GetXaxis()->SetLabelSize(0.05);
0412       h2_BSParameters->SetMarkerSize(1.5);
0413       h2_BSParameters->Draw("TEXT");
0414 
0415       auto ltx = TLatex();
0416       ltx.SetTextFont(62);
0417       if (isOnline_) {
0418         ltx.SetTextSize(0.030);
0419       } else {
0420         ltx.SetTextSize(0.025);
0421       }
0422       ltx.SetTextAlign(11);
0423 
0424       auto runLS = beamSpotPI::unpack(std::get<0>(iov));
0425 
0426       ltx.DrawLatexNDC(
0427           gPad->GetLeftMargin(),
0428           1 - gPad->GetTopMargin() + 0.01,
0429           (tagname + " IOV: #color[4]{" + std::to_string(runLS.first) + "," + std::to_string(runLS.second) + "}")
0430               .c_str());
0431 
0432       if (isOnline_) {
0433         canvas.cd(2);
0434         canvas.cd(2)->SetTopMargin(0.05);
0435         canvas.cd(2)->SetBottomMargin(0.06);
0436         canvas.cd(2)->SetLeftMargin(0.25);
0437         canvas.cd(2)->SetRightMargin(0.01);
0438         canvas.cd(2)->Modified();
0439         canvas.cd(2)->SetGrid();
0440 
0441         auto extras = fillTheExtraHistogram();
0442         if (extras) {
0443           for (int bin = 1; bin <= extras->GetNbinsY(); bin++) {
0444             edm::LogVerbatim("BeamSpotPayloadInspectorHelper")
0445                 << extras->GetYaxis()->GetBinLabel(bin) << ": " << extras->GetBinContent(1, bin) << "\n";
0446           }
0447         }
0448         extras->Draw("TEXT");
0449 
0450         ltx.DrawLatexNDC(
0451             gPad->GetLeftMargin(),
0452             1 - gPad->GetTopMargin() + 0.01,
0453             (tagname + " IOV: #color[4]{" + std::to_string(runLS.first) + "," + std::to_string(runLS.second) + "}")
0454                 .c_str());
0455 
0456         if constexpr (std::is_same_v<PayloadType, BeamSpotOnlineObjects>) {
0457           // protections needed against old payload that do not have these data members persisted
0458           const auto& creationTime = test_<cond::Time_t, std::out_of_range>(
0459               [&]() {
0460                 return m_payload->creationTime();
0461               },  // Lambda function capturing m_payload and calling creationTime
0462               better_error);
0463 
0464           const auto& startTime = test_<cond::Time_t, std::out_of_range>(
0465               [&]() {
0466                 return m_payload->startTimeStamp();
0467               },  // Lambda function capturing m_payload and calling startTimeStamp
0468               better_error);
0469 
0470           const auto& endTime = test_<cond::Time_t, std::out_of_range>(
0471               [&]() {
0472                 return m_payload->endTimeStamp();
0473               },  // Lambda function capturing m_payload and calling endTimeStamp
0474               better_error);
0475           canvas.cd(2);
0476           ltx.SetTextSize(0.025);
0477           ltx.DrawLatexNDC(
0478               gPad->GetLeftMargin() + 0.01,
0479               gPad->GetBottomMargin() + 0.15,
0480               ("#color[2]{(" + beamSpotPI::convertTimeToDateString(creationTime, /*has us*/ true) + ")}").c_str());
0481 
0482           ltx.DrawLatexNDC(gPad->GetLeftMargin() + 0.01,
0483                            gPad->GetBottomMargin() + 0.085,
0484                            ("#color[2]{(" + beamSpotPI::convertTimeToDateString(startTime) + ")}").c_str());
0485 
0486           ltx.DrawLatexNDC(gPad->GetLeftMargin() + 0.01,
0487                            gPad->GetBottomMargin() + 0.025,
0488                            ("#color[2]{(" + beamSpotPI::convertTimeToDateString(endTime) + ")}").c_str());
0489 
0490           ltx.DrawLatexNDC(
0491               gPad->GetLeftMargin(), gPad->GetBottomMargin() - 0.05, "#color[4]{N.B.} TimeStamps are in UTC");
0492         }
0493 
0494         std::string fileName(this->m_imageFileName);
0495         canvas.SaveAs(fileName.c_str());
0496 
0497         return true;
0498       } else {
0499         std::string fileName(this->m_imageFileName);
0500         canvas.SaveAs(fileName.c_str());
0501 
0502         return true;
0503       }
0504     }
0505 
0506   public:
0507     virtual std::shared_ptr<TH2F> fillTheExtraHistogram() const { return nullptr; }
0508 
0509   protected:
0510     bool isOnline_;
0511     std::shared_ptr<PayloadType> m_payload;
0512 
0513     /**
0514      * Can't use beamSpotPI::getStringFromParamEnum becasue it needs to be overridden
0515      * for the BeamSpotOnlineObjects case.
0516      */
0517     virtual std::string getStringFromTypeEnum(const parameters& parameter) const {
0518       switch (parameter) {
0519         case X:
0520           return "X [cm]";
0521         case Y:
0522           return "Y [cm]";
0523         case Z:
0524           return "Z [cm]";
0525         case sigmaX:
0526           return "#sigma_{X} [cm]";
0527         case sigmaY:
0528           return "#sigma_{Y} [cm]";
0529         case sigmaZ:
0530           return "#sigma_{Z} [cm]";
0531         case dxdz:
0532           return "#frac{dX}{dZ} [rad]";
0533         case dydz:
0534           return "#frac{dY}{dZ} [rad]";
0535         default:
0536           return "should never be here";
0537       }
0538     }
0539 
0540     // Slightly better error handler
0541     static void better_error(const std::exception& e) { edm::LogError("DisplayParameters") << e.what() << '\n'; }
0542 
0543     // Method to catch exceptions
0544     template <typename T, class Except, class Func, class Response>
0545     T test_(Func f, Response r) const {
0546       try {
0547         LogDebug("DisplayParameters") << "I have tried" << std::endl;
0548         return f();
0549       } catch (const Except& e) {
0550         LogDebug("DisplayParameters") << "I have caught!" << std::endl;
0551         r(e);
0552         return static_cast<T>(1);
0553       }
0554     }
0555   };
0556 
0557   /************************************************
0558     Display of Beam Spot parameters difference
0559   *************************************************/
0560   template <class PayloadType, cond::payloadInspector::IOVMultiplicity nIOVs, int ntags>
0561   class DisplayParametersDiff : public cond::payloadInspector::PlotImage<PayloadType, nIOVs, ntags> {
0562   public:
0563     DisplayParametersDiff()
0564         : cond::payloadInspector::PlotImage<PayloadType, nIOVs, ntags>("Display of BeamSpot parameters differences") {
0565       if constexpr (std::is_same_v<PayloadType, BeamSpotOnlineObjects>) {
0566         isOnline_ = true;
0567       } else {
0568         isOnline_ = false;
0569       }
0570     }
0571 
0572     bool fill() override {
0573       // trick to deal with the multi-ioved tag and two tag case at the same time
0574       auto theIOVs = cond::payloadInspector::PlotBase::getTag<0>().iovs;
0575       auto f_tagname = cond::payloadInspector::PlotBase::getTag<0>().name;
0576       std::string l_tagname = "";
0577       auto firstiov = theIOVs.front();
0578       std::tuple<cond::Time_t, cond::Hash> lastiov;
0579 
0580       // we don't support (yet) comparison with more than 2 tags
0581       assert(this->m_plotAnnotations.ntags < 3);
0582 
0583       if (this->m_plotAnnotations.ntags == 2) {
0584         auto tag2iovs = cond::payloadInspector::PlotBase::getTag<1>().iovs;
0585         l_tagname = cond::payloadInspector::PlotBase::getTag<1>().name;
0586         lastiov = tag2iovs.front();
0587       } else {
0588         lastiov = theIOVs.back();
0589       }
0590 
0591       l_payload = this->fetchPayload(std::get<1>(lastiov));
0592       f_payload = this->fetchPayload(std::get<1>(firstiov));
0593 
0594       std::string lastIOVsince = std::to_string(std::get<0>(lastiov));
0595       std::string firstIOVsince = std::to_string(std::get<0>(firstiov));
0596 
0597       TCanvas canvas("Beam Spot Parameters Difference Summary", "Beam Spot Parameters Difference summary", 1000, 1000);
0598       canvas.cd(1);
0599 
0600       canvas.cd(1)->SetTopMargin(0.08);
0601       canvas.cd(1)->SetBottomMargin(0.06);
0602       canvas.cd(1)->SetLeftMargin(0.14);
0603       canvas.cd(1)->SetRightMargin(0.16);
0604       canvas.cd(1)->Modified();
0605       canvas.cd(1)->SetGrid();
0606 
0607       // for the "text"-filled histogram
0608       auto h2_BSParameters = std::make_unique<TH2F>("Parameters", "", 2, 0.0, 2.0, 8, 0, 8.);
0609       h2_BSParameters->SetStats(false);
0610       h2_BSParameters->GetXaxis()->SetBinLabel(1, "Value");
0611       h2_BSParameters->GetXaxis()->SetBinLabel(2, "Error");
0612       h2_BSParameters->GetXaxis()->LabelsOption("h");
0613       h2_BSParameters->GetYaxis()->SetLabelSize(0.05);
0614       h2_BSParameters->GetXaxis()->SetLabelSize(0.05);
0615       h2_BSParameters->SetMarkerSize(1.5);
0616 
0617       // prepare the arrays to fill the histogram
0618       beamSpotPI::BSParamsHelper fBS(f_payload);
0619       beamSpotPI::BSParamsHelper lBS(l_payload);
0620 
0621 #ifdef MM_DEBUG
0622       std::stringstream ss1, ss2;
0623       edm::LogPrint("") << "**** first payload";
0624       fBS.printDebug(ss1);
0625       edm::LogPrint("") << ss1.str();
0626       edm::LogPrint("") << "**** last payload";
0627       lBS.printDebug(ss2);
0628       edm::LogPrint("") << ss2.str();
0629 #endif
0630 
0631       const auto diffPars = fBS.diffCentralValues(lBS);
0632       const auto diffErrors = fBS.diffErrors(lBS);
0633       //const auto pullPars = fBS.diffCentralValues(lBS,true /*normalize*/);
0634       //const auto pullErrors = fBS.diffErrors(lBS,true /*normalize*/);
0635 
0636       unsigned int yBin = 8;
0637       for (int foo = parameters::X; foo <= parameters::dydz; foo++) {
0638         parameters param = static_cast<parameters>(foo);
0639         std::string theLabel = beamSpotPI::getStringFromParamEnum(param, true /*use units*/);
0640         h2_BSParameters->GetYaxis()->SetBinLabel(yBin, theLabel.c_str());
0641         h2_BSParameters->SetBinContent(1, yBin, diffPars[foo]); /* profiting of the parameters enum indexing */
0642         h2_BSParameters->SetBinContent(2, yBin, diffErrors[foo]);
0643         yBin--;
0644       }
0645 
0646       // for the "colz"-filled histogram (clonde from the text-based one)
0647       auto h2_BSShadow = (TH2F*)(h2_BSParameters->Clone("shadow"));
0648       h2_BSShadow->GetZaxis()->SetTitle("#Delta Parameter(payload A - payload B)");
0649       h2_BSShadow->GetZaxis()->CenterTitle();
0650       h2_BSShadow->GetZaxis()->SetTitleOffset(1.5);
0651 
0652       // this is the fine gradient palette (blue to red)
0653       double max = h2_BSShadow->GetMaximum();
0654       double min = h2_BSShadow->GetMinimum();
0655       double val_white = 0.;
0656       double per_white = (max != min) ? ((val_white - min) / (max - min)) : 0.5;
0657 
0658       const int number = 3;
0659       double Red[number] = {0., 1., 1.};
0660       double Green[number] = {0., 1., 0.};
0661       double Blue[number] = {1., 1., 0.};
0662       double Stops[number] = {0., per_white, 1.};
0663       int nb = 256;
0664       h2_BSShadow->SetContour(nb);
0665       TColor::CreateGradientColorTable(number, Stops, Red, Green, Blue, nb);
0666 
0667       h2_BSShadow->Draw("colz");
0668       h2_BSParameters->Draw("TEXTsame");
0669 
0670       auto ltx = TLatex();
0671       ltx.SetTextFont(62);
0672       ltx.SetTextSize(0.025);
0673       ltx.SetTextAlign(11);
0674 
0675       // compute the (run,LS) pairs
0676       auto l_runLS = beamSpotPI::unpack(std::get<0>(lastiov));
0677       std::string l_runLSs = "(" + std::to_string(l_runLS.first) + "," + std::to_string(l_runLS.second) + ")";
0678       auto f_runLS = beamSpotPI::unpack(std::get<0>(firstiov));
0679       std::string f_runLSs = "(" + std::to_string(f_runLS.first) + "," + std::to_string(f_runLS.second) + ")";
0680 
0681       if (this->m_plotAnnotations.ntags == 2) {
0682         ltx.DrawLatexNDC(
0683             gPad->GetLeftMargin() - 0.1,
0684             1 - gPad->GetTopMargin() + 0.015,
0685             (fmt::sprintf(
0686                  "#splitline{A = #color[4]{%s}: %s}{B = #color[4]{%s}: %s}", f_tagname, f_runLSs, l_tagname, l_runLSs))
0687                 .c_str());
0688       } else {
0689         ltx.DrawLatexNDC(
0690             gPad->GetLeftMargin() - 0.1,
0691             1 - gPad->GetTopMargin() + 0.015,
0692             (fmt::sprintf("#splitline{#color[4]{%s}}{A = %s | B = %s}", f_tagname, l_runLSs, f_runLSs)).c_str());
0693       }
0694 
0695       std::string fileName(this->m_imageFileName);
0696       canvas.SaveAs(fileName.c_str());
0697 
0698       return true;
0699     }
0700 
0701   public:
0702     /**
0703      * In case an extension to the BeamSpotOnlineObjects case will be needed in future
0704      */
0705     virtual std::shared_ptr<TH2F> fillTheExtraHistogram() const { return nullptr; }
0706 
0707   protected:
0708     bool isOnline_;
0709     std::shared_ptr<PayloadType> f_payload;
0710     std::shared_ptr<PayloadType> l_payload;
0711   };
0712 }  // namespace beamSpotPI
0713 
0714 // Similar namespace for SimBeamSpotObject
0715 namespace simBeamSpotPI {
0716 
0717   enum parameters {
0718     X = 0,            // 0  - Positions
0719     Y = 1,            // 1
0720     Z = 2,            // 2
0721     meanX = 3,        // 3
0722     meanY = 4,        // 4
0723     meanZ = 5,        // 5
0724     sigmaX = 6,       // 6  - Widths
0725     sigmaY = 7,       // 7
0726     sigmaZ = 8,       // 8
0727     betaStar = 9,     // 9
0728     emittance = 10,   // 10
0729     phi = 11,         // 11  - Additional parameters
0730     alpha = 12,       // 12
0731     timeOffset = 13,  // 13
0732     END_OF_TYPES = 14,
0733   };
0734 
0735   /************************************************/
0736   inline std::string getStringFromParamEnum(const parameters& parameter, const bool addUnits = false) {
0737     switch (parameter) {
0738       case X:
0739         return (addUnits ? "X [cm]" : "X");
0740       case Y:
0741         return (addUnits ? "Y [cm]" : "Y");
0742       case Z:
0743         return (addUnits ? "Z [cm]" : "Z");
0744       case meanX:
0745         return (addUnits ? "MeanX [cm]" : "meanX");
0746       case meanY:
0747         return (addUnits ? "MeanY [cm]" : "meanY");
0748       case meanZ:
0749         return (addUnits ? "MeanZ [cm]" : "meanZ");
0750       case sigmaX:
0751         return (addUnits ? "#sigma_{X} [#mum]" : "sigmaX");
0752       case sigmaY:
0753         return (addUnits ? "#sigma_{Y} [#mum]" : "sigmaY");
0754       case sigmaZ:
0755         return (addUnits ? "#sigma_{Z} [cm]" : "sigmaZ");
0756       case betaStar:
0757         return (addUnits ? "#beta* [cm]" : "BetaStar");
0758       case emittance:
0759         return (addUnits ? "Emittance [cm]" : "Emittance");
0760       case phi:
0761         return (addUnits ? "Phi [rad]" : "Phi");
0762       case alpha:
0763         return (addUnits ? "Alpha [rad]" : "Alpha");
0764       case timeOffset:
0765         return (addUnits ? "TimeOffset [ns]" : "TimeOffset");
0766       default:
0767         return "should never be here";
0768     }
0769   }
0770 
0771   /**
0772    * Helper class for operations on the Sim Beam Spot Parameters
0773    * It's a simplified representation of the beamspot
0774    * data used as the underlying type for data transfers and comparisons
0775    */
0776   template <class PayloadType>
0777   class SimBSParamsHelper {
0778     typedef std::array<double, parameters::END_OF_TYPES> bshelpdata;
0779 
0780   public:
0781     SimBSParamsHelper(const std::shared_ptr<PayloadType>& bs) {
0782       // fill in the values
0783       m_values[parameters::X] = bs->x(), m_values[parameters::Y] = bs->y(), m_values[parameters::Z] = bs->z();
0784       m_values[parameters::meanX] = bs->meanX(), m_values[parameters::meanY] = bs->meanY();
0785       m_values[parameters::meanZ] = bs->meanZ();
0786       m_values[parameters::sigmaX] = bs->sigmaX() * 10000.f;
0787       m_values[parameters::sigmaY] = bs->sigmaY() * 10000.f;
0788       m_values[parameters::sigmaZ] = bs->sigmaZ();
0789       m_values[parameters::betaStar] = bs->betaStar(), m_values[parameters::emittance] = bs->emittance();
0790       m_values[parameters::phi] = bs->phi(), m_values[parameters::alpha] = bs->alpha(),
0791       m_values[parameters::timeOffset] = bs->timeOffset();
0792     }
0793 
0794     void printDebug(std::stringstream& ss) {
0795       ss << "Dumping SimBeamSpot parameters Data:" << std::endl;
0796       for (uint i = parameters::X; i <= parameters::timeOffset; i++) {
0797         parameters par = static_cast<parameters>(i);
0798         ss << getStringFromParamEnum(par) << " : " << m_values[i] << std::endl;
0799         ss << std::endl;
0800       }
0801     }
0802 
0803     inline const bshelpdata centralValues() const { return m_values; }
0804 
0805     // get the difference in values
0806     const bshelpdata diffCentralValues(const SimBSParamsHelper& bs2, const bool isPull = false) const {
0807       bshelpdata ret;
0808       for (uint i = parameters::X; i <= parameters::timeOffset; i++) {
0809         ret[i] = this->centralValues()[i] - bs2.centralValues()[i];
0810         if (isPull)
0811           (this->centralValues()[i] != 0.) ? ret[i] /= this->centralValues()[i] : 0.;
0812       }
0813       return ret;
0814     }
0815 
0816   private:
0817     bshelpdata m_values;
0818   };
0819 
0820   /************************************************
0821     Display of Sim Beam Spot parameters
0822   *************************************************/
0823   template <class PayloadType>
0824   class DisplayParameters : public cond::payloadInspector::PlotImage<PayloadType, cond::payloadInspector::SINGLE_IOV> {
0825   public:
0826     DisplayParameters()
0827         : cond::payloadInspector::PlotImage<PayloadType, cond::payloadInspector::SINGLE_IOV>(
0828               "Display of SimBeamSpot parameters") {}
0829 
0830     bool fill() override {
0831       auto tag = cond::payloadInspector::PlotBase::getTag<0>();
0832       auto tagname = tag.name;
0833       auto iov = tag.iovs.front();
0834 
0835       gStyle->SetHistMinimumZero(kTRUE);
0836 
0837       m_payload = this->fetchPayload(std::get<1>(iov));
0838 
0839       TCanvas canvas("Sim Beam Spot Parameters Summary", "Sim BeamSpot Parameters summary", 1000, 1000);
0840       canvas.cd(1);
0841       canvas.cd(1)->SetTopMargin(0.05);
0842       canvas.cd(1)->SetBottomMargin(0.06);
0843       canvas.cd(1)->SetLeftMargin(0.25);
0844       canvas.cd(1)->SetRightMargin(0.01);
0845       canvas.cd(1)->Modified();
0846       canvas.cd(1)->SetGrid();
0847 
0848       auto h2_SimBSParameters = std::make_unique<TH2F>("Parameters", "", 1, 0.0, 1.0, END_OF_TYPES, 0, END_OF_TYPES);
0849       h2_SimBSParameters->SetStats(false);
0850 
0851       std::function<double(parameters)> cutFunctor = [this](parameters my_param) {
0852         double ret(-999.);
0853         switch (my_param) {
0854           case X:
0855             return m_payload->x();
0856           case Y:
0857             return m_payload->y();
0858           case Z:
0859             return m_payload->z();
0860           case meanX:
0861             return m_payload->meanX();
0862           case meanY:
0863             return m_payload->meanY();
0864           case meanZ:
0865             return m_payload->meanZ();
0866           case sigmaX:
0867             return m_payload->sigmaX() * cmToUm;
0868           case sigmaY:
0869             return m_payload->sigmaY() * cmToUm;
0870           case sigmaZ:
0871             return m_payload->sigmaZ();
0872           case betaStar:
0873             return m_payload->betaStar();
0874           case emittance:
0875             return m_payload->emittance();
0876           case phi:
0877             return m_payload->phi();
0878           case alpha:
0879             return m_payload->alpha();
0880           case timeOffset:
0881             return m_payload->timeOffset();
0882           case END_OF_TYPES:
0883             return ret;
0884           default:
0885             return ret;
0886         }
0887       };
0888 
0889       h2_SimBSParameters->GetXaxis()->SetBinLabel(1, "Value");
0890 
0891       unsigned int yBin = END_OF_TYPES;
0892       for (int foo = parameters::X; foo <= parameters::timeOffset; foo++) {
0893         parameters param = static_cast<parameters>(foo);
0894         std::string theLabel = getStringFromParamEnum(param, true);
0895         h2_SimBSParameters->GetYaxis()->SetBinLabel(yBin, theLabel.c_str());
0896         h2_SimBSParameters->SetBinContent(1, yBin, cutFunctor(param));
0897         yBin--;
0898       }
0899 
0900       h2_SimBSParameters->GetXaxis()->LabelsOption("h");
0901       h2_SimBSParameters->GetYaxis()->SetLabelSize(0.05);
0902       h2_SimBSParameters->GetXaxis()->SetLabelSize(0.05);
0903       h2_SimBSParameters->SetMarkerSize(1.5);
0904       h2_SimBSParameters->Draw("TEXT");
0905 
0906       auto ltx = TLatex();
0907       ltx.SetTextFont(62);
0908       ltx.SetTextSize(0.025);
0909       //ltx.SetTextAlign(11);
0910 
0911       auto runLS = beamSpotPI::unpack(std::get<0>(iov));
0912 
0913       ltx.SetTextAlign(32);  // Set text alignment to left (left-aligned)
0914       ltx.DrawLatexNDC(1 - gPad->GetRightMargin(),
0915                        1 - gPad->GetTopMargin() + 0.01,
0916                        ("#color[2]{" + tagname + "} IOV: #color[4]{" + std::to_string(runLS.first) + "," +
0917                         std::to_string(runLS.second) + "}")
0918                            .c_str());
0919 
0920       std::string fileName(this->m_imageFileName);
0921       canvas.SaveAs(fileName.c_str());
0922 
0923       return true;
0924     }
0925 
0926   protected:
0927     std::shared_ptr<PayloadType> m_payload;
0928 
0929   private:
0930     static constexpr double cmToUm = 10000.f;
0931   };
0932 
0933   /************************************************
0934     Display of Sim Beam Spot parameters difference
0935   *************************************************/
0936   template <class PayloadType, cond::payloadInspector::IOVMultiplicity nIOVs, int ntags>
0937   class DisplayParametersDiff : public cond::payloadInspector::PlotImage<PayloadType, nIOVs, ntags> {
0938   public:
0939     DisplayParametersDiff()
0940         : cond::payloadInspector::PlotImage<PayloadType, nIOVs, ntags>(
0941               "Display of Sim BeamSpot parameters differences") {}
0942 
0943     bool fill() override {
0944       // trick to deal with the multi-ioved tag and two tag case at the same time
0945       auto theIOVs = cond::payloadInspector::PlotBase::getTag<0>().iovs;
0946       auto f_tagname = cond::payloadInspector::PlotBase::getTag<0>().name;
0947       std::string l_tagname = "";
0948       auto firstiov = theIOVs.front();
0949       std::tuple<cond::Time_t, cond::Hash> lastiov;
0950 
0951       // we don't support (yet) comparison with more than 2 tags
0952       assert(this->m_plotAnnotations.ntags < 3);
0953 
0954       if (this->m_plotAnnotations.ntags == 2) {
0955         auto tag2iovs = cond::payloadInspector::PlotBase::getTag<1>().iovs;
0956         l_tagname = cond::payloadInspector::PlotBase::getTag<1>().name;
0957         lastiov = tag2iovs.front();
0958       } else {
0959         lastiov = theIOVs.back();
0960       }
0961 
0962       l_payload = this->fetchPayload(std::get<1>(lastiov));
0963       f_payload = this->fetchPayload(std::get<1>(firstiov));
0964 
0965       std::string lastIOVsince = std::to_string(std::get<0>(lastiov));
0966       std::string firstIOVsince = std::to_string(std::get<0>(firstiov));
0967 
0968       TCanvas canvas(
0969           "Sim Beam Spot Parameters Difference Summary", "Sim Beam Spot Parameters Difference summary", 1000, 1000);
0970       canvas.cd(1);
0971       canvas.cd(1)->SetTopMargin(0.10);
0972       canvas.cd(1)->SetBottomMargin(0.06);
0973       canvas.cd(1)->SetLeftMargin(0.23);
0974       canvas.cd(1)->SetRightMargin(0.16);
0975       canvas.cd(1)->Modified();
0976       canvas.cd(1)->SetGrid();
0977 
0978       // for the "text"-filled histogram
0979       auto h2_SimBSParameters = std::make_unique<TH2F>("Parameters", "", 1, 0.0, 1.0, END_OF_TYPES, 0, END_OF_TYPES);
0980       h2_SimBSParameters->SetStats(false);
0981       h2_SimBSParameters->GetXaxis()->SetBinLabel(1, "Value");
0982       h2_SimBSParameters->GetXaxis()->LabelsOption("h");
0983       h2_SimBSParameters->GetYaxis()->SetLabelSize(0.05);
0984       h2_SimBSParameters->GetXaxis()->SetLabelSize(0.05);
0985       h2_SimBSParameters->SetMarkerSize(1.5);
0986 
0987       // prepare the arrays to fill the histogram
0988       simBeamSpotPI::SimBSParamsHelper fBS(f_payload);
0989       simBeamSpotPI::SimBSParamsHelper lBS(l_payload);
0990 
0991 #ifdef MM_DEBUG
0992       std::stringstream ss1, ss2;
0993       edm::LogPrint("") << "**** first payload";
0994       fBS.printDebug(ss1);
0995       edm::LogPrint("") << ss1.str();
0996       edm::LogPrint("") << "**** last payload";
0997       lBS.printDebug(ss2);
0998       edm::LogPrint("") << ss2.str();
0999 #endif
1000 
1001       const auto diffPars = fBS.diffCentralValues(lBS);
1002       //const auto pullPars = fBS.diffCentralValues(lBS,true /*normalize*/);
1003 
1004       unsigned int yBin = END_OF_TYPES;
1005       for (int foo = parameters::X; foo <= parameters::timeOffset; foo++) {
1006         parameters param = static_cast<parameters>(foo);
1007         std::string theLabel = simBeamSpotPI::getStringFromParamEnum(param, true /*use units*/);
1008         h2_SimBSParameters->GetYaxis()->SetBinLabel(yBin, theLabel.c_str());
1009         h2_SimBSParameters->SetBinContent(1, yBin, diffPars[foo]); /* profiting of the parameters enum indexing */
1010         yBin--;
1011       }
1012 
1013       // for the "colz"-filled histogram (clonde from the text-based one)
1014       auto h2_SimBSShadow = (TH2F*)(h2_SimBSParameters->Clone("shadow"));
1015       h2_SimBSShadow->GetZaxis()->SetTitle("#Delta Parameter(payload A - payload B)");
1016       h2_SimBSShadow->GetZaxis()->CenterTitle();
1017       h2_SimBSShadow->GetZaxis()->SetTitleOffset(1.5);
1018 
1019       // this is the fine gradient palette (blue to red)
1020       double max = h2_SimBSShadow->GetMaximum();
1021       double min = h2_SimBSShadow->GetMinimum();
1022       double val_white = 0.;
1023       double per_white = (max != min) ? ((val_white - min) / (max - min)) : 0.5;
1024 
1025       const int number = 3;
1026       double Red[number] = {0., 1., 1.};
1027       double Green[number] = {0., 1., 0.};
1028       double Blue[number] = {1., 1., 0.};
1029       double Stops[number] = {0., per_white, 1.};
1030       int nb = 256;
1031       h2_SimBSShadow->SetContour(nb);
1032       TColor::CreateGradientColorTable(number, Stops, Red, Green, Blue, nb);
1033 
1034       h2_SimBSShadow->Draw("colz");
1035       h2_SimBSParameters->Draw("TEXTsame");
1036 
1037       auto ltx = TLatex();
1038       ltx.SetTextFont(62);
1039       ltx.SetTextSize(0.025);
1040       ltx.SetTextAlign(11);
1041 
1042       // compute the (run,LS) pairs
1043       auto l_runLS = beamSpotPI::unpack(std::get<0>(lastiov));
1044       std::string l_runLSs = "(" + std::to_string(l_runLS.first) + "," + std::to_string(l_runLS.second) + ")";
1045       auto f_runLS = beamSpotPI::unpack(std::get<0>(firstiov));
1046       std::string f_runLSs = "(" + std::to_string(f_runLS.first) + "," + std::to_string(f_runLS.second) + ")";
1047 
1048       if (this->m_plotAnnotations.ntags == 2) {
1049         ltx.DrawLatexNDC(
1050             gPad->GetLeftMargin(),
1051             1 - gPad->GetTopMargin() + 0.025,
1052             (fmt::sprintf(
1053                  "#splitline{A = #color[4]{%s}: %s}{B = #color[4]{%s}: %s}", f_tagname, f_runLSs, l_tagname, l_runLSs))
1054                 .c_str());
1055       } else {
1056         ltx.DrawLatexNDC(
1057             gPad->GetLeftMargin(),
1058             1 - gPad->GetTopMargin() + 0.025,
1059             (fmt::sprintf("#splitline{#color[4]{%s}}{A = %s | B = %s}", f_tagname, l_runLSs, f_runLSs)).c_str());
1060       }
1061 
1062       std::string fileName(this->m_imageFileName);
1063       canvas.SaveAs(fileName.c_str());
1064 
1065       return true;
1066     }
1067 
1068   protected:
1069     std::shared_ptr<PayloadType> f_payload;
1070     std::shared_ptr<PayloadType> l_payload;
1071   };
1072 
1073 }  // namespace simBeamSpotPI
1074 
1075 #endif