def group_horizontal_links(all_nodes): """group direct horizontal links (por)""" h_groups = UnorderedGroup() excluded_nodes = OrderedSet() for i in all_nodes: if not i.directions.get("w"): # find leftmost nodes excluded_nodes.add(i) if i.directions.get("e"): h_group = HorizontalGroup([i]) _add_nodes_horizontally(i, h_group, excluded_nodes) if len(h_group) > 1: h_groups.append(h_group) else: h_groups.append(i) else: h_groups.append(i) # now handle circles (we find them by identifying left-over nodes that still have "e" links) for i in all_nodes: if not i in excluded_nodes: excluded_nodes.add(i) if i.directions.get("e"): h_group = HorizontalGroup([i]) _add_nodes_horizontally(i, h_group, excluded_nodes) if len(h_group) > 1: h_groups.append(h_group) else: h_groups.append(i) else: h_groups.append(i) _fix_link_inheritance(h_groups, OrderedSet()) return h_groups
def _fix_link_inheritance(group, excluded_nodes): """recursive helper function to mark for a group and every sub-group into which directions it is linked. The function adds the links as .directions to the group and its sub-groups, and carries a set of excluded_nodes to remember which links should not be inherited upwards""" from copy import deepcopy if hasattr(group, "uid"): excluded_nodes.add(group) else: for i in group: locally_excluded_nodes = OrderedSet() _fix_link_inheritance(i, locally_excluded_nodes) for d in i.directions: if d not in group.directions: group.directions[d] = OrderedSet() for node in i.directions[d]: group.directions[d].add(node) for i in locally_excluded_nodes: excluded_nodes.add(i) # now delete all links to excluded nodes dirs_copy = group.directions.copy() for d in dirs_copy: for node in deepcopy(dirs_copy[d]): if node in excluded_nodes: group.directions[d].remove(node) if not group.directions[d]: del group.directions[d]
def group_other_links(all_groups): """group other horizontal links (native modules)""" excluded_nodes = OrderedSet() _group_other_links(all_groups, excluded_nodes, "O") _group_other_links(all_groups, excluded_nodes, "o") _fix_link_inheritance(all_groups, OrderedSet()) return all_groups
def unify_links(nodenet, node_id_list): """create a proxy representation of the node space to simplify bi-directional links. This structure is an ordered set of proxy nodes (DisplayNode) with directions. Each direction is marked by its key (such as "n"), and followed by a list of nodes that are linked in that direction. The nodes are sorted by their index (as marked in the node net). Arguments: nodenet: the nodenet that we are working on node_id_list: a list of node ids to be processed """ node_index = OrderedDict([(i, DisplayNode(i)) for i in node_id_list]) for node_id in node_id_list: node = nodenet.get_node(node_id) vertical_only = True for gate_type in node.get_gate_types(): direction = { "sub": "s", "ret": "w", "cat": "ne", "sym": "nw", "sur": "n", "por": "e", "exp": "sw", "ref": "se", "gen": "n" }.get(gate_type, "o") if direction: # "o" is for unknown gate types for link in node.get_gate(gate_type).get_links(): target_node_id = link.target_node.uid if target_node_id in node_index: # otherwise, the link points outside the current nodespace and will be ignored here if direction not in node_index[node_id].directions: node_index[node_id].directions[ direction] = OrderedSet() node_index[node_id].directions[direction].add( node_index[target_node_id]) inverse = INVERSE_DIRECTIONS[direction] if inverse not in node_index[ target_node_id].directions: node_index[target_node_id].directions[ inverse] = OrderedSet() node_index[target_node_id].directions[inverse].add( node_index[node_id]) if direction != 'n' and direction != 's': vertical_only = False node_index[node_id].stackable = vertical_only # finally, let us sort all node_id_list in the direction groups for node_id in node_index: for direction in node_index[node_id].directions: node_index[node_id].directions[direction] = list( node_index[node_id].directions[direction]) node_index[node_id].directions[direction].sort( key=lambda i: nodenet.get_node(i.uid).index) return UnorderedGroup(node_index.values())
def update_flow_graphs(self, node_uids=None): if self.is_flowbuilder_active: return self.flowfunctions = [] startpoints = [] endpoints = [] pythonnodes = set() toposort = nx.topological_sort(self.flowgraph) self.flow_toposort = toposort for uid in toposort: node = self.flow_module_instances.get(uid) if node is not None: if node.implementation == 'python': pythonnodes.add(uid) if node.is_input_node(): startpoints.append(uid) if node.is_output_node(): endpoints.append(uid) graphs = [] for enduid in endpoints: ancestors = nx.ancestors(self.flowgraph, enduid) node = self.flow_module_instances[enduid] if ancestors or node.inputs == []: path = [uid for uid in toposort if uid in ancestors] + [enduid] if path: graphs.append(path) # worldadapter_names = [] # if self.worldadapter_instance is not None: # worldadapter_names += self.worldadapter_instance.get_available_flow_datasources() + self.worldadapter_instance.get_available_flow_datatargets() flowfunctions = {} floworder = OrderedSet() for idx, graph in enumerate(graphs): # split graph in parts: # node_uids = [uid for uid in graph if uid not in worldadapter_names] node_uids = [uid for uid in graph] nodes = [self.get_node(uid) for uid in node_uids] paths = self.split_flow_graph_into_implementation_paths(nodes) for p in paths: floworder.add(p['hash']) if p['hash'] not in flowfunctions: func, dang_in, dang_out = self.compile_flow_subgraph([n.uid for n in p['members']], use_unique_input_names=True) if func: flowfunctions[p['hash']] = {'callable': func, 'members': p['members'], 'endnodes': set([nodes[-1]]), 'inputs': dang_in, 'outputs': dang_out} else: flowfunctions[p['hash']]['endnodes'].add(nodes[-1]) for funcid in floworder: self.flowfunctions.append(flowfunctions[funcid]) self.logger.debug("Compiled %d flowfunctions" % len(self.flowfunctions))
def group_horizontal_links(all_nodes): """group direct horizontal links (por)""" h_groups = UnorderedGroup() excluded_nodes = OrderedSet() for i in all_nodes: if not i.directions.get("w"): # find leftmost nodes excluded_nodes.add(i) if i.directions.get("e"): h_group = HorizontalGroup([i]) _add_nodes_horizontally(i, h_group, excluded_nodes) if len(h_group) > 1: h_groups.append(h_group) else: h_groups.append(i) else: h_groups.append(i) # now handle circles (we find them by identifying left-over nodes that still have "e" links) for i in all_nodes: if i not in excluded_nodes: excluded_nodes.add(i) if i.directions.get("e"): h_group = HorizontalGroup([i]) _add_nodes_horizontally(i, h_group, excluded_nodes) if len(h_group) > 1: h_groups.append(h_group) else: h_groups.append(i) else: h_groups.append(i) _fix_link_inheritance(h_groups, OrderedSet()) return h_groups