This commit is contained in:
Ross
2022-07-27 10:06:56 +01:00
parent 8f5c878bab
commit ef478459d8
14 changed files with 701 additions and 645 deletions
+1 -1
View File
@@ -76,7 +76,7 @@ class RapidForm(ModelForm):
"all": ["css/widgets.css"],
}
# Adding this javascript is crucial
js = ["jsi18n.js", "tesseract.min.js"]
js = ["jsi18n.js", "tesseract.min.js", "js/upload_form_helpers.js"]
def __init__(self, *args, **kwargs):
self.user = kwargs.pop(
+73 -436
View File
@@ -6,11 +6,12 @@
<script type="text/javascript">
let normal = false;
let csrf_token = "{{csrf_token}}";
let hash_url = "{% url 'rapids:rapid_question_by_hash' %}";
//let monitor_directory_handler = false;
//let monitor_interval_id = false;
// set to hold the files that are still being processed
let active_file_inputs = new Set();
let load_viewer = false;
// async function listAllFilesAndDirs(dirHandle, files_only) {
@@ -39,84 +40,13 @@
// return files;
// }
function showEditPopup(url) {
var win = window.open(url, "Edit",
'height=500,width=800,resizable=yes,scrollbars=yes');
return false;
}
function showAddPopup(triggeringLink) {
var name = triggeringLink.id.replace(/^add_/, '');
href = triggeringLink.href;
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
win.focus();
return false;
}
function closePopup(win, newID, newRepr, id) {
$(id + "_to").append('<option value=' + newID + ' title=' + newRepr + ' >' + newRepr + '</option>')
win.close();
}
document.addEventListener('drop', function (e) {
e.preventDefault();
}, false);
function getUnusedInputs(inputs) {
new_inputs = [];
for (let i = 0; i < inputs.length; i++) {
input = inputs.get(i);
if (!input.value) {
new_inputs.push(input);
}
}
return $(new_inputs);
}
function getCurrentFiles() {
inputs = $("#rapid-form input[type=file]");
let files = new Set();
for (let j = 0; j < inputs.length; j++) {
i = inputs.get(j);
if (i.files.length > 0) {
files.add(i.files[0]);
}
}
return files;
}
function extendInputs(n) {
// Makes sure we have n inputs available
// returns available inputs
inputs = getUnusedInputs($("#rapid-form input[type=file][id^=id_images-]"));
//fileInput = document.getElementById("id_images-0-image");
// Make sure we have enough input targets
input_diff = (n - inputs.length)
if (input_diff > 0) {
for (let j = 0; j < input_diff; j++) {
add_input_form()
}
// Need to make sure we include the new ones...
inputs = getUnusedInputs($("#rapid-form input[type=file][id^=id_images-]"));
}
return inputs;
}
function add_input_form() {
var form_idx = $('#id_images-TOTAL_FORMS').val();
$('#image_form_set').append($($('#empty_form').html().replace(/__prefix__/g, form_idx)).on("change",
input_change));
$('#id_images-TOTAL_FORMS').val(parseInt(form_idx) + 1);
}
function add_answers_input_form() {
var form_idx = $('#id_answers-TOTAL_FORMS').val();
@@ -125,62 +55,6 @@
$('#id_answers-TOTAL_FORMS').val(parseInt(form_idx) + 1);
}
function input_change(evt) {
file = evt.target.files[0];
$(evt.target).removeClass("image-ident-warning");
$(evt.target).removeClass("image-ident-ok");
el = evt.target;
//readFileAndProcess();
readFileAndProcess2(el);
// Check if we have selected a examination type
if (!$("#id_examination_to option").length) {
// Yes we do read the file twice (here and where loading it in the viewer)
var reader = new FileReader();
reader.onload = function (file) {
var arrayBuffer = reader.result;
// Here we have the file data as an ArrayBuffer. dicomParser requires as input a
// Uint8Array so we create that here
var byteArray = new Uint8Array(arrayBuffer);
extractDicomStudyDescription(byteArray)
}
reader.readAsArrayBuffer(file);
}
}
function addFile(f, feedback) {
let dT = new DataTransfer();
dT.clearData();
dT.items.add(f);
for (let i = 0; i < inputs.length; i++) {
el = inputs.get(i);
if (el.files.length == 0) {
el.files = dT.files;
//ocr(el)
if (feedback) {
arr = el.name.split("-");
arr.splice(2, 1, "feedback_image");
feedback_el_name = arr.join("-");
$(`[name=${feedback_el_name}]`).prop("checked", true);
}
$(el).change();
return false;
}
}
}
$(document).ready(function () {
@@ -223,7 +97,7 @@
}
// Get all input elements
inputs = extendInputs(file_drop_number);
inputs = extendInputs("rapid-form", file_drop_number);
console.log("drop inputs", inputs, evt);
@@ -250,7 +124,7 @@
// listAllFilesAndDirs(monitor_directory_handler).then(async function (
// items) {
// files_to_add = new Set();
// current_files = getCurrentFiles();
// current_files = getCurrentFormFiles();
// current_files_tuple = new Set()
// for (let elem of current_files) {
// current_files_tuple.add(
@@ -368,321 +242,83 @@
});
function ocr2(url, input) {
console.log("OCR", url, input)
Tesseract.recognize(
url,
'eng',
{ logger: m => console.log(m) }
).then(({ data: { text } }) => {
l = text.toLowerCase();
uploading_el = $(`img[data-input-id='${input.id}'], div[data-input-id='${input.id}']`)
uploading_el.removeClass("image-ident-loading");
console.log("found text", l);
if (l.includes("accesion") || l.includes("number") || l.search(
/(ref|rk9|rh8|ra9|rbz)\d+/g) > -1) {
console.log("Match found ", input);
$(input).addClass("image-ident-warning");
uploading_el.addClass("image-ident-warning");
} else {
$(input).addClass("image-ident-ok");
}
})
}
async function blobToBase64(blob) {
return new Promise((resolve, _) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.readAsDataURL(blob);
});
}
// async function readFileAndProcess(callback) {
// //$("#single-dicom-viewer").empty()
// //images = []
// //Function that returns a promise to read the file
// const reader = (file) => {
// return new Promise((resolve, reject) => {
// const fileReader = new FileReader();
// fileReader.onload = () => resolve(fileReader);
// fileReader.readAsDataURL(file);
// });
// }
//
// // Add file to the process list
// active_file_inputs.add(el)
// const readFile = (file, el) => {
// reader(file).then(reader => {
// console.log("12345", reader)
// $(el).parent().parent().find(".temp-thumb").remove();
//
// if (reader.result.startsWith("data:application/octet-stream;base64")) {
// const element = $(`<div class='temp-thumb' src=${reader.result}></div>`).get(0)
// $(el).parent().parent().prepend(element);
// const imageId = cornerstoneWADOImageLoader.wadouri.fileManager.add(
// file
// );
// cornerstone.enable(element);
// cornerstone.loadAndCacheImage(imageId).then(function (image) {
// cornerstone.displayImage(element, image);
// cornerstone.resize(element)
//
// });
//
// } else {
// var image = new Image();
// image.title = file.name;
// image.src = reader.result;
// image.className = "temp-thumb";
// $(el).parent().parent().prepend(image);
// //images.push(reader.result);
// }
//
// active_file_inputs.delete(el)
// console.log("active", active_file_inputs)
// // Only load once all queued files have been processed
// if (active_file_inputs.size < 1) {
// loadViewer();
// }
// });
// }
//
// file_set = $("#image_form_set input[type=file]");
//
// file_set.each(async (n, el) => {
// if (el.files.length > 0) {
// filename = el.files[0].name;
// // Probably no need to await here anymore
// await readFile(el.files[0], el);
// }
// })
// }
async function readFileAndProcess2(el) {
//file_set = $("#image_form_set input[type=file]");
//file_set.each(async (n, el) => {
if (el.files.length > 0) {
filename = el.files[0].name;
// Probably no need to await here anymore
//await readFile(el.files[0], el);
// const viewLoadChecker = setInterval(function () {
// if (load_viewer) {
// load_viewer = false;
// loadViewer();
// }
// }, 2000);
console.log(el.files[0])
function extractDicomDetails(byteArray) {
if (!$("#id_examination_to option").length) {
$(el).parent().parent().find(".temp-thumb").remove();
let url = URL.createObjectURL(el.files[0])
n = el.id.split("-")[1];
$(`#drop-filenames span[data-input-id='${el.id}']`).remove();
let extra_class = " image-ident-loading";
if ($(el).hasClass("image-ident-warning")) {
extra_class = " image-ident-warning";
} else if ($(el).hasClass("image-ident-ok")) {
extra_class = " image-ident-ok";
}
//let extra_class = "";
let imageId;
if (el.files[0].type.startsWith("image")) {
let hash = CryptoJS.MD5(el.files[0]).toString();
console.log("HASH", hash)
base = await blobToBase64(el.files[0]);
imageId = "base64://" + base.split(",")[1];
imageId2 = base;
const element = $(`<img class='temp-thumb' src=${imageId}></div>`).get(0)
$(el).parent().parent().prepend(element);
ocr2(url, el);
checkHash(hash, el);
$("#drop-filenames").append(
`<span data-input-id='${el.id}'><span>${n}: ${el.files[0].name}</span><img class='uploading${extra_class}' data-input-id='${el.id}' src=${url}></span>`
)
} else {
imageId = `wadouri:${url}`;
imageId2 = imageId
console.log(imageId)
const element = $(`<div class='temp-thumb' src=${imageId2}></div>`).get(0)
$(el).parent().parent().prepend(element);
cornerstone.enable(element);
cornerstone.loadAndCacheImage(imageId).then(function (image) {
cornerstone.displayImage(element, image);
cornerstone.resize(element)
let pixel_data = image.getPixelData().toString()
console.log(element, "pixel data", pixel_data)
let hash = CryptoJS.MD5(pixel_data).toString();
console.log(element, "HASH", hash)
checkHash(hash, el);
});
$("#drop-filenames").append(
`<span data-input-id='${el.id}'><span>${n}: ${el.files[0].name}</span><div class='uploading${extra_class}' data-input-id='${el.id}' src=${url}></div></span>`
)
const element2 = $(`#drop-filenames div[data-input-id='${el.id}']`).get(0);
cornerstone.enable(element2);
cornerstone.loadAndCacheImage(imageId).then(function (image) {
cornerstone.displayImage(element2, image);
$(element2).addClass("temp-thumb-large");
cornerstone.resize(element2)
setTimeout(function () {
ocr2($(element2).find("canvas").get(0).toDataURL(), el);
$(element2).removeClass("temp-thumb-large");
cornerstone.resize(element2)
}, 500);
});
}
active_file_inputs.delete(el)
console.log("active", active_file_inputs)
// Only load once all queued files have been processed
if (active_file_inputs.size < 1) {
load_viewer = true;
//loadViewer();
}
}
//})
}
async function readFileAndProcess(callback) {
//$("#single-dicom-viewer").empty()
//images = []
//Function that returns a promise to read the file
const reader = (file) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.onload = () => resolve(fileReader);
fileReader.readAsDataURL(file);
});
}
// Add file to the process list
active_file_inputs.add(el)
const readFile = (file, el) => {
reader(file).then(reader => {
console.log("12345", reader)
$(el).parent().parent().find(".temp-thumb").remove();
if (reader.result.startsWith("data:application/octet-stream;base64")) {
const element = $(`<div class='temp-thumb' src=${reader.result}></div>`).get(0)
$(el).parent().parent().prepend(element);
const imageId = cornerstoneWADOImageLoader.wadouri.fileManager.add(
file
);
cornerstone.enable(element);
cornerstone.loadAndCacheImage(imageId).then(function (image) {
cornerstone.displayImage(element, image);
cornerstone.resize(element)
});
} else {
var image = new Image();
image.title = file.name;
image.src = reader.result;
image.className = "temp-thumb";
$(el).parent().parent().prepend(image);
//images.push(reader.result);
}
active_file_inputs.delete(el)
console.log("active", active_file_inputs)
// Only load once all queued files have been processed
if (active_file_inputs.size < 1) {
loadViewer();
}
});
}
file_set = $("#image_form_set input[type=file]");
file_set.each(async (n, el) => {
if (el.files.length > 0) {
filename = el.files[0].name;
// Probably no need to await here anymore
await readFile(el.files[0], el);
}
})
}
const viewLoadChecker = setInterval(function () {
if (load_viewer) {
load_viewer = false;
loadViewer();
}
}, 2000);
function loadViewer() {
console.log("LOAD VIEWER")
// temp fix before starting viewer collapsed
$("#single-dicom-viewer").show()
//file_set = $("#image_form_set input[type=file]");
//n = 0;
//for (let i = 0; i < file_set.length; i++) {
// el = file_set.get(i)
// if (el.files.length > 0) {
// n++;
// }
//}
image_set = $("#image_form_set .temp-thumb").get()//.map(function() { return $(this).attr("src")}).get();
console.log(image_set);
//console.log()
//if (n == image_set.length) {
const event = new CustomEvent('loadDicomViewer', {
"detail": image_set
});
window.dispatchEvent(event);
sortable('.sortable');
//sortable('.sortable')[0].addEventListener('sortstop', function(e) {
updateImagePositions();
//}
}
function updateImagePositions() {
console.log("UP pos");
file_set = $("#image_form_set ul");
n = 0;
for (let i = 0; i < file_set.length; i++) {
ul = file_set.get(i);
console.log(ul)
file_element = $(ul).find("input[type=file]").get(0);
// If a (new) file is being uploaded we save it's name prior to it being hashed
if (file_element.files.length > 0) {
file_name = file_element.files[0].name
//$(ul).find("input[type=text]").val(file_name);
$(ul).find("input[name*='filename']").val(file_name);
}
if (file_element.files.length > 0 || $(ul).find(":contains('Currently:')")) {
n++;
$(ul).find("input[type=number]").val(n);
}
}
}
function checkHash(hash, input) {
$.ajax({
url: "{% url 'rapids:rapid_question_by_hash' %}",
data: {
csrfmiddlewaretoken: '{{ csrf_token }}',
hash: hash
},
type: "POST",
dataType: "json",
})
// $.ajax().done(), $.ajax().fail(), $ajax().always() are upto you. Add/change accordingly
.done(function (data) {
console.log(data);
if (data.status == "success") {
console.log("success");
console.log(data.id)
if (data.id) {
//toastr.info(`id ${data.id}`)
uploading_el = $(`img[data-input-id='${input.id}'], div[data-input-id='${input.id}']`)
$(input).addClass("image-duplicate");
uploading_el.addClass("image-duplicate");
toastr.warning(`Image (${input.files[0].name}) already exists.<br /><a href='${data.url}'>Click to view</a><br /><button type="button" class="btn clear">Dismiss</button>`, "Duplicate image", {
"closeButton": false,
"debug": false,
"newestOnTop": false,
"progressBar": false,
"positionClass": "toast-top-full-width",
"preventDuplicates": false,
"onclick": null,
"showDuration": "0",
"hideDuration": "0",
"timeOut": 0,
"extendedTimeOut": 0,
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut",
"tapToDismiss": false
})
}
}
})
.always(function () {
console.log('[Done]');
})
}
function extractDicomStudyDescription(byteArray) {
// We need to setup a try/catch block because parseDicom will throw an exception
// if you attempt to parse a non dicom part 10 file (or one that is corrupted)
try {
@@ -717,6 +353,7 @@
} catch (err) {
console.log(err);
}
}
}
</script>
+1 -1
View File
@@ -179,4 +179,4 @@ def test_index(client, create_superuser, exam_views, django_user_model):
print(json_response)
assert len(json_response) == 2
assert len(json_response) == 2