Exemplo n.º 1
0
def generate_pajek_(G):
    import warnings
    from networkx.utils import is_string_like, open_file, make_str

    if G.name == '':
        name = 'NetworkX'
    else:
        name = G.name
    # Apparently many Pajek format readers can't process this line
    # So we'll leave it out for now.
    # yield '*network %s'%name

    # write nodes with attributes
    yield '*vertices %s' % (G.order())
    nodes = list(G)
    # make dictionary mapping nodes to integers
    nodenumber = dict(zip(nodes, range(1, len(nodes) + 1)))
    for n in nodes:
        # copy node attributes and pop mandatory attributes
        # to avoid duplication.
        na = G.nodes.get(n, {}).copy()
        x = na.pop('x', 0.0)
        y = na.pop('y', 0.0)
        id = int(na.pop('id', nodenumber[n]))
        nodenumber[n] = id
        shape = na.pop('shape', 'ellipse')
        s = ' '.join(map(make_qstr, (id, n, x, y, shape)))
        # only optional attributes are left in na.
        for k, v in na.items():
            if is_string_like(v) and v.strip() != '':
                s += ' %s %s' % (make_qstr(k), make_qstr(v))
            else:
                warnings.warn('Node attribute %s is not processed. %s.' %
                              (k,
                               'Empty attribute' if is_string_like(v) else
                               'Non-string attribute'))
        s = s.replace('\n', ' ')
        yield s

    # write edges with attributes
    if G.is_directed():
        yield '*arcs'
    else:
        yield '*edges'
    for u, v, edgedata in G.edges(data=True):
        d = edgedata.copy()
        value = d.pop('weight', 1.0)  # use 1 as default edge value
        s = ' '.join(map(make_qstr, (nodenumber[u], nodenumber[v], value)))
        for k, v in d.items():
            if is_string_like(v) and v.strip() != '':
                s += ' %s %s' % (make_qstr(k), make_qstr(v))
                s += ' '
            else:
                warnings.warn('Edge attribute %s is not processed. %s.' %
                              (k,
                               'Empty attribute' if is_string_like(v) else
                               'Non-string attribute'))
        yield s
Exemplo n.º 2
0
def generate_pajek(G):
    """Generate lines in Pajek graph format.

    Parameters
    ----------
    G : graph
       A Networkx graph

    References
    ----------
    See http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/draweps.htm
    for format information.
    """
    if G.name=='': 
        name='NetworkX'
    else:
        name=G.name
    yield '*network %s'%name

    # write nodes with attributes
    yield '*vertices %s'%(G.order())
    nodes = G.nodes()
    # make dictionary mapping nodes to integers
    nodenumber=dict(zip(nodes,range(1,len(nodes)+1))) 
    for n in nodes:
        na=G.node.get(n,{})
        x=na.get('x',0.0)
        y=na.get('y',0.0)
        id=int(na.get('id',nodenumber[n]))
        nodenumber[n]=id
        shape=na.get('shape','ellipse')
        s=' '.join(map(make_str,(id,n,x,y,shape)))
        for k,v in na.items():
            if is_string_like(v):
                # add quotes to any values with a blank space
                if " " in v: 
                    v="\"%s\""%v
            s+=' %s %s'%(k,v)
        yield s

    # write edges with attributes         
    if G.is_directed():
        yield '*arcs'
    else:
        yield '*edges'
    for u,v,edgedata in G.edges(data=True):
        d=edgedata.copy()
        value=d.pop('weight',1.0) # use 1 as default edge value
        s=' '.join(map(make_str,(nodenumber[u],nodenumber[v],value)))
        for k,v in d.items():
            if is_string_like(v):
                # add quotes to any values with a blank space
                if " " in v: 
                    v="\"%s\""%v
            s+=' %s %s'%(k,v)
        yield s
Exemplo n.º 3
0
def generate_pajek(G):
    """Generate lines in Pajek graph format.

    Parameters
    ----------
    G : graph
       A Networkx graph

    References
    ----------
    See http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/draweps.htm
    for format information.
    """
    if G.name == '':
        name = 'NetworkX'
    else:
        name = G.name
    yield '*network %s' % name

    # write nodes with attributes
    yield '*vertices %s' % (G.order())
    nodes = G.nodes()
    # make dictionary mapping nodes to integers
    nodenumber = dict(zip(nodes, range(1, len(nodes) + 1)))
    for n in nodes:
        na = G.node.get(n, {})
        x = na.get('x', 0.0)
        y = na.get('y', 0.0)
        id = int(na.get('id', nodenumber[n]))
        nodenumber[n] = id
        shape = na.get('shape', 'ellipse')
        s = ' '.join(map(make_str, (id, n, x, y, shape)))
        for k, v in na.items():
            if is_string_like(v):
                # add quotes to any values with a blank space
                if " " in v:
                    v = "\"%s\"" % v
            s += ' %s %s' % (k, v)
        yield s

    # write edges with attributes
    if G.is_directed():
        yield '*arcs'
    else:
        yield '*edges'
    for u, v, edgedata in G.edges(data=True):
        d = edgedata.copy()
        value = d.pop('weight', 1.0)  # use 1 as default edge value
        s = ' '.join(map(make_str, (nodenumber[u], nodenumber[v], value)))
        for k, v in d.items():
            if is_string_like(v):
                # add quotes to any values with a blank space
                if " " in v:
                    v = "\"%s\"" % v
            s += ' %s %s' % (k, v)
        yield s
Exemplo n.º 4
0
def generate_pajek_(G):
    import warnings
    from networkx.utils import is_string_like, open_file, make_str

    if G.name == '':
        name = 'NetworkX'
    else:
        name = G.name
    # Apparently many Pajek format readers can't process this line
    # So we'll leave it out for now.
    # yield '*network %s'%name

    # write nodes with attributes
    yield '*vertices %s' % (G.order())
    nodes = list(G)
    # make dictionary mapping nodes to integers
    nodenumber = dict(zip(nodes, range(1, len(nodes) + 1)))
    for n in nodes:
        # copy node attributes and pop mandatory attributes
        # to avoid duplication.
        na = G.nodes.get(n, {}).copy()
        x = na.pop('x', 0.0)
        y = na.pop('y', 0.0)
        id = int(na.pop('id', nodenumber[n]))
        nodenumber[n] = id
        shape = na.pop('shape', 'ellipse')
        s = ' '.join(map(make_qstr, (id, n, x, y, shape)))
        # only optional attributes are left in na.
        for k, v in na.items():
            if is_string_like(v) and v.strip() != '':
                s += ' %s %s' % (make_qstr(k), make_qstr(v))
            else:
                warnings.warn('Node attribute %s is not processed. %s.' %
                              (k, 'Empty attribute' if is_string_like(v) else
                               'Non-string attribute'))
        s = s.replace('\n', ' ')
        yield s

    # write edges with attributes
    if G.is_directed():
        yield '*arcs'
    else:
        yield '*edges'
    for u, v, edgedata in G.edges(data=True):
        d = edgedata.copy()
        value = d.pop('weight', 1.0)  # use 1 as default edge value
        s = ' '.join(map(make_qstr, (nodenumber[u], nodenumber[v], value)))
        for k, v in d.items():
            if is_string_like(v) and v.strip() != '':
                s += ' %s %s' % (make_qstr(k), make_qstr(v))
                s += ' '
            else:
                warnings.warn('Edge attribute %s is not processed. %s.' %
                              (k, 'Empty attribute' if is_string_like(v) else
                               'Non-string attribute'))
        yield s
Exemplo n.º 5
0
 def add_prefix1(x):
     prefix = rename[1]
     if is_string_like(x):
         name = prefix + x
     else:
         name = prefix + repr(x)
     return name
Exemplo n.º 6
0
 def add_prefix1(x):
     prefix = rename[1]
     if is_string_like(x):
         name = prefix + x
     else:
         name = prefix + repr(x)
     return name
Exemplo n.º 7
0
def parse_p2g(lines):
    """Parse p2g format graph from string or iterable. 

    Returns an MultiDiGraph.
    """
    if is_string_like(lines): lines=iter(lines.split('\n'))
    lines = iter([line.rstrip('\n') for line in lines])

    description = lines.next()
    # are multiedges (parallel edges) allowed?
    G=networkx.MultiDiGraph(name=description,selfloops=True)
    nnodes,nedges=map(int,lines.next().split())

    nodelabel={}
    nbrs={}
    # loop over the nodes keeping track of node labels and out neighbors
    # defer adding edges until all node labels are known
    for i in range(nnodes):
        n=lines.next()
        nodelabel[i]=n
        G.add_node(n)
        nbrs[n]=map(int,lines.next().split())

    # now we know all of the node labels so we can add the edges
    # with the correct labels        
    for n in G:
        for nbr in nbrs[n]:
            G.add_edge(n,nodelabel[nbr])
    return G
Exemplo n.º 8
0
def parse_p2g(lines):
    """Parse p2g format graph from string or iterable. Returns an XDiGraph."""
    if is_string_like(lines): lines = iter(lines.split('\n'))
    lines = iter([line.rstrip('\n') for line in lines])

    description = lines.next()
    # are multiedges (parallel edges) allowed?
    G = networkx.XDiGraph(name=description, selfloops=True)
    nnodes, nedges = map(int, lines.next().split())

    nodelabel = {}
    nbrs = {}
    # loop over the nodes keeping track of node labels and out neighbors
    # defer adding edges until all node labels are known
    for i in range(nnodes):
        n = lines.next()
        nodelabel[i] = n
        G.add_node(n)
        nbrs[n] = map(int, lines.next().split())

    # now we know all of the node labels so we can add the edges
    # with the correct labels
    for n in G:
        for nbr in nbrs[n]:
            G.add_edge(n, nodelabel[nbr])
    return G
Exemplo n.º 9
0
def write_pajek(G, path):
    """Write in Pajek format to path.

    Parameters
    ----------
    G : graph
       A networkx graph
    path : file or string
       File or filename to write.  
       Filenames ending in .gz or .bz2 will be compressed.

    Examples
    --------
    >>> G=nx.path_graph(4)
    >>> nx.write_pajek(G, "test.net")
    """
    fh=_get_fh(path,mode='w')

    if G.name=='': 
        name="NetworkX"
    else:
        name=G.name
    fh.write("*network %s\n"%name)

    # write nodes with attributes
    fh.write("*vertices %s\n"%(G.order()))
    nodes = G.nodes()
    # make dictionary mapping nodes to integers
    nodenumber=dict(zip(nodes,range(1,len(nodes)+1))) 
    for n in nodes:
        na=G.node[n].copy()
        x=na.pop('x',0.0)
        y=na.pop('y',0.0)
        id=int(na.pop('id',nodenumber[n]))
        nodenumber[n]=id
        shape=na.pop('shape','ellipse')
        fh.write("%d \"%s\" %f %f %s "%(id,n,float(x),float(y),shape))
        for k,v in na.items():
            fh.write("%s %s "%(k,v))
        fh.write("\n")                               
        
    # write edges with attributes         
    if G.is_directed():
        fh.write("*arcs\n")
    else:
        fh.write("*edges\n")
    for u,v,edgedata in G.edges(data=True):
        d=edgedata.copy()
        value=d.pop('weight',1.0) # use 1 as default edge value
        fh.write("%d %d %f "%(nodenumber[u],nodenumber[v],float(value)))
        for k,v in d.items():
            if is_string_like(v):
                # add quotes to any values with a blank space
                if " " in v: 
                    v="\"%s\""%v
            fh.write("%s %s "%(k,v))
        fh.write("\n")                               
Exemplo n.º 10
0
 def string_item(k,v,indent):
     # try to make a string of the data
     if type(v)==dict: 
         v=listify(v,indent,2)
     elif is_string_like(v):
         v='"%s"'%v
     elif type(v)==bool:
         v=int(v)
     return "%s %s"%(k,v)
Exemplo n.º 11
0
def parse_leda(lines):
    """Read graph in LEDA format from string or iterable.

    Parameters
    ----------
    lines : string or iterable
       Data in LEDA format.

    Returns
    -------
    G : NetworkX graph

    Examples
    --------
    G=nx.parse_leda(string)

    References
    ----------
    .. [1] http://www.algorithmic-solutions.info/leda_guide/graphs/leda_native_graph_fileformat.html
    """
    if is_string_like(lines):
        lines = iter(lines.split('\n'))
    lines = iter([
        line.rstrip('\n') for line in lines
        if not (line.startswith('#') or line.startswith('\n') or line == '')
    ])
    for i in range(3):
        next(lines)
    # Graph
    du = int(next(lines))  # -1=directed, -2=undirected
    if du == -1:
        G = nx.DiGraph()
    else:
        G = nx.Graph()

    # Nodes
    n = int(next(lines))  # number of nodes
    node = {}
    for i in range(1, n + 1):  # LEDA counts from 1 to n
        symbol = next(lines).rstrip().strip('|{}|  ')
        if symbol == "":
            symbol = str(i)  # use int if no label - could be trouble
        node[i] = symbol

    G.add_nodes_from([s for i, s in node.items()])

    # Edges
    m = int(next(lines))  # number of edges
    for i in range(m):
        try:
            s, t, reversal, label = next(lines).split()
        except:
            raise NetworkXError('Too few fields in LEDA.GRAPH edge %d' %
                                (i + 1))
        # BEWARE: no handling of reversal edges
        G.add_edge(node[int(s)], node[int(t)], label=label[2:-2])
    return G
Exemplo n.º 12
0
def make_qstr(t):
    """Return the string representation of t.
    Add outer double-quotes if the string has a space.
    """
    if not is_string_like(t):
        t = str(t)
    if " " in t:
        t=r'"%s"'%t
    return t
Exemplo n.º 13
0
def make_qstr(t):
    """Return the string representation of t.
    Add outer double-quotes if the string has a space.
    """
    if not is_string_like(t):
        t = str(t)
    if " " in t:
        t = r'"%s"' % t
    return t
Exemplo n.º 14
0
 def string_item(k, v, indent):
     # try to make a string of the data
     if type(v) == dict:
         v = listify(v, indent, 2)
     elif is_string_like(v):
         v = '"%s"' % v
     elif type(v) == bool:
         v = int(v)
     return "%s %s" % (k, v)
 def string_item(k,v,indent):
     # try to make a string of the data
     if type(v) == dict:
         v = listify(v, indent, 2)
     elif is_string_like(v):
         v = '"{0}"'.format(escape(v, quote=True))
         #v = '"{0}"'.format(v, quote=True)
     elif type(v) == bool:
         v = int(v)
     return "{0} {1}".format(k,v)
Exemplo n.º 16
0
 def string_item(k, v, indent):
     # try to make a string of the data
     if type(v) == dict:
         v = listify(v, indent, 2)
     elif is_string_like(v):
         v = '"{0}"'.format(escape(v, quote=True))
         #v = '"{0}"'.format(v, quote=True)
     elif type(v) == bool:
         v = int(v)
     return "{0} {1}".format(k, v)
Exemplo n.º 17
0
def parse_leda(lines):
    """Read graph in LEDA format from string or iterable.

    Parameters
    ----------
    lines : string or iterable
       Data in LEDA format.

    Returns
    -------
    G : NetworkX graph

    Examples
    --------
    G=nx.parse_leda(string)

    References
    ----------
    .. [1] http://www.algorithmic-solutions.info/leda_guide/graphs/leda_native_graph_fileformat.html
    """
    if is_string_like(lines):
        lines = iter(lines.split('\n'))
    lines = iter([line.rstrip('\n') for line in lines
                  if not (line.startswith('#') or line.startswith('\n') or line == '')])
    for i in range(3):
        next(lines)
    # Graph
    du = int(next(lines))  # -1=directed, -2=undirected
    if du == -1:
        G = nx.DiGraph()
    else:
        G = nx.Graph()

    # Nodes
    n = int(next(lines))  # number of nodes
    node = {}
    for i in range(1, n + 1):  # LEDA counts from 1 to n
        symbol = next(lines).rstrip().strip('|{}|  ')
        if symbol == "":
            symbol = str(i)  # use int if no label - could be trouble
        node[i] = symbol

    G.add_nodes_from([s for i, s in node.items()])

    # Edges
    m = int(next(lines))  # number of edges
    for i in range(m):
        try:
            s, t, reversal, label = next(lines).split()
        except:
            raise NetworkXError('Too few fields in LEDA.GRAPH edge %d' % (i + 1))
        # BEWARE: no handling of reversal edges
        G.add_edge(node[int(s)], node[int(t)], label=label[2:-2])
    return G
