CMS 3D CMS Logo

EGRegressionModifierV1.cc
Go to the documentation of this file.
6 
9 
14 
17 
19 
20 #include <vdt/vdtMath.h>
21 
22 namespace {
23  const edm::InputTag empty_tag;
24 }
25 
26 #include <unordered_map>
27 
29 public:
32  typedef std::pair<edm::InputTag, ValMapFloatToken> ValMapFloatTagTokenPair;
33  typedef std::pair<edm::InputTag, ValMapIntToken> ValMapIntTagTokenPair;
34 
35  struct electron_config {
38  std::unordered_map<std::string, ValMapFloatTagTokenPair> tag_float_token_map;
39  std::unordered_map<std::string, ValMapIntTagTokenPair> tag_int_token_map;
40 
41  std::vector<std::string> condnames_mean_50ns;
42  std::vector<std::string> condnames_sigma_50ns;
43  std::vector<std::string> condnames_mean_25ns;
44  std::vector<std::string> condnames_sigma_25ns;
47  };
48 
49  struct photon_config {
52  std::unordered_map<std::string, ValMapFloatTagTokenPair> tag_float_token_map;
53  std::unordered_map<std::string, ValMapIntTagTokenPair> tag_int_token_map;
54 
55  std::vector<std::string> condnames_mean_50ns;
56  std::vector<std::string> condnames_sigma_50ns;
57  std::vector<std::string> condnames_mean_25ns;
58  std::vector<std::string> condnames_sigma_25ns;
59  };
60 
62  ~EGRegressionModifierV1() override {};
63 
64  void setEvent(const edm::Event&) final;
65  void setEventContent(const edm::EventSetup&) final;
67 
68  void modifyObject(reco::GsfElectron&) const final;
69  void modifyObject(reco::Photon&) const final;
70 
71  // just calls reco versions
72  void modifyObject(pat::Electron&) const final;
73  void modifyObject(pat::Photon&) const final;
74 
75 private:
78  std::unordered_map<unsigned,edm::Ptr<reco::GsfElectron> > eles_by_oop; // indexed by original object ptr
79  std::unordered_map<unsigned,edm::Handle<edm::ValueMap<float> > > ele_vmaps;
80  std::unordered_map<unsigned,edm::Handle<edm::ValueMap<int> > > ele_int_vmaps;
81  std::unordered_map<unsigned,edm::Ptr<reco::Photon> > phos_by_oop;
82  std::unordered_map<unsigned,edm::Handle<edm::ValueMap<float> > > pho_vmaps;
83  std::unordered_map<unsigned,edm::Handle<edm::ValueMap<int> > > pho_int_vmaps;
84 
89  float rhoValue_;
92  int nVtx_;
97 
99 
100  std::vector<const GBRForestD*> ph_forestH_mean_;
101  std::vector<const GBRForestD*> ph_forestH_sigma_;
102  std::vector<const GBRForestD*> e_forestH_mean_;
103  std::vector<const GBRForestD*> e_forestH_sigma_;
105 };
106 
109  "EGRegressionModifierV1");
110 
112  ModifyObjectValueBase(conf) {
113 
114  bunchspacing_ = 450;
115  autoDetectBunchSpacing_ = conf.getParameter<bool>("autoDetectBunchSpacing");
116  applyExtraHighEnergyProtection_ = conf.getParameter<bool>("applyExtraHighEnergyProtection");
117 
118  rhoTag_ = conf.getParameter<edm::InputTag>("rhoCollection");
119  vtxTag_ = conf.getParameter<edm::InputTag>("vertexCollection");
120 
122  bunchspacingTag_ = conf.getParameter<edm::InputTag>("bunchSpacingTag");
123  } else {
124  bunchspacing_ = conf.getParameter<int>("manualBunchSpacing");
125  }
126 
127  constexpr char electronSrc[] = "electronSrc";
128  constexpr char photonSrc[] = "photonSrc";
129 
130  if(conf.exists("electron_config")) {
131  const edm::ParameterSet& electrons = conf.getParameter<edm::ParameterSet>("electron_config");
132  if( electrons.exists(electronSrc) )
133  e_conf.electron_src = electrons.getParameter<edm::InputTag>(electronSrc);
134 
135  std::vector<std::string> intValueMaps;
136  if ( electrons.existsAs<std::vector<std::string> >("intValueMaps"))
137  intValueMaps = electrons.getParameter<std::vector<std::string> >("intValueMaps");
138 
139  const std::vector<std::string> parameters = electrons.getParameterNames();
140  for( const std::string& name : parameters ) {
141  if( std::string(electronSrc) == name )
142  continue;
143  if( electrons.existsAs<edm::InputTag>(name)) {
144  for (auto vmp : intValueMaps) {
145  if (name == vmp) {
147  break;
148  }
149  }
151  }
152  }
153 
154  e_conf.condnames_mean_50ns = electrons.getParameter<std::vector<std::string> >("regressionKey_50ns");
155  e_conf.condnames_sigma_50ns = electrons.getParameter<std::vector<std::string> >("uncertaintyKey_50ns");
156  e_conf.condnames_mean_25ns = electrons.getParameter<std::vector<std::string> >("regressionKey_25ns");
157  e_conf.condnames_sigma_25ns = electrons.getParameter<std::vector<std::string> >("uncertaintyKey_25ns");
158  e_conf.condnames_weight_50ns = electrons.getParameter<std::string>("combinationKey_50ns");
159  e_conf.condnames_weight_25ns = electrons.getParameter<std::string>("combinationKey_25ns");
160  }
161 
162  if( conf.exists("photon_config") ) {
163  const edm::ParameterSet& photons = conf.getParameter<edm::ParameterSet>("photon_config");
164 
165  if( photons.exists(photonSrc) )
166  ph_conf.photon_src = photons.getParameter<edm::InputTag>(photonSrc);
167 
168  std::vector<std::string> intValueMaps;
169  if ( photons.existsAs<std::vector<std::string> >("intValueMaps"))
170  intValueMaps = photons.getParameter<std::vector<std::string> >("intValueMaps");
171 
172  const std::vector<std::string> parameters = photons.getParameterNames();
173  for( const std::string& name : parameters ) {
174  if( std::string(photonSrc) == name )
175  continue;
176  if( photons.existsAs<edm::InputTag>(name)) {
177  for (auto vmp : intValueMaps) {
178  if (name == vmp) {
180  break;
181  }
182  }
184  }
185  }
186 
187  ph_conf.condnames_mean_50ns = photons.getParameter<std::vector<std::string>>("regressionKey_50ns");
188  ph_conf.condnames_sigma_50ns = photons.getParameter<std::vector<std::string>>("uncertaintyKey_50ns");
189  ph_conf.condnames_mean_25ns = photons.getParameter<std::vector<std::string>>("regressionKey_25ns");
190  ph_conf.condnames_sigma_25ns = photons.getParameter<std::vector<std::string>>("uncertaintyKey_25ns");
191  }
192 }
193 
194 namespace {
195  template<typename T>
196  inline void get_product(const edm::Event& evt,
197  const edm::EDGetTokenT<edm::ValueMap<T> >& tok,
198  std::unordered_map<unsigned, edm::Handle<edm::ValueMap<T> > >& map) {
199  evt.getByToken(tok,map[tok.index()]);
200  }
201 }
202 
204  eles_by_oop.clear();
205  phos_by_oop.clear();
206  ele_vmaps.clear();
207  ele_int_vmaps.clear();
208  pho_vmaps.clear();
209  pho_int_vmaps.clear();
210 
214 
215  for( unsigned i = 0; i < eles->size(); ++i ) {
216  edm::Ptr<pat::Electron> ptr = eles->ptrAt(i);
217  eles_by_oop[ptr->originalObjectRef().key()] = ptr;
218  }
219  }
220 
221  for (std::unordered_map<std::string, ValMapFloatTagTokenPair>::iterator imap = e_conf.tag_float_token_map.begin();
222  imap != e_conf.tag_float_token_map.end();
223  imap++) {
224  get_product(evt, imap->second.second, ele_vmaps);
225  }
226 
227  for (std::unordered_map<std::string, ValMapIntTagTokenPair>::iterator imap = e_conf.tag_int_token_map.begin();
228  imap != e_conf.tag_int_token_map.end();
229  imap++) {
230  get_product(evt, imap->second.second, ele_int_vmaps);
231  }
232 
236 
237  for( unsigned i = 0; i < phos->size(); ++i ) {
238  edm::Ptr<pat::Photon> ptr = phos->ptrAt(i);
239  phos_by_oop[ptr->originalObjectRef().key()] = ptr;
240  }
241  }
242 
243 
244  for (std::unordered_map<std::string, ValMapFloatTagTokenPair>::iterator imap = ph_conf.tag_float_token_map.begin();
245  imap != ph_conf.tag_float_token_map.end();
246  imap++) {
247  get_product(evt, imap->second.second, pho_vmaps);
248  }
249 
250  for (std::unordered_map<std::string, ValMapIntTagTokenPair>::iterator imap = ph_conf.tag_int_token_map.begin();
251  imap != ph_conf.tag_int_token_map.end();
252  imap++) {
253  get_product(evt, imap->second.second, pho_int_vmaps);
254  }
255 
257  edm::Handle<unsigned int> bunchSpacingH;
258  evt.getByToken(bunchSpacingToken_,bunchSpacingH);
259  bunchspacing_ = *bunchSpacingH;
260  }
261 
262  edm::Handle<double> rhoH;
263  evt.getByToken(rhoToken_, rhoH);
264  rhoValue_ = *rhoH;
265 
266  evt.getByToken(vtxToken_, vtxH_);
267  nVtx_ = vtxH_->size();
268 }
269 
271 
272  iSetup_ = &evs;
273 
274  edm::ESHandle<GBRForestD> forestDEH;
275  edm::ESHandle<GBRForest> forestEH;
276 
277  const std::vector<std::string> ph_condnames_mean = (bunchspacing_ == 25) ? ph_conf.condnames_mean_25ns : ph_conf.condnames_mean_50ns;
278  const std::vector<std::string> ph_condnames_sigma = (bunchspacing_ == 25) ? ph_conf.condnames_sigma_25ns : ph_conf.condnames_sigma_50ns;
279 
280  unsigned int ncor = ph_condnames_mean.size();
281  for (unsigned int icor=0; icor<ncor; ++icor) {
282  evs.get<GBRDWrapperRcd>().get(ph_condnames_mean[icor], forestDEH);
283  ph_forestH_mean_.push_back(forestDEH.product());
284  evs.get<GBRDWrapperRcd>().get(ph_condnames_sigma[icor], forestDEH);
285  ph_forestH_sigma_.push_back(forestDEH.product());
286  }
287 
288  const std::vector<std::string> e_condnames_mean = (bunchspacing_ == 25) ? e_conf.condnames_mean_25ns : e_conf.condnames_mean_50ns;
289  const std::vector<std::string> e_condnames_sigma = (bunchspacing_ == 25) ? e_conf.condnames_sigma_25ns : e_conf.condnames_sigma_50ns;
290  const std::string ep_condnames_weight = (bunchspacing_ == 25) ? e_conf.condnames_weight_25ns : e_conf.condnames_weight_50ns;
291 
292  unsigned int encor = e_condnames_mean.size();
293  evs.get<GBRWrapperRcd>().get(ep_condnames_weight, forestEH);
294  ep_forestH_weight_ = forestEH.product();
295 
296  for (unsigned int icor=0; icor<encor; ++icor) {
297  evs.get<GBRDWrapperRcd>().get(e_condnames_mean[icor], forestDEH);
298  e_forestH_mean_.push_back(forestDEH.product());
299  evs.get<GBRDWrapperRcd>().get(e_condnames_sigma[icor], forestDEH);
300  e_forestH_sigma_.push_back(forestDEH.product());
301  }
302 }
303 
304 namespace {
305  template<typename T, typename U, typename V>
306  inline void make_consumes(T& tag,U& tok,V& sume) {
307  if(!(empty_tag == tag))
308  tok = sume.template consumes<edm::ValueMap<float> >(tag);
309  }
310 
311  template<typename T, typename U, typename V>
312  inline void make_int_consumes(T& tag,U& tok,V& sume) {
313  if(!(empty_tag == tag))
314  tok = sume.template consumes<edm::ValueMap<int> >(tag);
315  }
316 }
317 
319 
320  rhoToken_ = sumes.consumes<double>(rhoTag_);
322 
324  bunchSpacingToken_ = sumes.consumes<unsigned int>(bunchspacingTag_);
325 
326  //setup electrons
327  if(!(empty_tag == e_conf.electron_src))
329 
330  for ( std::unordered_map<std::string, ValMapFloatTagTokenPair>::iterator imap = e_conf.tag_float_token_map.begin();
331  imap != e_conf.tag_float_token_map.end();
332  imap++) {
333  make_consumes(imap->second.first, imap->second.second, sumes);
334  }
335 
336  for ( std::unordered_map<std::string, ValMapIntTagTokenPair>::iterator imap = e_conf.tag_int_token_map.begin();
337  imap != e_conf.tag_int_token_map.end();
338  imap++) {
339  make_int_consumes(imap->second.first, imap->second.second, sumes);
340  }
341 
342  // setup photons
343  if(!(empty_tag == ph_conf.photon_src))
345 
346  for ( std::unordered_map<std::string, ValMapFloatTagTokenPair>::iterator imap = ph_conf.tag_float_token_map.begin();
347  imap != ph_conf.tag_float_token_map.end();
348  imap++) {
349  make_consumes(imap->second.first, imap->second.second, sumes);
350  }
351 
352  for ( std::unordered_map<std::string, ValMapIntTagTokenPair>::iterator imap = ph_conf.tag_int_token_map.begin();
353  imap != ph_conf.tag_int_token_map.end();
354  imap++) {
355  make_int_consumes(imap->second.first, imap->second.second, sumes);
356  }
357 }
358 
359 namespace {
360  template<typename T, typename U, typename V, typename Z>
361  inline void assignValue(const T& ptr, const U& tok, const V& map, Z& value) {
362  if( !tok.isUninitialized() ) value = map.find(tok.index())->second->get(ptr.id(),ptr.key());
363  }
364 }
365 
367  // regression calculation needs no additional valuemaps
368 
369  const reco::SuperClusterRef& the_sc = ele.superCluster();
370  const edm::Ptr<reco::CaloCluster>& theseed = the_sc->seed();
371  const int numberOfClusters = the_sc->clusters().size();
372  const bool missing_clusters = !the_sc->clusters()[numberOfClusters-1].isAvailable();
373 
374  if( missing_clusters ) return ; // do not apply corrections in case of missing info (slimmed MiniAOD electrons)
375 
376  std::array<float, 33> eval;
377  const double raw_energy = the_sc->rawEnergy();
378  const auto& ess = ele.showerShape();
379 
380  // SET INPUTS
381  eval[0] = nVtx_;
382  eval[1] = raw_energy;
383  eval[2] = the_sc->eta();
384  eval[3] = the_sc->phi();
385  eval[4] = the_sc->etaWidth();
386  eval[5] = the_sc->phiWidth();
387  eval[6] = ess.r9;
388  eval[7] = theseed->energy()/raw_energy;
389  eval[8] = ess.eMax/raw_energy;
390  eval[9] = ess.e2nd/raw_energy;
391  eval[10] = (ess.eLeft + ess.eRight != 0.f ? (ess.eLeft-ess.eRight)/(ess.eLeft+ess.eRight) : 0.f);
392  eval[11] = (ess.eTop + ess.eBottom != 0.f ? (ess.eTop-ess.eBottom)/(ess.eTop+ess.eBottom) : 0.f);
393  eval[12] = ess.sigmaIetaIeta;
394  eval[13] = ess.sigmaIetaIphi;
395  eval[14] = ess.sigmaIphiIphi;
396  eval[15] = std::max(0,numberOfClusters-1);
397 
398  // calculate sub-cluster variables
399  std::vector<float> clusterRawEnergy;
400  clusterRawEnergy.resize(std::max(3, numberOfClusters), 0);
401  std::vector<float> clusterDEtaToSeed;
402  clusterDEtaToSeed.resize(std::max(3, numberOfClusters), 0);
403  std::vector<float> clusterDPhiToSeed;
404  clusterDPhiToSeed.resize(std::max(3, numberOfClusters), 0);
405  float clusterMaxDR = 999.;
406  float clusterMaxDRDPhi = 999.;
407  float clusterMaxDRDEta = 999.;
408  float clusterMaxDRRawEnergy = 0.;
409 
410  size_t iclus = 0;
411  float maxDR = 0;
413  // loop over all clusters that aren't the seed
414  auto clusend = the_sc->clustersEnd();
415  for( auto clus = the_sc->clustersBegin(); clus != clusend; ++clus ) {
416  pclus = *clus;
417 
418  if(theseed == pclus )
419  continue;
420  clusterRawEnergy[iclus] = pclus->energy();
421  clusterDPhiToSeed[iclus] = reco::deltaPhi(pclus->phi(),theseed->phi());
422  clusterDEtaToSeed[iclus] = pclus->eta() - theseed->eta();
423 
424  // find cluster with max dR
425  const auto the_dr = reco::deltaR(*pclus, *theseed);
426  if(the_dr > maxDR) {
427  maxDR = the_dr;
428  clusterMaxDR = maxDR;
429  clusterMaxDRDPhi = clusterDPhiToSeed[iclus];
430  clusterMaxDRDEta = clusterDEtaToSeed[iclus];
431  clusterMaxDRRawEnergy = clusterRawEnergy[iclus];
432  }
433  ++iclus;
434  }
435 
436  eval[16] = clusterMaxDR;
437  eval[17] = clusterMaxDRDPhi;
438  eval[18] = clusterMaxDRDEta;
439  eval[19] = clusterMaxDRRawEnergy/raw_energy;
440  eval[20] = clusterRawEnergy[0]/raw_energy;
441  eval[21] = clusterRawEnergy[1]/raw_energy;
442  eval[22] = clusterRawEnergy[2]/raw_energy;
443  eval[23] = clusterDPhiToSeed[0];
444  eval[24] = clusterDPhiToSeed[1];
445  eval[25] = clusterDPhiToSeed[2];
446  eval[26] = clusterDEtaToSeed[0];
447  eval[27] = clusterDEtaToSeed[1];
448  eval[28] = clusterDEtaToSeed[2];
449 
450  // calculate coordinate variables
451  const bool iseb = ele.isEB();
452  float dummy;
453  int iPhi;
454  int iEta;
455  float cryPhi;
456  float cryEta;
457  EcalClusterLocal _ecalLocal;
458  if (ele.isEB())
459  _ecalLocal.localCoordsEB(*theseed, *iSetup_, cryEta, cryPhi, iEta, iPhi, dummy, dummy);
460  else
461  _ecalLocal.localCoordsEE(*theseed, *iSetup_, cryEta, cryPhi, iEta, iPhi, dummy, dummy);
462 
463  if (iseb) {
464  eval[29] = cryEta;
465  eval[30] = cryPhi;
466  eval[31] = iEta;
467  eval[32] = iPhi;
468  } else {
469  eval[29] = the_sc->preshowerEnergy()/the_sc->rawEnergy();
470  }
471 
472  //magic numbers for MINUIT-like transformation of BDT output onto limited range
473  //(These should be stored inside the conditions object in the future as well)
474  constexpr double meanlimlow = 0.2;
475  constexpr double meanlimhigh = 2.0;
476  constexpr double meanoffset = meanlimlow + 0.5*(meanlimhigh-meanlimlow);
477  constexpr double meanscale = 0.5*(meanlimhigh-meanlimlow);
478 
479  constexpr double sigmalimlow = 0.0002;
480  constexpr double sigmalimhigh = 0.5;
481  constexpr double sigmaoffset = sigmalimlow + 0.5*(sigmalimhigh-sigmalimlow);
482  constexpr double sigmascale = 0.5*(sigmalimhigh-sigmalimlow);
483 
484  int coridx = 0;
485  if (!iseb)
486  coridx = 1;
487 
488  //these are the actual BDT responses
489  double rawmean = e_forestH_mean_[coridx]->GetResponse(eval.data());
490  double rawsigma = e_forestH_sigma_[coridx]->GetResponse(eval.data());
491 
492  //apply transformation to limited output range (matching the training)
493  double mean = meanoffset + meanscale*vdt::fast_sin(rawmean);
494  double sigma = sigmaoffset + sigmascale*vdt::fast_sin(rawsigma);
495 
496  //regression target is ln(Etrue/Eraw)
497  //so corrected energy is ecor=exp(mean)*e, uncertainty is exp(mean)*eraw*sigma=ecor*sigma
498  double ecor = mean*(eval[1]);
499  if (!iseb)
500  ecor = mean*(eval[1]+the_sc->preshowerEnergy());
501  const double sigmacor = sigma*ecor;
502 
503  ele.setCorrectedEcalEnergy(ecor);
504  ele.setCorrectedEcalEnergyError(sigmacor);
505 
506  // E-p combination
507  //std::array<float, 11> eval_ep;
508  float eval_ep[11];
509 
510  const float ep = ele.trackMomentumAtVtx().R();
511  const float tot_energy = the_sc->rawEnergy()+the_sc->preshowerEnergy();
512  const float momentumError = ele.trackMomentumError();
513  const float trkMomentumRelError = ele.trackMomentumError()/ep;
514  const float eOverP = tot_energy*mean/ep;
515  eval_ep[0] = tot_energy*mean;
516  eval_ep[1] = sigma/mean;
517  eval_ep[2] = ep;
518  eval_ep[3] = trkMomentumRelError;
519  eval_ep[4] = sigma/mean/trkMomentumRelError;
520  eval_ep[5] = tot_energy*mean/ep;
521  eval_ep[6] = tot_energy*mean/ep*sqrt(sigma/mean*sigma/mean+trkMomentumRelError*trkMomentumRelError);
522  eval_ep[7] = ele.ecalDriven();
523  eval_ep[8] = ele.trackerDrivenSeed();
524  eval_ep[9] = int(ele.classification());//eleClass;
525  eval_ep[10] = iseb;
526 
527  // CODE FOR FUTURE SEMI_PARAMETRIC
528  //double rawweight = ep_forestH_mean_[coridx]->GetResponse(eval_ep.data());
530  //double weight = meanoffset + meanscale*vdt::fast_sin(rawweight);
532 
533  // CODE FOR STANDARD BDT
534  double weight = 0.;
535  if ( eOverP > 0.025 &&
536  std::abs(ep-ecor) < 15.*std::sqrt( momentumError*momentumError + sigmacor*sigmacor ) &&
537  (!applyExtraHighEnergyProtection_ || ((momentumError < 10.*ep) || (ecor < 200.)))
538  ) {
539  // protection against crazy track measurement
540  weight = ep_forestH_weight_->GetResponse(eval_ep);
541  if(weight>1.)
542  weight = 1.;
543  else if(weight<0.)
544  weight = 0.;
545  }
546 
547  double combinedMomentum = weight*ele.trackMomentumAtVtx().R() + (1.-weight)*ecor;
548  double combinedMomentumError = sqrt(weight*weight*ele.trackMomentumError()*ele.trackMomentumError() + (1.-weight)*(1.-weight)*sigmacor*sigmacor);
549 
550  math::XYZTLorentzVector oldMomentum = ele.p4();
551  math::XYZTLorentzVector newMomentum = math::XYZTLorentzVector(oldMomentum.x()*combinedMomentum/oldMomentum.t(),
552  oldMomentum.y()*combinedMomentum/oldMomentum.t(),
553  oldMomentum.z()*combinedMomentum/oldMomentum.t(),
554  combinedMomentum);
555 
556  //ele.correctEcalEnergy(combinedMomentum, combinedMomentumError);
557  ele.correctMomentum(newMomentum, ele.trackMomentumError(), combinedMomentumError);
558 }
559 
561  modifyObject(static_cast<reco::GsfElectron&>(ele));
562 }
563 
565  // regression calculation needs no additional valuemaps
566 
567  std::array<float, 35> eval;
568  const reco::SuperClusterRef& the_sc = pho.superCluster();
569  const edm::Ptr<reco::CaloCluster>& theseed = the_sc->seed();
570 
571  const int numberOfClusters = the_sc->clusters().size();
572  const bool missing_clusters = !the_sc->clusters()[numberOfClusters-1].isAvailable();
573 
574  if( missing_clusters ) return ; // do not apply corrections in case of missing info (slimmed MiniAOD electrons)
575 
576  const double raw_energy = the_sc->rawEnergy();
577  const auto& ess = pho.showerShapeVariables();
578 
579  // SET INPUTS
580  eval[0] = raw_energy;
581  eval[1] = pho.r9();
582  eval[2] = the_sc->etaWidth();
583  eval[3] = the_sc->phiWidth();
584  eval[4] = std::max(0,numberOfClusters - 1);
585  eval[5] = pho.hadronicOverEm();
586  eval[6] = rhoValue_;
587  eval[7] = nVtx_;
588  eval[8] = theseed->eta()-the_sc->position().Eta();
589  eval[9] = reco::deltaPhi(theseed->phi(),the_sc->position().Phi());
590  eval[10] = theseed->energy()/raw_energy;
591  eval[11] = ess.e3x3/ess.e5x5;
592  eval[12] = ess.sigmaIetaIeta;
593  eval[13] = ess.sigmaIphiIphi;
594  eval[14] = ess.sigmaIetaIphi/(ess.sigmaIphiIphi*ess.sigmaIetaIeta);
595  eval[15] = ess.maxEnergyXtal/ess.e5x5;
596  eval[16] = ess.e2nd/ess.e5x5;
597  eval[17] = ess.eTop/ess.e5x5;
598  eval[18] = ess.eBottom/ess.e5x5;
599  eval[19] = ess.eLeft/ess.e5x5;
600  eval[20] = ess.eRight/ess.e5x5;
601  eval[21] = ess.e2x5Max/ess.e5x5;
602  eval[22] = ess.e2x5Left/ess.e5x5;
603  eval[23] = ess.e2x5Right/ess.e5x5;
604  eval[24] = ess.e2x5Top/ess.e5x5;
605  eval[25] = ess.e2x5Bottom/ess.e5x5;
606 
607  const bool iseb = pho.isEB();
608  if (iseb) {
609  EBDetId ebseedid(theseed->seed());
610  eval[26] = pho.e5x5()/theseed->energy();
611  int ieta = ebseedid.ieta();
612  int iphi = ebseedid.iphi();
613  eval[27] = ieta;
614  eval[28] = iphi;
615  int signieta = ieta > 0 ? +1 : -1;
616  eval[29] = (ieta-signieta)%5;
617  eval[30] = (iphi-1)%2;
618  // eval[31] = (abs(ieta)<=25)*((ieta-signieta)%25) + (abs(ieta)>25)*((ieta-26*signieta)%20); //%25 is unnescessary in this formula
619  eval[31] = (abs(ieta)<=25)*((ieta-signieta)) + (abs(ieta)>25)*((ieta-26*signieta)%20);
620  eval[32] = (iphi-1)%20;
621  eval[33] = ieta;
622  eval[34] = iphi;
623  } else {
624  EEDetId eeseedid(theseed->seed());
625  eval[26] = the_sc->preshowerEnergy()/raw_energy;
626  eval[27] = the_sc->preshowerEnergyPlane1()/raw_energy;
627  eval[28] = the_sc->preshowerEnergyPlane2()/raw_energy;
628  eval[29] = eeseedid.ix();
629  eval[30] = eeseedid.iy();
630  }
631 
632  //magic numbers for MINUIT-like transformation of BDT output onto limited range
633  //(These should be stored inside the conditions object in the future as well)
634  const double meanlimlow = 0.2;
635  const double meanlimhigh = 2.0;
636  const double meanoffset = meanlimlow + 0.5*(meanlimhigh-meanlimlow);
637  const double meanscale = 0.5*(meanlimhigh-meanlimlow);
638 
639  const double sigmalimlow = 0.0002;
640  const double sigmalimhigh = 0.5;
641  const double sigmaoffset = sigmalimlow + 0.5*(sigmalimhigh-sigmalimlow);
642  const double sigmascale = 0.5*(sigmalimhigh-sigmalimlow);
643 
644  int coridx = 0;
645  if (!iseb)
646  coridx = 1;
647 
648  //these are the actual BDT responses
649  double rawmean = ph_forestH_mean_[coridx]->GetResponse(eval.data());
650  double rawsigma = ph_forestH_sigma_[coridx]->GetResponse(eval.data());
651  //apply transformation to limited output range (matching the training)
652  double mean = meanoffset + meanscale*vdt::fast_sin(rawmean);
653  double sigma = sigmaoffset + sigmascale*vdt::fast_sin(rawsigma);
654 
655  //regression target is ln(Etrue/Eraw)
656  //so corrected energy is ecor=exp(mean)*e, uncertainty is exp(mean)*eraw*sigma=ecor*sigma
657  double ecor = mean*eval[0];
658  if (!iseb)
659  ecor = mean*(eval[0]+the_sc->preshowerEnergy());
660 
661  double sigmacor = sigma*ecor;
662  pho.setCorrectedEnergy(reco::Photon::P4type::regression2, ecor, sigmacor, true);
663 }
664 
666  modifyObject(static_cast<reco::Photon&>(pho));
667 }
edm::EDGetTokenT< reco::VertexCollection > vtxToken_
double GetResponse(const float *vector) const
Definition: GBRForest.h:59
constexpr double deltaPhi(double phi1, double phi2)
Definition: deltaPhi.h:22
const ShowerShape & showerShape() const
Definition: GsfElectron.h:454
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
bool isAvailable() const
Definition: Ref.h:577
std::vector< std::string > condnames_sigma_25ns
T getParameter(std::string const &) const
Analysis-level Photon class.
Definition: Photon.h:47
void setEventContent(const edm::EventSetup &) final
std::unordered_map< unsigned, edm::Handle< edm::ValueMap< float > > > pho_vmaps
float trackMomentumError() const
Definition: GsfElectron.h:836
bool existsAs(std::string const &parameterName, bool trackiness=true) const
checks if a parameter exists as a given type
Definition: ParameterSet.h:186
edm::Handle< reco::VertexCollection > vtxH_
const LorentzVector & p4(P4Kind kind) const
Definition: GsfElectron.cc:225
key_type key() const
Definition: Ptr.h:185
std::unordered_map< unsigned, edm::Handle< edm::ValueMap< int > > > pho_int_vmaps
void setCorrectedEnergy(P4type type, float E, float dE, bool toCand=true)
float e5x5() const
Definition: Photon.h:228
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:579
std::vector< const GBRForestD * > ph_forestH_sigma_
std::unordered_map< unsigned, edm::Handle< edm::ValueMap< int > > > ele_int_vmaps
std::unordered_map< unsigned, edm::Ptr< reco::Photon > > phos_by_oop
void correctMomentum(const LorentzVector &p4, float trackMomentumError, float p4Error)
Definition: GsfElectron.h:858
math::XYZVectorF trackMomentumAtVtx() const
Definition: GsfElectron.h:291
std::vector< const GBRForestD * > e_forestH_mean_
bool exists(std::string const &parameterName) const
checks if a parameter exists
std::unordered_map< unsigned, edm::Handle< edm::ValueMap< float > > > ele_vmaps
std::vector< Vertex > VertexCollection
collection of Vertex objects
Definition: VertexFwd.h:9
Definition: weight.py:1
std::unordered_map< unsigned, edm::Ptr< reco::GsfElectron > > eles_by_oop
std::vector< const GBRForestD * > ph_forestH_mean_
reco::SuperClusterRef superCluster() const override
Ref to SuperCluster.
std::unordered_map< std::string, ValMapFloatTagTokenPair > tag_float_token_map
#define constexpr
bool isEB() const
Definition: GsfElectron.h:352
double eta() const
pseudorapidity of cluster centroid
Definition: CaloCluster.h:168
void setEvent(const edm::Event &) final
return((rh^lh)&mask)
edm::EDGetTokenT< edm::View< pat::Electron > > tok_electron_src
U second(std::pair< T, U > const &p)
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
std::unordered_map< std::string, ValMapIntTagTokenPair > tag_int_token_map
void setCorrectedEcalEnergyError(float newEnergyError)
Definition: GsfElectron.cc:179
std::pair< edm::InputTag, ValMapFloatToken > ValMapFloatTagTokenPair
const std::string & name() const
std::unordered_map< std::string, ValMapFloatTagTokenPair > tag_float_token_map
T sqrt(T t)
Definition: SSEVec.h:18
std::vector< std::string > condnames_mean_25ns
const GBRForest * ep_forestH_weight_
edm::EDGetTokenT< edm::ValueMap< int > > ValMapIntToken
edm::EDGetTokenT< edm::ValueMap< float > > ValMapFloatToken
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::pair< edm::InputTag, ValMapIntToken > ValMapIntTagTokenPair
double energy() const
cluster energy
Definition: CaloCluster.h:126
edm::EDGetTokenT< double > rhoToken_
const edm::EventSetup * iSetup_
Definition: value.py:1
float hadronicOverEm() const
the total hadronic over electromagnetic fraction
Definition: Photon.h:206
std::vector< std::string > getParameterNames() const
const edm::Ptr< reco::Candidate > & originalObjectRef() const
reference to original object. Returns a null reference if not available
Definition: PATObject.h:500
void modifyObject(reco::GsfElectron &) const final
EGRegressionModifierV1(const edm::ParameterSet &conf)
edm::EDGetTokenT< edm::View< pat::Photon > > tok_photon_src
constexpr auto deltaR(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
Definition: deltaR.h:28
DetId seed() const
return DetId of seed
Definition: CaloCluster.h:207
std::vector< const GBRForestD * > e_forestH_sigma_
Classification classification() const
Definition: GsfElectron.h:757
Analysis-level electron class.
Definition: Electron.h:52
void setConsumes(edm::ConsumesCollector &) final
void localCoordsEB(const reco::CaloCluster &bclus, const edm::EventSetup &es, float &etacry, float &phicry, int &ieta, int &iphi, float &thetatilt, float &phitilt) const
bool isEB() const
Definition: Photon.h:121
void setCorrectedEcalEnergy(float newEnergy)
Definition: GsfElectron.cc:182
std::vector< std::string > condnames_sigma_50ns
std::vector< std::string > condnames_mean_50ns
T get() const
Definition: EventSetup.h:63
float r9() const
Definition: Photon.h:234
SuperClusterRef superCluster() const override
reference to a SuperCluster
Definition: GsfElectron.h:184
bool trackerDrivenSeed() const
Definition: GsfElectron.h:189
std::unordered_map< std::string, ValMapIntTagTokenPair > tag_int_token_map
bool isUninitialized() const
Definition: EDGetToken.h:73
#define DEFINE_EDM_PLUGIN(factory, type, name)
double phi() const
azimuthal angle of cluster centroid
Definition: CaloCluster.h:171
void localCoordsEE(const reco::CaloCluster &bclus, const edm::EventSetup &es, float &xcry, float &ycry, int &ix, int &iy, float &thetatilt, float &phitilt) const
edm::EDGetTokenT< unsigned int > bunchSpacingToken_
long double T
const ShowerShape & showerShapeVariables() const
Definition: Photon.h:199
bool ecalDriven() const
Definition: GsfElectron.cc:174
T const * product() const
Definition: ESHandle.h:86