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