aboutsummaryrefslogtreecommitdiff
path: root/wqflask
diff options
context:
space:
mode:
authorZachary Sloan2013-11-20 20:23:53 +0000
committerZachary Sloan2013-11-20 20:23:53 +0000
commit36cd8acc08477038664fc3532016036f3696f734 (patch)
tree77c8f096a9cb5a111336c7444eea2ce753fb0a1a /wqflask
parentf1e215c78f2d5889cad18d36c1c28623c924b768 (diff)
downloadgenenetwork2-36cd8acc08477038664fc3532016036f3696f734.tar.gz
Created a box plot
Made the bar chart use a gradient if colored by something with more than 6 distinct values Put figures in tabs under the Charts/Figures part of the trait page
Diffstat (limited to 'wqflask')
-rw-r--r--wqflask/wqflask/static/new/css/box_plot.css20
-rw-r--r--wqflask/wqflask/static/new/javascript/bar_chart.coffee100
-rw-r--r--wqflask/wqflask/static/new/javascript/bar_chart.js108
-rw-r--r--wqflask/wqflask/static/new/javascript/box.js307
-rw-r--r--wqflask/wqflask/static/new/javascript/box_plot.coffee50
-rw-r--r--wqflask/wqflask/static/new/javascript/show_trait.coffee389
-rw-r--r--wqflask/wqflask/static/new/javascript/show_trait.js426
-rw-r--r--wqflask/wqflask/templates/show_trait.html2
-rw-r--r--wqflask/wqflask/templates/show_trait_statistics_new.html76
9 files changed, 1396 insertions, 82 deletions
diff --git a/wqflask/wqflask/static/new/css/box_plot.css b/wqflask/wqflask/static/new/css/box_plot.css
new file mode 100644
index 00000000..4c743b33
--- /dev/null
+++ b/wqflask/wqflask/static/new/css/box_plot.css
@@ -0,0 +1,20 @@
+.box {
+ font: 10px sans-serif;
+}
+
+.box line,
+.box rect,
+.box circle {
+ fill: #fff;
+ stroke: #000;
+ stroke-width: 1.5px;
+}
+
+.box .center {
+ stroke-dasharray: 3,3;
+}
+
+.box .outlier {
+ fill: none;
+ stroke: #ccc;
+} \ 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 0ab70e0d..749a7dc0 100644
--- a/wqflask/wqflask/static/new/javascript/bar_chart.coffee
+++ b/wqflask/wqflask/static/new/javascript/bar_chart.coffee
@@ -1,19 +1,17 @@
root = exports ? this
class Bar_Chart
- constructor: (@sample_list, @attribute_names) ->
+ constructor: (@sample_list, @sample_group) ->
@get_samples()
console.log("sample names:", @sample_names)
+ if @sample_attr_vals.length > 0
+ @get_distinct_attr_vals()
+ @get_attr_color_dict()
#Used to calculate the bottom margin so sample names aren't cut off
longest_sample_name = d3.max(sample.length for sample in @sample_names)
- @margin =
- top: 20
- right: 20
- bottom: longest_sample_name * 7
- left: 40
-
+ @margin = {top: 20, right: 20, bottom: longest_sample_name * 7, left: 40}
@plot_width = @sample_vals.length * 15 - @margin.left - @margin.right
@plot_height = 500 - @margin.top - @margin.bottom
@@ -57,6 +55,7 @@ class Bar_Chart
else
return @attr_color_dict[attribute][d[2][attribute]]
)
+ @add_legend(attribute, @distinct_attr_vals[attribute])
)
@@ -79,7 +78,7 @@ class Bar_Chart
return @plot_height - @y_scale(d[1])
)
.style("fill", (d) =>
- if @attributes.length > 0 && attribute != "None"
+ if @attributes.length > 0
return @attr_color_dict[attribute][d[2][attribute]]
else
return "steelblue"
@@ -107,7 +106,7 @@ class Bar_Chart
return @plot_height - @y_scale(d[1])
)
.style("fill", (d) =>
- if @attributes.length > 0 && attribute != "None"
+ if @attributes.length > 0
return @attr_color_dict[attribute][d[2][attribute]]
else
return "steelblue"
@@ -122,23 +121,33 @@ class Bar_Chart
$('.x.axis').remove()
@add_x_axis(x_scale)
)
-
- d3.select("#color_by_trait").on("click", =>
- @color_by_trait()
- )
get_attr_color_dict: () ->
- color = d3.scale.category20()
@attr_color_dict = {}
- console.log("attribute_names:", @attribute_names)
- for own key, attribute_info of @attribute_names
+ console.log("distinct_attr_vals:", @distinct_attr_vals)
+ for own key, distinct_vals of @distinct_attr_vals
this_color_dict = {}
- for value, i in attribute_info.distinct_values
- this_color_dict[value] = color(i)
- @attr_color_dict[attribute_info.name] = this_color_dict
-
-
-
+ if distinct_vals.length < 10
+ color = d3.scale.category10()
+ for value, i in distinct_vals
+ this_color_dict[value] = color(i)
+ else
+ console.log("distinct_values:", distinct_vals)
+ if _.every(distinct_vals, (d) =>
+ if isNaN(d)
+ return false
+ else
+ return true
+ )
+ color_range = d3.scale.linear()
+ .domain([d3.min(distinct_vals),
+ d3.max(distinct_vals)])
+ .range([0,4])
+ for value, i in distinct_vals
+ console.log("color_range(value):", color_range(parseInt(value)))
+ 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
get_samples: () ->
@sample_names = (sample.name for sample in @sample_list when sample.value != null)
@@ -153,8 +162,16 @@ class Bar_Chart
attr_vals[attribute] = sample["extra_attributes"][attribute]
@sample_attr_vals.push(attr_vals)
@samples = _.zip(@sample_names, @sample_vals, @sample_attr_vals)
- @get_attr_color_dict()
- console.log("samples:", @samples)
+
+ get_distinct_attr_vals: () ->
+ @distinct_attr_vals = {}
+ for sample in @sample_attr_vals
+ for attribute of sample
+ if not @distinct_attr_vals[attribute]
+ @distinct_attr_vals[attribute] = []
+ if sample[attribute] not in @distinct_attr_vals[attribute]
+ @distinct_attr_vals[attribute].push(sample[attribute])
+ #console.log("distinct_attr_vals:", @distinct_attr_vals)
create_svg: () ->
svg = d3.select("#bar_chart")
@@ -248,6 +265,41 @@ class Bar_Chart
)
console.log("sorted:", sorted)
return sorted
+
+ add_legend: (attribute, distinct_vals) ->
+ legend = @svg.append("g")
+ .attr("class", "legend")
+ .attr("height", 100)
+ .attr("width", 100)
+ .attr('transform', 'translate(-20,50)')
+
+ legend_rect = legend.selectAll('rect')
+ .data(distinct_vals)
+ .enter()
+ .append("rect")
+ .attr("x", @plot_width - 65)
+ .attr("width", 10)
+ .attr("height", 10)
+ .attr("y", (d, i) =>
+ return i * 20
+ )
+ .style("fill", (d) =>
+ console.log("TEST:", @attr_color_dict[attribute][d])
+ return @attr_color_dict[attribute][d]
+ )
+
+ legend_text = legend.selectAll('text')
+ .data(distinct_vals)
+ .enter()
+ .append("text")
+ .attr("x", @plot_width - 52)
+ .attr("y", (d, i) =>
+ return i*20 + 9
+ )
+ .text((d) =>
+ return d
+ )
+
color_by_trait: () ->
console.log("Before load")
diff --git a/wqflask/wqflask/static/new/javascript/bar_chart.js b/wqflask/wqflask/static/new/javascript/bar_chart.js
index ab011de1..20fab15c 100644
--- a/wqflask/wqflask/static/new/javascript/bar_chart.js
+++ b/wqflask/wqflask/static/new/javascript/bar_chart.js
@@ -1,19 +1,24 @@
// Generated by CoffeeScript 1.6.1
(function() {
var Bar_Chart, root,
- __hasProp = {}.hasOwnProperty;
+ __hasProp = {}.hasOwnProperty,
+ __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; };
root = typeof exports !== "undefined" && exports !== null ? exports : this;
Bar_Chart = (function() {
- function Bar_Chart(sample_list, attribute_names) {
+ function Bar_Chart(sample_list, sample_group) {
var longest_sample_name, sample,
_this = this;
this.sample_list = sample_list;
- this.attribute_names = attribute_names;
+ this.sample_group = sample_group;
this.get_samples();
console.log("sample names:", this.sample_names);
+ if (this.sample_attr_vals.length > 0) {
+ this.get_distinct_attr_vals();
+ this.get_attr_color_dict();
+ }
longest_sample_name = d3.max((function() {
var _i, _len, _ref, _results;
_ref = this.sample_names;
@@ -44,7 +49,7 @@
var attribute;
attribute = $("#color_attribute").val();
if ($("#update_bar_chart").html() === 'Sort By Name') {
- return _this.svg.selectAll(".bar").data(_this.sorted_samples()).transition().duration(1000).style("fill", function(d) {
+ _this.svg.selectAll(".bar").data(_this.sorted_samples()).transition().duration(1000).style("fill", function(d) {
if (attribute === "None") {
return "steelblue";
} else {
@@ -54,7 +59,7 @@
return d[1];
});
} else {
- return _this.svg.selectAll(".bar").data(_this.samples).transition().duration(1000).style("fill", function(d) {
+ _this.svg.selectAll(".bar").data(_this.samples).transition().duration(1000).style("fill", function(d) {
if (attribute === "None") {
return "steelblue";
} else {
@@ -62,6 +67,7 @@
}
});
}
+ return _this.add_legend(attribute, _this.distinct_attr_vals[attribute]);
});
d3.select("#update_bar_chart").on("click", function() {
var attribute, sortItems, sorted_sample_names, x_scale;
@@ -78,7 +84,7 @@
}).attr("height", function(d) {
return _this.plot_height - _this.y_scale(d[1]);
}).style("fill", function(d) {
- if (_this.attributes.length > 0 && attribute !== "None") {
+ if (_this.attributes.length > 0) {
return _this.attr_color_dict[attribute][d[2][attribute]];
} else {
return "steelblue";
@@ -106,7 +112,7 @@
}).attr("height", function(d) {
return _this.plot_height - _this.y_scale(d[1]);
}).style("fill", function(d) {
- if (_this.attributes.length > 0 && attribute !== "None") {
+ if (_this.attributes.length > 0) {
return _this.attr_color_dict[attribute][d[2][attribute]];
} else {
return "steelblue";
@@ -119,28 +125,43 @@
return _this.add_x_axis(x_scale);
}
});
- d3.select("#color_by_trait").on("click", function() {
- return _this.color_by_trait();
- });
}
Bar_Chart.prototype.get_attr_color_dict = function() {
- var attribute_info, color, i, key, this_color_dict, value, _i, _len, _ref, _ref1, _results;
- color = d3.scale.category20();
+ var color, color_range, distinct_vals, i, key, this_color_dict, value, _i, _j, _len, _len1, _ref, _results,
+ _this = this;
this.attr_color_dict = {};
- console.log("attribute_names:", this.attribute_names);
- _ref = this.attribute_names;
+ console.log("distinct_attr_vals:", this.distinct_attr_vals);
+ _ref = this.distinct_attr_vals;
_results = [];
for (key in _ref) {
if (!__hasProp.call(_ref, key)) continue;
- attribute_info = _ref[key];
+ distinct_vals = _ref[key];
this_color_dict = {};
- _ref1 = attribute_info.distinct_values;
- for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) {
- value = _ref1[i];
- this_color_dict[value] = color(i);
+ if (distinct_vals.length < 10) {
+ color = d3.scale.category10();
+ for (i = _i = 0, _len = distinct_vals.length; _i < _len; i = ++_i) {
+ value = distinct_vals[i];
+ this_color_dict[value] = color(i);
+ }
+ } else {
+ console.log("distinct_values:", distinct_vals);
+ if (_.every(distinct_vals, function(d) {
+ if (isNaN(d)) {
+ return false;
+ } else {
+ return true;
+ }
+ })) {
+ color_range = d3.scale.linear().domain([d3.min(distinct_vals), d3.max(distinct_vals)]).range([0, 4]);
+ for (i = _j = 0, _len1 = distinct_vals.length; _j < _len1; i = ++_j) {
+ value = distinct_vals[i];
+ console.log("color_range(value):", color_range(parseInt(value)));
+ this_color_dict[value] = d3.rgb("lightblue").darker(color_range(parseInt(value)));
+ }
+ }
}
- _results.push(this.attr_color_dict[attribute_info.name] = this_color_dict);
+ _results.push(this.attr_color_dict[key] = this_color_dict);
}
return _results;
};
@@ -194,9 +215,33 @@
this.sample_attr_vals.push(attr_vals);
}
}
- this.samples = _.zip(this.sample_names, this.sample_vals, this.sample_attr_vals);
- this.get_attr_color_dict();
- return console.log("samples:", this.samples);
+ return this.samples = _.zip(this.sample_names, this.sample_vals, this.sample_attr_vals);
+ };
+
+ Bar_Chart.prototype.get_distinct_attr_vals = function() {
+ var attribute, sample, _i, _len, _ref, _results;
+ this.distinct_attr_vals = {};
+ _ref = this.sample_attr_vals;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ sample = _ref[_i];
+ _results.push((function() {
+ var _ref1, _results1;
+ _results1 = [];
+ for (attribute in sample) {
+ if (!this.distinct_attr_vals[attribute]) {
+ this.distinct_attr_vals[attribute] = [];
+ }
+ if (_ref1 = sample[attribute], __indexOf.call(this.distinct_attr_vals[attribute], _ref1) < 0) {
+ _results1.push(this.distinct_attr_vals[attribute].push(sample[attribute]));
+ } else {
+ _results1.push(void 0);
+ }
+ }
+ return _results1;
+ }).call(this));
+ }
+ return _results;
};
Bar_Chart.prototype.create_svg = function() {
@@ -255,6 +300,23 @@
return sorted;
};
+ Bar_Chart.prototype.add_legend = function(attribute, distinct_vals) {
+ var legend, legend_rect, legend_text,
+ _this = this;
+ legend = this.svg.append("g").attr("class", "legend").attr("height", 100).attr("width", 100).attr('transform', 'translate(-20,50)');
+ legend_rect = legend.selectAll('rect').data(distinct_vals).enter().append("rect").attr("x", this.plot_width - 65).attr("width", 10).attr("height", 10).attr("y", function(d, i) {
+ return i * 20;
+ }).style("fill", function(d) {
+ console.log("TEST:", _this.attr_color_dict[attribute][d]);
+ return _this.attr_color_dict[attribute][d];
+ });
+ return legend_text = legend.selectAll('text').data(distinct_vals).enter().append("text").attr("x", this.plot_width - 52).attr("y", function(d, i) {
+ return i * 20 + 9;
+ }).text(function(d) {
+ return d;
+ });
+ };
+
Bar_Chart.prototype.color_by_trait = function() {
console.log("Before load");
$('#collections_holder').load('/collections/list #collections_list');
diff --git a/wqflask/wqflask/static/new/javascript/box.js b/wqflask/wqflask/static/new/javascript/box.js
new file mode 100644
index 00000000..aae80f05
--- /dev/null
+++ b/wqflask/wqflask/static/new/javascript/box.js
@@ -0,0 +1,307 @@
+//Taken from http://bl.ocks.org/mbostock/4061502
+
+(function() {
+
+// Inspired by http://informationandvisualization.de/blog/box-plot
+d3.box = function() {
+ var width = 1,
+ height = 1,
+ duration = 0,
+ domain = null,
+ value = Number,
+ whiskers = boxWhiskers,
+ quartiles = boxQuartiles,
+ tickFormat = null;
+
+ // For each small multiple…
+ function box(g) {
+ g.each(function(d, i) {
+ console.log("d:", d)
+ console.log("domain:", domain)
+ d = d.map(value).sort(d3.ascending);
+ var g = d3.select(this),
+ n = d.length,
+ min = d[0],
+ max = d[n - 1];
+
+ // Compute quartiles. Must return exactly 3 elements.
+ var quartileData = d.quartiles = quartiles(d);
+
+ // Compute whiskers. Must return exactly 2 elements, or null.
+ var whiskerIndices = whiskers && whiskers.call(this, d, i),
+ whiskerData = whiskerIndices && whiskerIndices.map(function(i) { return d[i]; });
+
+ // Compute outliers. If no whiskers are specified, all data are "outliers".
+ // We compute the outliers as indices, so that we can join across transitions!
+ var outlierIndices = whiskerIndices
+ ? d3.range(0, whiskerIndices[0]).concat(d3.range(whiskerIndices[1] + 1, n))
+ : d3.range(n);
+
+ // Compute the new x-scale.
+ var x1 = d3.scale.linear()
+ .domain(domain && domain.call(this, d, i) || [min, max])
+ .range([height, 0]);
+
+ // Retrieve the old x-scale, if this is an update.
+ var x0 = this.__chart__ || d3.scale.linear()
+ .domain([0, Infinity])
+ .range(x1.range());
+
+ // Stash the new scale.
+ this.__chart__ = x1;
+
+ // Note: the box, median, and box tick elements are fixed in number,
+ // so we only have to handle enter and update. In contrast, the outliers
+ // and other elements are variable, so we need to exit them! Variable
+ // elements also fade in and out.
+
+ // Update center line: the vertical line spanning the whiskers.
+ var center = g.selectAll("line.center")
+ .data(whiskerData ? [whiskerData] : []);
+
+ center.enter().insert("line", "rect")
+ .attr("class", "center")
+ .attr("x1", width / 2)
+ .attr("y1", function(d) { return x0(d[0]); })
+ .attr("x2", width / 2)
+ .attr("y2", function(d) { return x0(d[1]); })
+ .style("opacity", 1e-6)
+ .transition()
+ .duration(duration)
+ .style("opacity", 1)
+ .attr("y1", function(d) { return x1(d[0]); })
+ .attr("y2", function(d) { return x1(d[1]); });
+
+ center.transition()
+ .duration(duration)
+ .style("opacity", 1)
+ .attr("y1", function(d) { return x1(d[0]); })
+ .attr("y2", function(d) { return x1(d[1]); });
+
+ center.exit().transition()
+ .duration(duration)
+ .style("opacity", 1e-6)
+ .attr("y1", function(d) { return x1(d[0]); })
+ .attr("y2", function(d) { return x1(d[1]); })
+ .remove();
+
+ // Update innerquartile box.
+ var box = g.selectAll("rect.box")
+ .data([quartileData]);
+
+ box.enter().append("rect")
+ .attr("class", "box")
+ .attr("x", 0)
+ .attr("y", function(d) { return x0(d[2]); })
+ .attr("width", width)
+ .attr("height", function(d) { return x0(d[0]) - x0(d[2]); })
+ .transition()
+ .duration(duration)
+ .attr("y", function(d) { return x1(d[2]); })
+ .attr("height", function(d) { return x1(d[0]) - x1(d[2]); });
+
+ box.transition()
+ .duration(duration)
+ .attr("y", function(d) { return x1(d[2]); })
+ .attr("height", function(d) { return x1(d[0]) - x1(d[2]); });
+
+ // Update median line.
+ var medianLine = g.selectAll("line.median")
+ .data([quartileData[1]]);
+
+ medianLine.enter().append("line")
+ .attr("class", "median")
+ .attr("x1", 0)
+ .attr("y1", x0)
+ .attr("x2", width)
+ .attr("y2", x0)
+ .transition()
+ .duration(duration)
+ .attr("y1", x1)
+ .attr("y2", x1);
+
+ medianLine.transition()
+ .duration(duration)
+ .attr("y1", x1)
+ .attr("y2", x1);
+
+ // Update whiskers.
+ var whisker = g.selectAll("line.whisker")
+ .data(whiskerData || []);
+
+ whisker.enter().insert("line", "circle, text")
+ .attr("class", "whisker")
+ .attr("x1", 0)
+ .attr("y1", x0)
+ .attr("x2", width)
+ .attr("y2", x0)
+ .style("opacity", 1e-6)
+ .transition()
+ .duration(duration)
+ .attr("y1", x1)
+ .attr("y2", x1)
+ .style("opacity", 1);
+
+ whisker.transition()
+ .duration(duration)
+ .attr("y1", x1)
+ .attr("y2", x1)
+ .style("opacity", 1);
+
+ whisker.exit().transition()
+ .duration(duration)
+ .attr("y1", x1)
+ .attr("y2", x1)
+ .style("opacity", 1e-6)
+ .remove();
+
+ // Update outliers.
+ var outlier = g.selectAll("circle.outlier")
+ .data(outlierIndices, Number);
+
+ outlier.enter().insert("circle", "text")
+ .attr("class", "outlier")
+ .attr("r", 5)
+ .attr("cx", width / 2)
+ .attr("cy", function(i) { return x0(d[i]); })
+ .style("opacity", 1e-6)
+ .transition()
+ .duration(duration)
+ .attr("cy", function(i) { return x1(d[i]); })
+ .style("opacity", 1);
+
+ outlier.transition()
+ .duration(duration)
+ .attr("cy", function(i) { return x1(d[i]); })
+ .style("opacity", 1);
+
+ outlier.exit().transition()
+ .duration(duration)
+ .attr("cy", function(i) { return x1(d[i]); })
+ .style("opacity", 1e-6)
+ .remove();
+
+ // Compute the tick format.
+ var format = tickFormat || x1.tickFormat(8);
+
+ // Update box ticks.
+ var boxTick = g.selectAll("text.box")
+ .data(quartileData);
+
+ console.log("quartileData:", quartileData);
+
+ boxTick.enter().append("text")
+ .attr("class", "box")
+ .attr("dy", ".3em")
+ .attr("dx", function(d, i) { return i & 1 ? 6 : -6 })
+ .attr("x", function(d, i) { return i & 1 ? width : 0 })
+ .attr("y", x0)
+ .attr("text-anchor", function(d, i) { return i & 1 ? "start" : "end"; })
+ .text(format)
+ .transition()
+ .duration(duration)
+ .attr("y", x1);
+
+ boxTick.transition()
+ .duration(duration)
+ .text(format)
+ .attr("y", x1);
+
+ // Update whisker ticks. These are handled separately from the box
+ // ticks because they may or may not exist, and we want don't want
+ // to join box ticks pre-transition with whisker ticks post-.
+ var whiskerTick = g.selectAll("text.whisker")
+ .data(whiskerData || []);
+
+ whiskerTick.enter().append("text")
+ .attr("class", "whisker")
+ .attr("dy", ".3em")
+ .attr("dx", 6)
+ .attr("x", width)
+ .attr("y", x0)
+ .text(format)
+ .style("opacity", 1e-6)
+ .transition()
+ .duration(duration)
+ .attr("y", x1)
+ .style("opacity", 1);
+
+ whiskerTick.transition()
+ .duration(duration)
+ .text(format)
+ .attr("y", x1)
+ .style("opacity", 1);
+
+ whiskerTick.exit().transition()
+ .duration(duration)
+ .attr("y", x1)
+ .style("opacity", 1e-6)
+ .remove();
+ });
+ d3.timer.flush();
+ }
+
+ box.width = function(x) {
+ if (!arguments.length) return width;
+ width = x;
+ return box;
+ };
+
+ box.height = function(x) {
+ if (!arguments.length) return height;
+ height = x;
+ return box;
+ };
+
+ box.tickFormat = function(x) {
+ if (!arguments.length) return tickFormat;
+ tickFormat = x;
+ return box;
+ };
+
+ box.duration = function(x) {
+ if (!arguments.length) return duration;
+ duration = x;
+ return box;
+ };
+
+ box.domain = function(x) {
+ if (!arguments.length) return domain;
+ domain = x == null ? x : d3.functor(x);
+ return box;
+ };
+
+ box.value = function(x) {
+ if (!arguments.length) return value;
+ value = x;
+ return box;
+ };
+
+ box.whiskers = function(x) {
+ if (!arguments.length) return whiskers;
+ whiskers = x;
+ return box;
+ };
+
+ box.quartiles = function(x) {
+ if (!arguments.length) return quartiles;
+ quartiles = x;
+ return box;
+ };
+
+ return box;
+};
+
+function boxWhiskers(d) {
+ return [0, d.length - 1];
+}
+
+function boxQuartiles(d) {
+ return [
+ d3.quantile(d, .25),
+ d3.quantile(d, .5),
+ d3.quantile(d, .75)
+ ];
+}
+
+})(); \ No newline at end of file
diff --git a/wqflask/wqflask/static/new/javascript/box_plot.coffee b/wqflask/wqflask/static/new/javascript/box_plot.coffee
new file mode 100644
index 00000000..562bd1dc
--- /dev/null
+++ b/wqflask/wqflask/static/new/javascript/box_plot.coffee
@@ -0,0 +1,50 @@
+root = exports ? this
+
+class Box_Plot
+ constructor: (@sample_list, @sample_group) ->
+ @get_samples()
+
+ @margin = {top: 10, right: 50, bottom: 20, left: 50}
+ @plot_width = 120 - @margin.left - @margin.right
+ @plot_height = 500 - @margin.top - @margin.bottom
+
+ @min = d3.min(@sample_vals)
+ @max = d3.max(@sample_vals) * 1.1
+
+ @svg = @create_svg()
+
+ @enter_data()
+
+
+ get_samples: () ->
+ @sample_names = (sample.name for sample in @sample_list when sample.value != null)
+ @sample_vals = (sample.value for sample in @sample_list when sample.value != null)
+ @samples = _.zip(@sample_names, @sample_vals)
+
+ create_svg: () -> d3.chart.box()
+ .whiskers(@inter_quartile_range(1.5))
+ .width(@plot_width)
+ .height(@plot_height)
+ .domain([@min, @max])
+
+ enter_data: () ->
+ d3.select("#box_plot").selectAll("svg")
+ .data(@sample_vals)
+ .enter().append("svg:svg")
+ .attr("class", "box")
+ .attr("width", @plot_width)
+ .attr("height", @plot_height)
+ .call(@svg)
+
+ inter_quartile_range: (k) ->
+ return (d, i) =>
+ q1 = d.quartiles[0],
+ q3 = d.quartiles[2],
+ inter_quartile_range = (q3 - q1) * k
+ i = -1
+ j = d.length
+ while (d[++i] < q1 - inter_quartile_range)
+ while (d[--j] > q3 + inter_quartile_range)
+ return [i, j]
+
+ \ No newline at end of file
diff --git a/wqflask/wqflask/static/new/javascript/show_trait.coffee b/wqflask/wqflask/static/new/javascript/show_trait.coffee
index 55eb1f56..8bcca85d 100644
--- a/wqflask/wqflask/static/new/javascript/show_trait.coffee
+++ b/wqflask/wqflask/static/new/javascript/show_trait.coffee
@@ -59,25 +59,404 @@ Stat_Table_Rows = [
]
$ ->
+ class Bar_Chart
+ constructor: (@sample_list, @sample_group) ->
+ @get_samples()
+ console.log("sample names:", @sample_names)
+ if @sample_attr_vals.length > 0
+ @get_distinct_attr_vals()
+ @get_attr_color_dict()
+
+ #Used to calculate the bottom margin so sample names aren't cut off
+ longest_sample_name = d3.max(sample.length for sample in @sample_names)
+
+ @margin = {top: 20, right: 20, bottom: longest_sample_name * 7, left: 40}
+ @plot_width = @sample_vals.length * 15 - @margin.left - @margin.right
+ @plot_height = 500 - @margin.top - @margin.bottom
+
+ @x_buffer = @plot_width/20
+ @y_buffer = @plot_height/20
+
+ @y_min = d3.min(@sample_vals)
+ @y_max = d3.max(@sample_vals) * 1.1
+
+ @svg = @create_svg()
+
+ @plot_height -= @y_buffer
+ @create_scales()
+ @create_graph()
+
+ d3.select("#color_attribute").on("change", =>
+ attribute = $("#color_attribute").val()
+ if $("#update_bar_chart").html() == 'Sort By Name'
+ @svg.selectAll(".bar")
+ .data(@sorted_samples())
+ .transition()
+ .duration(1000)
+ .style("fill", (d) =>
+ if attribute == "None"
+ return "steelblue"
+ else
+ return @attr_color_dict[attribute][d[2][attribute]]
+ )
+ .select("title")
+ .text((d) =>
+ return d[1]
+ )
+ else
+ @svg.selectAll(".bar")
+ .data(@samples)
+ .transition()
+ .duration(1000)
+ .style("fill", (d) =>
+ if attribute == "None"
+ return "steelblue"
+ else
+ return @attr_color_dict[attribute][d[2][attribute]]
+ )
+ @add_legend(attribute, @distinct_attr_vals[attribute])
+ )
+
+
+ d3.select("#update_bar_chart").on("click", =>
+ if @attributes.length > 0
+ attribute = $("#color_attribute").val()
+ if $("#update_bar_chart").html() == 'Sort By Value'
+ $("#update_bar_chart").html('Sort By Name')
+ sortItems = (a, b) ->
+ return a[1] - b[1]
+
+ @svg.selectAll(".bar")
+ .data(@sorted_samples())
+ .transition()
+ .duration(1000)
+ .attr("y", (d) =>
+ return @y_scale(d[1])
+ )
+ .attr("height", (d) =>
+ return @plot_height - @y_scale(d[1])
+ )
+ .style("fill", (d) =>
+ if @attributes.length > 0
+ return @attr_color_dict[attribute][d[2][attribute]]
+ else
+ return "steelblue"
+ )
+ .select("title")
+ .text((d) =>
+ return d[1]
+ )
+ sorted_sample_names = (sample[0] for sample in @sorted_samples())
+ x_scale = d3.scale.ordinal()
+ .domain(sorted_sample_names)
+ .rangeBands([0, @plot_width], .1)
+ $('.x.axis').remove()
+ @add_x_axis(x_scale)
+ else
+ $("#update_bar_chart").html('Sort By Value')
+ @svg.selectAll(".bar")
+ .data(@samples)
+ .transition()
+ .duration(1000)
+ .attr("y", (d) =>
+ return @y_scale(d[1])
+ )
+ .attr("height", (d) =>
+ return @plot_height - @y_scale(d[1])
+ )
+ .style("fill", (d) =>
+ if @attributes.length > 0
+ return @attr_color_dict[attribute][d[2][attribute]]
+ else
+ return "steelblue"
+ )
+ .select("title")
+ .text((d) =>
+ return d[1]
+ )
+ x_scale = d3.scale.ordinal()
+ .domain(@sample_names)
+ .rangeBands([0, @plot_width], .1)
+ $('.x.axis').remove()
+ @add_x_axis(x_scale)
+ )
+
+ d3.select("#color_by_trait").on("click", =>
+ @color_by_trait()
+ )
+
+ get_attr_color_dict: () ->
+ @attr_color_dict = {}
+ console.log("distinct_attr_vals:", @distinct_attr_vals)
+ for own key, distinct_vals of @distinct_attr_vals
+ this_color_dict = {}
+ if distinct_vals.length < 10
+ color = d3.scale.category10()
+ for value, i in distinct_vals
+ this_color_dict[value] = color(i)
+ else
+ console.log("distinct_values:", distinct_vals)
+ if _.every(distinct_vals, (d) =>
+ if isNaN(d)
+ return false
+ else
+ return true
+ )
+ color_range = d3.scale.linear()
+ .domain([d3.min(distinct_vals),
+ d3.max(distinct_vals)])
+ .range([0,4])
+ for value, i in distinct_vals
+ console.log("color_range(value):", color_range(parseInt(value)))
+ 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
+
+ get_samples: () ->
+ @sample_names = (sample.name for sample in @sample_list when sample.value != null)
+ @sample_vals = (sample.value for sample in @sample_list when sample.value != null)
+ @attributes = (key for key of @sample_list[0]["extra_attributes"])
+ console.log("attributes:", @attributes)
+ @sample_attr_vals = []
+ if @attributes.length > 0
+ for sample in @sample_list
+ attr_vals = {}
+ for attribute in @attributes
+ attr_vals[attribute] = sample["extra_attributes"][attribute]
+ @sample_attr_vals.push(attr_vals)
+ @samples = _.zip(@sample_names, @sample_vals, @sample_attr_vals)
+
+ get_distinct_attr_vals: () ->
+ @distinct_attr_vals = {}
+ for sample in @sample_attr_vals
+ for attribute of sample
+ if not @distinct_attr_vals[attribute]
+ @distinct_attr_vals[attribute] = []
+ if sample[attribute] not in @distinct_attr_vals[attribute]
+ @distinct_attr_vals[attribute].push(sample[attribute])
+ #console.log("distinct_attr_vals:", @distinct_attr_vals)
+
+ create_svg: () ->
+ svg = d3.select("#bar_chart")
+ .append("svg")
+ .attr("class", "bar_chart")
+ .attr("width", @plot_width + @margin.left + @margin.right)
+ .attr("height", @plot_height + @margin.top + @margin.bottom)
+ .append("g")
+ .attr("transform", "translate(" + @margin.left + "," + @margin.top + ")")
+
+ return svg
+
+ create_scales: () ->
+ @x_scale = d3.scale.ordinal()
+ .domain(@sample_names)
+ .rangeBands([0, @plot_width], .1)
+
+ @y_scale = d3.scale.linear()
+ .domain([@y_min * 0.75, @y_max])
+ .range([@plot_height, @y_buffer])
+
+ create_graph: () ->
+
+ #@add_border()
+ @add_x_axis(@x_scale)
+ @add_y_axis()
+
+ @add_bars()
+
+ add_x_axis: (scale) ->
+ xAxis = d3.svg.axis()
+ .scale(scale)
+ .orient("bottom");
+
+ @svg.append("g")
+ .attr("class", "x axis")
+ .attr("transform", "translate(0," + @plot_height + ")")
+ .call(xAxis)
+ .selectAll("text")
+ .style("text-anchor", "end")
+ .style("font-size", "12px")
+ .attr("dx", "-.8em")
+ .attr("dy", "-.3em")
+ .attr("transform", (d) =>
+ return "rotate(-90)"
+ )
+
+ add_y_axis: () ->
+ yAxis = d3.svg.axis()
+ .scale(@y_scale)
+ .orient("left")
+ .ticks(5)
+
+ @svg.append("g")
+ .attr("class", "y axis")
+ .call(yAxis)
+ .append("text")
+ .attr("transform", "rotate(-90)")
+ .attr("y", 6)
+ .attr("dy", ".71em")
+ .style("text-anchor", "end")
+
+ add_bars: () ->
+ @svg.selectAll(".bar")
+ .data(@samples)
+ .enter().append("rect")
+ .style("fill", "steelblue")
+ .attr("class", "bar")
+ .attr("x", (d) =>
+ return @x_scale(d[0])
+ )
+ .attr("width", @x_scale.rangeBand())
+ .attr("y", (d) =>
+ return @y_scale(d[1])
+ )
+ .attr("height", (d) =>
+ return @plot_height - @y_scale(d[1])
+ )
+ .append("svg:title")
+ .text((d) =>
+ return d[1]
+ )
+
+ sorted_samples: () ->
+ #if @sample_attr_vals.length > 0
+ sample_list = _.zip(@sample_names, @sample_vals, @sample_attr_vals)
+ #else
+ # sample_list = _.zip(@sample_names, @sample_vals)
+ sorted = _.sortBy(sample_list, (sample) =>
+ return sample[1]
+ )
+ console.log("sorted:", sorted)
+ return sorted
+
+ add_legend: (attribute, distinct_vals) ->
+ legend = @svg.append("g")
+ .attr("class", "legend")
+ .attr("height", 100)
+ .attr("width", 100)
+ .attr('transform', 'translate(-20,50)')
+
+ legend_rect = legend.selectAll('rect')
+ .data(distinct_vals)
+ .enter()
+ .append("rect")
+ .attr("x", @plot_width - 65)
+ .attr("width", 10)
+ .attr("height", 10)
+ .attr("y", (d, i) =>
+ return i * 20
+ )
+ .style("fill", (d) =>
+ console.log("TEST:", @attr_color_dict[attribute][d])
+ return @attr_color_dict[attribute][d]
+ )
+
+ legend_text = legend.selectAll('text')
+ .data(distinct_vals)
+ .enter()
+ .append("text")
+ .attr("x", @plot_width - 52)
+ .attr("y", (d, i) =>
+ return i*20 + 9
+ )
+ .text((d) =>
+ return d
+ )
+
+ color_by_trait: () ->
+ $('#collections_holder').load('/collections/list #collections_list', =>
+ $.colorbox(
+ inline: true
+ href: "#collections_holder"
+ )
+ )
+
+ class Box_Plot
+ constructor: (@sample_list, @sample_group) ->
+ @get_samples()
+
+ @margin = {top: 10, right: 50, bottom: 20, left: 50}
+ @plot_width = 200 - @margin.left - @margin.right
+ @plot_height = 500 - @margin.top - @margin.bottom
+
+ @min = d3.min(@sample_vals)
+ @max = d3.max(@sample_vals)
+
+ @svg = @create_svg()
+ @enter_data()
+
+
+ get_samples: () ->
+ @sample_vals = (sample.value for sample in @sample_list when sample.value != null)
+
+ create_svg: () ->
+ svg = d3.box()
+ .whiskers(@inter_quartile_range(1.5))
+ .width(@plot_width)
+ .height(@plot_height)
+ .domain([@min, @max])
+ return svg
+
+ enter_data: () ->
+ d3.select("#box_plot").selectAll("svg")
+ .data([@sample_vals])
+ .enter().append("svg:svg")
+ .attr("class", "box")
+ .attr("width", @plot_width)
+ .attr("height", @plot_height)
+ .append("svg:g")
+ .call(@svg)
+
+ inter_quartile_range: (k) ->
+ return (d, i) =>
+ console.log("iqr d:", d)
+ q1 = d.quartiles[0]
+ q3 = d.quartiles[2]
+ inter_quartile_range = (q3 - q1) * k
+ console.log("iqr:", inter_quartile_range)
+ i = 0
+ j = d.length
+ console.log("d[-1]:", d[1])
+ console.log("q1 - iqr:", q1 - inter_quartile_range)
+ i++ while (d[i] < q1 - inter_quartile_range)
+ j-- while (d[j] > q3 + inter_quartile_range)
+ #while (d[++i] < q1 - inter_quartile_range
+ #while d[--j] > q3 + inter_quartile_range
+ console.log("[i, j]", [i, j])
+ return [i, j]
+
sample_lists = js_data.sample_lists
- attribute_names = js_data.attribute_names
sample_group_types = js_data.sample_group_types
- new Bar_Chart(sample_lists[0], attribute_names)
+ new Bar_Chart(sample_lists[0])
+ new Box_Plot(sample_lists[0])
- $('.stats_samples_group').change ->
+
+ $('.bar_chart_samples_group').change ->
$('#bar_chart').remove()
$('#bar_chart_container').append('<div id="bar_chart"></div>')
group = $(this).val()
- console.log("group:", group)
if group == "samples_primary"
new Bar_Chart(sample_lists[0])
else if group == "samples_other"
new Bar_Chart(sample_lists[1])
else if group == "samples_all"
all_samples = sample_lists[0].concat sample_lists[1]
- new HBar_Chart(all_samples)
+ new Bar_Chart(all_samples)
+
+ $('.box_plot_samples_group').change ->
+ $('#box_plot').remove()
+ $('#box_plot_container').append('<div id="box_plot"></div>')
+ group = $(this).val()
+ if group == "samples_primary"
+ new Box_Plot(sample_lists[0])
+ else if group == "samples_other"
+ new Box_Plot(sample_lists[1])
+ else if group == "samples_all"
+ all_samples = sample_lists[0].concat sample_lists[1]
+ new Box_Plot(all_samples)
+
hide_tabs = (start) ->
for x in [start..10]
diff --git a/wqflask/wqflask/static/new/javascript/show_trait.js b/wqflask/wqflask/static/new/javascript/show_trait.js
index c5a6cbd5..b562bfe2 100644
--- a/wqflask/wqflask/static/new/javascript/show_trait.js
+++ b/wqflask/wqflask/static/new/javascript/show_trait.js
@@ -2,6 +2,7 @@
(function() {
var Stat_Table_Rows, is_number,
__hasProp = {}.hasOwnProperty,
+ __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; },
__slice = [].slice;
console.log("start_b");
@@ -56,24 +57,437 @@
];
$(function() {
- var attribute_names, block_by_attribute_value, block_by_index, block_outliers, change_stats_value, create_value_dropdown, edit_data_change, export_sample_table_data, get_sample_table_data, hide_no_value, hide_tabs, make_table, on_corr_method_change, populate_sample_attributes_values_dropdown, process_id, reset_samples_table, sample_group_types, sample_lists, show_hide_outliers, stats_mdp_change, update_stat_values;
+ var Bar_Chart, Box_Plot, block_by_attribute_value, block_by_index, block_outliers, change_stats_value, create_value_dropdown, edit_data_change, export_sample_table_data, get_sample_table_data, hide_no_value, hide_tabs, make_table, on_corr_method_change, populate_sample_attributes_values_dropdown, process_id, reset_samples_table, sample_group_types, sample_lists, show_hide_outliers, stats_mdp_change, update_stat_values;
+ Bar_Chart = (function() {
+
+ function Bar_Chart(sample_list, sample_group) {
+ var longest_sample_name, sample,
+ _this = this;
+ this.sample_list = sample_list;
+ this.sample_group = sample_group;
+ this.get_samples();
+ console.log("sample names:", this.sample_names);
+ if (this.sample_attr_vals.length > 0) {
+ this.get_distinct_attr_vals();
+ this.get_attr_color_dict();
+ }
+ longest_sample_name = d3.max((function() {
+ var _i, _len, _ref, _results;
+ _ref = this.sample_names;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ sample = _ref[_i];
+ _results.push(sample.length);
+ }
+ return _results;
+ }).call(this));
+ this.margin = {
+ top: 20,
+ right: 20,
+ bottom: longest_sample_name * 7,
+ left: 40
+ };
+ this.plot_width = this.sample_vals.length * 15 - this.margin.left - this.margin.right;
+ this.plot_height = 500 - this.margin.top - this.margin.bottom;
+ this.x_buffer = this.plot_width / 20;
+ this.y_buffer = this.plot_height / 20;
+ this.y_min = d3.min(this.sample_vals);
+ this.y_max = d3.max(this.sample_vals) * 1.1;
+ this.svg = this.create_svg();
+ this.plot_height -= this.y_buffer;
+ this.create_scales();
+ this.create_graph();
+ d3.select("#color_attribute").on("change", function() {
+ var attribute;
+ attribute = $("#color_attribute").val();
+ if ($("#update_bar_chart").html() === 'Sort By Name') {
+ _this.svg.selectAll(".bar").data(_this.sorted_samples()).transition().duration(1000).style("fill", function(d) {
+ if (attribute === "None") {
+ return "steelblue";
+ } else {
+ return _this.attr_color_dict[attribute][d[2][attribute]];
+ }
+ }).select("title").text(function(d) {
+ return d[1];
+ });
+ } else {
+ _this.svg.selectAll(".bar").data(_this.samples).transition().duration(1000).style("fill", function(d) {
+ if (attribute === "None") {
+ return "steelblue";
+ } else {
+ return _this.attr_color_dict[attribute][d[2][attribute]];
+ }
+ });
+ }
+ return _this.add_legend(attribute, _this.distinct_attr_vals[attribute]);
+ });
+ d3.select("#update_bar_chart").on("click", function() {
+ var attribute, sortItems, sorted_sample_names, x_scale;
+ if (_this.attributes.length > 0) {
+ attribute = $("#color_attribute").val();
+ }
+ if ($("#update_bar_chart").html() === 'Sort By Value') {
+ $("#update_bar_chart").html('Sort By Name');
+ sortItems = function(a, b) {
+ return a[1] - b[1];
+ };
+ _this.svg.selectAll(".bar").data(_this.sorted_samples()).transition().duration(1000).attr("y", function(d) {
+ return _this.y_scale(d[1]);
+ }).attr("height", function(d) {
+ return _this.plot_height - _this.y_scale(d[1]);
+ }).style("fill", function(d) {
+ if (_this.attributes.length > 0) {
+ return _this.attr_color_dict[attribute][d[2][attribute]];
+ } else {
+ return "steelblue";
+ }
+ }).select("title").text(function(d) {
+ return d[1];
+ });
+ sorted_sample_names = (function() {
+ var _i, _len, _ref, _results;
+ _ref = this.sorted_samples();
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ sample = _ref[_i];
+ _results.push(sample[0]);
+ }
+ return _results;
+ }).call(_this);
+ x_scale = d3.scale.ordinal().domain(sorted_sample_names).rangeBands([0, _this.plot_width], .1);
+ $('.x.axis').remove();
+ return _this.add_x_axis(x_scale);
+ } else {
+ $("#update_bar_chart").html('Sort By Value');
+ _this.svg.selectAll(".bar").data(_this.samples).transition().duration(1000).attr("y", function(d) {
+ return _this.y_scale(d[1]);
+ }).attr("height", function(d) {
+ return _this.plot_height - _this.y_scale(d[1]);
+ }).style("fill", function(d) {
+ if (_this.attributes.length > 0) {
+ return _this.attr_color_dict[attribute][d[2][attribute]];
+ } else {
+ return "steelblue";
+ }
+ }).select("title").text(function(d) {
+ return d[1];
+ });
+ x_scale = d3.scale.ordinal().domain(_this.sample_names).rangeBands([0, _this.plot_width], .1);
+ $('.x.axis').remove();
+ return _this.add_x_axis(x_scale);
+ }
+ });
+ d3.select("#color_by_trait").on("click", function() {
+ return _this.color_by_trait();
+ });
+ }
+
+ Bar_Chart.prototype.get_attr_color_dict = function() {
+ var color, color_range, distinct_vals, i, key, this_color_dict, value, _i, _j, _len, _len1, _ref, _results,
+ _this = this;
+ this.attr_color_dict = {};
+ console.log("distinct_attr_vals:", this.distinct_attr_vals);
+ _ref = this.distinct_attr_vals;
+ _results = [];
+ for (key in _ref) {
+ if (!__hasProp.call(_ref, key)) continue;
+ distinct_vals = _ref[key];
+ this_color_dict = {};
+ if (distinct_vals.length < 10) {
+ color = d3.scale.category10();
+ for (i = _i = 0, _len = distinct_vals.length; _i < _len; i = ++_i) {
+ value = distinct_vals[i];
+ this_color_dict[value] = color(i);
+ }
+ } else {
+ console.log("distinct_values:", distinct_vals);
+ if (_.every(distinct_vals, function(d) {
+ if (isNaN(d)) {
+ return false;
+ } else {
+ return true;
+ }
+ })) {
+ color_range = d3.scale.linear().domain([d3.min(distinct_vals), d3.max(distinct_vals)]).range([0, 4]);
+ for (i = _j = 0, _len1 = distinct_vals.length; _j < _len1; i = ++_j) {
+ value = distinct_vals[i];
+ console.log("color_range(value):", color_range(parseInt(value)));
+ this_color_dict[value] = d3.rgb("lightblue").darker(color_range(parseInt(value)));
+ }
+ }
+ }
+ _results.push(this.attr_color_dict[key] = this_color_dict);
+ }
+ return _results;
+ };
+
+ Bar_Chart.prototype.get_samples = function() {
+ var attr_vals, attribute, key, sample, _i, _j, _len, _len1, _ref, _ref1;
+ this.sample_names = (function() {
+ var _i, _len, _ref, _results;
+ _ref = this.sample_list;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ sample = _ref[_i];
+ if (sample.value !== null) {
+ _results.push(sample.name);
+ }
+ }
+ return _results;
+ }).call(this);
+ this.sample_vals = (function() {
+ var _i, _len, _ref, _results;
+ _ref = this.sample_list;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ sample = _ref[_i];
+ if (sample.value !== null) {
+ _results.push(sample.value);
+ }
+ }
+ return _results;
+ }).call(this);
+ this.attributes = (function() {
+ var _results;
+ _results = [];
+ for (key in this.sample_list[0]["extra_attributes"]) {
+ _results.push(key);
+ }
+ return _results;
+ }).call(this);
+ console.log("attributes:", this.attributes);
+ this.sample_attr_vals = [];
+ if (this.attributes.length > 0) {
+ _ref = this.sample_list;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ sample = _ref[_i];
+ attr_vals = {};
+ _ref1 = this.attributes;
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
+ attribute = _ref1[_j];
+ attr_vals[attribute] = sample["extra_attributes"][attribute];
+ }
+ this.sample_attr_vals.push(attr_vals);
+ }
+ }
+ return this.samples = _.zip(this.sample_names, this.sample_vals, this.sample_attr_vals);
+ };
+
+ Bar_Chart.prototype.get_distinct_attr_vals = function() {
+ var attribute, sample, _i, _len, _ref, _results;
+ this.distinct_attr_vals = {};
+ _ref = this.sample_attr_vals;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ sample = _ref[_i];
+ _results.push((function() {
+ var _ref1, _results1;
+ _results1 = [];
+ for (attribute in sample) {
+ if (!this.distinct_attr_vals[attribute]) {
+ this.distinct_attr_vals[attribute] = [];
+ }
+ if (_ref1 = sample[attribute], __indexOf.call(this.distinct_attr_vals[attribute], _ref1) < 0) {
+ _results1.push(this.distinct_attr_vals[attribute].push(sample[attribute]));
+ } else {
+ _results1.push(void 0);
+ }
+ }
+ return _results1;
+ }).call(this));
+ }
+ return _results;
+ };
+
+ Bar_Chart.prototype.create_svg = function() {
+ var svg;
+ svg = d3.select("#bar_chart").append("svg").attr("class", "bar_chart").attr("width", this.plot_width + this.margin.left + this.margin.right).attr("height", this.plot_height + this.margin.top + this.margin.bottom).append("g").attr("transform", "translate(" + this.margin.left + "," + this.margin.top + ")");
+ return svg;
+ };
+
+ Bar_Chart.prototype.create_scales = function() {
+ this.x_scale = d3.scale.ordinal().domain(this.sample_names).rangeBands([0, this.plot_width], .1);
+ return this.y_scale = d3.scale.linear().domain([this.y_min * 0.75, this.y_max]).range([this.plot_height, this.y_buffer]);
+ };
+
+ Bar_Chart.prototype.create_graph = function() {
+ this.add_x_axis(this.x_scale);
+ this.add_y_axis();
+ return this.add_bars();
+ };
+
+ Bar_Chart.prototype.add_x_axis = function(scale) {
+ var xAxis,
+ _this = this;
+ xAxis = d3.svg.axis().scale(scale).orient("bottom");
+ return this.svg.append("g").attr("class", "x axis").attr("transform", "translate(0," + this.plot_height + ")").call(xAxis).selectAll("text").style("text-anchor", "end").style("font-size", "12px").attr("dx", "-.8em").attr("dy", "-.3em").attr("transform", function(d) {
+ return "rotate(-90)";
+ });
+ };
+
+ Bar_Chart.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").call(yAxis).append("text").attr("transform", "rotate(-90)").attr("y", 6).attr("dy", ".71em").style("text-anchor", "end");
+ };
+
+ Bar_Chart.prototype.add_bars = function() {
+ var _this = this;
+ return this.svg.selectAll(".bar").data(this.samples).enter().append("rect").style("fill", "steelblue").attr("class", "bar").attr("x", function(d) {
+ return _this.x_scale(d[0]);
+ }).attr("width", this.x_scale.rangeBand()).attr("y", function(d) {
+ return _this.y_scale(d[1]);
+ }).attr("height", function(d) {
+ return _this.plot_height - _this.y_scale(d[1]);
+ }).append("svg:title").text(function(d) {
+ return d[1];
+ });
+ };
+
+ Bar_Chart.prototype.sorted_samples = function() {
+ var sample_list, sorted,
+ _this = this;
+ sample_list = _.zip(this.sample_names, this.sample_vals, this.sample_attr_vals);
+ sorted = _.sortBy(sample_list, function(sample) {
+ return sample[1];
+ });
+ console.log("sorted:", sorted);
+ return sorted;
+ };
+
+ Bar_Chart.prototype.add_legend = function(attribute, distinct_vals) {
+ var legend, legend_rect, legend_text,
+ _this = this;
+ legend = this.svg.append("g").attr("class", "legend").attr("height", 100).attr("width", 100).attr('transform', 'translate(-20,50)');
+ legend_rect = legend.selectAll('rect').data(distinct_vals).enter().append("rect").attr("x", this.plot_width - 65).attr("width", 10).attr("height", 10).attr("y", function(d, i) {
+ return i * 20;
+ }).style("fill", function(d) {
+ console.log("TEST:", _this.attr_color_dict[attribute][d]);
+ return _this.attr_color_dict[attribute][d];
+ });
+ return legend_text = legend.selectAll('text').data(distinct_vals).enter().append("text").attr("x", this.plot_width - 52).attr("y", function(d, i) {
+ return i * 20 + 9;
+ }).text(function(d) {
+ return d;
+ });
+ };
+
+ Bar_Chart.prototype.color_by_trait = function() {
+ var _this = this;
+ return $('#collections_holder').load('/collections/list #collections_list', function() {
+ return $.colorbox({
+ inline: true,
+ href: "#collections_holder"
+ });
+ });
+ };
+
+ return Bar_Chart;
+
+ })();
+ Box_Plot = (function() {
+
+ function Box_Plot(sample_list, sample_group) {
+ this.sample_list = sample_list;
+ this.sample_group = sample_group;
+ this.get_samples();
+ this.margin = {
+ top: 10,
+ right: 50,
+ bottom: 20,
+ left: 50
+ };
+ this.plot_width = 200 - this.margin.left - this.margin.right;
+ this.plot_height = 500 - this.margin.top - this.margin.bottom;
+ this.min = d3.min(this.sample_vals);
+ this.max = d3.max(this.sample_vals);
+ this.svg = this.create_svg();
+ this.enter_data();
+ }
+
+ Box_Plot.prototype.get_samples = function() {
+ var sample;
+ return this.sample_vals = (function() {
+ var _i, _len, _ref, _results;
+ _ref = this.sample_list;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ sample = _ref[_i];
+ if (sample.value !== null) {
+ _results.push(sample.value);
+ }
+ }
+ return _results;
+ }).call(this);
+ };
+
+ Box_Plot.prototype.create_svg = function() {
+ var svg;
+ svg = d3.box().whiskers(this.inter_quartile_range(1.5)).width(this.plot_width).height(this.plot_height).domain([this.min, this.max]);
+ return svg;
+ };
+
+ Box_Plot.prototype.enter_data = function() {
+ return d3.select("#box_plot").selectAll("svg").data([this.sample_vals]).enter().append("svg:svg").attr("class", "box").attr("width", this.plot_width).attr("height", this.plot_height).append("svg:g").call(this.svg);
+ };
+
+ Box_Plot.prototype.inter_quartile_range = function(k) {
+ var _this = this;
+ return function(d, i) {
+ var inter_quartile_range, j, q1, q3;
+ console.log("iqr d:", d);
+ q1 = d.quartiles[0];
+ q3 = d.quartiles[2];
+ inter_quartile_range = (q3 - q1) * k;
+ console.log("iqr:", inter_quartile_range);
+ i = 0;
+ j = d.length;
+ console.log("d[-1]:", d[1]);
+ console.log("q1 - iqr:", q1 - inter_quartile_range);
+ while (d[i] < q1 - inter_quartile_range) {
+ i++;
+ }
+ while (d[j] > q3 + inter_quartile_range) {
+ j--;
+ }
+ console.log("[i, j]", [i, j]);
+ return [i, j];
+ };
+ };
+
+ return Box_Plot;
+
+ })();
sample_lists = js_data.sample_lists;
- attribute_names = js_data.attribute_names;
sample_group_types = js_data.sample_group_types;
- new Bar_Chart(sample_lists[0], attribute_names);
- $('.stats_samples_group').change(function() {
+ new Bar_Chart(sample_lists[0]);
+ new Box_Plot(sample_lists[0]);
+ $('.bar_chart_samples_group').change(function() {
var all_samples, group;
$('#bar_chart').remove();
$('#bar_chart_container').append('<div id="bar_chart"></div>');
group = $(this).val();
- console.log("group:", group);
if (group === "samples_primary") {
return new Bar_Chart(sample_lists[0]);
} else if (group === "samples_other") {
return new Bar_Chart(sample_lists[1]);
} else if (group === "samples_all") {
all_samples = sample_lists[0].concat(sample_lists[1]);
- return new HBar_Chart(all_samples);
+ return new Bar_Chart(all_samples);
+ }
+ });
+ $('.box_plot_samples_group').change(function() {
+ var all_samples, group;
+ $('#box_plot').remove();
+ $('#box_plot_container').append('<div id="box_plot"></div>');
+ group = $(this).val();
+ if (group === "samples_primary") {
+ return new Box_Plot(sample_lists[0]);
+ } else if (group === "samples_other") {
+ return new Box_Plot(sample_lists[1]);
+ } else if (group === "samples_all") {
+ all_samples = sample_lists[0].concat(sample_lists[1]);
+ return new Box_Plot(all_samples);
}
});
hide_tabs = function(start) {
diff --git a/wqflask/wqflask/templates/show_trait.html b/wqflask/wqflask/templates/show_trait.html
index 36a62327..8a19e07b 100644
--- a/wqflask/wqflask/templates/show_trait.html
+++ b/wqflask/wqflask/templates/show_trait.html
@@ -3,6 +3,7 @@
{% block css %}
<link rel="stylesheet" type="text/css" href="/static/new/css/marker_regression.css" />
<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/packages/DataTables/css/jquery.dataTables.css" />
<link rel="stylesheet" type="text/css" href="/static/packages/DT_bootstrap/DT_bootstrap.css" />
{% endblock %}
@@ -53,6 +54,7 @@
<script type="text/javascript" src="/static/new/packages/ValidationPlugin/dist/jquery.validate.min.js"></script>
<script type="text/javascript" src="/static/new/javascript/stats.js"></script>
+ <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/show_trait.js"></script>
<script type="text/javascript" src="/static/new/javascript/show_trait_mapping_tools.js"></script>
diff --git a/wqflask/wqflask/templates/show_trait_statistics_new.html b/wqflask/wqflask/templates/show_trait_statistics_new.html
index 6c64989f..6385089b 100644
--- a/wqflask/wqflask/templates/show_trait_statistics_new.html
+++ b/wqflask/wqflask/templates/show_trait_statistics_new.html
@@ -2,30 +2,58 @@
<br>
<h2>Charts and Figures</h2>
<div class="well form-horizontal">
- {% if sample_groups|length > 1 %}
- <select class="stats_samples_group">
- {% for group, pretty_group in sample_group_types.items() %}
- <option value="{{ group }}">{{ pretty_group }}</option>
- {% endfor %}
- </select>
- {% endif %}
- {% if sample_groups[0].attributes %}
- <div class="input-append">
- <select id="color_attribute" size=1>
- <option value="None">None</option>
- {% for attribute in sample_groups[0].attributes %}
- <option value="{{ sample_groups[0].attributes[attribute].name.replace(' ', '_') }}">
- {{ sample_groups[0].attributes[attribute].name }}</option>
- {% endfor %}
- </select>
+ <div class="tabbable"> <!-- Only required for left/right tabs -->
+ <ul class="nav nav-pills">
+ <li class="active">
+ <a href="#bar_chart_tab" data-toggle="tab">Bar Chart</a>
+ </li>
+ <li>
+ <a href="#box_plot_tab" data-toggle="tab">Box Plot</a>
+ </li>
+ </ul>
+ <div class="tab-content">
+ <div class="tab-pane active" id="bar_chart_tab">
+ {% if sample_groups|length > 1 %}
+ <select class="bar_chart_samples_group">
+ {% for group, pretty_group in sample_group_types.items() %}
+ <option value="{{ group }}">{{ pretty_group }}</option>
+ {% endfor %}
+ </select>
+ {% endif %}
+ {% if sample_groups[0].attributes %}
+ <div class="input-append">
+ <select id="color_attribute" size=1>
+ <option value="None">None</option>
+ {% for attribute in sample_groups[0].attributes %}
+ <option value="{{ sample_groups[0].attributes[attribute].name.replace(' ', '_') }}">
+ {{ sample_groups[0].attributes[attribute].name }}</option>
+ {% endfor %}
+ </select>
+ </div>
+ {% endif %}
+ <button type="button" id="update_bar_chart">Sort By Value</button>
+ <button type="button" id="color_by_trait">Color by Trait</button>
+ <div id="bar_chart_container">
+ <div id="bar_chart"></div>
+ </div>
+ </div>
+ <div class="tab-pane active" id="box_plot_tab">
+ {% if sample_groups|length > 1 %}
+ <select class="box_plot_samples_group">
+ {% for group, pretty_group in sample_group_types.items() %}
+ <option value="{{ group }}">{{ pretty_group }}</option>
+ {% endfor %}
+ </select>
+ <br><br>
+ {% endif %}
+ <div id="box_plot_container">
+ <div id="box_plot"></div>
+ </div>
+ </div>
+ </div>
</div>
- {% endif %}
- <button type="button" id="update_bar_chart">Sort By Value</button>
- <button type="button" id="color_by_trait">Color by Trait</button>
- <div id="bar_chart_container">
- <div id="bar_chart"></div>
- </div>
-
</div>
- <div id="collections_holder"></div>
+ <div id="collections_holder_wrapper" style="display:none;">
+ <div id="collections_holder"></div>
+ </div>
</div> \ No newline at end of file