00001 #include "RecoLocalCalo/HcalRecAlgos/interface/HcalSimpleRecAlgo.h"
00002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00003 #include "CalibCalorimetry/HcalAlgos/interface/HcalTimeSlew.h"
00004 #include <algorithm>
00005 #include <math.h>
00006
00007 static double MaximumFractionalError = 0.0005;
00008
00009 HcalSimpleRecAlgo::HcalSimpleRecAlgo(int firstSample, int samplesToAdd, bool correctForTimeslew, bool correctForPulse, float phaseNS) :
00010 firstSample_(firstSample),
00011 samplesToAdd_(samplesToAdd),
00012 correctForTimeslew_(correctForTimeslew) {
00013 if (correctForPulse)
00014 pulseCorr_=std::auto_ptr<HcalPulseContainmentCorrection>(new HcalPulseContainmentCorrection(samplesToAdd_,phaseNS,MaximumFractionalError));
00015 }
00016
00017 HcalSimpleRecAlgo::HcalSimpleRecAlgo(int firstSample, int samplesToAdd) :
00018 firstSample_(firstSample),
00019 samplesToAdd_(samplesToAdd),
00020 correctForTimeslew_(false) {
00021 }
00022
00023
00024 void HcalSimpleRecAlgo::resetTimeSamples(int firstSample, int samplesToAdd)
00025 {
00026 firstSample_ = firstSample;
00027 samplesToAdd_ = samplesToAdd;
00028 }
00029
00030
00036 static float timeshift_ns_hbheho(float wpksamp);
00037
00039 static float timeshift_ns_hf(float wpksamp);
00040
00041
00042 namespace HcalSimpleRecAlgoImpl {
00043 template<class Digi, class RecHit>
00044 inline RecHit reco(const Digi& digi, const HcalCoder& coder, const HcalCalibrations& calibs,
00045 int ifirst, int n, bool slewCorrect, const HcalPulseContainmentCorrection* corr,
00046 HcalTimeSlew::BiasSetting slewFlavor) {
00047 CaloSamples tool;
00048 coder.adc2fC(digi,tool);
00049
00050 double ampl=0; int maxI = -1; double maxA = -1e10; float ta=0;
00051 double fc_ampl=0;
00052 for (int i=ifirst; i<tool.size() && i<n+ifirst; i++) {
00053 int capid=digi[i].capid();
00054 ta = (tool[i]-calibs.pedestal(capid));
00055 fc_ampl+=ta;
00056 ta*= calibs.respcorrgain(capid) ;
00057 ampl+=ta;
00058 if(ta>maxA){
00059 maxA=ta;
00060 maxI=i;
00061 }
00062 }
00063
00064 float time = -9999;
00066 if(maxI==0 || maxI==(tool.size()-1)) {
00067 LogDebug("HCAL Pulse") << "HcalSimpleRecAlgo::reconstruct :"
00068 << " Invalid max amplitude position, "
00069 << " max Amplitude: "<< maxI
00070 << " first: "<<ifirst
00071 << " last: "<<(tool.size()-1)
00072 << std::endl;
00073 } else {
00074 int capid=digi[maxI-1].capid();
00075 float t0 = ((tool[maxI-1]-calibs.pedestal(capid))*calibs.respcorrgain(capid) );
00076 capid=digi[maxI+1].capid();
00077 float t2 = ((tool[maxI+1]-calibs.pedestal(capid))*calibs.respcorrgain(capid) );
00078
00079
00080 float minA=t0;
00081 if (maxA<minA) minA=maxA;
00082 if (t2<minA) minA=t2;
00083 if (minA<0) { maxA-=minA; t0-=minA; t2-=minA; }
00084
00085 float wpksamp = (t0 + maxA + t2);
00086 if (wpksamp!=0) wpksamp=(maxA + 2.0*t2) / wpksamp;
00087 time = (maxI - digi.presamples())*25.0 + timeshift_ns_hbheho(wpksamp);
00088 if (corr!=0) {
00089
00090 ampl *= corr->getCorrection(fc_ampl);
00091
00092 }
00093 if (slewCorrect) time-=HcalTimeSlew::delay(std::max(1.0,fc_ampl),slewFlavor);
00094
00095 time=time-calibs.timecorr();
00096 }
00097
00098 return RecHit(digi.id(),ampl,time);
00099 }
00100 }
00101
00102 HBHERecHit HcalSimpleRecAlgo::reconstruct(const HBHEDataFrame& digi, const HcalCoder& coder, const HcalCalibrations& calibs) const {
00103 return HcalSimpleRecAlgoImpl::reco<HBHEDataFrame,HBHERecHit>(digi,coder,calibs,
00104 firstSample_,samplesToAdd_,correctForTimeslew_,
00105 pulseCorr_.get(),
00106 HcalTimeSlew::Medium);
00107 }
00108
00109 HORecHit HcalSimpleRecAlgo::reconstruct(const HODataFrame& digi, const HcalCoder& coder, const HcalCalibrations& calibs) const {
00110 return HcalSimpleRecAlgoImpl::reco<HODataFrame,HORecHit>(digi,coder,calibs,
00111 firstSample_,samplesToAdd_,correctForTimeslew_,
00112 pulseCorr_.get(),
00113 HcalTimeSlew::Slow);
00114 }
00115
00116 HcalCalibRecHit HcalSimpleRecAlgo::reconstruct(const HcalCalibDataFrame& digi, const HcalCoder& coder, const HcalCalibrations& calibs) const {
00117 return HcalSimpleRecAlgoImpl::reco<HcalCalibDataFrame,HcalCalibRecHit>(digi,coder,calibs,
00118 firstSample_,samplesToAdd_,correctForTimeslew_,
00119 pulseCorr_.get(),
00120 HcalTimeSlew::Fast);
00121 }
00122
00123 HFRecHit HcalSimpleRecAlgo::reconstruct(const HFDataFrame& digi, const HcalCoder& coder, const HcalCalibrations& calibs) const {
00124 CaloSamples tool;
00125 coder.adc2fC(digi,tool);
00126
00127 double ampl=0; int maxI = -1; double maxA = -1e10; float ta=0; float amp_fC=0;
00128 for (int i=firstSample_; i<tool.size() && i<samplesToAdd_+firstSample_; i++) {
00129 int capid=digi[i].capid();
00130 ta = (tool[i]-calibs.pedestal(capid))*calibs.respcorrgain(capid);
00131 ampl+=ta;
00132 amp_fC += tool[i]-calibs.pedestal(capid);
00133 if(ta>maxA){
00134 maxA=ta;
00135 maxI=i;
00136 }
00137 }
00138
00139 float time=-9999.0;
00141 if(maxI==0 || maxI==(tool.size()-1)) {
00142 LogDebug("HCAL Pulse") << "HcalSimpleRecAlgo::reconstruct :"
00143 << " Invalid max amplitude position, "
00144 << " max Amplitude: "<< maxI
00145 << " first: "<<firstSample_
00146 << " last: "<<(tool.size()-1)
00147 << std::endl;
00148 } else {
00149 int capid=digi[maxI-1].capid();
00150 float t0 = (tool[maxI-1]-calibs.pedestal(capid))*calibs.respcorrgain(capid);
00151 capid=digi[maxI+1].capid();
00152 float t2 = (tool[maxI+1]-calibs.pedestal(capid))*calibs.respcorrgain(capid);
00153
00154
00155 float zerocorr=std::min(t0,t2);
00156 if (zerocorr<0.f) {
00157 t0 -= zerocorr;
00158 t2 -= zerocorr;
00159 maxA -= zerocorr;
00160 }
00161
00162
00163 float wpksamp=0.f;
00164 if (t0>t2) {
00165 wpksamp = t0+maxA;
00166 if (wpksamp != 0.f) wpksamp = maxA/wpksamp;
00167 } else {
00168 wpksamp = maxA+t2;
00169 if (wpksamp != 0.f) wpksamp = 1.+(t2/wpksamp);
00170 }
00171
00172 time = (maxI - digi.presamples())*25.0 + timeshift_ns_hf(wpksamp);
00173
00174 if (correctForTimeslew_ && (amp_fC>0)) {
00175
00176 double tslew=exp(0.337681-5.94689e-4*amp_fC)+exp(2.44628-1.34888e-2*amp_fC);
00177 time -= (float)tslew;
00178 }
00179
00180 time=time-calibs.timecorr();
00181 }
00182
00183 return HFRecHit(digi.id(),ampl,time);
00184 }
00185
00186
00187
00188 static const float wpksamp0_hbheho = 0.5;
00189 static const int num_bins_hbheho = 61;
00190
00191 static const float actual_ns_hbheho[num_bins_hbheho] = {
00192 -5.44000,
00193 -4.84250,
00194 -4.26500,
00195 -3.71000,
00196 -3.18000,
00197 -2.66250,
00198 -2.17250,
00199 -1.69000,
00200 -1.23000,
00201 -0.78000,
00202 -0.34250,
00203 0.08250,
00204 0.50250,
00205 0.90500,
00206 1.30500,
00207 1.69500,
00208 2.07750,
00209 2.45750,
00210 2.82500,
00211 3.19250,
00212 3.55750,
00213 3.91750,
00214 4.27500,
00215 4.63000,
00216 4.98500,
00217 5.33750,
00218 5.69500,
00219 6.05000,
00220 6.40500,
00221 6.77000,
00222 7.13500,
00223 7.50000,
00224 7.88250,
00225 8.26500,
00226 8.66000,
00227 9.07000,
00228 9.48250,
00229 9.92750,
00230 10.37750,
00231 10.87500,
00232 11.38000,
00233 11.95250,
00234 12.55000,
00235 13.22750,
00236 13.98500,
00237 14.81500,
00238 15.71500,
00239 16.63750,
00240 17.53750,
00241 18.38500,
00242 19.16500,
00243 19.89750,
00244 20.59250,
00245 21.24250,
00246 21.85250,
00247 22.44500,
00248 22.99500,
00249 23.53250,
00250 24.03750,
00251 24.53250,
00252 25.00000
00253 };
00254
00255 float timeshift_ns_hbheho(float wpksamp) {
00256 float flx = (num_bins_hbheho-1)*(wpksamp - wpksamp0_hbheho);
00257 int index = (int)flx;
00258 float yval;
00259
00260 if (index < 0) return actual_ns_hbheho[0];
00261 else if (index >= num_bins_hbheho-1) return actual_ns_hbheho[num_bins_hbheho-1];
00262
00263
00264 float y1 = actual_ns_hbheho[index];
00265 float y2 = actual_ns_hbheho[index+1];
00266
00267 yval = y1 + (y2-y1)*(flx-(float)index);
00268
00269 return yval;
00270 }
00271
00272 static const int num_bins_hf = 101;
00273 static const float wpksamp0_hf = 0.5;
00274
00275 static const float actual_ns_hf[num_bins_hf] = {
00276 0.00250,
00277 0.04500,
00278 0.08750,
00279 0.13000,
00280 0.17250,
00281 0.21500,
00282 0.26000,
00283 0.30250,
00284 0.34500,
00285 0.38750,
00286 0.42750,
00287 0.46000,
00288 0.49250,
00289 0.52500,
00290 0.55750,
00291 0.59000,
00292 0.62250,
00293 0.65500,
00294 0.68750,
00295 0.72000,
00296 0.75250,
00297 0.78500,
00298 0.81750,
00299 0.85000,
00300 0.88250,
00301 0.91500,
00302 0.95500,
00303 0.99250,
00304 1.03250,
00305 1.07000,
00306 1.10750,
00307 1.14750,
00308 1.18500,
00309 1.22500,
00310 1.26250,
00311 1.30000,
00312 1.34000,
00313 1.37750,
00314 1.41750,
00315 1.48750,
00316 1.55750,
00317 1.62750,
00318 1.69750,
00319 1.76750,
00320 1.83750,
00321 1.90750,
00322 2.06750,
00323 2.23250,
00324 2.40000,
00325 2.82250,
00326 3.81000,
00327 6.90500,
00328 8.99250,
00329 10.50000,
00330 11.68250,
00331 12.66250,
00332 13.50250,
00333 14.23750,
00334 14.89750,
00335 15.49000,
00336 16.03250,
00337 16.53250,
00338 17.00000,
00339 17.44000,
00340 17.85250,
00341 18.24000,
00342 18.61000,
00343 18.96750,
00344 19.30500,
00345 19.63000,
00346 19.94500,
00347 20.24500,
00348 20.54000,
00349 20.82250,
00350 21.09750,
00351 21.37000,
00352 21.62750,
00353 21.88500,
00354 22.13000,
00355 22.37250,
00356 22.60250,
00357 22.83000,
00358 23.04250,
00359 23.24500,
00360 23.44250,
00361 23.61000,
00362 23.77750,
00363 23.93500,
00364 24.05500,
00365 24.17250,
00366 24.29000,
00367 24.40750,
00368 24.48250,
00369 24.55500,
00370 24.62500,
00371 24.69750,
00372 24.77000,
00373 24.84000,
00374 24.91250,
00375 24.95500,
00376 24.99750,
00377 };
00378
00379 float timeshift_ns_hf(float wpksamp) {
00380 float flx = (num_bins_hf-1)*(wpksamp-wpksamp0_hf);
00381 int index = (int)flx;
00382 float yval;
00383
00384 if (index < 0) return actual_ns_hf[0];
00385 else if (index >= num_bins_hf-1) return actual_ns_hf[num_bins_hf-1];
00386
00387
00388 float y1 = actual_ns_hf[index];
00389 float y2 = actual_ns_hf[index+1];
00390
00391
00392
00393
00394 yval = y1 + (y2-y1)*(flx-(float)index);
00395 return yval;
00396 }