ATLAS Offline Software
HLTMenuJSON.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 
3 import re
4 import json
5 from functools import cache
6 from TrigConfigSvc.TrigConfigSvcCfg import getHLTMenuFileName
7 from AthenaCommon.CFElements import getSequenceChildren
8 from AthenaCommon.Logging import logging
9 __log = logging.getLogger( __name__ )
10 
11 # remove prescale suffixes
12 def __getMenuBaseName(menuName):
13  pattern = re.compile(r'_v\d+|DC14')
14  patternPos = pattern.search(menuName)
15  if patternPos:
16  menuName=menuName[:patternPos.end()]
17  else:
18  __log.info('Can\'t find pattern to shorten menu name, either non-existent in name or not implemented.')
19  return menuName
20 
22  """ Generates a list where the index corresponds to a Step number and the stored object is a list of Sequencers making up the Step
23  """
24  stepsData = []
25  if HLTAllSteps is not None:
26  for HLTStep in HLTAllSteps.Members:
27  if "_reco" not in HLTStep.getName(): # Avoid the pre-step Filter execution
28  for Step in getSequenceChildren( HLTStep ):
29  for View in getSequenceChildren( Step ):
30  for Reco in getSequenceChildren( View ):
31  if "_reco" in Reco.getName() and HLTStep.getName() not in stepsData:
32  stepsData.append( HLTStep.Members )
33  break
34  continue
35 
36  stepsData.append( HLTStep.Members )
37  else:
38  __log.warn( "No HLTAllSteps sequencer, will not export per-Step data for chains.")
39  return stepsData
40 
41 @cache # called frequently
42 def __getFilterChains(filterAlg):
43  if hasattr(filterAlg, "Chains"):
44  # Format: leg000_CHAIN or CHAIN
45  return set(ch[7:] if ch.startswith('leg') else ch for ch in filterAlg.Chains)
46  else:
47  return set()
48 
49 def __getChainSequencers(stepsData, chainName):
50  """ Finds the Filter which is responsible for this Chain in each Step.
51  Return a list of the per-Step name() of the Sequencer which is unlocked by the Chain's Filter in the Step.
52  """
53  sequencers = []
54  for counter, step in enumerate(stepsData, 1):
55  mySequencer = None
56  for sequencer in step:
57  try:
58  sequencerFilter = sequencer.Members[0] # Always the first child in the step
59  except (AttributeError, IndexError):
60  continue # empty steps
61  if chainName in __getFilterChains(sequencerFilter):
62  if mySequencer is not None:
63  __log.error( "Multiple Filters found (corresponding Sequencers %s, %s) for %s in Step %i!",
64  mySequencer.getName(), sequencer.getName(), chainName, counter)
65  mySequencer = sequencer
66 
67  sequencers.append(mySequencer.getName() if mySequencer else "")
68  # drop trailing empty names
69  while len(sequencers) != 0 and sequencers[-1] == "":
70  del sequencers[-1]
71  return sequencers
72 
73 def __getSequencerAlgs(stepsData):
74  """ For each Sequencer in each Step, return a flat list of the full name of all Algorithms under the Sequencer
75  """
76  from AthenaCommon.CFElements import findAllAlgorithms
77  sequencerAlgs = {}
78  for step in stepsData:
79  for sequencer in step:
80  sequencerAlgs[ sequencer.getName() ] = list(map(lambda x: x.getFullJobOptName(), findAllAlgorithms(sequencer)))
81  return sorted(sequencerAlgs.items(), key=lambda t: t[0])
82 
83 def generateJSON(flags, chainDicts, HLTAllSteps):
84  """ Generates JSON given the ChainProps and sequences
85  """
86  # Menu dictionary that is used to create the JSON content
87  menuDict = {"filetype": "hltmenu",
88  "name": __getMenuBaseName(flags.Trigger.triggerMenuSetup),
89  "chains": {},
90  "streams": {},
91  "sequencers": {}}
92 
93  # List of steps data for sequencers
94  stepsData = __getStepsDataFromAlgSequence(HLTAllSteps)
95  from TriggerMenuMT.HLT.Menu import StreamInfo
96  for chain in chainDicts:
97  # Prepare information for stream list and fill separate dictionary
98  chainStreamTags = []
99  for streamName in chain["stream"]:
100  streamTag = StreamInfo.getStreamTag(streamName)
101  # Stream needs to have been defined in StreamInfo.py otherwise is not added to JSON
102  if streamTag is None:
103  __log.error('Stream %s does not have StreamTags defined excluding from JSON', streamName)
104  continue
105  # Add stream to the chain
106  chainStreamTags.append(streamName)
107  # If not already listed, add stream details to stream dictionary
108  if streamName not in menuDict["streams"]:
109  menuDict["streams"][streamName] = {
110  "name": streamName,
111  "type": streamTag.type(),
112  "obeyLB": streamTag.obeysLumiBlock(),
113  "forceFullEventBuilding": streamTag.forceFullEventBuilding()
114  }
115 
116  # Find L1 Threshold information for current chain
117  l1Thresholds = []
118 
119  [ l1Thresholds.append(p['L1threshold']) for p in chain['chainParts'] ]
120 
121  # Now have all information to write the chain to the menu dictionary
122  chainName = chain["chainName"]
123  menuDict["chains"][chainName] = {
124  "counter": chain["chainCounter"],
125  "nameHash": chain["chainNameHash"],
126  "legMultiplicities": chain["chainMultiplicities"],
127  "l1item": chain["L1item"],
128  "l1thresholds": l1Thresholds,
129  "groups": chain["groups"],
130  "streams": chainStreamTags,
131  "sequencers": __getChainSequencers(stepsData, chainName)
132  }
133 
134  # All algorithms executed by a given Sequencer
135  menuDict["sequencers"].update( __getSequencerAlgs(stepsData) )
136 
137  __validateJSON(menuDict)
138 
139  # Menu dictionary now completed, write to JSON
140  fileName = getHLTMenuFileName( flags)
141  __log.info( "Writing HLT Menu JSON to %s", fileName )
142  with open( fileName, 'w' ) as fp:
143  json.dump( menuDict, fp, indent=4, sort_keys=False )
144 
145 
146 def __validateJSON(menuDict):
147  """ Runs some validation checks which may pick up on issues with the menu
148  """
149  pass
150  #__validateGlobalAlgs(menuDict) # To be enabled once the current offenders are fixed
151 
152 def __validateGlobalAlgs(menuDict):
153  """ Check that global algs only go into one Step
154  """
155  algToStep = {}
156  import re
157  inError = False
158  for seqName, seqeuncer in menuDict["sequencers"].items():
159  stepNumber = int(re.search(r'\d+', seqName).group()) # Obtain first number from string
160  fullEventMode = False
161  for alg in seqeuncer:
162  if "EventViewCreatorAlgorithm" in alg:
163  fullEventMode = False
164  elif "InputMakerForRoI" in alg:
165  fullEventMode = True
166  if not fullEventMode:
167  continue
168  if alg in algToStep and algToStep[alg] != stepNumber:
169  __log.error("{} is a full-event context alg, it should only be running in one Step, however it is in both Steps {} and {}".format(alg, stepNumber, algToStep[alg]))
170  inError = True
171  else:
172  algToStep[alg] = stepNumber
173  if inError:
174  raise Exception("[validateJSON] Problems detected in validateGlobalAlgs().")
python.TrigConfigSvcCfg.getHLTMenuFileName
def getHLTMenuFileName(flags)
Definition: TrigConfigSvcCfg.py:140
python.CFElements.findAllAlgorithms
def findAllAlgorithms(sequence, nameToLookFor=None)
Definition: CFElements.py:153
HLTMenuJSON.__getStepsDataFromAlgSequence
def __getStepsDataFromAlgSequence(HLTAllSteps)
Definition: HLTMenuJSON.py:21
vtune_athena.format
format
Definition: vtune_athena.py:14
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
HLTMenuJSON.__getChainSequencers
def __getChainSequencers(stepsData, chainName)
Definition: HLTMenuJSON.py:49
HLTMenuJSON.__getFilterChains
def __getFilterChains(filterAlg)
Definition: HLTMenuJSON.py:42
HLTMenuJSON.__validateGlobalAlgs
def __validateGlobalAlgs(menuDict)
Definition: HLTMenuJSON.py:152
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
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
HLTMenuJSON.__getSequencerAlgs
def __getSequencerAlgs(stepsData)
Definition: HLTMenuJSON.py:73
HLTMenuJSON.__validateJSON
def __validateJSON(menuDict)
Definition: HLTMenuJSON.py:146
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:79
Trk::open
@ open
Definition: BinningType.h:40
CaloLCW_tf.group
group
Definition: CaloLCW_tf.py:28
HLTMenuJSON.__getMenuBaseName
def __getMenuBaseName(menuName)
Definition: HLTMenuJSON.py:12
HLTMenuJSON.generateJSON
def generateJSON(flags, chainDicts, HLTAllSteps)
Definition: HLTMenuJSON.py:83
python.CFElements.getSequenceChildren
def getSequenceChildren(comp)
Definition: CFElements.py:44
WriteBchToCool.update
update
Definition: WriteBchToCool.py:67