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 {
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>
65  void SetPulseShapeFlags(HBHERecHit& hbhe, const Dataframe& digi,
66  const HcalCoder& coder, const HcalCalibrations& calib);
67 private:
77  std::vector<double> mCharge; // stores charge for each TS in each digi
78  // the pair is defined as (threshold, cut position)
79  std::vector<std::pair<double, double> > mLambdaLinearCut;
80  std::vector<std::pair<double, double> > mLambdaRMS8MaxCut;
81  std::vector<std::pair<double, double> > mLeftSlopeCut;
82  std::vector<std::pair<double, double> > mRightSlopeCut;
83  std::vector<std::pair<double, double> > mRightSlopeSmallCut;
84  std::vector<std::pair<double, double> > mTS4TS5UpperCut;
85  std::vector<std::pair<double, double> > mTS4TS5LowerCut;
89  std::vector<double> CumulativeIdealPulse;
90 private:
91  TriangleFitResult PerformTriangleFit(const std::vector<double> &Charge);
92  double PerformNominalFit(const std::vector<double> &Charge);
93  double PerformDualNominalFit(const std::vector<double> &Charge);
94  double DualNominalFitSingleTry(const std::vector<double> &Charge, int Offset, int Distance, bool newCharges=true);
95  double CalculateRMS8Max(const std::vector<double> &Charge);
96  double PerformLinearFit(const std::vector<double> &Charge);
97 private:
98  bool CheckPassFilter(double Charge, double Discriminant, std::vector<std::pair<double, double> > &Cuts,
99  int Side);
100  std::vector<double> f1_;
101  std::vector<double> f2_;
102  std::vector<double> errors_;
103 
104 };
105 //---------------------------------------------------------------------------
107 {
108  double Chi2;
109  double LeftSlope;
110  double RightSlope;
111 };
112 //---------------------------------------------------------------------------
113 
114 template<class Dataframe>
116  HBHERecHit& hbhe, const Dataframe& digi,
117  const HcalCoder& coder, const HcalCalibrations& calib)
118 {
119  //
120  // Decide if a digi/pulse is good or bad using fit-based discriminants
121  //
122  // SetPulseShapeFlags determines the total charge in the digi.
123  // If the charge is above the minimum threshold, the code then
124  // runs the flag-setting algorithms to determine whether the
125  // flags should be set.
126  //
127 
128  // hack to exclude ieta=28/29 for the moment...
129  int abseta = hbhe.id().ietaAbs();
130  if(abseta == 28 || abseta == 29) return;
131 
132  CaloSamples Tool;
133  coder.adc2fC(digi, Tool);
134 
135  // mCharge.clear(); // mCharge is a vector of (pedestal-subtracted) Charge values vs. time slice
136  const unsigned nRead = digi.size();
137  mCharge.resize(nRead);
138 
139  double TotalCharge = 0.0;
140  for (unsigned i = 0; i < nRead; ++i)
141  {
142  mCharge[i] = Tool[i] - calib.pedestal(digi[i].capid());
143  TotalCharge += mCharge[i];
144  }
145 
146  // No flagging if TotalCharge is less than threshold
147  if(TotalCharge < mMinimumChargeThreshold)
148  return;
149 
150  if (mSetLegacyFlags)
151  {
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() >= mTrianglePeakTS) // can't compute flag if peak TS isn't present; revise this at some point?
170  {
171  TriangleFitResult TriangleResult = PerformTriangleFit(mCharge);
172 
173  // initial values
174  double TS4Left = 1000;
175  double TS4Right = 1000;
176 
177  // Use 'if' statements to protect against slopes that are either 0 or very small
178  if (TriangleResult.LeftSlope > 1e-5)
179  TS4Left = mCharge[mTrianglePeakTS] / TriangleResult.LeftSlope;
180  if (TriangleResult.RightSlope < -1e-5)
181  TS4Right = mCharge[mTrianglePeakTS] / -TriangleResult.RightSlope;
182 
183  if(TS4Left > 1000 || TS4Left < -1000)
184  TS4Left = 1000;
185  if(TS4Right > 1000 || TS4Right < -1000)
186  TS4Right = 1000;
187 
188  if(mTriangleIgnoreSlow == false) // the slow-rising and slow-dropping edges won't be useful in 50ns/75ns
189  {
190  if(CheckPassFilter(mCharge[mTrianglePeakTS], TS4Left, mLeftSlopeCut, 1) == false)
192  else if(CheckPassFilter(mCharge[mTrianglePeakTS], TS4Right, mRightSlopeCut, 1) == false)
194  }
195 
196  // fast-dropping ones should be checked in any case
197  if(CheckPassFilter(mCharge[mTrianglePeakTS], TS4Right, mRightSlopeSmallCut, -1) == false)
199  }
200  }
201 
202  int soi = digi.presamples();
203 
204  if(mCharge[soi] + mCharge[soi+1] > mTS4TS5ChargeThreshold && mTS4TS5ChargeThreshold>0) // silly protection against negative charge values
205  {
206  double TS4TS5 = (mCharge[soi] - mCharge[soi+1]) / (mCharge[soi] + mCharge[soi+1]);
207  if(CheckPassFilter(mCharge[soi] + mCharge[soi+1], TS4TS5, mTS4TS5UpperCut, 1) == false)
209  if(CheckPassFilter(mCharge[soi] + mCharge[soi+1], TS4TS5, mTS4TS5LowerCut, -1) == false)
211 
212  if(CheckPassFilter(mCharge[soi] + mCharge[soi+1], TS4TS5, mTS4TS5UpperCut, 1) == false && // TS4TS5 is above envelope
213  mCharge[soi-1] + mCharge[soi] > mTS3TS4ChargeThreshold && mTS3TS4ChargeThreshold>0 && // enough charge in 34
214  mCharge[soi+1] + mCharge[soi+2] < mTS5TS6UpperChargeThreshold && mTS5TS6UpperChargeThreshold>0 && // low charge in 56
215  fabs( (mCharge[soi] - mCharge[soi+1]) / (mCharge[soi] + mCharge[soi+1]) - 1.0 ) < mR45PlusOneRange ) // R45 is around +1
216  {
217  double TS3TS4 = (mCharge[soi-1] - mCharge[soi]) / (mCharge[soi-1] + mCharge[soi]);
218  if(CheckPassFilter(mCharge[soi-1] + mCharge[soi], TS3TS4, mTS4TS5UpperCut, 1) == true && // use the same envelope as TS4TS5
219  CheckPassFilter(mCharge[soi-1] + mCharge[soi], TS3TS4, mTS4TS5LowerCut, -1) == true && // use the same envelope as TS4TS5
220  TS3TS4>(mR45MinusOneRange-1) ) // horizontal cut on R34 (R34>-0.8)
221  hbhe.setFlagField(1, HcalCaloFlagLabels::HBHEOOTPU); // set to 1 if there is a pulse-shape-wise good OOTPU in TS3TS4.
222  }
223 
224  if(CheckPassFilter(mCharge[soi] + mCharge[soi+1], TS4TS5, mTS4TS5LowerCut, -1) == false && // TS4TS5 is below envelope
225  mCharge[soi-1] + mCharge[soi] < mTS3TS4UpperChargeThreshold && mTS3TS4UpperChargeThreshold>0 && // low charge in 34
226  mCharge[soi+1] + mCharge[soi+2] > mTS5TS6ChargeThreshold && mTS5TS6ChargeThreshold>0 && // enough charge in 56
227  fabs( (mCharge[soi] - mCharge[soi+1]) / (mCharge[soi] + mCharge[soi+1]) + 1.0 ) < mR45MinusOneRange ) // R45 is around -1
228  {
229  double TS5TS6 = (mCharge[soi+1] - mCharge[soi+2]) / (mCharge[soi+1] + mCharge[soi+2]);
230  if(CheckPassFilter(mCharge[soi+1] + mCharge[soi+2], TS5TS6, mTS4TS5UpperCut, 1) == true && // use the same envelope as TS4TS5
231  CheckPassFilter(mCharge[soi+1] + mCharge[soi+2], TS5TS6, mTS4TS5LowerCut, -1) == true && // use the same envelope as TS4TS5
232  TS5TS6<(1-mR45PlusOneRange) ) // horizontal cut on R56 (R56<+0.8)
233  hbhe.setFlagField(1, HcalCaloFlagLabels::HBHEOOTPU); // set to 1 if there is a pulse-shape-wise good OOTPU in TS5TS6.
234  }
235  }
236 }
237 
238 #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:42
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:38
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:154
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