Commit a9ef95a1 authored by Frank Winklmeier's avatar Frank Winklmeier
Browse files

Merge branch 'TMMT-Dec2018' into 'master'

ATR-17934: tidy up of menu

See merge request atlas/athena!16740

Former-commit-id: 0f012379
parents 1e5ded5b 3981b586
......@@ -2,7 +2,7 @@
from TriggerMenuMT.HLTMenuConfig.Egamma.ElectronDef import generateChain as generateElectronChain
from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponents import Chain
from TriggerMenuMT.HLTMenuConfig.Menu.MenuUtils import splitChainDict
from TriggerMenuMT.HLTMenuConfig.Menu.ChainDictTools import splitChainDict
#from TriggerMenuMT.HLTMenuConfig.Egamma.ElectronDef import Chain_electron as Chain_electron
......
# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
"""ChainDef is a simple object with state but no behaviour.
It serves to vehical information from trigger slice menu software,
which is often maintained by a slice domain expertto the central
trigger menu code."""
import pprint
pp = pprint.PrettyPrinter(indent=4, depth=8)
class ChainDef:
def __init__(self, chain_name, level, lower_chain_name, chain_counter=-1):
"""chain_name: string. Identifies the chain within the signature
lower_chain_name: string. the name of the chain that will be run
immediately prior to the curent chain. Can be the empty string.
signature list: a list of 2-entry dicionaries. Each dictionary
gives a signature counter which is used by the central trigger
for optimization. The 'normal' values an integer index which
is incremented each time a signature is added. The second
entry is the name of an output trigger element at which the
chain is tested for success or failure. If the chain fails, its
actions are aborted.
sequence list. a 3-element dictionary containing the names of the
input and output trigger elements of the sequence, and a list
of Algorithms (AthenaConfigurables) which are to be run. A chain
may have more than one sequence.
"""
self.chain_name = chain_name
self.level = level
self.lower_chain_name = lower_chain_name
self.chain_counter = chain_counter
self.signatureList = []
self.sequenceList = []
def addSignature(self, signature_counter, listOfTriggerElements):
"""add signature data to the chain"""
self.signatureList.append(
{'signature_counter': signature_counter,
'listOfTriggerElements': listOfTriggerElements})
def insertSignature(self, signature_counter, listOfTriggerElements):
"""insert signature data to the chain"""
#safety: if asked to insert with sig_counter -1, use addSignature
if signature_counter == -1:
addSignature(signature_counter,listOfTriggerElements)
else:
pos_newSeq = -1
for pos, sig in enumerate(self.signatureList):
if sig['signature_counter'] == signature_counter:
pos_newSeq = pos
self.signatureList.insert(pos_newSeq,
{'signature_counter': signature_counter,
'listOfTriggerElements': listOfTriggerElements})
for pos, sig in enumerate(self.signatureList):
if pos <= pos_newSeq: continue
sig['signature_counter'] = sig['signature_counter']+1
def appendSignature(self, listOfTriggerElements):
"""add new signature to the end of the signature list and increment chain counter automatically"""
self.signatureList.append(
{'signature_counter': self.signatureList[-1]["signature_counter"]+1,
'listOfTriggerElements': listOfTriggerElements})
def addSequence(self, listOfAlgorithmInstances, te_in, te_out, topo_start_from=None):
"""add sequence data to the chain"""
self.sequenceList.append(
{'algorithm': listOfAlgorithmInstances,
'input': te_in,
'output': te_out,
'topo_start_from': topo_start_from})
def __str__(self):
"""Provide a string representation of the chain"""
s = ['chain_name: %s ' % self.chain_name,
'lower chain name: %s ' % self.lower_chain_name,
'no signatures %d ' % len(self.signatureList),
'no sequences %d ' % len(self.sequenceList),
'\n',
'sequences:']
s.extend([pp.pformat(ss) for ss in self.sequenceList])
s.extend(['\n',
'signatures:'])
s.extend([pp.pformat(ss) for ss in self.signatureList])
return '\n'.join(s)
class ErrorChainDef(object):
"""Error object. Created when ChainDef creation fails."""
def __init__(self, err_msg, chain_name='unknown'):
self.chain_name = chain_name
self.err_msg = err_msg
def __str__(self):
return '\n'.join(['ErrorChainDef:',
'chain name: ' + self.chain_name,
'err msg: ' + self.err_msg])
def str_no_cr(self):
return str(self).replace('\n', '; ')
# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
# Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
from collections import Counter
from copy import deepcopy
from AthenaCommon.Logging import logging
log = logging.getLogger( 'TriggerMenu.menu.MenuUtils' )
log = logging.getLogger( 'TriggerMenu.menu.ChainDictTools' )
def splitInterSignatureChainDict(chainDict):
......
# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
# Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
"""
......
......@@ -18,8 +18,8 @@ from TriggerMenuMT.HLTMenuConfig.Menu.TriggerConfigHLT import TriggerConfigHLT
from TriggerMenuMT.HLTMenuConfig.Menu.HLTCFConfig import *
from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponents import *
from TriggerMenuMT.HLTMenuConfig.Menu import DictFromChainName
from TriggerMenuMT.HLTMenuConfig.Menu.MenuUtils import splitInterSignatureChainDict
from TriggerMenuMT.HLTMenuConfig.Menu.Lumi import lumi
from TriggerMenuMT.HLTMenuConfig.Menu.ChainDictTools import splitInterSignatureChainDict
from TriggerMenuMT.HLTMenuConfig.Menu.MenuPrescaleConfig import MenuPrescaleConfig
from TriggerMenuMT.HLTMenuConfig.Menu.HLTCFConfig import makeHLTTree
......@@ -189,9 +189,9 @@ class GenerateMenuMT:
def setupMenu(self):
# go over the slices and put together big list of signatures requested
#(L1Prescales, HLTPrescales, streamConfig) = lumi(self.triggerPythonConfig)
#(L1Prescales, HLTPrescales, streamConfig) = MenuPrescaleConfig(self.triggerPythonConfig)
# that does not seem to work
#(self.L1Prescales, self.HLTPrescales) = lumi(self.triggerConfigHLT)
#(self.L1Prescales, self.HLTPrescales) = MenuPrescaleConfig(self.triggerConfigHLT)
#return (self.HLTPrescales)
pass
......
# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
# Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
from AthenaCommon.Logging import logging
log = logging.getLogger( 'TriggerMenu.menu.GroupInfo' )
......
# Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
#-----------------------------------------------------
# Hlt configuration base classes
#-----------------------------------------------------
#from AthenaCommon.Configurable import *
from TriggerJobOpts.TriggerFlags import *
from TriggerMenu.menu.ChainDef import ChainDef
log = logging.getLogger( 'TriggerMenu.menu.HltConfig.py' )
class HltSeq:
def __init__(self, inputTEs, algos, outputTE, topo_start_from=None):
self.inputTEs = inputTEs
if type(inputTEs)==type(''): self.inputTEs = [inputTEs]
self.algos = algos
self.outputTE = outputTE
self.topo_start_from = topo_start_from
class HltChainDef:
"""signatures: dictionary from step
"""
def __init__(self, sig_id,
chain_name, chain_counter,
prescale,
pass_through,
rerun,
):
self.sig_id = "HLT_"+sig_id
self.chain_name = chain_name
self.chain_counter = chain_counter
self.prescale = prescale
self.pass_through = pass_through
self.rerun = rerun
self.signatures = []
self.sequences = []
self.sequencesPerSignature = {}
self.combined_chains = [] # optional
self.defineSequences()
self.defineSignatures()
self.defineCombinedChain()
if len(self.combined_chains)>0: self.mergeCombinedChains()
def getClassName(self):
return self.__class__.__name__
def defineSequences(self):
self.sequences = []
def defineSignatures(self):
self.signatures = []
def defineCombinedChain(self):
self.combined_chains = []
pass
def addSequence(self, inputTEs, algos, outputTE, topo_start_from=None):
self.sequences.append(HltSeq(inputTEs, algos, outputTE, topo_start_from))
def addSignature(self, TElist=[]):
self.signatures.append(TElist)
def mergeCombinedChains(self):
for (i, c) in enumerate(self.combined_chains):
for seq in c.sequences:
seq.inputTEs = map(lambda x: c.renameTE(x), seq.inputTEs)
seq.outputTE = c.renameTE(seq.outputTE)
self.sequences.extend(c.sequences)
n = max(map(lambda x: len(x.signatures), self.combined_chains))
for i in range(1, n+1):
tes = []
for c in self.combined_chains:
if len(c.signatures)>=i:
for te in c.signatures[i-1]:
tes.append(c.renameTE(te))
self.addSignature(tes)
pass
def generateChainDef(self):
chainDef = ChainDef(chain_name=self.chain_name, lower_chain_name=self.lower_chain_name, level=self.level)
log.debug("HltConfig: all sequences %s" % self.sequencesPerSignature)
log.debug("HltConfig: all signatures %s" % self.signatures)
log.debug("HltConfig: self.sequecnes %s" % self.sequences)
for sequence in self.sequences:
chainDef.addSequence(filter(lambda x: x!=None, sequence.algos), map(lambda x: self.renameTE(x), sequence.inputTEs), self.renameTE(sequence.outputTE))
for (isig, sig) in enumerate(self.signatures):
tes = []
for te in sig:
#print "HltConfig te",te
out = self.renameTE(te)
tes.append(out)
if len(tes)>0:
chainDef.addSignature(isig+1+self.signatureCounterOffset,tes) #addHLTSignature(tes, isig+1)
#print "HltConfig : DONE ==================="
return chainDef
# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
import os
import time
import re
import string
from sys import settrace
import xml.etree.cElementTree as etree
from AthenaCommon.Logging import logging # loads logger
def logger():
return logging.getLogger( "TriggerMenu.menu.HLTObjects" )
#########################################################################################
# HLT Chain classes
#
class HLTChain:
""" the HLT Chain definition class """
class HLTSignature:
""" HLT Signature, internal class of HLT Chain """
def __init__(self, telist, sigcounter, logic='1'):
self.sigcounter = sigcounter
if type(telist) != type([]):
self.tes = [ telist ]
else:
self.tes = telist
self.logic = logic
def __eq__(self, other):
if self.tes == other.tes:
return True
return False
def multiplicity(self):
return len(self.tes)
def uniqueTEs(self):
return len(self.tes)
def xml(self, xlist):
if len(self.tes) != 0:
xSignature = etree.SubElement(xlist,'SIGNATURE',
logic='1', signature_counter=str(self.sigcounter))
for te in self.tes:
if type(te) != type(''): # check if this is a string
raise Exception("The trigger element: " + str(te) + " in the signature: " + self.sigcounter + "is not a plain string" )
xTriggerElement = etree.SubElement(xSignature, 'TRIGGERELEMENT', te_name=str(te))
# construction
def __init__(self, chain_name, chain_counter,
lower_chain_name, level, prescale='1', pass_through='0', rerun_prescale='-1',stream_tag=None, groups=None, EBstep="-1"):
self.chain_name = chain_name
self.chain_counter = chain_counter
self.level = level
self.siglist = []
self.prescale = prescale
self.rerun_prescale = rerun_prescale
self.pass_through = pass_through
self.lower_chain_name = lower_chain_name
self.stream_tag = []
if stream_tag is not None: self.stream_tag += stream_tag
self.trigger_type_bits = []
self.groups = []
if groups is not None: self.addGroup(groups)
self.chainBindings = []
self.chains_to_merge = []
self.sigs_n_before_merge = 0
self.EBstep = EBstep
def addHLTSignature(self, telist, sigcounter=None, logic='1'):
if sigcounter is None: # figure out sigcounter if not specified
if len(self.siglist) == 0:
sigcounter = 1
else:
sigcounter = self.siglist[-1].sigcounter+1
else:
if len(self.siglist) != 0:
if sigcounter >= self.siglist[-1].sigcounter:
sigcounter = self.siglist[-1].sigcounter+1
self.siglist.append( HLTChain.HLTSignature(telist, sigcounter, logic) )
return self
def getHLTSignatureOfStep(self, step):
""" Returns signature at given step
If no signature at given step is present then method recursively searches back.
If step 0 is reached and no signature is found then empty one is returned.
"""
for sig in self.siglist:
if sig.sigcounter == step:
return sig
if step == 0:
return HLTChain.HLTSignature([], step)
else:
return self.getHLTSignatureOfStep(step -1)
def mergeAndAppendChains_Order(self, chains_list):
""" Helps definig complex chains made out of other chains.
All chains from the chains_list are scanned and thier signatures are merged and appended to the list of existing signatures.
Note, this is appending one chain to another, e.g. runs first all xe and then egamma, not in parallel
"""
self.chains_to_merge = chains_list
self.sigs_n_before_merge = len(self.siglist)
self.doChainsMerging_Order()
def doChainsMerging_Order(self):
if type(self.chains_to_merge) != type([]):
logger().error( "Not a chains list given to mergeAndAppendChains for chain: "+ self.chain_name+ " it is: "+ str(type(self.chains_to_merge)) )
raise Exception("Incorrect usage of: mergeAndAppendChains_Order")
logger().debug("merging chains seq:"+str([ c.chain_name for c in self.chains_to_merge]))
copysigs = self.siglist
self.siglist = copysigs[0:self.sigs_n_before_merge]
# find out counter of last signature
last_counter = 1
if len(self.siglist) != 0:
last_counter = self.siglist[-1].sigcounter
logger().debug( "The chain: " + self.chain_name + " contains already signatures. Will align sinatures to it." )
total_counter = 0
for chain in self.chains_to_merge:
if len(chain.siglist) != 0:
total_counter += chain.siglist[-1].sigcounter
logger().debug("Total counter in merged chains "+str(total_counter))
else:
logger().debug("Chain: "+ chain.chain_name + " is having empty signature list wil lbe ignored in merging")
del self.chains_to_merge[self.chains_to_merge.index(chain)]
current_counter = 0
for chain in self.chains_to_merge:
if len(chain.siglist) != 0:
for te in [chain.getHLTSignatureOfStep(step).tes for step in range(1,chain.siglist[-1].sigcounter+1)]:
current_counter += 1
self.addHLTSignature(te, sigcounter=current_counter)
# now append all signatures which were added after merging
for sig in copysigs[self.sigs_n_before_merge:]:
current_counter = current_counter+1
self.addHLTSignature(sig.tes, sigcounter=current_counter)
def mergeAndAppendChains(self, chains_list):
""" Helps definig complex chains made out of other chains.
All chains from the chains_list are scanned and thier signatures are merged and appended to the list of existing signatures.
"""
self.chains_to_merge = chains_list
self.sigs_n_before_merge = len(self.siglist)
self.doChainsMerging() # TB this needs to be cut short as we do noeed alignements anymore (TODO remove alignChain(s) etc.)
def doChainsMerging(self):
if type(self.chains_to_merge) != type([]):
logger().error( "Not a chains list given to mergeAndAppendChains for chain: "+ self.chain_name+ " it is: "+ str(type(self.chains_to_merge)) )
raise Exception("Incorrect usage of: mergeAndAppendChains")
logger().debug("merging chains:"+str([ c.chain_name for c in self.chains_to_merge]))
copysigs = self.siglist
self.siglist = copysigs[0:self.sigs_n_before_merge]
# find out counter of last signature
last_counter = 1
if len(self.siglist) != 0:
last_counter = self.siglist[-1].sigcounter
logger().debug( "The chain: " + self.chain_name + " contains already signatures. Will align sinatures to it." )
max_counter = 0;
for chain in self.chains_to_merge:
if len(chain.siglist) != 0:
max_counter = max(chain.siglist[-1].sigcounter, max_counter)
logger().debug("Max counter in merged chains "+str(max_counter))
else:
logger().debug("Chain: "+ chain.chain_name + " is having empty signature list wil lbe ignored in merging")
del self.chains_to_merge[self.chains_to_merge.index(chain)]
# make dictionary with TE sigantures
for i in range(1, max_counter+1):
telist = []
[ telist.extend(x) for x in [chain.getHLTSignatureOfStep(i).tes for chain in self.chains_to_merge]] # repack TEs from other chain signatures
self.addHLTSignature(telist, sigcounter=i)
# now append all signatures which were added after merging
for sig in copysigs[self.sigs_n_before_merge:]:
max_counter = max_counter+1
self.addHLTSignature(sig.tes, sigcounter=max_counter)
def continueOn(self, chain):
self.siglist = chain.siglist
return self
def evaluateSignatureAfter(self, mySig, otherChain, otherChainSig):
""" Adds chain binding. Note that at this point action is only scheduled. Real work is done be alignChain method """
if type(otherChain) == type(''):
self.chainBindings.append( (mySig, otherChain, otherChainSig) )
else:
self.chainBindings.append( (mySig, otherChain.chain_name, otherChainSig) )
# self.alignChain(mySig, otherChain, otherChainSig)
def alignChain(self, mySig, otherChain, otherChainSigName ):
""" Changes internals of this chains and makes sure that selected signatures of other chain are evaluated first """
# check if any binding is required
if len(self.chainBindings) == 0:
return False
# find this chain signature
thisChainSig = filter(lambda x: x.tes == HLTChain.HLTSignature(mySig, 0).tes, self.siglist)
if len(thisChainSig) == 0:
logger().debug( "Chains binding ineffective (1), can't find signature: " + mySig + " in chain " + self.chain_name )
return False
thisChainSig = thisChainSig[0] # unpack it from list
# find sigcounter of the otherChainSig
otherChainSig = filter(lambda x: x.tes == HLTChain.HLTSignature(otherChainSigName, 0).tes, otherChain.siglist)
if len(otherChainSig) == 0:
logger().debug( "Chains binding ineffective (2), can't find signature: " + str(otherChainSigName) + " in chain " + otherChain.chain_name )
return False
otherChainSig = otherChainSig[0]
# fianlly we have both, check if we need to do anything
if thisChainSig.sigcounter > otherChainSig.sigcounter:
logger().debug( "Chains binding ineffective (3), signatures steps already ordered" )
return False
# and real work to be done here
counterShift = otherChainSig.sigcounter - thisChainSig.sigcounter + 1
for i in range (self.siglist.index(thisChainSig), len(self.siglist)):
self.siglist[i].sigcounter = self.siglist[i].sigcounter + counterShift
logger().debug( "Chains binding effective: signature: " + str(self.siglist[i].tes) + " will be shifted to step: "+ str(self.siglist[i].sigcounter) )
# true means that there was something to do
return True
def getOutputTEs(self):
tes = []
for sig in self.siglist:
tes.extend(sig.tes)
return tes
def isL2(self):
if self.level == "L2":
return True
else:
return False
def isEF(self):
if self.level == "EF":
return True
else:
return False
def isHLT(self):
if self.level == "HLT":
return True
else:
return False
def addTriggerTypeBit(self, bit):
self.trigger_type_bits.append(bit)
def addStreamTag(self, stream, type="physics", obeyLB="yes", prescale='1'):
self.stream_tag.append( (stream, type, obeyLB, prescale) )
def addGroup(self, name ):
if type(name) == type(''):
self.groups += [name]
if type(name) == type([]):
self.groups += name
def xml(self, xChainList):
""" Returns XML representation of this chain """