File indexing completed on 2024-09-07 04:37:35
0001 #ifndef RecoLocalCalo_EcalRecAlgos_EcalUncalibRecHitFixedAlphaBetaAlgo_HH
0002 #define RecoLocalCalo_EcalRecAlgos_EcalUncalibRecHitFixedAlphaBetaAlgo_HH
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include "CLHEP/Matrix/Vector.h"
0015 #include "CLHEP/Matrix/SymMatrix.h"
0016
0017 #include "RecoLocalCalo/EcalRecAlgos/interface/EcalUncalibRecHitRecAbsAlgo.h"
0018
0019 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0020 #include "FWCore/Utilities/interface/isFinite.h"
0021
0022 #include <vector>
0023 #include <string>
0024
0025
0026
0027
0028
0029
0030
0031
0032 template <class C>
0033 class EcalUncalibRecHitFixedAlphaBetaAlgo : public EcalUncalibRecHitRecAbsAlgo<C> {
0034 private:
0035 double MinAmpl_;
0036 bool dyn_pedestal;
0037 double fAlpha_;
0038 double fBeta_;
0039 double fAmp_max_;
0040 double fTim_max_;
0041 double fPed_max_;
0042 double alfabeta_;
0043
0044 int fNb_iter_;
0045 int fNum_samp_bef_max_;
0046 int fNum_samp_after_max_;
0047
0048 float fSigma_ped;
0049 double un_sur_sigma;
0050
0051 float alpha_table_[36][1701];
0052 float beta_table_[36][1701];
0053
0054 bool doFit_;
0055
0056 double pulseShapeFunction(double t);
0057 float PerformAnalyticFit(double* samples, int max_sample);
0058 void InitFitParameters(double* samples, int max_sample);
0059 CLHEP::HepSymMatrix DM1_;
0060 CLHEP::HepVector temp_;
0061
0062 public:
0063 EcalUncalibRecHitFixedAlphaBetaAlgo()
0064 : fAlpha_(0.),
0065 fBeta_(0.),
0066 fAmp_max_(-1.),
0067 fTim_max_(-1),
0068 fPed_max_(0),
0069 alfabeta_(0),
0070 fNb_iter_(4),
0071 fNum_samp_bef_max_(1),
0072 fNum_samp_after_max_(3),
0073 fSigma_ped(1.1),
0074 DM1_(3),
0075 temp_(3) {
0076 un_sur_sigma = 1. / double(fSigma_ped);
0077 for (int i = 0; i < 36; i++) {
0078 for (int j = 0; j < 1701; j++) {
0079 alpha_table_[i][j] = 1.2;
0080 beta_table_[i][j] = 1.7;
0081 }
0082 }
0083 doFit_ = false;
0084 MinAmpl_ = 16;
0085 dyn_pedestal = true;
0086 }
0087 EcalUncalibRecHitFixedAlphaBetaAlgo(int n_iter, int n_bef_max = 1, int n_aft_max = 3, float sigma_ped = 1.1)
0088 : fAlpha_(0.), fBeta_(0.), fAmp_max_(-1.), fTim_max_(-1), fPed_max_(0), alfabeta_(0), DM1_(3), temp_(3) {
0089 fNb_iter_ = n_iter;
0090 fNum_samp_bef_max_ = n_bef_max;
0091 fNum_samp_after_max_ = n_aft_max;
0092 fSigma_ped = sigma_ped;
0093 un_sur_sigma = 1. / double(fSigma_ped);
0094 for (int i = 0; i < 36; i++) {
0095 for (int j = 0; j < 1701; j++) {
0096 alpha_table_[i][j] = 1.2;
0097 beta_table_[i][j] = 1.7;
0098 }
0099 }
0100 doFit_ = false;
0101 MinAmpl_ = 16;
0102 dyn_pedestal = true;
0103 };
0104
0105 ~EcalUncalibRecHitFixedAlphaBetaAlgo() override {}
0106 EcalUncalibratedRecHit makeRecHit(const C& dataFrame,
0107 const double* pedestals,
0108 const double* gainRatios,
0109 const EcalWeightSet::EcalWeightMatrix** weights,
0110 const EcalWeightSet::EcalChi2WeightMatrix** chi2Matrix) override;
0111 void SetAlphaBeta(double alpha, double beta);
0112 void SetMinAmpl(double ampl);
0113 void SetDynamicPedestal(bool dyn_pede);
0114 };
0115
0116
0117 template <class C>
0118 EcalUncalibratedRecHit EcalUncalibRecHitFixedAlphaBetaAlgo<C>::makeRecHit(
0119 const C& dataFrame,
0120 const double* pedestals,
0121 const double* gainRatios,
0122 const EcalWeightSet::EcalWeightMatrix** weights,
0123 const EcalWeightSet::EcalChi2WeightMatrix** chi2Matrix) {
0124 double chi2_(-1.);
0125
0126
0127 double frame[C::MAXSAMPLES];
0128 double pedestal = 0;
0129
0130 int gainId0 = 1;
0131 int iGainSwitch = 0;
0132 int GainId = 0;
0133 double maxsample(-1);
0134 int imax(-1);
0135 bool external_pede = false;
0136 bool isSaturated = false;
0137
0138
0139 if (pedestals) {
0140 external_pede = true;
0141 if (dyn_pedestal) {
0142 pedestal = (double(dataFrame.sample(0).adc()) + double(dataFrame.sample(1).adc())) / 2.;
0143 } else {
0144 pedestal = pedestals[0];
0145 }
0146 for (int iSample = 0; iSample < C::MAXSAMPLES; iSample++) {
0147
0148 GainId = dataFrame.sample(iSample).gainId();
0149
0150
0151
0152
0153 if (GainId == 0) {
0154 GainId = 3;
0155 isSaturated = true;
0156 }
0157
0158 if (GainId != gainId0)
0159 iGainSwitch = 1;
0160
0161 if (GainId == gainId0) {
0162 frame[iSample] = double(dataFrame.sample(iSample).adc()) - pedestal;
0163 } else {
0164 frame[iSample] = (double(dataFrame.sample(iSample).adc()) - pedestals[GainId - 1]) * gainRatios[GainId - 1];
0165 }
0166
0167 if (frame[iSample] > maxsample) {
0168 maxsample = frame[iSample];
0169 imax = iSample;
0170 }
0171 }
0172 } else {
0173 external_pede = false;
0174 pedestal = (double(dataFrame.sample(0).adc()) + double(dataFrame.sample(1).adc())) / 2.;
0175
0176 for (int iSample = 0; iSample < C::MAXSAMPLES; iSample++) {
0177
0178 GainId = dataFrame.sample(iSample).gainId();
0179
0180 if (GainId == 0) {
0181 GainId = 3;
0182 isSaturated = true;
0183 }
0184
0185 frame[iSample] = double(dataFrame.sample(iSample).adc()) - pedestal;
0186
0187 if (GainId > gainId0)
0188 iGainSwitch = 1;
0189 if (frame[iSample] > maxsample) {
0190 maxsample = frame[iSample];
0191 imax = iSample;
0192 }
0193 }
0194 }
0195
0196 if ((iGainSwitch == 1 && external_pede == false) ||
0197 imax == -1) {
0198 return EcalUncalibratedRecHit(dataFrame.id(), -1., -100., -1., -1.);
0199 }
0200
0201 InitFitParameters(frame, imax);
0202 chi2_ = PerformAnalyticFit(frame, imax);
0203 uint32_t flags = 0;
0204 if (isSaturated)
0205 flags = EcalUncalibratedRecHit::kSaturated;
0206
0207
0208
0209
0210 return EcalUncalibratedRecHit(dataFrame.id(), fAmp_max_, pedestal + fPed_max_, fTim_max_ - 5, chi2_, flags);
0211 }
0212
0213 template <class C>
0214 double EcalUncalibRecHitFixedAlphaBetaAlgo<C>::pulseShapeFunction(double t) {
0215 if (alfabeta_ <= 0)
0216 return ((double)0.);
0217 double dtsbeta, variable, puiss;
0218 double dt = t - fTim_max_;
0219 if (dt > -alfabeta_) {
0220 dtsbeta = dt / fBeta_;
0221 variable = 1. + dt / alfabeta_;
0222 puiss = pow(variable, fAlpha_);
0223 return fAmp_max_ * puiss * exp(-dtsbeta) + fPed_max_;
0224 }
0225 return fPed_max_;
0226 }
0227
0228 template <class C>
0229 void EcalUncalibRecHitFixedAlphaBetaAlgo<C>::InitFitParameters(double* samples, int max_sample) {
0230
0231 fAmp_max_ = samples[max_sample];
0232 fTim_max_ = max_sample;
0233 fPed_max_ = 0;
0234
0235
0236
0237 if (fAmp_max_ < MinAmpl_) {
0238 fAmp_max_ = samples[5];
0239 double sumA = samples[5] + samples[4] + samples[6];
0240 if (sumA != 0) {
0241 fTim_max_ = 5 + (samples[6] - samples[4]) / sumA;
0242 } else {
0243 fTim_max_ = -993;
0244 }
0245 doFit_ = false;
0246 }
0247
0248 else if (max_sample < 1 || max_sample > 7) {
0249 doFit_ = false;
0250 } else {
0251
0252 doFit_ = true;
0253 float a = float(samples[max_sample - 1] + samples[max_sample + 1] - 2 * samples[max_sample]) / 2.;
0254 if (a == 0) {
0255 doFit_ = false;
0256 return;
0257 }
0258 float b = float(samples[max_sample + 1] - samples[max_sample - 1]) / 2.;
0259
0260 fTim_max_ = max_sample - b / (2 * a);
0261 fAmp_max_ = samples[max_sample] - b * b / (4 * a);
0262 }
0263 }
0264
0265 template <class C>
0266 float EcalUncalibRecHitFixedAlphaBetaAlgo<C>::PerformAnalyticFit(double* samples, int max_sample) {
0267
0268
0269
0270
0271
0272
0273
0274 double chi2 = -1, db[3];
0275
0276
0277
0278 int num_fit_min = (int)(max_sample - fNum_samp_bef_max_);
0279 int num_fit_max = (int)(max_sample + fNum_samp_after_max_);
0280
0281 if (num_fit_min < 0)
0282 num_fit_min = 0;
0283
0284 if (num_fit_max >= C::MAXSAMPLES) {
0285 num_fit_max = C::MAXSAMPLES - 1;
0286 }
0287
0288 if (!doFit_) {
0289 LogDebug("EcalUncalibRecHitFixedAlphaBetaAlgo") << "No fit performed. The amplitude of sample 5 will be used";
0290 return -1;
0291 }
0292
0293 double func, delta;
0294 double variation_func_max = 0.;
0295 double variation_tim_max = 0.;
0296 double variation_ped_max = 0.;
0297
0298 for (int iter = 0; iter < fNb_iter_; iter++) {
0299
0300 chi2 = 0.;
0301
0302 for (int i1 = 0; i1 < 3; i1++) {
0303 temp_[i1] = 0;
0304 for (int j1 = i1; j1 < 3; j1++) {
0305 DM1_.fast(j1 + 1, i1 + 1) = 0;
0306 }
0307 }
0308
0309 fAmp_max_ += variation_func_max;
0310 fTim_max_ += variation_tim_max;
0311 fPed_max_ += variation_ped_max;
0312
0313
0314 for (int i = num_fit_min; i <= num_fit_max; i++) {
0315
0316
0317 func = pulseShapeFunction((double)i);
0318
0319 double dt = (double)i - fTim_max_;
0320 if (dt > -alfabeta_) {
0321 double dt_sur_beta = dt / fBeta_;
0322 double variable = (double)1. + dt / alfabeta_;
0323 double expo = exp(-dt_sur_beta);
0324 double puissance = pow(variable, fAlpha_);
0325
0326 db[0] = un_sur_sigma * puissance * expo;
0327 db[1] = fAmp_max_ * db[0] * dt_sur_beta / (alfabeta_ * variable);
0328 } else {
0329 db[0] = 0.;
0330 db[1] = 0.;
0331 }
0332 db[2] = un_sur_sigma;
0333
0334 for (int i1 = 0; i1 < 3; i1++) {
0335 for (int j1 = i1; j1 < 3; j1++) {
0336
0337 DM1_.fast(j1 + 1, i1 + 1) += db[i1] * db[j1];
0338 }
0339 }
0340
0341 delta = (samples[i] - func) * un_sur_sigma;
0342
0343 for (int ii = 0; ii < 3; ii++) {
0344 temp_[ii] += delta * db[ii];
0345 }
0346 chi2 += delta * delta;
0347 }
0348
0349 int fail = 0;
0350 DM1_.invert(fail);
0351 if (fail != 0.) {
0352
0353
0354 InitFitParameters(samples, max_sample);
0355 return -101;
0356 }
0357
0358
0359
0360
0361
0362
0363
0364 CLHEP::HepVector PROD = DM1_ * temp_;
0365
0366
0367
0368
0369
0370 if (edm::isNotFinite(PROD[0])) {
0371 InitFitParameters(samples, max_sample);
0372 return -103;
0373 }
0374
0375 variation_func_max = PROD[0];
0376 variation_tim_max = PROD[1];
0377 variation_ped_max = PROD[2];
0378
0379 }
0380
0381
0382 if (variation_func_max > 2000. || variation_func_max < -1000.) {
0383 InitFitParameters(samples, max_sample);
0384 return -102;
0385 }
0386
0387
0388 fAmp_max_ += variation_func_max;
0389 fTim_max_ += variation_tim_max;
0390 fPed_max_ += variation_ped_max;
0391
0392
0393
0394 if (fAmp_max_ > 2 * samples[max_sample] || fAmp_max_ < -100 || fTim_max_ < 0 || 9 < fTim_max_) {
0395 InitFitParameters(samples, max_sample);
0396 return -104;
0397 }
0398
0399
0400 return chi2;
0401 }
0402
0403 template <class C>
0404 void EcalUncalibRecHitFixedAlphaBetaAlgo<C>::SetAlphaBeta(double alpha, double beta) {
0405 fAlpha_ = alpha;
0406 fBeta_ = beta;
0407 alfabeta_ = fAlpha_ * fBeta_;
0408 }
0409
0410 template <class C>
0411 void EcalUncalibRecHitFixedAlphaBetaAlgo<C>::SetMinAmpl(double ampl) {
0412 MinAmpl_ = ampl;
0413 }
0414 template <class C>
0415 void EcalUncalibRecHitFixedAlphaBetaAlgo<C>::SetDynamicPedestal(bool p) {
0416 dyn_pedestal = p;
0417 }
0418 #endif