diff options
author | zsloan | 2019-06-04 11:24:46 -0500 |
---|---|---|
committer | zsloan | 2019-06-04 11:24:46 -0500 |
commit | 95a5e0e07fa9b4cd574beac5e4d9138a0b16bb60 (patch) | |
tree | e88780b0d1c33ef7511712d58eb5d682931be1c4 | |
parent | 25eae5f41f5c821459f99bd0f3d777035a284564 (diff) | |
parent | 34d962fe1e0dd5e30f067e7a30fcbd8931f2aacb (diff) | |
download | genenetwork2-95a5e0e07fa9b4cd574beac5e4d9138a0b16bb60.tar.gz |
Merge branch 'api' of github.com:zsloan/genenetwork2 into testing
-rw-r--r-- | doc/API_readme.md | 22 | ||||
-rw-r--r-- | wqflask/base/webqtlConfig.py | 2 | ||||
-rw-r--r-- | wqflask/wqflask/api/router.py | 132 | ||||
-rw-r--r-- | wqflask/wqflask/show_trait/show_trait.py | 11 | ||||
-rw-r--r-- | wqflask/wqflask/templates/collections/view.html | 4 | ||||
-rw-r--r-- | wqflask/wqflask/templates/search_result_page.html | 6 | ||||
-rw-r--r-- | wqflask/wqflask/templates/show_trait_details.html | 6 |
7 files changed, 157 insertions, 26 deletions
diff --git a/doc/API_readme.md b/doc/API_readme.md index 96e8b246..6c88d413 100644 --- a/doc/API_readme.md +++ b/doc/API_readme.md @@ -51,13 +51,6 @@ curl http://gn2-zach.genenetwork.org/api/v_pre1/datasets/mouse/bxd ``` (I added the option to specify species just in case we end up with the same group name across multiple species at some point, though it's currently unnecessary) -## Fetch Sample Data for Dataset ## -``` -curl http://gn2-zach.genenetwork.org/api/v_pre1/sample_data/HSNIH-PalmerPublish.csv -``` - -Returns a CSV file with sample/strain names as the columns and trait IDs as rows - ## Fetch Individual Dataset Info ## ### For mRNA Assay/"ProbeSet" ### @@ -78,12 +71,27 @@ curl http://gn2-zach.genenetwork.org/api/v_pre1/dataset/bxd/10001 { "dataset_type": "phenotype", "description": "Central nervous system, morphology: Cerebellum weight, whole, bilateral in adults of both sexes [mg]", "id": 10001, "name": "CBLWT2", "pubmed_id": 11438585, "title": "Genetic control of the mouse cerebellum: identification of quantitative trait loci modulating size and architecture", "year": "2001" } ``` +## Fetch Sample Data for Dataset ## +``` +curl http://gn2-zach.genenetwork.org/api/v_pre1/sample_data/HSNIH-PalmerPublish.csv +``` + +Returns a CSV file with sample/strain names as the columns and trait IDs as rows + ## Fetch Sample Data for Single Trait ## ``` curl http://gn2-zach.genenetwork.org/api/v_pre1/sample_data/HC_M2_0606_P/1436869_at [ { "data_id": 23415463, "sample_name": "129S1/SvImJ", "sample_name_2": "129S1/SvImJ", "se": 0.123, "value": 8.201 }, { "data_id": 23415463, "sample_name": "A/J", "sample_name_2": "A/J", "se": 0.046, "value": 8.413 }, { "data_id": 23415463, "sample_name": "AKR/J", "sample_name_2": "AKR/J", "se": 0.134, "value": 8.856 }, ... ] ``` +## Fetch Trait List for Dataset ## +``` +curl http://gn2-zach.genenetwork.org/api/v_pre1/traits/HXBBXHPublish.json +[ { "Additive": 0.0499967532467532, "Id": 10001, "LRS": 16.2831307029479, "Locus": "rs106114574", "PhenotypeId": 1449, "PublicationId": 319, "Sequence": 1 }, ... ] +``` + +Both JSON and CSV formats can be specified, with JSON as default. There is also an optional "ids_only" and "names_only" parameter that will only return a list of trait IDs or names, respectively. + ## Fetch Trait Info (Name, Description, Location, etc) ## ### For mRNA Expression/"ProbeSet" ### ``` diff --git a/wqflask/base/webqtlConfig.py b/wqflask/base/webqtlConfig.py index b14cc4b0..a08acb0a 100644 --- a/wqflask/base/webqtlConfig.py +++ b/wqflask/base/webqtlConfig.py @@ -43,6 +43,7 @@ HOMOLOGENE_ID = "http://www.ncbi.nlm.nih.gov/homologene/?term=%s" GENOTATION_URL = "http://www.genotation.org/Getd2g.pl?gene_list=%s" GTEX_URL = "https://www.gtexportal.org/home/gene/%s" GENEBRIDGE_URL = "https://www.systems-genetics.org/modules_by_gene/%s?organism=%s" +GENEMANIA_URL = "https://genemania.org/search/%s/%s" UCSC_REFSEQ = "http://genome.cse.ucsc.edu/cgi-bin/hgTracks?db=%s&hgg_gene=%s&hgg_chrom=chr%s&hgg_start=%s&hgg_end=%s" BIOGPS_URL = "http://biogps.org/?org=%s#goto=genereport&id=%s" STRING_URL = "http://string-db.org/newstring_cgi/show_network_section.pl?identifier=%s" @@ -87,4 +88,3 @@ if not valid_path(JSON_GENODIR): PORTADDR = "http://50.16.251.170" INFOPAGEHREF = '/dbdoc/%s.html' CGIDIR = '/webqtl/' #XZ: The variable name 'CGIDIR' should be changed to 'PYTHONDIR' -SCRIPTFILE = 'main.py' diff --git a/wqflask/wqflask/api/router.py b/wqflask/wqflask/api/router.py index 845873a0..707e4e65 100644 --- a/wqflask/wqflask/api/router.py +++ b/wqflask/wqflask/api/router.py @@ -290,6 +290,120 @@ def get_dataset_info(dataset_name, group_name = None, file_format="json"): else: return return_error(code=204, source=request.url_rule.rule, title="No Results", details="") +@app.route("/api/v_{}/traits/<path:dataset_name>".format(version), methods=('GET',)) +@app.route("/api/v_{}/traits/<path:dataset_name>.<path:file_format>".format(version), methods=('GET',)) +def fetch_traits(dataset_name, file_format = "json"): + trait_ids, trait_names, data_type, dataset_id = get_dataset_trait_ids(dataset_name) + if ('ids_only' in request.args) and (len(trait_ids) > 0): + if file_format == "json": + filename = dataset_name + "_trait_ids.json" + return flask.jsonify(trait_ids) + else: + filename = dataset_name + "_trait_ids.csv" + + si = StringIO.StringIO() + csv_writer = csv.writer(si) + csv_writer.writerows([[trait_id] for trait_id in trait_ids]) + output = make_response(si.getvalue()) + output.headers["Content-Disposition"] = "attachment; filename=" + filename + output.headers["Content-type"] = "text/csv" + return output + elif ('names_only' in request.args) and (len(trait_ids) > 0): + if file_format == "json": + filename = dataset_name + "_trait_names.json" + return flask.jsonify(trait_names) + else: + filename = dataset_name + "_trait_names.csv" + + si = StringIO.StringIO() + csv_writer = csv.writer(si) + csv_writer.writerows([[trait_name] for trait_name in trait_names]) + output = make_response(si.getvalue()) + output.headers["Content-Disposition"] = "attachment; filename=" + filename + output.headers["Content-type"] = "text/csv" + return output + else: + if len(trait_ids) > 0: + if data_type == "ProbeSet": + query = """ + SELECT + ProbeSet.Id, ProbeSet.Name, ProbeSet.Symbol, ProbeSet.description, ProbeSet.Chr, ProbeSet.Mb, ProbeSet.alias, + ProbeSetXRef.mean, ProbeSetXRef.se, ProbeSetXRef.Locus, ProbeSetXRef.LRS, ProbeSetXRef.pValue, ProbeSetXRef.additive, ProbeSetXRef.h2 + FROM + ProbeSet, ProbeSetXRef + WHERE + ProbeSetXRef.ProbeSetFreezeId = '{0}' AND + ProbeSetXRef.ProbeSetId = ProbeSet.Id + ORDER BY + ProbeSet.Id + """ + + field_list = ["Id", "Name", "Symbol", "Description", "Chr", "Mb", "Aliases", "Mean", "SE", "Locus", "LRS", "P-Value", "Additive", "h2"] + elif data_type == "Geno": + query = """ + SELECT + Geno.Id, Geno.Name, Geno.Marker_Name, Geno.Chr, Geno.Mb, Geno.Sequence, Geno.Source + FROM + Geno, GenoXRef + WHERE + GenoXRef.GenoFreezeId = '{0}' AND + GenoXRef.GenoId = Geno.Id + ORDER BY + Geno.Id + """ + + field_list = ["Id", "Name", "Marker_Name", "Chr", "Mb", "Sequence", "Source"] + else: + query = """ + SELECT + PublishXRef.Id, PublishXRef.PhenotypeId, PublishXRef.PublicationId, PublishXRef.Locus, PublishXRef.LRS, PublishXRef.additive, PublishXRef.Sequence + FROM + PublishXRef + WHERE + PublishXRef.InbredSetId = {0} + ORDER BY + PublishXRef.Id + """ + + field_list = ["Id", "PhenotypeId", "PublicationId", "Locus", "LRS", "Additive", "Sequence"] + + if file_format == "json": + filename = dataset_name + "_traits.json" + + final_query = query.format(dataset_id) + + result_list = [] + for result in g.db.execute(final_query).fetchall(): + trait_dict = {} + for i, field in enumerate(field_list): + if result[i]: + trait_dict[field] = result[i] + result_list.append(trait_dict) + + return flask.jsonify(result_list) + elif file_format == "csv": + filename = dataset_name + "_traits.csv" + + results_list = [] + header_list = [] + header_list += field_list + results_list.append(header_list) + + final_query = query.format(dataset_id) + for result in g.db.execute(final_query).fetchall(): + results_list.append(result) + + si = StringIO.StringIO() + csv_writer = csv.writer(si) + csv_writer.writerows(results_list) + output = make_response(si.getvalue()) + output.headers["Content-Disposition"] = "attachment; filename=" + filename + output.headers["Content-type"] = "text/csv" + return output + else: + return return_error(code=400, source=request.url_rule.rule, title="Invalid Output Format", details="Current formats available are JSON and CSV, with CSV as default") + else: + return return_error(code=204, source=request.url_rule.rule, title="No Results", details="") @app.route("/api/v_{}/sample_data/<path:dataset_name>".format(version)) @app.route("/api/v_{}/sample_data/<path:dataset_name>.<path:file_format>".format(version)) @@ -434,7 +548,7 @@ def trait_sample_data(dataset_name, trait_name, file_format = "json"): dataset_or_group = dataset_name pheno_query = """ - SELECT + SELECT DISTINCT Strain.Name, Strain.Name2, PublishData.value, PublishData.Id, PublishSE.error, NStrain.count FROM (PublishData, Strain, PublishXRef, PublishFreeze) @@ -528,8 +642,6 @@ def get_trait_info(dataset_name, trait_name, file_format = "json"): PublishXRef.Id = '{0}' AND PublishXRef.InbredSetId = '{1}' """.format(trait_name, group_id) - - logger.debug("QUERY:", pheno_query) pheno_results = g.db.execute(pheno_query) @@ -612,13 +724,6 @@ def get_genotypes(group_name, file_format="csv"): return output -@app.route("/api/v_{}/traits/<path:dataset_name>".format(version), methods=('GET',)) -@app.route("/api/v_{}/traits/<path:dataset_name>.<path:file_format>".format(version), methods=('GET',)) -def get_traits(dataset_name, file_format = "json"): - #ZS: Need to check about the "start" and "stop" stuff since it seems to just limit the number of results to stop - start + 1 in Pjotr's elixir code - - NotImplemented - def return_error(code, source, title, details): json_ob = {"errors": [ { @@ -652,7 +757,7 @@ def get_dataset_trait_ids(dataset_name): dataset_id = results[0][2] return trait_ids, trait_names, data_type, dataset_id - elif "Publish" in dataset_name: + elif "Publish" in dataset_name or get_group_id(dataset_name): data_type = "Publish" dataset_name = dataset_name.replace("Publish", "") dataset_id = get_group_id(dataset_name) @@ -743,7 +848,10 @@ def get_group_id_from_dataset(dataset_name): result = g.db.execute(query).fetchone() - return result[0] + if len(result) > 0: + return result[0] + else: + return None def get_group_id(group_name): query = """ diff --git a/wqflask/wqflask/show_trait/show_trait.py b/wqflask/wqflask/show_trait/show_trait.py index 66d3a448..e10b31c0 100644 --- a/wqflask/wqflask/show_trait/show_trait.py +++ b/wqflask/wqflask/show_trait/show_trait.py @@ -257,7 +257,7 @@ class ShowTrait(object): self.genbank_link = webqtlConfig.GENBANK_ID % genbank_id self.genotation_link = self.gtex_link = self.genebridge_link = self.ucsc_blat_link = self.biogps_link = None - self.string_link = self.panther_link = self.aba_link = self.ebi_gwas_link = self.wiki_pi_link = None + self.string_link = self.panther_link = self.aba_link = self.ebi_gwas_link = self.wiki_pi_link = self.genemania_link = None if self.this_trait.symbol: self.genotation_link = webqtlConfig.GENOTATION_URL % self.this_trait.symbol self.gtex_link = webqtlConfig.GTEX_URL % self.this_trait.symbol @@ -266,7 +266,10 @@ class ShowTrait(object): self.ebi_gwas_link = webqtlConfig.EBIGWAS_URL % self.this_trait.symbol if self.dataset.group.species == "mouse" or self.dataset.group.species == "human": - self.genebridge_link = webqtlConfig.GENEBRIDGE_URL % (self.this_trait.symbol, self.dataset.group.species) + if self.dataset.group.species == "mouse": + self.genemania_link = webqtlConfig.GENEMANIA_URL % ("mus-musculus", self.this_trait.symbol) + else: + self.genemania_link = webqtlConfig.GENEMANIA_URL % ("homo-sapiens", self.this_trait.symbol) if self.dataset.group.species == "mouse": self.aba_link = webqtlConfig.ABA_URL % self.this_trait.symbol @@ -282,8 +285,10 @@ class ShowTrait(object): self.ucsc_blat_link = webqtlConfig.UCSC_REFSEQ % ('mm10', self.this_trait.refseq_transcriptid, chr, transcript_start, transcript_end) if self.dataset.group.species == "rat": + self.genemania_link = webqtlConfig.GENEMANIA_URL % ("rattus-norvegicus", self.this_trait.symbol) + query = """SELECT kgID, chromosome, txStart, txEnd - FROM GeneLink_rn33 + FROM GeneList_rn33 WHERE geneSymbol = '{}'""".format(self.this_trait.symbol) kgId, chr, transcript_start, transcript_end = g.db.execute(query).fetchall()[0] if len(g.db.execute(query).fetchall()) > 0 else None diff --git a/wqflask/wqflask/templates/collections/view.html b/wqflask/wqflask/templates/collections/view.html index 8d22b2a8..7e1001fc 100644 --- a/wqflask/wqflask/templates/collections/view.html +++ b/wqflask/wqflask/templates/collections/view.html @@ -84,8 +84,8 @@ <button class="btn btn-default" id="select_all"><span class="glyphicon glyphicon-ok"></span> Select All</button> <button class="btn btn-default" id="deselect_all"><span class="glyphicon glyphicon-remove"></span> Deselect All</button> <button class="btn btn-default" id="invert"><span class="glyphicon glyphicon-resize-vertical"></span> Invert</button> - <button class="btn btn-danger" id="remove" disabled="disabled"><i class="icon-minus-sign"></i> Delete From Collection</button> - <button class="btn" id="add" disabled="disabled"><i class="icon-plus-sign"></i> Copy Record to Other Collection</button> + <button class="btn btn-danger" id="remove" disabled="disabled"><i class="icon-minus-sign"></i> Delete Rows</button> + <button class="btn" id="add" disabled="disabled"><i class="icon-plus-sign"></i> Copy to Other Collection</button> <br /> <br /> <form id="export_form" method="POST" action="/export_traits_csv"> diff --git a/wqflask/wqflask/templates/search_result_page.html b/wqflask/wqflask/templates/search_result_page.html index e20ea2d3..bf434452 100644 --- a/wqflask/wqflask/templates/search_result_page.html +++ b/wqflask/wqflask/templates/search_result_page.html @@ -324,7 +324,11 @@ 'width': "500px", 'data': null, 'render': function(data, type, row, meta) { - return decodeURIComponent(escape(data.description)) + try { + return decodeURIComponent(escape(data.description)) + } catch { + return escape(data.description) + } } }, { diff --git a/wqflask/wqflask/templates/show_trait_details.html b/wqflask/wqflask/templates/show_trait_details.html index 09f36021..43efa314 100644 --- a/wqflask/wqflask/templates/show_trait_details.html +++ b/wqflask/wqflask/templates/show_trait_details.html @@ -88,6 +88,12 @@ </a> {% endif %} + {% if genemania_link %} + <a href="{{ genemania_link }}" title="GeneMANIA"> + GeneMANIA + </a> + + {% endif %} {% if unigene_link %} <a href="{{ unigene_link }}" title="NCBI UniGene"> UniGene |