Exemplo n.º 18
0
 def graphml_datatype(val):
     if val is None:
         return "string"
     if is_string_like(val):
         return "string"
     if type(val) == type(1):
         return "int"
     if type(val) == type(1.0):
         return "double"
     if type(val) == type(True):
         return "boolean"
     if type(val) == type(1L):
         return "long"
Exemplo n.º 19
0
 def graphml_datatype(val):
     if val is None:
         return "string"
     if is_string_like(val):
         return "string"
     if type(val) == type(1):
         return "int"
     if type(val) == type(1.0):
         return "double"
     if type(val) == type(True):
         return "boolean"
     if type(val) == type(1L):
         return "long"
Exemplo n.º 20
0
def parse_pajek(lines):
    """Parse pajek format graph from string or iterable.."""
    import shlex
    if is_string_like(lines): lines=iter(lines.split('\n'))
    lines = iter([line.rstrip('\n') for line in lines])
    G=networkx.XDiGraph(selfloops=True) # are multiedges allowed in Pajek?
    G.node_attr={} # dictionary to hold node attributes
    directed=True # assume this is a directed network for now
    while lines:
        try:
            l=lines.next()
        except: #EOF
            break
        if l.startswith("*network"):
            label,name=l.split()
            G.name=name
        if l.startswith("*vertices"):
            nodelabels={}
            l,nnodes=l.split()
            for i in range(int(nnodes)):
                splitline=shlex.split(lines.next())
                id,label,x,y,shape=splitline[0:5]
                G.add_node(label)
                nodelabels[id]=label
                G.node_attr[label]={'id':id,'x':x,'y':y,'shape':shape}
                extra_attr=zip(splitline[5::2],splitline[6::2])
                G.node_attr[label].update(extra_attr)
        if l.startswith("*edges") or l.startswith("*arcs"):
            if l.startswith("*edge"):
                G=networkx.XGraph(G) # switch from digraph to graph
            for l in lines:
                splitline=shlex.split(l)
                ui,vi,w=splitline[0:3]
                u=nodelabels.get(ui,ui)
                v=nodelabels.get(vi,vi)
                edge_data={'value':float(w)}
                extra_attr=zip(splitline[3::2],splitline[4::2])
                edge_data.update(extra_attr)
                G.add_edge(u,v,edge_data)
    return G
Exemplo n.º 21
0
def parse_pajek(lines):
    """Parse pajek format graph from string or iterable.."""
    import shlex
    if is_string_like(lines): lines = iter(lines.split('\n'))
    lines = iter([line.rstrip('\n') for line in lines])
    G = networkx.XDiGraph(selfloops=True)  # are multiedges allowed in Pajek?
    G.node_attr = {}  # dictionary to hold node attributes
    directed = True  # assume this is a directed network for now
    while lines:
        try:
            l = lines.next()
        except:  #EOF
            break
        if l.startswith("*network"):
            label, name = l.split()
            G.name = name
        if l.startswith("*vertices"):
            nodelabels = {}
            l, nnodes = l.split()
            for i in range(int(nnodes)):
                splitline = shlex.split(lines.next())
                id, label, x, y, shape = splitline[0:5]
                G.add_node(label)
                nodelabels[id] = label
                G.node_attr[label] = {'id': id, 'x': x, 'y': y, 'shape': shape}
                extra_attr = zip(splitline[5::2], splitline[6::2])
                G.node_attr[label].update(extra_attr)
        if l.startswith("*edges") or l.startswith("*arcs"):
            if l.startswith("*edge"):
                G = networkx.XGraph(G)  # switch from digraph to graph
            for l in lines:
                splitline = shlex.split(l)
                ui, vi, w = splitline[0:3]
                u = nodelabels.get(ui, ui)
                v = nodelabels.get(vi, vi)
                edge_data = {'value': float(w)}
                extra_attr = zip(splitline[3::2], splitline[4::2])
                edge_data.update(extra_attr)
                G.add_edge(u, v, edge_data)
    return G
Exemplo n.º 22
0
def parse_leda(lines):
    """Parse LEDA.GRAPH format from string or iterable.
    Returns an Graph or DiGraph."""
    if is_string_like(lines): lines = iter(lines.split('\n'))
    lines = iter([line.rstrip('\n') for line in lines \
            if not (line.startswith('#') or line.startswith('\n') or line=='')])
    for i in range(3):
        lines.next()
    # Graph
    du = int(lines.next())  # -1 directed, -2 undirected
    if du == -1:
        G = networkx.DiGraph()
    else:
        G = networkx.Graph()

    # Nodes
    n = int(lines.next())  # number of vertices
    node = {}
    for i in range(1, n + 1):  # LEDA counts from 1 to n
        symbol = lines.next()[2:-3]  # strip out data from |{data}|
        if symbol == "":
            symbol = str(i)  # use int if no label - could be trouble
        node[i] = symbol

    G.add_nodes_from([s for i, s in node.items()])

    # Edges
    m = int(lines.next())  # number of edges
    for i in range(m):
        try:
            s, t, reversal, label = lines.next().split()
        except:
            raise NetworkXError,\
                  'Too few fields in LEDA.GRAPH edge %d' % (i+1)
        # BEWARE: no handling of reversal edges
        G.add_edge(node[int(s)], node[int(t)], label=label[2:-2])
    return G
Exemplo n.º 23
0
def parse_leda(lines):
    """Parse LEDA.GRAPH format from string or iterable.
    Returns an Graph or DiGraph."""
    if is_string_like(lines): lines=iter(lines.split('\n'))
    lines = iter([line.rstrip('\n') for line in lines \
            if not (line.startswith('#') or line.startswith('\n') or line=='')])
    for i in range(3):
        lines.next()
    # Graph
    du = int(lines.next())	# -1 directed, -2 undirected
    if du==-1:
        G = networkx.DiGraph()
    else:
        G = networkx.Graph()
        
    # Nodes
    n =int(lines.next())	# number of vertices
    node={}
    for i in range(1,n+1):  # LEDA counts from 1 to n
        symbol=lines.next()[2:-3]  # strip out data from |{data}|
        if symbol=="": symbol=str(i) # use int if no label - could be trouble
        node[i]=symbol

    G.add_nodes_from([s for i,s in node.items()])
	
    # Edges
    m = int(lines.next())	# number of edges
    for i in range(m):
        try:
            s,t,reversal,label=lines.next().split()
        except:
            raise NetworkXError,\
                  'Too few fields in LEDA.GRAPH edge %d' % (i+1)
        # BEWARE: no handling of reversal edges
        G.add_edge(node[int(s)],node[int(t)],label=label[2:-2])
    return G
Exemplo n.º 24
0
def parse_pajek(lines):
    """Parse Pajek format graph from string or iterable.

    Parameters
    ----------
    lines : string or iterable
       Data in Pajek format.

    Returns
    -------
    G : NetworkX graph

    See Also
    --------
    read_pajek()

    """
    import shlex
    # multigraph=False
    if is_string_like(lines): lines = iter(lines.split('\n'))
    lines = iter([line.rstrip('\n') for line in lines])
    G = nx.MultiDiGraph()  # are multiedges allowed in Pajek? assume yes
    while lines:
        try:
            l = next(lines)
        except:  #EOF
            break
        if l.lower().startswith("*network"):
            try:
                label, name = l.split(None, 1)
            except ValueError:
                # Line was not of the form:  *network NAME
                pass
            else:
                G.graph['name'] = name
        elif l.lower().startswith("*vertices"):
            nodelabels = {}
            l, nnodes = l.split()
            for i in range(int(nnodes)):
                l = next(lines)
                try:
                    splitline = [
                        x.decode('utf-8')
                        for x in shlex.split(make_str(l).encode('utf-8'))
                    ]
                except AttributeError:
                    splitline = shlex.split(str(l))
                id, label = splitline[0:2]
                G.add_node(label)
                nodelabels[id] = label
                G.node[label] = {'id': id}
                try:
                    x, y, shape = splitline[2:5]
                    G.node[label].update({
                        'x': float(x),
                        'y': float(y),
                        'shape': shape
                    })
                except:
                    pass
                extra_attr = zip(splitline[5::2], splitline[6::2])
                G.node[label].update(extra_attr)
        elif l.lower().startswith("*edges") or l.lower().startswith("*arcs"):
            if l.lower().startswith("*edge"):
                # switch from multidigraph to multigraph
                G = nx.MultiGraph(G)
            if l.lower().startswith("*arcs"):
                # switch to directed with multiple arcs for each existing edge
                G = G.to_directed()
            for l in lines:
                try:
                    splitline = [
                        x.decode('utf-8')
                        for x in shlex.split(make_str(l).encode('utf-8'))
                    ]
                except AttributeError:
                    splitline = shlex.split(str(l))

                if len(splitline) < 2:
                    continue
                ui, vi = splitline[0:2]
                u = nodelabels.get(ui, ui)
                v = nodelabels.get(vi, vi)
                # parse the data attached to this edge and put in a dictionary
                edge_data = {}
                try:
                    # there should always be a single value on the edge?
                    w = splitline[2:3]
                    edge_data.update({'weight': float(w[0])})
                except:
                    pass
                    # if there isn't, just assign a 1


#                    edge_data.update({'value':1})
                extra_attr = zip(splitline[3::2], splitline[4::2])
                edge_data.update(extra_attr)
                # if G.has_edge(u,v):
                #     multigraph=True
                G.add_edge(u, v, **edge_data)
    return G
Exemplo n.º 25
0
def parse_pajek(lines,edge_attr=True):
    """Parse pajek format graph from string or iterable.

    Primarily used as a helper for read_pajek().

    See Also
    --------
    read_pajek()

    """
    import shlex
    if is_string_like(lines): lines=iter(lines.split('\n'))
    lines = iter([line.rstrip('\n') for line in lines])
    G=nx.MultiDiGraph() # are multiedges allowed in Pajek?
    directed=True # assume this is a directed network for now
    while lines:
        try:
            l=lines.next()
        except: #EOF
            break
        if l.lower().startswith("*network"):
            label,name=l.split()
            G.name=name
        if l.lower().startswith("*vertices"):
            nodelabels={}
            l,nnodes=l.split()
            for i in range(int(nnodes)):
                splitline=shlex.split(lines.next())
                id,label=splitline[0:2]
                G.add_node(label)
                nodelabels[id]=label
                G.node[label]={'id':id}
                try: 
                    x,y,shape=splitline[2:5]
                    G.node[label].update({'x':x,'y':y,'shape':shape})
                except:
                    pass
                extra_attr=zip(splitline[5::2],splitline[6::2])
                G.node[label].update(extra_attr)
        if l.lower().startswith("*edges") or l.lower().startswith("*arcs"):
            if l.lower().startswith("*edge"):
               # switch from digraph to graph
                G=nx.MultiGraph(G)
            for l in lines:
                splitline=shlex.split(l)
                ui,vi=splitline[0:2]
                u=nodelabels.get(ui,ui)
                v=nodelabels.get(vi,vi)
                # parse the data attached to this edge and
                # put it in a dictionary 
                edge_data={}
                try:
                    # there should always be a single value on the edge?
                    w=splitline[2:3]
                    edge_data.update({'weight':float(w[0])})
                except:
                    pass
                    # if there isn't, just assign a 1
#                    edge_data.update({'value':1})
                extra_attr=zip(splitline[3::2],splitline[4::2])
                edge_data.update(extra_attr)
                G.add_edge(u,v,**edge_data)

    return G
Exemplo n.º 26
0
def generate_gml(G):
    """Generate a single entry of the graph G in GML format.

    Parameters
    ----------
    G : NetworkX graph

    Returns
    -------
    lines: string
       Lines in GML format.

    Notes
    -----
    This implementation does not support all Python data types as GML
    data.  Nodes, node attributes, edge attributes, and graph
    attributes must be either dictionaries or single stings or
    numbers.  If they are not an attempt is made to represent them as
    strings.  For example, a list as edge data
    G[1][2]['somedata']=[1,2,3], will be represented in the GML file
    as::

       edge [
         source 1
         target 2
         somedata "[1, 2, 3]"
       ]
    """

    # recursively make dicts into gml brackets
    def listify(d, indent, indentlevel):
        result = '[ \n'
        for k, v in d.items():
            result += (indentlevel+1)*indent + \
                string_item(k,v,indentlevel*indent)+'\n'
        return result + indentlevel * indent + "]"

    def string_item(k, v, indent):
        # try to make a string of the data
        if type(v) == dict:
            v = listify(v, indent, 2)
        elif is_string_like(v):
            v = '"%s"' % v
        elif type(v) == bool:
            v = int(v)
        return "%s %s" % (k, v)

    # check for attributes or assign empty dict
    if hasattr(G, 'graph_attr'):
        graph_attr = G.graph_attr
    else:
        graph_attr = {}
    if hasattr(G, 'node_attr'):
        node_attr = G.node_attr
    else:
        node_attr = {}

    indent = 2 * ' '
    count = iter(range(len(G)))
    node_id = {}

    yield "graph ["
    if G.is_directed():
        yield indent + "directed 1"
    # write graph attributes
    for k, v in G.graph.items():
        if k == 'directed':
            continue
        yield indent + string_item(k, v, indent)
    # write nodes
    for n in G:
        yield indent + "node ["
        # get id or assign number
        nid = G.node[n].get('id', next(count))
        node_id[n] = nid
        yield 2 * indent + "id %s" % nid
        label = G.node[n].get('label', n)
        if is_string_like(label):
            label = '"%s"' % label
        yield 2 * indent + 'label %s' % label
        if n in G:
            for k, v in G.node[n].items():
                if k == 'id' or k == 'label': continue
                yield 2 * indent + string_item(k, v, indent)
        yield indent + "]"
    # write edges
    for u, v, edgedata in G.edges_iter(data=True):
        yield indent + "edge ["
        yield 2 * indent + "source %s" % node_id[u]
        yield 2 * indent + "target %s" % node_id[v]
        for k, v in edgedata.items():
            if k == 'source': continue
            if k == 'target': continue
            yield 2 * indent + string_item(k, v, indent)
        yield indent + "]"
    yield "]"
Exemplo n.º 27
0
def write_gml(G, path):
    """
    Write the graph G in GML format to the file or file handle path.

    Examples
    ---------

    >>> G=nx.path_graph(4)
    >>> nx.write_gml(G,"test.gml")

    path can be a filehandle or a string with the name of the file.

    >>> fh=open("test.gml",'w')
    >>> nx.write_gml(G,fh)

    Filenames ending in .gz or .bz2 will be compressed.

    >>> nx.write_gml(G,"test.gml.gz")

    
    The output file will use the default text encoding on your system.
    It is possible to write files in other encodings by opening
    the file with the codecs module.  See doc/examples/unicode.py
    for hints.

    >>> import codecs
    >>> fh=codecs.open("test.gml",'w',encoding='iso8859-1')# use iso8859-1
    >>> nx.write_gml(G,fh)

    GML specifications indicate that the file should only use
    7bit ASCII text encoding.iso8859-1 (latin-1). 

    Only a single level of attributes for graphs, nodes, and edges,
    is supported.

    """
    fh=_get_fh(path,mode='w')        
