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