Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:10:08

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<TH3F>,
0111              Tokens<TProfile>,
0112              Tokens<TProfile2D>,
0113              Tokens<double>,
0114              Tokens<int>,
0115              Tokens<long long>,
0116              Tokens<TString> >
0117       tokens_;
0118 
0119   edm::EDPutTokenT<DQMToken> dqmLumiToken_;
0120   edm::EDPutTokenT<DQMToken> dqmRunToken_;
0121 };  // end class declaration
0122 
0123 using namespace lat;
0124 using dqm::legacy::DQMStore;
0125 using dqm::legacy::MonitorElement;
0126 
0127 template <typename T>
0128 void EDMtoMEConverter::Tokens<T>::set(const edm::InputTag &runInputTag,
0129                                       const edm::InputTag &lumiInputTag,
0130                                       edm::ConsumesCollector &iC) {
0131   runToken = iC.mayConsume<MEtoEDM<T>, edm::InRun>(runInputTag);
0132   lumiToken = iC.mayConsume<MEtoEDM<T>, edm::InLumi>(lumiInputTag);
0133 }
0134 
0135 template <typename T>
0136 void EDMtoMEConverter::Tokens<T>::getData(const edm::Run &iRun, edm::Handle<Product> &handle) const {
0137   iRun.getByToken(runToken, handle);
0138 }
0139 
0140 template <typename T>
0141 void EDMtoMEConverter::Tokens<T>::getData(const edm::LuminosityBlock &iLumi, edm::Handle<Product> &handle) const {
0142   iLumi.getByToken(lumiToken, handle);
0143 }
0144 
0145 namespace {
0146   // general
0147   template <size_t I, size_t N>
0148   struct ForEachHelper {
0149     template <typename Tuple, typename Func>
0150     static void call(Tuple &&tpl, Func &&func) {
0151       func(std::get<I - 1>(tpl));
0152       ForEachHelper<I + 1, N>::call(std::forward<Tuple>(tpl), std::forward<Func>(func));
0153     }
0154   };
0155   // break recursion
0156   template <size_t N>
0157   struct ForEachHelper<N, N> {
0158     template <typename Tuple, typename Func>
0159     static void call(Tuple &&tpl, Func &&func) {
0160       func(std::get<N - 1>(tpl));
0161     }
0162   };
0163 
0164   // helper function to provide nice interface
0165   template <typename Tuple, typename Func>
0166   void for_each(Tuple &&tpl, Func &&func) {
0167     constexpr auto size = std::tuple_size<typename std::decay<Tuple>::type>::value;
0168     ForEachHelper<1, size>::call(std::forward<Tuple>(tpl), std::forward<Func>(func));
0169   }
0170 
0171   template <typename T>
0172   struct HistoTraits;
0173   template <>
0174   struct HistoTraits<TH1F> {
0175     static TH1F *get(MonitorElement *me) { return me->getTH1F(); }
0176     template <typename... Args>
0177     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0178       return iBooker.book1D(std::forward<Args>(args)...);
0179     }
0180   };
0181   template <>
0182   struct HistoTraits<TH1S> {
0183     static TH1S *get(MonitorElement *me) { return me->getTH1S(); }
0184     template <typename... Args>
0185     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0186       return iBooker.book1S(std::forward<Args>(args)...);
0187     }
0188   };
0189   template <>
0190   struct HistoTraits<TH1D> {
0191     static TH1D *get(MonitorElement *me) { return me->getTH1D(); }
0192     template <typename... Args>
0193     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0194       return iBooker.book1DD(std::forward<Args>(args)...);
0195     }
0196   };
0197   template <>
0198   struct HistoTraits<TH1I> {
0199     static TH1I *get(MonitorElement *me) { return me->getTH1I(); }
0200     template <typename... Args>
0201     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0202       return iBooker.book1I(std::forward<Args>(args)...);
0203     }
0204   };
0205   template <>
0206   struct HistoTraits<TH2F> {
0207     static TH2F *get(MonitorElement *me) { return me->getTH2F(); }
0208     template <typename... Args>
0209     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0210       return iBooker.book2D(std::forward<Args>(args)...);
0211     }
0212   };
0213   template <>
0214   struct HistoTraits<TH2S> {
0215     static TH2S *get(MonitorElement *me) { return me->getTH2S(); }
0216     template <typename... Args>
0217     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0218       return iBooker.book2S(std::forward<Args>(args)...);
0219     }
0220   };
0221   template <>
0222   struct HistoTraits<TH2D> {
0223     static TH2D *get(MonitorElement *me) { return me->getTH2D(); }
0224     template <typename... Args>
0225     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0226       return iBooker.book2DD(std::forward<Args>(args)...);
0227     }
0228   };
0229   template <>
0230   struct HistoTraits<TH2I> {
0231     static TH2I *get(MonitorElement *me) { return me->getTH2I(); }
0232     template <typename... Args>
0233     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0234       return iBooker.book2I(std::forward<Args>(args)...);
0235     }
0236   };
0237   template <>
0238   struct HistoTraits<TH3F> {
0239     static TH3F *get(MonitorElement *me) { return me->getTH3F(); }
0240     template <typename... Args>
0241     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0242       return iBooker.book3D(std::forward<Args>(args)...);
0243     }
0244   };
0245   template <>
0246   struct HistoTraits<TProfile> {
0247     static TProfile *get(MonitorElement *me) { return me->getTProfile(); }
0248     template <typename... Args>
0249     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0250       return iBooker.bookProfile(std::forward<Args>(args)...);
0251     }
0252   };
0253   template <>
0254   struct HistoTraits<TProfile2D> {
0255     static TProfile2D *get(MonitorElement *me) { return me->getTProfile2D(); }
0256     template <typename... Args>
0257     static MonitorElement *book(DQMStore::IBooker &iBooker, Args &&...args) {
0258       return iBooker.bookProfile2D(std::forward<Args>(args)...);
0259     }
0260   };
0261 
0262   // Default to histograms and similar, others are specialized
0263   template <typename T>
0264   struct AddMonitorElement {
0265     template <typename MEtoEDMObject_object, typename RunOrLumi>
0266     static MonitorElement *call(DQMStore::IBooker &iBooker,
0267                                 DQMStore::IGetter &iGetter,
0268                                 MEtoEDMObject_object *metoedmobject,
0269                                 const std::string &dir,
0270                                 const std::string &name,
0271                                 const RunOrLumi &runOrLumi) {
0272       MonitorElement *me = iGetter.get(dir + "/" + metoedmobject->GetName());
0273 
0274       if (me) {
0275         auto histo = HistoTraits<T>::get(me);
0276         assert(histo);
0277         TList list;
0278         list.Add(metoedmobject);
0279         if (histo->Merge(&list) == -1)
0280           edm::LogError("EDMtoMEConverter") << "ERROR EDMtoMEConverter::getData(): merge failed for '"
0281                                             << metoedmobject->GetName() << "'" << std::endl;
0282         return me;
0283       } else {
0284         iBooker.setCurrentFolder(dir);
0285         return HistoTraits<T>::book(iBooker, metoedmobject->GetName(), metoedmobject);
0286       }
0287     }
0288   };
0289 
0290   template <>
0291   struct AddMonitorElement<double> {
0292     template <typename MEtoEDMObject_object, typename RunOrLumi>
0293     static MonitorElement *call(DQMStore::IBooker &iBooker,
0294                                 DQMStore::IGetter &iGetter,
0295                                 MEtoEDMObject_object *metoedmobject,
0296                                 const std::string &dir,
0297                                 const std::string &name,
0298                                 const RunOrLumi &runOrLumi) {
0299       iBooker.setCurrentFolder(dir);
0300       MonitorElement *me = iBooker.bookFloat(name);
0301       me->Fill(*metoedmobject);
0302       return me;
0303     }
0304   };
0305 
0306   // long long and int share some commonalities, which are captured here (we can have only one default template definition)
0307   template <typename T>
0308   struct AddMonitorElementForIntegers {
0309     template <typename MEtoEDMObject_object, typename RunOrLumi>
0310     static MonitorElement *call(DQMStore::IBooker &iBooker,
0311                                 DQMStore::IGetter &iGetter,
0312                                 MEtoEDMObject_object *metoedmobject,
0313                                 const std::string &dir,
0314                                 const std::string &name,
0315                                 const RunOrLumi &runOrLumi) {
0316       iBooker.setCurrentFolder(dir);
0317       iGetter.setCurrentFolder(dir);
0318       T ival = getProcessedEvents(iGetter, dir, name, runOrLumi);
0319       MonitorElement *me = iBooker.bookInt(name);
0320       me->Fill(*metoedmobject + ival);
0321       return me;
0322     }
0323 
0324     static T getProcessedEvents(DQMStore::IGetter &iGetter,
0325                                 const std::string &dir,
0326                                 const std::string &name,
0327                                 const edm::Run &) {
0328       if (name.find("processedEvents") != std::string::npos) {
0329         if (const MonitorElement *me = iGetter.get(dir + "/" + name)) {
0330           return me->getIntValue();
0331         }
0332       }
0333       return 0;
0334     }
0335 
0336     static T getProcessedEvents(DQMStore::IGetter &iGetter,
0337                                 const std::string &dir,
0338                                 const std::string &name,
0339                                 const edm::LuminosityBlock &) {
0340       return 0;
0341     }
0342   };
0343   template <>
0344   struct AddMonitorElement<long long> {
0345     template <typename... Args>
0346     static MonitorElement *call(Args &&...args) {
0347       return AddMonitorElementForIntegers<long long>::call(std::forward<Args>(args)...);
0348     }
0349   };
0350   template <>
0351   struct AddMonitorElement<int> {
0352     template <typename... Args>
0353     static MonitorElement *call(Args &&...args) {
0354       return AddMonitorElementForIntegers<int>::call(std::forward<Args>(args)...);
0355     }
0356   };
0357 
0358   template <>
0359   struct AddMonitorElement<TString> {
0360     template <typename MEtoEDMObject_object, typename RunOrLumi>
0361     static MonitorElement *call(DQMStore::IBooker &iBooker,
0362                                 DQMStore::IGetter &iGetter,
0363                                 MEtoEDMObject_object *metoedmobject,
0364                                 const std::string &dir,
0365                                 const std::string &name,
0366                                 const RunOrLumi &runOrLumi) {
0367       iBooker.setCurrentFolder(dir);
0368       std::string scont = metoedmobject->Data();
0369       return iBooker.bookString(name, scont);
0370     }
0371   };
0372 
0373   // TODO: might need re-scoping to JOB here.
0374   void adjustScope(DQMStore::IBooker &ibooker, const edm::Run &, MonitorElementData::Scope reScope) {
0375     if (reScope == MonitorElementData::Scope::JOB) {
0376       ibooker.setScope(MonitorElementData::Scope::JOB);
0377     } else {
0378       ibooker.setScope(MonitorElementData::Scope::RUN);
0379     }
0380   }
0381   void adjustScope(DQMStore::IBooker &ibooker, const edm::LuminosityBlock &, MonitorElementData::Scope reScope) {
0382     // will be LUMI for no reScoping, else the expected scope.
0383     ibooker.setScope(reScope);
0384   }
0385 
0386 }  // namespace
0387 
0388 EDMtoMEConverter::EDMtoMEConverter(const edm::ParameterSet &iPSet) : verbosity(0), frequency(0) {
0389   const edm::InputTag &runInputTag = iPSet.getParameter<edm::InputTag>("runInputTag");
0390   const edm::InputTag &lumiInputTag = iPSet.getParameter<edm::InputTag>("lumiInputTag");
0391   edm::ConsumesCollector iC = consumesCollector();
0392 
0393   for_each(tokens_, [&](auto &tok) { tok.set(runInputTag, lumiInputTag, iC); });
0394 
0395   constexpr char MsgLoggerCat[] = "EDMtoMEConverter_EDMtoMEConverter";
0396 
0397   // get information from parameter set
0398   name = iPSet.getUntrackedParameter<std::string>("Name");
0399   verbosity = iPSet.getUntrackedParameter<int>("Verbosity");
0400   frequency = iPSet.getUntrackedParameter<int>("Frequency");
0401 
0402   convertOnEndLumi = iPSet.getUntrackedParameter<bool>("convertOnEndLumi", true);
0403   convertOnEndRun = iPSet.getUntrackedParameter<bool>("convertOnEndRun", true);
0404 
0405   auto scopeDecode = std::map<std::string, MonitorElementData::Scope>{{"", MonitorElementData::Scope::LUMI},
0406                                                                       {"LUMI", MonitorElementData::Scope::LUMI},
0407                                                                       {"RUN", MonitorElementData::Scope::RUN},
0408                                                                       {"JOB", MonitorElementData::Scope::JOB}};
0409   reScope = scopeDecode[iPSet.getUntrackedParameter<std::string>("reScope", "")];
0410 
0411   // use value of first digit to determine default output level (inclusive)
0412   // 0 is none, 1 is basic, 2 is fill output, 3 is gather output
0413   verbosity %= 10;
0414 
0415   // print out Parameter Set information being used
0416   if (verbosity >= 0) {
0417     edm::LogInfo(MsgLoggerCat) << "\n===============================\n"
0418                                << "Initialized as EDAnalyzer with parameter values:\n"
0419                                << "    Name          = " << name << "\n"
0420                                << "    Verbosity     = " << verbosity << "\n"
0421                                << "    Frequency     = " << frequency << "\n"
0422                                << "===============================\n";
0423   }
0424 
0425   assert(sizeof(int64_t) == sizeof(long long));
0426   usesResource("DQMStore");
0427 
0428   dqmLumiToken_ = produces<DQMToken, edm::Transition::EndLuminosityBlock>("endLumi");
0429   dqmRunToken_ = produces<DQMToken, edm::Transition::EndRun>("endRun");
0430 }  // end constructor
0431 
0432 void EDMtoMEConverter::endRunProduce(edm::Run &iRun, edm::EventSetup const &iSetup) {
0433   if (convertOnEndRun) {
0434     DQMStore *store = edm::Service<DQMStore>().operator->();
0435     store->meBookerGetter([&](DQMStore::IBooker &b, DQMStore::IGetter &g) { getData(b, g, iRun); });
0436   }
0437 
0438   iRun.put(dqmRunToken_, std::make_unique<DQMToken>());
0439 }
0440 
0441 void EDMtoMEConverter::endLuminosityBlockProduce(edm::LuminosityBlock &iLumi, edm::EventSetup const &iSetup) {
0442   if (convertOnEndLumi) {
0443     DQMStore *store = edm::Service<DQMStore>().operator->();
0444     store->meBookerGetter([&](DQMStore::IBooker &b, DQMStore::IGetter &g) { getData(b, g, iLumi); });
0445   }
0446 
0447   iLumi.put(dqmLumiToken_, std::make_unique<DQMToken>());
0448 }
0449 
0450 template <class T>
0451 void EDMtoMEConverter::getData(DQMStore::IBooker &iBooker, DQMStore::IGetter &iGetter, T &iGetFrom) {
0452   constexpr char MsgLoggerCat[] = "EDMtoMEConverter_getData";
0453 
0454   if (verbosity >= 0)
0455     edm::LogInfo(MsgLoggerCat) << "\nRestoring MonitorElements.";
0456 
0457   for_each(tokens_, [&](const auto &tok) {
0458     using Tokens_T = typename std::decay<decltype(tok)>::type;
0459     using METype = typename Tokens_T::type;
0460     using MEtoEDM_T = typename Tokens_T::Product;
0461     edm::Handle<MEtoEDM_T> metoedm;
0462     tok.getData(iGetFrom, metoedm);
0463     if (!metoedm.isValid()) {
0464       //edm::LogWarning(MsgLoggerCat)
0465       //  << "MEtoEDM<TH1F> doesn't exist in run";
0466       return;
0467     }
0468 
0469     std::vector<typename MEtoEDM_T::MEtoEDMObject> metoedmobject = metoedm->getMEtoEdmObject();
0470 
0471     for (unsigned int i = 0; i < metoedmobject.size(); ++i) {
0472       // get full path of monitor element
0473       const std::string &pathname = metoedmobject[i].name;
0474       if (verbosity > 0)
0475         std::cout << pathname << std::endl;
0476 
0477       // deconstruct path from fullpath
0478       std::filesystem::path fulldir(pathname);
0479       std::string name = fulldir.filename();
0480       std::string dir = fulldir.parent_path();
0481       if (dir == "/")
0482         dir = "";
0483 
0484       // define new monitor element
0485       adjustScope(iBooker, iGetFrom, reScope);
0486       AddMonitorElement<METype>::call(iBooker, iGetter, &metoedmobject[i].object, dir, name, iGetFrom);
0487 
0488     }  // end loop thorugh metoedmobject
0489   });
0490 }
0491 
0492 #include "FWCore/PluginManager/interface/ModuleDef.h"
0493 #include "FWCore/Framework/interface/MakerMacros.h"
0494 DEFINE_FWK_MODULE(EDMtoMEConverter);