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 #include<iostream>
00008
00009 static double MaximumFractionalError = 0.0005;
00010
00011 HcalSimpleRecAlgo::HcalSimpleRecAlgo(bool correctForTimeslew, bool correctForPulse, float phaseNS) :
00012 correctForTimeslew_(correctForTimeslew),
00013 correctForPulse_(correctForPulse),
00014 phaseNS_(phaseNS), setForData_(false), setLeakCorrection_(false) { }
00015
00016
00017 HcalSimpleRecAlgo::HcalSimpleRecAlgo() :
00018 correctForTimeslew_(false), setForData_(false) { }
00019
00020 void HcalSimpleRecAlgo::initPulseCorr(int toadd) {
00021 if (correctForPulse_) {
00022 if (pulseCorr_[toadd].get()==0) {
00023 pulseCorr_[toadd]=std::auto_ptr<HcalPulseContainmentCorrection>(new HcalPulseContainmentCorrection(toadd,phaseNS_,MaximumFractionalError));
00024 }
00025 }
00026 }
00027
00028 void HcalSimpleRecAlgo::setForData () { setForData_ = true;}
00029
00030 void HcalSimpleRecAlgo::setLeakCorrection () { setLeakCorrection_ = true;}
00031
00037 static float timeshift_ns_hbheho(float wpksamp);
00038
00040 static float timeshift_ns_hf(float wpksamp);
00041
00043 static float eCorr(int ieta, int iphi, double ampl);
00044
00046 static float leakCorr(double energy);
00047
00048 namespace HcalSimpleRecAlgoImpl {
00049 template<class Digi, class RecHit>
00050 inline RecHit reco(const Digi& digi, const HcalCoder& coder, const HcalCalibrations& calibs,
00051 int ifirst, int n, bool slewCorrect, const HcalPulseContainmentCorrection* corr,
00052 HcalTimeSlew::BiasSetting slewFlavor, bool forData, bool useLeak) {
00053 CaloSamples tool;
00054 coder.adc2fC(digi,tool);
00055
00056 double ampl=0; int maxI = -1; double maxA = -1e10; float ta=0;
00057 double fc_ampl=0;
00058 for (int i=ifirst; i<tool.size() && i<n+ifirst; i++) {
00059 int capid=digi[i].capid();
00060 ta = (tool[i]-calibs.pedestal(capid));
00061 fc_ampl+=ta;
00062 ta*= calibs.respcorrgain(capid) ;
00063 ampl+=ta;
00064 if(ta>maxA){
00065 maxA=ta;
00066 maxI=i;
00067 }
00068 }
00069
00070 float time = -9999;
00072 if(maxI==0 || maxI==(tool.size()-1)) {
00073 LogDebug("HCAL Pulse") << "HcalSimpleRecAlgo::reconstruct :"
00074 << " Invalid max amplitude position, "
00075 << " max Amplitude: "<< maxI
00076 << " first: "<<ifirst
00077 << " last: "<<(tool.size()-1)
00078 << std::endl;
00079 } else {
00080 int capid=digi[maxI-1].capid();
00081 float t0 = ((tool[maxI-1]-calibs.pedestal(capid))*calibs.respcorrgain(capid) );
00082 capid=digi[maxI+1].capid();
00083 float t2 = ((tool[maxI+1]-calibs.pedestal(capid))*calibs.respcorrgain(capid) );
00084
00085
00086 float minA=t0;
00087 if (maxA<minA) minA=maxA;
00088 if (t2<minA) minA=t2;
00089 if (minA<0) { maxA-=minA; t0-=minA; t2-=minA; }
00090
00091 float wpksamp = (t0 + maxA + t2);
00092 if (wpksamp!=0) wpksamp=(maxA + 2.0*t2) / wpksamp;
00093 time = (maxI - digi.presamples())*25.0 + timeshift_ns_hbheho(wpksamp);
00094 if (corr!=0) {
00095
00096 ampl *= corr->getCorrection(fc_ampl);
00097
00098 }
00099 if (slewCorrect) time-=HcalTimeSlew::delay(std::max(1.0,fc_ampl),slewFlavor);
00100
00101 time=time-calibs.timecorr();
00102 }
00103
00104
00105
00106 if(forData) {
00107 HcalDetId cell(digi.id());
00108 int ieta = cell.ieta();
00109 int iphi = cell.iphi();
00110 ampl *= eCorr(ieta,iphi,ampl);
00111 }
00112
00113
00114 if(useLeak) {
00115 ampl *= leakCorr(ampl);
00116 }
00117
00118
00119 return RecHit(digi.id(),ampl,time);
00120 }
00121 }
00122
00123 HBHERecHit HcalSimpleRecAlgo::reconstruct(const HBHEDataFrame& digi, int first, int toadd, const HcalCoder& coder, const HcalCalibrations& calibs) const {
00124 return HcalSimpleRecAlgoImpl::reco<HBHEDataFrame,HBHERecHit>(digi,coder,calibs,
00125 first,toadd,correctForTimeslew_,
00126 pulseCorr_[toadd].get(),
00127 HcalTimeSlew::Medium,
00128 setForData_, setLeakCorrection_);
00129 }
00130
00131 HORecHit HcalSimpleRecAlgo::reconstruct(const HODataFrame& digi, int first, int toadd, const HcalCoder& coder, const HcalCalibrations& calibs) const {
00132 return HcalSimpleRecAlgoImpl::reco<HODataFrame,HORecHit>(digi,coder,calibs,
00133 first,toadd,
00134 correctForTimeslew_,
00135 pulseCorr_[toadd].get(),
00136 HcalTimeSlew::Slow,
00137 setForData_, false);
00138 }
00139
00140 HcalCalibRecHit HcalSimpleRecAlgo::reconstruct(const HcalCalibDataFrame& digi, int first, int toadd, const HcalCoder& coder, const HcalCalibrations& calibs) const {
00141 return HcalSimpleRecAlgoImpl::reco<HcalCalibDataFrame,HcalCalibRecHit>(digi,coder,calibs,
00142 first,toadd,correctForTimeslew_,
00143 pulseCorr_[toadd].get(),
00144 HcalTimeSlew::Fast,
00145 setForData_, false );
00146 }
00147
00148 HFRecHit HcalSimpleRecAlgo::reconstruct(const HFDataFrame& digi, int first, int toadd, const HcalCoder& coder, const HcalCalibrations& calibs) const {
00149 CaloSamples tool;
00150 coder.adc2fC(digi,tool);
00151
00152 double ampl=0; int maxI = -1; double maxA = -1e10; float ta=0; float amp_fC=0;
00153 for (int i=first; i<tool.size() && i<first+toadd; i++) {
00154 int capid=digi[i].capid();
00155 ta = (tool[i]-calibs.pedestal(capid))*calibs.respcorrgain(capid);
00156 ampl+=ta;
00157 amp_fC += tool[i]-calibs.pedestal(capid);
00158 if(ta>maxA){
00159 maxA=ta;
00160 maxI=i;
00161 }
00162 }
00163
00164 float time=-9999.0;
00166 if(maxI==0 || maxI==(tool.size()-1)) {
00167 LogDebug("HCAL Pulse") << "HcalSimpleRecAlgo::reconstruct :"
00168 << " Invalid max amplitude position, "
00169 << " max Amplitude: "<< maxI
00170 << " first: "<< first
00171 << " last: "<<(tool.size()-1)
00172 << std::endl;
00173 } else {
00174 int capid=digi[maxI-1].capid();
00175 float t0 = (tool[maxI-1]-calibs.pedestal(capid))*calibs.respcorrgain(capid);
00176 capid=digi[maxI+1].capid();
00177 float t2 = (tool[maxI+1]-calibs.pedestal(capid))*calibs.respcorrgain(capid);
00178
00179
00180 float zerocorr=std::min(t0,t2);
00181 if (zerocorr<0.f) {
00182 t0 -= zerocorr;
00183 t2 -= zerocorr;
00184 maxA -= zerocorr;
00185 }
00186
00187
00188 float wpksamp=0.f;
00189 if (t0>t2) {
00190 wpksamp = t0+maxA;
00191 if (wpksamp != 0.f) wpksamp = maxA/wpksamp;
00192 } else {
00193 wpksamp = maxA+t2;
00194 if (wpksamp != 0.f) wpksamp = 1.+(t2/wpksamp);
00195 }
00196
00197 time = (maxI - digi.presamples())*25.0 + timeshift_ns_hf(wpksamp);
00198
00199 if (correctForTimeslew_ && (amp_fC>0)) {
00200
00201 double tslew=exp(0.337681-5.94689e-4*amp_fC)+exp(2.44628-1.34888e-2*amp_fC);
00202 time -= (float)tslew;
00203 }
00204
00205 time=time-calibs.timecorr();
00206 }
00207
00208 return HFRecHit(digi.id(),ampl,time);
00209 }
00210
00212 float eCorr(int ieta, int iphi, double energy) {
00213
00214
00215
00216 static const float low32[7] = {0.741,0.721,0.730,0.698,0.708,0.751,0.861};
00217 static const float high32[7] = {0.973,0.925,0.900,0.897,0.950,0.935,1};
00218 static const float low6[15] = {0.635,0.623,0.670,0.633,0.644,0.648,0.600,
00219 0.570,0.595,0.554,0.505,0.513,0.515,0.561,0.579};
00220 static const float high6[15] = {0.875,0.937,0.942,0.900,0.922,0.925,0.901,
00221 0.850,0.852,0.818,0.731,0.717,0.782,0.853,0.778};
00222
00223
00224 double slope, mid, en;
00225 double corr = 1.0;
00226
00227 if (!(iphi==6 && ieta<0 && ieta>-16) && !(iphi==32 && ieta<0 && ieta>-8))
00228 return corr;
00229
00230 int jeta = -ieta-1;
00231 double xeta = (double) ieta;
00232 if (energy > 0.) en=energy;
00233 else en = 0.;
00234
00235 if (iphi == 32) {
00236 slope = 0.2272;
00237 mid = 17.14 + 0.7147*xeta;
00238 if (en > 100.) corr = high32[jeta];
00239 else corr = low32[jeta]+(high32[jeta]-low32[jeta])/(1.0+exp(-(en-mid)*slope));
00240 }
00241 else if (iphi == 6) {
00242 slope = 0.1956;
00243 mid = 15.96 + 0.3075*xeta;
00244 if (en > 100.0) corr = high6[jeta];
00245 else corr = low6[jeta]+(high6[jeta]-low6[jeta])/(1.0+exp(-(en-mid)*slope));
00246 }
00247
00248
00249
00250
00251 return corr;
00252 }
00253
00254
00255
00256 float leakCorr(double energy) {
00257 double corr = 1.0;
00258 return corr;
00259 }
00260
00261
00262
00263
00264 static const float wpksamp0_hbheho = 0.5;
00265 static const int num_bins_hbheho = 61;
00266
00267 static const float actual_ns_hbheho[num_bins_hbheho] = {
00268 -5.44000,
00269 -4.84250,
00270 -4.26500,
00271 -3.71000,
00272 -3.18000,
00273 -2.66250,
00274 -2.17250,
00275 -1.69000,
00276 -1.23000,
00277 -0.78000,
00278 -0.34250,
00279 0.08250,
00280 0.50250,
00281 0.90500,
00282 1.30500,
00283 1.69500,
00284 2.07750,
00285 2.45750,
00286 2.82500,
00287 3.19250,
00288 3.55750,
00289 3.91750,
00290 4.27500,
00291 4.63000,
00292 4.98500,
00293 5.33750,
00294 5.69500,
00295 6.05000,
00296 6.40500,
00297 6.77000,
00298 7.13500,
00299 7.50000,
00300 7.88250,
00301 8.26500,
00302 8.66000,
00303 9.07000,
00304 9.48250,
00305 9.92750,
00306 10.37750,
00307 10.87500,
00308 11.38000,
00309 11.95250,
00310 12.55000,
00311 13.22750,
00312 13.98500,
00313 14.81500,
00314 15.71500,
00315 16.63750,
00316 17.53750,
00317 18.38500,
00318 19.16500,
00319 19.89750,
00320 20.59250,
00321 21.24250,
00322 21.85250,
00323 22.44500,
00324 22.99500,
00325 23.53250,
00326 24.03750,
00327 24.53250,
00328 25.00000
00329 };
00330
00331 float timeshift_ns_hbheho(float wpksamp) {
00332 float flx = (num_bins_hbheho-1)*(wpksamp - wpksamp0_hbheho);
00333 int index = (int)flx;
00334 float yval;
00335
00336 if (index < 0) return actual_ns_hbheho[0];
00337 else if (index >= num_bins_hbheho-1) return actual_ns_hbheho[num_bins_hbheho-1];
00338
00339
00340 float y1 = actual_ns_hbheho[index];
00341 float y2 = actual_ns_hbheho[index+1];
00342
00343 yval = y1 + (y2-y1)*(flx-(float)index);
00344
00345 return yval;
00346 }
00347
00348 static const int num_bins_hf = 101;
00349 static const float wpksamp0_hf = 0.5;
00350
00351 static const float actual_ns_hf[num_bins_hf] = {
00352 0.00250,
00353 0.04500,
00354 0.08750,
00355 0.13000,
00356 0.17250,
00357 0.21500,
00358 0.26000,
00359 0.30250,
00360 0.34500,
00361 0.38750,
00362 0.42750,
00363 0.46000,
00364 0.49250,
00365 0.52500,
00366 0.55750,
00367 0.59000,
00368 0.62250,
00369 0.65500,
00370 0.68750,
00371 0.72000,
00372 0.75250,
00373 0.78500,
00374 0.81750,
00375 0.85000,
00376 0.88250,
00377 0.91500,
00378 0.95500,
00379 0.99250,
00380 1.03250,
00381 1.07000,
00382 1.10750,
00383 1.14750,
00384 1.18500,
00385 1.22500,
00386 1.26250,
00387 1.30000,
00388 1.34000,
00389 1.37750,
00390 1.41750,
00391 1.48750,
00392 1.55750,
00393 1.62750,
00394 1.69750,
00395 1.76750,
00396 1.83750,
00397 1.90750,
00398 2.06750,
00399 2.23250,
00400 2.40000,
00401 2.82250,
00402 3.81000,
00403 6.90500,
00404 8.99250,
00405 10.50000,
00406 11.68250,
00407 12.66250,
00408 13.50250,
00409 14.23750,
00410 14.89750,
00411 15.49000,
00412 16.03250,
00413 16.53250,
00414 17.00000,
00415 17.44000,
00416 17.85250,
00417 18.24000,
00418 18.61000,
00419 18.96750,
00420 19.30500,
00421 19.63000,
00422 19.94500,
00423 20.24500,
00424 20.54000,
00425 20.82250,
00426 21.09750,
00427 21.37000,
00428 21.62750,
00429 21.88500,
00430 22.13000,
00431 22.37250,
00432 22.60250,
00433 22.83000,
00434 23.04250,
00435 23.24500,
00436 23.44250,
00437 23.61000,
00438 23.77750,
00439 23.93500,
00440 24.05500,
00441 24.17250,
00442 24.29000,
00443 24.40750,
00444 24.48250,
00445 24.55500,
00446 24.62500,
00447 24.69750,
00448 24.77000,
00449 24.84000,
00450 24.91250,
00451 24.95500,
00452 24.99750,
00453 };
00454
00455 float timeshift_ns_hf(float wpksamp) {
00456 float flx = (num_bins_hf-1)*(wpksamp-wpksamp0_hf);
00457 int index = (int)flx;
00458 float yval;
00459
00460 if (index < 0) return actual_ns_hf[0];
00461 else if (index >= num_bins_hf-1) return actual_ns_hf[num_bins_hf-1];
00462
00463
00464 float y1 = actual_ns_hf[index];
00465 float y2 = actual_ns_hf[index+1];
00466
00467
00468
00469
00470 yval = y1 + (y2-y1)*(flx-(float)index);
00471 return yval;
00472 }