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 m_hEfficiency = new SVDSummaryPlots("SVDEfficiency@view", "Summary of SVD efficiencies (%), @view/@side Side");
87 if (m_setColzRange) {
90 }
91 m_hEfficiencyErr = new SVDSummaryPlots("SVDEfficiencyErr@view", "Summary of SVD efficiencies errors (%), @view/@side Side");
93
94 if (m_3Samples) {
95 m_cEfficiencyU3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiencyU3Samples");
96 m_cEfficiencyV3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiencyV3Samples");
97 m_cEfficiencyErrU3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiencyErrU3Samples");
98 m_cEfficiencyErrV3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiencyErrV3Samples");
99
100 m_cEfficiencyRPhiViewU3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiencyRPhiViewU3Samples", "", 800, 800);
101 m_cEfficiencyRPhiViewV3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiencyRPhiViewV3Samples", "", 800, 800);
102 m_cEfficiencyErrRPhiViewU3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiencyErrRPhiViewU3Samples", "", 800, 800);
103 m_cEfficiencyErrRPhiViewV3Samples = new TCanvas("SVDAnalysis/c_SVDEfficiencyErrRPhiViewV3Samples", "", 800, 800);
104
105 m_hEfficiency3Samples = new SVDSummaryPlots("SVD3Efficiency@view",
106 "Summary of SVD efficiencies (%), @view/@side Side for 3 samples");
108 if (m_setColzRange) {
111 }
112 m_hEfficiencyErr3Samples = new SVDSummaryPlots("SVD3EfficiencyErr@view",
113 "Summary of SVD efficiencies errors (%), @view/@side Side for 3 samples");
115 }
116
117 //register limits for EPICS
118 registerEpicsPV(m_pvPrefix + "efficiencyLimits", "effLimits");
119
120 //find nEvents testing if histograms are present
121 TH1* hnEvnts = findHist("SVDExpReco/SVDDQM_nEvents");
122 if (hnEvnts == NULL) {
123 B2INFO("no events, nothing to do here");
124 return;
125 }
126}
127
129{
130 B2DEBUG(10, "DQMHistAnalysisSVDEfficiency: beginRun called.");
131
132 if (m_cEfficiencyU)
133 m_cEfficiencyU->Clear();
134 if (m_cEfficiencyV)
135 m_cEfficiencyV->Clear();
137 m_cEfficiencyErrU->Clear();
139 m_cEfficiencyErrV->Clear();
140
142 m_cEfficiencyRPhiViewU->Clear();
144 m_cEfficiencyRPhiViewV->Clear();
149
150 if (m_3Samples) {
152 m_cEfficiencyU3Samples->Clear();
154 m_cEfficiencyV3Samples->Clear();
159
168 }
169
170 //Retrieve limits from EPICS
171 double effErrorLo = 0.;
172 double effWarnLo = 0.;
173
174 requestLimitsFromEpicsPVs("effLimits", effErrorLo, effWarnLo, m_effWarning, m_effError);
175
176 B2DEBUG(10, " SVD efficiency thresholds taken from EPICS configuration file:");
177 B2DEBUG(10, " EFFICIENCY: normal > " << m_effWarning << " > warning > " << m_effError << " > error with minimum statistics of " <<
179
180 //build the legend
181 m_legProblem->Clear();
182 m_legProblem->AddText("ERROR!");
183 m_legProblem->AddText("at least one sensor with:");
184 m_legProblem->AddText(Form("efficiency < %1.0f%%", m_effError * 100));
185
186 m_legWarning->Clear();
187 m_legWarning->AddText("WARNING!");
188 m_legWarning->AddText("at least one sensor with:");
189 m_legWarning->AddText(Form("%1.0f%% < efficiency < %1.0f%%", m_effError * 100, m_effWarning * 100));
190
191 m_legNormal->Clear();
192 m_legNormal->AddText("EFFICIENCY WITHIN LIMITS");
193 m_legNormal->AddText(Form("efficiency > %1.0f%%", m_effWarning * 100));
194
195 m_legLowStat->Clear();
196 m_legLowStat->AddText("Not enough statistics,");
197 m_legLowStat->AddText("check again in a few minutes");
198
199 m_legEmpty->Clear();
200 m_legEmpty->AddText("Track/clusters plots are emtpy");
201
204}
205
207{
208 B2DEBUG(10, "DQMHistAnalysisSVDEfficiency: event called.");
209
210 //find nEvents
211 TH1* hnEvnts = findHist("SVDExpReco/SVDDQM_nEvents", true);
212 if (hnEvnts == NULL) {
213 B2INFO("no events, nothing to do here");
214 return;
215 } else {
216 B2DEBUG(10, "SVDExpReco/SVDDQM_nEvents found");
217 }
218
219 TString tmp = hnEvnts->GetTitle();
220 Int_t pos = tmp.Last('~');
221 if (pos == -1) pos = 0;
222
223 TString runID = tmp(pos, tmp.Length() - pos);
224 B2INFO("DQMHistAnalysisSVDEfficiencyModule::runID = " << runID);
225
226 gStyle->SetOptStat(0);
227 gStyle->SetPaintTextFormat("2.1f");
228
229 // do it by nhand, the interface of the SVDSummaryPlots does not allow to change the title after cstr
230 if (m_hEfficiency) {
232 m_hEfficiency->setRunID(runID);
233 }
234
235 if (m_hEfficiencyErr) {
238 }
239
240 if (m_3Samples) {
244 }
245
249 }
250 }
251
252 Float_t effU = -1;
253 Float_t effV = -1;
254 Float_t effMinU = 9999;
255 Float_t effMinV = 9999;
256 Float_t erreffU = -1;
257 Float_t erreffV = -1;
258
259 // Efficiency for the U and V sides
260 TH2F* found_tracksU = (TH2F*)findHist("SVDEfficiency/TrackHitsU");
261 TH2F* matched_clusU = (TH2F*)findHist("SVDEfficiency/MatchedHitsU");
262
263 TH2F* found_tracksV = (TH2F*)findHist("SVDEfficiency/TrackHitsV");
264 TH2F* matched_clusV = (TH2F*)findHist("SVDEfficiency/MatchedHitsV");
265
266 if (matched_clusU != NULL && found_tracksU != NULL && matched_clusV != NULL && found_tracksV != NULL) {
267 B2DEBUG(10, "Before loop on sensors, size :" << m_SVDModules.size());
270 for (unsigned int i = 0; i < m_SVDModules.size(); i++) {
271 B2DEBUG(10, "module " << i << "," << m_SVDModules[i]);
272 int bin = found_tracksU->FindBin(m_SVDModules[i].getLadderNumber(), findBinY(m_SVDModules[i].getLayerNumber(),
273 m_SVDModules[i].getSensorNumber()));
274 // U-side
275 float numU = matched_clusU->GetBinContent(bin);
276 float denU = found_tracksU->GetBinContent(bin);
277 if (denU > 0) {
278 effU = numU / denU;
279 erreffU = std::sqrt(effU * (1 - effU) / denU);
280 }
281 if (effU < effMinU) effMinU = effU;
282 m_hEfficiency->fill(m_SVDModules[i], 1, effU * 100);
283 m_hEfficiencyErr->fill(m_SVDModules[i], 1, erreffU * 100);
284 B2DEBUG(10, "effU = " << numU << "/" << denU << " = " << effU);
285
286 // V-side
287 float numV = matched_clusV->GetBinContent(bin);
288 float denV = found_tracksV->GetBinContent(bin);
289 if (denV > 0) {
290 effV = numV / denV;
291 erreffV = std::sqrt(effV * (1 - effV) / denV);
292 }
293 if (effV < effMinV) effMinV = effV;
294 m_hEfficiency->fill(m_SVDModules[i], 0, effV * 100);
295 m_hEfficiencyErr->fill(m_SVDModules[i], 0, erreffV * 100);
296 B2DEBUG(10, "effV = " << numV << "/" << denV << " = " << effV);
297
298 setEffStatus(denU, effU, true);
299 setEffStatus(denV, effV, false);
300
301 B2DEBUG(10, "Status U-side is " << m_effUstatus);
302 B2DEBUG(10, "Status V-side is " << m_effVstatus);
303 }
304 } else {
305 if (matched_clusU == NULL || found_tracksU == NULL) {
306 B2INFO("Histograms needed for U-side Efficiency computation are not found");
307 setEffStatus(-1, -1, true);
308 }
309 if (matched_clusV == NULL || found_tracksV == NULL) {
310 B2INFO("Histograms needed for V-side Efficiency computation are not found");
311 setEffStatus(-1, -1, false);
312 }
313 }
314
315 // update summary for U side
316 m_valueMinimum = effMinU;
318
319 // update summary for V side
320 m_valueMinimum = effMinV;
322
323 // update error summary for U side
325
326 // update error summary for V side
328
329 if (m_3Samples) {
330 effMinU = 9999;
331 effMinV = 9999;
337
338 // Efficiency for the U and V-side - 3 samples
339 TH2F* found3_tracksU = (TH2F*)findHist("SVDEfficiency/TrackHits3U");
340 TH2F* matched3_clusU = (TH2F*)findHist("SVDEfficiency/MatchedHits3U");
341
342 TH2F* found3_tracksV = (TH2F*)findHist("SVDEfficiency/TrackHits3V");
343 TH2F* matched3_clusV = (TH2F*)findHist("SVDEfficiency/MatchedHits3V");
344
345 if (matched3_clusU != NULL && found3_tracksU != NULL && matched3_clusV != NULL && found3_tracksV != NULL) {
346 B2DEBUG(10, "Before loop on sensors, size :" << m_SVDModules.size());
349 for (unsigned int i = 0; i < m_SVDModules.size(); i++) {
350 B2DEBUG(10, "module " << i << "," << m_SVDModules[i]);
351 int bin = found3_tracksU->FindBin(m_SVDModules[i].getLadderNumber(), findBinY(m_SVDModules[i].getLayerNumber(),
352 m_SVDModules[i].getSensorNumber()));
353 // U-side
354 float numU = matched3_clusU->GetBinContent(bin);
355 float denU = found3_tracksU->GetBinContent(bin);
356 if (denU > 0) {
357 effU = numU / denU;
358 erreffU = std::sqrt(effU * (1 - effU) / denU);
359 }
360 if (effU < effMinU) effMinU = effU;
361 m_hEfficiency3Samples->fill(m_SVDModules[i], 1, effU * 100);
362 m_hEfficiencyErr3Samples->fill(m_SVDModules[i], 1, erreffU * 100);
363 B2DEBUG(10, "effU = " << numU << "/" << denU << " = " << effU);
364
365 // V-side
366 float numV = matched3_clusV->GetBinContent(bin);
367 float denV = found3_tracksV->GetBinContent(bin);
368 if (denV > 0) {
369 effV = numV / denV;
370 erreffV = std::sqrt(effV * (1 - effV) / denV);
371 }
372 if (effV < effMinV) effMinV = effV;
373 m_hEfficiency3Samples->fill(m_SVDModules[i], 0, effV * 100);
374 m_hEfficiencyErr3Samples->fill(m_SVDModules[i], 0, erreffV * 100);
375 B2DEBUG(10, "effV = " << numV << "/" << denV << " = " << effV);
376
377 setEffStatus(denU, effU, true);
378 setEffStatus(denV, effV, false);
379
380 B2DEBUG(10, "Status U-side is " << m_effUstatus);
381 B2DEBUG(10, "Status V-side is " << m_effVstatus);
382 }
383 } else {
384 if (matched3_clusU == NULL || found3_tracksU == NULL) {
385 B2INFO("Histograms needed for Efficiency computation are not found");
386 setEffStatus(-1, -1, true);
387 }
388 if (matched3_clusV == NULL || found3_tracksV == NULL) {
389 B2INFO("Histograms needed for Efficiency computation are not found");
390 setEffStatus(-1, -1, false);
391 }
392 }
393
394 // update summary for U side for 3 samples
395 m_valueMinimum = effMinU;
397
398 // update summary for V side for 3 samples
399 m_valueMinimum = effMinV;
401
402 // update error summary for U side for 3 samples
404
405 // update error summary for V side for 3 samples
407 }
408}
409
411{
412 B2DEBUG(10, "DQMHistAnalysisSVDEfficiency: endRun called");
413}
414
416{
417 B2DEBUG(10, "DQMHistAnalysisSVDEfficiency: terminate called");
418
419 delete m_hEfficiency;
420 delete m_cEfficiencyU;
421 delete m_cEfficiencyV;
422 delete m_hEfficiencyErr;
423 delete m_cEfficiencyErrU;
424 delete m_cEfficiencyErrV;
425
430
431 for (int i = 0; i < (int)m_laddersText.size(); i++) delete m_laddersText[i];
432 for (int i = 0; i < (int)m_sensorsText.size(); i++) delete m_sensorsText[i];
433
434 delete m_ly;
435 delete m_lx;
436 delete m_arrowx;
437 delete m_arrowy;
438
439 if (m_3Samples) {
446
451 }
452}
453
454// return y coordinate in TH2F histogram for specified sensor
455Int_t DQMHistAnalysisSVDEfficiencyModule::findBinY(Int_t layer, Int_t sensor)
456{
457 if (layer == 3)
458 return sensor; //2 -> 1,2
459 if (layer == 4)
460 return 2 + 1 + sensor; //6 -> 4,5,6
461 if (layer == 5)
462 return 6 + 1 + sensor; // 11 -> 8, 9, 10, 11
463 if (layer == 6)
464 return 11 + 1 + sensor; // 17 -> 13, 14, 15, 16, 17
465 else
466 return -1;
467}
468
469
470void DQMHistAnalysisSVDEfficiencyModule::setEffStatus(float den, float eff, bool isU)
471{
472 svdStatus* efficiencyStatus;
473
474 if (isU)
475 efficiencyStatus = &m_effUstatus;
476 else
477 efficiencyStatus = &m_effVstatus;
478
479 if (den < 0) {
480 *efficiencyStatus = std::max(noStat, *efficiencyStatus);
481 } else if (den < m_statThreshold) {
482 *efficiencyStatus = std::max(lowStat, *efficiencyStatus);
483 } else if (eff > m_effWarning) {
484 *efficiencyStatus = std::max(good, *efficiencyStatus);
485 } else if ((eff <= m_effWarning) && (eff > m_effError)) {
486 *efficiencyStatus = std::max(warning, *efficiencyStatus);
487 } else if ((eff <= m_effError)) {
488 *efficiencyStatus = std::max(error, *efficiencyStatus);
489 }
490}
491
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.
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 faciliate easy access to sensor information of the VXD like coordinate transformations or pi...
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 referecne 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:560
#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.
STL namespace.