"""
Write NetworkX graphs to structured and unstructured network file formats.
Many methods simply invoke equivalent methods in NetworkX.
.. autosummary::
to_gexf
to_graphml
to_sif
"""
import networkx as nx
import csv
[docs]def to_sif(graph, output_path):
"""
Generates Simple Interaction Format output file from provided graph.
The SIF specification is described
`here <http://wiki.cytoscape.org/Cytoscape_User_Manual/Network_Formats>`_.
:func:`.to_sif` will generate a .sif file describing the network, and a few
.eda and .noa files containing edge and node attributes, respectively. These
are equivalent to tab-delimited tables, and can be imported as such in
Cytoscape 3.0.
Parameters
----------
graph : networkx.Graph
The Graph to be exported to SIF.
output_path : str
Full path, including filename (without suffix).
e.g. using "./graphFolder/graphFile" will result in a SIF file at
./graphFolder/graphFile.sif, and corresponding .eda and .noa files.
"""
graph = _strip_list_attributes(graph)
if output_path[-4:] == ".sif":
output_path = output_path[:-4]
if nx.number_of_nodes(graph) == 0:
# write an empty file (for a non-existant graph)
f = open(output_path + ".sif","w")
f.write("")
f.close()
else:
# write node files
nodes = graph.nodes(data=True)
for node in nodes:
node_name = node[0]
node_attribs = node[1]
for key, value in node_attribs.iteritems():
# generate a node attribute file for each node attribute
if node == nodes[0]:
# first node, overwrite file
with open(output_path + "_" + key + ".noa",
"w") as f:
f.write(str(key) + '\n')
f.write(str(node_name).replace(" ","_") + " = " +
str(value) + "\n")
else:
# not first, append file
with open(output_path + "_" + key + ".noa",
"a") as f:
f.write(str(node_name).replace(" ","_") + " = " +
str(value) + "\n")
if nx.number_of_edges(graph) == 0:
# write an empty graph to a .sif file (just its nodes)
for node in nodes:
node_name = node[0]
if node == nodes[0]:
# first node, overwrite file
with open(output_path + ".sif","w") as f:
f.write(str(node_name).replace(" ","_") + "\n")
else:
# not first, append file
with open(output_path + ".sif","a") as f:
f.write(str(node_name).replace(" ","_") + "\n")
else:
# write the graph to a .sif file as well as other edge
# attribute files
if graph.is_multigraph():
# then the NetworkX graph supports multiple interaction
# types just like the .sif format
edges = graph.edges(data=True, keys=True)
edge_attribs = set()
for edge in edges:
for key in edge[3].iterkeys():
edge_attribs.add(key)
# create edge attribute files
for attrib in edge_attribs:
str_attrib = str(attrib)
with open(output_path + '_' + str_attrib + ".eda","w") as f:
f.write(str(attrib) + "\n")
# add data to eda files and write sif file
with open(output_path + '.sif', 'w') as f:
for edge in edges:
node1 = str(edge[0]).replace(" ", "_")
node2 = str(edge[1]).replace(" ", "_")
intr_type = str(edge[2]).replace(" ", "_")
sif_line = node1 + ' ' + intr_type + ' ' + node2 + '\n'
f.write(sif_line)
for attrib, value in edge[3].iteritems():
eda_line = (node1 + ' (' + intr_type + ') ' +
node2 + ' = ' + str(value) + '\n')
with open(output_path + '_' + str(attrib) + '.eda',
'a') as g:
g.write(eda_line)
else:
# then we support only one interaction type 'rel'
edges = graph.edges(data=True)
edge_attribs = set()
for edge in edges:
for key in edge[2].iterkeys():
edge_attribs.add(key)
# create edge attribute files
for attrib in edge_attribs:
str_attrib = str(attrib)
with open(output_path + '_' + str_attrib + ".eda","w") as f:
f.write(str(attrib) + "\n")
# add data to eda files and write sif file
with open(output_path + '.sif', 'w') as f:
for edge in edges:
node1 = str(edge[0]).replace(" ", "_")
node2 = str(edge[1]).replace(" ", "_")
intr_type = 'rel'
sif_line = node1 + ' ' + intr_type + ' ' + node2 + '\n'
f.write(sif_line)
for attrib, value in edge[2].iteritems():
eda_line = (node1 + ' (' + intr_type + ') ' +
node2 + ' = ' + str(value) + '\n')
with open(output_path + '_' + str(attrib) +
'.eda', 'a') as g:
g.write(eda_line)
[docs]def to_gexf(graph, output_path):
"""Writes graph to `GEXF <http://gexf.net>`_.
Uses the NetworkX method
`write_gexf <http://networkx.lanl.gov/reference/generated/networkx.readwrite.gexf.write_gexf.html>`_.
Parameters
----------
graph : networkx.Graph
The Graph to be exported to GEXF.
output_path : str
Full path, including filename (without suffix).
e.g. using "./graphFolder/graphFile" will result in a GEXF file at
./graphFolder/graphFile.gexf.
"""
graph = _strip_list_attributes(graph)
nx.write_gexf(graph, output_path + ".gexf")
[docs]def to_graphml(graph, output_path):
"""Writes graph to `GraphML <http://graphml.graphdrawing.org/>`_.
Uses the NetworkX method
`write_graphml <http://networkx.lanl.gov/reference/generated/networkx.readwrite.graphml.write_graphml.html>`_.
Parameters
----------
graph : networkx.Graph
The Graph to be exported to GraphML.
output_path : str
Full path, including filename (without suffix).
e.g. using "./graphFolder/graphFile" will result in a GraphML file at
./graphFolder/graphFile.graphml.
"""
graph = _strip_list_attributes(graph)
nx.write_graphml(graph, output_path + ".graphml")
#def to_csv(file, delim=","):
# '''
# Parameters
# ----------
# file : string
# Path to output file (will be created).
# delim : string
# String to use as field delimiter (default is ',').
#
# Notes
# -----
# TODO: should operate on a (provided) graph. Still uses old library approach.
# '''
#
# graph = _strip_list_attributes(graph)
#
# f = open(file, "w")
#
# # Headers
# f.write("Identifier" + delim + "Title" + delim + "Authors" +
# delim + "WoS Identifier" + delim + "Journal" + delim +
# "Volume" + delim + "Page" + delim + "DOI" + delim +
# "Num Authors\n")
# for entry in self.library:
# # Authors are separated by a colon -> : <-
# authors = ""
# for author in entry.meta['AU']:
# authors += ":" + author
# authors = authors[1:]
# datum = (entry.identifier + delim + entry.meta['TI'][0] +
# delim + authors + delim + entry.wosid + delim +
# entry.meta['SO'][0])
# if 'VL' in entry.meta:
# datum += delim + entry.meta['VL'][0]
# if 'BP' in entry.meta:
# datum += delim + entry.meta['BP'][0]
# else:
# datum += delim
# else:
# datum += delim + delim
# if 'DI' in entry.meta:
# datum += delim + entry.meta['DI'][0]
# else:
# datum += delim
# datum += delim + str(entry.meta['num_authors'])
# f.write(datum + "\n")
# f.close()
[docs]def to_table(graph, path):
graph = _strip_list_attributes(graph)
# Edge list.
with open(path + "_edges.csv", "wb") as f:
edges = graph.edges(data=True)
writer = csv.writer(f, delimiter='\t')
# Header.
writer.writerow(['source','target'] + [ k for k in edges[0][2].keys() ])
# Values.
for e in edges:
writer.writerow([ e[0], e[1]] + [ v for v in e[2].values() ] )
# Node attributes.
with open(path + "_nodes.csv", "wb") as f:
nodes = graph.nodes(data=True)
writer = csv.writer(f, delimiter='\t')
# Header.
writer.writerow(['node'] + [ k for k in nodes[0][1].keys() ])
# Values.
for n in nodes:
writer.writerow([ n[0] ] + [ v for v in n[1].values() ])
def _strip_list_attributes(G):
for n in G.nodes(data=True):
for k,v in n[1].iteritems():
if type(v) is list:
G.node[n[0]][k] = str(v)
for e in G.edges(data=True):
for k,v in e[2].iteritems():
if type(v) is list:
G.edge[e[0]][e[1]][k] = str(v)
return G