Belle II Software development
CDCDedxCosineAlgorithm.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/CDCDedxCosineAlgorithm.h>
10
11#include <TF1.h>
12#include <TLine.h>
13#include <TCanvas.h>
14#include <TH1I.h>
15#include <vector>
16
17using namespace Belle2;
18
19//-----------------------------------------------------------------
20// Implementation
21//-----------------------------------------------------------------
23 CalibrationAlgorithm("CDCDedxElectronCollector"),
24 isMethodSep(true),
25 isMakePlots(true),
26 isMergePayload(true),
27 m_sigLim(2.5),
28 m_cosBin(100),
29 m_cosMin(-1.0),
30 m_cosMax(1.0),
31 m_dedxBin(250),
32 m_dedxMin(0.0),
33 m_dedxMax(5.0),
34 m_suffix("")
35
36{
37 // Set module properties
38 setDescription("A calibration algorithm for CDC dE/dx electron cos(theta) dependence");
39
40}
41
42//-----------------------------------------------------------------
43// Run the calibration
44//-----------------------------------------------------------------
46{
47
49
50 if (!m_DBCosineCor.isValid())
51 B2FATAL("There is no valid previous payload for CDCDedxCosineCor");
52
53 B2INFO("Preparing dE/dx calibration for CDC dE/dx electron saturation");
54
55 // Get data objects
56 auto ttree = getObjectPtr<TTree>("tree");
57 if (!ttree) {
58 B2ERROR("Input tree 'tree' not found");
59 return c_Failure;
60 }
61 if (ttree->GetEntries() < 100)return c_NotEnoughData;
62
63 double dedx, costh; int charge;
64 ttree->SetBranchAddress("dedx", &dedx);
65 ttree->SetBranchAddress("costh", &costh);
66 ttree->SetBranchAddress("charge", &charge);
67
68
69 // make histograms to store dE/dx values in bins of cos(theta)
70 // bin size can be arbitrary, but for now just make uniform bins
71 std::vector<TH1D*> hDedxCos_neg, hDedxCos_pos, hDedxCos_all;
72
73 const double binW = (m_cosMax - m_cosMin) / m_cosBin;
74
75 defineHisto(hDedxCos_neg, "neg", "e-");
76 defineHisto(hDedxCos_pos, "pos", "e+");
77 defineHisto(hDedxCos_all, "all", "e-,e+");
78
79 // fill histograms, bin size may be arbitrary
80 TH1D* hCosth_neg = defineCosthHist("neg");
81 TH1D* hCosth_pos = defineCosthHist("pos");
82 TH1D* hCosth_all = defineCosthHist("all");
83
84 for (int i = 0; i < ttree->GetEntries(); ++i) {
85
86 ttree->GetEvent(i);
87
88 //if track is a junk
89 if (dedx <= 0 || charge == 0) continue;
90
91 //if track is in CDC accpetance (though it is inbuilt in collector module)
92 if (costh < TMath::Cos(150 * TMath::DegToRad()) || costh > TMath::Cos(17 * TMath::DegToRad())) continue;
93
94 int bin = int((costh - m_cosMin) / binW);
95 if (bin < 0 || bin >= static_cast<int>(m_cosBin)) continue;
96
97 if (isMethodSep) {
98 if (charge < 0) {
99 hCosth_neg->Fill(costh);
100 hDedxCos_neg[bin]->Fill(dedx);
101 } else if (charge > 0) {
102 hCosth_pos->Fill(costh);
103 hDedxCos_pos[bin]->Fill(dedx);
104 }
105 } else {
106 hCosth_all->Fill(costh);
107 hDedxCos_all[bin]->Fill(dedx);
108 }
109 }
110
111 // fit histograms to get gains in bins of cos(theta)
112 std::vector<double> cosine;
113
114 std::vector<std::vector<double>> dedxAll(4);
115 std::vector<std::vector<double>> dedxNeg(4);
116 std::vector<std::vector<double>> dedxPos(4);
117
118 for (unsigned int i = 0; i < m_cosBin; ++i) {
119
120 double meanDedx = 1.0; //This is what we need for calibration
121 // cppcheck-suppress unreadVariable ; overwritten before it is read
122 // cppcheck-suppress variableScope ; kept next to the related declarations for readability
123 double meanDedxErr = 0.0;
124
125 if (!isMethodSep) {
126 FitValues fitAll = fitHistogram(hDedxCos_all[i]);
127
128 meanDedx = fitAll.mean;
129
130 dedxAll[0].push_back(fitAll.mean);
131 dedxAll[1].push_back(fitAll.meanErr);
132 dedxAll[2].push_back(fitAll.sigma);
133 dedxAll[3].push_back(fitAll.sigmaErr);
134
135 } else {
136
137 //Fit electron dE/dx in cos bins
138 FitValues fitNeg = fitHistogram(hDedxCos_neg[i]);
139
140 //Fit positron dE/dx in cos bins
141 FitValues fitPos = fitHistogram(hDedxCos_pos[i]);
142
143 if (fitPos.status != "FitOK" && fitNeg.status == "FitOK") {
144 fitPos.mean = fitNeg.mean;
145 hDedxCos_pos[i]->SetTitle(Form("%s, mean (manual) = elec left", hDedxCos_pos[i]->GetTitle()));
146 } else if (fitNeg.status != "FitOK" && fitPos.status == "FitOK") {
147 fitNeg.mean = fitPos.mean;
148 hDedxCos_neg[i]->SetTitle(Form("%s, mean (manual) = posi right", hDedxCos_neg[i]->GetTitle()));
149 } else if (fitNeg.status != "FitOK" && fitPos.status != "FitOK") {
150 fitNeg.mean = 1.0;
151 fitPos.mean = 1.0;
152 }
153
154 dedxNeg[0].push_back(fitNeg.mean);
155 dedxNeg[1].push_back(fitNeg.meanErr);
156 dedxNeg[2].push_back(fitNeg.sigma);
157 dedxNeg[3].push_back(fitNeg.sigmaErr);
158
159 dedxPos[0].push_back(fitPos.mean);
160 dedxPos[1].push_back(fitPos.meanErr);
161 dedxPos[2].push_back(fitPos.sigma);
162 dedxPos[3].push_back(fitPos.sigmaErr);
163
164 meanDedx = 0.5 * (fitNeg.mean + fitPos.mean);
165 if (meanDedx <= 0.0) meanDedx = 1.0;
166
167 meanDedxErr = 0.5 * TMath::Sqrt(fitNeg.meanErr * fitNeg.meanErr +
168 fitPos.meanErr * fitPos.meanErr);
169
170 dedxAll[0].push_back(meanDedx);
171 dedxAll[1].push_back(meanDedxErr);
172
173 }
174
175 cosine.push_back(meanDedx);
176 }
177
178 createPayload(cosine);
179
180
181 if (isMakePlots) {
182
183 //1. dE/dx dist. for cosine bins
184 plotdedxHist(hDedxCos_all, hDedxCos_neg, hDedxCos_pos);
185
186 //4. costh distribution
187 plotCosThetaDist(hCosth_all, hCosth_pos, hCosth_neg);
188
189 plotFitResults(dedxAll, dedxNeg, dedxPos);
190
191 //7. plot statistics related plots here
193
194 //6. draw the final constants
196 }
197
198 m_suffix.clear();
199 m_coscors.clear();
200
201 return c_OK;
202}
203
204//--------------------------------------------------
206{
207
208 int cruns = 0;
209 for (auto expRun : getRunList()) {
210 if (cruns == 0) B2INFO("CDCDedxCosineCor: start exp " << expRun.first << " and run " << expRun.second << "");
211 cruns++;
212 }
213
214 const auto erStart = getRunList()[0];
215 int estart = erStart.first;
216 int rstart = erStart.second;
217
218 const auto erEnd = getRunList()[cruns - 1];
219 int rend = erEnd.second;
220
221 updateDBObjPtrs(1, rstart, estart);
222
223 if (m_suffix.length() > 0) m_suffix = Form("%s_e%d_r%dr%d", m_suffix.data(), estart, rstart, rend);
224 else m_suffix = Form("e%d_r%dr%d", estart, rstart, rend);
225}
226
227//--------------------------------------------------
228void CDCDedxCosineAlgorithm::defineHisto(std::vector<TH1D*>& hdedx, const std::string& tag,
229 const std::string& chargeLabel)
230{
231
232 const double binW = (m_cosMax - m_cosMin) / m_cosBin;
233
234 hdedx.reserve(m_cosBin);
235
236 for (unsigned int i = 0; i < m_cosBin; ++i) {
237 double coslow = i * binW + m_cosMin;
238 double coshigh = coslow + binW;
239
240 hdedx.push_back(new TH1D(Form("hDedxCos_%s_bin%d_%s", tag.c_str(), i, m_suffix.data()), "", m_dedxBin, m_dedxMin, m_dedxMax));
241
242 hdedx[i]->SetTitle(Form("dE/dx dist (%s) in costh (%0.02f, %0.02f);dE/dx (no had sat, for %s);Entries", chargeLabel.c_str(), coslow,
243 coshigh, chargeLabel.c_str()));
244
245 }
246}
247
248//--------------------------------------------------
249TH1D* CDCDedxCosineAlgorithm::defineCosthHist(const std::string& tag)
250{
251
252 TH1D* hist = new TH1D(Form("hCosth_%s_%s", tag.c_str(), m_suffix.data()), " ", m_cosBin, m_cosMin, m_cosMax);
253 hist->SetTitle("cos(#theta) dist (e- and e+); cos(#theta); Entries");
254
255 return hist;
256}
257
258//----------------------------------------
260{
261 FitValues fitValues;
262
263 fitGaussianWithRange(hist, fitValues.status);
264
265 hist->SetFillColorAlpha(kAzure + 1, 0.30);
266
267 if (fitValues.status == "FitOK") {
268 TF1* fitFunc = hist->GetFunction("gaus");
269 if (fitFunc) {
270 fitValues.mean = fitFunc->GetParameter(1);
271 fitValues.meanErr = fitFunc->GetParError(1);
272 fitValues.sigma = fitFunc->GetParameter(2);
273 fitValues.sigmaErr = fitFunc->GetParError(2);
274
275 std::string fitSummary = Form("#mu_{fit}: %0.03f #pm %0.03f, #sigma_{fit}: %0.03f",
276 fitValues.mean, fitValues.meanErr, fitValues.sigma);
277
278 hist->SetTitle(Form("%s, %s", hist->GetTitle(), fitSummary.data()));
279 }
280 }
281
282 return fitValues;
283}
284
285//--------------------------------------------------
286void CDCDedxCosineAlgorithm::fitGaussianWithRange(TH1D*& temphist, TString& status)
287{
288 if (temphist->Integral() < 2000) { //atleast 1k bhabha events
289 B2INFO(Form("\tThis hist (%s) have insufficient entries to perform fit (%0.03f)", temphist->GetName(), temphist->Integral()));
290 status = "LowStats";
291 return;
292 } else {
293 temphist->GetXaxis()->SetRange(temphist->FindFirstBinAbove(0, 1), temphist->FindLastBinAbove(0, 1));
294 int fs = temphist->Fit("gaus", "QR");
295 if (fs != 0) {
296 B2INFO(Form("\tFit (round 1) for hist (%s) failed (status = %d)", temphist->GetName(), fs));
297 status = "FitFailed";
298 return;
299 } else {
300 double meanDedx = temphist->GetFunction("gaus")->GetParameter(1);
301 double width = temphist->GetFunction("gaus")->GetParameter(2);
302 temphist->GetXaxis()->SetRangeUser(meanDedx - 5.0 * width, meanDedx + 5.0 * width);
303 fs = temphist->Fit("gaus", "QR", "", meanDedx - m_sigLim * width, meanDedx + m_sigLim * width);
304 if (fs != 0) {
305 B2INFO(Form("\tFit (round 2) for hist (%s) failed (status = %d)", temphist->GetName(), fs));
306 status = "FitFailed";
307 return;
308 } else {
309 temphist->GetXaxis()->SetRangeUser(meanDedx - 5.0 * width, meanDedx + 5.0 * width);
310 B2INFO(Form("\tFit for hist (%s) sucessfull (status = %d)", temphist->GetName(), fs));
311 status = "FitOK";
312 }
313 }
314 }
315}
316
317//--------------------------------------------------
318void CDCDedxCosineAlgorithm::createPayload(const std::vector<double>& cosine)
319{
320 m_coscors.resize(m_kNGroups);
321
322 for (unsigned int il = 0; il < m_kNGroups; il++) {
323
324 unsigned int nbins = m_DBCosineCor->getSize(getRepresentativeLayer(il));
325
326 if (nbins != m_cosBin)
327 B2ERROR("merging failed because of unmatch bins (old "
328 << nbins << " new " << m_cosBin << ")");
329
330 m_coscors[il].reserve(nbins);
331
332 for (unsigned int ibin = 0; ibin < nbins; ibin++) {
333
334 double value = cosine[ibin];
335
336 if (isMergePayload) {
337 double prev = m_DBCosineCor->getMean(getRepresentativeLayer(il), ibin);
338
339 value *= prev;
340
341 B2INFO("Cosine Corr for " << m_label[il]
342 << " Bin # " << ibin
343 << ", Previous = " << prev
344 << ", Relative = " << cosine[ibin]
345 << ", Merged = " << value);
346 }
347
348 m_coscors[il].push_back(value);
349 }
350 }
351
352 //Saving constants
353 B2INFO("dE/dx calibration done for CDC dE/dx electron saturation");
354
355 std::vector<unsigned int> layerToGroup(56);
356
357 for (unsigned int layer = 0; layer < 56; layer++) {
358 if (layer < 8) layerToGroup[layer] = 0; // SL0
359 else if (layer < 14) layerToGroup[layer] = 1; // SL1
360 else layerToGroup[layer] = 2; // SL2-8
361 }
362
363 CDCDedxCosineCor* gain = new CDCDedxCosineCor(m_coscors, layerToGroup);
364 saveCalibration(gain, "CDCDedxCosineCor");
365}
366
367//--------------------------------------------------
368void CDCDedxCosineAlgorithm::plotdedxHist(std::vector<TH1D*>& hDedxCos_all,
369 std::vector<TH1D*>& hDedxCos_neg,
370 std::vector<TH1D*>& hDedxCos_pos)
371{
372
373 TCanvas ctmp("tmp", "tmp", 1200, 1200);
374 int nx = 2;
375 int ny = isMethodSep ? 1 : 2;
376 unsigned int nPads = nx * ny;
377 if (isMethodSep) ctmp.SetCanvasSize(1200, 600);
378 ctmp.Divide(nx, ny);
379 std::stringstream psname;
380
381 psname << Form("cdcdedx_coscorr_dedx_%s.pdf[", m_suffix.data());
382 ctmp.Print(psname.str().c_str());
383 psname.str("");
384 psname << Form("cdcdedx_coscorr_dedx_%s.pdf", m_suffix.data());
385
386 for (unsigned int ic = 0; ic < m_cosBin; ic++) {
387 if (!isMethodSep) {
388 ctmp.cd(ic % nPads + 1);
389 hDedxCos_all[ic]->SetStats(0);
390 hDedxCos_all[ic]->SetFillColorAlpha(kYellow, 0.25);
391 hDedxCos_all[ic]->DrawCopy();
392
393 if (ic % nPads == nPads - 1 || ic == m_cosBin - 1) {
394 ctmp.Print(psname.str().c_str());
395 ctmp.Clear();
396 ctmp.Divide(nx, ny);
397 }
398 } else {
399
400 // left: electron
401 ctmp.cd(1);
402 hDedxCos_neg[ic]->SetFillColorAlpha(kRed, 0.25);
403 hDedxCos_neg[ic]->DrawCopy();
404
405
406 // right: positron
407 ctmp.cd(2);
408 hDedxCos_pos[ic]->SetFillColorAlpha(kBlue, 0.25);
409 hDedxCos_pos[ic]->DrawCopy();
410
411 ctmp.Print(psname.str().c_str());
412 ctmp.Clear();
413 ctmp.Divide(nx, ny);
414
415 }
416
417 }
418 psname.str("");
419 psname << Form("cdcdedx_coscorr_dedx_%s.pdf]", m_suffix.data());
420 ctmp.Print(psname.str().c_str());
421}
422
423//--------------------------------------------------
424void CDCDedxCosineAlgorithm::plotCosThetaDist(TH1D* hCosth_all, TH1D* hCosth_pos, TH1D* hCosth_neg)
425{
426
427 TCanvas ceadist("ceadist", "Cosine distributions", 800, 600);
428 ceadist.cd();
429
430
431 // If method separation, overlay pos/neg
432 if (isMethodSep) {
433 TLegend* leg = new TLegend(0.6, 0.7, 0.8, 0.9);
434
435 if (hCosth_neg) {
436 hCosth_neg->SetLineColor(kRed);
437 hCosth_neg->SetFillColorAlpha(kYellow, 0.55);
438 hCosth_neg->SetStats(0);
439 hCosth_neg->Draw("hist");
440 leg->AddEntry(hCosth_neg, "neg", "f");
441 }
442 if (hCosth_pos) {
443 hCosth_pos->SetLineColor(kBlue);
444 hCosth_pos->SetFillColorAlpha(kGray, 0.35);
445 hCosth_pos->SetStats(0);
446 hCosth_pos->Draw("hist same");
447 leg->AddEntry(hCosth_pos, "pos", "f");
448 }
449 leg->Draw();
450
451 } else {
452 // Always draw ALL first
453 if (hCosth_all) {
454 hCosth_all->SetFillColorAlpha(kGray, 0.25);
455 hCosth_all->SetLineColor(kGray);
456 hCosth_all->SetStats(0);
457 hCosth_all->Draw("hist");
458 }
459 }
460
461 ceadist.SaveAs(Form("cdcdedx_coscorr_cosine_%s.pdf", m_suffix.data()));
462 ceadist.SaveAs(Form("cdcdedx_coscorr_cosine_%s.root", m_suffix.data()));
463}
464
465
466//--------------------------------------------------
467void CDCDedxCosineAlgorithm::plotFitResults(const std::vector<std::vector<double>>& dedxAll,
468 const std::vector<std::vector<double>>& dedxNeg,
469 const std::vector<std::vector<double>>& dedxPos)
470{
471 // Fill histograms
472
473 TH1D* hMean_all = new TH1D("hMean_all", "mean vs cos#theta;cos#theta;mean", m_cosBin, m_cosMin, m_cosMax);
474
475 TH1D* hMean_el = new TH1D("hMean_el", "mean (e-);cos#theta;mean", m_cosBin, m_cosMin, m_cosMax);
476
477 TH1D* hMean_po = new TH1D("hMean_po", "mean (e+);cos#theta;mean", m_cosBin, m_cosMin, m_cosMax);
478
479
480 TH1D* hSig_all = new TH1D("hSig_all", "sigma vs cos#theta;cos#theta;#sigma", m_cosBin, m_cosMin, m_cosMax);
481
482 TH1D* hSig_el = new TH1D("hSig_el", "sigma (e-);cos#theta;#sigma", m_cosBin, m_cosMin, m_cosMax);
483
484 TH1D* hSig_po = new TH1D("hSig_po", "sigma (e+);cos#theta;#sigma", m_cosBin, m_cosMin, m_cosMax);
485
486
487 for (unsigned int i = 0; i < m_cosBin; i++) {
488 hMean_all->SetBinContent(i + 1, dedxAll[0][i]);
489 hMean_all->SetBinError(i + 1, dedxAll[1][i]);
490
491 if (isMethodSep) {
492 hMean_el->SetBinContent(i + 1, dedxNeg[0][i]);
493 hMean_el->SetBinError(i + 1, dedxNeg[1][i]);
494 hSig_el->SetBinContent(i + 1, dedxNeg[2][i]);
495 hSig_el->SetBinError(i + 1, dedxNeg[3][i]);
496
497 hMean_po->SetBinContent(i + 1, dedxPos[0][i]);
498 hMean_po->SetBinError(i + 1, dedxPos[1][i]);
499 hSig_po->SetBinContent(i + 1, dedxPos[2][i]);
500 hSig_po->SetBinError(i + 1, dedxPos[3][i]);
501 } else {
502 hSig_all->SetBinContent(i + 1, dedxAll[2][i]);
503 hSig_all->SetBinError(i + 1, dedxAll[3][i]);
504 }
505
506 }
507
508 TCanvas* ctmp = new TCanvas("c_fit", "Mean & Sigma", 1000, 500);
509 ctmp->Divide(2, 1);
510 ctmp->cd(1);
511 gPad->SetGridy(1);
512
513 setHist(hMean_all, kBlack, "dedx rel(#mu_{fit}) for e- and e+ combined", 0.97, 1.04);
514
515 if (isMethodSep) {
516
517 setHist(hMean_el, kRed, "comparison of dedx #mu_{fit}^{rel}", 0.96, 1.04);
518 setHist(hMean_po, kBlue, "", 0.96, 1.04);
519
520 hMean_el->Draw("E1");
521 hMean_po->Draw("E1 same");
522 hMean_all->Draw("E1 same");
523
524 } else {
525 hMean_all->Draw("E1");
526 }
527
528 ctmp->cd(2);
529 gPad->SetGridy(1);
530
531 setHist(hSig_all, kBlack, "dedx rel(#sigma_{fit}) for e- and e+ combined", 0.05, 0.23);
532
533 if (isMethodSep) {
534
535 setHist(hSig_el, kRed, "comparison of dedx #sigma_{fit}^{rel}", 0.05, 0.23, 24);
536 setHist(hSig_po, kBlue, "", 0.05, 0.23, 25);
537
538 hSig_el->Draw("E1");
539 hSig_po->Draw("E1 same");
540
541 } else {
542 hSig_all->Draw("E1");
543 }
544 B2INFO("Plotting finished ");
545
546
547 ctmp->SaveAs(Form("cdcdedx_coscorr_fit_%s.pdf", m_suffix.data()));
548 delete hMean_all;
549 delete hMean_el;
550 delete hMean_po;
551 delete hSig_all;
552 delete hSig_el;
553 delete hSig_po;
554 delete ctmp;
555}
556
557//--------------------------------------------------
559{
560
561 const std::string pdfName =
562 Form("cdcdedx_coscorr_fconsts_%s.pdf", m_suffix.data());
563
564 const std::string rootName =
565 Form("cdcdedx_coscorr_fconsts_%s.root", m_suffix.data());
566
567 TFile rootFile(rootName.c_str(), "RECREATE");
568
569 for (int il = 0; il < m_kNGroups; il++) {
570
571 unsigned int nbins = m_DBCosineCor->getSize(getRepresentativeLayer(il));
572
573 // --- Create histograms ---
574 TH1D* hnew = new TH1D(Form("hnew_%s", m_label[il].data()), Form("Final const: %s;cos(#theta);dedx #mu_{fit}", m_label[il].data()),
576 m_cosMax);
577
578 TH1D* hold = new TH1D(Form("hold_%s", m_label[il].data()), Form("Final const: %s;cos(#theta);dedx #mu_{fit}", m_label[il].data()),
580 m_cosMax);
581
582 for (unsigned int iea = 0; iea < nbins; iea++) {
583 double oldv = m_DBCosineCor->getMean(getRepresentativeLayer(il), iea);
584 double newv = m_coscors[il][iea];
585
586 hold->SetBinContent(iea + 1, oldv);
587 hnew->SetBinContent(iea + 1, newv);
588 }
589
590 // --- Ratio ---
591 TH1D* hratio = static_cast<TH1D*>(hnew->Clone(Form("hratio_%s", m_label[il].data())));
592 hratio->Divide(hold);
593
594 TCanvas c(Form("c_%s", m_label[il].data()), Form("Final constants %s", m_label[il].data()), 1000, 500);
595 c.Divide(2, 1);
596 c.cd(1);
597 gPad->SetGridy(1);
598 gPad->SetGridx(1);
599
600 hnew->SetLineColor(kBlack);
601 hnew->SetStats(0);
602 hold->SetLineColor(kRed);
603 hold->SetStats(0);
604
605 double min = std::min(hnew->GetMinimum(), hold->GetMinimum());
606 double max = std::max(hnew->GetMaximum(), hold->GetMaximum());
607 hnew->GetYaxis()->SetRangeUser(min * 0.95, max * 1.05);
608
609 hnew->Draw("hist");
610 hold->Draw("hist same");
611
612 auto leg = new TLegend(0.6, 0.75, 0.85, 0.88);
613 leg->SetBorderSize(0);
614 leg->SetFillStyle(0);
615 leg->AddEntry(hnew, "New", "l");
616 leg->AddEntry(hold, "Old", "l");
617 leg->Draw();
618
619 c.cd(2);
620 gPad->SetGridy(1);
621 hratio->SetLineColor(kBlue);
622 hratio->SetStats(0);
623 hratio->SetTitle(Form("Ratio: new/old, %s;cos(#theta); New / Old", m_label[il].data()));
624 hratio->GetYaxis()->SetRangeUser(0.8, 1.2);
625 hratio->Draw("hist");
626
627 TLine* line = new TLine(m_cosMin, 1.0, m_cosMax, 1.0);
628 line->SetLineStyle(2);
629 line->Draw();
630
631 c.Update();
632
633 if (il == 0) {
634 c.Print((pdfName + "(").c_str());
635 } else if (il == m_kNGroups - 1) {
636 c.Print((pdfName + ")").c_str());
637 } else {
638 c.Print(pdfName.c_str());
639 }
640
641 // Save this canvas in the ROOT file
642 rootFile.cd();
643 c.Write();
644
645 // cleanup
646 delete hnew;
647 delete hold;
648 delete hratio;
649 delete line;
650 }
651}
652
653//------------------------------------
655{
656
657 TCanvas cstats("cstats", "cstats", 1000, 500);
658 cstats.SetBatch(kTRUE);
659 cstats.Divide(2, 1);
660
661 cstats.cd(1);
662 auto hestats = getObjectPtr<TH1I>("hestats");
663 if (hestats) {
664 hestats->SetName(Form("hestats_%s", m_suffix.data()));
665 hestats->SetStats(0);
666 hestats->DrawCopy("");
667 }
668
669 cstats.cd(2);
670 auto htstats = getObjectPtr<TH1I>("htstats");
671 if (htstats) {
672 htstats->SetName(Form("htstats_%s", m_suffix.data()));
673 htstats->SetStats(0);
674 htstats->DrawCopy("");
675 }
676 cstats.Print(Form("cdcdedx_coscorr_stats_%s.pdf", m_suffix.data()));
677}
static void setHist(TH1D *h, int color, const char *title, double ymin, double ymax, int marker=20)
Set basic style (color, marker, title, y-range) for a TH1D histogram.
FitValues fitHistogram(TH1D *&hist)
Fit histogram with Gaussian and return mean, error, and width.
void getExpRunInfo()
function to extract calibration run/exp
TH1D * defineCosthHist(const std::string &tag)
function to define cosine histograms
static constexpr int m_kNGroups
SL grouping: inner (SL0), middle (SL1), outer (SL2–8)
int m_dedxBin
number of bins for dedx histogram
double m_cosMax
max cosine angle for cal
void plotCosThetaDist(TH1D *hCosth_all, TH1D *hCosth_pos, TH1D *hCosth_neg)
Plot cos(theta) distributions for all, positive, and negative tracks.
bool isMergePayload
merge payload at the time of calibration
static unsigned int getRepresentativeLayer(unsigned int igroup)
Representative CDC layer for each SL group (used to access group-wise constants): SL0 => 1,...
std::string m_suffix
add suffix to all plot name
DBObjPtr< CDCDedxCosineCor > m_DBCosineCor
Electron saturation correction DB object.
void plotConstants()
function to draw the old/new final constants
CDCDedxCosineAlgorithm()
Constructor: Sets the description, the properties and the parameters of the algorithm.
void fitGaussianWithRange(TH1D *&temphist, TString &status)
function to fit histogram in each cosine bin
const std::array< std::string, m_kNGroups > m_label
add inner/outer superlayer label
double m_cosMin
min cosine angle for cal
void plotEventStats()
function to draw the stats plots
virtual EResult calibrate() override
Cosine algorithm.
void createPayload(const std::vector< double > &cosine)
function to store new payload after full calibration
double m_sigLim
gaussian fit sigma limit
void plotFitResults(const std::vector< std::vector< double > > &dedxAll, const std::vector< std::vector< double > > &dedxNeg, const std::vector< std::vector< double > > &dedxPos)
Plot dE/dx fit results for all, negative, and positive tracks.
void plotdedxHist(std::vector< TH1D * > &hDedxCos_all, std::vector< TH1D * > &hDedxCos_neg, std::vector< TH1D * > &hDedxCos_pos)
function to draw the dE/dx histogram in costh bins
bool isMethodSep
if e+ e- need to be consider sep
double m_dedxMax
max dedx range for gain cal
bool isMakePlots
produce plots for status
double m_dedxMin
min dedx range for gain cal
unsigned int m_cosBin
number of bins across cosine range
void defineHisto(std::vector< TH1D * > &hdedx, const std::string &tag, const std::string &chargeLabel)
function to define dE/dx histograms
std::vector< std::vector< double > > m_coscors
final vectors of calibration
dE/dx cosine gain calibration constants
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
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(....
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...
Abstract base class for different kinds of events.
Container for Gaussian fit results of a histogram.
double meanErr
meanErr : uncertainty on the mean
double sigmaErr
sigmaErr : uncertainty on the width
TString status
status : fit status flag (e.g.