about summary refs log tree commit diff
diff options
context:
space:
mode:
authorArtem Tarasov2015-05-18 14:12:19 +0300
committerArtem Tarasov2015-05-18 14:13:05 +0300
commit744c247c4de7a49b565e7deead5176efff2b55a2 (patch)
tree8da86a25657817ddd1f6f1fc74b60d8d0c1ea70e
parent4128a7ab0e1361a2f598760d020e3575afb27bc8 (diff)
downloadgenenetwork2-744c247c4de7a49b565e7deead5176efff2b55a2.tar.gz
fix attribute coloring
also I found out that there are two legends shown simultaneously,
but one is suitable only for discrete values, and the other for
continuous; now only the suitable one is shown
-rwxr-xr-xwqflask/runserver.py3
-rwxr-xr-xwqflask/wqflask/static/new/javascript/bar_chart.coffee117
-rwxr-xr-xwqflask/wqflask/static/new/javascript/bar_chart.js169
3 files changed, 164 insertions, 125 deletions
diff --git a/wqflask/runserver.py b/wqflask/runserver.py
index 5a76d1e2..59ebf0d4 100755
--- a/wqflask/runserver.py
+++ b/wqflask/runserver.py
@@ -30,6 +30,7 @@ logging_tree.printout()
 
 app.run(host='0.0.0.0',
         port=app.config['SERVER_PORT'],
-        use_debugger=False,
+        debug=True,
+        use_debugger=True,
         threaded=True,
         use_reloader=True)
diff --git a/wqflask/wqflask/static/new/javascript/bar_chart.coffee b/wqflask/wqflask/static/new/javascript/bar_chart.coffee
index acc4ac46..8c958e7d 100755
--- a/wqflask/wqflask/static/new/javascript/bar_chart.coffee
+++ b/wqflask/wqflask/static/new/javascript/bar_chart.coffee
@@ -26,41 +26,36 @@ class Bar_Chart
         @svg = @create_svg()
 
         @plot_height -= @y_buffer
-        @create_scales()
+        @create_scales(@sample_names)
         @create_graph()
 
         d3.select("#color_attribute").on("change", =>
             @attribute = $("#color_attribute").val()
+
             console.log("attr_color_dict:", @attr_color_dict)
-            #if $("#update_bar_chart").html() == 'Sort By Name'
-            if @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]
-                    )
+
+            @svg.selectAll(".bar")
+                .data(if @sort_by == "name" then @samples else @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]
+                )
+
+            $(".legend").remove()
+            if @attribute == "None" or @is_discrete[@attribute]
+                $("#legend-left,#legend-right,#legend-colors").empty()
+                if @attribute != "None"
+                    @add_legend(@attribute, @distinct_attr_vals[@attribute])
             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]]
-                    )
-            @draw_legend()
-            @add_legend(@attribute, @distinct_attr_vals[@attribute])
+                @draw_legend()
         )
 
         $(".sort_by_value").on("click", =>
@@ -136,23 +131,31 @@ class Bar_Chart
             @open_trait_selection()
         )
 
+    extra: (sample) ->
+        attr_vals = {}
+        for attribute in @attributes
+            attr_vals[attribute] = sample["extra_attributes"][attribute]
+        attr_vals
+
     # takes a dict: name -> value and rebuilds the graph
     redraw: (samples_dict) ->
-        updated_samples = []
-        for [name, val, attr] in @full_sample_list
-            if name of samples_dict
-                updated_samples.push [name, samples_dict[name], attr]
-
-        @samples = updated_samples
-        # TODO: update underscore.js and replace the below with an _.unzip call
-        @sample_names = (x[0] for x in @samples)
-        @sample_vals = (x[1] for x in @samples)
-        @sample_attr_vals = (x[2] for x in @samples)
+        curr = (x for x in @sample_list when\
+                x.name of samples_dict and samples_dict[x.name] != null)
+        @sample_names = (x.name for x in curr)
+        @sample_vals = (samples_dict[x.name] for x in curr)
+        @sample_attr_vals = (@extra(x) for x in curr)
+        @samples = _.zip(@sample_names, @sample_vals, @sample_attr_vals)
 
         @rebuild_bar_graph(if @sort_by == 'name' then @samples else @sorted_samples())
 
     rebuild_bar_graph: (samples) ->
         console.log("samples:", samples)
