| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- """
- This module provides the following: read and write of p2g format
- used in metabolic pathway studies.
- See https://web.archive.org/web/20080626113807/http://www.cs.purdue.edu/homes/koyuturk/pathway/ for a description.
- The summary is included here:
- A file that describes a uniquely labeled graph (with extension ".gr")
- format looks like the following:
- name
- 3 4
- a
- 1 2
- b
- c
- 0 2
- "name" is simply a description of what the graph corresponds to. The
- second line displays the number of nodes and number of edges,
- respectively. This sample graph contains three nodes labeled "a", "b",
- and "c". The rest of the graph contains two lines for each node. The
- first line for a node contains the node label. After the declaration
- of the node label, the out-edges of that node in the graph are
- provided. For instance, "a" is linked to nodes 1 and 2, which are
- labeled "b" and "c", while the node labeled "b" has no outgoing
- edges. Observe that node labeled "c" has an outgoing edge to
- itself. Indeed, self-loops are allowed. Node index starts from 0.
- """
- import networkx
- from networkx.utils import open_file
- @open_file(1, mode="w")
- def write_p2g(G, path, encoding="utf-8"):
- """Write NetworkX graph in p2g format.
- Notes
- -----
- This format is meant to be used with directed graphs with
- possible self loops.
- """
- path.write((f"{G.name}\n").encode(encoding))
- path.write((f"{G.order()} {G.size()}\n").encode(encoding))
- nodes = list(G)
- # make dictionary mapping nodes to integers
- nodenumber = dict(zip(nodes, range(len(nodes))))
- for n in nodes:
- path.write((f"{n}\n").encode(encoding))
- for nbr in G.neighbors(n):
- path.write((f"{nodenumber[nbr]} ").encode(encoding))
- path.write("\n".encode(encoding))
- @open_file(0, mode="r")
- def read_p2g(path, encoding="utf-8"):
- """Read graph in p2g format from path.
- Returns
- -------
- MultiDiGraph
- Notes
- -----
- If you want a DiGraph (with no self loops allowed and no edge data)
- use D=networkx.DiGraph(read_p2g(path))
- """
- lines = (line.decode(encoding) for line in path)
- G = parse_p2g(lines)
- return G
- def parse_p2g(lines):
- """Parse p2g format graph from string or iterable.
- Returns
- -------
- MultiDiGraph
- """
- description = next(lines).strip()
- # are multiedges (parallel edges) allowed?
- G = networkx.MultiDiGraph(name=description, selfloops=True)
- nnodes, nedges = map(int, next(lines).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 = next(lines).strip()
- nodelabel[i] = n
- G.add_node(n)
- nbrs[n] = map(int, next(lines).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
|