diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/ConditionsToolSetterFastReduction.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/ConditionsToolSetterFastReduction.py index 4c40fe3ef828d8b390e56b12e78b25acbc9cd2a1..2162fa0f2f638fcef1d5f34454c1065c6cb53cce 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/ConditionsToolSetterFastReduction.py +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/ConditionsToolSetterFastReduction.py @@ -8,8 +8,6 @@ from __future__ import print_function from AthenaConfiguration.ComponentFactory import CompFactory -from TrigHLTJetHypo.node import Node - from collections import defaultdict import copy @@ -22,7 +20,8 @@ def is_leaf(node): def is_inner(node): - return node.scenario in ('root', 'and', 'combgen', 'partgen' , 'inserted') + # return node.scenario in ('root', 'and', 'combgen', 'partgen' , 'inserted') + return node.scenario in ('root', 'all', 'inserted') class ConditionsToolSetterFastReduction(object): @@ -227,39 +226,14 @@ class ConditionsToolSetterFastReduction(object): more than one set of shared nodes. These are generated if an "And" not is present in the hypo tree""" - - if node.scenario == 'root': - for cn in node.children: - self._find_shared(cn, shared) - - elif node.scenario == 'and': - for cn in node.children: - shared.append([]) - self._find_shared(cn, shared) - - elif node.scenario == 'partgen': - for cn in node.children: - self._find_shared(cn, shared) - - elif node.scenario == 'inserted': - for cn in node.children: - self._find_shared(cn, shared) - - elif is_leaf(node): - if len(node.children) == 0: - if len(shared) == 0: - shared.append([node]) - else: - shared[-1].append(node) - - else: - for cn in node.children: - self._find_shared(cn, shared) - + if node.scenario == 'simple': + shared.append(node.node_id) else: - raise RuntimeError('%s illegal node. scenario: %s' % - (self.__class__.__name__, - node.scenario)) + shared.append(-1) + + for cn in node.children: + self._find_shared(cn, shared) + return shared @@ -277,7 +251,6 @@ class ConditionsToolSetterFastReduction(object): def _fill_tree_map(self, node, tmap): tmap[node.node_id] = node.parent_id - for cn in node.children: self._fill_tree_map(cn, tmap) @@ -313,7 +286,7 @@ class ConditionsToolSetterFastReduction(object): for cn in node.children: self._check_scenarios(cn) - def mod(self, node): + def mod(self, tree): """Entry point for this module. Modifies a (usually compound) hypo tree node to reduce it to form from whuch the treevector, conditionsVector and @@ -327,22 +300,17 @@ class ConditionsToolSetterFastReduction(object): # navigate the tree filling in node-parent and node- Condtion factory # relations - - # Alg step 1: add root node - root = Node(scenario='root') - root.children = [node] - - self._check_scenarios(root) + self._check_scenarios(tree) # add Condition builders to leaf nodes. - self._set_conditions(root) + self._set_conditions(tree) - # Alg step 2: remove combgen nodes - self._remove_combgen(root) +# # Alg step 2: remove combgen nodes +# self._remove_combgen(root) # Alg step 3: split leaf nodes with multiple Conditions with a # single Condition - self._split_leaves(root) +# self._split_leaves(root) # Alg step 4: remove partgen nodes # single Condition @@ -350,42 +318,20 @@ class ConditionsToolSetterFastReduction(object): # Alg step 5: identify the leaf nodes that are to shared # ie that see the input jet collection. Then remove And nodes shared = [] - slist = self._find_shared(root, shared) - - # remove top stub node if possible - def is_prunable(node): - assert root.scenario == 'root' - return len(root.children) == 1 and is_inner(root.children[0]) + self.shared = self._find_shared(tree, shared) + if shared[-1] != -1: self.shared.append(-1) - if is_prunable(root): - root = root.children[0] - root.scenario - - root.set_ids(node_id=0, parent_id = 0) - - - # would like to pass a list of lists to the C++ tools - # but this cannot be done using Gaudi::Properties. - # use -1 to separate the list sections all entries of which - # are >= 0. - - self.shared = [] - for ilist in slist: - for n in ilist: - self.shared.append(n.node_id) - self.shared.append(-1) - - self.shared = self.shared[:-1] # remnove trailing -1 - + print ('shared ', self.shared) tree_map = {} - self._fill_tree_map(root, tree_map) + self._fill_tree_map(tree, tree_map) + for k, v in tree_map.items(): - log.debug("Tree map debug %s %s", str(k), str(v)) + log.debug("Tree map debug ", str(k), str(v)) self.treeVec = self._map_2_vec(tree_map) conditionsMap = {} - self._fill_conditions_map(root, conditionsMap) + self._fill_conditions_map(tree, conditionsMap) self.conditionsVec = self._map_2_vec(conditionsMap) # make a config tool and provide it with condition makers @@ -394,10 +340,10 @@ class ConditionsToolSetterFastReduction(object): config_tool.treeVector = self.treeVec config_tool.sharedVector = self.shared - nodestr = 'n%dp%d' % (node.node_id, node.parent_id) + nodestr = 'n%dp%d' % (tree.node_id, tree.parent_id) helper_tool = self._get_tool_instance('helper', extra=nodestr) helper_tool.HypoConfigurer = config_tool - helper_tool.node_id = node.node_id - helper_tool.parent_id = node.parent_id + helper_tool.node_id = tree.node_id + helper_tool.parent_id = tree.parent_id self.tool = helper_tool diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/ConditionsToolSetterHT.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/ConditionsToolSetterHT.py index 4af4a67d4c26bca4901590eafb9cb99c7b3d5878..bc866daca9b8a002ccf706229377d0cc9007bafe 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/ConditionsToolSetterHT.py +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/ConditionsToolSetterHT.py @@ -49,7 +49,7 @@ class ConditionsToolSetterHT(object): return rep - def mod(self, node): + def mod(self, anode): """Entry point for this module. HT specific. Set up TrigJetConditionConfig_ht, @@ -60,13 +60,14 @@ class ConditionsToolSetterHT(object): # navigate the tree filling in node-parent and node- Condtion factory # relations - - # root = Node(scenario='root') - # root.children = [node] - - # self._check_scenarios(root) - # root is an alias for node - as in ConditionTooSetterFastReduction + node = None + if anode.scenario == 'root': + assert len(anode.children)==1 + node =anode.children[0] + else: + node = anode + assert node.scenario == 'ht' print (node) diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/NodeSplitterVisitor.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/NodeSplitterVisitor.py new file mode 100644 index 0000000000000000000000000000000000000000..8a6c8187a022bdce144f3f611a58134a89305e7c --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/NodeSplitterVisitor.py @@ -0,0 +1,133 @@ +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + +"""Instantiates TrigJetHypoToolConfig_fastreduction AlgTool +from a hypo tree.""" + +from __future__ import print_function + +from TrigHLTJetHypo.node import Node + +import copy + +from AthenaCommon.Logging import logging +log = logging.getLogger( 'ConditionsToolSetterVisitor' ) + +def is_leaf(node): + return node.scenario in ('simple', 'etaet', 'dijet', 'qjet') + + +def is_inner(node): + # return node.scenario in ('root', 'and', 'combgen', 'partgen' , 'inserted') + return node.scenario in ('root', 'all', 'inserted') + + +class NodeSplitterVisitor(object): + + """Visitor to set instantiated AlgTools to a jet hypo tree""" + + + def mod(self, node): + + new_children = [] + for c in node.children: + if c.scenario == 'simple': + for c_a in c.conf_attrs: + n_c = copy.deepcopy(c) + n_c.conf_attrs = [c_a] + new_children.append(n_c) + else: + new_children.append(c) + + + node.children = new_children + +if __name__ == '__main__': + from chainDict2jetLabel import chainDict2jetLabel + from TrigHLTJetHypo.treeVisitors import TreeParameterExpander + from TriggerMenuMT.HLTMenuConfig.Menu.ChainDefInMenu import ChainProp + from TriggerMenuMT.HLTMenuConfig.Menu.DictFromChainName import dictFromChainName + from TriggerMenuMT.HLTMenuConfig.Menu.Physics_pp_run3_v1 import ( + SingleJetGroup, + MultiJetGroup) + from TrigHLTJetHypo.ChainLabelParser import ChainLabelParser + + + def testChainDictMaker(): + chain_props = [ + ChainProp(name='HLT_j260_320eta490_L1J75_31ETA49', + groups=SingleJetGroup), + + ChainProp(name='HLT_j80_j60_L1J15', + l1SeedThresholds=['FSNOSEED']*2, groups=MultiJetGroup), + + ChainProp(name='HLT_2j80_3j60_L1J15', + l1SeedThresholds=['FSNOSEED']*2, groups=MultiJetGroup), + + + ChainProp(name='HLT_j0_HTSEP1000htSEP100etSEP0eta320_L1J15', + l1SeedThresholds=['FSNOSEED'], groups=MultiJetGroup), + + + ChainProp(name='HLT_j80_0eta240_2j60_320eta490_j0_dijetSEP80j1etSEP0j1eta240SEP80j2etSEP0j2eta240SEP700djmass_L1J20', + l1SeedThresholds=['FSNOSEED']*3, + groups=MultiJetGroup), + + ChainProp(name='HLT_j0_vbenfSEP30etSEP34mass35SEP50fbet_L1J20', + l1SeedThresholds=['FSNOSEED'], + groups=MultiJetGroup), + + ChainProp(name='HLT_10j40_L1J15', + l1SeedThresholds=['FSNOSEED'], groups=MultiJetGroup), + + + # ChainProp(name='HLT_j70_j50 _0eta490_invm1000j50_dphi20_deta40_L1J20', + # l1SeedThresholds=['FSNOSEED']*2, + # groups=MultiJetGroup), + + ] + + result = [] + for cp in chain_props: + chain_dict = dictFromChainName(cp) + result.append((cp.name, chain_dict)) + + return result + + + dicts = testChainDictMaker() + for d in dicts: + print('') + # print (d) + + print ('\n chain_labels:\n') + + for d in dicts: + print (d[0]) + l = (chainDict2jetLabel(d[1])) + print (l) + print () + + + parser = ChainLabelParser(l) + rootless_tree = parser.parse() + + # add a root node so that split simple nodes cann connect. + tree = Node('root') + tree.children = [rootless_tree] + tree.node_id = 0 + tree.parent_id = 0 + rootless_tree.tree_top = False + tree.tree_top = True + + #expand strings of cuts to a cut dictionary + visitor = TreeParameterExpander() + tree.accept(visitor) + + visitor = NodeSplitterVisitor() + tree.accept(visitor) + tree.set_ids(0, 0) + + print ('\n - final dump ' + d[0]) + print ('label ', l, '\n') + print (tree.dump()) + print ('\n - end dump ') diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py index f433cd6f8264ba9b78597035d0a7c2a1a1c851a0..e5be52b755bf1dd20bce953e4d71c5f63d19bad0 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py @@ -12,9 +12,10 @@ from TrigHLTJetHypo.ConditionsToolSetterHT import ConditionsToolSetterHT from TrigHLTJetHypo.chainDict2jetLabel import chainDict2jetLabel -# from TrigHLTJetHypo.chainDict2jetLabel import make_simple_comb_label as make_simple_label # TIMING studies - from TrigHLTJetHypo.ChainLabelParser import ChainLabelParser +from TrigHLTJetHypo.node import Node +from TrigHLTJetHypo.NodeSplitterVisitor import NodeSplitterVisitor + from AthenaCommon.Logging import logging log = logging.getLogger( 'TrigJetHypoToolConfig' ) @@ -25,13 +26,24 @@ def trigJetHypoToolHelperFromDict_(chain_label, parser = ChainLabelParser(chain_label, debug=False) - tree = parser.parse() + rootless_tree = parser.parse() + + # add a root node so that split simple nodes cann connect. + tree = Node('root') + tree.children = [rootless_tree] + tree.node_id = 0 + tree.parent_id = 0 + rootless_tree.tree_top = False + tree.tree_top = True #expand strings of cuts to a cut dictionary visitor = TreeParameterExpander() tree.accept(visitor) log.debug(visitor.report()) + visitor = NodeSplitterVisitor() + tree.accept(visitor) + # tell the child nodes who their parent is. tree.set_ids(node_id=0, parent_id=0) @@ -48,7 +60,7 @@ def trigJetHypoToolHelperFromDict_(chain_label, toolSetter.mod(tree) tool = toolSetter.tool - log.debug(visitor.report()) + log.debug(toolSetter.report()) return tool diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/chainDict2jetLabel.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/chainDict2jetLabel.py index 5f87f4e0f1b6c47715f357bdc8f38ab9ed03f418..c1e28d3aaf21eab59af17ce70fe90327ab454a5c 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/chainDict2jetLabel.py +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/chainDict2jetLabel.py @@ -72,63 +72,6 @@ def _make_simple_label(chain_parts): return label -def _make_simple_partition_label(chain_dict): - """Marshal information deom the selected chainParts to create a - 'simple_partition' label. - """ - - cps = chain_dict['chainParts'] - if not (_select_simple_chainparts(cps)): - raise NotImplementedError( - 'chain fails substring selection: not "simple": %s' % ( - chain_dict['chainName'])) - - label = 'simplepartition([' - for cp in cps: - smcstr = str(cp['smc']) - if smcstr == 'nosmc': - smcstr = '' - for i in range(int(cp['multiplicity'])): - # condition_str = '(%set,%s,%s)' % (str(cp['threshold']), - # str(cp['etaRange']), - # smcstr,) - condition_str = '(%set,%s' % (str(cp['threshold']), - str(cp['etaRange']),) - if smcstr: - condition_str += ',%s)' - else: - condition_str += ')' - label += condition_str - label += '])' - return label - - -def _make_simple_comb_label(chain_dict): - """Marshal information deom the selected chainParts to create a - 'simple' label NOTE: DO NOT USE this method. - THIS CHAINLABEL IS FOR TIMING STUDIES ONLY. - It has n^2 behaviour rather than n obtained using _make_simple_label. - """ - - cps = chain_dict['chainParts'] - if not (_select_simple_chainparts(cps)): - raise NotImplementedError( - 'chain fails substring selection: not "simple": %s' % ( - chain_dict['chainName'])) - - simple_strs = [] - - for cp in cps: - print(cp) - simple_strs.append(_make_simple_label([cp])) - - label = 'combgen([(%d)]' % len(cps) - for s in simple_strs: - label += ' %s ' % s - label += ')' - return label - - def _args_from_scenario(scenario): separator = 'SEP' @@ -161,7 +104,7 @@ def _make_vbenf_label(chain_parts): assert scenario.startswith('vbenf') args = _args_from_scenario(scenario) if not args: - return 'and([]simple([(50et)(70et)])combgen([(2)] dijet([(900djmass, 26djdphi)])))' + return 'all([]simple([(50et)(70et)])dijet([(900djmass, 26djdphi)] all[], all[])))' arg_res = [ re.compile(r'(?P<lo>\d*)(?P<key>fbet)(?P<hi>\d*)'), re.compile(r'(?P<lo>\d*)(?P<key>mass)(?P<hi>\d*)'), @@ -199,20 +142,16 @@ def _make_vbenf_label(chain_parts): assert len(args) == 0 return """ - and + all ( [] simple ( [(%(etlo).0fet, 500neta)(%(etlo).0fet, peta500)] ) - combgen + dijet ( - [(10et, 0eta320)] - dijet - ( - [(%(masslo).0fdjmass, 26djdphi)] - ) + [(%(masslo).0fdjmass, 26djdphi)] simple ( [(10et, 0eta320)(20et, 0eta320)] @@ -281,16 +220,12 @@ def _make_dijet_label(chain_parts): assert len(args) == 0 return """ - combgen( - [(2)(%(j1etlo).0fet, %(j1etalo).0feta%(j1etahi).0f) - (%(j1etlo).0fet, %(j1etalo).0feta%(j1etahi).0f) - ] - - dijet( - [(%(djmasslo).0fdjmass)]) - simple([(%(j1etlo).0fet, %(j1etalo).0feta%(j1etahi).0f) - (%(j2etlo).0fet, %(j2etalo).0feta%(j2etahi).0f)]) - )""" % argvals + all([] + dijet( + [(%(djmasslo).0fdjmass)]) + simple([(%(j1etlo).0fet, %(j1etalo).0feta%(j1etahi).0f) + (%(j2etlo).0fet, %(j2etalo).0feta%(j2etahi).0f)]) + )""" % argvals def _make_agg_label(chain_parts): @@ -363,45 +298,6 @@ def _make_agg_label(chain_parts): return result - -def _make_combinationsTest_label(chain_parts): - """make test label for combinations helper with two simple children.""" - - assert len(chain_parts) == 1 - scenario = chain_parts[0]['hypoScenario'] - - assert scenario == 'combinationsTest' - - - - return """ - combgen( - [(2)(20et, 0eta320)] - - simple([(40et, 0eta320) (50et, 0eta320)]) - simple([(35et, 0eta240) (55et, 0eta240)]) - )""" - - -def _make_partitionsTest_label(chain_parts): - """make test label for combinations helper with two simple children.""" - - assert len(chain_parts) == 1 - scenario = chain_parts[0]['hypoScenario'] - - assert scenario == 'partitionsTest' - - - - return """ - partgen( - [(20et, 0eta320)] - - simple([(40et, 0eta320) (50et, 0eta320)]) - simple([(35et, 0eta240) (55et, 0eta240)]) - )""" - - def chainDict2jetLabel(chain_dict): """Entry point to this Module. Return a chain label according to the value of cp['hypoScenario'], where cp is an element of list/ @@ -420,8 +316,6 @@ def chainDict2jetLabel(chain_dict): 'agg': _make_agg_label, 'vbenf': _make_vbenf_label, 'dijet': _make_dijet_label, - 'combinationsTest': _make_combinationsTest_label, - 'partitionsTest': _make_partitionsTest_label, } # chain_part - scenario association @@ -446,7 +340,7 @@ def chainDict2jetLabel(chain_dict): if nlabels == 1: return labels[0] if nlabels == 2: alabel = """\ -and([] +all([] %s %s)""" % (tuple(labels)) return alabel diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/testChainDictMaker.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/testChainDictMaker.py index 312abad23137946c8b0fcaf66f80a6857404749e..21a0691446e324f9bfe6078a2373c848803a3c4e 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/testChainDictMaker.py +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/testChainDictMaker.py @@ -41,6 +41,8 @@ def testChainDictMaker(): ChainProp(name='HLT_10j40_L1J15', l1SeedThresholds=['FSNOSEED'], groups=MultiJetGroup), + ChainProp(name='HLT_j0_aggSEP1000htSEP30etSEP0eta320_L1J20', + groups=SingleJetGroup), # ChainProp(name='HLT_j70_j50 _0eta490_invm1000j50_dphi20_deta40_L1J20', # l1SeedThresholds=['FSNOSEED']*2, diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/treeVisitors.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/treeVisitors.py index c4c92e78b55762cf8f2cc0f55ca33b174d348923..a226fec52b7ccdc72db13870755088eb32be2343 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/treeVisitors.py +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/treeVisitors.py @@ -98,34 +98,6 @@ class TreeBuilder(object): return self.tree -class TreeToBooleanExpression(object): - """visit a hypo tree. If boolean scenarios are present, build a - boolean expression string.""" - - def __init__(self): - self.stack = [] - - def mod(self, node): - if node.scenario == 'not': - self.stack.append(' ! ') - return - - if node.scenario == 'and': - self.stack.append(' x ') - return - - if node.scenario == 'or': - self.stack.append(' + ') - return - - self.stack.append(' %s ' %node.tool.name()) - - def report(self): - s = '%s: ' % self.__class__.__name__ - while self.stack: s += self.stack.pop() - return s.strip() - - class ConditionsDictMaker(object): """Convert parameter string into dictionary holding low, high window @@ -328,12 +300,12 @@ class TreeParameterExpander_dijet(object): node.conf_attrs = d def report(self): - return '%s: ' % self.__class__.__name__ + '\n'.join(self.msgs) + return '%s: ' % self.__class__.__name__ + '\n'.join(self.msgs) -class TreeParameterExpander_combgen(object): +class TreeParameterExpander_all(object): """Convert parameter string into a dictionary holding low, high window - cut vals. Specialistaion for the combgen Tool + cut vals. Specialistaion for the "all" node parameter strings look like '40m,100deta200, 50dphi300' """ @@ -343,66 +315,18 @@ class TreeParameterExpander_combgen(object): def mod(self, node): - ok = True # status flag - # the group size must be the first attribute, then the conditions. - # size_re = re.compile(r'^\((\d+)\)') - parameters = node.parameters[:] - # m = size_re.match(parameters) - # if m is None: - # self.msgs.append('Error') - # return - - # node.conf_attrs = {'groupSize':int(m.groups()[0])} - # remove goup info + 2 parentheses - # parameters = parameters[len(m.groups()[0])+2:] - - cdm = ConditionsDictMaker() - d, error, msgs = cdm.makeDict(parameters) - self.msgs.extend(msgs) - node.conf_attrs = d - - - if ok: - self.msgs = ['All OK'] - else: - self.msgs.append('Error') - - - def report(self): - return '%s: ' % self.__class__.__name__ + '\n'.join(self.msgs) - - -class TreeParameterExpander_partgen(object): - """Convert parameter string into a dictionary holding low, high window - cut vals. Specialistaion for the combgen Tool - - parameter strings look like '40m,100deta200, 50dphi300' - """ - - def __init__(self): - self.msgs = [] - - def mod(self, node): + if node.parameters != '' : + self.msgs.append( + 'Error, all node with parameters ' + node.parameters) + return - parameters = node.parameters[:] - - cdm = ConditionsDictMaker() + node.conf_attrs = '' - d, error, msgs = cdm.makeDict(parameters) + self.msgs = ['All OK'] - self.msgs.extend(msgs) - node.conf_attrs = d - - if not error: - self.msgs = ['All OK'] - else: - self.msgs.append('Error') - - return d, error, msgs - def report(self): - return '%s: ' % self.__class__.__name__ + '\n'.join(self.msgs) + return '%s: ' % self.__class__.__name__ + '\n'.join(self.msgs) class TreeParameterExpander_null(object): @@ -418,23 +342,18 @@ class TreeParameterExpander_null(object): return '%s: ' % self.__class__.__name__ + '\n'.join(self.msgs) - class TreeParameterExpander(object): """Class to expand node.parameters string. Delegates to specialised expanders.""" router = { 'z': TreeParameterExpander_null, + 'root': TreeParameterExpander_null, 'simple': TreeParameterExpander_simple, - 'simplepartition': TreeParameterExpander_simple, 'ht': TreeParameterExpander_simple, 'dijet': TreeParameterExpander_dijet, 'qjet': TreeParameterExpander_simple, - 'not': TreeParameterExpander_null, - 'and': TreeParameterExpander_null, - 'or': TreeParameterExpander_null, - 'combgen': TreeParameterExpander_combgen, - 'partgen': TreeParameterExpander_partgen, + 'all': TreeParameterExpander_all, 'agree': TreeParameterExpander_null, } @@ -442,9 +361,9 @@ class TreeParameterExpander(object): self.expander = None def mod(self, node): + self.expander = self.router[node.scenario]() self.expander.mod(node) - print (self.expander.report()) def report(self): return self.expander.report()