158 lines
4.6 KiB
Python
158 lines
4.6 KiB
Python
|
from itertools import chain
|
||
|
|
||
|
import networkx as nx
|
||
|
|
||
|
__all__ = ["adjacency_data", "adjacency_graph"]
|
||
|
|
||
|
_attrs = dict(id="id", key="key")
|
||
|
|
||
|
|
||
|
def adjacency_data(G, attrs=_attrs):
|
||
|
"""Returns data in adjacency format that is suitable for JSON serialization
|
||
|
and use in Javascript documents.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
G : NetworkX graph
|
||
|
|
||
|
attrs : dict
|
||
|
A dictionary that contains two keys 'id' and 'key'. The corresponding
|
||
|
values provide the attribute names for storing NetworkX-internal graph
|
||
|
data. The values should be unique. Default value:
|
||
|
:samp:`dict(id='id', key='key')`.
|
||
|
|
||
|
If some user-defined graph data use these attribute names as data keys,
|
||
|
they may be silently dropped.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
data : dict
|
||
|
A dictionary with adjacency formatted data.
|
||
|
|
||
|
Raises
|
||
|
------
|
||
|
NetworkXError
|
||
|
If values in attrs are not unique.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> from networkx.readwrite import json_graph
|
||
|
>>> G = nx.Graph([(1, 2)])
|
||
|
>>> data = json_graph.adjacency_data(G)
|
||
|
|
||
|
To serialize with json
|
||
|
|
||
|
>>> import json
|
||
|
>>> s = json.dumps(data)
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
Graph, node, and link attributes will be written when using this format
|
||
|
but attribute keys must be strings if you want to serialize the resulting
|
||
|
data with JSON.
|
||
|
|
||
|
The default value of attrs will be changed in a future release of NetworkX.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
adjacency_graph, node_link_data, tree_data
|
||
|
"""
|
||
|
multigraph = G.is_multigraph()
|
||
|
id_ = attrs["id"]
|
||
|
# Allow 'key' to be omitted from attrs if the graph is not a multigraph.
|
||
|
key = None if not multigraph else attrs["key"]
|
||
|
if id_ == key:
|
||
|
raise nx.NetworkXError("Attribute names are not unique.")
|
||
|
data = {}
|
||
|
data["directed"] = G.is_directed()
|
||
|
data["multigraph"] = multigraph
|
||
|
data["graph"] = list(G.graph.items())
|
||
|
data["nodes"] = []
|
||
|
data["adjacency"] = []
|
||
|
for n, nbrdict in G.adjacency():
|
||
|
data["nodes"].append(dict(chain(G.nodes[n].items(), [(id_, n)])))
|
||
|
adj = []
|
||
|
if multigraph:
|
||
|
for nbr, keys in nbrdict.items():
|
||
|
for k, d in keys.items():
|
||
|
adj.append(dict(chain(d.items(), [(id_, nbr), (key, k)])))
|
||
|
else:
|
||
|
for nbr, d in nbrdict.items():
|
||
|
adj.append(dict(chain(d.items(), [(id_, nbr)])))
|
||
|
data["adjacency"].append(adj)
|
||
|
return data
|
||
|
|
||
|
|
||
|
def adjacency_graph(data, directed=False, multigraph=True, attrs=_attrs):
|
||
|
"""Returns graph from adjacency data format.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
data : dict
|
||
|
Adjacency list formatted graph data
|
||
|
|
||
|
directed : bool
|
||
|
If True, and direction not specified in data, return a directed graph.
|
||
|
|
||
|
multigraph : bool
|
||
|
If True, and multigraph not specified in data, return a multigraph.
|
||
|
|
||
|
attrs : dict
|
||
|
A dictionary that contains two keys 'id' and 'key'. The corresponding
|
||
|
values provide the attribute names for storing NetworkX-internal graph
|
||
|
data. The values should be unique. Default value:
|
||
|
:samp:`dict(id='id', key='key')`.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
G : NetworkX graph
|
||
|
A NetworkX graph object
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> from networkx.readwrite import json_graph
|
||
|
>>> G = nx.Graph([(1, 2)])
|
||
|
>>> data = json_graph.adjacency_data(G)
|
||
|
>>> H = json_graph.adjacency_graph(data)
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
The default value of attrs will be changed in a future release of NetworkX.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
adjacency_graph, node_link_data, tree_data
|
||
|
"""
|
||
|
multigraph = data.get("multigraph", multigraph)
|
||
|
directed = data.get("directed", directed)
|
||
|
if multigraph:
|
||
|
graph = nx.MultiGraph()
|
||
|
else:
|
||
|
graph = nx.Graph()
|
||
|
if directed:
|
||
|
graph = graph.to_directed()
|
||
|
id_ = attrs["id"]
|
||
|
# Allow 'key' to be omitted from attrs if the graph is not a multigraph.
|
||
|
key = None if not multigraph else attrs["key"]
|
||
|
graph.graph = dict(data.get("graph", []))
|
||
|
mapping = []
|
||
|
for d in data["nodes"]:
|
||
|
node_data = d.copy()
|
||
|
node = node_data.pop(id_)
|
||
|
mapping.append(node)
|
||
|
graph.add_node(node)
|
||
|
graph.nodes[node].update(node_data)
|
||
|
for i, d in enumerate(data["adjacency"]):
|
||
|
source = mapping[i]
|
||
|
for tdata in d:
|
||
|
target_data = tdata.copy()
|
||
|
target = target_data.pop(id_)
|
||
|
if not multigraph:
|
||
|
graph.add_edge(source, target)
|
||
|
graph[source][target].update(tdata)
|
||
|
else:
|
||
|
ky = target_data.pop(key, None)
|
||
|
graph.add_edge(source, target, key=ky)
|
||
|
graph[source][target][ky].update(tdata)
|
||
|
return graph
|