ATLAS Offline Software
Loading...
Searching...
No Matches
runITkAlign.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2
3# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
4
5# File: InDetAlignConfig/scripts/runIDAlign.py
6# Author: David Brunner (david.brunner@cern.ch), Thomas Strebler (thomas.strebler@cern.ch)
7
8import os
9from AthenaConfiguration.TestDefaults import defaultConditionsTags, defaultGeometryTags, defaultTestFiles
10
11
12def parser():
13 from argparse import ArgumentParser
14
15 parser = ArgumentParser(description="Script for ITk alignment")
16
17
18 parser.add_argument("-a", '--accumulate', action="store_true", help='Run accumulation step')
19 parser.add_argument("-s", '--solve', action="store_true", help='Run solve step')
20 parser.add_argument("-d", '--dryRun', action="store_true", help='Only configure, print and dont execute')
21 parser.add_argument("-b", '--baseDir', default = "./", help='Base dir where output is placed')
22
23
24 parser.add_argument("-i", "--input", default = defaultTestFiles.RDO_RUN4, nargs = "+", help='Input file(s)')
25 parser.add_argument("--maxEvents", default = -1, type = int, help='Number of maximal processed events')
26 parser.add_argument("-t", "--inputTracksCollection", default = "CombinedITkTracks", type = str, help='Name of the track collection to use')
27 parser.add_argument("--inputTFiles", default = "AlignmentTFile.root", type = str, help='ROOT file produced in MatrixTool in the accumulation step')
28
29 parser.add_argument("--alignmentConstants", default = [], nargs = "+", help='Local alignment constants to use')
30
31
32 parser.add_argument("--alignITk", action="store_true", help='Align whole ITk')
33 parser.add_argument("--alignITkPixel", action="store_true", help='Align ITkPixel')
34 parser.add_argument("--alignITkStrip", action="store_true", help='Align ITkStrip')
35
36
37 parser.add_argument("--globalTag", default = defaultConditionsTags.RUN4_MC, help='Global tag')
38 parser.add_argument("--atlasVersion", default = defaultGeometryTags.RUN4, help='Global tag')
39
40 parser.add_argument("--isBFieldOff", action="store_true", help='Check if Bfield is off')
41 parser.add_argument("--isCosmics", action="store_true", help='Check if cosmics run')
42 parser.add_argument("--isHeavyIon", action="store_true", help='Check if heavy ion run')
43
44
45 parser.add_argument("--localgeo", action="store_true", help='Use local geometry XML files')
46
47
48 parser.add_argument("--localDB", default = "", help='Use local DB file rather than from conditions tag')
49
50
51 parser.add_argument("--threads", default = 1, type = int, help='Number of threads')
52
53
54 return parser.parse_args()
55
56
57def stageLocalDBFiles(db_file):
58 """
59 Stage the local SQLite database, POOL payload file and POOL catalogue
60 in the current accumulation/solve working directory.
61 """
62
63 db_file = os.path.abspath(db_file)
64 db_dir = os.path.dirname(db_file)
65 db_basename = os.path.basename(db_file)
66 db_stem = os.path.splitext(db_basename)[0]
67
68 files_to_stage = (
69 db_basename,
70 f"{db_stem}.pool.root",
71 "PoolFileCatalog.xml",
72 )
73
74 for filename in files_to_stage:
75 source = os.path.join(db_dir, filename)
76 destination = os.path.join(os.getcwd(), filename)
77
78 if not os.path.exists(source):
79 raise FileNotFoundError(
80 f"Required local conditions file does not exist: {source}"
81 )
82
83 if os.path.lexists(destination):
84 os.remove(destination)
85
86 os.symlink(source, destination)
87
88
89kwargs = vars(parser())
90
91if kwargs["accumulate"] == kwargs["solve"]:
92 raise RuntimeError(
93 "Select exactly one running mode: either --accumulate or --solve"
94 )
95
96
97from AthenaConfiguration.AllConfigFlags import initConfigFlags
98flags = initConfigFlags()
99
100
101from InDetConfig.ConfigurationHelpers import OnlyTrackingPreInclude
102OnlyTrackingPreInclude(flags)
103
104
105flags.ITk.Align.accumulate = kwargs["accumulate"]
106flags.ITk.Align.baseDir = os.path.abspath(kwargs["baseDir"])
107
108flags.ITk.Align.alignITk = kwargs["alignITk"] or (not kwargs["alignITk"] and not kwargs["alignITkPixel"] and not kwargs["alignITkStrip"])
109flags.ITk.Align.alignITkPixel = kwargs["alignITkPixel"] or flags.ITk.Align.alignITk
110flags.ITk.Align.alignITkStrip = kwargs["alignITkStrip"] or flags.ITk.Align.alignITk
111
112flags.ITk.Align.writeSilicon = False #Issues with folders ATM - should be flags.ITk.Align.alignITkPixel or flags.ITk.Align.alignITkStrip
113
114flags.ITk.Align.inputTFiles = kwargs["inputTFiles"]
115
116flags.Input.Files = kwargs["input"]
117flags.Exec.MaxEvents = kwargs["maxEvents"] if not kwargs["solve"] else 1
118flags.IOVDb.GlobalTag = kwargs["globalTag"]
119
120flags.addFlag("ConstrainedTrackProvider.InputTracksCollection", kwargs["inputTracksCollection"])
121
122flags.GeoModel.Align.Dynamic = False
123flags.GeoModel.AtlasVersion = kwargs["atlasVersion"]
124
125if not flags.Input.isMC and kwargs["isCosmics"]:
126 from AthenaConfiguration.Enums import BeamType
127
128 flags.Beam.NumberOfCollisions = 0
129 flags.Beam.Type = BeamType.Cosmics
130 flags.Beam.Energy = 0.
131 flags.Beam.BunchSpacing = 50
132
133if kwargs["isHeavyIon"]:
134 flags.Beam.BunchSpacing = 50
135 flags.Reco.EnableHI = True
136 flags.HeavyIon.doGlobal = True
137
138else:
139 flags.Beam.BunchSpacing = 25
140
141if not kwargs["isBFieldOff"]:
142 flags.BField.solenoidOn = True
143 flags.BField.barrelToroidOn = True
144 flags.BField.endcapToroidOn = True
145
146else:
147 flags.BField.solenoidOn = False
148 flags.BField.barrelToroidOn = False
149 flags.BField.endcapToroidOn = False
150
151
152if kwargs["localgeo"]:
153 flags.ITk.Geometry.AllLocal = True
154
155if flags.ITk.Align.alignITkPixel:
156 flags.ITk.Geometry.pixelAlignable = True
157if flags.ITk.Align.alignITkStrip:
158 flags.ITk.Geometry.stripAlignable = True
159
160if kwargs["threads"] > 0:
161 flags.Concurrency.NumThreads = kwargs["threads"]
162
163
164# Uncomment for ATLAS-P2-RUN4-04-00-00 / ATLAS-P2-RUN4-05-00-00.
165# flags.DQ.useTrigger = False
166
167# Uncomment when running the monitoring configuration to produce IDAlignMon.root.
168# flags.Output.HISTFileName = "IDAlignMon.root"
169
170
171DBFile = ""
172DBName = "OFLCOND"
173misalignModeMap = {0:'InDetSi_MisalignmentMode_no Misalignment',
174 1: 'InDetSi_MisalignmentMode_misalignment by 6 parameters',
175 2: 'InDetSi_MisalignmentMode_random misalignment',
176 3: 'InDetSi_MisalignmentMode_IBL-stave temperature dependent bowing',
177 7: 'InDetSi_MisalignmentMode_misalignment according to module indices',
178 41: 'InDetSi_MisalignmentMode_ITk endcap beam-pipe z shift',
179 42: 'InDetSi_MisalignmentMode_ITk pixel barrel layer bowing',
180 43: 'InDetSi_MisalignmentMode_ITk barrel radial expansion',
181 11: 'InDetSi_MisalignmentMode_R deltaR (radial expansion)', 12: 'Phi deltaR (ellipse)',13: 'Z deltaR (funnel)',
182 21: 'InDetSi_MisalignmentMode_R deltaPhi (curl)', 22: 'Phi deltaPhi (clamshell) ',23:'Z deltaPhi (twist)',
183 31: 'InDetSi_MisalignmentMode_R deltaZ (telescope)',32:'Phi deltaZ (skew)',33:'Z deltaZ (z-expansion)'}
184
185get_db_name = os.path.basename(kwargs["localDB"])
186
187misalign_mode = int(get_db_name.removeprefix("MisalignmentSet").removesuffix(".db"))
188alignment_tag = misalignModeMap.get(int(misalign_mode),'unknown')
189if kwargs["localDB"]:
190 flags.ITk.Align.useLocalDatabase = True
191
192 if os.path.isabs(kwargs["localDB"]):
193 DBFile = os.path.abspath(kwargs["localDB"])
194 else:
195 DBFile = os.path.abspath(os.path.join(flags.ITk.Align.baseDir,kwargs["localDB"],))
196
197 if not os.path.exists(DBFile):
198 raise FileNotFoundError(f"Local alignment database does not exist: {DBFile}")
199
200 flags.IOVDb.DBConnection = (f"sqlite://;schema={DBFile};dbname={DBName}")
201
202 flags.ITk.Geometry.alignmentFolder = "/Indet/AlignITk"
203
204
205flags.lock()
206
207
208from RecJobTransforms.RecoSteering import RecoSteering
209cfg = RecoSteering(flags)
210
211if flags.ITk.Align.useLocalDatabase:
212 from IOVDbSvc.IOVDbSvcConfig import addFolders
213 print("Adding Align Folder "+flags.ITk.Geometry.alignmentFolder+" from local "+DBName+" Database in file "+DBFile)
214 cfg.merge(addFolders(flags,flags.ITk.Geometry.alignmentFolder,detDb=os.path.basename(DBFile),db=DBName,tag=alignment_tag,className="AlignableTransformContainer",))
215
216from MuonConfig.MuonGeometryConfig import MuonIdHelperSvcCfg
217cfg.getPrimaryAndMerge(MuonIdHelperSvcCfg(flags))
218
219
220if kwargs["accumulate"]:
221
222 # First configure the accumulation workflow.
223 from InDetAlignConfig.AccumulateITkConfig import ITkAccumulateCfg
224 cfg.merge(ITkAccumulateCfg(flags))
225 work_dir = os.path.join(flags.ITk.Align.baseDir,"Accumulate",)
226 os.makedirs(work_dir,exist_ok=True,)
227 os.chdir(work_dir)
228
229 # Make SQLite, POOL payload and POOL catalogue visible from the runtime working directory.
230 if flags.ITk.Align.useLocalDatabase:
231 stageLocalDBFiles(DBFile)
232
233
234elif kwargs["solve"] and not kwargs["accumulate"]:
235
236 # First configure the solve workflow.
237 from InDetAlignConfig.SolveITkConfig import ITkSolveCfg
238 cfg.merge(ITkSolveCfg(flags))
239
240 # Then move to the solve directory.
241 work_dir = os.path.join(flags.ITk.Align.baseDir,"Solve",)
242 os.makedirs(work_dir,exist_ok=True,)
243 os.chdir(work_dir)
244
245 if flags.ITk.Align.useLocalDatabase:
246 stageLocalDBFiles(DBFile)
247
248else:
249 raise Exception("You can run either the acculumation step or the solve step, but not both or neither at the same time!")
250
251
252
253if kwargs["dryRun"]:
254 cfg.printConfig()
255
256else:
257 cfg.run()
258
void print(char *figname, TCanvas *c1)
stageLocalDBFiles(db_file)