ATLAS Offline Software
CheckL1HLTConsistency.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
2 
3 from AthenaCommon.Logging import logging
4 log = logging.getLogger(__name__)
5 import re
6 
7 
8 def getL1TopoAlgMaps(lvl1access):
9  """
10  Returns tuple of L1Topo algorithm to board and item map: (alg_to_board, alg_to_item)
11 
12  alg_to_board: Map between L1 algorithm name and board (Topo2, Topo3 or LegacyTopo,
13  items coming from other boards will not be listed in the map)
14  alg_to_item: Map between L1 item name and topo algorithm
15  """
16 
17  lvl1items = lvl1access.items(includeKeys=["name"])
18  lvl1items_full = lvl1access.items()
19 
20  l1topo_alg_to_board = {}
21  l1topo_alg_to_item = {}
22  connectors = ['Topo2El','Topo3El','LegacyTopoMerged']
23 
24  for l1item in lvl1items:
25  # Split string of AND/OR-ed items
26  # e.g. ((AFP_NSA[x1] & AFP_FSA[x1]) | (AFP_NSC[x1] & AFP_FSC[x1])) & EM7[x1]
27  l1item_def_list = re.split("[&|]+", lvl1items_full[l1item]['definition'])
28  for l1item_def_aux in l1item_def_list:
29  # Strip brackets/whitespace and take name before multiplicity
30  l1item_def = l1item_def_aux.strip('() ').split('[')[0]
31 
32  # fill alg_to_board
33  for connect in connectors:
34  for v in lvl1access.connector(connect)['triggerlines']:
35  if l1item_def==v['name']:
36  l1topo_alg_to_board[l1item_def] = connect
37 
38  # fill alg_to_item (we stop once we found 'TOPO' item)
39  if 'TOPO' not in l1topo_alg_to_item.get(l1item,''):
40  l1topo_alg_to_item[l1item] = l1item_def
41 
42  log.debug("L1Topo alg to board map: %s",l1topo_alg_to_board)
43  log.debug("L1Topo alg to item map: %s",l1topo_alg_to_item)
44  return (l1topo_alg_to_board, l1topo_alg_to_item)
45 
46 
47 #this function checks each threshold within each chain to make sure that it is defined in the L1Menu
49  from TrigConfIO.L1TriggerConfigAccess import L1MenuAccess
50  from TrigConfigSvc.TrigConfigSvcCfg import getL1MenuFileName
51  lvl1name = getL1MenuFileName(flags)
52  lvl1access = L1MenuAccess(lvl1name)
53  lvl1thtypes = lvl1access.thresholdTypes()
54  lvl1items = lvl1access.items(includeKeys=["name"])
55  lvl1items_full = lvl1access.items()
56  from TriggerMenuMT.HLT.Config.Utility.HLTMenuConfig import HLTMenuConfig
57 
58  allUsedItems = []
59  allUnusedItems = []
60  chainsWithWrongLabel = {}
61 
62  l1topo_alg_to_board, l1topo_alg_to_item = getL1TopoAlgMaps(lvl1access)
63 
64  missing_L1_items = []
65  for chain in HLTMenuConfig.dictsList():
66  log.debug('[checkL1HLTConsistency] Checking the l1thresholds in the chain %s', chain["chainName"])
67 # #don't check the noalg chains (they don't do anything in the HLT anyway)
68 # if 'HLT_noalg_' in chain["chainName"]:
69 # continue
70 
71  is_missing=False
72  l1item_vec = chain['L1item'].split(',')
73  for l1item in l1item_vec:
74  if l1item == "":
75  log.debug('[checkL1HLTConsistency] chain %s in L1Menu %s: L1item not set...', chain["chainName"], lvl1name)
76  continue
77  if l1item not in lvl1items:
78  log.error('[checkL1HLTConsistency] chain %s: L1item: %s, not found in the items list of the L1Menu %s', chain["chainName"], chain["L1item"], lvl1name)
79  missing_L1_items.append(l1item)
80  is_missing=True
81  else:
82  if l1item not in allUsedItems:
83  allUsedItems.append(l1item)
84 
85  # Avoid crashing on lookups
86  if is_missing:
87  continue
88 
89  # Find L1 Threshold information for current chain
90  l1thr_vec = []
91  for p in chain['chainParts']:
92  #now check that the thresholds of the chain are listed in the L1Menu.thresholds field
93  th = p['L1threshold'][5:] if p['L1threshold'].startswith("PROBE") else p['L1threshold']
94  l1thr_vec.append(th)
95  if ('TAU' in th) and th[0] not in ['e','j','c']: #legacy TAU
96  th = th.replace('TAU','HA')
97  thFoundInL1Menu = False
98  l1type = "NOTFOUND"
99  if th == 'FSNOSEED':
100  log.debug('[checkL1HLTConsistency] \t %s in L1thresholds', th)
101  continue
102  for thtype in lvl1thtypes:
103  l1thresholds = lvl1access.thresholds(thtype)
104  if th in l1thresholds:
105  thFoundInL1Menu = True
106  l1type = thtype
107  break
108  if thFoundInL1Menu:
109  log.debug('[checkL1HLTConsistency] \t %s in L1HLTConsistency[%s]', th, l1type)
110  else:
111  log.error('[checkL1HLTConsistency] chain %s: L1Threshold %s not found in the L1thresholds of the L1Menu %s', chain["chainName"], th, lvl1name)
112  raise Exception("Please fix the menu or the chain.")
113 
114  # check that L1 seeds and L1 item are all either legacy or phase1
115  legacyItem = False
116  noCaloItemL1 = True
117  noCaloItemHLT = True
118  foundPhase1CaloSeed = False
119  foundLegacyCaloSeed = False
120  for item in l1item_vec:
121  if item=='':
122  continue
123  if 'legacy' in lvl1items_full[item]:
124  if lvl1items_full[item]['legacy']:
125  legacyItem = True
126  noCaloItemL1 = False
127  else:
128  items = item[2:].split('_')
129  for it in items:
130  if any(substring in it for substring in ['e','c','j','g']): # find phase1 calo inputs in L1Topo decision triggers
131  noCaloItemL1 = False
132 
133  # Don't check topo assignments for multi-seeded triggers
134  if len(l1item_vec)==1:
135  errormsg = ""
136  if l1topo_alg_to_item[item] in l1topo_alg_to_board:
137  if not any('Topo' in g for g in chain['groups']):
138  errormsg = f"Chain has item {item} ({l1topo_alg_to_board[l1topo_alg_to_item[item]]}) but has no topo group"
139 
140  # Possibilities for wrong assignment:
141  # - Item comes from topo board but has no topo group
142  # - Chain has topo label but L1 item does not come from topo board
143  # - Chain has wrong topo label (Topo2 when it should be Topo3 for example)
144  for group in chain['groups']:
145  if 'Topo' in group:
146  if l1topo_alg_to_item[item] in l1topo_alg_to_board:
147  if group in l1topo_alg_to_board[l1topo_alg_to_item[item]]:
148  log.debug("Chain correctly assigned topo board")
149  else:
150  errormsg = f"Chain should be labelled with topo board {l1topo_alg_to_board[l1topo_alg_to_item[item]]}"
151  elif l1topo_alg_to_item[item] not in l1topo_alg_to_board:
152  errormsg = f"Chain does not come from topo board but has Topo group {group}"
153 
154  if errormsg:
155  chainsWithWrongLabel.update({chain['chainName']: (chain['groups'], errormsg)})
156 
157  for th in l1thr_vec:
158  if th=='FSNOSEED':
159  continue
160  if th[:1] in ['e','c','j','g']:
161  foundPhase1CaloSeed = True
162  noCaloItemHLT = False
163  if th[:1] in ['E','T','J','X']:
164  foundLegacyCaloSeed = True
165  noCaloItemHLT = False
166 
167  mixedCaloSeed = False
168  if legacyItem and foundPhase1CaloSeed: # chain with L1 legacy item, cannot have phase1 seed
169  mixedCaloSeed = True
170  if not legacyItem:
171  if not noCaloItemL1: # chain with L1 phase1 item, cannot have legacy seed
172  if foundLegacyCaloSeed:
173  mixedCaloSeed = True
174  else:
175  if foundLegacyCaloSeed and foundPhase1CaloSeed: # chain without L1 calo items, cannot have both legacy and phase1 seeds
176  mixedCaloSeed = True
177  if mixedCaloSeed:
178  log.warning('[checkL1HLTConsistency] chain %s contains a mix of legacy and phase1 calo thresholds! L1 items: [%s] (legacy item = %s), L1 seeds: [%s] (foundPhase1CaloSeed = %s, foundLegacyCaloSeed = %s)', chain["chainName"], ",".join(l1item_vec), legacyItem, ",".join(l1thr_vec), foundPhase1CaloSeed, foundLegacyCaloSeed )
179  # log.error('[checkL1HLTConsistency] chain %s contains a mix of legacy and phase1 calo thresholds! L1 items: [%s] (legacy item = %s), L1 seeds: [%s] (foundPhase1CaloSeed = %s, foundLegacyCaloSeed = %s)', chain["chainName"], ",".join(l1item_vec), legacyItem, ",".join(l1thr_vec), foundPhase1CaloSeed, foundLegacyCaloSeed )
180  # raise Exception("Please fix the chain.")
181 
182  # check legacy and phase1 chains have the correct groups
183  wrongLabel = False
184  rightLabel = False
185  log.debug("Checking chain %s: noCaloItemL1 %s, noCaloItemHLT %s , legacyItem %s", chain['chainName'], noCaloItemL1, noCaloItemHLT, legacyItem )
186 
187  log.debug(chain['groups'])
188  for group in chain['groups']:
189  log.debug("Checking group %s: find 'Legacy' %s, find 'PhaseI' %s", group, str(group.find('Legacy')), str(group.find('PhaseI')) )
190 
191  if noCaloItemL1 and noCaloItemHLT:
192  if group.find('Legacy')>-1 or group.find('PhaseI')>-1 :
193  wrongLabel = True # chains without calo inputs should not have legacy or phase1 label
194  if group.find('Legacy')<0 and group.find('PhaseI')<0 :
195  rightLabel = True
196  else:
197  if legacyItem: # chain with L1 legacy seed
198  if group.find('Legacy')>-1 :
199  rightLabel = True
200  if group.find('PhaseI')>-1 :
201  wrongLabel = True
202  else:
203  if not noCaloItemL1: # chain with L1 phase1 item
204  if group.find('PhaseI')>-1 :
205  rightLabel = True
206  if group.find('Legacy')>-1 :
207  wrongLabel = True
208  if noCaloItemL1 and not noCaloItemHLT: # chain with HLT legacy or phase1 seed
209  if foundPhase1CaloSeed and group.find('Legacy')>-1 :
210  wrongLabel = True
211  if foundPhase1CaloSeed and group.find('PhaseI')>-1 :
212  rightLabel = True
213  if foundLegacyCaloSeed and group.find('PhaseI')>-1 :
214  wrongLabel = True
215  if foundLegacyCaloSeed and group.find('Legacy')>-1 :
216  rightLabel = True
217  if wrongLabel or not rightLabel:
218  errormsg = 'Incorrect L1Calo version label -- check Legacy/Phase-I assignment'
219  chainsWithWrongLabel.update({chain['chainName']: (chain['groups'],errormsg)})
220 
221  if missing_L1_items:
222  log.error('[checkL1HLTConsistency] Missing L1 items:')
223  for i in missing_L1_items:
224  log.error(f' {i}')
225  raise Exception("Please fix the menu or the chains.")
226 
227  if len(chainsWithWrongLabel) and ('Physics' in lvl1name) and not ('HI' in lvl1name) and not ('lowMu' in lvl1name): # apply this check only for the Physics menu, for now; don't apply for HI menu
228  log.error('These chains have the wrong groups for l1menu %s:',lvl1name)
229  for key, (groups, errormsg) in chainsWithWrongLabel.items():
230  log.error('%s: %s\n --> %s', key, ",".join(groups), errormsg)
231  raise Exception("Please fix these chains.")
232 
233  # check for unused L1 items
234  for item in lvl1items:
235  if item not in allUsedItems:
236  allUnusedItems.append(item)
237  if len(allUnusedItems)==0:
238  log.info('[checkL1HLTConsistency] All items in L1 menu are used')
239  else:
240  log.info('[checkL1HLTConsistency] %i items in L1 menu are not used: %s', len(allUnusedItems), ",".join(allUnusedItems))
241  log.info('[checkL1HLTConsistency] checkL1HLTConsistency completed succesfully')
python.TrigConfigSvcCfg.getL1MenuFileName
def getL1MenuFileName(flags)
Definition: TrigConfigSvcCfg.py:136
CheckL1HLTConsistency.checkL1HLTConsistency
def checkL1HLTConsistency(flags)
Definition: CheckL1HLTConsistency.py:48
CheckL1HLTConsistency.getL1TopoAlgMaps
def getL1TopoAlgMaps(lvl1access)
Definition: CheckL1HLTConsistency.py:8
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
str
Definition: BTagTrackIpAccessor.cxx:11
Trk::split
@ split
Definition: LayerMaterialProperties.h:38