ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Trigger
TriggerCommon
TriggerMenuMT
scripts
menu_config_tests.py
Go to the documentation of this file.
1
# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2
3
'''
4
Tests to verify generated menus are valid.
5
6
Ported from TrigConfStorage/ConfigurationCheck.cxx and
7
HLT/Config/Utility/HLTMenuConfig.py, see [ATR-19830].
8
9
Designed to be used by the `verify_menu_config.py` script.
10
'''
11
12
import
re
13
from
enum
import
Enum
14
from
collections
import
Counter
15
16
from
TriggerMenuMT.HLT.Menu.SignatureDicts
import
getListOfSignatureStrings
17
18
from
AthenaCommon.Logging
import
logging
19
log = logging.getLogger(
'TriggerMenuConfigTest'
)
20
log.info(
"Importing %s"
, __name__)
21
22
class
TriggerLevel
(Enum):
23
HLT =
"HLT"
24
L1 =
"L1"
25
26
27
class
MenuVerification
(object):
28
def
__init__
(self, description):
29
self.
description
= description
30
self.
failures
= []
31
32
def
run
(self, config):
33
raise
NotImplementedError(
"ConfigVerification subclass must implement run()"
)
34
35
36
class
UniqueChainNames
(
MenuVerification
):
37
def
__init__
(self):
38
super(UniqueChainNames, self).
__init__
(
39
description=
"Chain names are unique"
)
40
41
def
run
(self, config):
42
names = config[
"chains"
].keys()
43
counts = Counter(names)
44
self.
failures
= [chain
for
chain, count
45
in
counts.items()
if
count > 1]
46
47
48
class
ConsecutiveChainCounters
(
MenuVerification
):
49
def
__init__
(self):
50
super(ConsecutiveChainCounters, self).
__init__
(
51
description=
"Chain counters are consecutive 1..N"
)
52
53
def
run
(self, config):
54
counters = [chain[
"counter"
]
for
chain
55
in
config[
"chains"
].values()]
56
prev_counter = 0
57
for
count
in
counters:
58
if
count != prev_counter + 1:
59
self.
failures
.append(count)
60
prev_counter = count
61
62
63
class
StructuredChainNames
(
MenuVerification
):
64
'''
65
Verifies that chain names start with the expected prefix, and have their
66
parts in the correct order by type, as well as any trigger level specific
67
restrictions.
68
'''
69
70
_SIGNATURE_TYPE_ORDER = {
71
TriggerLevel.HLT: getListOfSignatureStrings(),
72
# TODO: import list of signatures items from L1 code
73
TriggerLevel.L1: [
74
"EM"
,
"MU"
,
"TAU"
,
"J"
,
"XE"
,
"HT"
75
],
76
}
77
78
def
__init__
(self, trigger_level):
79
super(StructuredChainNames, self).
__init__
(
80
description=
"Chain names are structured in the expected way"
)
81
self.
_trigger_level
= trigger_level
82
self.
_allowed_prefixes
= [trigger_level.value]
83
if
trigger_level == TriggerLevel.HLT:
84
self.
_allowed_prefixes
.append(
"EF"
)
85
self.
_signature_type_order
= \
86
self.
_SIGNATURE_TYPE_ORDER
[trigger_level]
87
88
def
run
(self, config):
89
if
self.
_trigger_level
== TriggerLevel.HLT:
90
names = config[
"chains"
].keys()
91
self.
failures
= [n
for
n
in
names
92
if
not
self.
_name_matches_hlt_convention
(n)]
93
elif
self.
_trigger_level
== TriggerLevel.L1:
94
names = [item[
"name"
]
for
item
in
config[
"items"
].values()]
95
self.
failures
= [n
for
n
in
names
96
if
not
self.
_name_matches_l1_convention
(n)]
97
98
def
_name_matches_hlt_convention
(self, name):
99
return
"_L1"
in
name
and
self.
_matches_shared_conventions
(name)
100
101
def
_name_matches_l1_convention
(self, name):
102
def
FEX_items_in_order(name):
103
'''
104
Where multiple FEX algorithms are used for the same item type,
105
they should be in alphabetical order.
106
'''
107
fex_pattern =
r"\d*([egj])({})[A-Z]*\d+s?"
.format(
108
"|"
.join(self.
_signature_type_order
))
109
fex_items = re.findall(fex_pattern, name)
110
111
for
item_type
in
self.
_signature_type_order
:
112
fexes_of_type = [fex
for
fex, match_type
in
fex_items
113
if
match_type == item_type]
114
if
not
fexes_of_type == sorted(fexes_of_type):
115
return
False
116
return
True
117
118
return
self.
_matches_shared_conventions
(name)
and
FEX_items_in_order(name)
119
120
def
_matches_shared_conventions
(self, name):
121
'''
122
True if name starts with level prefix, and all signature
123
types are in the correct order, otherwise False.
124
'''
125
# The signature objects in each item should be ordered by type, in the
126
# order defined in _SIGNATURE_TYPE_ORDER.
127
signature_types =
"|"
.join(self.
_signature_type_order
)
128
sig_type_pattern = re.compile(
129
r"_\d*[egj]?({})\d+s?"
.format(signature_types))
130
131
# this is commented because needs to be discussed (it will be removed/changed in next dev)
132
# re to find the signature that has the probe leg
133
#sig_probe_pattern = re.compile(r"_\d*?({})\d+s?[\D]*?_probe".format(signature_types))
134
135
136
def
items_in_order(part):
137
#part = part.replace("leg","p") #if we leave the word leg, the findall(..) function will find a 'g'
138
indices = [self.
_signature_type_order
.
index
(x)
for
x
in
139
sig_type_pattern.findall(part)]
140
141
# this is commented because needs to be discussed (it will be removed/changed in next dev)
142
# this finds the signatures with the probe leg
143
# matches = sig_type_pattern.findall(part)
144
# matches_probe = sig_probe_pattern.findall(part)
145
# if len(matches_probe):
146
# assert(len(matches_probe)==1)
147
# probe_leg = matches_probe[0]
148
# matches_after_probe = matches.copy()
149
# # force the probe leg to be the last one
150
# if probe_leg in matches_after_probe:
151
# # Remove the element
152
# matches_after_probe.remove(probe_leg)
153
# # Append it to the end
154
# matches_after_probe.append(probe_leg)
155
# indices_after_probe = [self._signature_type_order.index(x) for x in matches_after_probe]
156
# # copy the new indices
157
# #indices = indices_after_probe.copy()
158
159
160
rr = indices == sorted(indices)
161
if
not
rr:
162
log.error(
"[StructuredChainNames::items_in_order] %s NOT SORTED!"
, indices)
163
164
return
rr
165
166
def
are_signatures_in_order(name_parts):
167
168
to_check = [
""
.join(f
"_{p}"
for
p
in
name_parts
if
"-"
not
in
p)]
169
170
# Sections of topo item parts are checked for ordering independently.
171
topo_parts = [p
for
p
in
name_parts
if
"-"
in
p]
172
for
topo
in
topo_parts:
173
to_check.extend(topo.split(
"-"
))
174
res = all(items_in_order(part)
for
part
in
to_check)
175
if
not
res:
176
for
part
in
to_check:
177
if
not
items_in_order(part):
178
log.error(
"[StructuredChainNames::are_signatures_in_order] %s not in order!"
, part)
179
return
res
180
181
# Name must begin with the trigger level, and contain at least one item.
182
parts = name.split(
"_"
)
183
184
result= all((len(parts) > 1,
185
parts[0]
in
self.
_allowed_prefixes
,
186
are_signatures_in_order(parts[1:])))
187
if
not
result:
188
log.error(
"[StructuredChainNames::_matches_shared_conventions] chain deosn't match convention: parts[0] = %s, value = %s, parts[1:] = %s, signature_types = %s"
,
189
parts[0], self.
_trigger_level
.value, parts[1:], signature_types)
190
191
return
result
192
193
194
class
RestrictedCTPIDs
(
MenuVerification
):
195
def
__init__
(self):
196
super(RestrictedCTPIDs, self).
__init__
(
197
description=
"Less than 512 CTP items, and no CTP id greater than 512"
)
198
199
def
run
(self, config):
200
ctp_ids = {name: item[
"ctpid"
]
for
201
name, item
in
config[
"items"
].items()}
202
if
len(ctp_ids) > 512:
203
self.
failures
.append(
204
"More than 512 CTP items defined"
)
205
over_max_ids = [name
for
name, ctp_id
in
ctp_ids.items()
206
if
ctp_id > 512]
207
self.
failures
.extend(over_max_ids)
208
209
210
class
PartialEventBuildingChecks
(
MenuVerification
):
211
def
__init__
(self):
212
super(PartialEventBuildingChecks, self).
__init__
(
213
description=
'Config consistency of Partial Event Building'
)
214
215
def
run
(self, config):
216
from
TriggerMenuMT.HLT.Menu
import
EventBuildingInfo
217
eb_identifiers = EventBuildingInfo.getAllEventBuildingIdentifiers()
218
219
for
chain_name, chain_config
in
config[
'chains'
].items():
220
peb_identifiers = [idf
for
idf
in
eb_identifiers
if
'_'
+idf+
'_'
in
chain_name]
221
peb_writers = [seq
for
seq
in
chain_config[
'sequencers'
]
if
'PEBInfoWriter'
in
seq]
222
223
is_peb_chain = (len(peb_identifiers) > 0
or
len(peb_writers) > 0)
224
225
# Check streaming configuration
226
for
stream_name
in
chain_config[
'streams'
]:
227
if
stream_name
not
in
config[
'streams'
]:
228
self.
failures
.append(
229
'Stream {:s} for chain {:s} is not defined in streaming configuration'
.format(
230
stream_name, chain_name))
231
232
is_feb_stream = config[
'streams'
][stream_name][
'forceFullEventBuilding'
]
233
234
if
is_peb_chain
and
is_feb_stream:
235
self.
failures
.append(
236
'PEB chain {:s} streamed to a full-event-building stream {:s} '
237
'(forceFullEventBuilding=True)'
.format(
238
chain_name, stream_name))
239
240
elif
not
is_peb_chain
and
not
is_feb_stream:
241
self.
failures
.append(
242
'Full-event-building chain {:s} streamed to the stream {:s} which allows partial '
243
'event building (forceFullEventBuilding=False)'
.format(
244
chain_name, stream_name))
245
246
if
not
is_peb_chain:
247
# Not a PEB chain, skip further PEB-specific checks
248
continue
249
250
if
len(peb_identifiers) != 1:
251
self.
failures
.append(
252
'{:s} has {:d} event building identifiers'
.format(chain_name, len(peb_identifiers)))
253
254
if
len(peb_writers) != 1:
255
self.
failures
.append(
256
'{:s} has {:d} PEBInfoWriter sequences'
.format(chain_name, len(peb_writers)))
257
258
if
peb_identifiers
and
peb_writers
and
not
peb_writers[0].endswith(peb_identifiers[0]):
259
self.
failures
.append(
260
'{:s} PEB sequence name {:s} doesn\'t end with PEB identifier {:s}'
.format(
261
chain_name, peb_writers[0], peb_identifiers[0]))
262
263
264
265
menu_tests = {
266
TriggerLevel.HLT: [
267
UniqueChainNames
(),
268
ConsecutiveChainCounters
(),
269
StructuredChainNames
(TriggerLevel.HLT),
270
PartialEventBuildingChecks
()
271
],
272
TriggerLevel.L1: [
273
RestrictedCTPIDs
(),
274
StructuredChainNames
(TriggerLevel.L1),
275
]
276
}
menu_config_tests.ConsecutiveChainCounters
Definition
menu_config_tests.py:48
menu_config_tests.ConsecutiveChainCounters.__init__
__init__(self)
Definition
menu_config_tests.py:49
menu_config_tests.ConsecutiveChainCounters.run
run(self, config)
Definition
menu_config_tests.py:53
menu_config_tests.MenuVerification
Definition
menu_config_tests.py:27
menu_config_tests.MenuVerification.run
run(self, config)
Definition
menu_config_tests.py:32
menu_config_tests.MenuVerification.failures
list failures
Definition
menu_config_tests.py:30
menu_config_tests.MenuVerification.description
description
Definition
menu_config_tests.py:29
menu_config_tests.MenuVerification.__init__
__init__(self, description)
Definition
menu_config_tests.py:28
menu_config_tests.PartialEventBuildingChecks
Definition
menu_config_tests.py:210
menu_config_tests.PartialEventBuildingChecks.run
run(self, config)
Definition
menu_config_tests.py:215
menu_config_tests.PartialEventBuildingChecks.__init__
__init__(self)
Definition
menu_config_tests.py:211
menu_config_tests.RestrictedCTPIDs
Definition
menu_config_tests.py:194
menu_config_tests.RestrictedCTPIDs.run
run(self, config)
Definition
menu_config_tests.py:199
menu_config_tests.RestrictedCTPIDs.__init__
__init__(self)
Definition
menu_config_tests.py:195
menu_config_tests.StructuredChainNames
Definition
menu_config_tests.py:63
menu_config_tests.StructuredChainNames._signature_type_order
dict _signature_type_order
Definition
menu_config_tests.py:85
menu_config_tests.StructuredChainNames.run
run(self, config)
Definition
menu_config_tests.py:88
menu_config_tests.StructuredChainNames._name_matches_l1_convention
_name_matches_l1_convention(self, name)
Definition
menu_config_tests.py:101
menu_config_tests.StructuredChainNames._allowed_prefixes
list _allowed_prefixes
Definition
menu_config_tests.py:82
menu_config_tests.StructuredChainNames.__init__
__init__(self, trigger_level)
Definition
menu_config_tests.py:78
menu_config_tests.StructuredChainNames._matches_shared_conventions
_matches_shared_conventions(self, name)
Definition
menu_config_tests.py:120
menu_config_tests.StructuredChainNames._name_matches_hlt_convention
_name_matches_hlt_convention(self, name)
Definition
menu_config_tests.py:98
menu_config_tests.StructuredChainNames._SIGNATURE_TYPE_ORDER
dict _SIGNATURE_TYPE_ORDER
Definition
menu_config_tests.py:70
menu_config_tests.StructuredChainNames._trigger_level
_trigger_level
Definition
menu_config_tests.py:81
menu_config_tests.TriggerLevel
Definition
menu_config_tests.py:22
menu_config_tests.UniqueChainNames
Definition
menu_config_tests.py:36
menu_config_tests.UniqueChainNames.run
run(self, config)
Definition
menu_config_tests.py:41
menu_config_tests.UniqueChainNames.__init__
__init__(self)
Definition
menu_config_tests.py:37
index
Definition
index.py:1
Generated on
for ATLAS Offline Software by
1.17.0