ATLAS Offline Software
TauAnalysisConfig.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2 
3 # AnaAlgorithm import(s):
4 from AnalysisAlgorithmsConfig.ConfigAccumulator import DataType
5 from AnalysisAlgorithmsConfig.ConfigBlock import ConfigBlock
6 from AthenaCommon.Logging import logging
7 from AthenaConfiguration.Enums import LHCPeriod
8 from Campaigns.Utils import Campaign
9 
10 from TriggerAnalysisAlgorithms.TriggerAnalysisSFConfig import trigger_set
11 
12 
13 class TauCalibrationConfig (ConfigBlock):
14  """the ConfigBlock for the tau four-momentum correction"""
15 
16  def __init__ (self) :
17  super (TauCalibrationConfig, self).__init__ ()
18  self.setBlockName('Taus')
19  self.addOption ('inputContainer', '', type=str,
20  info="select tau input container, by default set to TauJets")
21  self.addOption ('containerName', '', type=str,
22  noneAction='error',
23  info="the name of the output container after calibration.")
24  self.addOption ('postfix', '', type=str,
25  info="a postfix to apply to decorations and algorithm names. "
26  "Typically not needed here since the calibration is common to "
27  "all taus.")
28  self.addOption ('rerunTruthMatching', True, type=bool,
29  info="whether to rerun truth matching (sets up an instance of "
30  "CP::TauTruthMatchingAlg). The default is True.")
31  self.addOption ('decorateTruth', False, type=bool,
32  info="decorate truth particle information on the reconstructed one")
33  self.addOption ('decorateExtraVariables', True, type=bool,
34  info="decorate extra variables for the reconstructed tau")
35 
36  def instanceName (self) :
37  """Return the instance name for this block"""
38  return self.containerName + self.postfix
39 
40  def makeAlgs (self, config) :
41 
42  # protection for EleRM taus, which are available only from 2024 onward
43  if 'EleRM' in self.inputContainer:
44  if config.dataType() is DataType.Data and config.dataYear() <= 2023:
45  raise RuntimeError("EleRM taus are only available from 2024 dataset onward")
46  elif config.dataType() is not DataType.Data and config.campaign() <= Campaign.MC23d:
47  raise RuntimeError("EleRM taus are only available from 2024 dataset onward")
48 
49  postfix = self.postfix
50  if postfix != '' and postfix[0] != '_' :
51  postfix = '_' + postfix
52 
53  inputContainer = "AnalysisTauJets" if config.isPhyslite() else "TauJets"
54  if self.inputContainer:
55  inputContainer = self.inputContainer
56  config.setSourceName (self.containerName, inputContainer)
57 
58  # Set up the tau truth matching algorithm:
59  if self.rerunTruthMatching and config.dataType() is not DataType.Data:
60  alg = config.createAlgorithm( 'CP::TauTruthMatchingAlg',
61  'TauTruthMatchingAlg' )
62  config.addPrivateTool( 'matchingTool',
63  'TauAnalysisTools::TauTruthMatchingTool' )
64  alg.matchingTool.TruthJetContainerName = 'AntiKt4TruthDressedWZJets'
65  alg.taus = config.readName (self.containerName)
66  alg.preselection = config.getPreselection (self.containerName, '')
67 
68  # decorate truth tau information on the reconstructed object:
69  if self.decorateTruth and config.dataType() is not DataType.Data:
70  alg = config.createAlgorithm( 'CP::TauTruthDecorationsAlg',
71  'TauTruthDecorationsAlg',
72  reentrant=True )
73  alg.taus = config.readName (self.containerName)
74  alg.doubleDecorations = ['pt_vis', 'pt_invis', 'eta_vis', 'eta_invis', 'phi_vis', 'phi_invis', 'm_vis', 'm_invis']
75  alg.floatDecorations = []
76  alg.intDecorations = ['pdgId']
77  alg.unsignedIntDecorations = ['classifierParticleOrigin', 'classifierParticleType']
78  alg.charDecorations = ['IsHadronicTau']
79  alg.prefix = 'truth_'
80 
81  # these are "_ListHelper" objects, and not "list", need to copy to lists to allow concatenate
82  for var in ['DecayMode', 'ParticleType', 'PartonTruthLabelID'] + alg.doubleDecorations[:] + alg.floatDecorations[:] + alg.intDecorations[:] + alg.unsignedIntDecorations[:] + alg.charDecorations[:]:
83  branchName = alg.prefix + var
84  if 'classifierParticle' in var:
85  branchOutput = alg.prefix + var.replace('classifierParticle', '').lower()
86  else:
87  branchOutput = branchName
88  config.addOutputVar (self.containerName, branchName, branchOutput, noSys=True)
89 
90  # Decorate extra variables
91  if self.decorateExtraVariables:
92  alg = config.createAlgorithm( 'CP::TauExtraVariablesAlg',
93  'TauExtraVariablesAlg',
94  reentrant=True )
95  alg.taus = config.readName (self.containerName)
96 
97  # Set up the tau 4-momentum smearing algorithm:
98  alg = config.createAlgorithm( 'CP::TauSmearingAlg', 'TauSmearingAlg' )
99  config.addPrivateTool( 'smearingTool', 'TauAnalysisTools::TauSmearingTool' )
100  alg.smearingTool.useFastSim = config.dataType() is DataType.FastSim
101  alg.smearingTool.Campaign = "mc23" if config.geometry() is LHCPeriod.Run3 else "mc20"
102  alg.taus = config.readName (self.containerName)
103  alg.tausOut = config.copyName (self.containerName)
104  alg.preselection = config.getPreselection (self.containerName, '')
105 
106  # Additional decorations
107  alg = config.createAlgorithm( 'CP::AsgEnergyDecoratorAlg', 'EnergyDecorator' )
108  alg.particles = config.readName (self.containerName)
109 
110  config.addOutputVar (self.containerName, 'pt', 'pt')
111  config.addOutputVar (self.containerName, 'eta', 'eta', noSys=True)
112  config.addOutputVar (self.containerName, 'phi', 'phi', noSys=True)
113  config.addOutputVar (self.containerName, 'e_%SYS%', 'e')
114  config.addOutputVar (self.containerName, 'charge', 'charge', noSys=True)
115  config.addOutputVar (self.containerName, 'NNDecayMode', 'NNDecayMode', noSys=True)
116  config.addOutputVar (self.containerName, 'passTATTauMuonOLR', 'passTATTauMuonOLR', noSys=True)
117  config.addOutputVar (self.containerName, 'TESCompatibility', 'TESCompatibility')
118  if self.decorateExtraVariables:
119  config.addOutputVar (self.containerName, 'nTracksCharged', 'nTracksCharged', noSys=True)
120 
121 
122 class TauWorkingPointConfig (ConfigBlock) :
123  """the ConfigBlock for the tau working point
124 
125  This may at some point be split into multiple blocks (16 Mar 22)."""
126 
127  def __init__ (self) :
128  super (TauWorkingPointConfig, self).__init__ ()
129  self.addOption ('containerName', '', type=str,
130  noneAction='error',
131  info="the name of the input container.")
132  self.addOption ('selectionName', '', type=str,
133  noneAction='error',
134  info="the name of the tau-jet selection to define (e.g. tight or "
135  "loose).")
136  self.addOption ('postfix', None, type=str,
137  info="a postfix to apply to decorations and algorithm names. "
138  "Typically not needed here as selectionName is used internally.")
139  self.addOption ('quality', None, type=str,
140  info="the ID WP (string) to use. Supported ID WPs: Tight, Medium, "
141  "Loose, VeryLoose, Baseline, BaselineForFakes.")
142  self.addOption ('use_eVeto', False, type=bool,
143  info="use selection with or without eVeto combined with tauID "
144  "recommendations: set it to True if electron mis-reconstructed as tau is a large background for your analysis")
145  self.addOption ('use_muonOLR', False, type=bool,
146  info="use selection with or without muonOLR with TauID "
147  "recommendations: set it to True if muon mis-reconstructed as tau is a large background for your analysis")
148  self.addOption ('useGNTau', False, type=bool,
149  info="use GNTau based ID instead of RNNTau ID "
150  "recommendations: that's new experimental feature and might come default soon",
151  expertMode=True)
152  self.addOption ('dropPtCut', False, type=bool,
153  info="select taus without explicit min Pt cut. For PHYS/PHYSLITE, this would mean selecting taus starting from 13 GeV "
154  "recommendations: that's experimental feature and not supported for all combinations of ID/eVeto WPs",
155  expertMode=True)
156  self.addOption ('useLowPt', False, type=bool,
157  info="select taus starting from 15 GeV instead of the default 20 GeV cut "
158  "recommendations: that's experimental feature and not supported for all combinations of ID/eVeto WPs",
159  expertMode=True)
160  self.addOption ('useSelectionConfigFile', True, type=bool,
161  info="use pre-defined configuration files for selecting taus "
162  "recommendations: set this to False only if you want to test/optimise the tau selection for selections not already provided through config files")
163  self.addOption ('manual_sel_minpt', 20.0, type=float,
164  info="minimum pt cut used for tau selection when useSelectionConfigFile is set to false")
165  self.addOption ('manual_sel_absetaregion', [0, 1.37, 1.52, 2.5], type=list,
166  info="eta regions cut used for tau selection when useSelectionConfigFile is set to false")
167  self.addOption ('manual_sel_abscharges', [1,], type=list,
168  info="charge of the tau cut used for tau selection when useSelectionConfigFile is set to false")
169  self.addOption ('manual_sel_ntracks', [1,3], type=list,
170  info="number of tau tracks used for tau selection when useSelectionConfigFile is set to false")
171  self.addOption ('manual_sel_minrnnscore', -1, type=float,
172  info="minimum rnn score cut used for tau selection when useSelectionConfigFile is set to false")
173  self.addOption ('manual_sel_mingntauscore', -1, type=float,
174  info="minimum gntau score selection when useSelectionConfigFile is set to false")
175  self.addOption ('manual_sel_rnnwp', None, type=str,
176  info="rnn working point used for tau selection when useSelectionConfigFile is set to false")
177  self.addOption ('manual_sel_gntauwp', None, type=str,
178  info="gntau working point used for tau selection when useSelectionConfigFile is set to false")
179  self.addOption ('manual_sel_evetowp', None, type=str,
180  info="eveto working point used for tau selection when useSelectionConfigFile is set to false")
181  self.addOption ('manual_sel_muonolr', False, type=bool,
182  info="use muonolr used for tau selection when useSelectionConfigFile is set to false")
183  self.addOption ('noEffSF', False, type=bool,
184  info="disables the calculation of efficiencies and scale factors. "
185  "Experimental! only useful to test a new WP for which scale "
186  "factors are not available. The default is False.",
187  expertMode=True)
188  self.addOption ('saveDetailedSF', True, type=bool,
189  info="save all the independent detailed object scale factors. "
190  "The default is True.")
191  self.addOption ('saveCombinedSF', False, type=bool,
192  info="save the combined object scale factor. "
193  "The default is False.")
194  self.addOption ('addSelectionToPreselection', True, type=bool,
195  info="whether to retain only tau-jets satisfying the working point "
196  "requirements. The default is True.")
197 
198  def instanceName (self) :
199  """Return the instance name for this block"""
200  if self.postfix is not None:
201  return self.containerName + '_' + self.selectionName + self.postfix
202  else:
203  return self.containerName + '_' + self.selectionName
204 
205  def makeAlgs (self, config) :
206 
207  selectionPostfix = self.selectionName
208  if selectionPostfix != '' and selectionPostfix[0] != '_' :
209  selectionPostfix = '_' + selectionPostfix
210 
211  postfix = self.postfix
212  if postfix is None :
213  postfix = self.selectionName
214  if postfix != '' and postfix[0] != '_' :
215  postfix = '_' + postfix
216 
217  # do tau seletion through external txt config file
218  if self.useSelectionConfigFile:
219  nameFormat = 'TauAnalysisAlgorithms/tau_selection_'
220  if self.dropPtCut:
221  nameFormat = nameFormat + 'nopt_'
222  if self.useLowPt:
223  nameFormat = nameFormat + 'lowpt_'
224  if self.useGNTau:
225  nameFormat = nameFormat + 'gntau_'
226  nameFormat = nameFormat + '{}_'
227  if self.use_eVeto:
228  nameFormat = nameFormat + 'eleid'
229  else:
230  nameFormat = nameFormat + 'noeleid'
231  if self.use_muonOLR:
232  nameFormat = nameFormat + '_muonolr'
233  nameFormat = nameFormat + '.conf'
234 
235  if self.quality not in ['Tight', 'Medium', 'Loose', 'VeryLoose', 'Baseline', 'BaselineForFakes'] :
236  raise ValueError ("invalid tau quality: \"" + self.quality +
237  "\", allowed values are Tight, Medium, Loose, " +
238  "VeryLoose, Baseline, BaselineForFakes")
239 
240  # Set up the algorithm selecting taus:
241  alg = config.createAlgorithm( 'CP::AsgSelectionAlg', 'TauSelectionAlg' )
242  config.addPrivateTool( 'selectionTool', 'TauAnalysisTools::TauSelectionTool' )
243  if self.useSelectionConfigFile:
244  inputfile = nameFormat.format(self.quality.lower())
245  alg.selectionTool.ConfigPath = inputfile
246  else:
247  #build selection from user handmade selection
248  from ROOT import TauAnalysisTools
249  selectioncuts = TauAnalysisTools.SelectionCuts
250  alg.selectionTool.ConfigPath = ""
251  alg.selectionTool.SelectionCuts = int(selectioncuts.CutPt |
252  selectioncuts.CutAbsEta |
253  selectioncuts.CutAbsCharge |
254  selectioncuts.CutNTrack |
255  selectioncuts.CutJetRNNScoreSigTrans |
256  selectioncuts.CutGNTauScoreSigTrans |
257  selectioncuts.CutJetIDWP |
258  selectioncuts.CutEleIDWP |
259  selectioncuts.CutMuonOLR)
260 
261  alg.selectionTool.PtMin = self.manual_sel_minpt
262  alg.selectionTool.AbsEtaRegion = self.manual_sel_absetaregion
263  alg.selectionTool.AbsCharges = self.manual_sel_abscharges
264  alg.selectionTool.NTracks = self.manual_sel_ntracks
265  alg.selectionTool.JetRNNSigTransMin = self.manual_sel_minrnnscore
266  alg.selectionTool.GNTauSigTransMin = self.manual_sel_mingntauscore
267  #cross-check that min rnn score and min gntau score are not both set at the same time
268  if self.manual_sel_minrnnscore != -1 and self.manual_sel_mingntauscore != -1:
269  raise RuntimeError("manual_sel_minrnnscore and manual_sel_mingntauscore have been both set; please choose only one type of ID: RNN or GNTau, not both")
270  # working point following the Enums from https://gitlab.cern.ch/atlas/athena/-/blob/main/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/Enums.h
271  if self.manual_sel_rnnwp is None:
272  alg.selectionTool.JetIDWP = 1
273  elif self.manual_sel_rnnwp == "veryloose":
274  alg.selectionTool.JetIDWP = 6
275  elif self.manual_sel_rnnwp == "loose":
276  alg.selectionTool.JetIDWP = 7
277  elif self.manual_sel_rnnwp == "medium":
278  alg.selectionTool.JetIDWP = 8
279  elif self.manual_sel_rnnwp == "tight":
280  alg.selectionTool.JetIDWP = 9
281  else:
282  raise ValueError ("invalid RNN TauID WP: \"" + self.manual_sel_rnnwp + "\". Allowed values are None, veryloose, loose, medium, tight")
283 
284  # cross-check that min rnn score and RNN WPs are not set at the same time
285  if self.manual_sel_minrnnscore != -1 and self.manual_sel_rnnwp is not None:
286  raise RuntimeError("manual_sel_minrnnscore and manual_sel_rnnwp have been both set; please set only one of them")
287 
288  # working point following the Enums from https://gitlab.cern.ch/atlas/athena/-/blob/main/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/Enums.h
289  if self.manual_sel_gntauwp is None:
290  alg.selectionTool.JetIDWP = 1
291  elif self.manual_sel_gntauwp == "veryloose":
292  alg.selectionTool.JetIDWP = 10
293  elif self.manual_sel_gntauwp == "loose":
294  alg.selectionTool.JetIDWP = 11
295  elif self.manual_sel_gntauwp == "medium":
296  alg.selectionTool.JetIDWP = 12
297  elif self.manual_sel_gntauwp == "tight":
298  alg.selectionTool.JetIDWP = 13
299  else:
300  raise ValueError ("invalid GNN Tau ID WP: \"" + self.manual_sel_gntauwp + "\". Allowed values are None, veryloose, loose, medium, tight")
301 
302  # cross-check that min gntau score and GNTau WPs are not set at the same time
303  if self.manual_sel_mingntauscore != -1 and self.manual_sel_gntauwp is not None:
304  raise RuntimeError("manual_sel_mingntauscore and manual_sel_gntauwp have been both set; please set only one of them")
305 
306  # working point following the Enums from https://gitlab.cern.ch/atlas/athena/-/blob/main/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/Enums.h
307  if self.manual_sel_evetowp is None:
308  alg.selectionTool.EleIDWP = 1
309  elif self.manual_sel_evetowp == "loose":
310  alg.selectionTool.EleIDWP = 2
311  elif self.manual_sel_evetowp == "medium":
312  alg.selectionTool.EleIDWP = 3
313  elif self.manual_sel_evetowp == "tight":
314  alg.selectionTool.EleIDWP = 4
315  else:
316  raise ValueError ("invalid eVeto WP: \"" + self.manual_sel_evetowp + "\". Allowed values are None, loose, medium, tight")
317 
318  # set MuonOLR option:
319  alg.selectionTool.MuonOLR = self.manual_sel_muonolr
320 
321  alg.selectionDecoration = 'selected_tau' + selectionPostfix + ',as_char'
322  alg.particles = config.readName (self.containerName)
323  alg.preselection = config.getPreselection (self.containerName, self.selectionName)
324  config.addSelection (self.containerName, self.selectionName, alg.selectionDecoration,
325  preselection=self.addSelectionToPreselection)
326 
327  sfList = []
328  # Set up the algorithm calculating the efficiency scale factors for the
329  # taus:
330  if config.dataType() is not DataType.Data and not self.noEffSF:
331  log = logging.getLogger('TauJetSFConfig')
332  # need multiple instances of the TauEfficiencyCorrectionTool
333  # 1) Reco 2) TauID, 3) eVeto for fake tau 4) eVeto for true tau
334  # 3) and 4) are optional if eVeto is used in TauSelectionTool
335 
336  # TauEfficiencyCorrectionTool for Reco, this should be always enabled
337  alg = config.createAlgorithm( 'CP::TauEfficiencyCorrectionsAlg',
338  'TauEfficiencyCorrectionsAlgReco' )
339  config.addPrivateTool( 'efficiencyCorrectionsTool',
340  'TauAnalysisTools::TauEfficiencyCorrectionsTool' )
341  alg.efficiencyCorrectionsTool.EfficiencyCorrectionTypes = [0]
342  alg.efficiencyCorrectionsTool.Campaign = "mc23" if config.geometry() is LHCPeriod.Run3 else "mc20"
343  alg.efficiencyCorrectionsTool.useFastSim = config.dataType() is DataType.FastSim
344  alg.scaleFactorDecoration = 'tau_Reco_effSF' + selectionPostfix + '_%SYS%'
345  alg.outOfValidity = 2 #silent
346  alg.outOfValidityDeco = 'bad_Reco_eff' + selectionPostfix
347  alg.taus = config.readName (self.containerName)
348  alg.preselection = config.getPreselection (self.containerName, self.selectionName)
349  if self.saveDetailedSF:
350  config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
351  'Reco_effSF' + postfix)
352  sfList += [alg.scaleFactorDecoration]
353 
354  # TauEfficiencyCorrectionTool for Identification, use only in case TauID is requested in TauSelectionTool
355  if self.quality not in ('VeryLoose','Baseline','BaselineForFakes'):
356  if not self.useGNTau: # current recommendations are for RNN ID, so don't use in case of GNTau
357 
358  alg = config.createAlgorithm( 'CP::TauEfficiencyCorrectionsAlg',
359  'TauEfficiencyCorrectionsAlgID' )
360  config.addPrivateTool( 'efficiencyCorrectionsTool',
361  'TauAnalysisTools::TauEfficiencyCorrectionsTool' )
362  alg.efficiencyCorrectionsTool.EfficiencyCorrectionTypes = [4]
363  if self.quality=="Loose" or self.manual_sel_rnnwp == "loose":
364  JetIDLevel = 7
365  elif self.quality=="Medium" or self.manual_sel_rnnwp == "medium":
366  JetIDLevel = 8
367  elif self.quality=="Tight" or self.manual_sel_rnnwp == "tight":
368  JetIDLevel = 9
369  else:
370  raise ValueError ("invalid tauID: \"" + self.quality + "\". Allowed values are loose, medium, tight")
371 
372  alg.efficiencyCorrectionsTool.JetIDLevel = JetIDLevel
373  alg.efficiencyCorrectionsTool.useFastSim = config.dataType() is DataType.FastSim
374  alg.efficiencyCorrectionsTool.Campaign = "mc23" if config.geometry() is LHCPeriod.Run3 else "mc20"
375  alg.scaleFactorDecoration = 'tau_ID_effSF' + selectionPostfix + '_%SYS%'
376  alg.outOfValidity = 2 #silent
377  alg.outOfValidityDeco = 'bad_ID_eff' + selectionPostfix
378  alg.taus = config.readName (self.containerName)
379  alg.preselection = config.getPreselection (self.containerName, self.selectionName)
380  if self.saveDetailedSF:
381  config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
382  'ID_effSF' + postfix)
383  sfList += [alg.scaleFactorDecoration]
384 
385  # TauEfficiencyCorrectionTool for eVeto both on true tau and fake tau, use only in case eVeto is requested in TauSelectionTool
386  if self.use_eVeto:
387  if not self.useGNTau: # eVeto correction for fake tau are for RNN ID, so don't use them for GNTau
388  # correction for fake tau
389  alg = config.createAlgorithm( 'CP::TauEfficiencyCorrectionsAlg',
390  'TauEfficiencyCorrectionsAlgEvetoFakeTau' )
391  config.addPrivateTool( 'efficiencyCorrectionsTool',
392  'TauAnalysisTools::TauEfficiencyCorrectionsTool' )
393  alg.efficiencyCorrectionsTool.EfficiencyCorrectionTypes = [10]
394  # since all TauSelectionTool config files have loose eRNN, code only this option for now
395  alg.efficiencyCorrectionsTool.EleIDLevel = 2
396  #overwrite decision in case user selects a WP manually
397  if self.manual_sel_evetowp == "loose":
398  alg.efficiencyCorrectionsTool.EleIDLevel = 2
399  elif self.manual_sel_evetowp == "medium":
400  alg.efficiencyCorrectionsTool.EleIDLevel = 3
401 
402  alg.efficiencyCorrectionsTool.useFastSim = config.dataType() is DataType.FastSim
403  alg.efficiencyCorrectionsTool.Campaign = "mc23" if config.geometry() is LHCPeriod.Run3 else "mc20"
404  alg.scaleFactorDecoration = 'tau_EvetoFakeTau_effSF' + selectionPostfix + '_%SYS%'
405  # for 2025-prerec, eVeto recommendations are given separately for Loose and Medium RNN
406  if self.quality=="Loose" or self.manual_sel_rnnwp == "loose":
407  JetIDLevel = 7
408  elif self.quality=="Medium" or self.manual_sel_rnnwp == "medium":
409  JetIDLevel = 8
410  elif self.quality=="Tight" or self.manual_sel_rnnwp == "tight":
411  log.warning("eVeto SFs are not available for Tight WP -> fallback to Medium WP")
412  JetIDLevel = 8
413  alg.efficiencyCorrectionsTool.JetIDLevel = JetIDLevel
414  alg.outOfValidity = 2 #silent
415  alg.outOfValidityDeco = 'bad_EvetoFakeTau_eff' + selectionPostfix
416  alg.taus = config.readName (self.containerName)
417  alg.preselection = config.getPreselection (self.containerName, self.selectionName)
418  if self.saveDetailedSF:
419  config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
420  'EvetoFakeTau_effSF' + postfix)
421  sfList += [alg.scaleFactorDecoration]
422 
423  # correction for true tau
424  alg = config.createAlgorithm( 'CP::TauEfficiencyCorrectionsAlg',
425  'TauEfficiencyCorrectionsAlgEvetoTrueTau' )
426  config.addPrivateTool( 'efficiencyCorrectionsTool',
427  'TauAnalysisTools::TauEfficiencyCorrectionsTool' )
428  alg.efficiencyCorrectionsTool.EfficiencyCorrectionTypes = [8]
429  alg.efficiencyCorrectionsTool.useFastSim = config.dataType() is DataType.FastSim
430  alg.efficiencyCorrectionsTool.Campaign = "mc23" if config.geometry() is LHCPeriod.Run3 else "mc20"
431  alg.scaleFactorDecoration = 'tau_EvetoTrueTau_effSF' + selectionPostfix + '_%SYS%'
432  alg.outOfValidity = 2 #silent
433  alg.outOfValidityDeco = 'bad_EvetoTrueTau_eff' + selectionPostfix
434  alg.taus = config.readName (self.containerName)
435  alg.preselection = config.getPreselection (self.containerName, self.selectionName)
436  if self.saveDetailedSF:
437  config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
438  'EvetoTrueTau_effSF' + postfix)
439  sfList += [alg.scaleFactorDecoration]
440 
441  if self.saveCombinedSF:
442  alg = config.createAlgorithm( 'CP::AsgObjectScaleFactorAlg',
443  'TauCombinedEfficiencyScaleFactorAlg' )
444  alg.particles = config.readName (self.containerName)
445  alg.inScaleFactors = sfList
446  alg.outScaleFactor = 'effSF' + postfix + '_%SYS%'
447  config.addOutputVar (self.containerName, alg.outScaleFactor,
448  'effSF' + postfix)
449 
450 
452  def __init__ (self) :
453  super (EXPERIMENTAL_TauCombineMuonRemovalConfig, self).__init__ ()
454  self.addOption (
455  'inputTaus', 'TauJets', type=str,
456  noneAction='error',
457  info="the name of the input tau container."
458  )
459  self.addOption (
460  'inputTausMuRM', 'TauJets_MuonRM', type=str,
461  noneAction='error',
462  info="the name of the input tau container with muon removal applied."
463  )
464  self.addOption (
465  'outputTaus', 'TauJets_MuonRmCombined', type=str,
466  noneAction='error',
467  info="the name of the output tau container."
468  )
469 
470  def instanceName (self) :
471  """Return the instance name for this block"""
472  return self.outputTaus
473 
474  def makeAlgs (self, config) :
475 
476  if config.isPhyslite() :
477  raise(RuntimeError("Muon removal taus is not available in Physlite mode"))
478 
479  alg = config.createAlgorithm( 'CP::TauCombineMuonRMTausAlg', 'TauCombineMuonRMTausAlg' )
480  alg.taus = self.inputTaus
481  alg.muonrm_taus = self.inputTausMuRM
482  alg.combined_taus = self.outputTaus
483 
484 class TauTriggerAnalysisSFBlock (ConfigBlock):
485 
486  def __init__ (self) :
487  super (TauTriggerAnalysisSFBlock, self).__init__ ()
488 
489  self.addOption ('triggerChainsPerYear', {}, type=None,
490  info="a dictionary with key (string) the year and value (list of "
491  "strings) the trigger chains. The default is {} (empty dictionary).")
492  self.addOption ('tauID', '', type=str,
493  info="the tau quality WP (string) to use.")
494  self.addOption ('prefixSF', 'trigEffSF', type=str,
495  info="the decoration prefix for trigger scale factors, "
496  "the default is 'trigEffSF'")
497  self.addOption ('includeAllYearsPerRun', False, type=bool,
498  info="if True, all configured years in the LHC run will "
499  "be included in all jobs. The default is False.")
500  self.addOption ('removeHLTPrefix', True, type=bool,
501  info="remove the HLT prefix from trigger chain names, "
502  "The default is True.")
503  self.addOption ('containerName', '', type=str,
504  info="the input tau container, with a possible selection, in "
505  "the format container or container.selection.")
506 
507  def instanceName (self) :
508  """Return the instance name for this block"""
509  return self.containerName + '_' + self.prefixSF + '_' + self.tauID
510 
511  def makeAlgs (self, config) :
512 
513  if config.dataType() is not DataType.Data:
514  triggers = trigger_set(config, self.triggerChainsPerYear,
515  self.includeAllYearsPerRun)
516  for chain in triggers:
517  chain_noHLT = chain.replace("HLT_", "")
518  chain_out = chain_noHLT if self.removeHLTPrefix else chain
519  alg = config.createAlgorithm( 'CP::TauEfficiencyCorrectionsAlg',
520  'TauTrigEfficiencyCorrectionsAlg_' + chain )
521  config.addPrivateTool( 'efficiencyCorrectionsTool',
522  'TauAnalysisTools::TauEfficiencyCorrectionsTool' )
523  # SFTriggerHadTau correction type from
524  # https://gitlab.cern.ch/atlas/athena/-/blob/main/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/Enums.h#L79
525  alg.efficiencyCorrectionsTool.EfficiencyCorrectionTypes = [12]
526  if config.geometry() is LHCPeriod.Run2:
527  alg.efficiencyCorrectionsTool.Campaign = "mc20"
528  else:
529  alg.efficiencyCorrectionsTool.Campaign = config.campaign().value
530  alg.efficiencyCorrectionsTool.TriggerName = chain
531 
532  # JetIDLevel from
533  # https://gitlab.cern.ch/atlas/athena/-/blob/main/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/Enums.h#L79
534  if self.tauID=="Loose":
535  JetIDLevel = 7
536  elif self.tauID=="Medium":
537  JetIDLevel = 8
538  elif self.tauID=="Tight":
539  JetIDLevel = 9
540  else:
541  raise ValueError ("invalid tauID: \"" + self.tauID + "\". Allowed values are loose, medium, tight")
542  alg.efficiencyCorrectionsTool.JetIDLevel = JetIDLevel
543  alg.efficiencyCorrectionsTool.TriggerSFMeasurement = "combined"
544  alg.efficiencyCorrectionsTool.useFastSim = config.dataType() is DataType.FastSim
545 
546  alg.scaleFactorDecoration = f"tau_{self.prefixSF}_{chain_out}_%SYS%"
547  alg.outOfValidity = 2 #silent
548  alg.outOfValidityDeco = f"bad_eff_tautrig_{chain_out}"
549  alg.taus = config.readName (self.containerName)
550  alg.preselection = config.getPreselection (self.containerName, self.tauID)
551  config.addOutputVar (self.containerName, alg.scaleFactorDecoration, f"{self.prefixSF}_{chain_out}")
python.TauAnalysisConfig.TauCalibrationConfig.__init__
def __init__(self)
Definition: TauAnalysisConfig.py:16
python.TauAnalysisConfig.TauWorkingPointConfig.manual_sel_gntauwp
manual_sel_gntauwp
Definition: TauAnalysisConfig.py:291
python.TauAnalysisConfig.TauTriggerAnalysisSFBlock.tauID
tauID
Definition: TauAnalysisConfig.py:534
python.TauAnalysisConfig.TauWorkingPointConfig.__init__
def __init__(self)
Definition: TauAnalysisConfig.py:127
python.TauAnalysisConfig.EXPERIMENTAL_TauCombineMuonRemovalConfig
Definition: TauAnalysisConfig.py:451
python.TriggerAnalysisSFConfig.trigger_set
def trigger_set(config, triggerChainsPerYear, includeAllYearsPerRun)
Definition: TriggerAnalysisSFConfig.py:64
python.TauAnalysisConfig.EXPERIMENTAL_TauCombineMuonRemovalConfig.makeAlgs
def makeAlgs(self, config)
Definition: TauAnalysisConfig.py:474
python.TauAnalysisConfig.TauTriggerAnalysisSFBlock
Definition: TauAnalysisConfig.py:484
python.TauAnalysisConfig.TauWorkingPointConfig.manual_sel_evetowp
manual_sel_evetowp
Definition: TauAnalysisConfig.py:309
python.TauAnalysisConfig.TauCalibrationConfig.instanceName
def instanceName(self)
Definition: TauAnalysisConfig.py:36
python.TauAnalysisConfig.EXPERIMENTAL_TauCombineMuonRemovalConfig.instanceName
def instanceName(self)
Definition: TauAnalysisConfig.py:470
python.TauAnalysisConfig.TauTriggerAnalysisSFBlock.makeAlgs
def makeAlgs(self, config)
Definition: TauAnalysisConfig.py:511
python.TauAnalysisConfig.TauTriggerAnalysisSFBlock.instanceName
def instanceName(self)
Definition: TauAnalysisConfig.py:507
python.TauAnalysisConfig.TauWorkingPointConfig.instanceName
def instanceName(self)
Definition: TauAnalysisConfig.py:198
python.TauAnalysisConfig.TauCalibrationConfig
Definition: TauAnalysisConfig.py:13
python.TauAnalysisConfig.TauWorkingPointConfig
Definition: TauAnalysisConfig.py:122
python.TauAnalysisConfig.TauTriggerAnalysisSFBlock.__init__
def __init__(self)
Definition: TauAnalysisConfig.py:486
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
python.TauAnalysisConfig.TauWorkingPointConfig.quality
quality
Definition: TauAnalysisConfig.py:363
python.TauAnalysisConfig.EXPERIMENTAL_TauCombineMuonRemovalConfig.__init__
def __init__(self)
Definition: TauAnalysisConfig.py:452
python.TauAnalysisConfig.TauCalibrationConfig.makeAlgs
def makeAlgs(self, config)
Definition: TauAnalysisConfig.py:40
python.TauAnalysisConfig.TauWorkingPointConfig.manual_sel_rnnwp
manual_sel_rnnwp
Definition: TauAnalysisConfig.py:273
python.TauAnalysisConfig.TauWorkingPointConfig.makeAlgs
def makeAlgs(self, config)
Definition: TauAnalysisConfig.py:205