about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/heatmap-generation.org34
-rw-r--r--doc/images/gn2_header_collections.pngbin0 -> 7890 bytes
-rw-r--r--doc/images/heatmap_form.pngbin0 -> 9363 bytes
-rw-r--r--doc/images/heatmap_with_hover_tools.pngbin0 -> 42578 bytes
-rw-r--r--etc/default_settings.py1
-rw-r--r--wqflask/wqflask/collect.py7
-rw-r--r--wqflask/wqflask/templates/collections/view.html101
7 files changed, 140 insertions, 3 deletions
diff --git a/doc/heatmap-generation.org b/doc/heatmap-generation.org
new file mode 100644
index 00000000..a697c70b
--- /dev/null
+++ b/doc/heatmap-generation.org
@@ -0,0 +1,34 @@
+#+STARTUP: inlineimages
+#+TITLE: Heatmap Generation
+#+AUTHOR: Muriithi Frederick Muriuki
+
+* Generating Heatmaps
+
+Like a lot of other features, the heatmap generation requires an existing collection. If none exists, see [[][Creating a new collection]] for how to create a new collection.
+
+Once you have a collection, you can navigate to the collections page by clicking on the "Collections" link in the header
+
+
+[[./images/gn2_header_collections.png]]
+
+From that page, pick the collection that you want to work with by clicking on its name on the collections table.
+
+That takes you to that collection's page, where you can select the data that you want to use to generate the heatmap.
+
+** Selecting Orientation
+
+Once you have selected the data, select the orientation of the heatmap you want generated. You do this by selecting either *"vertical"* or *"horizontal"* in the heatmaps form:
+
+[[./images/heatmap_form.png]]
+
+Once you have selected the orientation, click on the "Generate Heatmap" button as in the image above.
+
+The heatmap generation might take a while, but once it is done, an image shows up above the data table.
+
+** Downloading the PNG copy of the Heatmap
+
+Once the heatmap image is shown, hovering over it, displays some tools to interact with the image.
+
+To download, hover over the heatmap image, and click on the "Download plot as png" icon as shown.
+
+[[./images/heatmap_with_hover_tools.png]]
diff --git a/doc/images/gn2_header_collections.png b/doc/images/gn2_header_collections.png
new file mode 100644
index 00000000..ac23f9c1
--- /dev/null
+++ b/doc/images/gn2_header_collections.png
Binary files differdiff --git a/doc/images/heatmap_form.png b/doc/images/heatmap_form.png
new file mode 100644
index 00000000..163fbb60
--- /dev/null
+++ b/doc/images/heatmap_form.png
Binary files differdiff --git a/doc/images/heatmap_with_hover_tools.png b/doc/images/heatmap_with_hover_tools.png
new file mode 100644
index 00000000..4ab79f99
--- /dev/null
+++ b/doc/images/heatmap_with_hover_tools.png
Binary files differdiff --git a/etc/default_settings.py b/etc/default_settings.py
index a194b10e..023aa53b 100644
--- a/etc/default_settings.py
+++ b/etc/default_settings.py
@@ -25,7 +25,6 @@ import os
 import sys
 
 GN_VERSION = open("../etc/VERSION", "r").read()
-GN_SERVER_URL = "http://localhost:8880/" # REST API server
 
 # ---- MySQL
 
diff --git a/wqflask/wqflask/collect.py b/wqflask/wqflask/collect.py
index 01274ba9..3475ae5d 100644
--- a/wqflask/wqflask/collect.py
+++ b/wqflask/wqflask/collect.py
@@ -12,6 +12,7 @@ from flask import flash
 from wqflask import app
 from utility import hmac
 from utility.formatting import numify
+from utility.tools import GN_SERVER_URL
 from utility.redis_tools import get_redis_conn
 
 from base.trait import create_trait
@@ -218,8 +219,10 @@ def view_collection():
 
         json_version.append(jsonable(trait_ob))
 
-    collection_info = dict(trait_obs=trait_obs,
-                           uc=uc)
+    collection_info = dict(
+        trait_obs=trait_obs,
+        uc=uc,
+        heatmap_data_url=f"{GN_SERVER_URL}api/heatmaps/clustered")
 
     if "json" in params:
         return json.dumps(json_version)