+        @attribute = $("#color_attribute").val()
+
+        vals = (x[1] for x in samples)
+        @y_min = d3.min(vals)
+        @y_max = d3.max(vals) * 1.1
+
         @svg.selectAll(".bar")
             .data(samples)
             .transition()
@@ -185,7 +188,8 @@ class Bar_Chart
             #    return @trait_color_dict[d[0]]
             #    #return @attr_color_dict["collection_trait"][trimmed_samples[d[0]]]
             #)
-        @create_scales()
+        names = (x[0] for x in samples)
+        @create_scales(names)
         $('.bar_chart').find('.x.axis').remove()
         $('.bar_chart').find('.y.axis').remove()
         @add_x_axis()
@@ -193,12 +197,16 @@ class Bar_Chart
 
     get_attr_color_dict: (vals) ->
         @attr_color_dict = {}
+        @is_discrete = {}
+        @minimum_values = {}
+        @maximum_values = {}
         console.log("vals:", vals)
         for own key, distinct_vals of vals
             @min_val = d3.min(distinct_vals)
             @max_val = d3.max(distinct_vals)
             this_color_dict = {}
-            if distinct_vals.length < 10
+            discrete = distinct_vals.length < 10
+            if discrete
                 color = d3.scale.category10()
                 for value, i in distinct_vals
                     this_color_dict[value] = color(i)
@@ -213,8 +221,7 @@ class Bar_Chart
                         return true
                 )
                     color_range = d3.scale.linear()
-                                    .domain([min_val,
-                                            max_val])
+                                    .domain([@min_val, @max_val])
                                     .range([0,255])
                     for value, i in distinct_vals
                         console.log("color_range(value):", parseInt(color_range(value)))
@@ -222,12 +229,15 @@ class Bar_Chart
                         #this_color_dict[value] = d3.rgb("lightblue").darker(color_range(parseInt(value)))
                         #this_color_dict[value] = "rgb(0, 0, " + color_range(parseInt(value)) + ")"
             @attr_color_dict[key] = this_color_dict
+            @is_discrete[key] = discrete
+            @minimum_values[key] = @min_val
+            @maximum_values[key] = @max_val
        
 
 
     draw_legend: () ->
-        $('#legend-left').html(@min_val)
-        $('#legend-right').html(@max_val)
+        $('#legend-left').html(@minimum_values[@attribute])
+        $('#legend-right').html(@maximum_values[@attribute])
         svg_html = '<svg height="10" width="90"> \
                         <rect x="0" width="15" height="10" style="fill: rgb(0, 0, 0);"></rect> \
                         <rect x="15" width="15" height="10" style="fill: rgb(50, 0, 0);"></rect> \
@@ -285,19 +295,11 @@ class Bar_Chart
         @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 = []
-        # WTF??? how can they be zipped later???
-        # TODO find something with extra_attributes for testing
-        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)
+        @sample_attr_vals = (@extra(sample) for sample in @sample_list when sample.value != null)
         @samples = _.zip(@sample_names, @sample_vals, @sample_attr_vals)
-        @full_sample_list = @samples.slice() # keeps attributes across redraws
 
     get_distinct_attr_vals: () ->
+        # FIXME: this has quadratic behaviour, may cause issues with many samples and continuous attributes
         @distinct_attr_vals = {}
         for sample in @sample_attr_vals
             for attribute of sample
@@ -318,9 +320,9 @@ class Bar_Chart
             
         return svg
         
-    create_scales: () ->
+    create_scales: (sample_names) ->
         @x_scale = d3.scale.ordinal()
