|
3 | 3 | """This module contains the methods used to deal with BELGraphs.""" |
4 | 4 |
|
5 | 5 | from operator import methodcaller |
| 6 | +from itertools import combinations |
6 | 7 |
|
7 | 8 | from flask import abort, Response, jsonify, send_file |
8 | 9 | from flask import current_app |
9 | | -from pybel import to_bel_lines, to_graphml, to_bytes, to_csv |
10 | | -from pybel import union |
| 10 | +from pybel import to_bel_lines, to_graphml, to_bytes, to_csv, union |
| 11 | +from pybel.dsl import BaseAbundance |
11 | 12 | from pybel.constants import * |
12 | 13 | from pybel.io import from_bytes |
13 | 14 | from pybel.struct import add_annotation_value |
@@ -313,3 +314,104 @@ def get_contradiction_summary(graph): |
313 | 314 | relations = {data[RELATION] for data in graph[u][v].values()} |
314 | 315 | if relation_set_has_contradictions(relations): |
315 | 316 | yield u, v, relations |
| 317 | + |
| 318 | + |
| 319 | +def get_pathway_nodes(pathway): |
| 320 | + """Return single nodes in pathway. |
| 321 | +
|
| 322 | + :param pathme_viewer.models.Pathway pathway: pathway entry |
| 323 | + :return: BaseAbundance nodes |
| 324 | + :rtype: list[pybel.dsl.BaseAbundance] |
| 325 | + """ |
| 326 | + # Loads the BELGraph |
| 327 | + graph = from_bytes(pathway.blob) |
| 328 | + |
| 329 | + # Return BaseAbundace BEL nodes |
| 330 | + return { |
| 331 | + node.as_bel() |
| 332 | + for node in graph |
| 333 | + if isinstance(node, BaseAbundance) |
| 334 | + } |
| 335 | + |
| 336 | + |
| 337 | +def prepare_venn_diagram_data(manager, pathways): |
| 338 | + """Prepare Venn Diagram data. |
| 339 | +
|
| 340 | + :param pathme_viewer.manager.Manager manager: Manager |
| 341 | + :param dict[str,str] pathways: pathway id resource dict |
| 342 | + :rtype: dict |
| 343 | + """ |
| 344 | + pathway_data = {} |
| 345 | + for pathway_id, resource in pathways.items(): |
| 346 | + # Get pathway from DB |
| 347 | + pathway = manager.get_pathway_by_id(pathway_id, resource) |
| 348 | + |
| 349 | + # Confirm that pathway exists |
| 350 | + if not pathway: |
| 351 | + abort( |
| 352 | + 500, |
| 353 | + 'Pathway "{}" in resource "{}" was not found in the database. ' |
| 354 | + 'Please check that you have used correctly the autocompletion form.'.format( |
| 355 | + pathway_id, resource) |
| 356 | + ) |
| 357 | + # Get pathway nodes |
| 358 | + nodes = get_pathway_nodes(pathway) |
| 359 | + |
| 360 | + pathway_data[pathway.name] = nodes |
| 361 | + |
| 362 | + return pathway_data |
| 363 | + |
| 364 | + |
| 365 | +def process_overlap_for_venn_diagram(pathways_nodes, skip_gene_set_info=False): |
| 366 | + """Calculate gene sets overlaps and process the structure to render venn diagram -> https://github.com/benfred/venn.js/. |
| 367 | +
|
| 368 | + :param dict[str,set] pathways_nodes: pathway to bel nodes dictionary |
| 369 | + :param bool skip_gene_set_info: include gene set overlap data |
| 370 | + :return: list[dict] |
| 371 | + """ |
| 372 | + |
| 373 | + # Creates future js array with gene sets' lengths |
| 374 | + overlaps_venn_diagram = [] |
| 375 | + |
| 376 | + pathway_to_index = {} |
| 377 | + index = 0 |
| 378 | + |
| 379 | + for name, bel_nodes in pathways_nodes.items(): |
| 380 | + |
| 381 | + # Only minimum info is returned |
| 382 | + if skip_gene_set_info: |
| 383 | + overlaps_venn_diagram.append( |
| 384 | + {'sets': [index], 'size': len(bel_nodes), 'label': name.upper()} |
| 385 | + ) |
| 386 | + # Returns gene set overlap/intersection information as well |
| 387 | + else: |
| 388 | + overlaps_venn_diagram.append( |
| 389 | + {'sets': [index], 'size': len(bel_nodes), 'label': name, 'bel_nodes': list(bel_nodes)} |
| 390 | + ) |
| 391 | + |
| 392 | + pathway_to_index[name] = index |
| 393 | + |
| 394 | + index += 1 |
| 395 | + |
| 396 | + # Perform intersection calculations |
| 397 | + for (set_1_name, set_1_values), (set_2_name, set_2_values) in combinations(pathways_nodes.items(), r=2): |
| 398 | + # Only minimum info is returned |
| 399 | + if skip_gene_set_info: |
| 400 | + overlaps_venn_diagram.append( |
| 401 | + { |
| 402 | + 'sets': [pathway_to_index[set_1_name], pathway_to_index[set_2_name]], |
| 403 | + 'size': len(set_1_values.intersection(set_2_values)), |
| 404 | + } |
| 405 | + ) |
| 406 | + # Returns gene set overlap/intersection information as well |
| 407 | + else: |
| 408 | + overlaps_venn_diagram.append( |
| 409 | + { |
| 410 | + 'sets': [pathway_to_index[set_1_name], pathway_to_index[set_2_name]], |
| 411 | + 'size': len(set_1_values.intersection(set_2_values)), |
| 412 | + 'bel_nodes': list(set_1_values.intersection(set_2_values)), |
| 413 | + 'intersection': set_1_name + ' ∩ ' + set_2_name |
| 414 | + } |
| 415 | + ) |
| 416 | + |
| 417 | + return overlaps_venn_diagram |
0 commit comments