CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/src/RecoLocalCalo/HcalRecAlgos/src/ZdcSimpleRecAlgo.cc

Go to the documentation of this file.
00001 #include "RecoLocalCalo/HcalRecAlgos/interface/ZdcSimpleRecAlgo.h"
00002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00003 #include "CalibCalorimetry/HcalAlgos/interface/HcalTimeSlew.h"
00004 #include <algorithm> // for "max"
00005 #include <iostream>
00006 #include <math.h>
00007 
00008 
00009 
00010 static double MaximumFractionalError = 0.0005; // 0.05% error allowed from this source
00011 
00012 ZdcSimpleRecAlgo::ZdcSimpleRecAlgo(bool correctForTimeslew, bool correctForPulse, float phaseNS, int recoMethod, int lowGainOffset, double lowGainFrac) : 
00013   recoMethod_(recoMethod),
00014   correctForTimeslew_(correctForTimeslew),
00015   correctForPulse_(correctForPulse),
00016   lowGainOffset_(lowGainOffset),
00017   lowGainFrac_(lowGainFrac)
00018   {
00019 }
00020 
00021 ZdcSimpleRecAlgo::ZdcSimpleRecAlgo(int recoMethod) : 
00022   recoMethod_(recoMethod),
00023   correctForTimeslew_(false) {
00024 }
00025 void ZdcSimpleRecAlgo::initPulseCorr(int toadd) {
00026   if (correctForPulse_) {    
00027     pulseCorr_=std::auto_ptr<HcalPulseContainmentCorrection>(new HcalPulseContainmentCorrection(toadd,phaseNS_,MaximumFractionalError));
00028   }
00029 }
00030 //static float timeshift_ns_zdc(float wpksamp);
00031 
00032 namespace ZdcSimpleRecAlgoImpl {
00033   template<class Digi, class RecHit>
00034   inline RecHit reco1(const Digi& digi, const HcalCoder& coder, const HcalCalibrations& calibs, 
00035                       const std::vector<unsigned int>& myNoiseTS, const std::vector<unsigned int>& mySignalTS, int lowGainOffset, double lowGainFrac, bool slewCorrect, const HcalPulseContainmentCorrection* corr, HcalTimeSlew::BiasSetting slewFlavor) {
00036     CaloSamples tool;
00037     coder.adc2fC(digi,tool);
00038     int ifirst = mySignalTS[0];
00039     int n = mySignalTS.size();
00040     double ampl=0; int maxI = -1; double maxA = -1e10; double ta=0;
00041     double fc_ampl=0;
00042     double lowGEnergy=0; double lowGfc_ampl=0; double TempLGAmp=0;
00043 // TS increment for regular energy to lowGainEnergy      
00044 // Signal in higher TS (effective "low Gain") has a fraction of the whole signal
00045 // This constant for fC --> GeV is dervied from 2010 PbPb analysis of single neutrons
00046 // assumed similar fraction for EM and HAD sections
00047 // this variable converts from current assumed TestBeam values for fC--> GeV
00048 // to the lowGain TS region fraction value (based on 1N Had, assume EM same response)
00049 // regular energy    
00050     for (int i=ifirst; i<tool.size() && i<n+ifirst; i++) {
00051       int capid=digi[i].capid();
00052       ta = (tool[i]-calibs.pedestal(capid)); // pedestal subtraction
00053       fc_ampl+=ta; 
00054       ta*= calibs.respcorrgain(capid) ; // fC --> GeV
00055       ampl+=ta;
00056       if(ta>maxA){
00057         maxA=ta;
00058         maxI=i;
00059       }
00060     }
00061 // calculate low Gain Energy (in 2010 PbPb, signal TS 4,5,6, lowGain TS: 6,7,8) 
00062     int topLowGain=10;
00063     if((n+ifirst+lowGainOffset)<=10){
00064       topLowGain=n+ifirst+lowGainOffset;
00065     } else {
00066       topLowGain=10;
00067     }
00068     for (int iLG=(ifirst+lowGainOffset); iLG<tool.size() && iLG<topLowGain; iLG++) {
00069       int capid=digi[iLG].capid();
00070       TempLGAmp = (tool[iLG]-calibs.pedestal(capid)); // pedestal subtraction
00071       lowGfc_ampl+=TempLGAmp; 
00072       TempLGAmp*= calibs.respcorrgain(capid) ; // fC --> GeV
00073       TempLGAmp*= lowGainFrac ; // TS (signalRegion) --> TS (lowGainRegion)
00074       lowGEnergy+=TempLGAmp;
00075     }    
00076     double time=-9999;
00077     // Time based on regular energy (lowGainEnergy signal assumed to happen at same Time)
00079     if(maxI==0 || maxI==(tool.size()-1)) {      
00080       LogDebug("HCAL Pulse") << "ZdcSimpleRecAlgo::reco2 :" 
00081                                                << " Invalid max amplitude position, " 
00082                                                << " max Amplitude: "<< maxI
00083                                                << " first: "<<ifirst
00084                                                << " last: "<<(tool.size()-1)
00085                                                << std::endl;
00086     } else {
00087       int capid=digi[maxI-1].capid();
00088       double Energy0 = ((tool[maxI-1])*calibs.respcorrgain(capid) );
00089 // if any of the energies used in the weight are negative, make them 0 instead
00090 // these are actually QIE values, not energy
00091       if(Energy0<0){Energy0=0.;}
00092       capid=digi[maxI].capid();
00093       double Energy1 = ((tool[maxI])*calibs.respcorrgain(capid) ) ;
00094       if(Energy1<0){Energy1=0.;}
00095       capid=digi[maxI+1].capid();
00096       double Energy2 = ((tool[maxI+1])*calibs.respcorrgain(capid) );
00097       if(Energy2<0){Energy2=0.;}
00098 //
00099       double TSWeightEnergy = ((maxI-1)*Energy0 + maxI*Energy1 + (maxI+1)*Energy2);
00100       double EnergySum=Energy0+Energy1+Energy2;
00101       double AvgTSPos=0.;
00102       if (EnergySum!=0) AvgTSPos=TSWeightEnergy/ EnergySum; 
00103 // If time is zero, set it to the "nonsensical" -99
00104 // Time should be between 75ns and 175ns (Timeslices 3-7)
00105       if(AvgTSPos==0){
00106          time=-99;
00107       } else {
00108          time = (AvgTSPos*25.0);
00109       }
00110       if (corr!=0) {
00111         // Apply phase-based amplitude correction:
00112                ampl *= corr->getCorrection(fc_ampl);     
00113       }
00114     }
00115     return RecHit(digi.id(),ampl,time,lowGEnergy);    
00116   }
00117 }
00118 
00119 namespace ZdcSimpleRecAlgoImpl {
00120   template<class Digi, class RecHit>
00121   inline RecHit reco2(const Digi& digi, const HcalCoder& coder, const HcalCalibrations& calibs, 
00122                      const std::vector<unsigned int>& myNoiseTS, const std::vector<unsigned int>& mySignalTS, int lowGainOffset, double lowGainFrac, bool slewCorrect, const HcalPulseContainmentCorrection* corr, HcalTimeSlew::BiasSetting slewFlavor) {
00123     CaloSamples tool;
00124     coder.adc2fC(digi,tool);
00125     // Reads noiseTS and signalTS from database
00126     int ifirst = mySignalTS[0];
00127 //    int n = mySignalTS.size();
00128     double ampl=0; int maxI = -1; double maxA = -1e10; double ta=0;
00129     double fc_ampl=0;
00130     double lowGEnergy=0; double lowGfc_ampl=0; double TempLGAmp=0;
00131 //  TS increment for regular energy to lowGainEnergy      
00132 // Signal in higher TS (effective "low Gain") has a fraction of the whole signal
00133 // This constant for fC --> GeV is dervied from 2010 PbPb analysis of single neutrons
00134 // assumed similar fraction for EM and HAD sections
00135 // this variable converts from current assumed TestBeam values for fC--> GeV
00136 // to the lowGain TS region fraction value (based on 1N Had, assume EM same response)
00137     double Allnoise = 0; 
00138     int noiseslices = 0;
00139     int CurrentTS = 0;
00140     double noise = 0;
00141 // regular energy (both use same noise)    
00142     for(unsigned int iv = 0; iv<myNoiseTS.size(); ++iv)
00143     {
00144       CurrentTS = myNoiseTS[iv];
00145       Allnoise += tool[CurrentTS];
00146       noiseslices++;
00147     }
00148     if(noiseslices != 0) {
00149       noise = (Allnoise)/double(noiseslices);
00150     } else {
00151       noise = 0;
00152     }
00153     for(unsigned int ivs = 0; ivs<mySignalTS.size(); ++ivs)
00154     {
00155       CurrentTS = mySignalTS[ivs];
00156       int capid=digi[CurrentTS].capid();
00157 //       if(noise<0){
00158 //       // flag hit as having negative noise, and don't subtract anything, because
00159 //       // it will falsely increase the energy
00160 //          noisefactor=0.;
00161 //       } 
00162       ta = tool[CurrentTS]-noise;
00163       fc_ampl+=ta; 
00164       ta*= calibs.respcorrgain(capid) ; // fC --> GeV
00165       ampl+=ta;
00166       if(ta>maxA){
00167              maxA=ta;
00168              maxI=CurrentTS;
00169           }
00170     }   
00171 // calculate low Gain Energy (in 2010 PbPb, signal TS 4,5,6, lowGain TS: 6,7,8)    
00172     for(unsigned int iLGvs = 0; iLGvs<mySignalTS.size(); ++iLGvs)
00173     {
00174       CurrentTS = mySignalTS[iLGvs]+lowGainOffset;
00175       int capid=digi[CurrentTS].capid();
00176       TempLGAmp = tool[CurrentTS]-noise;
00177       lowGfc_ampl+=TempLGAmp; 
00178       TempLGAmp*= calibs.respcorrgain(capid) ; // fC --> GeV
00179       TempLGAmp*= lowGainFrac ; // TS (signalRegion) --> TS (lowGainRegion)
00180       lowGEnergy+=TempLGAmp;
00181     }      
00182 //    if(ta<0){
00183 //      // flag hits that have negative energy
00184 //    }
00185 
00186     double time=-9999;
00187     // Time based on regular energy (lowGainEnergy signal assumed to happen at same Time)
00189     if(maxI==0 || maxI==(tool.size()-1)) {      
00190       LogDebug("HCAL Pulse") << "ZdcSimpleRecAlgo::reco2 :" 
00191                                                << " Invalid max amplitude position, " 
00192                                                << " max Amplitude: "<< maxI
00193                                                << " first: "<<ifirst
00194                                                << " last: "<<(tool.size()-1)
00195                                                << std::endl;
00196     } else {
00197       int capid=digi[maxI-1].capid();
00198       double Energy0 = ((tool[maxI-1])*calibs.respcorrgain(capid) );
00199 // if any of the energies used in the weight are negative, make them 0 instead
00200 // these are actually QIE values, not energy
00201       if(Energy0<0){Energy0=0.;}
00202       capid=digi[maxI].capid();
00203       double Energy1 = ((tool[maxI])*calibs.respcorrgain(capid) ) ;
00204       if(Energy1<0){Energy1=0.;}
00205       capid=digi[maxI+1].capid();
00206       double Energy2 = ((tool[maxI+1])*calibs.respcorrgain(capid) );
00207       if(Energy2<0){Energy2=0.;}
00208 //
00209       double TSWeightEnergy = ((maxI-1)*Energy0 + maxI*Energy1 + (maxI+1)*Energy2);
00210       double EnergySum=Energy0+Energy1+Energy2;
00211       double AvgTSPos=0.;
00212       if (EnergySum!=0) AvgTSPos=TSWeightEnergy/ EnergySum; 
00213 // If time is zero, set it to the "nonsensical" -99
00214 // Time should be between 75ns and 175ns (Timeslices 3-7)
00215       if(AvgTSPos==0){
00216          time=-99;
00217       } else {
00218          time = (AvgTSPos*25.0);
00219       }
00220       if (corr!=0) {
00221         // Apply phase-based amplitude correction:
00222                ampl *= corr->getCorrection(fc_ampl);     
00223       }
00224     }
00225     return RecHit(digi.id(),ampl,time,lowGEnergy);    
00226   }
00227 }
00228 
00229 ZDCRecHit ZdcSimpleRecAlgo::reconstruct(const ZDCDataFrame& digi, const std::vector<unsigned int>& myNoiseTS, const std::vector<unsigned int>& mySignalTS, const HcalCoder& coder, const HcalCalibrations& calibs) const {
00230 
00231   if(recoMethod_ == 1)
00232    return ZdcSimpleRecAlgoImpl::reco1<ZDCDataFrame,ZDCRecHit>(digi,coder,calibs,
00233                                                               myNoiseTS,mySignalTS,lowGainOffset_,lowGainFrac_,false,
00234                                                               0,
00235                                                               HcalTimeSlew::Fast);
00236   if(recoMethod_ == 2)
00237    return ZdcSimpleRecAlgoImpl::reco2<ZDCDataFrame,ZDCRecHit>(digi,coder,calibs,
00238                                                               myNoiseTS,mySignalTS,lowGainOffset_,lowGainFrac_,false,
00239                                                               0,HcalTimeSlew::Fast);
00240 
00241      edm::LogError("ZDCSimpleRecAlgoImpl::reconstruct, recoMethod was not declared");
00242      throw cms::Exception("ZDCSimpleRecoAlgos::exiting process");
00243    
00244 }
00245 
00246 static const float wpksamp0_zdc = 0.500053;
00247 static const float scale_zdc    = 0.999683;
00248 static const int   num_bins_zdc = 100;
00249 
00250 static const float actual_ns_zdc[num_bins_zdc] = {
00251  0.00250, // 0.000-0.010
00252  0.08000, // 0.010-0.020
00253  0.16000, // 0.020-0.030
00254  0.23750, // 0.030-0.040
00255  0.31750, // 0.040-0.050
00256  0.39500, // 0.050-0.060
00257  0.47500, // 0.060-0.070
00258  0.55500, // 0.070-0.080
00259  0.63000, // 0.080-0.090
00260  0.70000, // 0.090-0.100
00261  0.77000, // 0.100-0.110
00262  0.84000, // 0.110-0.120
00263  0.91000, // 0.120-0.130
00264  0.98000, // 0.130-0.140
00265  1.05000, // 0.140-0.150
00266  1.12000, // 0.150-0.160
00267  1.19000, // 0.160-0.170
00268  1.26000, // 0.170-0.180
00269  1.33000, // 0.180-0.190
00270  1.40000, // 0.190-0.200
00271  1.47000, // 0.200-0.210
00272  1.54000, // 0.210-0.220
00273  1.61000, // 0.220-0.230
00274  1.68000, // 0.230-0.240
00275  1.75000, // 0.240-0.250
00276  1.82000, // 0.250-0.260
00277  1.89000, // 0.260-0.270
00278  1.96000, // 0.270-0.280
00279  2.03000, // 0.280-0.290
00280  2.10000, // 0.290-0.300
00281  2.17000, // 0.300-0.310
00282  2.24000, // 0.310-0.320
00283  2.31000, // 0.320-0.330
00284  2.38000, // 0.330-0.340
00285  2.45000, // 0.340-0.350
00286  2.52000, // 0.350-0.360
00287  2.59000, // 0.360-0.370
00288  2.68500, // 0.370-0.380
00289  2.79250, // 0.380-0.390
00290  2.90250, // 0.390-0.400
00291  3.01000, // 0.400-0.410
00292  3.11750, // 0.410-0.420
00293  3.22500, // 0.420-0.430
00294  3.33500, // 0.430-0.440
00295  3.44250, // 0.440-0.450
00296  3.55000, // 0.450-0.460
00297  3.73250, // 0.460-0.470
00298  4.02000, // 0.470-0.480
00299  4.30750, // 0.480-0.490
00300  4.59500, // 0.490-0.500
00301  6.97500, // 0.500-0.510
00302 10.98750, // 0.510-0.520
00303 13.03750, // 0.520-0.530
00304 14.39250, // 0.530-0.540
00305 15.39500, // 0.540-0.550
00306 16.18250, // 0.550-0.560
00307 16.85250, // 0.560-0.570
00308 17.42750, // 0.570-0.580
00309 17.91500, // 0.580-0.590
00310 18.36250, // 0.590-0.600
00311 18.76500, // 0.600-0.610
00312 19.11250, // 0.610-0.620
00313 19.46000, // 0.620-0.630
00314 19.76500, // 0.630-0.640
00315 20.03500, // 0.640-0.650
00316 20.30250, // 0.650-0.660
00317 20.57250, // 0.660-0.670
00318 20.79250, // 0.670-0.680
00319 21.00250, // 0.680-0.690
00320 21.21000, // 0.690-0.700
00321 21.42000, // 0.700-0.710
00322 21.62750, // 0.710-0.720
00323 21.79000, // 0.720-0.730
00324 21.95250, // 0.730-0.740
00325 22.11500, // 0.740-0.750
00326 22.27750, // 0.750-0.760
00327 22.44000, // 0.760-0.770
00328 22.60500, // 0.770-0.780
00329 22.73250, // 0.780-0.790
00330 22.86000, // 0.790-0.800
00331 22.98500, // 0.800-0.810
00332 23.11250, // 0.810-0.820
00333 23.23750, // 0.820-0.830
00334 23.36500, // 0.830-0.840
00335 23.49000, // 0.840-0.850
00336 23.61750, // 0.850-0.860
00337 23.71500, // 0.860-0.870
00338 23.81250, // 0.870-0.880
00339 23.91250, // 0.880-0.890
00340 24.01000, // 0.890-0.900
00341 24.10750, // 0.900-0.910
00342 24.20750, // 0.910-0.920
00343 24.30500, // 0.920-0.930
00344 24.40500, // 0.930-0.940
00345 24.50250, // 0.940-0.950
00346 24.60000, // 0.950-0.960
00347 24.68250, // 0.960-0.970
00348 24.76250, // 0.970-0.980
00349 24.84000, // 0.980-0.990
00350 24.92000  // 0.990-1.000
00351 };
00352 
00353 /*
00354 float timeshift_ns_zdc(float wpksamp) {
00355   float flx = (num_bins_zdc*(wpksamp - wpksamp0_zdc)/scale_zdc);
00356   int index = (int)flx;
00357   float yval;
00358   
00359   if      (index <    0)        return actual_ns_zdc[0];
00360   else if (index >= num_bins_zdc-1) return actual_ns_zdc[num_bins_zdc-1];
00361 
00362   // else interpolate:
00363   float y1       = actual_ns_zdc[index];
00364   float y2       = actual_ns_zdc[index+1];
00365 
00366   // float delta_x  = 1/(float)num_bins_zdc;
00367   // yval = y1 + (y2-y1)*(flx-(float)index)/delta_x;
00368 
00369   yval = y1 + (y2-y1)*(flx-(float)index);
00370   return yval;
00371 }
00372 */