about summary refs log tree commit diff
diff options
context:
space:
mode:
authorzsloan2019-06-04 11:24:46 -0500
committerzsloan2019-06-04 11:24:46 -0500
commit95a5e0e07fa9b4cd574beac5e4d9138a0b16bb60 (patch)
treee88780b0d1c33ef7511712d58eb5d682931be1c4
parent25eae5f41f5c821459f99bd0f3d777035a284564 (diff)
parent34d962fe1e0dd5e30f067e7a30fcbd8931f2aacb (diff)
downloadgenenetwork2-95a5e0e07fa9b4cd574beac5e4d9138a0b16bb60.tar.gz
Merge branch 'api' of github.com:zsloan/genenetwork2 into testing
-rw-r--r--doc/API_readme.md22
-rw-r--r--wqflask/base/webqtlConfig.py2
-rw-r--r--wqflask/wqflask/api/router.py132
-rw-r--r--wqflask/wqflask/show_trait/show_trait.py11
-rw-r--r--wqflask/wqflask/templates/collections/view.html4
-rw-r--r--wqflask/wqflask/templates/search_result_page.html6
-rw-r--r--wqflask/wqflask/templates/show_trait_details.html6
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>
             &nbsp;&nbsp;
             {% endif %}
+            {% if genemania_link %}
+            <a href="{{ genemania_link }}" title="GeneMANIA">
+                GeneMANIA
+            </a>
+            &nbsp;&nbsp;
+            {% endif %}
             {% if unigene_link %}
             <a href="{{ unigene_link }}" title="NCBI UniGene">
                 UniGene