cytoscape.py 5.7 KB

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