CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/RecoLocalCalo/CastorReco/src/CastorSimpleRecAlgo.cc

Go to the documentation of this file.
00001 #include "RecoLocalCalo/CastorReco/interface/CastorSimpleRecAlgo.h"
00002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00003 #include "CalibCalorimetry/CastorCalib/interface/CastorTimeSlew.h"
00004 #include "RecoLocalCalo/HcalRecAlgos/interface/HcalCaloFlagLabels.h"
00005 #include <algorithm> // for "max"
00006 #include <math.h>
00007 
00008 constexpr double MaximumFractionalError = 0.0005; // 0.05% error allowed from this source
00009 
00010 CastorSimpleRecAlgo::CastorSimpleRecAlgo(int firstSample, int samplesToAdd, bool correctForTimeslew, bool correctForPulse, float phaseNS) : 
00011   firstSample_(firstSample), 
00012   samplesToAdd_(samplesToAdd), 
00013   correctForTimeslew_(correctForTimeslew) {
00014   if (correctForPulse) 
00015     pulseCorr_=std::auto_ptr<CastorPulseContainmentCorrection>(new CastorPulseContainmentCorrection(samplesToAdd_,phaseNS,MaximumFractionalError));
00016 }
00017 
00018 CastorSimpleRecAlgo::CastorSimpleRecAlgo(int firstSample, int samplesToAdd) : 
00019   firstSample_(firstSample), 
00020   samplesToAdd_(samplesToAdd), 
00021   correctForTimeslew_(false) {
00022 }
00023 
00029 //static float timeshift_ns_hbheho(float wpksamp);
00030 
00032 static float timeshift_ns_hf(float wpksamp);
00033 
00034 
00035 namespace CastorSimpleRecAlgoImpl {
00036   template<class Digi, class RecHit>
00037   inline RecHit reco(const Digi& digi, const CastorCoder& coder, const CastorCalibrations& calibs, 
00038                      int ifirst, int n, bool slewCorrect, const CastorPulseContainmentCorrection* corr, CastorTimeSlew::BiasSetting slewFlavor) {
00039     CaloSamples tool;
00040     coder.adc2fC(digi,tool);
00041 
00042     double ampl=0; int maxI = -1; double maxA = -1e10; float ta=0;
00043     double fc_ampl=0;
00044     for (int i=ifirst; i<tool.size() && i<n+ifirst; i++) {
00045       int capid=digi[i].capid();
00046       ta = (tool[i]-calibs.pedestal(capid)); // pedestal subtraction
00047       fc_ampl+=ta; 
00048       ta*=calibs.gain(capid); // fC --> GeV
00049       ampl+=ta;
00050       if(ta>maxA){
00051         maxA=ta;
00052         maxI=i;
00053       }
00054     }
00055 
00056     float time=-9999;
00058     if(maxI==0 || maxI==(tool.size()-1)) {      
00059       // supress warning and use dummy time value for 2009 data
00060       /*
00061       edm::LogWarning("HCAL/CASTOR Pulse") << "CastorSimpleRecAlgo::reconstruct :" 
00062                                                << " Invalid max amplitude position, " 
00063                                                << " max Amplitude: "<< maxI
00064                                                << " first: "<<ifirst
00065                                                << " last: "<<(tool.size()-1)
00066                                                << std::endl;
00067     */
00068     } else {
00069       maxA=fabs(maxA);
00070       int capid=digi[maxI-1].capid();
00071       float t0 = fabs((tool[maxI-1]-calibs.pedestal(capid))*calibs.gain(capid));
00072       capid=digi[maxI+1].capid();
00073       float t2 = fabs((tool[maxI+1]-calibs.pedestal(capid))*calibs.gain(capid));    
00074       float wpksamp = (t0 + maxA + t2);
00075       if (wpksamp!=0) wpksamp=(maxA + 2.0*t2) / wpksamp; 
00076       time = (maxI - digi.presamples())*25.0 + timeshift_ns_hf(wpksamp);
00077 
00078       if (corr!=0) {
00079         // Apply phase-based amplitude correction:
00080         ampl *= corr->getCorrection(fc_ampl);
00081         //      std::cout << fc_ampl << " --> " << corr->getCorrection(fc_ampl) << std::endl;
00082       }
00083 
00084     
00085       if (slewCorrect) time-=CastorTimeSlew::delay(std::max(1.0,fc_ampl),slewFlavor);
00086     }
00087     return RecHit(digi.id(),ampl,time);    
00088   }
00089 
00090   // returns TRUE if ADC count is >= maxADCvalue
00091   template<class Digi>
00092   inline bool isSaturated(const Digi& digi, const int& maxADCvalue, int ifirst, int n) {
00093     for (int i=ifirst; i<digi.size() && i<n+ifirst; i++) {
00094       if(digi[i].adc() >= maxADCvalue) return true;
00095     }
00096     
00097     return false;
00098   }
00099 
00100   //++++ Saturation Correction +++++
00101   // returns TRUE when saturation correction was done
00102   template<class Digi, class RecHit>
00103   inline bool corrSaturation(RecHit& rechit, const CastorCoder& coder, const CastorCalibrations& calibs,
00104                              const Digi& digi, const int& maxADCvalue, const double& satCorrConst, int ifirst, int n)
00105   {
00106     // correction works only with 2 used TS
00107     if(n != 2) return false;
00108 
00109     // to avoid segmentation violation
00110     if(ifirst+n > digi.size()) return false;
00111 
00112     // look if first TS is saturated not the second one
00113     // in case the second one is saturated do no correction
00114     if(digi[ifirst].adc() >= maxADCvalue && digi[ifirst+1].adc() < maxADCvalue) {
00115       float ampl = 0;
00116 
00117       CaloSamples tool;
00118       coder.adc2fC(digi,tool);
00119 
00120       // get energy of first TS
00121       int capid = digi[ifirst].capid();
00122       float ta = tool[ifirst]-calibs.pedestal(capid); // pedestal subtraction
00123       float ta1 = ta*calibs.gain(capid); // fC --> GeV
00124 
00125       // get energy of second TS
00126       capid = digi[ifirst+1].capid();
00127       ta = tool[ifirst+1]-calibs.pedestal(capid); // pedestal subtraction
00128       float ta2 = ta*calibs.gain(capid); // fC --> GeV
00129 
00130       // use second TS to calc the first one
00131       // check if recalculated TS ampl is
00132       // realy greater than the saturated value
00133       if(ta2 / satCorrConst <= ta1) return false;
00134 
00135       // ampl = TS5 + TS4 => TS4 = TS5 / TSratio
00136       // ampl = TS5 + TS5 / TSratio
00137       ampl    = ta2  + ta2  / satCorrConst;
00138 
00139       // reset energy of rechit
00140       rechit.setEnergy(ampl);
00141 
00142       return true;
00143     }
00144 
00145     return false;
00146   }
00147 }
00148 
00149 CastorRecHit CastorSimpleRecAlgo::reconstruct(const CastorDataFrame& digi, const CastorCoder& coder, const CastorCalibrations& calibs) const {
00150   return CastorSimpleRecAlgoImpl::reco<CastorDataFrame,CastorRecHit>(digi,coder,calibs,
00151                                                              firstSample_,samplesToAdd_,false,
00152                                                              0,
00153                                                              CastorTimeSlew::Fast);
00154 }
00155 
00156 void CastorSimpleRecAlgo::checkADCSaturation(CastorRecHit& rechit, const CastorDataFrame& digi, const int& maxADCvalue) const {
00157   if(CastorSimpleRecAlgoImpl::isSaturated<CastorDataFrame>(digi,maxADCvalue,firstSample_,samplesToAdd_))
00158     rechit.setFlagField(1,HcalCaloFlagLabels::ADCSaturationBit);
00159 }
00160 
00161 //++++ Saturation Correction +++++
00162 void CastorSimpleRecAlgo::recoverADCSaturation(CastorRecHit& rechit,  const CastorCoder& coder, const CastorCalibrations& calibs,
00163                                                const CastorDataFrame& digi, const int& maxADCvalue, const double& satCorrConst) const {
00164   if(CastorSimpleRecAlgoImpl::corrSaturation<CastorDataFrame,CastorRecHit>(rechit,coder,calibs,digi,
00165                                                                            maxADCvalue,satCorrConst,
00166                                                                            firstSample_,samplesToAdd_))
00167     // use empty flag bit for recording saturation correction
00168     // see also CMSSW/RecoLocalCalo/HcalRecAlgos/interface/HcalCaloFlagLabels.h
00169     rechit.setFlagField(1,HcalCaloFlagLabels::UserDefinedBit0);
00170 } 
00171 
00172 // timeshift implementation
00173 
00174 static const float wpksamp0_hf = 0.500635;
00175 static const float scale_hf    = 0.999301;
00176 static const int   num_bins_hf = 100;
00177 
00178 static const float actual_ns_hf[num_bins_hf] = {
00179  0.00000, // 0.000-0.010
00180  0.03750, // 0.010-0.020
00181  0.07250, // 0.020-0.030
00182  0.10750, // 0.030-0.040
00183  0.14500, // 0.040-0.050
00184  0.18000, // 0.050-0.060
00185  0.21500, // 0.060-0.070
00186  0.25000, // 0.070-0.080
00187  0.28500, // 0.080-0.090
00188  0.32000, // 0.090-0.100
00189  0.35500, // 0.100-0.110
00190  0.39000, // 0.110-0.120
00191  0.42500, // 0.120-0.130
00192  0.46000, // 0.130-0.140
00193  0.49500, // 0.140-0.150
00194  0.53000, // 0.150-0.160
00195  0.56500, // 0.160-0.170
00196  0.60000, // 0.170-0.180
00197  0.63500, // 0.180-0.190
00198  0.67000, // 0.190-0.200
00199  0.70750, // 0.200-0.210
00200  0.74250, // 0.210-0.220
00201  0.78000, // 0.220-0.230
00202  0.81500, // 0.230-0.240
00203  0.85250, // 0.240-0.250
00204  0.89000, // 0.250-0.260
00205  0.92750, // 0.260-0.270
00206  0.96500, // 0.270-0.280
00207  1.00250, // 0.280-0.290
00208  1.04250, // 0.290-0.300
00209  1.08250, // 0.300-0.310
00210  1.12250, // 0.310-0.320
00211  1.16250, // 0.320-0.330
00212  1.20500, // 0.330-0.340
00213  1.24500, // 0.340-0.350
00214  1.29000, // 0.350-0.360
00215  1.33250, // 0.360-0.370
00216  1.38000, // 0.370-0.380
00217  1.42500, // 0.380-0.390
00218  1.47500, // 0.390-0.400
00219  1.52500, // 0.400-0.410
00220  1.57750, // 0.410-0.420
00221  1.63250, // 0.420-0.430
00222  1.69000, // 0.430-0.440
00223  1.75250, // 0.440-0.450
00224  1.82000, // 0.450-0.460
00225  1.89250, // 0.460-0.470
00226  1.97500, // 0.470-0.480
00227  2.07250, // 0.480-0.490
00228  2.20000, // 0.490-0.500
00229 19.13000, // 0.500-0.510
00230 21.08750, // 0.510-0.520
00231 21.57750, // 0.520-0.530
00232 21.89000, // 0.530-0.540
00233 22.12250, // 0.540-0.550
00234 22.31000, // 0.550-0.560
00235 22.47000, // 0.560-0.570
00236 22.61000, // 0.570-0.580
00237 22.73250, // 0.580-0.590
00238 22.84500, // 0.590-0.600
00239 22.94750, // 0.600-0.610
00240 23.04250, // 0.610-0.620
00241 23.13250, // 0.620-0.630
00242 23.21500, // 0.630-0.640
00243 23.29250, // 0.640-0.650
00244 23.36750, // 0.650-0.660
00245 23.43750, // 0.660-0.670
00246 23.50500, // 0.670-0.680
00247 23.57000, // 0.680-0.690
00248 23.63250, // 0.690-0.700
00249 23.69250, // 0.700-0.710
00250 23.75000, // 0.710-0.720
00251 23.80500, // 0.720-0.730
00252 23.86000, // 0.730-0.740
00253 23.91250, // 0.740-0.750
00254 23.96500, // 0.750-0.760
00255 24.01500, // 0.760-0.770
00256 24.06500, // 0.770-0.780
00257 24.11250, // 0.780-0.790
00258 24.16000, // 0.790-0.800
00259 24.20500, // 0.800-0.810
00260 24.25000, // 0.810-0.820
00261 24.29500, // 0.820-0.830
00262 24.33750, // 0.830-0.840
00263 24.38000, // 0.840-0.850
00264 24.42250, // 0.850-0.860
00265 24.46500, // 0.860-0.870
00266 24.50500, // 0.870-0.880
00267 24.54500, // 0.880-0.890
00268 24.58500, // 0.890-0.900
00269 24.62500, // 0.900-0.910
00270 24.66500, // 0.910-0.920
00271 24.70250, // 0.920-0.930
00272 24.74000, // 0.930-0.940
00273 24.77750, // 0.940-0.950
00274 24.81500, // 0.950-0.960
00275 24.85250, // 0.960-0.970
00276 24.89000, // 0.970-0.980
00277 24.92750, // 0.980-0.990
00278 24.96250, // 0.990-1.000
00279 };
00280 
00281 
00282 float timeshift_ns_hf(float wpksamp) {
00283   float flx = (num_bins_hf*(wpksamp - wpksamp0_hf)/scale_hf);
00284   int index = (int)flx;
00285   float yval;
00286   
00287   if      (index <    0)        return actual_ns_hf[0];
00288   else if (index >= num_bins_hf-1) return actual_ns_hf[num_bins_hf-1];
00289 
00290   // else interpolate:
00291   float y1       = actual_ns_hf[index];
00292   float y2       = actual_ns_hf[index+1];
00293 
00294   // float delta_x  = 1/(float)num_bins_hf;
00295   // yval = y1 + (y2-y1)*(flx-(float)index)/delta_x;
00296 
00297   yval = y1 + (y2-y1)*(flx-(float)index);
00298   return yval;
00299 }