diff planemo/lib/python3.7/site-packages/networkx/drawing/nx_agraph.py @ 1:56ad4e20f292 draft

"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author guerler
date Fri, 31 Jul 2020 00:32:28 -0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/planemo/lib/python3.7/site-packages/networkx/drawing/nx_agraph.py	Fri Jul 31 00:32:28 2020 -0400
@@ -0,0 +1,473 @@
+#    Copyright (C) 2004-2019 by
+#    Aric Hagberg <hagberg@lanl.gov>
+#    Dan Schult <dschult@colgate.edu>
+#    Pieter Swart <swart@lanl.gov>
+#    All rights reserved.
+#    BSD license.
+#
+# Author: Aric Hagberg (hagberg@lanl.gov)
+"""
+***************
+Graphviz AGraph
+***************
+
+Interface to pygraphviz AGraph class.
+
+Examples
+--------
+>>> G = nx.complete_graph(5)
+>>> A = nx.nx_agraph.to_agraph(G)
+>>> H = nx.nx_agraph.from_agraph(A)
+
+See Also
+--------
+Pygraphviz: http://pygraphviz.github.io/
+"""
+import os
+import tempfile
+import networkx as nx
+
+__all__ = ['from_agraph', 'to_agraph',
+           'write_dot', 'read_dot',
+           'graphviz_layout',
+           'pygraphviz_layout',
+           'view_pygraphviz']
+
+
+def from_agraph(A, create_using=None):
+    """Returns a NetworkX Graph or DiGraph from a PyGraphviz graph.
+
+    Parameters
+    ----------
+    A : PyGraphviz AGraph
+      A graph created with PyGraphviz
+
+    create_using : NetworkX graph constructor, optional (default=nx.Graph)
+       Graph type to create. If graph instance, then cleared before populated.
+
+    Examples
+    --------
+    >>> K5 = nx.complete_graph(5)
+    >>> A = nx.nx_agraph.to_agraph(K5)
+    >>> G = nx.nx_agraph.from_agraph(A)
+
+    Notes
+    -----
+    The Graph G will have a dictionary G.graph_attr containing
+    the default graphviz attributes for graphs, nodes and edges.
+
+    Default node attributes will be in the dictionary G.node_attr
+    which is keyed by node.
+
+    Edge attributes will be returned as edge data in G.  With
+    edge_attr=False the edge data will be the Graphviz edge weight
+    attribute or the value 1 if no edge weight attribute is found.
+
+    """
+    if create_using is None:
+        if A.is_directed():
+            if A.is_strict():
+                create_using = nx.DiGraph
+            else:
+                create_using = nx.MultiDiGraph
+        else:
+            if A.is_strict():
+                create_using = nx.Graph
+            else:
+                create_using = nx.MultiGraph
+
+    # assign defaults
+    N = nx.empty_graph(0, create_using)
+    if A.name is not None:
+        N.name = A.name
+
+    # add graph attributes
+    N.graph.update(A.graph_attr)
+
+    # add nodes, attributes to N.node_attr
+    for n in A.nodes():
+        str_attr = {str(k): v for k, v in n.attr.items()}
+        N.add_node(str(n), **str_attr)
+
+    # add edges, assign edge data as dictionary of attributes
+    for e in A.edges():
+        u, v = str(e[0]), str(e[1])
+        attr = dict(e.attr)
+        str_attr = {str(k): v for k, v in attr.items()}
+        if not N.is_multigraph():
+            if e.name is not None:
+                str_attr['key'] = e.name
+            N.add_edge(u, v, **str_attr)
+        else:
+            N.add_edge(u, v, key=e.name, **str_attr)
+
+    # add default attributes for graph, nodes, and edges
+    # hang them on N.graph_attr
+    N.graph['graph'] = dict(A.graph_attr)
+    N.graph['node'] = dict(A.node_attr)
+    N.graph['edge'] = dict(A.edge_attr)
+    return N
+
+
+def to_agraph(N):
+    """Returns a pygraphviz graph from a NetworkX graph N.
+
+    Parameters
+    ----------
+    N : NetworkX graph
+      A graph created with NetworkX
+
+    Examples
+    --------
+    >>> K5 = nx.complete_graph(5)
+    >>> A = nx.nx_agraph.to_agraph(K5)
+
+    Notes
+    -----
+    If N has an dict N.graph_attr an attempt will be made first
+    to copy properties attached to the graph (see from_agraph)
+    and then updated with the calling arguments if any.
+
+    """
+    try:
+        import pygraphviz
+    except ImportError:
+        raise ImportError('requires pygraphviz ',
+                          'http://pygraphviz.github.io/')
+    directed = N.is_directed()
+    strict = nx.number_of_selfloops(N) == 0 and not N.is_multigraph()
+    A = pygraphviz.AGraph(name=N.name, strict=strict, directed=directed)
+
+    # default graph attributes
+    A.graph_attr.update(N.graph.get('graph', {}))
+    A.node_attr.update(N.graph.get('node', {}))
+    A.edge_attr.update(N.graph.get('edge', {}))
+
+    A.graph_attr.update((k, v) for k, v in N.graph.items()
+                        if k not in ('graph', 'node', 'edge'))
+
+    # add nodes
+    for n, nodedata in N.nodes(data=True):
+        A.add_node(n)
+        if nodedata is not None:
+            a = A.get_node(n)
+            a.attr.update({k: str(v) for k, v in nodedata.items()})
+
+    # loop over edges
+    if N.is_multigraph():
+        for u, v, key, edgedata in N.edges(data=True, keys=True):
+            str_edgedata = {k: str(v) for k, v in edgedata.items()
+                            if k != 'key'}
+            A.add_edge(u, v, key=str(key))
+            if edgedata is not None:
+                a = A.get_edge(u, v)
+                a.attr.update(str_edgedata)
+
+    else:
+        for u, v, edgedata in N.edges(data=True):
+            str_edgedata = {k: str(v) for k, v in edgedata.items()}
+            A.add_edge(u, v)
+            if edgedata is not None:
+                a = A.get_edge(u, v)
+                a.attr.update(str_edgedata)
+
+    return A
+
+
+def write_dot(G, path):
+    """Write NetworkX graph G to Graphviz dot format on path.
+
+    Parameters
+    ----------
+    G : graph
+       A networkx graph
+    path : filename
+       Filename or file handle to write
+    """
+    try:
+        import pygraphviz
+    except ImportError:
+        raise ImportError('requires pygraphviz ',
+                          'http://pygraphviz.github.io/')
+    A = to_agraph(G)
+    A.write(path)
+    A.clear()
+    return
+
+
+def read_dot(path):
+    """Returns a NetworkX graph from a dot file on path.
+
+    Parameters
+    ----------
+    path : file or string
+       File name or file handle to read.
+    """
+    try:
+        import pygraphviz
+    except ImportError:
+        raise ImportError('read_dot() requires pygraphviz ',
+                          'http://pygraphviz.github.io/')
+    A = pygraphviz.AGraph(file=path)
+    return from_agraph(A)
+
+
+def graphviz_layout(G, prog='neato', root=None, args=''):
+    """Create node positions for G using Graphviz.
+
+    Parameters
+    ----------
+    G : NetworkX graph
+      A graph created with NetworkX
+    prog : string
+      Name of Graphviz layout program
+    root : string, optional
+      Root node for twopi layout
+    args : string, optional
+      Extra arguments to Graphviz layout program
+
+    Returns
+    -------
+      Dictionary of x, y, positions keyed by node.
+
+    Examples
+    --------
+    >>> G = nx.petersen_graph()
+    >>> pos = nx.nx_agraph.graphviz_layout(G)
+    >>> pos = nx.nx_agraph.graphviz_layout(G, prog='dot')
+
+    Notes
+    -----
+    This is a wrapper for pygraphviz_layout.
+    """
+    return pygraphviz_layout(G, prog=prog, root=root, args=args)
+
+
+def pygraphviz_layout(G, prog='neato', root=None, args=''):
+    """Create node positions for G using Graphviz.
+
+    Parameters
+    ----------
+    G : NetworkX graph
+      A graph created with NetworkX
+    prog : string
+      Name of Graphviz layout program
+    root : string, optional
+      Root node for twopi layout
+    args : string, optional
+      Extra arguments to Graphviz layout program
+
+    Returns : dictionary
+      Dictionary of x, y, positions keyed by node.
+
+    Examples
+    --------
+    >>> G = nx.petersen_graph()
+    >>> pos = nx.nx_agraph.graphviz_layout(G)
+    >>> pos = nx.nx_agraph.graphviz_layout(G, prog='dot')
+
+    Notes
+    -----
+    If you use complex node objects, they may have the same string
+    representation and GraphViz could treat them as the same node.
+    The layout may assign both nodes a single location. See Issue #1568
+    If this occurs in your case, consider relabeling the nodes just
+    for the layout computation using something similar to:
+
+        H = nx.convert_node_labels_to_integers(G, label_attribute='node_label')
+        H_layout = nx.nx_agraph.pygraphviz_layout(G, prog='dot')
+        G_layout = {H.nodes[n]['node_label']: p for n, p in H_layout.items()}
+
+    """
+    try:
+        import pygraphviz
+    except ImportError:
+        raise ImportError('requires pygraphviz ',
+                          'http://pygraphviz.github.io/')
+    if root is not None:
+        args += "-Groot=%s" % root
+    A = to_agraph(G)
+    A.layout(prog=prog, args=args)
+    node_pos = {}
+    for n in G:
+        node = pygraphviz.Node(A, n)
+        try:
+            xs = node.attr["pos"].split(',')
+            node_pos[n] = tuple(float(x) for x in xs)
+        except:
+            print("no position for node", n)
+            node_pos[n] = (0.0, 0.0)
+    return node_pos
+
+
+@nx.utils.open_file(5, 'w+b')
+def view_pygraphviz(G, edgelabel=None, prog='dot', args='',
+                    suffix='', path=None):
+    """Views the graph G using the specified layout algorithm.
+
+    Parameters
+    ----------
+    G : NetworkX graph
+        The machine to draw.
+    edgelabel : str, callable, None
+        If a string, then it specifes the edge attribute to be displayed
+        on the edge labels. If a callable, then it is called for each
+        edge and it should return the string to be displayed on the edges.
+        The function signature of `edgelabel` should be edgelabel(data),
+        where `data` is the edge attribute dictionary.
+    prog : string
+        Name of Graphviz layout program.
+    args : str
+        Additional arguments to pass to the Graphviz layout program.
+    suffix : str
+        If `filename` is None, we save to a temporary file.  The value of
+        `suffix` will appear at the tail end of the temporary filename.
+    path : str, None
+        The filename used to save the image.  If None, save to a temporary
+        file.  File formats are the same as those from pygraphviz.agraph.draw.
+
+    Returns
+    -------
+    path : str
+        The filename of the generated image.
+    A : PyGraphviz graph
+        The PyGraphviz graph instance used to generate the image.
+
+    Notes
+    -----
+    If this function is called in succession too quickly, sometimes the
+    image is not displayed. So you might consider time.sleep(.5) between
+    calls if you experience problems.
+
+    """
+    if not len(G):
+        raise nx.NetworkXException("An empty graph cannot be drawn.")
+
+    import pygraphviz
+
+    # If we are providing default values for graphviz, these must be set
+    # before any nodes or edges are added to the PyGraphviz graph object.
+    # The reason for this is that default values only affect incoming objects.
+    # If you change the default values after the objects have been added,
+    # then they inherit no value and are set only if explicitly set.
+
+    # to_agraph() uses these values.
+    attrs = ['edge', 'node', 'graph']
+    for attr in attrs:
+        if attr not in G.graph:
+            G.graph[attr] = {}
+
+    # These are the default values.
+    edge_attrs = {'fontsize': '10'}
+    node_attrs = {'style': 'filled',
+                  'fillcolor': '#0000FF40',
+                  'height': '0.75',
+                  'width': '0.75',
+                  'shape': 'circle'}
+    graph_attrs = {}
+
+    def update_attrs(which, attrs):
+        # Update graph attributes. Return list of those which were added.
+        added = []
+        for k, v in attrs.items():
+            if k not in G.graph[which]:
+                G.graph[which][k] = v
+                added.append(k)
+
+    def clean_attrs(which, added):
+        # Remove added attributes
+        for attr in added:
+            del G.graph[which][attr]
+        if not G.graph[which]:
+            del G.graph[which]
+
+    # Update all default values
+    update_attrs('edge', edge_attrs)
+    update_attrs('node', node_attrs)
+    update_attrs('graph', graph_attrs)
+
+    # Convert to agraph, so we inherit default values
+    A = to_agraph(G)
+
+    # Remove the default values we added to the original graph.
+    clean_attrs('edge', edge_attrs)
+    clean_attrs('node', node_attrs)
+    clean_attrs('graph', graph_attrs)
+
+    # If the user passed in an edgelabel, we update the labels for all edges.
+    if edgelabel is not None:
+        if not hasattr(edgelabel, '__call__'):
+            def func(data):
+                return ''.join(["  ", str(data[edgelabel]), "  "])
+        else:
+            func = edgelabel
+
+        # update all the edge labels
+        if G.is_multigraph():
+            for u, v, key, data in G.edges(keys=True, data=True):
+                # PyGraphviz doesn't convert the key to a string. See #339
+                edge = A.get_edge(u, v, str(key))
+                edge.attr['label'] = str(func(data))
+        else:
+            for u, v, data in G.edges(data=True):
+                edge = A.get_edge(u, v)
+                edge.attr['label'] = str(func(data))
+
+    if path is None:
+        ext = 'png'
+        if suffix:
+            suffix = '_%s.%s' % (suffix, ext)
+        else:
+            suffix = '.%s' % (ext,)
+        path = tempfile.NamedTemporaryFile(suffix=suffix, delete=False)
+    else:
+        # Assume the decorator worked and it is a file-object.
+        pass
+
+    display_pygraphviz(A, path=path, prog=prog, args=args)
+
+    return path.name, A
+
+
+def display_pygraphviz(graph, path, format=None, prog=None, args=''):
+    """Internal function to display a graph in OS dependent manner.
+
+    Parameters
+    ----------
+    graph : PyGraphviz graph
+        A PyGraphviz AGraph instance.
+    path :  file object
+        An already opened file object that will be closed.
+    format : str, None
+        An attempt is made to guess the output format based on the extension
+        of the filename. If that fails, the value of `format` is used.
+    prog : string
+        Name of Graphviz layout program.
+    args : str
+        Additional arguments to pass to the Graphviz layout program.
+
+    Notes
+    -----
+    If this function is called in succession too quickly, sometimes the
+    image is not displayed. So you might consider time.sleep(.5) between
+    calls if you experience problems.
+
+    """
+    if format is None:
+        filename = path.name
+        format = os.path.splitext(filename)[1].lower()[1:]
+    if not format:
+        # Let the draw() function use its default
+        format = None
+
+    # Save to a file and display in the default viewer.
+    # We must close the file before viewing it.
+    graph.draw(path, format, prog, args)
+    path.close()
+    nx.utils.default_opener(filename)
+
+
+# fixture for pytest
+def setup_module(module):
+    import pytest
+    pygraphviz = pytest.importorskip('pygraphviz')