about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBonfaceKilz2020-11-11 14:40:18 +0300
committerBonfaceKilz2020-11-11 14:40:18 +0300
commitdbeefadc25fb2bc6e04b4baa4b35bbbd5298e880 (patch)
tree9ae956af7a43465851e4f786d416755e890337d8
parent394a67ca2f28b18aa3ea8398ca48661985be8f5a (diff)
parent25f7d30b9f052ec5d812bfe3bf9713df850cc267 (diff)
downloadgenenetwork2-dbeefadc25fb2bc6e04b4baa4b35bbbd5298e880.tar.gz
Merge branch 'testing' of github.com:genenetwork/genenetwork2 into feature/add-glossary-page
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md16
-rw-r--r--.github/ISSUE_TEMPLATE/feature_request.md23
-rw-r--r--.github/ISSUE_TEMPLATE/user_story.md8
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md9
-rw-r--r--wqflask/base/GeneralObject.py2
-rw-r--r--wqflask/tests/wqflask/show_trait/test_show_trait.py242
-rw-r--r--wqflask/wqflask/marker_regression/display_mapping_results.py2
-rw-r--r--wqflask/wqflask/show_trait/SampleList.py19
-rw-r--r--wqflask/wqflask/show_trait/show_trait.py6
-rw-r--r--wqflask/wqflask/static/new/css/show_trait.css2
-rw-r--r--wqflask/wqflask/static/new/css/trait_list.css12
-rw-r--r--wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js8
-rw-r--r--wqflask/wqflask/templates/collections/view.html33
-rw-r--r--wqflask/wqflask/templates/correlation_page.html4
-rw-r--r--wqflask/wqflask/templates/search_result_page.html72
15 files changed, 378 insertions, 80 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 7d7e34a5..48bad39b 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -9,26 +9,26 @@ assignees: ''
 
 **Describe the bug**
 
-A clear and concise description of what the bug is.
+<!-- A clear and concise description of what the bug is. -->
 
 **To Reproduce**
 
-Steps to reproduce the behavior
+<!-- Steps to reproduce the behavior -->
 
 **Expected behavior**
 
-A clear and concise description of what you expected to happen.
+<!-- A clear and concise description of what you expected to happen. -->
 
 **Screenshots**
 
-If applicable, add screenshots to help explain your problem.
+<!-- If applicable, add screenshots to help explain your problem. -->
 
 **Environment setup (please complete the following information):**
 
-- OS: [e.g. Linux]
-- Guix Version (optional)
-- [Anything else you think is relevant]
+<!-- - OS: [e.g. Linux] -->
+<!-- - Guix Version (optional) -->
+<!-- - [Anything else you think is relevant] -->
 
 **Additional context**
 
-Add any other context about the problem here.
+<!-- Add any other context about the problem here. -->
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index 254754c6..eb6c3e4b 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -9,26 +9,33 @@ assignees: ''
 
 ## Is your feature request related to a problem? Please describe.
 
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+<!-- A clear and concise description of what the problem is. -->
+
+<!-- Example: I'm always frustrated when [...] -->
 
 ## Describe the solution you'd like
 
-A clear and concise description of what you want to happen.
+<!-- A clear and concise description of what you want to happen. -->
 
 ## Describe alternatives you've considered
 
-A clear and concise description of any alternative solutions or features you've considered.
+<!-- A clear and concise description of any alternative solutions or features you've considered. -->
 
 ## User Stories (optional)
 
-As a _[role or persona]_, I want _[goal/ need]_ so that _[why]_
+<!-- Example: -->
+
+<!-- As a _[role or persona]_, I want _[goal/ need]_ so that _[why]_ -->
+
+<!-- **Feature:** _[Brief description of feature]_ -->
 
-**Feature:** _[Brief description of feature]_
+<!-- _[Any additional descriptions on feature]_ -->
 
-_[Any additional descriptions on feature]_
+<!-- **Scenario:**
 
