Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:23:27

0001 from PhysicsTools.Heppy.physicsobjects.Lepton import Lepton
0002 from PhysicsTools.Heppy.physicsutils.ElectronMVAID import *
0003 from PhysicsTools.HeppyCore.utils.deltar import deltaR
0004 import ROOT
0005 
0006 class Electron( Lepton ):
0007 
0008     def __init__(self, *args, **kwargs):
0009         '''Initializing tightIdResult to None. The user is responsible
0010         for setting this attribute externally if he wants to use the tightId
0011         function.'''
0012         super(Electron, self).__init__(*args, **kwargs)
0013         self._physObjInit()
0014 
0015     def _physObjInit(self):
0016         self.tightIdResult = None
0017         self.associatedVertex = None
0018         self.rho              = None
0019         self._mvaNonTrigV0  = {True:None, False:None}
0020         self._mvaTrigV0     = {True:None, False:None}
0021         self._mvaTrigNoIPV0 = {True:None, False:None}
0022         self._mvaRun2 = {}
0023 
0024     def electronID( self, id, vertex=None, rho=None ):
0025         if id is None or id == "": return True
0026         if vertex == None and hasattr(self,'associatedVertex') and self.associatedVertex != None: vertex = self.associatedVertex
0027         if rho == None and hasattr(self,'rho') and self.rho != None: rho = self.rho
0028         if   id == "POG_MVA_ID_NonTrig":  return self.mvaIDLoose()
0029         elif id == "POG_MVA_ID_Trig":     return self.mvaIDTight()
0030         elif id == "POG_MVA_ID_NonTrig_full5x5":  return self.mvaIDLoose(full5x5=True)
0031         elif id == "POG_MVA_ID_Trig_full5x5":     return self.mvaIDTight(full5x5=True)
0032         elif id == "POG_MVA_ID_Phys14_NonTrig_VLoose":   return self.mvaIDRun2("NonTrigPhys14","VLoose")
0033         elif id == "POG_MVA_ID_Phys14_NonTrig_Loose":    return self.mvaIDRun2("NonTrigPhys14","Loose")
0034         elif id == "POG_MVA_ID_Phys14_NonTrig_Tight":    return self.mvaIDRun2("NonTrigPhys14","Tight")
0035         elif id == "POG_MVA_ID_Spring15_NonTrig_VLoose":   return self.mvaIDRun2("NonTrigSpring15MiniAOD","VLoose")
0036         elif id == "POG_MVA_ID_Spring15_NonTrig_VLooseIdEmu":   return self.mvaIDRun2("NonTrigSpring15MiniAOD","VLooseIdEmu")
0037         elif id == "POG_MVA_ID_Spring15_NonTrig_VLooseIdIsoEmu":   return self.mvaIDRun2("NonTrigSpring15MiniAOD","VLooseIdIsoEmu")
0038         elif id == "POG_MVA_ID_Spring15_NonTrig_Tight":    return self.mvaIDRun2("NonTrigSpring15MiniAOD","Tight")
0039         elif id == "MVA_ID_NonTrig_Phys14Fix_HZZ":     return self.mvaIDRun2("NonTrigPhys14Fix","HZZ")
0040         elif id == "MVA_ID_NonTrig_Spring15_HZZ":     return self.mvaIDRun2("NonTrigSpring15MiniAOD","HZZ")
0041         elif id.startswith("POG_Cuts_ID_"):
0042             return self.cutBasedId(id.replace("POG_Cuts_ID_","POG_"))
0043         for ID in self.electronIDs():
0044             if ID.first == id:
0045                 return ID.second
0046         raise RuntimeError("Electron id '%s' not yet implemented in Electron.py" % id)
0047 
0048     def cutBasedId(self, wp, showerShapes="auto"):
0049         if "_full5x5" in wp:
0050             showerShapes = "full5x5"
0051             wp = wp.replace("_full5x5","")
0052         elif showerShapes == "auto":
0053             if "POG_CSA14_25ns_v1" in wp or "POG_CSA14_50ns_v1" in wp or "POG_PHYS14_25ns_v1" in wp or "POG_PHYS14_25ns_v1_ConvVeto" in wp or "POG_PHYS14_25ns_v1_ConvVetoDxyDz" in wp or "POG_PHYS14_25ns_v2" in wp or "POG_PHYS14_25ns_v2_ConvVeto" in wp or "POG_PHYS14_25ns_v2_ConvVetoDxyDz" in wp or "POG_SPRING15_25ns_v1" in wp or "POG_SPRING15_25ns_v1_ConvVeto" in wp or "POG_SPRING15_25ns_v1_ConvVetoDxyDz" in wp or "POG_SPRING15_50ns_v2" in wp or "POG_SPRING15_50ns_v2_ConvVeto" in wp or "POG_SPRING15_50ns_v2_ConvVetoDxyDz" in wp:
0054                 showerShapes = "full5x5"
0055         vars = {
0056             'dEtaIn' : abs(self.physObj.deltaEtaSuperClusterTrackAtVtx()),
0057             'dPhiIn' : abs(self.physObj.deltaPhiSuperClusterTrackAtVtx()),
0058             'sigmaIEtaIEta' : self.physObj.full5x5_sigmaIetaIeta() if showerShapes == "full5x5" else self.physObj.sigmaIetaIeta(),
0059             'H/E' : self.physObj.hadronicOverEm(),
0060             #'1/E-1/p' : abs(1.0/self.physObj.ecalEnergy() - self.physObj.eSuperClusterOverP()/self.physObj.ecalEnergy()),
0061             '1/E-1/p' : abs(1.0/self.physObj.ecalEnergy() - self.physObj.eSuperClusterOverP()/self.physObj.ecalEnergy()) if self.physObj.ecalEnergy()>0. else 9e9,
0062             'conversionVeto' : self.physObj.passConversionVeto(),
0063             'missingHits' : self.physObj.gsfTrack().hitPattern().numberOfLostHits(ROOT.reco.HitPattern.MISSING_INNER_HITS), # http://cmslxr.fnal.gov/source/DataFormats/TrackReco/interface/HitPattern.h?v=CMSSW_7_2_3#0153
0064             'dxy' : abs(self.dxy()),
0065             'dz' : abs(self.dz()),
0066         }
0067         WP = {
0068             ## ------- https://twiki.cern.ch/twiki/bin/viewauth/CMS/EgammaCutBasedIdentification?rev=31
0069             '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])],
0070             '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])],
0071             '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])],
0072             '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])],
0073             # RIC: in the EG POG WPs, isolation is included too. Here only the pure ID part.
0074             # dz and d0 cuts are excluded here as well.
0075             ## ------- https://twiki.cern.ch/twiki/bin/viewauth/CMS/CutBasedElectronIdentificationRun2#Working_points_for_CSA14_samples?rev=13
0076             'POG_CSA14_25ns_v1_Veto'   :  [('dEtaIn', [0.017938, 0.014569]), ('dPhiIn', [0.182958, 0.230914]), ('sigmaIEtaIEta', [0.012708, 0.036384]), ('H/E', [0.335015, 0.200792]), ('1/E-1/p', [0.198287, 0.146856])],
0077             'POG_CSA14_25ns_v1_Loose'  :  [('dEtaIn', [0.014928, 0.013045]), ('dPhiIn', [0.141050, 0.149017]), ('sigmaIEtaIEta', [0.011304, 0.035536]), ('H/E', [0.127690, 0.107898]), ('1/E-1/p', [0.097806, 0.102261])],
0078             'POG_CSA14_25ns_v1_Medium' :  [('dEtaIn', [0.013071, 0.010006]), ('dPhiIn', [0.132113, 0.052321]), ('sigmaIEtaIEta', [0.010726, 0.032882]), ('H/E', [0.109761, 0.101755]), ('1/E-1/p', [0.032639, 0.041427])],
0079             'POG_CSA14_25ns_v1_Tight'  :  [('dEtaIn', [0.012671, 0.008823]), ('dPhiIn', [0.025218, 0.027286]), ('sigmaIEtaIEta', [0.010061, 0.030222]), ('H/E', [0.065085, 0.090710]), ('1/E-1/p', [0.027873, 0.019404])],
0080             'POG_CSA14_50ns_v1_Veto'   :  [('dEtaIn', [0.021, 0.028]), ('dPhiIn', [0.25 , 0.23 ]), ('sigmaIEtaIEta', [0.012, 0.035]), ('H/E', [0.24 , 0.19 ]), ('1/E-1/p', [0.32 , 0.13 ])],
0081             'POG_CSA14_50ns_v1_Loose'  :  [('dEtaIn', [0.016, 0.025]), ('dPhiIn', [0.080, 0.097]), ('sigmaIEtaIEta', [0.012, 0.032]), ('H/E', [0.15 , 0.12 ]), ('1/E-1/p', [0.11 , 0.11 ])],
0082             'POG_CSA14_50ns_v1_Medium' :  [('dEtaIn', [0.015, 0.023]), ('dPhiIn', [0.051, 0.056]), ('sigmaIEtaIEta', [0.010, 0.030]), ('H/E', [0.10 , 0.099]), ('1/E-1/p', [0.053, 0.11 ])],
0083             'POG_CSA14_50ns_v1_Tight'  :  [('dEtaIn', [0.012, 0.019]), ('dPhiIn', [0.024, 0.043]), ('sigmaIEtaIEta', [0.010, 0.029]), ('H/E', [0.074, 0.080]), ('1/E-1/p', [0.026, 0.076])],
0084             ## ------- https://twiki.cern.ch/twiki/bin/viewauth/CMS/CutBasedElectronIdentificationRun2#Working_points_for_PHYS14_sample?rev=13
0085             'POG_PHYS14_25ns_v1_Veto'   :  [('dEtaIn', [0.016315, 0.010671]), ('dPhiIn', [0.252044, 0.245263]), ('sigmaIEtaIEta', [0.011100 , 0.033987]), ('H/E', [0.345843, 0.134691]), ('1/E-1/p', [0.248070, 0.157160])],
0086             'POG_PHYS14_25ns_v1_Loose'  :  [('dEtaIn', [0.012442, 0.010654]), ('dPhiIn', [0.072624, 0.145129]), ('sigmaIEtaIEta', [0.010557 , 0.032602]), ('H/E', [0.121476, 0.131862]), ('1/E-1/p', [0.221803, 0.142283])],
0087             'POG_PHYS14_25ns_v1_Medium' :  [('dEtaIn', [0.007641, 0.009285]), ('dPhiIn', [0.032643, 0.042447]), ('sigmaIEtaIEta', [0.010399 , 0.029524]), ('H/E', [0.060662, 0.104263]), ('1/E-1/p', [0.153897, 0.137468])],
0088             'POG_PHYS14_25ns_v1_Tight'  :  [('dEtaIn', [0.006574, 0.005681]), ('dPhiIn', [0.022868, 0.032046]), ('sigmaIEtaIEta', [0.010181 , 0.028766]), ('H/E', [0.037553, 0.081902]), ('1/E-1/p', [0.131191, 0.106055])],
0089             ## ------- https://twiki.cern.ch/twiki/bin/viewauth/CMS/CutBasedElectronIdentificationRun2#Working_points_for_PHYS14_sample?rev=17
0090             'POG_PHYS14_25ns_v2_Veto'   :  [('dEtaIn', [0.013625, 0.011932]), ('dPhiIn', [0.230374, 0.255450]), ('sigmaIEtaIEta', [0.011586 , 0.031849]), ('H/E', [0.181130, 0.223870]), ('1/E-1/p', [0.295751, 0.155501])],
0091             'POG_PHYS14_25ns_v2_Loose'  :  [('dEtaIn', [0.009277, 0.009833]), ('dPhiIn', [0.094739, 0.149934]), ('sigmaIEtaIEta', [0.010331 , 0.031838]), ('H/E', [0.093068, 0.115754]), ('1/E-1/p', [0.189968, 0.140662])],
0092             'POG_PHYS14_25ns_v2_Medium' :  [('dEtaIn', [0.008925, 0.007429]), ('dPhiIn', [0.035973, 0.067879]), ('sigmaIEtaIEta', [0.009996 , 0.030135]), ('H/E', [0.050537, 0.086782]), ('1/E-1/p', [0.091942, 0.100683])],
0093             'POG_PHYS14_25ns_v2_Tight'  :  [('dEtaIn', [0.006046, 0.007057]), ('dPhiIn', [0.028092, 0.030159]), ('sigmaIEtaIEta', [0.009947 , 0.028237]), ('H/E', [0.045772, 0.067778]), ('1/E-1/p', [0.020118, 0.098919])],
0094             ## ------- https://twiki.cern.ch/twiki/bin/view/CMS/CutBasedElectronIdentificationRun2?rev=24#Working_points_for_Spring15_MC_s
0095             'POG_SPRING15_50ns_v2_Veto'   :  [('dEtaIn', [0.01260, 0.01090]), ('dPhiIn', [0.1070, 0.2190]), ('sigmaIEtaIEta', [0.0120, 0.0339]), ('H/E', [0.1860, 0.0962]), ('1/E-1/p', [0.2390, 0.141])],
0096             'POG_SPRING15_50ns_v2_Loose'  :  [('dEtaIn', [0.00976, 0.00952]), ('dPhiIn', [0.0929, 0.1810]), ('sigmaIEtaIEta', [0.0105, 0.0318]), ('H/E', [0.0765, 0.0824]), ('1/E-1/p', [0.1840, 0.125])],
0097             'POG_SPRING15_50ns_v2_Medium' :  [('dEtaIn', [0.00940, 0.00773]), ('dPhiIn', [0.0296, 0.1480]), ('sigmaIEtaIEta', [0.0101, 0.0287]), ('H/E', [0.0372, 0.0546]), ('1/E-1/p', [0.1180, 0.104])],
0098             'POG_SPRING15_50ns_v2_Tight'  :  [('dEtaIn', [0.00864, 0.00762]), ('dPhiIn', [0.0291, 0.0439]), ('sigmaIEtaIEta', [0.0101, 0.0287]), ('H/E', [0.0372, 0.0544]), ('1/E-1/p', [0.0116, 0.010])],
0099             'POG_SPRING15_25ns_v1_Veto'   :  [('dEtaIn', [0.01520, 0.01130]), ('dPhiIn', [0.2160, 0.2370]), ('sigmaIEtaIEta', [0.0114, 0.0352]), ('H/E', [0.1810, 0.1160]), ('1/E-1/p', [0.2070, 0.17400])],
0100             'POG_SPRING15_25ns_v1_Loose'  :  [('dEtaIn', [0.01050, 0.00814]), ('dPhiIn', [0.1150, 0.1820]), ('sigmaIEtaIEta', [0.0103, 0.0301]), ('H/E', [0.1040, 0.0897]), ('1/E-1/p', [0.1020, 0.12600])],
0101             'POG_SPRING15_25ns_v1_Medium' :  [('dEtaIn', [0.01030, 0.00733]), ('dPhiIn', [0.0336, 0.1140]), ('sigmaIEtaIEta', [0.0101, 0.0283]), ('H/E', [0.0876, 0.0678]), ('1/E-1/p', [0.0174, 0.08980])],
0102             'POG_SPRING15_25ns_v1_Tight'  :  [('dEtaIn', [0.00926, 0.00724]), ('dPhiIn', [0.0336, 0.0918]), ('sigmaIEtaIEta', [0.0101, 0.0279]), ('H/E', [0.0597, 0.0615]), ('1/E-1/p', [0.0120, 0.00999])],
0103 
0104         }
0105         WP_conversion_veto = {
0106             # missing Hits incremented by 1 because we return False if >=, note the '='
0107             ## ------- https://twiki.cern.ch/twiki/bin/viewauth/CMS/CutBasedElectronIdentificationRun2#Working_points_for_CSA14_samples?rev=13
0108             'POG_CSA14_25ns_v1_ConvVeto_Veto'   :  WP['POG_CSA14_25ns_v1_Veto'  ]+[('conversionVeto', [True, True]), ('missingHits', [3, 4])],
0109             'POG_CSA14_25ns_v1_ConvVeto_Loose'  :  WP['POG_CSA14_25ns_v1_Loose' ]+[('conversionVeto', [True, True]), ('missingHits', [2, 2])],
0110             'POG_CSA14_25ns_v1_ConvVeto_Medium' :  WP['POG_CSA14_25ns_v1_Medium']+[('conversionVeto', [True, True]), ('missingHits', [2, 2])],
0111             'POG_CSA14_25ns_v1_ConvVeto_Tight'  :  WP['POG_CSA14_25ns_v1_Tight' ]+[('conversionVeto', [True, True]), ('missingHits', [2, 2])],
0112             'POG_CSA14_50ns_v1_ConvVeto_Veto'   :  WP['POG_CSA14_50ns_v1_Veto'  ]+[('conversionVeto', [True, True]), ('missingHits', [3, 4])],
0113             'POG_CSA14_50ns_v1_ConvVeto_Loose'  :  WP['POG_CSA14_50ns_v1_Loose' ]+[('conversionVeto', [True, True]), ('missingHits', [2, 2])],
0114             'POG_CSA14_50ns_v1_ConvVeto_Medium' :  WP['POG_CSA14_50ns_v1_Medium']+[('conversionVeto', [True, True]), ('missingHits', [2, 2])],
0115             'POG_CSA14_50ns_v1_ConvVeto_Tight'  :  WP['POG_CSA14_50ns_v1_Tight' ]+[('conversionVeto', [True, True]), ('missingHits', [2, 2])],
0116             ## ------- https://twiki.cern.ch/twiki/bin/viewauth/CMS/CutBasedElectronIdentificationRun2#Working_points_for_PHYS14_sample?rev=13
0117             'POG_PHYS14_25ns_v1_ConvVeto_Veto'   :  WP['POG_PHYS14_25ns_v1_Veto'  ]+[('conversionVeto', [True, True]), ('missingHits', [3, 4])],
0118             'POG_PHYS14_25ns_v1_ConvVeto_Loose'  :  WP['POG_PHYS14_25ns_v1_Loose' ]+[('conversionVeto', [True, True]), ('missingHits', [2, 2])],
0119             'POG_PHYS14_25ns_v1_ConvVeto_Medium' :  WP['POG_PHYS14_25ns_v1_Medium']+[('conversionVeto', [True, True]), ('missingHits', [2, 2])],
0120             'POG_PHYS14_25ns_v1_ConvVeto_Tight'  :  WP['POG_PHYS14_25ns_v1_Tight' ]+[('conversionVeto', [True, True]), ('missingHits', [2, 2])],
0121             ## ------- https://twiki.cern.ch/twiki/bin/viewauth/CMS/CutBasedElectronIdentificationRun2#Working_points_for_PHYS14_sample?rev=17
0122             'POG_PHYS14_25ns_v2_ConvVeto_Veto'   :  WP['POG_PHYS14_25ns_v2_Veto'  ]+[('conversionVeto', [True, True]), ('missingHits', [3, 4])],
0123             'POG_PHYS14_25ns_v2_ConvVeto_Loose'  :  WP['POG_PHYS14_25ns_v2_Loose' ]+[('conversionVeto', [True, True]), ('missingHits', [2, 2])],
0124             'POG_PHYS14_25ns_v2_ConvVeto_Medium' :  WP['POG_PHYS14_25ns_v2_Medium']+[('conversionVeto', [True, True]), ('missingHits', [2, 2])],
0125             'POG_PHYS14_25ns_v2_ConvVeto_Tight'  :  WP['POG_PHYS14_25ns_v2_Tight' ]+[('conversionVeto', [True, True]), ('missingHits', [2, 2])],
0126             ## ------- https://twiki.cern.ch/twiki/bin/view/CMS/CutBasedElectronIdentificationRun2?rev=24#Working_points_for_Spring15_MC_s
0127             'POG_SPRING15_50ns_v2_ConvVeto_Veto'   :  WP['POG_SPRING15_50ns_v2_Veto'  ]+[('conversionVeto', [True, True]), ('missingHits', [3, 4])],
0128             'POG_SPRING15_50ns_v2_ConvVeto_Loose'  :  WP['POG_SPRING15_50ns_v2_Loose' ]+[('conversionVeto', [True, True]), ('missingHits', [3, 2])],
0129             'POG_SPRING15_50ns_v2_ConvVeto_Medium' :  WP['POG_SPRING15_50ns_v2_Medium']+[('conversionVeto', [True, True]), ('missingHits', [3, 2])],
0130             'POG_SPRING15_50ns_v2_ConvVeto_Tight'  :  WP['POG_SPRING15_50ns_v2_Tight' ]+[('conversionVeto', [True, True]), ('missingHits', [3, 2])],
0131             'POG_SPRING15_25ns_v1_ConvVeto_Veto'   :  WP['POG_SPRING15_25ns_v1_Veto'  ]+[('conversionVeto', [True, True]), ('missingHits', [3, 4])],
0132             'POG_SPRING15_25ns_v1_ConvVeto_Loose'  :  WP['POG_SPRING15_25ns_v1_Loose' ]+[('conversionVeto', [True, True]), ('missingHits', [3, 2])],
0133             'POG_SPRING15_25ns_v1_ConvVeto_Medium' :  WP['POG_SPRING15_25ns_v1_Medium']+[('conversionVeto', [True, True]), ('missingHits', [3, 2])],
0134             'POG_SPRING15_25ns_v1_ConvVeto_Tight'  :  WP['POG_SPRING15_25ns_v1_Tight' ]+[('conversionVeto', [True, True]), ('missingHits', [3, 2])],
0135         }
0136 
0137         WP.update(WP_conversion_veto)
0138 
0139         WP_conversion_veto_DxyDz = {
0140             ## ------- https://twiki.cern.ch/twiki/bin/viewauth/CMS/CutBasedElectronIdentificationRun2#Working_points_for_PHYS14_sample
0141             'POG_PHYS14_25ns_v1_ConvVetoDxyDz_Veto'   :  WP['POG_PHYS14_25ns_v1_ConvVeto_Veto'  ]+[('dxy',[0.060279, 0.273097]), ('dz',[0.800538, 0.885860])],
0142             'POG_PHYS14_25ns_v1_ConvVetoDxyDz_Loose'  :  WP['POG_PHYS14_25ns_v1_ConvVeto_Loose' ]+[('dxy',[0.022664, 0.097358]), ('dz',[0.173670, 0.198444])],
0143             'POG_PHYS14_25ns_v1_ConvVetoDxyDz_Medium' :  WP['POG_PHYS14_25ns_v1_ConvVeto_Medium']+[('dxy',[0.011811, 0.051682]), ('dz',[0.070775, 0.180720])],
0144             'POG_PHYS14_25ns_v1_ConvVetoDxyDz_Tight'  :  WP['POG_PHYS14_25ns_v1_ConvVeto_Tight' ]+[('dxy',[0.009924, 0.027261]), ('dz',[0.015310, 0.147154])],
0145             ## ------- https://twiki.cern.ch/twiki/bin/viewauth/CMS/CutBasedElectronIdentificationRun2#Working_points_for_PHYS14_sample?rev=17
0146             'POG_PHYS14_25ns_v2_ConvVetoDxyDz_Veto'   :  WP['POG_PHYS14_25ns_v2_ConvVeto_Veto'  ]+[('dxy',[0.094095, 0.342293]), ('dz',[0.713070, 0.953461])],
0147             'POG_PHYS14_25ns_v2_ConvVetoDxyDz_Loose'  :  WP['POG_PHYS14_25ns_v2_ConvVeto_Loose' ]+[('dxy',[0.035904, 0.099266]), ('dz',[0.075496, 0.197897])],
0148             'POG_PHYS14_25ns_v2_ConvVetoDxyDz_Medium' :  WP['POG_PHYS14_25ns_v2_ConvVeto_Medium']+[('dxy',[0.012235, 0.036719]), ('dz',[0.042020, 0.138142])],
0149             'POG_PHYS14_25ns_v2_ConvVetoDxyDz_Tight'  :  WP['POG_PHYS14_25ns_v2_ConvVeto_Tight' ]+[('dxy',[0.008790, 0.027984]), ('dz',[0.021226, 0.133431])],
0150             ## ------- https://twiki.cern.ch/twiki/bin/view/CMS/CutBasedElectronIdentificationRun2?rev=24#Working_points_for_Spring15_MC_s
0151             'POG_SPRING15_50ns_v2_ConvVetoDxyDz_Veto'   :  WP['POG_SPRING15_50ns_v2_ConvVeto_Veto'  ]+[('dxy',[0.0621, 0.2790]), ('dz',[0.613, 0.947])],
0152             'POG_SPRING15_50ns_v2_ConvVetoDxyDz_Loose'  :  WP['POG_SPRING15_50ns_v2_ConvVeto_Loose' ]+[('dxy',[0.0227, 0.2420]), ('dz',[0.379, 0.921])],
0153             'POG_SPRING15_50ns_v2_ConvVetoDxyDz_Medium' :  WP['POG_SPRING15_50ns_v2_ConvVeto_Medium']+[('dxy',[0.0151, 0.0535]), ('dz',[0.238, 0.572])],
0154             'POG_SPRING15_50ns_v2_ConvVetoDxyDz_Tight'  :  WP['POG_SPRING15_50ns_v2_ConvVeto_Tight' ]+[('dxy',[0.0144, 0.0377]), ('dz',[0.170, 0.571])],
0155             'POG_SPRING15_25ns_v1_ConvVetoDxyDz_Veto'   :  WP['POG_SPRING15_25ns_v1_ConvVeto_Veto'  ]+[('dxy',[0.0564, 0.2220]), ('dz',[0.472, 0.921])],
0156             'POG_SPRING15_25ns_v1_ConvVetoDxyDz_Loose'  :  WP['POG_SPRING15_25ns_v1_ConvVeto_Loose' ]+[('dxy',[0.0261, 0.1180]), ('dz',[0.410, 0.822])],
0157             'POG_SPRING15_25ns_v1_ConvVetoDxyDz_Medium' :  WP['POG_SPRING15_25ns_v1_ConvVeto_Medium']+[('dxy',[0.0118, 0.0739]), ('dz',[0.373, 0.602])],
0158             'POG_SPRING15_25ns_v1_ConvVetoDxyDz_Tight'  :  WP['POG_SPRING15_25ns_v1_ConvVeto_Tight' ]+[('dxy',[0.0111, 0.0351]), ('dz',[0.0466,0.417])],
0159         }
0160 
0161         WP.update(WP_conversion_veto_DxyDz)
0162 
0163 
0164         if wp not in WP:
0165             raise RuntimeError("Working point '%s' not yet implemented in Electron.py" % wp)
0166         for (cut_name,(cut_eb,cut_ee)) in WP[wp]:
0167             if cut_name == 'conversionVeto':
0168                 if (cut_eb if self.physObj.isEB() else cut_ee) and not vars[cut_name]:
0169                     return False
0170             elif vars[cut_name] >= (cut_eb if self.physObj.isEB() else cut_ee):
0171                 return False
0172         return True
0173 
0174     def mvaId( self ):
0175         return self.mvaNonTrigV0()
0176 
0177     def tightId( self ):
0178         return self.tightIdResult
0179 
0180     def mvaNonTrigV0( self, full5x5=False, debug = False ):
0181         if self._mvaNonTrigV0[full5x5] == None:
0182             if self.associatedVertex == None: raise RuntimeError("You need to set electron.associatedVertex before calling any MVA")
0183             if self.rho              == None: raise RuntimeError("You need to set electron.rho before calling any MVA")
0184             self._mvaNonTrigV0[full5x5] = ElectronMVAID_NonTrig(self.physObj, self.associatedVertex, self.rho, full5x5, debug)
0185         return self._mvaNonTrigV0[full5x5]
0186 
0187     def mvaTrigV0( self, full5x5=False, debug = False ):
0188         if self._mvaTrigV0[full5x5] == None:
0189             if self.associatedVertex == None: raise RuntimeError("You need to set electron.associatedVertex before calling any MVA")
0190             if self.rho              == None: raise RuntimeError("You need to set electron.rho before calling any MVA")
0191             self._mvaTrigV0[full5x5] = ElectronMVAID_Trig(self.physObj, self.associatedVertex, self.rho, full5x5, debug)
0192         return self._mvaTrigV0[full5x5]
0193 
0194     def mvaTrigNoIPV0( self, full5x5=False, debug = False ):
0195         if self._mvaTrigNoIPV0[full5x5] == None:
0196             if self.associatedVertex == None: raise RuntimeError("You need to set electron.associatedVertex before calling any MVA")
0197             if self.rho              == None: raise RuntimeError("You need to set electron.rho before calling any MVA")
0198             self._mvaTrigNoIPV0[full5x5] = ElectronMVAID_TrigNoIP(self.physObj, self.associatedVertex, self.rho, full5x5, debug)
0199         return self._mvaTrigNoIPV0[full5x5]
0200 
0201     def mvaRun2( self, name, debug = False ):
0202         if name not in self._mvaRun2:
0203             if name == "NonTrigSpring15MiniAOD" and self.physObj.hasUserFloat("ElectronMVAEstimatorRun2Spring15NonTrig25nsV1Values"):
0204                 self._mvaRun2[name] =  self.physObj.userFloat("ElectronMVAEstimatorRun2Spring15NonTrig25nsV1Values")
0205                 return self._mvaRun2[name]
0206             if name not in ElectronMVAID_ByName: raise RuntimeError("Unknown electron run2 mva id %s (known ones are: %s)\n" % (name, ElectronMVAID_ByName.keys()))
0207             if self.associatedVertex == None: raise RuntimeError("You need to set electron.associatedVertex before calling any MVA")
0208             if self.rho              == None: raise RuntimeError("You need to set electron.rho before calling any MVA")
0209             # -v---- below is correct in Heppy 74X, but probably not functional anyway
0210             self._mvaRun2[name] = ElectronMVAID_ByName[name](self.physObj, self.associatedVertex, self.rho, True, debug)
0211             # -v---- below would be correct for CMGTools 74X witht the updated Spring15 MVA electron ID
0212             #if self.event            == None: raise RuntimeError, "You need to set electron.event before calling any MVA"
0213             #self._mvaRun2[name] = ElectronMVAID_ByName[name](self.physObj, self.associatedVertex, self.event, self.rho, True, debug)
0214         return self._mvaRun2[name]
0215 
0216     def mvaIDTight(self, full5x5=False):
0217         eta = abs(self.superCluster().eta())
0218         if self.pt() < 20:
0219             if   (eta < 0.8)  : return self.mvaTrigV0(full5x5) > +0.00;
0220             elif (eta < 1.479): return self.mvaTrigV0(full5x5) > +0.10;
0221             else              : return self.mvaTrigV0(full5x5) > +0.62;
0222         else:
0223             if   (eta < 0.8)  : return self.mvaTrigV0(full5x5) > +0.94;
0224             elif (eta < 1.479): return self.mvaTrigV0(full5x5) > +0.85;
0225             else              : return self.mvaTrigV0(full5x5) > +0.92;
0226 
0227     def mvaIDLoose(self, full5x5=False):
0228         eta = abs(self.superCluster().eta())
0229         if self.pt() < 10:
0230             if   (eta < 0.8)  : return self.mvaNonTrigV0(full5x5) > +0.47;
0231             elif (eta < 1.479): return self.mvaNonTrigV0(full5x5) > +0.004;
0232             else              : return self.mvaNonTrigV0(full5x5) > +0.295;
0233         else:
0234             if   (eta < 0.8)  : return self.mvaNonTrigV0(full5x5) > -0.34;
0235             elif (eta < 1.479): return self.mvaNonTrigV0(full5x5) > -0.65;
0236             else              : return self.mvaNonTrigV0(full5x5) > +0.60;
0237 
0238     def mvaIDRun2(self, name, wp):
0239         eta = abs(self.superCluster().eta())
0240         if name == "NonTrigPhys14":
0241             if wp=="Loose":
0242                 if   (eta < 0.8)  : return self.mvaRun2(name) > +0.35;
0243                 elif (eta < 1.479): return self.mvaRun2(name) > +0.20;
0244                 else              : return self.mvaRun2(name) > -0.52;
0245             elif wp=="VLoose":
0246                 if   (eta < 0.8)  : return self.mvaRun2(name) > -0.11;
0247                 elif (eta < 1.479): return self.mvaRun2(name) > -0.35;
0248                 else              : return self.mvaRun2(name) > -0.55;
0249             elif wp=="Tight":
0250                 if   (eta < 0.8)  : return self.mvaRun2(name) > 0.73;
0251                 elif (eta < 1.479): return self.mvaRun2(name) > 0.57;
0252                 else              : return self.mvaRun2(name) > 0.05;
0253             else: raise RuntimeError("Ele MVA ID Working point not found")
0254         elif name == "NonTrigPhys14Fix":
0255             if wp == "HZZ":
0256                 if self.pt() <= 10:
0257                     if   eta < 0.8  : return self.mvaRun2(name) > -0.586;
0258                     elif eta < 1.479: return self.mvaRun2(name) > -0.712;
0259                     else            : return self.mvaRun2(name) > -0.662;
0260                 else:
0261                     if   eta < 0.8  : return self.mvaRun2(name) > -0.652;
0262                     elif eta < 1.479: return self.mvaRun2(name) > -0.701;
0263                     else            : return self.mvaRun2(name) > -0.350;
0264             else: raise RuntimeError("Ele MVA ID Working point not found")
0265         elif name in ("NonTrigSpring15","NonTrigSpring15MiniAOD"):
0266             if wp=="VLoose":
0267                 if self.pt() <= 10:
0268                     if   (eta < 0.8)  : return self.mvaRun2(name) > -0.11;
0269                     elif (eta < 1.479): return self.mvaRun2(name) > -0.55;
0270                     else              : return self.mvaRun2(name) > -0.60;
0271                 else:
0272                     if   (eta < 0.8)  : return self.mvaRun2(name) > -0.16;
0273                     elif (eta < 1.479): return self.mvaRun2(name) > -0.65;
0274                     else              : return self.mvaRun2(name) > -0.74;                        
0275             elif wp=="VLooseIdEmu":
0276                 if   (eta < 0.8)  : return self.mvaRun2(name) > -0.70;
0277                 elif (eta < 1.479): return self.mvaRun2(name) > -0.83;
0278                 else              : return self.mvaRun2(name) > -0.92;
0279             elif wp=="VLooseIdIsoEmu":
0280                 if   (eta < 0.8)  : return self.mvaRun2(name) > -0.155;
0281                 elif (eta < 1.479): return self.mvaRun2(name) > -0.56;
0282                 else              : return self.mvaRun2(name) > -0.76;
0283             elif wp=="Tight":
0284                 if   (eta < 0.8)  : return self.mvaRun2(name) > 0.87;
0285                 elif (eta < 1.479): return self.mvaRun2(name) > 0.60;
0286                 else              : return self.mvaRun2(name) > 0.17;
0287             elif wp == "HZZ":
0288                 if self.pt() <= 10:
0289                     if   eta < 0.8  : return self.mvaRun2(name) > -0.265;
0290                     elif eta < 1.479: return self.mvaRun2(name) > -0.556;
0291                     else            : return self.mvaRun2(name) > -0.551;
0292                 else:
0293                     if   eta < 0.8  : return self.mvaRun2(name) > -0.072;
0294                     elif eta < 1.479: return self.mvaRun2(name) > -0.286;
0295                     else            : return self.mvaRun2(name) > -0.267;
0296             elif wp == "POG80":
0297                 if self.pt() > 10.:
0298                     if eta < 0.8: return self.mvaRun2(name) > 0.967083
0299                     elif eta < 1.479: return self.mvaRun2(name) > 0.929117
0300                     else: return self.mvaRun2(name) > 0.726311
0301                 else: # pt <= 10
0302                     if eta < 0.8: return self.mvaRun2(name) > 0.287435
0303                     elif eta < 1.479: return self.mvaRun2(name) > 0.221846
0304                     else: return self.mvaRun2(name) > -0.303263
0305             elif wp == "POG90":
0306                 if self.pt() > 10.:
0307                     if eta < 0.8: return self.mvaRun2(name) > 0.913286
0308                     elif eta < 1.479: return self.mvaRun2(name) > 0.805013
0309                     else: return self.mvaRun2(name) > 0.358969
0310                 else: # pt <= 10
0311                     if eta < 0.8: return self.mvaRun2(name) > -0.083313
0312                     elif eta < 1.479: return self.mvaRun2(name) > -0.235222
0313                     else: return self.mvaRun2(name) > -0.67099
0314             else: raise RuntimeError("Ele MVA ID Working point not found")
0315         else: raise RuntimeError("Ele MVA ID type not found")
0316 
0317 
0318 
0319     def chargedHadronIsoR(self,R=0.4):
0320         if   R == 0.3: return self.physObj.pfIsolationVariables().sumChargedHadronPt
0321         elif R == 0.4: return self.physObj.chargedHadronIso()
0322         raise RuntimeError("Electron chargedHadronIso missing for R=%s" % R)
0323 
0324     def neutralHadronIsoR(self,R=0.4):
0325         if   R == 0.3: return self.physObj.pfIsolationVariables().sumNeutralHadronEt
0326         elif R == 0.4: return self.physObj.neutralHadronIso()
0327         raise RuntimeError("Electron neutralHadronIso missing for R=%s" % R)
0328 
0329     def photonIsoR(self,R=0.4):
0330         if   R == 0.3: return self.physObj.pfIsolationVariables().sumPhotonEt
0331         elif R == 0.4: return self.physObj.photonIso()
0332         raise RuntimeError("Electron photonIso missing for R=%s" % R)
0333 
0334     def chargedAllIsoR(self,R=0.4):
0335         if   R == 0.3: return self.physObj.pfIsolationVariables().sumChargedParticlePt
0336         raise RuntimeError("Electron chargedAllIso missing for R=%s" % R)
0337 
0338     def chargedAllIso(self):
0339         raise RuntimeError("Electron chargedAllIso missing")
0340 
0341     def puChargedHadronIsoR(self,R=0.4):
0342         if   R == 0.3: return self.physObj.pfIsolationVariables().sumPUPt
0343         elif R == 0.4: return self.physObj.puChargedHadronIso()
0344         raise RuntimeError("Electron chargedHadronIso missing for R=%s" % R)
0345 
0346 
0347     def absIsoWithFSR(self, R=0.4, puCorr="rhoArea", dBetaFactor=0.5):
0348         '''
0349         Calculate Isolation, subtract FSR, apply specific PU corrections" 
0350         '''
0351         photonIso = self.photonIsoR(R)
0352         if hasattr(self,'fsrPhotons'):
0353             for gamma in self.fsrPhotons:
0354                 dr = deltaR(gamma.eta(), gamma.phi(), self.physObj.eta(), self.physObj.phi())
0355                 if (self.isEB() or dr > 0.08) and dr < R:
0356                     photonIso = max(photonIso-gamma.pt(),0.0)                
0357         if puCorr == "deltaBeta":
0358             offset = dBetaFactor * self.puChargedHadronIsoR(R)
0359         elif puCorr == "rhoArea":
0360             offset = self.rho*getattr(self,"EffectiveArea"+(str(R).replace(".","")))
0361         elif puCorr in ["none","None",None]:
0362             offset = 0
0363         else:
0364             raise RuntimeError("Unsupported PU correction scheme %s" % puCorr)
0365         return self.chargedHadronIsoR(R)+max(0.,photonIso+self.neutralHadronIsoR(R)-offset)            
0366 
0367 
0368     def dxy(self, vertex=None):
0369         '''Returns dxy.
0370         Computed using vertex (or self.associatedVertex if vertex not specified),
0371         and the gsf track.
0372         '''
0373         if vertex is None:
0374             vertex = self.associatedVertex
0375         return self.gsfTrack().dxy( vertex.position() )
0376 
0377     def edxy(self):
0378         '''returns the uncertainty on dxy (from gsf track)'''
0379         return self.gsfTrack().dxyError()
0380 
0381     def p4(self):
0382         return ROOT.reco.Candidate.p4(self.physObj)
0383 
0384 #    def p4(self):
0385 #        return self.physObj.p4(self.physObj.candidateP4Kind()) # if kind == None else kind)
0386 
0387     def dz(self, vertex=None):
0388         '''Returns dz.
0389         Computed using vertex (or self.associatedVertex if vertex not specified),
0390         and the gsf track.
0391         '''
0392         if vertex is None:
0393             vertex = self.associatedVertex
0394         return self.gsfTrack().dz( vertex.position() )
0395 
0396     def edz(self):
0397         '''returns the uncertainty on dxz (from gsf track)'''
0398         return self.gsfTrack().dzError()
0399 
0400 
0401     def lostInner(self) :
0402         if hasattr(self.gsfTrack(),"trackerExpectedHitsInner") :
0403             return self.gsfTrack().trackerExpectedHitsInner().numberOfLostHits()
0404         else :
0405             return self.gsfTrack().hitPattern().numberOfLostHits(ROOT.reco.HitPattern.MISSING_INNER_HITS)
0406 
0407     def validCandidateP4Kind(self):
0408         raw = self.physObj.candidateP4Kind()
0409         return raw in (0,1,2) 
0410 
0411     def ptErr(self):
0412         return self.p4Error(self.candidateP4Kind())*self.pt()/self.p() if self.validCandidateP4Kind() else None
0413