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 self._draw_nodes(g) self._draw_edges(g, self.config.get('natural', False)) return g.string()
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)
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()
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 if namespace: 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()
__author__ = """Aric Hagberg ([email protected])""" from pygraphviz import AGraph A = AGraph() # set some default node attributes A.node_attr['style'] = 'filled' A.node_attr['shape'] = 'circle' A.node_attr['fixedsize'] = 'true' A.node_attr['fontcolor'] = '#FFFFFF' # make a star in shades of red for i in range( 16 ): A.add_edge( 0, i ) n = A.get_node( i ) n.attr['fillcolor'] = "#%2x0000" % ( i * 16 ) n.attr['height'] = "%s" % ( i / 16.0 + 0.5 ) n.attr['width'] = "%s" % ( i / 16.0 + 0.5 ) print A.string() # print to screen A.write( "star.dot" ) # write to simple.dot print "Wrote star.dot" A.draw( 'star.png', prog="circo" ) # draw to png using circo print "Wrote star.png" import matplotlib.pyplot as plt a = plt.imread( 'star.png' ) plt.imshow( a ) plt.show()