From 8215466fbfce7c3c48dcde64f1d8093369c88a2c Mon Sep 17 00:00:00 2001 From: Aaron LI Date: Tue, 22 Nov 2016 20:43:25 +0800 Subject: webui: products: Implement HPX conversion function --- fg21sim/webui/handlers/products.py | 28 ++++++++++++++++++-- fg21sim/webui/static/js/console.js | 8 +++--- fg21sim/webui/static/js/products.js | 53 ++++++++++++++++++++++++++++--------- 3 files changed, 71 insertions(+), 18 deletions(-) (limited to 'fg21sim') diff --git a/fg21sim/webui/handlers/products.py b/fg21sim/webui/handlers/products.py index 5c9e0c8..f68fa5d 100644 --- a/fg21sim/webui/handlers/products.py +++ b/fg21sim/webui/handlers/products.py @@ -78,6 +78,7 @@ class ProductsAJAXHandler(BaseRequestHandler): request = json_decode(self.request.body) logger.debug("Received request: {0}".format(request)) action = request.get("action") + response = {"action": action} if action == "load": # Load the manifest from supplied file try: @@ -98,14 +99,22 @@ class ProductsAJAXHandler(BaseRequestHandler): success = self._reset_products() elif action == "convert": # Convert the product from HEALPix map to HPX image - raise NotImplementedError("TODO") + try: + comp_id = request["compID"] + freq_id = request["freqID"] + success, reason = self._convert_hpx(comp_id, freq_id) + data = self.products.get_product(comp_id, freq_id) + response["data"] = data + except KeyError: + success = False + reason = "'compID' or 'freqID' is missing" else: # ERROR: bad action success = False reason = "Bad request action: {0}".format(action) # if success: - response = {"action": action, "success": success} + response["success"] = success logger.debug("Response: {0}".format(response)) self.set_header("Content-Type", "application/json; charset=UTF-8") self.write(json_encode(response)) @@ -171,3 +180,18 @@ class ProductsAJAXHandler(BaseRequestHandler): except (ValueError, OSError) as e: error = str(e) return (success, error) + + def _convert_hpx(self, comp_id, freq_id): + """ + Convert the HEALPix map of the product to HPX projected FITS image. + + FIXME/TODO: make this non-blocking! + """ + success = False + error = None + try: + self.products.convert_hpx(comp_id, freq_id, clobber=True) + success = True + except IOError as e: + error = str(e) + return (success, error) diff --git a/fg21sim/webui/static/js/console.js b/fg21sim/webui/static/js/console.js index 71603ed..2bb9525 100644 --- a/fg21sim/webui/static/js/console.js +++ b/fg21sim/webui/static/js/console.js @@ -33,7 +33,7 @@ var updateTaskStatus = function (status) { $("#task-status").removeClass("label-success label-warning label-danger") .addClass("label-default"); $("#task-status .icon").removeClass("fa-check-circle fa-question-circle") - .removeClass("fa-spin fa-spinner") + .removeClass("fa-cog fa-spinner") .addClass("fa-coffee"); } else if (!running && finished) { @@ -41,7 +41,7 @@ var updateTaskStatus = function (status) { $("#task-status").removeClass("label-default label-warning label-danger") .addClass("label-success"); $("#task-status .icon").removeClass("fa-coffee fa-question-circle") - .removeClass("fa-spin fa-spinner") + .removeClass("fa-cog fa-spinner") .addClass("fa-check-circle"); } else if (running && !finished) { @@ -50,7 +50,7 @@ var updateTaskStatus = function (status) { .addClass("label-warning"); $("#task-status .icon").removeClass("fa-coffee fa-check-circle") .removeClass("fa-question-circle") - .addClass("fa-spin fa-spinner"); + .addClass("fa-cog fa-spinner"); } else { // Unknown status: ERROR ?? @@ -58,7 +58,7 @@ var updateTaskStatus = function (status) { $("#task-status").removeClass("label-default label-success label-warning") .addClass("label-danger"); $("#task-status .icon").removeClass("fa-coffee fa-check-circle") - .removeClass("fa-spin fa-spinner") + .removeClass("fa-cog fa-spinner") .addClass("fa-question-circle"); } console.log("Task status:", ts); diff --git a/fg21sim/webui/static/js/products.js b/fg21sim/webui/static/js/products.js index f2507bf..0b25eaa 100644 --- a/fg21sim/webui/static/js/products.js +++ b/fg21sim/webui/static/js/products.js @@ -44,7 +44,7 @@ var makeManifestTableCell = function (data, localhost) { cell.append($("").attr("title", "Show product information") .addClass("info btn btn-small fa fa-info-circle")); cell.append($("").attr("title", "Download HEALPix map") - .addClass("healpix btn btn-small fa fa-file")); + .addClass("healpix healpix-download btn btn-small fa fa-file")); if (data.hpx) { cell.data("hpx-image", true) .data("hpx-path", data.hpx.path) @@ -53,7 +53,9 @@ var makeManifestTableCell = function (data, localhost) { cell.append($("").attr("title", localhost ? "Open HPX FITS image" : "Download HPX FITS image") - .addClass("hpx btn btn-small fa fa-image")); + .addClass("hpx") + .addClass(localhost ? "hpx-open" : "hpx-download") + .addClass("btn btn-small fa fa-image")); } else { cell.data("hpx-image", false); cell.append($("").attr("title", "Generate HPX image") @@ -111,15 +113,15 @@ var loadManifestToTable = function (manifest, localhost) { /** * Update the content of one single cell in the manifest table + * + * @param {Object} cell - The table cell DOM/jQuery object */ -var updateManifestTableCell = function (compID, freqID, data) { - var tr = $("table#products-manifest").find("tr.frequency.freqid-" + freqID); - tr.find("td").each(function () { - if ($(this).data("compID") === compID) { - // Found the target table cell - $(this).html(makeManifestTableCell(data)); - } - }); +var updateManifestTableCell = function (cell, data) { + cell = $(cell); + var cell_new = makeManifestTableCell(data, cell.data("localhost")); + cell_new.data("compID", cell.data("compID")) + .data("freqID", cell.data("freqID")); + cell.replaceWith(cell_new); }; @@ -193,7 +195,7 @@ var getServerManifest = function (url) { * Reset the products manifest on both the server side and client side */ var resetManifest = function (url) { - $.postJSON(url, {action: "reset"}) + return $.postJSON(url, {action: "reset"}) .done(function () { resetManifestTable(); // Popup a modal notification @@ -220,7 +222,15 @@ var resetManifest = function (url) { * @param {Integer} freqID - Frequency ID */ var convertProductHPX = function (url, compID, freqID) { - ; + return $.postJSON(url, {action: "convert", compID: compID, freqID: freqID}) + .fail(function (jqxhr) { + var modalData = {}; + modalData.icon = "times-circle"; + modalData.contents = "Failed to convert the HEALPix map to HPX image!"; + modalData.code = jqxhr.status; + modalData.reason = jqxhr.statusText; + showModalProducts(modalData); + }); }; @@ -287,4 +297,23 @@ $(document).ready(function () { } showModalProducts(modalData); }); + + // Convert HEALPix map of a product to HPX projected FITS image. + $(document).on("click", "td.product > .hpx.hpx-convert", function () { + var cell = $(this).closest("td"); + var compID = cell.data("compID"); + var freqID = cell.data("freqID"); + // Replace the icon with a spinner when converting + $(this).removeClass("fa-image").addClass("fa-spinner fa-pulse") + .fadeTo("fast", 1.0).css({"font-size": "2em"}) + .attr("title", "Generating HPX image ..."); + convertProductHPX(ajax_url, compID, freqID) + .done(function (response) { + updateManifestTableCell(cell, response.data); + showModalProducts({ + icon: "check-circle", + contents: "Generated HPX projected FITS image." + }); + }); + }); }); -- cgit v1.2.2