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
19 from AthenaCommon.Logging
import logging
20 log = logging.getLogger( __name__ )
22 _ComboHypoPool = dict()
23 _CustomComboHypoAllowed =
set()
26 """base class representing one Alg + inputs + outputs, to be used to connect """
27 """stores all the inputs, even if repeated (self.inputs)"""
29 self.
name = (
"%sNode")%( Alg.getName() )
51 """Node class that represent an algorithm: sets R/W handles (as unique input/output) and properties as parameters """
52 """Automatically de-duplicates input ReadHandles upon repeated calls to addInput."""
53 def __init__(self, Alg, inputProp, outputProp):
54 Node.__init__(self, Alg)
59 cval = getattr( self.
Alg, propname)
60 if isinstance(cval, MutableSequence):
62 return setattr(self.
Alg, propname, cval)
64 return setattr(self.
Alg, propname, value)
69 log.debug(
"Output DH not added in %s: %s already set!", self.
Alg.
getName(), name)
74 log.debug(
"no outputProp set for output of %s", self.
Alg.
getName())
75 Node.addOutput(self, name)
79 return (cval
if isinstance(cval, MutableSequence)
else
80 ([
str(cval)]
if cval
else []))
85 log.debug(
"Input DH not added in %s: %s already set!", self.
Alg.
getName(), name)
90 log.debug(
"no InputProp set for input of %s", self.
Alg.
getName())
91 Node.addInput(self, name)
96 return (cval
if isinstance(cval, MutableSequence)
else
97 ([
str(cval)]
if cval
else []))
104 """ Class to group info on hypotools for ChainDict"""
110 if type(chainDict)
is not dict:
111 raise RuntimeError(
"Configuring hypo with %s, not good anymore, use chainDict" %
str(chainDict) )
115 """creates instance of the hypo tool"""
119 """sets the configuration and creates instance of the hypo tool"""
125 """AlgNode for HypoAlgs"""
126 initialOutput=
'StoreGateSvc+UNSPECIFIED_OUTPUT'
128 assert isHypoBase(Alg),
"Error in creating HypoAlgNode from Alg " + Alg.name
129 AlgNode.__init__(self, Alg,
'HypoInputDecisions',
'HypoOutputDecisions')
135 log.debug(
"Output DH not added in %s: %s already set!", self.
name, name)
137 AlgNode.addOutput(self, name)
139 log.error(
"Hypo %s has already %s as configured output: you may want to duplicate the Hypo!",
140 self.
name, outputs[0])
143 log.debug(
"Adding HypoTool %s for chain %s to %s", hypoToolConf.name, hypoToolConf.chainDict[
'chainName'], self.
Alg.
getName())
145 result = hypoToolConf.create(flags)
146 if isinstance(result, ComponentAccumulator):
147 tool = result.popPrivateTools()
148 assert not isinstance(tool, list),
"Can not handle list of tools"
149 self.
Alg.HypoTools.append(tool)
152 self.
Alg.HypoTools = self.
Alg.HypoTools + [result]
154 except NoHypoToolCreated
as e:
155 log.debug(
"%s returned empty tool: %s", hypoToolConf.name, e)
163 return "HypoAlg::%s [%s] -> [%s], previous = [%s], HypoTools=[%s]" % \
167 ' '.
join([t.getName()
for t
in self.
Alg.HypoTools]))
171 """AlgNode for InputMaker Algs"""
173 assert isInputMakerBase(Alg),
"Error in creating InputMakerNode from Alg " + Alg.name
174 AlgNode.__init__(self, Alg,
'InputMakerInputDecisions',
'InputMakerOutputDecisions')
175 input_maker_output = CFNaming.inputMakerOutName(self.
Alg.name)
180 """AlgNode for Combo HypoAlgs"""
184 thealgs= self.
acc.getEventAlgos()
186 log.error(
"ComboHypoNode: Combo alg %s not found", name)
187 if len(thealgs) != 1:
188 log.error(
"ComboHypoNode: Combo alg %s len is %d",name, len(thealgs))
191 log.debug(
"ComboHypoNode init: Alg %s", name)
192 AlgNode.__init__(self, Alg,
'HypoInputDecisions',
'HypoOutputDecisions')
198 log.debug(
"ComboHypoNode.create %s",name)
202 AlgNode automatically de-duplicates input ReadHandles upon repeated calls to addInput.
203 Node instead stores all the inputs, even if repeated (self.inputs)
204 This function maps from the raw number of times that addInput was called to the de-duplicated index of the handle.
205 E.g. a step processing chains such as HLT_e5_mu6 would return [0,1]
206 E.g. a step processing chains such as HLT_e5_e6 would return [0,0]
207 E.g. a step processing chains such as HLT_e5_mu6_mu7 would return [0,1,1]
208 These data are needed to configure the step's ComboHypo
213 for rawInput
in self.
inputs:
214 mapping.append( theInputs.index(rawInput) )
219 chainName = chainDict[
'chainName']
220 chainMult = chainDict[
'chainMultiplicities']
222 if len(chainMult) != len(legsToInputCollections):
223 log.error(
"ComboHypoNode for Alg:{} with addChain for:{} Chain multiplicity:{} Per leg input collection index:{}."
224 .
format(self.
Alg.name, chainName, tuple(chainMult), tuple(legsToInputCollections)))
225 log.error(
"The size of the multiplicies vector must be the same size as the per leg input collection vector.")
226 log.error(
"The ComboHypo needs to know which input DecisionContainers contain the DecisionObjects to be used for each leg.")
227 log.error(
"Check why ComboHypoNode.addInput(...) was not called exactly once per leg.")
228 raise Exception(
"[createDataFlow] Error in ComboHypoNode.addChain. Cannot proceed.")
230 if chainName
in self.
Alg.MultiplicitiesMap:
231 log.error(
"ComboAlg %s has already been configured for chain %s", self.
Alg.name, chainName)
232 raise Exception(
"[createDataFlow] Error in ComboHypoNode.addChain. Cannot proceed.")
234 self.
Alg.MultiplicitiesMap[chainName] = chainMult
235 self.
Alg.LegToInputCollectionMap[chainName] = legsToInputCollections
239 return self.
Alg.MultiplicitiesMap.keys()
243 """Create the ComboHypoTools and add them to the main alg"""
244 if not len(comboToolConfs):
246 confs = [
HypoToolConf( tool )
for tool
in comboToolConfs ]
247 log.debug(
"ComboHypoNode.createComboHypoTools for chain %s, Alg %s with %d tools", chainDict[
"chainName"],self.
Alg.
getName(), len(comboToolConfs))
249 log.debug(
"ComboHypoNode.createComboHypoTools adding %s", conf)
250 tools = self.
Alg.ComboHypoTools
251 self.
Alg.ComboHypoTools = tools + [ conf.confAndCreate( flags, chainDict ) ]
259 """Class to emulate reco sequences with no Hypo"""
260 """It contains an InputMaker and and empty seqAND used for merging"""
261 """It contains empty function to follow the same MenuSequence behaviour"""
263 log.debug(
"Made EmptySequence %s", the_name)
269 makerAlg = CompFactory.InputMakerForRoI(f
"IM{the_name}",
271 RoIsLink =
'initialRoI')
277 self.
ca.addSequence(
seqAND(the_name))
278 self.
ca.addEventAlgo(makerAlg, sequenceName=the_name)
300 return self.
maker.readOutputList()
303 """Connect filter to the InputMaker"""
309 def buildDFDot(self, cfseq_algs, all_hypos, last_step_hypo_nodes, file):
310 cfseq_algs.append(self.
maker)
312 file.write(
" %s[fillcolor=%s]\n"%(self.
maker.Alg.getName(),
algColor(self.
maker.Alg)))
314 return cfseq_algs, all_hypos, last_step_hypo_nodes
317 return "MenuSequence::%s \n Hypo::%s \n Maker::%s \n Sequence::%s \n HypoTool::%s\n"\
318 %(self.
name,
"Empty", self.
maker.Alg.getName(), self.
sequence.Alg.getName(),
"None")
321 """ creates the generator function named as the empty sequence"""
322 def create_sequence(flags, name):
325 create_sequence.__name__ = name
326 globals()[name] = create_sequence
327 return globals()[name]
331 return 'Empty' in o.func.__name__
334 """Class to group reco sequences with the Hypo.
335 By construction it has one Hypo only, which gives the name to this class object"""
337 def __init__(self, flags, selectionCA, HypoToolGen):
338 self.
ca = selectionCA
347 assert len(inputMaker) == 1, f
"{len(inputMaker)} input makers in the ComponentAccumulator"
348 inputMaker = inputMaker[0]
349 assert inputMaker.name.startswith(
"IM"), f
"Input maker {inputMaker.name} name needs to start with 'IM'"
351 input_maker_output = self.
maker.readOutputList()[0]
355 hypoAlg = selectionCA.hypoAcc.getEventAlgos()
356 assert len(hypoAlg) == 1, f
"{len(hypoAlg)} hypo algs in the ComponentAccumulator"
358 hypoAlg.RuntimeValidation = flags.Trigger.doRuntimeNaviVal
360 self.
_name = CFNaming.menuSequenceName(hypoAlg.name)
362 self.
_hypo.addOutput( CFNaming.hypoAlgOutName(hypoAlg.name) )
363 self.
_hypo.setPreviousDecision( input_maker_output )
367 if ROBPrefetching.StepRoI
in flags.Trigger.ROBPrefetchingOptions:
368 for child
in sequence.Members:
369 if ( isinstance(child, CompFactory.ROBPrefetchingAlg)
and
370 input_maker_output
not in child.ROBPrefetchingInputDecisions ):
371 child.ROBPrefetchingInputDecisions.append(input_maker_output)
373 log.debug(
"connecting InputMaker and HypoAlg, adding: InputMaker::%s.output=%s",
374 self.
maker.Alg.name, input_maker_output)
375 log.debug(
"HypoAlg::%s.HypoInputDecisions=%s, HypoAlg::%s.HypoOutputDecisions=%s",
376 self.
hypo.Alg.name, self.
hypo.readInputList()[0],
377 self.
hypo.Alg.name, self.
hypo.readOutputList()[0])
404 return [self.
_hypo.readOutputList()[0]]
407 """Connect filter to the InputMaker"""
408 log.debug(
"connectToFilter: connecting %s to inputs of %s", outfilter, self.
maker.Alg.name)
415 def buildDFDot(self, cfseq_algs, all_hypos, last_step_hypo_nodes, file):
416 cfseq_algs.append(self.
maker)
418 file.write(
" %s[fillcolor=%s]\n"%(self.
maker.Alg.getName(),
algColor(self.
maker.Alg)))
420 cfseq_algs.append(self.
_hypo)
422 all_hypos.append(self.
_hypo)
423 return cfseq_algs, all_hypos, last_step_hypo_nodes
426 hyponame = self.
_hypo.Alg.name
428 return "MenuSequence::%s \n Hypo::%s \n Maker::%s \n Sequence::%s \n HypoTool::%s\n"\
433 """Basic class to define the trigger menu """
434 __slots__ =
'name',
'steps',
'nSteps',
'alignmentGroups',
'L1decisions',
'topoMap'
435 def __init__(self, name, ChainSteps, L1decisions, nSteps = None, alignmentGroups = None, topoMap=None):
438 Construct the Chain from the steps
439 Out of all arguments the ChainSteps & L1Thresholds are most relevant, the chain name is used in debug messages
443 if nSteps
is None: nSteps = []
444 if alignmentGroups
is None: alignmentGroups = []
465 log.debug(
"[Chain.__init__] Made Chain %s with seeds: %s ", name, self.
L1decisions)
468 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!"
473 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!"
479 if len(self.
steps)==0:
482 for stepID,step
in enumerate(self.
steps):
483 step_name = step.name
484 if re.search(
'^Step[0-9]_',step_name):
485 step_name = step_name[6:]
486 elif re.search(
'^Step[0-9]{2}_', step_name):
487 step_name = step_name[7:]
488 step.name =
'Step%d_'%(stepID+1)+step_name
490 for iseq, seq
in enumerate(step.sequenceGens):
492 name = seq.func.__name__
493 if re.search(
'Seq[0-9]_',name):
494 newname = re.sub(
'Seq[0-9]_',
'Seq%d_'%(stepID+1), name)
497 step.sequenceGens[iseq]=functools.partial(thisEmpty, flags=
None, name=newname)
505 if len(self.
steps) == 0 :
506 log.error(
"I can't insert empty steps because the chain doesn't have any steps yet!")
508 if len(self.
steps) < start_position :
509 log.error(
"I can't insert empty steps at step %d because the chain doesn't have that many steps!", start_position)
512 chain_steps_pre_split = self.
steps[:start_position]
513 chain_steps_post_split = self.
steps[start_position:]
519 if start_position == 0:
520 next_step_name = chain_steps_post_split[0].name
521 if re.search(
'^Step[0-9]_',next_step_name):
522 next_step_name = next_step_name[6:]
523 elif re.search(
'^Step[0-9]{2}_', next_step_name):
524 next_step_name = next_step_name[7:]
527 prev_chain_dict = chain_steps_post_split[0].stepDicts
529 if len(chain_steps_post_split) == 0:
530 log.error(
"Adding empty steps to the end of a chain (%s)- why would you do this?",self.
name)
532 prev_step_name = chain_steps_pre_split[-1].name
533 next_step_name = chain_steps_post_split[0].name
534 prev_chain_dict = chain_steps_pre_split[-1].stepDicts
538 for stepID
in range(1,n_new_steps+1):
539 new_step_name = prev_step_name+
'_'+empty_step_name+
'%d_'%stepID+next_step_name
541 log.debug(
"Adding empty step %s", new_step_name)
542 steps_to_add += [
ChainStep(new_step_name, chainDicts=prev_chain_dict, isEmpty=
True)]
544 self.
steps = chain_steps_pre_split + steps_to_add + chain_steps_post_split
549 """ return 0 if the chain has unexpected number of step legs """
550 if len(self.
steps) == 0:
553 mult=[step.nLegs
for step
in self.
steps]
554 not_empty_mult = [m
for m
in mult
if m!=0]
556 if len(not_empty_mult) == 0:
557 log.error(
"checkNumberOfLegs: Chain %s has all steps with nLegs =0: what to do?", self.
name)
561 if not_empty_mult.count(not_empty_mult[0]) != len(not_empty_mult):
562 log.error(
"checkNumberOfLegs: Chain %s has steps with differnt number of legs: %s", self.
name,
' '.
join(mult))
567 log.error(
"checkNumberOfLegs: Chain %s has %i legs per step, and %d L1Decisions", self.
name, mult, len(self.
L1decisions))
569 return not_empty_mult[0]
576 stepname =
"last step" if step==
"last" else step.name
577 log.debug(
"Adding topo configurator %s for %s to %s", topoPair[0].__qualname__, topoPair[1],
"step " + stepname)
581 return "\n-*- Chain %s -*- \n + Seeds: %s, Steps: %s, AlignmentGroups: %s "%(\
585 return "\n-*- Chain %s -*- \n + Seeds: %s, Steps: %s, AlignmentGroups: %s \n + Steps: \n %s \n"%(\
591 """ Class to describe one step of a chain;
592 a step is described by a list of ChainDicts and a list of sequence generators;
593 there is one leg per ChainDict;
594 a step can have one leg (single) or more legs (combined);
595 not-empty steps have one sequence per leg;
596 empty steps have zero sequences, while chainDict len is not zero;
597 legID is taken from the ChainDict;
600 def __init__(self, name, SequenceGens = None, chainDicts = None, comboHypoCfg = None, comboToolConfs = None, isEmpty = False, createsGhostLegs = False):
603 if SequenceGens
is None: SequenceGens = []
604 if comboHypoCfg
is None: comboHypoCfg = functools.partial(ComboHypoCfg)
605 if comboToolConfs
is None: comboToolConfs = []
606 assert chainDicts
is not None,
"Error building a ChainStep without chainDicts"
611 if not isinstance(comboHypoCfg, functools.partial):
612 raise RuntimeError(
"[ChainStep] Tried to configure a ChainStep %s with ComboHypo %s that is not a function" % (name, comboHypoCfg) )
622 log.debug(
"Building step %s for chain %s: n.sequences=%d, nLegs=%i", name, chainDicts[0][
'chainName'], len (self.
sequenceGens) , self.
nLegs )
624 log.error(
"[ChainStep] SequenceGens: %s",self.
sequenceGens)
625 log.error(
"[ChainStep] stepDicts: %s",self.
stepDicts)
626 log.error(
"[ChainStep] n.legs: %i",self.
nLegs)
627 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) ) )
631 if not isinstance(seq, functools.partial):
632 log.error(
"[ChainStep] %s SequenceGens verification failed, sequence %d is not partial function, likely ChainBase.getStep function was not used", self.
name, iseq)
633 log.error(
"[ChainStep] It rather seems to be of type %s trying to print it",
type(seq))
634 raise RuntimeError(
"Sequence is not packaged in a tuple, see error message above" )
638 if 'signature' in chainDicts[0]:
639 sig_set =
set([step[
'signature']
for step
in chainDicts])
640 if len(sig_set) == 1
and (
'Jet' in sig_set
or 'Bjet' in sig_set):
642 if len(sig_set) == 2
and (
'Jet' in sig_set
and 'Bjet' in sig_set):
652 """ creation of this step sequences with instantiation of the CAs"""
653 log.debug(
"createSequences: creating %d sequences for step %s", len(self.
sequenceGens), self.
name)
655 log.debug(
"createSequences: creating sequence %s", seq.func.__name__)
662 lists_of_chainPartNames = []
664 if len(lists_of_chainPartNames) == 0:
665 lists_of_chainPartNames += [[cp[
'chainPartName']
for cp
in step_dict[
'chainParts']]]
667 new_list_of_chainPartNames = [cp[
'chainPartName']
for cp
in step_dict[
'chainParts']]
668 if new_list_of_chainPartNames == lists_of_chainPartNames[-1]:
669 leg_counter -= len(new_list_of_chainPartNames)
670 for chainPart
in step_dict[
'chainParts']:
671 chainPart[
'chainPartIndex'] = leg_counter
686 """ Configure the Combo Hypo Alg and generate the corresponding function, without instantiation which is done in createSequences() """
690 comboNameFromStep = CFNaming.comboHypoName(self.
name)
692 key =
hash((comboNameFromStep, funcName))
693 if key
not in _ComboHypoPool:
695 CHname = tmpCombo.name[:-4]
698 if comboNameFromStep != CHname:
699 log.debug(
"Created ComboHypo with name %s, expected from the step is instead %s. This is accepted only for allowed custom ComboHypos", CHname, comboNameFromStep)
700 _CustomComboHypoAllowed.add(CHname)
701 key =
hash((CHname, funcName))
702 _ComboHypoPool[key] = tmpCombo
703 self.
combo = _ComboHypoPool[key]
704 log.debug(
"Created combo %s with name %s, step comboName %s, key %s", funcName, self.
combo.name, comboNameFromStep,key)
708 chainDict = HLTMenuConfig.getChainDictFromChainName(chainName)
712 """ This is extrapolating the chain legs from the step dictionaries"""
713 legs = [part[
'chainName']
for part
in self.
stepDicts]
717 if self.
combo is not None:
723 return "\n--- ChainStep %s ---\n is Empty, ChainDict = %s "%(self.
name,
' '.
join(map(str, [dic[
'chainName']
for dic
in self.
stepDicts])) )
725 repr_string=
"\n--- ChainStep %s ---\n , nLegs = %s ChainDict = %s \n + MenuSequenceGens = %s "%\
727 ' '.
join(map(str, [dic[
'chainName']
for dic
in self.
stepDicts])),
730 if self.
combo is not None:
731 repr_string +=
"\n + ComboHypo = %s" % self.
combo.Alg.name
733 repr_string +=
", ComboHypoTools = %s" %(
' '.
join(map(str, [tool.__name__
for tool
in self.
comboToolConfs])))
739 """ Class to handle in-event reco """
740 def __init__(self, name, inputMaker=None, **inputMakerArgs):
741 super( InEventRecoCA, self ).
__init__()
746 assert len(inputMakerArgs) == 0,
"No support for explicitly passed input maker and and input maker arguments at the same time"
749 assert 'name' not in inputMakerArgs,
"The name of input maker is predefined by the name of sequence"
750 args = {
'name':
"IM"+name,
751 'RoIsLink' :
'initialRoI',
752 'RoIs' : f
'{name}RoIs',
753 'RoITool': CompFactory.ViewCreatorInitialROITool(),
754 'mergeUsingFeature':
False}
755 args.update(**inputMakerArgs)
761 self.addSequence( self.
recoSeq )
764 """ Merged CA moving reconstruction algorithms into the right sequence """
766 return self.merge( ca, sequenceName=self.
recoSeq.name )
769 """ Place algorithm in the correct reconstruction sequence """
771 return self.addEventAlgo( algo, sequenceName=self.
recoSeq.name )
779 """ 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 """
780 def __init__(self, name, viewMaker=None, isProbe=False, **viewMakerArgs):
781 super( InViewRecoCA, self ).
__init__()
782 self.
name = name +
"_probe" if isProbe
else name
783 def updateHandle(baseTool, probeTool, handleName):
784 if hasattr(baseTool, handleName)
and getattr(baseTool, handleName).Path!=
"StoreGateSvc+":
785 setattr(probeTool, handleName, getattr(probeTool, handleName).Path +
"_probe")
787 if len(viewMakerArgs) != 0:
788 assert viewMaker
is None,
"No support for explicitly passed view maker and args for EventViewCreatorAlgorithm"
791 assert len(viewMakerArgs) == 0,
"No support for explicitly passed view maker and args for EventViewCreatorAlgorithm"
793 self.
viewMakerAlg = viewMaker.__class__(viewMaker.getName()+
'_probe', **viewMaker._properties)
796 log.debug(f
"InViewRecoCA: Setting InputCachedViews on {self.viewMaker.getName()} to read decisions from tag leg {viewMaker.getName()}: {viewMaker.InputMakerOutputDecisions}")
797 self.
viewMakerAlg.InputCachedViews = viewMaker.InputMakerOutputDecisions
798 updateHandle(viewMakerArgs[
'RoITool'], roiTool,
"RoisWriteHandleKey")
799 if hasattr(viewMakerArgs[
'RoITool'],
"RoiCreator"):
800 updateHandle(viewMakerArgs[
'RoITool'], roiTool,
"ExtraPrefetchRoIsKey")
801 updateHandle(viewMakerArgs[
'RoITool'].RoiCreator, roiTool.RoiCreator,
"RoisWriteHandleKey")
807 assert 'name' not in viewMakerArgs,
"The name of view maker is predefined by the name of sequence"
808 assert 'Views' not in viewMakerArgs,
"The Views is predefined by the name of sequence"
809 assert 'ViewsNodeName' not in viewMakerArgs,
"The ViewsNodeName is predefined by the name of sequence"
810 if 'RoITool' in viewMakerArgs:
811 roiTool = viewMakerArgs[
'RoITool']
813 roiTool = CompFactory.ViewCreatorInitialROITool()
816 args = {
'name': f
'IM_{self.name}',
817 'ViewFallThrough' :
True,
818 'RoIsLink' :
'initialRoI',
820 'InViewRoIs' : f
'{name}RoIs',
821 'Views' : f
'{name}Views'+
'_probe' if isProbe
else f
'{name}Views',
822 'ViewNodeName' : f
'{name}InViews'+
'_probe' if isProbe
else f
'{name}InViews',
823 'RequireParentView' :
False,
824 'mergeUsingFeature' :
False }
825 args.update(**viewMakerArgs)
826 self.
viewMakerAlg = CompFactory.EventViewCreatorAlgorithm(**args)
828 updateHandle(args[
'RoITool'], roiTool,
"RoisWriteHandleKey")
829 if hasattr(args[
'RoITool'],
"RoiCreator"):
830 updateHandle(args[
'RoITool'], roiTool,
"ExtraPrefetchRoIsKey")
831 updateHandle(args[
'RoITool'].RoiCreator, roiTool.RoiCreator,
"RoisWriteHandleKey")
836 """ Merge CA moving reconstruction algorithms into the right sequence """
837 return self.merge( ca, sequenceName=self.
viewsSeq.name )
841 """ Place algorithm in the correct reconstruction sequence """
842 return self.addEventAlgo( algo, sequenceName=self.
viewsSeq.name )
850 """ CA component for MenuSequence sequence """
852 self.
name = name+
"_probe" if isProbe
else name
854 super( SelectionCA, self ).
__init__()
863 def mergeReco(self, recoCA, robPrefetchCA=None, upSequenceCA=None):
864 ''' upSequenceCA is the user CA to run before the recoCA'''
869 ca.addEventAlgo(recoCA.inputMaker(), sequenceName=self.
stepViewSequence.name)
876 """To be used when the hypo alg configuration comes with auxiliary tools/services"""
880 """To be used when the hypo alg configuration does not require auxiliary tools/services"""
882 newname = algo.getName()+
'_probe'
884 self.
hypoAcc.addEventAlgo(algo)
887 """Access hypo algo (or throws)"""
889 assert h
is not None,
"No hypo in SeelectionCA {}".
format(self.
name)
893 """Access Input Maker (or throws)"""
895 assert im
is not None,
"No input maker in SeelectionCA {}".
format(self.
name)