about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--misc/gn_installation_notes.txt6
-rw-r--r--misc/notes.txt3
-rwxr-xr-xwqflask/base/data_set.py1
-rwxr-xr-xwqflask/base/trait.py6
-rw-r--r--wqflask/other_config/nginx_conf/penguin.conf2
-rw-r--r--wqflask/wqflask/correlation/show_corr_results.py15
-rwxr-xr-x[-rw-r--r--]wqflask/wqflask/interval_mapping/interval_mapping.py70
-rw-r--r--wqflask/wqflask/show_trait/SampleList.py2
-rw-r--r--wqflask/wqflask/static/new/css/bar_chart.css14
-rw-r--r--wqflask/wqflask/static/new/javascript/show_trait.coffee264
-rw-r--r--wqflask/wqflask/static/new/javascript/show_trait.js271
-rw-r--r--wqflask/wqflask/templates/correlation_page.html119
-rw-r--r--wqflask/wqflask/templates/quick_search.html7
-rw-r--r--wqflask/wqflask/templates/search_result_page.html3
-rw-r--r--wqflask/wqflask/templates/show_trait.html3
-rw-r--r--wqflask/wqflask/templates/show_trait_statistics_new.html29
-rw-r--r--wqflask/wqflask/views.py44
17 files changed, 755 insertions, 104 deletions
diff --git a/misc/gn_installation_notes.txt b/misc/gn_installation_notes.txt
index a73e7d4f..584080f7 100644
--- a/misc/gn_installation_notes.txt
+++ b/misc/gn_installation_notes.txt
@@ -304,6 +304,12 @@ sudo apt-get install colordiff
 
 ==========================================
 
+Install NTP (network time protocol)
+
+sudo apt-get install ntp
+
+==========================================
+
 To get server running:
 
 !If having seemingly inexplicable problems with imports, make sure I've started the environment!
diff --git a/misc/notes.txt b/misc/notes.txt
index 91a0e67c..f6a2bb33 100644
--- a/misc/notes.txt
+++ b/misc/notes.txt
@@ -90,6 +90,9 @@ Reload web server:
 Run server:
 python runserver.py
 
+Run sendmail.py
+python send_mail.py
+
 ===========================================
 
 UFW - default firewall confirguation tool for Ubuntu; eases iptables firewall configuration
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py
index f25e7974..cd8c1ac1 100755
--- a/wqflask/base/data_set.py
+++ b/wqflask/base/data_set.py
@@ -224,6 +224,7 @@ class DatasetGroup(object):
     """
     def __init__(self, dataset):
         """This sets self.group and self.group_id"""
+        print("dataset name:", dataset.name)
         self.name, self.id = g.db.execute(dataset.query_for_group).fetchone()
         if self.name == 'BXD300':
             self.name = "BXD"
diff --git a/wqflask/base/trait.py b/wqflask/base/trait.py
index aea1f9a9..731f99eb 100755
--- a/wqflask/base/trait.py
+++ b/wqflask/base/trait.py
@@ -387,6 +387,7 @@ class GeneralTrait(object):
                     #trait_qtl = self.cursor.fetchone()
                     if trait_qtl:
                         self.locus, self.lrs, self.pvalue, self.mean = trait_qtl
+                        print("self.locus:", self.locus)
                         if self.locus:
                             query = """
                                 select Geno.Chr, Geno.Mb from Geno, Species
