aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Kabui2020-12-04 21:41:28 +0300
committerAlexander Kabui2020-12-04 21:41:28 +0300
commitf67f0f0d8f62f8bb6f8b708886c6ec2252450aeb (patch)
treead01d1e1f2e118ddb263d325a8b64b43064366d6
parent9b7c09e14576a39c3f986e5b6e633b0380a72095 (diff)
parent8084309bdfa46e29d3cc941911fa25b23f8400d5 (diff)
downloadgenenetwork2-f67f0f0d8f62f8bb6f8b708886c6ec2252450aeb.tar.gz
Merge branch 'testing' of https://github.com/genenetwork/genenetwork2 into bugfix/markdown-links-fix
-rw-r--r--wqflask/wqflask/correlation/show_corr_results.py1
-rw-r--r--wqflask/wqflask/export_traits.py8
-rw-r--r--wqflask/wqflask/markdown_routes.py55
-rw-r--r--wqflask/wqflask/static/new/css/markdown.css41
-rw-r--r--wqflask/wqflask/static/new/javascript/lodheatmap.js6
-rw-r--r--wqflask/wqflask/static/new/javascript/panelutil.js1
-rw-r--r--wqflask/wqflask/static/new/javascript/search_results.js165
-rw-r--r--wqflask/wqflask/templates/collections/view.html33
-rw-r--r--wqflask/wqflask/templates/correlation_page.html54
-rw-r--r--wqflask/wqflask/templates/environment.html152
-rw-r--r--wqflask/wqflask/templates/search_result_page.html46
11 files changed, 368 insertions, 194 deletions
diff --git a/wqflask/wqflask/correlation/show_corr_results.py b/wqflask/wqflask/correlation/show_corr_results.py
index 1b801b1d..51aa1622 100644
--- a/wqflask/wqflask/correlation/show_corr_results.py
+++ b/wqflask/wqflask/correlation/show_corr_results.py
@@ -487,6 +487,7 @@ def generate_corr_json(corr_results, this_trait, dataset, target_dataset, for_ap
results_dict['index'] = i + 1
results_dict['trait_id'] = trait.name
results_dict['dataset'] = trait.dataset.name
+ results_dict['hmac'] = hmac.data_hmac('{}:{}'.format(trait.name, trait.dataset.name))
if target_dataset.type == "ProbeSet":
results_dict['symbol'] = trait.symbol
results_dict['description'] = "N/A"
diff --git a/wqflask/wqflask/export_traits.py b/wqflask/wqflask/export_traits.py
index 3a886537..6fb760e0 100644
--- a/wqflask/wqflask/export_traits.py
+++ b/wqflask/wqflask/export_traits.py
@@ -44,7 +44,7 @@ def export_search_results_csv(targs):
if targs['filter_term'] != "None":
metadata.append(["Search Filter Terms: " + targs['filter_term']])
metadata.append(["Exported Row Number: " + str(len(table_rows))])
- metadata.append(["Funding for The GeneNetwork: NIAAA (U01AA13499, U24AA13513), NIDA, NIMH, and NIAAA (P20-DA21131), NCI MMHCC (U01CA105417), and NCRR (U01NR 105417)"])
+ metadata.append(["Funding for The GeneNetwork: NIGMS (R01 GM123489, 2017-2021), NIDA (P30 DA044223, 2017-2022), NIA (R01AG043930, 2013-2018), NIAAA (U01 AA016662, U01 AA013499, U24 AA013513, U01 AA014425, 2006-2017), NIDA/NIMH/NIAAA (P20-DA 21131, 2001-2012), NCI MMHCC (U01CA105417), NCRR/BIRN (U24 RR021760)"])
metadata.append([])
trait_list = []
@@ -54,7 +54,7 @@ def export_search_results_csv(targs):
trait_ob = retrieve_trait_info(trait_ob, trait_ob.dataset, get_qtl_info=True)
trait_list.append(trait_ob)
- table_headers = ['Species', 'Group', 'Dataset', 'Record ID', 'Symbol', 'Description', 'ProbeTarget', 'PubMed_ID', 'Chr', 'Mb', 'Alias', 'Gene_ID', 'Homologene_ID', 'UniGene_ID', 'Strand_Probe', 'Probe_set_specificity', 'Probe_set_BLAT_score', 'Probe_set_BLAT_Mb_start', 'Probe_set_BLAT_Mb_end', 'QTL_Chr', 'QTL_Mb', 'Locus_at_Peak', 'Max_LRS', 'P_value_of_MAX', 'Mean_Expression']
+ table_headers = ['Index', 'URL', 'Species', 'Group', 'Dataset', 'Record ID', 'Symbol', 'Description', 'ProbeTarget', 'PubMed_ID', 'Chr', 'Mb', 'Alias', 'Gene_ID', 'Homologene_ID', 'UniGene_ID', 'Strand_Probe', 'Probe_set_specificity', 'Probe_set_BLAT_score', 'Probe_set_BLAT_Mb_start', 'Probe_set_BLAT_Mb_end', 'QTL_Chr', 'QTL_Mb', 'Locus_at_Peak', 'Max_LRS', 'P_value_of_MAX', 'Mean_Expression']
traits_by_group = sort_traits_by_group(trait_list)
@@ -77,7 +77,7 @@ def export_search_results_csv(targs):
csv_rows.append(full_headers)
- for trait in group_traits:
+ for i, trait in enumerate(group_traits):
if getattr(trait, "symbol", None):
trait_symbol = getattr(trait, "symbol")
elif getattr(trait, "abbreviation", None):
@@ -85,6 +85,8 @@ def export_search_results_csv(targs):
else:
trait_symbol = "N/A"
row_contents = [
+ i + 1,
+ "https://genenetwork.org/show_trait?trait_id=" + str(trait.name) + "&dataset=" + str(trait.dataset.name),
trait.dataset.group.species,
trait.dataset.group.name,
trait.dataset.name,
diff --git a/wqflask/wqflask/markdown_routes.py b/wqflask/wqflask/markdown_routes.py
index 3109a352..3b60bc96 100644
--- a/wqflask/wqflask/markdown_routes.py
+++ b/wqflask/wqflask/markdown_routes.py
@@ -4,6 +4,10 @@ Render pages from github, or if they are unavailable, look for it else where
"""
import requests
import markdown
+import os
+import sys
+
+from bs4 import BeautifulSoup
from flask import Blueprint
from flask import render_template
@@ -16,18 +20,25 @@ policies_blueprint = Blueprint("policies_blueprint", __name__)
facilities_blueprint = Blueprint("facilities_blueprint", __name__)
-def render_markdown(file_name):
+def render_markdown(file_name, is_remote_file=True):
"""Try to fetch the file name from Github and if that fails, try to
look for it inside the file system """
github_url = ("https://raw.githubusercontent.com/"
"genenetwork/gn-docs/master/")
+ if not is_remote_file:
+ text = ""
+ with open(file_name, "r", encoding="utf-8") as input_file:
+ text = input_file.read()
+ return markdown.markdown(text,
+ extensions=['tables'])
+
md_content = requests.get(f"{github_url}{file_name}")
+
if md_content.status_code == 200:
+ return markdown.markdown(md_content.content.decode("utf-8"),
+ extensions=['tables'])
- return markdown.markdown(md_content.content.decode("utf-8"), extensions=['tables'])
- # TODO: Add fallback on our git server by checking the mirror.
- # Content not available
return (f"\nContent for {file_name} not available. "
"Please check "
"(here to see where content exists)"
@@ -35,6 +46,14 @@ look for it inside the file system """
"Please reach out to the gn2 team to have a look at this")
+def get_file_from_python_search_path(pathname_suffix):
+ cands = [os.path.join(d, pathname_suffix) for d in sys.path]
+ try:
+ return list(filter(os.path.exists, cands))[0]
+ except IndexError:
+ return None
+
+
@glossary_blueprint.route('/')
def glossary():
return render_template(
@@ -51,7 +70,33 @@ def references():
@environments_blueprint.route("/")
def environments():
- return render_template("environment.html", rendered_markdown=render_markdown("general/environments/environments.md")), 200
+
+ md_file = get_file_from_python_search_path("wqflask/DEPENDENCIES.md")
+ svg_file = get_file_from_python_search_path(
+ "wqflask/dependency-graph.html")
+ svg_data = None
+ if svg_file:
+ with open(svg_file, 'r') as f:
+ svg_data = "".join(
+ BeautifulSoup(f.read(),
+ 'lxml').body.script.contents)
+
+ if md_file is not None:
+ return (
+ render_template("environment.html",
+ svg_data=svg_data,
+ rendered_markdown=render_markdown(
+ md_file,
+ is_remote_file=False)),
+ 200
+ )
+ # Fallback: Fetch file from server
+ return (render_template(
+ "environment.html",
+ svg_data=None,
+ rendered_markdown=render_markdown(
+ "general/environments/environments.md")),
+ 200)
@links_blueprint.route("/")
diff --git a/wqflask/wqflask/static/new/css/markdown.css b/wqflask/wqflask/static/new/css/markdown.css
index dca3e31d..38d664e2 100644
--- a/wqflask/wqflask/static/new/css/markdown.css
+++ b/wqflask/wqflask/static/new/css/markdown.css
@@ -57,8 +57,47 @@
word-spacing: 0.2em;
}
+.graph-legend h1 {
+ text-align: center;
+}
+
+.graph-legend,
+#guix-graph {
+ width: 90%;
+ margin: 10px auto;
+}
+
+#guix-graph {
+ border: solid 2px black;
+}
+
+#markdown table {
+ width: 100%;
+}
+
+#markdown td {
+ padding: 1em;
+ text-align: left;
+}
+
+#markdown th {
+ text-align: center;
+}
+
+#markdown table,
+#markdown td,
+#markdown th {
+ border: solid 2px black;
+}
+
+#markdown td,
+#markdown th {
+ padding-top: 8px;
+ padding-bottom: 8px;
+}
+
@media(max-width:650px) {
.container {
width: 100vw;
}
-} \ No newline at end of file
+}
diff --git a/wqflask/wqflask/static/new/javascript/lodheatmap.js b/wqflask/wqflask/static/new/javascript/lodheatmap.js
index 965a1d53..b82c95ad 100644
--- a/wqflask/wqflask/static/new/javascript/lodheatmap.js
+++ b/wqflask/wqflask/static/new/javascript/lodheatmap.js
@@ -44,7 +44,9 @@ lodheatmap = function() {
_ref = data.chrnames;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
chr = _ref[_i];
- xLR[chr[0]] = getLeftRight(data.posByChr[chr[0]]);
+ if (data.posByChr[chr[0]].length > 0){
+ xLR[chr[0]] = getLeftRight(data.posByChr[chr[0]]);
+ }
}
zmin = 0;
zmax = 0;
@@ -144,7 +146,7 @@ lodheatmap = function() {
}).attr("stroke", "none").attr("stroke-width", "1").on("mouseover.paneltip", function(d) {
yaxis.select("text#yaxis" + d.lodindex).attr("opacity", 1);
d3.select(this).attr("stroke", "black");
- return celltip.show(d);
+ return celltip.show(d, this);
}).on("mouseout.paneltip", function(d) {
yaxis.select("text#yaxis" + d.lodindex).attr("opacity", 0);
d3.select(this).attr("stroke", "none");
diff --git a/wqflask/wqflask/static/new/javascript/panelutil.js b/wqflask/wqflask/static/new/javascript/panelutil.js
index 3c715c81..ea55a7cf 100644
--- a/wqflask/wqflask/static/new/javascript/panelutil.js
+++ b/wqflask/wqflask/static/new/javascript/panelutil.js
@@ -159,7 +159,6 @@ chrscales = function(data, width, chrGap, leftMargin, pad4heatmap, mappingScale)
if (mappingScale == "morgan") {
max_pos = d3.max(data.posByChr[chr[0]])
- console.log("max_pos:", max_pos)
data.xscale[chr[0]] = d3.scale.linear().domain([chrStart[i], max_pos]).range([data.chrStart[i], data.chrEnd[i]]);
}
else {
diff --git a/wqflask/wqflask/static/new/javascript/search_results.js b/wqflask/wqflask/static/new/javascript/search_results.js
index 86660126..9ffef4f8 100644
--- a/wqflask/wqflask/static/new/javascript/search_results.js
+++ b/wqflask/wqflask/static/new/javascript/search_results.js
@@ -1,42 +1,87 @@
+change_buttons = function() {
+ var button, buttons, item, num_checked, text, _i, _j, _k, _l, _len, _len2, _len3, _len4, _results, _results2;
+ buttons = ["#add", "#remove"];
+
+ num_checked = 0
+ table_api = $('#trait_table').DataTable();
+ check_cells = table_api.column(0).nodes().to$();
+ for (let i = 0; i < check_cells.length; i++) {
+ if (check_cells[i].childNodes[0].checked){
+ num_checked += 1
+ }
+ }
+
+ if (num_checked === 0) {
+ for (_i = 0, _len = buttons.length; _i < _len; _i++) {
+ button = buttons[_i];
+ $(button).prop("disabled", true);
+ }
+ } else {
+ for (_j = 0, _len2 = buttons.length; _j < _len2; _j++) {
+ button = buttons[_j];
+ $(button).prop("disabled", false);
+ }
+ }
+};
+
$(function() {
- var add, change_buttons, checked_traits, deselect_all, invert, remove, removed_traits, select_all;
+ var add, checked_traits, deselect_all, invert, remove, removed_traits, select_all;
checked_traits = null;
select_all = function() {
- console.log("selected_all");
- $(".trait_checkbox").each(function() {
- $(this).prop('checked', true);
- if (!$(this).closest('tr').hasClass('selected')) {
- $(this).closest('tr').addClass('selected')
- }
- });
+ table_api = $('#trait_table').DataTable();
+
+ check_cells = table_api.column(0).nodes().to$();
+ for (let i = 0; i < check_cells.length; i++) {
+ check_cells[i].childNodes[0].checked = true;
+ }
+
+ check_rows = table_api.rows().nodes();
+ for (let i =0; i < check_rows.length; i++) {
+ check_rows[i].classList.add("selected");
+ }
+
+ change_buttons();
};
deselect_all = function() {
- $(".trait_checkbox").each(function() {
- $(this).prop('checked', false);
- if ($(this).closest('tr').hasClass('selected')) {
- $(this).closest('tr').removeClass('selected')
- }
- });
+ table_api = $('#trait_table').DataTable();
+
+ check_cells = table_api.column(0).nodes().to$();
+ for (let i = 0; i < check_cells.length; i++) {
+ check_cells[i].childNodes[0].checked = false;
+ }
+
+ check_rows = table_api.rows().nodes();
+ for (let i =0; i < check_rows.length; i++) {
+ check_rows[i].classList.remove("selected")
+ }
+
+ change_buttons();
};
invert = function() {
- $(".trait_checkbox").each(function() {
- if ($(this).prop('checked') == true) {
- $(this).prop('checked', false)
- }
- else {
- $(this).prop('checked', true)
- }
-
- if ($(this).closest('tr').hasClass('selected')) {
- $(this).closest('tr').removeClass('selected')
- }
- else {
- $(this).closest('tr').addClass('selected')
- }
- });
+ table_api = $('#trait_table').DataTable();
+
+ check_cells = table_api.column(0).nodes().to$();
+ for (let i = 0; i < check_cells.length; i++) {
+ if (check_cells[i].childNodes[0].checked){
+ check_cells[i].childNodes[0].checked = false;
+ } else {
+ check_cells[i].childNodes[0].checked = true;
+ }
+ }
+
+ check_rows = table_api.rows().nodes();
+ for (let i =0; i < check_rows.length; i++) {
+ if (check_rows[i].classList.contains("selected")){
+ check_rows[i].classList.remove("selected")
+ } else {
+ check_rows[i].classList.add("selected")
+ }
+ }
+
+ change_buttons();
};
$('#searchbox').keyup(function(){
@@ -77,22 +122,6 @@ $(function() {
change_buttons();
});
- $('.trait_checkbox:checkbox').change(function() {
- change_buttons()
-
- if ($(this).is(":checked")) {
- if (!$(this).closest('tr').hasClass('selected')) {
- $(this).closest('tr').addClass('selected')
- }
- }
- else {
- if ($(this).closest('tr').hasClass('selected')) {
- $(this).closest('tr').removeClass('selected')
- }
- }
-
- });
-
add_to_collection = function() {
var traits;
traits = $("#trait_table input:checked").map(function() {
@@ -117,25 +146,8 @@ $(function() {
};
removed_traits = function() {
- console.log('in removed_traits with checked_traits:', checked_traits);
return checked_traits.closest("tr").fadeOut();
};
- change_buttons = function() {
- var button, buttons, item, num_checked, text, _i, _j, _k, _l, _len, _len2, _len3, _len4, _results, _results2;
- buttons = ["#add", "#remove"];
- num_checked = $('.trait_checkbox:checked').length;
- if (num_checked === 0) {
- for (_i = 0, _len = buttons.length; _i < _len; _i++) {
- button = buttons[_i];
- $(button).prop("disabled", true);
- }
- } else {
- for (_j = 0, _len2 = buttons.length; _j < _len2; _j++) {
- button = buttons[_j];
- $(button).prop("disabled", false);
- }
- }
- };
submit_bnw = function() {
trait_data = submit_traits_to_export_or_bnw("trait_table", "submit_bnw")
@@ -157,18 +169,23 @@ $(function() {
});
table_dict['headers'] = headers;
- rows = [];
- trait_table.find('tbody tr').each(function (i, tr) {
- if (trait_table.find('input[name="searchResult"]:checked').length > 0) {
- if ($(this).find('input[name="searchResult"]').is(':checked')){
- rows.push($(this).find('input[name="searchResult"]:checked').val())
- }
- }
- else {
- rows.push($(this).find('input[name="searchResult"]').val())
+ selected_rows = [];
+ all_rows = []; //ZS: If no rows are checked, export all
+ table_api = $('#' + table_name).DataTable();
+ check_cells = table_api.column(0).nodes().to$();
+ for (let i = 0; i < check_cells.length; i++) {
+ this_node = check_cells[i].childNodes[0];
+ all_rows.push(this_node.value)
+ if (this_node.checked){
+ selected_rows.push(this_node.value)
}
- });
- table_dict['rows'] = rows;
+ }
+
+ if (selected_rows.length > 0){
+ table_dict['rows'] = selected_rows;
+ } else {
+ table_dict['rows'] = all_rows;
+ }
json_table_dict = JSON.stringify(table_dict);
$('input[name=export_data]').val(json_table_dict);
@@ -253,8 +270,6 @@ $(function() {
$("#add").click(add_to_collection);
$("#submit_bnw").click(submit_bnw);
$("#export_traits").click(export_traits);
- $('.trait_checkbox, .btn').click(change_buttons);
-
let naturalAsc = $.fn.dataTableExt.oSort["natural-ci-asc"]
let naturalDesc = $.fn.dataTableExt.oSort["natural-ci-desc"]
diff --git a/wqflask/wqflask/templates/collections/view.html b/wqflask/wqflask/templates/collections/view.html
index e37f8104..ccec495b 100644
--- a/wqflask/wqflask/templates/collections/view.html
+++ b/wqflask/wqflask/templates/collections/view.html
@@ -73,7 +73,7 @@
<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>
+ <button class="btn btn-success" id="add" type="button" disabled><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">
@@ -81,7 +81,7 @@
<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="remove" class="btn btn-danger" data-url="/collections/remove" type="button" disabled><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>
@@ -109,10 +109,7 @@
<tbody>
{% for this_trait in trait_obs %}
<TR id="trait:{{ this_trait.name }}:{{ this_trait.dataset.name }}">
- <TD align="center" style="padding: 0px;">
- <INPUT TYPE="checkbox" NAME="searchResult" class="checkbox trait_checkbox"
- VALUE="{{ data_hmac('{}:{}'.format(this_trait.name, this_trait.dataset.name)) }}">
- </TD>
+ <TD align="center" style="padding: 0px;"><INPUT TYPE="checkbox" NAME="searchResult" class="checkbox trait_checkbox" VALUE="{{ data_hmac('{}:{}'.format(this_trait.name, this_trait.dataset.name)) }}"></TD>
<TD data-export="{{ loop.index }}" align="right">{{ loop.index }}</TD>
<TD title="{{ this_trait.dataset.fullname }}" data-export="{{ this_trait.dataset.fullname }}">{{ this_trait.dataset.fullname }}</TD>
<TD data-export="{{ this_trait.name }}">
@@ -178,15 +175,21 @@
<script language="javascript" type="text/javascript">
$(document).ready( function () {
-
- $('#trait_table tr').click(function(event) {
- if (event.target.type !== 'checkbox') {
- $(':checkbox', this).trigger('click');
- }
- });
-
- console.time("Creating table");
$('#trait_table').dataTable( {
+ 'drawCallback': function( settings ) {
+ $('#trait_table tr').off().on("click", function(event) {
+ if (event.target.type !== 'checkbox' && event.target.tagName.toLowerCase() !== 'a') {
+ var obj =$(this).find('input');
+ obj.prop('checked', !obj.is(':checked'));
+ }
+ if ($(this).hasClass("selected")){
+ $(this).removeClass("selected")
+ } else {
+ $(this).addClass("selected")
+ }
+ change_buttons()
+ });
+ },
"columns": [
{
"orderDataType": "dom-checkbox",
@@ -220,7 +223,7 @@
"paging": false,
"orderClasses": true
} );
- console.timeEnd("Creating table");
+
submit_special = function(url) {
$("#collection_form").attr("action", url);
diff --git a/wqflask/wqflask/templates/correlation_page.html b/wqflask/wqflask/templates/correlation_page.html
index 6419b185..aa74abf5 100644
--- a/wqflask/wqflask/templates/correlation_page.html
+++ b/wqflask/wqflask/templates/correlation_page.html
@@ -75,6 +75,7 @@
<div>
<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-adjust"></span> Invert</button>
<button class="btn btn-success" id="add" type="button" disabled><span class="glyphicon glyphicon-plus-sign"></span> Add</button>
<input type="hidden" name="database_name" id="database_name" value="None">
<input type="hidden" name="export_data" id="export_data" value="">
@@ -256,41 +257,6 @@
{% endif %}
$(document).ready( function () {
-
- $('#trait_table tr').click(function(event) {
- if (event.target.type !== 'checkbox') {
- $(':checkbox', this).trigger('click');
- }
- });
-
- function change_buttons() {
- buttons = ["#add", "#remove"];
- num_checked = $('.trait_checkbox:checked').length;
- if (num_checked === 0) {
- for (_i = 0, _len = buttons.length; _i < _len; _i++) {
- button = buttons[_i];
- $(button).prop("disabled", true);
- }
- } else {
- for (_j = 0, _len2 = buttons.length; _j < _len2; _j++) {
- button = buttons[_j];
- $(button).prop("disabled", false);
- }
- }
- if ($(this).is(":checked")) {
- if (!$(this).closest('tr').hasClass('selected')) {
- $(this).closest('tr').addClass('selected')
- }
- }
- else {
- if ($(this).closest('tr').hasClass('selected')) {
- $(this).closest('tr').removeClass('selected')
- }
- }
- }
-
- console.time("Creating table");
-
table_conf = {
buttons: [
{
@@ -305,6 +271,20 @@
postfixButtons: [ 'colvisRestore' ]
}
],
+ 'drawCallback': function( settings ) {
+ $('#trait_table tr').off().on("click", function(event) {
+ if (event.target.type !== 'checkbox' && event.target.tagName.toLowerCase() !== 'a') {
+ var obj =$(this).find('input');
+ obj.prop('checked', !obj.is(':checked'));
+ }
+ if ($(this).hasClass("selected")){
+ $(this).removeClass("selected")
+ } else {
+ $(this).addClass("selected")
+ }
+ });
+ $('.trait_checkbox:checkbox').on("change", change_buttons);
+ },
"data": table_json,
"columns": [
{
@@ -557,7 +537,7 @@
"sDom": "itir",
"autoWidth": true,
"bSortClasses": false,
- "scrollY": "50vh",
+ "scrollY": "100vh",
"scroller": true,
"scrollCollapse": true
}
@@ -570,8 +550,6 @@
} );
} ).draw();
- console.timeEnd("Creating table");
-
$('.toggle-vis').on('click', function (e) {
e.preventDefault();
diff --git a/wqflask/wqflask/templates/environment.html b/wqflask/wqflask/templates/environment.html
index 94b31464..5fe01dad 100644
--- a/wqflask/wqflask/templates/environment.html
+++ b/wqflask/wqflask/templates/environment.html
@@ -8,33 +8,143 @@
{% block content %}
- <div class="github-btn-container">
- <div class="github-btn ">
- <a href="https://github.com/genenetwork/gn-docs">
- Edit Text
- <img src="/static/images/edit.png">
- </a>
- </div>
-</div>
<div id="markdown" class="container">
<div class="cls-table-style">{{ rendered_markdown|safe }} </div>
</div>
-<style type="text/css">
-table {
- width: 100%;
-}
-table, th, td {
- border: 1px solid black;
+{% if svg_data %}
+
+<div class="graph-legend">
+ <h1>Chord dependency Graph of Genenetwork2</h1>
+ Graph generated from <a href="http://git.genenetwork.org/guix-bioinformatics/guix-bioinformatics/src/branch/master/gn/packages/genenetwork.scm">genenetwork.scm</a>. You can zoom in and out within the bounding box.
+</div>
+
+<div id="guix-graph"></div>
+{% endif %}
+
+{% endblock %}
+
+{% block js %}
+
+{% if svg_data %}
+<script language="javascript" type="text/javascript" src="{{ url_for('js', filename='d3js/d3.min.js') }}"></script>
+<script type="text/javascript">
+ {{ svg_data|safe }}
+ // based on http://bl.ocks.org/mbostock/1046712 under GPLv3
+ // Adapted from: https://elephly.net/graph.html
+ var outerRadius = (nodeArray.length * 10) / 2,
+ innerRadius = outerRadius - 100,
+ width = outerRadius * 2,
+ height = outerRadius * 2,
+ colors = d3.scale.category20c(),
+ matrix = [];
+
+ function neighborsOf (node) {
+ return links.filter(function (e) {
+ return e.source === node;
+ }).map(function (e) {
+ return e.target;
+ });
+ }
+
+ function zoomed () {
+ zoomer.attr("transform",
+ "translate(" + d3.event.translate + ")" +
+ "scale(" + d3.event.scale + ")");
+ }
+
+ function fade (opacity, root) {
+ return function (g, i) {
+ root.selectAll("g path.chord")
+ .filter(function (d) {
+ return d.source.index != i && d.target.index != i;
+ })
+ .transition()
+ .style("opacity", opacity);
+ };
+ }
+
+ // Now that we have all nodes in an object we can replace each reference
+ // with the actual node object.
+ links.forEach(function (link) {
+ link.target = nodes[link.target];
+ link.source = nodes[link.source];
+ });
+
+ // Construct a square matrix for package dependencies
+ nodeArray.forEach(function (d, index, arr) {
+ var source = index,
+ row = matrix[source];
+ if (!row) {
+ row = matrix[source] = [];
+ for (var i = -1; ++i < arr.length;) row[i] = 0;
+ }
+ neighborsOf(d).forEach(function (d) { row[d.index]++; });
+ });
+
+ // chord layout
+ var chord = d3.layout.chord()
+ .padding(0.01)
+ .sortSubgroups(d3.descending)
+ .sortChords(d3.descending)
+ .matrix(matrix);
+
+ var arc = d3.svg.arc()
+ .innerRadius(innerRadius)
+ .outerRadius(innerRadius + 20);
+
+ var zoom = d3.behavior.zoom()
+ .scaleExtent([0.1, 10])
+ .on("zoom", zoomed);
+
+ var svg = d3.select("#guix-graph").append("svg")
+ .attr("width", "100%")
+ .attr("height", "100%")
+ .attr('viewBox','0 0 '+Math.min(width,height)+' '+Math.min(width,height))
+ .attr('preserveAspectRatio','xMinYMin')
+ .call(zoom);
+
+ var zoomer = svg.append("g");
+
+ var container = zoomer.append("g")
+ .attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");
+
+ // Group for arcs and labels
+ var g = container.selectAll(".group")
+ .data(chord.groups)
+ .enter().append("g")
+ .attr("class", "group")
+ .on("mouseout", fade(1, container))
+ .on("mouseover", fade(0.1, container));
+
+ // Draw one segment per package
+ g.append("path")
+ .style("fill", function (d) { return colors(d.index); })
+ .style("stroke", function (d) { return colors(d.index); })
+ .attr("d", arc);
-}
+ // Add circular labels
+ g.append("text")
+ .each(function (d) { d.angle = (d.startAngle + d.endAngle) / 2; })
+ .attr("dy", ".35em")
+ .attr("transform", function (d) {
+ return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")"
+ + "translate(" + (innerRadius + 26) + ")"
+ + (d.angle > Math.PI ? "rotate(180)" : "");
+ })
+ .style("text-anchor", function (d) { return d.angle > Math.PI ? "end" : null; })
+ .text(function (d) { return nodeArray[d.index].label; });
-td,th{
- padding-top:8px;
- padding-bottom: 8px;
- text-align: center;
-}
+ // Draw chords from source to target; color by source.
+ container.selectAll(".chord")
+ .data(chord.chords)
+ .enter().append("path")
+ .attr("class", "chord")
+ .style("stroke", function (d) { return d3.rgb(colors(d.source.index)).darker(); })
+ .style("fill", function (d) { return colors(d.source.index); })
+ .attr("d", d3.svg.chord().radius(innerRadius));
+</script>
+{% endif %}
-</style>
{% endblock %}
diff --git a/wqflask/wqflask/templates/search_result_page.html b/wqflask/wqflask/templates/search_result_page.html
index 2a8d6931..87c97c50 100644
--- a/wqflask/wqflask/templates/search_result_page.html
+++ b/wqflask/wqflask/templates/search_result_page.html
@@ -129,6 +129,7 @@
{% endif %}
<input type="hidden" name="export_data" id="export_data" value="">
<button class="btn btn-default" id="select_all" type="button"><span class="glyphicon glyphicon-ok"></span> Select</button>
+ <button class="btn btn-default" id="invert" type="button"><span class="glyphicon glyphicon-adjust"></span> Invert</button>
<button class="btn btn-success" id="add" type="button" disabled><span class="glyphicon glyphicon-plus-sign"></span> Add</button>
<button class="btn btn-default" id="export_traits">Download <span class="glyphicon glyphicon-download"></span></button>
<input type="text" id="searchbox" class="form-control" style="width: 200px; display: inline;" placeholder="Search This Table For ...">
@@ -203,42 +204,21 @@
}
});
- function change_buttons() {
- buttons = ["#add", "#remove"];
- num_checked = $('.trait_checkbox:checked').length;
- if (num_checked === 0) {
- for (_i = 0, _len = buttons.length; _i < _len; _i++) {
- button = buttons[_i];
- $(button).prop("disabled", true);
- }
- } else {
- for (_j = 0, _len2 = buttons.length; _j < _len2; _j++) {
- button = buttons[_j];
- $(button).prop("disabled", false);
- }
- }
- //});
- if ($(this).is(":checked")) {
- if (!$(this).closest('tr').hasClass('selected')) {
- $(this).closest('tr').addClass('selected')
- }
- }
- else {
- if ($(this).closest('tr').hasClass('selected')) {
- $(this).closest('tr').removeClass('selected')
- }
- }
- }
-
//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 = $('#trait_table').DataTable( {
'drawCallback': function( settings ) {
- $('#trait_table tr').click(function(event) {
- if (event.target.type !== 'checkbox' && event.target.tagName.toLowerCase() !== 'a') {
- $(':checkbox', this).trigger('click');
- }
- });
- $('.trait_checkbox:checkbox').on("change", change_buttons);
+ $('#trait_table tr').off().on("click", function(event) {
+ if (event.target.type !== 'checkbox' && event.target.tagName.toLowerCase() !== 'a') {
+ var obj =$(this).find('input');
+ obj.prop('checked', !obj.is(':checked'));
+ }
+ if ($(this).hasClass("selected")){
+ $(this).removeClass("selected")
+ } else {
+ $(this).addClass("selected")
+ }
+ change_buttons()
+ });
},
'createdRow': function ( row, data, index ) {
$('td', row).eq(0).attr("style", "text-align: center; padding: 0px 10px 2px 10px;");