#    comments="#"
#    pargs=comments+" "+' '.join(sys.argv)
#    fh.write("%s\n" % (pargs))
#    fh.write(comments+" GMT %s\n" % (time.asctime(time.gmtime())))
#    fh.write(comments+" %s\n" % (G.name))

    # check for attributes or assign empty dict
    if hasattr(G,'graph_attr'):
        graph_attr=G.graph_attr
    else:
        graph_attr={}
    if hasattr(G,'node_attr'):
        node_attr=G.node_attr
    else:
        node_attr={}

    indent=2*' '
    count=iter(range(G.number_of_nodes()))
    node_id={}

    fh.write("graph [\n")
    # write graph attributes 
    for k,v in graph_attr.items():
        if is_string_like(v):
            v='"'+v+'"'
        fh.write(indent+"%s %s\n"%(k,v))
    # write nodes        
    for n in G:
        fh.write(indent+"node [\n")
        # get id or assign number
        if n in node_attr:
            nid=node_attr[n].get('id',count.next())
        else:
            nid=count.next()
        node_id[n]=nid
        fh.write(2*indent+"id %s\n"%nid)
        fh.write(2*indent+"label \"%s\"\n"%n)
        if n in node_attr:
          for k,v in node_attr[n].items():
              if is_string_like(v): v='"'+v+'"'
              if k=='id': continue
              fh.write(2*indent+"%s %s\n"%(k,v))
        fh.write(indent+"]\n")
    # write edges
    for e in G.edges_iter():
        if len(e)==3:
            u,v,d=e
            # try to guess what is on the edge and do something reasonable
            edgedata={}
            if d is None:  # no data 
                pass
            elif hasattr(d,'iteritems'): # try dict-like
                edgedata=dict(d.iteritems())
            elif hasattr(d,'__iter__'): # some kind of container
                edgedata['data']=d.__repr__()
            else: # something else - string, number
                edgedata['data']=d
        else:
            u,v=e
            edgedata={}
        fh.write(indent+"edge [\n")
        fh.write(2*indent+"source %s\n"%node_id[u])
        fh.write(2*indent+"target %s\n"%node_id[v])
        for k,v in edgedata.items():
            if k=='source': continue
            if k=='target': continue
            if is_string_like(v): v='"'+v+'"'
            fh.write(2*indent+"%s %s\n"%(k,v))
        fh.write(indent+"]\n")
    fh.write("]\n")
Exemplo n.º 28
0
def parse_pajek_(lines):
    import shlex
    import networkx as nx
    from networkx.utils import is_string_like, open_file, make_str
    # multigraph=False
    if is_string_like(lines):
        lines = iter(lines.split('\n'))
    lines = iter([line.rstrip('\n') for line in lines])
    G = nx.MultiDiGraph()  # are multiedges allowed in Pajek? assume yes
    labels = []  # in the order of the file, needed for matrix
    while lines:
        try:
            l = next(lines)
        except:  # EOF
            break
        if l.lower().startswith("*network"):
            try:
                label, name = l.split(None, 1)
            except ValueError:
                # Line was not of the form:  *network NAME
                pass
            else:
                G.graph['name'] = name
        elif l.lower().startswith("*vertices"):
            nodelabels = {}
            l, nnodes = l.split()
            for i in range(int(nnodes)):
                l = next(lines)
                try:
                    splitline = [
                        x.decode('utf-8')
                        for x in shlex.split(make_str(l).encode('utf-8'))
                    ]
                except AttributeError:
                    splitline = shlex.split(str(l))
                id, label = splitline[0:2]
                labels.append(label)
                G.add_node(label)
                nodelabels[id] = label
                G.nodes[label]['id'] = id
                try:
                    x, y, shape = splitline[2:5]
                    G.nodes[label].update({
                        'x': float(x),
                        'y': float(y),
                        'shape': shape
                    })
                except:
                    pass
                extra_attr = zip(splitline[5::2], splitline[6::2])
                G.nodes[label].update(extra_attr)
        elif l.lower().startswith("*edges") or l.lower().startswith("*arcs"):
            if l.lower().startswith("*edge"):
                # switch from multidigraph to multigraph
                G = nx.MultiGraph(G)
            if l.lower().startswith("*arcs"):
                # switch to directed with multiple arcs for each existing edge
                G = G.to_directed()
            for l in lines:
                try:
                    splitline = [
                        x.decode('utf-8')
                        for x in shlex.split(make_str(l).encode('utf-8'))
                    ]
                except AttributeError:
                    splitline = shlex.split(str(l))

                if len(splitline) < 2:
                    continue
                ui, vi = splitline[0:2]
                u = nodelabels.get(ui, ui)
                v = nodelabels.get(vi, vi)
                # parse the data attached to this edge and put in a dictionary
                edge_data = {}
                try:
                    # there should always be a single value on the edge?
                    w = splitline[2:3]
                    edge_data.update({'weight': float(w[0])})
                except:
                    pass
                    # if there isn't, just assign a 1


#                    edge_data.update({'value':1})
                extra_attr = zip(splitline[3::2], splitline[4::2])
                edge_data.update(extra_attr)
                # if G.has_edge(u,v):
                #     multigraph=True
                G.add_edge(u, v, **edge_data)
        elif l.lower().startswith("*matrix"):
            G = nx.DiGraph(G)
            adj_list = ((labels[row], labels[col], {
                'weight': int(data)
            }) for (row, line) in enumerate(lines)
                        for (col, data) in enumerate(line.split())
                        if int(data) != 0)
            G.add_edges_from(adj_list)

    return G
Exemplo n.º 29
0
def union(G, H, create_using=None, rename=False, name=None):
    """ Return the union of graphs G and H.
    
    Graphs G and H must be disjoint, otherwise an exception is raised.

    Parameters
    ----------
    G,H : graph
       A NetworkX graph 

    create_using : NetworkX graph
       Use specified graph for result.  Otherwise a new graph is created.


    rename : bool (default=False)         
       Node names of G and H can be changed be specifying the tuple
       rename=('G-','H-') (for example).
       Node u in G is then renamed "G-u" and v in H is renamed "H-v".

    name : string       
       Specify name for union graph

    Notes       
    -----
    To force a disjoint union with node relabeling, use
    disjoint_union(G,H) or convert_node_labels_to integers().

    """
    if name is None:
        name = "union( %s, %s )" % (G.name, H.name)
    if create_using is None:
        R = G.__class__()
    else:
        R = create_using
        R.clear()
    R.name = name

    # rename graph to obtain disjoint node labels
    # note that for objects w/o succinct __name__,
    # the new labels can be quite verbose
    # See also disjoint_union
    if rename:  # create new string labels
        Gname = {}
        Hname = {}
        for v in G:
            if is_string_like(v):
                Gname[v] = rename[0] + v
            else:
                Gname[v] = rename[0] + repr(v)
        for v in H:
            if is_string_like(v):
                Hname[v] = rename[1] + v
            else:
                Hname[v] = rename[1] + repr(v)
    else:
        Gname = dict(((v, v) for v in G))
        Hname = dict(((v, v) for v in H))

    # node name check
    Hnames = set(Hname.values())
    Gnames = set(Gname.values())
    if Gnames & Hnames:
        raise networkx.NetworkXError,\
        "node sets of G and H are not disjoint. Use appropriate rename=('Gprefix','Hprefix')"
    # node names OK, now build union
    R.add_nodes_from(Gnames)
    R.add_edges_from(
        ((Gname[u], Gname[v], x) for u, v, x in G.edges_iter(data=True)))
    R.add_nodes_from(Hnames)
    R.add_edges_from(
        ((Hname[u], Hname[v], x) for u, v, x in H.edges_iter(data=True)))
    return R
Exemplo n.º 30
0
 def label(x):
     if is_string_like(x):
         name = prefix + x
     else:
         name = prefix + repr(x)
     return name
Exemplo n.º 31
0
def test_is_string_like():
    assert is_string_like("aaaa")
    assert not is_string_like(None)
    assert not is_string_like(123)
Exemplo n.º 32
0
def draw_networkx_edge_labels(G, pos,
                              edge_labels=None,
                              label_pos=0.5,
                              font_size=10,
                              font_color='k',
                              font_family='sans-serif',
                              font_weight='normal',
                              alpha=1.0,
                              bbox=None,
                              ax=None,
                              rotate=True,
                              **kwds):
    """Draw edge labels.

    Parameters
    ----------
    G : graph
       A networkx graph

    pos : dictionary
       A dictionary with nodes as keys and positions as values.
       Positions should be sequences of length 2.

    ax : Matplotlib Axes object, optional
       Draw the graph in the specified Matplotlib axes.

    alpha : float
       The text transparency (default=1.0)

    edge_labels : dictionary
       Edge labels in a dictionary keyed by edge two-tuple of text
       labels (default=None). Only labels for the keys in the dictionary
       are drawn.

    label_pos : float
       Position of edge label along edge (0=head, 0.5=center, 1=tail)

    font_size : int
       Font size for text labels (default=12)

    font_color : string
       Font color string (default='k' black)

    font_weight : string
       Font weight (default='normal')

    font_family : string
       Font family (default='sans-serif')

    bbox : Matplotlib bbox
       Specify text box shape and colors.

    clip_on : bool
       Turn on clipping at axis boundaries (default=True)

    Returns
    -------
    dict
        `dict` of labels keyed on the edges

    Examples
    --------
    >>> G = nx.dodecahedral_graph()
    >>> edge_labels = nx.draw_networkx_edge_labels(G, pos=nx.spring_layout(G))

    Also see the NetworkX drawing examples at
    https://networkx.github.io/documentation/latest/auto_examples/index.html

    See Also
    --------
    draw()
    draw_networkx()
    draw_networkx_nodes()
    draw_networkx_edges()
    draw_networkx_labels()
    """
    try:
        import matplotlib.pyplot as plt
        import numpy as np
    except ImportError:
        raise ImportError("Matplotlib required for draw()")
    except RuntimeError:
        print("Matplotlib unable to open display")
        raise

    if ax is None:
        ax = plt.gca()
    if edge_labels is None:
        labels = {(u, v): d for u, v, d in G.edges(data=True)}
    else:
        labels = edge_labels
    text_items = {}
    for (n1, n2), label in labels.items():
        (x1, y1) = pos[n1]
        (x2, y2) = pos[n2]
        (x, y) = (x1 * label_pos + x2 * (1.0 - label_pos),
                  y1 * label_pos + y2 * (1.0 - label_pos))

        if rotate:
            # in degrees
            angle = np.arctan2(y2 - y1, x2 - x1) / (2.0 * np.pi) * 360
            # make label orientation "right-side-up"
            if angle > 90:
                angle -= 180
            if angle < - 90:
                angle += 180
            # transform data coordinate angle to screen coordinate angle
            xy = np.array((x, y))
            trans_angle = ax.transData.transform_angles(np.array((angle,)),
                                                        xy.reshape((1, 2)))[0]
        else:
            trans_angle = 0.0
        # use default box of white with white border
        if bbox is None:
            bbox = dict(boxstyle='round',
                        ec=(1.0, 1.0, 1.0),
                        fc=(1.0, 1.0, 1.0),
                        )
        if not is_string_like(label):
            label = str(label)  # this makes "1" and 1 labeled the same

        # set optional alignment
        horizontalalignment = kwds.get('horizontalalignment', 'center')
        verticalalignment = kwds.get('verticalalignment', 'center')

        t = ax.text(x, y,
                    label,
                    size=font_size,
                    color=font_color,
                    family=font_family,
                    weight=font_weight,
                    alpha=alpha,
                    horizontalalignment=horizontalalignment,
                    verticalalignment=verticalalignment,
                    rotation=trans_angle,
                    transform=ax.transData,
                    bbox=bbox,
                    zorder=1,
                    clip_on=True,
                    )
        text_items[(n1, n2)] = t

    plt.tick_params(
        axis='both',
        which='both',
        bottom=False,
        left=False,
        labelbottom=False,
        labelleft=False)

    return text_items
Exemplo n.º 33
0
def parse_pajek(lines):
    """Parse pajek format graph from string or iterable.."""
    import shlex
    if is_string_like(lines): lines=iter(lines.split('\n'))
    lines = iter([line.rstrip('\n') for line in lines])
    G=networkx.DiGraph() # are multiedges allowed in Pajek?
    G.node_attr={} # dictionary to hold node attributes
    directed=True # assume this is a directed network for now
    while lines:
        try:
            l=lines.next()
            l=l.lower()
        except: #EOF
            break
        if l.startswith("#"):
            continue
        if l.startswith("*network"):
            label,name=l.split()
            G.name=name
        if l.startswith("*vertices"):
            nodelabels={}
            l,nnodes=l.split()
            while not l.startswith("*arcs"):
                if l.startswith('#'):
                    l = lines.next()
                    l = l.lower()
                    continue
                if l.startswith('*'):
                    l = lines.next()
                    l = l.lower()
                    continue
                splitline=shlex.split(l)
                #print splitline
                id, label = splitline[0:2]
                G.add_node(label)
                nodelabels[id]=label
                G.node_attr[label]={'id':id}                
                if len(splitline) > 2:
                    id,label,x,y=splitline[0:4]                
                    G.node_attr[label]={'id':id,'x':x,'y':y}
                extra_attr=zip(splitline[4::2],splitline[5::2])
                #print extra_attr
                G.node_attr[label].update(extra_attr)
                l = lines.next()
                l = l.lower()
        if l.startswith("*arcs"):
            for l in lines:
                if not l: break
                if l.startswith('#'): continue
                splitline=shlex.split(l)
                ui,vi,w=splitline[0:3]
                u=nodelabels.get(ui,ui)
                v=nodelabels.get(vi,vi)
                edge_data={'value':float(w)}
                extra_attr=zip(splitline[3::2],splitline[4::2])
                edge_data.update(extra_attr)
                if G.has_edge(u,v):
                    if G[u][v]['value'] > float(w):
                        G.add_edge(u,v,**edge_data)
                else:
                    G.add_edge(u,v,**edge_data)
    if not G.name:
        raise Exception("No graph definition found")
    if len(G.nodes()) == 0:
        raise Exception("No graph definition found")
    return G
