ATLAS Offline Software
Loading...
Searching...
No Matches
DiTauAnalysisConfig.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.ConfigBlock import ConfigBlock
5from AnalysisAlgorithmsConfig.ConfigAccumulator import DataType
6
7
8class DiTauCalibrationConfig (ConfigBlock):
9 """the ConfigBlock for the tau four-momentum correction"""
10
11 def __init__ (self) :
12 super (DiTauCalibrationConfig, self).__init__ ()
13 self.setBlockName('DiTaus')
14 self.addOption ('inputContainer', '', type=str,
15 info="select ditau input container, by default set to DiTauJets")
16 self.addOption ('containerName', '', type=str,
17 noneAction='error',
18 info="the name of the output container after calibration.")
19 self.addOption ('postfix', '', type=str,
20 info="a postfix to apply to decorations and algorithm names. "
21 "Typically not needed here since the calibration is common to "
22 "all ditaus.")
23 self.addOption ('rerunTruthMatching', True, type=bool,
24 info="whether to rerun truth matching (sets up an instance of "
25 "CP::DiTauTruthMatchingAlg). The default is True.")
26 self.addOption ('decorateTruth', False, type=bool,
27 info="decorate truth particle information on the reconstructed one")
28 self.addOption ('decorateExtraVariables', True, type=bool,
29 info="decorate extra variables for the reconstructed ditau")
30
31 def instanceName (self) :
32 """Return the instance name for this block"""
33 return self.containerName + self.postfix
34
35 def makeAlgs (self, config) :
36
37 postfix = self.postfix
38 if postfix != '' and postfix[0] != '_' :
39 postfix = '_' + postfix
40
41 inputContainer = "DiTauJets"
43 inputContainer = self.inputContainer
44 config.setSourceName (self.containerName, inputContainer)
45
46 # Set up the tau truth matching algorithm:
47 if self.rerunTruthMatching and config.dataType() is not DataType.Data:
48 alg = config.createAlgorithm( 'CP::DiTauTruthMatchingAlg',
49 'DiTauTruthMatchingAlg' )
50 config.addPrivateTool( 'matchingTool',
51 'TauAnalysisTools::DiTauTruthMatchingTool' )
52 alg.taus = config.readName (self.containerName)
53 alg.preselection = config.getPreselection (self.containerName, '')
54
55
56 # decorate truth tau information on the reconstructed object:
57 if self.decorateTruth and self.rerunTruthMatching and config.dataType() is not DataType.Data:
58 # in the case of the ditau, the DiTauTruthMatchingTool decorates directly the reco ditau with truth information.
59 # So information can be written directly out without any additional algorithm
60 config.addOutputVar (self.containerName, 'TruthVisLeadPt', 'TruthVisLeadPt', noSys=True)
61 config.addOutputVar (self.containerName, 'TruthVisLeadEta', 'TruthVisLeadEta', noSys=True)
62 config.addOutputVar (self.containerName, 'TruthVisLeadPhi', 'TruthVisLeadPhi', noSys=True)
63 config.addOutputVar (self.containerName, 'TruthVisLeadM', 'TruthVisLeadM', noSys=True)
64 config.addOutputVar (self.containerName, 'TruthLeadPdgID', 'TruthLeadPdgID', noSys=True)
65 config.addOutputVar (self.containerName, 'TruthVisSubleadPt', 'TruthVisSubleadPt', noSys=True)
66 config.addOutputVar (self.containerName, 'TruthVisSubleadEta', 'TruthVisSubleadEta', noSys=True)
67 config.addOutputVar (self.containerName, 'TruthVisSubleadPhi', 'TruthVisSubleadPhi', noSys=True)
68 config.addOutputVar (self.containerName, 'TruthVisSubleadM', 'TruthVisSubleadM', noSys=True)
69 config.addOutputVar (self.containerName, 'TruthSubleadPdgID', 'TruthSubleadPdgID', noSys=True)
70 config.addOutputVar (self.containerName, 'TruthVisDeltaR', 'TruthVisDeltaR', noSys=True)
71 config.addOutputVar (self.containerName, 'TruthVisMass', 'TruthVisMass', noSys=True)
72 config.addOutputVar (self.containerName, 'IsTruthMatched', 'IsTruthMatched', noSys=True)
73 config.addOutputVar (self.containerName, 'IsTruthHadronic', 'IsTruthHadronic', noSys=True)
74
75 # Decorate extra variables
77 alg = config.createAlgorithm( 'CP::DiTauExtraVariablesAlg',
78 'DiTauExtraVariablesAlg',
79 reentrant=True )
80 alg.ditaus = config.readName (self.containerName)
81 config.addOutputVar (self.containerName, 'omniScore', 'omniScore', noSys=True)
82 config.addOutputVar (self.containerName, 'nSubjets', 'nSubjets', noSys=True)
83 config.addOutputVar (self.containerName, 'leadSubjetPt', 'leadSubjetPt', noSys=True)
84 config.addOutputVar (self.containerName, 'leadSubjetEta', 'leadSubjetEta', noSys=True)
85 config.addOutputVar (self.containerName, 'leadSubjetPhi', 'leadSubjetPhi', noSys=True)
86 config.addOutputVar (self.containerName, 'leadSubjetE', 'leadSubjetE', noSys=True)
87 config.addOutputVar (self.containerName, 'leadSubjetNTracks', 'leadSubjetNTracks', noSys=True)
88 config.addOutputVar (self.containerName, 'leadSubjetCharge', 'leadSubjetCharge', noSys=True)
89 config.addOutputVar (self.containerName, 'subleadSubjetPt', 'subleadSubjetPt', noSys=True)
90 config.addOutputVar (self.containerName, 'subleadSubjetEta', 'subleadSubjetEta', noSys=True)
91 config.addOutputVar (self.containerName, 'subleadSubjetPhi', 'subleadSubjetPhi', noSys=True)
92 config.addOutputVar (self.containerName, 'subleadSubjetE', 'subleadSubjetE', noSys=True)
93 config.addOutputVar (self.containerName, 'subleadSubjetNTracks', 'subleadSubjetNTracks', noSys=True)
94 config.addOutputVar (self.containerName, 'subleadSubjetCharge', 'subleadSubjetCharge', noSys=True)
95
96 # Set up the tau 4-momentum smearing algorithm:
97 alg = config.createAlgorithm( 'CP::DiTauSmearingAlg', 'DiTauSmearingAlg' )
98 config.addPrivateTool( 'smearingTool', 'TauAnalysisTools::DiTauSmearingTool' )
99 alg.taus = config.readName (self.containerName)
100 alg.tausOut = config.copyName (self.containerName)
101 alg.preselection = config.getPreselection (self.containerName, '')
102
103 # Save base kinematic ditau variables in output
104 config.addOutputVar (self.containerName, 'pt', 'pt')
105 config.addOutputVar (self.containerName, 'eta', 'eta', noSys=True)
106 config.addOutputVar (self.containerName, 'phi', 'phi', noSys=True)
107 config.addOutputVar (self.containerName, 'm', 'm', noSys=True)
108
109
110
111class DiTauWorkingPointConfig (ConfigBlock) :
112 """the ConfigBlock for the tau working point
113
114 This may at some point be split into multiple blocks (16 Mar 22)."""
115
116 def __init__ (self) :
117 super (DiTauWorkingPointConfig, self).__init__ ()
118 self.addOption ('containerName', '', type=str,
119 noneAction='error',
120 info="the name of the input container.")
121 self.addOption ('selectionName', '', type=str,
122 noneAction='error',
123 info="the name of the tau-jet selection to define (e.g. tight or "
124 "loose).")
125 self.addOption ('postfix', None, type=str,
126 info="a postfix to apply to decorations and algorithm names. "
127 "Typically not needed here as selectionName is used internally.")
128 self.addOption ('quality', None, type=str,
129 info="the ID WP (string) to use. Supported ID WPs: Tight, Medium, "
130 "Loose, VeryLoose, Baseline, BaselineForFakes.")
131 self.addOption ('addSelectionToPreselection', True, type=bool,
132 info="whether to retain only ditau-jets satisfying the working point "
133 "requirements. The default is True.")
134
135 def instanceName (self) :
136 """Return the instance name for this block"""
137 if self.postfix is not None:
138 return self.containerName + '_' + self.selectionName + self.postfix
139 else:
140 return self.containerName + '_' + self.selectionName
141
142 def makeAlgs (self, config) :
143
144 selectionPostfix = self.selectionName
145 if selectionPostfix != '' and selectionPostfix[0] != '_' :
146 selectionPostfix = '_' + selectionPostfix
147
148 postfix = self.postfix
149 if postfix is None :
150 postfix = self.selectionName
151 if postfix != '' and postfix[0] != '_' :
152 postfix = '_' + postfix
153
154 # using enum value from: https://gitlab.cern.ch/atlas/athena/blob/21.2/PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/Enums.h
155 # the dictionary is missing in Athena, so hard-coding values here
156 if self.quality == 'Tight' :
157 IDLevel = 4 # ROOT.TauAnalysisTools.JETIDBDTTIGHT
158 elif self.quality == 'Medium' :
159 IDLevel = 3 # ROOT.TauAnalysisTools.JETIDBDTMEDIUM
160 elif self.quality == 'Loose' :
161 IDLevel = 2 # ROOT.TauAnalysisTools.JETIDBDTLOOSE
162 else :
163 raise ValueError ("invalid tau quality: \"" + self.quality +
164 "\", allowed values are Tight, Medium, Loose")
165
166 inputfile = 'TauAnalysisAlgorithms/ditau_selection_highpt.conf'
167 if "DiTauJetsLowPt" in self.containerName:
168 inputfile = 'TauAnalysisAlgorithms/ditau_selection_lowpt.conf'
169
170 # Set up the algorithm selecting taus:
171 alg = config.createAlgorithm( 'CP::AsgSelectionAlg', 'DiTauSelectionAlg' )
172 config.addPrivateTool( 'selectionTool', 'TauAnalysisTools::DiTauSelectionTool' )
173 alg.selectionTool.ConfigPath = inputfile
174 alg.selectionDecoration = 'selected_ditau' + selectionPostfix + ',as_char'
175 alg.particles = config.readName (self.containerName)
176 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
177 config.addSelection (self.containerName, self.selectionName, alg.selectionDecoration,
178 preselection=self.addSelectionToPreselection)
179
180
181 # Set up the algorithm calculating the efficiency scale factors for the
182 # taus:
183 if config.dataType() is not DataType.Data:
184 alg = config.createAlgorithm( 'CP::DiTauEfficiencyCorrectionsAlg',
185 'DiTauEfficiencyCorrectionsAlg' )
186 config.addPrivateTool( 'efficiencyCorrectionsTool',
187 'TauAnalysisTools::DiTauEfficiencyCorrectionsTool' )
188 alg.efficiencyCorrectionsTool.JetIDLevel = IDLevel
189 alg.scaleFactorDecoration = 'tau_effSF' + postfix + '_%SYS%'
190 # alg.outOfValidity = 2 #silent
191 # alg.outOfValidityDeco = "bad_eff"
192 alg.taus = config.readName (self.containerName)
193 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
194 config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
195 'effSF' + postfix)
196