about summary refs log tree commit diff
diff options
context:
space:
mode:
authorZachary Sloan2014-07-14 16:38:22 +0000
committerZachary Sloan2014-07-14 16:38:22 +0000
commit9c9ab3fc175306e4ed9b67facdcd65bbe63066eb (patch)
tree270a6d7728e7ac25341be1b332b229a98c13ee7a
parentfbdbf4b7410185e2a978ecc8e120ae56ff6da0ce (diff)
downloadgenenetwork2-9c9ab3fc175306e4ed9b67facdcd65bbe63066eb.tar.gz
Made interval map zoom look better
Started creating probability plot for show trait page

Added outlier detection message when user does mapping
-rwxr-xr-xwqflask/wqflask/correlation_matrix/.show_corr_matrix.py.swnbin16384 -> 0 bytes
-rwxr-xr-xwqflask/wqflask/marker_regression/marker_regression.py7
-rwxr-xr-xwqflask/wqflask/show_trait/SampleList.py11
-rwxr-xr-xwqflask/wqflask/show_trait/show_trait.py1
-rw-r--r--wqflask/wqflask/static/new/css/panelutil.css4
-rw-r--r--wqflask/wqflask/static/new/css/show_trait.css3
-rw-r--r--wqflask/wqflask/static/new/javascript/create_interval_map.coffee26
-rw-r--r--wqflask/wqflask/static/new/javascript/create_interval_map.js14
-rw-r--r--wqflask/wqflask/static/new/javascript/create_manhattan_plot.coffee21
-rw-r--r--wqflask/wqflask/static/new/javascript/create_manhattan_plot.js14
-rwxr-xr-xwqflask/wqflask/static/new/javascript/dataset_select_menu.js137
-rw-r--r--wqflask/wqflask/static/new/javascript/draw_probability_plot.coffee37
-rw-r--r--wqflask/wqflask/static/new/javascript/lod_chart.coffee12
-rw-r--r--wqflask/wqflask/static/new/javascript/lod_chart.js12
-rw-r--r--wqflask/wqflask/static/new/javascript/manhattan_plot.coffee97
-rw-r--r--wqflask/wqflask/static/new/javascript/manhattan_plot.js10
-rw-r--r--wqflask/wqflask/static/new/javascript/probability_plot.coffee424
-rwxr-xr-xwqflask/wqflask/static/new/javascript/show_trait.coffee4
-rwxr-xr-xwqflask/wqflask/static/new/javascript/show_trait.js4
-rwxr-xr-xwqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee194
-rwxr-xr-xwqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js127
-rwxr-xr-xwqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables.css2
-rwxr-xr-xwqflask/wqflask/templates/corr_scatter_plot_old.html63
-rwxr-xr-xwqflask/wqflask/templates/interval_mapping.html7
-rwxr-xr-xwqflask/wqflask/templates/marker_regression.html7
-rw-r--r--wqflask/wqflask/templates/marker_regression_old.html106
-rwxr-xr-xwqflask/wqflask/templates/show_trait.html3
-rwxr-xr-xwqflask/wqflask/templates/show_trait_mapping_tools.html1
-rwxr-xr-xwqflask/wqflask/views.py12
29 files changed, 900 insertions, 460 deletions
diff --git a/wqflask/wqflask/correlation_matrix/.show_corr_matrix.py.swn b/wqflask/wqflask/correlation_matrix/.show_corr_matrix.py.swn
deleted file mode 100755
index fd928439..00000000
--- a/wqflask/wqflask/correlation_matrix/.show_corr_matrix.py.swn
+++ /dev/null
Binary files differdiff --git a/wqflask/wqflask/marker_regression/marker_regression.py b/wqflask/wqflask/marker_regression/marker_regression.py
index 30c6453c..0bee5994 100755
--- a/wqflask/wqflask/marker_regression/marker_regression.py
+++ b/wqflask/wqflask/marker_regression/marker_regression.py
@@ -65,6 +65,8 @@ class MarkerRegression(object):
         self.dataset.group.get_markers()

         if self.mapping_method == "gemma":

             qtl_results = self.run_gemma()

+        elif self.mapping_method == "rqtl":

+            qtl_results = self.run_rqtl()

         elif self.mapping_method == "plink":

             qtl_results = self.run_plink()

             #print("qtl_results:", pf(qtl_results))

@@ -184,6 +186,11 @@ class MarkerRegression(object):
     #

     #

     

+    #def run_rqtl(self):

+    #    os.chdir("/home/zas1024/plink")

+    #    

+    

+    

     def run_plink(self):

     

         os.chdir("/home/zas1024/plink")

diff --git a/wqflask/wqflask/show_trait/SampleList.py b/wqflask/wqflask/show_trait/SampleList.py
index 9cd7d895..6be6ddcd 100755
--- a/wqflask/wqflask/show_trait/SampleList.py
+++ b/wqflask/wqflask/show_trait/SampleList.py
@@ -6,6 +6,8 @@ from base import webqtlCaseData
 from utility import webqtlUtil, Plot, Bunch
 from base.trait import GeneralTrait
 
+import numpy as np
+from scipy import stats
 from pprint import pformat as pf
 
 class SampleList(object):
@@ -71,6 +73,15 @@ class SampleList(object):
     def __repr__(self):
         return "<SampleList> --> %s" % (pf(self.__dict__))
 
+    def get_z_scores(self):
+        values = [sample.value for sample in self.sample_list if sample.value != None]
+        numpy_array = np.array(values)
+        z_scores = stats.zscore(numpy_array)
+        
+        for i, sample in enumerate(self.sample_list):
+            if sample.value:
+                sample.z_score = z_scores[i]
+        
     def do_outliers(self):
         values = [sample.value for sample in self.sample_list if sample.value != None]
         upper_bound, lower_bound = Plot.find_outliers(values)
diff --git a/wqflask/wqflask/show_trait/show_trait.py b/wqflask/wqflask/show_trait/show_trait.py
index 670a1188..a7dd59d5 100755
--- a/wqflask/wqflask/show_trait/show_trait.py
+++ b/wqflask/wqflask/show_trait/show_trait.py
@@ -97,6 +97,7 @@ class ShowTrait(object):
 
         hddn['trait_id'] = self.trait_id
         hddn['dataset'] = self.dataset.name
+        hddn['use_outliers'] = False
         hddn['method'] = "pylmm"
         hddn['mapping_display_all'] = True
         hddn['suggestive'] = 0
diff --git a/wqflask/wqflask/static/new/css/panelutil.css b/wqflask/wqflask/static/new/css/panelutil.css
index 35e40db7..ff363e49 100644
--- a/wqflask/wqflask/static/new/css/panelutil.css
+++ b/wqflask/wqflask/static/new/css/panelutil.css
@@ -30,7 +30,7 @@ div.qtlcharts .x.axis text.title {
   fill: slateblue;

 }

 

-div.qtlcharts line.axis.grid {

+/*div.qtlcharts line.axis.grid {

   fill: none;

   stroke-width: 1;

   pointer-events: none;

@@ -48,7 +48,7 @@ div.qtlcharts line.y.axis.grid {
 div.qtlcharts .extent {

   fill: #cac;

   opacity: 0.3;

-}

+}*/

 

 div.qtlcharts circle.selected {

   fill: hotpink;

diff --git a/wqflask/wqflask/static/new/css/show_trait.css b/wqflask/wqflask/static/new/css/show_trait.css
new file mode 100644
index 00000000..9dcbfce9
--- /dev/null
+++ b/wqflask/wqflask/static/new/css/show_trait.css
@@ -0,0 +1,3 @@
+tr .outlier {

+    background-color: #ffff99;

+}
\ No newline at end of file
diff --git a/wqflask/wqflask/static/new/javascript/create_interval_map.coffee b/wqflask/wqflask/static/new/javascript/create_interval_map.coffee
index cacba03e..2b4b20c8 100644
--- a/wqflask/wqflask/static/new/javascript/create_interval_map.coffee
+++ b/wqflask/wqflask/static/new/javascript/create_interval_map.coffee
@@ -1,4 +1,4 @@
-create_interval_map = ->

+create_interval_map = () ->

     h = 500

     w = 1200

     margin = {left:60, top:40, right:40, bottom: 40, inner:5}

@@ -39,6 +39,7 @@ create_interval_map = ->
 create_interval_map()

 

 $("#export").click =>

+    

     #Get d3 SVG element

     svg = $("#topchart").find("svg")[0]

     

@@ -54,6 +55,29 @@ $("#export").click =>
     form.find("#data").val(svg_xml)

     form.find("#filename").val(filename)

     form.submit()

+    

+

+$("#export_pdf").click =>

+    

+    #$('#topchart').remove()

+    #$('#chart_container').append('<div class="qtlcharts" id="topchart"></div>')

+    #create_interval_map()

+    

+    #Get d3 SVG element

+    svg = $("#topchart").find("svg")[0]

+    

+    #Extract SVG text string

+    svg_xml = (new XMLSerializer).serializeToString(svg)

+    console.log("svg_xml:", svg_xml)

+        

+    #Set filename

+    filename = "interval_map_pdf"

+

+    #Make a form with the SVG data

+    form = $("#exportpdfform")

+    form.find("#data").val(svg_xml)

+    form.find("#filename").val(filename)

+    form.submit()

 

 # two LOD charts within one SVG

 #d3.json "data.json", (data) ->

diff --git a/wqflask/wqflask/static/new/javascript/create_interval_map.js b/wqflask/wqflask/static/new/javascript/create_interval_map.js
index 5041cfea..341e92c0 100644
--- a/wqflask/wqflask/static/new/javascript/create_interval_map.js
+++ b/wqflask/wqflask/static/new/javascript/create_interval_map.js
@@ -51,3 +51,17 @@ $("#export").click((function(_this) {
     return form.submit();
   };
 })(this));
+
+$("#export_pdf").click((function(_this) {
+  return function() {
+    var filename, form, svg, svg_xml;
+    svg = $("#topchart").find("svg")[0];
+    svg_xml = (new XMLSerializer).serializeToString(svg);
+    console.log("svg_xml:", svg_xml);
+    filename = "interval_map_pdf";
+    form = $("#exportpdfform");
+    form.find("#data").val(svg_xml);
+    form.find("#filename").val(filename);
+    return form.submit();
+  };
+})(this));
diff --git a/wqflask/wqflask/static/new/javascript/create_manhattan_plot.coffee b/wqflask/wqflask/static/new/javascript/create_manhattan_plot.coffee
index 258d5c01..05ad5419 100644
--- a/wqflask/wqflask/static/new/javascript/create_manhattan_plot.coffee
+++ b/wqflask/wqflask/static/new/javascript/create_manhattan_plot.coffee
@@ -55,3 +55,24 @@ $("#export").click =>
     form.find("#filename").val(filename)

     form.submit()

 

+$("#export_pdf").click =>

+    

+    #$('#topchart').remove()

+    #$('#chart_container').append('<div class="qtlcharts" id="topchart"></div>')

+    #create_interval_map()

+    

+    #Get d3 SVG element

+    svg = $("#topchart").find("svg")[0]

+    

+    #Extract SVG text string

+    svg_xml = (new XMLSerializer).serializeToString(svg)

+    console.log("svg_xml:", svg_xml)

+        

+    #Set filename

+    filename = "manhattan_plot_" + js_data.this_trait

+

+    #Make a form with the SVG data

+    form = $("#exportpdfform")

+    form.find("#data").val(svg_xml)

+    form.find("#filename").val(filename)

+    form.submit()

diff --git a/wqflask/wqflask/static/new/javascript/create_manhattan_plot.js b/wqflask/wqflask/static/new/javascript/create_manhattan_plot.js
index 7daaa921..62584fb2 100644
--- a/wqflask/wqflask/static/new/javascript/create_manhattan_plot.js
+++ b/wqflask/wqflask/static/new/javascript/create_manhattan_plot.js
@@ -51,3 +51,17 @@ $("#export").click((function(_this) {
     return form.submit();
   };
 })(this));
