def render(self, filename): g = AGraph(strict=False, directed=True) # create nodes for frame_id, node in self.callers.items(): label = "{ %s }" % node g.add_node(frame_id, shape='Mrecord', label=label, fontsize=13, labelfontsize=13) # create edges for frame_id, node in self.callers.items(): child_nodes = [] for child_id in node.child_methods: child_nodes.append(child_id) g.add_edge(frame_id, child_id) # order edges l to r if len(child_nodes) > 1: sg = g.add_subgraph(child_nodes, rank='same') sg.graph_attr['rank'] = 'same' prev_node = None for child_node in child_nodes: if prev_node: sg.add_edge(prev_node, child_node, color="#ffffff") prev_node = child_node g.layout() g.draw(path=filename, prog='dot') print("callviz: rendered to %s" % filename) self.clear()
class FSM(object): '''Finite State Machine''' def __init__(self, finite_states): self.states = finite_states nodes = { state : [] for state in finite_states } self.graph = AGraph(nodes, directed=True, strict=False) self.edgesize = len(nodes) / 5.0 def validate(self, *args): for arg in args: assert arg in self.states, arg def transition(self, src, dest, label='', **kwargs): self.validate(src, dest) self.graph.add_edge(src, dest, label=label, len=self.edgesize, **kwargs) def success(self, src, dest, label=''): self.transition(src, dest, label, color='green') def fail(self, src, dest, label=''): self.transition(src, dest, label, color='red') def save(self,name='graph',prog='dot'): self.graph.layout(prog=prog) self.graph.draw('{}.png'.format(name))
def gen_graph_bundle_dep(exp_file, idx_map): G = AGraph(directed=True, strict=True) G.graph_attr['splines'] = 'true' G.graph_attr['overlap'] = 'false' #G.graph_attr['ordering'] = 'out' #G.graph_attr['concentrate'] = 'false' keys = [key for key in idx_map.keys()] values = [] for lst in idx_map.values(): for item in lst: if not item in values: values.append(item) kvp_list = [] for key in idx_map.keys(): for val in idx_map[key]: kvp_list.append((key, val)) G.add_nodes_from(keys, color='green', style='filled') for val in values: if val.count('#exist'): G.add_node(val, color='yellow', style='filled') elif val.count('#miss'): G.add_node(val, color='red', style='filled') #G.add_nodes_from(values, color = 'red', style = 'filled') G.add_edges_from(kvp_list, color='blue') G.layout(prog='sfdp') G.draw(exp_file)
def render(self, filename): g = AGraph(strict=False, directed=True) # create nodes for frame_id, node in self.callers.items(): label = "{ %s }" % node g.add_node(frame_id, shape='Mrecord', label=label, fontsize=13, labelfontsize=13) # create edges for frame_id, node in self.callers.items(): child_nodes = [] for child_id in node.child_methods: child_nodes.append(child_id) g.add_edge(frame_id, child_id) # order edges l to r if len(child_nodes) > 1: sg = g.add_subgraph(child_nodes, rank='same') sg.graph_attr['rank'] = 'same' prev_node = None for child_node in child_nodes: if prev_node: sg.add_edge(prev_node, child_node, color="#ffffff") prev_node = child_node g.layout() g.draw(path=filename, prog='dot') print("rendered to %s" % filename) self.clear()
def draw(self, filename='bst.png'): from pygraphviz import AGraph G = AGraph() G.node_attr['shape'] = 'circle' none_count = 0 def __draw_edge(node0: self.Node, node1: self.Node): """ 画一条从node0到node1边 """ nonlocal none_count if node1: G.add_edge(node0.key, node1.key) else: none_node = f'None{none_count}' G.add_node(none_node, shape='point') G.add_edge(node0.key, none_node) none_count += 1 def __draw(root: self.Node): """ 画出以root为根的子树 """ if root is None: return __draw(root.left) __draw_edge(root, root.left) __draw_edge(root, root.right) __draw(root.right) __draw(self.root) G.layout('dot') G.draw(filename)
def plot(table_names=None): """ Plot relationships between columns and tables using Graphviz. Parameters ---------- table_names : iterable of str, optional Names of UrbanSim registered tables to plot. Defaults to all registered tables. Returns ------- graph : pygraphviz.AGraph PyGraphviz graph object. """ if not table_names: # Default to all registered tables. table_names = simulation.list_tables() graph = AGraph(directed=True) graph.graph_attr['fontname'] = 'Sans' graph.graph_attr['fontsize'] = 28 graph.node_attr['shape'] = 'box' graph.node_attr['fontname'] = 'Sans' graph.node_attr['fontcolor'] = 'blue' graph.edge_attr['weight'] = 2 # Add each registered table as a subgraph with columns as nodes. for table_name in table_names: subgraph = graph.add_subgraph(name='cluster_' + table_name, label=table_name, fontcolor='red') table = simulation.get_table(table_name) for column_name in table.columns: full_name = table_name + '.' + column_name subgraph.add_node(full_name, label=column_name) # Iterate over computed columns to build nodes. for key, wrapped_col in simulation._COLUMNS.items(): table_name = key[0] column_name = key[1] # Combine inputs from argument names and argument default values. args = list(wrapped_col._argspec.args) if wrapped_col._argspec.defaults: default_args = list(wrapped_col._argspec.defaults) else: default_args = [] inputs = args[:len(args) - len(default_args)] + default_args # Create edge from each input column to the computed column. for input_name in inputs: full_name = table_name + '.' + column_name graph.add_edge(input_name, full_name) graph.layout(prog='dot') return graph
def networkx_visualize(self, filename): dgraph = AGraph(strict=False, directed=True) for n in self.subgraph.get_nodes(): self.subgraph._add_nx_subgraph(dgraph, n) dgraph.add_edges_from(self.subgraph.get_viz_edge_list()) dgraph.layout("dot") dgraph.draw(f"{filename}.pdf", format="pdf")
def draw_workflow(filename, workflow): dot = AGraph(directed=True, strict=False) # (comment="Computing scheme") for i, n in workflow.nodes.items(): dot.add_node(i, label="{0} \n {1}".format(n.foo.__name__, _format_arg_list(n.bound_args.args, None))) for i in workflow.links: for j in workflow.links[i]: dot.add_edge(i, j[0], j[1].name) # , headlabel=j[1].name, labeldistance=1.8) dot.layout(prog="dot") dot.draw(filename)
def visualize(self, name='lp'): ls = self.edge_list() G = AGraph(directed=True) for (_id, label, next_id, next_label, edge_label) in ls: G.add_node(_id, label=label) G.add_node(next_id, label=next_label) G.add_edge(_id, next_id, label=edge_label) G.layout(prog='dot') G.draw(name + '.png')
def startGraph(): # We maintain this globally to make it accessible, pylint: disable=global-statement global graph if Options.shallCreateGraph(): try: from pygraphviz import AGraph # pylint: disable=I0021,import-error graph = AGraph(name = "Optimization", directed = True) graph.layout() except ImportError: warning("Cannot import pygraphviz module, no graphing capability.")
def __call__(self): self.request.response.setHeader('Content-Type', 'image/svg+xml') self.request.response.setHeader('Content-Disposition', 'inline; filename=%s.svg' % \ self.context.getId()) tfile = tempfile.NamedTemporaryFile(suffix='.svg') gv = generate_gv(self.context) ag = AGraph(string=gv) ag.layout() ag.draw(path=tfile, format='svg', prog='dot') tfile.seek(0) return tfile.read()
def draw_workflow(filename, workflow): dot = AGraph(directed=True) # (comment="Computing scheme") for i, n in workflow.nodes.items(): dot.add_node(i, label="{0} \n {1}".format( n.foo.__name__, _format_arg_list(n.bound_args.args, None))) for i in workflow.links: for j in workflow.links[i]: dot.add_edge(i, j[0]) dot.layout(prog='dot') dot.draw(filename)
def startGraph(): # We maintain this globally to make it accessible, pylint: disable=global-statement global graph if Options.shallCreateGraph(): try: from pygraphviz import AGraph # pylint: disable=I0021,import-error graph = AGraph(name="Optimization", directed=True) graph.layout() except ImportError: warning("Cannot import pygraphviz module, no graphing capability.")
def get_image(): global TIMESTAMP ip_dict = { } # maps source-destination IP pairs to their number of occurrences trace_file = open(LOG_PATH, newline='') local_timestamp = TIMESTAMP for line in trace_file.readlines(): split_line = line.split('|') if len(split_line) == 4: timestamp = float(split_line[0].split('[')[1].split(']')[0]) if timestamp > local_timestamp: src_dst_pair = (split_line[1], split_line[2]) if src_dst_pair in ip_dict.keys(): ip_dict[src_dst_pair] = ip_dict[src_dst_pair] + 1 else: ip_dict[src_dst_pair] = 1 local_timestamp = timestamp if local_timestamp > TIMESTAMP: ip_graph = AGraph(directed=True) for (src_ip, dst_ip), packet_count in ip_dict.items(): ip_graph.add_edge(src_ip, dst_ip, color='brown', label=packet_count, labelangle=45, len=1.95) ip_graph.layout() ip_graph.draw('graph.png') TIMESTAMP = local_timestamp graph_img = Image.open('graph.png') graph_img.thumbnail((720, 720)) background_image = Image.new('RGB', SIZE, color=(255, 255, 255)) x = round((SIZE[0] / 2.0) - graph_img.width) y = round((SIZE[1] / 4.0) - (graph_img.height / 4.0)) background_image.paste(graph_img, (x, y)) return background_image
class Visualizer: def __init__(self, hsm): self.graph = AGraph(strict=False, directed=True, name=type(hsm).__name__) self._load_transitions(hsm) def _load_transitions(self, hsm, group=None): prefix = group + "." if group else "" nodes = [] for t in hsm.transitions: # if origin is an HSM we have to connect from it's final node if issubclass(t["from"], HSM): u = prefix + t["from"].__name__ + ".FINAL" else: u = prefix + t["from"].__name__ nodes.append(u) # if we connect to an HSM we must create a new substructure and load from the hsm recursively if issubclass(t["to"], HSM): sub = t["to"].__name__ v = prefix + sub + "." + t["to"].init_state.__name__ nodes.append(v) self._load_transitions(t["to"], group=sub) # there is always only one FAILED elif issubclass(t["to"], FAILED): v = FAILED.__name__ else: v = prefix + t["to"].__name__ nodes.append(v) # finally add it to the graph self.graph.add_edge(u, v, label=self._get_condition_string( t["condition"])) sg = self.graph.add_subgraph(nodes, name="cluster_" + prefix, style="dotted") #TODO not done here yet def _get_condition_string(self, cond): if isinstance(cond, dict): return str(list(cond.keys())[0].name) + ": " + str( list(cond.values())[0]) elif callable(cond): return cond.__name__ return cond.name def save_graph(self, filename): self.graph.layout(prog="dot") self.graph.draw(filename)
def render_local(self, filename): """Renders the OBST image locally using pygraphviz.""" # Get the graph information node_list, edge_list = self.__generate_image() # Generate the graph from pygraphviz import AGraph G=AGraph(strict=True,directed=True) # Create a graph for node in node_list: G.add_node(node) for edge in edge_list: G.add_edge(edge[0], edge[1]) G.layout('dot') # Set hierarchical layout G.draw(filename) # Save the image.
def to_dot(self, filename, edges): from pygraphviz import AGraph dot = AGraph(directed=True) for n in edges.keys(): dot.add_node(str(n)) if lib.qcgc_arena_get_blocktype(ffi.cast( "cell_t *", n)) not in [lib.BLOCK_BLACK, lib.BLOCK_WHITE]: node = dot.get_node(str(n)) node.attr['color'] = 'red' for n in edges.keys(): if edges[n] is not None: dot.add_edge(str(n), str(edges[n])) dot.layout(prog='dot') dot.draw(filename)
def to_dot(self, filename, edges): from pygraphviz import AGraph dot = AGraph(directed=True) for n in edges.keys(): dot.add_node(str(n)) if lib.qcgc_arena_get_blocktype(ffi.cast("cell_t *", n)) not in [ lib.BLOCK_BLACK, lib.BLOCK_WHITE]: node = dot.get_node(str(n)) node.attr['color'] = 'red' for n in edges.keys(): if edges[n] is not None: dot.add_edge(str(n), str(edges[n])) dot.layout(prog='dot') dot.draw(filename)
def crear_grafo_invocaciones(datos_csv): '''[Autor: Ivan Litteri] [Ayuda: crea grafo.svg y grafo.png]''' g = AGraph(directed=True, rankdir='LR') for funcion in datos: g.add_node(funcion) for i in datos[funcion]["invocaciones"]: g.add_edge((funcion, i)) g.layout(prog='dot') g.draw('grafo.svg') g.draw('grafo.png')
def toSVG(B, name): if B: graph = AGraph(toDot(B)) layout = graph.layout(prog="dot") draw = graph.draw("{}.svg".format(name)) else: print("Give me a better tree")
def run(self): options = self.options filename = self.arguments[0] if self.content: content = u'\n'.join(self.content) ofilename = filename + '.' + self.outputformat else: content = open(filename).read().decode(options.get('encoding','utf-8')) ofilename = os.path.splitext(filename)[0] + '.' + self.outputformat g = AGraph(string=content) g.layout(prog='dot') opath = os.path.join(OUTPUT_DIR, ofilename) g.draw(opath, 'png') self.arguments[0] = opath return super(GraphvizBlock, self).run()
def gen_graph_res_idx(exp_file, idx_map): keys = [key for key in idx_map.keys()] values = [] for val in idx_map.values(): if not val in values: values.append(val) G = AGraph(directed=True, strict=True) G.graph_attr['splines'] = 'true' G.graph_attr['overlap'] = 'false' #G.graph_attr['ordering'] = 'out' #G.graph_attr['concentrate'] = 'false' G.add_nodes_from(keys, color='green', style='filled') G.add_nodes_from(values, color='red', style='filled') G.add_edges_from(idx_map.items(), color='blue') G.layout(prog=GRAPH_PROG) G.draw(exp_file)
def render_image(self, filename): """Renders the graph image locally using pygraphviz.""" # Create a graph G=AGraph(directed=False) # Add nodes for node in self.nodes: G.add_node(node) # Add edges for edge in self.edges: G.add_edge(edge[0], edge[1], color='blue') # Give layout and draw. G.layout('circo') G.draw(filename) # Save the image. # Display the output image. os.system("gwenview %s&" % filename)
def render_image(self, filename): """Renders the graph image locally using pygraphviz.""" # Create a graph G = AGraph(directed=False) # Add nodes for node in self.nodes: G.add_node(node) # Add edges for edge in self.edges: G.add_edge(edge[0], edge[1], color='blue') # Give layout and draw. G.layout('circo') G.draw(filename) # Save the image. # Display the output image. os.system("gwenview %s&" % filename)
def run(self): options = self.options filename = self.arguments[0] if self.content: content = u'\n'.join(self.content) ofilename = filename + '.' + self.outputformat else: content = open(filename).read().decode( options.get('encoding', 'utf-8')) ofilename = os.path.splitext(filename)[0] + '.' + self.outputformat g = AGraph(string=content) g.layout(prog='dot') opath = os.path.join(OUTPUT_DIR, ofilename) g.draw(opath, 'png') self.arguments[0] = opath return super(GraphvizBlock, self).run()
def draw_workflow(filename, workflow, paint=None): dot = AGraph(directed=True) # (comment="Computing scheme") dot.node_attr['style'] = 'filled' for i, n in workflow.nodes.items(): dot.add_node(i, label="{0} \n {1}".format( n.foo.__name__, _format_arg_list(n.bound_args.args, None))) x = dot.get_node(i) if paint: paint(x, n.foo.__name__) for i in workflow.links: for j in workflow.links[i]: dot.add_edge(i, j[0]) dot.layout(prog='dot') dot.draw(filename)
def render_image(node_list, edge_list): # Generate the graph from pygraphviz import AGraph G=AGraph(strict=False,directed=True) # Create a graph for node in node_list: G.add_node(node) for edge in edge_list: G.add_edge(edge[0], edge[1]) G.layout('dot') # Set hierarchical layout filename = str(time()) postfix = 0 while exists(filename+str(postfix)+".png"): postfix+=1 filename += str(postfix) + ".png" G.draw(filename) # Save the image. with open(filename, "rb") as handle: return xmlrpclib.Binary(handle.read())
def render_image(node_list, edge_list): # Generate the graph from pygraphviz import AGraph G = AGraph(strict=False, directed=True) # Create a graph for node in node_list: G.add_node(node) for edge in edge_list: G.add_edge(edge[0], edge[1]) G.layout('dot') # Set hierarchical layout filename = str(time()) postfix = 0 while exists(filename + str(postfix) + ".png"): postfix += 1 filename += str(postfix) + ".png" G.draw(filename) # Save the image. with open(filename, "rb") as handle: return xmlrpclib.Binary(handle.read())
def write_graph(probs, path): graph = AGraph(directed=True) next_label = 0 labels = {} for from_state, to_states in probs.iteritems(): if from_state not in labels: labels[from_state] = next_label next_label += 1 for to_state in to_states: if to_state not in labels: labels[to_state] = next_label next_label += 1 for label in xrange(next_label): graph.add_node(label, fillcolor="blue", label="", style="filled") for from_state, to_states in probs.iteritems(): for to_state, prob in to_states.iteritems(): graph.add_edge(labels[from_state], labels[to_state], label="%.2g" % prob) # prog: neato (default), dot, twopi, circo, fdp or nop. graph.layout() graph.draw(path)
def _drawmap(fs, rulename=None): """Draw a map of the firewalls and their connections based on their interfaces. If nulename is specified, draw also the sources and dests for a that rule. #TODO: implement this """ A = AGraph() A.graph_attr['bgcolor'] = 'transparent' # A.graph_attr['size'] = '8,5' # Draw hosts for h in fs.hosts: A.add_node(h.hostname) if h.network_fw in (1, True, '1'): # network firewall f = Node(A, h.hostname) f.attr['color'] = 'red' # Draw nets for net in fs.networks: A.add_node(net.name) poly = Node(A, net.name) poly.attr['shape'] = 'polygon' poly.attr['sides'] = '8' # Connect hosts to nets for host in fs.hosts: on_Internet = True for net in fs.networks: if host in net: on_Internet = False A.add_edge(host.hostname, net.name) e = Edge(A, host.hostname, net.name) e.attr['label'] = host.iface e.attr['fontsize'] = '6' # If a host is not in any configured net, it's on the Internet if on_Internet: A.add_edge(host.hostname, 'Internet') e = Edge(A, host.hostname, 'Internet') e.attr['label'] = host.iface e.attr['fontsize'] = '6' A.layout(prog='circo') return A
def to_agraph(self, idempotents=True) -> AGraph: graph = AGraph(strict=False, directed=True) for generator, data in self.graph.nodes(data=True): graph.add_node(str(generator.key) + '[' + str(data['grading'])[1:-1] + ']', shape='box', fontname='Arial') for x, y, (left, right), d in self.graph.edges(keys=True, data=True): c = d['c'] x_grading = self.graph.nodes(data=True)[x]['grading'] y_grading = self.graph.nodes(data=True)[y]['grading'] if not idempotents and self.is_idempotent_edge_data( left, c, right): continue graph.add_edge(str(x.key) + '[' + str(x_grading)[1:-1] + ']', str(y.key) + '[' + str(y_grading)[1:-1] + ']', label=' ' + str((left, c, right)) + ' ', dir='forward', color=self.edge_color(left, c, right), fontname='Arial', decorate=True) graph.layout('dot') return graph
def draw(self): """Draw graph with graphviz and save it to self.config['filename']""" default_gv_attributes = { 'node': {'shape': 'rect', 'fontname': 'PT Sans'}, 'edge': {'arrowhead': 'open', 'arrowtail': 'open', 'fontname': 'PT Sans'}, 'graph': {'fontname': 'PT Sans'} } directed = self.config.get('directed', False) attrs = self.config.get('gv_attributes', default_gv_attributes) g = AGraph(directed=directed, strict=False) for k, v in attrs.get('graph', {}).items(): g.graph_attr[k] = v for k, v in attrs.get('node', {}).items(): g.node_attr[k] = v for k, v in attrs.get('edge', {}).items(): g.edge_attr[k] = v for section in self.sections: if section.type and section.type in attrs: section_attrs = {**attrs[section.type], **section.gv} else: section_attrs = section.gv title = wrap_title(section.title) g.add_node(section.full_name, label=title, **section_attrs) for rel in self.relations: if rel.type and rel.type in attrs: rel_attrs = {**attrs[rel.type], **rel.gv} else: rel_attrs = rel.gv g.add_edge(rel.parent.full_name, rel.child.full_name, **rel_attrs) g.layout(prog='dot') output = self.config.get('filename', 'project_graph.png') g.draw(output)
def draw(self, path="graph.pdf"): # TODO add edges for shared state try: from pygraphviz import AGraph def add_graph(g: AGraph, layer_graph: tx.Graph, cluster): for node in layer_graph.nodes: # HTML for record nodes https://graphviz.org/doc/info/shapes.html#top g.add_node(f"{cluster}_{node.name}", shape="none", margin=0, label=tx.utils.vizstyle(node)) for node in layer_graph.nodes: for other_node in layer_graph.edges_out[node]: g.add_edge(f"{cluster}_{node.name}", f"{cluster}_{other_node.name}") dg = AGraph(directed=True) if self.run_graph and self.run_graph.nodes: dg.add_subgraph(name="cluster_run", label="run") g = dg.subgraphs()[-1] add_graph(g, self.run_graph, cluster="run") if self.train_graph and self.train_graph.nodes: dg.add_subgraph(name="cluster_train", label="train") g = dg.subgraphs()[-1] add_graph(g, self.train_graph, "train") if self.eval_graph and self.eval_graph.nodes: dg.add_subgraph(name="cluster_eval", label="eval") g = dg.subgraphs()[-1] add_graph(g, self.eval_graph, cluster="eval") dg.layout(prog="dot") dg.draw(path=path) except ImportError: raise ImportError("Could't find required pygraphviz module")
def create_graph(filename, layout="dot", use_singularity=False): """ :param filename: should end in .png or .svg or .dot If extension is .dot, only the dot file is created. This is useful if you have issues installing graphviz. If so, under Linux you could use our singularity container see github.com/cokelaer/graphviz4all """ from bioconvert.core.registry import Registry rr = Registry() try: if filename.endswith(".dot") or use_singularity is True: raise from pygraphviz import AGraph dg = AGraph(directed=True) for a, b in rr.get_conversions(): dg.add_edge(a, b) dg.layout(layout) dg.draw(filename) except: dot = """ strict digraph{ node [label="\\N"]; """ nodes = set([item for items in rr.get_conversions() for item in items]) for node in nodes: dot += "\"{}\";\n".format(node) for a, b in rr.get_conversions(): dot += "\"{}\" -> \"{}\";\n".format(a, b) dot += "}\n" from easydev import TempFile from bioconvert import shell dotfile = TempFile(suffix=".dot") with open(dotfile.name, "w") as fout: fout.write(dot) dotpath = "" if use_singularity: from bioconvert.core.downloader import download_singularity_image singfile = download_singularity_image( "graphviz.simg", "shub://cokelaer/graphviz4all:v1", "4288088d91c848e5e3a327282a1ab3d1") dotpath = "singularity run {} ".format(singfile) on_rtd = environ.get('READTHEDOCS', None) == 'True' if on_rtd: dotpath = "" ext = filename.rsplit(".", 1)[1] cmd = "{}dot -T{} {} -o {}".format(dotpath, ext, dotfile.name, filename) try: shell(cmd) except: import os os.system(cmd)
def dot_layout(cy_elements): """ Get a CyElements object and augment it (in-place) with positions, widths, heights, and spline data from a dot based layout. Returns the object. """ elements = cy_elements.elements g = AGraph(directed=True, strict=False) # make transitive relations appear top to bottom # TODO: make this not specific to leader example elements = list(elements) nodes_by_id = dict( (e["data"]["id"], e) for e in elements if e["group"] == "nodes" ) order = [ (nodes_by_id[e["data"]["source"]], nodes_by_id[e["data"]["target"]]) for e in elements if e["group"] == "edges" and e["data"]["obj"] in ('reach', 'le') ] elements = topological_sort(elements, order, lambda e: e["data"]["id"]) # add nodes to the graph for e in elements: if e["group"] == "nodes": g.add_node(e["data"]["id"], label=e["data"]["label"].replace('\n', '\\n')) # TODO: remove this, it's specific to leader_demo weight = { 'reach': 10, 'le': 10, 'id': 1, } constraint = { 'pending': False, } # add edges to the graph for e in elements: if e["group"] == "edges": g.add_edge( e["data"]["source"], e["data"]["target"], e["data"]["id"], weight=weight.get(e["data"]["obj"], 0), #constraint=constraint.get(e["data"]["obj"], True), ) # add clusters clusters = defaultdict(list) for e in elements: if e["group"] == "nodes" and e["data"]["cluster"] is not None: clusters[e["data"]["cluster"]].append(e["data"]["id"]) for i, k in enumerate(sorted(clusters.keys())): g.add_subgraph( name='cluster_{}'.format(i), nbunch=clusters[k], ) # now get positions, heights, widths, and bsplines g.layout(prog='dot') for e in elements: if e["group"] == "nodes": attr = g.get_node(e["data"]["id"]).attr e["position"] = _to_position(attr['pos']) e["data"]["width"] = 72 * float(attr['width']) e["data"]["height"] = 72 * float(attr['height']) elif e["group"] == "edges": attr = g.get_edge(e["data"]["source"], e["data"]["target"], e["data"]["id"]).attr e["data"].update(_to_edge_position(attr['pos'])) g.draw('g.png') return cy_elements
class UmlPygraphVizDiagram: """ Creates a diagram similar to the class diagrams and objects diagrams from UML using pygraphviz """ def __init__(self): logging.basicConfig() self.graph = AGraph(directed=True, strict=False) self.graph.node_attr["shape"] = "record" self.graph.graph_attr["fontsize"] = "8" self.graph.graph_attr["fontname"] = "Bitstream Vera Sans" self.graph.graph_attr["label"] = "" self.connected_nodes = set() self.described_nodes = set() def _add_node(self, node_id, node_label): self.graph.add_node(node_id, label=node_label) def add_class_node(self, class_name, attributes): self.described_nodes.add(class_name) label = "<{<b>%s</b> | %s }>" % ( class_name, "<br align='left'/>".join(attributes).strip() + "<br align='left'/>", ) self.subgraph.add_node(graphviz_id(class_name), label=label) def add_object_node(self, object_name, class_name, attributes): self.described_nodes.add(object_name) if class_name: label = "<{<b><u>%s (%s)</u></b>| %s }>" % ( object_name, class_name, "<br align='left'/>".join(attributes) + "<br align='left'/>", ) else: label = "<{<b><u>%s</u></b>| %s }>" % ( object_name, "<br align='left'/>".join(attributes) + "<br align='left'/>", ) self.subgraph.add_node(graphviz_id(object_name), label=label) def add_edge(self, src, dst, name): self.connected_nodes.add(src) self.connected_nodes.add(dst) self.graph.add_edge(graphviz_id(src), graphviz_id(dst), label=name, arrowhead="open") def add_cardinality_edge(self, src, dst, name, card): self.connected_nodes.add(src) self.connected_nodes.add(dst) self.graph.add_edge( graphviz_id(src), graphviz_id(dst), label=name, arrowhead="open", labeldistance=2.0, headlabel=card + "..." + card, labelangle=-65.0, ) def add_min_cardinality_edge(self, src, dst, name, card): self.connected_nodes.add(src) self.connected_nodes.add(dst) self.graph.add_edge( graphviz_id(src), graphviz_id(dst), label=name, arrowhead="open", labeldistance=2.0, headlabel=card + "...*", labelangle=-65.0, ) def add_max_cardinality_edge(self, src, dst, name, card): self.connected_nodes.add(src) self.connected_nodes.add(dst) self.graph.add_edge( graphviz_id(src), graphviz_id(dst), label=name, arrowhead="open", labeldistance=2.0, headlabel="0..." + card, labelangle=-65.0, ) def add_min_max_cardinality_edge(self, src, dst, name, min, max): self.connected_nodes.add(src) self.connected_nodes.add(dst) self.graph.add_edge( graphviz_id(src), graphviz_id(dst), label=name, arrowhead="open", labeldistance=2.0, headlabel=min + "..." + max, labelangle=-65.0, ) def add_list_edge(self, src, dst, name): self.connected_nodes.add(src) self.connected_nodes.add(dst) self.graph.add_edge( graphviz_id(src), graphviz_id(dst), label=name, arrowtail="ediamond", dir="back", headlabel="0...*", labeldistance=2.0, labelfontcolor="black", labelangle=-65.0, ) # self.graph.add_edge(graphviz_id(src), graphviz_id(dst),label=name,arrowtail="ediamond", dir="back",headlabel="0...*", taillabel=(dst.split(":")[1])+"s",labeldistance=2.0,labelfontcolor="black") def add_symmetric_edge(self, src, dst, name): self.connected_nodes.add(src) self.connected_nodes.add(dst) self.graph.add_edge(graphviz_id(src), graphviz_id(dst), label=name, arrowhead="none") def add_functional_edge(self, src, dst, name): self.connected_nodes.add(src) self.connected_nodes.add(dst) self.graph.add_edge( graphviz_id(src), graphviz_id(dst), label=name, arrowhead="open", headlabel="1...1", taillabel="0...*", labeldistance=2.0, labelfontcolor="black", labelangle=-65.0, ) def add_inversefunctional_edge(self, src, dst, name): self.connected_nodes.add(src) self.connected_nodes.add(dst) self.graph.add_edge( graphviz_id(src), graphviz_id(dst), label=name, arrowhead="open", headlabel="0...*", taillabel="1...1", labeldistance=2.0, labelfontcolor="black", labelangle=-65.0, ) def add_equivalentclass_edge(self, src, dst): self.connected_nodes.add(src) self.connected_nodes.add(dst) self.graph.add_edge( graphviz_id(src), graphviz_id(dst), label="\<\<equivalentClass\>\>", arrowhead="none", style="dashed" ) def add_unionof_edge(self, src, dst): self.connected_nodes.add(src) self.connected_nodes.add(dst) self.graph.add_edge( graphviz_id(src), graphviz_id(dst), label="\<\<unionOf\>\>", arrowhead="open", style="dashed" ) def add_oneof_edge(self, src, dst): self.connected_nodes.add(src) self.connected_nodes.add(dst) self.graph.add_edge( graphviz_id(src), graphviz_id(dst), label="\<\<instanceOf\>\>", arrowhead="open", style="dashed", dir="back" ) def add_subclass_edge(self, src, dst): self.connected_nodes.add(src) self.connected_nodes.add(dst) self.graph.add_edge(graphviz_id(src), graphviz_id(dst), arrowhead="empty") def set_label(self, label): self.graph.graph_attr["label"] = label def start_subgraph(self, graph_name): self.subgraph = self.graph.add_subgraph(name="cluster_%s" % graphviz_id(graph_name)) self.subgraph.graph_attr["label"] = graph_name def add_undescribed_nodes(self): s = self.connected_nodes - self.described_nodes for node in s: self.graph.add_node(graphviz_id(node), label=node) def write_to_file(self, filename_dot): f = open(filename_dot, "w") f.write(self.graph.string()) print("dot file created: " + filename_dot) def visualize(self, filename, namespaceList=None): self.graph.layout(prog="dot") self.graph.draw(filename) if filename.endswith(".svg"): self._add_links_to_svg_file(filename, namespaceList) print("graphic file created: " + filename) def _add_links_to_svg_file(self, output, namespaceList=None): # SVG Datei anpassen svg_string = open(output).read() # Titel der SVG Datei anpassen svg_string = svg_string.replace("%3", output) # Hyperlinks mit den Internetseiten hinzufügen for ns in namespaceList: namespace = str(ns[0]) # Präfix des Namespaces url = str(ns[1]) # URL des Namespaces regex_str = """%s:(\w+)""" % namespace regex = re.compile(regex_str) svg_string = regex.sub("""<a xlink:href='%s\\1'>%s:\\1</a>""" % (url, namespace), svg_string) # Datei schreiben svg_file = open(output, "w") svg_file.write(svg_string) svg_file.close()
def get_graphviz_layout(input_subgraph, ref_chain=[], aim_chain=[], freq_min=1, draw_all=False): print('SD') ps = AGraph(directed=True) ps.graph_attr['rankdir'] = 'LR' ps.graph_attr['mode'] = 'hier' nodes = delete_nodes(ref_chain, input_subgraph[1], freq_min) print('Number of nodes: ', end='') if draw_all == False: print(len(nodes)) elif draw_all == True: print(len(input_subgraph[1])) cluster_main = ps.add_subgraph() cluster_main.graph_attr['rank'] = '0' for i in range(len(ref_chain)): shape = 'circle' if ref_chain[i] in aim_chain: cluster_main.add_node(ref_chain[i], shape=shape, color='red') else: cluster_main.add_node(ref_chain[i], shape=shape, color='pink') for i in input_subgraph[0]: if i in aim_chain or i in ref_chain: continue if i in nodes: ps.add_node(str(i)) continue else: if draw_all == True: ps.add_node(str(i), color='grey') continue for i in input_subgraph[1]: color = 'black' try: if ref_chain.index(i[1]) - ref_chain.index(i[0]) == 1: color = 'red' ps.add_edge(str(i[0]), str(i[1]), color=color, penwidth=str(math.sqrt(i[2]))) continue except ValueError: pass if i[2] < freq_min: if draw_all == True: ps.add_edge(str(i[0]), str(i[1]), color='grey', penwidth=str(math.sqrt(i[2])), constraint='false') continue elif i[0] in nodes and i[1] in nodes: ps.add_edge(str(i[0]), str(i[1]), color=color, penwidth=str(math.sqrt(i[2]))) elif draw_all == True: ps.add_edge(str(i[0]), str(i[1]), color='grey', penwidth=str(math.sqrt(i[2])), constraint='false') ps.layout(prog='dot') positions = {n: n.attr['pos'] for n in ps.nodes()} edge_points = {edge: edge.attr['pos'] for edge in ps.edges()} return positions, edge_points
def draw(self, path): try: from pygraphviz import AGraph def vizstyle(layer_obj): # HTML for record nodes https://graphviz.org/doc/info/shapes.html#top dtype = layer_obj.dtype.name if layer_obj.dtype is not None else None label = f"<<TABLE BORDER=\"0\"" \ f" CELLPADDING=\"2\"" \ f" CELLSPACING=\"0\">" \ f"<TR><TD BGCOLOR=\"BLACK\"" \ f" BORDER=\"1\"" \ f" COLOR=\"BLACK\"" \ f" VALIGN=\"BOTTOM\">" \ f"<FONT COLOR=\"WHITE\"><B>{type(layer_obj).__name__}</B></FONT>" \ f"</TD><TD BORDER=\"1\">{layer_obj.name}</TD></TR>" \ f"<TR>" \ f"<TD BORDER=\"1\"" \ f" BGCOLOR=\"#aec4c7\"" \ f" COLOR=\"BLACK\"" \ f" ALIGN=\"RIGHT\">" \ f"units" \ f"</TD><TD BORDER=\"1\"" \ f" COLOR=\"BLACK\"" \ f" ALIGN=\"LEFT\">" \ f"{layer_obj.n_units}</TD></TR>" \ f"<TR>" \ f"<TD BORDER=\"1\" " \ f" BGCOLOR=\"#aec4c7\"" \ f" ALIGN=\"RIGHT\">dtype</TD>" \ f"<TD BORDER=\"1\"" \ f" ALIGN=\"LEFT\">{dtype}</TD></TR>" \ f"</TABLE>>" return label viz_graph = AGraph(directed=True) for node in self.dependency_iter(): if node not in viz_graph: viz_graph.add_node( node.name, shape="none", margin=0, label=vizstyle(node)) # , label=vizstyle(node)) for other_node in self.edges_out[node]: viz_graph.add_edge(node.name, other_node.name) dependencies = dependency_graph(self.nodes) state_deps = [ node for node in dependencies.nodes if not dependencies.edges_in[node] and len(dependencies.edges_out[node]) > 1 ] for node in state_deps: if hasattr(node, "name"): name = node.name else: # might be a tf.Variable try: name = node.deref().name except AttributeError as e: name = str(type(node).__name__) viz_graph.add_node(name, color="red", shape="box") layers = dependencies.edges_out[node] for layer in layers: viz_graph.add_edge(name, layer.name, color="red") viz_graph.layout(prog="dot") viz_graph.draw(path=path) except ImportError: raise ImportError("Could't find required pygraphviz module")
def dot_layout(cy_elements): """ Get a CyElements object and augment it (in-place) with positions, widths, heights, and spline data from a dot based layout. Returns the object. """ elements = cy_elements.elements g = AGraph(directed=True, strict=False) # make transitive relations appear top to bottom # TODO: make this not specific to leader example elements = list(elements) nodes_by_id = dict( (e["data"]["id"], e) for e in elements if e["group"] == "nodes") order = [(nodes_by_id[e["data"]["source"]], nodes_by_id[e["data"]["target"]]) for e in elements if e["group"] == "edges" and e["data"]["obj"] in ('reach', 'le')] elements = topological_sort(elements, order, lambda e: e["data"]["id"]) # add nodes to the graph for e in elements: if e["group"] == "nodes": g.add_node(e["data"]["id"], label=e["data"]["label"].replace('\n', '\\n')) # TODO: remove this, it's specific to leader_demo weight = { 'reach': 10, 'le': 10, 'id': 1, } constraint = { 'pending': False, } # add edges to the graph for e in elements: if e["group"] == "edges": g.add_edge( e["data"]["source"], e["data"]["target"], e["data"]["id"], weight=weight.get(e["data"]["obj"], 0), #constraint=constraint.get(e["data"]["obj"], True), ) # add clusters clusters = defaultdict(list) for e in elements: if e["group"] == "nodes" and e["data"]["cluster"] is not None: clusters[e["data"]["cluster"]].append(e["data"]["id"]) for i, k in enumerate(sorted(clusters.keys())): g.add_subgraph( name='cluster_{}'.format(i), nbunch=clusters[k], ) # now get positions, heights, widths, and bsplines g.layout(prog='dot') for e in elements: if e["group"] == "nodes": attr = g.get_node(e["data"]["id"]).attr e["position"] = _to_position(attr['pos']) e["data"]["width"] = 72 * float(attr['width']) e["data"]["height"] = 72 * float(attr['height']) elif e["group"] == "edges": attr = g.get_edge(e["data"]["source"], e["data"]["target"], e["data"]["id"]).attr e["data"].update(_to_edge_position(attr['pos'])) g.draw('g.png') return cy_elements
from pygraphviz import AGraph ip_dict = {} # maps source-destination IP pairs to their number of occurrences trace_path = '/var/log/syslog' trace_file = open(trace_path, newline='') for line in trace_file.readlines(): split_line = line.split('|') if len(split_line) == 4: src_dst_pair = (split_line[1], split_line[2]) if src_dst_pair in ip_dict.keys(): ip_dict[src_dst_pair] = ip_dict[src_dst_pair] + 1 else: ip_dict[src_dst_pair] = 1 ip_graph = AGraph(directed=True) for (src_ip, dst_ip), packet_count in ip_dict.items(): ip_graph.add_edge(src_ip, dst_ip, color='brown', label=packet_count, labelangle=45, len=1.75) ip_graph.layout() ip_graph.draw('graph.png')
def pdf_export(self, id, **kw): app = DBSession.query(Application).get(id) log.info("pdf_export: id=%s" % (id)) action_by_id = {} for a in DBSession.query(Action): action_by_id[a.action_id] = asterisk_string(a.name) prev_context = None nodes = [] edges = [] label = [] for s in ( DBSession.query(Scenario).filter(Scenario.app_id == id).order_by(Scenario.context).order_by(Scenario.step) ): if prev_context is None: # First loop log.debug(" * * * First context") prev_context = s.context elif prev_context != s.context: # Next context log.debug(" * * * Write context %s" % prev_context) nodes.append(mk_label(label, action_by_id)) label = [] prev_context = s.context edges += mk_edges(s) label.append(s) log.debug(" * * * Write last %s" % prev_context) nodes.append(mk_label(label, action_by_id)) dir_tmp = mkdtemp() dot = open(dir_tmp + "/graphviz.dot", "w") dot.write("digraph g {\n") for n in nodes: dot.write(asterisk_string(n)) log.debug("edges: %s" % edges) for e in edges: dot.write(asterisk_string(e)) dot.write("}\n") dot.close() fn = "%s/%s.pdf" % (dir_tmp, app.name) from pygraphviz import AGraph g = AGraph(dir_tmp + "/graphviz.dot") log.debug(" * * * AGraph encoding %s" % g.encoding) g.layout(prog="dot") g.draw(fn) import os try: st = os.stat(fn) f = open(fn) except: flash(u"Erreur à la génération du fichier PDF", "error") redirect("") rh = response.headers rh["Pragma"] = "public" # for IE rh["Expires"] = "0" rh["Cache-control"] = "must-revalidate, post-check=0, pre-check=0" # for IE rh["Cache-control"] = "max-age=0" # for IE rh["Content-Type"] = "application/pdf" rh["Content-Disposition"] = str( (u'attachment; filename="%s.pdf"; size=%d;' % (app.name, st.st_size)).encode("utf-8") ) rh["Content-Transfer-Encoding"] = "binary" return f.read()
class Plugin: def __init__(self, title="System"): self.schematic = AGraph( directed=True, label=title, rankdir='LR', splines='true' ) self.nodes = [] self.edges = [] self.outputs = {} self.ip_outputs = {} #sources def write_stimulus(self, stream): self.nodes.append((id(stream), "Stimulus", "ellipse")) def write_repeater(self, stream): self.nodes.append( (id(stream), "Repeater : {0}".format(stream.value), "ellipse") ) def write_counter(self, stream): self.nodes.append( ( id(stream), "Counter : {0}, {1}, {2}".format( stream.start, stream.stop, stream.step ), "ellipse" ) ) def write_in_port(self, stream): self.nodes.append( ( id(stream), "InPort : {0} {1}".format( stream.name, stream.bits ), "ellipse" ) ) def write_serial_in(self, stream): self.nodes.append( ( id(stream), "SerialIn : {0}".format( stream.name ), "ellipse" ) ) #sinks def write_response(self, stream): self.nodes.append((id(stream), "Response", "box")) self.edges.append( ( id(stream.a), id(stream), stream.a.get_bits(), "w" ) ) def write_out_port(self, stream): self.nodes.append( ( id(stream), "OutPort : {0}".format( stream.name ), "box" ) ) self.edges.append( ( id(stream.a), id(stream), stream.a.get_bits(), "w" ) ) def write_serial_out(self, stream): self.nodes.append( ( id(stream), "SerialOut : {0}".format( stream.name ), "box" ) ) self.edges.append( ( id(stream.a), id(stream), stream.a.get_bits(), "w" ) ) def write_svga(self, stream): self.nodes.append((id(stream), "SVGA", "box")) self.edges.append( ( id(stream.a), id(stream), stream.a.get_bits(), "w" ) ) def write_console(self, stream): self.nodes.append((id(stream), "Console", "box")) self.edges.append( ( id(stream.a), id(stream), stream.a.get_bits(), "w" ) ) def write_asserter(self, stream): self.nodes.append((id(stream), "Asserter", "box")) self.edges.append( ( id(stream.a), id(stream), stream.a.get_bits(), "w" ) ) #combinators def write_binary(self, stream): labels = { 'add' : '+', 'sub' : '-', 'mul' : '*', 'div' : '//', 'mod' : '%', 'and' : '&', 'or' : '|', 'xor' : '^', 'sl' : '<<', 'sr' : '>>', 'eq' : '==', 'ne' : '!=', 'lt' : '<=', 'le' : '<', 'gt' : '>', 'ge' : '>=' } self.nodes.append((id(stream), labels[stream.function], "circle")) self.edges.append( ( id(stream.a), id(stream), stream.a.get_bits(), "nw" ) ) self.edges.append( ( id(stream.b), id(stream), stream.b.get_bits(), "sw" ) ) def write_unary(self, stream): labels = { 'abs' : 'abs', 'not' : '!', 'invert' : '~', 'sln' : '<<', 'srn' : '>>', } self.nodes.append((id(stream), labels[stream.function], "circle")) self.edges.append( ( id(stream.a), id(stream), stream.a.get_bits(), "nw" ) ) self.edges.append( ( id(stream.b), id(stream), stream.b.get_bits(), "sw" ) ) def write_lookup(self, stream): self.nodes.append((id(stream), "Lookup", "ellipse")) self.edges.append( ( id(stream.a), id(stream), stream.a.get_bits(), "w" ) ) def write_array(self, stream): self.nodes.append((id(stream), "Array", "ellipse")) self.edges.append( ( id(stream.a), id(stream), stream.a.get_bits(), "nw" ) ) self.edges.append( ( id(stream.b), id(stream), stream.b.get_bits(), "w" ) ) self.edges.append( ( id(stream.c), id(stream), stream.c.get_bits(), "sw" ) ) def write_decoupler(self, stream): self.nodes.append( ( id(stream), "Decoupler", "ellipse" ) ) self.edges.append( ( id(stream.a), id(stream), stream.a.get_bits(), "w" ) ) def write_resizer(self, stream): self.nodes.append((id(stream), "Resizer", "ellipse")) self.edges.append( ( id(stream.a), id(stream), stream.a.get_bits(), "w" ) ) def write_printer(self, stream): self.nodes.append((id(stream), "Printer", "ellipse")) self.edges.append( ( id(stream.a), id(stream), stream.a.get_bits(), "w" ) ) def write_output(self, stream): self.outputs[id(stream)] = id(stream.process) def write_process(self, p): self.nodes.append((id(p), "Process", "ellipse")) for i in p.inputs: self.edges.append((id(i), id(p), i.get_bits(), "centre")) def write_external_ip(self, ip): for i in ip.output_streams: self.ip_outputs[id(i)]=id(ip) self.nodes.append((id(ip), ip.definition.name, "ellipse")) for i in ip.input_streams: self.edges.append((id(i), id(ip), i.get_bits(), "centre")) def write_chip(self, *args): pass #System VHDL Generation and external tools def draw(self, filename): for ident, label, shape in self.nodes: self.schematic.add_node( str(ident), shape=shape, label=str(label) ) for from_node, to_node, bits, headport in self.edges: if from_node in self.outputs: self.schematic.add_edge( str(self.outputs[from_node]), str(to_node), label=str(bits), headport=headport ) elif from_node in self.ip_outputs: self.schematic.add_edge( str(self.ip_outputs[from_node]), str(to_node), label=str(bits), headport=headport ) else: self.schematic.add_edge( str(from_node), str(to_node), label=str(bits) ) self.schematic.layout(prog='dot') self.schematic.draw(filename)
def dot_layout(cy_elements, edge_labels=False, subgraph_boxes=False, node_gt=None): """ Get a CyElements object and augment it (in-place) with positions, widths, heights, and spline data from a dot based layout. edge_labels is true if labels should appear on edges subgraph_boxes is true if boxes should be drawn around subgraphs Returns the object. """ elements = cy_elements.elements # g = AGraph(directed=True, strict=False) g = AGraph(directed=True, strict=False, forcelabels=True) # make transitive relations appear top to bottom elements = list(elements) nodes_by_id = dict((e["data"]["id"], e) for e in elements if e["group"] == "nodes") order = [ (nodes_by_id[e["data"]["source"]], nodes_by_id[e["data"]["target"]]) for e in elements if e["group"] == "edges" and "transitive" in e["data"] and e["data"]["transitive"] ] elements = topological_sort(elements, order, lambda e: e["data"]["id"]) # get the node id's and stable sort them by cluster # the idea here is to convert the graph into a dag by sorting # the nodes, then reversing the back edges. In particular, we try to make # all the edges between two clusters go in the same direction so clustering # doesn't result in horizontal edges, which dot renders badly. sorted_nodes = [e["data"]["id"] for e in elements if e["group"] == "nodes"] sorted_nodes = sorted(enumerate(sorted_nodes), key=lambda x: (nodes_by_id[x[1]]["data"]["cluster"], x[0])) sorted_nodes = [y for idx, y in sorted_nodes] node_key = dict((id, idx) for idx, id in enumerate(sorted_nodes)) if node_gt is None: node_gt = lambda X, y: False else: node_gt = lambda x, y: node_key[x] > node_key[y] # add nodes to the graph for e in elements: if e["group"] == "nodes" and e["classes"] != "non_existing": g.add_node(e["data"]["id"], label=e["data"]["label"].replace("\n", "\\n")) # TODO: remove this, it's specific to leader_demo weight = {"reach": 10, "le": 10, "id": 1} constraint = {"pending": False} # add edges to the graph for e in elements: if e["group"] == "edges": # kwargs = {'weight': weight.get(e["data"]["obj"], 0)}, kwargs = {"label": e["data"]["label"]} if edge_labels else {} if node_gt(e["data"]["source"], e["data"]["target"]): g.add_edge( e["data"]["target"], e["data"]["source"], e["data"]["id"], dir="back", **kwargs # constraint=constraint.get(e["data"]["obj"], True), ) else: g.add_edge( e["data"]["source"], e["data"]["target"], e["data"]["id"], **kwargs # constraint=constraint.get(e["data"]["obj"], True), ) # add clusters clusters = defaultdict(list) for e in elements: if e["group"] == "nodes" and e["data"]["cluster"] is not None and e["classes"] != "non_existing": clusters[e["data"]["cluster"]].append(e["data"]["id"]) for i, k in enumerate(sorted(clusters.keys())): g.add_subgraph(name="cluster_{}".format(i), nbunch=clusters[k], rank="min") # now get positions, heights, widths, and bsplines g.layout(prog="dot") # get the y origin. we want the top left of the graph to be a # fixed coordinate (hopefully (0,0)) so the graph doesn't jump when # its height changes. Unfortunately, pygraphviz has a bug a gives # the wrong bbox, so we compute the max y coord. # bbox = pygraphviz.graphviz.agget(g.handle,'bb') global y_origin y_origin = 0.0 for n in g.nodes(): top = float(n.attr["pos"].split(",")[1]) + float(n.attr["height"]) / 2 if top > y_origin: y_origin = top if subgraph_boxes: for sg in g.subgraphs(): top = float(sg.graph_attr["bb"].split(",")[3]) if top > y_origin: y_origin = top for e in elements: if e["group"] == "nodes" and e["classes"] != "non_existing": attr = g.get_node(e["data"]["id"]).attr e["position"] = _to_position(attr["pos"]) e["data"]["width"] = 72 * float(attr["width"]) e["data"]["height"] = 72 * float(attr["height"]) elif e["group"] == "edges": if node_gt(e["data"]["source"], e["data"]["target"]): attr = g.get_edge(e["data"]["target"], e["data"]["source"], e["data"]["id"]).attr pos = attr["pos"] pe = pos.split() ppe = pe[1:] ppe.reverse() pos = " ".join([pe[0].replace("s", "e")] + ppe) else: attr = g.get_edge(e["data"]["source"], e["data"]["target"], e["data"]["id"]).attr pos = attr["pos"] e["data"].update(_to_edge_position(pos)) if edge_labels and e["data"]["label"] != "": e["data"]["lp"] = _to_position(attr["lp"]) # g.draw('g.png') if subgraph_boxes: for sg in g.subgraphs(): box = cy_elements.add_shape(sg.name, classes="subgraphs") coords = _to_coord_list(sg.graph_attr["bb"]) box["data"]["coords"] = coords return cy_elements
def show(self, filename='AST.png'): g = AGraph() g.graph_attr['label'] = 'AST' AST_DFS(self, g) g.layout(prog='dot') g.draw(filename)
def dot_layout(cy_elements, edge_labels=False, subgraph_boxes=False, node_gt=None): """ Get a CyElements object and augment it (in-place) with positions, widths, heights, and spline data from a dot based layout. edge_labels is true if labels should appear on edges subgraph_boxes is true if boxes should be drawn around subgraphs Returns the object. """ elements = cy_elements.elements # g = AGraph(directed=True, strict=False) g = AGraph(directed=True, strict=False, forcelabels=True) # make transitive relations appear top to bottom elements = list(elements) nodes_by_id = dict( (e["data"]["id"], e) for e in elements if e["group"] == "nodes") order = [(nodes_by_id[e["data"]["source"]], nodes_by_id[e["data"]["target"]]) for e in elements if e["group"] == "edges" and "transitive" in e["data"] and e["data"]["transitive"]] elements = topological_sort(elements, order, lambda e: e["data"]["id"]) # get the node id's and stable sort them by cluster # the idea here is to convert the graph into a dag by sorting # the nodes, then reversing the back edges. In particular, we try to make # all the edges between two clusters go in the same direction so clustering # doesn't result in horizontal edges, which dot renders badly. sorted_nodes = [e["data"]["id"] for e in elements if e["group"] == "nodes"] sorted_nodes = sorted(enumerate(sorted_nodes), key=lambda x: (nodes_by_id[x[1]]["data"]["cluster"], x[0])) sorted_nodes = [y for idx, y in sorted_nodes] node_key = dict((id, idx) for idx, id in enumerate(sorted_nodes)) if node_gt is None: node_gt = lambda X, y: False else: node_gt = lambda x, y: node_key[x] > node_key[y] # add nodes to the graph for e in elements: if e["group"] == "nodes" and e["classes"] != 'non_existing': g.add_node(e["data"]["id"], label=e["data"]["label"].replace('\n', '\\n')) # TODO: remove this, it's specific to leader_demo weight = { 'reach': 10, 'le': 10, 'id': 1, } constraint = { 'pending': False, } # add edges to the graph for e in elements: if e["group"] == "edges": # kwargs = {'weight': weight.get(e["data"]["obj"], 0)}, kwargs = {'label': e["data"]["label"]} if edge_labels else {} if node_gt(e["data"]["source"], e["data"]["target"]): g.add_edge(e["data"]["target"], e["data"]["source"], e["data"]["id"], dir='back', **kwargs #constraint=constraint.get(e["data"]["obj"], True), ) else: g.add_edge(e["data"]["source"], e["data"]["target"], e["data"]["id"], **kwargs #constraint=constraint.get(e["data"]["obj"], True), ) # add clusters clusters = defaultdict(list) for e in elements: if e["group"] == "nodes" and e["data"][ "cluster"] is not None and e["classes"] != 'non_existing': clusters[e["data"]["cluster"]].append(e["data"]["id"]) for i, k in enumerate(sorted(clusters.keys())): g.add_subgraph( name='cluster_{}'.format(i), nbunch=clusters[k], rank='min', ) # now get positions, heights, widths, and bsplines g.layout(prog='dot') # get the y origin. we want the top left of the graph to be a # fixed coordinate (hopefully (0,0)) so the graph doesn't jump when # its height changes. Unfortunately, pygraphviz has a bug a gives # the wrong bbox, so we compute the max y coord. # bbox = pygraphviz.graphviz.agget(g.handle,'bb') global y_origin y_origin = 0.0 for n in g.nodes(): top = float(n.attr['pos'].split(',')[1]) + float(n.attr['height']) / 2 if top > y_origin: y_origin = top if subgraph_boxes: for sg in g.subgraphs(): top = float(sg.graph_attr['bb'].split(',')[3]) if top > y_origin: y_origin = top for e in elements: if e["group"] == "nodes" and e["classes"] != 'non_existing': attr = g.get_node(e["data"]["id"]).attr e["position"] = _to_position(attr['pos']) e["data"]["width"] = 72 * float(attr['width']) e["data"]["height"] = 72 * float(attr['height']) elif e["group"] == "edges": if node_gt(e["data"]["source"], e["data"]["target"]): attr = g.get_edge(e["data"]["target"], e["data"]["source"], e["data"]["id"]).attr pos = attr['pos'] pe = pos.split() ppe = pe[1:] ppe.reverse() pos = ' '.join([pe[0].replace('s', 'e')] + ppe) else: attr = g.get_edge(e["data"]["source"], e["data"]["target"], e["data"]["id"]).attr pos = attr['pos'] e["data"].update(_to_edge_position(pos)) if edge_labels and e["data"]["label"] != '': e["data"]["lp"] = _to_position(attr['lp']) # g.draw('g.png') if subgraph_boxes: for sg in g.subgraphs(): box = cy_elements.add_shape(sg.name, classes='subgraphs') coords = _to_coord_list(sg.graph_attr['bb']) box["data"]["coords"] = coords return cy_elements