from IPython.display import IFrame import json import uuid def vis_network(nodes, edges, physics=False): html = """ <html> <head> <script type="text/javascript" src="../lib/vis/dist/vis.js"></script> <link href="../lib/vis/dist/vis.css" rel="stylesheet" type="text/css"> </head> <body> <div id="{id}"></div> <script type="text/javascript"> var nodes = {nodes}; var edges = {edges}; var container = document.getElementById("{id}"); var data = {{ nodes: nodes, edges: edges }}; var options = {{ nodes: {{ shape: 'dot', size: 25, font: {{ size: 14 }} }}, edges: {{ font: {{ size: 14, align: 'middle' }}, color: 'gray', arrows: {{ to: {{enabled: true, scaleFactor: 0.5}} }}, smooth: {{enabled: false}} }}, physics: {{ enabled: {physics} }} }}; var network = new vis.Network(container, data, options); </script> </body> </html> """ unique_id = str(uuid.uuid4()) html = html.format(id=unique_id, nodes=json.dumps(nodes), edges=json.dumps(edges), physics=json.dumps(physics)) filename = "figure/graph-{}.html".format(unique_id) file = open(filename, "w") file.write(html) file.close() return IFrame(filename, width="100%", height="400") def draw(graph, options, physics=False, limit=100): # The options argument should be a dictionary of node labels and property keys; it determines which property # is displayed for the node label. For example, in the movie graph, options = {"Movie": "title", "Person": "name"}. # Omitting a node label from the options dict will leave the node unlabeled in the visualization. # Setting physics = True makes the nodes bounce around when you touch them! query = """ MATCH (n) WITH n, rand() AS random ORDER BY random LIMIT {limit} OPTIONAL MATCH (n)-[r]->(m) RETURN n AS source_node, id(n) AS source_id, r, m AS target_node, id(m) AS target_id """ data = graph.run(query, limit=limit) nodes = [] edges = [] def get_vis_info(node, id): node_label = list(node.labels())[0] prop_key = options.get(node_label) vis_label = node.properties.get(prop_key, "") return {"id": id, "label": vis_label, "group": node_label, "title": repr(node.properties)} for row in data: source_node = row[0] source_id = row[1] rel = row[2] target_node = row[3] target_id = row[4] source_info = get_vis_info(source_node, source_id) if source_info not in nodes: nodes.append(source_info) if rel is not None: target_info = get_vis_info(target_node, target_id) if target_info not in nodes: nodes.append(target_info) edges.append({"from": source_info["id"], "to": target_info["id"], "label": rel.type()}) return vis_network(nodes, edges, physics=physics)