-            .domain(@sample_names)
+            .domain(sample_names)
             .rangeRoundBands([0, @range], 0.1, 0)
 
         @y_scale = d3.scale.linear()
@@ -401,6 +403,7 @@ class Bar_Chart
         console.log("sorted:", sorted)
         return sorted
 
+    # FIXME: better positioning of the legend
     add_legend: (attribute, distinct_vals) ->
         legend = @svg.append("g")
             .attr("class", "legend")
diff --git a/wqflask/wqflask/static/new/javascript/bar_chart.js b/wqflask/wqflask/static/new/javascript/bar_chart.js
index 4dba3793..c392acc8 100755
--- a/wqflask/wqflask/static/new/javascript/bar_chart.js
+++ b/wqflask/wqflask/static/new/javascript/bar_chart.js
@@ -42,33 +42,30 @@
       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_scales(this.sample_names);
       this.create_graph();
       d3.select("#color_attribute").on("change", (function(_this) {
         return function() {
           _this.attribute = $("#color_attribute").val();
           console.log("attr_color_dict:", _this.attr_color_dict);
-          if (_this.sort_by = "name") {
-            _this.svg.selectAll(".bar").data(_this.sorted_samples()).transition().duration(1000).style("fill", function(d) {
-              if (_this.attribute === "None") {
-                return "steelblue";
-              } else {
-                return _this.attr_color_dict[_this.attribute][d[2][_this.attribute]];
-              }
-            }).select("title").text(function(d) {
-              return d[1];
-            });
+          _this.svg.selectAll(".bar").data(_this.sort_by === "name" ? _this.samples : _this.sorted_samples()).transition().duration(1000).style("fill", function(d) {
+            if (_this.attribute === "None") {
+              return "steelblue";
+            } else {
+              return _this.attr_color_dict[_this.attribute][d[2][_this.attribute]];
+            }
+          }).select("title").text(function(d) {
+            return d[1];
+          });
+          $(".legend").remove();
+          if (_this.attribute === "None" || _this.is_discrete[_this.attribute]) {
+            $("#legend-left,#legend-right,#legend-colors").empty();
+            if (_this.attribute !== "None") {
+              return _this.add_legend(_this.attribute, _this.distinct_attr_vals[_this.attribute]);
+            }
           } else {
-            _this.svg.selectAll(".bar").data(_this.samples).transition().duration(1000).style("fill", function(d) {
-              if (_this.attribute === "None") {
-                return "steelblue";
-              } else {
-                return _this.attr_color_dict[_this.attribute][d[2][_this.attribute]];
-              }
-            });
+            return _this.draw_legend();
           }
-          _this.draw_legend();
-          return _this.add_legend(_this.attribute, _this.distinct_attr_vals[_this.attribute]);
         };
       })(this));
       $(".sort_by_value").on("click", (function(_this) {
@@ -98,52 +95,77 @@
       })(this));
     }
 
