CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/RecoLocalCalo/HcalRecAlgos/src/HcalSimpleRecAlgo.cc

Go to the documentation of this file.
00001 #include "RecoLocalCalo/HcalRecAlgos/interface/HcalSimpleRecAlgo.h"
00002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00003 #include "CalibCalorimetry/HcalAlgos/interface/HcalTimeSlew.h"
00004 #include <algorithm> // for "max"
00005 #include <math.h>
00006 //--- temporary for printouts
00007 #include<iostream>
00008 
00009 static double MaximumFractionalError = 0.0005; // 0.05% error allowed from this source
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)); // pedestal subtraction
00061       fc_ampl+=ta; 
00062       ta*= calibs.respcorrgain(capid) ; // fC --> GeV
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       // Handle negative excursions by moving "zero":
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; } // positivizes all samples
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         // Apply phase-based amplitude correction:
00096         ampl *= corr->getCorrection(fc_ampl);
00097         //      std::cout << fc_ampl << " --> " << corr->getCorrection(fc_ampl) << std::endl;
00098       }
00099       if (slewCorrect) time-=HcalTimeSlew::delay(std::max(1.0,fc_ampl),slewFlavor);
00100 
00101       time=time-calibs.timecorr(); // time calibration
00102     }
00103 
00104 
00105     // Temoprary hack to apply energy-dependent corrections to some HB- cells
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     // Correction for a leak to pre-sample
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     // Handle negative excursions by moving "zero":
00180     float zerocorr=std::min(t0,t2);
00181     if (zerocorr<0.f) {
00182       t0   -= zerocorr;
00183       t2   -= zerocorr;
00184       maxA -= zerocorr;
00185     }
00186     
00187     // pair the peak with the larger of the two neighboring time samples
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       // -5.12327 - put in calibs.timecorr()
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 // return energy correction factor for HBM channels 
00214 // iphi=6 ieta=(-1,-15) and iphi=32 ieta=(-1,-7)
00215 // I.Vodopianov 28 Feb. 2011
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   //  std::cout << "HBHE cell:  ieta, iphi = " << ieta << "  " << iphi 
00249   //        << "  ->  energy = " << en << "   corr = " << corr << std::endl;
00250 
00251   return corr;
00252 }
00253 
00254 
00255 // Actual leakage (to pre-sample) correction 
00256 float leakCorr(double energy) {
00257   double corr = 1.0;
00258   return corr;
00259 }
00260 
00261 
00262 // timeshift implementation
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, // 0.500, 0.000-0.017
00269 -4.84250, // 0.517, 0.017-0.033
00270 -4.26500, // 0.533, 0.033-0.050
00271 -3.71000, // 0.550, 0.050-0.067
00272 -3.18000, // 0.567, 0.067-0.083
00273 -2.66250, // 0.583, 0.083-0.100
00274 -2.17250, // 0.600, 0.100-0.117
00275 -1.69000, // 0.617, 0.117-0.133
00276 -1.23000, // 0.633, 0.133-0.150
00277 -0.78000, // 0.650, 0.150-0.167
00278 -0.34250, // 0.667, 0.167-0.183
00279  0.08250, // 0.683, 0.183-0.200
00280  0.50250, // 0.700, 0.200-0.217
00281  0.90500, // 0.717, 0.217-0.233
00282  1.30500, // 0.733, 0.233-0.250
00283  1.69500, // 0.750, 0.250-0.267
00284  2.07750, // 0.767, 0.267-0.283
00285  2.45750, // 0.783, 0.283-0.300
00286  2.82500, // 0.800, 0.300-0.317
00287  3.19250, // 0.817, 0.317-0.333
00288  3.55750, // 0.833, 0.333-0.350
00289  3.91750, // 0.850, 0.350-0.367
00290  4.27500, // 0.867, 0.367-0.383
00291  4.63000, // 0.883, 0.383-0.400
00292  4.98500, // 0.900, 0.400-0.417
00293  5.33750, // 0.917, 0.417-0.433
00294  5.69500, // 0.933, 0.433-0.450
00295  6.05000, // 0.950, 0.450-0.467
00296  6.40500, // 0.967, 0.467-0.483
00297  6.77000, // 0.983, 0.483-0.500
00298  7.13500, // 1.000, 0.500-0.517
00299  7.50000, // 1.017, 0.517-0.533
00300  7.88250, // 1.033, 0.533-0.550
00301  8.26500, // 1.050, 0.550-0.567
00302  8.66000, // 1.067, 0.567-0.583
00303  9.07000, // 1.083, 0.583-0.600
00304  9.48250, // 1.100, 0.600-0.617
00305  9.92750, // 1.117, 0.617-0.633
00306 10.37750, // 1.133, 0.633-0.650
00307 10.87500, // 1.150, 0.650-0.667
00308 11.38000, // 1.167, 0.667-0.683
00309 11.95250, // 1.183, 0.683-0.700
00310 12.55000, // 1.200, 0.700-0.717
00311 13.22750, // 1.217, 0.717-0.733
00312 13.98500, // 1.233, 0.733-0.750
00313 14.81500, // 1.250, 0.750-0.767
00314 15.71500, // 1.267, 0.767-0.783
00315 16.63750, // 1.283, 0.783-0.800
00316 17.53750, // 1.300, 0.800-0.817
00317 18.38500, // 1.317, 0.817-0.833
00318 19.16500, // 1.333, 0.833-0.850
00319 19.89750, // 1.350, 0.850-0.867
00320 20.59250, // 1.367, 0.867-0.883
00321 21.24250, // 1.383, 0.883-0.900
00322 21.85250, // 1.400, 0.900-0.917
00323 22.44500, // 1.417, 0.917-0.933
00324 22.99500, // 1.433, 0.933-0.950
00325 23.53250, // 1.450, 0.950-0.967
00326 24.03750, // 1.467, 0.967-0.983
00327 24.53250, // 1.483, 0.983-1.000
00328 25.00000  // 1.500, 1.000-1.017 - keep for interpolation
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   // else interpolate:
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, // 0.000-0.010
00353  0.04500, // 0.010-0.020
00354  0.08750, // 0.020-0.030
00355  0.13000, // 0.030-0.040
00356  0.17250, // 0.040-0.050
00357  0.21500, // 0.050-0.060
00358  0.26000, // 0.060-0.070
00359  0.30250, // 0.070-0.080
00360  0.34500, // 0.080-0.090
00361  0.38750, // 0.090-0.100
00362  0.42750, // 0.100-0.110
00363  0.46000, // 0.110-0.120
00364  0.49250, // 0.120-0.130
00365  0.52500, // 0.130-0.140
00366  0.55750, // 0.140-0.150
00367  0.59000, // 0.150-0.160
00368  0.62250, // 0.160-0.170
00369  0.65500, // 0.170-0.180
00370  0.68750, // 0.180-0.190
00371  0.72000, // 0.190-0.200
00372  0.75250, // 0.200-0.210
00373  0.78500, // 0.210-0.220
00374  0.81750, // 0.220-0.230
00375  0.85000, // 0.230-0.240
00376  0.88250, // 0.240-0.250
00377  0.91500, // 0.250-0.260
00378  0.95500, // 0.260-0.270
00379  0.99250, // 0.270-0.280
00380  1.03250, // 0.280-0.290
00381  1.07000, // 0.290-0.300
00382  1.10750, // 0.300-0.310
00383  1.14750, // 0.310-0.320
00384  1.18500, // 0.320-0.330
00385  1.22500, // 0.330-0.340
00386  1.26250, // 0.340-0.350
00387  1.30000, // 0.350-0.360
00388  1.34000, // 0.360-0.370
00389  1.37750, // 0.370-0.380
00390  1.41750, // 0.380-0.390
00391  1.48750, // 0.390-0.400
00392  1.55750, // 0.400-0.410
00393  1.62750, // 0.410-0.420
00394  1.69750, // 0.420-0.430
00395  1.76750, // 0.430-0.440
00396  1.83750, // 0.440-0.450
00397  1.90750, // 0.450-0.460
00398  2.06750, // 0.460-0.470
00399  2.23250, // 0.470-0.480
00400  2.40000, // 0.480-0.490
00401  2.82250, // 0.490-0.500
00402  3.81000, // 0.500-0.510
00403  6.90500, // 0.510-0.520
00404  8.99250, // 0.520-0.530
00405 10.50000, // 0.530-0.540
00406 11.68250, // 0.540-0.550
00407 12.66250, // 0.550-0.560
00408 13.50250, // 0.560-0.570
00409 14.23750, // 0.570-0.580
00410 14.89750, // 0.580-0.590
00411 15.49000, // 0.590-0.600
00412 16.03250, // 0.600-0.610
00413 16.53250, // 0.610-0.620
00414 17.00000, // 0.620-0.630
00415 17.44000, // 0.630-0.640
00416 17.85250, // 0.640-0.650
00417 18.24000, // 0.650-0.660
00418 18.61000, // 0.660-0.670
00419 18.96750, // 0.670-0.680
00420 19.30500, // 0.680-0.690
00421 19.63000, // 0.690-0.700
00422 19.94500, // 0.700-0.710
00423 20.24500, // 0.710-0.720
00424 20.54000, // 0.720-0.730
00425 20.82250, // 0.730-0.740
00426 21.09750, // 0.740-0.750
00427 21.37000, // 0.750-0.760
00428 21.62750, // 0.760-0.770
00429 21.88500, // 0.770-0.780
00430 22.13000, // 0.780-0.790
00431 22.37250, // 0.790-0.800
00432 22.60250, // 0.800-0.810
00433 22.83000, // 0.810-0.820
00434 23.04250, // 0.820-0.830
00435 23.24500, // 0.830-0.840
00436 23.44250, // 0.840-0.850
00437 23.61000, // 0.850-0.860
00438 23.77750, // 0.860-0.870
00439 23.93500, // 0.870-0.880
00440 24.05500, // 0.880-0.890
00441 24.17250, // 0.890-0.900
00442 24.29000, // 0.900-0.910
00443 24.40750, // 0.910-0.920
00444 24.48250, // 0.920-0.930
00445 24.55500, // 0.930-0.940
00446 24.62500, // 0.940-0.950
00447 24.69750, // 0.950-0.960
00448 24.77000, // 0.960-0.970
00449 24.84000, // 0.970-0.980
00450 24.91250, // 0.980-0.990
00451 24.95500, // 0.990-1.000
00452 24.99750, // 1.000-1.010 - keep for interpolation
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   // else interpolate:
00464   float y1       = actual_ns_hf[index];
00465   float y2       = actual_ns_hf[index+1];
00466 
00467   // float delta_x  = 1/(float)num_bins_hf;
00468   // yval = y1 + (y2-y1)*(flx-(float)index)/delta_x;
00469 
00470   yval = y1 + (y2-y1)*(flx-(float)index);
00471   return yval;
00472 }