Project
Loading...
Searching...
No Matches
T0Fit.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
15
22#include "TStopwatch.h"
23#include "CCDB/CcdbApi.h"
27#include <TFile.h>
28#include <TTree.h>
29
30#include "TMath.h"
31
32#include <string>
33#include <map>
34#include <memory>
35#include <ctime>
36
37using namespace o2::trd::constants;
38
39namespace o2::trd
40{
41//______________________________________________________________________________________________
42double ErfLandauChi2Functor::operator()(const double* par) const
43{
44 // provides chi2 estimate of PH profile comparing the y-value of profiles to
45 // par[0]*ROOT::Math::erf(x) + par[1]*TMath::Landau(x,par[2],par[3])
46 //
47 // par[0] : offset
48 // par[1] : amplitude
49 // par[2] : mean
50 // par[3] : sigma
51
52 double sum2 = 0;
53
54 for (int i = lowerBoundFit; i <= upperBoundFit; ++i) {
55
56 if (TMath::Abs(y[i]) < 1e-7) {
57 continue;
58 }
59
60 double funcVal = par[0] * TMath::Erf(x[i]) + par[1] * TMath::Landau(x[i], par[2], par[3]);
61
62 sum2 += TMath::Power(y[i] - funcVal, 2) / y[i];
63 }
64
65 return sum2;
66}
67
68//______________________________________________________________________________________________
70
72{
73 // reset the CCDB output vectors
74 mInfoVector.clear();
75 mObjectVector.clear();
76}
77
79{
80 if (mInitDone) {
81 return;
82 }
83
84 adcProfIncl = std::make_unique<TProfile>("adcProfIncl", "adcProfIncl", 30, -0.5, 29.5);
85 for (int iDet = 0; iDet < constants::MAXCHAMBER; ++iDet) {
86 adcProfDet[iDet] = std::make_unique<TProfile>(Form("adcProfDet_%i", iDet), Form("adcProfDet_%i", iDet), 30, -0.5, 29.5);
87 }
88
89 mFitFunctor.lowerBoundFit = 0;
90 mFitFunctor.upperBoundFit = 5;
91
92 double mParamsStart[4];
93 mParamsStart[0] = 100;
94 mParamsStart[1] = 500;
95 mParamsStart[2] = 0.5;
96 mParamsStart[3] = 0.5;
97
98 mFitter.SetFCN<ErfLandauChi2Functor>(4, mFitFunctor, mParamsStart);
99
100 ROOT::Math::MinimizerOptions opt;
101 opt.SetMinimizerType("Minuit2");
102 opt.SetMinimizerAlgorithm("Migrad");
103 opt.SetPrintLevel(0);
104 opt.SetMaxFunctionCalls(1000);
105 opt.SetTolerance(.001);
106 mFitter.Config().SetMinimizerOptions(opt);
107
108 mFuncErfLandau = std::make_unique<TF1>(
109 "fErfLandau", [&](double* x, double* par) { return par[0] * TMath::Erf(x[0]) + par[1] * TMath::Landau(x[0], par[2], par[3]); }, mFitFunctor.lowerBoundFit, mFitFunctor.upperBoundFit, 4);
110
111 // set tree addresses
112 if (mEnableOutput) {
113 mOutTree->Branch("t0_chambers", &t0_chambers);
114 mOutTree->Branch("t0_average", &t0_average);
115 }
116
117 mInitDone = true;
118}
119
121{
122 // do actual fits for the data provided in the given slot
123
124 TStopwatch timer;
125 timer.Start();
127
128 // get data and fill profiles
129 auto dataPH = slot.getContainer();
130
131 for (int iEntry = 0; iEntry < dataPH->getNEntries(); ++iEntry) {
132 int iDet = dataPH->getDetector(iEntry);
133 adcProfIncl->Fill(dataPH->getTimeBin(iEntry), dataPH->getADC(iEntry));
134 adcProfDet[iDet]->Fill(dataPH->getTimeBin(iEntry), dataPH->getADC(iEntry));
135 }
136
137 // do fits
138 // inclusive distribution
139 mFitFunctor.x.clear();
140 mFitFunctor.y.clear();
141 for (int i = 1; i <= 30; ++i) {
142 mFitFunctor.x.push_back(i - 1);
143 mFitFunctor.y.push_back(adcProfIncl->GetBinContent(i));
144 }
145
146 mFitter.FitFCN();
147 auto fitResult = mFitter.Result();
148
149 if (fitResult.IsValid()) {
150 mFuncErfLandau->SetParameters(fitResult.GetParams()[0], fitResult.GetParams()[1], fitResult.GetParams()[2], fitResult.GetParams()[3]);
151 t0_average = mFuncErfLandau->GetMaximumX();
152 } else {
153 LOG(warn) << "t0 fit for inclusive distribtion is not valid, set to " << mDummyT0;
154 t0_average = mDummyT0;
155 }
156
157 // single chambers
158 for (int iDet = 0; iDet < constants::MAXCHAMBER; ++iDet) {
159 if (adcProfDet[iDet]->GetEntries() < mParams.minEntriesChamberT0Fit) {
160 LOG(info) << "not enough entries in chamber " << iDet << " for t0 fit, set to " << mDummyT0;
161 t0_chambers[iDet] = mDummyT0;
162 continue;
163 }
164
165 mFitFunctor.x.clear();
166 mFitFunctor.y.clear();
167 for (int i = 1; i <= 30; ++i) {
168 mFitFunctor.x.push_back(i - 1);
169 mFitFunctor.y.push_back(adcProfDet[iDet]->GetBinContent(i));
170 }
171
172 mFitter.FitFCN();
173 fitResult = mFitter.Result();
174
175 if (fitResult.IsValid()) {
176 mFuncErfLandau->SetParameters(fitResult.GetParams()[0], fitResult.GetParams()[1], fitResult.GetParams()[2], fitResult.GetParams()[3]);
177 t0_chambers[iDet] = mFuncErfLandau->GetMaximumX();
178 } else {
179 LOG(info) << "t0 fit for chamber " << iDet << " is not valid, set to " << mDummyT0;
180 t0_chambers[iDet] = mDummyT0;
181 }
182 }
183
184 // fill tree
185 if (mEnableOutput) {
186 mOutTree->Fill();
187
188 LOGF(debug, "Fit result for inclusive distribution: t0 = ", t0_average);
189 for (int iDet = 0; iDet < MAXCHAMBER; ++iDet) {
190 LOGF(debug, "Fit result for chamber %i: t0 = ", iDet, t0_chambers[iDet]);
191 }
192 }
193
194 // assemble CCDB object
195 CalT0 t0Object;
196 t0Object.setT0av(t0_average);
197 for (int iDet = 0; iDet < constants::MAXCHAMBER; ++iDet) {
198 t0Object.setT0(iDet, t0_chambers[iDet]);
199 }
200 auto clName = o2::utils::MemFileHelper::getClassName(t0Object);
201 auto flName = o2::ccdb::CcdbApi::generateFileName(clName);
202 std::map<std::string, std::string> metadata; // TODO: do we want to store any meta data?
203 long startValidity = slot.getStartTimeMS();
204 mInfoVector.emplace_back("TRD/Calib/CalT0", clName, flName, metadata, startValidity, startValidity + o2::ccdb::CcdbObjectInfo::HOUR);
205 mObjectVector.push_back(t0Object);
206}
207
208Slot& T0Fit::emplaceNewSlot(bool front, TFType tStart, TFType tEnd)
209{
210 auto& container = getSlots();
211 auto& slot = front ? container.emplace_front(tStart, tEnd) : container.emplace_back(tStart, tEnd);
212 slot.setContainer(std::make_unique<T0FitHistos>());
213 return slot;
214}
215
217{
218 mEnableOutput = true;
219 mOutFile = std::make_unique<TFile>("trd_calt0.root", "RECREATE");
220 if (mOutFile->IsZombie()) {
221 LOG(error) << "Failed to create output file!";
222 mEnableOutput = false;
223 return;
224 }
225 mOutTree = std::make_unique<TTree>("calib", "t0 values");
226 LOG(info) << "Created output file trd_calt0.root";
227}
228
230{
231 if (!mEnableOutput) {
232 return;
233 }
234
235 try {
236 mOutFile->cd();
237 mOutTree->Write();
238 mOutTree.reset();
239 mOutFile->Close();
240 mOutFile.reset();
241 } catch (std::exception const& e) {
242 LOG(error) << "Failed to write t0-value data file, reason: " << e.what();
243 }
244 mEnableOutput = false;
245}
246} // namespace o2::trd
Global TRD definitions and constants.
int32_t i
Definition of the Names Generator class.
Fits the TRD PH distributions to extract the t0 value.
std::ostringstream debug
long getStartTimeMS() const
Definition TimeSlot.h:50
const Container * getContainer() const
Definition TimeSlot.h:53
static std::string generateFileName(const std::string &inp)
Definition CcdbApi.cxx:798
static constexpr long HOUR
void setT0av(float t0)
Definition CalT0.h:35
void setT0(int iDet, float t0)
Definition CalT0.h:34
void initProcessing()
Definition T0Fit.cxx:78
void finalizeSlot(Slot &slot) final
Definition T0Fit.cxx:120
void initOutput() final
Definition T0Fit.cxx:71
Slot & emplaceNewSlot(bool front, TFType tStart, TFType tEnd) final
Definition T0Fit.cxx:208
void createOutputFile()
Definition T0Fit.cxx:216
void closeOutputFile()
Definition T0Fit.cxx:229
GLint GLenum GLint x
Definition glcorearb.h:403
constexpr int MAXCHAMBER
the maximum number of installed chambers
Definition Constants.h:30
std::vector< float > y
y-value (av. adc) for corresp. time-bin
Definition T0Fit.h:46
float lowerBoundFit
lower bound for fit
Definition T0Fit.h:47
double operator()(const double *par) const
Definition T0Fit.cxx:42
float upperBoundFit
upper bound for fit
Definition T0Fit.h:48
std::vector< float > x
x-value (time-bin) of adc profile
Definition T0Fit.h:45
size_t minEntriesChamberT0Fit
minimum number of entries in one chamber for (meaningful) t0 fit
static std::string getClassName(const T &obj)
get the class name of the object
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"