Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
L1Menu.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 
3 from .CTP import CTP
4 from .Items import MenuItemsCollection
5 from .Thresholds import MenuThresholdsCollection
6 from .TopoAlgorithms import MenuTopoAlgorithmsCollection, AlgType, AlgCategory
7 from .Boards import MenuBoardsCollection
8 from .Connectors import MenuConnectorsCollection, CType
9 from .MenuUtils import get_smk_psk_Name
10 from .Limits import Limits
11 from .L1MenuFlags import L1MenuFlags
12 from .ThresholdType import ThrType
13 from ..Config.TypeWideThresholdConfig import getTypeWideThresholdConfig
14 
15 from collections import OrderedDict as odict
16 from AthenaCommon.Logging import logging
17 log = logging.getLogger(__name__)
18 
19 class L1Menu(object):
20  """
21  This class holds everything that is needed to define the menu
22  """
23 
24  def __init__(self, menuName, flags):
25  self.menuName = menuName
26 
27  self.menuFullName = L1MenuFlags.MenuSetup()
28 
29  # items in menu
31 
32  # store cached flags
33  self.flags = flags
34 
35  # all thresholds that are in menu (new and legacy)
37 
38  # all thresholds that are in menu (new and legacy)
40 
41  # all connectors between legacyCalo, muctpi, topo and the CTPIN/CTPCORE
43 
44  # board definition
46 
47  # CTP Info in the menu
48  self.ctp = CTP()
49 
50  if self.menuName:
51  smk_psk_Name = get_smk_psk_Name(self.menuName)
52  self.items.menuName = smk_psk_Name["smkName"]
53  self.items.pssName = smk_psk_Name["pskName"]
54 
55 
56  def setBunchGroupSplitting(self, v = True):
57  MenuItemsCollection.splitBunchGroups = v
58 
59 
60  def addItem(self, item):
61  self.items += item
62 
63 
64  def getItem(self,name):
65  return self.items.findItemByName(name)
66 
67 
68  def addThreshold(self, threshold):
69  self.thresholds += threshold
70 
71 
72  def addTopoAlgo(self, algo, category):
73  algo.setThresholds( self.thresholds ) # each algo gets a pointer to the full thresholds definition (for the extrainfo)
74  self.topoAlgos.addAlgo(algo, category)
75 
76 
77  def addBoard(self, boardDef):
78  return self.boards.addBoard(boardDef)
79 
80 
81  def addConnector(self, connDef):
82  self.connectors.addConnector(connDef)
83 
84 
85  def setupCTPMonitoring(self):
86  self.ctp.setupMonitoring(self.menuName, self.items, self.thresholds, self.connectors, self.menuFullName)
87 
88  def check(self):
89  log.info("Doing L1 Menu checks")
90  from collections import defaultdict as dd
91  missing = dd(list)
92  allThresholds = set([thr.name for thr in self.thresholds])
93  allUsedThresholds = set()
94  for item in self.items:
95  for thrName in item.thresholdNames():
96  if 'SPARE' in thrName:
97  raise RuntimeError("CTP input %s is used by %s but SPARE thresholds are not to be used!" %(thrName, item) )
98  if thrName not in allThresholds:
99  missing[thrName].append(item.name)
100  else:
101  allUsedThresholds.add(thrName)
102 
103  for thrName in sorted(missing.keys()):
104  log.warning("Threshold %s (used by %s) is not defined in the menu", thrName,",".join(missing[thrName]))
105 
106  if len(allThresholds)-len(allUsedThresholds)>0:
107  unusedThresholds = allThresholds.difference(allUsedThresholds)
108  log.debug("The following thresholds are unused")
109  log.debug("MU: %s", ", ".join([thr for thr in unusedThresholds if thr.startswith("MU")]))
110  log.debug("EM: %s", ", ".join([thr for thr in unusedThresholds if thr.startswith("EM")]))
111  log.debug("HA: %s", ", ".join([thr for thr in unusedThresholds if thr.startswith("HA")]))
112  log.debug("J: %s", ", ".join([thr for thr in unusedThresholds if thr.startswith("J")]))
113  log.debug("eFEX: %s", ", ".join([thr for thr in unusedThresholds if thr.startswith("e")]))
114  log.debug("jFEX: %s", ", ".join([thr for thr in unusedThresholds if thr.startswith("j")]))
115  log.debug("cTAU: %s", ", ".join([thr for thr in unusedThresholds if thr.startswith("cTAU")]))
116  log.debug("gFEX: %s", ", ".join([thr for thr in unusedThresholds if thr.startswith("g")]))
117 
119  from collections import defaultdict as dd
120  from ..Menu.LegacyMenuThresholds import legacyThresholds
121  extraThresholds = dd(list)
122  for item in self.items:
123  for thrName in item.thresholdNames():
124  if thrName[:3]=='ZB_':
125  thrName = thrName[3:]
126  if thrName[0] not in ('e','j','g', 'c') and thrName[:2] not in ["MU"] and "TOPO" not in thrName[:4]:
127  if thrName not in legacyThresholds:
128  extraThresholds[thrName].append(item.name)
129 
130  for thrName in sorted(extraThresholds.keys()):
131  log.warning("Threshold %s (used by %s) should not be used!", thrName,",".join(extraThresholds[thrName]))
132 
134  if 'MC' not in self.menuName:
135  from collections import defaultdict as dd
136  perfThresholds = dd(list)
137  for item in self.items:
138  for thrName in item.thresholdNames():
139  if 'Perf' in thrName:
140  perfThresholds[thrName].append(item.name)
141  for thrName in sorted(perfThresholds.keys()):
142  raise RuntimeError("Threshold %s (used by %s) should not be used!", thrName,",".join(perfThresholds[thrName]))
143 
144  def checkBoardInputs(self, algo, connDefName, fpgaName ):
145  if 'MuCTPi' in connDefName or 'Legacy' in connDefName:
146  return
147 
148  boardName = connDefName+fpgaName
149 
150  allowedInputs = odict()
151  allowedInputs['Topo1Opt0'] = ['MU', 'eEM', 'eTAU', 'gJ', 'gLJ', 'ZeroBiasA'] # TOPO1A, FPGA1
152  allowedInputs['Topo1Opt1'] = ['MU', 'eEM', 'eTAU', 'gJ', 'gLJ', ] # TOPO1A, FPGA2
153  allowedInputs['Topo1Opt2'] = ['MU', 'eTAU', 'cTAU', 'j', 'gXE', 'gTE', 'gMHT'] # TOPO1B, FPGA1
154  allowedInputs['Topo1Opt3'] = ['MU', 'eTAU', 'cTAU', 'j', 'gXE', 'gTE', 'gMHT', 'LArSaturation', 'ZeroBiasB'] # TOPO1B, FPGA2
155  allowedInputs['Topo2El0'] = ['MU', 'eTAU', 'j', ] # TOPO2, FPGA1
156  allowedInputs['Topo2El1'] = [ 'eEM', 'j', ] # TOPO2, FPGA2
157  allowedInputs['Topo3El0'] = [ 'eEM', 'eTAU', 'j', ] # TOPO3, FPGA1
158  allowedInputs['Topo3El1'] = ['MU', 'eEM', 'eTAU', 'g', ] # TOPO3, FPGA2
159 
160  if boardName not in allowedInputs.keys():
161  raise RuntimeError("Connector name %s not found" % boardName )
162 
163  if 'Mult_' in algo.name:
164  if not (any(x in algo.threshold for x in allowedInputs[boardName])):
165  raise RuntimeError("Algorithm %s in board %s with threshold %s not allowed" % (algo.name, boardName, algo.threshold ))
166 
167  if 'Mult_' not in algo.name:
168  for algoInput in algo.inputs:
169  if not (any(x in algoInput for x in allowedInputs[boardName])):
170  raise RuntimeError("Algorithm %s in board %s with input %s not allowed" % (algo.name, boardName, algoInput ))
171 
172  def checkL1CaloThresholds(self, thresholds, boardName, connName):
173  fullName = boardName + connName
174 
175  allowedInputs = odict()
176  allowedInputs['Ctpin7EM1'] = 8*['EM']
177  allowedInputs['Ctpin7EM2'] = 8*['EM']
178  allowedInputs['Ctpin7TAU1'] = 8*['HA']
179  allowedInputs['Ctpin7TAU2'] = 8*['HA']
180 
181  allowedInputs['Ctpin8JET1'] = 10*['J'] # 3-bit JET
182  allowedInputs['Ctpin8JET2'] = 15*['J'] # 2-bit JET
183  allowedInputs['Ctpin8EN1'] = 8*['TE'] + 8*['XE'] + 8*['XS']
184  allowedInputs['Ctpin8EN2'] = 8*['TE'] + 8*['XE']
185 
186  invalidThresholds = False
187  for ithr,thr in enumerate(thresholds):
188  try:
189  allowedThr = allowedInputs[fullName][ithr]
190  if thr[:len(allowedThr)] != allowedThr:
191  log.error(f"Threshold {thr} does not match expected type {allowedThr} at position {ithr} in connector {fullName}")
192  invalidThresholds = True
193  except IndexError:
194  log.error(f"Too many thresholds ({len(thresholds)}) provided for connector {fullName}, which only supports {len(allowedInputs[fullName])} thresholds")
195  invalidThresholds = True
196  if invalidThresholds:
197  raise RuntimeError("Incorrect specification of legacy L1Calo thresholds")
198 
200  for conn in self.connectors:
201  if conn.ctype == CType.CTPIN:
202  if len(conn.triggerLines)>31:
203  raise RuntimeError("Too many CTP inputs in %s: %i but a max of 31 are allowed" %(conn.name,len(conn.triggerLines)))
204 
205  def checkTOPObits(self):
206  import re
207  pattern=r"topo[1-3](e|$)"
208  for conn in self.connectors:
209  flatindexs = []
210  if re.search(pattern, conn.name.lower()):
211  for tl in conn.triggerLines:
212  for thr in conn.triggerLines[tl]:
213  for thrname in conn.triggerLines[tl][thr]:
214  if thrname.flatindex not in flatindexs:
215  flatindexs.append(thrname.flatindex)
216  else:
217  log.error("TOPO connector %s has duplicate flatindex %i", conn.name, thrname.flatindex)
218  raise RuntimeError("Duplicate flatindex found in TOPO algorithm")
219 
220 
222  from collections import namedtuple
223  ctpInput = namedtuple('ctpInput',"name, conn, nbit")
224  ctpInputs = []
225  ctpUnusedInputs = []
226  ctpOutputs = []
227  thrNames = []
228  ctpInputBitSets = dict()
229  ctpInputNameSets = dict()
230  ctpUnusedInputBitSets = dict()
231  ctpUnusedInputNameSets = dict()
232  for item in self.items:
233  ctpOutputs.append(item.name)
234  for thrName in item.thresholdNames():
235  if thrName[:3]=='ZB_':
236  thrName = thrName[3:]
237  if thrName not in thrNames:
238  thrNames.append(thrName)
239  thrNames_notFound = []
240  for thrName in thrNames:
241  thrName_found = False
242  for conn in self.connectors:
243  if conn.ctype != CType.ELEC:
244  for tl in conn.triggerLines:
245  if thrName == tl.name:
246  ctpInputs.append(ctpInput(name=thrName,conn=conn.name,nbit=tl.nbits))
247  thrName_found = True
248  else:
249  for fpga in conn.triggerLines:
250  for clock in conn.triggerLines[fpga]:
251  for tl in conn.triggerLines[fpga][clock]:
252  if thrName == tl.name:
253  ctpInputs.append(ctpInput(name=thrName,conn=conn.name,nbit=tl.nbits))
254  thrName_found = True
255  if not thrName_found:
256  thrNames_notFound.append(thrName)
257 
258  for conn in self.connectors:
259  if conn.ctype != CType.ELEC:
260  for tl in conn.triggerLines:
261  thrName = tl.name
262  if thrName[:3]=='ZB_':
263  thrName = thrName[3:]
264  usedInput = False
265  for ctpIn in ctpInputs:
266  if thrName == ctpIn.name:
267  usedInput = True
268  if not usedInput:
269  ctpUnusedInputs.append(ctpInput(name=thrName,conn=conn.name,nbit=tl.nbits))
270  else:
271  for fpga in conn.triggerLines:
272  for clock in conn.triggerLines[fpga]:
273  for tl in conn.triggerLines[fpga][clock]:
274  thrName = tl.name
275  if thrName[:3]=='ZB_':
276  thrName = thrName[3:]
277  usedInput = False
278  for ctpIn in ctpInputs:
279  if thrName == ctpIn.name:
280  usedInput = True
281  if not usedInput:
282  ctpUnusedInputs.append(ctpInput(name=thrName,conn=conn.name,nbit=tl.nbits))
283 
284  if len(thrNames_notFound)>0:
285  log.error("Thresholds [%s] are not found", ",".join(thrNames_notFound))
286  log.error("Input thresholds are [%s]", ",".join([ input.name for input in ctpInputs]))
287  raise RuntimeError("Not all input thresholds found!")
288 
289  for ctpIn in ctpInputs:
290  thrset = None
291  thrName = ctpIn.name
292  if thrName[:2] in ['EM','HA','XE','TE','XS']:
293  thrset = 'legacyCalo'
294  elif thrName[:1]=='J':
295  thrset = 'legacyCalo'
296  elif thrName[:2]=='MU':
297  thrset = 'muon'
298  elif thrName[:3] in ['MBT','AFP','BCM','CAL','NIM','ZDC','BPT','LUC','BMA']:
299  thrset = 'detector'
300  elif thrName[:6]=='R2TOPO':
301  thrset = 'legacyTopo'
302  elif thrName[:1] in ['e','j','c','g']:
303  thrset = 'topo1'
304  elif thrName[:4]=='TOPO':
305  if 'Topo2' in ctpIn.conn:
306  thrset = 'topo2'
307  elif 'Topo3' in ctpIn.conn:
308  thrset = 'topo3'
309 
310  if thrset not in ctpInputBitSets:
311  ctpInputBitSets[thrset] = 0
312  ctpInputNameSets[thrset] = []
313  if thrName not in ctpInputNameSets[thrset]:
314  ctpInputNameSets[thrset].append(thrName)
315  ctpInputBitSets[thrset] += ctpIn.nbit
316 
317  for ctpIn in ctpUnusedInputs:
318  thrset = None
319  thrName = ctpIn.name
320  if thrName[:2] in ['EM','HA','XE','TE','XS']:
321  thrset = 'legacyCalo'
322  elif thrName[:1]=='J':
323  thrset = 'legacyCalo'
324  elif thrName[:2]=='MU':
325  thrset = 'muon'
326  elif thrName[:3] in ['MBT','AFP','BCM','CAL','NIM','ZDC','BPT','LUC']:
327  thrset = 'detector'
328  elif thrName[:6]=='R2TOPO':
329  thrset = 'legacyTopo'
330  elif thrName[:1] in ['e','j','c','g']:
331  thrset = 'topo1'
332  elif thrName[:4]=='TOPO':
333  if 'Topo2' in ctpIn.conn:
334  thrset = 'topo2'
335  elif 'Topo3' in ctpIn.conn:
336  thrset = 'topo3'
337 
338  if thrset not in ctpUnusedInputBitSets:
339  ctpUnusedInputBitSets[thrset] = 0
340  ctpUnusedInputNameSets[thrset] = []
341  if thrName not in ctpUnusedInputNameSets[thrset]:
342  ctpUnusedInputNameSets[thrset].append(thrName)
343  ctpUnusedInputBitSets[thrset] += ctpIn.nbit
344 
345  totalInputs = 0
346  log.info("Check total number of CTP input and output bits:")
347  log.info("Number of output bits: %i", len(ctpOutputs) )
348  for thrset in ctpInputBitSets:
349  log.info("Used inputs in %s: %i thresholds and %i bits", thrset, len(ctpInputNameSets[thrset]), ctpInputBitSets[thrset] )
350  if thrset is not None:
351  log.debug("Threshold set %s: %s", thrset, ",".join(ctpInputNameSets[thrset]) )
352  else:
353  log.info("Unrecognised CTP input bits: %s", ",".join(ctpInputNameSets[thrset]) )
354  totalInputs += ctpInputBitSets[thrset]
355  log.info("Number of used inputs bits: %i" , totalInputs )
356  totalUnusedInputs = 0
357  for thrset in ctpUnusedInputBitSets:
358  log.debug("Unused thresholds in %s: %i thresholds and %i bits", thrset, len(ctpUnusedInputNameSets[thrset]), ctpUnusedInputBitSets[thrset] )
359  if thrset is not None:
360  log.debug("Unused threshold set %s: %s", thrset, ",".join(ctpUnusedInputNameSets[thrset]) )
361  else:
362  log.debug("Unrecognised CTP input bits: %s", ",".join(ctpUnusedInputNameSets[thrset]) )
363  totalUnusedInputs += ctpUnusedInputBitSets[thrset]
364  log.debug("Number of un-used inputs bits: %i" , totalUnusedInputs )
365 
366  # Fail menu generation for menus going to P1:
367  if ( totalInputs > Limits.MaxTrigItems or len(ctpOutputs) > Limits.MaxTrigItems):
368  if 'AllCTPIn' in self.menuName:
369  log.warning(f"Input or output bits limit of {Limits.MaxTrigItems} exceeded in the dummy CTP menu -- OK")
370  else:
371  raise RuntimeError("Both the numbers of inputs and outputs need to be not greater than %i in a physics menu!" % Limits.MaxTrigItems)
372 
373  # Avoid that L1 item is defined only for BGRP0 as this include also the CALREQ BGRP2 (ATR-24781)
374  def checkBGRP(self):
375  for item in self.items:
376  if len(item.bunchGroups)==1 and item.bunchGroups[0]=='BGRP0':
377  raise RuntimeError("L1 item %s is defined with only BGRP0, ie it can trigger also in the CALREQ BGRP2 bunches. Please add another bunch group (ATR-24781)" % item.name)
378  if 'BGRP2' in item.bunchGroups:
379  thrtype = item.logic.content['threshold'].ttype
380  if thrtype in ThrType.CaloTypes():
381  # The LAr Digital Trigger sends an "align frame" to the FEXes in BCID 3500 (in BGRP2)
382  # No trigger can be sent during this align frame, so we block all calo triggers from this BGRP
383  raise RuntimeError(f"L1 item {item.name} with threshold type {thrtype} is in CALREQ BGRP2. This is not allowed!")
384 
385 
386  def checkPtMinToTopo(self):
387  # check that the ptMinToTopo for all types of thresholds is lower than the minimum Et cuts applied in multiplicity and decision algorithms
388 
389  # collect the ptMinToTopo values
390  ptMin = {}
391  for thrtype in ThrType.Run3Types():
392  ttconfig = getTypeWideThresholdConfig(thrtype, self.flags.Trigger.L1.Menu.doHeavyIonTobThresholds, self.flags.Trigger.L1.Menu.doeFexBDTTau)
393  inputtype = thrtype.name
394  if inputtype == 'cTAU':
395  inputtype = 'eTAU'
396  for key, value in ttconfig.items():
397  if "ptMinToTopo" in key:
398  if inputtype in ptMin:
399  if ptMin[inputtype] > value:
400  ptMin[inputtype] = value
401  else:
402  ptMin[inputtype] = value
403 
404  # loop over multiplicity algorithms and get the min et values
405  thresholdMin = {}
406  for algo in self.topoAlgos.topoAlgos[AlgCategory.MULTI][AlgType.MULT]:
407  alg = self.topoAlgos.topoAlgos[AlgCategory.MULTI][AlgType.MULT][algo]
408  threshold = alg.threshold
409  inputtype = alg.input
410  if 'cTAU' in inputtype:
411  inputtype = 'eTAU'
412  elif any(substring in inputtype for substring in ['XE','TE','MHT','LArSaturation','ZeroBias']):
413  continue
414  thr = self.thresholds.thresholds[threshold]
415  minEt = 99999
416  if hasattr(thr, 'thresholdValues'):
417  etvalues = thr.thresholdValues
418  for etvalue in etvalues:
419  et = etvalue.value
420  if et < minEt:
421  minEt = et
422  if hasattr(thr, 'et'):
423  if thr.et < minEt:
424  minEt = thr.et
425  if inputtype in thresholdMin:
426  if minEt < thresholdMin[inputtype]:
427  thresholdMin[inputtype] = minEt
428  else:
429  thresholdMin[inputtype] = minEt
430 
431  # loop over sorting algorithms and get the min et values
432  for algo in self.topoAlgos.topoAlgos[AlgCategory.TOPO][AlgType.SORT]:
433  alg = self.topoAlgos.topoAlgos[AlgCategory.TOPO][AlgType.SORT][algo]
434  if alg.inputvalue == 'MuonTobs':
435  continue
436  for (pos, variable) in enumerate(alg.variables):
437  if variable.name == "MinET":
438  value = variable.value/10 # convert energies from 100MeV to GeV units
439  inputtype = ''
440  if alg.inputvalue == 'eEmTobs':
441  inputtype = 'eEM'
442  elif alg.inputvalue == 'eTauTobs':
443  inputtype = 'eTAU'
444  elif alg.inputvalue == 'jJetTobs':
445  inputtype = 'jJ'
446  else:
447  raise RuntimeError("checkPtMinToTopo: input type %s in sorting algo not recognised" % alg.inputvalue)
448  if inputtype in thresholdMin:
449  if value < thresholdMin[inputtype]:
450  thresholdMin[inputtype] = value
451  else:
452  thresholdMin[inputtype] = value
453  for thr in thresholdMin:
454  if thr in ptMin:
455  if thresholdMin[thr] < ptMin[thr]:
456  raise RuntimeError("checkPtMinToTopo: for threshold type %s the minimum threshold %i is less than ptMinToTopo %i" % (thr, thresholdMin[thr], ptMin[thr]))
457  else:
458  raise RuntimeError("checkPtMinToTopo: for threshold type %s the minimum threshold is %i and no ptMinToTopo value is found" % (thr, thresholdMin[thr]))
459 
460  def checkL1TopoParams(self):
461  from ..Menu.L1TopoParams import L1TopoParams as params
462 
463  algo_param_mismatch = []
464  # No need to check multiplicity algs
465  for algtype in [AlgType.SORT, AlgType.DEC]:
466  # Only check Phase-I Topo algs
467  for algname,algo in self.topoAlgos.topoAlgos[AlgCategory.TOPO][algtype].items():
468  log.debug(f'Checking variable parameter ordering for {algname} ({algo.classtype})')
469  pars_for_algo = params[algo.classtype]
470  generics_map = {g.name:g.value for g in algo.generics}
471  # No conditional parameters
472  common_params = None # Common parameters at the beginning, not repeated on multiple algo instances
473  ordered_params = None # Parameters that can be repeated if configuring multiple algo instances
474  if 'common_parameters' in pars_for_algo:
475  common_params = pars_for_algo['common_parameters']
476  if 'parameters' in pars_for_algo:
477  ordered_params = pars_for_algo['parameters']
478  # If all of the param lists are None, we have conditionals
479  if common_params is None and ordered_params is None:
480  for cond in pars_for_algo.keys():
481  if cond == 'comment': continue
482 
483  # Check that the condition is valid
484  pass_condition = True
485  for c in cond.split(' and '):
486  condname, condval = c.split(' = ')
487  if condname in generics_map:
488  if int(condval) == generics_map[condname]:
489  continue
490  else:
491  pass_condition = False
492  break
493  elif int(condval) == 0: # If the generic is not defined, assume that false is ok
494  continue
495  else:
496  pass_condition = False
497  break
498 
499  if pass_condition:
500  if 'common_parameters' in pars_for_algo[cond]:
501  common_params = pars_for_algo[cond]['common_parameters']
502  if 'parameters' in pars_for_algo[cond]:
503  ordered_params = pars_for_algo[cond]['parameters']
504  break
505 
506  if common_params is None and ordered_params is None and common_params is None:
507  raise RuntimeError(f'checkL1TopoParams: Did not find ordered parameter list for L1Topo algorithm type {algo.classtype}')
508 
509  menu_params = [p.name for p in algo.variables]
510  log.debug(f'Menu contains parameter list: {menu_params}')
511 
512  if common_params is None: common_params = []
513  if ordered_params is None: ordered_params = []
514  log.debug(f'Expected parameter list: {common_params + ordered_params}')
515 
516  # Handle case where parameters are supplied repeatedly to
517  # configure multiple instances
518  non_common_param_count = len(menu_params) - len(common_params)
519  if non_common_param_count > len(ordered_params):
520  log.debug(f'Can repeat the parameters: {ordered_params}')
521  if non_common_param_count % len(ordered_params) == 0:
522  ordered_params = int(non_common_param_count/len(ordered_params)) * ordered_params
523  else:
524  log.error("Mismatch in number of parameters")
525 
526  total_params = common_params + ordered_params
527  if menu_params != total_params:
528  log.error(f'checkL1TopoParams: Parameter list for {algo.name}/{algo.classtype} does not match specification')
529  log.error(f' Menu contains parameter list {menu_params}')
530  log.error(f' Expected parameter list {total_params}')
531  algo_param_mismatch.append(algo)
532 
533  if algo_param_mismatch:
534  log.error('checkL1TopoParams: Following L1Topo algorithms have incorrect parameter ordering in L1Menu:')
535  for algo in algo_param_mismatch:
536  log.error(f' {algo.name} ({algo.classtype})')
537  raise RuntimeError('checkL1TopoParams: L1Topo algorithm parameters do not match specification')
538 
540  all_ctpin = []
541  connected_boards = []
542  for layout,connectors in self.ctp.inputConnectors.items():
543  for connector, contents in connectors.items():
544  if layout=='ctpin':
545  # Ignore empty
546  connected_boards += [board for board in contents.values() if board]
547  else:
548  connected_boards.append(contents)
549 
550  for conn_name in connected_boards:
551  conn = self.connectors[conn_name]
552  if conn.ctype != CType.ELEC:
553  for tl in conn.triggerLines:
554  thrName = tl.name
555  if thrName[:3]=='ZB_':
556  thrName = thrName[3:]
557  all_ctpin.append(thrName)
558  else:
559  for fpga in conn.triggerLines:
560  for clock in conn.triggerLines[fpga]:
561  for tl in conn.triggerLines[fpga][clock]:
562  thrName = tl.name
563  if thrName[:3]=='ZB_':
564  thrName = thrName[3:]
565  all_ctpin.append(thrName)
566 
567  for item in self.items:
568  for thrName in item.thresholdNames():
569  if thrName[:3]=='ZB_':
570  thrName = thrName[3:]
571  if thrName not in all_ctpin:
572  raise RuntimeError(
573  f'checkItemsHaveInputs: Threshold {thrName} used by {item.name} is not on a board connected to CTP')
574 
575  def checkHFmonitoring(self):
576  requiredItems = [
577  "L1_BCM_2A_FIRSTINTRAIN",
578  "L1_BCM_2C_FIRSTINTRAIN"
579  ]
580  missingItems = [item for item in requiredItems if self.items.items[item].monitorsHF == 0]
581  if missingItems:
582  raise RuntimeError(
583  f'The HF monitoring flags for {", ".join(missingItems)} are missing')
python.L1.Base.L1Menu.L1Menu.flags
flags
Definition: L1Menu.py:33
python.L1.Base.L1Menu.L1Menu.getItem
def getItem(self, name)
Definition: L1Menu.py:64
python.L1.Config.TypeWideThresholdConfig.getTypeWideThresholdConfig
def getTypeWideThresholdConfig(ttype, do_HI_tob_thresholds=False, do_eFex_BDT_Tau=True)
Definition: TypeWideThresholdConfig.py:102
python.L1.Base.L1Menu.L1Menu.thresholds
thresholds
Definition: L1Menu.py:36
python.L1.Base.L1Menu.L1Menu.setBunchGroupSplitting
def setBunchGroupSplitting(self, v=True)
Definition: L1Menu.py:56
python.L1.Base.L1Menu.L1Menu.boards
boards
Definition: L1Menu.py:45
python.L1.Base.L1Menu.L1Menu.ctp
ctp
Definition: L1Menu.py:48
python.L1.Base.TopoAlgorithms.MenuTopoAlgorithmsCollection
Definition: TopoAlgorithms.py:53
python.L1.Base.L1Menu.L1Menu.addThreshold
def addThreshold(self, threshold)
Definition: L1Menu.py:68
python.L1.Base.L1Menu.L1Menu.checkCountCTPInputsOutput
def checkCountCTPInputsOutput(self)
Definition: L1Menu.py:221
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
python.L1.Base.L1Menu.L1Menu.checkPerfThresholds
def checkPerfThresholds(self)
Definition: L1Menu.py:133
python.L1.Base.L1Menu.L1Menu.checkBoardInputs
def checkBoardInputs(self, algo, connDefName, fpgaName)
Definition: L1Menu.py:144
python.L1.Base.L1Menu.L1Menu.checkHFmonitoring
def checkHFmonitoring(self)
Definition: L1Menu.py:575
python.L1.Base.MenuUtils.get_smk_psk_Name
def get_smk_psk_Name(menuName)
Definition: MenuUtils.py:30
python.L1.Base.L1Menu.L1Menu.addTopoAlgo
def addTopoAlgo(self, algo, category)
Definition: L1Menu.py:72
python.L1.Base.Connectors.MenuConnectorsCollection
Definition: Connectors.py:53
python.L1.Base.L1Menu.L1Menu.checkCTPINconnectors
def checkCTPINconnectors(self)
Definition: L1Menu.py:199
python.L1.Base.L1Menu.L1Menu.topoAlgos
topoAlgos
Definition: L1Menu.py:39
python.L1.Base.Thresholds.MenuThresholdsCollection
Definition: Trigger/TriggerCommon/TriggerMenuMT/python/L1/Base/Thresholds.py:18
python.LArMinBiasAlgConfig.int
int
Definition: LArMinBiasAlgConfig.py:59
python.L1.Base.L1Menu.L1Menu.addConnector
def addConnector(self, connDef)
Definition: L1Menu.py:81
python.L1.Base.L1Menu.L1Menu.checkBGRP
def checkBGRP(self)
Definition: L1Menu.py:374
python.L1.Base.L1Menu.L1Menu.addBoard
def addBoard(self, boardDef)
Definition: L1Menu.py:77
python.L1.Base.CTP.CTP
Definition: CTP.py:13
python.L1.Base.L1Menu.L1Menu.addItem
def addItem(self, item)
Definition: L1Menu.py:60
python.L1.Base.L1Menu.L1Menu.menuFullName
menuFullName
Definition: L1Menu.py:27
python.L1.Base.L1Menu.L1Menu.setupCTPMonitoring
def setupCTPMonitoring(self)
Definition: L1Menu.py:85
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename T::value_type > sorted(T begin, T end)
Helper function to create a sorted vector from an unsorted one.
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:232
python.L1.Base.L1Menu.L1Menu.checkItemsHaveInputs
def checkItemsHaveInputs(self)
Definition: L1Menu.py:539
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
python.L1.Base.L1Menu.L1Menu.check
def check(self)
Definition: L1Menu.py:88
library_scraper.dd
list dd
Definition: library_scraper.py:46
python.L1.Base.Items.MenuItemsCollection
Definition: Items.py:17
python.L1.Base.L1Menu.L1Menu.checkL1TopoParams
def checkL1TopoParams(self)
Definition: L1Menu.py:460
python.L1.Base.L1Menu.L1Menu
Definition: L1Menu.py:19
python.L1.Base.L1Menu.L1Menu.connectors
connectors
Definition: L1Menu.py:42
python.L1.Base.L1Menu.L1Menu.checkL1CaloThresholds
def checkL1CaloThresholds(self, thresholds, boardName, connName)
Definition: L1Menu.py:172
python.L1.Base.L1Menu.L1Menu.checkTOPObits
def checkTOPObits(self)
Definition: L1Menu.py:205
pickleTool.object
object
Definition: pickleTool.py:30
python.L1.Base.L1Menu.L1Menu.checkPtMinToTopo
def checkPtMinToTopo(self)
Definition: L1Menu.py:386
python.L1.Base.L1Menu.L1Menu.items
items
Definition: L1Menu.py:30
python.L1.Base.Boards.MenuBoardsCollection
Definition: Boards.py:36
python.L1.Base.L1Menu.L1Menu.menuName
menuName
Definition: L1Menu.py:25
python.L1.Base.L1Menu.L1Menu.__init__
def __init__(self, menuName, flags)
Definition: L1Menu.py:24
python.L1.Base.L1Menu.L1Menu.checkLegacyThresholds
def checkLegacyThresholds(self)
Definition: L1Menu.py:118