Belle II Software  release-05-02-19
DQMHistAnalysisHLTModule.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2019 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Nils Braun *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 #include <dqm/analysis/modules/DQMHistAnalysisHLTModule.h>
11 #include <framework/core/ModuleParam.templateDetails.h>
12 #include <TROOT.h>
13 
14 #include <hlt/softwaretrigger/modules/dqm/SoftwareTriggerHLTDQMModule.h>
15 
16 using namespace std;
17 using namespace Belle2;
18 
19 namespace {
20  bool hasValue(const std::string& name, TH1* histogram)
21  {
22  return histogram->GetXaxis()->FindFixBin(name.c_str()) != -1;
23  }
24 
25  double getValue(const std::string& name, TH1* histogram)
26  {
27  if (not hasValue(name, histogram)) {
28  B2ERROR("This histogram does not have this value! (fallback value = -1)"
29  << LogVar("histogram", histogram->GetName())
30  << LogVar("value", name));
31  return -1;
32  }
33  auto binNumber = histogram->GetXaxis()->FindFixBin(name.c_str());
34  return histogram->GetBinContent(binNumber);
35  }
36 }
37 
38 REG_MODULE(DQMHistAnalysisHLT)
39 
40 DQMHistAnalysisHLTModule::DQMHistAnalysisHLTModule()
41 {
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  SoftwareTrigger::HLTUnit::max_hlt_units + 1, 0,
85  SoftwareTrigger::HLTUnit::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  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  if (!ca_current_context()) SEVCHK(ca_context_create(ca_disable_preemptive_callback), "ca_context_create");
253  SEVCHK(ca_get(DBR_DOUBLE, m_epicschid, (void*)&instLuminosity), "ca_get failure");
254  SEVCHK(ca_pend_io(5.0), "ca_pend_io failure");
255  } else {
256  instLuminosity = 0;
257  }
258 #endif
259 
260  m_hEfficiencyTotal.second->Fill("total_result", numberOfAcceptedHLTEvents / numberOfAllEvents);
261  if (instLuminosity != 0) {
262  m_hCrossSection.second->Fill("total_result", numberOfAcceptedHLTEvents / numberOfAllEvents * instLuminosity);
263  }
264  m_hRatios.second->Fill("total_result", numberOfAcceptedHLTEvents / numberOfBhabhaEvents);
265 
266  for (const auto& columnMapping : m_columnMapping) {
267  const auto& from = columnMapping.first;
268  const auto& to = columnMapping.second;
269 
270  double value = 0;
271  if (hasValue(from, filterHistogram)) {
272  value = getValue(from, filterHistogram);
273  } else if (hasValue(from, skimHistogram)) {
274  value = getValue(from, skimHistogram);
275  } else {
276  B2ERROR("Can not find value " << from << ". Will not use it!");
277  continue;
278  }
279 
280  m_hEfficiency.second->Fill(to.c_str(), value / numberOfAcceptedHLTEvents);
281  m_hEfficiencyTotal.second->Fill(to.c_str(), value / numberOfAllEvents);
282  if (instLuminosity != 0) {
283  m_hCrossSection.second->Fill(to.c_str(), value / numberOfAllEvents * instLuminosity);
284  }
285  m_hRatios.second->Fill(to.c_str(), value / numberOfBhabhaEvents);
286  }
287 
288  for (const std::string& l1Name : m_l1Histograms) {
289  auto* histogram = m_hl1Ratios.at(l1Name).second;
290  histogram->Reset();
291 
292  auto* l1Histogram = findHist("softwaretrigger/" + l1Name);
293  auto* l1TotalResultHistogram = findHist("softwaretrigger/l1_total_result");
294 
295  if (not l1Histogram or not l1TotalResultHistogram) {
296  B2ERROR("Can not find L1 histograms from softwaretrigger!");
297  continue;
298  }
299 
300  for (const auto& columnMapping : m_columnMapping) {
301  const auto& from = columnMapping.first;
302  const auto& to = columnMapping.second;
303 
304  if (not hasValue(from, l1Histogram)) {
305  B2ERROR("Can not find label " << from << " in l1 histogram " << l1Name);
306  continue;
307  }
308 
309  if (not hasValue(l1Name, l1TotalResultHistogram)) {
310  B2ERROR("Can not find label " << l1Name << " in l1 total result histogram");
311  continue;
312  }
313 
314  const double hltValueInL1Bin = getValue(from, l1Histogram);
315  const double l1TotalResult = getValue(l1Name, l1TotalResultHistogram);
316 
317  histogram->Fill(to.c_str(), hltValueInL1Bin / l1TotalResult);
318  }
319 
320  // and add a total result bin
321  const auto from = "hlt_result";
322  const auto to = "hlt_result";
323 
324  if (not hasValue(from, l1Histogram)) {
325  B2ERROR("Can not find label " << from << " in l1 histogram " << l1Name);
326  continue;
327  }
328 
329  if (not hasValue(l1Name, l1TotalResultHistogram)) {
330  B2ERROR("Can not find label " << l1Name << " in l1 total result histogram");
331  continue;
332  }
333 
334  const double hltValueInL1Bin = getValue(from, l1Histogram);
335  const double l1TotalResult = getValue(l1Name, l1TotalResultHistogram);
336 
337  histogram->Fill(to, hltValueInL1Bin / l1TotalResult);
338  }
339 
340  for (const std::string& filterLine : m_retentionPerUnit) {
341  auto* histogram = m_hRetentionPerUnit.at(filterLine).second;
342  histogram->Reset();
343 
344  auto* filterLineHistogram = findHist("softwaretrigger/" + filterLine + "_per_unit");
345 
346  if (not filterLineHistogram) {
347  B2ERROR("Can not find " << filterLineHistogram << "_per_event histograms from softwaretrigger!");
348  continue;
349  }
350 
351  for (unsigned int i = 1; i <= SoftwareTrigger::HLTUnit::max_hlt_units + 1; i++) {
352  double totalUnitValue = hltUnitNumberHistogram->GetBinContent(i);
353  if (totalUnitValue == 0) {
354  histogram->Fill(i, 0);
355  } else {
356  double filterLineUnitValue = filterLineHistogram->GetBinContent(i);
357  histogram->SetBinContent(i, filterLineUnitValue / totalUnitValue);
358  }
359  }
360  }
361 
362  m_hMeanTime.second = (TH1F*) meanTimeHistogram->Clone("MeanTime");
363  m_hMeanTime.second->Scale(1 / numberOfProcesses);
364 
365  m_hMeanMemory.second = (TH1F*) meanMemoryHistogram->Clone("MeanMemoryChange");
366  m_hMeanMemory.second->Scale(1 / numberOfProcesses);
367 
368  m_hErrorFlagFraction.second = (TH1D*) errorFlagHistogram->Clone("ErrorFlagFraction");
369  m_hErrorFlagFraction.second->Scale(1 / numberOfAllEvents);
370  m_hErrorFlagFraction.second->SetTitle("Fraction of events with error flags");
371 
372  m_hFilteredFractionPerUnit.second = (TH1D*) hltUnitNumberHistogram_filtered->Clone("FilteredFractionPerUnit");
373  m_hFilteredFractionPerUnit.second->Divide(hltUnitNumberHistogram_filtered, hltUnitNumberHistogram);
374  m_hFilteredFractionPerUnit.second->SetTitle("Fraction of events filtered per unit");
375 
376  m_hMeanBudgetTimePerUnit.second = (TH1F*) fullTimeMeanPerUnitHistogram->Clone("MeanBudgetTimePerUnit");
377  m_hMeanBudgetTimePerUnit.second->Divide(fullTimeMeanPerUnitHistogram, processesPerUnitHistogram);
378 
379  m_hMeanProcessingTimePerUnit.second = (TH1F*) processingTimeMeanPerUnitHistogram->Clone("MeanProcessingTimePerUnit");
380  m_hMeanProcessingTimePerUnit.second->Divide(processingTimeMeanPerUnitHistogram, processesPerUnitHistogram);
381 
382  for (auto& canvasAndHisto : {m_hEfficiencyTotal, m_hEfficiency, m_hCrossSection, m_hRatios, m_hMeanTime, m_hMeanBudgetTimePerUnit, m_hMeanProcessingTimePerUnit, m_hMeanMemory}) {
383  auto* canvas = canvasAndHisto.first;
384  auto* histogram = canvasAndHisto.second;
385 
386  canvas->cd();
387  histogram->LabelsDeflate("X");
388  histogram->Draw("hist");
389  canvas->Modified();
390  canvas->Update();
391  }
392 
393  for (auto& canvasAndHisto : {m_hErrorFlagFraction, m_hFilteredFractionPerUnit}) {
394  auto* canvas = canvasAndHisto.first;
395  auto* histogram = canvasAndHisto.second;
396 
397  canvas->cd();
398  histogram->LabelsDeflate("X");
399  histogram->Draw("hist");
400  histogram->SetStats(false);
401  canvas->Modified();
402  canvas->Update();
403  }
404 
405  for (auto& nameAndCanvasAndHisto : m_hl1Ratios) {
406  auto* canvas = nameAndCanvasAndHisto.second.first;
407  auto* histogram = nameAndCanvasAndHisto.second.second;
408 
409  canvas->cd();
410  histogram->LabelsDeflate("X");
411  histogram->Draw("hist");
412  canvas->Modified();
413  canvas->Update();
414  }
415 
416  for (auto& nameAndCanvasAndHisto : m_hRetentionPerUnit) {
417  auto* canvas = nameAndCanvasAndHisto.second.first;
418  auto* histogram = nameAndCanvasAndHisto.second.second;
419 
420  canvas->cd();
421  histogram->Draw("hist");
422  canvas->Modified();
423  canvas->Update();
424  }
425 }
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
LogVar
Class to store variables with their name which were sent to the logging service.
Definition: LogVariableStream.h:24