update viewer for atlas series

This commit is contained in:
Ross
2025-06-10 11:36:28 +01:00
parent b825342a24
commit 0c07400cc3
14 changed files with 3896 additions and 4074 deletions
@@ -413,14 +413,6 @@
.then(response => response.text())
.then(html => {
modalBody.innerHTML = html; // Load the fetched HTML into the modal body
const viewer_element = document.getElementById('single-dicom-viewer');
const images = JSON.parse(viewer_element.getAttribute('data-images'));
window.loadDicomViewer(images);
annotationjson = JSON.parse(viewer_element.dataset.annotationjson);
viewport = JSON.parse(viewer_element.dataset.viewportjson);
current_image_id_index = viewer_element.dataset.currentimageid;
console.log(viewer_element.dataset.annotationjson3d)
console.log(viewer_element.dataset.viewerstate3d)
load_3d = false;
viewer_element_3d = document.getElementById('root');
if (viewer_element_3d.dataset.viewerstate3d != undefined) {
@@ -430,11 +422,9 @@
} else {
viewer_element_3d = null;
}
dicom_element = $(".cornerstone-element").get(0);
// We have a slight delay to allow the viewer to load
setTimeout(function () {
// Then we load the annotation and viewport
loadAnnotationAndViewportOnElement(annotationjson, viewport, dicom_element, current_image_id_index);
window.mountDicomViewers();
if (load_3d) {
console.log("loading 3d")
@@ -450,7 +440,6 @@
}, 200);
document.getElementById("reload-finding").addEventListener("click", function () {
loadAnnotationAndViewportOnElement(annotationjson, viewport, dicom_element, current_image_id_index);
importAnnotations_root(annotationjson3d)
importViewerState_root(viewerState);
});
@@ -20,9 +20,6 @@
<button class="btn btn-primary" id="reload-finding">Reload</button>
{% with image_url_array_and_count=finding.series.get_image_url_array_and_count %}
<div id="single-dicom-viewer" class="dicom-viewer" data-images='{{ image_url_array_and_count.0 }}' data-annotations='' data-annotationjson={{finding.annotation_json}}
data-viewportjson={{finding.viewport_json}} data-findingid={{finding.id}} data-currentimageid={{finding.current_image_id_index}}>
</div>
<div id="root" class="dicom-viewer-root" data-images="{{ image_url_array_and_count.0 }}"
style="height: 600px; box-sizing: border-box; background: #222;"
data-annotationjson='{{ finding.annotation_json_3d }}' data-viewerstate='{{ finding.viewer_state_3d }}'
+20 -106
View File
@@ -40,8 +40,8 @@ Associated case:
{% endfor %}
{% with image_url_array_and_count=series.get_image_url_array_and_count %}
<div id="single-dicom-viewer" class="dicom-viewer" data-images="{{ image_url_array_and_count.0 }}" data-annotations=''>
</div>
{% comment %} <div id="single-dicom-viewer" class="dicom-viewer" data-images="{{ image_url_array_and_count.0 }}" data-annotations=''>
</div> {% endcomment %}
<div id="root" class="dicom-viewer-root" data-images="{{ image_url_array_and_count.0 }}"
style="width: 1000px; height: 600px; box-sizing: border-box; background: #222;"
@@ -91,12 +91,7 @@ Associated case:
{% for finding in series.findings.all %}
<div class="finding-box">
<button id="finding-{{finding.pk}}" class="view-finding-button" data-annotationjson={{finding.annotation_json}}
data-viewportjson={{finding.viewport_json}} data-findingid={{finding.id}} data-currentimageid={{finding.current_image_id_index}}>Click to view</button>
{% if finding.viewer_state_3d %}
<button id="finding-{{finding.pk}}-3d" class="view-finding-button-3d" data-annotationjson3d='{{finding.annotation_json_3d}}' data-viewerstatejson='{{finding.viewer_state_3d}}'>Click to view 3D</button>
{% endif %}
<button id="finding-{{finding.pk}}-3d" class="view-finding-button-3d" data-annotationjson3d='{{finding.annotation_json_3d}}' data-viewerstatejson='{{finding.viewer_state_3d}}' data-findingid='{{finding.pk}}'>Click to view</button>
<span class="view-finding-details">
Finding(s): {% for f in finding.findings.all %}{{f.get_link}}{% endfor %}<br />
@@ -135,6 +130,10 @@ Associated case:
<p>
This will limit the series to the selected bounds (the rest of the images will be deleted). This is useful when you have a large volume of which only a small area is relevant to the case. NOTE: once deleted the images cannot be recovered on the site (they would have to be reuploaded if required). Make sure your images are shown in the correct order above and use test the test truncate button first.
</p>
<div role="alert" class="alert alert-warning">
<strong>Warning:</strong> Please note: if you have reordered the series this may result in the incorrect images being deleted.
</div>
Start <input id="lower-truncation-bound-input" type="number" value="1"> <button id="set-lower-truncation-bound-button">Set</button><br/>
End <input id="upper-truncation-bound-input"type="number" value="{{image_url_array_and_count.1}}"> <button id="set-upper-truncation-bound-button">Set</button><br/>
<button id="truncate-test-button">Test truncate</button>
@@ -225,44 +224,22 @@ Associated case:
<script>
$(document).ready(function () {
const apiKey = "root"
$("#set-lower-truncation-bound-button").click(() => {
dicom_element = $(".cornerstone-element").get(0);
index = cornerstone.getEnabledElement(dicom_element).toolStateManager.toolState.stack.data[0].currentImageIdIndex
$("#lower-truncation-bound-input").val(index+1);
$("#lower-truncation-bound-input").val(getCurrentStackPosition_root(0) + 1);
});
$("#set-upper-truncation-bound-button").click(() => {
dicom_element = $(".cornerstone-element").get(0);
index = cornerstone.getEnabledElement(dicom_element).toolStateManager.toolState.stack.data[0].currentImageIdIndex
$("#upper-truncation-bound-input").val(index+1);
$("#upper-truncation-bound-input").val(getCurrentStackPosition_root(0) + 1);
});
$("#truncate-test-button").click(() => {
lower_bound = parseInt($("#lower-truncation-bound-input").val()) - 1;
upper_bound = parseInt($("#upper-truncation-bound-input").val()) - 1;
$("#lower-truncation-bound-input").prop("disabled", true);
$("#upper-truncation-bound-input").prop("disabled", true);
$("#set-lower-truncation-bound-button").remove();
$("#set-upper-truncation-bound-button").remove();
$("#truncate-test-button").remove();
if (lower_bound >= upper_bound) {
alert("The lower bound must be less than the upper bound.");
return;
const lower = parseInt($("#lower-truncation-bound-input").val()) - 1;
const upper = parseInt($("#upper-truncation-bound-input").val()) - 1;
const ok = window[`truncateStack_${apiKey}`](lower, upper);
if (ok) {
$("#truncate-output").text("The truncated images are shown above.");
}
dicom_element = $(".cornerstone-element").get(0);
stack = cornerstone.getEnabledElement(dicom_element).toolStateManager.toolState.stack.data[0]
stack.imageIds = stack.imageIds.slice(lower_bound, upper_bound+1) // inclusive
stack.currentImageIdIndex = 0
//let id = stack.imageIds[0];
//cornerstone.loadImage(id).then((b) => {
// cornerstone.displayImage(dicom_element, b);
//});
cornerstone.reset(dicom_element);
$("#truncate-output").text("The truncated images are shown above. If you wish to make changes refresh the page. To continue click the trucated series button.")
})
});
$("#truncate-button").click(() => {
lower_bound = parseInt($("#lower-truncation-bound-input").val()) - 1;
upper_bound = parseInt($("#upper-truncation-bound-input").val()) - 1;
@@ -282,7 +259,7 @@ Associated case:
$("#add-finding-button").click(() => {
$("#hidden-form").show()
dicom_element = $(".cornerstone-element").get(0);
//dicom_element = $(".cornerstone-element").get(0);
//cornerstoneTools.globalImageIdSpecificToolStateManager.clear(dicom_element);
//cornerstone.reset(dicom_element);
////cornerstone.resize(dicom_element, true);
@@ -302,11 +279,7 @@ Associated case:
$("#reset-viewport-button").click(() => {
dicom_element = $(".cornerstone-element").get(0);
//annotationjson = JSON.parse(e.currentTarget.dataset.annotationjson);
cornerstoneTools.globalImageIdSpecificToolStateManager.clear(dicom_element);
cornerstone.reset(dicom_element);
cornerstone.resize(dicom_element, true);
resetViewer_root();
});
$(".view-finding-button-3d").each((n, el) => {
@@ -321,38 +294,11 @@ Associated case:
});
});
$(".view-finding-button").each((n, el) => {
$(el).click((e) => {
dicom_element = $(".cornerstone-element").get(0);
annotationjson = JSON.parse(e.currentTarget.dataset.annotationjson);
viewport = JSON.parse(e.currentTarget.dataset.viewportjson);
current_image_id_index = e.currentTarget.dataset.currentimageid;
console.log(e.currentTarget, current_image_id_index)
loadAnnotationAndViewportOnElement(annotationjson, viewport, dicom_element, current_image_id_index);
importLegacyViewport_root(viewport)
importLegacyAnnotations_root(annotationjson);
jumpToSliceByImageId_root(0, current_image_id_index);
console.log("Loaded annotation and viewport on element", dicom_element, annotationjson, viewport, current_image_id_index);
$(el).addClass("active");
});
});
$("#diff-show-all").click(() => {
console.log("Helol");
})
$("#diff-show-diff").click(() => {
console.log("diff");
})
{% if editing_finding > 0 %}
$("#hidden-form").show()
setTimeout(function() {
$(".view-finding-button[data-findingid={{editing_finding}}]").trigger("click");
$(".view-finding-button-3d[data-findingid={{editing_finding}}]").trigger("click");
}, 1000)
{% endif %}
@@ -367,31 +313,7 @@ Associated case:
{% endif %}
});
function loadAnnotationAndViewportOnElement(annotation, viewport, dicom_element, current_image_id_index) {
cornerstoneTools.globalImageIdSpecificToolStateManager.clear(dicom_element);
cornerstone.getEnabledElement(dicom_element).viewport = viewport
cornerstoneTools.globalImageIdSpecificToolStateManager.restoreToolState(
annotation);
//cornerstone.getEnabledElement(dicom_element).toolStateManager.restoreToolState(annotationjson)
cornerstone.resize(dicom_element);
//current_image_id_index = parseInt(current_image_id_index);
if (Number.isInteger(current_image_id_index)) {
dicomViewer.loadStackIndex(current_image_id_index, dicom_element);
} else {
try {
dicomViewer.loadImageById(current_image_id_index, dicom_element);
} catch (e) {
dicomViewer.getNextAnnotationImage(dicom_element);
}
}
}
$(document).on('submit', '#series_finding_form', function (e) {
dicom_element = $(".cornerstone-element").get(0);
c = cornerstone.getEnabledElement(dicom_element);
e.preventDefault();
$.ajax({
@@ -401,14 +323,6 @@ Associated case:
series_finding_id: {{ editing_finding }},
description: $('#id_description').val(),
series: {{ series.pk }},
//annotation_json: JSON.stringify(c.toolStateManager.saveToolState()),
// This is the stack number
//current_image_id_index: c.toolStateManager.toolState.stack.data[0].currentImageIdIndex,
// but we want to use the current image id (so if the stack is reordered it still attaches to the correct image)
current_image_id_index: c.toolStateManager.toolState.stack.data[0].imageIds[c.toolStateManager.toolState.stack.data[0].currentImageIdIndex],
annotation_json: JSON.stringify(cornerstoneTools.globalImageIdSpecificToolStateManager
.saveToolState()),
viewport_json: JSON.stringify(c.viewport),
annotation_json_3d: window.exportAnnotations_root(),
viewer_state_3d: window.exportViewerState_root(),
findings: JSON.stringify($('#finding-form select[name="findings"]').find(":selected")
+8 -8
View File
@@ -1450,9 +1450,9 @@ def create_series_findings(request):
structure_ids = json.loads(request.POST.get("structures"))
condition_ids = json.loads(request.POST.get("conditions"))
description = request.POST.get("description")
annotation_json = request.POST.get("annotation_json")
viewport_json = request.POST.get("viewport_json")
current_image_id_index = request.POST.get("current_image_id_index")
#annotation_json = request.POST.get("annotation_json")
#viewport_json = request.POST.get("viewport_json")
#current_image_id_index = request.POST.get("current_image_id_index")
annotation_json_3d = request.POST.get("annotation_json_3d")
viewer_state_3d = request.POST.get("viewer_state_3d")
@@ -1465,20 +1465,20 @@ def create_series_findings(request):
sf = get_object_or_404(SeriesFinding, pk=series_finding_id)
sf.series = series
sf.description = description
sf.annotation_json = annotation_json
sf.viewport_json = viewport_json
#sf.annotation_json = annotation_json
#sf.viewport_json = viewport_json
else:
sf = SeriesFinding.objects.create(
series=series,
description=description,
annotation_json=annotation_json,
viewport_json=viewport_json,
#annotation_json=annotation_json,
#viewport_json=viewport_json,
)
sf.findings.set(findings)
sf.structures.set(structures)
sf.conditions.set(conditions)
sf.current_image_id_index = current_image_id_index
#sf.current_image_id_index = current_image_id_index
sf.annotation_json_3d = annotation_json_3d
sf.viewer_state_3d = viewer_state_3d
sf.save()
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -70,7 +70,7 @@
<script src="{% static 'js/cornerstone/cornerstoneWADOImageLoader.min.js' %}"></script>
<script src="{% static 'js/cornerstone/cornerstone-base64-image-loader.umd.js' %}"></script>
<script src="{% static 'js/anatomy.js' %}" defer="defer" type="module"></script>
<script src="{% static 'dv3d/index-DBrYmXwn.js' %}" type="module" defer="defer" type="module"></script>
<script src="{% static 'dv3d/index.js' %}" type="module" defer="defer" type="module"></script>
{% block js %}
{% endblock %}