ATLAS Offline Software
Loading...
Searching...
No Matches
DumpGeoConfig.py
Go to the documentation of this file.
1# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3#----------------------------------------------------------------
4# Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
5# Initial version: Feb 2024
6#
7# Main updates:
8# - 2025, Feb -- Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
9# Added dedicated DumpGeo flags as GeoModel.DumpGeo;
10# also, support the use of DumpGeo transforms and other
11# Athena jobs -- that is, not standalone. This is useful
12# when we want to dump the geometry that comes out as the
13# output of an Athena job.
14#----------------------------------------------------------------
15import os, sys
16
17# Set the CA environment
18from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
19from AthenaConfiguration.ComponentFactory import CompFactory
20
21# Set the Athena Logger
22from AthenaCommon.Logging import logging
23_logger = logging.getLogger('DumpGeo')
24
25def configureGeometry(flags, cfg):
26
27 # Beam pipe
28 if flags.Detector.GeometryBpipe:
29 from BeamPipeGeoModel.BeamPipeGMConfig import BeamPipeGeometryCfg
30 cfg.merge(BeamPipeGeometryCfg(flags))
31
32 # Inner Detectors
33 if flags.Detector.GeometryPixel:
34 from PixelGeoModel.PixelGeoModelConfig import PixelReadoutGeometryCfg
35 cfg.merge(PixelReadoutGeometryCfg(flags))
36 # TODO: do we need to set this separately?
37 # if flags.Detector.GeometryBCM:
38
39 if flags.Detector.GeometrySCT:
40 from SCT_GeoModel.SCT_GeoModelConfig import SCT_ReadoutGeometryCfg
41 cfg.merge(SCT_ReadoutGeometryCfg(flags))
42
43 if flags.Detector.GeometryTRT:
44 from TRT_GeoModel.TRT_GeoModelConfig import TRT_ReadoutGeometryCfg
45 cfg.merge(TRT_ReadoutGeometryCfg(flags))
46
47 # InDetServMat
48 # Trigger the build of the InDetServMat geometry
49 # if any ID subsystems have been enabled
50 if flags.Detector.GeometryID:
51 from InDetServMatGeoModel.InDetServMatGeoModelConfig import (
52 InDetServiceMaterialCfg)
53 cfg.merge(InDetServiceMaterialCfg(flags))
54
55 # Calorimeters
56 if flags.Detector.GeometryLAr:
57 from LArGeoAlgsNV.LArGMConfig import LArGMCfg
58 cfg.merge(LArGMCfg(flags))
59
60 if flags.Detector.GeometryTile:
61 from TileGeoModel.TileGMConfig import TileGMCfg
62 #flags.Tile.forceFullGeometry = True
63 cfg.merge(TileGMCfg(flags))
64 # We must set the "FULL" geometry explicitely, otherwise the "RECO" version will be used by default,
65 # which is almost 'empty' (just the first level of child volumes is created for the "RECO" geo).
66 cfg.getService("GeoModelSvc").DetectorTools["TileDetectorTool"].GeometryConfig="FULL"
67 # TODO: do we need to set this separately?
68 # if flags.Detector.GeometryMBTS:
69
70 # Muon spectrometer
71 if flags.Detector.GeometryMuon:
72 from MuonConfig.MuonGeometryConfig import MuonGeoModelCfg
73 cfg.merge(MuonGeoModelCfg(flags))
74
75 # HGTD (defined only for Run4 geometry tags)
76 if flags.Detector.GeometryHGTD:
77 #set up geometry
78 if flags.HGTD.Geometry.useGeoModelXml:
79 from HGTD_GeoModelXml.HGTD_GeoModelConfig import HGTD_SimulationGeometryCfg
80 else:
81 from HGTD_GeoModel.HGTD_GeoModelConfig import HGTD_SimulationGeometryCfg
82 cfg.merge(HGTD_SimulationGeometryCfg(flags))
83
84 # ITk (defined only for Run4 geometry tags)
85 if flags.Detector.GeometryITkPixel:
86 from PixelGeoModelXml.ITkPixelGeoModelConfig import ITkPixelReadoutGeometryCfg
87 cfg.merge(ITkPixelReadoutGeometryCfg(flags))
88 if flags.Detector.GeometryITkStrip:
89 from StripGeoModelXml.ITkStripGeoModelConfig import ITkStripReadoutGeometryCfg
90 cfg.merge(ITkStripReadoutGeometryCfg(flags))
91 # TODO: do we need to set those separately?
92 # if flags.Detector.GeometryBCMPrime:
93 # if flags.Detector.GeometryPLR:
94
95 # Cavern (disabled by default)
96 if flags.Detector.GeometryCavern:
97 from AtlasGeoModel.CavernGMConfig import CavernGeometryCfg
98 cfg.merge(CavernGeometryCfg(flags))
99
100 # Forward detectors (disabled by default)
101 if flags.Detector.GeometryLucid or flags.Detector.GeometryALFA or flags.Detector.GeometryAFP or flags.Detector.GeometryFwdRegion :
102 from AtlasGeoModel.ForDetGeoModelConfig import ForDetGeometryCfg
103 cfg.merge(ForDetGeometryCfg(flags))
104 if flags.Detector.GeometryZDC:
105 from ZDC_GeoM.ZdcGeoModelConfig import ZDC_DetToolCfg
106 cfg.merge(ZDC_DetToolCfg(flags))
107
108 # Temporary 'hack':
109 # Replace EllipticTube with Box,
110 # to bypass a crash due to lack of support
111 # for EllipticTube in GeoModelIO
112 # See: https://its.cern.ch/jira/browse/ATLASSIM-7263
113 if "ForwardRegionGeoModelTool" in cfg.getService("GeoModelSvc").DetectorTools:
114 cfg.getService("GeoModelSvc").DetectorTools["ForwardRegionGeoModelTool"].vp1Compatibility=True
115
116
118 if "AtlasVersion" in os.environ:
119 return os.environ["AtlasVersion"]
120 if "AtlasBaseVersion" in os.environ:
121 return os.environ["AtlasBaseVersion"]
122 return "Unknown"
123
124def DumpGeoCfg(flags, name="DumpGeoCA", **kwargs):
125 result = ComponentAccumulator()
126
127 _logger.info("We're using these 'GeoModel.DumpGeo' configuration flags:")
128 flags.dump("GeoModel.DumpGeo")
129
130 # Debug messages
131 _logger.debug("kwargs: %s", kwargs)
132
133 # set additional DumpGeo Alg's properties
134 _logger.verbose("Using ATLAS/Athena version: %s", getATLASVersion())
135 _logger.verbose("Using GeoModel ATLAS version: %s", flags.GeoModel.AtlasVersion)
136 kwargs.setdefault("AtlasRelease", getATLASVersion())
137 kwargs.setdefault("AtlasVersion", flags.GeoModel.AtlasVersion)
138
139 # Set the user's choice to see the content of the Treetops
140 if flags.GeoModel.DumpGeo.ShowTreetopContent:
141 kwargs.setdefault("ShowTreetopContent", True)
142
143 # Set the name of the output '.db' file.
144 # Pick the custom name if the user set it;
145 # otherwise, build it from the geometry tag
146 # and the filtered Detector Managers (if any).
147 outFileName = ""
148 if flags.GeoModel.DumpGeo.OutputFileName:
149 outFileName = flags.GeoModel.DumpGeo.OutputFileName
150 else:
151 # Handle the user's inputs and create a file name
152 # for the output SQLite, accordingly
153 outFileName = "geometry"
154 filterDetManagers = []
155 # - Put Geometry TAG into the file name
156 # NOTE: at this point, the user-defined Geo TAG args.detDescr,
157 # if set, has already replaced the default TAG in 'flags';
158 # so, we can use the latter, directy.
159 geoTAG = flags.GeoModel.AtlasVersion
160 _logger.info("+++ Dumping this Detector Description geometry TAG: '%s'", geoTAG)
161 outFileName = outFileName + "-" + geoTAG
162
163 if flags.GeoModel.DumpGeo.FilterDetManagers:
164
165 _logger.info("+++ Filtering on these GeoModel 'Detector Managers': '%s'", flags.GeoModel.DumpGeo.FilterDetManagers)
166
167 filterDetManagers = flags.GeoModel.DumpGeo.FilterDetManagers
168
169 # Set the filter variable that is used in the C++ code
170 kwargs.setdefault("UserFilterDetManager", filterDetManagers)
171
172 # - Put the filtered Detector Managers' names into the file name,
173 # if the user asked to filter on them
174 outFileName = outFileName + "-" + "-".join(filterDetManagers)
175
176 # - Add the final extension to the name of the output SQLite file
177 outFileName = outFileName + ".db"
178
179 # Set the output file name variable in the C++ code
180 kwargs.setdefault("OutSQLiteFileName", outFileName)
181
182 # Check if the output SQLite file exists already,
183 # and overwrite it if the user asked to do so;
184 # otherwise, throw an error.
185 if os.path.exists(outFileName):
186 if flags.GeoModel.DumpGeo.ForceOverwrite:
187 print("+ DumpGeo -- NOTE -- You chose to overwrite an existing geometry dump file with the same name, if present.")
188 # os.environ["DUMPGEOFORCEOVERWRITE"] = "1" # save to an env var, for later use in GeoModelStandalone/GeoExporter
189 # Check if the file exists before attempting to delete it
190 if os.path.exists(outFileName):
191 os.remove(outFileName)
192 _logger.verbose(f"The file {outFileName} has been deleted.")
193 else:
194 _logger.verbose(f"The file {outFileName} does not exist. So, it was not needed to 'force-delete' it. Continuing...")
195 else:
196 _logger.error(f"+++ DumpGeo -- ERROR!! The ouput file '{outFileName}' exists already!\nPlease move or remove it, or use the 'force' option: '-f' or '--forceOverWrite'.\n\n")
197 sys.exit()
198
199 # Schedule the DumpGeo Athena Algorithm
200 the_alg = CompFactory.DumpGeo(name="DumpGeoAlg", **kwargs)
201 result.addEventAlgo(the_alg, primary=True)
202 return result
203
204
205if __name__=="__main__":
206 # Run with e.g. python -m DumpGeo.DumpGeoConfig --detDescr=<ATLAS-geometry-tag> --filterDetManagers=[<list of tree tops>]
207
208 from AthenaConfiguration.TestDefaults import defaultGeometryTags
209
210 # ++++ Firstly we setup flags ++++
211 # +++ Set the Athena Flags
212 from AthenaConfiguration.AllConfigFlags import initConfigFlags
213 flags = initConfigFlags()
214
215 flags.Exec.MaxEvents = 0
216 # ^ We do not need any events to get the GeoModel tree from the GeoModelSvc.
217 # So, we don't need to run on any events,
218 # and we don't need to trigger any execute() Athena methods either.
219 # So, we set 'EvtMax' to 0 and Athena will skip the 'execute' phase;
220 # only the 'finalize' step will be run after the 'init'.
221 # -- Note:
222 # Also, if we run on events (even on 1 event) and we dump the Pixel
223 # as part of the DetectorManager filter, then we get a crash because
224 # the PixelDetectorManager complains during the 'execute' phase,
225 # because we 'stole' a handle on its TreeTop,
226 # which contains a FullPhysVol and cannot be shared.
227
228 flags.Concurrency.NumThreads = 0
229 # ^ DumpGeo will not work with the scheduler, since its condition/data dependencies are not known in advance
230 # More in details: the scheduler needs to know BEFORE the event, what the dependencies of each Alg are.
231 # So for DumpGeo, no dependencies are declared, which means the conditions data is not there.
232 # So when I load tracks, the geometry is missing and it crashes.
233 # Turning off the scheduler (with NumThreads=0) fixes this.
234
235 # +++ Set custom CLI parameters for DumpGeo when ran as a standalone program
236 # (that is, from the command line,
237 # and not as part of an Athena Transform or job)
238 parser = flags.getArgumentParser(description="Dump the detector geometry to a GeoModel-based SQLite '.db' file.")
239 parser.prog = 'dump-geo'
240 # here we extend the parser with CLI options specific to DumpGeo
241 parser.add_argument("--detDescr", default=defaultGeometryTags.RUN3,
242 help="The ATLAS geometry tag you want to dump (a convenience alias for the Athena flag 'GeoModel.AtlasVersion=TAG')", metavar="TAG")
243 parser.add_argument("--outFilename", default="",
244 help="Here you can set a custom name for the output '.db' file. It will replace the name that is built with the geometry tag and the list of fileterd Detector Managers, if any.", metavar="FILENAME")
245 # parser.add_argument("--filterTreeTops", help="Only output the GeoModel Tree Tops specified in the FILTER list; input is a comma-separated list")
246 parser.add_argument("--filterDetManagers", help="Only output the GeoModel Detector Managers specified in the FILTER list; input is a comma-separated list")
247 parser.add_argument("-f", "--forceOverwrite",
248 help="Force to overwrite an existing SQLite output file with the same name, if any", action = 'store_true')
249 parser.add_argument("--showTreetopContent",
250 help="Show the content of the Treetops --- (by default, only the list of Treetops is shown)", action = 'store_true')
251 parser.add_argument("--debugCA", help="Debug the CA configuration: print flags, tools, ... --- mainly, for DumpGeo developers. '1' prints a subset of the CA flags, '2' prints all of them.")
252
253 from AthenaConfiguration.TestDefaults import defaultTestFiles
254 parser.set_defaults(filesInput=f"{defaultTestFiles.EVNT[0]}")
255 args = flags.fillFromArgs(parser=parser)
256
257 if args.help:
258 # No point doing more here, since we just want to print the help.
259 sys.exit()
260
261 # +++ Get CLI parameters and set the corresponding configuration flags
262 # Get the user's custom file name, if set;
263 # this will replace the filename computed
264 # from the geometry tag and the filtered volumes
265 if args.outFilename:
266 flags.GeoModel.DumpGeo.OutputFileName = args.outFilename
267 if args.showTreetopContent:
268 flags.GeoModel.DumpGeo.ShowTreetopContent = True
269 if args.forceOverwrite:
270 flags.GeoModel.DumpGeo.ForceOverwrite = True
271
272
273 # +++ Set the empty input
274 _logger.verbose("+ About to set flags related to the input")
275 # Empty input is not normal for Athena, so we will need to check
276 # this repeatedly below (the same as with VP1)
277 dumpgeo_empty_input = False
278 # This covers the use case where we launch DumpGeo
279 # without input files; e.g., to check the detector description
280 from AthenaConfiguration.AutoConfigFlags import GetFileMD
281 if ( len(flags.Input.Files) == 0 or GetFileMD(flags.Input.Files).get("GeoAtlas", None) is None):
282 from Campaigns.Utils import Campaign
283 from AthenaConfiguration.TestDefaults import defaultConditionsTags, defaultGeometryTags
284
285 dumpgeo_empty_input = True
286 # NB Must set e.g. ConfigFlags.Input.Runparse_args() Number and
287 # ConfigFlags.Input.TimeStamp before calling the
288 # MainServicesCfg to avoid it attempting auto-configuration
289 # from an input file, which is empty in this use case.
290 # If you don't have it, it (and/or other Cfg routines) complains and crashes.
291 # See also:
292 # https://acode-browser1.usatlas.bnl.gov/lxr/source/athena/InnerDetector/InDetConditions/SCT_ConditionsAlgorithms/python/SCT_DCSConditionsTestAlgConfig.py#0023
293 flags.Input.ProjectName = "mc23_13p6TeV"
294 flags.Input.RunNumbers = [330000]
295 flags.Input.TimeStamps = [1]
296 flags.Input.TypedCollections = []
297
298 # set default CondDB and Geometry version
299 flags.IOVDb.GlobalTag = defaultConditionsTags.RUN3_MC
300 flags.Input.isMC = True
301 flags.Input.MCCampaign = Campaign.Unknown
302 flags.GeoModel.AtlasVersion = defaultGeometryTags.RUN3
303 _logger.verbose("+ ... Done")
304 _logger.verbose("+ empty input: '%s'" % dumpgeo_empty_input)
305
306 _logger.verbose("+ detDescr flag: '%s'" % args.detDescr)
307
308
309 # +++ Set the detector geometry
310 _logger.verbose("+ About to set the detector flags")
311 # So we can now set up the geometry flags from the input
312 from AthenaConfiguration.DetectorConfigFlags import setupDetectorFlags
313 setupDetectorFlags(flags, None, use_metadata=not dumpgeo_empty_input,
314 toggle_geometry=True, keep_beampipe=True)
315 _logger.verbose("+ ... Done")
316
317 if args.detDescr:
318 _logger.verbose("+ About to set this detector description tag: '%s'" % args.detDescr)
319 flags.GeoModel.AtlasVersion = args.detDescr
320 _logger.verbose("+ ... Done")
321
322 # finalize setting flags: lock them.
323 flags.lock()
324
325 # ++++ Now we setup the actual configuration ++++
326 _logger.verbose("+ Setup main services")
327 from AthenaConfiguration.MainServicesConfig import MainServicesCfg
328 cfg = MainServicesCfg(flags)
329 _logger.verbose("+ ...Done")
330
331 _logger.verbose("+ About to setup geometry")
332 configureGeometry(flags,cfg)
333 _logger.verbose("+ ...Done")
334
335 # debug messages
336 if args.debugCA:
337 debugCAlevel = int(args.debugCA)
338 if debugCAlevel >= 1:
339 _logger.verbose("Debug --- printing flags...")
340 print("\nflags:", flags)
341 for fl in flags:
342 print("fl:", fl)
343 print("\nflags.Tile:", flags.Tile)
344 for fl in flags.Tile:
345 print("fl.Tile:", fl)
346 print(dir(cfg))
347 print("cfg._privateTools: ", cfg._privateTools)
348 print("cfg._publicTools: ", cfg._publicTools)
349 if debugCAlevel >= 2:
350 flags.dump()
351 flags._loadDynaFlags('GeoModel')
352 flags._loadDynaFlags('Detector')
353 flags.dump('Detector.(Geometry|Enable)', True)
354 if debugCAlevel >= 1:
355 _logger.verbose("We're in a debugCA session, flags have been printed out, now exiting...")
356 sys.exit()
357
358 # +++ Configure DumpGeo and run
359 cfg.merge(DumpGeoCfg(flags))
360 cfg.run()
361
void print(char *figname, TCanvas *c1)
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
DumpGeoCfg(flags, name="DumpGeoCA", **kwargs)
configureGeometry(flags, cfg)