CMS 3D CMS Logo

EGRegressionModifierV2.cc
Go to the documentation of this file.
7 
10 
14 
15 #include <vdt/vdtMath.h>
16 
17 namespace {
18  const edm::InputTag empty_tag;
19 }
20 
21 #include <unordered_map>
22 
24 public:
27  typedef std::pair<edm::InputTag, ValMapFloatToken> ValMapFloatTagTokenPair;
28  typedef std::pair<edm::InputTag, ValMapIntToken> ValMapIntTagTokenPair;
29 
30  struct electron_config {
33  std::unordered_map<std::string, ValMapFloatTagTokenPair> tag_float_token_map;
34  std::unordered_map<std::string, ValMapIntTagTokenPair> tag_int_token_map;
35 
36  std::vector<std::string> condnames_ecalonly_mean;
37  std::vector<std::string> condnames_ecalonly_sigma;
38  std::vector<std::string> condnames_ecaltrk_mean;
39  std::vector<std::string> condnames_ecaltrk_sigma;
40  };
41 
42  struct photon_config {
45  std::unordered_map<std::string, ValMapFloatTagTokenPair> tag_float_token_map;
46  std::unordered_map<std::string, ValMapIntTagTokenPair> tag_int_token_map;
47 
48  std::vector<std::string> condnames_ecalonly_mean;
49  std::vector<std::string> condnames_ecalonly_sigma;
50  };
51 
53  ~EGRegressionModifierV2() override;
54 
55  void setEvent(const edm::Event&) final;
56  void setEventContent(const edm::EventSetup&) final;
57  void setConsumes(edm::ConsumesCollector&) final;
58 
59  void modifyObject(reco::GsfElectron&) const final;
60  void modifyObject(reco::Photon&) const final;
61 
62  // just calls reco versions
63  void modifyObject(pat::Electron&) const final;
64  void modifyObject(pat::Photon&) const final;
65 
66 private:
69  std::unordered_map<unsigned,edm::Ptr<reco::GsfElectron> > eles_by_oop; // indexed by original object ptr
70  std::unordered_map<unsigned,edm::Handle<edm::ValueMap<float> > > ele_vmaps;
71  std::unordered_map<unsigned,edm::Handle<edm::ValueMap<int> > > ele_int_vmaps;
72  std::unordered_map<unsigned,edm::Ptr<reco::Photon> > phos_by_oop;
73  std::unordered_map<unsigned,edm::Handle<edm::ValueMap<float> > > pho_vmaps;
74  std::unordered_map<unsigned,edm::Handle<edm::ValueMap<int> > > pho_int_vmaps;
75 
76  float rhoValue_;
77  edm::InputTag rhoTag_;
78  edm::EDGetTokenT<double> rhoToken_;
79 
81 
82  std::vector<const GBRForestD*> ph_forestH_mean_;
83  std::vector<const GBRForestD*> ph_forestH_sigma_;
84  std::vector<const GBRForestD*> e_forestH_mean_;
85  std::vector<const GBRForestD*> e_forestH_sigma_;
86 
87  double lowEnergy_ECALonlyThr_; // 300
88  double lowEnergy_ECALTRKThr_; // 50
89  double highEnergy_ECALTRKThr_; // 200
90  double eOverP_ECALTRKThr_; // 0.025
91  double epDiffSig_ECALTRKThr_; // 15
92  double epSig_ECALTRKThr_; // 10
94 
95 
96 };
97 
100  "EGRegressionModifierV2");
101 
102 EGRegressionModifierV2::EGRegressionModifierV2(const edm::ParameterSet& conf) :
103  ModifyObjectValueBase(conf) {
104 
105  lowEnergy_ECALonlyThr_ = conf.getParameter<double>("lowEnergy_ECALonlyThr");
106  lowEnergy_ECALTRKThr_ = conf.getParameter<double>("lowEnergy_ECALTRKThr");
107  highEnergy_ECALTRKThr_ = conf.getParameter<double>("highEnergy_ECALTRKThr");
108  eOverP_ECALTRKThr_ = conf.getParameter<double>("eOverP_ECALTRKThr");
109  epDiffSig_ECALTRKThr_ = conf.getParameter<double>("epDiffSig_ECALTRKThr");
110  epSig_ECALTRKThr_ = conf.getParameter<double>("epSig_ECALTRKThr");
111  forceHighEnergyEcalTrainingIfSaturated_ = conf.getParameter<bool>("forceHighEnergyEcalTrainingIfSaturated");
112  rhoTag_ = conf.getParameter<edm::InputTag>("rhoCollection");
113 
114  constexpr char electronSrc[] = "electronSrc";
115  constexpr char photonSrc[] = "photonSrc";
116 
117  if(conf.exists("electron_config")) {
118  const edm::ParameterSet& electrons = conf.getParameter<edm::ParameterSet>("electron_config");
119  if( electrons.exists(electronSrc) )
120  e_conf.electron_src = electrons.getParameter<edm::InputTag>(electronSrc);
121 
122  std::vector<std::string> intValueMaps;
123  if ( electrons.existsAs<std::vector<std::string> >("intValueMaps"))
124  intValueMaps = electrons.getParameter<std::vector<std::string> >("intValueMaps");
125 
126  const std::vector<std::string> parameters = electrons.getParameterNames();
127  for( const std::string& name : parameters ) {
128  if( std::string(electronSrc) == name )
129  continue;
130  if( electrons.existsAs<edm::InputTag>(name)) {
131  for (auto vmp : intValueMaps) {
132  if (name == vmp) {
133  e_conf.tag_int_token_map[name] = ValMapIntTagTokenPair(electrons.getParameter<edm::InputTag>(name), ValMapIntToken());
134  break;
135  }
136  }
137  e_conf.tag_float_token_map[name] = ValMapFloatTagTokenPair(electrons.getParameter<edm::InputTag>(name), ValMapFloatToken());
138  }
139  }
140 
141  e_conf.condnames_ecalonly_mean = electrons.getParameter<std::vector<std::string> >("regressionKey_ecalonly");
142  e_conf.condnames_ecalonly_sigma = electrons.getParameter<std::vector<std::string> >("uncertaintyKey_ecalonly");
143  e_conf.condnames_ecaltrk_mean = electrons.getParameter<std::vector<std::string> >("regressionKey_ecaltrk");
144  e_conf.condnames_ecaltrk_sigma = electrons.getParameter<std::vector<std::string> >("uncertaintyKey_ecaltrk");
145 
146  unsigned int encor = e_conf.condnames_ecalonly_mean.size();
147  e_forestH_mean_.reserve(2*encor);
148  e_forestH_sigma_.reserve(2*encor);
149 
150  }
151 
152  if( conf.exists("photon_config") ) {
153  const edm::ParameterSet& photons = conf.getParameter<edm::ParameterSet>("photon_config");
154 
155  if( photons.exists(photonSrc) )
156  ph_conf.photon_src = photons.getParameter<edm::InputTag>(photonSrc);
157 
158  std::vector<std::string> intValueMaps;
159  if ( photons.existsAs<std::vector<std::string> >("intValueMaps"))
160  intValueMaps = photons.getParameter<std::vector<std::string> >("intValueMaps");
161 
162  const std::vector<std::string> parameters = photons.getParameterNames();
163  for( const std::string& name : parameters ) {
164  if( std::string(photonSrc) == name )
165  continue;
166  if( photons.existsAs<edm::InputTag>(name)) {
167  for (auto vmp : intValueMaps) {
168  if (name == vmp) {
169  ph_conf.tag_int_token_map[name] = ValMapIntTagTokenPair(photons.getParameter<edm::InputTag>(name), ValMapIntToken());
170  break;
171  }
172  }
173  ph_conf.tag_float_token_map[name] = ValMapFloatTagTokenPair(photons.getParameter<edm::InputTag>(name), ValMapFloatToken());
174  }
175  }
176 
177  ph_conf.condnames_ecalonly_mean = photons.getParameter<std::vector<std::string>>("regressionKey_ecalonly");
178  ph_conf.condnames_ecalonly_sigma = photons.getParameter<std::vector<std::string>>("uncertaintyKey_ecalonly");
179 
180  unsigned int ncor = ph_conf.condnames_ecalonly_mean.size();
181  ph_forestH_mean_.reserve(ncor);
182  ph_forestH_sigma_.reserve(ncor);
183 
184  }
185 
186 
187 }
188 
189 namespace {
190  template<typename T>
191  inline void get_product(const edm::Event& evt,
192  const edm::EDGetTokenT<edm::ValueMap<T> >& tok,
193  std::unordered_map<unsigned, edm::Handle<edm::ValueMap<T> > >& map) {
194  evt.getByToken(tok,map[tok.index()]);
195  }
196 }
197 
199 
201 
202  eles_by_oop.clear();
203  phos_by_oop.clear();
204  ele_vmaps.clear();
205  ele_int_vmaps.clear();
206  pho_vmaps.clear();
207  pho_int_vmaps.clear();
208 
212 
213  for( unsigned i = 0; i < eles->size(); ++i ) {
214  edm::Ptr<pat::Electron> ptr = eles->ptrAt(i);
215  eles_by_oop[ptr->originalObjectRef().key()] = ptr;
216  }
217  }
218 
219  for (std::unordered_map<std::string, ValMapFloatTagTokenPair>::iterator imap = e_conf.tag_float_token_map.begin();
220  imap != e_conf.tag_float_token_map.end();
221  imap++) {
222  get_product(evt, imap->second.second, ele_vmaps);
223  }
224 
225  for (std::unordered_map<std::string, ValMapIntTagTokenPair>::iterator imap = e_conf.tag_int_token_map.begin();
226  imap != e_conf.tag_int_token_map.end();
227  imap++) {
228  get_product(evt, imap->second.second, ele_int_vmaps);
229  }
230 
234 
235  for( unsigned i = 0; i < phos->size(); ++i ) {
236  edm::Ptr<pat::Photon> ptr = phos->ptrAt(i);
237  phos_by_oop[ptr->originalObjectRef().key()] = ptr;
238  }
239  }
240 
241 
242  for (std::unordered_map<std::string, ValMapFloatTagTokenPair>::iterator imap = ph_conf.tag_float_token_map.begin();
243  imap != ph_conf.tag_float_token_map.end();
244  imap++) {
245  get_product(evt, imap->second.second, pho_vmaps);
246  }
247 
248  for (std::unordered_map<std::string, ValMapIntTagTokenPair>::iterator imap = ph_conf.tag_int_token_map.begin();
249  imap != ph_conf.tag_int_token_map.end();
250  imap++) {
251  get_product(evt, imap->second.second, pho_int_vmaps);
252  }
253 
254  edm::Handle<double> rhoH;
255  evt.getByToken(rhoToken_, rhoH);
256  rhoValue_ = *rhoH;
257 
258 }
259 
261 
262  iSetup_ = &evs;
263 
264  edm::ESHandle<GBRForestD> forestDEH;
265 
266  const std::vector<std::string> ph_condnames_ecalonly_mean = ph_conf.condnames_ecalonly_mean;
267  const std::vector<std::string> ph_condnames_ecalonly_sigma = ph_conf.condnames_ecalonly_sigma;
268 
269  unsigned int ncor = ph_condnames_ecalonly_mean.size();
270  for (unsigned int icor=0; icor<ncor; ++icor) {
271  evs.get<GBRDWrapperRcd>().get(ph_condnames_ecalonly_mean[icor], forestDEH);
272  ph_forestH_mean_[icor] = forestDEH.product();
273  evs.get<GBRDWrapperRcd>().get(ph_condnames_ecalonly_sigma[icor], forestDEH);
274  ph_forestH_sigma_[icor] = forestDEH.product();
275  }
276 
277  const std::vector<std::string> e_condnames_ecalonly_mean = e_conf.condnames_ecalonly_mean;
278  const std::vector<std::string> e_condnames_ecalonly_sigma = e_conf.condnames_ecalonly_sigma;
279  const std::vector<std::string> e_condnames_ecaltrk_mean = e_conf.condnames_ecaltrk_mean;
280  const std::vector<std::string> e_condnames_ecaltrk_sigma = e_conf.condnames_ecaltrk_sigma;
281 
282  unsigned int encor = e_condnames_ecalonly_mean.size();
283  for (unsigned int icor=0; icor<encor; ++icor) {
284  evs.get<GBRDWrapperRcd>().get(e_condnames_ecalonly_mean[icor], forestDEH);
285  e_forestH_mean_[icor] = forestDEH.product();
286  evs.get<GBRDWrapperRcd>().get(e_condnames_ecalonly_sigma[icor], forestDEH);
287  e_forestH_sigma_[icor] = forestDEH.product();
288  }
289  for (unsigned int icor=0; icor<encor; ++icor) {
290  evs.get<GBRDWrapperRcd>().get(e_condnames_ecaltrk_mean[icor], forestDEH);
291  e_forestH_mean_[icor+encor] = forestDEH.product();
292  evs.get<GBRDWrapperRcd>().get(e_condnames_ecaltrk_sigma[icor], forestDEH);
293  e_forestH_sigma_[icor+encor] = forestDEH.product();
294  }
295 
296 }
297 
298 namespace {
299  template<typename T, typename U, typename V>
300  inline void make_consumes(T& tag,U& tok,V& sume) {
301  if(!(empty_tag == tag))
302  tok = sume.template consumes<edm::ValueMap<float> >(tag);
303  }
304 
305  template<typename T, typename U, typename V>
306  inline void make_int_consumes(T& tag,U& tok,V& sume) {
307  if(!(empty_tag == tag))
308  tok = sume.template consumes<edm::ValueMap<int> >(tag);
309  }
310 }
311 
313 
314  rhoToken_ = sumes.consumes<double>(rhoTag_);
315 
316  //setup electrons
317  if(!(empty_tag == e_conf.electron_src))
319 
320  for ( std::unordered_map<std::string, ValMapFloatTagTokenPair>::iterator imap = e_conf.tag_float_token_map.begin();
321  imap != e_conf.tag_float_token_map.end();
322  imap++) {
323  make_consumes(imap->second.first, imap->second.second, sumes);
324  }
325 
326  for ( std::unordered_map<std::string, ValMapIntTagTokenPair>::iterator imap = e_conf.tag_int_token_map.begin();
327  imap != e_conf.tag_int_token_map.end();
328  imap++) {
329  make_int_consumes(imap->second.first, imap->second.second, sumes);
330  }
331 
332  // setup photons
333  if(!(empty_tag == ph_conf.photon_src))
335 
336  for ( std::unordered_map<std::string, ValMapFloatTagTokenPair>::iterator imap = ph_conf.tag_float_token_map.begin();
337  imap != ph_conf.tag_float_token_map.end();
338  imap++) {
339  make_consumes(imap->second.first, imap->second.second, sumes);
340  }
341 
342  for ( std::unordered_map<std::string, ValMapIntTagTokenPair>::iterator imap = ph_conf.tag_int_token_map.begin();
343  imap != ph_conf.tag_int_token_map.end();
344  imap++) {
345  make_int_consumes(imap->second.first, imap->second.second, sumes);
346  }
347 }
348 
349 namespace {
350  template<typename T, typename U, typename V, typename Z>
351  inline void assignValue(const T& ptr, const U& tok, const V& map, Z& value) {
352  if( !tok.isUninitialized() ) value = map.find(tok.index())->second->get(ptr.id(),ptr.key());
353  }
354 }
355 
357 
358  // regression calculation needs no additional valuemaps
359 
360  const reco::SuperClusterRef& the_sc = ele.superCluster();
361  const edm::Ptr<reco::CaloCluster>& theseed = the_sc->seed();
362 
363  // skip HGCAL for now
364  if( theseed->seed().det() == DetId::Forward ) return;
365 
366  const int numberOfClusters = the_sc->clusters().size();
367  const bool missing_clusters = !the_sc->clusters()[numberOfClusters-1].isAvailable();
368  if( missing_clusters ) return ; // do not apply corrections in case of missing info (slimmed MiniAOD electrons)
369 
370  //check if fbrem is filled as its needed for E/p combination so abort if its set to the default value
371  //this will be the case for <5 (or current cuts) for miniAOD electrons
373 
374  const bool iseb = ele.isEB();
375 
376  std::array<float, 32> eval;
377  const double raw_energy = the_sc->rawEnergy();
378  const double raw_es_energy = the_sc->preshowerEnergy();
379  const auto& full5x5_ess = ele.full5x5_showerShape();
380 
381  float e5x5Inverse = full5x5_ess.e5x5 != 0. ? vdt::fast_inv(full5x5_ess.e5x5) : 0.;
382 
383  eval[0] = raw_energy;
384  eval[1] = the_sc->etaWidth();
385  eval[2] = the_sc->phiWidth();
386  eval[3] = the_sc->seed()->energy()/raw_energy;
387  eval[4] = full5x5_ess.e5x5/raw_energy;
388  eval[5] = ele.hcalOverEcalBc();
389  eval[6] = rhoValue_;
390  eval[7] = theseed->eta() - the_sc->position().Eta();
391  eval[8] = reco::deltaPhi( theseed->phi(),the_sc->position().Phi());
392  eval[9] = full5x5_ess.r9;
393  eval[10] = full5x5_ess.sigmaIetaIeta;
394  eval[11] = full5x5_ess.sigmaIetaIphi;
395  eval[12] = full5x5_ess.sigmaIphiIphi;
396  eval[13] = full5x5_ess.eMax*e5x5Inverse;
397  eval[14] = full5x5_ess.e2nd*e5x5Inverse;
398  eval[15] = full5x5_ess.eTop*e5x5Inverse;
399  eval[16] = full5x5_ess.eBottom*e5x5Inverse;
400  eval[17] = full5x5_ess.eLeft*e5x5Inverse;
401  eval[18] = full5x5_ess.eRight*e5x5Inverse;
402  eval[19] = full5x5_ess.e2x5Max*e5x5Inverse;
403  eval[20] = full5x5_ess.e2x5Left*e5x5Inverse;
404  eval[21] = full5x5_ess.e2x5Right*e5x5Inverse;
405  eval[22] = full5x5_ess.e2x5Top*e5x5Inverse;
406  eval[23] = full5x5_ess.e2x5Bottom*e5x5Inverse;
407  eval[24] = ele.nSaturatedXtals();
408  eval[25] = std::max(0,numberOfClusters);
409 
410  // calculate coordinate variables
411  EcalClusterLocal _ecalLocal;
412  if (iseb) {
413 
414  float dummy;
415  int ieta;
416  int iphi;
417  _ecalLocal.localCoordsEB(*theseed, *iSetup_, dummy, dummy, ieta, iphi, dummy, dummy);
418  eval[26] = ieta;
419  eval[27] = iphi;
420  int signieta = ieta > 0 ? +1 : -1;
421  eval[28] = (ieta-signieta)%5;
422  eval[29] = (iphi-1)%2;
423  eval[30] = (abs(ieta)<=25)*((ieta-signieta)) + (abs(ieta)>25)*((ieta-26*signieta)%20);
424  eval[31] = (iphi-1)%20;
425 
426  } else {
427 
428  float dummy;
429  int ix;
430  int iy;
431  _ecalLocal.localCoordsEE(*theseed, *iSetup_, dummy, dummy, ix, iy, dummy, dummy);
432  eval[26] = ix;
433  eval[27] = iy;
434  eval[28] = raw_es_energy/raw_energy;
435 
436  }
437 
438  //magic numbers for MINUIT-like transformation of BDT output onto limited range
439  //(These should be stored inside the conditions object in the future as well)
440  constexpr double meanlimlow = -1.0;
441  constexpr double meanlimhigh = 3.0;
442  constexpr double meanoffset = meanlimlow + 0.5*(meanlimhigh-meanlimlow);
443  constexpr double meanscale = 0.5*(meanlimhigh-meanlimlow);
444 
445  constexpr double sigmalimlow = 0.0002;
446  constexpr double sigmalimhigh = 0.5;
447  constexpr double sigmaoffset = sigmalimlow + 0.5*(sigmalimhigh-sigmalimlow);
448  constexpr double sigmascale = 0.5*(sigmalimhigh-sigmalimlow);
449 
450 
451  size_t coridx = 0;
452  float raw_pt = raw_energy*the_sc->position().rho()/the_sc->position().r();
453  bool isSaturated = ele.nSaturatedXtals()!=0;
454 
455  if(raw_pt >= lowEnergy_ECALonlyThr_ ||
456  (isSaturated && forceHighEnergyEcalTrainingIfSaturated_)){
457  if(iseb) coridx = 1;
458  else coridx = 3;
459  }else{
460  if(iseb) coridx = 0;
461  else coridx = 2;
462  }
463 
464 
465  //these are the actual BDT responses
466  double rawmean = e_forestH_mean_[coridx]->GetResponse(eval.data());
467  double rawsigma = e_forestH_sigma_[coridx]->GetResponse(eval.data());
468 
469  //apply transformation to limited output range (matching the training)
470  double mean = meanoffset + meanscale*vdt::fast_sin(rawmean);
471  double sigma = sigmaoffset + sigmascale*vdt::fast_sin(rawsigma);
472 
473  // Correct the energy. A negative energy means that the correction went
474  // outside the boundaries of the training. In this case uses raw.
475  // The resolution estimation, on the other hand should be ok.
476  if (mean < 0.) mean = 1.0;
477 
478  const double ecor = mean*(raw_energy + raw_es_energy);
479  const double sigmacor = sigma*ecor;
480 
481  ele.setCorrectedEcalEnergy(ecor);
482  ele.setCorrectedEcalEnergyError(sigmacor);
483 
484  double combinedEnergy = ecor;
485  double combinedEnergyError = sigmacor;
486 
487  auto el_track = ele.gsfTrack();
488  const float trkMomentum = el_track->pMode();
489  const float trkEta = el_track->etaMode();
490  const float trkPhi = el_track->phiMode();
491  const float trkMomentumError = std::abs(el_track->qoverpModeError())*trkMomentum*trkMomentum;
492 
493  const float eOverP = (raw_energy+raw_es_energy)*mean/trkMomentum;
494  const float fbrem = ele.fbrem();
495 
496  // E-p combination
497  if (ecor < highEnergy_ECALTRKThr_ &&
498  eOverP > eOverP_ECALTRKThr_ &&
499  std::abs(ecor - trkMomentum) < epDiffSig_ECALTRKThr_*std::sqrt(trkMomentumError*trkMomentumError+sigmacor*sigmacor) &&
500  trkMomentumError < epSig_ECALTRKThr_*trkMomentum) {
501 
502  raw_pt = ecor/cosh(trkEta);
503  if (iseb && raw_pt < lowEnergy_ECALTRKThr_)
504  coridx = 4;
505  else if (iseb && raw_pt >= lowEnergy_ECALTRKThr_)
506  coridx = 5;
507  else if (!iseb && raw_pt < lowEnergy_ECALTRKThr_)
508  coridx = 6;
509  else if (!iseb && raw_pt >= lowEnergy_ECALTRKThr_)
510  coridx = 7;
511 
512  eval[0] = ecor;
513  eval[1] = sigma/mean;
514  eval[2] = trkMomentumError/trkMomentum;
515  eval[3] = eOverP;
516  eval[4] = ele.ecalDrivenSeed();
517  eval[5] = full5x5_ess.r9;
518  eval[6] = fbrem;
519  eval[7] = trkEta;
520  eval[8] = trkPhi;
521 
522  float ecalEnergyVar = (raw_energy + raw_es_energy)*sigma;
523  float rawcombNormalization = (trkMomentumError*trkMomentumError + ecalEnergyVar*ecalEnergyVar);
524  float rawcomb = ( ecor*trkMomentumError*trkMomentumError + trkMomentum*ecalEnergyVar*ecalEnergyVar ) / rawcombNormalization;
525 
526  //these are the actual BDT responses
527  double rawmean_trk = e_forestH_mean_[coridx]->GetResponse(eval.data());
528  double rawsigma_trk = e_forestH_sigma_[coridx]->GetResponse(eval.data());
529 
530  //apply transformation to limited output range (matching the training)
531  double mean_trk = meanoffset + meanscale*vdt::fast_sin(rawmean_trk);
532  double sigma_trk = sigmaoffset + sigmascale*vdt::fast_sin(rawsigma_trk);
533 
534  // Final correction
535  // A negative energy means that the correction went
536  // outside the boundaries of the training. In this case uses raw.
537  // The resolution estimation, on the other hand should be ok.
538  if (mean_trk < 0.) mean_trk = 1.0;
539 
540  combinedEnergy = mean_trk*rawcomb;
541  combinedEnergyError = sigma_trk*rawcomb;
542  }
543 
544  math::XYZTLorentzVector oldFourMomentum = ele.p4();
545  math::XYZTLorentzVector newFourMomentum = math::XYZTLorentzVector(oldFourMomentum.x()*combinedEnergy/oldFourMomentum.t(),
546  oldFourMomentum.y()*combinedEnergy/oldFourMomentum.t(),
547  oldFourMomentum.z()*combinedEnergy/oldFourMomentum.t(),
548  combinedEnergy);
549 
550  ele.correctMomentum(newFourMomentum, ele.trackMomentumError(), combinedEnergyError);
551 }
552 
554  modifyObject(static_cast<reco::GsfElectron&>(ele));
555 }
556 
558  // regression calculation needs no additional valuemaps
559 
560  const reco::SuperClusterRef& the_sc = pho.superCluster();
561  const edm::Ptr<reco::CaloCluster>& theseed = the_sc->seed();
562 
563  // skip HGCAL for now
564  if( theseed->seed().det() == DetId::Forward ) return;
565 
566  const int numberOfClusters = the_sc->clusters().size();
567  const bool missing_clusters = !the_sc->clusters()[numberOfClusters-1].isAvailable();
568  if( missing_clusters ) return ; // do not apply corrections in case of missing info (slimmed MiniAOD electrons)
569 
570  const bool iseb = pho.isEB();
571 
572  std::array<float, 32> eval;
573  const double raw_energy = the_sc->rawEnergy();
574  const double raw_es_energy = the_sc->preshowerEnergy();
575  const auto& full5x5_pss = pho.full5x5_showerShapeVariables();
576 
577  float e5x5Inverse = full5x5_pss.e5x5 != 0. ? vdt::fast_inv(full5x5_pss.e5x5) : 0.;
578 
579  eval[0] = raw_energy;
580  eval[1] = the_sc->etaWidth();
581  eval[2] = the_sc->phiWidth();
582  eval[3] = the_sc->seed()->energy()/raw_energy;
583  eval[4] = full5x5_pss.e5x5/raw_energy;
584  eval[5] = pho.hadronicOverEm();
585  eval[6] = rhoValue_;
586  eval[7] = theseed->eta() - the_sc->position().Eta();
587  eval[8] = reco::deltaPhi( theseed->phi(),the_sc->position().Phi());
588  eval[9] = pho.full5x5_r9();
589  eval[10] = full5x5_pss.sigmaIetaIeta;
590  eval[11] = full5x5_pss.sigmaIetaIphi;
591  eval[12] = full5x5_pss.sigmaIphiIphi;
592  eval[13] = full5x5_pss.maxEnergyXtal*e5x5Inverse;
593  eval[14] = full5x5_pss.e2nd*e5x5Inverse;
594  eval[15] = full5x5_pss.eTop*e5x5Inverse;
595  eval[16] = full5x5_pss.eBottom*e5x5Inverse;
596  eval[17] = full5x5_pss.eLeft*e5x5Inverse;
597  eval[18] = full5x5_pss.eRight*e5x5Inverse;
598  eval[19] = full5x5_pss.e2x5Max*e5x5Inverse;
599  eval[20] = full5x5_pss.e2x5Left*e5x5Inverse;
600  eval[21] = full5x5_pss.e2x5Right*e5x5Inverse;
601  eval[22] = full5x5_pss.e2x5Top*e5x5Inverse;
602  eval[23] = full5x5_pss.e2x5Bottom*e5x5Inverse;
603  eval[24] = pho.nSaturatedXtals();
604  eval[25] = std::max(0,numberOfClusters);
605 
606  // calculate coordinate variables
607  EcalClusterLocal _ecalLocal;
608 
609  if (iseb) {
610 
611  float dummy;
612  int ieta;
613  int iphi;
614  _ecalLocal.localCoordsEB(*theseed, *iSetup_, dummy, dummy, ieta, iphi, dummy, dummy);
615  eval[26] = ieta;
616  eval[27] = iphi;
617  int signieta = ieta > 0 ? +1 : -1;
618  eval[28] = (ieta-signieta)%5;
619  eval[29] = (iphi-1)%2;
620  eval[30] = (abs(ieta)<=25)*((ieta-signieta)) + (abs(ieta)>25)*((ieta-26*signieta)%20);
621  eval[31] = (iphi-1)%20;
622 
623  } else {
624 
625  float dummy;
626  int ix;
627  int iy;
628  _ecalLocal.localCoordsEE(*theseed, *iSetup_, dummy, dummy, ix, iy, dummy, dummy);
629  eval[26] = ix;
630  eval[27] = iy;
631  eval[28] = raw_es_energy/raw_energy;
632 
633  }
634 
635  //magic numbers for MINUIT-like transformation of BDT output onto limited range
636  //(These should be stored inside the conditions object in the future as well)
637  constexpr double meanlimlow = -1.0;
638  constexpr double meanlimhigh = 3.0;
639  constexpr double meanoffset = meanlimlow + 0.5*(meanlimhigh-meanlimlow);
640  constexpr double meanscale = 0.5*(meanlimhigh-meanlimlow);
641 
642  constexpr double sigmalimlow = 0.0002;
643  constexpr double sigmalimhigh = 0.5;
644  constexpr double sigmaoffset = sigmalimlow + 0.5*(sigmalimhigh-sigmalimlow);
645  constexpr double sigmascale = 0.5*(sigmalimhigh-sigmalimlow);
646 
647  size_t coridx = 0;
648  float raw_pt = raw_energy*the_sc->position().rho()/the_sc->position().r();
649  bool isSaturated = pho.nSaturatedXtals();
650 
651  if(raw_pt >= lowEnergy_ECALonlyThr_ ||
652  (isSaturated && forceHighEnergyEcalTrainingIfSaturated_)){
653  if(iseb) coridx = 1;
654  else coridx = 3;
655  }else{
656  if(iseb) coridx = 0;
657  else coridx = 2;
658  }
659 
660  //these are the actual BDT responses
661  double rawmean = ph_forestH_mean_[coridx]->GetResponse(eval.data());
662  double rawsigma = ph_forestH_sigma_[coridx]->GetResponse(eval.data());
663 
664  //apply transformation to limited output range (matching the training)
665  double mean = meanoffset + meanscale*vdt::fast_sin(rawmean);
666  double sigma = sigmaoffset + sigmascale*vdt::fast_sin(rawsigma);
667 
668  // Correct the energy. A negative energy means that the correction went
669  // outside the boundaries of the training. In this case uses raw.
670  // The resolution estimation, on the other hand should be ok.
671  if (mean < 0.) mean = 1.0;
672 
673  const double ecor = mean*(raw_energy + raw_es_energy);
674  const double sigmacor = sigma*ecor;
675 
676  pho.setCorrectedEnergy(reco::Photon::P4type::regression2, ecor, sigmacor, true);
677 }
678 
680  modifyObject(static_cast<reco::Photon&>(pho));
681 }
constexpr double deltaPhi(double phi1, double phi2)
Definition: deltaPhi.h:22
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
bool isAvailable() const
Definition: Ref.h:577
T getParameter(std::string const &) const
GsfTrackRef gsfTrack() const override
reference to a GsfTrack
Definition: GsfElectron.h:185
Analysis-level Photon class.
Definition: Photon.h:47
std::unordered_map< std::string, ValMapIntTagTokenPair > tag_int_token_map
float nSaturatedXtals() const
Definition: GsfElectron.h:516
std::unordered_map< unsigned, edm::Handle< edm::ValueMap< float > > > ele_vmaps
float trackMomentumError() const
Definition: GsfElectron.h:836
Definition: Photon.py:1
bool existsAs(std::string const &parameterName, bool trackiness=true) const
checks if a parameter exists as a given type
Definition: ParameterSet.h:186
void setEventContent(const edm::EventSetup &) final
const LorentzVector & p4(P4Kind kind) const
Definition: GsfElectron.cc:225
key_type key() const
Definition: Ptr.h:185
EGRegressionModifierV2(const edm::ParameterSet &conf)
edm::EDGetTokenT< edm::View< pat::Electron > > tok_electron_src
void setCorrectedEnergy(P4type type, float E, float dE, bool toCand=true)
const edm::EventSetup * iSetup_
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:579
void correctMomentum(const LorentzVector &p4, float trackMomentumError, float p4Error)
Definition: GsfElectron.h:858
std::vector< std::string > condnames_ecalonly_sigma
bool exists(std::string const &parameterName) const
checks if a parameter exists
std::pair< edm::InputTag, ValMapIntToken > ValMapIntTagTokenPair
std::vector< std::string > condnames_ecalonly_mean
std::vector< std::string > condnames_ecalonly_mean
float fbrem() const
Definition: GsfElectron.h:761
void setEvent(const edm::Event &) final
std::vector< std::string > condnames_ecalonly_sigma
reco::SuperClusterRef superCluster() const override
Ref to SuperCluster.
#define constexpr
bool isEB() const
Definition: GsfElectron.h:352
double eta() const
pseudorapidity of cluster centroid
Definition: CaloCluster.h:168
return((rh^lh)&mask)
Definition: HeavyIon.h:7
std::unordered_map< unsigned, edm::Handle< edm::ValueMap< int > > > ele_int_vmaps
U second(std::pair< T, U > const &p)
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
float full5x5_r9() const
Definition: Photon.h:246
std::unordered_map< std::string, ValMapFloatTagTokenPair > tag_float_token_map
std::unordered_map< unsigned, edm::Ptr< reco::Photon > > phos_by_oop
void setCorrectedEcalEnergyError(float newEnergyError)
Definition: GsfElectron.cc:179
const std::string & name() const
std::pair< edm::InputTag, ValMapFloatToken > ValMapFloatTagTokenPair
std::unordered_map< unsigned, edm::Handle< edm::ValueMap< float > > > pho_vmaps
void modifyObject(reco::GsfElectron &) const final
T sqrt(T t)
Definition: SSEVec.h:18
std::vector< const GBRForestD * > ph_forestH_sigma_
std::unordered_map< unsigned, edm::Ptr< reco::GsfElectron > > eles_by_oop
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
void setConsumes(edm::ConsumesCollector &) final
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
float hcalOverEcalBc() const
Definition: GsfElectron.h:448
edm::EDGetTokenT< edm::ValueMap< int > > ValMapIntToken
std::vector< std::string > condnames_ecaltrk_mean
DetId seed() const
return DetId of seed
Definition: CaloCluster.h:207
std::unordered_map< unsigned, edm::Handle< edm::ValueMap< int > > > pho_int_vmaps
std::vector< std::string > condnames_ecaltrk_sigma
Analysis-level electron class.
Definition: Electron.h:52
void localCoordsEB(const reco::CaloCluster &bclus, const edm::EventSetup &es, float &etacry, float &phicry, int &ieta, int &iphi, float &thetatilt, float &phitilt) const
std::unordered_map< std::string, ValMapFloatTagTokenPair > tag_float_token_map
bool isEB() const
Definition: Photon.h:121
std::unordered_map< std::string, ValMapIntTagTokenPair > tag_int_token_map
void setCorrectedEcalEnergy(float newEnergy)
Definition: GsfElectron.cc:182
edm::EDGetTokenT< double > rhoToken_
bool isSaturated(const Digi &digi, const int &maxADCvalue, int ifirst, int n)
const ShowerShape & full5x5_showerShape() const
Definition: GsfElectron.h:479
fixed size matrix
HLT enums.
const ShowerShape & full5x5_showerShapeVariables() const
Definition: Photon.h:200
edm::EDGetTokenT< edm::View< pat::Photon > > tok_photon_src
std::vector< const GBRForestD * > e_forestH_sigma_
T get() const
Definition: EventSetup.h:63
SuperClusterRef superCluster() const override
reference to a SuperCluster
Definition: GsfElectron.h:184
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
long double T
T const * product() const
Definition: ESHandle.h:86
edm::EDGetTokenT< edm::ValueMap< float > > ValMapFloatToken
std::vector< const GBRForestD * > ph_forestH_mean_
std::vector< const GBRForestD * > e_forestH_mean_
float nSaturatedXtals() const
Definition: Photon.h:260
bool ecalDrivenSeed() const
Definition: GsfElectron.h:188
constexpr Detector det() const
get the detector field from this detid
Definition: DetId.h:39