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.")
34 self.addOption (
'biasZ0',
None, type=float,
35 info=
"a manual bias (float) to z0 in mm. Will be applied by the "
36 "InDetTrackBiasingTool. Expert option in addition to the "
37 "recommendations. The default is 0.")
38 self.addOption (
'biasQoverPsagitta',
None, type=float,
39 info=
"a manual bias (float) to QoverP in TeV^-1. Will be applied "
40 "by the InDetTrackBiasingTool. Expert option in addition to the "
41 "recommendations. The default is 0.")
42 self.addOption (
'customRunNumber',
None, type=int,
43 info=
"manually sets the runNumber (int) in the InDetTrackBiasingTool. "
44 "Expert option leads to use of different recommendations. Default is "
45 "retrieved from EventInfo")
46 self.addOption (
'calibFile',
None, type=str,
47 info=
"name (str) of the calibration file to use for the CTIDE "
48 "calibration. Expert option to override the recommendations "
49 "based on the campaign. The default is None.")
50 self.addOption (
'smearingToolSeed',
None, type=int,
51 info=
"random seed (int) to be used by the InDetTrackSmearingTool. "
52 "Expert option. The default is 0.")
53 self.addOption (
'minPt', 0.5*GeV, type=float,
54 info=
"the minimum pT cut to apply to calibrated tracks. "
55 "The default is 0.5 GeV.")
56 self.addOption (
'maxEta', 2.5, type=float,
57 info=
"maximum track |eta| (float). The default is 2.5.")
58 self.addOption (
'outputTrackSummaryInfo',
False, type=bool,
59 info=
"decorate track summary information on the reconstructed object")
62 """Return the instance name for this block"""
63 return self.containerName + self.postfix
66 log = logging.getLogger(
'InDetTrackCalibrationConfig')
68 inputContainer =
"InDetTrackParticles"
69 if self.inputContainer:
70 inputContainer = self.inputContainer
71 config.setSourceName (self.containerName, inputContainer)
74 if config.wantCopy (self.containerName) :
75 alg = config.createAlgorithm(
'CP::AsgShallowCopyAlg',
'InDetTrackShallowCopyAlg' )
76 alg.input = config.readName (self.containerName)
77 alg.output = config.copyName (self.containerName)
80 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
'InDetTrackEtaCutAlg' )
81 alg.selectionDecoration =
'selectEta' + self.postfix +
',as_bits'
82 config.addPrivateTool(
'selectionTool',
'CP::AsgPtEtaSelectionTool' )
83 alg.selectionTool.maxEta = self.maxEta
84 alg.particles = config.readName (self.containerName)
85 alg.preselection = config.getPreselection (self.containerName,
'')
86 config.addSelection (self.containerName,
'', alg.selectionDecoration)
89 if config.dataType()
is not DataType.Data:
90 if not self.runBiasing:
91 log.warning(
'Disabling the biasing tool for now. This should not '
92 'be used in an analysis.')
94 if config.geometry()
is LHCPeriod.Run3:
95 raise ValueError (
'Recommendations are not yet available in Run 3.')
96 elif config.geometry()
is not LHCPeriod.Run2:
97 raise ValueError (
'No recommendations found for geometry \"'
98 + config.geometry().value +
'\". Please check '
100 alg = config.createAlgorithm(
'CP::InDetTrackBiasingAlg',
'InDetTrackBiasingAlg' )
101 config.addPrivateTool(
'biasingTool',
'InDet::InDetTrackBiasingTool' )
103 alg.biasingTool.biasD0 = self.biasD0
105 alg.biasingTool.biasZ0 = self.biasZ0
106 if self.biasQoverPsagitta:
107 alg.biasingTool.biasQoverPsagitta = self.biasQoverPsagitta
108 if self.customRunNumber:
109 alg.biasingTool.runNumber = self.customRunNumber
110 alg.inDetTracks = config.readName (self.containerName)
111 alg.inDetTracksOut = config.copyName (self.containerName)
112 alg.preselection = config.getPreselection (self.containerName,
'')
115 if config.dataType()
is not DataType.Data:
116 alg = config.createAlgorithm(
'CP::InDetTrackSmearingAlg',
'InDetTrackSmearingAlg' )
117 config.addPrivateTool(
'smearingTool',
'InDet::InDetTrackSmearingTool' )
118 if self.smearingToolSeed:
119 alg.smearingTool.Seed = self.smearingToolSeed
121 alg.smearingTool.calibFileIP_CTIDE = self.calibFile
123 if config.geometry()
is LHCPeriod.Run2:
125 alg.smearingTool.calibFileIP_CTIDE =
"InDetTrackSystematicsTools/CalibData_22.0_2022-v00/d0z0_smearing_factors_Run2_v2.root"
126 elif config.geometry()
is LHCPeriod.Run3:
127 if config.campaign()
is Campaign.MC23a:
129 alg.smearingTool.calibFileIP_CTIDE =
"InDetTrackSystematicsTools/CalibData_25.2_2025-v00/2022_d0z0_smearing_factors_v2.root"
130 elif config.campaign()
is Campaign.MC23d:
132 alg.smearingTool.calibFileIP_CTIDE =
"InDetTrackSystematicsTools/CalibData_25.2_2025-v00/2023_d0z0_smearing_factors_v2.root"
133 elif config.campaign()
is Campaign.MC23e:
135 alg.smearingTool.calibFileIP_CTIDE =
"InDetTrackSystematicsTools/CalibData_25.2_2025-v00/2024_d0z0_smearing_factors.root"
137 raise ValueError (
'No recommendations found for capaign \"'
138 + config.campaign().value +
'\" in Run 3. '
139 'Please check that the recommendations exist.')
141 raise ValueError (
'No recommendations found for geometry \"'
142 + config.geometry().value +
'\". Please check '
143 'the configuration.')
144 alg.inDetTracks = config.readName (self.containerName)
145 alg.inDetTracksOut = config.copyName (self.containerName)
146 alg.preselection = config.getPreselection (self.containerName,
'')
149 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
'InDetTrackPtCutAlg' )
150 alg.selectionDecoration =
'selectPt' + self.postfix +
',as_bits'
151 config.addPrivateTool(
'selectionTool',
'CP::AsgPtEtaSelectionTool' )
152 alg.selectionTool.minPt = self.minPt
153 alg.particles = config.readName (self.containerName)
154 alg.preselection = config.getPreselection (self.containerName,
'')
155 config.addSelection (self.containerName,
'', alg.selectionDecoration,
158 alg = config.createAlgorithm(
'CP::InDetTrackMomentumDecoratorAlg',
'MomentumDecorator' )
159 alg.inDetTracks = config.readName(self.containerName)
161 config.addOutputVar (self.containerName,
'pt_%SYS%',
'pt')
162 config.addOutputVar (self.containerName,
'eta',
'eta', noSys=
True)
163 config.addOutputVar (self.containerName,
'phi',
'phi', noSys=
True)
164 config.addOutputVar (self.containerName,
'charge',
'charge', noSys=
True)
165 config.addOutputVar (self.containerName,
'qOverP',
'qOverP')
166 config.addOutputVar (self.containerName,
'd0',
'd0')
167 config.addOutputVar (self.containerName,
'z0',
'z0')
168 config.addOutputVar (self.containerName,
'vz',
'vz', noSys=
True)
171 if self.outputTrackSummaryInfo
and config.dataType()
is not DataType.Data:
172 config.addOutputVar (self.containerName,
'numberOfInnermostPixelLayerHits',
'numberOfInnermostPixelLayerHits', noSys=
True)
173 config.addOutputVar (self.containerName,
'numberOfPixelDeadSensors',
'numberOfPixelDeadSensors', noSys=
True)
174 config.addOutputVar (self.containerName,
'numberOfPixelHits',
'numberOfPixelHits', noSys=
True)
175 config.addOutputVar (self.containerName,
'numberOfPixelHoles',
'numberOfPixelHoles', noSys=
True)
176 config.addOutputVar (self.containerName,
'numberOfPixelSharedHits',
'numberOfPixelSharedHits', noSys=
True)
177 config.addOutputVar (self.containerName,
'numberOfSCTDeadSensors',
'numberOfSCTDeadSensors', noSys=
True)
178 config.addOutputVar (self.containerName,
'numberOfSCTHits',
'numberOfSCTHits', noSys=
True)
179 config.addOutputVar (self.containerName,
'numberOfSCTHoles',
'numberOfSCTHoles', noSys=
True)
180 config.addOutputVar (self.containerName,
'numberOfSCTSharedHits',
'numberOfSCTSharedHits', noSys=
True)
181 config.addOutputVar (self.containerName,
'numberOfTRTHits',
'numberOfTRTHits', noSys=
True)
182 config.addOutputVar (self.containerName,
'numberOfTRTOutliers',
'numberOfTRTOutliers', noSys=
True)
186 """the ConfigBlock for the track working point"""
189 super (InDetTrackWorkingPointConfig, self).__init__ ()
190 self.addOption (
'containerName',
'', type=str,
192 info=
"the name of the input container.")
193 self.addOption (
'selectionName',
'', type=str,
195 info=
"the name of the track selection to define (e.g. tightPrimary "
197 self.addOption (
'postfix',
None, type=str,
198 info=
"a postfix to apply to decorations and algorithm names. "
199 "Typically not needed here as selectionName is used internally.")
200 self.addOption (
'cutLevel',
None, type=str,
202 info=
"the selection WP (str) to use. Supported WPs for general "
203 "use: `Loose` and `TightPrimary`. For expert studies, further "
204 "WPs are available: `NoCut`, `LoosePrimary`, `LooseElectron`, "
205 "`LooseMuon`, `LooseTau`, `MinBias`, `HILoose`, `HITight`, "
206 "`HILooseOptimized`, `HITightOptimized`.")
207 self.addOption (
'additionalCuts',
None, type=
None,
208 info=
"additional cuts to modify the selection WP. Only meant for "
209 "expert studies of track selection. Passed as pairs of `cutName: value`. "
210 "For an overview of available cuts, see twiki.cern.ch/twiki/bin/viewauth/"
211 "AtlasProtected/InDetTrackSelectionTool#List_of_possible_cuts.")
212 self.addOption (
'runTruthFilter',
True, type=bool,
213 info=
"whether to run the TruthFilterTool. This tool is only compatible "
214 "with the cut levels 'Loose' and 'TightPrimary'.")
215 self.addOption (
'calibFile',
None, type=str,
216 info=
"name (str) of the calibration file to use for efficiencies "
217 "in the TruthFilter tool. Expert option to override the "
218 "recommendations based on the campaign. The default is None.")
219 self.addOption (
'filterToolSeed',
None, type=int,
220 info=
"random seed (int) to be used by the InDetTrackTruthFilterTool. "
221 "Expert option. The default is 0.")
222 self.addOption (
'fFakeLoose',
None, type=float,
223 info=
"the fraction of fake tracks (float) in the Loose working point. "
224 "Will be used by the InDetTrackTruthFilterTool. Expert option to "
225 "override the recommendations.")
226 self.addOption (
'fFakeTight',
None, type=float,
227 info=
"the fraction of fake tracks (float) in the TightPrimary working "
228 "point. Will be used by the InDetTrackTruthFilterTool. Expert option "
229 "to override the recommendations.")
230 self.addOption (
'trkEffSystScale',
None, type=float,
231 info=
"the track efficiency systematic scale (float). Will be used "
232 "by the InDetTrackTruthFilterTool. Expert option to override the "
233 "recommendations. Default is 1.0")
234 self.addOption (
'addSelectionToPreselection',
True, type=bool,
235 info=
"whether to retain only tracks satisfying the cutLevel "
236 "requirements. The default is True.")
239 """Return the instance name for this block"""
240 if self.postfix
is not None:
241 return self.containerName + self.selectionName + self.postfix
243 return self.containerName + self.selectionName
246 log = logging.getLogger(
'InDetTrackWorkingPointConfig')
248 selectionPostfix = self.selectionName
249 if selectionPostfix !=
'' and selectionPostfix[0] !=
'_' :
250 selectionPostfix =
'_' + selectionPostfix
252 postfix = self.postfix
254 postfix = self.selectionName
255 if postfix !=
'' and postfix[0] !=
'_' :
256 postfix =
'_' + postfix
258 cutLevels = [
"NoCut",
"Loose",
"LoosePrimary",
"TightPrimary",
"LooseMuon",
259 "LooseElectron",
"LooseTau",
"MinBias",
"HILoose",
"HITight",
260 "HILooseOptimized",
"HITightOptimized"]
261 alg = config.createAlgorithm(
'CP::InDetTrackSelectionAlg',
'InDetTrackSelectionAlg' )
262 alg.selectionDecoration =
'selectTrack' + postfix +
'_%SYS%,as_bits'
263 config.addPrivateTool(
'selectionTool',
'InDet::InDetTrackSelectionTool')
265 log.warning(
"No selection WP chosen, not setting up InDetTrackSelectionTool.")
266 elif self.
cutLevel not in cutLevels:
267 raise ValueError (
'Invalid cut level: \"' + self.
cutLevel +
'\", has '
268 'to be one of: ' +
', '.
join(cutLevels))
269 elif self.
cutLevel in [
"Loose",
"TightPrimary"]:
270 alg.selectionTool.CutLevel = self.
cutLevel
272 log.warning(
'Using cut level: \"' + self.
cutLevel +
'\" that is not '
273 'meant for general use, but only expert studies.')
274 alg.selectionTool.CutLevel = self.
cutLevel
275 if self.additionalCuts:
276 for cutName, value
in self.additionalCuts.
items():
277 setattr(alg.selectionTool, cutName, value)
279 if config.dataType()
is not DataType.Data:
280 if not self.runTruthFilter:
281 log.warning(
'Disabling the TruthFilterTool.')
283 config.addPrivateTool(
'filterTool',
'InDet::InDetTrackTruthFilterTool' )
284 config.addPrivateTool(
'filterTool.trackOriginTool',
'InDet::InDetTrackTruthOriginTool' )
287 alg.filterWP =
"LOOSE"
288 elif self.
cutLevel ==
"TightPrimary":
289 alg.filterWP =
"TIGHT"
291 raise ValueError (
'Attempting to set TruthFilter WP based on cut level: \"'
292 + self.efficiencyWP +
'\" that is not supported.')
294 if config.geometry()
is LHCPeriod.Run2:
296 alg.filterTool.calibFileNomEff =
"InDetTrackSystematicsTools/CalibData_22.0_2022-v00/TrackingRecommendations_prelim_rel22.root"
297 alg.filterTool.fFakeLoose = 0.10
298 alg.filterTool.fFakeTight = 1.00
299 elif config.geometry()
is LHCPeriod.Run3:
300 if config.campaign()
is Campaign.MC23a:
302 alg.filterTool.calibFileNomEff =
"InDetTrackSystematicsTools/CalibData_22.0_2022-v00/TrackingRecommendations_prelim_rel22.root"
303 alg.filterTool.fFakeLoose = 0.40
304 alg.filterTool.fFakeTight = 1.00
305 elif config.campaign()
is Campaign.MC23d:
307 alg.filterTool.calibFileNomEff =
"InDetTrackSystematicsTools/CalibData_22.0_2022-v00/TrackingRecommendations_prelim_rel22.root"
308 alg.filterTool.fFakeLoose = 0.40
309 alg.filterTool.fFakeTight = 1.00
310 elif not (self.calibFile
and self.fFakeLoose
and self.fFakeTight):
311 raise ValueError (
'No efficiency recommendations found for capaign \"'
312 + config.campaign().value +
'\" in Run 3. '
313 'Please check that the recommendations exist.')
314 elif not (self.calibFile
and self.fFakeLoose
and self.fFakeTight):
315 raise ValueError (
'No efficiency recommendations found for geometry \"'
316 + config.geometry().value +
'\". Please check '
317 'the configuration.')
320 alg.filterTool.calibFileNomEff = self.calibFile
322 alg.filterTool.fFakeLoose = self.fFakeLoose
324 alg.filterTool.fFakeTight = self.fFakeTight
325 if self.filterToolSeed:
326 alg.filterTool.Seed = self.filterToolSeed
327 if self.trkEffSystScale:
328 alg.filterTool.trkEffSystScale = self.trkEffSystScale
329 alg.inDetTracks = config.readName (self.containerName)
330 alg.preselection = config.getPreselection (self.containerName,
'')
331 config.addSelection (self.containerName, self.selectionName, alg.selectionDecoration,
332 preselection=self.addSelectionToPreselection)