def focus(self, node): ''' prunes graph to include only the given node and its dependencies. ''' edges_by_source = {} for e in self.edges: if e.source in edges_by_source: edges_by_source[e.source].append(e) else: edges_by_source[e.source] = [e] edges_to_save = OrderedSet() # edge objects nodes_to_save = OrderedSet() # label strings q = deque() if node.label in edges_by_source: q.append(node.label) nodes_to_save.add(node.label) while len(q) > 0: source = q.pop() if source in edges_by_source: for e in edges_by_source[source]: q.append(e.target) edges_to_save.add(e) nodes_to_save.add(e.target) self.edges = list(edges_to_save) self.nodes = [n for n in self.nodes if n.label in nodes_to_save]
def center(self, node): ''' prunes graph to include only (1) the given node, (2) its dependencies, and nodes that depend on it. ''' edges_by_source = {} for e in self.edges: if e.source in edges_by_source: edges_by_source[e.source].append(e) else: edges_by_source[e.source] = [e] edges_by_target = {} for e in self.edges: if e.target in edges_by_target: edges_by_target[e.target].append(e) else: edges_by_target[e.target] = [e] edges_to_save = OrderedSet() # edge objects nodes_to_save = OrderedSet() # label strings q = deque() if node.label in edges_by_source: q.append(node.label) nodes_to_save.add(node.label) while len(q) > 0: source = q.pop() if source in edges_by_source: for e in edges_by_source[source]: q.append(e.target) edges_to_save.add(e) nodes_to_save.add(e.target) q = deque() if node.label in edges_by_target: q.append(node.label) nodes_to_save.add(node.label) while len(q) > 0: target = q.pop() if target in edges_by_target: for e in edges_by_target[target]: q.append(e.source) edges_to_save.add(e) nodes_to_save.add(e.source) self.edges = list(edges_to_save) self.nodes = [n for n in self.nodes if n.label in nodes_to_save]
def set_module_depth(self, depth): """ group resources belonging to modules into a single node, to simplify presentation. No claims made for this code. It's garbage! """ depth += 1 # account for [root] module def is_too_deep(modules): if len(modules) >= depth and modules[0] != 'root': return True def find_edge(edges, e): for edge in edges: if e.source == edge.source and e.target == edge.target and e.edge_type == edge.edge_type: return True return False # find DotNodes at too great a depth. too_deep = [n for n in self.nodes if is_too_deep(n.modules)] # generate ModuleNodes to stand-in for DotNodes at too great a depth. placeholders = [] for n in too_deep: match = False for p in placeholders: if p.is_standin(n.modules): match = True break if match == False: placeholders.append(ModuleNode(n.modules[:depth])) # create replacement edges new_edges = [] for e in self.edges: src_mods = DotNode._label_to_modules(e.source) tgt_mods = DotNode._label_to_modules(e.target) if is_too_deep(src_mods) and is_too_deep(tgt_mods): continue elif is_too_deep(src_mods): for p in placeholders: if p.is_standin(src_mods): replace = True for ne in new_edges: if ne.source == p.label and ne.target == e.target: replace = False break if replace: new_edges.append( DotEdge(p.label, e.target, fmt=Format(''))) break elif is_too_deep(tgt_mods): for p in placeholders: if p.is_standin(tgt_mods): replace = True for ne in new_edges: if ne.source == e.source and ne.target == p.label: replace = False break if replace: new_edges.append( DotEdge(e.source, p.label, fmt=Format(''))) break else: new_edges.append(e) # make sure we haven't got any duplicate edges. final_edges = [] for e in new_edges: if not find_edge(final_edges, e): final_edges.append(e) self.edges = final_edges # add placeholder nodes, remove nodes beyond specified module_depth. self.nodes = list( OrderedSet(placeholders) | (OrderedSet(self.nodes) - OrderedSet(too_deep)))