+
+$("#export_pdf").click((function(_this) {
+  return function() {
+    var filename, form, svg, svg_xml;
+    svg = $("#topchart").find("svg")[0];
+    svg_xml = (new XMLSerializer).serializeToString(svg);
+    console.log("svg_xml:", svg_xml);
+    filename = "manhattan_plot_" + js_data.this_trait;
+    form = $("#exportpdfform");
+    form.find("#data").val(svg_xml);
+    form.find("#filename").val(filename);
+    return form.submit();
+  };
+})(this));
diff --git a/wqflask/wqflask/static/new/javascript/dataset_select_menu.js b/wqflask/wqflask/static/new/javascript/dataset_select_menu.js
deleted file mode 100755
index f4ca2c37..00000000
--- a/wqflask/wqflask/static/new/javascript/dataset_select_menu.js
+++ /dev/null
@@ -1,137 +0,0 @@
-// Generated by CoffeeScript 1.7.1
-$(function() {
-  var apply_default, dataset_info, group_info, make_default, open_window, populate_dataset, populate_group, populate_species, populate_type, process_json, redo_dropdown;
-  process_json = function(data) {
-    window.jdata = data;
-    populate_species();
-    return apply_default();
-  };
-  $.ajax('/static/new/javascript/dataset_menu_structure.json', {
-    dataType: 'json',
-    success: process_json
-  });
-  populate_species = function() {
-    var species_list;
-    species_list = this.jdata.species;
-    redo_dropdown($('#species'), species_list);
-    return populate_group();
-  };
-  window.populate_species = populate_species;
-  populate_group = function() {
-    var group_list, species;
-    console.log("in populate group");
-    species = $('#species').val();
-    group_list = this.jdata.groups[species];
-    redo_dropdown($('#group'), group_list);
-    return populate_type();
-  };
-  window.populate_group = populate_group;
-  populate_type = function() {
-    var group, species, type_list;
-    species = $('#species').val();
-    group = $('#group').val();
-    type_list = this.jdata.types[species][group];
-    redo_dropdown($('#type'), type_list);
-    return populate_dataset();
-  };
-  window.populate_type = populate_type;
-  populate_dataset = function() {
-    var dataset_list, group, species, type;
-    species = $('#species').val();
-    group = $('#group').val();
-    type = $('#type').val();
-    console.log("sgt:", species, group, type);
-    dataset_list = this.jdata.datasets[species][group][type];
-    console.log("pop_dataset:", dataset_list);
-    return redo_dropdown($('#dataset'), dataset_list);
-  };
-  window.populate_dataset = populate_dataset;
-  redo_dropdown = function(dropdown, items) {
-    var item, _i, _len, _results;
-    console.log("in redo:", dropdown, items);
-    dropdown.empty();
-    _results = [];
-    for (_i = 0, _len = items.length; _i < _len; _i++) {
-      item = items[_i];
-      _results.push(dropdown.append($("<option />").val(item[0]).text(item[1])));
-    }
-    return _results;
-  };
-  $('#species').change((function(_this) {
-    return function() {
-      return populate_group();
-    };
-  })(this));
-  $('#group').change((function(_this) {
-    return function() {
-      return populate_type();
-    };
-  })(this));
-  $('#type').change((function(_this) {
-    return function() {
-      return populate_dataset();
-    };
-  })(this));
-  open_window = function(url, name) {
-    var options;
-    options = "menubar=1,toolbar=1,location=1,resizable=1,status=1,scrollbars=1,directories=1,width=900";
-    return open(url, name, options).focus();
-  };
-  group_info = function() {
-    var group, species, url;
-    species = $('#species').val();
-    group = $('#group').val();
-    url = "/" + species + "Cross.html#" + group;
-    return open_window(url, "Group Info");
-  };
-  $('#group_info').click(group_info);
-  dataset_info = function() {
-    var dataset, url;
-    dataset = $('#dataset').val();
-    url = "/webqtl/main.py?FormID=sharinginfo&InfoPageName=" + dataset;
-    return open_window(url, "Dataset Info");
-  };
-  $('#dataset_info').click(dataset_info);
-  make_default = function() {
-    var holder, item, jholder, _i, _len, _ref;
-    holder = {};
-    _ref = ['species', 'group', 'type', 'dataset'];
-    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
-      item = _ref[_i];
-      holder[item] = $("#" + item).val();
-    }
-    jholder = JSON.stringify(holder);
-    return $.cookie('search_defaults', jholder, {
-      expires: 365
-    });
-  };
-  apply_default = function() {
-    var defaults, item, populate_function, _i, _len, _ref, _results;
-    defaults = $.cookie('search_defaults');
-    if (defaults) {
-      defaults = $.parseJSON(defaults);
-    } else {
-      defaults = {
-        species: "mouse",
-        group: "BXD",
-        type: "Hippocampus mRNA",
-        dataset: "HC_M2_0606_P"
-      };
-    }
-    _ref = [['species', 'group'], ['group', 'type'], ['type', 'dataset'], ['dataset', null]];
-    _results = [];
-    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
-      item = _ref[_i];
-      $("#" + item[0]).val(defaults[item[0]]);
-      if (item[1]) {
-        populate_function = "populate_" + item[1];
-        console.log("Calling:", populate_function);
-        _results.push(window[populate_function]());
-      } else {
-        _results.push(void 0);
-      }
-    }
-    return _results;
-  };
-  return $("#make_default").click(make_default);
-});
diff --git a/wqflask/wqflask/static/new/javascript/draw_probability_plot.coffee b/wqflask/wqflask/static/new/javascript/draw_probability_plot.coffee
new file mode 100644
index 00000000..90db990a
--- /dev/null
+++ b/wqflask/wqflask/static/new/javascript/draw_probability_plot.coffee
@@ -0,0 +1,37 @@
+# illustration of use of the scatterplot function

+

+h = 400

+w = 500

+margin = {left:60, top:40, right:40, bottom: 40, inner:5}

+halfh = (h+margin.top+margin.bottom)

+totalh = halfh*2

+halfw = (w+margin.left+margin.right)

+totalw = halfw*2

+

+# Example 1: simplest use

+#d3.json "data.json", (data) ->

+mychart = scatterplot().xvar(0)

+                       .yvar(1)

+                       .xlab(js_data.trait_1)

+                       .ylab(js_data.trait_2)

+                       .height(h)

+                       .width(w)

+                       .margin(margin)

+

+data = js_data.data

+indID = js_data.indIDs

+slope = js_data.slope

+intercept = js_data.intercept

+

+console.log("THE DATA IS:", data)

+

+d3.select("div#chart1")

+  .datum({data:data, indID:indID, slope:slope, intercept:intercept})

+  .call(mychart)

+

+# animate points

+mychart.pointsSelect()

+          .on "mouseover", (d) ->

+             d3.select(this).attr("r", mychart.pointsize()*3)

+          .on "mouseout", (d) ->

+             d3.select(this).attr("r", mychart.pointsize())

diff --git a/wqflask/wqflask/static/new/javascript/lod_chart.coffee b/wqflask/wqflask/static/new/javascript/lod_chart.coffee
index 777aac2a..8794625a 100644
--- a/wqflask/wqflask/static/new/javascript/lod_chart.coffee
+++ b/wqflask/wqflask/static/new/javascript/lod_chart.coffee
@@ -123,6 +123,8 @@ lodchart = () ->
              .text((d) -> d[0])

              .attr("x", (d,i) -> (data.chrStart[i]+data.chrEnd[i])/2)

              .attr("y", margin.top+height+axispos.xlabel)

