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 | |
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
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"> |