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." |
19 |
> |
print >>self.stdout, "usePF2PAT() output suppressed. (%s)"%__file__ |
20 |
|
|
21 |
|
self.before = set(dir(process)) |
22 |
|
process.load( "PhysicsTools.PatAlgos.patSequences_cff" ) |
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.isoEA = 'elPFIsoValueEA03' |
44 |
+ |
self.dBFactorEl = -1.0 if options.doElectronEA else -0.5 |
45 |
+ |
self.dBFactorMu = -0.5 |
46 |
+ |
self.cuts = {'el': ['abs(eta)<2.5', |
47 |
+ |
'pt>20.', |
48 |
+ |
'gsfTrackRef.isNonnull', |
49 |
+ |
'gsfTrackRef.trackerExpectedHitsInner.numberOfLostHits<2', |
50 |
+ |
'(chargedHadronIso+max(0.,neutralHadronIso+photonIso%+.1f*%s))/pt < %.2f'%(self.dBFactorEl, 'userIsolation("User1Iso")' if options.doElectronEA else 'puChargedHadronIso',self.isoValues['el']), |
51 |
+ |
'electronID("%s") > %.2f'%(self.eleID,self.minEleID), |
52 |
+ |
], |
53 |
+ |
'mu' :['abs(eta)<2.5', |
54 |
+ |
'pt>10.', |
55 |
+ |
'(chargedHadronIso+neutralHadronIso+photonIso%+.2f*puChargedHadronIso)/pt < %.2f'%(self.dBFactorMu, self.isoValues['mu']), |
56 |
+ |
'(isPFMuon && (isGlobalMuon || isTrackerMuon) )', |
57 |
+ |
], |
58 |
+ |
'jet' : ['abs(eta)<2.5', # Careful! these jet cuts affect the typeI met corrections |
59 |
+ |
'pt > 15.', |
60 |
+ |
# PF jet ID: |
61 |
+ |
'numberOfDaughters > 1', |
62 |
+ |
'neutralHadronEnergyFraction < 0.99', |
63 |
+ |
'neutralEmEnergyFraction < 0.99', |
64 |
+ |
'(chargedEmEnergyFraction < 0.99 || abs(eta) >= 2.4)', |
65 |
+ |
'(chargedHadronEnergyFraction > 0. || abs(eta) >= 2.4)', |
66 |
+ |
'(chargedMultiplicity > 0 || abs(eta) >= 2.4)'] |
67 |
+ |
} |
68 |
+ |
|
69 |
|
self.process = process |
70 |
|
self.options = options |
71 |
|
self.fix = options.postfix |
72 |
|
self.patSeq = getattr(process, 'patPF2PATSequence' + self.fix) |
73 |
< |
self.btags = ['combinedSecondaryVertex','jetProbability'] |
73 |
> |
self.btags = self.options.btags |
74 |
|
self.taginfos = ["impactParameter","secondaryVertex"] |
75 |
|
|
76 |
|
self.configTopProjections() |
79 |
|
self.configPatMuons() |
80 |
|
self.configPatElectrons() |
81 |
|
self.configPatJets() |
82 |
+ |
self.configLeptonFilter() |
83 |
|
self.removeCruft() |
84 |
|
sys.stdout = self.stdout |
85 |
|
|
86 |
|
def attr(self, item) : return getattr(self.process, item) |
87 |
< |
def show(self, item) : print >>self.stdout, item, '=', self.attr(item).dumpPython() |
87 |
> |
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.' |
88 |
|
|
89 |
|
def configTopProjections(self) : |
90 |
|
'''Enable TopProjections except for Taus (do not remove tau cands from jet collection).''' |
91 |
|
|
92 |
|
for key,val in {'PileUp':1,'Muon':1,'Electron':1,'Jet':1,'Tau':0}.items() : |
93 |
|
self.attr('pfNo'+key+self.fix).enable = bool(val) |
94 |
< |
|
60 |
< |
for lep in ['Muon','Electron'] : |
61 |
< |
sub = (lep,self.fix) |
62 |
< |
pfNo = self.attr('pfNo%s%s'%sub) |
63 |
< |
pfNo.topCollection = 'selectedPat%ss%s'%sub |
64 |
< |
mods = [ self.attr( item) for item in [ lep.lower() + 'Match'+self.fix, |
65 |
< |
'pat%ss%s'%sub, |
66 |
< |
'selectedPat%ss%s'%sub]][int(self.options.isData):] |
67 |
< |
for mod in mods : self.patSeq.remove(mod) |
68 |
< |
self.patSeq.replace( pfNo, reduce(operator.mul, mods) * pfNo ) |
69 |
< |
pfNo.verbose = True |
70 |
< |
self.show('pfNo%s%s'%sub) |
94 |
> |
self.attr('pfNoElectron').verbose = True |
95 |
|
return |
96 |
|
|
97 |
|
def configPfLepton(self, lep, iso3) : |
98 |
|
full = {'el':'Electrons','mu':'Muons'}[lep] + self.fix |
99 |
|
iso = self.attr('pfIsolated'+full) |
100 |
< |
iso.isolationCut = 0.2 |
100 |
> |
iso.isolationCut = self.isoValues[lep] |
101 |
|
iso.doDeltaBetaCorrection = True |
102 |
< |
iso.deltaBetaFactor = -0.5 |
102 |
> |
iso.deltaBetaFactor = getattr(self, 'dBFactor' + full[:2]) |
103 |
> |
sel = self.attr('pfSelected'+full) |
104 |
> |
sel.cut = ' && '.join(self.cuts[lep][:-2]) |
105 |
> |
isoEA = getattr(self.process, self.isoEA) |
106 |
> |
print >>self.stdout, "" |
107 |
> |
if lep == 'el' : |
108 |
> |
idName = 'pfIdentifiedElectrons'+self.fix |
109 |
> |
id = cms.EDFilter("ElectronIDPFCandidateSelector", |
110 |
> |
src = cms.InputTag('pfElectronsFromVertex'+self.fix), |
111 |
> |
recoGsfElectrons = cms.InputTag("gsfElectrons"), |
112 |
> |
electronIdMap = cms.InputTag(self.eleID), |
113 |
> |
electronIdCut = cms.double(self.minEleID)) |
114 |
> |
setattr(self.process, idName, id ) |
115 |
> |
self.patSeq.replace( sel, id*sel*isoEA) |
116 |
> |
sel.src = idName |
117 |
> |
isoEA.pfElectrons = 'pfSelectedElectrons'+self.fix |
118 |
> |
if not iso3 : isoEA.EffectiveAreaType = "kEleGammaAndNeutralHadronIso04" |
119 |
> |
self.show(idName) |
120 |
> |
|
121 |
|
if iso3: |
122 |
|
pf = {'el':'PFId','mu':''}[lep] + self.fix |
123 |
|
for item in ['pf','pfIsolated'] : |
131 |
|
val.pfPUChargedHadrons = tags( lep+'PFIsoValuePU03' + pf ) |
132 |
|
val.pfPhotons = tags( lep+'PFIsoValueGamma03' + pf ) |
133 |
|
val.pfChargedHadrons = tags( lep+'PFIsoValueCharged03' + pf ) |
134 |
+ |
|
135 |
+ |
if lep == 'el' and self.options.doElectronEA : |
136 |
+ |
self.attr( 'pfIsolated' + full).deltaBetaIsolationValueMap = self.isoEA |
137 |
+ |
|
138 |
+ |
self.show('pfSelected'+full) |
139 |
+ |
self.show('pfIsolated'+full) |
140 |
|
return |
141 |
|
|
142 |
|
def configPatMuons(self) : |
95 |
– |
muonCuts = ['isPFMuon', # general reconstruction property |
96 |
– |
'(isGlobalMuon || isTrackerMuon)', # general reconstruction property |
97 |
– |
'pt > 10.', # transverse momentum |
98 |
– |
'abs(eta) < 2.5', # pseudo-rapisity range |
99 |
– |
'(chargedHadronIso+neutralHadronIso+photonIso-0.5*puChargedHadronIso)/pt < 0.20']# relative isolation w/ Delta beta corrections (factor 0.5) |
100 |
– |
|
143 |
|
for mod,attr,val in [('patMuons','usePV',False), # use beam spot rather than PV, which is necessary for 'dB' cut |
144 |
|
('patMuons','embedTrack',True), # embedded track needed for muon ID cuts |
145 |
< |
('selectedPatMuons','cut', ' && '.join(muonCuts)), |
145 |
> |
('selectedPatMuons','cut', ' && '.join(self.cuts['mu'])), |
146 |
|
] : setattr( self.attr(mod+self.fix), attr, val ) |
147 |
|
self.show('selectedPatMuons'+self.fix) |
148 |
|
return |
149 |
|
|
150 |
|
def configPatElectrons(self) : |
151 |
< |
electronIDSources = cms.PSet(**dict([(i,tags(i)) for i in ['mvaTrigV0','mvaNonTrigV0']])) |
152 |
< |
electronCuts = ['pt > 20.', # transverse energy |
153 |
< |
'abs(eta) < 2.5', # pseudo-rapidity range |
112 |
< |
'electronID("mvaTrigV0") > 0.', # MVA electrons ID |
113 |
< |
'(chargedHadronIso+max(0.,neutralHadronIso)+photonIso-0.5*puChargedHadronIso)/et < 0.15']# relative isolation with Delta beta corrections |
114 |
< |
|
115 |
< |
for mod,attr,val in [('patElectrons','electronIDSources',electronIDSources), |
116 |
< |
('selectedPatElectrons','cut', ' && '.join(electronCuts)), |
151 |
> |
electronIDSources = cms.PSet(**dict([(i,tags(i)) for i in [self.eleID]])) |
152 |
> |
for mod,attr,val in [('patElectrons','electronIDSources', electronIDSources), |
153 |
> |
('selectedPatElectrons','cut', ' && '.join(c for c in self.cuts['el'] if 'gsfTrackRef' not in c)), |
154 |
|
] : setattr( self.attr( mod+self.fix), attr, val ) |
155 |
+ |
self.attr('patElectrons'+self.fix).isolationValues.user = tags( [self.isoEA] ) |
156 |
+ |
|
157 |
|
self.show('selectedPatElectrons'+self.fix) |
158 |
|
return |
159 |
|
|
160 |
|
def configPatJets(self) : |
122 |
– |
# Careful! these jet cuts affect the typeI met corrections |
123 |
– |
jetCuts = ['abs(eta) < 2.5', |
124 |
– |
'pt > 15.', |
125 |
– |
# PF jet ID: |
126 |
– |
'numberOfDaughters > 1', |
127 |
– |
'neutralHadronEnergyFraction < 0.99', |
128 |
– |
'neutralEmEnergyFraction < 0.99', |
129 |
– |
'(chargedEmEnergyFraction < 0.99 || abs(eta) >= 2.4)', |
130 |
– |
'(chargedHadronEnergyFraction > 0. || abs(eta) >= 2.4)', |
131 |
– |
'(chargedMultiplicity > 0 || abs(eta) >= 2.4)'] |
132 |
– |
|
161 |
|
for mod,attr,val in [('patJets','discriminatorSources',[tags(tag+'BJetTagsAOD'+self.fix) for tag in self.btags]), |
162 |
|
('patJets','tagInfoSources',[tags(tag+'TagInfosAOD'+self.fix) for tag in self.taginfos]), |
163 |
|
('patJets','addTagInfos',True), |
164 |
< |
('selectedPatJets','cut', ' && '.join(jetCuts)), |
164 |
> |
('selectedPatJets','cut', ' && '.join(self.cuts['jet'])), |
165 |
|
] : setattr( self.attr(mod+self.fix), attr, val ) |
166 |
|
self.show('selectedPatJets'+self.fix) |
167 |
|
return |
168 |
|
|
169 |
+ |
def configLeptonFilter(self) : |
170 |
+ |
if not self.options.requireLepton : return |
171 |
+ |
muons20Name = 'pfIsolatedMuons20'+self.fix |
172 |
+ |
leptonsName = 'pfLeptons'+self.fix |
173 |
+ |
requireLeptonName = 'requireLepton'+self.fix |
174 |
+ |
|
175 |
+ |
muons20 = cms.EDFilter("GenericPFCandidateSelector", src = tags('pfIsolatedMuons'+self.fix), cut = cms.string('pt>20 && abs(eta) < 2.4')) |
176 |
+ |
leptons = cms.EDProducer("CandViewMerger", src = tags(['pfIsolated%s%s'%(lep,self.fix) for lep in ['Electrons','Muons20']])) |
177 |
+ |
requireLepton = cms.EDFilter("CandViewCountFilter", src = tags(leptonsName), minNumber = cms.uint32(1) ) |
178 |
+ |
|
179 |
+ |
setattr(self.process, muons20Name, muons20) |
180 |
+ |
setattr(self.process, leptonsName, leptons) |
181 |
+ |
setattr(self.process, requireLeptonName, requireLepton) |
182 |
+ |
|
183 |
+ |
jets = self.attr('pfJets'+self.fix) |
184 |
+ |
self.patSeq.replace(jets, muons20*leptons*requireLepton*jets) |
185 |
+ |
|
186 |
+ |
self.show(muons20Name) |
187 |
+ |
self.show(leptonsName) |
188 |
+ |
self.show(requireLeptonName) |
189 |
+ |
return |
190 |
|
|
191 |
|
def removeCruft(self) : |
192 |
|
nothanks = [mod for mod in set(str(self.patSeq).split('+')) |