1 |
bbetchar |
1.1 |
import operator,sys,os
|
2 |
|
|
from FWCore.ParameterSet import Config as cms
|
3 |
|
|
from PhysicsTools.PatAlgos.tools import coreTools,pfTools
|
4 |
|
|
|
5 |
|
|
def tags(stuff) :
|
6 |
|
|
return ( cms.InputTag(stuff) if type(stuff)!=list else
|
7 |
|
|
cms.VInputTag([tags(item) for item in stuff]) )
|
8 |
|
|
|
9 |
|
|
class TopRefPF2PAT(object) :
|
10 |
|
|
'''Implement the Top Reference configuration of PF2PAT.
|
11 |
|
|
|
12 |
|
|
https://twiki.cern.ch/twiki/bin/viewauth/CMS/TWikiTopRefEventSel
|
13 |
bbetchar |
1.2 |
Modify the PF selections to match the PAT selections, for consistent TopProjection cross-cleaning.
|
14 |
bbetchar |
1.1 |
'''
|
15 |
|
|
|
16 |
|
|
def __init__(self, process, options) :
|
17 |
|
|
self.stdout = sys.stdout
|
18 |
|
|
sys.stdout = open(os.devnull, 'w')
|
19 |
bbetchar |
1.2 |
print >>self.stdout, "usePF2PAT() output suppressed. (%s)"%__file__
|
20 |
bbetchar |
1.1 |
|
21 |
|
|
self.before = set(dir(process))
|
22 |
|
|
process.load( "PhysicsTools.PatAlgos.patSequences_cff" )
|
23 |
|
|
pfTools.usePF2PAT( process,
|
24 |
|
|
runPF2PAT = True,
|
25 |
|
|
postfix = options.postfix,
|
26 |
|
|
runOnMC = not options.isData,
|
27 |
|
|
pvCollection = tags( 'goodOfflinePrimaryVertices' ),
|
28 |
|
|
typeIMetCorrections = True,
|
29 |
|
|
jetAlgo = 'AK5',
|
30 |
|
|
jetCorrections = ('AK5PFchs', ['L1FastJet','L2Relative','L3Absolute','L2L3Residual'][:None if options.isData else -1] )
|
31 |
|
|
)
|
32 |
bbetchar |
1.8 |
|
33 |
bbetchar |
1.7 |
getattr( process, 'pfPileUp'+options.postfix).checkClosestZVertex = False # https://twiki.cern.ch/twiki/bin/view/CMSPublic/WorkBookJetEnergyCorrections#JetEnCorPFnoPU2012
|
34 |
bbetchar |
1.1 |
getattr( process, 'pfPileUpIso'+options.postfix).checkClosestZVertex = True
|
35 |
bbetchar |
1.8 |
getattr( process, 'patJetCorrFactors'+options.postfix).flavorType = 'T' # top events, not dijets, but only relevant for L5Flavor,L7Parton
|
36 |
|
|
#getattr( process, 'patJetCorrFactors'+options.postfix).levels.append('L5Flavor') # apparently not available in GlobalTags
|
37 |
bbetchar |
1.1 |
if options.isData: coreTools.runOnData( process, names = [ 'PFAll' ], postfix = options.postfix )
|
38 |
|
|
coreTools.removeSpecificPATObjects( process, names = [ 'Photons', 'Taus' ], postfix = options.postfix )
|
39 |
|
|
|
40 |
bbetchar |
1.2 |
self.isoValues = {'el':0.15,'mu':0.20}
|
41 |
|
|
self.eleID = 'mvaTrigV0'
|
42 |
|
|
self.minEleID = 0.
|
43 |
|
|
self.dBFactor = -0.5
|
44 |
bbetchar |
1.3 |
self.cuts = {'el': ['abs(eta)<2.5',
|
45 |
|
|
'pt>20.',
|
46 |
bbetchar |
1.2 |
'gsfTrackRef.isNonnull',
|
47 |
|
|
'gsfTrackRef.trackerExpectedHitsInner.numberOfLostHits<2',
|
48 |
bbetchar |
1.4 |
'(chargedHadronIso+max(0.,neutralHadronIso+photonIso%+f*puChargedHadronIso))/pt < %f'%(self.dBFactor, self.isoValues['el']),
|
49 |
bbetchar |
1.2 |
'electronID("%s") > %f'%(self.eleID,self.minEleID),
|
50 |
|
|
],
|
51 |
bbetchar |
1.3 |
'mu' :['abs(eta)<2.5',
|
52 |
|
|
'pt>10.',
|
53 |
bbetchar |
1.2 |
'(chargedHadronIso+neutralHadronIso+photonIso%+f*puChargedHadronIso)/pt < %f'%(self.dBFactor, self.isoValues['mu']),
|
54 |
bbetchar |
1.3 |
'(isPFMuon && (isGlobalMuon || isTrackerMuon) )',
|
55 |
bbetchar |
1.2 |
],
|
56 |
bbetchar |
1.3 |
'jet' : ['abs(eta)<2.5', # Careful! these jet cuts affect the typeI met corrections
|
57 |
bbetchar |
1.2 |
'pt > 15.',
|
58 |
|
|
# PF jet ID:
|
59 |
|
|
'numberOfDaughters > 1',
|
60 |
|
|
'neutralHadronEnergyFraction < 0.99',
|
61 |
|
|
'neutralEmEnergyFraction < 0.99',
|
62 |
|
|
'(chargedEmEnergyFraction < 0.99 || abs(eta) >= 2.4)',
|
63 |
|
|
'(chargedHadronEnergyFraction > 0. || abs(eta) >= 2.4)',
|
64 |
|
|
'(chargedMultiplicity > 0 || abs(eta) >= 2.4)']
|
65 |
|
|
}
|
66 |
|
|
|
67 |
bbetchar |
1.1 |
self.process = process
|
68 |
|
|
self.options = options
|
69 |
|
|
self.fix = options.postfix
|
70 |
|
|
self.patSeq = getattr(process, 'patPF2PATSequence' + self.fix)
|
71 |
bbetchar |
1.6 |
self.btags = self.options.btags
|
72 |
bbetchar |
1.1 |
self.taginfos = ["impactParameter","secondaryVertex"]
|
73 |
|
|
|
74 |
|
|
self.configTopProjections()
|
75 |
|
|
self.configPfLepton('el', iso3 = True)
|
76 |
|
|
self.configPfLepton('mu', iso3 = False)
|
77 |
|
|
self.configPatMuons()
|
78 |
|
|
self.configPatElectrons()
|
79 |
|
|
self.configPatJets()
|
80 |
bbetchar |
1.2 |
self.configLeptonFilter()
|
81 |
bbetchar |
1.1 |
self.removeCruft()
|
82 |
|
|
sys.stdout = self.stdout
|
83 |
|
|
|
84 |
|
|
def attr(self, item) : return getattr(self.process, item)
|
85 |
bbetchar |
1.2 |
def show(self, item) : print >> (sys.stdout if self.options.quiet else self.stdout), item, '=', self.attr(item).dumpPython() if hasattr(self.process, item) else 'Not Found.'
|
86 |
bbetchar |
1.1 |
|
87 |
|
|
def configTopProjections(self) :
|
88 |
|
|
'''Enable TopProjections except for Taus (do not remove tau cands from jet collection).'''
|
89 |
|
|
|
90 |
|
|
for key,val in {'PileUp':1,'Muon':1,'Electron':1,'Jet':1,'Tau':0}.items() :
|
91 |
|
|
self.attr('pfNo'+key+self.fix).enable = bool(val)
|
92 |
bbetchar |
1.2 |
self.attr('pfNoElectron').verbose = True
|
93 |
bbetchar |
1.1 |
return
|
94 |
|
|
|
95 |
|
|
def configPfLepton(self, lep, iso3) :
|
96 |
|
|
full = {'el':'Electrons','mu':'Muons'}[lep] + self.fix
|
97 |
|
|
iso = self.attr('pfIsolated'+full)
|
98 |
bbetchar |
1.2 |
iso.isolationCut = self.isoValues[lep]
|
99 |
bbetchar |
1.1 |
iso.doDeltaBetaCorrection = True
|
100 |
bbetchar |
1.2 |
iso.deltaBetaFactor = self.dBFactor
|
101 |
|
|
sel = self.attr('pfSelected'+full)
|
102 |
|
|
sel.cut = ' && '.join(self.cuts[lep][:-2])
|
103 |
|
|
print >>self.stdout, ""
|
104 |
|
|
if lep == 'el' :
|
105 |
|
|
idName = 'pfIdentifiedElectrons'+self.fix
|
106 |
|
|
id = cms.EDFilter("ElectronIDPFCandidateSelector",
|
107 |
|
|
src = cms.InputTag('pfElectronsFromVertex'+self.fix),
|
108 |
|
|
recoGsfElectrons = cms.InputTag("gsfElectrons"),
|
109 |
|
|
electronIdMap = cms.InputTag(self.eleID),
|
110 |
|
|
electronIdCut = cms.double(self.minEleID))
|
111 |
|
|
setattr(self.process, idName, id )
|
112 |
|
|
self.patSeq.replace( sel, id*sel)
|
113 |
|
|
sel.src = idName
|
114 |
|
|
self.show(idName)
|
115 |
|
|
|
116 |
bbetchar |
1.1 |
if iso3:
|
117 |
|
|
pf = {'el':'PFId','mu':''}[lep] + self.fix
|
118 |
|
|
for item in ['pf','pfIsolated'] :
|
119 |
|
|
col = self.attr( item+full )
|
120 |
|
|
col.deltaBetaIsolationValueMap = tags( lep+'PFIsoValuePU03'+pf )
|
121 |
|
|
col.isolationValueMapsCharged = tags( [lep+'PFIsoValueCharged03'+pf] )
|
122 |
|
|
col.isolationValueMapsNeutral = tags( [ lep+'PFIsoValueNeutral03'+pf, lep+'PFIsoValueGamma03'+pf] )
|
123 |
|
|
val = self.attr( 'pat'+full ).isolationValues
|
124 |
|
|
val.pfNeutralHadrons = tags( lep+'PFIsoValueNeutral03' + pf )
|
125 |
|
|
val.pfChargedAll = tags( lep+'PFIsoValueChargedAll03' + pf )
|
126 |
|
|
val.pfPUChargedHadrons = tags( lep+'PFIsoValuePU03' + pf )
|
127 |
|
|
val.pfPhotons = tags( lep+'PFIsoValueGamma03' + pf )
|
128 |
|
|
val.pfChargedHadrons = tags( lep+'PFIsoValueCharged03' + pf )
|
129 |
bbetchar |
1.2 |
|
130 |
|
|
self.show('pfSelected'+full)
|
131 |
|
|
self.show('pfIsolated'+full)
|
132 |
bbetchar |
1.1 |
return
|
133 |
|
|
|
134 |
|
|
def configPatMuons(self) :
|
135 |
|
|
for mod,attr,val in [('patMuons','usePV',False), # use beam spot rather than PV, which is necessary for 'dB' cut
|
136 |
|
|
('patMuons','embedTrack',True), # embedded track needed for muon ID cuts
|
137 |
bbetchar |
1.2 |
('selectedPatMuons','cut', ' && '.join(self.cuts['mu'])),
|
138 |
bbetchar |
1.1 |
] : setattr( self.attr(mod+self.fix), attr, val )
|
139 |
|
|
self.show('selectedPatMuons'+self.fix)
|
140 |
|
|
return
|
141 |
|
|
|
142 |
|
|
def configPatElectrons(self) :
|
143 |
bbetchar |
1.2 |
electronIDSources = cms.PSet(**dict([(i,tags(i)) for i in [self.eleID]]))
|
144 |
|
|
for mod,attr,val in [('patElectrons','electronIDSources', electronIDSources),
|
145 |
|
|
('selectedPatElectrons','cut', ' && '.join(c for c in self.cuts['el'] if 'gsfTrackRef' not in c)),
|
146 |
bbetchar |
1.1 |
] : setattr( self.attr( mod+self.fix), attr, val )
|
147 |
|
|
self.show('selectedPatElectrons'+self.fix)
|
148 |
|
|
return
|
149 |
|
|
|
150 |
|
|
def configPatJets(self) :
|
151 |
|
|
for mod,attr,val in [('patJets','discriminatorSources',[tags(tag+'BJetTagsAOD'+self.fix) for tag in self.btags]),
|
152 |
|
|
('patJets','tagInfoSources',[tags(tag+'TagInfosAOD'+self.fix) for tag in self.taginfos]),
|
153 |
|
|
('patJets','addTagInfos',True),
|
154 |
bbetchar |
1.2 |
('selectedPatJets','cut', ' && '.join(self.cuts['jet'])),
|
155 |
bbetchar |
1.1 |
] : setattr( self.attr(mod+self.fix), attr, val )
|
156 |
|
|
self.show('selectedPatJets'+self.fix)
|
157 |
|
|
return
|
158 |
|
|
|
159 |
bbetchar |
1.2 |
def configLeptonFilter(self) :
|
160 |
|
|
if not self.options.requireLepton : return
|
161 |
bbetchar |
1.5 |
muons20Name = 'pfIsolatedMuons20'+self.fix
|
162 |
bbetchar |
1.2 |
leptonsName = 'pfLeptons'+self.fix
|
163 |
|
|
requireLeptonName = 'requireLepton'+self.fix
|
164 |
bbetchar |
1.5 |
|
165 |
|
|
muons20 = cms.EDFilter("GenericPFCandidateSelector", src = tags('pfIsolatedMuons'+self.fix), cut = cms.string('pt>20 && abs(eta) < 2.4'))
|
166 |
|
|
leptons = cms.EDProducer("CandViewMerger", src = tags(['pfIsolated%s%s'%(lep,self.fix) for lep in ['Electrons','Muons20']]))
|
167 |
bbetchar |
1.2 |
requireLepton = cms.EDFilter("CandViewCountFilter", src = tags(leptonsName), minNumber = cms.uint32(1) )
|
168 |
bbetchar |
1.5 |
|
169 |
|
|
setattr(self.process, muons20Name, muons20)
|
170 |
bbetchar |
1.2 |
setattr(self.process, leptonsName, leptons)
|
171 |
|
|
setattr(self.process, requireLeptonName, requireLepton)
|
172 |
|
|
|
173 |
|
|
jets = self.attr('pfJets'+self.fix)
|
174 |
bbetchar |
1.5 |
self.patSeq.replace(jets, muons20*leptons*requireLepton*jets)
|
175 |
|
|
|
176 |
|
|
self.show(muons20Name)
|
177 |
bbetchar |
1.2 |
self.show(leptonsName)
|
178 |
|
|
self.show(requireLeptonName)
|
179 |
|
|
return
|
180 |
bbetchar |
1.1 |
|
181 |
|
|
def removeCruft(self) :
|
182 |
|
|
nothanks = [mod for mod in set(str(self.patSeq).split('+'))
|
183 |
|
|
if ( any( keyword in mod for keyword in ['count','Legacy','pfJetsPiZeros','ak7','soft','iterativeCone',
|
184 |
|
|
'tauIsoDeposit','tauGenJet','hpsPFTau','tauMatch','pfTau','hpsSelection',
|
185 |
|
|
'photonMatch','phPFIso','pfIsolatedPhotons','pfCandsNotInJet','pfCandMETcorr',
|
186 |
|
|
'Negative','ToVertex','particleFlowDisplacedVertex',
|
187 |
|
|
'ype2Corr','ype0','patType1p2CorrectedPFMet','atCandidateSummaryTR','atPFParticles'] ) or
|
188 |
|
|
( 'JetTagsAOD' in mod and not any( (btag+'B') in mod for btag in self.btags ) ) or
|
189 |
|
|
( 'TagInfosAOD' in mod and not any( (info+'TagInfosAOD') in mod for info in self.taginfos ) ) or
|
190 |
|
|
( 'elPFIsoValue' in mod and ('04' in mod or 'NoPFId' in mod ) ) or
|
191 |
|
|
( 'muPFIsoValue' in mod and ('03' in mod))) ]
|
192 |
|
|
for mod in nothanks : self.patSeq.remove( self.attr(mod) )
|
193 |
|
|
|
194 |
|
|
nothanks = ['ic5','kt4','kt6','JPT','ak7','ak5Calo']
|
195 |
|
|
now = set(dir(self.process))
|
196 |
|
|
for item in now - self.before - set(str(self.patSeq).split('+')) :
|
197 |
|
|
if any(part in item for part in nothanks) :
|
198 |
|
|
delattr(self.process,item)
|
199 |
|
|
return
|