Belle II Software  release-08-01-10
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 
23 using namespace std;
24 using namespace Belle2;
25 
26 //-----------------------------------------------------------------
27 // Register module
28 //-----------------------------------------------------------------
29 
30 REG_MODULE(DQMHistAnalysisCDCMonObj);
31 
32 DQMHistAnalysisCDCMonObjModule::DQMHistAnalysisCDCMonObjModule()
34 {
35  // set module description (e.g. insert text)
36  setDescription("Modify and analyze the data quality histograms of CDCMonObj");
38  for (int i = 0; i < 300; i++) {
39  m_hADCs[i] = nullptr;
40  m_hTDCs[i] = nullptr;
41  }
42  for (int i = 0; i < 56; i++) m_hHits[i] = nullptr;
43 }
44 
46 {
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 
62 
63 
65 
66  gStyle->SetOptStat(0);
67  gStyle->SetPalette(kViridis);
68  gStyle->SetPadTopMargin(0.1);
69  gStyle->SetPadRightMargin(0.05);
70  gStyle->SetPadBottomMargin(0.1);
71  gStyle->SetPadLeftMargin(0.15);
72 
73  m_cMain = new TCanvas("cdc_main", "cdc_main", 1500, 1000);
75 
76  m_cADC = new TCanvas("cdc_adc", "cdc_adc", 2000, 10000);
78  m_cTDC = new TCanvas("cdc_tdc", "cdc_tdc", 2000, 10000);
80  m_cHit = new TCanvas("cdc_hit", "cdc_hit", 1500, 6000);
82 
83  B2DEBUG(20, "DQMHistAnalysisCDCMonObj: initialized.");
84 
85 }
86 
88 {
89  for (const auto& cm : (*m_channelMapFromDB)) {
90  const int isl = cm.getISuperLayer();
91  const int il = cm.getILayer();
92  const int iw = cm.getIWire();
93  const int iBoard = cm.getBoardID();
94  const int iCh = cm.getBoardChannel();
95  const WireID wireId(isl, il, iw);
96  m_chMap.insert(std::make_pair(wireId, std::make_pair(iBoard, iCh)));
97  }
98 
99 
100  const CDCGeometry& geom = **m_cdcGeo;
101 
102  for (const auto& sense : geom.getSenseLayers()) {
103  int i = sense.getId();
104  if (i < 0 || i > 55) {
105  B2FATAL("no such sense layer");
106  }
107  m_senseR[i] = sense.getR();
108  m_nSenseWires[i] = sense.getNWires();
109  m_offset[i] = sense.getOffset();
110  }
111 
112  for (const auto& field : geom.getFieldLayers()) {
113  int i = field.getId();
114  if (i < 0 || i > 54) {
115  B2FATAL("no such sense layer");
116  }
117  m_fieldR[i + 1] = field.getR();
118  }
119  m_fieldR[56] = geom.getOuterWall(0).getRmin();
120  m_fieldR[0] = geom.getInnerWall(0).getRmax();
121 
122 }
123 
124 
126 {
127  for (int ilayer = 0; ilayer < 56; ++ilayer) {
128  float dPhi = float(2 * M_PI / m_nSenseWires[ilayer]);
129  float r1 = m_fieldR[ilayer];
130  float r2 = m_fieldR[ilayer + 1];
131  for (int iwire = 0; iwire < m_nSenseWires[ilayer]; ++iwire) {
132  float phi = dPhi * (iwire + m_offset[ilayer]);
133  float phi1 = phi - dPhi * 0.5;
134  float phi2 = phi + dPhi * 0.5;
135  Double_t x_pos[] = {r1* (sin(phi)*tan(phi - phi1) + cos(phi)),
136  r2 * cos(phi1),
137  r2 * cos(phi2),
138  r1* (sin(phi)*tan(phi - phi2) + cos(phi))
139  };
140  Double_t y_pos[] = {r1* (-cos(phi)*tan(phi - phi1) + sin(phi)),
141  r2 * sin(phi1),
142  r2 * sin(phi2),
143  r1* (-cos(phi)*tan(phi - phi2) + sin(phi))
144  };
145  h->AddBin(4, x_pos, y_pos);
146  }
147  }
148 }
149 
150 
152 {
153  m_badChannels.clear();
154  for (int il = 0; il < 56; ++il) {
155  for (int iw = 0; iw < m_nSenseWires[il]; ++iw) {
156  const int y = m_hHits[il]->GetBinContent(iw + 1);
157  if (y == 0) {
158  m_badChannels.push_back(std::make_pair(il, iw));
159  }
160  }
161  }
162  B2DEBUG(20, "num bad wires " << m_badChannels.size());
163 }
164 
166 {
167  TH1D* hist = (TH1D*)h->Clone();
168  hist->SetBinContent(1, 0.0); // Exclude 0-th bin
169  float m = hist->GetMean();
170  return m;
171 }
172 
174 {
175  TH1D* hist = (TH1D*)h->Clone();
176  hist->SetBinContent(1, 0.0); // Exclude 0-th bin
177  if (hist->GetMean() == 0) {return 0.0;} // Avoid an error if only ADC=0 entries
178  double quantiles[1] = {0.0}; // One element to store median
179  double probSums[1] = {0.5}; // Median definition
180  hist->GetQuantiles(1, quantiles, probSums);
181  float median = quantiles[0];
182  return median;
183 }
184 
185 std::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  m_hADC = (TH2F*)findHist("CDC/hADC");
202  m_hTDC = (TH2F*)findHist("CDC/hTDC");
203  m_hHit = (TH2F*)findHist("CDC/hHit");
204 
205  if (m_hADC == nullptr) {
206  m_monObj->setVariable("comment", "No ADC histograms of CDC in file");
207  B2INFO("Histogram named m_hADC is not found.");
208  return;
209  }
210 
211  TF1* fitFunc[300] = {};
212  for (int i = 0; i < 300; ++i) {
213  fitFunc[i] = new TF1(Form("f%d", i), "[0]+[6]*x+[1]*(exp([2]*(x-[3]))/(1+exp(-([4]-x)/[5])))",
214  4921 - 100, 4921 + 100);
215  fitFunc[i]->SetParLimits(6, 0, 0.1);
216  fitFunc[i]->SetParLimits(4, 4850., 5000.0);
217  fitFunc[i]->SetParLimits(5, 0, 50.0);
218  }
219 
220  int neve = m_hTDC->GetEntries();
221  if (neve == 0)neve = 1;
222 
223  B2DEBUG(20, "adc related");
224  int nDeadADC = -1; // bid 0 always empty
225  int nBadADC = 0;
226  TH1F* hADCMean = new TH1F("hADCMean", "ADC mean;board;adc mean", 300, 0, 300);
227  TH1F* hADC1000 = new TH1F("ADC1000", "ADC1000", 300, 0, 300);
228  TH1F* hADC0 = new TH1F("ADC0", "ADC0", 300, 0, 300);
229 
230  // Collect ADC mean/median for each board
231  std::vector<float> means = {};
232  std::vector<float> medians = {};
233 
234  for (int i = 0; i < 300; ++i) {
235  m_hADCs[i] = m_hADC->ProjectionY(Form("hADC%d", i), i + 1, i + 1, "");
236  m_hADCs[i]->SetTitle(Form("hADC%d", i));
237  float n = static_cast<float>(m_hADCs[i]->GetEntries());
238  if (m_hADCs[i]->Integral(0, m_hADCs[i]->GetNbinsX()) == 0) {
239  nDeadADC += 1;
240  hADC0->SetBinContent(i + 1, -0.1);
241  } else {
242  float n0 = static_cast<float>(m_hADCs[i]->GetBinContent(1));
243  if (n0 / n > 0.9) {
244  B2DEBUG(21, "bad adc bid " << i << " " << n0 << " " << n);
245  nBadADC += 1;
246  }
247  float bin1 = m_hADCs[i]->GetBinContent(1);
248  float m = getHistMean(m_hADCs[i]);
249  float md = getHistMedian(m_hADCs[i]);
250  means.push_back(m);
251  medians.push_back(md);
252  hADCMean->SetBinContent(i + 1, m);
253  hADCMean->SetBinError(i + 1, 0);
254  double overflow = m_hADCs[i]->GetBinContent(m_hADCs[i]->GetNbinsX() + 1);
255  hADC1000->SetBinContent(i + 1, overflow / (overflow + n));
256  hADC0->SetBinContent(i + 1, bin1 / (overflow + n));
258  }
259  }
260  // TDC related
261  B2DEBUG(20, "tdc related");
262  int nDeadTDC = -1; // bid 0 always empty
263  TH1F* hTDCEdge = new TH1F("hTDCEdge", "TDC edge;board;tdc edge [nsec]", 300, 0, 300);
264  TH1F* hTDCSlope = new TH1F("hTDCSlope", "TDC slope;board;tdc slope [nsec]", 300, 0, 300);
265  std::vector<float> tdcEdges = {};
266  std::vector<float> tdcSlopes = {};
267  for (int i = 0; i < 300; ++i) {
268  m_hTDCs[i] = m_hTDC->ProjectionY(Form("hTDC%d", i), i + 1, i + 1);
269  m_hTDCs[i]->SetTitle(Form("hTDC%d", i));
270  if (m_hTDCs[i]->Integral(0, m_hTDCs[i]->GetNbinsX()) == 0 || m_hTDCs[i] == nullptr) {
271  nDeadTDC += 1;
272  tdcEdges.push_back(0);
273  tdcSlopes.push_back(0);
274  } else {
275  double init_p0 = m_hTDCs[i]->GetBinContent(700 + 60);
276  fitFunc[i]->SetParameters(init_p0, 100, 0.01, 4700, 4900, 2, 0.01);
277  fitFunc[i]->SetParameter(6, 0.02);
278  fitFunc[i]->SetParLimits(0, init_p0 - 200, init_p0 + 200);
279  int xxx = -1;
280  if (i < 28) {
281  xxx = m_hTDCs[i]->Fit(fitFunc[i], "qM0", "", 4850, 5000);
282  } else {
283  xxx = m_hTDCs[i]->Fit(fitFunc[i], "qM0", "", 4800, 5000);
284  }
285  float p4 = fitFunc[i]->GetParameter(4);
286  float p5 = fitFunc[i]->GetParameter(5);
287 
288  if (xxx != -1 && 4850 < p4 && p4 < 5000) {
289  hTDCEdge->SetBinContent(i + 1, p4);
290  hTDCEdge->SetBinError(i + 1, 0);
291  hTDCSlope->SetBinContent(i + 1, p5);
292  hTDCSlope->SetBinError(i + 1, 0);
293  }
294  tdcEdges.push_back(p4);
295  tdcSlopes.push_back(p5);
296  }
297 
298  }
299 
300  // Hit related
301  B2DEBUG(20, "hit related");
302  TH1F* hHitPerLayer = new TH1F("hHitPerLayer", "hit/Layer;layer", 56, 0, 56);
303  int nHits = 0;
304  for (int i = 0; i < 56; ++i) {
305  m_hHits[i] = m_hHit->ProjectionY(Form("hHit%d", i), i + 1, i + 1);
306  m_hHits[i]->SetTitle(Form("hHit%d", i));
307  if (m_hHits[i]->GetEntries() > 0 && m_hHits[i] != nullptr) {
308  int nhitSumL = 0;
309  int nBins = m_nSenseWires[i];
310  for (int j = 0; j < nBins; ++j) {
311  nhitSumL += m_hHits[i]->GetBinContent(j + 1);
312  }
313  if (neve > 0) {
314  hHitPerLayer->SetBinContent(i + 1, static_cast<float>(1.0 * nhitSumL / neve));
315  } else hHitPerLayer->SetBinContent(i + 1, static_cast<float>(nhitSumL));
316  hHitPerLayer->SetBinError(i + 1, 0);
317  nHits += nhitSumL;
318  }
319  }
320 
321  // Bad wires related
322  B2DEBUG(20, "bad wire related");
323  hBadChannel = new TH2F("hbadch", "bad channel map;wire;layer", 400, 0, 400, 56, 0, 56);
324  for (int i = 0; i < 400; ++i) {
325  for (int j = 0; j < 56; ++j) {
326  hBadChannel->Fill(i, j, -1);
327  }
328  }
329 
330  hBadChannelBC = new TH2F("hbadchBC", "bad channel map per board/channel;board;channel", 300, 0, 300, 48, 0, 48);
331  for (int i = 0; i < 300; ++i) {
332  for (int j = 0; j < 48; ++j) {
333  hBadChannelBC->Fill(i, j, -1);
334  }
335  }
336 
337  h2p = new TH2Poly();
339  h2p->SetTitle("bad wires in xy view");
340  h2p->GetXaxis()->SetTitle("X [cm]");
341  h2p->GetYaxis()->SetTitle("Y [cm]");
343  for (const auto& lw : m_badChannels) {
344  const int l = lw.first;
345  const int w = lw.second;
346  B2DEBUG(21, "l " << l << " w " << w);
347  hBadChannel->Fill(w, l);
348  std::pair<int, int> bc = getBoardChannel(l, w);
349  hBadChannelBC->Fill(bc.first, bc.second);
350  float r = m_senseR[l];
351  float dPhi = static_cast<float>(2.0 * M_PI / m_nSenseWires[l]);
352  float phi = dPhi * (w + m_offset[l]);
353  float x = r * cos(phi);
354  float y = r * sin(phi);
355  h2p->Fill(x, y, 1.1);
356  }
357 
358  B2DEBUG(20, "writing");
359  m_cMain->Divide(3, 3);
360 
361  m_cMain->cd(1);
362  hADCMean->SetMinimum(0);
363  hADCMean->SetMaximum(300);
364  hADCMean->DrawCopy();
365 
366  m_cMain->cd(2);
367  hTDCEdge->SetMinimum(4800);
368  hTDCEdge->SetMaximum(5000);
369  hTDCEdge->DrawCopy();
370 
371  m_cMain->cd(3);
372  hTDCSlope->SetMinimum(0);
373  hTDCSlope->SetMaximum(50);
374  hTDCSlope->DrawCopy();
375  m_cMain->cd(4);
376  hBadChannel->DrawCopy("col");
377 
378  m_cMain->cd(5);
379  hBadChannelBC->DrawCopy("col");
380  m_cMain->cd(9);
381  hHitPerLayer->DrawCopy();
382  m_cMain->cd(7);
383  hADC1000->DrawCopy();
384  m_cMain->cd(8);
385  hADC0->DrawCopy();
386 
387  m_cHit->Divide(4, 14);
388  for (int i = 0; i < 56; i++) {
389  m_cHit->cd(i + 1);
390  m_hHits[i]->GetXaxis()->SetRangeUser(0, m_nSenseWires[i]);
391  m_hHits[i]->Draw("hist");
392  }
393 
394  m_cADC->Divide(6, 50, 0.0002, 0.0002);
395  m_cTDC->Divide(6, 50, 0.0002, 0.0002);
396 
397  for (int i = 0; i < 300; i++) {
398  m_cADC->cd(i + 1);
399  Double_t max = m_hADCs[i]->GetMaximum();
400  m_hADCs[i]->GetYaxis()->SetRangeUser(0, 3 * max);
401  m_hADCs[i]->Draw("hist");
402 
403  m_cTDC->cd(i + 1);
404  m_hTDCs[i]->Draw("hist");
405  fitFunc[i]->SetLineColor(kRed);
406  fitFunc[i]->Draw("same");
407  max = m_hTDCs[i]->GetMaximum();
408  TLine* l1 = new TLine(tdcEdges[i], 0, tdcEdges[i], max * 1.05);
409  l1->SetLineColor(kRed);
410  TLine* l0 = new TLine(4910, 0, 4910, max * 1.05);
411  l0->Draw();
412  l1->Draw();
413  }
414 
415  m_cMain->cd(6);
416  h2p->DrawCopy("col");
417  float superLayerR[10] = {16.3, 24.3, 35.66, 46.63, 57.55, 68.47,
418  79.39, 90.31, 101.23, 112.05
419  };
420 
421  TEllipse* circs[10];
422  for (int i = 0; i < 10; ++i) {
423  circs[i] = new TEllipse(0, 0, superLayerR[i], superLayerR[i]);
424  circs[i]->SetFillStyle(4000);
425  circs[i]->SetLineStyle(kDashed);
426  circs[i]->SetLineColor(0);
427  circs[i]->Draw("same");
428  }
429 
430  m_monObj->setVariable("nEvents", neve);
431  m_monObj->setVariable("nHits", nHits / neve);
432  m_monObj->setVariable("nBadWires", m_badChannels.size());
433  m_monObj->setVariable("adcMean", std::accumulate(means.begin(), means.end(), 0.0) / means.size());
434  m_monObj->setVariable("adcMeanMedianBoard", std::accumulate(medians.begin(), medians.end(), 0.0) / medians.size());
435  m_monObj->setVariable("nDeadADC", nDeadADC);
436  m_monObj->setVariable("nBadADC", nBadADC); //???? n_0/n_tot>0.9
437  m_monObj->setVariable("tdcEdge", std::accumulate(tdcEdges.begin(), tdcEdges.end(), 0.0) / (tdcEdges.size() - 1 - nDeadTDC));
438  m_monObj->setVariable("nDeadTDC", nDeadTDC);
439  m_monObj->setVariable("tdcSlope", std::accumulate(tdcSlopes.begin(), tdcSlopes.end(), 0.0) / (tdcSlopes.size() - 1 - nDeadTDC));
440 
441  delete hADCMean;
442  delete hADC1000;
443  delete hADC0;
444  delete hTDCEdge;
445  delete hTDCSlope;
446  delete hHitPerLayer;
447 
448 }
449 
451 {
452 
453  B2DEBUG(20, "terminate called");
454 }
455 
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.
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 m_fieldR[57]
Radius of field layer.
float getHistMedian(TH1D *h) const
Get median of ADC histogram excluding 0-th bin.
float m_senseR[56]
Radius of sense (+field) layer.
TH2F * m_hHit
Summary of hit histograms.
The base class for the histogram analysis module.
static TH1 * findHist(const std::string &histname, bool onlyIfUpdated=false)
Get histogram from list (no other search).
static MonitoringObject * getMonitoringObject(const std::string &histname)
Get MonitoringObject with given name (new object is created if non-existing)
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
void setVariable(const std::string &var, float val, float upErr=-1., float dwErr=-1)
set value to float variable (new variable is made if not yet existing)
void addCanvas(TCanvas *canv)
Add Canvas to monitoring object.
Class to identify a wire inside the CDC.
Definition: WireID.h:34
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
double tan(double a)
tan for double
Definition: beamHelpers.h:31
Abstract base class for different kinds of events.