import networkx as nx __all__ = ["cytoscape_data", "cytoscape_graph"] def cytoscape_data(G, attrs=None, name="name", ident="id"): """Returns data in Cytoscape JSON format (cyjs). Parameters ---------- G : NetworkX Graph The graph to convert to cytoscape format attrs : dict or None (default=None) A dictionary containing the keys 'name' and 'ident' which are mapped to the 'name' and 'id' node elements in cyjs format. All other keys are ignored. Default is `None` which results in the default mapping ``dict(name="name", ident="id")``. .. deprecated:: 2.6 The `attrs` keyword argument will be replaced with `name` and `ident` in networkx 3.0 name : string A string which is mapped to the 'name' node element in cyjs format. Must not have the same value as `ident`. ident : string A string which is mapped to the 'id' node element in cyjs format. Must not have the same value as `name`. Returns ------- data: dict A dictionary with cyjs formatted data. Raises ------ NetworkXError If the values for `name` and `ident` are identical. See Also -------- cytoscape_graph: convert a dictionary in cyjs format to a graph References ---------- .. [1] Cytoscape user's manual: http://manual.cytoscape.org/en/stable/index.html Examples -------- >>> G = nx.path_graph(2) >>> nx.cytoscape_data(G) # doctest: +SKIP {'data': [], 'directed': False, 'multigraph': False, 'elements': {'nodes': [{'data': {'id': '0', 'value': 0, 'name': '0'}}, {'data': {'id': '1', 'value': 1, 'name': '1'}}], 'edges': [{'data': {'source': 0, 'target': 1}}]}} """ # ------ TODO: Remove between the lines in 3.0 ----- # if attrs is not None: import warnings msg = ( "\nThe `attrs` keyword argument of cytoscape_data is deprecated\n" "and will be removed in networkx 3.0.\n" "It is replaced with explicit `name` and `ident` keyword\n" "arguments.\n" "To make this warning go away and ensure usage is forward\n" "compatible, replace `attrs` with `name` and `ident`,\n" "for example:\n\n" " >>> cytoscape_data(G, attrs={'name': 'foo', 'ident': 'bar'})\n\n" "should instead be written as\n\n" " >>> cytoscape_data(G, name='foo', ident='bar')\n\n" "in networkx 3.0.\n" "The default values of 'name' and 'id' will not change." ) warnings.warn(msg, DeprecationWarning, stacklevel=2) name = attrs["name"] ident = attrs["ident"] # -------------------------------------------------- # if name == ident: raise nx.NetworkXError("name and ident must be different.") jsondata = {"data": list(G.graph.items())} jsondata["directed"] = G.is_directed() jsondata["multigraph"] = G.is_multigraph() jsondata["elements"] = {"nodes": [], "edges": []} nodes = jsondata["elements"]["nodes"] edges = jsondata["elements"]["edges"] for i, j in G.nodes.items(): n = {"data": j.copy()} n["data"]["id"] = j.get(ident) or str(i) n["data"]["value"] = i n["data"]["name"] = j.get(name) or str(i) nodes.append(n) if G.is_multigraph(): for e in G.edges(keys=True): n = {"data": G.adj[e[0]][e[1]][e[2]].copy()} n["data"]["source"] = e[0] n["data"]["target"] = e[1] n["data"]["key"] = e[2] edges.append(n) else: for e in G.edges(): n = {"data": G.adj[e[0]][e[1]].copy()} n["data"]["source"] = e[0] n["data"]["target"] = e[1] edges.append(n) return jsondata def cytoscape_graph(data, attrs=None, name="name", ident="id"): """ Create a NetworkX graph from a dictionary in cytoscape JSON format. Parameters ---------- data : dict A dictionary of data conforming to cytoscape JSON format. attrs : dict or None (default=None) A dictionary containing the keys 'name' and 'ident' which are mapped to the 'name' and 'id' node elements in cyjs format. All other keys are ignored. Default is `None` which results in the default mapping ``dict(name="name", ident="id")``. .. deprecated:: 2.6 The `attrs` keyword argument will be replaced with `name` and `ident` in networkx 3.0 name : string A string which is mapped to the 'name' node element in cyjs format. Must not have the same value as `ident`. ident : string A string which is mapped to the 'id' node element in cyjs format. Must not have the same value as `name`. Returns ------- graph : a NetworkX graph instance The `graph` can be an instance of `Graph`, `DiGraph`, `MultiGraph`, or `MultiDiGraph` depending on the input data. Raises ------ NetworkXError If the `name` and `ident` attributes are identical. See Also -------- cytoscape_data: convert a NetworkX graph to a dict in cyjs format References ---------- .. [1] Cytoscape user's manual: http://manual.cytoscape.org/en/stable/index.html Examples -------- >>> data_dict = { ... 'data': [], ... 'directed': False, ... 'multigraph': False, ... 'elements': {'nodes': [{'data': {'id': '0', 'value': 0, 'name': '0'}}, ... {'data': {'id': '1', 'value': 1, 'name': '1'}}], ... 'edges': [{'data': {'source': 0, 'target': 1}}]} ... } >>> G = nx.cytoscape_graph(data_dict) >>> G.name '' >>> G.nodes() NodeView((0, 1)) >>> G.nodes(data=True)[0] {'id': '0', 'value': 0, 'name': '0'} >>> G.edges(data=True) EdgeDataView([(0, 1, {'source': 0, 'target': 1})]) """ # ------ TODO: Remove between the lines in 3.0 ----- # if attrs is not None: import warnings msg = ( "\nThe `attrs` keyword argument of cytoscape_data is deprecated\n" "and will be removed in networkx 3.0.\n" "It is replaced with explicit `name` and `ident` keyword\n" "arguments.\n" "To make this warning go away and ensure usage is forward\n" "compatible, replace `attrs` with `name` and `ident`,\n" "for example:\n\n" " >>> cytoscape_data(G, attrs={'name': 'foo', 'ident': 'bar'})\n\n" "should instead be written as\n\n" " >>> cytoscape_data(G, name='foo', ident='bar')\n\n" "The default values of 'name' and 'id' will not change." ) warnings.warn(msg, DeprecationWarning, stacklevel=2) name = attrs["name"] ident = attrs["ident"] # -------------------------------------------------- # if name == ident: raise nx.NetworkXError("name and ident must be different.") multigraph = data.get("multigraph") directed = data.get("directed") if multigraph: graph = nx.MultiGraph() else: graph = nx.Graph() if directed: graph = graph.to_directed() graph.graph = dict(data.get("data")) for d in data["elements"]["nodes"]: node_data = d["data"].copy() node = d["data"]["value"] if d["data"].get(name): node_data[name] = d["data"].get(name) if d["data"].get(ident): node_data[ident] = d["data"].get(ident) graph.add_node(node) graph.nodes[node].update(node_data) for d in data["elements"]["edges"]: edge_data = d["data"].copy() sour = d["data"]["source"] targ = d["data"]["target"] if multigraph: key = d["data"].get("key", 0) graph.add_edge(sour, targ, key=key) graph.edges[sour, targ, key].update(edge_data) else: graph.add_edge(sour, targ) graph.edges[sour, targ].update(edge_data) return graph