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