+             .attr("dominant-baseline", "hanging")

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

              .attr("cursor", "pointer")

              .on("click", (d) ->

                  redraw_plot(d)

@@ -131,6 +133,7 @@ lodchart = () ->
         xaxis.append("text").attr("class", "title")

              .attr("y", margin.top+height+axispos.xtitle)

              .attr("x", margin.left+width/2)

+             .attr("fill", "slateblue")

              .text(xlab)

 

   

@@ -164,6 +167,8 @@ lodchart = () ->
              .attr("y", (d) -> yscale(d))

              .attr("x", margin.left-axispos.ylabel)

              .attr("fill", "blue")

+             .attr("dominant-baseline", "middle")

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

              .text((d) -> formatAxis(yticks)(d))

              

         yaxis.append("text").attr("class", "title")

@@ -171,6 +176,8 @@ lodchart = () ->
              .attr("x", margin.left-axispos.ytitle)

              .text(ylab)

              .attr("transform", if rotate_ylab then "rotate(270,#{margin.left-axispos.ytitle},#{margin.top+height/2})" else "")

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

+             .attr("fill", "slateblue")

   

         if data['additive'].length > 0

             rotate_additive_ylab = rotate_additive_ylab ? (additive_ylab.length > 1)

@@ -195,6 +202,8 @@ lodchart = () ->
                  .attr("y", (d) -> additive_yscale(d))

                  .attr("x", (d) -> margin.left + width + axispos.ylabel + 20)

                  .attr("fill", "green")

+                 .attr("dominant-baseline", "middle")

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

                  .text((d) -> formatAxis(additive_yticks)(d))

                  

             additive_yaxis.append("text").attr("class", "title")

@@ -202,7 +211,8 @@ lodchart = () ->
                  .attr("x", margin.left + width + axispos.ytitle)

                  .text(additive_ylab)

                  .attr("transform", if rotate_additive_ylab then "rotate(270,#{margin.left + width + axispos.ytitle}, #{margin.top+height*1.5})" else "")

-  

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

+                 .attr("fill", "green")

   

         suggestive_bar = g.append("g").attr("class", "suggestive")

         suggestive_bar.selectAll("empty")

diff --git a/wqflask/wqflask/static/new/javascript/lod_chart.js b/wqflask/wqflask/static/new/javascript/lod_chart.js
index c974c9d2..75adc792 100644
--- a/wqflask/wqflask/static/new/javascript/lod_chart.js
+++ b/wqflask/wqflask/static/new/javascript/lod_chart.js
@@ -120,10 +120,10 @@ lodchart = function() {
         return d[0];
       }).attr("x", function(d, i) {
         return (data.chrStart[i] + data.chrEnd[i]) / 2;
-      }).attr("y", margin.top + height + axispos.xlabel).attr("cursor", "pointer").on("click", function(d) {
+      }).attr("y", margin.top + height + axispos.xlabel).attr("dominant-baseline", "hanging").attr("text-anchor", "middle").attr("cursor", "pointer").on("click", function(d) {
         return redraw_plot(d);
       });
-      xaxis.append("text").attr("class", "title").attr("y", margin.top + height + axispos.xtitle).attr("x", margin.left + width / 2).text(xlab);
+      xaxis.append("text").attr("class", "title").attr("y", margin.top + height + axispos.xtitle).attr("x", margin.left + width / 2).attr("fill", "slateblue").text(xlab);
       redraw_plot = function(chr_ob) {
         var chr_plot;
         console.log("chr_name is:", chr_ob[0]);
@@ -141,10 +141,10 @@ lodchart = function() {
       }).attr("x1", margin.left).attr("x2", margin.left + 7).attr("fill", "none").attr("stroke", "white").attr("stroke-width", 1).style("pointer-events", "none");
       yaxis.selectAll("empty").data(yticks).enter().append("text").attr("y", function(d) {
         return yscale(d);
-      }).attr("x", margin.left - axispos.ylabel).attr("fill", "blue").text(function(d) {
+      }).attr("x", margin.left - axispos.ylabel).attr("fill", "blue").attr("dominant-baseline", "middle").attr("text-anchor", "end").text(function(d) {
         return formatAxis(yticks)(d);
       });
-      yaxis.append("text").attr("class", "title").attr("y", margin.top + height / 2).attr("x", margin.left - axispos.ytitle).text(ylab).attr("transform", rotate_ylab ? "rotate(270," + (margin.left - axispos.ytitle) + "," + (margin.top + height / 2) + ")" : "");
+      yaxis.append("text").attr("class", "title").attr("y", margin.top + height / 2).attr("x", margin.left - axispos.ytitle).text(ylab).attr("transform", rotate_ylab ? "rotate(270," + (margin.left - axispos.ytitle) + "," + (margin.top + height / 2) + ")" : "").attr("text-anchor", "middle").attr("fill", "slateblue");
       if (data['additive'].length > 0) {
         rotate_additive_ylab = rotate_additive_ylab != null ? rotate_additive_ylab : additive_ylab.length > 1;
         additive_yaxis = g.append("g").attr("class", "y axis");
@@ -157,10 +157,10 @@ lodchart = function() {
           return additive_yscale(d);
         }).attr("x", function(d) {
           return margin.left + width + axispos.ylabel + 20;
-        }).attr("fill", "green").text(function(d) {
+        }).attr("fill", "green").attr("dominant-baseline", "middle").attr("text-anchor", "end").text(function(d) {
           return formatAxis(additive_yticks)(d);
         });
