Belle II Software development
TimeWalkCalibration.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#include <cdc/calibration/TimeWalkCalibration.h>
9#include <cdc/dbobjects/CDCTimeWalks.h>
10#include <cdc/geometry/CDCGeometryPar.h>
11#include <cdc/dataobjects/WireID.h>
12
13#include <TF1.h>
14#include <TFile.h>
15#include <TChain.h>
16#include <TDirectory.h>
17#include <TROOT.h>
18#include <framework/utilities/FileSystem.h>
19#include <framework/database/DBImportObjPtr.h>
20#include <framework/database/DBObjPtr.h>
21#include <framework/database/IntervalOfValidity.h>
22#include <framework/logging/Logger.h>
23
24using namespace std;
25using namespace Belle2;
26using namespace CDC;
27
29{
30 // setDescription("CDC Time Walk Calibration");
31}
33{
34 double x;
35 double t_mea;
36 double w;
37 double t_fit;
38 double ndf;
39 double Pval;
40 unsigned short adc;
41 // int board;
42 int IWire;
43 int lay;
44
45 // auto& tree = getObject<TTree>("cdcCalib");
46 TChain* tree = new TChain("tree");
47 tree->Add(m_InputRootFileName.c_str());
48
49 tree->SetBranchAddress("lay", &lay);
50 tree->SetBranchAddress("IWire", &IWire);
51 tree->SetBranchAddress("x_u", &x);
52 tree->SetBranchAddress("t", &t_mea);
53 tree->SetBranchAddress("t_fit", &t_fit);
54 tree->SetBranchAddress("weight", &w);
55 tree->SetBranchAddress("ndf", &ndf);
56 tree->SetBranchAddress("Pval", &Pval);
57 tree->SetBranchAddress("adc", &adc);
58
59 /* Disable unused branch */
60 std::vector<TString> list_vars = {"lay", "IWire", "x_u", "t", "t_fit", "weight", "Pval", "ndf", "adc"};
61 tree->SetBranchStatus("*", 0);
62
63 for (TString brname : list_vars) {
64 tree->SetBranchStatus(brname, 1);
65 }
66
67
69 double halfCSize[56];
70 for (int i = 0; i < 56; ++i) {
71 double R = cdcgeo.senseWireR(i);
72 double nW = cdcgeo.nWiresInLayer(i);
73 halfCSize[i] = M_PI * R / nW;
74 }
75 int nEntries = tree->GetEntries();
76 B2INFO("Number of entry: " << nEntries);
77 //Histogram of each board
78 for (int i = 0; i < 300; ++i) {
79 m_h2[i] = new TH2D(Form("board_%d", i), Form("board_%d", i), 50, 0., 500, 60, -30, 30);
80 }
81
82 //read data
83 for (int i = 0; i < nEntries; ++i) {
84 tree->GetEntry(i);
85 double xmax = halfCSize[lay] - 0.12;
86 if ((fabs(x) < m_xmin) || (fabs(x) > xmax)
87 || (ndf < m_ndfmin)
88 || (Pval < m_Pvalmin)) continue; /*select good region*/
89
90 m_h2[cdcgeo.getBoardID(WireID(lay, IWire))]->Fill(adc, fabs(t_mea) - fabs(t_fit));
91 }
92 B2INFO("Reading data and filling histogram are done");
93}
94
96{
97 gROOT->SetBatch(1);
98 readTW();
100 TF1* fold = nullptr;
101 if (m_twParamMode_old == 0)
102 fold = new TF1("fold", "[0]/sqrt(x)", 0, 500);
103 else if (m_twParamMode_old == 1)
104 fold = new TF1("fold", "[0]*exp(-1*[1]*x)", 0, 500);
105 else
106 B2FATAL("Mode " << m_twParamMode_new << " haven't implemented yet.");
107
108 B2INFO("Old time walk formular: ");
109 fold->Print();
110 B2INFO("Time walk mode new: " << m_twParamMode_new << " with " << m_nTwParams_new << " parameters");
111 // double p3, p1;
112 m_tw_new[0].resize(m_nTwParams_new, 0.0); //for board 0, no available
113 for (int ib = 1; ib < 300; ++ib) {
114 m_flag[ib] = 1;
115 B2DEBUG(199, "Board ID:" << ib);
116 m_h2[ib]->SetDirectory(0);
117
118 // ignore if histogram is low statistic
119 if (m_h2[ib]->GetEntries() < 500) { m_flag[ib] = 0; continue;}
120 // do slide fit
121 m_h2[ib]->FitSlicesY(0, 1, -1, 10);
122 TString name = m_h2[ib]->GetName();
123 TString hm_name = name + "_1";
124 m_h1[ib] = (TH1D*)gDirectory->Get(hm_name);
125 if (!m_h1[ib]) {m_flag[ib] = 0; continue;}
126 m_h1[ib]->SetDirectory(0);
127
128 //if number of poist after slide fit quite low, ignore
129 if (m_h1[ib]->GetEntries() < 5) {
130 m_flag[ib] = 0;
131 B2WARNING("Low statistic, number of points after slice fit: " << m_h1[ib]->GetEntries());
132 continue;
133 }
134
135 // Add previous correction to this
136 for (int p = 0; p < m_nTwParams_old; ++p) {
137 fold->SetParameter(p, m_tw_old[ib][p]);
138 }
139 m_h1[ib]->Add(fold);
140 if (m_twParamMode_new == 0) {
141 TF1* func = new TF1("func", "[0]+[1]/sqrt(x)", 0, 500);
142 func->SetParameters(-4, 28);
143 m_h1[ib]->Fit("func", "MQ", "", 20, 150);
144 }//fit for mode 0
145 else if (m_twParamMode_new == 1) {
146 fitToExponentialFunc(m_h1[ib]);//do fitting for mode 1
147 } else {
148 B2FATAL("Mode " << m_twParamMode_new << " is not available, please check again");
149 }
150
151 // read fitted parameters
152 TF1* f1 = m_h1[ib]->GetFunction("func");
153 if (!f1) { m_flag[ib] = 0; continue;}
154 m_constTerm[ib] = f1->GetParameter(0);
155 m_tw_new[ib].resize(m_nTwParams_new, 0.0);
156 for (int i = 1; i <= m_nTwParams_new; ++i) {
157 m_tw_new[ib][i - 1] = f1->GetParameter(i);
158 }
159 B2DEBUG(199, "Prob of fitting:" << f1->GetProb());
160 B2DEBUG(199, "Fitting Param 0-1:" << f1->GetParameter(0) << " - " << f1->GetParameter(1));
161 }
162 //Write histogram to file
163 if (m_storeHisto) {
164 B2INFO("Storing histogram");
165 TFile* fhist = new TFile("tw_histo.root", "recreate");
166 TDirectory* old = gDirectory;
167 TDirectory* h1D = old->mkdir("h1D");
168 TDirectory* h2D = old->mkdir("h2D");
169 h1D->cd();
170 for (int ib = 1; ib < 300; ++ib) {
171 if (!m_h1[ib] || m_flag[ib] != 1) continue;
172 m_h1[ib]->SetDirectory(0);
173 if (m_h1[ib]->GetEntries() < 5) continue;
174
175 m_h1[ib]->SetMinimum(-5);
176 m_h1[ib]->SetMaximum(15);
177 m_h1[ib]->Write();
178 }
179 B2DEBUG(199, "Store 2D histogram");
180 h2D->cd();
181 for (int ib = 1; ib < 300; ++ib) {
182 if (m_h2[ib]) {
183 m_h2[ib]->SetDirectory(0);
184 m_h2[ib]->Write();
185 }
186 }
187 fhist->Close();
188 B2INFO("All hitograms were stored");
189 }
190 Write();
191 updateT0();
192 return true;
193}
195{
196 B2INFO("Store calibrated time walk parameters");
197 int nfailure(-1);//for no exist board; board 0;
198 // CDCTimeWalks* dbTw = new CDCTimeWalks();
200 dbTw.construct();
201
202 for (int ib = 0; ib < 300; ++ib) {
203 // If fitting fail and new mode is same as previous input mode. use old param
204 if (m_flag[ib] != 1) {
205 nfailure += 1;
207 dbTw->setTimeWalkParams(ib, m_tw_old[ib]);
208 } else {
209 //and even calibrated fail but mode is different from previous.
210 //in this case, param is zero
211 m_tw_new[ib].resize(m_nTwParams_new, 0.0);
212 dbTw->setTimeWalkParams(ib, m_tw_new[ib]);
213 }
214 } else {
215 //Use new param if board is successfuly calibrated
216 dbTw->setTimeWalkParams(ib, m_tw_new[ib]);
217 }
218 }
219 dbTw->setTwParamMode(m_twParamMode_new);
220 dbTw->outputToFile(m_outputTWFileName);
221 if (m_useDB) {
224 dbTw.import(iov);
225 }
226
227 B2RESULT("Failure to calibrate time-walk for " << nfailure << " board");
228 B2RESULT("Time-walk coeff. table wrote to " << m_outputTWFileName.c_str());
229}
231{
232 B2INFO("Add constant term into T0 database");
233 static CDCGeometryPar& cdcgeo = CDCGeometryPar::Instance();
234 ofstream ofs(m_outputT0FileName.c_str());
235 DBImportObjPtr<CDCTimeZeros> tz;// = new CDCTimeZeros();
236 tz.construct();
237 double T0;
238 //correct T0 and write
239 for (int ilay = 0; ilay < 56; ++ilay) {
240 for (unsigned int iwire = 0; iwire < cdcgeo.nWiresInLayer(ilay); ++iwire) {
241 WireID wireid(ilay, iwire);
242 int bID = cdcgeo.getBoardID(wireid);
243 T0 = cdcgeo.getT0(wireid);
244 if (m_flag[bID] == 1) {
245 ofs << ilay << "\t" << iwire << "\t" << T0 - m_constTerm[bID] << std::endl;
246 if (m_useDB)
247 tz->setT0(wireid, T0 - m_constTerm[bID]);
248 } else {
249 ofs << ilay << "\t" << iwire << "\t" << T0 << std::endl;
250 if (m_useDB)
251 tz->setT0(wireid, T0 - m_constTerm[bID]);
252 }
253 }
254 }
255 ofs.close();
256 if (m_useDB) {
259 tz.import(iov);
260 }
261 B2RESULT("updated constant term of tw correction to T0 constant.");
262}
264{
265 h1->SetDirectory(0);
266 int max = h1->GetMaximumBin();
267 double maxX = h1->GetBinCenter(max);
268 double maxY = h1->GetBinContent(max);
269 B2DEBUG(199, "Max: id - x - y : " << max << " " << maxX << " " << maxY);
270
271 //search for p0
272 double p0 = -1;
273 h1->Fit("pol0", "MQE", "", maxX + 125, 500);
274 if (h1->GetFunction("pol0")) {
275 p0 = h1->GetFunction("pol0")->GetParameter(0);
276 }
277 //create histo = old-p0;
278 // fit with expo function to find intial parameters
279 TH1D* hshift = new TH1D("hshift", "shift", h1->GetNbinsX(), 0, 500);
280 hshift->SetDirectory(0);
281 for (int i = 0; i <= h1->GetNbinsX(); ++i) {
282 hshift->SetBinContent(i, h1->GetBinContent(i) - p0);
283 }
284 hshift->Fit("expo", "MQE", "", 0, 400);
285 double p1 = maxY + p0;
286 double p2 = -0.04;
287 if (hshift->GetFunction("expo")) {
288 p1 = exp(hshift->GetFunction("expo")->GetParameter(0));
289 p2 = hshift->GetFunction("expo")->GetParameter(1);
290 }
291
292 // fit with function
293 TF1* func = new TF1("func", "[0]+ [1]*exp(-1*[2]*x)", 0, 500);
294 func->SetParameters(p0, p1, -1 * p2);
295 func->SetParLimits(0, -5, 5);
296 func->SetParLimits(1, -5, 500);
297 func->SetParLimits(2, -0.01, 0.1);
298 h1->Fit("func", "MQE", "", 10, 400);
299}
301{
302 if (m_useDB) {
304 m_twParamMode_old = oldDB->getTwParamMode();
305 for (int ib = 0; ib < 300; ++ib) {
306 m_tw_old[ib] = oldDB->getTimeWalkParams(ib);
307 }
308 } else {
309 //For text mode
310 std::string fileName1 = "/data/cdc" + m_InputTWFileName;
311 std::string fileName = FileSystem::findFile(fileName1);
312 ifstream ifs;
313 if (fileName == "") {
315 }
316 if (fileName == "") {
317 B2FATAL("CDCGeometryPar: " << fileName1 << " not exist!");
318 } else {
319 B2INFO("Time Walk Calibration: open " << fileName);
320 ifs.open(fileName.c_str());
321 if (!ifs) B2FATAL("CDCGeometryPar: cannot open " << fileName1 << " !");
322 }
323
324 unsigned short iBoard(0);
325 int nRead(0);
326 double dumy(0.);// dumy2(0.), dumy3(0.);
328 while (ifs >> iBoard) {
329 m_tw_old[iBoard].resize(m_nTwParams_old);
330 for (int i = 0; i < m_nTwParams_old; ++i) {
331 ifs >> dumy;
332 m_tw_old[iBoard][i] = dumy;
333 }
334 ++nRead;
335 }
336 if (nRead - 1 != 299) B2FATAL("#lines read-in (=" << nRead << ") is not equal #boards 299 !");
337 ifs.close();
338 B2INFO("TW from database: mode = " << m_twParamMode_old << " with " << m_nTwParams_old << " parameters");
339 }
340}
double R
typedef autogenerated by FFTW
The Class for CDC Geometry Parameters.
unsigned short getBoardID(const WireID &wID) const
Returns frontend board id. corresponding to the wire id.
float getT0(const WireID &wireID) const
Returns t0 parameter of the specified sense wire.
unsigned nWiresInLayer(int layerId) const
Returns wire numbers in a layer.
static CDCGeometryPar & Instance(const CDCGeometry *=nullptr)
Static method to get a reference to the CDCGeometryPar instance.
double senseWireR(int layerId) const
Returns radius of sense wire in each layer.
unsigned short m_twParamMode_new
=0 for P0/Sqrt(ADC); =1 for P0*Exp(-P1*ADC).
double m_xmin
minimum value cut of drift length.
virtual void readTW()
read tw from database
std::string m_outputT0FileName
Output tw file name for time walk.
TH2D * m_h2[300]
2D histogram of residual vs ADC for each board
double m_constTerm[300]
const term in fitting, it will be added to T0 instead tw
bool m_storeHisto
Store all Histogram or not.
double m_ndfmin
minimum number of degree of freedom required for track.
unsigned short m_flag[300]
flag for fit status
virtual void updateT0()
update constant term to t0 database.
std::vector< float > m_tw_old[300]
tw list old.
virtual void Write()
save calibration
std::string m_InputTWFileName
Old tw file name.
std::string m_outputTWFileName
Output tw file name for time walk.
std::vector< float > m_tw_new[300]
tw list new.
virtual bool calibrate()
Run algorithm.
virtual void CreateHisto()
Create histo for calibrate.
std::string m_InputRootFileName
root input file name.
virtual void fitToExponentialFunc(TH1D *h1)
fit tw histogram
unsigned short m_twParamMode_old
=0 for P0/Sqrt(ADC); =1 for P0*Exp(-P1*ADC).
TH1D * m_h1[300]
Mean of residual as function of ADC of each board.
double m_Pvalmin
minimum number of Prob(chi2) of fitted track.
bool m_useDB
flag to switch btw text mode and database.
bool import(const IntervalOfValidity &iov)
Import the object to database.
Definition: DBImportBase.cc:36
Class for importing a single object to the database.
void construct(Args &&... params)
Construct an object of type T in this DBImportObjPtr using the provided constructor arguments.
Class for accessing objects in the database.
Definition: DBObjPtr.h:21
static std::string findFile(const std::string &path, bool silent=false)
Search for given file or directory in local or central release directory, and return absolute path if...
Definition: FileSystem.cc:151
A class that describes the interval of experiments/runs for which an object in the database is valid.
Class to identify a wire inside the CDC.
Definition: WireID.h:34
Abstract base class for different kinds of events.
STL namespace.