CMS 3D CMS Logo

EGEtScaleSysModifier.cc
Go to the documentation of this file.
5 
6 #include <vdt/vdtMath.h>
7 
8 //in the legacy re-reco we came across an Et scale issue, specifically an inflection at 45 GeV
9 //it is problematic to address in the normal scale and smearing code therefore
10 //this patch modifies the e/gamma object to "patch in" this additional systematic
11 //Questions:
12 //1 ) Why dont we add this to the overall scale systematic?
13 //Well we could but the whole point of this is to get a proper template which can be evolved
14 //correctly. The issue is not that the current systematic doesnt cover this systematic on a
15 //per bin basis, it does, the problem is the sign flips at 45 GeV so its fine if you use
16 //only eles/phos > 45 or <45 GeV but the template cant simultaneously cover the entire spectrum
17 //and you'll get a nasty constrained fit.
18 //And if you care about these sort of things (and you probably should), you shouldnt be using
19 //the overall systematic anyways but its seperate parts
20 //
21 //2 ) Why dont you do it inside the standard class
22 //We could but we're rather hoping to solve this issue more cleanly in the future
23 //but we would hold up the reminiAOD too long to do so so this is just to get something
24 //which should be fine for 90% of analyses in the miniAOD. So this is a temporary fix
25 //which we hope to rip out soon (if you're reading this in 2024 because we're still doing it
26 //this way, all I can say is sorry, we thought it would go away soon! )
27 
29 public:
31  ~EGEtScaleSysModifier() override {}
32 
33  void setEvent(const edm::Event&) final;
34  void setEventContent(const edm::EventSetup&) final;
35 
36  void modifyObject(pat::Electron& ele) const final;
37  void modifyObject(pat::Photon& pho) const final;
38 
39 private:
40  std::pair<float, float> calCombinedMom(reco::GsfElectron& ele, const float scale, const float smear) const;
41  void setEcalEnergy(reco::GsfElectron& ele, const float scale, const float smear) const;
42 
44  public:
46  virtual ~UncertFuncBase() {}
47  virtual float val(const float et) const = 0;
48  };
49 
50  //defines two uncertaintes, one Et<X and one Et>Y
51  //for X<Et<Y, it linearly extrapolates betwen the two values
52  class UncertFuncV1 : public UncertFuncBase {
53  public:
55  : lowEt_(conf.getParameter<double>("lowEt")),
56  highEt_(conf.getParameter<double>("highEt")),
57  lowEtUncert_(conf.getParameter<double>("lowEtUncert")),
58  highEtUncert_(conf.getParameter<double>("highEtUncert")),
59  dEt_(highEt_ - lowEt_),
61  if (highEt_ <= lowEt_)
62  throw cms::Exception("ConfigError") << " highEt " << highEt_ << " is not higher than lowEt " << lowEt_;
63  }
64  ~UncertFuncV1() override {}
65 
66  float val(const float et) const override {
67  if (et <= lowEt_)
68  return lowEtUncert_;
69  else if (et >= highEt_)
70  return highEtUncert_;
71  else {
72  return (et - lowEt_) * dUncert_ / dEt_ + lowEtUncert_;
73  }
74  }
75 
76  private:
77  float lowEt_;
78  float highEt_;
79  float lowEtUncert_;
81  float dEt_;
82  float dUncert_;
83  };
84 
86  std::unique_ptr<UncertFuncBase> uncertFunc_;
87 };
88 
90  : ModifyObjectValueBase(conf), epCombTool_{conf.getParameterSet("epCombConfig"), std::move(cc)} {
91  const edm::ParameterSet& funcPSet = conf.getParameterSet("uncertFunc");
92  const std::string& funcName = funcPSet.getParameter<std::string>("name");
93  if (funcName == "UncertFuncV1") {
94  uncertFunc_ = std::make_unique<UncertFuncV1>(funcPSet);
95  } else {
96  throw cms::Exception("ConfigError") << "Error constructing EGEtScaleSysModifier, function name " << funcName
97  << " not valid";
98  }
99 }
100 
102 
104 
106  auto getVal = [](const pat::Electron& ele, EGEnergySysIndex::Index valIndex) {
107  return ele.userFloat(EGEnergySysIndex::name(valIndex));
108  };
109  //so ele.energy() may be either pre or post corrections, we have no idea
110  //so we explicity access the pre and post correction ecal energies
111  //we need the pre corrected to properly do the e/p combination
112  //we need the post corrected to get et uncertainty
113  const float ecalEnergyPostCorr = getVal(ele, EGEnergySysIndex::kEcalPostCorr);
114  const float ecalEnergyPreCorr = getVal(ele, EGEnergySysIndex::kEcalPreCorr);
115  const float ecalEnergyErrPreCorr = getVal(ele, EGEnergySysIndex::kEcalErrPreCorr);
116 
117  //the et cut is in terms of ecal et using the track angle and post corr ecal energy
118  const float etUncert = uncertFunc_->val(ele.et() / ele.energy() * ecalEnergyPostCorr);
119  const float smear = getVal(ele, EGEnergySysIndex::kSmearValue);
120  const float corr = getVal(ele, EGEnergySysIndex::kScaleValue);
121 
122  //get the values we have to reset back to
123  const float oldEcalEnergy = ele.ecalEnergy();
124  const float oldEcalEnergyErr = ele.ecalEnergyError();
125  const auto oldP4 = ele.p4();
126  const float oldP4Err = ele.p4Error(reco::GsfElectron::P4_COMBINATION);
127  const float oldTrkMomErr = ele.trackMomentumError();
128 
129  ele.setCorrectedEcalEnergy(ecalEnergyPreCorr);
130  ele.setCorrectedEcalEnergyError(ecalEnergyErrPreCorr);
131 
132  const float energyEtUncertUp = calCombinedMom(ele, corr + etUncert, smear).first;
133  const float energyEtUncertDn = calCombinedMom(ele, corr - etUncert, smear).first;
134 
135  //reset it back to how it was
136  ele.setCorrectedEcalEnergy(oldEcalEnergy);
137  ele.setCorrectedEcalEnergyError(oldEcalEnergyErr);
138  ele.correctMomentum(oldP4, oldTrkMomErr, oldP4Err);
139 
140  ele.addUserFloat("energyScaleEtUp", energyEtUncertUp);
141  ele.addUserFloat("energyScaleEtDown", energyEtUncertDn);
142 }
143 
145  auto getVal = [](const pat::Photon& pho, EGEnergySysIndex::Index valIndex) {
146  return pho.userFloat(EGEnergySysIndex::name(valIndex));
147  };
148  //so pho.energy() may be either pre or post corrections, we have no idea
149  //so we explicity access the pre and post correction ecal energies
150  //post corr for the et value for the systematic, pre corr to apply them
151  const float ecalEnergyPostCorr = getVal(pho, EGEnergySysIndex::kEcalPostCorr);
152  const float ecalEnergyPreCorr = getVal(pho, EGEnergySysIndex::kEcalPreCorr);
153 
154  //the et cut is in terms of post corr ecal energy
155  const float etUncert = uncertFunc_->val(pho.et() / pho.energy() * ecalEnergyPostCorr);
156  const float corr = getVal(pho, EGEnergySysIndex::kScaleValue);
157 
158  const float energyEtUncertUp = ecalEnergyPreCorr * (corr + etUncert);
159  const float energyEtUncertDn = ecalEnergyPreCorr * (corr - etUncert);
160 
161  pho.addUserFloat("energyScaleEtUp", energyEtUncertUp);
162  pho.addUserFloat("energyScaleEtDown", energyEtUncertDn);
163 }
164 
166  const float scale,
167  const float smear) const {
168  const float oldEcalEnergy = ele.ecalEnergy();
169  const float oldEcalEnergyErr = ele.ecalEnergyError();
170  const auto oldP4 = ele.p4();
171  const float oldP4Err = ele.p4Error(reco::GsfElectron::P4_COMBINATION);
172  const float oldTrkMomErr = ele.trackMomentumError();
173 
174  setEcalEnergy(ele, scale, smear);
175  const auto& combinedMomentum = epCombTool_.combine(ele);
176  ele.setCorrectedEcalEnergy(oldEcalEnergy);
177  ele.setCorrectedEcalEnergyError(oldEcalEnergyErr);
178  ele.correctMomentum(oldP4, oldTrkMomErr, oldP4Err);
179 
180  return combinedMomentum;
181 }
182 
183 void EGEtScaleSysModifier::setEcalEnergy(reco::GsfElectron& ele, const float scale, const float smear) const {
184  const float oldEcalEnergy = ele.ecalEnergy();
185  const float oldEcalEnergyErr = ele.ecalEnergyError();
186  ele.setCorrectedEcalEnergy(oldEcalEnergy * scale);
187  ele.setCorrectedEcalEnergyError(std::hypot(oldEcalEnergyErr * scale, oldEcalEnergy * smear * scale));
188 }
189 
Analysis-level Photon class.
Definition: Photon.h:46
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
std::unique_ptr< UncertFuncBase > uncertFunc_
static const std::string & name(size_t index)
float trackMomentumError() const
Definition: GsfElectron.h:884
void correctMomentum(const LorentzVector &p4, float trackMomentumError, float p4Error)
Definition: GsfElectron.h:905
EpCombinationTool epCombTool_
ParameterSet const & getParameterSet(std::string const &) const
void addUserFloat(const std::string &label, float data, const bool overwrite=false)
Set user-defined float.
Definition: PATObject.h:892
void combine(SimpleElectron &mySimpleElectron) const
int iEvent
Definition: GenABIO.cc:224
void setCorrectedEcalEnergyError(float newEnergyError)
Definition: GsfElectron.cc:170
std::pair< float, float > calCombinedMom(reco::GsfElectron &ele, const float scale, const float smear) const
dictionary corr
virtual float val(const float et) const =0
const LorentzVector & p4(P4Kind kind) const
Definition: GsfElectron.cc:217
UncertFuncV1(const edm::ParameterSet &conf)
void setEventContent(const edm::EventSetup &iSetup)
void setEcalEnergy(reco::GsfElectron &ele, const float scale, const float smear) const
float p4Error(P4Kind kind) const
Definition: GsfElectron.cc:230
float ecalEnergy() const
Definition: GsfElectron.h:896
void setEvent(const edm::Event &) final
Analysis-level electron class.
Definition: Electron.h:51
void setEventContent(const edm::EventSetup &) final
float ecalEnergyError() const
Definition: GsfElectron.h:897
float val(const float et) const override
void setCorrectedEcalEnergy(float newEnergy)
Definition: GsfElectron.cc:174
double et() const final
transverse energy
EGEtScaleSysModifier(const edm::ParameterSet &conf, edm::ConsumesCollector &)
void modifyObject(pat::Electron &ele) const final
#define DEFINE_EDM_PLUGIN(factory, type, name)
float userFloat(const std::string &key) const
Definition: PATObject.h:871
def move(src, dest)
Definition: eostools.py:511
double energy() const final
energy