def visualize_stream_orders(orders, streams=[], filename='stream_orders' + DEFAULT_EXTENSION): from pygraphviz import AGraph graph = AGraph(strict=True, directed=True) graph.node_attr['style'] = 'filled' graph.node_attr['shape'] = 'box' graph.node_attr['color'] = STREAM_COLOR graph.node_attr['fontcolor'] = 'black' #graph.node_attr['fontsize'] = 12 graph.node_attr['width'] = 0 graph.node_attr['height'] = 0.02 # Minimum height is 0.02 graph.node_attr['margin'] = 0 graph.graph_attr['outputMode'] = 'nodesfirst' graph.graph_attr['dpi'] = 300 streams = set(streams) | set(flatten(orders)) for stream in streams: graph.add_node(str(stream)) for stream1, stream2 in orders: graph.add_edge(str(stream1), str(stream2)) # TODO: could also print the raw values (or a lookup table) # https://stackoverflow.com/questions/3499056/making-a-legend-key-in-graphviz graph.draw(filename, prog='dot') print('Saved', filename) #display_image(filename) return graph
def networkx(self): d = self.graph() # FIXME deduplicate from pygraphviz import AGraph import networkx as nx dot = AGraph(strict=True, directed=True) def rec(nodes, parent): for d in nodes: if not isinstance(d, dict): if '(dirty)' in d: d = d.replace('(dirty)', '') dot.add_node(d, label=d, color='red') dot.add_edge(d, parent, color='red') else: dot.add_node(d, label=d) dot.add_edge(d, parent) else: for k in d: if '(dirty)' in k: k = k.replace('(dirty)', '') dot.add_node(k, label=k, color='red') rec(d[k], k) dot.add_edge(k, parent, color='red') else: dot.add_node(k, label=k) rec(d[k], k) dot.add_edge(k, parent) for k in d: dot.add_node(k, label=k) rec(d[k], k) return nx.nx_agraph.from_agraph(dot)
def visualize_streams(goals, constants, filename='graph.pdf'): from pygraphviz import AGraph import subprocess graph = AGraph(strict=True, directed=False) graph.node_attr['style'] = 'filled' graph.node_attr['shape'] = 'circle' graph.node_attr['fontcolor'] = 'black' graph.node_attr['colorscheme'] = 'SVG' graph.edge_attr['colorscheme'] = 'SVG' for constant in constants: graph.add_node(str(constant), shape='box', color='LightGreen') for goal in goals: name = '\n'.join( str(arg) for arg in [goal.predicate.name] + list(goal.args)) #name = str(goal) graph.add_node(name, shape='box', color='LightBlue') for arg in goal.args: if isinstance(arg, AbstractConstant): arg_name = str(arg) graph.add_edge(name, arg_name) #import os #import webbrowser graph.draw(filename, prog='dot') subprocess.Popen('open %s' % filename, shell=True) #os.system(filename) #webbrowser.open(filename) raw_input('Display?') #safe_remove(filename) return graph
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 get_graphviz(self, triple_args_function=None, ignore_properties=VIS_IGNORE_PROPERTIES): """ Create a pygraphviz graph from the tree """ def _id(node): return node.uri.split("/")[-1] g = AGraph(directed=True) triples = list(self.get_triples()) nodeset = set(chain.from_iterable((t.subject, t.object) for t in triples)) for n in nodeset: label = "%s: %s" % (n.id, n.word) for k, v in n.__dict__.iteritems(): if k not in ignore_properties: label += "\\n%s: %s" % (k, v) g.add_node(_id(n), label=label) # create edges for triple in triples: kargs = (triple_args_function(triple) if triple_args_function else {}) if 'label' not in kargs: kargs['label'] = triple.predicate g.add_edge(_id(triple.subject), _id(triple.object), **kargs) # some theme options g.graph_attr["rankdir"] = "BT" g.node_attr["shape"] = "rect" g.edge_attr["edgesize"] = 10 g.node_attr["fontsize"] = 10 g.edge_attr["fontsize"] = 10 return g
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()
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 get_graphviz(self, triple_args_function=None, ignore_properties=VIS_IGNORE_PROPERTIES): """ Create a pygraphviz graph from the tree """ def _id(node): return node.uri.split("/")[-1] g = AGraph(directed=True) triples = list(self.get_triples()) nodeset = set( chain.from_iterable((t.subject, t.object) for t in triples)) for n in nodeset: label = "%s: %s" % (n.id, n.word) for k, v in n.__dict__.iteritems(): if k not in ignore_properties: label += "\\n%s: %s" % (k, v) g.add_node(_id(n), label=label) # create edges for triple in triples: kargs = (triple_args_function(triple) if triple_args_function else {}) if 'label' not in kargs: kargs['label'] = triple.predicate g.add_edge(_id(triple.subject), _id(triple.object), **kargs) # some theme options g.graph_attr["rankdir"] = "BT" g.node_attr["shape"] = "rect" g.edge_attr["edgesize"] = 10 g.node_attr["fontsize"] = 10 g.edge_attr["fontsize"] = 10 return g
def _render_graph(source_to_targets, node_to_label, metric_name, node_to_value): g = AGraph(directed=True) # Gather all nodes in graph all_nodes = set(source_to_targets.keys()) for targets in source_to_targets.values(): all_nodes.update(targets) # Build graphviz graph for node in all_nodes: if node not in node_to_value: continue cmap = mpl.cm.get_cmap('viridis') rgba = cmap(node_to_value[node]) color_value = mpl.colors.rgb2hex(rgba) if node_to_value[node] > 0.5: font_color = 'black' else: font_color = 'white' g.add_node(node_to_label[node], label=node_to_label[node], fontname='arial', style='filled', fontcolor=font_color, fillcolor=color_value) for source, targets in source_to_targets.items(): for target in targets: if source in node_to_value and target in node_to_value: g.add_edge(node_to_label[source], node_to_label[target]) return g
def construct_directed_graph(collections_data: List[CollectionData]) -> AGraph: graph = AGraph(directed=True, fontzise=10, fontname='Verdana') graph.node_attr['fontname'] = 'Verdana' graph.node_attr['shape'] = 'record' collection_direction_order_ids = [ collection.id for collection in collections_data ] collection_names = [collection.name for collection in collections_data] # draw "y axe" with tree ordering graph.add_nodes_from(collection_names, shape='plaintext', fontsize=14) graph.add_edges_from(zip(collection_names, collection_names[1:])) graph.add_subgraph(collection_names) # combine all pages in one graph for collection_data in collections_data: for page in collection_data.pages: node = get_node(page) graph.add_node(node, label=page.title) # don't include reversed relations: edges = get_edges(page, collection_direction_order_ids) graph.add_edges_from(edges) # align all nodes for one level in one line (include element from "y" line for alignment) one_level_nodes = [collection_data.name] + [ get_node(page) for page in collection_data.pages ] graph.add_subgraph(one_level_nodes, None, rank='same') return graph
def path_graph(nodes): graph = AGraph(directed=True) for node in nodes: graph.add_node(node, shape='rectangle') graph.add_path(nodes) return graph
def visualize_constraints(constraints, filename='constraint_network.pdf', use_functions=True): from pygraphviz import AGraph graph = AGraph(strict=True, directed=False) graph.node_attr['style'] = 'filled' #graph.node_attr['fontcolor'] = 'black' #graph.node_attr['fontsize'] = 12 graph.node_attr['colorscheme'] = 'SVG' graph.edge_attr['colorscheme'] = 'SVG' #graph.graph_attr['rotate'] = 90 #graph.node_attr['fixedsize'] = True graph.node_attr['width'] = 0 graph.node_attr['height'] = 0.02 # Minimum height is 0.02 graph.node_attr['margin'] = 0 graph.graph_attr['rankdir'] = 'RL' graph.graph_attr['nodesep'] = 0.05 graph.graph_attr['ranksep'] = 0.25 #graph.graph_attr['pad'] = 0 # splines="false"; graph.graph_attr['outputMode'] = 'nodesfirst' graph.graph_attr['dpi'] = 300 functions = set() negated = set() heads = set() for fact in constraints: prefix = get_prefix(fact) if prefix in (EQ, MINIMIZE): functions.add(fact[1]) elif prefix == NOT: negated.add(fact[1]) else: heads.add(fact) heads.update(functions) heads.update(negated) objects = {a for head in heads for a in get_args(head)} optimistic_objects = filter(lambda o: isinstance(o, OptimisticObject), objects) for opt_obj in optimistic_objects: graph.add_node(str(opt_obj), shape='circle', color=PARAMETER_COLOR) for head in heads: if not use_functions and (head in functions): continue # TODO: prune values w/o free parameters? name = str_from_fact(head) if head in functions: color = COST_COLOR elif head in negated: color = NEGATED_COLOR else: color = CONSTRAINT_COLOR graph.add_node(name, shape='box', color=color) for arg in get_args(head): if arg in optimistic_objects: graph.add_edge(name, str(arg)) graph.draw(filename, prog='dot') # neato | dot | twopi | circo | fdp | nop return graph
def draw(diagram: 'Diagram', output_file: 'str') -> None: G = AGraph(**GRAPH_OPTIONS) for node in diagram.components.values(): G.add_node(node.name, label=node.render(), **COMPONENT_OPTIONS) for node in diagram.sections.values(): G.add_node(node.name, label=node.render(), **SECTION_OPTIONS) add_edges(G, diagram) G.write() G.draw(output_file, prog=LAYOUT)
def cm_json_to_graph(cm_json): """Return pygraphviz Agraph from Kappy's contact map JSON. Parameters ---------- cm_json : dict A JSON dict which contains a contact map generated by Kappy. Returns ------- graph : pygraphviz.Agraph A graph representing the contact map. """ cmap_data = get_cmap_data_from_json(cm_json) # Initialize the graph graph = AGraph() # In this loop we add sites as nodes and clusters around sites to the # graph. We also collect edges to be added between sites later. edges = [] for node_idx, node in enumerate(cmap_data): sites_in_node = [] for site_idx, site in enumerate(node['node_sites']): # We map the unique ID of the site to its name site_key = (node_idx, site_idx) sites_in_node.append(site_key) graph.add_node(site_key, label=site['site_name'], style='filled', shape='ellipse') # Each port link is an edge from the current site to the # specified site if not site['site_type'] or not site['site_type'][0] == 'port': continue # As of kappy 4.1.2, the format of port links have changed # Old format: [[1, 0]], New format: [[[0, 1], 0]] for port_link in site['site_type'][1]['port_links']: port_link = tuple([ link[1] if isinstance(link, list) else link for link in port_link ]) if isinstance(port_link, list): port_link = port_link[1] edge = (site_key, tuple(port_link)) edges.append(edge) graph.add_subgraph(sites_in_node, name='cluster_%s' % node['node_type'], label=node['node_type']) # Finally we add the edges between the sites for source, target in edges: graph.add_edge(source, target) return graph
def _render(self, costs=False, word_probs=False, highlight_best=False): from pygraphviz import AGraph graph = AGraph(directed=True) for node_id, node_label in self.nodes.iteritems(): attributes = self._node_attr(node_id, costs=costs, word_probs=word_probs) graph.add_node(node_id, **attributes) for (parent_node_id, child_node_id) in self.edges: graph.add_edge(parent_node_id, child_node_id) self.graph = graph if highlight_best: self._highlight_best()
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 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}")
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 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 as_graph(self, to=None): from pygraphviz import AGraph g = AGraph(directed=True) for a in self.activities.values(): g.add_node(a.title, label=a.title) for t in self.transitions.values(): g.add_edge(t.input.title, t.output.title, label=t.name) if to: g.write(to) else: return str(g)
def _construct_graph(graph: gz.AGraph, state): graph.add_node( state.id_nr, label=_state_to_node(state), shape="record", ) for move, next_state in state.next_states.items(): if next_state: _construct_graph(graph, next_state) graph.add_edge(u=state.id_nr, v=next_state.id_nr, key="l", label=str(move))
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 visualize_stream_plan(stream_plan, filename='stream_plan.pdf'): from pygraphviz import AGraph graph = AGraph(strict=True, directed=True) graph.node_attr['style'] = 'filled' graph.node_attr['shape'] = 'box' graph.node_attr['color'] = STREAM_COLOR for stream in stream_plan: graph.add_node(str(stream)) for stream1, stream2 in get_partial_orders(stream_plan): graph.add_edge(str(stream1), str(stream2)) # TODO: could also print the raw values (or a lookup table) # https://stackoverflow.com/questions/3499056/making-a-legend-key-in-graphviz graph.draw(filename, prog='dot') return graph
def cm_json_to_graph(im_json): """Return pygraphviz Agraph from Kappy's contact map JSON. Parameters ---------- im_json : dict A JSON dict which contains a contact map generated by Kappy. Returns ------- graph : pygraphviz.Agraph A graph representing the contact map. """ cmap_data = im_json['contact map']['map'] # Initialize the graph graph = AGraph() # In this loop we add sites as nodes and clusters around sites to the # graph. We also collect edges to be added between sites later. edges = [] for node_idx, node in enumerate(cmap_data): sites_in_node = [] for site_idx, site in enumerate(node['node_sites']): # We map the unique ID of the site to its name site_key = (node_idx, site_idx) sites_in_node.append(site_key) graph.add_node(site_key, label=site['site_name'], style='filled', shape='ellipse') # Each port link is an edge from the current site to the # specified site if not site['site_type'] or not site['site_type'][0] == 'port': continue for port_link in site['site_type'][1]['port_links']: edge = (site_key, tuple(port_link)) edges.append(edge) graph.add_subgraph(sites_in_node, name='cluster_%s' % node['node_type'], label=node['node_type']) # Finally we add the edges between the sites for source, target in edges: graph.add_edge(source, target) return graph
def visualize_constraints(constraints, filename='constraint_network' + DEFAULT_EXTENSION, use_functions=True): from pygraphviz import AGraph graph = AGraph(strict=True, directed=False) graph.node_attr['style'] = 'filled' #graph.node_attr['fontcolor'] = 'black' #graph.node_attr['fontsize'] = 12 graph.node_attr['colorscheme'] = 'SVG' graph.edge_attr['colorscheme'] = 'SVG' #graph.graph_attr['rotate'] = 90 #graph.node_attr['fixedsize'] = True graph.node_attr['width'] = 0 graph.node_attr['height'] = 0.02 # Minimum height is 0.02 graph.node_attr['margin'] = 0 graph.graph_attr['rankdir'] = 'RL' graph.graph_attr['nodesep'] = 0.05 graph.graph_attr['ranksep'] = 0.25 #graph.graph_attr['pad'] = 0 # splines="false"; graph.graph_attr['outputMode'] = 'nodesfirst' graph.graph_attr['dpi'] = 300 positive, negated, functions = partition_facts(constraints) for head in (positive + negated + functions): # TODO: prune values w/o free parameters? name = str_from_fact(head) if head in functions: if not use_functions: continue color = COST_COLOR elif head in negated: color = NEGATED_COLOR else: color = CONSTRAINT_COLOR graph.add_node(name, shape='box', color=color) for arg in get_args(head): if isinstance(arg, OptimisticObject) or is_parameter(arg): arg_name = str(arg) graph.add_node(arg_name, shape='circle', color=PARAMETER_COLOR) graph.add_edge(name, arg_name) graph.draw(filename, prog='dot') # neato | dot | twopi | circo | fdp | nop print('Saved', filename) return graph
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 generate_graph(self) -> AGraph: graph = AGraph(directed=True, splines='curved', overlap='vpsc') for cfg in self.cfgs: for bb in cfg.basic_blocks: style = {} if bb.type == 'BBExit': style = dict(style='filled', color='#665c54') if bb.type == 'BBEntry': style = dict(style='filled', color='#458588') graph.add_node(n=bb.id, label=f'bb={bb.id} stmt={bb.stmt_id}', **style) for succ in bb.succs: graph.add_edge(bb.id, succ) for pred in bb.preds: graph.add_edge(pred, bb.id) return graph
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)
class Graph(object): def __init__(self, graph_dict={}): self.__graph_dict = graph_dict self.__G = AGraph() def add_vertex(self, v): if (v not in self.__graph_dict): self.__graph_dict[v] = [] self.__G.add_node(v) def add_edge(self, u, v): if (u not in self.__graph_dict): self.__graph_dict[u] = [v] else: self.__graph_dict[u].append(v) self.__G.add_edge(u, v) def draw(self, fn): print(self.__graph_dict) self.__G.draw(fn, prog="circo") Image.open(fn).show() def clear(self): self.__graph_dict = {} self.__G.clear() def isConnected(self, path=None, start_vertex=None): if path == None: path = set() vertices = list( self.__graph_dict.keys()) # "list" necessary in Python 3 if start_vertex == None: start_vertex = vertices[0] path.add(start_vertex) if len(path) == len(vertices): return True else: for v in self.__graph_dict[start_vertex]: if v not in path: if self.isConnected(path, v): return True return False
def _( G: ProgramAnalysisGraph, show_values=True, save=False, filename="program_analysis_graph.pdf", **kwargs, ): """ Visualizes ProgramAnalysisGraph in Jupyter notebook cell. Args: args kwargs Returns: AGraph """ A = AGraph(directed=True) A.graph_attr.update({"dpi": 227, "fontsize": 20, "fontname": "Menlo"}) A.node_attr.update({ "shape": "rectangle", "color": "#650021", "style": "rounded", "fontname": "Gill Sans", }) color_str = "#650021" for n in G.nodes(): A.add_node(n, label=n) for e in G.edges(data=True): A.add_edge(e[0], e[1], color=color_str, arrowsize=0.5) if show_values: for n in A.nodes(): value = str(G.nodes[n]["value"]) n.attr["label"] = n.attr["label"] + f": {value:.4}" if save: A.draw(filename, prog=kwargs.get("layout", "dot")) return Image(A.draw(format="png", prog=kwargs.get("layout", "dot")), retina=True)
def get_dot(self, labeller=None): self.labeller = labeller a_graph = AGraph(directed=True) nx_graph = self.graph.nx_graph # TODO: Add some default stuff? # a_graph.graph_attr.update(N.graph.get('graph',{})) # a_graph.node_attr.update(N.graph.get('node',{})) # a_graph.edge_attr.update(N.graph.get('edge',{})) structural_nodes = [] output_nodes = [] input_nodes = [] # First, add nodes for node in nx_graph.nodes(): name, attrs = self.get_node_attributes(node) if self.graph.is_input(node): input_nodes.append(name) elif self.graph.is_structural(node): structural_nodes.append(name) elif self.graph.is_output(node): output_nodes.append(name) # Keep a reference to the original node a_graph.add_node(name, **attrs) # We need to add subgraphs to cluster stuff on rank sub = a_graph.add_subgraph(input_nodes, name='input') sub.graph_attr['rank'] = 'source' sub = a_graph.add_subgraph(structural_nodes, name='structural') sub.graph_attr['rank'] = 'same' sub = a_graph.add_subgraph(output_nodes, name='output') sub.graph_attr['rank'] = 'sink' # Now add edges for u, v, edgedata in nx_graph.edges_iter(data=True): attrs = {} a_graph.add_edge(self.graph.node_to_name(u), self.graph.node_to_name(v), **attrs) return a_graph
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 draw_relations(self, relations, fname): def get_node_name(n): return n.__name__ g= AGraph(directed=True) for n in relations: n_name= get_node_name(n) g.add_node(n_name) for relation in chain(*relations.values()): n1_name= get_node_name(relation.object1) n2_name= get_node_name(relation.object2) g.add_edge(n1_name, n2_name) e= g.get_edge(n1_name, n2_name) relation.set_edge_attributes(e) for n in g.nodes(): n.attr['shape']= 'box' g.draw(fname, prog='dot', args='-Grankdir=TB')
def get_graphviz(self, triple_hook=graphviz_triple_hook, node_hook=graphviz_node_hook, theme_options=VIS_THEME_OPTIONS, **hook_options): """ Create a pygraphviz graph from the tree @param triple_hook: a function that returns an attribute dict (or None) given a triple and the kargs @param node_hook: a function that returns a label given a node and the kargs @param theme_options: a dict-of-dicts containing global graph/node/edge attributes @param hook_options: additional arguments to pass to the hook functions """ def _id(node): return node.uri.split("/")[-1] g = AGraph(directed=True, strict=False) triples = list(self.get_triples()) # create nodes nodeset = set(chain.from_iterable((t.subject, t.object) for t in triples)) for n in sorted(nodeset, key=lambda n:n.id): g.add_node(_id(n), **node_hook(n, **hook_options)) connected = set() # create edges for triple in sorted(triples, key=lambda t:t.predicate): kargs = triple_hook(triple, **hook_options) if kargs: if kargs.get('reverse'): g.add_edge(_id(triple.object), _id(triple.subject), **kargs) else: g.add_edge(_id(triple.subject), _id(triple.object), **kargs) connected |= {_id(triple.subject), _id(triple.object)} connected = chain.from_iterable(g.edges()) for isolate in set(g.nodes()) - set(connected): g.remove_node(isolate) # some theme options for obj, attrs in theme_options.iteritems(): for k, v in attrs.iteritems(): getattr(g, "%s_attr" % obj)[k] = v return g
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
class DotRenderer(GraphRenderer): """Renderer fox dot.""" """The AGraph used for rendering.""" _graph = None def __init__(self, settings, reporter): GraphRenderer.__init__(self, settings, reporter) if not pygraphvizAvail: self.reporter.severe("Can not render dot format because module `pygraphviz` cannot be loaded") def prepare(self): self._graph = AGraph(strict=False, directed=True, name=self._visitor.sourceName) def finish(self): # TODO The ordering of nodes seems to be rather random in the output; # however, the node ordering is used for the layout of the graph # at least by `dot` and by `neato`; there should be a way to # determine the ordering r = self._graph.string() self._graph = None return r def renderAnchor(self, anchor): self._graph.add_node(anchor.id(), label=anchor.name()) def renderReference(self, reference): if reference.fromAnchor is None: # No anchor to start edge from # TODO Should result in a warning return fromId = reference.fromAnchor.id() toId = reference.toAnchor.id() if self._doReverse: (fromId, toId) = (toId, fromId) self._graph.add_edge(fromId, toId)
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 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 recalculate(user): # remove old ranking RankedTeam.objects.filter(team__user = user).delete() for pic in RankingPicture.objects.all(): pic.image.delete() pic.delete() color_index = 0 team_graph = Graph() gvfull = AGraph(directed = True) for team in user.teams.all(): gvfull.add_node(asciiname(team), label = team.name) team_graph.add_node(team) for game in Game.objects.filter(team_1__user = user, team_2__user = user): team_graph.add_edge(game.winner(), game.loser(), game.jugg_diff()) for source, dest, weight in team_graph.edges(): gvfull.add_edge(asciiname(source), asciiname(dest), label = str(weight)) current_place = 1 gvcircles = AGraph(directed = True) gvtiebreaker = AGraph(directed = True) for place in team_graph.topological_sort(): place_list = [] relevant_teams = set() for circle in place: relevant_teams |= circle if len(circle) == 1: continue color_index, current_color = getcolor(color_index) for team in circle: gvcircles.add_node(asciiname(team), label = team.name, color = current_color, fontcolor = current_color) gvfull.get_node(asciiname(team)).attr['color'] = current_color gvfull.get_node(asciiname(team)).attr['fontcolor'] = current_color for source, dest, weight in team_graph.edges(): if source in circle and dest in circle: gvcircles.add_edge(asciiname(source), asciiname(dest), label = str(weight), color = current_color, fontcolor = current_color) gvfull.get_edge(asciiname(source), asciiname(dest)).attr['color'] = current_color gvfull.get_edge(asciiname(source), asciiname(dest)).attr['fontcolor'] = current_color place = [[(team.normalized_jugg_diff(relevant_teams), team.name, team) for team in circle] for circle in place] for circle in place: circle.sort(reverse = True) while place: place_list.append(set()) i = 0 while i < len(place): circle = place[i] jd = circle[0][0] while circle and circle[0][0] == jd: place_list[-1].add(circle.pop(0)) if not circle: place.remove(circle) else: i += 1 for same_place_set in place_list: # tie breaker if len(same_place_set) > 1: # teams that everyone on this place played against relevant_teams = team_graph.nodes() for circ_jugg_diff, name, team in same_place_set: opponents = set() for game in team.games(): if game.team_1 == team: opponents.add(game.team_2) else: opponents.add(game.team_1) relevant_teams &= opponents if len(relevant_teams) > 0: color_index, current_color_a = getcolor(color_index) color_index, current_color_b = getcolor(color_index) for team in relevant_teams: gvtiebreaker.add_node("b-" + asciiname(team), label = team.name, color = current_color_b, fontcolor = current_color_b) for void, void, team in same_place_set: gvtiebreaker.add_node("a-" + asciiname(team), label = team.name, color = current_color_a, fontcolor = current_color_a) for game in team.games(): if game.team_1 == team and game.team_2 in relevant_teams: if game.winner() == team: gvtiebreaker.add_edge("a-" + asciiname(team), "b-" + asciiname(game.team_2), label = game.jugg_diff(), color = current_color_a, fontcolor = current_color_a) else: gvtiebreaker.add_edge("b-" + asciiname(game.team_2), "a-" + asciiname(team), label = game.jugg_diff(), color = current_color_b, fontcolor = current_color_b) elif game.team_2 == team and game.team_1 in relevant_teams: if game.winner() == team: gvtiebreaker.add_edge("a-" + asciiname(team), "b-" + asciiname(game.team_1), label = game.jugg_diff(), color = current_color_a, fontcolor = current_color_a) else: gvtiebreaker.add_edge("b-" + asciiname(game.team_1), "a-" + asciiname(team), label = game.jugg_diff(), color = current_color_b, fontcolor = current_color_b) # jugg differences against relevant teams rel_jugg_diffs = set() for team_tuple in same_place_set: rel_jugg_diffs.add((team_tuple, team_tuple[2].normalized_jugg_diff(relevant_teams))) # pop all teams, highest relevant jugg difference first while rel_jugg_diffs: # current maximum max_rel_jugg_diff = None # teams with maximum jugg difference to_remove = None for team_tuple, rel_jugg_diff in rel_jugg_diffs: # new maximum if max_rel_jugg_diff is None or rel_jugg_diff > max_rel_jugg_diff[0]: max_rel_jugg_diff = (rel_jugg_diff, {team_tuple}) to_remove = {(team_tuple, rel_jugg_diff)} # same as maximum elif rel_jugg_diff == max_rel_jugg_diff[0]: max_rel_jugg_diff[1].add(team_tuple) to_remove.add((team_tuple, rel_jugg_diff)) # remove teams with maximum jugg difference rel_jugg_diffs -= to_remove # add teams to listing for (circ_jugg_diff, name, team), rel_jugg_diff in to_remove: RankedTeam.objects.create(place = current_place, team = team) current_place += 1 else: circ_jugg_diff, name, team = same_place_set.pop() RankedTeam.objects.create(place = current_place, team = team) current_place += 1 with tempfile.NamedTemporaryFile(suffix = ".png") as tmp: gvfull.draw(tmp, "png", "dot") pic = RankingPicture(user = user, image = File(tmp), title = "Full Team Graph") pic.save() with tempfile.NamedTemporaryFile(suffix = ".png") as tmp: gvcircles.draw(tmp, "png", "dot") pic = RankingPicture(user = user, image = File(tmp), title = "Circles") pic.save() with tempfile.NamedTemporaryFile(suffix = ".png") as tmp: gvtiebreaker.draw(tmp, "png", "dot") pic = RankingPicture(user = user, image = File(tmp), title = "Tie Breaker") pic.save()
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()