ATLAS Offline Software
TriggerConfigAccess.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
2 
3 from typing import Any, Optional
4 from AthenaConfiguration.AccumulatorCache import AccumulatorCache
5 from AthenaCommon.Logging import logging
6 log = logging.getLogger( "TriggerConfigAccess.py" )
7 
8 from .TrigConfigSvcCfg import getTrigConfigFromFlag, getL1MenuFileName, getHLTMenuFileName, getL1PrescalesSetFileName, getHLTPrescalesSetFileName, getBunchGroupSetFileName, getHLTJobOptionsFileName, getHLTMonitoringFileName
9 
10 from TrigConfIO.L1TriggerConfigAccess import L1MenuAccess, L1PrescalesSetAccess, BunchGroupSetAccess
11 from TrigConfIO.HLTTriggerConfigAccess import HLTMenuAccess, HLTPrescalesSetAccess, HLTJobOptionsAccess, HLTMonitoringAccess
12 
13 from AthenaConfiguration.AutoConfigFlags import GetFileMD
14 from AthenaConfiguration.Enums import Format
15 
16 from functools import lru_cache
17 
18 """
19 Access to the trigger configuration in python is provided depending on
20 the trigger configuration source
21 
22 The tc source is taken from the TriggerFlag triggerConfig
23 
24 1) tc source is set to INFILE
25 
26 This is usually the case when running on ESD, AOD, and dAOD files and
27 only in this case. An exception is RDO with trigger information in
28 MC. The menu and prescales are taken from the pool file, from the
29 in-file metadata.
30 
31 
32 2) tc source is set to FILE
33 
34 This is the case when executing the trigger with the configuration
35 taken from file. The filename is provided by the function
36 @getL1MenuFileName
37 
38 3) tc source is set to DB
39 
40 This is the case when executing the trigger from the DB. The DB
41 connection and keys are provided by the triggerConfig flag
42 
43 4) tc source is COOL
44 
45 This is the case when reconstructing the data. From COOL the
46 configuration keys and db alias are taken, the configurations
47 are then loaded from the DB.
48 
49 """
50 
51 def getKeysFromConditions(runNr: int, lbNr: int, flags) -> dict[str, str | int]:
52  if flags.Trigger.useCrest:
53  confKeys: dict[str, str | int] = getKeysFromCrest(runNr, lbNr, flags.Trigger.crestServer)
54  else:
55  confKeys = getKeysFromCool(runNr, lbNr)
56 
57  # dbalias mapping
58  dbaliasMapping = {
59  "TRIGGERDBR2R" : "TRIGGERDB",
60  "TRIGGERDBV2" : "TRIGGERDB_RUN1"
61  }
62  if confKeys["DB"] in dbaliasMapping:
63  confKeys["DB"] = dbaliasMapping[ confKeys["DB"] ]
64 
65  return confKeys
66 
67 @lru_cache(maxsize=None)
68 def getKeysFromCrest(runNr: int, lbNr: int, crest_server: str) -> dict[str, str | int]:
69  """Return dictionary of trigger keys for given run and lumiblock number from crest
70  """
71  from TrigConfStorage.TriggerCrestUtil import TriggerCrestUtil
72  return TriggerCrestUtil.getTrigConfKeys(runNumber=runNr, lumiBlock=lbNr, server=crest_server)
73 
74 @lru_cache(maxsize=None)
75 def getKeysFromCool(runNr: int, lbNr: int = 0) -> dict[str, str | int]:
76  """Return dictionary of trigger keys for given run and lumiblock number
77  """
78  from TrigConfStorage.TriggerCoolUtil import TriggerCoolUtil
79  return TriggerCoolUtil.getTrigConfKeys(runNumber=runNr, lumiBlock=lbNr)
80 
81 def getDBKeysFromMetadata(flags) -> Optional[dict[str, Any]]:
82  """Provides access to the database keys from the in-file metadata
83 
84  Gets the database keys from the in-file metadata which are stored together with the json representation
85  If the keys are in the file, then usually SMK, L1PSK and HLTPSK are present.
86  The bunchgroupset is not stored in the metadata, so 0 is returned for the BGS key for completeness.
87 
88  Example of the 'TriggerConfigInfo' metadata entry (run 453713, lb 1416):
89  {
90  'HLT': {'key': 3221, 'name': 'PhysicsP1_pp_run3_v1'},
91  'HLTPS': {'key': 6247, 'name': 'PhysicsP1_pp_run3_v1'},
92  'L1': {'key': 3221, 'name': 'Physics_pp_run3_v1'},
93  'L1PS': {'key': 7475, 'name': 'Physics_pp_run3_v1'}
94  }
95  @returns: dictionary with the DB keys. Returns 'None' if information is not present.
96  """
97  metadata = GetFileMD(flags.Input.Files)
98  keys = metadata.get("TriggerConfigInfo", None)
99  if keys is None:
100  return None
101  return {
102  'SMK': keys['HLT']['key'] if 'HLT' in keys else 0,
103  'LVL1PSK': keys['L1PS']['key'] if 'L1PS' in keys else 0,
104  'HLTPSK': keys['HLTPS']['key'] if 'HLTPS' in keys else 0,
105  'BGSK': 0
106  }
107 
108 """
109 Returns a string-serialised JSON object from the metadata store.
110 Checks AOD syntax first, then fully-qualified ESD syntax
111 """
112 def _getJSONFromMetadata(flags, key) -> Optional[dict[str,Any]]:
113  if flags.Input.Format != Format.POOL:
114  raise RuntimeError("Cannot read trigger configuration (%s) from input type %s", key, flags.Input.Format)
115  from AthenaConfiguration.AutoConfigFlags import GetFileMD
116  metadata = GetFileMD(flags.Input.Files)
117  menu_json = metadata.get(key, None)
118  if menu_json is None:
119  menu_json = metadata.get('DataVector<xAOD::TriggerMenuJson_v1>_%s' % key, None)
120  if menu_json is None:
121  if key == 'TriggerMenuJson_HLTMonitoring':
122  # currently the HLT Monitoring information is missing from many pool files' metadata
123  log.info("Trigger metadata with key 'TriggerMenuJson_HLTMonitoring' is not available in this file. This feature is currently being introduced.")
124  return None
125  else:
126  raise RuntimeError("Cannot read trigger configuration (%s) from input file metadata" % key)
127  return menu_json
128 
129 
130 """
131 
132 L1 information
133 
134 """
135 @AccumulatorCache
136 def getL1MenuAccess( flags ) -> L1MenuAccess:
137  tc = getTrigConfigFromFlag( flags )
138  if tc["SOURCE"] == "FILE":
139  cfg = L1MenuAccess( filename = getL1MenuFileName( flags ) )
140  elif tc["SOURCE"] == "COOL":
141  """This is the case when reconstructing the data."""
142  if len(flags.Input.RunNumbers) == 0:
143  raise RuntimeError("No run number available in input metadata")
144  keysFromConditions = getKeysFromConditions( flags.Input.RunNumbers[0], 0, flags )
145  cfg = L1MenuAccess( dbalias = keysFromConditions["DB"], smkey = keysFromConditions['SMK'] )
146  elif tc["SOURCE"] == "DB":
147  cfg = L1MenuAccess( dbalias = tc["DBCONN"], smkey = tc["SMK"] )
148  elif tc["SOURCE"] == "INFILE":
149  cfg = L1MenuAccess(jsonString=_getJSONFromMetadata(flags, key='TriggerMenuJson_L1'))
150  else:
151  raise RuntimeError("Unknown source of trigger configuration: %s" % tc["SOURCE"])
152  return cfg
153 
154 
155 @AccumulatorCache
156 def getL1PrescalesSetAccess( flags ) -> L1PrescalesSetAccess:
157  tc = getTrigConfigFromFlag( flags )
158  if tc["SOURCE"] == "FILE":
159  cfg = L1PrescalesSetAccess( filename = getL1PrescalesSetFileName( flags ) )
160  elif tc["SOURCE"] == "COOL":
161  """This is the case when reconstructing the data."""
162  if len(flags.Input.RunNumbers) == 0:
163  raise RuntimeError("No run number available in input metadata")
164  keysFromConditions = getKeysFromConditions( flags.Input.RunNumbers[0], 0, flags )
165  cfg = L1PrescalesSetAccess( dbalias = keysFromConditions["DB"], l1pskey = keysFromConditions['LVL1PSK'] )
166  elif tc["SOURCE"] == "DB":
167  cfg = L1PrescalesSetAccess( dbalias = tc["DBCONN"], l1pskey = tc["LVL1PSK"] )
168  elif tc["SOURCE"] == "INFILE":
169  cfg = L1PrescalesSetAccess(jsonString=_getJSONFromMetadata(flags, key='TriggerMenuJson_L1PS'))
170  else:
171  raise RuntimeError("Unknown source of trigger configuration: %s" % tc["SOURCE"])
172  return cfg
173 
174 
175 @AccumulatorCache
176 def getBunchGroupSetAccess( flags ) -> BunchGroupSetAccess:
177  tc = getTrigConfigFromFlag( flags )
178  if tc["SOURCE"] == "FILE":
179  cfg = BunchGroupSetAccess( filename = getBunchGroupSetFileName( flags ) )
180  elif tc["SOURCE"] == "COOL":
181  """This is the case when reconstructing the data."""
182  if len(flags.Input.RunNumbers) == 0:
183  raise RuntimeError("No run number available in input metadata")
184  keysFromConditions = getKeysFromConditions( flags.Input.RunNumbers[0], 0, flags )
185  cfg = BunchGroupSetAccess( dbalias = keysFromConditions["DB"], bgskey = keysFromConditions['BGSK'] )
186  elif tc["SOURCE"] == "DB":
187  cfg = BunchGroupSetAccess( dbalias = tc["DBCONN"], bgskey = tc["BGSK"] )
188  elif tc["SOURCE"] == "INFILE":
189  if flags.Input.Format != Format.POOL:
190  raise RuntimeError(f"Cannot read trigger configuration (Bunchgroup Set) from input type {flags.Input.Format}")
191  raise NotImplementedError("Python access to the trigger configuration (Bunchgroup Set) from in-file metadata not yet implemented")
192  else:
193  raise RuntimeError("Unknown source of trigger configuration: %s" % tc["SOURCE"])
194  return cfg
195 
196 
197 """
198 
199 HLT information
200 
201 """
202 @AccumulatorCache
203 def getHLTMenuAccess( flags ) -> HLTMenuAccess:
204  tc = getTrigConfigFromFlag( flags )
205  if tc["SOURCE"] == "FILE":
206  cfg = HLTMenuAccess( filename = getHLTMenuFileName( flags ) )
207  elif tc["SOURCE"] == "COOL":
208  """This is the case when reconstructing the data."""
209  if len(flags.Input.RunNumbers) == 0:
210  raise RuntimeError("No run number available in input metadata")
211  keysFromConditions = getKeysFromConditions( flags.Input.RunNumbers[0], 0, flags )
212  cfg = HLTMenuAccess( dbalias = keysFromConditions["DB"], smkey = keysFromConditions['SMK'] )
213  elif tc["SOURCE"] == "DB":
214  cfg = HLTMenuAccess( dbalias = tc["DBCONN"], smkey = tc["SMK"] )
215  elif tc["SOURCE"] == "INFILE":
216  cfg = HLTMenuAccess(jsonString=_getJSONFromMetadata(flags, key='TriggerMenuJson_HLT'))
217  else:
218  raise RuntimeError("Unknown source of trigger configuration: %s" % tc["SOURCE"])
219  return cfg
220 
221 
222 @AccumulatorCache
223 def getHLTPrescalesSetAccess( flags ) -> HLTPrescalesSetAccess:
224  tc = getTrigConfigFromFlag( flags )
225  if tc["SOURCE"] == "FILE":
226  cfg = HLTPrescalesSetAccess( filename = getHLTPrescalesSetFileName( flags ) )
227  elif tc["SOURCE"] == "COOL":
228  """This is the case when reconstructing the data."""
229  if len(flags.Input.RunNumbers) == 0:
230  raise RuntimeError("No run number available in input metadata")
231  keysFromConditions = getKeysFromConditions( flags.Input.RunNumbers[0], 0, flags )
232  cfg = HLTPrescalesSetAccess( dbalias = keysFromConditions["DB"], hltpskey = keysFromConditions['HLTPSK'] )
233  elif tc["SOURCE"] == "DB":
234  cfg = HLTPrescalesSetAccess( dbalias = tc["DBCONN"], hltpskey = tc["HLTPSK"] )
235  elif tc["SOURCE"] == "INFILE":
236  cfg = HLTPrescalesSetAccess(jsonString=_getJSONFromMetadata(flags, key='TriggerMenuJson_HLTPS'))
237  else:
238  raise RuntimeError("Unknown source of trigger configuration: %s" % tc["SOURCE"])
239  return cfg
240 
241 
242 @AccumulatorCache
243 def getHLTJobOptionsAccess( flags ) -> HLTJobOptionsAccess:
244  tc = getTrigConfigFromFlag( flags )
245  if tc["SOURCE"] == "FILE":
246  cfg = HLTJobOptionsAccess( filename = getHLTJobOptionsFileName() )
247  elif tc["SOURCE"] == "COOL":
248  """This is the case when reconstructing the data."""
249  if len(flags.Input.RunNumbers) == 0:
250  raise RuntimeError("No run number available in input metadata")
251  keysFromConditions = getKeysFromConditions( flags.Input.RunNumbers[0], 0, flags )
252  cfg = HLTJobOptionsAccess( dbalias = keysFromConditions["DB"], smkey = keysFromConditions['SMK'] )
253  elif tc["SOURCE"] == "DB":
254  cfg = HLTJobOptionsAccess( dbalias = tc["DBCONN"], smkey = tc["SMK"] )
255  elif tc["SOURCE"] == "INFILE":
256  raise NotImplementedError("Python access to the HLT Job Options configuration from in-file metadata is NOT SUPPORTED (this file is huge!)")
257  else:
258  raise RuntimeError("Unknown source of trigger configuration: %s" % tc["SOURCE"])
259  return cfg
260 
261 
262 @AccumulatorCache
263 def getHLTMonitoringAccess( flags = None, filterOnActiveChains = False ) -> HLTMonitoringAccess:
264  tc = getTrigConfigFromFlag( flags )
265  if tc["SOURCE"] == "FILE":
266  cfg = HLTMonitoringAccess( filename = getHLTMonitoringFileName( flags ) )
267  elif tc["SOURCE"] == "COOL":
268  """This is the case when reconstructing the data."""
269  if len(flags.Input.RunNumbers) == 0:
270  raise RuntimeError("No run number available in input metadata")
271  keysFromConditions = getKeysFromConditions( flags.Input.RunNumbers[0], 0, flags )
272  cfg = HLTMonitoringAccess( dbalias = keysFromConditions["DB"], smkey = keysFromConditions['SMK'] )
273  elif tc["SOURCE"] == "DB":
274  cfg = HLTMonitoringAccess( dbalias = tc["DBCONN"], smkey = tc["SMK"] )
275  elif tc["SOURCE"] == "INFILE":
276  jsonHLTMon = _getJSONFromMetadata(flags, key='TriggerMenuJson_HLTMonitoring')
277  if jsonHLTMon is not None:
278  cfg = HLTMonitoringAccess(jsonString=jsonHLTMon)
279  else:
280  keysFromInfileMD = getDBKeysFromMetadata(flags)
281  smkey = keysFromInfileMD['SMK'] if keysFromInfileMD is not None else 0
282  if smkey < 3000 and not flags.Input.isMC:
283  # Run 1/2 data or keys missing in metadata
284  log.info("Trigger metadata with key 'TriggerMenuJson_HLTMonitoring' is not available for Run 2 data. Returning empty dummy.")
285  jsonHLTMon = '{"filetype": "hltmonitoringsummary","name": "EmptyDefault", "signatures": {}}'
286  cfg = HLTMonitoringAccess(jsonString=jsonHLTMon)
287  else:
288  # Run 3 data or MC
289  try:
290  log.info("Falling back on reading the HLTMonitoring from the TRIGGERDB_RUN3 for SMK %i.", smkey)
291  cfg = HLTMonitoringAccess( dbalias = "TRIGGERDB_RUN3", smkey = smkey )
292  except KeyError:
293  # SMK for this run has no HLT monitoring (earlier 2022 data) => providing dummy configuration
294  log.info("Trigger HLTMonitoring is not available for SMK %i. Returning empty dummy.", smkey)
295  jsonHLTMon = '{"filetype": "hltmonitoringsummary","name": "EmptyDefault", "signatures": {}}'
296  cfg = HLTMonitoringAccess(jsonString=jsonHLTMon)
297 
298  else:
299  raise RuntimeError("Unknown source of trigger configuration: %s" % tc["SOURCE"])
300 
301  # Optional deletion of chains from the monitoring JSON which were not enabled,
302  # based on the first HLT PS set in the file or the HLT PS set for the RAW file's LB.
303  if filterOnActiveChains:
304  hltPs = getHLTPrescalesSetAccess(flags)
305  if hltPs:
306  for sig in cfg["signatures"]:
307  for chain in list(cfg["signatures"][sig]): # Make a copy as we might be deleting
308  if chain in hltPs.chainNames() and not hltPs.enabled(chain):
309  del cfg["signatures"][sig][chain]
310 
311  return cfg
python.TriggerConfigAccess.getHLTMenuAccess
HLTMenuAccess getHLTMenuAccess(flags)
Definition: TriggerConfigAccess.py:203
python.AutoConfigFlags.GetFileMD
def GetFileMD(filenames, allowEmpty=True, maxLevel='peeker')
Definition: AutoConfigFlags.py:65
python.TriggerConfigAccess.getL1PrescalesSetAccess
L1PrescalesSetAccess getL1PrescalesSetAccess(flags)
Definition: TriggerConfigAccess.py:156
python.TrigConfigSvcCfg.getHLTMenuFileName
def getHLTMenuFileName(flags)
Definition: TrigConfigSvcCfg.py:177
python.TrigConfigSvcCfg.getTrigConfigFromFlag
def getTrigConfigFromFlag(flags)
Definition: TrigConfigSvcCfg.py:87
python.TriggerConfigAccess.getHLTPrescalesSetAccess
HLTPrescalesSetAccess getHLTPrescalesSetAccess(flags)
Definition: TriggerConfigAccess.py:223
python.TriggerConfigAccess.getHLTMonitoringAccess
HLTMonitoringAccess getHLTMonitoringAccess(flags=None, filterOnActiveChains=False)
Definition: TriggerConfigAccess.py:263
python.TrigConfigSvcCfg.getL1MenuFileName
def getL1MenuFileName(flags)
Definition: TrigConfigSvcCfg.py:173
python.TrigConfigSvcCfg.getHLTJobOptionsFileName
def getHLTJobOptionsFileName()
Definition: TrigConfigSvcCfg.py:197
python.TrigConfigSvcCfg.getBunchGroupSetFileName
def getBunchGroupSetFileName(flags)
Definition: TrigConfigSvcCfg.py:193
python.TrigConfigSvcCfg.getL1PrescalesSetFileName
def getL1PrescalesSetFileName(flags)
Definition: TrigConfigSvcCfg.py:185
python.TriggerConfigAccess.getKeysFromCrest
dict[str, str|int] getKeysFromCrest(int runNr, int lbNr, str crest_server)
Definition: TriggerConfigAccess.py:68
python.TriggerConfigAccess.getKeysFromConditions
dict[str, str|int] getKeysFromConditions(int runNr, int lbNr, flags)
Definition: TriggerConfigAccess.py:51
python.TriggerConfigAccess.getKeysFromCool
dict[str, str|int] getKeysFromCool(int runNr, int lbNr=0)
Definition: TriggerConfigAccess.py:75
python.TriggerConfigAccess.getDBKeysFromMetadata
Optional[dict[str, Any]] getDBKeysFromMetadata(flags)
Definition: TriggerConfigAccess.py:81
python.TrigConfigSvcCfg.getHLTMonitoringFileName
def getHLTMonitoringFileName(flags)
Definition: TrigConfigSvcCfg.py:181
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
python.TriggerConfigAccess.getL1MenuAccess
L1MenuAccess getL1MenuAccess(flags)
Definition: TriggerConfigAccess.py:136
python.TriggerConfigAccess._getJSONFromMetadata
Optional[dict[str, Any]] _getJSONFromMetadata(flags, key)
Definition: TriggerConfigAccess.py:112
python.TriggerConfigAccess.getBunchGroupSetAccess
BunchGroupSetAccess getBunchGroupSetAccess(flags)
Definition: TriggerConfigAccess.py:176
python.TriggerConfigAccess.getHLTJobOptionsAccess
HLTJobOptionsAccess getHLTJobOptionsAccess(flags)
Definition: TriggerConfigAccess.py:243
python.TrigConfigSvcCfg.getHLTPrescalesSetFileName
def getHLTPrescalesSetFileName(flags)
Definition: TrigConfigSvcCfg.py:189