Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-05-07 00:41:13

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