about summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-xwqflask/base/data_set.py13
-rw-r--r--wqflask/wqflask/my_pylmm/data/genofile_parser.py4
-rw-r--r--wqflask/wqflask/static/new/css/bar_chart.css1
-rw-r--r--wqflask/wqflask/static/new/javascript/bar_chart.coffee43
-rw-r--r--wqflask/wqflask/static/new/javascript/bar_chart.js27
-rw-r--r--wqflask/wqflask/static/new/javascript/histogram.coffee149
-rw-r--r--wqflask/wqflask/static/new/javascript/histogram.js140
-rw-r--r--wqflask/wqflask/static/new/javascript/show_trait.coffee17
-rw-r--r--wqflask/wqflask/static/new/javascript/show_trait.js7
-rw-r--r--wqflask/wqflask/templates/show_trait.html1
-rw-r--r--wqflask/wqflask/templates/show_trait_statistics_new.html16
11 files changed, 367 insertions, 51 deletions
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py
index fbe78d5d..d421f21e 100755
--- a/wqflask/base/data_set.py
+++ b/wqflask/base/data_set.py
@@ -168,13 +168,14 @@ class Markers(object):
         
         for marker, p_value in itertools.izip(self.markers, p_values):
             marker['p_value'] = p_value
-            if math.isnan(marker['p_value']):
+            if math.isnan(marker['p_value']) or marker['p_value'] <= 0:
                 print("p_value is:", marker['p_value'])
-            marker['lod_score'] = -math.log10(marker['p_value'])
-            #Using -log(p) for the LRS; need to ask Rob how he wants to get LRS from p-values
-            marker['lrs_value'] = -math.log10(marker['p_value']) * 4.61
-        
-        
+                marker['lod_score'] = 0
+                marker['lrs_value'] = 0
+            else:
+                marker['lod_score'] = -math.log10(marker['p_value'])
+                #Using -log(p) for the LRS; need to ask Rob how he wants to get LRS from p-values
+                marker['lrs_value'] = -math.log10(marker['p_value']) * 4.61
 
 
 class HumanMarkers(Markers):
diff --git a/wqflask/wqflask/my_pylmm/data/genofile_parser.py b/wqflask/wqflask/my_pylmm/data/genofile_parser.py
index af855fb4..c8c0929f 100644
--- a/wqflask/wqflask/my_pylmm/data/genofile_parser.py
+++ b/wqflask/wqflask/my_pylmm/data/genofile_parser.py
@@ -106,8 +106,8 @@ class ConvertGenoFile(object):
                     this_marker.genotypes.append("NA")
                 
             #print("this_marker is:", pf(this_marker.__dict__))   
-                
-            self.markers.append(this_marker.__dict__)
+            if this_marker.chr == "5":
+                self.markers.append(this_marker.__dict__)
 
         with open(self.output_file, 'w') as fh:
             json.dump(self.markers, fh, indent="   ", sort_keys=True)