Exemplo n.º 34
0
def draw_networkx_edges(G, pos,
                        edgelist=None,
                        width=1.0,
                        edge_color='k',
                        style='solid',
                        alpha=1.0,
                        arrowstyle='-|>',
                        arrowsize=10,
                        edge_cmap=None,
                        edge_vmin=None,
                        edge_vmax=None,
                        ax=None,
                        arrows=True,
                        label=None,
                        node_size=300,
                        nodelist=None,
                        node_shape="o",
                        connectionstyle=None,
                        **kwds):
    """Draw the edges of the graph G.

    This draws only the edges of the graph G.

    Parameters
    ----------
    G : graph
       A networkx graph

    pos : dictionary
       A dictionary with nodes as keys and positions as values.
       Positions should be sequences of length 2.

    edgelist : collection of edge tuples
       Draw only specified edges(default=G.edges())

    width : float, or array of floats
       Line width of edges (default=1.0)

    edge_color : color string, or array of floats
       Edge color. Can be a single color format string (default='r'),
       or a sequence of colors with the same length as edgelist.
       If numeric values are specified they will be mapped to
       colors using the edge_cmap and edge_vmin,edge_vmax parameters.

    style : string
       Edge line style (default='solid') (solid|dashed|dotted,dashdot)

    alpha : float
       The edge transparency (default=1.0)

    edge_ cmap : Matplotlib colormap
       Colormap for mapping intensities of edges (default=None)

    edge_vmin,edge_vmax : floats
       Minimum and maximum for edge colormap scaling (default=None)

    ax : Matplotlib Axes object, optional
       Draw the graph in the specified Matplotlib axes.

    arrows : bool, optional (default=True)
       For directed graphs, if True draw arrowheads.
       Note: Arrows will be the same color as edges.

    arrowstyle : str, optional (default='-|>')
       For directed graphs, choose the style of the arrow heads.
       See :py:class: `matplotlib.patches.ArrowStyle` for more
       options.

    arrowsize : int, optional (default=10)
       For directed graphs, choose the size of the arrow head head's length and
       width. See :py:class: `matplotlib.patches.FancyArrowPatch` for attribute
       `mutation_scale` for more info.

    connectionstyle : str, optional (default=None)
       Pass the connectionstyle parameter to create curved arc of rounding
       radius rad. For example, connectionstyle='arc3,rad=0.2'.
       See :py:class: `matplotlib.patches.ConnectionStyle` and
       :py:class: `matplotlib.patches.FancyArrowPatch` for more info.

    label : [None| string]
       Label for legend

    Returns
    -------
    matplotlib.collection.LineCollection
        `LineCollection` of the edges

    list of matplotlib.patches.FancyArrowPatch
        `FancyArrowPatch` instances of the directed edges

    Depending whether the drawing includes arrows or not.

    Notes
    -----
    For directed graphs, arrows are drawn at the head end.  Arrows can be
    turned off with keyword arrows=False. Be sure to include `node_size` as a
    keyword argument; arrows are drawn considering the size of nodes.

    Examples
    --------
    >>> G = nx.dodecahedral_graph()
    >>> edges = nx.draw_networkx_edges(G, pos=nx.spring_layout(G))

    >>> G = nx.DiGraph()
    >>> G.add_edges_from([(1, 2), (1, 3), (2, 3)])
    >>> arcs = nx.draw_networkx_edges(G, pos=nx.spring_layout(G))
    >>> alphas = [0.3, 0.4, 0.5]
    >>> for i, arc in enumerate(arcs):  # change alpha values of arcs
    ...     arc.set_alpha(alphas[i])

    Also see the NetworkX drawing examples at
    https://networkx.github.io/documentation/latest/auto_examples/index.html

    See Also
    --------
    draw()
    draw_networkx()
    draw_networkx_nodes()
    draw_networkx_labels()
    draw_networkx_edge_labels()
    """
    try:
        import matplotlib
        import matplotlib.pyplot as plt
        import matplotlib.cbook as cb
        from matplotlib.colors import colorConverter, Colormap, Normalize
        from matplotlib.collections import LineCollection
        from matplotlib.patches import FancyArrowPatch
        import numpy as np
    except ImportError:
        raise ImportError("Matplotlib required for draw()")
    except RuntimeError:
        print("Matplotlib unable to open display")
        raise

    if ax is None:
        ax = plt.gca()

    if edgelist is None:
        edgelist = list(G.edges())

    if not edgelist or len(edgelist) == 0:  # no edges!
        return None

    if nodelist is None:
        nodelist = list(G.nodes())

    # set edge positions
    edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist])

    if not cb.iterable(width):
        lw = (width,)
    else:
        lw = width

    if not is_string_like(edge_color) \
            and cb.iterable(edge_color) \
            and len(edge_color) == len(edge_pos):
        if np.alltrue([is_string_like(c) for c in edge_color]):
            # (should check ALL elements)
            # list of color letters such as ['k','r','k',...]
            edge_colors = tuple([colorConverter.to_rgba(c, alpha)
                                 for c in edge_color])
        elif np.alltrue([not is_string_like(c) for c in edge_color]):
            # If color specs are given as (rgb) or (rgba) tuples, we're OK
            if np.alltrue([cb.iterable(c) and len(c) in (3, 4)
                           for c in edge_color]):
                edge_colors = tuple(edge_color)
            else:
                # numbers (which are going to be mapped with a colormap)
                edge_colors = None
        else:
            raise ValueError('edge_color must contain color names or numbers')
    else:
        if is_string_like(edge_color) or len(edge_color) == 1:
            edge_colors = (colorConverter.to_rgba(edge_color, alpha), )
        else:
            msg = 'edge_color must be a color or list of one color per edge'
            raise ValueError(msg)

    if (not G.is_directed() or not arrows):
        edge_collection = LineCollection(edge_pos,
                                         colors=edge_colors,
                                         linewidths=lw,
                                         antialiaseds=(1,),
                                         linestyle=style,
                                         transOffset=ax.transData,
                                         )

        edge_collection.set_zorder(1)  # edges go behind nodes
        edge_collection.set_label(label)
        ax.add_collection(edge_collection)

        # Note: there was a bug in mpl regarding the handling of alpha values
        # for each line in a LineCollection. It was fixed in matplotlib by
        # r7184 and r7189 (June 6 2009). We should then not set the alpha
        # value globally, since the user can instead provide per-edge alphas
        # now.  Only set it globally if provided as a scalar.
        if isinstance(alpha, Number):
            edge_collection.set_alpha(alpha)

        if edge_colors is None:
            if edge_cmap is not None:
                assert(isinstance(edge_cmap, Colormap))
            edge_collection.set_array(np.asarray(edge_color))
            edge_collection.set_cmap(edge_cmap)
            if edge_vmin is not None or edge_vmax is not None:
                edge_collection.set_clim(edge_vmin, edge_vmax)
            else:
                edge_collection.autoscale()
        return edge_collection

    arrow_collection = None

    if G.is_directed() and arrows:
        # Note: Waiting for someone to implement arrow to intersection with
        # marker.  Meanwhile, this works well for polygons with more than 4
        # sides and circle.

        def to_marker_edge(marker_size, marker):
            if marker in "s^>v<d":  # `large` markers need extra space
                return np.sqrt(2 * marker_size) / 2
            else:
                return np.sqrt(marker_size) / 2

        # Draw arrows with `matplotlib.patches.FancyarrowPatch`
        arrow_collection = []
        mutation_scale = arrowsize  # scale factor of arrow head
        arrow_colors = edge_colors
        if arrow_colors is None:
            if edge_cmap is not None:
                assert(isinstance(edge_cmap, Colormap))
            else:
                edge_cmap = plt.get_cmap()  # default matplotlib colormap
            if edge_vmin is None:
                edge_vmin = min(edge_color)
            if edge_vmax is None:
                edge_vmax = max(edge_color)
            color_normal = Normalize(vmin=edge_vmin, vmax=edge_vmax)

        for i, (src, dst) in enumerate(edge_pos):
            x1, y1 = src
            x2, y2 = dst
            arrow_color = None
            line_width = None
            shrink_source = 0  # space from source to tail
            shrink_target = 0  # space from  head to target
            if cb.iterable(node_size):  # many node sizes
                src_node, dst_node = edgelist[i][:2]
                index_node = nodelist.index(dst_node)
                marker_size = node_size[index_node]
                shrink_target = to_marker_edge(marker_size, node_shape)
            else:
                shrink_target = to_marker_edge(node_size, node_shape)
            if arrow_colors is None:
                arrow_color = edge_cmap(color_normal(edge_color[i]))
            elif len(arrow_colors) > 1:
                arrow_color = arrow_colors[i]
            else:
                arrow_color = arrow_colors[0]
            if len(lw) > 1:
                line_width = lw[i]
            else:
                line_width = lw[0]
            arrow = FancyArrowPatch((x1, y1), (x2, y2),
                                    arrowstyle=arrowstyle,
                                    shrinkA=shrink_source,
                                    shrinkB=shrink_target,
                                    mutation_scale=mutation_scale,
                                    color=arrow_color,
                                    linewidth=line_width,
                                    connectionstyle=connectionstyle,
                                    zorder=1)  # arrows go behind nodes

            # There seems to be a bug in matplotlib to make collections of
            # FancyArrowPatch instances. Until fixed, the patches are added
            # individually to the axes instance.
            arrow_collection.append(arrow)
            ax.add_patch(arrow)

    # update view
    minx = np.amin(np.ravel(edge_pos[:, :, 0]))
    maxx = np.amax(np.ravel(edge_pos[:, :, 0]))
    miny = np.amin(np.ravel(edge_pos[:, :, 1]))
    maxy = np.amax(np.ravel(edge_pos[:, :, 1]))

    w = maxx - minx
    h = maxy - miny
    padx,  pady = 0.05 * w, 0.05 * h
    corners = (minx - padx, miny - pady), (maxx + padx, maxy + pady)
    ax.update_datalim(corners)
    ax.autoscale_view()

    plt.tick_params(
        axis='both',
        which='both',
        bottom=False,
        left=False,
        labelbottom=False,
        labelleft=False)

    return arrow_collection
Exemplo n.º 35
0
def write_gml(G, path):
    """
    Write the graph G in GML format to the file or file handle path.

    Examples
    ---------

    >>> G=nx.path_graph(4)
    >>> nx.write_gml(G,"test.gml")

    path can be a filehandle or a string with the name of the file.

    >>> fh=open("test.gml",'w')
    >>> nx.write_gml(G,fh)

    Filenames ending in .gz or .bz2 will be compressed.

    >>> nx.write_gml(G,"test.gml.gz")

    
    The output file will use the default text encoding on your system.
    It is possible to write files in other encodings by opening
    the file with the codecs module.  See doc/examples/unicode.py
    for hints.

    >>> import codecs
    >>> fh=codecs.open("test.gml",'w',encoding='iso8859-1')# use iso8859-1
    >>> nx.write_gml(G,fh)

    GML specifications indicate that the file should only use
    7bit ASCII text encoding.iso8859-1 (latin-1). 

    Only a single level of attributes for graphs, nodes, and edges,
    is supported.

    """
    fh = _get_fh(path, mode='w')
    #    comments="#"
    #    pargs=comments+" "+' '.join(sys.argv)
    #    fh.write("%s\n" % (pargs))
    #    fh.write(comments+" GMT %s\n" % (time.asctime(time.gmtime())))
    #    fh.write(comments+" %s\n" % (G.name))

    # check for attributes or assign empty dict
    if hasattr(G, 'graph_attr'):
        graph_attr = G.graph_attr
    else:
        graph_attr = {}
    if hasattr(G, 'node_attr'):
        node_attr = G.node_attr
    else:
        node_attr = {}

    indent = 2 * ' '
    count = iter(range(G.number_of_nodes()))
    node_id = {}

    fh.write("graph [\n")
    # write graph attributes
    for k, v in graph_attr.items():
        if is_string_like(v):
            v = '"' + v + '"'
        fh.write(indent + "%s %s\n" % (k, v))
    # write nodes
    for n in G:
        fh.write(indent + "node [\n")
        # get id or assign number
        if n in node_attr:
            nid = node_attr[n].get('id', count.next())
        else:
            nid = count.next()
        node_id[n] = nid
        fh.write(2 * indent + "id %s\n" % nid)
        fh.write(2 * indent + "label \"%s\"\n" % n)
        if n in node_attr:
            for k, v in node_attr[n].items():
                if is_string_like(v): v = '"' + v + '"'
                if k == 'id': continue
                fh.write(2 * indent + "%s %s\n" % (k, v))
        fh.write(indent + "]\n")
    # write edges
    for e in G.edges_iter():
        if len(e) == 3:
            u, v, d = e
            # try to guess what is on the edge and do something reasonable
            edgedata = {}
            if d is None:  # no data
                pass
            elif hasattr(d, 'iteritems'):  # try dict-like
                edgedata = dict(d.iteritems())
            elif hasattr(d, '__iter__'):  # some kind of container
                edgedata['data'] = d.__repr__()
            else:  # something else - string, number
                edgedata['data'] = d
        else:
            u, v = e
            edgedata = {}
        fh.write(indent + "edge [\n")
        fh.write(2 * indent + "source %s\n" % node_id[u])
        fh.write(2 * indent + "target %s\n" % node_id[v])
        for k, v in edgedata.items():
            if k == 'source': continue
            if k == 'target': continue
            if is_string_like(v): v = '"' + v + '"'
            fh.write(2 * indent + "%s %s\n" % (k, v))
        fh.write(indent + "]\n")
    fh.write("]\n")
Exemplo n.º 36
0
def draw_networkx_edges(G,
                        pos,
                        edgelist=None,
                        width=1.0,
                        edge_color='k',
                        style='solid',
                        alpha=1.0,
                        edge_cmap=None,
                        edge_vmin=None,
                        edge_vmax=None,
                        ax=None,
                        arrows=True,
                        label=None,
                        **kwds):
    """Draw the edges of the graph G.

    This draws only the edges of the graph G.

    Parameters
    ----------
    G : graph
       A networkx graph

    pos : dictionary
       A dictionary with nodes as keys and positions as values.
       Positions should be sequences of length 2.

    edgelist : collection of edge tuples
       Draw only specified edges(default=G.edges())

    width : float, or array of floats
       Line width of edges (default=1.0)

    edge_color : color string, or array of floats
       Edge color. Can be a single color format string (default='r'),
       or a sequence of colors with the same length as edgelist.
       If numeric values are specified they will be mapped to
       colors using the edge_cmap and edge_vmin,edge_vmax parameters.

    style : string
       Edge line style (default='solid') (solid|dashed|dotted,dashdot)

    alpha : float
       The edge transparency (default=1.0)

    edge_ cmap : Matplotlib colormap
       Colormap for mapping intensities of edges (default=None)

    edge_vmin,edge_vmax : floats
       Minimum and maximum for edge colormap scaling (default=None)

    ax : Matplotlib Axes object, optional
       Draw the graph in the specified Matplotlib axes.

    arrows : bool, optional (default=True)
       For directed graphs, if True draw arrowheads.

    label : [None| string]
       Label for legend

    Returns
    -------
    matplotlib.collection.LineCollection
        `LineCollection` of the edges

    Notes
    -----
    For directed graphs, "arrows" (actually just thicker stubs) are drawn
    at the head end.  Arrows can be turned off with keyword arrows=False.
    Yes, it is ugly but drawing proper arrows with Matplotlib this
    way is tricky.

    Examples
    --------
    >>> G = nx.dodecahedral_graph()
    >>> edges = nx.draw_networkx_edges(G, pos=nx.spring_layout(G))

    Also see the NetworkX drawing examples at
    https://networkx.github.io/documentation/latest/auto_examples/index.html

    See Also
    --------
    draw()
    draw_networkx()
    draw_networkx_nodes()
    draw_networkx_labels()
    draw_networkx_edge_labels()
    """
    try:
        import matplotlib
        import matplotlib.pyplot as plt
        import matplotlib.cbook as cb
        from matplotlib.colors import colorConverter, Colormap
        from matplotlib.collections import LineCollection
        import numpy as np
    except ImportError:
        raise ImportError("Matplotlib required for draw()")
    except RuntimeError:
        print("Matplotlib unable to open display")
        raise

    if ax is None:
        ax = plt.gca()

    if edgelist is None:
        edgelist = list(G.edges())

    if not edgelist or len(edgelist) == 0:  # no edges!
        return None

    # set edge positions
    edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist])

    if not cb.iterable(width):
        lw = (width, )
    else:
        lw = width

    if not is_string_like(edge_color) \
            and cb.iterable(edge_color) \
            and len(edge_color) == len(edge_pos):
        if np.alltrue([is_string_like(c) for c in edge_color]):
            # (should check ALL elements)
            # list of color letters such as ['k','r','k',...]
            edge_colors = tuple(
                [colorConverter.to_rgba(c, alpha) for c in edge_color])
        elif np.alltrue([not is_string_like(c) for c in edge_color]):
            # If color specs are given as (rgb) or (rgba) tuples, we're OK
            if np.alltrue(
                [cb.iterable(c) and len(c) in (3, 4) for c in edge_color]):
                edge_colors = tuple(edge_color)
            else:
                # numbers (which are going to be mapped with a colormap)
                edge_colors = None
        else:
            raise ValueError(
                'edge_color must consist of either color names or numbers')
    else:
        if is_string_like(edge_color) or len(edge_color) == 1:
            edge_colors = (colorConverter.to_rgba(edge_color, alpha), )
        else:
            raise ValueError(
                'edge_color must be a single color or list of exactly m colors where m is the number or edges'
            )

    edge_collection = LineCollection(
        edge_pos,
        colors=edge_colors,
        linewidths=lw,
        antialiaseds=(1, ),
        linestyle=style,
        transOffset=ax.transData,
    )

    edge_collection.set_zorder(1)  # edges go behind nodes
    edge_collection.set_label(label)
    ax.add_collection(edge_collection)

    # Note: there was a bug in mpl regarding the handling of alpha values for
    # each line in a LineCollection.  It was fixed in matplotlib in r7184 and
    # r7189 (June 6 2009).  We should then not set the alpha value globally,
    # since the user can instead provide per-edge alphas now.  Only set it
    # globally if provided as a scalar.
    if cb.is_numlike(alpha):
        edge_collection.set_alpha(alpha)

    if edge_colors is None:
        if edge_cmap is not None:
            assert (isinstance(edge_cmap, Colormap))
        edge_collection.set_array(np.asarray(edge_color))
        edge_collection.set_cmap(edge_cmap)
        if edge_vmin is not None or edge_vmax is not None:
            edge_collection.set_clim(edge_vmin, edge_vmax)
        else:
            edge_collection.autoscale()

    arrow_collection = None

    if G.is_directed() and arrows:

        # a directed graph hack
        # draw thick line segments at head end of edge
        # waiting for someone else to implement arrows that will work
        arrow_colors = edge_colors
        a_pos = []
        p = 1.0 - 0.25  # make head segment 25 percent of edge length
        for src, dst in edge_pos:
            x1, y1 = src
            x2, y2 = dst
            dx = x2 - x1  # x offset
            dy = y2 - y1  # y offset
            d = np.sqrt(float(dx**2 + dy**2))  # length of edge
            if d == 0:  # source and target at same position
                continue
            if dx == 0:  # vertical edge
                xa = x2
                ya = dy * p + y1
            if dy == 0:  # horizontal edge
                ya = y2
                xa = dx * p + x1
            else:
                theta = np.arctan2(dy, dx)
                xa = p * d * np.cos(theta) + x1
                ya = p * d * np.sin(theta) + y1

            a_pos.append(((xa, ya), (x2, y2)))

        arrow_collection = LineCollection(
            a_pos,
            colors=arrow_colors,
            linewidths=[4 * ww for ww in lw],
            antialiaseds=(1, ),
            transOffset=ax.transData,
        )

        arrow_collection.set_zorder(1)  # edges go behind nodes
        arrow_collection.set_label(label)
        ax.add_collection(arrow_collection)

    # update view
    minx = np.amin(np.ravel(edge_pos[:, :, 0]))
    maxx = np.amax(np.ravel(edge_pos[:, :, 0]))
    miny = np.amin(np.ravel(edge_pos[:, :, 1]))
    maxy = np.amax(np.ravel(edge_pos[:, :, 1]))

    w = maxx - minx
    h = maxy - miny
    padx, pady = 0.05 * w, 0.05 * h
    corners = (minx - padx, miny - pady), (maxx + padx, maxy + pady)
    ax.update_datalim(corners)
    ax.autoscale_view()

    #    if arrow_collection:

    return edge_collection
