Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 /** \class EDMtoMEConverter
0002  *  
0003  *  Class to take dqm monitor elements and convert into a
0004  *  ROOT dataformat stored in Run tree of edm file
0005  *
0006  *  \author M. Strang SUNY-Buffalo
0007  */
0008 
0009 // framework & common header files
0010 #include "DataFormats/Common/interface/Handle.h"
0011 #include "DataFormats/Histograms/interface/DQMToken.h"
0012 #include "FWCore/Framework/interface/ConsumesCollector.h"
0013 #include "FWCore/Framework/interface/ESHandle.h"
0014 #include "FWCore/Framework/interface/Event.h"
0015 #include "FWCore/Framework/interface/EventSetup.h"
0016 #include "FWCore/Framework/interface/FileBlock.h"
0017 #include "FWCore/Framework/interface/Frameworkfwd.h"
0018 #include "FWCore/Framework/interface/LuminosityBlock.h"
0019 #include "FWCore/Framework/interface/MakerMacros.h"
0020 #include "FWCore/Framework/interface/Run.h"
0021 #include "FWCore/Framework/interface/one/EDProducer.h"
0022 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0023 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0024 #include "FWCore/Utilities/interface/EDPutToken.h"
0025 #include "FWCore/Utilities/interface/InputTag.h"
0026 
0027 //DQM services
0028 #include "DQMServices/Core/interface/DQMStore.h"
0029 #include "FWCore/ServiceRegistry/interface/Service.h"
0030 
0031 // data format
0032 #include "DataFormats/Histograms/interface/MEtoEDMFormat.h"
0033 #include "DataFormats/Histograms/interface/DQMToken.h"
0034 
0035 // helper files
0036 #include <cassert>
0037 #include <iostream>
0038 #include <cstdlib>
0039 #include <string>
0040 #include <memory>
0041 #include <vector>
0042 #include <map>
0043 #include <tuple>
0044 #include <filesystem>
0045 
0046 #include "TString.h"
0047 #include "TList.h"
0048 
0049 class EDMtoMEConverter : public edm::one::EDProducer<edm::one::WatchRuns,
0050                                                      edm::one::WatchLuminosityBlocks,
0051                                                      edm::one::SharedResources,
0052                                                      edm::EndLuminosityBlockProducer,
0053                                                      edm::EndRunProducer> {
0054 public:
0055   typedef dqm::legacy::DQMStore DQMStore;
0056   typedef dqm::legacy::MonitorElement MonitorElement;
0057 
0058   explicit EDMtoMEConverter(const edm::ParameterSet &);
0059   ~EDMtoMEConverter() override = default;
0060 
0061   void beginRun(const edm::Run &, const edm::EventSetup &) final {}
0062   void endRun(const edm::Run &, const edm::EventSetup &) final {}
0063   void beginLuminosityBlock(const edm::LuminosityBlock &, const edm::EventSetup &) final {}
0064   void endLuminosityBlock(const edm::LuminosityBlock &, const edm::EventSetup &) final {}
0065   void produce(edm::Event &, edm::EventSetup const &) final {}
0066 
0067   void endLuminosityBlockProduce(edm::LuminosityBlock &, edm::EventSetup const &) override;
0068   void endRunProduce(edm::Run &run, edm::EventSetup const &setup) override;
0069 
0070   template <class T>
0071   void getData(DQMStore::IBooker &iBooker, DQMStore::IGetter &iGetter, T &iGetFrom);
0072 
0073   using TagList = std::vector<uint32_t>;
0074 
0075 private:
0076   std::string name;
0077   int verbosity;
0078   int frequency;
0079 
0080   bool convertOnEndLumi;
0081   bool convertOnEndRun;
0082   MonitorElementData::Scope reScope;
0083 
0084   template <typename T>
0085   class Tokens {
0086   public:
0087     using type = T;
0088     using Product = MEtoEDM<T>;
0089 
0090     Tokens() = default;
0091 
0092     void set(const edm::InputTag &runInputTag, const edm::InputTag &lumiInputTag, edm::ConsumesCollector &iC);
0093 
0094     void getData(const edm::Run &iRun, edm::Handle<Product> &handle) const;
0095     void getData(const edm::LuminosityBlock &iLumi, edm::Handle<Product> &handle) const;
0096 
0097   private:
0098     edm::EDGetTokenT<Product> runToken;
0099     edm::EDGetTokenT<Product> lumiToken;
0100   };
0101 
0102   std::tuple<Tokens<TH1F>,
0103              Tokens<TH1S>,
0104              Tokens<TH1D>,
0105              Tokens<TH1I>,
0106              Tokens<TH2F>,
0107              Tokens<TH2S>,
0108              Tokens<TH2D>,
0109              Tokens<TH2I>,
0110              Tokens<TH2Poly>,
0111              Tokens<TH3F>,
0112              Tokens<TProfile>,
0113              Tokens<TProfile2D>,
0114              Tokens<double>,
0115              Tokens<int>,
0116              Tokens<long long>,
0117              Tokens<TString> >
0118       tokens_;
0119 
0120   edm::EDPutTokenT<DQMToken> dqmLumiToken_;
0121   edm::EDPutTokenT<DQMToken> dqmRunToken_;
0122 };  // end class declaration
0123 
0124 using namespace lat;
0125 using dqm::legacy::DQMStore;
0126 using dqm::legacy::MonitorElement;
0127 
0128 template <typename T>
0129 void EDMtoMEConverter::Tokens<T>::set(const edm::InputTag &runInputTag,
0130                                       const edm::InputTag &lumiInputTag,
0131                                       edm::ConsumesCollector &iC) {
0132   runToken = iC.mayConsume<MEtoEDM<T>, edm::InRun>(runInputTag);
0133   lumiToken = iC.mayConsume<MEtoEDM<T>, edm::InLumi>(lumiInputTag);
0134 }
0135 
0136 template <typename T>
0137 void EDMtoMEConverter::Tokens<T>::getData(const edm::Run &iRun, edm::Handle<Product> &handle) const {
0138   iRun.getByToken(runToken, handle);
0139 }
0140 
0141 template <typename T>
0142 void EDMtoMEConverter::Tokens<T>::getData(const edm::LuminosityBlock &iLumi, edm::Handle<Product> &handle) const {
0143   iLumi.getByToken(lumiToken, handle);
0144 }
0145 
0146 namespace {
0147   // general
0148   template <size_t I, size_t N>
0149   struct ForEachHelper {
0150     template <typename Tuple, typename Func>
0151     static void call(Tuple &&tpl, Func &&func) {
0152       func(std::get<I - 1>(tpl));
0153       ForEachHelper<I + 1, N>::call(std::forward<Tuple>(tpl), std::forward<Func>(func));
0154     }
0155   };
0156   // break recursion
0157   template <size_t N>
0158   struct ForEachHelper<N, N> {
0159     template <typename Tuple, typename Func>
0160     static void call(Tuple &&tpl, Func &&func) {
0161       func(std::get<N - 1>(tpl));
0162     }
0163   };
0164 
0165   // helper function to provide nice interface
0166   template <typename Tuple, typename Func>
0167   void for_each(Tuple &&tpl, Func &&func) {
0168     constexpr auto size = std::tuple_size<typename std::decay<Tuple>::type>::value;
0169     ForEachHelper<1, size>::call(std::forward<Tuple>(tpl), std::forward<Func>(func));
0170   }
0171 
0172   template <typename T>
0173   struct HistoTraits;
0174   template <>
0175   struct HistoTraits<TH1F> {
0176     static TH1F *get(MonitorElement *me) { return me->getTH1F(); }
0177     template <typename... Args>
0178     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0179       return iBooker.book1D(std::forward<Args>(args)...);
0180     }
0181   };
0182   template <>
0183   struct HistoTraits<TH1S> {
0184     static TH1S *get(MonitorElement *me) { return me->getTH1S(); }
0185     template <typename... Args>
0186     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0187       return iBooker.book1S(std::forward<Args>(args)...);
0188     }
0189   };
0190   template <>
0191   struct HistoTraits<TH1D> {
0192     static TH1D *get(MonitorElement *me) { return me->getTH1D(); }
0193     template <typename... Args>
0194     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0195       return iBooker.book1DD(std::forward<Args>(args)...);
0196     }
0197   };
0198   template <>
0199   struct HistoTraits<TH1I> {
0200     static TH1I *get(MonitorElement *me) { return me->getTH1I(); }
0201     template <typename... Args>
0202     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0203       return iBooker.book1I(std::forward<Args>(args)...);
0204     }
0205   };
0206   template <>
0207   struct HistoTraits<TH2F> {
0208     static TH2F *get(MonitorElement *me) { return me->getTH2F(); }
0209     template <typename... Args>
0210     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0211       return iBooker.book2D(std::forward<Args>(args)...);
0212     }
0213   };
0214   template <>
0215   struct HistoTraits<TH2S> {
0216     static TH2S *get(MonitorElement *me) { return me->getTH2S(); }
0217     template <typename... Args>
0218     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0219       return iBooker.book2S(std::forward<Args>(args)...);
0220     }
0221   };
0222   template <>
0223   struct HistoTraits<TH2D> {
0224     static TH2D *get(MonitorElement *me) { return me->getTH2D(); }
0225     template <typename... Args>
0226     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0227       return iBooker.book2DD(std::forward<Args>(args)...);
0228     }
0229   };
0230   template <>
0231   struct HistoTraits<TH2I> {
0232     static TH2I *get(MonitorElement *me) { return me->getTH2I(); }
0233     template <typename... Args>
0234     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0235       return iBooker.book2I(std::forward<Args>(args)...);
0236     }
0237   };
0238   template <>
0239   struct HistoTraits<TH2Poly> {
0240     static TH2Poly *get(MonitorElement *me) { return me->getTH2Poly(); }
0241     template <typename... Args>
0242     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0243       return iBooker.book2DPoly(std::forward<Args>(args)...);
0244     }
0245   };
0246   template <>
0247   struct HistoTraits<TH3F> {
0248     static TH3F *get(MonitorElement *me) { return me->getTH3F(); }
0249     template <typename... Args>
0250     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0251       return iBooker.book3D(std::forward<Args>(args)...);
0252     }
0253   };
0254   template <>
0255   struct HistoTraits<TProfile> {
0256     static TProfile *get(MonitorElement *me) { return me->getTProfile(); }
0257     template <typename... Args>
0258     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0259       return iBooker.bookProfile(std::forward<Args>(args)...);
0260     }
0261   };
0262   template <>
0263   struct HistoTraits<TProfile2D> {
0264     static TProfile2D *get(MonitorElement *me) { return me->getTProfile2D(); }
0265     template <typename... Args>
0266     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0267       return iBooker.bookProfile2D(std::forward<Args>(args)...);
0268     }
0269   };
0270 
0271   // Default to histograms and similar, others are specialized
0272   template <typename T>
0273   struct AddMonitorElement {
0274     template <typename MEtoEDMObject_object, typename RunOrLumi>
0275     static MonitorElement *call(DQMStore::IBooker &iBooker,
0276                                 DQMStore::IGetter &iGetter,
0277                                 MEtoEDMObject_object *metoedmobject,
0278                                 const std::string &dir,
0279                                 const std::string &name,
0280                                 const RunOrLumi &runOrLumi) {
0281       MonitorElement *me = iGetter.get(dir + "/" + metoedmobject->GetName());
0282 
0283       if (me) {
0284         auto histo = HistoTraits<T>::get(me);
0285         assert(histo);
0286         TList list;
0287         list.Add(metoedmobject);
0288         if (histo->Merge(&list) == -1)
0289           edm::LogError("EDMtoMEConverter") << "ERROR EDMtoMEConverter::getData(): merge failed for '"
0290                                             << metoedmobject->GetName() << "'" << std::endl;
0291         return me;
0292       } else {
0293         iBooker.setCurrentFolder(dir);
0294         return HistoTraits<T>::book(iBooker, metoedmobject->GetName(), metoedmobject);
0295       }
0296     }
0297   };
0298 
0299   template <>
0300   struct AddMonitorElement<double> {
0301     template <typename MEtoEDMObject_object, typename RunOrLumi>
0302     static MonitorElement *call(DQMStore::IBooker &iBooker,
0303                                 DQMStore::IGetter &iGetter,
0304                                 MEtoEDMObject_object *metoedmobject,
0305                                 const std::string &dir,
0306                                 const std::string &name,
0307                                 const RunOrLumi &runOrLumi) {
0308       iBooker.setCurrentFolder(dir);
0309       MonitorElement *me = iBooker.bookFloat(name);
0310       me->Fill(*metoedmobject);
0311       return me;
0312     }
0313   };
0314 
0315   // long long and int share some commonalities, which are captured here (we can have only one default template definition)
0316   template <typename T>
0317   struct AddMonitorElementForIntegers {
0318     template <typename MEtoEDMObject_object, typename RunOrLumi>
0319     static MonitorElement *call(DQMStore::IBooker &iBooker,
0320                                 DQMStore::IGetter &iGetter,
0321                                 MEtoEDMObject_object *metoedmobject,
0322                                 const std::string &dir,
0323                                 const std::string &name,
0324                                 const RunOrLumi &runOrLumi) {
0325       iBooker.setCurrentFolder(dir);
0326       iGetter.setCurrentFolder(dir);
0327       T ival = getProcessedEvents(iGetter, dir, name, runOrLumi);
0328       MonitorElement *me = iBooker.bookInt(name);
0329       me->Fill(*metoedmobject + ival);
0330       return me;
0331     }
0332 
0333     static T getProcessedEvents(DQMStore::IGetter &iGetter,
0334                                 const std::string &dir,
0335                                 const std::string &name,
0336                                 const edm::Run &) {
0337       if (name.find("processedEvents") != std::string::npos) {
0338         if (const MonitorElement *me = iGetter.get(dir + "/" + name)) {
0339           return me->getIntValue();
0340         }
0341       }
0342       return 0;
0343     }
0344 
0345     static T getProcessedEvents(DQMStore::IGetter &iGetter,
0346                                 const std::string &dir,
0347                                 const std::string &name,
0348                                 const edm::LuminosityBlock &) {
0349       return 0;
0350     }
0351   };
0352   template <>
0353   struct AddMonitorElement<long long> {
0354     template <typename... Args>
0355     static MonitorElement *call(Args &&...args) {
0356       return AddMonitorElementForIntegers<long long>::call(std::forward<Args>(args)...);
0357     }
0358   };
0359   template <>
0360   struct AddMonitorElement<int> {
0361     template <typename... Args>
0362     static MonitorElement *call(Args &&...args) {
0363       return AddMonitorElementForIntegers<int>::call(std::forward<Args>(args)...);
0364     }
0365   };
0366 
0367   template <>
0368   struct AddMonitorElement<TString> {
0369     template <typename MEtoEDMObject_object, typename RunOrLumi>
0370     static MonitorElement *call(DQMStore::IBooker &iBooker,
0371                                 DQMStore::IGetter &iGetter,
0372                                 MEtoEDMObject_object *metoedmobject,
0373                                 const std::string &dir,
0374                                 const std::string &name,
0375                                 const RunOrLumi &runOrLumi) {
0376       iBooker.setCurrentFolder(dir);
0377       std::string scont = metoedmobject->Data();
0378       return iBooker.bookString(name, scont);
0379     }
0380   };
0381 
0382   // TODO: might need re-scoping to JOB here.
0383   void adjustScope(DQMStore::IBooker &ibooker, const edm::Run &, MonitorElementData::Scope reScope) {
0384     if (reScope == MonitorElementData::Scope::JOB) {
0385       ibooker.setScope(MonitorElementData::Scope::JOB);
0386     } else {
0387       ibooker.setScope(MonitorElementData::Scope::RUN);
0388     }
0389   }
0390   void adjustScope(DQMStore::IBooker &ibooker, const edm::LuminosityBlock &, MonitorElementData::Scope reScope) {
0391     // will be LUMI for no reScoping, else the expected scope.
0392     ibooker.setScope(reScope);
0393   }
0394 
0395 }  // namespace
0396 
0397 EDMtoMEConverter::EDMtoMEConverter(const edm::ParameterSet &iPSet) : verbosity(0), frequency(0) {
0398   const edm::InputTag &runInputTag = iPSet.getParameter<edm::InputTag>("runInputTag");
0399   const edm::InputTag &lumiInputTag = iPSet.getParameter<edm::InputTag>("lumiInputTag");
0400   edm::ConsumesCollector iC = consumesCollector();
0401 
0402   for_each(tokens_, [&](auto &tok) { tok.set(runInputTag, lumiInputTag, iC); });
0403 
0404   constexpr char MsgLoggerCat[] = "EDMtoMEConverter_EDMtoMEConverter";
0405 
0406   // get information from parameter set
0407   name = iPSet.getUntrackedParameter<std::string>("Name");
0408   verbosity = iPSet.getUntrackedParameter<int>("Verbosity");
0409   frequency = iPSet.getUntrackedParameter<int>("Frequency");
0410 
0411   convertOnEndLumi = iPSet.getUntrackedParameter<bool>("convertOnEndLumi", true);
0412   convertOnEndRun = iPSet.getUntrackedParameter<bool>("convertOnEndRun", true);
0413 
0414   auto scopeDecode = std::map<std::string, MonitorElementData::Scope>{{"", MonitorElementData::Scope::LUMI},
0415                                                                       {"LUMI", MonitorElementData::Scope::LUMI},
0416                                                                       {"RUN", MonitorElementData::Scope::RUN},
0417                                                                       {"JOB", MonitorElementData::Scope::JOB}};
0418   reScope = scopeDecode[iPSet.getUntrackedParameter<std::string>("reScope", "")];
0419 
0420   // use value of first digit to determine default output level (inclusive)
0421   // 0 is none, 1 is basic, 2 is fill output, 3 is gather output
0422   verbosity %= 10;
0423 
0424   // print out Parameter Set information being used
0425   if (verbosity >= 0) {
0426     edm::LogInfo(MsgLoggerCat) << "\n===============================\n"
0427                                << "Initialized as EDAnalyzer with parameter values:\n"
0428                                << "    Name          = " << name << "\n"
0429                                << "    Verbosity     = " << verbosity << "\n"
0430                                << "    Frequency     = " << frequency << "\n"
0431                                << "===============================\n";
0432   }
0433 
0434   assert(sizeof(int64_t) == sizeof(long long));
0435   usesResource("DQMStore");
0436 
0437   dqmLumiToken_ = produces<DQMToken, edm::Transition::EndLuminosityBlock>("endLumi");
0438   dqmRunToken_ = produces<DQMToken, edm::Transition::EndRun>("endRun");
0439 }  // end constructor
0440 
0441 void EDMtoMEConverter::endRunProduce(edm::Run &iRun, edm::EventSetup const &iSetup) {
0442   if (convertOnEndRun) {
0443     DQMStore *store = edm::Service<DQMStore>().operator->();
0444     store->meBookerGetter([&](DQMStore::IBooker &b, DQMStore::IGetter &g) { getData(b, g, iRun); });
0445   }
0446 
0447   iRun.put(dqmRunToken_, std::make_unique<DQMToken>());
0448 }
0449 
0450 void EDMtoMEConverter::endLuminosityBlockProduce(edm::LuminosityBlock &iLumi, edm::EventSetup const &iSetup) {
0451   if (convertOnEndLumi) {
0452     DQMStore *store = edm::Service<DQMStore>().operator->();
0453     store->meBookerGetter([&](DQMStore::IBooker &b, DQMStore::IGetter &g) { getData(b, g, iLumi); });
0454   }
0455 
0456   iLumi.put(dqmLumiToken_, std::make_unique<DQMToken>());
0457 }
0458 
0459 template <class T>
0460 void EDMtoMEConverter::getData(DQMStore::IBooker &iBooker, DQMStore::IGetter &iGetter, T &iGetFrom) {
0461   constexpr char MsgLoggerCat[] = "EDMtoMEConverter_getData";
0462 
0463   if (verbosity >= 0)
0464     edm::LogInfo(MsgLoggerCat) << "\nRestoring MonitorElements.";
0465 
0466   for_each(tokens_, [&](const auto &tok) {
0467     using Tokens_T = typename std::decay<decltype(tok)>::type;
0468     using METype = typename Tokens_T::type;
0469     using MEtoEDM_T = typename Tokens_T::Product;
0470     edm::Handle<MEtoEDM_T> metoedm;
0471     tok.getData(iGetFrom, metoedm);
0472     if (!metoedm.isValid()) {
0473       //edm::LogWarning(MsgLoggerCat)
0474       //  << "MEtoEDM<TH1F> doesn't exist in run";
0475       return;
0476     }
0477 
0478     std::vector<typename MEtoEDM_T::MEtoEDMObject> metoedmobject = metoedm->getMEtoEdmObject();
0479 
0480     for (unsigned int i = 0; i < metoedmobject.size(); ++i) {
0481       // get full path of monitor element
0482       const std::string &pathname = metoedmobject[i].name;
0483       if (verbosity > 0)
0484         std::cout << pathname << std::endl;
0485 
0486       // deconstruct path from fullpath
0487       std::filesystem::path fulldir(pathname);
0488       std::string name = fulldir.filename();
0489       std::string dir = fulldir.parent_path();
0490       if (dir == "/")
0491         dir = "";
0492 
0493       // define new monitor element
0494       adjustScope(iBooker, iGetFrom, reScope);
0495       AddMonitorElement<METype>::call(iBooker, iGetter, &metoedmobject[i].object, dir, name, iGetFrom);
0496 
0497     }  // end loop thorugh metoedmobject
0498   });
0499 }
0500 
0501 #include "FWCore/PluginManager/interface/ModuleDef.h"
0502 #include "FWCore/Framework/interface/MakerMacros.h"
0503 DEFINE_FWK_MODULE(EDMtoMEConverter);