00001 #include "RecoLocalCalo/HcalRecAlgos/interface/ZdcSimpleRecAlgo.h"
00002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00003 #include "CalibCalorimetry/HcalAlgos/interface/HcalTimeSlew.h"
00004 #include <algorithm>
00005 #include <iostream>
00006 #include <math.h>
00007
00008
00009
00010 static double MaximumFractionalError = 0.0005;
00011
00012 ZdcSimpleRecAlgo::ZdcSimpleRecAlgo(int firstSample, int samplesToAdd, bool correctForTimeslew, bool correctForPulse, float phaseNS, int recoMethod) :
00013 firstSample_(firstSample),
00014 samplesToAdd_(samplesToAdd),
00015 recoMethod_(recoMethod),
00016 correctForTimeslew_(correctForTimeslew) {
00017 if (correctForPulse)
00018 pulseCorr_=std::auto_ptr<HcalPulseContainmentCorrection>(new HcalPulseContainmentCorrection(samplesToAdd_,phaseNS,MaximumFractionalError));
00019 }
00020
00021 ZdcSimpleRecAlgo::ZdcSimpleRecAlgo(int firstSample, int samplesToAdd, int recoMethod) :
00022 firstSample_(firstSample),
00023 samplesToAdd_(samplesToAdd),
00024 recoMethod_(recoMethod),
00025 correctForTimeslew_(false) {
00026 }
00027
00028 static float timeshift_ns_zdc(float wpksamp);
00029
00030 namespace ZdcSimpleRecAlgoImpl {
00031 template<class Digi, class RecHit>
00032 inline RecHit reco1(const Digi& digi, const HcalCoder& coder, const HcalCalibrations& calibs,
00033 int ifirst, int n, bool slewCorrect, const HcalPulseContainmentCorrection* corr, HcalTimeSlew::BiasSetting slewFlavor) {
00034 CaloSamples tool;
00035 coder.adc2fC(digi,tool);
00036 double ampl=0; int maxI = -1; double maxA = -1e10; double ta=0;
00037 double fc_ampl=0;
00038 for (int i=ifirst; i<tool.size() && i<n+ifirst; i++) {
00039 int capid=digi[i].capid();
00040 ta = (tool[i]-calibs.pedestal(capid));
00041 fc_ampl+=ta;
00042 ta*= calibs.respcorrgain(capid) ;
00043 ampl+=ta;
00044 if(ta>maxA){
00045 maxA=ta;
00046 maxI=i;
00047 }
00048 }
00049
00050 double time=-9999;
00052 if(maxI==0 || maxI==(tool.size()-1)) {
00053 LogDebug("HCAL Pulse") << "ZdcSimpleRecAlgo::reconstruct :"
00054 << " Invalid max amplitude position, "
00055 << " max Amplitude: "<< maxI
00056 << " first: "<<ifirst
00057 << " last: "<<(tool.size()-1)
00058 << std::endl;
00059 } else {
00060 maxA=fabs(maxA);
00061 int capid=digi[maxI-1].capid();
00062 double t0 = fabs((tool[maxI-1]-calibs.pedestal(capid))*calibs.respcorrgain(capid) );
00063 capid=digi[maxI+1].capid();
00064 double t2 = fabs((tool[maxI+1]-calibs.pedestal(capid))*calibs.respcorrgain(capid) );
00065 double wpksamp = (t0 + maxA + t2);
00066 if (wpksamp!=0) wpksamp=(maxA + 2.0*t2) / wpksamp;
00067 time = (maxI - digi.presamples())*25.0 + timeshift_ns_zdc(wpksamp);
00068 if (corr!=0) {
00069
00070 ampl *= corr->getCorrection(fc_ampl);
00071
00072 }
00073
00074 if (slewCorrect) time-=HcalTimeSlew::delay(std::max(1.0,fc_ampl),slewFlavor);
00075 }
00076
00077 time=time-calibs.timecorr();
00078 return RecHit(digi.id(),ampl,time);
00079 }
00080 }
00081
00082
00083 namespace ZdcSimpleRecAlgoImpl {
00084 template<class Digi, class RecHit>
00085 inline RecHit reco2(const Digi& digi, const HcalCoder& coder, const HcalCalibrations& calibs,
00086 int ifirst, int n, bool slewCorrect, const HcalPulseContainmentCorrection* corr, HcalTimeSlew::BiasSetting slewFlavor) {
00087 CaloSamples tool;
00088 coder.adc2fC(digi,tool);
00089 double ampl=0; int maxI = -1; double maxA = -1e10; double ta=0;
00090 double prenoise = 0; double postnoise = 0;
00091 int noiseslices = 0;
00092 double noise = 0;
00093 double fc_ampl=0;
00094
00095 for(int k = 0 ; k < tool.size() && k < ifirst; k++){
00096 prenoise += tool[k];
00097 noiseslices++;
00098 }
00099
00100
00101
00102
00103
00104
00105 postnoise=0;
00106 if(noiseslices != 0) {
00107 noise = (prenoise+postnoise)/double(noiseslices);
00108 } else {
00109 noise = 0;
00110 }
00111
00112 double noisefactor=1.;
00113 for (int i=ifirst; i<tool.size() && i<n+ifirst; i++) {
00114 int capid=digi[i].capid();
00115 if(noise<0){
00116
00117
00118 noisefactor=0.;
00119 }
00120 ta = tool[i]-noisefactor*noise;
00121 fc_ampl+=ta;
00122 ta*= calibs.respcorrgain(capid) ;
00123 ampl+=ta;
00124 if(ta>maxA){
00125 maxA=ta;
00126 maxI=i;
00127 }
00128 }
00129
00130
00131
00132
00133 double time=-9999;
00135 if(maxI==0 || maxI==(tool.size()-1)) {
00136 LogDebug("HCAL Pulse") << "ZdcSimpleRecAlgo::reco2 :"
00137 << " Invalid max amplitude position, "
00138 << " max Amplitude: "<< maxI
00139 << " first: "<<ifirst
00140 << " last: "<<(tool.size()-1)
00141 << std::endl;
00142 } else {
00143 int capid=digi[maxI-1].capid();
00144 double Energy0 = ((tool[maxI-1])*calibs.respcorrgain(capid) );
00145
00146
00147 if(Energy0<0){Energy0=0.;}
00148 capid=digi[maxI].capid();
00149 double Energy1 = ((tool[maxI])*calibs.respcorrgain(capid) ) ;
00150 if(Energy1<0){Energy1=0.;}
00151 capid=digi[maxI+1].capid();
00152 double Energy2 = ((tool[maxI+1])*calibs.respcorrgain(capid) );
00153 if(Energy2<0){Energy2=0.;}
00154
00155 double TSWeightEnergy = ((maxI-1)*Energy0 + maxI*Energy1 + (maxI+1)*Energy2);
00156 double EnergySum=Energy0+Energy1+Energy2;
00157 double AvgTSPos=0.;
00158 if (EnergySum!=0) AvgTSPos=TSWeightEnergy/ EnergySum;
00159
00160
00161 if(AvgTSPos==0){
00162 time=-99;
00163 } else {
00164 time = (AvgTSPos*25.0);
00165 }
00166 if (corr!=0) {
00167
00168 ampl *= corr->getCorrection(fc_ampl);
00169 }
00170 }
00171 return RecHit(digi.id(),ampl,time);
00172 }
00173 }
00174
00175 ZDCRecHit ZdcSimpleRecAlgo::reconstruct(const ZDCDataFrame& digi, const HcalCoder& coder, const HcalCalibrations& calibs) const {
00176
00177 if(recoMethod_ == 1)
00178 return ZdcSimpleRecAlgoImpl::reco1<ZDCDataFrame,ZDCRecHit>(digi,coder,calibs,
00179 firstSample_,samplesToAdd_,false,
00180 0,
00181 HcalTimeSlew::Fast);
00182 if(recoMethod_ == 2)
00183 return ZdcSimpleRecAlgoImpl::reco2<ZDCDataFrame,ZDCRecHit>(digi,coder,calibs,
00184 firstSample_,samplesToAdd_,false,
00185 0,HcalTimeSlew::Fast);
00186
00187 edm::LogError("ZDCSimpleRecAlgoImpl::reconstruct, recoMethod was not declared");
00188 throw cms::Exception("ZDCSimpleRecoAlgos::exiting process");
00189
00190 }
00191
00192 static const float wpksamp0_zdc = 0.500053;
00193 static const float scale_zdc = 0.999683;
00194 static const int num_bins_zdc = 100;
00195
00196 static const float actual_ns_zdc[num_bins_zdc] = {
00197 0.00250,
00198 0.08000,
00199 0.16000,
00200 0.23750,
00201 0.31750,
00202 0.39500,
00203 0.47500,
00204 0.55500,
00205 0.63000,
00206 0.70000,
00207 0.77000,
00208 0.84000,
00209 0.91000,
00210 0.98000,
00211 1.05000,
00212 1.12000,
00213 1.19000,
00214 1.26000,
00215 1.33000,
00216 1.40000,
00217 1.47000,
00218 1.54000,
00219 1.61000,
00220 1.68000,
00221 1.75000,
00222 1.82000,
00223 1.89000,
00224 1.96000,
00225 2.03000,
00226 2.10000,
00227 2.17000,
00228 2.24000,
00229 2.31000,
00230 2.38000,
00231 2.45000,
00232 2.52000,
00233 2.59000,
00234 2.68500,
00235 2.79250,
00236 2.90250,
00237 3.01000,
00238 3.11750,
00239 3.22500,
00240 3.33500,
00241 3.44250,
00242 3.55000,
00243 3.73250,
00244 4.02000,
00245 4.30750,
00246 4.59500,
00247 6.97500,
00248 10.98750,
00249 13.03750,
00250 14.39250,
00251 15.39500,
00252 16.18250,
00253 16.85250,
00254 17.42750,
00255 17.91500,
00256 18.36250,
00257 18.76500,
00258 19.11250,
00259 19.46000,
00260 19.76500,
00261 20.03500,
00262 20.30250,
00263 20.57250,
00264 20.79250,
00265 21.00250,
00266 21.21000,
00267 21.42000,
00268 21.62750,
00269 21.79000,
00270 21.95250,
00271 22.11500,
00272 22.27750,
00273 22.44000,
00274 22.60500,
00275 22.73250,
00276 22.86000,
00277 22.98500,
00278 23.11250,
00279 23.23750,
00280 23.36500,
00281 23.49000,
00282 23.61750,
00283 23.71500,
00284 23.81250,
00285 23.91250,
00286 24.01000,
00287 24.10750,
00288 24.20750,
00289 24.30500,
00290 24.40500,
00291 24.50250,
00292 24.60000,
00293 24.68250,
00294 24.76250,
00295 24.84000,
00296 24.92000
00297 };
00298
00299 float timeshift_ns_zdc(float wpksamp) {
00300 float flx = (num_bins_zdc*(wpksamp - wpksamp0_zdc)/scale_zdc);
00301 int index = (int)flx;
00302 float yval;
00303
00304 if (index < 0) return actual_ns_zdc[0];
00305 else if (index >= num_bins_zdc-1) return actual_ns_zdc[num_bins_zdc-1];
00306
00307
00308 float y1 = actual_ns_zdc[index];
00309 float y2 = actual_ns_zdc[index+1];
00310
00311
00312
00313
00314 yval = y1 + (y2-y1)*(flx-(float)index);
00315 return yval;
00316 }