Exemplo n.º 37
0
def union(G,H,create_using=None,rename=False,name=None):
    """ Return the union of graphs G and H.
    
    Graphs G and H must be disjoint, otherwise an exception is raised.

    Parameters
    ----------
    G,H : graph
       A NetworkX graph 

    create_using : NetworkX graph
       Use specified graph for result.  Otherwise a new graph is created.


    rename : bool (default=False)         
       Node names of G and H can be changed be specifying the tuple
       rename=('G-','H-') (for example).
       Node u in G is then renamed "G-u" and v in H is renamed "H-v".

    name : string       
       Specify name for union graph

    Notes       
    -----
    To force a disjoint union with node relabeling, use
    disjoint_union(G,H) or convert_node_labels_to integers().

    """
    if name is None:
        name="union( %s, %s )"%(G.name,H.name)
    if create_using is None:
        R=G.__class__()
    else:
        R=create_using
        R.clear()
    R.name=name

    # rename graph to obtain disjoint node labels
    # note that for objects w/o succinct __name__,
    # the new labels can be quite verbose
    # See also disjoint_union
    if rename: # create new string labels
        Gname={}
        Hname={}
        for v in G:
            if is_string_like(v):
                Gname[v]=rename[0]+v
            else:
                Gname[v]=rename[0]+repr(v)
        for v in H:
            if is_string_like(v):
                Hname[v]=rename[1]+v
            else:
                Hname[v]=rename[1]+repr(v)
    else:
        Gname=dict( ((v,v) for v in G) )
        Hname=dict( ((v,v) for v in H) )

    # node name check
    Hnames=set(Hname.values())
    Gnames=set(Gname.values())
    if Gnames & Hnames:
            raise networkx.NetworkXError,\
            "node sets of G and H are not disjoint. Use appropriate rename=('Gprefix','Hprefix')"
    # node names OK, now build union
    R.add_nodes_from(Gnames)
    R.add_edges_from( ( (Gname[u],Gname[v],x) for u,v,x in G.edges_iter(data=True) ))
    R.add_nodes_from(Hnames)
    R.add_edges_from( ( (Hname[u],Hname[v],x) for u,v,x in H.edges_iter(data=True) ))
    return R
Exemplo n.º 38
0
def draw_networkx_labels(G, pos,
                         labels=None,
                         font_size=12,
                         font_color='k',
                         font_family='sans-serif',
                         font_weight='normal',
                         alpha=1.0,
                         bbox=None,
                         ax=None,
                         **kwds):
    """Draw node labels on the graph G.

    Parameters
    ----------
    G : graph
       A networkx graph

    pos : dictionary
       A dictionary with nodes as keys and positions as values.
       Positions should be sequences of length 2.

    labels : dictionary, optional (default=None)
       Node labels in a dictionary keyed by node of text labels

    font_size : int
       Font size for text labels (default=12)

    font_color : string
       Font color string (default='k' black)

    font_family : string
       Font family (default='sans-serif')

    font_weight : string
       Font weight (default='normal')

    alpha : float
       The text transparency (default=1.0)

    ax : Matplotlib Axes object, optional
       Draw the graph in the specified Matplotlib axes.

    Returns
    -------
    dict
        `dict` of labels keyed on the nodes

    Examples
    --------
    >>> G = nx.dodecahedral_graph()
    >>> labels = nx.draw_networkx_labels(G, pos=nx.spring_layout(G))

    Also see the NetworkX drawing examples at
    https://networkx.github.io/documentation/latest/auto_examples/index.html

    See Also
    --------
    draw()
    draw_networkx()
    draw_networkx_nodes()
    draw_networkx_edges()
    draw_networkx_edge_labels()
    """
    try:
        import matplotlib.pyplot as plt
        import matplotlib.cbook as cb
    except ImportError:
        raise ImportError("Matplotlib required for draw()")
    except RuntimeError:
        print("Matplotlib unable to open display")
        raise

    if ax is None:
        ax = plt.gca()

    if labels is None:
        labels = dict((n, n) for n in G.nodes())

    # set optional alignment
    horizontalalignment = kwds.get('horizontalalignment', 'center')
    verticalalignment = kwds.get('verticalalignment', 'center')

    text_items = {}  # there is no text collection so we'll fake one
    for n, label in labels.items():
        (x, y) = pos[n]
        if not is_string_like(label):
            label = str(label)  # this will cause "1" and 1 to be labeled the same
        t = ax.text(x, y,
                    label,
                    size=font_size,
                    color=font_color,
                    family=font_family,
                    weight=font_weight,
                    alpha=alpha,
                    horizontalalignment=horizontalalignment,
                    verticalalignment=verticalalignment,
                    transform=ax.transData,
                    bbox=bbox,
                    clip_on=True,
                    )
        text_items[n] = t

    return text_items
Exemplo n.º 39
0
def generate_gml(G):
    """Generate a single entry of the graph G in GML format.

    Parameters
    ----------
    G : NetworkX graph

    Returns
    -------
    lines: string
       Lines in GML format.

    Notes
    -----
    This implementation does not support all Python data types as GML
    data.  Nodes, node attributes, edge attributes, and graph
    attributes must be either dictionaries or single stings or
    numbers.  If they are not an attempt is made to represent them as
    strings.  For example, a list as edge data
    G[1][2]['somedata']=[1,2,3], will be represented in the GML file
    as::

       edge [
         source 1
         target 2
         somedata "[1, 2, 3]"
       ]
    """
    # recursively make dicts into gml brackets
    dicttype = type({})

    def listify(d, indent, indentlevel):
        result = "[ \n"
        dicttype = type({})
        for k, v in d.items():
            if type(v) == dicttype:
                v = listify(v, indent, indentlevel + 1)
            result += indentlevel * indent + "%s %s\n" % (k, v)
        return result + indentlevel * indent + "]"

    # check for attributes or assign empty dict
    if hasattr(G, "graph_attr"):
        graph_attr = G.graph_attr
    else:
        graph_attr = {}
    if hasattr(G, "node_attr"):
        node_attr = G.node_attr
    else:
        node_attr = {}

    indent = 2 * " "
    count = iter(range(len(G)))
    node_id = {}

    yield "graph ["
    if G.is_directed():
        yield indent + "directed 1"
    # write graph attributes
    for k, v in G.graph.items():
        if type(v) == dicttype:
            v = listify(v, indent, 2)
        elif is_string_like(v):
            v = '"%s"' % v
        yield indent + "%s %s" % (k, v)
    # write nodes
    for n in G:
        yield indent + "node ["
        # get id or assign number
        nid = G.node[n].get("id", next(count))
        node_id[n] = nid
        yield 2 * indent + "id %s" % nid
        label = G.node[n].pop("label", n)
        if is_string_like(label):
            label = '"%s"' % label
        yield 2 * indent + "label %s" % label
        if n in G:
            for k, v in G.node[n].items():
                if k == "id":
                    continue
                if type(v) == dicttype:
                    v = listify(v, indent, 3)
                elif is_string_like(v):
                    v = '"%s"' % v
                yield 2 * indent + "%s %s" % (k, v)
        yield indent + "]"
    # write edges
    for u, v, edgedata in G.edges_iter(data=True):
        # try to guess what is on the edge and do something reasonable
        yield indent + "edge ["
        yield 2 * indent + "source %s" % node_id[u]
        yield 2 * indent + "target %s" % node_id[v]
        for k, v in edgedata.items():
            if k == "source":
                continue
            if k == "target":
                continue
            if type(v) == dicttype:
                v = listify(v, indent, 3)
            elif is_string_like(v):
                v = '"%s"' % v
            yield 2 * indent + "%s %s" % (k, v)
        yield indent + "]"
    yield "]"
Exemplo n.º 40
0
def draw_networkx_edges(G, pos,
                        edgelist=None,
                        width=1.0,
                        edge_color='k',
                        style='solid',
                        alpha=1.0,
                        arrowstyle='-|>',
                        arrowsize=10,
                        edge_cmap=None,
                        edge_vmin=None,
                        edge_vmax=None,
                        ax=None,
                        arrows=True,
                        label=None,
                        node_size=300,
                        nodelist=None,
                        node_shape="o",
                        **kwds):
    """Draw the edges of the graph G.

    This draws only the edges of the graph G.

    Parameters
    ----------
    G : graph
       A networkx graph

    pos : dictionary
       A dictionary with nodes as keys and positions as values.
       Positions should be sequences of length 2.

    edgelist : collection of edge tuples
       Draw only specified edges(default=G.edges())

    width : float, or array of floats
       Line width of edges (default=1.0)

    edge_color : color string, or array of floats
       Edge color. Can be a single color format string (default='r'),
       or a sequence of colors with the same length as edgelist.
       If numeric values are specified they will be mapped to
       colors using the edge_cmap and edge_vmin,edge_vmax parameters.

    style : string
       Edge line style (default='solid') (solid|dashed|dotted,dashdot)

    alpha : float
       The edge transparency (default=1.0)

    edge_ cmap : Matplotlib colormap
       Colormap for mapping intensities of edges (default=None)

    edge_vmin,edge_vmax : floats
       Minimum and maximum for edge colormap scaling (default=None)

    ax : Matplotlib Axes object, optional
       Draw the graph in the specified Matplotlib axes.

    arrows : bool, optional (default=True)
       For directed graphs, if True draw arrowheads.
       Note: Arrows will be the same color as edges.

    arrowstyle : str, optional (default='-|>')
       For directed graphs, choose the style of the arrow heads.
       See :py:class: `matplotlib.patches.ArrowStyle` for more
       options.

    arrowsize : int, optional (default=10)
       For directed graphs, choose the size of the arrow head head's length and
       width. See :py:class: `matplotlib.patches.FancyArrowPatch` for attribute
       `mutation_scale` for more info.

    label : [None| string]
       Label for legend

    Returns
    -------
    matplotlib.collection.LineCollection
        `LineCollection` of the edges

    list of matplotlib.patches.FancyArrowPatch
        `FancyArrowPatch` instances of the directed edges

    Depending whether the drawing includes arrows or not.

    Notes
    -----
    For directed graphs, arrows are drawn at the head end.  Arrows can be
    turned off with keyword arrows=False. Be sure to include `node_size' as a
    keyword argument; arrows are drawn considering the size of nodes.

    Examples
    --------
    >>> G = nx.dodecahedral_graph()
    >>> edges = nx.draw_networkx_edges(G, pos=nx.spring_layout(G))

    >>> G = nx.DiGraph()
    >>> G.add_edges_from([(1, 2), (1, 3), (2, 3)])
    >>> arcs = nx.draw_networkx_edges(G, pos=nx.spring_layout(G))
    >>> alphas = [0.3, 0.4, 0.5]
    >>> for i, arc in enumerate(arcs):  # change alpha values of arcs
    ...     arc.set_alpha(alphas[i])

    Also see the NetworkX drawing examples at
    https://networkx.github.io/documentation/latest/auto_examples/index.html

    See Also
    --------
    draw()
    draw_networkx()
    draw_networkx_nodes()
    draw_networkx_labels()
    draw_networkx_edge_labels()
    """
    try:
        import matplotlib
        import matplotlib.pyplot as plt
        import matplotlib.cbook as cb
        from matplotlib.colors import colorConverter, Colormap, Normalize
        from matplotlib.collections import LineCollection
        from matplotlib.patches import FancyArrowPatch
        import numpy as np
    except ImportError:
        raise ImportError("Matplotlib required for draw()")
    except RuntimeError:
        print("Matplotlib unable to open display")
        raise

    if ax is None:
        ax = plt.gca()

    if edgelist is None:
        edgelist = list(G.edges())

    if not edgelist or len(edgelist) == 0:  # no edges!
        return None

    if nodelist is None:
        nodelist = list(G.nodes())

    # set edge positions
    edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist])

    if not cb.iterable(width):
        lw = (width,)
    else:
        lw = width

    if not is_string_like(edge_color) \
            and cb.iterable(edge_color) \
            and len(edge_color) == len(edge_pos):
        if np.alltrue([is_string_like(c) for c in edge_color]):
            # (should check ALL elements)
            # list of color letters such as ['k','r','k',...]
            edge_colors = tuple([colorConverter.to_rgba(c, alpha)
                                 for c in edge_color])
        elif np.alltrue([not is_string_like(c) for c in edge_color]):
            # If color specs are given as (rgb) or (rgba) tuples, we're OK
            if np.alltrue([cb.iterable(c) and len(c) in (3, 4)
                          for c in edge_color]):
                edge_colors = tuple(edge_color)
            else:
                # numbers (which are going to be mapped with a colormap)
                edge_colors = None
        else:
            raise ValueError('edge_color must contain color names or numbers')
    else:
        if is_string_like(edge_color) or len(edge_color) == 1:
            edge_colors = (colorConverter.to_rgba(edge_color, alpha), )
        else:
            msg = 'edge_color must be a color or list of one color per edge'
            raise ValueError(msg)

    if (not G.is_directed() or not arrows):
        edge_collection = LineCollection(edge_pos,
                                         colors=edge_colors,
                                         linewidths=lw,
                                         antialiaseds=(1,),
                                         linestyle=style,
                                         transOffset=ax.transData,
                                         )

        edge_collection.set_zorder(1)  # edges go behind nodes
        edge_collection.set_label(label)
        ax.add_collection(edge_collection)

        # Note: there was a bug in mpl regarding the handling of alpha values
        # for each line in a LineCollection. It was fixed in matplotlib by
        # r7184 and r7189 (June 6 2009). We should then not set the alpha
        # value globally, since the user can instead provide per-edge alphas
        # now.  Only set it globally if provided as a scalar.
        if cb.is_numlike(alpha):
            edge_collection.set_alpha(alpha)

        if edge_colors is None:
            if edge_cmap is not None:
                assert(isinstance(edge_cmap, Colormap))
            edge_collection.set_array(np.asarray(edge_color))
            edge_collection.set_cmap(edge_cmap)
            if edge_vmin is not None or edge_vmax is not None:
                edge_collection.set_clim(edge_vmin, edge_vmax)
            else:
                edge_collection.autoscale()
        return edge_collection

    arrow_collection = None

    if G.is_directed() and arrows:
        # Note: Waiting for someone to implement arrow to intersection with
        # marker.  Meanwhile, this works well for polygons with more than 4
        # sides and circle.

        def to_marker_edge(marker_size, marker):
            if marker in "s^>v<d":  # `large` markers need extra space
                return np.sqrt(2 * marker_size) / 2
            else:
                return np.sqrt(marker_size) / 2

        # Draw arrows with `matplotlib.patches.FancyarrowPatch`
        arrow_collection = []
        mutation_scale = arrowsize  # scale factor of arrow head
        arrow_colors = edge_colors
        if arrow_colors is None:
            if edge_cmap is not None:
                assert(isinstance(edge_cmap, Colormap))
            else:
                edge_cmap = plt.get_cmap()  # default matplotlib colormap
            if edge_vmin is None:
                edge_vmin = min(edge_color)
            if edge_vmax is None:
                edge_vmax = max(edge_color)
            color_normal = Normalize(vmin=edge_vmin, vmax=edge_vmax)

        for i, (src, dst) in enumerate(edge_pos):
            x1, y1 = src
            x2, y2 = dst
            arrow_color = None
            line_width = None
            shrink_source = 0  # space from source to tail
            shrink_target = 0  # space from  head to target
            if cb.iterable(node_size):  # many node sizes
                src_node, dst_node = edgelist[i]
                index_node = nodelist.index(dst_node)
                marker_size = node_size[index_node]
                shrink_target = to_marker_edge(marker_size, node_shape)
            else:
                shrink_target = to_marker_edge(node_size, node_shape)
            if arrow_colors is None:
                arrow_color = edge_cmap(color_normal(edge_color[i]))
            elif len(arrow_colors) > 1:
                arrow_color = arrow_colors[i]
            else:
                arrow_color = arrow_colors[0]
            if len(lw) > 1:
                line_width = lw[i]
            else:
                line_width = lw[0]
            arrow = FancyArrowPatch((x1, y1), (x2, y2),
                                    arrowstyle=arrowstyle,
                                    shrinkA=shrink_source,
                                    shrinkB=shrink_target,
                                    mutation_scale=mutation_scale,
                                    color=arrow_color,
                                    linewidth=line_width,
                                    zorder=1)  # arrows go behind nodes

            # There seems to be a bug in matplotlib to make collections of
            # FancyArrowPatch instances. Until fixed, the patches are added
            # individually to the axes instance.
            arrow_collection.append(arrow)
            ax.add_patch(arrow)

    # update view
    minx = np.amin(np.ravel(edge_pos[:, :, 0]))
    maxx = np.amax(np.ravel(edge_pos[:, :, 0]))
    miny = np.amin(np.ravel(edge_pos[:, :, 1]))
    maxy = np.amax(np.ravel(edge_pos[:, :, 1]))

    w = maxx - minx
    h = maxy - miny
    padx,  pady = 0.05 * w, 0.05 * h
    corners = (minx - padx, miny - pady), (maxx + padx, maxy + pady)
    ax.update_datalim(corners)
    ax.autoscale_view()

    return arrow_collection