-**Scenario:** Please use _[Gherkin](https://cucumber.io/docs/gherkin/reference/)_ here
+Please use _[Gherkin](https://cucumber.io/docs/gherkin/reference/)_
+here -->
 
 ## Additional context
 
-Add any other context or screenshots about the feature request here.
+<!-- Add any other context or screenshots about the feature request here. -->
diff --git a/.github/ISSUE_TEMPLATE/user_story.md b/.github/ISSUE_TEMPLATE/user_story.md
index 2682fc98..52ae775d 100644
--- a/.github/ISSUE_TEMPLATE/user_story.md
+++ b/.github/ISSUE_TEMPLATE/user_story.md
@@ -7,10 +7,10 @@ assignees: ''
 
 ---
 
-As a _[role or persona]_, I want _[goal/ need]_ so that _[why]_
+<!-- As a _[role or persona]_, I want _[goal/ need]_ so that _[why]_ -->
 
-**Feature:** _[Brief description of feature]_
+<!-- **Feature:** _[Brief description of feature]_ -->
 
-_[Any additional descriptions on feature]_
+<!-- _[Any additional descriptions on feature]_ -->
 
-**Scenario:** Please use _[Gherkin](https://cucumber.io/docs/gherkin/reference/)_ here
+<!-- **Scenario:** Please use _[Gherkin](https://cucumber.io/docs/gherkin/reference/)_ here -->
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 223e24ef..f3371183 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,11 +1,20 @@
 #### Description
+<!--Brief description of the PR. What does this PR do? -->
 
 #### How should this be tested?
+<!-- What should you do to test this PR? Is there any manual quality
+assurance checks that should be done. What are the expectations -->
 
 #### Any background context you want to provide?
 
+<!-- Anything the reviewer should be aware of ahead of testing -->
+
 #### What are the relevant pivotal tracker stories?
 
+<!-- Does this PR track anything anywhere? -->
+
 #### Screenshots (if appropriate)
 
 #### Questions
+
+<!-- Are there any questions for the reviewer -->
diff --git a/wqflask/base/GeneralObject.py b/wqflask/base/GeneralObject.py
index 0122ee32..249195e2 100644
--- a/wqflask/base/GeneralObject.py
+++ b/wqflask/base/GeneralObject.py
@@ -28,7 +28,7 @@ class GeneralObject:
     """
     Base class to define an Object.
     a = [Spam(1, 4), Spam(9, 3), Spam(4,6)]
-    a.sort(lambda x, y: cmp(x.eggs, y.eggs))
+    a.sort(key = lambda x: x.eggs)
     """
 
     def __init__(self, *args, **kw):
diff --git a/wqflask/tests/wqflask/show_trait/test_show_trait.py b/wqflask/tests/wqflask/show_trait/test_show_trait.py
new file mode 100644
index 00000000..24150738
--- /dev/null
+++ b/wqflask/tests/wqflask/show_trait/test_show_trait.py
@@ -0,0 +1,242 @@
+"""test for wqflask/show_trait/test_show_trait.py"""
+import unittest
+from unittest import mock
+from wqflask import app
+from wqflask.show_trait.show_trait import check_if_attr_exists
+from wqflask.show_trait.show_trait import get_ncbi_summary
+from wqflask.show_trait.show_trait import has_num_cases
+from wqflask.show_trait.show_trait import get_table_widths
+from wqflask.show_trait.show_trait import get_categorical_variables
+from wqflask.show_trait.show_trait import get_trait_units
+from wqflask.show_trait.show_trait import get_nearest_marker
+from wqflask.show_trait.show_trait import get_genotype_scales
+from wqflask.show_trait.show_trait import requests
+
+
+class TraitObject:
+    def __init__(self, obj):
+        for key, value in obj.items():
+            setattr(self, key, value)
+
+
+class TestTraits(unittest.TestCase):
+    def setUp(self):
+        self.app_context = app.app_context()
+        self.app_context.push()
+
+    def tearDown(self):
+        self.app_context.pop()
+
+    def test_check_if_attr_exists_truthy(self):
+        """"test if attributes exists with true return"""
+        trait_obj = TraitObject({"id_type": "id"})
+        trait_obj2 = TraitObject({"sample_name": ['samp1']})
+        results = check_if_attr_exists(trait_obj, "id_type")
+        result2 = check_if_attr_exists(trait_obj2, "sample_name")
+        self.assertIsInstance(trait_obj, TraitObject)
+        self.assertTrue(results)
+        self.assertTrue(result2)
+
+    def test_check_if_attr_exists_empty_attr(self):
+        """test if attributes exists with false return"""
+        trait_obj = TraitObject({"sample": ""})
+        trait_obj2 = TraitObject({"group": None})
+        result = check_if_attr_exists(trait_obj, "sample")
+        result2 = check_if_attr_exists(trait_obj, "group")
+        self.assertFalse(result)
+        self.assertFalse(result2)
+
+    def test_check_if_attr_exists_falsey(self):
+        """check if attribute exists with empty attributes"""
+        trait_obj = TraitObject({})
+        results = check_if_attr_exists(trait_obj, "any")
+        self.assertFalse(results)
+
+    @mock.patch("wqflask.show_trait.show_trait.requests.get")
+    @mock.patch("wqflask.show_trait.show_trait.check_if_attr_exists")
+    def test_get_ncbi_summary_request_success(self, mock_exists, mock_get):
+        """test for getting ncbi summary with 
+        successful request"""
+        trait = TraitObject({"geneid": "id"})
+        mock_exists.return_value = True
+        content_json_string = """{
+          "result":{
+            "id":{
+              "summary":"this is a summary of the geneid"
+            }
+          }
+        }
+        """
+        get_return_obj = TraitObject({"content": content_json_string})
+        mock_get.return_value = get_return_obj
+        results = get_ncbi_summary(trait)
+        mock_exists.assert_called_once()
+        mock_get.assert_called_once_with(f"http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=gene&id={trait.geneid}&retmode=json")
+
+        self.assertEqual(results, "this is a summary of the geneid")
+
+    @mock.patch("wqflask.show_trait.show_trait.requests.get")
+    @mock.patch("wqflask.show_trait.show_trait.check_if_attr_exists")
+    def test_get_ncbi_summary_request_fail(self, mock_exists, mock_get_fail):
+        """test for getting ncbi summary with request fail"""
+        trait = TraitObject({"geneid": "id"})
+        mock_exists.return_value = True
+        mock_get_fail.side_effect = Exception("an error occurred")
+        content_json_string = """{
+          "result":{
+            "id":{
+              "summary":"this is a summary of the geneid"
+            }
+          }
+        }
+        """
+        results = get_ncbi_summary(trait)
+        self.assertEqual(results, None)
+
+    def test_hash_num_cases_is_probeset(self):
+        """test for hash num_cases with dataset.type set to Probeset"""
+        create_dataset = TraitObject({"type": "ProbeSet"})
+        create_trait = TraitObject({"dataset": create_dataset})
+        self.assertFalse(has_num_cases(create_trait))
+
+    def test_hash_num_cases_no_probeset(self):
+        """test for hash num cases with dataset.type not Probeset"""
+        create_dataset = TraitObject({"type": "Temp"})
+        construct_data = {
+            "nm1": TraitObject({"num_cases": False}),
+            "nm2": TraitObject({"num_cases": True}),
+            "nm3": TraitObject({"num_cases": False})
+        }
+        construct_data2 = {
+            "nm1": TraitObject({"num_cases": False}),
+            "nm2": TraitObject({"num_cases": False}),
+            "nm3": TraitObject({"num_cases": False})
+        }
+        create_trait = TraitObject(
+            {"dataset": create_dataset, "data": construct_data})
+        create_trait2 = TraitObject(
+            {"dataset": create_dataset, "data": construct_data2})
+
+        results = has_num_cases(create_trait)
+        self.assertTrue(has_num_cases(create_trait))
+        self.assertFalse(has_num_cases(create_trait2))
+
+    def test_get_table_widths(self):
+        """test for getting table widths"""
+        sample_groups = [TraitObject({'se_exists': True, "attributes": ["attr1", "attr2", "attr3"]}
+                                     ), TraitObject(
+            {"se_exists": False, "attributes": ["at1", "at2"]
+             })]
+
+        results_with_numcase = get_table_widths(sample_groups, True)
+        result_no_numcase = get_table_widths(sample_groups, False)
+
+        results_one_sample = get_table_widths(
+            [TraitObject({"se_exists": True, "attributes": []})], True)
+        expected_with_numcase = (450, "750px")
+        expected_no_numcase = (450, "670px")
+        expected_one_sample = (250, "540px")
+        self.assertEqual(results_with_numcase, expected_with_numcase)
+        self.assertEqual(result_no_numcase, expected_no_numcase)
+        self.assertEqual(results_one_sample,
+                         expected_one_sample)
+
+    def test_get_categorical_variables_no_sample_attributes(self):
+        """test for getting categorical variable names with no samples"""
+        trait = TraitObject({})
+        sample_list = TraitObject({"se_exists": True, "attributes": []})
+        self.assertEqual(get_categorical_variables(trait, sample_list), [])
+
+    def test_get_categorical_variables_with_sample_attributes(self):
+        """test for getting categorical variable names with no samples"""
+        this_trait = TraitObject({"data": {
+            "Gene1": TraitObject({"extra_attributes": {"ex1": "ex1value"}}),
+            "Gene2": TraitObject({"extra_attributes": {"ex2": "ex2value"}}),
+            "Gene3": TraitObject({"extra_attributes": {"ex3": "ex3value"}})
+        }})
+        sample_list = TraitObject({"attributes": {
+            "sample_attribute_1": TraitObject({"name": "ex1"}),
+            "sample_attribute_2": TraitObject({"name": "ex2"}),
+            "sample_attribute_3": TraitObject({"name": "ex3"}),
+            "sample_attribute_4": TraitObject({"name": "not_in_extra_attributes"})
+        }})
+        results = get_categorical_variables(this_trait, sample_list)
+        self.assertEqual(
+            ["ex1", "ex2", "ex3", "not_in_extra_attributes"], results)
+
+    def test_get_trait_units(self):
+        """test for getting trait units"""
+        trait = TraitObject(
+            {"description_fmt": "[this is a description] another test [N/A]"})
+        trait_no_unit_type = TraitObject({"description_fmt": ""})
+        results = get_trait_units(trait)
+        results_no_unit = get_trait_units(trait_no_unit_type)
+        self.assertEqual(results, "this is a descriptionN/A")
+        self.assertEqual(results_no_unit, "Value")
+
+    @mock.patch("wqflask.show_trait.show_trait.g")
+    def test_get_nearest_marker(self, mock_db):
+        """test for getting nearest marker with non-empty db"""
+
+        mock_db.db.execute.return_value.fetchall.return_value = [
+            ["Geno1", "Geno2"], ["Geno3"]]
+
+        trait = TraitObject({"locus_chr": "test_chr", "locus_mb": "test_mb"})
+        group_name = TraitObject({"name": "group_name"})
+        this_db = TraitObject({"group": group_name})
+        results_with_item_db = get_nearest_marker(trait, this_db)
+        called_with_value = """SELECT Geno.Name
+               FROM Geno, GenoXRef, GenoFreeze
+               WHERE Geno.Chr = 'test_chr' AND
+                     GenoXRef.GenoId = Geno.Id AND
+                     GenoFreeze.Id = GenoXRef.GenoFreezeId AND
+                     GenoFreeze.Name = 'group_nameGeno'
+               ORDER BY ABS( Geno.Mb - test_mb) LIMIT 1"""
+
+        mock_db.db.execute.assert_called_with(called_with_value)
+
+        self.assertEqual(results_with_item_db, "Geno1")
+
+    @mock.patch("wqflask.show_trait.show_trait.g")
+    def test_get_nearest_marker_empty_db(self, mock_db):
+        """test for getting nearest marker with empty db"""
+        mock_db.db.execute.return_value.fetchall.return_value = []
+        trait = TraitObject({"locus_chr": "test_chr", "locus_mb": "test_mb"})
+        group_name = TraitObject({"name": "group_name"})
+        this_db = TraitObject({"group": group_name})
+        results_empty_db = get_nearest_marker(trait, this_db)
+        mock_db.db.execute.assert_called_once()
+        self.assertEqual(results_empty_db, "")
+
+    @mock.patch("wqflask.show_trait.show_trait.get_scales_from_genofile")
+    def test_get_genotype_scales_with_genofile_is_list(self, mock_get_scales):
+        """test for getting genotype scales with genofile as list """
+        # where genofile is instance of list
+        genofiles_list = [{"filename": "file1", "location": "~/data/files/f1"},
+                          {"filename": "file2", "location": "~/data/files/f2"},
+                          {"filename": "file3", "location": "~/data/files/f3"}]
+
+        mock_get_scales.side_effect = [[["morgan", "cM"]],
+                                       [["morgan", "cM"]],
+                                       [["physic", "Mb"]]]
+
+        results = get_genotype_scales(genofiles_list)
+        expected_results = {
+            "~/data/files/f1": [["morgan", "cM"]],
+            "~/data/files/f2": [["morgan", "cM"]],
+            "~/data/files/f3": [["physic", "Mb"]]
+        }
+
+        multiple_calls = [mock.call('~/data/files/f1'), mock.call('~/data/files/f2'),
+                          mock.call('~/data/files/f3')]
+        mock_get_scales.assert_has_calls(multiple_calls)
+        self.assertEqual(results, expected_results)
+
+    @mock.patch("wqflask.show_trait.show_trait.get_scales_from_genofile")
+    def test_genotype_scales_with_genofile_other(self, mock_get_scales):
+        """test for getting genotype scales with genofile as a string"""
+        file_location = "~/another_file_location"
+        mock_get_scales.return_value = [["physic", "Mb"]]
+        expected_results = {f"{file_location}": [["physic", "Mb"]]}
+        self.assertEqual(get_genotype_scales(file_location), expected_results)
+        mock_get_scales.assert_called_once_with(file_location)
diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py
index 04d47624..6d6572ff 100644
--- a/wqflask/wqflask/marker_regression/display_mapping_results.py
+++ b/wqflask/wqflask/marker_regression/display_mapping_results.py
@@ -1460,7 +1460,7 @@ class DisplayMappingResults(object):
             else:
                 continue
 
-        smd.sort(lambda A, B: cmp(A.value, B.value))
+        smd.sort(key = lambda A: A.value)
         smd.reverse()
 
         samplelist = list(self.genotype.prgy)
diff --git a/wqflask/wqflask/show_trait/SampleList.py b/wqflask/wqflask/show_trait/SampleList.py
index 37c1d6d5..a535c493 100644
--- a/wqflask/wqflask/show_trait/SampleList.py
+++ b/wqflask/wqflask/show_trait/SampleList.py
@@ -34,13 +34,18 @@ class SampleList(object):
 
             # ZS: self.this_trait will be a list if it is a Temp trait
             if isinstance(self.this_trait, list):
-                if (counter <= len(self.this_trait) and
-                        str(self.this_trait[counter-1]).upper() != 'X'):
-                    sample = webqtlCaseData.webqtlCaseData(
-                        name=sample_name,
-                        value=float(self.this_trait[counter-1]))
-                else:
-                    sample = webqtlCaseData.webqtlCaseData(name=sample_name)
+                sample = webqtlCaseData.webqtlCaseData(name=sample_name)
+                if counter <= len(self.this_trait):
+                    if isinstance(self.this_trait[counter-1], (bytes, bytearray)):
+                        if (self.this_trait[counter-1].decode("utf-8").lower() != 'x'):
+                            sample = webqtlCaseData.webqtlCaseData(
+                                name=sample_name,
+                                value=float(self.this_trait[counter-1]))
+                    else:
+                        if (self.this_trait[counter-1].lower() != 'x'):
+                            sample = webqtlCaseData.webqtlCaseData(
+                                name=sample_name,
+                                value=float(self.this_trait[counter-1]))
             else:
                 # ZS - If there's no value for the sample/strain,
                 # create the sample object (so samples with no value
diff --git a/wqflask/wqflask/show_trait/show_trait.py b/wqflask/wqflask/show_trait/show_trait.py
index edf9638c..0c6ae198 100644
--- a/wqflask/wqflask/show_trait/show_trait.py
+++ b/wqflask/wqflask/show_trait/show_trait.py
@@ -228,8 +228,8 @@ class ShowTrait(object):
         hddn = OrderedDict()
 
         if self.dataset.group.allsamples:
-            hddn['allsamples'] = ''.join(self.dataset.group.allsamples)
-        hddn['primary_samples'] = ''.join(self.primary_sample_names)
+            hddn['allsamples'] = ','.join(self.dataset.group.allsamples)
+        hddn['primary_samples'] = ','.join(self.primary_sample_names)
         hddn['trait_id'] = self.trait_id
         hddn['trait_display_name'] = self.this_trait.display_name
         hddn['dataset'] = self.dataset.name
@@ -372,7 +372,7 @@ class ShowTrait(object):
 
         # We're checking a string here!
         assert isinstance(this_group, str), "We need a string type thing here"
-        if this_group[:3] == 'BXD' and this_group != "BXD-Harvested":
+        if this_group[:3] == 'BXD' and this_group != "BXD-Longevity":
             this_group = 'BXD'
 
         if this_group:
diff --git a/wqflask/wqflask/static/new/css/show_trait.css b/wqflask/wqflask/static/new/css/show_trait.css
index d8964f5d..5e1a279b 100644
--- a/wqflask/wqflask/static/new/css/show_trait.css
+++ b/wqflask/wqflask/static/new/css/show_trait.css
@@ -67,7 +67,7 @@ table.dataTable.cell-border tbody tr td:first-child {
 }
 
 .showtrait-main-div {
-  min-width: 700px;
+  min-width: 1100px;
 }
 
 table.dataTable tbody td.column_name-Checkbox {
diff --git a/wqflask/wqflask/static/new/css/trait_list.css b/wqflask/wqflask/static/new/css/trait_list.css
new file mode 100644
index 00000000..691dcb12
--- /dev/null
+++ b/wqflask/wqflask/static/new/css/trait_list.css
@@ -0,0 +1,12 @@
+div.tool-button-container {

+    min-width: 950px;

+}

+

+div.collection-table-options {

+    min-width: 1100px;

+}

+

+div.show-hide-container {

+    margin-bottom: 5px;

+    margin-top: 10px;

+}
\ No newline at end of file
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 c0f36eaa..34582f21 100644
--- a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js
+++ b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js
@@ -147,7 +147,7 @@ var mapping_input_list = ['temp_uuid', 'trait_id', 'dataset', 'tool_used', 'form
                           'pair_scan', 'startMb', 'endMb', 'graphWidth', 'lrsMax', 'additiveCheck', 'showSNP', 'showGenes', 'viewLegend', 'haplotypeAnalystCheck', 
                           'mapmethod_rqtl_geno', 'mapmodel_rqtl_geno', 'temp_trait', 'group', 'species', 'reaper_version', 'primary_samples']
 
-$(".rqtl_tab, #rqtl_geno_compute").on("click", (function(_this) {
+$(".rqtl-tab, #rqtl_geno_compute").on("click", (function(_this) {
   return function() {
     if ($(this).hasClass('active') || $(this).attr('id') == "rqtl_geno_compute"){
       var form_data, url;
@@ -171,7 +171,7 @@ $(".rqtl_tab, #rqtl_geno_compute").on("click", (function(_this) {
   };
 })(this));
 
-$(".gemma_tab, #gemma_compute").on("click", (function(_this) {
+$(".gemma-tab, #gemma_compute").on("click", (function(_this) {
   return function() {
     if ($(this).hasClass('active') || $(this).attr('id') == "gemma_compute"){
       var form_data, url;
@@ -192,7 +192,7 @@ $(".gemma_tab, #gemma_compute").on("click", (function(_this) {
   };
 })(this));
 
-$(".reaper_tab, #interval_mapping_compute").on("click", (function(_this) {
+$(".reaper-tab, #interval_mapping_compute").on("click", (function(_this) {
   return function() {
     if ($(this).hasClass('active') || $(this).attr('id') == "interval_mapping_compute"){
       var form_data, url;
@@ -260,7 +260,7 @@ $("#mapmethod_rqtl_geno").change(function() {
   }
 });
 
-$("li.mapping_tab").click(function() {
+$("li.mapping-tab").click(function() {
   if ($(this).hasClass("rqtl")){
     $(".rqtl_description").css("display", "block");
   } else {
diff --git a/wqflask/wqflask/templates/collections/view.html b/wqflask/wqflask/templates/collections/view.html
index 873a6703..e37f8104 100644
--- a/wqflask/wqflask/templates/collections/view.html
+++ b/wqflask/wqflask/templates/collections/view.html
@@ -4,6 +4,7 @@
     <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />
     <link rel="stylesheet" type="text/css" href="{{ url_for('js', filename='DataTablesExtensions/buttonStyles/css/buttons.dataTables.min.css') }}">
     <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
+    <link rel="stylesheet" type="text/css" href="/static/new/css/trait_list.css" />
 {% endblock %}
 {% block content %}
 <!-- Start of body -->
@@ -16,7 +17,7 @@
         </h1>
         <h3>This collection has {{ '{}'.format(numify(trait_obs|count, "record", "records")) }}</h3>
 
-        <div>
+        <div class="tool-button-container">
           <form id="collection_form" action="/delete" method="post">
             <input type="hidden" name="uc_id" id="uc_id" value="{{ uc.id }}" />
             <input type="hidden" name="collection_name" id="collection_name" value="{{ collection_name }}" />
@@ -68,20 +69,22 @@
 
         <div>
             <br />
-            <form id="export_form" method="POST" action="/export_traits_csv">
-            <button class="btn btn-default" id="select_all" type="button"><span class="glyphicon glyphicon-ok"></span> Select All</button>
-            <button class="btn btn-default" id="invert" type="button"><span class="glyphicon glyphicon-ok"></span> Invert</button>
-            <button class="btn btn-success" id="add" disabled="disabled" type="button"><i class="icon-plus-sign"></i> Copy</button>
-            <input type="hidden" name="database_name" id="database_name" value="None">
-            <input type="hidden" name="export_data" id="export_data" value="">
-            <input type="hidden" name="file_name" id="file_name" value="collection_table">
-            <button class="btn btn-default" id="export_traits">Download</button>
-            <input type="text" id="searchbox" class="form-control" style="width: 200px; display: inline; padding-bottom: 9px;" placeholder="Search Table For ...">
-            <input type="text" id="select_top" class="form-control" style="width: 200px; display: inline; padding-bottom: 9px;" placeholder="Select Top ...">
-            <button class="btn btn-default" id="deselect_all" type="button"><span class="glyphicon glyphicon-remove"></span> Deselect</button>
-            <button id="remove" class="btn btn-danger" data-url="/collections/remove" disabled="disabled" type="button"><i class="icon-minus-sign"></i> Delete Rows</button>
-            <button id="delete" class="btn btn-danger submit_special" data-url="/collections/delete" title="Delete this collection" > Delete Collection</button>
-            </form>
+            <div class="collection-table-options">
+                <form id="export_form" method="POST" action="/export_traits_csv">
+                    <button class="btn btn-default" id="select_all" type="button"><span class="glyphicon glyphicon-ok"></span> Select All</button>
+                    <button class="btn btn-default" id="invert" type="button"><span class="glyphicon glyphicon-ok"></span> Invert</button>
+                    <button class="btn btn-success" id="add" disabled="disabled" type="button"><i class="icon-plus-sign"></i> Copy</button>
+                    <input type="hidden" name="database_name" id="database_name" value="None">
+                    <input type="hidden" name="export_data" id="export_data" value="">
+                    <input type="hidden" name="file_name" id="file_name" value="collection_table">
+                    <button class="btn btn-default" id="export_traits">Download</button>
+                    <input type="text" id="searchbox" class="form-control" style="width: 200px; display: inline; padding-bottom: 9px;" placeholder="Search Table For ...">
+                    <input type="text" id="select_top" class="form-control" style="width: 200px; display: inline; padding-bottom: 9px;" placeholder="Select Top ...">
+                    <button class="btn btn-default" id="deselect_all" type="button"><span class="glyphicon glyphicon-remove"></span> Deselect</button>
+                    <button id="remove" class="btn btn-danger" data-url="/collections/remove" disabled="disabled" type="button"><i class="icon-minus-sign"></i> Delete Rows</button>
+                    <button id="delete" class="btn btn-danger submit_special" data-url="/collections/delete" title="Delete this collection" > Delete Collection</button>
+                </form>
+            </div>
             <div style="margin-top: 10px; margin-bottom: 5px;">
                 <b>Show/Hide Columns:</b>
             </div>
diff --git a/wqflask/wqflask/templates/correlation_page.html b/wqflask/wqflask/templates/correlation_page.html
index 134f15be..bc0b592c 100644
--- a/wqflask/wqflask/templates/correlation_page.html
+++ b/wqflask/wqflask/templates/correlation_page.html
@@ -367,8 +367,8 @@
                     { "orderDataType": "dom-innertext", 'orderSequence': [ "desc", "asc"] },
                     { "type": "natural" },
                     { "type": "scientific" },
-                    { "type": "numeric-html", 'orderSequence': [ "desc", "asc"] },
-                    { "type": "numeric-html", 'orderSequence': [ "desc", "asc"] },
+                    { "type": "natural-minus-na", 'orderSequence': [ "desc", "asc"] },
+                    { "type": "natural-minus-na", 'orderSequence': [ "desc", "asc"] },
                     { "type": "scientific" },
                     { "type": "natural-minus-na" },
                     { "type": "natural-minus-na" },
diff --git a/wqflask/wqflask/templates/search_result_page.html b/wqflask/wqflask/templates/search_result_page.html
index 6d9ea8fe..36f144c2 100644
--- a/wqflask/wqflask/templates/search_result_page.html
+++ b/wqflask/wqflask/templates/search_result_page.html
@@ -5,6 +5,7 @@
     <link rel="stylesheet" type="text/css" href="{{ url_for('js', filename='DataTablesExtensions/scroller/css/scroller.dataTables.min.css') }}">
     <link rel="stylesheet" type="text/css" href="{{ url_for('js', filename='DataTablesExtensions/buttonStyles/css/buttons.dataTables.min.css') }}">
     <link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
+    <link rel="stylesheet" type="text/css" href="static/new/css/trait_list.css" />
 {% endblock %}
 {% block content %}
 <!-- Start of body -->
@@ -40,10 +41,10 @@
                     {% elif word.search_term|length == 5 %}
                     with <u>{{ word.key|upper }}</u> between <strong>{{ word.search_term[0] }}</strong> and <strong>{{ word.search_term[1] }}</strong> on chromosome <strong>{{ word.search_term[2] }}</strong> between <strong>{{ word.search_term[3] }}</strong> and <strong>{{ word.search_term[4] }}</strong> Mb{% if loop.last %}.{% else %} and {% endif %}
                     {% endif %}
-                    {% elif word.key|lower == "position" %}
-                    with <u>target genes</u> on chromosome <strong>{% if word.search_term[0].split('chr')|length > 1 %}{{ word.search_term[0].split('chr')[1] }}{% elif word.search_term[0].split('CHR')|length > 1 %}{{ word.search_term[0].split('CHR')[1] }}{% else %}{{ word.search_term[0] }}{% endif %}</strong> between <strong>{{ word.search_term[1] }}</strong> and <strong>{{ word.search_term[2] }}</strong> Mb{% if loop.last %}.{% else %} and {% endif %}
+                    {% elif word.key|lower == "position" or word.key|lower == "mb" %}
+                    with <u>target genes</u> on chromosome <strong>{% if (word.search_term[0]|lower).split('chr')|length > 1 %}{{ (word.search_term[0]|lower).split('chr')[1] }}{% else %}{{ word.search_term[0] }}{% endif %}</strong> between <strong>{{ word.search_term[1] }}</strong> and <strong>{{ word.search_term[2] }}</strong> Mb{% if loop.last %}.{% else %} and {% endif %}
                     {% else %}
-                    {% if word.search_term[0] == "*" %} in the dataset.{% else %}{% if loop.first %}that match:<br>{% endif %}<b>"{{ word.search_term[0] }}"</b>{% if loop.last %}{% else %} and {% endif %}{% endif %}
+                    {% if word.search_term[0] == "*" %} in the dataset.{% else %}{% if loop.first %}that match:<br>{% endif %}<b>{{ word.search_term[0] }}</b>{% if loop.last %}{% else %} and {% endif %}{% endif %}
                     {% endif %}
                 {% endfor %}
                 {% endif %}
@@ -133,11 +134,29 @@
               <button class="btn btn-default" id="deselect_all" type="button"><span class="glyphicon glyphicon-remove"></span> Deselect</button>
             </div>
           </form>
-          <br />
           {% if dataset.type != 'Geno' %}
-          <br />
-          <div style="margin-bottom: 5px;">
+          <div class="show-hide-container">
             <b>Show/Hide Columns:</b>
+            <br>
+            <button class="toggle-vis" data-column="1">Index</button>
+            <button class="toggle-vis" data-column="2">Record</button>
+            {% if dataset.type == 'ProbeSet' %}
+            <button class="toggle-vis" data-column="3">Symbol</button>
+            <button class="toggle-vis" data-column="4">Description</button>
+            <button class="toggle-vis" data-column="5">Location</button>
+            <button class="toggle-vis" data-column="6">Mean</button>
+            <button class="toggle-vis" data-column="7">High P</button>
+            <button class="toggle-vis" data-column="8">Peak Location</button>
+            <button class="toggle-vis" data-column="9">Effect Size</button>
+            {% elif dataset.type == 'Publish' %}
+            <button class="toggle-vis" data-column="3">Description</button>
+            <button class="toggle-vis" data-column="4">Mean</button>
+            <button class="toggle-vis" data-column="5">Authors</button>
+            <button class="toggle-vis" data-column="6">Year</button>
+            <button class="toggle-vis" data-column="7">High P</button>
+            <button class="toggle-vis" data-column="8">Peak Location</button>
+            <button class="toggle-vis" data-column="9">Effect Size</button>
+            {% endif %}
           </div>
           {% endif %}
           <div id="table_container" {% if dataset.type == 'ProbeSet' or dataset.type == 'Publish' %}style="min-width: 1500px;"{% endif %}>
@@ -209,7 +228,7 @@
             }
 
             //ZS: Need to make sort by symbol, also need to make sure blank symbol fields at the bottom and symbols starting with numbers below letters
-            $('#trait_table').DataTable( {
+            trait_table = $('#trait_table').DataTable( {
                 'drawCallback': function( settings ) {
                      $('#trait_table tr').click(function(event) {
                          if (event.target.type !== 'checkbox' && event.target.tagName.toLowerCase() !== 'a') {
@@ -381,7 +400,7 @@
                       'orderSequence': [ "desc", "asc"]
                     },
                     {
-                      'title': "Max LRS<a href=\"{{ url_for('glossary_blueprint.glossary') }}#LRS\" target=\"_blank\" style=\"color: white;\"><sup style=\"font-size: small; color: #FF0000;\"> ?</sup></a>",
+                      'title': "High P<a href=\"{{ url_for('glossary_blueprint.glossary') }}#LRS\" target=\"_blank\" style=\"color: white;\"><sup style=\"font-size: small; color: #FF0000;\"> ?</sup></a>",
                       'type': "natural-minus-na",
                       'data': "lrs_score",
                       'width': "80px",
@@ -408,24 +427,7 @@
                     }{% endif %}
                 ],
                 "order": [[1, "asc" ]],
-                {% if dataset.type != 'Geno' %}
-                buttons: [
-                    {
-                        extend: 'columnsToggle',
-                        columns: function( idx, data, node ) {
-                          if (idx != 0) {
-                            return true;
-                          } else {
-                            return false;
-                          }
-                        },
-                        postfixButtons: [ 'colvisRestore' ]
-                    }
-                ],
-                'sDom': "Bpitirp",
-                {% else %}
-                'sDom': "pitirp",
-                {% endif %}
+                'sDom': "itirp",
                 'iDisplayLength': 500,
                 'deferRender': true,
                 'paging': true,
@@ -439,6 +441,23 @@
 
             console.timeEnd("Creating table");
             
+            $('.toggle-vis').on( 'click', function (e) {
+              e.preventDefault();
+
+              // Get the column API object
+              var column = trait_table.column( $(this).attr('data-column') );
+
+              // Toggle the visibility
+              column.visible( ! column.visible() );
+
+              if (column.visible()){
+                $(this).removeClass("active");
+              } else {
+                $(this).addClass("active");
+              }
+            } );
+
+
             $('#redraw').click(function() {
                 var table = $('#trait_table').DataTable();
                 table.colReorder.reset()
@@ -452,3 +471,4 @@
         });
     </script>
 {% endblock %}
+