Belle II Software  release-05-01-25
TOPLocalCalFitter.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2019 - Belle II Collaboration *
4  * *
5  * *
6  * Author: The Belle II Collaboration *
7  * Contributors: Umberto Tamponi *
8  * *
9  * This software is provided "as is" without any warranty. *
10  **************************************************************************/
11 
12 #include <top/calibration/TOPLocalCalFitter.h>
13 
14 #include "TH2F.h"
15 #include "TFile.h"
16 #include "TMath.h"
17 #include "TF1.h"
18 #include "TROOT.h"
19 #include "TTree.h"
20 #include "math.h"
21 #include <limits>
22 #include <framework/logging/Logger.h>
23 #include <top/dbobjects/TOPCalChannelT0.h>
24 
25 
26 //using namespace std;
27 using namespace Belle2;
28 using namespace TOP;
29 
30 double crystalball_function(double x, double alpha, double n, double sigma, double mean)
31 {
32  // evaluate the crystal ball function
33  if (sigma < 0.) return 0.;
34  double z = (x - mean) / sigma;
35  if (alpha < 0) z = -z;
36  double abs_alpha = std::abs(alpha);
37  if (z > - abs_alpha)
38  return std::exp(- 0.5 * z * z);
39  else {
40  double nDivAlpha = n / abs_alpha;
41  double AA = std::exp(-0.5 * abs_alpha * abs_alpha);
42  double B = nDivAlpha - abs_alpha;
43  double arg = nDivAlpha / (B - z);
44  return AA * std::pow(arg, n);
45  }
46 }
47 
48 double crystalball_pdf(double x, double alpha, double n, double sigma, double mean)
49 {
50  // evaluation of the PDF ( is defined only for n >1)
51  if (sigma < 0.) return 0.;
52  if (n <= 1) return std::numeric_limits<double>::quiet_NaN(); // pdf is not normalized for n <=1
53  double abs_alpha = std::abs(alpha);
54  double C = n / abs_alpha * 1. / (n - 1.) * std::exp(-alpha * alpha / 2.);
55  double D = std::sqrt(M_PI / 2.) * (1. + erf(abs_alpha / std::sqrt(2.)));
56  double N = 1. / (sigma * (C + D));
57  return N * crystalball_function(x, alpha, n, sigma, mean);
58 }
59 
60 
61 
62 // Two gaussians to model the TTS of the MCP-PMTs.
63 double TTSPDF(double x, double time, double deltaT, double sigma1, double sigma2, double f1)
64 {
65  return f1 * TMath::Gaus(x, time, sigma1, kTRUE) + (1 - f1) * TMath::Gaus(x, time + deltaT, sigma2, kTRUE) ;
66 }
67 
68 
69 // Full PDF to fit the laser, made of:
70 // 2 TTSPDF
71 // 1 crystal ball PDF for the extra peak at +1 ns we don't understand
72 // 1 gaussian to help modelling the tail
73 double laserPDF(double* x, double* p)
74 {
75  double time = p[0];
76  double sigma = p[1];
77  double fraction = p[2];
78  double deltaTLaser = p[3];
79  double sigmaRatio = p[4];
80  double deltaTTS = p[5];
81  double f1 = p[6];
82  double norm = p[7];
83 
84  double deltaTExtra = p[8];
85  double sigmaExtra = p[9];
86  double normExtra = p[10];
87 
88  double deltaTBkg = p[11];
89  double sigmaBkg = p[12];
90  double bkg = p[13];
91 
92  double alpha = p[14];
93  double n = p[15];
94 
95  double mainPeak = fraction * TTSPDF(x[0], time, deltaTTS, sigma, TMath::Sqrt(sigma * sigma + sigmaRatio * sigmaRatio), f1);
96  double secondaryPeak = (1. - fraction) * TTSPDF(x[0], time + deltaTLaser, deltaTTS, sigma,
97  TMath::Sqrt(sigma * sigma + sigmaRatio * sigmaRatio), f1);
98  double extraPeak = crystalball_pdf(x[0], alpha, n, sigmaExtra, time + deltaTExtra);
99  double background = TMath::Gaus(x[0], time + deltaTBkg + deltaTTS, sigmaBkg, kTRUE);
100 
101  return norm * (mainPeak + secondaryPeak) + normExtra * extraPeak + bkg * background;
102 }
103 
104 
106 {
108  "Perform the fit of the laser and pulser runs"
109  );
110 
111 }
112 
113 
114 
116 {
117  m_inputTTS = TFile::Open(m_TTSData.c_str());
118  m_inputConstraints = TFile::Open(m_fitConstraints.c_str());
119 
120  B2INFO("Getting the TTS parameters from " << m_TTSData);
121  m_inputTTS->cd();
122  m_inputTTS->GetObject("tree", m_treeTTS);
123  m_treeTTS->SetBranchAddress("mean2", &m_mean2);
124  m_treeTTS->SetBranchAddress("sigma1", &m_sigma1);
125  m_treeTTS->SetBranchAddress("sigma2", &m_sigma2);
126  m_treeTTS->SetBranchAddress("fraction1", &m_f1);
127  m_treeTTS->SetBranchAddress("fraction2", &m_f2);
128  m_treeTTS->SetBranchAddress("pixelRow", &m_pixelRow);
129  m_treeTTS->SetBranchAddress("pixelCol", &m_pixelCol);
130 
131  if (m_fitterMode == "MC")
132  std::cout << "Running in MC mode, not constraints will be set" << std::endl;
133  else {
134  B2INFO("Getting the laser fit parameters from " << m_fitConstraints);
135  m_inputConstraints->cd();
136  m_inputConstraints->GetObject("fitTree", m_treeConstraints);
137  m_treeConstraints->SetBranchAddress("peakTime", &m_peakTimeConstraints);
138  m_treeConstraints->SetBranchAddress("deltaT", &m_deltaTConstraints);
139  m_treeConstraints->SetBranchAddress("fraction", &m_fractionConstraints);
140  if (m_fitterMode == "monitoring") {
141  m_treeConstraints->SetBranchAddress("timeExtra", &m_timeExtraConstraints);
142  m_treeConstraints->SetBranchAddress("sigmaExtra", &m_sigmaExtraConstraints);
143  m_treeConstraints->SetBranchAddress("alphaExtra", &m_alphaExtraConstraints);
144  m_treeConstraints->SetBranchAddress("nExtra", &m_nExtraConstraints);
145  m_treeConstraints->SetBranchAddress("timeBackground", &m_timeBackgroundConstraints);
146  m_treeConstraints->SetBranchAddress("sigmaBackground", &m_sigmaBackgroundConstraints);
147  }
148  }
149  return;
150 }
151 
152 
154 {
155  m_histFile = new TFile(m_output.c_str(), "recreate");
156  m_histFile->cd();
157  m_fitTree = new TTree("fitTree", "fitTree");
158  m_fitTree->Branch<short>("channel", &m_channel);
159  m_fitTree->Branch<short>("slot", &m_slot);
160  m_fitTree->Branch<short>("row", &m_row);
161  m_fitTree->Branch<short>("col", &m_col);
162  m_fitTree->Branch<float>("peakTime", &m_peakTime);
163  m_fitTree->Branch<float>("peakTimeErr", &m_peakTimeErr);
164  m_fitTree->Branch<float>("deltaT", &m_deltaT);
165  m_fitTree->Branch<float>("deltaTErr", &m_deltaTErr);
166  m_fitTree->Branch<float>("sigma", &m_sigma);
167  m_fitTree->Branch<float>("sigmaErr", &m_sigmaErr);
168  m_fitTree->Branch<float>("fraction", &m_fraction);
169  m_fitTree->Branch<float>("fractionErr", &m_fractionErr);
170  m_fitTree->Branch<float>("yieldLaser", &m_yieldLaser);
171  m_fitTree->Branch<float>("yieldLaserErr", &m_yieldLaserErr);
172  m_fitTree->Branch<float>("timeExtra", &m_timeExtra);
173  m_fitTree->Branch<float>("sigmaExtra", &m_sigmaExtra);
174  m_fitTree->Branch<float>("nExtra", &m_nExtra);
175  m_fitTree->Branch<float>("alphaExtra", &m_alphaExtra);
176  m_fitTree->Branch<float>("yieldLaserExtra", &m_yieldLaserExtra);
177  m_fitTree->Branch<float>("timeBackground", &m_timeBackground);
178  m_fitTree->Branch<float>("sigmaBackground", &m_sigmaBackground);
179  m_fitTree->Branch<float>("yieldLaserBackground", &m_yieldLaserBackground);
180 
181  m_fitTree->Branch<float>("fractionMC", &m_fractionMC);
182  m_fitTree->Branch<float>("deltaTMC", &m_deltaTMC);
183  m_fitTree->Branch<float>("peakTimeMC", &m_peakTimeMC);
184  m_fitTree->Branch<float>("firstPulserTime", &m_firstPulserTime);
185  m_fitTree->Branch<float>("firstPulserSigma", &m_firstPulserSigma);
186  m_fitTree->Branch<float>("secondPulserTime", &m_secondPulserTime);
187  m_fitTree->Branch<float>("secondPulserSigma", &m_secondPulserSigma);
188  m_fitTree->Branch<short>("fitStatus", &m_fitStatus);
189 
190  m_fitTree->Branch<float>("chi2", &m_chi2);
191  m_fitTree->Branch<float>("rms", &m_rms);
192 
193 
195  m_timewalkTree = new TTree("timewalkTree", "timewalkTree");
196 
197  m_timewalkTree->Branch<float>("binLowerEdge", &m_binLowerEdge);
198  m_timewalkTree->Branch<float>("binUpperEdge", &m_binUpperEdge);
199  m_timewalkTree->Branch<short>("channel", &m_channel);
200  m_timewalkTree->Branch<short>("slot", &m_slot);
201  m_timewalkTree->Branch<short>("row", &m_row);
202  m_timewalkTree->Branch<short>("col", &m_col);
203  m_timewalkTree->Branch<float>("histoIntegral", &m_histoIntegral);
204  m_timewalkTree->Branch<float>("peakTime", &m_peakTime);
205  m_timewalkTree->Branch<float>("peakTimeErr", &m_peakTimeErr);
206  m_timewalkTree->Branch<float>("deltaT", &m_deltaT);
207  m_timewalkTree->Branch<float>("deltaTErr", &m_deltaTErr);
208  m_timewalkTree->Branch<float>("sigma", &m_sigma);
209  m_timewalkTree->Branch<float>("sigmaErr", &m_sigmaErr);
210  m_timewalkTree->Branch<float>("fraction", &m_fraction);
211  m_timewalkTree->Branch<float>("fractionErr", &m_fractionErr);
212  m_timewalkTree->Branch<float>("yieldLaser", &m_yieldLaser);
213  m_timewalkTree->Branch<float>("yieldLaserErr", &m_yieldLaserErr);
214  m_timewalkTree->Branch<float>("timeExtra", &m_timeExtra);
215  m_timewalkTree->Branch<float>("sigmaExtra", &m_sigmaExtra);
216  m_timewalkTree->Branch<float>("nExtra", &m_nExtra);
217  m_timewalkTree->Branch<float>("alphaExtra", &m_alphaExtra);
218  m_timewalkTree->Branch<float>("yieldLaserExtra", &m_yieldLaserExtra);
219  m_timewalkTree->Branch<float>("timeBackground", &m_timeBackground);
220  m_timewalkTree->Branch<float>("sigmaBackground", &m_sigmaBackground);
221  m_timewalkTree->Branch<float>("yieldLaserBackground", &m_yieldLaserBackground);
222 
223  m_timewalkTree->Branch<float>("fractionMC", &m_fractionMC);
224  m_timewalkTree->Branch<float>("deltaTMC", &m_deltaTMC);
225  m_timewalkTree->Branch<float>("peakTimeMC", &m_peakTimeMC);
226  m_timewalkTree->Branch<float>("firstPulserTime", &m_firstPulserTime);
227  m_timewalkTree->Branch<float>("firstPulserSigma", &m_firstPulserSigma);
228  m_timewalkTree->Branch<float>("secondPulserTime", &m_secondPulserTime);
229  m_timewalkTree->Branch<float>("secondPulserSigma", &m_secondPulserSigma);
230  m_timewalkTree->Branch<short>("fitStatus", &m_fitStatus);
231 
232  m_timewalkTree->Branch<float>("chi2", &m_chi2);
233  m_timewalkTree->Branch<float>("rms", &m_rms);
234 
235  }
236 
237  return;
238 }
239 
240 
241 
242 
243 void TOPLocalCalFitter::fitChannel(short iSlot, short iChannel, TH1* h_profile)
244 {
245 
246  // loads the TTS infos and the fit constraint for the given channel and slot
247  if (m_fitterMode == "monitoring")
248  m_treeConstraints->GetEntry(iChannel + 512 * iSlot);
249  else if (m_fitterMode == "calibration") // The MC-based constraint file has only slot 1 at the moment
250  m_treeConstraints->GetEntry(iChannel);
251 
252  m_treeTTS->GetEntry(iChannel + 512 * iSlot);
253  // finds the maximum of the hit timing histogram and adjust the histogram range around it (3 ns window)
254  double maxpos = h_profile->GetBinCenter(h_profile->GetMaximumBin());
255  h_profile->GetXaxis()->SetRangeUser(maxpos - 1, maxpos + 2.);
256 
257  // gets the histogram integral to give a starting value to the fitter
258  double integral = h_profile->Integral();
259 
260  // creates the fit function
261  TF1 laser = TF1("laser", laserPDF, maxpos - 1, maxpos + 2., 16);
262 
263  // par[0] = peakTime
264  laser.SetParameter(0, maxpos);
265  laser.SetParLimits(0, maxpos - 0.06, maxpos + 0.06);
266 
267  // par[1] = sigma
268  laser.SetParameter(1, 0.1);
269  laser.SetParLimits(1, 0.05, 0.25);
270  if (m_fitterMode == "MC") {
271  laser.SetParameter(1, 0.02);
272  laser.SetParLimits(1, 0., 0.04);
273  }
274  // par[2] = fraction of the main peak respect to the total
275  laser.SetParameter(2, m_fractionConstraints);
276  laser.SetParLimits(2, 0.5, 1.);
277 
278  // par[3]= time difference between the main and secondary path. fixed to the MC value
279  laser.FixParameter(3, m_deltaTConstraints);
280 
281  // This is an hack: in some channels the MC sees one peak only, while in the data there are clearly
282  // two well distinguished peaks. This will disappear if we'll ever get a better laser simulation.
283  if (m_deltaTConstraints > -0.001) {
284  laser.SetParameter(3, -0.3);
285  laser.SetParLimits(3, -0.4, -0.2);
286  }
287 
288  // par[4] is the quadratic difference of the sigmas of the two TTS gaussians (tail - core)
289  laser.FixParameter(4, TMath::Sqrt(m_sigma2 * m_sigma2 - m_sigma1 * m_sigma1));
290  // par[5] is the position of the second TTS gaussian w/ respect to the first one
291  laser.FixParameter(5, m_mean2);
292  // par[6] is the relative contribution of the second TTS gaussian
293  laser.FixParameter(6, m_f1);
294  if (m_fitterMode == "MC")
295  laser.FixParameter(6, 0);
296 
297  // par[7] is the PDF normalization, = integral*bin width
298  laser.SetParameter(7, integral * 0.005);
299  laser.SetParLimits(7, 0.2 * integral * 0.005, 2.*integral * 0.005);
300 
301  // par[8-10] are the relative position, the sigma and the integral of the extra peak
302  laser.SetParameter(8, 1.);
303  laser.SetParLimits(8, 0.3, 2.);
304  laser.SetParameter(9, 0.2);
305  laser.SetParLimits(9, 0.08, 1.);
306  laser.SetParameter(10, 0.1 * integral * 0.005);
307  laser.SetParLimits(10, 0., 0.2 * integral * 0.005);
308  // par[14-15] are the tail parameters of the crystal ball function used to describe the extra peak
309  laser.SetParameter(14, -2.);
310  laser.SetParameter(15, 2.);
311  laser.SetParLimits(15, 1.01, 20.);
312 
313  // par[11-13] are relative position, sigma and integral of the broad gaussian added to better describe the tail at high times
314  laser.SetParameter(11, 1.);
315  laser.SetParLimits(11, 0.1, 5.);
316  laser.SetParameter(12, 0.8);
317  laser.SetParLimits(12, 0., 5.);
318  laser.SetParameter(13, 0.01 * integral * 0.005);
319  laser.SetParLimits(13, 0., 0.2 * integral * 0.005);
320 
321  // if it's a monitoring fit, fix a buch more parameters.
322  if (m_fitterMode == "monitoring") {
323  laser.FixParameter(2, m_fractionConstraints);
324  laser.FixParameter(3, m_deltaTConstraints);
325  laser.FixParameter(8, m_timeExtraConstraints);
326  laser.FixParameter(9, m_sigmaExtraConstraints);
327  laser.FixParameter(14, m_alphaExtraConstraints);
328  laser.FixParameter(15, m_nExtraConstraints);
329  laser.FixParameter(11, m_timeBackgroundConstraints);
330  laser.FixParameter(12, m_sigmaBackgroundConstraints);
331  }
332 
333 
334  // if it's a MC fit, fix a buch more parameters.
335  if (m_fitterMode == "MC") {
336  laser.SetParameter(2, 0.8);
337  laser.SetParLimits(2, 0., 1.);
338  laser.SetParameter(3, -0.1);
339  laser.SetParLimits(3, -0.4, -0.);
340  // The following are just random reasonable number, only to pin-point the tail components to some value and remove them form the fit
341  laser.FixParameter(8, 0);
342  laser.FixParameter(9, 0.1);
343  laser.FixParameter(14, -2.);
344  laser.FixParameter(15, 2);
345  laser.FixParameter(11, 1.);
346  laser.FixParameter(12, 0.1);
347  laser.FixParameter(13, 0.);
348  laser.FixParameter(10, 0.);
349  }
350 
351 
352 
353  // make the plot of the fit function nice setting 2000 sampling points
354  laser.SetNpx(2000);
355 
356 
357  // do the fit!
358  h_profile->Fit("laser", "R L Q");
359 
360 
361  // Add by hand the different fit components to the histogram, mostly for debugging/presentation purposes
362  TF1* peak1 = new TF1("peak1", laserPDF, maxpos - 1, maxpos + 2., 16);
363  TF1* peak2 = new TF1("peak2", laserPDF, maxpos - 1, maxpos + 2., 16);
364  TF1* extra = new TF1("extra", laserPDF, maxpos - 1, maxpos + 2., 16);
365  TF1* background = new TF1("background", laserPDF, maxpos - 1, maxpos + 2., 16);
366  for (int iPar = 0; iPar < 16; iPar++) {
367  peak1->FixParameter(iPar, laser.GetParameter(iPar));
368  peak2->FixParameter(iPar, laser.GetParameter(iPar));
369  extra->FixParameter(iPar, laser.GetParameter(iPar));
370  background->FixParameter(iPar, laser.GetParameter(iPar));
371  }
372  peak1->FixParameter(2, 0.);
373  peak1->FixParameter(7, (1 - laser.GetParameter(2))*laser.GetParameter(7));
374  peak1->FixParameter(10, 0.);
375  peak1->FixParameter(13, 0.);
376 
377  peak2->FixParameter(2, 1.);
378  peak2->FixParameter(7, laser.GetParameter(2)*laser.GetParameter(7));
379  peak2->FixParameter(10, 0.);
380  peak2->FixParameter(13, 0.);
381 
382  extra->FixParameter(7, 0.);
383  extra->FixParameter(13, 0.);
384 
385  background->FixParameter(7, 0.);
386  background->FixParameter(10, 0.);
387 
388  h_profile->GetListOfFunctions()->Add(peak1);
389  h_profile->GetListOfFunctions()->Add(peak2);
390  h_profile->GetListOfFunctions()->Add(extra);
391  h_profile->GetListOfFunctions()->Add(background);
392 
393 
394  // save the results in the variables linked to the tree branches
395  m_channel = iChannel;
396  m_row = m_pixelRow;
397  m_col = m_pixelCol;
398  m_slot = iSlot + 1;
399  m_peakTime = laser.GetParameter(0);
400  m_peakTimeErr = laser.GetParError(0);
401  m_deltaT = laser.GetParameter(3);
402  m_deltaTErr = laser.GetParError(3);
403  m_sigma = laser.GetParameter(1);
404  m_sigmaErr = laser.GetParError(1);
405  m_fraction = laser.GetParameter(2);
406  m_fractionErr = laser.GetParError(2);
407  m_yieldLaser = laser.GetParameter(7) / 0.005;
408  m_yieldLaserErr = laser.GetParError(7) / 0.005;
409  m_timeExtra = laser.GetParameter(8);
410  m_sigmaExtra = laser.GetParameter(9);
411  m_yieldLaserExtra = laser.GetParameter(10) / 0.005;
412  m_alphaExtra = laser.GetParameter(14);
413  m_nExtra = laser.GetParameter(15);
414  m_timeBackground = laser.GetParameter(11);
415  m_sigmaBackground = laser.GetParameter(12);
416  m_yieldLaserBackground = laser.GetParameter(13) / 0.005;
417  m_chi2 = laser.GetChisquare() / laser.GetNDF();
418 
419  // copy some MC information to the output tree
423 
424  return;
425 }
426 
427 
428 void TOPLocalCalFitter::fitPulser(TH1* h_profileFirstPulser, TH1* h_profileSecondPulser)
429 {
430  float maxpos = h_profileFirstPulser->GetBinCenter(h_profileFirstPulser->GetMaximumBin());
431  h_profileFirstPulser->GetXaxis()->SetRangeUser(maxpos - 1, maxpos + 1.);
432  if (h_profileFirstPulser->Integral() > 1000) {
433  TF1 pulser1 = TF1("pulser1", "[0]*TMath::Gaus(x, [1], [2], kTRUE)", maxpos - 1, maxpos + 1.);
434  pulser1.SetParameter(0, 1.);
435  pulser1.SetParameter(1, maxpos);
436  pulser1.SetParameter(2, 0.05);
437  h_profileFirstPulser->Fit("pulser1", "R Q");
438  m_firstPulserTime = pulser1.GetParameter(1);
439  m_firstPulserSigma = pulser1.GetParameter(2);
440  h_profileFirstPulser->Write();
441  } else {
442  m_firstPulserTime = -999;
443  m_firstPulserSigma = -999;
444  }
445 
446  maxpos = h_profileSecondPulser->GetBinCenter(h_profileSecondPulser->GetMaximumBin());
447  h_profileSecondPulser->GetXaxis()->SetRangeUser(maxpos - 1, maxpos + 1.);
448  if (h_profileSecondPulser->Integral() > 1000) {
449  TF1 pulser2 = TF1("pulser2", "[0]*TMath::Gaus(x, [1], [2], kTRUE)", maxpos - 1, maxpos + 1.);
450  pulser2.SetParameter(0, 1.);
451  pulser2.SetParameter(1, maxpos);
452  pulser2.SetParameter(2, 0.05);
453  h_profileSecondPulser->Fit("pulser2", "R Q");
454  m_secondPulserTime = pulser2.GetParameter(1);
455  m_secondPulserSigma = pulser2.GetParameter(2);
456  h_profileSecondPulser->Write();
457  } else {
458  m_secondPulserTime = -999;
459  m_secondPulserSigma = -999;
460  }
461  return;
462 }
463 
464 
465 
467 {
468  if (m_chi2 < 4 && m_sigma < 0.2 && m_yieldLaser > 1000) {
469  m_fitStatus = 0;
470  } else {
471  m_fitStatus = 1;
472  }
473  return;
474 }
475 
476 
478 {
479  int nEntries = m_fitTree->GetEntries();
480  if (nEntries != 8192) {
481  B2ERROR("fitTree does not contain an entry wit a fit result for each channel. Found " << nEntries <<
482  " instead of 8192. Perhaps you tried to run the commonT0 calculation before finishing the fitting?");
483  return;
484  }
485 
486  // Create and fill the TOPCalChannelT0 object.
487  // This part is mostly copy-pasted from the DB importer used up to Jan 2020
488  auto* channelT0 = new TOPCalChannelT0();
489  short nCal[16] = {0};
490  for (int i = 0; i < nEntries; i++) {
491  m_fitTree->GetEntry(i);
492  channelT0->setT0(m_slot, m_channel, m_peakTime - m_peakTimeMC, m_peakTimeErr);
493  if (m_fitStatus == 0) {
494  nCal[m_slot - 1]++;
495  } else {
496  channelT0->setUnusable(m_slot, m_channel);
497  }
498  }
499 
500  // Normalize the constants
501  channelT0->suppressAverage();
502 
503  // create the localDB
504  saveCalibration(channelT0);
505 
506  short nCalTot = 0;
507  B2INFO("Summary: ");
508  for (int iSlot = 1; iSlot < 17; iSlot++) {
509  B2INFO("--> Number of calibrated channels on Slot " << iSlot << " : " << nCal[iSlot - 1] << "/512");
510  B2INFO("--> Cal on ch 1, 256 and 511: " << channelT0->getT0(iSlot, 0) << ", " << channelT0->getT0(iSlot,
511  257) << ", " << channelT0->getT0(iSlot, 511));
512  nCalTot += nCal[iSlot - 1];
513  }
514 
515  B2RESULT("Channel T0 calibration constants imported to database, calibrated channels: " << nCalTot << "/ 8192");
516 
517 
518  // Loop again on the output tree to save the constants there too, adding two more branches.
519  TBranch* channelT0Branch = m_fitTree->Branch<float>("channelT0", &m_channelT0);
520  TBranch* channelT0ErrBranch = m_fitTree->Branch<float>("channelT0Err", &m_channelT0Err);
521 
522  for (int i = 0; i < nEntries; i++) {
523  m_fitTree->GetEntry(i);
524  m_channelT0 = channelT0->getT0(m_slot, m_channel);
525  m_channelT0Err = channelT0->getT0Error(m_slot, m_channel);
526  channelT0Branch->Fill();
527  channelT0ErrBranch->Fill();
528  }
529  return ;
530 
531 }
532 
533 
534 
536 {
537  gROOT->SetBatch();
538 
539  loadMCInfoTrees();
540 
541 
543 
544  // Loads the tree with the hits
545  auto hitTree = getObjectPtr<TTree>("hitTree");
546  TH2F* h_hitTime = new TH2F("h_hitTime", " ", 512 * 16, 0., 512 * 16, 22000, -70, 40.); // 5 ps bins
547 
548  float amplitude, hitTime;
549  short channel, slot;
550  bool refTimeValid;
551  hitTree->SetBranchAddress("amplitude", &amplitude);
552  hitTree->SetBranchAddress("hitTime", &hitTime);
553  hitTree->SetBranchAddress("channel", &channel);
554  hitTree->SetBranchAddress("slot", &slot);
555  hitTree->SetBranchAddress("refTimeValid", &refTimeValid);
556 
557  // An attempt to speed things up looping over the tree only once.
558  std::vector<TH2F*> h_hitTimeLaserHistos = {};
559  for (int iLowerEdge = 0; iLowerEdge < (int)m_binEdges.size() - 1; iLowerEdge++) {
560  TH2F* h_hitTimeLaser = new TH2F(("h_hitTimeLaser_" + std::to_string(iLowerEdge + 1)).c_str(), " ", 512 * 16, 0., 512 * 16, 14000,
561  -70, 0.); // 5 ps bins
562  h_hitTimeLaserHistos.push_back(h_hitTimeLaser);
563  }
564 
565  for (unsigned int i = 0; i < hitTree->GetEntries(); i++) {
566  auto onepc = (unsigned int)(hitTree->GetEntries() / 100);
567  if (i % onepc == 0)
568  std::cout << "processing hit " << i << " of " << hitTree->GetEntries() << " (" << i / (onepc * 10) << " %)" << std::endl;
569  hitTree->GetEntry(i);
570  auto it = std::lower_bound(m_binEdges.cbegin(), m_binEdges.cend(), amplitude);
571  int iLowerEdge = std::distance(m_binEdges.cbegin(), it) - 1;
572 
573  if (iLowerEdge >= 0 && iLowerEdge < static_cast<int>(m_binEdges.size()) - 1 && refTimeValid)
574  h_hitTimeLaserHistos[iLowerEdge]->Fill(channel + (slot - 1) * 512, hitTime);
575  if (amplitude > 80. && refTimeValid)
576  h_hitTime->Fill(channel + (slot - 1) * 512, hitTime);
577  }
578 
579  m_histFile->cd();
580  h_hitTime->Write();
581 
582  for (short iSlot = 0; iSlot < 16; iSlot++) {
583  std::cout << "fitting slot " << iSlot + 1 << std::endl;
584  for (short iChannel = 0; iChannel < 512; iChannel++) {
585  TH1D* h_profile = h_hitTime->ProjectionY(("profile_" + std::to_string(iSlot + 1) + "_" + std::to_string(iChannel)).c_str(),
586  iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1);
587  if (m_fitterMode == "MC")
588  h_profile->GetXaxis()->SetRangeUser(-10, -10);
589  else
590  h_profile->GetXaxis()->SetRangeUser(-65,
591  -5); // if you will even change it, make sure not to include the h_hitTime overflow bins in this range
592  fitChannel(iSlot, iChannel, h_profile);
593 
595 
596  // Now let's fit the pulser
597  TH1D* h_profileFirstPulser = h_hitTime->ProjectionY(("profileFirstPulser_" + std::to_string(iSlot + 1) + "_" + std::to_string(
598  iChannel)).c_str(), iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1);
599  TH1D* h_profileSecondPulser = h_hitTime->ProjectionY(("profileSecondPulser_" + std::to_string(iSlot + 1) + "_" + std::to_string(
600  iChannel)).c_str(), iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1);
601  h_profileFirstPulser->GetXaxis()->SetRangeUser(-10, 10);
602  h_profileSecondPulser->GetXaxis()->SetRangeUser(10, 40);
603 
604  fitPulser(h_profileFirstPulser, h_profileSecondPulser);
605 
606  m_fitTree->Fill();
607 
608  h_profile->Write();
609  h_profileFirstPulser->Write();
610  h_profileSecondPulser->Write();
611  }
612 
613  h_hitTime->Write();
614  }
615 
617 
618  m_fitTree->Write();
619 
620 
622  std::cout << "Fitting in bins" << std::endl;
623  for (int iLowerEdge = 0; iLowerEdge < (int)m_binEdges.size() - 1; iLowerEdge++) {
624  m_binLowerEdge = m_binEdges[iLowerEdge];
625  m_binUpperEdge = m_binEdges[iLowerEdge + 1];
626  std::cout << "Fitting the amplitude interval (" << m_binLowerEdge << ", " << m_binUpperEdge << " )" << std::endl;
627 
628  for (short iSlot = 0; iSlot < 16; iSlot++) {
629  std::cout << " Fitting slot " << iSlot + 1 << std::endl;
630  for (short iChannel = 0; iChannel < 512; iChannel++) {
631  TH1D* h_profile = h_hitTimeLaserHistos[iLowerEdge]->ProjectionY(("profile_" + std::to_string(iSlot + 1) + "_" + std::to_string(
632  iChannel) + "_" + std::to_string(iLowerEdge)).c_str(),
633  iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1);
634  if (m_fitterMode == "MC")
635  h_profile->GetXaxis()->SetRangeUser(-10, -10);
636  else
637  h_profile->GetXaxis()->SetRangeUser(-65,
638  -5); // if you will even change it, make sure not to include the h_hitTime overflow bins in this range
639  fitChannel(iSlot, iChannel, h_profile);
640  m_histoIntegral = h_profile->Integral();
642 
643  m_timewalkTree->Fill();
644  h_profile->Write();
645  }
646  }
647  }
648 
649  m_timewalkTree->Write();
650  }
651 
652  m_histFile->Close();
653 
654  return c_OK;
655 }
Belle2::TOP::TOPLocalCalFitter::calibrate
virtual EResult calibrate() override
Runs the algorithm on events.
Definition: TOPLocalCalFitter.cc:535
Belle2::TOP::TOPLocalCalFitter::m_sigmaBackgroundConstraints
float m_sigmaBackgroundConstraints
Sigma of the gaussian used to describe the background.
Definition: TOPLocalCalFitter.h:170
Belle2::TOP::TOPLocalCalFitter::m_f2
float m_f2
Fraction of the second gaussian on the TTS parametrization.
Definition: TOPLocalCalFitter.h:157
Belle2::TOP::TOPLocalCalFitter::m_fractionConstraints
float m_fractionConstraints
Fraction of the main peak.
Definition: TOPLocalCalFitter.h:164
Belle2::TOP::TOPLocalCalFitter::m_alphaExtraConstraints
float m_alphaExtraConstraints
alpha parameter of the tail of the extra peak.
Definition: TOPLocalCalFitter.h:167
Belle2::TOP::TOPLocalCalFitter::m_secondPulserSigma
float m_secondPulserSigma
Time resolution from the fit of the first electronic pulse, from a Gaussian fit.
Definition: TOPLocalCalFitter.h:221
Belle2::TOP::TOPLocalCalFitter::m_yieldLaser
float m_yieldLaser
Total number of laser hits from the fitting function integral.
Definition: TOPLocalCalFitter.h:185
Belle2::TOP::TOPLocalCalFitter::setupOutputTreeAndFile
void setupOutputTreeAndFile()
prepares the output tree
Definition: TOPLocalCalFitter.cc:153
Belle2::TOP::TOPLocalCalFitter::m_row
short m_row
Pixel row.
Definition: TOPLocalCalFitter.h:178
Belle2::TOP::TOPLocalCalFitter::m_channelT0
float m_channelT0
Raw, channelT0 calibration, defined as peakTime-peakTimeMC.
Definition: TOPLocalCalFitter.h:212
Belle2::CalibrationAlgorithm::saveCalibration
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
Definition: CalibrationAlgorithm.cc:290
Belle2::TOP::TOPLocalCalFitter::m_yieldLaserBackground
float m_yieldLaserBackground
Integral of the background gaussian.
Definition: TOPLocalCalFitter.h:202
Belle2::TOP::TOPLocalCalFitter::m_nExtra
float m_nExtra
parameter n of the tail of the extra peak
Definition: TOPLocalCalFitter.h:198
Belle2::TOP::TOPLocalCalFitter::m_fitConstraints
std::string m_fitConstraints
File with the TTS parametrization.
Definition: TOPLocalCalFitter.h:133
Belle2::TOP::TOPLocalCalFitter::m_fractionMC
float m_fractionMC
Fraction of events in the secondary peak form the MC simulation.
Definition: TOPLocalCalFitter.h:204
Belle2::TOP::TOPLocalCalFitter::m_inputTTS
TFile * m_inputTTS
File containing m_treeTTS.
Definition: TOPLocalCalFitter.h:140
Belle2::TOP::TOPLocalCalFitter::m_deltaTErr
float m_deltaTErr
Statistical error on deltaT.
Definition: TOPLocalCalFitter.h:189
Belle2::TOP::TOPLocalCalFitter::m_sigmaBackground
float m_sigmaBackground
Sigma of the gaussian used to describe the background.
Definition: TOPLocalCalFitter.h:201
Belle2::TOP::TOPLocalCalFitter::calculateChennelT0
void calculateChennelT0()
Calculates the commonT0 calibration after the fits have been done.
Definition: TOPLocalCalFitter.cc:477
Belle2::TOP::TOPLocalCalFitter::m_peakTime
float m_peakTime
Fitted time of the main (i.e.
Definition: TOPLocalCalFitter.h:180
Belle2::TOP::TOPLocalCalFitter::m_treeTTS
TTree * m_treeTTS
Input to the fitter.
Definition: TOPLocalCalFitter.h:143
Belle2::CalibrationAlgorithm::c_OK
@ c_OK
Finished successfuly =0 in Python.
Definition: CalibrationAlgorithm.h:51
Belle2::CalibrationAlgorithm::setDescription
void setDescription(const std::string &description)
Set algorithm description (in constructor)
Definition: CalibrationAlgorithm.h:331
Belle2::TOP::TOPLocalCalFitter::m_firstPulserTime
float m_firstPulserTime
Average time of the first electronic pulse respect to the reference pulse, from a Gaussian fit.
Definition: TOPLocalCalFitter.h:216
Belle2::TOP::TOPLocalCalFitter::m_sigma2
float m_sigma2
Width of the second gaussian on the TTS parametrization.
Definition: TOPLocalCalFitter.h:155
Belle2::TOP::TOPLocalCalFitter::m_secondPulserTime
float m_secondPulserTime
Average time of the second electronic pulse respect to the reference pulse, from a gaussian fit.
Definition: TOPLocalCalFitter.h:219
Belle2::TOP::TOPLocalCalFitter::m_timeExtra
float m_timeExtra
Position of the extra peak seen in the timing tail, w/ respect to peakTime.
Definition: TOPLocalCalFitter.h:194
Belle2::TOP::TOPLocalCalFitter::m_timewalkTree
TTree * m_timewalkTree
Output of the fitter.
Definition: TOPLocalCalFitter.h:148
Belle2::TOP::TOPLocalCalFitter::m_col
short m_col
Pixel column.
Definition: TOPLocalCalFitter.h:179
Belle2::TOP::TOPLocalCalFitter::TOPLocalCalFitter
TOPLocalCalFitter()
Constructor.
Definition: TOPLocalCalFitter.cc:105
Belle2::TOP::TOPLocalCalFitter::m_firstPulserSigma
float m_firstPulserSigma
Time resolution from the fit of the first electronic pulse, from a Gaussian fit.
Definition: TOPLocalCalFitter.h:217
Belle2::TOP::TOPLocalCalFitter::m_channel
short m_channel
Channel number (0-511)
Definition: TOPLocalCalFitter.h:176
Belle2::TOP::TOPLocalCalFitter::m_histFile
TFile * m_histFile
Output of the fitter.
Definition: TOPLocalCalFitter.h:146
Belle2::TOP::TOPLocalCalFitter::m_histoIntegral
float m_histoIntegral
Integral of the fitted histogram.
Definition: TOPLocalCalFitter.h:186
Belle2::TOP::TOPLocalCalFitter::m_timeBackgroundConstraints
float m_timeBackgroundConstraints
Position of the gaussian used to describe the background, w/ respect to peakTime.
Definition: TOPLocalCalFitter.h:169
Belle2::TOP::TOPLocalCalFitter::m_deltaTConstraints
float m_deltaTConstraints
Distance between the main and the secondary laser peak.
Definition: TOPLocalCalFitter.h:163
Belle2::TOPCalChannelT0
Channel T0 calibration constants for all 512 channels of 16 modules.
Definition: TOPCalChannelT0.h:33
Belle2::TOP::TOPLocalCalFitter::m_fitTree
TTree * m_fitTree
Output of the fitter.
Definition: TOPLocalCalFitter.h:147
Belle2::TOP::TOPLocalCalFitter::loadMCInfoTrees
void loadMCInfoTrees()
loads the TTS parameters and the MC truth info
Definition: TOPLocalCalFitter.cc:115
Belle2::TOP::TOPLocalCalFitter::fitChannel
void fitChannel(short, short, TH1 *)
Fits the laser light on one channel.
Definition: TOPLocalCalFitter.cc:243
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::TOP::TOPLocalCalFitter::m_output
std::string m_output
Name of the output file.
Definition: TOPLocalCalFitter.h:132
Belle2::TOP::TOPLocalCalFitter::m_mean2
float m_mean2
Position of the second gaussian of the TTS parametrization with respect to the first one.
Definition: TOPLocalCalFitter.h:153
Belle2::TOP::TOPLocalCalFitter::m_channelT0Err
float m_channelT0Err
Statistical error on channelT0.
Definition: TOPLocalCalFitter.h:214
Belle2::TOP::TOPLocalCalFitter::m_fitterMode
std::string m_fitterMode
Fit mode.
Definition: TOPLocalCalFitter.h:137
Belle2::TOP::TOPLocalCalFitter::m_binEdges
std::vector< float > m_binEdges
Amplitude bins.
Definition: TOPLocalCalFitter.h:139
Belle2::TOP::TOPLocalCalFitter::m_fraction
float m_fraction
Fraction of events in the secondary peak.
Definition: TOPLocalCalFitter.h:184
Belle2::TOP::TOPLocalCalFitter::m_inputConstraints
TFile * m_inputConstraints
File containing m_treeConstraints.
Definition: TOPLocalCalFitter.h:141
Belle2::TOP::TOPLocalCalFitter::m_binLowerEdge
float m_binLowerEdge
Lower edge of the amplitude bin in which this fit is performed.
Definition: TOPLocalCalFitter.h:174
Belle2::TOP::TOPLocalCalFitter::m_peakTimeErr
float m_peakTimeErr
Statistical error on peakTime.
Definition: TOPLocalCalFitter.h:188
Belle2::TOP::TOPLocalCalFitter::m_yieldLaserErr
float m_yieldLaserErr
Statistical error on yield.
Definition: TOPLocalCalFitter.h:192
Belle2::TOP::TOPLocalCalFitter::m_isFitInAmplitudeBins
bool m_isFitInAmplitudeBins
Enables the fit in amplitude bins.
Definition: TOPLocalCalFitter.h:138
Belle2::TOP::TOPLocalCalFitter::m_fitStatus
short m_fitStatus
Fit quality flag, propagated to the constants.
Definition: TOPLocalCalFitter.h:223
Belle2::TOP::TOPLocalCalFitter::determineFitStatus
void determineFitStatus()
determines if the constant obtained by the fit are good or not
Definition: TOPLocalCalFitter.cc:466
Belle2::TOP::TOPLocalCalFitter::m_sigmaExtraConstraints
float m_sigmaExtraConstraints
Width of the guassian used to describe the extra peak on the timing distribution tail.
Definition: TOPLocalCalFitter.h:166
Belle2::TOP::TOPLocalCalFitter::m_timeExtraConstraints
float m_timeExtraConstraints
Position of the guassian used to describe the extra peak on the timing distribution tail.
Definition: TOPLocalCalFitter.h:165
Belle2::CalibrationAlgorithm::EResult
EResult
The result of calibration.
Definition: CalibrationAlgorithm.h:50
Belle2::TOP::TOPLocalCalFitter::m_fractionErr
float m_fractionErr
Statistical error on fraction.
Definition: TOPLocalCalFitter.h:191
Belle2::TOP::TOPLocalCalFitter::m_alphaExtra
float m_alphaExtra
alpha parameter of the tail of the extra peak.
Definition: TOPLocalCalFitter.h:197
Belle2::TOP::TOPLocalCalFitter::m_nExtraConstraints
float m_nExtraConstraints
parameter n of the tail of the extra peak
Definition: TOPLocalCalFitter.h:168
Belle2::TOP::TOPLocalCalFitter::m_yieldLaserExtra
float m_yieldLaserExtra
Integral of the extra peak.
Definition: TOPLocalCalFitter.h:196
Belle2::TOP::TOPLocalCalFitter::m_f1
float m_f1
Fraction of the first gaussian on the TTS parametrization.
Definition: TOPLocalCalFitter.h:156
Belle2::TOP::TOPLocalCalFitter::m_peakTimeMC
float m_peakTimeMC
Time of the main peak in teh MC simulation, i.e.
Definition: TOPLocalCalFitter.h:206
Belle2::TOP::TOPLocalCalFitter::fitPulser
void fitPulser(TH1 *, TH1 *)
Fits the two pulsers.
Definition: TOPLocalCalFitter.cc:428
Belle2::TOP::TOPLocalCalFitter::m_sigma
float m_sigma
Gaussian time resolution, fitted.
Definition: TOPLocalCalFitter.h:183
Belle2::TOP::TOPLocalCalFitter::m_deltaTMC
float m_deltaTMC
Time difference between the main peak and the secondary peak in the MC simulation.
Definition: TOPLocalCalFitter.h:205
Belle2::TOP::TOPLocalCalFitter::m_pixelRow
short m_pixelRow
Pixel row.
Definition: TOPLocalCalFitter.h:158
Belle2::TOP::TOPLocalCalFitter::m_deltaT
float m_deltaT
Time difference between the main peak and the secondary peak.
Definition: TOPLocalCalFitter.h:181
Belle2::TOP::TOPLocalCalFitter::m_rms
float m_rms
RMS of the histogram used for the fit.
Definition: TOPLocalCalFitter.h:210
Belle2::TOP::TOPLocalCalFitter::m_timeBackground
float m_timeBackground
Position of the gaussian used to describe the background, w/ respect to peakTime.
Definition: TOPLocalCalFitter.h:200
Belle2::CalibrationAlgorithm
Base class for calibration algorithms.
Definition: CalibrationAlgorithm.h:47
Belle2::TOP::TOPLocalCalFitter::m_peakTimeConstraints
float m_peakTimeConstraints
Time of the main laser peak in the MC simulation (aka MC correction)
Definition: TOPLocalCalFitter.h:162
Belle2::TOP::TOPLocalCalFitter::m_chi2
float m_chi2
Reduced chi2 of the fit.
Definition: TOPLocalCalFitter.h:209
Belle2::TOP::TOPLocalCalFitter::m_sigmaExtra
float m_sigmaExtra
Gaussian sigma of the extra peak in the timing tail
Definition: TOPLocalCalFitter.h:195
Belle2::TOP::TOPLocalCalFitter::m_TTSData
std::string m_TTSData
File with the Fit constraints and MC info.
Definition: TOPLocalCalFitter.h:135
Belle2::TOP::TOPLocalCalFitter::m_slot
short m_slot
Slot ID (1-16)
Definition: TOPLocalCalFitter.h:177
Belle2::TOP::TOPLocalCalFitter::m_binUpperEdge
float m_binUpperEdge
Upper edge of the amplitude bin in which this fit is performed.
Definition: TOPLocalCalFitter.h:175
Belle2::TOP::TOPLocalCalFitter::m_sigmaErr
float m_sigmaErr
Statistical error on sigma.
Definition: TOPLocalCalFitter.h:190
Belle2::TOP::TOPLocalCalFitter::m_treeConstraints
TTree * m_treeConstraints
Input to the fitter.
Definition: TOPLocalCalFitter.h:144
Belle2::TOP::TOPLocalCalFitter::m_pixelCol
short m_pixelCol
Pixel column.
Definition: TOPLocalCalFitter.h:159
Belle2::TOP::TOPLocalCalFitter::m_sigma1
float m_sigma1
Width of the first gaussian on the TTS parametrization.
Definition: TOPLocalCalFitter.h:154