Exemplo n.º 41
0
def generate_pajek(G):
    """Generate lines in Pajek graph format.

    Parameters
    ----------
    G : graph
       A Networkx graph

    References
    ----------
    See http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/draweps.htm
    for format information.
    """
    if G.name == '':
        name = 'NetworkX'
    else:
        name = G.name
    # Apparently many Pajek format readers can't process this line
    # So we'll leave it out for now.
    # yield '*network %s'%name

    # write nodes with attributes
    yield '*vertices %s' % (G.order())
    nodes = list(G)
    # make dictionary mapping nodes to integers
    nodenumber = dict(zip(nodes, range(1, len(nodes) + 1)))
    for n in nodes:
        # copy node attributes and pop mandatory attributes
        # to avoid duplication.
        na = G.nodes.get(n, {}).copy()
        x = na.pop('x', 0.0)
        y = na.pop('y', 0.0)
        id = int(na.pop('id', nodenumber[n]))
        nodenumber[n] = id
        shape = na.pop('shape', 'ellipse')
        s = ' '.join(map(make_qstr, (id, n, x, y, shape)))
        # only optional attributes are left in na.
        for k, v in na.items():
            if is_string_like(v) and v.strip() != '':
                s += ' %s %s' % (make_qstr(k), make_qstr(v))
            else:
                warnings.warn('Node attribute %s is not processed. %s.' %
                              (k, 'Empty attribute' if is_string_like(v) else
                               'Non-string attribute'))
        yield s

    # write edges with attributes
    if G.is_directed():
        yield '*arcs'
    else:
        yield '*edges'
    for u, v, edgedata in G.edges(data=True):
        d = edgedata.copy()
        value = d.pop('weight', 1.0)  # use 1 as default edge value
        s = ' '.join(map(make_qstr, (nodenumber[u], nodenumber[v], value)))
        for k, v in d.items():
            if is_string_like(v) and v.strip() != '':
                s += ' %s %s' % (make_qstr(k), make_qstr(v))
            else:
                warnings.warn('Edge attribute %s is not processed. %s.' %
                              (k, 'Empty attribute' if is_string_like(v) else
                               'Non-string attribute'))
        yield s
Exemplo n.º 42
0
def generate_gml(G):
    """Generate a single entry of the nxgraph G in GML format.

    Parameters
    ----------
    G : NetworkX nxgraph

    Returns
    -------
    lines: string
       Lines in GML format.

    Notes
    -----
    This implementation does not support all Python data types as GML
    data.  Nodes, node attributes, edge attributes, and nxgraph
    attributes must be either dictionaries or single stings or
    numbers.  If they are not an attempt is made to represent them as
    strings.  For example, a list as edge data
    G[1][2]['somedata']=[1,2,3], will be represented in the GML file
    as::

       edge [
         source 1
         target 2
         somedata "[1, 2, 3]"
       ]
    """
    # recursively make dicts into gml brackets
    def listify(d,indent,indentlevel):
        result='[ \n'
        for k,v in d.items():
            if type(v)==dict:
                v=listify(v,indent,indentlevel+1)
            result += (indentlevel+1)*indent + \
                string_item(k,v,indentlevel*indent)+'\n'
        return result+indentlevel*indent+"]"

    def string_item(k,v,indent):
        # try to make a string of the data
        if type(v)==dict: 
            v=listify(v,indent,2)
        elif is_string_like(v):
            v='"%s"'%v
        elif type(v)==bool:
            v=int(v)
        return "%s %s"%(k,v)

    # check for attributes or assign empty dict
    if hasattr(G,'graph_attr'):
        graph_attr=G.graph_attr
    else:
        graph_attr={}
    if hasattr(G,'node_attr'):
        node_attr=G.node_attr
    else:
        node_attr={}

    indent=2*' '
    count=iter(range(len(G)))
    node_id={}

    yield "nxgraph ["
    if G.is_directed():
        yield indent+"directed 1"
    # write nxgraph attributes
    for k,v in G.graph.items():
        if k == 'directed':
            continue
        yield indent+string_item(k,v,indent)
    # write nodes
    for n in G:
        yield indent+"node ["
        # get id or assign number
        nid=G.node[n].get('id',next(count))
        node_id[n]=nid
        yield 2*indent+"id %s"%nid
        label=G.node[n].get('label',n)
        if is_string_like(label):
            label='"%s"'%label
        yield 2*indent+'label %s'%label
        if n in G:
          for k,v in G.node[n].items():
              if k=='id' or k == 'label': continue
              yield 2*indent+string_item(k,v,indent)
        yield indent+"]"
    # write edges
    for u,v,edgedata in G.edges_iter(data=True):
        yield indent+"edge ["
        yield 2*indent+"source %s"%node_id[u]
        yield 2*indent+"target %s"%node_id[v]
        for k,v in edgedata.items():
            if k=='source': continue
            if k=='target': continue
            yield 2*indent+string_item(k,v,indent)
        yield indent+"]"
    yield "]"
Exemplo n.º 43
0
def draw_networkx_edges(G, pos,
                        edgelist=None,
                        width=1.0,
                        edge_color='k',
                        style='solid',
                        alpha=1.0,
                        edge_cmap=None,
                        edge_vmin=None,
                        edge_vmax=None,
                        ax=None,
                        arrows=True,
                        label=None,
                        **kwds):
    """Draw the edges of the graph G.

    This draws only the edges of the graph G.

    Parameters
    ----------
    G : graph
       A networkx graph

    pos : dictionary
       A dictionary with nodes as keys and positions as values.
       Positions should be sequences of length 2.

    edgelist : collection of edge tuples
       Draw only specified edges(default=G.edges())

    width : float, or array of floats
       Line width of edges (default=1.0)

    edge_color : color string, or array of floats
       Edge color. Can be a single color format string (default='r'),
       or a sequence of colors with the same length as edgelist.
       If numeric values are specified they will be mapped to
       colors using the edge_cmap and edge_vmin,edge_vmax parameters.

    style : string
       Edge line style (default='solid') (solid|dashed|dotted,dashdot)

    alpha : float
       The edge transparency (default=1.0)

    edge_ cmap : Matplotlib colormap
       Colormap for mapping intensities of edges (default=None)

    edge_vmin,edge_vmax : floats
       Minimum and maximum for edge colormap scaling (default=None)

    ax : Matplotlib Axes object, optional
       Draw the graph in the specified Matplotlib axes.

    arrows : bool, optional (default=True)
       For directed graphs, if True draw arrowheads.

    label : [None| string]
       Label for legend

    Returns
    -------
    matplotlib.collection.LineCollection
        `LineCollection` of the edges

    Notes
    -----
    For directed graphs, "arrows" (actually just thicker stubs) are drawn
    at the head end.  Arrows can be turned off with keyword arrows=False.
    Yes, it is ugly but drawing proper arrows with Matplotlib this
    way is tricky.

    Examples
    --------
    >>> G = nx.dodecahedral_graph()
    >>> edges = nx.draw_networkx_edges(G, pos=nx.spring_layout(G))

    Also see the NetworkX drawing examples at
    https://networkx.github.io/documentation/latest/auto_examples/index.html

    See Also
    --------
    draw()
    draw_networkx()
    draw_networkx_nodes()
    draw_networkx_labels()
    draw_networkx_edge_labels()
    """
    try:
        import matplotlib
        import matplotlib.pyplot as plt
        import matplotlib.cbook as cb
        from matplotlib.colors import colorConverter, Colormap
        from matplotlib.collections import LineCollection
        import numpy as np
    except ImportError:
        raise ImportError("Matplotlib required for draw()")
    except RuntimeError:
        print("Matplotlib unable to open display")
        raise

    if ax is None:
        ax = plt.gca()

    if edgelist is None:
        edgelist = list(G.edges())

    if not edgelist or len(edgelist) == 0:  # no edges!
        return None

    # set edge positions
    edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist])

    if not cb.iterable(width):
        lw = (width,)
    else:
        lw = width

    if not is_string_like(edge_color) \
            and cb.iterable(edge_color) \
            and len(edge_color) == len(edge_pos):
        if np.alltrue([is_string_like(c) for c in edge_color]):
            # (should check ALL elements)
            # list of color letters such as ['k','r','k',...]
            edge_colors = tuple([colorConverter.to_rgba(c, alpha)
                                 for c in edge_color])
        elif np.alltrue([not is_string_like(c) for c in edge_color]):
            # If color specs are given as (rgb) or (rgba) tuples, we're OK
            if np.alltrue([cb.iterable(c) and len(c) in (3, 4)
                          for c in edge_color]):
                edge_colors = tuple(edge_color)
            else:
                # numbers (which are going to be mapped with a colormap)
                edge_colors = None
        else:
            raise ValueError('edge_color must consist of either color names or numbers')
    else:
        if is_string_like(edge_color) or len(edge_color) == 1:
            edge_colors = (colorConverter.to_rgba(edge_color, alpha), )
        else:
            raise ValueError(
                'edge_color must be a single color or list of exactly m colors where m is the number or edges')

    edge_collection = LineCollection(edge_pos,
                                     colors=edge_colors,
                                     linewidths=lw,
                                     antialiaseds=(1,),
                                     linestyle=style,
                                     transOffset=ax.transData,
                                     )

    edge_collection.set_zorder(1)  # edges go behind nodes
    edge_collection.set_label(label)
    ax.add_collection(edge_collection)

    # Note: there was a bug in mpl regarding the handling of alpha values for
    # each line in a LineCollection.  It was fixed in matplotlib in r7184 and
    # r7189 (June 6 2009).  We should then not set the alpha value globally,
    # since the user can instead provide per-edge alphas now.  Only set it
    # globally if provided as a scalar.
    if cb.is_numlike(alpha):
        edge_collection.set_alpha(alpha)

    if edge_colors is None:
        if edge_cmap is not None:
            assert(isinstance(edge_cmap, Colormap))
        edge_collection.set_array(np.asarray(edge_color))
        edge_collection.set_cmap(edge_cmap)
        if edge_vmin is not None or edge_vmax is not None:
            edge_collection.set_clim(edge_vmin, edge_vmax)
        else:
            edge_collection.autoscale()

    arrow_collection = None

    if G.is_directed() and arrows:

        # a directed graph hack
        # draw thick line segments at head end of edge
        # waiting for someone else to implement arrows that will work
        arrow_colors = edge_colors
        a_pos = []
        p = 1.0 - 0.25  # make head segment 25 percent of edge length
        for src, dst in edge_pos:
            x1, y1 = src
            x2, y2 = dst
            dx = x2 - x1   # x offset
            dy = y2 - y1   # y offset
            d = np.sqrt(float(dx**2 + dy**2))  # length of edge
            if d == 0:   # source and target at same position
                continue
            if dx == 0:  # vertical edge
                xa = x2
                ya = dy * p + y1
            if dy == 0:  # horizontal edge
                ya = y2
                xa = dx * p + x1
            else:
                theta = np.arctan2(dy, dx)
                xa = p * d * np.cos(theta) + x1
                ya = p * d * np.sin(theta) + y1

            a_pos.append(((xa, ya), (x2, y2)))

        arrow_collection = LineCollection(a_pos,
                                          colors=arrow_colors,
                                          linewidths=[4 * ww for ww in lw],
                                          antialiaseds=(1,),
                                          transOffset=ax.transData,
                                          )

        arrow_collection.set_zorder(1)  # edges go behind nodes
        ax.add_collection(arrow_collection)

    # update view
    minx = np.amin(np.ravel(edge_pos[:, :, 0]))
    maxx = np.amax(np.ravel(edge_pos[:, :, 0]))
    miny = np.amin(np.ravel(edge_pos[:, :, 1]))
    maxy = np.amax(np.ravel(edge_pos[:, :, 1]))

    w = maxx - minx
    h = maxy - miny
    padx,  pady = 0.05 * w, 0.05 * h
    corners = (minx - padx, miny - pady), (maxx + padx, maxy + pady)
    ax.update_datalim(corners)
    ax.autoscale_view()

#    if arrow_collection:

    return edge_collection
Exemplo n.º 44
0
def parse_pajek(lines):
    """Parse Pajek format graph from string or iterable.

    Parameters
    ----------
    lines : string or iterable
       Data in Pajek format.

    Returns
    -------
    G : NetworkX graph

    See Also
    --------
    read_pajek()

    """
    import shlex

    # multigraph=False
    if is_string_like(lines):
        lines = iter(lines.split("\n"))
    lines = iter([line.rstrip("\n") for line in lines])
    G = nx.MultiDiGraph()  # are multiedges allowed in Pajek? assume yes
    labels = []  # in the order of the file, needed for matrix
    while lines:
        try:
            l = next(lines)
        except:  # EOF
            break
        if l.lower().startswith("*network"):
            try:
                label, name = l.split(None, 1)
            except ValueError:
                # Line was not of the form:  *network NAME
                pass
            else:
                G.graph["name"] = name
        elif l.lower().startswith("*vertices"):
            nodelabels = {}
            l, nnodes = l.split()
            for i in range(int(nnodes)):
                l = next(lines)
                try:
                    splitline = [x.decode("utf-8") for x in shlex.split(make_str(l).encode("utf-8"))]
                except AttributeError:
                    splitline = shlex.split(str(l))
                id, label = splitline[0:2]
                labels.append(label)
                G.add_node(label)
                nodelabels[id] = label
                G.node[label] = {"id": id}
                try:
                    x, y, shape = splitline[2:5]
                    G.node[label].update({"x": float(x), "y": float(y), "shape": shape})
                except:
                    pass
                extra_attr = zip(splitline[5::2], splitline[6::2])
                G.node[label].update(extra_attr)
        elif l.lower().startswith("*edges") or l.lower().startswith("*arcs"):
            if l.lower().startswith("*edge"):
                # switch from multidigraph to multigraph
                G = nx.MultiGraph(G)
            if l.lower().startswith("*arcs"):
                # switch to directed with multiple arcs for each existing edge
                G = G.to_directed()
            for l in lines:
                try:
                    splitline = [x.decode("utf-8") for x in shlex.split(make_str(l).encode("utf-8"))]
                except AttributeError:
                    splitline = shlex.split(str(l))

                if len(splitline) < 2:
                    continue
                ui, vi = splitline[0:2]
                u = nodelabels.get(ui, ui)
                v = nodelabels.get(vi, vi)
                # parse the data attached to this edge and put in a dictionary
                edge_data = {}
                try:
                    # there should always be a single value on the edge?
                    w = splitline[2:3]
                    edge_data.update({"weight": float(w[0])})
                except:
                    pass
                    # if there isn't, just assign a 1
                #                    edge_data.update({'value':1})
                extra_attr = zip(splitline[3::2], splitline[4::2])
                edge_data.update(extra_attr)
                # if G.has_edge(u,v):
                #     multigraph=True
                G.add_edge(u, v, **edge_data)
        elif l.lower().startswith("*matrix"):
            G = nx.DiGraph(G)
            adj_list = (
                (labels[row], labels[col], {"weight": int(data)})
                for (row, line) in enumerate(lines)
                for (col, data) in enumerate(line.split())
                if int(data) != 0
            )
            G.add_edges_from(adj_list)

    return G
