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