Project
Loading...
Searching...
No Matches
TOFChannelCalibrator.h
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
12#ifndef TOF_CHANNEL_CALIBRATOR_H_
13#define TOF_CHANNEL_CALIBRATOR_H_
14
20#include "TOFBase/Geo.h"
21#include "CCDB/CcdbObjectInfo.h"
22#include "TOFBase/CalibTOFapi.h"
23
24#include <array>
25#include <boost/histogram.hpp>
26
27#include "TGraphErrors.h"
28#include "TF1.h"
29#include "MathUtils/fit.h"
30#include "TLinearFitter.h"
31#include "Fit/Fitter.h"
32
34#include <boost/histogram.hpp>
35#include <boost/histogram/ostream.hpp>
37#include "CCDB/CcdbApi.h"
38#include <boost/format.hpp>
39#include "TOFBase/Utils.h"
40
41//#define DEBUGGING
42
43#ifdef DEBUGGING
44#include "TProfile.h"
45#include "TH2F.h"
46#endif
47
49
50namespace o2
51{
52namespace tof
53{
54
56{
57
60 using boostHisto = boost::histogram::histogram<std::tuple<boost::histogram::axis::regular<double, boost::use_default, boost::use_default, boost::use_default>, boost::histogram::axis::integer<>>, boost::histogram::unlimited_storage<std::allocator<char>>>;
61
62 public:
64
66 {
67 LOG(info) << "Default c-tor, not to be used";
68 }
69
70#ifndef DEBUGGING
71 TOFChannelData(int nb, float r, CalibTOFapi* cta, int nElsPerSector = o2::tof::Geo::NPADSXSECTOR, bool perstrip = false, bool safe = false) : mNBins(nb), mRange(r), mCalibTOFapi(cta), mNElsPerSector(nElsPerSector), mPerStrip(perstrip), mSafeMode(safe)
72#else
73 TOFChannelData(int nb, float r, CalibTOFapi* cta, int nElsPerSector = o2::tof::Geo::NPADSXSECTOR, bool perstrip = false, bool safe = false, TH2F* h = nullptr) : mNBins(nb), mRange(r), mCalibTOFapi(cta), mNElsPerSector(nElsPerSector), mPerStrip(perstrip), mSafeMode(safe), mChannelDist(h)
74#endif
75 {
76 if (r <= 0. || nb < 1) {
77 throw std::runtime_error("Wrong initialization of the histogram");
78 }
79 mV2Bin = mNBins / (2 * mRange);
80 for (int isect = 0; isect < 18; isect++) {
81 mHisto[isect] = boost::histogram::make_histogram(boost::histogram::axis::regular<>(mNBins, -mRange, mRange, "t-texp"),
82 boost::histogram::axis::integer<>(0, mNElsPerSector, "channel index in sector" + std::to_string(isect))); // bin is defined as [low, high[
83 }
84 mEntries.resize(mNElsPerSector * 18, 0);
85 }
86
87 ~TOFChannelData() = default;
88
89 void print() const;
90 void print(int isect) const;
91 void printEntries() const;
92 void fill(const gsl::span<const o2::dataformats::CalibInfoTOF> data);
93 void fill(const gsl::span<const o2::tof::CalibInfoCluster> data);
94 void merge(const TOFChannelData* prev);
95 int findBin(float v) const;
96 float integral(int chmin, int chmax, float binmin, float binmax) const;
97 float integral(int chmin, int chmax, int binxmin, int binxmax) const;
98 float integral(int ch, float binmin, float binmax) const;
99 float integral(int ch, int binxmin, int binxmax) const;
100 float integral(int ch) const;
101 bool hasEnoughData(int minEntries) const;
102
103 float getRange() const { return mRange; }
104 void setRange(float r) { mRange = r; }
105
106 int getNbins() const { return mNBins; }
107 void setNbins(int nb) { mNBins = nb; }
108
109 boostHisto& getHisto(int isect) { return mHisto[isect]; }
110 const boostHisto& getHisto(int isect) const { return mHisto[isect]; }
111 //const boostHisto getHisto() const { return &mHisto[0]; }
112 // boostHisto* getHisto(int isect) const { return &mHisto[isect]; }
113
114 std::vector<int> getEntriesPerChannel() const { return mEntries; }
115
116 void doPerStrip(bool val = true) { mPerStrip = val; }
117 void doSafeMode(bool val = true) { mSafeMode = val; }
118
119 void resetAndReRange(float range);
120
121 private:
122 float mRange = o2::tof::Geo::BC_TIME_INPS * 0.5;
123 int mNBins = 2000;
124 float mV2Bin;
125 std::array<boostHisto, 18> mHisto;
126 std::vector<int> mEntries; // vector containing number of entries per channel
127
128#ifdef DEBUGGING
129 TH2F* mChannelDist;
130#endif
131
132 CalibTOFapi* mCalibTOFapi = nullptr; // calibTOFapi to correct the t-text
133 int mNElsPerSector = o2::tof::Geo::NPADSXSECTOR;
134
135 bool mPerStrip = false;
136 bool mSafeMode = false;
137
138 ClassDefNV(TOFChannelData, 1);
139};
140
141template <class T>
142class TOFChannelCalibrator final : public o2::calibration::TimeSlotCalibration<o2::tof::TOFChannelData>
143{
144 using TFType = o2::calibration::TFType;
149 using CcdbObjectInfoVector = std::vector<CcdbObjectInfo>;
150 using TimeSlewingVector = std::vector<TimeSlewing>;
151
152#ifdef DEBUGGING
153 TProfile* mFitCal; //("fitCal",";channel;offset (ps)",13104,0,157248);
154 TH2F* mChannelDist; //("channelDist",";channel; t - t_{exp}^{#pi} (ps)",13104,0,157248,1000,-100000,100000);
155#endif
156
157 protected:
158 std::deque<o2::calibration::TimeSlot<o2::tof::TOFChannelData>>& getSlots() { return o2::calibration::TimeSlotCalibration<o2::tof::TOFChannelData>::getSlots(); }
159
160 public:
161 void doPerStrip(bool val = true) { mPerStrip = val; }
162 void doSafeMode(bool val = true) { mSafeMode = val; }
163
164 static double FuncDeltaOffset(double* x, double* params)
165 {
166 int i1 = int(x[0]) % 96;
167 int i2 = int(x[0]) / 96 ? (i1 + 48) : (i1 + 1);
168
169 if (i1 < 0) {
170 return 0;
171 }
172 if (i2 >= Geo::NPADS) {
173 return 0;
174 }
175
176 return (params[i1] - params[i2]);
177 }
178
180 static constexpr int NMAXTHREADS = o2::tof::Geo::NSECTORS; // number of max threads that we allow OpenMP to use;
181 // since at max we parallelize the processing of the sectors,
182 // the number if sectors is what we use
183
184 TOFChannelCalibrator(int minEnt = 500, int nb = 1000, float r = 24400, bool perstrip = false, bool safe = false) : mMinEntries(minEnt), mNBins(nb), mRange(r), mPerStrip(perstrip), mSafeMode(safe)
185 {
187 for (int i = 0; i < NMAXTHREADS; ++i) {
188 //mLinFitters[i] = new TLinearFitter(3, "pol2");
189 mLinFitters[i].SetDim(3);
190 mLinFitters[i].SetFormula("pol2");
191 }
192#ifdef DEBUGGING
193 mFitCal = new TProfile("fitCal", ";channel;offset (ps)", 157248, 0, 157248);
194 int nbins = mNBins;
195 if (nbins > 2000) { // not more than 2000 otherwise it will cause overflow in the bin indexing
196 nbins = 2000;
197 }
198 mChannelDist = new TH2F("channelDist", ";channel; t - t_{exp}^{#pi} (ps)", 157248, 0, 157248, nbins, -mRange, mRange);
199#endif
200 }
201
202 ~TOFChannelCalibrator() final = default;
203
204 bool hasEnoughData(const Slot& slot) const final
205 {
206 // Checking if all channels have enough data to do calibration.
207 // Delegating this to TOFChannelData
208 const o2::tof::TOFChannelData* c = slot.getContainer();
209 LOG(debug) << "Checking statistics";
210 return (mTest ? true : c->hasEnoughData(mMinEntries));
211 }
212
213 void initOutput() final
214 {
215 // Here we initialize the vector of our output objects
216 mInfoVector.clear();
217 mTimeSlewingVector.clear();
218 return;
219 }
220
221 void finalizeSlot(Slot& slot) final
222 {
223 // here we simply decide which finalize to call: for the use case with Tracks or cosmics
224 mCalibWithCosmics ? finalizeSlotWithCosmics(slot) : finalizeSlotWithTracks(slot);
225 return;
226 }
227
228 void finalizeSlotWithCosmics(Slot& slot);
229 void finalizeSlotWithTracks(Slot& slot);
230
231 Slot& emplaceNewSlot(bool front, TFType tstart, TFType tend) final
232 {
233 auto& cont = getSlots();
234 auto& slot = front ? cont.emplace_front(tstart, tend) : cont.emplace_back(tstart, tend);
235 int nElements = mCalibWithCosmics ? NCOMBINSTRIP * Geo::NSTRIPXSECTOR : Geo::NPADSXSECTOR; // if we calibrate with cosmics, we pass the number of possible combinations per sector; otherwise, the number of pads per sector
236#ifndef DEBUGGING
237 slot.setContainer(std::make_unique<TOFChannelData>(mNBins, mRange, mCalibTOFapi, nElements, mPerStrip, mSafeMode));
238#else
239 slot.setContainer(std::make_unique<TOFChannelData>(mNBins, mRange, mCalibTOFapi, nElements, mPerStrip, mSafeMode, mChannelDist));
240#endif
241
242 return slot;
243 }
244
245 const TimeSlewingVector& getTimeSlewingVector() const { return mTimeSlewingVector; }
246 const CcdbObjectInfoVector& getTimeSlewingInfoVector() const { return mInfoVector; }
247 CcdbObjectInfoVector& getTimeSlewingInfoVector() { return mInfoVector; }
248
249 void setIsTest(bool isTest) { mTest = isTest; }
250 bool isTest() const { return mTest; }
251
252 void setCalibTOFapi(CalibTOFapi* api) { mCalibTOFapi = api; }
253 CalibTOFapi* getCalibTOFapi() const { return mCalibTOFapi; }
254
255 void setRange(float r) { mRange = r; }
256 float getRange() const { return mRange; }
257
258 void setDoCalibWithCosmics(bool doCalibWithCosmics = true) { mCalibWithCosmics = doCalibWithCosmics; }
259 bool doCalibWithCosmics() const { return mCalibWithCosmics; }
260
261 void setNThreads(int n) { mNThreads = std::min(n, NMAXTHREADS); }
262 int getNThreads() const { return mNThreads; }
263
265 {
266 mStripOffsetFunction.clear();
267 for (int i = 0; i < 96; i++) {
268 int irow = i % 48;
269 int icolumn = i / 48;
270 if (i > 0) {
271 mStripOffsetFunction.append(Form("++ ("));
272 } else {
273 mStripOffsetFunction.append(Form("("));
274 }
275 bool kadd = false;
276 if (irow < 47) {
277 mStripOffsetFunction.append(Form("(x > %d && x < %d)", irow + icolumn * 48, irow + icolumn * 48 + 1));
278 kadd = true;
279 }
280 if (irow > 0) {
281 mStripOffsetFunction.append("-");
282 mStripOffsetFunction.append(Form("(x > %d && x < %d)", irow + icolumn * 48 - 1, irow + icolumn * 48));
283 kadd = true;
284 }
285 if (icolumn < 1) {
286 if (kadd) {
287 mStripOffsetFunction.append("+");
288 }
289 mStripOffsetFunction.append(Form("(x > %d && x < %d)", irow + 96, irow + 96 + 1));
290 } else {
291 mStripOffsetFunction.append("-");
292 mStripOffsetFunction.append(Form("(x > %d && x < %d)", irow + 96, irow + 96 + 1));
293 }
294 mStripOffsetFunction.append(Form(") "));
295 }
296 TLinearFitter localFitter2(1, mStripOffsetFunction.c_str()); // this is a workaround: when we define the TLinearFitter,
297 // the function is sort of added in some global namespace
298 // or somthing analogous; when then we use more than 1 thread,
299 // the threads conflict with each other in this operation, and
300 // it does not work. So we do the operation of adding the
301 // function to this global namespece in advance.
302 }
303
304 private:
305 int mMinEntries = 0; // min number of entries to calibrate the TimeSlot
306 int mNBins = 0; // bins of the histogram with the t-text per channel
307 float mRange = 0.; // range of the histogram with the t-text per channel
308 bool mTest = false; // flag to be used when running in test mode: it simplify the processing (e.g. does not go through all channels)
309 bool mPerStrip = false;
310 bool mSafeMode = false;
311
312 CalibTOFapi* mCalibTOFapi = nullptr; // CalibTOFapi needed to get the previous calibrations read from CCDB (do we need that it is a pointer?)
313
314 // output
315 CcdbObjectInfoVector mInfoVector; // vector of CCDB Infos , each element is filled with the CCDB description of the accompanying TimeSlewing object
316 TimeSlewingVector mTimeSlewingVector; // vector of TimeSlewing, each element is filled in "process"
317 // when we finalize one slot (multiple can be finalized
318 // during the same "process", which is why we have a vector).
319 // Each element is to be considered the output of the device,
320 // and will go to the CCDB. Note that for the channel offset
321 // we still fill the TimeSlewing object
322
323 bool mCalibWithCosmics = false; // flag to indicate whether we are calibrating with cosmics
324
325 int mNThreads = 1; // number of threads from OpenMP
326
327 std::string mStripOffsetFunction; // TLinear functon for fitting channel offset within the strip in cosmic data
328
329 TLinearFitter mLinFitters[NMAXTHREADS]; // fitters for OpenMP for fitGaus
330
331 ClassDefOverride(TOFChannelCalibrator, 1);
332};
333
334} // end namespace tof
335} // end namespace o2
336
337#endif /* TOF_CHANNEL_CALIBRATOR_H_ */
Class to store the output of the matching to TOF for calibration.
Class to store the output of the matching to TOF for calibration.
Class to use TOF calibration (decalibration, calibration)
Utils and constants for calibration and related workflows.
int32_t i
uint32_t c
Definition RawData.h:2
std::ostringstream debug
Class for time synchronization of RawReader instances.
TOF geo parameters (only statics)
Definition Geo.h:28
static constexpr Int_t NSECTORS
Definition Geo.h:120
static constexpr Double_t BC_TIME_INPS
Definition Geo.h:103
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_t NPADX
Definition Geo.h:107
CcdbObjectInfoVector & getTimeSlewingInfoVector()
~TOFChannelCalibrator() final=default
void setDoCalibWithCosmics(bool doCalibWithCosmics=true)
static double FuncDeltaOffset(double *x, double *params)
Slot & emplaceNewSlot(bool front, TFType tstart, TFType tend) final
std::deque< o2::calibration::TimeSlot< o2::tof::TOFChannelData > > & getSlots()
const CcdbObjectInfoVector & getTimeSlewingInfoVector() const
void finalizeSlot(Slot &slot) final
void setCalibTOFapi(CalibTOFapi *api)
TOFChannelCalibrator(int minEnt=500, int nb=1000, float r=24400, bool perstrip=false, bool safe=false)
const TimeSlewingVector & getTimeSlewingVector() const
bool hasEnoughData(const Slot &slot) const final
void fill(const gsl::span< const o2::dataformats::CalibInfoTOF > data)
static constexpr int NCOMBINSTRIP
std::vector< int > getEntriesPerChannel() const
TOFChannelData(int nb, float r, CalibTOFapi *cta, int nElsPerSector=o2::tof::Geo::NPADSXSECTOR, bool perstrip=false, bool safe=false)
boostHisto & getHisto(int isect)
float integral(int chmin, int chmax, float binmin, float binmax) const
void doSafeMode(bool val=true)
void doPerStrip(bool val=true)
const boostHisto & getHisto(int isect) const
void merge(const TOFChannelData *prev)
bool hasEnoughData(int minEntries) const
GLdouble n
Definition glcorearb.h:1982
GLint GLenum GLint x
Definition glcorearb.h:403
const GLdouble * v
Definition glcorearb.h:832
GLenum GLint * range
Definition glcorearb.h:1899
GLenum const GLfloat * params
Definition glcorearb.h:272
GLboolean * data
Definition glcorearb.h:298
GLuint GLfloat * val
Definition glcorearb.h:1582
GLboolean r
Definition glcorearb.h:1233
uint32_t TFType
Definition TimeSlot.h:29
Double_t fitGaus(const size_t nBins, const T *arr, const T xMin, const T xMax, std::vector< T > &param)
Definition fit.h:231
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"