@@ -395,8 +396,9 @@ class GeneralTrait(object):
                                 Geno.SpeciesId = Species.Id
                                 """.format(self.dataset.group.species, self.locus)
                             result = g.db.execute(query).fetchone()
-                            self.locus_chr = result[0]
-                            self.locus_mb = result[1]
+                            if result:
+                                self.locus_chr = result[0]
+                                self.locus_mb = result[1]
                     else:
                         self.locus = self.locus_chr = self.locus_mb = self.lrs = self.pvalue = self.mean = ""
 
diff --git a/wqflask/other_config/nginx_conf/penguin.conf b/wqflask/other_config/nginx_conf/penguin.conf
index 822556d3..5c380da8 100644
--- a/wqflask/other_config/nginx_conf/penguin.conf
+++ b/wqflask/other_config/nginx_conf/penguin.conf
@@ -2,7 +2,7 @@ server {
     # Modeled after http://flask.pocoo.org/docs/deploying/wsgi-standalone/
     listen 80;
 
-    server_name penguin.uthsc.edu;
+    server_name gn2python.genenetwork.org;
 
     access_log  /var/log/nginx/access.log;
     error_log  /var/log/nginx/error.log;
diff --git a/wqflask/wqflask/correlation/show_corr_results.py b/wqflask/wqflask/correlation/show_corr_results.py
index 8f23165c..0b66bc61 100644
--- a/wqflask/wqflask/correlation/show_corr_results.py
+++ b/wqflask/wqflask/correlation/show_corr_results.py
@@ -102,6 +102,7 @@ class CorrelationResults(object):
             self.sample_data = {}
             self.corr_type = start_vars['corr_type']
             self.corr_method = start_vars['corr_sample_method']
+            self.get_formatted_corr_type()
             self.return_number = 50
 
             #The two if statements below append samples to the sample list based upon whether the user
@@ -239,6 +240,20 @@ class CorrelationResults(object):
 
 ############################################################################################################################################
 
+    def get_formatted_corr_type(self):
+        self.formatted_corr_type = ""
+        if self.corr_type == "lit":
+            self.formatted_corr_type += "Literature Correlation "
+        elif self.corr_type == "tissue":
+            self.formatted_corr_type += "Tissue Correlation "
+        elif self.corr_type == "sample":
+            self.formatted_corr_type += "Genetic Correlation "
+        
+        if self.corr_method == "pearson":
+            self.formatted_corr_type += "(Pearson's r)"
+        elif self.corr_method == "spearman":
+            self.formatted_corr_type += "(Spearman's rho)"
+
     def do_tissue_correlation_for_trait_list(self, tissue_dataset_id=1):
         """Given a list of correlation results (self.correlation_results), gets the tissue correlation value for each"""
 
diff --git a/wqflask/wqflask/interval_mapping/interval_mapping.py b/wqflask/wqflask/interval_mapping/interval_mapping.py
index 5d660224..aca99cbe 100644..100755
--- a/wqflask/wqflask/interval_mapping/interval_mapping.py
+++ b/wqflask/wqflask/interval_mapping/interval_mapping.py
@@ -89,26 +89,56 @@ class IntervalMapping(object):
         samples, values, variances = self.trait.export_informative()
         if self.control_locus:
             if self.weighted_regression:
-                qtl_result = self.dataset.genotype.regression(strains = samples,
+                self.qtl_results = self.dataset.genotype.regression(strains = samples,
                                                               trait = values,
                                                               variance = variances,
                                                               control = self.control_locus)
             else:
-                qtl_result = self.dataset.genotype.regression(strains = samples,
+                self.qtl_results = self.dataset.genotype.regression(strains = samples,
                                                               trait = values,
                                                               control = self.control_locus)
         else:
             if self.weighted_regression:
-                qtl_result = self.dataset.genotype.regression(strains = samples,
+                self.qtl_results = self.dataset.genotype.regression(strains = samples,
                                                               trait = values,
                                                               variance = variances)
             else:
-                qtl_result = self.dataset.genotype.regression(strains = samples,
+                self.qtl_results = self.dataset.genotype.regression(strains = samples,
                                                               trait = values)
 
 
-        pheno_vector = np.array([val == "x" and np.nan or float(val) for val in self.vals])
+        #pheno_vector = np.array([val == "x" and np.nan or float(val) for val in self.vals])
+
+        #if self.dataset.group.species == "human":
+        #    p_values, t_stats = self.gen_human_results(pheno_vector, tempdata)
+        #else:
+        genotype_data = [marker['genotypes'] for marker in self.dataset.group.markers.markers]
+        
+        no_val_samples = self.identify_empty_samples()
+        trimmed_genotype_data = self.trim_genotypes(genotype_data, no_val_samples)
+        
+        genotype_matrix = np.array(trimmed_genotype_data).T
+        
+        #t_stats, p_values = lmm.run(
+        #    pheno_vector,
+        #    genotype_matrix,
+        #    restricted_max_likelihood=True,
+        #    refit=False,
+        #    temp_data=tempdata
+        #)
+        
+        #self.dataset.group.markers.add_pvalues(p_values)
+        
+        #self.qtl_results = self.dataset.group.markers.markers
 
+    def gen_qtl_results_2(self, tempdata):
+        """Generates qtl results for plotting interval map"""
+    
+        self.dataset.group.get_markers()
+        self.dataset.read_genotype_file()
+    
+        pheno_vector = np.array([val == "x" and np.nan or float(val) for val in self.vals])
+    
         #if self.dataset.group.species == "human":
         #    p_values, t_stats = self.gen_human_results(pheno_vector, tempdata)
         #else:
@@ -131,36 +161,6 @@ class IntervalMapping(object):
         
         self.qtl_results = self.dataset.group.markers.markers
 
-    #def gen_qtl_results_2(self, tempdata):
-    #    """Generates qtl results for plotting interval map"""
-    #
-    #    self.dataset.group.get_markers()
-    #    self.dataset.read_genotype_file()
-    #
-    #    pheno_vector = np.array([val == "x" and np.nan or float(val) for val in self.vals])
-    #
-    #    #if self.dataset.group.species == "human":
-    #    #    p_values, t_stats = self.gen_human_results(pheno_vector, tempdata)
-    #    #else:
-    #    genotype_data = [marker['genotypes'] for marker in self.dataset.group.markers.markers]
-    #    
-    #    no_val_samples = self.identify_empty_samples()
-    #    trimmed_genotype_data = self.trim_genotypes(genotype_data, no_val_samples)
-    #    
-    #    genotype_matrix = np.array(trimmed_genotype_data).T
-    #    
-    #    t_stats, p_values = lmm.run(
-    #        pheno_vector,
-    #        genotype_matrix,
-    #        restricted_max_likelihood=True,
-    #        refit=False,
-    #        temp_data=tempdata
-    #    )
-    #    
-    #    self.dataset.group.markers.add_pvalues(p_values)
-    #    
-    #    self.qtl_results = self.dataset.group.markers.markers
-
 
     def identify_empty_samples(self):
         no_val_samples = []
diff --git a/wqflask/wqflask/show_trait/SampleList.py b/wqflask/wqflask/show_trait/SampleList.py
index 1130fb60..9cd7d895 100644
--- a/wqflask/wqflask/show_trait/SampleList.py
+++ b/wqflask/wqflask/show_trait/SampleList.py
@@ -138,7 +138,7 @@ class SampleList(object):
                                                 StrainId = %s AND
                                                 CaseAttributeId = %s
                                         group by CaseAttributeXRef.CaseAttributeId""", (
-                                            self.this_trait.db.id, sample_id, str(attribute)))
+                                            self.this_trait.dataset.id, sample_id, str(attribute)))
 
                 attribute_value = result.fetchone().Value #Trait-specific attributes, if any
 
