Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #ifndef CORE_DQMED_HARVESTER_H
0002 #define CORE_DQMED_HARVESTER_H
0003 
0004 #include "DQMServices/Core/interface/DQMStore.h"
0005 
0006 #include "FWCore/Framework/interface/one/EDProducer.h"
0007 
0008 #include "FWCore/Framework/interface/Run.h"
0009 #include "FWCore/Framework/interface/Event.h"
0010 #include "FWCore/Framework/interface/EventSetup.h"
0011 #include "FWCore/Framework/interface/LuminosityBlock.h"
0012 #include "FWCore/Framework/interface/InputTagMatch.h"
0013 #include "FWCore/Framework/interface/GetterOfProducts.h"
0014 #include "FWCore/ServiceRegistry/interface/Service.h"
0015 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0016 #include "FWCore/Utilities/interface/EDPutToken.h"
0017 
0018 #include "DataFormats/Histograms/interface/DQMToken.h"
0019 
0020 namespace edm {
0021   class VInputTagMatch {
0022   public:
0023     VInputTagMatch(std::vector<edm::InputTag> const &inputTags) {
0024       for (auto &tag : inputTags) {
0025         matchers_.emplace_back(InputTagMatch(tag));
0026       }
0027     }
0028 
0029     bool operator()(edm::BranchDescription const &branchDescription) {
0030       for (auto &m : matchers_) {
0031         if (m(branchDescription)) {
0032           return true;
0033         }
0034       }
0035       return false;
0036     }
0037 
0038   private:
0039     std::vector<InputTagMatch> matchers_;
0040   };
0041 }  // namespace edm
0042 
0043 class DQMEDHarvester
0044     : public edm::one::EDProducer<edm::EndLuminosityBlockProducer,
0045                                   edm::EndRunProducer,
0046                                   edm::EndProcessBlockProducer,
0047                                   edm::one::WatchLuminosityBlocks,
0048                                   edm::one::WatchRuns,
0049                                   // for uncontrolled DQMStore access, and that EDM does not even attempt to
0050                                   // run things in parallel (which would then be blocked by the booking lock).
0051                                   edm::one::SharedResources,
0052                                   edm::Accumulator> {
0053 public:
0054   typedef dqm::harvesting::DQMStore DQMStore;
0055   typedef dqm::harvesting::MonitorElement MonitorElement;
0056 
0057 protected:
0058   DQMStore *dqmstore_;
0059   edm::GetterOfProducts<DQMToken> jobmegetter_;
0060   edm::GetterOfProducts<DQMToken> runmegetter_;
0061   edm::GetterOfProducts<DQMToken> lumimegetter_;
0062   edm::EDPutTokenT<DQMToken> lumiToken_;
0063   edm::EDPutTokenT<DQMToken> runToken_;
0064   edm::EDPutTokenT<DQMToken> jobToken_;
0065 
0066 public:
0067   DQMEDHarvester(edm::ParameterSet const &iConfig) {
0068     usesResource("DQMStore");
0069     dqmstore_ = edm::Service<DQMStore>().operator->();
0070 
0071     auto inputgeneration = iConfig.getUntrackedParameter<std::string>("inputGeneration", "DQMGenerationReco");
0072     auto outputgeneration = iConfig.getUntrackedParameter<std::string>("outputGeneration", "DQMGenerationHarvesting");
0073 
0074     // TODO: Run/Lumi suffix should not be needed, complain to CMSSW core in case.
0075     lumiToken_ = produces<DQMToken, edm::Transition::EndLuminosityBlock>(outputgeneration + "Lumi");
0076     runToken_ = produces<DQMToken, edm::Transition::EndRun>(outputgeneration + "Run");
0077     jobToken_ = produces<DQMToken, edm::Transition::EndProcessBlock>(outputgeneration + "Job");
0078 
0079     // Use explicitly specified inputs, but if there are none...
0080     auto inputtags =
0081         iConfig.getUntrackedParameter<std::vector<edm::InputTag>>("inputMEs", std::vector<edm::InputTag>());
0082     if (inputtags.empty()) {
0083       // ... use all RECO MEs.
0084       inputtags.push_back(edm::InputTag("", inputgeneration + "Job"));
0085       inputtags.push_back(edm::InputTag("", inputgeneration + "Run"));
0086       inputtags.push_back(edm::InputTag("", inputgeneration + "Lumi"));
0087     }
0088     jobmegetter_ = edm::GetterOfProducts<DQMToken>(edm::VInputTagMatch(inputtags), this, edm::InProcess);
0089     runmegetter_ = edm::GetterOfProducts<DQMToken>(edm::VInputTagMatch(inputtags), this, edm::InRun);
0090     lumimegetter_ = edm::GetterOfProducts<DQMToken>(edm::VInputTagMatch(inputtags), this, edm::InLumi);
0091     callWhenNewProductsRegistered([this](edm::BranchDescription const &bd) {
0092       jobmegetter_(bd);
0093       runmegetter_(bd);
0094       lumimegetter_(bd);
0095     });
0096   };
0097 
0098   DQMEDHarvester() : DQMEDHarvester(edm::ParameterSet()){};
0099 
0100   void beginJob() override{};
0101 
0102   void beginRun(edm::Run const &run, edm::EventSetup const &) override {
0103     // According to edm experts, it is never save to look at run products
0104     // in beginRun, since they might be merged as new input files how up.
0105   }
0106 
0107   void beginLuminosityBlock(edm::LuminosityBlock const &lumi, edm::EventSetup const &) final {
0108     // According to edm experts, it is never save to look at run products
0109     // in beginRun, since they might be merged as new input files how up.
0110   }
0111 
0112   void accumulate(edm::Event const &ev, edm::EventSetup const &es) final {
0113     dqmstore_->meBookerGetter([this, &ev, &es](DQMStore::IBooker &b, DQMStore::IGetter &g) {
0114       b.setScope(MonitorElementData::Scope::JOB);
0115       this->dqmAnalyze(b, g, ev, es);
0116     });
0117   }
0118 
0119   void endLuminosityBlockProduce(edm::LuminosityBlock &lumi, edm::EventSetup const &es) final {
0120     // No need to actually get products for now
0121     //auto refs = std::vector<edm::Handle<DQMToken>>();
0122     //lumimegetter_.fillHandles(lumi, refs);
0123 
0124     dqmstore_->meBookerGetter([this, &lumi, &es](DQMStore::IBooker &b, DQMStore::IGetter &g) {
0125       b.setScope(MonitorElementData::Scope::JOB);
0126       this->dqmEndLuminosityBlock(b, g, lumi, es);
0127     });
0128 
0129     lumi.put(lumiToken_, std::make_unique<DQMToken>());
0130   }
0131 
0132   void endLuminosityBlock(edm::LuminosityBlock const &, edm::EventSetup const &) final{};
0133 
0134   void endRunProduce(edm::Run &run, edm::EventSetup const &es) final {
0135     dqmstore_->meBookerGetter([this, &run, &es](DQMStore::IBooker &b, DQMStore::IGetter &g) {
0136       b.setScope(MonitorElementData::Scope::JOB);
0137       this->dqmEndRun(b, g, run, es);
0138     });
0139 
0140     run.put(runToken_, std::make_unique<DQMToken>());
0141   }
0142 
0143   void endRun(edm::Run const &, edm::EventSetup const &) override{};
0144 
0145   void endProcessBlockProduce(edm::ProcessBlock &) final {
0146     dqmstore_->meBookerGetter([this](DQMStore::IBooker &b, DQMStore::IGetter &g) {
0147       b.setScope(MonitorElementData::Scope::JOB);
0148       this->dqmEndJob(b, g);
0149     });
0150   };
0151 
0152   ~DQMEDHarvester() override = default;
0153 
0154   // DQM_EXPERIMENTAL
0155   // Could be used for niche workflows like commissioning.
0156   // Real harvesting jobs have no events and will never call this.
0157   virtual void dqmAnalyze(DQMStore::IBooker &, DQMStore::IGetter &, edm::Event const &, edm::EventSetup const &){};
0158   virtual void dqmEndLuminosityBlock(DQMStore::IBooker &,
0159                                      DQMStore::IGetter &,
0160                                      edm::LuminosityBlock const &,
0161                                      edm::EventSetup const &){};
0162   // HARVESTING should happen in endJob (or endLumi, for online), but there can
0163   // be applications for end-run harvesting. Better to have a callback than
0164   // have unprotected DQMStore access.
0165   virtual void dqmEndRun(DQMStore::IBooker &, DQMStore::IGetter &, edm::Run const &, edm::EventSetup const &){};
0166   virtual void dqmEndJob(DQMStore::IBooker &, DQMStore::IGetter &) = 0;
0167 };
0168 
0169 #endif  // CORE_DQMED_HARVESTER_H