File indexing completed on 2024-04-06 12:25:38
0001 #include "RecoLocalCalo/CastorReco/interface/CastorSimpleRecAlgo.h"
0002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0003 #include "CalibCalorimetry/CastorCalib/interface/CastorTimeSlew.h"
0004 #include "DataFormats/METReco/interface/HcalCaloFlagLabels.h"
0005 #include <algorithm> // for "max"
0006 #include <cmath>
0007
0008 constexpr double MaximumFractionalError = 0.0005;
0009
0010 CastorSimpleRecAlgo::CastorSimpleRecAlgo(
0011 int firstSample, int samplesToAdd, bool correctForTimeslew, bool correctForPulse, float phaseNS)
0012 : firstSample_(firstSample), samplesToAdd_(samplesToAdd), correctForTimeslew_(correctForTimeslew) {
0013 if (correctForPulse)
0014 pulseCorr_ = std::make_unique<CastorPulseContainmentCorrection>(samplesToAdd_, phaseNS, MaximumFractionalError);
0015 }
0016
0017 CastorSimpleRecAlgo::CastorSimpleRecAlgo(int firstSample, int samplesToAdd)
0018 : firstSample_(firstSample), samplesToAdd_(samplesToAdd), correctForTimeslew_(false) {}
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 static float timeshift_ns_hf(float wpksamp);
0029
0030 namespace CastorSimpleRecAlgoImpl {
0031 template <class Digi, class RecHit>
0032 inline RecHit reco(const Digi& digi,
0033 const CastorCoder& coder,
0034 const CastorCalibrations& calibs,
0035 int ifirst,
0036 int n,
0037 bool slewCorrect,
0038 const CastorPulseContainmentCorrection* corr,
0039 CastorTimeSlew::BiasSetting slewFlavor) {
0040 CaloSamples tool;
0041 coder.adc2fC(digi, tool);
0042
0043 double ampl = 0;
0044 int maxI = -1;
0045 double maxA = -1e10;
0046 float ta = 0;
0047 double fc_ampl = 0;
0048 for (int i = ifirst; i < tool.size() && i < n + ifirst; i++) {
0049 int capid = digi[i].capid();
0050 ta = (tool[i] - calibs.pedestal(capid));
0051 fc_ampl += ta;
0052 ta *= calibs.gain(capid);
0053 ampl += ta;
0054 if (ta > maxA) {
0055 maxA = ta;
0056 maxI = i;
0057 }
0058 }
0059
0060 float time = -9999;
0061
0062 if (maxI == 0 || maxI == (tool.size() - 1)) {
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 } else {
0073 maxA = fabs(maxA);
0074 int capid = digi[maxI - 1].capid();
0075 float t0 = fabs((tool[maxI - 1] - calibs.pedestal(capid)) * calibs.gain(capid));
0076 capid = digi[maxI + 1].capid();
0077 float t2 = fabs((tool[maxI + 1] - calibs.pedestal(capid)) * calibs.gain(capid));
0078 float wpksamp = (t0 + maxA + t2);
0079 if (wpksamp != 0)
0080 wpksamp = (maxA + 2.0 * t2) / wpksamp;
0081 time = (maxI - digi.presamples()) * 25.0 + timeshift_ns_hf(wpksamp);
0082
0083 if (corr != nullptr) {
0084
0085 ampl *= corr->getCorrection(fc_ampl);
0086
0087 }
0088
0089 if (slewCorrect)
0090 time -= CastorTimeSlew::delay(std::max(1.0, fc_ampl), slewFlavor);
0091 }
0092 return RecHit(digi.id(), ampl, time);
0093 }
0094
0095
0096 template <class Digi>
0097 inline bool isSaturated(const Digi& digi, const int& maxADCvalue, int ifirst, int n) {
0098 for (int i = ifirst; i < digi.size() && i < n + ifirst; i++) {
0099 if (digi[i].adc() >= maxADCvalue)
0100 return true;
0101 }
0102
0103 return false;
0104 }
0105
0106
0107
0108 template <class Digi, class RecHit>
0109 inline bool corrSaturation(RecHit& rechit,
0110 const CastorCoder& coder,
0111 const CastorCalibrations& calibs,
0112 const Digi& digi,
0113 const int& maxADCvalue,
0114 const double& satCorrConst,
0115 int ifirst,
0116 int n) {
0117
0118 if (n != 2)
0119 return false;
0120
0121
0122 if (ifirst + n > digi.size())
0123 return false;
0124
0125
0126
0127 if (digi[ifirst].adc() >= maxADCvalue && digi[ifirst + 1].adc() < maxADCvalue) {
0128 float ampl = 0;
0129
0130 CaloSamples tool;
0131 coder.adc2fC(digi, tool);
0132
0133
0134 int capid = digi[ifirst].capid();
0135 float ta = tool[ifirst] - calibs.pedestal(capid);
0136 float ta1 = ta * calibs.gain(capid);
0137
0138
0139 capid = digi[ifirst + 1].capid();
0140 ta = tool[ifirst + 1] - calibs.pedestal(capid);
0141 float ta2 = ta * calibs.gain(capid);
0142
0143
0144
0145
0146 if (ta2 / satCorrConst <= ta1)
0147 return false;
0148
0149
0150
0151 ampl = ta2 + ta2 / satCorrConst;
0152
0153
0154 rechit.setEnergy(ampl);
0155
0156 return true;
0157 }
0158
0159 return false;
0160 }
0161 }
0162
0163 CastorRecHit CastorSimpleRecAlgo::reconstruct(const CastorDataFrame& digi,
0164 const CastorCoder& coder,
0165 const CastorCalibrations& calibs) const {
0166 return CastorSimpleRecAlgoImpl::reco<CastorDataFrame, CastorRecHit>(
0167 digi, coder, calibs, firstSample_, samplesToAdd_, false, nullptr, CastorTimeSlew::Fast);
0168 }
0169
0170 void CastorSimpleRecAlgo::checkADCSaturation(CastorRecHit& rechit,
0171 const CastorDataFrame& digi,
0172 const int& maxADCvalue) const {
0173 if (CastorSimpleRecAlgoImpl::isSaturated<CastorDataFrame>(digi, maxADCvalue, firstSample_, samplesToAdd_))
0174 rechit.setFlagField(1, HcalCaloFlagLabels::ADCSaturationBit);
0175 }
0176
0177
0178 void CastorSimpleRecAlgo::recoverADCSaturation(CastorRecHit& rechit,
0179 const CastorCoder& coder,
0180 const CastorCalibrations& calibs,
0181 const CastorDataFrame& digi,
0182 const int& maxADCvalue,
0183 const double& satCorrConst) const {
0184 if (CastorSimpleRecAlgoImpl::corrSaturation<CastorDataFrame, CastorRecHit>(
0185 rechit, coder, calibs, digi, maxADCvalue, satCorrConst, firstSample_, samplesToAdd_))
0186
0187
0188 rechit.setFlagField(1, HcalCaloFlagLabels::UserDefinedBit0);
0189 }
0190
0191
0192
0193 static const float wpksamp0_hf = 0.500635;
0194 static const float scale_hf = 0.999301;
0195 static const int num_bins_hf = 100;
0196
0197 static const float actual_ns_hf[num_bins_hf] = {
0198 0.00000,
0199 0.03750,
0200 0.07250,
0201 0.10750,
0202 0.14500,
0203 0.18000,
0204 0.21500,
0205 0.25000,
0206 0.28500,
0207 0.32000,
0208 0.35500,
0209 0.39000,
0210 0.42500,
0211 0.46000,
0212 0.49500,
0213 0.53000,
0214 0.56500,
0215 0.60000,
0216 0.63500,
0217 0.67000,
0218 0.70750,
0219 0.74250,
0220 0.78000,
0221 0.81500,
0222 0.85250,
0223 0.89000,
0224 0.92750,
0225 0.96500,
0226 1.00250,
0227 1.04250,
0228 1.08250,
0229 1.12250,
0230 1.16250,
0231 1.20500,
0232 1.24500,
0233 1.29000,
0234 1.33250,
0235 1.38000,
0236 1.42500,
0237 1.47500,
0238 1.52500,
0239 1.57750,
0240 1.63250,
0241 1.69000,
0242 1.75250,
0243 1.82000,
0244 1.89250,
0245 1.97500,
0246 2.07250,
0247 2.20000,
0248 19.13000,
0249 21.08750,
0250 21.57750,
0251 21.89000,
0252 22.12250,
0253 22.31000,
0254 22.47000,
0255 22.61000,
0256 22.73250,
0257 22.84500,
0258 22.94750,
0259 23.04250,
0260 23.13250,
0261 23.21500,
0262 23.29250,
0263 23.36750,
0264 23.43750,
0265 23.50500,
0266 23.57000,
0267 23.63250,
0268 23.69250,
0269 23.75000,
0270 23.80500,
0271 23.86000,
0272 23.91250,
0273 23.96500,
0274 24.01500,
0275 24.06500,
0276 24.11250,
0277 24.16000,
0278 24.20500,
0279 24.25000,
0280 24.29500,
0281 24.33750,
0282 24.38000,
0283 24.42250,
0284 24.46500,
0285 24.50500,
0286 24.54500,
0287 24.58500,
0288 24.62500,
0289 24.66500,
0290 24.70250,
0291 24.74000,
0292 24.77750,
0293 24.81500,
0294 24.85250,
0295 24.89000,
0296 24.92750,
0297 24.96250,
0298 };
0299
0300 float timeshift_ns_hf(float wpksamp) {
0301 float flx = (num_bins_hf * (wpksamp - wpksamp0_hf) / scale_hf);
0302 int index = (int)flx;
0303 float yval;
0304
0305 if (index < 0)
0306 return actual_ns_hf[0];
0307 else if (index >= num_bins_hf - 1)
0308 return actual_ns_hf[num_bins_hf - 1];
0309
0310
0311 float y1 = actual_ns_hf[index];
0312 float y2 = actual_ns_hf[index + 1];
0313
0314
0315
0316
0317 yval = y1 + (y2 - y1) * (flx - (float)index);
0318 return yval;
0319 }