File indexing completed on 2024-04-06 12:25:03
0001 #include "CommonTools/CandAlgos/interface/ModifyObjectValueBase.h"
0002 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0003 #include "RecoEgamma/EgammaTools/interface/EpCombinationTool.h"
0004 #include "RecoEgamma/EgammaTools/interface/EGEnergySysIndex.h"
0005
0006 #include <vdt/vdtMath.h>
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 class EGEtScaleSysModifier : public ModifyObjectValueBase {
0029 public:
0030 EGEtScaleSysModifier(const edm::ParameterSet& conf, edm::ConsumesCollector&);
0031 ~EGEtScaleSysModifier() override {}
0032
0033 void setEvent(const edm::Event&) final;
0034 void setEventContent(const edm::EventSetup&) final;
0035
0036 void modifyObject(pat::Electron& ele) const final;
0037 void modifyObject(pat::Photon& pho) const final;
0038
0039 private:
0040 std::pair<float, float> calCombinedMom(reco::GsfElectron& ele, const float scale, const float smear) const;
0041 void setEcalEnergy(reco::GsfElectron& ele, const float scale, const float smear) const;
0042
0043 class UncertFuncBase {
0044 public:
0045 UncertFuncBase() {}
0046 virtual ~UncertFuncBase() {}
0047 virtual float val(const float et) const = 0;
0048 };
0049
0050
0051
0052 class UncertFuncV1 : public UncertFuncBase {
0053 public:
0054 UncertFuncV1(const edm::ParameterSet& conf)
0055 : lowEt_(conf.getParameter<double>("lowEt")),
0056 highEt_(conf.getParameter<double>("highEt")),
0057 lowEtUncert_(conf.getParameter<double>("lowEtUncert")),
0058 highEtUncert_(conf.getParameter<double>("highEtUncert")),
0059 dEt_(highEt_ - lowEt_),
0060 dUncert_(highEtUncert_ - lowEtUncert_) {
0061 if (highEt_ <= lowEt_)
0062 throw cms::Exception("ConfigError") << " highEt " << highEt_ << " is not higher than lowEt " << lowEt_;
0063 }
0064 ~UncertFuncV1() override {}
0065
0066 float val(const float et) const override {
0067 if (et <= lowEt_)
0068 return lowEtUncert_;
0069 else if (et >= highEt_)
0070 return highEtUncert_;
0071 else {
0072 return (et - lowEt_) * dUncert_ / dEt_ + lowEtUncert_;
0073 }
0074 }
0075
0076 private:
0077 float lowEt_;
0078 float highEt_;
0079 float lowEtUncert_;
0080 float highEtUncert_;
0081 float dEt_;
0082 float dUncert_;
0083 };
0084
0085 EpCombinationTool epCombTool_;
0086 std::unique_ptr<UncertFuncBase> uncertFunc_;
0087 };
0088
0089 EGEtScaleSysModifier::EGEtScaleSysModifier(const edm::ParameterSet& conf, edm::ConsumesCollector& cc)
0090 : ModifyObjectValueBase(conf), epCombTool_{conf.getParameterSet("epCombConfig"), std::move(cc)} {
0091 const edm::ParameterSet& funcPSet = conf.getParameterSet("uncertFunc");
0092 const std::string& funcName = funcPSet.getParameter<std::string>("name");
0093 if (funcName == "UncertFuncV1") {
0094 uncertFunc_ = std::make_unique<UncertFuncV1>(funcPSet);
0095 } else {
0096 throw cms::Exception("ConfigError") << "Error constructing EGEtScaleSysModifier, function name " << funcName
0097 << " not valid";
0098 }
0099 }
0100
0101 void EGEtScaleSysModifier::setEvent(const edm::Event& iEvent) {}
0102
0103 void EGEtScaleSysModifier::setEventContent(const edm::EventSetup& iSetup) { epCombTool_.setEventContent(iSetup); }
0104
0105 void EGEtScaleSysModifier::modifyObject(pat::Electron& ele) const {
0106 auto getVal = [](const pat::Electron& ele, EGEnergySysIndex::Index valIndex) {
0107 return ele.userFloat(EGEnergySysIndex::name(valIndex));
0108 };
0109
0110
0111
0112
0113 const float ecalEnergyPostCorr = getVal(ele, EGEnergySysIndex::kEcalPostCorr);
0114 const float ecalEnergyPreCorr = getVal(ele, EGEnergySysIndex::kEcalPreCorr);
0115 const float ecalEnergyErrPreCorr = getVal(ele, EGEnergySysIndex::kEcalErrPreCorr);
0116
0117
0118 const float etUncert = uncertFunc_->val(ele.et() / ele.energy() * ecalEnergyPostCorr);
0119 const float smear = getVal(ele, EGEnergySysIndex::kSmearValue);
0120 const float corr = getVal(ele, EGEnergySysIndex::kScaleValue);
0121
0122
0123 const float oldEcalEnergy = ele.ecalEnergy();
0124 const float oldEcalEnergyErr = ele.ecalEnergyError();
0125 const auto oldP4 = ele.p4();
0126 const float oldP4Err = ele.p4Error(reco::GsfElectron::P4_COMBINATION);
0127 const float oldTrkMomErr = ele.trackMomentumError();
0128
0129 ele.setCorrectedEcalEnergy(ecalEnergyPreCorr);
0130 ele.setCorrectedEcalEnergyError(ecalEnergyErrPreCorr);
0131
0132 const float energyEtUncertUp = calCombinedMom(ele, corr + etUncert, smear).first;
0133 const float energyEtUncertDn = calCombinedMom(ele, corr - etUncert, smear).first;
0134
0135
0136 ele.setCorrectedEcalEnergy(oldEcalEnergy);
0137 ele.setCorrectedEcalEnergyError(oldEcalEnergyErr);
0138 ele.correctMomentum(oldP4, oldTrkMomErr, oldP4Err);
0139
0140 ele.addUserFloat("energyScaleEtUp", energyEtUncertUp);
0141 ele.addUserFloat("energyScaleEtDown", energyEtUncertDn);
0142 }
0143
0144 void EGEtScaleSysModifier::modifyObject(pat::Photon& pho) const {
0145 auto getVal = [](const pat::Photon& pho, EGEnergySysIndex::Index valIndex) {
0146 return pho.userFloat(EGEnergySysIndex::name(valIndex));
0147 };
0148
0149
0150
0151 const float ecalEnergyPostCorr = getVal(pho, EGEnergySysIndex::kEcalPostCorr);
0152 const float ecalEnergyPreCorr = getVal(pho, EGEnergySysIndex::kEcalPreCorr);
0153
0154
0155 const float etUncert = uncertFunc_->val(pho.et() / pho.energy() * ecalEnergyPostCorr);
0156 const float corr = getVal(pho, EGEnergySysIndex::kScaleValue);
0157
0158 const float energyEtUncertUp = ecalEnergyPreCorr * (corr + etUncert);
0159 const float energyEtUncertDn = ecalEnergyPreCorr * (corr - etUncert);
0160
0161 pho.addUserFloat("energyScaleEtUp", energyEtUncertUp);
0162 pho.addUserFloat("energyScaleEtDown", energyEtUncertDn);
0163 }
0164
0165 std::pair<float, float> EGEtScaleSysModifier::calCombinedMom(reco::GsfElectron& ele,
0166 const float scale,
0167 const float smear) const {
0168 const float oldEcalEnergy = ele.ecalEnergy();
0169 const float oldEcalEnergyErr = ele.ecalEnergyError();
0170 const auto oldP4 = ele.p4();
0171 const float oldP4Err = ele.p4Error(reco::GsfElectron::P4_COMBINATION);
0172 const float oldTrkMomErr = ele.trackMomentumError();
0173
0174 setEcalEnergy(ele, scale, smear);
0175 const auto& combinedMomentum = epCombTool_.combine(ele);
0176 ele.setCorrectedEcalEnergy(oldEcalEnergy);
0177 ele.setCorrectedEcalEnergyError(oldEcalEnergyErr);
0178 ele.correctMomentum(oldP4, oldTrkMomErr, oldP4Err);
0179
0180 return combinedMomentum;
0181 }
0182
0183 void EGEtScaleSysModifier::setEcalEnergy(reco::GsfElectron& ele, const float scale, const float smear) const {
0184 const float oldEcalEnergy = ele.ecalEnergy();
0185 const float oldEcalEnergyErr = ele.ecalEnergyError();
0186 ele.setCorrectedEcalEnergy(oldEcalEnergy * scale);
0187 ele.setCorrectedEcalEnergyError(std::hypot(oldEcalEnergyErr * scale, oldEcalEnergy * smear * scale));
0188 }
0189
0190 DEFINE_EDM_PLUGIN(ModifyObjectValueFactory, EGEtScaleSysModifier, "EGEtScaleSysModifier");