1import networkx as nx
2
3__all__ = ["cytoscape_data", "cytoscape_graph"]
4
5
6def cytoscape_data(G, name="name", ident="id"):
7 """Returns data in Cytoscape JSON format (cyjs).
8
9 Parameters
10 ----------
11 G : NetworkX Graph
12 The graph to convert to cytoscape format
13 name : string
14 A string which is mapped to the 'name' node element in cyjs format.
15 Must not have the same value as `ident`.
16 ident : string
17 A string which is mapped to the 'id' node element in cyjs format.
18 Must not have the same value as `name`.
19
20 Returns
21 -------
22 data: dict
23 A dictionary with cyjs formatted data.
24
25 Raises
26 ------
27 NetworkXError
28 If the values for `name` and `ident` are identical.
29
30 See Also
31 --------
32 cytoscape_graph: convert a dictionary in cyjs format to a graph
33
34 References
35 ----------
36 .. [1] Cytoscape user's manual:
37 http://manual.cytoscape.org/en/stable/index.html
38
39 Examples
40 --------
41 >>> from pprint import pprint
42 >>> G = nx.path_graph(2)
43 >>> cyto_data = nx.cytoscape_data(G)
44 >>> pprint(cyto_data, sort_dicts=False)
45 {'data': [],
46 'directed': False,
47 'multigraph': False,
48 'elements': {'nodes': [{'data': {'id': '0', 'value': 0, 'name': '0'}},
49 {'data': {'id': '1', 'value': 1, 'name': '1'}}],
50 'edges': [{'data': {'source': 0, 'target': 1}}]}}
51
52 The :mod:`json` package can be used to serialize the resulting data
53
54 >>> import io, json
55 >>> with io.StringIO() as fh: # replace io with `open(...)` to write to disk
56 ... json.dump(cyto_data, fh)
57 ... fh.seek(0) # doctest: +SKIP
58 ... print(fh.getvalue()[:64]) # View the first 64 characters
59 {"data": [], "directed": false, "multigraph": false, "elements":
60
61 """
62 if name == ident:
63 raise nx.NetworkXError("name and ident must be different.")
64
65 jsondata = {"data": list(G.graph.items())}
66 jsondata["directed"] = G.is_directed()
67 jsondata["multigraph"] = G.is_multigraph()
68 jsondata["elements"] = {"nodes": [], "edges": []}
69 nodes = jsondata["elements"]["nodes"]
70 edges = jsondata["elements"]["edges"]
71
72 for i, j in G.nodes.items():
73 n = {"data": j.copy()}
74 n["data"]["id"] = j.get(ident) or str(i)
75 n["data"]["value"] = i
76 n["data"]["name"] = j.get(name) or str(i)
77 nodes.append(n)
78
79 if G.is_multigraph():
80 for e in G.edges(keys=True):
81 n = {"data": G.adj[e[0]][e[1]][e[2]].copy()}
82 n["data"]["source"] = e[0]
83 n["data"]["target"] = e[1]
84 n["data"]["key"] = e[2]
85 edges.append(n)
86 else:
87 for e in G.edges():
88 n = {"data": G.adj[e[0]][e[1]].copy()}
89 n["data"]["source"] = e[0]
90 n["data"]["target"] = e[1]
91 edges.append(n)
92 return jsondata
93
94
95@nx._dispatchable(graphs=None, returns_graph=True)
96def cytoscape_graph(data, name="name", ident="id"):
97 """
98 Create a NetworkX graph from a dictionary in cytoscape JSON format.
99
100 Parameters
101 ----------
102 data : dict
103 A dictionary of data conforming to cytoscape JSON format.
104 name : string
105 A string which is mapped to the 'name' node element in cyjs format.
106 Must not have the same value as `ident`.
107 ident : string
108 A string which is mapped to the 'id' node element in cyjs format.
109 Must not have the same value as `name`.
110
111 Returns
112 -------
113 graph : a NetworkX graph instance
114 The `graph` can be an instance of `Graph`, `DiGraph`, `MultiGraph`, or
115 `MultiDiGraph` depending on the input data.
116
117 Raises
118 ------
119 NetworkXError
120 If the `name` and `ident` attributes are identical.
121
122 See Also
123 --------
124 cytoscape_data: convert a NetworkX graph to a dict in cyjs format
125
126 References
127 ----------
128 .. [1] Cytoscape user's manual:
129 http://manual.cytoscape.org/en/stable/index.html
130
131 Examples
132 --------
133 >>> data_dict = {
134 ... "data": [],
135 ... "directed": False,
136 ... "multigraph": False,
137 ... "elements": {
138 ... "nodes": [
139 ... {"data": {"id": "0", "value": 0, "name": "0"}},
140 ... {"data": {"id": "1", "value": 1, "name": "1"}},
141 ... ],
142 ... "edges": [{"data": {"source": 0, "target": 1}}],
143 ... },
144 ... }
145 >>> G = nx.cytoscape_graph(data_dict)
146 >>> G.name
147 ''
148 >>> G.nodes()
149 NodeView((0, 1))
150 >>> G.nodes(data=True)[0]
151 {'id': '0', 'value': 0, 'name': '0'}
152 >>> G.edges(data=True)
153 EdgeDataView([(0, 1, {'source': 0, 'target': 1})])
154 """
155 if name == ident:
156 raise nx.NetworkXError("name and ident must be different.")
157
158 multigraph = data.get("multigraph")
159 directed = data.get("directed")
160 if multigraph:
161 graph = nx.MultiGraph()
162 else:
163 graph = nx.Graph()
164 if directed:
165 graph = graph.to_directed()
166 graph.graph = dict(data.get("data"))
167 for d in data["elements"]["nodes"]:
168 node_data = d["data"].copy()
169 node = d["data"]["value"]
170
171 if d["data"].get(name):
172 node_data[name] = d["data"].get(name)
173 if d["data"].get(ident):
174 node_data[ident] = d["data"].get(ident)
175
176 graph.add_node(node)
177 graph.nodes[node].update(node_data)
178
179 for d in data["elements"]["edges"]:
180 edge_data = d["data"].copy()
181 sour = d["data"]["source"]
182 targ = d["data"]["target"]
183 if multigraph:
184 key = d["data"].get("key", 0)
185 graph.add_edge(sour, targ, key=key)
186 graph.edges[sour, targ, key].update(edge_data)
187 else:
188 graph.add_edge(sour, targ)
189 graph.edges[sour, targ].update(edge_data)
190 return graph