diff --git a/wqflask/wqflask/static/new/css/bar_chart.css b/wqflask/wqflask/static/new/css/bar_chart.css
index ba14fe4e..c8e081f9 100644
--- a/wqflask/wqflask/static/new/css/bar_chart.css
+++ b/wqflask/wqflask/static/new/css/bar_chart.css
@@ -7,6 +7,7 @@
 

 .bar {

   fill: steelblue;

+  shape-rendering: crispEdges;

 }

 

 .x.axis path {

diff --git a/wqflask/wqflask/static/new/javascript/bar_chart.coffee b/wqflask/wqflask/static/new/javascript/bar_chart.coffee
index 27a8d284..3f12d956 100644
--- a/wqflask/wqflask/static/new/javascript/bar_chart.coffee
+++ b/wqflask/wqflask/static/new/javascript/bar_chart.coffee
@@ -132,7 +132,6 @@ class Bar_Chart
 
         d3.select("#color_by_trait").on("click", =>
             @open_trait_selection()
-            
         )
 
     rebuild_bar_graph: (samples) ->
@@ -141,20 +140,11 @@ class Bar_Chart
             .data(samples)
             .transition()
             .duration(1000)
-            .attr("y", (d) =>
-                return @y_scale(d[1])
-            )
-            .attr("height", (d) =>
-                return @plot_height - @y_scale(d[1])
-            )
-            .select("title")
-            .text((d) =>
-                return d[1]
-            )
             .style("fill", (d) =>
-                if @attributes.length == 0
+                if @attributes.length == 0 and @trait_color_dict?
                     console.log("SAMPLE:", d[0])
                     console.log("CHECKING:", @trait_color_dict[d[0]])
+                    #return "steelblue"
                     return @trait_color_dict[d[0]]
                 else if @attributes.length > 0 and @attribute != "None"
                     console.log("@attribute:", @attribute)
@@ -164,6 +154,16 @@ class Bar_Chart
                 else
                     return "steelblue"
             )
+            .attr("y", (d) =>
+                return @y_scale(d[1])
+            )
+            .attr("height", (d) =>
+                return @plot_height - @y_scale(d[1])
+            )
+            .select("title")
+            .text((d) =>
+                return d[1]
+            )
             #.style("fill", (d) =>
             #    return @trait_color_dict[d[0]]
             #    #return @attr_color_dict["collection_trait"][trimmed_samples[d[0]]]
@@ -419,29 +419,34 @@ class Bar_Chart
         #@get_attr_color_dict(distinct_values)
         @get_trait_color_dict(trimmed_samples, distinct_values)
         console.log("TRAIT_COLOR_DICT:", @trait_color_dict)
-        if $("#update_bar_chart").html() == 'Sort By Name' 
+        console.log("SAMPLES:", @samples)
+        if @sort_by = "value"
             @svg.selectAll(".bar")
-                .data(@sorted_samples())
+                .data(@samples)
                 .transition()
                 .duration(1000)
                 .style("fill", (d) =>
+                    console.log("this color:", @trait_color_dict[d[0]])
                     return @trait_color_dict[d[0]]
-                    #return @attr_color_dict["collection_trait"][trimmed_samples[d[0]]]
                 )
                 .select("title")
                 .text((d) =>
                     return d[1]
-                )
+                )            
+
         else
             @svg.selectAll(".bar")
-                .data(@samples)
+                .data(@sorted_samples())
                 .transition()
                 .duration(1000)
                 .style("fill", (d) =>
+                    console.log("this color:", @trait_color_dict[d[0]])
                     return @trait_color_dict[d[0]]
-                    #return @attr_color_dict["collection_trait"][trimmed_samples[d[0]]]
                 )
-
+                .select("title")
+                .text((d) =>
+                    return d[1]
+                )            
 
     trim_values: (trait_sample_data) ->
         trimmed_samples = {}
diff --git a/wqflask/wqflask/static/new/javascript/bar_chart.js b/wqflask/wqflask/static/new/javascript/bar_chart.js
index faf66cd4..c0b056f8 100644
--- a/wqflask/wqflask/static/new/javascript/bar_chart.js
+++ b/wqflask/wqflask/static/new/javascript/bar_chart.js
@@ -95,14 +95,8 @@
       var sample, sample_names, x_scale,
         _this = this;
       console.log("samples:", samples);
