Skip to content

Commit

Permalink
improved select-image pane
Browse files Browse the repository at this point in the history
  • Loading branch information
jacksonjacobs1 committed Feb 22, 2024
1 parent 166d0ad commit c9f2b40
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 93 deletions.
2 changes: 1 addition & 1 deletion histoqc/ui/HQC_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def run_cohort_finder():
pass


current_app.logger.info('running cohort finder')
current_app.logger.info('running CohortFinder...')
cf_args = Namespace()

# ---------------- default values ----------------
Expand Down
6 changes: 3 additions & 3 deletions histoqc/ui/static/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,8 @@ th {

#select-image-container {
order: 0;
height: 100%;
width: 30%;
height: 50vh;
width: 60%;
display: flex;
align-items: center;
justify-content: center;
Expand Down Expand Up @@ -250,7 +250,7 @@ th {

#select-candidate-container {
order: 1;
height: 100%;
height: 50vh;
width: 70%;
display: flex;
flex-wrap: wrap;
Expand Down
4 changes: 2 additions & 2 deletions histoqc/ui/static/js/cohortfinder.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function handleCohortFinderSubmit(event) {
data: params,
beforeSend: function () {
$('#cf-params-modal').modal('toggle');
initScatterPlotMessage("<h4>Running cohort finder with the following params...</h4>")
initScatterPlotMessage("<h4>Running CohortFinder with the following parameters...</h4>")
Object.keys(params).forEach((key) => {
appendScatterPlotMessage(`<b>${key}</b>: ${params[key]}`)
})
Expand Down Expand Up @@ -111,7 +111,7 @@ function handleCohortFinderResponse(data) {
};
});

console.log("received cohort finder results:")
console.log("received CohortFinder results:")
console.log(COHORT_FINDER_RESULTS)
renderScatterPlot(COHORT_FINDER_RESULTS);
}
Expand Down
5 changes: 4 additions & 1 deletion histoqc/ui/static/js/global_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,8 @@ var DEFAULT_IMAGE_EXTENSIONS = [
var SMALL_IMAGE_EXTENSIONS = [
"_thumb.png"
];

const SKIP_IMAGE_EXTENSIONS = [];
// Default image type
var DEFAULT_IMAGE_EXTENSION = "_thumb_small.png";
var DEFAULT_IMAGE_EXTENSION = "_thumb_small.png";
var DEFAULT_LARGE_IMAGE_EXTENSION = "_thumb.png";
2 changes: 1 addition & 1 deletion histoqc/ui/static/js/histoqc.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function renderComponents() {

var dataView = renderLines();
initializeImageView(dataView);
initScatterPlotMessage('Click "CohortFinder" to render scatter plot.');
initScatterPlotMessage('<h4>Click "CohortFinder" to compute and render the 2D embedding.<h4>');
initializeCF();
}
});
Expand Down
158 changes: 88 additions & 70 deletions histoqc/ui/static/js/image_init.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,30 @@
* initialize/update the image view, enter/exit selected stage & detailed stage for image view.
* last modified: 03/17/2018 14:24:00
* update log: Add id to image blocks. Add multi-select. Re-define the generate_img_block function.
*/
*/

