Belle II Software development
CDCDedxValidationAlgorithm.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#include <cdc/calibration/CDCdEdx/CDCDedxValidationAlgorithm.h>
10#include <cdc/calibration/CDCdEdx/CDCDedxWireGainAlgorithm.h>
11
12#include <cdc/dbobjects/CDCDedxWireGain.h>
13#include <cdc/dbobjects/CDCDedxCosineCor.h>
14#include <cdc/dbobjects/CDCDedx1DCell.h>
15#include <cdc/dbobjects/CDCDedxRunGain.h>
16#include <cdc/dbobjects/CDCDedxBadWires.h>
17#include <framework/database/IntervalOfValidity.h>
18
19#include <framework/database/Database.h>
20#include <framework/database/DBStore.h>
21#include <framework/database/Configuration.h>
22
23#include <cmath>
24#include <TTree.h>
25#include <TMap.h>
26#include <TLegend.h>
27#include <TF1.h>
28
29
30using namespace Belle2;
31using namespace CDC;
32
33//-----------------------------------------------------------------
34// Implementation
35//-----------------------------------------------------------------
36
38 CalibrationAlgorithm("ElectronValCollector"),
39 m_sigmaR(2.0),
40 m_dedxBins(600),
41 m_dedxMin(0.0),
42 m_dedxMax(5.0),
43 m_cosBins(100),
44 m_cosMin(-1.0),
45 m_cosMax(1.0),
46 m_momBins(80),
47 m_momMin(0.0),
48 m_momMax(8.0),
49 m_eaBin(316),
50 m_eaMin(-TMath::Pi() / 2),
51 m_eaMax(+TMath::Pi() / 2),
52 m_suffix("")
53{
54 // Set module properties
55 setDescription("A validation algorithm for CDC dE/dx electron");
56}
57
58//-----------------------------------------------------------------
59// Run the calibration
60//-----------------------------------------------------------------
61
63{
64
66
67 std::vector<std::string> subdirs = {"run", "costh", "mom", "wire", "injection", "oneD"};
68 for (const auto& dir : subdirs) {
69 gSystem->Exec(Form("mkdir -p plots/%s", dir.c_str()));
70 }
71
72 // Get data objects
73 auto tBhabha = getObjectPtr<TTree>("tBhabha");
74
75 // require at least 100 tracks
76 if (tBhabha->GetEntries() < 100) return c_NotEnoughData;
77
78 // Get data objects
79 auto tRadee = getObjectPtr<TTree>("tRadee");
80
81 // require at least 100 tracks
82 if (tRadee->GetEntries() < 100) return c_NotEnoughData;
83
87
88 m_suffix.clear();
89
90 return c_OK;
91}
92
93//------------------------------------
95{
96
97 int cruns = 0;
98 for (auto expRun : getRunList()) {
99 if (cruns == 0) B2INFO("start exp " << expRun.first << " and run " << expRun.second << "");
100 cruns++;
101 }
102
103 const auto erStart = getRunList()[0];
104 int estart = erStart.first;
105 int rstart = erStart.second;
106
107 updateDBObjPtrs(1, rstart, estart);
108
109 if (m_suffix.length() > 0) m_suffix = Form("%s_e%d_r%d", m_suffix.data(), estart, rstart);
110 else m_suffix = Form("e%d_r%d", estart, rstart);
111}
112
113
115{
116 auto ttree = getObjectPtr<TTree>("tRadee");
117
118 double dedx, costh, p, injtime = 0.0, injring = 1.0;
119 int charge;
120
121 std::vector<double>* dedxhit = 0, *enta = 0;
122 std::vector<int>* layer = 0;
123
124 ttree->SetBranchAddress("dedx", &dedx);
125 ttree->SetBranchAddress("p", &p);
126 ttree->SetBranchAddress("costh", &costh);
127 ttree->SetBranchAddress("charge", &charge);
128 ttree->SetBranchAddress("injtime", &injtime);
129 ttree->SetBranchAddress("injring", &injring);
130 ttree->SetBranchAddress("dedxhit", &dedxhit);
131 ttree->SetBranchAddress("entaRS", &enta);
132 ttree->SetBranchAddress("layer", &layer);
133
135 m_tbins = m_vtlocaledges.size() - 1;
137
138 std::array<std::array<std::vector<TH1D*>, 2>, 13> hdedx_mom;
139 std::array<std::vector<TH1D*>, 2> hdedx_mom_peaks, hdedx_inj, hdedx_inj_nocor;
140 std::array<std::vector<TH1D*>, 3> hdedx_oned;
141
142 TH1D* htimes = new TH1D(Form("htimes_%s", m_suffix.data()), "", m_tbins, m_tedges);
143
144 const double momBinWidth = (m_momMax - m_momMin) / m_momBins;
145 const double momBinW = (4.0 - m_momMin) / 4;
146
147 std::string scos[13] = {"acos", "cos#theta > 0.0", "cos#theta < 0.0", "cos#theta <= -0.8",
148 "cos#theta > -0.8 and cos#theta <= -0.6",
149 "cos#theta > -0.6 and cos#theta <= -0.4", "cos#theta > -0.4 and cos#theta <= -0.2",
150 "cos#theta > -0.2 and cos#theta <= 0", "cos#theta > 0 and cos#theta <= 0.2",
151 "cos#theta > 0.2 and cos#theta <= 0.4", "cos#theta > 0.4 and cos#theta <= 0.6",
152 "cos#theta > 0.6 and cos#theta <= 0.8", "cos#theta > 0.8"
153 };
154 std::string stype[2] = {"posi", "elec"};
155 std::string sLayer[3] = {"SL0", "SL1", "SL2-8"};
156
157 // Define histograms for momentum bins and charge types
158 for (int ic = 0; ic < 13; ic++) {
159 for (int it = 0; it < 2; ++it) {
160 hdedx_mom[ic][it].resize(m_momBins);
161 defineHisto(hdedx_mom[ic][it], "mom", Form("%d_%s", ic, stype[it].data()));
162 }
163 }
164
165 // Define histograms for injection time bins and rings
166 for (unsigned int ir = 0; ir < 2; ir++) {
167 hdedx_inj[ir].resize(m_tbins);
168 hdedx_inj_nocor[ir].resize(m_tbins);
169 hdedx_mom_peaks[ir].resize(4);
170
171 defineHisto(hdedx_inj[ir], "inj", m_sring[ir].data());
172 defineHisto(hdedx_inj_nocor[ir], "inj", Form("nocor_%s", m_sring[ir].data()));
173 defineHisto(hdedx_mom_peaks[ir], "mom_peaks", Form("%s", stype[ir].data()));
174
175 }
176
177 for (unsigned int ir = 0; ir < 3; ir++) {
178 hdedx_oned[ir].resize(m_eaBin);
179 defineHisto(hdedx_oned[ir], "oned", Form("%s", sLayer[ir].data()));
180 }
181
182 double eaBW = (m_eaMax - m_eaMin) / m_eaBin;
183 double icos[3] = {0, -1, -1};
184 double chgtype;
185
186 // Loop over all the entries in the tree
187 for (int i = 0; i < ttree->GetEntries(); ++i) {
188 ttree->GetEvent(i);
189
190 // Skip invalid events
191 if (dedx <= 0 || injtime < 0 || injring < 0) continue;
192
193 // Calculate momentum bin index for hdedx_mom
194 int binIndex = static_cast<int>((abs(p) - m_momMin) / momBinWidth);
195
196 // Determine cos(theta) category
197
198 icos[1] = (costh > 0) ? 1 : 2;
199 icos[2] = int((costh + 1.0) / 0.2) + 3;
200 if (icos[2] < 3) icos[2] = 3;
201 if (icos[2] > 12) icos[2] = 12;
202
203 // Determine charge type
204 chgtype = (charge > 0) ? 0 : 1;
205
206 // Fill momentum histograms (only if binIndex is valid)
207 if (binIndex >= 0 && binIndex < m_momBins) {
208 hdedx_mom[icos[0]][chgtype][binIndex]->Fill(dedx);
209 hdedx_mom[icos[1]][chgtype][binIndex]->Fill(dedx);
210 hdedx_mom[icos[2]][chgtype][binIndex]->Fill(dedx);
211 }
212
213 // Add larger times to the last bin
214 if (injtime > m_tedges[m_tbins]) injtime = m_tedges[m_tbins] - 10.0;
215
216 // Injection ring type
217 int wr = (injring > 0.5) ? 1 : 0;
218
219 double timeGain = m_DBInjectTime->getCorrection("mean", injring, injtime);
220
221 // Injection time bin
222 unsigned int tb = htimes->GetXaxis()->FindBin(injtime);
223 tb = std::min(tb, static_cast<unsigned int>(m_tbins)) - 1;
224
225 // Fill injection time and dE/dx histograms
226 htimes->Fill(injtime);
227 hdedx_inj[wr][tb]->Fill(dedx);
228 hdedx_inj_nocor[wr][tb]->Fill(dedx * timeGain);
229
230 // Fill hdedx_mom_peaks with its own binning
231 int binI = static_cast<int>((abs(p) - m_momMin) / momBinW);
232 if (binI >= 0 && binI < 4) {
233 hdedx_mom_peaks[chgtype][binI]->Fill(dedx);
234 }
235
236 // Fill dE/dx in enta bins from hits
237 for (unsigned int j = 0; j < dedxhit->size(); ++j) {
238 if (dedxhit->at(j) == 0) continue;
239
240 double entaval = enta->at(j);
241 int ibin = std::floor((entaval - m_eaMin) / eaBW);
242 if (ibin < 0 || ibin >= m_eaBin) continue;
243
244 int lay = layer->at(j);
245 int mL = (lay < 8) ? 0 : ((lay < 14) ? 1 : 2);
246 hdedx_oned[mL][ibin]->Fill(dedxhit->at(j));
247 }
248 }
249
250
251 for (int ic = 0; ic < 13; ic++) {
252 for (int it = 0; it < 2; ++it) {
253 printCanvas(hdedx_mom[ic][it], Form("plots/mom/dedx_vs_mom_%d_%s_%s", ic, stype[it].data(), m_suffix.data()), "mom");
254 }
255 }
256 for (int it = 0; it < 2; ++it) {
257 printCanvas(hdedx_inj[it], Form("plots/injection/dedx_vs_inj_%s_%s", m_sring[it].data(), m_suffix.data()), "inj");
258 printCanvas(hdedx_inj_nocor[it], Form("plots/injection/dedx_vs_inj_nocor_%s_%s", m_sring[it].data(), m_suffix.data()), "inj");
259 }
260 for (int it = 0; it < 3; ++it)
261 printCanvas(hdedx_oned[it], Form("plots/oneD/dedx_vs_1D_%s_%s", sLayer[it].data(), m_suffix.data()), "oned");
262
263 printCanvasdEdx(hdedx_mom_peaks, Form("plots/mom/dedxpeaks_vs_mom_%s", m_suffix.data()), "mom");
264
265}
266
268{
269 auto ttree = getObjectPtr<TTree>("tBhabha");
270
271 double dedx, costh;
272 int run, charge;
273
274 std::vector<int>* wire = 0;
275 ttree->SetBranchAddress("wire", &wire);
276
277 std::vector<double>* dedxhit = 0;
278 ttree->SetBranchAddress("dedxhit", &dedxhit);
279
280 ttree->SetBranchAddress("dedx", &dedx);
281 ttree->SetBranchAddress("run", &run);
282 ttree->SetBranchAddress("charge", &charge);
283 ttree->SetBranchAddress("costh", &costh);
284
285 std::map<int, TH1D*> hdedx_run;
286 std::array<std::vector<TH1D*>, 3> hdedx_cos;
287 std::array<std::vector<TH1D*>, 2> hdedx_cos_peaks;
288 std::vector<TH1D*> hdedxhit(c_nSenseWires);
289
290 const double cosBinWidth = (m_cosMax - m_cosMin) / m_cosBins;
291 const double cosBinW = (m_cosMax - m_cosMin) / 4;
292
293 std::string stype[3] = {"all", "posi", "elec"};
294
295 for (int it = 0; it < 3; ++it) {
296 hdedx_cos[it].resize(m_cosBins);
297 defineHisto(hdedx_cos[it], "costh", stype[it]);
298 }
299
300 for (int ir = 0; ir < 2; ir++) {
301 hdedx_cos_peaks[ir].resize(4);
302 defineHisto(hdedx_cos_peaks[ir], "cos_peaks", Form("%s", stype[ir + 1].data()));
303 }
304
305 defineHisto(hdedxhit, "wire", "wire");
306
307 // Loop over all the entries in the tree
308 for (int i = 0; i < ttree->GetEntries(); ++i) {
309 ttree->GetEvent(i);
310 if (dedx <= 0) continue;
311
312 // Check if a dE/dx histogram for this run number already exists
313 if (hdedx_run.find(run) == hdedx_run.end()) {
314 std::string histName = Form("hist_dedx_run_%d", run);
315 std::string histTitle = Form("dE/dx Histogram for Run %d", run);
316 hdedx_run[run] = new TH1D(histName.data(), histTitle.data(), m_dedxBins, m_dedxMin, m_dedxMax);
317 }
318
319 // Fill run-specific histogram
320 hdedx_run[run]->Fill(dedx);
321
322 // Fill cos(theta) histograms (all charge + by charge sign)
323 int binIndex = static_cast<int>((costh - m_cosMin) / cosBinWidth);
324 if (binIndex >= 0 && binIndex < m_cosBins) {
325 hdedx_cos[0][binIndex]->Fill(dedx); // All charge
326
327 if (charge > 0)
328 hdedx_cos[1][binIndex]->Fill(dedx);
329 else if (charge < 0)
330 hdedx_cos[2][binIndex]->Fill(dedx);
331 }
332
333 // Fill dE/dx for each wire hit
334 for (unsigned int j = 0; j < wire->size(); ++j) {
335 int jwire = wire->at(j);
336 double jhitdedx = dedxhit->at(j);
337 hdedxhit[jwire]->Fill(jhitdedx);
338 }
339
340 // Fill cos(theta) peaks histograms
341 int binI = static_cast<int>((costh - m_cosMin) / cosBinW);
342 if (binI >= 0 && binI < 4) {
343 if (charge > 0)
344 hdedx_cos_peaks[0][binI]->Fill(dedx);
345 else if (charge < 0)
346 hdedx_cos_peaks[1][binI]->Fill(dedx);
347 }
348 }
349
350 printCanvasRun(hdedx_run, Form("plots/run/dedx_vs_run_%s", m_suffix.data()));
351 printCanvas(hdedx_cos[0], Form("plots/costh/dedx_vs_cos_all_%s", m_suffix.data()), "costh");
352 printCanvas(hdedx_cos[1], Form("plots/costh/dedx_vs_cos_positrons_%s", m_suffix.data()), "costh");
353 printCanvas(hdedx_cos[2], Form("plots/costh/dedx_vs_cos_electrons_%s", m_suffix.data()), "costh");
354 printCanvasdEdx(hdedx_cos_peaks, Form("plots/costh/dedxpeaks_vs_cos_%s", m_suffix.data()), "costh");
355 wireGain(hdedxhit);
356}
357
358//------------------------------------
359void CDCDedxValidationAlgorithm::defineHisto(std::vector<TH1D*>& htemp, const std::string& var, const std::string& stype)
360{
361 int xbins = 0;
362 double xmin = 0.0, xmax = 0.0;
363 double binWidth = 0.0;
364 int dedxbins = m_dedxBins;
365
366 if (var == "mom") {
367 xbins = m_momBins; xmin = m_momMin; xmax = m_momMax;
368 } else if (var == "oned") {
369 xbins = m_eaBin; xmin = m_eaMin; xmax = m_eaMax; dedxbins = 250;
370 } else if (var == "costh") {
371 xbins = m_cosBins; xmin = m_cosMin; xmax = m_cosMax;
372 } else if (var == "inj") {
373 xbins = m_tbins;
374 } else if (var == "mom_peaks") {
375 xbins = 4; xmin = m_momMin; xmax = 4.0;
376 } else if (var == "cos_peaks") {
377 xbins = 4; xmin = m_cosMin; xmax = m_cosMax;
378 } else {
379 xbins = c_nSenseWires; dedxbins = 250;
380 }
381
382 if (var == "costh" || var == "mom" || var == "mom_peaks" || var == "cos_peaks" || var == "oned") {
383 binWidth = (xmax - xmin) / xbins;
384 }
385
386 for (int ic = 0; ic < xbins; ic++) {
387 std::string title = Form("dedxhit-dist, wire:%d", ic);
388 std::string name = Form("hdedx_%s_%s_%d", m_suffix.data(), var.data(), ic);
389
390 if (var == "costh" || var == "mom" || var == "mom_peaks" || var == "cos_peaks" || var == "oned") {
391 double min = ic * binWidth + xmin;
392 double max = min + binWidth;
393 title = Form("%s: (%0.02f, %0.02f) %s", var.data(), min, max, stype.data());
394 name = Form("hdedx_%s_%s_%s_%d", m_suffix.data(), var.data(), stype.data(), ic);
395 } else if (var == "inj") {
396 std::string label = getTimeBinLabel(m_tedges[ic], ic);
397 title = Form("%s, time(%s)", stype.data(), label.data());
398 name = Form("h%s_%s_%s_t%d", var.data(), m_suffix.data(), stype.data(), ic);
399 }
400 htemp[ic] = new TH1D(name.data(), "", dedxbins, m_dedxMin, m_dedxMax);
401 htemp[ic]->SetTitle(Form("%s;dedx;entries", title.data()));
402 }
403}
404
405void CDCDedxValidationAlgorithm::printCanvasdEdx(std::array<std::vector<TH1D*>, 2>& htemp, const std::string& namesfx,
406 const std::string& svar)
407{
408 int xbins = 4;
409 double xmin = 0., xmax = 0.;
410
411 if (svar == "mom") {
412 xmin = m_momMin; xmax = 4.0;
413 } else if (svar == "costh") {
414 xmin = m_cosMin; xmax = m_cosMax;
415 } else {
416 B2FATAL("wrong input");
417 }
418 double binWidth = (xmax - xmin) / xbins;
419
420 // Set up the TCanvas with 2x2 grid
421 TCanvas* ctmp = new TCanvas("tmp", "tmp", 1200, 1200);
422 ctmp->Divide(2, 2); // Divide into 2x2 grid
423
424 // Prepare the PDF output
425 std::stringstream psname;
426 psname << Form("%s.pdf[", namesfx.data());
427 ctmp->Print(psname.str().c_str());
428 psname.str("");
429 psname << Form("%s.pdf", namesfx.data());
430
431 // Iterate through the histograms and plot them in the canvas
432 for (int i = 0; i < xbins; ++i) {
433
434 ctmp->cd(i % 4 + 1);
435
436 double emean, emeanErr, esigma, esigmaErr;
437 double pmean, pmeanErr, psigma, psigmaErr;
438
439 fit(htemp[0][i], emean, emeanErr, esigma, esigmaErr);
440 fit(htemp[1][i], pmean, pmeanErr, psigma, psigmaErr);
441
442 double min = i * binWidth + xmin;
443 double max = min + binWidth;
444
445 TPaveText pt(0.6, 0.63, 0.85, 0.89, "NBNDC");
446 setTextCosmetics(pt, kBlack);
447 pt.AddText("e+");
448 pt.AddText(Form("#mu_{fit}: %0.03f#pm%0.03f", emean, emeanErr));
449 pt.AddText(Form("#sigma_{fit}: %0.03f#pm%0.03f", esigma, esigmaErr));
450
451 pt.AddText("e-");
452 pt.AddText(Form("#mu_{fit}: %0.03f#pm%0.03f", pmean, pmeanErr));
453 pt.AddText(Form("#sigma_{fit}: %0.03f#pm%0.03f", psigma, psigmaErr));
454
455 htemp[0][i]->SetStats(0);
456 htemp[1][i]->SetStats(0);
457 htemp[0][i]->SetFillColor(0);
458 htemp[1][i]->SetFillColor(0);
459 htemp[0][i]->SetLineColor(8);
460 htemp[1][i]->SetLineColor(9);
461 htemp[0][i]->SetTitle(Form("%s: (%0.02f, %0.02f)", svar.data(), min, max));
462 if (htemp[0][i]->GetEntries() > 0)
463 htemp[0][i]->Scale(1.0 / htemp[0][i]->GetEntries());
464 if (htemp[1][i]->GetEntries() > 0)
465 htemp[1][i]->Scale(1.0 / htemp[1][i]->GetEntries());
466
467 if (htemp[1][i]->GetMaximum() > htemp[0][i]->GetMaximum())
468 htemp[0][i]->SetMaximum(htemp[1][i]->GetMaximum());
469
470 htemp[0][i]->DrawCopy("HIST");
471 htemp[1][i]->DrawCopy("same HIST");
472 pt.DrawClone("same");
473
474 TLegend* lego = new TLegend(0.15, 0.67, 0.3, 0.8);
475 lego->AddEntry(htemp[0][i], "e+", "l");
476 lego->AddEntry(htemp[1][i], "e-", "l");
477 lego->Draw("same");
478
479 if ((i + 1) % 4 == 0 || i == xbins - 1) {
480 ctmp->SetBatch(kTRUE);
481 ctmp->Print(psname.str().c_str());
482 if ((i + 1) % 4 == 0) ctmp->Clear("D");
483 }
484 }
485
486 psname.str("");
487 psname << Form("%s.pdf]", namesfx.data());
488 ctmp->Print(psname.str().c_str());
489
490 delete ctmp;
491}
492
493void CDCDedxValidationAlgorithm::printCanvas(std::vector<TH1D*>& htemp, const std::string& namesfx, const std::string& svar)
494{
495 int xbins = 0;
496 double xmin = 0.0, xmax = 0.0;
497
498 if (svar == "mom") {
499 xbins = m_momBins; xmin = m_momMin; xmax = m_momMax;
500 } else if (svar == "oned") {
501 xbins = m_eaBin; xmin = m_eaMin; xmax = m_eaMax;
502 } else if (svar == "costh") {
503 xbins = m_cosBins; xmin = m_cosMin; xmax = m_cosMax;
504 } else if (svar == "inj") {
505 xbins = m_tbins;
506 } else if (svar == "mom_peaks") {
507 xbins = 4; xmin = m_momMin; xmax = 4.0;
508 } else {
509 B2FATAL("wrong input");
510 }
511
512 // Set up the TCanvas with 4x4 grid
513 TCanvas* ctmp = new TCanvas("tmp", "tmp", 1200, 1200);
514 ctmp->Divide(4, 4); // Divide into 4x4 grid
515
516 // Prepare the PDF output
517 std::stringstream psname;
518 psname << Form("%s.pdf[", namesfx.data());
519 ctmp->Print(psname.str().c_str());
520 psname.str("");
521 psname << Form("%s.pdf", namesfx.data());
522
523 std::ofstream outFile;
524 outFile.open(Form("%s.txt", namesfx.data()));
526
527 // Iterate through the histograms and plot them in the canvas
528 for (int i = 0; i < xbins; ++i) {
529
530 ctmp->cd(i % 16 + 1);
531 TPaveText pt(0.6, 0.73, 0.85, 0.89, "NBNDC");
532 setTextCosmetics(pt, kBlack);
533
534 if (svar == "oned") {
535 unsigned int minbin, maxbin;
536 wireg.getTruncatedBins(htemp[i], minbin, maxbin);
537 htemp[i]->SetTitle(Form("dedxhit-dist, entabin: %d ;%d;%d", i, minbin, maxbin));
538
539 double dedxmean = wireg.getTruncationMean(htemp[i], minbin, maxbin);
540
541 const double binWidth = (xmax - xmin) / xbins;
542 double binCenter = xmin + (i + 0.5) * binWidth; // Calculate bin center for cos(theta) or mom
543
544 outFile << binCenter << " " << dedxmean << std::endl;
545 } else {
546 double mean, meanErr, sigma, sigmaErr;
547 fit(htemp[i], mean, meanErr, sigma, sigmaErr);
548
549 if (svar == "mom" || svar == "costh" || svar == "mom_peaks") {
550 const double binWidth = (xmax - xmin) / xbins;
551 double binCenter = xmin + (i + 0.5) * binWidth; // Calculate bin center for cos(theta) or mom
552
553 outFile << binCenter << " " << mean << " " << meanErr << " " << sigma << " " << sigmaErr << std::endl;
554 } else {
555 std::string label = getTimeBinLabel(m_tedges[i], i);
556 outFile << i << " " << label << " " << mean << " " << meanErr << " " << sigma << " " << sigmaErr << std::endl;
557 }
558
559 pt.AddText(Form("#mu_{fit}: %0.03f#pm%0.03f", mean, meanErr));
560 pt.AddText(Form("#sigma_{fit}: %0.03f#pm%0.03f", sigma, sigmaErr));
561 }
562 htemp[i]->SetStats(0);
563 htemp[i]->DrawCopy("");
564 pt.DrawClone("same");
565
566 if ((i + 1) % 16 == 0 || ((i + 1) == xbins)) {
567 ctmp->SetBatch(kTRUE);
568 ctmp->Print(psname.str().c_str());
569 ctmp->Clear("D");
570 }
571 }
572
573 // ctmp->Print(psname.str().c_str());
574 psname.str("");
575 psname << Form("%s.pdf]", namesfx.data());
576 ctmp->Print(psname.str().c_str());
577
578 outFile.close();
579
580 delete ctmp;
581}
582
583void CDCDedxValidationAlgorithm::fit(TH1D*& hist, double& mean, double& meanErr, double& sigma, double& sigmaErr)
584{
585
586 std::string status = "";
587
588 if (hist->Integral() > 100)
589 fitGaussianWRange(hist, status);
590
591 if (status != "fitOK") {
592 hist->SetFillColor(kOrange);
593 mean = 0.0, meanErr = 0.0, sigma = 0.0, sigmaErr = 0.0;
594 } else {
595 mean = hist->GetFunction("gaus")->GetParameter(1);
596 meanErr = hist->GetFunction("gaus")->GetParError(1);
597 sigma = hist->GetFunction("gaus")->GetParameter(2);
598 sigmaErr = hist->GetFunction("gaus")->GetParError(2);
599 hist->SetFillColor(kYellow);
600 }
601}
602
603void CDCDedxValidationAlgorithm::printCanvasRun(const std::map<int, TH1D*>& htemp, const std::string& namesfx)
604{
605 // Set up the TCanvas with 4x4 grid
606 TCanvas* ctmp = new TCanvas("tmp", "tmp", 1200, 1200);
607 ctmp->Divide(4, 4); // Divide into 4x4 grid
608
609 // Prepare the PDF output
610 std::stringstream psname;
611 psname << Form("%s.pdf[", namesfx.data());
612 ctmp->Print(psname.str().c_str());
613 psname.str("");
614 psname << Form("%s.pdf", namesfx.data());
615
616 std::ofstream outFile;
617 outFile.open(Form("%s.txt", namesfx.data()));
618
619 // Iterate through the histograms and plot them in the canvas
620 int irun = 0;
621 for (const auto& entry : htemp) {
622 int run = entry.first;
623 TH1D* hist = entry.second;
624
625 ctmp->cd(irun % 16 + 1);
626
627 TPaveText pt(0.6, 0.73, 0.85, 0.89, "NBNDC");
628 setTextCosmetics(pt, kBlack);
629
630 double mean, meanErr, sigma, sigmaErr;
631 fit(hist, mean, meanErr, sigma, sigmaErr);
632
633 outFile << run << " " << mean << " " << meanErr << " " << sigma << " " << sigmaErr << std::endl;
634
635 pt.AddText(Form("#mu_{fit}: %0.03f#pm%0.03f", mean, meanErr));
636 pt.AddText(Form("#sigma_{fit}: %0.03f#pm%0.03f", sigma, sigmaErr));
637
638 hist->SetStats(0);
639 hist->DrawCopy("");
640 pt.DrawClone("same");
641
642 if ((irun + 1) % 16 == 0 || irun == int(htemp.size() - 1)) {
643 ctmp->SetBatch(kTRUE);
644 ctmp->Print(psname.str().c_str());
645 ctmp->Clear("D");
646 }
647 irun++;
648 }
649
650 ctmp->Print(psname.str().c_str());
651 psname.str("");
652 psname << Form("%s.pdf]", namesfx.data());
653 ctmp->Print(psname.str().c_str());
654
655 outFile.close();
656
657 delete ctmp;
658}
659
660//----------------------------------------
661void CDCDedxValidationAlgorithm::fitGaussianWRange(TH1D*& temphist, std::string& status)
662{
663 double histmean = temphist->GetMean();
664 double histrms = temphist->GetRMS();
665 temphist->GetXaxis()->SetRangeUser(histmean - 5.0 * histrms, histmean + 5.0 * histrms);
666
667 int fs = temphist->Fit("gaus", "Q0");
668 if (fs != 0) {
669 B2INFO(Form("\tFit (round 1) for hist (%s) failed (status = %d)", temphist->GetName(), fs));
670 status = "fitFailed";
671 return;
672 } else {
673 double mean = temphist->GetFunction("gaus")->GetParameter(1);
674 double width = temphist->GetFunction("gaus")->GetParameter(2);
675 temphist->GetXaxis()->SetRangeUser(mean - 5.0 * width, mean + 5.0 * width);
676 fs = temphist->Fit("gaus", "QR", "", mean - m_sigmaR * width, mean + m_sigmaR * width);
677 if (fs != 0) {
678 B2INFO(Form("\tFit (round 2) for hist (%s) failed (status = %d)", temphist->GetName(), fs));
679 status = "fitFailed";
680 return;
681 } else {
682 temphist->GetXaxis()->SetRangeUser(mean - 5.0 * width, mean + 5.0 * width);
683 B2INFO(Form("\tFit for hist (%s) successful (status = %d)", temphist->GetName(), fs));
684 status = "fitOK";
685 }
686 }
687}
688
689void CDCDedxValidationAlgorithm::wireGain(std::vector<TH1D*>& hdedxhit)
690{
691
692 std::vector<double> vdedx_means;
693 std::vector<double> layermean(c_maxNSenseLayers);
694 std::vector<double> lgmean(c_maxNSenseLayers);
695
696 std::ofstream outFile, outFileLayer, outFileAvg, outFilebdwire;
697 outFile.open(Form("plots/wire/dedx_mean_gwire_%s.txt", m_suffix.data()));
698 outFilebdwire.open(Form("plots/wire/dedx_mean_badwire_%s.txt", m_suffix.data()));
699 outFileLayer.open(Form("plots/wire/dedx_mean_layer_%s.txt", m_suffix.data()));
700 outFileAvg.open(Form("plots/wire/dedx_mean_layer_avg_%s.txt", m_suffix.data()));
701
702 int activelayers = 0;
703 double layeravg = 0.0;
704
707
709
710 int jwire = -1;
711 for (unsigned int il = 0; il < c_maxNSenseLayers; ++il) {
712
713 int activewires = 0, goodwires = 0;
714 layermean[il] = 0.0;
715 lgmean[il] = 0.0;
716
717 for (unsigned int iw = 0; iw < cdcgeo.nWiresInLayer(il); ++iw) {
718 jwire++;
719
720 unsigned int minbin, maxbin;
721 wireg.getTruncatedBins(hdedxhit[jwire], minbin, maxbin);
722 hdedxhit[jwire]->SetTitle(Form("dedxhit-dist, wire: %d ;%d;%d", jwire, minbin, maxbin));
723
724 double dedxmean = wireg.getTruncationMean(hdedxhit[jwire], minbin, maxbin);
725 vdedx_means.push_back(dedxmean);
726
727 if (Badwire->getBadWireStatus(jwire) == kTRUE)
728 outFilebdwire << jwire << " " << dedxmean << std::endl;
729 else
730 outFile << jwire << " " << dedxmean << std::endl;
731
732 if (vdedx_means.at(jwire) > 0) {
733 layermean[il] += vdedx_means.at(jwire);
734 activewires++;
735 if (Badwire->getBadWireStatus(jwire) != kTRUE) {
736 lgmean[il] += vdedx_means.at(jwire);
737 goodwires++;
738 }
739 }
740 }
741
742 if (activewires > 0) layermean[il] /= activewires;
743 else layermean[il] = 1.0;
744
745 if (goodwires > 0) lgmean[il] /= goodwires;
746 else lgmean[il] = 1.0;
747
748 outFileLayer << il << " " << layermean[il] << " " << lgmean[il] << std::endl;
749
750 //calculate outer layer average for active layer
751 if (il >= 8 && layermean[il] > 0) {
752 layeravg += layermean[il];
753 activelayers++;
754 }
755 }
756
757 //normalisation of wiregains to get outergain ~1.0
758 if (activelayers > 0) layeravg /= activelayers;
759 outFileAvg << layeravg << std::endl;
760
761 outFile.close();
762 outFilebdwire.close();
763 outFileLayer.close();
764 outFileAvg.close();
765 printCanvasWire(hdedxhit, Form("plots/wire/dedx_vs_wire_%s", m_suffix.data()), vdedx_means);
766}
767
768void CDCDedxValidationAlgorithm::printCanvasWire(std::vector<TH1D*> temp, const std::string& namesfx,
769 const std::vector<double>& vdedx_mean)
770{
771 TCanvas* ctmp = new TCanvas("tmp", "tmp", 900, 900);
772 ctmp->Divide(4, 4);
773
774 std::stringstream psname;
775 psname << Form("%s.pdf[", namesfx.data());
776 ctmp->Print(psname.str().c_str());
777 psname.str("");
778 psname << Form("%s.pdf", namesfx.data());
779
780 for (unsigned int ip = 0; ip < c_nwireCDC; ip++) {
781 int minbin = std::stoi(temp[ip]->GetXaxis()->GetTitle());
782 int maxbin = std::stoi(temp[ip]->GetYaxis()->GetTitle());
783 temp[ip]->SetFillColor(kYellow - 9);
784 temp[ip]->SetTitle(Form("%s, #mu_{trunc} %0.03f;dedxhit;entries", temp[ip]->GetTitle(), vdedx_mean.at(ip)));
785
786 ctmp->cd(ip % 16 + 1);
787 gPad->cd();
788 temp[ip]->DrawCopy("hist");
789 TH1D* hdedxhitC = static_cast<TH1D*>(temp[ip]->Clone(Form("%sC", temp[ip]->GetName())));
790 hdedxhitC->GetXaxis()->SetRange(minbin, maxbin);
791 hdedxhitC->SetFillColor(kAzure + 1);
792 hdedxhitC->DrawCopy("same histo");
793
794 if ((ip + 1) % 16 == 0) {
795 ctmp->SetBatch(kTRUE);
796 ctmp->Print(psname.str().c_str());
797 ctmp->Clear("D");
798 }
799 delete temp[ip];
800 delete hdedxhitC;
801
802 }
803
804 psname.str("");
805 psname << Form("%s.pdf]", namesfx.data());
806 ctmp->Print(psname.str().c_str());
807 delete ctmp;
808}
809
810void CDCDedxValidationAlgorithm::defineTimeBins(std::vector<double>& vtlocaledges)
811{
812 double fixedges[69];
813 for (int ib = 0; ib < 69; ib++) {
814 fixedges[ib] = ib * 0.5 * 1e3;
815 if (ib > 40 && ib <= 60) fixedges[ib] = fixedges[ib - 1] + 1.0 * 1e3;
816 else if (ib > 60 && ib <= 64) fixedges[ib] = fixedges[ib - 1] + 10.0 * 1e3;
817 else if (ib > 64 && ib <= 65) fixedges[ib] = fixedges[ib - 1] + 420.0 * 1e3;
818 else if (ib > 65 && ib <= 66) fixedges[ib] = fixedges[ib - 1] + 500.0 * 1e3;
819 else if (ib > 66) fixedges[ib] = fixedges[ib - 1] + 2e6;
820 vtlocaledges.push_back(fixedges[ib]);
821 }
822}
823
824//--------------------------
826{
827
828 TCanvas cstats("cstats", "cstats", 800, 400);
829 cstats.SetBatch(kTRUE);
830 cstats.Divide(2, 1);
831
832 cstats.cd(1);
833 auto hestats = getObjectPtr<TH1I>("hestats");
834 if (hestats) {
835 hestats->SetName(Form("hestats_%s", m_suffix.data()));
836 hestats->SetStats(0);
837 hestats->DrawCopy("");
838 }
839
840 cstats.cd(2);
841 auto htstats = getObjectPtr<TH1I>("htstats");
842 if (htstats) {
843 htstats->SetName(Form("htstats_%s", m_suffix.data()));
844 htstats->SetStats(0);
845 htstats->DrawCopy("");
846 }
847
848 cstats.Print(Form("cdcdedx_stats_%s.pdf", m_suffix.data()));
849}
850
851void CDCDedxValidationAlgorithm::DatabaseIN(int experiment, int run)
852{
853 auto& dbConfiguration = Conditions::Configuration::getInstance();
854
855 dbConfiguration.overrideGlobalTags();
856 dbConfiguration.setGlobalTags({"online"});
857
858 if (!m_testingPayloadName.empty() && m_GlobalTagName.empty()) {
859 dbConfiguration.prependTestingPayloadLocation(m_testingPayloadName);
860 } else if (m_testingPayloadName.empty() && !m_GlobalTagName.empty()) {
861 dbConfiguration.prependGlobalTag(m_GlobalTagName);
862 } else
863 B2FATAL("Setting both testing payload and Global Tag or setting no one of them.");
864
866
867 /* Mimic a module initialization. */
869 EventMetaData.registerInDataStore();
871
872 if (!EventMetaData.isValid())
873 EventMetaData.construct(1, run, experiment);
874
875 else {
877 EventMetaData->setExperiment(experiment);
878 EventMetaData->setRun(run);
879 }
880
881 /* Database instance and configuration. */
882 DBStore& dbStore = DBStore::Instance();
883 dbStore.update();
884 dbStore.updateEvent();
885}
886
888{
889
890 DatabaseIN(experiment, run);
891
892 std::vector<double> wiregain;
893 std::vector<double> layermean(c_maxNSenseLayers);
894
895 DBObjPtr<CDCDedxWireGain> DBWireGains;
896 if (!DBWireGains.isValid()) B2FATAL("Wire gain data are not valid.");
897
899
900 int jwire = -1;
901 for (unsigned int il = 0; il < c_maxNSenseLayers; ++il) {
902
903 int activewires = 0;
904 layermean[il] = 0.0;
905
906 for (unsigned int iw = 0; iw < cdcgeo.nWiresInLayer(il); ++iw) {
907 jwire++;
908
909 wiregain.push_back(DBWireGains->getWireGain(jwire));
910
911 if (wiregain.at(jwire) > 0) {
912 layermean[il] += wiregain.at(jwire);
913 activewires++;
914 }
915 }
916
917 if (activewires > 0) layermean[il] /= activewires;
918 else layermean[il] = 1.0;
919 }
920
922 return { wiregain, layermean };
923}
924
926{
927
928 DatabaseIN(experiment, run);
929
930 std::array<std::vector<double>, 3> cosgain;
931 std::vector<double> cos;
932
933 DBObjPtr<CDCDedxCosineCor> DBCosineCor;
934 if (!DBCosineCor.isValid()) {
935 B2FATAL("Cosine gain data are not valid.");
936 }
937
938 // representative layer index for each group
939 const std::array<unsigned int, 3> layerIndex = {1, 9, 17};
940
941 for (int igroup = 0; igroup < 3; ++igroup) {
942 unsigned int nCosBins = DBCosineCor->getSize(layerIndex[igroup]);
943
944 for (unsigned int ibin = 0; ibin < nCosBins; ++ibin) {
945
946 double costh = -1.0 + (ibin + 0.5) * 2.0 / nCosBins;
947 costh += 1e-6;
948
949 if (igroup == 0) {
950 cos.push_back(costh);
951 }
952
953 cosgain[igroup].push_back(DBCosineCor->getMean(layerIndex[igroup], ibin));
954 }
955 }
956
958 return {cosgain, cos};
959}
960
962{
963
964 DatabaseIN(experiment, run);
965
966 std::array<std::vector<double>, 3> oneDcorr;
967 std::vector<double> enta;
968
969 DBObjPtr<CDCDedx1DCell> DBOneDCell;
970 if (!DBOneDCell.isValid()) {
971 B2FATAL("OneD cell gain data are not valid.");
972 }
973
974 // representative layer index for each group
975 const std::array<unsigned int, 3> layerIndex = {1, 9, 17};
976
977 for (int igroup = 0; igroup < 3; igroup++) {
978
979 unsigned int nBins = DBOneDCell->getNBins(layerIndex[igroup]);
980 double binSize = TMath::Pi() / nBins;
981
982 for (unsigned int nbin = 0; nbin < nBins; nbin++) {
983
984 double eta = (-1.0 * TMath::Pi() / 2.0) + binSize * nbin;
985
986 if (igroup == 0) {
987 enta.push_back(eta);
988 }
989
990 oneDcorr[igroup].push_back(DBOneDCell->getMean(layerIndex[igroup], nbin));
991 }
992 }
993
995 return {oneDcorr, enta};
996
997}
998double CDCDedxValidationAlgorithm::getrungain(int experiment, int run)
999{
1000
1001 DatabaseIN(experiment, run);
1002
1004 if (!RunGain.isValid()) B2FATAL("Run gain data are not valid.");
1005 double gain = RunGain->getRunGain();
1006 return gain;
1007}
1008
1010{
1011 /* Reset both DataStore and Database. */
1013 Database::Instance().reset(false);
1014 DBStore::Instance().reset(false);
1015}
void bhabhaValidation()
Validate dE/dx using bhabha sample (vs run, cosine)
double m_eaMax
upper edge of entrance angle
static void resetDatabase()
Clear current DB pointers and state.
static void setTextCosmetics(TPaveText pt, Color_t color)
Set text cosmetics for TPaveText.
void wireGain(std::vector< TH1D * > &hdedxhit)
Validate wire gain data using dE/dx histograms.
void printCanvas(std::vector< TH1D * > &htemp, const std::string &namesfx, const std::string &svar)
Draw dE/dx histograms across bins.
std::vector< double > m_vtlocaledges
internal time vector
void radeeValidation()
Validate dE/dx using radee sample (vs momentum, injection time)
double m_sigmaR
fit dedx dist in sigma range
WireGainData getwiregain(int experiment, int run)
Retrieve wire gain data from DB.
void getExpRunInfo()
function to get extract calibration run/exp
OnedData getonedgain(int experiment, int run)
Retrieve 1D gain data from DB.
double * m_tedges
internal time array (points into m_vtlocaledges)
void DatabaseIN(int experiment, int run)
Load database payload for given run.
static void defineTimeBins(std::vector< double > &vtlocaledges)
Set bin edges for injection time.
std::array< std::string, 2 > m_sring
injection ring name
CosGainData getcosgain(int experiment, int run)
Retrieve cosine gain data from DB.
std::string m_testingPayloadName
Testing payload location.
std::string m_suffix
suffix string to separate plots
DBObjPtr< CDCGeometry > m_cdcGeo
Geometry of CDC.
CDCDedxValidationAlgorithm()
Constructor: Sets the description, the properties and the parameters of the algorithm.
double getrungain(int experiment, int run)
Retrieve run gain data from DB.
void printCanvasRun(const std::map< int, TH1D * > &htemp, const std::string &namesfx)
Draw dE/dx per run histogram canvas.
void fitGaussianWRange(TH1D *&temphist, std::string &status)
Perform Gaussian fit with range on a histogram.
void plotEventStats()
Plot summary statistics of selected events.
virtual EResult calibrate() override
Main calibration method.
void printCanvasdEdx(std::array< std::vector< TH1D * >, 2 > &htemp, const std::string &namesfx, const std::string &svar)
Draw dE/dx histograms for momentum and cosine bins.
static void printCanvasWire(std::vector< TH1D * > temp, const std::string &namesfx, const std::vector< double > &vdedx_mean)
Plot dE/dx vs wire number.
DBObjPtr< CDCDedxInjectionTime > m_DBInjectTime
Injection time DB object.
void defineHisto(std::vector< TH1D * > &htemp, const std::string &var, const std::string &stype)
Define dE/dx histograms for plotting.
std::string getTimeBinLabel(const double &tedges, const int &it)
Get time bin label string.
void fit(TH1D *&hist, double &mean, double &meanErr, double &sigma, double &sigmaErr)
Perform full Gaussian fit and extract parameters.
double m_eaMin
lower edge of entrance angle
A calibration algorithm for CDC dE/dx wire gains.
void getTruncatedBins(TH1D *hdedxhit, unsigned int &binlow, unsigned int &binhigh)
function to get bins of truncation from histogram
static double getTruncationMean(TH1D *hdedxhit, int binlow, int binhigh)
function to get mean of truncation from histogram
The Class for CDC Geometry Parameters.
unsigned nWiresInLayer(int layerId) const
Returns wire numbers in a layer.
static CDCGeometryPar & Instance(const CDCGeometry *=nullptr)
Static method to get a reference to the CDCGeometryPar instance.
static void updateDBObjPtrs(const unsigned int event, const int run, const int experiment)
Updates any DBObjPtrs by calling update(event) for DBStore.
void setDescription(const std::string &description)
Set algorithm description (in constructor)
const std::vector< Calibration::ExpRun > & getRunList() const
Get the list of runs for which calibration is called.
EResult
The result of calibration.
@ c_OK
Finished successfully =0 in Python.
@ c_NotEnoughData
Needs more data =2 in Python.
CalibrationAlgorithm(const std::string &collectorModuleName)
Constructor - sets the prefix for collected objects (won't be accesses until execute(....
static Configuration & getInstance()
Get a reference to the instance which will be used when the Database is initialized.
bool isValid() const
Check whether a valid object was obtained from the database.
Class for accessing objects in the database.
Definition DBObjPtr.h:21
Singleton class to cache database objects.
Definition DBStore.h:31
static DataStore & Instance()
Instance of singleton Store.
Definition DataStore.cc:53
void setInitializeActive(bool active)
Setter for m_initializeActive.
Definition DataStore.cc:93
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
Definition DataStore.cc:85
Store event, run, and experiment numbers.
void setEvent(unsigned int event)
Event Setter.
void setExperiment(int experiment)
Experiment Setter.
void setRun(int run)
Run Setter.
Type-safe access to single objects in the data store.
Definition StoreObjPtr.h:96
std::shared_ptr< T > getObjectPtr(const std::string &name, const std::vector< Calibration::ExpRun > &requestedRuns)
Get calibration data object by name and list of runs, the Merge function will be called to generate t...
void reset(bool keepEntries=false)
Invalidate all payloads.
Definition DBStore.cc:175
static Database & Instance()
Instance of a singleton Database.
Definition Database.cc:42
static DBStore & Instance()
Instance of a singleton DBStore.
Definition DBStore.cc:26
void updateEvent()
Updates all intra-run dependent objects.
Definition DBStore.cc:140
void update()
Updates all objects that are outside their interval of validity.
Definition DBStore.cc:77
static void reset(bool keepConfig=false)
Reset the database instance.
Definition Database.cc:50
Abstract base class for different kinds of events.
Container for cosine gain data.
Container for 1D gain data.
Container for wire gain data.