diff --git a/wqflask/wqflask/templates/collections/view.html b/wqflask/wqflask/templates/collections/view.html
index a3090bcf..0ded66a6 100644
--- a/wqflask/wqflask/templates/collections/view.html
+++ b/wqflask/wqflask/templates/collections/view.html
@@ -36,6 +36,28 @@
 
         <div>
             <br />
+	    <form id="heatmaps_form">
+	      <fieldset>
+		<legend>Heatmap Orientation</legend>
+		<label for="heatmap-orient-vertical">Vertical</label>
+		<input id="heatmap-orient-vertical"
+		       type="radio"
+		       name="vertical"
+		       value="true" />
+		<label for="heatmap-orient-horizontal">Horizontal</label>
+		<input id="heatmap-orient-horizontal"
+		       type="radio"
+		       name="vertical"
+		       value="false" />
+	      </fieldset>
+	      <button id="clustered-heatmap"
+		      class="btn btn-primary"
+		      data-url="{{heatmap_data_url}}"
+		      title="Generate heatmap from this collection">
+		Generate Heatmap
+	      </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>
@@ -52,6 +74,8 @@
                     <button id="delete" class="btn btn-danger submit_special" data-url="/collections/delete" type="button" title="Delete this collection" > Delete Collection</button>
                 </form>
             </div>
+	    <div id="clustered-heatmap-image-area">
+	    </div>
             <div style="margin-top: 10px; margin-bottom: 5px;">
                 <b>Show/Hide Columns:</b>
             </div>
@@ -139,6 +163,8 @@
     <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTablesExtensions/buttons/js/buttons.colVis.min.js') }}"></script>
     <script type="text/javascript" src="/static/new/javascript/search_results.js"></script>
 
+    <script type="text/javascript" src="{{ url_for('js', filename='plotly/plotly.min.js') }}"></script>
+
 
     <script language="javascript" type="text/javascript">
         $(document).ready( function () {
@@ -247,6 +273,81 @@
             $("#make_default").on("click", function(){
                 make_default();
             });
+
+	    $("#heatmaps_form").submit(function(e) {
+		e.preventDefault();
+	    });
+
+	    function clear_heatmap_area() {
+		area = document.getElementById("clustered-heatmap-image-area");
+		area.querySelectorAll("*").forEach(function(child) {
+		    child.remove();
+		});
+	    }
+
+	    function generate_progress_indicator() {
+		count = 0;
+		default_message = "Computing"
+		return function() {
+		    message = default_message;
+		    if(count >= 10) {
+			count = 0;
+		    }
+		    for(i = 0; i < count; i++) {
+			message = message + " .";
+		    }
+		    clear_heatmap_area();
+		    $("#clustered-heatmap-image-area").append(
+			'<div class="alert alert-info"' +
+			    ' style="font-weigh: bold; font-size: 150%;">' +
+			    message + '</div>');
+		    count = count + 1;
+		};
+	    }
+
+	    function display_clustered_heatmap(heatmap_data) {
+		clear_heatmap_area();
+		image_area = document.getElementById("clustered-heatmap-image-area")
+		Plotly.newPlot(image_area, heatmap_data)
+	    }
+
+	    function process_clustered_heatmap_error(xhr, status, error) {
+		clear_heatmap_area()
+		$("#clustered-heatmap-image-area").append(
+		    $(
+			'<div class="alert alert-danger">ERROR: ' +
+			    xhr.responseJSON.message +
+			    '</div>'));
+	    }
+
+	    $("#clustered-heatmap").on("click", function() {
+		clear_heatmap_area();
+		intv = window.setInterval(generate_progress_indicator(), 300);
+		vert_element = document.getElementById("heatmap-orient-vertical");
+		vert_true = vert_element == null ? false : vert_element.checked;
+		heatmap_url = $(this).attr("data-url")
+		traits = $(".trait_checkbox:checked").map(function() {
+		    return this.value
+		}).get();
+		$.ajax({
+		    type: "POST",
+		    url: heatmap_url,
+		    contentType: "application/json",
+		    data: JSON.stringify({
+			"traits_names": traits,
+			"vertical": vert_true
+		    }),
+		    dataType: "JSON",
+		    success: function(data, status, xhr) {
+			window.clearInterval(intv);
+			display_clustered_heatmap(data);
+		    },
+		    error: function(xhr, status, error) {
+			window.clearInterval(intv);
+			process_clustered_heatmap_error(xhr, status, error);
+		    }
+		});
+	    });
         });
     </script>