File indexing completed on 2024-04-06 12:25:50
0001 #include <iostream>
0002 #include <cmath>
0003 #include <climits>
0004 #include "RecoLocalCalo/HcalRecAlgos/interface/PulseShapeFunctor.h"
0005 #include "FWCore/Utilities/interface/isFinite.h"
0006
0007 namespace FitterFuncs {
0008
0009
0010 PulseShapeFunctor::PulseShapeFunctor(const HcalPulseShapes::Shape &pulse,
0011 bool iPedestalConstraint,
0012 bool iTimeConstraint,
0013 bool iAddPulseJitter,
0014 double iPulseJitter,
0015 double iTimeMean,
0016 double iPedMean,
0017 unsigned nSamplesToFit)
0018 : cntNANinfit(0),
0019 acc25nsVec_(hcal::constants::maxPSshapeBin),
0020 diff25nsItvlVec_(hcal::constants::maxPSshapeBin),
0021 accVarLenIdxZEROVec_(hcal::constants::nsPerBX),
0022 diffVarItvlIdxZEROVec_(hcal::constants::nsPerBX),
0023 accVarLenIdxMinusOneVec_(hcal::constants::nsPerBX),
0024 diffVarItvlIdxMinusOneVec_(hcal::constants::nsPerBX) {
0025
0026 for (int i = 0; i < hcal::constants::maxPSshapeBin; ++i)
0027 pulse_hist[i] = pulse(i);
0028
0029 for (int i = 0; i < hcal::constants::maxPSshapeBin; ++i) {
0030 for (int j = i; j < i + hcal::constants::nsPerBX; ++j) {
0031 acc25nsVec_[i] +=
0032 (j < hcal::constants::maxPSshapeBin ? pulse_hist[j] : pulse_hist[hcal::constants::maxPSshapeBin - 1]);
0033 }
0034 diff25nsItvlVec_[i] = (i + hcal::constants::nsPerBX < hcal::constants::maxPSshapeBin
0035 ? pulse_hist[i + hcal::constants::nsPerBX] - pulse_hist[i]
0036 : pulse_hist[hcal::constants::maxPSshapeBin - 1] - pulse_hist[i]);
0037 }
0038
0039 for (int i = 0; i < hcal::constants::nsPerBX; ++i) {
0040 if (i == 0) {
0041 accVarLenIdxZEROVec_[0] = pulse_hist[0];
0042 accVarLenIdxMinusOneVec_[i] = pulse_hist[0];
0043 } else {
0044 accVarLenIdxZEROVec_[i] = accVarLenIdxZEROVec_[i - 1] + pulse_hist[i];
0045 accVarLenIdxMinusOneVec_[i] = accVarLenIdxMinusOneVec_[i - 1] + pulse_hist[i - 1];
0046 }
0047 diffVarItvlIdxZEROVec_[i] = pulse_hist[i + 1] - pulse_hist[0];
0048 diffVarItvlIdxMinusOneVec_[i] = pulse_hist[i] - pulse_hist[0];
0049 }
0050 for (int i = 0; i < hcal::constants::maxSamples; i++) {
0051 psFit_x[i] = 0;
0052 psFit_y[i] = 0;
0053 psFit_erry[i] = 1.;
0054 psFit_erry2[i] = 1.;
0055 psFit_slew[i] = 0.;
0056 }
0057
0058 pedestalConstraint_ = iPedestalConstraint;
0059 timeConstraint_ = iTimeConstraint;
0060 addPulseJitter_ = iAddPulseJitter;
0061 pulseJitter_ = iPulseJitter * iPulseJitter;
0062
0063
0064 timeMean_ = iTimeMean;
0065 pedMean_ = iPedMean;
0066 timeShift_ = 100.;
0067 timeShift_ += 12.5;
0068
0069 nSamplesToFit_ = nSamplesToFit;
0070 }
0071
0072 void PulseShapeFunctor::funcShape(std::array<double, hcal::constants::maxSamples> &ntmpbin,
0073 const double pulseTime,
0074 const double pulseHeight,
0075 const double slew,
0076 bool scalePulse) {
0077
0078 constexpr int ns_per_bx = hcal::constants::nsPerBX;
0079
0080 int i_start = (-hcal::constants::iniTimeShift - pulseTime - slew > 0
0081 ? 0
0082 : (int)std::abs(-hcal::constants::iniTimeShift - pulseTime - slew) + 1);
0083 double offset_start = i_start - hcal::constants::iniTimeShift - pulseTime -
0084 slew;
0085
0086 ntmpbin.fill(0.0f);
0087
0088 if (edm::isNotFinite(offset_start)) {
0089 ++cntNANinfit;
0090 } else {
0091 if (offset_start == 1.0) {
0092 offset_start = 0.;
0093 i_start -= 1;
0094 }
0095
0096 const int bin_start = (int)offset_start;
0097 const int bin_0_start = (offset_start < bin_start + 0.5 ? bin_start - 1 : bin_start);
0098 const int iTS_start = i_start / ns_per_bx;
0099 const int distTo25ns_start = ns_per_bx - 1 - i_start % ns_per_bx;
0100 const double factor = offset_start - bin_0_start - 0.5;
0101
0102
0103 ntmpbin[iTS_start] =
0104 (bin_0_start == -1
0105 ?
0106 accVarLenIdxMinusOneVec_[distTo25ns_start] + factor * diffVarItvlIdxMinusOneVec_[distTo25ns_start]
0107 : accVarLenIdxZEROVec_[distTo25ns_start] + factor * diffVarItvlIdxZEROVec_[distTo25ns_start]);
0108
0109 for (int iTS = iTS_start + 1; iTS < hcal::constants::maxSamples; ++iTS) {
0110 int bin_idx = distTo25ns_start + 1 + (iTS - iTS_start - 1) * ns_per_bx + bin_0_start;
0111 ntmpbin[iTS] = acc25nsVec_[bin_idx] + factor * diff25nsItvlVec_[bin_idx];
0112 }
0113
0114 if (scalePulse) {
0115 for (int i = iTS_start; i < hcal::constants::maxSamples; ++i) {
0116 ntmpbin[i] *= pulseHeight;
0117 }
0118 }
0119 }
0120
0121 return;
0122 }
0123
0124 PulseShapeFunctor::~PulseShapeFunctor() {}
0125
0126 void PulseShapeFunctor::EvalPulse(const float *pars) {
0127 int time = (pars[0] + timeShift_ - timeMean_) * hcal::constants::invertnsPerBx;
0128 float dummyPulseHeight = 0.f;
0129 funcShape(pulse_shape_, pars[0], dummyPulseHeight, psFit_slew[time], false);
0130 return;
0131 }
0132
0133 double PulseShapeFunctor::EvalPulseM2(const double *pars, const unsigned nPars) {
0134 unsigned i = 0, j = 0;
0135
0136 const double pedestal = pars[nPars - 1];
0137
0138
0139 for (i = 0; i < nPars; ++i)
0140 if (edm::isNotFinite(pars[i])) {
0141 ++cntNANinfit;
0142 return 1e10;
0143 }
0144
0145
0146 double chisq = 0;
0147 const unsigned parBy2 = (nPars - 1) / 2;
0148
0149
0150 if (addPulseJitter_) {
0151 int time = (pars[0] + timeShift_ - timeMean_) * hcal::constants::invertnsPerBx;
0152
0153 funcShape(pulse_shape_, pars[0], pars[1], psFit_slew[time], true);
0154 for (j = 0; j < nSamplesToFit_; ++j) {
0155 psFit_erry2[j] += pulse_shape_[j] * pulse_shape_[j] * pulseJitter_;
0156 pulse_shape_sum_[j] = pulse_shape_[j] + pedestal;
0157 }
0158
0159 for (i = 1; i < parBy2; ++i) {
0160 time = (pars[i * 2] + timeShift_ - timeMean_) * hcal::constants::invertnsPerBx;
0161
0162 funcShape(pulse_shape_, pars[i * 2], pars[i * 2 + 1], psFit_slew[time], true);
0163
0164
0165 for (j = 0; j < nSamplesToFit_; ++j) {
0166 psFit_erry2[j] += pulse_shape_[j] * pulse_shape_[j] * pulseJitter_;
0167 pulse_shape_sum_[j] += pulse_shape_[j];
0168 }
0169 }
0170 } else {
0171 int time = (pars[0] + timeShift_ - timeMean_) * hcal::constants::invertnsPerBx;
0172
0173 funcShape(pulse_shape_, pars[0], pars[1], psFit_slew[time], true);
0174 for (j = 0; j < nSamplesToFit_; ++j)
0175 pulse_shape_sum_[j] = pulse_shape_[j] + pedestal;
0176
0177 for (i = 1; i < parBy2; ++i) {
0178 time = (pars[i * 2] + timeShift_ - timeMean_) * hcal::constants::invertnsPerBx;
0179
0180 funcShape(pulse_shape_, pars[i * 2], pars[i * 2 + 1], psFit_slew[time], true);
0181
0182 for (j = 0; j < nSamplesToFit_; ++j)
0183 pulse_shape_sum_[j] += pulse_shape_[j];
0184 }
0185 }
0186
0187 for (i = 0; i < nSamplesToFit_; ++i) {
0188 const double d = psFit_y[i] - pulse_shape_sum_[i];
0189 chisq += d * d / psFit_erry2[i];
0190 }
0191
0192 if (pedestalConstraint_) {
0193
0194 chisq += invertpedSig2_ * (pedestal - pedMean_) * (pedestal - pedMean_);
0195 }
0196
0197 if (timeConstraint_) {
0198 for (j = 0; j < parBy2; ++j) {
0199 int time = (pars[j * 2] + timeShift_ - timeMean_) * (double)hcal::constants::invertnsPerBx;
0200 double time1 = -100. + time * hcal::constants::nsPerBX;
0201 chisq += inverttimeSig2_ * (pars[j * 2] - timeMean_ - time1) * (pars[j * 2] - timeMean_ - time1);
0202 }
0203 }
0204 return chisq;
0205 }
0206 }