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 L1 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 
6 // C++ headers
7 #include <string>
8 #include <cstring>
9 
10 // boost headers
11 #include <boost/regex.hpp>
12 #include <boost/format.hpp>
13 
14 // Root headers
15 #include <TH1F.h>
16 
17 // CMSSW headers
40 
41 namespace {
42 
43  struct RunBasedHistograms {
44 
45  // HLT configuration
46  struct HLTIndices {
47  unsigned int index_l1_seed;
48  unsigned int index_prescale;
49 
50  HLTIndices() :
51  index_l1_seed( (unsigned int) -1),
52  index_prescale( (unsigned int) -1)
53  { }
54  };
55 
56  HLTConfigProvider hltConfig;
57  std::vector<HLTIndices> hltIndices;
58 
59  std::vector<std::vector<unsigned int>> datasets;
60  std::vector<std::vector<unsigned int>> streams;
61 
62  // L1T and HLT rate plots
63 
64  // per-path HLT plots
65  struct HLTRatesPlots {
66  ConcurrentMonitorElement pass_l1_seed;
67  ConcurrentMonitorElement pass_prescale;
71  };
72 
73  // overall event count and event types
74  ConcurrentMonitorElement events_processed;
75  std::vector<ConcurrentMonitorElement> tcds_counts;
76 
77  // L1T triggers
78  std::vector<ConcurrentMonitorElement> l1t_counts;
79 
80  // HLT triggers
81  std::vector<std::vector<HLTRatesPlots>> hlt_by_dataset_counts;
82 
83  // datasets
84  std::vector<ConcurrentMonitorElement> dataset_counts;
85 
86  // streams
87  std::vector<ConcurrentMonitorElement> stream_counts;
88 
89  RunBasedHistograms() :
90  // L1T and HLT configuration
91  hltConfig(),
92  hltIndices(),
93  datasets(),
94  streams(),
95  // overall event count and event types
96  events_processed(),
97  tcds_counts(),
98  // L1T triggers
99  l1t_counts(),
100  // HLT triggers
101  hlt_by_dataset_counts(),
102  // datasets
103  dataset_counts(),
104  // streams
105  stream_counts()
106  {
107  }
108 
109  };
110 }
111 
112 class TriggerRatesMonitor : public DQMGlobalEDAnalyzer<RunBasedHistograms> {
113 public:
114  explicit TriggerRatesMonitor(edm::ParameterSet const &);
115  ~TriggerRatesMonitor() override = default;
116 
117  static void fillDescriptions(edm::ConfigurationDescriptions & descriptions);
118 
119 private:
120  void dqmBeginRun(edm::Run const &, edm::EventSetup const &, RunBasedHistograms &) const override;
121  void bookHistograms(DQMStore::ConcurrentBooker &, edm::Run const&, edm::EventSetup const&, RunBasedHistograms &) const override;
122  void dqmAnalyze(edm::Event const &, edm::EventSetup const &, RunBasedHistograms const&) const override;
123 
124  // TCDS trigger types
125  // see https://twiki.cern.ch/twiki/bin/viewauth/CMS/TcdsEventRecord
126  static constexpr const char * const s_tcds_trigger_types[] = {
127  "Empty", // 0 - No trigger
128  "Physics", // 1 - GT trigger
129  "Calibration", // 2 - Sequence trigger (calibration)
130  "Random", // 3 - Random trigger
131  "Auxiliary", // 4 - Auxiliary (CPM front panel NIM input) trigger
132  nullptr, // 5 - reserved
133  nullptr, // 6 - reserved
134  nullptr, // 7 - reserved
135  "Cyclic", // 8 - Cyclic trigger
136  "Bunch-pattern", // 9 - Bunch-pattern trigger
137  "Software", // 10 - Software trigger
138  "TTS", // 11 - TTS-sourced trigger
139  nullptr, // 12 - reserved
140  nullptr, // 13 - reserved
141  nullptr, // 14 - reserved
142  nullptr // 15 - reserved
143  };
144 
145  // module configuration
149  const uint32_t m_lumisections_range;
150 };
151 
152 
153 // definition
155 
156 
158 {
160  desc.addUntracked<edm::InputTag>( "l1tResults", edm::InputTag("gtStage2Digis"));
161  desc.addUntracked<edm::InputTag>( "hltResults", edm::InputTag("TriggerResults"));
162  desc.addUntracked<std::string>( "dqmPath", "HLT/TriggerRates" );
163  desc.addUntracked<uint32_t>( "lumisectionRange", 2500 ); // ~16 hours
164  descriptions.add("triggerRatesMonitor", desc);
165 }
166 
167 
169  // module configuration
170  m_l1t_results(consumes<GlobalAlgBlkBxCollection>( config.getUntrackedParameter<edm::InputTag>( "l1tResults" ) )),
171  m_hlt_results(consumes<edm::TriggerResults>( config.getUntrackedParameter<edm::InputTag>( "hltResults" ) )),
172  m_dqm_path( config.getUntrackedParameter<std::string>( "dqmPath" ) ),
173  m_lumisections_range( config.getUntrackedParameter<uint32_t>( "lumisectionRange" ) )
174 {
175 }
176 
177 void TriggerRatesMonitor::dqmBeginRun(edm::Run const& run, edm::EventSetup const& setup, RunBasedHistograms& histograms) const
178 {
179  histograms.events_processed.reset();
180  histograms.tcds_counts.clear();
181  histograms.tcds_counts.resize(sizeof(s_tcds_trigger_types)/sizeof(const char *));
182 
183  // cache the L1 trigger menu
184  histograms.l1t_counts.clear();
185  histograms.l1t_counts.resize(GlobalAlgBlk::maxPhysicsTriggers);
186 
187  // initialise the HLTConfigProvider
188  bool changed = true;
190  labelsForToken(m_hlt_results, labels);
191  if (histograms.hltConfig.init(run, setup, labels.process, changed)) {
192  histograms.hltIndices.resize(histograms.hltConfig.size());
193 
194  unsigned int datasets = histograms.hltConfig.datasetNames().size();
195  histograms.hlt_by_dataset_counts.clear();
196  histograms.hlt_by_dataset_counts.resize(datasets);
197 
198  histograms.datasets.clear();
199  histograms.datasets.resize(datasets);
200  for (unsigned int i = 0; i < datasets; ++i) {
201  auto const & paths = histograms.hltConfig.datasetContent(i);
202  histograms.hlt_by_dataset_counts[i].resize(paths.size());
203  histograms.datasets[i].reserve(paths.size());
204  for (auto const & path: paths) {
205  histograms.datasets[i].push_back(histograms.hltConfig.triggerIndex(path));
206  }
207  }
208  histograms.dataset_counts.clear();
209  histograms.dataset_counts.resize(datasets);
210 
211  unsigned int streams = histograms.hltConfig.streamNames().size();
212  histograms.streams.clear();
213  histograms.streams.resize(streams);
214  for (unsigned int i = 0; i < streams; ++i) {
215  for (auto const & dataset : histograms.hltConfig.streamContent(i)) {
216  for (auto const & path : histograms.hltConfig.datasetContent(dataset))
217  histograms.streams[i].push_back(histograms.hltConfig.triggerIndex(path));
218  }
219  std::sort(histograms.streams[i].begin(), histograms.streams[i].end());
220  auto unique_end = std::unique(histograms.streams[i].begin(), histograms.streams[i].end());
221  histograms.streams[i].resize(unique_end - histograms.streams[i].begin());
222  histograms.streams[i].shrink_to_fit();
223  }
224  histograms.stream_counts.clear();
225  histograms.stream_counts.resize(streams);
226  } else {
227  // HLTConfigProvider not initialised, skip the the HLT monitoring
228  edm::LogError("TriggerRatesMonitor") << "failed to initialise HLTConfigProvider, the HLT trigger and datasets rates will not be monitored";
229  }
230 }
231 
233 {
234  // book the overall event count and event types histograms
235  booker.setCurrentFolder( m_dqm_path );
236  histograms.events_processed = booker.book1D("events", "Processed events vs. lumisection", m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
237  booker.setCurrentFolder( m_dqm_path + "/TCDS" );
238  for (unsigned int i = 0; i < sizeof(s_tcds_trigger_types)/sizeof(const char *); ++i)
239  if (s_tcds_trigger_types[i]) {
240  std::string const & title = (boost::format("%s events vs. lumisection") % s_tcds_trigger_types[i]).str();
241  histograms.tcds_counts[i] = booker.book1D(s_tcds_trigger_types[i], title, m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
242  }
243 
244  // book the rate histograms for the L1 triggers that are included in the L1 menu
245  booker.setCurrentFolder( m_dqm_path + "/L1T" );
246  auto const& l1tMenu = edm::get<L1TUtmTriggerMenu, L1TUtmTriggerMenuRcd>(setup);
247  for (auto const & keyval: l1tMenu.getAlgorithmMap()) {
248  unsigned int bit = keyval.second.getIndex();
249  bool masked = false; // FIXME read L1 masks once they will be avaiable in the EventSetup
250  std::string const & name = (boost::format("%s (bit %d)") % keyval.first % bit).str();
251  std::string const & title = (boost::format("%s (bit %d)%s vs. lumisection") % keyval.first % bit % (masked ? " (masked)" : "")).str();
252  histograms.l1t_counts.at(bit) = booker.book1D(name, title, m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
253  }
254 
255  if (histograms.hltConfig.inited()) {
256 
257  auto const & datasets = histograms.hltConfig.datasetNames();
258 
259  // book the rate histograms for the HLT triggers
260  for (unsigned int d = 0; d < datasets.size(); ++d) {
261  booker.setCurrentFolder( m_dqm_path + "/HLT/" + datasets[d]);
262  for (unsigned int i = 0; i < histograms.datasets[d].size(); ++i) {
263  unsigned int index = histograms.datasets[d][i];
264  std::string const & name = histograms.hltConfig.triggerName(index);
265  histograms.hlt_by_dataset_counts[d][i].pass_l1_seed = booker.book1D(name + "_pass_L1_seed", name + " pass L1 seed, vs. lumisection", m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
266  histograms.hlt_by_dataset_counts[d][i].pass_prescale = booker.book1D(name + "_pass_prescaler", name + " pass prescaler, vs. lumisection", m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
267  histograms.hlt_by_dataset_counts[d][i].accept = booker.book1D(name + "_accept", name + " accept, vs. lumisection", m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
268  histograms.hlt_by_dataset_counts[d][i].reject = booker.book1D(name + "_reject", name + " reject, vs. lumisection", m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
269  histograms.hlt_by_dataset_counts[d][i].error = booker.book1D(name + "_error", name + " error, vs. lumisection", m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
270  }
271 
272  // booker.setCurrentFolder( m_dqm_path + "/HLT/" + datasets[d]);
273  for (unsigned int i: histograms.datasets[d]) {
274 
275  // look for the index of the (last) L1 seed and prescale module in each path
276  histograms.hltIndices[i].index_l1_seed = histograms.hltConfig.size(i);
277  histograms.hltIndices[i].index_prescale = histograms.hltConfig.size(i);
278  for (unsigned int j = 0; j < histograms.hltConfig.size(i); ++j) {
279  std::string const & label = histograms.hltConfig.moduleLabel(i, j);
280  std::string const & type = histograms.hltConfig.moduleType(label);
281  if (type == "HLTL1TSeed" or type == "HLTLevel1GTSeed" or type == "HLTLevel1Activity" or type == "HLTLevel1Pattern") {
282  // there might be more L1 seed filters in sequence
283  // keep looking and store the index of the last one
284  histograms.hltIndices[i].index_l1_seed = j;
285  } else if (type == "HLTPrescaler") {
286  // there should be only one prescaler in a path, and it should follow all L1 seed filters
287  histograms.hltIndices[i].index_prescale = j;
288  break;
289  }
290  }
291  }
292  }
293 
294  // book the HLT datasets rate histograms
295  booker.setCurrentFolder( m_dqm_path + "/Datasets" );
296  for (unsigned int i = 0; i < datasets.size(); ++i)
297  histograms.dataset_counts[i] = booker.book1D(datasets[i], datasets[i], m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
298 
299  // book the HLT streams rate histograms
300  booker.setCurrentFolder( m_dqm_path + "/Streams" );
301  auto const & streams = histograms.hltConfig.streamNames();
302  for (unsigned int i = 0; i < streams.size(); ++i)
303  histograms.stream_counts[i] = booker.book1D(streams[i], streams[i], m_lumisections_range + 1, -0.5, m_lumisections_range + 0.5);
304  }
305 
306 }
307 
308 
309 void TriggerRatesMonitor::dqmAnalyze(edm::Event const & event, edm::EventSetup const & setup, RunBasedHistograms const& histograms) const
310 {
311  unsigned int lumisection = event.luminosityBlock();
312 
313  // monitor the overall event count and event types rates
314  histograms.events_processed.fill(lumisection);
315  if (histograms.tcds_counts[event.experimentType()])
316  histograms.tcds_counts[event.experimentType()].fill(lumisection);
317 
318  // monitor the L1 triggers rates
319  auto const & bxvector = edm::get(event, m_l1t_results);
320  if (not bxvector.isEmpty(0)) {
321  auto const & results = bxvector.at(0, 0);
322  for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i)
323  if (results.getAlgoDecisionFinal(i))
324  if (histograms.l1t_counts[i])
325  histograms.l1t_counts[i].fill(lumisection);
326  }
327 
328  // monitor the HLT triggers and datsets rates
329  if (histograms.hltConfig.inited()) {
331  if (hltResults.size() == histograms.hltIndices.size()) {
332  } else {
333  edm::LogWarning("TriggerRatesMonitor") << "This should never happen: the number of HLT paths has changed since the beginning of the run";
334  }
335 
336  for (unsigned int d = 0; d < histograms.datasets.size(); ++d) {
337  for (unsigned int i: histograms.datasets[d])
338  if (hltResults.at(i).accept()) {
339  histograms.dataset_counts[d].fill(lumisection);
340  // ensure each dataset is incremented only once per event
341  break;
342  }
343  for (unsigned int i = 0; i < histograms.datasets[d].size(); ++i) {
344  unsigned int index = histograms.datasets[d][i];
345  edm::HLTPathStatus const & path = hltResults.at(index);
346 
347  if (path.index() > histograms.hltIndices[index].index_l1_seed)
348  histograms.hlt_by_dataset_counts[d][i].pass_l1_seed.fill(lumisection);
349  if (path.index() > histograms.hltIndices[index].index_prescale)
350  histograms.hlt_by_dataset_counts[d][i].pass_prescale.fill(lumisection);
351  if (path.accept())
352  histograms.hlt_by_dataset_counts[d][i].accept.fill(lumisection);
353  else if (path.error())
354  histograms.hlt_by_dataset_counts[d][i].error .fill(lumisection);
355  else
356  histograms.hlt_by_dataset_counts[d][i].reject.fill(lumisection);
357  }
358  }
359 
360  for (unsigned int i = 0; i < histograms.streams.size(); ++i)
361  for (unsigned int j: histograms.streams[i])
362  if (hltResults.at(j).accept()) {
363  histograms.stream_counts[i].fill(lumisection);
364  // ensure each stream is incremented only once per event
365  break;
366  }
367  }
368 }
369 
370 
371 //define this as a plug-in
type
Definition: HCALResponse.h:21
const std::string m_dqm_path
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
const edm::EDGetTokenT< GlobalAlgBlkBxCollection > m_l1t_results
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
virtual example_global void dqmAnalyze(edm::Event const &,@example_global edm::EventSetup const &,@example_global Histograms___class__ const &) const override
const edm::EDGetTokenT< edm::TriggerResults > m_hlt_results
def setup(process, global_tag, zero_tesla=False)
Definition: GeneralSetup.py:1
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
Definition: config.py:1
const uint32_t m_lumisections_range
bool accept(const edm::Event &event, const edm::TriggerResults &triggerTable, const std::string &triggerPath)
Definition: TopDQMHelpers.h:30
#define constexpr
char const * process
Definition: ProductLabels.h:7
static const char *const s_tcds_trigger_types[]
void dqmBeginRun(edm::Run const &, edm::EventSetup const &, RunBasedHistograms &) const override
unsigned int size() const
Get number of paths stored.
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
T const & get(Event const &event, InputTag const &tag)
Definition: Event.h:690
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
virtual example_stream void bookHistograms(DQMStore::IBooker &,@example_stream edm::Run const &,@example_stream edm::EventSetup const &) override
ConcurrentMonitorElement book1D(Args &&...args)
Definition: DQMStore.h:223
format
Some error handling for the usage.
const HLTPathStatus & at(const unsigned int i) const
void bookHistograms(DQMStore::ConcurrentBooker &, edm::Run const &, edm::EventSetup const &, RunBasedHistograms &) const override
bool error() const
has this path encountered an error (exception)?
Definition: HLTPathStatus.h:64
void setCurrentFolder(const std::string &fullpath)
Definition: DQMStore.cc:274
static unsigned int maxPhysicsTriggers
Definition: GlobalAlgBlk.h:54
void add(std::string const &label, ParameterSetDescription const &psetDescription)
bool accept() const
has this path accepted the event?
Definition: HLTPathStatus.h:62
void labelsForToken(EDGetToken iToken, Labels &oLabels) const
HLT enums.
TriggerRatesMonitor(edm::ParameterSet const &)
edm::EventAuxiliary::ExperimentType experimentType() const
Definition: EventBase.h:65
#define str(s)
void dqmAnalyze(edm::Event const &, edm::EventSetup const &, RunBasedHistograms const &) const override
Definition: event.py:1
Definition: Run.h:44
unsigned int index() const
Definition: HLTPathStatus.h:55