CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
objectsUncertaintyTools.py
Go to the documentation of this file.
2 
3 def isValidInputTag(input):
4  input_str = input
5  if isinstance(input, cms.InputTag):
6  input_str = input.value()
7  if input is None or input_str == '""':
8  return False
9  else:
10  return True
11 
12 
13 def addModuleToSequence(process, module, moduleName_parts, sequence, postfix):
14 
15  if not len(moduleName_parts) > 0:
16  raise ValueError("Empty list !!")
17 
18  moduleName = ""
19 
20  lastPart = None
21  for part in moduleName_parts:
22  if part is None or part == "":
23  continue
24 
25  part = part.replace("selected", "")
26  part = part.replace("clean", "")
27 
28  if lastPart is None:
29  moduleName += part[0].lower() + part[1:]
30  lastPart = part
31  else:
32  if lastPart[-1].islower() or lastPart[-1].isdigit():
33  moduleName += part[0].capitalize() + part[1:]
34  else:
35  moduleName += part[0].lower() + part[1:]
36  lastPart = part
37 
38  moduleName += postfix
39  setattr(process, moduleName, module)
40 
41  sequence += module
42 
43  return moduleName
44 
45 
46 
47 def addShiftedSingleParticleCollection(process, identifier,objectCollection,
48  varyByNsigmas,sequence, postfix = ""):
49 
50  shiftedParticleCollections = {}
51  collectionsToKeep = []
52 
53  shiftedCollectionName = identifier+"Collection"
54  shiftedParticleCollections[ shiftedCollectionName ] = objectCollection
55 
56 
57 
58  objectCollectionUp = None
59  objectCollectionDown = None
60 
61  if isValidInputTag(objectCollection):
62 
63  ##
64  ## Up variation
65  ##
66  objectCollectionUp = createShiftedSingleParticleUpModule(process,identifier,
67  objectCollection,
68  varyByNsigmas, sequence,postfix)
69  # collectionName = objectCollection.value()
70  # collectionName = collectionName.replace("selected", "")
71  # collectionName = collectionName.replace("clean", "")
72  objectModuleUp = getattr(process, objectCollectionUp)
73  shiftedParticleCollections[ shiftedCollectionName+'EnUp'] = objectCollectionUp
74  collectionsToKeep.append(objectCollectionUp)
75 
76  ##
77  ## Down variation
78  ##
79  objectModuleDown = objectModuleUp.clone(
80  shiftBy = cms.double(-1.*varyByNsigmas)
81  )
82  objectCollectionDown = addModuleToSequence(process, objectModuleDown,
83  [ "shifted", objectCollection, "EnDown" ],
84  sequence, postfix)
85  shiftedParticleCollections[ shiftedCollectionName+'EnDown'] = objectCollectionDown
86  collectionsToKeep.append(objectCollectionDown)
87 
88 
89  return (shiftedParticleCollections, collectionsToKeep)
90 
91 
92 
93 def createShiftedSingleParticleUpModule(process,identifier, objectCollection,
94  varyByNsigmas,sequence,postfix=""):
95 
96  shiftedCollectionUp = None
97 
98  if identifier == "electron":
99  shiftedModuleUp = cms.EDProducer("ShiftedPATElectronProducer",
100  src = cms.InputTag(objectCollection),
101  binning = cms.VPSet(
102  cms.PSet(
103  binSelection = cms.string('isEB'),
104  binUncertainty = cms.double(0.006)
105  ),
106  cms.PSet(
107  binSelection = cms.string('!isEB'),
108  binUncertainty = cms.double(0.015)
109  ),
110  ),
111  shiftBy = cms.double(+1.*varyByNsigmas)
112  )
113 
114  if identifier == "photon":
115  shiftedModuleUp = cms.EDProducer("ShiftedPATPhotonProducer",
116  src = cms.InputTag(objectCollection),
117  binning = cms.VPSet(
118  cms.PSet(
119  binSelection = cms.string('isEB'),
120  binUncertainty = cms.double(0.01)
121  ),
122  cms.PSet(
123  binSelection = cms.string('!isEB'),
124  binUncertainty = cms.double(0.025)
125  ),
126  ),
127  shiftBy = cms.double(+1.*varyByNsigmas)
128  )
129 
130  if identifier == "muon":
131  shiftedModuleUp = cms.EDProducer("ShiftedPATMuonProducer",
132  src = cms.InputTag(objectCollection),
133  binning = cms.VPSet(
134  cms.PSet(
135  binSelection = cms.string('pt < 100'),
136  binUncertainty = cms.double(0.002)
137  ),
138  cms.PSet(
139  binSelection = cms.string('pt >= 100'),
140  binUncertainty = cms.double(0.05)
141  ),
142  ),
143  shiftBy = cms.double(+1.*varyByNsigmas)
144  )
145 
146  if identifier == "tau":
147  shiftedModuleUp = cms.EDProducer("ShiftedPATTauProducer",
148  src = cms.InputTag(objectCollection),
149  uncertainty = cms.double(0.03),
150  shiftBy = cms.double(+1.*varyByNsigmas)
151  )
152 
153  shiftedCollectionUp = addModuleToSequence(process, shiftedModuleUp,
154  [ "shifted", objectCollection, "EnUp" ],
155  sequence, postfix)
156 
157  return shiftedCollectionUp
158 
159 
160 
161 
162 def addShiftedJetCollections(process, jetCollection, lastJetCollection,
163  jetCorrLabelUpToL3, jetCorrLabelUpToL3Res,
164  jecUncertaintyFile, jecUncertaintyTag,
165  varyByNsigmas, sequence,
166  postfix = ""):
167 
168  shiftedParticleCollections = {}
169  collectionsToKeep = []
170 
171  shiftedParticleCollections['jetCollection'] = jetCollection
172  shiftedParticleCollections['lastJetCollection'] = lastJetCollection
173 
174  #
175  # Creating two sets for shifted jets corrections, depending of the use needed :
176  #
177 
178  variations=["Up","Down"]
179 
180  for var in variations:
181  # in case of "raw" (uncorrected) MET,
182  # add residual jet energy corrections in quadrature to jet energy uncertainties:
183  # cf. https://twiki.cern.ch/twiki/bin/view/CMS/MissingETUncertaintyPrescription
184  jetsEnShiftForRawMEt = cms.EDProducer("ShiftedPATJetProducer",
185  src = cms.InputTag(lastJetCollection),
186  #jetCorrPayloadName = cms.string(jetCorrPayloadName),
187  #jetCorrUncertaintyTag = cms.string('Uncertainty'),
188  jetCorrInputFileName = cms.FileInPath(jecUncertaintyFile),
189  jetCorrUncertaintyTag = cms.string(jecUncertaintyTag),
190  addResidualJES = cms.bool(True),
191  jetCorrLabelUpToL3 = cms.InputTag(jetCorrLabelUpToL3.value()),
192  jetCorrLabelUpToL3Res = cms.InputTag(jetCorrLabelUpToL3Res.value()),
193  shiftBy = cms.double(+1.*varyByNsigmas)
194  )
195 
196  jetCollectionEnShiftForRawMEt = \
197  addModuleToSequence(process, jetsEnShiftForRawMEt,
198  [ "shifted", jetCollection, "En%sForRawMEt"%var ],
199  sequence, postfix)
200  shiftedParticleCollections[ 'jetCollectionEn%sForRawMEt'%var ] = jetCollectionEnShiftForRawMEt
201  collectionsToKeep.append(jetCollectionEnShiftForRawMEt)
202 
203  ##
204  ## Now, jet variation for corrected METs, the default collection to use
205  ##
206 
207  jetsEnShift = jetsEnShiftForRawMEt.clone(
208  addResidualJES = cms.bool(False)
209  )
210 
211  ## Up Variation
212  jetCollectionEnShift =addModuleToSequence(process, jetsEnShift,
213  [ "shifted", jetCollection, "En"+ var ],
214  sequence, postfix)
215  shiftedParticleCollections['jetCollectionEn' + var ] = jetCollectionEnShift
216  collectionsToKeep.append(jetCollectionEnShift)
217 
218 
219  return (shiftedParticleCollections, collectionsToKeep)
220 
221 
222 
223 def addSmearedJets(process, jetCollection, smearedJetCollectionName_parts,
224  jetSmearFileName, jetSmearHistogram, jetResolutions,
225  varyByNsigmas, shiftBy = None, sequence = None, postfix = ""):
226 
227  smearedJets = cms.EDProducer("SmearedPATJetProducer",
228  src = cms.InputTag(jetCollection),
229  dRmaxGenJetMatch = cms.string('min(0.5, 0.1 + 0.3*exp(-0.05*(genJetPt - 10.)))'),
230  sigmaMaxGenJetMatch = cms.double(3.),
231  inputFileName = cms.FileInPath(jetSmearFileName),
232  lutName = cms.string(jetSmearHistogram),
233  jetResolutions = jetResolutions.METSignificance_params,
234  # CV: skip jet smearing for pat::Jets for which the jet-energy correction (JEC) factors are either very large or negative
235  # since both cases produce unphysically large tails in the Type 1 corrected MET distribution after the smearing,
236  #
237  # e.g. raw jet: energy = 50 GeV, eta = 2.86, pt = 1 GeV
238  # corr. jet: energy = -3 GeV , pt = -0.1 GeV (JEC factor L1fastjet*L2*L3 = -17)
239  # energy = 10 GeV for corrected jet after smearing
240  # --> smeared raw jet energy = -170 GeV !!
241  #
242  # --> (corr. - raw) jet contribution to MET = -1 (-10) GeV before (after) smearing,
243  # even though jet energy got smeared by merely 1 GeV
244  #
245  skipJetSelection = cms.string(
246  'jecSetsAvailable & abs(energy - correctedP4("Uncorrected").energy) > (5.*min(energy, correctedP4("Uncorrected").energy))'
247  ),
248  skipRawJetPtThreshold = cms.double(10.), # GeV
249  skipCorrJetPtThreshold = cms.double(1.e-2),
250  verbosity = cms.int32(0)
251  )
252  if shiftBy is not None:
253  setattr(smearedJets, "shiftBy", cms.double(shiftBy*varyByNsigmas))
254  smearedJetCollection = addModuleToSequence(process, smearedJets,
255  smearedJetCollectionName_parts,
256  sequence, postfix)
257 
258  return smearedJetCollection
259 
def addShiftedJetCollections
Now, jet variation for corrected METs, the default collection to use.
def addShiftedSingleParticleCollection
Up variation.