@@ -12,15 +12,16 @@ def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs)
12
12
import copy
13
13
14
14
sys .path .append (os .path .dirname (os .path .abspath (__file__ )))
15
- from Path_Finder .converter .paths_to_response_converter_factory import paths_to_response_converter_factory
15
+ from Path_Finder .converter .EdgeExtractorFromPloverDB import EdgeExtractorFromPloverDB
16
+ from Path_Finder .converter .SuperNodeConverter import SuperNodeConverter
16
17
from Path_Finder .converter .Names import Names
17
18
from Path_Finder .BidirectionalPathFinder import BidirectionalPathFinder
18
- from Path_Finder .repo .NGDSortedNeighborsRepo import NGDSortedNeighborsRepo
19
- from Path_Finder .repo .PloverDBRepo import PloverDBRepo
20
19
21
20
sys .path .append (os .path .dirname (os .path .abspath (__file__ )) + "/../../UI/OpenAPI/python-flask-server/" )
22
21
from openapi_server .models .q_edge import QEdge
22
+ from openapi_server .models .q_node import QNode
23
23
from openapi_server .models .knowledge_graph import KnowledgeGraph
24
+
24
25
sys .path .append (os .path .dirname (os .path .abspath (__file__ )) + "/../NodeSynonymizer/" )
25
26
from node_synonymizer import NodeSynonymizer
26
27
@@ -51,12 +52,11 @@ def __init__(self):
51
52
"type" : "list" ,
52
53
"description" : "List with just two qnode keys to connect. example: [n1, n2]"
53
54
}
54
- self .result_as_info = {
55
+ self .node_category_constraint_info = {
55
56
"is_required" : False ,
56
- "examples" : ['betweenness_centrality ' , 'all_in_one ' , 'one_by_one ' ],
57
+ "examples" : ['biolink:Disease ' , 'biolink:Gene ' , 'biolink:ChemicalEntity ' ],
57
58
"type" : "string" ,
58
- "description" : "It determines how to receive the results. For instance, one_by_one means that it will "
59
- "return each path in one subgraph. The default value is betweenness_centrality"
59
+ "description" : "This constraint will display paths that only pass through the user-specified category."
60
60
}
61
61
62
62
# command descriptions
@@ -78,7 +78,7 @@ def __init__(self):
78
78
"parameters" : {
79
79
"max_path_length" : self .max_path_length_info ,
80
80
"qnode_keys" : self .qnode_keys_info ,
81
- "result_as " : self .result_as_info
81
+ "node_category_constraint " : self .node_category_constraint_info
82
82
}
83
83
}
84
84
}
@@ -148,6 +148,8 @@ def check_params(self, allowable_parameters):
148
148
continue
149
149
elif any ([type (x ) == int for x in allowable_parameters [key ]]):
150
150
continue
151
+ elif any ([type (x ) == str for x in allowable_parameters [key ]]):
152
+ continue
151
153
else : # otherwise, it's really not an allowable parameter
152
154
self .response .warning (
153
155
f"Supplied value { item } is not permitted. In action { allowable_parameters ['action' ]} , allowable values to { key } are: { list (allowable_parameters [key ])} " )
@@ -217,15 +219,15 @@ def __connect_nodes(self, describe=False):
217
219
if message and parameters and hasattr (message , 'query_graph' ) and hasattr (message .query_graph , 'nodes' ):
218
220
allowable_parameters = {'action' : {'connect_nodes' },
219
221
'max_path_length' : {int ()},
220
- 'result_as ' : {'betweenness_centrality' , 'all_in_one' , 'one_by_one' },
222
+ 'node_category_constraint ' : {str () },
221
223
'qnode_keys' : set (self .message .query_graph .nodes .keys ())
222
224
}
223
225
else :
224
226
allowable_parameters = {'action' : {'connect_nodes' },
225
227
'max_path_length' : {
226
- 'a maximum path length to use to connect qnodes. Defaults to 2.' },
227
- 'result_as ' : {
228
- 'How to show results? ' },
228
+ 'A maximum path length to use to connect qnodes. Defaults to 2.' },
229
+ 'node_category_constraint ' : {
230
+ 'All paths must include at least one node from this category constraint. ' },
229
231
'qnode_keys' : {'A list with just two query keys to connect' }
230
232
}
231
233
@@ -253,8 +255,8 @@ def __connect_nodes(self, describe=False):
253
255
254
256
if 'max_path_length' not in self .parameters :
255
257
self .parameters ['max_path_length' ] = 2
256
- if 'result_as ' not in self .parameters :
257
- self .parameters ['result_as ' ] = 'betweenness_centrality '
258
+ if 'node_category_constraint ' not in self .parameters :
259
+ self .parameters ['node_category_constraint ' ] = ''
258
260
# convert path length to int if it isn't already
259
261
if type (self .parameters ['max_path_length' ]) != int :
260
262
self .parameters ['max_path_length' ] = int (self .parameters ['max_path_length' ])
@@ -281,43 +283,89 @@ def __connect_nodes(self, describe=False):
281
283
self .response .error (f"Need to have two nodes to find paths between them. Number of nodes: { len (nodes )} " )
282
284
283
285
path_finder = BidirectionalPathFinder (
284
- NGDSortedNeighborsRepo (
285
- PloverDBRepo (plover_url = RTXConfiguration ().plover_url )
286
- )
286
+ "NGDSortedNeighborsRepo" ,
287
+ self .response
287
288
)
288
289
qnode_1_id = self .parameters ['qnode_keys' ][0 ]
289
290
qnode_2_id = self .parameters ['qnode_keys' ][1 ]
290
291
synonymizer = NodeSynonymizer ()
291
- node_1_id = synonymizer .get_canonical_curies (curies = nodes [qnode_1_id ].ids [0 ])[nodes [qnode_1_id ].ids [0 ]]['preferred_curie' ]
292
- node_2_id = synonymizer .get_canonical_curies (curies = nodes [qnode_2_id ].ids [0 ])[nodes [qnode_2_id ].ids [0 ]]['preferred_curie' ]
292
+ try :
293
+ node_1_id = synonymizer .get_canonical_curies (curies = nodes [qnode_1_id ].ids [0 ])[nodes [qnode_1_id ].ids [0 ]][
294
+ 'preferred_curie' ]
295
+ except Exception as e :
296
+ self .response .error (f"PathFinder could not get canonical CURIE for the node: { qnode_1_id } ."
297
+ f" You need to provide id (CURIE) or name for this node"
298
+ f" Error message is: { e } " )
299
+ return self .response
300
+
301
+ try :
302
+ node_2_id = synonymizer .get_canonical_curies (curies = nodes [qnode_2_id ].ids [0 ])[nodes [qnode_2_id ].ids [0 ]][
303
+ 'preferred_curie' ]
304
+ except Exception as e :
305
+ self .response .error (f"PathFinder could not get canonical CURIE for the node: { qnode_2_id } "
306
+ f" You need to provide id (CURIE) or name for this node."
307
+ f" Error message is: { e } " )
308
+ return self .response
293
309
294
310
paths = path_finder .find_all_paths (node_1_id , node_2_id , hops_numbers = self .parameters ['max_path_length' ])
295
311
312
+ self .response .debug (f"PathFinder found { len (paths )} paths" )
313
+
296
314
if len (paths ) == 0 :
297
315
self .response .warning (f"Could not connect the nodes { qnode_1_id } and { qnode_2_id } "
298
316
f"with a max path length of { self .parameters ['max_path_length' ]} ." )
299
317
return self .response
300
318
301
- q_edge_name = 'q_edge_path_finder'
302
- self .response .envelope .message .query_graph .edges [q_edge_name ] = QEdge (
319
+ qnode_mid_id = "qnode_mid_id"
320
+ self .response .envelope .message .query_graph .nodes [qnode_mid_id ] = QNode (
321
+ ids = [],
322
+ categories = None ,
323
+ is_set = False ,
324
+ set_interpretation = 'BATCH' ,
325
+ set_id = None ,
326
+ constraints = [],
327
+ option_group_id = None
328
+ )
329
+
330
+ q_edge_src_dest = 'q_edge_src_dest'
331
+ self .response .envelope .message .query_graph .edges [q_edge_src_dest ] = QEdge (
303
332
object = qnode_1_id ,
304
333
subject = qnode_2_id
305
334
)
335
+ q_edge_src_mid = 'q_edge_src_mid'
336
+ self .response .envelope .message .query_graph .edges [q_edge_src_mid ] = QEdge (
337
+ object = qnode_1_id ,
338
+ subject = qnode_mid_id
339
+ )
340
+ q_edge_mid_dest = 'q_edge_mid_dest'
341
+ self .response .envelope .message .query_graph .edges [q_edge_mid_dest ] = QEdge (
342
+ object = qnode_mid_id ,
343
+ subject = qnode_2_id
344
+ )
306
345
307
346
names = Names (
308
- q_edge_name = q_edge_name ,
347
+ q_src_dest_edge_name = q_edge_src_dest ,
348
+ q_src_mid_edge_name = q_edge_src_mid ,
349
+ q_mid_dest_edge_name = q_edge_mid_dest ,
309
350
result_name = "result" ,
310
351
auxiliary_graph_name = "aux" ,
311
- kg_edge_name = "kg_edge"
352
+ kg_src_dest_edge_name = "kg_src_dest_edge" ,
353
+ kg_src_mid_edge_name = "kg_src_mid_edge" ,
354
+ kg_mid_dest_edge_name = "kg_mid_dest_edge" ,
355
+ )
356
+ edge_extractor = EdgeExtractorFromPloverDB (
357
+ RTXConfiguration ().plover_url
312
358
)
313
- paths_to_response_converter_factory (
314
- self .parameters ['result_as' ],
359
+ SuperNodeConverter (
315
360
paths ,
316
361
node_1_id ,
317
362
node_2_id ,
318
363
qnode_1_id ,
319
364
qnode_2_id ,
320
- names
365
+ qnode_mid_id ,
366
+ names ,
367
+ edge_extractor ,
368
+ self .parameters ['node_category_constraint' ]
321
369
).convert (self .response )
322
370
323
371
if mode != "RTXKG2" and not hasattr (self .response , "original_query_graph" ):
0 commit comments