Project
Loading...
Searching...
No Matches
CaloRawFitter.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 <gsl/span>
16
19
20using namespace o2::phos;
21
29
30CaloRawFitter::FitStatus CaloRawFitter::evaluate(gsl::span<short unsigned int> signal)
31{
32
33 //Pedestal analysis mode
34 if (mPedestalRun) {
35 int nPed = signal.size();
36 float mean = 0.;
37 float rms = 0.;
38 for (auto a : signal) {
39 mean += a;
40 rms += a * a;
41 }
42 if (nPed > 0) {
43 mean /= nPed;
44 rms = rms / nPed - mean * mean;
45 if (rms > 0.) {
46 rms = sqrt(rms);
47 }
48 }
49 mAmp = mean;
50 mTime = rms; // only in Pedestal mode!
51 mOverflow = false;
52 mStatus = kOK;
53 return kOK;
54 }
55
56 // Extract amplitude and time using maximum and k-level methods
57 return evalKLevel(signal);
58}
59
60CaloRawFitter::FitStatus CaloRawFitter::evalKLevel(gsl::span<short unsigned int> signal) //const ushort *signal, int sigStart, int sigLength)
61{
62 // Calculate signal parameters (energy, time, quality) from array of samples
63 // Energy is a maximum sample minus pedestal 9
64 // Time is the first time bin
65 // Signal overflows is there are at least 3 samples of the same amplitude above 900
66
67 int sigLength = signal.size();
68 if (sigLength == 0) {
69 return kEmptyBunch;
70 }
71
72 float pedMean = 0;
73 int nPed = 0;
74 mMaxSample = 0;
75 int nMax = 0; //number of consequitive maximal samples
76 bool spike = false;
77 mOverflow = false;
78
79 int ap = -1, app = -1; //remember previous values to evaluate spikes
80 for (auto it = signal.rbegin(); it != signal.rend(); ++it) {
81 uint16_t a = *it;
82 if (mPedSubtract) {
83 if (nPed < mPreSamples) { //inverse signal time order
84 nPed++;
85 pedMean += a;
86 }
87 }
88 if (a > mMaxSample) {
89 mMaxSample = a;
90 nMax = 0;
91 }
92 if (a == mMaxSample) {
93 nMax++;
94 }
95 //check if there is a spike
96 if (app >= 0 && ap >= 0) {
97 spike |= (2 * ap - (a + app) > 2 * mSpikeThreshold);
98 }
99 app = ap;
100 ap = a;
101 }
102 mAmp = (float)mMaxSample;
103
104 if (spike) {
105 mTime = -2;
106 mOverflow = false;
107 return kSpike;
108 }
109
110 if (mMaxSample > 900 && nMax > 2) {
111 mOverflow = true;
112 }
113
114 float pedestal = 0;
115 if (mPedSubtract) {
116 if (nPed > 0) {
117 pedMean /= nPed;
118 } else {
119 mAmp = 0.;
120 mTime = -2;
121 mOverflow = false;
122 return kBadPedestal;
123 }
124 } else {
125 pedMean = 0.;
126 }
127
128 mAmp -= pedMean;
129 if (mAmp < mBaseLine) {
130 mAmp = 0;
131 }
132
133 //Evaluate time
134 mTime = -2;
135 const int nLine = 6; //Parameters of fitting
136 const float eMinTOF = 10.; //Choosed from beam-test and cosmic analyis
137 const float kAmp = 0.35; //Result slightly depends on them, so no getters
138 // Avoid too low peak:
139 if (mAmp < eMinTOF) {
140 return kOK; //use estimated time
141 }
142
143 // Find index posK (kLevel is a level of "timestamp" point Tk):
144 int posK = sigLength - 1; //last point before crossing k-level
145 float levelK = pedestal + kAmp * mAmp;
146 while (posK >= 0 && signal[posK] <= levelK) {
147 posK--;
148 }
149 posK++;
150
151 if (posK == 0 || posK == sigLength - 1) {
152 return kNoTime; //
153 }
154
155 // Find crossing point by solving linear equation (least squares method)
156 int np = 0;
157 int iup = posK - 1;
158 int idn = posK;
159 double sx = 0., sy = 0., sxx = 0., sxy = 0.;
160 double x, y;
161
162 while (np < nLine) {
163 //point above crossing point
164 if (iup >= 0) {
165 x = sigLength - iup - 1;
166 y = signal[iup];
167 sx += x;
168 sy += y;
169 sxx += (x * x);
170 sxy += (x * y);
171 np++;
172 iup--;
173 }
174 //Point below crossing point
175 if (idn < sigLength) {
176 if (signal[idn] < pedestal) {
177 idn = sigLength - 1; //do not scan further
178 idn++;
179 continue;
180 }
181 x = sigLength - idn - 1;
182 y = signal[idn];
183 sx += x;
184 sy += y;
185 sxx += (x * x);
186 sxy += (x * y);
187 np++;
188 idn++;
189 }
190 if (idn >= sigLength && iup < 0) {
191 break; //can not fit futher
192 }
193 }
194
195 double det = np * sxx - sx * sx;
196 if (det == 0) {
197 return kNoTime;
198 }
199 if (np == 0) {
200 return kEmptyBunch;
201 }
202 double c1 = (np * sxy - sx * sy) / det; //slope
203 double c0 = (sy - c1 * sx) / np; //offset
204 if (c1 == 0) {
205 return kNoTime;
206 }
207
208 // Find where the line cross kLevel:
209 mTime += (levelK - c0) / c1 - 5.; //5: mean offset between k-Level and start times
210
211 if (mOverflow) {
212 return kOverflow;
213 } else {
214 return kOK;
215 }
216}
bool const GPUTPCGMMerger::trackCluster * c1
FitStatus evalKLevel(gsl::span< short unsigned int > signal)
float mAmp
amplitude of last processed sample
bool mOverflow
is last sample saturated
short mMaxSample
maximal sample
bool mPedSubtract
should one evaluate and subtract pedestals
float mTime
time of last processed sample
virtual FitStatus evaluate(gsl::span< short unsigned int > signal)
Evaluation Amplitude and TOF return status -1: not evaluated/empty bunch; 0: OK; 1: overflow; 4: sing...
bool mPedestalRun
analyze as pedestal run
FitStatus mStatus
status of last evaluated sample: -1: not yet evaluated; 0: OK; 1: overflow; 2: too large RMS; 3: sing...
GLint GLenum GLint x
Definition glcorearb.h:403
GLint y
Definition glcorearb.h:270
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
short mSpikeThreshold
Single spike >100 ADC channels.
short mPreSamples
number of pre-samples readout before sample (if no pedestal subtrauction)