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 for f
in (
"enabledSignatures",
"disabledSignatures",
"selectChains",
"disableChains"):
41 value = getattr(flags.Trigger, f)
42 assert isinstance(value, list), f
"Flag Trigger.{f}={value!r} is not of type list"
44 setattr(self, f, value)
47 return ((signame
in self.enabledSignatures
and signame
not in self.disabledSignatures)
and \
48 (
not self.selectChains
or chain
in self.selectChains)
and chain
not in self.disableChains)
51 return f
'FilterChainsToGenerate(enabledSignatures={self.enabledSignatures!r}, disabledSignatures={self.disabledSignatures!r}, selectChains={self.selectChains!r}, disableChains={self.disableChains!r})'
66 """Singleton class for the Trigger Menu"""
94 signatureDeps = {sig:[sig]
for sig
in allSigs}
96 signatureDeps.update({
98 'Bjet': [
'Bjet',
'Jet'],
100 'Egamma': [
'Electron',
'Photon'],
107 """Set chain filter for menu generation.
109 This can be any callable object taking two
110 arguments for signature and chain name and returning a boolean.
111 E.g. to only generate Egamma chains:
112 menu.setChainFilter(lambda slice,chain : slice=='Egamma').
114 In the special case that f is a functor with the list attributes
115 selectChains and/or disableChains, the contents will be explicitly
116 checked to be in the menu.
118 fname = f.__class__.__name__
if isinstance(f,object)
else f.__name__
120 if len(inspect.signature(f).parameters)!=2:
121 log.error(
'%s is not a valid chain filter. Function/callable needs take two arguments '
122 'for signature and chain name and return a boolean', fname)
124 log.info(
'Setting chain filter to: %s', f)
130 def validSignature(currentSig, chainSig):
131 """Check if chain is assigned to the correct signature"""
132 reqd = GenerateMenuMT.getRequiredSignatures(currentSig)
133 isValid = chainSig.issubset( reqd )
134 log.debug(
"Chain signatures: %s, required signatures: %s",chainSig,reqd)
136 log.error(
"Chain signatures %s not a subset of required signatures %s",
set(chainSig),reqd)
139 from TriggerMenuMT.HLT.Config.Utility.DictFromChainName
import dictFromChainName
145 log.debug(
"Now processing chain: %s from signature %s", chain, sig)
148 chainDict[
'chainCounter'] = chainCounter
149 chainDict[
'prescale'] = 1
152 for sigfo, subsig
in chainDict[
'sigDicts'].
items():
162 if not validSignature(sig,
set(chainDict[
'signatures'])):
164 log.error(
'Chain %s assigned to signature %s but creates %s',
165 chainDict[
'chainName'], sig,
set(chainDict[
'signatures']))
167 raise RuntimeError(
'Incorrect assignment of chains to slices -- see preceding messages.')
170 """check if all the signature files can be imported and then import them"""
175 import_module =
'TriggerMenuMT.HLT.' + sig +
'.Generate' + ss +
'ChainDefs'
182 log.exception(
'Problems when importing ChainDef generating code for %s', sig)
184 traceback.print_exc()
192 combinations_in_menu = []
193 alignmentGroups_to_align =
set()
194 length_of_configs = {}
197 notify_increment =
max(
int(nchainDicts / 10),1)
198 for ichainDict, chainDict
in enumerate(self.
chainDicts):
199 log.debug(
"Next: getting chain configuration for chain %s ", chainDict[
'chainName'])
200 if ichainDict % notify_increment==0:
201 log.info(
"Generating HLT chain %d / %d", ichainDict+1, nchainDicts)
203 all_chains += [(chainDict,chainConfig,lengthOfChainConfigs)]
207 for config_length, config_grp
in lengthOfChainConfigs:
208 if config_grp
in length_of_configs:
209 if config_length > length_of_configs[config_grp]:
210 length_of_configs[config_grp] = config_length
212 length_of_configs[config_grp] = config_length
217 if len(
set(chainDict[
'alignmentGroups'])) > 1:
218 combinations_in_menu += [
list(
set(chainDict[
'alignmentGroups']))]
219 for align_group
in list(
set(chainDict[
'alignmentGroups'])):
220 alignmentGroups_to_align.update([align_group])
232 == Obtains chain configs for all chains in menu
235 from TriggerMenuMT.HLT.Config.Utility.MenuAlignmentTools
import MenuAlignment
236 from TriggerMenuMT.HLT.CommonSequences
import EventBuildingSequences, TLABuildingSequences
239 log.info(
"Will now get chains from the menu")
243 log.info(
"Will now get chain dictionaries for each chain")
246 if flags.Trigger.disableCPS:
247 log.warning(
'Removing all CPS group because the flag Trigger.disableCPS is set')
249 chainDict[
'groups'] = [g
for g
in chainDict[
'groups']
if not g.startswith(
'RATE:CPS_')]
252 log.debug(
"Importing the necessary signatures")
255 log.info(
"Will now generate the chain configuration for each chain")
258 log.info(
"Will now calculate the alignment parameters")
264 menuAlignment.analyse_combinations()
271 log.info(
'Aligning the following signatures: %s',
sorted(menuAlignment.sets_to_align))
272 log.debug(
'Length of each of the alignment groups: %s',self.
configLengthDict)
287 log.debug(
"[generateAllChainConfigs] chain %s has config lengths %s and alignment groups %s", chainDict[
'chainName'], lengthOfChainConfigs, chainDict[
'alignmentGroups'])
289 alignmentGroups = chainDict[
'alignmentGroups']
292 if len(
set(alignmentGroups)) == 1:
293 alignedChainConfig = menuAlignment.single_align(chainDict, chainConfig)
294 HLTMenuConfig.registerChain( chainDict )
295 chainConfigs.append( alignedChainConfig )
297 elif len(alignmentGroups) >= 2:
298 alignedChainConfig = menuAlignment.multi_align(chainDict, chainConfig, lengthOfChainConfigs)
299 HLTMenuConfig.registerChain( chainDict )
300 chainConfigs.append( alignedChainConfig )
303 log.error(
"Menu can't deal with combined chains with more than two alignmentGroups at the moment. oops...")
304 raise NotImplementedError(
"more than three alignment groups still needs implementing in ChainMerging.py, ATR-22206")
306 if not HLTMenuConfig.isChainRegistered(chainDict[
'chainName']):
307 log.error(
"Chain %s has not been registered in the menu!", chainDict[
'chainName'])
309 pp = pprint.PrettyPrinter(indent=4, depth=8)
310 log.error(
'The chain dictionary is: %s', pp.pformat(chainDict))
311 raise Exception(
"Please fix the menu or the chain.")
314 log.info(
"[generateAllChainConfigs] general alignment complete, will now align TLA chains")
315 TLABuildingSequences.alignTLASteps(chainConfigs, HLTMenuConfig.dicts())
316 log.info(
"[generateAllChainConfigs] general and TLA alignment complete, will now align PEB chains")
317 EventBuildingSequences.alignEventBuildingSteps(chainConfigs, HLTMenuConfig.dicts())
319 log.info(
"[generateAllChainConfigs] all chain configurations have been generated.")
325 == Returns the list of chain names that are in the menu
329 log.info(f
'Menu name: {flags.Trigger.triggerMenuSetup}')
334 menu_module = importlib.import_module(f
'TriggerMenuMT.HLT.Menu.{self.base_menu_name}')
335 except Exception
as e:
336 log.fatal(f
'Failed to import menu module "{self.base_menu_name}" inferred from menu "{flags.Trigger.triggerMenuSetup}"')
353 for chain
in chainsToCheck:
356 if chain
in [c.name
for c
in self.
chainsInMenu[signame]]:
360 raise RuntimeError(f
'Request to enable/disable chain {chain} that is not in menu')
367 log.warning(
"There seem to be no chains in the menu - please check")
368 elif log.isEnabledFor(logging.DEBUG):
370 log.debug(
"The following chains were found in the menu:")
376 # Assembles the chain configuration and returns a chain object with (name, L1see and list of ChainSteps)
379 from TriggerMenuMT.HLT.Config.Utility.ChainDictTools
import splitInterSignatureChainDict
380 from TriggerMenuMT.HLT.Config.Utility.ComboHypoHandling
import addTopoInfo, comboConfigurator, topoLegIndices, anomdetWPIndices
381 from TriggerMenuMT.HLT.Config.Utility.ChainMerging
import mergeChainDefs
382 from TriggerMenuMT.HLT.CommonSequences
import EventBuildingSequences, TLABuildingSequences
387 if log.isEnabledFor(logging.DEBUG):
389 pp = pprint.PrettyPrinter(indent=4, depth=8)
390 log.debug(
'dictionary is: %s', pp.pformat(chainDicts))
393 listOfChainConfigs = []
394 perSig_lengthOfChainConfigs = []
396 for chainPartDict
in chainDicts:
397 chainPartConfig =
None
398 currentSig = chainPartDict[
'signature']
399 currentAlignGroup =
None
400 if len(chainPartDict[
'chainParts']) == 1:
401 currentAlignGroup = chainPartDict[
'chainParts'][0][
'alignmentGroup']
403 chainName = chainPartDict[
'chainName']
404 log.debug(
'Checking chainDict for chain %s in signature %s, alignment group %s' , chainName, currentSig, currentAlignGroup)
408 log.debug(
"[__generateChainConfigs] Trying to get chain config for %s", currentSig)
414 except AttributeError:
415 log.debug(
"prepareDefaultSignatureFlags not present")
417 except Exception
as e:
418 log.error(f
"Unexpected error invoking prepareDefaultSignatureFlags {e}")
423 if currentSig
in [
'Electron',
'Photon',
'Muon',
'Tau',
'Bphysics'] :
427 if currentSig ==
'Test' and isinstance(chainPartConfig, tuple):
428 chainPartConfig = chainPartConfig[0]
430 log.error(
'[__generateChainConfigs] Problems creating ChainDef for chain %s ', chainName)
431 log.error(
'[__generateChainConfigs] I am in chain part\n %s ', chainPartDict)
432 log.exception(
'[__generateChainConfigs] Full chain dictionary is\n %s ', mainChainDict)
433 raise Exception(
'[__generateChainConfigs] Stopping menu generation. Please investigate the exception shown above.')
435 log.error(
'Chain %s cannot be generated - Signature "%s" not available', chainPartDict[
'chainName'], currentSig)
437 raise Exception(
'Stopping the execution. Please correct the configuration.')
439 log.debug(
"Chain %s \n chain config: %s",chainPartDict[
'chainName'],chainPartConfig)
441 listOfChainConfigs.append(chainPartConfig)
442 log.debug(
"[__generateChainConfigs] adding to the perSig_lengthOfChainConfigs list (%s, %s)",chainPartConfig.nSteps,chainPartConfig.alignmentGroups)
443 perSig_lengthOfChainConfigs.append((chainPartConfig.nSteps,chainPartConfig.alignmentGroups))
448 lengthOfChainConfigs = []
449 for nSteps, aGrps
in perSig_lengthOfChainConfigs:
450 if len(nSteps) != len(aGrps):
451 log.error(
"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))
459 if len(listOfChainConfigs) == 0:
460 raise Exception(
'[__generateChainConfigs] No Chain Configuration found for {0}'.
format(mainChainDict[
'chainName']))
462 if len(listOfChainConfigs)>1:
463 log.debug(
"Merging strategy from dictionary: %s", mainChainDict[
"mergingStrategy"])
464 theChainConfig, perSig_lengthOfChainConfigs =
mergeChainDefs(listOfChainConfigs, mainChainDict, perSig_lengthOfChainConfigs)
465 lengthOfChainConfigs = []
466 for nSteps, aGrps
in perSig_lengthOfChainConfigs:
467 if len(nSteps) != len(aGrps):
468 log.error(
"Post-merged chain part has %s steps and %s alignment groups - these don't match!",nSteps,aGrps)
470 for a,b
in zip(nSteps,aGrps):
471 lengthOfChainConfigs.append((a,b))
473 theChainConfig = listOfChainConfigs[0]
475 for topoID
in range(len(mainChainDict[
'extraComboHypos'])):
476 thetopo = mainChainDict[
'extraComboHypos'][topoID].strip(string.digits).rstrip(topoLegIndices)
479 if "anomdet" in thetopo:
480 thetopo = thetopo.rstrip(anomdetWPIndices)
482 theChainConfig.addTopo((comboConfigurator[thetopo],thetopo))
485 if len(theChainConfig.topoMap) > 0:
486 log.debug(
"Trying to add extra ComboHypoTool for %s",mainChainDict[
'extraComboHypos'])
487 addTopoInfo(theChainConfig,mainChainDict,listOfChainConfigs,lengthOfChainConfigs)
489 log.error(
'[__generateChainConfigs] Problems creating ChainDef for chain %s ', chainName)
490 log.error(
'[__generateChainConfigs] I am in the extraComboHypos section, for %s ', mainChainDict[
'extraComboHypos'])
491 log.exception(
'[__generateChainConfigs] Full chain dictionary is\n %s ', mainChainDict)
492 raise Exception(
'[__generateChainConfigs] Stopping menu generation. Please investigate the exception shown above.')
493 except AttributeError:
494 raise Exception(
'[__generateChainConfigs] Stopping menu generation. Please investigate the exception shown above.')
497 eventBuildType = mainChainDict[
'eventBuildType']
498 TLAEventBuildTypes = (
'PhysicsTLA',
'FTagPEBTLA',
'EgammaPEBTLA',
'DarkJetPEBTLA')
501 if any(ebtype
in eventBuildType
for ebtype
in TLAEventBuildTypes):
502 log.debug(
"Adding TLA Step for chain %s", mainChainDict[
'chainName'])
503 TLABuildingSequences.addTLAStep(flags, theChainConfig, mainChainDict)
504 log.debug(
'Configuring event building sequence %s for chain %s', eventBuildType, mainChainDict[
'chainName'])
505 EventBuildingSequences.addEventBuildingSequence(flags, theChainConfig, eventBuildType, mainChainDict)
506 except TypeError
as ex:
508 raise Exception(
'[__generateChainConfigs] Stopping menu generation for EventBuilding/TLA sequences. Please investigate the exception shown above.')
510 log.debug(
'[__generateChainConfigs] lengthOfChainConfigs %s, ChainConfigs %s ', lengthOfChainConfigs, theChainConfig)
511 return theChainConfig,lengthOfChainConfigs
515 max_steps =
max([len(cc.steps)
for cc
in chainConfigs], default=0)
516 steps_are_empty = [
True for i
in range(0,max_steps)]
518 for cc
in chainConfigs:
519 for istep, the_step
in enumerate(cc.steps):
520 if not the_step.isEmpty:
521 steps_are_empty[istep] =
False
523 emptySteps.append(the_step)
525 log.debug(
"Are there any fully empty steps? %s", steps_are_empty)
526 log.debug(
"The empty step(s) and associated chain(s) are: %s", emptySteps)
527 empty_step_indices = [i
for i,is_empty
in enumerate(steps_are_empty)
if is_empty]
529 if len(empty_step_indices) == 0:
533 getattr(self.
chainFilter,
"disableChains",
False)
or \
534 getattr(self.
chainFilter,
"disabledSignatures",
False)
or \
535 getattr(self.
chainFilter,
"enabledSignatures",
False) )
539 raise Exception(
"[resolveEmptySteps] Please find the reason for this empty step and resolve it / remove it from the menu: %s", emptySteps)
541 log.info(
"Will now delete steps %s (indexed from zero)",empty_step_indices)
543 for cc
in chainConfigs:
546 for istep,step
in enumerate(cc.steps):
547 if istep
not in empty_step_indices:
554 '''Add prescales for disabling items (e.g. MC production)'''
556 menu_name = flags.Trigger.triggerMenuSetup
557 if prescale_set ==
'__auto__':
558 if menu_name.endswith(
'_prescale'):
560 prescale_set = menu_name.removeprefix(f
'{self.base_menu_name}_').removesuffix(
'_prescale')
565 from TriggerMenuMT.HLT.Menu.MenuPrescaleConfig
import menu_prescale_set_gens
566 if prescale_set
not in menu_prescale_set_gens:
567 raise RuntimeError(f
'Unknown menu prescale set for menu {flags.Trigger.triggerMenuSetup}')
569 gen = menu_prescale_set_gens[prescale_set]
571 from TriggerMenuMT.HLT.Config.Utility.MenuPrescaleSet
import AutoPrescaleSetGen
572 gen = AutoPrescaleSetGen()
575 log.info(f
'Generating automatic prescale set: {prescale_set}')
576 ps_set = gen.generate(flags, store=
True)
584 == Main function to generate the L1, L1Topo and HLT menu configs and CA, using the GenerateMenuMT class
588 from TrigConfigSvc.TrigConfigSvcCfg
import generateL1Menu
596 menu.setChainFilter(chains_gen_filter)
597 log.debug(
'Filtering chains: %d', menu.chainFilter
is not None)
600 finalListOfChainConfigs = menu.generateAllChainConfigs(flags)
602 checkNumberOfLegs = [chain.checkNumberOfLegs()
for chain
in finalListOfChainConfigs]
603 if 0
in checkNumberOfLegs:
604 log.error(
'There is a chain with unexpected number of legs. Revisit your configuration')
606 log.info(
'Number of configured chains: %d', len(finalListOfChainConfigs))
608 from TriggerMenuMT.HLT.Config
import MenuComponents
609 if len(MenuComponents._CustomComboHypoAllowed)> _maxAllowedCustomCH:
610 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')
612 menu.generatePrescales(flags)
616 finalListOfChainConfigs = menu.resolveEmptySteps(finalListOfChainConfigs)
617 log.debug(
"finalListOfChainConfig: %s", finalListOfChainConfigs)
621 log.info(
"Making the HLT configuration tree")
622 menuAcc, CFseq_list =
makeHLTTree(flags, finalListOfChainConfigs)
625 from TriggerJobOpts.TriggerConfigFlags
import ROBPrefetching
626 if ROBPrefetching.InitialRoI
in flags.Trigger.ROBPrefetchingOptions:
627 from TrigGenericAlgs.TrigGenericAlgsConfig
import prefetchingInitialRoIConfig
632 log.info(
"Checking the L1HLTConsistency...")
633 from TriggerMenuMT.HLT.Config.Validation.CheckL1HLTConsistency
import checkL1HLTConsistency
636 log.info(
"Checking the Coherent Prescale assignments...")
637 from TriggerMenuMT.HLT.Config.Validation.CheckCPSGroups
import checkCPSGroups
640 log.info(
"Checking that all chains streamed in express have a signature or detctor monGroup")
641 from TriggerMenuMT.HLT.Config.Validation.CheckMonGroups
import checkMonGroups
645 GenerateMenuMT.clear()
646 from TriggerMenuMT.HLT.Config
import MenuComponents
647 MenuComponents._ComboHypoPool.clear()
648 MenuComponents._CustomComboHypoAllowed.clear()
655 Generate appropriate Control Flow Graph wiht all HLT algorithms
657 from TriggerMenuMT.HLT.Config.ControlFlow.HLTCFConfig
import decisionTreeFromChains, sequenceScanner
658 from TriggerJobOpts.TriggerConfig
import collectViewMakers
659 from AthenaConfiguration.ComponentAccumulator
import ComponentAccumulator
660 from AthenaCommon.CFElements
import seqAND
663 steps =
seqAND(
'HLTAllSteps')
664 finalDecisions, CFseq_list, menuAcc =
decisionTreeFromChains(flags, steps, chainConfigs, HLTMenuConfig.dictsList())
665 if log.getEffectiveLevel() <= logging.DEBUG:
666 menuAcc.printConfig()
670 if not successful_scan:
671 raise Exception(
"[makeHLTTree] At least one sequence is expected in more than one step. Check error messages and fix!")
674 for step
in finalDecisions:
675 flatDecisions.extend (step)
678 viewMakerMap = {vm.name:vm
for vm
in viewMakers}
679 for vmname, vm
in viewMakerMap.items():
680 log.debug(f
"[makeHLTTree] {vmname} InputMakerOutputDecisions: {vm.InputMakerOutputDecisions}")
681 if vmname.endswith(
"_probe"):
683 log.debug(f
"Setting InputCachedViews on {vmname} to read decisions from tag leg {vmname[:-6]}: {vm.InputMakerOutputDecisions}")
684 vm.InputCachedViews = viewMakerMap[vmname[:-6]].InputMakerOutputDecisions
686 log.debug(f
"Tag leg does not match probe: '{vmname[:-6]}', will not use cached views")
690 from TriggerMenuMT.HLT.Config.JSON.HLTMenuJSON
import generateJSON
691 generateJSON(flags, HLTMenuConfig.dictsList(), menuAcc.getSequence(
"HLTAllSteps"))
694 from TriggerMenuMT.HLT.Config.JSON.HLTMonitoringJSON
import generateDefaultMonitoringJSON
697 return acc, CFseq_list