diff options
author | Zachary Sloan | 2015-01-30 17:21:19 +0000 |
---|---|---|
committer | Zachary Sloan | 2015-01-30 17:21:19 +0000 |
commit | e48ec8826ec48bd4ba53f681796a235737ab0d29 (patch) | |
tree | 4345363ab32d69a899bf4ee21e726075bc749d3a /wqflask | |
parent | c05b56d96d0a86a0c88daea6ec5c68c5856741cd (diff) | |
download | genenetwork2-e48ec8826ec48bd4ba53f681796a235737ab0d29.tar.gz |
Fixed several bugs
Added legend to bar chart color by trait function
Added scatterplot matrix figure
Fixed database timeout problem
Diffstat (limited to 'wqflask')
20 files changed, 979 insertions, 345 deletions
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py index 15a8c7cc..8965e1d1 100755 --- a/wqflask/base/data_set.py +++ b/wqflask/base/data_set.py @@ -640,7 +640,7 @@ class PhenotypeDataSet(DataSet): 'Year', 'Max LRS', 'Max LRS Location', - 'Add. Effect'] + 'Add. Effect<a href="http://genenetwork.org//glossary.html#A" target="_blank"><sup style="color:#f00"> ?</sup></a>'] self.type = 'Publish' @@ -901,7 +901,7 @@ class MrnaAssayDataSet(DataSet): 'Mean Expr', 'Max LRS', 'Max LRS Location', - 'Add. Effect'] + 'Add. Effect<a href="http://genenetwork.org//glossary.html#A" target="_blank"><sup style="color:#f00"> ?</sup></a>'] # Todo: Obsolete or rename this field self.type = 'ProbeSet' diff --git a/wqflask/cfg/default_settings.py b/wqflask/cfg/default_settings.py index 8fca3d77..8b5d1313 100755 --- a/wqflask/cfg/default_settings.py +++ b/wqflask/cfg/default_settings.py @@ -13,3 +13,5 @@ SECURITY_RECOVERABLE = True SECURITY_EMAIL_SENDER = "no-reply@genenetwork.org" SECURITY_POST_LOGIN_VIEW = "/thank_you" + +SQLALCHEMY_POOL_RECYCLE = 3600
\ No newline at end of file diff --git a/wqflask/wqflask/search_results.py b/wqflask/wqflask/search_results.py index 5444d1bc..9d2d0b88 100755 --- a/wqflask/wqflask/search_results.py +++ b/wqflask/wqflask/search_results.py @@ -233,11 +233,6 @@ class SearchResultPage(object): print("search_type is:", pf(search_type)) - # This is throwing an error when a_search['key'] is None, so I changed above - #search_type = string.upper(a_search['key']) - #if not search_type: - # search_type = self.dataset.type - search_ob = do_search.DoSearch.get_search(search_type) search_class = getattr(do_search, search_ob) print("search_class is: ", pf(search_class)) diff --git a/wqflask/wqflask/static/new/css/show_trait.css b/wqflask/wqflask/static/new/css/show_trait.css index 9dcbfce9..9fc82a85 100644 --- a/wqflask/wqflask/static/new/css/show_trait.css +++ b/wqflask/wqflask/static/new/css/show_trait.css @@ -1,3 +1,7 @@ -tr .outlier {
- background-color: #ffff99;
+tr .outlier { + background-color: #ffff99; +} + +#bar_chart_container { + overflow-x:scroll; }
\ No newline at end of file diff --git a/wqflask/wqflask/static/new/javascript/bar_chart.coffee b/wqflask/wqflask/static/new/javascript/bar_chart.coffee index a48718de..c83de64e 100755 --- a/wqflask/wqflask/static/new/javascript/bar_chart.coffee +++ b/wqflask/wqflask/static/new/javascript/bar_chart.coffee @@ -28,7 +28,7 @@ class Bar_Chart @plot_height -= @y_buffer @create_scales() @create_graph() - + d3.select("#color_attribute").on("change", => @attribute = $("#color_attribute").val() console.log("attr_color_dict:", @attr_color_dict) @@ -59,6 +59,7 @@ class Bar_Chart else return @attr_color_dict[@attribute][d[2][@attribute]] ) + @draw_legend() @add_legend(@attribute, @distinct_attr_vals[@attribute]) ) @@ -181,6 +182,8 @@ class Bar_Chart @attr_color_dict = {} console.log("vals:", vals) for own key, distinct_vals of vals + @min_val = d3.min(distinct_vals) + @max_val = d3.max(distinct_vals) this_color_dict = {} if distinct_vals.length < 10 color = d3.scale.category10() @@ -197,8 +200,8 @@ class Bar_Chart return true ) color_range = d3.scale.linear() - .domain([d3.min(distinct_vals), - d3.max(distinct_vals)]) + .domain([min_val, + max_val]) .range([0,255]) for value, i in distinct_vals console.log("color_range(value):", parseInt(color_range(value))) @@ -206,12 +209,30 @@ class Bar_Chart #this_color_dict[value] = d3.rgb("lightblue").darker(color_range(parseInt(value))) #this_color_dict[value] = "rgb(0, 0, " + color_range(parseInt(value)) + ")" @attr_color_dict[key] = this_color_dict + + + + draw_legend: () -> + $('#legend-left').html(@min_val) + $('#legend-right').html(@max_val) + svg_html = '<svg height="10" width="90"> \ + <rect x="0" width="15" height="10" style="fill: rgb(0, 0, 0);"></rect> \ + <rect x="15" width="15" height="10" style="fill: rgb(50, 0, 0);"></rect> \ + <rect x="30" width="15" height="10" style="fill: rgb(100, 0, 0);"></rect> \ + <rect x="45" width="15" height="10" style="fill: rgb(150, 0, 0);"></rect> \ + <rect x="60" width="15" height="10" style="fill: rgb(200, 0, 0);"></rect> \ + <rect x="75" width="15" height="10" style="fill: rgb(255, 0, 0);"></rect> \ + </svg>' + console.log("svg_html:", svg_html) + $('#legend-colors').html(svg_html) get_trait_color_dict: (samples, vals) -> @trait_color_dict = {} console.log("vals:", vals) for own key, distinct_vals of vals this_color_dict = {} + @min_val = d3.min(distinct_vals) + @max_val = d3.max(distinct_vals) if distinct_vals.length < 10 color = d3.scale.category10() for value, i in distinct_vals @@ -434,8 +455,8 @@ class Bar_Chart .select("title") .text((d) => return d[1] - ) - + ) + @draw_legend() else @svg.selectAll(".bar") .data(@sorted_samples()) @@ -448,7 +469,8 @@ class Bar_Chart .select("title") .text((d) => return d[1] - ) + ) + @draw_legend() trim_values: (trait_sample_data) -> trimmed_samples = {} diff --git a/wqflask/wqflask/static/new/javascript/bar_chart.js b/wqflask/wqflask/static/new/javascript/bar_chart.js index 07761ba7..f5ed544b 100755 --- a/wqflask/wqflask/static/new/javascript/bar_chart.js +++ b/wqflask/wqflask/static/new/javascript/bar_chart.js @@ -66,6 +66,7 @@ Bar_Chart = (function() { } }); } + _this.draw_legend(); return _this.add_legend(_this.attribute, _this.distinct_attr_vals[_this.attribute]); }; })(this)); @@ -150,6 +151,8 @@ Bar_Chart = (function() { for (key in vals) { if (!__hasProp.call(vals, key)) continue; distinct_vals = vals[key]; + this.min_val = d3.min(distinct_vals); + this.max_val = d3.max(distinct_vals); this_color_dict = {}; if (distinct_vals.length < 10) { color = d3.scale.category10(); @@ -168,7 +171,7 @@ Bar_Chart = (function() { } }; })(this))) { - color_range = d3.scale.linear().domain([d3.min(distinct_vals), d3.max(distinct_vals)]).range([0, 255]); + color_range = d3.scale.linear().domain([min_val, max_val]).range([0, 255]); for (i = _j = 0, _len1 = distinct_vals.length; _j < _len1; i = ++_j) { value = distinct_vals[i]; console.log("color_range(value):", parseInt(color_range(value))); @@ -181,6 +184,15 @@ Bar_Chart = (function() { return _results; }; + Bar_Chart.prototype.draw_legend = function() { + var svg_html; + $('#legend-left').html(this.min_val); + $('#legend-right').html(this.max_val); + svg_html = '<svg height="10" width="90"> <rect x="0" width="15" height="10" style="fill: rgb(0, 0, 0);"></rect> <rect x="15" width="15" height="10" style="fill: rgb(50, 0, 0);"></rect> <rect x="30" width="15" height="10" style="fill: rgb(100, 0, 0);"></rect> <rect x="45" width="15" height="10" style="fill: rgb(150, 0, 0);"></rect> <rect x="60" width="15" height="10" style="fill: rgb(200, 0, 0);"></rect> <rect x="75" width="15" height="10" style="fill: rgb(255, 0, 0);"></rect> </svg>'; + console.log("svg_html:", svg_html); + return $('#legend-colors').html(svg_html); + }; + Bar_Chart.prototype.get_trait_color_dict = function(samples, vals) { var color, color_range, distinct_vals, i, key, sample, this_color_dict, value, _i, _j, _len, _len1, _results; this.trait_color_dict = {}; @@ -189,6 +201,8 @@ Bar_Chart = (function() { if (!__hasProp.call(vals, key)) continue; distinct_vals = vals[key]; this_color_dict = {}; + this.min_val = d3.min(distinct_vals); + this.max_val = d3.max(distinct_vals); if (distinct_vals.length < 10) { color = d3.scale.category10(); for (i = _i = 0, _len = distinct_vals.length; _i < _len; i = ++_i) { @@ -426,7 +440,7 @@ Bar_Chart = (function() { console.log("TRAIT_COLOR_DICT:", this.trait_color_dict); console.log("SAMPLES:", this.samples); if (this.sort_by = "value") { - return this.svg.selectAll(".bar").data(this.samples).transition().duration(1000).style("fill", (function(_this) { + this.svg.selectAll(".bar").data(this.samples).transition().duration(1000).style("fill", (function(_this) { return function(d) { console.log("this color:", _this.trait_color_dict[d[0]]); return _this.trait_color_dict[d[0]]; @@ -436,8 +450,9 @@ Bar_Chart = (function() { return d[1]; }; })(this)); + return this.draw_legend(); } else { - return this.svg.selectAll(".bar").data(this.sorted_samples()).transition().duration(1000).style("fill", (function(_this) { + this.svg.selectAll(".bar").data(this.sorted_samples()).transition().duration(1000).style("fill", (function(_this) { return function(d) { console.log("this color:", _this.trait_color_dict[d[0]]); return _this.trait_color_dict[d[0]]; @@ -447,6 +462,7 @@ Bar_Chart = (function() { return d[1]; }; })(this)); + return this.draw_legend(); } }; diff --git a/wqflask/wqflask/static/new/javascript/get_traits_from_collection.coffee b/wqflask/wqflask/static/new/javascript/get_traits_from_collection.coffee index ff7c041c..07be824f 100755 --- a/wqflask/wqflask/static/new/javascript/get_traits_from_collection.coffee +++ b/wqflask/wqflask/static/new/javascript/get_traits_from_collection.coffee @@ -57,10 +57,52 @@ submit_click = () -> this_trait_vals.push(null) all_vals.push(this_trait_vals) - create_scatterplots(trait_names, samples, all_vals) + trait_vals_csv = create_trait_data_csv(selected_traits) + scatter_matrix = new ScatterMatrix(trait_vals_csv) + scatter_matrix.render() + + + #create_scatterplots(trait_names, samples, all_vals) $.colorbox.close() +create_trait_data_csv = (selected_traits) -> + trait_names = [] + trait_names.push($('input[name=trait_id]').val()) + samples = $('input[name=allsamples]').val().split(" ") + all_vals = [] + this_trait_vals = get_this_trait_vals(samples) + all_vals.push(this_trait_vals) + + for trait in Object.keys(selected_traits) + trait_names.push(trait) + + this_trait_vals = [] + for sample in samples + if sample in Object.keys(selected_traits[trait]) + this_trait_vals.push(parseFloat(selected_traits[trait][sample])) + else + this_trait_vals.push(null) + all_vals.push(this_trait_vals) + + console.log("all_vals:", all_vals) + + trait_vals_csv = trait_names.join(",") + trait_vals_csv += "\n" + + for sample, index in samples + if all_vals[0][index] == null + continue + sample_vals = [] + for trait in all_vals + sample_vals.push(trait[index]) + trait_vals_csv += sample_vals.join(",") + trait_vals_csv += "\n" + + #console.log("trait_vals_csv:", trait_vals_csv) + + return trait_vals_csv + trait_click = () -> console.log("Clicking on:", $(this)) trait = $(this).parent().find('.trait').text() diff --git a/wqflask/wqflask/static/new/javascript/get_traits_from_collection.js b/wqflask/wqflask/static/new/javascript/get_traits_from_collection.js index af3f5135..a73eafe4 100755 --- a/wqflask/wqflask/static/new/javascript/get_traits_from_collection.js +++ b/wqflask/wqflask/static/new/javascript/get_traits_from_collection.js @@ -1,5 +1,5 @@ // Generated by CoffeeScript 1.8.0 -var add_trait_data, assemble_into_json, back_to_collections, collection_click, collection_list, color_by_trait, get_this_trait_vals, get_trait_data, process_traits, selected_traits, submit_click, this_trait_data, trait_click, +var add_trait_data, assemble_into_json, back_to_collections, collection_click, collection_list, color_by_trait, create_trait_data_csv, get_this_trait_vals, get_trait_data, process_traits, selected_traits, submit_click, this_trait_data, trait_click, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; console.log("before get_traits_from_collection"); @@ -25,7 +25,7 @@ collection_click = function() { }; submit_click = function() { - var all_vals, sample, samples, this_trait_vals, trait, trait_names, traits, _i, _j, _len, _len1, _ref; + var all_vals, sample, samples, scatter_matrix, this_trait_vals, trait, trait_names, trait_vals_csv, traits, _i, _j, _len, _len1, _ref; selected_traits = {}; traits = []; $('#collections_holder').find('input[type=checkbox]:checked').each(function() { @@ -63,10 +63,54 @@ submit_click = function() { } all_vals.push(this_trait_vals); } - create_scatterplots(trait_names, samples, all_vals); + trait_vals_csv = create_trait_data_csv(selected_traits); + scatter_matrix = new ScatterMatrix(trait_vals_csv); + scatter_matrix.render(); return $.colorbox.close(); }; +create_trait_data_csv = function(selected_traits) { + var all_vals, index, sample, sample_vals, samples, this_trait_vals, trait, trait_names, trait_vals_csv, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref; + trait_names = []; + trait_names.push($('input[name=trait_id]').val()); + samples = $('input[name=allsamples]').val().split(" "); + all_vals = []; + this_trait_vals = get_this_trait_vals(samples); + all_vals.push(this_trait_vals); + _ref = Object.keys(selected_traits); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + trait = _ref[_i]; + trait_names.push(trait); + this_trait_vals = []; + for (_j = 0, _len1 = samples.length; _j < _len1; _j++) { + sample = samples[_j]; + if (__indexOf.call(Object.keys(selected_traits[trait]), sample) >= 0) { + this_trait_vals.push(parseFloat(selected_traits[trait][sample])); + } else { + this_trait_vals.push(null); + } + } + all_vals.push(this_trait_vals); + } + console.log("all_vals:", all_vals); + trait_vals_csv = trait_names.join(","); + trait_vals_csv += "\n"; + for (index = _k = 0, _len2 = samples.length; _k < _len2; index = ++_k) { + sample = samples[index]; + if (all_vals[0][index] === null) { + continue; + } + sample_vals = []; + for (_l = 0, _len3 = all_vals.length; _l < _len3; _l++) { + trait = all_vals[_l]; + sample_vals.push(trait[index]); + } + trait_vals_csv += sample_vals.join(","); + trait_vals_csv += "\n"; + } + return trait_vals_csv; +}; + trait_click = function() { var dataset, this_trait_url, trait; console.log("Clicking on:", $(this)); diff --git a/wqflask/wqflask/static/new/javascript/scatter-matrix.js b/wqflask/wqflask/static/new/javascript/scatter-matrix.js new file mode 100644 index 00000000..38fd276e --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/scatter-matrix.js @@ -0,0 +1,549 @@ +// Heavily influenced by Mike Bostock's Scatter Matrix example +// http://mbostock.github.io/d3/talk/20111116/iris-splom.html +// + +/* +ScatterMatrix = function(url) { + this.__url = url; + this.__data = undefined; + this.__cell_size = 140; +}; +*/ + +ScatterMatrix = function(csv_string) { + this.__csv_string = csv_string; + this.__data = undefined; + this.__cell_size = 140; +}; + +ScatterMatrix.prototype.cellSize = function(n) { + this.__cell_size = n; + return this; +}; + +/* +ScatterMatrix.prototype.onData = function(cb) { + if (this.__data) { cb(); return; } + var self = this; + d3.csv(self.__url, function(data) { + self.__data = data; + cb(); + }); +}; +*/ + +ScatterMatrix.prototype.onData = function(cb) { + if (this.__data) { cb(); return; } + var self = this; + console.log("self.csv_string:", self.__csv_string) + + data = d3.csv.parse(self.__csv_string); + self.__data = data; + cb(); + +/* + d3.csv.parseRows(self.__csv_string, function(data) { + self.__data = data; + cb(); + }); +*/ + +}; + +ScatterMatrix.prototype.render = function () { + var self = this; + + var container = d3.select('#scatterplot_container').append('div') + .attr('class', 'scatter-matrix-container'); + var control = container.append('div') + .attr('class', 'scatter-matrix-control'); + var svg = container.append('div') + .attr('class', 'scatter-matrix-svg') + .html('<em>Loading data...</em>'); + + this.onData(function() { + var data = self.__data; + + // Fetch data and get all string variables + var string_variables = [undefined]; + var numeric_variables = []; + var numeric_variable_values = {}; + + for (k in data[0]) { + if (isNaN(+data[0][k])) { string_variables.push(k); } + else { numeric_variables.push(k); numeric_variable_values[k] = []; } + } + + console.log("data:", data) + + data.forEach(function(d) { + for (var j in numeric_variables) { + var k = numeric_variables[j]; + var value = d[k]; + if (numeric_variable_values[k].indexOf(value) < 0) { + numeric_variable_values[k].push(value); + } + } + }); + + var size_control = control.append('div').attr('class', 'scatter-matrix-size-control'); + var color_control = control.append('div').attr('class', 'scatter-matrix-color-control'); + var filter_control = control.append('div').attr('class', 'scatter-matrix-filter-control'); + var variable_control = control.append('div').attr('class', 'scatter-matrix-variable-control'); + var drill_control = control.append('div').attr('class', 'scatter-matrix-drill-control'); + + // shared control states + var to_include = []; + var color_variable = undefined; + var selected_colors = undefined; + for (var j in numeric_variables) { + var v = numeric_variables[j]; + to_include.push(v); + } + var drill_variables = []; + + function set_filter(variable) { + filter_control.selectAll('*').remove(); + if (variable) { + // Get unique values for this variable + var values = []; + data.forEach(function(d) { + var v = d[variable]; + if (values.indexOf(v) < 0) { values.push(v); } + }); + + selected_colors = []; + for (var j in values) { + var v = values[j]; + selected_colors.push(v); + } + + var filter_li = + filter_control + .append('p').text('Filter by '+variable+': ') + .append('ul') + .selectAll('li') + .data(values) + .enter().append('li'); + + filter_li.append('input') + .attr('type', 'checkbox') + .attr('checked', 'checked') + .on('click', function(d, i) { + var new_selected_colors = []; + for (var j in selected_colors) { + var v = selected_colors[j]; + if (v !== d || this.checked) { new_selected_colors.push(v); } + } + if (this.checked) { new_selected_colors.push(d); } + selected_colors = new_selected_colors; + self.__draw(self.__cell_size, svg, color_variable, selected_colors, to_include, drill_variables); + }); + filter_li.append('label') + .html(function(d) { return d; }); + } + } + + size_a = size_control.append('p').text('Change cell size: '); + size_a.append('a') + .attr('href', '#') + .html('-') + .on('click', function() { + self.__cell_size *= 0.75; + self.__draw(self.__cell_size, svg, color_variable, selected_colors, to_include, drill_variables); + }); + size_a.append('span').html(' '); + size_a.append('a') + .attr('href', '#') + .html('+') + .on('click', function() { + self.__cell_size *= 1.25; + self.__draw(self.__cell_size, svg, color_variable, selected_colors, to_include, drill_variables); + }); + + color_control.append('p').text('Select a variable to color:') + color_control + .append('ul') + .selectAll('li') + .data(string_variables) + .enter().append('li') + .append('a') + .attr('href', '#') + .text(function(d) { return d ? d : 'None'; }) + .on('click', function(d, i) { + color_variable = d; + selected_colors = undefined; + self.__draw(self.__cell_size, svg, color_variable, selected_colors, to_include, drill_variables); + set_filter(d); + }); + + var variable_li = + variable_control + .append('p').text('Include variables: ') + .append('ul') + .selectAll('li') + .data(numeric_variables) + .enter().append('li'); + + variable_li.append('input') + .attr('type', 'checkbox') + .attr('checked', 'checked') + .on('click', function(d, i) { + var new_to_include = []; + for (var j in to_include) { + var v = to_include[j]; + if (v !== d || this.checked) { new_to_include.push(v); } + } + if (this.checked) { new_to_include.push(d); } + to_include = new_to_include; + self.__draw(self.__cell_size, svg, color_variable, selected_colors, to_include, drill_variables); + }); + variable_li.append('label') + .html(function(d) { return d; }); + + drill_li = + drill_control + .append('p').text('Drill and Expand: ') + .append('ul') + .selectAll('li') + .data(numeric_variables) + .enter().append('li'); + + drill_li.append('input') + .attr('type', 'checkbox') + .on('click', function(d, i) { + var new_drill_variables = []; + for (var j in drill_variables) { + var v = drill_variables[j]; + if (v !== d || this.checked) { new_drill_variables.push(v); } + } + if (this.checked) { new_drill_variables.push(d); } + drill_variables = new_drill_variables; + self.__draw(self.__cell_size, svg, color_variable, selected_colors, to_include, drill_variables); + }); + drill_li.append('label') + .html(function(d) { return d+' ('+numeric_variable_values[d].length+')'; }); + + self.__draw(self.__cell_size, svg, color_variable, selected_colors, to_include, drill_variables); + }); +}; + +ScatterMatrix.prototype.__draw = + function(cell_size, container_el, color_variable, selected_colors, to_include, drill_variables) { + var self = this; + this.onData(function() { + var data = self.__data; + + if (color_variable && selected_colors) { + data = []; + self.__data.forEach(function(d) { + if (selected_colors.indexOf(d[color_variable]) >= 0) { data.push(d); } + }); + } + + container_el.selectAll('*').remove(); + + // If no data, don't do anything + if (data.length == 0) { return; } + + // Parse headers from first row of data + var numeric_variables = []; + for (k in data[0]) { + if (!isNaN(+data[0][k]) && to_include.indexOf(k) >= 0) { numeric_variables.push(k); } + } + numeric_variables.sort(); + + // Get values of the string variable + var colors = []; + if (color_variable) { + // Using self.__data, instead of data, so our css classes are consistent when + // we filter by value. + self.__data.forEach(function(d) { + var s = d[color_variable]; + if (colors.indexOf(s) < 0) { colors.push(s); } + }); + } + + function color_class(d) { + var c = d; + if (color_variable && d[color_variable]) { c = d[color_variable]; } + return colors.length > 0 ? 'color-'+colors.indexOf(c) : 'color-2'; + } + + // Size parameters + var size = cell_size, padding = 10, + axis_width = 20, axis_height = 15, legend_width = 200, label_height = 15; + + // Get x and y scales for each numeric variable + var x = {}, y = {}; + numeric_variables.forEach(function(trait) { + // Coerce values to numbers. + data.forEach(function(d) { d[trait] = +d[trait]; }); + + var value = function(d) { return d[trait]; }, + domain = [d3.min(data, value), d3.max(data, value)], + range_x = [padding / 2, size - padding / 2], + range_y = [padding / 2, size - padding / 2]; + + x[trait] = d3.scale.linear().domain(domain).range(range_x); + y[trait] = d3.scale.linear().domain(domain).range(range_y.reverse()); + }); + + // When drilling, user select one or more variables. The first drilled + // variable becomes the x-axis variable for all columns, and each column + // contains only data points that match specific values for each of the + // drilled variables other than the first. + + var drill_values = []; + var drill_degrees = [] + drill_variables.forEach(function(variable) { + // Skip first one, since that's just the x axis + if (drill_values.length == 0) { + drill_values.push([]); + drill_degrees.push(1); + } + else { + var values = []; + data.forEach(function(d) { + var v = d[variable]; + if (v !== undefined && values.indexOf(v) < 0) { values.push(v); } + }); + values.sort(); + drill_values.push(values); + drill_degrees.push(values.length); + } + }); + var total_columns = 1; + drill_degrees.forEach(function(d) { total_columns *= d; }); + + // Pick out stuff to draw on horizontal and vertical dimensions + + if (drill_variables.length > 0) { + // First drill is now the x-axis variable for all columns + x_variables = []; + for (var i=0; i<total_columns; i++) { + x_variables.push(drill_variables[0]); + } + } + else { + x_variables = numeric_variables.slice(0); + } + + if (drill_variables.length > 0) { + // Don't draw any of the "drilled" variables in vertical dimension + y_variables = []; + numeric_variables.forEach(function(variable) { + if (drill_variables.indexOf(variable) < 0) { y_variables.push(variable); } + }); + } + else { + y_variables = numeric_variables.slice(0); + } + + var filter_descriptions = 0; + if (drill_variables.length > 1) { + filter_descriptions = drill_variables.length-1; + } + + // Axes + var x_axis = d3.svg.axis(); + var y_axis = d3.svg.axis(); + var intf = d3.format('d'); + var fltf = d3.format('.f'); + var scif = d3.format('e'); + + x_axis.ticks(5) + .tickSize(size * y_variables.length) + .tickFormat(function(d) { + if (Math.abs(+d) > 10000 || (Math.abs(d) < 0.001 && Math.abs(d) != 0)) { return scif(d); } + if (parseInt(d) == +d) { return intf(d); } + return fltf(d); + }); + + y_axis.ticks(5) + .tickSize(size * x_variables.length) + .tickFormat(function(d) { + if (Math.abs(+d) > 10000 || (Math.abs(d) < 0.001 && Math.abs(d) != 0)) { return scif(d); } + if (parseInt(d) == +d) { return intf(d); } + return fltf(d); + }); + + // Brush - for highlighting regions of data + var brush = d3.svg.brush() + .on("brushstart", brushstart) + .on("brush", brush) + .on("brushend", brushend); + + // Root panel + var svg = container_el.append("svg:svg") + .attr("width", label_height + size * x_variables.length + axis_width + padding + legend_width) + .attr("height", size * y_variables.length + axis_height + label_height + label_height*filter_descriptions) + .append("svg:g") + .attr("transform", "translate("+label_height+",0)"); + + // Push legend to the side + var legend = svg.selectAll("g.legend") + .data(colors) + .enter().append("svg:g") + .attr("class", "legend") + .attr("transform", function(d, i) { + return "translate(" + (label_height + size * x_variables.length + padding) + "," + (i*20+10) + ")"; + }); + + legend.append("svg:circle") + .attr("class", function(d, i) { return color_class(d); }) + .attr("r", 3); + + legend.append("svg:text") + .attr("x", 12) + .attr("dy", ".31em") + .text(function(d) { return d; }); + + // Draw X-axis + svg.selectAll("g.x.axis") + .data(x_variables) + .enter().append("svg:g") + .attr("class", "x axis") + .attr("transform", function(d, i) { return "translate(" + i * size + ",0)"; }) + .each(function(d) { d3.select(this).call(x_axis.scale(x[d]).orient("bottom")); }); + + // Draw Y-axis + svg.selectAll("g.y.axis") + .data(y_variables) + .enter().append("svg:g") + .attr("class", "y axis") + .attr("transform", function(d, i) { return "translate(0," + i * size + ")"; }) + .each(function(d) { d3.select(this).call(y_axis.scale(y[d]).orient("right")); }); + + // Draw scatter plot + var cell = svg.selectAll("g.cell") + .data(cross(x_variables, y_variables)) + .enter().append("svg:g") + .attr("class", "cell") + .attr("transform", function(d) { return "translate(" + d.i * size + "," + d.j * size + ")"; }) + .each(plot); + + // Add titles for y variables + cell.filter(function(d) { return d.i == 0; }).append("svg:text") + .attr("x", padding-size) + .attr("y", -label_height) + .attr("dy", ".71em") + .attr("transform", function(d) { return "rotate(-90)"; }) + .text(function(d) { return d.y; }); + + function plot(p) { + // console.log(p); + + var data_to_draw = data; + + // If drilling, compute what values of the drill variables correspond to + // this column. + // + var filter = {}; + if (drill_variables.length > 1) { + var column = p.i; + + var cap = 1; + for (var i=drill_variables.length-1; i > 0; i--) { + var var_name = drill_variables[i]; + var var_value = undefined; + + if (i == drill_variables.length-1) { + // for the last drill variable, we index by % + var_value = drill_values[i][column % drill_degrees[i]]; + } + else { + // otherwise divide by capacity of subsequent variables to get value array index + var_value = drill_values[i][parseInt(column/cap)]; + } + + filter[var_name] = var_value; + cap *= drill_degrees[i]; + } + + data_to_draw = []; + data.forEach(function(d) { + var pass = true; + for (k in filter) { if (d[k] != filter[k]) { pass = false; break; } } + if (pass === true) { data_to_draw.push(d); } + }); + } + + var cell = d3.select(this); + + // Frame + cell.append("svg:rect") + .attr("class", "frame") + .attr("x", padding / 2) + .attr("y", padding / 2) + .attr("width", size - padding) + .attr("height", size - padding); + + // Scatter plot dots + cell.selectAll("circle") + .data(data_to_draw) + .enter().append("svg:circle") + .attr("class", function(d) { return color_class(d); }) + .attr("cx", function(d) { return x[p.x](d[p.x]); }) + .attr("cy", function(d) { return y[p.y](d[p.y]); }) + .attr("r", 5); + + // Add titles for x variables and drill variable values + if (p.j == y_variables.length-1) { + cell.append("svg:text") + .attr("x", padding) + .attr("y", size+axis_height) + .attr("dy", ".71em") + .text(function(d) { return d.x; }); + + if (drill_variables.length > 1) { + var i = 0; + for (k in filter) { + i += 1; + cell.append("svg:text") + .attr("x", padding) + .attr("y", size+axis_height+label_height*i) + .attr("dy", ".71em") + .text(function(d) { return filter[k]+': '+k; }); + } + } + } + + // Brush + cell.call(brush.x(x[p.x]).y(y[p.y])); + } + + // Clear the previously-active brush, if any + function brushstart(p) { + if (brush.data !== p) { + cell.call(brush.clear()); + brush.x(x[p.x]).y(y[p.y]).data = p; + } + } + + // Highlight selected circles + function brush(p) { + var e = brush.extent(); + svg.selectAll(".cell circle").attr("class", function(d) { + return e[0][0] <= d[p.x] && d[p.x] <= e[1][0] + && e[0][1] <= d[p.y] && d[p.y] <= e[1][1] + ? color_class(d) : null; + }); + } + + // If brush is empty, select all circles + function brushend() { + if (brush.empty()) svg.selectAll(".cell circle").attr("class", function(d) { + return color_class(d); + }); + } + + function cross(a, b) { + var c = [], n = a.length, m = b.length, i, j; + for (i = -1; ++i < n;) for (j = -1; ++j < m;) c.push({x: a[i], i: i, y: b[j], j: j}); + return c; + } + }); + +}; + diff --git a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee index 8b73b85d..fdec0ee4 100755 --- a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee +++ b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee @@ -67,15 +67,24 @@ do_ajax_post = (url, form_data) -> success: (data) => clearInterval(this.my_timer) $('#progress_bar_container').modal('hide') - $("body").html(data) + open_mapping_results(data) + #$("body").html(data) ) console.log("settingInterval") this.my_timer = setInterval(get_progress, 1000) return false +open_mapping_results = (data) -> + $.colorbox( + html: data + href: "#mapping_results_holder" + height: "80%" + width: "80%" + ) + showalert = (message,alerttype) -> - $('#alert_placeholder').append('<div id="alertdiv" class="alert ' + alerttype + '"><a class="close" data-dismiss="alert">×</a><span>'+message+'</span></div>') + $('#alert_placeholder').append('<div id="alertdiv" class="alert ' + alerttype + '"><a class="close" data-dismiss="alert">×</a><span>'+message+'</span></div>') $("#interval_mapping_compute").click(() => @@ -95,32 +104,6 @@ $("#interval_mapping_compute").click(() => console.log("form_data is:", form_data) do_ajax_post(url, form_data) - - #remove_outliers = confirm("Remove outliers?") - #if use_outliers == true - # block_outliers() - # do_ajax_post(url, form_data) - #else - # do_ajax_post(url, form_data) - #$.ajax( - # type: "POST" - # url: url - # data: form_data - # error: (xhr, ajaxOptions, thrownError) => - # alert("Sorry, an error occurred") - # console.log(xhr) - # clearInterval(this.my_timer) - # $('#progress_bar_container').modal('hide') - # $("body").html("We got an error.") - # success: (data) => - # clearInterval(this.my_timer) - # $('#progress_bar_container').modal('hide') - # $("body").html(data) - #) - #console.log("settingInterval") - # - #this.my_timer = setInterval(get_progress, 1000) - #return false ) $('#suggestive').hide() @@ -146,26 +129,6 @@ $("#pylmm_compute").click(() => #if use_outliers == true # block_outliers() do_ajax_post(url, form_data) - - #$.ajax( - # type: "POST" - # url: url - # data: form_data - # error: (xhr, ajaxOptions, thrownError) => - # alert("Sorry, an error occurred") - # console.log(xhr) - # clearInterval(this.my_timer) - # $('#progress_bar_container').modal('hide') - # $("body").html("We got an error.") - # success: (data) => - # clearInterval(this.my_timer) - # $('#progress_bar_container').modal('hide') - # $("body").html(data) - #) - #console.log("settingInterval") - # - #this.my_timer = setInterval(get_progress, 1000) - #return false ) @@ -184,26 +147,6 @@ $("#rqtl_geno_compute").click(() => #if use_outliers == true # block_outliers() do_ajax_post(url, form_data) - - #$.ajax( - # type: "POST" - # url: url - # data: form_data - # error: (xhr, ajaxOptions, thrownError) => - # alert("Sorry, an error occurred") - # console.log(xhr) - # clearInterval(this.my_timer) - # $('#progress_bar_container').modal('hide') - # $("body").html("We got an error.") - # success: (data) => - # clearInterval(this.my_timer) - # $('#progress_bar_container').modal('hide') - # $("body").html(data) - #) - #console.log("settingInterval") - # - #this.my_timer = setInterval(get_progress, 1000) - #return false ) @@ -218,26 +161,6 @@ $("#plink_compute").click(() => console.log("form_data is:", form_data) do_ajax_post(url, form_data) - - #$.ajax( - # type: "POST" - # url: url - # data: form_data - # error: (xhr, ajaxOptions, thrownError) => - # alert("Sorry, an error occurred") - # console.log(xhr) - # clearInterval(this.my_timer) - # $('#static_progress_bar_container').modal('hide') - # $("body").html("We got an error.") - # success: (data) => - # clearInterval(this.my_timer) - # $('#static_progress_bar_container').modal('hide') - # $("body").html(data) - #) - #console.log("settingInterval") - # - #this.my_timer = setInterval(get_progress, 1000) - #return false ) $("#gemma_compute").click(() => @@ -251,26 +174,6 @@ $("#gemma_compute").click(() => console.log("form_data is:", form_data) do_ajax_post(url, form_data) - - #$.ajax( - # type: "POST" - # url: url - # data: form_data - # error: (xhr, ajaxOptions, thrownError) => - # alert("Sorry, an error occurred") - # console.log(xhr) - # clearInterval(this.my_timer) - # $('#static_progress_bar_container').modal('hide') - # $("body").html("We got an error.") - # success: (data) => - # clearInterval(this.my_timer) - # $('#static_progress_bar_container').modal('hide') - # $("body").html(data) - #) - #console.log("settingInterval") - # - #this.my_timer = setInterval(get_progress, 1000) - #return false ) #$(".submit_special").click(submit_special) diff --git a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js index 92d3183a..c8988cdc 100755 --- a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js +++ b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js @@ -1,5 +1,5 @@ // Generated by CoffeeScript 1.8.0 -var block_outliers, composite_mapping_fields, do_ajax_post, get_progress, mapping_method_fields, showalert, submit_special, toggle_enable_disable, update_time_remaining; +var block_outliers, composite_mapping_fields, do_ajax_post, get_progress, mapping_method_fields, open_mapping_results, showalert, submit_special, toggle_enable_disable, update_time_remaining; submit_special = function() { var url; @@ -86,7 +86,7 @@ do_ajax_post = function(url, form_data) { return function(data) { clearInterval(_this.my_timer); $('#progress_bar_container').modal('hide'); - return $("body").html(data); + return open_mapping_results(data); }; })(this) }); @@ -95,6 +95,15 @@ do_ajax_post = function(url, form_data) { return false; }; +open_mapping_results = function(data) { + return $.colorbox({ + html: data, + href: "#mapping_results_holder", + height: "80%", + width: "80%" + }); +}; + showalert = function(message, alerttype) { return $('#alert_placeholder').append('<div id="alertdiv" class="alert ' + alerttype + '"><a class="close" data-dismiss="alert">�</a><span>' + message + '</span></div>'); }; diff --git a/wqflask/wqflask/static/packages/bootstrap/css/bootstrap.css b/wqflask/wqflask/static/packages/bootstrap/css/bootstrap.css index 3dc73a7a..8326e83f 100755 --- a/wqflask/wqflask/static/packages/bootstrap/css/bootstrap.css +++ b/wqflask/wqflask/static/packages/bootstrap/css/bootstrap.css @@ -1414,6 +1414,7 @@ pre code { margin-right: auto; margin-left: auto; } + .row { margin-right: -15px; margin-left: -15px; @@ -2763,13 +2764,13 @@ select[multiple].form-group-lg .form-control { margin-right: -15px; margin-left: -15px; } -@media (min-width: 768px) { - .form-horizontal .control-label { - padding-top: 7px; - margin-bottom: 0; - text-align: right; - } + +.form-horizontal .control-label { + padding-top: 7px; + margin-bottom: 0; + text-align: right; } + .form-horizontal .has-feedback .form-control-feedback { right: 15px; } @@ -3760,7 +3761,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { top: auto; left: auto; } -@media (min-width: 768px) { + .nav-tabs.nav-justified > li { display: table-cell; width: 1%; @@ -3768,7 +3769,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .nav-tabs.nav-justified > li > a { margin-bottom: 0; } -} + .nav-tabs.nav-justified > li > a { margin-right: 0; border-radius: 4px; @@ -3778,7 +3779,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .nav-tabs.nav-justified > .active > a:focus { border: 1px solid #ddd; } -@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { border-bottom: 1px solid #ddd; border-radius: 4px 4px 0 0; @@ -3788,7 +3789,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .nav-tabs.nav-justified > .active > a:focus { border-bottom-color: #fff; } -} + .nav-pills > li { float: left; } @@ -3825,7 +3826,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { top: auto; left: auto; } -@media (min-width: 768px) { + .nav-justified > li { display: table-cell; width: 1%; @@ -3833,7 +3834,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .nav-justified > li > a { margin-bottom: 0; } -} + .nav-tabs-justified { border-bottom: 0; } @@ -3846,7 +3847,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .nav-tabs-justified > .active > a:focus { border: 1px solid #ddd; } -@media (min-width: 768px) { + .nav-tabs-justified > li > a { border-bottom: 1px solid #ddd; border-radius: 4px 4px 0 0; @@ -3856,7 +3857,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .nav-tabs-justified > .active > a:focus { border-bottom-color: #fff; } -} + .tab-content > .tab-pane { display: none; visibility: hidden; @@ -4079,7 +4080,7 @@ float: right!important; background-image: none; } } -@media (min-width: 768px) { + .navbar-nav { float: left; margin: 0; @@ -4091,7 +4092,7 @@ float: right!important; padding-top: 15px; padding-bottom: 15px; } -} + .navbar-form { padding: 10px 15px; margin-top: 8px; @@ -4200,25 +4201,25 @@ float: right!important; margin-top: 15px; margin-bottom: 15px; } -@media (min-width: 768px) { - .navbar-text { - float: left; - margin-right: 15px; - margin-left: 15px; - } + +.navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px; } -@media (min-width: 768px) { - .navbar-left { - float: left !important; - } - .navbar-right { - float: right !important; - margin-right: -15px; - } - .navbar-right ~ .navbar-right { - margin-right: 0; - } + + +.navbar-left { + float: left !important; +} +.navbar-right { + float: right !important; + margin-right: -15px; } +.navbar-right ~ .navbar-right { + margin-right: 0; +} + .navbar-default { background-color: #f8f8f8; border-color: #e7e7e7; @@ -6061,6 +6062,7 @@ button.close { .carousel-caption .btn { text-shadow: none; } +/* @media screen and (min-width: 768px) { .carousel-control .glyphicon-chevron-left, .carousel-control .glyphicon-chevron-right, @@ -6088,6 +6090,7 @@ button.close { bottom: 20px; } } +*/ .clearfix:before, .clearfix:after, .dl-horizontal dd:before, @@ -6195,6 +6198,7 @@ button.close { .visible-lg-inline-block { display: none !important; } +/* @media (max-width: 767px) { .visible-xs { display: block !important; @@ -6353,6 +6357,7 @@ button.close { display: table-cell !important; } } +*/ .visible-print-block { display: none !important; } diff --git a/wqflask/wqflask/templates/collections/view.html b/wqflask/wqflask/templates/collections/view.html index 3d777866..fc1edf2a 100755 --- a/wqflask/wqflask/templates/collections/view.html +++ b/wqflask/wqflask/templates/collections/view.html @@ -69,9 +69,9 @@ <th>Description</th> <th>Location</th> <th>Mean</th> - <th>Max LRS</th> + <th>Max LRS<a href="http://genenetwork.org//glossary.html#L" target="_blank"><sup style="color:#f00"> ?</sup></a></th> <th>Max LRS Location</th> - <th>Additive Effect</th> + <th>Additive Effect<a href="http://genenetwork.org//glossary.html#A" target="_blank"><sup style="color:#f00"> ?</sup></a></th> </tr> </thead> @@ -119,6 +119,13 @@ <script language="javascript" type="text/javascript" src="/static/packages/TableTools/media/js/TableTools.min.js"></script> <script language="javascript" type="text/javascript"> $(document).ready( function () { + + $('#trait_table tr').click(function(event) { + if (event.target.type !== 'checkbox') { + $(':checkbox', this).trigger('click'); + } + }); + console.time("Creating table"); $('#trait_table').dataTable( { "aoColumns": [ @@ -130,7 +137,7 @@ "sWidth": "15%" }, { "sType": "cust-txt" }, { "sType": "natural", - "sWidth": "10%" }, + "sWidth": "12%" }, { "sType": "natural", "sWidth": "15%" }, { "sType": "cust-txt" } @@ -143,7 +150,7 @@ null, null ], - "sDom": "ftir", + "sDom": "tir", "iDisplayLength": -1, "autoWidth": true, "bLengthChange": true, diff --git a/wqflask/wqflask/templates/index_page.html b/wqflask/wqflask/templates/index_page.html index adc004a5..eb4f883c 100755 --- a/wqflask/wqflask/templates/index_page.html +++ b/wqflask/wqflask/templates/index_page.html @@ -65,7 +65,7 @@ <!-- GET ANY SEARCH --> <div class="form-group"> - <label for="tfor" class="col-xs-1 control-label" style="width: 65px !important;">Search:</label> + <label for="tfor" class="col-xs-1 control-label" style="width: 65px !important;">Search for:</label> <div class="col-xs-10 controls"> <textarea name="search_terms" rows="2" class="form-control search-query" style="width: 450px !important;" id="tfor"></textarea> </div> @@ -93,7 +93,7 @@ <input id="btsearch" type="submit" class="btn btn-primary form-control" value="Search"> </div> <div class="col-xs-4 controls" style="width: 150px !important;"> - <input id="make_default" type="submit" class="btn btn-default form-control" value="Make Default"> + <input id="make_default" class="btn btn-default form-control" value="Make Default"> </div> </div> @@ -103,11 +103,9 @@ </fieldset> </form> </section> - </div> - <div style="padding-left:120px" class="col-xs-6" style="width: 600px !important;"> <section id="advanced"> <div class="page-header"> - <h1>Advanced commands</h1> + <h2>Advanced commands</h2> </div> <p>GeneNetwork supports a variety of advanced searches.</p> @@ -148,6 +146,8 @@ scores between 9 and 999.</li>--> </ul> </section> + </div> + <div style="padding-left:120px" class="col-xs-6" style="width: 600px !important;"> <!-- <section id="tour-info"> <div class="page-header"> diff --git a/wqflask/wqflask/templates/interval_mapping.html b/wqflask/wqflask/templates/interval_mapping.html index 7a03ce34..82a96ba1 100755 --- a/wqflask/wqflask/templates/interval_mapping.html +++ b/wqflask/wqflask/templates/interval_mapping.html @@ -1,120 +1,116 @@ -{% extends "base.html" %}
-{% block title %}Interval Mapping{% endblock %}
-{% block css %}
-<!-- <link rel="stylesheet" type="text/css" href="/static/new/css/interval_mapping.css" />-->
- <link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/css/jquery.dataTables.css" />
- <link rel="stylesheet" type="text/css" href="/static/packages/DT_bootstrap/DT_bootstrap.css" />
- <link rel="stylesheet" type="text/css" href="/static/packages/TableTools/media/css/TableTools.css" />
- <link rel="stylesheet" type="text/css" href="/static/new/css/d3-tip.min.css" />
- <link rel="stylesheet" type="text/css" href="/static/new/css/panelutil.css" />
-{% endblock %}
-{% block content %} <!-- Start of body -->
-
- {{ header("Mapping",
- '{}: {}'.format(this_trait.name, this_trait.description_fmt)) }}
-
- <div class="container">
- <div>
- <h2>
- Whole Genome Mapping
- </h2>
- <form style ='float: left; padding: 5px;' id="exportform" action="export" method="post">
- <input type="hidden" id="data" name="data" value="">
- <input type="hidden" id="filename" name="filename" value="">
- <input type="submit" id="export" value="Download SVG">
- </form>
- <form style ='float: left; padding: 5px;' id="exportpdfform" action="export_pdf" method="post">
- <input type="hidden" id="data" name="data" value="">
- <input type="hidden" id="filename" name="filename" value="">
- <input type="submit" id="export_pdf" value="Download PDF">
- </form>
- </div>
- <div id="chart_container">
- <div class="qtlcharts" id="topchart">
-
- </div>
- </div>
- <div>
- <h2>
- Results
- </h2>
- </div>
- <table cellpadding="0" cellspacing="0" border="0" id="qtl_results" class="table table-hover table-striped table-bordered">
- <thead>
- <tr>
- <td>Index</td>
- <td>LRS Score</td>
- <td>Chr</td>
- <td>Mb</td>
- <td>Locus</td>
- <td>Additive Effect</td>
- </tr>
- </thead>
- <tbody>
- {% for marker in qtl_results %}
- <tr>
- <td>{{ loop.index }}</td>
- <td>{{ marker.lrs_value|float }}</td>
- <td>{{ marker.chr|int }}</td>
- <td>{{ marker.Mb|float }}</td>
- <td>{{ marker.name }}</td>
- <td>{{ marker.additive|float }}</td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
-
- </div>
-
- <!-- End of body -->
-
-{% endblock %}
-
-{% block js %}
- <script>
- js_data = {{ js_data | safe }}
- </script>
-
- <!--[if lt IE 9]>
-<!-- <script language="javascript" type="text/javascript" src="/static/packages/jqplot/excanvas.js"></script>-->
- <![endif]-->
- <script language="javascript" type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
- <script language="javascript" type="text/javascript" src="/static/new/js_external/d3-tip.min.js"></script>
- <script language="javascript" type="text/javascript" src="/static/new/javascript/panelutil.js"></script>
- <script language="javascript" type="text/javascript" src="/static/new/javascript/chr_interval_map.js"></script>
- <script language="javascript" type="text/javascript" src="/static/new/javascript/lod_chart.js"></script>
- <script language="javascript" type="text/javascript" src="/static/new/javascript/create_lodchart.js"></script>
- <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.js"></script>
- <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.dataTables.min.js"></script>
- <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/dataTables.scientific.js"></script>
- <script language="javascript" type="text/javascript" src="/static/packages/DT_bootstrap/DT_bootstrap.js"></script>
- <script language="javascript" type="text/javascript" src="/static/packages/TableTools/media/js/TableTools.min.js"></script>
- <script language="javascript" type="text/javascript" src="/static/packages/underscore/underscore-min.js"></script>
-
- <script type="text/javascript" charset="utf-8">
- $(document).ready( function () {
- console.time("Creating table");
- $('#qtl_results').dataTable( {
- //"sDom": "<<'span3'l><'span3'T><'span4'f>'row-fluid'r>t<'row-fluid'<'span6'i><'span6'p>>",
- "sDom": "lTftipr",
- "oTableTools": {
- "aButtons": [
- "copy",
- "print",
- {
- "sExtends": "collection",
- "sButtonText": 'Save <span class="caret" />',
- "aButtons": [ "csv", "xls", "pdf" ]
- }
- ],
- "sSwfPath": "/static/packages/TableTools/media/swf/copy_csv_xls_pdf.swf"
- },
- "iDisplayLength": 50,
- "bLengthChange": true,
- "bDeferRender": true,
- "bSortClasses": false
- } );
- console.timeEnd("Creating table");
- });
- </script>
+{% block css %} +<!-- <link rel="stylesheet" type="text/css" href="/static/new/css/interval_mapping.css" />--> + <link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/css/jquery.dataTables.css" /> + <link rel="stylesheet" type="text/css" href="/static/packages/DT_bootstrap/DT_bootstrap.css" /> + <link rel="stylesheet" type="text/css" href="/static/packages/TableTools/media/css/TableTools.css" /> + <link rel="stylesheet" type="text/css" href="/static/new/css/d3-tip.min.css" /> + <link rel="stylesheet" type="text/css" href="/static/new/css/panelutil.css" /> +{% endblock %} +{% block content %} <!-- Start of body --> + + + <div id="mapping_results" class="container"> + <div> + <h2> + Whole Genome Mapping + </h2> + <form style ='float: left; padding: 5px;' id="exportform" action="export" method="post"> + <input type="hidden" id="data" name="data" value=""> + <input type="hidden" id="filename" name="filename" value=""> + <input type="submit" id="export" value="Download SVG"> + </form> + <form style ='float: left; padding: 5px;' id="exportpdfform" action="export_pdf" method="post"> + <input type="hidden" id="data" name="data" value=""> + <input type="hidden" id="filename" name="filename" value=""> + <input type="submit" id="export_pdf" value="Download PDF"> + </form> + </div> + <div id="chart_container"> + <div class="qtlcharts" id="topchart"> + + </div> + </div> + <div> + <h2> + Results + </h2> + </div> + <table cellpadding="0" cellspacing="0" border="0" id="qtl_results" class="table table-hover table-striped table-bordered"> + <thead> + <tr> + <td>Index</td> + <td>LRS Score</td> + <td>Chr</td> + <td>Mb</td> + <td>Locus</td> + <td>Additive Effect</td> + </tr> + </thead> + <tbody> + {% for marker in qtl_results %} + <tr> + <td>{{ loop.index }}</td> + <td>{{ marker.lrs_value|float }}</td> + <td>{{ marker.chr|int }}</td> + <td>{{ marker.Mb|float }}</td> + <td>{{ marker.name }}</td> + <td>{{ marker.additive|float }}</td> + </tr> + {% endfor %} + </tbody> + </table> + + </div> + + <!-- End of body --> + +{% endblock %} + +{% block js %} + <script> + js_data = {{ js_data | safe }} + </script> + + <!--[if lt IE 9]> +<!-- <script language="javascript" type="text/javascript" src="/static/packages/jqplot/excanvas.js"></script>--> + <![endif]--> + <script language="javascript" type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script> + <script language="javascript" type="text/javascript" src="/static/new/js_external/d3-tip.min.js"></script> + <script language="javascript" type="text/javascript" src="/static/new/javascript/panelutil.js"></script> + <script language="javascript" type="text/javascript" src="/static/new/javascript/chr_interval_map.js"></script> + <script language="javascript" type="text/javascript" src="/static/new/javascript/lod_chart.js"></script> + <script language="javascript" type="text/javascript" src="/static/new/javascript/create_lodchart.js"></script> + <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.js"></script> + <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.dataTables.min.js"></script> + <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/dataTables.scientific.js"></script> + <script language="javascript" type="text/javascript" src="/static/packages/DT_bootstrap/DT_bootstrap.js"></script> + <script language="javascript" type="text/javascript" src="/static/packages/TableTools/media/js/TableTools.min.js"></script> + <script language="javascript" type="text/javascript" src="/static/packages/underscore/underscore-min.js"></script> + + <script type="text/javascript" charset="utf-8"> + $(document).ready( function () { + console.time("Creating table"); + $('#qtl_results').dataTable( { + //"sDom": "<<'span3'l><'span3'T><'span4'f>'row-fluid'r>t<'row-fluid'<'span6'i><'span6'p>>", + "sDom": "lTftipr", + "oTableTools": { + "aButtons": [ + "copy", + "print", + { + "sExtends": "collection", + "sButtonText": 'Save <span class="caret" />', + "aButtons": [ "csv", "xls", "pdf" ] + } + ], + "sSwfPath": "/static/packages/TableTools/media/swf/copy_csv_xls_pdf.swf" + }, + "iDisplayLength": 50, + "bLengthChange": true, + "bDeferRender": true, + "bSortClasses": false + } ); + console.timeEnd("Creating table"); + }); + </script> {% endblock %}
\ No newline at end of file diff --git a/wqflask/wqflask/templates/new_security/login_user.html b/wqflask/wqflask/templates/new_security/login_user.html index ecf8278c..8ad0c79e 100755 --- a/wqflask/wqflask/templates/new_security/login_user.html +++ b/wqflask/wqflask/templates/new_security/login_user.html @@ -3,6 +3,9 @@ {% block content %} <div class="container"> + + {{ flash_me() }} + <div class="page-header"> <h1>Login</h1> </div> @@ -24,15 +27,15 @@ <form class="form-horizontal" action="/n/login" method="POST" name="login_user_form"> <fieldset> <div class="form-group"> - <label class="col-xs-2 control-label" for="email_address">Email Address</label> - <div class="col-xs-10"> + <label style="text-align:left;" class="col-xs-1 control-label" for="email_address">Email Address</label> + <div style="margin-left:20px;" class="col-xs-10"> <input id="email_address" class="focused" name="email_address" type="text" value=""> </div> </div> <div class="form-group"> - <label class="col-xs-2 control-label" for="password">Password</label> - <div class="col-xs-3 controls"> + <label style="text-align:left;" class="col-xs-1 control-label" for="password">Password</label> + <div style="margin-left:20px;" class="col-xs-3 controls"> <input id="password" name="password" type="password" value=""> <br /> <a href="/n/forgot_password">Forgot your password?</a><br/> @@ -41,17 +44,15 @@ <div class="form-group"> - <label class="col-xs-2 control-label" for="remember"></label> - <div class="col-xs-3 controls"> - <label class="checkbox"> - <input id="remember" name="remember" type="checkbox" value="y"> Remember me - </label> + <label class="col-xs-1 control-label" for="remember"></label> + <div style="margin-left:20px;" class="col-xs-3 controls"> + <input id="remember" name="remember" type="checkbox" value="y"> <b>Remember me</b> </div> </div> <div class="form-group"> - <label class="col-xs-2 control-label" for="submit"></label> - <div class="col-xs-3 controls"> + <label class="col-xs-1 control-label" for="submit"></label> + <div style="margin-left:20px;" class="col-xs-3 controls"> <input id="next" name="next" type="hidden" value=""> <input class="btn btn-primary" id="submit" name="submit" type="submit" value="Sign in"> </div> diff --git a/wqflask/wqflask/templates/search_result_page.html b/wqflask/wqflask/templates/search_result_page.html index 055ab979..731f6fbd 100755 --- a/wqflask/wqflask/templates/search_result_page.html +++ b/wqflask/wqflask/templates/search_result_page.html @@ -49,7 +49,13 @@ <thead> <tr> {% for header in header_fields %} + {% if header == 'Max LRS' %} + <th>{{header}}<a href="http://genenetwork.org//glossary.html#L" target="_blank"><sup style="color:#f00"> ?</sup></a></th> + {% elif header == 'Additive Effect' %} + <th>{{header}}<a href="http://genenetwork.org//glossary.html#A" target="_blank"><sup style="color:#f00"> ?</sup></a></th> + {% else %} <th>{{header}}</th> + {% endif %} {% endfor %} </tr> </thead> @@ -140,17 +146,11 @@ $(document).ready( function () { - /*num_columns = $('#trait_table').find('tr:first th').length; - - nul_cols = [] - for (i=0; i<num_columns - 1, i++) { - $('#trait_table > tbody > tr').each(function() { - if ($(this).find('td:eq(i)').html()){ - continue; - } - }); - nul_cols.push(i) - }*/ + $('#trait_table tr').click(function(event) { + if (event.target.type !== 'checkbox') { + $(':checkbox', this).trigger('click'); + } + }); console.time("Creating table"); {% if dataset.type == 'ProbeSet' %} @@ -166,7 +166,7 @@ "sWidth": "15%" }, { "sType": "cust-txt" }, { "sType": "natural", - "sWidth": "10%" }, + "sWidth": "12%" }, { "sType": "natural", "sWidth": "15%" }, { "sType": "cust-txt" } diff --git a/wqflask/wqflask/templates/show_trait.html b/wqflask/wqflask/templates/show_trait.html index 5d0437df..a1723ef8 100755 --- a/wqflask/wqflask/templates/show_trait.html +++ b/wqflask/wqflask/templates/show_trait.html @@ -6,6 +6,7 @@ <link rel="stylesheet" type="text/css" href="/static/new/css/bar_chart.css" /> <link rel="stylesheet" type="text/css" href="/static/new/css/box_plot.css" /> <link rel="stylesheet" type="text/css" href="/static/new/css/panelutil.css" /> + <link rel="stylesheet" type="text/css" href="/static/new/css/scatter-matrix.css" /> <link rel="stylesheet" type="text/css" href="/static/new/css/d3-tip.min.css" /> <link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/css/jquery.dataTables.css" /> <link rel="stylesheet" type="text/css" href="/static/packages/DT_bootstrap/DT_bootstrap.css" /> @@ -40,7 +41,7 @@ <div class="panel-heading"> <h3 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne"> - Statistics + <span class="glyphicon glyphicon-chevron-down"></span> Statistics </a> </h3> </div> @@ -54,7 +55,7 @@ <div class="panel-heading"> <h3 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo"> - Calculate Correlations + <span class="glyphicon glyphicon-chevron-down"></span> Calculate Correlations </a> </h3> </div> @@ -68,7 +69,7 @@ <div class="panel-heading"> <h3 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseThree"> - Mapping Tools + <span class="glyphicon glyphicon-chevron-down"></span> Mapping Tools </a> </h3> </div> @@ -82,7 +83,7 @@ <div class="panel-heading"> <h3 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="#collapseFour" aria-expanded="true"> - Review and Edit Data + <span class="glyphicon glyphicon-chevron-up"></span> Review and Edit Data </a> </h3> </div> @@ -122,6 +123,7 @@ <script type="text/javascript" src="/static/new/javascript/histogram.js"></script> <script type="text/javascript" src="/static/new/javascript/box_plot.js"></script> <script type="text/javascript" src="/static/new/javascript/scatterplot.js"></script> + <script type="text/javascript" src="/static/new/javascript/scatter-matrix.js"></script> <script type="text/javascript" src="/static/new/javascript/draw_probability_plot.js"></script> <script type="text/javascript" src="/static/new/javascript/compare_traits_scatterplot.js"></script> @@ -162,6 +164,16 @@ }; $(document).ready( function () { + + $('.panel-heading').find('a').click(function () { + if ($(this).hasClass('collapsed')){ + $(this).find('.glyphicon-chevron-down').removeClass('glyphicon-chevron-down').addClass('glyphicon-chevron-up'); + } + else { + $(this).find('.glyphicon-chevron-up').removeClass('glyphicon-chevron-up').addClass('glyphicon-chevron-down'); + } + }); + console.time("Creating table"); {% if sample_groups[0].se_exists() %} diff --git a/wqflask/wqflask/templates/show_trait_mapping_tools.html b/wqflask/wqflask/templates/show_trait_mapping_tools.html index 84ddfd53..6f5fe237 100755 --- a/wqflask/wqflask/templates/show_trait_mapping_tools.html +++ b/wqflask/wqflask/templates/show_trait_mapping_tools.html @@ -1,5 +1,7 @@ <div> + <div class="col-xs-6"> <div class="tabbable"> <!-- Only required for left/right tabs --> + <ul class="nav nav-pills"> <li class="active"> <a href="#interval_mapping" data-toggle="tab">Interval Mapping</a> @@ -27,22 +29,22 @@ <div class="tab-pane active" id="interval_mapping"> <div style="padding: 20px" class="form-horizontal"> <div class="mapping_method_fields form-group"> - <label for="mapping_permutations" class="col-xs-1 control-label">Permutations</label> - <div style="margin-left: 20px;" class="col-xs-2 controls"> + <label for="mapping_permutations" class="col-xs-2 control-label">Permutations</label> + <div style="margin-left: 20px;" class="col-xs-4 controls"> <input name="num_perm_reaper" value="2000" type="text" class="form-control"> </div> </div> <div class="mapping_method_fields form-group"> - <label for="mapping_bootstraps" class="col-xs-1 control-label" title="Bootstrapping Resamples">Bootstrap</label> - <div style="margin-left: 20px;" class="col-xs-2 controls"> + <label for="mapping_bootstraps" class="col-xs-2 control-label" title="Bootstrapping Resamples">Bootstrap</label> + <div style="margin-left: 20px;" class="col-xs-4 controls"> <input name="mapping_bootstraps" value="2000" type="text" class="form-control"> </div> </div> <div class="mapping_method_fields form-group"> - <label class="col-xs-2 control-label">Display Additive Effect</label> - <div class="col-xs-4 controls" id="display_additive_effect"> + <label style="text-align:left;" class="col-xs-12 control-label">Display Additive Effect</label> + <div class="col-xs-12 controls" id="display_additive_effect"> <label class="radio-inline"> <input type="radio" name="display_additive" id="display_additive" value="yes" checked=""> Yes @@ -55,8 +57,8 @@ </div> <div class="mapping_method_fields form-group"> - <label class="col-xs-2 control-label">Manhattan Plot</label> - <div class="col-xs-4 controls"> + <label style="text-align:left;" class="col-xs-12 control-label">Manhattan Plot</label> + <div class="col-xs-12 controls"> <label class="radio-inline"> <input type="radio" name="manhattan_plot_reaper" value="true"> Yes @@ -67,16 +69,14 @@ </label> </div> </div> - </div> - <div class="form-group"> - <label for="interval_mapping_submit" class="col-xs-1 control-label"></label> - <div style="margin-left:35px;" class="col-xs-4 controls"> - <button id="interval_mapping_compute" class="btn submit_special btn-primary" data-url="/interval_mapping" title="Compute Interval Mapping"> - <i class="icon-ok-circle icon-white"></i> Compute - </button> + <div class="form-group"> + <div style="padding-left:15px;" class="controls"> + <button id="interval_mapping_compute" class="btn submit_special btn-primary" data-url="/interval_mapping" title="Compute Interval Mapping"> + <i class="icon-ok-circle icon-white"></i> Open Mapping Tool + </button> + </div> </div> </div> - <div id="alert_placeholder"></div> </div> <div class="tab-pane" id="pylmm"> @@ -119,8 +119,7 @@ </button> </div> </div> - <div id="alert_placeholder"></div> - + </div> <div class="tab-pane" id="rqtl_geno"> @@ -167,7 +166,6 @@ </button> </div> </div> - <div id="alert_placeholder"></div> </div> @@ -190,8 +188,6 @@ </button> </div> </div> - <div id="alert_placeholder"></div> - </div> <div class="tab-pane" id="gemma"> @@ -212,10 +208,23 @@ </button> </div> </div> - <div id="alert_placeholder"></div> - </div> {% endif %} </div> </div> + </div> + <div class="col-xs-6"> + <dl> + <dt>Interval Mapping</dt> + <dd>Interval mapping is a process in which the statistical significance of a hypothetical QTL is evaluated at regular points across a chromosome, even in the absence of explicit genotype data at those points.</dd> + <dt>pyLMM</dt> + <dd>pyLMM is a fast and lightweight linear mixed-model (LMM) solver for use in genome-wide association studies (GWAS).</dd> + <dt>R/qtl</dt> + <dd>R/qtl is an extensible, interactive environment for mapping quantitative trait loci (QTL) in experimental crosses.</dd> + </dl> + </div> + <div id="alert_placeholder"></div> + <div id="mapping_result_holder_wrapper" style="display:none;"> + <div id="mapping_result_holder"></div> + </div> </div>
\ No newline at end of file diff --git a/wqflask/wqflask/templates/show_trait_statistics_new.html b/wqflask/wqflask/templates/show_trait_statistics_new.html index 11f5ba68..9ce60c0b 100755 --- a/wqflask/wqflask/templates/show_trait_statistics_new.html +++ b/wqflask/wqflask/templates/show_trait_statistics_new.html @@ -78,10 +78,28 @@ <i class="icon-tint"></i> Color by Trait </button> </div> - <div id="bar_chart_container"> + </div> + <div class="row" style="height: 0px"> + <div id="bar_chart_legend" style="margin-left: 900px; margin-top:50px; positive: relative;"> + <span id="legend-left"></span> + <span id="legend-colors"> + <!-- + <svg height="10" width="90"> + <rect x="0" width="15" height="10" style="fill: rgb(0, 0, 0);"></rect> + <rect x="15" width="15" height="10" style="fill: rgb(50, 0, 0);"></rect> + <rect x="30" width="15" height="10" style="fill: rgb(100, 0, 0);"></rect> + <rect x="45" width="15" height="10" style="fill: rgb(150, 0, 0);"></rect> + <rect x="60" width="15" height="10" style="fill: rgb(200, 0, 0);"></rect> + <rect x="75" width="15" height="10" style="fill: rgb(255, 0, 0);"></rect> + </svg> + --> + </span> + <span id="legend-right"></span> + </div> + </div> + <div style="margin-left: 20px; margin-right: 20px;" class="row" id="bar_chart_container"> <div id="bar_chart" class="barchart"></div> </div> - </div> </div> <div class="tab-pane" id="probability_plot"> <div id="probability_plot_container"> |