4 from AnalysisAlgorithmsConfig.ConfigBlock
import ConfigBlock
6 from AnalysisAlgorithmsConfig.ConfigAccumulator
import DataType
7 from AthenaConfiguration.Enums
import LHCPeriod
8 from Campaigns.Utils
import Campaign
9 from AthenaCommon.Logging
import logging
13 """the ConfigBlock for the track impact parameter correction"""
16 super (InDetTrackCalibrationConfig, self).__init__ ()
17 self.setBlockName (
'InDetTracks')
18 self.addOption (
'inputContainer',
'', type=str,
19 info=
"select track input container, by default set to InDetTrackParticles")
20 self.addOption (
'containerName',
'', type=str,
22 info=
"the name of the output container after calibration.")
23 self.addOption (
'postfix',
'', type=str,
24 info=
"a postfix to apply to decorations and algorithm names. Typically "
25 "not needed here since the calibration is common to all tracks.")
26 self.addOption (
'runBiasing',
True, type=bool,
27 info=
"whether to run the InDetTrackBiasingTool. Allows the user to "
28 "disable the tool if no recommendations are available. This should "
29 "not be used in an analysis. The default is True.")
30 self.addOption (
'biasD0',
None, type=float,
31 info=
"a manual bias (float) to d0 in mm. Will be applied by the "
32 "InDetTrackBiasingTool. Expert option in addition to the "
33 "recommendations. The default is 0.",
35 self.addOption (
'biasZ0',
None, type=float,
36 info=
"a manual bias (float) to z0 in mm. Will be applied by the "
37 "InDetTrackBiasingTool. Expert option in addition to the "
38 "recommendations. The default is 0.",
40 self.addOption (
'biasQoverPsagitta',
None, type=float,
41 info=
"a manual bias (float) to QoverP in TeV^-1. Will be applied "
42 "by the InDetTrackBiasingTool. Expert option in addition to the "
43 "recommendations. The default is 0.",
45 self.addOption (
'customRunNumber',
None, type=int,
46 info=
"manually sets the runNumber (int) in the InDetTrackBiasingTool. "
47 "Expert option leads to use of different recommendations. Default is "
48 "retrieved from EventInfo",
50 self.addOption (
'calibFile',
None, type=str,
51 info=
"name (str) of the calibration file to use for the CTIDE "
52 "calibration. Expert option to override the recommendations "
53 "based on the campaign. The default is None.",
55 self.addOption (
'smearingToolSeed',
None, type=int,
56 info=
"random seed (int) to be used by the InDetTrackSmearingTool. "
57 "Expert option. The default is 0.",
59 self.addOption (
'minPt', 0.5*GeV, type=float,
60 info=
"the minimum pT cut to apply to calibrated tracks. "
61 "The default is 0.5 GeV.")
62 self.addOption (
'maxEta', 2.5, type=float,
63 info=
"maximum track |eta| (float). The default is 2.5.")
64 self.addOption (
'outputTrackSummaryInfo',
False, type=bool,
65 info=
"decorate track summary information on the reconstructed object")
68 """Return the instance name for this block"""
69 return self.containerName + self.postfix
72 log = logging.getLogger(
'InDetTrackCalibrationConfig')
74 inputContainer =
"InDetTrackParticles"
75 if self.inputContainer:
76 inputContainer = self.inputContainer
77 config.setSourceName (self.containerName, inputContainer)
80 if config.wantCopy (self.containerName) :
81 alg = config.createAlgorithm(
'CP::AsgShallowCopyAlg',
'InDetTrackShallowCopyAlg' )
82 alg.input = config.readName (self.containerName)
83 alg.output = config.copyName (self.containerName)
86 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
'InDetTrackEtaCutAlg' )
87 alg.selectionDecoration =
'selectEta' + self.postfix +
',as_bits'
88 config.addPrivateTool(
'selectionTool',
'CP::AsgPtEtaSelectionTool' )
89 alg.selectionTool.maxEta = self.maxEta
90 alg.particles = config.readName (self.containerName)
91 alg.preselection = config.getPreselection (self.containerName,
'')
92 config.addSelection (self.containerName,
'', alg.selectionDecoration)
95 if config.dataType()
is not DataType.Data:
96 if not self.runBiasing:
97 log.warning(
'Disabling the biasing tool for now. This should not '
98 'be used in an analysis.')
100 if config.geometry()
is LHCPeriod.Run3:
101 raise ValueError (
'Recommendations are not yet available in Run 3.')
102 elif config.geometry()
is not LHCPeriod.Run2:
103 raise ValueError (
'No recommendations found for geometry \"'
104 + config.geometry().value +
'\". Please check '
105 'the configuration.')
106 alg = config.createAlgorithm(
'CP::InDetTrackBiasingAlg',
'InDetTrackBiasingAlg' )
107 config.addPrivateTool(
'biasingTool',
'InDet::InDetTrackBiasingTool' )
109 alg.biasingTool.biasD0 = self.biasD0
111 alg.biasingTool.biasZ0 = self.biasZ0
112 if self.biasQoverPsagitta:
113 alg.biasingTool.biasQoverPsagitta = self.biasQoverPsagitta
114 if self.customRunNumber:
115 alg.biasingTool.runNumber = self.customRunNumber
116 alg.inDetTracks = config.readName (self.containerName)
117 alg.inDetTracksOut = config.copyName (self.containerName)
118 alg.preselection = config.getPreselection (self.containerName,
'')
121 if config.dataType()
is not DataType.Data:
122 alg = config.createAlgorithm(
'CP::InDetTrackSmearingAlg',
'InDetTrackSmearingAlg' )
123 config.addPrivateTool(
'smearingTool',
'InDet::InDetTrackSmearingTool' )
124 if self.smearingToolSeed:
125 alg.smearingTool.Seed = self.smearingToolSeed
127 alg.smearingTool.calibFileIP_CTIDE = self.calibFile
129 if config.geometry()
is LHCPeriod.Run2:
131 alg.smearingTool.calibFileIP_CTIDE =
"InDetTrackSystematicsTools/CalibData_22.0_2022-v00/d0z0_smearing_factors_Run2_v2.root"
132 elif config.geometry()
is LHCPeriod.Run3:
133 if config.campaign()
is Campaign.MC23a:
135 alg.smearingTool.calibFileIP_CTIDE =
"InDetTrackSystematicsTools/CalibData_25.2_2025-v00/2022_d0z0_smearing_factors_v2.root"
136 elif config.campaign()
is Campaign.MC23d:
138 alg.smearingTool.calibFileIP_CTIDE =
"InDetTrackSystematicsTools/CalibData_25.2_2025-v00/2023_d0z0_smearing_factors_v2.root"
139 elif config.campaign()
is Campaign.MC23e:
141 alg.smearingTool.calibFileIP_CTIDE =
"InDetTrackSystematicsTools/CalibData_25.2_2025-v00/2024_d0z0_smearing_factors.root"
143 raise ValueError (
'No recommendations found for capaign \"'
144 + config.campaign().value +
'\" in Run 3. '
145 'Please check that the recommendations exist.')
147 raise ValueError (
'No recommendations found for geometry \"'
148 + config.geometry().value +
'\". Please check '
149 'the configuration.')
150 alg.inDetTracks = config.readName (self.containerName)
151 alg.inDetTracksOut = config.copyName (self.containerName)
152 alg.preselection = config.getPreselection (self.containerName,
'')
155 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
'InDetTrackPtCutAlg' )
156 alg.selectionDecoration =
'selectPt' + self.postfix +
',as_bits'
157 config.addPrivateTool(
'selectionTool',
'CP::AsgPtEtaSelectionTool' )
158 alg.selectionTool.minPt = self.minPt
159 alg.particles = config.readName (self.containerName)
160 alg.preselection = config.getPreselection (self.containerName,
'')
161 config.addSelection (self.containerName,
'', alg.selectionDecoration,
165 alg = config.createAlgorithm(
'CP::InDetTrackExtraVarDecoratorAlg',
'ExtraVarDecorator' )
166 alg.inDetTracks = config.readName(self.containerName)
168 config.addOutputVar (self.containerName,
'pt_%SYS%',
'pt')
169 config.addOutputVar (self.containerName,
'eta_%SYS%',
'eta', noSys=
True)
170 config.addOutputVar (self.containerName,
'phi',
'phi', noSys=
True)
171 config.addOutputVar (self.containerName,
'charge_%SYS%',
'charge', noSys=
True)
172 config.addOutputVar (self.containerName,
'qOverP',
'qOverP')
173 config.addOutputVar (self.containerName,
'd0',
'd0')
174 config.addOutputVar (self.containerName,
'z0',
'z0')
175 config.addOutputVar (self.containerName,
'vz',
'vz', noSys=
True)
178 if self.outputTrackSummaryInfo
and config.dataType()
is not DataType.Data:
179 config.addOutputVar (self.containerName,
'numberOfInnermostPixelLayerHits',
'numberOfInnermostPixelLayerHits', noSys=
True)
180 config.addOutputVar (self.containerName,
'numberOfPixelDeadSensors',
'numberOfPixelDeadSensors', noSys=
True)
181 config.addOutputVar (self.containerName,
'numberOfPixelHits',
'numberOfPixelHits', noSys=
True)
182 config.addOutputVar (self.containerName,
'numberOfPixelHoles',
'numberOfPixelHoles', noSys=
True)
183 config.addOutputVar (self.containerName,
'numberOfPixelSharedHits',
'numberOfPixelSharedHits', noSys=
True)
184 config.addOutputVar (self.containerName,
'numberOfSCTDeadSensors',
'numberOfSCTDeadSensors', noSys=
True)
185 config.addOutputVar (self.containerName,
'numberOfSCTHits',
'numberOfSCTHits', noSys=
True)
186 config.addOutputVar (self.containerName,
'numberOfSCTHoles',
'numberOfSCTHoles', noSys=
True)
187 config.addOutputVar (self.containerName,
'numberOfSCTSharedHits',
'numberOfSCTSharedHits', noSys=
True)
188 config.addOutputVar (self.containerName,
'numberOfTRTHits',
'numberOfTRTHits', noSys=
True)
189 config.addOutputVar (self.containerName,
'numberOfTRTOutliers',
'numberOfTRTOutliers', noSys=
True)
193 """the ConfigBlock for the track working point"""
196 super (InDetTrackWorkingPointConfig, self).__init__ ()
197 self.addOption (
'containerName',
'', type=str,
199 info=
"the name of the input container.")
200 self.addOption (
'selectionName',
'', type=str,
202 info=
"the name of the track selection to define (e.g. tightPrimary "
204 self.addOption (
'postfix',
None, type=str,
205 info=
"a postfix to apply to decorations and algorithm names. "
206 "Typically not needed here as selectionName is used internally.")
207 self.addOption (
'cutLevel',
None, type=str,
209 info=
"the selection WP (str) to use. Supported WPs for general "
210 "use: `Loose` and `TightPrimary`. For expert studies, further "
211 "WPs are available: `NoCut`, `LoosePrimary`, `LooseElectron`, "
212 "`LooseMuon`, `LooseTau`, `MinBias`, `HILoose`, `HITight`, "
213 "`HILooseOptimized`, `HITightOptimized`.",
214 expertMode=[
"NoCut",
"LoosePrimary",
"LooseElectron",
215 "LooseMuon",
"LooseTau",
"MinBias",
"HILoose",
"HITight",
216 "HILooseOptimized",
"HITightOptimized"])
217 self.addOption (
'additionalCuts',
None, type=
None,
218 info=
"additional cuts to modify the selection WP. Only meant for "
219 "expert studies of track selection. Passed as pairs of `cutName: value`. "
220 "For an overview of available cuts, see twiki.cern.ch/twiki/bin/viewauth/"
221 "AtlasProtected/InDetTrackSelectionTool#List_of_possible_cuts.",
223 self.addOption (
'runTruthFilter',
True, type=bool,
224 info=
"whether to run the TruthFilterTool. This tool is only compatible "
225 "with the cut levels 'Loose' and 'TightPrimary'.")
226 self.addOption (
'calibFile',
None, type=str,
227 info=
"name (str) of the calibration file to use for efficiencies "
228 "in the TruthFilter tool. Expert option to override the "
229 "recommendations based on the campaign. The default is None.",
231 self.addOption (
'filterToolSeed',
None, type=int,
232 info=
"random seed (int) to be used by the InDetTrackTruthFilterTool. "
233 "Expert option. The default is 0.",
235 self.addOption (
'fFakeLoose',
None, type=float,
236 info=
"the fraction of fake tracks (float) in the Loose working point. "
237 "Will be used by the InDetTrackTruthFilterTool. Expert option to "
238 "override the recommendations.",
240 self.addOption (
'fFakeTight',
None, type=float,
241 info=
"the fraction of fake tracks (float) in the TightPrimary working "
242 "point. Will be used by the InDetTrackTruthFilterTool. Expert option "
243 "to override the recommendations.",
245 self.addOption (
'trkEffSystScale',
None, type=float,
246 info=
"the track efficiency systematic scale (float). Will be used "
247 "by the InDetTrackTruthFilterTool. Expert option to override the "
248 "recommendations. Default is 1.0",
250 self.addOption (
'addSelectionToPreselection',
True, type=bool,
251 info=
"whether to retain only tracks satisfying the cutLevel "
252 "requirements. The default is True.")
255 """Return the instance name for this block"""
256 if self.postfix
is not None:
257 return self.containerName + self.selectionName + self.postfix
259 return self.containerName + self.selectionName
262 log = logging.getLogger(
'InDetTrackWorkingPointConfig')
264 selectionPostfix = self.selectionName
265 if selectionPostfix !=
'' and selectionPostfix[0] !=
'_' :
266 selectionPostfix =
'_' + selectionPostfix
268 postfix = self.postfix
270 postfix = self.selectionName
271 if postfix !=
'' and postfix[0] !=
'_' :
272 postfix =
'_' + postfix
274 cutLevels = [
"NoCut",
"Loose",
"LoosePrimary",
"TightPrimary",
"LooseMuon",
275 "LooseElectron",
"LooseTau",
"MinBias",
"HILoose",
"HITight",
276 "HILooseOptimized",
"HITightOptimized"]
277 alg = config.createAlgorithm(
'CP::InDetTrackSelectionAlg',
'InDetTrackSelectionAlg' )
278 alg.selectionDecoration =
'selectTrack' + postfix +
'_%SYS%,as_bits'
279 config.addPrivateTool(
'selectionTool',
'InDet::InDetTrackSelectionTool')
281 log.warning(
"No selection WP chosen, not setting up InDetTrackSelectionTool.")
282 elif self.
cutLevel not in cutLevels:
283 raise ValueError (
'Invalid cut level: \"' + self.
cutLevel +
'\", has '
284 'to be one of: ' +
', '.
join(cutLevels))
285 elif self.
cutLevel in [
"Loose",
"TightPrimary"]:
286 alg.selectionTool.CutLevel = self.
cutLevel
288 log.warning(
'Using cut level: \"' + self.
cutLevel +
'\" that is not '
289 'meant for general use, but only expert studies.')
290 alg.selectionTool.CutLevel = self.
cutLevel
291 if self.additionalCuts:
292 for cutName, value
in self.additionalCuts.
items():
293 setattr(alg.selectionTool, cutName, value)
295 if config.dataType()
is not DataType.Data:
296 if not self.runTruthFilter:
297 log.warning(
'Disabling the TruthFilterTool.')
299 config.addPrivateTool(
'filterTool',
'InDet::InDetTrackTruthFilterTool' )
300 config.addPrivateTool(
'filterTool.trackOriginTool',
'InDet::InDetTrackTruthOriginTool' )
303 alg.filterWP =
"LOOSE"
304 elif self.
cutLevel ==
"TightPrimary":
305 alg.filterWP =
"TIGHT"
307 raise ValueError (
'Attempting to set TruthFilter WP based on cut level: \"'
308 + self.efficiencyWP +
'\" that is not supported.')
310 if config.geometry()
is LHCPeriod.Run2:
312 alg.filterTool.calibFileNomEff =
"InDetTrackSystematicsTools/CalibData_22.0_2022-v00/TrackingRecommendations_prelim_rel22.root"
313 alg.filterTool.fFakeLoose = 0.10
314 alg.filterTool.fFakeTight = 1.00
315 elif config.geometry()
is LHCPeriod.Run3:
316 if config.campaign()
in [Campaign.MC23a, Campaign.MC23d, Campaign.MC23e]:
318 alg.filterTool.calibFileNomEff =
"InDetTrackSystematicsTools/CalibData_22.0_2022-v00/TrackingRecommendations_prelim_rel22.root"
319 alg.filterTool.fFakeLoose = 0.40
320 alg.filterTool.fFakeTight = 1.00
321 elif not (self.calibFile
and self.fFakeLoose
and self.fFakeTight):
322 raise ValueError (
'No efficiency recommendations found for capaign \"'
323 + config.campaign().value +
'\" in Run 3. '
324 'Please check that the recommendations exist.')
325 elif not (self.calibFile
and self.fFakeLoose
and self.fFakeTight):
326 raise ValueError (
'No efficiency recommendations found for geometry \"'
327 + config.geometry().value +
'\". Please check '
328 'the configuration.')
331 alg.filterTool.calibFileNomEff = self.calibFile
333 alg.filterTool.fFakeLoose = self.fFakeLoose
335 alg.filterTool.fFakeTight = self.fFakeTight
336 if self.filterToolSeed:
337 alg.filterTool.Seed = self.filterToolSeed
338 if self.trkEffSystScale:
339 alg.filterTool.trkEffSystScale = self.trkEffSystScale
340 alg.inDetTracks = config.readName (self.containerName)
341 alg.preselection = config.getPreselection (self.containerName,
'')
342 config.addSelection (self.containerName, self.selectionName, alg.selectionDecoration,
343 preselection=self.addSelectionToPreselection)