Skip to content

Commit b566da5

Browse files
authored
Merge pull request #39 from TranslatorSRI/claude/focused-brahmagupta-e1iltd
Migrate novelty/scoring TRAPI access to 1.5+ binding format
2 parents 430fd6c + 221e918 commit b566da5

14 files changed

Lines changed: 83 additions & 139 deletions

.github/workflows/dev.yml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,6 @@ jobs:
2828
- name: Exit if there are any test failures
2929
run: '[[ $TEST_OUTPUT != *FAILED* ]]'
3030

31-
verify-lock:
32-
name: Verify lockfiles are up to date
33-
runs-on: ubuntu-latest
34-
steps:
35-
- name: Checkout the repository
36-
uses: actions/checkout@v2
37-
38-
- name: Verify lockfiles
39-
run: python manage.py verify_locked
40-
4131
check-format:
4232
name: Check that code matches Black formatter
4333
runs-on: ubuntu-latest

app/clinical_evidence/compute_clinical_evidence.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ def compute_clinical_evidence(
1818
found_edges = []
1919
# loop over all analyses in the given result and append any clinical kp edges to found_edges
2020
for analysis in result.get("analyses") or []:
21-
for edge_bindings in analysis.get("edge_bindings", {}).values():
22-
for edge_binding in edge_bindings:
21+
for edge_binding in analysis.get("edge_bindings", {}).values():
22+
for edge_id in edge_binding["ids"]:
2323
try:
24-
kg_edge = message["knowledge_graph"]["edges"][edge_binding["id"]]
24+
kg_edge = message["knowledge_graph"]["edges"][edge_id]
2525
except KeyError:
2626
# this is malformed TRAPI
2727
logger.error("malformed TRAPI")

app/clinical_evidence/merge.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
"""Script for combining multiple KGX node and edge files."""
22

3+
from datetime import datetime
34
import glob
45
import json
56
import jsonlines
6-
7+
from tqdm import tqdm
78

89
if __name__ == "__main__":
9-
node_files = glob.glob("./kgx/*_nodes.jsonl")
10-
edge_files = glob.glob("./kgx/*_edges.jsonl")
10+
time = datetime.now().strftime("%Y_%m_%d")
11+
node_files = glob.glob("./kgx/full/*_nodes.jsonl")
12+
edge_files = glob.glob("./kgx/full/*_edges.jsonl")
1113

1214
node_ids = set()
1315
nodes = {}
@@ -19,7 +21,7 @@
1921
if node["id"] not in node_ids:
2022
nodes[node["id"]] = node
2123

22-
with open("nodes_merged.json", "w") as f:
24+
with open(f"kgx/nodes_merged_{time}.json", "w") as f:
2325
json.dump(nodes, f, indent=2)
2426

2527
supported_categories = ["biolink:Drug", "biolink:ChemicalEntity", "biolink:Disease"]
@@ -29,7 +31,8 @@
2931
for edge_file in edge_files:
3032
print(f"merging {edge_file}")
3133
with jsonlines.open(edge_file) as reader:
32-
for edge in reader:
34+
print("loaded edge file")
35+
for edge in tqdm(reader):
3336
# get subject node
3437
if type(edge["subject"]) == dict:
3538
# from ehr
@@ -133,6 +136,23 @@
133136
"log_odds_analysis_result"
134137
].get("total_sample_size", 0)
135138

139+
elif (
140+
edge.get("primary_knowledge_source")
141+
== "infores:isb-EHRMLA-data"
142+
):
143+
# from ehr may treat
144+
save_edge["supporting_data_source"] = (
145+
"infores:isb-EHRMLA-data"
146+
)
147+
save_edge["predicate"] = edge["predicate"]
148+
save_edge["log_odds_ratio"] = edge.get("log_odds_ratio", 0)
149+
save_edge["log_odds_ratio_95_ci"] = edge.get(
150+
"log_odds_ratio_95_ci", [0, 0]
151+
)
152+
save_edge["total_sample_size"] = edge.get(
153+
"total_sample_size", 0
154+
)
155+
136156
if save_edge["log_odds_ratio"] > 10:
137157
save_edge["log_odds_ratio"] = 10
138158
save_edge["log_odds_ratio_95_ci"] = [10, 10]
@@ -148,6 +168,6 @@
148168
]
149169