Exemplo n.º 45
0
def draw_networkx_edge_labels(G, pos,
                              edge_labels=None,
                              label_pos=0.5,
                              font_size=10,
                              font_color='k',
                              font_family='sans-serif',
                              font_weight='normal',
                              alpha=1.0,
                              bbox=None,
                              ax=None,
                              rotate=True,
                              **kwds):
    """Draw edge labels.

    Parameters
    ----------
    G : graph
       A networkx graph

    pos : dictionary
       A dictionary with nodes as keys and positions as values.
       Positions should be sequences of length 2.

    ax : Matplotlib Axes object, optional
       Draw the graph in the specified Matplotlib axes.

    alpha : float
       The text transparency (default=1.0)

    edge_labels : dictionary
       Edge labels in a dictionary keyed by edge two-tuple of text
       labels (default=None). Only labels for the keys in the dictionary
       are drawn.

    label_pos : float
       Position of edge label along edge (0=head, 0.5=center, 1=tail)

    font_size : int
       Font size for text labels (default=12)

    font_color : string
       Font color string (default='k' black)

    font_weight : string
       Font weight (default='normal')

    font_family : string
       Font family (default='sans-serif')

    bbox : Matplotlib bbox
       Specify text box shape and colors.

    clip_on : bool
       Turn on clipping at axis boundaries (default=True)

    Returns
    -------
    dict
        `dict` of labels keyed on the edges

    Examples
    --------
    >>> G = nx.dodecahedral_graph()
    >>> edge_labels = nx.draw_networkx_edge_labels(G, pos=nx.spring_layout(G))

    Also see the NetworkX drawing examples at
    https://networkx.github.io/documentation/latest/auto_examples/index.html

    See Also
    --------
    draw()
    draw_networkx()
    draw_networkx_nodes()
    draw_networkx_edges()
    draw_networkx_labels()
    """
    try:
        import matplotlib.pyplot as plt
        import matplotlib.cbook as cb
        import numpy as np
    except ImportError:
        raise ImportError("Matplotlib required for draw()")
    except RuntimeError:
        print("Matplotlib unable to open display")
        raise

    if ax is None:
        ax = plt.gca()
    if edge_labels is None:
        labels = {(u, v): d for u, v, d in G.edges(data=True)}
    else:
        labels = edge_labels
    text_items = {}
    for (n1, n2), label in labels.items():
        (x1, y1) = pos[n1]
        (x2, y2) = pos[n2]
        (x, y) = (x1 * label_pos + x2 * (1.0 - label_pos),
                  y1 * label_pos + y2 * (1.0 - label_pos))

        if rotate:
            angle = np.arctan2(y2 - y1, x2 - x1) / (2.0 * np.pi) * 360  # degrees
            # make label orientation "right-side-up"
            if angle > 90:
                angle -= 180
            if angle < - 90:
                angle += 180
            # transform data coordinate angle to screen coordinate angle
            xy = np.array((x, y))
            trans_angle = ax.transData.transform_angles(np.array((angle,)),
                                                        xy.reshape((1, 2)))[0]
        else:
            trans_angle = 0.0
        # use default box of white with white border
        if bbox is None:
            bbox = dict(boxstyle='round',
                        ec=(1.0, 1.0, 1.0),
                        fc=(1.0, 1.0, 1.0),
                        )
        if not is_string_like(label):
            label = str(label)  # this will cause "1" and 1 to be labeled the same

        # set optional alignment
        horizontalalignment = kwds.get('horizontalalignment', 'center')
        verticalalignment = kwds.get('verticalalignment', 'center')

        t = ax.text(x, y,
                    label,
                    size=font_size,
                    color=font_color,
                    family=font_family,
                    weight=font_weight,
                    alpha=alpha,
                    horizontalalignment=horizontalalignment,
                    verticalalignment=verticalalignment,
                    rotation=trans_angle,
                    transform=ax.transData,
                    bbox=bbox,
                    zorder=1,
                    clip_on=True,
                    )
        text_items[(n1, n2)] = t

    return text_items
Exemplo n.º 46
0
 def label(x):
     if is_string_like(x):
         name = prefix + x
     else:
         name = prefix + repr(x)
     return name
Exemplo n.º 47
0
 def make_str(t):
     if is_string_like(t): return t
     return str(t)
Exemplo n.º 48
0
def parse_pajek(lines):
    """Parse Pajek format graph from string or iterable.

    Parameters
    ----------
    lines : string or iterable
       Data in Pajek format.

    Returns
    -------
    G : NetworkX graph

    See Also
    --------
    read_pajek()

    """
    import shlex
    # multigraph=False
    if is_string_like(lines): lines=iter(lines.split('\n'))
    lines = iter([line.rstrip('\n') for line in lines])
    G=nx.MultiDiGraph() # are multiedges allowed in Pajek? assume yes
    while lines:
        try:
            l=next(lines)
        except: #EOF
            break
        if l.lower().startswith("*network"):
            try:
                label, name = l.split()
            except ValueError:
                # Line was not of the form:  *network NAME
                pass
            else:
                G.graph['name'] = name
        elif l.lower().startswith("*vertices"):
            nodelabels={}
            l,nnodes=l.split()
            for i in range(int(nnodes)):
                splitline=shlex.split(str(next(lines)))
                id,label=splitline[0:2]
                G.add_node(label)
                nodelabels[id]=label
                G.node[label]={'id':id}
                try:
                    x,y,shape=splitline[2:5]
                    G.node[label].update({'x':float(x),
                                          'y':float(y),
                                          'shape':shape})
                except:
                    pass
                extra_attr=zip(splitline[5::2],splitline[6::2])
                G.node[label].update(extra_attr)
        elif l.lower().startswith("*edges") or l.lower().startswith("*arcs"):
            if l.lower().startswith("*edge"):
               # switch from multidigraph to multigraph
                G=nx.MultiGraph(G)
            if l.lower().startswith("*arcs"):
               # switch to directed with multiple arcs for each existing edge
                G=G.to_directed()
            for l in lines:
                splitline=shlex.split(str(l))
                if len(splitline)<2:
                    continue
                ui,vi=splitline[0:2]
                u=nodelabels.get(ui,ui)
                v=nodelabels.get(vi,vi)
                # parse the data attached to this edge and put in a dictionary
                edge_data={}
                try:
                    # there should always be a single value on the edge?
                    w=splitline[2:3]
                    edge_data.update({'weight':float(w[0])})
                except:
                    pass
                    # if there isn't, just assign a 1
#                    edge_data.update({'value':1})
                extra_attr=zip(splitline[3::2],splitline[4::2])
                edge_data.update(extra_attr)
                # if G.has_edge(u,v):
                #     multigraph=True
                G.add_edge(u,v,**edge_data)
    return G
Exemplo n.º 49
0
def generate_pajek(G):
    """Generate lines in Pajek graph format.

    Parameters
    ----------
    G : graph
       A Networkx graph

    References
    ----------
    See http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/draweps.htm
    for format information.
    """
    if G.name == '':
        name = 'NetworkX'
    else:
        name = G.name
    # Apparently many Pajek format readers can't process this line
    # So we'll leave it out for now.
    # yield '*network %s'%name

    # write nodes with attributes
    yield '*vertices %s' % (G.order())
    nodes = list(G)
    # make dictionary mapping nodes to integers
    nodenumber = dict(zip(nodes, range(1, len(nodes) + 1)))
    for n in nodes:
        # copy node attributes and pop mandatory attributes
        # to avoid duplication.
        na = G.nodes.get(n, {}).copy()
        x = na.pop('x', 0.0)
        y = na.pop('y', 0.0)
        id = int(na.pop('id', nodenumber[n]))
        nodenumber[n] = id
        shape = na.pop('shape', 'ellipse')
        s = ' '.join(map(make_qstr, (id, n, x, y, shape)))
        # only optional attributes are left in na.
        for k, v in na.items():
            if is_string_like(v) and v.strip() != '':
                s += ' %s %s' % (make_qstr(k), make_qstr(v))
            else:
                warnings.warn('Node attribute %s is not processed. %s.' %
                              (k,
                               'Empty attribute' if is_string_like(v) else
                               'Non-string attribute'))
        yield s

    # write edges with attributes
    if G.is_directed():
        yield '*arcs'
    else:
        yield '*edges'
    for u, v, edgedata in G.edges(data=True):
        d = edgedata.copy()
        value = d.pop('weight', 1.0)  # use 1 as default edge value
        s = ' '.join(map(make_qstr, (nodenumber[u], nodenumber[v], value)))
        for k, v in d.items():
            if is_string_like(v) and v.strip() != '':
                s += ' %s %s' % (make_qstr(k), make_qstr(v))
            else:
                warnings.warn('Edge attribute %s is not processed. %s.' %
                              (k,
                               'Empty attribute' if is_string_like(v) else
                               'Non-string attribute'))
        yield s
Exemplo n.º 50
0
    else:
        node_attr={}

    indent=2*' '
    count=iter(range(len(G)))
    node_id={}

    yield "graph ["
    if G.is_directed():    
        yield indent+"directed 1"
    # write graph attributes 
    for k,v in G.graph.items():
<<<<<<< local
        if type(v)==dicttype: 
            v=listify(v,indent,2)
        elif is_string_like(v):
            v='"%s"'%v                  
        elif type(v) == bool:
            v = int(v)
        yield indent+"%s %s"%(k,v)
=======
        yield indent+string_item(k,v,indent)
>>>>>>> other
    # write nodes
    for n in G:
        yield indent+"node ["
        # get id or assign number
        nid=G.node[n].get('id',next(count))
        node_id[n]=nid
        yield 2*indent+"id %s"%nid
        label=G.node[n].pop('label',n)
Exemplo n.º 51
0
    def _open_file(func, *args, **kwargs):

        # Note that since we have used @decorator, *args, and **kwargs have
        # already been resolved to match the function signature of func. This
        # means default values have been propagated. For example,  the function
        # func(x, y, a=1, b=2, **kwargs) if called as func(0,1,b=5,c=10) would
        # have args=(0,1,1,5) and kwargs={'c':10}.

        # First we parse the arguments of the decorator. The path_arg could
        # be an positional argument or a keyword argument.  Even if it is
        try:
            # path_arg is a required positional argument
            # This works precisely because we are using @decorator
            path = args[path_arg]
        except TypeError:
            # path_arg is a keyword argument. It is "required" in the sense
            # that it must exist, according to the decorator specification,
            # It can exist in `kwargs` by a developer specified default value
            # or it could have been explicitly set by the user.
            try:
                path = kwargs[path_arg]
            except KeyError:
                # Could not find the keyword. Thus, no default was specified
                # in the function signature and the user did not provide it.
                msg = 'Missing required keyword argument: {0}'
                raise nx.NetworkXError(msg.format(path_arg))
            else:
                is_kwarg = True
        except IndexError:
            # A "required" argument was missing. This can only happen if
            # the decorator of the function was incorrectly specified.
            # So this probably is not a user error, but a developer error.
            msg = "path_arg of open_file decorator is incorrect"
            raise nx.NetworkXError(msg)
        else:
            is_kwarg = False

        # Now we have the path_arg. There are two types of input to consider:
        #   1) string representing a path that should be opened
        #   2) an already opened file object
        if is_string_like(path):
            ext = splitext(path)[1]
            fobj = _dispatch_dict[ext](path, mode=mode)
            close_fobj = True
        elif hasattr(path, 'read'):
            # path is already a file-like object
            fobj = path
            close_fobj = False
        else:
            # could be None, in which case the algorithm will deal with it
            fobj = path
            close_fobj = False

        # Insert file object into args or kwargs.
        if is_kwarg:
            new_args = args
            kwargs[path_arg] = fobj
        else:
            # args is a tuple, so we must convert to list before modifying it.
            new_args = list(args)
            new_args[path_arg] = fobj

        # Finally, we call the original function, making sure to close the fobj.
        try:
            result = func(*new_args, **kwargs)
        finally:
            if close_fobj:
                fobj.close()

        return result
Exemplo n.º 52
0
def parse_pajek(lines):
    """Parse Pajek format graph from string or iterable.

    Parameters
    ----------
    lines : string or iterable
       Data in Pajek format.

    Returns
    -------
    G : NetworkX graph

    See Also
    --------
    read_pajek()

    """
    import shlex
    # multigraph=False
    if is_string_like(lines): lines = iter(lines.split('\n'))
    lines = iter([line.rstrip('\n') for line in lines])
    G = nx.MultiDiGraph()  # are multiedges allowed in Pajek? assume yes
    while lines:
        try:
            l = next(lines)
        except:  #EOF
            break
        if l.lower().startswith("*network"):
            label, name = l.split()
            G.name = name
        if l.lower().startswith("*vertices"):
            nodelabels = {}
            l, nnodes = l.split()
            for i in range(int(nnodes)):
                splitline = shlex.split(str(next(lines)))
                id, label = splitline[0:2]
                G.add_node(label)
                nodelabels[id] = label
                G.node[label] = {'id': id}
                try:
                    x, y, shape = splitline[2:5]
                    G.node[label].update({
                        'x': float(x),
                        'y': float(y),
                        'shape': shape
                    })
                except:
                    pass
                extra_attr = zip(splitline[5::2], splitline[6::2])
                G.node[label].update(extra_attr)
        if l.lower().startswith("*edges") or l.lower().startswith("*arcs"):
            if l.lower().startswith("*edge"):
                # switch from multi digraph to multi graph
                G = nx.MultiGraph(G)
            for l in lines:
                splitline = shlex.split(str(l))
                ui, vi = splitline[0:2]
                u = nodelabels.get(ui, ui)
                v = nodelabels.get(vi, vi)
                # parse the data attached to this edge and put in a dictionary
                edge_data = {}
                try:
                    # there should always be a single value on the edge?
                    w = splitline[2:3]
                    edge_data.update({'weight': float(w[0])})
                except:
                    pass
                    # if there isn't, just assign a 1
#                    edge_data.update({'value':1})
                extra_attr = zip(splitline[3::2], splitline[4::2])
                edge_data.update(extra_attr)
                # if G.has_edge(u,v):
                #     multigraph=True
                G.add_edge(u, v, **edge_data)

    # if not multigraph: # use Graph/DiGraph if no parallel edges
    #     if G.is_directed():
    #         G=nx.DiGraph(G)
    #     else:
    #         G=nx.Graph(G)
    return G
Exemplo n.º 53
0
 def make_str(t):
     if is_string_like(t): return t
     return str(t)
