ATLAS Offline Software
Loading...
Searching...
No Matches
Trigger/TriggerCommon/TrigEDMConfig/python/Utils.py
Go to the documentation of this file.
1# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
2
3from functools import lru_cache
4from collections import defaultdict
5import re
6from GaudiKernel.DataHandle import DataHandle
7from AthenaCommon.Logging import logging
8log = logging.getLogger('TrigEDMConfig')
9
10@lru_cache(maxsize=None)
11def getEDMVersionFromBS(filename):
12 """Determine Trigger EDM version based on the input ByteStream file.
13
14 Run-3 EDM is indicated by HLT ROD version > 1.0. For Run 1 and 2 the
15 HLT ROD version was 0.0 and the run number is used to disambiguate between them.
16 """
17
18 boundary_run12 = 230000
19 boundary_run23 = 368000
20
21 import eformat
22 from libpyeformat_helper import SubDetector
23 bs = eformat.istream(filename)
24
25 rodVersionM = None
26 rodVersionL = None
27 # Find the first HLT ROBFragment in the first event
28 for robf in bs[0]:
29 if robf.rob_source_id().subdetector_id()==SubDetector.TDAQ_HLT:
30 rodVersionM = robf.rod_minor_version() >> 8
31 rodVersionL = robf.rod_minor_version() & 0xFF
32 log.debug("HLT ROD minor version from input file is %d.%d", rodVersionM, rodVersionL)
33 break
34
35 # Case 1: failed to read ROD version
36 if rodVersionM is None or rodVersionL is None:
37 log.warning("Cannot determine HLT ROD version from input file, falling back to run-number-based decision")
38 # Case 2: ROD version indicating Run 3
39 elif rodVersionM >= 1:
40 log.info("Determined EDMVersion to be 3, because running on BS file with HLT ROD version %d.%d",
41 rodVersionM, rodVersionL)
42 return 3
43
44 # Case 3: ROD version indicating Run 1 or 2 - use run number to disambiguate
45 runNumber = bs[0].run_no()
46 log.debug("Read run number %s", runNumber)
47
48 if not runNumber or runNumber <= 0:
49 log.warning("Cannot determine EDM version because run number %s is invalid. ", runNumber)
50 return None
51 elif runNumber < boundary_run12:
52 # Run-1 data
53 log.info("Determined EDMVersion to be 1 based on BS file run number (runNumber < %d)",
54 boundary_run12)
55 return 1
56 elif runNumber < boundary_run23:
57 # Run-2 data
58 log.info("Determined EDMVersion to be 2 based on BS file run number (%d < runNumber < %d)",
59 boundary_run12, boundary_run23)
60 return 2
61 else:
62 # Run-3 data
63 log.info("Determined EDMVersion to be 3 based on BS file run number (runNumber > %d)",
64 boundary_run23)
65 return 3
66
67
68def edmDictToList(edmDict):
69 '''
70 Convert EDM dictionary in the format:
71 {'type1': ['key1','key2'], 'type2': ['key3']}
72 to a flat list in the format:
73 ['type1#key1', 'type1#key2', 'type2#key3']
74 '''
75 return [ f"{type}#{name}" for type, names in edmDict.items() for name in names ]
76
77
78def edmListToDict(edmList):
79 '''
80 Convert EDM list in the format:
81 ['type1#key1', 'type1#key2', 'type2#key3']
82 to a dictionary in the format:
83 {'type1': ['key1','key2'], 'type2': ['key3']}
84 '''
85 edmDict = defaultdict(list)
86 for typeName in edmList:
87 edmType, edmKey = typeName.split('#')
88 edmDict[edmType].append(edmKey)
89 return edmDict
90
91
92def getEDMListFromWriteHandles(configurables):
93 '''
94 Build OutputStream ItemList from all WriteHandles in a list of components (configurables),
95 for example a list of AlgTools. The output is in flat list format:
96 ['type1#key1', 'type1#key2', 'type2#key3']
97 '''
98
99 def getWriteHandles(comp):
100 properties = [getattr(comp,propName) for propName in comp.getDefaultProperties().keys()]
101 return [prop for prop in properties if isinstance(prop,DataHandle) and prop.mode()=='W']
102
103 def formatItem(containerType, containerKey):
104 auxType = containerType.replace('Container','AuxContainer')
105 return [f'{containerType}#{containerKey}',
106 f'{auxType}#{containerKey}Aux.-']
107
108 def containerTypedef(containerType):
109 if containerType.startswith('xAOD::') and containerType.endswith('Container'):
110 # Already the right typedef
111 return containerType
112 m = re.match(r'DataVector<xAOD::(\w+)_v[0-9]+,', containerType)
113 if m and len(m.groups()) > 0:
114 return f'xAOD::{m.group(1)}Container'
115 raise RuntimeError(f'Failed to convert type {containerType} into a container typedef')
116
117 def itemListFromConfigurable(comp):
118 items = []
119 for handle in getWriteHandles(comp):
120 sgKey = handle.Path.replace('StoreGateSvc+','')
121 if not sgKey:
122 continue
123 items += formatItem(containerTypedef(handle.Type), handle.Path)
124 return items
125
126 itemList = []
127 for comp in configurables:
128 itemList += itemListFromConfigurable(comp)
129 return itemList