Belle II Software  release-05-02-19
TOPModuleT0DeltaTAlgorithm.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: Marko Staric *
8  * *
9  * This software is provided "as is" without any warranty. *
10  **************************************************************************/
11 
12 #include <top/calibration/TOPModuleT0DeltaTAlgorithm.h>
13 #include <top/dbobjects/TOPCalModuleT0.h>
14 #include <math.h>
15 #include <TROOT.h>
16 #include <TFile.h>
17 #include <TF1.h>
18 #include <TH2F.h>
19 #include <TMatrixDSym.h>
20 #include <TDecompChol.h>
21 #include <string>
22 #include <vector>
23 #include <sstream>
24 
25 using namespace std;
26 
27 namespace Belle2 {
32  namespace TOP {
33 
34  TOPModuleT0DeltaTAlgorithm::TOPModuleT0DeltaTAlgorithm():
35  CalibrationAlgorithm("TOPModuleT0DeltaTCollector")
36  {
37  setDescription("Calibration algorithm for method DeltaT");
38  }
39 
41  {
42  gROOT->SetBatch();
43 
44  // get basic histogram
45 
46  auto slotPairs = getObjectPtr<TH2F>("slots");
47  if (not slotPairs) {
48  B2ERROR("TOPModuleT0DeltaTAlgorithm: histogram 'slots' not found");
49  return c_Failure;
50  }
51 
52  // construct file name and open output root file
53 
54  const auto& expRun = getRunList();
55  string expNo = to_string(expRun[0].first);
56  while (expNo.length() < 4) expNo.insert(0, "0");
57  string runNo = to_string(expRun[0].second);
58  while (runNo.length() < 5) runNo.insert(0, "0");
59  string outputFileName = "moduleT0_rough-e" + expNo + "-r" + runNo + ".root";
60  auto* file = TFile::Open(outputFileName.c_str(), "recreate");
61 
62  slotPairs->Write();
63 
64  // create vectors and a histogram to store the results of fits
65 
66  std::vector<double> deltaT0;
67  std::vector<double> sigma;
68  std::vector<std::vector<double> > A;
69  auto* chi2Fits = new TH2F("chi2_of_fits", "normalized chi2 of succesfull fits",
70  16, 0.5, 16.5, 16, 0.5, 16.5);
71  chi2Fits->SetXTitle("first slot number");
72  chi2Fits->SetYTitle("second slot number");
73 
74  // fit histograms of time differences and store the results
75 
76  for (int i = 0; i < slotPairs->GetNbinsX(); i++) {
77  for (int k = 0; k < slotPairs->GetNbinsY(); k++) {
78  if (slotPairs->GetBinContent(i + 1, k + 1) < m_minEntries) continue;
79  int slot1 = slotPairs->GetXaxis()->GetBinCenter(i + 1);
80  int slot2 = slotPairs->GetYaxis()->GetBinCenter(k + 1);
81  string name = "deltaT0_" + to_string(slot1) + "-" + to_string(slot2);
82  auto h = getObjectPtr<TH1F>(name);
83  if (not h) continue;
84  int status = fitHistogram(h);
85  if (status != 0) continue;
86  h->Write();
87  deltaT0.push_back(m_delT0);
88  sigma.push_back(m_error);
89  std::vector<double> a(16, 0);
90  a[slot1 - 1] = 1;
91  a[slot2 - 1] = -1;
92  A.push_back(a);
93  chi2Fits->SetBinContent(i + 1, k + 1, m_chi2 / m_ndf);
94  }
95  }
96 
97  // append the bound (sum of all calibration constants equals to 0)
98 
99  A.push_back(std::vector<double>(16, 1));
100  deltaT0.push_back(0);
101  sigma.push_back(0.001); // arbitrary but small compared to calibration precision
102 
103  // check degrees of freedom and return if not positive
104 
105  int m = deltaT0.size();
106  int ndf = m - 16;
107  if (ndf <= 0) {
108  file->Write();
109  file->Close();
110  B2INFO("TOPModuleT0DeltaTAlgorithm: NDF < 0");
111  return c_NotEnoughData;
112  }
113 
114  // construct the matrix of a linear system of equations
115 
116  TMatrixDSym B(16);
117  for (int i = 0; i < 16; i++) {
118  for (int j = 0; j < 16; j++) {
119  for (int k = 0; k < m; k++) {
120  B[i][j] += A[k][i] * A[k][j] / (sigma[k] * sigma[k]);
121  }
122  }
123  }
124 
125  // invert the matrix and return if not positive definite
126 
127  TDecompChol C(B); // Choletski decomposition to check also for positive definitness
128  bool ok = C.Invert(B);
129  if (not ok) {
130  file->Write();
131  file->Close();
132  B2INFO("TOPModuleT0DeltaTAlgorithm: matrix is not positive definite");
133  return c_NotEnoughData;
134  }
135 
136  // construct the right side of a linear system of equations
137 
138  std::vector<double> b(16, 0);
139  for (int i = 0; i < 16; i++) {
140  for (int k = 0; k < m; k++) {
141  b[i] += A[k][i] * deltaT0[k] / (sigma[k] * sigma[k]);
142  }
143  }
144 
145  // solve for unknown module T0's
146 
147  std::vector<double> x(16, 0); // module T0's
148  std::vector<double> e(16, 0); // uncertainties on module T0
149  for (int i = 0; i < 16; i++) {
150  for (int j = 0; j < 16; j++) {
151  x[i] += B[i][j] * b[j];
152  }
153  e[i] = sqrt(B[i][i]);
154  }
155 
156  // calculate chi^2
157 
158  double chi2 = 0;
159  for (int k = 0; k < m; k++) {
160  double s = 0;
161  for (int i = 0; i < 16; i++) {
162  s += A[k][i] * x[i];
163  }
164  chi2 += pow((s - deltaT0[k]) / sigma[k], 2);
165  }
166 
167  // store the results in a histogram
168 
169  stringstream ss;
170  ss.precision(3);
171  ss << "Module T0, chi^2/NDF = " << chi2 << "/" << ndf;
172  string title = ss.str();
173 
174  auto* h_moduleT0 = new TH1F("moduleT0", title.c_str(), 16, 0.5, 16.5);
175  h_moduleT0->SetXTitle("slot number");
176  h_moduleT0->SetYTitle("module T0 [ns]");
177  for (int i = 0; i < 16; i++) {
178  h_moduleT0->SetBinContent(i + 1, x[i]);
179  h_moduleT0->SetBinError(i + 1, e[i]);
180  }
181 
182  // write the results and close the file
183 
184  file->Write();
185  file->Close();
186 
187  // check the results and return if not good enough
188 
189  for (auto err : e) {
190  if (err > m_minError) return c_NotEnoughData;
191  }
192 
193  // otherwise create and import payload to DB
194 
195  auto* moduleT0 = new TOPCalModuleT0();
196  for (int i = 0; i < 16; i++) {
197  moduleT0->setT0(i + 1, x[i], e[i]);
198  }
199  moduleT0->suppressAverage();
200  saveCalibration(moduleT0);
201 
202  return c_OK;
203  }
204 
205 
206  int TOPModuleT0DeltaTAlgorithm::fitHistogram(std::shared_ptr<TH1F> h)
207  {
208  int numEntries = h->GetSumOfWeights();
209  int status = 0;
210  if (numEntries > m_cutoffEntries and m_tailFractInit > 0) {
211  status = fitDoubleGaus(h);
212  if (status != 0) status = fitSingleGaus(h);
213  } else {
214  status = fitSingleGaus(h);
215  }
216  return status;
217  }
218 
219 
220  int TOPModuleT0DeltaTAlgorithm::fitSingleGaus(std::shared_ptr<TH1F> h)
221  {
222  double sum = h->GetSumOfWeights();
223  if (sum < 5) return 5;
224  double maxPosition = h->GetBinCenter(h->GetMaximumBin());
225  double binWidth = h->GetBinWidth(1);
226  double xmin = h->GetXaxis()->GetXmin();
227  double xmax = h->GetXaxis()->GetXmax();
228 
229  auto* func = new TF1("func1g",
230  "[0] + [1]/sqrt(2*pi)/[3]*exp(-0.5*((x-[2])/[3])**2)",
231  xmin, xmax);
232  func->SetParameter(0, 0);
233  func->SetParameter(1, sum * binWidth);
234  func->SetParameter(2, maxPosition);
235  func->SetParameter(3, m_sigmaCoreInit);
236 
237  int status = h->Fit(func, "LERSQ");
238 
239  m_delT0 = func->GetParameter(2);
240  m_error = func->GetParError(2);
241  m_chi2 = func->GetChisquare();
242  m_ndf = func->GetNDF();
243 
244  return status;
245  }
246 
247 
248  int TOPModuleT0DeltaTAlgorithm::fitDoubleGaus(std::shared_ptr<TH1F> h)
249  {
250  double sum = h->GetSumOfWeights();
251  if (sum < 7) return 7;
252  double maxPosition = h->GetBinCenter(h->GetMaximumBin());
253  double binWidth = h->GetBinWidth(1);
254  double xmin = h->GetXaxis()->GetXmin();
255  double xmax = h->GetXaxis()->GetXmax();
256 
257  auto* func = new TF1("func2g",
258  "[0] + [1]*((1-[4])/sqrt(2*pi)/[3]*exp(-0.5*((x-[2])/[3])**2)"
259  "+ [4]/sqrt(2*pi)/[5]*exp(-0.5*((x-[2])/[5])**2))",
260  xmin, xmax);
261  func->SetParameter(0, 0);
262  func->SetParameter(1, sum * binWidth);
263  func->SetParameter(2, maxPosition);
264  func->SetParameter(3, m_sigmaCoreInit);
265  func->SetParameter(4, m_tailFractInit);
266  func->SetParameter(5, m_sigmaTailInit);
267 
268  int status = h->Fit(func, "LERSQ");
269 
270  m_delT0 = func->GetParameter(2);
271  m_error = func->GetParError(2);
272  m_chi2 = func->GetChisquare();
273  m_ndf = func->GetNDF();
274 
275  return status;
276  }
277 
278  } // end namespace TOP
280 } // end namespace Belle2
Belle2::TOP::TOPModuleT0DeltaTAlgorithm::m_tailFractInit
double m_tailFractInit
fraction of tail gaussian
Definition: TOPModuleT0DeltaTAlgorithm.h:113
Belle2::TOP::TOPModuleT0DeltaTAlgorithm::fitSingleGaus
int fitSingleGaus(std::shared_ptr< TH1F > h)
Fit single gaus + constant.
Definition: TOPModuleT0DeltaTAlgorithm.cc:220
Belle2::TOP::TOPModuleT0DeltaTAlgorithm::m_delT0
double m_delT0
fitted delta T0
Definition: TOPModuleT0DeltaTAlgorithm.h:118
Belle2::TOP::TOPModuleT0DeltaTAlgorithm::m_minError
double m_minError
minimal moduleT0 uncertainty [ns] to declare c_OK
Definition: TOPModuleT0DeltaTAlgorithm.h:115
Belle2::TOP::TOPModuleT0DeltaTAlgorithm::m_cutoffEntries
int m_cutoffEntries
cutoff entries for single/double gaussian fit
Definition: TOPModuleT0DeltaTAlgorithm.h:114
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::TOPModuleT0DeltaTAlgorithm::m_error
double m_error
error on fitted delta T0
Definition: TOPModuleT0DeltaTAlgorithm.h:119
Belle2::TOP::TOPModuleT0DeltaTAlgorithm::m_minEntries
int m_minEntries
minimal number of histogram entries to perform fit
Definition: TOPModuleT0DeltaTAlgorithm.h:110
Belle2::CalibrationAlgorithm::c_OK
@ c_OK
Finished successfuly =0 in Python.
Definition: CalibrationAlgorithm.h:51
Belle2::TOP::TOPModuleT0DeltaTAlgorithm::fitDoubleGaus
int fitDoubleGaus(std::shared_ptr< TH1F > h)
Fit double gaus w/ same mean + constant.
Definition: TOPModuleT0DeltaTAlgorithm.cc:248
Belle2::CalibrationAlgorithm::setDescription
void setDescription(const std::string &description)
Set algorithm description (in constructor)
Definition: CalibrationAlgorithm.h:331
Belle2::TOP::TOPModuleT0DeltaTAlgorithm::m_sigmaTailInit
double m_sigmaTailInit
tail gaussian sigma [ns]
Definition: TOPModuleT0DeltaTAlgorithm.h:112
Belle2::TOP::TOPModuleT0DeltaTAlgorithm::calibrate
virtual EResult calibrate() final
algorithm implementation
Definition: TOPModuleT0DeltaTAlgorithm.cc:40
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::TOP::TOPModuleT0DeltaTAlgorithm::fitHistogram
int fitHistogram(std::shared_ptr< TH1F > h)
Fit histogram.
Definition: TOPModuleT0DeltaTAlgorithm.cc:206
Belle2::CalibrationAlgorithm::c_Failure
@ c_Failure
Failed =3 in Python.
Definition: CalibrationAlgorithm.h:54
Belle2::TOP::TOPModuleT0DeltaTAlgorithm::m_sigmaCoreInit
double m_sigmaCoreInit
core gaussian sigma [ns]
Definition: TOPModuleT0DeltaTAlgorithm.h:111
Belle2::TOP::TOPModuleT0DeltaTAlgorithm::m_ndf
double m_ndf
NDF of the fit.
Definition: TOPModuleT0DeltaTAlgorithm.h:121
Belle2::CalibrationAlgorithm::EResult
EResult
The result of calibration.
Definition: CalibrationAlgorithm.h:50
Belle2::CalibrationAlgorithm::getRunList
const std::vector< Calibration::ExpRun > & getRunList() const
Get the list of runs for which calibration is called.
Definition: CalibrationAlgorithm.h:276
Belle2::CalibrationAlgorithm::c_NotEnoughData
@ c_NotEnoughData
Needs more data =2 in Python.
Definition: CalibrationAlgorithm.h:53
Belle2::CalibrationAlgorithm
Base class for calibration algorithms.
Definition: CalibrationAlgorithm.h:47
Belle2::TOPCalModuleT0
Module T0 calibration constants for all 16 modules.
Definition: TOPCalModuleT0.h:33
Belle2::TOP::TOPModuleT0DeltaTAlgorithm::m_chi2
double m_chi2
chi2 of the fit
Definition: TOPModuleT0DeltaTAlgorithm.h:120