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