3
3
import json
4
4
import gzip
5
5
import logging
6
+
7
+ from flask import Flask , jsonify , make_response , abort , render_template , request
8
+ from flasgger import Swagger , swag_from
6
9
from db import get_mongo_connection
7
10
from concurrent .futures import ThreadPoolExecutor
8
11
import configparser
9
- import urllib .parse
10
12
from typing import List , Dict , Optional , Any
11
- from flask import Flask , jsonify , make_response , abort , render_template , request
12
13
from utils import map_gene
13
14
from gprofiler import GProfiler
14
15
16
+
15
17
# Gets production flag
16
18
IS_DEBUG : bool = os .environ .get ('DEBUG' , 'true' ) == 'true'
17
19
@@ -515,9 +517,6 @@ def bfs_on_terms(term_id, relations: Optional[List[str]] = None, general_depth=0
515
517
return list (graph .values ())
516
518
517
519
518
- # PharmGKB
519
-
520
-
521
520
def cancer_drugs_related_to_gene (gene : str ) -> List :
522
521
"""
523
522
Gets all cancer related drugs associated with a gene .
@@ -527,6 +526,7 @@ def cancer_drugs_related_to_gene(gene: str) -> List:
527
526
collection_pharm = mydb ["pharmgkb" ]
528
527
return list (collection_pharm .find ({"genes" : gene }, {"_id" : 0 }))
529
528
529
+
530
530
def get_data_from_oncokb (genes : List [str ], query : str ) -> Dict [str , Dict [str , Any ]]:
531
531
"""
532
532
Gets all data from OncoKB database associated with a gene list.
@@ -643,33 +643,41 @@ def associated_string_genes(gene_symbol: str, min_combined_score: int = 400) ->
643
643
return res
644
644
645
645
646
- # Documentation of included services
647
- services = [
648
- {"name" : "Genes symbols validator" , "url" : "[POST] /gene-symbols" },
649
- {"name" : "Genes symbols finder" , "url" : "[GET] /gene-symbols-finder" },
650
- {"name" : "Genes information" , "url" : "[POST] /information-of-genes" },
651
- {"name" : "Gene Groups" , "url" : "[GET] /genes-of-its-group/<gene_id>" },
652
- {"name" : "Genes of a metabolic pathway" , "url" : "[GET] /pathway-genes/<source>/<external_id>" },
653
- {"name" : "Metabolic pathways from different genes" , "url" : "[POST] /pathways-in-common" },
654
- {"name" : "Gene expression" , "url" : "[POST] /expression-of-genes" },
655
- {"name" : "Therapies and actionable genes in cancer" , "url" : "[POST] /information-of-oncokb" },
656
- {"name" : "Gene Ontology terms related to a list of genes" , "url" : "[POST] /genes-to-terms" },
657
- {"name" : "Gene Ontology terms related to another specific term" , "url" : "[POST] /related-terms" },
658
- {"name" : "Cancer related drugs" , "url" : "[POST] /drugs-pharm-gkb" },
659
- {"name" : "Predicted functional associations network" , "url" : "[POST] /string-relations" },
660
- {"name" : "Drugs that regulate a gene" , "url" : "[GET] /drugs-regulating-gene/<gene_id>" }
661
- ]
662
-
663
-
664
646
def create_app ():
665
647
# Creates and configures the app
666
648
flask_app = Flask (__name__ , instance_relative_config = True )
667
649
650
+ swagger_config = {
651
+ "headers" : [
652
+ ],
653
+ "openapi" : "3.0.0" ,
654
+ "specs" : [
655
+ {
656
+ "endpoint" : "swagger" ,
657
+ "route" : "/apispec.json" ,
658
+ "rule_filter" : lambda rule : True ,
659
+ "model_filter" : lambda tag : True
660
+ }
661
+ ],
662
+ "title" : "BioAPI" ,
663
+ "uiversion" : 3 ,
664
+ "version" : VERSION ,
665
+ "termsOfService" : False ,
666
+ "swagger_ui" : True ,
667
+ "static_url_path" : "/" ,
668
+ "specs_route" : "/apidocs/" ,
669
+ "description" : """
670
+ ## A powerful abstraction of genomics databases.
671
+ BioAPI is part of the Multiomix project. For more information, visit our [website](https://omicsdatascience.org/).
672
+ To contribute: [OmicsDatascience](https://github.com/omics-datascience/BioAPI)"""
673
+ }
674
+
675
+ Swagger (flask_app , config = swagger_config )
676
+
668
677
# Endpoints
669
678
@flask_app .route ("/" )
670
679
def homepage ():
671
- # return render_template('index.html', title=f"API v{VERSION}", services=services)
672
- return render_template ('homepage.html' , version = VERSION , services = services )
680
+ return render_template ('homepage.html' , version = VERSION )
673
681
674
682
@flask_app .route ("/ping" )
675
683
def ping_ok ():
@@ -678,12 +686,13 @@ def ping_ok():
678
686
return make_response (output , 200 , headers )
679
687
680
688
@flask_app .route ("/gene-symbols" , methods = ['POST' ])
689
+ @swag_from ("swagger_specs/geneSymbols.yml" )
681
690
def gene_symbols ():
682
691
"""Receives a list of gene IDs in any standard and returns the standardized corresponding gene IDs.
683
692
In case it is not found it returns an empty list for the specific not found gene."""
684
693
response = {}
685
694
if request .method == 'POST' :
686
- body = request .get_json () # type: ignore
695
+ body = request .get_json ()
687
696
if "gene_ids" not in body :
688
697
abort (400 , "gene_ids is mandatory" )
689
698
@@ -700,16 +709,17 @@ def gene_symbols():
700
709
return make_response (response , 200 , headers )
701
710
702
711
@flask_app .route ("/gene-symbols-finder/" , methods = ['GET' ])
712
+ @swag_from ("swagger_specs/geneSymbolFinder.yml" )
703
713
def gene_symbol_finder ():
704
714
"""Takes a string of any length and returns a list of genes that contain that search criteria."""
705
715
if "query" not in request .args :
706
716
abort (400 , "'query' parameter is mandatory" )
707
717
else :
708
- query = request .args .get ('query' ) # type: ignore
718
+ query = request .args .get ('query' )
709
719
710
720
limit = 50
711
721
if "limit" in request .args :
712
- limit_arg = request .args .get ('limit' ) # type: ignore
722
+ limit_arg = request .args .get ('limit' )
713
723
if limit_arg .isnumeric ():
714
724
limit = int (limit_arg )
715
725
else :
@@ -722,6 +732,7 @@ def gene_symbol_finder():
722
732
abort (400 , e )
723
733
724
734
@flask_app .route ("/information-of-genes" , methods = ['POST' ])
735
+ @swag_from ("swagger_specs/informationOfGenes.yml" )
725
736
def information_of_genes ():
726
737
"""Receives a list of gene IDs and returns information about them."""
727
738
body = request .get_json () # type: ignore
@@ -739,7 +750,8 @@ def information_of_genes():
739
750
return make_response (response , 200 , headers )
740
751
741
752
@flask_app .route ("/genes-of-its-group/<gene_id>" , methods = ['GET' ])
742
- def genes_in_the_same_group (gene_id ):
753
+ @swag_from ("swagger_specs/genesOfItsGroup.yml" )
754
+ def genes_in_the_same_group (gene_id : str ):
743
755
response = {"gene_id" : None , "groups" : [],
744
756
"locus_group" : None , "locus_type" : None }
745
757
try :
@@ -774,6 +786,7 @@ def genes_in_the_same_group(gene_id):
774
786
return make_response (response , 200 , headers )
775
787
776
788
@flask_app .route ("/pathway-genes/<pathway_source>/<pathway_id>" , methods = ['GET' ])
789
+ @swag_from ("swagger_specs/genesOfMetabolicPathway.yml" )
777
790
def pathway_genes (pathway_source , pathway_id ):
778
791
if pathway_source .lower () not in PATHWAYS_SOURCES :
779
792
abort (404 , f'{ pathway_source } is an invalid pathway source' )
@@ -782,6 +795,7 @@ def pathway_genes(pathway_source, pathway_id):
782
795
return make_response (response , 200 , headers )
783
796
784
797
@flask_app .route ("/pathways-in-common" , methods = ['POST' ])
798
+ @swag_from ("swagger_specs/pathwaysInCommon.yml" )
785
799
def pathways_in_common ():
786
800
body = request .get_json () # type: ignore
787
801
if "gene_ids" not in body :
@@ -802,6 +816,7 @@ def pathways_in_common():
802
816
return make_response (response , 200 , headers )
803
817
804
818
@flask_app .route ("/expression-of-genes" , methods = ['POST' ])
819
+ @swag_from ("swagger_specs/expressionOfGenes.yml" )
805
820
def expression_data_from_gtex ():
806
821
body = request .get_json () # type: ignore
807
822
@@ -839,6 +854,7 @@ def expression_data_from_gtex():
839
854
return jsonify (expression_data )
840
855
841
856
@flask_app .route ("/genes-to-terms" , methods = ['POST' ])
857
+ @swag_from ("swagger_specs/genesToTerms.yml" )
842
858
def genes_to_go_terms ():
843
859
"""Receives a list of genes and returns the related terms"""
844
860
valid_filter_types = ["union" , "intersection" , "enrichment" ]
@@ -926,6 +942,7 @@ def genes_to_go_terms():
926
942
return jsonify (response )
927
943
928
944
@flask_app .route ("/related-terms" , methods = ['POST' ])
945
+ @swag_from ("swagger_specs/relatedTerms.yml" )
929
946
def related_terms ():
930
947
"""Receives a term and returns the related terms"""
931
948
valid_ontology_types = ["biological_process" ,
@@ -973,6 +990,7 @@ def related_terms():
973
990
return jsonify (response )
974
991
975
992
@flask_app .route ("/information-of-oncokb" , methods = ['POST' ])
993
+ @swag_from ("swagger_specs/informationOfOncokb.yml" )
976
994
def oncokb_data ():
977
995
body = request .get_json () # type: ignore
978
996
@@ -993,6 +1011,7 @@ def oncokb_data():
993
1011
return jsonify (data )
994
1012
995
1013
@flask_app .route ("/drugs-pharm-gkb" , methods = ['POST' ])
1014
+ @swag_from ("swagger_specs/cancerDrugsRelatedToGenes.yml" )
996
1015
def cancer_drugs_related_to_genes ():
997
1016
"""Receives genes and returns the related drugs"""
998
1017
response = {}
@@ -1007,6 +1026,7 @@ def cancer_drugs_related_to_genes():
1007
1026
return jsonify (response )
1008
1027
1009
1028
@flask_app .route ("/string-relations" , methods = ['POST' ])
1029
+ @swag_from ("swagger_specs/stringRelations.yml" )
1010
1030
def string_relations_to_gene ():
1011
1031
body = request .get_json ()
1012
1032
optionals = {}
@@ -1024,6 +1044,7 @@ def string_relations_to_gene():
1024
1044
return jsonify (res )
1025
1045
1026
1046
@flask_app .route ("/drugs-regulating-gene/<gene_id>" , methods = ['GET' ])
1047
+ @swag_from ("swagger_specs/drugsRegulatingGene.yml" )
1027
1048
def drugs_regulating_gene (gene_id ):
1028
1049
return {
1029
1050
"link" : "https://go.drugbank.com/pharmaco/transcriptomics?q%5Bg%5B0%5D%5D%5Bm%5D=or&q%5Bg%5B0%5D%5D"
0 commit comments