Belle II Software development
DQMHistAnalysisSVDEfficiency.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// File : DQMHistAnalysisSVDEfficiency.cc
10// Description : module for DQM histogram analysis of SVD sensors efficiencies
11//-
12
13
14#include <dqm/analysis/modules/DQMHistAnalysisSVDEfficiency.h>
15#include <vxd/geometry/GeoCache.h>
16
17#include <TROOT.h>
18#include <TStyle.h>
19#include <TString.h>
20#include <TMath.h>
21
22using namespace std;
23using namespace Belle2;
24
25//-----------------------------------------------------------------
26// Register the Module
27//-----------------------------------------------------------------
28REG_MODULE(DQMHistAnalysisSVDEfficiency);
29
30//-----------------------------------------------------------------
31// Implementation
32//-----------------------------------------------------------------
33
36 m_effUstatus(good),
37 m_effVstatus(good)
38{
39 //Parameter definition
40 B2DEBUG(10, "DQMHistAnalysisSVDEfficiency: Constructor done.");
41
42 setDescription("DQM Analysis Module that computes the average SVD sensor efficiency.");
43
44 addParam("effLevel_Error", m_effError, "Efficiency error (%) level (red)", double(0.9));
45 addParam("effLevel_Warning", m_effWarning, "Efficiency WARNING (%) level (orange)", double(0.94));
46 addParam("statThreshold", m_statThreshold, "minimal number of tracks per sensor to set green/red alert", double(100));
47 addParam("samples3", m_3Samples, "if True 3 samples histograms analysis is performed", bool(false));
48 addParam("PVPrefix", m_pvPrefix, "PV Prefix", std::string("SVD:"));
49}
50
52{
53
54}
55
57{
58 B2DEBUG(10, "DQMHistAnalysisSVDEfficiency: initialize");
59
60
62
63 //collect the list of all SVD Modules in the geometry here
64 std::vector<VxdID> sensors = geo.getListOfSensors();
65 for (VxdID& aVxdID : sensors) {
66 VXD::SensorInfoBase info = geo.getSensorInfo(aVxdID);
67 // B2INFO("VXD " << aVxdID);
68 if (info.getType() != VXD::SensorInfoBase::SVD) continue;
69 m_SVDModules.push_back(aVxdID); // reorder, sort would be better
70 }
71 std::sort(m_SVDModules.begin(), m_SVDModules.end()); // back to natural order
72
73
74 gROOT->cd();
75 m_cEfficiencyU = new TCanvas("SVDAnalysis/c_SVDEfficiencyU");
76 m_cEfficiencyV = new TCanvas("SVDAnalysis/c_SVDEfficiencyV");
77 m_cEfficiencyErrU = new TCanvas("SVDAnalysis/c_SVDEfficiencyErrU");
78 m_cEfficiencyErrV = new TCanvas("SVDAnalysis/c_SVDEfficiencyErrV");
79
80 m_cEfficiencyRPhiViewU = new TCanvas("SVDAnalysis/c_SVDEfficiencyRPhiViewU", "", 800, 800);
81 m_cEfficiencyRPhiViewV = new TCanvas("SVDAnalysis/c_SVDEfficiencyRPhiViewV", "", 800, 800);
82 m_cEfficiencyErrRPhiViewU = new TCanvas("SVDAnalysis/c_SVDEfficiencyErrRPhiViewU", "", 800, 800);
83 m_cEfficiencyErrRPhiViewV = new TCanvas("SVDAnalysis/c_SVDEfficiencyErrRPhiViewV", "", 800, 800);
84
85 TString hName = getHistoNameFromCanvas(m_cEfficiencyU->GetName(), "@view");
86 m_hEfficiency = new SVDSummaryPlots(hName.Data(), "Summary of SVD efficiencies (%), @view/@side Side");
88 if (m_setColzRange) {
91 }
92 hName = getHistoNameFromCanvas(m_cEfficiencyErrU->GetName(), "@view");
93 m_hEfficiencyErr = new SVDSummaryPlots(hName.Data(), "Summary of SVD efficiencies errors (%), @view/@side Side");
95
96 if (m_3Samples) {
97 m_cEfficiencyU3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiency3SamplesU");
98 m_cEfficiencyV3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiency3SamplesV");
99 m_cEfficiencyErrU3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiencyErr3SamplesU");
100 m_cEfficiencyErrV3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiencyErr3SamplesV");
101
102 m_cEfficiencyRPhiViewU3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiencyRPhiView3SamplesU", "", 800, 800);
103 m_cEfficiencyRPhiViewV3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiencyRPhiView3SamplesV", "", 800, 800);
104 m_cEfficiencyErrRPhiViewU3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiencyErrRPhiView3SamplesU", "", 800, 800);
105 m_cEfficiencyErrRPhiViewV3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiencyErrRPhiView3SamplesV", "", 800, 800);
106
107 hName = getHistoNameFromCanvas(m_cEfficiencyU3Samples->GetName(), "@view");
108 m_hEfficiency3Samples = new SVDSummaryPlots(hName.Data(), "Summary of SVD efficiencies (%), @view/@side Side for 3 samples");
110 if (m_setColzRange) {
113 }
114 hName = getHistoNameFromCanvas(m_cEfficiencyErrU3Samples->GetName(), "@view");
115 m_hEfficiencyErr3Samples = new SVDSummaryPlots(hName.Data(),
116 "Summary of SVD efficiencies errors (%), @view/@side Side for 3 samples");
118 }
119
120 //register limits for EPICS
121 registerEpicsPV(m_pvPrefix + "efficiencyLimits", "effLimits");
122
123 //find nEvents testing if histograms are present
124 TH1* hnEvnts = findHist("SVDExpReco/SVDDQM_nEvents");
125 if (hnEvnts == NULL) {
126 B2INFO("no events, nothing to do here");
127 return;
128 }
129}
130
132{
133 B2DEBUG(10, "DQMHistAnalysisSVDEfficiency: beginRun called.");
134
135 if (m_cEfficiencyU)
136 m_cEfficiencyU->Clear();
137 if (m_cEfficiencyV)
138 m_cEfficiencyV->Clear();
140 m_cEfficiencyErrU->Clear();
142 m_cEfficiencyErrV->Clear();
143
145 m_cEfficiencyRPhiViewU->Clear();
147 m_cEfficiencyRPhiViewV->Clear();
152
153 if (m_3Samples) {
155 m_cEfficiencyU3Samples->Clear();
157 m_cEfficiencyV3Samples->Clear();
162
171 }
172
173 //Retrieve limits from EPICS
174 double effErrorLo = 0.;
175 double effWarnLo = 0.;
176
177 requestLimitsFromEpicsPVs("effLimits", effErrorLo, effWarnLo, m_effWarning, m_effError);
178
179 B2DEBUG(10, " SVD efficiency thresholds taken from EPICS configuration file:");
180 B2DEBUG(10, " EFFICIENCY: normal > " << m_effWarning << " > warning > " << m_effError << " > error with minimum statistics of " <<
182
183 //build the legend
184 m_legProblem->Clear();
185 m_legProblem->AddText("ERROR!");
186 m_legProblem->AddText("at least one sensor with:");
187 m_legProblem->AddText(Form("efficiency < %1.0f%%", m_effError * 100));
188
189 m_legWarning->Clear();
190 m_legWarning->AddText("WARNING!");
191 m_legWarning->AddText("at least one sensor with:");
192 m_legWarning->AddText(Form("%1.0f%% < efficiency < %1.0f%%", m_effError * 100, m_effWarning * 100));
193
194 m_legNormal->Clear();
195 m_legNormal->AddText("EFFICIENCY WITHIN LIMITS");
196 m_legNormal->AddText(Form("efficiency > %1.0f%%", m_effWarning * 100));
197
198 m_legLowStat->Clear();
199 m_legLowStat->AddText("Not enough statistics,");
200 m_legLowStat->AddText("check again in a few minutes");
201
202 m_legEmpty->Clear();
203 m_legEmpty->AddText("Track/clusters plots are emtpy");
204
207}
208
210{
211 B2DEBUG(10, "DQMHistAnalysisSVDEfficiency: event called.");
212
213 //find nEvents
214 TH1* hnEvnts = findHist("SVDExpReco/SVDDQM_nEvents", true);
215 if (hnEvnts == NULL) {
216 B2INFO("no events, nothing to do here");
217 return;
218 } else {
219 B2DEBUG(10, "SVDExpReco/SVDDQM_nEvents found");
220 }
221
222 TString tmp = hnEvnts->GetTitle();
223 Int_t pos = tmp.Last('~');
224 if (pos == -1) pos = 0;
225
226 TString runID = tmp(pos, tmp.Length() - pos);
227 B2INFO("DQMHistAnalysisSVDEfficiencyModule::runID = " << runID);
228
229 gStyle->SetOptStat(0);
230 gStyle->SetPaintTextFormat("2.1f");
231
232 // do it by nhand, the interface of the SVDSummaryPlots does not allow to change the title after cstr
233 if (m_hEfficiency) {
235 m_hEfficiency->setRunID(runID);
236 }
237
238 if (m_hEfficiencyErr) {
241 }
242
243 if (m_3Samples) {
247 }
248
252 }
253 }
254
255 Float_t effU = -1;
256 Float_t effV = -1;
257 Float_t effMinU = 9999;
258 Float_t effMinV = 9999;
259 Float_t erreffU = -1;
260 Float_t erreffV = -1;
261
262 // Efficiency for the U and V sides
263 TH2F* found_tracksU = (TH2F*)findHist("SVDEfficiency/TrackHitsU");
264 TH2F* matched_clusU = (TH2F*)findHist("SVDEfficiency/MatchedHitsU");
265
266 TH2F* found_tracksV = (TH2F*)findHist("SVDEfficiency/TrackHitsV");
267 TH2F* matched_clusV = (TH2F*)findHist("SVDEfficiency/MatchedHitsV");
268
269 if (matched_clusU != NULL && found_tracksU != NULL && matched_clusV != NULL && found_tracksV != NULL) {
270 B2DEBUG(10, "Before loop on sensors, size :" << m_SVDModules.size());
273 for (unsigned int i = 0; i < m_SVDModules.size(); i++) {
274 B2DEBUG(10, "module " << i << "," << m_SVDModules[i]);
275 int bin = found_tracksU->FindBin(m_SVDModules[i].getLadderNumber(), findBinY(m_SVDModules[i].getLayerNumber(),
276 m_SVDModules[i].getSensorNumber()));
277 // U-side
278 float numU = matched_clusU->GetBinContent(bin);
279 float denU = found_tracksU->GetBinContent(bin);
280 if (denU > 0) {
281 effU = numU / denU;
282 erreffU = std::sqrt(effU * (1 - effU) / denU);
283 }
284 if (effU < effMinU) effMinU = effU;
285 m_hEfficiency->fill(m_SVDModules[i], 1, effU * 100);
286 m_hEfficiencyErr->fill(m_SVDModules[i], 1, erreffU * 100);
287 B2DEBUG(10, "effU = " << numU << "/" << denU << " = " << effU);
288
289 // V-side
290 float numV = matched_clusV->GetBinContent(bin);
291 float denV = found_tracksV->GetBinContent(bin);
292 if (denV > 0) {
293 effV = numV / denV;
294 erreffV = std::sqrt(effV * (1 - effV) / denV);
295 }
296 if (effV < effMinV) effMinV = effV;
297 m_hEfficiency->fill(m_SVDModules[i], 0, effV * 100);
298 m_hEfficiencyErr->fill(m_SVDModules[i], 0, erreffV * 100);
299 B2DEBUG(10, "effV = " << numV << "/" << denV << " = " << effV);
300
301 setEffStatus(denU, effU, true);
302 setEffStatus(denV, effV, false);
303
304 B2DEBUG(10, "Status U-side is " << m_effUstatus);
305 B2DEBUG(10, "Status V-side is " << m_effVstatus);
306 }
307 } else {
308 if (matched_clusU == NULL || found_tracksU == NULL) {
309 B2INFO("Histograms needed for U-side Efficiency computation are not found");
310 setEffStatus(-1, -1, true);
311 }
312 if (matched_clusV == NULL || found_tracksV == NULL) {
313 B2INFO("Histograms needed for V-side Efficiency computation are not found");
314 setEffStatus(-1, -1, false);
315 }
316 }
317
318 // update summary for U side
319 m_valueMinimum = effMinU;
321
322 // update summary for V side
323 m_valueMinimum = effMinV;
325
326 // update error summary for U side
328
329 // update error summary for V side
331
332 if (m_3Samples) {
333 effMinU = 9999;
334 effMinV = 9999;
340
341 // Efficiency for the U and V-side - 3 samples
342 TH2F* found3_tracksU = (TH2F*)findHist("SVDEfficiency/TrackHits3U");
343 TH2F* matched3_clusU = (TH2F*)findHist("SVDEfficiency/MatchedHits3U");
344
345 TH2F* found3_tracksV = (TH2F*)findHist("SVDEfficiency/TrackHits3V");
346 TH2F* matched3_clusV = (TH2F*)findHist("SVDEfficiency/MatchedHits3V");
347
348 if (matched3_clusU != NULL && found3_tracksU != NULL && matched3_clusV != NULL && found3_tracksV != NULL) {
349 B2DEBUG(10, "Before loop on sensors, size :" << m_SVDModules.size());
352 for (unsigned int i = 0; i < m_SVDModules.size(); i++) {
353 B2DEBUG(10, "module " << i << "," << m_SVDModules[i]);
354 int bin = found3_tracksU->FindBin(m_SVDModules[i].getLadderNumber(), findBinY(m_SVDModules[i].getLayerNumber(),
355 m_SVDModules[i].getSensorNumber()));
356 // U-side
357 float numU = matched3_clusU->GetBinContent(bin);
358 float denU = found3_tracksU->GetBinContent(bin);
359 if (denU > 0) {
360 effU = numU / denU;
361 erreffU = std::sqrt(effU * (1 - effU) / denU);
362 }
363 if (effU < effMinU) effMinU = effU;
364 m_hEfficiency3Samples->fill(m_SVDModules[i], 1, effU * 100);
365 m_hEfficiencyErr3Samples->fill(m_SVDModules[i], 1, erreffU * 100);
366 B2DEBUG(10, "effU = " << numU << "/" << denU << " = " << effU);
367
368 // V-side
369 float numV = matched3_clusV->GetBinContent(bin);
370 float denV = found3_tracksV->GetBinContent(bin);
371 if (denV > 0) {
372 effV = numV / denV;
373 erreffV = std::sqrt(effV * (1 - effV) / denV);
374 }
375 if (effV < effMinV) effMinV = effV;
376 m_hEfficiency3Samples->fill(m_SVDModules[i], 0, effV * 100);
377 m_hEfficiencyErr3Samples->fill(m_SVDModules[i], 0, erreffV * 100);
378 B2DEBUG(10, "effV = " << numV << "/" << denV << " = " << effV);
379
380 setEffStatus(denU, effU, true);
381 setEffStatus(denV, effV, false);
382
383 B2DEBUG(10, "Status U-side is " << m_effUstatus);
384 B2DEBUG(10, "Status V-side is " << m_effVstatus);
385 }
386 } else {
387 if (matched3_clusU == NULL || found3_tracksU == NULL) {
388 B2INFO("Histograms needed for Efficiency computation are not found");
389 setEffStatus(-1, -1, true);
390 }
391 if (matched3_clusV == NULL || found3_tracksV == NULL) {
392 B2INFO("Histograms needed for Efficiency computation are not found");
393 setEffStatus(-1, -1, false);
394 }
395 }
396
397 // update summary for U side for 3 samples
398 m_valueMinimum = effMinU;
400
401 // update summary for V side for 3 samples
402 m_valueMinimum = effMinV;
404
405 // update error summary for U side for 3 samples
407
408 // update error summary for V side for 3 samples
410 }
411}
412
414{
415 B2DEBUG(10, "DQMHistAnalysisSVDEfficiency: endRun called");
416}
417
419{
420 B2DEBUG(10, "DQMHistAnalysisSVDEfficiency: terminate called");
421
422 delete m_hEfficiency;
423 delete m_cEfficiencyU;
424 delete m_cEfficiencyV;
425 delete m_hEfficiencyErr;
426 delete m_cEfficiencyErrU;
427 delete m_cEfficiencyErrV;
428
433
434 for (int i = 0; i < (int)m_laddersText.size(); i++) delete m_laddersText[i];
435 for (int i = 0; i < (int)m_sensorsText.size(); i++) delete m_sensorsText[i];
436
437 delete m_ly;
438 delete m_lx;
439 delete m_arrowx;
440 delete m_arrowy;
441
442 if (m_3Samples) {
449
454 }
455}
456
457// return y coordinate in TH2F histogram for specified sensor
458Int_t DQMHistAnalysisSVDEfficiencyModule::findBinY(Int_t layer, Int_t sensor)
459{
460 if (layer == 3)
461 return sensor; //2 -> 1,2
462 if (layer == 4)
463 return 2 + 1 + sensor; //6 -> 4,5,6
464 if (layer == 5)
465 return 6 + 1 + sensor; // 11 -> 8, 9, 10, 11
466 if (layer == 6)
467 return 11 + 1 + sensor; // 17 -> 13, 14, 15, 16, 17
468 else
469 return -1;
470}
471
472
473void DQMHistAnalysisSVDEfficiencyModule::setEffStatus(float den, float eff, bool isU)
474{
475 svdStatus* efficiencyStatus;
476
477 if (isU)
478 efficiencyStatus = &m_effUstatus;
479 else
480 efficiencyStatus = &m_effVstatus;
481
482 if (den < 0) {
483 *efficiencyStatus = std::max(noStat, *efficiencyStatus);
484 } else if (den < m_statThreshold) {
485 *efficiencyStatus = std::max(lowStat, *efficiencyStatus);
486 } else if (eff > m_effWarning) {
487 *efficiencyStatus = std::max(good, *efficiencyStatus);
488 } else if ((eff <= m_effWarning) && (eff > m_effError)) {
489 *efficiencyStatus = std::max(warning, *efficiencyStatus);
490 } else if ((eff <= m_effError)) {
491 *efficiencyStatus = std::max(error, *efficiencyStatus);
492 }
493}
494
static TH1 * findHist(const std::string &histname, bool onlyIfUpdated=false)
Get histogram from list (no other search).
int registerEpicsPV(std::string pvname, std::string keyname="")
EPICS related Functions.
bool requestLimitsFromEpicsPVs(chid id, double &lowerAlarm, double &lowerWarn, double &upperWarn, double &upperAlarm)
Get Alarm Limits from EPICS PV.
TCanvas * m_cEfficiencyErrRPhiViewU
efficiency U error plot canvas
TCanvas * m_cEfficiencyErrRPhiViewV3Samples
efficiency V error plot canvas for 3 samples
SVDSummaryPlots * m_hEfficiency3Samples
efficiency histo for 3 samples
TCanvas * m_cEfficiencyErrV3Samples
efficiency V error plot canvas for 3 samples
svdStatus m_effUstatus
number representing the status of the efficiency U side
TCanvas * m_cEfficiencyErrRPhiViewV
efficiency V error plot canvas
double m_statThreshold
minimal number of tracks per sensor to set green or red frame
TCanvas * m_cEfficiencyErrU
efficiency U error plot canvas
Int_t findBinY(Int_t layer, Int_t sensor)
find Y bin corresponding to sensor, efficiency plot
TCanvas * m_cEfficiencyRPhiViewV3Samples
efficiency V plot canvas for 3 samples
std::vector< VxdID > m_SVDModules
IDs of all SVD Modules to iterate over.
svdStatus m_effVstatus
number representing the status of the efficiency V side
SVDSummaryPlots * m_hEfficiencyErr3Samples
efficiency error histo for 3 samples
std::string m_pvPrefix
string prefix for EPICS PVs
double m_effWarning
warning level of the efficiency
double m_effError
error level of the efficiency
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.
bool m_3Samples
if true enable 3 samples histograms analysis
TCanvas * m_cEfficiencyU3Samples
efficiency U plot canvas for 3 samples
void endRun() override final
This method is called if the current run ends.
TCanvas * m_cEfficiencyErrU3Samples
efficiency U error plot canvas for 3 samples
void setEffStatus(float den, float eff, bool isU=false)
set efficiency status
void beginRun() override final
Called when entering a new run.
TCanvas * m_cEfficiencyRPhiViewU
efficiency U plot canvas
TCanvas * m_cEfficiencyV3Samples
efficiency V plot canvas for 3 samples
TCanvas * m_cEfficiencyErrV
efficiency V error plot canvas
TCanvas * m_cEfficiencyRPhiViewV
efficiency V plot canvas
TCanvas * m_cEfficiencyErrRPhiViewU3Samples
efficiency U error plot canvas for 3 samples
SVDSummaryPlots * m_hEfficiencyErr
efficiency error histo
TCanvas * m_cEfficiencyRPhiViewU3Samples
efficiency U plot canvas for 3 samples
Class definition for common method.
int m_colzMaximum
Maximum of the histogram.
TString getHistoNameFromCanvas(TString cName, TString view="", TString cPrefix="c_", TString hPrefix="")
get histogram name from Canvas name
TPaveText * m_legEmpty
plot legend, empty
int m_colzMinimum
Minimum of the histogram.
TPaveText * m_legLowStat
plot legend, low stats
TPaveText * m_legWarning
plot legend, warning
TArrow * m_arrowx
x-axis direction
std::vector< TText * > m_sensorsText
list of sensors to write on the cancas
float m_valueMinimum
Minimum value of parameter
TPaveText * m_legNormal
plot legend, normal
TArrow * m_arrowy
y-axis direction
std::vector< TText * > m_laddersText
list of ladders to write on the canvas
TPaveText * m_legProblem
plot legend, problem
void updateErrCanvases(SVDSummaryPlots *histo, TCanvas *canvas, TCanvas *canvasRPhi, bool isU)
update error canvases
void updateCanvases(SVDSummaryPlots *histo, TCanvas *canvas, TCanvas *canvasRPhi, svdStatus status, bool isU, bool online=false)
update canvases
bool m_setColzRange
set the range of the histogram in colz
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
class to summarize SVD quantities per sensor and side
void setStats(bool stats=true)
set histograms stat
void fill(int layer, int ladder, int sensor, int view, float value)
fill the histogram for
TH2F * getHistogram(int view)
get a reference to the histogram for
void setMinimum(Int_t value=0)
set histogram minimum
void setRunID(const TString &runID)
set run ids in title
void reset()
Reset histograms.
void setMaximum(Int_t value=0)
set histogram maximum
Class to facilitate easy access to sensor information of the VXD like coordinate transformations or p...
Definition: GeoCache.h:39
const std::vector< VxdID > getListOfSensors() const
Get list of all sensors.
Definition: GeoCache.cc:59
const SensorInfoBase & getSensorInfo(Belle2::VxdID id) const
Return a reference to the SensorInfo of a given SensorID.
Definition: GeoCache.cc:67
static GeoCache & getInstance()
Return a reference to the singleton instance.
Definition: GeoCache.cc:214
Base class to provide Sensor Information for PXD and SVD.
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33
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.