function initializeImageView(dataView) {
var $div = $("#overview-gallery");
$div.empty();
var zoomSlider = d3.select("#zoom-range");
zoomSlider.property('value', 0.5);
zoomSlider.on("input", function() {

zoomSlider.on("input", function () {
const zoomValue = d3.select(this).property('value');
zoomImages(zoomValue);
});

const div = d3.select("#overview-gallery");
const zoomValue = d3.select("#zoom-range").property('value');

CURRENT_IMAGE_TYPE = DEFAULT_IMAGE_EXTENSIONS.indexOf(DEFAULT_IMAGE_EXTENSION);
SKIP_IMAGE_EXTENSIONS.push(CURRENT_IMAGE_TYPE);

const case_ids = getCaseidsFromDataView(dataView);
case_ids.forEach(function (case_id) {
// $div.append(
// generateImgBlock(case_id,
// "overview-image-block", ORIGINAL_CASE_LIST[case_id],
// CURRENT_IMAGE_TYPE, CURRENT_COMPARE_TYPE, ORIGINAL_CASE_LIST[case_id]
// )
// );
generateImgBlock(div, ORIGINAL_DATASET[case_id]["id"],
"overview-image-block", ORIGINAL_CASE_LIST[case_id],
CURRENT_IMAGE_TYPE, CURRENT_COMPARE_TYPE, ORIGINAL_CASE_LIST[case_id]
"overview-image-block", ORIGINAL_CASE_LIST[case_id],
CURRENT_IMAGE_TYPE, CURRENT_COMPARE_TYPE, ORIGINAL_CASE_LIST[case_id], zoomValue
);
});

Expand All @@ -43,7 +39,7 @@ function initializeImageView(dataView) {
// )
// );
// }

// IMAGE SELECT MODE FUNCTIONALITY

// $div.children("div").children("img").click(function(){
Expand All @@ -56,7 +52,7 @@ function initializeImageView(dataView) {
}


function updateImageView (dataView) {
function updateImageView(dataView) {
// TODO: rewrite update function.

updateImageViewHeight();
Expand All @@ -65,12 +61,13 @@ function updateImageView (dataView) {
$div.empty();

div = d3.select("#overview-gallery");

const zoomValue = d3.select("#zoom-range").property('value');
const case_ids = getCaseidsFromDataView(dataView);

case_ids.forEach(function (case_id) {
const imgBlock = generateImgBlock(div, ORIGINAL_DATASET[case_id]["id"],
"overview-image-block", ORIGINAL_CASE_LIST[case_id],
CURRENT_IMAGE_TYPE, CURRENT_COMPARE_TYPE, ORIGINAL_CASE_LIST[case_id]
CURRENT_IMAGE_TYPE, CURRENT_COMPARE_TYPE, ORIGINAL_CASE_LIST[case_id], zoomValue
);

imgBlock.on("mouseover", function () {
Expand All @@ -91,7 +88,7 @@ function updateImageView (dataView) {
// )
// );
// }

// $div.children("div").children("img").click(function(){
// src_list = this.src.split('/');
// enter_select_mode(src_list[src_list.length-2].replace("%20", " "));
Expand All @@ -101,68 +98,88 @@ function updateImageView (dataView) {
}


function updateImageViewHeight () {
function updateImageViewHeight() {
$("#image-view").outerHeight(
$(window).height() -
$("header").outerHeight(includeMargin=true) -
$("#table-view").outerHeight(includeMargin=true) -
$("#chart-view").outerHeight(includeMargin=true)
);
$(window).height() -
$("header").outerHeight(includeMargin = true) -
$("#table-view").outerHeight(includeMargin = true) -
$("#chart-view").outerHeight(includeMargin = true)
);
}


function enterSelectImageView (dir) {
function enterSelectImageView(dir, img_type) {
// $("#overview-gallery").css("display", "none");
// $("#img-select-button").css("display", "none");
// $("#exit-image-select-view-btn").css("display", "block");
$('#select-image-modal').modal('show');
$("#select-candidate-container > *").remove();
$("#select-image-container > *").remove();
$("#zoomable-svg > *").remove();
$("#select-image-view").css("display", "flex");

var $div = $("#select-image-container");
$div.append(
"<img id='exibit-img' src='" +
generateImgSrc(dir, CURRENT_IMAGE_TYPE, false) +
"' file_name='" + dir +
"' img_type='" + CURRENT_IMAGE_TYPE + "'/>"
);
$div.append("<div><span>" + dir + "</span></div>");
d3.select("#select-image-container").html("").style("height", "50vh");
d3.select('#select-image-modal-title').text("Selected Image: " + dir)
var imgSrc = generateImgSrc(dir, img_type, false);

var svg = d3.select("#select-image-container").append("svg").attr('width', '100%')
.attr('height', '100%');

svg.append('image')
.attr("id", "zoomable-image")
.attr('xlink:href', imgSrc) // Note: For modern browsers and the latest SVG spec, just 'href' might be sufficient
// .attr('href', imgSrc) // This is more compatible with the latest SVG specifications
.attr('file_name', dir) // Custom attributes like 'file_name' are not standard SVG attributes. Consider using data attributes or managing this data separately.
.attr('img_type', img_type) // Similarly, this should be handled as a data attribute if necessary.
.attr('width', '100%')
.attr('height', '100%');


enableZoomInSelectImageView(svg);
// $div = $("#select-candidate-container");
const div = d3.select("#select-candidate-container");
for (i = 0; i < DEFAULT_IMAGE_EXTENSIONS.length; i++) {
// if (SKIP_IMAGE_EXTENSIONS.indexOf(i) >= 0) {
// continue;
// }
// $div.append(
// generateImgBlock(dir,
// "candidate-image-block", dir,
// i, -1, DEFAULT_IMAGE_EXTENSIONS[i]
// )
// );
if (SKIP_IMAGE_EXTENSIONS.indexOf(i) >= 0) {
continue;
}
generateImgBlock(div, dir,
"candidate-image-block", dir,
i, -1, DEFAULT_IMAGE_EXTENSIONS[i]
"candidate-image-block", dir,
i, -1, DEFAULT_IMAGE_EXTENSIONS[i], 1.0
);
}

$("#select-candidate-container > div > img").dblclick(function(){
$("#select-candidate-container > div > img").dblclick(function () {
enterDetailImageView($(this).attr("file_name"), $(this).attr("img_type"), this.src);
});

$("#select-candidate-container > div > img").click(function(){
$("#exibit-img").attr("src", this.src)
.attr("img_type", $(this).attr("img_type"));
$("#select-candidate-container > div > img").click(function () {
$("#exhibit-img").attr("src", this.src)
.attr("img_type", $(this).attr("img_type"));
});

$("#exibit-img").click(function(){
enterDetailImageView($(this).attr("file_name"), $(this).attr("img_type"), this.src);
});
// $("#exhibit-img").click(function () {
// enterDetailImageView($(this).attr("file_name"), $(this).attr("img_type"), this.src);
// });
}

function enableZoomInSelectImageView(svg) {
// Create the zoom behavior
var zoom = d3.zoom()
.scaleExtent([1, 10]) // Limit zoom scale (min, max)
.on('zoom', zoomed);

// Function to handle zoom event, compatible with D3 v5
function zoomed() {
// Apply the zoom and pan transformation to the image within the SVG
svg.select('image').attr('transform', d3.event.transform);
}

// Apply the zoom behavior to the SVG container
svg.call(zoom);

}


function exitSelectImageView () {
function exitSelectImageView() {
$("#select-candidate-container > *").remove();
$("#select-image-container > *").remove();
$("#select-image-view").css("display", "none");
Expand All @@ -173,7 +190,7 @@ function exitSelectImageView () {
}


function updateMultiSelectedImageView (file_names) {
function updateMultiSelectedImageView(file_names) {
ORIGINAL_CASE_LIST.forEach(function (d) {
if (file_names.indexOf(d) == -1) {
$("#" + ORIGINAL_CASE_DICT[d]["dom_id"]).css("display", "none");
Expand All @@ -184,36 +201,37 @@ function updateMultiSelectedImageView (file_names) {
}


function calculateHeight ($div) {
function calculateHeight($div) {
var num_thumbs = DEFAULT_IMAGE_EXTENSIONS.length;
var max_width = Math.floor($div.width() / Math.ceil(num_thumbs / 2)) - 5;
var cor_height = Math.floor(max_width / $("#exibit-img").width() * $("#exibit-img").height());
var cor_height = Math.floor(max_width / $("#exhibit-img").width() * $("#exhibit-img").height());
var max_height = Math.floor($div.height() / 2) - 20;

return Math.min(max_height, cor_height);
}


function generateImgBlock (container, id, blk_class, file_name, img_type, compare_type, img_label) {
const zoomValue = d3.select("#zoom-range").property('value');
function generateImgBlock(container, id, blk_class, file_name, img_type, compare_type, img_label, zoomValue) {

const imgBlock = container.append("div")
.attr("id", id)
.attr("class", blk_class)
.style("zoom", zoomValue);


var imgTypeToShow = img_type;
if (img_type == DEFAULT_IMAGE_EXTENSIONS.indexOf(DEFAULT_IMAGE_EXTENSION)) { // No need to show the small image.
imgTypeToShow = DEFAULT_IMAGE_EXTENSIONS.indexOf(DEFAULT_LARGE_IMAGE_EXTENSION)
}
imgBlock.append("img")
.attr("src", generateImgSrc(
file_name, img_type, blk_class == "overview-image-block"
))
.attr("file_name", file_name)
.attr("img_type", img_type)
.attr("onerror", "this.style.display='none'")
.attr("onclick", "enterSelectImageView(\"" + file_name + "\")")
.attr("onclick", "enterSelectImageView('" + file_name + "', '" + imgTypeToShow + "')");



if (compare_type != -1) { // add on second image if we are in compare mode
imgBlock.append("img")
.attr("src", generateImgSrc(
Expand All @@ -231,7 +249,7 @@ function generateImgBlock (container, id, blk_class, file_name, img_type, compar
}


function generateImgSrc (file_name, img_type_index, use_small=false) {
function generateImgSrc(file_name, img_type_index, use_small = false) {
var image_extension = DEFAULT_IMAGE_EXTENSIONS[img_type_index];
// if (use_small && SMALL_IMAGE_EXTENSIONS.indexOf(image_extension) >= 0) {
// image_extension = image_extension.split(".")[0] + "_small.png";
Expand All @@ -242,7 +260,7 @@ function generateImgSrc (file_name, img_type_index, use_small=false) {
}


function enterDetailImageView (file_name, img_type, src) {
function enterDetailImageView(file_name, img_type, src) {
$("#detail-image-name > span").text(file_name);
$("#overlay-image > figure").css("width", "auto")
.css("background-image", "url(" + src + ")");
Expand All @@ -259,12 +277,12 @@ function enterDetailImageView (file_name, img_type, src) {
}


function initImageSelector (dataView) {
function initImageSelector(dataView) {

$img_selector = $("#img-select");
$cmp_selector = $("#comparison-select");

for (var index = 0; index < DEFAULT_IMAGE_EXTENSIONS.length; index ++) {
for (var index = 0; index < DEFAULT_IMAGE_EXTENSIONS.length; index++) {
// if (SKIP_IMAGE_EXTENSIONS.indexOf(index) >= 0) {
// continue;
// }
Expand Down Expand Up @@ -306,11 +324,11 @@ function initImageSelector (dataView) {

$("#overlay-image > figure > img").click(function () {
$("#overlay-container").css("pointer-events", "none")
.css("opacity", 0);
.css("opacity", 0);
});

function generateOptionHtml (value, key, selected = false) {

function generateOptionHtml(value, key, selected = false) {
if (selected) {
return "<option value='" + value + "' selected>" + key + "</option>";
} else {
Expand All @@ -333,10 +351,10 @@ function getCaseidsFromDataView(dataView) {

function setPageSize(dataView, n) {
dataView.setRefreshHints({
isFilterUnchanged: true
isFilterUnchanged: true
});
dataView.setPagingOptions({pageSize: n});
}
dataView.setPagingOptions({ pageSize: n });
}

function zoomImages(zoomValue) {
d3.selectAll(".overview-image-block").style("zoom", zoomValue);
Expand Down
Loading

0 comments on commit c9f2b40

Please sign in to comment.