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>
00006 #include <math.h>
00007
00008 constexpr double MaximumFractionalError = 0.0005;
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
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));
00047 fc_ampl+=ta;
00048 ta*=calibs.gain(capid);
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
00060
00061
00062
00063
00064
00065
00066
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
00080 ampl *= corr->getCorrection(fc_ampl);
00081
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
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
00101
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
00107 if(n != 2) return false;
00108
00109
00110 if(ifirst+n > digi.size()) return false;
00111
00112
00113
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
00121 int capid = digi[ifirst].capid();
00122 float ta = tool[ifirst]-calibs.pedestal(capid);
00123 float ta1 = ta*calibs.gain(capid);
00124
00125
00126 capid = digi[ifirst+1].capid();
00127 ta = tool[ifirst+1]-calibs.pedestal(capid);
00128 float ta2 = ta*calibs.gain(capid);
00129
00130
00131
00132
00133 if(ta2 / satCorrConst <= ta1) return false;
00134
00135
00136
00137 ampl = ta2 + ta2 / satCorrConst;
00138
00139
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
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
00168
00169 rechit.setFlagField(1,HcalCaloFlagLabels::UserDefinedBit0);
00170 }
00171
00172
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,
00180 0.03750,
00181 0.07250,
00182 0.10750,
00183 0.14500,
00184 0.18000,
00185 0.21500,
00186 0.25000,
00187 0.28500,
00188 0.32000,
00189 0.35500,
00190 0.39000,
00191 0.42500,
00192 0.46000,
00193 0.49500,
00194 0.53000,
00195 0.56500,
00196 0.60000,
00197 0.63500,
00198 0.67000,
00199 0.70750,
00200 0.74250,
00201 0.78000,
00202 0.81500,
00203 0.85250,
00204 0.89000,
00205 0.92750,
00206 0.96500,
00207 1.00250,
00208 1.04250,
00209 1.08250,
00210 1.12250,
00211 1.16250,
00212 1.20500,
00213 1.24500,
00214 1.29000,
00215 1.33250,
00216 1.38000,
00217 1.42500,
00218 1.47500,
00219 1.52500,
00220 1.57750,
00221 1.63250,
00222 1.69000,
00223 1.75250,
00224 1.82000,
00225 1.89250,
00226 1.97500,
00227 2.07250,
00228 2.20000,
00229 19.13000,
00230 21.08750,
00231 21.57750,
00232 21.89000,
00233 22.12250,
00234 22.31000,
00235 22.47000,
00236 22.61000,
00237 22.73250,
00238 22.84500,
00239 22.94750,
00240 23.04250,
00241 23.13250,
00242 23.21500,
00243 23.29250,
00244 23.36750,
00245 23.43750,
00246 23.50500,
00247 23.57000,
00248 23.63250,
00249 23.69250,
00250 23.75000,
00251 23.80500,
00252 23.86000,
00253 23.91250,
00254 23.96500,
00255 24.01500,
00256 24.06500,
00257 24.11250,
00258 24.16000,
00259 24.20500,
00260 24.25000,
00261 24.29500,
00262 24.33750,
00263 24.38000,
00264 24.42250,
00265 24.46500,
00266 24.50500,
00267 24.54500,
00268 24.58500,
00269 24.62500,
00270 24.66500,
00271 24.70250,
00272 24.74000,
00273 24.77750,
00274 24.81500,
00275 24.85250,
00276 24.89000,
00277 24.92750,
00278 24.96250,
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
00291 float y1 = actual_ns_hf[index];
00292 float y2 = actual_ns_hf[index+1];
00293
00294
00295
00296
00297 yval = y1 + (y2-y1)*(flx-(float)index);
00298 return yval;
00299 }