-      this.svg.selectAll(".bar").data(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]);
-      }).select("title").text(function(d) {
-        return d[1];
-      }).style("fill", function(d) {
-        if (_this.attributes.length === 0) {
+      this.svg.selectAll(".bar").data(samples).transition().duration(1000).style("fill", function(d) {
+        if (_this.attributes.length === 0 && (_this.trait_color_dict != null)) {
           console.log("SAMPLE:", d[0]);
           console.log("CHECKING:", _this.trait_color_dict[d[0]]);
           return _this.trait_color_dict[d[0]];
@@ -114,6 +108,12 @@
         } else {
           return "steelblue";
         }
+      }).attr("y", function(d) {
+        return _this.y_scale(d[1]);
+      }).attr("height", function(d) {
+        return _this.plot_height - _this.y_scale(d[1]);
+      }).select("title").text(function(d) {
+        return d[1];
       });
       sample_names = (function() {
         var _i, _len, _results;
@@ -394,15 +394,20 @@
       distinct_values["collection_trait"] = this.get_distinct_values(trimmed_samples);
       this.get_trait_color_dict(trimmed_samples, distinct_values);
       console.log("TRAIT_COLOR_DICT:", this.trait_color_dict);
-      if ($("#update_bar_chart").html() === 'Sort By Name') {
-        return this.svg.selectAll(".bar").data(this.sorted_samples()).transition().duration(1000).style("fill", function(d) {
+      console.log("SAMPLES:", this.samples);
+      if (this.sort_by = "value") {
+        return this.svg.selectAll(".bar").data(this.samples).transition().duration(1000).style("fill", function(d) {
+          console.log("this color:", _this.trait_color_dict[d[0]]);
           return _this.trait_color_dict[d[0]];
         }).select("title").text(function(d) {
           return d[1];
         });
       } else {
-        return this.svg.selectAll(".bar").data(this.samples).transition().duration(1000).style("fill", function(d) {
+        return this.svg.selectAll(".bar").data(this.sorted_samples()).transition().duration(1000).style("fill", function(d) {
+          console.log("this color:", _this.trait_color_dict[d[0]]);
           return _this.trait_color_dict[d[0]];
+        }).select("title").text(function(d) {
+          return d[1];
         });
       }
     };
diff --git a/wqflask/wqflask/static/new/javascript/histogram.coffee b/wqflask/wqflask/static/new/javascript/histogram.coffee
new file mode 100644
index 00000000..03332835
--- /dev/null
+++ b/wqflask/wqflask/static/new/javascript/histogram.coffee
@@ -0,0 +1,149 @@
+root = exports ? this

+

+class Histogram

+    constructor: (@sample_list, @sample_group) ->

+        @sort_by = "name"

+        @format_count = d3.format(",.0f") #a formatter for counts

+        @get_samples()

+        #if @sample_attr_vals.length > 0

+        #    @get_distinct_attr_vals()

+        #    @get_attr_color_dict(@distinct_attr_vals)

+        

+        @margin = {top: 10, right: 30, bottom: 30, left: 30}

+        @plot_width = 960 - @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

+        

+        @plot_height -= @y_buffer

+        @create_x_scale()

+        @get_histogram_data()

+        @create_y_scale()

+        

+        @svg = @create_svg()

+

+        @create_graph()

+

+    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)

+

+    create_svg: () ->

+        svg = d3.select("#histogram")

+          .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_x_scale: () ->

+        @x_scale = d3.scale.linear()

+            .domain([d3.min(@sample_vals), d3.max(@sample_vals)])

+            .range([0, @plot_width])    

+

+    get_histogram_data: () ->

+        console.log("sample_vals:", @sample_vals)

+        @histogram_data = d3.layout.histogram()

+            .bins(@x_scale.ticks(10))(@sample_vals)

+        console.log("histogram_data:", @histogram_data[0])

+

+    create_y_scale: () ->

+        @y_scale = d3.scale.linear()

+            .domain([0, d3.max(@histogram_data, (d) => return d.y )])

+            .range([@plot_height, 0])

+

+    create_graph: () ->

+        

+        @add_x_axis()

+        #@add_y_axis() 

+

+        @add_bars()

+        

+    add_x_axis: () ->

+        x_axis = d3.svg.axis()

+            .scale(@x_scale)

+            .orient("bottom");

+        

+        @svg.append("g")

+            .attr("class", "x axis")

+            .attr("transform", "translate(0," + @plot_height + ")")

+            .call(x_axis)

+            #.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: () ->

+    #    y_axis = d3.svg.axis()

+    #            .scale(@y_scale)

+    #            .orient("left")

+    #            .ticks(5)

+    #

+    #    @svg.append("g")

+    #        .attr("class", "y axis")

+    #        .call(y_axis)

+    #      .append("text")

+    #        .attr("transform", "rotate(-90)")

+    #        .attr("y", 6)

+    #        .attr("dy", ".71em")

+    #        .style("text-anchor", "end")

+

+    add_bars: () ->

+        @svg.selectAll(".bar")

+            .data(@histogram_data)

+          .enter().append("g")

+            .attr("class", "bar")

+            .attr("transform", (d) =>

+                return "translate(" + @margin.left + "," + @margin.top + ")")

+          .append("rect")

+            .attr("x", 1)

+            .attr("width", @x_scale(@histogram_data[0].dx) - 1)

+            .attr("height", (d) =>

+                return @plot_height - @y_scale(d.y)

+            )

+          .append("text")

+            .attr("dy", ".75em")

+            .attr("y", 6)

+            .attr("x", @x_scale(@histogram_data[0].dx) / 2)

+            .attr("text-anchor", "middle")

+            .text((d) =>

+                return @format_count(d.y)

+            )

+

+    #open_trait_selection: () ->

+    #    $('#collections_holder').load('/collections/list?color_by_trait #collections_list', =>

+    #        $.colorbox(

+    #            inline: true

+    #            href: "#collections_holder"

+    #        )

+    #        #Removes the links from the collection names, because clicking them would leave the page

+    #        #instead of loading the list of traits in the colorbox

+    #        $('a.collection_name').attr( 'onClick', 'return false' )

+    #        #$('.collection_name').each (index, element) =>

+    #        #    console.log("contents:", $(element).contents())

+    #        #    $(element).contents().unwrap()

+    #    )

+

+root.Histogram = Histogram
\ No newline at end of file
diff --git a/wqflask/wqflask/static/new/javascript/histogram.js b/wqflask/wqflask/static/new/javascript/histogram.js
new file mode 100644
index 00000000..e7926ab1
--- /dev/null
+++ b/wqflask/wqflask/static/new/javascript/histogram.js
@@ -0,0 +1,140 @@
+// Generated by CoffeeScript 1.6.1
+(function() {
+  var Histogram, root;
+
+  root = typeof exports !== "undefined" && exports !== null ? exports : this;
+
+  Histogram = (function() {
+
+    function Histogram(sample_list, sample_group) {
+      this.sample_list = sample_list;
+      this.sample_group = sample_group;
+      this.sort_by = "name";
+      this.format_count = d3.format(",.0f");
+      this.get_samples();
+      this.margin = {
+        top: 10,
+        right: 30,
+        bottom: 30,
+        left: 30
+      };
+      this.plot_width = 960 - 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.plot_height -= this.y_buffer;
+      this.create_x_scale();
+      this.get_histogram_data();
+      this.create_y_scale();
+      this.svg = this.create_svg();
+      this.create_graph();
+    }
+
+    Histogram.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);
+    };
+
+    Histogram.prototype.create_svg = function() {
+      var svg;
+      svg = d3.select("#histogram").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;
+    };
+
+    Histogram.prototype.create_x_scale = function() {
+      return this.x_scale = d3.scale.linear().domain([d3.min(this.sample_vals), d3.max(this.sample_vals)]).range([0, this.plot_width]);
+    };
+
+    Histogram.prototype.get_histogram_data = function() {
+      console.log("sample_vals:", this.sample_vals);
+      this.histogram_data = d3.layout.histogram().bins(this.x_scale.ticks(10))(this.sample_vals);
+      return console.log("histogram_data:", this.histogram_data[0]);
+    };
+
+    Histogram.prototype.create_y_scale = function() {
+      var _this = this;
+      return this.y_scale = d3.scale.linear().domain([
+        0, d3.max(this.histogram_data, function(d) {
+          return d.y;
+        })
+      ]).range([this.plot_height, 0]);
+    };
+
+    Histogram.prototype.create_graph = function() {
+      this.add_x_axis();
+      return this.add_bars();
+    };
+
+    Histogram.prototype.add_x_axis = function() {
+      var x_axis;
+      x_axis = d3.svg.axis().scale(this.x_scale).orient("bottom");
+      return this.svg.append("g").attr("class", "x axis").attr("transform", "translate(0," + this.plot_height + ")").call(x_axis);
+    };
+
+    Histogram.prototype.add_bars = function() {
+      var _this = this;
+      return this.svg.selectAll(".bar").data(this.histogram_data).enter().append("g").attr("class", "bar").attr("transform", function(d) {
+        return "translate(" + _this.margin.left + "," + _this.margin.top + ")";
+      }).append("rect").attr("x", 1).attr("width", this.x_scale(this.histogram_data[0].dx) - 1).attr("height", function(d) {
+        return _this.plot_height - _this.y_scale(d.y);
+      }).append("text").attr("dy", ".75em").attr("y", 6).attr("x", this.x_scale(this.histogram_data[0].dx) / 2).attr("text-anchor", "middle").text(function(d) {
+        return _this.format_count(d.y);
+      });
+    };
+
+    return Histogram;
+
+  })();
+
+  root.Histogram = Histogram;
+
+}).call(this);
diff --git a/wqflask/wqflask/static/new/javascript/show_trait.coffee b/wqflask/wqflask/static/new/javascript/show_trait.coffee
index 1df033d6..e42a7d82 100644
--- a/wqflask/wqflask/static/new/javascript/show_trait.coffee
+++ b/wqflask/wqflask/static/new/javascript/show_trait.coffee
@@ -66,6 +66,7 @@ $ ->
 
     $("#update_bar_chart.btn-group").button()
     root.bar_chart = new Bar_Chart(sample_lists[0])
+    root.histogram = new Histogram(sample_lists[0])
     new Box_Plot(sample_lists[0])
 
     $('.bar_chart_samples_group').change ->
@@ -73,13 +74,12 @@ $ ->
         $('#bar_chart_container').append('<div id="bar_chart"></div>')
         group = $(this).val()
         if group == "samples_primary"
-            new Bar_Chart(sample_lists[0])
+            root.bar_chart = new Bar_Chart(sample_lists[0])
         else if group == "samples_other"
-            new Bar_Chart(sample_lists[1])
+            root.bar_chart = new Bar_Chart(sample_lists[1])
         else if group == "samples_all"
             all_samples = sample_lists[0].concat sample_lists[1]
-            new Bar_Chart(all_samples)
-        #$(".btn-group").button()
+            root.bar_chart = new Bar_Chart(all_samples)
 
     $('.box_plot_samples_group').change ->
         $('#box_plot').remove()
@@ -93,18 +93,18 @@ $ ->
             all_samples = sample_lists[0].concat sample_lists[1]
             new Box_Plot(all_samples)
 
-    
+
     hide_tabs = (start) ->
         for x in [start..10]
             $("#stats_tabs" + x).hide()
 
+
     # Changes stats table between all, bxd only and non-bxd, etc.
     stats_mdp_change = ->
         selected = $(this).val()
         hide_tabs(0)
         $("#stats_tabs" + selected).show()
 
-    #$(".stats_mdp").change(stats_mdp_change)
 
     change_stats_value = (sample_sets, category, value_type, decimal_places)->
         id = "#" + process_id(category, value_type)
@@ -130,12 +130,9 @@ $ ->
         if title_value
             $(id).attr('title', title_value)
 
+
     update_stat_values = (sample_sets)->
         for category in ['samples_primary', 'samples_other', 'samples_all']
-            #change_stats_value(sample_sets, category, "n_of_samples", 0)
-
-            #for stat in ["mean", "median", "std_dev", "std_error", "min", "max"]
-            #for stat in (row.vn for row in Stat_Table_Rows)
             for row in Stat_Table_Rows
                 console.log("Calling change_stats_value")
                 change_stats_value(sample_sets, category, row.vn, row.digits)
diff --git a/wqflask/wqflask/static/new/javascript/show_trait.js b/wqflask/wqflask/static/new/javascript/show_trait.js
index 90fa8228..d3a34166 100644
--- a/wqflask/wqflask/static/new/javascript/show_trait.js
+++ b/wqflask/wqflask/static/new/javascript/show_trait.js
@@ -63,6 +63,7 @@
     sample_group_types = js_data.sample_group_types;
     $("#update_bar_chart.btn-group").button();
     root.bar_chart = new Bar_Chart(sample_lists[0]);
+    root.histogram = new Histogram(sample_lists[0]);
     new Box_Plot(sample_lists[0]);
     $('.bar_chart_samples_group').change(function() {
       var all_samples, group;
@@ -70,12 +71,12 @@
       $('#bar_chart_container').append('<div id="bar_chart"></div>');
       group = $(this).val();
       if (group === "samples_primary") {
-        return new Bar_Chart(sample_lists[0]);
+        return root.bar_chart = new Bar_Chart(sample_lists[0]);
       } else if (group === "samples_other") {
-        return new Bar_Chart(sample_lists[1]);
+        return root.bar_chart = new Bar_Chart(sample_lists[1]);
       } else if (group === "samples_all") {
         all_samples = sample_lists[0].concat(sample_lists[1]);
-        return new Bar_Chart(all_samples);
+        return root.bar_chart = new Bar_Chart(all_samples);
       }
     });
     $('.box_plot_samples_group').change(function() {
diff --git a/wqflask/wqflask/templates/show_trait.html b/wqflask/wqflask/templates/show_trait.html
index 86891bb0..26f21f08 100644
--- a/wqflask/wqflask/templates/show_trait.html
+++ b/wqflask/wqflask/templates/show_trait.html
@@ -58,6 +58,7 @@
     <script type="text/javascript" src="/static/new/javascript/box.js"></script>
     <script type="text/javascript" src="/static/new/javascript/get_traits_from_collection.js"></script>    
     <script type="text/javascript" src="/static/new/javascript/bar_chart.js"></script>
+    <script type="text/javascript" src="/static/new/javascript/histogram.js"></script>
     <script type="text/javascript" src="/static/new/javascript/box_plot.js"></script>
     
     <script type="text/javascript" src="/static/new/javascript/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 9393e9bd..28f7e0c7 100644
--- a/wqflask/wqflask/templates/show_trait_statistics_new.html
+++ b/wqflask/wqflask/templates/show_trait_statistics_new.html
@@ -8,6 +8,9 @@
                     <a href="#bar_chart_tab" data-toggle="tab">Bar Chart</a>
                 </li>
                 <li>
+                    <a href="#histogram_tab" data-toggle="tab">Histogram</a>
+                </li>
+                <li>
                     <a href="#box_plot_tab" data-toggle="tab">Box Plot</a>
                 </li>
             </ul>
@@ -51,6 +54,19 @@
                         <div id="bar_chart"></div>
                     </div>
                 </div>
+                <div class="tab-pane" id="histogram_tab">
+                    {% if sample_groups|length > 1 %}
+                    <select class="histogram_samples_group">
+                        {% for group, pretty_group in sample_group_types.items() %}
+                            <option value="{{ group }}">{{ pretty_group }}</option>
+                        {% endfor %}
+                    </select>
+                    <br><br>
+                    {% endif %}
+                    <div id="histogram_container">
+                        <div id="histogram"></div>
+                    </div>
+                </div>
                 <div class="tab-pane" id="box_plot_tab">
                     {% if sample_groups|length > 1 %}
                     <select class="box_plot_samples_group">