8 #include <cdc/calibration/TimeWalkCalibration.h>
9 #include <cdc/dbobjects/CDCTimeWalks.h>
10 #include <cdc/geometry/CDCGeometryPar.h>
11 #include <cdc/dataobjects/WireID.h>
16 #include <TDirectory.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>
28 TimeWalkCalibration::TimeWalkCalibration()
32 void TimeWalkCalibration::CreateHisto()
46 TChain* tree =
new TChain(
"tree");
47 tree->Add(m_InputRootFileName.c_str());
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);
60 std::vector<TString> list_vars = {
"lay",
"IWire",
"x_u",
"t",
"t_fit",
"weight",
"Pval",
"ndf",
"adc"};
61 tree->SetBranchStatus(
"*", 0);
63 for (TString brname : list_vars) {
64 tree->SetBranchStatus(brname, 1);
70 for (
int i = 0; i < 56; ++i) {
73 halfCSize[i] = M_PI *
R / nW;
75 int nEntries = tree->GetEntries();
76 B2INFO(
"Number of entry: " << nEntries);
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);
83 for (
int i = 0; i < nEntries; ++i) {
85 double xmax = halfCSize[lay] - 0.12;
86 if ((fabs(x) < m_xmin) || (fabs(x) > xmax)
88 || (Pval < m_Pvalmin))
continue;
90 m_h2[cdcgeo.
getBoardID(
WireID(lay, IWire))]->Fill(adc, fabs(t_mea) - fabs(t_fit));
92 B2INFO(
"Reading data and filling histogram are done");
95 bool TimeWalkCalibration::calibrate()
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);
106 B2FATAL(
"Mode " << m_twParamMode_new <<
" haven't implemented yet.");
108 B2INFO(
"Old time walk formular: ");
110 B2INFO(
"Time walk mode new: " << m_twParamMode_new <<
" with " << m_nTwParams_new <<
" parameters");
112 m_tw_new[0].resize(m_nTwParams_new, 0.0);
113 for (
int ib = 1; ib < 300; ++ib) {
115 B2DEBUG(199,
"Board ID:" << ib);
116 m_h2[ib]->SetDirectory(0);
119 if (m_h2[ib]->GetEntries() < 500) { m_flag[ib] = 0;
continue;}
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);
129 if (m_h1[ib]->GetEntries() < 5) {
131 B2WARNING(
"Low statistic, number of points after slice fit: " << m_h1[ib]->GetEntries());
136 for (
int p = 0; p < m_nTwParams_old; ++p) {
137 fold->SetParameter(p, m_tw_old[ib][p]);
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);
145 else if (m_twParamMode_new == 1) {
146 fitToExponentialFunc(m_h1[ib]);
148 B2FATAL(
"Mode " << m_twParamMode_new <<
" is not available, please check again");
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);
159 B2DEBUG(199,
"Prob of fitting:" << f1->GetProb());
160 B2DEBUG(199,
"Fitting Param 0-1:" << f1->GetParameter(0) <<
" - " << f1->GetParameter(1));
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");
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;
175 m_h1[ib]->SetMinimum(-5);
176 m_h1[ib]->SetMaximum(15);
179 B2DEBUG(199,
"Store 2D histogram");
181 for (
int ib = 1; ib < 300; ++ib) {
183 m_h2[ib]->SetDirectory(0);
188 B2INFO(
"All hitograms were stored");
194 void TimeWalkCalibration::Write()
196 B2INFO(
"Store calibrated time walk parameters");
202 for (
int ib = 0; ib < 300; ++ib) {
204 if (m_flag[ib] != 1) {
206 if (m_twParamMode_old == m_twParamMode_new) {
207 dbTw->setTimeWalkParams(ib, m_tw_old[ib]);
211 m_tw_new[ib].resize(m_nTwParams_new, 0.0);
212 dbTw->setTimeWalkParams(ib, m_tw_new[ib]);
216 dbTw->setTimeWalkParams(ib, m_tw_new[ib]);
219 dbTw->setTwParamMode(m_twParamMode_new);
220 dbTw->outputToFile(m_outputTWFileName);
223 m_lastExperiment, m_lastRun);
227 B2RESULT(
"Failure to calibrate time-walk for " << nfailure <<
" board");
228 B2RESULT(
"Time-walk coeff. table wrote to " << m_outputTWFileName.c_str());
230 void TimeWalkCalibration::updateT0()
232 B2INFO(
"Add constant term into T0 database");
234 ofstream ofs(m_outputT0FileName.c_str());
239 for (
int ilay = 0; ilay < 56; ++ilay) {
240 for (
unsigned int iwire = 0; iwire < cdcgeo.
nWiresInLayer(ilay); ++iwire) {
241 WireID wireid(ilay, iwire);
243 T0 = cdcgeo.
getT0(wireid);
244 if (m_flag[bID] == 1) {
245 ofs << ilay <<
"\t" << iwire <<
"\t" << T0 - m_constTerm[bID] << std::endl;
247 tz->setT0(wireid, T0 - m_constTerm[bID]);
249 ofs << ilay <<
"\t" << iwire <<
"\t" << T0 << std::endl;
251 tz->setT0(wireid, T0 - m_constTerm[bID]);
258 m_lastExperiment, m_lastRun);
261 B2RESULT(
"updated constant term of tw correction to T0 constant.");
263 void TimeWalkCalibration::fitToExponentialFunc(TH1D* h1)
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);
273 h1->Fit(
"pol0",
"MQE",
"", maxX + 125, 500);
274 if (h1->GetFunction(
"pol0")) {
275 p0 = h1->GetFunction(
"pol0")->GetParameter(0);
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);
284 hshift->Fit(
"expo",
"MQE",
"", 0, 400);
285 double p1 = maxY + p0;
287 if (hshift->GetFunction(
"expo")) {
288 p1 = exp(hshift->GetFunction(
"expo")->GetParameter(0));
289 p2 = hshift->GetFunction(
"expo")->GetParameter(1);
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);
300 void TimeWalkCalibration::readTW()
304 m_twParamMode_old = oldDB->getTwParamMode();
305 for (
int ib = 0; ib < 300; ++ib) {
306 m_tw_old[ib] = oldDB->getTimeWalkParams(ib);
310 std::string fileName1 =
"/data/cdc" + m_InputTWFileName;
311 std::string fileName = FileSystem::findFile(fileName1);
313 if (fileName ==
"") {
314 fileName = FileSystem::findFile(m_InputTWFileName);
316 if (fileName ==
"") {
317 B2FATAL(
"CDCGeometryPar: " << fileName1 <<
" not exist!");
319 B2INFO(
"Time Walk Calibration: open " << fileName);
320 ifs.open(fileName.c_str());
321 if (!ifs) B2FATAL(
"CDCGeometryPar: cannot open " << fileName1 <<
" !");
324 unsigned short iBoard(0);
327 ifs >> m_twParamMode_old >> m_nTwParams_old;
328 while (ifs >> iBoard) {
329 m_tw_old[iBoard].resize(m_nTwParams_old);
330 for (
int i = 0; i < m_nTwParams_old; ++i) {
332 m_tw_old[iBoard][i] = dumy;
336 if (nRead - 1 != 299) B2FATAL(
"#lines read-in (=" << nRead <<
") is not equal #boards 299 !");
338 B2INFO(
"TW from database: mode = " << m_twParamMode_old <<
" with " << m_nTwParams_old <<
" parameters");
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.
double senseWireR(int layerId) const
Returns radius of sense wire in each layer.
bool import(const IntervalOfValidity &iov)
Import the object to database.
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.
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.
Abstract base class for different kinds of events.