diff --git a/UserInterface/css/index.css b/UserInterface/css/index.css index 098101d..394e059 100644 --- a/UserInterface/css/index.css +++ b/UserInterface/css/index.css @@ -64,7 +64,8 @@ th { margin-top: 15%; } -#upload-input { +#upload-input, +#cf-input { display: none; } @@ -297,7 +298,7 @@ th { } .selected-bar { - fill: orangered; + fill: var(--selected-color)!important; } .bar { @@ -305,7 +306,7 @@ th { } .bar:hover { - fill: orangered; + fill: orangered!important; } .y.axis path, @@ -532,7 +533,7 @@ table.dataTable { .selected-foreground-path { fill: none; - stroke: var(--selected-color); + stroke: var(--selected-color)!important; stroke-width: 2; opacity: 1; } @@ -585,7 +586,8 @@ table.dataTable { } .selected-dot { - fill: var(--selected-color); - stroke: #aaa; + fill: var(--selected-color)!important; + stroke: #ddd; + stroke-width: 0.4; fill-opacity: 1; } diff --git a/UserInterface/index.html b/UserInterface/index.html index 2c971fc..45137f1 100644 --- a/UserInterface/index.html +++ b/UserInterface/index.html @@ -41,21 +41,26 @@
HistoQc
- + +
diff --git a/UserInterface/scripts/bar_chart.js b/UserInterface/scripts/bar_chart.js index f5561a6..709ca4f 100644 --- a/UserInterface/scripts/bar_chart.js +++ b/UserInterface/scripts/bar_chart.js @@ -6,7 +6,10 @@ function init_bar_canvas () { .attr("width", $CHART.width()) .attr("height", $CHART.height()) .append("g") - .attr("transform", "translate(" + CHART_MARGIN.left + "," + CHART_MARGIN.top + ")"); + .attr( + "transform", + "translate(" + CHART_MARGIN.left + "," + CHART_MARGIN.top + ")" + ); } @@ -18,6 +21,7 @@ function init_bar_chart (dataset) { var data = ORIGINAL_DATASET.map(function (d) { return { case_name: d["filename"], + groupid: d["groupid"], attr_value: d[CURRENT_CHART_ATTRIBUTE] }; }); @@ -47,9 +51,11 @@ function init_bar_chart (dataset) { .attr('class', 'd3-tip') .offset([-10, 0]) .html(function (d) { - return "" + d.case_name + "" + - "
" + - "" + d.attr_value.toFixed(5) + ""; + return "" + + d.case_name + "" + + "
" + + "" + + d.attr_value.toFixed(5) + ""; }); svg.call(TIP); @@ -86,10 +92,16 @@ function init_bar_chart (dataset) { .data(data) .enter().append("rect") .attr("class", "background-bar") - .attr("x", function (d) { return xScale(d.case_name); }) + .attr("x", function (d) { + return xScale(d.case_name); + }) .attr("width", Math.max(xScale.rangeBand() - 1, 1)) - .attr("y", function (d) { return yScale(d.attr_value); }) - .attr("height", function (d) { return chart_height - yScale(d.attr_value); }); + .attr("y", function (d) { + return yScale(d.attr_value); + }) + .attr("height", function (d) { + return chart_height - yScale(d.attr_value); + }); // Add blue foreground bar for focus. foreground = svg.append("g") @@ -105,16 +117,22 @@ function init_bar_chart (dataset) { } }) .style("display", function (d) { - if (selected_cases.length == 0 || selected_cases.indexOf(d.case_name) != -1) { + if (selected_cases.indexOf(d.case_name) != -1) { return null; } else { return "none"; } }) - .attr("x", function (d) { return xScale(d.case_name); }) + .attr("x", function (d) { + return xScale(d.case_name); + }) .attr("width", Math.max(xScale.rangeBand() - 1, 1)) - .attr("y", function (d) { return yScale(d.attr_value); }) - .attr("height", function (d) { return chart_height - yScale(d.attr_value); }) + .attr("y", function (d) { + return yScale(d.attr_value); + }) + .attr("height", function (d) { + return chart_height - yScale(d.attr_value); + }) .on('mouseover', TIP.show) .on('mouseout', TIP.hide) .on('click', function (d) { @@ -146,6 +164,7 @@ function update_bar_chart (dataset) { var data = ORIGINAL_DATASET.map(function (d) { return { case_name: d["filename"], + groupid: d["groupid"], attr_value: d[CURRENT_CHART_ATTRIBUTE] }; }); @@ -201,18 +220,26 @@ function update_bar_chart (dataset) { .call(yAxis); // update bars - var background_bars = CHART_SVG.select("g.background-bar-group").selectAll("rect").data(data); + var background_bars = CHART_SVG.select("g.background-bar-group") + .selectAll("rect").data(data); background_bars.exit().remove(); background_bars.enter().append("rect"); background_bars.transition() .duration(500) .attr("class", "background-bar") - .attr("x", function (d) { return xScale(d.case_name); }) + .attr("x", function (d) { + return xScale(d.case_name); + }) .attr("width", Math.max(xScale.rangeBand() - 1, 1)) - .attr("y", function (d) { return yScale(d.attr_value); }) - .attr("height", function (d) { return chart_height - yScale(d.attr_value); }); + .attr("y", function (d) { + return yScale(d.attr_value); + }) + .attr("height", function (d) { + return chart_height - yScale(d.attr_value); + }); - var foreground_bars = CHART_SVG.select("g.foreground-bar-group").selectAll("rect").data(data); + var foreground_bars = CHART_SVG.select("g.foreground-bar-group"). + selectAll("rect").data(data); foreground_bars.exit().remove(); foreground_bars.enter().append("rect") .on('mouseover', TIP.show) @@ -234,16 +261,33 @@ function update_bar_chart (dataset) { } }) .style("display", function (d) { - if (selected_cases.length == 0 || selected_cases.indexOf(d.case_name) != -1) { + if (selected_cases.indexOf(d.case_name) != -1) { return null; } else { return "none"; } }) - .attr("x", function (d) { return xScale(d.case_name); }) + .style("fill", function (d) { + if (CURRENT_SELECTED === d.case_name) { + return "orangered"; + } else { + if (d["groupid"] === -1) { + return FOREGROUND_COLOR; + } else { + return COLOR_PLATE[d["groupid"]]; + } + } + }) + .attr("x", function (d) { + return xScale(d.case_name); + }) .attr("width", Math.max(xScale.rangeBand() - 1, 1)) - .attr("y", function (d) { return yScale(d.attr_value); }) - .attr("height", function (d) { return chart_height - yScale(d.attr_value); }); + .attr("y", function (d) { + return yScale(d.attr_value); + }) + .attr("height", function (d) { + return chart_height - yScale(d.attr_value); + }); } diff --git a/UserInterface/scripts/chart_init.js b/UserInterface/scripts/chart_init.js index a858556..896bbf9 100644 --- a/UserInterface/scripts/chart_init.js +++ b/UserInterface/scripts/chart_init.js @@ -1,12 +1,16 @@ function update_chart_width () { - $("#dimension-reduction-view").outerWidth($("#dimension-reduction-view").outerHeight()); - $("#original-feature-view").outerWidth($("#chart-view").width() - $("#dimension-reduction-view").outerWidth() - 10); + $("#dimension-reduction-view").outerWidth( + $("#dimension-reduction-view").outerHeight() + ); + $("#original-feature-view").outerWidth( + $("#chart-view").width() - + $("#dimension-reduction-view").outerWidth() - 10 + ); } function initialize_chart_view (dataset, vis_type="bar_chart") { - show_view("chart"); update_chart_width(); init_bar_canvas(); @@ -29,16 +33,17 @@ function update_chart_view (vis_type, dataset) { update_chart_width(); - // can be optimized by differentiate update type (just switch from chart to parallel coordiate?) + // can be optimized by differentiate update type + // (just switch from chart to parallel coordiate?) show_chosen_vis(vis_type); - if (vis_type == "bar_chart") { + if (vis_type === "bar_chart") { update_bar_chart(dataset); - } else if (vis_type == "parallel_coordinate") { + } else if (vis_type === "parallel_coordinate") { update_parallel_coordinate(dataset); - } else if (vis_type == "scatter_plot") { + } else if (vis_type === "scatter_plot") { update_scatter_plot(ORIGINAL_DATASET, dataset); - } else if (vis_type == "both") { + } else { update_bar_chart(dataset); update_parallel_coordinate(dataset); update_scatter_plot(ORIGINAL_DATASET, dataset); @@ -49,11 +54,6 @@ function update_chart_view (vis_type, dataset) { function enter_select_chart_view (case_name) { exit_select_chart_view(); - // DRPLT_SVG.select("g.foreground-dot-group") - // .selectAll("circle") - // .filter(function (d) {return d.case_name==case_name;}) - // .classed({"selected-dot": true, "foreground-dot": false}); - CHART_SVG.select("g.foreground-bar-group") .selectAll("rect") .filter(function (d) {return d.case_name==case_name;}) @@ -77,9 +77,6 @@ function exit_select_chart_view () { .selectAll(".selected-foreground-path") .classed({"selected-foreground-path": false, "foreground-path": true}); - // DRPLT_SVG.select("g.foreground-dot-group") - // .selectAll(".selected-dot") - // .classed({"selected-dot": false, "foreground-dot": true}); exit_select_scatter_plot(); } @@ -90,28 +87,19 @@ function update_multi_selected_chart_view (selected_cases) { .transition() .duration(500) .style("display", function (d) { - if (selected_cases.length == 0 || selected_cases.indexOf(d.case_name) != -1) { + if (selected_cases.indexOf(d.case_name) != -1) { return null; } else { return "none"; } }); - // DRPLT_SVG.select("g.foreground-dot-group") - // .selectAll("circle") - // .style("display", function (d) { - // if (selected_cases.length == 0 || selected_cases.indexOf(d.case_name) != -1) { - // return null; - // } else { - // return "none"; - // } - // }); enter_multi_select_scatter_plot(selected_cases); PARAC_SVG.select("g.foreground") .selectAll("path") .style("display", function (d) { - if (selected_cases.length == 0 || selected_cases.indexOf(d.case_name) != -1) { + if (selected_cases.indexOf(d.case_name) != -1) { return null; } else { return "none"; @@ -138,7 +126,7 @@ function init_chart_selector () { var sort_attribute = CURRENT_CHART_ATTRIBUTE; var sort_attribute_index = ORIGINAL_FEATURE_LIST.indexOf(sort_attribute); TABLE.order([sort_attribute_index, 'desc']).draw(); - data_sorting(sort_attribute, true); + sort_data(sort_attribute, true); update_views(); }) } diff --git a/UserInterface/scripts/data_load.js b/UserInterface/scripts/data_load.js index 19921f9..112e2ee 100644 --- a/UserInterface/scripts/data_load.js +++ b/UserInterface/scripts/data_load.js @@ -1,16 +1,9 @@ -/* Initiation model. - * read in dataset, initialize data dict, initialize selectors, initialize each views. - * last modified: 03/11/2018 23:22:00 - * update log: init header and comments. - */ - - -function data_loading () { +function load_raw_data () { var $this = $(this); var cur_file = null; - // escape the cancelation case + // escape the case when the user cancel the file selection pop-up if ($this.val() == "") { return; } else { @@ -20,9 +13,9 @@ function data_loading () { // hide the "Upload Dataset" button $("#upload-button").css("display", "none"); - // read dataset from the file - FILE_NAME = cur_file.name.split(".")[0]; - console.log("[LOG] Read in file: " + FILE_NAME); + // read dataset from the file ---------------------------------------------- + console.log("[LOG] Read in file: " + cur_file.name.split(".")[0]); + var fileReader = new FileReader(); fileReader.readAsText(cur_file); fileReader.onload = function () { @@ -30,15 +23,18 @@ function data_loading () { console.log("[LOG] App initializing..."); var file_text = fileReader.result; + // parse the file into header and dataset ------------------------------ + // parse necessary information from the header var absdirRe = /#outdir:?\s*([^\n]*)\n/; var abs_outdir = absdirRe.exec(file_text)[1]; var reldirRe = /([^\\\/]*)$/; var rel_outdir = reldirRe.exec(abs_outdir)[1]; DATA_PATH = DATA_PATH + rel_outdir + "/"; + // the header will be needed when saving result using the table view FILE_HEADER = file_text.split(/#dataset:\s?/)[0] + "#dataset: "; - dataset_text = file_text.split(/#dataset:\s?/)[1]; - // load dataset as list. + // load dataset as list + dataset_text = file_text.split(/#dataset:\s?/)[1]; ORIGINAL_DATASET = d3.tsv.parse(dataset_text, function (d) { if (d.hasOwnProperty("")) delete d[""]; for (var key in d) { @@ -46,95 +42,58 @@ function data_loading () { d[key] = +d[key]; } } + // add placeholder for cohortfinder results + if (!d.hasOwnProperty("embed_x")) d["embed_x"] = null; + if (!d.hasOwnProperty("embed_y")) d["embed_y"] = null; + // non-negative integers in cohortfinder results + if (!d.hasOwnProperty("groupid")) d["groupid"] = -1; + // 0 or 1 in cohortfinder results + if (!d.hasOwnProperty("testind")) d["testind"] = 2; + if (!d.hasOwnProperty("sitecol")) d["sitecol"] = "None"; + if (!d.hasOwnProperty("labelcol")) d["labelcol"] = "None"; return d; }); // show the current loaded dataset name - $("#dataset-tag").css("display", "inline") - .text("Current dataset: " + cur_file.name + " | Size: " + ORIGINAL_DATASET.length + " slides"); - - // build case list. - ORIGINAL_CASE_LIST = ORIGINAL_DATASET.map(function(d){return d["filename"];}); - - // build case dict with casename as key. + $("#dataset-tag") + .css("display", "inline") + .text("Current dataset: " + cur_file.name + " | Size: " + + ORIGINAL_DATASET.length + " slides"); + + // update all necessary global variables ------------------------------- + // build case list + ORIGINAL_CASE_LIST = ORIGINAL_DATASET.map(function (d) { + return d["filename"]; + }); + // build the lookup table (filename -> dom_id) for (var i = 0; i < ORIGINAL_DATASET.length; i ++) { var cur_file_name = ORIGINAL_DATASET[i]["filename"]; - ORIGINAL_CASE_DICT[cur_file_name] = {}; - for (var index in FEATURES_TO_MAP) { - ORIGINAL_CASE_DICT[cur_file_name][FEATURES_TO_MAP[index]] = ORIGINAL_DATASET[i][FEATURES_TO_MAP[index]]; - } - ORIGINAL_CASE_DICT[cur_file_name]["dom_id"] = cur_file_name.replace(/\W/g, "-"); + ORIGINAL_CASE_DICT[cur_file_name] = { + "dom_id": cur_file_name.replace(/\W/g, "-") + }; } - // build feature list ORIGINAL_FEATURE_LIST = Object.keys(ORIGINAL_DATASET[0]); - - CURRENT_MULTI_SELECTED = ORIGINAL_DATASET; + // update current selection PARA_COOR_SELECTED = ORIGINAL_CASE_LIST; - // UMAP_PROJ_SELECTED = ORIGINAL_CASE_LIST; - - CURRENT_PARALLEL_ATTRIBUTES = ORIGINAL_FEATURE_LIST.filter(function (d) { - if (typeof(ORIGINAL_DATASET[0][d]) == "number" && DEFAULT_PARAC_ATTRIBUTES.indexOf(d) != -1) { + CURRENT_PARALLEL_ATTRIBUTES = ORIGINAL_FEATURE_LIST.filter(function(d) { + // in DEFAULT_PARAC_ATTRIBUTES and is numeric + if (typeof(ORIGINAL_DATASET[0][d]) == "number" && + DEFAULT_PARAC_ATTRIBUTES.indexOf(d) != -1) { return true; } return false; }); - init_image_format_list(); - - var image_check_interval = setInterval (function () { - var check_sum = 0; - for (var ck_index = 0; ck_index < CHECK_IMAGE_EXTENSIONS.length; ck_index ++) { - check_sum += CHECK_IMAGE_EXTENSIONS[ck_index]; - } - if (check_sum == CHECK_IMAGE_EXTENSIONS.length) { - clearInterval (image_check_interval); - - // initialize table view - initialize_data_table(ORIGINAL_DATASET); - if (!OPEN_WITH_TABLE) { - hide_view("table"); - } - d3.select("#table-btn") - .classed("view-mngmt-btn-hidden", false) - .classed("view-enabled", OPEN_WITH_TABLE) - .classed("view-disabled", !OPEN_WITH_TABLE); - - // initialize chart view - initialize_chart_view(ORIGINAL_DATASET, CURRENT_VIS_TYPE); - if (!OPEN_WITH_CHART) { - hide_view("chart"); - } - d3.select("#chart-btn") - .classed("view-mngmt-btn-hidden", false) - .classed("view-enabled", OPEN_WITH_CHART) - .classed("view-disabled", !OPEN_WITH_CHART); - - // initialize image view - initialize_image_view(ORIGINAL_CASE_LIST); - if (!OPEN_WITH_IMAGE) { - hide_view("image"); - } - d3.select("#image-btn") - .classed("view-mngmt-btn-hidden", false) - .classed("view-enabled", OPEN_WITH_IMAGE) - .classed("view-disabled", !OPEN_WITH_IMAGE); - - $("#view-mngmt-btn-group").css("display", "block"); - d3.select("#page-title") - .classed("mr-md-auto", false) - .classed("mr-md-3", true); - - console.log("[LOG] App initialized."); - APP_INITIALIZED = true; - } else { - console.log("waiting for image type checking ..."); - } - }, 500); + // initiate the UI ----------------------------------------------------- + CURRENT_MULTI_SELECTED = ORIGINAL_DATASET; + CURRENT_CASE_LIST = ORIGINAL_CASE_LIST; + init_views(); } } -function data_sorting (keyword, desc=false) { + +function sort_data (keyword, desc=false) { var compare = function (a, b) { if (a[keyword] < b[keyword]) { if (desc) { @@ -155,28 +114,106 @@ function data_sorting (keyword, desc=false) { CURRENT_SORT_ATTRIBUTE = keyword; ORIGINAL_DATASET.sort(compare); - ORIGINAL_CASE_LIST = ORIGINAL_DATASET.map(function (d) {return d["filename"];}); + ORIGINAL_CASE_LIST = ORIGINAL_DATASET.map(function (d) { + return d["filename"]; + }); CURRENT_MULTI_SELECTED.sort(compare); - CURRENT_CASE_LIST = CURRENT_MULTI_SELECTED.map(function (d) {return d["filename"];}); + CURRENT_CASE_LIST = CURRENT_MULTI_SELECTED.map(function (d) { + return d["filename"]; + }); } -function init_image_format_list () { +function load_cohort_finder () { - var test_file = ORIGINAL_DATASET[0]["filename"]; - var test_out_dir = ORIGINAL_DATASET[0]["outdir"]; + var $this = $(this); + var cur_file = null; - for (var img_type_index = 0; img_type_index < DEFAULT_IMAGE_EXTENSIONS.length; img_type_index ++) { - var src = DATA_PATH + test_file + "/" + test_file + DEFAULT_IMAGE_EXTENSIONS[img_type_index]; - var img = new Image(); - img.typeidx = img_type_index; - img.onload = (function () { - CHECK_IMAGE_EXTENSIONS[this.typeidx] = true; - }); - img.onerror = (function () { - SKIP_IMAGE_EXTENSIONS.push(this.typeidx); - CHECK_IMAGE_EXTENSIONS[this.typeidx] = true; + // escape the case when the user cancel the file selection pop-up + if ($this.val() == "") { + return; + } else { + cur_file = $this.get(0).files[0]; + } + + // read dataset from the file ---------------------------------------------- + var file_reader = new FileReader(); + file_reader.readAsText(cur_file); + file_reader.onload = function () { + + var file_text = file_reader.result; + + // parse the file into header and dataset ------------------------------ + // parse necessary information from the header + var site_col_re = /#sitecol:?\s*([^\n]*)\n/; + var site_col = site_col_re.exec(file_text)[1]; + var label_col_re = /#labelcol:?\s*([^\n]*)\n/; + var label_col = label_col_re.exec(file_text)[1]; + var color_list_re = /#colorlist:?\s*([^\n]*)\n/; + COLOR_PLATE = color_list_re.exec(file_text)[1].split(","); + + // load dataset as list + dataset_text = file_text.split(/#dataset:\s?/)[1]; + var cf_dataset = d3.tsv.parse(dataset_text, function (d) { + var subset = { + "filename": d["filename"], + "embed_x": +d["embed_x"], + "embed_y": +d["embed_y"], + "groupid": +d["groupid"], + "testind": +d["testind"] + }; + + if (site_col.trim().toLowerCase() === "none") { + subset["sitecol"] = "None"; + } else { + subset["sitecol"] = d[site_col.trim()]; + } + + if (label_col.trim().toLowerCase() === "none") { + subset["labelcol"] = "None"; + } else { + subset["labelcol"] = d[label_col.trim()]; + } + + return subset; }); - img.src = src; + + // update all necessary global variables ------------------------------- + for (var i = 0; i < cf_dataset.length; i++) { + var cohort = cf_dataset[i]; + ORIGINAL_CASE_DICT[cohort["filename"]]["cohort"] = cohort; + } + + for (var i = 0; i < ORIGINAL_DATASET.length; i ++) { + var cur_fname = ORIGINAL_DATASET[i]["filename"]; + var cohort = ORIGINAL_CASE_DICT[cur_fname]["cohort"]; + ORIGINAL_DATASET[i]["embed_x"] = cohort["embed_x"]; + ORIGINAL_DATASET[i]["embed_y"] = cohort["embed_y"]; + ORIGINAL_DATASET[i]["groupid"] = cohort["groupid"]; + ORIGINAL_DATASET[i]["testind"] = cohort["testind"]; + ORIGINAL_DATASET[i]["sitecol"] = cohort["sitecol"]; + ORIGINAL_DATASET[i]["labelcol"] = cohort["labelcol"]; + } + + for (var i = 0; i < CURRENT_MULTI_SELECTED.length; i ++) { + var cur_fname = CURRENT_MULTI_SELECTED[i]["filename"]; + var cohort = ORIGINAL_CASE_DICT[cur_fname]["cohort"]; + CURRENT_MULTI_SELECTED[i]["embed_x"] = cohort["embed_x"]; + CURRENT_MULTI_SELECTED[i]["embed_y"] = cohort["embed_y"]; + CURRENT_MULTI_SELECTED[i]["groupid"] = cohort["groupid"]; + CURRENT_MULTI_SELECTED[i]["testind"] = cohort["testind"]; + CURRENT_MULTI_SELECTED[i]["sitecol"] = cohort["sitecol"]; + CURRENT_MULTI_SELECTED[i]["labelcol"] = cohort["labelcol"]; + } + + COHORT_LOADED = true; + + // update the UI ------------------------------------------------------- + update_chart_view("all", CURRENT_MULTI_SELECTED); + update_multi_selected_table_view(); + + // disable all dropdowns for scatter plot (the x and y is now given) + d3.select("#drplt-control-group") + .selectAll("button").classed("disabled", true); } } diff --git a/UserInterface/scripts/global_vars.js b/UserInterface/scripts/global_vars.js index 97c4142..54d46a3 100644 --- a/UserInterface/scripts/global_vars.js +++ b/UserInterface/scripts/global_vars.js @@ -15,14 +15,17 @@ var CURRENT_SELECTED = ""; var FEATURES_TO_MAP = ["outdir"]; // current sorting attribute var CURRENT_SORT_ATTRIBUTE; -// all possible views -var ORIGINAL_VIEWS = ["table", "chart", "image"]; // current showing views var CURRENT_DISPLAY_VIEWS = []; -var APP_INITIALIZED = false; +if (OPEN_WITH_TABLE) {CURRENT_DISPLAY_VIEWS.push("table");}; +if (OPEN_WITH_CHART) {CURRENT_DISPLAY_VIEWS.push("chart");}; +if (OPEN_WITH_IMAGE) {CURRENT_DISPLAY_VIEWS.push("image");}; +var INITIALIZED_VIEWS = []; + var FILE_NAME = ""; var FILE_HEADER = ""; +var COHORT_LOADED = false; /****************** TABLE VIEW ****************/ var TABLE; @@ -80,6 +83,8 @@ var DATA_TABLE_CONFIG = { var CURRENT_HIDDEN_COLUMNS = DEFAULT_HIDDEN_COLUMNS;; /****************** CHART VIEW ****************/ +var FOREGROUND_COLOR = "#007bff"; + var CURRENT_CHART_ATTRIBUTE = DEFAULT_CHART_ATTRIBUTE; var $CHART = $("#chart-svg-container"); // bar chart for single attribute var $PARAC = $("#parac-svg-container"); // parallel coordinate chart @@ -89,6 +94,7 @@ var CHART_SVG, PARAC_SVG, TIP; var PARA_COOR_SELECTED; var CURRENT_PARALLEL_ATTRIBUTES; +var COLOR_PLATE = []; /****************** IMAGE VIEW ****************/ var SKIP_IMAGE_EXTENSIONS = []; diff --git a/UserInterface/scripts/image_init.js b/UserInterface/scripts/image_init.js index ae5116f..e9e7ef7 100644 --- a/UserInterface/scripts/image_init.js +++ b/UserInterface/scripts/image_init.js @@ -7,17 +7,18 @@ function initialize_image_view (case_list) { - show_view("image"); - update_image_view_height(); - var $div = $("#overview-gallery"); $div.empty(); - CURRENT_CASE_LIST = ORIGINAL_CASE_LIST; CURRENT_IMAGE_TYPE = DEFAULT_IMAGE_EXTENSIONS.indexOf(DEFAULT_IMAGE_EXTENSION); for (var i = 0; i < case_list.length; i++) { - $div.append(generate_img_block("overview-image-block", case_list[i], CURRENT_IMAGE_TYPE, CURRENT_COMPARE_TYPE, case_list[i])); + $div.append( + generate_img_block( + "overview-image-block", case_list[i], + CURRENT_IMAGE_TYPE, CURRENT_COMPARE_TYPE, case_list[i] + ) + ); } $div.children("div").children("img").click(function(){ @@ -38,7 +39,12 @@ function update_image_view (case_list) { $div.empty(); for (var i = 0; i < ORIGINAL_CASE_LIST.length; i++) { - $div.append(generate_img_block("overview-image-block", ORIGINAL_CASE_LIST[i], CURRENT_IMAGE_TYPE, CURRENT_COMPARE_TYPE, ORIGINAL_CASE_LIST[i])); + $div.append( + generate_img_block( + "overview-image-block", ORIGINAL_CASE_LIST[i], + CURRENT_IMAGE_TYPE, CURRENT_COMPARE_TYPE, ORIGINAL_CASE_LIST[i] + ) + ); } $div.children("div").children("img").click(function(){ @@ -70,7 +76,12 @@ function enter_select_image_view (dir) { $("#select-image-view").css("display", "flex"); var $div = $("#select-image-container"); - $div.append(""); + $div.append( + "" + ); $div.append("
" + dir + "
"); $div = $("#select-candidate-container"); @@ -78,7 +89,12 @@ function enter_select_image_view (dir) { if (SKIP_IMAGE_EXTENSIONS.indexOf(i) >= 0) { continue; } - $div.append(generate_img_block("candidate-image-block", dir, i, -1, DEFAULT_IMAGE_EXTENSIONS[i])); + $div.append( + generate_img_block( + "candidate-image-block", dir, + i, -1, DEFAULT_IMAGE_EXTENSIONS[i] + ) + ); } $("#select-candidate-container > div > img").dblclick(function(){ @@ -129,10 +145,19 @@ function calculate_height ($div) { function generate_img_block (blk_class, file_name, img_type, compare_type, img_label) { - var img_block = "
" + - ""; + var img_block = "
" + + ""; if (compare_type != -1) { - img_block += ""; + img_block += ""; } img_block += "
" + img_label + "
"; return img_block; diff --git a/UserInterface/scripts/index.js b/UserInterface/scripts/index.js index 224c3d0..ca3e49c 100644 --- a/UserInterface/scripts/index.js +++ b/UserInterface/scripts/index.js @@ -1,14 +1,10 @@ -/* Index model. - * Link buttons with actions. Setup the response to the change of window size. - * last modified: 03/11/2018 23:22:00 - * update log: init header and comments. - */ - $(document).ready(function () { console.log("[LOG] Document ready.") - $("#upload-input").change(data_loading); // app entrance. func `data_loading` at data_load.js. - $("#reset-button").click(function(){window.location.reload(); console.log("App reset.")}); // app exit. back to the uploading page, reset to the init structure. + // app entrance. func `load_raw_data` at data_load.js. + $("#upload-input").change(load_raw_data); + // app exit. back to the uploading page, reset to the init structure. + $("#reset-button").click(function () {window.location.reload();}); $(".view-mngmt-btn").click(function(){ if ($(this).hasClass("view-enabled")) { hide_view($(this).attr("value")); @@ -16,10 +12,14 @@ $(document).ready(function () { show_view($(this).attr("value")); } }) + $("#cf-input").change(load_cohort_finder); - $(window).resize(function () { // additional listener for size-responsiblility of certain views + // listener for re-size of certain views + $(window).resize(function () { update_image_view_height(); - update_chart_view("both", CURRENT_MULTI_SELECTED); + if (INITIALIZED_VIEWS.indexOf("chart") >= 0) { + update_chart_view("all", CURRENT_MULTI_SELECTED); + } }); // detail view zoomability setup @@ -36,27 +36,9 @@ $(document).ready(function () { function reset_views_size () { - if (!APP_INITIALIZED) { - return; - } - - console.log(CURRENT_DISPLAY_VIEWS); - // reset background color - index = -1; - for (var i = 0; i < ORIGINAL_VIEWS.length; i++) { - var view_name = ORIGINAL_VIEWS[i]; - if (CURRENT_DISPLAY_VIEWS.indexOf(view_name) >= 0) { - index++; - if (index % 2 == 0) { - $("#" + view_name + "-view").addClass("bg-light"); - } else { - $("#" + view_name + "-view").removeClass("bg-light"); - } - } - } - // TODO: re-write this!!!!!! - // HARD CODE size assignment - var total_height = $(window).height() - $("header").outerHeight(includeMargin=true) + // TODO: HARD CODE size assignment + var total_height = $(window).height() - + $("header").outerHeight(includeMargin=true) if (CURRENT_DISPLAY_VIEWS.indexOf("table") >= 0) { if (CURRENT_DISPLAY_VIEWS.indexOf("chart") >= 0) { @@ -67,7 +49,10 @@ function reset_views_size () { } else { // table + chart $("#table-view").outerHeight(230); - $("#chart-view").outerHeight(total_height - $("#table-view").outerHeight(includeMargin=true)); + $("#chart-view").outerHeight( + total_height - + $("#table-view").outerHeight(includeMargin=true) + ); } } else { if (CURRENT_DISPLAY_VIEWS.indexOf("image") >= 0) { @@ -96,25 +81,54 @@ function reset_views_size () { // image $("#table-view").outerHeight(0); $("#chart-view").outerHeight(0); + } else { + // no view + $("#table-view").outerHeight(230); + $("#chart-view").outerHeight(330); } } } - update_chart_view("both", CURRENT_MULTI_SELECTED); update_image_view_height(); } -function show_view (view_name) { +function show_view (view_name, skip_reset=false) { $("#" + view_name + "-view").css("display", "block"); $("#" + view_name + "-btn") .addClass("view-enabled") .removeClass("view-disabled"); - var index = CURRENT_DISPLAY_VIEWS.indexOf(view_name); - if (index < 0) { + + if (CURRENT_DISPLAY_VIEWS.indexOf(view_name) < 0) { CURRENT_DISPLAY_VIEWS.push(view_name); } - reset_views_size(); + + if (!skip_reset) { + reset_views_size(); + if (INITIALIZED_VIEWS.indexOf("chart") >= 0) { + update_chart_view("all", CURRENT_MULTI_SELECTED); + } + } + + // if a view is displayed for the first time + if (INITIALIZED_VIEWS.indexOf(view_name) < 0) { + if (view_name === "table") { + initialize_data_table(CURRENT_MULTI_SELECTED); + } else if (view_name === "chart") { + initialize_chart_view(CURRENT_MULTI_SELECTED, CURRENT_VIS_TYPE); + } else if (view_name === "image") { + initialize_image_view(ORIGINAL_CASE_LIST); + update_multi_selected_image_view(CURRENT_CASE_LIST); + } else { + console.log("[ERROR] Unknown view name for initialization.") + } + + $("#" + view_name + "-btn").removeClass("view-mngmt-btn-hidden"); + + INITIALIZED_VIEWS.push(view_name); + } else { + } + } @@ -123,9 +137,86 @@ function hide_view (view_name) { $("#" + view_name + "-btn") .addClass("view-disabled") .removeClass("view-enabled"); + var index = CURRENT_DISPLAY_VIEWS.indexOf(view_name); if (index > -1) { CURRENT_DISPLAY_VIEWS.splice(index, 1); } + reset_views_size(); -} \ No newline at end of file + if (INITIALIZED_VIEWS.indexOf("chart") >= 0) { + update_chart_view("all", CURRENT_MULTI_SELECTED); + } +} + + +function init_views () { + + function init_image_format_list () { + var test_file = ORIGINAL_DATASET[0]["filename"]; + var test_out_dir = ORIGINAL_DATASET[0]["outdir"]; + + for (var idx = 0; idx < DEFAULT_IMAGE_EXTENSIONS.length; idx ++) { + var img = new Image(); + img.typeidx = idx; + img.onload = function () { + CHECK_IMAGE_EXTENSIONS[this.typeidx] = true; + }; + img.onerror = function () { + SKIP_IMAGE_EXTENSIONS.push(this.typeidx); + CHECK_IMAGE_EXTENSIONS[this.typeidx] = true; + }; + + var cur_ext = DEFAULT_IMAGE_EXTENSIONS[idx]; + img.src = DATA_PATH + test_file + "/" + test_file + cur_ext; + } + } + + // we need to firstly check which variants of the images are presented + init_image_format_list(); + + // since the above check relies on trying to load each image format, which + // will not pause the thread, we will need to manually set a pause here and + // only continue to initiate the views after the check loops through all the + // expected formats + var image_check_interval = setInterval (function () { + var check_sum = 0; + for (var idx = 0; idx < CHECK_IMAGE_EXTENSIONS.length; idx++) { + check_sum += CHECK_IMAGE_EXTENSIONS[idx]; + } + if (check_sum == CHECK_IMAGE_EXTENSIONS.length) { + clearInterval (image_check_interval); + + reset_views_size(); + for (var idx = 0; idx < CURRENT_DISPLAY_VIEWS.length; idx++) { + show_view(CURRENT_DISPLAY_VIEWS[idx], true); + } + + // display the view management button group + $("#view-mngmt-btn-group").css("display", "block"); + d3.select("#page-title") + .classed("mr-md-auto", false) + .classed("mr-md-3", true); + + // enable the cohort finder upload button + $("#cf-upload-button").removeClass("disabled"); + $("#cf-input").prop("disabled", false); + + console.log("[LOG] App initialized."); + APP_INITIALIZED = true; + } else { + console.log("waiting for image type checking ..."); + } + }, 500); +} + + +function update_views () { + if (INITIALIZED_VIEWS.indexOf("chart") >= 0) { + update_chart_view(CURRENT_VIS_TYPE, CURRENT_MULTI_SELECTED); + } + if (INITIALIZED_VIEWS.indexOf("image") >= 0) { + update_image_view(CURRENT_CASE_LIST); + } +} + diff --git a/UserInterface/scripts/parallel_chart.js b/UserInterface/scripts/parallel_chart.js index 104e5e4..f6f2212 100644 --- a/UserInterface/scripts/parallel_chart.js +++ b/UserInterface/scripts/parallel_chart.js @@ -6,7 +6,9 @@ function init_parallel_canvas () { .attr("width", $PARAC.width()) .attr("height", $PARAC.height()) .append("g") - .attr("transform", "translate(" + PARAC_MARGIN.left + "," + PARAC_MARGIN.top + ")"); + .attr("transform", + "translate(" + PARAC_MARGIN.left + "," + PARAC_MARGIN.top + ")" + ); } @@ -34,18 +36,24 @@ function init_parallel_coordinate (dataset) { foreground; var data = ORIGINAL_DATASET.map(function (d) { - attr_value_dict = {case_name: d["filename"]}; + attr_value_dict = { + case_name: d["filename"], + gid: d["groupid"] + }; for (var i = 0; i < CURRENT_PARALLEL_ATTRIBUTES.length; i++) { - attr_value_dict[CURRENT_PARALLEL_ATTRIBUTES[i]] = d[CURRENT_PARALLEL_ATTRIBUTES[i]]; + attr_value_dict[CURRENT_PARALLEL_ATTRIBUTES[i]] = + d[CURRENT_PARALLEL_ATTRIBUTES[i]]; } return attr_value_dict; }); var selected_cases = dataset.map(function (d) {return d["filename"];}); xScale.domain(dimensions = d3.keys(data[0]).filter(function (d) { - return d != "case_name" && (yScale[d] = d3.scale.linear() - .domain(d3.extent(data, function (p) { return p[d]; })) - .range([parac_height, 0])); + return d != "case_name" && d != "gid" && ( + yScale[d] = d3.scale.linear() + .domain(d3.extent(data, function (p) { return p[d]; })) + .range([parac_height, 0]) + ); })); // Add grey background lines for context. @@ -64,19 +72,30 @@ function init_parallel_coordinate (dataset) { .data(data) .enter().append("path") .attr("class", function (d) { - if (CURRENT_SELECTED == d.case_name) { + if (CURRENT_SELECTED === d.case_name) { return "selected-foreground-path"; } else { return "foreground-path"; } }) .style("display", function (d) { - if (selected_cases.length == 0 || selected_cases.indexOf(d.case_name) != -1) { + if (selected_cases.indexOf(d.case_name) != -1) { return null; } else { return "none"; } }) + .style("stroke", function (d) { + if (CURRENT_SELECTED === d.case_name) { + return "orangered"; + } else { + if (d["gid"] === -1) { + return FOREGROUND_COLOR; + } else { + return COLOR_PLATE[d["gid"]]; + } + } + }) .attr("d", path); // Add a group element for each dimension. @@ -84,38 +103,42 @@ function init_parallel_coordinate (dataset) { .data(dimensions) .enter().append("g") .attr("class", "dimension") - .attr("transform", function (d) { return "translate(" + xScale(d) + ")"; }) - .call(d3.behavior.drag() - .origin(function (d) { return {x: xScale(d)}; }) - .on("dragstart", function (d) { - dragging[d] = xScale(d); - background.attr("visibility", "hidden"); - // foreground.attr("visibility", "hidden"); - }) - .on("drag", function (d) { - dragging[d] = Math.min(parac_width, Math.max(0, d3.event.x)); - foreground.attr("d", path); - dimensions.sort(function (a, b) { return position(a) - position(b); }); - xScale.domain(dimensions); - g.attr("transform", function (d) { return "translate(" + position(d) + ")"; }) - }) - .on("dragend", function (d) { - delete dragging[d]; - transition(d3.select(this)).attr("transform", "translate(" + xScale(d) + ")"); - transition(foreground).attr("d", path); - background - .attr("d", path) - .transition() - .delay(500) - .duration(0) - .attr("visibility", null); - // foreground - // .attr("d", path) - // .transition() - // .delay(500) - // .duration(0) - // .attr("visibility", null); - })); + .attr("transform", function (d) { + return "translate(" + xScale(d) + ")"; + }) + .call( + d3.behavior.drag() + .origin(function (d) { return {x: xScale(d)}; }) + .on("dragstart", function (d) { + dragging[d] = xScale(d); + background.attr("visibility", "hidden"); + // foreground.attr("visibility", "hidden"); + }) + .on("drag", function (d) { + dragging[d] = Math.min(parac_width, Math.max(0,d3.event.x)); + foreground.attr("d", path); + dimensions.sort(function (a, b) { + return position(a) - position(b); + }); + xScale.domain(dimensions); + g.attr("transform", function (d) { + return "translate(" + position(d) + ")"; + }); + }) + .on("dragend", function (d) { + delete dragging[d]; + transition(d3.select(this)) + .attr("transform", "translate(" + xScale(d) + ")"); + transition(foreground) + .attr("d", path); + background + .attr("d", path) + .transition() + .delay(500) + .duration(0) + .attr("visibility", null); + }) + ); // Add an axis and title. g.append("g") @@ -134,16 +157,18 @@ function init_parallel_coordinate (dataset) { g.append("g") .attr("class", "brush") .each(function (d) { - d3.select(this).call(yScale[d].brush = d3.svg.brush().y(yScale[d]) - .on("brushstart", brushstart) - .on("brush", brush) - .on("brushend", brushend)); + d3.select(this).call( + yScale[d].brush = d3.svg.brush().y(yScale[d]) + .on("brushstart", brushstart) + .on("brush", brush) + .on("brushend", brushend)); }) .selectAll("rect") .attr("x", -8) .attr("width", 16); - // functions for parallel coordinate, ref: https://bl.ocks.org/jasondavies/1341281 + // functions for parallel coordinate, + // ref: https://bl.ocks.org/jasondavies/1341281 function position(d) { var v = dragging[d]; return v == null ? xScale(d) : v; @@ -155,7 +180,9 @@ function init_parallel_coordinate (dataset) { // Returns the path for a given data point. function path(d) { - return line(dimensions.map(function (p) { return [position(p), yScale[p](d[p])]; })); + return line(dimensions.map(function (p) { + return [position(p), yScale[p](d[p])]; + })); } function brushstart() { @@ -164,8 +191,12 @@ function init_parallel_coordinate (dataset) { // Handles a brush event, toggling the display of foreground lines. function brush() { - var actives = dimensions.filter(function (p) { return !yScale[p].brush.empty(); }), - extents = actives.map(function (p) { return yScale[p].brush.extent(); }); + var actives = dimensions.filter(function (p) { + return !yScale[p].brush.empty(); + }); + var extents = actives.map(function (p) { + return yScale[p].brush.extent(); + }); foreground.style("display", function (d) { return actives.every(function (p, i) { return extents[i][0] <= d[p] && d[p] <= extents[i][1]; @@ -174,8 +205,12 @@ function init_parallel_coordinate (dataset) { } function brushend() { - var actives = dimensions.filter(function (p) { return !yScale[p].brush.empty(); }), - extents = actives.map(function (p) { return yScale[p].brush.extent(); }); + var actives = dimensions.filter(function (p) { + return !yScale[p].brush.empty(); + }); + var extents = actives.map(function (p) { + return yScale[p].brush.extent(); + }); PARA_COOR_SELECTED = []; ORIGINAL_DATASET.forEach(function (d) { @@ -208,7 +243,7 @@ function update_parallel_coordinate (dataset) { } // update currently selected numeric attributes - init_parallel_coordinate (dataset); + init_parallel_coordinate(dataset); } @@ -238,7 +273,7 @@ function init_parallel_vars_selector() { function generate_option_html (key, value, selected = false) { if (selected) { - return ""; + return ""; } else { return ""; } diff --git a/UserInterface/scripts/scatter_chart.js b/UserInterface/scripts/scatter_chart.js index a12c008..815d74a 100644 --- a/UserInterface/scripts/scatter_chart.js +++ b/UserInterface/scripts/scatter_chart.js @@ -1,6 +1,7 @@ 'use strict'; -// WIP: this script is almost ready to be wrapped into an object oriented class +// WIP: this script is in the process of being wrapped into an object oriented +// class /* Global variables used in this view: * - DEFAULT_UMAP_ATTRIBUTES @@ -13,7 +14,7 @@ // class attributes var canvas_id; -var drplt_svg, drplt_width, drplt_height; +var drplt_svg, margin, drplt_width, drplt_height; var current_umap_attrs; var umap_selected; var lasso; @@ -21,6 +22,7 @@ var lasso; // constructor function scatter_plot_constructor (all_cases, canvas="#drplt-svg-container") { canvas_id = canvas; + margin = {top: 10, right: 10, bottom: 10, left: 10}; current_umap_attrs = DEFAULT_UMAP_ATTRIBUTES.filter(function (d) { if (typeof(all_cases[0][d]) == "number") { @@ -34,12 +36,13 @@ function scatter_plot_constructor (all_cases, canvas="#drplt-svg-container") { // public functions function init_scatter_plot (selected_cases, all_cases) { + console.log("scatter init func called."); + // temporarily call constructor in init function scatter_plot_constructor(all_cases); - var base_dom = $(canvas_id) + var base_dom = $(canvas_id); base_dom.empty(); - var margin = {top: 10, right: 10, bottom: 10, left: 10}; drplt_svg = d3.select(canvas_id).append("svg") .attr("id", "drplt-svg") .attr("width", base_dom.width()) @@ -52,8 +55,10 @@ function init_scatter_plot (selected_cases, all_cases) { base_dom.css("display", "block"); drplt_svg.selectAll("*").remove(); - var dot_background = drplt_svg.append("g").attr("class", "background-dot-group"); - var dot_foreground = drplt_svg.append("g").attr("class", "foreground-dot-group"); + var dot_background = drplt_svg.append("g") + .attr("class", "background-dot-group"); + var dot_foreground = drplt_svg.append("g") + .attr("class", "foreground-dot-group"); // Create the area where the lasso event can be triggered var lasso_area = dot_foreground.append("rect") @@ -76,6 +81,7 @@ function init_scatter_plot (selected_cases, all_cases) { dot_foreground.call(lasso); var data = calc_umap_embedding(all_cases); + console.log(data); var x_scale = d3.scale.linear() .range([0, drplt_width]) @@ -102,13 +108,58 @@ function init_scatter_plot (selected_cases, all_cases) { .attr("cx", function(d) { return x_scale(d.x_pos); }) .attr("cy", function(d) { return y_scale(d.y_pos); }); - enter_multi_select_scatter_plot(selected_cases.map(function (d) {return d["filename"];})); + // WIP: attempts to change marker for different testind value + // var marker = d3.svg.symbol().type(function(d) { + // if (d.testind === 1) { + // return "cross"; + // } else { + // return "circle"; + // } + // }).size(30); + // + // dot_background.selectAll("path.background-dot") + // .data(data) + // .enter().append("path") + // .attr("class", "background-dot") + // .attr("transform", function(d) { + // return "translate(" + x_scale(d.x_pos) +","+ y_scale(d.y_pos) + ")"; + // }) + // .attr("d", marker); + // + // dot_foreground.selectAll("path.foreground-dot-general") + // .data(data) + // .enter().append("path") + // .attr("id", function(d, i) {return "dot_" + i;}) // added + // .attr("class", get_foreground_dot_class) + // .attr("transform", function(d) { + // return "translate(" + x_scale(d.x_pos) +","+ y_scale(d.y_pos) + ")"; + // }) + // .attr("d", marker) + // .style("fill", function (d) { + // if (CURRENT_SELECTED === d.case_name) { + // return "orangered"; + // } else { + // if (d["groupid"] === -1) { + // return FOREGROUND_COLOR; + // } else { + // return COLOR_PLATE[d["groupid"]]; + // } + // } + // }); + + enter_multi_select_scatter_plot( + selected_cases.map(function (d) {return d["filename"];}) + ); lasso.items(dot_foreground.selectAll("circle")); init_scatter_vars_selector(all_cases, "#scatter-select"); } function update_scatter_plot (all_cases, selected_cases) { - var base_dom = $(canvas_id) + console.log("scatter update func called."); + + var base_dom = $(canvas_id); + drplt_width = base_dom.width() - margin.left - margin.right; + drplt_height = base_dom.height() - margin.top - margin.bottom; // update svg size base_dom.css("display", "block"); @@ -125,7 +176,9 @@ function update_scatter_plot (all_cases, selected_cases) { .attr("height", drplt_height); var data = calc_umap_embedding(all_cases); - var selected_casenames = selected_cases.map(function (d) {return d["filename"];}); + var selected_casenames = selected_cases.map(function (d) { + return d["filename"]; + }); var x_scale = d3.scale.linear() .range([0, drplt_width]) @@ -138,25 +191,63 @@ function update_scatter_plot (all_cases, selected_cases) { var background_circles = dot_background.selectAll("circle").data(data); background_circles.exit().remove(); background_circles.enter().append("circle"); - background_circles.transition() - .duration(500) + background_circles .attr("class", "background-dot") .attr("r", 3.5) .attr("cx", function(d) { return x_scale(d.x_pos); }) .attr("cy", function(d) { return y_scale(d.y_pos); }); - var foreground_circles = dot_foreground.selectAll("circle.foreground-dot-general").data(data); + var foreground_circles = dot_foreground + .selectAll("circle.foreground-dot-general").data(data); foreground_circles.exit().remove(); foreground_circles.enter().append("circle"); - foreground_circles.transition() - .duration(500) + foreground_circles .attr("id", function(d, i) {return "dot_" + i;}) .attr("class", get_foreground_dot_class) .attr("r", 3.5) .attr("cx", function(d) { return x_scale(d.x_pos); }) - .attr("cy", function(d) { return y_scale(d.y_pos); }); + .attr("cy", function(d) { return y_scale(d.y_pos); }) + .style("fill", function (d) { + if (d.testind != 1) { + return "none"; + } + + if (CURRENT_SELECTED === d.case_name) { + return "orangered"; + } else { + if (d["groupid"] === -1) { + return FOREGROUND_COLOR; + } else { + return COLOR_PLATE[d["groupid"]]; + } + } + }) + .style("stroke", function (d) { + if (d.testind === 1) { + return "#aaa"; + } + + if (CURRENT_SELECTED === d.case_name) { + return "orangered"; + } else { + if (d["groupid"] === -1) { + return FOREGROUND_COLOR; + } else { + return COLOR_PLATE[d["groupid"]]; + } + } + }) + .style("stroke-width", function (d) { + if (d.testind != 1) { + return 1; + } else { + return 0.4; + } + }); - enter_multi_select_scatter_plot(selected_cases.map(function (d) {return d["filename"];})); + enter_multi_select_scatter_plot( + selected_cases.map(function (d) {return d["filename"];}) + ); lasso.items(dot_foreground.selectAll("circle.foreground-dot-general")); } @@ -164,20 +255,28 @@ function enter_select_scatter_plot (case_name) { drplt_svg.select("g.foreground-dot-group") .selectAll("circle.foreground-dot-general") .filter(function (d) {return d.case_name==case_name;}) - .classed({"selected-dot": true, "foreground-dot": false, "foreground-dot-general": true}); + .classed({ + "selected-dot": true, + "foreground-dot": false, + "foreground-dot-general": true + }); } function exit_select_scatter_plot () { drplt_svg.select("g.foreground-dot-group") .selectAll(".selected-dot") - .classed({"selected-dot": false, "foreground-dot": true, "foreground-dot-general": true}); + .classed({ + "selected-dot": false, + "foreground-dot": true, + "foreground-dot-general": true + }); } function enter_multi_select_scatter_plot (selected_casenames) { drplt_svg.select("g.foreground-dot-group") .selectAll("circle.foreground-dot-general") .style("display", function (d) { - if (selected_casenames.length == 0 || selected_casenames.indexOf(d.case_name) != -1) { + if (selected_casenames.indexOf(d.case_name) != -1) { return null; } else { return "none"; @@ -187,50 +286,68 @@ function enter_multi_select_scatter_plot (selected_casenames) { // helper functions function calc_umap_embedding (cases) { - var pre_matrix = cases.map(function (d) { - var case_value = []; - for (var i = 0; i < current_umap_attrs.length; i++) { - case_value.push(d[current_umap_attrs[i]]); - } - return case_value; - }); + if (COHORT_LOADED) { + var data = cases.map(function (d, i) { + return { + case_name: d["filename"], + groupid: d["groupid"], + testind: d["testind"], + x_pos: d["embed_x"], + y_pos: d["embed_y"] + }; + }); - if (cases.length > 1) { - if ($("#dist-select").val() === "euclidean") { - console.log("Using Euclidean distance.") - var umap = new UMAP({ - nComponents: 2, - distanceFn: UMAP.euclidean, - nNeighbors: Math.min(cases.length - 1, UMAP_MAX_N_NEIGHBORS), - minDist: UMAP_MIN_DIST, - spread: UMAP_SPREAD - }); + return data; + } else { + var pre_matrix = cases.map(function (d) { + var case_value = []; + for (var i = 0; i < current_umap_attrs.length; i++) { + case_value.push(d[current_umap_attrs[i]]); + } + return case_value; + }); + + if (cases.length > 1) { + if ($("#dist-select").val() === "euclidean") { + console.log("Using Euclidean distance.") + var umap = new UMAP({ + nComponents: 2, + distanceFn: UMAP.euclidean, + nNeighbors: Math.min(cases.length-1, UMAP_MAX_N_NEIGHBORS), + minDist: UMAP_MIN_DIST, + spread: UMAP_SPREAD + }); + } else { + console.log("Using cosine distance.") + var umap = new UMAP({ + nComponents: 2, + distanceFn: UMAP.cosine, + nNeighbors: Math.min(cases.length-1, UMAP_MAX_N_NEIGHBORS), + minDist: UMAP_MIN_DIST, + spread: UMAP_SPREAD + }); + } + var embedding = umap.fit(pre_matrix); } else { - console.log("Using cosine distance.") - var umap = new UMAP({ - nComponents: 2, - distanceFn: UMAP.cosine, - nNeighbors: Math.min(cases.length - 1, UMAP_MAX_N_NEIGHBORS), - minDist: UMAP_MIN_DIST, - spread: UMAP_SPREAD - }); + var embedding = [[0, 0]]; } - var embedding = umap.fit(pre_matrix); - } else { - var embedding = [[0, 0]]; - } - var data = cases.map(function (d, i) { - return { - case_name: d["filename"], - x_pos: embedding[i][0], - y_pos: embedding[i][1] - }; - }); + var data = cases.map(function (d, i) { + return { + case_name: d["filename"], + groupid: d["groupid"], + testind: d["testind"], + x_pos: embedding[i][0], + y_pos: embedding[i][1] + }; + }); - return data; + return data; + } } -function init_scatter_vars_selector(all_cases, control_group_id="#scatter-select") { +function init_scatter_vars_selector( + all_cases, control_group_id="#scatter-select" +) { var $scatter_selector = $(control_group_id); $scatter_selector.empty(); @@ -264,7 +381,8 @@ function init_scatter_vars_selector(all_cases, control_group_id="#scatter-select function generate_option_html (key, value, selected = false) { if (selected) { - return ""; + return ""; } else { return ""; } @@ -308,7 +426,8 @@ var lasso_end = function() { if (pre_update_umap_selected != all_cases.length) { update_multi_selected(); } else { - lasso.items().style("display", null); // restore all of the foreground dots + // restore all of the foreground dots + lasso.items().style("display", null); } } else { diff --git a/UserInterface/scripts/select_mode.js b/UserInterface/scripts/select_mode.js index c2e50af..5b5f638 100644 --- a/UserInterface/scripts/select_mode.js +++ b/UserInterface/scripts/select_mode.js @@ -1,9 +1,15 @@ function enter_select_mode (file_name, istable=false) { CURRENT_SELECTED = file_name; - enter_select_image_view(CURRENT_SELECTED); - enter_select_chart_view(CURRENT_SELECTED); - select_row_in_table(CURRENT_SELECTED, istable); + if (INITIALIZED_VIEWS.indexOf("image") >= 0) { + enter_select_image_view(CURRENT_SELECTED); + } + if (INITIALIZED_VIEWS.indexOf("chart") >= 0) { + enter_select_chart_view(CURRENT_SELECTED); + } + if (INITIALIZED_VIEWS.indexOf("table") >= 0) { + select_row_in_table(CURRENT_SELECTED, istable); + } } @@ -15,16 +21,14 @@ function exit_select_mode () { CURRENT_SELECTED = ""; - exit_select_image_view(); - exit_select_chart_view(); - TABLE.rows('.selected').deselect(); + if (INITIALIZED_VIEWS.indexOf("image") >= 0) { + exit_select_image_view(); + } + if (INITIALIZED_VIEWS.indexOf("chart") >= 0) { + exit_select_chart_view(); + } + if (INITIALIZED_VIEWS.indexOf("table") >= 0) { + TABLE.rows('.selected').deselect(); + } } - -function update_views () { - update_chart_view(CURRENT_VIS_TYPE, CURRENT_MULTI_SELECTED); - update_image_view(CURRENT_CASE_LIST); -} - - - diff --git a/UserInterface/scripts/table_init.js b/UserInterface/scripts/table_init.js index 1ce6af5..fb8fa99 100644 --- a/UserInterface/scripts/table_init.js +++ b/UserInterface/scripts/table_init.js @@ -1,6 +1,5 @@ function initialize_data_table (dataset) { - show_view("table"); var $table = $("#result-table"); generate_table(dataset, $table); @@ -30,7 +29,7 @@ function initialize_data_table (dataset) { }); $(".dataTables_scrollHeadInner > table > thead > tr > th").on("click", function () { - data_sorting($(this).text(), (TABLE.order()[0][1] == 'desc')); + sort_data($(this).text(), (TABLE.order()[0][1] == 'desc')); update_views(); }); } @@ -73,9 +72,6 @@ function generate_config (dataset) { TABLE.column(column_name + ":name").visible(false); CURRENT_HIDDEN_COLUMNS.push(column_name); - - // update_chart_view("parallel_coordinate", CURRENT_MULTI_SELECTED); - // update_chart_view("scatter_plot", CURRENT_MULTI_SELECTED); } else { // update the table column @@ -88,9 +84,6 @@ function generate_config (dataset) { } else { console.log("[DEBUG] " + column_name + " is not in CURRENT_HIDDEN_COLUMNS.") } - - // update_chart_view("parallel_coordinate", CURRENT_MULTI_SELECTED); - // update_chart_view("scatter_plot", CURRENT_MULTI_SELECTED); } }; @@ -177,7 +170,9 @@ function select_row_in_table (case_name, from_table) { } -function update_multi_selected_table_view (case_names) { +function update_multi_selected_table_view () { TABLE.clear(); - TABLE.rows.add(CURRENT_MULTI_SELECTED.map(function(d) {return Object.values(d);})).draw(); + TABLE.rows.add( + CURRENT_MULTI_SELECTED.map(function (d) {return Object.values(d);}) + ).draw(); }