-    Bar_Chart.prototype.redraw = function(samples_dict) {
-      var attr, j, len, name, ref, ref1, updated_samples, val, x;
-      updated_samples = [];
-      ref = this.full_sample_list;
+    Bar_Chart.prototype.extra = function(sample) {
+      var attr_vals, attribute, j, len, ref;
+      attr_vals = {};
+      ref = this.attributes;
       for (j = 0, len = ref.length; j < len; j++) {
-        ref1 = ref[j], name = ref1[0], val = ref1[1], attr = ref1[2];
-        if (name in samples_dict) {
-          updated_samples.push([name, samples_dict[name], attr]);
-        }
+        attribute = ref[j];
+        attr_vals[attribute] = sample["extra_attributes"][attribute];
       }
-      this.samples = updated_samples;
-      this.sample_names = (function() {
-        var k, len1, ref2, results;
-        ref2 = this.samples;
+      return attr_vals;
+    };
+
+    Bar_Chart.prototype.redraw = function(samples_dict) {
+      var curr, x;
+      curr = (function() {
+        var j, len, ref, results;
+        ref = this.sample_list;
         results = [];
-        for (k = 0, len1 = ref2.length; k < len1; k++) {
-          x = ref2[k];
-          results.push(x[0]);
+        for (j = 0, len = ref.length; j < len; j++) {
+          x = ref[j];
+          if (x.name in samples_dict && samples_dict[x.name] !== null) {
+            results.push(x);
+          }
         }
         return results;
       }).call(this);
+      this.sample_names = (function() {
+        var j, len, results;
+        results = [];
+        for (j = 0, len = curr.length; j < len; j++) {
+          x = curr[j];
+          results.push(x.name);
+        }
+        return results;
+      })();
       this.sample_vals = (function() {
-        var k, len1, ref2, results;
-        ref2 = this.samples;
+        var j, len, results;
         results = [];
-        for (k = 0, len1 = ref2.length; k < len1; k++) {
-          x = ref2[k];
-          results.push(x[1]);
+        for (j = 0, len = curr.length; j < len; j++) {
+          x = curr[j];
+          results.push(samples_dict[x.name]);
         }
         return results;
-      }).call(this);
+      })();
       this.sample_attr_vals = (function() {
-        var k, len1, ref2, results;
-        ref2 = this.samples;
+        var j, len, results;
         results = [];
-        for (k = 0, len1 = ref2.length; k < len1; k++) {
-          x = ref2[k];
-          results.push(x[2]);
+        for (j = 0, len = curr.length; j < len; j++) {
+          x = curr[j];
+          results.push(this.extra(x));
         }
         return results;
       }).call(this);
+      this.samples = _.zip(this.sample_names, this.sample_vals, this.sample_attr_vals);
       return this.rebuild_bar_graph(this.sort_by === 'name' ? this.samples : this.sorted_samples());
     };
 
     Bar_Chart.prototype.rebuild_bar_graph = function(samples) {
+      var names, vals, x;
       console.log("samples:", samples);
+      this.attribute = $("#color_attribute").val();
+      vals = (function() {
+        var j, len, results;
+        results = [];
+        for (j = 0, len = samples.length; j < len; j++) {
+          x = samples[j];
+          results.push(x[1]);
+        }
+        return results;
+      })();
+      this.y_min = d3.min(vals);
+      this.y_max = d3.max(vals) * 1.1;
       this.svg.selectAll(".bar").data(samples).transition().duration(1000).style("fill", (function(_this) {
         return function(d) {
           if (_this.attributes.length === 0 && (_this.trait_color_dict != null)) {
@@ -172,7 +194,16 @@
           return d[1];
         };
       })(this));
-      this.create_scales();
+      names = (function() {
+        var j, len, results;
+        results = [];
+        for (j = 0, len = samples.length; j < len; j++) {
+          x = samples[j];
+          results.push(x[0]);
+        }
+        return results;
+      })();
+      this.create_scales(names);
       $('.bar_chart').find('.x.axis').remove();
       $('.bar_chart').find('.y.axis').remove();
       this.add_x_axis();
@@ -180,8 +211,11 @@
     };
 
     Bar_Chart.prototype.get_attr_color_dict = function(vals) {
-      var color, color_range, distinct_vals, i, j, k, key, len, len1, results, this_color_dict, value;
+      var color, color_range, discrete, distinct_vals, i, j, k, key, len, len1, results, this_color_dict, value;
       this.attr_color_dict = {};
+      this.is_discrete = {};
+      this.minimum_values = {};
+      this.maximum_values = {};
       console.log("vals:", vals);
       results = [];
       for (key in vals) {
@@ -190,7 +224,8 @@
         this.min_val = d3.min(distinct_vals);
         this.max_val = d3.max(distinct_vals);
         this_color_dict = {};
-        if (distinct_vals.length < 10) {
+        discrete = distinct_vals.length < 10;
+        if (discrete) {
           color = d3.scale.category10();
           for (i = j = 0, len = distinct_vals.length; j < len; i = ++j) {
             value = distinct_vals[i];
@@ -207,7 +242,7 @@
               }
             };
           })(this))) {
-            color_range = d3.scale.linear().domain([min_val, max_val]).range([0, 255]);
+            color_range = d3.scale.linear().domain([this.min_val, this.max_val]).range([0, 255]);
             for (i = k = 0, len1 = distinct_vals.length; k < len1; i = ++k) {
               value = distinct_vals[i];
               console.log("color_range(value):", parseInt(color_range(value)));
@@ -215,15 +250,18 @@
             }
           }
         }
-        results.push(this.attr_color_dict[key] = this_color_dict);
+        this.attr_color_dict[key] = this_color_dict;
+        this.is_discrete[key] = discrete;
+        this.minimum_values[key] = this.min_val;
+        results.push(this.maximum_values[key] = this.max_val);
       }
       return results;
     };
 
     Bar_Chart.prototype.draw_legend = function() {
       var svg_html;
-      $('#legend-left').html(this.min_val);
-      $('#legend-right').html(this.max_val);
+      $('#legend-left').html(this.minimum_values[this.attribute]);
+      $('#legend-right').html(this.maximum_values[this.attribute]);
       svg_html = '<svg height="10" width="90"> <rect x="0" width="15" height="10" style="fill: rgb(0, 0, 0);"></rect> <rect x="15" width="15" height="10" style="fill: rgb(50, 0, 0);"></rect> <rect x="30" width="15" height="10" style="fill: rgb(100, 0, 0);"></rect> <rect x="45" width="15" height="10" style="fill: rgb(150, 0, 0);"></rect> <rect x="60" width="15" height="10" style="fill: rgb(200, 0, 0);"></rect> <rect x="75" width="15" height="10" style="fill: rgb(255, 0, 0);"></rect> </svg>';
       console.log("svg_html:", svg_html);
       return $('#legend-colors').html(svg_html);
@@ -287,7 +325,7 @@
     };
 
     Bar_Chart.prototype.get_samples = function() {
-      var attr_vals, attribute, j, k, key, len, len1, ref, ref1, sample;
+      var key, sample;
       this.sample_names = (function() {
         var j, len, ref, results;
         ref = this.sample_list;
@@ -321,22 +359,19 @@
         return results;
       }).call(this);
       console.log("attributes:", this.attributes);
-      this.sample_attr_vals = [];
-      if (this.attributes.length > 0) {
+      this.sample_attr_vals = (function() {
+        var j, len, ref, results;
         ref = this.sample_list;
+        results = [];
         for (j = 0, len = ref.length; j < len; j++) {
           sample = ref[j];
-          attr_vals = {};
-          ref1 = this.attributes;
-          for (k = 0, len1 = ref1.length; k < len1; k++) {
-            attribute = ref1[k];
-            attr_vals[attribute] = sample["extra_attributes"][attribute];
+          if (sample.value !== null) {
+            results.push(this.extra(sample));
           }
-          this.sample_attr_vals.push(attr_vals);
         }
-      }
-      this.samples = _.zip(this.sample_names, this.sample_vals, this.sample_attr_vals);
-      return this.full_sample_list = this.samples.slice();
+        return results;
+      }).call(this);
+      return this.samples = _.zip(this.sample_names, this.sample_vals, this.sample_attr_vals);
     };
 
     Bar_Chart.prototype.get_distinct_attr_vals = function() {
@@ -371,8 +406,8 @@
       return svg;
     };
 
-    Bar_Chart.prototype.create_scales = function() {
-      this.x_scale = d3.scale.ordinal().domain(this.sample_names).rangeRoundBands([0, this.range], 0.1, 0);
+    Bar_Chart.prototype.create_scales = function(sample_names) {
+      this.x_scale = d3.scale.ordinal().domain(sample_names).rangeRoundBands([0, this.range], 0.1, 0);
       return this.y_scale = d3.scale.linear().domain([this.y_min * 0.75, this.y_max]).range([this.plot_height, this.y_buffer]);
     };