CMS 3D CMS Logo

CSCFindPeakTime.cc
Go to the documentation of this file.
1 // This is CSCFindPeakTime
2 
5 
6 #include <cmath>
7 
9  : useAverageTime(false), useParabolaFit(false), useFivePoleFit(false) {
10  useAverageTime = ps.getParameter<bool>("UseAverageTime");
11  useParabolaFit = ps.getParameter<bool>("UseParabolaFit");
12  useFivePoleFit = ps.getParameter<bool>("UseFivePoleFit");
13  LogTrace("CSCRecHit") << "[CSCFindPeakTime] useAverageTime=" << useAverageTime
14  << ", useParabolaFit=" << useParabolaFit << ", useFivePoleFit=" << useFivePoleFit;
15 }
16 
17 float CSCFindPeakTime::peakTime(int tmax, const float* adc, float t_peak) {
18  if (useAverageTime) {
19  return averageTime(tmax, adc);
20  } else if (useParabolaFit) {
21  return parabolaFitTime(tmax, adc);
22  } else if (useFivePoleFit) {
23  return fivePoleFitTime(tmax, adc, t_peak);
24  } else {
25  // return something, anyway.. may as well be average
26  return averageTime(tmax, adc);
27  }
28 }
29 
30 float CSCFindPeakTime::averageTime(int tmax, const float* adc) {
31  float sum = 0.;
32  float sumt = 0.;
33  for (size_t i = 0; i < 4; ++i) {
34  sum += adc[i];
35  sumt += adc[i] * float(tmax - 1 + i);
36  }
37  return sumt / sum * 50.; //@@ in ns. May be some bin width offset things to handle here?
38 }
39 
40 float CSCFindPeakTime::parabolaFitTime(int tmax, const float* adc) {
41  // 3-point parabolic fit, from Andy Kubik
42 
43  // We calculate offset to tmax by finding the peak of a parabola through three points
44  float tpeak = tmax;
45  float tcorr = 0;
46 
47  // By construction, input array adc is for bins tmax-1 to tmax+2
48  float y1 = adc[0];
49  float y2 = adc[1];
50  float y3 = adc[2];
51 
52  // Checked and simplified... Tim Cox 08-Apr-2009
53  // Denominator is not zero unless we fed in nonsense values with y2 not the peak!
54  if ((y1 + y3) < 2.f * y2)
55  tcorr = 0.5f * (y1 - y3) / (y1 - 2. * y2 + y3);
56  tpeak += tcorr;
57 
58  LogTrace("CSCFindPeakTime") << "[CSCFindPeakTime] tmax=" << tmax << ", parabolic peak time is tmax+" << tcorr
59  << " bins, or " << tpeak * 50.f << " ns";
60 
61  return tpeak * 50.f; // convert to ns.
62 }
63 
64 float CSCFindPeakTime::fivePoleFitTime(int tmax, const float* adc, float t_peak) {
65  // Input is
66  // tmax = bin# 0-7 containing max SCA pulse height
67  // adc = 4-dim array containing SCA pulse heights in bins tmax-1 to tmax+2
68  // t_peak = input estimate for SCA peak time
69 
70  // Returned value is improved (we hope) estimate for SCA peak time
71 
72  // Algorithm is to fit five-pole Semi-Gaussian function for start time of SCA pulse, t0
73  // (The SCA peak is assumed to be 133 ns from t0.)
74  // Note that t^4 in time domain corresponds to 1/t^5 in frequency domain (that's the 5 poles).
75 
76  // Initialize parameters to sensible (?) values
77 
78  float t0 = 0.f;
79  constexpr float t0peak = 133.f; // this is offset of peak from start time t0
80  constexpr float p0 = 4.f / t0peak;
81 
82  // Require that tmax is in range 2-6 of bins the eight SCA time bins 0-7
83  // (Bins 0, 1 used for dynamic ped)
84 
85  if (tmax < 2 || tmax > 6)
86  return t_peak; //@@ Just return the input value
87 
88  // Set up time bins to match adc[4] input
89 
90  float tb[4];
91  for (int time = 0; time < 4; ++time) {
92  tb[time] = (tmax + time - 1) * 50.f;
93  }
94 
95  // How many time bins are we fitting?
96 
97  int n_fit = 4;
98  if (tmax == 6)
99  n_fit = 3;
100 
101  float chi_min = 1.e10f;
102  float chi_last = 1.e10f;
103  float tt0 = 0.f;
104  float chi2 = 0.f;
105  float del_t = 100.f;
106 
107  float x[4];
108  float sx2 = 0.f;
109  float sxy = 0.f;
110  float fN = 0.f;
111 
112  while (del_t > 1.f) {
113  sx2 = 0.f;
114  sxy = 0.f;
115 
116  for (int j = 0; j < n_fit; ++j) {
117  float tdif = tb[j] - tt0;
118  x[j] = (tdif * tdif) * (tdif * tdif) * std::exp(-p0 * tdif);
119  sx2 += x[j] * x[j];
120  sxy += x[j] * adc[j];
121  }
122  fN = sxy / sx2; // least squares fit over time bins i to adc[i] = fN * fivePoleFunction[i]
123 
124  // Compute chi^2
125  chi2 = 0.0;
126  for (int j = 0; j < n_fit; ++j)
127  chi2 += (adc[j] - fN * x[j]) * (adc[j] - fN * x[j]);
128 
129  // Test on chi^2 to decide what to do
130  if (chi_last > chi2) {
131  if (chi2 < chi_min) {
132  t0 = tt0;
133  }
134  chi_last = chi2;
135  tt0 = tt0 + del_t;
136  } else {
137  tt0 = tt0 - 2.f * del_t;
138  del_t = 0.5 * del_t;
139  tt0 = tt0 + del_t;
140  chi_last = 1.0e10f;
141  }
142  }
143 
144  return t0 + t0peak;
145 }
146 
148  int tmax, const float* adc, const float& t_zero, const float& t_peak, std::vector<float>& adcsFit) {
149  //@@ This code can certainly be replaced by fivePoleFitTime above, but I haven't time to do that now (Tim).
150 
151  float p0 = 4.f / t_peak;
152  float tt0 = t_zero;
153  int n_fit = 4;
154  if (tmax == 6)
155  n_fit = 3;
156 
157  float tb[4], y[4];
158  for (int t = 0; t < 4; ++t) {
159  tb[t] = float(tmax + t - 1) * 50.f;
160  y[t] = adc[t];
161  }
162 
163  // Find the normalization factor for the function
164  float x[4];
165  float sx2 = 0.f;
166  float sxy = 0.f;
167  for (int j = 0; j < n_fit; ++j) {
168  float t = tb[j];
169  x[j] = ((t - tt0) * (t - tt0)) * ((t - tt0) * (t - tt0)) * std::exp(-p0 * (t - tt0));
170  sx2 = sx2 + x[j] * x[j];
171  sxy = sxy + x[j] * y[j];
172  }
173  float N = sxy / sx2;
174 
175  // Now compute charge for a given t --> only need charges at: t_peak-50, t_peak and t_peak+50
176  for (int i = 0; i < 3; ++i) {
177  float t = t_peak + float(i - 1) * 50.f;
178  float q_fitted = float(N) * ((t - tt0) * (t - tt0)) * ((t - tt0) * (t - tt0)) * std::exp(-p0 * (t - tt0));
179  adcsFit.push_back(q_fitted);
180  }
181  return;
182 }
float parabolaFitTime(int tmax, const float *adc)
Parabolic fit to three time bins centered on maximum.
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
float fivePoleFitTime(int tmax, const float *adc, float t_peak)
void fivePoleFitCharge(int tmax, const float *adc, const float &t_zero, const float &t_peak, std::vector< float > &adcsFit)
#define LogTrace(id)
double f[11][100]
static const double tmax[3]
#define N
Definition: blowfish.cc:9
CSCFindPeakTime(const edm::ParameterSet &ps)
float averageTime(int tmax, const float *adc)
Weighted average of time bins.
float peakTime(int tmax, const float *adc, float t_peak)
Basic result of this class.
uint16_t *__restrict__ uint16_t const *__restrict__ adc