Belle II Software development
TOPCommonT0BFAlgorithm.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 <top/calibration/TOPCommonT0BFAlgorithm.h>
10#include <top/dbobjects/TOPCalCommonT0.h>
11#include <math.h>
12#include <TROOT.h>
13#include <TF1.h>
14#include <TFile.h>
15#include <TTree.h>
16#include <string>
17
18using namespace std;
19
20namespace Belle2 {
25 namespace TOP {
26
28 CalibrationAlgorithm("TOPCommonT0BFCollector")
29 {
30 setDescription("Calibration algorithm for common T0 calibration "
31 "with a fit of bunch finder residuals (method BF)");
32
33 }
34
36 {
37 gROOT->SetBatch();
38
39 // get histogram to fit and check if statistics is sufficient
40
41 auto h = getHistogram();
42 if (not h) {
43 B2ERROR("TOPCommonT0BFAlgorithm: no histogram to fit");
44 return c_NotEnoughData;
45 }
46
47 int numEntries = h->GetSumOfWeights();
48 if (numEntries < m_minEntries) {
49 B2ERROR("TOPCommonT0BFAlgorithm: too few entries to fit the histogram");
50 return c_NotEnoughData;
51 }
52
53 m_bunchTimeSep = h->GetXaxis()->GetXmax() - h->GetXaxis()->GetXmin();
54
55 // construct file name, open output root file and book output tree
56
57 const auto& expRun = getRunList();
58 string expNo = to_string(expRun[0].first);
59 while (expNo.length() < 4) expNo.insert(0, "0");
60 string runNo = to_string(expRun[0].second);
61 while (runNo.length() < 5) runNo.insert(0, "0");
62 string outputFileName = "commonT0-e" + expNo + "-r" + runNo + ".root";
63 auto* file = TFile::Open(outputFileName.c_str(), "recreate");
64
65 auto* tree = new TTree("tree", "common T0 calibration results");
66 tree->Branch<int>("expNum", &m_expNo);
67 tree->Branch<int>("runNum", &m_runNo);
68 tree->Branch<int>("runLast", &m_runLast);
69 tree->Branch<float>("fitted_offset", &m_fittedOffset);
70 tree->Branch<float>("offset", &m_offset);
71 tree->Branch<float>("offsetErr", &m_offsetError);
72 tree->Branch<float>("sigma", &m_sigmaCore);
73 tree->Branch<float>("sigmaTail", &m_sigmaTail);
74 tree->Branch<float>("tailFract", &m_tailFract);
75 tree->Branch<float>("chi2", &m_chi2);
76 tree->Branch<float>("integral", &m_integral);
77 tree->Branch<int>("nEvt", &m_numEvents);
78 tree->Branch<int>("fitStatus", &m_fitStatus);
79
80 m_expNo = expRun[0].first;
81 m_runNo = expRun[0].second;
82 m_runLast = expRun.back().second;
83
84 // fit histogram
85
86 if (numEntries > m_cutoffEntries and m_tailFractInit > 0) {
87 int status = fitDoubleGaus(h);
88 if (status != 0) fitSingleGaus(h);
89 } else {
91 }
92 tree->Fill();
93
94 // write the results and close the file
95
96 h->Write();
97 file->Write();
98 file->Close();
99
100 // check the results and return if not good enough
101
103
104 // otherwise create and import payload to DB
105
106 auto* commonT0 = new TOPCalCommonT0(m_offset, m_offsetError);
107 saveCalibration(commonT0);
108
109 return c_OK;
110 }
111
113 {
114 auto h1a = getObjectPtr<TH1F>("offset_a");
115 auto h1b = getObjectPtr<TH1F>("offset_b");
116 if (not h1a) {
117 B2ERROR("TOPCommonT0BFAlgorithm: histogram 'offset_a' not found");
118 return 0;
119 }
120 if (not h1b) {
121 B2ERROR("TOPCommonT0BFAlgorithm: histogram 'offset_b' not found");
122 return 0;
123 }
124
125 int halfbins = h1a->GetNbinsX() / 2;
126 if (abs(h1a->GetMaximumBin() - halfbins) < abs(h1b->GetMaximumBin() - halfbins)) {
127 return h1a;
128 } else {
129 return h1b;
130 }
131 }
132
133 int TOPCommonT0BFAlgorithm::fitSingleGaus(std::shared_ptr<TH1F> h)
134 {
135 double sum = h->GetSumOfWeights();
136 if (sum < 5) return 5;
137 double maxPosition = h->GetBinCenter(h->GetMaximumBin());
138 double binWidth = h->GetBinWidth(1);
139 double xmin = h->GetXaxis()->GetXmin();
140 double xmax = h->GetXaxis()->GetXmax();
141
142 auto* func = new TF1("func1g",
143 "[0] + [1]/sqrt(2*pi)/[3]*exp(-0.5*((x-[2])/[3])**2)",
144 xmin, xmax);
145 func->SetParameter(0, 0);
146 func->SetParameter(1, sum * binWidth);
147 func->SetParameter(2, maxPosition);
148 func->SetParameter(3, m_sigmaCoreInit);
149
150 int status = h->Fit(func, "LRSQ");
151
152 m_fittedOffset = func->GetParameter(2);
154 m_offsetError = func->GetParError(2);
155 m_sigmaCore = func->GetParameter(3);
156 m_sigmaTail = 0;
157 m_tailFract = 0;
158 m_chi2 = func->GetChisquare() / func->GetNDF();
159 m_integral = func->GetParameter(1) / binWidth;
160 m_numEvents = sum;
161 m_fitStatus = status;
162
163 return status;
164 }
165
166
167 int TOPCommonT0BFAlgorithm::fitDoubleGaus(std::shared_ptr<TH1F> h)
168 {
169 double sum = h->GetSumOfWeights();
170 if (sum < 7) return 7;
171 double maxPosition = h->GetBinCenter(h->GetMaximumBin());
172 double binWidth = h->GetBinWidth(1);
173 double xmin = h->GetXaxis()->GetXmin();
174 double xmax = h->GetXaxis()->GetXmax();
175
176 auto* func = new TF1("func2g",
177 "[0] + [1]*((1-[4])/sqrt(2*pi)/[3]*exp(-0.5*((x-[2])/[3])**2)"
178 "+ [4]/sqrt(2*pi)/[5]*exp(-0.5*((x-[2])/[5])**2))",
179 xmin, xmax);
180 func->SetParameter(0, 0);
181 func->SetParameter(1, sum * binWidth);
182 func->SetParameter(2, maxPosition);
183 func->SetParameter(3, m_sigmaCoreInit);
184 func->SetParameter(4, m_tailFractInit);
185 func->SetParameter(5, m_sigmaTailInit);
186
187 int status = h->Fit(func, "LRSQ");
188
189 m_fittedOffset = func->GetParameter(2);
191 m_offsetError = func->GetParError(2);
192 m_sigmaCore = func->GetParameter(3);
193 m_sigmaTail = func->GetParameter(5);
194 m_tailFract = func->GetParameter(4);
195 m_chi2 = func->GetChisquare() / func->GetNDF();
196 m_integral = func->GetParameter(1) / binWidth;
197 m_numEvents = sum;
198 m_fitStatus = status;
199
200 return status;
201 }
202
203
204 } // end namespace TOP
206} // end namespace Belle2
Base class for calibration algorithms.
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
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.
Common T0 calibration constant.
int fitDoubleGaus(std::shared_ptr< TH1F > h)
Fit double gaus w/ same mean + constant.
float m_offsetError
error on fitted offset
int m_minEntries
minimal number of histogram entries to perform fit
float m_offset
wrap-around of fitted offset (= common T0)
virtual EResult calibrate() final
algorithm implementation
float m_tailFract
tail fraction (set to 0 for single gauss fit)
int m_numEvents
number of all events in the histogram
int m_cutoffEntries
cutoff entries for single/double gaussian fit
double m_sigmaTailInit
tail gaussian sigma [ns]
double m_minError
minimal commonT0 uncertainty [ns] to declare c_OK
double m_tailFractInit
fraction of tail gaussian
double m_sigmaCoreInit
core gaussian sigma [ns]
float m_integral
number of fitted signal events
float m_sigmaTail
tail gaussian sigma (set to 0 for single gauss fit)
double m_bunchTimeSep
bunch separation in time [ns]
int fitSingleGaus(std::shared_ptr< TH1F > h)
Fit single gaus + constant.
std::shared_ptr< TH1F > getHistogram()
Returns histogram to be fitted.
Abstract base class for different kinds of events.
STL namespace.