ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/Betchart/TopRefTuple/python/pf2pat.py
Revision: 1.8
Committed: Thu Nov 15 05:09:24 2012 UTC (12 years, 5 months ago) by bbetchar
Content type: text/x-python
Branch: MAIN
CVS Tags: V00-01-05, V00-01-04, V00-01-03, V00-01-02, V00-01-01, V00-01-00
Changes since 1.7: +3 -0 lines
Log Message:
patJetCorrFactors

File Contents

# Content
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 Modify the PF selections to match the PAT selections, for consistent TopProjection cross-cleaning.
14 '''
15
16 def __init__(self, process, options) :
17 self.stdout = sys.stdout
18 sys.stdout = open(os.devnull, 'w')
19 print >>self.stdout, "usePF2PAT() output suppressed. (%s)"%__file__
20
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
33 getattr( process, 'pfPileUp'+options.postfix).checkClosestZVertex = False # https://twiki.cern.ch/twiki/bin/view/CMSPublic/WorkBookJetEnergyCorrections#JetEnCorPFnoPU2012
34 getattr( process, 'pfPileUpIso'+options.postfix).checkClosestZVertex = True
35 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 if options.isData: coreTools.runOnData( process, names = [ 'PFAll' ], postfix = options.postfix )
38 coreTools.removeSpecificPATObjects( process, names = [ 'Photons', 'Taus' ], postfix = options.postfix )
39
40 self.isoValues = {'el':0.15,'mu':0.20}
41 self.eleID = 'mvaTrigV0'
42 self.minEleID = 0.
43 self.dBFactor = -0.5
44 self.cuts = {'el': ['abs(eta)<2.5',
45 'pt>20.',
46 'gsfTrackRef.isNonnull',
47 'gsfTrackRef.trackerExpectedHitsInner.numberOfLostHits<2',
48 '(chargedHadronIso+max(0.,neutralHadronIso+photonIso%+f*puChargedHadronIso))/pt < %f'%(self.dBFactor, self.isoValues['el']),
49 'electronID("%s") > %f'%(self.eleID,self.minEleID),
50 ],
51 'mu' :['abs(eta)<2.5',
52 'pt>10.',
53 '(chargedHadronIso+neutralHadronIso+photonIso%+f*puChargedHadronIso)/pt < %f'%(self.dBFactor, self.isoValues['mu']),
54 '(isPFMuon && (isGlobalMuon || isTrackerMuon) )',
55 ],
56 'jet' : ['abs(eta)<2.5', # Careful! these jet cuts affect the typeI met corrections
57 '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 self.process = process
68 self.options = options
69 self.fix = options.postfix
70 self.patSeq = getattr(process, 'patPF2PATSequence' + self.fix)
71 self.btags = self.options.btags
72 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 self.configLeptonFilter()
81 self.removeCruft()
82 sys.stdout = self.stdout
83
84 def attr(self, item) : return getattr(self.process, item)
85 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
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 self.attr('pfNoElectron').verbose = True
93 return
94
95 def configPfLepton(self, lep, iso3) :
96 full = {'el':'Electrons','mu':'Muons'}[lep] + self.fix
97 iso = self.attr('pfIsolated'+full)
98 iso.isolationCut = self.isoValues[lep]
99 iso.doDeltaBetaCorrection = True
100 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 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
130 self.show('pfSelected'+full)
131 self.show('pfIsolated'+full)
132 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 ('selectedPatMuons','cut', ' && '.join(self.cuts['mu'])),
138 ] : setattr( self.attr(mod+self.fix), attr, val )
139 self.show('selectedPatMuons'+self.fix)
140 return
141
142 def configPatElectrons(self) :
143 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 ] : 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 ('selectedPatJets','cut', ' && '.join(self.cuts['jet'])),
155 ] : setattr( self.attr(mod+self.fix), attr, val )
156 self.show('selectedPatJets'+self.fix)
157 return
158
159 def configLeptonFilter(self) :
160 if not self.options.requireLepton : return
161 muons20Name = 'pfIsolatedMuons20'+self.fix
162 leptonsName = 'pfLeptons'+self.fix
163 requireLeptonName = 'requireLepton'+self.fix
164
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 requireLepton = cms.EDFilter("CandViewCountFilter", src = tags(leptonsName), minNumber = cms.uint32(1) )
168
169 setattr(self.process, muons20Name, muons20)
170 setattr(self.process, leptonsName, leptons)
171 setattr(self.process, requireLeptonName, requireLepton)
172
173 jets = self.attr('pfJets'+self.fix)
174 self.patSeq.replace(jets, muons20*leptons*requireLepton*jets)
175
176 self.show(muons20Name)
177 self.show(leptonsName)
178 self.show(requireLeptonName)
179 return
180
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