Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:07:14

0001 #include "DQM/EcalCommon/interface/MESetEcal.h"
0002 
0003 #include "DQM/EcalCommon/interface/EcalDQMCommonUtils.h"
0004 #include "DQM/EcalCommon/interface/MESetUtils.h"
0005 
0006 #include <limits>
0007 #include <sstream>
0008 
0009 namespace ecaldqm {
0010   MESetEcal::MESetEcal(std::string const &_fullPath,
0011                        binning::ObjectType _otype,
0012                        binning::BinningType _btype,
0013                        MonitorElement::Kind _kind,
0014                        unsigned _logicalDimensions,
0015                        binning::AxisSpecs const *_xaxis /* = 0*/,
0016                        binning::AxisSpecs const *_yaxis /* = 0*/,
0017                        binning::AxisSpecs const *_zaxis /* = 0*/)
0018       : MESet(_fullPath, _otype, _btype, _kind),
0019         logicalDimensions_(_logicalDimensions),
0020         xaxis_(_xaxis ? new binning::AxisSpecs(*_xaxis) : nullptr),
0021         yaxis_(_yaxis ? new binning::AxisSpecs(*_yaxis) : nullptr),
0022         zaxis_(_zaxis ? new binning::AxisSpecs(*_zaxis) : nullptr) {
0023     if (btype_ == binning::kUser && ((logicalDimensions_ > 0 && !xaxis_) || (logicalDimensions_ > 1 && !yaxis_)))
0024       throw_("Need axis specifications");
0025   }
0026 
0027   MESetEcal::MESetEcal(MESetEcal const &_orig)
0028       : MESet(_orig),
0029         logicalDimensions_(_orig.logicalDimensions_),
0030         xaxis_(_orig.xaxis_ ? new binning::AxisSpecs(*_orig.xaxis_) : nullptr),
0031         yaxis_(_orig.yaxis_ ? new binning::AxisSpecs(*_orig.yaxis_) : nullptr),
0032         zaxis_(_orig.zaxis_ ? new binning::AxisSpecs(*_orig.zaxis_) : nullptr) {}
0033 
0034   MESetEcal::~MESetEcal() {
0035     delete xaxis_;
0036     delete yaxis_;
0037     delete zaxis_;
0038   }
0039 
0040   MESet &MESetEcal::operator=(MESet const &_rhs) {
0041     delete xaxis_;
0042     delete yaxis_;
0043     delete zaxis_;
0044     xaxis_ = nullptr;
0045     yaxis_ = nullptr;
0046     zaxis_ = nullptr;
0047 
0048     MESetEcal const *pRhs(dynamic_cast<MESetEcal const *>(&_rhs));
0049     if (pRhs) {
0050       logicalDimensions_ = pRhs->logicalDimensions_;
0051       if (pRhs->xaxis_)
0052         xaxis_ = new binning::AxisSpecs(*pRhs->xaxis_);
0053       if (pRhs->yaxis_)
0054         yaxis_ = new binning::AxisSpecs(*pRhs->yaxis_);
0055       if (pRhs->zaxis_)
0056         zaxis_ = new binning::AxisSpecs(*pRhs->zaxis_);
0057     }
0058     return MESet::operator=(_rhs);
0059   }
0060 
0061   MESet *MESetEcal::clone(std::string const &_path /* = ""*/) const {
0062     std::string path(path_);
0063     if (!_path.empty())
0064       path_ = _path;
0065     MESet *copy(new MESetEcal(*this));
0066     path_ = path;
0067     return copy;
0068   }
0069 
0070   void MESetEcal::book(DQMStore::IBooker &_ibooker, EcalElectronicsMapping const *electronicsMap) {
0071     using namespace std;
0072 
0073     auto oldscope = MonitorElementData::Scope::RUN;
0074     if (lumiFlag_)
0075       oldscope = _ibooker.setScope(MonitorElementData::Scope::LUMI);
0076 
0077     clear();
0078 
0079     vector<string> mePaths(generatePaths(electronicsMap));
0080 
0081     for (unsigned iME(0); iME < mePaths.size(); iME++) {
0082       string &path(mePaths[iME]);
0083       if (path.find('%') != string::npos)
0084         throw_("book() called with incompletely formed path [" + path + "]");
0085 
0086       binning::ObjectType actualObject(binning::getObject(otype_, iME));
0087 
0088       binning::AxisSpecs xaxis, yaxis, zaxis;
0089 
0090       bool isHistogram(logicalDimensions_ > 0);
0091       bool isMap(logicalDimensions_ > 1);
0092 
0093       if (isHistogram) {
0094         if (xaxis_)
0095           xaxis = *xaxis_;
0096         if (yaxis_)
0097           yaxis = *yaxis_;
0098         if (zaxis_)
0099           zaxis = *zaxis_;
0100 
0101         if (xaxis.nbins == 0) {  // uses preset
0102           binning::AxisSpecs xdef(binning::getBinning(electronicsMap, actualObject, btype_, isMap, 1, iME));
0103           if (!xaxis.labels.empty() || !xaxis.title.empty()) {  // PSet specifies title / label only
0104             std::vector<string> labels(xaxis.labels);
0105             std::string title(xaxis.title);
0106             xaxis = xdef;
0107             xaxis.labels = labels;
0108             xaxis.title = title;
0109           } else
0110             xaxis = xdef;
0111         }
0112 
0113         if (isMap && yaxis.nbins == 0) {
0114           binning::AxisSpecs ydef(binning::getBinning(electronicsMap, actualObject, btype_, isMap, 2, iME));
0115           if (!yaxis.labels.empty() || !yaxis.title.empty()) {  // PSet specifies title / label only
0116             std::vector<string> labels(yaxis.labels);
0117             std::string title(yaxis.title);
0118             yaxis = ydef;
0119             yaxis.labels = labels;
0120             yaxis.title = title;
0121           } else
0122             yaxis = ydef;
0123         }
0124 
0125         if (yaxis.high - yaxis.low < 1.e-10) {
0126           yaxis.low = -numeric_limits<double>::max();
0127           yaxis.high = numeric_limits<double>::max();
0128         }
0129 
0130         if (zaxis.high - zaxis.low < 1.e-10) {
0131           zaxis.low = -numeric_limits<double>::max();
0132           zaxis.high = numeric_limits<double>::max();
0133         }
0134       }
0135 
0136       size_t slashPos(path.find_last_of('/'));
0137       string name(path.substr(slashPos + 1));
0138       _ibooker.cd();
0139       _ibooker.setCurrentFolder(path.substr(0, slashPos));
0140 
0141       MonitorElement *me(nullptr);
0142 
0143       switch (kind_) {
0144         case MonitorElement::Kind::REAL:
0145           me = _ibooker.bookFloat(name);
0146 
0147           break;
0148 
0149         case MonitorElement::Kind::TH1F:
0150           if (xaxis.edges.empty())
0151             me = _ibooker.book1D(name, name, xaxis.nbins, xaxis.low, xaxis.high);
0152           else
0153             me = _ibooker.book1D(name, name, xaxis.nbins, &(xaxis.edges[0]));
0154 
0155           break;
0156 
0157         case MonitorElement::Kind::TPROFILE:
0158           if (xaxis.edges.empty()) {
0159             me = _ibooker.bookProfile(name, name, xaxis.nbins, xaxis.low, xaxis.high, yaxis.low, yaxis.high, "");
0160           } else {
0161             // DQMStore bookProfile interface uses double* for bin edges
0162             double *edges(new double[xaxis.nbins + 1]);
0163             std::copy(xaxis.edges.begin(), xaxis.edges.end(), edges);
0164             me = _ibooker.bookProfile(name, name, xaxis.nbins, edges, yaxis.low, yaxis.high, "");
0165             delete[] edges;
0166           }
0167 
0168           break;
0169 
0170         case MonitorElement::Kind::TH2F:
0171           if (xaxis.edges.empty() && yaxis.edges.empty()) {
0172             me = _ibooker.book2D(name, name, xaxis.nbins, xaxis.low, xaxis.high, yaxis.nbins, yaxis.low, yaxis.high);
0173           } else {
0174             binning::AxisSpecs *specs[] = {&xaxis, &yaxis};
0175             for (int iSpec(0); iSpec < 2; iSpec++) {
0176               if (specs[iSpec]->edges.empty()) {
0177                 specs[iSpec]->edges = std::vector<float>(specs[iSpec]->nbins + 1);
0178                 int nbins(specs[iSpec]->nbins);
0179                 double low(specs[iSpec]->low), high(specs[iSpec]->high);
0180                 for (int i(0); i < nbins + 1; i++)
0181                   specs[iSpec]->edges[i] = low + (high - low) / nbins * i;
0182               }
0183             }
0184             me = _ibooker.book2D(name, name, xaxis.nbins, &(xaxis.edges[0]), yaxis.nbins, &(yaxis.edges[0]));
0185           }
0186 
0187           break;
0188 
0189         case MonitorElement::Kind::TPROFILE2D:
0190           if (!zaxis.edges.empty()) {
0191             zaxis.low = zaxis.edges[0];
0192             zaxis.high = zaxis.edges[zaxis.nbins];
0193           }
0194           if (!(xaxis.edges.empty() && yaxis.edges.empty()))
0195             throw_("Variable bin size for 2D profile not implemented");
0196           me = _ibooker.bookProfile2D(name,
0197                                       name,
0198                                       xaxis.nbins,
0199                                       xaxis.low,
0200                                       xaxis.high,
0201                                       yaxis.nbins,
0202                                       yaxis.low,
0203                                       yaxis.high,
0204                                       zaxis.low,
0205                                       zaxis.high,
0206                                       "");
0207 
0208           break;
0209 
0210         default:
0211           break;
0212       }
0213 
0214       if (!me)
0215         throw_("ME could not be booked");
0216 
0217       if (isHistogram) {
0218         me->setAxisTitle(xaxis.title, 1);
0219         me->setAxisTitle(yaxis.title, 2);
0220         if (isMap)
0221           me->setAxisTitle(zaxis.title, 3);
0222 
0223         if (!xaxis.labels.empty()) {
0224           for (int iBin(1); iBin <= xaxis.nbins; ++iBin)
0225             me->setBinLabel(iBin, xaxis.labels[iBin - 1], 1);
0226         }
0227         if (!yaxis.labels.empty()) {
0228           for (int iBin(1); iBin <= yaxis.nbins; ++iBin)
0229             me->setBinLabel(iBin, yaxis.labels[iBin - 1], 2);
0230         }
0231         if (!zaxis.labels.empty()) {
0232           for (int iBin(1); iBin <= zaxis.nbins; ++iBin)
0233             me->setBinLabel(iBin, zaxis.labels[iBin - 1], 3);
0234         }
0235 
0236         /* FIX: In ROOT 6.0.12 bit 20 is used by ROOT (bit 19 was already in use
0237       in 6.0.x). Talking with the ROOT team, users should never use SetBit for
0238       their own purpose since those bits are reserved for ROOT internally. See
0239       https://github.com/cms-sw/cmssw/issues/21423 for some alternative ways of
0240       attaching additional information to a TH1
0241 
0242       // For plot tagging in RenderPlugin; default values are 1 for both
0243       // bits 19 - 23 are free in TH1::fBits
0244       // can only pack object + logical dimensions into 5 bits (4 bits for
0245       object, 1 bit for dim (1 -> dim >= 2))
0246       me->getTH1()->SetBit(uint32_t(actualObject + 1) << 20);
0247       if(isMap) me->getTH1()->SetBit(0x1 << 19);
0248       */
0249 
0250         // The render plugin requires some metadata in order to set the correct
0251         // rendering for each plot. The original solution was to use bits number
0252         // 19 to 23 in TH1::fBits, but these were meant for ROOT's internal usage
0253         // and eventually started breaking things, see:
0254         // https://github.com/cms-sw/cmssw/issues/21423 The current solution is to
0255         // use the UniqueID field in the parent TObject, which is expected to work
0256         // if there is no TRef pointing to the TObject.
0257 
0258         // To check that indeed there is no such TRef, one can use
0259         // TestBit(kIsReferenced), e.g. std::cout << "Need to set unique ID at
0260         // path = " << path << "; for this path, TestBit(kIsReferenced) is: " <<
0261         // (me->getTH1()->TestBit(kIsReferenced)? "true": "false") << std::endl;
0262         // // should always output false for the solution to work
0263 
0264         // Originally, bit 19 in TH1::fBits was set to isMap, while bits 20-23
0265         // contained (actualObject+1). The idea is to make sure that both these
0266         // variables are easily recoverable in the render plugin, as in this
0267         // solution, where isMap is the last bit.
0268         me->getTH1()->SetUniqueID(uint32_t(2 * (actualObject + 1) + (isMap ? 1 : 0)));
0269       }
0270 
0271       mes_.push_back(me);
0272     }
0273 
0274     if (lumiFlag_)
0275       _ibooker.setScope(oldscope);
0276 
0277     active_ = true;
0278   }
0279 
0280   bool MESetEcal::retrieve(EcalElectronicsMapping const *electronicsMap,
0281                            DQMStore::IGetter &_igetter,
0282                            std::string *_failedPath /* = 0*/) const {
0283     clear();
0284 
0285     std::vector<std::string> mePaths(generatePaths(electronicsMap));
0286     if (mePaths.empty()) {
0287       if (_failedPath)
0288         _failedPath->clear();
0289       return false;
0290     }
0291 
0292     for (unsigned iME(0); iME < mePaths.size(); iME++) {
0293       std::string &path(mePaths[iME]);
0294       if (path.find('%') != std::string::npos)
0295         throw_("retrieve() called with incompletely formed path [" + path + "]");
0296 
0297       MonitorElement *me(_igetter.get(path));
0298       if (me)
0299         mes_.push_back(me);
0300       else {
0301         clear();
0302         if (_failedPath)
0303           *_failedPath = path;
0304         return false;
0305       }
0306     }
0307 
0308     active_ = true;
0309     return true;
0310   }
0311 
0312   void MESetEcal::fill(EcalDQMSetupObjects const edso,
0313                        DetId const &_id,
0314                        double _x /* = 1.*/,
0315                        double _wy /* = 1.*/,
0316                        double _w /* = 1.*/) {
0317     if (!active_)
0318       return;
0319 
0320     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0321     checkME_(iME);
0322 
0323     fill_(iME, _x, _wy, _w);
0324   }
0325 
0326   void MESetEcal::fill(EcalDQMSetupObjects const edso,
0327                        EcalElectronicsId const &_id,
0328                        double _x /* = 1.*/,
0329                        double _wy /* = 1.*/,
0330                        double _w /* = 1.*/) {
0331     if (!active_)
0332       return;
0333 
0334     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0335     checkME_(iME);
0336 
0337     fill_(iME, _x, _wy, _w);
0338   }
0339 
0340   void MESetEcal::fill(
0341       EcalDQMSetupObjects const edso, int _dcctccid, double _x /* = 1.*/, double _wy /* = 1.*/, double _w /* = 1.*/) {
0342     if (!active_)
0343       return;
0344 
0345     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _dcctccid, btype_));
0346     checkME_(iME);
0347 
0348     fill_(iME, _x, _wy, _w);
0349   }
0350 
0351   void MESetEcal::fill(EcalDQMSetupObjects const edso, double _x, double _wy /* = 1.*/, double _w /* = 1.*/) {
0352     if (!active_)
0353       return;
0354 
0355     if (mes_.size() != 1)
0356       return;
0357 
0358     fill_(0, _x, _wy, _w);
0359   }
0360 
0361   void MESetEcal::setBinContent(EcalDQMSetupObjects const edso, DetId const &_id, int _bin, double _content) {
0362     if (!active_)
0363       return;
0364 
0365     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0366     checkME_(iME);
0367 
0368     mes_[iME]->setBinContent(_bin, _content);
0369   }
0370 
0371   void MESetEcal::setBinContent(EcalDQMSetupObjects const edso,
0372                                 EcalElectronicsId const &_id,
0373                                 int _bin,
0374                                 double _content) {
0375     if (!active_)
0376       return;
0377 
0378     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0379     checkME_(iME);
0380 
0381     mes_[iME]->setBinContent(_bin, _content);
0382   }
0383 
0384   void MESetEcal::setBinContent(EcalDQMSetupObjects const edso, int _dcctccid, int _bin, double _content) {
0385     if (!active_)
0386       return;
0387 
0388     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _dcctccid, btype_));
0389     checkME_(iME);
0390 
0391     mes_[iME]->setBinContent(_bin, _content);
0392   }
0393 
0394   void MESetEcal::setBinError(EcalDQMSetupObjects const edso, DetId const &_id, int _bin, double _error) {
0395     if (!active_)
0396       return;
0397 
0398     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0399     checkME_(iME);
0400 
0401     mes_[iME]->setBinError(_bin, _error);
0402   }
0403 
0404   void MESetEcal::setBinError(EcalDQMSetupObjects const edso, EcalElectronicsId const &_id, int _bin, double _error) {
0405     if (!active_)
0406       return;
0407 
0408     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0409     checkME_(iME);
0410 
0411     mes_[iME]->setBinError(_bin, _error);
0412   }
0413 
0414   void MESetEcal::setBinError(EcalDQMSetupObjects const edso, int _dcctccid, int _bin, double _error) {
0415     if (!active_)
0416       return;
0417 
0418     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _dcctccid, btype_));
0419     checkME_(iME);
0420 
0421     mes_[iME]->setBinError(_bin, _error);
0422   }
0423 
0424   void MESetEcal::setBinEntries(EcalDQMSetupObjects const edso, DetId const &_id, int _bin, double _entries) {
0425     if (!active_)
0426       return;
0427     if (kind_ != MonitorElement::Kind::TPROFILE && kind_ != MonitorElement::Kind::TPROFILE2D)
0428       return;
0429 
0430     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0431     checkME_(iME);
0432 
0433     mes_[iME]->setBinEntries(_bin, _entries);
0434   }
0435 
0436   void MESetEcal::setBinEntries(EcalDQMSetupObjects const edso,
0437                                 EcalElectronicsId const &_id,
0438                                 int _bin,
0439                                 double _entries) {
0440     if (!active_)
0441       return;
0442     if (kind_ != MonitorElement::Kind::TPROFILE && kind_ != MonitorElement::Kind::TPROFILE2D)
0443       return;
0444 
0445     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0446     checkME_(iME);
0447 
0448     mes_[iME]->setBinEntries(_bin, _entries);
0449   }
0450 
0451   void MESetEcal::setBinEntries(EcalDQMSetupObjects const edso, int _dcctccid, int _bin, double _entries) {
0452     if (!active_)
0453       return;
0454     if (kind_ != MonitorElement::Kind::TPROFILE && kind_ != MonitorElement::Kind::TPROFILE2D)
0455       return;
0456 
0457     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _dcctccid, btype_));
0458     checkME_(iME);
0459 
0460     mes_[iME]->setBinEntries(_bin, _entries);
0461   }
0462 
0463   double MESetEcal::getBinContent(EcalDQMSetupObjects const edso, DetId const &_id, int _bin) const {
0464     if (!active_)
0465       return 0.;
0466 
0467     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0468     checkME_(iME);
0469 
0470     return mes_[iME]->getBinContent(_bin);
0471   }
0472 
0473   double MESetEcal::getBinContent(EcalDQMSetupObjects const edso, EcalElectronicsId const &_id, int _bin) const {
0474     if (!active_)
0475       return 0.;
0476 
0477     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0478     checkME_(iME);
0479 
0480     return mes_[iME]->getBinContent(_bin);
0481   }
0482 
0483   double MESetEcal::getBinContent(EcalDQMSetupObjects const edso, int _dcctccid, int _bin) const {
0484     if (!active_)
0485       return 0.;
0486 
0487     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _dcctccid, btype_));
0488     checkME_(iME);
0489 
0490     return mes_[iME]->getBinContent(_bin);
0491   }
0492 
0493   double MESetEcal::getBinError(EcalDQMSetupObjects const edso, DetId const &_id, int _bin) const {
0494     if (!active_)
0495       return 0.;
0496 
0497     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0498     checkME_(iME);
0499 
0500     return mes_[iME]->getBinError(_bin);
0501   }
0502 
0503   double MESetEcal::getBinError(EcalDQMSetupObjects const edso, EcalElectronicsId const &_id, int _bin) const {
0504     if (!active_)
0505       return 0.;
0506 
0507     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0508     checkME_(iME);
0509 
0510     return mes_[iME]->getBinError(_bin);
0511   }
0512 
0513   double MESetEcal::getBinError(EcalDQMSetupObjects const edso, int _dcctccid, int _bin) const {
0514     if (!active_)
0515       return 0.;
0516 
0517     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _dcctccid, btype_));
0518     checkME_(iME);
0519 
0520     return mes_[iME]->getBinError(_bin);
0521   }
0522 
0523   double MESetEcal::getBinEntries(EcalDQMSetupObjects const edso, DetId const &_id, int _bin) const {
0524     if (!active_)
0525       return 0.;
0526     if (kind_ != MonitorElement::Kind::TPROFILE && kind_ != MonitorElement::Kind::TPROFILE2D)
0527       return 0.;
0528 
0529     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0530     checkME_(iME);
0531 
0532     return mes_[iME]->getBinEntries(_bin);
0533   }
0534 
0535   double MESetEcal::getBinEntries(EcalDQMSetupObjects const edso, EcalElectronicsId const &_id, int _bin) const {
0536     if (!active_)
0537       return 0.;
0538     if (kind_ != MonitorElement::Kind::TPROFILE && kind_ != MonitorElement::Kind::TPROFILE2D)
0539       return 0.;
0540 
0541     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0542     checkME_(iME);
0543 
0544     return mes_[iME]->getBinEntries(_bin);
0545   }
0546 
0547   double MESetEcal::getBinEntries(EcalDQMSetupObjects const edso, int _dcctccid, int _bin) const {
0548     if (!active_)
0549       return 0.;
0550     if (kind_ != MonitorElement::Kind::TPROFILE && kind_ != MonitorElement::Kind::TPROFILE2D)
0551       return 0.;
0552 
0553     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _dcctccid, btype_));
0554     checkME_(iME);
0555 
0556     return mes_[iME]->getBinEntries(_bin);
0557   }
0558 
0559   int MESetEcal::findBin(EcalDQMSetupObjects const edso, DetId const &_id, double _x, double _y /* = 0.*/) const {
0560     if (!active_)
0561       return -1;
0562 
0563     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0564     checkME_(iME);
0565 
0566     return mes_[iME]->getTH1()->FindBin(_x, _y);
0567   }
0568 
0569   int MESetEcal::findBin(EcalDQMSetupObjects const edso,
0570                          EcalElectronicsId const &_id,
0571                          double _x,
0572                          double _y /* = 0.*/) const {
0573     if (!active_)
0574       return -1;
0575 
0576     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _id));
0577     checkME_(iME);
0578 
0579     return mes_[iME]->getTH1()->FindBin(_x, _y);
0580   }
0581 
0582   int MESetEcal::findBin(EcalDQMSetupObjects const edso, int _dcctccid, double _x, double _y /* = 0.*/) const {
0583     if (!active_)
0584       return -1;
0585 
0586     unsigned iME(binning::findPlotIndex(edso.electronicsMap, otype_, _dcctccid, btype_));
0587     checkME_(iME);
0588 
0589     return mes_[iME]->getTH1()->FindBin(_x, _y);
0590   }
0591 
0592   bool MESetEcal::isVariableBinning() const {
0593     return (xaxis_ && !xaxis_->edges.empty()) || (yaxis_ && !yaxis_->edges.empty()) ||
0594            (zaxis_ && !zaxis_->edges.empty());
0595   }
0596 
0597   std::vector<std::string> MESetEcal::generatePaths(EcalElectronicsMapping const *electronicsMap) const {
0598     using namespace std;
0599 
0600     vector<string> paths(0);
0601 
0602     unsigned nME(binning::getNObjects(otype_));
0603 
0604     for (unsigned iME(0); iME < nME; iME++) {
0605       binning::ObjectType obj(binning::getObject(otype_, iME));
0606 
0607       string path(path_);
0608       map<string, string> replacements;
0609 
0610       switch (obj) {
0611         case binning::kEB:
0612         case binning::kEBMEM:
0613           replacements["subdet"] = "EcalBarrel";
0614           replacements["prefix"] = "EB";
0615           replacements["suffix"] = "";
0616           replacements["subdetshort"] = "EB";
0617           replacements["subdetshortsig"] = "EB";
0618           replacements["supercrystal"] = "trigger tower";
0619           break;
0620         case binning::kEE:
0621         case binning::kEEMEM:
0622           replacements["subdet"] = "EcalEndcap";
0623           replacements["prefix"] = "EE";
0624           replacements["subdetshort"] = "EE";
0625           replacements["subdetshortsig"] = "EE";
0626           replacements["supercrystal"] = "super crystal";
0627           break;
0628         case binning::kEEm:
0629           replacements["subdet"] = "EcalEndcap";
0630           replacements["prefix"] = "EE";
0631           replacements["suffix"] = " EE -";
0632           replacements["subdetshort"] = "EE";
0633           replacements["subdetshortsig"] = "EEM";
0634           replacements["supercrystal"] = "super crystal";
0635           break;
0636         case binning::kEEp:
0637           replacements["subdet"] = "EcalEndcap";
0638           replacements["prefix"] = "EE";
0639           replacements["suffix"] = " EE +";
0640           replacements["subdetshort"] = "EE";
0641           replacements["subdetshortsig"] = "EEP";
0642           replacements["supercrystal"] = "super crystal";
0643           break;
0644         case binning::kSM:
0645           if (iME <= kEEmHigh || iME >= kEEpLow) {
0646             replacements["subdet"] = "EcalEndcap";
0647             replacements["prefix"] = "EE";
0648             replacements["supercrystal"] = "super crystal";
0649           } else {
0650             replacements["subdet"] = "EcalBarrel";
0651             replacements["prefix"] = "EB";
0652             replacements["supercrystal"] = "trigger tower";
0653           }
0654           replacements["sm"] = binning::channelName(electronicsMap, iME + 1);
0655           break;
0656         case binning::kEBSM:
0657           replacements["subdet"] = "EcalBarrel";
0658           replacements["prefix"] = "EB";
0659           replacements["sm"] = binning::channelName(electronicsMap, iME + kEBmLow + 1);
0660           replacements["supercrystal"] = "trigger tower";
0661           break;
0662         case binning::kEESM:
0663           replacements["subdet"] = "EcalEndcap";
0664           replacements["prefix"] = "EE";
0665           replacements["sm"] = binning::channelName(electronicsMap, iME <= kEEmHigh ? iME + 1 : iME + 37);
0666           replacements["supercrystal"] = "super crystal";
0667           break;
0668         case binning::kSMMEM: {
0669           unsigned iDCC(memDCCId(iME) - 1);
0670           // dccId(unsigned) skips DCCs without MEM
0671           if (iDCC <= kEEmHigh || iDCC >= kEEpLow) {
0672             replacements["subdet"] = "EcalEndcap";
0673             replacements["prefix"] = "EE";
0674           } else {
0675             replacements["subdet"] = "EcalBarrel";
0676             replacements["prefix"] = "EB";
0677           }
0678           replacements["sm"] = binning::channelName(electronicsMap, iDCC + 1);
0679         } break;
0680         case binning::kEBSMMEM: {
0681           unsigned iDCC(memDCCId(iME + 4) - 1);
0682           replacements["subdet"] = "EcalBarrel";
0683           replacements["prefix"] = "EB";
0684           replacements["sm"] = binning::channelName(electronicsMap, iDCC + 1);
0685         } break;
0686         case binning::kEESMMEM: {
0687           unsigned iDCC(memDCCId(iME < 4 ? iME : iME + 36) - 1);
0688           replacements["subdet"] = "EcalEndcap";
0689           replacements["prefix"] = "EE";
0690           replacements["sm"] = binning::channelName(electronicsMap, iDCC + 1);
0691         }
0692         default:
0693           break;
0694       }
0695 
0696       paths.push_back(formPath(replacements));
0697     }
0698 
0699     return paths;
0700   }
0701 }  // namespace ecaldqm