|
|
from itertools import chain |
|
|
|
|
|
import networkx as nx |
|
|
|
|
|
__all__ = ["tree_data", "tree_graph"] |
|
|
|
|
|
|
|
|
def tree_data(G, root, ident="id", children="children"): |
|
|
"""Returns data in tree format that is suitable for JSON serialization |
|
|
and use in JavaScript documents. |
|
|
|
|
|
Parameters |
|
|
---------- |
|
|
G : NetworkX graph |
|
|
G must be an oriented tree |
|
|
|
|
|
root : node |
|
|
The root of the tree |
|
|
|
|
|
ident : string |
|
|
Attribute name for storing NetworkX-internal graph data. `ident` must |
|
|
have a different value than `children`. The default is 'id'. |
|
|
|
|
|
children : string |
|
|
Attribute name for storing NetworkX-internal graph data. `children` |
|
|
must have a different value than `ident`. The default is 'children'. |
|
|
|
|
|
Returns |
|
|
------- |
|
|
data : dict |
|
|
A dictionary with node-link formatted data. |
|
|
|
|
|
Raises |
|
|
------ |
|
|
NetworkXError |
|
|
If `children` and `ident` attributes are identical. |
|
|
|
|
|
Examples |
|
|
-------- |
|
|
>>> from networkx.readwrite import json_graph |
|
|
>>> G = nx.DiGraph([(1, 2)]) |
|
|
>>> data = json_graph.tree_data(G, root=1) |
|
|
|
|
|
To serialize with json |
|
|
|
|
|
>>> import json |
|
|
>>> s = json.dumps(data) |
|
|
|
|
|
Notes |
|
|
----- |
|
|
Node attributes are stored in this format but keys |
|
|
for attributes must be strings if you want to serialize with JSON. |
|
|
|
|
|
Graph and edge attributes are not stored. |
|
|
|
|
|
See Also |
|
|
-------- |
|
|
tree_graph, node_link_data, adjacency_data |
|
|
""" |
|
|
if G.number_of_nodes() != G.number_of_edges() + 1: |
|
|
raise TypeError("G is not a tree.") |
|
|
if not G.is_directed(): |
|
|
raise TypeError("G is not directed.") |
|
|
if not nx.is_weakly_connected(G): |
|
|
raise TypeError("G is not weakly connected.") |
|
|
|
|
|
if ident == children: |
|
|
raise nx.NetworkXError("The values for `id` and `children` must be different.") |
|
|
|
|
|
def add_children(n, G): |
|
|
nbrs = G[n] |
|
|
if len(nbrs) == 0: |
|
|
return [] |
|
|
children_ = [] |
|
|
for child in nbrs: |
|
|
d = {**G.nodes[child], ident: child} |
|
|
c = add_children(child, G) |
|
|
if c: |
|
|
d[children] = c |
|
|
children_.append(d) |
|
|
return children_ |
|
|
|
|
|
return {**G.nodes[root], ident: root, children: add_children(root, G)} |
|
|
|
|
|
|
|
|
@nx._dispatch(graphs=None) |
|
|
def tree_graph(data, ident="id", children="children"): |
|
|
"""Returns graph from tree data format. |
|
|
|
|
|
Parameters |
|
|
---------- |
|
|
data : dict |
|
|
Tree formatted graph data |
|
|
|
|
|
ident : string |
|
|
Attribute name for storing NetworkX-internal graph data. `ident` must |
|
|
have a different value than `children`. The default is 'id'. |
|
|
|
|
|
children : string |
|
|
Attribute name for storing NetworkX-internal graph data. `children` |
|
|
must have a different value than `ident`. The default is 'children'. |
|
|
|
|
|
Returns |
|
|
------- |
|
|
G : NetworkX DiGraph |
|
|
|
|
|
Examples |
|
|
-------- |
|
|
>>> from networkx.readwrite import json_graph |
|
|
>>> G = nx.DiGraph([(1, 2)]) |
|
|
>>> data = json_graph.tree_data(G, root=1) |
|
|
>>> H = json_graph.tree_graph(data) |
|
|
|
|
|
See Also |
|
|
-------- |
|
|
tree_data, node_link_data, adjacency_data |
|
|
""" |
|
|
graph = nx.DiGraph() |
|
|
|
|
|
def add_children(parent, children_): |
|
|
for data in children_: |
|
|
child = data[ident] |
|
|
graph.add_edge(parent, child) |
|
|
grandchildren = data.get(children, []) |
|
|
if grandchildren: |
|
|
add_children(child, grandchildren) |
|
|
nodedata = { |
|
|
str(k): v for k, v in data.items() if k != ident and k != children |
|
|
} |
|
|
graph.add_node(child, **nodedata) |
|
|
|
|
|
root = data[ident] |
|
|
children_ = data.get(children, []) |
|
|
nodedata = {str(k): v for k, v in data.items() if k != ident and k != children} |
|
|
graph.add_node(root, **nodedata) |
|
|
add_children(root, children_) |
|
|
return graph |
|
|
|