150170
print("Writing output edges...")
151-
with open("edges_merged.json", "w") as f:
171+
with open(f"kgx/edges_merged_{time}.json", "w") as f:
152172
json.dump(edges, f, indent=2)
153173
print("Merge Complete!")

app/novelty/compute_novelty.py

Lines changed: 35 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,20 @@
1010
from .gene_nmf_adapter import get_gene_nmf_novelty_for_gene_list
1111
from ..config import settings
1212

13+
14+
def result_node_id(result, query_id_node):
15+
"""Return the KG id of the non-query (result) node for a TRAPI result.
16+
17+
Picks the first node-bound Knowledge Graph identifier that is not the
18+
queried node.
19+
"""
20+
for binding in result["node_bindings"].values():
21+
for kg_id in binding["ids"]:
22+
if kg_id != query_id_node:
23+
return kg_id
24+
return None
25+
26+
1327
"""
1428
This script computes the novelty score for a list of results obtained for a 1-H response using publications from 5 ARAs.
1529
The steps for the ideal workflow are as follows:
@@ -114,27 +128,11 @@ async def molecular_sim(known, unknown, message, query_id):
114128
known_ids = []
115129
if len(unknown) > 0:
116130
for drug in unknown:
117-
s = list(message["results"][drug]["node_bindings"].keys())
118-
if message["results"][drug]["node_bindings"][s[0]][0]["id"] == query_id:
119-
unknown_ids.append(
120-
message["results"][drug]["node_bindings"][s[1]][0]["id"]
121-
)
122-
else:
123-
unknown_ids.append(
124-
message["results"][drug]["node_bindings"][s[0]][0]["id"]
125-
)
131+
unknown_ids.append(result_node_id(message["results"][drug], query_id))
126132

127133
if len(known) > 0:
128134
for drug in known:
129-
s = list(message["results"][drug]["node_bindings"].keys())
130-
if message["results"][drug]["node_bindings"][s[0]][0]["id"] == query_id:
131-
known_ids.append(
132-
message["results"][drug]["node_bindings"][s[1]][0]["id"]
133-
)
134-
else:
135-
known_ids.append(
136-
message["results"][drug]["node_bindings"][s[0]][0]["id"]
137-
)
135+
known_ids.append(result_node_id(message["results"][drug], query_id))
138136

139137
smile_unkown = await mol_to_smile_molpro(unknown_ids)
140138
smile_known = await mol_to_smile_molpro(known_ids)
@@ -225,10 +223,10 @@ def extracting_publications(message, result):
225223
publications = []
226224
for idi, i in enumerate(result["analyses"]):
227225
edge_keys = list(i["edge_bindings"].keys())
228-
for idj, j in enumerate(i["edge_bindings"][edge_keys[0]]):
226+
for edge_id in i["edge_bindings"][edge_keys[0]]["ids"]:
229227
aux_graph, edges = [], []
230228
for idl, l in enumerate(
231-
message["knowledge_graph"]["edges"][j["id"]]["attributes"]
229+
message["knowledge_graph"]["edges"][edge_id]["attributes"]
232230
):
233231
if l["attribute_type_id"] == "biolink:publications":
234232
publications.extend(l["value"])
@@ -271,19 +269,17 @@ def extract_results(message, unknown, known):
271269
if idi in unknown:
272270
results.append([])
273271
for idj, j in enumerate(i["analyses"]):
274-
for idk, k in enumerate(
275-
j["edge_bindings"][list(j["edge_bindings"].keys())[0]]
276-
):
277-
results[ukid].append(k["id"])
272+
edge_key = list(j["edge_bindings"].keys())[0]
273+
for edge_id in j["edge_bindings"][edge_key]["ids"]:
274+
results[ukid].append(edge_id)
278275
ukid += 1
279276

280277
elif idi in known:
281278
results_known.append([])
282279
for idj, j in enumerate(i["analyses"]):
283-
for idk, k in enumerate(
284-
j["edge_bindings"][list(j["edge_bindings"].keys())[0]]
285-
):
286-
results_known[kid].append(k["id"])
280+
edge_key = list(j["edge_bindings"].keys())[0]
281+
for edge_id in j["edge_bindings"][edge_key]["ids"]:
282+
results_known[kid].append(edge_id)
287283
kid += 1
288284
return results, results_known
289285

@@ -335,11 +331,7 @@ async def compute_novelty(
335331
novelty_score_rec_tdl, novelty_score_rec_clin = [], []
336332
for idi, i in enumerate(message["results"]):
337333
curated = 0
338-
node_binding_keys = list(i["node_bindings"].keys())
339-
if i["node_bindings"][node_binding_keys[0]][0]["id"] == query_id_node:
340-
result_id_node = i["node_bindings"][node_binding_keys[1]][0]["id"]
341-
else:
342-
result_id_node = i["node_bindings"][node_binding_keys[0]][0]["id"]
334+
result_id_node = result_node_id(i, query_id_node)
343335
df_numpy.append([query_id_node, result_id_node])
344336
result_node_cat = message["knowledge_graph"]["nodes"][result_id_node][
345337
"categories"
@@ -363,39 +355,17 @@ async def compute_novelty(
363355
correct_results.append(idi)
364356
for idj, j in enumerate(i["analyses"]):
365357
edge_keys = list(j["edge_bindings"].keys())
366-
for idk, k in enumerate(j["edge_bindings"][edge_keys[0]]):
358+
for edge_id in j["edge_bindings"][edge_keys[0]]["ids"]:
367359
knowledge_graph_edge = message["knowledge_graph"]["edges"][
368-
k["id"]
360+
edge_id
369361
]
370-
epc_found = 0
371-
for idl, l in enumerate(knowledge_graph_edge["attributes"]):
372-
if l["attribute_type_id"] == "biolink:knowledge_level":
373-
epc_found = 1
374-
if l["value"] != "prediction":
375-
curated = 1
376-
df_numpy[idi].extend(
377-
[l["attribute_type_id"], l["value"]]
378-
)
379-
break
380-
if curated == 1 and epc_found == 1:
362+
knowledge_level = knowledge_graph_edge["knowledge_level"]
363+
if knowledge_level != "prediction":
364+
curated = 1
365+
df_numpy[idi].extend(
366+
["biolink:knowledge_level", knowledge_level]
367+
)
381368
break
382-
elif curated == 0 and epc_found == 0:
383-
for idl, l in enumerate(knowledge_graph_edge["sources"]):
384-
if l["resource_role"] == "primary_knowledge_source":
385-
if l["resource_id"] not in [
386-
"infores:arax",
387-
"infores:aragorn",
388-
"infores:biothings-explorer",
389-
"infores:unsecret-agent",
390-
"infores:improving-agent",
391-
"infores:cqs",
392-
]:
393-
curated = 1
394-
df_numpy[idi].extend(
395-
[l["resource_role"], l["resource_id"]]
396-
)
397-
break
398-
399369
if curated == 1:
400370
break
401371
if curated == 1:
@@ -470,14 +440,7 @@ async def compute_novelty(
470440
map_result_keys = list(map_result["gene_results"].keys())
471441
for idi, i in enumerate(message["results"]):
472442
if idi in unknown_list:
473-
node_binding_keys = list(i["node_bindings"].keys())
474-
if (
475-
i["node_bindings"][node_binding_keys[0]][0]["id"]
476-
== query_id_node
477-
):
478-
res = i["node_bindings"][node_binding_keys[1]][0]["id"]
479-
else:
480-
res = i["node_bindings"][node_binding_keys[0]][0]["id"]
443+
res = result_node_id(i, query_id_node)
481444
if res in map_result_keys:
482445
gene_distinct = (
483446
1 - map_result["gene_results"][res]["novelty_score"]
@@ -589,14 +552,7 @@ async def compute_novelty(
589552
similarity_map_keys = list(similarity_map.keys())
590553
for idi, i in enumerate(message["results"]):
591554
if idi in unknown_list:
592-
node_binding_keys = list(i["node_bindings"].keys())
593-
if (
594-
i["node_bindings"][node_binding_keys[0]][0]["id"]
595-
== query_id_node
596-
):
597-
res = i["node_bindings"][node_binding_keys[1]][0]["id"]
598-
else:
599-
res = i["node_bindings"][node_binding_keys[0]][0]["id"]
555+
res = result_node_id(i, query_id_node)
600556

601557
if res in similarity_map_keys and similarity_map[res] != []:
602558
similarity = similarity_map[res][0][1]

app/novelty/dcc/compute_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ def compute_beta_tildes(
386386

387387
# MPD - change so only return pvalues
388388
# return finalize_regression(beta_tildes=beta_tildes, ses=ses, se_inflation_factors=se_inflation_factors)
389-
(cal_beta_tildes, cal_ses, cal_z_scores, cal_p_values, cal_se_inflation_factors) = (
389+
cal_beta_tildes, cal_ses, cal_z_scores, cal_p_values, cal_se_inflation_factors = (
390390
finalize_regression(
391391
beta_tildes=beta_tildes, ses=ses, se_inflation_factors=se_inflation_factors
392392
)
@@ -845,7 +845,7 @@ def _calc_X_shift_scale(X, y_corr_cholesky=None):
845845
scale_factors = np.array([])
846846
mean_shifts = np.array([])
847847
for X_b, begin, end, batch in _get_X_blocks_internal(X, y_corr_cholesky):
848-
(cur_mean_shifts, cur_scale_factors) = _calc_shift_scale(X_b)
848+
cur_mean_shifts, cur_scale_factors = _calc_shift_scale(X_b)
849849
mean_shifts = np.append(mean_shifts, cur_mean_shifts)
850850
scale_factors = np.append(scale_factors, cur_scale_factors)
851851

app/novelty/dcc/file_utils.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535

3636
from .dcc_utils import get_logger
3737

38-
3938
# constants
4039
logger = get_logger(__name__)
4140

app/novelty/dcc/gui_utils.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
from .matrix_utils import sum_of_gene_row
3434
from .dcc_utils import get_logger
3535

36-
3736
# constants
3837
logger = get_logger(__name__)
3938

app/novelty/dcc/sql_utils.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434

3535
from .dcc_utils import get_logger
3636

37-
3837
# constants
3938
logger = get_logger(__name__)
4039
SQL_SELECT_ALL_GENES = (

app/novelty/gene_nmf_adapter.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
from .dcc import sql_utils as sql_utils
4343
from .dcc import gui_utils as gutils
4444

45-
4645
# constants
4746
P_VALUE_CUTOFF = 0.3
4847
MAX_NUMBER_GENE_SETS_FOR_COMPUTATION = 100
@@ -75,7 +74,7 @@
7574
)
7675

7776
# get the other 2 cached matrices
78-
(mean_shifts, scale_factors) = cutils._calc_X_shift_scale(X=matrix_gene_sets)
77+
mean_shifts, scale_factors = cutils._calc_X_shift_scale(X=matrix_gene_sets)
7978

8079
print("================ Bayes NMF data structures LOADED! ===========================")
8180

app/ordering_components.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from .clinical_evidence.compute_clinical_evidence import compute_clinical_evidence
99
from .novelty.compute_novelty import compute_novelty
1010

11-
1211
redis_pool = redis.ConnectionPool(
1312
host=settings.redis_host,
1413
port=settings.redis_port,
@@ -73,8 +72,7 @@ async def get_ordering_components(message, logger):
7372
"clinical_evidence": clinical_evidence_score,
7473
"novelty": 0.0,
7574
}
76-
for node_bindings in result.get("node_bindings", {}).values():
77-
for node_binding in node_bindings:
78-
result["ordering_components"]["novelty"] = novelty_scores.get(
79-
node_binding["id"], 0.0
80-
)
75+
for binding in result.get("node_bindings", {}).values():
76+
for kg_id in binding["ids"]:
77+
if kg_id in novelty_scores:
78+
result["ordering_components"]["novelty"] = novelty_scores[kg_id]

0 commit comments

Comments
 (0)