CMS 3D CMS Logo

HBHEPulseShapeFlag.h
Go to the documentation of this file.
1 //---------------------------------------------------------------------------
2 #ifndef HBHE_PULSESHAPE_FLAG_H_IKAJHGEWRHIGKHAWFIKGHAWIKGH
3 #define HBHE_PULSESHAPE_FLAG_H_IKAJHGEWRHIGKHAWFIKGHAWIKGH
4 //---------------------------------------------------------------------------
5 // Fitting-based algorithms for HBHE noise flagging
6 //
7 // Included:
8 // 1. Linear discriminator (chi2 from linear fit / chi2 from nominal fit)
9 // 2. RMS8/Max ((RMS8/Max)^2 / chi2 from nominal fit)
10 // 3. Triangle fit
11 //
12 // Original Author: Yi Chen (Caltech), 6351 (Nov. 8, 2010)
13 //---------------------------------------------------------------------------
14 #include <string>
15 #include <vector>
16 #include <map>
17 #include <cmath>
18 //---------------------------------------------------------------------------
26 //---------------------------------------------------------------------------
28 struct TriangleFitResult;
29 //---------------------------------------------------------------------------
31 public:
33  double TS4TS5ChargeThreshold,
34  double TS3TS4ChargeThreshold,
36  double TS5TS6ChargeThreshold,
38  double R45PlusOneRange,
39  double R45MinusOneRange,
40  unsigned int TrianglePeakTS,
41  const std::vector<double>& LinearThreshold,
42  const std::vector<double>& LinearCut,
43  const std::vector<double>& RMS8MaxThreshold,
44  const std::vector<double>& RMS8MaxCut,
45  const std::vector<double>& LeftSlopeThreshold,
46  const std::vector<double>& LeftSlopeCut,
47  const std::vector<double>& RightSlopeThreshold,
48  const std::vector<double>& RightSlopeCut,
49  const std::vector<double>& RightSlopeSmallThreshold,
50  const std::vector<double>& RightSlopeSmallCut,
51  const std::vector<double>& TS4TS5UpperThreshold,
52  const std::vector<double>& TS4TS5UpperCut,
53  const std::vector<double>& TS4TS5LowerThreshold,
54  const std::vector<double>& TS4TS5LowerCut,
55  bool UseDualFit,
56  bool TriangleIgnoreSlow,
57  bool setLegacyFlags = true);
58 
60 
61  void Clear();
62  void Initialize();
63 
64  template <class Dataframe>
66  const Dataframe& digi,
67  const HcalCoder& coder,
68  const HcalCalibrations& calib);
69 
70 private:
80  std::vector<double> mCharge; // stores charge for each TS in each digi
81  // the pair is defined as (threshold, cut position)
82  std::vector<std::pair<double, double> > mLambdaLinearCut;
83  std::vector<std::pair<double, double> > mLambdaRMS8MaxCut;
84  std::vector<std::pair<double, double> > mLeftSlopeCut;
85  std::vector<std::pair<double, double> > mRightSlopeCut;
86  std::vector<std::pair<double, double> > mRightSlopeSmallCut;
87  std::vector<std::pair<double, double> > mTS4TS5UpperCut;
88  std::vector<std::pair<double, double> > mTS4TS5LowerCut;
92  std::vector<double> CumulativeIdealPulse;
93 
94 private:
95  TriangleFitResult PerformTriangleFit(const std::vector<double>& Charge);
96  double PerformNominalFit(const std::vector<double>& Charge);
97  double PerformDualNominalFit(const std::vector<double>& Charge);
98  double DualNominalFitSingleTry(const std::vector<double>& Charge, int Offset, int Distance, bool newCharges = true);
99  double CalculateRMS8Max(const std::vector<double>& Charge);
100  double PerformLinearFit(const std::vector<double>& Charge);
101 
102 private:
103  bool CheckPassFilter(double Charge, double Discriminant, std::vector<std::pair<double, double> >& Cuts, int Side);
104  std::vector<double> f1_;
105  std::vector<double> f2_;
106  std::vector<double> errors_;
107 };
108 //---------------------------------------------------------------------------
110  double Chi2;
111  double LeftSlope;
112  double RightSlope;
113 };
114 //---------------------------------------------------------------------------
115 
116 template <class Dataframe>
118  const Dataframe& digi,
119  const HcalCoder& coder,
120  const HcalCalibrations& calib) {
121  //
122  // Decide if a digi/pulse is good or bad using fit-based discriminants
123  //
124  // SetPulseShapeFlags determines the total charge in the digi.
125  // If the charge is above the minimum threshold, the code then
126  // runs the flag-setting algorithms to determine whether the
127  // flags should be set.
128  //
129 
130  // hack to exclude ieta=28/29 for the moment...
131  int abseta = hbhe.id().ietaAbs();
132  if (abseta == 28 || abseta == 29)
133  return;
134 
135  CaloSamples Tool;
136  coder.adc2fC(digi, Tool);
137 
138  // mCharge.clear(); // mCharge is a vector of (pedestal-subtracted) Charge values vs. time slice
139  const unsigned nRead = digi.size();
140  mCharge.resize(nRead);
141 
142  double TotalCharge = 0.0;
143  for (unsigned i = 0; i < nRead; ++i) {
144  mCharge[i] = Tool[i] - calib.pedestal(digi[i].capid());
145  TotalCharge += mCharge[i];
146  }
147 
148  // No flagging if TotalCharge is less than threshold
149  if (TotalCharge < mMinimumChargeThreshold)
150  return;
151 
152  if (mSetLegacyFlags) {
153  double NominalChi2 = 0;
154  if (mUseDualFit == true)
155  NominalChi2 = PerformDualNominalFit(mCharge);
156  else
157  NominalChi2 = PerformNominalFit(mCharge);
158 
159  double LinearChi2 = PerformLinearFit(mCharge);
160 
161  double RMS8Max = CalculateRMS8Max(mCharge);
162 
163  // Set the HBHEFlatNoise and HBHESpikeNoise flags
164  if (CheckPassFilter(TotalCharge, log(LinearChi2) - log(NominalChi2), mLambdaLinearCut, -1) == false)
165  hbhe.setFlagField(1, HcalCaloFlagLabels::HBHEFlatNoise);
166  if (CheckPassFilter(TotalCharge, log(RMS8Max) * 2 - log(NominalChi2), mLambdaRMS8MaxCut, -1) == false)
167  hbhe.setFlagField(1, HcalCaloFlagLabels::HBHESpikeNoise);
168 
169  // Set the HBHETriangleNoise flag
170  if ((int)mCharge.size() >=
171  mTrianglePeakTS) // can't compute flag if peak TS isn't present; revise this at some point?
172  {
173  TriangleFitResult TriangleResult = PerformTriangleFit(mCharge);
174 
175  // initial values
176  double TS4Left = 1000;
177  double TS4Right = 1000;
178 
179  // Use 'if' statements to protect against slopes that are either 0 or very small
180  if (TriangleResult.LeftSlope > 1e-5)
181  TS4Left = mCharge[mTrianglePeakTS] / TriangleResult.LeftSlope;
182  if (TriangleResult.RightSlope < -1e-5)
183  TS4Right = mCharge[mTrianglePeakTS] / -TriangleResult.RightSlope;
184 
185  if (TS4Left > 1000 || TS4Left < -1000)
186  TS4Left = 1000;
187  if (TS4Right > 1000 || TS4Right < -1000)
188  TS4Right = 1000;
189 
190  if (mTriangleIgnoreSlow == false) // the slow-rising and slow-dropping edges won't be useful in 50ns/75ns
191  {
192  if (CheckPassFilter(mCharge[mTrianglePeakTS], TS4Left, mLeftSlopeCut, 1) == false)
194  else if (CheckPassFilter(mCharge[mTrianglePeakTS], TS4Right, mRightSlopeCut, 1) == false)
196  }
197 
198  // fast-dropping ones should be checked in any case
199  if (CheckPassFilter(mCharge[mTrianglePeakTS], TS4Right, mRightSlopeSmallCut, -1) == false)
201  }
202  }
203 
204  int soi = digi.presamples();
205 
206  if (mCharge[soi] + mCharge[soi + 1] > mTS4TS5ChargeThreshold &&
207  mTS4TS5ChargeThreshold > 0) // silly protection against negative charge values
208  {
209  double TS4TS5 = (mCharge[soi] - mCharge[soi + 1]) / (mCharge[soi] + mCharge[soi + 1]);
210  if (CheckPassFilter(mCharge[soi] + mCharge[soi + 1], TS4TS5, mTS4TS5UpperCut, 1) == false)
211  hbhe.setFlagField(1, HcalCaloFlagLabels::HBHETS4TS5Noise);
212  if (CheckPassFilter(mCharge[soi] + mCharge[soi + 1], TS4TS5, mTS4TS5LowerCut, -1) == false)
213  hbhe.setFlagField(1, HcalCaloFlagLabels::HBHETS4TS5Noise);
214 
215  if (CheckPassFilter(mCharge[soi] + mCharge[soi + 1], TS4TS5, mTS4TS5UpperCut, 1) ==
216  false && // TS4TS5 is above envelope
217  mCharge[soi - 1] + mCharge[soi] > mTS3TS4ChargeThreshold &&
218  mTS3TS4ChargeThreshold > 0 && // enough charge in 34
219  mCharge[soi + 1] + mCharge[soi + 2] < mTS5TS6UpperChargeThreshold &&
220  mTS5TS6UpperChargeThreshold > 0 && // low charge in 56
221  fabs((mCharge[soi] - mCharge[soi + 1]) / (mCharge[soi] + mCharge[soi + 1]) - 1.0) <
222  mR45PlusOneRange) // R45 is around +1
223  {
224  double TS3TS4 = (mCharge[soi - 1] - mCharge[soi]) / (mCharge[soi - 1] + mCharge[soi]);
225  if (CheckPassFilter(mCharge[soi - 1] + mCharge[soi], TS3TS4, mTS4TS5UpperCut, 1) ==
226  true && // use the same envelope as TS4TS5
227  CheckPassFilter(mCharge[soi - 1] + mCharge[soi], TS3TS4, mTS4TS5LowerCut, -1) ==
228  true && // use the same envelope as TS4TS5
229  TS3TS4 > (mR45MinusOneRange - 1)) // horizontal cut on R34 (R34>-0.8)
230  hbhe.setFlagField(
231  1, HcalCaloFlagLabels::HBHEOOTPU); // set to 1 if there is a pulse-shape-wise good OOTPU in TS3TS4.
232  }
233 
234  if (CheckPassFilter(mCharge[soi] + mCharge[soi + 1], TS4TS5, mTS4TS5LowerCut, -1) ==
235  false && // TS4TS5 is below envelope
236  mCharge[soi - 1] + mCharge[soi] < mTS3TS4UpperChargeThreshold &&
237  mTS3TS4UpperChargeThreshold > 0 && // low charge in 34
238  mCharge[soi + 1] + mCharge[soi + 2] > mTS5TS6ChargeThreshold &&
239  mTS5TS6ChargeThreshold > 0 && // enough charge in 56
240  fabs((mCharge[soi] - mCharge[soi + 1]) / (mCharge[soi] + mCharge[soi + 1]) + 1.0) <
241  mR45MinusOneRange) // R45 is around -1
242  {
243  double TS5TS6 = (mCharge[soi + 1] - mCharge[soi + 2]) / (mCharge[soi + 1] + mCharge[soi + 2]);
244  if (CheckPassFilter(mCharge[soi + 1] + mCharge[soi + 2], TS5TS6, mTS4TS5UpperCut, 1) ==
245  true && // use the same envelope as TS4TS5
246  CheckPassFilter(mCharge[soi + 1] + mCharge[soi + 2], TS5TS6, mTS4TS5LowerCut, -1) ==
247  true && // use the same envelope as TS4TS5
248  TS5TS6 < (1 - mR45PlusOneRange)) // horizontal cut on R56 (R56<+0.8)
249  hbhe.setFlagField(
250  1, HcalCaloFlagLabels::HBHEOOTPU); // set to 1 if there is a pulse-shape-wise good OOTPU in TS5TS6.
251  }
252  }
253 }
254 
255 #endif
std::vector< double > f1_
std::vector< std::pair< double, double > > mLambdaLinearCut
HBHEPulseShapeFlagSetter(double MinimumChargeThreshold, double TS4TS5ChargeThreshold, double TS3TS4ChargeThreshold, double TS3TS4UpperChargeThreshold, double TS5TS6ChargeThreshold, double TS5TS6UpperChargeThreshold, double R45PlusOneRange, double R45MinusOneRange, unsigned int TrianglePeakTS, const std::vector< double > &LinearThreshold, const std::vector< double > &LinearCut, const std::vector< double > &RMS8MaxThreshold, const std::vector< double > &RMS8MaxCut, const std::vector< double > &LeftSlopeThreshold, const std::vector< double > &LeftSlopeCut, const std::vector< double > &RightSlopeThreshold, const std::vector< double > &RightSlopeCut, const std::vector< double > &RightSlopeSmallThreshold, const std::vector< double > &RightSlopeSmallCut, const std::vector< double > &TS4TS5UpperThreshold, const std::vector< double > &TS4TS5UpperCut, const std::vector< double > &TS4TS5LowerThreshold, const std::vector< double > &TS4TS5LowerCut, bool UseDualFit, bool TriangleIgnoreSlow, bool setLegacyFlags=true)
void SetPulseShapeFlags(HBHERecHit &hbhe, const Dataframe &digi, const HcalCoder &coder, const HcalCalibrations &calib)
std::vector< double > f2_
double CalculateRMS8Max(const std::vector< double > &Charge)
std::vector< std::pair< double, double > > mTS4TS5LowerCut
double PerformNominalFit(const std::vector< double > &Charge)
double DualNominalFitSingleTry(const std::vector< double > &Charge, int Offset, int Distance, bool newCharges=true)
double PerformDualNominalFit(const std::vector< double > &Charge)
double PerformLinearFit(const std::vector< double > &Charge)
std::vector< std::pair< double, double > > mLeftSlopeCut
TriangleFitResult PerformTriangleFit(const std::vector< double > &Charge)
std::vector< std::pair< double, double > > mRightSlopeCut
bool CheckPassFilter(double Charge, double Discriminant, std::vector< std::pair< double, double > > &Cuts, int Side)
std::vector< double > mCharge
std::vector< std::pair< double, double > > mRightSlopeSmallCut
virtual void adc2fC(const HBHEDataFrame &df, CaloSamples &lf) const =0
std::vector< double > errors_
std::vector< double > CumulativeIdealPulse
std::vector< std::pair< double, double > > mLambdaRMS8MaxCut
std::vector< std::pair< double, double > > mTS4TS5UpperCut