Belle II Software  release-08-01-10
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 
15 using namespace std;
16 using namespace Belle2;
17 
18 namespace {
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 
37 REG_MODULE(DQMHistAnalysisHLT);
38 
39 DQMHistAnalysisHLTModule::DQMHistAnalysisHLTModule()
40 {
41  setDescription("Modify and analyze the data quality histograms of HLT");
42  addParam("pvPrefix", m_pvPrefix, "EPICS PV Name for the inst. luminosity", m_pvPrefix);
43  addParam("bhabhaName", m_bhabhaName, "Name of the bhabha trigger to do a ratio against", m_bhabhaName);
44  addParam("columnMapping", m_columnMapping, "Which columns to use for calculating ratios and cross sections", m_columnMapping);
45  addParam("l1Histograms", m_l1Histograms, "Which l1 histograms to show", m_l1Histograms);
46  addParam("retentionPerUnit", m_retentionPerUnit, "Which HLT filter lines to use for calculation retention rate per unit",
47  m_retentionPerUnit);
48 }
49 
50 void DQMHistAnalysisHLTModule::initialize()
51 {
52  // this seems to be important, or strange things happen
53  gROOT->cd();
54 
55  m_hEfficiency = {
56  new TCanvas("HLT/Ratio"),
57  new TH1F("Ratio", "Retention of selected HLT skims", 1, 0, 0)
58  };
59  m_hEfficiencyTotal = {
60  new TCanvas("HLT/RatioTotal"),
61  new TH1F("RatioTotal", "Ratio of Tags to all events", 1, 0, 0)
62  };
63  m_hCrossSection = {
64  new TCanvas("HLT/CrossSection"),
65  new TH1F("CrossSection", "Cross Section of triggered Events", 1, 0, 0)
66  };
67  m_hRatios = {
68  new TCanvas("HLT/RatioToBahbha"),
69  new TH1F("RatioToBahbha", "Ratio to bhabha events", 1, 0, 0)
70  };
71 
72  for (const std::string& l1Name : m_l1Histograms) {
73  m_hl1Ratios.emplace(l1Name, std::make_pair(
74  new TCanvas(("HLT/" + l1Name + "RatioToL1").c_str()),
75  // + 1 for total result
76  new TH1F((l1Name + "RatioToL1").c_str(), ("HLT Fractions for L1 " + l1Name).c_str(), 1, 0, 0)
77  ));
78  }
79 
80  for (const std::string& filterLine : m_retentionPerUnit) {
81  m_hRetentionPerUnit.emplace(filterLine, std::make_pair(
82  new TCanvas(("HLT/" + filterLine + "_RetentionPerUnit").c_str()),
83  new TH1F((filterLine + "_RetentionPerUnit").c_str(), ("Retention rate per unit of: " + filterLine).c_str(),
84  HLTUnits::max_hlt_units + 1, 0,
85  HLTUnits::max_hlt_units + 1)
86  ));
87  }
88 
89  for (auto& canvasAndHisto : {m_hEfficiencyTotal, m_hEfficiency, m_hCrossSection, m_hRatios}) {
90  auto* histogram = canvasAndHisto.second;
91  histogram->SetDirectory(0);
92  histogram->SetOption("bar");
93  histogram->SetFillStyle(0);
94  histogram->SetMinimum(0);
95  histogram->SetStats(false);
96  histogram->Draw("hist");
97  }
98 
99  for (auto& nameAndcanvasAndHisto : m_hl1Ratios) {
100  auto* histogram = nameAndcanvasAndHisto.second.second;
101  histogram->SetDirectory(0);
102  histogram->SetOption("bar");
103  histogram->SetFillStyle(0);
104  histogram->SetStats(false);
105  histogram->Draw("hist");
106  }
107 
108  for (auto& nameAndcanvasAndHisto : m_hRetentionPerUnit) {
109  auto* histogram = nameAndcanvasAndHisto.second.second;
110  histogram->SetDirectory(0);
111  histogram->SetOption("histe");
112  histogram->SetMinimum(0);
113  histogram->SetStats(false);
114  histogram->Draw();
115  }
116 
117  m_hMeanTime = {
118  new TCanvas("HLT/MeanTime"),
119  new TH1F("MeanTime", "Mean processing time", 1, 0, 0)
120  };
121 
122  m_hErrorFlagFraction = {
123  new TCanvas("HLT/ErrorFlagFraction"),
124  new TH1D("ErrorFlagFraction", "Fraction of events with Error Flags", 1, 0, 0)
125  };
126 
127  m_hFilteredFractionPerUnit = {
128  new TCanvas("HLT/FilteredFractionPerUnit"),
129  new TH1D("FilteredFractionPerUnit", "Fraction of events filtered per unit", 1, 0, 0)
130  };
131 
132  m_hMeanBudgetTimePerUnit = {
133  new TCanvas("HLT/MeanBudgetTimePerUnit"),
134  new TH1F("MeanBudgetTimePerUnit", "Mean budget time per unit", 1, 0, 0)
135  };
136 
137  m_hMeanProcessingTimePerUnit = {
138  new TCanvas("HLT/MeanProcessingTimePerUnit"),
139  new TH1F("MeanProcessingTimePerUnit", "Mean processing time per unit", 1, 0, 0)
140  };
141 
142  m_hMeanMemory = {
143  new TCanvas("HLT/MeanMemoryChange"),
144  new TH1F("MeanMemoryChange", "Mean memory change [MB]", 1, 0, 0)
145  };
146 
147 #ifdef _BELLE2_EPICS
148  if (not m_pvPrefix.empty()) {
149  if (!ca_current_context()) SEVCHK(ca_context_create(ca_disable_preemptive_callback), "ca_context_create");
150  SEVCHK(ca_create_channel(m_pvPrefix.data(), NULL, NULL, 10, &m_epicschid), "ca_create_channel failure");
151  SEVCHK(ca_pend_io(5.0), "ca_pend_io failure");
152  }
153 #endif
154 }
155 
156 
157 void DQMHistAnalysisHLTModule::beginRun()
158 {
159  for (auto& canvasAndHisto : {m_hEfficiencyTotal, m_hEfficiency, m_hCrossSection, m_hRatios, m_hMeanTime, m_hMeanBudgetTimePerUnit, m_hMeanProcessingTimePerUnit, m_hMeanMemory}) {
160  auto* canvas = canvasAndHisto.first;
161  canvas->Clear();
162  }
163 
164  for (auto& canvasAndHisto : {m_hErrorFlagFraction, m_hFilteredFractionPerUnit}) {
165  auto* canvas = canvasAndHisto.first;
166  canvas->Clear();
167  }
168 
169  for (auto& nameAndcanvasAndHisto : m_hl1Ratios) {
170  auto* canvas = nameAndcanvasAndHisto.second.first;
171  canvas->Clear();
172  }
173 
174  for (auto& nameAndcanvasAndHisto : m_hRetentionPerUnit) {
175  auto* canvas = nameAndcanvasAndHisto.second.first;
176  canvas->Clear();
177  }
178 }
179 
180 void DQMHistAnalysisHLTModule::event()
181 {
182  auto* filterHistogram = findHist("softwaretrigger/filter");
183  auto* skimHistogram = findHist("softwaretrigger/skim");
184  auto* totalResultHistogram = findHist("softwaretrigger/total_result");
185  auto* hltUnitNumberHistogram = findHist("softwaretrigger_before_filter/hlt_unit_number");
186  auto* processesPerUnitHistogram = findHist("timing_statistics/processesPerUnitHistogram");
187  auto* meanTimeHistogram = findHist("timing_statistics/meanTimeHistogram");
188  auto* errorFlagHistogram = findHist("softwaretrigger_before_filter/error_flag");
189  auto* hltUnitNumberHistogram_filtered = findHist("softwaretrigger/hlt_unit_number_after_filter");
190  auto* fullTimeMeanPerUnitHistogram = findHist("timing_statistics/fullTimeMeanPerUnitHistogram");
191  auto* processingTimeMeanPerUnitHistogram = findHist("timing_statistics/processingTimeMeanPerUnitHistogram");
192  auto* meanMemoryHistogram = findHist("timing_statistics/meanMemoryHistogram");
193 
194  if (not filterHistogram) {
195  B2ERROR("Can not find the filter histogram!");
196  return;
197  }
198  if (not skimHistogram) {
199  B2ERROR("Can not find the skim histogram!");
200  return;
201  }
202  if (not totalResultHistogram) {
203  B2ERROR("Can not find the total result histogram!");
204  return;
205  }
206  if (not hltUnitNumberHistogram) {
207  B2ERROR("Can not find the HLT unit number histogram!");
208  return;
209  }
210  if (not processesPerUnitHistogram) {
211  B2ERROR("Can not find the processes per unit histogram!");
212  return;
213  }
214  if (not meanTimeHistogram) {
215  B2ERROR("Can not find the mean processing time histogram!");
216  return;
217  }
218  if (not errorFlagHistogram) {
219  B2ERROR("Can not find the error flag histogram!");
220  return;
221  }
222  if (not hltUnitNumberHistogram_filtered) {
223  B2ERROR("Can not find the HLT unit number after filter histogram!");
224  return;
225  }
226  if (not fullTimeMeanPerUnitHistogram) {
227  B2ERROR("Can not find the HLT budget time per unit histogram!");
228  return;
229  }
230  if (not processingTimeMeanPerUnitHistogram) {
231  B2ERROR("Can not find the HLT processing time per unit histogram!");
232  return;
233  }
234  if (not meanMemoryHistogram) {
235  B2ERROR("Can not find the mean memory change histogram!");
236  return;
237  }
238 
239  m_hEfficiencyTotal.second->Reset();
240  m_hEfficiency.second->Reset();
241  m_hCrossSection.second->Reset();
242  m_hRatios.second->Reset();
243 
244  double instLuminosity = 0;
245  double numberOfAcceptedHLTEvents = getValue("total_result", totalResultHistogram);
246  double numberOfBhabhaEvents = getValue(m_bhabhaName, skimHistogram);
247  double numberOfAllEvents = hltUnitNumberHistogram->GetEntries();
248  double numberOfProcesses = processesPerUnitHistogram->GetEntries();
249 
250 #ifdef _BELLE2_EPICS
251  if (not m_pvPrefix.empty()) {
252  SEVCHK(ca_get(DBR_DOUBLE, m_epicschid, (void*)&instLuminosity), "ca_get failure");
253  SEVCHK(ca_pend_io(5.0), "ca_pend_io failure");
254  } else {
255  instLuminosity = 0;
256  }
257 #endif
258 
259  m_hEfficiencyTotal.second->Fill("total_result", numberOfAcceptedHLTEvents / numberOfAllEvents);
260  if (instLuminosity != 0) {
261  m_hCrossSection.second->Fill("total_result", numberOfAcceptedHLTEvents / numberOfAllEvents * instLuminosity);
262  }
263  m_hRatios.second->Fill("total_result", numberOfAcceptedHLTEvents / numberOfBhabhaEvents);
264 
265  for (const auto& columnMapping : m_columnMapping) {
266  const auto& from = columnMapping.first;
267  const auto& to = columnMapping.second;
268 
269  double value = 0;
270  if (hasValue(from, filterHistogram)) {
271  value = getValue(from, filterHistogram);
272  } else if (hasValue(from, skimHistogram)) {
273  value = getValue(from, skimHistogram);
274  } else {
275  B2ERROR("Can not find value " << from << ". Will not use it!");
276  continue;
277  }
278 
279  m_hEfficiency.second->Fill(to.c_str(), value / numberOfAcceptedHLTEvents);
280  m_hEfficiencyTotal.second->Fill(to.c_str(), value / numberOfAllEvents);
281  if (instLuminosity != 0) {
282  m_hCrossSection.second->Fill(to.c_str(), value / numberOfAllEvents * instLuminosity);
283  }
284  m_hRatios.second->Fill(to.c_str(), value / numberOfBhabhaEvents);
285  }
286 
287  for (const std::string& l1Name : m_l1Histograms) {
288  auto* histogram = m_hl1Ratios.at(l1Name).second;
289  histogram->Reset();
290 
291  auto* l1Histogram = findHist("softwaretrigger/" + l1Name);
292  auto* l1TotalResultHistogram = findHist("softwaretrigger/l1_total_result");
293 
294  if (not l1Histogram or not l1TotalResultHistogram) {
295  B2ERROR("Can not find L1 histograms from softwaretrigger!");
296  continue;
297  }
298 
299  for (const auto& columnMapping : m_columnMapping) {
300  const auto& from = columnMapping.first;
301  const auto& to = columnMapping.second;
302 
303  if (not hasValue(from, l1Histogram)) {
304  B2ERROR("Can not find label " << from << " in l1 histogram " << l1Name);
305  continue;
306  }
307 
308  if (not hasValue(l1Name, l1TotalResultHistogram)) {
309  B2ERROR("Can not find label " << l1Name << " in l1 total result histogram");
310  continue;
311  }
312 
313  const double hltValueInL1Bin = getValue(from, l1Histogram);
314  const double l1TotalResult = getValue(l1Name, l1TotalResultHistogram);
315 
316  histogram->Fill(to.c_str(), hltValueInL1Bin / l1TotalResult);
317  }
318 
319  // and add a total result bin
320  const auto from = "hlt_result";
321  const auto to = "hlt_result";
322 
323  if (not hasValue(from, l1Histogram)) {
324  B2ERROR("Can not find label " << from << " in l1 histogram " << l1Name);
325  continue;
326  }
327 
328  if (not hasValue(l1Name, l1TotalResultHistogram)) {
329  B2ERROR("Can not find label " << l1Name << " in l1 total result histogram");
330  continue;
331  }
332 
333  const double hltValueInL1Bin = getValue(from, l1Histogram);
334  const double l1TotalResult = getValue(l1Name, l1TotalResultHistogram);
335 
336  histogram->Fill(to, hltValueInL1Bin / l1TotalResult);
337  }
338 
339  for (const std::string& filterLine : m_retentionPerUnit) {
340  auto* histogram = m_hRetentionPerUnit.at(filterLine).second;
341  histogram->Reset();
342 
343  auto* filterLineHistogram = findHist("softwaretrigger/" + filterLine + "_per_unit");
344 
345  if (not filterLineHistogram) {
346  B2ERROR("Can not find " << filterLineHistogram << "_per_event histograms from softwaretrigger!");
347  continue;
348  }
349 
350  for (unsigned int i = 1; i <= HLTUnits::max_hlt_units + 1; i++) {
351  double totalUnitValue = hltUnitNumberHistogram->GetBinContent(i);
352  if (totalUnitValue == 0) {
353  histogram->Fill(i, 0);
354  } else {
355  double filterLineUnitValue = filterLineHistogram->GetBinContent(i);
356  histogram->SetBinContent(i, filterLineUnitValue / totalUnitValue);
357  }
358  }
359  }
360 
361  m_hMeanTime.second = (TH1F*) meanTimeHistogram->Clone("MeanTime");
362  m_hMeanTime.second->Scale(1 / numberOfProcesses);
363 
364  m_hMeanMemory.second = (TH1F*) meanMemoryHistogram->Clone("MeanMemoryChange");
365  m_hMeanMemory.second->Scale(1 / numberOfProcesses);
366 
367  m_hErrorFlagFraction.second = (TH1D*) errorFlagHistogram->Clone("ErrorFlagFraction");
368  m_hErrorFlagFraction.second->Scale(1 / numberOfAllEvents);
369  m_hErrorFlagFraction.second->SetTitle("Fraction of events with error flags");
370 
371  m_hFilteredFractionPerUnit.second = (TH1D*) hltUnitNumberHistogram_filtered->Clone("FilteredFractionPerUnit");
372  m_hFilteredFractionPerUnit.second->Divide(hltUnitNumberHistogram_filtered, hltUnitNumberHistogram);
373  m_hFilteredFractionPerUnit.second->SetTitle("Fraction of events filtered per unit");
374 
375  m_hMeanBudgetTimePerUnit.second = (TH1F*) fullTimeMeanPerUnitHistogram->Clone("MeanBudgetTimePerUnit");
376  m_hMeanBudgetTimePerUnit.second->Divide(fullTimeMeanPerUnitHistogram, processesPerUnitHistogram);
377 
378  m_hMeanProcessingTimePerUnit.second = (TH1F*) processingTimeMeanPerUnitHistogram->Clone("MeanProcessingTimePerUnit");
379  m_hMeanProcessingTimePerUnit.second->Divide(processingTimeMeanPerUnitHistogram, processesPerUnitHistogram);
380 
381  for (auto& canvasAndHisto : {m_hEfficiencyTotal, m_hEfficiency, m_hCrossSection, m_hRatios, m_hMeanTime, m_hMeanBudgetTimePerUnit, m_hMeanProcessingTimePerUnit, m_hMeanMemory}) {
382  auto* canvas = canvasAndHisto.first;
383  auto* histogram = canvasAndHisto.second;
384 
385  canvas->cd();
386  histogram->LabelsDeflate("X");
387  histogram->Draw("hist");
388  canvas->Modified();
389  canvas->Update();
390  }
391 
392  for (auto& canvasAndHisto : {m_hErrorFlagFraction, m_hFilteredFractionPerUnit}) {
393  auto* canvas = canvasAndHisto.first;
394  auto* histogram = canvasAndHisto.second;
395 
396  canvas->cd();
397  histogram->LabelsDeflate("X");
398  histogram->Draw("hist");
399  histogram->SetStats(false);
400  canvas->Modified();
401  canvas->Update();
402  }
403 
404  for (auto& nameAndCanvasAndHisto : m_hl1Ratios) {
405  auto* canvas = nameAndCanvasAndHisto.second.first;
406  auto* histogram = nameAndCanvasAndHisto.second.second;
407 
408  canvas->cd();
409  histogram->LabelsDeflate("X");
410  histogram->Draw("hist");
411  canvas->Modified();
412  canvas->Update();
413  }
414 
415  for (auto& nameAndCanvasAndHisto : m_hRetentionPerUnit) {
416  auto* canvas = nameAndCanvasAndHisto.second.first;
417  auto* histogram = nameAndCanvasAndHisto.second.second;
418 
419  canvas->cd();
420  histogram->Draw("hist");
421  canvas->Modified();
422  canvas->Update();
423  }
424 }
425 
426 void DQMHistAnalysisHLTModule::terminate()
427 {
428 #ifdef _BELLE2_EPICS
429  if (not m_pvPrefix.empty()) {
430  SEVCHK(ca_clear_channel(m_epicschid), "ca_clear_channel failure");
431  SEVCHK(ca_pend_io(5.0), "ca_pend_io failure");
432  }
433 #endif
434 }
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
Abstract base class for different kinds of events.