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 (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 (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 (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 (auto& canvasAndHisto : {m_hErrorFlagFraction, m_hFilteredFractionPerUnit}) {
166 auto* canvas = canvasAndHisto.first;
167 canvas->Clear();
168 }
169
170 for (auto& nameAndcanvasAndHisto : m_hl1Ratios) {
171 auto* canvas = nameAndcanvasAndHisto.second.first;
172 canvas->Clear();
173 }
174
175 for (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", 0, true);
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 = getDelta("timing_statistics", "processesPerUnitHistogram", 0, true);
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->GetMean() * 0.5; // Number of HLT threads
262 HLTBudgetTime = nProcs * 1e03 / L1Rate; // unit = ms
263 setEpicsPV("BudgetTime", HLTBudgetTime);
264 }
265
266 if (HLTBudgetTime != 0)
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 = (TH1F*) meanTimeHistogram->Clone("MeanTime");
385 m_hMeanTime.second->Scale(1 / numberOfProcesses);
386
387 if (m_hMeanMemory.second) delete m_hMeanMemory.second;
388 m_hMeanMemory.second = (TH1F*) meanMemoryHistogram->Clone("MeanMemoryChange");
389 m_hMeanMemory.second->Scale(1 / numberOfProcesses);
390
391 if (m_hErrorFlagFraction.second) delete m_hErrorFlagFraction.second;
392 m_hErrorFlagFraction.second = (TH1D*) 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 = (TH1D*) 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 = (TH1F*) fullTimeMeanPerUnitHistogram->Clone("MeanBudgetTimePerUnit");
403 m_hMeanBudgetTimePerUnit.second->Divide(fullTimeMeanPerUnitHistogram, processesPerUnitHistogram);
404
406 m_hMeanProcessingTimePerUnit.second = (TH1F*) 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 (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 (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 (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
void initialize() override final
Initializer.
std::string m_bhabhaName
name of the bhabha trigger
std::pair< TCanvas *, TH1F * > m_hCrossSection
Histogram with final cross sections.
std::map< std::string, std::pair< TCanvas *, TH1F * > > m_hRetentionPerUnit
Histogram with retention rate per unit of some hlt filter lines.
std::map< std::string, std::pair< TCanvas *, TH1F * > > m_hl1Ratios
Histogram with hlt&l1 ratios to l1 numbers.
std::vector< std::string > m_retentionPerUnit
Which HLT filter lines to use for calculation retention rate per unit.
void terminate() override final
This method is called at the end of the event processing.
std::pair< TCanvas *, TH1D * > m_hFilteredFractionPerUnit
Histogram with fraction of events filtered per unit.
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 *, TH1F * > m_hMeanBudgetTimePerUnit
Histogram with mean budget time per unit per process.
std::pair< TCanvas *, TH1F * > m_hMeanProcessingTimePerUnit
Histogram with mean processing time per unit per process.
std::pair< TCanvas *, TH1F * > m_hMeanMemory
Histogram with mean memory change per process.
std::pair< TCanvas *, TH1D * > m_hErrorFlagFraction
Histogram with fraction of events with error flags.
std::pair< TCanvas *, TH1F * > m_hRatios
Histogram with final ratios to bhabha.
std::pair< TCanvas *, TH1F * > m_hEfficiency
Histogram with final efficiencies to HLT.
std::pair< TCanvas *, TH1F * > 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 *, TH1F * > m_hMeanTime
Histogram with mean processing time 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.
static TH1 * findHist(const std::string &histname, bool onlyIfUpdated=false)
Get histogram from list (no other search).
TH1 * getDelta(const std::string &fullname, 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.
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.