Project
Loading...
Searching...
No Matches
CalibPulser.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
14
15#include <string>
16#include <vector>
17#include <algorithm>
18
19#include "TObjArray.h"
20#include "TFile.h"
21
22#include "TPCBase/ROC.h"
23#include "MathUtils/fit.h"
26
27using namespace o2::tpc;
30
32 : mNbinsT0{200},
33 mXminT0{-2},
34 mXmaxT0{2},
35 mNbinsQtot{200},
36 mXminQtot{50},
37 mXmaxQtot{700},
38 mNbinsWidth{100},
39 mXminWidth{0.1},
40 mXmaxWidth{5.1},
41 mFirstTimeBin{10},
42 mLastTimeBin{490},
43 mADCMin{5},
44 mADCMax{1023},
45 mNumberOfADCs{mADCMax - mADCMin + 1},
46 mPeakIntMinus{2},
47 mPeakIntPlus{2},
48 mMinimumQtot{20},
49 mMinimumQmax{10},
50 mMaxTimeBinRange{5},
51 mPedestal{nullptr},
52 mNoise{nullptr},
53 mPulserData{},
54 mT0Histograms{},
55 mWidthHistograms{},
56 mQtotHistograms{}
57{
58 mT0Histograms.resize(ROC::MaxROC);
59 mWidthHistograms.resize(ROC::MaxROC);
60 mQtotHistograms.resize(ROC::MaxROC);
61
62 // TODO: until automatic T0 calibration is done we use the same time range
63 // as for the time bin selection
64 mXminT0 = mFirstTimeBin;
65 mXmaxT0 = mLastTimeBin;
66
67 mCalDets["T0"] = CalPad("T0");
68 mCalDets["Width"] = CalPad("Width");
69 mCalDets["Qtot"] = CalPad("Qtot");
70}
71
72//______________________________________________________________________________
74{
75 const auto& param = CalibPulserParam::Instance();
76
77 mNbinsT0 = param.NbinsT0;
78 mXminT0 = param.XminT0;
79 mXmaxT0 = param.XmaxT0;
80 mNbinsQtot = param.NbinsQtot;
81 mXminQtot = param.XminQtot;
82 mXmaxQtot = param.XmaxQtot;
83 mNbinsWidth = param.NbinsWidth;
84 mXminWidth = param.XminWidth;
85 mXmaxWidth = param.XmaxWidth;
86 mFirstTimeBin = param.FirstTimeBin;
87 mLastTimeBin = param.LastTimeBin;
88 mADCMin = param.ADCMin;
89 mADCMax = param.ADCMax;
90 mNumberOfADCs = mADCMax - mADCMin + 1;
91 mPeakIntMinus = param.PeakIntMinus;
92 mPeakIntPlus = param.PeakIntPlus;
93 mMinimumQtot = param.MinimumQtot;
94 mMinimumQmax = param.MinimumQmax;
95 mMaxTimeBinRange = param.MaxTimeBinRange;
96}
97
98//______________________________________________________________________________
99Int_t CalibPulser::updateROC(const Int_t roc, const Int_t row, const Int_t pad,
100 const Int_t timeBin, Float_t signal)
101{
102 // ===| range checks |========================================================
103 if (timeBin < mFirstTimeBin || timeBin > mLastTimeBin) {
104 return 0;
105 }
106
107 // ---| pedestal subtraction |---
108 if (mPedestal) {
109 signal -= mPedestal->getValue(ROC(roc), row, pad);
110 }
111
112 if (signal < mADCMin || signal > mADCMax) {
113 return 0;
114 }
115
116 // ===| temporary calibration data |==========================================
117 const PadROCPos padROCPos(roc, row, pad);
118 VectorType& adcData = mPulserData[padROCPos];
119
120 if (!adcData.size()) {
121 // accept first and last time bin, so difference +1
122 adcData.resize(mLastTimeBin - mFirstTimeBin + 1);
123 // printf("new pad pos\n");
124 }
125
126 adcData[timeBin - mFirstTimeBin] = signal;
127 // printf("%2d, %3d, %3d, %3d: %.2f\n", roc, row, pad, timeBin, signal);
128
129 // ---| entries per time bin |---
130 auto& timeBinEntries = mTimeBinEntries[roc];
131 if (!timeBinEntries.size()) {
132 timeBinEntries.resize(mLastTimeBin - mFirstTimeBin + 1);
133 }
134 ++timeBinEntries[timeBin - mFirstTimeBin];
135
136 return 1;
137}
138
139//______________________________________________________________________________
141{
142 // loop over all signals of all pads filled for the present raw reader
143 // for (auto& keyValue : mPulserData) {
144 // const auto& padROCPos = keyValue.first;
145 // const auto& adcData = keyValue.second;
146 //
147 auto timeRangeROCs = getTimeRangeROCs();
148
149 for (const auto& [padROCPos, adcData] : mPulserData) {
150 const auto currentChannel = mMapper.getPadNumberInROC(padROCPos);
151
152 // std::cout << (int)padROCPos.getROC().getRoc() << ", " << padROCPos.getRow() << ", " << padROCPos.getPad() << std::endl;
153 // for (auto& val: adcData) std::cout << val << ", ";
154 // std::cout << std::endl;
155
156 const auto& elemPair = timeRangeROCs[int(padROCPos.getROC())];
157 const auto data = processPadData(padROCPos, adcData, elemPair);
158 // std::cout << data.mT0+mFirstTimeBin << " : " << data.mQtot << " : " << data.mWidth << "\n";
159
160 // fill histograms
161 if (data.isValid()) {
162 getHistoT0(padROCPos.getROC(), true)->Fill(data.mT0 + mFirstTimeBin, currentChannel);
163 getHistoQtot(padROCPos.getROC(), true)->Fill(data.mQtot, currentChannel);
164 getHistoSigma(padROCPos.getROC(), true)->Fill(data.mWidth, currentChannel);
165 }
166 }
167
168 // reset the adc data to free space
169 mPulserData.clear();
170 for (auto& v : mTimeBinEntries) {
171 std::fill(v.begin(), v.end(), 0);
172 }
173}
174
175//______________________________________________________________________________
176TH2S* CalibPulser::getHistogram(ROC roc, CalibPulser::PtrVectorType& rocVector,
177 int nbins, float min, float max,
178 std::string_view type, bool create /*=kFALSE*/)
179{
180 TH2S* vec = rocVector[roc].get();
181 if (vec || !create) {
182 return vec;
183 }
184
185 const size_t nChannels = mMapper.getNumberOfPads(roc);
186 rocVector[roc] = std::make_unique<TH2S>(Form("hCalib%s%02d", type.data(), roc.getRoc()),
187 Form("%s calibration histogram ROC %02d", type.data(), roc.getRoc()),
188 nbins, min, max,
189 nChannels, 0, nChannels);
190 // printf("new histogram %s for ROC %2d\n", type.data(), int(roc));
191 return rocVector[roc].get();
192}
193
194//______________________________________________________________________________
195CalibPulser::PulserData CalibPulser::processPadData(const PadROCPos& padROCPos, const CalibPulser::VectorType& adcData, const CalibPulser::ElemPair& range)
196{
197 // data to return
198 PulserData data;
199
200 // find time bin with maximum number of entreis
201
202 const auto vectorSize = adcData.size();
203 // const auto maxElement = std::max_element(std::begin(adcData), std::end(adcData));
204 const auto maxElement = std::max_element(std::begin(adcData) + range.first, std::begin(adcData) + range.last);
205
206 if (*maxElement < mMinimumQmax) {
207 return data;
208 }
209
210 const auto maxPosition = std::distance(std::begin(adcData), maxElement);
211
212 double weightedSum = 0.;
213 double weightedSum2 = 0.;
214 double chargeSum = 0.;
215 for (int t = maxPosition - mPeakIntMinus; t <= maxPosition + mPeakIntPlus; ++t) {
216 const auto signal = adcData[t];
217 // check time bounds
218 if (t < 0 || t >= vectorSize) {
219 continue;
220 }
221 weightedSum += signal * (t + 0.5); // +0.5 to get the center of the time bin
222 weightedSum2 += signal * (t + 0.5) * (t + 0.5);
223 chargeSum += signal;
224 }
225
226 if (chargeSum > mMinimumQtot) {
227 weightedSum /= chargeSum;
228 weightedSum2 = std::sqrt(std::abs(weightedSum2 / chargeSum - weightedSum * weightedSum));
229 // L1 phase correction?
230 data.mT0 = weightedSum;
231 data.mWidth = weightedSum2;
232 data.mQtot = chargeSum;
233 }
234
235 return data;
236}
237
238//______________________________________________________________________________
239std::array<CalibPulser::ElemPair, ROC::MaxROC> CalibPulser::getTimeRangeROCs()
240{
241 std::array<ElemPair, ROC::MaxROC> maxTimeBin;
242
243 for (size_t iROC = 0; iROC < mTimeBinEntries.size(); ++iROC) {
244 const auto& timeBinEntries = mTimeBinEntries[iROC];
245 const auto size = timeBinEntries.size();
246 const auto maxElement = std::max_element(std::begin(timeBinEntries), std::end(timeBinEntries));
247 const auto maxPosition = std::distance(std::begin(timeBinEntries), maxElement);
248
249 maxTimeBin[iROC].first = (maxPosition > mMaxTimeBinRange) ? maxPosition - mMaxTimeBinRange : 0;
250 maxTimeBin[iROC].last = std::min(size_t(maxPosition + mMaxTimeBinRange), size - 1);
251 }
252
253 return maxTimeBin;
254}
255
256//______________________________________________________________________________
258{
259 mPulserData.clear();
260 for (auto& v : mTimeBinEntries) {
261 std::fill(v.begin(), v.end(), 0);
262 }
263
264 std::vector<PtrVectorType*> v{&mT0Histograms, &mWidthHistograms, &mQtotHistograms};
265 for (auto histArray : v) {
266 for (auto& histPtr : *histArray) {
267 auto ptr = histPtr.get();
268 if (ptr) {
269 ptr->Reset();
270 }
271 }
272 }
273}
274
275//______________________________________________________________________________
277{
278 for (ROC roc; !roc.looped(); ++roc) {
279 auto histT0 = mT0Histograms.at(roc).get();
280 auto histWidth = mWidthHistograms.at(roc).get();
281 auto histQtot = mQtotHistograms.at(roc).get();
282
283 if (!histT0 || !histWidth || !histQtot) {
284 continue;
285 }
286
287 // array pointer
288 const auto arrT0 = histT0->GetArray();
289 const auto arrWidth = histWidth->GetArray();
290 const auto arrQtot = histQtot->GetArray();
291
292 const auto numberOfPads = mMapper.getNumberOfPads(roc);
293 for (auto iChannel = 0; iChannel < numberOfPads; ++iChannel) {
294 const int offsetT0 = (mNbinsT0 + 2) * (iChannel + 1) + 1;
295 const int offsetQtot = (mNbinsQtot + 2) * (iChannel + 1) + 1;
296 const int offsetWidth = (mNbinsWidth + 2) * (iChannel + 1) + 1;
297
298 StatisticsData dataT0 = getStatisticsData(arrT0 + offsetT0, mNbinsT0, mXminT0, mXmaxT0);
299 StatisticsData dataWidth = getStatisticsData(arrWidth + offsetWidth, mNbinsWidth, mXminWidth, mXmaxWidth);
300 StatisticsData dataQtot = getStatisticsData(arrQtot + offsetQtot, mNbinsQtot, mXminQtot, mXmaxQtot);
301
302 mCalDets["T0"].getCalArray(roc).setValue(iChannel, dataT0.mCOG);
303 mCalDets["Width"].getCalArray(roc).setValue(iChannel, dataWidth.mCOG);
304 mCalDets["Qtot"].getCalArray(roc).setValue(iChannel, dataQtot.mCOG);
305 }
306 }
307}
308
309//______________________________________________________________________________
310void CalibPulser::dumpToFile(const std::string filename, uint32_t type /* = 0*/)
311{
312 auto f = std::unique_ptr<TFile>(TFile::Open(filename.c_str(), "recreate"));
313 if (type == 0) {
314 f->WriteObject(&mCalDets["T0"], "T0");
315 f->WriteObject(&mCalDets["Width"], "Width");
316 f->WriteObject(&mCalDets["Qtot"], "Qtot");
317
318 if (mDebugLevel) {
319 printf("dump debug info\n");
320 // temporary arrays for writing the objects
321 TObjArray vT0;
322 for (auto& val : mT0Histograms) {
323 vT0.Add(val.get());
324 }
325 TObjArray vWidth;
326 for (auto& val : mWidthHistograms) {
327 vWidth.Add(val.get());
328 }
329 TObjArray vQtot;
330 for (auto& val : mQtotHistograms) {
331 vQtot.Add(val.get());
332 }
333
334 vT0.Write("T0Histograms", TObject::kSingleKey);
335 vWidth.Write("WidthHistograms", TObject::kSingleKey);
336 vQtot.Write("QtotHistograms", TObject::kSingleKey);
337 }
338 } else if (type == 1) {
339 f->WriteObject(this, "CalibPulser");
340 }
341
342 f->Close();
343}
Implementation of the parameter class for the hardware clusterer.
uint32_t roc
Definition RawData.h:3
TBranch * ptr
const T getValue(const int sec, const int globalPadInSector) const
Definition CalDet.h:154
CalibPulser(PadSubset padSubset=PadSubset::ROC)
default constructor
std::vector< float > VectorType
Definition CalibPulser.h:45
void init()
initialize the clusterer from CalibPedestalParam
void endReader() final
Process the end of one raw reader.
void analyse()
Analyse the buffered pulser information.
Int_t updateROC(const Int_t roc, const Int_t row, const Int_t pad, const Int_t timeBin, const Float_t signal) final
void resetData()
Reset temporary data and histogrms.
std::vector< std::unique_ptr< TH2S > > PtrVectorType
Definition CalibPulser.h:46
void dumpToFile(const std::string filename, uint32_t type=0) final
Dump the relevant data to file.
int mDebugLevel
debug level
const Mapper & mMapper
TPC mapper.
static constexpr unsigned short getNumberOfPads(const GEMstack gemStack)
Definition Mapper.h:416
GlobalPadNumber getPadNumberInROC(const PadROCPos &rocPadPosition) const
Definition Mapper.h:96
Pad and row inside a ROC.
Definition PadROCPos.h:37
@ MaxROC
Definition ROC.h:47
bool looped() const
if increment operator went above MaxROC
Definition ROC.h:108
GLsizeiptr size
Definition glcorearb.h:659
const GLdouble * v
Definition glcorearb.h:832
GLdouble f
Definition glcorearb.h:310
GLenum GLint * range
Definition glcorearb.h:1899
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLboolean * data
Definition glcorearb.h:298
GLuint GLfloat * val
Definition glcorearb.h:1582
GLenum GLfloat param
Definition glcorearb.h:271
StatisticsData getStatisticsData(const T *arr, const size_t nBins, const double xMin, const double xMax)
Definition fit.h:470
Global TPC definitions and constants.
Definition SimTraits.h:167
PadSubset
Definition of the different pad subsets.
Definition Defs.h:63
CalDet< float > CalPad
Definition CalDet.h:492
std::string filename()
double mCOG
calculated centre of gravity
Definition fit.h:457
constexpr size_t min
constexpr size_t max
constexpr size_t nChannels
std::vector< o2::ctf::BufferType > vec
std::vector< int > row