Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-03-10 23:53:32

0001 #define __STDC_FORMAT_MACROS 1
0002 #include "DQMServices/Core/interface/MonitorElement.h"
0003 #include "TClass.h"
0004 #include "TMath.h"
0005 #include "TList.h"
0006 #include "THashList.h"
0007 #include <iostream>
0008 #include <cassert>
0009 #include <cfloat>
0010 #include <cinttypes>
0011 
0012 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0013 
0014 namespace dqm::impl {
0015 
0016   static TH1 *checkRootObject(const std::string &name, TObject *tobj, const char *func, int reqdim) {
0017     if (!tobj)
0018       throw cms::Exception("MonitorElementError") << "Method '" << func
0019                                                   << "' cannot be invoked on monitor"
0020                                                      " element '"
0021                                                   << name << "' because it is not a ROOT object.";
0022 
0023     auto *h = static_cast<TH1 *>(tobj);
0024     int ndim = h->GetDimension();
0025     if (reqdim < 0 || reqdim > ndim)
0026       throw cms::Exception("MonitorElementError") << "Method '" << func
0027                                                   << "' cannot be invoked on monitor"
0028                                                      " element '"
0029                                                   << name << "' because it requires " << reqdim
0030                                                   << " dimensions; this"
0031                                                      " object of type '"
0032                                                   << typeid(*h).name() << "' has " << ndim << " dimensions";
0033 
0034     return h;
0035   }
0036 
0037   MonitorElement::MonitorElement(MonitorElementData &&data) {
0038     this->mutable_ = std::make_shared<MutableMonitorElementData>();
0039     this->mutable_->data_ = std::move(data);
0040     syncCoreObject();
0041   }
0042   MonitorElement::MonitorElement(std::shared_ptr<MutableMonitorElementData> data) { switchData(std::move(data)); }
0043   MonitorElement::MonitorElement(MonitorElement *me) { switchData(me); }
0044 
0045   MonitorElementData MonitorElement::cloneMEData() {
0046     MonitorElementData out;
0047     auto access = this->access();
0048     out.key_ = access.key;
0049     out.value_.scalar_ = access.value.scalar_;
0050     if (access.value.object_) {
0051       out.value_.object_ = std::unique_ptr<TH1>(static_cast<TH1 *>(access.value.object_->Clone()));
0052     }
0053     return out;
0054   }
0055 
0056   std::shared_ptr<MutableMonitorElementData> MonitorElement::release() {
0057     auto data = this->mutable_;
0058     this->mutable_.reset();
0059     return data;
0060   }
0061 
0062   void MonitorElement::switchData(MonitorElement *other) {
0063     assert(other);
0064     this->mutable_ = other->mutable_;
0065     syncCoreObject();
0066   }
0067 
0068   void MonitorElement::switchData(std::shared_ptr<MutableMonitorElementData> data) {
0069     this->mutable_ = std::move(data);
0070     syncCoreObject();
0071   }
0072 
0073   void MonitorElement::switchObject(std::unique_ptr<TH1> &&newobject) {
0074     auto access = this->accessMut();
0075     // Assume kind etc. matches.
0076     // This should free the old object.
0077     access.value.object_ = std::move(newobject);
0078   }
0079 
0080   void MonitorElement::syncCoreObject() {
0081     auto access = this->accessMut();
0082     syncCoreObject(access);
0083   }
0084 
0085   void MonitorElement::syncCoreObject(AccessMut &access) {
0086     data_.flags &= ~DQMNet::DQM_PROP_TYPE_MASK;
0087     data_.flags |= (int)access.key.kind_;
0088 
0089     // mark as updated.
0090     data_.flags |= DQMNet::DQM_PROP_NEW;
0091 
0092     // lumi flag is approximately equivalent to Scope::LUMI.
0093     data_.flags &= ~DQMNet::DQM_PROP_LUMI;
0094     if (access.key.scope_ == MonitorElementData::Scope::LUMI) {
0095       data_.flags |= DQMNet::DQM_PROP_LUMI;
0096     }
0097 
0098     // these are unsupported and always off.
0099     data_.flags &= ~DQMNet::DQM_PROP_HAS_REFERENCE;
0100     data_.flags &= ~DQMNet::DQM_PROP_TAGGED;
0101     data_.flags &= ~DQMNet::DQM_PROP_RESET;
0102     data_.flags &= ~DQMNet::DQM_PROP_ACCUMULATE;
0103 
0104     // we use ROOT's internal efficiency flag as the truth
0105     data_.flags &= ~DQMNet::DQM_PROP_EFFICIENCY_PLOT;
0106     if (access.value.object_ && access.value.object_->TestBit(TH1::kIsAverage)) {
0107       data_.flags |= DQMNet::DQM_PROP_EFFICIENCY_PLOT;
0108     }
0109 
0110     data_.tag = 0;
0111 
0112     // don't touch version (a timestamp).
0113 
0114     // we could set proper values here, but nobody should use them.
0115     data_.run = 0;
0116     data_.lumi = 0;
0117 
0118     // these are relics from the threaded migration and should not be used anywhere.
0119     data_.streamId = 0;
0120     data_.moduleId = 0;
0121 
0122     // leaking a pointer here, but that should be fine.
0123     data_.dirname = access.key.path_.getDirname();
0124 
0125     data_.objname = access.key.path_.getObjectname();
0126 
0127     data_.flags &= ~DQMNet::DQM_PROP_REPORT_ALARM;
0128     data_.qreports.clear();
0129     for (QReport const &qr : access.value.qreports_) {
0130       data_.qreports.push_back(qr.getValue());
0131       switch (qr.getStatus()) {
0132         case dqm::qstatus::STATUS_OK:
0133           break;
0134         case dqm::qstatus::WARNING:
0135           data_.flags |= DQMNet::DQM_PROP_REPORT_WARN;
0136           break;
0137         case dqm::qstatus::ERROR:
0138           data_.flags |= DQMNet::DQM_PROP_REPORT_ERROR;
0139           break;
0140         default:
0141           data_.flags |= DQMNet::DQM_PROP_REPORT_OTHER;
0142           break;
0143       }
0144     }
0145   }
0146 
0147   MonitorElement::~MonitorElement() {}
0148 
0149   //utility function to check the consistency of the axis labels
0150   //taken from TH1::CheckBinLabels which is not public
0151   bool MonitorElement::CheckBinLabels(const TAxis *a1, const TAxis *a2) {
0152     // check that axis have same labels
0153     THashList *l1 = (const_cast<TAxis *>(a1))->GetLabels();
0154     THashList *l2 = (const_cast<TAxis *>(a2))->GetLabels();
0155 
0156     if (!l1 && !l2)
0157       return true;
0158     if (!l1 || !l2) {
0159       return false;
0160     }
0161     // check now labels sizes  are the same
0162     if (l1->GetSize() != l2->GetSize()) {
0163       return false;
0164     }
0165     for (int i = 1; i <= a1->GetNbins(); ++i) {
0166       TString label1 = a1->GetBinLabel(i);
0167       TString label2 = a2->GetBinLabel(i);
0168       if (label1 != label2) {
0169         return false;
0170       }
0171     }
0172     return true;
0173   }
0174 
0175   /// "Fill" ME methods for string
0176   void MonitorElement::Fill(std::string &value) {
0177     auto access = this->accessMut();
0178     update();
0179     if (kind() == Kind::STRING) {
0180       access.value.scalar_.str = value;
0181     } else {
0182       incompatible(__PRETTY_FUNCTION__);
0183     }
0184   }
0185 
0186   /// "Fill" ME methods for double
0187   void MonitorElement::Fill(double x) {
0188     auto access = this->accessMut();
0189     update();
0190     if (kind() == Kind::INT)
0191       access.value.scalar_.num = static_cast<int64_t>(x);
0192     else if (kind() == Kind::REAL)
0193       access.value.scalar_.real = x;
0194     else if (kind() == Kind::TH1F)
0195       accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, 1);
0196     else if (kind() == Kind::TH1S)
0197       accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, 1);
0198     else if (kind() == Kind::TH1I)
0199       accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, 1);
0200     else if (kind() == Kind::TH1D)
0201       accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, 1);
0202     else
0203       incompatible(__PRETTY_FUNCTION__);
0204   }
0205 
0206   /// "Fill" ME method for int64_t
0207   void MonitorElement::doFill(int64_t x) {
0208     auto access = this->accessMut();
0209     update();
0210     if (kind() == Kind::INT)
0211       access.value.scalar_.num = static_cast<int64_t>(x);
0212     else if (kind() == Kind::REAL)
0213       access.value.scalar_.real = static_cast<double>(x);
0214     else if (kind() == Kind::TH1F)
0215       accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(static_cast<double>(x), 1);
0216     else if (kind() == Kind::TH1S)
0217       accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(static_cast<double>(x), 1);
0218     else if (kind() == Kind::TH1I)
0219       accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(static_cast<double>(x), 1);
0220     else if (kind() == Kind::TH1D)
0221       accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(static_cast<double>(x), 1);
0222     else
0223       incompatible(__PRETTY_FUNCTION__);
0224   }
0225 
0226   /// can be used with 2D (x,y) or 1D (x, w) histograms
0227   void MonitorElement::Fill(double x, double yw) {
0228     auto access = this->accessMut();
0229     update();
0230     if (kind() == Kind::TH1F)
0231       accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, yw);
0232     else if (kind() == Kind::TH1S)
0233       accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, yw);
0234     else if (kind() == Kind::TH1D)
0235       accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, yw);
0236     else if (kind() == Kind::TH1I)
0237       accessRootObject(access, __PRETTY_FUNCTION__, 1)->Fill(x, yw);
0238     else if (kind() == Kind::TH2F)
0239       static_cast<TH2F *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, yw, 1);
0240     else if (kind() == Kind::TH2S)
0241       static_cast<TH2S *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, yw, 1);
0242     else if (kind() == Kind::TH2D)
0243       static_cast<TH2D *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, yw, 1);
0244     else if (kind() == Kind::TH2I)
0245       static_cast<TH2I *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, yw, 1);
0246     else if (kind() == Kind::TH2Poly)
0247       static_cast<TH2Poly *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, yw, 1);
0248     else if (kind() == Kind::TPROFILE)
0249       static_cast<TProfile *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->Fill(x, yw, 1);
0250     else
0251       incompatible(__PRETTY_FUNCTION__);
0252   }
0253 
0254   /// shift bin to the left and fill last bin with new entry
0255   /// 1st argument is y value, 2nd argument is y error (default 0)
0256   /// can be used with 1D or profile histograms only
0257   void MonitorElement::ShiftFillLast(double y, double ye, int xscale) {
0258     // TODO: this should take the lock only once to be actually safe.
0259     // But since it is not const, we don't even claim it is thread-safe.
0260     update();
0261     if (kind() == Kind::TH1F || kind() == Kind::TH1S || kind() == Kind::TH1D || kind() == Kind::TH1I) {
0262       int nbins = getNbinsX();
0263       auto entries = (int)getEntries();
0264       // first fill bins from left to right
0265       int index = entries + 1;
0266       int xlow = 2;
0267       int xup = nbins;
0268       // if more entries than bins then start shifting
0269       if (entries >= nbins) {
0270         index = nbins;
0271         xlow = entries - nbins + 3;
0272         xup = entries + 1;
0273         // average first bin
0274         double y1 = getBinContent(1);
0275         double y2 = getBinContent(2);
0276         double y1err = getBinError(1);
0277         double y2err = getBinError(2);
0278         double N = entries - nbins + 1.;
0279         if (ye == 0. || y1err == 0. || y2err == 0.) {
0280           // for errors zero calculate unweighted mean and its error
0281           double sum = N * y1 + y2;
0282           y1 = sum / (N + 1.);
0283           // FIXME check if correct
0284           double s = (N + 1.) * (N * y1 * y1 + y2 * y2) - sum * sum;
0285           if (s >= 0.)
0286             y1err = sqrt(s) / (N + 1.);
0287           else
0288             y1err = 0.;
0289         } else {
0290           // for errors non-zero calculate weighted mean and its error
0291           double denom = (1. / y1err + 1. / y2err);
0292           double mean = (y1 / y1err + y2 / y2err) / denom;
0293           // FIXME check if correct
0294           y1err = sqrt(((y1 - mean) * (y1 - mean) / y1err + (y2 - mean) * (y2 - mean) / y2err) / denom / 2.);
0295           y1 = mean;  // set y1 to mean for filling below
0296         }
0297         setBinContent(1, y1);
0298         setBinError(1, y1err);
0299         // shift remaining bins to the left
0300         for (int i = 3; i <= nbins; i++) {
0301           setBinContent(i - 1, getBinContent(i));
0302           setBinError(i - 1, getBinError(i));
0303         }
0304       }
0305       // fill last bin with new values
0306       setBinContent(index, y);
0307       setBinError(index, ye);
0308       // set entries
0309       setEntries(entries + 1);
0310       // set axis labels and reset drawing option
0311       char buffer[10];
0312       sprintf(buffer, "%d", xlow * xscale);
0313       std::string a(buffer);
0314       setBinLabel(2, a);
0315       sprintf(buffer, "%d", xup * xscale);
0316       std::string b(buffer);
0317       setBinLabel(nbins, b);
0318       setBinLabel(1, "av.");
0319     } else
0320       incompatible(__PRETTY_FUNCTION__);
0321   }
0322   /// can be used with 3D (x, y, z) or 2D (x, y, w) histograms
0323   void MonitorElement::Fill(double x, double y, double zw) {
0324     auto access = this->accessMut();
0325     update();
0326     if (kind() == Kind::TH2F)
0327       static_cast<TH2F *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, zw);
0328     else if (kind() == Kind::TH2S)
0329       static_cast<TH2S *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, zw);
0330     else if (kind() == Kind::TH2D)
0331       static_cast<TH2D *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, zw);
0332     else if (kind() == Kind::TH2I)
0333       static_cast<TH2I *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, zw);
0334     else if (kind() == Kind::TH2Poly)
0335       static_cast<TH2Poly *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, zw);
0336     else if (kind() == Kind::TH3F)
0337       static_cast<TH3F *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, zw, 1);
0338     else if (kind() == Kind::TPROFILE)
0339       static_cast<TProfile *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, zw);
0340     else if (kind() == Kind::TPROFILE2D)
0341       static_cast<TProfile2D *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, zw, 1);
0342     else
0343       incompatible(__PRETTY_FUNCTION__);
0344   }
0345 
0346   /// can be used with 3D (x, y, z, w) histograms
0347   void MonitorElement::Fill(double x, double y, double z, double w) {
0348     auto access = this->accessMut();
0349     update();
0350     if (kind() == Kind::TH3F)
0351       static_cast<TH3F *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, z, w);
0352     else if (kind() == Kind::TPROFILE2D)
0353       static_cast<TProfile2D *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->Fill(x, y, z, w);
0354     else
0355       incompatible(__PRETTY_FUNCTION__);
0356   }
0357 
0358   /// reset ME (ie. contents, errors, etc)
0359   void MonitorElement::Reset() {
0360     auto access = this->accessMut();
0361     update();
0362     if (kind() == Kind::INT)
0363       access.value.scalar_.num = 0;
0364     else if (kind() == Kind::REAL)
0365       access.value.scalar_.real = 0;
0366     else if (kind() == Kind::STRING)
0367       access.value.scalar_.str.clear();
0368     else if (kind() == Kind::TH1F)
0369       return accessRootObject(access, __PRETTY_FUNCTION__, 1)->Reset();
0370     else if (kind() == Kind::TH1S)
0371       return accessRootObject(access, __PRETTY_FUNCTION__, 1)->Reset();
0372     else if (kind() == Kind::TH1D)
0373       return accessRootObject(access, __PRETTY_FUNCTION__, 1)->Reset();
0374     else if (kind() == Kind::TH1I)
0375       return accessRootObject(access, __PRETTY_FUNCTION__, 1)->Reset();
0376     else if (kind() == Kind::TPROFILE)
0377       return accessRootObject(access, __PRETTY_FUNCTION__, 1)->Reset();
0378     else if (kind() == Kind::TH2F)
0379       return accessRootObject(access, __PRETTY_FUNCTION__, 2)->Reset();
0380     else if (kind() == Kind::TH2S)
0381       return accessRootObject(access, __PRETTY_FUNCTION__, 2)->Reset();
0382     else if (kind() == Kind::TH2D)
0383       return accessRootObject(access, __PRETTY_FUNCTION__, 2)->Reset();
0384     else if (kind() == Kind::TH2I)
0385       return accessRootObject(access, __PRETTY_FUNCTION__, 2)->Reset();
0386     else if (kind() == Kind::TH2Poly)
0387       return accessRootObject(access, __PRETTY_FUNCTION__, 2)->Reset();
0388     else if (kind() == Kind::TPROFILE2D)
0389       return accessRootObject(access, __PRETTY_FUNCTION__, 2)->Reset();
0390     else if (kind() == Kind::TH3F)
0391       return accessRootObject(access, __PRETTY_FUNCTION__, 3)->Reset();
0392     else
0393       incompatible(__PRETTY_FUNCTION__);
0394   }
0395 
0396   /// convert scalar data into a string.
0397   void MonitorElement::packScalarData(std::string &into, const char *prefix) const {
0398     auto access = this->access();
0399     char buf[64];
0400     if (kind() == Kind::INT) {
0401       snprintf(buf, sizeof(buf), "%s%" PRId64, prefix, access.value.scalar_.num);
0402       into = buf;
0403     } else if (kind() == Kind::REAL) {
0404       snprintf(buf, sizeof(buf), "%s%.*g", prefix, DBL_DIG + 2, access.value.scalar_.real);
0405       into = buf;
0406     } else if (kind() == Kind::STRING) {
0407       into.reserve(strlen(prefix) + access.value.scalar_.str.size());
0408       into += prefix;
0409       into += access.value.scalar_.str;
0410     } else
0411       incompatible(__PRETTY_FUNCTION__);
0412   }
0413 
0414   /// serialise quality report information into a string.
0415   void MonitorElement::packQualityData(std::string &into) const { DQMNet::packQualityData(into, data_.qreports); }
0416 
0417   /// returns value of ME in string format (eg. "f = 3.14151926" for double numbers);
0418   /// relevant only for scalar or string MEs
0419   std::string MonitorElement::valueString() const {
0420     std::string result;
0421     if (kind() == Kind::INT)
0422       packScalarData(result, "i=");
0423     else if (kind() == Kind::REAL)
0424       packScalarData(result, "f=");
0425     else if (kind() == Kind::STRING)
0426       packScalarData(result, "s=");
0427     else
0428       incompatible(__PRETTY_FUNCTION__);
0429 
0430     return result;
0431   }
0432 
0433   /// return tagged value of ME in string format
0434   /// (eg. <name>f=3.14151926</name> for double numbers);
0435   /// relevant only for sending scalar or string MEs over TSocket
0436   std::string MonitorElement::tagString() const {
0437     std::string result;
0438     std::string val(valueString());
0439     result.reserve(6 + 2 * data_.objname.size() + val.size());
0440     result += '<';
0441     result += data_.objname;
0442     result += '>';
0443     result += val;
0444     result += '<';
0445     result += '/';
0446     result += data_.objname;
0447     result += '>';
0448     return result;
0449   }
0450 
0451   /// return label string for the monitor element tag (eg. <name>t=12345</name>)
0452   std::string MonitorElement::tagLabelString() const {
0453     char buf[32];
0454     std::string result;
0455     size_t len = sprintf(buf, "t=%" PRIu32, data_.tag);
0456 
0457     result.reserve(6 + 2 * data_.objname.size() + len);
0458     result += '<';
0459     result += data_.objname;
0460     result += '>';
0461     result += buf;
0462     result += '<';
0463     result += '/';
0464     result += data_.objname;
0465     result += '>';
0466     return result;
0467   }
0468 
0469   /// return label string for the monitor element tag (eg. <name>t=12345</name>)
0470   std::string MonitorElement::effLabelString() const {
0471     std::string result;
0472 
0473     result.reserve(6 + 2 * data_.objname.size() + 3);
0474     result += '<';
0475     result += data_.objname;
0476     result += '>';
0477     result += "e=1";
0478     result += '<';
0479     result += '/';
0480     result += data_.objname;
0481     result += '>';
0482     return result;
0483   }
0484 
0485   std::string MonitorElement::qualityTagString(const DQMNet::QValue &qv) const {
0486     char buf[64];
0487     std::string result;
0488     size_t titlelen = data_.objname.size() + qv.qtname.size() + 1;
0489     size_t buflen = sprintf(buf, "qr=st:%d:%.*g:", qv.code, DBL_DIG + 2, qv.qtresult);
0490 
0491     result.reserve(7 + 2 * titlelen + buflen + qv.algorithm.size() + qv.message.size());
0492     result += '<';
0493     result += data_.objname;
0494     result += '.';
0495     result += qv.qtname;
0496     result += '>';
0497     result += buf;
0498     result += qv.algorithm;
0499     result += ':';
0500     result += qv.message;
0501     result += '<';
0502     result += '/';
0503     result += data_.objname;
0504     result += '.';
0505     result += qv.qtname;
0506     result += '>';
0507     return result;
0508   }
0509 
0510   const MonitorElementData::QReport *MonitorElement::getQReport(const std::string &qtname) const {
0511     MonitorElementData::MonitorElementData::QReport *qr;
0512     DQMNet::QValue *qv;
0513     const_cast<MonitorElement *>(this)->getQReport(false, qtname, qr, qv);
0514     return qr;
0515   }
0516 
0517   template <typename FILTER>
0518   std::vector<MonitorElementData::QReport *> MonitorElement::filterQReports(FILTER filter) const {
0519     auto access = this->access();
0520     std::vector<MonitorElementData::QReport *> result;
0521     for (MonitorElementData::QReport const &qr : access.value.qreports_) {
0522       if (filter(qr)) {
0523         // const_cast here because this API always violated cons'ness. Should
0524         // make the result type const and fix all usages.
0525         result.push_back(const_cast<MonitorElementData::QReport *>(&qr));
0526       }
0527     }
0528     return result;
0529   }
0530 
0531   std::vector<MonitorElementData::QReport *> MonitorElement::getQReports() const {
0532     return filterQReports([](MonitorElementData::QReport const &qr) { return true; });
0533   }
0534 
0535   std::vector<MonitorElementData::QReport *> MonitorElement::getQWarnings() const {
0536     return filterQReports(
0537         [](MonitorElementData::QReport const &qr) { return qr.getStatus() == dqm::qstatus::WARNING; });
0538   }
0539 
0540   std::vector<MonitorElementData::QReport *> MonitorElement::getQErrors() const {
0541     return filterQReports([](MonitorElementData::QReport const &qr) { return qr.getStatus() == dqm::qstatus::ERROR; });
0542   }
0543 
0544   std::vector<MonitorElementData::QReport *> MonitorElement::getQOthers() const {
0545     return filterQReports([](MonitorElementData::QReport const &qr) {
0546       return qr.getStatus() != dqm::qstatus::STATUS_OK && qr.getStatus() != dqm::qstatus::WARNING &&
0547              qr.getStatus() != dqm::qstatus::ERROR;
0548     });
0549   }
0550 
0551   void MonitorElement::incompatible(const char *func) const {
0552     throw cms::Exception("MonitorElementError") << "Method '" << func
0553                                                 << "' cannot be invoked on monitor"
0554                                                    " element '"
0555                                                 << data_.objname << "'";
0556   }
0557 
0558   TH1 const *MonitorElement::accessRootObject(Access const &access, const char *func, int reqdim) const {
0559     if (kind() < Kind::TH1F)
0560       throw cms::Exception("MonitorElement") << "Method '" << func
0561                                              << "' cannot be invoked on monitor"
0562                                                 " element '"
0563                                              << data_.objname << "' because it is not a root object";
0564     return access.value.object_.get();
0565   }
0566   TH1 *MonitorElement::accessRootObject(AccessMut const &access, const char *func, int reqdim) const {
0567     if (kind() < Kind::TH1F)
0568       throw cms::Exception("MonitorElement") << "Method '" << func
0569                                              << "' cannot be invoked on monitor"
0570                                                 " element '"
0571                                              << data_.objname << "' because it is not a root object";
0572     return checkRootObject(data_.objname, access.value.object_.get(), func, reqdim);
0573   }
0574 
0575   /*** getter methods (wrapper around ROOT methods) ****/
0576   //
0577   /// get mean value of histogram along x, y or z axis (axis=1, 2, 3 respectively)
0578   double MonitorElement::getMean(int axis /* = 1 */) const {
0579     auto access = this->access();
0580     return accessRootObject(access, __PRETTY_FUNCTION__, axis - 1)->GetMean(axis);
0581   }
0582 
0583   /// get mean value uncertainty of histogram along x, y or z axis
0584   /// (axis=1, 2, 3 respectively)
0585   double MonitorElement::getMeanError(int axis /* = 1 */) const {
0586     auto access = this->access();
0587     return accessRootObject(access, __PRETTY_FUNCTION__, axis - 1)->GetMeanError(axis);
0588   }
0589 
0590   /// get RMS of histogram along x, y or z axis (axis=1, 2, 3 respectively)
0591   double MonitorElement::getRMS(int axis /* = 1 */) const {
0592     auto access = this->access();
0593     return accessRootObject(access, __PRETTY_FUNCTION__, axis - 1)->GetRMS(axis);
0594   }
0595 
0596   /// get RMS uncertainty of histogram along x, y or z axis(axis=1,2,3 respectively)
0597   double MonitorElement::getRMSError(int axis /* = 1 */) const {
0598     auto access = this->access();
0599     return accessRootObject(access, __PRETTY_FUNCTION__, axis - 1)->GetRMSError(axis);
0600   }
0601 
0602   /// get # of bins in X-axis
0603   int MonitorElement::getNbinsX() const {
0604     auto access = this->access();
0605     return accessRootObject(access, __PRETTY_FUNCTION__, 1)->GetNbinsX();
0606   }
0607 
0608   /// get # of bins in Y-axis
0609   int MonitorElement::getNbinsY() const {
0610     auto access = this->access();
0611     return accessRootObject(access, __PRETTY_FUNCTION__, 2)->GetNbinsY();
0612   }
0613 
0614   /// get # of bins in Z-axis
0615   int MonitorElement::getNbinsZ() const {
0616     auto access = this->access();
0617     return accessRootObject(access, __PRETTY_FUNCTION__, 3)->GetNbinsZ();
0618   }
0619 
0620   /// get content of bin (1-D)
0621   double MonitorElement::getBinContent(int binx) const {
0622     auto access = this->access();
0623     return accessRootObject(access, __PRETTY_FUNCTION__, 1)->GetBinContent(binx);
0624   }
0625 
0626   /// get content of bin (2-D)
0627   double MonitorElement::getBinContent(int binx, int biny) const {
0628     auto access = this->access();
0629     return accessRootObject(access, __PRETTY_FUNCTION__, 2)->GetBinContent(binx, biny);
0630   }
0631 
0632   /// get content of bin (3-D)
0633   double MonitorElement::getBinContent(int binx, int biny, int binz) const {
0634     auto access = this->access();
0635     return accessRootObject(access, __PRETTY_FUNCTION__, 3)->GetBinContent(binx, biny, binz);
0636   }
0637 
0638   /// get uncertainty on content of bin (1-D) - See TH1::GetBinError for details
0639   double MonitorElement::getBinError(int binx) const {
0640     auto access = this->access();
0641     return accessRootObject(access, __PRETTY_FUNCTION__, 1)->GetBinError(binx);
0642   }
0643 
0644   /// get uncertainty on content of bin (2-D) - See TH1::GetBinError for details
0645   double MonitorElement::getBinError(int binx, int biny) const {
0646     auto access = this->access();
0647     return accessRootObject(access, __PRETTY_FUNCTION__, 2)->GetBinError(binx, biny);
0648   }
0649 
0650   /// get uncertainty on content of bin (3-D) - See TH1::GetBinError for details
0651   double MonitorElement::getBinError(int binx, int biny, int binz) const {
0652     auto access = this->access();
0653     return accessRootObject(access, __PRETTY_FUNCTION__, 3)->GetBinError(binx, biny, binz);
0654   }
0655 
0656   /// get # of entries
0657   double MonitorElement::getEntries() const {
0658     auto access = this->access();
0659     return accessRootObject(access, __PRETTY_FUNCTION__, 1)->GetEntries();
0660   }
0661 
0662   /// get global bin number (for 2-D profiles)
0663   int MonitorElement::getBin(int binx, int biny) const {
0664     auto access = this->access();
0665     if (kind() == Kind::TPROFILE2D)
0666       return static_cast<TProfile2D const *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->GetBin(binx, biny);
0667     else {
0668       incompatible(__PRETTY_FUNCTION__);
0669       return 0;
0670     }
0671   }
0672 
0673   // Returns number of cells (9 indicates empty TH2Poly without user-defined bins)
0674   int MonitorElement::getNcells() const {
0675     auto access = this->access();
0676     if (kind() == Kind::TH1F)
0677       return accessRootObject(access, __PRETTY_FUNCTION__, 1)->GetNcells();
0678     else if (kind() == Kind::TH1S)
0679       return accessRootObject(access, __PRETTY_FUNCTION__, 1)->GetNcells();
0680     else if (kind() == Kind::TH1D)
0681       return accessRootObject(access, __PRETTY_FUNCTION__, 1)->GetNcells();
0682     else if (kind() == Kind::TH1I)
0683       return accessRootObject(access, __PRETTY_FUNCTION__, 1)->GetNcells();
0684     else if (kind() == Kind::TPROFILE)
0685       return accessRootObject(access, __PRETTY_FUNCTION__, 1)->GetNcells();
0686     else if (kind() == Kind::TH2F)
0687       return accessRootObject(access, __PRETTY_FUNCTION__, 2)->GetNcells();
0688     else if (kind() == Kind::TH2S)
0689       return accessRootObject(access, __PRETTY_FUNCTION__, 2)->GetNcells();
0690     else if (kind() == Kind::TH2D)
0691       return accessRootObject(access, __PRETTY_FUNCTION__, 2)->GetNcells();
0692     else if (kind() == Kind::TH2I)
0693       return accessRootObject(access, __PRETTY_FUNCTION__, 2)->GetNcells();
0694     else if (kind() == Kind::TH2Poly)
0695       return accessRootObject(access, __PRETTY_FUNCTION__, 2)->GetNcells();
0696     else if (kind() == Kind::TPROFILE2D)
0697       return accessRootObject(access, __PRETTY_FUNCTION__, 2)->GetNcells();
0698     else if (kind() == Kind::TH3F)
0699       return accessRootObject(access, __PRETTY_FUNCTION__, 3)->GetNcells();
0700     else {
0701       incompatible(__PRETTY_FUNCTION__);
0702       return 0;
0703     }
0704   }
0705 
0706   /// get # of bin entries (for profiles)
0707   double MonitorElement::getBinEntries(int bin) const {
0708     auto access = this->access();
0709     if (kind() == Kind::TPROFILE)
0710       return static_cast<TProfile const *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->GetBinEntries(bin);
0711     else if (kind() == Kind::TPROFILE2D)
0712       return static_cast<TProfile2D const *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->GetBinEntries(bin);
0713     else {
0714       incompatible(__PRETTY_FUNCTION__);
0715       return 0;
0716     }
0717   }
0718 
0719   /// get # of bin entries (for 2-D profiles)
0720   double MonitorElement::getBinEntries(int binx, int biny) const {
0721     auto access = this->access();
0722     if (kind() == Kind::TPROFILE2D) {
0723       int globBin =
0724           static_cast<TProfile2D const *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->GetBin(binx, biny);
0725       return static_cast<TProfile2D const *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->GetBinEntries(globBin);
0726     } else {
0727       incompatible(__PRETTY_FUNCTION__);
0728       return 0;
0729     }
0730   }
0731 
0732   /// get integral of bins
0733   double MonitorElement::integral() const {
0734     auto access = this->access();
0735     return accessRootObject(access, __PRETTY_FUNCTION__, 1)->Integral();
0736   }
0737 
0738   /// get x-, y- or z-axis title (axis=1, 2, 3 respectively)
0739   std::string MonitorElement::getAxisTitle(int axis /* = 1 */) const {
0740     auto access = this->access();
0741     return getAxis(access, __PRETTY_FUNCTION__, axis)->GetTitle();
0742   }
0743 
0744   /// get MonitorElement title
0745   std::string MonitorElement::getTitle() const {
0746     auto access = this->access();
0747     return accessRootObject(access, __PRETTY_FUNCTION__, 1)->GetTitle();
0748   }
0749 
0750   /*** setter methods (wrapper around ROOT methods) ****/
0751 
0752   // Add a polygonal bin to a TH2Poly histogram through TGraph
0753   void MonitorElement::addBin(TGraph *graph) {
0754     auto access = this->accessMut();
0755     if (kind() == Kind::TH2Poly) {
0756       static_cast<TH2Poly *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->AddBin(graph);
0757     } else {
0758       incompatible(__PRETTY_FUNCTION__);
0759     }
0760   }
0761 
0762   // Add a polygonal bin to a TH2Poly histogram through arrays
0763   void MonitorElement::addBin(int n, const double *x, const double *y) {
0764     auto access = this->accessMut();
0765     if (kind() == Kind::TH2Poly) {
0766       static_cast<TH2Poly *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->AddBin(n, x, y);
0767     } else {
0768       incompatible(__PRETTY_FUNCTION__);
0769     }
0770   }
0771 
0772   // Add a rectangular bin to a TH2Poly histogram
0773   void MonitorElement::addBin(double x1, double y1, double x2, double y2) {
0774     auto access = this->accessMut();
0775     if (kind() == Kind::TH2Poly) {
0776       static_cast<TH2Poly *>(accessRootObject(access, __PRETTY_FUNCTION__, 2))->AddBin(x1, y1, x2, y2);
0777     } else {
0778       incompatible(__PRETTY_FUNCTION__);
0779     }
0780   }
0781 
0782   /// set content of bin (1-D)
0783   void MonitorElement::setBinContent(int binx, double content) {
0784     auto access = this->accessMut();
0785     accessRootObject(access, __PRETTY_FUNCTION__, 1)->SetBinContent(binx, content);
0786   }
0787 
0788   /// set content of bin (2-D)
0789   void MonitorElement::setBinContent(int binx, int biny, double content) {
0790     auto access = this->accessMut();
0791     accessRootObject(access, __PRETTY_FUNCTION__, 2)->SetBinContent(binx, biny, content);
0792   }
0793 
0794   /// set content of bin (3-D)
0795   void MonitorElement::setBinContent(int binx, int biny, int binz, double content) {
0796     auto access = this->accessMut();
0797     accessRootObject(access, __PRETTY_FUNCTION__, 3)->SetBinContent(binx, biny, binz, content);
0798   }
0799 
0800   /// set uncertainty on content of bin (1-D)
0801   void MonitorElement::setBinError(int binx, double error) {
0802     auto access = this->accessMut();
0803     accessRootObject(access, __PRETTY_FUNCTION__, 1)->SetBinError(binx, error);
0804   }
0805 
0806   /// set uncertainty on content of bin (2-D)
0807   void MonitorElement::setBinError(int binx, int biny, double error) {
0808     auto access = this->accessMut();
0809     accessRootObject(access, __PRETTY_FUNCTION__, 2)->SetBinError(binx, biny, error);
0810   }
0811 
0812   /// set uncertainty on content of bin (3-D)
0813   void MonitorElement::setBinError(int binx, int biny, int binz, double error) {
0814     auto access = this->accessMut();
0815     accessRootObject(access, __PRETTY_FUNCTION__, 3)->SetBinError(binx, biny, binz, error);
0816   }
0817 
0818   /// set # of bin entries (to be used for profiles)
0819   void MonitorElement::setBinEntries(int bin, double nentries) {
0820     auto access = this->accessMut();
0821     if (kind() == Kind::TPROFILE)
0822       static_cast<TProfile *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->SetBinEntries(bin, nentries);
0823     else if (kind() == Kind::TPROFILE2D)
0824       static_cast<TProfile2D *>(accessRootObject(access, __PRETTY_FUNCTION__, 1))->SetBinEntries(bin, nentries);
0825     else
0826       incompatible(__PRETTY_FUNCTION__);
0827   }
0828 
0829   /// set # of entries
0830   void MonitorElement::setEntries(double nentries) {
0831     auto access = this->accessMut();
0832     accessRootObject(access, __PRETTY_FUNCTION__, 1)->SetEntries(nentries);
0833   }
0834 
0835   /// Replace entries with results of dividing num by denom
0836   void MonitorElement::divide(
0837       const MonitorElement *num, const MonitorElement *denom, double c1, double c2, const char *options) {
0838     if (num->kind() < Kind::TH1F)
0839       num->incompatible(__PRETTY_FUNCTION__);
0840     if (denom->kind() < Kind::TH1F)
0841       denom->incompatible(__PRETTY_FUNCTION__);
0842 
0843     TH1 const *numH = static_cast<TH1 const *>(num->getRootObject());
0844     TH1 const *denomH = static_cast<TH1 const *>(denom->getRootObject());
0845     TH1 *thisH = getTH1();
0846 
0847     //Need to take locks in a consistent order to avoid deadlocks. Use pointer value order of underlying ROOT object..
0848     //This is known as the monitor pattern.
0849     std::array<const MonitorElement *, 3> order{{this, num, denom}};
0850     std::sort(order.begin(), order.end(), [](auto const *lhs, auto const *rhs) {
0851       return lhs->mutable_->data_.value_.object_.get() < rhs->mutable_->data_.value_.object_.get();
0852     });
0853 
0854     auto a0 = order[0]->access();
0855     auto a1 = order[1]->access();
0856     auto a2 = order[2]->access();
0857 
0858     //Have ROOT do check that the types are compatible
0859     thisH->Divide(numH, denomH, c1, c2, options);
0860   }
0861 
0862   /// set bin label for x, y or z axis (axis=1, 2, 3 respectively)
0863   void MonitorElement::setBinLabel(int bin, const std::string &label, int axis /* = 1 */) {
0864     bool fail = false;
0865     {
0866       auto access = this->accessMut();
0867       update();
0868       if (getAxis(access, __PRETTY_FUNCTION__, axis)->GetNbins() >= bin) {
0869         getAxis(access, __PRETTY_FUNCTION__, axis)->SetBinLabel(bin, label.c_str());
0870       } else {
0871         fail = true;
0872       }
0873     }
0874     // do this with the ME lock released to prevent a deadlock
0875     if (fail) {
0876       // this also takes the lock, make sure to release it before going to edm
0877       // (which might take more locks)
0878       auto name = getFullname();
0879       edm::LogWarning("MonitorElement") << "*** MonitorElement: WARNING:"
0880                                         << "setBinLabel: attempting to set label of non-existent bin number for ME: "
0881                                         << name << " \n";
0882     }
0883   }
0884 
0885   /// set x-, y- or z-axis range (axis=1, 2, 3 respectively)
0886   void MonitorElement::setAxisRange(double xmin, double xmax, int axis /* = 1 */) {
0887     auto access = this->accessMut();
0888     getAxis(access, __PRETTY_FUNCTION__, axis)->SetRangeUser(xmin, xmax);
0889   }
0890 
0891   /// set x-, y- or z-axis title (axis=1, 2, 3 respectively)
0892   void MonitorElement::setAxisTitle(const std::string &title, int axis /* = 1 */) {
0893     auto access = this->accessMut();
0894     getAxis(access, __PRETTY_FUNCTION__, axis)->SetTitle(title.c_str());
0895   }
0896 
0897   /// set x-, y-, or z-axis to display time values
0898   void MonitorElement::setAxisTimeDisplay(int value, int axis /* = 1 */) {
0899     auto access = this->accessMut();
0900     getAxis(access, __PRETTY_FUNCTION__, axis)->SetTimeDisplay(value);
0901   }
0902 
0903   /// set the format of the time values that are displayed on an axis
0904   void MonitorElement::setAxisTimeFormat(const char *format /* = "" */, int axis /* = 1 */) {
0905     auto access = this->accessMut();
0906     getAxis(access, __PRETTY_FUNCTION__, axis)->SetTimeFormat(format);
0907   }
0908 
0909   /// set (ie. change) histogram/profile title
0910   void MonitorElement::setTitle(const std::string &title) {
0911     auto access = this->accessMut();
0912     accessRootObject(access, __PRETTY_FUNCTION__, 1)->SetTitle(title.c_str());
0913   }
0914 
0915   TAxis *MonitorElement::getAxis(AccessMut const &access, const char *func, int axis) const {
0916     TH1 *h = accessRootObject(access, func, axis - 1);
0917     TAxis *a = nullptr;
0918     if (axis == 1)
0919       a = h->GetXaxis();
0920     else if (axis == 2)
0921       a = h->GetYaxis();
0922     else if (axis == 3)
0923       a = h->GetZaxis();
0924 
0925     if (!a)
0926       throw cms::Exception("MonitorElementError") << "No such axis " << axis
0927                                                   << " in monitor element"
0928                                                      " '"
0929                                                   << data_.objname << "' of type '" << typeid(*h).name() << "'";
0930 
0931     return a;
0932   }
0933 
0934   TAxis const *MonitorElement::getAxis(Access const &access, const char *func, int axis) const {
0935     TH1 const *h = accessRootObject(access, func, axis - 1);
0936     TAxis const *a = nullptr;
0937     if (axis == 1)
0938       a = h->GetXaxis();
0939     else if (axis == 2)
0940       a = h->GetYaxis();
0941     else if (axis == 3)
0942       a = h->GetZaxis();
0943 
0944     if (!a)
0945       throw cms::Exception("MonitorElementError") << "No such axis " << axis
0946                                                   << " in monitor element"
0947                                                      " '"
0948                                                   << data_.objname << "' of type '" << typeid(*h).name() << "'";
0949 
0950     return a;
0951   }
0952 
0953   void MonitorElement::setXTitle(std::string const &title) {
0954     auto access = this->accessMut();
0955     update();
0956     access.value.object_->SetXTitle(title.c_str());
0957   }
0958   void MonitorElement::setYTitle(std::string const &title) {
0959     auto access = this->accessMut();
0960     update();
0961     access.value.object_->SetYTitle(title.c_str());
0962   }
0963 
0964   void MonitorElement::enableSumw2() {
0965     auto access = this->accessMut();
0966     update();
0967     if (access.value.object_->GetSumw2() == nullptr) {
0968       access.value.object_->Sumw2();
0969     }
0970   }
0971 
0972   void MonitorElement::disableAlphanumeric() {
0973     auto access = this->accessMut();
0974     update();
0975     access.value.object_->GetXaxis()->SetNoAlphanumeric(false);
0976     access.value.object_->GetYaxis()->SetNoAlphanumeric(false);
0977   }
0978 
0979   void MonitorElement::setOption(const char *option) {
0980     auto access = this->accessMut();
0981     update();
0982     access.value.object_->SetOption(option);
0983   }
0984   double MonitorElement::getAxisMin(int axis) const {
0985     auto access = this->access();
0986     return getAxis(access, __PRETTY_FUNCTION__, axis)->GetXmin();
0987   }
0988 
0989   double MonitorElement::getAxisMax(int axis) const {
0990     auto access = this->access();
0991     return getAxis(access, __PRETTY_FUNCTION__, axis)->GetXmax();
0992   }
0993 
0994   void MonitorElement::setCanExtend(unsigned int value) {
0995     auto access = this->accessMut();
0996     access.value.object_->SetCanExtend(value);
0997   }
0998 
0999   void MonitorElement::setStatOverflows(bool value) {
1000     auto access = this->accessMut();
1001     if (value == kTRUE)
1002       access.value.object_->SetStatOverflows(TH1::kConsider);
1003     else
1004       access.value.object_->SetStatOverflows(TH1::kIgnore);
1005   }
1006 
1007   bool MonitorElement::getStatOverflows() {
1008     auto access = this->accessMut();
1009     auto value = access.value.object_->GetStatOverflows();
1010     if (value == TH1::kConsider)
1011       return true;
1012     else
1013       return false;
1014   }
1015 
1016   int64_t MonitorElement::getIntValue() const {
1017     assert(kind() == Kind::INT);
1018     auto access = this->access();
1019     return access.value.scalar_.num;
1020   }
1021   double MonitorElement::getFloatValue() const {
1022     assert(kind() == Kind::REAL);
1023     auto access = this->access();
1024     return access.value.scalar_.real;
1025   }
1026   const std::string &MonitorElement::getStringValue() const {
1027     assert(kind() == Kind::STRING);
1028     auto access = this->access();
1029     return access.value.scalar_.str;
1030   }
1031 
1032   void MonitorElement::getQReport(bool create,
1033                                   const std::string &qtname,
1034                                   MonitorElementData::QReport *&qr,
1035                                   DQMNet::QValue *&qv) {
1036     auto access = this->accessMut();
1037 
1038     syncCoreObject(access);
1039 
1040     assert(access.value.qreports_.size() == data_.qreports.size());
1041 
1042     qr = nullptr;
1043     qv = nullptr;
1044 
1045     size_t pos = 0, end = access.value.qreports_.size();
1046     while (pos < end && data_.qreports[pos].qtname != qtname)
1047       ++pos;
1048 
1049     if (pos == end && !create)
1050       return;
1051     else if (pos == end) {
1052       DQMNet::QValue q;
1053       q.code = dqm::qstatus::DID_NOT_RUN;
1054       q.qtresult = 0;
1055       q.qtname = qtname;
1056       q.message = "NO_MESSAGE_ASSIGNED";
1057       q.algorithm = "UNKNOWN_ALGORITHM";
1058       access.value.qreports_.push_back(MonitorElementData::QReport(q));
1059       syncCoreObject(access);
1060     }
1061 
1062     qr = &access.value.qreports_[pos];
1063     qv = &(qr->getValue());
1064   }
1065 
1066   // -------------------------------------------------------------------
1067   // TODO: all of these are UNSAFE and have to be NON-const.
1068   TObject const *MonitorElement::getRootObject() const {
1069     auto access = this->access();
1070     return access.value.object_.get();
1071   }
1072 
1073   TH1 *MonitorElement::getTH1() {
1074     auto access = this->accessMut();
1075     return accessRootObject(access, __PRETTY_FUNCTION__, 0);
1076   }
1077 
1078   TH1F *MonitorElement::getTH1F() {
1079     auto access = this->accessMut();
1080     assert(kind() == Kind::TH1F);
1081     return static_cast<TH1F *>(accessRootObject(access, __PRETTY_FUNCTION__, 1));
1082   }
1083 
1084   TH1S *MonitorElement::getTH1S() {
1085     auto access = this->accessMut();
1086     assert(kind() == Kind::TH1S);
1087     return static_cast<TH1S *>(accessRootObject(access, __PRETTY_FUNCTION__, 1));
1088   }
1089 
1090   TH1I *MonitorElement::getTH1I() {
1091     auto access = this->accessMut();
1092     assert(kind() == Kind::TH1I);
1093     return static_cast<TH1I *>(accessRootObject(access, __PRETTY_FUNCTION__, 1));
1094   }
1095 
1096   TH1D *MonitorElement::getTH1D() {
1097     auto access = this->accessMut();
1098     assert(kind() == Kind::TH1D);
1099     return static_cast<TH1D *>(accessRootObject(access, __PRETTY_FUNCTION__, 1));
1100   }
1101 
1102   TH2F *MonitorElement::getTH2F() {
1103     auto access = this->accessMut();
1104     assert(kind() == Kind::TH2F);
1105     return static_cast<TH2F *>(accessRootObject(access, __PRETTY_FUNCTION__, 2));
1106   }
1107 
1108   TH2S *MonitorElement::getTH2S() {
1109     auto access = this->accessMut();
1110     assert(kind() == Kind::TH2S);
1111     return static_cast<TH2S *>(accessRootObject(access, __PRETTY_FUNCTION__, 2));
1112   }
1113 
1114   TH2I *MonitorElement::getTH2I() {
1115     auto access = this->accessMut();
1116     assert(kind() == Kind::TH2I);
1117     return static_cast<TH2I *>(accessRootObject(access, __PRETTY_FUNCTION__, 2));
1118   }
1119 
1120   TH2D *MonitorElement::getTH2D() {
1121     auto access = this->accessMut();
1122     assert(kind() == Kind::TH2D);
1123     return static_cast<TH2D *>(accessRootObject(access, __PRETTY_FUNCTION__, 2));
1124   }
1125 
1126   TH2Poly *MonitorElement::getTH2Poly() {
1127     auto access = this->accessMut();
1128     assert(kind() == Kind::TH2Poly);
1129     return static_cast<TH2Poly *>(accessRootObject(access, __PRETTY_FUNCTION__, 2));
1130   }
1131 
1132   TH3F *MonitorElement::getTH3F() {
1133     auto access = this->accessMut();
1134     assert(kind() == Kind::TH3F);
1135     return static_cast<TH3F *>(accessRootObject(access, __PRETTY_FUNCTION__, 3));
1136   }
1137 
1138   TProfile *MonitorElement::getTProfile() {
1139     auto access = this->accessMut();
1140     assert(kind() == Kind::TPROFILE);
1141     return static_cast<TProfile *>(accessRootObject(access, __PRETTY_FUNCTION__, 1));
1142   }
1143 
1144   TProfile2D *MonitorElement::getTProfile2D() {
1145     auto access = this->accessMut();
1146     assert(kind() == Kind::TPROFILE2D);
1147     return static_cast<TProfile2D *>(accessRootObject(access, __PRETTY_FUNCTION__, 2));
1148   }
1149 
1150 }  // namespace dqm::impl