CMS 3D CMS Logo

ElectronMVAEstimatorRun2Spring16GeneralPurpose.cc
Go to the documentation of this file.
2 
5 
7 
9 
10 #include "TMath.h"
11 #include "TMVA/MethodBDT.h"
12 
15  tag_(conf.getParameter<std::string>("mvaTag")),
16  MethodName_("BDTG method"),
17  beamSpotLabel_(conf.getParameter<edm::InputTag>("beamSpot")),
18  conversionsLabelAOD_(conf.getParameter<edm::InputTag>("conversionsAOD")),
19  conversionsLabelMiniAOD_(conf.getParameter<edm::InputTag>("conversionsMiniAOD")) {
20 
21  const std::vector <std::string> weightFileNames
22  = conf.getParameter<std::vector<std::string> >("weightFileNames");
23  init(weightFileNames);
24 }
25 
27  if( (int)(weightFileNames.size()) != nCategories )
28  throw cms::Exception("MVA config failure: ")
29  << "wrong number of weightfiles" << std::endl;
30 
31  gbrForest_s.clear();
32  // Create a TMVA reader object for each category
33  for(int i=0; i<nCategories; i++){
34 
35  // Use unique_ptr so that all readers are properly cleaned up
36  // when the vector clear() is called in the destructor
37 
38  edm::FileInPath weightFile( weightFileNames[i] );
39  gbrForest_s.push_back( createSingleReader(i, weightFile ) );
40 
41  }
42 
43 }
44 
47 
50  tag_(mvaTag),
51  MethodName_("BDTG method"),
52  beamSpotLabel_(edm::InputTag(beamspotTag)),
53  conversionsLabelAOD_(edm::InputTag(conversionsTag)),
55  }
56 
57 
58 
61 }
62 
63 
65 
66  // All tokens for event content needed by this MVA
67 
68  // Beam spot (same for AOD and miniAOD)
69  cc.consumes<reco::BeamSpot>(beamSpotLabel_);
70 
71  // Conversions collection (different names in AOD and miniAOD)
74 
75 
76 }
77 
79 mvaValue( const edm::Ptr<reco::Candidate>& particle, const edm::Event& iEvent) const {
80 
81  const int iCategory = findCategory( particle );
82  const std::vector<float> vars = std::move( fillMVAVariables( particle, iEvent ) );
83  return mvaValue(iCategory, vars);
84 }
85 
87 mvaValue( const reco::GsfElectron * particle, const edm::EventBase & iEvent) const {
90  iEvent.getByLabel(conversionsLabelAOD_, conversions);
91  iEvent.getByLabel(beamSpotLabel_, beamSpot);
92  const int iCategory = findCategory( particle );
93  const std::vector<float> vars = std::move( fillMVAVariables( particle, conversions, beamSpot.product() ) );
94  return mvaValue(iCategory, vars);
95 }
96 
98 mvaValue( const int iCategory, const std::vector<float> & vars) const {
99  const float result = gbrForest_s.at(iCategory)->GetClassifier(vars.data());
100 
101  const bool debug = false;
102  if(debug) {
103  std::cout << " *** Inside the class MethodName_ " << MethodName_ << std::endl;
104  std::cout << " bin " << iCategory
105  << " fbrem " << vars[11]
106  << " kfchi2 " << vars[9]
107  << " mykfhits " << vars[8]
108  << " gsfchi2 " << vars[10]
109  << " deta " << vars[18]
110  << " dphi " << vars[19]
111  << " detacalo " << vars[20]
112  << " see " << vars[0]
113  << " spp " << vars[1]
114  << " etawidth " << vars[4]
115  << " phiwidth " << vars[5]
116  << " OneMinusE1x5E5x5 " << vars[2]
117  << " R9 " << vars[3]
118  << " HoE " << vars[6]
119  << " EoP " << vars[15]
120  << " IoEmIoP " << vars[17]
121  << " eleEoPout " << vars[16]
122  << " eta " << vars[24]
123  << " pt " << vars[21] << std::endl;
124  std::cout << " ### MVA " << result << std::endl;
125  }
126 
127  return result;
128 }
129 
131 
132  // Try to cast the particle into a reco particle.
133  // This should work for both reco and pat.
134  const edm::Ptr<reco::GsfElectron> eleRecoPtr = ( edm::Ptr<reco::GsfElectron> )particle;
135  if( eleRecoPtr.get() == NULL )
136  throw cms::Exception("MVA failure: ")
137  << " given particle is expected to be reco::GsfElectron or pat::Electron," << std::endl
138  << " but appears to be neither" << std::endl;
139  return findCategory(eleRecoPtr.get());
140 }
141 
143  float eta = eleRecoPtr->superCluster()->eta();
144 
145  //
146  // Determine the category
147  //
148  int iCategory = UNDEFINED;
149  const float ebSplit = 0.800;// barrel is split into two regions
150  const float ebeeSplit = 1.479; // division between barrel and endcap
151 
152 
153  if (std::abs(eta) < ebSplit)
154  iCategory = CAT_EB1_PT10plus;
155 
156  if (std::abs(eta) >= ebSplit && std::abs(eta) < ebeeSplit)
157  iCategory = CAT_EB2_PT10plus;
158 
159  if (std::abs(eta) >= ebeeSplit)
160  iCategory = CAT_EE_PT10plus;
161 
162  return iCategory;
163 }
164 
167 
168  bool isEndcap = false;
169  if( category == CAT_EE_PT10plus )
170  isEndcap = true;
171 
172  return isEndcap;
173 }
174 
175 
176 std::unique_ptr<const GBRForest> ElectronMVAEstimatorRun2Spring16GeneralPurpose::
177 createSingleReader(const int iCategory, const edm::FileInPath &weightFile){
178 
179  //
180  // Create the reader
181  //
182  TMVA::Reader tmpTMVAReader( "!Color:Silent:!Error" );
183 
184  //
185  // Configure all variables and spectators. Note: the order and names
186  // must match what is found in the xml weights file!
187  //
188 
189  // Pure ECAL -> shower shapes
190  tmpTMVAReader.AddVariable("ele_oldsigmaietaieta", &allMVAVars_.see);
191  tmpTMVAReader.AddVariable("ele_oldsigmaiphiiphi", &allMVAVars_.spp);
192  tmpTMVAReader.AddVariable("ele_oldcircularity", &allMVAVars_.OneMinusE1x5E5x5);
193  tmpTMVAReader.AddVariable("ele_oldr9", &allMVAVars_.R9);
194  tmpTMVAReader.AddVariable("ele_scletawidth", &allMVAVars_.etawidth);
195  tmpTMVAReader.AddVariable("ele_sclphiwidth", &allMVAVars_.phiwidth);
196  tmpTMVAReader.AddVariable("ele_oldhe", &allMVAVars_.HoE);
197 
198  //Pure tracking variables
199  tmpTMVAReader.AddVariable("ele_kfhits", &allMVAVars_.kfhits);
200  tmpTMVAReader.AddVariable("ele_kfchi2", &allMVAVars_.kfchi2);
201  tmpTMVAReader.AddVariable("ele_gsfchi2", &allMVAVars_.gsfchi2);
202 
203  // Energy matching
204  tmpTMVAReader.AddVariable("ele_fbrem", &allMVAVars_.fbrem);
205 
206  tmpTMVAReader.AddVariable("ele_gsfhits", &allMVAVars_.gsfhits);
207  tmpTMVAReader.AddVariable("ele_expected_inner_hits", &allMVAVars_.expectedMissingInnerHits);
208  tmpTMVAReader.AddVariable("ele_conversionVertexFitProbability", &allMVAVars_.convVtxFitProbability);
209 
210  tmpTMVAReader.AddVariable("ele_ep", &allMVAVars_.EoP);
211  tmpTMVAReader.AddVariable("ele_eelepout", &allMVAVars_.eleEoPout);
212  tmpTMVAReader.AddVariable("ele_IoEmIop", &allMVAVars_.IoEmIoP);
213 
214  // Geometrical matchings
215  tmpTMVAReader.AddVariable("ele_deltaetain", &allMVAVars_.deta);
216  tmpTMVAReader.AddVariable("ele_deltaphiin", &allMVAVars_.dphi);
217  tmpTMVAReader.AddVariable("ele_deltaetaseed", &allMVAVars_.detacalo);
218 
219  tmpTMVAReader.AddVariable("ele_pt", &allMVAVars_.pt);
220  tmpTMVAReader.AddVariable("scl_eta", &allMVAVars_.SCeta);
221 
222  // Endcap only variables
223  if( isEndcapCategory(iCategory) )
224  tmpTMVAReader.AddVariable("ele_psEoverEraw", &allMVAVars_.PreShowerOverRaw);
225 
226  //
227  // Book the method and set up the weights file
228  //
229  tmpTMVAReader.BookMVA(MethodName_ , weightFile.fullPath());
230 
231  return std::unique_ptr<const GBRForest> ( new GBRForest( dynamic_cast<TMVA::MethodBDT*>( tmpTMVAReader.FindMVA(MethodName_) ) ) );
232 }
233 
234 // A function that should work on both pat and reco objects
237  const edm::Event& iEvent ) const {
238 
239  //
240  // Declare all value maps corresponding to the products we defined earlier
241  //
242  edm::Handle<reco::BeamSpot> theBeamSpot;
244 
245  // Get data needed for conversion rejection
246  iEvent.getByLabel(beamSpotLabel_, theBeamSpot);
247 
248  // Conversions in miniAOD and AOD have different names,
249  // but the same type, so we use the same handle with different tokens.
250  iEvent.getByLabel(conversionsLabelAOD_, conversions);
251  if( !conversions.isValid() )
252  iEvent.getByLabel(conversionsLabelMiniAOD_, conversions);
253 
254  // Make sure everything is retrieved successfully
255  if(! (theBeamSpot.isValid()
256  && conversions.isValid() )
257  )
258  throw cms::Exception("MVA failure: ")
259  << "Failed to retrieve event content needed for this MVA"
260  << std::endl
261  << "Check python MVA configuration file."
262  << std::endl;
263 
264  // Try to cast the particle into a reco particle.
265  // This should work for both reco and pat.
266  const edm::Ptr<reco::GsfElectron> eleRecoPtr = ( edm::Ptr<reco::GsfElectron> )particle;
267  if( eleRecoPtr.get() == NULL )
268  throw cms::Exception("MVA failure: ")
269  << " given particle is expected to be reco::GsfElectron or pat::Electron," << std::endl
270  << " but appears to be neither" << std::endl;
271  return fillMVAVariables(eleRecoPtr.get(), conversions, theBeamSpot.product());
272 }
273 
274 // A function that should work on both pat and reco objects
277  const edm::Handle<reco::ConversionCollection> conversions, const reco::BeamSpot *theBeamSpot ) const {
278 
279 
280  // Both pat and reco particles have exactly the same accessors, so we use a reco ptr
281  // throughout the code, with a single exception as of this writing, handled separately below.
282  auto superCluster = eleRecoPtr->superCluster();
283 
284  AllVariables allMVAVars;
285 
286  // Pure ECAL -> shower shapes
287  allMVAVars.see = eleRecoPtr->full5x5_sigmaIetaIeta();
288  allMVAVars.spp = eleRecoPtr->full5x5_sigmaIphiIphi();
289  allMVAVars.OneMinusE1x5E5x5 = 1. - eleRecoPtr->full5x5_e1x5() / eleRecoPtr->full5x5_e5x5();
290  allMVAVars.R9 = eleRecoPtr->full5x5_r9();
291  allMVAVars.etawidth = superCluster->etaWidth();
292  allMVAVars.phiwidth = superCluster->phiWidth();
293  allMVAVars.HoE = eleRecoPtr->full5x5_hcalOverEcal(); //hadronicOverEm();
294  // Endcap only variables
295  allMVAVars.PreShowerOverRaw = superCluster->preshowerEnergy() / superCluster->rawEnergy();
296 
297  // To get to CTF track information in pat::Electron, we have to have the pointer
298  // to pat::Electron, it is not accessible from the pointer to reco::GsfElectron.
299  // This behavior is reported and is expected to change in the future (post-7.4.5 some time).
300  bool validKF= false;
301  reco::TrackRef myTrackRef = eleRecoPtr->closestCtfTrackRef();
302  const pat::Electron * elePatPtr = dynamic_cast<const pat::Electron *>(eleRecoPtr);
303  // Check if this is really a pat::Electron, and if yes, get the track ref from this new
304  // pointer instead
305  if( elePatPtr != NULL )
306  myTrackRef = elePatPtr->closestCtfTrackRef();
307  validKF = (myTrackRef.isAvailable() && (myTrackRef.isNonnull()) );
308 
309  //Pure tracking variables
310  allMVAVars.kfhits = (validKF) ? myTrackRef->hitPattern().trackerLayersWithMeasurement() : -1. ;
311  allMVAVars.kfchi2 = (validKF) ? myTrackRef->normalizedChi2() : 0;
312  allMVAVars.gsfchi2 = eleRecoPtr->gsfTrack()->normalizedChi2();
313 
314  // Energy matching
315  allMVAVars.fbrem = eleRecoPtr->fbrem();
316 
317  allMVAVars.gsfhits = eleRecoPtr->gsfTrack()->hitPattern().trackerLayersWithMeasurement();
318  allMVAVars.expectedMissingInnerHits = eleRecoPtr->gsfTrack()
319  ->hitPattern().numberOfHits(reco::HitPattern::MISSING_INNER_HITS);
320 
322  conversions,
323  theBeamSpot->position());
324  double vertexFitProbability = -1.;
325  if(!conv_ref.isNull()) {
326  const reco::Vertex &vtx = conv_ref.get()->conversionVertex(); if (vtx.isValid()) {
327  vertexFitProbability = TMath::Prob( vtx.chi2(), vtx.ndof());
328  }
329  }
330  allMVAVars.convVtxFitProbability = vertexFitProbability;
331 
332  allMVAVars.EoP = eleRecoPtr->eSuperClusterOverP();
333  allMVAVars.eleEoPout = eleRecoPtr->eEleClusterOverPout();
334  float pAtVertex = eleRecoPtr->trackMomentumAtVtx().R();
335  allMVAVars.IoEmIoP = (1.0/eleRecoPtr->ecalEnergy()) - (1.0 / pAtVertex );
336 
337  // Geometrical matchings
338  allMVAVars.deta = eleRecoPtr->deltaEtaSuperClusterTrackAtVtx();
339  allMVAVars.dphi = eleRecoPtr->deltaPhiSuperClusterTrackAtVtx();
340  allMVAVars.detacalo = eleRecoPtr->deltaEtaSeedClusterTrackAtCalo();
341 
342  // Spectator variables
343  allMVAVars.pt = eleRecoPtr->pt();
344  float scEta = superCluster->eta();
345  constexpr float ebeeSplit = 1.479;
346  allMVAVars.isBarrel = ( std::abs(scEta) < ebeeSplit );
347  allMVAVars.isEndcap = ( std::abs(scEta) >= ebeeSplit );
348  allMVAVars.SCeta = scEta;
349  allMVAVars.pt = eleRecoPtr->pt();
350 
351  constrainMVAVariables(allMVAVars);
352 
353  std::vector<float> vars;
354 
355  if( isEndcapCategory( findCategory( eleRecoPtr ) ) ) {
356  vars = std::move( packMVAVariables(allMVAVars.see,
357  allMVAVars.spp,
358  allMVAVars.OneMinusE1x5E5x5,
359  allMVAVars.R9,
360  allMVAVars.etawidth,
361  allMVAVars.phiwidth,
362  allMVAVars.HoE,
363  //Pure tracking variables
364  allMVAVars.kfhits,
365  allMVAVars.kfchi2,
366  allMVAVars.gsfchi2,
367  // Energy matching
368  allMVAVars.fbrem,
369  allMVAVars.gsfhits,
370  allMVAVars.expectedMissingInnerHits,
371  allMVAVars.convVtxFitProbability,
372  allMVAVars.EoP,
373  allMVAVars.eleEoPout,
374  allMVAVars.IoEmIoP,
375  // Geometrical matchings
376  allMVAVars.deta,
377  allMVAVars.dphi,
378  allMVAVars.detacalo,
379 
380  allMVAVars.pt,
381  allMVAVars.SCeta,
382  // Endcap only variables
383  allMVAVars.PreShowerOverRaw)
384  );
385  } else {
386  vars = std::move( packMVAVariables(allMVAVars.see,
387  allMVAVars.spp,
388  allMVAVars.OneMinusE1x5E5x5,
389  allMVAVars.R9,
390  allMVAVars.etawidth,
391  allMVAVars.phiwidth,
392  allMVAVars.HoE,
393  //Pure tracking variables
394  allMVAVars.kfhits,
395  allMVAVars.kfchi2,
396  allMVAVars.gsfchi2,
397  // Energy matching
398  allMVAVars.fbrem,
399  allMVAVars.gsfhits,
400  allMVAVars.expectedMissingInnerHits,
401  allMVAVars.convVtxFitProbability,
402  allMVAVars.EoP,
403  allMVAVars.eleEoPout,
404  allMVAVars.IoEmIoP,
405  // Geometrical matchings
406  allMVAVars.deta,
407  allMVAVars.dphi,
408  allMVAVars.detacalo,
409  allMVAVars.pt,
410  allMVAVars.SCeta)
411  );
412  }
413  return vars;
414 }
415 
417 
418  // Check that variables do not have crazy values
419 
420  if(allMVAVars.fbrem < -1.)
421  allMVAVars.fbrem = -1.;
422 
423  allMVAVars.deta = fabs(allMVAVars.deta);
424  if(allMVAVars.deta > 0.06)
425  allMVAVars.deta = 0.06;
426 
427 
428  allMVAVars.dphi = fabs(allMVAVars.dphi);
429  if(allMVAVars.dphi > 0.6)
430  allMVAVars.dphi = 0.6;
431 
432 
433  if(allMVAVars.EoP > 20.)
434  allMVAVars.EoP = 20.;
435 
436  if(allMVAVars.eleEoPout > 20.)
437  allMVAVars.eleEoPout = 20.;
438 
439 
440  allMVAVars.detacalo = fabs(allMVAVars.detacalo);
441  if(allMVAVars.detacalo > 0.2)
442  allMVAVars.detacalo = 0.2;
443 
444  if(allMVAVars.OneMinusE1x5E5x5 < -1.)
445  allMVAVars.OneMinusE1x5E5x5 = -1;
446 
447  if(allMVAVars.OneMinusE1x5E5x5 > 2.)
448  allMVAVars.OneMinusE1x5E5x5 = 2.;
449 
450 
451  if(allMVAVars.R9 > 5)
452  allMVAVars.R9 = 5;
453 
454  if(allMVAVars.gsfchi2 > 200.)
455  allMVAVars.gsfchi2 = 200;
456 
457 
458  if(allMVAVars.kfchi2 > 10.)
459  allMVAVars.kfchi2 = 10.;
460 }
bool isAvailable() const
Definition: Ref.h:576
T getParameter(std::string const &) const
virtual double pt() const final
transverse momentum
void init(const std::vector< std::string > weightFileNames)
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:252
float eSuperClusterOverP() const
Definition: GsfElectron.h:245
float full5x5_e5x5() const
Definition: GsfElectron.h:459
float full5x5_e1x5() const
Definition: GsfElectron.h:457
T const * get() const
Returns C++ pointer to the item.
Definition: Ptr.h:160
bool isValid() const
Tells whether the vertex is valid.
Definition: Vertex.h:68
math::XYZVectorF trackMomentumAtVtx() const
Definition: GsfElectron.h:291
float full5x5_sigmaIphiIphi() const
Definition: GsfElectron.h:456
#define NULL
Definition: scimark2.h:8
float fbrem() const
Definition: GsfElectron.h:750
#define constexpr
std::vector< Conversion > ConversionCollection
collectin of Conversion objects
Definition: ConversionFwd.h:9
TrackRef closestCtfTrackRef() const
Definition: GsfElectron.h:201
float full5x5_sigmaIetaIeta() const
Definition: GsfElectron.h:455
std::vector< float > packMVAVariables(const Args...args) const
float deltaEtaSuperClusterTrackAtVtx() const
Definition: GsfElectron.h:249
int iEvent
Definition: GenABIO.cc:230
reco::TrackRef closestCtfTrackRef() const
override the reco::GsfElectron::closestCtfTrackRef method, to access the internal storage of the trac...
void setConsumes(edm::ConsumesCollector &&) const override final
virtual SuperClusterRef superCluster() const
reference to a SuperCluster
Definition: GsfElectron.h:184
float deltaPhiSuperClusterTrackAtVtx() const
Definition: GsfElectron.h:252
float mvaValue(const edm::Ptr< reco::Candidate > &particle, const edm::Event &) const override
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double chi2() const
chi-squares
Definition: Vertex.h:98
float eEleClusterOverPout() const
Definition: GsfElectron.h:248
T const * get() const
Returns C++ pointer to the item.
Definition: Ref.h:244
std::vector< float > fillMVAVariables(const edm::Ptr< reco::Candidate > &particle, const edm::Event &) const override
int findCategory(const edm::Ptr< reco::Candidate > &particle) const override
bool isValid() const
Definition: HandleBase.h:74
bool getByLabel(InputTag const &tag, Handle< PROD > &result) const
Definition: Event.h:416
bool isEndcap(GeomDetEnumerators::SubDetector m)
bool isNull() const
Checks for null.
Definition: Ref.h:249
double ndof() const
Definition: Vertex.h:105
#define debug
Definition: HDRShower.cc:19
T const * product() const
Definition: Handle.h:81
float full5x5_hcalOverEcal() const
Definition: GsfElectron.h:463
Analysis-level electron class.
Definition: Electron.h:52
float ecalEnergy() const
Definition: GsfElectron.h:837
float full5x5_r9() const
Definition: GsfElectron.h:460
float deltaEtaSeedClusterTrackAtCalo() const
Definition: GsfElectron.h:250
bool getByLabel(InputTag const &, Handle< T > &) const
Definition: EventBase.h:94
HLT enums.
const Point & position() const
position
Definition: BeamSpot.h:62
std::string fullPath() const
Definition: FileInPath.cc:184
std::unique_ptr< const GBRForest > createSingleReader(const int iCategory, const edm::FileInPath &weightFile)
static reco::ConversionRef matchedConversion(const reco::GsfElectron &ele, const edm::Handle< reco::ConversionCollection > &convCol, const math::XYZPoint &beamspot, bool allowCkfMatch=true, float lxyMin=2.0, float probMin=1e-6, unsigned int nHitsBeforeVtxMax=0)
def move(src, dest)
Definition: eostools.py:510
virtual GsfTrackRef gsfTrack() const
reference to a GsfTrack
Definition: GsfElectron.h:185