diff options
19 files changed, 890 insertions, 58 deletions
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py index cd8c1ac1..8296adea 100755 --- a/wqflask/base/data_set.py +++ b/wqflask/base/data_set.py @@ -318,12 +318,17 @@ class DatasetGroup(object): #determine default genotype object if self.incparentsf1 and genotype_1.type != "intercross": - self.genotype = genotype_2 + #self.genotype = genotype_2 + genotype = genotype_2 else: self.incparentsf1 = 0 - self.genotype = genotype_1 + #self.genotype = genotype_1 + genotype = genotype_1 - self.samplelist = list(self.genotype.prgy) + #self.samplelist = list(self.genotype.prgy) + self.samplelist = list(genotype.prgy) + + return genotype #class DataSets(object): @@ -1084,6 +1089,7 @@ class MrnaAssayDataSet(DataSet): Strain.Name """ % (escape(trait), escape(self.name)) results = g.db.execute(query).fetchall() + print("RETRIEVED RESULTS HERE:", results) return results diff --git a/wqflask/base/trait.py b/wqflask/base/trait.py index 731f99eb..74bc07bb 100755 --- a/wqflask/base/trait.py +++ b/wqflask/base/trait.py @@ -154,7 +154,7 @@ class GeneralTrait(object): result.append(None) return result - def export_informative(self, incVar=0): + def export_informative(self, include_variance=0): """ export informative sample mostly used in qtl regression @@ -163,12 +163,12 @@ class GeneralTrait(object): samples = [] vals = [] the_vars = [] - for sample, value in self.data.items(): - if value.val != None: - if not incVar or value.var != None: - samples.append(sample) - vals.append(value.val) - the_vars.append(value.var) + for sample_name, sample_data in self.data.items(): + if sample_data.value != None: + if not include_variance or sample_data.variance != None: + samples.append(sample_name) + vals.append(sample_data.value) + the_vars.append(sample_data.variance) return samples, vals, the_vars @@ -235,11 +235,19 @@ class GeneralTrait(object): # Todo: is this necessary? If not remove self.data.clear() + if self.dataset.group.parlist: + all_samples_ordered = (self.dataset.group.parlist + + self.dataset.group.f1list + + self.dataset.group.samplelist) + elif self.dataset.group.f1list: + all_samples_ordered = self.dataset.group.f1list + self.dataset.group.samplelist + else: + all_samples_ordered = self.dataset.group.samplelist + if results: for item in results: - #name, value, variance, num_cases = item + name, value, variance, num_cases = item if not samplelist or (samplelist and name in samplelist): - name = item[0] self.data[name] = webqtlCaseData(*item) #name, value, variance, num_cases) #def keys(self): diff --git a/wqflask/wqflask/collect.py b/wqflask/wqflask/collect.py index ef7b37df..991d281c 100644 --- a/wqflask/wqflask/collect.py +++ b/wqflask/wqflask/collect.py @@ -23,7 +23,7 @@ Redis = redis.StrictRedis() from flask import (Flask, g, render_template, url_for, request, make_response, - redirect, flash) + redirect, flash, jsonify) from wqflask import app @@ -122,16 +122,18 @@ def create_new(): @app.route("/collections/list") def list_collections(): + params = request.args user_collections = g.user_session.user_ob.user_collections return render_template("collections/list.html", + params = params, user_collections = user_collections, ) - @app.route("/collections/view") def view_collection(): params = request.args + print("params in view collection:", params) uc_id = params['uc_id'] uc = model.UserCollection.query.get(uc_id) traits = json.loads(uc.members) @@ -139,6 +141,7 @@ def view_collection(): print("in view_collection traits are:", traits) trait_obs = [] + json_version = [] for atrait in traits: name, dataset_name = atrait.split(':') @@ -146,8 +149,16 @@ def view_collection(): trait_ob = trait.GeneralTrait(name=name, dataset_name=dataset_name) trait_ob.get_info() trait_obs.append(trait_ob) - - return render_template("collections/view.html", - trait_obs=trait_obs, - uc = uc, + + json_version.append(dict(name=trait_ob.name)) + #dis=trait_ob.description)) + + collection_info = dict(trait_obs=trait_obs, + uc = uc) + if "json" in params: + print("json_version:", json_version) + return json.dumps(json_version) + else: + return render_template("collections/view.html", + **collection_info ) diff --git a/wqflask/wqflask/interval_mapping/interval_mapping.py b/wqflask/wqflask/interval_mapping/interval_mapping.py index f41ebd2c..de7a2704 100755 --- a/wqflask/wqflask/interval_mapping/interval_mapping.py +++ b/wqflask/wqflask/interval_mapping/interval_mapping.py @@ -64,10 +64,12 @@ class IntervalMapping(object): for key in self.species.chromosomes.chromosomes.keys(): chromosome_mb_lengths[key] = self.species.chromosomes.chromosomes[key].mb_length + #print("self.qtl_results:", self.qtl_results) + self.js_data = dict( - lrs_lod = self.lrs_lod, chromosomes = chromosome_mb_lengths, qtl_results = self.qtl_results, + #lrs_lod = self.lrs_lod, ) def set_options(self, start_vars): @@ -76,10 +78,13 @@ class IntervalMapping(object): #self.plot_scale = start_vars['scale'] #if self.plotScale == 'physic' and not fd.genotype.Mbmap: # self.plotScale = 'morgan' - self.num_permutations = start_vars['num_permutations'] + self.num_permutations = int(start_vars['num_permutations']) #self.do_bootstrap = start_vars['do_bootstrap'] - #self.control_locus = start_vars['control_locus'] self.selected_chr = start_vars['chromosome'] + if 'control_locus' in start_vars: + self.control_locus = start_vars['control_locus'] + else: + self.control_locus = None #self.weighted_regression = start_vars['weighted'] #self.lrs_lod = start_vars['lrs_lod'] @@ -88,40 +93,76 @@ class IntervalMapping(object): """Generates qtl results for plotting interval map""" self.dataset.group.get_markers() - self.dataset.group.read_genotype_file() + genotype = self.dataset.group.read_genotype_file() samples, values, variances = self.this_trait.export_informative() + + trimmed_samples = [] + trimmed_values = [] + for i in range(0, len(samples)): + if samples[i] in self.dataset.group.samplelist: + trimmed_samples.append(samples[i]) + trimmed_values.append(values[i]) + + #if self.weighted_regression: + # self.lrs_array = self.genotype.permutation(strains = trimmed_samples, + # trait = trimmed_values, + # variance = _vars, + # nperm=self.num_permutations) + #else: + self.lrs_array = genotype.permutation(strains = trimmed_samples, + trait = trimmed_values, + nperm= self.num_permutations) + self.suggestive = self.lrs_array[int(self.num_permutations*0.37-1)] + self.significant = self.lrs_array[int(self.num_permutations*0.95-1)] + + print("samples:", trimmed_samples) + if self.control_locus: - if self.weighted_regression: - self.qtl_results = self.dataset.genotype.regression(strains = samples, - trait = values, - variance = variances, - control = self.control_locus) - else: - self.qtl_results = self.dataset.genotype.regression(strains = samples, - trait = values, - control = self.control_locus) + #if self.weighted_regression: + # self.qtl_results = self.dataset.genotype.regression(strains = samples, + # trait = values, + # variance = variances, + # control = self.control_locus) + #else: + #reaper_results = self.dataset.group.genotype.regression(strains = trimmed_samples, + # trait = trimmed_values, + # control = self.control_locus) + reaper_results = genotype.regression(strains = trimmed_samples, + trait = trimmed_values, + control = self.control_locus) else: - if self.weighted_regression: - self.qtl_results = self.dataset.genotype.regression(strains = samples, - trait = values, - variance = variances) - else: - self.qtl_results = self.dataset.genotype.regression(strains = samples, - trait = values) + #if self.weighted_regression: + # self.qtl_results = self.dataset.genotype.regression(strains = samples, + # trait = values, + # variance = variances) + #else: + print("strains:", trimmed_samples) + print("trait:", trimmed_values) + #reaper_results = self.dataset.group.genotype.regression(strains = trimmed_samples, + # trait = trimmed_values) + reaper_results = genotype.regression(strains = trimmed_samples, + trait = trimmed_values) + #Need to convert the QTL objects that qtl reaper returns into a json serializable dictionary + self.qtl_results = [] + for qtl in reaper_results: + reaper_locus = qtl.locus + locus = {"name":reaper_locus.name, "chr":reaper_locus.chr, "cM":reaper_locus.cM, "Mb":reaper_locus.Mb} + qtl = {"lrs": qtl.lrs, "locus": locus, "additive": qtl.additive} + self.qtl_results.append(qtl) #pheno_vector = np.array([val == "x" and np.nan or float(val) for val in self.vals]) #if self.dataset.group.species == "human": # p_values, t_stats = self.gen_human_results(pheno_vector, tempdata) #else: - genotype_data = [marker['genotypes'] for marker in self.dataset.group.markers.markers] - - no_val_samples = self.identify_empty_samples() - trimmed_genotype_data = self.trim_genotypes(genotype_data, no_val_samples) - - genotype_matrix = np.array(trimmed_genotype_data).T + #genotype_data = [marker['genotypes'] for marker in self.dataset.group.markers.markers] + # + #no_val_samples = self.identify_empty_samples() + #trimmed_genotype_data = self.trim_genotypes(genotype_data, no_val_samples) + # + #genotype_matrix = np.array(trimmed_genotype_data).T #t_stats, p_values = lmm.run( # pheno_vector, diff --git a/wqflask/wqflask/static/new/css/interval_mapping.css b/wqflask/wqflask/static/new/css/interval_mapping.css new file mode 100644 index 00000000..9d23ba25 --- /dev/null +++ b/wqflask/wqflask/static/new/css/interval_mapping.css @@ -0,0 +1,27 @@ +.manhattan_plot .y_axis path, +.manhattan_plot .y_axis line { + fill: none; + stroke: black; + shape-rendering: crispEdges; +} +.manhattan_plot .y_axis text { + font-family: sans-serif; + font-size: 14px; +} + +.manhattan_plot .x_axis path, +.manhattan_plot .x_axis line { + fill: none; + stroke: black; + shape-rendering: crispEdges; +} +.manhattan_plot .x_axis text { + text-anchor: end; + font-family: sans-serif; + font-size: 8px; +} + +rect { + stroke: WhiteSmoke; + fill: lightgrey; +} \ 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 2c60d3ab..4921b55e 100644 --- a/wqflask/wqflask/static/new/javascript/bar_chart.coffee +++ b/wqflask/wqflask/static/new/javascript/bar_chart.coffee @@ -276,7 +276,7 @@ class Bar_Chart .attr("height", 100) .attr("width", 100) .attr('transform', 'translate(-20,50)') - + legend_rect = legend.selectAll('rect') .data(distinct_vals) .enter() @@ -305,13 +305,12 @@ class Bar_Chart ) color_by_trait: () -> - $('#collections_holder').load('/collections/list #collections_list', => + $('#collections_holder').load('/collections/list?color_by_trait #collections_list', => $.colorbox( inline: true href: "#collections_holder" ) ) - - + root.Bar_Chart = Bar_Chart \ No newline at end of file diff --git a/wqflask/wqflask/static/new/javascript/bar_chart.js b/wqflask/wqflask/static/new/javascript/bar_chart.js index 03902741..9c2059c0 100644 --- a/wqflask/wqflask/static/new/javascript/bar_chart.js +++ b/wqflask/wqflask/static/new/javascript/bar_chart.js @@ -322,7 +322,7 @@ Bar_Chart.prototype.color_by_trait = function() { var _this = this; - return $('#collections_holder').load('/collections/list #collections_list', function() { + return $('#collections_holder').load('/collections/list?color_by_trait #collections_list', function() { return $.colorbox({ inline: true, href: "#collections_holder" diff --git a/wqflask/wqflask/static/new/javascript/get_traits_from_collection.coffee b/wqflask/wqflask/static/new/javascript/get_traits_from_collection.coffee new file mode 100644 index 00000000..6854dda5 --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/get_traits_from_collection.coffee @@ -0,0 +1,15 @@ + +console.log("before get_traits_from_collection") + + +collection_hover = () -> + console.log("Hovering over:", $(this)) + this_collection_url = $(this).find('.collection_name').prop("href") + this_collection_url += "&json" + console.log("this_collection_url", this_collection_url) + +$ -> + console.log("inside get_traits_from_collection") + $(document).on("mouseover", ".collection_line", collection_hover) + + \ No newline at end of file diff --git a/wqflask/wqflask/static/new/javascript/get_traits_from_collection.js b/wqflask/wqflask/static/new/javascript/get_traits_from_collection.js new file mode 100644 index 00000000..9ef31088 --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/get_traits_from_collection.js @@ -0,0 +1,20 @@ +// Generated by CoffeeScript 1.6.1 +(function() { + var collection_hover; + + console.log("before get_traits_from_collection"); + + collection_hover = function() { + var this_collection_url; + console.log("Hovering over:", $(this)); + this_collection_url = $(this).find('.collection_name').prop("href"); + this_collection_url += "&json"; + return console.log("this_collection_url", this_collection_url); + }; + + $(function() { + console.log("inside get_traits_from_collection"); + return $(document).on("mouseover", ".collection_line", collection_hover); + }); + +}).call(this); diff --git a/wqflask/wqflask/static/new/javascript/interval_mapping.coffee b/wqflask/wqflask/static/new/javascript/interval_mapping.coffee new file mode 100644 index 00000000..78265f27 --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/interval_mapping.coffee @@ -0,0 +1,293 @@ +$ -> + + class Interval_Map + constructor: (@plot_height, @plot_width) -> + @qtl_results = js_data.qtl_results + console.log("qtl_results are:", @qtl_results) + @chromosomes = js_data.chromosomes + + @total_length = 0 + + @max_chr = @get_max_chr() + + @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') + [@chr_lengths, @cumulative_chr_lengths] = @get_chr_lengths() + + # 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) + @x_max = @total_length + console.log("@x_max: ", @x_max) + console.log("@x_buffer: ", @x_buffer) + @y_max = d3.max(@y_coords) * 1.2 + + @svg = @create_svg() + @plot_coordinates = _.zip(@x_coords, @y_coords, @marker_names) + + @plot_height -= @y_buffer + @create_scales() + console.time('Create graph') + @create_graph() + console.timeEnd('Create graph') + + get_max_chr: () -> + max_chr = 0 + for result in @qtl_results + chr = parseInt(result.chr) + if not _.isNaN(chr) + if chr > max_chr + max_chr = chr + return max_chr + + get_chr_lengths: () -> + ### + #Gets a list of both individual and cumulative (the position of one on the graph + #is its own length plus the lengths of all preceding chromosomes) lengths in order + #to draw the vertical lines separating chromosomes and the chromosome labels + # + ### + + console.log("@chromosomes: ", @chromosomes) + + cumulative_chr_lengths = [] + chr_lengths = [] + total_length = 0 + for key of @chromosomes + this_length = @chromosomes[key] + chr_lengths.push(this_length) + cumulative_chr_lengths.push(total_length + this_length) + total_length += this_length + + console.log("chr_lengths: ", chr_lengths) + + return [chr_lengths, cumulative_chr_lengths] + + create_coordinates: () -> + chr_lengths = [] + chr_seen = [] + for result in js_data.qtl_results + if result.locus.chr == "X" + chr_length = parseFloat(@chromosomes[20]) + else + chr_length = parseFloat(@chromosomes[result.locus.chr]) + if not(result.locus.chr in chr_seen) + chr_seen.push(result.locus.chr) + chr_lengths.push(chr_length) + if result.locus.chr != "1" + @total_length += parseFloat(chr_lengths[chr_lengths.length - 2]) + @x_coords.push(@total_length + parseFloat(result.locus.Mb)) + @y_coords.push(result.lrs) + @marker_names.push(result.locus.name) + @total_length += parseFloat(chr_lengths[chr_lengths.length-1]) + #console.log("chr_lengths: ", chr_lengths) + + create_svg: () -> + svg = d3.select("#interval_map") + .append("svg") + .attr("class", "interval_map") + .attr("width", @plot_width+@x_buffer) + .attr("height", @plot_height+@y_buffer) + + return svg + + create_graph: () -> + @add_border() + @add_x_axis() + @add_y_axis() + @add_chr_lines() + @fill_chr_areas() + @add_chr_labels() + @connect_markers() + + 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") + + create_scales: () -> + @x_scale = d3.scale.linear() + .domain([0, d3.max(@x_coords)]) + .range([@x_buffer, @plot_width]) + + @y_scale = d3.scale.linear() + .domain([0, @y_max]) + .range([@plot_height, @y_buffer]) + + create_x_axis_tick_values: () -> + tick_vals = [] + for val in [25..@cumulative_chr_lengths[0]] when val%25 == 0 + tick_vals.push(val) + + for length, i in @cumulative_chr_lengths + if i == 0 + continue + chr_ticks = [] + tick_count = Math.floor(@chr_lengths[i]/25) + tick_val = parseInt(@cumulative_chr_lengths[i-1]) + for tick in [0..(tick_count-1)] + tick_val += 25 + chr_ticks.push(tick_val) + Array::push.apply tick_vals, chr_ticks + + #console.log("tick_vals:", tick_vals) + return tick_vals + + add_x_axis: () -> + xAxis = d3.svg.axis() + .scale(@x_scale) + .orient("bottom") + .tickValues(@create_x_axis_tick_values()) + + next_chr = 1 + tmp_tick_val = 0 + xAxis.tickFormat((d) => + d3.format("d") #format as integer + if d < @cumulative_chr_lengths[0] + tick_val = d + else + next_chr_length = @cumulative_chr_lengths[next_chr] + if d > next_chr_length + next_chr += 1 + tmp_tick_val = 25 + tick_val = tmp_tick_val + else + tmp_tick_val += 25 + tick_val = tmp_tick_val + return (tick_val) + ) + + @svg.append("g") + .attr("class", "x_axis") + .attr("transform", "translate(0," + @plot_height + ")") + .call(xAxis) + .selectAll("text") + .attr("text-anchor", "right") + .attr("dx", "-1.6em") + .attr("transform", (d) => + return "translate(-12,0) rotate(-90)" + ) + #.attr("dy", "-1.0em") + + + 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_chr_lines: () -> + @svg.selectAll("line") + .data(@cumulative_chr_lengths, (d) => + return d + ) + .enter() + .append("line") + .attr("x1", @x_scale) + .attr("x2", @x_scale) + .attr("y1", @y_buffer) + .attr("y2", @plot_height) + .style("stroke", "#ccc") + + fill_chr_areas: () -> + @svg.selectAll("rect.chr_fill_area_1") + .data(_.zip(@chr_lengths, @cumulative_chr_lengths), (d) => + return d + ) + .enter() + .append("rect") + .attr("class", "chr_fill_area_1") + .attr("x", (d, i) => + if i == 0 + return @x_scale(0) + else + return @x_scale(@cumulative_chr_lengths[i-1]) + ) + .attr("y", @y_buffer) + .attr("width", (d) => + return @x_scale(d[0]) + ) + .attr("height", @plot_height-@y_buffer) + + add_chr_labels: () -> + chr_names = [] + for key of @chromosomes + chr_names.push(key) + chr_info = _.zip(chr_names, @chr_lengths, @cumulative_chr_lengths) + @svg.selectAll("text") + .data(chr_info, (d) => + return d + ) + .enter() + .append("text") + .text((d) => + return d[0] + ) + .attr("x", (d) => + return @x_scale(d[2] - d[1]/2) + ) + .attr("y", @plot_height * 0.1) + .attr("dx", "0em") + .attr("text-anchor", "middle") + .attr("font-family", "sans-serif") + .attr("font-size", "18px") + .attr("fill", "grey") + + connect_markers: () -> + @svg.selectAll("path") + .data(@plot_coordinates) + .enter() + .attr("x1", (d, i) => + if i == 0 + return @x_buffer + else + return parseFloat(@x_buffer) + ((parseFloat(@plot_width)-parseFloat(@x_buffer)) * @plot_coordinates[i-1][0]/parseFloat(@x_max)) + ) + .attr("y1", (d, i) => + if i == 0 + return @plot_height + else + return @plot_height - ((@plot_height-@y_buffer) * @plot_coordinates[i-1][1]/@y_max) + ) + .attr("x2", (d) => + return parseFloat(@x_buffer) + ((parseFloat(@plot_width)-parseFloat(@x_buffer)) * d[0]/parseFloat(@x_max)) + ) + .attr("y2", (d) => + return @plot_height - ((@plot_height-@y_buffer) * d[1]/@y_max) + ) + + console.time('Create manhattan plot') + new Interval_Map(600, 1200) + console.timeEnd('Create manhattan plot') \ No newline at end of file diff --git a/wqflask/wqflask/static/new/javascript/interval_mapping.js b/wqflask/wqflask/static/new/javascript/interval_mapping.js new file mode 100644 index 00000000..5ae8ffab --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/interval_mapping.js @@ -0,0 +1,272 @@ +// Generated by CoffeeScript 1.6.1 +(function() { + var __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; }; + + $(function() { + var Interval_Map; + Interval_Map = (function() { + + function Interval_Map(plot_height, plot_width) { + var _ref; + this.plot_height = plot_height; + this.plot_width = plot_width; + this.qtl_results = js_data.qtl_results; + console.log("qtl_results are:", this.qtl_results); + this.chromosomes = js_data.chromosomes; + this.total_length = 0; + this.max_chr = this.get_max_chr(); + 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'); + _ref = this.get_chr_lengths(), this.chr_lengths = _ref[0], this.cumulative_chr_lengths = _ref[1]; + this.x_buffer = this.plot_width / 30; + this.y_buffer = this.plot_height / 20; + this.x_max = this.total_length; + console.log("@x_max: ", this.x_max); + console.log("@x_buffer: ", this.x_buffer); + this.y_max = d3.max(this.y_coords) * 1.2; + this.svg = this.create_svg(); + this.plot_coordinates = _.zip(this.x_coords, this.y_coords, this.marker_names); + this.plot_height -= this.y_buffer; + this.create_scales(); + console.time('Create graph'); + this.create_graph(); + console.timeEnd('Create graph'); + } + + Interval_Map.prototype.get_max_chr = function() { + var chr, max_chr, result, _i, _len, _ref; + max_chr = 0; + _ref = this.qtl_results; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + result = _ref[_i]; + chr = parseInt(result.chr); + if (!_.isNaN(chr)) { + if (chr > max_chr) { + max_chr = chr; + } + } + } + return max_chr; + }; + + Interval_Map.prototype.get_chr_lengths = function() { + /* + #Gets a list of both individual and cumulative (the position of one on the graph + #is its own length plus the lengths of all preceding chromosomes) lengths in order + #to draw the vertical lines separating chromosomes and the chromosome labels + # + */ + + var chr_lengths, cumulative_chr_lengths, key, this_length, total_length; + console.log("@chromosomes: ", this.chromosomes); + cumulative_chr_lengths = []; + chr_lengths = []; + total_length = 0; + for (key in this.chromosomes) { + this_length = this.chromosomes[key]; + chr_lengths.push(this_length); + cumulative_chr_lengths.push(total_length + this_length); + total_length += this_length; + } + console.log("chr_lengths: ", chr_lengths); + return [chr_lengths, cumulative_chr_lengths]; + }; + + Interval_Map.prototype.create_coordinates = function() { + var chr_length, chr_lengths, chr_seen, result, _i, _len, _ref, _ref1; + chr_lengths = []; + chr_seen = []; + _ref = js_data.qtl_results; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + result = _ref[_i]; + if (result.locus.chr === "X") { + chr_length = parseFloat(this.chromosomes[20]); + } else { + chr_length = parseFloat(this.chromosomes[result.locus.chr]); + } + if (!(_ref1 = result.locus.chr, __indexOf.call(chr_seen, _ref1) >= 0)) { + chr_seen.push(result.locus.chr); + chr_lengths.push(chr_length); + if (result.locus.chr !== "1") { + this.total_length += parseFloat(chr_lengths[chr_lengths.length - 2]); + } + } + this.x_coords.push(this.total_length + parseFloat(result.locus.Mb)); + this.y_coords.push(result.lrs); + this.marker_names.push(result.locus.name); + } + return this.total_length += parseFloat(chr_lengths[chr_lengths.length - 1]); + }; + + Interval_Map.prototype.create_svg = function() { + var svg; + svg = d3.select("#interval_map").append("svg").attr("class", "interval_map").attr("width", this.plot_width + this.x_buffer).attr("height", this.plot_height + this.y_buffer); + return svg; + }; + + Interval_Map.prototype.create_graph = function() { + this.add_border(); + this.add_x_axis(); + this.add_y_axis(); + this.add_chr_lines(); + this.fill_chr_areas(); + this.add_chr_labels(); + return this.connect_markers(); + }; + + Interval_Map.prototype.add_border = function() { + var border_coords, + _this = this; + 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(d) { + return d[0]; + }).attr("y2", function(d) { + return d[1]; + }).attr("x1", function(d) { + return d[2]; + }).attr("x2", function(d) { + return d[3]; + }).style("stroke", "#000"); + }; + + Interval_Map.prototype.create_scales = function() { + this.x_scale = d3.scale.linear().domain([0, d3.max(this.x_coords)]).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]); + }; + + Interval_Map.prototype.create_x_axis_tick_values = function() { + var chr_ticks, i, length, tick, tick_count, tick_val, tick_vals, val, _i, _j, _k, _len, _ref, _ref1, _ref2; + tick_vals = []; + for (val = _i = 25, _ref = this.cumulative_chr_lengths[0]; 25 <= _ref ? _i <= _ref : _i >= _ref; val = 25 <= _ref ? ++_i : --_i) { + if (val % 25 === 0) { + tick_vals.push(val); + } + } + _ref1 = this.cumulative_chr_lengths; + for (i = _j = 0, _len = _ref1.length; _j < _len; i = ++_j) { + length = _ref1[i]; + if (i === 0) { + continue; + } + chr_ticks = []; + tick_count = Math.floor(this.chr_lengths[i] / 25); + tick_val = parseInt(this.cumulative_chr_lengths[i - 1]); + for (tick = _k = 0, _ref2 = tick_count - 1; 0 <= _ref2 ? _k <= _ref2 : _k >= _ref2; tick = 0 <= _ref2 ? ++_k : --_k) { + tick_val += 25; + chr_ticks.push(tick_val); + } + Array.prototype.push.apply(tick_vals, chr_ticks); + } + return tick_vals; + }; + + Interval_Map.prototype.add_x_axis = function() { + var next_chr, tmp_tick_val, xAxis, + _this = this; + xAxis = d3.svg.axis().scale(this.x_scale).orient("bottom").tickValues(this.create_x_axis_tick_values()); + next_chr = 1; + tmp_tick_val = 0; + xAxis.tickFormat(function(d) { + var next_chr_length, tick_val; + d3.format("d"); + if (d < _this.cumulative_chr_lengths[0]) { + tick_val = d; + } else { + next_chr_length = _this.cumulative_chr_lengths[next_chr]; + if (d > next_chr_length) { + next_chr += 1; + tmp_tick_val = 25; + tick_val = tmp_tick_val; + } else { + tmp_tick_val += 25; + tick_val = tmp_tick_val; + } + } + return tick_val; + }); + return this.svg.append("g").attr("class", "x_axis").attr("transform", "translate(0," + this.plot_height + ")").call(xAxis).selectAll("text").attr("text-anchor", "right").attr("dx", "-1.6em").attr("transform", function(d) { + return "translate(-12,0) rotate(-90)"; + }); + }; + + Interval_Map.prototype.add_y_axis = function() { + var yAxis; + 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(yAxis); + }; + + Interval_Map.prototype.add_chr_lines = function() { + var _this = this; + return this.svg.selectAll("line").data(this.cumulative_chr_lengths, function(d) { + return d; + }).enter().append("line").attr("x1", this.x_scale).attr("x2", this.x_scale).attr("y1", this.y_buffer).attr("y2", this.plot_height).style("stroke", "#ccc"); + }; + + Interval_Map.prototype.fill_chr_areas = function() { + var _this = this; + return this.svg.selectAll("rect.chr_fill_area_1").data(_.zip(this.chr_lengths, this.cumulative_chr_lengths), function(d) { + return d; + }).enter().append("rect").attr("class", "chr_fill_area_1").attr("x", function(d, i) { + if (i === 0) { + return _this.x_scale(0); + } else { + return _this.x_scale(_this.cumulative_chr_lengths[i - 1]); + } + }).attr("y", this.y_buffer).attr("width", function(d) { + return _this.x_scale(d[0]); + }).attr("height", this.plot_height - this.y_buffer); + }; + + Interval_Map.prototype.add_chr_labels = function() { + var chr_info, chr_names, key, + _this = this; + chr_names = []; + for (key in this.chromosomes) { + chr_names.push(key); + } + chr_info = _.zip(chr_names, this.chr_lengths, this.cumulative_chr_lengths); + return this.svg.selectAll("text").data(chr_info, function(d) { + return d; + }).enter().append("text").text(function(d) { + return d[0]; + }).attr("x", function(d) { + return _this.x_scale(d[2] - d[1] / 2); + }).attr("y", this.plot_height * 0.1).attr("dx", "0em").attr("text-anchor", "middle").attr("font-family", "sans-serif").attr("font-size", "18px").attr("fill", "grey"); + }; + + Interval_Map.prototype.connect_markers = function() { + var _this = this; + return this.svg.selectAll("path").data(this.plot_coordinates).enter().attr("x1", function(d, i) { + if (i === 0) { + return _this.x_buffer; + } else { + return parseFloat(_this.x_buffer) + ((parseFloat(_this.plot_width) - parseFloat(_this.x_buffer)) * _this.plot_coordinates[i - 1][0] / parseFloat(_this.x_max)); + } + }).attr("y1", function(d, i) { + if (i === 0) { + return _this.plot_height; + } else { + return _this.plot_height - ((_this.plot_height - _this.y_buffer) * _this.plot_coordinates[i - 1][1] / _this.y_max); + } + }).attr("x2", function(d) { + return parseFloat(_this.x_buffer) + ((parseFloat(_this.plot_width) - parseFloat(_this.x_buffer)) * d[0] / parseFloat(_this.x_max)); + }).attr("y2", function(d) { + return _this.plot_height - ((_this.plot_height - _this.y_buffer) * d[1] / _this.y_max); + }); + }; + + return Interval_Map; + + })(); + console.time('Create manhattan plot'); + new Interval_Map(600, 1200); + return console.timeEnd('Create manhattan plot'); + }); + +}).call(this); diff --git a/wqflask/wqflask/static/new/javascript/scientific_notation.js b/wqflask/wqflask/static/new/javascript/scientific_notation.js new file mode 100644 index 00000000..82c55fda --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/scientific_notation.js @@ -0,0 +1,13 @@ +jQuery.extend( jQuery.fn.dataTableExt.oSort, { + "scientific-pre": function ( a ) { + return parseFloat(a); + }, + + "scientific-asc": function ( a, b ) { + return ((a < b) ? -1 : ((a > b) ? 1 : 0)); + }, + + "scientific-desc": function ( a, b ) { + return ((a < b) ? 1 : ((a > b) ? -1 : 0)); + } +} ); \ No newline at end of file diff --git a/wqflask/wqflask/static/new/packages/DataTables/js/dataTables.scientific.js b/wqflask/wqflask/static/new/packages/DataTables/js/dataTables.scientific.js new file mode 100644 index 00000000..82c55fda --- /dev/null +++ b/wqflask/wqflask/static/new/packages/DataTables/js/dataTables.scientific.js @@ -0,0 +1,13 @@ +jQuery.extend( jQuery.fn.dataTableExt.oSort, { + "scientific-pre": function ( a ) { + return parseFloat(a); + }, + + "scientific-asc": function ( a, b ) { + return ((a < b) ? -1 : ((a > b) ? 1 : 0)); + }, + + "scientific-desc": function ( a, b ) { + return ((a < b) ? 1 : ((a > b) ? -1 : 0)); + } +} ); \ No newline at end of file diff --git a/wqflask/wqflask/templates/base.html b/wqflask/wqflask/templates/base.html index ea6db646..9b98c955 100644 --- a/wqflask/wqflask/templates/base.html +++ b/wqflask/wqflask/templates/base.html @@ -198,7 +198,7 @@ <!--</div>--> </div> - <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> + <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <script src="/static/packages/bootstrap/js/bootstrap.min.js"></script> <script> //http://stackoverflow.com/questions/11521763/bootstrap-scrollspy-not-working diff --git a/wqflask/wqflask/templates/collections/list.html b/wqflask/wqflask/templates/collections/list.html index dce7d41d..ac621a61 100644 --- a/wqflask/wqflask/templates/collections/list.html +++ b/wqflask/wqflask/templates/collections/list.html @@ -5,6 +5,7 @@ {{ header("Your Collections", 'You have {}.'.format(numify(user_collections|count, "collection", "collections"))) }} + <div class="container"> <div class="page-header"> <h1>Collections owned by {{ g.user_session.user_ob.full_name }}</h1> @@ -23,8 +24,8 @@ <tbody> {% for uc in user_collections %} - <tr> - <td><a href="{{ url_for('view_collection', uc_id=uc.id) }}">{{ uc.name }}</a></td> + <tr class="collection_line"> + <td><a class="collection_name" href="{{ url_for('view_collection', uc_id=uc.id) }}">{{ uc.name }}</a></td> <td>{{ timeago(uc.created_timestamp.isoformat() + "Z") }}</td> <td>{{ timeago(uc.changed_timestamp.isoformat() + "Z") }}</td> <td>{{ uc.num_members }}</td> @@ -33,6 +34,10 @@ </tbody> </table> + {# if "color_by_trait" in params #} + <script type="text/javascript" src="/static/new/javascript/get_traits_from_collection.js"></script> + {# endif #} + </div> </div> @@ -41,10 +46,8 @@ {% endblock %} {% block js %} - <script type="text/javascript" src="/static/packages/smart-time-ago/lib/timeago.js"></script> <script> $('body').timeago(); </script> - {% endblock %} diff --git a/wqflask/wqflask/templates/interval_mapping.html b/wqflask/wqflask/templates/interval_mapping.html new file mode 100644 index 00000000..25de2dc1 --- /dev/null +++ b/wqflask/wqflask/templates/interval_mapping.html @@ -0,0 +1,104 @@ +{% extends "base.html" %} +{% block title %}Interval Mapping{% endblock %} +{% block css %} + <link rel="stylesheet" type="text/css" href="/static/packages/jqplot/jquery.jqplot.min.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" /> +{% 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> + </div> + <div id="interval_map" class="interval_map"> + + </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>Additive Effect</td> + <td>Chr</td> + <td>Mb</td> + <td>Locus</td> + </tr> + </thead> + <tbody> + {% for marker in qtl_results %} + <tr> + <td>{{ loop.index }}</td> + <td>{{ marker.lrs|float }}</td> + <td>{{ marker.additive|float }}</td> + <td>{{ marker.locus.chr|int }}</td> + <td>{{ marker.locus.Mb|float }}</td> + <td>{{ marker.locus.name }}</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/javascript/interval_mapping.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/show_trait.html b/wqflask/wqflask/templates/show_trait.html index 91e6df42..ec729e1c 100644 --- a/wqflask/wqflask/templates/show_trait.html +++ b/wqflask/wqflask/templates/show_trait.html @@ -57,6 +57,7 @@ <script type="text/javascript" src="/static/new/javascript/box.js"></script> <script type="text/javascript" src="/static/new/javascript/bar_chart.js"></script> <script type="text/javascript" src="/static/new/javascript/box_plot.js"></script> + <script type="text/javascript" src="/static/new/javascript/get_traits_from_collection.js"></script> <script type="text/javascript" src="/static/new/javascript/show_trait.js"></script> <script type="text/javascript" src="/static/new/javascript/show_trait_mapping_tools.js"></script> <script type="text/javascript" src="/static/new/javascript/validation.js"></script> diff --git a/wqflask/wqflask/templates/show_trait_mapping_tools.html b/wqflask/wqflask/templates/show_trait_mapping_tools.html index 00301d39..a835a41b 100644 --- a/wqflask/wqflask/templates/show_trait_mapping_tools.html +++ b/wqflask/wqflask/templates/show_trait_mapping_tools.html @@ -20,6 +20,7 @@ <label for="chromosome" class="control-label">Chromosome</label> <div class="controls"> <select name="chromosome"> + <option value="-1">All</option> {% for name, value in dataset.species.chromosomes.chromosomes.items() %} <option value="{{ value }}">{{ name }}</option> {% endfor %} diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py index 50161d41..b528f2b1 100644 --- a/wqflask/wqflask/views.py +++ b/wqflask/wqflask/views.py @@ -213,7 +213,7 @@ def marker_regression_page(): if key in wanted or key.startswith(('value:')): start_vars[key] = value - version = "v14" + version = "v1" key = "marker_regression:{}:".format(version) + json.dumps(start_vars, sort_keys=True) print("key is:", pf(key)) with Bench("Loading cache"): @@ -237,8 +237,10 @@ def marker_regression_page(): result = template_vars.__dict__ - #for item in template_vars.__dict__.keys(): - # print(" ---**--- {}: {}".format(type(template_vars.__dict__[item]), item)) + print("DATASET:", pf(result['dataset'])) + + for item in template_vars.__dict__.keys(): + print(" ---**--- {}: {}".format(type(template_vars.__dict__[item]), item)) #causeerror Redis.set(key, pickle.dumps(result, pickle.HIGHEST_PROTOCOL)) @@ -268,7 +270,7 @@ def interval_mapping_page(): if key in wanted or key.startswith(('value:')): start_vars[key] = value - version = "v1" + version = "v7" key = "interval_mapping:{}:".format(version) + json.dumps(start_vars, sort_keys=True) print("key is:", pf(key)) with Bench("Loading cache"): @@ -288,6 +290,9 @@ def interval_mapping_page(): result = template_vars.__dict__ + for item in template_vars.__dict__.keys(): + print(" ---**--- {}: {}".format(type(template_vars.__dict__[item]), item)) + #causeerror Redis.set(key, pickle.dumps(result, pickle.HIGHEST_PROTOCOL)) Redis.expire(key, 60*60) |