CMS 3D CMS Logo

jetCollectionTools.py
Go to the documentation of this file.
1 import FWCore.ParameterSet.Config as cms
2 
4 
5 from CommonTools.PileupAlgos.Puppi_cff import puppi
6 from CommonTools.PileupAlgos.softKiller_cfi import softKiller
7 
8 from RecoJets.JetProducers.PFJetParameters_cfi import PFJetParameters
9 from RecoJets.JetProducers.GenJetParameters_cfi import GenJetParameters
10 from RecoJets.JetProducers.AnomalousCellParameters_cfi import AnomalousCellParameters
11 
12 from RecoJets.JetProducers.ak4GenJets_cfi import ak4GenJets
13 from RecoJets.JetProducers.ak4PFJets_cfi import ak4PFJets, ak4PFJetsCHS, ak4PFJetsPuppi, ak4PFJetsSK, ak4PFJetsCS
14 from RecoJets.JetProducers.ak4CaloJets_cfi import ak4CaloJets
15 
17 from PhysicsTools.PatAlgos.recoLayer0.jetCorrFactors_cfi import patJetCorrFactors
18 from PhysicsTools.PatAlgos.mcMatchLayer0.jetFlavourId_cff import patJetFlavourAssociation
19 
20 from PhysicsTools.PatAlgos.tools.jetTools import supportedJetAlgos, addJetCollection, updateJetCollection
21 from PhysicsTools.PatAlgos.tools.helpers import getPatAlgosToolsTask, addToProcessAndTask
22 
23 import re
24 
25 #============================================
26 #
27 # GenJetInfo
28 #
29 #============================================
31  """
32  Class to hold information of a genjet collection
33  """
34  def __init__(self, jet, inputCollection):
35  self.jet = jet
36  self.jetLower = jet.lower()
37  self.jetUpper = jet.upper()
38  self.jetTagName = self.jetUpper
39  self.inputCollection = inputCollection
40  algoKey = 'algo'
41  sizeKey = 'size'
42  recoKey = 'reco'
43  jetRegex = re.compile(
44  r'(?P<{algo}>({algoList}))(?P<{size}>[0-9]+)gen'.format(
45  algo = algoKey,
46  algoList = '|'.join(supportedJetAlgos.keys()),
47  size = sizeKey,
48  )
49  )
50  jetMatch = jetRegex.match(jet.lower())
51  if not jetMatch:
52  raise RuntimeError('Invalid jet collection: %s' % jet)
53  self.jetAlgo = jetMatch.group(algoKey)
54  self.jetSize = jetMatch.group(sizeKey)
55  self.jetSizeNr = float(self.jetSize) / 10.
56 
57 #============================================
58 #
59 # GenJetAdder
60 #
61 #============================================
63  """
64  Tool to schedule modules for building a genjet collection with input MiniAODs
65  """
66  def __init__(self):
67  self.prerequisites = []
68  self.main = []
69  self.gpLabel = "prunedGenParticles"
70 
71  def addProcessAndTask(self, proc, label, module):
72  task = getPatAlgosToolsTask(proc)
73  addToProcessAndTask(label, module, proc, task)
74 
75  def addGenJetCollection(self,
76  proc,
77  jet,
78  inputCollection = "",
79  genName = "",
80  ):
81  print("jetCollectionTools::GenJetAdder::addGenJetCollection: Adding Gen Jet Collection: {}".format(jet))
82 
83  #
84  # Decide which genJet collection we are dealing with
85  #
86  jetLower = jet.lower()
87  jetUpper = jet.upper()
88  tagName = jetUpper
89  genJetInfo = GenJetInfo(jet,inputCollection)
90 
91  #=======================================================
92  #
93  # If genJet collection in MiniAOD is not
94  # specified, build the genjet collection.
95  #
96  #========================================================
97  if not inputCollection:
98  print("jetCollectionTools::GenJetAdder::addGenJetCollection: inputCollection not specified. Building genjet collection now")
99  #
100  # Setup GenParticles
101  #
102  packedGenPartNoNu = "packedGenParticlesForJetsNoNu"
103  if packedGenPartNoNu not in self.prerequisites:
104  self.addProcessAndTask(proc, packedGenPartNoNu, cms.EDFilter("CandPtrSelector",
105  src = cms.InputTag("packedGenParticles"),
106  cut = cms.string("abs(pdgId) != 12 && abs(pdgId) != 14 && abs(pdgId) != 16"),
107  )
108  )
109  self.prerequisites.append(packedGenPartNoNu)
110  #
111  # Create the GenJet collection
112  #
113  genJetsCollection = "{}{}{}".format(genJetInfo.jetAlgo.upper(), genJetInfo.jetSize, 'GenJetsNoNu')
114  self.addProcessAndTask(proc, genJetsCollection, ak4GenJets.clone(
115  src = packedGenPartNoNu,
116  jetAlgorithm = cms.string(supportedJetAlgos[genJetInfo.jetAlgo]),
117  rParam = cms.double(genJetInfo.jetSizeNr),
118  )
119  )
120  self.prerequisites.append(genJetsCollection)
121 
122  return genJetInfo
123 
124 #============================================
125 #
126 # RecoJetInfo
127 #
128 #============================================
130  """
131  Class to hold information of a recojet collection
132  """
133  def __init__(self, jet, inputCollection):
134  self.jet = jet
135  self.jetLower = jet.lower()
136  self.jetUpper = jet.upper()
137  self.jetTagName = self.jetUpper
138  self.inputCollection = inputCollection
139  algoKey = 'algo'
140  sizeKey = 'size'
141  recoKey = 'reco'
142  puMethodKey = 'puMethod'
143  jetRegex = re.compile(
144  r'(?P<{algo}>({algoList}))(?P<{size}>[0-9]+)(?P<{reco}>(pf|calo))(?P<{puMethod}>(chs|puppi|sk|cs|))'.format(
145  algo = algoKey,
146  algoList = '|'.join(supportedJetAlgos.keys()),
147  size = sizeKey,
148  reco = recoKey,
149  puMethod = puMethodKey,
150  )
151  )
152  jetMatch = jetRegex.match(jet.lower())
153  if not jetMatch:
154  raise RuntimeError('Invalid jet collection: %s' % jet)
155 
156  self.jetAlgo = jetMatch.group(algoKey)
157  self.jetSize = jetMatch.group(sizeKey)
158  self.jetReco = jetMatch.group(recoKey)
159  self.jetPUMethod = jetMatch.group(puMethodKey)
160 
161  self.jetSizeNr = float(self.jetSize) / 10.
162 
163  self.doCalo = self.jetReco == "calo"
164  self.doPF = self.jetReco == "pf"
165 
166  self.doCS = self.jetPUMethod == "cs"
167  self.skipUserData = self.doCalo or (self.jetPUMethod in [ "puppi", "sk" ] and inputCollection == "")
168 
169  self.jetCorrPayload = "{}{}{}".format(
170  self.jetAlgo.upper(), self.jetSize, "Calo" if self.doCalo else self.jetReco.upper()
171  )
172 
173  if self.jetPUMethod == "puppi":
174  self.jetCorrPayload += "Puppi"
175  elif self.jetPUMethod in [ "cs", "sk" ]:
176  self.jetCorrPayload += "chs"
177  else:
178  self.jetCorrPayload += self.jetPUMethod.lower()
179 
180 #============================================
181 #
182 # RecoJetAdder
183 #
184 #============================================
186  """
187  Tool to schedule modules for building a patJet collection from MiniAODs
188  """
189  def __init__(self,runOnMC=True):
190  self.prerequisites = []
191  self.main = []
192  self.pfLabel = "packedPFCandidates"
193  self.pvLabel = "offlineSlimmedPrimaryVertices"
194  self.svLabel = "slimmedSecondaryVertices"
195  self.muLabel = "slimmedMuons"
196  self.elLabel = "slimmedElectrons"
197  self.gpLabel = "prunedGenParticles"
198  self.runOnMC = runOnMC
199  self.patJetsInMiniAOD = ["slimmedJets", "slimmedJetsAK8", "slimmedJetsPuppi", "slimmedCaloJets"]
200 
201  def addProcessAndTask(self, proc, label, module):
202  task = getPatAlgosToolsTask(proc)
203  addToProcessAndTask(label, module, proc, task)
204 
205  def addRecoJetCollection(self,
206  proc,
207  jet,
208  inputCollection = "",
209  genJetsCollection = "",
210  bTagDiscriminators = ["None"],
211  JETCorrLevels = ["L1FastJet", "L2Relative", "L3Absolute", "L2L3Residual"],
212  ):
213  print("jetCollectionTools::RecoJetAdder::addRecoJetCollection: Adding Reco Jet Collection: {}".format(jet))
214 
215  currentTasks = []
216 
217  if inputCollection and inputCollection not in self.patJetsInMiniAOD:
218  raise RuntimeError("Invalid input collection: %s" % inputCollection)
219 
220  #=======================================================
221  #
222  # Figure out which jet collection we're dealing with
223  #
224  #=======================================================
225  recoJetInfo = RecoJetInfo(jet, inputCollection)
226  jetLower = recoJetInfo.jetLower
227  jetUpper = recoJetInfo.jetUpper
228  tagName = recoJetInfo.jetTagName
229 
230  if inputCollection == "slimmedJets":
231  assert(jetLower == "ak4pfchs")
232  elif inputCollection == "slimmedJetsAK8":
233  assert(jetLower == "ak8pfpuppi")
234  elif inputCollection == "slimmedJetsPuppi":
235  assert(jetLower == "ak4pfpuppi")
236  elif inputCollection == "slimmedCaloJets":
237  assert(jetLower == "ak4calo")
238 
239  #=======================================================
240  #
241  # If the patJet collection in MiniAOD is not specified,
242  # we have to build the patJet collection from scratch.
243  #
244  #========================================================
245  if not inputCollection or recoJetInfo.doCalo:
246  print("jetCollectionTools::RecoJetAdder::addRecoJetCollection: inputCollection not specified. Building recojet collection now")
247 
248  #=======================================================
249  #
250  # Prepare the inputs to jet clustering
251  #
252  #========================================================
253  #
254  # Specify PF candidates
255  #
256  pfCand = self.pfLabel
257  #
258  # Setup PU method for PF candidates
259  #
260  if recoJetInfo.jetPUMethod not in [ "", "cs" ]:
261  pfCand += recoJetInfo.jetPUMethod
262 
263 
264  #
265  # Setup modules to perform PU mitigation for
266  # PF candidates
267  #
268  if pfCand not in self.prerequisites:
269  #
270  # Skip if no PU Method or CS specified
271  #
272  if recoJetInfo.jetPUMethod in [ "", "cs" ]:
273  pass
274  #
275  # CHS
276  #
277  elif recoJetInfo.jetPUMethod == "chs":
278  self.addProcessAndTask(proc, pfCand, cms.EDFilter("CandPtrSelector",
279  src = cms.InputTag(self.pfLabel),
280  cut = cms.string("fromPV"),
281  )
282  )
283  self.prerequisites.append(pfCand)
284  #
285  # PUPPI
286  #
287  elif recoJetInfo.jetPUMethod == "puppi":
288  self.addProcessAndTask(proc, pfCand, puppi.clone(
289  candName = self.pfLabel,
290  vertexName = self.pvLabel,
291  clonePackedCands = True,
292  useExistingWeights = True,
293  )
294  )
295  self.prerequisites.append(pfCand)
296  #
297  # Softkiller
298  #
299  elif recoJetInfo.jetPUMethod == "sk":
300  self.addProcessAndTask(proc, pfCand, softKiller.clone(
301  PFCandidates = self.pfLabel,
302  rParam = recoJetInfo.jetSizeNr,
303  )
304  )
305  self.prerequisites.append(pfCand)
306  else:
307  raise RuntimeError("Currently unsupported PU method: '%s'" % recoJetInfo.jetPUMethod)
308 
309  #============================================
310  #
311  # Create the recojet collection
312  #
313  #============================================
314  if not recoJetInfo.doCalo:
315  jetCollection = '{}Collection'.format(jetUpper)
316 
317  if jetCollection in self.main:
318  raise ValueError("Step '%s' already implemented" % jetCollection)
319  #
320  # Cluster new jet
321  #
322  if recoJetInfo.jetPUMethod == "chs":
323  self.addProcessAndTask(proc, jetCollection, ak4PFJetsCHS.clone(
324  src = pfCand,
325  )
326  )
327  elif recoJetInfo.jetPUMethod == "puppi":
328  self.addProcessAndTask(proc, jetCollection, ak4PFJetsPuppi.clone(
329  src = pfCand,
330  )
331  )
332  elif recoJetInfo.jetPUMethod == "sk":
333  self.addProcessAndTask(proc, pfCand, ak4PFJetsSK.clone(
334  src = pfCand,
335  )
336  )
337  elif recoJetInfo.jetPUMethod == "cs":
338  self.addProcessAndTask(proc, jetCollection, ak4PFJetsCS.clone(
339  src = pfCand,
340  )
341  )
342  else:
343  self.addProcessAndTask(proc, jetCollection, ak4PFJets.clone(
344  src = pfCand,
345  )
346  )
347  getattr(proc, jetCollection).jetAlgorithm = supportedJetAlgos[recoJetInfo.jetAlgo]
348  getattr(proc, jetCollection).rParam = recoJetInfo.jetSizeNr
349  currentTasks.append(jetCollection)
350  else:
351  jetCollection = inputCollection
352 
353 
354  #=============================================
355  #
356  # Make patJet collection
357  #
358  #=============================================
359  #
360  # Jet correction
361  #
362  if recoJetInfo.jetPUMethod == "puppi":
363  jetCorrLabel = "Puppi"
364  elif recoJetInfo.jetPUMethod in [ "cs", "sk" ]:
365  jetCorrLabel = "chs"
366  else:
367  jetCorrLabel = recoJetInfo.jetPUMethod
368 
369  jetCorrections = (
370  "{}{}{}{}".format(
371  recoJetInfo.jetAlgo.upper(),
372  recoJetInfo.jetSize,
373  "Calo" if recoJetInfo.doCalo else recoJetInfo.jetReco.upper(),
374  jetCorrLabel
375  ),
376  JETCorrLevels,
377  "None",
378  )
379 
380  postfix = "Recluster" if inputCollection == "" else ""
381  addJetCollection(
382  proc,
383  labelName = jetUpper,
384  postfix = postfix,
385  jetSource = cms.InputTag(jetCollection),
386  algo = recoJetInfo.jetAlgo,
387  rParam = recoJetInfo.jetSizeNr,
388  pvSource = cms.InputTag(self.pvLabel),
389  pfCandidates = cms.InputTag(self.pfLabel),
390  svSource = cms.InputTag(self.svLabel),
391  muSource = cms.InputTag(self.muLabel),
392  elSource = cms.InputTag(self.elLabel),
393  genJetCollection = cms.InputTag(genJetsCollection),
394  genParticles = cms.InputTag(self.gpLabel),
395  jetCorrections = jetCorrections,
396  )
397 
398  #
399  # Need to set this explicitly for PUPPI jets
400  #
401  if recoJetInfo.jetPUMethod == "puppi":
402  getattr(proc, "patJetFlavourAssociation{}{}".format(tagName,postfix)).weights = cms.InputTag(pfCand)
403 
404  getJetMCFlavour = not recoJetInfo.doCalo and recoJetInfo.jetPUMethod != "cs"
405  if not self.runOnMC: #Remove modules for Gen-level object matching
406  delattr(proc, 'patJetGenJetMatch{}{}'.format(tagName,postfix))
407  delattr(proc, 'patJetPartonMatch{}{}'.format(tagName,postfix))
408  getJetMCFlavour = False
409  setattr(getattr(proc, "patJets{}{}".format(tagName,postfix)), "getJetMCFlavour", cms.bool(getJetMCFlavour))
410 
411  selectedPatJetCollection = "selectedPatJets{}{}".format(tagName,postfix)
412  #=============================================
413  #
414  # Update the patJet collection.
415  # This is where we setup
416  # - JEC
417  # - b-tagging discriminators
418  #
419  #=============================================
420  updateJetCollection(
421  proc,
422  labelName = jetUpper,
423  postfix = "Final",
424  jetSource = cms.InputTag(selectedPatJetCollection),
425  jetCorrections = jetCorrections,
426  btagDiscriminators = bTagDiscriminators,
427  )
428 
429  patJetFinalCollection="selectedUpdatedPatJets{}{}".format(tagName,"Final")
430  else:
431  patJetFinalCollection = inputCollection
432 
433  self.main.extend(currentTasks)
434 
435  return recoJetInfo
def __init__(self, runOnMC=True)
def addToProcessAndTask(label, module, process, task)
Definition: helpers.py:29
def addProcessAndTask(self, proc, label, module)
S & print(S &os, JobReport::InputFile const &f)
Definition: JobReport.cc:66
def __init__(self, jet, inputCollection)
def __init__(self, jet, inputCollection)
def addRecoJetCollection(self, proc, jet, inputCollection="", genJetsCollection="", bTagDiscriminators=["None"], JETCorrLevels=["L1FastJet", L2Relative, L3Absolute, L2L3Residual)
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
def addProcessAndTask(self, proc, label, module)
def getPatAlgosToolsTask(process)
Definition: helpers.py:14
def addGenJetCollection(self, proc, jet, inputCollection="", genName="")