diff --git a/css/main.css b/css/main.css index 8db139d..78c9e5d 100644 --- a/css/main.css +++ b/css/main.css @@ -497,6 +497,20 @@ td { box-shadow: 0 0 0 3px #4527A0; } +/* .short-option-answer { + width: 100%; + display: block; + border: 1px solid #4527A0; + margin: 0.8rem 1.6rem 1.6rem 1.6rem; + overflow: hidden; + resize: none; + padding: 0.4rem; +} + +.short-option-answer:focus { + box-shadow: 0 0 0 3px #4527A0; +} */ + img { display: block; padding: 0; @@ -1124,4 +1138,33 @@ h2:has(+ #exam-list:empty), h2:has(+ #packet-list:empty){ #exam-list:empty::after, #packet-list:empty::after{ content: "None available."; opacity: 30%; +} + +#viewer-title-bar { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 0.8rem 1.6rem; + background-color: gray; + color: white; +} + +.title-bar-button { + display: inline-flex; + flex-direction: column; + align-items: center; + border: none; + margin: 0 0 0 2px; + background-color: gray; + color: white; + border-left: 1px solid white; +} + +.viewer-icon { + margin: auto; +} + +.title-bar-button:hover { + background-color: darkgray; } \ No newline at end of file diff --git a/js/main.js b/js/main.js index b573cdc..f9cc97a 100644 --- a/js/main.js +++ b/js/main.js @@ -515,6 +515,15 @@ async function loadExamList(data) { }); // Sort different lists + $(".packet-list.short div") + .sort(function(a, b) { + return a.dataset.eid > b.dataset.eid ? + 1 : + a.dataset.eid < b.dataset.eid ? + -1 : + 0; + }) + .appendTo(".packet-list.short"); $(".packet-list.rapid div") .sort(function(a, b) { return a.dataset.eid > b.dataset.eid ? @@ -1040,6 +1049,8 @@ function setUpQuestions(load_previous) { if (!load_previous && exam_time == null) { if (question_type == "rapid") { exam_time = 35 * 60; + } else if (question_type == "short") { + exam_time = 120 * 60; } else if (question_type == "anatomy") { exam_time = 90 * 60; } else if (question_type == "long") { @@ -1291,6 +1302,138 @@ async function loadQuestion(n, section = 1, force_reload = false) { ap.empty(); switch (question_data.type) { + case "short": { + ap.append( + '
' + + display_n + + '.1Case normal/abnormal
' +
@@ -1646,7 +1789,7 @@ function updateQuestionListPanel(answer) {
answer.qidn
).addClass("question-saved-localdb");
- if (question_type == "rapid" && answer.qidn == "1") {
+ if ((question_type == "rapid" || question_type == "short") && answer.qidn == "1") {
if (answer.ans == "Abnormal") {
$(
"#question-list-item-" +
@@ -1795,6 +1938,12 @@ function createQuestionListPanel() {
appendQuestionListItem(n, "1");
appendQuestionListItem(n, "2").hide();
}
+ } else if (question_type == "short") {
+ // Loop through all questions and append list items
+ for (let n = 1; n < exam_details.number_of_questions + 1; n++) {
+ appendQuestionListItem(n, "1");
+ appendQuestionListItem(n, "2").hide();
+ }
} else if (question_type == "anatomy") {
for (let n = 1; n < exam_details.number_of_questions + 1; n++) {
appendQuestionListItem(n, "1");
@@ -2194,6 +2343,69 @@ function reviewQuestions() {
}
}
}
+ } else if (question_type == "short") {
+ // First check normal vs abnormal
+ if (question["normal"] == true) {
+ if (section_1_answer == "Normal") {
+ setReviewAnswer(
+ el,
+ "correct",
+ section_1_answer,
+ true,
+ question_answers
+ );
+ correct_count++;
+ questions_correct[qid] = true;
+ } else {
+ if (section_1_answer != "Not Answered") {
+ overcall_number++;
+ }
+ setReviewAnswer(
+ el,
+ "incorrect",
+ section_1_answer,
+ true,
+ question_answers
+ );
+ questions_correct[qid] = false;
+ }
+ } else {
+ if (answerInArray(question_answers, section_2_answer)) {
+ correct_count++;
+ setReviewAnswer(
+ el,
+ "correct",
+ section_2_answer,
+ false,
+ question_answers
+ );
+ questions_correct[qid] = true;
+ } else {
+ setReviewAnswer(
+ el,
+ "incorrect",
+ section_2_answer,
+ false,
+ question_answers
+ );
+ questions_correct[qid] = false;
+
+ if (section_1_answer == "Not Answered") {} else if (section_1_answer == "Normal") {
+ undercall_number++;
+ } else {
+ // Incorrect calls could be correct if
+ // the answer is not in the database
+ incorrectcall_number++;
+
+ el.append(
+ "[Mark correct]"
+ ).click(() => {
+ markCorrect(qid, section_2_answer, question_type);
+ reviewQuestions();
+ });
+ }
+ }
+ }
} else if (question_type == "anatomy") {
// Anatomy answers are either correct or incorrect
if (answerInArray(question_answers, section_1_answer)) {
@@ -2278,7 +2490,7 @@ function markAnswer(qid, current_question, n) {
$(".long-answer").attr("readonly", "true");
$(".long-answer").addClass("long-answer-marked");
- if (type == "rapid") {
+ if (type == "rapid" || type == "short") {
option = document.getElementById("rapid-option");
// If the current question is normal
if (current_question.normal == true) {
diff --git a/js/viewer.js b/js/viewer.js
index 1d6dd3e..1f3ac5a 100644
--- a/js/viewer.js
+++ b/js/viewer.js
@@ -11,6 +11,9 @@ export function loadMainImage(image, stack) {
const RotateTool = cornerstoneTools.RotateTool;
const StackScrollTool = cornerstoneTools.StackScrollTool;
const ArrowAnnotateTool = cornerstoneTools.ArrowAnnotateTool;
+ const LengthTool = cornerstoneTools.LengthTool;
+ const RectangleRoiTool = cornerstoneTools.RectangleRoiTool;
+ const EllipseRoiTool = cornerstoneTools.EllipseRoiTool;
const AngleTool = cornerstoneTools.AngleTool;
const CobbAngleTool = cornerstoneTools.CobbAngleTool;
const EraserTool = cornerstoneTools.EraserTool;
@@ -35,6 +38,9 @@ export function loadMainImage(image, stack) {
cornerstoneTools.addToolForElement(element, CobbAngleTool);
cornerstoneTools.addToolForElement(element, StackScrollTool);
cornerstoneTools.addToolForElement(element, EraserTool);
+ cornerstoneTools.addToolForElement(element, LengthTool);
+ cornerstoneTools.addToolForElement(element, RectangleRoiTool);
+ //cornerstoneTools.addToolForElement(element, EllipseRoiTool);
cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, {
configuration: {
@@ -58,15 +64,17 @@ export function loadMainImage(image, stack) {
setDicomCanvasNonFullscreen(element);
cornerstone.reset(element);
- element.scrollIntoView(false);
- // element.scrollTo(0);
+ let viewerTitleBar = document.getElementById("viewer-title-bar");
+ viewerTitleBar.scrollIntoView();
+ //element.scrollIntoView(false);
+ //element.scrollTo(0);
$(element).dblclick(function () {
if ($(".canvas-panel").length == 0) {
// already fullscreen (disable it)
disableFullscreen(this);
} else {
- $(".content-panel").append($(".canvas-panel"));
+ $(".content-panel").prepend($(".canvas-panel"));
$(".canvas-panel").toggleClass("canvas-panel canvas-panel-fullscreen");
$("#dicom-image").attr("height", "100%");
$("#dicom-image").height("100%");
@@ -78,28 +86,7 @@ export function loadMainImage(image, stack) {
element.removeEventListener("wheel", element.wheelEventHandler);
- // Add tool selector
- $(".canvas-panel").append(
- ''
- );
-
- $(".control-overlay")
+ $(".dicom-select-control")
.get(0)
.addEventListener("change", function () {
changeControlSelection();
@@ -117,7 +104,7 @@ function onImageRendered(e) {
const eventData = e.detail;
// Update ww/wl
- const sel = $(".control-overlay").get(0);
+ const sel = $(".dicom-select-control").get(0);
sel.options[find_option(sel, "window")].firstChild.textContent =
"window (" +
Math.round(eventData.viewport.voi.windowCenter) +
@@ -176,7 +163,7 @@ export function disableFullscreen(dicom_element) {
$(".canvas-panel-fullscreen").toggleClass(
"canvas-panel canvas-panel-fullscreen"
);
- $(".question").append($(".canvas-panel"));
+ $(".question").prepend($(".canvas-panel"));
$(".canvas-panel").get(0).scrollIntoView();
setDicomCanvasNonFullscreen(dicom_element);
@@ -284,7 +271,7 @@ export function debugCornerstone() {
*/
export function changeControlSelection() {
// We also duplicate the sel that are available
- const sel = $(".control-overlay").get(0);
+ const sel = $(".dicom-select-control").get(0);
const old = sel.oldSelectedIndex;
sel.oldSelectedIndex = sel.selectedIndex;
@@ -309,6 +296,25 @@ export function changeControlSelection() {
});
break;
}
+ case "measure": {
+ cornerstoneTools.setToolActiveForElement(dicom_element, "Length", {
+ mouseButtonMask: 1,
+ });
+ break;
+ }
+ case "rectangle": {
+ cornerstoneTools.setToolActiveForElement(dicom_element, "RectangleRoi", {
+ mouseButtonMask: 1,
+ });
+ break;
+ }
+ case "ellipse": {
+ cornerstoneTools.setToolActiveForElement(dicom_element, "EllipseRoi", {
+ mouseButtonMask: 1,
+ });
+ break;
+ }
+
case "angle": {
cornerstoneTools.setToolActiveForElement(dicom_element, "Angle", {
mouseButtonMask: 1,
@@ -384,18 +390,7 @@ export function changeControlSelection() {
break;
}
case "close": {
- // disable fullscreen if required
- if ($(".canvas-panel").length == 0) {
- disableFullscreen(dicom_element);
- }
- if (dicom_element != undefined) {
- // See https://github.com/cornerstonejs/cornerstoneTools/issues/1337
- cornerstone.removeElementData(dicom_element);
- cornerstone.disable(dicom_element);
- $(".canvas-panel").remove();
- $(".figure-open").removeClass("figure-open").addClass("figure");
- $(dicom_element).remove();
- }
+ closeViewer(dicom_element);
break;
}
}
@@ -424,7 +419,7 @@ export function keydown_handler(event) {
if (target_element == "INPUT" || target_element == "TEXTAREA") {
return;
}
- const sel = $(".control-overlay").get(0);
+ const sel = $(".dicom-select-control").get(0);
switch (event.code) {
case "KeyP":
sel.selectedIndex = find_option(sel, "pan");
@@ -660,7 +655,7 @@ export function openMainImage(current_question, t, source) {
// No full size figure / dicom loaded yet
if (figure_to_load == open_figure) {
// Scroll to the image if it is already open
- document.getElementById("dicom-image").scrollIntoView();
+ document.getElementById("viewer-title-bar").scrollIntoView();
return;
} else {
let el;
@@ -678,8 +673,33 @@ export function openMainImage(current_question, t, source) {
source.className = "figure-open";
- $(".question").append(
- '