ATLAS Offline Software
HLTCFComponents.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2 
3 from TriggerMenuMT.HLT.Config.MenuComponents import AlgNode, HypoAlgNode
4 from TriggerMenuMT.HLT.Config.ControlFlow.MenuComponentsNaming import CFNaming
5 from TriggerMenuMT.HLT.Config.Utility.HLTMenuConfig import HLTMenuConfig
6 from TriggerMenuMT.HLT.Config.ControlFlow.HLTCFTools import isComboHypoAlg
7 from TriggerMenuMT.HLT.Config.MenuComponents import EmptyMenuSequence
8 from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
9 from AthenaConfiguration.ComponentFactory import CompFactory
10 from AthenaCommon.CFElements import findAlgorithmByPredicate, parOR, seqAND
11 from functools import lru_cache
12 
13 from AthenaCommon.Logging import logging
14 log = logging.getLogger( __name__ )
15 
16 RoRSeqFilter = CompFactory.RoRSeqFilter
17 PassFilter = CompFactory.PassFilter
18 
19 
20 class SequenceFilterNode(AlgNode):
21  """Node for any kind of sequence filter"""
22  def __init__(self, Alg, inputProp, outputProp):
23  AlgNode.__init__(self, Alg, inputProp, outputProp)
24 
25  def addChain(self, name, input_name):
26  return
27 
28  def getChains(self):
29  return []
30 
31  def getChainsPerInput(self):
32  return [[]]
33 
34  def __repr__(self):
35  return "SequenceFilter::%s [%s] -> [%s], chains=%s"%(self.Alg.name,' '.join(map(str, self.getInputList())),' '.join(map(str, self.getOutputList())), self.getChains())
36 
37 
39  def __init__(self, name):
40  Alg= RoRSeqFilter(name)
41  SequenceFilterNode.__init__(self, Alg, 'Input', 'Output')
42 
43  def addChain(self, name, input_name):
44  input_index = self.readInputList().index(input_name)
45  if len(self.Alg.ChainsPerInput) == input_index:
46  self.Alg.ChainsPerInput.append([name])
47  elif len(self.Alg.ChainsPerInput) > input_index:
48  self.Alg.ChainsPerInput[input_index].append(name)
49  else:
50  log.error("Error: why requiring input %i when size is %i ?" , input_index , len(self.Alg.ChainsPerInput))
51  raise RuntimeError("Error: why requiring input %i when size is %i " , input_index , len(self.Alg.ChainsPerInput))
52 
53  return self.Alg.Chains.append(name) # still neded?
54 
55  def getChains(self):
56  return self.Alg.Chains
57 
58  def getChainsPerInput(self):
59  return self.Alg.ChainsPerInput
60 
61 
62 
64  """ PassFilter is a Filter node without inputs/outputs, so OutputProp=InputProp=empty"""
65  def __init__(self, name):
66  Alg=CompFactory.AthSequencer( "PassSequence" )
67  Alg.IgnoreFilterPassed=True # always pass
68  SequenceFilterNode.__init__(self, Alg, '', '')
69 
70  def addOutput(self, name):
71  self.outputs.append(str(name))
72 
73  def addInput(self, name):
74  self.inputs.append(str(name))
75 
76  def getOutputList(self):
77  return self.outputs
78 
79  def getInputList(self):
80  return self.inputs
81 
82 def isPassSequence(alg):
83  return isinstance(alg, PassFilterNode)
84 
85 
89  """Class to describe the flow of decisions through ChainStep + filter with their connections (input, output)
90  A Filter can have more than one input/output if used in different chains, so this class stores and manages all of them (when doing the connect)
91  """
92  def __init__(self, ChainStep, FilterAlg):
93  log.debug(" *** Create CFSequence %s with Filter %s", ChainStep.name, FilterAlg.Alg.getName())
94  self.filterNode = FilterAlg
95  self.step = ChainStep
96 
98  #empty step: add the PassSequence, one instance only is appended to the tree
99  seqAndWithFilter = FilterAlg.Alg if ChainStep.isEmpty else seqAND(ChainStep.name)
100  self.ca.addSequence(seqAndWithFilter)
101  self.seq = seqAndWithFilter
102  if not ChainStep.isEmpty:
103  self.ca.addEventAlgo(FilterAlg.Alg, sequenceName=seqAndWithFilter.getName())
104  self.stepReco = parOR(ChainStep.name + CFNaming.RECO_POSTFIX)
105  # all reco algorithms from all the sequences in a parallel sequence
106  self.ca.addSequence(self.stepReco, parentName=seqAndWithFilter.getName())
107  log.debug("created parOR %s inside seqAND %s ", self.stepReco.getName(), seqAndWithFilter.getName())
108  self.mergeStepSequences(ChainStep)
109  # merge the Hypoalg (before the Combo)
110  for menuseq in ChainStep.sequences:
111  if not isinstance(menuseq, EmptyMenuSequence):
112  self.ca.merge(menuseq.hypoAcc, sequenceName=seqAndWithFilter.getName())
113 
114  self.connectCombo()
115  self.setDecisions()
116  if self.step.combo is not None:
117  self.ca.merge(self.step.combo.acc, sequenceName=seqAndWithFilter.getName())
118  log.debug("CFSequence.__init: created %s ",self)
119 
120 
121  def setDecisions(self):
122  """ Set the output decision of this CFSequence as the hypo outputdecision; In case of combo, takes the Combo outputs"""
123  self.decisions=[]
124  # empty steps:
125  if self.step.combo is None:
126  self.decisions.extend(self.filterNode.getOutputList())
127  else:
128  self.decisions.extend(self.step.combo.getOutputList())
129  log.debug("CFSequence: set out decisions: %s", self.decisions)
130 
131 
132  def connectCombo(self):
133  """ connect Combo to Hypos"""
134  if self.step.combo is None:
135  log.debug("CFSequence.connectCombo: no Combo found")
136  return
137 
138  for seq in self.step.sequences:
139  combo_input=seq.getOutputList()[0]
140  self.step.combo.addInput(combo_input)
141  inputs = self.step.combo.readInputList()
142  legindex = inputs.index(combo_input)
143  log.debug("CFSequence.connectCombo: adding input to %s: %s", self.step.combo.Alg.getName(), combo_input)
144  # inputs are the output decisions of the hypos of the sequences
145  combo_output=CFNaming.comboHypoOutputName (self.step.combo.Alg.getName(), legindex)
146  self.step.combo.addOutput(combo_output)
147  log.debug("CFSequence.connectCombo: adding output to %s: %s", self.step.combo.Alg.getName(), combo_output)
148 
149  def mergeStepSequences(self, chainStep):
150  for menuseq in chainStep.sequences:
151  try:
152  self.ca.merge(menuseq.ca, sequenceName=self.stepReco.getName())
153  except Exception as e:
154  log.error(f'Failed to merge into {self.stepReco.getName()}')
155  raise e
156 
157  @lru_cache(None)
158  def findComboHypoAlg(self):
159  return findAlgorithmByPredicate(self.seq, lambda alg: alg.name == self.step.Alg.name and isComboHypoAlg(alg))
160 
161  def __repr__(self):
162  return "--- CFSequence ---\n + Filter: %s \n + decisions: %s\n + %s \n"%(\
163  self.filterNode.Alg.name, self.decisions, self.step)
164 
165 
166 
167 
169  """Class to store the Step + its Filter (CFSequence) plus the chains and dictionaries of the legs using that step """
170  def __init__(self, ChainStep, FilterAlg):
171  self.stepDicts = [] # will become a list of lists
172  self.chains = []
173  self.comboToolConfs = []
174  self.createCFSequence(ChainStep, FilterAlg)
175  log.debug("CFGroup.__init: created for %s ",ChainStep.name)
176 
177  def createCFSequence(self, ChainStep, FilterAlg):
178  '''This creates the CAs for the menu sequences, if fastMenu style, and the CFSequence'''
179  log.debug("CFGroup.creating CFSEquence")
180  self.sequenceCA = CFSequence(ChainStep, FilterAlg)
181  return self.sequenceCA
182 
183  def addStepLeg(self, newstep, chainName):
184  self.stepDicts.append(newstep.stepDicts) # one dict per leg
185  self.chains.append(chainName)
186  self.comboToolConfs.append(newstep.comboToolConfs)
187 
188 
189  def connect(self, connections):
190  """Connect filter to ChainStep (and all its sequences) through these connections (which are sets of filter outputs)
191  if a ChainStep contains the same sequence multiple times (for multi-leg chains),
192  the filter is connected only once (to avoid multiple DH links)
193  """
194  if log.isEnabledFor(logging.DEBUG):
195  log.debug("CFGroup: connect Filter %s with %d menuSequences of step %s, using %d connections", self.sequenceCA.filterNode.Alg.name, len(self.sequenceCA.step.sequences), self.sequenceCA.step.name, len(connections))
196  log.debug(" --- sequences: ")
197  for seq in self.sequenceCA.step.sequences:
198  log.debug(seq)
199 
200  if len(connections) == 0:
201  log.error("No filter outputs are set!")
202 
203  if len(self.sequenceCA.step.sequences):
204  # check whether the number of filter outputs are the same as the number of sequences in the step
205  if len(connections) != len(self.sequenceCA.step.sequences):
206  log.error("CFGroup: Found %d connections and %d MenuSequences in Step %s", len(connections), len(self.sequenceCA.step.sequences), self.sequenceCA.step.name)
207  raise Exception("[CFGroup] Connections and sequences do not match, this must be fixed!")
208 
209  for nseq, seq in enumerate(self.sequenceCA.step.sequences):
210  filter_out = connections[nseq]
211  log.debug("CFGroup: Found input %s to sequence::%s from Filter::%s", filter_out, seq.name, self.sequenceCA.filterNode.Alg.name)
212  seq.connectToFilter( filter_out )
213  else:
214  log.debug("This CFGroup has no sequences: outputs are the Filter outputs, which are %d", len(self.sequenceCA.decisions))
215 
216  def createHypoTools(self, flags):
217  """ set and create HypoTools accumulated on the self.step from an input step configuration
218  """
219  if self.sequenceCA.step.combo is None:
220  return
221 
222  log.debug("CFGroup.createHypoTools for Step %s", self.sequenceCA.step.name)
223  for sdict in self.stepDicts:
224  for seq, onePartChainDict in zip(self.sequenceCA.step.sequences, sdict):
225  log.debug(' seq: %s, onePartChainDict:', seq.name)
226  log.debug(' %s', onePartChainDict)
227  if not isinstance(seq, EmptyMenuSequence):
228  hypoToolConf=seq.getHypoToolConf()
229  if hypoToolConf is None: # avoid empty sequences
230  log.error("HypoToolConf not found ", seq.name)
231  hypoToolConf.setConf( onePartChainDict )
232  hypo = HypoAlgNode(Alg = self.sequenceCA.ca.getEventAlgo(seq.hypo.Alg.getName()))
233  hypoToolAcc = hypo.addHypoTool(flags, hypoToolConf) #this creates the HypoTools
234  if isinstance(hypoToolAcc, ComponentAccumulator):
235  self.sequenceCA.ca.merge(hypoToolAcc)
236 
237  for chain,conf in zip(self.chains, self.comboToolConfs):
238  chainDict = HLTMenuConfig.getChainDictFromChainName(chain)
239  self.sequenceCA.step.combo.createComboHypoTools(flags, chainDict, conf)
HLTCFComponents.CFSequence.__init__
def __init__(self, ChainStep, FilterAlg)
Definition: HLTCFComponents.py:92
HLTCFComponents.CFGroup.addStepLeg
def addStepLeg(self, newstep, chainName)
Definition: HLTCFComponents.py:183
RoRSeqFilter
Definition: RoRSeqFilter.h:49
HLTCFComponents.CFSequence
CFSequence class.
Definition: HLTCFComponents.py:88
HLTCFComponents.CFSequence.ca
ca
Definition: HLTCFComponents.py:97
python.JetAnalysisCommon.ComponentAccumulator
ComponentAccumulator
Definition: JetAnalysisCommon.py:302
HLTCFComponents.RoRSequenceFilterNode.getChains
def getChains(self)
Definition: HLTCFComponents.py:55
HLTCFComponents.CFGroup.createCFSequence
def createCFSequence(self, ChainStep, FilterAlg)
Definition: HLTCFComponents.py:177
index
Definition: index.py:1
HLTCFComponents.CFGroup.stepDicts
stepDicts
Definition: HLTCFComponents.py:171
python.CFElements.findAlgorithmByPredicate
def findAlgorithmByPredicate(startSequence, predicate, depth=1000000)
Definition: CFElements.py:102
HLTCFComponents.CFGroup
Definition: HLTCFComponents.py:168
HLTCFComponents.CFGroup.__init__
def __init__(self, ChainStep, FilterAlg)
Definition: HLTCFComponents.py:170
HLTCFComponents.CFSequence.connectCombo
def connectCombo(self)
Definition: HLTCFComponents.py:132
HLTCFComponents.PassFilterNode
Definition: HLTCFComponents.py:63
HLTCFComponents.CFGroup.chains
chains
Definition: HLTCFComponents.py:172
HLTCFComponents.CFSequence.seq
seq
Definition: HLTCFComponents.py:101
HLTCFComponents.CFSequence.step
step
Definition: HLTCFComponents.py:95
HLTCFComponents.PassFilterNode.getOutputList
def getOutputList(self)
Definition: HLTCFComponents.py:76
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
HLTCFComponents.PassFilterNode.addOutput
def addOutput(self, name)
Definition: HLTCFComponents.py:70
HLTCFComponents.PassFilterNode.__init__
def __init__(self, name)
Definition: HLTCFComponents.py:65
HLTCFComponents.isPassSequence
def isPassSequence(alg)
Definition: HLTCFComponents.py:82
dumpTruth.getName
getName
Definition: dumpTruth.py:34
HLTCFComponents.RoRSequenceFilterNode.getChainsPerInput
def getChainsPerInput(self)
Definition: HLTCFComponents.py:58
HLTCFComponents.CFSequence.filterNode
filterNode
Definition: HLTCFComponents.py:94
HLTCFComponents.CFSequence.findComboHypoAlg
def findComboHypoAlg(self)
Definition: HLTCFComponents.py:158
HLTCFComponents.PassFilterNode.getInputList
def getInputList(self)
Definition: HLTCFComponents.py:79
python.CFElements.seqAND
def seqAND(name, subs=[])
Definition: CFElements.py:25
HLTCFComponents.RoRSequenceFilterNode.__init__
def __init__(self, name)
Definition: HLTCFComponents.py:39
python.JetAnalysisCommon.parOR
parOR
Definition: JetAnalysisCommon.py:271
HLTCFComponents.CFSequence.mergeStepSequences
def mergeStepSequences(self, chainStep)
Definition: HLTCFComponents.py:149
HLTCFComponents.PassFilterNode.addInput
def addInput(self, name)
Definition: HLTCFComponents.py:73
HLTCFComponents.CFSequence.stepReco
stepReco
Definition: HLTCFComponents.py:104
HLTCFComponents.CFGroup.comboToolConfs
comboToolConfs
Definition: HLTCFComponents.py:173
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
HLTCFComponents.CFSequence.setDecisions
def setDecisions(self)
Definition: HLTCFComponents.py:121
HLTCFComponents.RoRSequenceFilterNode
Definition: HLTCFComponents.py:38
HLTCFComponents.CFGroup.createHypoTools
def createHypoTools(self, flags)
Definition: HLTCFComponents.py:216
ActsTrk::detail::MakeDerivedVariant::extend
constexpr std::variant< Args..., T > extend(const std::variant< Args... > &, const T &)
Definition: MakeDerivedVariant.h:17
HLTCFComponents.SequenceFilterNode.addChain
def addChain(self, name, input_name)
Definition: HLTCFComponents.py:25
HLTCFComponents.SequenceFilterNode.getChains
def getChains(self)
Definition: HLTCFComponents.py:28
HLTCFComponents.SequenceFilterNode.__repr__
def __repr__(self)
Definition: HLTCFComponents.py:34
HLTCFComponents.SequenceFilterNode.__init__
def __init__(self, Alg, inputProp, outputProp)
Definition: HLTCFComponents.py:22
pickleTool.object
object
Definition: pickleTool.py:29
str
Definition: BTagTrackIpAccessor.cxx:11
HLTCFComponents.CFSequence.__repr__
def __repr__(self)
Definition: HLTCFComponents.py:161
HLTCFComponents.SequenceFilterNode.getChainsPerInput
def getChainsPerInput(self)
Definition: HLTCFComponents.py:31
HLTCFComponents.CFSequence.decisions
decisions
Definition: HLTCFComponents.py:123
HLTCFComponents.CFGroup.connect
def connect(self, connections)
Definition: HLTCFComponents.py:189
HLTCFComponents.RoRSequenceFilterNode.addChain
def addChain(self, name, input_name)
Definition: HLTCFComponents.py:43
HLTCFComponents.SequenceFilterNode
Definition: HLTCFComponents.py:20
HLTCFComponents.CFGroup.sequenceCA
sequenceCA
Definition: HLTCFComponents.py:180
HLTCFTools.isComboHypoAlg
def isComboHypoAlg(alg)
Definition: HLTCFTools.py:49
merge
Definition: merge.py:1