Skip to content

Commit 6198c5f

Browse files
authored
utils.paths module for query_paths endpoint
Merges #33 Refs #31
1 parent ac47bc4 commit 6198c5f

File tree

4 files changed

+143
-1
lines changed

4 files changed

+143
-1
lines changed

dj_hetmech/settings.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# Read secrets from YAML file
2121
path = os.path.join(BASE_DIR, 'dj_hetmech', 'secrets.yml')
2222
with open(path) as read_file:
23-
secrets = yaml.load(read_file)
23+
secrets = yaml.full_load(read_file)
2424

2525
# Quick-start development settings - unsuitable for production
2626
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import json
2+
3+
import hetio.readwrite
4+
from django.core.management.base import BaseCommand
5+
6+
from dj_hetmech_app.utils.paths import (
7+
get_neo4j_node_info,
8+
get_neo4j_rel_info,
9+
get_paths,
10+
)
11+
12+
13+
class Command(BaseCommand):
14+
15+
help = 'Call dj_hetmech_app.utils.paths.get_paths for prototyping purposes.'
16+
17+
def handle(self, *args, **options):
18+
metagraph_url = 'https://github.com/hetio/hetionet/raw/727411d4796ba2858bc8e684ba407047c1615390/hetnet/json/hetionet-v1.0-metagraph.json'
19+
metagraph = hetio.readwrite.read_metagraph(metagraph_url)
20+
json_obj = get_paths(
21+
metagraph=metagraph,
22+
metapath='CbGiGaD',
23+
source_identifier='DB01156', # Bupropion
24+
target_identifier='DOID:0050742', # nicotine dependency
25+
limit=100,
26+
)
27+
json_str = json.dumps(json_obj, indent=2)
28+
print(json_str)

dj_hetmech_app/utils.py dj_hetmech_app/utils/__init__.py

+7
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,10 @@ def get_hetionet_metagraph():
231231
def metapath_from_abbrev(abbreviation):
232232
metagraph = get_hetionet_metagraph()
233233
return metagraph.metapath_from_abbrev(abbreviation)
234+
235+
236+
@functools.lru_cache()
237+
def get_neo4j_driver():
238+
from neo4j import GraphDatabase
239+
driver = GraphDatabase.driver('bolt://neo4j.het.io')
240+
return driver

dj_hetmech_app/utils/paths.py

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import json
2+
import functools
3+
4+
import hetio.neo4j
5+
6+
from dj_hetmech_app.utils import (
7+
metapath_from_abbrev,
8+
get_neo4j_driver,
9+
)
10+
11+
12+
def get_paths(metagraph, metapath, source_identifier, target_identifier, limit=None):
13+
"""
14+
Return JSON-serializable object with paths between two nodes for a given metapath.
15+
"""
16+
metapath = metagraph.get_metapath(metapath)
17+
query = hetio.neo4j.construct_pdp_query(metapath, property='identifier', path_style='id_lists')
18+
if limit is not None:
19+
query += f'\nLIMIT {limit}'
20+
driver = get_neo4j_driver()
21+
neo4j_params = {
22+
'source': source_identifier,
23+
'target': target_identifier,
24+
'w': 0.5,
25+
}
26+
with driver.session() as session:
27+
results = session.run(query, neo4j_params)
28+
results = [dict(record) for record in results]
29+
neo4j_node_ids = set()
30+
neo4j_rel_ids = set()
31+
paths_obj = []
32+
for record in results:
33+
row = {
34+
'metapath': metapath.abbrev,
35+
}
36+
row.update(record)
37+
neo4j_node_ids.update(row['node_ids'])
38+
neo4j_rel_ids.update(row['rel_ids'])
39+
paths_obj.append(row)
40+
41+
node_id_to_info = get_neo4j_node_info(neo4j_node_ids)
42+
rel_id_to_info = get_neo4j_rel_info(neo4j_rel_ids)
43+
json_obj = {
44+
'query': {
45+
'source': source_identifier,
46+
'target': target_identifier,
47+
'metapath': metapath.abbrev,
48+
'metapath_id': [edge.get_id() for edge in metapath],
49+
'limit': limit,
50+
},
51+
'paths': paths_obj,
52+
'nodes': node_id_to_info,
53+
'relationships': rel_id_to_info,
54+
}
55+
return json_obj
56+
57+
58+
cypher_node_query = '''\
59+
MATCH (node)
60+
WHERE id(node) IN $node_ids
61+
RETURN
62+
id(node) AS neo4j_id,
63+
node.identifier AS identifier,
64+
head(labels(node)) AS node_label,
65+
properties(node) AS data
66+
ORDER BY neo4j_id
67+
'''
68+
69+
70+
def get_neo4j_node_info(node_ids):
71+
"""
72+
Return information on nodes corresponding to the input neo4j node ids.
73+
"""
74+
node_ids = sorted(node_ids)
75+
driver = get_neo4j_driver()
76+
with driver.session() as session:
77+
results = session.run(cypher_node_query, node_ids=node_ids)
78+
results = [dict(record) for record in results]
79+
id_to_info = {x['neo4j_id']: x for x in results}
80+
return id_to_info
81+
82+
83+
cypher_rel_query = '''\
84+
MATCH ()-[rel]-()
85+
WHERE id(rel) in $rel_ids
86+
RETURN
87+
id(rel) AS neo4j_id,
88+
type(rel) AS rel_type,
89+
id(startNode(rel)) AS source_neo4j_id,
90+
id(endNode(rel)) AS target_neo4j_id,
91+
properties(rel) AS data
92+
ORDER BY neo4j_id
93+
'''
94+
95+
96+
def get_neo4j_rel_info(rel_ids):
97+
"""
98+
Return information on relationships corresponding to the
99+
input neo4j relationship ids.
100+
"""
101+
rel_ids = sorted(rel_ids)
102+
driver = get_neo4j_driver()
103+
with driver.session() as session:
104+
results = session.run(cypher_rel_query, rel_ids=rel_ids)
105+
results = [dict(record) for record in results]
106+
id_to_info = {x['neo4j_id']: x for x in results}
107+
return id_to_info

0 commit comments

Comments
 (0)