diff --git a/wqflask/wqflask/static/new/css/bar_chart.css b/wqflask/wqflask/static/new/css/bar_chart.css
new file mode 100644
index 00000000..ba14fe4e
--- /dev/null
+++ b/wqflask/wqflask/static/new/css/bar_chart.css
@@ -0,0 +1,14 @@
+.axis path,

+.axis line {

+  fill: none;

+  stroke: #000;

+  shape-rendering: crispEdges;

+}

+

+.bar {

+  fill: steelblue;

+}

+

+.x.axis path {

+  display: none;

+}
\ 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 0f16ac68..66110469 100644
--- a/wqflask/wqflask/static/new/javascript/show_trait.coffee
+++ b/wqflask/wqflask/static/new/javascript/show_trait.coffee
@@ -56,16 +56,271 @@ Stat_Table_Rows = [
                     url: "/glossary.html#Interquartile"
                     digits: 2
                 }
-
         ]
 
 $ ->
+    class Histogram
+        constructor: (@sample_list, @sample_group) ->
+            @get_samples()
+            console.log("sample names:", @sample_names)
+            
+            #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]]
+                        )
+            )
+        
+        
+            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)
+            )
+
+        get_attr_color_dict: () ->
+            color = d3.scale.category20()
+            @attr_color_dict = {}
+            for own key, attribute_info of js_data.attribute_names
+                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
+            
+            
+            
+
+        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_attr_color_dict()
+            console.log("samples:", @samples)
+            
+        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
+
+    sample_lists = js_data.sample_lists
+    sample_group_types = js_data.sample_group_types
+
+    new Histogram(sample_lists[0])
+
+    $('.stats_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 Histogram(sample_lists[0])
+        else if group == "samples_other"
+            new Histogram(sample_lists[1])
+        else if group == "samples_all"
+            all_samples = sample_lists[0].concat sample_lists[1]
+            new Histogram(all_samples)
+
+    
     hide_tabs = (start) ->
         for x in [start..10]
             $("#stats_tabs" + x).hide()
 
-    #hide_tabs(1)
-
     # Changes stats table between all, bxd only and non-bxd, etc.
     stats_mdp_change = ->
         selected = $(this).val()
@@ -81,7 +336,6 @@ $ ->
 
         current_value = parseFloat($(in_box)).toFixed(decimal_places)
 
-        console.log("urgh:", category, value_type)
         the_value = sample_sets[category][value_type]()
         console.log("After running sample_sets, the_value is:", the_value)
         if decimal_places > 0
@@ -121,7 +375,6 @@ $ ->
         tables = ['samples_primary', 'samples_other']
         for table in tables
             rows = $("#" + table).find('tr')
-            console.log("[fuji3] rows:", rows)
             for row in rows
                 name = $(row).find('.edit_sample_sample_name').html()
                 name = $.trim(name)
@@ -180,7 +433,6 @@ $ ->
         $("#stats_table").append(table)
 
 
-
     process_id = (values...) ->
         ### Make an id or a class valid javascript by, for example, eliminating spaces ###
         processed = ""
diff --git a/wqflask/wqflask/static/new/javascript/show_trait.js b/wqflask/wqflask/static/new/javascript/show_trait.js
index f554267f..4e7fe8f8 100644
--- a/wqflask/wqflask/static/new/javascript/show_trait.js
+++ b/wqflask/wqflask/static/new/javascript/show_trait.js
@@ -56,7 +56,274 @@
   ];
 
   $(function() {
-    var 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, show_hide_outliers, stats_mdp_change, update_stat_values;
+    var Histogram, 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;
+    Histogram = (function() {
+
+      function Histogram(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);
+        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') {
+            return _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 {
+            return _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]];
+              }
+            });
+          }
+        });
+        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);
+          }
+        });
+      }
+
+      Histogram.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();
+        this.attr_color_dict = {};
+        _ref = js_data.attribute_names;
+        _results = [];
+        for (key in _ref) {
+          if (!__hasProp.call(_ref, key)) continue;
+          attribute_info = _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);
+          }
+          _results.push(this.attr_color_dict[attribute_info.name] = this_color_dict);
+        }
+        return _results;
+      };
+
+      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);
+          }
+        }
+        this.samples = _.zip(this.sample_names, this.sample_vals, this.sample_attr_vals);
+        this.get_attr_color_dict();
+        return console.log("samples:", this.samples);
+      };
+
+      Histogram.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;
+      };
+
+      Histogram.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]);
+      };
+
+      Histogram.prototype.create_graph = function() {
+        this.add_x_axis(this.x_scale);
+        this.add_y_axis();
+        return this.add_bars();
+      };
+
+      Histogram.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)";
+        });
+      };
+
+      Histogram.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");
+      };
+
+      Histogram.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];
+        });
+      };
+
+      Histogram.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;
+      };
+
+      return Histogram;
+
+    })();
+    sample_lists = js_data.sample_lists;
+    sample_group_types = js_data.sample_group_types;
+    new Histogram(sample_lists[0]);
+    $('.stats_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 Histogram(sample_lists[0]);
+      } else if (group === "samples_other") {
+        return new Histogram(sample_lists[1]);
+      } else if (group === "samples_all") {
+        all_samples = sample_lists[0].concat(sample_lists[1]);
+        return new Histogram(all_samples);
+      }
+    });
     hide_tabs = function(start) {
       var x, _i, _results;
       _results = [];
@@ -77,7 +344,6 @@
       console.log("the_id:", id);
       in_box = $(id).html;
       current_value = parseFloat($(in_box)).toFixed(decimal_places);
-      console.log("urgh:", category, value_type);
       the_value = sample_sets[category][value_type]();
       console.log("After running sample_sets, the_value is:", the_value);
       if (decimal_places > 0) {
@@ -127,7 +393,6 @@
       for (_i = 0, _len = tables.length; _i < _len; _i++) {
         table = tables[_i];
         rows = $("#" + table).find('tr');
-        console.log("[fuji3] rows:", rows);
         for (_j = 0, _len1 = rows.length; _j < _len1; _j++) {
           row = rows[_j];
           name = $(row).find('.edit_sample_sample_name').html();
diff --git a/wqflask/wqflask/templates/correlation_page.html b/wqflask/wqflask/templates/correlation_page.html
index 7e149506..d675b801 100644
--- a/wqflask/wqflask/templates/correlation_page.html
+++ b/wqflask/wqflask/templates/correlation_page.html
@@ -9,55 +9,76 @@
     
     {{ header("Correlation", 'Trait: {} Dataset: {}'.format(this_trait.name, dataset.name)) }}
 
-    <table id="corr_results" class="table table-hover table-striped table-bordered">
-        <thead>
-            <tr>
-                <th>Trait</th>
-                <th>Symbol</th>
-                <th>Alias</th>
-                <th>Description</th>
-                <th>Location</th>
-                <th>Mean Expr</th>
-                <th>Max LRS</th>
-                <th>Max LRS Location</th>
-                {% if corr_method == 'pearson' %}
-                <th>Sample r</th>
-                <th>N Cases</th>
-                <th>Sample p(r)</th>
-                <th>Lit Corr</th>
-                <th>Tissue r</th>
-                <th>Tissue p(r)</th>
-                {% else %}
-                <th>Sample rho</th>
-                <th>Sample p(rho)</th>
-                <th>Lit Corr</th>
-                <th>Tissue rho</th>
-                <th>Tissue p(rho)</th>
-                {% endif %}
+    <div class="container">
+        <div class="page-header">
+            <h1>Correlation Table</h1>
+        </div>
+
+        <p>Values of record {{ this_trait.name }} in the <a href="/dbdoc/{{dataset.fullname}}">{{ dataset.fullname }}</a>
+        dataset were compared to all records in the <a href="/dbdoc/{{target_dataset.fullname}}">{{ target_dataset.fullname }}</a>
+        dataset. The top {{ return_number }} correlations ranked by the {{ formatted_corr_type }} are displayed.
+        You can resort this list by clicking the headers. Select the Record ID to open the trait data
+        and analysis page.
+        </p>    
+
+        <div>
+            <table id="corr_results" class="table table-hover table-striped table-bordered">
+                <thead>
+                    <tr>
+                        <th>Trait</th>
+                        <th>Symbol</th>
+                        <th>Description</th>
+                        <th>Location</th>
+                        <th>Mean Expr</th>
+                        <th>Max LRS</th>
+                        <th>Max LRS Location</th>
+                        {% if corr_method == 'pearson' %}
+                        <th>Sample r</th>
+                        <th>N Cases</th>
+                        <th>Sample p(r)</th>
+                        <th>Lit Corr</th>
+                        <th>Tissue r</th>
+                        <th>Tissue p(r)</th>
+                        {% else %}
+                        <th>Sample rho</th>
+                        <th>N Cases</th>
+                        <th>Sample p(rho)</th>
+                        <th>Lit Corr</th>
+                        <th>Tissue rho</th>
+                        <th>Tissue p(rho)</th>
+                        {% endif %}
+                    </tr>
+                </thead>
+                <tbody>
+                {% for trait in correlation_results %}
+                    <tr>
+                        <td><a href="/show_trait?trait_id={{trait.name}}&amp;dataset={{trait.dataset.name}}">{{ trait.name }}</a></td>
+                        <td>{{ trait.symbol }}</td>
+                        <td>{{ trait.description }} <br><br> <b>Aliases</b>: {{ trait.alias }}</td>
+                        <td>Chr{{ trait.chr }}: {{'%0.3f'|format(trait.mb) }}</td>
+                        <td>{{'%0.3f'|format(trait.mean)}}</td>
+                        <td>{{'%0.3f'|format(trait.lrs)}}</td>
+                        <td>Chr{{ trait.locus_chr }}: {{'%0.3f'|format(trait.locus_mb) }}</td>
+                        <td>{{'%0.3f'|format(trait.sample_r)}}</td>
+                        <td>{{ trait.num_overlap }}</td>
+                        <td>{{'%0.3e'|format(trait.sample_p)}}</td>
+                        <td>{{'%0.3f'|format(trait.lit_corr)}}</td>
+                        <td>{{'%0.3f'|format(trait.tissue_corr)}}</td>
+                        <td>{{'%0.3e'|format(trait.tissue_pvalue)}}</td>
+                    </tr>
+                {% endfor %}
+                </tbody>
+            </table>
             
-            </tr>
-        </thead>
-        <tbody>
-        {% for trait in correlation_results %}
-            <tr>
-                <td><a href="/show_trait?trait_id={{trait.name}}&amp;dataset={{trait.dataset.name}}">{{ trait.name }}</a></td>
-                <td>{{ trait.symbol }}</td>
-                <td>{{ trait.alias }}</td>
-                <td>{{ trait.description }}</td>
-                <td>Chr{{ trait.chr }}:{{trait.mb}}</td>
-                <td>{{'%0.3f'|format(trait.mean)}}</td>
-                <td>{{'%0.3f'|format(trait.lrs)}}</td>
-                <td>Chr{{ trait.locus_chr }}:{{'%0.6f'|format(trait.locus_mb)}}</td>
-                <td>{{'%0.3f'|format(trait.sample_r)}}</td>
-                <td>{{ trait.num_overlap }}</td>
-                <td>{{'%0.3e'|format(trait.sample_p)}}</td>
-                <td>{{'%0.3f'|format(trait.lit_corr)}}</td>
-                <td>{{'%0.3f'|format(trait.tissue_corr)}}</td>
-                <td>{{'%0.3e'|format(trait.tissue_pvalue)}}</td>
-            </tr>
-        {% endfor %}
-        </tbody>
-    </table>
+            <br />
+
+<!--            <button class="btn"><i class="icon-ok"></i> Select</button>
+            <button class="btn"><i class="icon-remove"></i> Deselect</button>
+            <button class="btn"><i class="icon-resize-vertical"></i> Invert</button>
+            <button class="btn"><i class="icon-plus-sign"></i> Add</button>
+            <button class="btn btn-primary pull-right"><i class="icon-download icon-white"></i> Download Table</button>-->
+        </div>
+    </div>
 {% endblock %}
 
 {% block js %}  
@@ -92,4 +113,4 @@
             console.timeEnd("Creating table");
         });
     </script>
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/wqflask/wqflask/templates/quick_search.html b/wqflask/wqflask/templates/quick_search.html
index 2f268c5a..fe6f3f65 100644
--- a/wqflask/wqflask/templates/quick_search.html
+++ b/wqflask/wqflask/templates/quick_search.html
@@ -3,15 +3,14 @@
 {% block content %}
 <!-- Start of body -->
 
-    {{ header("QuickSearch Results",
-        'GeneNetwork found {}.'.format(numify(results|count, "record", "records"))) }}
+    {{ header("QuickSearch Results") }}
 
     <div class="container">
         <div class="page-header">
             <h1>Your Search</h1>
         </div>
 
-        <p>We across all data sets to find all records that match:</p>
+        <p>We searched across all data sets to find all records that match:</p>
 
         <ul>
             {% if search_terms %}
@@ -276,7 +275,7 @@
             console.time("Creating table");
             $('#pheno_results, #mrna_assay_results, #geno_results').dataTable( {
                 //"sDom": "<<'span3'l><'span3'T><'span4'f>'row-fluid'r>t<'row-fluid'<'span6'i><'span6'p>>",
-                "sDom": "lTftipr",
+                //"sDom": "lTftipr",
                 "oTableTools": {
                     "aButtons": [
                         "copy",
diff --git a/wqflask/wqflask/templates/search_result_page.html b/wqflask/wqflask/templates/search_result_page.html
index b29e6482..5bd6534c 100644
--- a/wqflask/wqflask/templates/search_result_page.html
+++ b/wqflask/wqflask/templates/search_result_page.html
@@ -10,7 +10,7 @@
             <h1>Your Search</h1>
         </div>
 
-        <p>We searched <a href="/dbdoc/{{dataset.fullname}}">{{ dataset.fullname }}</a><//>
+        <p>We searched <a href="/dbdoc/{{dataset.fullname}}">{{ dataset.fullname }}</a></p>
 
         <p>To find all records that match:</p>
         <ul>
@@ -85,7 +85,6 @@
             <button class="btn" id="add"><i class="icon-plus-sign"></i> Add</button>
             <button class="btn btn-primary pull-right"><i class="icon-download icon-white"></i> Download Table</button>
         </div>
-
     </div>
 
     <div id="myModal"></div>
diff --git a/wqflask/wqflask/templates/show_trait.html b/wqflask/wqflask/templates/show_trait.html
index e3c84de7..5d77750c 100644
--- a/wqflask/wqflask/templates/show_trait.html
+++ b/wqflask/wqflask/templates/show_trait.html
@@ -2,6 +2,7 @@
 {% block title %}Trait Data and Analysis{% endblock %}
 {% 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/packages/DataTables/css/jquery.dataTables.css" />
     <link rel="stylesheet" type="text/css" href="/static/packages/DT_bootstrap/DT_bootstrap.css" />
 {% endblock %}
@@ -28,7 +29,7 @@
             </div>
             
             {% include 'show_trait_details.html' %}
-        {#  {% include 'show_trait_statistics.html' %}    #}
+            {% include 'show_trait_statistics_new.html' %}
             {% include 'show_trait_calculate_correlations.html' %}
             {% include 'show_trait_mapping_tools.html' %}
             {% include 'show_trait_edit_data.html' %}
diff --git a/wqflask/wqflask/templates/show_trait_statistics_new.html b/wqflask/wqflask/templates/show_trait_statistics_new.html
new file mode 100644
index 00000000..105c4f95
--- /dev/null
+++ b/wqflask/wqflask/templates/show_trait_statistics_new.html
@@ -0,0 +1,29 @@
+<div>

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

+        {% endif %}

+        <button type="button" id="update_bar_chart">Sort By Value</button>

+        <div id="bar_chart_container">

+            <div id="bar_chart"></div>

+        </div>

+        

+    </div>

+</div>
\ No newline at end of file
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index 6c9addbc..22973045 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -32,6 +32,7 @@ from base.data_set import create_datasets_list
 from wqflask.show_trait import show_trait
 from wqflask.show_trait import export_trait_data
 from wqflask.marker_regression import marker_regression
+#from wqflask.interval_mapping import interval_mapping
 from wqflask.correlation import show_corr_results
 from utility import temp_data
 
@@ -247,6 +248,49 @@ def marker_regression_page():
 
     return rendered_template
 
+@app.route("/interval_mapping", methods=('POST',))
+def interval_mapping_page():
+    initial_start_vars = request.form
+    temp_uuid = initial_start_vars['temp_uuid']
+    wanted = (
+        'trait_id',
+        'dataset',
+        'suggestive'
+    )
+
+    start_vars = {}
+    for key, value in initial_start_vars.iteritems():
+        if key in wanted or key.startswith(('value:')):
+            start_vars[key] = value
+
+    version = "v1"
+    key = "interval_mapping:{}:".format(version) + json.dumps(start_vars, sort_keys=True)
+    print("key is:", pf(key))
+    with Bench("Loading cache"):
+        result = Redis.get(key)
+
+    if result:
+        print("Cache hit!!!")
+        with Bench("Loading results"):
+            result = pickle.loads(result)
+    else:
+        print("Cache miss!!!")
+        template_vars = interval_mapping.IntervalMapping(start_vars, temp_uuid)
+
+        template_vars.js_data = json.dumps(template_vars.js_data,
+                                           default=json_default_handler,
+                                           indent="   ")
+
+        result = template_vars.__dict__
+        
+        #causeerror
+        Redis.set(key, pickle.dumps(result, pickle.HIGHEST_PROTOCOL))
+        Redis.expire(key, 60*60)
+
+    with Bench("Rendering template"):
+        rendered_template = render_template("interval_mapping.html", **result)
+
+    return rendered_template
 
 @app.route("/corr_compute", methods=('POST',))
 def corr_compute_page():