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