Project
Loading...
Searching...
No Matches
CalibTOF.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11#include <TTree.h>
12#include <cassert>
13
14#include <fairlogger/Logger.h>
15#include "TOFBase/Geo.h"
16
17#include <TFile.h>
20
22
24
25#include "TMath.h"
26#include "TRandom.h"
27
28using namespace o2::globaltracking;
29
31
32//______________________________________________
34{
35
36 // constructor needed to instantiate the pointers of the class (histos + array)
37
38 for (int ipad = 0; ipad < NPADSPERSTEP; ipad++) {
39 }
40 mHistoChTimeSlewingAll = new TH2F("hTOFchTimeSlewingAll", ";tot (ns);t - t_{exp} - t_{offset} (ps)", 5000, 0., 250., 1000, -24400., 24400.);
41}
42//______________________________________________
44{
45
46 // destructor
47
48 if (mHistoLHCphase) {
49 delete mHistoLHCphase;
50 }
51 delete mHistoChTimeSlewingAll;
52}
53//______________________________________________
54void CalibTOF::attachInputTrees()
55{
57
58 if (!mTreeCollectedCalibInfoTOF) {
59 LOG(fatal) << "Input tree with collected TOF calib infos is not set";
60 }
61
62 if (!mTreeCollectedCalibInfoTOF->GetBranch(mCollectedCalibInfoTOFBranchName.data())) {
63 LOG(fatal) << "Did not find collected TOF calib info branch " << mCollectedCalibInfoTOFBranchName << " in the input tree";
64 }
65 /*
66 LOG(info) << "Attached tracksTOF calib info " << mCollectedCalibInfoTOFBranchName << " branch with " << mTreeCollectedCalibInfoTOF->GetEntries()
67 << " entries";
68 */
69}
70
71//______________________________________________
73{
75
76 if (mInitDone) {
77 LOG(error) << "Initialization was already done";
78 return;
79 }
80
81 TH1::AddDirectory(0); // needed because we have the LHCPhase created here, while in the macro we might have the output file open
82 // (we don't want to bind the histogram to the file, or teh destructor will complain)
83
84 attachInputTrees();
85
86 std::fill_n(mCalibChannelOffset, o2::tof::Geo::NCHANNELS, 0);
87 std::fill_n(mCalibChannelOffsetErr, o2::tof::Geo::NCHANNELS, -1);
88 std::fill_n(mInitialCalibChannelOffset, o2::tof::Geo::NCHANNELS, 0);
89
90 // this is only to test random offsets!!!!
91 for (int i = 0; i < o2::tof::Geo::NCHANNELS; i++) {
92 mInitialCalibChannelOffset[i] = gRandom->Rndm() * 25000 - 12500;
93 }
94
95 // load better knoldge of channel offset (from CCDB?)
96 // to be done
97
98 // create output branch with output -- for now this is empty
99 if (mOutputTree) {
100 mLHCphaseObj = new o2::dataformats::CalibLHCphaseTOF();
101 mTimeSlewingObj = new o2::dataformats::CalibTimeSlewingParamTOF();
102 mOutputTree->Branch("mLHCphaseObj", &mLHCphaseObj);
103 mOutputTree->Branch("mTimeSlewingObj", &mTimeSlewingObj);
104
105 // LOG(info) << "Matched tracks will be stored in " << mOutputBranchName << " branch of tree "
106 // << mOutputTree->GetName();
107 } else {
108 LOG(error) << "Output tree is not attached, matched tracks will not be stored";
109 }
110
111 // booking the histogram of the LHCphase
112 int nbinsLHCphase = TMath::Min(1000, int((mMaxTimestamp - mMinTimestamp) / 300) + 1);
113 if (nbinsLHCphase < 1000) {
114 mMaxTimestamp = mMinTimestamp + nbinsLHCphase * 300; // we want that the last bin of the histogram is also large 300s; this we need to do only when we have less than 1000 bins, because in this case we will integrate over intervals that are larger than 300s anyway
115 }
116 mHistoLHCphase = new TH2F("hLHCphase", ";clock offset (ps); timestamp (s)", 1000, -24400, 24400, nbinsLHCphase, mMinTimestamp, mMaxTimestamp);
117
118 // setting CCDB for output
119 mCalibTOFapi.setURL(mCCDBpath.c_str());
120
121 mInitDone = true;
122
123 print();
124}
125//______________________________________________
126void CalibTOF::run(int flag, int sector)
127{
129
130 Int_t currTOFInfoTreeEntry = -1;
131
132 std::vector<o2::dataformats::CalibInfoTOFshort>* localCalibInfoTOF = nullptr;
133 TFile fOpenLocally(mTreeCollectedCalibInfoTOF->GetCurrentFile()->GetName());
134 TTree* localTree = (TTree*)fOpenLocally.Get(mTreeCollectedCalibInfoTOF->GetName());
135
136 if (!localTree) {
137 LOG(fatal) << "tree " << mTreeCollectedCalibInfoTOF->GetName() << " not found in " << mTreeCollectedCalibInfoTOF->GetCurrentFile()->GetName();
138 }
139
140 localTree->SetBranchAddress(mCollectedCalibInfoTOFBranchName.data(), &localCalibInfoTOF);
141
142 if (!mInitDone) {
143 LOG(fatal) << "init() was not done yet";
144 }
145
146 TStopwatch timerTot;
147 timerTot.Start();
148
149 if (flag & kLHCphase) { // LHC phase --> we will use all the entries in the tree
150 while (loadTOFCollectedCalibInfo(localTree, currTOFInfoTreeEntry)) { // fill here all histos you need
151 fillLHCphaseCalibInput(localCalibInfoTOF); // we will fill the input for the LHC phase calibration
152 }
153 doLHCPhaseCalib();
154 }
155 // channel offset + problematic (flag = 2), or time slewing (flag = 4)
156 if ((flag & kChannelOffset) || (flag & kChannelTimeSlewing)) { // for the moment compute everything idependetly of the flag
157 TH1F* histoChOffsetTemp[NPADSPERSTEP];
158 std::vector<o2::dataformats::CalibInfoTOFshort>* calibTimePad[NPADSPERSTEP];
159 for (int ipad = 0; ipad < NPADSPERSTEP; ipad++) {
160 histoChOffsetTemp[ipad] = new TH1F(Form("OffsetTemp_Sec%02d_Pad%04d", sector, ipad), Form("Sector %02d (pad = %04d);channel offset (ps)", sector, ipad), 1000, -24400, 24400);
161 if (flag & kChannelTimeSlewing) {
162 calibTimePad[ipad] = new std::vector<o2::dataformats::CalibInfoTOFshort>; // temporary array containing [time, tot] for every pad that we process; this will be the input for the 2D histo for timeSlewing calibration (to be filled after we get the channel offset)
163 } else {
164 calibTimePad[ipad] = nullptr;
165 }
166 }
167
168 TF1* funcChOffset = new TF1(Form("fTOFchOffset_%02d", sector), "[0]*TMath::Gaus((x-[1])*(x-[1] < 12500 && x-[1] > -12500) + (x-[1]+25000)*(x-[1] < -12500) + (x-[1]-25000)*(x-[1] > 12500),0,[2])*(x > -12500 && x < 12500)", -12500, 12500);
169 funcChOffset->SetParLimits(1, -12500, 12500);
170 funcChOffset->SetParLimits(2, 50, 2000);
171
172 TH2F* histoChTimeSlewingTemp = new TH2F(Form("hTOFchTimeSlewingTemp_%02d", sector), Form("Sector %02d;tot (ns);t - t_{exp} - t_{offset} (ps)", sector), 5000, 0., 250., 1000, -24400., 24400.);
173
174 int startLoop = 0; // first pad that we will process in this process (we are processing a sector, unless sector = -1)
175 int endLoop = o2::tof::Geo::NCHANNELS; // last pad that we will process in this process (we are processing a sector)
176 if (sector > -1) {
177 startLoop = sector * o2::tof::Geo::NPADSXSECTOR; // first pad that we will process in this process (we are processing a sector, unless sector = -1)
178 endLoop = startLoop + o2::tof::Geo::NPADSXSECTOR; // last pad that we will process in this process (we are processing a sector, unless sector = -1)
179 }
180 for (int ich = startLoop; ich < endLoop; ich += NPADSPERSTEP) {
181 sector = ich / o2::tof::Geo::NPADSXSECTOR; // we change the value of sector which is needed when it is "-1" to put
182 // in the output histograms a meaningful name; this is not needed in
183 // case we run with sector != -1, but it will not hurt :)
184 resetChannelLevelHistos(histoChOffsetTemp, histoChTimeSlewingTemp, calibTimePad);
185 printf("strip %i\n", ich / 96);
186 currTOFInfoTreeEntry = ich - 1;
187 int ipad = 0;
188 int entryNext = currTOFInfoTreeEntry + o2::tof::Geo::NCHANNELS;
189
190 while (loadTOFCollectedCalibInfo(localTree, currTOFInfoTreeEntry)) { // fill here all histos you need
191
192 histoChOffsetTemp[ipad]->SetName(Form("OffsetTemp_Sec%02d_Pad%04d", sector, (ipad + ich) % o2::tof::Geo::NPADSXSECTOR));
193 fillChannelCalibInput(localCalibInfoTOF, mInitialCalibChannelOffset[ich + ipad], ipad, histoChOffsetTemp[ipad], calibTimePad[ipad]); // we will fill the input for the channel-level calibration
194 ipad++;
195
196 if (ipad == NPADSPERSTEP) {
197 ipad = 0;
198 currTOFInfoTreeEntry = entryNext;
199 entryNext += o2::tof::Geo::NCHANNELS;
200 }
201 }
202 TFile* fout = nullptr;
203 if (flag & kChannelTimeSlewing && mDebugMode) {
204 fout = new TFile(Form("timeslewingTOF%06i.root", ich / 96), "RECREATE");
205 }
206
207 for (ipad = 0; ipad < NPADSPERSTEP; ipad++) {
208 if (histoChOffsetTemp[ipad]->GetEntries() > 30) {
209 float fractionUnderPeak = doChannelCalibration(ipad, histoChOffsetTemp[ipad], funcChOffset);
210 mCalibChannelOffset[ich + ipad] = funcChOffset->GetParameter(1) + mInitialCalibChannelOffset[ich + ipad];
211
212 int channelInSector = (ipad + ich) % o2::tof::Geo::NPADSXSECTOR;
213
214 mTimeSlewingObj->setFractionUnderPeak(sector, channelInSector, fractionUnderPeak);
215 mTimeSlewingObj->setSigmaPeak(sector, channelInSector, std::abs(funcChOffset->GetParameter(2)));
216
217 // now fill 2D histo for time-slewing using current channel offset
218
219 if (flag & kChannelTimeSlewing) {
220 histoChTimeSlewingTemp->Reset();
221 fillChannelTimeSlewingCalib(mCalibChannelOffset[ich + ipad], ipad, histoChTimeSlewingTemp, calibTimePad[ipad]); // we will fill the input for the channel-time-slewing calibration
222
223 histoChTimeSlewingTemp->SetName(Form("TimeSlewing_Sec%02d_Pad%04d", sector, channelInSector));
224 histoChTimeSlewingTemp->SetTitle(Form("Sector %02d (pad = %04d)", sector, channelInSector));
225 TGraphErrors* gTimeVsTot = processSlewing(histoChTimeSlewingTemp, 1, funcChOffset);
226
227 if (gTimeVsTot && gTimeVsTot->GetN()) {
228 for (int itot = 0; itot < gTimeVsTot->GetN(); itot++) {
229 mTimeSlewingObj->addTimeSlewingInfo(ich + ipad, gTimeVsTot->GetX()[itot], gTimeVsTot->GetY()[itot] + mCalibChannelOffset[ich + ipad]);
230 }
231 } else { // just add the channel offset
232 mTimeSlewingObj->addTimeSlewingInfo(ich + ipad, 0, mCalibChannelOffset[ich + ipad]);
233 }
234
235 if (mDebugMode && gTimeVsTot && gTimeVsTot->GetN() && fout) {
236 fout->cd();
237 int istrip = ((ich + ipad) / o2::tof::Geo::NPADS) % o2::tof::Geo::NSTRIPXSECTOR;
238 gTimeVsTot->SetName(Form("pad_%02d_%02d_%02d", sector, istrip, ipad % o2::tof::Geo::NPADS));
239 gTimeVsTot->Write();
240 // histoChTimeSlewingTemp->Write(Form("histoChTimeSlewingTemp_%02d_%02d_%02d", sector, istrip, ipad%o2::tof::Geo::NPADS)); // no longer written since it produces a very large output
241 }
242 } else if (flag & kChannelOffset) {
243 mTimeSlewingObj->addTimeSlewingInfo(ich + ipad, 0, mCalibChannelOffset[ich + ipad]);
244 }
245 }
246 }
247 if (fout) {
248 fout->Close();
249 delete fout;
250 }
251 }
252
253 for (int ipad = 0; ipad < NPADSPERSTEP; ipad++) {
254 delete histoChOffsetTemp[ipad];
255 if (calibTimePad[ipad]) {
256 delete calibTimePad[ipad];
257 }
258 }
259 delete histoChTimeSlewingTemp;
260 delete funcChOffset;
261 }
262
263 fOpenLocally.Close();
264
265 timerTot.Stop();
266 printf("Timing (%i):\n", sector);
267 printf("Total: ");
268 timerTot.Print();
269}
270
271//______________________________________________
273{
274 mOutputTree->Fill();
275
276 if (mFillCCDB) {
277 if (flag & kLHCphase) {
278 std::map<std::string, std::string> metadataLHCphase; // can be empty
279 mCalibTOFapi.writeLHCphase(mLHCphaseObj, metadataLHCphase, (uint64_t)mMinTimestamp * 1000, (uint64_t)mMaxTimestamp * 1000); // we use as validity the timestamps that we got from the input for the calibration; but we need to convert to ms for the CCDB (at least for now that we use an integer for the timestamp)
280 }
281 if (flag & kChannelOffset || flag & kChannelTimeSlewing) {
282 std::map<std::string, std::string> metadataChannelCalib; // can be empty
283 mCalibTOFapi.writeTimeSlewingParam(mTimeSlewingObj, metadataChannelCalib, (uint64_t)mMinTimestamp * 1000); // contains both offset and time slewing; we use as validity the START ONLY timestamp that we got from the input for the calibration; but we need to convert to ms for the CCDB (at least for now that we use an integer for the timestamp), END is default
284 }
285 }
286}
287
288//______________________________________________
289void CalibTOF::print() const
290{
292
293 LOG(info) << "****** component for calibration of TOF channels ******";
294 if (!mInitDone) {
295 LOG(info) << "init is not done yet - nothing to print";
296 return;
297 }
298
299 LOG(info) << "**********************************************************************";
300}
301
302//______________________________________________
303bool CalibTOF::loadTOFCollectedCalibInfo(TTree* localTree, int& currententry, int increment)
304{
306 // printf("Loading TOF calib infos: number of entries in tree = %lld\n", mTreeCollectedCalibInfoTOF->GetEntries());
307
308 currententry += increment;
309 while (currententry < localTree->GetEntries()) {
310 //while (currententry < 800000){
311 // && currententry < o2::tof::Geo::NCHANNELS) {
312 localTree->GetEntry(currententry);
313 //LOG(info) << "Loading TOF calib info entry " << currententry << " -> " << mCalibInfoTOF->size()<< " infos";
314
315 return true;
316 }
317 currententry -= increment;
318
319 return false;
320}
321
322//______________________________________________
323
324void CalibTOF::fillLHCphaseCalibInput(std::vector<o2::dataformats::CalibInfoTOFshort>* calibinfotof)
325{
326
327 // we will fill the input for the LHC phase calibration
328
329 static double bc = 1.e13 / o2::constants::lhc::LHCRFFreq; // bunch crossing period (ps)
330 static double bc_inv = 1. / bc;
331
332 for (auto infotof = calibinfotof->begin(); infotof != calibinfotof->end(); infotof++) {
333 double dtime = infotof->getDeltaTimePi();
334 dtime -= (int(dtime * bc_inv + 5.5) - 5) * bc; // do truncation far (by 5 units) from zero to avoid truncation of negative numbers
335
336 mHistoLHCphase->Fill(dtime, infotof->getTimestamp());
337 }
338}
339//______________________________________________
340
341void CalibTOF::doLHCPhaseCalib()
342{
343
344 // calibrate with respect LHC phase
345
346 if (!mFuncLHCphase) {
347 mFuncLHCphase = new TF1("fLHCphase", "gaus");
348 }
349
350 int ifit0 = 1;
351 for (int ifit = ifit0; ifit <= mHistoLHCphase->GetNbinsY(); ifit++) {
352 TH1D* htemp = mHistoLHCphase->ProjectionX("htemp", ifit0, ifit);
353 if (htemp->GetEntries() < 300) {
354 // we cannot fit the histogram, we will merge with the next bin
355 // Printf("We don't have enough entries to fit");
356 continue;
357 }
358
359 int res = FitPeak(mFuncLHCphase, htemp, 500., 3., 2., "LHCphase");
360 if (res) {
361 continue;
362 }
363
364 mLHCphaseObj->addLHCphase(mHistoLHCphase->GetYaxis()->GetBinLowEdge(ifit0), mFuncLHCphase->GetParameter(1));
365 ifit0 = ifit + 1; // starting point for the next LHC interval
366 }
367}
368//______________________________________________
369
370void CalibTOF::fillChannelCalibInput(std::vector<o2::dataformats::CalibInfoTOFshort>* calibinfotof, float offset, int ipad, TH1F* histo, std::vector<o2::dataformats::CalibInfoTOFshort>* calibTimePad)
371{
372
373 // we will fill the input for the channel-level calibration
374
375 static double bc = 1.e13 / o2::constants::lhc::LHCRFFreq; // bunch crossing period (ps)
376 static double bc_inv = 1. / bc;
377
378 for (auto infotof = calibinfotof->begin(); infotof != calibinfotof->end(); infotof++) {
379 double dtime = infotof->getDeltaTimePi() - offset; // removing existing offset
380 dtime -= (int(dtime * bc_inv + 5.5) - 5) * bc; // do truncation far (by 5 units) from zero to avoid truncation of negative numbers
381
382 histo->Fill(dtime);
383 if (calibTimePad) {
384 calibTimePad->push_back(*infotof);
385 }
386 }
387}
388//______________________________________________
389
390void CalibTOF::fillChannelTimeSlewingCalib(float offset, int ipad, TH2F* histo, std::vector<o2::dataformats::CalibInfoTOFshort>* calibTimePad)
391{
392
393 // we will fill the input for the channel-time-slewing calibration
394
395 static double bc = 1.e13 / o2::constants::lhc::LHCRFFreq; // bunch crossing period (ps)
396 static double bc_inv = 1. / bc;
397
398 for (auto infotof = calibTimePad->begin(); infotof != calibTimePad->end(); infotof++) {
399 double dtime = infotof->getDeltaTimePi() - offset; // removing the already calculated offset; this is needed to
400 // fill the time slewing histogram in the correct range
401 dtime -= (int(dtime * bc_inv + 5.5) - 5) * bc; // do truncation far (by 5 units) from zero to avoid truncation of negative numbers
402
403 histo->Fill(TMath::Min(double(infotof->getTot()), 249.9), dtime);
404 mHistoChTimeSlewingAll->Fill(infotof->getTot(), dtime);
405 }
406}
407//______________________________________________
408
409float CalibTOF::doChannelCalibration(int ipad, TH1F* histo, TF1* funcChOffset)
410{
411 // calibrate single channel from histos - offsets
412
413 float integral = histo->Integral();
414 if (!integral) {
415 return -1; // we skip directly the channels that were switched off online, the PHOS holes...
416 }
417
418 int resfit = FitPeak(funcChOffset, histo, 500., 3., 2., "ChannelOffset");
419
420 // return a number greater than zero to distinguish bad fit from empty channels(fraction=0)
421 if (resfit) {
422 return 0.0001; // fit was not good
423 }
424
425 float mean = funcChOffset->GetParameter(1);
426 float sigma = funcChOffset->GetParameter(2);
427 float intmin = mean - 5 * sigma;
428 float intmax = mean + 5 * sigma;
429 float intmin2;
430 float intmax2;
431
432 // if peak is at the border of our bunch-crossing window (-12.5:12.5 ns)
433 // continue to extrapolate gaussian integral from the other border
434 float addduetoperiodicity = 0;
435 if (intmin < -12500) { // at left border
436 intmin2 = intmin + 25000;
437 intmin = -12500;
438 intmax2 = 12500;
439 if (intmin2 > intmax) {
440 int binmin2 = histo->FindBin(intmin2);
441 int binmax2 = histo->FindBin(intmax2);
442 addduetoperiodicity = histo->Integral(binmin2, binmax2);
443 }
444 } else if (intmax > 12500) { // at right border
445 intmax2 = intmax - 25000;
446 intmax = 12500;
447 intmin2 = -12500;
448 if (intmax2 < intmin) {
449 int binmin2 = histo->FindBin(intmin2);
450 int binmax2 = histo->FindBin(intmax2);
451 addduetoperiodicity = histo->Integral(binmin2, binmax2);
452 }
453 }
454
455 int binmin = histo->FindBin(intmin);
456 int binmax = histo->FindBin(intmax);
457
458 if (binmin < 1) {
459 binmin = 1; // avoid to take the underflow bin (can happen in case the sigma is too large)
460 }
461 if (binmax > histo->GetNbinsX()) {
462 binmax = histo->GetNbinsX(); // avoid to take the overflow bin (can happen in case the sigma is too large)
463 }
464
465 return (histo->Integral(binmin, binmax) + addduetoperiodicity) / integral;
466}
467//______________________________________________
468
469void CalibTOF::resetChannelLevelHistos(TH1F* histoOffset[NPADSPERSTEP], TH2F* histoTimeSlewing, std::vector<o2::dataformats::CalibInfoTOFshort>* calibTimePad[NPADSPERSTEP])
470{
471
472 // reset single channel histos
473
474 for (int ipad = 0; ipad < NPADSPERSTEP; ipad++) {
475 histoOffset[ipad]->Reset();
476 if (calibTimePad[ipad]) {
477 calibTimePad[ipad]->clear();
478 }
479 }
480 histoTimeSlewing->Reset();
481}
482
483//______________________________________________
484
485TGraphErrors* CalibTOF::processSlewing(TH2F* histo, Bool_t forceZero, TF1* fitFunc)
486{
487 /* projection-x */
488 TH1D* hpx = histo->ProjectionX("hpx");
489
490 /* define mix and max TOT bin */
491 Int_t minBin = hpx->FindFirstBinAbove(0);
492 Int_t maxBin = hpx->FindLastBinAbove(0);
493 Float_t minTOT = hpx->GetBinLowEdge(minBin);
494 Float_t maxTOT = hpx->GetBinLowEdge(maxBin + 1);
495 // printf("min/max TOT defined: %f < TOT < %f ns [%d, %d]\n", minTOT, maxTOT, minBin, maxBin);
496
497 /* loop over TOT bins */
498 Int_t nPoints = 0;
499 Float_t tot[10000], toterr[10000];
500 Float_t mean[10000], meanerr[10000];
501 Float_t sigma[10000], vertexSigmaerr[10000];
502 for (Int_t ibin = minBin; ibin <= maxBin; ibin++) {
503
504 /* define TOT window */
505 Int_t startBin = ibin;
506 Int_t endBin = ibin;
507 while (hpx->Integral(startBin, endBin) < 300) {
508 if (startBin == 1 && forceZero) {
509 break;
510 }
511 if (endBin < maxBin) {
512 endBin++;
513 } else if (startBin > minBin) {
514 startBin--;
515 } else {
516 break;
517 }
518 }
519 if (hpx->Integral(startBin, endBin) <= 0) {
520 continue;
521 }
522 // printf("TOT window defined: %f < TOT < %f ns [%d, %d], %d tracks\n", hpx->GetBinLowEdge(startBin), hpx->GetBinLowEdge(endBin + 1), startBin, endBin, (Int_t)hpx->Integral(startBin, endBin));
523
524 /* projection-y */
525 TH1D* hpy = histo->ProjectionY("hpy", startBin, endBin);
526
527 /* average TOT */
528 hpx->GetXaxis()->SetRange(startBin, endBin);
529 tot[nPoints] = hpx->GetMean();
530 toterr[nPoints] = hpx->GetMeanError();
531
532 /* fit peak in slices of tot */
533 if (FitPeak(fitFunc, hpy, 500., 3., 2., Form("TotBins%04d_%04d", startBin, endBin), histo) != 0) {
534 // printf("troubles fitting time-zero TRACKS, skip\n");
535 delete hpy;
536 continue;
537 }
538 mean[nPoints] = fitFunc->GetParameter(1);
539 meanerr[nPoints] = fitFunc->GetParError(1);
540
541 /* delete projection-y */
542 delete hpy;
543
544 // printf("meanerr = %f\n",meanerr[nPoints]);
545
546 /* increment n points if good mean error */
547 if (meanerr[nPoints] < 100.) {
548 nPoints++;
549 }
550
551 /* set current bin */
552 ibin = endBin;
553
554 } /* end of loop over time bins */
555
556 /* check points */
557 if (nPoints <= 0) {
558 // printf("no measurement available, quit\n");
559 delete hpx;
560 return nullptr;
561 }
562
563 /* create graph */
564 TGraphErrors* gSlewing = new TGraphErrors(nPoints, tot, mean, toterr, meanerr);
565
566 delete hpx;
567 return gSlewing;
568}
569//______________________________________________
570
571Int_t CalibTOF::FitPeak(TF1* fitFunc, TH1* h, Float_t startSigma, Float_t nSigmaMin, Float_t nSigmaMax, const char* debuginfo, TH2* hdbg)
572{
573 /*
574 * fit peak
575 */
576
577 Double_t fitCent = h->GetBinCenter(h->GetMaximumBin());
578 if (fitCent < -12500) {
579 printf("fitCent = %f (%s). This is wrong, please check!\n", fitCent, h->GetName());
580 fitCent = -12500;
581 }
582 if (fitCent > 12500) {
583 printf("fitCent = %f (%s). This is wrong, please check!\n", fitCent, h->GetName());
584 fitCent = 12500;
585 }
586 Double_t fitMin = fitCent - nSigmaMin * startSigma;
587 Double_t fitMax = fitCent + nSigmaMax * startSigma;
588 if (fitMin < -12500) {
589 fitMin = -12500;
590 }
591 if (fitMax > 12500) {
592 fitMax = 12500;
593 }
594 fitFunc->SetParLimits(1, fitMin, fitMax);
595 fitFunc->SetParameter(0, 100);
596 fitFunc->SetParameter(1, fitCent);
597 fitFunc->SetParameter(2, startSigma);
598 Int_t fitres = h->Fit(fitFunc, "WWq0", "", fitMin, fitMax);
599 //printf("%s) init: %f %f\n ",h->GetName(),fitMin,fitMax);
600 if (fitres != 0) {
601 return fitres;
602 }
603 /* refit with better range */
604 for (Int_t i = 0; i < 3; i++) {
605 fitCent = fitFunc->GetParameter(1);
606 fitMin = fitCent - nSigmaMin * std::abs(fitFunc->GetParameter(2));
607 fitMax = fitCent + nSigmaMax * std::abs(fitFunc->GetParameter(2));
608 if (fitMin < -12500) {
609 fitMin = -12500;
610 }
611 if (fitMax > 12500) {
612 fitMax = 12500;
613 }
614 if (fitMin >= fitMax) {
615 printf("%s) step%i: %f %f\n ", h->GetName(), i, fitMin, fitMax);
616 }
617 fitFunc->SetParLimits(1, fitMin, fitMax);
618 fitres = h->Fit(fitFunc, "q0", "", fitMin, fitMax);
619 if (fitres != 0) {
620 printf("%s) step%i: %f in %f - %f\n ", h->GetName(), i, fitCent, fitMin, fitMax);
621
622 if (mDebugMode > 1) {
623 char* filename = Form("TOFDBG_%s.root", h->GetName());
624 if (hdbg) {
625 filename = Form("TOFDBG_%s_%s.root", hdbg->GetName(), debuginfo);
626 }
627 // printf("write %s\n", filename);
628 TFile ff(filename, "RECREATE");
629 h->Write();
630 if (hdbg) {
631 hdbg->Write();
632 }
633 ff.Close();
634 }
635
636 return fitres;
637 }
638 }
639
640 if (mDebugMode > 1 && fitFunc->GetParError(1) > 100) {
641 char* filename = Form("TOFDBG_%s.root", h->GetName());
642 if (hdbg) {
643 filename = Form("TOFDBG_%s_%s.root", hdbg->GetName(), debuginfo);
644 }
645 // printf("write %s\n", filename);
646 TFile ff(filename, "RECREATE");
647 h->Write();
648 if (hdbg) {
649 hdbg->Write();
650 }
651 ff.Close();
652 }
653
654 return fitres;
655}
656//______________________________________________
657
658void CalibTOF::merge(const char* name)
659{
660 TFile* f = TFile::Open(name);
661 if (!f) {
662 LOG(error) << "File " << name << "not found (merging skept)";
663 return;
664 }
665 TTree* t = (TTree*)f->Get(mOutputTree->GetName());
666 if (!t) {
667 LOG(error) << "Tree " << mOutputTree->GetName() << "not found in " << name << " (merging skept)";
668 return;
669 }
670 t->ls();
671 mOutputTree->ls();
672
673 o2::dataformats::CalibLHCphaseTOF* LHCphaseObj = nullptr;
674
675 o2::dataformats::CalibTimeSlewingParamTOF* timeSlewingObj = nullptr;
676
677 t->SetBranchAddress("mLHCphaseObj", &LHCphaseObj);
678 t->SetBranchAddress("mTimeSlewingObj", &timeSlewingObj);
679
680 t->GetEvent(0);
681
682 *mTimeSlewingObj += *timeSlewingObj;
683 *mLHCphaseObj += *LHCphaseObj;
684 f->Close();
685}
686//______________________________________________
687
689{
690
691 // method to flag problematic channels: Fraction, Sigma -> all negative if channel is bad (otherwise all positive)
692
693 TH1F* hsigmapeak = new TH1F("hsigmapeak", ";#sigma_{peak} (ps)", 1000, 0, 1000);
694 TH1F* hfractionpeak = new TH1F("hfractionpeak", ";fraction under peak", 1001, 0, 1.01);
695
696 int ipad;
697 float sigmaMin, sigmaMax, fractionMin;
698
699 int nActiveChannels = 0;
700 int nGoodChannels = 0;
701
702 TF1* fFuncSigma = new TF1("fFuncSigma", "TMath::Gaus(x,[1],[2])*[0]*(x<[1]) + TMath::Gaus(x,[1],[3])*[0]*(x>[1])");
703 fFuncSigma->SetParameter(0, 1000);
704 fFuncSigma->SetParameter(1, 200);
705 fFuncSigma->SetParameter(2, 200);
706 fFuncSigma->SetParameter(3, 200);
707
708 TF1* fFuncFraction = new TF1("fFuncFraction", "TMath::Gaus(x,[1],[2])*[0]*(x<[1]) + TMath::Gaus(x,[1],[3])*[0]*(x>[1])");
709 fFuncFraction->SetParameter(0, 1000);
710 fFuncFraction->SetParameter(1, 0.8);
711 fFuncFraction->SetParameter(2, 0.1);
712 fFuncFraction->SetParameter(3, 0.1);
713
714 // we group pads according to the z-coordinate since we noted a z-dependence in sigmas and fraction-under-peak
715 for (int iz = 0; iz < o2::tof::Geo::NSTRIPXSECTOR * 2; iz++) {
716 hsigmapeak->Reset();
717 hfractionpeak->Reset();
718
719 for (int k = 0; k < o2::tof::Geo::NPADX; k++) {
720 ipad = 48 * iz + k;
721
722 for (int i = 0; i < 18; i++) {
723 // exclude channel without entries
724 if (mTimeSlewingObj->getFractionUnderPeak(i, ipad) < 0) {
725 continue;
726 }
727
728 nActiveChannels++;
729
730 hsigmapeak->Fill(mTimeSlewingObj->getSigmaPeak(i, ipad));
731 hfractionpeak->Fill(mTimeSlewingObj->getFractionUnderPeak(i, ipad));
732 }
733 }
734
735 hsigmapeak->Fit(fFuncSigma, "WWq0");
736 hfractionpeak->Fit(fFuncFraction, "WWq0");
737
738 sigmaMin = fFuncSigma->GetParameter(1) - mNsigmaSigmaProblematicCut * std::abs(fFuncSigma->GetParameter(2));
739 sigmaMax = fFuncSigma->GetParameter(1) + mNsigmaSigmaProblematicCut * std::abs(fFuncSigma->GetParameter(3));
740 fractionMin = fFuncFraction->GetParameter(1) - mNsigmaFractionProblematicCut * std::abs(fFuncFraction->GetParameter(2));
741
742 for (int k = 0; k < o2::tof::Geo::NPADX; k++) {
743 ipad = 48 * iz + k;
744
745 for (int i = 0; i < 18; i++) {
746 // exclude channel without entries
747 if (mTimeSlewingObj->getFractionUnderPeak(i, ipad) < 0) {
748 continue;
749 }
750
751 if (mTimeSlewingObj->getSigmaPeak(i, ipad) < sigmaMin ||
752 mTimeSlewingObj->getSigmaPeak(i, ipad) > sigmaMax ||
753 mTimeSlewingObj->getFractionUnderPeak(i, ipad) < fractionMin) {
754 mTimeSlewingObj->setFractionUnderPeak(i, ipad, -mTimeSlewingObj->getFractionUnderPeak(i, ipad));
755 mTimeSlewingObj->setSigmaPeak(i, ipad, -mTimeSlewingObj->getSigmaPeak(i, ipad));
756 } else {
757 nGoodChannels++;
758 }
759 }
760 }
761 }
762
763 Printf("Check for TOF problematics: nActiveChannels=%d - nGoodChannels=%d - fractionGood = %f", int(nActiveChannels), int(nGoodChannels), nGoodChannels * 1. / nActiveChannels);
764}
ClassImp(CalibTOF)
particle ids, masses, names class definition
uint64_t bc
Definition RawEventData.h:5
int32_t i
Header of the General Run Parameters object.
Header to collect LHC related constants.
uint32_t res
Definition RawData.h:0
Class for time synchronization of RawReader instances.
void addLHCphase(int timestamp, float phaseLHC)
float getFractionUnderPeak(int sector, int channel) const
void addTimeSlewingInfo(int channel, float tot, float time)
void setSigmaPeak(int sector, int channel, float value)
float getSigmaPeak(int sector, int channel) const
void setFractionUnderPeak(int sector, int channel, float value)
static constexpr int NPADSPERSTEP
Definition CalibTOF.h:51
Int_t FitPeak(TF1 *fitFunc, TH1 *h, Float_t startSigma, Float_t nSigmaMin, Float_t nSigmaMax, const char *debuginfo="", TH2 *hdbg=nullptr)
Definition CalibTOF.cxx:571
void merge(const char *name)
Definition CalibTOF.cxx:658
TGraphErrors * processSlewing(TH2F *histo, Bool_t forceZero, TF1 *fitFunc)
Definition CalibTOF.cxx:485
void run(int flag, int sector=-1)
Definition CalibTOF.cxx:126
void init()
set tree/chain containing TOF calib info
Definition CalibTOF.cxx:72
~CalibTOF()
calibrate using the provided input
Definition CalibTOF.cxx:43
void fillOutput(int flag=kLHCphase|kChannelOffset|kChannelTimeSlewing)
perform all initializations
Definition CalibTOF.cxx:272
void flagProblematics()
problematics are flagged with negative values for frationUnderPeak: -100 empty channels,...
Definition CalibTOF.cxx:688
void writeLHCphase(LhcPhase *phase, std::map< std::string, std::string > metadataLHCphase, uint64_t minTimeSTamp, uint64_t maxTimeStamp)
void writeTimeSlewingParam(SlewParam *param, std::map< std::string, std::string > metadataChannelCalib, uint64_t minTimeSTamp, uint64_t maxTimeStamp=0)
void setURL(const std::string url)
Definition CalibTOFapi.h:62
static constexpr Int_t NSTRIPXSECTOR
Definition Geo.h:116
static constexpr Int_t NPADS
Definition Geo.h:110
static constexpr Int_t NPADSXSECTOR
Definition Geo.h:118
static constexpr int NCHANNELS
Definition Geo.h:124
static constexpr Int_t NPADX
Definition Geo.h:107
GLuint const GLchar * name
Definition glcorearb.h:781
GLdouble f
Definition glcorearb.h:310
GLintptr offset
Definition glcorearb.h:660
double mean(std::vector< double >::const_iterator first, std::vector< double >::const_iterator last)
constexpr double LHCRFFreq
std::string filename()
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"