ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/VHbbAnalysis/additionalFiles/jetTools.py
Revision: 1.2
Committed: Fri Mar 30 18:23:41 2012 UTC (13 years, 1 month ago) by arizzi
Content type: text/x-python
Branch: MAIN
CVS Tags: V21TauCand_0, V21emuCand, EdmV22May9, EdmV21Apr06, EdmV21Apr10, EdmV21Apr04, EdmV21Apr03, EdmV21Apr2, EdmV21Mar30
Branch point for: V21TauCand, V21emuCandidate
Changes since 1.1: +5 -5 lines
Log Message:
fix super combined tagger, add softelectron taginfo that was missing

File Contents

# User Rev Content
1 arizzi 1.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 arizzi 1.2 seTILabel = 'softElectronTagInfos' + label + postfix
94 arizzi 1.1 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 arizzi 1.2 setattr( process, seTILabel, btag.softElectronTagInfos.clone(jets = jetCollection) )
102 arizzi 1.1 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 arizzi 1.2 setattr( process, 'combinedMVABJetTags'+label+postfix, btag.combinedMVABJetTags.clone(tagInfos = vit(ipTILabel, ivfTILabel,smTILabel,seTILabel)) )
118 arizzi 1.1 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 arizzi 1.2 # 'tagInfos' : (ipTILabel,svTILabel,seTILabel,smTILabel),
128     'tagInfos' : (ipTILabel,svTILabel,ivfTILabel,smTILabel,seTILabel),
129 arizzi 1.1 '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()