From 4e6c8eba35a5ecd9e6b5b1c5faa98021656acb9d Mon Sep 17 00:00:00 2001 From: zsloan Date: Mon, 12 Aug 2019 16:34:05 -0500 Subject: Fixed some things to update the genome browser and get it running correctly Fixed issue where trait page for genotype traits didn't work Removed bad y axis title on probability plot --- .../marker_regression/display_mapping_results.py | 9 + wqflask/wqflask/marker_regression/run_mapping.py | 49 +- wqflask/wqflask/show_trait/show_trait.py | 4 +- .../static/new/javascript/init_genome_browser.js | 168 +- .../new/javascript/plotly_probability_plot.js | 1 - .../css/purescript-genetics-browser.css | 1 + .../css/purescript_genetics_browser_v01.css | 1 - .../js/purescript-genetics-browser.js | 63016 +++++++++++++++++++ .../js/purescript-genetics-browser_v01.js | 659 - wqflask/wqflask/templates/mapping_results.html | 10 +- wqflask/wqflask/views.py | 4 +- 11 files changed, 63166 insertions(+), 756 deletions(-) create mode 100644 wqflask/wqflask/static/packages/purescript_genome_browser/css/purescript-genetics-browser.css delete mode 100644 wqflask/wqflask/static/packages/purescript_genome_browser/css/purescript_genetics_browser_v01.css create mode 100644 wqflask/wqflask/static/packages/purescript_genome_browser/js/purescript-genetics-browser.js delete mode 100644 wqflask/wqflask/static/packages/purescript_genome_browser/js/purescript-genetics-browser_v01.js diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py index ea1ca5ed..b1e9dad4 100644 --- a/wqflask/wqflask/marker_regression/display_mapping_results.py +++ b/wqflask/wqflask/marker_regression/display_mapping_results.py @@ -31,6 +31,7 @@ import piddle as pid import sys,os import cPickle import httplib +import json from flask import Flask, g @@ -1696,6 +1697,14 @@ class DisplayMappingResults(object): else: LRS_LOD_Max = self.lrsMax + #ZS: Needed to pass to genome browser + js_data = json.loads(self.js_data) + if self.LRS_LOD == "LRS": + js_data['max_score'] = LRS_LOD_Max/4.16 + else: + js_data['max_score'] = LRS_LOD_Max + self.js_data = json.dumps(js_data) + if LRS_LOD_Max > 100: LRSScale = 20.0 elif LRS_LOD_Max > 20: diff --git a/wqflask/wqflask/marker_regression/run_mapping.py b/wqflask/wqflask/marker_regression/run_mapping.py index 7f6bb0a5..11ad7aa4 100644 --- a/wqflask/wqflask/marker_regression/run_mapping.py +++ b/wqflask/wqflask/marker_regression/run_mapping.py @@ -7,6 +7,7 @@ from pprint import pformat as pf import string import math +from decimal import Decimal import random import sys import datetime @@ -314,30 +315,41 @@ class RunMapping(object): else: self.qtl_results = [] self.qtl_results_for_browser = [] + self.annotations_for_browser = [] highest_chr = 1 #This is needed in order to convert the highest chr to X/Y for marker in results: browser_marker = dict( chr = str(marker['chr']), rs = marker['name'], - ps = marker['Mb']*1000000 + ps = marker['Mb']*1000000, + url = "/show_trait?trait_id=" + marker['name'] + "&dataset=" + self.dataset.group.name + "Geno" ) - if 'p_value' in marker: - browser_marker['p_wald'] = marker['p_value'] + annot_marker = dict( + name = str(marker['name']), + chr = str(marker['chr']), + rs = marker['name'], + pos = marker['Mb']*1000000, + url = "/show_trait?trait_id=" + marker['name'] + "&dataset=" + self.dataset.group.name + "Geno" + ) + #if 'p_value' in marker: + # logger.debug("P EXISTS:", marker['p_value']) + #else: + if 'lrs_value' in marker and marker['lrs_value'] > 0: + browser_marker['p_wald'] = 10**-(marker['lrs_value']/4.61) + elif 'lod_score' in marker and marker['lod_score'] > 0: + browser_marker['p_wald'] = 10**-(marker['lod_score']) else: - if 'lrs_value' in marker and marker['lrs_value'] > 0: - browser_marker['p_wald'] = -math.log10(marker['lrs_value']/4.16) - elif 'lod_score' in marker and marker['lod_score'] > 0: - browser_marker['p_wald'] = -math.log10(marker['lod_score']) - else: - browser_marker['p_wald'] = 0 + browser_marker['p_wald'] = 0 + self.qtl_results_for_browser.append(browser_marker) + self.annotations_for_browser.append(annot_marker) if marker['chr'] > 0 or marker['chr'] == "X" or marker['chr'] == "X/Y": if marker['chr'] > highest_chr or marker['chr'] == "X" or marker['chr'] == "X/Y": highest_chr = marker['chr'] if ('lod_score' in marker.keys()) or ('lrs_value' in marker.keys()): self.qtl_results.append(marker) - browser_files = write_input_for_browser(self.dataset, self.qtl_results_for_browser) + browser_files = write_input_for_browser(self.dataset, self.qtl_results_for_browser, self.annotations_for_browser) with Bench("Exporting Results"): export_mapping_results(self.dataset, self.this_trait, self.qtl_results, self.mapping_results_path, self.mapping_scale, self.score_type) @@ -350,6 +362,11 @@ class RunMapping(object): self.trimmed_markers = trim_markers_for_table(results) if self.mapping_method != "gemma": + if self.score_type == "LRS": + significant_for_browser = self.significant / 4.16 + else: + significant_for_browser = self.significant + self.js_data = dict( #result_score_type = self.score_type, #this_trait = self.this_trait.name, @@ -361,7 +378,8 @@ class RunMapping(object): #qtl_results = self.qtl_results, num_perm = self.num_perm, perm_results = self.perm_output, - browser_files = browser_files + browser_files = browser_files, + significant = significant_for_browser ) else: self.js_data = dict( @@ -406,6 +424,7 @@ class RunMapping(object): def export_mapping_results(dataset, trait, markers, results_path, mapping_scale, score_type): with open(results_path, "w+") as output_file: + output_file.write("Time/Date: " + datetime.datetime.now().strftime("%x / %X") + "\n") output_file.write("Population: " + dataset.group.species.title() + " " + dataset.group.name + "\n") output_file.write("Data Set: " + dataset.fullname + "\n") if dataset.type == "ProbeSet": @@ -413,6 +432,8 @@ def export_mapping_results(dataset, trait, markers, results_path, mapping_scale, output_file.write("Location: " + str(trait.chr) + " @ " + str(trait.mb) + " Mb\n") output_file.write("\n") output_file.write("Name,Chr,") + if score_type.lower() == "-log(p)": + score_type = "'-log(p)" if mapping_scale == "physic": output_file.write("Mb," + score_type) else: @@ -491,7 +512,7 @@ def trim_markers_for_table(markers): else: return sorted_markers -def write_input_for_browser(this_dataset, markers): +def write_input_for_browser(this_dataset, gwas_results, annotations): file_base = this_dataset.group.name + "_" + ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(6)) gwas_filename = file_base + "_GWAS" annot_filename = file_base + "_ANNOT" @@ -499,8 +520,8 @@ def write_input_for_browser(this_dataset, markers): annot_path = "{}/gn2/".format(TEMPDIR) + annot_filename with open(gwas_path + ".json", "w") as gwas_file, open(annot_path + ".json", "w") as annot_file: - gwas_file.write(json.dumps(markers)) - annot_file.write(json.dumps([])) + gwas_file.write(json.dumps(gwas_results)) + annot_file.write(json.dumps(annotations)) return [gwas_filename, annot_filename] #return [gwas_filename, annot_filename] \ No newline at end of file diff --git a/wqflask/wqflask/show_trait/show_trait.py b/wqflask/wqflask/show_trait/show_trait.py index b0a46b32..02c65d47 100644 --- a/wqflask/wqflask/show_trait/show_trait.py +++ b/wqflask/wqflask/show_trait/show_trait.py @@ -194,10 +194,10 @@ class ShowTrait(object): trait_symbol = self.this_trait.symbol short_description = trait_symbol - elif self.this_trait.post_publication_abbreviation: + elif hasattr(self.this_trait, 'post_publication_abbreviation'): short_description = self.this_trait.post_publication_abbreviation - elif self.this_trait.pre_publication_abbreviation: + elif hasattr(self.this_trait, 'pre_publication_abbreviation'): short_description = self.this_trait.pre_publication_abbreviation # Todo: Add back in the ones we actually need from below, as we discover we need them diff --git a/wqflask/wqflask/static/new/javascript/init_genome_browser.js b/wqflask/wqflask/static/new/javascript/init_genome_browser.js index 64a300bc..7dfd6712 100644 --- a/wqflask/wqflask/static/new/javascript/init_genome_browser.js +++ b/wqflask/wqflask/static/new/javascript/init_genome_browser.js @@ -1,73 +1,97 @@ -console.log("THE FILES:", js_data.browser_files) - -snps_filename = "/browser_input?filename=" + js_data.browser_files[0] -annot_filename = "/browser_input?filename=" + js_data.browser_files[1] - -localUrls = -{ - snps: snps_filename, - annotations: null -}; - -var vscaleWidth = 90.0; -var legendWidth = 140.0; -var score = { min: 0.0, max: 30.0, sig: 4 }; -var gwasPadding = { top: 35.0, - bottom: 35.0, - left: vscaleWidth, - right: legendWidth }; -var gwasHeight = 420.0; -var genePadding = { top: 10.0, - bottom: 35.0, - left: vscaleWidth, - right: legendWidth }; -var geneHeight = 140.0; - - -var config = -{ trackHeight: 400.0, - padding: gwasPadding, - score: score, - urls: localUrls, - tracks: { - gwas: { - trackHeight: gwasHeight, - padding: gwasPadding, - snps: { - radius: 3.75, - lineWidth: 1.0, - color: { outline: "#FFFFFF", - fill: "#00008B" }, - pixelOffset: {x: 0.0, y: 0.0} - }, - annotations: { - radius: 5.5, - outline: "#000000", - snpColor: "#0074D9", - geneColor: "#FF4136" - }, - score: score, - legend: { - fontSize: 14, - hPad: 0.2, - vPad: 0.2 - }, - vscale: { - color: "#000000", - hPad: 0.125, - numSteps: 3, - fonts: { labelSize: 18, scaleSize: 16 } - }, - } - }, - chrs: { - chrBG1: "#FFFFFF", - chrBG2: "#DDDDDD", - chrLabels: { fontSize: 16 }, - }, - initialChrs: { left: "1", right: "19" } -}; - -GenomeBrowser.main(config)(); - +console.log("THE FILES:", js_data.browser_files) + +snps_filename = "/browser_input?filename=" + js_data.browser_files[0] +annot_filename = "/browser_input?filename=" + js_data.browser_files[1] + +localUrls = +{ + snps: snps_filename, + annotations: annot_filename +}; + +var coordinateSystem = + [ + { chr: "1", size: "195471971" }, + { chr: "2", size: "182113224" }, + { chr: "3", size: "160039680" }, + { chr: "4", size: "156508116" }, + { chr: "5", size: "151834684" }, + { chr: "6", size: "149736546" }, + { chr: "7", size: "145441459" }, + { chr: "8", size: "129401213" }, + { chr: "9", size: "124595110" }, + { chr: "10", size: "130694993" }, + { chr: "11", size: "122082543" }, + { chr: "12", size: "120129022" }, + { chr: "13", size: "120421639" }, + { chr: "14", size: "124902244" }, + { chr: "15", size: "104043685" }, + { chr: "16", size: "98207768" }, + { chr: "17", size: "94987271" }, + { chr: "18", size: "90702639" }, + { chr: "19", size: "61431566" }, + ]; + +var vscaleWidth = 90.0; +var legendWidth = 140.0; + +if ('significant' in js_data) { + var significant_score = parseFloat(js_data.significant) +} else { + var significant_score = 4 +} +var score = { min: 0.0, max: js_data.max_score, sig: significant_score }; +var gwasPadding = { top: 35.0, + bottom: 35.0, + left: vscaleWidth, + right: legendWidth }; +var gwasHeight = 320.0; +var config = +{ score: score, + urls: localUrls, + tracks: { + gwas: { + trackHeight: gwasHeight, + padding: gwasPadding, + snps: { + radius: 3.75, + lineWidth: 1.0, + color: { outline: "#FFFFFF", + fill: "#00008B" }, + pixelOffset: {x: 0.0, y: 0.0} + }, + annotations: { + urls: { + url: "GeneNetwork" + }, + radius: 5.5, + outline: "#000000", + snpColor: "#0074D9", + geneColor: "#FF4136" + }, + score: score, + legend: { + fontSize: 14, + hPad: 0.2, + vPad: 0.2 + }, + vscale: { + color: "#000000", + hPad: 0.125, + numSteps: 3, + fonts: { labelSize: 18, scaleSize: 16 } + }, + }, + }, + chrs: { + chrBG1: "#FFFFFF", + chrBG2: "#EEEEEE", + chrLabels: { fontSize: 16 }, + }, + // initialChrs: { left: "1", right: "5" } + coordinateSystem: coordinateSystem, + }; + +GenomeBrowser.main(config)(); + document.getElementById("controls").style.visibility = "visible"; \ No newline at end of file diff --git a/wqflask/wqflask/static/new/javascript/plotly_probability_plot.js b/wqflask/wqflask/static/new/javascript/plotly_probability_plot.js index cc4195e4..e8b7ab83 100644 --- a/wqflask/wqflask/static/new/javascript/plotly_probability_plot.js +++ b/wqflask/wqflask/static/new/javascript/plotly_probability_plot.js @@ -195,7 +195,6 @@ } }, yaxis: { - title: "Data Quantiles", zeroline: false, visible: true, linecolor: 'black', diff --git a/wqflask/wqflask/static/packages/purescript_genome_browser/css/purescript-genetics-browser.css b/wqflask/wqflask/static/packages/purescript_genome_browser/css/purescript-genetics-browser.css new file mode 100644 index 00000000..135292ac --- /dev/null +++ b/wqflask/wqflask/static/packages/purescript_genome_browser/css/purescript-genetics-browser.css @@ -0,0 +1 @@ +body,html{max-width:100%;overflow-x:hidden}#browser{position:absolute;margin:0}#info-line{border:1px solid #aaa;padding:2px;position:absolute;right:0;top:1px;min-width:14%;font-size:9pt}#controls{visibility:hidden;position:absolute;top:4px;left:100px;z-index:1000}#controls>button{border:1px solid #aaa;border-radius:2px;padding-left:6px;padding-right:6px;height:23px;min-width:20px}button#scrollRight,button#zoomIn{margin-left:-2px;margin-right:4px}#infoBox{position:absolute;display:inline-block;z-index:10000;visibility:hidden;padding:5px;border:2px solid grey;border-radius:5%;background-color:#fff;min-height:100px;min-width:10px;max-width:80%;margin-top:9.7em;font-family:sans-serif}#infoBox>div{float:left;margin:1em 1.2em}#infoBox>div>p{margin:.1em} \ No newline at end of file diff --git a/wqflask/wqflask/static/packages/purescript_genome_browser/css/purescript_genetics_browser_v01.css b/wqflask/wqflask/static/packages/purescript_genome_browser/css/purescript_genetics_browser_v01.css deleted file mode 100644 index 135292ac..00000000 --- a/wqflask/wqflask/static/packages/purescript_genome_browser/css/purescript_genetics_browser_v01.css +++ /dev/null @@ -1 +0,0 @@ -body,html{max-width:100%;overflow-x:hidden}#browser{position:absolute;margin:0}#info-line{border:1px solid #aaa;padding:2px;position:absolute;right:0;top:1px;min-width:14%;font-size:9pt}#controls{visibility:hidden;position:absolute;top:4px;left:100px;z-index:1000}#controls>button{border:1px solid #aaa;border-radius:2px;padding-left:6px;padding-right:6px;height:23px;min-width:20px}button#scrollRight,button#zoomIn{margin-left:-2px;margin-right:4px}#infoBox{position:absolute;display:inline-block;z-index:10000;visibility:hidden;padding:5px;border:2px solid grey;border-radius:5%;background-color:#fff;min-height:100px;min-width:10px;max-width:80%;margin-top:9.7em;font-family:sans-serif}#infoBox>div{float:left;margin:1em 1.2em}#infoBox>div>p{margin:.1em} \ No newline at end of file diff --git a/wqflask/wqflask/static/packages/purescript_genome_browser/js/purescript-genetics-browser.js b/wqflask/wqflask/static/packages/purescript_genome_browser/js/purescript-genetics-browser.js new file mode 100644 index 00000000..27bb4b2f --- /dev/null +++ b/wqflask/wqflask/static/packages/purescript_genome_browser/js/purescript-genetics-browser.js @@ -0,0 +1,63016 @@ +// modules are defined as an array +// [ module function, map of requires ] +// +// map of requires is short require name -> numeric require +// +// anything defined in a previous bundle is accessed via the +// orig method which is the require for previous bundles +parcelRequire = (function (modules, cache, entry, globalName) { + // Save the require from previous bundle to this closure if any + var previousRequire = typeof parcelRequire === 'function' && parcelRequire; + var nodeRequire = typeof require === 'function' && require; + + function newRequire(name, jumped) { + if (!cache[name]) { + if (!modules[name]) { + // if we cannot find the module within our internal map or + // cache jump to the current global require ie. the last bundle + // that was added to the page. + var currentRequire = typeof parcelRequire === 'function' && parcelRequire; + if (!jumped && currentRequire) { + return currentRequire(name, true); + } + + // If there are other bundles on this page the require from the + // previous one is saved to 'previousRequire'. Repeat this as + // many times as there are bundles until the module is found or + // we exhaust the require chain. + if (previousRequire) { + return previousRequire(name, true); + } + + // Try the node require function if it exists. + if (nodeRequire && typeof name === 'string') { + return nodeRequire(name); + } + + var err = new Error('Cannot find module \'' + name + '\''); + err.code = 'MODULE_NOT_FOUND'; + throw err; + } + + localRequire.resolve = resolve; + localRequire.cache = {}; + + var module = cache[name] = new newRequire.Module(name); + + modules[name][0].call(module.exports, localRequire, module, module.exports, this); + } + + return cache[name].exports; + + function localRequire(x){ + return newRequire(localRequire.resolve(x)); + } + + function resolve(x){ + return modules[name][1][x] || x; + } + } + + function Module(moduleName) { + this.id = moduleName; + this.bundle = newRequire; + this.exports = {}; + } + + newRequire.isParcelRequire = true; + newRequire.Module = Module; + newRequire.modules = modules; + newRequire.cache = cache; + newRequire.parent = previousRequire; + newRequire.register = function (id, exports) { + modules[id] = [function (require, module) { + module.exports = exports; + }, {}]; + }; + + var error; + for (var i = 0; i < entry.length; i++) { + try { + newRequire(entry[i]); + } catch (e) { + // Save first error but execute all entries + if (!error) { + error = e; + } + } + } + + if (entry.length) { + // Expose entry point to Node, AMD or browser globals + // Based on https://github.com/ForbesLindesay/umd/blob/master/template.js + var mainExports = newRequire(entry[entry.length - 1]); + + // CommonJS + if (typeof exports === "object" && typeof module !== "undefined") { + module.exports = mainExports; + + // RequireJS + } else if (typeof define === "function" && define.amd) { + define(function () { + return mainExports; + }); + + // - +