Belle II Software development
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#include <hlt/utilities/Units.h>
15
16#include <framework/core/ModuleParam.templateDetails.h>
17
18#include <algorithm>
19#include <fstream>
20#include <stdexcept>
21
22using namespace Belle2;
23using namespace SoftwareTrigger;
24
25REG_MODULE(SoftwareTriggerHLTDQM);
26
28{
29 setDescription("Monitor Physics Trigger");
31
32 // Fill in the default values of the module parameters
34
35 m_param_cutResultIdentifiers["filter"]["filter"] = {"total_result"};
36
37 addParam("cutResultIdentifiers", m_param_cutResultIdentifiers,
38 "Which cuts should be reported? Please remember to include the total_result also, if wanted.",
40
41 addParam("cutResultIdentifiersIgnored", m_param_cutResultIdentifiersIgnored,
42 "Which cuts should be ignored? This will display cleaner trigger lines, e.g. to clear them from bhabha contamination. "
43 "Vetoes on skims do not apply in filter plot and vice versa.",
45
46 addParam("cutResultIdentifiersPerUnit", m_param_cutResultIdentifiersPerUnit,
47 "Which cuts should be reported per unit?",
49
50 addParam("variableIdentifiers", m_param_variableIdentifiers,
51 "Which variables should be reported?",
53
54 addParam("l1Identifiers", m_param_l1Identifiers,
55 "Which l1 identifiers to report?",
57
58 addParam("additionalL1Identifiers", m_param_additionalL1Identifiers,
59 "Which additional l1 identifiers to be added to the l1 total result plot?",
61
62 addParam("createTotalResultHistograms", m_param_create_total_result_histograms,
63 "Create total result histogram?",
64 true);
65
66 addParam("createExpRunEventHistograms", m_param_create_exp_run_event_histograms,
67 "Create exp/run/event histograms?",
68 true);
69
70 addParam("createHLTUnitHistograms", m_param_create_hlt_unit_histograms,
71 "Create HLT unit histograms?",
72 false);
73
74 addParam("createErrorFlagHistograms", m_param_create_error_flag_histograms,
75 "Create Error Flag histograms?",
76 false);
77
78 addParam("histogramDirectoryName", m_param_histogramDirectoryName,
79 "SoftwareTrigger DQM histograms will be put into this directory", m_param_histogramDirectoryName);
80
81 addParam("pathLocation", m_param_pathLocation,
82 "Location of the module in the path: before filter or after filter", m_param_pathLocation);
83}
84
86{
87 TDirectory* oldDirectory = nullptr;
88
89 if (!m_param_histogramDirectoryName.empty()) {
90 oldDirectory = gDirectory;
91 TDirectory* histDir = oldDirectory->mkdir(m_param_histogramDirectoryName.c_str());
92 histDir->cd();
93 }
94
95 for (auto const& variable : m_param_variableIdentifiers) {
96 // todo: make correct range
97 const unsigned int numberOfBins = 50;
98 const double lowerX = 0;
99 const double upperX = 50;
100 m_triggerVariablesHistograms.emplace(variable, new TH1F(variable.c_str(), variable.c_str(), numberOfBins, lowerX, upperX));
101 m_triggerVariablesHistograms[variable]->SetXTitle(("SoftwareTriggerVariable " + variable).c_str());
102 }
103
104 for (const std::string& trigger : m_param_l1Identifiers) {
105 m_l1Histograms.emplace(trigger, new TH1F(trigger.c_str(), ("Events triggered in L1 " + trigger).c_str(), 150, 0, 150));
106 m_l1Histograms[trigger]->SetXTitle("HLT line");
107 m_l1Histograms[trigger]->SetOption("hist");
108 m_l1Histograms[trigger]->SetStats(false);
109 m_l1Histograms[trigger]->SetMinimum(0);
110
111 float index = 0;
112 for (auto const& cutIdentifier : m_param_cutResultIdentifiers) {
113 const std::string& title = cutIdentifier.first;
114 const auto& mapVal = *(m_param_cutResultIdentifiers[title].begin());
115 const std::string& baseIdentifier = mapVal.first;
116 const auto& cuts = mapVal.second;
117
118 if (title == baseIdentifier) {
119 for (const std::string& cutTitle : cuts) {
120 index++;
121 m_l1Histograms[trigger]->GetXaxis()->SetBinLabel(index, cutTitle.c_str());
122 }
123 }
124 }
125 index++;
126 m_l1Histograms[trigger]->GetXaxis()->SetBinLabel(index, "hlt_result");
127 m_l1Histograms[trigger]->LabelsDeflate();
128 }
129
130 for (const auto& cutIdentifier : m_param_cutResultIdentifiers) {
131
132 const std::string& title = cutIdentifier.first;
133 const auto& mapVal = *(m_param_cutResultIdentifiers[title].begin());
134 const std::string& baseIdentifier = mapVal.first;
135 const auto& cuts = mapVal.second;
136 const int numberOfFlags = cuts.size();
137
138 if (m_param_histogramDirectoryName == "softwaretrigger_skim_nobhabha") {
139 if (title == baseIdentifier)
140 m_cutResultHistograms.emplace(title,
141 new TH1F((title + "_nobhabha").c_str(), ("Events triggered in HLT " + baseIdentifier).c_str(),
142 numberOfFlags, 0,
143 numberOfFlags));
144 else
145 m_cutResultHistograms.emplace(title,
146 new TH1F((baseIdentifier + "_" + title + "_nobhabha").c_str(),
147 ("Events triggered in HLT " + baseIdentifier + " : " + title).c_str(),
148 numberOfFlags, 0,
149 numberOfFlags));
150 } else {
151 if (title == baseIdentifier)
152 m_cutResultHistograms.emplace(title,
153 new TH1F(title.c_str(), ("Events triggered in HLT " + baseIdentifier).c_str(),
154 numberOfFlags, 0,
155 numberOfFlags));
156 else
157 m_cutResultHistograms.emplace(title,
158 new TH1F((baseIdentifier + "_" + title).c_str(), ("Events triggered in HLT " + baseIdentifier + " : " + title).c_str(),
159 numberOfFlags, 0,
160 numberOfFlags));
161 }
162 m_cutResultHistograms[title]->SetXTitle("");
163 m_cutResultHistograms[title]->SetOption("hist");
164 m_cutResultHistograms[title]->SetStats(false);
165 m_cutResultHistograms[title]->SetMinimum(0);
166
167 // Set bin labels
168 int index = 0;
169 for (const std::string& cutTitle : cuts) {
170 index++;
171 m_cutResultHistograms[title]->GetXaxis()->SetBinLabel(index, cutTitle.c_str());
172 }
173 }
174
175 // We add one for the total result
177 m_cutResultHistograms.emplace("total_result",
178 new TH1F("total_result", "Total Result of HLT (absolute numbers)", 1, 0, 0));
179 m_cutResultHistograms["total_result"]->SetXTitle("Total Cut Result");
180 m_cutResultHistograms["total_result"]->SetOption("hist");
181 m_cutResultHistograms["total_result"]->SetStats(false);
182 m_cutResultHistograms["total_result"]->SetMinimum(0);
183
184 m_l1Histograms.emplace("l1_total_result",
185 new TH1F("l1_total_result", "Events triggered in L1 (total results)", 1, 0, 0));
186 m_l1Histograms["l1_total_result"]->SetXTitle("Total L1 Cut Result");
187 m_l1Histograms["l1_total_result"]->SetOption("hist");
188 m_l1Histograms["l1_total_result"]->SetStats(false);
189 m_l1Histograms["l1_total_result"]->SetMinimum(0);
190
191 const int numberOfL1Flags = m_param_l1Identifiers.size() + m_param_additionalL1Identifiers.size();
192 m_l1Histograms["l1_total_result"]->SetBins(numberOfL1Flags, 0, numberOfL1Flags);
193 // Set bin labels
194 int l1Index = 0;
195 for (const std::string& l1Trigger : m_param_l1Identifiers) {
196 l1Index++;
197 m_l1Histograms["l1_total_result"]->GetXaxis()->SetBinLabel(l1Index, l1Trigger.c_str());
198 }
199 for (const std::string& l1Trigger : m_param_additionalL1Identifiers) {
200 l1Index++;
201 m_l1Histograms["l1_total_result"]->GetXaxis()->SetBinLabel(l1Index, l1Trigger.c_str());
202 }
203 }
204
206 m_runInfoHistograms.emplace("run_number", new TH1D("run_number", "Run Number", 100, 0, 10000));
207 m_runInfoHistograms.emplace("event_number", new TH1D("event_number", "Event Number", 100, 0, 1'000'000));
208 m_runInfoHistograms.emplace("experiment_number", new TH1D("experiment_number", "Experiment Number", 50, 0, 50));
209 }
210
212 if (m_param_histogramDirectoryName != "softwaretrigger_before_filter") {
213 m_runInfoHistograms.emplace("hlt_unit_number", new TH1D("hlt_unit_number_after_filter",
214 ("Number of events per HLT unit " + m_param_pathLocation).c_str(), HLTUnits::max_hlt_units + 1, 0,
215 HLTUnits::max_hlt_units + 1));
216 } else {
217 m_runInfoHistograms.emplace("hlt_unit_number", new TH1D("hlt_unit_number",
218 ("Number of events per HLT unit " + m_param_pathLocation).c_str(), HLTUnits::max_hlt_units + 1, 0,
219 HLTUnits::max_hlt_units + 1));
220 }
221 m_runInfoHistograms["hlt_unit_number"]->SetMinimum(0);
222
223 for (const auto& cutIdentifierPerUnit : m_param_cutResultIdentifiersPerUnit) {
224 m_cutResultPerUnitHistograms.emplace(cutIdentifierPerUnit, new TH1F((cutIdentifierPerUnit + "_per_unit").c_str(),
225 ("Events triggered per unit in HLT : " + cutIdentifierPerUnit).c_str(), HLTUnits::max_hlt_units + 1, 0,
226 HLTUnits::max_hlt_units + 1));
227 m_cutResultPerUnitHistograms[cutIdentifierPerUnit]->SetXTitle("HLT unit number");
228 m_cutResultPerUnitHistograms[cutIdentifierPerUnit]->SetOption("histe");
229 m_cutResultPerUnitHistograms[cutIdentifierPerUnit]->SetMinimum(0);
230 }
231
232 }
233
235 m_runInfoHistograms.emplace("error_flag", new TH1D("error_flag", "Error Flag", 4, 0, 4));
236 m_runInfoHistograms["error_flag"]->SetStats(false);
237 m_runInfoHistograms["error_flag"]->SetOption("hist");
238 m_runInfoHistograms["error_flag"]->SetMinimum(0);
239 }
240
241 if (oldDirectory) {
242 oldDirectory->cd();
243 }
244}
245
247{
248 // Register histograms (calls back defineHisto)
249 REG_HISTOGRAM
250
252 // Read the HLT unit's hostname straight from the HLT worker
253 FILE* pipe = popen("hostname -d", "r");
254 if (pipe) {
255 char buffer[128];
256 std::string host = "";
257
258 while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
259 host += buffer;
260 }
261
262 pclose(pipe);
263
264 if (host.length() == 5) {
265 m_hlt_unit = atoi(host.substr(3, 2).c_str());
266 } else {
267 B2WARNING("HLT unit number not found");
268 }
269 } else {
270 B2WARNING("HLT unit number not found");
271 }
272 }
273}
274
276{
277 // this might be pre-scaled for performance reasons in the final configuration, therefore this structure
278 // might not be filled in every event
279 if (m_variables.isValid()) {
280 for (auto& variableNameAndTH1F : m_triggerVariablesHistograms) {
281 const std::string& variable = variableNameAndTH1F.first;
282 TH1F* histogram = variableNameAndTH1F.second;
283
284 // try to load this variable from the computed trigger variables
285 if (not m_variables->has(variable)) {
286 B2ERROR("Variable " << variable << " configured for SoftwareTriggerDQM plotting is not available");
287 } else {
288 const double value = m_variables->getVariable(variable);
289 histogram->Fill(value);
290 }
291 }
292 }
293
294 if (m_triggerResult.isValid()) {
295 const auto results = m_triggerResult->getResults();
296
297 for (auto const& cutIdentifier : m_param_cutResultIdentifiers) {
298 const std::string& title = cutIdentifier.first;
299 const auto& mapVal = *(m_param_cutResultIdentifiers[title].begin());
300 const std::string& baseIdentifier = mapVal.first;
301 const auto& cuts = mapVal.second;
302
303 // check if we want to ignore it
304 bool skip = false;
305 const auto& cutsIgnored = m_param_cutResultIdentifiersIgnored[baseIdentifier];
306
307 for (const std::string& cutTitleIgnored : cutsIgnored) {
308 const std::string& cutNameIgnored = cutTitleIgnored.substr(0, cutTitleIgnored.find("\\"));
309 const std::string& fullCutIdentifierIgnored = SoftwareTriggerDBHandler::makeFullCutName(baseIdentifier, cutNameIgnored);
310
311 auto const cutEntryIgnored = results.find(fullCutIdentifierIgnored);
312
313 if (cutEntryIgnored != results.end()) {
314 if (cutEntryIgnored->second > 0) skip = true;
315 }
316 }
317
318 float index = 0;
319 for (const std::string& cutTitle : cuts) {
320 index++;
321 const std::string& cutName = cutTitle.substr(0, cutTitle.find("\\"));
322 const std::string& fullCutIdentifier = SoftwareTriggerDBHandler::makeFullCutName(baseIdentifier, cutName);
323
324 // check if the cutResult is in the list, be graceful when not available
325 // Create results object instead of calling .find() on a temporary object. This will cause undefined behaviour
326 // when checking again the .end() pointer, when the .end() pointer is also created from a temporary object.
327 auto const cutEntry = results.find(fullCutIdentifier);
328
329 if (cutEntry != results.end()) {
330 const int cutResult = cutEntry->second;
331 if (cutResult > 0 and not skip) {
332 m_cutResultHistograms[title]->Fill(index - 0.5);
333 }
334 }
335 }
336
338 if (title == baseIdentifier) {
339 const std::string& totalCutIdentifier = SoftwareTriggerDBHandler::makeTotalResultName(baseIdentifier);
340 const int cutResult = static_cast<int>(m_triggerResult->getResult(totalCutIdentifier));
341
342 m_cutResultHistograms["total_result"]->Fill(totalCutIdentifier.c_str(), cutResult > 0);
343 }
344 }
345 }
346
349 m_cutResultHistograms["total_result"]->Fill("total_result", totalResult > 0);
350 }
351
353 for (const std::string& cutIdentifierPerUnit : m_param_cutResultIdentifiersPerUnit) {
354 const std::string& cutName = cutIdentifierPerUnit.substr(0, cutIdentifierPerUnit.find("\\"));
355 const std::string& fullCutIdentifier = SoftwareTriggerDBHandler::makeFullCutName("filter", cutName);
356
357 // check if the cutResult is in the list, be graceful when not available
358 auto const cutEntry = results.find(fullCutIdentifier);
359
360 if (cutEntry != results.end()) {
361 const int cutResult = cutEntry->second;
362 if (cutResult > 0) {
363 m_cutResultPerUnitHistograms[cutIdentifierPerUnit]->Fill(m_hlt_unit);
364 }
365 }
366 }
367 }
368
369 if (m_l1TriggerResult.isValid()) {
370 float l1Index = 0;
371 for (const std::string& l1Trigger : m_param_l1Identifiers) {
372 l1Index++;
373 bool triggerResult;
374 try {
375 triggerResult = m_l1TriggerResult->testPsnm(l1Trigger.c_str());
376 } catch (const std::exception&) {
377 try {
378 triggerResult = m_l1TriggerResult->testInput(l1Trigger.c_str());
379 } catch (const std::exception&) {
380 triggerResult = false;
381 }
382 }
384 if (triggerResult) {
385 m_l1Histograms["l1_total_result"]->Fill(l1Index - 0.5);
386 }
387 }
388
389 if (not triggerResult) {
390 continue;
391 }
392
393 float index = 0;
394 for (auto const& cutIdentifier : m_param_cutResultIdentifiers) {
395 const std::string& title = cutIdentifier.first;
396 const auto& mapVal = *(m_param_cutResultIdentifiers[title].begin());
397 const std::string& baseIdentifier = mapVal.first;
398 const auto& cuts = mapVal.second;
399
400 if (title == baseIdentifier) {
401 for (const std::string& cutTitle : cuts) {
402 index++;
403 const std::string& cutName = cutTitle.substr(0, cutTitle.find("\\"));
404 const std::string& fullCutIdentifier = SoftwareTriggerDBHandler::makeFullCutName(baseIdentifier, cutName);
405
406 // check if the cutResult is in the list, be graceful when not available
407 auto const cutEntry = results.find(fullCutIdentifier);
408
409 if (cutEntry != results.end()) {
410 const int cutResult = cutEntry->second;
411 if (cutResult > 0) {
412 m_l1Histograms[l1Trigger]->Fill(index - 0.5);
413 }
414 }
415 }
416 }
417 }
418
419 index++;
421 if (totalResult > 0) {
422 m_l1Histograms[l1Trigger]->Fill(index - 0.5);
423 }
424 }
426 for (const std::string& l1Trigger : m_param_additionalL1Identifiers) {
427 l1Index++;
428 bool triggerResult;
429 try {
430 triggerResult = m_l1TriggerResult->testPsnm(l1Trigger.c_str());
431 } catch (const std::exception&) {
432 try {
433 triggerResult = m_l1TriggerResult->testInput(l1Trigger.c_str());
434 } catch (const std::exception&) {
435 triggerResult = false;
436 }
437 }
438 if (triggerResult) {
439 m_l1Histograms["l1_total_result"]->Fill(l1Index - 0.5);
440 }
441 }
442 }
443 }
444 }
445
447 m_runInfoHistograms["run_number"]->Fill(m_eventMetaData->getRun());
448 m_runInfoHistograms["event_number"]->Fill(m_eventMetaData->getEvent());
449 m_runInfoHistograms["experiment_number"]->Fill(m_eventMetaData->getExperiment());
450 }
451
453 m_runInfoHistograms["error_flag"]->Fill("B2LinkPacketCRCError",
455 m_runInfoHistograms["error_flag"]->Fill("B2LinkEventCRCError",
457 m_runInfoHistograms["error_flag"]->Fill("HLTCrash",
459 m_runInfoHistograms["error_flag"]->Fill("ReconstructionAbort",
461 }
462
464 m_runInfoHistograms["hlt_unit_number"]->Fill(m_hlt_unit);
465 }
466}
467
469{
470 std::for_each(m_cutResultHistograms.begin(), m_cutResultHistograms.end(),
471 [](auto & it) { it.second->Reset(); });
473 [](auto & it) { it.second->Reset(); });
475 [](auto & it) { it.second->Reset(); });
476 std::for_each(m_l1Histograms.begin(), m_l1Histograms.end(),
477 [](auto & it) { it.second->Reset(); });
478 std::for_each(m_runInfoHistograms.begin(), m_runInfoHistograms.end(),
479 [](auto & it) { it.second->Reset(); });
480}
481
@ c_B2LinkPacketCRCError
Belle2link CRC error is detected in the event.
Definition: EventMetaData.h:44
@ c_HLTCrash
The HLT reconstruction crashed in this event or the event before.
Definition: EventMetaData.h:46
@ c_ReconstructionAbort
The event was not reconstructed, e.g.
Definition: EventMetaData.h:47
@ c_B2LinkEventCRCError
HSLB_COPPER CRC error is detected in the event.
Definition: EventMetaData.h:45
HistoModule.h is supposed to be used instead of Module.h for the modules with histogram definitions t...
Definition: HistoModule.h:29
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
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.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Abstract base class for different kinds of events.