navigate annotations

This commit is contained in:
Ross
2021-12-04 16:06:55 +00:00
parent db46c153f0
commit 67591e92e6
+148 -135
View File
@@ -9,7 +9,7 @@ cornerstoneBase64ImageLoader.external.cornerstone = cornerstone;
cornerstoneWebImageLoader.external.cornerstone = cornerstone; cornerstoneWebImageLoader.external.cornerstone = cornerstone;
cornerstoneWADOImageLoader.external.cornerstone = cornerstone; cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
cornerstoneTools.init({keyboardEnabled: true}); cornerstoneTools.init({ keyboardEnabled: true });
let tool_state = {}; let tool_state = {};
@@ -314,7 +314,6 @@ export function loadCornerstone(main_element, db, images, annotations_to_load, l
</div> </div>
</div>`)); </div>`));
//console.log(cornerstone_element);
canvas_panel.append($(`<div id='dicom-log-panel'> canvas_panel.append($(`<div id='dicom-log-panel'>
<span id="dicom-log-close" class="close-button"><a href="#">close</a></span> <span id="dicom-log-close" class="close-button"><a href="#">close</a></span>
@@ -322,7 +321,7 @@ export function loadCornerstone(main_element, db, images, annotations_to_load, l
// Add generic settings menus to canvas-panel // Add generic settings menus to canvas-panel
$(".canvas-panel").append( $(".canvas-panel").append(
$(`<div id='dicom-settings-panel'> $(`<div id='dicom-settings-panel'>
<span id="dicom-settings-close" class="close-button"><a href="#">close</a></span> <span id="dicom-settings-close" class="close-button"><a href="#">close</a></span>
<span class="view-log-button"><a href="#">view log</a></span> <span class="view-log-button"><a href="#">view log</a></span>
<h3>Image viewer settings:</h3> <h3>Image viewer settings:</h3>
@@ -384,7 +383,7 @@ export function loadCornerstone(main_element, db, images, annotations_to_load, l
</div> </div>
</div>`) </div>`)
) )
.append($("<span id='dicom-toggle-mode-button' class='dicom-button' title='toggle stack/thumbnail view'>↻</span>")) .append($("<span id='dicom-toggle-mode-button' class='dicom-button' title='toggle stack/thumbnail view'>↻</span>"))
.append($("<span id='dicom-fullscreen-button' class='dicom-button' title='toggle stack/thumbnail view'>⛶</span>")) .append($("<span id='dicom-fullscreen-button' class='dicom-button' title='toggle stack/thumbnail view'>⛶</span>"))
.append($("<span id='dicom-settings-button' class='dicom-button' title='open settings'>&#9881;</span>")) .append($("<span id='dicom-settings-button' class='dicom-button' title='open settings'>&#9881;</span>"))
@@ -421,8 +420,6 @@ export function loadCornerstone(main_element, db, images, annotations_to_load, l
$("#dicom-window-panel button").each((n, el) => { $("#dicom-window-panel button").each((n, el) => {
$(el).click((e) => { $(el).click((e) => {
//console.log(e);
//console.log(e.target);
let button_id = e.target.id; let button_id = e.target.id;
let [ww, wc] = window_presets[button_id]; let [ww, wc] = window_presets[button_id];
@@ -458,6 +455,13 @@ export function loadCornerstone(main_element, db, images, annotations_to_load, l
$("#dicom-settings-panel").toggle(); $("#dicom-settings-panel").toggle();
}); });
$("#dicom-info-button").click(e => { $("#dicom-info-button").click(e => {
try {
// todo improve
dumpDataSet(cornerstone.getEnabledElement(element).image.data);
} catch {
console.log("unable to extract dicom data")
}
$("#dicom-summary-panel").toggle(); $("#dicom-summary-panel").toggle();
}); });
$("#dicom-fullscreen-button").click(e => { $("#dicom-fullscreen-button").click(e => {
@@ -501,7 +505,6 @@ export function loadCornerstone(main_element, db, images, annotations_to_load, l
images = [images]; images = [images];
} }
//console.log("Images", images)
//let annotations = []; //let annotations = [];
//if (annotations_to_load) { //if (annotations_to_load) {
@@ -514,11 +517,9 @@ export function loadCornerstone(main_element, db, images, annotations_to_load, l
if (!Array.isArray(annotations)) { if (!Array.isArray(annotations)) {
annotations = [annotations]; annotations = [annotations];
} }
//console.log("annon", annotations);
function loadAnnotation(imageId, annotation) { function loadAnnotation(imageId, annotation) {
//console.log("loadAnnotations", imageId, annotation);
const toolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager; const toolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager;
if (annotation == undefined || annotation.length < 1 || annotation == [undefined]) { if (annotation == undefined || annotation.length < 1 || annotation == [undefined]) {
@@ -533,7 +534,6 @@ export function loadCornerstone(main_element, db, images, annotations_to_load, l
} }
async function load(images, annotations) { async function load(images, annotations) {
console.log("LOAD", images);
let imageIds = []; let imageIds = [];
for (let i = 0; i < images.length; i++) { for (let i = 0; i < images.length; i++) {
let data_url = images[i]; let data_url = images[i];
@@ -597,12 +597,16 @@ export function loadCornerstone(main_element, db, images, annotations_to_load, l
imageIds imageIds
}; };
//cornerstone.loadAndCacheImage(imageIds[0]).then(function(image) { //cornerstone.loadAndCacheImage(imageIds[0]).then(function(image) {
//console.log("load and cache", imageIds[0])
cornerstone.loadAndCacheImage(imageIds[0]).then(function (image) { cornerstone.loadAndCacheImage(imageIds[0]).then(function (image) {
//console.log("LOAD and cache, then", image); //console.log("LOAD and cache, then", image);
loadCornerstoneMainImage(element, image, stack, db, load_as_stack); loadCornerstoneMainImage(element, image, stack, db, load_as_stack);
})
let load_annotation_image = true;
if (load_annotation_image) {
getNextAnnotationImage(element)
}
})
.catch((err, err2) => { .catch((err, err2) => {
console.log(err); console.log(err);
$("#dicom-log-panel").append("<br/>").append(err.stack); $("#dicom-log-panel").append("<br/>").append(err.stack);
@@ -646,7 +650,6 @@ export function loadCornerstone(main_element, db, images, annotations_to_load, l
let img; let img;
//console.log("load thumb", image_url);
if (image_url.startsWith("data")) { if (image_url.startsWith("data")) {
// based (image) data url, just load the image directly // based (image) data url, just load the image directly
@@ -674,7 +677,7 @@ export function loadCornerstone(main_element, db, images, annotations_to_load, l
); );
cornerstone.loadAndCacheImage(imageId).then(function (image) { cornerstone.loadAndCacheImage(imageId).then(function (image) {
loadCornerstoneThumb(image, id); loadCornerstoneThumb(image, id);
}); });
}); });
} }
} else { } else {
@@ -708,127 +711,123 @@ export function loadCornerstone(main_element, db, images, annotations_to_load, l
load(images, annotations); load(images, annotations);
console.log(main_element) main_element.keydown((evt) => { keyDownHandler(evt, element) });
main_element.keyup((evt) => { keyUpHandler(evt, element) });
main_element.keydown((evt) => { keyDownHandler(evt, element)});
main_element.keyup((evt) => { keyUpHandler(evt, element)});
} }
function keyUpHandler(e, element) { function keyUpHandler(e, element) {
console.log("Key up", e, e.key) if (e.key == "Control") {
if (e.key == "Control") { registerPrimaryDicomInterface(element);
registerPrimaryDicomInterface(element); window.control_pressed = false;
window.control_pressed = false; }
}
} }
function keyDownHandler(e, element) { function keyDownHandler(e, element) {
//// Ignore our custom keybindings if we are currently in a field that //// Ignore our custom keybindings if we are currently in a field that
//// accepts some kind of input //// accepts some kind of input
//if ($("*:focus:not(disabled)").is("textarea, input")) { //if ($("*:focus:not(disabled)").is("textarea, input")) {
// // unless a modifier key is pressed (not shift) // // unless a modifier key is pressed (not shift)
// if (e.altKey ? true : false || e.ctrlKey ? true : false) {} else { // if (e.altKey ? true : false || e.ctrlKey ? true : false) {} else {
// return; // return;
// } // }
//} //}
console.log("Key down", e, e.key)
if (e.key == "Control") { if (e.key == "Control") {
if (window.control_pressed != true) { if (window.control_pressed != true) {
window.control_pressed = true; window.control_pressed = true;
registerAltDicomInterface(e, element); registerAltDicomInterface(e, element);
}
} }
}
var charCode = typeof e.which == "number" ? e.which : e.keyCode; var charCode = typeof e.which == "number" ? e.which : e.keyCode;
function numberKeyPressed(e, x) { function numberKeyPressed(e, x) {
if (e.altKey ? true : false) { if (e.altKey ? true : false) {
selectThumb(x, element); loadStackIndex(x, element);
e.preventDefault(); e.preventDefault();
} else {} } else { }
} }
switch (charCode) { switch (charCode) {
case 13: // Return case 13: // Return
if (e.shiftKey ? true : false) { getNextAnnotationImage(element);
//$(".next-button:last").click(); if (e.shiftKey ? true : false) {
} else { //$(".next-button:last").click();
//$(".check-button:last").click(); } else {
} //$(".check-button:last").click();
break; }
case 32: // Space break;
if (e.shiftKey ? true : false) { case 32: // Space
//$(".previous-button:last").click(); if (e.shiftKey ? true : false) {
} else { //$(".previous-button:last").click();
//$(".next-button:last").click(); } else {
} //$(".next-button:last").click();
e.preventDefault(); // Needed to stop the default action (scroll) }
break; e.preventDefault(); // Needed to stop the default action (scroll)
case 46: // . break;
//toggleFlagged(); case 46: // .
break; //toggleFlagged();
break;
// Numbers 1-9 select the corresponding answer (if it exists) // Numbers 1-9 select the corresponding answer (if it exists)
// TODO: fix for multi question questions // TODO: fix for multi question questions
case 49: // 1 case 49: // 1
numberKeyPressed(e, 0); numberKeyPressed(e, 0);
break; break;
case 50: // 2 case 50: // 2
numberKeyPressed(e, 1); numberKeyPressed(e, 1);
break; break;
case 51: // 3 case 51: // 3
numberKeyPressed(e, 2); numberKeyPressed(e, 2);
break; break;
case 52: // 4 case 52: // 4
numberKeyPressed(e, 3); numberKeyPressed(e, 3);
break; break;
case 53: // 5 case 53: // 5
numberKeyPressed(e, 4); numberKeyPressed(e, 4);
break; break;
case 54: // 6 case 54: // 6
numberKeyPressed(e, 5); numberKeyPressed(e, 5);
break; break;
case 55: // 7 case 55: // 7
numberKeyPressed(e, 6); numberKeyPressed(e, 6);
break; break;
case 56: // 8 case 56: // 8
numberKeyPressed(e, 7); numberKeyPressed(e, 7);
break; break;
case 57: // 9 case 57: // 9
numberKeyPressed(e, 8); numberKeyPressed(e, 8);
break; break;
case 72: // H case 72: // H
previousQuestion(); previousQuestion();
break; break;
case 76: // L case 76: // L
//nextQuestion(); //nextQuestion();
break; break;
case 102: // f case 102: // f
//$("#filter-toggle").click(); //$("#filter-toggle").click();
break; break;
case 103: // g case 103: // g
//$("#options").slideDown("slow"); //$("#options").slideDown("slow");
//$("#goto-question-input").focus(); //$("#goto-question-input").focus();
//e.preventDefault(); //e.preventDefault();
break; break;
// Vim like scrolling (incredibly important) // Vim like scrolling (incredibly important)
case 106: // j case 106: // j
//window.scrollBy(0, 25); //window.scrollBy(0, 25);
break; break;
case 107: // k case 107: // k
//window.scrollBy(0, -25); //window.scrollBy(0, -25);
break; break;
} }
} }
function loadCornerstoneMainImage(element, image, stack, db, load_as_stack) { function loadCornerstoneMainImage(element, image, stack, db, load_as_stack) {
//dumpDataSet(image.data)
//console.log("loadCornerstoneMainImage")
//console.log("load as stack:", load_as_stack)
// It is probably silly to do this each time we load a question // It is probably silly to do this each time we load a question
const PanTool = cornerstoneTools.PanTool; const PanTool = cornerstoneTools.PanTool;
const ZoomTool = cornerstoneTools.ZoomTool; const ZoomTool = cornerstoneTools.ZoomTool;
@@ -843,7 +842,6 @@ function loadCornerstoneMainImage(element, image, stack, db, load_as_stack) {
const RectangleRoiTool = cornerstoneTools.RectangleRoiTool; const RectangleRoiTool = cornerstoneTools.RectangleRoiTool;
const LengthTool = cornerstoneTools.LengthTool; const LengthTool = cornerstoneTools.LengthTool;
//console.log("enable element", element);
cornerstone.enable(element); cornerstone.enable(element);
element.tabIndex = 0; element.tabIndex = 0;
@@ -869,8 +867,8 @@ function loadCornerstoneMainImage(element, image, stack, db, load_as_stack) {
cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, { cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, {
configuration: { configuration: {
getTextCallback: () => {}, getTextCallback: () => { },
changeTextCallback: () => {}, changeTextCallback: () => { },
allowEmptyLabel: true, allowEmptyLabel: true,
renderDashed: false, renderDashed: false,
drawHandles: false, drawHandles: false,
@@ -888,7 +886,8 @@ function loadCornerstoneMainImage(element, image, stack, db, load_as_stack) {
}, },
}); });
cornerstoneTools.setToolEnabledForElement(element, "ArrowAnnotate"); //cornerstoneTools.setToolEnabledForElement(element, "ArrowAnnotate");
//cornerstoneTools.setToolEnabledForElement(element, ArrowAnnotateTool);
let available_tools = [ let available_tools = [
@@ -922,7 +921,6 @@ function loadCornerstoneMainImage(element, image, stack, db, load_as_stack) {
$("#primary-mouse-binding .mouse-binding-select[data-button=4]").val("Zoom"); $("#primary-mouse-binding .mouse-binding-select[data-button=4]").val("Zoom");
//cornerstoneTools.setToolActive("Pan", { mouseButtonMask: 1 }); //cornerstoneTools.setToolActive("Pan", { mouseButtonMask: 1 });
//console.log(load_as_stack);
if (load_as_stack) { if (load_as_stack) {
cornerstoneTools.setToolActiveForElement(element, "StackScrollMouseWheel", { cornerstoneTools.setToolActiveForElement(element, "StackScrollMouseWheel", {
mouseButtonMask: 3 mouseButtonMask: 3
@@ -972,7 +970,7 @@ function loadCornerstoneMainImage(element, image, stack, db, load_as_stack) {
resizeHandler(element); resizeHandler(element);
window.addEventListener("resize", () => { resizeHandler(element)}); window.addEventListener("resize", () => { resizeHandler(element) });
element.addEventListener( element.addEventListener(
"contextmenu", "contextmenu",
function (e) { function (e) {
@@ -1027,14 +1025,6 @@ async function loadAltDicomInterface(db) {
// Called when the dicom image is loaded / rendered // Called when the dicom image is loaded / rendered
function onImageRendered(e) { function onImageRendered(e) {
const eventData = e.detail; const eventData = e.detail;
//console.log(e);
try {
// todo improve
dumpDataSet(eventData.image.data);
} catch {
console.log("unable to extract dicom data")
}
// Update ww/wl // Update ww/wl
$("#wc").text(Math.round(eventData.viewport.voi.windowCenter)); $("#wc").text(Math.round(eventData.viewport.voi.windowCenter));
@@ -1070,7 +1060,7 @@ function stopEvent(evt) {
function selectThumbClick(evt, element) { function selectThumbClick(evt, element) {
let new_index = evt.currentTarget.dataset.id; let new_index = evt.currentTarget.dataset.id;
selectThumb(new_index, element); loadStackIndex(new_index, element);
evt.preventDefault(); evt.preventDefault();
} }
@@ -1122,8 +1112,8 @@ function changeMouseBinding(evt, db, element) {
//db.mouse_bindings.put({button: button, mode: mode, tool: tool}).then(loadPrimaryDicomInterface()); //db.mouse_bindings.put({button: button, mode: mode, tool: tool}).then(loadPrimaryDicomInterface());
} }
export function selectThumb(new_index, dicom_element) { export function loadStackIndex(new_index, dicom_element) {
//console.log("select thumb new index", new_index); console.log("select new stack index", new_index);
// There must be a better way to do this... // There must be a better way to do this...
if (dicom_element == null) { if (dicom_element == null) {
return; return;
@@ -1183,4 +1173,27 @@ function dumpDataSet(dataSet) {
$(value).text(text); $(value).text(text);
}); });
}
export function getNextAnnotationImage(element) {
const enabled_element = cornerstone.getEnabledElement(element)
const image_ids = enabled_element.toolStateManager.toolState.stack.data[0].imageIds;
const current_image = enabled_element.toolStateManager.toolState.stack.data[0].currentImageIdIndex;
const annotated_images = Object.getOwnPropertyNames(cornerstoneTools.globalImageIdSpecificToolStateManager.toolState);
console.log("getNextAnnotationImage", image_ids, current_image, annotated_images);
if (annotated_images.length > 0) {
let offset = current_image;
for( let i=0; i < image_ids.length; i++) {
console.log("i", i)
let pointer = (i + offset) % image_ids.length;
console.log("pointer", pointer, image_ids[pointer]);
console.log(annotated_images);
if (annotated_images.includes(image_ids[pointer])) {
console.log("load")
loadStackIndex(pointer, element);
}
}
}
} }