From c3e36bfb12018f38c2d3bc9e7faab2093eb98abd Mon Sep 17 00:00:00 2001
From: Ross
Date: Mon, 7 Aug 2023 13:42:22 +0100
Subject: [PATCH] fix a number of things
---
atlas/CaseDetail, | 0
atlas/forms.py | 6 +-
.../0008_remove_case_scrapped_case_archive.py | 22 +++
atlas/models.py | 129 ++++++++++++++++--
.../atlas/collection_case_view_take.html | 30 ++--
.../atlas/collection_take_overview.html | 6 +-
.../atlas/collection_take_start.html | 3 +
atlas/templates/atlas/index.html | 4 +
atlas/templates/atlas/selfreview_form.html | 1 +
atlas/templates/atlas/user_collections.html | 16 +++
atlas/urls.py | 21 ++-
atlas/views.py | 89 +++++++++++-
docker/docker-compose.yml | 1 +
rad/static/css/anatomy.css | 5 +
rad/urls.py | 1 +
templates/base.html | 2 +
16 files changed, 302 insertions(+), 34 deletions(-)
create mode 100644 atlas/CaseDetail,
create mode 100644 atlas/migrations/0008_remove_case_scrapped_case_archive.py
create mode 100644 atlas/templates/atlas/user_collections.html
diff --git a/atlas/CaseDetail, b/atlas/CaseDetail,
new file mode 100644
index 00000000..e69de29b
diff --git a/atlas/forms.py b/atlas/forms.py
index d65050f1..48b88594 100755
--- a/atlas/forms.py
+++ b/atlas/forms.py
@@ -583,8 +583,10 @@ class SelfReviewForm(ModelForm):
widgets = {"user_exam": HiddenInput(), "case": HiddenInput()}
def __init__(self, *args, **kwargs):
- user_exam_id = kwargs.pop("user_exam_id")
- case_id = kwargs.pop("case_id")
+ if "user_exam_id" in kwargs:
+ user_exam_id = kwargs.pop("user_exam_id")
+ if "case_id" in kwargs:
+ case_id = kwargs.pop("case_id")
ModelForm.__init__(self, *args, **kwargs)
super(SelfReviewForm, self).__init__(*args, **kwargs)
\ No newline at end of file
diff --git a/atlas/migrations/0008_remove_case_scrapped_case_archive.py b/atlas/migrations/0008_remove_case_scrapped_case_archive.py
new file mode 100644
index 00000000..07be81b5
--- /dev/null
+++ b/atlas/migrations/0008_remove_case_scrapped_case_archive.py
@@ -0,0 +1,22 @@
+# Generated by Django 4.1.4 on 2023-08-07 08:14
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('atlas', '0007_selfreview'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='case',
+ name='scrapped',
+ ),
+ migrations.AddField(
+ model_name='case',
+ name='archive',
+ field=models.BooleanField(default=False, help_text='Case has been archived, this will remain on the system but will not be shown'),
+ ),
+ ]
diff --git a/atlas/models.py b/atlas/models.py
index 78ce2a79..3afc3ce5 100644
--- a/atlas/models.py
+++ b/atlas/models.py
@@ -13,6 +13,7 @@ from django.utils import timezone
import pydicom
+import pydicom.multival
from django.core.files.storage import FileSystemStorage
from django.conf import settings
@@ -272,8 +273,9 @@ class Case(models.Model):
related_name="atlas_edited_cases",
)
- scrapped = models.BooleanField(
- default=False, help_text="Question has been scrapped and will not be shown"
+ archive = models.BooleanField(
+ default=False,
+ help_text="Case has been archived, this will remain on the system but will not be shown",
)
open_access = models.BooleanField(
@@ -325,6 +327,30 @@ class Case(models.Model):
examinations = [series.get_examination() for series in self.series.all()]
return f"{self.pk}:{self.title} {'/'.join([str(c) for c in self.condition.all()])} [{', '.join(examinations)}]"
+ def get_case_dicom_json(self):
+ series_json = []
+ for series in self.series.all():
+ series_json.append(series.get_series_dicom_json())
+
+ print(series_json)
+
+ return {
+ "studies": [
+ {
+ "StudyInstanceUID": "1.3.6.1.4.1.14519.5.2.1.6279.6001.298806137288633453246975630178",
+ "StudyDate": "20000101",
+ "StudyTime": "",
+ "PatientName": "",
+ "PatientID": "LIDC-IDRI-0001",
+ "AccessionNumber": "",
+ "PatientAge": "",
+ "PatientSex": "",
+ "series": series_json,
+ }
+ ]
+ }
+ pass
+
class SeriesImage(SeriesImageBase):
image = models.FileField(upload_to=image_directory_path)
@@ -332,6 +358,50 @@ class SeriesImage(SeriesImageBase):
"Series", related_name="images", on_delete=models.SET_NULL, null=True
)
+ def get_image_dicom_json(self):
+ try:
+ with pydicom.dcmread(self.image) as ds:
+ to_keep = [
+ "Columns",
+ "Rows",
+ "InstanceNumber",
+ "SOPClassUID",
+ "PhotometricInterpretation",
+ "BitsAllocated",
+ "BitsStored",
+ "PixelRepresentation",
+ "SamplesPerPixel",
+ "PixelSpacing",
+ "HighBit",
+ "ImageOrientationPatient",
+ "ImagePositionPatient",
+ "FrameOfReferenceUID",
+ "ImageType",
+ "Modality",
+ "SOPInstanceUID",
+ "SeriesInstanceUID",
+ "StudyInstanceUID",
+ "WindowCenter",
+ "WindowWidth",
+ "SeriesDate",
+ ]
+
+ d = {}
+
+ for key in to_keep:
+ val = ds[key].value
+
+ if type(val) == pydicom.multival.MultiValue:
+ d[key] = list(val)
+ else:
+ d[key] = val
+
+
+
+ return {"metadata": d, "url": self.image.url}
+ except FileNotFoundError:
+ return []
+
class SeriesFinding(models.Model):
series = models.ForeignKey(
@@ -411,6 +481,23 @@ class Series(SeriesBase):
"{}", self.get_absolute_url(), self.get_full_str()
)
+ def get_series_dicom_json(self):
+ instances = []
+
+ image: SeriesImage
+ for image in self.images.all():
+ instances.append(image.get_image_dicom_json())
+
+ series_json = {
+ "SeriesInstanceUID": "1.3.6.1.4.1.14519.5.2.1.6279.6001.179049373636438705059720603192",
+ "SeriesNumber": 3000566,
+ "Modality": "CT",
+ "SliceThickness": 2.5,
+ "instances": instances,
+ }
+
+ return series_json
+
class CaseCollection(ExamCollectionGenericBase):
app_name = "atlas"
@@ -522,10 +609,14 @@ class CaseCollection(ExamCollectionGenericBase):
return False
- def get_case_by_index(self, case_index:int, case_count=False) -> Case | Tuple[Case, int]:
+ def get_case_by_index(
+ self, case_index: int, case_count=False
+ ) -> Case | Tuple[Case, int]:
# Seems to be a bug when case_number is 0 or 1 the same (first) object gets returned
# forces a list fixes (but is likely inefficient)
- cases = list(self.cases.all().order_by("casedetail__sort_order").prefetch_related())
+ cases = list(
+ self.cases.all().order_by("casedetail__sort_order").prefetch_related()
+ )
try:
case = cases[case_index]
@@ -534,10 +625,20 @@ class CaseCollection(ExamCollectionGenericBase):
raise Http404(s)
if case_count:
- return case, len(cases)
+ return case, len(cases)
else:
return case
+ def get_case_take_url(self, case):
+ cases = list(
+ self.cases.all().order_by("casedetail__sort_order").prefetch_related()
+ )
+
+ return reverse(
+ "atlas:collection_case_view_take_user",
+ kwargs={"pk": self.pk, "case_number": cases.index(case)},
+ )
+
class CaseDetail(models.Model):
case = models.ForeignKey(Case, on_delete=models.CASCADE)
@@ -617,9 +718,7 @@ class SelfReview(models.Model):
review_update_date = models.DateTimeField(auto_now=True)
def get_absolute_url(self):
- return reverse(
- "atlas:collection_take_overview_user", kwargs={"pk": self.user_exam.exam.pk}
- )
+ return self.user_exam.exam.get_case_take_url(self.case)
def get_display_block(self):
html = """
@@ -628,15 +727,27 @@ class SelfReview(models.Model):
Findings:
{findings}
Interpretation:
{interpretation}
-
Date: {date}
+
Date: {date}Edit
"""
+ edit_url = reverse(
+ "atlas:self_review_update",
+ kwargs={
+ "user_exam_id": self.user_exam.pk,
+ "case_id": self.case.pk,
+ "pk": self.pk,
+ },
+ )
+ # edit_url = "TEST"
+
return format_html(
html,
comments=self.comments,
findings=self.findings,
interpretation=self.interpretation,
date=self.review_date,
+ id=self.pk,
+ edit_url=edit_url,
)
diff --git a/atlas/templates/atlas/collection_case_view_take.html b/atlas/templates/atlas/collection_case_view_take.html
index 69570af4..b8d1789f 100644
--- a/atlas/templates/atlas/collection_case_view_take.html
+++ b/atlas/templates/atlas/collection_case_view_take.html
@@ -1,6 +1,7 @@
{% extends 'atlas/base.html' %}
{% block content %}
+ Collection: {{collection}}
Case {{case_number|add:1}}
{% if show_title %}
@@ -75,6 +76,10 @@
{% endif %}
+ {% if collection.publish_results or cid_user_exam.completed %}
+
+
+ {% endif %}