Belle II Software development
DQMHistAnalysisCDCMonObj.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// Own header.
10#include <dqm/analysis/modules/DQMHistAnalysisCDCMonObj.h>
11
12// CDC geometry
13#include <cdc/geometry/CDCGeometryPar.h>
14
15#include <TROOT.h>
16#include <TEllipse.h>
17#include <TF1.h>
18#include <TLine.h>
19#include <TStyle.h>
20
21#include <numeric>
22
23using namespace std;
24using namespace Belle2;
25
26//-----------------------------------------------------------------
27// Register module
28//-----------------------------------------------------------------
29
30REG_MODULE(DQMHistAnalysisCDCMonObj);
31
34{
35 // set module description (e.g. insert text)
36 addParam("HistDirectory", m_name_dir, "CDC Dir of DQM Histogram", std::string("CDC"));
37 addParam("HistBoardADC", m_hname_badc, "Board ADC Histogram Name", std::string("hADCBoard"));
38 addParam("HistBoardTDC", m_hname_btdc, "Board TDC Histogram Name", std::string("hTDC"));
39 addParam("HistHitsPhi", m_hname_hits, "Phi Hits Histogram Name", std::string("hHit"));
40 setDescription("Modify and analyze the data quality histograms of CDCMonObj");
42 for (int i = 0; i < 300; i++) {
43 m_hADCs[i] = nullptr;
44 m_hTDCs[i] = nullptr;
45 }
46 for (int i = 0; i < 56; i++) m_hHits[i] = nullptr;
47}
48
50{
51
53 if (!(*m_channelMapFromDB).isValid()) {
54 B2FATAL("Channel map is not valid");
55 }
56
58 if (m_cdcGeo == nullptr) {
59 B2FATAL("CDCGeometryp is not valid");
60 }
61
63
64 gStyle->SetOptStat(0);
65 gStyle->SetPalette(kViridis);
66 gStyle->SetPadTopMargin(0.1);
67 gStyle->SetPadRightMargin(0.05);
68 gStyle->SetPadBottomMargin(0.1);
69 gStyle->SetPadLeftMargin(0.15);
70
71 m_cMain = new TCanvas("cdc_main", "cdc_main", 1500, 1200);
72 m_monObj->addCanvas(m_cMain);
73
74 m_cADC = new TCanvas("cdc_adc", "cdc_adc", 2000, 10000);
75 m_monObj->addCanvas(m_cADC);
76 m_cTDC = new TCanvas("cdc_tdc", "cdc_tdc", 2000, 10000);
77 m_monObj->addCanvas(m_cTDC);
78 m_cHit = new TCanvas("cdc_hit", "cdc_hit", 1500, 6000);
79 m_monObj->addCanvas(m_cHit);
80
81 B2DEBUG(20, "DQMHistAnalysisCDCMonObj: initialized.");
82
83}
84
86{
87 for (const auto& cm : (*m_channelMapFromDB)) {
88 const int isl = cm.getISuperLayer();
89 const int il = cm.getILayer();
90 const int iw = cm.getIWire();
91 const int iBoard = cm.getBoardID();
92 const int iCh = cm.getBoardChannel();
93 const WireID wireId(isl, il, iw);
94 m_chMap.insert(std::make_pair(wireId, std::make_pair(iBoard, iCh)));
95 }
96
97
98 const CDCGeometry& geom = **m_cdcGeo;
99
100 for (const auto& sense : geom.getSenseLayers()) {
101 int i = sense.getId();
102 if (i < 0 || i > 55) {
103 B2FATAL("no such sense layer");
104 }
105 m_senseR[i] = sense.getR();
106 m_nSenseWires[i] = sense.getNWires();
107 m_offset[i] = sense.getOffset();
108 }
109
110 for (const auto& field : geom.getFieldLayers()) {
111 int i = field.getId();
112 if (i < 0 || i > 54) {
113 B2FATAL("no such sense layer");
114 }
115 m_fieldR[i + 1] = field.getR();
116 }
117 m_fieldR[56] = geom.getOuterWall(0).getRmin();
118 m_fieldR[0] = geom.getInnerWall(0).getRmax();
119
120}
121
122
124{
125 for (int ilayer = 0; ilayer < 56; ++ilayer) {
126 float dPhi = float(2 * M_PI / m_nSenseWires[ilayer]);
127 float r1 = m_fieldR[ilayer];
128 float r2 = m_fieldR[ilayer + 1];
129 for (int iwire = 0; iwire < m_nSenseWires[ilayer]; ++iwire) {
130 float phi = dPhi * (iwire + m_offset[ilayer]);
131 float phi1 = phi - dPhi * 0.5;
132 float phi2 = phi + dPhi * 0.5;
133 Double_t x_pos[] = {r1* (sin(phi)*tan(phi - phi1) + cos(phi)),
134 r2 * cos(phi1),
135 r2 * cos(phi2),
136 r1* (sin(phi)*tan(phi - phi2) + cos(phi))
137 };
138 Double_t y_pos[] = {r1* (-cos(phi)*tan(phi - phi1) + sin(phi)),
139 r2 * sin(phi1),
140 r2 * sin(phi2),
141 r1* (-cos(phi)*tan(phi - phi2) + sin(phi))
142 };
143 h->AddBin(4, x_pos, y_pos);
144 }
145 }
146}
147
148
150{
151 m_badChannels.clear();
152 for (int il = 0; il < 56; ++il) {
153 for (int iw = 0; iw < m_nSenseWires[il]; ++iw) {
154 const int y = m_hHits[il]->GetBinContent(iw + 1);
155 if (y == 0) {
156 m_badChannels.push_back(std::make_pair(il, iw));
157 }
158 }
159 }
160 B2DEBUG(20, "num bad wires " << m_badChannels.size());
161}
162
164{
165 TH1D* hist = (TH1D*)h->Clone();
166 hist->SetBinContent(1, 0.0); // Exclude 0-th bin
167 float m = hist->GetMean();
168 delete hist;
169 return m;
170}
171
173{
174 TH1D* hist = (TH1D*)h->Clone();
175 hist->SetBinContent(1, 0.0); // Exclude 0-th bin
176 if (hist->GetMean() == 0) {return 0.0;} // Avoid an error if only ADC=0 entries
177 double quantiles[1] = {0.0}; // One element to store median
178 double probSums[1] = {0.5}; // Median definition
179 hist->GetQuantiles(1, quantiles, probSums);
180 float median = quantiles[0];
181 delete hist;
182 return median;
183}
184
185std::pair<int, int> DQMHistAnalysisCDCMonObjModule::getBoardChannel(unsigned short layer, unsigned short wire)
186{
187 const WireID w(layer, wire);
188 decltype(m_chMap)::iterator it = m_chMap.find(w);
189 if (it != m_chMap.end()) {
190 return it->second;
191 } else {
192 B2ERROR("no corresponding board/channel found layer " << layer << " wire " << wire);
193 return std::make_pair(-1, -1);
194 }
195}
196
197
199{
200 B2DEBUG(20, "end run");
201
202 m_hADC = (TH2F*)findHist(m_name_dir + "/" + m_hname_badc);
203 m_hTDC = (TH2F*)findHist(m_name_dir + "/" + m_hname_btdc);
204 m_hHit = (TH2F*)findHist(m_name_dir + "/" + m_hname_hits);
205
206 if (m_hADC == nullptr) {
207 m_monObj->setVariable("comment", "No ADC histograms of CDC in file");
208 B2INFO("Histogram named m_hADC is not found.");
209 return;
210 }
211
212 TF1* fitFunc[300] = {};
213 for (int i = 0; i < 300; ++i) {
214 fitFunc[i] = new TF1(Form("f%d", i), "[0]+[6]*x+[1]*(exp([2]*(x-[3]))/(1+exp(-([4]-x)/[5])))",
215 4921 - 100, 4921 + 100);
216 fitFunc[i]->SetParLimits(6, 0, 0.1);
217 fitFunc[i]->SetParLimits(4, 4850., 5000.0);
218 fitFunc[i]->SetParLimits(5, 0, 50.0);
219 }
220
221 int neve = m_hTDC->GetEntries();
222 if (neve == 0)neve = 1;
223
224 B2DEBUG(20, "adc related");
225 int nDeadADC = -1; // bid 0 always empty
226 int nBadADC = 0;
227 TH1F* hADCMean = new TH1F("hADCMean", "ADC mean;board;adc mean", 300, 0, 300);
228 TH1F* hADC1000 = new TH1F("ADC1000", "ADC1000", 300, 0, 300);
229 TH1F* hADC0 = new TH1F("ADC0", "ADC0", 300, 0, 300);
230
231 // Collect ADC mean/median for each board
232 std::vector<float> means = {};
233 std::vector<float> medians = {};
234
235 for (int i = 0; i < 300; ++i) {
236 m_hADCs[i] = m_hADC->ProjectionY(Form("hADC%d", i), i + 1, i + 1, "");
237 m_hADCs[i]->SetTitle(Form("hADC%d", i));
238 float n = static_cast<float>(m_hADCs[i]->GetEntries());
239 if (m_hADCs[i]->Integral(0, m_hADCs[i]->GetNbinsX()) == 0) {
240 nDeadADC += 1;
241 hADC0->SetBinContent(i + 1, -0.1);
242 } else {
243 float n0 = static_cast<float>(m_hADCs[i]->GetBinContent(1));
244 if (n0 / n > 0.9) {
245 B2DEBUG(21, "bad adc bid " << i << " " << n0 << " " << n);
246 nBadADC += 1;
247 }
248 float bin1 = m_hADCs[i]->GetBinContent(1);
249 float m = getHistMean(m_hADCs[i]);
250 float md = getHistMedian(m_hADCs[i]);
251 means.push_back(m);
252 medians.push_back(md);
253 hADCMean->SetBinContent(i + 1, m);
254 hADCMean->SetBinError(i + 1, 0);
255 double overflow = m_hADCs[i]->GetBinContent(m_hADCs[i]->GetNbinsX() + 1);
256 hADC1000->SetBinContent(i + 1, overflow / (overflow + n));
257 hADC0->SetBinContent(i + 1, bin1 / (overflow + n));
259 }
260 }
261 // TDC related
262 B2DEBUG(20, "tdc related");
263 int nDeadTDC = -1; // bid 0 always empty
264 TH1F* hTDCEdge = new TH1F("hTDCEdge", "TDC edge;board;tdc edge [nsec]", 300, 0, 300);
265 TH1F* hTDCSlope = new TH1F("hTDCSlope", "TDC slope;board;tdc slope [nsec]", 300, 0, 300);
266 std::vector<float> tdcEdges = {};
267 std::vector<float> tdcSlopes = {};
268 for (int i = 0; i < 300; ++i) {
269 m_hTDCs[i] = m_hTDC->ProjectionY(Form("hTDC%d", i), i + 1, i + 1);
270 m_hTDCs[i]->SetTitle(Form("hTDC%d", i));
271 if (m_hTDCs[i]->Integral(0, m_hTDCs[i]->GetNbinsX()) == 0 || m_hTDCs[i] == nullptr) {
272 nDeadTDC += 1;
273 tdcEdges.push_back(0);
274 tdcSlopes.push_back(0);
275 } else {
276 double init_p0 = m_hTDCs[i]->GetBinContent(700 + 60);
277 fitFunc[i]->SetParameters(init_p0, 100, 0.01, 4700, 4900, 2, 0.01);
278 fitFunc[i]->SetParameter(6, 0.02);
279 fitFunc[i]->SetParLimits(0, init_p0 - 200, init_p0 + 200);
280 int TDCfitstatus = -1;
281 if (i < 28) {
282 TDCfitstatus = m_hTDCs[i]->Fit(fitFunc[i], "qM0", "", 4850, 5000);
283 } else {
284 TDCfitstatus = m_hTDCs[i]->Fit(fitFunc[i], "qM0", "", 4800, 5000);
285 }
286 float p4 = fitFunc[i]->GetParameter(4);
287 float p5 = fitFunc[i]->GetParameter(5);
288
289 if (TDCfitstatus != -1 && 4850 < p4 && p4 < 5000) {
290 hTDCEdge->SetBinContent(i + 1, p4);
291 hTDCEdge->SetBinError(i + 1, 0);
292 hTDCSlope->SetBinContent(i + 1, p5);
293 hTDCSlope->SetBinError(i + 1, 0);
294 }
295 tdcEdges.push_back(p4);
296 tdcSlopes.push_back(p5);
297 }
298
299 }
300
301 // Hit related
302 B2DEBUG(20, "hit related");
303 TH1F* hHitPerLayer = new TH1F("hHitPerLayer", "hit/Layer;layer", 56, 0, 56);
304 TH1F* hHitRatePerWire = new TH1F("hHitRatePerWire", "hit rate (kHz)/Wire;layer", 56, 0, 56);
305 int nHits = 0;
306 for (int i = 0; i < 56; ++i) {
307 int tdcwindow;
308 double tdcclock = 0.98255764; //unit: ns
309 if (i < 8) tdcwindow = 416;
310 else tdcwindow = 768;
311 m_hHits[i] = m_hHit->ProjectionY(Form("hHit%d", i), i + 1, i + 1);
312 m_hHits[i]->SetTitle(Form("hHit%d", i));
313 if (m_hHits[i]->GetEntries() > 0 && m_hHits[i] != nullptr) {
314 int nhitSumL = 0;
315 int nBins = m_nSenseWires[i];
316 for (int j = 0; j < nBins; ++j) {
317 nhitSumL += m_hHits[i]->GetBinContent(j + 1);
318 }
319 if (neve > 0) {
320 hHitPerLayer->SetBinContent(i + 1, 1.0 * nhitSumL / neve);
321 hHitRatePerWire->SetBinContent(i + 1, (1.0 * nhitSumL / neve) / (1.0 * nBins * tdcwindow * tdcclock * 1e-6));
322 } else {
323 hHitPerLayer->SetBinContent(i + 1, nhitSumL);
324 hHitRatePerWire->SetBinContent(i + 1, (1.0 * nhitSumL) / (1.0 * nBins * tdcwindow * tdcclock * 1e-6));
325 }
326 hHitPerLayer->SetBinError(i + 1, 0);
327 hHitRatePerWire->SetBinError(i + 1, 0);
328 nHits += nhitSumL;
329 }
330 }
331
332 // Bad wires related
333 B2DEBUG(20, "bad wire related");
334 hBadChannel = new TH2F("hbadch", "bad channel map;wire;layer", 400, 0, 400, 56, 0, 56);
335 for (int i = 0; i < 400; ++i) {
336 for (int j = 0; j < 56; ++j) {
337 hBadChannel->Fill(i, j, -1);
338 }
339 }
340
341 hBadChannelBC = new TH2F("hbadchBC", "bad channel map per board/channel;board;channel", 300, 0, 300, 48, 0, 48);
342 for (int i = 0; i < 300; ++i) {
343 for (int j = 0; j < 48; ++j) {
344 hBadChannelBC->Fill(i, j, -1);
345 }
346 }
347
348 h2p = new TH2Poly();
350 h2p->SetTitle("bad wires in xy view");
351 h2p->GetXaxis()->SetTitle("X [cm]");
352 h2p->GetYaxis()->SetTitle("Y [cm]");
354 for (const auto& lw : m_badChannels) {
355 const int l = lw.first;
356 const int w = lw.second;
357 B2DEBUG(21, "l " << l << " w " << w);
358 hBadChannel->Fill(w, l);
359 std::pair<int, int> bc = getBoardChannel(l, w);
360 hBadChannelBC->Fill(bc.first, bc.second);
361 float r = m_senseR[l];
362 float dPhi = static_cast<float>(2.0 * M_PI / m_nSenseWires[l]);
363 float phi = dPhi * (w + m_offset[l]);
364 float x = r * cos(phi);
365 float y = r * sin(phi);
366 h2p->Fill(x, y, 1.1);
367 }
368
369 B2DEBUG(20, "writing");
370 m_cMain->Divide(4, 3);
371
372 m_cMain->cd(1);
373 hADCMean->SetMinimum(0);
374 hADCMean->SetMaximum(300);
375 hADCMean->DrawCopy();
376
377 m_cMain->cd(2);
378 hTDCEdge->SetMinimum(4800);
379 hTDCEdge->SetMaximum(5000);
380 hTDCEdge->DrawCopy();
381
382 m_cMain->cd(3);
383 hTDCSlope->SetMinimum(0);
384 hTDCSlope->SetMaximum(50);
385 hTDCSlope->DrawCopy();
386
387 m_cMain->cd(4);
388 hBadChannel->DrawCopy("col");
389
390 m_cMain->cd(5);
391 hBadChannelBC->DrawCopy("col");
392
393 m_cMain->cd(7);
394 hADC1000->DrawCopy();
395
396 m_cMain->cd(8);
397 hADC0->DrawCopy();
398
399 m_cMain->cd(9);
400 hHitPerLayer->DrawCopy();
401
402 m_cMain->cd(10);
403 hHitRatePerWire->DrawCopy();
404
405 m_cHit->Divide(4, 14);
406 for (int i = 0; i < 56; i++) {
407 m_cHit->cd(i + 1);
408 m_hHits[i]->GetXaxis()->SetRangeUser(0, m_nSenseWires[i]);
409 m_hHits[i]->Draw("hist");
410 }
411
412 m_cADC->Divide(6, 50, 0.0002, 0.0002);
413 m_cTDC->Divide(6, 50, 0.0002, 0.0002);
414
415 for (int i = 0; i < 300; i++) {
416 m_cADC->cd(i + 1);
417 Double_t max = m_hADCs[i]->GetMaximum();
418 m_hADCs[i]->GetYaxis()->SetRangeUser(0, 3 * max);
419 m_hADCs[i]->Draw("hist");
420
421 m_cTDC->cd(i + 1);
422 m_hTDCs[i]->Draw("hist");
423 fitFunc[i]->SetLineColor(kRed);
424 fitFunc[i]->Draw("same");
425 max = m_hTDCs[i]->GetMaximum();
426 TLine* l1 = new TLine(tdcEdges[i], 0, tdcEdges[i], max * 1.05);
427 l1->SetLineColor(kRed);
428 TLine* l0 = new TLine(4910, 0, 4910, max * 1.05);
429 l0->Draw();
430 l1->Draw();
431 }
432
433 m_cMain->cd(6);
434 h2p->DrawCopy("col");
435 float superLayerR[10] = {16.3, 24.3, 35.66, 46.63, 57.55, 68.47,
436 79.39, 90.31, 101.23, 112.05
437 };
438
439 TEllipse* circs[10];
440 for (int i = 0; i < 10; ++i) {
441 circs[i] = new TEllipse(0, 0, superLayerR[i], superLayerR[i]);
442 circs[i]->SetFillStyle(4000);
443 circs[i]->SetLineStyle(kDashed);
444 circs[i]->SetLineColor(0);
445 circs[i]->Draw("same");
446 }
447
448 m_monObj->setVariable("nEvents", neve);
449 m_monObj->setVariable("nHits", nHits / neve);
450 m_monObj->setVariable("nBadWires", m_badChannels.size());
451 m_monObj->setVariable("adcMean", std::accumulate(means.begin(), means.end(), 0.0) / means.size());
452 m_monObj->setVariable("adcMeanMedianBoard", std::accumulate(medians.begin(), medians.end(), 0.0) / medians.size());
453 m_monObj->setVariable("nDeadADC", nDeadADC);
454 m_monObj->setVariable("nBadADC", nBadADC); //???? n_0/n_tot>0.9
455 m_monObj->setVariable("tdcEdge", std::accumulate(tdcEdges.begin(), tdcEdges.end(), 0.0) / (tdcEdges.size() - 1 - nDeadTDC));
456 m_monObj->setVariable("nDeadTDC", nDeadTDC);
457 m_monObj->setVariable("tdcSlope", std::accumulate(tdcSlopes.begin(), tdcSlopes.end(), 0.0) / (tdcSlopes.size() - 1 - nDeadTDC));
458
459 delete hADCMean;
460 delete hADC1000;
461 delete hADC0;
462 delete hTDCEdge;
463 delete hTDCSlope;
464 delete hHitPerLayer;
465 delete hHitRatePerWire;
466
467}
468
470{
471
472 B2DEBUG(20, "terminate called");
473}
474
The Class for CDC geometry.
Definition CDCGeometry.h:27
Class for accessing arrays of objects in the database.
Definition DBArray.h:26
Class for accessing objects in the database.
Definition DBObjPtr.h:21
std::map< WireID, std::pair< int, int > > m_chMap
Channel map retrieved.
void initialize() override final
Initialize the Module.
std::string m_hname_hits
Hits histogram names.
DBArray< CDCChannelMap > * m_channelMapFromDB
Channel map retrieved from DB.
std::vector< std::pair< int, int > > m_badChannels
bad wires list
int m_nSenseWires[56]
number of wires for each layer.
TH1D * m_hTDCs[300]
TDC histograms with track associated hits for each board (0-299)
MonitoringObject * m_monObj
monitoring object
void terminate() override final
Termination action.
DBObjPtr< CDCGeometry > * m_cdcGeo
Geometry of CDC.
TH2F * m_hTDC
Summary of TDC histograms with track associated hits.
TH1D * m_hADCs[300]
ADC histograms with track associated hits for each board (0-299)
TH2F * hBadChannel
bad channel map;wire;layer
std::pair< int, int > getBoardChannel(unsigned short layer, unsigned short wire)
Get board/channel from layer/wire.
TH1D * m_hHits[56]
hit histograms for each layer (0-55)
void endRun() override final
End-of-run action.
void configureBins(TH2Poly *h)
Configure bins of TH2Poly.
float getHistMean(TH1D *h) const
Get mean of ADC histogram excluding 0-th bin.
void beginRun() override final
Called when entering a new run.
TH2F * m_hADC
Summary of ADC histograms with track associated hits.
TH2F * hBadChannelBC
bad channel map per board/channel;board;channel
float getHistMedian(TH1D *h) const
Get median of ADC histogram excluding 0-th bin.
float m_senseR[56]
Radius of sense (+field) layer.
std::string m_hname_btdc
Board TDC histogram name.
std::string m_hname_badc
Board ADC histogram name.
static MonitoringObject * getMonitoringObject(const std::string &name)
Get MonitoringObject with given name (new object is created if non-existing)
static TH1 * findHist(const std::string &histname, bool onlyIfUpdated=false)
Get histogram from list (no other search).
DQMHistAnalysisModule()
Constructor / Destructor.
void setDescription(const std::string &description)
Sets the description of the module.
Definition Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition Module.h:80
Class to identify a wire inside the CDC.
Definition WireID.h:34
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
double tan(double a)
tan for double
Definition beamHelpers.h:31
Abstract base class for different kinds of events.
STL namespace.