ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/VHbbAnalysis/additionalFiles/jetTools.py
Revision: 1.1
Committed: Fri Mar 30 12:18:37 2012 UTC (13 years, 1 month ago) by arizzi
Content type: text/x-python
Branch: MAIN
Log Message:
file needed to add more btaggers in pat

File Contents

# Content
1 from FWCore.GuiBrowsers.ConfigToolBase import *
2
3 from PhysicsTools.PatAlgos.tools.helpers import *
4
5
6 class RunBTagging(ConfigToolBase):
7
8 """ Define sequence to run b tagging on AOD input for a given jet
9 collection including a JetTracksAssociatorAtVertex module with
10 name 'jetTracksAssociatorAtVertex' + 'label'
11
12 Return value is a pair of (sequence, labels) where 'sequence' is
13 the cms.Sequence, and 'labels' is a vector with the following
14 entries:
15 * labels['jta'] = the name of the JetTrackAssociator module
16 * labels['tagInfos'] = a list of names of the TagInfo modules
17 * labels['jetTags '] = a list of names of the JetTag modules
18 """
19 _label='runBTagging'
20 _defaultParameters=dicttypes.SortedKeysDict()
21 def __init__(self):
22 ConfigToolBase.__init__(self)
23 self.addParameter(self._defaultParameters,'jetCollection',self._defaultValue, 'input jet collection',Type=cms.InputTag)
24 self.addParameter(self._defaultParameters,'label',self._defaultValue, 'postfix label to identify new sequence/modules', Type=str)
25 self.addParameter(self._defaultParameters,'postfix',"", "postfix of default sequence (do not confuse with 'label')")
26 self._parameters=copy.deepcopy(self._defaultParameters)
27 self._comment = ""
28
29 def getDefaultParameters(self):
30 return self._defaultParameters
31
32 def __call__(self,process,
33 jetCollection = None,
34 label = None,
35 postfix = None) :
36 if jetCollection is None:
37 jetCollection=self._defaultParameters['jetCollection'].value
38 if label is None:
39 label=self._defaultParameters['label'].value
40 if postfix is None:
41 postfix=self._defaultParameters['postfix'].value
42 self.setParameter('jetCollection',jetCollection)
43 self.setParameter('label',label)
44 self.setParameter('postfix',postfix)
45
46 return self.apply(process)
47
48 def apply(self, process):
49 jetCollection=self._parameters['jetCollection'].value
50 label=self._parameters['label'].value
51 postfix=self._parameters['postfix'].value
52
53 if hasattr(process, "addAction"):
54 process.disableRecording()
55
56 try:
57 comment=inspect.stack(2)[2][4][0].rstrip("\n")
58 if comment.startswith("#"):
59 self.setComment(comment.lstrip("#"))
60 except:
61 pass
62
63 #############################
64 ### TOOL CODE STARTS HERE ###
65 #############################
66 if (label == ''):
67 ## label is not allowed to be empty
68 raise ValueError, "label for re-running b tagging is not allowed to be empty"
69
70 ## import track associator & b tag configuration
71 process.load("RecoJets.JetAssociationProducers.ak5JTA_cff")
72 from RecoJets.JetAssociationProducers.ak5JTA_cff import ak5JetTracksAssociatorAtVertex
73 process.load("RecoBTag.Configuration.RecoBTag_cff")
74 import RecoBTag.Configuration.RecoBTag_cff as btag
75
76 # add negative tag infos
77 import PhysicsTools.PatAlgos.recoLayer0.bTagging_cff as nbtag
78
79 ## define jetTracksAssociator; for switchJetCollection
80 ## the label is 'AOD' as empty labels will lead to crashes
81 ## of crab. In this case the postfix label is skiped,
82 ## otherwise a postfix label is added as for the other
83 ## labels
84 jtaLabel = 'jetTracksAssociatorAtVertex'+postfix
85
86 if (not label == 'AOD'):
87 jtaLabel += label
88 ## define tag info labels (compare with jetProducer_cfi.py)
89 ipTILabel = 'impactParameterTagInfos' + label + postfix
90 svTILabel = 'secondaryVertexTagInfos' + label + postfix
91 ivfTILabel = 'inclusiveSecondaryVertexFinderTagInfos' + label + postfix
92 #nvTILabel = '' + label + postfix
93 #seTILabel = 'softElectronTagInfos' + label + postfix
94 smTILabel = 'softMuonTagInfos' + label + postfix
95
96 ## produce tag infos
97 setattr( process, ipTILabel, btag.impactParameterTagInfos.clone(jetTracks = cms.InputTag(jtaLabel)) )
98 setattr( process, svTILabel, btag.secondaryVertexTagInfos.clone(trackIPTagInfos = cms.InputTag(ipTILabel)) )
99 setattr( process, ivfTILabel, btag.inclusiveSecondaryVertexFinderTagInfos.clone(trackIPTagInfos = cms.InputTag(ipTILabel)) )
100 #setattr( process, nvTILabel, nbtag.secondaryVertexNegativeTagInfos.clone(trackIPTagInfos = cms.InputTag(ipTILabel)) )
101 #setattr( process, seTILabel, btag.softElectronTagInfos.clone(jets = jetCollection) )
102 setattr( process, smTILabel, btag.softMuonTagInfos.clone(jets = jetCollection) )
103
104 ## make VInputTag from strings
105 def vit(*args) : return cms.VInputTag( *[ cms.InputTag(x) for x in args ] )
106
107 ## produce btags
108 setattr( process, 'jetBProbabilityBJetTags'+label+postfix, btag.jetBProbabilityBJetTags.clone(tagInfos = vit(ipTILabel)) )
109 setattr( process, 'jetProbabilityBJetTags'+label+postfix, btag.jetProbabilityBJetTags.clone (tagInfos = vit(ipTILabel)) )
110 setattr( process, 'trackCountingHighPurBJetTags'+label+postfix, btag.trackCountingHighPurBJetTags.clone(tagInfos = vit(ipTILabel)) )
111 setattr( process, 'trackCountingHighEffBJetTags'+label+postfix, btag.trackCountingHighEffBJetTags.clone(tagInfos = vit(ipTILabel)) )
112 setattr( process, 'simpleSecondaryVertexHighEffBJetTags'+label+postfix, btag.simpleSecondaryVertexHighEffBJetTags.clone(tagInfos = vit(svTILabel)) )
113 setattr( process, 'simpleSecondaryVertexHighPurBJetTags'+label+postfix, btag.simpleSecondaryVertexHighPurBJetTags.clone(tagInfos = vit(svTILabel)) )
114 #setattr( process, 'simpleSecondaryVertexNegativeBJetTags'+label+postfix, nbtag.simpleSecondaryVertexNegativeBJetTags.clone(tagInfos = vit(nvTILabel)) )
115 setattr( process, 'combinedSecondaryVertexBJetTags'+label+postfix, btag.combinedSecondaryVertexBJetTags.clone(tagInfos = vit(ipTILabel, svTILabel)) )
116 setattr( process, 'combinedInclusiveSecondaryVertexBJetTags'+label+postfix, btag.combinedInclusiveSecondaryVertexBJetTags.clone(tagInfos = vit(ipTILabel, ivfTILabel)) )
117 setattr( process, 'combinedMVABJetTags'+label+postfix, btag.combinedInclusiveSecondaryVertexBJetTags.clone(tagInfos = vit(ipTILabel, ivfTILabel)) )
118 setattr( process, 'combinedSecondaryVertexMVABJetTags'+label+postfix, btag.combinedSecondaryVertexMVABJetTags.clone(tagInfos = vit(ipTILabel, svTILabel)) )
119 #setattr( process, 'softElectronByPtBJetTags'+label+postfix, btag.softElectronByPtBJetTags.clone(tagInfos = vit(seTILabel)) )
120 #setattr( process, 'softElectronByIP3dBJetTags'+label+postfix, btag.softElectronByIP3dBJetTags.clone(tagInfos = vit(seTILabel)) )
121 setattr( process, 'softMuonBJetTags'+label+postfix, btag.softMuonBJetTags.clone(tagInfos = vit(smTILabel)) )
122 setattr( process, 'softMuonByPtBJetTags'+label+postfix, btag.softMuonByPtBJetTags.clone(tagInfos = vit(smTILabel)) )
123 setattr( process, 'softMuonByIP3dBJetTags'+label+postfix, btag.softMuonByIP3dBJetTags.clone(tagInfos = vit(smTILabel)) )
124
125 ## define vector of (output) labels
126 labels = { 'jta' : jtaLabel,
127 #'tagInfos' : (ipTILabel,svTILabel,seTILabel,smTILabel),
128 'tagInfos' : (ipTILabel,svTILabel,ivfTILabel,smTILabel),
129 'jetTags' : [ (x + label+postfix) for x in ('jetBProbabilityBJetTags',
130 'jetProbabilityBJetTags',
131 'trackCountingHighPurBJetTags',
132 'trackCountingHighEffBJetTags',
133 #'simpleSecondaryVertexNegativeBJetTags',
134 'simpleSecondaryVertexHighEffBJetTags',
135 'simpleSecondaryVertexHighPurBJetTags',
136 'combinedSecondaryVertexBJetTags',
137 'combinedInclusiveSecondaryVertexBJetTags',
138 'combinedMVABJetTags',
139 'combinedSecondaryVertexMVABJetTags',
140 #'softElectronByPtBJetTags',
141 #'softElectronByIP3dBJetTags',
142 'softMuonBJetTags',
143 'softMuonByPtBJetTags',
144 'softMuonByIP3dBJetTags'
145 )
146 ]
147 }
148
149 ## extend an existing sequence by otherLabels
150 def mkseq(process, firstlabel, *otherlabels):
151 seq = getattr(process, firstlabel)
152 for x in otherlabels: seq += getattr(process, x)
153 return cms.Sequence(seq)
154
155 ## add tag infos to the process
156 setattr( process, 'btaggingTagInfos'+label+postfix, mkseq(process, *(labels['tagInfos']) ) )
157 ## add b tags to the process
158 setattr( process, 'btaggingJetTags'+label+postfix, mkseq(process, *(labels['jetTags']) ) )
159 ## add a combined sequence to the process
160 seq = mkseq(process, 'btaggingTagInfos'+label+postfix, 'btaggingJetTags' + label + postfix)
161 setattr( process, 'btagging'+label+postfix, seq )
162 ## return the combined sequence and the labels defined above
163
164 if hasattr(process, "addAction"):
165 process.enableRecording()
166 action=self.__copy__()
167 process.addAction(action)
168 return (seq, labels)
169
170 runBTagging=RunBTagging()
171
172
173 class AddJetCollection(ConfigToolBase):
174
175 """ Add a new collection of jets. Takes the configuration from the
176 already configured standard jet collection as starting point;
177 replaces before calling addJetCollection will also affect the
178 new jet collections
179 """
180 _label='addJetCollection'
181 _defaultParameters=dicttypes.SortedKeysDict()
182 def __init__(self):
183 ConfigToolBase.__init__(self)
184 self.addParameter(self._defaultParameters,'jetCollection',self._defaultValue,'Input jet collection', cms.InputTag)
185 self.addParameter(self._defaultParameters,'algoLabel',self._defaultValue, "label to indicate the jet algorithm (e.g.'AK5')",str)
186 self.addParameter(self._defaultParameters,'typeLabel',self._defaultValue, "label to indicate the type of constituents (e.g. 'Calo', 'Pflow', 'Jpt', ...)",str)
187 self.addParameter(self._defaultParameters,'doJTA',True, "run b tagging sequence for new jet collection and add it to the new pat jet collection")
188 self.addParameter(self._defaultParameters,'doBTagging',True, 'run JetTracksAssociation and JetCharge and add it to the new pat jet collection (will autom. be true if doBTagging is set to true)')
189 self.addParameter(self._defaultParameters,'jetCorrLabel',None, "payload and list of new jet correction labels, such as (\'AK5Calo\',[\'L2Relative\', \'L3Absolute\'])", tuple,acceptNoneValue=True )
190 self.addParameter(self._defaultParameters,'doType1MET',True, "if jetCorrLabel is not 'None', set this to 'True' to redo the Type1 MET correction for the new jet colllection; at the moment it must be 'False' for non CaloJets otherwise the JetMET POG module crashes. ")
191 self.addParameter(self._defaultParameters,'doL1Cleaning',True, "copy also the producer modules for cleanLayer1 will be set to 'True' automatically when doL1Counters is 'True'")
192 self.addParameter(self._defaultParameters,'doL1Counters',False, "copy also the filter modules that accept/reject the event looking at the number of jets")
193 self.addParameter(self._defaultParameters,'genJetCollection',cms.InputTag("ak5GenJets"), "GenJet collection to match to")
194 self.addParameter(self._defaultParameters,'doJetID',True, "add jetId variables to the added jet collection?")
195 self.addParameter(self._defaultParameters,'jetIdLabel',"ak5", " specify the label prefix of the xxxJetID object; in general it is the jet collection tag like ak5, kt4 sc5, aso. For more information have a look to SWGuidePATTools#add_JetCollection")
196 self.addParameter(self._defaultParameters, 'outputModule', "out", "Output module label, empty label indicates no output, default: out")
197
198 self._parameters=copy.deepcopy(self._defaultParameters)
199 self._comment = ""
200
201 def getDefaultParameters(self):
202 return self._defaultParameters
203
204 def __call__(self,process,
205 jetCollection = None,
206 algoLabel = None,
207 typeLabel = None,
208 doJTA = None,
209 doBTagging = None,
210 jetCorrLabel = None,
211 doType1MET = None,
212 doL1Cleaning = None,
213 doL1Counters = None,
214 genJetCollection = None,
215 doJetID = None,
216 jetIdLabel = None,
217 outputModule = None):
218
219 if jetCollection is None:
220 jetCollection=self._defaultParameters['jetCollection'].value
221 if algoLabel is None:
222 algoLabel=self._defaultParameters['algoLabel'].value
223 if typeLabel is None:
224 typeLabel=self._defaultParameters['typeLabel'].value
225 if doJTA is None:
226 doJTA=self._defaultParameters['doJTA'].value
227 if doBTagging is None:
228 doBTagging=self._defaultParameters['doBTagging'].value
229 if jetCorrLabel is None:
230 jetCorrLabel=self._defaultParameters['jetCorrLabel'].value
231 if doType1MET is None:
232 doType1MET=self._defaultParameters['doType1MET'].value
233 if doL1Cleaning is None:
234 doL1Cleaning=self._defaultParameters['doL1Cleaning'].value
235 if doL1Counters is None:
236 doL1Counters=self._defaultParameters['doL1Counters'].value
237 if genJetCollection is None:
238 genJetCollection=self._defaultParameters['genJetCollection'].value
239 if doJetID is None:
240 doJetID=self._defaultParameters['doJetID'].value
241 if jetIdLabel is None:
242 jetIdLabel=self._defaultParameters['jetIdLabel'].value
243 if outputModule is None:
244 outputModule=self._defaultParameters['outputModule'].value
245
246 self.setParameter('jetCollection',jetCollection)
247 self.setParameter('algoLabel',algoLabel)
248 self.setParameter('typeLabel',typeLabel)
249 self.setParameter('doJTA',doJTA)
250 self.setParameter('doBTagging',doBTagging)
251 self.setParameter('jetCorrLabel',jetCorrLabel)
252 self.setParameter('doType1MET',doType1MET)
253 self.setParameter('doL1Cleaning',doL1Cleaning)
254 self.setParameter('doL1Counters',doL1Counters)
255 self.setParameter('genJetCollection',genJetCollection)
256 self.setParameter('doJetID',doJetID)
257 self.setParameter('jetIdLabel',jetIdLabel)
258 self.setParameter('outputModule',outputModule)
259
260 self.apply(process)
261
262 def toolCode(self, process):
263 jetCollection=self._parameters['jetCollection'].value
264 algoLabel=self._parameters['algoLabel'].value
265 typeLabel=self._parameters['typeLabel'].value
266 doJTA=self._parameters['doJTA'].value
267 doBTagging=self._parameters['doBTagging'].value
268 jetCorrLabel=self._parameters['jetCorrLabel'].value
269 doType1MET =self._parameters['doType1MET'].value
270 doL1Cleaning=self._parameters['doL1Cleaning'].value
271 doL1Counters=self._parameters['doL1Counters'].value
272 genJetCollection=self._parameters['genJetCollection'].value
273 doJetID=self._parameters['doJetID'].value
274 jetIdLabel=self._parameters['jetIdLabel'].value
275 outputModule=self._parameters['outputModule'].value
276
277 ## create old module label from standardAlgo
278 ## and standardType and return
279 def oldLabel(prefix=''):
280 return jetCollectionString(prefix, '', '')
281
282 ## create new module label from old module
283 ## label and return
284 def newLabel(oldLabel):
285 newLabel=oldLabel
286 oldLabel=oldLabel+algoLabel+typeLabel
287 return oldLabel
288
289 ## clone module and add it to the patDefaultSequence
290 def addClone(hook, **replaceStatements):
291 ## create a clone of the hook with corresponding
292 ## parameter replacements
293 newModule = getattr(process, hook).clone(**replaceStatements)
294 ## add the module to the sequence
295 addModuleToSequence(hook, newModule)
296
297 ## add module to the patDefaultSequence
298 def addModuleToSequence(hook, newModule):
299 hookModule = getattr(process, hook)
300 ## add the new module with standardAlgo &
301 ## standardType replaced in module label
302 setattr( process, newLabel(hook), newModule)
303 ## add new module to default sequence
304 ## just behind the hookModule
305 process.patDefaultSequence.replace( hookModule, hookModule*newModule )
306
307 ## add a clone of patJets
308 addClone(oldLabel(), jetSource = jetCollection)
309 ## add a clone of selectedPatJets
310 addClone(oldLabel('selected'), src=cms.InputTag(newLabel(oldLabel())))
311 ## add a clone of cleanPatJets
312 if( doL1Cleaning ):
313 addClone(oldLabel('clean'), src=cms.InputTag(newLabel(oldLabel('selected'))))
314 ## add a clone of countPatJets
315 if( doL1Counters ):
316 if( doL1Cleaning ):
317 addClone(oldLabel('count'), src=cms.InputTag(newLabel(oldLabel('clean'))))
318 else:
319 addClone(oldLabel('count'), src=cms.InputTag(newLabel(oldLabel('selected'))))
320
321 ## get attributes of new module
322 l1Jets = getattr(process, newLabel(oldLabel()))
323
324 ## add a clone of gen jet matching
325 addClone('patJetPartonMatch', src = jetCollection)
326 addClone('patJetGenJetMatch', src = jetCollection, matched = genJetCollection)
327
328 ## add a clone of parton and flavour associations
329 addClone('patJetPartonAssociation', jets = jetCollection)
330 addClone('patJetFlavourAssociation', srcByReference = cms.InputTag(newLabel('patJetPartonAssociation')))
331
332 ## fix label for input tag
333 def fixInputTag(x): x.setModuleLabel(newLabel(x.moduleLabel))
334 ## fix label for vector of input tags
335 def fixVInputTag(x): x[0].setModuleLabel(newLabel(x[0].moduleLabel))
336
337 ## provide allLayer1Jet inputs with individual labels
338 fixInputTag(l1Jets.genJetMatch)
339 fixInputTag(l1Jets.genPartonMatch)
340 fixInputTag(l1Jets.JetPartonMapSource)
341
342 ## make VInputTag from strings
343 def vit(*args) : return cms.VInputTag( *[ cms.InputTag(x) for x in args ] )
344
345 if (doJTA or doBTagging):
346 ## add clone of jet track association
347 process.load("RecoJets.JetAssociationProducers.ak5JTA_cff")
348 from RecoJets.JetAssociationProducers.ak5JTA_cff import ak5JetTracksAssociatorAtVertex
349 ## add jet track association module to processes
350 jtaLabel = 'jetTracksAssociatorAtVertex'+algoLabel+typeLabel
351 setattr( process, jtaLabel, ak5JetTracksAssociatorAtVertex.clone(jets = jetCollection) )
352 process.patDefaultSequence.replace(process.patJetCharge, getattr(process,jtaLabel)+process.patJetCharge)
353 l1Jets.trackAssociationSource = cms.InputTag(jtaLabel)
354 addClone('patJetCharge', src=cms.InputTag(jtaLabel)),
355 fixInputTag(l1Jets.jetChargeSource)
356 else:
357 ## switch embedding of track association and jet
358 ## charge estimate to 'False'
359 l1Jets.addAssociatedTracks = False
360 l1Jets.addJetCharge = False
361
362 if (doBTagging):
363 ## define postfixLabel
364 postfixLabel=algoLabel+typeLabel
365 ## add b tagging sequence
366 (btagSeq, btagLabels) = runBTagging(process, jetCollection, postfixLabel)
367 ## add b tagging sequence before running the allLayer1Jets modules
368 process.patDefaultSequence.replace(getattr(process,jtaLabel), getattr(process,jtaLabel)+btagSeq)
369 ## replace corresponding tags for pat jet production
370 l1Jets.trackAssociationSource = cms.InputTag(btagLabels['jta'])
371 l1Jets.tagInfoSources = cms.VInputTag( *[ cms.InputTag(x) for x in btagLabels['tagInfos'] ] )
372 l1Jets.discriminatorSources = cms.VInputTag( *[ cms.InputTag(x) for x in btagLabels['jetTags'] ] )
373 else:
374 ## switch general b tagging info switch off
375 l1Jets.addBTagInfo = False
376 ## adjust output
377 if outputModule is not '':
378 getattr(process, outputModule).outputCommands.append("drop *_"+newLabel(oldLabel('selected'))+"_tagInfos_*")
379
380 if (doJetID):
381 l1Jets.addJetID = cms.bool(True)
382 jetIdLabelNew = jetIdLabel + 'JetID'
383 l1Jets.jetIDMap = cms.InputTag( jetIdLabelNew )
384 else :
385 l1Jets.addJetID = cms.bool(False)
386
387 if (jetCorrLabel != None):
388 ## add clone of jet energy corrections;
389 ## catch a couple of exceptions first
390 if (jetCorrLabel == False ):
391 raise ValueError, "In addJetCollection 'jetCorrLabel' must be set to 'None', not 'False'"
392 if (jetCorrLabel == "None"):
393 raise ValueError, "In addJetCollection 'jetCorrLabel' must be set to 'None' (without quotes)"
394 ## check for the correct format
395 if type(jetCorrLabel) != type(('AK5Calo',['L2Relative'])):
396 raise ValueError, "In addJetCollection 'jetCorrLabel' must be 'None', or of type ('payload',['correction1', 'correction2'])"
397
398 ## add clone of jetCorrFactors
399 addClone('patJetCorrFactors', src = jetCollection)
400 switchJetCorrLevels(process, jetCorrLabel = jetCorrLabel, postfix=algoLabel+typeLabel)
401 #getattr(process,newLabel('patJetCorrFactors')).payload = jetCorrLabel[0]
402 #getattr(process,newLabel('patJetCorrFactors')).levels = jetCorrLabel[1]
403 getattr(process, newLabel('patJets')).jetCorrFactorsSource = cms.VInputTag( cms.InputTag(newLabel('patJetCorrFactors')) )
404
405 ## switch type1MET corrections off for PFJets or JPTJets
406 if ( jetCollection.getModuleLabel().find('CaloJets')<0 ):
407 print '================================================='
408 print 'Type1MET corrections are switched off for other '
409 print 'jet types but CaloJets. Users are recommened to '
410 print 'use pfMET together with PFJets & tcMET together '
411 print 'with JPT jets. '
412 print '================================================='
413 doType1MET=False
414
415 ## add a clone of the type1MET correction for the new jet collection
416 if (doType1MET):
417 ## in case there is no jet correction service in the paths add it
418 ## as L2L3 if possible, as combined from L2 and L3 otherwise
419 if not hasattr( process, '%sL2L3' % (jetCollection.getModuleLabel().replace("Jets", "")) ):
420 setattr( process, '%sL2L3' % (jetCollection.getModuleLabel().replace("Jets", "")),
421 cms.ESSource("JetCorrectionServiceChain",
422 correctors = cms.vstring('%sL2Relative' % (jetCollection.getModuleLabel().replace("Jets", "")),
423 '%sL3Absolute' % (jetCollection.getModuleLabel().replace("Jets", ""))
424 )
425 )
426 )
427 ## add a clone of the type1MET correction
428 ## and the following muonMET correction
429 addClone('metJESCorAK5CaloJet', inputUncorJetsLabel = jetCollection.value(),
430 corrector = cms.string('%sL2L3' % (jetCollection.getModuleLabel().replace("Jets", "")))
431 )
432 addClone('metJESCorAK5CaloJetMuons', uncorMETInputTag = cms.InputTag(newLabel('metJESCorAK5CaloJet')))
433 addClone('patMETs', metSource = cms.InputTag(newLabel('metJESCorAK5CaloJetMuons')))
434 l1MET = getattr(process, newLabel('patMETs'))
435 ## add new met collections output to the pat summary
436 process.patCandidateSummary.candidates += [ cms.InputTag(newLabel('patMETs')) ]
437 else:
438 ## switch jetCorrFactors off
439 l1Jets.addJetCorrFactors = False
440
441 addJetCollection=AddJetCollection()
442
443
444 class SwitchJetCollection(ConfigToolBase):
445
446 """ Switch the collection of jets in PAT from the default value to a
447 new jet collection
448 """
449 _label='switchJetCollection'
450 _defaultParameters=dicttypes.SortedKeysDict()
451 def __init__(self):
452 ConfigToolBase.__init__(self)
453 self.addParameter(self._defaultParameters,'jetCollection',self._defaultValue,'Input jet collection', cms.InputTag)
454 self.addParameter(self._defaultParameters,'doJTA',True, "run b tagging sequence for new jet collection and add it to the new pat jet collection")
455 self.addParameter(self._defaultParameters,'doBTagging',True, 'run JetTracksAssociation and JetCharge and add it to the new pat jet collection (will autom. be true if doBTagging is set to true)')
456 self.addParameter(self._defaultParameters,'jetCorrLabel',None, "payload and list of new jet correction labels, such as (\'AK5Calo\',[\'L2Relative\', \'L3Absolute\'])", tuple,acceptNoneValue=True )
457 self.addParameter(self._defaultParameters,'doType1MET',True, "if jetCorrLabel is not 'None', set this to 'True' to redo the Type1 MET correction for the new jet colleection; at the moment it must be 'False' for non CaloJets otherwise the JetMET POG module crashes. ")
458 self.addParameter(self._defaultParameters,'genJetCollection',cms.InputTag("ak5GenJets"), "GenJet collection to match to")
459 self.addParameter(self._defaultParameters,'doJetID',True, "add jetId variables to the added jet collection")
460 self.addParameter(self._defaultParameters,'jetIdLabel',"ak5", " specify the label prefix of the xxxJetID object; in general it is the jet collection tag like ak5, kt4 sc5, aso. For more information have a look to SWGuidePATTools#add_JetCollection")
461 self.addParameter(self._defaultParameters,'postfix',"", "postfix of default sequence")
462 self.addParameter(self._defaultParameters, 'outputModule', "out", "Output module label, empty label indicates no output, default: out")
463
464 self._parameters=copy.deepcopy(self._defaultParameters)
465 self._comment = ""
466
467 def getDefaultParameters(self):
468 return self._defaultParameters
469
470 def __call__(self,process,
471 jetCollection = None,
472 doJTA = None,
473 doBTagging = None,
474 jetCorrLabel = None,
475 doType1MET = None,
476 genJetCollection = None,
477 doJetID = None,
478 jetIdLabel = None,
479 postfix = None,
480 outputModule = None):
481
482 if jetCollection is None:
483 jetCollection=self._defaultParameters['jetCollection'].value
484 if doJTA is None:
485 doJTA=self._defaultParameters['doJTA'].value
486 if doBTagging is None:
487 doBTagging=self._defaultParameters['doBTagging'].value
488 if jetCorrLabel is None:
489 jetCorrLabel=self._defaultParameters['jetCorrLabel'].value
490 if doType1MET is None:
491 doType1MET=self._defaultParameters['doType1MET'].value
492 if genJetCollection is None:
493 genJetCollection=self._defaultParameters['genJetCollection'].value
494 if doJetID is None:
495 doJetID=self._defaultParameters['doJetID'].value
496 if jetIdLabel is None:
497 jetIdLabel=self._defaultParameters['jetIdLabel'].value
498 if outputModule is None:
499 outputModule=self._defaultParameters['outputModule'].value
500 if postfix is None:
501 postfix=self._defaultParameters['postfix'].value
502
503 self.setParameter('jetCollection',jetCollection)
504 self.setParameter('doJTA',doJTA)
505 self.setParameter('doBTagging',doBTagging)
506 self.setParameter('jetCorrLabel',jetCorrLabel)
507 self.setParameter('doType1MET',doType1MET)
508 self.setParameter('genJetCollection',genJetCollection)
509 self.setParameter('doJetID',doJetID)
510 self.setParameter('jetIdLabel',jetIdLabel)
511 self.setParameter('outputModule',outputModule)
512 self.setParameter('postfix',postfix)
513
514 self.apply(process)
515
516 def toolCode(self, process):
517 jetCollection=self._parameters['jetCollection'].value
518 doJTA=self._parameters['doJTA'].value
519 doBTagging=self._parameters['doBTagging'].value
520 jetCorrLabel=self._parameters['jetCorrLabel'].value
521 doType1MET =self._parameters['doType1MET'].value
522 genJetCollection=self._parameters['genJetCollection'].value
523 doJetID=self._parameters['doJetID'].value
524 jetIdLabel=self._parameters['jetIdLabel'].value
525 outputModule=self._parameters['outputModule'].value
526 postfix=self._parameters['postfix'].value
527
528 ## save label of old input jet collection
529 oldLabel = applyPostfix(process, "patJets", postfix).jetSource;
530
531 ## replace input jet collection for generator matches if the
532 ## genJetCollection is no empty
533 if (process.patJets.addGenPartonMatch):
534 applyPostfix(process, "patJetPartonMatch", postfix).src = jetCollection
535 if (process.patJets.addGenJetMatch):
536 applyPostfix(process, "patJetGenJetMatch", postfix).src = jetCollection
537 applyPostfix(process, "patJetGenJetMatch", postfix).matched = genJetCollection
538 if (process.patJets.getJetMCFlavour):
539 applyPostfix(process, "patJetPartonAssociation", postfix).jets = jetCollection
540
541 ## replace input jet collection for pat jet production
542 applyPostfix(process, "patJets", postfix).jetSource = jetCollection
543
544 ## make VInputTag from strings
545 def vit(*args) : return cms.VInputTag( *[ cms.InputTag(x) for x in args ] )
546
547 if (doJTA or doBTagging):
548 ## replace jet track association
549 process.load("RecoJets.JetAssociationProducers.ak5JTA_cff")
550 from RecoJets.JetAssociationProducers.ak5JTA_cff import ak5JetTracksAssociatorAtVertex
551 setattr(process, "jetTracksAssociatorAtVertex"+postfix, ak5JetTracksAssociatorAtVertex.clone(jets = jetCollection))
552 getattr(process, "patDefaultSequence"+postfix).replace(
553 applyPostfix(process, "patJetCharge", postfix),
554 getattr(process, "jetTracksAssociatorAtVertex" + postfix) #module with postfix that is not n patDefaultSequence
555 + applyPostfix(process, "patJetCharge", postfix)
556 )
557
558 applyPostfix(process, "patJetCharge", postfix).src = 'jetTracksAssociatorAtVertex'+postfix
559 applyPostfix(process, "patJets", postfix).trackAssociationSource = 'jetTracksAssociatorAtVertex'+postfix
560 else:
561 ## remove the jet track association from the std
562 ## sequence
563 removeIfInSequence(process, "patJetCharge", "patDefaultSequence", postfix)
564 ## switch embedding of track association and jet
565 ## charge estimate to 'False'
566 applyPostfix(process, "patJets", postfix).addAssociatedTracks = False
567 applyPostfix(process, "patJets", postfix).addJetCharge = False
568
569 if (doBTagging):
570 ## replace b tagging sequence; add postfix label 'AOD' as crab will
571 ## crash when confronted with empy labels
572 (btagSeq, btagLabels) = runBTagging(process, jetCollection, 'AOD',postfix)
573 ## add b tagging sequence before running the allLayer1Jets modules
574 getattr(process, "patDefaultSequence"+postfix).replace(
575 getattr( process,"jetTracksAssociatorAtVertex"+postfix),
576 getattr( process,"jetTracksAssociatorAtVertex"+postfix) + btagSeq
577 )
578
579 ## replace corresponding tags for pat jet production
580 applyPostfix(process, "patJets", postfix).trackAssociationSource = btagLabels['jta']
581 applyPostfix(process, "patJets", postfix).tagInfoSources = cms.VInputTag( *[ cms.InputTag(x) for x in btagLabels['tagInfos'] ] )
582 applyPostfix(process, "patJets", postfix).discriminatorSources = cms.VInputTag( *[ cms.InputTag(x) for x in btagLabels['jetTags'] ] )
583 else:
584 ## remove b tagging from the std sequence
585 removeIfInSequence(process, "secondaryVertexNegativeTagInfos", "patDefaultSequence", postfix)
586 removeIfInSequence(process, "simpleSecondaryVertexNegativeBJetTags", "patDefaultSequence", postfix)
587 ## switch embedding of b tagging for pat
588 ## jet production to 'False'
589 applyPostfix(process, "patJets", postfix).addBTagInfo = False
590 ## adjust output
591 if outputModule is not '':
592 getattr(process, outputModule).outputCommands.append("drop *_selectedPatJets_tagInfos_*")
593
594 if (doJetID):
595 jetIdLabelNew = jetIdLabel + 'JetID'
596 applyPostfix(process, "patJets", postfix).jetIDMap = cms.InputTag( jetIdLabelNew )
597 else:
598 applyPostfix(process, "patJets", postfix).addJetID = cms.bool(False)
599
600 if (jetCorrLabel!=None):
601 ## replace jet energy corrections; catch
602 ## a couple of exceptions first
603 if (jetCorrLabel == False ):
604 raise ValueError, "In switchJetCollection 'jetCorrLabel' must be set to 'None', not 'False'"
605 if (jetCorrLabel == "None"):
606 raise ValueError, "In switchJetCollection 'jetCorrLabel' must be set to 'None' (without quotes)"
607 ## check for the correct format
608 if type(jetCorrLabel) != type(('AK5Calo',['L2Relative'])):
609 raise ValueError, "In addJetCollection 'jetCorrLabel' must be 'None', or of type ('payload',['correction1', 'correction2'])"
610
611 ## switch JEC parameters to the new jet collection
612 applyPostfix(process, "patJetCorrFactors", postfix).src = jetCollection
613 switchJetCorrLevels(process, jetCorrLabel = jetCorrLabel, postfix=postfix)
614 #getattr( process, "patJetCorrFactors" + postfix).payload = jetCorrLabel[0]
615 #getattr( process, "patJetCorrFactors" + postfix).levels = jetCorrLabel[1]
616 getattr( process, "patJets" + postfix).jetCorrFactorsSource = cms.VInputTag( cms.InputTag("patJetCorrFactors" + postfix ) )
617
618 ## switch type1MET corrections off for PFJets or JPTJets
619 if ( jetCollection.getModuleLabel().find('CaloJets')<0 ):
620 print '================================================='
621 print 'Type1MET corrections are switched off for other '
622 print 'jet types but CaloJets. Users are recommened to '
623 print 'use pfMET together with PFJets & tcMET together '
624 print 'with JPT jets. '
625 print '================================================='
626 doType1MET=False
627
628 ## redo the type1MET correction for the new jet collection
629 if (doType1MET):
630 ## in case there is no jet correction service in the paths add it
631 ## as L2L3 if possible, as combined from L2 and L3 otherwise
632 if not hasattr( process, '%sL2L3' % (jetCollection.getModuleLabel().replace("Jets", "")) ):
633 setattr( process, '%sL2L3' % (jetCollection.getModuleLabel().replace("Jets", "")),
634 cms.ESSource("JetCorrectionServiceChain",
635 correctors = cms.vstring('%sL2Relative' % (jetCollection.getModuleLabel().replace("Jets", "")),
636 '%sL3Absolute' % (jetCollection.getModuleLabel().replace("Jets", ""))
637 )
638 )
639 )
640 ## configure the type1MET correction the following muonMET
641 ## corrections have the metJESCorAK5CaloJet as input and
642 ## are automatically correct
643 applyPostfix(process, "metJESCorAK5CaloJet", postfix).inputUncorJetsLabel = jetCollection.value()
644 applyPostfix(process, "metJESCorAK5CaloJet", postfix).corrector = '%sL2L3' % (jetCollection.getModuleLabel().replace("Jets", ""))
645 else:
646 ## remove the jetCorrFactors from the std sequence
647 process.patJetMETCorrections.remove(process.patJetCorrFactors)
648 ## switch embedding of jetCorrFactors off
649 ## for pat jet production
650 applyPostfix(process, "patJets", postfix).addJetCorrFactors = False
651 applyPostfix(process, "patJets", postfix).jetCorrFactorsSource=[]
652
653 ## adjust output when switching to PFJets
654 if (jetCollection.getModuleLabel().find('PFJets')>=0 ):
655 ## in this case we can omit caloTowers and should keep pfCandidates
656 if outputModule is not '':
657 getattr(process, outputModule).outputCommands.append("keep *_selectedPatJets_pfCandidates_*")
658 getattr(process, outputModule).outputCommands.append("drop *_selectedPatJets_caloTowers_*")
659
660 switchJetCollection=SwitchJetCollection()
661
662
663 class AddJetID(ConfigToolBase):
664
665 """ Compute jet id for process
666 """
667 _label='addJetID'
668 _defaultParameters=dicttypes.SortedKeysDict()
669 def __init__(self):
670 ConfigToolBase.__init__(self)
671 self.addParameter(self._defaultParameters,'jetSrc',self._defaultValue, "", Type=cms.InputTag)
672 self.addParameter(self._defaultParameters,'jetIdTag',self._defaultValue, "Tag to append to jet id map", Type=str)
673 self._parameters=copy.deepcopy(self._defaultParameters)
674 self._comment = ""
675
676 def getDefaultParameters(self):
677 return self._defaultParameters
678
679 def __call__(self,process,
680 jetSrc = None,
681 jetIdTag = None) :
682 if jetSrc is None:
683 jetSrc=self._defaultParameters['jetSrc'].value
684 if jetIdTag is None:
685 jetIdTag=self._defaultParameters['jetIdTag'].value
686 self.setParameter('jetSrc',jetSrc)
687 self.setParameter('jetIdTag',jetIdTag)
688 self.apply(process)
689
690 def toolCode(self, process):
691 jetSrc=self._parameters['jetSrc'].value
692 jetIdTag=self._parameters['jetIdTag'].value
693
694 jetIdLabel = jetIdTag + 'JetID'
695 print "Making new jet ID label with label " + jetIdTag
696
697 ## replace jet id sequence
698 process.load("RecoJets.JetProducers.ak5JetID_cfi")
699 setattr( process, jetIdLabel, process.ak5JetID.clone(src = jetSrc))
700 process.makePatJets.replace( process.patJets, getattr(process,jetIdLabel) + process.patJets )
701
702 addJetID=AddJetID()
703
704
705 class SetTagInfos(ConfigToolBase):
706
707 """ Replace tag infos for collection jetSrc
708 """
709 _label='setTagInfos'
710 _defaultParameters=dicttypes.SortedKeysDict()
711 def __init__(self):
712 ConfigToolBase.__init__(self)
713 self.addParameter(self._defaultParameters,'coll',"allLayer1Jets","jet collection to set tag infos for")
714 self.addParameter(self._defaultParameters,'tagInfos',cms.vstring( ), "tag infos to set")
715 self._parameters=copy.deepcopy(self._defaultParameters)
716 self._comment = ""
717
718 def getDefaultParameters(self):
719 return self._defaultParameters
720
721 def __call__(self,process,
722 coll = None,
723 tagInfos = None) :
724 if coll is None:
725 coll=self._defaultParameters['coll'].value
726 if tagInfos is None:
727 tagInfos=self._defaultParameters['tagInfos'].value
728 self.setParameter('coll',coll)
729 self.setParameter('tagInfos',tagInfos)
730 self.apply(process)
731
732 def toolCode(self, process):
733 coll=self._parameters['coll'].value
734 tagInfos=self._parameters['tagInfos'].value
735
736 found = False
737 newTags = cms.VInputTag()
738 iNewTags = 0
739 for k in tagInfos :
740 for j in getattr( process, coll ).tagInfoSources :
741 vv = j.value();
742 if ( vv.find(k) != -1 ):
743 found = True
744 newTags.append( j )
745
746 if not found:
747 raise RuntimeError,"""
748 Cannot replace tag infos in jet collection""" % (coll)
749 else :
750 getattr(process,coll).tagInfoSources = newTags
751
752 setTagInfos=SetTagInfos()
753
754
755 class SwitchJetCorrLevels(ConfigToolBase):
756
757 """ Switch from jet energy correction levels and do all necessary adjustments
758 """
759 _label='switchJetCorrLevels'
760 _defaultParameters=dicttypes.SortedKeysDict()
761 def __init__(self):
762 ConfigToolBase.__init__(self)
763 self.addParameter(self._defaultParameters,'jetCorrLabel',None, "payload and list of new jet correction labels, such as (\'AK5Calo\',[\'L2Relative\', \'L3Absolute\'])", tuple,acceptNoneValue=True )
764 self.addParameter(self._defaultParameters,'postfix',"", "postfix of default sequence")
765 self._parameters=copy.deepcopy(self._defaultParameters)
766 self._comment = ""
767
768 def getDefaultParameters(self):
769 return self._defaultParameters
770
771 def __call__(self,process,
772 jetCorrLabel = None,
773 postfix = None) :
774 if jetCorrLabel is None:
775 jetCorrLabel=self._defaultParameters['jetCorrLabel'].value
776 if postfix is None:
777 postfix=self._defaultParameters['postfix'].value
778
779 self.setParameter('jetCorrLabel',jetCorrLabel)
780 self.setParameter('postfix',postfix)
781
782 self.apply(process)
783
784 def toolCode(self, process):
785 jetCorrLabel=self._parameters['jetCorrLabel'].value
786 postfix=self._parameters['postfix'].value
787
788 if (jetCorrLabel!=None):
789 ## replace jet energy corrections; catch
790 ## a couple of exceptions first
791 if (jetCorrLabel == False ):
792 raise ValueError, "In switchJetCollection 'jetCorrLabel' must be set to 'None', not 'False'"
793 if (jetCorrLabel == "None"):
794 raise ValueError, "In switchJetCollection 'jetCorrLabel' must be set to 'None' (without quotes)"
795 ## check for the correct format
796 if type(jetCorrLabel) != type(('AK5Calo',['L2Relative'])):
797 raise ValueError, "In addJetCollection 'jetCorrLabel' must be 'None', or of type ('payload',['correction1', 'correction2'])"
798
799 jetCorrFactorsModule = getattr(process, "patJetCorrFactors"+postfix)
800 jetCorrFactorsModule.payload = jetCorrLabel[0]
801 jetCorrFactorsModule.levels = jetCorrLabel[1]
802
803 ## check whether L1Offset or L1FastJet is part of levels
804 error = False
805 for x in jetCorrLabel[1]:
806 if x == 'L1Offset':
807 if not error:
808 jetCorrFactorsModule.useNPV = True
809 primaryVertices = 'offlinePrimaryVertices'
810 ## we set this to True now as a L1 correction type should appear only once
811 ## otherwise levels is miss configured
812 error = True
813 else:
814 print 'ERROR : you miss configured the levels parameter. A L1 correction'
815 print ' type should appear not more than once in there.'
816 print jetCorrLabel[1]
817
818 if x == 'L1FastJet':
819 if not error:
820 ## re-run jet algo to compute rho and jetArea for the L1Fastjet corrections
821 process.load("RecoJets.JetProducers.kt4PFJets_cfi")
822 process.kt6PFJets = process.kt4PFJets.clone(doAreaFastjet=True, doRhoFastjet=True, rParam=0.6)
823 process.patDefaultSequence.replace(jetCorrFactorsModule, process.kt6PFJets*jetCorrFactorsModule)
824 ## configure module
825 jetCorrFactorsModule.useRho = True
826 jetCorrFactorsModule.rho = cms.InputTag('kt6PFJets', 'rho')
827 ## we set this to True now as a L1 correction type should appear only once
828 ## otherwise levels is miss configured
829 error = True
830 else:
831 print 'ERROR : you miss configured the levels parameter. A L1 correction'
832 print ' type should appear not more than once in there.'
833 print jetCorrLabel[1]
834
835 switchJetCorrLevels=SwitchJetCorrLevels()