",
'type': "natural-minus-na",
'width': "60px",
'data': "additive",
--
cgit v1.2.3
From da49ee44334723358957dab3d1393a98ea9d7f51 Mon Sep 17 00:00:00 2001
From: zsloan
Date: Tue, 18 Jan 2022 22:28:24 +0000
Subject: Increased the width of the location columns a bit, since they were
being pushed onto a second line in some browsers (specifically Robs, but
couldn't reproduce in mine, so I just changed it to something that should
work for him)
---
wqflask/wqflask/templates/search_result_page.html | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/wqflask/wqflask/templates/search_result_page.html b/wqflask/wqflask/templates/search_result_page.html
index 065d9049..63e06237 100644
--- a/wqflask/wqflask/templates/search_result_page.html
+++ b/wqflask/wqflask/templates/search_result_page.html
@@ -232,7 +232,7 @@
{
'title': "
",
'type': "natural-minus-na",
- 'width': "120px",
+ 'width': "125px",
'targets': 2,
'data': "location"
}{% endif %}
--
cgit v1.2.3
From 3e3335ec46a61056ffd8130969bca1d6857d182f Mon Sep 17 00:00:00 2001
From: zsloan
Date: Tue, 18 Jan 2022 22:30:53 +0000
Subject: Made the search result table wider for genotype results, since
previously the Location text was being pushed to a second line (this was
actually visible for me as well, not just Rob)
---
wqflask/wqflask/templates/search_result_page.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/wqflask/wqflask/templates/search_result_page.html b/wqflask/wqflask/templates/search_result_page.html
index 63e06237..eb4fe6a1 100644
--- a/wqflask/wqflask/templates/search_result_page.html
+++ b/wqflask/wqflask/templates/search_result_page.html
@@ -126,7 +126,7 @@
{% endif %}
{% endif %}
-
+
Loading...
--
cgit v1.2.3
From 77f15b22adf297a8d46c3d590183b8f52b2baf51 Mon Sep 17 00:00:00 2001
From: zsloan
Date: Wed, 19 Jan 2022 20:05:42 +0000
Subject: Make glossary link question marks italicized and red
---
wqflask/wqflask/templates/search_result_page.html | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/wqflask/wqflask/templates/search_result_page.html b/wqflask/wqflask/templates/search_result_page.html
index eb4fe6a1..c86aae39 100644
--- a/wqflask/wqflask/templates/search_result_page.html
+++ b/wqflask/wqflask/templates/search_result_page.html
@@ -245,7 +245,7 @@
'orderSequence': [ "desc", "asc"]
},
{
- 'title': "
",
'type': "natural-minus-na",
'width': "60px",
'data': "additive",
--
cgit v1.2.3
From 65ebd0ae48d77120569fb830b593c16f52a15cca Mon Sep 17 00:00:00 2001
From: zsloan
Date: Wed, 19 Jan 2022 21:20:19 +0000
Subject: Moved the Show/Hide Columns text onto the same line as the buttons,
to save a little vertical space
---
wqflask/wqflask/templates/search_result_page.html | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/wqflask/wqflask/templates/search_result_page.html b/wqflask/wqflask/templates/search_result_page.html
index 62c0164b..419f9512 100644
--- a/wqflask/wqflask/templates/search_result_page.html
+++ b/wqflask/wqflask/templates/search_result_page.html
@@ -105,8 +105,7 @@
{% if dataset.type != 'Geno' %}
- Show/Hide Columns:
-
+ Show/Hide Columns:
{% if dataset.type == 'ProbeSet' %}
--
cgit v1.2.3
From fb8e8c5f56b122e4561d448ce2873183da73f561 Mon Sep 17 00:00:00 2001
From: zsloan
Date: Thu, 20 Jan 2022 19:40:47 +0000
Subject: Added some JS disabling form submission on hitting Enter, so that
users can hit Enter in the Select Rows text area
---
wqflask/wqflask/static/new/javascript/search_results.js | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/wqflask/wqflask/static/new/javascript/search_results.js b/wqflask/wqflask/static/new/javascript/search_results.js
index 355fd18e..8ab41f25 100644
--- a/wqflask/wqflask/static/new/javascript/search_results.js
+++ b/wqflask/wqflask/static/new/javascript/search_results.js
@@ -130,6 +130,13 @@ $(function() {
})
}
+ $(window).keydown(function(event){
+ if((event.keyCode == 13)) {
+ event.preventDefault();
+ return false;
+ }
+ });
+
$('#select_top').keyup(function(event){
if (event.keyCode === 13) {
filter_by_index()
--
cgit v1.2.3
From 95d06e4b9028e25527239911d99bf584666073a8 Mon Sep 17 00:00:00 2001
From: zsloan
Date: Thu, 20 Jan 2022 19:43:42 +0000
Subject: Changed the placeholder text for the table search to Search For
---
wqflask/wqflask/templates/search_result_page.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/wqflask/wqflask/templates/search_result_page.html b/wqflask/wqflask/templates/search_result_page.html
index 419f9512..a5b2242c 100644
--- a/wqflask/wqflask/templates/search_result_page.html
+++ b/wqflask/wqflask/templates/search_result_page.html
@@ -94,7 +94,7 @@
{% endif %}
-
+
--
cgit v1.2.3
From 58cda1ea8740792beb5d0f3f1de15c51b2f47f82 Mon Sep 17 00:00:00 2001
From: zsloan
Date: Wed, 26 Jan 2022 18:41:31 +0000
Subject: Removed unnecessary variable from for-loop in parse_index_string
---
wqflask/wqflask/static/new/javascript/search_results.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/wqflask/wqflask/static/new/javascript/search_results.js b/wqflask/wqflask/static/new/javascript/search_results.js
index 8ab41f25..17b41812 100644
--- a/wqflask/wqflask/static/new/javascript/search_results.js
+++ b/wqflask/wqflask/static/new/javascript/search_results.js
@@ -96,7 +96,7 @@ $(function() {
parse_index_string = function(idx_string) {
index_list = [];
_ref = idx_string.split(",");
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ for (_i = 0; _i < _ref.length; _i++) {
index_set = _ref[_i];
if (index_set.indexOf('-') !== -1) {
try {
--
cgit v1.2.3
From e374cac6eec2d05345d6f7a05061ee38a63db9f1 Mon Sep 17 00:00:00 2001
From: zsloan
Date: Wed, 26 Jan 2022 19:21:24 +0000
Subject: Changed functions in search_results.js to be camelCased, except for
change_buttons because it's referenced in many other files
---
.../static/new/javascript/search_results.js | 68 +++++++++++-----------
1 file changed, 34 insertions(+), 34 deletions(-)
diff --git a/wqflask/wqflask/static/new/javascript/search_results.js b/wqflask/wqflask/static/new/javascript/search_results.js
index 17b41812..7124151e 100644
--- a/wqflask/wqflask/static/new/javascript/search_results.js
+++ b/wqflask/wqflask/static/new/javascript/search_results.js
@@ -25,10 +25,10 @@ change_buttons = function(check_node = 0) {
};
$(function() {
- var add, checked_traits, deselect_all, invert, remove, removed_traits, select_all;
+ var add, checked_traits, deselectAll, invert, selectAll;
checked_traits = null;
- select_all = function() {
+ selectAll = function() {
table_api = $('#trait_table').DataTable();
check_cells = table_api.column(0).nodes().to$();
@@ -44,7 +44,7 @@ $(function() {
change_buttons();
};
- deselect_all = function() {
+ deselectAll = function() {
table_api = $('#trait_table').DataTable();
check_cells = table_api.column(0).nodes().to$();
@@ -93,7 +93,7 @@ $(function() {
$('#trait_table').DataTable().search($(this).val()).draw();
});
- parse_index_string = function(idx_string) {
+ parseIndexString = function(idx_string) {
index_list = [];
_ref = idx_string.split(",");
for (_i = 0; _i < _ref.length; _i++) {
@@ -117,9 +117,9 @@ $(function() {
return new Set(index_list)
}
- filter_by_index = function() {
+ filterByIndex = function() {
index_string = $('#select_top').val()
- index_set = parse_index_string(index_string)
+ index_set = parseIndexString(index_string)
table_api = $('#trait_table').DataTable();
check_nodes = table_api.column(0).nodes().to$();
@@ -139,15 +139,15 @@ $(function() {
$('#select_top').keyup(function(event){
if (event.keyCode === 13) {
- filter_by_index()
+ filterByIndex()
}
});
$('#select_top').blur(function() {
- filter_by_index()
+ filterByIndex()
});
- add_to_collection = function() {
+ addToCollection = function() {
var traits;
table_api = $('#trait_table').DataTable();
check_nodes = table_api.column(0).nodes().to$();
@@ -174,19 +174,19 @@ $(function() {
};
- removed_traits = function() {
+ removedTraits = function() {
return checked_traits.closest("tr").fadeOut();
};
- submit_bnw = function() {
- trait_data = submit_traits_to_export_or_bnw("trait_table", "submit_bnw")
+ submitBnw = function() {
+ trait_data = submitTraitsToExportOrBnw("trait_table", "submit_bnw")
}
- export_traits = function() {
- trait_data = submit_traits_to_export_or_bnw("trait_table", "export_csv")
+ exportTraits = function() {
+ trait_data = submitTraitsToExportOrBnw("trait_table", "export_csv")
};
- submit_traits_to_export_or_bnw = function(table_name, destination) {
+ submitTraitsToExportOrBnw = function(table_name, destination) {
trait_table = $('#'+table_name);
table_dict = {};
@@ -227,7 +227,7 @@ $(function() {
$('#export_form').submit();
};
- get_traits_from_table = function(){
+ getTraitsFromTable = function(){
traits = $("#trait_table input:checked").map(function() {
return $(this).val();
}).get();
@@ -243,42 +243,42 @@ $(function() {
}
$("#corr_matrix").on("click", function() {
- traits = get_traits_from_table()
+ traits = getTraitsFromTable()
$("#trait_list").val(traits)
$("input[name=tool_used]").val("Correlation Matrix")
$("input[name=form_url]").val($(this).data("url"))
return submit_special("/loading")
});
$("#network_graph").on("click", function() {
- traits = get_traits_from_table()
+ traits = getTraitsFromTable()
$("#trait_list").val(traits)
$("input[name=tool_used]").val("Network Graph")
$("input[name=form_url]").val($(this).data("url"))
return submit_special("/loading")
});
$("#wgcna_setup").on("click", function() {
- traits = get_traits_from_table()
+ traits = getTraitsFromTable()
$("#trait_list").val(traits)
$("input[name=tool_used]").val("WGCNA Setup")
$("input[name=form_url]").val($(this).data("url"))
return submit_special("/loading")
});
$("#ctl_setup").on("click", function() {
- traits = get_traits_from_table()
+ traits = getTraitsFromTable()
$("#trait_list").val(traits)
$("input[name=tool_used]").val("CTL Setup")
$("input[name=form_url]").val($(this).data("url"))
return submit_special("/loading")
});
$("#heatmap").on("click", function() {
- traits = get_traits_from_table()
+ traits = getTraitsFromTable()
$("#trait_list").val(traits)
$("input[name=tool_used]").val("Heatmap")
$("input[name=form_url]").val($(this).data("url"))
return submit_special("/loading")
});
$("#comp_bar_chart").on("click", function() {
- traits = get_traits_from_table()
+ traits = getTraitsFromTable()
$("#trait_list").val(traits)
$("input[name=tool_used]").val("Comparison Bar Chart")
$("input[name=form_url]").val($(this).data("url"))
@@ -286,32 +286,32 @@ $(function() {
});
$("#send_to_webgestalt, #send_to_bnw, #send_to_geneweaver").on("click", function() {
- traits = get_traits_from_table()
+ traits = getTraitsFromTable()
$("#trait_list").val(traits)
url = $(this).data("url")
return submit_special(url)
});
- $("#select_all").click(select_all);
- $("#deselect_all").click(deselect_all);
+ $("#select_all").click(selectAll);
+ $("#deselect_all").click(deselectAll);
$("#invert").click(invert);
- $("#add").click(add_to_collection);
- $("#submit_bnw").click(submit_bnw);
- $("#export_traits").click(export_traits);
+ $("#add").click(addToCollection);
+ $("#submit_bnw").click(submitBnw);
+ $("#export_traits").click(exportTraits);
let naturalAsc = $.fn.dataTableExt.oSort["natural-ci-asc"]
let naturalDesc = $.fn.dataTableExt.oSort["natural-ci-desc"]
let na_equivalent_vals = ["N/A", "--", ""]; //ZS: Since there are multiple values that should be treated the same as N/A
- function extract_inner_text(the_string){
+ function extractInnerText(the_string){
var span = document.createElement('span');
span.innerHTML = the_string;
return span.textContent || span.innerText;
}
- function sort_NAs(a, b, sort_function){
+ function sortNAs(a, b, sort_function){
if ( na_equivalent_vals.includes(a) && na_equivalent_vals.includes(b)) {
return 0;
}
@@ -326,10 +326,10 @@ $(function() {
$.extend( $.fn.dataTableExt.oSort, {
"natural-minus-na-asc": function (a, b) {
- return sort_NAs(extract_inner_text(a), extract_inner_text(b), naturalAsc)
+ return sortNAs(extractInnerText(a), extractInnerText(b), naturalAsc)
},
"natural-minus-na-desc": function (a, b) {
- return sort_NAs(extract_inner_text(a), extract_inner_text(b), naturalDesc)
+ return sortNAs(extractInnerText(a), extractInnerText(b), naturalDesc)
}
});
@@ -347,7 +347,7 @@ $(function() {
} );
}
- apply_default = function() {
+ applyDefault = function() {
let default_collection_id = $.cookie('default_collection');
if (default_collection_id) {
let the_option = $('[name=existing_collection] option').filter(function() {
@@ -356,6 +356,6 @@ $(function() {
the_option.prop('selected', true);
}
}
- apply_default();
+ applyDefault();
});
--
cgit v1.2.3
From 6ab213921932d904c64c8b37a327a971a3c46cfc Mon Sep 17 00:00:00 2001
From: zsloan
Date: Wed, 26 Jan 2022 19:36:38 +0000
Subject: Replaced a confusing for loop with something that is (hopefully)
easier to read and explicitly inverts start_index and end_index when the
former is greater than the latter
---
wqflask/wqflask/static/new/javascript/search_results.js | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/wqflask/wqflask/static/new/javascript/search_results.js b/wqflask/wqflask/static/new/javascript/search_results.js
index 7124151e..a665e3d2 100644
--- a/wqflask/wqflask/static/new/javascript/search_results.js
+++ b/wqflask/wqflask/static/new/javascript/search_results.js
@@ -102,7 +102,13 @@ $(function() {
try {
start_index = parseInt(index_set.split("-")[0]);
end_index = parseInt(index_set.split("-")[1]);
- for (index = _j = start_index; start_index <= end_index ? _j <= end_index : _j >= end_index; index = start_index <= end_index ? ++_j : --_j) {
+
+ // If start index is higher than end index (for example is the string "10-5" exists) swap values so it'll be interpreted as "5-10" instead
+ if (start_index > end_index) {
+ [start_index, end_index] = [end_index, start_index]
+ }
+
+ for (index = start_index; index <= end_index; index++) {
index_list.push(index);
}
} catch (_error) {
--
cgit v1.2.3
From 480d71d9e12878449f7526cacb644f686a9169af Mon Sep 17 00:00:00 2001
From: zsloan
Date: Wed, 26 Jan 2022 19:42:30 +0000
Subject: Added a comment explaining what the parseIndexString function does
---
wqflask/wqflask/static/new/javascript/search_results.js | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/wqflask/wqflask/static/new/javascript/search_results.js b/wqflask/wqflask/static/new/javascript/search_results.js
index a665e3d2..b7ad359f 100644
--- a/wqflask/wqflask/static/new/javascript/search_results.js
+++ b/wqflask/wqflask/static/new/javascript/search_results.js
@@ -93,6 +93,13 @@ $(function() {
$('#trait_table').DataTable().search($(this).val()).draw();
});
+ /**
+ * parseIndexString takes a string consisting of integers,
+ * hyphens, and/or commas to indicate range(s) of indices
+ * to select a rows and returns the corresponding set of indices
+ * For example - "1, 5-10, 15" would return a set of 8 rows
+ * @return {Set} The list of indices as a Set
+ */
parseIndexString = function(idx_string) {
index_list = [];
_ref = idx_string.split(",");
--
cgit v1.2.3
From e5f179330b024671e066edb0672a5a8b628766ed Mon Sep 17 00:00:00 2001
From: zsloan
Date: Wed, 26 Jan 2022 20:54:03 +0000
Subject: Replaced the try/catch with something checking for the correct
pattern with regex, for validating the Select Rows input
---
wqflask/wqflask/static/new/javascript/search_results.js | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/wqflask/wqflask/static/new/javascript/search_results.js b/wqflask/wqflask/static/new/javascript/search_results.js
index b7ad359f..a3e21081 100644
--- a/wqflask/wqflask/static/new/javascript/search_results.js
+++ b/wqflask/wqflask/static/new/javascript/search_results.js
@@ -102,11 +102,17 @@ $(function() {
*/
parseIndexString = function(idx_string) {
index_list = [];
+
_ref = idx_string.split(",");
for (_i = 0; _i < _ref.length; _i++) {
index_set = _ref[_i];
+ if (!/^ *([0-9]+$) *| *([0-9]+ *- *[0-9]+$) *|(^$)$/.test(index_set)) {
+ $('#select_samples_invalid').show();
+ break
+ } else {
+ $('#select_samples_invalid').hide();
+ }
if (index_set.indexOf('-') !== -1) {
- try {
start_index = parseInt(index_set.split("-")[0]);
end_index = parseInt(index_set.split("-")[1]);
@@ -118,10 +124,6 @@ $(function() {
for (index = start_index; index <= end_index; index++) {
index_list.push(index);
}
- } catch (_error) {
- error = _error;
- alert("Syntax error");
- }
} else {
index = parseInt(index_set);
index_list.push(index);
--
cgit v1.2.3
From b25d68790fdf8d66644297dc104408140baf77e5 Mon Sep 17 00:00:00 2001
From: zsloan
Date: Wed, 26 Jan 2022 20:55:37 +0000
Subject: Added the div for showing the error when the Select Rows text has
wrong syntax
---
wqflask/wqflask/templates/search_result_page.html | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/wqflask/wqflask/templates/search_result_page.html b/wqflask/wqflask/templates/search_result_page.html
index a5b2242c..26cdc437 100644
--- a/wqflask/wqflask/templates/search_result_page.html
+++ b/wqflask/wqflask/templates/search_result_page.html
@@ -102,6 +102,10 @@
+
+ Please check that your syntax includes only a combination of integers, dashes, and commas of a format
+ similar to 1,5,10 or 2, 5-10, 15, etc.
+
{% if dataset.type != 'Geno' %}
--
cgit v1.2.3
From 3dc47b73cd597291c8410cad05d1143819303e1d Mon Sep 17 00:00:00 2001
From: zsloan
Date: Thu, 27 Jan 2022 19:21:41 +0000
Subject: Removed unused variables code
---
wqflask/wqflask/static/new/javascript/search_results.js | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/wqflask/wqflask/static/new/javascript/search_results.js b/wqflask/wqflask/static/new/javascript/search_results.js
index a3e21081..4c634399 100644
--- a/wqflask/wqflask/static/new/javascript/search_results.js
+++ b/wqflask/wqflask/static/new/javascript/search_results.js
@@ -25,9 +25,8 @@ change_buttons = function(check_node = 0) {
};
$(function() {
- var add, checked_traits, deselectAll, invert, selectAll;
+ var selectAll, deselectAll, invert;
- checked_traits = null;
selectAll = function() {
table_api = $('#trait_table').DataTable();
@@ -189,10 +188,6 @@ $(function() {
};
- removedTraits = function() {
- return checked_traits.closest("tr").fadeOut();
- };
-
submitBnw = function() {
trait_data = submitTraitsToExportOrBnw("trait_table", "submit_bnw")
}
--
cgit v1.2.3
From 63cfd61c030312158aba242ff239e79e2025f2e0 Mon Sep 17 00:00:00 2001
From: zsloan
Date: Thu, 27 Jan 2022 19:24:04 +0000
Subject: Changed var to let
---
wqflask/wqflask/static/new/javascript/search_results.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/wqflask/wqflask/static/new/javascript/search_results.js b/wqflask/wqflask/static/new/javascript/search_results.js
index 4c634399..c5f9fe00 100644
--- a/wqflask/wqflask/static/new/javascript/search_results.js
+++ b/wqflask/wqflask/static/new/javascript/search_results.js
@@ -25,7 +25,7 @@ change_buttons = function(check_node = 0) {
};
$(function() {
- var selectAll, deselectAll, invert;
+ let selectAll, deselectAll, invert;
selectAll = function() {
table_api = $('#trait_table').DataTable();
--
cgit v1.2.3
From 04ef9ee2f18e812b4a24d478bdbf78303923623e Mon Sep 17 00:00:00 2001
From: zsloan
Date: Thu, 27 Jan 2022 19:40:54 +0000
Subject: Highlight rows selected by filterByIndex
This adds the "selected" class to rows selected by filterByIndex, which adds highlighting to them
I also made the variables in this part of the code camel cased
---
.../wqflask/static/new/javascript/search_results.js | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/wqflask/wqflask/static/new/javascript/search_results.js b/wqflask/wqflask/static/new/javascript/search_results.js
index c5f9fe00..ff2452af 100644
--- a/wqflask/wqflask/static/new/javascript/search_results.js
+++ b/wqflask/wqflask/static/new/javascript/search_results.js
@@ -132,16 +132,23 @@ $(function() {
}
filterByIndex = function() {
- index_string = $('#select_top').val()
- index_set = parseIndexString(index_string)
+ indexString = $('#select_top').val()
+ indexSet = parseIndexString(indexString)
- table_api = $('#trait_table').DataTable();
- check_nodes = table_api.column(0).nodes().to$();
- check_nodes.each(function(index) {
- if (index_set.has(index + 1)){
+ tableApi = $('#trait_table').DataTable();
+ checkNodes = tableApi.column(0).nodes().to$();
+ checkNodes.each(function(index) {
+ if (indexSet.has(index + 1)){
$(this)[0].childNodes[0].checked = true
}
})
+
+ checkRows = tableApi.rows().nodes().to$();
+ checkRows.each(function(index) {
+ if (indexSet.has(index + 1)){
+ $(this)[0].classList.add("selected");
+ }
+ })
}
$(window).keydown(function(event){
--
cgit v1.2.3
From fab4168e813524f8d904cd93e1e4810f9768a09c Mon Sep 17 00:00:00 2001
From: Arun Isaac
Date: Fri, 28 Jan 2022 13:38:00 +0530
Subject: Revert "README: Document `guix shell' development process."
This reverts commit e0a260b0de55fbea0c507eb0ca5fbdc3c1a825c0.
---
README.md | 32 +++++++++++++++-----------------
1 file changed, 15 insertions(+), 17 deletions(-)
diff --git a/README.md b/README.md
index ea473699..2b41a415 100644
--- a/README.md
+++ b/README.md
@@ -11,27 +11,24 @@ many different populations and many types of molecular, cellular, and physiologi
The system is used by scientists and clinicians in the field of precision health care and systems genetics.
GN and its predecessors have been in operation since Jan 1994, making it one of the longest-lived web services in biomedical research (https://en.wikipedia.org/wiki/GeneNetwork, and see a partial list of publications using GN and its predecessor, WebQTL (https://genenetwork.org/references/).
-## Run
+## Install
-We recommend you use GNU Guix. GNU Guix allows you to deploy
-GeneNetwork2 and dependencies as a self contained unit on any machine.
+The recommended installation is with GNU Guix which allows you to
+deploy GN2 and dependencies as a self contained unit on any machine.
The database can be run separately as well as the source tree (for
-developers).
+developers). See the [installation docs](doc/README.org).
+
+## Run
+
+Once having installed GN2 it can be run through a browser
+interface
-Make sure you have the
-[guix-bioinformatics](https://git.genenetwork.org/guix-bioinformatics/guix-bioinformatics)
-channel set up. Then, to drop into a development environment with all
-dependencies, run
```sh
-guix shell -Df guix.scm
-```
-Or, to drop into a development environment in a container, run
-```
-guix shell -C --network -Df guix.scm
+genenetwork2
```
-In the development environment, start GeneNetwork2 by running, for
-example,
+A quick example is
+
```sh
env SERVER_PORT=5300 \
GENENETWORK_FILES=~/data/gn2_data/ \
@@ -42,12 +39,13 @@ env SERVER_PORT=5300 \
For full examples (you may need to set a number of environment
variables), including running scripts and a Python REPL, also see the
-startup script
-[./bin/genenetwork2](https://github.com/genenetwork/genenetwork2/blob/testing/bin/genenetwork2).
+startup script [./bin/genenetwork2](https://github.com/genenetwork/genenetwork2/blob/testing/bin/genenetwork2).
Also mariadb and redis need to be running, see
[INSTALL](./doc/README.org).
+## Development
+
## Testing
To have tests pass, the redis and mariadb instance should be running, because of
--
cgit v1.2.3
From 2b629077ba1ec52233c118707d44dca2fb5e6afb Mon Sep 17 00:00:00 2001
From: Arun Isaac
Date: Fri, 28 Jan 2022 13:38:20 +0530
Subject: Revert "bin: Do not set environment variables set by guix shell."
This reverts commit 344e428126b60932bff4c62c5ded8c36519155e8.
---
README.md | 4 ++++
bin/genenetwork2 | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+)
diff --git a/README.md b/README.md
index 2b41a415..7b4fc01f 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,10 @@ Also mariadb and redis need to be running, see
## Development
+It may be useful to pull in the GN3 python modules locally. For this
+use `GN3_PYTHONPATH` environment that gets injected in
+the ./bin/genenetwork2 startup.
+
## Testing
To have tests pass, the redis and mariadb instance should be running, because of
diff --git a/bin/genenetwork2 b/bin/genenetwork2
index 7669a89a..f1e04eef 100755
--- a/bin/genenetwork2
+++ b/bin/genenetwork2
@@ -91,7 +91,14 @@ fi
export GN2_SETTINGS=$settings # Python
echo GN2_SETTINGS=$settings
+export PATH=$GN2_PROFILE/bin:$PATH
+export PYTHONPATH="$GN2_PROFILE/lib/python3.8/site-packages" # never inject another PYTHONPATH!!
+export R_LIBS_SITE=$GN2_PROFILE/site-library
export JS_GUIX_PATH=$GN2_PROFILE/share/genenetwork2/javascript
+export GUIX_GTK3_PATH="$GN2_PROFILE/lib/gtk-3.0"
+export GI_TYPELIB_PATH="$GN2_PROFILE/lib/girepository-1.0"
+export XDG_DATA_DIRS="$GN2_PROFILE/share"
+export GIO_EXTRA_MODULES="$GN2_PROFILE/lib/gio/modules"
export LC_ALL=C # FIXME
export GUIX_GENENETWORK_FILES="$GN2_PROFILE/share/genenetwork2"
export PLINK_COMMAND="$GN2_PROFILE/bin/plink2"
@@ -99,6 +106,25 @@ export GEMMA_COMMAND="$GN2_PROFILE/bin/gemma"
if [ -z $GEMMA_WRAPPER_COMMAND ]; then
export GEMMA_WRAPPER_COMMAND="$GN2_PROFILE/bin/gemma-wrapper"
fi
+while IFS=":" read -ra PPATH; do
+ for PPART in "${PPATH[@]}"; do
+ if [ ! -d $PPART ] ; then echo "$PPART in PYTHONPATH not valid $PYTHONPATH" ; exit 1 ; fi
+ done
+done <<< "$PYTHONPATH"
+if [ ! -d $R_LIBS_SITE ] ; then echo "R_LIBS_SITE not valid "$R_LIBS_SITE ; exit 1 ; fi
+if [ -z $PYTHONPATH ] ; then
+ echo "ERROR PYTHONPATH has not been set - use GN2_PROFILE!"
+ exit 1
+fi
+if [ ! -d $R_LIBS_SITE ] ; then
+ echo "ERROR R_LIBS_SITE has not been set correctly (we only allow one path) - use GN2_PROFILE!"
+ echo "Paste into your shell the output of (for example)"
+ echo "guix package -p \$GN2_PROFILE --search-paths"
+ exit 1
+fi
+
+# We may change this one:
+export PYTHONPATH=$PYTHON_GN_PATH:$GN2_BASE_DIR/wqflask:$GN3_PYTHONPATH:$PYTHONPATH
# Our UNIX TMPDIR defaults to /tmp - change this on a shared server
if [ -z $TMPDIR ]; then
@@ -114,6 +140,7 @@ set|grep TMPDIR
if [ "$1" = '-c' ] ; then
cd $GN2_BASE_DIR/wqflask
cmd=${2#wqflask/}
+ echo PYTHONPATH=$PYTHONPATH
shift ; shift
echo RUNNING COMMAND $cmd $*
python $cmd $*
@@ -124,6 +151,7 @@ fi
if [ "$1" = "-cli" ] ; then
cd $GN2_BASE_DIR/wqflask
cmd=$2
+ echo PYTHONPATH=$PYTHONPATH
shift ; shift
echo RUNNING COMMAND $cmd $*
$cmd $*
@@ -132,12 +160,14 @@ fi
if [ "$1" = '-gunicorn' ] ; then
cd $GN2_BASE_DIR/wqflask
cmd=$2
+ echo PYTHONPATH=$PYTHONPATH
echo RUNNING gunicorn $cmd
gunicorn $cmd
exit $?
fi
if [ "$1" = '-gunicorn-dev' ] ; then
cd $GN2_BASE_DIR/wqflask
+ echo PYTHONPATH=$PYTHONPATH
if [ -z $SERVER_PORT ]; then echo "ERROR: Provide a SERVER_PORT" ; exit 1 ; fi
cmd="--bind 0.0.0.0:$SERVER_PORT --workers=1 --timeout 180 --reload wsgi"
echo RUNNING gunicorn $cmd
@@ -146,6 +176,7 @@ if [ "$1" = '-gunicorn-dev' ] ; then
fi
if [ "$1" = '-gunicorn-prod' ] ; then
cd $GN2_BASE_DIR/wqflask
+ echo PYTHONPATH=$PYTHONPATH
if [ -z $SERVER_PORT ]; then echo "ERROR: Provide a SERVER_PORT" ; exit 1 ; fi
PID=$TMPDIR/gunicorn.$USER.pid
cmd="--bind 0.0.0.0:$SERVER_PORT --pid $PID --workers 20 --keep-alive 6000 --max-requests 100 --max-requests-jitter 30 --timeout 1200 wsgi"
@@ -159,6 +190,9 @@ echo -n "dir $TMPDIR
dbfilename gn2.rdb
" | redis-server - &
+# Overrides for packages that are not yet public (currently r-auwerx)
+# export R_LIBS_SITE=$R_LIBS_SITE:$HOME/.Rlibs/das1i1pm54dj6lbdcsw5w0sdwhccyj1a-r-3.3.2/lib/R/lib
+
# Start the flask server running GN2
cd $GN2_BASE_DIR/wqflask
echo "Starting with $settings"
--
cgit v1.2.3
From fadf0b836d512c9839f91df77f5f957e7aca6a1c Mon Sep 17 00:00:00 2001
From: Arun Isaac
Date: Fri, 28 Jan 2022 13:38:24 +0530
Subject: Revert "bin: Set GN2_PROFILE from GUIX_ENVIRONMENT."
This reverts commit f4e336eb1ea526156e112cff97a3ec8137a2bc90.
---
README.md | 17 +++++++-----
bin/genenetwork2 | 83 ++++++++++++++++++++++++++++++++++++--------------------
2 files changed, 63 insertions(+), 37 deletions(-)
diff --git a/README.md b/README.md
index 7b4fc01f..52382c98 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,7 @@ genenetwork2
A quick example is
```sh
-env SERVER_PORT=5300 \
+env GN2_PROFILE=~/opt/gn-latest SERVER_PORT=5300 \
GENENETWORK_FILES=~/data/gn2_data/ \
GN_PROXY_URL="http://localhost:8080"\
GN3_LOCAL_URL="http://localhost:8081"\
@@ -69,16 +69,19 @@ We are building 'Mechanical Rob' automated testing using Python
which can be run with:
```sh
-env ./bin/genenetwork2 \
+env GN2_PROFILE=~/opt/gn-latest \
+ ./bin/genenetwork2 \
GN_PROXY_URL="http://localhost:8080" \
GN3_LOCAL_URL="http://localhost:8081 "\
./etc/default_settings.py -c \
../test/requests/test-website.py -a http://localhost:5003
```
-The ./bin/genenetwork2 script sets up the environment and executes
-test-website.py in a Python interpreter. The -a switch says to run all
-tests and the URL points to the running GN2 http server.
+The GN2_PROFILE is the Guix profile that contains all
+dependencies. The ./bin/genenetwork2 script sets up the environment
+and executes test-website.py in a Python interpreter. The -a switch
+says to run all tests and the URL points to the running GN2 http
+server.
#### Unit tests
@@ -99,9 +102,9 @@ runcmd coverage html
The `runcmd` and `runpython` are shell aliases defined in the following way:
```sh
-alias runpython="env TMPDIR=/tmp SERVER_PORT=5004 GENENETWORK_FILES=/gnu/data/gn2_data/ GN_PROXY_URL="http://localhost:8080" GN3_LOCAL_URL="http://localhost:8081" ./bin/genenetwork2
+alias runpython="env GN2_PROFILE=~/opt/gn-latest TMPDIR=/tmp SERVER_PORT=5004 GENENETWORK_FILES=/gnu/data/gn2_data/ GN_PROXY_URL="http://localhost:8080" GN3_LOCAL_URL="http://localhost:8081" ./bin/genenetwork2
-alias runcmd="time env TMPDIR=//tmp SERVER_PORT=5004 GENENETWORK_FILES=/gnu/data/gn2_data/ GN_PROXY_URL="http://localhost:8080" GN3_LOCAL_URL="http://localhost:8081" ./bin/genenetwork2 ./etc/default_settings.py -cli"
+alias runcmd="time env GN2_PROFILE=~/opt/gn-latest TMPDIR=//tmp SERVER_PORT=5004 GENENETWORK_FILES=/gnu/data/gn2_data/ GN_PROXY_URL="http://localhost:8080" GN3_LOCAL_URL="http://localhost:8081" ./bin/genenetwork2 ./etc/default_settings.py -cli"
```
Replace some of the env variables as per your use case.
diff --git a/bin/genenetwork2 b/bin/genenetwork2
index f1e04eef..ea5a4f50 100755
--- a/bin/genenetwork2
+++ b/bin/genenetwork2
@@ -5,45 +5,55 @@
#
# Typical usage
#
-# ./bin/genenetwork2 ~/my_settings.py
+# env GN2_PROFILE=~/opt/genenetwork2-phewas ./bin/genenetwork2 ~/my_settings.py
+#
+# Where GN2_PROFILE points to the GNU Guix profile used for deployment.
#
# This will run the GN2 server (with default settings if none
-# supplied).
+# supplied). Typically you need a GNU Guix profile which is set with
+# an environment variable (this profile is dictated by the
+# installation path of genenetwork). Say your profile is in
+# ~/opt/gn-latest-guix
+#
+# env GN2_PROFILE=~/opt/gn-latest ./bin/genenetwork2
+#
+# You can pass in your own settings file, e.g.
+#
+# env GN2_PROFILE=~/opt/gn-latest ./bin/genenetwork2 ~/my_settings.py
#
# To run a maintenance python script with settings (instead of the
# webserver) run from the base-dir with settings file and add that
# script with a -c switch, e.g.
#
-# env TMPDIR=/export/local/home/zas1024/gn2-zach/tmp WEBSERVER_MODE=DEBUG LOG_LEVEL=DEBUG SERVER_PORT=5002 GENENETWORK_FILES=/export/local/home/zas1024/gn2-zach/genotype_files SQL_URI=mysql://webqtlout:webqtlout@lily.uthsc.edu/db_webqtl ./bin/genenetwork2 ./etc/default_settings.py -c ./maintenance/gen_select_dataset.py
+# env GN2_PROFILE=/usr/local/guix-profiles/gn-latest-20190905 TMPDIR=/export/local/home/zas1024/gn2-zach/tmp WEBSERVER_MODE=DEBUG LOG_LEVEL=DEBUG SERVER_PORT=5002 GENENETWORK_FILES=/export/local/home/zas1024/gn2-zach/genotype_files SQL_URI=mysql://webqtlout:webqtlout@lily.uthsc.edu/db_webqtl ./bin/genenetwork2 ./etc/default_settings.py -c ./maintenance/gen_select_dataset.py
#
# To run any script in the environment
#
-# ./bin/genenetwork2 ./etc/default_settings.py -cli echo "HELLO WORLD"
+# env GN2_PROFILE=~/opt/gn-latest ./bin/genenetwork2 ./etc/default_settings.py -cli echo "HELLO WORLD"
#
# To get a python REPL(!)
#
-# ./bin/genenetwork2 ./etc/default_settings.py -cli python
+# env GN2_PROFILE=~/opt/gn-latest ./bin/genenetwork2 ./etc/default_settings.py -cli python
#
# For development you may want to run
#
-# env WEBSERVER_MODE=DEBUG LOG_LEVEL=DEBUG ./bin/genenetwork2
+# env GN2_PROFILE=~/opt/gn-latest WEBSERVER_MODE=DEBUG LOG_LEVEL=DEBUG ./bin/genenetwork2
#
# For staging and production we use gunicorn. Run with something like
# (note you have to provide the server port). Provide a settings file!
#
-# env SERVER_PORT=5003 ./bin/genenetwork2 ./etc/default_settings.py -gunicorn-prod
+# env GN2_PROFILE=~/opt/gn-latest-guix SERVER_PORT=5003 ./bin/genenetwork2 ./etc/default_settings.py -gunicorn-prod
#
# For development use
#
-# env SERVER_PORT=5003 ./bin/genenetwork2 ./etc/default_settings.py -gunicorn-dev
+# env GN2_PROFILE=~/opt/gn-latest-guix SERVER_PORT=5003 ./bin/genenetwork2 ./etc/default_settings.py -gunicorn-dev
#
# For extra flexibility you can also provide gunicorn parameters yourself with something like
#
-# ./bin/genenetwork2 ./etc/default_settings.py -gunicorn "--bind 0.0.0.0:5003 --workers=1 wsgi"
+# env GN2_PROFILE=~/opt/gn-latest-guix ./bin/genenetwork2 ./etc/default_settings.py -gunicorn "--bind 0.0.0.0:5003 --workers=1 wsgi"
SCRIPT=$(realpath "$0")
echo SCRIPT=$SCRIPT
-export GN2_PROFILE=$GUIX_ENVIRONMENT
echo GN2_PROFILE=$GN2_PROFILE
GN2_BASE_DIR=$(dirname $(dirname "$SCRIPT"))
GN2_ID=$(cat /etc/hostname):$(basename $GN2_BASE_DIR)
@@ -91,27 +101,40 @@ fi
export GN2_SETTINGS=$settings # Python
echo GN2_SETTINGS=$settings
-export PATH=$GN2_PROFILE/bin:$PATH
-export PYTHONPATH="$GN2_PROFILE/lib/python3.8/site-packages" # never inject another PYTHONPATH!!
-export R_LIBS_SITE=$GN2_PROFILE/site-library
-export JS_GUIX_PATH=$GN2_PROFILE/share/genenetwork2/javascript
-export GUIX_GTK3_PATH="$GN2_PROFILE/lib/gtk-3.0"
-export GI_TYPELIB_PATH="$GN2_PROFILE/lib/girepository-1.0"
-export XDG_DATA_DIRS="$GN2_PROFILE/share"
-export GIO_EXTRA_MODULES="$GN2_PROFILE/lib/gio/modules"
-export LC_ALL=C # FIXME
-export GUIX_GENENETWORK_FILES="$GN2_PROFILE/share/genenetwork2"
-export PLINK_COMMAND="$GN2_PROFILE/bin/plink2"
-export GEMMA_COMMAND="$GN2_PROFILE/bin/gemma"
-if [ -z $GEMMA_WRAPPER_COMMAND ]; then
- export GEMMA_WRAPPER_COMMAND="$GN2_PROFILE/bin/gemma-wrapper"
+if [ -z $GN2_PROFILE ] ; then
+ echo "WARNING: GN2_PROFILE has not been set - you need the environment, so I hope you know what you are doing!"
+ export GN2_PROFILE=$(dirname $(dirname $(which genenetwork2)))
+ if [ -d $GN2_PROFILE ]; then
+ echo "Best guess is $GN2_PROFILE"
+ fi
+ echo "ERROR: always set GN2_PROFILE"
+ exit 1
+fi
+if [ -z $GN2_PROFILE ]; then
+ read -p "PRESS [ENTER] TO CONTINUE..."
+else
+ export PATH=$GN2_PROFILE/bin:$PATH
+ export PYTHONPATH="$GN2_PROFILE/lib/python3.8/site-packages" # never inject another PYTHONPATH!!
+ export R_LIBS_SITE=$GN2_PROFILE/site-library
+ export JS_GUIX_PATH=$GN2_PROFILE/share/genenetwork2/javascript
+ export GUIX_GTK3_PATH="$GN2_PROFILE/lib/gtk-3.0"
+ export GI_TYPELIB_PATH="$GN2_PROFILE/lib/girepository-1.0"
+ export XDG_DATA_DIRS="$GN2_PROFILE/share"
+ export GIO_EXTRA_MODULES="$GN2_PROFILE/lib/gio/modules"
+ export LC_ALL=C # FIXME
+ export GUIX_GENENETWORK_FILES="$GN2_PROFILE/share/genenetwork2"
+ export PLINK_COMMAND="$GN2_PROFILE/bin/plink2"
+ export GEMMA_COMMAND="$GN2_PROFILE/bin/gemma"
+ if [ -z $GEMMA_WRAPPER_COMMAND ]; then
+ export GEMMA_WRAPPER_COMMAND="$GN2_PROFILE/bin/gemma-wrapper"
+ fi
+ while IFS=":" read -ra PPATH; do
+ for PPART in "${PPATH[@]}"; do
+ if [ ! -d $PPART ] ; then echo "$PPART in PYTHONPATH not valid $PYTHONPATH" ; exit 1 ; fi
+ done
+ done <<< "$PYTHONPATH"
+ if [ ! -d $R_LIBS_SITE ] ; then echo "R_LIBS_SITE not valid "$R_LIBS_SITE ; exit 1 ; fi
fi
-while IFS=":" read -ra PPATH; do
- for PPART in "${PPATH[@]}"; do
- if [ ! -d $PPART ] ; then echo "$PPART in PYTHONPATH not valid $PYTHONPATH" ; exit 1 ; fi
- done
-done <<< "$PYTHONPATH"
-if [ ! -d $R_LIBS_SITE ] ; then echo "R_LIBS_SITE not valid "$R_LIBS_SITE ; exit 1 ; fi
if [ -z $PYTHONPATH ] ; then
echo "ERROR PYTHONPATH has not been set - use GN2_PROFILE!"
exit 1
--
cgit v1.2.3
From 631504680ce31b1a181cf6617e87ef0cc2cefa26 Mon Sep 17 00:00:00 2001
From: zsloan
Date: Fri, 28 Jan 2022 13:40:10 -0600
Subject: Revert 'bin: Set shebang to sh instead of bash'
It seems that this also needed to be reverted, because I was getting the error below (which was prevented by reverting to #! /bin/bash):
./bin/genenetwork2: 135: ./bin/genenetwork2: Syntax error: redirection unexpected---
bin/genenetwork2 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bin/genenetwork2 b/bin/genenetwork2
index ea5a4f50..ea70835b 100755
--- a/bin/genenetwork2
+++ b/bin/genenetwork2
@@ -1,4 +1,4 @@
-#! /bin/sh -e
+#! /bin/bash
#
# This is the startup script for GN2. It sets the environment variables to pick
# up a Guix profile and allows for overriding parameters.
--
cgit v1.2.3
From b9f16a3b28c4d996ac91befa5a919a9e0a7ac981 Mon Sep 17 00:00:00 2001
From: zsloan
Date: Fri, 28 Jan 2022 14:53:53 -0600
Subject: Update PYTHONPATH
The PYTHONPATH apparently needs to be updated to 3.9, because 3.8 throws an error (at least on production).---
bin/genenetwork2 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bin/genenetwork2 b/bin/genenetwork2
index ea70835b..1d645c23 100755
--- a/bin/genenetwork2
+++ b/bin/genenetwork2
@@ -114,7 +114,7 @@ if [ -z $GN2_PROFILE ]; then
read -p "PRESS [ENTER] TO CONTINUE..."
else
export PATH=$GN2_PROFILE/bin:$PATH
- export PYTHONPATH="$GN2_PROFILE/lib/python3.8/site-packages" # never inject another PYTHONPATH!!
+ export PYTHONPATH="$GN2_PROFILE/lib/python3.9/site-packages" # never inject another PYTHONPATH!!
export R_LIBS_SITE=$GN2_PROFILE/site-library
export JS_GUIX_PATH=$GN2_PROFILE/share/genenetwork2/javascript
export GUIX_GTK3_PATH="$GN2_PROFILE/lib/gtk-3.0"
--
cgit v1.2.3
From a01033438a85e3097e4ade30e9a208fd5109d4e1 Mon Sep 17 00:00:00 2001
From: Frederick Muriuki Muriithi
Date: Mon, 6 Dec 2021 17:58:28 +0300
Subject: Add "Partial Correlations" UI elements on collections page
Issue:
https://github.com/genenetwork/gn-gemtext-threads/blob/main/topics/gn1-migration-to-gn2/partial-correlations.gmi
* Add UI elements to trigger the partial correlations feature
* Connect partial correlation view to the application
* Point to correct application element for gunicorn
---
bin/genenetwork2 | 2 +-
wqflask/wqflask/__init__.py | 1 +
wqflask/wqflask/partial_correlations_views.py | 263 +++++++++++++++++++++
wqflask/wqflask/templates/collections/view.html | 17 ++
.../wqflask/templates/partial_correlations.html | 199 ++++++++++++++++
5 files changed, 481 insertions(+), 1 deletion(-)
create mode 100644 wqflask/wqflask/partial_correlations_views.py
create mode 100644 wqflask/wqflask/templates/partial_correlations.html
diff --git a/bin/genenetwork2 b/bin/genenetwork2
index 1d645c23..0a2c18cf 100755
--- a/bin/genenetwork2
+++ b/bin/genenetwork2
@@ -192,7 +192,7 @@ if [ "$1" = '-gunicorn-dev' ] ; then
cd $GN2_BASE_DIR/wqflask
echo PYTHONPATH=$PYTHONPATH
if [ -z $SERVER_PORT ]; then echo "ERROR: Provide a SERVER_PORT" ; exit 1 ; fi
- cmd="--bind 0.0.0.0:$SERVER_PORT --workers=1 --timeout 180 --reload wsgi"
+ cmd="--bind 0.0.0.0:$SERVER_PORT --workers=1 --timeout 180 --reload run_gunicorn:app"
echo RUNNING gunicorn $cmd
gunicorn $cmd
exit $?
diff --git a/wqflask/wqflask/__init__.py b/wqflask/wqflask/__init__.py
index 05e040ed..ab8b9e66 100644
--- a/wqflask/wqflask/__init__.py
+++ b/wqflask/wqflask/__init__.py
@@ -98,3 +98,4 @@ from wqflask import user_login
from wqflask import user_session
import wqflask.views
+import wqflask.partial_correlations_views
diff --git a/wqflask/wqflask/partial_correlations_views.py b/wqflask/wqflask/partial_correlations_views.py
new file mode 100644
index 00000000..bee0a033
--- /dev/null
+++ b/wqflask/wqflask/partial_correlations_views.py
@@ -0,0 +1,263 @@
+from typing import Union, Tuple
+
+import MySQLdb
+from gn3.db.traits import retrieve_trait_info
+from flask import flash, request, current_app, render_template
+from gn3.computations.partial_correlations import partial_correlations_entry
+
+from wqflask import app
+
+def parse_trait(trait_str: str) -> Union[dict, None]:
+ keys = ("name", "dataset", "symbol", "description", "data_hmac")
+ parts = tuple(part.strip() for part in trait_str.split(":::"))
+ if len(parts) == len(keys):
+ return dict(zip(keys, parts))
+ return None
+
+def process_step_select_primary(
+ primary_trait: dict, control_traits: Tuple[dict, ...],
+ target_traits: Tuple[dict, ...],
+ traits_list: Tuple[dict, ...], corr_method: str) -> Tuple[
+ str, dict, Tuple[dict, ...], Tuple[dict, ...], Tuple[dict, ...],
+ str]:
+ if primary_trait is None:
+ flash("You must select a primary trait", "alert-danger")
+ return (
+ "select-primary", primary_trait, control_traits, target_traits,
+ traits_list, corr_method)
+
+ return (
+ "select-controls", primary_trait, control_traits, target_traits,
+ tuple(
+ trait for trait in traits_list
+ if trait["data_hmac"] != primary_trait["data_hmac"]),
+ corr_method)
+
+def process_step_select_controls(
+ primary_trait: dict, control_traits: Tuple[dict, ...],
+ target_traits: Tuple[dict, ...],
+ traits_list: Tuple[dict, ...], corr_method: str) -> Tuple[
+ str, dict, Tuple[dict, ...], Tuple[dict, ...], Tuple[dict, ...],
+ str]:
+ if len(control_traits) == 0 or len(control_traits) > 3:
+ flash(
+ ("You must select a minimum of one control trait, up to a maximum "
+ "of three control traits."),
+ "alert-danger")
+ return (
+ "select-controls", primary_trait, control_traits, target_traits,
+ traits_list, corr_method)
+
+ hmacs =(primary_trait["data_hmac"],) + tuple(
+ trait["data_hmac"] for trait in control_traits)
+ return (
+ "select-targets", primary_trait, control_traits, target_traits,
+ tuple(
+ trait for trait in traits_list if trait["data_hmac"] not in hmacs),
+ corr_method)
+
+def process_step_select_targets(
+ primary_trait: dict, control_traits: Tuple[dict, ...],
+ target_traits: Tuple[dict, ...],
+ traits_list: Tuple[dict, ...], corr_method: str) -> Tuple[
+ str, dict, Tuple[dict, ...], Tuple[dict, ...], Tuple[dict, ...],
+ str]:
+ if len(target_traits) == 0:
+ flash(
+ "You must select at least one target trait.", "alert-danger")
+ return (
+ "select-targets", primary_trait, control_traits, target_traits,
+ traits_list, corr_method)
+
+ hmacs =(primary_trait["data_hmac"],) + tuple(
+ trait["data_hmac"] for trait in (control_traits + target_traits))
+ return (
+ "select-corr-method", primary_trait, control_traits, target_traits,
+ tuple(
+ trait for trait in traits_list if trait["data_hmac"] not in hmacs),
+ corr_method)
+
+def process_step_select_corr_method(
+ primary_trait: dict, control_traits: Tuple[dict, ...],
+ target_traits: Tuple[dict, ...],
+ traits_list: Tuple[dict, ...], corr_method: str) -> Tuple[
+ str, dict, Tuple[dict, ...], Tuple[dict, ...], Tuple[dict, ...],
+ str]:
+ methods = (
+ "genetic correlation, pearson's r",
+ "genetic correlation, spearman's rho",
+ "sgo literature correlation",
+ "tissue correlation, pearson's r",
+ "tissue correlation, spearman's rho")
+ if corr_method.lower() not in methods:
+ flash(
+ "Selected method is unknown.", "alert-danger")
+ return (
+ "select-corr-method", primary_trait, control_traits, target_traits,
+ traits_list, corr_method)
+
+ hmacs =(primary_trait["data_hmac"],) + tuple(
+ trait["data_hmac"] for trait in (control_traits + target_traits))
+ return (
+ "run-correlation", primary_trait, control_traits, target_traits,
+ tuple(
+ trait for trait in traits_list if trait["data_hmac"] not in hmacs),
+ corr_method)
+
+def process_step(
+ step: str, primary_trait: dict, control_traits: Tuple[dict, ...],
+ target_traits: Tuple[dict, ...], traits_list: Tuple[dict, ...],
+ corr_method: str) -> Tuple[
+ str, dict, Tuple[dict, ...], Tuple[dict, ...], Tuple[dict, ...],
+ str]:
+ processor_functions = {
+ # "select-traits": lambda arg: arg,
+ "select-primary": process_step_select_primary,
+ "select-controls": process_step_select_controls,
+ "select-targets": process_step_select_targets,
+ "select-corr-method": process_step_select_corr_method
+ }
+ return processor_functions[(step or "select-primary")](
+ primary_trait, control_traits, target_traits, traits_list, corr_method)
+
+def sequence_of_traits(trait_strs) -> Tuple[dict, ...]:
+ return tuple(filter(
+ lambda trt: trt is not None,
+ (parse_trait(tstr.strip()) for tstr in trait_strs)))
+
+def publish_target_dabases(conn, group, threshold):
+ query = (
+ "SELECT PublishFreeze.FullName,PublishFreeze.Name "
+ "FROM PublishFreeze, InbredSet "
+ "WHERE PublishFreeze.InbredSetId = InbredSet.Id "
+ "AND InbredSet.Name = %(group)s "
+ "AND PublishFreeze.public > %(threshold)s")
+ with conn.cursor() as cursor:
+ cursor.execute(query, {"group": group, "threshold": threshold})
+ res = cursor.fetchall()
+ if res:
+ return tuple(
+ dict(zip(("description", "value"), row)) for row in res)
+
+ return tuple()
+
+def geno_target_databases(conn, group, threshold):
+ query = (
+ "SELECT GenoFreeze.FullName,GenoFreeze.Name "
+ "FROM GenoFreeze, InbredSet "
+ "WHERE GenoFreeze.InbredSetId = InbredSet.Id "
+ "AND InbredSet.Name = %(group)s "
+ "AND GenoFreeze.public > %(threshold)s")
+ with conn.cursor() as cursor:
+ cursor.execute(query, {"group": group, "threshold": threshold})
+ res = cursor.fetchall()
+ if res:
+ return tuple(
+ dict(zip(("description", "value"), row)) for row in res)
+
+ return tuple()
+
+def probeset_target_databases(conn, group, threshold):
+ query1 = "SELECT Id, Name FROM Tissue order by Name"
+ query2 = (
+ "SELECT ProbeFreeze.TissueId, ProbeSetFreeze.FullName, ProbeSetFreeze.Name "
+ "FROM ProbeSetFreeze, ProbeFreeze, InbredSet "
+ "WHERE ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id "
+ "AND ProbeFreeze.TissueId IN %(tissue_ids)s "
+ "AND ProbeSetFreeze.public > %(threshold)s "
+ "AND ProbeFreeze.InbredSetId = InbredSet.Id "
+ "AND InbredSet.Name like %(group)s "
+ "ORDER BY ProbeSetFreeze.CreateTime desc, ProbeSetFreeze.AvgId")
+ with conn.cursor() as cursor:
+ cursor.execute(query1)
+ tissue_res = cursor.fetchall()
+ if tissue_res:
+ tissue_ids = tuple(row[0] for row in tissue_res)
+ cursor.execute(
+ query2,{
+ "tissue_ids": tissue_ids, "group": f"{group}%%",
+ "threshold": threshold
+ })
+ db_res = cursor.fetchall()
+ if db_res:
+ databases = tuple(
+ dict(zip(("tissue_id", "description", "value"), row))
+ for row in db_res)
+ return tuple(
+ {tissue_name: tuple(
+ {
+ "value": item["value"],
+ "description": item["description"]
+ } for item in databases
+ if item["tissue_id"] == tissue_id)}
+ for tissue_id, tissue_name in tissue_res)
+
+ return tuple()
+
+def target_databases(conn, step, trait, threshold):
+ """
+ Retrieves the names of possible target databases from the database.
+ """
+ if step != "select-corr-method":
+ return None
+
+ trait_info = retrieve_trait_info(
+ threshold, f"{trait['dataset']}::{trait['name']}", conn)
+ group = trait_info["group"]
+ return (
+ publish_target_dabases(conn, group, threshold) +
+ geno_target_databases(conn, group, threshold) +
+ probeset_target_databases(conn, group, threshold))
+
+def pcorrelations(conn, values):
+ if values["step"] != "run-correlation":
+ return None
+
+ def trait_fullname(trait):
+ return f"{trait['dataset']}::{trait['name']}"
+
+ return partial_correlations_entry(
+ conn, trait_fullname(values["primary_trait"]),
+ tuple(trait_fullname(trait) for trait in values["control_traits"]),
+ values["method"], values["criteria"], values["target_db"])
+
+@app.route("/partial_correlations", methods=("POST",))
+def partial_correlations():
+ form = request.form
+ traits_list = tuple(filter(
+ lambda trt: trt is not None,
+ (parse_trait(tstr) for tstr in form.get("traits_list", "").split("|||"))))
+
+ args_dict = dict(zip(
+ ("step", "primary_trait", "control_traits", "target_traits",
+ "traits_list", "method"),
+ process_step(
+ form.get("step", None),
+ parse_trait(form.get("primary_trait", "")),
+ sequence_of_traits(
+ form.getlist("control_traits[]") or
+ form.get("control_traits", "").split("|||")),
+ sequence_of_traits(
+ form.getlist("target_traits[]") or
+ form.get("target_traits", "").split("|||")),
+ sequence_of_traits(form.get("traits_list", "").split("|||")),
+ form.get("method"))))
+
+ conn = MySQLdb.Connect(
+ db=current_app.config.get("DB_NAME"),
+ user=current_app.config.get("DB_USER"),
+ passwd=current_app.config.get("DB_PASS"),
+ host=current_app.config.get("DB_HOST"))
+ target_dbs = target_databases(
+ conn, args_dict["step"], args_dict["primary_trait"], 0)
+
+ if args_dict["step"] == "run-correlation":
+ args_dict = {
+ **args_dict, "target_db": form.get("target_db"),
+ "criteria": int(form.get("criteria", 500))}
+
+ corr_results = pcorrelations(conn, args_dict)
+
+ return render_template(
+ "partial_correlations.html", **args_dict, target_dbs=target_dbs,
+ corr_results=corr_results)
diff --git a/wqflask/wqflask/templates/collections/view.html b/wqflask/wqflask/templates/collections/view.html
index 0ded66a6..f4270b67 100644
--- a/wqflask/wqflask/templates/collections/view.html
+++ b/wqflask/wqflask/templates/collections/view.html
@@ -34,6 +34,23 @@