Merge branch 'master' of ssh://git.xkjq.uk:30001/ross/rad
This commit is contained in:
@@ -5,16 +5,43 @@
|
|||||||
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
let normal = false;
|
let normal = false;
|
||||||
|
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 active_file_inputs = new Set()
|
||||||
|
|
||||||
|
async function listAllFilesAndDirs(dirHandle) {
|
||||||
|
const files = [];
|
||||||
|
for await (let [name, handle] of dirHandle) {
|
||||||
|
const {
|
||||||
|
kind
|
||||||
|
} = handle;
|
||||||
|
if (handle.kind === 'directory') {
|
||||||
|
files.push({
|
||||||
|
name,
|
||||||
|
handle,
|
||||||
|
kind
|
||||||
|
});
|
||||||
|
files.push(...await listAllFilesAndDirs(handle));
|
||||||
|
} else {
|
||||||
|
files.push({
|
||||||
|
name,
|
||||||
|
handle,
|
||||||
|
kind
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
function showEditPopup(url) {
|
function showEditPopup(url) {
|
||||||
var win = window.open(url, "Edit",
|
var win = window.open(url, "Edit",
|
||||||
'height=500,width=800,resizable=yes,scrollbars=yes');
|
'height=500,width=800,resizable=yes,scrollbars=yes');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showAddPopup(triggeringLink) {
|
function showAddPopup(triggeringLink) {
|
||||||
var name = triggeringLink.id.replace(/^add_/, '');
|
var name = triggeringLink.id.replace(/^add_/, '');
|
||||||
href = triggeringLink.href;
|
href = triggeringLink.href;
|
||||||
@@ -22,13 +49,16 @@
|
|||||||
win.focus();
|
win.focus();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function closePopup(win, newID, newRepr, id) {
|
function closePopup(win, newID, newRepr, id) {
|
||||||
console.log(id)
|
console.log(id)
|
||||||
$(id + "_to").append('<option value=' + newID + ' title=' + newRepr + ' >' + newRepr + '</option>')
|
$(id + "_to").append('<option value=' + newID + ' title=' + newRepr + ' >' + newRepr + '</option>')
|
||||||
win.close();
|
win.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('drop', function (e) { e.preventDefault(); }, false);
|
document.addEventListener('drop', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
}, false);
|
||||||
|
|
||||||
function getUnusedInputs(inputs) {
|
function getUnusedInputs(inputs) {
|
||||||
new_inputs = [];
|
new_inputs = [];
|
||||||
@@ -69,7 +99,8 @@
|
|||||||
|
|
||||||
function add_input_form() {
|
function add_input_form() {
|
||||||
var form_idx = $('#id_images-TOTAL_FORMS').val();
|
var form_idx = $('#id_images-TOTAL_FORMS').val();
|
||||||
$('#image_form_set').append($($('#empty_form').html().replace(/__prefix__/g, form_idx)).on("change", input_change));
|
$('#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);
|
$('#id_images-TOTAL_FORMS').val(parseInt(form_idx) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,6 +162,32 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
$(el).change();
|
||||||
|
|
||||||
|
if(feedback) {
|
||||||
|
arr = el.name.split("-");
|
||||||
|
arr.splice(2, 1, "feedback_image");
|
||||||
|
feedback_el_name = arr.join("-");
|
||||||
|
|
||||||
|
$(`[name=${feedback_el_name}]`).prop("checked", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$("#add_abnormality").appendTo($("label[for='id_abnormality']"));
|
$("#add_abnormality").appendTo($("label[for='id_abnormality']"));
|
||||||
@@ -165,10 +222,6 @@
|
|||||||
$(evt.target).removeClass("drop-target-active");
|
$(evt.target).removeClass("drop-target-active");
|
||||||
|
|
||||||
file_drop_number = evt.dataTransfer.files.length;
|
file_drop_number = evt.dataTransfer.files.length;
|
||||||
// Get all input elements
|
|
||||||
inputs = extendInputs(file_drop_number);
|
|
||||||
|
|
||||||
console.log("drop inputs", inputs, evt);
|
|
||||||
|
|
||||||
if (file_drop_number < 1) {
|
if (file_drop_number < 1) {
|
||||||
toastr.warning(`Drop failed (no files), try again.`);
|
toastr.warning(`Drop failed (no files), try again.`);
|
||||||
@@ -176,32 +229,20 @@
|
|||||||
toastr.info(`Loading ${file_drop_number} dropped image(s).`);
|
toastr.info(`Loading ${file_drop_number} dropped image(s).`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get all input elements
|
||||||
|
inputs = extendInputs(file_drop_number);
|
||||||
|
|
||||||
|
console.log("drop inputs", inputs, evt);
|
||||||
|
|
||||||
|
|
||||||
// Loop through each dropped file and try to assign to an
|
// Loop through each dropped file and try to assign to an
|
||||||
// input element
|
// input element
|
||||||
[...evt.dataTransfer.files].forEach((f) => {
|
[...evt.dataTransfer.files].forEach((f) => {
|
||||||
let dT = new DataTransfer();
|
feedback = false;
|
||||||
dT.clearData();
|
|
||||||
dT.items.add(f);
|
|
||||||
for (let i = 0; i < inputs.length; i++) {
|
|
||||||
el = inputs.get(i);
|
|
||||||
console.log("drop el", el);
|
|
||||||
|
|
||||||
if (el.files.length == 0) {
|
|
||||||
el.files = dT.files;
|
|
||||||
//ocr(el)
|
|
||||||
$(el).change();
|
|
||||||
console.log("drop change")
|
|
||||||
|
|
||||||
if (evt.target.id == "feedback-drop-target") {
|
if (evt.target.id == "feedback-drop-target") {
|
||||||
arr = el.name.split("-");
|
feedback = true;
|
||||||
arr.splice(2, 1, "feedback_image");
|
|
||||||
feedback_el_name = arr.join("-");
|
|
||||||
|
|
||||||
$(`[name=${feedback_el_name}]`).prop("checked", true);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
addFile(f, feedback)
|
||||||
})
|
})
|
||||||
|
|
||||||
// // If you want to use some of the dropped files
|
// // If you want to use some of the dropped files
|
||||||
@@ -215,8 +256,34 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
$('#add_more_images').click(() => { add_input_form() });
|
$('#directory-picker-button').click(() => {
|
||||||
$('#add_more_answers').click(() => { add_answers_input_form() });
|
window.showDirectoryPicker().then((handler) => {
|
||||||
|
monitor_directory_handler = handler;
|
||||||
|
monitor_interval_id = setInterval(function () {
|
||||||
|
listAllFilesAndDirs(monitor_directory_handler).then((items) => {
|
||||||
|
console.log(items);
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
|
$("#directory-picker-display").text(monitor_directory_handler.name).after(
|
||||||
|
$(
|
||||||
|
" <span>[clear]</span>").click((evt) => {
|
||||||
|
$(evt.target).remove();
|
||||||
|
$("#directory-picker-display").text("");
|
||||||
|
monitor_directory_handler = false;
|
||||||
|
clearInterval(monitor_interval_id);
|
||||||
|
//const files = await listAllFilesAndDirs(directoryHandle);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$('#add_more_images').click(() => {
|
||||||
|
add_input_form()
|
||||||
|
});
|
||||||
|
$('#add_more_answers').click(() => {
|
||||||
|
add_answers_input_form()
|
||||||
|
});
|
||||||
|
|
||||||
$("input[type=file]").on('change', input_change);
|
$("input[type=file]").on('change', input_change);
|
||||||
|
|
||||||
@@ -282,6 +349,7 @@
|
|||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function ocr(input) {
|
function ocr(input) {
|
||||||
// Tesseract.recognize(f, "eng",{ logger: m => console.log(m) }
|
// Tesseract.recognize(f, "eng",{ logger: m => console.log(m) }
|
||||||
// ).then(({ data: { text } }) => {
|
// ).then(({ data: { text } }) => {
|
||||||
@@ -319,12 +387,17 @@
|
|||||||
await worker.loadLanguage('eng');
|
await worker.loadLanguage('eng');
|
||||||
await worker.initialize('eng');
|
await worker.initialize('eng');
|
||||||
// const { data: { text } } = await worker.recognize(input.files[0], { rectangle });
|
// const { data: { text } } = await worker.recognize(input.files[0], { rectangle });
|
||||||
const { data: { text } } = await worker.recognize(input.files[0]);
|
const {
|
||||||
|
data: {
|
||||||
|
text
|
||||||
|
}
|
||||||
|
} = await worker.recognize(input.files[0]);
|
||||||
//console.log(text);
|
//console.log(text);
|
||||||
l = text.toLowerCase();
|
l = text.toLowerCase();
|
||||||
$(`img[data-input-id='${input.id}'`).removeClass("image-ident-loading");
|
$(`img[data-input-id='${input.id}'`).removeClass("image-ident-loading");
|
||||||
console.log(l);
|
console.log(l);
|
||||||
if (l.includes("accesion") || l.includes("number") || l.search(/(ref|rk9|rh8|ra9|rbz)\d+/g) > -1) {
|
if (l.includes("accesion") || l.includes("number") || l.search(
|
||||||
|
/(ref|rk9|rh8|ra9|rbz)\d+/g) > -1) {
|
||||||
console.log("SHIT", input);
|
console.log("SHIT", input);
|
||||||
$(input).addClass("image-ident-warning");
|
$(input).addClass("image-ident-warning");
|
||||||
$(`img[data-input-id='${input.id}'`).addClass("image-ident-warning");
|
$(`img[data-input-id='${input.id}'`).addClass("image-ident-warning");
|
||||||
@@ -350,6 +423,7 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add file to the process list
|
||||||
active_file_inputs.add(el)
|
active_file_inputs.add(el)
|
||||||
const readFile = (file, el) => {
|
const readFile = (file, el) => {
|
||||||
reader(file).then(reader => {
|
reader(file).then(reader => {
|
||||||
@@ -375,6 +449,7 @@
|
|||||||
|
|
||||||
|
|
||||||
active_file_inputs.delete(el)
|
active_file_inputs.delete(el)
|
||||||
|
// Only load once all queued files have been processed
|
||||||
if (active_file_inputs.size < 1) {
|
if (active_file_inputs.size < 1) {
|
||||||
loadViewer();
|
loadViewer();
|
||||||
}
|
}
|
||||||
@@ -391,6 +466,7 @@
|
|||||||
console.log(el);
|
console.log(el);
|
||||||
if (el.files.length > 0) {
|
if (el.files.length > 0) {
|
||||||
filename = el.files[0].name;
|
filename = el.files[0].name;
|
||||||
|
// Probably no need to await here anymore
|
||||||
await readFile(el.files[0], el);
|
await readFile(el.files[0], el);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -414,7 +490,9 @@
|
|||||||
|
|
||||||
image_set = $("#image_form_set img");
|
image_set = $("#image_form_set img");
|
||||||
if (n == image_set.length) {
|
if (n == image_set.length) {
|
||||||
const event = new CustomEvent('loadDicomViewer', { "detail": image_set });
|
const event = new CustomEvent('loadDicomViewer', {
|
||||||
|
"detail": image_set
|
||||||
|
});
|
||||||
|
|
||||||
window.dispatchEvent(event);
|
window.dispatchEvent(event);
|
||||||
sortable('.sortable');
|
sortable('.sortable');
|
||||||
@@ -476,17 +554,16 @@
|
|||||||
option.appendTo($("#id_examination_to"));
|
option.appendTo($("#id_examination_to"));
|
||||||
toastr.success(`Examination set to ${option.attr('title')} from dicom data`);
|
toastr.success(`Examination set to ${option.attr('title')} from dicom data`);
|
||||||
} else {
|
} else {
|
||||||
toastr.warning(`Unable to set examination ${study_description} from dicom data (it needs creating)`);
|
toastr.warning(
|
||||||
|
`Unable to set examination ${study_description} from dicom data (it needs creating)`);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} catch (err) {
|
||||||
catch (err) {
|
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{{ form.media }}
|
{{ form.media }}
|
||||||
@@ -495,11 +572,17 @@
|
|||||||
<h2>Submit Rapid</h2>
|
<h2>Submit Rapid</h2>
|
||||||
<a href="{% url 'rapids:rapid_create_defaults' %}">Edit defaults</a>
|
<a href="{% url 'rapids:rapid_create_defaults' %}">Edit defaults</a>
|
||||||
<p>
|
<p>
|
||||||
<h3>Instructions</h3>
|
<h3>Instructions</h3>
|
||||||
Abnormality, Region and Laterality are used to categorise within the system (they are not used for marking). String
|
Abnormality, Region and Laterality are used to categorise within the system (they are not used for marking). String
|
||||||
answers that match those added below will be used for automatic marking. Multiple images can be added to a question. If
|
answers that match those added below will be used for automatic marking. Multiple images can be added to a question.
|
||||||
the feedback image box is checked they will not be displayed when taking the question.
|
If
|
||||||
|
the feedback image box is checked they will not be displayed when taking the question.
|
||||||
</p>
|
</p>
|
||||||
|
<div>
|
||||||
|
To monitor a directory select it here.<br />
|
||||||
|
<button id="directory-picker-button">Pick a directory</button>
|
||||||
|
<span id="directory-picker-display">No directory monitored</span>
|
||||||
|
</div>
|
||||||
<form action="" method="post" enctype="multipart/form-data" id="rapid-form">
|
<form action="" method="post" enctype="multipart/form-data" id="rapid-form">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<a href="/rapids/abnormality/create" id="add_abnormality" class="add-popup"
|
<a href="/rapids/abnormality/create" id="add_abnormality" class="add-popup"
|
||||||
|
|||||||
Reference in New Issue
Block a user