CMS 3D CMS Logo

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
EGRegressionModifierV1.cc
Go to the documentation of this file.
15 
16 #include <vdt/vdtMath.h>
17 
19 public:
20 
22 
23  void setEvent(const edm::Event&) final;
24  void setEventContent(const edm::EventSetup&) final;
25 
26  void modifyObject(reco::GsfElectron&) const final;
27  void modifyObject(reco::Photon&) const final;
28 
29  // just calls reco versions
30  void modifyObject(pat::Electron& ele) const final { modifyObject(static_cast<reco::GsfElectron&>(ele)); }
31  void modifyObject(pat::Photon& pho) const final { modifyObject(static_cast<reco::Photon&>(pho)); }
32 
33 private:
34 
35  struct CondNames {
36  std::vector<std::string> mean50ns;
37  std::vector<std::string> sigma50ns;
38  std::vector<std::string> mean25ns;
39  std::vector<std::string> sigma25ns;
40  };
41 
44 
47 
51  float rhoValue_;
53  int nVtx_;
57 
59 
60  std::vector<const GBRForestD*> phoForestsMean_;
61  std::vector<const GBRForestD*> phoForestsSigma_;
62  std::vector<const GBRForestD*> eleForestsMean_;
63  std::vector<const GBRForestD*> eleForestsSigma_;
65 };
66 
68 
70  : ModifyObjectValueBase(conf)
71  , autoDetectBunchSpacing_(conf.getParameter<bool>("autoDetectBunchSpacing"))
72  , bunchspacing_(autoDetectBunchSpacing_ ? 450 : conf.getParameter<int>("manualBunchSpacing"))
73  , rhoToken_(cc.consumes<double>(conf.getParameter<edm::InputTag>("rhoCollection")))
74  , vtxToken_(cc.consumes<reco::VertexCollection>(conf.getParameter<edm::InputTag>("vertexCollection")))
75  , applyExtraHighEnergyProtection_(conf.getParameter<bool>("applyExtraHighEnergyProtection"))
76 {
78  bunchSpacingToken_ = cc.consumes<unsigned int>(conf.getParameter<edm::InputTag>("bunchSpacingTag"));
79 
80  const edm::ParameterSet& electrons = conf.getParameter<edm::ParameterSet>("electron_config");
82  .mean50ns = electrons.getParameter<std::vector<std::string> >("regressionKey_50ns"),
83  .sigma50ns = electrons.getParameter<std::vector<std::string> >("uncertaintyKey_50ns"),
84  .mean25ns = electrons.getParameter<std::vector<std::string> >("regressionKey_25ns"),
85  .sigma25ns = electrons.getParameter<std::vector<std::string> >("uncertaintyKey_25ns")
86  };
87  condNamesWeight50ns_ = electrons.getParameter<std::string>("combinationKey_50ns");
88  condNamesWeight25ns_ = electrons.getParameter<std::string>("combinationKey_25ns");
89 
90  const edm::ParameterSet& photons = conf.getParameter<edm::ParameterSet>("photon_config");
92  .mean50ns = photons.getParameter<std::vector<std::string>>("regressionKey_50ns"),
93  .sigma50ns = photons.getParameter<std::vector<std::string>>("uncertaintyKey_50ns"),
94  .mean25ns = photons.getParameter<std::vector<std::string>>("regressionKey_25ns"),
95  .sigma25ns = photons.getParameter<std::vector<std::string>>("uncertaintyKey_25ns")
96  };
97 }
98 
100 {
102  edm::Handle<unsigned int> bunchSpacingH;
103  evt.getByToken(bunchSpacingToken_,bunchSpacingH);
104  bunchspacing_ = *bunchSpacingH;
105  }
106 
107  edm::Handle<double> rhoH;
108  evt.getByToken(rhoToken_, rhoH);
109  rhoValue_ = *rhoH;
110 
111  evt.getByToken(vtxToken_, vtxH_);
112  nVtx_ = vtxH_->size();
113 }
114 
116 {
117  iSetup_ = &evs;
118 
121 
124 
125  edm::ESHandle<GBRForest> forestEH;
126  const std::string ep_condnames_weight = (bunchspacing_ == 25) ? condNamesWeight25ns_ : condNamesWeight50ns_;
127  evs.get<GBRWrapperRcd>().get(ep_condnames_weight, forestEH);
128  epForest_ = forestEH.product();
129 }
130 
132  // regression calculation needs no additional valuemaps
133 
134  const reco::SuperClusterRef& superClus = ele.superCluster();
135  const edm::Ptr<reco::CaloCluster>& theseed = superClus->seed();
136  const int numberOfClusters = superClus->clusters().size();
137  const bool missing_clusters = !superClus->clusters()[numberOfClusters-1].isAvailable();
138 
139  if( missing_clusters ) return ; // do not apply corrections in case of missing info (slimmed MiniAOD electrons)
140 
141  std::array<float, 33> eval;
142  const double rawEnergy = superClus->rawEnergy();
143  const auto& ess = ele.showerShape();
144 
145  // SET INPUTS
146  eval[0] = nVtx_;
147  eval[1] = rawEnergy;
148  eval[2] = superClus->eta();
149  eval[3] = superClus->phi();
150  eval[4] = superClus->etaWidth();
151  eval[5] = superClus->phiWidth();
152  eval[6] = ess.r9;
153  eval[7] = theseed->energy()/rawEnergy;
154  eval[8] = ess.eMax/rawEnergy;
155  eval[9] = ess.e2nd/rawEnergy;
156  eval[10] = (ess.eLeft + ess.eRight != 0.f ? (ess.eLeft-ess.eRight)/(ess.eLeft+ess.eRight) : 0.f);
157  eval[11] = (ess.eTop + ess.eBottom != 0.f ? (ess.eTop-ess.eBottom)/(ess.eTop+ess.eBottom) : 0.f);
158  eval[12] = ess.sigmaIetaIeta;
159  eval[13] = ess.sigmaIetaIphi;
160  eval[14] = ess.sigmaIphiIphi;
161  eval[15] = std::max(0,numberOfClusters-1);
162 
163  // calculate sub-cluster variables
164  std::vector<float> clusterRawEnergy;
165  clusterRawEnergy.resize(std::max(3, numberOfClusters), 0);
166  std::vector<float> clusterDEtaToSeed;
167  clusterDEtaToSeed.resize(std::max(3, numberOfClusters), 0);
168  std::vector<float> clusterDPhiToSeed;
169  clusterDPhiToSeed.resize(std::max(3, numberOfClusters), 0);
170  float clusterMaxDR = 999.;
171  float clusterMaxDRDPhi = 999.;
172  float clusterMaxDRDEta = 999.;
173  float clusterMaxDRRawEnergy = 0.;
174 
175  size_t iclus = 0;
176  float maxDR = 0;
177  // loop over all clusters that aren't the seed
178  for (auto const& pclus : superClus->clusters())
179  {
180  if(theseed == pclus )
181  continue;
182  clusterRawEnergy[iclus] = pclus->energy();
183  clusterDPhiToSeed[iclus] = reco::deltaPhi(pclus->phi(),theseed->phi());
184  clusterDEtaToSeed[iclus] = pclus->eta() - theseed->eta();
185 
186  // find cluster with max dR
187  const auto the_dr = reco::deltaR(*pclus, *theseed);
188  if(the_dr > maxDR) {
189  maxDR = the_dr;
190  clusterMaxDR = maxDR;
191  clusterMaxDRDPhi = clusterDPhiToSeed[iclus];
192  clusterMaxDRDEta = clusterDEtaToSeed[iclus];
193  clusterMaxDRRawEnergy = clusterRawEnergy[iclus];
194  }
195  ++iclus;
196  }
197 
198  eval[16] = clusterMaxDR;
199  eval[17] = clusterMaxDRDPhi;
200  eval[18] = clusterMaxDRDEta;
201  eval[19] = clusterMaxDRRawEnergy/rawEnergy;
202  eval[20] = clusterRawEnergy[0]/rawEnergy;
203  eval[21] = clusterRawEnergy[1]/rawEnergy;
204  eval[22] = clusterRawEnergy[2]/rawEnergy;
205  eval[23] = clusterDPhiToSeed[0];
206  eval[24] = clusterDPhiToSeed[1];
207  eval[25] = clusterDPhiToSeed[2];
208  eval[26] = clusterDEtaToSeed[0];
209  eval[27] = clusterDEtaToSeed[1];
210  eval[28] = clusterDEtaToSeed[2];
211 
212  // calculate coordinate variables
213  const bool isEB = ele.isEB();
214  float dummy;
215  int iPhi;
216  int iEta;
217  float cryPhi;
218  float cryEta;
219  edm::ESHandle<CaloGeometry> caloGeometry;
220  iSetup_->get<CaloGeometryRecord>().get(caloGeometry);
221  if (ele.isEB())
222  egammaTools::localEcalClusterCoordsEB(*theseed, *caloGeometry, cryEta, cryPhi, iEta, iPhi, dummy, dummy);
223  else
224  egammaTools::localEcalClusterCoordsEE(*theseed, *caloGeometry, cryEta, cryPhi, iEta, iPhi, dummy, dummy);
225 
226  if (isEB) {
227  eval[29] = cryEta;
228  eval[30] = cryPhi;
229  eval[31] = iEta;
230  eval[32] = iPhi;
231  } else {
232  eval[29] = superClus->preshowerEnergy()/superClus->rawEnergy();
233  }
234 
235  //magic numbers for MINUIT-like transformation of BDT output onto limited range
236  //(These should be stored inside the conditions object in the future as well)
237  constexpr double meanlimlow = 0.2;
238  constexpr double meanlimhigh = 2.0;
239  constexpr double meanoffset = meanlimlow + 0.5*(meanlimhigh-meanlimlow);
240  constexpr double meanscale = 0.5*(meanlimhigh-meanlimlow);
241 
242  constexpr double sigmalimlow = 0.0002;
243  constexpr double sigmalimhigh = 0.5;
244  constexpr double sigmaoffset = sigmalimlow + 0.5*(sigmalimhigh-sigmalimlow);
245  constexpr double sigmascale = 0.5*(sigmalimhigh-sigmalimlow);
246 
247  const int coridx = isEB ? 0 : 1;
248 
249  //these are the actual BDT responses
250  double rawmean = eleForestsMean_[coridx]->GetResponse(eval.data());
251  double rawsigma = eleForestsSigma_[coridx]->GetResponse(eval.data());
252 
253  //apply transformation to limited output range (matching the training)
254  double mean = meanoffset + meanscale*vdt::fast_sin(rawmean);
255  double sigma = sigmaoffset + sigmascale*vdt::fast_sin(rawsigma);
256 
257  //regression target is ln(Etrue/Eraw)
258  //so corrected energy is ecor=exp(mean)*e, uncertainty is exp(mean)*eraw*sigma=ecor*sigma
259  double ecor = mean*(eval[1]);
260  if (!isEB)
261  ecor = mean*(eval[1]+superClus->preshowerEnergy());
262  const double sigmacor = sigma*ecor;
263 
264  ele.setCorrectedEcalEnergy(ecor);
265  ele.setCorrectedEcalEnergyError(sigmacor);
266 
267  // E-p combination
268  std::array<float, 11> eval_ep;
269 
270  const float ep = ele.trackMomentumAtVtx().R();
271  const float tot_energy = superClus->rawEnergy()+superClus->preshowerEnergy();
272  const float momentumError = ele.trackMomentumError();
273  const float trkMomentumRelError = ele.trackMomentumError()/ep;
274  const float eOverP = tot_energy*mean/ep;
275  eval_ep[0] = tot_energy*mean;
276  eval_ep[1] = sigma/mean;
277  eval_ep[2] = ep;
278  eval_ep[3] = trkMomentumRelError;
279  eval_ep[4] = sigma/mean/trkMomentumRelError;
280  eval_ep[5] = tot_energy*mean/ep;
281  eval_ep[6] = tot_energy*mean/ep*sqrt(sigma/mean*sigma/mean+trkMomentumRelError*trkMomentumRelError);
282  eval_ep[7] = ele.ecalDriven();
283  eval_ep[8] = ele.trackerDrivenSeed();
284  eval_ep[9] = int(ele.classification());//eleClass;
285  eval_ep[10] = isEB;
286 
287  // CODE FOR FUTURE SEMI_PARAMETRIC
288  //double rawweight = ep_forestsMean_[coridx]->GetResponse(eval_ep.data());
290  //double weight = meanoffset + meanscale*vdt::fast_sin(rawweight);
292 
293  // CODE FOR STANDARD BDT
294  double weight = 0.;
295  if ( eOverP > 0.025 &&
296  std::abs(ep-ecor) < 15.*std::sqrt( momentumError*momentumError + sigmacor*sigmacor ) &&
297  (!applyExtraHighEnergyProtection_ || ((momentumError < 10.*ep) || (ecor < 200.)))
298  ) {
299  // protection against crazy track measurement
300  weight = std::clamp(epForest_->GetResponse(eval_ep.data()), 0., 1.);
301  }
302 
303  double combinedMomentum = weight*ele.trackMomentumAtVtx().R() + (1.-weight)*ecor;
304  double combinedMomentumError = sqrt(weight*weight*ele.trackMomentumError()*ele.trackMomentumError() + (1.-weight)*(1.-weight)*sigmacor*sigmacor);
305 
306  math::XYZTLorentzVector oldMomentum = ele.p4();
307  math::XYZTLorentzVector newMomentum( oldMomentum.x()*combinedMomentum/oldMomentum.t(),
308  oldMomentum.y()*combinedMomentum/oldMomentum.t(),
309  oldMomentum.z()*combinedMomentum/oldMomentum.t(),
310  combinedMomentum );
311 
312  ele.correctMomentum(newMomentum, ele.trackMomentumError(), combinedMomentumError);
313 }
314 
316  // regression calculation needs no additional valuemaps
317 
318  std::array<float, 35> eval;
319  const reco::SuperClusterRef& superClus = pho.superCluster();
320  const edm::Ptr<reco::CaloCluster>& theseed = superClus->seed();
321 
322  const int numberOfClusters = superClus->clusters().size();
323  const bool missing_clusters = !superClus->clusters()[numberOfClusters-1].isAvailable();
324 
325  if( missing_clusters ) return ; // do not apply corrections in case of missing info (slimmed MiniAOD electrons)
326 
327  const double rawEnergy = superClus->rawEnergy();
328  const auto& ess = pho.showerShapeVariables();
329 
330  // SET INPUTS
331  eval[0] = rawEnergy;
332  eval[1] = pho.r9();
333  eval[2] = superClus->etaWidth();
334  eval[3] = superClus->phiWidth();
335  eval[4] = std::max(0,numberOfClusters - 1);
336  eval[5] = pho.hadronicOverEm();
337  eval[6] = rhoValue_;
338  eval[7] = nVtx_;
339  eval[8] = theseed->eta()-superClus->position().Eta();
340  eval[9] = reco::deltaPhi(theseed->phi(),superClus->position().Phi());
341  eval[10] = theseed->energy()/rawEnergy;
342  eval[11] = ess.e3x3/ess.e5x5;
343  eval[12] = ess.sigmaIetaIeta;
344  eval[13] = ess.sigmaIphiIphi;
345  eval[14] = ess.sigmaIetaIphi/(ess.sigmaIphiIphi*ess.sigmaIetaIeta);
346  eval[15] = ess.maxEnergyXtal/ess.e5x5;
347  eval[16] = ess.e2nd/ess.e5x5;
348  eval[17] = ess.eTop/ess.e5x5;
349  eval[18] = ess.eBottom/ess.e5x5;
350  eval[19] = ess.eLeft/ess.e5x5;
351  eval[20] = ess.eRight/ess.e5x5;
352  eval[21] = ess.e2x5Max/ess.e5x5;
353  eval[22] = ess.e2x5Left/ess.e5x5;
354  eval[23] = ess.e2x5Right/ess.e5x5;
355  eval[24] = ess.e2x5Top/ess.e5x5;
356  eval[25] = ess.e2x5Bottom/ess.e5x5;
357 
358  const bool isEB = pho.isEB();
359  if (isEB) {
360  EBDetId ebseedid(theseed->seed());
361  eval[26] = pho.e5x5()/theseed->energy();
362  int ieta = ebseedid.ieta();
363  int iphi = ebseedid.iphi();
364  eval[27] = ieta;
365  eval[28] = iphi;
366  int signieta = ieta > 0 ? +1 : -1;
367  eval[29] = (ieta-signieta)%5;
368  eval[30] = (iphi-1)%2;
369  eval[31] = (abs(ieta)<=25)*((ieta-signieta)) + (abs(ieta)>25)*((ieta-26*signieta)%20);
370  eval[32] = (iphi-1)%20;
371  eval[33] = ieta;
372  eval[34] = iphi;
373  } else {
374  EEDetId eeseedid(theseed->seed());
375  eval[26] = superClus->preshowerEnergy()/rawEnergy;
376  eval[27] = superClus->preshowerEnergyPlane1()/rawEnergy;
377  eval[28] = superClus->preshowerEnergyPlane2()/rawEnergy;
378  eval[29] = eeseedid.ix();
379  eval[30] = eeseedid.iy();
380  }
381 
382  //magic numbers for MINUIT-like transformation of BDT output onto limited range
383  //(These should be stored inside the conditions object in the future as well)
384  const double meanlimlow = 0.2;
385  const double meanlimhigh = 2.0;
386  const double meanoffset = meanlimlow + 0.5*(meanlimhigh-meanlimlow);
387  const double meanscale = 0.5*(meanlimhigh-meanlimlow);
388 
389  const double sigmalimlow = 0.0002;
390  const double sigmalimhigh = 0.5;
391  const double sigmaoffset = sigmalimlow + 0.5*(sigmalimhigh-sigmalimlow);
392  const double sigmascale = 0.5*(sigmalimhigh-sigmalimlow);
393 
394  const int coridx = isEB ? 0 : 1;
395 
396  //these are the actual BDT responses
397  const double rawmean = phoForestsMean_[coridx]->GetResponse(eval.data());
398  const double rawsigma = phoForestsSigma_[coridx]->GetResponse(eval.data());
399  //apply transformation to limited output range (matching the training)
400  const double mean = meanoffset + meanscale*vdt::fast_sin(rawmean);
401  const double sigma = sigmaoffset + sigmascale*vdt::fast_sin(rawsigma);
402 
403  //regression target is ln(Etrue/Eraw)
404  //so corrected energy is ecor=exp(mean)*e, uncertainty is exp(mean)*eraw*sigma=ecor*sigma
405  const double ecor = isEB ? mean*eval[0] : mean*(eval[0]+superClus->preshowerEnergy());
406 
407  const double sigmacor = sigma*ecor;
408  pho.setCorrectedEnergy(reco::Photon::P4type::regression2, ecor, sigmacor, true);
409 }
edm::EDGetTokenT< reco::VertexCollection > vtxToken_
double GetResponse(const float *vector) const
Definition: GBRForest.h:53
constexpr double deltaPhi(double phi1, double phi2)
Definition: deltaPhi.h:22
const ShowerShape & showerShape() const
Definition: GsfElectron.h:458
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
bool isAvailable() const
Definition: Ref.h:575
T getParameter(std::string const &) const
Analysis-level Photon class.
Definition: Photon.h:47
void setEventContent(const edm::EventSetup &) final
void localEcalClusterCoordsEB(const reco::CaloCluster &bclus, const CaloGeometry &geom, float &etacry, float &phicry, int &ieta, int &iphi, float &thetatilt, float &phitilt)
EGRegressionModifierV1(const edm::ParameterSet &conf, edm::ConsumesCollector &cc)
float trackMomentumError() const
Definition: GsfElectron.h:846
edm::Handle< reco::VertexCollection > vtxH_
std::vector< std::string > sigma25ns
const LorentzVector & p4(P4Kind kind) const
Definition: GsfElectron.cc:225
void setCorrectedEnergy(P4type type, float E, float dE, bool toCand=true)
float e5x5() const
Definition: Photon.h:234
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:517
void correctMomentum(const LorentzVector &p4, float trackMomentumError, float p4Error)
Definition: GsfElectron.h:868
math::XYZVectorF trackMomentumAtVtx() const
Definition: GsfElectron.h:295
std::vector< Vertex > VertexCollection
collection of Vertex objects
Definition: VertexFwd.h:9
Definition: weight.py:1
reco::SuperClusterRef superCluster() const override
Ref to SuperCluster.
bool isEB() const
Definition: GsfElectron.h:356
double eta() const
pseudorapidity of cluster centroid
Definition: CaloCluster.h:168
void setEvent(const edm::Event &) final
return((rh^lh)&mask)
std::vector< const GBRForestD * > phoForestsMean_
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
void setCorrectedEcalEnergyError(float newEnergyError)
Definition: GsfElectron.cc:179
std::vector< std::string > sigma50ns
std::vector< const GBRForestD * > retrieveGBRForests(edm::EventSetup const &evs, std::vector< std::string > const &names)
T sqrt(T t)
Definition: SSEVec.h:18
void modifyObject(pat::Electron &ele) const final
std::vector< const GBRForestD * > eleForestsSigma_
std::vector< const GBRForestD * > eleForestsMean_
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double energy() const
cluster energy
Definition: CaloCluster.h:126
edm::EDGetTokenT< double > rhoToken_
void localEcalClusterCoordsEE(const reco::CaloCluster &bclus, const CaloGeometry &geom, float &xcry, float &ycry, int &ix, int &iy, float &thetatilt, float &phitilt)
const edm::EventSetup * iSetup_
float hadronicOverEm() const
the total hadronic over electromagnetic fraction
Definition: Photon.h:212
void modifyObject(reco::GsfElectron &) const final
constexpr auto deltaR(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
Definition: deltaR.h:28
std::vector< const GBRForestD * > phoForestsSigma_
DetId seed() const
return DetId of seed
Definition: CaloCluster.h:207
Classification classification() const
Definition: GsfElectron.h:767
Analysis-level electron class.
Definition: Electron.h:52
bool isEB() const
Definition: Photon.h:121
void setCorrectedEcalEnergy(float newEnergy)
Definition: GsfElectron.cc:182
fixed size matrix
HLT enums.
T get() const
Definition: EventSetup.h:71
float r9() const
Definition: Photon.h:240
SuperClusterRef superCluster() const override
reference to a SuperCluster
Definition: GsfElectron.h:185
bool trackerDrivenSeed() const
Definition: GsfElectron.h:189
#define DEFINE_EDM_PLUGIN(factory, type, name)
double phi() const
azimuthal angle of cluster centroid
Definition: CaloCluster.h:171
void modifyObject(pat::Photon &pho) const final
edm::EDGetTokenT< unsigned int > bunchSpacingToken_
const ShowerShape & showerShapeVariables() const
Definition: Photon.h:205
bool ecalDriven() const
Definition: GsfElectron.cc:174
T const * product() const
Definition: ESHandle.h:86
#define constexpr