Exemplo n.º 54
0
def write_gml(G, path):
    """
    Write the graph G in GML format to the file or file handle path.

    Parameters
    ----------
    path : filename or filehandle
       The filename or filehandle to write.  Filenames ending in
       .gz or .gz2 will be compressed.

    See Also
    --------
    read_gml, parse_gml

    Notes
    -----
    The output file will use the default text encoding on your system.
    It is possible to write files in other encodings by opening
    the file with the codecs module.  See doc/examples/unicode.py
    for hints.

    >>> G=nx.path_graph(4)
    >>> import codecs
    >>> fh=codecs.open('test.gml','w',encoding='iso8859-1')# use iso8859-1
    >>> nx.write_gml(G,fh)

    GML specifications indicate that the file should only use
    7bit ASCII text encoding.iso8859-1 (latin-1). 

    For nested attributes for graphs, nodes, and edges you should
    use dicts for the value of the attribute.  

    Examples
    ---------
    >>> G=nx.path_graph(4)
    >>> nx.write_gml(G,"test.gml")

    path can be a filehandle or a string with the name of the file.

    >>> fh=open("test.gml",'w')
    >>> nx.write_gml(G,fh)

    Filenames ending in .gz or .bz2 will be compressed.

    >>> nx.write_gml(G,"test.gml.gz")
    """
    fh = _get_fh(path, mode="w")

    # check for attributes or assign empty dict
    if hasattr(G, "graph_attr"):
        graph_attr = G.graph_attr
    else:
        graph_attr = {}
    if hasattr(G, "node_attr"):
        node_attr = G.node_attr
    else:
        node_attr = {}

    indent = 2 * " "
    count = iter(range(G.number_of_nodes()))
    node_id = {}
    dicttype = type({})

    # recursively make dicts into gml brackets
    def listify(d, indent, indentlevel):
        result = "[ \n"
        dicttype = type({})
        for k, v in d.iteritems():
            if type(v) == dicttype:
                v = listify(v, indent, indentlevel + 1)
            result += indentlevel * indent + "%s %s\n" % (k, v)
        return result + indentlevel * indent + "]"

    fh.write("graph [\n")
    if G.is_directed():
        fh.write(indent + "directed 1\n")
    # write graph attributes
    for k, v in G.graph.items():
        if is_string_like(v):
            v = '"' + v + '"'
        elif type(v) == dicttype:
            v = listify(v, indent, 1)
        fh.write(indent + "%s %s\n" % (k, v))
    # write nodes
    for n in G:
        fh.write(indent + "node [\n")
        # get id or assign number
        nid = G.node[n].get("id", count.next())
        node_id[n] = nid
        fh.write(2 * indent + "id %s\n" % nid)
        fh.write(2 * indent + 'label "%s"\n' % n)
        if n in G:
            for k, v in G.node[n].items():
                if is_string_like(v):
                    v = '"' + v + '"'
                if type(v) == dicttype:
                    v = listify(v, indent, 2)
                if k == "id":
                    continue
                fh.write(2 * indent + "%s %s\n" % (k, v))
        fh.write(indent + "]\n")
    # write edges
    for u, v, edgedata in G.edges_iter(data=True):
        # try to guess what is on the edge and do something reasonable
        fh.write(indent + "edge [\n")
        fh.write(2 * indent + "source %s\n" % node_id[u])
        fh.write(2 * indent + "target %s\n" % node_id[v])
        for k, v in edgedata.items():
            if k == "source":
                continue
            if k == "target":
                continue
            if is_string_like(v):
                v = '"' + v + '"'
            if type(v) == dicttype:
                v = listify(v, indent, 2)
            fh.write(2 * indent + "%s %s\n" % (k, v))
        fh.write(indent + "]\n")
    fh.write("]")
Exemplo n.º 55
0
def draw_networkx_labels(G, pos,
                         labels=None,
                         font_size=12,
                         font_color='k',
                         font_family='sans-serif',
                         font_weight='normal',
                         alpha=1.0,
                         bbox=None,
                         ax=None,
                         **kwds):
    """Draw node labels on the graph G.

    Parameters
    ----------
    G : graph
       A networkx graph

    pos : dictionary
       A dictionary with nodes as keys and positions as values.
       Positions should be sequences of length 2.

    labels : dictionary, optional (default=None)
       Node labels in a dictionary keyed by node of text labels
       Node-keys in labels should appear as keys in `pos`.
       If needed use: `{n:lab for n,lab in labels.items() if n in pos}`

    font_size : int
       Font size for text labels (default=12)

    font_color : string
       Font color string (default='k' black)

    font_family : string
       Font family (default='sans-serif')

    font_weight : string
       Font weight (default='normal')

    alpha : float
       The text transparency (default=1.0)

    ax : Matplotlib Axes object, optional
       Draw the graph in the specified Matplotlib axes.

    Returns
    -------
    dict
        `dict` of labels keyed on the nodes

    Examples
    --------
    >>> G = nx.dodecahedral_graph()
    >>> labels = nx.draw_networkx_labels(G, pos=nx.spring_layout(G))

    Also see the NetworkX drawing examples at
    https://networkx.github.io/documentation/latest/auto_examples/index.html

    See Also
    --------
    draw()
    draw_networkx()
    draw_networkx_nodes()
    draw_networkx_edges()
    draw_networkx_edge_labels()
    """
    try:
        import matplotlib.pyplot as plt
        import matplotlib.cbook as cb
    except ImportError:
        raise ImportError("Matplotlib required for draw()")
    except RuntimeError:
        print("Matplotlib unable to open display")
        raise

    if ax is None:
        ax = plt.gca()

    if labels is None:
        labels = dict((n, n) for n in G.nodes())

    # set optional alignment
    horizontalalignment = kwds.get('horizontalalignment', 'center')
    verticalalignment = kwds.get('verticalalignment', 'center')

    text_items = {}  # there is no text collection so we'll fake one
    for n, label in labels.items():
        (x, y) = pos[n]
        if not is_string_like(label):
            label = str(label)  # this makes "1" and 1 labeled the same
        t = ax.text(x, y,
                    label,
                    size=font_size,
                    color=font_color,
                    family=font_family,
                    weight=font_weight,
                    alpha=alpha,
                    horizontalalignment=horizontalalignment,
                    verticalalignment=verticalalignment,
                    transform=ax.transData,
                    bbox=bbox,
                    clip_on=True,
                    )
        text_items[n] = t
        
    plt.tick_params(
        axis='both',
        which='both',
        bottom=False,
        left=False,
        labelbottom=False,
        labelleft=False)

    return text_items
Exemplo n.º 56
0
def draw_edges(G,
               pos,
               ax,
               edgelist=None,
               width=1.0,
               width_adjuster=50,
               edge_color='k',
               style='solid',
               alpha=None,
               edge_cmap=None,
               edge_vmin=None,
               edge_vmax=None,
               traversal_weight=1.0,
               edge_delengthify=0.15,
               arrows=True,
               label=None,
               zorder=1,
               **kwds):
    """
    Code cleaned-up version of networkx.draw_networkx_edges

    New args:

    width_adjuster - the line width is generated from the weight if present, use this adjuster to thicken the lines (multiply)
    """
    if edgelist is None:
        edgelist = G.edges()

    if not edgelist or len(edgelist) == 0:  # no edges!
        return None

    # set edge positions
    edge_pos = [(pos[e[0]], pos[e[1]]) for e in edgelist]
    new_ep = []
    for e in edge_pos:
        x, y = e[0]
        dx, dy = e[1]

        # Get edge length
        elx = (dx - x) * edge_delengthify
        ely = (dy - y) * edge_delengthify

        x += elx
        y += ely
        dx -= elx
        dy -= ely

        new_ep.append(((x, y), (dx, dy)))
    edge_pos = numpy.asarray(new_ep)

    if not cb.iterable(width):
        #print [G.get_edge_data(n[0], n[1])['weight'] for n in edgelist]
        # see if I can find an edge attribute:
        if 'weight' in G.get_edge_data(edgelist[0][0],
                                       edgelist[0][1]):  # Test an edge
            lw = [
                0.5 +
                ((G.get_edge_data(n[0], n[1])['weight'] - traversal_weight) *
                 width_adjuster) for n in edgelist
            ]
        else:
            lw = (width, )
    else:
        lw = width

    if not is_string_like(edge_color) and cb.iterable(edge_color) and len(
            edge_color) == len(edge_pos):
        if numpy.alltrue([cb.is_string_like(c) for c in edge_color]):
            # (should check ALL elements)
            # list of color letters such as ['k','r','k',...]
            edge_colors = tuple(
                [colorConverter.to_rgba(c, alpha) for c in edge_color])
        elif numpy.alltrue([not cb.is_string_like(c) for c in edge_color]):
            # If color specs are given as (rgb) or (rgba) tuples, we're OK
            if numpy.alltrue(
                [cb.iterable(c) and len(c) in (3, 4) for c in edge_color]):
                edge_colors = tuple(edge_color)
            else:
                # numbers (which are going to be mapped with a colormap)
                edge_colors = None
        else:
            raise ValueError(
                'edge_color must consist of either color names or numbers')
    else:
        if is_string_like(edge_color) or len(edge_color) == 1:
            edge_colors = (colorConverter.to_rgba(edge_color, alpha), )
        else:
            raise ValueError(
                'edge_color must be a single color or list of exactly m colors where m is the number or edges'
            )

    edge_collection = LineCollection(edge_pos,
                                     colors=edge_colors,
                                     linewidths=lw,
                                     antialiaseds=(1, ),
                                     linestyle=style,
                                     transOffset=ax.transData,
                                     zorder=zorder)

    edge_collection.set_label(label)
    ax.add_collection(edge_collection)

    if cb.is_numlike(alpha):
        edge_collection.set_alpha(alpha)

    if edge_colors is None:
        if edge_cmap is not None:
            assert (isinstance(edge_cmap, Colormap))
        edge_collection.set_array(numpy.asarray(edge_color))
        edge_collection.set_cmap(edge_cmap)
        if edge_vmin is not None or edge_vmax is not None:
            edge_collection.set_clim(edge_vmin, edge_vmax)
        else:
            edge_collection.autoscale()

    # update view
    '''
    minx = numpy.amin(numpy.ravel(edge_pos[:,:,0]))
    maxx = numpy.amax(numpy.ravel(edge_pos[:,:,0]))
    miny = numpy.amin(numpy.ravel(edge_pos[:,:,1]))
    maxy = numpy.amax(numpy.ravel(edge_pos[:,:,1]))

    w = maxx-minx
    h = maxy-miny
    padx,  pady = 0.05*w, 0.05*h
    corners = (minx-padx, miny-pady), (maxx+padx, maxy+pady)
    ax.update_datalim(corners)
    ax.autoscale_view()
    '''
    return (edge_collection)
Exemplo n.º 57
0
    def _open_file(func, *args, **kwargs):

        # Note that since we have used @decorator, *args, and **kwargs have
        # already been resolved to match the function signature of func. This
        # means default values have been propagated. For example,  the function
        # func(x, y, a=1, b=2, **kwargs) if called as func(0,1,b=5,c=10) would
        # have args=(0,1,1,5) and kwargs={'c':10}.

        # First we parse the arguments of the decorator. The path_arg could
        # be an positional argument or a keyword argument.  Even if it is
        try:
            # path_arg is a required positional argument
            # This works precisely because we are using @decorator
            path = args[path_arg]
        except TypeError:
            # path_arg is a keyword argument. It is "required" in the sense
            # that it must exist, according to the decorator specification,
            # It can exist in `kwargs` by a developer specified default value
            # or it could have been explicitly set by the user.
            try:
                path = kwargs[path_arg]
            except KeyError:
                # Could not find the keyword. Thus, no default was specified
                # in the function signature and the user did not provide it.
                msg = 'Missing required keyword argument: {0}'
                raise nx.NetworkXError(msg.format(path_arg))
            else:
                is_kwarg = True
        except IndexError:
            # A "required" argument was missing. This can only happen if
            # the decorator of the function was incorrectly specified.
            # So this probably is not a user error, but a developer error.
            msg = "path_arg of open_file decorator is incorrect"
            raise nx.NetworkXError(msg)
        else:
            is_kwarg = False

        # Now we have the path_arg. There are two types of input to consider:
        #   1) string representing a path that should be opened
        #   2) an already opened file object
        if is_string_like(path):
            ext = splitext(path)[1]
            fobj = _dispatch_dict[ext](path, mode=mode)
            close_fobj = True
        elif hasattr(path, 'read'):
            # path is already a file-like object
            fobj = path
            close_fobj = False
        else:
            # could be None, in which case the algorithm will deal with it
            fobj = path
            close_fobj = False

        # Insert file object into args or kwargs.
        if is_kwarg:
            new_args = args
            kwargs[path_arg] = fobj
        else:
            # args is a tuple, so we must convert to list before modifying it.
            new_args = list(args)
            new_args[path_arg] = fobj

        # Finally, we call the original function, making sure to close the fobj.
        try:
            result = func(*new_args, **kwargs)
        finally:
            if close_fobj:
                fobj.close()

        return result
Exemplo n.º 58
0
def write_gml(G, path):
    """
    Write the graph G in GML format to the file or file handle path.

    Parameters
    ----------
    path : filename or filehandle
       The filename or filehandle to write.  Filenames ending in
       .gz or .gz2 will be compressed.

    See Also
    --------
    read_gml, parse_gml

    Notes
    -----
    The output file will use the default text encoding on your system.
    It is possible to write files in other encodings by opening
    the file with the codecs module.  See doc/examples/unicode.py
    for hints.

    >>> G=nx.path_graph(4)
    >>> import codecs
    >>> fh=codecs.open('test.gml','w',encoding='iso8859-1')# use iso8859-1
    >>> nx.write_gml(G,fh)

    GML specifications indicate that the file should only use
    7bit ASCII text encoding.iso8859-1 (latin-1). 

    For nested attributes for graphs, nodes, and edges you should
    use dicts for the value of the attribute.  

    Examples
    ---------
    >>> G=nx.path_graph(4)
    >>> nx.write_gml(G,"test.gml")

    path can be a filehandle or a string with the name of the file.

    >>> fh=open("test.gml",'w')
    >>> nx.write_gml(G,fh)

    Filenames ending in .gz or .bz2 will be compressed.

    >>> nx.write_gml(G,"test.gml.gz")
    """
    fh = _get_fh(path, mode='w')

    # check for attributes or assign empty dict
    if hasattr(G, 'graph_attr'):
        graph_attr = G.graph_attr
    else:
        graph_attr = {}
    if hasattr(G, 'node_attr'):
        node_attr = G.node_attr
    else:
        node_attr = {}

    indent = 2 * ' '
    count = iter(range(G.number_of_nodes()))
    node_id = {}
    dicttype = type({})

    # recursively make dicts into gml brackets
    def listify(d, indent, indentlevel):
        result = '[ \n'
        dicttype = type({})
        for k, v in d.iteritems():
            if type(v) == dicttype:
                v = listify(v, indent, indentlevel + 1)
            result += indentlevel * indent + "%s %s\n" % (k, v)
        return result + indentlevel * indent + "]"

    fh.write("graph [\n")
    if G.is_directed():
        fh.write(indent + "directed 1\n")
    # write graph attributes
    for k, v in G.graph.items():
        if is_string_like(v):
            v = '"' + v + '"'
        elif type(v) == dicttype:
            v = listify(v, indent, 1)
        fh.write(indent + "%s %s\n" % (k, v))
    # write nodes
    for n in G:
        fh.write(indent + "node [\n")
        # get id or assign number
        nid = G.node[n].get('id', count.next())
        node_id[n] = nid
        fh.write(2 * indent + "id %s\n" % nid)
        fh.write(2 * indent + "label \"%s\"\n" % n)
        if n in G:
            for k, v in G.node[n].items():
                if is_string_like(v): v = '"' + v + '"'
                if type(v) == dicttype: v = listify(v, indent, 2)
                if k == 'id': continue
                fh.write(2 * indent + "%s %s\n" % (k, v))
        fh.write(indent + "]\n")
    # write edges
    for u, v, edgedata in G.edges_iter(data=True):
        # try to guess what is on the edge and do something reasonable
        fh.write(indent + "edge [\n")
        fh.write(2 * indent + "source %s\n" % node_id[u])
        fh.write(2 * indent + "target %s\n" % node_id[v])
        for k, v in edgedata.items():
            if k == 'source': continue
            if k == 'target': continue
            if is_string_like(v): v = '"' + v + '"'
            if type(v) == dicttype: v = listify(v, indent, 2)
            fh.write(2 * indent + "%s %s\n" % (k, v))
        fh.write(indent + "]\n")
    fh.write("]")