CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Electron.py
Go to the documentation of this file.
1 from PhysicsTools.Heppy.physicsobjects.Lepton import Lepton
2 from PhysicsTools.Heppy.physicsutils.ElectronMVAID import ElectronMVAID_Trig, ElectronMVAID_NonTrig, ElectronMVAID_TrigNoIP
3 import ROOT
4 
5 class Electron( Lepton ):
6 
7  def __init__(self, *args, **kwargs):
8  '''Initializing tightIdResult to None. The user is responsible
9  for setting this attribute externally if he wants to use the tightId
10  function.'''
11  super(Electron, self).__init__(*args, **kwargs)
12  self._physObjInit()
13 
14  def _physObjInit(self):
15  self.tightIdResult = None
16  self.associatedVertex = None
17  self.rho = None
18  self._mvaNonTrigV0 = {True:None, False:None}
19  self._mvaTrigV0 = {True:None, False:None}
20  self._mvaTrigNoIPV0 = {True:None, False:None}
21 
22  def electronID( self, id, vertex=None, rho=None ):
23  if id is None or id == "": return True
24  if vertex == None and hasattr(self,'associatedVertex') and self.associatedVertex != None: vertex = self.associatedVertex
25  if rho == None and hasattr(self,'rho') and self.rho != None: rho = self.rho
26  if id == "POG_MVA_ID_NonTrig": return self.mvaIDLoose()
27  elif id == "POG_MVA_ID_Trig": return self.mvaIDTight()
28  elif id == "POG_MVA_ID_NonTrig_full5x5": return self.mvaIDLoose(full5x5=True)
29  elif id == "POG_MVA_ID_Trig_full5x5": return self.mvaIDTight(full5x5=True)
30  elif id.startswith("POG_Cuts_ID_"):
31  return self.cutBasedId(id.replace("POG_Cuts_ID_","POG_"))
32  for ID in self.electronIDs():
33  if ID.first == id:
34  return ID.second
35  raise RuntimeError, "Electron id '%s' not yet implemented in Electron.py" % id
36 
37  def cutBasedId(self, wp, showerShapes="auto"):
38  if "_full5x5" in wp:
39  showerShapes = "full5x5"
40  wp = wp.replace("_full5x5","")
41  elif showerShapes == "auto":
42  if "POG_CSA14_25ns_v1" in wp or "POG_CSA14_50ns_v1" in wp:
43  showerShapes = "full5x5"
44  vars = {
45  'dEtaIn' : abs(self.physObj.deltaEtaSuperClusterTrackAtVtx()),
46  'dPhiIn' : abs(self.physObj.deltaPhiSuperClusterTrackAtVtx()),
47  'sigmaIEtaIEta' : self.physObj.full5x5_sigmaIetaIeta() if showerShapes == "full5x5" else self.physObj.sigmaIetaIeta(),
48  'H/E' : self.physObj.hadronicOverEm(),
49  #'1/E-1/p' : abs(1.0/self.physObj.ecalEnergy() - self.physObj.eSuperClusterOverP()/self.physObj.ecalEnergy()),
50  '1/E-1/p' : abs(1.0/self.physObj.ecalEnergy() - self.physObj.eSuperClusterOverP()/self.physObj.ecalEnergy()) if self.physObj.ecalEnergy()>0. else 9e9,
51  }
52  WP = {
53  ## ------- https://twiki.cern.ch/twiki/bin/viewauth/CMS/EgammaCutBasedIdentification?rev=31
54  'POG_2012_Veto' : [('dEtaIn', [0.007, 0.01]), ('dPhiIn', [0.8, 0.7 ]), ('sigmaIEtaIEta', [0.01, 0.03]), ('H/E', [0.15, 9e9]), ('1/E-1/p', [9e9, 9e9])],
55  'POG_2012_Loose' : [('dEtaIn', [0.007, 0.009]), ('dPhiIn', [0.15, 0.1 ]), ('sigmaIEtaIEta', [0.01, 0.03]), ('H/E', [0.12, 0.1]), ('1/E-1/p', [0.05, 0.05])],
56  'POG_2012_Medium' : [('dEtaIn', [0.004, 0.007]), ('dPhiIn', [0.06, 0.03]), ('sigmaIEtaIEta', [0.01, 0.03]), ('H/E', [0.12, 0.1]), ('1/E-1/p', [0.05, 0.05])],
57  'POG_2012_Tight' : [('dEtaIn', [0.004, 0.005]), ('dPhiIn', [0.03, 0.02]), ('sigmaIEtaIEta', [0.01, 0.03]), ('H/E', [0.12, 0.1]), ('1/E-1/p', [0.05, 0.05])],
58  ## ------- https://indico.cern.cH/Event/298242/contribution/1/material/slides/5.pdf (slide 5)
59  'POG_CSA14_25ns_v1_Veto' : [('dEtaIn', [0.012, 0.015]), ('dPhiIn', [0.8, 0.7 ]), ('sigmaIEtaIEta', [0.01 , 0.033]), ('H/E', [0.15, 9e9 ]), ('1/E-1/p', [9e9, 9e9])],
60  'POG_CSA14_25ns_v1_Loose' : [('dEtaIn', [0.012, 0.014]), ('dPhiIn', [0.15, 0.1 ]), ('sigmaIEtaIEta', [0.01 , 0.033]), ('H/E', [0.12, 0.12]), ('1/E-1/p', [0.05, 0.05])],
61  'POG_CSA14_25ns_v1_Medium' : [('dEtaIn', [0.009, 0.012]), ('dPhiIn', [0.06, 0.03]), ('sigmaIEtaIEta', [0.01 , 0.031]), ('H/E', [0.12, 0.12]), ('1/E-1/p', [0.05, 0.05])],
62  'POG_CSA14_25ns_v1_Tight' : [('dEtaIn', [0.009, 0.010]), ('dPhiIn', [0.03, 0.02]), ('sigmaIEtaIEta', [0.01 , 0.031]), ('H/E', [0.12, 0.12]), ('1/E-1/p', [0.05, 0.05])],
63  'POG_CSA14_50ns_v1_Veto' : [('dEtaIn', [0.012, 0.022]), ('dPhiIn', [0.8, 0.7 ]), ('sigmaIEtaIEta', [0.012, 0.033]), ('H/E', [0.15, 9e9 ]), ('1/E-1/p', [9e9, 9e9])],
64  'POG_CSA14_50ns_v1_Loose' : [('dEtaIn', [0.012, 0.021]), ('dPhiIn', [0.15, 0.1 ]), ('sigmaIEtaIEta', [0.012, 0.033]), ('H/E', [0.12, 0.12]), ('1/E-1/p', [0.05, 0.05])],
65  'POG_CSA14_50ns_v1_Medium' : [('dEtaIn', [0.009, 0.019]), ('dPhiIn', [0.06, 0.03]), ('sigmaIEtaIEta', [0.01 , 0.031]), ('H/E', [0.12, 0.12]), ('1/E-1/p', [0.05, 0.05])],
66  'POG_CSA14_50ns_v1_Tight' : [('dEtaIn', [0.009, 0.017]), ('dPhiIn', [0.03, 0.02]), ('sigmaIEtaIEta', [0.01 , 0.031]), ('H/E', [0.12, 0.12]), ('1/E-1/p', [0.05, 0.05])],
67  }
68  if wp not in WP:
69  raise RuntimeError, "Working point '%s' not yet implemented in Electron.py" % wp
70  for (cut_name,(cut_eb,cut_ee)) in WP[wp]:
71  if vars[cut_name] >= (cut_eb if self.physObj.isEB() else cut_ee):
72  return False
73  return True
74 
75  def absEffAreaIso(self,rho,effectiveAreas):
76  '''MIKE, missing doc.
77  Should have the same name as the function in the mother class.
78  Can call the mother class function with super.
79  '''
80  return self.absIsoFromEA(rho,self.superCluster().eta(),effectiveAreas.eGamma)
81 
82  def mvaId( self ):
83  return self.mvaNonTrigV0()
84 
85  def tightId( self ):
86  return self.tightIdResult
87 
88  def mvaNonTrigV0( self, full5x5=False, debug = False ):
89  if self._mvaNonTrigV0[full5x5] == None:
90  if self.associatedVertex == None: raise RuntimeError, "You need to set electron.associatedVertex before calling any MVA"
91  if self.rho == None: raise RuntimeError, "You need to set electron.rho before calling any MVA"
92  self._mvaNonTrigV0[full5x5] = ElectronMVAID_NonTrig(self.physObj, self.associatedVertex, self.rho, full5x5, debug)
93  return self._mvaNonTrigV0[full5x5]
94 
95  def mvaTrigV0( self, full5x5=False, debug = False ):
96  if self._mvaTrigV0[full5x5] == None:
97  if self.associatedVertex == None: raise RuntimeError, "You need to set electron.associatedVertex before calling any MVA"
98  if self.rho == None: raise RuntimeError, "You need to set electron.rho before calling any MVA"
99  self._mvaTrigV0[full5x5] = ElectronMVAID_Trig(self.physObj, self.associatedVertex, self.rho, full5x5, debug)
100  return self._mvaTrigV0[full5x5]
101 
102  def mvaTrigNoIPV0( self, full5x5=False, debug = False ):
103  if self._mvaTrigNoIPV0[full5x5] == None:
104  if self.associatedVertex == None: raise RuntimeError, "You need to set electron.associatedVertex before calling any MVA"
105  if self.rho == None: raise RuntimeError, "You need to set electron.rho before calling any MVA"
106  self._mvaTrigNoIPV0[full5x5] = ElectronMVAID_TrigNoIP(self.physObj, self.associatedVertex, self.rho, full5x5, debug)
107  return self._mvaTrigNoIPV0[full5x5]
108 
109 
110  def mvaIDTight(self, full5x5=False):
111  eta = abs(self.superCluster().eta())
112  if self.pt() < 20:
113  if (eta < 0.8) : return self.mvaTrigV0(full5x5) > +0.00;
114  elif (eta < 1.479): return self.mvaTrigV0(full5x5) > +0.10;
115  else : return self.mvaTrigV0(full5x5) > +0.62;
116  else:
117  if (eta < 0.8) : return self.mvaTrigV0(full5x5) > +0.94;
118  elif (eta < 1.479): return self.mvaTrigV0(full5x5) > +0.85;
119  else : return self.mvaTrigV0(full5x5) > +0.92;
120 
121  def mvaIDLoose(self, full5x5=False):
122  eta = abs(self.superCluster().eta())
123  if self.pt() < 10:
124  if (eta < 0.8) : return self.mvaNonTrigV0(full5x5) > +0.47;
125  elif (eta < 1.479): return self.mvaNonTrigV0(full5x5) > +0.004;
126  else : return self.mvaNonTrigV0(full5x5) > +0.295;
127  else:
128  if (eta < 0.8) : return self.mvaNonTrigV0(full5x5) > -0.34;
129  elif (eta < 1.479): return self.mvaNonTrigV0(full5x5) > -0.65;
130  else : return self.mvaNonTrigV0(full5x5) > +0.60;
131 
132  def mvaIDZZ(self):
133  return self.mvaIDLoose() and (self.gsfTrack().trackerExpectedHitsInner().numberOfLostHits()<=1)
134 
135  def chargedHadronIsoR(self,R=0.4):
136  if R == 0.3: return self.physObj.pfIsolationVariables().sumChargedHadronPt
137  elif R == 0.4: return self.physObj.chargedHadronIso()
138  raise RuntimeError, "Electron chargedHadronIso missing for R=%s" % R
139 
140  def neutralHadronIsoR(self,R=0.4):
141  if R == 0.3: return self.physObj.pfIsolationVariables().sumNeutralHadronEt
142  elif R == 0.4: return self.physObj.neutralHadronIso()
143  raise RuntimeError, "Electron neutralHadronIso missing for R=%s" % R
144 
145  def photonIsoR(self,R=0.4):
146  if R == 0.3: return self.physObj.pfIsolationVariables().sumPhotonEt
147  elif R == 0.4: return self.physObj.photonIso()
148  raise RuntimeError, "Electron photonIso missing for R=%s" % R
149 
150  def chargedAllIsoR(self,R=0.4):
151  if R == 0.3: return self.physObj.pfIsolationVariables().sumChargedParticlePt
152  raise RuntimeError, "Electron chargedAllIso missing for R=%s" % R
153 
154  def chargedAllIso(self):
155  raise RuntimeError, "Electron chargedAllIso missing"
156 
157  def puChargedHadronIsoR(self,R=0.4):
158  if R == 0.3: return self.physObj.pfIsolationVariables().sumPUPt
159  elif R == 0.4: return self.physObj.puChargedHadronIso()
160  raise RuntimeError, "Electron chargedHadronIso missing for R=%s" % R
161 
162  def dxy(self, vertex=None):
163  '''Returns dxy.
164  Computed using vertex (or self.associatedVertex if vertex not specified),
165  and the gsf track.
166  '''
167  if vertex is None:
168  vertex = self.associatedVertex
169  return self.gsfTrack().dxy( vertex.position() )
170  def p4(self):
171  return ROOT.reco.Candidate.p4(self.physObj)
172 
173 # def p4(self):
174 # return self.physObj.p4(self.physObj.candidateP4Kind()) # if kind == None else kind)
175 
176  def dz(self, vertex=None):
177  '''Returns dz.
178  Computed using vertex (or self.associatedVertex if vertex not specified),
179  and the gsf track.
180  '''
181  if vertex is None:
182  vertex = self.associatedVertex
183  return self.gsfTrack().dz( vertex.position() )
184 
185  def lostInner(self) :
186  if hasattr(self.gsfTrack(),"trackerExpectedHitsInner") :
187  return self.gsfTrack().trackerExpectedHitsInner().numberOfLostHits()
188  else :
189  return self.gsfTrack().hitPattern().numberOfHits(ROOT.reco.HitPattern.MISSING_INNER_HITS)
190 
tuple ElectronMVAID_NonTrig
T eta() const
tuple ElectronMVAID_TrigNoIP
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
def puChargedHadronIsoR
Definition: Electron.py:157
Definition: Lepton.py:1
tuple ElectronMVAID_Trig