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
14 from TrigCompositeUtils.TrigCompositeUtils
import legName
15 from TriggerJobOpts.TriggerConfigFlags
import ROBPrefetching
17 from collections.abc
import MutableSequence
23 from AthenaCommon.Logging
import logging
24 log = logging.getLogger( __name__ )
26 _ComboHypoPool = dict()
27 _CustomComboHypoAllowed =
set()
30 """base class representing one Alg + inputs + outputs, to be used to connect """
31 """stores all the inputs, even if repeated (self.inputs)"""
33 self.
name = (
"%sNode")%( Alg.getName() )
55 """Node class that represent an algorithm: sets R/W handles (as unique input/output) and properties as parameters """
56 """Automatically de-duplicates input ReadHandles upon repeated calls to addInput."""
57 def __init__(self, Alg, inputProp, outputProp):
58 Node.__init__(self, Alg)
67 cval = getattr( self.
Alg, propname)
68 if isinstance(cval, MutableSequence):
70 return setattr(self.
Alg, propname, cval)
72 return setattr(self.
Alg, propname, value)
75 cval = getattr(self.
Alg, prop)
76 if isinstance(cval, MutableSequence):
77 return setattr(self.
Alg, prop, [])
79 return setattr(self.
Alg, prop,
"")
82 return getattr(self.
Alg, prop)
93 log.debug(
"Output DH not added in %s: %s already set!", self.
Alg.
getName(), name)
98 log.debug(
"no outputProp set for output of %s", self.
Alg.
getName())
99 Node.addOutput(self, name)
103 return (cval
if isinstance(cval, MutableSequence)
else
104 ([
str(cval)]
if cval
else []))
109 log.debug(
"Input DH not added in %s: %s already set!", self.
Alg.
getName(), name)
114 log.debug(
"no InputProp set for input of %s", self.
Alg.
getName())
115 Node.addInput(self, name)
120 return (cval
if isinstance(cval, MutableSequence)
else
121 ([
str(cval)]
if cval
else []))
128 """ Class to group info on hypotools for ChainDict"""
131 self.
hasFlags =
'flags' in inspect.signature(hypoToolGen).parameters
136 if type(chainDict)
is not dict:
137 raise RuntimeError(
"Configuring hypo with %s, not good anymore, use chainDict" %
str(chainDict) )
141 """creates instance of the hypo tool"""
148 """sets the configuration and creates instance of the hypo tool"""
154 """AlgNode for HypoAlgs"""
155 initialOutput=
'StoreGateSvc+UNSPECIFIED_OUTPUT'
157 assert isHypoBase(Alg),
"Error in creating HypoAlgNode from Alg " + Alg.name
158 AlgNode.__init__(self, Alg,
'HypoInputDecisions',
'HypoOutputDecisions')
164 log.debug(
"Output DH not added in %s: %s already set!", self.
name, name)
166 AlgNode.addOutput(self, name)
168 log.error(
"Hypo %s has already %s as configured output: you may want to duplicate the Hypo!",
169 self.
name, outputs[0])
172 log.debug(
"Adding HypoTool %s for chain %s to %s", hypoToolConf.name, hypoToolConf.chainDict[
'chainName'], self.
Alg.
getName())
174 result = hypoToolConf.create(flags)
175 if isinstance(result, ComponentAccumulator):
176 tool = result.popPrivateTools()
177 assert not isinstance(tool, list),
"Can not handle list of tools"
178 self.
Alg.HypoTools.append(tool)
181 self.
Alg.HypoTools = self.
Alg.HypoTools + [result]
183 except NoHypoToolCreated
as e:
184 log.debug(
"%s returned empty tool: %s", hypoToolConf.name, e)
192 return "HypoAlg::%s [%s] -> [%s], previous = [%s], HypoTools=[%s]" % \
196 ' '.
join([t.getName()
for t
in self.
Alg.HypoTools]))
200 """AlgNode for InputMaker Algs"""
202 assert isInputMakerBase(Alg),
"Error in creating InputMakerNode from Alg " + Alg.name
203 AlgNode.__init__(self, Alg,
'InputMakerInputDecisions',
'InputMakerOutputDecisions')
206 input_maker_output = CFNaming.inputMakerOutName(self.
Alg.name)
211 """AlgNode for Combo HypoAlgs"""
214 self.
prop2 =
"LegToInputCollectionMap"
217 thealgs= self.
acc.getEventAlgos()
219 log.error(
"ComboHypoNode: Combo alg %s not found", name)
220 if len(thealgs) != 1:
221 log.error(
"ComboHypoNode: Combo alg %s len is %d",name, len(thealgs))
224 log.debug(
"ComboHypoNode init: Alg %s", name)
225 AlgNode.__init__(self, Alg,
'HypoInputDecisions',
'HypoOutputDecisions')
236 log.debug(
"ComboHypoNode.create %s",name)
240 AlgNode automatically de-duplicates input ReadHandles upon repeated calls to addInput.
241 Node instead stores all the inputs, even if repeated (self.inputs)
242 This function maps from the raw number of times that addInput was called to the de-duplicated index of the handle.
243 E.g. a step processing chains such as HLT_e5_mu6 would return [0,1]
244 E.g. a step processing chains such as HLT_e5_e6 would return [0,0]
245 E.g. a step processing chains such as HLT_e5_mu6_mu7 would return [0,1,1]
246 These data are needed to configure the step's ComboHypo
251 for rawInput
in self.
inputs:
252 mapping.append( theInputs.index(rawInput) )
257 chainName = chainDict[
'chainName']
258 chainMult = chainDict[
'chainMultiplicities']
260 if len(chainMult) != len(legsToInputCollections):
261 log.error(
"ComboHypoNode for Alg:{} with addChain for:{} Chain multiplicity:{} Per leg input collection index:{}."
262 .
format(self.
Alg.name, chainName, tuple(chainMult), tuple(legsToInputCollections)))
263 log.error(
"The size of the multiplicies vector must be the same size as the per leg input collection vector.")
264 log.error(
"The ComboHypo needs to know which input DecisionContainers contain the DecisionObjects to be used for each leg.")
265 log.error(
"Check why ComboHypoNode.addInput(...) was not called exactly once per leg.")
266 raise Exception(
"[createDataFlow] Error in ComboHypoNode.addChain. Cannot proceed.")
268 cval1 = getattr(self.
Alg, self.
prop1)
269 cval2 = getattr(self.
Alg, self.
prop2)
270 if type(cval1)
is dict
or isinstance(cval1, GaudiConfig2.semantics._DictHelper):
271 if chainName
in cval1.keys():
272 log.error(
"ERROR in configuration: ComboAlg %s has already been configured for chain %s", self.
Alg.name, chainName)
273 raise Exception(
"[createDataFlow] Error in ComboHypoNode.addChain. Cannot proceed.")
275 cval1[chainName] = chainMult
276 cval2[chainName] = legsToInputCollections
278 cval1 = {chainName : chainMult}
279 cval2 = {chainName : legsToInputCollections}
281 setattr(self.
Alg, self.
prop1, cval1)
282 setattr(self.
Alg, self.
prop2, cval2)
286 cval = getattr(self.
Alg, self.
prop1)
291 """Create the ComboHypoTools and add them to the main alg"""
292 if not len(comboToolConfs):
294 confs = [
HypoToolConf( tool )
for tool
in comboToolConfs ]
295 log.debug(
"ComboHypoNode.createComboHypoTools for chain %s, Alg %s with %d tools", chainDict[
"chainName"],self.
Alg.
getName(), len(comboToolConfs))
297 log.debug(
"ComboHypoNode.createComboHypoTools adding %s", conf)
298 tools = self.
Alg.ComboHypoTools
299 self.
Alg.ComboHypoTools = tools + [ conf.confAndCreate( flags, chainDict ) ]
307 """Class to emulate reco sequences with no Hypo"""
308 """It contains an InputMaker and and empty seqAND used for merging"""
309 """It contains empty function to follow the same MenuSequence behaviour"""
311 log.debug(
"Made EmptySequence %s", the_name)
317 makerAlg = CompFactory.InputMakerForRoI(f
"IM{the_name}",
319 RoIsLink =
'initialRoI')
325 self.
ca.addSequence(
seqAND(the_name))
326 self.
ca.addEventAlgo(makerAlg, sequenceName=the_name)
348 return self.
maker.readOutputList()
351 """Connect filter to the InputMaker"""
357 def buildDFDot(self, cfseq_algs, all_hypos, last_step_hypo_nodes, file):
358 cfseq_algs.append(self.
maker)
360 file.write(
" %s[fillcolor=%s]\n"%(self.
maker.Alg.getName(),
algColor(self.
maker.Alg)))
362 return cfseq_algs, all_hypos, last_step_hypo_nodes
365 return "MenuSequence::%s \n Hypo::%s \n Maker::%s \n Sequence::%s \n HypoTool::%s\n"\
366 %(self.
name,
"Empty", self.
maker.Alg.getName(), self.
sequence.Alg.getName(),
"None")
369 """ creates the generator function named as the empty sequence"""
370 def create_sequence(flags, name):
373 create_sequence.__name__ = name
374 globals()[name] = create_sequence
375 return globals()[name]
379 return 'Empty' in o.func.__name__
382 """Class to group reco sequences with the Hypo.
383 By construction it has one Hypo only, which gives the name to this class object"""
385 def __init__(self, flags, selectionCA, HypoToolGen):
386 self.
ca = selectionCA
395 assert len(inputMaker) == 1, f
"{len(inputMaker)} input makers in the ComponentAccumulator"
396 inputMaker = inputMaker[0]
397 assert inputMaker.name.startswith(
"IM"), f
"Input maker {inputMaker.name} name needs to start with 'IM'"
399 input_maker_output = self.
maker.readOutputList()[0]
403 hypoAlg = selectionCA.hypoAcc.getEventAlgos()
404 assert len(hypoAlg) == 1, f
"{len(hypoAlg)} hypo algs in the ComponentAccumulator"
406 hypoAlg.RuntimeValidation = flags.Trigger.doRuntimeNaviVal
408 self.
_name = CFNaming.menuSequenceName(hypoAlg.name)
410 self.
_hypo.addOutput( CFNaming.hypoAlgOutName(hypoAlg.name) )
411 self.
_hypo.setPreviousDecision( input_maker_output )
415 if ROBPrefetching.StepRoI
in flags.Trigger.ROBPrefetchingOptions:
416 for child
in sequence.Members:
417 if ( isinstance(child, CompFactory.ROBPrefetchingAlg)
and
418 input_maker_output
not in child.ROBPrefetchingInputDecisions ):
419 child.ROBPrefetchingInputDecisions.append(input_maker_output)
421 log.debug(
"connecting InputMaker and HypoAlg, adding: InputMaker::%s.output=%s",
422 self.
maker.Alg.name, input_maker_output)
423 log.debug(
"HypoAlg::%s.HypoInputDecisions=%s, HypoAlg::%s.HypoOutputDecisions=%s",
424 self.
hypo.Alg.name, self.
hypo.readInputList()[0],
425 self.
hypo.Alg.name, self.
hypo.readOutputList()[0])
452 return [self.
_hypo.readOutputList()[0]]
455 """Connect filter to the InputMaker"""
456 log.debug(
"connecting %s to inputs of %s", outfilter, self.
maker.Alg.name)
463 def buildDFDot(self, cfseq_algs, all_hypos, last_step_hypo_nodes, file):
464 cfseq_algs.append(self.
maker)
466 file.write(
" %s[fillcolor=%s]\n"%(self.
maker.Alg.getName(),
algColor(self.
maker.Alg)))
468 cfseq_algs.append(self.
_hypo)
470 all_hypos.append(self.
_hypo)
471 return cfseq_algs, all_hypos, last_step_hypo_nodes
474 hyponame = self.
_hypo.Alg.name
476 return "MenuSequence::%s \n Hypo::%s \n Maker::%s \n Sequence::%s \n HypoTool::%s\n"\
481 """Basic class to define the trigger menu """
482 __slots__ =
'name',
'steps',
'nSteps',
'alignmentGroups',
'L1decisions',
'topoMap'
483 def __init__(self, name, ChainSteps, L1decisions, nSteps = None, alignmentGroups = None, topoMap=None):
486 Construct the Chain from the steps
487 Out of all arguments the ChainSteps & L1Thresholds are most relevant, the chain name is used in debug messages
491 if nSteps
is None: nSteps = []
492 if alignmentGroups
is None: alignmentGroups = []
513 log.debug(
"[Chain.__init__] Made Chain %s with seeds: %s ", name, self.
L1decisions)
516 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!"
521 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!"
527 if len(self.
steps)==0:
530 for stepID,step
in enumerate(self.
steps):
531 step_name = step.name
532 if re.search(
'^Step[0-9]_',step_name):
533 step_name = step_name[6:]
534 elif re.search(
'^Step[0-9]{2}_', step_name):
535 step_name = step_name[7:]
536 step.name =
'Step%d_'%(stepID+1)+step_name
538 for iseq, seq
in enumerate(step.sequenceGens):
540 name = seq.func.__name__
541 if re.search(
'Seq[0-9]_',name):
542 newname = re.sub(
'Seq[0-9]_',
'Seq%d_'%(stepID+1), name)
545 step.sequenceGens[iseq]=functools.partial(thisEmpty, flags=
None, name=newname)
553 if len(self.
steps) == 0 :
554 log.error(
"I can't insert empty steps because the chain doesn't have any steps yet!")
556 if len(self.
steps) < start_position :
557 log.error(
"I can't insert empty steps at step %d because the chain doesn't have that many steps!", start_position)
560 chain_steps_pre_split = self.
steps[:start_position]
561 chain_steps_post_split = self.
steps[start_position:]
567 if start_position == 0:
568 next_step_name = chain_steps_post_split[0].name
569 if re.search(
'^Step[0-9]_',next_step_name):
570 next_step_name = next_step_name[6:]
571 elif re.search(
'^Step[0-9]{2}_', next_step_name):
572 next_step_name = next_step_name[7:]
575 prev_chain_dict = chain_steps_post_split[0].stepDicts
577 if len(chain_steps_post_split) == 0:
578 log.error(
"Adding empty steps to the end of a chain (%s)- why would you do this?",self.
name)
580 prev_step_name = chain_steps_pre_split[-1].name
581 next_step_name = chain_steps_post_split[0].name
582 prev_chain_dict = chain_steps_pre_split[-1].stepDicts
586 for stepID
in range(1,n_new_steps+1):
587 new_step_name = prev_step_name+
'_'+empty_step_name+
'%d_'%stepID+next_step_name
589 log.debug(
"Adding empty step %s", new_step_name)
590 steps_to_add += [
ChainStep(new_step_name, chainDicts=prev_chain_dict, comboHypoCfg=ComboHypoCfg, isEmpty=
True)]
592 self.
steps = chain_steps_pre_split + steps_to_add + chain_steps_post_split
598 if len(self.
steps) == 0:
600 mult=[
sum(step.multiplicity)
for step
in self.
steps]
601 not_empty_mult = [m
for m
in mult
if m!=0]
602 if len(not_empty_mult) == 0:
603 log.error(
"checkMultiplicity: Chain %s has all steps with multiplicity =0: what to do?", self.
name)
605 if not_empty_mult.count(not_empty_mult[0]) != len(not_empty_mult):
606 log.error(
"checkMultiplicity: Chain %s has steps with differnt multiplicities: %s", self.
name,
' '.
join(mult))
610 log.error(
"checkMultiplicity: Chain %s has %d multiplicity per step, and %d L1Decisions", self.
name, mult, len(self.
L1decisions))
612 return not_empty_mult[0]
619 stepname =
"last step" if step==
"last" else step.name
620 log.debug(
"Adding topo configurator %s for %s to %s", topoPair[0].__qualname__, topoPair[1],
"step " + stepname)
624 return "\n-*- Chain %s -*- \n + Seeds: %s, Steps: %s, AlignmentGroups: %s "%(\
628 return "\n-*- Chain %s -*- \n + Seeds: %s, Steps: %s, AlignmentGroups: %s \n + Steps: \n %s \n"%(\
635 """Class to describe one step of a chain; if multiplicity is greater than 1, the step is combo/combined. Set one multiplicity value per sequence"""
637 def __init__(self, name, SequenceGens = None, chainDicts = None, comboHypoCfg = ComboHypoCfg , comboToolConfs = None, isEmpty = False, createsGhostLegs = False):
640 if SequenceGens
is None: SequenceGens = []
641 if comboToolConfs
is None: comboToolConfs = []
643 assert chainDicts
is not None,
"Error building a ChainStep without a chainDicts"
657 log.debug(
"Building step %s for chain %s: len=%d multiplicty=%s", name, chainDicts[0][
'chainName'], len(chainDicts),
' '.
join(map(str,[mult
for mult
in self.
multiplicity])))
659 if len(chainDicts) != len(self.
multiplicity)
and 'Jet' not in chainDicts[0][
'signatures']:
660 log.error(
"[ChainStep] SequenceGens: %s",self.
sequenceGens)
661 log.error(
"[ChainStep] chainDicts: %s",chainDicts)
662 log.error(
"[ChainStep] multiplicity: %s",self.
multiplicity)
663 raise RuntimeError(
"[ChainStep] Tried to configure a ChainStep %s with %i multiplicity and %i dictionaries. These lists must have the same size" % (name, len(self.
multiplicity), len(chainDicts)) )
667 if not isinstance(seq, functools.partial):
668 log.error(
"[ChainStep] %s SequenceGens verification failed, sequence %d is not partial function, likely ChainBase.getStep function was not used", self.
name, iseq)
669 log.error(
"[ChainStep] It rather seems to be of type %s trying to print it",
type(seq))
670 raise RuntimeError(
"Sequence is not packaged in a tuple, see error message above" )
674 if len(chainDicts) > 0
and 'signature' in chainDicts[0]:
675 leg_signatures = [step[
'signature']
for step
in chainDicts
if step[
'signature'] !=
'Bjet']
676 if (len(self.
multiplicity) > 0
and leg_signatures.count(
'Jet') == 1)
and (len(
set(leg_signatures)) > 1
and chainDicts[0][
'signatures'].
count(
'Jet') > 1)
and (len(leg_signatures) != 2
or leg_signatures.count(
'MET') == 0):
677 index_jetLeg = leg_signatures.index(
'Jet')
678 self.
multiplicity[index_jetLeg:index_jetLeg] = [1] * (len(chainDicts[0][
'chainMultiplicities']) - len(self.
multiplicity))
679 sig_set =
set([step[
'signature']
for step
in chainDicts])
680 if len(sig_set) == 1
and (
'Jet' in sig_set
or 'Bjet' in sig_set):
682 if len(sig_set) == 2
and (
'Jet' in sig_set
and 'Bjet' in sig_set):
694 """ creation of this step sequences with instantiation of the CAs"""
695 log.debug(
"creating sequences for step %s", self.
name)
704 if 'Jet' in step_dict[
'signatures']
or 'Bjet' in step_dict[
'signatures']:
706 leg_counter += [len(step_dict[
'chainParts'])]
707 elif len(step_dict[
'chainParts']) > 1:
708 log.error(
"[relabelLegIdsForJets] this should only happen for jet chains, but the signatures are %s",step_dict[
'signatures'])
709 raise Exception(
"[relabelLegIdsForJets] leg labelling is probably wrong...")
717 log.debug(
"[relabelLegIdsForJets] leg_counter: %s , onlyjets: %s, multiplicity: %s...",leg_counter, self.
onlyJets, self.
multiplicity)
719 if not has_jets
or len(leg_counter) == len(self.
multiplicity):
722 if len(leg_counter) == 1
or (len(
set(leg_counter)) == 1
and leg_counter[0] == 1):
725 elif len(
set(leg_counter[:-1])) == 1
and leg_counter[0] == 1:
730 for i,nLegParts
in enumerate(leg_counter):
731 oldLegName = self.
stepDicts[i][
'chainName']
732 if re.search(
'^leg[0-9]{3}_',oldLegName):
733 oldLegName = oldLegName[7:]
735 log.error(
"[relabelLegIdsForJets] you told me to relabel the legs for %s",self.
stepDicts)
736 raise Exception(
"[relabelLegIdsForJets] you told me to relabel the legs but this leg doesn't have a legXXX_ name!")
744 lists_of_chainPartNames = []
746 if len(lists_of_chainPartNames) == 0:
747 lists_of_chainPartNames += [[cp[
'chainPartName']
for cp
in step_dict[
'chainParts']]]
749 new_list_of_chainPartNames = [cp[
'chainPartName']
for cp
in step_dict[
'chainParts']]
750 if new_list_of_chainPartNames == lists_of_chainPartNames[-1]:
751 leg_counter -= len(new_list_of_chainPartNames)
752 for chainPart
in step_dict[
'chainParts']:
753 chainPart[
'chainPartIndex'] = leg_counter
758 """ get the gelId from the step dictionary for multi-leg chains"""
762 for istep,step_dict
in enumerate(self.
stepDicts):
763 if step_dict[
'chainName'][0:3] !=
'leg':
767 log.error(
"[getLegIds] chain %s has multiplicities %s but no legs? ",step_dict[
'chainName'], self.
multiplicity)
768 raise Exception(
"[getLegIds] cannot extract leg IDs, exiting.")
770 leg_ids += [
int(step_dict[
'chainName'][3:6])]
782 """ Configure the Combo Hypo Alg and generate the corresponding function, without instantiation which is done in createSequences() """
786 comboNameFromStep = CFNaming.comboHypoName(self.
name)
788 key =
hash((comboNameFromStep, funcName))
789 if key
not in _ComboHypoPool:
791 CHname = tmpCombo.name[:-4]
794 if comboNameFromStep != CHname:
795 log.debug(
"Created ComboHypo with name %s, expected from the step is instead %s. This is accepted only for allowed custom ComboHypos", CHname, comboNameFromStep)
796 _CustomComboHypoAllowed.add(CHname)
797 key =
hash((CHname, funcName))
798 _ComboHypoPool[key] = tmpCombo
799 self.
combo = _ComboHypoPool[key]
800 log.debug(
"Created combo %s with name %s, step comboName %s, key %s", funcName, self.
combo.name, comboNameFromStep,key)
804 chainDict = HLTMenuConfig.getChainDictFromChainName(chainName)
808 """ This is extrapolating the chain legs from the step dictionaries"""
809 legs = [part[
'chainName']
for part
in self.
stepDicts]
813 if self.
combo is not None:
819 return "\n--- ChainStep %s ---\n is Empty, ChainDict = %s "%(self.
name,
' '.
join(map(str, [dic[
'chainName']
for dic
in self.
stepDicts])) )
821 repr_string=
"\n--- ChainStep %s ---\n , multiplicity = %s ChainDict = %s \n + MenuSequenceGens = %s "%\
823 ' '.
join(map(str, [dic[
'chainName']
for dic
in self.
stepDicts])),
826 if self.
combo is not None:
827 repr_string +=
"\n + ComboHypo = %s" % self.
combo.Alg.name
829 repr_string +=
", ComboHypoTools = %s" %(
' '.
join(map(str, [tool.__name__
for tool
in self.
comboToolConfs])))
835 """ Class to handle in-event reco """
836 def __init__(self, name, inputMaker=None, **inputMakerArgs):
837 super( InEventRecoCA, self ).
__init__()
842 assert len(inputMakerArgs) == 0,
"No support for explicitly passed input maker and and input maker arguments at the same time"
845 assert 'name' not in inputMakerArgs,
"The name of input maker is predefined by the name of sequence"
846 args = {
'name':
"IM"+name,
847 'RoIsLink' :
'initialRoI',
848 'RoIs' : f
'{name}RoIs',
849 'RoITool': CompFactory.ViewCreatorInitialROITool(),
850 'mergeUsingFeature':
False}
851 args.update(**inputMakerArgs)
857 self.addSequence( self.
recoSeq )
860 """ Merged CA moving reconstruction algorithms into the right sequence """
862 return self.merge( ca, sequenceName=self.
recoSeq.name )
865 """ Place algorithm in the correct reconstruction sequence """
867 return self.addEventAlgo( algo, sequenceName=self.
recoSeq.name )
875 """ 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 """
876 def __init__(self, name, viewMaker=None, isProbe=False, **viewMakerArgs):
877 super( InViewRecoCA, self ).
__init__()
878 self.
name = name +
"_probe" if isProbe
else name
879 def updateHandle(baseTool, probeTool, handleName):
880 if hasattr(baseTool, handleName)
and getattr(baseTool, handleName).Path!=
"StoreGateSvc+":
881 setattr(probeTool, handleName, getattr(probeTool, handleName).Path +
"_probe")
883 if len(viewMakerArgs) != 0:
884 assert viewMaker
is None,
"No support for explicitly passed view maker and args for EventViewCreatorAlgorithm"
887 assert len(viewMakerArgs) == 0,
"No support for explicitly passed view maker and args for EventViewCreatorAlgorithm"
889 self.
viewMakerAlg = viewMaker.__class__(viewMaker.getName()+
'_probe', **viewMaker._properties)
892 log.debug(f
"InViewRecoCA: Setting InputCachedViews on {self.viewMaker.getName()} to read decisions from tag leg {viewMaker.getName()}: {viewMaker.InputMakerOutputDecisions}")
893 self.
viewMakerAlg.InputCachedViews = viewMaker.InputMakerOutputDecisions
894 updateHandle(viewMakerArgs[
'RoITool'], roiTool,
"RoisWriteHandleKey")
895 if hasattr(viewMakerArgs[
'RoITool'],
"RoiCreator"):
896 updateHandle(viewMakerArgs[
'RoITool'], roiTool,
"ExtraPrefetchRoIsKey")
897 updateHandle(viewMakerArgs[
'RoITool'].RoiCreator, roiTool.RoiCreator,
"RoisWriteHandleKey")
903 assert 'name' not in viewMakerArgs,
"The name of view maker is predefined by the name of sequence"
904 assert 'Views' not in viewMakerArgs,
"The Views is predefined by the name of sequence"
905 assert 'ViewsNodeName' not in viewMakerArgs,
"The ViewsNodeName is predefined by the name of sequence"
906 if 'RoITool' in viewMakerArgs:
907 roiTool = viewMakerArgs[
'RoITool']
909 roiTool = CompFactory.ViewCreatorInitialROITool()
912 args = {
'name': f
'IM_{self.name}',
913 'ViewFallThrough' :
True,
914 'RoIsLink' :
'initialRoI',
916 'InViewRoIs' : f
'{name}RoIs',
917 'Views' : f
'{name}Views'+
'_probe' if isProbe
else f
'{name}Views',
918 'ViewNodeName' : f
'{name}InViews'+
'_probe' if isProbe
else f
'{name}InViews',
919 'RequireParentView' :
False,
920 'mergeUsingFeature' :
False }
921 args.update(**viewMakerArgs)
922 self.
viewMakerAlg = CompFactory.EventViewCreatorAlgorithm(**args)
924 updateHandle(args[
'RoITool'], roiTool,
"RoisWriteHandleKey")
925 if hasattr(args[
'RoITool'],
"RoiCreator"):
926 updateHandle(args[
'RoITool'], roiTool,
"ExtraPrefetchRoIsKey")
927 updateHandle(args[
'RoITool'].RoiCreator, roiTool.RoiCreator,
"RoisWriteHandleKey")
932 """ Merge CA moving reconstruction algorithms into the right sequence """
933 return self.merge( ca, sequenceName=self.
viewsSeq.name )
937 """ Place algorithm in the correct reconstruction sequence """
938 return self.addEventAlgo( algo, sequenceName=self.
viewsSeq.name )
946 """ CA component for MenuSequence sequence """
948 self.
name = name+
"_probe" if isProbe
else name
950 super( SelectionCA, self ).
__init__()
959 def mergeReco(self, recoCA, robPrefetchCA=None, upSequenceCA=None):
960 ''' upSequenceCA is the user CA to run before the recoCA'''
965 ca.addEventAlgo(recoCA.inputMaker(), sequenceName=self.
stepViewSequence.name)
972 """To be used when the hypo alg configuration comes with auxiliary tools/services"""
976 """To be used when the hypo alg configuration does not require auxiliary tools/services"""
978 newname = algo.getName()+
'_probe'
980 self.
hypoAcc.addEventAlgo(algo)
983 """Access hypo algo (or throws)"""
985 assert h
is not None,
"No hypo in SeelectionCA {}".
format(self.
name)
989 """Access Input Maker (or throws)"""
991 assert im
is not None,
"No input maker in SeelectionCA {}".
format(self.
name)