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