Project
Loading...
Searching...
No Matches
CaloRawFitterGamma2.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 <fairlogger/Logger.h>
16#include <cfloat>
17#include <random>
18
19// ROOT sytem
20#include "TMath.h"
21
25
27
28using namespace o2::emcal;
29
30CaloRawFitterGamma2::CaloRawFitterGamma2() : CaloRawFitter("Chi Square ( Gamma2 )", "Gamma2")
31{
33}
34
35CaloFitResults CaloRawFitterGamma2::evaluate(const gsl::span<const Bunch> bunchlist)
36{
37 float time = 0;
38 float amp = 0;
39 float chi2 = 0;
40 int ndf = 0;
41 bool fitDone = false;
42
43 auto [nsamples, bunchIndex, ampEstimate,
44 maxADC, timeEstimate, pedEstimate, first, last] = preFitEvaluateSamples(bunchlist, mAmpCut);
45
46 if (bunchIndex >= 0 && ampEstimate >= mAmpCut) {
47 time = timeEstimate;
48 int timebinOffset = bunchlist[bunchIndex].getStartTime() - (bunchlist[bunchIndex].getBunchLength() - 1);
49 amp = ampEstimate;
50
51 if (nsamples > 2 && maxADC < constants::OVERFLOWCUT) {
52 std::tie(amp, time) = doParabolaFit(timeEstimate - 1);
53 mNiter = 0;
54 try {
55 chi2 = doFit_1peak(first, nsamples, amp, time);
56 fitDone = true;
57 } catch (RawFitterError_t& e) {
58 // Fit has failed, set values to estimates
59 // TODO: Check whether we want to include cases in which the peak fit failed
60 amp = ampEstimate;
61 time = timeEstimate;
62 chi2 = 1.e9;
63 }
64
65 time += timebinOffset;
66 timeEstimate += timebinOffset;
67 ndf = nsamples - 2;
68 }
69 }
70
71 if (fitDone) {
72 float ampAsymm = (amp - ampEstimate) / (amp + ampEstimate);
73 float timeDiff = time - timeEstimate;
74
75 if ((TMath::Abs(ampAsymm) > 0.1) || (TMath::Abs(timeDiff) > 2)) {
76 amp = ampEstimate;
77 time = timeEstimate;
78 fitDone = false;
79 }
80 }
81 if (amp >= mAmpCut) {
82 if (!fitDone) {
83 std::default_random_engine generator;
84 std::uniform_real_distribution<float> distribution(0.0, 1.0);
85 amp += (0.5 - distribution(generator));
86 }
87 time = time * constants::EMCAL_TIMESAMPLE;
88 time -= mL1Phase;
89
90 return CaloFitResults(maxADC, pedEstimate, 0, amp, time, (int)time, chi2, ndf);
91 }
92 // Fit failed, rethrow error
94}
95
96float CaloRawFitterGamma2::doFit_1peak(int firstTimeBin, int nSamples, float& ampl, float& time)
97{
98
99 float chi2(0.);
100
101 // fit using gamma-2 function (ORDER =2 assumed)
102 if (nSamples < 3) {
104 }
105 if (mNiter > mNiterationsMax) {
107 }
108
109 double D, dA, dt;
110 double c11 = 0;
111 double c12 = 0;
112 double c21 = 0;
113 double c22 = 0;
114 double d1 = 0;
115 double d2 = 0;
116
117 mNiter++;
118
119 for (int itbin = 0; itbin < nSamples; itbin++) {
120
121 double ti = (itbin - time) / constants::TAU;
122 if ((ti + 1) < 0) {
123 continue;
124 }
125
126 double g_1i = (ti + 1) * TMath::Exp(-2 * ti);
127 double g_i = (ti + 1) * g_1i;
128 double gp_i = 2 * (g_i - g_1i);
129 double q1_i = (2 * ti + 1) * TMath::Exp(-2 * ti);
130 double q2_i = g_1i * g_1i * (4 * ti + 1);
131 c11 += (getReversed(itbin) - ampl * 2 * g_i) * gp_i;
132 c12 += g_i * g_i;
133 c21 += getReversed(itbin) * q1_i - ampl * q2_i;
134 c22 += g_i * g_1i;
135 double delta = ampl * g_i - getReversed(itbin);
136 d1 += delta * g_i;
137 d2 += delta * g_1i;
138 chi2 += (delta * delta);
139 }
140
141 D = c11 * c22 - c12 * c21;
142
143 if (TMath::Abs(D) < DBL_EPSILON) {
145 }
146
147 dt = (d1 * c22 - d2 * c12) / D * constants::TAU;
148 dA = (d1 * c21 - d2 * c11) / D;
149
150 time += dt;
151 ampl += dA;
152
153 if (TMath::Abs(dA) > 1 || TMath::Abs(dt) > 0.01) {
154 chi2 = doFit_1peak(firstTimeBin, nSamples, ampl, time);
155 }
156
157 return chi2;
158}
159
160std::tuple<float, float> CaloRawFitterGamma2::doParabolaFit(int maxTimeBin) const
161{
162 float amp(0.), time(0.);
163
164 // The equation of parabola is "y = a*x^2 + b*x + c"
165 // We have to find "a", "b", and "c"
166
167 double a = (getReversed(maxTimeBin + 2) + getReversed(maxTimeBin) - 2. * getReversed(maxTimeBin + 1)) / 2.;
168
169 if (TMath::Abs(a) < DBL_EPSILON) {
170 amp = getReversed(maxTimeBin + 1);
171 time = maxTimeBin + 1;
172 return std::make_tuple(amp, time);
173 }
174
175 double b = getReversed(maxTimeBin + 1) - getReversed(maxTimeBin) - a * (2. * maxTimeBin + 1);
176 double c = getReversed(maxTimeBin) - b * maxTimeBin - a * maxTimeBin * maxTimeBin;
177
178 time = -b / 2. / a;
179 amp = a * time * time + b * time + c;
180
181 return std::make_tuple(amp, time);
182}
int16_t time
Definition RawEventData.h:4
std::vector< uint16_t > nsamples
Definition testDigit.cxx:38
uint32_t c
Definition RawData.h:2
Container class to hold results from fitting.
CaloFitResults evaluate(const gsl::span< const Bunch > bunchvector) final
Evaluation Amplitude and TOF.
float mAmpCut
Max ADC - pedestal must be higher than this befor attemting to extract the amplitude.
double getReversed(const int i) const
std::tuple< int, int, float, short, short, float, int, int > preFitEvaluateSamples(const gsl::span< const Bunch > bunchvector, int adcThreshold)
Method to do the selection of what should possibly be fitted.
double mL1Phase
Phase of the ADC sampling clock relative to the LHC clock.
RawFitterError_t
Error codes for failures in raw fitter procedure.
FitAlgorithm mAlgo
Which algorithm to use.
GLint first
Definition glcorearb.h:399
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
@ Gamma2
Gamma2 raw fitter.
Definition Constants.h:113
value_T d2
Definition TrackUtils.h:135