3 from TriggerMenuMT.HLT.Config.Utility.HLTMenuConfig
import HLTMenuConfig
4 from TriggerMenuMT.HLT.Config.ControlFlow.MenuComponentsNaming
import CFNaming
5 from TriggerMenuMT.HLT.Config.ControlFlow.HLTCFTools
import (NoHypoToolCreated,
9 from AthenaCommon.CFElements
import parOR, seqAND, findAlgorithmByPredicate
10 from AthenaConfiguration.ComponentAccumulator
import ComponentAccumulator
11 from AthenaConfiguration.ComponentFactory
import CompFactory
12 from DecisionHandling.DecisionHandlingConfig
import ComboHypoCfg
13 from TriggerJobOpts.TriggerConfigFlags
import ROBPrefetching
15 from collections.abc
import MutableSequence
20 from AthenaCommon.Logging
import logging
21 log = logging.getLogger( __name__ )
23 _ComboHypoPool = dict()
24 _CustomComboHypoAllowed =
set()
27 """base class representing one Alg + inputs + outputs, to be used to connect """
28 """stores all the inputs, even if repeated (self.inputs)"""
30 self.
name = (
"%sNode")%( Alg.getName() )
52 """Node class that represent an algorithm: sets R/W handles (as unique input/output) and properties as parameters """
53 """Automatically de-duplicates input ReadHandles upon repeated calls to addInput."""
54 def __init__(self, Alg, inputProp, outputProp):
55 Node.__init__(self, Alg)
60 cval = getattr( self.
Alg, propname)
61 if isinstance(cval, MutableSequence):
63 return setattr(self.
Alg, propname, cval)
65 return setattr(self.
Alg, propname, value)
70 log.debug(
"Output DH not added in %s: %s already set!", self.
Alg.
getName(), name)
75 log.debug(
"no outputProp set for output of %s", self.
Alg.
getName())
76 Node.addOutput(self, name)
80 return (cval
if isinstance(cval, MutableSequence)
else
81 ([
str(cval)]
if cval
else []))
86 log.debug(
"Input DH not added in %s: %s already set!", self.
Alg.
getName(), name)
91 log.debug(
"no InputProp set for input of %s", self.
Alg.
getName())
92 Node.addInput(self, name)
97 return (cval
if isinstance(cval, MutableSequence)
else
98 ([
str(cval)]
if cval
else []))
105 """ Class to group info on hypotools for ChainDict"""
111 if type(chainDict)
is not dict:
112 raise RuntimeError(
"Configuring hypo with %s, not good anymore, use chainDict" %
str(chainDict) )
116 """creates instance of the hypo tool"""
120 """sets the configuration and creates instance of the hypo tool"""
126 """AlgNode for HypoAlgs"""
127 initialOutput=
'StoreGateSvc+UNSPECIFIED_OUTPUT'
129 assert isHypoBase(Alg),
"Error in creating HypoAlgNode from Alg " + Alg.name
130 AlgNode.__init__(self, Alg,
'HypoInputDecisions',
'HypoOutputDecisions')
136 log.debug(
"Output DH not added in %s: %s already set!", self.
name, name)
138 AlgNode.addOutput(self, name)
140 log.error(
"Hypo %s has already %s as configured output: you may want to duplicate the Hypo!",
141 self.
name, outputs[0])
144 log.debug(
"Adding HypoTool %s for chain %s to %s", hypoToolConf.name, hypoToolConf.chainDict[
'chainName'], self.
Alg.
getName())
146 result = hypoToolConf.create(flags)
147 if isinstance(result, ComponentAccumulator):
148 tool = result.popPrivateTools()
149 assert not isinstance(tool, list),
"Can not handle list of tools"
150 self.
Alg.HypoTools.append(tool)
153 self.
Alg.HypoTools = self.
Alg.HypoTools + [result]
155 except NoHypoToolCreated
as e:
156 log.debug(
"%s returned empty tool: %s", hypoToolConf.name, e)
164 return "HypoAlg::%s [%s] -> [%s], previous = [%s], HypoTools=[%s]" % \
168 ' '.
join([t.getName()
for t
in self.
Alg.HypoTools]))
172 """AlgNode for InputMaker Algs"""
174 assert isInputMakerBase(Alg),
"Error in creating InputMakerNode from Alg " + Alg.name
175 AlgNode.__init__(self, Alg,
'InputMakerInputDecisions',
'InputMakerOutputDecisions')
176 input_maker_output = CFNaming.inputMakerOutName(self.
Alg.name)
181 """AlgNode for Combo HypoAlgs"""
185 thealgs= self.
acc.getEventAlgos()
187 log.error(
"ComboHypoNode: Combo alg %s not found", name)
188 if len(thealgs) != 1:
189 log.error(
"ComboHypoNode: Combo alg %s len is %d",name, len(thealgs))
192 log.debug(
"ComboHypoNode init: Alg %s", name)
193 AlgNode.__init__(self, Alg,
'HypoInputDecisions',
'HypoOutputDecisions')
199 log.debug(
"ComboHypoNode.create %s",name)
203 AlgNode automatically de-duplicates input ReadHandles upon repeated calls to addInput.
204 Node instead stores all the inputs, even if repeated (self.inputs)
205 This function maps from the raw number of times that addInput was called to the de-duplicated index of the handle.
206 E.g. a step processing chains such as HLT_e5_mu6 would return [0,1]
207 E.g. a step processing chains such as HLT_e5_e6 would return [0,0]
208 E.g. a step processing chains such as HLT_e5_mu6_mu7 would return [0,1,1]
209 These data are needed to configure the step's ComboHypo
214 for rawInput
in self.
inputs:
215 mapping.append( theInputs.index(rawInput) )
220 chainName = chainDict[
'chainName']
221 chainMult = chainDict[
'chainMultiplicities']
223 if len(chainMult) != len(legsToInputCollections):
224 log.error(
"ComboHypoNode for Alg:{} with addChain for:{} Chain multiplicity:{} Per leg input collection index:{}."
225 .
format(self.
Alg.name, chainName, tuple(chainMult), tuple(legsToInputCollections)))
226 log.error(
"The size of the multiplicies vector must be the same size as the per leg input collection vector.")
227 log.error(
"The ComboHypo needs to know which input DecisionContainers contain the DecisionObjects to be used for each leg.")
228 log.error(
"Check why ComboHypoNode.addInput(...) was not called exactly once per leg.")
229 raise Exception(
"[createDataFlow] Error in ComboHypoNode.addChain. Cannot proceed.")
231 if chainName
in self.
Alg.MultiplicitiesMap:
232 log.error(
"ComboAlg %s has already been configured for chain %s", self.
Alg.name, chainName)
233 raise Exception(
"[createDataFlow] Error in ComboHypoNode.addChain. Cannot proceed.")
235 self.
Alg.MultiplicitiesMap[chainName] = chainMult
236 self.
Alg.LegToInputCollectionMap[chainName] = legsToInputCollections
240 return self.
Alg.MultiplicitiesMap.keys()
244 """Create the ComboHypoTools and add them to the main alg"""
245 if not len(comboToolConfs):
247 confs = [
HypoToolConf( tool )
for tool
in comboToolConfs ]
248 log.debug(
"ComboHypoNode.createComboHypoTools for chain %s, Alg %s with %d tools", chainDict[
"chainName"],self.
Alg.
getName(), len(comboToolConfs))
250 log.debug(
"ComboHypoNode.createComboHypoTools adding %s", conf)
251 tools = self.
Alg.ComboHypoTools
252 self.
Alg.ComboHypoTools = tools + [ conf.confAndCreate( flags, chainDict ) ]
260 """Class to emulate reco sequences with no Hypo"""
261 """It contains an InputMaker and and empty seqAND used for merging"""
262 """It contains empty function to follow the same MenuSequence behaviour"""
264 log.debug(
"Made EmptySequence %s", the_name)
270 makerAlg = CompFactory.InputMakerForRoI(f
"IM{the_name}",
272 RoIsLink =
'initialRoI')
278 self.
ca.addSequence(
seqAND(the_name))
279 self.
ca.addEventAlgo(makerAlg, sequenceName=the_name)
301 return self.
maker.readOutputList()
304 """Connect filter to the InputMaker"""
310 def buildDFDot(self, cfseq_algs, all_hypos, last_step_hypo_nodes, file):
311 cfseq_algs.append(self.
maker)
313 file.write(
" %s[fillcolor=%s]\n"%(self.
maker.Alg.getName(),
algColor(self.
maker.Alg)))
315 return cfseq_algs, all_hypos, last_step_hypo_nodes
318 return "MenuSequence::%s \n Hypo::%s \n Maker::%s \n Sequence::%s \n HypoTool::%s\n"\
319 %(self.
name,
"Empty", self.
maker.Alg.getName(), self.
sequence.Alg.getName(),
"None")
322 """ creates the generator function named as the empty sequence"""
323 def create_sequence(flags, name):
326 create_sequence.__name__ = name
327 globals()[name] = create_sequence
328 return globals()[name]
332 return 'Empty' in o.func.__name__
335 """Class to group reco sequences with the Hypo.
336 By construction it has one Hypo only, which gives the name to this class object"""
338 def __init__(self, flags, selectionCA, HypoToolGen):
339 self.
ca = selectionCA
348 assert len(inputMaker) == 1, f
"{len(inputMaker)} input makers in the ComponentAccumulator"
349 inputMaker = inputMaker[0]
350 assert inputMaker.name.startswith(
"IM"), f
"Input maker {inputMaker.name} name needs to start with 'IM'"
352 input_maker_output = self.
maker.readOutputList()[0]
356 hypoAlg = selectionCA.hypoAcc.getEventAlgos()
357 assert len(hypoAlg) == 1, f
"{len(hypoAlg)} hypo algs in the ComponentAccumulator"
359 hypoAlg.RuntimeValidation = flags.Trigger.doRuntimeNaviVal
361 self.
_name = CFNaming.menuSequenceName(hypoAlg.name)
363 self.
_hypo.addOutput( CFNaming.hypoAlgOutName(hypoAlg.name) )
364 self.
_hypo.setPreviousDecision( input_maker_output )
368 if ROBPrefetching.StepRoI
in flags.Trigger.ROBPrefetchingOptions:
369 for child
in sequence.Members:
370 if ( isinstance(child, CompFactory.ROBPrefetchingAlg)
and
371 input_maker_output
not in child.ROBPrefetchingInputDecisions ):
372 child.ROBPrefetchingInputDecisions.append(input_maker_output)
374 log.debug(
"connecting InputMaker and HypoAlg, adding: InputMaker::%s.output=%s",
375 self.
maker.Alg.name, input_maker_output)
376 log.debug(
"HypoAlg::%s.HypoInputDecisions=%s, HypoAlg::%s.HypoOutputDecisions=%s",
377 self.
hypo.Alg.name, self.
hypo.readInputList()[0],
378 self.
hypo.Alg.name, self.
hypo.readOutputList()[0])
405 return [self.
_hypo.readOutputList()[0]]
408 """Connect filter to the InputMaker"""
409 log.debug(
"connecting %s to inputs of %s", outfilter, self.
maker.Alg.name)
416 def buildDFDot(self, cfseq_algs, all_hypos, last_step_hypo_nodes, file):
417 cfseq_algs.append(self.
maker)
419 file.write(
" %s[fillcolor=%s]\n"%(self.
maker.Alg.getName(),
algColor(self.
maker.Alg)))
421 cfseq_algs.append(self.
_hypo)
423 all_hypos.append(self.
_hypo)
424 return cfseq_algs, all_hypos, last_step_hypo_nodes
427 hyponame = self.
_hypo.Alg.name
429 return "MenuSequence::%s \n Hypo::%s \n Maker::%s \n Sequence::%s \n HypoTool::%s\n"\
434 """Basic class to define the trigger menu """
435 __slots__ =
'name',
'steps',
'nSteps',
'alignmentGroups',
'L1decisions',
'topoMap'
436 def __init__(self, name, ChainSteps, L1decisions, nSteps = None, alignmentGroups = None, topoMap=None):
439 Construct the Chain from the steps
440 Out of all arguments the ChainSteps & L1Thresholds are most relevant, the chain name is used in debug messages
444 if nSteps
is None: nSteps = []
445 if alignmentGroups
is None: alignmentGroups = []
466 log.debug(
"[Chain.__init__] Made Chain %s with seeds: %s ", name, self.
L1decisions)
469 assert len(self.
nSteps) == 1,
"[Chain.append_bjet_steps] appending already-merged step lists - chain object will be broken. This should only be used to append Bjets to jets!"
474 assert len(self.
nSteps) == 1,
"[Chain.append_step_to_jet] appending already-merged step lists - chain object will be broken. This is used either for appending Beamspot algorithms to jets!"
480 if len(self.
steps)==0:
483 for stepID,step
in enumerate(self.
steps):
484 step_name = step.name
485 if re.search(
'^Step[0-9]_',step_name):
486 step_name = step_name[6:]
487 elif re.search(
'^Step[0-9]{2}_', step_name):
488 step_name = step_name[7:]
489 step.name =
'Step%d_'%(stepID+1)+step_name
491 for iseq, seq
in enumerate(step.sequenceGens):
493 name = seq.func.__name__
494 if re.search(
'Seq[0-9]_',name):
495 newname = re.sub(
'Seq[0-9]_',
'Seq%d_'%(stepID+1), name)
498 step.sequenceGens[iseq]=functools.partial(thisEmpty, flags=
None, name=newname)
506 if len(self.
steps) == 0 :
507 log.error(
"I can't insert empty steps because the chain doesn't have any steps yet!")
509 if len(self.
steps) < start_position :
510 log.error(
"I can't insert empty steps at step %d because the chain doesn't have that many steps!", start_position)
513 chain_steps_pre_split = self.
steps[:start_position]
514 chain_steps_post_split = self.
steps[start_position:]
520 if start_position == 0:
521 next_step_name = chain_steps_post_split[0].name
522 if re.search(
'^Step[0-9]_',next_step_name):
523 next_step_name = next_step_name[6:]
524 elif re.search(
'^Step[0-9]{2}_', next_step_name):
525 next_step_name = next_step_name[7:]
528 prev_chain_dict = chain_steps_post_split[0].stepDicts
530 if len(chain_steps_post_split) == 0:
531 log.error(
"Adding empty steps to the end of a chain (%s)- why would you do this?",self.
name)
533 prev_step_name = chain_steps_pre_split[-1].name
534 next_step_name = chain_steps_post_split[0].name
535 prev_chain_dict = chain_steps_pre_split[-1].stepDicts
539 for stepID
in range(1,n_new_steps+1):
540 new_step_name = prev_step_name+
'_'+empty_step_name+
'%d_'%stepID+next_step_name
542 log.debug(
"Adding empty step %s", new_step_name)
543 steps_to_add += [
ChainStep(new_step_name, chainDicts=prev_chain_dict, comboHypoCfg=ComboHypoCfg, isEmpty=
True)]
545 self.
steps = chain_steps_pre_split + steps_to_add + chain_steps_post_split
550 """ return 0 if the chain has unexpected number of step legs """
551 if len(self.
steps) == 0:
554 mult=[step.nLegs
for step
in self.
steps]
555 not_empty_mult = [m
for m
in mult
if m!=0]
557 if len(not_empty_mult) == 0:
558 log.error(
"checkNumberOfLegs: Chain %s has all steps with nLegs =0: what to do?", self.
name)
562 if not_empty_mult.count(not_empty_mult[0]) != len(not_empty_mult):
563 log.error(
"checkNumberOfLegs: Chain %s has steps with differnt number of legs: %s", self.
name,
' '.
join(mult))
568 log.error(
"checkNumberOfLegs: Chain %s has %i legs per step, and %d L1Decisions", self.
name, mult, len(self.
L1decisions))
570 return not_empty_mult[0]
577 stepname =
"last step" if step==
"last" else step.name
578 log.debug(
"Adding topo configurator %s for %s to %s", topoPair[0].__qualname__, topoPair[1],
"step " + stepname)
582 return "\n-*- Chain %s -*- \n + Seeds: %s, Steps: %s, AlignmentGroups: %s "%(\
586 return "\n-*- Chain %s -*- \n + Seeds: %s, Steps: %s, AlignmentGroups: %s \n + Steps: \n %s \n"%(\
592 """ Class to describe one step of a chain;
593 a step is described by a list of ChainDicts and a list of sequence generators;
594 there is one leg per ChainDict;
595 a step can have one leg (single) or more legs (combined);
596 not-empty steps have one sequence per leg;
597 empty steps have zero sequences, while chainDict len is not zero;
598 legID is taken from the ChainDict;
601 def __init__(self, name, SequenceGens = None, chainDicts = None, comboHypoCfg = ComboHypoCfg , comboToolConfs = None, isEmpty = False, createsGhostLegs = False):
604 if SequenceGens
is None: SequenceGens = []
605 if comboToolConfs
is None: comboToolConfs = []
606 assert chainDicts
is not None,
"Error building a ChainStep without chainDicts"
619 log.debug(
"Building step %s for chain %s: n.sequences=%d, nLegs=%i", name, chainDicts[0][
'chainName'], len (self.
sequenceGens) , self.
nLegs )
621 log.error(
"[ChainStep] SequenceGens: %s",self.
sequenceGens)
622 log.error(
"[ChainStep] stepDicts: %s",self.
stepDicts)
623 log.error(
"[ChainStep] n.legs: %i",self.
nLegs)
624 raise RuntimeError(
"[ChainStep] Tried to configure a ChainStep %s with %i legs and %i sequences. These lists must have the same size" % (name, self.
nLegs, len (self.
sequenceGens) ) )
628 if not isinstance(seq, functools.partial):
629 log.error(
"[ChainStep] %s SequenceGens verification failed, sequence %d is not partial function, likely ChainBase.getStep function was not used", self.
name, iseq)
630 log.error(
"[ChainStep] It rather seems to be of type %s trying to print it",
type(seq))
631 raise RuntimeError(
"Sequence is not packaged in a tuple, see error message above" )
635 if 'signature' in chainDicts[0]:
636 sig_set =
set([step[
'signature']
for step
in chainDicts])
637 if len(sig_set) == 1
and (
'Jet' in sig_set
or 'Bjet' in sig_set):
639 if len(sig_set) == 2
and (
'Jet' in sig_set
and 'Bjet' in sig_set):
649 """ creation of this step sequences with instantiation of the CAs"""
650 log.debug(
"creating sequences for step %s", self.
name)
658 lists_of_chainPartNames = []
660 if len(lists_of_chainPartNames) == 0:
661 lists_of_chainPartNames += [[cp[
'chainPartName']
for cp
in step_dict[
'chainParts']]]
663 new_list_of_chainPartNames = [cp[
'chainPartName']
for cp
in step_dict[
'chainParts']]
664 if new_list_of_chainPartNames == lists_of_chainPartNames[-1]:
665 leg_counter -= len(new_list_of_chainPartNames)
666 for chainPart
in step_dict[
'chainParts']:
667 chainPart[
'chainPartIndex'] = leg_counter
681 """ Configure the Combo Hypo Alg and generate the corresponding function, without instantiation which is done in createSequences() """
685 comboNameFromStep = CFNaming.comboHypoName(self.
name)
687 key =
hash((comboNameFromStep, funcName))
688 if key
not in _ComboHypoPool:
690 CHname = tmpCombo.name[:-4]
693 if comboNameFromStep != CHname:
694 log.debug(
"Created ComboHypo with name %s, expected from the step is instead %s. This is accepted only for allowed custom ComboHypos", CHname, comboNameFromStep)
695 _CustomComboHypoAllowed.add(CHname)
696 key =
hash((CHname, funcName))
697 _ComboHypoPool[key] = tmpCombo
698 self.
combo = _ComboHypoPool[key]
699 log.debug(
"Created combo %s with name %s, step comboName %s, key %s", funcName, self.
combo.name, comboNameFromStep,key)
703 chainDict = HLTMenuConfig.getChainDictFromChainName(chainName)
707 """ This is extrapolating the chain legs from the step dictionaries"""
708 legs = [part[
'chainName']
for part
in self.
stepDicts]
712 if self.
combo is not None:
718 return "\n--- ChainStep %s ---\n is Empty, ChainDict = %s "%(self.
name,
' '.
join(map(str, [dic[
'chainName']
for dic
in self.
stepDicts])) )
720 repr_string=
"\n--- ChainStep %s ---\n , nLegs = %s ChainDict = %s \n + MenuSequenceGens = %s "%\
722 ' '.
join(map(str, [dic[
'chainName']
for dic
in self.
stepDicts])),
725 if self.
combo is not None:
726 repr_string +=
"\n + ComboHypo = %s" % self.
combo.Alg.name
728 repr_string +=
", ComboHypoTools = %s" %(
' '.
join(map(str, [tool.__name__
for tool
in self.
comboToolConfs])))
734 """ Class to handle in-event reco """
735 def __init__(self, name, inputMaker=None, **inputMakerArgs):
736 super( InEventRecoCA, self ).
__init__()
741 assert len(inputMakerArgs) == 0,
"No support for explicitly passed input maker and and input maker arguments at the same time"
744 assert 'name' not in inputMakerArgs,
"The name of input maker is predefined by the name of sequence"
745 args = {
'name':
"IM"+name,
746 'RoIsLink' :
'initialRoI',
747 'RoIs' : f
'{name}RoIs',
748 'RoITool': CompFactory.ViewCreatorInitialROITool(),
749 'mergeUsingFeature':
False}
750 args.update(**inputMakerArgs)
756 self.addSequence( self.
recoSeq )
759 """ Merged CA moving reconstruction algorithms into the right sequence """
761 return self.merge( ca, sequenceName=self.
recoSeq.name )
764 """ Place algorithm in the correct reconstruction sequence """
766 return self.addEventAlgo( algo, sequenceName=self.
recoSeq.name )
774 """ Class to handle in-view reco, sets up the View maker if not provided and exposes InputMaker so that more inputs to it can be added in the process of assembling the menu """
775 def __init__(self, name, viewMaker=None, isProbe=False, **viewMakerArgs):
776 super( InViewRecoCA, self ).
__init__()
777 self.
name = name +
"_probe" if isProbe
else name
778 def updateHandle(baseTool, probeTool, handleName):
779 if hasattr(baseTool, handleName)
and getattr(baseTool, handleName).Path!=
"StoreGateSvc+":
780 setattr(probeTool, handleName, getattr(probeTool, handleName).Path +
"_probe")
782 if len(viewMakerArgs) != 0:
783 assert viewMaker
is None,
"No support for explicitly passed view maker and args for EventViewCreatorAlgorithm"
786 assert len(viewMakerArgs) == 0,
"No support for explicitly passed view maker and args for EventViewCreatorAlgorithm"
788 self.
viewMakerAlg = viewMaker.__class__(viewMaker.getName()+
'_probe', **viewMaker._properties)
791 log.debug(f
"InViewRecoCA: Setting InputCachedViews on {self.viewMaker.getName()} to read decisions from tag leg {viewMaker.getName()}: {viewMaker.InputMakerOutputDecisions}")
792 self.
viewMakerAlg.InputCachedViews = viewMaker.InputMakerOutputDecisions
793 updateHandle(viewMakerArgs[
'RoITool'], roiTool,
"RoisWriteHandleKey")
794 if hasattr(viewMakerArgs[
'RoITool'],
"RoiCreator"):
795 updateHandle(viewMakerArgs[
'RoITool'], roiTool,
"ExtraPrefetchRoIsKey")
796 updateHandle(viewMakerArgs[
'RoITool'].RoiCreator, roiTool.RoiCreator,
"RoisWriteHandleKey")
802 assert 'name' not in viewMakerArgs,
"The name of view maker is predefined by the name of sequence"
803 assert 'Views' not in viewMakerArgs,
"The Views is predefined by the name of sequence"
804 assert 'ViewsNodeName' not in viewMakerArgs,
"The ViewsNodeName is predefined by the name of sequence"
805 if 'RoITool' in viewMakerArgs:
806 roiTool = viewMakerArgs[
'RoITool']
808 roiTool = CompFactory.ViewCreatorInitialROITool()
811 args = {
'name': f
'IM_{self.name}',
812 'ViewFallThrough' :
True,
813 'RoIsLink' :
'initialRoI',
815 'InViewRoIs' : f
'{name}RoIs',
816 'Views' : f
'{name}Views'+
'_probe' if isProbe
else f
'{name}Views',
817 'ViewNodeName' : f
'{name}InViews'+
'_probe' if isProbe
else f
'{name}InViews',
818 'RequireParentView' :
False,
819 'mergeUsingFeature' :
False }
820 args.update(**viewMakerArgs)
821 self.
viewMakerAlg = CompFactory.EventViewCreatorAlgorithm(**args)
823 updateHandle(args[
'RoITool'], roiTool,
"RoisWriteHandleKey")
824 if hasattr(args[
'RoITool'],
"RoiCreator"):
825 updateHandle(args[
'RoITool'], roiTool,
"ExtraPrefetchRoIsKey")
826 updateHandle(args[
'RoITool'].RoiCreator, roiTool.RoiCreator,
"RoisWriteHandleKey")
831 """ Merge CA moving reconstruction algorithms into the right sequence """
832 return self.merge( ca, sequenceName=self.
viewsSeq.name )
836 """ Place algorithm in the correct reconstruction sequence """
837 return self.addEventAlgo( algo, sequenceName=self.
viewsSeq.name )
845 """ CA component for MenuSequence sequence """
847 self.
name = name+
"_probe" if isProbe
else name
849 super( SelectionCA, self ).
__init__()
858 def mergeReco(self, recoCA, robPrefetchCA=None, upSequenceCA=None):
859 ''' upSequenceCA is the user CA to run before the recoCA'''
864 ca.addEventAlgo(recoCA.inputMaker(), sequenceName=self.
stepViewSequence.name)
871 """To be used when the hypo alg configuration comes with auxiliary tools/services"""
875 """To be used when the hypo alg configuration does not require auxiliary tools/services"""
877 newname = algo.getName()+
'_probe'
879 self.
hypoAcc.addEventAlgo(algo)
882 """Access hypo algo (or throws)"""
884 assert h
is not None,
"No hypo in SeelectionCA {}".
format(self.
name)
888 """Access Input Maker (or throws)"""
890 assert im
is not None,
"No input maker in SeelectionCA {}".
format(self.
name)