Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 10:00:00

0001 /** \class EcalUncalibRecHitRecGlobalAlgo
0002  *  Template used to compute amplitude, pedestal using a weights method
0003  *                           time using a ratio method
0004  *                           chi2 using express method
0005  *
0006  *  \author R. Bruneliere - A. Zabi
0007  */
0008 
0009 #include "CondFormats/DataRecord/interface/EcalGainRatiosRcd.h"
0010 #include "CondFormats/DataRecord/interface/EcalPedestalsRcd.h"
0011 #include "CondFormats/DataRecord/interface/EcalPulseCovariancesRcd.h"
0012 #include "CondFormats/DataRecord/interface/EcalPulseShapesRcd.h"
0013 #include "CondFormats/DataRecord/interface/EcalSampleMaskRcd.h"
0014 #include "CondFormats/DataRecord/interface/EcalSamplesCorrelationRcd.h"
0015 #include "CondFormats/DataRecord/interface/EcalTBWeightsRcd.h"
0016 #include "CondFormats/DataRecord/interface/EcalTimeBiasCorrectionsRcd.h"
0017 #include "CondFormats/DataRecord/interface/EcalTimeCalibConstantsRcd.h"
0018 #include "CondFormats/DataRecord/interface/EcalTimeOffsetConstantRcd.h"
0019 #include "CondFormats/DataRecord/interface/EcalWeightXtalGroupsRcd.h"
0020 #include "CondFormats/EcalObjects/interface/EcalGainRatios.h"
0021 #include "CondFormats/EcalObjects/interface/EcalPedestals.h"
0022 #include "CondFormats/EcalObjects/interface/EcalPulseCovariances.h"
0023 #include "CondFormats/EcalObjects/interface/EcalPulseShapes.h"
0024 #include "CondFormats/EcalObjects/interface/EcalSampleMask.h"
0025 #include "CondFormats/EcalObjects/interface/EcalSamplesCorrelation.h"
0026 #include "CondFormats/EcalObjects/interface/EcalTBWeights.h"
0027 #include "CondFormats/EcalObjects/interface/EcalTimeBiasCorrections.h"
0028 #include "CondFormats/EcalObjects/interface/EcalTimeCalibConstants.h"
0029 #include "CondFormats/EcalObjects/interface/EcalTimeOffsetConstant.h"
0030 #include "CondFormats/EcalObjects/interface/EcalWeightXtalGroups.h"
0031 #include "FWCore/Framework/interface/ESHandle.h"
0032 #include "FWCore/Framework/interface/Event.h"
0033 #include "FWCore/Framework/interface/EventSetup.h"
0034 #include "FWCore/Framework/interface/Run.h"
0035 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0036 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0037 #include "FWCore/ParameterSet/interface/EmptyGroupDescription.h"
0038 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0039 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0040 #include "FWCore/Utilities/interface/ESGetToken.h"
0041 #include "FWCore/Utilities/interface/ESInputTag.h"
0042 #include "RecoLocalCalo/EcalRecAlgos/interface/EcalUncalibRecHitMultiFitAlgo.h"
0043 #include "RecoLocalCalo/EcalRecAlgos/interface/EcalUncalibRecHitRatioMethodAlgo.h"
0044 #include "RecoLocalCalo/EcalRecAlgos/interface/EcalUncalibRecHitRecChi2Algo.h"
0045 #include "RecoLocalCalo/EcalRecAlgos/interface/EcalUncalibRecHitTimeWeightsAlgo.h"
0046 #include "RecoLocalCalo/EcalRecAlgos/interface/EcalUncalibRecHitTimingCCAlgo.h"
0047 #include "RecoLocalCalo/EcalRecAlgos/interface/EigenMatrixTypes.h"
0048 #include "RecoLocalCalo/EcalRecProducers/interface/EcalUncalibRecHitWorkerBaseClass.h"
0049 
0050 class EcalUncalibRecHitWorkerMultiFit final : public EcalUncalibRecHitWorkerBaseClass {
0051 public:
0052   EcalUncalibRecHitWorkerMultiFit(const edm::ParameterSet&, edm::ConsumesCollector& c);
0053   EcalUncalibRecHitWorkerMultiFit(){};
0054 
0055 private:
0056   void set(const edm::EventSetup& es) override;
0057   void set(const edm::Event& evt) override;
0058   void run(const edm::Event& evt, const EcalDigiCollection& digis, EcalUncalibratedRecHitCollection& result) override;
0059 
0060 public:
0061   edm::ParameterSetDescription getAlgoDescription() override;
0062 
0063 private:
0064   edm::ESHandle<EcalPedestals> peds;
0065   edm::ESGetToken<EcalPedestals, EcalPedestalsRcd> pedsToken_;
0066   edm::ESHandle<EcalGainRatios> gains;
0067   edm::ESGetToken<EcalGainRatios, EcalGainRatiosRcd> gainsToken_;
0068   edm::ESHandle<EcalSamplesCorrelation> noisecovariances;
0069   edm::ESGetToken<EcalSamplesCorrelation, EcalSamplesCorrelationRcd> noiseConvariancesToken_;
0070   edm::ESHandle<EcalPulseShapes> pulseshapes;
0071   edm::ESGetToken<EcalPulseShapes, EcalPulseShapesRcd> pulseShapesToken_;
0072   edm::ESHandle<EcalPulseCovariances> pulsecovariances;
0073   edm::ESGetToken<EcalPulseCovariances, EcalPulseCovariancesRcd> pulseConvariancesToken_;
0074 
0075   double timeCorrection(float ampli, const std::vector<float>& amplitudeBins, const std::vector<float>& shiftBins);
0076 
0077   const SampleMatrix& noisecor(bool barrel, int gain) const { return noisecors_[barrel ? 1 : 0][gain]; }
0078   const SampleMatrixGainArray& noisecor(bool barrel) const { return noisecors_[barrel ? 1 : 0]; }
0079 
0080   // multifit method
0081   std::array<SampleMatrixGainArray, 2> noisecors_;
0082   BXVector activeBX;
0083   bool ampErrorCalculation_;
0084   bool useLumiInfoRunHeader_;
0085   EcalUncalibRecHitMultiFitAlgo multiFitMethod_;
0086 
0087   int bunchSpacingManual_;
0088   edm::EDGetTokenT<unsigned int> bunchSpacing_;
0089 
0090   // determine which of the samples must actually be used by ECAL local reco
0091   edm::ESHandle<EcalSampleMask> sampleMaskHand_;
0092   edm::ESGetToken<EcalSampleMask, EcalSampleMaskRcd> sampleMaskToken_;
0093 
0094   // time algorithm to be used to set the jitter and its uncertainty
0095   enum TimeAlgo { noMethod, ratioMethod, weightsMethod, crossCorrelationMethod };
0096   TimeAlgo timealgo_ = noMethod;
0097 
0098   // time weights method
0099   edm::ESHandle<EcalWeightXtalGroups> grps;
0100   edm::ESGetToken<EcalWeightXtalGroups, EcalWeightXtalGroupsRcd> grpsToken_;
0101   edm::ESHandle<EcalTBWeights> wgts;
0102   edm::ESGetToken<EcalTBWeights, EcalTBWeightsRcd> wgtsToken_;
0103   const EcalWeightSet::EcalWeightMatrix* weights[2];
0104   EcalUncalibRecHitTimeWeightsAlgo<EBDataFrame> weightsMethod_barrel_;
0105   EcalUncalibRecHitTimeWeightsAlgo<EEDataFrame> weightsMethod_endcap_;
0106   bool doPrefitEB_;
0107   bool doPrefitEE_;
0108   double prefitMaxChiSqEB_;
0109   double prefitMaxChiSqEE_;
0110   bool dynamicPedestalsEB_;
0111   bool dynamicPedestalsEE_;
0112   bool mitigateBadSamplesEB_;
0113   bool mitigateBadSamplesEE_;
0114   bool gainSwitchUseMaxSampleEB_;
0115   bool gainSwitchUseMaxSampleEE_;
0116   bool selectiveBadSampleCriteriaEB_;
0117   bool selectiveBadSampleCriteriaEE_;
0118   double addPedestalUncertaintyEB_;
0119   double addPedestalUncertaintyEE_;
0120   bool simplifiedNoiseModelForGainSwitch_;
0121 
0122   // ratio method
0123   std::vector<double> EBtimeFitParameters_;
0124   std::vector<double> EEtimeFitParameters_;
0125   std::vector<double> EBamplitudeFitParameters_;
0126   std::vector<double> EEamplitudeFitParameters_;
0127   std::pair<double, double> EBtimeFitLimits_;
0128   std::pair<double, double> EEtimeFitLimits_;
0129 
0130   EcalUncalibRecHitRatioMethodAlgo<EBDataFrame> ratioMethod_barrel_;
0131   EcalUncalibRecHitRatioMethodAlgo<EEDataFrame> ratioMethod_endcap_;
0132 
0133   double EBtimeConstantTerm_;
0134   double EEtimeConstantTerm_;
0135   double EBtimeNconst_;
0136   double EEtimeNconst_;
0137   double outOfTimeThreshG12pEB_;
0138   double outOfTimeThreshG12mEB_;
0139   double outOfTimeThreshG61pEB_;
0140   double outOfTimeThreshG61mEB_;
0141   double outOfTimeThreshG12pEE_;
0142   double outOfTimeThreshG12mEE_;
0143   double outOfTimeThreshG61pEE_;
0144   double outOfTimeThreshG61mEE_;
0145   double amplitudeThreshEB_;
0146   double amplitudeThreshEE_;
0147   double ebSpikeThresh_;
0148 
0149   edm::ESHandle<EcalTimeBiasCorrections> timeCorrBias_;
0150   edm::ESGetToken<EcalTimeBiasCorrections, EcalTimeBiasCorrectionsRcd> timeCorrBiasToken_;
0151 
0152   edm::ESHandle<EcalTimeCalibConstants> itime;
0153   edm::ESGetToken<EcalTimeCalibConstants, EcalTimeCalibConstantsRcd> itimeToken_;
0154   edm::ESHandle<EcalTimeOffsetConstant> offtime;
0155   edm::ESGetToken<EcalTimeOffsetConstant, EcalTimeOffsetConstantRcd> offtimeToken_;
0156   std::vector<double> ebPulseShape_;
0157   std::vector<double> eePulseShape_;
0158 
0159   // chi2 thresholds for flags settings
0160   bool kPoorRecoFlagEB_;
0161   bool kPoorRecoFlagEE_;
0162   double chi2ThreshEB_;
0163   double chi2ThreshEE_;
0164 
0165   //Timing Cross Correlation Algo
0166   std::unique_ptr<EcalUncalibRecHitTimingCCAlgo> computeCC_;
0167   double CCminTimeToBeLateMin_;
0168   double CCminTimeToBeLateMax_;
0169   double CCTimeShiftWrtRations_;
0170   double CCtargetTimePrecision_;
0171   double CCtargetTimePrecisionForDelayedPulses_;
0172 };
0173 
0174 EcalUncalibRecHitWorkerMultiFit::EcalUncalibRecHitWorkerMultiFit(const edm::ParameterSet& ps, edm::ConsumesCollector& c)
0175     : EcalUncalibRecHitWorkerBaseClass(ps, c) {
0176   // get the BX for the pulses to be activated
0177   std::vector<int32_t> activeBXs = ps.getParameter<std::vector<int32_t>>("activeBXs");
0178   activeBX.resize(activeBXs.size());
0179   for (unsigned int ibx = 0; ibx < activeBXs.size(); ++ibx) {
0180     activeBX.coeffRef(ibx) = activeBXs[ibx];
0181   }
0182 
0183   // uncertainty calculation (CPU intensive)
0184   ampErrorCalculation_ = ps.getParameter<bool>("ampErrorCalculation");
0185   useLumiInfoRunHeader_ = ps.getParameter<bool>("useLumiInfoRunHeader");
0186 
0187   if (useLumiInfoRunHeader_) {
0188     bunchSpacing_ = c.consumes<unsigned int>(edm::InputTag("bunchSpacingProducer"));
0189     bunchSpacingManual_ = 0;
0190   } else {
0191     bunchSpacingManual_ = ps.getParameter<int>("bunchSpacing");
0192   }
0193 
0194   doPrefitEB_ = ps.getParameter<bool>("doPrefitEB");
0195   doPrefitEE_ = ps.getParameter<bool>("doPrefitEE");
0196 
0197   prefitMaxChiSqEB_ = ps.getParameter<double>("prefitMaxChiSqEB");
0198   prefitMaxChiSqEE_ = ps.getParameter<double>("prefitMaxChiSqEE");
0199 
0200   dynamicPedestalsEB_ = ps.getParameter<bool>("dynamicPedestalsEB");
0201   dynamicPedestalsEE_ = ps.getParameter<bool>("dynamicPedestalsEE");
0202   mitigateBadSamplesEB_ = ps.getParameter<bool>("mitigateBadSamplesEB");
0203   mitigateBadSamplesEE_ = ps.getParameter<bool>("mitigateBadSamplesEE");
0204   gainSwitchUseMaxSampleEB_ = ps.getParameter<bool>("gainSwitchUseMaxSampleEB");
0205   gainSwitchUseMaxSampleEE_ = ps.getParameter<bool>("gainSwitchUseMaxSampleEE");
0206   selectiveBadSampleCriteriaEB_ = ps.getParameter<bool>("selectiveBadSampleCriteriaEB");
0207   selectiveBadSampleCriteriaEE_ = ps.getParameter<bool>("selectiveBadSampleCriteriaEE");
0208   addPedestalUncertaintyEB_ = ps.getParameter<double>("addPedestalUncertaintyEB");
0209   addPedestalUncertaintyEE_ = ps.getParameter<double>("addPedestalUncertaintyEE");
0210   simplifiedNoiseModelForGainSwitch_ = ps.getParameter<bool>("simplifiedNoiseModelForGainSwitch");
0211   pedsToken_ = c.esConsumes<EcalPedestals, EcalPedestalsRcd>();
0212   gainsToken_ = c.esConsumes<EcalGainRatios, EcalGainRatiosRcd>();
0213   noiseConvariancesToken_ = c.esConsumes<EcalSamplesCorrelation, EcalSamplesCorrelationRcd>();
0214   pulseShapesToken_ = c.esConsumes<EcalPulseShapes, EcalPulseShapesRcd>();
0215   pulseConvariancesToken_ = c.esConsumes<EcalPulseCovariances, EcalPulseCovariancesRcd>();
0216   sampleMaskToken_ = c.esConsumes<EcalSampleMask, EcalSampleMaskRcd>();
0217   grpsToken_ = c.esConsumes<EcalWeightXtalGroups, EcalWeightXtalGroupsRcd>();
0218   wgtsToken_ = c.esConsumes<EcalTBWeights, EcalTBWeightsRcd>();
0219   timeCorrBiasToken_ = c.esConsumes<EcalTimeBiasCorrections, EcalTimeBiasCorrectionsRcd>();
0220   itimeToken_ =
0221       c.esConsumes<EcalTimeCalibConstants, EcalTimeCalibConstantsRcd>(ps.getParameter<edm::ESInputTag>("timeCalibTag"));
0222   offtimeToken_ = c.esConsumes<EcalTimeOffsetConstant, EcalTimeOffsetConstantRcd>(
0223       ps.getParameter<edm::ESInputTag>("timeOffsetTag"));
0224 
0225   // algorithm to be used for timing
0226   auto const& timeAlgoName = ps.getParameter<std::string>("timealgo");
0227   if (timeAlgoName == "RatioMethod")
0228     timealgo_ = ratioMethod;
0229   else if (timeAlgoName == "WeightsMethod")
0230     timealgo_ = weightsMethod;
0231   else if (timeAlgoName == "crossCorrelationMethod") {
0232     timealgo_ = crossCorrelationMethod;
0233     double startTime = ps.getParameter<double>("crossCorrelationStartTime");
0234     double stopTime = ps.getParameter<double>("crossCorrelationStopTime");
0235     CCtargetTimePrecision_ = ps.getParameter<double>("crossCorrelationTargetTimePrecision");
0236     CCtargetTimePrecisionForDelayedPulses_ =
0237         ps.getParameter<double>("crossCorrelationTargetTimePrecisionForDelayedPulses");
0238     CCminTimeToBeLateMin_ = ps.getParameter<double>("crossCorrelationMinTimeToBeLateMin") / ecalcctiming::clockToNS;
0239     CCminTimeToBeLateMax_ = ps.getParameter<double>("crossCorrelationMinTimeToBeLateMax") / ecalcctiming::clockToNS;
0240     CCTimeShiftWrtRations_ = ps.getParameter<double>("crossCorrelationTimeShiftWrtRations");
0241     computeCC_ = std::make_unique<EcalUncalibRecHitTimingCCAlgo>(startTime, stopTime);
0242   } else if (timeAlgoName != "None")
0243     edm::LogError("EcalUncalibRecHitError") << "No time estimation algorithm defined";
0244 
0245   // ratio method parameters
0246   EBtimeFitParameters_ = ps.getParameter<std::vector<double>>("EBtimeFitParameters");
0247   EEtimeFitParameters_ = ps.getParameter<std::vector<double>>("EEtimeFitParameters");
0248   EBamplitudeFitParameters_ = ps.getParameter<std::vector<double>>("EBamplitudeFitParameters");
0249   EEamplitudeFitParameters_ = ps.getParameter<std::vector<double>>("EEamplitudeFitParameters");
0250   EBtimeFitLimits_.first = ps.getParameter<double>("EBtimeFitLimits_Lower");
0251   EBtimeFitLimits_.second = ps.getParameter<double>("EBtimeFitLimits_Upper");
0252   EEtimeFitLimits_.first = ps.getParameter<double>("EEtimeFitLimits_Lower");
0253   EEtimeFitLimits_.second = ps.getParameter<double>("EEtimeFitLimits_Upper");
0254   EBtimeConstantTerm_ = ps.getParameter<double>("EBtimeConstantTerm");
0255   EEtimeConstantTerm_ = ps.getParameter<double>("EEtimeConstantTerm");
0256   EBtimeNconst_ = ps.getParameter<double>("EBtimeNconst");
0257   EEtimeNconst_ = ps.getParameter<double>("EEtimeNconst");
0258   outOfTimeThreshG12pEB_ = ps.getParameter<double>("outOfTimeThresholdGain12pEB");
0259   outOfTimeThreshG12mEB_ = ps.getParameter<double>("outOfTimeThresholdGain12mEB");
0260   outOfTimeThreshG61pEB_ = ps.getParameter<double>("outOfTimeThresholdGain61pEB");
0261   outOfTimeThreshG61mEB_ = ps.getParameter<double>("outOfTimeThresholdGain61mEB");
0262   outOfTimeThreshG12pEE_ = ps.getParameter<double>("outOfTimeThresholdGain12pEE");
0263   outOfTimeThreshG12mEE_ = ps.getParameter<double>("outOfTimeThresholdGain12mEE");
0264   outOfTimeThreshG61pEE_ = ps.getParameter<double>("outOfTimeThresholdGain61pEE");
0265   outOfTimeThreshG61mEE_ = ps.getParameter<double>("outOfTimeThresholdGain61mEE");
0266   amplitudeThreshEB_ = ps.getParameter<double>("amplitudeThresholdEB");
0267   amplitudeThreshEE_ = ps.getParameter<double>("amplitudeThresholdEE");
0268 }
0269 
0270 void EcalUncalibRecHitWorkerMultiFit::set(const edm::EventSetup& es) {
0271   // common setup
0272   gains = es.getHandle(gainsToken_);
0273   peds = es.getHandle(pedsToken_);
0274 
0275   // for the multifit method
0276   if (!ampErrorCalculation_)
0277     multiFitMethod_.disableErrorCalculation();
0278   noisecovariances = es.getHandle(noiseConvariancesToken_);
0279   pulseshapes = es.getHandle(pulseShapesToken_);
0280   pulsecovariances = es.getHandle(pulseConvariancesToken_);
0281 
0282   // weights parameters for the time
0283   grps = es.getHandle(grpsToken_);
0284   wgts = es.getHandle(wgtsToken_);
0285 
0286   // which of the samples need be used
0287   sampleMaskHand_ = es.getHandle(sampleMaskToken_);
0288 
0289   // for the ratio method
0290   itime = es.getHandle(itimeToken_);
0291   offtime = es.getHandle(offtimeToken_);
0292 
0293   // for the time correction methods
0294   timeCorrBias_ = es.getHandle(timeCorrBiasToken_);
0295 
0296   int nnoise = SampleVector::RowsAtCompileTime;
0297   SampleMatrix& noisecorEBg12 = noisecors_[1][0];
0298   SampleMatrix& noisecorEBg6 = noisecors_[1][1];
0299   SampleMatrix& noisecorEBg1 = noisecors_[1][2];
0300   SampleMatrix& noisecorEEg12 = noisecors_[0][0];
0301   SampleMatrix& noisecorEEg6 = noisecors_[0][1];
0302   SampleMatrix& noisecorEEg1 = noisecors_[0][2];
0303 
0304   for (int i = 0; i < nnoise; ++i) {
0305     for (int j = 0; j < nnoise; ++j) {
0306       int vidx = std::abs(j - i);
0307       noisecorEBg12(i, j) = noisecovariances->EBG12SamplesCorrelation[vidx];
0308       noisecorEEg12(i, j) = noisecovariances->EEG12SamplesCorrelation[vidx];
0309       noisecorEBg6(i, j) = noisecovariances->EBG6SamplesCorrelation[vidx];
0310       noisecorEEg6(i, j) = noisecovariances->EEG6SamplesCorrelation[vidx];
0311       noisecorEBg1(i, j) = noisecovariances->EBG1SamplesCorrelation[vidx];
0312       noisecorEEg1(i, j) = noisecovariances->EEG1SamplesCorrelation[vidx];
0313     }
0314   }
0315 }
0316 
0317 void EcalUncalibRecHitWorkerMultiFit::set(const edm::Event& evt) {
0318   unsigned int bunchspacing = 450;
0319 
0320   if (useLumiInfoRunHeader_) {
0321     edm::Handle<unsigned int> bunchSpacingH;
0322     evt.getByToken(bunchSpacing_, bunchSpacingH);
0323     bunchspacing = *bunchSpacingH;
0324   } else {
0325     bunchspacing = bunchSpacingManual_;
0326   }
0327 
0328   if (useLumiInfoRunHeader_ || bunchSpacingManual_ > 0) {
0329     if (bunchspacing == 25) {
0330       activeBX.resize(10);
0331       activeBX << -5, -4, -3, -2, -1, 0, 1, 2, 3, 4;
0332     } else {
0333       //50ns configuration otherwise (also for no pileup)
0334       activeBX.resize(5);
0335       activeBX << -4, -2, 0, 2, 4;
0336     }
0337   }
0338 }
0339 
0340 /**
0341  * Amplitude-dependent time corrections; EE and EB have separate corrections:
0342  * EXtimeCorrAmplitudes (ADC) and EXtimeCorrShifts (ns) need to have the same number of elements
0343  * Bins must be ordered in amplitude. First-last bins take care of under-overflows.
0344  *
0345  * The algorithm is the same for EE and EB, only the correction vectors are different.
0346  *
0347  * @return Jitter (in clock cycles) which will be added to UncalibRechit.setJitter(), 0 if no correction is applied.
0348  */
0349 double EcalUncalibRecHitWorkerMultiFit::timeCorrection(float ampli,
0350                                                        const std::vector<float>& amplitudeBins,
0351                                                        const std::vector<float>& shiftBins) {
0352   // computed initially in ns. Than turned in the BX's, as
0353   // EcalUncalibratedRecHit need be.
0354   double theCorrection = 0;
0355 
0356   // sanity check for arrays
0357   if (amplitudeBins.empty()) {
0358     edm::LogError("EcalRecHitError") << "timeCorrAmplitudeBins is empty, forcing no time bias corrections.";
0359 
0360     return 0;
0361   }
0362 
0363   if (amplitudeBins.size() != shiftBins.size()) {
0364     edm::LogError("EcalRecHitError") << "Size of timeCorrAmplitudeBins different from "
0365                                         "timeCorrShiftBins. Forcing no time bias corrections. ";
0366 
0367     return 0;
0368   }
0369 
0370   // FIXME? what about a binary search?
0371   int myBin = -1;
0372   for (int bin = 0; bin < (int)amplitudeBins.size(); bin++) {
0373     if (ampli > amplitudeBins[bin]) {
0374       myBin = bin;
0375     } else {
0376       break;
0377     }
0378   }
0379 
0380   if (myBin == -1) {
0381     theCorrection = shiftBins[0];
0382   } else if (myBin == ((int)(amplitudeBins.size() - 1))) {
0383     theCorrection = shiftBins[myBin];
0384   } else {
0385     // interpolate linearly between two assingned points
0386     theCorrection = (shiftBins[myBin + 1] - shiftBins[myBin]);
0387     theCorrection *= (((double)ampli) - amplitudeBins[myBin]) / (amplitudeBins[myBin + 1] - amplitudeBins[myBin]);
0388     theCorrection += shiftBins[myBin];
0389   }
0390 
0391   // convert ns into clocks
0392   constexpr double inv25 = 1. / 25.;
0393   return theCorrection * inv25;
0394 }
0395 
0396 void EcalUncalibRecHitWorkerMultiFit::run(const edm::Event& evt,
0397                                           const EcalDigiCollection& digis,
0398                                           EcalUncalibratedRecHitCollection& result) {
0399   if (digis.empty())
0400     return;
0401 
0402   // assume all digis come from the same subdetector (either barrel or endcap)
0403   DetId detid(digis.begin()->id());
0404   bool barrel = (detid.subdetId() == EcalBarrel);
0405 
0406   multiFitMethod_.setSimplifiedNoiseModelForGainSwitch(simplifiedNoiseModelForGainSwitch_);
0407   if (barrel) {
0408     multiFitMethod_.setDoPrefit(doPrefitEB_);
0409     multiFitMethod_.setPrefitMaxChiSq(prefitMaxChiSqEB_);
0410     multiFitMethod_.setDynamicPedestals(dynamicPedestalsEB_);
0411     multiFitMethod_.setMitigateBadSamples(mitigateBadSamplesEB_);
0412     multiFitMethod_.setGainSwitchUseMaxSample(gainSwitchUseMaxSampleEB_);
0413     multiFitMethod_.setSelectiveBadSampleCriteria(selectiveBadSampleCriteriaEB_);
0414     multiFitMethod_.setAddPedestalUncertainty(addPedestalUncertaintyEB_);
0415   } else {
0416     multiFitMethod_.setDoPrefit(doPrefitEE_);
0417     multiFitMethod_.setPrefitMaxChiSq(prefitMaxChiSqEE_);
0418     multiFitMethod_.setDynamicPedestals(dynamicPedestalsEE_);
0419     multiFitMethod_.setMitigateBadSamples(mitigateBadSamplesEE_);
0420     multiFitMethod_.setGainSwitchUseMaxSample(gainSwitchUseMaxSampleEE_);
0421     multiFitMethod_.setSelectiveBadSampleCriteria(selectiveBadSampleCriteriaEE_);
0422     multiFitMethod_.setAddPedestalUncertainty(addPedestalUncertaintyEE_);
0423   }
0424 
0425   FullSampleVector fullpulse(FullSampleVector::Zero());
0426   FullSampleMatrix fullpulsecov(FullSampleMatrix::Zero());
0427 
0428   result.reserve(result.size() + digis.size());
0429   for (auto itdg = digis.begin(); itdg != digis.end(); ++itdg) {
0430     DetId detid(itdg->id());
0431 
0432     const EcalSampleMask* sampleMask_ = sampleMaskHand_.product();
0433 
0434     // intelligence for recHit computation
0435     float offsetTime = 0;
0436 
0437     const EcalPedestals::Item* aped = nullptr;
0438     const EcalMGPAGainRatio* aGain = nullptr;
0439     const EcalXtalGroupId* gid = nullptr;
0440     const EcalPulseShapes::Item* aPulse = nullptr;
0441     const EcalPulseCovariances::Item* aPulseCov = nullptr;
0442 
0443     if (barrel) {
0444       unsigned int hashedIndex = EBDetId(detid).hashedIndex();
0445       aped = &peds->barrel(hashedIndex);
0446       aGain = &gains->barrel(hashedIndex);
0447       gid = &grps->barrel(hashedIndex);
0448       aPulse = &pulseshapes->barrel(hashedIndex);
0449       aPulseCov = &pulsecovariances->barrel(hashedIndex);
0450       offsetTime = offtime->getEBValue();
0451     } else {
0452       unsigned int hashedIndex = EEDetId(detid).hashedIndex();
0453       aped = &peds->endcap(hashedIndex);
0454       aGain = &gains->endcap(hashedIndex);
0455       gid = &grps->endcap(hashedIndex);
0456       aPulse = &pulseshapes->endcap(hashedIndex);
0457       aPulseCov = &pulsecovariances->endcap(hashedIndex);
0458       offsetTime = offtime->getEEValue();
0459     }
0460 
0461     double pedVec[3] = {aped->mean_x12, aped->mean_x6, aped->mean_x1};
0462     double pedRMSVec[3] = {aped->rms_x12, aped->rms_x6, aped->rms_x1};
0463     double gainRatios[3] = {1., aGain->gain12Over6(), aGain->gain6Over1() * aGain->gain12Over6()};
0464 
0465     for (int i = 0; i < EcalPulseShape::TEMPLATESAMPLES; ++i)
0466       fullpulse(i + 7) = aPulse->pdfval[i];
0467 
0468     for (int i = 0; i < EcalPulseShape::TEMPLATESAMPLES; i++)
0469       for (int j = 0; j < EcalPulseShape::TEMPLATESAMPLES; j++)
0470         fullpulsecov(i + 7, j + 7) = aPulseCov->covval[i][j];
0471 
0472     // compute the right bin of the pulse shape using time calibration constants
0473     EcalTimeCalibConstantMap::const_iterator it = itime->find(detid);
0474     EcalTimeCalibConstant itimeconst = 0;
0475     if (it != itime->end()) {
0476       itimeconst = (*it);
0477     } else {
0478       edm::LogError("EcalRecHitError") << "No time intercalib const found for xtal " << detid.rawId()
0479                                        << "! something wrong with EcalTimeCalibConstants in your DB? ";
0480     }
0481 
0482     int lastSampleBeforeSaturation = -2;
0483     for (unsigned int iSample = 0; iSample < EcalDataFrame::MAXSAMPLES; iSample++) {
0484       if (((EcalDataFrame)(*itdg)).sample(iSample).gainId() == 0) {
0485         lastSampleBeforeSaturation = iSample - 1;
0486         break;
0487       }
0488     }
0489 
0490     // === amplitude computation ===
0491 
0492     if (lastSampleBeforeSaturation == 4) {  // saturation on the expected max sample
0493       result.emplace_back((*itdg).id(), 4095 * 12, 0, 0, 0);
0494       auto& uncalibRecHit = result.back();
0495       uncalibRecHit.setFlagBit(EcalUncalibratedRecHit::kSaturated);
0496       // do not propagate the default chi2 = -1 value to the calib rechit (mapped to 64), set it to 0 when saturation
0497       uncalibRecHit.setChi2(0);
0498     } else if (lastSampleBeforeSaturation >=
0499                -1) {  // saturation on other samples: cannot extrapolate from the fourth one
0500       int gainId = ((EcalDataFrame)(*itdg)).sample(5).gainId();
0501       if (gainId == 0)
0502         gainId = 3;
0503       auto pedestal = pedVec[gainId - 1];
0504       auto gainratio = gainRatios[gainId - 1];
0505       double amplitude = ((double)(((EcalDataFrame)(*itdg)).sample(5).adc()) - pedestal) * gainratio;
0506       result.emplace_back((*itdg).id(), amplitude, 0, 0, 0);
0507       auto& uncalibRecHit = result.back();
0508       uncalibRecHit.setFlagBit(EcalUncalibratedRecHit::kSaturated);
0509       // do not propagate the default chi2 = -1 value to the calib rechit (mapped to 64), set it to 0 when saturation
0510       uncalibRecHit.setChi2(0);
0511     } else {
0512       // multifit
0513       const SampleMatrixGainArray& noisecors = noisecor(barrel);
0514 
0515       result.push_back(multiFitMethod_.makeRecHit(*itdg, aped, aGain, noisecors, fullpulse, fullpulsecov, activeBX));
0516       auto& uncalibRecHit = result.back();
0517 
0518       // === time computation ===
0519       if (timealgo_ == ratioMethod) {
0520         // ratio method
0521         constexpr float clockToNsConstant = 25.;
0522         constexpr float invClockToNs = 1. / clockToNsConstant;
0523         if (not barrel) {
0524           ratioMethod_endcap_.init(*itdg, *sampleMask_, pedVec, pedRMSVec, gainRatios);
0525           ratioMethod_endcap_.computeTime(EEtimeFitParameters_, EEtimeFitLimits_, EEamplitudeFitParameters_);
0526           ratioMethod_endcap_.computeAmplitude(EEamplitudeFitParameters_);
0527           EcalUncalibRecHitRatioMethodAlgo<EEDataFrame>::CalculatedRecHit crh =
0528               ratioMethod_endcap_.getCalculatedRecHit();
0529           double theTimeCorrectionEE = timeCorrection(
0530               uncalibRecHit.amplitude(), timeCorrBias_->EETimeCorrAmplitudeBins, timeCorrBias_->EETimeCorrShiftBins);
0531 
0532           uncalibRecHit.setJitter(crh.timeMax - 5 + theTimeCorrectionEE);
0533           uncalibRecHit.setJitterError(
0534               std::sqrt(std::pow(crh.timeError, 2) + std::pow(EEtimeConstantTerm_ * invClockToNs, 2)));
0535 
0536           // consider flagging as kOutOfTime only if above noise
0537           if (uncalibRecHit.amplitude() > pedRMSVec[0] * amplitudeThreshEE_) {
0538             float outOfTimeThreshP = outOfTimeThreshG12pEE_;
0539             float outOfTimeThreshM = outOfTimeThreshG12mEE_;
0540             // determine if gain has switched away from gainId==1 (x12 gain)
0541             // and determine cuts (number of 'sigmas') to ose for kOutOfTime
0542             // >3k ADC is necessasry condition for gain switch to occur
0543             if (uncalibRecHit.amplitude() > 3000.) {
0544               for (int iSample = 0; iSample < EEDataFrame::MAXSAMPLES; iSample++) {
0545                 int GainId = ((EcalDataFrame)(*itdg)).sample(iSample).gainId();
0546                 if (GainId != 1) {
0547                   outOfTimeThreshP = outOfTimeThreshG61pEE_;
0548                   outOfTimeThreshM = outOfTimeThreshG61mEE_;
0549                   break;
0550                 }
0551               }
0552             }
0553             float correctedTime = (crh.timeMax - 5) * clockToNsConstant + itimeconst + offsetTime;
0554             float cterm = EEtimeConstantTerm_;
0555             float sigmaped = pedRMSVec[0];  // approx for lower gains
0556             float nterm = EEtimeNconst_ * sigmaped / uncalibRecHit.amplitude();
0557             float sigmat = std::sqrt(nterm * nterm + cterm * cterm);
0558             if ((correctedTime > sigmat * outOfTimeThreshP) || (correctedTime < -sigmat * outOfTimeThreshM)) {
0559               uncalibRecHit.setFlagBit(EcalUncalibratedRecHit::kOutOfTime);
0560             }
0561           }
0562 
0563         } else {
0564           ratioMethod_barrel_.init(*itdg, *sampleMask_, pedVec, pedRMSVec, gainRatios);
0565           ratioMethod_barrel_.fixMGPAslew(*itdg);
0566           ratioMethod_barrel_.computeTime(EBtimeFitParameters_, EBtimeFitLimits_, EBamplitudeFitParameters_);
0567           ratioMethod_barrel_.computeAmplitude(EBamplitudeFitParameters_);
0568           EcalUncalibRecHitRatioMethodAlgo<EBDataFrame>::CalculatedRecHit crh =
0569               ratioMethod_barrel_.getCalculatedRecHit();
0570 
0571           double theTimeCorrectionEB = timeCorrection(
0572               uncalibRecHit.amplitude(), timeCorrBias_->EBTimeCorrAmplitudeBins, timeCorrBias_->EBTimeCorrShiftBins);
0573 
0574           uncalibRecHit.setJitter(crh.timeMax - 5 + theTimeCorrectionEB);
0575           uncalibRecHit.setJitterError(std::hypot(crh.timeError, EBtimeConstantTerm_ / clockToNsConstant));
0576 
0577           // consider flagging as kOutOfTime only if above noise
0578           if (uncalibRecHit.amplitude() > pedRMSVec[0] * amplitudeThreshEB_) {
0579             float outOfTimeThreshP = outOfTimeThreshG12pEB_;
0580             float outOfTimeThreshM = outOfTimeThreshG12mEB_;
0581             // determine if gain has switched away from gainId==1 (x12 gain)
0582             // and determine cuts (number of 'sigmas') to ose for kOutOfTime
0583             // >3k ADC is necessasry condition for gain switch to occur
0584             if (uncalibRecHit.amplitude() > 3000.) {
0585               for (int iSample = 0; iSample < EBDataFrame::MAXSAMPLES; iSample++) {
0586                 int GainId = ((EcalDataFrame)(*itdg)).sample(iSample).gainId();
0587                 if (GainId != 1) {
0588                   outOfTimeThreshP = outOfTimeThreshG61pEB_;
0589                   outOfTimeThreshM = outOfTimeThreshG61mEB_;
0590                   break;
0591                 }
0592               }
0593             }
0594             float correctedTime = (crh.timeMax - 5) * clockToNsConstant + itimeconst + offsetTime;
0595             float cterm = EBtimeConstantTerm_;
0596             float sigmaped = pedRMSVec[0];  // approx for lower gains
0597             float nterm = EBtimeNconst_ * sigmaped / uncalibRecHit.amplitude();
0598             float sigmat = std::sqrt(nterm * nterm + cterm * cterm);
0599             if ((correctedTime > sigmat * outOfTimeThreshP) || (correctedTime < -sigmat * outOfTimeThreshM)) {
0600               uncalibRecHit.setFlagBit(EcalUncalibratedRecHit::kOutOfTime);
0601             }
0602           }
0603         }
0604       } else if (timealgo_ == weightsMethod) {
0605         //  weights method on the PU subtracted pulse shape
0606         std::vector<double> amplitudes;
0607         for (unsigned int ibx = 0; ibx < activeBX.size(); ++ibx)
0608           amplitudes.push_back(uncalibRecHit.outOfTimeAmplitude(ibx));
0609 
0610         EcalTBWeights::EcalTDCId tdcid(1);
0611         EcalTBWeights::EcalTBWeightMap const& wgtsMap = wgts->getMap();
0612         EcalTBWeights::EcalTBWeightMap::const_iterator wit;
0613         wit = wgtsMap.find(std::make_pair(*gid, tdcid));
0614         if (wit == wgtsMap.end()) {
0615           edm::LogError("EcalUncalibRecHitError")
0616               << "No weights found for EcalGroupId: " << gid->id() << " and  EcalTDCId: " << tdcid
0617               << "\n  skipping digi with id: " << detid.rawId();
0618           result.pop_back();
0619           continue;
0620         }
0621         const EcalWeightSet& wset = wit->second;  // this is the EcalWeightSet
0622 
0623         const EcalWeightSet::EcalWeightMatrix& mat1 = wset.getWeightsBeforeGainSwitch();
0624         const EcalWeightSet::EcalWeightMatrix& mat2 = wset.getWeightsAfterGainSwitch();
0625 
0626         weights[0] = &mat1;
0627         weights[1] = &mat2;
0628 
0629         double timerh;
0630         if (detid.subdetId() == EcalEndcap) {
0631           timerh = weightsMethod_endcap_.time(*itdg, amplitudes, aped, aGain, fullpulse, weights);
0632         } else {
0633           timerh = weightsMethod_barrel_.time(*itdg, amplitudes, aped, aGain, fullpulse, weights);
0634         }
0635         uncalibRecHit.setJitter(timerh);
0636         uncalibRecHit.setJitterError(0.);  // not computed with weights
0637 
0638       } else if (timealgo_ == crossCorrelationMethod) {
0639         std::vector<double> amplitudes(activeBX.size());
0640         for (unsigned int ibx = 0; ibx < activeBX.size(); ++ibx)
0641           amplitudes[ibx] = uncalibRecHit.outOfTimeAmplitude(ibx);
0642 
0643         float jitter =
0644             computeCC_->computeTimeCC(*itdg, amplitudes, aped, aGain, fullpulse, CCtargetTimePrecision_, true) +
0645             CCTimeShiftWrtRations_ / ecalcctiming::clockToNS;
0646         float noCorrectedJitter =
0647             computeCC_->computeTimeCC(
0648                 *itdg, amplitudes, aped, aGain, fullpulse, CCtargetTimePrecisionForDelayedPulses_, false) +
0649             CCTimeShiftWrtRations_ / ecalcctiming::clockToNS;
0650 
0651         uncalibRecHit.setJitter(jitter);
0652         uncalibRecHit.setNonCorrectedTime(jitter, noCorrectedJitter);
0653 
0654         float retreivedNonCorrectedTime = uncalibRecHit.nonCorrectedTime();
0655         float noCorrectedTime = ecalcctiming::clockToNS * noCorrectedJitter;
0656         if (retreivedNonCorrectedTime > -29.0 && std::abs(retreivedNonCorrectedTime - noCorrectedTime) > 0.05) {
0657           edm::LogError("EcalUncalibRecHitError") << "Problem with noCorrectedJitter: true value:" << noCorrectedTime
0658                                                   << "\t received: " << retreivedNonCorrectedTime << std::endl;
0659         }  //<<>>if (abs(retreivedNonCorrectedTime - noCorrectedJitter)>1);
0660 
0661         // consider flagging as kOutOfTime only if above noise
0662         float threshold, cterm, timeNconst;
0663         float timeThrP = 0.;
0664         float timeThrM = 0.;
0665         if (barrel) {
0666           threshold = pedRMSVec[0] * amplitudeThreshEB_;
0667           cterm = EBtimeConstantTerm_;
0668           timeNconst = EBtimeNconst_;
0669           timeThrP = outOfTimeThreshG12pEB_;
0670           timeThrM = outOfTimeThreshG12mEB_;
0671           if (uncalibRecHit.amplitude() > 3000.) {  // Gain switch
0672             for (int iSample = 0; iSample < EBDataFrame::MAXSAMPLES; iSample++) {
0673               int GainId = ((EcalDataFrame)(*itdg)).sample(iSample).gainId();
0674               if (GainId != 1) {
0675                 timeThrP = outOfTimeThreshG61pEB_;
0676                 timeThrM = outOfTimeThreshG61mEB_;
0677                 break;
0678               }
0679             }
0680           }
0681         } else {  //EndCap
0682           threshold = pedRMSVec[0] * amplitudeThreshEE_;
0683           cterm = EEtimeConstantTerm_;
0684           timeNconst = EEtimeNconst_;
0685           timeThrP = outOfTimeThreshG12pEE_;
0686           timeThrM = outOfTimeThreshG12mEE_;
0687           if (uncalibRecHit.amplitude() > 3000.) {  // Gain switch
0688             for (int iSample = 0; iSample < EEDataFrame::MAXSAMPLES; iSample++) {
0689               int GainId = ((EcalDataFrame)(*itdg)).sample(iSample).gainId();
0690               if (GainId != 1) {
0691                 timeThrP = outOfTimeThreshG61pEE_;
0692                 timeThrM = outOfTimeThreshG61mEE_;
0693                 break;
0694               }
0695             }
0696           }
0697         }
0698         if (uncalibRecHit.amplitude() > threshold) {
0699           float correctedTime = noCorrectedJitter * ecalcctiming::clockToNS + itimeconst + offsetTime;
0700           float sigmaped = pedRMSVec[0];  // approx for lower gains
0701           float nterm = timeNconst * sigmaped / uncalibRecHit.amplitude();
0702           float sigmat = std::sqrt(nterm * nterm + cterm * cterm);
0703           if ((correctedTime > sigmat * timeThrP) || (correctedTime < -sigmat * timeThrM))
0704             uncalibRecHit.setFlagBit(EcalUncalibratedRecHit::kOutOfTime);
0705         }
0706 
0707       } else {  // no time method;
0708         uncalibRecHit.setJitter(0.);
0709         uncalibRecHit.setJitterError(0.);
0710       }
0711     }
0712 
0713     // set flags if gain switch has occurred
0714     auto& uncalibRecHit = result.back();
0715     if (((EcalDataFrame)(*itdg)).hasSwitchToGain6())
0716       uncalibRecHit.setFlagBit(EcalUncalibratedRecHit::kHasSwitchToGain6);
0717     if (((EcalDataFrame)(*itdg)).hasSwitchToGain1())
0718       uncalibRecHit.setFlagBit(EcalUncalibratedRecHit::kHasSwitchToGain1);
0719   }
0720 }
0721 
0722 edm::ParameterSetDescription EcalUncalibRecHitWorkerMultiFit::getAlgoDescription() {
0723   edm::ParameterSetDescription psd;
0724   psd.addNode(edm::ParameterDescription<std::vector<int>>("activeBXs", {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4}, true) and
0725               edm::ParameterDescription<bool>("ampErrorCalculation", true, true) and
0726               edm::ParameterDescription<bool>("useLumiInfoRunHeader", true, true) and
0727               edm::ParameterDescription<int>("bunchSpacing", 0, true) and
0728               edm::ParameterDescription<bool>("doPrefitEB", false, true) and
0729               edm::ParameterDescription<bool>("doPrefitEE", false, true) and
0730               edm::ParameterDescription<double>("prefitMaxChiSqEB", 25., true) and
0731               edm::ParameterDescription<double>("prefitMaxChiSqEE", 10., true) and
0732               edm::ParameterDescription<bool>("dynamicPedestalsEB", false, true) and
0733               edm::ParameterDescription<bool>("dynamicPedestalsEE", false, true) and
0734               edm::ParameterDescription<bool>("mitigateBadSamplesEB", false, true) and
0735               edm::ParameterDescription<bool>("mitigateBadSamplesEE", false, true) and
0736               edm::ParameterDescription<bool>("gainSwitchUseMaxSampleEB", true, true) and
0737               edm::ParameterDescription<bool>("gainSwitchUseMaxSampleEE", false, true) and
0738               edm::ParameterDescription<bool>("selectiveBadSampleCriteriaEB", false, true) and
0739               edm::ParameterDescription<bool>("selectiveBadSampleCriteriaEE", false, true) and
0740               edm::ParameterDescription<double>("addPedestalUncertaintyEB", 0., true) and
0741               edm::ParameterDescription<double>("addPedestalUncertaintyEE", 0., true) and
0742               edm::ParameterDescription<bool>("simplifiedNoiseModelForGainSwitch", true, true) and
0743               edm::ParameterDescription<std::string>("timealgo", "RatioMethod", true) and
0744               edm::ParameterDescription<std::vector<double>>("EBtimeFitParameters",
0745                                                              {-2.015452e+00,
0746                                                               3.130702e+00,
0747                                                               -1.234730e+01,
0748                                                               4.188921e+01,
0749                                                               -8.283944e+01,
0750                                                               9.101147e+01,
0751                                                               -5.035761e+01,
0752                                                               1.105621e+01},
0753                                                              true) and
0754               edm::ParameterDescription<std::vector<double>>("EEtimeFitParameters",
0755                                                              {-2.390548e+00,
0756                                                               3.553628e+00,
0757                                                               -1.762341e+01,
0758                                                               6.767538e+01,
0759                                                               -1.332130e+02,
0760                                                               1.407432e+02,
0761                                                               -7.541106e+01,
0762                                                               1.620277e+01},
0763                                                              true) and
0764               edm::ParameterDescription<std::vector<double>>("EBamplitudeFitParameters", {1.138, 1.652}, true) and
0765               edm::ParameterDescription<std::vector<double>>("EEamplitudeFitParameters", {1.890, 1.400}, true) and
0766               edm::ParameterDescription<edm::ESInputTag>("timeCalibTag", edm::ESInputTag(), true) and
0767               edm::ParameterDescription<edm::ESInputTag>("timeOffsetTag", edm::ESInputTag(), true) and
0768               edm::ParameterDescription<double>("EBtimeFitLimits_Lower", 0.2, true) and
0769               edm::ParameterDescription<double>("EBtimeFitLimits_Upper", 1.4, true) and
0770               edm::ParameterDescription<double>("EEtimeFitLimits_Lower", 0.2, true) and
0771               edm::ParameterDescription<double>("EEtimeFitLimits_Upper", 1.4, true) and
0772               edm::ParameterDescription<double>("EBtimeConstantTerm", .6, true) and
0773               edm::ParameterDescription<double>("EEtimeConstantTerm", 1.0, true) and
0774               edm::ParameterDescription<double>("EBtimeNconst", 28.5, true) and
0775               edm::ParameterDescription<double>("EEtimeNconst", 31.8, true) and
0776               edm::ParameterDescription<double>("outOfTimeThresholdGain12pEB", 5., true) and
0777               edm::ParameterDescription<double>("outOfTimeThresholdGain12mEB", 5., true) and
0778               edm::ParameterDescription<double>("outOfTimeThresholdGain61pEB", 5., true) and
0779               edm::ParameterDescription<double>("outOfTimeThresholdGain61mEB", 5., true) and
0780               edm::ParameterDescription<double>("outOfTimeThresholdGain12pEE", 1000, true) and
0781               edm::ParameterDescription<double>("outOfTimeThresholdGain12mEE", 1000, true) and
0782               edm::ParameterDescription<double>("outOfTimeThresholdGain61pEE", 1000, true) and
0783               edm::ParameterDescription<double>("outOfTimeThresholdGain61mEE", 1000, true) and
0784               edm::ParameterDescription<double>("amplitudeThresholdEB", 10, true) and
0785               edm::ParameterDescription<double>("amplitudeThresholdEE", 10, true) and
0786               edm::ParameterDescription<double>("crossCorrelationStartTime", -25.0, true) and
0787               edm::ParameterDescription<double>("crossCorrelationStopTime", 25.0, true) and
0788               edm::ParameterDescription<double>("crossCorrelationTargetTimePrecision", 0.01, true) and
0789               edm::ParameterDescription<double>("crossCorrelationTargetTimePrecisionForDelayedPulses", 0.05, true) and
0790               edm::ParameterDescription<double>("crossCorrelationTimeShiftWrtRations", 0., true) and
0791               edm::ParameterDescription<double>("crossCorrelationMinTimeToBeLateMin", 2., true) and
0792               edm::ParameterDescription<double>("crossCorrelationMinTimeToBeLateMax", 5., true));
0793 
0794   return psd;
0795 }
0796 
0797 #include "FWCore/Framework/interface/MakerMacros.h"
0798 #include "RecoLocalCalo/EcalRecProducers/interface/EcalUncalibRecHitWorkerFactory.h"
0799 DEFINE_EDM_PLUGIN(EcalUncalibRecHitWorkerFactory, EcalUncalibRecHitWorkerMultiFit, "EcalUncalibRecHitWorkerMultiFit");
0800 #include "RecoLocalCalo/EcalRecProducers/interface/EcalUncalibRecHitFillDescriptionWorkerFactory.h"
0801 DEFINE_EDM_PLUGIN(EcalUncalibRecHitFillDescriptionWorkerFactory,
0802                   EcalUncalibRecHitWorkerMultiFit,
0803                   "EcalUncalibRecHitWorkerMultiFit");