CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
tauTools.py
Go to the documentation of this file.
2 
4 from PhysicsTools.PatAlgos.tools.helpers import cloneProcessingSnippet
6 
7 # applyPostFix function adapted to unscheduled mode
8 def applyPostfix(process, label, postfix):
9  result = None
10  if hasattr(process, label+postfix):
11  result = getattr(process, label + postfix)
12  else:
13  raise ValueError("Error in <applyPostfix>: No module of name = %s attached to process !!" % (label + postfix))
14  return result
15 
16 # switch to CaloTau collection
17 def switchToCaloTau(process,
18  tauSource = cms.InputTag('caloRecoTauProducer'),
19  patTauLabel = "",
20  postfix = ""):
21  print ' switching PAT Tau input to: ', tauSource
22 
23  applyPostfix(process, "tauMatch" + patTauLabel, postfix).src = tauSource
24  applyPostfix(process, "tauGenJetMatch"+ patTauLabel, postfix).src = tauSource
25 
26  applyPostfix(process, "patTaus" + patTauLabel, postfix).tauSource = tauSource
27  applyPostfix(process, "patTaus" + patTauLabel, postfix).tauIDSources = _buildIDSourcePSet('caloRecoTau', classicTauIDSources, postfix)
28 
29  ## Isolation is somewhat an issue, so we start just by turning it off
30  print "NO PF Isolation will be computed for CaloTau (this could be improved later)"
31  applyPostfix(process, "patTaus" + patTauLabel, postfix).isolation = cms.PSet()
32  applyPostfix(process, "patTaus" + patTauLabel, postfix).isoDeposits = cms.PSet()
33  applyPostfix(process, "patTaus" + patTauLabel, postfix).userIsolation = cms.PSet()
34 
35  ## adapt cleanPatTaus
36  if hasattr(process, "cleanPatTaus" + patTauLabel + postfix):
37  getattr(process, "cleanPatTaus" + patTauLabel + postfix).preselection = \
38  'tauID("leadingTrackFinding") > 0.5 & tauID("leadingTrackPtCut") > 0.5' \
39  + ' & tauID("byIsolation") > 0.5 & tauID("againstElectron") > 0.5 & (signalTracks.size() = 1 | signalTracks.size() = 3)'
40 
41 def _buildIDSourcePSet(tauType, idSources, postfix =""):
42  """ Build a PSet defining the tau ID sources to embed into the pat::Tau """
43  output = cms.PSet()
44  for label, discriminator in idSources:
45  if ":" in discriminator:
46  discr = discriminator.split(":")
47  setattr(output, label, cms.InputTag(tauType + discr[0] + postfix + ":" + discr[1]))
48  else:
49  setattr(output, label, cms.InputTag(tauType + discriminator + postfix))
50  return output
51 
52 def _switchToPFTau(process,
53  tauSource,
54  pfTauType,
55  idSources,
56  patTauLabel = "",
57  postfix = ""):
58  """internal auxiliary function to switch to **any** PFTau collection"""
59  print ' switching PAT Tau input to: ', tauSource
60 
61  applyPostfix(process, "tauMatch" + patTauLabel, postfix).src = tauSource
62  applyPostfix(process, "tauGenJetMatch" + patTauLabel, postfix).src = tauSource
63 
64  applyPostfix(process, "tauIsoDepositPFCandidates" + patTauLabel, postfix).src = tauSource
65  applyPostfix(process, "tauIsoDepositPFCandidates" + patTauLabel, postfix).ExtractorPSet.tauSource = tauSource
66  applyPostfix(process, "tauIsoDepositPFChargedHadrons" + patTauLabel, postfix).src = tauSource
67  applyPostfix(process, "tauIsoDepositPFChargedHadrons" + patTauLabel, postfix).ExtractorPSet.tauSource = tauSource
68  applyPostfix(process, "tauIsoDepositPFNeutralHadrons" + patTauLabel, postfix).src = tauSource
69  applyPostfix(process, "tauIsoDepositPFNeutralHadrons" + patTauLabel, postfix).ExtractorPSet.tauSource = tauSource
70  applyPostfix(process, "tauIsoDepositPFGammas" + patTauLabel, postfix).src = tauSource
71  applyPostfix(process, "tauIsoDepositPFGammas" + patTauLabel, postfix).ExtractorPSet.tauSource = tauSource
72 
73  applyPostfix(process, "patTaus" + patTauLabel, postfix).tauSource = tauSource
74  applyPostfix(process, "patTaus" + patTauLabel, postfix).tauIDSources = _buildIDSourcePSet(pfTauType, idSources, postfix)
75 
76  if hasattr(process, "cleanPatTaus" + patTauLabel + postfix):
77  getattr(process, "cleanPatTaus" + patTauLabel + postfix).preselection = \
78  'tauID("leadingTrackFinding") > 0.5 & tauID("leadingPionPtCut") > 0.5 & tauID("byIsolationUsingLeadingPion") > 0.5' \
79  + ' & tauID("againstMuon") > 0.5 & tauID("againstElectron") > 0.5' \
80  + ' & (signalPFChargedHadrCands.size() = 1 | signalPFChargedHadrCands.size() = 3)'
81 
82 # Name mapping for classic tau ID sources (present for fixed and shrinkingCones)
83 classicTauIDSources = [
84  ("leadingTrackFinding", "DiscriminationByLeadingTrackFinding"),
85  ("leadingTrackPtCut", "DiscriminationByLeadingTrackPtCut"),
86  ("trackIsolation", "DiscriminationByTrackIsolation"),
87  ("ecalIsolation", "DiscriminationByECALIsolation"),
88  ("byIsolation", "DiscriminationByIsolation"),
89  ("againstElectron", "DiscriminationAgainstElectron"),
90  ("againstMuon", "DiscriminationAgainstMuon") ]
91 
92 classicPFTauIDSources = [
93  ("leadingPionPtCut", "DiscriminationByLeadingPionPtCut"),
94  ("trackIsolationUsingLeadingPion", "DiscriminationByTrackIsolationUsingLeadingPion"),
95  ("ecalIsolationUsingLeadingPion", "DiscriminationByECALIsolationUsingLeadingPion"),
96  ("byIsolationUsingLeadingPion", "DiscriminationByIsolationUsingLeadingPion")]
97 
98 # Hadron-plus-strip(s) (HPS) Tau Discriminators
99 hpsTauIDSources = [
100  ("decayModeFinding", "DiscriminationByDecayModeFinding"),
101  ("byLooseIsolation", "DiscriminationByLooseIsolation"),
102  ("byVLooseCombinedIsolationDeltaBetaCorr", "DiscriminationByVLooseCombinedIsolationDBSumPtCorr"),
103  ("byLooseCombinedIsolationDeltaBetaCorr", "DiscriminationByLooseCombinedIsolationDBSumPtCorr"),
104  ("byMediumCombinedIsolationDeltaBetaCorr", "DiscriminationByMediumCombinedIsolationDBSumPtCorr"),
105  ("byTightCombinedIsolationDeltaBetaCorr", "DiscriminationByTightCombinedIsolationDBSumPtCorr"),
106  ("byCombinedIsolationDeltaBetaCorrRaw", "DiscriminationByRawCombinedIsolationDBSumPtCorr"),
107  ("byLooseCombinedIsolationDeltaBetaCorr3Hits", "DiscriminationByLooseCombinedIsolationDBSumPtCorr3Hits"),
108  ("byMediumCombinedIsolationDeltaBetaCorr3Hits", "DiscriminationByMediumCombinedIsolationDBSumPtCorr3Hits"),
109  ("byTightCombinedIsolationDeltaBetaCorr3Hits", "DiscriminationByTightCombinedIsolationDBSumPtCorr3Hits"),
110  ("byCombinedIsolationDeltaBetaCorrRaw3Hits", "DiscriminationByRawCombinedIsolationDBSumPtCorr3Hits"),
111  ("byIsolationMVAraw", "DiscriminationByIsolationMVAraw"),
112  ("byLooseIsolationMVA", "DiscriminationByLooseIsolationMVA"),
113  ("byMediumIsolationMVA", "DiscriminationByMediumIsolationMVA"),
114  ("byTightIsolationMVA", "DiscriminationByTightIsolationMVA"),
115  ("againstElectronLoose", "DiscriminationByLooseElectronRejection"),
116  ("againstElectronMedium", "DiscriminationByMediumElectronRejection"),
117  ("againstElectronTight", "DiscriminationByTightElectronRejection"),
118  ("againstElectronMVA", "DiscriminationByMVAElectronRejection"),
119  ("againstElectronMVA2raw", "DiscriminationByMVA2rawElectronRejection"),
120  ("againstElectronMVA2category", "DiscriminationByMVA2rawElectronRejection:category"),
121  ("againstElectronVLooseMVA2", "DiscriminationByMVA2VLooseElectronRejection"),
122  ("againstElectronLooseMVA2", "DiscriminationByMVA2LooseElectronRejection"),
123  ("againstElectronMediumMVA2", "DiscriminationByMVA2MediumElectronRejection"),
124  ("againstElectronTightMVA2", "DiscriminationByMVA2TightElectronRejection"),
125  ("againstElectronMVA3raw", "DiscriminationByMVA3rawElectronRejection"),
126  ("againstElectronMVA3category", "DiscriminationByMVA3rawElectronRejection:category"),
127  ("againstElectronLooseMVA3", "DiscriminationByMVA3LooseElectronRejection"),
128  ("againstElectronMediumMVA3", "DiscriminationByMVA3MediumElectronRejection"),
129  ("againstElectronTightMVA3", "DiscriminationByMVA3TightElectronRejection"),
130  ("againstElectronDeadECAL", "DiscriminationByDeadECALElectronRejection"),
131  ("againstMuonLoose", "DiscriminationByLooseMuonRejection"),
132  ("againstMuonMedium", "DiscriminationByMediumMuonRejection"),
133  ("againstMuonTight", "DiscriminationByTightMuonRejection"),
134  ("againstMuonLoose2", "DiscriminationByLooseMuonRejection2"),
135  ("againstMuonMedium2", "DiscriminationByMediumMuonRejection2"),
136  ("againstMuonTight2", "DiscriminationByTightMuonRejection2"),
137  ("againstMuonLoose3", "DiscriminationByLooseMuonRejection3"),
138  ("againstMuonTight3", "DiscriminationByTightMuonRejection3")
139  ]
140 
141 # switch to PFTau collection produced for fixed dR = 0.07 signal cone size
142 def switchToPFTauFixedCone(process,
143  tauSource = cms.InputTag('fixedConePFTauProducer'),
144  patTauLabel = "",
145  postfix = ""):
146  fixedConeIDSources = copy.copy(classicTauIDSources)
147  fixedConeIDSources.extend(classicPFTauIDSources)
148 
149  _switchToPFTau(process, tauSource, 'fixedConePFTau', fixedConeIDSources,
150  patTauLabel = patTauLabel, postfix = postfix)
151 
152 # switch to PFTau collection produced for shrinking signal cone of size dR = 5.0/Et(PFTau)
153 def switchToPFTauShrinkingCone(process,
154  tauSource = cms.InputTag('shrinkingConePFTauProducer'),
155  patTauLabel = "",
156  postfix = ""):
157  shrinkingIDSources = copy.copy(classicTauIDSources)
158  shrinkingIDSources.extend(classicPFTauIDSources)
159 
160  _switchToPFTau(process, tauSource, 'shrinkingConePFTau', shrinkingIDSources,
161  patTauLabel = patTauLabel, postfix = postfix)
162 
163 # switch to hadron-plus-strip(s) (HPS) PFTau collection
164 def switchToPFTauHPS(process,
165  tauSource = cms.InputTag('hpsPFTauProducer'),
166  patTauLabel = "",
167  jecLevels = [],
168  postfix = ""):
169 
170  _switchToPFTau(process, tauSource, 'hpsPFTau', hpsTauIDSources,
171  patTauLabel = patTauLabel, postfix = postfix)
172 
173  ## adapt cleanPatTaus
174  if hasattr(process, "cleanPatTaus" + patTauLabel + postfix):
175  getattr(process, "cleanPatTaus" + patTauLabel + postfix).preselection = \
176  'pt > 15 & abs(eta) < 2.3 & tauID("decayModeFinding") > 0.5 & tauID("byLooseIsolation") > 0.5' \
177  + ' & tauID("againstMuonTight") > 0.5 & tauID("againstElectronLoose") > 0.5'
178 
179 # Select switcher by string
180 def switchToPFTauByType(process,
181  pfTauType = None,
182  tauSource = cms.InputTag('hpsPFTauProducer'),
183  patTauLabel = "",
184  postfix = "" ):
185  mapping = {
186  'shrinkingConePFTau' : switchToPFTauShrinkingCone,
187  'fixedConePFTau' : switchToPFTauFixedCone,
188  'hpsPFTau' : switchToPFTauHPS,
189  'caloRecoTau' : switchToCaloTau
190  }
191  if not pfTauType in mapping.keys():
192  raise ValueError("Error in <switchToPFTauByType>: Undefined pfTauType = %s !!" % pfTauType)
193 
194  mapping[pfTauType](process, tauSource = tauSource,
195  patTauLabel = patTauLabel, postfix = postfix)
196 
198 
199  """ Add a new collection of taus. Takes the configuration from the
200  already configured standard tau collection as starting point;
201  replaces before calling addTauCollection will also affect the
202  new tau collections
203  """
204  _label='addTauCollection'
205  _defaultParameters=dicttypes.SortedKeysDict()
206  def __init__(self):
207  ConfigToolBase.__init__(self)
208  self.addParameter(self._defaultParameters, 'tauCollection',
209  self._defaultValue, 'Input tau collection', cms.InputTag)
210  self.addParameter(self._defaultParameters, 'algoLabel',
211  self._defaultValue, "label to indicate the tau algorithm (e.g.'hps')", str)
212  self.addParameter(self._defaultParameters, 'typeLabel',
213  self._defaultValue, "label to indicate the type of constituents (either 'PFTau' or 'Tau')", str)
214  self.addParameter(self._defaultParameters, 'doPFIsoDeposits',
215  True, "run sequence for computing particle-flow based IsoDeposits")
216  self.addParameter(self._defaultParameters, 'standardAlgo',
217  "hps", "standard algorithm label of the collection from which the clones " \
218  + "for the new tau collection will be taken from " \
219  + "(note that this tau collection has to be available in the event before hand)")
220  self.addParameter(self._defaultParameters, 'standardType',
221  "PFTau", "standard constituent type label of the collection from which the clones " \
222  + " for the new tau collection will be taken from "\
223  + "(note that this tau collection has to be available in the event before hand)")
224 
225  self._parameters=copy.deepcopy(self._defaultParameters)
226  self._comment = ""
227 
229  return self._defaultParameters
230 
231  def __call__(self,process,
232  tauCollection = None,
233  algoLabel = None,
234  typeLabel = None,
235  doPFIsoDeposits = None,
236  jetCorrLabel = None,
237  standardAlgo = None,
238  standardType = None):
239 
240  if tauCollection is None:
241  tauCollection = self._defaultParameters['tauCollection'].value
242  if algoLabel is None:
243  algoLabel = self._defaultParameters['algoLabel'].value
244  if typeLabel is None:
245  typeLabel = self._defaultParameters['typeLabel'].value
246  if doPFIsoDeposits is None:
247  doPFIsoDeposits = self._defaultParameters['doPFIsoDeposits'].value
248  if standardAlgo is None:
249  standardAlgo = self._defaultParameters['standardAlgo'].value
250  if standardType is None:
251  standardType = self._defaultParameters['standardType'].value
252 
253  self.setParameter('tauCollection', tauCollection)
254  self.setParameter('algoLabel', algoLabel)
255  self.setParameter('typeLabel', typeLabel)
256  self.setParameter('doPFIsoDeposits', doPFIsoDeposits)
257  self.setParameter('standardAlgo', standardAlgo)
258  self.setParameter('standardType', standardType)
259 
260  self.apply(process)
261 
262  def toolCode(self, process):
263  tauCollection = self._parameters['tauCollection'].value
264  algoLabel = self._parameters['algoLabel'].value
265  typeLabel = self._parameters['typeLabel'].value
266  doPFIsoDeposits = self._parameters['doPFIsoDeposits'].value
267  standardAlgo = self._parameters['standardAlgo'].value
268  standardType = self._parameters['standardType'].value
269 
270  ## disable computation of particle-flow based IsoDeposits
271  ## in case tau is of CaloTau type
272  if typeLabel == 'Tau':
273  print "NO PF Isolation will be computed for CaloTau (this could be improved later)"
274  doPFIsoDeposits = False
275 
276  ## create old module label from standardAlgo
277  ## and standardType and return
278  def oldLabel(prefix = ''):
279  if prefix == '':
280  return "patTaus"
281  else:
282  return prefix + "PatTaus"
283 
284  ## capitalize first character of appended part
285  ## when creating new module label
286  ## (giving e.g. "patTausCaloRecoTau")
287  def capitalize(label):
288  return label[0].capitalize() + label[1:]
289 
290  ## create new module label from old module
291  ## label and return
292  def newLabel(oldLabel):
293  newLabel = oldLabel
294  if ( oldLabel.find(standardAlgo) >= 0 and oldLabel.find(standardType) >= 0 ):
295  oldLabel = oldLabel.replace(standardAlgo, algoLabel).replace(standardType, typeLabel)
296  else:
297  oldLabel = oldLabel + capitalize(algoLabel + typeLabel)
298  return oldLabel
299 
300  ## clone module and add it to the patDefaultSequence
301  def addClone(hook, **replaceStatements):
302  ## create a clone of the hook with corresponding
303  ## parameter replacements
304  newModule = getattr(process, hook).clone(**replaceStatements)
305 
306  ## clone module for computing particle-flow IsoDeposits
307  def addPFIsoDepositClone(hook, **replaceStatements):
308  newModule = getattr(process, hook).clone(**replaceStatements)
309  newModuleIsoDepositExtractor = getattr(newModule, "ExtractorPSet")
310  setattr(newModuleIsoDepositExtractor, "tauSource", getattr(newModule, "src"))
311 
312  ## add a clone of patTaus
313  addClone(oldLabel(), tauSource = tauCollection)
314 
315  ## add a clone of selectedPatTaus
316  addClone(oldLabel('selected'), src = cms.InputTag(newLabel(oldLabel())))
317 
318  ## add a clone of cleanPatTaus
319  addClone(oldLabel('clean'), src=cms.InputTag(newLabel(oldLabel('selected'))))
320 
321  ## get attributes of new module
322  newTaus = getattr(process, newLabel(oldLabel()))
323 
324  ## add a clone of gen tau matching
325  addClone('tauMatch', src = tauCollection)
326  addClone('tauGenJetMatch', src = tauCollection)
327 
328  ## add a clone of IsoDeposits computed based on particle-flow
329  if doPFIsoDeposits:
330  addPFIsoDepositClone('tauIsoDepositPFCandidates', src = tauCollection)
331  addPFIsoDepositClone('tauIsoDepositPFChargedHadrons', src = tauCollection)
332  addPFIsoDepositClone('tauIsoDepositPFNeutralHadrons', src = tauCollection)
333  addPFIsoDepositClone('tauIsoDepositPFGammas', src = tauCollection)
334 
335  ## fix label for input tag
336  def fixInputTag(x):
337  x.setModuleLabel(newLabel(x.moduleLabel))
338 
339  ## provide patTau inputs with individual labels
340  fixInputTag(newTaus.genParticleMatch)
341  fixInputTag(newTaus.genJetMatch)
342  fixInputTag(newTaus.isoDeposits.pfAllParticles)
343  fixInputTag(newTaus.isoDeposits.pfNeutralHadron)
344  fixInputTag(newTaus.isoDeposits.pfChargedHadron)
345  fixInputTag(newTaus.isoDeposits.pfGamma)
346  fixInputTag(newTaus.userIsolation.pfAllParticles.src)
347  fixInputTag(newTaus.userIsolation.pfNeutralHadron.src)
348  fixInputTag(newTaus.userIsolation.pfChargedHadron.src)
349  fixInputTag(newTaus.userIsolation.pfGamma.src)
350 
351  ## set discriminators
352  ## (using switchTauCollection functions)
353  oldTaus = getattr(process, oldLabel())
354  if typeLabel == 'Tau':
355  switchToCaloTau(process,
356  tauSource = getattr(newTaus, "tauSource"),
357  patTauLabel = capitalize(algoLabel + typeLabel))
358  else:
359  switchToPFTauByType(process, pfTauType = algoLabel + typeLabel,
360  tauSource = getattr(newTaus, "tauSource"),
361  patTauLabel = capitalize(algoLabel + typeLabel))
362 
363 addTauCollection=AddTauCollection()
def switchToPFTauFixedCone
Definition: tauTools.py:145
def applyPostfix
Definition: tauTools.py:8
def replace
Definition: linker.py:10
def _switchToPFTau
Definition: tauTools.py:57
def switchToCaloTau
Definition: tauTools.py:20
def _buildIDSourcePSet
Definition: tauTools.py:41
def switchToPFTauHPS
Definition: tauTools.py:168
TEveGeoShape * clone(const TEveElement *element, TEveElement *parent)
Definition: eve_macros.cc:135
def switchToPFTauShrinkingCone
Definition: tauTools.py:156
def switchToPFTauByType
Definition: tauTools.py:184