CMS 3D CMS Logo

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