CMS 3D CMS Logo

EcalUncalibRecHitRecChi2Algo.h
Go to the documentation of this file.
1 #ifndef RecoLocalCalo_EcalRecAlgos_EcalUncalibRecHitRecChi2Algo_HH
2 #define RecoLocalCalo_EcalRecAlgos_EcalUncalibRecHitRecChi2Algo_HH
3 
13 #include "Math/SVector.h"
14 #include "Math/SMatrix.h"
20 
21 
22 #include <vector>
23 
24 template<class C> class EcalUncalibRecHitRecChi2Algo
25 {
26  public:
27 
28  // destructor
30 
33  const C& dataFrame,
34  const double amplitude,
35  const EcalTimeCalibConstant& timeIC,
36  const double amplitudeOutOfTime,
37  const double jitter,
38  const double* pedestals,
39  const double* pedestalsRMS,
40  const double* gainRatios,
41  const EcalShapeBase & testbeamPulseShape,
42  const std::vector<double>& chi2Parameters
43  );
44 
45 
46  virtual double chi2(){return chi2_;}
47  virtual double chi2OutOfTime(){return chi2OutOfTime_;}
48 
49 
50  private:
51  double chi2_;
53 };
54 
55 
56 template <class C>
58  const C& dataFrame,
59  const double amplitude,
60  const EcalTimeCalibConstant& timeIC,
61  const double amplitudeOutOfTime,
62  const double jitter,
63  const double* pedestals,
64  const double* pedestalsRMS,
65  const double* gainRatios,
66  const EcalShapeBase & testbeamPulseShape,
67  const std::vector<double>& chi2Parameters
68 )
69 {
70 
71  double noise_A = chi2Parameters[0]; // noise term for in-time chi2
72  double const_A = chi2Parameters[1]; // constant term for in-time chi2
73  double noise_B = chi2Parameters[2]; // noise term for out-of-time chi2
74  double const_B = chi2Parameters[3]; // constant term for out-of-time chi2
75 
76 
77  chi2_=0;
79  double S_0=0; // will store the first mgpa sample
80  double ped_ave=0; // will store the average pedestal
81 
82  int gainId0 = 1;
83  int iGainSwitch = 0;
84  bool isSaturated = false;
85  for(int iSample = 0; iSample < C::MAXSAMPLES; iSample++) // if gain switch use later the pedestal RMS, otherwise we use the pedestal from the DB
86  {
87  int gainId = dataFrame.sample(iSample).gainId();
88  if(gainId == 0)
89  {
90  gainId = 3; // if saturated, treat it as G1
91  isSaturated = true;
92  }
93  if(gainId != gainId0)iGainSwitch = 1;
94 
95  if(gainId==1 && iSample==0)S_0 = dataFrame.sample(iSample).adc(); // take only first presample to estimate the pedestal
96  if(gainId==1 && iSample<3)ped_ave += (1/3.0)*dataFrame.sample(iSample).adc(); // take first 3 presamples to estimate the pedestal
97  }
98 
99 
100  // compute testbeamPulseShape shape parameters
101  double ADC_clock = 25; // 25 ns
102  double risingTime = testbeamPulseShape.timeToRise();
103  double tzero = risingTime - 5*ADC_clock; // 5 samples before the peak
104 
105  double shiftTime = + timeIC; // we put positive here
106  double shiftTimeOutOfTime = -jitter*ADC_clock; // we put negative here
107 
108 
109  bool readoutError = false;
110 
111  for(int iSample = 0; iSample < C::MAXSAMPLES; iSample++)
112  {
113  int gainId = dataFrame.sample(iSample).gainId();
114  if(dataFrame.sample(iSample).adc()==0)readoutError=true;
115  if(gainId==0)continue; // skip saturated samples
116 
117 
118  double ped = !iGainSwitch ? ped_ave:pedestals[gainId-1]; // use dynamic pedestal for G12 and average pedestal for G6,G1
119  //double pedRMS = pedestalsRMS[gainId-1];
120  double S_i = double(dataFrame.sample(iSample).adc());
121 
122  // --- calculate in-time chi2
123 
124 
125  double f_i = (testbeamPulseShape)(tzero + shiftTime + iSample*ADC_clock);
126  double R_i = (S_i- ped)*gainRatios[gainId-1] - f_i*amplitude;
127  double R_iErrorSquare = noise_A*noise_A + const_A*const_A*amplitude*amplitude;
128 
129  chi2_ += R_i*R_i/R_iErrorSquare;
130 
131  // --- calculate out-of-time chi2
132 
133  double g_i = (testbeamPulseShape)(tzero + shiftTimeOutOfTime + iSample*ADC_clock); // calculate out of time chi2
134 
135  double R_iOutOfTime = (S_i- S_0)*gainRatios[gainId-1] - g_i*amplitudeOutOfTime;
136  double R_iOutOfTimeErrorSquare = noise_B*noise_B + const_B*const_B*amplitudeOutOfTime*amplitudeOutOfTime;
137 
138 
139  chi2OutOfTime_ += R_iOutOfTime*R_iOutOfTime/R_iOutOfTimeErrorSquare;
140  }
141 
142 
143  if(!isSaturated && !iGainSwitch && chi2_>0 && chi2OutOfTime_>0)
144  {
145  chi2_ = 7*(3+log(chi2_)); chi2_ = chi2_<0 ? 0:chi2_; // this is just a convinient mapping for storing in the calibRecHit bit map
147  }else
148  {
149  chi2_=0;
150  chi2OutOfTime_=0;
151  }
152 
153  if(readoutError) // rare situation
154  {
155  chi2_=99.0; // chi2 is very large in these cases, put a code value to discriminate against normal noise
156  chi2OutOfTime_=99.0;
157  }
158 }
159 
160 #endif
constexpr int gainId(sample_type sample)
get the gainId (2 bits)
bool isSaturated(const Digi &digi, const int &maxADCvalue, int ifirst, int n)
float EcalTimeCalibConstant
static const double tzero[3]
double timeToRise() const override