Belle II Software  release-05-02-19
EKLMTimeCalibrationAlgorithm.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2015 Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Kirill Chilikin *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 /* Own header. */
12 #include <klm/eklm/calibration/EKLMTimeCalibrationAlgorithm.h>
13 
14 /* KLM headers. */
15 #include <klm/dataobjects/eklm/EKLMElementNumbers.h>
16 #include <klm/dbobjects/eklm/EKLMTimeCalibration.h>
17 
18 /* ROOT headers. */
19 #include <TCanvas.h>
20 #include <TF1.h>
21 #include <TH1F.h>
22 #include <TTree.h>
23 
24 using namespace Belle2;
25 
26 static double CrystalBall(double* x, double* par)
27 {
28  double d1, d2, t, f;
29  if (*x < par[1]) {
30  d1 = *x - par[1];
31  f = exp(-0.5 * d1 * d1 / par[2] / par[2]);
32  } else if (*x < par[4]) {
33  d1 = *x - par[1];
34  f = exp(-0.5 * d1 * d1 / par[3] / par[3]);
35  } else {
36  d1 = par[4] - par[1];
37  d2 = *x - par[4];
38  t = par[5] * par[3] * par[3] / d1;
39  f = exp(-0.5 * d1 * d1 / par[3] / par[3]) *
40  pow(t / (d2 + t), par[5]);
41  }
42  return par[0] * f;
43 }
44 
46  CalibrationAlgorithm("EKLMTimeCalibrationCollector"),
47  m_Debug(false)
48 {
49 }
50 
52 {
53 }
54 
56 {
57  int i, j1, j2, n, strip, maxStrip;
58  double s[2][3], k[2][3], dt, dl, dn, effectiveLightSpeed, tau;
59  double* averageDist, *averageTime, *averageSqrtN, *timeShift, timeShift0;
60  struct Event ev;
61  std::vector<struct Event>* stripEvents;
62  std::vector<struct Event>::iterator it;
63  EKLMTimeCalibration* calibration = new EKLMTimeCalibration();
64  EKLMTimeCalibrationData calibrationData;
65  const EKLMElementNumbers& elementNumbers = EKLMElementNumbers::Instance();
66  maxStrip = elementNumbers.getMaximalStripGlobalNumber();
67  bool* calibrateStrip;
68  TH1F* h, *h2;
69  TF1* fcn;
70  std::shared_ptr<TTree> t;
71  TCanvas* c1 = nullptr;
72  if (m_Debug)
73  c1 = new TCanvas();
74  fcn = new TF1("fcn", CrystalBall, 0, 10, 6);
75  stripEvents = new std::vector<struct Event>[maxStrip];
76  averageDist = new double[maxStrip];
77  averageTime = new double[maxStrip];
78  averageSqrtN = new double[maxStrip];
79  timeShift = new double[maxStrip];
80  calibrateStrip = new bool[maxStrip];
81  t = getObjectPtr<TTree>("calibration_data");
82  t->SetBranchAddress("time", &ev.time);
83  t->SetBranchAddress("dist", &ev.dist);
84  t->SetBranchAddress("npe", &ev.npe);
85  t->SetBranchAddress("strip", &strip);
86  n = t->GetEntries();
87  for (i = 0; i < n; i++) {
88  t->GetEntry(i);
89  stripEvents[strip - 1].push_back(ev);
90  }
91  for (j1 = 0; j1 < 2; j1++) {
92  for (j2 = 0; j2 < 3; j2++)
93  k[j1][j2] = 0;
94  }
95  /*
96  * Determination of the effective light speed. For each strip, the variance
97  * of time is
98  *
99  * sigma = \frac{1}{n - 1} \sum (t_i - (t_0 + l_i / c_{eff} +
100  * \tau / \sqrt{N_i})^2, (1)
101  *
102  * where t_i, l_i and N_i are time, distance from SiPM and number of
103  * photoelectrons for a hit, respectively, t_0 is the time shift for this
104  * strip, c_{eff} is the effective light speed and \tau is signal amplitude
105  * dependence time constant. The parameters c_{eff} and \tau are constant
106  * for all strips. The variance is approximated by
107  *
108  * sigma = \frac{1}{n - 1} \sum (t_i - \sum t_i -
109  * (l_i - (\sum l_i))/ c_{eff} + \tau / \sqrt{N_i})^2, (2)
110  *
111  * and sum of sigmas is minimized similarly to chi^2 minimization by direct
112  * calculation. Partial derivatives of Eq. (2) by c_{eff} and \tau are equal
113  * to 0 at the minimum.
114  */
115  for (i = 0; i < maxStrip; i++) {
116  n = stripEvents[i].size();
117  if (n < 2) {
118  B2WARNING("Not enough calibration data collected."
119  << LogVar("Strip", i + 1));
120  delete fcn;
121  delete[] stripEvents;
122  delete[] averageDist;
123  delete[] averageTime;
124  delete[] averageSqrtN;
125  delete[] timeShift;
126  delete[] calibrateStrip;
128  }
129  calibrateStrip[i] = true;
130  averageDist[i] = 0;
131  averageTime[i] = 0;
132  averageSqrtN[i] = 0;
133  for (it = stripEvents[i].begin(); it != stripEvents[i].end(); ++it) {
134  averageDist[i] = averageDist[i] + it->dist;
135  averageTime[i] = averageTime[i] + it->time;
136  averageSqrtN[i] = averageSqrtN[i] + 1.0 / sqrt(it->npe);
137  }
138  averageDist[i] = averageDist[i] / n;
139  averageTime[i] = averageTime[i] / n;
140  averageSqrtN[i] = averageSqrtN[i] / n;
141  for (j1 = 0; j1 < 2; j1++) {
142  for (j2 = 0; j2 < 3; j2++)
143  s[j1][j2] = 0;
144  }
145  for (it = stripEvents[i].begin(); it != stripEvents[i].end(); ++it) {
146  dt = it->time - averageTime[i];
147  dl = it->dist - averageDist[i];
148  dn = 1.0 / sqrt(it->npe);
149  s[0][0] += dl * dl;
150  s[0][1] += dl * dn;
151  s[0][2] += dl * dt;
152  s[1][0] += dn * dl;
153  s[1][1] += dn * dn;
154  s[1][2] += dn * dt;
155  }
156  for (j1 = 0; j1 < 2; j1++) {
157  for (j2 = 0; j2 < 3; j2++)
158  k[j1][j2] += (n - 1) * s[j1][j2];
159  }
160  }
161  /*
162  * Now, the system of equations is
163  *
164  * k[0][0] / c_{eff} + k[0][1] \tau = k[0][2],
165  * k[1][0] / c_{eff} + k[1][1] \tau = k[1][2].
166  */
167  h = new TH1F("h", "", 200, -10., 10.);
168  h2 = new TH1F("h2", "", 200, -10., 10.);
169  effectiveLightSpeed = (k[0][0] * k[1][1] - k[1][0] * k[0][1]) /
170  (k[0][2] * k[1][1] - k[1][2] * k[0][1]);
171  tau = (k[0][0] * k[1][2] - k[1][0] * k[0][2]) /
172  (k[0][0] * k[1][1] - k[1][0] * k[0][1]);
173  B2INFO("EKLM time calibration results:"
174  << LogVar("Effective light speed, cm / ns", effectiveLightSpeed)
175  << LogVar("Amplitude time constant, ns", tau));
176  calibration->setEffectiveLightSpeed(effectiveLightSpeed);
177  calibration->setAmplitudeTimeConstant(tau);
178  for (i = 0; i < maxStrip; i++) {
179  if (!calibrateStrip[i])
180  continue;
181  timeShift[i] = averageTime[i] - averageDist[i] / effectiveLightSpeed -
182  averageSqrtN[i] * tau;
183  for (it = stripEvents[i].begin(); it != stripEvents[i].end(); ++it) {
184  h->Fill(it->time - (timeShift[i] + it->dist / effectiveLightSpeed +
185  tau / sqrt(it->npe)));
186  }
187  }
188  fcn->SetParameter(0, h->Integral());
189  fcn->SetParameter(1, h->GetMean());
190  fcn->SetParameter(2, h->GetRMS());
191  fcn->SetParameter(3, h->GetRMS());
192  fcn->FixParameter(4, h->GetMean() + 1.0);
193  fcn->FixParameter(5, 1.0);
194  if (m_Debug)
195  h->Fit("fcn");
196  else
197  h->Fit("fcn", "n");
198  fcn->ReleaseParameter(4);
199  fcn->ReleaseParameter(5);
200  if (m_Debug)
201  h->Fit("fcn");
202  else
203  h->Fit("fcn", "n");
204  timeShift0 = fcn->GetParameter(1);
205  if (m_Debug) {
206  h->Draw();
207  c1->Print("corrtime.eps");
208  }
209  for (i = 0; i < maxStrip; i++) {
210  if (!calibrateStrip[i])
211  continue;
212  timeShift[i] = timeShift[i] + timeShift0;
213  calibrationData.setTimeShift(timeShift[i]);
214  calibration->setTimeCalibrationData(i + 1, &calibrationData);
215  for (it = stripEvents[i].begin(); it != stripEvents[i].end(); ++it) {
216  h2->Fill(it->time - (timeShift[i] + it->dist / effectiveLightSpeed +
217  tau / sqrt(it->npe)));
218  }
219  }
220  if (m_Debug) {
221  h2->Draw();
222  c1->Print("corrtime2.eps");
223  }
224  delete fcn;
225  delete[] stripEvents;
226  delete[] averageDist;
227  delete[] averageTime;
228  delete[] averageSqrtN;
229  delete[] timeShift;
230  delete[] calibrateStrip;
231  saveCalibration(calibration, "EKLMTimeCalibration");
233 }
Belle2::EKLMElementNumbers
EKLM element numbers.
Definition: EKLMElementNumbers.h:34
Belle2::EKLMTimeCalibration
Class to store EKLM time calibration data in the database.
Definition: EKLMTimeCalibration.h:40
Belle2::EKLMTimeCalibrationAlgorithm::Event
Event (hit): time, distance from hit to SiPM.
Definition: EKLMTimeCalibrationAlgorithm.h:40
Belle2::EKLMTimeCalibrationAlgorithm::calibrate
CalibrationAlgorithm::EResult calibrate() override
Calibration.
Definition: EKLMTimeCalibrationAlgorithm.cc:55
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::EKLMTimeCalibrationAlgorithm::m_Debug
bool m_Debug
Debug mode.
Definition: EKLMTimeCalibrationAlgorithm.h:72
Belle2::CalibrationAlgorithm::c_OK
@ c_OK
Finished successfuly =0 in Python.
Definition: CalibrationAlgorithm.h:51
Belle2::EKLMElementNumbers::getMaximalStripGlobalNumber
static constexpr int getMaximalStripGlobalNumber()
Get maximal strip global number.
Definition: EKLMElementNumbers.h:377
Belle2::EKLMTimeCalibrationAlgorithm::Event::npe
float npe
Number of photoelectrons.
Definition: EKLMTimeCalibrationAlgorithm.h:43
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::EKLMTimeCalibrationAlgorithm::~EKLMTimeCalibrationAlgorithm
~EKLMTimeCalibrationAlgorithm()
Destructor.
Definition: EKLMTimeCalibrationAlgorithm.cc:51
LogVar
Class to store variables with their name which were sent to the logging service.
Definition: LogVariableStream.h:24
Belle2::EKLMElementNumbers::Instance
static const EKLMElementNumbers & Instance()
Instantiation.
Definition: EKLMElementNumbers.cc:20
Belle2::EKLMTimeCalibrationAlgorithm::Event::time
float time
Time.
Definition: EKLMTimeCalibrationAlgorithm.h:41
Belle2::EKLMTimeCalibrationData::setTimeShift
void setTimeShift(float timeShift)
Set time shift.
Definition: EKLMTimeCalibrationData.h:56
Belle2::CalibrationAlgorithm::EResult
EResult
The result of calibration.
Definition: CalibrationAlgorithm.h:50
Belle2::CalibrationAlgorithm::c_NotEnoughData
@ c_NotEnoughData
Needs more data =2 in Python.
Definition: CalibrationAlgorithm.h:53
Belle2::EKLMTimeCalibrationData
EKLM time calibration data (for one strip).
Definition: EKLMTimeCalibrationData.h:33
Belle2::CalibrationAlgorithm
Base class for calibration algorithms.
Definition: CalibrationAlgorithm.h:47
Belle2::EKLMTimeCalibrationAlgorithm::Event::dist
float dist
Distance.
Definition: EKLMTimeCalibrationAlgorithm.h:42
Belle2::EKLMTimeCalibrationAlgorithm::EKLMTimeCalibrationAlgorithm
EKLMTimeCalibrationAlgorithm()
Constructor.
Definition: EKLMTimeCalibrationAlgorithm.cc:45