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(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
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
00044
00045
00046
00047
00048
00049
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));
00053 fc_ampl+=ta;
00054 ta*= calibs.respcorrgain(capid) ;
00055 ampl+=ta;
00056 if(ta>maxA){
00057 maxA=ta;
00058 maxI=i;
00059 }
00060 }
00061
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));
00071 lowGfc_ampl+=TempLGAmp;
00072 TempLGAmp*= calibs.respcorrgain(capid) ;
00073 TempLGAmp*= lowGainFrac ;
00074 lowGEnergy+=TempLGAmp;
00075 }
00076 double time=-9999;
00077
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
00090
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
00104
00105 if(AvgTSPos==0){
00106 time=-99;
00107 } else {
00108 time = (AvgTSPos*25.0);
00109 }
00110 if (corr!=0) {
00111
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
00126 int ifirst = mySignalTS[0];
00127
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
00132
00133
00134
00135
00136
00137 double Allnoise = 0;
00138 int noiseslices = 0;
00139 int CurrentTS = 0;
00140 double noise = 0;
00141
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
00158
00159
00160
00161
00162 ta = tool[CurrentTS]-noise;
00163 fc_ampl+=ta;
00164 ta*= calibs.respcorrgain(capid) ;
00165 ampl+=ta;
00166 if(ta>maxA){
00167 maxA=ta;
00168 maxI=CurrentTS;
00169 }
00170 }
00171
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) ;
00179 TempLGAmp*= lowGainFrac ;
00180 lowGEnergy+=TempLGAmp;
00181 }
00182
00183
00184
00185
00186 double time=-9999;
00187
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
00200
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
00214
00215 if(AvgTSPos==0){
00216 time=-99;
00217 } else {
00218 time = (AvgTSPos*25.0);
00219 }
00220 if (corr!=0) {
00221
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,
00252 0.08000,
00253 0.16000,
00254 0.23750,
00255 0.31750,
00256 0.39500,
00257 0.47500,
00258 0.55500,
00259 0.63000,
00260 0.70000,
00261 0.77000,
00262 0.84000,
00263 0.91000,
00264 0.98000,
00265 1.05000,
00266 1.12000,
00267 1.19000,
00268 1.26000,
00269 1.33000,
00270 1.40000,
00271 1.47000,
00272 1.54000,
00273 1.61000,
00274 1.68000,
00275 1.75000,
00276 1.82000,
00277 1.89000,
00278 1.96000,
00279 2.03000,
00280 2.10000,
00281 2.17000,
00282 2.24000,
00283 2.31000,
00284 2.38000,
00285 2.45000,
00286 2.52000,
00287 2.59000,
00288 2.68500,
00289 2.79250,
00290 2.90250,
00291 3.01000,
00292 3.11750,
00293 3.22500,
00294 3.33500,
00295 3.44250,
00296 3.55000,
00297 3.73250,
00298 4.02000,
00299 4.30750,
00300 4.59500,
00301 6.97500,
00302 10.98750,
00303 13.03750,
00304 14.39250,
00305 15.39500,
00306 16.18250,
00307 16.85250,
00308 17.42750,
00309 17.91500,
00310 18.36250,
00311 18.76500,
00312 19.11250,
00313 19.46000,
00314 19.76500,
00315 20.03500,
00316 20.30250,
00317 20.57250,
00318 20.79250,
00319 21.00250,
00320 21.21000,
00321 21.42000,
00322 21.62750,
00323 21.79000,
00324 21.95250,
00325 22.11500,
00326 22.27750,
00327 22.44000,
00328 22.60500,
00329 22.73250,
00330 22.86000,
00331 22.98500,
00332 23.11250,
00333 23.23750,
00334 23.36500,
00335 23.49000,
00336 23.61750,
00337 23.71500,
00338 23.81250,
00339 23.91250,
00340 24.01000,
00341 24.10750,
00342 24.20750,
00343 24.30500,
00344 24.40500,
00345 24.50250,
00346 24.60000,
00347 24.68250,
00348 24.76250,
00349 24.84000,
00350 24.92000
00351 };
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372