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 chargedAllIso(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 puChargedHadronIsoR(self,R=0.4):
155  if R == 0.3: return self.physObj.pfIsolationVariables().sumPUPt
156  elif R == 0.4: return self.physObj.puChargedHadronIso()
157  raise RuntimeError, "Electron chargedHadronIso missing for R=%s" % R
158 
159 
160 
161 
162  def chargedAllIso(self):
163  '''This function is used in the isolation, see Lepton class.
164  Here, we replace the all charged isolation by the all charged isolation with cone veto'''
165  return self.chargedAllIsoWithConeVeto()
166 
167 
168  def dxy(self, vertex=None):
169  '''Returns dxy.
170  Computed using vertex (or self.associatedVertex if vertex not specified),
171  and the gsf track.
172  '''
173  if vertex is None:
174  vertex = self.associatedVertex
175  return self.gsfTrack().dxy( vertex.position() )
176  def p4(self):
177  return ROOT.reco.Candidate.p4(self.physObj)
178 
179 # def p4(self):
180 # return self.physObj.p4(self.physObj.candidateP4Kind()) # if kind == None else kind)
181 
182  def dz(self, vertex=None):
183  '''Returns dz.
184  Computed using vertex (or self.associatedVertex if vertex not specified),
185  and the gsf track.
186  '''
187  if vertex is None:
188  vertex = self.associatedVertex
189  return self.gsfTrack().dz( vertex.position() )
190 
191  def lostInner(self) :
192  if hasattr(self.gsfTrack(),"trackerExpectedHitsInner") :
193  return self.gsfTrack().trackerExpectedHitsInner().numberOfLostHits()
194  else :
195  return self.gsfTrack().hitPattern().numberOfHits(ROOT.reco.HitPattern.MISSING_INNER_HITS)
196 
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:154
Definition: Lepton.py:1
tuple ElectronMVAID_Trig