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