-        additive_yaxis.append("text").attr("class", "title").attr("y", margin.top + 1.5 * height).attr("x", margin.left + width + axispos.ytitle).text(additive_ylab).attr("transform", rotate_additive_ylab ? "rotate(270," + (margin.left + width + axispos.ytitle) + ", " + (margin.top + height * 1.5) + ")" : "");
+        additive_yaxis.append("text").attr("class", "title").attr("y", margin.top + 1.5 * height).attr("x", margin.left + width + axispos.ytitle).text(additive_ylab).attr("transform", rotate_additive_ylab ? "rotate(270," + (margin.left + width + axispos.ytitle) + ", " + (margin.top + height * 1.5) + ")" : "").attr("text-anchor", "middle").attr("fill", "green");
       }
       suggestive_bar = g.append("g").attr("class", "suggestive");
       suggestive_bar.selectAll("empty").data([data.suggestive]).enter().append("line").attr("y1", function(d) {
diff --git a/wqflask/wqflask/static/new/javascript/manhattan_plot.coffee b/wqflask/wqflask/static/new/javascript/manhattan_plot.coffee
index 492c2f3f..37226b8a 100644
--- a/wqflask/wqflask/static/new/javascript/manhattan_plot.coffee
+++ b/wqflask/wqflask/static/new/javascript/manhattan_plot.coffee
@@ -105,10 +105,11 @@ lodchart = () ->
              .data(data.chrnames)

              .enter()

              .append("text")

-             .attr("class", "chr_label")

              .text((d) -> d[0])

              .attr("x", (d,i) -> (data.chrStart[i]+data.chrEnd[i])/2)

              .attr("y", margin.top+height+axispos.xlabel)

+             .attr("dominant-baseline", "hanging")

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

              .attr("cursor", "pointer")

              .on("click", (d) ->

                  redraw_plot(d)

@@ -117,16 +118,18 @@ lodchart = () ->
         xaxis.append("text").attr("class", "title")

              .attr("y", margin.top+height+axispos.xtitle)

              .attr("x", margin.left+width/2)

+             .attr("fill", "slateblue")

              .text(xlab)

-  

+

+

         redraw_plot = (chr_ob) ->

              console.log("chr_name is:", chr_ob[0])

              console.log("chr_length is:", chr_ob[1])

              $('#topchart').remove()

              $('#chart_container').append('<div class="qtlcharts" id="topchart"></div>')

              chr_plot = new Chr_Manhattan_Plot(600, 1200, chr_ob)

-        

-  

+

+

         # y-axis

         rotate_ylab = rotate_ylab ? (ylab.length > 1)

         yaxis = g.append("g").attr("class", "y axis")

@@ -150,6 +153,8 @@ lodchart = () ->
              .attr("y", (d) -> yscale(d))

              .attr("x", margin.left-axispos.ylabel)

              .attr("fill", "blue")

+             .attr("dominant-baseline", "middle")

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

              .text((d) -> formatAxis(yticks)(d))

              

         yaxis.append("text").attr("class", "title")

@@ -157,86 +162,10 @@ lodchart = () ->
              .attr("x", margin.left-axispos.ytitle)

              .text(ylab)

              .attr("transform", if rotate_ylab then "rotate(270,#{margin.left-axispos.ytitle},#{margin.top+height/2})" else "")

-  

-        # lod curves by chr

-        #lodcurve = (chr, lodcolumn) ->

-        #    d3.svg.line()

-        #      .x((d) -> xscale[chr](d))

-        #      .y((d,i) -> yscale(data.lodByChr[chr][i][lodcolumn]))

-              

-          #add_plot_points: () ->

-          #    @plot_point = @svg.selectAll("circle")

-          #        .data(@plot_coordinates)

-          #        .enter()

-          #        .append("circle")

-          #        .attr("cx", (d) =>

-          #            return @x_scale(d[0])

-          #        )

-          #        .attr("cy", (d) =>

-          #            return @y_scale(d[1])

-          #        )

-          #        .attr("r", (d) =>

-          #            #if d[1] > 3

-          #            #    return 3

-          #            #else

-          #            return 2

-          #        )

-          #        .attr("fill", (d) =>

-          #            #if d[1] > 3

-          #            #    return "white"

-          #            #else

-          #            return "black"

-          #        )

-          #        .attr("stroke", "black")

-          #        .attr("stroke-width", "1")

-          #        .attr("id", (d) =>

-          #            return "point_" + String(d[2])

-          #        )

-          #        .classed("circle", true)

-          #        .on("mouseover", (d) =>

-          #            console.log("d3.event is:", d3.event)

-          #            console.log("d is:", d)

-          #            this_id = "point_" + String(d[2])

-          #            d3.select("#" + this_id).classed("d3_highlight", true)

-          #                .attr("r", 5)

-          #                .attr("stroke", "none")

-          #                .attr("fill", "blue")

-          #                .call(@show_marker_in_table(d))

-          #        )

-          #        .on("mouseout", (d) =>

-          #            this_id = "point_" + String(d[2])

-          #            d3.select("#" + this_id).classed("d3_highlight", false)

-          #                .attr("r", (d) =>

-          #                    #if d[1] > 2

-          #                    #    return 3

-          #                    #else

-          #                    return 2

-          #                )

-          #                .attr("fill", (d) =>

-          #                    #if d[1] > 2

-          #                    #    return "white"

-          #                    #else

-          #                    return "black"

-          #                )

-          #                .attr("stroke", "black")

-          #                .attr("stroke-width", "1")

-          #        )

-          #        .append("svg:title")

-          #            .text((d) =>

-          #                return d[2]

-          #            )

-  

-        #curves = g.append("g").attr("id", "curves")

-  

-        #for chr in data.chrnames

-        #  curves.append("path")

-        #        .datum(data.posByChr[chr])

-        #        .attr("d", lodcurve(chr, lodvarnum))

-        #        .attr("stroke", lodlinecolor)

-        #        .attr("fill", "none")

-        #        .attr("stroke-width", linewidth)

-        #        .style("pointer-events", "none")

-  

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

+             .attr("fill", "slateblue")

+

+

         # points at markers

         if pointsize > 0

           markerpoints = g.append("g").attr("id", "markerpoints_visible")

diff --git a/wqflask/wqflask/static/new/javascript/manhattan_plot.js b/wqflask/wqflask/static/new/javascript/manhattan_plot.js
index 546cf9a9..203f3a1b 100644
--- a/wqflask/wqflask/static/new/javascript/manhattan_plot.js
+++ b/wqflask/wqflask/static/new/javascript/manhattan_plot.js
@@ -91,14 +91,14 @@ lodchart = function() {
         return redraw_plot(d);
       });
       xaxis = g.append("g").attr("class", "x axis");
-      xaxis.selectAll("empty").data(data.chrnames).enter().append("text").attr("class", "chr_label").text(function(d) {
+      xaxis.selectAll("empty").data(data.chrnames).enter().append("text").text(function(d) {
         return d[0];
       }).attr("x", function(d, i) {
         return (data.chrStart[i] + data.chrEnd[i]) / 2;
-      }).attr("y", margin.top + height + axispos.xlabel).attr("cursor", "pointer").on("click", function(d) {
+      }).attr("y", margin.top + height + axispos.xlabel).attr("dominant-baseline", "hanging").attr("text-anchor", "middle").attr("cursor", "pointer").on("click", function(d) {
         return redraw_plot(d);
       });
-      xaxis.append("text").attr("class", "title").attr("y", margin.top + height + axispos.xtitle).attr("x", margin.left + width / 2).text(xlab);
+      xaxis.append("text").attr("class", "title").attr("y", margin.top + height + axispos.xtitle).attr("x", margin.left + width / 2).attr("fill", "slateblue").text(xlab);
       redraw_plot = function(chr_ob) {
         var chr_plot;
         console.log("chr_name is:", chr_ob[0]);
@@ -116,10 +116,10 @@ lodchart = function() {
       }).attr("x1", margin.left).attr("x2", margin.left + 7).attr("fill", "none").attr("stroke", "white").attr("stroke-width", 1).style("pointer-events", "none");
       yaxis.selectAll("empty").data(yticks).enter().append("text").attr("y", function(d) {
         return yscale(d);
-      }).attr("x", margin.left - axispos.ylabel).attr("fill", "blue").text(function(d) {
+      }).attr("x", margin.left - axispos.ylabel).attr("fill", "blue").attr("dominant-baseline", "middle").attr("text-anchor", "end").text(function(d) {
         return formatAxis(yticks)(d);
       });
-      yaxis.append("text").attr("class", "title").attr("y", margin.top + height / 2).attr("x", margin.left - axispos.ytitle).text(ylab).attr("transform", rotate_ylab ? "rotate(270," + (margin.left - axispos.ytitle) + "," + (margin.top + height / 2) + ")" : "");
+      yaxis.append("text").attr("class", "title").attr("y", margin.top + height / 2).attr("x", margin.left - axispos.ytitle).text(ylab).attr("transform", rotate_ylab ? "rotate(270," + (margin.left - axispos.ytitle) + "," + (margin.top + height / 2) + ")" : "").attr("text-anchor", "middle").attr("fill", "slateblue");
       if (pointsize > 0) {
         markerpoints = g.append("g").attr("id", "markerpoints_visible");
         markerpoints.selectAll("empty").data(data.markers).enter().append("circle").attr("cx", function(d) {
diff --git a/wqflask/wqflask/static/new/javascript/probability_plot.coffee b/wqflask/wqflask/static/new/javascript/probability_plot.coffee
new file mode 100644
index 00000000..c1f26941
--- /dev/null
+++ b/wqflask/wqflask/static/new/javascript/probability_plot.coffee
@@ -0,0 +1,424 @@
+probability_plot = () ->

+    width = 800

+    height = 600

+    margin = {left:60, top:40, right:40, bottom: 40, inner:5}

+    axispos = {xtitle:25, ytitle:45, xlabel:5, ylabel:5}

+    titlepos = 20

+    xNA = {handle:true, force:false, width:15, gap:10}

+    yNA = {handle:true, force:false, width:15, gap:10}

+    xlim = null

+    ylim = null

+    nxticks = 5

+    xticks = null

+    nyticks = 5

+    yticks = null

+    rectcolor = d3.rgb(230, 230, 230)

+    pointcolor = null

+    pointstroke = "black"

+    pointsize = 3 # default = no visible points at markers

+    title = "Correlation Scatterplot"

+    xlab = "X"

+    ylab = "Y"

+    rotate_ylab = null

+    yscale = d3.scale.linear()

+    xscale = d3.scale.linear()

+    xvar = 0

+    yvar = 1

+    pointsSelect = null

+    dataByInd = false

+  

+    ## the main function

+    chart = (selection) ->

+      selection.each (data) ->

+  

+        if dataByInd

+          x = data.data.map (d) -> d[xvar]

+          y = data.data.map (d) -> d[yvar]

+        else # reorganize data

+          x = data.data[xvar]

+          y = data.data[yvar]

+  

+        console.log("x:", x)

+        console.log("y:", y)

+  

+        # grab indID if it's there

+        # if no indID, create a vector of them

+        indID = data?.indID ? null

+        indID = indID ? [1..x.length]

+  

+        console.log("indID:", indID)

+  

+        # groups of colors

+        group = data?.group ? (1 for i in x)

+        ngroup = d3.max(group)

+        group = (g-1 for g in group) # changed from (1,2,3,...) to (0,1,2,...)

+  

+        # colors of the points in the different groups

+        pointcolor = pointcolor ? selectGroupColors(ngroup, "dark")

+        pointcolor = expand2vector(pointcolor, ngroup)

+  

+        # if all (x,y) not null

+        xNA.handle = false if x.every (v) -> (v?) and !xNA.force

+        yNA.handle = false if y.every (v) -> (v?) and !yNA.force

+        if xNA.handle

+          paneloffset = xNA.width + xNA.gap

+          panelwidth = width - paneloffset

+        else

+          paneloffset = 0

+          panelwidth = width

+        if yNA.handle

+          panelheight = height - (yNA.width + yNA.gap)

+        else

+          panelheight = height

+  

+        xlim = xlim ? d3.extent(x)

+        ylim = ylim ? d3.extent(y)

+  

+        # I'll replace missing values something smaller than what's observed

+        na_value = d3.min(x.concat y) - 100

+  

+        # Select the svg element, if it exists.

+        svg = d3.select(this).selectAll("svg").data([data])

+  

+        # Otherwise, create the skeletal chart.

+        gEnter = svg.enter().append("svg").append("g")

+  

+        # Update the outer dimensions.

+        svg.attr("width", width+margin.left+margin.right)

+           .attr("height", height+margin.top+margin.bottom)

+  

+        g = svg.select("g")

+  

+        # box

+        g.append("rect")

+         .attr("x", paneloffset+margin.left)

+         .attr("y", margin.top)

+         .attr("height", panelheight)

+         .attr("width", panelwidth)

+         .attr("fill", rectcolor)

+         .attr("stroke", "none")

+        if xNA.handle

+          g.append("rect")

+           .attr("x", margin.left)

+           .attr("y", margin.top)

+           .attr("height", panelheight)

+           .attr("width", xNA.width)

+           .attr("fill", rectcolor)

+           .attr("stroke", "none")

+        if xNA.handle and yNA.handle

+          g.append("rect")

+           .attr("x", margin.left)

+           .attr("y", margin.top+height - yNA.width)

+           .attr("height", yNA.width)

+           .attr("width", xNA.width)

+           .attr("fill", rectcolor)

+           .attr("stroke", "none")

+        if yNA.handle

+          g.append("rect")

+           .attr("x", margin.left+paneloffset)

+           .attr("y", margin.top+height-yNA.width)

+           .attr("height", yNA.width)

+           .attr("width", panelwidth)

+           .attr("fill", rectcolor)

+           .attr("stroke", "none")

+  

+        # simple scales (ignore NA business)

+        xrange = [margin.left+paneloffset+margin.inner, margin.left+paneloffset+panelwidth-margin.inner]

+        yrange = [margin.top+panelheight-margin.inner, margin.top+margin.inner]

+        xscale.domain(xlim).range(xrange)

+        yscale.domain(ylim).range(yrange)

+        xs = d3.scale.linear().domain(xlim).range(xrange)

+        ys = d3.scale.linear().domain(ylim).range(yrange)

+  

+        # "polylinear" scales to handle missing values

+        if xNA.handle

+          xscale.domain([na_value].concat xlim) 

+                .range([margin.left + xNA.width/2].concat xrange)

+          x = x.map (e) -> if e? then e else na_value

+        if yNA.handle

+          yscale.domain([na_value].concat ylim)

+                .range([height+margin.top-yNA.width/2].concat yrange)

+          y = y.map (e) -> if e? then e else na_value

+  

+        # if yticks not provided, use nyticks to choose pretty ones

+        yticks = yticks ? ys.ticks(nyticks)

+        xticks = xticks ? xs.ticks(nxticks)

+  

+        # title

+        titlegrp = g.append("g").attr("class", "title")

+         .append("text")

+         .attr("x", margin.left + width/2)

+         .attr("y", margin.top - titlepos)

+         .text(title)

+  

+        # x-axis

+        xaxis = g.append("g").attr("class", "x axis")

+        xaxis.selectAll("empty")

+             .data(xticks)

+             .enter()

+             .append("line")

+             .attr("x1", (d) -> xscale(d))

+             .attr("x2", (d) -> xscale(d))

+             .attr("y1", margin.top)

+             .attr("y2", margin.top+height)

+             .attr("fill", "none")

+             .attr("stroke", "white")

+             .attr("stroke-width", 1)

+             .style("pointer-events", "none")

+        xaxis.selectAll("empty")

+             .data(xticks)

+             .enter()

+             .append("text")

+             .attr("x", (d) -> xscale(d))

+             .attr("y", margin.top+height+axispos.xlabel)

+             .text((d) -> formatAxis(xticks)(d))

+        xaxis.append("text").attr("class", "title")

+             .attr("x", margin.left+width/2)

+             .attr("y", margin.top+height+axispos.xtitle)

+             .text(xlab)

+        if xNA.handle

+          xaxis.append("text")

+              .attr("x", margin.left+xNA.width/2)

+              .attr("y", margin.top+height+axispos.xlabel)

+              .text("N/A")

+  

+        # y-axis

+        rotate_ylab = rotate_ylab ? (ylab.length > 1)

+        yaxis = g.append("g").attr("class", "y axis")

+        yaxis.selectAll("empty")

+             .data(yticks)

+             .enter()

+             .append("line")

+             .attr("y1", (d) -> yscale(d))

+             .attr("y2", (d) -> yscale(d))

+             .attr("x1", margin.left)

+             .attr("x2", margin.left+width)

+             .attr("fill", "none")

+             .attr("stroke", "white")

+             .attr("stroke-width", 1)

+             .style("pointer-events", "none")

+        yaxis.selectAll("empty")

+             .data(yticks)

+             .enter()

+             .append("text")

+             .attr("y", (d) -> yscale(d))

+             .attr("x", margin.left-axispos.ylabel)

+             .text((d) -> formatAxis(yticks)(d))

+        yaxis.append("text").attr("class", "title")

+             .attr("y", margin.top+height/2)

+             .attr("x", margin.left-axispos.ytitle)

+             .text(ylab)

+             .attr("transform", if rotate_ylab then "rotate(270,#{margin.left-axispos.ytitle},#{margin.top+height/2})" else "")

+        if yNA.handle

+          yaxis.append("text")

+              .attr("x", margin.left-axispos.ylabel)

+              .attr("y", margin.top+height-yNA.width/2)

+              .text("N/A")

+  

+        indtip = d3.tip()

+                   .attr('class', 'd3-tip')

+                   .html((d,i) -> indID[i])

+                   .direction('e')

+                   .offset([0,10])

+        svg.call(indtip)

+  

+        #g.append("line")

+        #        .attr("x1")

+        #

+        #g.append("line")

+        #  .attr("x1", xscale(minx))

+        #  .attr("x2", xscale(maxx*0.995))

+        #  .attr("y2", yscale(slope*maxx*0.995+intercept))

+        #  .style("stroke", "black")

+        #  .style("stroke-width", 2);

+  

+        points = g.append("g").attr("id", "points")

+        pointsSelect =

+          points.selectAll("empty")

+                .data(d3.range(x.length))

+                .enter()

+                .append("circle")

+                .attr("cx", (d,i) -> xscale(x[i]))

+                .attr("cy", (d,i) -> yscale(y[i]))

+                .attr("class", (d,i) -> "pt#{i}")

+                .attr("r", pointsize)

+                .attr("fill", (d,i) -> pointcolor[group[i]])

+                .attr("stroke", pointstroke)

+                .attr("stroke-width", "1")

+                .attr("opacity", (d,i) ->

+                     return 1 if (x[i]? or xNA.handle) and (y[i]? or yNA.handle)

+                     return 0)

+                .on("mouseover.paneltip", indtip.show)

+                .on("mouseout.paneltip", indtip.hide)

+  

+        # box

+        g.append("rect")

+               .attr("x", margin.left+paneloffset)

+               .attr("y", margin.top)

+               .attr("height", panelheight)

+               .attr("width", panelwidth)

+               .attr("fill", "none")

+               .attr("stroke", "black")

+               .attr("stroke-width", "none")

+        if xNA.handle

+          g.append("rect")

+           .attr("x", margin.left)

+           .attr("y", margin.top)

+           .attr("height", panelheight)

+           .attr("width", xNA.width)

+           .attr("fill", "none")

+           .attr("stroke", "black")

+           .attr("stroke-width", "none")

+        if xNA.handle and yNA.handle

+          g.append("rect")

+           .attr("x", margin.left)

+           .attr("y", margin.top+height - yNA.width)

+           .attr("height", yNA.width)

+           .attr("width", xNA.width)

+           .attr("fill", "none")

+           .attr("stroke", "black")

+           .attr("stroke-width", "none")

+        if yNA.handle

+          g.append("rect")

+           .attr("x", margin.left+paneloffset)

+           .attr("y", margin.top+height-yNA.width)

+           .attr("height", yNA.width)

+           .attr("width", panelwidth)

+           .attr("fill", "none")

+           .attr("stroke", "black")

+           .attr("stroke-width", "none")

+  

+    ## configuration parameters

+    chart.width = (value) ->

+      return width if !arguments.length

+      width = value

+      chart

+  

+    chart.height = (value) ->

+      return height if !arguments.length

+      height = value

+      chart

+  

+    chart.margin = (value) ->

+      return margin if !arguments.length

+      margin = value

+      chart

+  

+    chart.axispos = (value) ->

+      return axispos if !arguments.length

+      axispos = value

+      chart

+  

+    chart.titlepos = (value) ->

+      return titlepos if !arguments.length

+      titlepos

+      chart

+  

+    chart.xlim = (value) ->

+      return xlim if !arguments.length

+      xlim = value

+      chart

+  

+    chart.nxticks = (value) ->

+      return nxticks if !arguments.length

+      nxticks = value

+      chart

+  

+    chart.xticks = (value) ->

+      return xticks if !arguments.length

+      xticks = value

+      chart

+  

+    chart.ylim = (value) ->

+      return ylim if !arguments.length

+      ylim = value

+      chart

+  

+    chart.nyticks = (value) ->

+      return nyticks if !arguments.length

+      nyticks = value

+      chart

+  

+    chart.yticks = (value) ->

+      return yticks if !arguments.length

+      yticks = value

+      chart

+  

+    chart.rectcolor = (value) ->

+      return rectcolor if !arguments.length

+      rectcolor = value

+      chart

+  

+    chart.pointcolor = (value) ->

+      return pointcolor if !arguments.length

+      pointcolor = value

+      chart

+  

+    chart.pointsize = (value) ->

+      return pointsize if !arguments.length

+      pointsize = value

+      chart

+  

+    chart.pointstroke = (value) ->

+      return pointstroke if !arguments.length

+      pointstroke = value

+      chart

+  

+    chart.dataByInd = (value) ->

+      return dataByInd if !arguments.length

+      dataByInd = value

+      chart

+  

+    chart.title = (value) ->

+      return title if !arguments.length

+      title = value

+      chart

+  

+    chart.xlab = (value) ->

+      return xlab if !arguments.length

+      xlab = value

+      chart

+  

+    chart.ylab = (value) ->

+      return ylab if !arguments.length

+      ylab = value

+      chart

+  

+    chart.rotate_ylab = (value) ->

+      return rotate_ylab if !arguments.length

+      rotate_ylab = value

+      chart

+  

+    chart.xvar = (value) ->

+      return xvar if !arguments.length

+      xvar = value

+      chart

+  

+    chart.yvar = (value) ->

+      return yvar if !arguments.length

+      yvar = value

+      chart

+  

+    chart.xNA = (value) ->

+      return xNA if !arguments.length

+      xNA = value

+      chart

+  

+    chart.yNA = (value) ->

+      return yNA if !arguments.length

+      yNA = value

+      chart

+  

+    chart.yscale = () ->

+      return yscale

+  

+    chart.xscale = () ->

+      return xscale

+  

+    chart.pointsSelect = () ->

+      return pointsSelect

+  

+    # return the chart function

+    chart

+

+probability_plot()
\ 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 1a7f6a0b..2cdad5ee 100755
--- a/wqflask/wqflask/static/new/javascript/show_trait.coffee
+++ b/wqflask/wqflask/static/new/javascript/show_trait.coffee
@@ -1,7 +1,7 @@
-root = exports ? this
-
 console.log("start_b")
 
+#root = exports ? this
+
 # this is our isNumber, do not confuse with the underscore.js one
 is_number = (o) ->
     return ! isNaN (o-0) && o != null
diff --git a/wqflask/wqflask/static/new/javascript/show_trait.js b/wqflask/wqflask/static/new/javascript/show_trait.js
index 5f452f32..71c23272 100755
--- a/wqflask/wqflask/static/new/javascript/show_trait.js
+++ b/wqflask/wqflask/static/new/javascript/show_trait.js
@@ -1,10 +1,8 @@
 // Generated by CoffeeScript 1.7.1
-var Stat_Table_Rows, is_number, root,
+var Stat_Table_Rows, is_number,
   __hasProp = {}.hasOwnProperty,
   __slice = [].slice;
 
-root = typeof exports !== "undefined" && exports !== null ? exports : this;
-
 console.log("start_b");
 
 is_number = function(o) {
diff --git a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee
index b37cfe09..27bf80d5 100755
--- a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee
+++ b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee
@@ -1,7 +1,8 @@
 # http://stackoverflow.com/a/4215132/1175849
-root = exports ? this
+#root = exports ? this
 
 $ ->
+    
     submit_special = ->
         # Add submit_special class plus a data-url field to any button
         # And it will submit to that url
@@ -52,15 +53,12 @@ $ ->
         )
         return false
 
-    $("#interval_mapping_compute").click(() =>
-        console.log("In interval mapping")
-        $("#progress_bar_container").modal()
-        url = "/interval_mapping"
-        $('input[name=method]').val("reaper")
-        $('input[name=mapping_display_all]').val($('input[name=display_all_reaper]'))
-        $('input[name=suggestive]').val($('input[name=suggestive_reaper]'))
-        form_data = $('#trait_data_form').serialize()
-        console.log("form_data is:", form_data)
+    ##Block Outliers Code
+    block_outliers = ->
+        $('.outlier').each (_index, element) =>
+            $(element).find('.trait_value_input').val('x')
+            
+    do_ajax_post = (url, form_data) ->
         $.ajax(
             type: "POST"
             url: url
@@ -77,9 +75,57 @@ $ ->
                 $("body").html(data)
         )
         console.log("settingInterval")
-
+        
         this.my_timer = setInterval(get_progress, 1000)
         return false
+
+    showalert = (message,alerttype) ->
+      $('#alert_placeholder').append('<div id="alertdiv" class="alert ' +  alerttype + '"><a class="close" data-dismiss="alert">×</a><span>'+message+'</span></div>')
+    
+
+    $("#interval_mapping_compute").click(() =>
+        showalert("One or more outliers exist in this data set. Please review values before mapping. \
+                  Including outliers when mapping may lead to misleading results. \
+                  We recommend <A HREF=\"http://en.wikipedia.org/wiki/Winsorising\">winsorising</A> the outliers \
+                  or simply deleting them.", "alert-success")
+        console.log("In interval mapping")
+        $("#progress_bar_container").modal()
+        url = "/interval_mapping"
+        
+        $('input[name=method]').val("reaper")
+        
+        $('input[name=mapping_display_all]').val($('input[name=display_all_reaper]'))
+        $('input[name=suggestive]').val($('input[name=suggestive_reaper]'))
+        form_data = $('#trait_data_form').serialize()
+        console.log("form_data is:", form_data)
+        
+        do_ajax_post(url, form_data)
+        
+        #remove_outliers = confirm("Remove outliers?")
+        #if use_outliers == true
+        #    block_outliers()
+        #    do_ajax_post(url, form_data)
+        #else
+        #    do_ajax_post(url, form_data)
+        #$.ajax(
+        #    type: "POST"
+        #    url: url
+        #    data: form_data
+        #    error: (xhr, ajaxOptions, thrownError) =>
+        #        alert("Sorry, an error occurred")
+        #        console.log(xhr)
+        #        clearInterval(this.my_timer)
+        #        $('#progress_bar_container').modal('hide')
+        #        $("body").html("We got an error.")        
+        #    success: (data) =>
+        #        clearInterval(this.my_timer)
+        #        $('#progress_bar_container').modal('hide')
+        #        $("body").html(data)
+        #)
+        #console.log("settingInterval")
+        #
+        #this.my_timer = setInterval(get_progress, 1000)
+        #return false
     )
 
     $('#suggestive').hide()
@@ -98,25 +144,31 @@ $ ->
         $('input[name=method]').val("pylmm")
         form_data = $('#trait_data_form').serialize()
         console.log("form_data is:", form_data)
-        $.ajax(
-            type: "POST"
-            url: url
-            data: form_data
-            error: (xhr, ajaxOptions, thrownError) =>
-                alert("Sorry, an error occurred")
-                console.log(xhr)
-                clearInterval(this.my_timer)
-                $('#progress_bar_container').modal('hide')
-                $("body").html("We got an error.")        
-            success: (data) =>
-                clearInterval(this.my_timer)
-                $('#progress_bar_container').modal('hide')
-                $("body").html(data)
-        )
-        console.log("settingInterval")
-
-        this.my_timer = setInterval(get_progress, 1000)
-        return false
+        
+        #remove_outliers = confirm("Remove outliers?")
+        #if use_outliers == true
+        #    block_outliers()
+        do_ajax_post(url, form_data)
+        
+        #$.ajax(
+        #    type: "POST"
+        #    url: url
+        #    data: form_data
+        #    error: (xhr, ajaxOptions, thrownError) =>
+        #        alert("Sorry, an error occurred")
+        #        console.log(xhr)
+        #        clearInterval(this.my_timer)
+        #        $('#progress_bar_container').modal('hide')
+        #        $("body").html("We got an error.")        
+        #    success: (data) =>
+        #        clearInterval(this.my_timer)
+        #        $('#progress_bar_container').modal('hide')
+        #        $("body").html(data)
+        #)
+        #console.log("settingInterval")
+        #
+        #this.my_timer = setInterval(get_progress, 1000)
+        #return false
     )
 
     $("#plink_compute").click(() =>
@@ -128,25 +180,28 @@ $ ->
         $('input[name=maf]').val($('input[name=maf_plink]').val())
         form_data = $('#trait_data_form').serialize()
         console.log("form_data is:", form_data)
-        $.ajax(
-            type: "POST"
-            url: url
-            data: form_data
-            error: (xhr, ajaxOptions, thrownError) =>
-                alert("Sorry, an error occurred")
-                console.log(xhr)
-                clearInterval(this.my_timer)
-                $('#static_progress_bar_container').modal('hide')
-                $("body").html("We got an error.")        
-            success: (data) =>
-                clearInterval(this.my_timer)
-                $('#static_progress_bar_container').modal('hide')
-                $("body").html(data)
-        )
-        console.log("settingInterval")
-
-        this.my_timer = setInterval(get_progress, 1000)
-        return false
+        
+        do_ajax_post(url, form_data)
+        
+        #$.ajax(
+        #    type: "POST"
+        #    url: url
+        #    data: form_data
+        #    error: (xhr, ajaxOptions, thrownError) =>
+        #        alert("Sorry, an error occurred")
+        #        console.log(xhr)
+        #        clearInterval(this.my_timer)
+        #        $('#static_progress_bar_container').modal('hide')
+        #        $("body").html("We got an error.")        
+        #    success: (data) =>
+        #        clearInterval(this.my_timer)
+        #        $('#static_progress_bar_container').modal('hide')
+        #        $("body").html(data)
+        #)
+        #console.log("settingInterval")
+        #
+        #this.my_timer = setInterval(get_progress, 1000)
+        #return false
     )
 
     $("#gemma_compute").click(() =>
@@ -158,25 +213,28 @@ $ ->
         $('input[name=maf]').val($('input[name=maf_gemma]').val())
         form_data = $('#trait_data_form').serialize()
         console.log("form_data is:", form_data)
-        $.ajax(
-            type: "POST"
-            url: url
-            data: form_data
-            error: (xhr, ajaxOptions, thrownError) =>
-                alert("Sorry, an error occurred")
-                console.log(xhr)
-                clearInterval(this.my_timer)
-                $('#static_progress_bar_container').modal('hide')
-                $("body").html("We got an error.")        
-            success: (data) =>
-                clearInterval(this.my_timer)
-                $('#static_progress_bar_container').modal('hide')
-                $("body").html(data)
-        )
-        console.log("settingInterval")
-
-        this.my_timer = setInterval(get_progress, 1000)
-        return false
+        
+        do_ajax_post(url, form_data)
+        
+        #$.ajax(
+        #    type: "POST"
+        #    url: url
+        #    data: form_data
+        #    error: (xhr, ajaxOptions, thrownError) =>
+        #        alert("Sorry, an error occurred")
+        #        console.log(xhr)
+        #        clearInterval(this.my_timer)
+        #        $('#static_progress_bar_container').modal('hide')
+        #        $("body").html("We got an error.")        
+        #    success: (data) =>
+        #        clearInterval(this.my_timer)
+        #        $('#static_progress_bar_container').modal('hide')
+        #        $("body").html(data)
+        #)
+        #console.log("settingInterval")
+        #
+        #this.my_timer = setInterval(get_progress, 1000)
+        #return false
     )
 
     #$(".submit_special").click(submit_special)
diff --git a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js
index 1a2ad637..d02bca4b 100755
--- a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js
+++ b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js
@@ -1,10 +1,6 @@
 // Generated by CoffeeScript 1.7.1
-var root;
-
-root = typeof exports !== "undefined" && exports !== null ? exports : this;
-
 $(function() {
-  var composite_mapping_fields, get_progress, mapping_method_fields, submit_special, toggle_enable_disable, update_time_remaining;
+  var block_outliers, composite_mapping_fields, do_ajax_post, get_progress, mapping_method_fields, showalert, submit_special, toggle_enable_disable, update_time_remaining;
   submit_special = function() {
     var url;
     console.log("In submit_special");
@@ -61,9 +57,46 @@ $(function() {
     });
     return false;
   };
+  block_outliers = function() {
+    return $('.outlier').each((function(_this) {
+      return function(_index, element) {
+        return $(element).find('.trait_value_input').val('x');
+      };
+    })(this));
+  };
+  do_ajax_post = function(url, form_data) {
+    $.ajax({
+      type: "POST",
+      url: url,
+      data: form_data,
+      error: (function(_this) {
+        return function(xhr, ajaxOptions, thrownError) {
+          alert("Sorry, an error occurred");
+          console.log(xhr);
+          clearInterval(_this.my_timer);
+          $('#progress_bar_container').modal('hide');
+          return $("body").html("We got an error.");
+        };
+      })(this),
+      success: (function(_this) {
+        return function(data) {
+          clearInterval(_this.my_timer);
+          $('#progress_bar_container').modal('hide');
+          return $("body").html(data);
+        };
+      })(this)
+    });
+    console.log("settingInterval");
+    this.my_timer = setInterval(get_progress, 1000);
+    return false;
+  };
+  showalert = function(message, alerttype) {
+    return $('#alert_placeholder').append('<div id="alertdiv" class="alert ' + alerttype + '"><a class="close" data-dismiss="alert">�</a><span>' + message + '</span></div>');
+  };
   $("#interval_mapping_compute").click((function(_this) {
     return function() {
       var form_data, url;
+      showalert("One or more outliers exist in this data set. Please review values before mapping. Including outliers when mapping may lead to misleading results. We recommend <A HREF=\"http://en.wikipedia.org/wiki/Winsorising\">winsorising</A> the outliers or simply deleting them.", "alert-success");
       console.log("In interval mapping");
       $("#progress_bar_container").modal();
       url = "/interval_mapping";
@@ -72,26 +105,7 @@ $(function() {
       $('input[name=suggestive]').val($('input[name=suggestive_reaper]'));
       form_data = $('#trait_data_form').serialize();
       console.log("form_data is:", form_data);
-      $.ajax({
-        type: "POST",
-        url: url,
-        data: form_data,
-        error: function(xhr, ajaxOptions, thrownError) {
-          alert("Sorry, an error occurred");
-          console.log(xhr);
-          clearInterval(_this.my_timer);
-          $('#progress_bar_container').modal('hide');
-          return $("body").html("We got an error.");
-        },
-        success: function(data) {
-          clearInterval(_this.my_timer);
-          $('#progress_bar_container').modal('hide');
-          return $("body").html(data);
-        }
-      });
-      console.log("settingInterval");
-      _this.my_timer = setInterval(get_progress, 1000);
-      return false;
+      return do_ajax_post(url, form_data);
     };
   })(this));
   $('#suggestive').hide();
@@ -113,26 +127,7 @@ $(function() {
       $('input[name=method]').val("pylmm");
       form_data = $('#trait_data_form').serialize();
       console.log("form_data is:", form_data);
-      $.ajax({
-        type: "POST",
-        url: url,
-        data: form_data,
-        error: function(xhr, ajaxOptions, thrownError) {
-          alert("Sorry, an error occurred");
-          console.log(xhr);
-          clearInterval(_this.my_timer);
-          $('#progress_bar_container').modal('hide');
-          return $("body").html("We got an error.");
-        },
-        success: function(data) {
-          clearInterval(_this.my_timer);
-          $('#progress_bar_container').modal('hide');
-          return $("body").html(data);
-        }
-      });
-      console.log("settingInterval");
-      _this.my_timer = setInterval(get_progress, 1000);
-      return false;
+      return do_ajax_post(url, form_data);
     };
   })(this));
   $("#plink_compute").click((function(_this) {
@@ -146,26 +141,7 @@ $(function() {
       $('input[name=maf]').val($('input[name=maf_plink]').val());
       form_data = $('#trait_data_form').serialize();
       console.log("form_data is:", form_data);
-      $.ajax({
-        type: "POST",
-        url: url,
-        data: form_data,
-        error: function(xhr, ajaxOptions, thrownError) {
-          alert("Sorry, an error occurred");
-          console.log(xhr);
-          clearInterval(_this.my_timer);
-          $('#static_progress_bar_container').modal('hide');
-          return $("body").html("We got an error.");
-        },
-        success: function(data) {
-          clearInterval(_this.my_timer);
-          $('#static_progress_bar_container').modal('hide');
-          return $("body").html(data);
-        }
-      });
-      console.log("settingInterval");
-      _this.my_timer = setInterval(get_progress, 1000);
-      return false;
+      return do_ajax_post(url, form_data);
     };
   })(this));
   $("#gemma_compute").click((function(_this) {
@@ -179,26 +155,7 @@ $(function() {
       $('input[name=maf]').val($('input[name=maf_gemma]').val());
       form_data = $('#trait_data_form').serialize();
       console.log("form_data is:", form_data);
-      $.ajax({
-        type: "POST",
-        url: url,
-        data: form_data,
-        error: function(xhr, ajaxOptions, thrownError) {
-          alert("Sorry, an error occurred");
-          console.log(xhr);
-          clearInterval(_this.my_timer);
-          $('#static_progress_bar_container').modal('hide');
-          return $("body").html("We got an error.");
-        },
-        success: function(data) {
-          clearInterval(_this.my_timer);
-          $('#static_progress_bar_container').modal('hide');
-          return $("body").html(data);
-        }
-      });
-      console.log("settingInterval");
-      _this.my_timer = setInterval(get_progress, 1000);
-      return false;
+      return do_ajax_post(url, form_data);
     };
   })(this));
   composite_mapping_fields = function() {
diff --git a/wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables.css b/wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables.css
index 7da7faec..68d5e4fa 100755
--- a/wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables.css
+++ b/wqflask/wqflask/static/new/packages/DataTables/css/jquery.dataTables.css
@@ -41,6 +41,8 @@ table.dataTable tr.even td.sorting_1 { background-color: #EAEBFF; }
 table.dataTable tr.even td.sorting_2 { background-color: #F2F3FF; }
 table.dataTable tr.even td.sorting_3 { background-color: #F9F9FF; }
 
+table.dataTable tr.outlier td{ background-color: #FFFF00; }
+
 
 /*
  * Table wrapper
diff --git a/wqflask/wqflask/templates/corr_scatter_plot_old.html b/wqflask/wqflask/templates/corr_scatter_plot_old.html
deleted file mode 100755
index 79c63ada..00000000
--- a/wqflask/wqflask/templates/corr_scatter_plot_old.html
+++ /dev/null
@@ -1,63 +0,0 @@
-{% extends "base.html" %}
-
-{% block css %}
-    <link rel="stylesheet" type="text/css" href="/static/packages/jqplot/jquery.jqplot.min.css" />
-    <link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/css/jquery.dataTables.css" />
-    <link rel="stylesheet" type="text/css" href="/static/packages/DT_bootstrap/DT_bootstrap.css" />
-    <link rel="stylesheet" type="text/css" href="/static/packages/TableTools/media/css/TableTools.css" />
-    <link rel="stylesheet" type="text/css" href="/static/new/css/panelutil.css" />
-    <link rel="stylesheet" type="text/css" href="/static/new/css/d3-tip.min.css" />
-    <link rel="stylesheet" type="text/css" href="/static/new/css/corr_scatter_plot.css" />
-{% endblock %}
-
-{% block content %}
-<form action="" method="get">
-<input type="hidden" name="dataset_1" value="{{data_set_1.name}}">
-<input type="hidden" name="dataset_2" value="{{data_set_2.name}}">
-<input type="hidden" name="trait_1" value="{{trait_1.name}}">
-<input type="hidden" name="trait_2" value="{{trait_2.name}}">
-<table class="table" style="width: auto;">
-    <tr>
-        <td>Canvas Width</td>
-        <td>Canvas Height</td>
-        <td>Circle Color</td>
-        <td>Circle Radius</td>
-        <td>Line Color</td>
-        <td>Line Width</td>
-        <td rowspan="2" style="vertical-align:middle;"><button type="submit" class="btn btn-primary"><i class="icon-refresh"></i>Redraw</button></td>
-    </tr>
-    <tr>
-        <td><input type="text" name="width" value="{{width}}" style="width: 100px;"></td>
-        <td><input type="text" name="height" value="{{height}}" style="width: 100px;"></td>
-        <td>
-            <select name="circle_color" style="width: 100px;">
-                <option value="red">Red</option>
-                <option value="green">Green</option>
-                <option value="blue">Blue</option>
-            </select>
-        </td>
-        <td><input type="text" name="circle_radius" value="{{circle_radius}}" style="width: 100px;"></td>
-        <td>
-            <select name="line_color" style="width: 100px;">
-                <option value="red">Red</option>
-                <option value="green">Green</option>
-                <option value="blue">Blue</option>
-            </select>
-        </td>
-        <td><input type="text" name="line_width" value="{{line_width}}" style="width: 100px;"></td>
-    </tr>
-</table>
-</form>
-<div id='scatter_plot'></div>
-{% endblock %}
-
-{% block js %}
-    <script>
-       js_data = {{ js_data | safe }}
-    </script>
-    <script language="javascript" type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
-    <script language="javascript" type="text/javascript" src="/static/packages/underscore/underscore-min.js"></script>
-    <script language="javascript" type="text/javascript" src="/static/new/js_external/d3-tip.min.js"></script>
-    <script language="javascript" type="text/javascript" src="/static/new/javascript/panelutil.js"></script>
-    <script language="javascript" type="text/javascript" src="/static/new/javascript/corr_scatter_plot.js"></script>
-{% endblock %}
\ No newline at end of file
diff --git a/wqflask/wqflask/templates/interval_mapping.html b/wqflask/wqflask/templates/interval_mapping.html
index 25ee22ac..4fe5d0f8 100755
--- a/wqflask/wqflask/templates/interval_mapping.html
+++ b/wqflask/wqflask/templates/interval_mapping.html
@@ -19,11 +19,16 @@
             <h2>

                 Whole Genome Mapping

             </h2>

-            <form id="exportform" action="export" method="post">

+            <form style ='float: left; padding: 5px;' id="exportform" action="export" method="post">

               <input type="hidden" id="data" name="data" value="">

               <input type="hidden" id="filename" name="filename" value="">

               <input type="submit" id="export" value="Download SVG">

             </form>

+            <form style ='float: left; padding: 5px;' id="exportpdfform" action="export_pdf" method="post">

+              <input type="hidden" id="data" name="data" value="">

+              <input type="hidden" id="filename" name="filename" value="">

+              <input type="submit" id="export_pdf" value="Download PDF">

+            </form>

         </div>

         <div id="chart_container">

             <div class="qtlcharts" id="topchart">

diff --git a/wqflask/wqflask/templates/marker_regression.html b/wqflask/wqflask/templates/marker_regression.html
index 3dce5266..451b3754 100755
--- a/wqflask/wqflask/templates/marker_regression.html
+++ b/wqflask/wqflask/templates/marker_regression.html
@@ -18,11 +18,16 @@
             <h2>

                 Whole Genome Mapping

             </h2>

-            <form id="exportform" action="export" method="post">

+            <form style ='float: left; padding: 5px;' id="exportform" action="export" method="post">

               <input type="hidden" id="data" name="data" value="">

               <input type="hidden" id="filename" name="filename" value="">

               <input type="submit" id="export" value="Download SVG">

             </form>

+            <form style ='float: left; padding: 5px;' id="exportpdfform" action="export_pdf" method="post">

+              <input type="hidden" id="data" name="data" value="">

+              <input type="hidden" id="filename" name="filename" value="">

+              <input type="submit" id="export_pdf" value="Download PDF">

+            </form>

 <!--            <button id="export_pdf" class="btn">Export PDF</button>-->

         </div>

         <div id="chart_container">

diff --git a/wqflask/wqflask/templates/marker_regression_old.html b/wqflask/wqflask/templates/marker_regression_old.html
new file mode 100644
index 00000000..defcd929
--- /dev/null
+++ b/wqflask/wqflask/templates/marker_regression_old.html
@@ -0,0 +1,106 @@
+{% extends "base.html" %}
+{% block title %}Marker Regression{% endblock %}
+{% block css %}
+    <link rel="stylesheet" type="text/css" href="/static/packages/jqplot/jquery.jqplot.min.css" />
+    <link rel="stylesheet" type="text/css" href="/static/new/css/marker_regression.css" />
+    <link rel="stylesheet" type="text/css" href="/static/new/packages/DataTables/css/jquery.dataTables.css" />
+    <link rel="stylesheet" type="text/css" href="/static/packages/DT_bootstrap/DT_bootstrap.css" />
+    <link rel="stylesheet" type="text/css" href="/static/packages/TableTools/media/css/TableTools.css" />
+{% endblock %}
+{% block content %} <!-- Start of body -->
+
+    {{ header("Marker Regression",
+        '{}: {}'.format(this_trait.name, this_trait.description_fmt)) }}
+
+    <div class="container">
+        <div>
+            <h2>
+                Manhattan Plot
+            </h2>
+        </div>
+        <div id="manhattan_plot_container" class="manhattan_plot_container">
+            <div id="manhattan_plot" class="manhattan_plots">
+                
+            </div>
+        </div>
+        <div>
+            <h2>
+                Genome Association Results
+            </h2>
+        </div>
+
+        <table cellpadding="0" cellspacing="0" border="0" id="qtl_results" class="table table-hover table-striped table-bordered">
+            <thead>
+                <tr>
+                    <td>Index</td>
+                    <td>LOD Score</td>
+                    <td>Chr</td>
+                    <td>Mb</td>
+                    <td>Locus</td>
+                </tr>
+            </thead>
+            <tbody>
+                {% for marker in filtered_markers %}
+                    {% if marker.lod_score > lod_cutoff %}
+                    <tr>
+                        <td>{{loop.index}}</td>
+                        <td>{{marker.lod_score}}</td>
+                        <td>{{marker.chr}}</td>
+                        <td>{{marker.Mb}}</td>
+                        <td>{{marker.name}}</td>
+                    </tr>
+                    {% endif %}
+                {% endfor %}
+            </tbody>
+        </table>
+    </div>
+
+    <!-- End of body -->
+
+{% endblock %}
+
+{% block js %}  
+    <script>
+        js_data = {{ js_data | safe }}
+    </script>
+
+    <!--[if lt IE 9]>
+<!--        <script language="javascript" type="text/javascript" src="/static/packages/jqplot/excanvas.js"></script>-->
+    <![endif]-->
+    <script language="javascript" type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
+    <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.js"></script>
+    <script language="javascript" type="text/javascript" src="/static/new/packages/DataTables/js/jquery.dataTables.min.js"></script>
+    <script language="javascript" type="text/javascript" src="/static/packages/DT_bootstrap/DT_bootstrap.js"></script>
+    <script language="javascript" type="text/javascript" src="/static/packages/TableTools/media/js/TableTools.min.js"></script>
+    <script language="javascript" type="text/javascript" src="/static/packages/underscore/underscore-min.js"></script>
+    <script language="javascript" type="text/javascript" src="/static/new/javascript/chr_manhattan_plot.js"></script>
+    <script language="javascript" type="text/javascript" src="/static/new/javascript/marker_regression.js"></script>
+
+    
+    <script type="text/javascript" charset="utf-8">
+        $(document).ready( function () {
+            console.time("Creating table");
+            $('#qtl_results').dataTable( {
+                //"sDom": "<<'span3'l><'span3'T><'span4'f>'row-fluid'r>t<'row-fluid'<'span6'i><'span6'p>>",
+                "sDom": "lTftipr",
+                "oTableTools": {
+                    "aButtons": [
+                        "copy",
+                        "print",
+                        {
+                            "sExtends":    "collection",
+                            "sButtonText": 'Save <span class="caret" />',
+                            "aButtons":    [ "csv", "xls", "pdf" ]
+                        }
+                    ],
+                    "sSwfPath": "/static/packages/TableTools/media/swf/copy_csv_xls_pdf.swf"
+                },
+                "iDisplayLength": 50,
+                "bLengthChange": true,
+                "bDeferRender": true,
+                "bSortClasses": false
+            } );
+            console.timeEnd("Creating table");
+        });
+    </script>
+{% endblock %}
\ No newline at end of file
diff --git a/wqflask/wqflask/templates/show_trait.html b/wqflask/wqflask/templates/show_trait.html
index f20d66ed..d2b748ca 100755
--- 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/show_trait.css" />
     <link rel="stylesheet" type="text/css" href="/static/new/css/bar_chart.css" />
     <link rel="stylesheet" type="text/css" href="/static/new/css/box_plot.css" />
     <link rel="stylesheet" type="text/css" href="/static/new/css/panelutil.css" />
@@ -107,7 +108,7 @@
                 console.time("Creating table");
                 
                 {% if sample_groups[0].se_exists() %}
-                    $('#samples_primary, #samples_other').dataTable( {
+                    $('#samples_primary, #samples_other').find("tr.outlier").css('background-color', 'yellow').dataTable( {
                         //"sDom": "<<'span3'l><'span3'T><'span4'f>'row-fluid'r>t<'row-fluid'<'span6'i><'span6'p>>",
                         "aoColumns": [
                             { "sType": "natural" },
diff --git a/wqflask/wqflask/templates/show_trait_mapping_tools.html b/wqflask/wqflask/templates/show_trait_mapping_tools.html
index f8542c78..705eda88 100755
--- a/wqflask/wqflask/templates/show_trait_mapping_tools.html
+++ b/wqflask/wqflask/templates/show_trait_mapping_tools.html
@@ -127,6 +127,7 @@
                             </button>
                         </div>
                     </div>
+                    <div id="alert_placeholder"></div>
                 </div>
                 
                 <div class="tab-pane" id="pylmm">
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index 6315260d..47a18149 100755
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -269,6 +269,18 @@ def export():
     response.headers["Content-Disposition"] = "attchment; filename=%s"%filename
     return response
 
+@app.route("/export_pdf", methods = ('POST',))
+def export_pdf():
+    import cairosvg
+    print("request.form:", request.form)
+    svg_xml = request.form.get("data", "Invalid data")
+    print("svg_xml:", svg_xml)
+    filename = request.form.get("filename", "interval_map_pdf")
+    filepath = "/home/zas1024/gene/wqflask/output/"+filename
+    pdf_file = cairosvg.svg2pdf(bytestring=svg_xml)
+    response = Response(pdf_file, mimetype="application/pdf")
+    response.headers["Content-Disposition"] = "attchment; filename=%s"%filename
+    return response
 
 @app.route("/interval_mapping", methods=('POST',))
 def interval_mapping_page():