ATLAS Offline Software
Loading...
Searching...
No Matches
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):
4from AnalysisAlgorithmsConfig.ConfigAccumulator import DataType
5from AnalysisAlgorithmsConfig.ConfigBlock import ConfigBlock
6from AthenaCommon.Logging import logging
7from AthenaConfiguration.Enums import LHCPeriod
8from Campaigns.Utils import Campaign
9
10from TriggerAnalysisAlgorithms.TriggerAnalysisSFConfig import trigger_set
11
12
13class 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
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')
119 config.addOutputVar (self.containerName, 'nTracksCharged', 'nTracksCharged', noSys=True)
120
121
122class 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
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' )
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)
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
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
484class 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}")
# current recommendations are for RNN ID, so donCPTauEfficiencyCorrectionsAlgTauEfficiencyCorrectionsAlgIDefficiencyCorrectionsToolTauAnalysisToolsTauEfficiencyCorrectionsTooltau_ID_effSF_%SYS%bad_ID_effID_effSFt use them for GNTau useGNTau