Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-10-30 00:11:31

0001 // Note to self: the implementation uses TH1F's to store the L1T and HLT rates.
0002 // Assuming a maximum rate of 100 kHz times a period of 23.31 s, one needs to store counts up to ~2.3e6.
0003 // A "float" has 24 bits of precision, so it can store up to 2**24 ~ 16.7e6 without loss of precision.
0004 
0005 // C++ headers
0006 #include <algorithm>
0007 #include <string>
0008 #include <vector>
0009 
0010 #include <fmt/printf.h>
0011 
0012 // boost headers
0013 #include <boost/regex.hpp>
0014 
0015 // CMSSW headers
0016 #include "CondFormats/DataRecord/interface/L1TUtmTriggerMenuRcd.h"
0017 #include "CondFormats/L1TObjects/interface/L1TUtmTriggerMenu.h"
0018 #include "DQMServices/Core/interface/DQMGlobalEDAnalyzer.h"
0019 #include "DataFormats/Common/interface/TriggerResults.h"
0020 #include "DataFormats/L1TGlobal/interface/GlobalAlgBlk.h"
0021 #include "FWCore/Framework/interface/Event.h"
0022 #include "FWCore/Framework/interface/EventSetup.h"
0023 #include "FWCore/Framework/interface/LuminosityBlock.h"
0024 #include "FWCore/Framework/interface/Run.h"
0025 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0026 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0027 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0028 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0029 #include "HLTrigger/HLTcore/interface/HLTConfigProvider.h"
0030 
0031 namespace {
0032 
0033   using dqm::reco::MonitorElement;
0034 
0035   struct RunBasedHistograms {
0036     // HLT configuration
0037     struct HLTIndices {
0038       unsigned int index_trigger;
0039       unsigned int index_l1_seed;
0040       unsigned int index_prescale;
0041 
0042       HLTIndices()
0043           : index_trigger((unsigned int)-1), index_l1_seed((unsigned int)-1), index_prescale((unsigned int)-1) {}
0044     };
0045 
0046     HLTConfigProvider hltConfig;
0047     std::vector<HLTIndices> hltIndices;
0048 
0049     std::vector<std::vector<unsigned int>> datasets;
0050     std::vector<std::vector<unsigned int>> streams;
0051 
0052     // L1T and HLT rate plots
0053 
0054     // per-path HLT plots
0055     struct HLTRatesPlots {
0056       MonitorElement *pass_l1_seed;
0057       MonitorElement *pass_prescale;
0058       MonitorElement *accept;
0059       MonitorElement *reject;
0060       MonitorElement *error;
0061     };
0062 
0063     // overall event count and event types
0064     MonitorElement *events_processed;
0065     std::vector<MonitorElement *> tcds_counts;
0066 
0067     // L1T triggers
0068     std::vector<MonitorElement *> l1t_counts;
0069 
0070     // HLT triggers
0071     std::vector<HLTRatesPlots> hlt_counts;
0072 
0073     // datasets
0074     std::vector<MonitorElement *> dataset_counts;
0075 
0076     // streams
0077     std::vector<MonitorElement *> stream_counts;
0078 
0079     RunBasedHistograms()
0080         :  // L1T and HLT configuration
0081           hltConfig(),
0082           hltIndices(),
0083           datasets(),
0084           streams(),
0085           // overall event count and event types
0086           events_processed(),
0087           tcds_counts(),
0088           // L1T triggers
0089           l1t_counts(),
0090           // HLT triggers
0091           hlt_counts(),
0092           // datasets
0093           dataset_counts(),
0094           // streams
0095           stream_counts() {}
0096   };
0097 }  // namespace
0098 
0099 class TriggerRatesMonitor : public DQMGlobalEDAnalyzer<RunBasedHistograms> {
0100 public:
0101   explicit TriggerRatesMonitor(edm::ParameterSet const &);
0102   ~TriggerRatesMonitor() override = default;
0103 
0104   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions);
0105 
0106 private:
0107   void dqmBeginRun(edm::Run const &, edm::EventSetup const &, RunBasedHistograms &) const override;
0108   void bookHistograms(DQMStore::IBooker &,
0109                       edm::Run const &,
0110                       edm::EventSetup const &,
0111                       RunBasedHistograms &) const override;
0112   void dqmAnalyze(edm::Event const &, edm::EventSetup const &, RunBasedHistograms const &) const override;
0113 
0114   // TCDS trigger types
0115   // see https://twiki.cern.ch/twiki/bin/viewauth/CMS/TcdsEventRecord
0116   static constexpr const char *const s_tcds_trigger_types[] = {
0117       "Empty",          //  0 - No trigger
0118       "Physics",        //  1 - GT trigger
0119       "Calibration",    //  2 - Sequence trigger (calibration)
0120       "Random",         //  3 - Random trigger
0121       "Auxiliary",      //  4 - Auxiliary (CPM front panel NIM input) trigger
0122       nullptr,          //  5 - reserved
0123       nullptr,          //  6 - reserved
0124       nullptr,          //  7 - reserved
0125       "Cyclic",         //  8 - Cyclic trigger
0126       "Bunch-pattern",  //  9 - Bunch-pattern trigger
0127       "Software",       // 10 - Software trigger
0128       "TTS",            // 11 - TTS-sourced trigger
0129       nullptr,          // 12 - reserved
0130       nullptr,          // 13 - reserved
0131       nullptr,          // 14 - reserved
0132       nullptr           // 15 - reserved
0133   };
0134 
0135   // module configuration
0136   const edm::ESGetToken<L1TUtmTriggerMenu, L1TUtmTriggerMenuRcd> m_l1tMenu_token;
0137   const edm::InputTag m_l1t_results_inputTag;
0138   const edm::EDGetTokenT<GlobalAlgBlkBxCollection> m_l1t_results_token;
0139   const edm::EDGetTokenT<edm::TriggerResults> m_hlt_results_token;
0140   const std::string m_dqm_path;
0141   const uint32_t m_lumisections_range;
0142 };
0143 
0144 // definition
0145 constexpr const char *const TriggerRatesMonitor::s_tcds_trigger_types[];
0146 
0147 void TriggerRatesMonitor::fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0148   edm::ParameterSetDescription desc;
0149   desc.addUntracked<edm::InputTag>("l1tResults", edm::InputTag("gtStage2Digis"));
0150   desc.addUntracked<edm::InputTag>("hltResults", edm::InputTag("TriggerResults"));
0151   desc.addUntracked<std::string>("dqmPath", "HLT/TriggerRates");
0152   desc.addUntracked<uint32_t>("lumisectionRange", 2500);  // ~16 hours
0153   descriptions.add("triggerRatesMonitor", desc);
0154 }
0155 
0156 TriggerRatesMonitor::TriggerRatesMonitor(edm::ParameterSet const &config)
0157     :  // module configuration
0158       m_l1tMenu_token{esConsumes<edm::Transition::BeginRun>()},
0159       m_l1t_results_inputTag{config.getUntrackedParameter<edm::InputTag>("l1tResults")},
0160       m_l1t_results_token{consumes(m_l1t_results_inputTag)},
0161       m_hlt_results_token{consumes(config.getUntrackedParameter<edm::InputTag>("hltResults"))},
0162       m_dqm_path{config.getUntrackedParameter<std::string>("dqmPath")},
0163       m_lumisections_range{config.getUntrackedParameter<uint32_t>("lumisectionRange")} {}
0164 
0165 void TriggerRatesMonitor::dqmBeginRun(edm::Run const &run,
0166                                       edm::EventSetup const &setup,
0167                                       RunBasedHistograms &histograms) const {
0168   histograms.tcds_counts.clear();
0169   histograms.tcds_counts.resize(sizeof(s_tcds_trigger_types) / sizeof(const char *));
0170 
0171   // cache the L1T trigger menu
0172   histograms.l1t_counts.clear();
0173   histograms.l1t_counts.resize(GlobalAlgBlk::maxPhysicsTriggers);
0174 
0175   // initialise the HLTConfigProvider
0176   bool changed = true;
0177   edm::EDConsumerBase::Labels labels;
0178   labelsForToken(m_hlt_results_token, labels);
0179   if (histograms.hltConfig.init(run, setup, labels.process, changed)) {
0180     // number of trigger paths in labels.process
0181     auto const nTriggers = histograms.hltConfig.size();
0182     histograms.hltIndices.clear();
0183     histograms.hltIndices.resize(nTriggers);
0184     histograms.hlt_counts.clear();
0185     histograms.hlt_counts.resize(nTriggers);
0186 
0187     unsigned int const nDatasets = histograms.hltConfig.datasetNames().size();
0188     histograms.datasets.clear();
0189     histograms.datasets.resize(nDatasets);
0190     for (unsigned int i = 0; i < nDatasets; ++i) {
0191       auto const &paths = histograms.hltConfig.datasetContent(i);
0192       histograms.datasets[i].reserve(paths.size());
0193       for (auto const &path : paths) {
0194         auto const triggerIdx = histograms.hltConfig.triggerIndex(path);
0195         if (triggerIdx < nTriggers)
0196           histograms.datasets[i].push_back(triggerIdx);
0197         else
0198           LogDebug("TriggerRatesMonitor")
0199               << "The rates of the HLT path \"" << path << "\" (dataset: \"" << histograms.hltConfig.datasetName(i)
0200               << "\") will not be monitored for this run.\nThis HLT path is not available in the process \""
0201               << labels.process << "\", but it is listed in its \"datasets\" PSet.";
0202       }
0203     }
0204     histograms.dataset_counts.clear();
0205     histograms.dataset_counts.resize(nDatasets);
0206 
0207     unsigned int const nStreams = histograms.hltConfig.streamNames().size();
0208     histograms.streams.clear();
0209     histograms.streams.resize(nStreams);
0210     for (unsigned int i = 0; i < nStreams; ++i) {
0211       for (auto const &dataset : histograms.hltConfig.streamContent(i)) {
0212         for (auto const &path : histograms.hltConfig.datasetContent(dataset)) {
0213           auto const triggerIdx = histograms.hltConfig.triggerIndex(path);
0214           if (triggerIdx < nTriggers)
0215             histograms.streams[i].push_back(triggerIdx);
0216           else
0217             LogDebug("TriggerRatesMonitor")
0218                 << "The rates of the HLT path \"" << path << "\" (stream: \"" << histograms.hltConfig.streamName(i)
0219                 << "\", dataset: \"" << dataset << "\") will not be monitored for this run.\n"
0220                 << "This HLT path is not available in the process \"" << labels.process
0221                 << "\", but it is listed in its \"datasets\" PSet.";
0222         }
0223       }
0224       std::sort(histograms.streams[i].begin(), histograms.streams[i].end());
0225       auto unique_end = std::unique(histograms.streams[i].begin(), histograms.streams[i].end());
0226       histograms.streams[i].resize(unique_end - histograms.streams[i].begin());
0227       histograms.streams[i].shrink_to_fit();
0228     }
0229     histograms.stream_counts.clear();
0230     histograms.stream_counts.resize(nStreams);
0231   } else {
0232     // HLTConfigProvider not initialised, skip the the HLT monitoring
0233     edm::LogError("TriggerRatesMonitor") << "Failed to initialise HLTConfigProvider: the rates of HLT triggers, "
0234                                             "datasets and streams will not be monitored for this run.";
0235   }
0236 }
0237 
0238 void TriggerRatesMonitor::bookHistograms(DQMStore::IBooker &booker,
0239                                          edm::Run const &run,
0240                                          edm::EventSetup const &setup,
0241                                          RunBasedHistograms &histograms) const {
0242   // book histograms for the overall event count, and trigger types
0243   booker.setCurrentFolder(m_dqm_path);
0244   histograms.events_processed = booker.book1D(
0245       "events", "Processed events vs. lumisection", m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
0246   booker.setCurrentFolder(m_dqm_path + "/TCDS");
0247   unsigned int const sizeof_tcds_trigger_types = sizeof(s_tcds_trigger_types) / sizeof(const char *);
0248   if (sizeof_tcds_trigger_types == histograms.tcds_counts.size()) {
0249     for (unsigned int i = 0; i < sizeof_tcds_trigger_types; ++i)
0250       if (s_tcds_trigger_types[i]) {
0251         std::string const &title = fmt::sprintf("%s events vs. lumisection", s_tcds_trigger_types[i]);
0252         histograms.tcds_counts[i] =
0253             booker.book1D(s_tcds_trigger_types[i], title, m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
0254       }
0255   } else
0256     edm::LogError("TriggerRatesMonitor")
0257         << "This should never happen: size of \"s_tcds_trigger_types\" array (" << sizeof_tcds_trigger_types
0258         << ") differs from size of \"histograms.tcds_counts\" vector (size=" << histograms.tcds_counts.size()
0259         << ").\nRate histograms of TCDS trigger types will not be booked for this run.";
0260 
0261   // book the rate histograms for the L1T triggers that are included in the L1T menu
0262   booker.setCurrentFolder(m_dqm_path + "/L1T");
0263   auto const &l1tMenu = setup.getData(m_l1tMenu_token);
0264   for (auto const &keyval : l1tMenu.getAlgorithmMap()) {
0265     unsigned int const bit = keyval.second.getIndex();
0266     if (bit >= histograms.l1t_counts.size()) {
0267       edm::LogError("TriggerRatesMonitor")
0268           << "This should never happen: bit of L1T algorithm (bit=" << bit << ", name=\"" << keyval.first
0269           << "\") is not smaller than size of \"histograms.l1t_counts\" vector (size=" << histograms.l1t_counts.size()
0270           << ").\nRate histogram of this L1T algorithm will not be booked for this run.";
0271       continue;
0272     }
0273     bool masked = false;  // FIXME read L1T masks once they will be avaiable in the EventSetup
0274     std::string const &name = fmt::sprintf("%s (bit %d)", keyval.first, bit);
0275     std::string const &title =
0276         fmt::sprintf("%s (bit %d)%s vs. lumisection", keyval.first, bit, (masked ? " (masked)" : ""));
0277     histograms.l1t_counts[bit] = booker.book1D(name, title, m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
0278   }
0279 
0280   if (histograms.hltConfig.inited()) {
0281     // book the rate histograms for the HLT triggers
0282     auto const &triggerNames = histograms.hltConfig.triggerNames();
0283     for (unsigned int i = 0; i < triggerNames.size(); ++i) {
0284       std::string const &name = triggerNames[i];
0285       booker.setCurrentFolder(m_dqm_path + "/HLT/" + name);
0286 
0287       histograms.hlt_counts[i].pass_l1_seed = booker.book1D(name + "_pass_L1_seed",
0288                                                             name + " pass L1 seed, vs. lumisection",
0289                                                             m_lumisections_range + 1,
0290                                                             -0.5,
0291                                                             m_lumisections_range + 0.5);
0292       histograms.hlt_counts[i].pass_prescale = booker.book1D(name + "_pass_prescaler",
0293                                                              name + " pass prescaler, vs. lumisection",
0294                                                              m_lumisections_range + 1,
0295                                                              -0.5,
0296                                                              m_lumisections_range + 0.5);
0297       histograms.hlt_counts[i].accept = booker.book1D(name + "_accept",
0298                                                       name + " accept, vs. lumisection",
0299                                                       m_lumisections_range + 1,
0300                                                       -0.5,
0301                                                       m_lumisections_range + 0.5);
0302       histograms.hlt_counts[i].reject = booker.book1D(name + "_reject",
0303                                                       name + " reject, vs. lumisection",
0304                                                       m_lumisections_range + 1,
0305                                                       -0.5,
0306                                                       m_lumisections_range + 0.5);
0307       histograms.hlt_counts[i].error = booker.book1D(
0308           name + "_error", name + " error, vs. lumisection", m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
0309 
0310       // set trigger index, and indices of the (last) L1T seed and prescale module in each path
0311       histograms.hltIndices[i].index_trigger = histograms.hltConfig.triggerIndex(name);
0312       histograms.hltIndices[i].index_l1_seed = histograms.hltConfig.size(i);
0313       histograms.hltIndices[i].index_prescale = histograms.hltConfig.size(i);
0314       for (unsigned int j = 0; j < histograms.hltConfig.size(i); ++j) {
0315         std::string const &label = histograms.hltConfig.moduleLabel(i, j);
0316         std::string const &type = histograms.hltConfig.moduleType(label);
0317         if (type == "HLTL1TSeed" or type == "HLTLevel1GTSeed" or type == "HLTLevel1Activity" or
0318             type == "HLTLevel1Pattern") {
0319           // there might be more L1T seed filters in sequence
0320           // keep looking and store the index of the last one
0321           histograms.hltIndices[i].index_l1_seed = j;
0322         } else if (type == "HLTPrescaler") {
0323           // there should be only one prescaler in a path, and it should follow all L1T seed filters
0324           histograms.hltIndices[i].index_prescale = j;
0325           break;
0326         }
0327       }
0328     }
0329 
0330     // book the rate histograms for the HLT datasets
0331     booker.setCurrentFolder(m_dqm_path + "/Datasets");
0332     auto const &datasetNames = histograms.hltConfig.datasetNames();
0333     for (unsigned int i = 0; i < datasetNames.size(); ++i)
0334       histograms.dataset_counts[i] =
0335           booker.book1D(datasetNames[i], datasetNames[i], m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
0336 
0337     // book the rate histograms for the HLT streams
0338     booker.setCurrentFolder(m_dqm_path + "/Streams");
0339     auto const &streamNames = histograms.hltConfig.streamNames();
0340     for (unsigned int i = 0; i < streamNames.size(); ++i)
0341       histograms.stream_counts[i] =
0342           booker.book1D(streamNames[i], streamNames[i], m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
0343   }
0344 }
0345 
0346 void TriggerRatesMonitor::dqmAnalyze(edm::Event const &event,
0347                                      edm::EventSetup const &setup,
0348                                      RunBasedHistograms const &histograms) const {
0349   unsigned int lumisection = event.luminosityBlock();
0350 
0351   // monitor the overall event count and event types rates
0352   histograms.events_processed->Fill(lumisection);
0353   if (histograms.tcds_counts[event.experimentType()])
0354     histograms.tcds_counts[event.experimentType()]->Fill(lumisection);
0355 
0356   // monitor the rates of L1T triggers
0357   auto const &algBlkBxVecHandle = event.getHandle(m_l1t_results_token);
0358   if (not algBlkBxVecHandle.isValid()) {
0359     edm::LogError("TriggerRatesMonitor")
0360         << "L1 trigger results with label [" << m_l1t_results_inputTag.encode()
0361         << "] not present or invalid. MonitorElements of L1T results not filled for this event.";
0362   } else if (algBlkBxVecHandle->isEmpty(0)) {
0363     edm::LogError("TriggerRatesMonitor")
0364         << "L1 trigger results with label [" << m_l1t_results_inputTag.encode()
0365         << "] empty for BX=0. MonitorElements of L1T results not filled for this event.";
0366   } else {
0367     auto const &results = algBlkBxVecHandle->at(0, 0);
0368     for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i)
0369       if (results.getAlgoDecisionFinal(i))
0370         if (histograms.l1t_counts[i])
0371           histograms.l1t_counts[i]->Fill(lumisection);
0372   }
0373 
0374   // monitor the rates of HLT triggers, datasets and streams
0375   if (histograms.hltConfig.inited()) {
0376     auto const &hltResults = event.get(m_hlt_results_token);
0377     if (hltResults.size() != histograms.hltIndices.size()) {
0378       edm::LogError("TriggerRatesMonitor")
0379           << "This should never happen: the number of HLT paths has changed since the beginning of the run"
0380           << " (from " << histograms.hltIndices.size() << " to " << hltResults.size() << ").\n"
0381           << "Histograms for rates of HLT paths, datasets and streams will not be filled for this event.";
0382       return;
0383     }
0384 
0385     for (unsigned int i = 0; i < histograms.hltIndices.size(); ++i) {
0386       auto const index = histograms.hltIndices[i].index_trigger;
0387       edm::HLTPathStatus const &path = hltResults[index];
0388 
0389       if (path.index() > histograms.hltIndices[i].index_l1_seed)
0390         histograms.hlt_counts[i].pass_l1_seed->Fill(lumisection);
0391       if (path.index() > histograms.hltIndices[i].index_prescale)
0392         histograms.hlt_counts[i].pass_prescale->Fill(lumisection);
0393       if (path.accept())
0394         histograms.hlt_counts[i].accept->Fill(lumisection);
0395       else if (path.error())
0396         histograms.hlt_counts[i].error->Fill(lumisection);
0397       else
0398         histograms.hlt_counts[i].reject->Fill(lumisection);
0399     }
0400 
0401     for (unsigned int d = 0; d < histograms.datasets.size(); ++d) {
0402       for (unsigned int i : histograms.datasets[d]) {
0403         if (hltResults[i].accept()) {
0404           histograms.dataset_counts[d]->Fill(lumisection);
0405           // ensure each dataset is incremented only once per event
0406           break;
0407         }
0408       }
0409     }
0410 
0411     for (unsigned int i = 0; i < histograms.streams.size(); ++i) {
0412       for (unsigned int j : histograms.streams[i]) {
0413         if (hltResults[j].accept()) {
0414           histograms.stream_counts[i]->Fill(lumisection);
0415           // ensure each stream is incremented only once per event
0416           break;
0417         }
0418       }
0419     }
0420   }
0421 }
0422 
0423 // define this as a plugin
0424 #include "FWCore/Framework/interface/MakerMacros.h"
0425 DEFINE_FWK_MODULE(TriggerRatesMonitor);