ATLAS Offline Software
AutoConfigFlags.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 
3 from PyUtils.MetaReader import read_metadata, lite_primary_keys_to_keep, lite_TagInfo_keys_to_keep
4 from AthenaCommon.Logging import logging
5 from functools import lru_cache
6 
7 msg = 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 
65 def 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 
86 def _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),
117  'Pixel' : PixelGeoDB.InitializeGeometryParameters_SQLite(sqliteReader),
118  'LAr' : LArGeoDB.InitializeGeometryParameters_SQLite(sqliteReader),
119  'Muon' : MuonGeoDB.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
131 def 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
146 def 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 
223 def getGeneratorsInfo(flags):
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  legacyPreIncludeToCAPreInclude = { 'SimulationJobOptions/preInclude.AMSB.py' : None,
253  'SimulationJobOptions/preInclude.Monopole.py' : 'Monopole.MonopoleConfig.MonopolePreInclude',
254  'SimulationJobOptions/preInclude.Quirks.py' : None,
255  'SimulationJobOptions/preInclude.SleptonsLLP.py' : None,
256  'SimulationJobOptions/preInclude.GMSB.py' : None,
257  'SimulationJobOptions/preInclude.Qball.py' : 'Monopole.MonopoleConfig.QballPreInclude',
258  'SimulationJobOptions/preInclude.RHadronsPythia8.py' : 'RHadrons.RHadronsConfig.RHadronsPreInclude',
259  'SimulationJobOptions/preInclude.fcp.py' : 'Monopole.MonopoleConfig.fcpPreInclude' }
260  specialConfigString = ''
261  from AthenaConfiguration.Enums import ProductionStep
262  inputFiles = flags.Input.Files
263  secondaryInputFiles = flags.Input.SecondaryFiles
264  if flags.Common.ProductionStep in [ProductionStep.Overlay, ProductionStep.FastChain] and not flags.Overlay.DataOverlay and flags.Input.SecondaryFiles:
265  # Do something special for MC Overlay
266  inputFiles = flags.Input.SecondaryFiles
267  secondaryInputFiles = flags.Input.Files
268  from AthenaConfiguration.AutoConfigFlags import GetFileMD
269  if len(inputFiles)>0:
270  specialConfigString = GetFileMD(inputFiles).get('specialConfiguration', '')
271  if (not len(specialConfigString) or specialConfigString == 'NONE') and len(secondaryInputFiles)>0:
272  # If there is no specialConfiguration metadata in the primary
273  # input try the secondary inputs (MC Overlay case)
274  specialConfigString = GetFileMD(secondaryInputFiles).get('specialConfiguration', '')
275  if len(specialConfigString)>0:
276 
278  spcitems = specialConfigString.split(";")
279  for spcitem in spcitems:
280  #print spcitem
281 
282  if not spcitem or spcitem.upper() == "NONE":
283  continue
284 
285  if "=" not in spcitem:
286  spcitem = "preInclude=" + spcitem
287 
288  k, v = spcitem.split("=")
289  if k == "preInclude" and v.endswith('.py'): # Translate old preIncludes into CA-based versions.
290  if v == 'SimulationJobOptions/preInclude.RhadronsPythia8.py':
291  v = 'SimulationJobOptions/preInclude.RHadronsPythia8.py' # ATLASSIM-6687 Fixup for older EVNT files
292  v1 = legacyPreIncludeToCAPreInclude[v]
293  if v1 is not None:
294  specialConfigDict[k] = v1
295  v2 = legacyPreIncludeToCAPostInclude[v]
296  if v2 is not None:
297  specialConfigDict['postInclude'] = v2
298  else:
299  specialConfigDict[k] = v
300  return specialConfigDict
301 
python.AutoConfigFlags.GetFileMD
def GetFileMD(filenames, allowEmpty=True, maxLevel='peeker')
Definition: AutoConfigFlags.py:65
python.AutoConfigFlags.getGeneratorsInfo
def getGeneratorsInfo(flags)
Definition: AutoConfigFlags.py:223
PixelGeoDB.InitializeGeometryParameters_SQLite
def InitializeGeometryParameters_SQLite(sqliteDbReader)
Definition: PixelGeoDB.py:54
python.AutoConfigFlags.getDefaultDetectors
def getDefaultDetectors(geoTag, sqliteDB, sqliteDBFullPath, includeForward=False)
Definition: AutoConfigFlags.py:146
python.MetaReader.read_metadata
def read_metadata(filenames, file_type=None, mode='lite', promote=None, meta_key_filter=None, unique_tag_info_values=True, ignoreNonExistingLocalFiles=False)
Definition: MetaReader.py:70
python.AutoConfigFlags._initializeGeometryParameters
def _initializeGeometryParameters(geoTag, sqliteDB, sqliteDBFullPath)
Definition: AutoConfigFlags.py:86
MuonGeoDB.InitializeGeometryParameters
def InitializeGeometryParameters(dbGeomCursor)
Definition: MuonGeoDB.py:3
python.AutoConfigFlags.DynamicallyLoadMetadata.maxAccessLevel
maxAccessLevel
Definition: AutoConfigFlags.py:17
python.AutoConfigFlags.DynamicallyLoadMetadata.currentAccessLevel
currentAccessLevel
Definition: AutoConfigFlags.py:16
python.AutoConfigFlags.DynamicallyLoadMetadata.get
def get(self, key, default)
Definition: AutoConfigFlags.py:28
LArGeoDB.InitializeGeometryParameters
def InitializeGeometryParameters(dbGeomCursor)
Definition: LArGeoDB.py:3
python.AutoConfigFlags.DynamicallyLoadMetadata._loadMore
def _loadMore(self, level)
Definition: AutoConfigFlags.py:22
python.AutoConfigFlags.DynamicallyLoadMetadata.__getitem__
def __getitem__(self, key)
Definition: AutoConfigFlags.py:56
python.AutoConfigFlags.DynamicallyLoadMetadata
Definition: AutoConfigFlags.py:12
python.AutoConfigFlags.DynamicallyLoadMetadata.filename
filename
Definition: AutoConfigFlags.py:15
PyAthena::repr
std::string repr(PyObject *o)
returns the string representation of a python object equivalent of calling repr(o) in python
Definition: PyAthenaUtils.cxx:106
python.AutoConfigFlags.DynamicallyLoadMetadata.metadata
metadata
Definition: AutoConfigFlags.py:14
python.AutoConfigFlags.getRunToTimestampDict
def getRunToTimestampDict()
Definition: AutoConfigFlags.py:207
python.AutoConfigFlags.DynamicallyLoadMetadata.__repr__
def __repr__(self)
Definition: AutoConfigFlags.py:59
python.AutoConfigFlags.DynamicallyLoadMetadata.__init__
def __init__(self, filename, maxLevel='peeker')
Definition: AutoConfigFlags.py:13
LArGeoDB.InitializeGeometryParameters_SQLite
def InitializeGeometryParameters_SQLite(sqliteDbReader)
Definition: LArGeoDB.py:34
python.AutoConfigFlags.getInitialTimeStampsFromRunNumbers
def getInitialTimeStampsFromRunNumbers(runNumbers)
Definition: AutoConfigFlags.py:213
python.AutoConfigFlags.DynamicallyLoadMetadata.__contains__
def __contains__(self, key)
Definition: AutoConfigFlags.py:52
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
python.AutoConfigFlags.DynamicallyLoadMetadata.keys
def keys(self)
Definition: AutoConfigFlags.py:62
PixelGeoDB.InitializeGeometryParameters
def InitializeGeometryParameters(dbGeomCursor)
Definition: PixelGeoDB.py:3
python.Versioning.generatorsGetFromMetadata
def generatorsGetFromMetadata(metadataString)
Definition: Versioning.py:65
python.AutoConfigFlags.DetDescrInfo
def DetDescrInfo(geoTag, sqliteDB, sqliteDBFullPath)
Definition: AutoConfigFlags.py:131
str
Definition: BTagTrackIpAccessor.cxx:11
python.AutoConfigFlags.getSpecialConfigurationMetadata
def getSpecialConfigurationMetadata(flags)
Definition: AutoConfigFlags.py:239
MuonGeoDB.InitializeGeometryParameters_SQLite
def InitializeGeometryParameters_SQLite(sqliteDbReader)
Definition: MuonGeoDB.py:31