Warning

This documents an unmaintained version of NetworkX. Please upgrade to a maintained version and see the current NetworkX documentation.

Source code for networkx.readwrite.pajek

"""
*****
Pajek
*****
Read graphs in Pajek format.

This implementation handles directed and undirected graphs including
those with self loops and parallel edges.

Format
------
See http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/draweps.htm
for format information.
"""
#    Copyright (C) 2008-2014 by
#    Aric Hagberg <hagberg@lanl.gov>
#    Dan Schult <dschult@colgate.edu>
#    Pieter Swart <swart@lanl.gov>
#    All rights reserved.
#    BSD license.
import networkx as nx
from networkx.utils import is_string_like, open_file, make_str
__author__ = """Aric Hagberg <aric.hagberg@gmail.com>"""
__all__ = ['read_pajek', 'parse_pajek', 'generate_pajek', 'write_pajek']

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 = 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_qstr,(id,n,x,y,shape)))
        for k,v in na.items():
            s+=' %s %s'%(make_qstr(k),make_qstr(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_qstr,(nodenumber[u],nodenumber[v],value)))
        for k,v in d.items():
            s+=' %s %s'%(make_qstr(k),make_qstr(v))
            s+=' %s %s'%(k,v)
        yield s

@open_file(1,mode='wb')
[docs]def write_pajek(G, path, encoding='UTF-8'): """Write graph 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") References ---------- See http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/draweps.htm for format information. """ for line in generate_pajek(G): line+='\n' path.write(line.encode(encoding))
@open_file(0, mode='rb')
[docs]def read_pajek(path, encoding='UTF-8'): """Read graph in Pajek format from path. Parameters ---------- path : file or string File or filename to write. Filenames ending in .gz or .bz2 will be uncompressed. Returns ------- G : NetworkX MultiGraph or MultiDiGraph. Examples -------- >>> G=nx.path_graph(4) >>> nx.write_pajek(G, "test.net") >>> G=nx.read_pajek("test.net") To create a Graph instead of a MultiGraph use >>> G1=nx.Graph(G) References ---------- See http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/draweps.htm for format information. """ lines = (line.decode(encoding) for line in path) return parse_pajek(lines)
[docs]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)): 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
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 # fixture for nose tests def teardown_module(module): import os os.unlink('test.net')