CMS 3D CMS Logo

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