CMS 3D CMS Logo

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