start removing lots of print
This commit is contained in:
@@ -113,8 +113,6 @@ def get_exam_user_status_cid_user(request, exam_id: int, cid: int):
|
||||
if not exam.check_user_can_edit(request.user):
|
||||
raise HttpError(HTTPStatus.UNAUTHORIZED,"Exam author required")
|
||||
|
||||
print(exam_id, cid)
|
||||
|
||||
return exam.exam_user_status.filter(cid_user_exam__cid_user__cid=cid)
|
||||
|
||||
@router.get('/exam/{exam_id}/user_status/{user_id}/user', response=List[ExamStatusSchema])
|
||||
|
||||
@@ -492,7 +492,6 @@ class Exam(ExamBase):
|
||||
return answer
|
||||
|
||||
def get_question_user_user_answer(self, question_index, user):
|
||||
print(user)
|
||||
question = self.get_question_by_index(question_index)
|
||||
answer = UserAnswer.objects.filter(question=question, user=user.pk, exam=self)
|
||||
|
||||
|
||||
@@ -194,8 +194,6 @@ def test_exams(db, client):
|
||||
exam.save()
|
||||
|
||||
res = client.get(exam_metadata["url"])
|
||||
print("PRE ERRER", exam_metadata["url"])
|
||||
print(res.content)
|
||||
assert res.status_code == 404
|
||||
|
||||
exam.active = True
|
||||
|
||||
@@ -646,22 +646,6 @@ class AnatomyQuestionUpdate(UpdateQuestionMixin):
|
||||
context = self.get_context_data(form=form)
|
||||
#formset = context["answer_formset"]
|
||||
return super().form_valid(form)
|
||||
## logger.debug(formset.is_valid())
|
||||
#if formset.is_valid():
|
||||
# response = super().form_valid(form)
|
||||
# formset.instance = self.object
|
||||
# formset.save()
|
||||
|
||||
# # restore exam orders
|
||||
# #for exam in self.object.exams.all():
|
||||
# # if exam in exam_orders and self.object in exam_orders[exam]:
|
||||
# # print(exam_orders[exam])
|
||||
# # exam.exam_questions.set(exam_orders[exam])
|
||||
# # exam.save()
|
||||
|
||||
# return response
|
||||
#else:
|
||||
# return super().form_invalid(form)
|
||||
|
||||
|
||||
class QuestionClone(AnatomyQuestionCreateBase):
|
||||
@@ -797,7 +781,6 @@ def question_save_annotation(request, pk):
|
||||
question = get_object_or_404(AnatomyQuestion, pk=pk)
|
||||
|
||||
question.image_annotations = request.POST.get("annotation")
|
||||
print(question.image_annotations)
|
||||
|
||||
question.save()
|
||||
data = {"status": "success"}
|
||||
|
||||
+54
-68
@@ -128,15 +128,10 @@ def uncategorised_dicoms(request):
|
||||
|
||||
|
||||
def import_dicoms_helper(request, case_id: int | None = None):
|
||||
# TODO: move this out of the api (would be better with HTMX)
|
||||
|
||||
|
||||
# dicoms = UncategorisedDicom.objects.filter(user=request.user)
|
||||
if "selection" in request.POST:
|
||||
dicoms = UncategorisedDicom.objects.filter(
|
||||
series_instance_uid__in=request.POST.getlist("selection")
|
||||
)
|
||||
|
||||
else:
|
||||
dicoms = UncategorisedDicom.objects.filter(user=request.user)
|
||||
|
||||
@@ -145,73 +140,66 @@ def import_dicoms_helper(request, case_id: int | None = None):
|
||||
else:
|
||||
order = None
|
||||
|
||||
data = defaultdict(list)
|
||||
for d in dicoms:
|
||||
# Group dicoms by SeriesInstanceUID, but don't keep all tags in memory
|
||||
series_map = {}
|
||||
for d in dicoms.iterator(): # Use iterator() to avoid loading all at once
|
||||
tags = d.basic_dicom_tags
|
||||
series_uid = tags["SeriesInstanceUID"]
|
||||
|
||||
data[tags["SeriesInstanceUID"]].append((d, tags))
|
||||
|
||||
series_list = []
|
||||
for series_uid in data:
|
||||
# Hmm probably not a good idea to blinding create a modality...
|
||||
try:
|
||||
modality = Modality.objects.get(short_code=tags["Modality"])
|
||||
except Modality.DoesNotExist:
|
||||
modality = Modality.objects.create(short_code=tags["Modality"], modality=tags["Modality"])
|
||||
|
||||
|
||||
tags = data[series_uid][0][1]
|
||||
|
||||
try:
|
||||
with transaction.atomic():
|
||||
series, created = Series.objects.get_or_create(
|
||||
series_instance_uid=tags["SeriesInstanceUID"],
|
||||
defaults={
|
||||
"modality": modality,
|
||||
"description": tags["SeriesDescription"],
|
||||
}
|
||||
)
|
||||
if created and tags["StudyDescription"]:
|
||||
examination, created_exam = Examination.objects.get_or_create(
|
||||
examination=tags["StudyDescription"]
|
||||
)
|
||||
if created_exam:
|
||||
examination.modality = modality
|
||||
examination.save()
|
||||
series.examination = examination
|
||||
series.save()
|
||||
except IntegrityError:
|
||||
# If a race condition still occurs, fetch the existing series
|
||||
pass
|
||||
|
||||
|
||||
if 'series' not in locals():
|
||||
series = Series.objects.get(series_instance_uid=tags["SeriesInstanceUID"])
|
||||
|
||||
|
||||
# We might only want to add the author during creation....
|
||||
series.author.add(request.user)
|
||||
|
||||
if case_id is not None:
|
||||
case_object = get_object_or_404(Case, pk=case_id)
|
||||
if series_uid not in series_map:
|
||||
# Get or create Series and related objects as needed
|
||||
try:
|
||||
series.case.add(case_object)
|
||||
modality = Modality.objects.get(short_code=tags["Modality"])
|
||||
except Modality.DoesNotExist:
|
||||
modality = Modality.objects.create(short_code=tags["Modality"], modality=tags["Modality"])
|
||||
|
||||
series_tags = tags # Save the first tag for this series
|
||||
try:
|
||||
with transaction.atomic():
|
||||
series, created = Series.objects.get_or_create(
|
||||
series_instance_uid=series_uid,
|
||||
defaults={
|
||||
"modality": modality,
|
||||
"description": tags.get("SeriesDescription", ""),
|
||||
}
|
||||
)
|
||||
if created and tags.get("StudyDescription"):
|
||||
examination, created_exam = Examination.objects.get_or_create(
|
||||
examination=tags["StudyDescription"]
|
||||
)
|
||||
if created_exam:
|
||||
examination.modality = modality
|
||||
examination.save()
|
||||
series.examination = examination
|
||||
series.save()
|
||||
except IntegrityError:
|
||||
# The relation already exists, safe to ignore
|
||||
pass
|
||||
series = Series.objects.get(series_instance_uid=series_uid)
|
||||
|
||||
for dicom, dicom_tags in data[series_uid]:
|
||||
series_image = SeriesImage(
|
||||
image=dicom.image,
|
||||
series=series,
|
||||
is_dicom=True,
|
||||
image_blake3_hash=dicom.image_blake3_hash,
|
||||
)
|
||||
series_image.save()
|
||||
# dicom.image.delete()
|
||||
# Add author and case if needed
|
||||
series.author.add(request.user)
|
||||
if case_id is not None:
|
||||
case_object = get_object_or_404(Case, pk=case_id)
|
||||
try:
|
||||
series.case.add(case_object)
|
||||
except IntegrityError:
|
||||
pass
|
||||
|
||||
dicom.delete()
|
||||
series_map[series_uid] = series
|
||||
else:
|
||||
series = series_map[series_uid]
|
||||
|
||||
# Create and save SeriesImage immediately
|
||||
series_image = SeriesImage(
|
||||
image=d.image,
|
||||
series=series,
|
||||
is_dicom=True,
|
||||
image_blake3_hash=d.image_blake3_hash,
|
||||
)
|
||||
series_image.save()
|
||||
d.delete() # Remove UncategorisedDicom immediately
|
||||
|
||||
# Optionally, re-order series if needed
|
||||
for series in series_map.values():
|
||||
match order:
|
||||
case "order-series-instance-number":
|
||||
series.order_by_dicom("InstanceNumber")
|
||||
@@ -219,10 +207,8 @@ def import_dicoms_helper(request, case_id: int | None = None):
|
||||
series.order_by_dicom("SliceLocation")
|
||||
case _:
|
||||
pass
|
||||
|
||||
series_list.append((series, series.get_link()))
|
||||
|
||||
return series_list
|
||||
return [(series, series.get_link()) for series in series_map.values()]
|
||||
|
||||
|
||||
@router.post(
|
||||
|
||||
@@ -84,9 +84,6 @@ class CaseSelect(Select):
|
||||
def create_option(self, *args, **kwargs):
|
||||
option = super().create_option(*args, **kwargs)
|
||||
|
||||
print(option)
|
||||
|
||||
|
||||
return option
|
||||
|
||||
def get_context(self, name: str, value, attrs) -> dict[str, Any]:
|
||||
@@ -694,7 +691,6 @@ class CidReportAnswerMarkForm(ModelForm):
|
||||
#
|
||||
# def __init__(self, *args, user, **kwargs):
|
||||
# super(AddCollectionToCaseForm, self).__init__(*args, **kwargs)
|
||||
# print("INIT", args, kwargs)
|
||||
#
|
||||
# if not user.groups.filter(name="atlas_editor").exists():
|
||||
# queryset = CaseCollection.objects.filter(author__id=user.id)
|
||||
@@ -736,7 +732,6 @@ class AddCollectionToCaseForm(Form):
|
||||
|
||||
def __init__(self, *args, user, **kwargs):
|
||||
super(AddCollectionToCaseForm, self).__init__(*args, **kwargs)
|
||||
print("INIT", args, kwargs)
|
||||
|
||||
if not user.groups.filter(name="atlas_editor").exists():
|
||||
queryset = CaseCollection.objects.filter(author__id=user.id)
|
||||
@@ -752,21 +747,16 @@ class AddCollectionToCaseForm(Form):
|
||||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
print("SAVE", args, kwargs)
|
||||
instance = super(AddCollectionToCaseForm, self).save(*args, **kwargs)
|
||||
|
||||
# Here we save the modified project selection back into the database
|
||||
instance.casecollection_set.set(self.cleaned_data['casecollection'])
|
||||
|
||||
print(f"{instance=}")
|
||||
|
||||
return instance
|
||||
|
||||
def clean_casecollection(self):
|
||||
collection_set = self.cleaned_data["casecollection"]
|
||||
|
||||
print(f"{collection_set=}")
|
||||
|
||||
for col in collection_set:
|
||||
if col not in self.valid_collections:
|
||||
raise ValidationError("Invalid collection")
|
||||
|
||||
@@ -1215,10 +1215,7 @@ class BaseReportAnswer(models.Model):
|
||||
if self.question.question_schema is None or not "properties" in self.question.question_schema:
|
||||
return []
|
||||
answers = []
|
||||
print("1", self.json_answer)
|
||||
print("2", self.question.question_answers)
|
||||
for name, value in self.question.question_schema["properties"].items():
|
||||
print(name, value)
|
||||
|
||||
try:
|
||||
user_answer = self.json_answer[name]
|
||||
@@ -1229,11 +1226,8 @@ class BaseReportAnswer(models.Model):
|
||||
except KeyError: # If the schema has changed?
|
||||
correct_answer = ""
|
||||
|
||||
print(correct_answer)
|
||||
|
||||
match value:
|
||||
case {"type": "string", "enum": _}:
|
||||
print("YES", value)
|
||||
automark = True
|
||||
answer_is_correct = user_answer == correct_answer
|
||||
case {"type": "string"}:
|
||||
@@ -1366,8 +1360,6 @@ class UncategorisedDicom(models.Model):
|
||||
# duplicate = obj
|
||||
return obj
|
||||
|
||||
print(image_hash)
|
||||
|
||||
if obj := SeriesImage.objects.filter(image_blake3_hash=image_hash).first():
|
||||
duplicate = obj
|
||||
|
||||
@@ -1409,8 +1401,6 @@ class UncategorisedDicom(models.Model):
|
||||
ds = pydicom.dcmread(self.image)
|
||||
return ds
|
||||
except pydicom.errors.InvalidDicomError:
|
||||
print("Error getting dicom dataset")
|
||||
print(self.image)
|
||||
return {"SeriesInstanceUID": "1234"}
|
||||
|
||||
def get_basic_dicom_tags(self, dataset=None):
|
||||
|
||||
@@ -196,11 +196,6 @@ class PopupLinkColumn(tables.Column):
|
||||
return obj.get_thumbnail()[0]
|
||||
|
||||
|
||||
def create_link(test):
|
||||
print(test)
|
||||
return "Hello"
|
||||
|
||||
|
||||
class SeriesTable(tables.Table):
|
||||
edit = tables.LinkColumn(
|
||||
"atlas:series_update", text="Edit", args=[A("pk")], orderable=False
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
{% endif %}
|
||||
<details><summary>Upload settings</summary>
|
||||
<form>
|
||||
<div>
|
||||
<fieldset><legend>Select how series should be ordered when uploaded</legend>
|
||||
<div>
|
||||
<fieldset><legend>Select how series should be ordered when uploaded</legend>
|
||||
<div class="helptext">
|
||||
This will affect how series are displayed when viewing with the built in site viewer. By default when exporting from Insight the order is not maintained so you should choose to order either by slice location or instance number.<br/>
|
||||
If you are not sure, leave this as the default.
|
||||
@@ -57,8 +57,8 @@
|
||||
<input type="radio" id="order-series-none" value="order-series-none" name="order-series" >
|
||||
<label for="order-series-none">None</label><br/>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</form>
|
||||
</details>
|
||||
|
||||
@@ -69,15 +69,15 @@
|
||||
title="Deleted selected uploads"
|
||||
>Delete Uploads</button>
|
||||
|
||||
<button id="import-dicoms-sequential-button"
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
>Import {% if case %}into case{% endif %} (one at a time)</button>
|
||||
<button id="import-dicoms-sequential-button"
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
>Import {% if case %}into case{% endif %} (one at a time)</button>
|
||||
|
||||
<div id="import-status"></div>
|
||||
<div id="import-status"></div>
|
||||
|
||||
<div class="indicator"><div class="loader"></div>Loading...</div>
|
||||
<div id="import-status"></div>
|
||||
<div id="import-status"></div>
|
||||
|
||||
<div class="imported">
|
||||
|
||||
@@ -89,136 +89,138 @@
|
||||
|
||||
<p><a href="{% url 'atlas:series_view' %}?case=null&sort=-modified_date">View orphan series</a></p>
|
||||
|
||||
<script>
|
||||
document.getElementById('import-dicoms-sequential-button').addEventListener('click', async function() {
|
||||
const checkboxes = Array.from(document.querySelectorAll('input[name="selection"]:checked'));
|
||||
const allCheckboxes = Array.from(document.querySelectorAll('input[name="selection"]'));
|
||||
<script>
|
||||
const importButton = document.getElementById('import-dicoms-sequential-button');
|
||||
if (importButton) {
|
||||
document.getElementById('import-dicoms-sequential-button').addEventListener('click', async function() {
|
||||
const checkboxes = Array.from(document.querySelectorAll('input[name="selection"]:checked'));
|
||||
const allCheckboxes = Array.from(document.querySelectorAll('input[name="selection"]'));
|
||||
// Only include checkboxes that are not disabled (i.e., not already imported)
|
||||
const selectableCheckboxes = allCheckboxes.filter(cb => !cb.disabled);
|
||||
const toImport = checkboxes.length
|
||||
? checkboxes.filter(cb => !cb.disabled)
|
||||
: selectableCheckboxes;
|
||||
if (toImport.length === 0) {
|
||||
alert("Please select at least one series to import (not already imported).");
|
||||
return;
|
||||
}
|
||||
const statusDiv = document.getElementById('import-status');
|
||||
statusDiv.innerHTML = '';
|
||||
const orderSeries = document.querySelector('input[name="order-series"]:checked').value;
|
||||
const csrfToken = '{{ csrf_token }}';
|
||||
{% if case %}
|
||||
const importUrl = "{% url 'api-1:import_dicoms_case' case.id %}";
|
||||
{% else %}
|
||||
const importUrl = "{% url 'api-1:import_dicoms' %}";
|
||||
{% endif %}
|
||||
for (let i = 0; i < toImport.length; i++) {
|
||||
const seriesId = toImport[i].value;
|
||||
statusDiv.innerHTML += `<div id="import-status-${seriesId}">Importing series ${seriesId}...</div>`;
|
||||
try {
|
||||
const response = await fetch(importUrl, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"X-CSRFToken": csrfToken,
|
||||
},
|
||||
body: `selection=${encodeURIComponent(seriesId)}&order-series=${encodeURIComponent(orderSeries)}`
|
||||
});
|
||||
const text = await response.text();
|
||||
document.getElementById(`import-status-${seriesId}`).innerHTML = `Series ${seriesId}: ${text}`;
|
||||
const selectableCheckboxes = allCheckboxes.filter(cb => !cb.disabled);
|
||||
const toImport = checkboxes.length
|
||||
? checkboxes.filter(cb => !cb.disabled)
|
||||
: selectableCheckboxes;
|
||||
if (toImport.length === 0) {
|
||||
alert("Please select at least one series to import (not already imported).");
|
||||
return;
|
||||
}
|
||||
const statusDiv = document.getElementById('import-status');
|
||||
statusDiv.innerHTML = '';
|
||||
const orderSeries = document.querySelector('input[name="order-series"]:checked').value;
|
||||
const csrfToken = '{{ csrf_token }}';
|
||||
{% if case %}
|
||||
const importUrl = "{% url 'api-1:import_dicoms_case' case.id %}";
|
||||
{% else %}
|
||||
const importUrl = "{% url 'api-1:import_dicoms' %}";
|
||||
{% endif %}
|
||||
for (let i = 0; i < toImport.length; i++) {
|
||||
const seriesId = toImport[i].value;
|
||||
statusDiv.innerHTML += `<div id="import-status-${seriesId}">Importing series ${seriesId}...</div>`;
|
||||
try {
|
||||
const response = await fetch(importUrl, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"X-CSRFToken": csrfToken,
|
||||
},
|
||||
body: `selection=${encodeURIComponent(seriesId)}&order-series=${encodeURIComponent(orderSeries)}`
|
||||
});
|
||||
const text = await response.text();
|
||||
document.getElementById(`import-status-${seriesId}`).innerHTML = `Series ${seriesId}: ${text}`;
|
||||
// Mark as imported in the UI and make unselectable
|
||||
const li = document.querySelector(`#series-list input[value="${seriesId}"]`)?.closest('li');
|
||||
if (li && !li.classList.contains('imported')) {
|
||||
li.classList.add('imported');
|
||||
const li = document.querySelector(`#series-list input[value="${seriesId}"]`)?.closest('li');
|
||||
if (li && !li.classList.contains('imported')) {
|
||||
li.classList.add('imported');
|
||||
// Add badge if not already present
|
||||
if (!li.querySelector('.badge.bg-success')) {
|
||||
const badge = document.createElement('span');
|
||||
badge.className = 'badge bg-success ms-2';
|
||||
badge.textContent = 'Imported';
|
||||
li.appendChild(badge);
|
||||
}
|
||||
if (!li.querySelector('.badge.bg-success')) {
|
||||
const badge = document.createElement('span');
|
||||
badge.className = 'badge bg-success ms-2';
|
||||
badge.textContent = 'Imported';
|
||||
li.appendChild(badge);
|
||||
}
|
||||
// Disable checkbox and prevent further selection
|
||||
const checkbox = li.querySelector('input[name="selection"]');
|
||||
if (checkbox) {
|
||||
checkbox.disabled = true;
|
||||
checkbox.checked = false;
|
||||
}
|
||||
const checkbox = li.querySelector('input[name="selection"]');
|
||||
if (checkbox) {
|
||||
checkbox.disabled = true;
|
||||
checkbox.checked = false;
|
||||
}
|
||||
// Remove click handler for selection
|
||||
li.querySelector('span').onclick = null;
|
||||
li.style.pointerEvents = "none";
|
||||
li.style.opacity = "0.7";
|
||||
}
|
||||
} catch (e) {
|
||||
document.getElementById(`import-status-${seriesId}`).innerHTML = `Series ${seriesId}: <span style="color:red;">Failed</span>`;
|
||||
li.querySelector('span').onclick = null;
|
||||
li.style.pointerEvents = "none";
|
||||
li.style.opacity = "0.7";
|
||||
}
|
||||
} catch (e) {
|
||||
document.getElementById(`import-status-${seriesId}`).innerHTML = `Series ${seriesId}: <span style="color:red;">Failed</span>`;
|
||||
}
|
||||
}
|
||||
statusDiv.innerHTML += "<div>All done.</div>";
|
||||
});
|
||||
}
|
||||
}
|
||||
statusDiv.innerHTML += "<div>All done.</div>";
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block css %}
|
||||
<style>
|
||||
.indicator {
|
||||
display: none;
|
||||
}
|
||||
<style>
|
||||
.indicator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.indicator.htmx-request {
|
||||
display: block;
|
||||
}
|
||||
.indicator.htmx-request {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.loader {
|
||||
width: 50px;
|
||||
aspect-ratio: 1;
|
||||
display: grid;
|
||||
}
|
||||
.loader::before,
|
||||
.loader::after {
|
||||
content:"";
|
||||
grid-area: 1/1;
|
||||
--c:no-repeat radial-gradient(farthest-side,#25b09b 92%,#0000);
|
||||
background:
|
||||
var(--c) 50% 0,
|
||||
var(--c) 50% 100%,
|
||||
var(--c) 100% 50%,
|
||||
var(--c) 0 50%;
|
||||
background-size: 12px 12px;
|
||||
animation: l12 1s infinite;
|
||||
}
|
||||
.loader::before {
|
||||
margin: 4px;
|
||||
filter: hue-rotate(45deg);
|
||||
background-size: 8px 8px;
|
||||
animation-timing-function: linear
|
||||
}
|
||||
.loader {
|
||||
width: 50px;
|
||||
aspect-ratio: 1;
|
||||
display: grid;
|
||||
}
|
||||
.loader::before,
|
||||
.loader::after {
|
||||
content:"";
|
||||
grid-area: 1/1;
|
||||
--c:no-repeat radial-gradient(farthest-side,#25b09b 92%,#0000);
|
||||
background:
|
||||
var(--c) 50% 0,
|
||||
var(--c) 50% 100%,
|
||||
var(--c) 100% 50%,
|
||||
var(--c) 0 50%;
|
||||
background-size: 12px 12px;
|
||||
animation: l12 1s infinite;
|
||||
}
|
||||
.loader::before {
|
||||
margin: 4px;
|
||||
filter: hue-rotate(45deg);
|
||||
background-size: 8px 8px;
|
||||
animation-timing-function: linear
|
||||
}
|
||||
|
||||
@keyframes l12 {
|
||||
100%{transform: rotate(.5turn)}
|
||||
}
|
||||
@keyframes l12 {
|
||||
100%{transform: rotate(.5turn)}
|
||||
}
|
||||
|
||||
#series-list {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
#series-list {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#series-list li {
|
||||
}
|
||||
#series-list .selected {
|
||||
color: white;
|
||||
border: 1px solid #52057b;
|
||||
user-select: none;
|
||||
margin: -1px;
|
||||
#series-list li {
|
||||
}
|
||||
#series-list .selected {
|
||||
color: white;
|
||||
border: 1px solid #52057b;
|
||||
user-select: none;
|
||||
margin: -1px;
|
||||
|
||||
}
|
||||
.series-block-popup-link {
|
||||
float: right;
|
||||
}
|
||||
#series-list li.imported {
|
||||
border-color: #e6ffe6;
|
||||
opacity: 0.7;
|
||||
}
|
||||
</style>
|
||||
|
||||
}
|
||||
.series-block-popup-link {
|
||||
float: right;
|
||||
}
|
||||
#series-list li.imported {
|
||||
border-color: #e6ffe6;
|
||||
opacity: 0.7;
|
||||
}
|
||||
</style>
|
||||
|
||||
{% endblock css %}
|
||||
|
||||
@@ -37,7 +37,6 @@ def test_condition_tree_structure(db):
|
||||
assert len(child2.get_parents()) == 1
|
||||
assert parent in child2.get_parents()
|
||||
|
||||
print(parent.get_descendents())
|
||||
|
||||
#@pytest.fixture
|
||||
#def create_basic_user(db, django_user_model):
|
||||
|
||||
@@ -568,7 +568,6 @@ class SeriesBase(models.Model):
|
||||
n = n + 1
|
||||
|
||||
def order_by_dicom(self, field="SliceLocation"):
|
||||
print(f"Ordering by dicom field {field}")
|
||||
images = self.images.filter(removed=False)
|
||||
|
||||
|
||||
@@ -577,9 +576,6 @@ class SeriesBase(models.Model):
|
||||
for i in images:
|
||||
files.append((i, pydicom.dcmread(i.image.path)))
|
||||
|
||||
print("images to order")
|
||||
print(files)
|
||||
|
||||
# print("file count: {}".format(len(files)))
|
||||
|
||||
# skip files with no SliceLocation (eg scout views)
|
||||
@@ -594,8 +590,6 @@ class SeriesBase(models.Model):
|
||||
else:
|
||||
skipcount = skipcount + 1
|
||||
|
||||
print("skipped, no {}: {}".format(field, skipcount))
|
||||
|
||||
if not slices:
|
||||
return
|
||||
|
||||
@@ -607,7 +601,6 @@ class SeriesBase(models.Model):
|
||||
for f in slices:
|
||||
i = map[f[field].value]
|
||||
i.position = n
|
||||
print(f"Setting position {n} for {i}")
|
||||
i.save()
|
||||
n = n + 1
|
||||
|
||||
|
||||
+1
-11
@@ -93,38 +93,29 @@ def get_dicom_order(path):
|
||||
files = []
|
||||
|
||||
for fname in glob.glob(path, recursive=False):
|
||||
print("loading: {}".format(fname))
|
||||
files.append((fname, pydicom.dcmread(fname)))
|
||||
|
||||
print("file count: {}".format(len(files)))
|
||||
|
||||
# skip files with no SliceLocation (eg scout views)
|
||||
slices = []
|
||||
map = {}
|
||||
skipcount = 0
|
||||
for fname, f in files:
|
||||
print(dir(f))
|
||||
print(fname)
|
||||
if hasattr(f, 'SliceLocation'):
|
||||
slices.append(f)
|
||||
map[f.SliceLocation] = fname
|
||||
else:
|
||||
skipcount = skipcount + 1
|
||||
|
||||
print("skipped, no SliceLocation: {}".format(skipcount))
|
||||
|
||||
# ensure they are in the correct order
|
||||
slices = sorted(slices, key=lambda s: s.SliceLocation)
|
||||
|
||||
#print(slices)
|
||||
for i in slices:
|
||||
print(map[i.SliceLocation])
|
||||
return slices
|
||||
|
||||
#get_dicom_order("/home/ross/Downloads/DICOM HEAD/STD4/SER1/*.dcm")
|
||||
|
||||
def pretty_print_dicom(dataset, indent=0):
|
||||
l = print_dicom(dataset, indent)
|
||||
print(l)
|
||||
return "".join(l)
|
||||
|
||||
|
||||
@@ -183,7 +174,6 @@ def get_image_dicom_hash(img, dataset=None, hash_type="md5", direct_pixel_data=T
|
||||
hasher.update(dataset.PixelData)
|
||||
except AttributeError as e:
|
||||
print("Error getting pixel data hash from dataset")
|
||||
print(dataset)
|
||||
raise InvalidDicomError("Error getting pixel data hash from dataset")
|
||||
|
||||
else:
|
||||
|
||||
@@ -11,7 +11,6 @@ if __name__ == "__main__":
|
||||
if os.environ.get('RUN_MAIN'):
|
||||
if settings.DEBUG_CONTAINER:
|
||||
import debugpy
|
||||
print("DEBUG LISTEN")
|
||||
debugpy.listen(("0.0.0.0", 3459))
|
||||
|
||||
try:
|
||||
|
||||
+146
-146
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user