CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
jmeUncertaintyTools.py
Go to the documentation of this file.
2 
4 
5 import PhysicsTools.PatAlgos.tools.helpers as configtools
6 from PhysicsTools.PatAlgos.tools.trigTools import _addEventContent
7 
8 #from PhysicsTools.PatUtils.patPFMETCorrections_cff import *
9 import RecoMET.METProducers.METSigParams_cfi as jetResolutions
11 
13 
14 ##MM
15 #from PhysicsTools.PatAlgos.patSequences_cff import *
16 
18 
19  """ Base class for estimating systematic uncertainties on MET """
20  _label='JetMEtUncertaintyTools'
21  _defaultParameters=dicttypes.SortedKeysDict()
22  def __init__(self):
23  ConfigToolBase.__init__(self)
24  self.addParameter(self._defaultParameters, 'electronCollection', cms.InputTag('cleanPatElectrons'),
25  "Input electron collection", Type=cms.InputTag, acceptNoneValue=True)
26  self.addParameter(self._defaultParameters, 'photonCollection', None, # CV: set to empty InputTag to avoid double-counting wrt. cleanPatElectrons collection
27  "Input photon collection", Type=cms.InputTag, acceptNoneValue=True)
28  self.addParameter(self._defaultParameters, 'muonCollection', cms.InputTag('cleanPatMuons'),
29  "Input muon collection", Type=cms.InputTag, acceptNoneValue=True)
30  self.addParameter(self._defaultParameters, 'tauCollection', cms.InputTag('cleanPatTaus'),
31  "Input tau collection", Type=cms.InputTag, acceptNoneValue=True)
32  self.addParameter(self._defaultParameters, 'jetCollection', cms.InputTag('cleanPatJets'),
33  "Input jet collection", Type=cms.InputTag)
34  self.addParameter(self._defaultParameters, 'jetCorrLabel', "L3Absolute",
35  "NOTE: use 'L3Absolute' for MC/'L2L3Residual' for Data", Type=str)
36  self.addParameter(self._defaultParameters, 'doSmearJets', True,
37  "Flag to enable/disable jet smearing to better match MC to Data", Type=bool)
38  self.addParameter(self._defaultParameters, 'jetSmearFileName', 'PhysicsTools/PatUtils/data/pfJetResolutionMCtoDataCorrLUT.root',
39  "Name of ROOT file containing histogram with jet smearing factors", Type=str)
40  self.addParameter(self._defaultParameters, 'jetSmearHistogram', 'pfJetResolutionMCtoDataCorrLUT',
41  "Name of histogram with jet smearing factors", Type=str)
42  self.addParameter(self._defaultParameters, 'jetCorrPayloadName', 'AK4PF',
43  "Use AK4PF for PFJets, AK4Calo for CaloJets", Type=str)
44  self.addParameter(self._defaultParameters, 'jetCorrLabelUpToL3', 'ak4PFL1FastL2L3',
45  "Use ak4PFL1FastL2L3 (ak4PFchsL1FastL2L3) for PFJets with (without) charged hadron subtraction, ak4CaloL1FastL2L3 for CaloJets", Type=str)
46  self.addParameter(self._defaultParameters, 'jetCorrLabelUpToL3Res', 'ak4PFL1FastL2L3Residual',
47  "Use ak4PFL1FastL2L3Residual (ak4PFchsL1FastL2L3Residual) for PFJets with (without) charged hadron subtraction, ak4CaloL1FastL2L3Residual for CaloJets", Type=str)
48  self.addParameter(self._defaultParameters, 'jecUncertaintyFile', "PhysicsTools/PatUtils/data/Summer13_V1_DATA_UncertaintySources_AK5PF.txt",
49  "Name of file containing jet energy uncertainty parameters", Type=str)
50  self.addParameter(self._defaultParameters, 'jecUncertaintyTag', 'SubTotalMC',
51  "Name of tag for Data/MC jet energy uncertainties", Type=str)
52  self.addParameter(self._defaultParameters, 'varyByNsigmas', 1.0,
53  "Number of standard deviations by which energies are varied", Type=float)
54  self.addParameter(self._defaultParameters, 'addToPatDefaultSequence', True,
55  "Flag to enable/disable that metUncertaintySequence is inserted into patDefaultSequence", Type=bool)
56  self.addParameter(self._defaultParameters, 'outputModule', 'out',
57  "Module label of PoolOutputModule (empty label indicates no PoolOutputModule is to be configured)", Type=str)
58  self.addParameter(self._defaultParameters, 'postfix', '',
59  "Technical parameter to identify the resulting sequence and its modules (allows multiple calls in a job)", Type=str)
60  self._parameters = copy.deepcopy(self._defaultParameters)
61  self._comment = ""
62 
64  return self._defaultParameters
65 
66 
67  def _initializeInputTag(self, input, default):
68  retVal = None
69  if input is None:
70  retVal = self._defaultParameters[default].value
71  elif type(input) == str:
72  retVal = cms.InputTag(input)
73  else:
74  retVal = input
75  return retVal
76 
77 
78  def _addCleanedJets(self, process, jetCollection,
79  electronCollection, photonCollection,
80  muonCollection, tauCollection,
81  uncertaintySequence, postfix = ""):
82 
83  # produce collection of jets not overlapping with reconstructed
84  # electrons/photons, muons and tau-jet candidates
85  jetsNotOverlappingWithLeptons = cms.EDProducer("PATJetCleaner",
86  src = jetCollection,
87  preselection = cms.string(''),
88  checkOverlaps = cms.PSet(),
89  finalCut = cms.string('')
90  )
91  numOverlapCollections = 0
92  for collection in [
93  [ 'electrons', electronCollection ],
94  [ 'photons', photonCollection ],
95  [ 'muons', muonCollection ],
96  [ 'taus', tauCollection ] ]:
97  if isValidInputTag(collection[1]):
98  setattr(jetsNotOverlappingWithLeptons.checkOverlaps, collection[0], cms.PSet(
99  src = collection[1],
100  algorithm = cms.string("byDeltaR"),
101  preselection = cms.string(""),
102  deltaR = cms.double(0.5),
103  checkRecoComponents = cms.bool(False),
104  pairCut = cms.string(""),
105  requireNoOverlaps = cms.bool(True),
106  ))
107  numOverlapCollections = numOverlapCollections + 1
108  lastJetCollection = jetCollection.value()
109  if numOverlapCollections >= 1:
110  lastJetCollection = \
111  addModuleToSequence(process, jetsNotOverlappingWithLeptons,
112  [ jetCollection.value(), "NotOverlappingWithLeptonsForJetMEtUncertainty" ],
113  uncertaintySequence, postfix)
114  cleanedJetCollection = lastJetCollection
115 
116  return ( lastJetCollection, cleanedJetCollection )
117 
118 
119  def _addShiftedParticleCollections(self, process,
120  electronCollection = None,
121  photonCollection = None,
122  muonCollection = None,
123  tauCollection = None,
124  jetCollection = None, cleanedJetCollection = None,
125  lastJetCollection = None, addShiftedResJetCollections = False,
126  jetCorrLabelUpToL3 = None, jetCorrLabelUpToL3Res = None,
127  jecUncertaintyFile = None, jecUncertaintyTag = None,
128  jetSmearFileName=None, jetSmearHistogram=None,
129  varyByNsigmas = None,
130  postfix = ""):
131 
132  shiftedParticleSequence = cms.Sequence()
133  shiftedParticleCollections = {}
134  collectionsToKeep = []
135 
136  # standard jet collections
137  shiftedParticleCollections[ 'cleanedJetCollection' ] = cleanedJetCollection
138 
139  #--------------------------------------------------------------------------------------------
140  # store collection of jets shifted up/down in energy resolution
141  #--------------------------------------------------------------------------------------------
142  if not isValidInputTag(jetCollection) or jetCollection=="":
143  print "Warning, jet collection %s does not exists, no energy resolution shifting performed in PAT" % jetCollection
144  else:
145  if addShiftedResJetCollections:
146  variations = { "ResUp":-1., "ResDown":1. }
147  for var in variations.keys():
148  jetCollectionToKeep = \
149  addSmearedJets(process, cleanedJetCollection,
150  [ "smeared", jetCollection, var ],
151  jetSmearFileName,jetSmearHistogram,jetResolutions,
152  varyByNsigmas, variations[ var ],
153  shiftedParticleSequence, postfix)
154  jetCol={'jetCollection%s'%var:jetCollectionToKeep}
155  shiftedParticleCollections.update( jetCol )
156  collectionsToKeep.append( jetCollectionToKeep )
157 
158  #--------------------------------------------------------------------------------------------
159  # produce collection of jets shifted up/down in energy
160  #--------------------------------------------------------------------------------------------
161  if not isValidInputTag(jetCollection) or jetCollection=="":
162  print "Warning, jet collection %s does not exists, no energy shifting performed in PAT" % jetCollection
163  else:
164  shiftedJetsCollections, jetsCollectionsToKeep = addShiftedJetCollections(
165  process,jetCollection,lastJetCollection,
166  jetCorrLabelUpToL3, jetCorrLabelUpToL3Res,
167  jecUncertaintyFile, jecUncertaintyTag,
168  varyByNsigmas, shiftedParticleSequence,
169  postfix)
170  shiftedParticleCollections.update( shiftedJetsCollections )
171  collectionsToKeep.extend( jetsCollectionsToKeep )
172 
173  #--------------------------------------------------------------------------------------------
174  # produce collection of electrons shifted up/down in energy
175  #--------------------------------------------------------------------------------------------
176  if not isValidInputTag(electronCollection) or electronCollection=="":
177  print "Warning, electron collection %s does not exists, no energy shifting performed in PAT" % electronCollection
178  else:
179  shiftedElectronsCollections, electronsCollectionsToKeep = addShiftedSingleParticleCollection(
180  process, "electron", electronCollection,
181  varyByNsigmas,shiftedParticleSequence,
182  postfix)
183 
184  shiftedParticleCollections.update( shiftedElectronsCollections )
185  collectionsToKeep.extend( electronsCollectionsToKeep )
186 
187  #--------------------------------------------------------------------------------------------
188  # produce collection of (high Pt) photon candidates shifted up/down in energy
189  #--------------------------------------------------------------------------------------------
190  if not isValidInputTag(photonCollection) or photonCollection=="":
191  print "Warning, photon collection %s does not exists, no energy shifting performed in PAT" % photonCollection
192  else:
193  shiftedPhotonsCollections, photonsCollectionsToKeep = addShiftedSingleParticleCollection(
194  process, "photon", photonCollection,
195  varyByNsigmas,shiftedParticleSequence,
196  postfix)
197  shiftedParticleCollections.update( shiftedPhotonsCollections )
198  collectionsToKeep.extend( photonsCollectionsToKeep )
199 
200  #--------------------------------------------------------------------------------------------
201  # produce collection of muons shifted up/down in energy/momentum
202  #--------------------------------------------------------------------------------------------
203  if not isValidInputTag(muonCollection) or muonCollection=="":
204  print "Warning, muon collection %s does not exists, no energy shifting performed in PAT" % muonCollection
205  else:
206  shiftedMuonsCollections, muonsCollectionsToKeep = addShiftedSingleParticleCollection(process, "muon", muonCollection,
207  varyByNsigmas,shiftedParticleSequence,
208  postfix)
209  shiftedParticleCollections.update( shiftedMuonsCollections )
210  collectionsToKeep.extend( muonsCollectionsToKeep )
211 
212  #--------------------------------------------------------------------------------------------
213  # produce collection of tau-jets shifted up/down in energy
214  #--------------------------------------------------------------------------------------------
215  if not isValidInputTag(tauCollection) or tauCollection=="":
216  print "Warning, tau collection %s does not exists, no energy shifting performed in PAT" % tauCollection
217  else:
218  shiftedTausCollections, tausCollectionsToKeep = addShiftedSingleParticleCollection(process, "tau", tauCollection,
219  varyByNsigmas,shiftedParticleSequence,
220  postfix)
221  shiftedParticleCollections.update( shiftedTausCollections )
222  collectionsToKeep.extend( tausCollectionsToKeep )
223 
224 
225  return ( shiftedParticleSequence, shiftedParticleCollections, collectionsToKeep )
226 
227 
228 
229 
230 
231  def _addPFCandidatesForPFMEtInput(self, process, metUncertaintySequence,
232  particleCollection, particleType, shiftType, particleCollectionShiftUp, particleCollectionShiftDown,
233  dRmatch,
234  pfCandCollection, postfix):
235 
236  srcUnshiftedObjects = particleCollection
237  if isinstance(srcUnshiftedObjects, cms.InputTag):
238  srcUnshiftedObjects = srcUnshiftedObjects.value()
239  moduleShiftUp = cms.EDProducer("ShiftedPFCandidateProducerByMatchedObject",
240  srcPFCandidates = pfCandCollection,
241  srcUnshiftedObjects = cms.InputTag(srcUnshiftedObjects),
242  srcShiftedObjects = cms.InputTag(particleCollectionShiftUp),
243  dRmatch_PFCandidate = cms.double(dRmatch)
244  )
245  moduleNameShiftUp = "pfCandidates%s%sUp%s" % (particleType, shiftType, postfix)
246  setattr(process, moduleNameShiftUp, moduleShiftUp)
247  metUncertaintySequence += moduleShiftUp
248 
249  moduleShiftDown = moduleShiftUp.clone(
250  srcShiftedObjects = cms.InputTag(particleCollectionShiftDown)
251  )
252  moduleNameShiftDown = "pfCandidates%s%sDown%s" % (particleType, shiftType, postfix)
253  setattr(process, moduleNameShiftDown, moduleShiftDown)
254  metUncertaintySequence += moduleShiftDown
255 
256  return ( moduleNameShiftUp, moduleNameShiftDown )
257 
258  def _getLeptonsForPFMEtInput(self, shiftedParticleCollections, substituteKeyUnshifted = None, substituteKeyShifted = None, postfix=""):
259  retVal = []
260  for collectionName in [ 'electronCollection',
261  'photonCollection',
262  'muonCollection',
263  'tauCollection' ]:
264  if self._isValidInputTag(shiftedParticleCollections[collectionName]):
265  if substituteKeyUnshifted is not None and substituteKeyUnshifted in shiftedParticleCollections.keys() and \
266  substituteKeyShifted is not None and substituteKeyShifted in shiftedParticleCollections.keys() and \
267  shiftedParticleCollections[collectionName] == shiftedParticleCollections[substituteKeyUnshifted]:
268  retVal.append(cms.InputTag(shiftedParticleCollections[substituteKeyShifted]))
269  else:
270  retVal.append(shiftedParticleCollections[collectionName])
271  return retVal
272 
273  def _addPATMEtProducer(self, process, metUncertaintySequence,
274  patMEtCollection, metCollection,
275  collectionsToKeep, postfix):
276 
277  module = patMETs.clone(
278  metSource = cms.InputTag(metCollection),
279  addMuonCorrections = cms.bool(False),
280  genMETSource = cms.InputTag('genMetTrue')
281  )
282  patMEtCollectionName = patMEtCollection+postfix
283  setattr(process, patMEtCollectionName, module)
284  metUncertaintySequence += module
285  collectionsToKeep.append(patMEtCollectionName)
286 
287  def __call__(self, process,
288  electronCollection = None,
289  photonCollection = None,
290  muonCollection = None,
291  tauCollection = None,
292  jetCollection = None,
293  jetCorrLabel = None,
294  doSmearJets = None,
295  jetSmearFileName = None,
296  jetSmearHistogram = None,
297  jetCorrPayloadName = None,
298  jetCorrLabelUpToL3 = None,
299  jetCorrLabelUpToL3Res = None,
300  jecUncertaintyFile = None,
301  jecUncertaintyTag = None,
302  varyByNsigmas = None,
303  addToPatDefaultSequence = None,
304  outputModule = None,
305  postfix = None):
306  electronCollection = self._initializeInputTag(electronCollection, 'electronCollection')
307  photonCollection = self._initializeInputTag(photonCollection, 'photonCollection')
308  muonCollection = self._initializeInputTag(muonCollection, 'muonCollection')
309  tauCollection = self._initializeInputTag(tauCollection, 'tauCollection')
310  jetCollection = self._initializeInputTag(jetCollection, 'jetCollection')
311  if jetCorrLabel is None:
312  jetCorrLabel = self._defaultParameters['jetCorrLabel'].value
313  if doSmearJets is None:
314  doSmearJets = self._defaultParameters['doSmearJets'].value
315  if jetSmearFileName is None:
316  jetSmearFileName = self._defaultParameters['jetSmearFileName'].value
317  if jetSmearHistogram is None:
318  jetSmearHistogram = self._defaultParameters['jetSmearHistogram'].value
319  if jetCorrPayloadName is None:
320  jetCorrPayloadName = self._defaultParameters['jetCorrPayloadName'].value
321  if jetCorrLabelUpToL3 is None:
322  jetCorrLabelUpToL3 = self._defaultParameters['jetCorrLabelUpToL3'].value
323  if jetCorrLabelUpToL3Res is None:
324  jetCorrLabelUpToL3Res = self._defaultParameters['jetCorrLabelUpToL3Res'].value
325  if jecUncertaintyFile is None:
326  jecUncertaintyFile = self._defaultParameters['jecUncertaintyFile'].value
327  if jecUncertaintyTag is None:
328  jecUncertaintyTag = self._defaultParameters['jecUncertaintyTag'].value
329  if varyByNsigmas is None:
330  varyByNsigmas = self._defaultParameters['varyByNsigmas'].value
331  if addToPatDefaultSequence is None:
332  addToPatDefaultSequence = self._defaultParameters['addToPatDefaultSequence'].value
333  if outputModule is None:
334  outputModule = self._defaultParameters['outputModule'].value
335  if postfix is None:
336  postfix = self._defaultParameters['postfix'].value
337 
338  self.setParameter('electronCollection', electronCollection)
339  self.setParameter('photonCollection', photonCollection)
340  self.setParameter('muonCollection', muonCollection)
341  self.setParameter('tauCollection', tauCollection)
342  self.setParameter('jetCollection', jetCollection)
343  self.setParameter('jetCorrLabel', jetCorrLabel)
344  self.setParameter('doSmearJets', doSmearJets)
345  self.setParameter('jetSmearFileName', jetSmearFileName)
346  self.setParameter('jetSmearHistogram', jetSmearHistogram)
347  self.setParameter('jetCorrPayloadName', jetCorrPayloadName)
348  self.setParameter('jetCorrLabelUpToL3', jetCorrLabelUpToL3)
349  self.setParameter('jetCorrLabelUpToL3Res', jetCorrLabelUpToL3Res)
350  self.setParameter('jecUncertaintyFile', jecUncertaintyFile)
351  self.setParameter('jecUncertaintyTag', jecUncertaintyTag)
352  self.setParameter('varyByNsigmas', varyByNsigmas)
353  self.setParameter('addToPatDefaultSequence', addToPatDefaultSequence)
354  self.setParameter('outputModule', outputModule)
355  self.setParameter('postfix', postfix)
356 
MM from PhysicsTools.PatAlgos.patSequences_cff import *.
def addShiftedJetCollections
Now, jet variation for corrected METs, the default collection to use.
def addShiftedSingleParticleCollection
Up variation.