Belle II Software  release-06-00-14
SoftwareTriggerHLTDQMModule.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #include <hlt/softwaretrigger/modules/dqm/SoftwareTriggerHLTDQMModule.h>
9 
10 #include <TDirectory.h>
11 
12 #include <hlt/softwaretrigger/core/SoftwareTriggerDBHandler.h>
13 #include <hlt/softwaretrigger/core/FinalTriggerDecisionCalculator.h>
14 
15 #include <framework/core/ModuleParam.templateDetails.h>
16 
17 #include <algorithm>
18 #include <fstream>
19 #include <stdexcept>
20 
21 using namespace Belle2;
22 using namespace SoftwareTrigger;
23 
24 REG_MODULE(SoftwareTriggerHLTDQM)
25 
27 {
28  setDescription("Monitor Physics Trigger");
29  setPropertyFlags(c_ParallelProcessingCertified);
30 
31  // Fill in the default values of the module parameters
32  m_param_variableIdentifiers = {};
33 
34  m_param_cutResultIdentifiers["filter"]["filter"] = {"total_result"};
35 
36  addParam("cutResultIdentifiers", m_param_cutResultIdentifiers,
37  "Which cuts should be reported? Please remember to include the total_result also, if wanted.",
38  m_param_cutResultIdentifiers);
39 
40  addParam("cutResultIdentifiersIgnored", m_param_cutResultIdentifiersIgnored,
41  "Which cuts should be ignored? This will display cleaner trigger lines, e.g. to clear them from bhabha contamination. "
42  "Vetoes on skims do not apply in filter plot and vice versa.",
43  m_param_cutResultIdentifiersIgnored);
44 
45  addParam("cutResultIdentifiersPerUnit", m_param_cutResultIdentifiersPerUnit,
46  "Which cuts should be reported per unit?",
47  m_param_cutResultIdentifiersPerUnit);
48 
49  addParam("variableIdentifiers", m_param_variableIdentifiers,
50  "Which variables should be reported?",
51  m_param_variableIdentifiers);
52 
53  addParam("l1Identifiers", m_param_l1Identifiers,
54  "Which l1 identifiers to report?",
55  m_param_l1Identifiers);
56 
57  addParam("additionalL1Identifiers", m_param_additionalL1Identifiers,
58  "Which additional l1 identifiers to be added to the l1 total result plot?",
59  m_param_additionalL1Identifiers);
60 
61  addParam("createTotalResultHistograms", m_param_create_total_result_histograms,
62  "Create total result histogram?",
63  true);
64 
65  addParam("createExpRunEventHistograms", m_param_create_exp_run_event_histograms,
66  "Create exp/run/event histograms?",
67  true);
68 
69  addParam("createHLTUnitHistograms", m_param_create_hlt_unit_histograms,
70  "Create HLT unit histograms?",
71  false);
72 
73  addParam("createErrorFlagHistograms", m_param_create_error_flag_histograms,
74  "Create Error Flag histograms?",
75  false);
76 
77  addParam("histogramDirectoryName", m_param_histogramDirectoryName,
78  "SoftwareTrigger DQM histograms will be put into this directory", m_param_histogramDirectoryName);
79 
80  addParam("pathLocation", m_param_pathLocation,
81  "Location of the module in the path: before filter or after filter", m_param_pathLocation);
82 }
83 
85 {
86  TDirectory* oldDirectory = nullptr;
87 
88  if (!m_param_histogramDirectoryName.empty()) {
89  oldDirectory = gDirectory;
90  TDirectory* histDir = oldDirectory->mkdir(m_param_histogramDirectoryName.c_str());
91  histDir->cd();
92  }
93 
94  for (auto const& variable : m_param_variableIdentifiers) {
95  // todo: make correct range
96  const unsigned int numberOfBins = 50;
97  const double lowerX = 0;
98  const double upperX = 50;
99  m_triggerVariablesHistograms.emplace(variable, new TH1F(variable.c_str(), variable.c_str(), numberOfBins, lowerX, upperX));
100  m_triggerVariablesHistograms[variable]->SetXTitle(("SoftwareTriggerVariable " + variable).c_str());
101  }
102 
103  for (const auto& cutIdentifier : m_param_cutResultIdentifiers) {
104 
105  const std::string& title = cutIdentifier.first;
106  const auto& mapVal = *(m_param_cutResultIdentifiers[title].begin());
107  const std::string& baseIdentifier = mapVal.first;
108  const auto& cuts = mapVal.second;
109  const int numberOfFlags = cuts.size();
110 
111  if (m_param_histogramDirectoryName == "softwaretrigger_skim_nobhabha") {
112  if (title == baseIdentifier)
113  m_cutResultHistograms.emplace(title,
114  new TH1F((title + "_nobhabha").c_str(), ("Events triggered in HLT " + baseIdentifier).c_str(),
115  numberOfFlags, 0,
116  numberOfFlags));
117  else
118  m_cutResultHistograms.emplace(title,
119  new TH1F((baseIdentifier + "_" + title + "_nobhabha").c_str(),
120  ("Events triggered in HLT " + baseIdentifier + " : " + title).c_str(),
121  numberOfFlags, 0,
122  numberOfFlags));
123  } else {
124  if (title == baseIdentifier)
125  m_cutResultHistograms.emplace(title,
126  new TH1F(title.c_str(), ("Events triggered in HLT " + baseIdentifier).c_str(),
127  numberOfFlags, 0,
128  numberOfFlags));
129  else
130  m_cutResultHistograms.emplace(title,
131  new TH1F((baseIdentifier + "_" + title).c_str(), ("Events triggered in HLT " + baseIdentifier + " : " + title).c_str(),
132  numberOfFlags, 0,
133  numberOfFlags));
134  }
135  m_cutResultHistograms[title]->SetXTitle("");
136  m_cutResultHistograms[title]->SetOption("hist");
137  m_cutResultHistograms[title]->SetStats(false);
138  m_cutResultHistograms[title]->SetMinimum(0);
139 
140  // Set bin labels
141  int index = 0;
142  for (const std::string& cutTitle : cuts) {
143  index++;
144  m_cutResultHistograms[title]->GetXaxis()->SetBinLabel(index, cutTitle.c_str());
145  }
146  }
147 
148  // We add one for the total result
150  m_cutResultHistograms.emplace("total_result",
151  new TH1F("total_result", "Total Result of HLT (absolute numbers)", 1, 0, 0));
152  m_cutResultHistograms["total_result"]->SetXTitle("Total Cut Result");
153  m_cutResultHistograms["total_result"]->SetOption("hist");
154  m_cutResultHistograms["total_result"]->SetStats(false);
155  m_cutResultHistograms["total_result"]->SetMinimum(0);
156  }
157 
158  for (const std::string& trigger : m_param_l1Identifiers) {
159  m_l1Histograms.emplace(trigger, new TH1F(trigger.c_str(), ("Events triggered in L1 " + trigger).c_str(), 1, 0, 0));
160  m_l1Histograms[trigger]->SetXTitle("");
161  m_l1Histograms[trigger]->SetOption("hist");
162  m_l1Histograms[trigger]->SetStats(false);
163  m_l1Histograms[trigger]->SetMinimum(0);
164  }
165 
166  // And also one for the total numbers
168  m_l1Histograms.emplace("l1_total_result",
169  new TH1F("l1_total_result", "Events triggered in L1 (total results)", 1, 0, 0));
170  m_l1Histograms["l1_total_result"]->SetXTitle("Total L1 Cut Result");
171  m_l1Histograms["l1_total_result"]->SetOption("hist");
172  m_l1Histograms["l1_total_result"]->SetStats(false);
173  m_l1Histograms["l1_total_result"]->SetMinimum(0);
174 
175  const int numberOfL1Flags = m_param_l1Identifiers.size() + m_param_additionalL1Identifiers.size();
176  m_l1Histograms["l1_total_result"]->SetBins(numberOfL1Flags, 0, numberOfL1Flags);
177  // Set bin labels
178  int l1Index = 0;
179  for (const std::string& l1Trigger : m_param_l1Identifiers) {
180  l1Index++;
181  m_l1Histograms["l1_total_result"]->GetXaxis()->SetBinLabel(l1Index, l1Trigger.c_str());
182  }
183  for (const std::string& l1Trigger : m_param_additionalL1Identifiers) {
184  l1Index++;
185  m_l1Histograms["l1_total_result"]->GetXaxis()->SetBinLabel(l1Index, l1Trigger.c_str());
186  }
187  }
188 
190  m_runInfoHistograms.emplace("run_number", new TH1D("run_number", "Run Number", 100, 0, 10000));
191  m_runInfoHistograms.emplace("event_number", new TH1D("event_number", "Event Number", 100, 0, 1'000'000));
192  m_runInfoHistograms.emplace("experiment_number", new TH1D("experiment_number", "Experiment Number", 50, 0, 50));
193  }
194 
196  if (m_param_histogramDirectoryName != "softwaretrigger_before_filter") {
197  m_runInfoHistograms.emplace("hlt_unit_number", new TH1D("hlt_unit_number_after_filter",
198  ("Number of events per HLT unit " + m_param_pathLocation).c_str(), HLTUnit::max_hlt_units + 1, 0,
200  } else {
201  m_runInfoHistograms.emplace("hlt_unit_number", new TH1D("hlt_unit_number",
202  ("Number of events per HLT unit " + m_param_pathLocation).c_str(), HLTUnit::max_hlt_units + 1, 0,
204  }
205  m_runInfoHistograms["hlt_unit_number"]->SetMinimum(0);
206 
207  for (const auto& cutIdentifierPerUnit : m_param_cutResultIdentifiersPerUnit) {
208  m_cutResultPerUnitHistograms.emplace(cutIdentifierPerUnit , new TH1F((cutIdentifierPerUnit + "_per_unit").c_str(),
209  ("Events triggered per unit in HLT : " + cutIdentifierPerUnit).c_str(), HLTUnit::max_hlt_units + 1, 0,
211  m_cutResultPerUnitHistograms[cutIdentifierPerUnit]->SetXTitle("HLT unit number");
212  m_cutResultPerUnitHistograms[cutIdentifierPerUnit]->SetOption("histe");
213  m_cutResultPerUnitHistograms[cutIdentifierPerUnit]->SetMinimum(0);
214  }
215 
216  }
217 
219  m_runInfoHistograms.emplace("error_flag", new TH1D("error_flag", "Error Flag", 4, 0, 4));
220  m_runInfoHistograms["error_flag"]->SetStats(false);
221  m_runInfoHistograms["error_flag"]->SetOption("hist");
222  m_runInfoHistograms["error_flag"]->SetMinimum(0);
223  }
224 
225  if (oldDirectory) {
226  oldDirectory->cd();
227  }
228 }
229 
231 {
232  // Register histograms (calls back defineHisto)
233  REG_HISTOGRAM
234 
236  std::ifstream file;
237  file.open(HLTUnit::hlt_unit_file);
238  if (file.good()) {
239  std::string host;
240  getline(file, host);
241  m_hlt_unit = atoi(host.substr(3, 2).c_str());
242  file.close();
243  } else {
244  B2WARNING("HLT unit number not found");
245  }
246  }
247 }
248 
250 {
251  // this might be pre-scaled for performance reasons in the final configuration, therefore this structure
252  // might not be filled in every event
253  if (m_variables.isValid()) {
254  for (auto& variableNameAndTH1F : m_triggerVariablesHistograms) {
255  const std::string& variable = variableNameAndTH1F.first;
256  TH1F* histogram = variableNameAndTH1F.second;
257 
258  // try to load this variable from the computed trigger variables
259  if (not m_variables->has(variable)) {
260  B2ERROR("Variable " << variable << " configured for SoftwareTriggerDQM plotting is not available");
261  } else {
262  const double value = m_variables->getVariable(variable);
263  histogram->Fill(value);
264  }
265  }
266  }
267 
268  if (m_triggerResult.isValid()) {
269  const auto results = m_triggerResult->getResults();
270 
271  for (auto const& cutIdentifier : m_param_cutResultIdentifiers) {
272  const std::string& title = cutIdentifier.first;
273  const auto& mapVal = *(m_param_cutResultIdentifiers[title].begin());
274  const std::string& baseIdentifier = mapVal.first;
275  const auto& cuts = mapVal.second;
276 
277  // check if we want to ignore it
278  bool skip = false;
279  const auto& cutsIgnored = m_param_cutResultIdentifiersIgnored[baseIdentifier];
280 
281  for (const std::string& cutTitleIgnored : cutsIgnored) {
282  const std::string& cutNameIgnored = cutTitleIgnored.substr(0, cutTitleIgnored.find("\\"));
283  const std::string& fullCutIdentifierIgnored = SoftwareTriggerDBHandler::makeFullCutName(baseIdentifier, cutNameIgnored);
284 
285  auto const cutEntryIgnored = results.find(fullCutIdentifierIgnored);
286 
287  if (cutEntryIgnored != results.end()) {
288  if (cutEntryIgnored->second > 0) skip = true;
289  }
290  }
291 
292  float index = 0;
293  for (const std::string& cutTitle : cuts) {
294  index++;
295  const std::string& cutName = cutTitle.substr(0, cutTitle.find("\\"));
296  const std::string& fullCutIdentifier = SoftwareTriggerDBHandler::makeFullCutName(baseIdentifier, cutName);
297 
298  // check if the cutResult is in the list, be graceful when not available
299  // Create results object instead of calling .find() on a temporary object. This will cause undefined behaviour
300  // when checking again the .end() pointer, when the .end() pointer is also created from a temporary object.
301  auto const cutEntry = results.find(fullCutIdentifier);
302 
303  if (cutEntry != results.end()) {
304  const int cutResult = cutEntry->second;
305  if (cutResult > 0 and not skip) {
306  m_cutResultHistograms[title]->Fill(index - 0.5);
307  }
308  }
309  }
310 
312  if (title == baseIdentifier) {
313  const std::string& totalCutIdentifier = SoftwareTriggerDBHandler::makeTotalResultName(baseIdentifier);
314  const int cutResult = static_cast<int>(m_triggerResult->getResult(totalCutIdentifier));
315 
316  m_cutResultHistograms["total_result"]->Fill(totalCutIdentifier.c_str(), cutResult > 0);
317  }
318  }
319  }
320 
323  m_cutResultHistograms["total_result"]->Fill("total_result", totalResult > 0);
324  }
325 
327  for (const std::string& cutIdentifierPerUnit : m_param_cutResultIdentifiersPerUnit) {
328  const std::string& cutName = cutIdentifierPerUnit.substr(0, cutIdentifierPerUnit.find("\\"));
329  const std::string& fullCutIdentifier = SoftwareTriggerDBHandler::makeFullCutName("filter", cutName);
330 
331  // check if the cutResult is in the list, be graceful when not available
332  auto const cutEntry = results.find(fullCutIdentifier);
333 
334  if (cutEntry != results.end()) {
335  const int cutResult = cutEntry->second;
336  if (cutResult > 0) {
337  m_cutResultPerUnitHistograms[cutIdentifierPerUnit]->Fill(m_hlt_unit);
338  }
339  }
340  }
341  }
342 
343  if (m_l1TriggerResult.isValid() and m_l1NameLookup.isValid()) {
344  float l1Index = 0;
345  for (const std::string& l1Trigger : m_param_l1Identifiers) {
346  l1Index++;
347  const int triggerBit = m_l1NameLookup->getoutbitnum(l1Trigger.c_str());
348  if (triggerBit < 0) {
349  B2WARNING("Could not find"
350  << LogVar("L1 trigger line", l1Trigger));
351  continue;
352  }
353  bool triggerResult;
354  try {
355  triggerResult = m_l1TriggerResult->testPsnm(triggerBit);
356  } catch (const std::exception&) {
357  triggerResult = false;
358  }
360  if (triggerResult) {
361  m_l1Histograms["l1_total_result"]->Fill(l1Index - 0.5);
362  }
363  }
364 
365  if (not triggerResult) {
366  continue;
367  }
368 
369  for (auto const& cutIdentifier : m_param_cutResultIdentifiers) {
370  const std::string& title = cutIdentifier.first;
371  const auto& mapVal = *(m_param_cutResultIdentifiers[title].begin());
372  const std::string& baseIdentifier = mapVal.first;
373  const auto& cuts = mapVal.second;
374 
375  if (title == baseIdentifier) {
376  for (const std::string& cutTitle : cuts) {
377  const std::string& cutName = cutTitle.substr(0, cutTitle.find("\\"));
378  const std::string& fullCutIdentifier = SoftwareTriggerDBHandler::makeFullCutName(baseIdentifier, cutName);
379 
380  // check if the cutResult is in the list, be graceful when not available
381  auto const cutEntry = results.find(fullCutIdentifier);
382 
383  if (cutEntry != results.end()) {
384  const int cutResult = cutEntry->second;
385  m_l1Histograms[l1Trigger]->Fill(cutTitle.c_str(), cutResult > 0);
386  }
387  }
388  }
389  }
390 
392  m_l1Histograms[l1Trigger]->Fill("hlt_result", totalResult > 0);
393  m_l1Histograms[l1Trigger]->LabelsDeflate("X");
394  }
396  for (const std::string& l1Trigger : m_param_additionalL1Identifiers) {
397  l1Index++;
398  const int triggerBit = m_l1NameLookup->getoutbitnum(l1Trigger.c_str());
399  if (triggerBit < 0) {
400  B2WARNING("Could not find"
401  << LogVar("L1 trigger line", l1Trigger));
402  continue;
403  }
404  bool triggerResult;
405  try {
406  triggerResult = m_l1TriggerResult->testPsnm(triggerBit);
407  } catch (const std::exception&) {
408  triggerResult = false;
409  }
410  if (triggerResult) {
411  m_l1Histograms["l1_total_result"]->Fill(l1Index - 0.5);
412  }
413  }
414  }
415  }
416  }
417 
419  m_runInfoHistograms["run_number"]->Fill(m_eventMetaData->getRun());
420  m_runInfoHistograms["event_number"]->Fill(m_eventMetaData->getEvent());
421  m_runInfoHistograms["experiment_number"]->Fill(m_eventMetaData->getExperiment());
422  }
423 
425  m_runInfoHistograms["error_flag"]->Fill("B2LinkPacketCRCError",
426  (bool)(m_eventMetaData->getErrorFlag() & EventMetaData::EventErrorFlag::c_B2LinkPacketCRCError));
427  m_runInfoHistograms["error_flag"]->Fill("B2LinkEventCRCError",
428  (bool)(m_eventMetaData->getErrorFlag() & EventMetaData::EventErrorFlag::c_B2LinkEventCRCError));
429  m_runInfoHistograms["error_flag"]->Fill("HLTCrash",
430  (bool)(m_eventMetaData->getErrorFlag() & EventMetaData::EventErrorFlag::c_HLTCrash));
431  m_runInfoHistograms["error_flag"]->Fill("ReconstructionAbort",
432  (bool)(m_eventMetaData->getErrorFlag() & EventMetaData::EventErrorFlag::c_ReconstructionAbort));
433  }
434 
436  m_runInfoHistograms["hlt_unit_number"]->Fill(m_hlt_unit);
437  }
438 }
439 
441 {
442  std::for_each(m_cutResultHistograms.begin(), m_cutResultHistograms.end(),
443  [](auto & it) { it.second->Reset(); });
444  std::for_each(m_cutResultPerUnitHistograms.begin(), m_cutResultPerUnitHistograms.end(),
445  [](auto & it) { it.second->Reset(); });
446  std::for_each(m_triggerVariablesHistograms.begin(), m_triggerVariablesHistograms.end(),
447  [](auto & it) { it.second->Reset(); });
448  std::for_each(m_l1Histograms.begin(), m_l1Histograms.end(),
449  [](auto & it) { it.second->Reset(); });
450  std::for_each(m_runInfoHistograms.begin(), m_runInfoHistograms.end(),
451  [](auto & it) { it.second->Reset(); });
452 }
453 
HistoModule.h is supposed to be used instead of Module.h for the modules with histogram definitions t...
Definition: HistoModule.h:29
static bool getFinalTriggerDecision(const SoftwareTriggerResult &result, bool forgetTotalResult=false)
Calculate the final cut decision using all "total_results" of all sub triggers in the software trigge...
static std::string makeFullCutName(const std::string &baseCutIdentifier, const std::string &cutIdentifier)
Helper function to compile the full identifier from the base and the specific cut name.
static std::string makeTotalResultName(const std::string &baseIdentifier="all")
Handy function to create the name related to the total result of a specific trigger stage (either fil...
std::map< std::string, TH1D * > m_runInfoHistograms
histograms with the run information
std::map< std::string, std::map< std::string, std::vector< std::string > > > m_param_cutResultIdentifiers
Which cuts should be reported? Please remember to include the total_result also, if wanted.
std::map< std::string, TH1F * > m_l1Histograms
histogram with the L1 information
void initialize() override
Module functions to be called from main process.
void event() override
Module functions to be called from event process.
StoreObjPtr< SoftwareTriggerResult > m_triggerResult
STM cut results.
std::vector< std::string > m_param_l1Identifiers
Which L1 cuts should be reported?
std::map< std::string, TH1F * > m_cutResultPerUnitHistograms
histograms for the final sw trigger decisions for each base identifier per unit
std::map< std::string, TH1F * > m_triggerVariablesHistograms
histograms for the software trigger variables in all calculators (although maybe not filled)
std::map< std::string, std::vector< std::string > > m_param_cutResultIdentifiersIgnored
Which cuts should be ignored? This can be used to clear trigger lines from e.g. bhabha contamination.
std::string m_param_pathLocation
Location of the module in the path: before filter or after filter.
void beginRun() override
Reset all histogram entries for a new run.
std::map< std::string, TH1F * > m_cutResultHistograms
histograms for the final sw trigger decisions for each base identifier
bool m_param_create_error_flag_histograms
Create error flag histograms?
std::vector< std::string > m_param_additionalL1Identifiers
Which additional L1 cuts should be added to the L1 total result plot?
bool m_param_create_hlt_unit_histograms
Create HLT unit number histograms?
StoreObjPtr< TRGSummary > m_l1TriggerResult
L1 cut results.
std::vector< std::string > m_param_cutResultIdentifiersPerUnit
Which cuts should be reported per unit?
bool m_param_create_total_result_histograms
Create total result histogram?
std::vector< std::string > m_param_variableIdentifiers
Which variables should be reported?
bool m_param_create_exp_run_event_histograms
Create exp/run/event number histograms?
std::string m_param_histogramDirectoryName
Directory to put the generated histograms.
StoreObjPtr< SoftwareTriggerVariables > m_variables
STM cut variables.
Class to store variables with their name which were sent to the logging service.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
static constexpr char hlt_unit_file[]
Location of HLT unit number information.
static constexpr unsigned int max_hlt_units
Maximum number of HLT units used during the experiment.
Abstract base class for different kinds of events.