CMS 3D CMS Logo

CastorSimpleRecAlgo.cc
Go to the documentation of this file.
5 #include <algorithm> // for "max"
6 #include <cmath>
7 
8 constexpr double MaximumFractionalError = 0.0005; // 0.05% error allowed from this source
9 
11  int firstSample, int samplesToAdd, bool correctForTimeslew, bool correctForPulse, float phaseNS)
12  : firstSample_(firstSample), samplesToAdd_(samplesToAdd), correctForTimeslew_(correctForTimeslew) {
13  if (correctForPulse)
14  pulseCorr_ = std::make_unique<CastorPulseContainmentCorrection>(samplesToAdd_, phaseNS, MaximumFractionalError);
15 }
16 
18  : firstSample_(firstSample), samplesToAdd_(samplesToAdd), correctForTimeslew_(false) {}
19 
25 //static float timeshift_ns_hbheho(float wpksamp);
26 
28 static float timeshift_ns_hf(float wpksamp);
29 
31  template <class Digi, class RecHit>
32  inline RecHit reco(const Digi& digi,
33  const CastorCoder& coder,
34  const CastorCalibrations& calibs,
35  int ifirst,
36  int n,
37  bool slewCorrect,
39  CastorTimeSlew::BiasSetting slewFlavor) {
40  CaloSamples tool;
41  coder.adc2fC(digi, tool);
42 
43  double ampl = 0;
44  int maxI = -1;
45  double maxA = -1e10;
46  float ta = 0;
47  double fc_ampl = 0;
48  for (int i = ifirst; i < tool.size() && i < n + ifirst; i++) {
49  int capid = digi[i].capid();
50  ta = (tool[i] - calibs.pedestal(capid)); // pedestal subtraction
51  fc_ampl += ta;
52  ta *= calibs.gain(capid); // fC --> GeV
53  ampl += ta;
54  if (ta > maxA) {
55  maxA = ta;
56  maxI = i;
57  }
58  }
59 
60  float time = -9999;
62  if (maxI == 0 || maxI == (tool.size() - 1)) {
63  // supress warning and use dummy time value for 2009 data
64  /*
65  edm::LogWarning("HCAL/CASTOR Pulse") << "CastorSimpleRecAlgo::reconstruct :"
66  << " Invalid max amplitude position, "
67  << " max Amplitude: "<< maxI
68  << " first: "<<ifirst
69  << " last: "<<(tool.size()-1)
70  << std::endl;
71  */
72  } else {
73  maxA = fabs(maxA);
74  int capid = digi[maxI - 1].capid();
75  float t0 = fabs((tool[maxI - 1] - calibs.pedestal(capid)) * calibs.gain(capid));
76  capid = digi[maxI + 1].capid();
77  float t2 = fabs((tool[maxI + 1] - calibs.pedestal(capid)) * calibs.gain(capid));
78  float wpksamp = (t0 + maxA + t2);
79  if (wpksamp != 0)
80  wpksamp = (maxA + 2.0 * t2) / wpksamp;
81  time = (maxI - digi.presamples()) * 25.0 + timeshift_ns_hf(wpksamp);
82 
83  if (corr != nullptr) {
84  // Apply phase-based amplitude correction:
85  ampl *= corr->getCorrection(fc_ampl);
86  // std::cout << fc_ampl << " --> " << corr->getCorrection(fc_ampl) << std::endl;
87  }
88 
89  if (slewCorrect)
90  time -= CastorTimeSlew::delay(std::max(1.0, fc_ampl), slewFlavor);
91  }
92  return RecHit(digi.id(), ampl, time);
93  }
94 
95  // returns TRUE if ADC count is >= maxADCvalue
96  template <class Digi>
97  inline bool isSaturated(const Digi& digi, const int& maxADCvalue, int ifirst, int n) {
98  for (int i = ifirst; i < digi.size() && i < n + ifirst; i++) {
99  if (digi[i].adc() >= maxADCvalue)
100  return true;
101  }
102 
103  return false;
104  }
105 
106  //++++ Saturation Correction +++++
107  // returns TRUE when saturation correction was done
108  template <class Digi, class RecHit>
109  inline bool corrSaturation(RecHit& rechit,
110  const CastorCoder& coder,
111  const CastorCalibrations& calibs,
112  const Digi& digi,
113  const int& maxADCvalue,
114  const double& satCorrConst,
115  int ifirst,
116  int n) {
117  // correction works only with 2 used TS
118  if (n != 2)
119  return false;
120 
121  // to avoid segmentation violation
122  if (ifirst + n > digi.size())
123  return false;
124 
125  // look if first TS is saturated not the second one
126  // in case the second one is saturated do no correction
127  if (digi[ifirst].adc() >= maxADCvalue && digi[ifirst + 1].adc() < maxADCvalue) {
128  float ampl = 0;
129 
130  CaloSamples tool;
131  coder.adc2fC(digi, tool);
132 
133  // get energy of first TS
134  int capid = digi[ifirst].capid();
135  float ta = tool[ifirst] - calibs.pedestal(capid); // pedestal subtraction
136  float ta1 = ta * calibs.gain(capid); // fC --> GeV
137 
138  // get energy of second TS
139  capid = digi[ifirst + 1].capid();
140  ta = tool[ifirst + 1] - calibs.pedestal(capid); // pedestal subtraction
141  float ta2 = ta * calibs.gain(capid); // fC --> GeV
142 
143  // use second TS to calc the first one
144  // check if recalculated TS ampl is
145  // realy greater than the saturated value
146  if (ta2 / satCorrConst <= ta1)
147  return false;
148 
149  // ampl = TS5 + TS4 => TS4 = TS5 / TSratio
150  // ampl = TS5 + TS5 / TSratio
151  ampl = ta2 + ta2 / satCorrConst;
152 
153  // reset energy of rechit
154  rechit.setEnergy(ampl);
155 
156  return true;
157  }
158 
159  return false;
160  }
161 } // namespace CastorSimpleRecAlgoImpl
162 
164  const CastorCoder& coder,
165  const CastorCalibrations& calibs) const {
166  return CastorSimpleRecAlgoImpl::reco<CastorDataFrame, CastorRecHit>(
167  digi, coder, calibs, firstSample_, samplesToAdd_, false, nullptr, CastorTimeSlew::Fast);
168 }
169 
171  const CastorDataFrame& digi,
172  const int& maxADCvalue) const {
173  if (CastorSimpleRecAlgoImpl::isSaturated<CastorDataFrame>(digi, maxADCvalue, firstSample_, samplesToAdd_))
175 }
176 
177 //++++ Saturation Correction +++++
179  const CastorCoder& coder,
180  const CastorCalibrations& calibs,
181  const CastorDataFrame& digi,
182  const int& maxADCvalue,
183  const double& satCorrConst) const {
184  if (CastorSimpleRecAlgoImpl::corrSaturation<CastorDataFrame, CastorRecHit>(
185  rechit, coder, calibs, digi, maxADCvalue, satCorrConst, firstSample_, samplesToAdd_))
186  // use empty flag bit for recording saturation correction
187  // see also CMSSW/DataFormats/METReco/interface/HcalCaloFlagLabels.h
189 }
190 
191 // timeshift implementation
192 
193 static const float wpksamp0_hf = 0.500635;
194 static const float scale_hf = 0.999301;
195 static const int num_bins_hf = 100;
196 
197 static const float actual_ns_hf[num_bins_hf] = {
198  0.00000, // 0.000-0.010
199  0.03750, // 0.010-0.020
200  0.07250, // 0.020-0.030
201  0.10750, // 0.030-0.040
202  0.14500, // 0.040-0.050
203  0.18000, // 0.050-0.060
204  0.21500, // 0.060-0.070
205  0.25000, // 0.070-0.080
206  0.28500, // 0.080-0.090
207  0.32000, // 0.090-0.100
208  0.35500, // 0.100-0.110
209  0.39000, // 0.110-0.120
210  0.42500, // 0.120-0.130
211  0.46000, // 0.130-0.140
212  0.49500, // 0.140-0.150
213  0.53000, // 0.150-0.160
214  0.56500, // 0.160-0.170
215  0.60000, // 0.170-0.180
216  0.63500, // 0.180-0.190
217  0.67000, // 0.190-0.200
218  0.70750, // 0.200-0.210
219  0.74250, // 0.210-0.220
220  0.78000, // 0.220-0.230
221  0.81500, // 0.230-0.240
222  0.85250, // 0.240-0.250
223  0.89000, // 0.250-0.260
224  0.92750, // 0.260-0.270
225  0.96500, // 0.270-0.280
226  1.00250, // 0.280-0.290
227  1.04250, // 0.290-0.300
228  1.08250, // 0.300-0.310
229  1.12250, // 0.310-0.320
230  1.16250, // 0.320-0.330
231  1.20500, // 0.330-0.340
232  1.24500, // 0.340-0.350
233  1.29000, // 0.350-0.360
234  1.33250, // 0.360-0.370
235  1.38000, // 0.370-0.380
236  1.42500, // 0.380-0.390
237  1.47500, // 0.390-0.400
238  1.52500, // 0.400-0.410
239  1.57750, // 0.410-0.420
240  1.63250, // 0.420-0.430
241  1.69000, // 0.430-0.440
242  1.75250, // 0.440-0.450
243  1.82000, // 0.450-0.460
244  1.89250, // 0.460-0.470
245  1.97500, // 0.470-0.480
246  2.07250, // 0.480-0.490
247  2.20000, // 0.490-0.500
248  19.13000, // 0.500-0.510
249  21.08750, // 0.510-0.520
250  21.57750, // 0.520-0.530
251  21.89000, // 0.530-0.540
252  22.12250, // 0.540-0.550
253  22.31000, // 0.550-0.560
254  22.47000, // 0.560-0.570
255  22.61000, // 0.570-0.580
256  22.73250, // 0.580-0.590
257  22.84500, // 0.590-0.600
258  22.94750, // 0.600-0.610
259  23.04250, // 0.610-0.620
260  23.13250, // 0.620-0.630
261  23.21500, // 0.630-0.640
262  23.29250, // 0.640-0.650
263  23.36750, // 0.650-0.660
264  23.43750, // 0.660-0.670
265  23.50500, // 0.670-0.680
266  23.57000, // 0.680-0.690
267  23.63250, // 0.690-0.700
268  23.69250, // 0.700-0.710
269  23.75000, // 0.710-0.720
270  23.80500, // 0.720-0.730
271  23.86000, // 0.730-0.740
272  23.91250, // 0.740-0.750
273  23.96500, // 0.750-0.760
274  24.01500, // 0.760-0.770
275  24.06500, // 0.770-0.780
276  24.11250, // 0.780-0.790
277  24.16000, // 0.790-0.800
278  24.20500, // 0.800-0.810
279  24.25000, // 0.810-0.820
280  24.29500, // 0.820-0.830
281  24.33750, // 0.830-0.840
282  24.38000, // 0.840-0.850
283  24.42250, // 0.850-0.860
284  24.46500, // 0.860-0.870
285  24.50500, // 0.870-0.880
286  24.54500, // 0.880-0.890
287  24.58500, // 0.890-0.900
288  24.62500, // 0.900-0.910
289  24.66500, // 0.910-0.920
290  24.70250, // 0.920-0.930
291  24.74000, // 0.930-0.940
292  24.77750, // 0.940-0.950
293  24.81500, // 0.950-0.960
294  24.85250, // 0.960-0.970
295  24.89000, // 0.970-0.980
296  24.92750, // 0.980-0.990
297  24.96250, // 0.990-1.000
298 };
299 
300 float timeshift_ns_hf(float wpksamp) {
301  float flx = (num_bins_hf * (wpksamp - wpksamp0_hf) / scale_hf);
302  int index = (int)flx;
303  float yval;
304 
305  if (index < 0)
306  return actual_ns_hf[0];
307  else if (index >= num_bins_hf - 1)
308  return actual_ns_hf[num_bins_hf - 1];
309 
310  // else interpolate:
311  float y1 = actual_ns_hf[index];
312  float y2 = actual_ns_hf[index + 1];
313 
314  // float delta_x = 1/(float)num_bins_hf;
315  // yval = y1 + (y2-y1)*(flx-(float)index)/delta_x;
316 
317  yval = y1 + (y2 - y1) * (flx - (float)index);
318  return yval;
319 }
static double delay(double fC, BiasSetting bias=Medium)
Returns the amount (ns) by which a pulse of the given number of fC will be delayed by the timeslew ef...
int size() const
get the size
Definition: CaloSamples.h:24
CastorSimpleRecAlgo(int firstSample, int samplesToAdd, bool correctForTimeslew, bool correctForContainment, float fixedPhaseNs)
void recoverADCSaturation(CastorRecHit &rechit, const CastorCoder &coder, const CastorCalibrations &calibs, const CastorDataFrame &digi, const int &maxADCvalue, const double &satCorrConst) const
double gain(int fCapId) const
get gain for capid=0..3
virtual void adc2fC(const CastorDataFrame &df, CaloSamples &lf) const =0
constexpr void setFlagField(uint32_t value, int base, int width=1)
Definition: CaloRecHit.h:36
bool corrSaturation(RecHit &rechit, const CastorCoder &coder, const CastorCalibrations &calibs, const Digi &digi, const int &maxADCvalue, const double &satCorrConst, int ifirst, int n)
std::unique_ptr< CastorPulseContainmentCorrection > pulseCorr_
static const float wpksamp0_hf
dictionary corr
static const float actual_ns_hf[num_bins_hf]
static const float scale_hf
double pedestal(int fCapId) const
get pedestal for capid=0..3
constexpr double MaximumFractionalError
static float timeshift_ns_hf(float wpksamp)
Same as above, but for the HF PMTs.
void checkADCSaturation(CastorRecHit &rechit, const CastorDataFrame &digi, const int &maxADCvalue) const
bool isSaturated(const Digi &digi, const int &maxADCvalue, int ifirst, int n)
static const int num_bins_hf
CastorRecHit reconstruct(const CastorDataFrame &digi, const CastorCoder &coder, const CastorCalibrations &calibs) const
RecHit reco(const Digi &digi, const CastorCoder &coder, const CastorCalibrations &calibs, int ifirst, int n, bool slewCorrect, const CastorPulseContainmentCorrection *corr, CastorTimeSlew::BiasSetting slewFlavor)
uint16_t *__restrict__ uint16_t const *__restrict__ adc