CMS 3D CMS Logo

EGRegressionModifierV2.cc
Go to the documentation of this file.
13 
14 #include <vdt/vdtMath.h>
15 
17 
18 public:
20 
21  void setEvent(const edm::Event&) final;
22  void setEventContent(const edm::EventSetup&) final;
23 
24  void modifyObject(reco::GsfElectron&) const final;
25  void modifyObject(reco::Photon&) const final;
26 
27  // just calls reco versions
28  void modifyObject(pat::Electron& ele) const final { modifyObject(static_cast<reco::GsfElectron&>(ele)); }
29  void modifyObject(pat::Photon& pho) const final { modifyObject(static_cast<reco::Photon&>(pho)); }
30 
31 private:
32  struct CondNames {
33  std::vector<std::string> mean;
34  std::vector<std::string> sigma;
35  };
36 
39 
40  float rhoValue_;
43 
44  std::vector<const GBRForestD*> phoForestsMean_;
45  std::vector<const GBRForestD*> phoForestsSigma_;
46  std::vector<const GBRForestD*> eleForestsMean_;
47  std::vector<const GBRForestD*> eleForestsSigma_;
48 
49  const double lowEnergyEcalOnlyThr_; // 300
50  const double lowEnergyEcalTrackThr_; // 50
51  const double highEnergyEcalTrackThr_; // 200
52  const double eOverPEcalTrkThr_; // 0.025
53  const double epDiffSigEcalTrackThr_; // 15
54  const double epSigEcalTrackThr_; // 10
56 
57 };
58 
60 
62  : ModifyObjectValueBase(conf)
63  , rhoToken_(cc.consumes<double>(conf.getParameter<edm::InputTag>("rhoCollection")))
64  , lowEnergyEcalOnlyThr_(conf.getParameter<double>("lowEnergy_ECALonlyThr"))
65  , lowEnergyEcalTrackThr_(conf.getParameter<double>("lowEnergy_ECALTRKThr"))
66  , highEnergyEcalTrackThr_(conf.getParameter<double>("highEnergy_ECALTRKThr"))
67  , eOverPEcalTrkThr_(conf.getParameter<double>("eOverP_ECALTRKThr"))
68  , epDiffSigEcalTrackThr_(conf.getParameter<double>("epDiffSig_ECALTRKThr"))
69  , epSigEcalTrackThr_(conf.getParameter<double>("epSig_ECALTRKThr"))
70  , forceHighEnergyEcalTrainingIfSaturated_(conf.getParameter<bool>("forceHighEnergyEcalTrainingIfSaturated"))
71 {
72  const edm::ParameterSet& electrons = conf.getParameter<edm::ParameterSet>("electron_config");
74  .mean = electrons.getParameter<std::vector<std::string> >("regressionKey"),
75  .sigma = electrons.getParameter<std::vector<std::string> >("uncertaintyKey"),
76  };
77 
78  unsigned int encor = eleCondNames_.mean.size();
79  eleForestsMean_.reserve(2*encor);
80  eleForestsSigma_.reserve(2*encor);
81 
82  const edm::ParameterSet& photons = conf.getParameter<edm::ParameterSet>("photon_config");
84  .mean = photons.getParameter<std::vector<std::string> >("regressionKey"),
85  .sigma = photons.getParameter<std::vector<std::string> >("uncertaintyKey"),
86  };
87 
88  unsigned int ncor = phoCondNames_.mean.size();
89  phoForestsMean_.reserve(ncor);
90  phoForestsSigma_.reserve(ncor);
91 }
92 
94 {
96  evt.getByToken(rhoToken_, rhoH);
97  rhoValue_ = *rhoH;
98 }
99 
101 {
104 
107 
109 }
110 
112 
113  // regression calculation needs no additional valuemaps
114 
115  const reco::SuperClusterRef& superClus = ele.superCluster();
116  const edm::Ptr<reco::CaloCluster>& seed = superClus->seed();
117 
118  // skip HGCAL for now
119  if( EcalTools::isHGCalDet(seed->seed().det()) ) return;
120 
121  const int numberOfClusters = superClus->clusters().size();
122  const bool missing_clusters = !superClus->clusters()[numberOfClusters-1].isAvailable();
123  if( missing_clusters ) return ; // do not apply corrections in case of missing info (slimmed MiniAOD electrons)
124 
125  //check if fbrem is filled as its needed for E/p combination so abort if its set to the default value
126  //this will be the case for <5 (or current cuts) for miniAOD electrons
128 
129  const bool isEB = ele.isEB();
130 
131  std::array<float, 32> eval;
132  const double rawEnergy = superClus->rawEnergy();
133  const double raw_es_energy = superClus->preshowerEnergy();
134  const auto& full5x5_ess = ele.full5x5_showerShape();
135 
136  float e5x5Inverse = full5x5_ess.e5x5 != 0. ? vdt::fast_inv(full5x5_ess.e5x5) : 0.;
137 
138  eval[0] = rawEnergy;
139  eval[1] = superClus->etaWidth();
140  eval[2] = superClus->phiWidth();
141  eval[3] = superClus->seed()->energy()/rawEnergy;
142  eval[4] = full5x5_ess.e5x5/rawEnergy;
143  eval[5] = ele.hcalOverEcalBc();
144  eval[6] = rhoValue_;
145  eval[7] = seed->eta() - superClus->position().Eta();
146  eval[8] = reco::deltaPhi( seed->phi(),superClus->position().Phi());
147  eval[9] = full5x5_ess.r9;
148  eval[10] = full5x5_ess.sigmaIetaIeta;
149  eval[11] = full5x5_ess.sigmaIetaIphi;
150  eval[12] = full5x5_ess.sigmaIphiIphi;
151  eval[13] = full5x5_ess.eMax*e5x5Inverse;
152  eval[14] = full5x5_ess.e2nd*e5x5Inverse;
153  eval[15] = full5x5_ess.eTop*e5x5Inverse;
154  eval[16] = full5x5_ess.eBottom*e5x5Inverse;
155  eval[17] = full5x5_ess.eLeft*e5x5Inverse;
156  eval[18] = full5x5_ess.eRight*e5x5Inverse;
157  eval[19] = full5x5_ess.e2x5Max*e5x5Inverse;
158  eval[20] = full5x5_ess.e2x5Left*e5x5Inverse;
159  eval[21] = full5x5_ess.e2x5Right*e5x5Inverse;
160  eval[22] = full5x5_ess.e2x5Top*e5x5Inverse;
161  eval[23] = full5x5_ess.e2x5Bottom*e5x5Inverse;
162  eval[24] = ele.nSaturatedXtals();
163  eval[25] = std::max(0,numberOfClusters);
164 
165  // calculate coordinate variables
166  if (isEB) {
167 
168  float dummy;
169  int ieta;
170  int iphi;
171  egammaTools::localEcalClusterCoordsEB(*seed, *caloGeometry_, dummy, dummy, ieta, iphi, dummy, dummy);
172  eval[26] = ieta;
173  eval[27] = iphi;
174  int signieta = ieta > 0 ? +1 : -1;
175  eval[28] = (ieta-signieta)%5;
176  eval[29] = (iphi-1)%2;
177  eval[30] = (abs(ieta)<=25)*((ieta-signieta)) + (abs(ieta)>25)*((ieta-26*signieta)%20);
178  eval[31] = (iphi-1)%20;
179 
180  } else {
181 
182  float dummy;
183  int ix;
184  int iy;
185  egammaTools::localEcalClusterCoordsEE(*seed, *caloGeometry_, dummy, dummy, ix, iy, dummy, dummy);
186  eval[26] = ix;
187  eval[27] = iy;
188  eval[28] = raw_es_energy/rawEnergy;
189 
190  }
191 
192  //magic numbers for MINUIT-like transformation of BDT output onto limited range
193  //(These should be stored inside the conditions object in the future as well)
194  constexpr double meanlimlow = -1.0;
195  constexpr double meanlimhigh = 3.0;
196  constexpr double meanoffset = meanlimlow + 0.5*(meanlimhigh-meanlimlow);
197  constexpr double meanscale = 0.5*(meanlimhigh-meanlimlow);
198 
199  constexpr double sigmalimlow = 0.0002;
200  constexpr double sigmalimhigh = 0.5;
201  constexpr double sigmaoffset = sigmalimlow + 0.5*(sigmalimhigh-sigmalimlow);
202  constexpr double sigmascale = 0.5*(sigmalimhigh-sigmalimlow);
203 
204 
205  size_t coridx = 0;
206  float rawPt = rawEnergy*superClus->position().rho()/superClus->position().r();
207  bool isSaturated = ele.nSaturatedXtals()!=0;
208 
209  if(rawPt >= lowEnergyEcalOnlyThr_ ||
210  (isSaturated && forceHighEnergyEcalTrainingIfSaturated_)){
211  if(isEB) coridx = 1;
212  else coridx = 3;
213  }else{
214  if(isEB) coridx = 0;
215  else coridx = 2;
216  }
217 
218 
219  //these are the actual BDT responses
220  double rawmean = eleForestsMean_[coridx]->GetResponse(eval.data());
221  double rawsigma = eleForestsSigma_[coridx]->GetResponse(eval.data());
222 
223  //apply transformation to limited output range (matching the training)
224  double mean = meanoffset + meanscale*vdt::fast_sin(rawmean);
225  double sigma = sigmaoffset + sigmascale*vdt::fast_sin(rawsigma);
226 
227  // Correct the energy. A negative energy means that the correction went
228  // outside the boundaries of the training. In this case uses raw.
229  // The resolution estimation, on the other hand should be ok.
230  if (mean < 0.) mean = 1.0;
231 
232  const double ecor = mean*(rawEnergy + raw_es_energy);
233  const double sigmacor = sigma*ecor;
234 
235  ele.setCorrectedEcalEnergy(ecor);
236  ele.setCorrectedEcalEnergyError(sigmacor);
237 
238  double combinedEnergy = ecor;
239  double combinedEnergyError = sigmacor;
240 
241  auto el_track = ele.gsfTrack();
242  const float trkMomentum = el_track->pMode();
243  const float trkEta = el_track->etaMode();
244  const float trkPhi = el_track->phiMode();
245  const float trkMomentumError = std::abs(el_track->qoverpModeError())*trkMomentum*trkMomentum;
246 
247  const float eOverP = (rawEnergy+raw_es_energy)*mean/trkMomentum;
248  const float fbrem = ele.fbrem();
249 
250  // E-p combination
251  if (ecor < highEnergyEcalTrackThr_ &&
252  eOverP > eOverPEcalTrkThr_ &&
253  std::abs(ecor - trkMomentum) < epDiffSigEcalTrackThr_*std::sqrt(trkMomentumError*trkMomentumError+sigmacor*sigmacor) &&
254  trkMomentumError < epSigEcalTrackThr_*trkMomentum) {
255 
256  rawPt = ecor/cosh(trkEta);
257  if (isEB && rawPt < lowEnergyEcalTrackThr_)
258  coridx = 4;
259  else if (isEB && rawPt >= lowEnergyEcalTrackThr_)
260  coridx = 5;
261  else if (!isEB && rawPt < lowEnergyEcalTrackThr_)
262  coridx = 6;
263  else if (!isEB && rawPt >= lowEnergyEcalTrackThr_)
264  coridx = 7;
265 
266  eval[0] = ecor;
267  eval[1] = sigma/mean;
268  eval[2] = trkMomentumError/trkMomentum;
269  eval[3] = eOverP;
270  eval[4] = ele.ecalDrivenSeed();
271  eval[5] = full5x5_ess.r9;
272  eval[6] = fbrem;
273  eval[7] = trkEta;
274  eval[8] = trkPhi;
275 
276  float ecalEnergyVar = (rawEnergy + raw_es_energy)*sigma;
277  float rawcombNormalization = (trkMomentumError*trkMomentumError + ecalEnergyVar*ecalEnergyVar);
278  float rawcomb = ( ecor*trkMomentumError*trkMomentumError + trkMomentum*ecalEnergyVar*ecalEnergyVar ) / rawcombNormalization;
279 
280  //these are the actual BDT responses
281  double rawmean_trk = eleForestsMean_[coridx]->GetResponse(eval.data());
282  double rawsigma_trk = eleForestsSigma_[coridx]->GetResponse(eval.data());
283 
284  //apply transformation to limited output range (matching the training)
285  double mean_trk = meanoffset + meanscale*vdt::fast_sin(rawmean_trk);
286  double sigma_trk = sigmaoffset + sigmascale*vdt::fast_sin(rawsigma_trk);
287 
288  // Final correction
289  // A negative energy means that the correction went
290  // outside the boundaries of the training. In this case uses raw.
291  // The resolution estimation, on the other hand should be ok.
292  if (mean_trk < 0.) mean_trk = 1.0;
293 
294  combinedEnergy = mean_trk*rawcomb;
295  combinedEnergyError = sigma_trk*rawcomb;
296  }
297 
298  math::XYZTLorentzVector oldFourMomentum = ele.p4();
299  math::XYZTLorentzVector newFourMomentum( oldFourMomentum.x()*combinedEnergy/oldFourMomentum.t(),
300  oldFourMomentum.y()*combinedEnergy/oldFourMomentum.t(),
301  oldFourMomentum.z()*combinedEnergy/oldFourMomentum.t(),
302  combinedEnergy );
303 
304  ele.correctMomentum(newFourMomentum, ele.trackMomentumError(), combinedEnergyError);
305 }
306 
308  // regression calculation needs no additional valuemaps
309 
310  const reco::SuperClusterRef& superClus = pho.superCluster();
311  const edm::Ptr<reco::CaloCluster>& seed = superClus->seed();
312 
313  // skip HGCAL for now
314  if( EcalTools::isHGCalDet(seed->seed().det()) ) return;
315 
316  const int numberOfClusters = superClus->clusters().size();
317  const bool missing_clusters = !superClus->clusters()[numberOfClusters-1].isAvailable();
318  if( missing_clusters ) return ; // do not apply corrections in case of missing info (slimmed MiniAOD electrons)
319 
320  const bool isEB = pho.isEB();
321 
322  std::array<float, 32> eval;
323  const double rawEnergy = superClus->rawEnergy();
324  const double raw_es_energy = superClus->preshowerEnergy();
325  const auto& full5x5_pss = pho.full5x5_showerShapeVariables();
326 
327  float e5x5Inverse = full5x5_pss.e5x5 != 0. ? vdt::fast_inv(full5x5_pss.e5x5) : 0.;
328 
329  eval[0] = rawEnergy;
330  eval[1] = superClus->etaWidth();
331  eval[2] = superClus->phiWidth();
332  eval[3] = superClus->seed()->energy()/rawEnergy;
333  eval[4] = full5x5_pss.e5x5/rawEnergy;
334  eval[5] = pho.hadronicOverEm();
335  eval[6] = rhoValue_;
336  eval[7] = seed->eta() - superClus->position().Eta();
337  eval[8] = reco::deltaPhi( seed->phi(),superClus->position().Phi());
338  eval[9] = pho.full5x5_r9();
339  eval[10] = full5x5_pss.sigmaIetaIeta;
340  eval[11] = full5x5_pss.sigmaIetaIphi;
341  eval[12] = full5x5_pss.sigmaIphiIphi;
342  eval[13] = full5x5_pss.maxEnergyXtal*e5x5Inverse;
343  eval[14] = full5x5_pss.e2nd*e5x5Inverse;
344  eval[15] = full5x5_pss.eTop*e5x5Inverse;
345  eval[16] = full5x5_pss.eBottom*e5x5Inverse;
346  eval[17] = full5x5_pss.eLeft*e5x5Inverse;
347  eval[18] = full5x5_pss.eRight*e5x5Inverse;
348  eval[19] = full5x5_pss.e2x5Max*e5x5Inverse;
349  eval[20] = full5x5_pss.e2x5Left*e5x5Inverse;
350  eval[21] = full5x5_pss.e2x5Right*e5x5Inverse;
351  eval[22] = full5x5_pss.e2x5Top*e5x5Inverse;
352  eval[23] = full5x5_pss.e2x5Bottom*e5x5Inverse;
353  eval[24] = pho.nSaturatedXtals();
354  eval[25] = std::max(0,numberOfClusters);
355 
356  // calculate coordinate variables
357 
358  if (isEB) {
359 
360  float dummy;
361  int ieta;
362  int iphi;
363  egammaTools::localEcalClusterCoordsEB(*seed, *caloGeometry_, dummy, dummy, ieta, iphi, dummy, dummy);
364  eval[26] = ieta;
365  eval[27] = iphi;
366  int signieta = ieta > 0 ? +1 : -1;
367  eval[28] = (ieta-signieta)%5;
368  eval[29] = (iphi-1)%2;
369  eval[30] = (abs(ieta)<=25)*((ieta-signieta)) + (abs(ieta)>25)*((ieta-26*signieta)%20);
370  eval[31] = (iphi-1)%20;
371 
372  } else {
373 
374  float dummy;
375  int ix;
376  int iy;
377  egammaTools::localEcalClusterCoordsEE(*seed, *caloGeometry_, dummy, dummy, ix, iy, dummy, dummy);
378  eval[26] = ix;
379  eval[27] = iy;
380  eval[28] = raw_es_energy/rawEnergy;
381 
382  }
383 
384  //magic numbers for MINUIT-like transformation of BDT output onto limited range
385  //(These should be stored inside the conditions object in the future as well)
386  constexpr double meanlimlow = -1.0;
387  constexpr double meanlimhigh = 3.0;
388  constexpr double meanoffset = meanlimlow + 0.5*(meanlimhigh-meanlimlow);
389  constexpr double meanscale = 0.5*(meanlimhigh-meanlimlow);
390 
391  constexpr double sigmalimlow = 0.0002;
392  constexpr double sigmalimhigh = 0.5;
393  constexpr double sigmaoffset = sigmalimlow + 0.5*(sigmalimhigh-sigmalimlow);
394  constexpr double sigmascale = 0.5*(sigmalimhigh-sigmalimlow);
395 
396  size_t coridx = 0;
397  float rawPt = rawEnergy*superClus->position().rho()/superClus->position().r();
398  bool isSaturated = pho.nSaturatedXtals();
399 
400  if(rawPt >= lowEnergyEcalOnlyThr_ ||
401  (isSaturated && forceHighEnergyEcalTrainingIfSaturated_)){
402  if(isEB) coridx = 1;
403  else coridx = 3;
404  }else{
405  if(isEB) coridx = 0;
406  else coridx = 2;
407  }
408 
409  //these are the actual BDT responses
410  double rawmean = phoForestsMean_[coridx]->GetResponse(eval.data());
411  double rawsigma = phoForestsSigma_[coridx]->GetResponse(eval.data());
412 
413  //apply transformation to limited output range (matching the training)
414  double mean = meanoffset + meanscale*vdt::fast_sin(rawmean);
415  double sigma = sigmaoffset + sigmascale*vdt::fast_sin(rawsigma);
416 
417  // Correct the energy. A negative energy means that the correction went
418  // outside the boundaries of the training. In this case uses raw.
419  // The resolution estimation, on the other hand should be ok.
420  if (mean < 0.) mean = 1.0;
421 
422  const double ecor = mean*(rawEnergy + raw_es_energy);
423  const double sigmacor = sigma*ecor;
424 
425  pho.setCorrectedEnergy(reco::Photon::P4type::regression2, ecor, sigmacor, true);
426 }
constexpr double deltaPhi(double phi1, double phi2)
Definition: deltaPhi.h:22
bool isAvailable() const
Definition: Ref.h:575
T getParameter(std::string const &) const
GsfTrackRef gsfTrack() const override
reference to a GsfTrack
Definition: GsfElectron.h:186
static bool isHGCalDet(DetId::Detector thedet)
identify HGCal cells
Definition: EcalTools.h:54
Analysis-level Photon class.
Definition: Photon.h:47
void localEcalClusterCoordsEB(const reco::CaloCluster &bclus, const CaloGeometry &geom, float &etacry, float &phicry, int &ieta, int &iphi, float &thetatilt, float &phitilt)
float nSaturatedXtals() const
Definition: GsfElectron.h:520
float trackMomentumError() const
Definition: GsfElectron.h:847
void setEventContent(const edm::EventSetup &) final
const LorentzVector & p4(P4Kind kind) const
Definition: GsfElectron.cc:225
void setCorrectedEnergy(P4type type, float E, float dE, bool toCand=true)
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:517
void correctMomentum(const LorentzVector &p4, float trackMomentumError, float p4Error)
Definition: GsfElectron.h:869
float fbrem() const
Definition: GsfElectron.h:772
void setEvent(const edm::Event &) final
void modifyObject(pat::Photon &pho) const final
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
return((rh^lh)&mask)
std::vector< const GBRForestD * > phoForestsSigma_
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
float full5x5_r9() const
Definition: Photon.h:252
void setCorrectedEcalEnergyError(float newEnergyError)
Definition: GsfElectron.cc:179
std::vector< const GBRForestD * > retrieveGBRForests(edm::EventSetup const &evs, std::vector< std::string > const &names)
void modifyObject(reco::GsfElectron &) const final
void modifyObject(pat::Electron &ele) const final
T sqrt(T t)
Definition: SSEVec.h:18
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::vector< const GBRForestD * > phoForestsMean_
void localEcalClusterCoordsEE(const reco::CaloCluster &bclus, const CaloGeometry &geom, float &xcry, float &ycry, int &ix, int &iy, float &thetatilt, float &phitilt)
float hadronicOverEm() const
the total hadronic over electromagnetic fraction
Definition: Photon.h:212
float hcalOverEcalBc() const
Definition: GsfElectron.h:452
DetId seed() const
return DetId of seed
Definition: CaloCluster.h:207
EGRegressionModifierV2(const edm::ParameterSet &conf, edm::ConsumesCollector &cc)
const bool forceHighEnergyEcalTrainingIfSaturated_
Analysis-level electron class.
Definition: Electron.h:52
bool isEB() const
Definition: Photon.h:121
void setCorrectedEcalEnergy(float newEnergy)
Definition: GsfElectron.cc:182
edm::ESHandle< CaloGeometry > caloGeometry_
edm::EDGetTokenT< double > rhoToken_
bool isSaturated(const Digi &digi, const int &maxADCvalue, int ifirst, int n)
const ShowerShape & full5x5_showerShape() const
Definition: GsfElectron.h:483
HLT enums.
const ShowerShape & full5x5_showerShapeVariables() const
Definition: Photon.h:206
T get() const
Definition: EventSetup.h:71
SuperClusterRef superCluster() const override
reference to a SuperCluster
Definition: GsfElectron.h:185
#define DEFINE_EDM_PLUGIN(factory, type, name)
double phi() const
azimuthal angle of cluster centroid
Definition: CaloCluster.h:171
std::vector< const GBRForestD * > eleForestsMean_
std::vector< const GBRForestD * > eleForestsSigma_
float nSaturatedXtals() const
Definition: Photon.h:266
#define constexpr
bool ecalDrivenSeed() const
Definition: GsfElectron.h:188
constexpr Detector det() const
get the detector field from this detid
Definition: DetId.h:39