Belle II Software development
DQMHistAnalysisHLTModule.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
9#include <dqm/analysis/modules/DQMHistAnalysisHLTModule.h>
10#include <framework/core/ModuleParam.templateDetails.h>
11#include <TROOT.h>
12
13#include <hlt/utilities/Units.h>
14
15using namespace std;
16using namespace Belle2;
17
18namespace {
19 bool hasValue(const std::string& name, TH1* histogram)
20 {
21 return histogram->GetXaxis()->FindFixBin(name.c_str()) != -1;
22 }
23
24 double getValue(const std::string& name, TH1* histogram)
25 {
26 if (not hasValue(name, histogram)) {
27 B2ERROR("This histogram does not have this value! (fallback value = -1)"
28 << LogVar("histogram", histogram->GetName())
29 << LogVar("value", name));
30 return -1;
31 }
32 auto binNumber = histogram->GetXaxis()->FindFixBin(name.c_str());
33 return histogram->GetBinContent(binNumber);
34 }
35}
36
37REG_MODULE(DQMHistAnalysisHLT);
38
40{
41 setDescription("Modify and analyze the data quality histograms of HLT");
42 addParam("bhabhaName", m_bhabhaName, "Name of the bhabha trigger to do a ratio against", m_bhabhaName);
43 addParam("columnMapping", m_columnMapping, "Which columns to use for calculating ratios and cross sections", m_columnMapping);
44 addParam("l1Histograms", m_l1Histograms, "Which l1 histograms to show", m_l1Histograms);
45 addParam("retentionPerUnit", m_retentionPerUnit, "Which HLT filter lines to use for calculation retention rate per unit",
47}
48
50{
51 // this seems to be important, or strange things happen
52 gROOT->cd();
53
55 new TCanvas("HLT/Ratio"),
56 new TH1F("Ratio", "Retention of selected HLT skims", 1, 0, 0)
57 };
59 new TCanvas("HLT/RatioTotal"),
60 new TH1F("RatioTotal", "Ratio of Tags to all events", 1, 0, 0)
61 };
63 new TCanvas("HLT/CrossSection"),
64 new TH1F("CrossSection", "Cross Section of triggered Events", 1, 0, 0)
65 };
66 m_hRatios = {
67 new TCanvas("HLT/RatioToBahbha"),
68 new TH1F("RatioToBahbha", "Ratio to bhabha events", 1, 0, 0)
69 };
70
71 for (const std::string& l1Name : m_l1Histograms) {
72 m_hl1Ratios.emplace(l1Name, std::make_pair(
73 new TCanvas(("HLT/" + l1Name + "RatioToL1").c_str()),
74 // + 1 for total result
75 new TH1F((l1Name + "RatioToL1").c_str(), ("HLT Fractions for L1 " + l1Name).c_str(), 1, 0, 0)
76 ));
77 }
78
79 for (const std::string& filterLine : m_retentionPerUnit) {
80 m_hRetentionPerUnit.emplace(filterLine, std::make_pair(
81 new TCanvas(("HLT/" + filterLine + "_RetentionPerUnit").c_str()),
82 new TH1F((filterLine + "_RetentionPerUnit").c_str(), ("Retention rate per unit of: " + filterLine).c_str(),
83 HLTUnits::max_hlt_units + 1, 0,
84 HLTUnits::max_hlt_units + 1)
85 ));
86 }
87
88 for (const auto& canvasAndHisto : {m_hEfficiencyTotal, m_hEfficiency, m_hCrossSection, m_hRatios}) {
89 auto* histogram = canvasAndHisto.second;
90 histogram->SetDirectory(0);
91 histogram->SetOption("bar");
92 histogram->SetFillStyle(0);
93 histogram->SetMinimum(0);
94 histogram->SetStats(false);
95 histogram->Draw("hist");
96 }
97
98 for (const auto& nameAndcanvasAndHisto : m_hl1Ratios) {
99 auto* histogram = nameAndcanvasAndHisto.second.second;
100 histogram->SetDirectory(0);
101 histogram->SetOption("bar");
102 histogram->SetFillStyle(0);
103 histogram->SetStats(false);
104 histogram->Draw("hist");
105 }
106
107 for (const auto& nameAndcanvasAndHisto : m_hRetentionPerUnit) {
108 auto* histogram = nameAndcanvasAndHisto.second.second;
109 histogram->SetDirectory(0);
110 histogram->SetOption("histe");
111 histogram->SetMinimum(0);
112 histogram->SetStats(false);
113 histogram->Draw();
114 }
115
116 m_hMeanTime = {
117 new TCanvas("HLT/MeanTime"),
118 new TH1F("MeanTime", "Mean processing time", 1, 0, 0)
119 };
120
122 new TCanvas("HLT/ErrorFlagFraction"),
123 new TH1D("ErrorFlagFraction", "Fraction of events with Error Flags", 1, 0, 0)
124 };
125
127 new TCanvas("HLT/FilteredFractionPerUnit"),
128 new TH1D("FilteredFractionPerUnit", "Fraction of events filtered per unit", 1, 0, 0)
129 };
130
132 new TCanvas("HLT/MeanBudgetTimePerUnit"),
133 new TH1F("MeanBudgetTimePerUnit", "Mean budget time per unit", 1, 0, 0)
134 };
135
137 new TCanvas("HLT/MeanProcessingTimePerUnit"),
138 new TH1F("MeanProcessingTimePerUnit", "Mean processing time per unit", 1, 0, 0)
139 };
140
141 m_hMeanMemory = {
142 new TCanvas("HLT/MeanMemoryChange"),
143 new TH1F("MeanMemoryChange", "Mean memory change [MB]", 1, 0, 0)
144 };
145
146 //EPICS PVs for HLT
147 addDeltaPar("timing_statistics", "processingTimeHistogram", HistDelta::c_Events, 10000, 1);
148 addDeltaPar("timing_statistics", "processesPerUnitHistogram", HistDelta::c_Events, 10000, 1);
149 registerExternalEpicsPV("B2_nsm:get:ECL_LUM_MON:lum_det_run", "instLuminosity");
150 registerExternalEpicsPV("B2_nsm:get:TTDS_COM:trigoutrate", "L1Rate");
151 registerEpicsPV("HLT:ProcessingTime", "ProcessingTime");
152 registerEpicsPV("HLT:BudgetTime", "BudgetTime");
153 registerEpicsPV("HLT:CPUUsage", "CPUUsage");
154
155}
156
157
159{
161 auto* canvas = canvasAndHisto.first;
162 canvas->Clear();
163 }
164
165 for (const auto& canvasAndHisto : {m_hErrorFlagFraction, m_hFilteredFractionPerUnit}) {
166 auto* canvas = canvasAndHisto.first;
167 canvas->Clear();
168 }
169
170 for (const auto& nameAndcanvasAndHisto : m_hl1Ratios) {
171 auto* canvas = nameAndcanvasAndHisto.second.first;
172 canvas->Clear();
173 }
174
175 for (const auto& nameAndcanvasAndHisto : m_hRetentionPerUnit) {
176 auto* canvas = nameAndcanvasAndHisto.second.first;
177 canvas->Clear();
178 }
179
180 // Set alarm limits for HLT:CPUUsage epicsPV
181 double unused = NAN;
182 double m_meanUpperWarn = 0.9;
183 double m_meanUpperAlarm = 1.0;
184 requestLimitsFromEpicsPVs("CPUUsage", unused, unused, m_meanUpperWarn, m_meanUpperAlarm);
185
186}
187
189{
190 auto* filterHistogram = findHist("softwaretrigger/filter");
191 auto* skimHistogram = findHist("softwaretrigger/skim");
192 auto* totalResultHistogram = findHist("softwaretrigger/total_result");
193 auto* hltUnitNumberHistogram = findHist("softwaretrigger_before_filter/hlt_unit_number");
194 auto* processesPerUnitHistogram = findHist("timing_statistics/processesPerUnitHistogram");
195 auto* meanTimeHistogram = findHist("timing_statistics/meanTimeHistogram");
196 auto* errorFlagHistogram = findHist("softwaretrigger_before_filter/error_flag");
197 auto* hltUnitNumberHistogram_filtered = findHist("softwaretrigger/hlt_unit_number_after_filter");
198 auto* fullTimeMeanPerUnitHistogram = findHist("timing_statistics/fullTimeMeanPerUnitHistogram");
199 auto* processingTimeMeanPerUnitHistogram = findHist("timing_statistics/processingTimeMeanPerUnitHistogram");
200 auto* meanMemoryHistogram = findHist("timing_statistics/meanMemoryHistogram");
201
202 if (not filterHistogram) {
203 B2ERROR("Can not find the filter histogram!");
204 return;
205 }
206 if (not skimHistogram) {
207 B2ERROR("Can not find the skim histogram!");
208 return;
209 }
210 if (not totalResultHistogram) {
211 B2ERROR("Can not find the total result histogram!");
212 return;
213 }
214 if (not hltUnitNumberHistogram) {
215 B2ERROR("Can not find the HLT unit number histogram!");
216 return;
217 }
218 if (not processesPerUnitHistogram) {
219 B2ERROR("Can not find the processes per unit histogram!");
220 return;
221 }
222 if (not meanTimeHistogram) {
223 B2ERROR("Can not find the mean processing time histogram!");
224 return;
225 }
226 if (not errorFlagHistogram) {
227 B2ERROR("Can not find the error flag histogram!");
228 return;
229 }
230 if (not hltUnitNumberHistogram_filtered) {
231 B2ERROR("Can not find the HLT unit number after filter histogram!");
232 return;
233 }
234 if (not fullTimeMeanPerUnitHistogram) {
235 B2ERROR("Can not find the HLT budget time per unit histogram!");
236 return;
237 }
238 if (not processingTimeMeanPerUnitHistogram) {
239 B2ERROR("Can not find the HLT processing time per unit histogram!");
240 return;
241 }
242 if (not meanMemoryHistogram) {
243 B2ERROR("Can not find the mean memory change histogram!");
244 return;
245 }
246
247 // Set the epicsPVs for HLT
248 auto hist_ProcessingTime = getDelta("timing_statistics", "processingTimeHistogram");
249 double HLTProcessingTime = 0;
250
251 if (hist_ProcessingTime) {
252 HLTProcessingTime = hist_ProcessingTime->GetMean(); // unit = ms
253 setEpicsPV("ProcessingTime", HLTProcessingTime);
254 }
255
256 auto hist_Procs = findHist("timing_statistics/processesPerUnitHistogram");
257 double HLTBudgetTime = 0; // Number of HLT threads / L1 rate [kHz]
258 double L1Rate = getEpicsPV("L1Rate");
259
260 if (hist_Procs && L1Rate != 0) {
261 double nProcs = hist_Procs->GetEntries() * 0.5; // Number of HLT threads
262 HLTBudgetTime = nProcs * 1e03 / L1Rate; // unit = ms
263 setEpicsPV("BudgetTime", HLTBudgetTime);
264 }
265
266 if (HLTBudgetTime != 0 and hist_ProcessingTime)
267 setEpicsPV("CPUUsage", HLTProcessingTime / HLTBudgetTime);
268
269
270 m_hEfficiencyTotal.second->Reset();
271 m_hEfficiency.second->Reset();
272 m_hCrossSection.second->Reset();
273 m_hRatios.second->Reset();
274
275 double instLuminosity = getEpicsPV("instLuminosity");
276 double numberOfAcceptedHLTEvents = getValue("total_result", totalResultHistogram);
277 double numberOfBhabhaEvents = getValue(m_bhabhaName, skimHistogram);
278 double numberOfAllEvents = hltUnitNumberHistogram->GetEntries();
279 double numberOfProcesses = processesPerUnitHistogram->GetEntries();
280
281 m_hEfficiencyTotal.second->Fill("total_result", numberOfAcceptedHLTEvents / numberOfAllEvents);
282 if (instLuminosity != 0) {
283 m_hCrossSection.second->Fill("total_result", numberOfAcceptedHLTEvents / numberOfAllEvents * instLuminosity);
284 }
285 m_hRatios.second->Fill("total_result", numberOfAcceptedHLTEvents / numberOfBhabhaEvents);
286
287 for (const auto& columnMapping : m_columnMapping) {
288 const auto& from = columnMapping.first;
289 const auto& to = columnMapping.second;
290
291 double value = 0;
292 if (hasValue(from, filterHistogram)) {
293 value = getValue(from, filterHistogram);
294 } else if (hasValue(from, skimHistogram)) {
295 value = getValue(from, skimHistogram);
296 } else {
297 B2ERROR("Can not find value " << from << ". Will not use it!");
298 continue;
299 }
300
301 m_hEfficiency.second->Fill(to.c_str(), value / numberOfAcceptedHLTEvents);
302 m_hEfficiencyTotal.second->Fill(to.c_str(), value / numberOfAllEvents);
303 if (instLuminosity != 0) {
304 m_hCrossSection.second->Fill(to.c_str(), value / numberOfAllEvents * instLuminosity);
305 }
306 m_hRatios.second->Fill(to.c_str(), value / numberOfBhabhaEvents);
307 }
308
309 for (const std::string& l1Name : m_l1Histograms) {
310 auto* histogram = m_hl1Ratios.at(l1Name).second;
311 histogram->Reset();
312
313 auto* l1Histogram = findHist("softwaretrigger/" + l1Name);
314 auto* l1TotalResultHistogram = findHist("softwaretrigger/l1_total_result");
315
316 if (not l1Histogram or not l1TotalResultHistogram) {
317 B2ERROR("Can not find L1 histograms from softwaretrigger!");
318 continue;
319 }
320
321 for (const auto& columnMapping : m_columnMapping) {
322 const auto& from = columnMapping.first;
323 const auto& to = columnMapping.second;
324
325 if (not hasValue(from, l1Histogram)) {
326 B2ERROR("Can not find label " << from << " in l1 histogram " << l1Name);
327 continue;
328 }
329
330 if (not hasValue(l1Name, l1TotalResultHistogram)) {
331 B2ERROR("Can not find label " << l1Name << " in l1 total result histogram");
332 continue;
333 }
334
335 const double hltValueInL1Bin = getValue(from, l1Histogram);
336 const double l1TotalResult = getValue(l1Name, l1TotalResultHistogram);
337
338 histogram->Fill(to.c_str(), hltValueInL1Bin / l1TotalResult);
339 }
340
341 // and add a total result bin
342 const auto from = "hlt_result";
343 const auto to = "hlt_result";
344
345 if (not hasValue(from, l1Histogram)) {
346 B2ERROR("Can not find label " << from << " in l1 histogram " << l1Name);
347 continue;
348 }
349
350 if (not hasValue(l1Name, l1TotalResultHistogram)) {
351 B2ERROR("Can not find label " << l1Name << " in l1 total result histogram");
352 continue;
353 }
354
355 const double hltValueInL1Bin = getValue(from, l1Histogram);
356 const double l1TotalResult = getValue(l1Name, l1TotalResultHistogram);
357
358 histogram->Fill(to, hltValueInL1Bin / l1TotalResult);
359 }
360
361 for (const std::string& filterLine : m_retentionPerUnit) {
362 auto* histogram = m_hRetentionPerUnit.at(filterLine).second;
363 histogram->Reset();
364
365 auto* filterLineHistogram = findHist("softwaretrigger/" + filterLine + "_per_unit");
366
367 if (not filterLineHistogram) {
368 B2ERROR("Can not find " << filterLineHistogram << "_per_event histograms from softwaretrigger!");
369 continue;
370 }
371
372 for (unsigned int i = 1; i <= HLTUnits::max_hlt_units + 1; i++) {
373 double totalUnitValue = hltUnitNumberHistogram->GetBinContent(i);
374 if (totalUnitValue == 0) {
375 histogram->Fill(i, 0);
376 } else {
377 double filterLineUnitValue = filterLineHistogram->GetBinContent(i);
378 histogram->SetBinContent(i, filterLineUnitValue / totalUnitValue);
379 }
380 }
381 }
382
383 if (m_hMeanTime.second) delete m_hMeanTime.second;
384 m_hMeanTime.second = dynamic_cast<TH1*>(meanTimeHistogram->Clone("MeanTime"));
385 m_hMeanTime.second->Scale(1 / numberOfProcesses);
386
387 if (m_hMeanMemory.second) delete m_hMeanMemory.second;
388 m_hMeanMemory.second = dynamic_cast<TH1*>(meanMemoryHistogram->Clone("MeanMemoryChange"));
389 m_hMeanMemory.second->Scale(1 / numberOfProcesses);
390
391 if (m_hErrorFlagFraction.second) delete m_hErrorFlagFraction.second;
392 m_hErrorFlagFraction.second = dynamic_cast<TH1*>(errorFlagHistogram->Clone("ErrorFlagFraction"));
393 m_hErrorFlagFraction.second->Scale(1 / numberOfAllEvents);
394 m_hErrorFlagFraction.second->SetTitle("Fraction of events with error flags");
395
397 m_hFilteredFractionPerUnit.second = dynamic_cast<TH1*>(hltUnitNumberHistogram_filtered->Clone("FilteredFractionPerUnit"));
398 m_hFilteredFractionPerUnit.second->Divide(hltUnitNumberHistogram_filtered, hltUnitNumberHistogram);
399 m_hFilteredFractionPerUnit.second->SetTitle("Fraction of events filtered per unit");
400
401 if (m_hMeanBudgetTimePerUnit.second) delete m_hMeanBudgetTimePerUnit.second;
402 m_hMeanBudgetTimePerUnit.second = dynamic_cast<TH1*>(fullTimeMeanPerUnitHistogram->Clone("MeanBudgetTimePerUnit"));
403 m_hMeanBudgetTimePerUnit.second->Divide(fullTimeMeanPerUnitHistogram, processesPerUnitHistogram);
404
406 m_hMeanProcessingTimePerUnit.second = dynamic_cast<TH1*>(processingTimeMeanPerUnitHistogram->Clone("MeanProcessingTimePerUnit"));
407 m_hMeanProcessingTimePerUnit.second->Divide(processingTimeMeanPerUnitHistogram, processesPerUnitHistogram);
408
410 auto* canvas = canvasAndHisto.first;
411 auto* histogram = canvasAndHisto.second;
412
413 canvas->cd();
414 histogram->LabelsDeflate("X");
415 histogram->Draw("hist");
416 canvas->Modified();
417 canvas->Update();
418 }
419
420 for (const auto& canvasAndHisto : {m_hErrorFlagFraction, m_hFilteredFractionPerUnit}) {
421 auto* canvas = canvasAndHisto.first;
422 auto* histogram = canvasAndHisto.second;
423
424 canvas->cd();
425 histogram->LabelsDeflate("X");
426 histogram->Draw("hist");
427 histogram->SetStats(false);
428 canvas->Modified();
429 canvas->Update();
430 }
431
432 for (const auto& nameAndCanvasAndHisto : m_hl1Ratios) {
433 auto* canvas = nameAndCanvasAndHisto.second.first;
434 auto* histogram = nameAndCanvasAndHisto.second.second;
435
436 canvas->cd();
437 histogram->LabelsDeflate("X");
438 histogram->Draw("hist");
439 canvas->Modified();
440 canvas->Update();
441 }
442
443 for (const auto& nameAndCanvasAndHisto : m_hRetentionPerUnit) {
444 auto* canvas = nameAndCanvasAndHisto.second.first;
445 auto* histogram = nameAndCanvasAndHisto.second.second;
446
447 canvas->cd();
448 histogram->Draw("hist");
449 canvas->Modified();
450 canvas->Update();
451 }
452}
453
std::pair< TCanvas *, TH1 * > m_hFilteredFractionPerUnit
Histogram with fraction of events filtered per unit.
std::pair< TCanvas *, TH1 * > m_hCrossSection
Histogram with final cross sections.
void initialize() override final
Initializer.
std::string m_bhabhaName
name of the bhabha trigger
std::pair< TCanvas *, TH1 * > m_hRatios
Histogram with final ratios to bhabha.
std::map< std::string, std::pair< TCanvas *, TH1 * > > m_hRetentionPerUnit
Histogram with retention rate per unit of some hlt filter lines.
std::vector< std::string > m_retentionPerUnit
Which HLT filter lines to use for calculation retention rate per unit.
std::map< std::string, std::pair< TCanvas *, TH1 * > > m_hl1Ratios
Histogram with hlt&l1 ratios to l1 numbers.
std::pair< TCanvas *, TH1 * > m_hMeanProcessingTimePerUnit
Histogram with mean processing time per unit per process.
std::pair< TCanvas *, TH1 * > m_hMeanBudgetTimePerUnit
Histogram with mean budget time per unit per process.
std::pair< TCanvas *, TH1 * > m_hMeanTime
Histogram with mean processing time per process.
void terminate() override final
This method is called at the end of the event processing.
void event() override final
This method is called for each event.
std::vector< std::string > m_l1Histograms
Which l1 triggers to show.
std::pair< TCanvas *, TH1 * > m_hEfficiency
Histogram with final efficiencies to HLT.
std::pair< TCanvas *, TH1 * > m_hEfficiencyTotal
Histogram with final efficiencies to all events.
void beginRun() override final
Called when entering a new run.
std::map< std::string, std::string > m_columnMapping
Which columns to use.
std::pair< TCanvas *, TH1 * > m_hErrorFlagFraction
Histogram with fraction of events with error flags.
std::pair< TCanvas *, TH1 * > m_hMeanMemory
Histogram with mean memory change per process.
int registerEpicsPV(const std::string &pvname, const std::string &keyname="")
EPICS related Functions.
int registerExternalEpicsPV(const std::string &pvname, const std::string &keyname="")
Register a PV with its name and a key name.
static void addDeltaPar(const std::string &dirname, const std::string &histname, HistDelta::EDeltaType t, int p, unsigned int a=1)
Add Delta histogram parameters.
TH1 * getDelta(const std::string &dirname, const std::string &histname="", int n=0, bool onlyIfUpdated=true)
Get Delta histogram.
double getEpicsPV(const std::string &keyname)
Read value from a EPICS PV.
bool requestLimitsFromEpicsPVs(chid id, double &lowerAlarm, double &lowerWarn, double &upperWarn, double &upperAlarm)
Get Alarm Limits from EPICS PV.
void setEpicsPV(const std::string &keyname, double value)
Write value to a EPICS PV.
static TH1 * findHist(const std::string &dirname, const std::string &histname="", bool onlyIfUpdated=false)
Find histogram.
void setDescription(const std::string &description)
Sets the description of the module.
Definition Module.cc:214
Class to store variables with their name which were sent to the logging service.
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:559
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition Module.h:649
Abstract base class for different kinds of events.
STL namespace.