CMS 3D CMS Logo

TriggerRatesMonitor.cc
Go to the documentation of this file.
1 // Note to self: the implementation uses TH1F's to store the L1T and HLT rates.
2 // Assuming a maximum rate of 100 kHz times a period of 23.31 s, one needs to store counts up to ~2.3e6.
3 // A "float" has 24 bits of precision, so it can store up to 2**24 ~ 16.7e6 without loss of precision.
4 
5 // C++ headers
6 #include <algorithm>
7 #include <string>
8 #include <vector>
9 
10 #include <fmt/printf.h>
11 
12 // boost headers
13 #include <boost/regex.hpp>
14 
15 // CMSSW headers
30 
31 namespace {
32 
34 
35  struct RunBasedHistograms {
36  // HLT configuration
37  struct HLTIndices {
38  unsigned int index_trigger;
39  unsigned int index_l1_seed;
40  unsigned int index_prescale;
41 
42  HLTIndices()
43  : index_trigger((unsigned int)-1), index_l1_seed((unsigned int)-1), index_prescale((unsigned int)-1) {}
44  };
45 
47  std::vector<HLTIndices> hltIndices;
48 
49  std::vector<std::vector<unsigned int>> datasets;
50  std::vector<std::vector<unsigned int>> streams;
51 
52  // L1T and HLT rate plots
53 
54  // per-path HLT plots
55  struct HLTRatesPlots {
56  MonitorElement *pass_l1_seed;
57  MonitorElement *pass_prescale;
61  };
62 
63  // overall event count and event types
64  MonitorElement *events_processed;
65  std::vector<MonitorElement *> tcds_counts;
66 
67  // L1T triggers
68  std::vector<MonitorElement *> l1t_counts;
69 
70  // HLT triggers
71  std::vector<HLTRatesPlots> hlt_counts;
72 
73  // datasets
74  std::vector<MonitorElement *> dataset_counts;
75 
76  // streams
77  std::vector<MonitorElement *> stream_counts;
78 
79  RunBasedHistograms()
80  : // L1T and HLT configuration
81  hltConfig(),
82  hltIndices(),
83  datasets(),
84  streams(),
85  // overall event count and event types
86  events_processed(),
87  tcds_counts(),
88  // L1T triggers
89  l1t_counts(),
90  // HLT triggers
91  hlt_counts(),
92  // datasets
93  dataset_counts(),
94  // streams
95  stream_counts() {}
96  };
97 } // namespace
98 
99 class TriggerRatesMonitor : public DQMGlobalEDAnalyzer<RunBasedHistograms> {
100 public:
101  explicit TriggerRatesMonitor(edm::ParameterSet const &);
102  ~TriggerRatesMonitor() override = default;
103 
104  static void fillDescriptions(edm::ConfigurationDescriptions &descriptions);
105 
106 private:
107  void dqmBeginRun(edm::Run const &, edm::EventSetup const &, RunBasedHistograms &) const override;
109  edm::Run const &,
110  edm::EventSetup const &,
111  RunBasedHistograms &) const override;
112  void dqmAnalyze(edm::Event const &, edm::EventSetup const &, RunBasedHistograms const &) const override;
113 
114  // TCDS trigger types
115  // see https://twiki.cern.ch/twiki/bin/viewauth/CMS/TcdsEventRecord
116  static constexpr const char *const s_tcds_trigger_types[] = {
117  "Empty", // 0 - No trigger
118  "Physics", // 1 - GT trigger
119  "Calibration", // 2 - Sequence trigger (calibration)
120  "Random", // 3 - Random trigger
121  "Auxiliary", // 4 - Auxiliary (CPM front panel NIM input) trigger
122  nullptr, // 5 - reserved
123  nullptr, // 6 - reserved
124  nullptr, // 7 - reserved
125  "Cyclic", // 8 - Cyclic trigger
126  "Bunch-pattern", // 9 - Bunch-pattern trigger
127  "Software", // 10 - Software trigger
128  "TTS", // 11 - TTS-sourced trigger
129  nullptr, // 12 - reserved
130  nullptr, // 13 - reserved
131  nullptr, // 14 - reserved
132  nullptr // 15 - reserved
133  };
134 
135  // module configuration
141  const uint32_t m_lumisections_range;
142 };
143 
144 // definition
146 
149  desc.addUntracked<edm::InputTag>("l1tResults", edm::InputTag("gtStage2Digis"));
150  desc.addUntracked<edm::InputTag>("hltResults", edm::InputTag("TriggerResults"));
151  desc.addUntracked<std::string>("dqmPath", "HLT/TriggerRates");
152  desc.addUntracked<uint32_t>("lumisectionRange", 2500); // ~16 hours
153  descriptions.add("triggerRatesMonitor", desc);
154 }
155 
157  : // module configuration
158  m_l1tMenu_token{esConsumes<edm::Transition::BeginRun>()},
159  m_l1t_results_inputTag{config.getUntrackedParameter<edm::InputTag>("l1tResults")},
160  m_l1t_results_token{consumes(m_l1t_results_inputTag)},
161  m_hlt_results_token{consumes(config.getUntrackedParameter<edm::InputTag>("hltResults"))},
162  m_dqm_path{config.getUntrackedParameter<std::string>("dqmPath")},
163  m_lumisections_range{config.getUntrackedParameter<uint32_t>("lumisectionRange")} {}
164 
166  edm::EventSetup const &setup,
167  RunBasedHistograms &histograms) const {
168  histograms.tcds_counts.clear();
169  histograms.tcds_counts.resize(sizeof(s_tcds_trigger_types) / sizeof(const char *));
170 
171  // cache the L1T trigger menu
172  histograms.l1t_counts.clear();
173  histograms.l1t_counts.resize(GlobalAlgBlk::maxPhysicsTriggers);
174 
175  // initialise the HLTConfigProvider
176  bool changed = true;
179  if (histograms.hltConfig.init(run, setup, labels.process, changed)) {
180  // number of trigger paths in labels.process
181  auto const nTriggers = histograms.hltConfig.size();
182  histograms.hltIndices.clear();
183  histograms.hltIndices.resize(nTriggers);
184  histograms.hlt_counts.clear();
185  histograms.hlt_counts.resize(nTriggers);
186 
187  unsigned int const nDatasets = histograms.hltConfig.datasetNames().size();
188  histograms.datasets.clear();
189  histograms.datasets.resize(nDatasets);
190  for (unsigned int i = 0; i < nDatasets; ++i) {
191  auto const &paths = histograms.hltConfig.datasetContent(i);
192  histograms.datasets[i].reserve(paths.size());
193  for (auto const &path : paths) {
194  auto const triggerIdx = histograms.hltConfig.triggerIndex(path);
195  if (triggerIdx < nTriggers)
196  histograms.datasets[i].push_back(triggerIdx);
197  else
198  LogDebug("TriggerRatesMonitor")
199  << "The rates of the HLT path \"" << path << "\" (dataset: \"" << histograms.hltConfig.datasetName(i)
200  << "\") will not be monitored for this run.\nThis HLT path is not available in the process \""
201  << labels.process << "\", but it is listed in its \"datasets\" PSet.";
202  }
203  }
204  histograms.dataset_counts.clear();
205  histograms.dataset_counts.resize(nDatasets);
206 
207  unsigned int const nStreams = histograms.hltConfig.streamNames().size();
208  histograms.streams.clear();
209  histograms.streams.resize(nStreams);
210  for (unsigned int i = 0; i < nStreams; ++i) {
211  for (auto const &dataset : histograms.hltConfig.streamContent(i)) {
212  for (auto const &path : histograms.hltConfig.datasetContent(dataset)) {
213  auto const triggerIdx = histograms.hltConfig.triggerIndex(path);
214  if (triggerIdx < nTriggers)
215  histograms.streams[i].push_back(triggerIdx);
216  else
217  LogDebug("TriggerRatesMonitor")
218  << "The rates of the HLT path \"" << path << "\" (stream: \"" << histograms.hltConfig.streamName(i)
219  << "\", dataset: \"" << dataset << "\") will not be monitored for this run.\n"
220  << "This HLT path is not available in the process \"" << labels.process
221  << "\", but it is listed in its \"datasets\" PSet.";
222  }
223  }
224  std::sort(histograms.streams[i].begin(), histograms.streams[i].end());
225  auto unique_end = std::unique(histograms.streams[i].begin(), histograms.streams[i].end());
226  histograms.streams[i].resize(unique_end - histograms.streams[i].begin());
227  histograms.streams[i].shrink_to_fit();
228  }
229  histograms.stream_counts.clear();
230  histograms.stream_counts.resize(nStreams);
231  } else {
232  // HLTConfigProvider not initialised, skip the the HLT monitoring
233  edm::LogError("TriggerRatesMonitor") << "Failed to initialise HLTConfigProvider: the rates of HLT triggers, "
234  "datasets and streams will not be monitored for this run.";
235  }
236 }
237 
239  edm::Run const &run,
240  edm::EventSetup const &setup,
241  RunBasedHistograms &histograms) const {
242  // book histograms for the overall event count, and trigger types
244  histograms.events_processed = booker.book1D(
245  "events", "Processed events vs. lumisection", m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
246  booker.setCurrentFolder(m_dqm_path + "/TCDS");
247  unsigned int const sizeof_tcds_trigger_types = sizeof(s_tcds_trigger_types) / sizeof(const char *);
248  if (sizeof_tcds_trigger_types == histograms.tcds_counts.size()) {
249  for (unsigned int i = 0; i < sizeof_tcds_trigger_types; ++i)
250  if (s_tcds_trigger_types[i]) {
251  std::string const &title = fmt::sprintf("%s events vs. lumisection", s_tcds_trigger_types[i]);
252  histograms.tcds_counts[i] =
254  }
255  } else
256  edm::LogError("TriggerRatesMonitor")
257  << "This should never happen: size of \"s_tcds_trigger_types\" array (" << sizeof_tcds_trigger_types
258  << ") differs from size of \"histograms.tcds_counts\" vector (size=" << histograms.tcds_counts.size()
259  << ").\nRate histograms of TCDS trigger types will not be booked for this run.";
260 
261  // book the rate histograms for the L1T triggers that are included in the L1T menu
262  booker.setCurrentFolder(m_dqm_path + "/L1T");
263  auto const &l1tMenu = setup.getData(m_l1tMenu_token);
264  for (auto const &keyval : l1tMenu.getAlgorithmMap()) {
265  unsigned int const bit = keyval.second.getIndex();
266  if (bit >= histograms.l1t_counts.size()) {
267  edm::LogError("TriggerRatesMonitor")
268  << "This should never happen: bit of L1T algorithm (bit=" << bit << ", name=\"" << keyval.first
269  << "\") is not smaller than size of \"histograms.l1t_counts\" vector (size=" << histograms.l1t_counts.size()
270  << ").\nRate histogram of this L1T algorithm will not be booked for this run.";
271  continue;
272  }
273  bool masked = false; // FIXME read L1T masks once they will be avaiable in the EventSetup
274  std::string const &name = fmt::sprintf("%s (bit %d)", keyval.first, bit);
275  std::string const &title =
276  fmt::sprintf("%s (bit %d)%s vs. lumisection", keyval.first, bit, (masked ? " (masked)" : ""));
277  histograms.l1t_counts[bit] = booker.book1D(name, title, m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
278  }
279 
280  if (histograms.hltConfig.inited()) {
281  // book the rate histograms for the HLT triggers
282  auto const &triggerNames = histograms.hltConfig.triggerNames();
283  for (unsigned int i = 0; i < triggerNames.size(); ++i) {
284  std::string const &name = triggerNames[i];
285  booker.setCurrentFolder(m_dqm_path + "/HLT/" + name);
286 
287  histograms.hlt_counts[i].pass_l1_seed = booker.book1D(name + "_pass_L1_seed",
288  name + " pass L1 seed, vs. lumisection",
290  -0.5,
291  m_lumisections_range + 0.5);
292  histograms.hlt_counts[i].pass_prescale = booker.book1D(name + "_pass_prescaler",
293  name + " pass prescaler, vs. lumisection",
295  -0.5,
296  m_lumisections_range + 0.5);
297  histograms.hlt_counts[i].accept = booker.book1D(name + "_accept",
298  name + " accept, vs. lumisection",
300  -0.5,
301  m_lumisections_range + 0.5);
302  histograms.hlt_counts[i].reject = booker.book1D(name + "_reject",
303  name + " reject, vs. lumisection",
305  -0.5,
306  m_lumisections_range + 0.5);
307  histograms.hlt_counts[i].error = booker.book1D(
308  name + "_error", name + " error, vs. lumisection", m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
309 
310  // set trigger index, and indices of the (last) L1T seed and prescale module in each path
311  histograms.hltIndices[i].index_trigger = histograms.hltConfig.triggerIndex(name);
312  histograms.hltIndices[i].index_l1_seed = histograms.hltConfig.size(i);
313  histograms.hltIndices[i].index_prescale = histograms.hltConfig.size(i);
314  for (unsigned int j = 0; j < histograms.hltConfig.size(i); ++j) {
315  std::string const &label = histograms.hltConfig.moduleLabel(i, j);
316  std::string const &type = histograms.hltConfig.moduleType(label);
317  if (type == "HLTL1TSeed" or type == "HLTLevel1GTSeed" or type == "HLTLevel1Activity" or
318  type == "HLTLevel1Pattern") {
319  // there might be more L1T seed filters in sequence
320  // keep looking and store the index of the last one
321  histograms.hltIndices[i].index_l1_seed = j;
322  } else if (type == "HLTPrescaler") {
323  // there should be only one prescaler in a path, and it should follow all L1T seed filters
324  histograms.hltIndices[i].index_prescale = j;
325  break;
326  }
327  }
328  }
329 
330  // book the rate histograms for the HLT datasets
331  booker.setCurrentFolder(m_dqm_path + "/Datasets");
332  auto const &datasetNames = histograms.hltConfig.datasetNames();
333  for (unsigned int i = 0; i < datasetNames.size(); ++i)
334  histograms.dataset_counts[i] =
336 
337  // book the rate histograms for the HLT streams
338  booker.setCurrentFolder(m_dqm_path + "/Streams");
339  auto const &streamNames = histograms.hltConfig.streamNames();
340  for (unsigned int i = 0; i < streamNames.size(); ++i)
341  histograms.stream_counts[i] =
342  booker.book1D(streamNames[i], streamNames[i], m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
343  }
344 }
345 
347  edm::EventSetup const &setup,
348  RunBasedHistograms const &histograms) const {
349  unsigned int lumisection = event.luminosityBlock();
350 
351  // monitor the overall event count and event types rates
352  histograms.events_processed->Fill(lumisection);
353  if (histograms.tcds_counts[event.experimentType()])
354  histograms.tcds_counts[event.experimentType()]->Fill(lumisection);
355 
356  // monitor the rates of L1T triggers
357  auto const &algBlkBxVecHandle = event.getHandle(m_l1t_results_token);
358  if (not algBlkBxVecHandle.isValid()) {
359  edm::LogError("TriggerRatesMonitor")
360  << "L1 trigger results with label [" << m_l1t_results_inputTag.encode()
361  << "] not present or invalid. MonitorElements of L1T results not filled for this event.";
362  } else if (algBlkBxVecHandle->isEmpty(0)) {
363  edm::LogError("TriggerRatesMonitor")
364  << "L1 trigger results with label [" << m_l1t_results_inputTag.encode()
365  << "] empty for BX=0. MonitorElements of L1T results not filled for this event.";
366  } else {
367  auto const &results = algBlkBxVecHandle->at(0, 0);
368  for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i)
369  if (results.getAlgoDecisionFinal(i))
370  if (histograms.l1t_counts[i])
371  histograms.l1t_counts[i]->Fill(lumisection);
372  }
373 
374  // monitor the rates of HLT triggers, datasets and streams
375  if (histograms.hltConfig.inited()) {
376  auto const &hltResults = event.get(m_hlt_results_token);
377  if (hltResults.size() != histograms.hltIndices.size()) {
378  edm::LogError("TriggerRatesMonitor")
379  << "This should never happen: the number of HLT paths has changed since the beginning of the run"
380  << " (from " << histograms.hltIndices.size() << " to " << hltResults.size() << ").\n"
381  << "Histograms for rates of HLT paths, datasets and streams will not be filled for this event.";
382  return;
383  }
384 
385  for (unsigned int i = 0; i < histograms.hltIndices.size(); ++i) {
386  auto const index = histograms.hltIndices[i].index_trigger;
388 
389  if (path.index() > histograms.hltIndices[i].index_l1_seed)
390  histograms.hlt_counts[i].pass_l1_seed->Fill(lumisection);
391  if (path.index() > histograms.hltIndices[i].index_prescale)
392  histograms.hlt_counts[i].pass_prescale->Fill(lumisection);
393  if (path.accept())
394  histograms.hlt_counts[i].accept->Fill(lumisection);
395  else if (path.error())
396  histograms.hlt_counts[i].error->Fill(lumisection);
397  else
398  histograms.hlt_counts[i].reject->Fill(lumisection);
399  }
400 
401  for (unsigned int d = 0; d < histograms.datasets.size(); ++d) {
402  for (unsigned int i : histograms.datasets[d]) {
403  if (hltResults[i].accept()) {
404  histograms.dataset_counts[d]->Fill(lumisection);
405  // ensure each dataset is incremented only once per event
406  break;
407  }
408  }
409  }
410 
411  for (unsigned int i = 0; i < histograms.streams.size(); ++i) {
412  for (unsigned int j : histograms.streams[i]) {
413  if (hltResults[j].accept()) {
414  histograms.stream_counts[i]->Fill(lumisection);
415  // ensure each stream is incremented only once per event
416  break;
417  }
418  }
419  }
420  }
421 }
422 
423 // define this as a plugin
void dqmBeginRun(edm::Run const &, edm::EventSetup const &, RunBasedHistograms &) const override
const std::string m_dqm_path
dqm::impl::MonitorElement MonitorElement
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:36
std::string encode() const
Definition: InputTag.cc:159
const edm::EDGetTokenT< edm::TriggerResults > m_hlt_results_token
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
Definition: config.py:1
Log< level::Error, false > LogError
const uint32_t m_lumisections_range
bool accept(const edm::Event &event, const edm::TriggerResults &triggerTable, const std::string &triggerPath)
Definition: TopDQMHelpers.h:31
void bookHistograms(DQMStore::IBooker &, edm::Run const &, edm::EventSetup const &, RunBasedHistograms &) const override
static constexpr const char *const s_tcds_trigger_types[]
char const * label
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
def unique(seq, keepstr=True)
Definition: tier0.py:24
const edm::EDGetTokenT< GlobalAlgBlkBxCollection > m_l1t_results_token
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
d
Definition: ztail.py:151
void dqmAnalyze(edm::Event const &, edm::EventSetup const &, RunBasedHistograms const &) const override
const edm::ESGetToken< L1TUtmTriggerMenu, L1TUtmTriggerMenuRcd > m_l1tMenu_token
void add(std::string const &label, ParameterSetDescription const &psetDescription)
TriggerRatesMonitor(edm::ParameterSet const &)
results
Definition: mysort.py:8
static constexpr unsigned int maxPhysicsTriggers
Definition: GlobalAlgBlk.h:52
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:98
~TriggerRatesMonitor() override=default
const edm::InputTag m_l1t_results_inputTag
Definition: event.py:1
Definition: Run.h:45
void labelsForToken(EDGetToken iToken, Labels &oLabels) const
#define LogDebug(id)