CMS 3D CMS Logo

ElectronMVAEstimatorRun2Phys14NonTrig.cc
Go to the documentation of this file.
2 
5 
7 
9 
12 
13  _tag = conf.getParameter<std::string>("mvaTag");
14 
15  const std::vector <std::string> weightFileNames
16  = conf.getParameter<std::vector<std::string> >("weightFileNames");
17 
18  if( (int)(weightFileNames.size()) != nCategories )
19  throw cms::Exception("MVA config failure: ")
20  << "wrong number of weightfiles" << std::endl;
21 
22  _gbrForests.clear();
23  _MethodName = "BDTG method";
24  // Create a TMVA reader object for each category
25  for(int i=0; i<nCategories; i++){
26 
27  // Use unique_ptr so that all readers are properly cleaned up
28  // when the vector clear() is called in the destructor
29 
30  edm::FileInPath weightFile( weightFileNames[i] );
31  _gbrForests.push_back( createSingleReader(i, weightFile ) );
32 
33  }
34 
35 }
36 
39 }
40 
42 mvaValue( const edm::Ptr<reco::Candidate>& particle, const edm::Event& evt) const {
43 
44  const int iCategory = findCategory( particle );
45  const std::vector<float> vars = std::move( fillMVAVariables( particle, evt ) );
46  const float result = _gbrForests.at(iCategory)->GetClassifier(vars.data());
47 
48  constexpr bool debug = false;
49  if(debug) {
50  std::cout << " *** Inside the class _MethodName " << _MethodName << std::endl;
51  std::cout << " bin " << iCategory
52  << " fbrem " << vars[11] //_allMVAVars.fbrem
53  << " kfchi2 " << vars[9] //_allMVAVars.kfchi2
54  << " mykfhits " << vars[0] //_allMVAVars.kfhits
55  << " gsfchi2 " << vars[10] //_allMVAVars.gsfchi2
56  << " deta " << vars[15] //_allMVAVars.deta
57  << " dphi " << vars[16] //_allMVAVars.dphi
58  << " detacalo " << vars[17] //_allMVAVars.detacalo
59  << " see " << vars[1] //_allMVAVars.see
60  << " spp " << vars[2] //_allMVAVars.spp
61  << " etawidth " << vars[5] //_allMVAVars.etawidth
62  << " phiwidth " << vars[6] // _allMVAVars.phiwidth
63  << " OneMinusE1x5E5x5 " << vars[3] //_allMVAVars.OneMinusE1x5E5x5
64  << " R9 " << vars[4] //_allMVAVars.R9
65  << " HoE " << vars[7] //_allMVAVars.HoE
66  << " EoP " << vars[12] //_allMVAVars.EoP
67  << " IoEmIoP " << vars[14] //_allMVAVars.IoEmIoP
68  << " eleEoPout " << vars[13] // _allMVAVars.eleEoPout
69  //<< " d0 " << _allMVAVars.d0
70  // << " ip3d " << _allMVAVars.ip3d
71  << " eta " << vars[21] //_allMVAVars.SCeta
72  << " isBarrel " << vars[19] //_allMVAVars.isBarrel
73  << " isEndcap " << vars[20] //_allMVAVars.isEndcap
74  << " pt " << vars[18] //_allMVAVars.pt
75  << std::endl;
76  std::cout << " ### MVA " << result << std::endl;
77  }
78 
79  return result;
80 }
81 
83 
84  // Try to cast the particle into a reco particle.
85  // This should work for both reco and pat.
86  const edm::Ptr<reco::GsfElectron> eleRecoPtr = ( edm::Ptr<reco::GsfElectron> )particle;
87  if( eleRecoPtr.get() == NULL )
88  throw cms::Exception("MVA failure: ")
89  << " given particle is expected to be reco::GsfElectron or pat::Electron," << std::endl
90  << " but appears to be neither" << std::endl;
91 
92  const float pt = eleRecoPtr->pt();
93  const float eta = eleRecoPtr->superCluster()->eta();
94 
95  //
96  // Determine the category
97  //
98  int iCategory = UNDEFINED;
99  constexpr float ptSplit = 10; // we have above and below 10 GeV categories
100  constexpr float ebSplit = 0.800;// barrel is split into two regions
101  constexpr float ebeeSplit = 1.479; // division between barrel and endcap
102 
103  if (pt < ptSplit && std::abs(eta) < ebSplit)
104  iCategory = CAT_EB1_PT5to10;
105 
106  if (pt < ptSplit && std::abs(eta) >= ebSplit && std::abs(eta) < ebeeSplit)
107  iCategory = CAT_EB2_PT5to10;
108 
109  if (pt < ptSplit && std::abs(eta) >= ebeeSplit)
110  iCategory = CAT_EE_PT5to10;
111 
112  if (pt >= ptSplit && std::abs(eta) < ebSplit)
113  iCategory = CAT_EB1_PT10plus;
114 
115  if (pt >= ptSplit && std::abs(eta) >= ebSplit && std::abs(eta) < ebeeSplit)
116  iCategory = CAT_EB2_PT10plus;
117 
118  if (pt >= ptSplit && std::abs(eta) >= ebeeSplit)
119  iCategory = CAT_EE_PT10plus;
120 
121  return iCategory;
122 }
123 
126 
127  bool isEndcap = false;
128  if( category == CAT_EE_PT5to10 || category == CAT_EE_PT10plus )
129  isEndcap = true;
130 
131  return isEndcap;
132 }
133 
134 
135 std::unique_ptr<const GBRForest>
137 createSingleReader(const int iCategory, const edm::FileInPath &weightFile) {
138 
139  //
140  // Create the reader
141  //
142  TMVA::Reader tmpTMVAReader( "!Color:Silent:Error" );
143 
144  //
145  // Configure all variables and spectators. Note: the order and names
146  // must match what is found in the xml weights file!
147  //
148 
149  tmpTMVAReader.AddVariable("ele_kfhits", &_allMVAVars.kfhits);
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_kfchi2", &_allMVAVars.kfchi2);
165  tmpTMVAReader.AddVariable("ele_chi2_hits", &_allMVAVars.gsfchi2);
166 
167  // Energy matching
168  tmpTMVAReader.AddVariable("ele_fbrem", &_allMVAVars.fbrem);
169  tmpTMVAReader.AddVariable("ele_ep", &_allMVAVars.EoP);
170  tmpTMVAReader.AddVariable("ele_eelepout", &_allMVAVars.eleEoPout);
171  tmpTMVAReader.AddVariable("ele_IoEmIop", &_allMVAVars.IoEmIoP);
172 
173  // Geometrical matchings
174  tmpTMVAReader.AddVariable("ele_deltaetain", &_allMVAVars.deta);
175  tmpTMVAReader.AddVariable("ele_deltaphiin", &_allMVAVars.dphi);
176  tmpTMVAReader.AddVariable("ele_deltaetaseed", &_allMVAVars.detacalo);
177 
178  // Spectator variables
179  tmpTMVAReader.AddSpectator("ele_pT", &_allMVAVars.pt);
180  tmpTMVAReader.AddSpectator("ele_isbarrel", &_allMVAVars.isBarrel);
181  tmpTMVAReader.AddSpectator("ele_isendcap", &_allMVAVars.isEndcap);
182  tmpTMVAReader.AddSpectator("scl_eta", &_allMVAVars.SCeta);
183 
184  //
185  // Book the method and set up the weights file
186  //
187  tmpTMVAReader.BookMVA(_MethodName , weightFile.fullPath());
188 
189  return std::make_unique<const GBRForest>(dynamic_cast<TMVA::MethodBDT*>(tmpTMVAReader.FindMVA(_MethodName) ) );
190 }
191 
192 // A function that should work on both pat and reco objects
193 std::vector<float>
195  const edm::Event& ) const {
196 
197  // Try to cast the particle into a reco particle.
198  // This should work for both reco and pat.
199  const edm::Ptr<reco::GsfElectron> eleRecoPtr = ( edm::Ptr<reco::GsfElectron> )particle;
200  if( eleRecoPtr.get() == NULL )
201  throw cms::Exception("MVA failure: ")
202  << " given particle is expected to be reco::GsfElectron or pat::Electron," << std::endl
203  << " but appears to be neither" << std::endl;
204 
205  // the instance of the variables that we will manipulate
206  AllVariables allMVAVars;
207 
208  // Both pat and reco particles have exactly the same accessors, so we use a reco ptr
209  // throughout the code, with a single exception as of this writing, handled separately below.
210  auto superCluster = eleRecoPtr->superCluster();
211 
212  // To get to CTF track information in pat::Electron, we have to have the pointer
213  // to pat::Electron, it is not accessible from the pointer to reco::GsfElectron.
214  // This behavior is reported and is expected to change in the future (post-7.4.5 some time).
215  bool validKF= false;
216  reco::TrackRef myTrackRef = eleRecoPtr->closestCtfTrackRef();
217  const edm::Ptr<pat::Electron> elePatPtr(eleRecoPtr);
218  // Check if this is really a pat::Electron, and if yes, get the track ref from this new
219  // pointer instead
220  if( elePatPtr.get() != NULL )
221  myTrackRef = elePatPtr->closestCtfTrackRef();
222  validKF = (myTrackRef.isAvailable() && (myTrackRef.isNonnull()) );
223 
224  allMVAVars.kfhits = (validKF) ? myTrackRef->hitPattern().trackerLayersWithMeasurement() : -1. ;
225  // Pure ECAL -> shower shapes
226  allMVAVars.see = eleRecoPtr->full5x5_sigmaIetaIeta();
227  allMVAVars.spp = eleRecoPtr->full5x5_sigmaIphiIphi();
228  allMVAVars.OneMinusE1x5E5x5 = 1. - eleRecoPtr->full5x5_e1x5() / eleRecoPtr->full5x5_e5x5();
229  allMVAVars.R9 = eleRecoPtr->full5x5_r9();
230  allMVAVars.etawidth = superCluster->etaWidth();
231  allMVAVars.phiwidth = superCluster->phiWidth();
232  allMVAVars.HoE = eleRecoPtr->hadronicOverEm();
233  // Endcap only variables
234  allMVAVars.PreShowerOverRaw = superCluster->preshowerEnergy() / superCluster->rawEnergy();
235  //Pure tracking variables
236  allMVAVars.kfchi2 = (validKF) ? myTrackRef->normalizedChi2() : 0;
237  allMVAVars.gsfchi2 = eleRecoPtr->gsfTrack()->normalizedChi2();
238  // Energy matching
239  allMVAVars.fbrem = eleRecoPtr->fbrem();
240  allMVAVars.EoP = eleRecoPtr->eSuperClusterOverP();
241  allMVAVars.eleEoPout = eleRecoPtr->eEleClusterOverPout();
242  allMVAVars.IoEmIoP = (1.0/eleRecoPtr->ecalEnergy()) - (1.0 / eleRecoPtr->p());
243  // Geometrical matchings
244  allMVAVars.deta = eleRecoPtr->deltaEtaSuperClusterTrackAtVtx();
245  allMVAVars.dphi = eleRecoPtr->deltaPhiSuperClusterTrackAtVtx();
246  allMVAVars.detacalo = eleRecoPtr->deltaEtaSeedClusterTrackAtCalo();
247  // Spectator variables
248  allMVAVars.pt = eleRecoPtr->pt();
249  const float scEta = superCluster->eta();
250  constexpr float ebeeSplit = 1.479;
251  allMVAVars.isBarrel = ( std::abs(scEta) < ebeeSplit );
252  allMVAVars.isEndcap = ( std::abs(scEta) >= ebeeSplit );
253  allMVAVars.SCeta = scEta;
254 
255  constrainMVAVariables(allMVAVars);
256 
257  std::vector<float> vars;
258 
259  if( isEndcapCategory( findCategory(particle) ) ) {
260  vars = std::move( packMVAVariables( allMVAVars.kfhits,
261  allMVAVars.see,
262  allMVAVars.spp,
263  allMVAVars.OneMinusE1x5E5x5,
264  allMVAVars.R9,
265  allMVAVars.etawidth,
266  allMVAVars.phiwidth,
267  allMVAVars.HoE,
268  allMVAVars.PreShowerOverRaw,
269  allMVAVars.kfchi2,
270  allMVAVars.gsfchi2,
271  allMVAVars.fbrem,
272  allMVAVars.EoP,
273  allMVAVars.eleEoPout,
274  allMVAVars.IoEmIoP,
275  allMVAVars.deta,
276  allMVAVars.dphi,
277  allMVAVars.detacalo,
278  allMVAVars.pt,
279  allMVAVars.isBarrel,
280  allMVAVars.isEndcap,
281  allMVAVars.SCeta )
282  );
283  } else {
284  vars = std::move( packMVAVariables( allMVAVars.kfhits,
285  allMVAVars.see,
286  allMVAVars.spp,
287  allMVAVars.OneMinusE1x5E5x5,
288  allMVAVars.R9,
289  allMVAVars.etawidth,
290  allMVAVars.phiwidth,
291  allMVAVars.HoE,
292  allMVAVars.kfchi2,
293  allMVAVars.gsfchi2,
294  allMVAVars.fbrem,
295  allMVAVars.EoP,
296  allMVAVars.eleEoPout,
297  allMVAVars.IoEmIoP,
298  allMVAVars.deta,
299  allMVAVars.dphi,
300  allMVAVars.detacalo,
301  allMVAVars.pt,
302  allMVAVars.isBarrel,
303  allMVAVars.isEndcap,
304  allMVAVars.SCeta )
305  );
306  }
307 
308  return vars;
309 }
310 
312 
313  // Check that variables do not have crazy values
314 
315  if(vars.fbrem < -1.)
316  vars.fbrem = -1.;
317 
318  vars.deta = std::abs(vars.deta);
319  if(vars.deta > 0.06)
320  vars.deta = 0.06;
321 
322  vars.dphi = std::abs(vars.dphi);
323  if(vars.dphi > 0.6)
324  vars.dphi = 0.6;
325 
326  if(vars.EoP > 20.)
327  vars.EoP = 20.;
328 
329  if(vars.eleEoPout > 20.)
330  vars.eleEoPout = 20.;
331 
332  vars.detacalo = std::abs(vars.detacalo);
333  if(vars.detacalo > 0.2)
334  vars.detacalo = 0.2;
335 
336  if(vars.OneMinusE1x5E5x5 < -1.)
337  vars.OneMinusE1x5E5x5 = -1;
338 
339  if(vars.OneMinusE1x5E5x5 > 2.)
340  vars.OneMinusE1x5E5x5 = 2.;
341 
342  if(vars.R9 > 5)
343  vars.R9 = 5;
344 
345  if(vars.gsfchi2 > 200.)
346  vars.gsfchi2 = 200;
347 
348  if(vars.kfchi2 > 10.)
349  vars.kfchi2 = 10.;
350 }
351 
354  "ElectronMVAEstimatorRun2Phys14NonTrig");
bool isAvailable() const
Definition: Ref.h:576
T getParameter(std::string const &) const
virtual double pt() const final
transverse momentum
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
float full5x5_sigmaIphiIphi() const
Definition: GsfElectron.h:456
#define NULL
Definition: scimark2.h:8
float fbrem() const
Definition: GsfElectron.h:750
#define constexpr
TrackRef closestCtfTrackRef() const
Definition: GsfElectron.h:201
float full5x5_sigmaIetaIeta() const
Definition: GsfElectron.h:455
std::vector< float > packMVAVariables(const Args...args) const
std::vector< std::unique_ptr< const GBRForest > > _gbrForests
float deltaEtaSuperClusterTrackAtVtx() const
Definition: GsfElectron.h:249
std::unique_ptr< const GBRForest > createSingleReader(const int iCategory, const edm::FileInPath &weightFile)
float hadronicOverEm() const
Definition: GsfElectron.h:487
std::vector< float > fillMVAVariables(const edm::Ptr< reco::Candidate > &particle, const edm::Event &) const override
reco::TrackRef closestCtfTrackRef() const
override the reco::GsfElectron::closestCtfTrackRef method, to access the internal storage of the trac...
virtual SuperClusterRef superCluster() const
reference to a SuperCluster
Definition: GsfElectron.h:184
float deltaPhiSuperClusterTrackAtVtx() const
Definition: GsfElectron.h:252
ElectronMVAEstimatorRun2Phys14NonTrig(const edm::ParameterSet &conf)
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
virtual double p() const final
magnitude of momentum vector
float eEleClusterOverPout() const
Definition: GsfElectron.h:248
bool isEndcap(GeomDetEnumerators::SubDetector m)
float mvaValue(const edm::Ptr< reco::Candidate > &particle, const edm::Event &evt) const override
#define debug
Definition: HDRShower.cc:19
float ecalEnergy() const
Definition: GsfElectron.h:837
float full5x5_r9() const
Definition: GsfElectron.h:460
float deltaEtaSeedClusterTrackAtCalo() const
Definition: GsfElectron.h:250
#define DEFINE_EDM_PLUGIN(factory, type, name)
std::string fullPath() const
Definition: FileInPath.cc:184
def move(src, dest)
Definition: eostools.py:510
virtual GsfTrackRef gsfTrack() const
reference to a GsfTrack
Definition: GsfElectron.h:185
int findCategory(const edm::Ptr< reco::Candidate > &particle) const override