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.tightIdResult = None
13  self.associatedVertex = None
14  self.rho = None
15  self._mvaNonTrigV0 = {True:None, False:None}
16  self._mvaTrigV0 = {True:None, False:None}
17  self._mvaTrigNoIPV0 = {True:None, False:None}
18 
19  def electronID( self, id, vertex=None, rho=None ):
20  if id is None or id == "": return True
21  if vertex == None and hasattr(self,'associatedVertex') and self.associatedVertex != None: vertex = self.associatedVertex
22  if rho == None and hasattr(self,'rho') and self.rho != None: rho = self.rho
23  if id == "POG_MVA_ID_NonTrig": return self.mvaIDLoose()
24  elif id == "POG_MVA_ID_Trig": return self.mvaIDTight()
25  elif id == "POG_MVA_ID_NonTrig_full5x5": return self.mvaIDLoose(full5x5=True)
26  elif id == "POG_MVA_ID_Trig_full5x5": return self.mvaIDTight(full5x5=True)
27  elif id.startswith("POG_Cuts_ID_"):
28  return self.cutBasedId(id.replace("POG_Cuts_ID_","POG_"))
29  raise RuntimeError, "Electron id '%s' not yet implemented in Electron.py" % id
30 
31  def cutBasedId(self, wp, showerShapes="auto"):
32  if "_full5x5" in wp:
33  showerShapes = "full5x5"
34  wp = wp.replace("_full5x5","")
35  elif showerShapes == "auto":
36  if "POG_CSA14_25ns_v1" in wp or "POG_CSA14_50ns_v1" in wp:
37  showerShapes = "full5x5"
38  vars = {
39  'dEtaIn' : abs(self.physObj.deltaEtaSuperClusterTrackAtVtx()),
40  'dPhiIn' : abs(self.physObj.deltaPhiSuperClusterTrackAtVtx()),
41  'sigmaIEtaIEta' : self.physObj.full5x5_sigmaIetaIeta() if showerShapes == "full5x5" else self.physObj.sigmaIetaIeta(),
42  'H/E' : self.physObj.hadronicOverEm(),
43  #'1/E-1/p' : abs(1.0/self.physObj.ecalEnergy() - self.physObj.eSuperClusterOverP()/self.physObj.ecalEnergy()),
44  '1/E-1/p' : abs(1.0/self.physObj.ecalEnergy() - self.physObj.eSuperClusterOverP()/self.physObj.ecalEnergy()) if self.physObj.ecalEnergy()>0. else 9e9,
45  }
46  WP = {
47  ## ------- https://twiki.cern.ch/twiki/bin/viewauth/CMS/EgammaCutBasedIdentification?rev=31
48  '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])],
49  '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])],
50  '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])],
51  '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])],
52  ## ------- https://indico.cern.cH/Event/298242/contribution/1/material/slides/5.pdf (slide 5)
53  '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])],
54  '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])],
55  '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])],
56  '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])],
57  '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])],
58  '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])],
59  '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])],
60  '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])],
61  }
62  if wp not in WP:
63  raise RuntimeError, "Working point '%s' not yet implemented in Electron.py" % wp
64  for (cut_name,(cut_eb,cut_ee)) in WP[wp]:
65  if vars[cut_name] >= (cut_eb if self.physObj.isEB() else cut_ee):
66  return False
67  return True
68 
69  def absEffAreaIso(self,rho,effectiveAreas):
70  '''MIKE, missing doc.
71  Should have the same name as the function in the mother class.
72  Can call the mother class function with super.
73  '''
74  return self.absIsoFromEA(rho,self.superCluster().eta(),effectiveAreas.eGamma)
75 
76  def mvaId( self ):
77  return self.mvaNonTrigV0()
78 
79  def tightId( self ):
80  return self.tightIdResult
81 
82  def mvaNonTrigV0( self, full5x5=False, debug = False ):
83  if self._mvaNonTrigV0[full5x5] == None:
84  if self.associatedVertex == None: raise RuntimeError, "You need to set electron.associatedVertex before calling any MVA"
85  if self.rho == None: raise RuntimeError, "You need to set electron.rho before calling any MVA"
86  self._mvaNonTrigV0[full5x5] = ElectronMVAID_NonTrig(self.physObj, self.associatedVertex, self.rho, full5x5, debug)
87  return self._mvaNonTrigV0[full5x5]
88 
89  def mvaTrigV0( self, full5x5=False, debug = False ):
90  if self._mvaTrigV0[full5x5] == None:
91  if self.associatedVertex == None: raise RuntimeError, "You need to set electron.associatedVertex before calling any MVA"
92  if self.rho == None: raise RuntimeError, "You need to set electron.rho before calling any MVA"
93  self._mvaTrigV0[full5x5] = ElectronMVAID_Trig(self.physObj, self.associatedVertex, self.rho, full5x5, debug)
94  return self._mvaTrigV0[full5x5]
95 
96  def mvaTrigNoIPV0( self, full5x5=False, debug = False ):
97  if self._mvaTrigNoIPV0[full5x5] == None:
98  if self.associatedVertex == None: raise RuntimeError, "You need to set electron.associatedVertex before calling any MVA"
99  if self.rho == None: raise RuntimeError, "You need to set electron.rho before calling any MVA"
100  self._mvaTrigNoIPV0[full5x5] = ElectronMVAID_TrigNoIP(self.physObj, self.associatedVertex, self.rho, full5x5, debug)
101  return self._mvaTrigNoIPV0[full5x5]
102 
103 
104  def mvaIDTight(self, full5x5=False):
105  eta = abs(self.superCluster().eta())
106  if self.pt() < 20:
107  if (eta < 0.8) : return self.mvaTrigV0(full5x5) > +0.00;
108  elif (eta < 1.479): return self.mvaTrigV0(full5x5) > +0.10;
109  else : return self.mvaTrigV0(full5x5) > +0.62;
110  else:
111  if (eta < 0.8) : return self.mvaTrigV0(full5x5) > +0.94;
112  elif (eta < 1.479): return self.mvaTrigV0(full5x5) > +0.85;
113  else : return self.mvaTrigV0(full5x5) > +0.92;
114 
115  def mvaIDLoose(self, full5x5=False):
116  eta = abs(self.superCluster().eta())
117  if self.pt() < 10:
118  if (eta < 0.8) : return self.mvaNonTrigV0(full5x5) > +0.47;
119  elif (eta < 1.479): return self.mvaNonTrigV0(full5x5) > +0.004;
120  else : return self.mvaNonTrigV0(full5x5) > +0.295;
121  else:
122  if (eta < 0.8) : return self.mvaNonTrigV0(full5x5) > -0.34;
123  elif (eta < 1.479): return self.mvaNonTrigV0(full5x5) > -0.65;
124  else : return self.mvaNonTrigV0(full5x5) > +0.60;
125 
126  def mvaIDZZ(self):
127  return self.mvaIDLoose() and (self.gsfTrack().trackerExpectedHitsInner().numberOfLostHits()<=1)
128 
129  def chargedHadronIso(self,R=0.4):
130  if R == 0.3: return self.physObj.pfIsolationVariables().sumChargedHadronPt
131  elif R == 0.4: return self.physObj.chargedHadronIso()
132  raise RuntimeError, "Electron chargedHadronIso missing for R=%s" % R
133 
134  def neutralHadronIso(self,R=0.4):
135  if R == 0.3: return self.physObj.pfIsolationVariables().sumNeutralHadronEt
136  elif R == 0.4: return self.physObj.neutralHadronIso()
137  raise RuntimeError, "Electron neutralHadronIso missing for R=%s" % R
138 
139  def photonIso(self,R=0.4):
140  if R == 0.3: return self.physObj.pfIsolationVariables().sumPhotonEt
141  elif R == 0.4: return self.physObj.photonIso()
142  raise RuntimeError, "Electron photonIso missing for R=%s" % R
143 
144  def chargedAllIso(self,R=0.4):
145  if R == 0.3: return self.physObj.pfIsolationVariables().sumChargedParticlePt
146  raise RuntimeError, "Electron chargedAllIso missing for R=%s" % R
147 
148  def puChargedHadronIso(self,R=0.4):
149  if R == 0.3: return self.physObj.pfIsolationVariables().sumPUPt
150  elif R == 0.4: return self.physObj.puChargedHadronIso()
151  raise RuntimeError, "Electron chargedHadronIso missing for R=%s" % R
152 
153 
154 
155 
156  def chargedAllIso(self):
157  '''This function is used in the isolation, see Lepton class.
158  Here, we replace the all charged isolation by the all charged isolation with cone veto'''
159  return self.chargedAllIsoWithConeVeto()
160 
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 
171 
172  def p4(self,kind=None):
173  return self.physObj.p4(self.physObj.candidateP4Kind() if kind == None else kind)
174 
175  def dz(self, vertex=None):
176  '''Returns dz.
177  Computed using vertex (or self.associatedVertex if vertex not specified),
178  and the gsf track.
179  '''
180  if vertex is None:
181  vertex = self.associatedVertex
182  return self.gsfTrack().dz( vertex.position() )
183 
184  def lostInner(self) :
185  if hasattr(self.gsfTrack(),"trackerExpectedHitsInner") :
186  return self.gsfTrack().trackerExpectedHitsInner().numberOfLostHits()
187  else :
188  return self.gsfTrack().hitPattern().numberOfHits(ROOT.reco.HitPattern.MISSING_INNER_HITS)
189 
def puChargedHadronIso
Definition: Electron.py:148
tuple ElectronMVAID_NonTrig
T eta() const
tuple ElectronMVAID_TrigNoIP
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
Definition: Lepton.py:1
tuple ElectronMVAID_Trig