From 41fb705cc57c94276573fd19b50c91c095fe76a9 Mon Sep 17 00:00:00 2001 From: Zachary Sloan Date: Thu, 21 Aug 2014 17:08:38 +0000 Subject: Added the option to display mapping results as either an interval mapping or manhattan plot Fixed a few minor bugs --- wqflask/base/data_set.py | 2 - .../wqflask/interval_mapping/interval_mapping.py | 6 + .../wqflask/marker_regression/marker_regression.py | 25 +- .../static/new/javascript/chr_lod_chart.coffee | 296 +++++++++++++++++++++ .../wqflask/static/new/javascript/chr_lod_chart.js | 274 +++++++++++++++++++ .../new/javascript/chr_manhattan_plot.coffee | 19 +- .../static/new/javascript/chr_manhattan_plot.js | 22 +- .../static/new/javascript/create_lodchart.coffee | 87 ++++++ .../static/new/javascript/create_lodchart.js | 73 +++++ .../wqflask/static/new/javascript/lod_chart.coffee | 73 ++--- wqflask/wqflask/static/new/javascript/lod_chart.js | 42 ++- .../new/javascript/show_trait_mapping_tools.coffee | 3 +- .../new/javascript/show_trait_mapping_tools.js | 2 + wqflask/wqflask/templates/interval_mapping.html | 3 +- wqflask/wqflask/templates/marker_regression.html | 4 +- .../templates/show_trait_mapping_tools.html | 18 +- wqflask/wqflask/views.py | 3 +- 17 files changed, 878 insertions(+), 74 deletions(-) create mode 100644 wqflask/wqflask/static/new/javascript/chr_lod_chart.coffee create mode 100644 wqflask/wqflask/static/new/javascript/chr_lod_chart.js create mode 100644 wqflask/wqflask/static/new/javascript/create_lodchart.coffee create mode 100644 wqflask/wqflask/static/new/javascript/create_lodchart.js (limited to 'wqflask') diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py index 2ffa8767..c2a05c90 100755 --- a/wqflask/base/data_set.py +++ b/wqflask/base/data_set.py @@ -697,8 +697,6 @@ class PhenotypeDataSet(DataSet): else: this_trait.description_display = "" - print("this_trait.description_display is:", this_trait.description_display) - if not this_trait.year.isdigit(): this_trait.pubmed_text = "N/A" diff --git a/wqflask/wqflask/interval_mapping/interval_mapping.py b/wqflask/wqflask/interval_mapping/interval_mapping.py index 1b651411..5eb901f7 100755 --- a/wqflask/wqflask/interval_mapping/interval_mapping.py +++ b/wqflask/wqflask/interval_mapping/interval_mapping.py @@ -82,6 +82,8 @@ class IntervalMapping(object): json.dumps(self.json_data, webqtlConfig.TMPDIR + json_filename) self.js_data = dict( + manhattan_plot = self.manhattan_plot, + additive = self.additive, chromosomes = chromosome_mb_lengths, qtl_results = self.qtl_results, json_data = self.json_data @@ -98,6 +100,10 @@ class IntervalMapping(object): self.num_permutations = int(start_vars['num_perm']) #self.do_bootstrap = start_vars['do_bootstrap'] #self.selected_chr = start_vars['chromosome'] + if start_vars['manhattan_plot'] == "true": + self.manhattan_plot = True + else: + self.manhattan_plot = False if start_vars['display_additive'] == "yes": self.additive = True else: diff --git a/wqflask/wqflask/marker_regression/marker_regression.py b/wqflask/wqflask/marker_regression/marker_regression.py index 539bc995..bb67a3ba 100755 --- a/wqflask/wqflask/marker_regression/marker_regression.py +++ b/wqflask/wqflask/marker_regression/marker_regression.py @@ -60,6 +60,10 @@ class MarkerRegression(object): self.vals.append(value) self.mapping_method = start_vars['method'] + if start_vars['manhattan_plot'] == "true": + self.manhattan_plot = True + else: + self.manhattan_plot = False self.maf = start_vars['maf'] # Minor allele frequency self.suggestive = "" self.significant = "" @@ -73,10 +77,7 @@ class MarkerRegression(object): elif self.mapping_method == "rqtl_geno": self.num_perm = start_vars['num_perm'] self.control = start_vars['control_marker'] - if start_vars['manhattan_plot'] == "true": - self.manhattan_plot = True - else: - self.manhattan_plot = False + print("doing rqtl_geno") qtl_results = self.run_rqtl_geno() print("qtl_results:", qtl_results) @@ -227,8 +228,10 @@ class MarkerRegression(object): def run_rqtl_geno(self): robjects.packages.importr("qtl") robjects.r('the_cross <- read.cross(format="csvr", dir="/home/zas1024/PLINK2RQTL/test", file="BXD.csvr")') - robjects.r('the_cross <- calc.genoprob(the_cross)') - + if self.manhattan_plot: + robjects.r('the_cross <- calc.genoprob(the_cross)') + else: + robjects.r('the_cross <- calc.genoprob(the_cross, step=1, stepwidth="max")') pheno_as_string = "c(" #for i, val in enumerate(self.vals): # if val == "x": @@ -295,23 +298,23 @@ class MarkerRegression(object): robjects.r('covariates <- cbind( '+ control_string +')') - r_string = 'scanone(the_cross, pheno.col="the_pheno", n.perm='+self.num_perm+', addcovar=covariates, intcovar=covariates[,'+ str(len(control_markers)) +'])' + r_string = 'scanone(the_cross, pheno.col="the_pheno", n.cluster=16, n.perm='+self.num_perm+', addcovar=covariates, intcovar=covariates[,'+ str(len(control_markers)) +'])' print("r_string:", r_string) if int(self.num_perm) > 0: thresholds = robjects.r(r_string) self.suggestive, self.significant = self.process_rqtl_perm_results(results) - r_string = 'scanone(the_cross, pheno.col="the_pheno", addcovar=covariates, intcovar=covariates[,'+ str(len(control_markers)) +'])' + r_string = 'scanone(the_cross, pheno.col="the_pheno", n.cluster=16, addcovar=covariates, intcovar=covariates[,'+ str(len(control_markers)) +'])' #r_string = 'scanone(the_cross, pheno.col='+pheno_as_string+', addcovar='+control_as_string+')' else: #r_string = 'scanone(the_cross, pheno.col='+pheno_as_string+', n.perm='+self.num_perm+')' - r_string = 'scanone(the_cross, pheno.col="the_pheno", n.perm='+self.num_perm+')' - if int(self.num_perm) > 0: + r_string = 'scanone(the_cross, pheno.col="the_pheno", n.cluster=16, n.perm='+self.num_perm+')' + if self.num_perm.isdigit() and int(self.num_perm) > 0: results = robjects.r(r_string) self.suggestive, self.significant = self.process_rqtl_perm_results(results) - r_string = 'scanone(the_cross, pheno.col="the_pheno")' + r_string = 'scanone(the_cross, pheno.col="the_pheno", n.cluster=16)' print("r_string:", r_string) result_data_frame = robjects.r(r_string) diff --git a/wqflask/wqflask/static/new/javascript/chr_lod_chart.coffee b/wqflask/wqflask/static/new/javascript/chr_lod_chart.coffee new file mode 100644 index 00000000..321957b3 --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/chr_lod_chart.coffee @@ -0,0 +1,296 @@ +class Chr_Lod_Chart + + constructor: (@plot_height, @plot_width, @chr, manhattanPlot) -> + @manhattanPlot = manhattanPlot + @qtl_results = js_data.qtl_results + console.log("qtl_results are:", @qtl_results) + console.log("chr is:", @chr) + + @get_max_chr() + + @filter_qtl_results() + console.log("filtered results:", @these_results) + @get_qtl_count() + + @x_coords = [] + @y_coords = [] + @marker_names = [] + + console.time('Create coordinates') + @create_coordinates() + console.log("@x_coords: ", @x_coords) + console.log("@y_coords: ", @y_coords) + console.timeEnd('Create coordinates') + + # Buffer to allow for the ticks/labels to be drawn + @x_buffer = @plot_width/30 + @y_buffer = @plot_height/20 + + @x_max = d3.max(@x_coords) + @y_max = d3.max(@y_coords) * 1.2 + + @y_threshold = @get_lod_threshold() + + @svg = @create_svg() + + @plot_coordinates = _.zip(@x_coords, @y_coords, @marker_names) + console.log("coordinates:", @plot_coordinates) + + @plot_height -= @y_buffer + + @create_scales() + + console.time('Create graph') + @create_graph() + console.timeEnd('Create graph') + + get_max_chr: () -> + @max_chr = 0 + for key of js_data.chromosomes + console.log("key is:", key) + if parseInt(key) > @max_chr + @max_chr = parseInt(key) + + filter_qtl_results: () -> + @these_results = [] + this_chr = 100 + for result in @qtl_results + if result.chr == "X" + this_chr = @max_chr + else + this_chr = result.chr + console.log("this_chr is:", this_chr) + console.log("@chr[0] is:", parseInt(@chr[0])) + if this_chr > parseInt(@chr[0]) + break + if parseInt(this_chr) == parseInt(@chr[0]) + @these_results.push(result) + + get_qtl_count: () -> + high_qtl_count = 0 + for result in @these_results + if result.lod_score > 1 + high_qtl_count += 1 + console.log("high_qtl_count:", high_qtl_count) + + #if high_qtl_count > 10000 + @y_axis_filter = 2 + #else if high_qtl_count > 1000 + # @y_axis_filter = 1 + #else + # @y_axis_filter = 0 + + create_coordinates: () -> + for result in @these_results + @x_coords.push(parseFloat(result.Mb)) + @y_coords.push(result.lod_score) + @marker_names.push(result.name) + + create_svg: () -> + svg = d3.select("#topchart") + .append("svg") + .attr("class", "chr_manhattan_plot") + .attr("width", @plot_width+@x_buffer) + .attr("height", @plot_height+@y_buffer) + .append("g") + return svg + + create_scales: () -> + @x_scale = d3.scale.linear() + .domain([0, @chr[1]]) + .range([@x_buffer, @plot_width]) + @y_scale = d3.scale.linear() + .domain([0, @y_max]) + .range([@plot_height, @y_buffer]) + + get_lod_threshold: () -> + if @y_max/2 > 2 + return @y_max/2 + else + return 2 + + create_graph: () -> + @add_border() + @add_x_axis() + @add_y_axis() + @add_title() + @add_back_button() + if @manhattanPlot + @add_plot_points() + else + @add_path() + + add_border: () -> + border_coords = [[@y_buffer, @plot_height, @x_buffer, @x_buffer], + [@y_buffer, @plot_height, @plot_width, @plot_width], + [@y_buffer, @y_buffer, @x_buffer, @plot_width], + [@plot_height, @plot_height, @x_buffer, @plot_width]] + + @svg.selectAll("line") + .data(border_coords) + .enter() + .append("line") + .attr("y1", (d) => + return d[0] + ) + .attr("y2", (d) => + return d[1] + ) + .attr("x1", (d) => + return d[2] + ) + .attr("x2", (d) => + return d[3] + ) + .style("stroke", "#000") + + add_x_axis: () -> + @xAxis = d3.svg.axis() + .scale(@x_scale) + .orient("bottom") + .ticks(20) + + @xAxis.tickFormat((d) => + d3.format("d") #format as integer + return (d) + ) + + @svg.append("g") + .attr("class", "x_axis") + .attr("transform", "translate(0," + @plot_height + ")") + .call(@xAxis) + .selectAll("text") + .attr("text-anchor", "right") + .attr("font-size", "12px") + .attr("dx", "-1.6em") + .attr("transform", (d) => + return "translate(-12,0) rotate(-90)" + ) + + add_y_axis: () -> + @yAxis = d3.svg.axis() + .scale(@y_scale) + .orient("left") + .ticks(5) + + @svg.append("g") + .attr("class", "y_axis") + .attr("transform", "translate(" + @x_buffer + ",0)") + .call(@yAxis) + + add_title: () -> + @svg.append("text") + .attr("class", "title") + .text("Chr " + @chr[0]) + .attr("x", (d) => + return (@plot_width + @x_buffer)/2 + ) + .attr("y", @y_buffer + 20) + .attr("dx", "0em") + .attr("text-anchor", "middle") + .attr("font-family", "sans-serif") + .attr("font-size", "18px") + .attr("fill", "black") + + add_back_button: () -> + @svg.append("text") + .attr("class", "back") + .text("Return to full view") + .attr("x", @x_buffer*2) + .attr("y", @y_buffer/2) + .attr("dx", "0em") + .attr("text-anchor", "middle") + .attr("font-family", "sans-serif") + .attr("font-size", "18px") + .attr("cursor", "pointer") + .attr("fill", "black") + .on("click", @return_to_full_view) + + add_path: () -> + line_function = d3.svg.line() + .x( (d) => return @x_scale(d[0])) + .y( (d) => return @y_scale(d[1])) + .interpolate("linear") + + line_graph = @svg.append("path") + .attr("d", line_function(@plot_coordinates)) + .attr("stroke", "blue") + .attr("stroke-width", 1) + .attr("fill", "none") + + add_plot_points: () -> + @plot_point = @svg.selectAll("circle") + .data(@plot_coordinates) + .enter() + .append("circle") + .attr("cx", (d) => + return @x_scale(d[0]) + ) + .attr("cy", (d) => + return @y_scale(d[1]) + ) + .attr("r", (d) => + #if d[1] > 2 + # return 3 + #else + return 2 + ) + .attr("fill", (d) => + #if d[1] > 2 + # return "white" + #else + return "black" + ) + .attr("stroke", "black") + .attr("stroke-width", "1") + .attr("id", (d) => + return "point_" + String(d[2]) + ) + .classed("circle", true) + .on("mouseover", (d) => + console.log("d3.event is:", d3.event) + console.log("d is:", d) + this_id = "point_" + String(d[2]) + d3.select("#" + this_id).classed("d3_highlight", true) + .attr("r", 5) + .attr("stroke", "none") + .attr("fill", "blue") + .call(@show_marker_in_table(d)) + ) + .on("mouseout", (d) => + this_id = "point_" + String(d[2]) + d3.select("#" + this_id).classed("d3_highlight", false) + .attr("r", (d) => + #if d[1] > 2 + # return 3 + #else + return 2 + ) + .attr("fill", (d) => + #if d[1] > 2 + # return "white" + #else + return "black" + ) + .attr("stroke", "black") + .attr("stroke-width", "1") + ) + .append("svg:title") + .text((d) => + return d[2] + ) + + return_to_full_view: () -> + $('#topchart').remove() + $('#chart_container').append('
') + create_manhattan_plot() + + show_marker_in_table: (marker_info) -> + console.log("in show_marker_in_table") + ### Searches for the select marker in the results table below ### + if marker_info + marker_name = marker_info[2] + $("#qtl_results_filter").find("input:first").val(marker_name).change() + #else + # marker_name = "" + #$("#qtl_results_filter").find("input:first").val(marker_name).change() diff --git a/wqflask/wqflask/static/new/javascript/chr_lod_chart.js b/wqflask/wqflask/static/new/javascript/chr_lod_chart.js new file mode 100644 index 00000000..deeb03d3 --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/chr_lod_chart.js @@ -0,0 +1,274 @@ +// Generated by CoffeeScript 1.7.1 +var Chr_Lod_Chart; + +Chr_Lod_Chart = (function() { + function Chr_Lod_Chart(plot_height, plot_width, chr, manhattanPlot) { + this.plot_height = plot_height; + this.plot_width = plot_width; + this.chr = chr; + this.manhattanPlot = manhattanPlot; + this.qtl_results = js_data.qtl_results; + console.log("qtl_results are:", this.qtl_results); + console.log("chr is:", this.chr); + this.get_max_chr(); + this.filter_qtl_results(); + console.log("filtered results:", this.these_results); + this.get_qtl_count(); + this.x_coords = []; + this.y_coords = []; + this.marker_names = []; + console.time('Create coordinates'); + this.create_coordinates(); + console.log("@x_coords: ", this.x_coords); + console.log("@y_coords: ", this.y_coords); + console.timeEnd('Create coordinates'); + this.x_buffer = this.plot_width / 30; + this.y_buffer = this.plot_height / 20; + this.x_max = d3.max(this.x_coords); + this.y_max = d3.max(this.y_coords) * 1.2; + this.y_threshold = this.get_lod_threshold(); + this.svg = this.create_svg(); + this.plot_coordinates = _.zip(this.x_coords, this.y_coords, this.marker_names); + console.log("coordinates:", this.plot_coordinates); + this.plot_height -= this.y_buffer; + this.create_scales(); + console.time('Create graph'); + this.create_graph(); + console.timeEnd('Create graph'); + } + + Chr_Lod_Chart.prototype.get_max_chr = function() { + var key, _results; + this.max_chr = 0; + _results = []; + for (key in js_data.chromosomes) { + console.log("key is:", key); + if (parseInt(key) > this.max_chr) { + _results.push(this.max_chr = parseInt(key)); + } else { + _results.push(void 0); + } + } + return _results; + }; + + Chr_Lod_Chart.prototype.filter_qtl_results = function() { + var result, this_chr, _i, _len, _ref, _results; + this.these_results = []; + this_chr = 100; + _ref = this.qtl_results; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + result = _ref[_i]; + if (result.chr === "X") { + this_chr = this.max_chr; + } else { + this_chr = result.chr; + } + console.log("this_chr is:", this_chr); + console.log("@chr[0] is:", parseInt(this.chr[0])); + if (this_chr > parseInt(this.chr[0])) { + break; + } + if (parseInt(this_chr) === parseInt(this.chr[0])) { + _results.push(this.these_results.push(result)); + } else { + _results.push(void 0); + } + } + return _results; + }; + + Chr_Lod_Chart.prototype.get_qtl_count = function() { + var high_qtl_count, result, _i, _len, _ref; + high_qtl_count = 0; + _ref = this.these_results; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + result = _ref[_i]; + if (result.lod_score > 1) { + high_qtl_count += 1; + } + } + console.log("high_qtl_count:", high_qtl_count); + return this.y_axis_filter = 2; + }; + + Chr_Lod_Chart.prototype.create_coordinates = function() { + var result, _i, _len, _ref, _results; + _ref = this.these_results; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + result = _ref[_i]; + this.x_coords.push(parseFloat(result.Mb)); + this.y_coords.push(result.lod_score); + _results.push(this.marker_names.push(result.name)); + } + return _results; + }; + + Chr_Lod_Chart.prototype.create_svg = function() { + var svg; + svg = d3.select("#topchart").append("svg").attr("class", "chr_manhattan_plot").attr("width", this.plot_width + this.x_buffer).attr("height", this.plot_height + this.y_buffer).append("g"); + return svg; + }; + + Chr_Lod_Chart.prototype.create_scales = function() { + this.x_scale = d3.scale.linear().domain([0, this.chr[1]]).range([this.x_buffer, this.plot_width]); + return this.y_scale = d3.scale.linear().domain([0, this.y_max]).range([this.plot_height, this.y_buffer]); + }; + + Chr_Lod_Chart.prototype.get_lod_threshold = function() { + if (this.y_max / 2 > 2) { + return this.y_max / 2; + } else { + return 2; + } + }; + + Chr_Lod_Chart.prototype.create_graph = function() { + this.add_border(); + this.add_x_axis(); + this.add_y_axis(); + this.add_title(); + this.add_back_button(); + if (this.manhattanPlot) { + return this.add_plot_points(); + } else { + return this.add_path(); + } + }; + + Chr_Lod_Chart.prototype.add_border = function() { + var border_coords; + border_coords = [[this.y_buffer, this.plot_height, this.x_buffer, this.x_buffer], [this.y_buffer, this.plot_height, this.plot_width, this.plot_width], [this.y_buffer, this.y_buffer, this.x_buffer, this.plot_width], [this.plot_height, this.plot_height, this.x_buffer, this.plot_width]]; + return this.svg.selectAll("line").data(border_coords).enter().append("line").attr("y1", (function(_this) { + return function(d) { + return d[0]; + }; + })(this)).attr("y2", (function(_this) { + return function(d) { + return d[1]; + }; + })(this)).attr("x1", (function(_this) { + return function(d) { + return d[2]; + }; + })(this)).attr("x2", (function(_this) { + return function(d) { + return d[3]; + }; + })(this)).style("stroke", "#000"); + }; + + Chr_Lod_Chart.prototype.add_x_axis = function() { + this.xAxis = d3.svg.axis().scale(this.x_scale).orient("bottom").ticks(20); + this.xAxis.tickFormat((function(_this) { + return function(d) { + d3.format("d"); + return d; + }; + })(this)); + return this.svg.append("g").attr("class", "x_axis").attr("transform", "translate(0," + this.plot_height + ")").call(this.xAxis).selectAll("text").attr("text-anchor", "right").attr("font-size", "12px").attr("dx", "-1.6em").attr("transform", (function(_this) { + return function(d) { + return "translate(-12,0) rotate(-90)"; + }; + })(this)); + }; + + Chr_Lod_Chart.prototype.add_y_axis = function() { + this.yAxis = d3.svg.axis().scale(this.y_scale).orient("left").ticks(5); + return this.svg.append("g").attr("class", "y_axis").attr("transform", "translate(" + this.x_buffer + ",0)").call(this.yAxis); + }; + + Chr_Lod_Chart.prototype.add_title = function() { + return this.svg.append("text").attr("class", "title").text("Chr " + this.chr[0]).attr("x", (function(_this) { + return function(d) { + return (_this.plot_width + _this.x_buffer) / 2; + }; + })(this)).attr("y", this.y_buffer + 20).attr("dx", "0em").attr("text-anchor", "middle").attr("font-family", "sans-serif").attr("font-size", "18px").attr("fill", "black"); + }; + + Chr_Lod_Chart.prototype.add_back_button = function() { + return this.svg.append("text").attr("class", "back").text("Return to full view").attr("x", this.x_buffer * 2).attr("y", this.y_buffer / 2).attr("dx", "0em").attr("text-anchor", "middle").attr("font-family", "sans-serif").attr("font-size", "18px").attr("cursor", "pointer").attr("fill", "black").on("click", this.return_to_full_view); + }; + + Chr_Lod_Chart.prototype.add_path = function() { + var line_function, line_graph; + line_function = d3.svg.line().x((function(_this) { + return function(d) { + return _this.x_scale(d[0]); + }; + })(this)).y((function(_this) { + return function(d) { + return _this.y_scale(d[1]); + }; + })(this)).interpolate("linear"); + return line_graph = this.svg.append("path").attr("d", line_function(this.plot_coordinates)).attr("stroke", "blue").attr("stroke-width", 1).attr("fill", "none"); + }; + + Chr_Lod_Chart.prototype.add_plot_points = function() { + return this.plot_point = this.svg.selectAll("circle").data(this.plot_coordinates).enter().append("circle").attr("cx", (function(_this) { + return function(d) { + return _this.x_scale(d[0]); + }; + })(this)).attr("cy", (function(_this) { + return function(d) { + return _this.y_scale(d[1]); + }; + })(this)).attr("r", (function(_this) { + return function(d) { + return 2; + }; + })(this)).attr("fill", (function(_this) { + return function(d) { + return "black"; + }; + })(this)).attr("stroke", "black").attr("stroke-width", "1").attr("id", (function(_this) { + return function(d) { + return "point_" + String(d[2]); + }; + })(this)).classed("circle", true).on("mouseover", (function(_this) { + return function(d) { + var this_id; + console.log("d3.event is:", d3.event); + console.log("d is:", d); + this_id = "point_" + String(d[2]); + return d3.select("#" + this_id).classed("d3_highlight", true).attr("r", 5).attr("stroke", "none").attr("fill", "blue").call(_this.show_marker_in_table(d)); + }; + })(this)).on("mouseout", (function(_this) { + return function(d) { + var this_id; + this_id = "point_" + String(d[2]); + return d3.select("#" + this_id).classed("d3_highlight", false).attr("r", function(d) { + return 2; + }).attr("fill", function(d) { + return "black"; + }).attr("stroke", "black").attr("stroke-width", "1"); + }; + })(this)).append("svg:title").text((function(_this) { + return function(d) { + return d[2]; + }; + })(this)); + }; + + Chr_Lod_Chart.prototype.return_to_full_view = function() { + $('#topchart').remove(); + $('#chart_container').append(''); + return create_manhattan_plot(); + }; + + Chr_Lod_Chart.prototype.show_marker_in_table = function(marker_info) { + var marker_name; + console.log("in show_marker_in_table"); + + /* Searches for the select marker in the results table below */ + if (marker_info) { + marker_name = marker_info[2]; + return $("#qtl_results_filter").find("input:first").val(marker_name).change(); + } + }; + + return Chr_Lod_Chart; + +})(); diff --git a/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.coffee b/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.coffee index 8b62d58a..b1d2305e 100755 --- a/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.coffee +++ b/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.coffee @@ -1,5 +1,6 @@ class Chr_Manhattan_Plot - constructor: (@plot_height, @plot_width, @chr) -> + + constructor: (@plot_height, @plot_width, @chr, manhattanPlot) -> @qtl_results = js_data.qtl_results console.log("qtl_results are:", @qtl_results) console.log("chr is:", @chr) @@ -113,7 +114,10 @@ class Chr_Manhattan_Plot @add_y_axis() @add_title() @add_back_button() - @add_plot_points() + if manhattanPlot + @add_plot_points() + else + @add_path() add_border: () -> border_coords = [[@y_buffer, @plot_height, @x_buffer, @x_buffer], @@ -201,6 +205,17 @@ class Chr_Manhattan_Plot .attr("fill", "black") .on("click", @return_to_full_view) + add_path: () -> + line_function = d3.svg.line() + .x( (d) => return @x_scale(d[0])) + .y( (d) => return @y_scale(d[1])) + .interpolate("linear") + + line_graph = @svg.append("path") + .attr("d", line_function(@plot_coordinates)) + .attr("stroke", "blue") + .attr("stroke-width", 1) + .attr("fill", "none") add_plot_points: () -> @plot_point = @svg.selectAll("circle") diff --git a/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.js b/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.js index 24d8b962..001d0593 100755 --- a/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.js +++ b/wqflask/wqflask/static/new/javascript/chr_manhattan_plot.js @@ -2,7 +2,7 @@ var Chr_Manhattan_Plot; Chr_Manhattan_Plot = (function() { - function Chr_Manhattan_Plot(plot_height, plot_width, chr) { + function Chr_Manhattan_Plot(plot_height, plot_width, chr, manhattanPlot) { this.plot_height = plot_height; this.plot_width = plot_width; this.chr = chr; @@ -130,7 +130,11 @@ Chr_Manhattan_Plot = (function() { this.add_y_axis(); this.add_title(); this.add_back_button(); - return this.add_plot_points(); + if (manhattanPlot) { + return this.add_plot_points(); + } else { + return this.add_path(); + } }; Chr_Manhattan_Plot.prototype.add_border = function() { @@ -187,6 +191,20 @@ Chr_Manhattan_Plot = (function() { return this.svg.append("text").attr("class", "back").text("Return to full view").attr("x", this.x_buffer * 2).attr("y", this.y_buffer / 2).attr("dx", "0em").attr("text-anchor", "middle").attr("font-family", "sans-serif").attr("font-size", "18px").attr("cursor", "pointer").attr("fill", "black").on("click", this.return_to_full_view); }; + Chr_Manhattan_Plot.prototype.add_path = function() { + var line_function, line_graph; + line_function = d3.svg.line().x((function(_this) { + return function(d) { + return _this.x_scale(d[0]); + }; + })(this)).y((function(_this) { + return function(d) { + return _this.y_scale(d[1]); + }; + })(this)).interpolate("linear"); + return line_graph = this.svg.append("path").attr("d", line_function(this.plot_coordinates)).attr("stroke", "blue").attr("stroke-width", 1).attr("fill", "none"); + }; + Chr_Manhattan_Plot.prototype.add_plot_points = function() { return this.plot_point = this.svg.selectAll("circle").data(this.plot_coordinates).enter().append("circle").attr("cx", (function(_this) { return function(d) { diff --git a/wqflask/wqflask/static/new/javascript/create_lodchart.coffee b/wqflask/wqflask/static/new/javascript/create_lodchart.coffee new file mode 100644 index 00000000..2d5e3acb --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/create_lodchart.coffee @@ -0,0 +1,87 @@ +create_manhattan_plot = -> + h = 500 + w = 1200 + margin = {left:60, top:40, right:40, bottom: 40, inner:5} + halfh = (h+margin.top+margin.bottom) + totalh = halfh*2 + totalw = (w+margin.left+margin.right) + if 'additive' of js_data + additive = js_data.additive + else + additive = false + + console.log("js_data:", js_data) + + # simplest use + #d3.json "data.json", (data) -> + mychart = lodchart().lodvarname("lod.hk") + .height(h) + .width(w) + .margin(margin) + .ylab("LOD score") + .manhattanPlot(js_data.manhattan_plot) + #.additive(additive) + + data = js_data.json_data + + d3.select("div#topchart") + .datum(data) + .call(mychart) + + # grab chromosome rectangles; color pink on hover + chrrect = mychart.chrSelect() + chrrect.on "mouseover", -> + d3.select(this).attr("fill", "#E9CFEC") + .on "mouseout", (d,i) -> + d3.select(this).attr("fill", -> + return "#F1F1F9" if i % 2 + "#FBFBFF") + + # animate points at markers on click + mychart.markerSelect() + .on "click", (d) -> + r = d3.select(this).attr("r") + d3.select(this) + .transition().duration(500).attr("r", r*3) + .transition().duration(500).attr("r", r) + +create_manhattan_plot() + +$("#export").click => + #Get d3 SVG element + svg = $("#topchart").find("svg")[0] + + #Extract SVG text string + svg_xml = (new XMLSerializer).serializeToString(svg) + console.log("svg_xml:", svg_xml) + + #Set filename + filename = "manhattan_plot_" + js_data.this_trait + + #Make a form with the SVG data + form = $("#exportform") + form.find("#data").val(svg_xml) + form.find("#filename").val(filename) + form.submit() + +$("#export_pdf").click => + + #$('#topchart').remove() + #$('#chart_container').append('') + #create_interval_map() + + #Get d3 SVG element + svg = $("#topchart").find("svg")[0] + + #Extract SVG text string + svg_xml = (new XMLSerializer).serializeToString(svg) + console.log("svg_xml:", svg_xml) + + #Set filename + filename = "manhattan_plot_" + js_data.this_trait + + #Make a form with the SVG data + form = $("#exportpdfform") + form.find("#data").val(svg_xml) + form.find("#filename").val(filename) + form.submit() diff --git a/wqflask/wqflask/static/new/javascript/create_lodchart.js b/wqflask/wqflask/static/new/javascript/create_lodchart.js new file mode 100644 index 00000000..f8aafee7 --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/create_lodchart.js @@ -0,0 +1,73 @@ +// Generated by CoffeeScript 1.7.1 +var create_manhattan_plot; + +create_manhattan_plot = function() { + var additive, chrrect, data, h, halfh, margin, mychart, totalh, totalw, w; + h = 500; + w = 1200; + margin = { + left: 60, + top: 40, + right: 40, + bottom: 40, + inner: 5 + }; + halfh = h + margin.top + margin.bottom; + totalh = halfh * 2; + totalw = w + margin.left + margin.right; + if ('additive' in js_data) { + additive = js_data.additive; + } else { + additive = false; + } + console.log("js_data:", js_data); + mychart = lodchart().lodvarname("lod.hk").height(h).width(w).margin(margin).ylab("LOD score").manhattanPlot(js_data.manhattan_plot); + data = js_data.json_data; + d3.select("div#topchart").datum(data).call(mychart); + chrrect = mychart.chrSelect(); + chrrect.on("mouseover", function() { + return d3.select(this).attr("fill", "#E9CFEC"); + }).on("mouseout", function(d, i) { + return d3.select(this).attr("fill", function() { + if (i % 2) { + return "#F1F1F9"; + } + return "#FBFBFF"; + }); + }); + return mychart.markerSelect().on("click", function(d) { + var r; + r = d3.select(this).attr("r"); + return d3.select(this).transition().duration(500).attr("r", r * 3).transition().duration(500).attr("r", r); + }); +}; + +create_manhattan_plot(); + +$("#export").click((function(_this) { + return function() { + var filename, form, svg, svg_xml; + svg = $("#topchart").find("svg")[0]; + svg_xml = (new XMLSerializer).serializeToString(svg); + console.log("svg_xml:", svg_xml); + filename = "manhattan_plot_" + js_data.this_trait; + form = $("#exportform"); + form.find("#data").val(svg_xml); + form.find("#filename").val(filename); + return form.submit(); + }; +})(this)); + +$("#export_pdf").click((function(_this) { + return function() { + var filename, form, svg, svg_xml; + svg = $("#topchart").find("svg")[0]; + svg_xml = (new XMLSerializer).serializeToString(svg); + console.log("svg_xml:", svg_xml); + filename = "manhattan_plot_" + js_data.this_trait; + form = $("#exportpdfform"); + form.find("#data").val(svg_xml); + form.find("#filename").val(filename); + return form.submit(); + }; +})(this)); diff --git a/wqflask/wqflask/static/new/javascript/lod_chart.coffee b/wqflask/wqflask/static/new/javascript/lod_chart.coffee index 309cec9e..b0f4b2f5 100644 --- a/wqflask/wqflask/static/new/javascript/lod_chart.coffee +++ b/wqflask/wqflask/static/new/javascript/lod_chart.coffee @@ -5,6 +5,7 @@ lodchart = () -> axispos = {xtitle:25, ytitle:30, xlabel:5, ylabel:5} titlepos = 20 manhattanPlot = false + additive = false ylim = null additive_ylim = null nyticks = 5 @@ -49,27 +50,26 @@ lodchart = () -> lodvarname = lodvarname ? data.lodnames[0] data[lodvarname] = (Math.abs(x) for x in data[lodvarname]) # take absolute values - if 'additive' of data + ylim = ylim ? [0, d3.max(data[lodvarname])] + if additive data['additive'] = (Math.abs(x) for x in data['additive']) - ylim = ylim ? [0, d3.max(data[lodvarname])] - if 'additive' of data - #if data['additive'].length > 0 - additive_ylim = additive_ylim ? [0, d3.max(data['additive'])] + additive_ylim = additive_ylim ? [0, d3.max(data['additive'])] + lodvarnum = data.lodnames.indexOf(lodvarname) - + # Select the svg element, if it exists. svg = d3.select(this).selectAll("svg").data([data]) - + # Otherwise, create the skeletal chart. gEnter = svg.enter().append("svg").append("g") - + # Update the outer dimensions. svg.attr("width", width+margin.left+margin.right) .attr("height", height+margin.top+margin.bottom) - + # Update the inner dimensions. g = svg.select("g") - + # box g.append("rect") .attr("x", margin.left) @@ -78,23 +78,22 @@ lodchart = () -> .attr("width", width) .attr("fill", darkrect) .attr("stroke", "none") - + yscale.domain(ylim) .range([height+margin.top, margin.top+margin.inner]) - - #if data['additive'].length > 0 - if 'additive' of data - additive_yscale.domain(additive_ylim) - .range([height+margin.top, margin.top+margin.inner + height/2]) - + # if yticks not provided, use nyticks to choose pretty ones yticks = yticks ? yscale.ticks(nyticks) + #if data['additive'].length > 0 - if 'additive' of data + if additive + additive_yscale.domain(additive_ylim) + .range([height+margin.top, margin.top+margin.inner + height/2]) + additive_yticks = additive_yticks ? additive_yscale.ticks(nyticks) # reorganize lod,pos by chromosomes - data = reorgLodData(data, lodvarname) + reorgLodData(data, lodvarname) # add chromosome scales (for x-axis) data = chrscales(data, width, chrGap, margin.left, pad4heatmap) @@ -153,7 +152,7 @@ lodchart = () -> #console.log("chr_length is:", chr_ob[1]) $('#topchart').remove() $('#chart_container').append('') - chr_plot = new Chr_Manhattan_Plot(600, 1200, chr_ob) + chr_plot = new Chr_Lod_Chart(600, 1200, chr_ob, manhattanPlot) # y-axis rotate_ylab = rotate_ylab ? (ylab.length > 1) @@ -191,7 +190,7 @@ lodchart = () -> .attr("fill", "slateblue") #if data['additive'].length > 0 - if 'additive' of data + if additive rotate_additive_ylab = rotate_additive_ylab ? (additive_ylab.length > 1) additive_yaxis = g.append("g").attr("class", "y axis") additive_yaxis.selectAll("empty") @@ -262,11 +261,11 @@ lodchart = () -> .x((d) -> xscale[chr](d)) .y((d,i) -> yscale(data.lodByChr[chr][i][lodcolumn])) - #if 'additive' of data - # additivecurve = (chr, lodcolumn) -> - # d3.svg.line() - # .x((d) -> xscale[chr](d)) - # .y((d,i) -> additive_yscale(data.additiveByChr[chr][i][lodcolumn])) + if additive + additivecurve = (chr, lodcolumn) -> + d3.svg.line() + .x((d) -> xscale[chr](d)) + .y((d,i) -> additive_yscale(data.additiveByChr[chr][i][lodcolumn])) curves = g.append("g").attr("id", "curves") @@ -279,16 +278,15 @@ lodchart = () -> .attr("stroke-width", linewidth) .style("pointer-events", "none") - ##if data['additive'].length > 0 - #if 'additive' of data - # for chr in data.chrnames - # curves.append("path") - # .datum(data.posByChr[chr[0]]) - # .attr("d", additivecurve(chr[0], lodvarnum)) - # .attr("stroke", additivelinecolor) - # .attr("fill", "none") - # .attr("stroke-width", 1) - # .style("pointer-events", "none") + if additive + for chr in data.chrnames + curves.append("path") + .datum(data.posByChr[chr[0]]) + .attr("d", additivecurve(chr[0], lodvarnum)) + .attr("stroke", additivelinecolor) + .attr("fill", "none") + .attr("stroke-width", 1) + .style("pointer-events", "none") # points at markers console.log("before pointsize") @@ -487,6 +485,9 @@ lodchart = () -> chart.yscale = () -> return yscale + chart.additive = () -> + return additive + #if data['additive'].length > 0 chart.additive_yscale = () -> return additive_yscale diff --git a/wqflask/wqflask/static/new/javascript/lod_chart.js b/wqflask/wqflask/static/new/javascript/lod_chart.js index e6f34854..2d00d3a5 100644 --- a/wqflask/wqflask/static/new/javascript/lod_chart.js +++ b/wqflask/wqflask/static/new/javascript/lod_chart.js @@ -2,7 +2,7 @@ var lodchart; lodchart = function() { - var additive_ylab, additive_ylim, additive_yscale, additive_yticks, additivelinecolor, axispos, chart, chrGap, chrSelect, darkrect, height, lightrect, linewidth, lodcurve, lodlinecolor, lodvarname, manhattanPlot, margin, markerSelect, nyticks, pad4heatmap, pointcolor, pointsAtMarkers, pointsize, pointstroke, rotate_ylab, significantcolor, suggestivecolor, title, titlepos, width, xlab, xscale, ylab, ylim, yscale, yticks; + var additive, additive_ylab, additive_ylim, additive_yscale, additive_yticks, additivelinecolor, axispos, chart, chrGap, chrSelect, darkrect, height, lightrect, linewidth, lodcurve, lodlinecolor, lodvarname, manhattanPlot, margin, markerSelect, nyticks, pad4heatmap, pointcolor, pointsAtMarkers, pointsize, pointstroke, rotate_ylab, significantcolor, suggestivecolor, title, titlepos, width, xlab, xscale, ylab, ylim, yscale, yticks; width = 800; height = 500; margin = { @@ -20,6 +20,7 @@ lodchart = function() { }; titlepos = 20; manhattanPlot = false; + additive = false; ylim = null; additive_ylim = null; nyticks = 5; @@ -52,7 +53,7 @@ lodchart = function() { pointsAtMarkers = true; chart = function(selection) { return selection.each(function(data) { - var additive_yaxis, chr, curves, g, gEnter, hiddenpoints, lodvarnum, markerpoints, markertip, redraw_plot, rotate_additive_ylab, suggestive_bar, svg, titlegrp, x, xaxis, yaxis, _i, _len, _ref; + var additive_yaxis, additivecurve, chr, curves, g, gEnter, hiddenpoints, lodvarnum, markerpoints, markertip, redraw_plot, rotate_additive_ylab, suggestive_bar, svg, titlegrp, x, xaxis, yaxis, _i, _j, _len, _len1, _ref, _ref1; if (manhattanPlot === true) { pointcolor = "darkslateblue"; pointsize = 2; @@ -68,7 +69,8 @@ lodchart = function() { } return _results; })(); - if ('additive' in data) { + ylim = ylim != null ? ylim : [0, d3.max(data[lodvarname])]; + if (additive) { data['additive'] = (function() { var _i, _len, _ref, _results; _ref = data['additive']; @@ -79,9 +81,6 @@ lodchart = function() { } return _results; })(); - } - ylim = ylim != null ? ylim : [0, d3.max(data[lodvarname])]; - if ('additive' in data) { additive_ylim = additive_ylim != null ? additive_ylim : [0, d3.max(data['additive'])]; } lodvarnum = data.lodnames.indexOf(lodvarname); @@ -91,14 +90,12 @@ lodchart = function() { g = svg.select("g"); g.append("rect").attr("x", margin.left).attr("y", margin.top).attr("height", height).attr("width", width).attr("fill", darkrect).attr("stroke", "none"); yscale.domain(ylim).range([height + margin.top, margin.top + margin.inner]); - if ('additive' in data) { - additive_yscale.domain(additive_ylim).range([height + margin.top, margin.top + margin.inner + height / 2]); - } yticks = yticks != null ? yticks : yscale.ticks(nyticks); - if ('additive' in data) { + if (additive) { + additive_yscale.domain(additive_ylim).range([height + margin.top, margin.top + margin.inner + height / 2]); additive_yticks = additive_yticks != null ? additive_yticks : additive_yscale.ticks(nyticks); } - data = reorgLodData(data, lodvarname); + reorgLodData(data, lodvarname); data = chrscales(data, width, chrGap, margin.left, pad4heatmap); xscale = data.xscale; chrSelect = g.append("g").attr("class", "chrRect").selectAll("empty").data(data.chrnames).enter().append("rect").attr("id", function(d) { @@ -135,7 +132,7 @@ lodchart = function() { var chr_plot; $('#topchart').remove(); $('#chart_container').append(''); - return chr_plot = new Chr_Manhattan_Plot(600, 1200, chr_ob); + return chr_plot = new Chr_Lod_Chart(600, 1200, chr_ob, manhattanPlot); }; rotate_ylab = rotate_ylab != null ? rotate_ylab : ylab.length > 1; yaxis = g.append("g").attr("class", "y axis"); @@ -150,7 +147,7 @@ lodchart = function() { return formatAxis(yticks)(d); }); yaxis.append("text").attr("class", "title").attr("y", margin.top + height / 2).attr("x", margin.left - axispos.ytitle).text(ylab).attr("transform", rotate_ylab ? "rotate(270," + (margin.left - axispos.ytitle) + "," + (margin.top + height / 2) + ")" : "").attr("text-anchor", "middle").attr("fill", "slateblue"); - if ('additive' in data) { + if (additive) { rotate_additive_ylab = rotate_additive_ylab != null ? rotate_additive_ylab : additive_ylab.length > 1; additive_yaxis = g.append("g").attr("class", "y axis"); additive_yaxis.selectAll("empty").data(additive_yticks).enter().append("line").attr("y1", function(d) { @@ -189,12 +186,28 @@ lodchart = function() { return yscale(data.lodByChr[chr][i][lodcolumn]); }); }; + if (additive) { + additivecurve = function(chr, lodcolumn) { + return d3.svg.line().x(function(d) { + return xscale[chr](d); + }).y(function(d, i) { + return additive_yscale(data.additiveByChr[chr][i][lodcolumn]); + }); + }; + } curves = g.append("g").attr("id", "curves"); _ref = data.chrnames; for (_i = 0, _len = _ref.length; _i < _len; _i++) { chr = _ref[_i]; curves.append("path").datum(data.posByChr[chr[0]]).attr("d", lodcurve(chr[0], lodvarnum)).attr("stroke", lodlinecolor).attr("fill", "none").attr("stroke-width", linewidth).style("pointer-events", "none"); } + if (additive) { + _ref1 = data.chrnames; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + chr = _ref1[_j]; + curves.append("path").datum(data.posByChr[chr[0]]).attr("d", additivecurve(chr[0], lodvarnum)).attr("stroke", additivelinecolor).attr("fill", "none").attr("stroke-width", 1).style("pointer-events", "none"); + } + } } console.log("before pointsize"); if (pointsize > 0) { @@ -413,6 +426,9 @@ lodchart = function() { chart.yscale = function() { return yscale; }; + chart.additive = function() { + return additive; + }; chart.additive_yscale = function() { return additive_yscale; }; 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 d25c1d3a..b0eea3b6 100755 --- a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee +++ b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee @@ -93,7 +93,7 @@ $ -> url = "/interval_mapping" $('input[name=method]').val("reaper") - + $('input[name=manhattan_plot]').val($('input[name=manhattan_plot_reaper]:checked').val()) $('input[name=mapping_display_all]').val($('input[name=display_all_reaper]')) $('input[name=suggestive]').val($('input[name=suggestive_reaper]')) form_data = $('#trait_data_form').serialize() @@ -142,6 +142,7 @@ $ -> $("#progress_bar_container").modal() url = "/marker_regression" $('input[name=method]').val("pylmm") + $('input[name=manhattan_plot]').val($('input[name=manhattan_plot_pylmm]:checked').val()) form_data = $('#trait_data_form').serialize() console.log("form_data is:", form_data) 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 d178879c..0b056442 100755 --- a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js +++ b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js @@ -101,6 +101,7 @@ $(function() { $("#progress_bar_container").modal(); url = "/interval_mapping"; $('input[name=method]').val("reaper"); + $('input[name=manhattan_plot]').val($('input[name=manhattan_plot_reaper]:checked').val()); $('input[name=mapping_display_all]').val($('input[name=display_all_reaper]')); $('input[name=suggestive]').val($('input[name=suggestive_reaper]')); form_data = $('#trait_data_form').serialize(); @@ -125,6 +126,7 @@ $(function() { $("#progress_bar_container").modal(); url = "/marker_regression"; $('input[name=method]').val("pylmm"); + $('input[name=manhattan_plot]').val($('input[name=manhattan_plot_pylmm]:checked').val()); form_data = $('#trait_data_form').serialize(); console.log("form_data is:", form_data); return do_ajax_post(url, form_data); diff --git a/wqflask/wqflask/templates/interval_mapping.html b/wqflask/wqflask/templates/interval_mapping.html index 4fe5d0f8..7a03ce34 100755 --- a/wqflask/wqflask/templates/interval_mapping.html +++ b/wqflask/wqflask/templates/interval_mapping.html @@ -5,7 +5,6 @@ - {% endblock %} @@ -84,7 +83,7 @@ - + diff --git a/wqflask/wqflask/templates/marker_regression.html b/wqflask/wqflask/templates/marker_regression.html index 51aab95c..2c8f42a1 100755 --- a/wqflask/wqflask/templates/marker_regression.html +++ b/wqflask/wqflask/templates/marker_regression.html @@ -87,10 +87,10 @@ --> - + - + diff --git a/wqflask/wqflask/templates/show_trait_mapping_tools.html b/wqflask/wqflask/templates/show_trait_mapping_tools.html index e5d96490..3fd98df3 100755 --- a/wqflask/wqflask/templates/show_trait_mapping_tools.html +++ b/wqflask/wqflask/templates/show_trait_mapping_tools.html @@ -80,6 +80,20 @@ +