ATLAS Offline Software
Loading...
Searching...
No Matches
AutoConfigFlags.py
Go to the documentation of this file.
1# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2
3from PyUtils.MetaReader import read_metadata, lite_primary_keys_to_keep, lite_TagInfo_keys_to_keep
4from AthenaCommon.Logging import logging
5from functools import lru_cache
6
7msg = logging.getLogger('AutoConfigFlags')
8
9# Module level cache of file-metadata:
10_fileMetaData = dict()
11
13 def __init__(self, filename, maxLevel='peeker'):
14 self.metadata = {}
15 self.filename = filename
16 self.currentAccessLevel = 'lite'
17 self.maxAccessLevel = maxLevel
18 thisFileMD = read_metadata(filename, None, 'lite')
19 self.metadata.update(thisFileMD[self.filename])
20 msg.debug("Loaded using 'lite' %s", str(self.metadata))
21
22 def _loadMore(self, level):
23 self.currentAccessLevel = level
24
25 thisFileMD = read_metadata(self.filename, None, level)
26 self.metadata.update(thisFileMD[self.filename])
27
28 def get(self, key, default):
29 if key in self.metadata:
30 return self.metadata[key]
31 if key in lite_primary_keys_to_keep or key in lite_TagInfo_keys_to_keep:
32 # no need to load more
33 return default
34
35 if self.currentAccessLevel == self.maxAccessLevel:
36 return default
37
38 levels = []
39 if self.currentAccessLevel == 'lite':
40 levels = ['peeker', 'full'] if self.maxAccessLevel == 'full' else ['peeker']
41 elif self.currentAccessLevel == 'peeker':
42 levels = ['full']
43
44 for level in levels:
45 msg.info("Looking into the file in '%s' mode as the configuration requires more details: %s ", level, key)
46 self._loadMore(level)
47 if key in self.metadata:
48 return self.metadata[key]
49
50 return default
51
52 def __contains__(self, key):
53 self.get(key, None)
54 return key in self.metadata
55
56 def __getitem__(self, key):
57 return self.get(key, None)
58
59 def __repr__(self):
60 return repr(self.metadata)
61
62 def keys(self):
63 return self.metadata.keys()
64
65def GetFileMD(filenames, allowEmpty=True, maxLevel='peeker'):
66 if not filenames or '_ATHENA_GENERIC_INPUTFILE_NAME_' in filenames:
67 if allowEmpty:
68 msg.info("Running an input-less job. Will have empty metadata.")
69 return {}
70 raise RuntimeError("Metadata can not be read in an input-less job.")
71 if isinstance(filenames, str):
72 filenames = [filenames]
73 for filename in filenames:
74 if filename not in _fileMetaData:
75 msg.info("Obtaining metadata of auto-configuration by peeking into '%s'", filename)
76 _fileMetaData[filename] = DynamicallyLoadMetadata(filename, maxLevel)
77 if _fileMetaData[filename].maxAccessLevel != maxLevel:
78 _fileMetaData[filename].maxAccessLevel = maxLevel
79 if _fileMetaData[filename]['nentries'] not in [None, 0]:
80 return _fileMetaData[filename]
81 else:
82 msg.info("The file: %s has no entries, going to the next one for harvesting the metadata", filename)
83 msg.info("No file with events found, returning anyways metadata associated to the first file %s", filenames[0])
84 return _fileMetaData[filenames[0]]
85
86def _initializeGeometryParameters(geoTag,sqliteDB,sqliteDBFullPath):
87 """Read geometry database for all detectors"""
88
89 from AtlasGeoModel import CommonGeoDB
90 from PixelGeoModel import PixelGeoDB
91 from LArGeoAlgsNV import LArGeoDB
92 from MuonGeoModel import MuonGeoDB
93
94 if not sqliteDB:
95 # Read parameters from Oracle/Frontier
96 from AtlasGeoModel.AtlasGeoDBInterface import AtlasGeoDBInterface
97 dbGeomCursor = AtlasGeoDBInterface(geoTag)
98 dbGeomCursor.ConnectAndBrowseGeoDB()
99
100 params = { 'Common' : CommonGeoDB.InitializeGeometryParameters(dbGeomCursor),
101 'Pixel' : PixelGeoDB.InitializeGeometryParameters(dbGeomCursor),
102 'LAr' : LArGeoDB.InitializeGeometryParameters(dbGeomCursor),
103 'Muon' : MuonGeoDB.InitializeGeometryParameters(dbGeomCursor),
104 'Luminosity' : CommonGeoDB.InitializeLuminosityDetectorParameters(dbGeomCursor),
105 }
106
107 msg.debug('Config parameters retrieved from Geometry DB (Frontier/Oracle):')
108 for key in params.keys():
109 msg.debug(f'{key} -> {params[key]}')
110 else:
111 # Read parameters from SQLite
112 from AtlasGeoModel.AtlasGeoDBInterface import AtlasGeoDBInterface_SQLite
113 sqliteReader = AtlasGeoDBInterface_SQLite(geoTag,sqliteDBFullPath)
114 sqliteReader.ConnectToDB()
115
116 params = { 'Common' : CommonGeoDB.InitializeGeometryParameters_SQLite(sqliteReader),
120 'Luminosity' : CommonGeoDB.InitializeLuminosityDetectorParameters_SQLite(sqliteReader),
121 }
122
123 msg.debug('Config parameters retrieved from Geometry DB (SQLite):')
124 for key in params.keys():
125 msg.debug(f'{key} -> {params[key]}')
126
127 return params
128
129
130@lru_cache(maxsize=4) # maxsize=1 should be enough for most jobs
131def DetDescrInfo(geoTag, sqliteDB, sqliteDBFullPath):
132 """Query geometry DB for detector description. Returns dictionary with
133 detector description. Queries DB for each tag only once.
134
135 geoTag: geometry tag (e.g. ATLAS-R2-2016-01-00-01)
136 """
137 if not geoTag:
138 raise ValueError("No geometry tag specified")
139
140 detDescrInfo = _initializeGeometryParameters(geoTag,sqliteDB,sqliteDBFullPath)
141 detDescrInfo["geomTag"] = geoTag
142 return detDescrInfo
143
144
145@lru_cache(maxsize=4) # maxsize=1 should be enough for most jobs
146def getDefaultDetectors(geoTag, sqliteDB, sqliteDBFullPath, includeForward=False):
147 """Query geometry DB for detector description.
148 Returns a set of detectors used in a geometry tag.
149
150 geoTag: geometry tag (e.g. ATLAS-R2-2016-01-00-01)
151 """
152 detectors = DetDescrInfo(geoTag,sqliteDB,sqliteDBFullPath)['Common']['Detectors']
153
154 manualConfig = not DetDescrInfo(geoTag,sqliteDB,sqliteDBFullPath)['Common']["DetectorsConfigured"]
155
156
157 if manualConfig:
158 detectors.add('Bpipe')
159 if DetDescrInfo(geoTag,sqliteDB,sqliteDBFullPath)['Common']['Run'] not in ['RUN1', 'RUN2', 'RUN3']: # RUN4 and beyond
160 detectors.add('ITkPixel')
161 detectors.add('ITkStrip')
162 if DetDescrInfo(geoTag,sqliteDB,sqliteDBFullPath)['Luminosity']['BCMPrime']:
163 detectors.add('BCMPrime') # since https://gitlab.cern.ch/Atlas-Inner-Tracking/ITKLayouts/-/merge_requests/347 introduced BCMPrime geometry
164 if DetDescrInfo(geoTag,sqliteDB,sqliteDBFullPath)['Luminosity']['PLR']:
165 detectors.add('PLR')
166 else:
167 detectors.add('Pixel')
168 detectors.add('SCT')
169 detectors.add('TRT')
170 detectors.add('BCM')
171
172 if DetDescrInfo(geoTag,sqliteDB,sqliteDBFullPath)['Common']['Run'] not in ['RUN1', 'RUN2', 'RUN3']: # RUN4 and beyond
173 detectors.add('HGTD')
174
175 detectors.add('LAr')
176 detectors.add('Tile')
177
178
179 if DetDescrInfo(geoTag,sqliteDB,sqliteDBFullPath)['Common']['Run'] in ['RUN1', 'RUN2', 'RUN3']:
180 detectors.add('MBTS')
181
182 if DetDescrInfo(geoTag,sqliteDB,sqliteDBFullPath)['Muon']['HasMDT']:
183 detectors.add('MDT')
184 if DetDescrInfo(geoTag,sqliteDB,sqliteDBFullPath)['Muon']['HasRPC']:
185 detectors.add('RPC')
186 if DetDescrInfo(geoTag,sqliteDB,sqliteDBFullPath)['Muon']['HasTGC']:
187 detectors.add('TGC')
188 if DetDescrInfo(geoTag,sqliteDB,sqliteDBFullPath)['Muon']['HasCSC']:
189 detectors.add('CSC')
190 if DetDescrInfo(geoTag,sqliteDB,sqliteDBFullPath)['Muon']['HasSTGC']:
191 detectors.add('sTGC')
192 if DetDescrInfo(geoTag,sqliteDB,sqliteDBFullPath)['Muon']['HasMM']:
193 detectors.add('MM')
194
195 if includeForward:
196 detectors.add('Lucid')
197 if DetDescrInfo(geoTag,sqliteDB,sqliteDBFullPath)['Common']['Run'] not in ['RUN1']:
198 detectors.add('AFP')
199 detectors.add('ZDC')
200 detectors.add('ALFA')
201 detectors.add('FwdRegion')
202
203 return detectors
204
205
206# Based on RunDMCFlags.py
208 # this wrapper is intended to avoid an initial import
209 from .RunToTimestampData import RunToTimestampDict
210 return RunToTimestampDict
211
212
214 """This is used to hold a dictionary of the form
215 {152166:1269948352889940910, ...} to allow the
216 timestamp to be determined from the run.
217 """
218 run2timestampDict = getRunToTimestampDict()
219 timeStamps = [run2timestampDict.get(runNumber,1) for runNumber in runNumbers] # Add protection here?
220 return timeStamps
221
222
224 """Read in GeneratorsInfo from the input file
225 """
226 from AthenaConfiguration.Enums import ProductionStep
227 inputFiles = flags.Input.Files
228 if flags.Common.ProductionStep in [ProductionStep.Overlay, ProductionStep.FastChain] and flags.Input.SecondaryFiles and not flags.Overlay.ByteStream:
229 # Do something special for MC Overlay
230 inputFiles = flags.Input.SecondaryFiles
231 generatorsString = ""
232 from AthenaConfiguration.AutoConfigFlags import GetFileMD
233 if inputFiles:
234 generatorsString = GetFileMD(inputFiles).get("generators", "")
235 from GeneratorConfig.Versioning import generatorsGetFromMetadata
236 return generatorsGetFromMetadata( generatorsString )
237
238
240 """Read in special simulation job option fragments based on metadata
241 passed by the evgen stage
242 """
243 specialConfigDict = dict()
244 legacyPreIncludeToCAPostInclude = { 'SimulationJobOptions/preInclude.AMSB.py' : 'Charginos.CharginosConfig.AMSB_Cfg',
245 'SimulationJobOptions/preInclude.Monopole.py' : 'Monopole.MonopoleConfig.MonopoleCfg',
246 'SimulationJobOptions/preInclude.Quirks.py' : 'Quirks.QuirksConfig.QuirksCfg',
247 'SimulationJobOptions/preInclude.SleptonsLLP.py' : 'Sleptons.SleptonsConfig.SleptonsLLPCfg',
248 'SimulationJobOptions/preInclude.GMSB.py' : 'Sleptons.SleptonsConfig.GMSB_Cfg',
249 'SimulationJobOptions/preInclude.Qball.py' : 'Monopole.MonopoleConfig.QballCfg',
250 'SimulationJobOptions/preInclude.RHadronsPythia8.py' : 'RHadrons.RHadronsConfig.RHadronsCfg',
251 'SimulationJobOptions/preInclude.fcp.py' : 'Monopole.MonopoleConfig.fcpCfg',
252 'SimulationJobOptions/preInclude.Dyon.py' : 'Monopole.MonopoleConfig.DyonCfg' }
253 legacyPreIncludeToCAPreInclude = { 'SimulationJobOptions/preInclude.AMSB.py' : None,
254 'SimulationJobOptions/preInclude.Monopole.py' : 'Monopole.MonopoleConfig.MonopolePreInclude',
255 'SimulationJobOptions/preInclude.Quirks.py' : None,
256 'SimulationJobOptions/preInclude.SleptonsLLP.py' : None,
257 'SimulationJobOptions/preInclude.GMSB.py' : None,
258 'SimulationJobOptions/preInclude.Qball.py' : 'Monopole.MonopoleConfig.QballPreInclude',
259 'SimulationJobOptions/preInclude.RHadronsPythia8.py' : 'RHadrons.RHadronsConfig.RHadronsPreInclude',
260 'SimulationJobOptions/preInclude.fcp.py' : 'Monopole.MonopoleConfig.fcpPreInclude',
261 'SimulationJobOptions/preInclude.Dyon.py' : 'Monopole.MonopoleConfig.DyonPreInclude' }
262 specialConfigString = ''
263 from AthenaConfiguration.Enums import ProductionStep
264 inputFiles = flags.Input.Files
265 secondaryInputFiles = flags.Input.SecondaryFiles
266 if flags.Common.ProductionStep in [ProductionStep.Overlay, ProductionStep.FastChain] and not flags.Overlay.DataOverlay and flags.Input.SecondaryFiles:
267 # Do something special for MC Overlay
268 inputFiles = flags.Input.SecondaryFiles
269 secondaryInputFiles = flags.Input.Files
270 from AthenaConfiguration.AutoConfigFlags import GetFileMD
271 if len(inputFiles)>0:
272 specialConfigString = GetFileMD(inputFiles).get('specialConfiguration', '')
273 if (not len(specialConfigString) or specialConfigString == 'NONE') and len(secondaryInputFiles)>0:
274 # If there is no specialConfiguration metadata in the primary
275 # input try the secondary inputs (MC Overlay case)
276 specialConfigString = GetFileMD(secondaryInputFiles).get('specialConfiguration', '')
277 if len(specialConfigString)>0:
278
280 spcitems = specialConfigString.split(";")
281 for spcitem in spcitems:
282 #print spcitem
283
284 if not spcitem or spcitem.upper() == "NONE":
285 continue
286
287 if "=" not in spcitem:
288 spcitem = "preInclude=" + spcitem
289
290 k, v = spcitem.split("=")
291 if k == "preInclude" and v.endswith('.py'): # Translate old preIncludes into CA-based versions.
292 if v == 'SimulationJobOptions/preInclude.RhadronsPythia8.py':
293 v = 'SimulationJobOptions/preInclude.RHadronsPythia8.py' # ATLASSIM-6687 Fixup for older EVNT files
294 v1 = legacyPreIncludeToCAPreInclude[v]
295 if v1 is not None:
296 specialConfigDict[k] = v1
297 v2 = legacyPreIncludeToCAPostInclude[v]
298 if v2 is not None:
299 specialConfigDict['postInclude'] = v2
300 else:
301 specialConfigDict[k] = v
302 return specialConfigDict
303
__init__(self, filename, maxLevel='peeker')
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
InitializeGeometryParameters(dbGeomCursor)
Definition LArGeoDB.py:3
InitializeGeometryParameters_SQLite(sqliteDbReader)
Definition LArGeoDB.py:34
InitializeGeometryParameters(dbGeomCursor)
Definition MuonGeoDB.py:3
InitializeGeometryParameters_SQLite(sqliteDbReader)
Definition MuonGeoDB.py:31
InitializeGeometryParameters_SQLite(sqliteDbReader)
Definition PixelGeoDB.py:54
InitializeGeometryParameters(dbGeomCursor)
Definition PixelGeoDB.py:3
DetDescrInfo(geoTag, sqliteDB, sqliteDBFullPath)
_initializeGeometryParameters(geoTag, sqliteDB, sqliteDBFullPath)
getInitialTimeStampsFromRunNumbers(runNumbers)
GetFileMD(filenames, allowEmpty=True, maxLevel='peeker')
getDefaultDetectors(geoTag, sqliteDB, sqliteDBFullPath, includeForward=False)