3 from typing
import Optional
4 import importlib, re, string
6 from TriggerMenuMT.HLT.Config.Utility.HLTMenuConfig
import HLTMenuConfig
8 from AthenaCommon.Logging
import logging
9 log = logging.getLogger(__name__)
12 _maxAllowedCustomCH = 10
15 return [
'Streaming',
'Monitor',
'Beamspot',
'Cosmic',
'Calib',
'EnhancedBias']
18 return [
'MinBias',
'Electron',
'Photon',
'Muon',
'Tau',
'Jet',
'Bjet',
'MET',
'UnconventionalTracking',
'HeavyIon']
21 return [
'Bjet',
'Egamma',
'Combined']
37 """Standard chain filter"""
39 self.
enabledSignatures = flags.Trigger.enabledSignatures
if flags.hasFlag(
"Trigger.enabledSignatures")
else []
40 self.
disabledSignatures = flags.Trigger.disabledSignatures
if flags.hasFlag(
"Trigger.disabledSignatures")
else []
41 self.
selectChains = flags.Trigger.selectChains
if flags.hasFlag(
"Trigger.selectChains")
else []
42 self.
disableChains = flags.Trigger.disableChains
if flags.hasFlag(
"Trigger.disableChains")
else []
49 return f
'FilterChainsToGenerate(enabledSignatures={self.enabledSignatures}, disabledSignatures={self.disabledSignatures}, selectChains={self.selectChains}, disableChains={self.disableChains})'
64 """Singleton class for the Trigger Menu"""
91 signatureDeps = {sig:[sig]
for sig
in allSigs}
93 signatureDeps.update({
95 'Bjet': [
'Bjet',
'Jet'],
97 'Egamma': [
'Electron',
'Photon'],
104 """Set chain filter for menu generation.
106 This can be any callable object taking two
107 arguments for signature and chain name and returning a boolean.
108 E.g. to only generate Egamma chains:
109 menu.setChainFilter(lambda slice,chain : slice=='Egamma').
111 In the special case that f is a functor with the list attributes
112 selectChains and/or disableChains, the contents will be explicitly
113 checked to be in the menu.
115 fname = f.__class__.__name__
if isinstance(f,object)
else f.__name__
117 if len(inspect.signature(f).parameters)!=2:
118 log.error(
'%s is not a valid chain filter. Function/callable needs take two arguments '
119 'for signature and chain name and return a boolean', fname)
121 log.info(
'Setting chain filter to: %s', f)
127 def validSignature(currentSig, chainSig):
128 """Check if chain is assigned to the correct signature"""
129 reqd = GenerateMenuMT.getRequiredSignatures(currentSig)
130 isValid = chainSig.issubset( reqd )
131 log.debug(
"Chain signatures: %s, required signatures: %s",chainSig,reqd)
133 log.error(
"Chain signatures %s not a subset of required signatures %s",
set(chainSig),reqd)
136 from TriggerMenuMT.HLT.Config.Utility.DictFromChainName
import dictFromChainName
142 log.debug(
"Now processing chain: %s from signature %s", chain, sig)
145 chainDict[
'chainCounter'] = chainCounter
146 chainDict[
'prescale'] = 1
149 for sigfo, subsig
in chainDict[
'sigDicts'].
items():
159 if not validSignature(sig,
set(chainDict[
'signatures'])):
161 log.error(
'Chain %s assigned to signature %s but creates %s',
162 chainDict[
'chainName'], sig,
set(chainDict[
'signatures']))
164 raise RuntimeError(
'Incorrect assignment of chains to slices -- see preceding messages.')
167 """check if all the signature files can be imported and then import them"""
172 import_module =
'TriggerMenuMT.HLT.' + sig +
'.Generate' + ss +
'ChainDefs'
179 log.exception(
'Problems when importing ChainDef generating code for %s', sig)
181 traceback.print_exc()
189 combinations_in_menu = []
190 alignmentGroups_to_align =
set()
191 length_of_configs = {}
194 notify_increment =
max(
int(nchainDicts / 10),1)
195 for ichainDict, chainDict
in enumerate(self.
chainDicts):
196 log.debug(
"Next: getting chain configuration for chain %s ", chainDict[
'chainName'])
197 if ichainDict % notify_increment==0:
198 log.info(
"Generating HLT chain %d / %d", ichainDict+1, nchainDicts)
200 all_chains += [(chainDict,chainConfig,lengthOfChainConfigs)]
204 for config_length, config_grp
in lengthOfChainConfigs:
205 if config_grp
in length_of_configs:
206 if config_length > length_of_configs[config_grp]:
207 length_of_configs[config_grp] = config_length
209 length_of_configs[config_grp] = config_length
214 if len(
set(chainDict[
'alignmentGroups'])) > 1:
215 combinations_in_menu += [
list(
set(chainDict[
'alignmentGroups']))]
216 for align_group
in list(
set(chainDict[
'alignmentGroups'])):
217 alignmentGroups_to_align.update([align_group])
229 == Obtains chain configs for all chains in menu
232 from TriggerMenuMT.HLT.Config.Utility.MenuAlignmentTools
import MenuAlignment
233 from TriggerMenuMT.HLT.CommonSequences
import EventBuildingSequences, TLABuildingSequences
236 log.info(
"Will now get chains from the menu")
240 log.info(
"Will now get chain dictionaries for each chain")
243 if flags.Trigger.disableCPS:
244 log.warning(
'Removing all CPS group because the flag Trigger.disableCPS is set')
246 chainDict[
'groups'] = [g
for g
in chainDict[
'groups']
if not g.startswith(
'RATE:CPS_')]
249 log.debug(
"Importing the necessary signatures")
252 log.info(
"Will now generate the chain configuration for each chain")
255 log.info(
"Will now calculate the alignment parameters")
261 menuAlignment.analyse_combinations()
268 log.info(
'Aligning the following signatures: %s',
sorted(menuAlignment.sets_to_align))
269 log.debug(
'Length of each of the alignment groups: %s',self.
configLengthDict)
284 log.debug(
"[generateAllChainConfigs] chain %s has config lengths %s and alignment groups %s", chainDict[
'chainName'], lengthOfChainConfigs, chainDict[
'alignmentGroups'])
286 alignmentGroups = chainDict[
'alignmentGroups']
289 if len(
set(alignmentGroups)) == 1:
290 alignedChainConfig = menuAlignment.single_align(chainDict, chainConfig)
291 HLTMenuConfig.registerChain( chainDict )
292 chainConfigs.append( alignedChainConfig )
294 elif len(alignmentGroups) >= 2:
295 alignedChainConfig = menuAlignment.multi_align(chainDict, chainConfig, lengthOfChainConfigs)
296 HLTMenuConfig.registerChain( chainDict )
297 chainConfigs.append( alignedChainConfig )
300 log.error(
"Menu can't deal with combined chains with more than two alignmentGroups at the moment. oops...")
301 raise NotImplementedError(
"more than three alignment groups still needs implementing in ChainMerging.py, ATR-22206")
303 if not HLTMenuConfig.isChainRegistered(chainDict[
'chainName']):
304 log.error(
"Chain %s has not been registered in the menu!", chainDict[
'chainName'])
306 pp = pprint.PrettyPrinter(indent=4, depth=8)
307 log.error(
'The chain dictionary is: %s', pp.pformat(chainDict))
308 raise Exception(
"Please fix the menu or the chain.")
311 log.info(
"[generateAllChainConfigs] general alignment complete, will now align TLA chains")
312 TLABuildingSequences.alignTLASteps(chainConfigs, HLTMenuConfig.dicts())
313 log.info(
"[generateAllChainConfigs] general and TLA alignment complete, will now align PEB chains")
314 EventBuildingSequences.alignEventBuildingSteps(chainConfigs, HLTMenuConfig.dicts())
316 log.info(
"[generateAllChainConfigs] all chain configurations have been generated.")
322 == Returns the list of chain names that are in the menu
326 log.info(f
'Menu name: {flags.Trigger.triggerMenuSetup}')
331 menu_module = importlib.import_module(f
'TriggerMenuMT.HLT.Menu.{self.base_menu_name}')
332 except Exception
as e:
333 log.fatal(f
'Failed to import menu module "{self.base_menu_name}" inferred from menu "{flags.Trigger.triggerMenuSetup}"')
350 for chain
in chainsToCheck:
353 if chain
in [c.name
for c
in self.
chainsInMenu[signame]]:
357 raise RuntimeError(f
'Request to enable/disable chain {chain} that is not in menu')
364 log.warning(
"There seem to be no chains in the menu - please check")
365 elif log.isEnabledFor(logging.DEBUG):
367 log.debug(
"The following chains were found in the menu:")
373 # Assembles the chain configuration and returns a chain object with (name, L1see and list of ChainSteps)
376 from TriggerMenuMT.HLT.Config.Utility.ChainDictTools
import splitInterSignatureChainDict
377 from TriggerMenuMT.HLT.Config.Utility.ComboHypoHandling
import addTopoInfo, comboConfigurator, topoLegIndices, anomdetWPIndices
378 from TriggerMenuMT.HLT.Config.Utility.ChainMerging
import mergeChainDefs
379 from TriggerMenuMT.HLT.CommonSequences
import EventBuildingSequences, TLABuildingSequences
384 if log.isEnabledFor(logging.DEBUG):
386 pp = pprint.PrettyPrinter(indent=4, depth=8)
387 log.debug(
'dictionary is: %s', pp.pformat(chainDicts))
390 listOfChainConfigs = []
391 perSig_lengthOfChainConfigs = []
393 for chainPartDict
in chainDicts:
394 chainPartConfig =
None
395 currentSig = chainPartDict[
'signature']
396 currentAlignGroup =
None
397 if len(chainPartDict[
'chainParts']) == 1:
398 currentAlignGroup = chainPartDict[
'chainParts'][0][
'alignmentGroup']
400 chainName = chainPartDict[
'chainName']
401 log.debug(
'Checking chainDict for chain %s in signature %s, alignment group %s' , chainName, currentSig, currentAlignGroup)
405 log.debug(
"[__generateChainConfigs] Trying to get chain config for %s", currentSig)
406 if currentSig
in [
'Electron',
'Photon',
'Muon',
'Tau',
'Bphysics'] :
410 if currentSig ==
'Test' and isinstance(chainPartConfig, tuple):
411 chainPartConfig = chainPartConfig[0]
413 log.error(
'[__generateChainConfigs] Problems creating ChainDef for chain %s ', chainName)
414 log.error(
'[__generateChainConfigs] I am in chain part\n %s ', chainPartDict)
415 log.exception(
'[__generateChainConfigs] Full chain dictionary is\n %s ', mainChainDict)
416 raise Exception(
'[__generateChainConfigs] Stopping menu generation. Please investigate the exception shown above.')
418 log.error(
'Chain %s cannot be generated - Signature "%s" not available', chainPartDict[
'chainName'], currentSig)
420 raise Exception(
'Stopping the execution. Please correct the configuration.')
422 log.debug(
"Chain %s \n chain config: %s",chainPartDict[
'chainName'],chainPartConfig)
424 listOfChainConfigs.append(chainPartConfig)
425 log.debug(
"[__generateChainConfigs] adding to the perSig_lengthOfChainConfigs list (%s, %s)",chainPartConfig.nSteps,chainPartConfig.alignmentGroups)
426 perSig_lengthOfChainConfigs.append((chainPartConfig.nSteps,chainPartConfig.alignmentGroups))
431 lengthOfChainConfigs = []
432 for nSteps, aGrps
in perSig_lengthOfChainConfigs:
433 if len(nSteps) != len(aGrps):
434 log.error(
"Chain part has %s steps and %s alignment groups - these don't match!",nSteps,aGrps)
436 for a,b
in zip(nSteps,aGrps):
437 lengthOfChainConfigs.append((a,b))
442 if len(listOfChainConfigs) == 0:
443 raise Exception(
'[__generateChainConfigs] No Chain Configuration found for {0}'.
format(mainChainDict[
'chainName']))
445 if len(listOfChainConfigs)>1:
446 log.debug(
"Merging strategy from dictionary: %s", mainChainDict[
"mergingStrategy"])
447 theChainConfig, perSig_lengthOfChainConfigs =
mergeChainDefs(listOfChainConfigs, mainChainDict, perSig_lengthOfChainConfigs)
448 lengthOfChainConfigs = []
449 for nSteps, aGrps
in perSig_lengthOfChainConfigs:
450 if len(nSteps) != len(aGrps):
451 log.error(
"Post-merged chain part has %s steps and %s alignment groups - these don't match!",nSteps,aGrps)
453 for a,b
in zip(nSteps,aGrps):
454 lengthOfChainConfigs.append((a,b))
456 theChainConfig = listOfChainConfigs[0]
458 for topoID
in range(len(mainChainDict[
'extraComboHypos'])):
459 thetopo = mainChainDict[
'extraComboHypos'][topoID].strip(string.digits).rstrip(topoLegIndices)
462 if "anomdet" in thetopo:
463 thetopo = thetopo.rstrip(anomdetWPIndices)
465 theChainConfig.addTopo((comboConfigurator[thetopo],thetopo))
468 if len(theChainConfig.topoMap) > 0:
469 log.debug(
"Trying to add extra ComboHypoTool for %s",mainChainDict[
'extraComboHypos'])
470 addTopoInfo(theChainConfig,mainChainDict,listOfChainConfigs,lengthOfChainConfigs)
472 log.error(
'[__generateChainConfigs] Problems creating ChainDef for chain %s ', chainName)
473 log.error(
'[__generateChainConfigs] I am in the extraComboHypos section, for %s ', mainChainDict[
'extraComboHypos'])
474 log.exception(
'[__generateChainConfigs] Full chain dictionary is\n %s ', mainChainDict)
475 raise Exception(
'[__generateChainConfigs] Stopping menu generation. Please investigate the exception shown above.')
476 except AttributeError:
477 raise Exception(
'[__generateChainConfigs] Stopping menu generation. Please investigate the exception shown above.')
480 eventBuildType = mainChainDict[
'eventBuildType']
483 if 'PhysicsTLA' in eventBuildType:
484 log.debug(
"Adding TLA Step for chain %s", mainChainDict[
'chainName'])
485 TLABuildingSequences.addTLAStep(flags, theChainConfig, mainChainDict)
486 log.debug(
'Configuring event building sequence %s for chain %s', eventBuildType, mainChainDict[
'chainName'])
487 EventBuildingSequences.addEventBuildingSequence(flags, theChainConfig, eventBuildType, mainChainDict)
488 except TypeError
as ex:
490 raise Exception(
'[__generateChainConfigs] Stopping menu generation for EventBuilding/TLA sequences. Please investigate the exception shown above.')
492 log.debug(
'[__generateChainConfigs] lengthOfChainConfigs %s, ChainConfigs %s ', lengthOfChainConfigs, theChainConfig)
493 return theChainConfig,lengthOfChainConfigs
497 max_steps =
max([len(cc.steps)
for cc
in chainConfigs], default=0)
498 steps_are_empty = [
True for i
in range(0,max_steps)]
500 for cc
in chainConfigs:
501 for istep, the_step
in enumerate(cc.steps):
502 if not the_step.isEmpty:
503 steps_are_empty[istep] =
False
505 emptySteps.append(the_step)
507 log.debug(
"Are there any fully empty steps? %s", steps_are_empty)
508 log.debug(
"The empty step(s) and associated chain(s) are: %s", emptySteps)
509 empty_step_indices = [i
for i,is_empty
in enumerate(steps_are_empty)
if is_empty]
511 if len(empty_step_indices) == 0:
515 getattr(self.
chainFilter,
"disableChains",
False)
or \
516 getattr(self.
chainFilter,
"disabledSignatures",
False)
or \
517 getattr(self.
chainFilter,
"enabledSignatures",
False) )
521 raise Exception(
"[resolveEmptySteps] Please find the reason for this empty step and resolve it / remove it from the menu: %s", emptySteps)
523 log.info(
"Will now delete steps %s (indexed from zero)",empty_step_indices)
525 for cc
in chainConfigs:
528 for istep,step
in enumerate(cc.steps):
529 if istep
not in empty_step_indices:
536 '''Add prescales for disabling items (e.g. MC production)'''
538 menu_name = flags.Trigger.triggerMenuSetup
539 if prescale_set ==
'__auto__':
540 if menu_name.endswith(
'_prescale'):
542 prescale_set = menu_name.removeprefix(f
'{self.base_menu_name}_').removesuffix(
'_prescale')
547 from TriggerMenuMT.HLT.Menu.MenuPrescaleConfig
import menu_prescale_set_gens
548 if prescale_set
not in menu_prescale_set_gens:
549 raise RuntimeError(f
'Unknown menu prescale set for menu {flags.Trigger.triggerMenuSetup}')
551 gen = menu_prescale_set_gens[prescale_set]
553 from TriggerMenuMT.HLT.Config.Utility.MenuPrescaleSet
import AutoPrescaleSetGen
554 gen = AutoPrescaleSetGen()
557 log.info(f
'Generating automatic prescale set: {prescale_set}')
558 ps_set = gen.generate(flags, store=
True)
566 == Main function to generate the L1, L1Topo and HLT menu configs and CA, using the GenerateMenuMT class
570 from TrigConfigSvc.TrigConfigSvcCfg
import generateL1Menu
578 menu.setChainFilter(chains_gen_filter)
579 log.debug(
'Filtering chains: %d', menu.chainFilter
is not None)
582 finalListOfChainConfigs = menu.generateAllChainConfigs(flags)
584 log.info(
'Number of configured chains: %d', len(finalListOfChainConfigs))
585 from TriggerMenuMT.HLT.Config
import MenuComponents
586 if len(MenuComponents._CustomComboHypoAllowed)> _maxAllowedCustomCH:
587 log.error(f
'Found {len(MenuComponents._CustomComboHypoAllowed)} ComboHypo algorithms violating the one-CH-per-step rule, only {_maxAllowedCustomCH} are allowed (which are BLS ComboHypos). This is the list of current violations: {MenuComponents._CustomComboHypoAllowed}. Please consolidate your choice of ComboHypo, by checking that it is able to handle decisions internally; if yes eventually increase the limit set by _maxAllowedCustomCH, after discussing with experts')
589 menu.generatePrescales(flags)
593 finalListOfChainConfigs = menu.resolveEmptySteps(finalListOfChainConfigs)
594 log.debug(
"finalListOfChainConfig: %s", finalListOfChainConfigs)
598 log.info(
"Making the HLT configuration tree")
599 menuAcc, CFseq_list =
makeHLTTree(flags, finalListOfChainConfigs)
602 from TriggerJobOpts.TriggerConfigFlags
import ROBPrefetching
603 if ROBPrefetching.InitialRoI
in flags.Trigger.ROBPrefetchingOptions:
604 from TrigGenericAlgs.TrigGenericAlgsConfig
import prefetchingInitialRoIConfig
609 log.info(
"Checking the L1HLTConsistency...")
610 from TriggerMenuMT.HLT.Config.Validation.CheckL1HLTConsistency
import checkL1HLTConsistency
613 log.info(
"Checking the Coherent Prescale assignments...")
614 from TriggerMenuMT.HLT.Config.Validation.CheckCPSGroups
import checkCPSGroups
619 GenerateMenuMT.clear()
620 from TriggerMenuMT.HLT.Config
import MenuComponents
621 MenuComponents._ComboHypoPool.clear()
622 MenuComponents._CustomComboHypoAllowed.clear()
629 Generate appropriate Control Flow Graph wiht all HLT algorithms
631 from TriggerMenuMT.HLT.Config.ControlFlow.HLTCFConfig
import decisionTreeFromChains, sequenceScanner
632 from TriggerJobOpts.TriggerConfig
import collectViewMakers
633 from AthenaConfiguration.ComponentAccumulator
import ComponentAccumulator
634 from AthenaCommon.CFElements
import seqAND
637 steps =
seqAND(
'HLTAllSteps')
638 finalDecisions, CFseq_list, menuAcc =
decisionTreeFromChains(flags, steps, chainConfigs, HLTMenuConfig.dictsList())
639 if log.getEffectiveLevel() <= logging.DEBUG:
640 menuAcc.printConfig()
644 if not successful_scan:
645 raise Exception(
"[makeHLTTree] At least one sequence is expected in more than one step. Check error messages and fix!")
648 for step
in finalDecisions:
649 flatDecisions.extend (step)
652 viewMakerMap = {vm.name:vm
for vm
in viewMakers}
653 for vmname, vm
in viewMakerMap.items():
654 log.debug(f
"[makeHLTTree] {vmname} InputMakerOutputDecisions: {vm.InputMakerOutputDecisions}")
655 if vmname.endswith(
"_probe"):
657 log.debug(f
"Setting InputCachedViews on {vmname} to read decisions from tag leg {vmname[:-6]}: {vm.InputMakerOutputDecisions}")
658 vm.InputCachedViews = viewMakerMap[vmname[:-6]].InputMakerOutputDecisions
660 log.debug(f
"Tag leg does not match probe: '{vmname[:-6]}', will not use cached views")
664 from TriggerMenuMT.HLT.Config.JSON.HLTMenuJSON
import generateJSON
665 generateJSON(flags, HLTMenuConfig.dictsList(), menuAcc.getSequence(
"HLTAllSteps"))
668 from TriggerMenuMT.HLT.Config.JSON.HLTMonitoringJSON
import generateDefaultMonitoringJSON
672 from AthenaCommon.CFElements
import checkSequenceConsistency
674 return acc, CFseq_list