Skip to content

Commit 9552393

Browse files
committed
major reorg
1 parent eeb7446 commit 9552393

29 files changed

+415
-1730
lines changed

.ipython/extensions/neo4j_cypher_query.py

+159-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,153 @@
44
from yfiles_jupyter_graphs import GraphWidget
55
from IPython.core.magic import (register_line_magic,
66
register_cell_magic)
7-
7+
from IPython.display import IFrame
8+
import json
9+
import uuid
10+
import os
11+
from py2neo import Graph
812

913

1014
driver = GraphDatabase.driver(uri = "neo4j://localhost")
1115

16+
17+
def vis_network(nodes, edges, physics=True):
18+
html = """
19+
<html>
20+
<head>
21+
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
22+
<meta content="utf-8" http-equiv="encoding">
23+
<script type="text/javascript" src="https://thedatasociety.github.io/resources/purl/lab-neo4j/graphdrawer/vis.js"></script>
24+
<link type="text/css" href="https://thedatasociety.github.io/resources/purl/lab-neo4j/graphdrawer/vis.css" rel="stylesheet" >
25+
</head>
26+
<body>
27+
28+
<div id="{id}"></div>
29+
30+
<script type="text/javascript">
31+
var nodes = {nodes};
32+
var edges = {edges};
33+
34+
var container = document.getElementById("{id}");
35+
36+
var data = {{
37+
nodes: nodes,
38+
edges: edges
39+
}};
40+
41+
var options = {{
42+
nodes: {{
43+
shape: 'dot',
44+
size: 25,
45+
font: {{
46+
size: 14
47+
}}
48+
}},
49+
edges: {{
50+
font: {{
51+
size: 14,
52+
align: 'middle'
53+
}},
54+
color: 'gray',
55+
arrows: {{
56+
to: {{enabled: true, scaleFactor: 0.5}}
57+
}},
58+
smooth: {{enabled: false}}
59+
}},
60+
physics: {{
61+
enabled: {physics}
62+
}}
63+
}};
64+
65+
var network = new vis.Network(container, data, options);
66+
67+
</script>
68+
</body>
69+
</html>
70+
"""
71+
72+
unique_id = str(uuid.uuid4())
73+
html = html.format(id=unique_id, nodes=json.dumps(nodes), edges=json.dumps(edges), physics=json.dumps(physics))
74+
75+
try:
76+
os.makedirs('graphs')
77+
except OSError as e:
78+
pass
79+
80+
filename = "resources/graphs/graph-{}.html".format(unique_id)
81+
82+
file = open(filename, "w+")
83+
file.write(html)
84+
file.close()
85+
86+
return IFrame(filename, width="100%", height="450")
87+
88+
def draw(graph, options, physics=False, limit=300):
89+
# The options argument should be a dictionary of node labels and property keys; it determines which property
90+
# is displayed for the node label. For example, in the movie graph, options = {"Movie": "title", "Person": "name"}.
91+
# Omitting a node label from the options dict will leave the node unlabeled in the visualization.
92+
# Setting physics = True makes the nodes bounce around when you touch them!
93+
query = """
94+
MATCH (n)
95+
WITH n, rand() AS random
96+
ORDER BY random
97+
LIMIT 300
98+
OPTIONAL MATCH (n)-[r]->(m)
99+
RETURN n AS source_node,
100+
id(n) AS source_id,
101+
r,
102+
m AS target_node,
103+
id(m) AS target_id
104+
"""
105+
106+
data = graph.run(query, limit=limit)
107+
108+
nodes = []
109+
edges = []
110+
111+
def get_vis_info(node, id):
112+
node_label = list(node.labels)[0]
113+
prop_key = options.get(node_label)
114+
vis_label = node['label']
115+
116+
if node['label'] == None:
117+
118+
return {
119+
"id": id,
120+
"label": "\n{}".format(node.labels),
121+
"group": node_label, "title": "Type(s) = {} <br/> Properties = ".format(node_label)+repr(dict(node))
122+
}
123+
else:
124+
125+
return {
126+
"id": id,
127+
"label": "\n\n{} ({})".format(node.labels,node['label']),
128+
"group": node_label, "title": "Type(s) = {} <br/> Properties = ".format(node_label)+repr(dict(node))
129+
}
130+
131+
132+
for row in data:
133+
source_node = row[0]
134+
source_id = row[1]
135+
rel = row[2]
136+
target_node = row[3]
137+
target_id = row[4]
138+
139+
source_info = get_vis_info(source_node, source_id)
140+
141+
if source_info not in nodes:
142+
nodes.append(source_info)
143+
144+
if rel is not None:
145+
target_info = get_vis_info(target_node, target_id)
146+
147+
if target_info not in nodes:
148+
nodes.append(target_info)
149+
150+
edges.append({"from": source_info["id"], "to": target_info["id"], "label": "{}".format(type(rel).__name__)})
151+
152+
return vis_network(nodes, edges, physics=physics)
153+
12154
def print_counters(counters):
13155
for attr in dir(counters):
14156
# Filter out private methods and attributes
@@ -35,11 +177,26 @@ def query_neo4j_output_table(cypher_query: str):
35177
return df
36178

37179

180+
def query_neo4j_output_only_counter(cypher_query: str):
181+
query_graph_result = driver.session().run(cypher_query)
182+
print_counters(query_graph_result.consume().counters)
183+
184+
185+
186+
187+
38188

39189
def cypher(line, cell_content):
40190

41-
if line == 'graph':
191+
if line == 'show returned graph':
42192
query_neo4j_output_graph(cell_content)
193+
elif line == 'show full graph':
194+
if cell_content.replace(" ", "").lower().strip() != 'display':
195+
query_neo4j_output_only_counter(cell_content)
196+
graph = Graph("bolt://127.0.0.1:7687")
197+
iframe = draw(graph, {}, physics=True)
198+
display(iframe)
199+
43200
else:
44201
query_neo4j_output_table(cell_content)
45202

0 commit comments

Comments
 (0)