diff --git a/atlas/api.py b/atlas/api.py
index 7733bfc4..0c617671 100644
--- a/atlas/api.py
+++ b/atlas/api.py
@@ -32,6 +32,11 @@ class SeriesSchema(ModelSchema):
def resolve_case_id(obj):
return [i.id for i in obj.case.all()]
+class CaseSchema(ModelSchema):
+ class Config:
+ model = Case
+ model_fields = ["id", "title"]
+
@router.post("/upload_dicom", auth=django_auth)
def upload_dicom(request, files: List[UploadedFile] = File(...)):
@@ -73,9 +78,7 @@ def uncategorised_dicoms(request):
return data
-
-@router.get("/import_dicoms", auth=django_auth, response=List[SeriesSchema])
-def import_dicoms(request):
+def import_dicoms_helper(request, case_id: int | None=None):
dicoms = UncategorisedDicom.objects.filter(user=request.user)
data = defaultdict(list)
@@ -104,16 +107,30 @@ def import_dicoms(request):
# We might only want to add the author during creation....
series.author.add(request.user)
+ if case_id is not None:
+ series.case.add(case_id)
+
for dicom, dicom_tags in data[series_uid]:
series_image = SeriesImage(image=dicom.image, series=series)
series_image.save()
- dicom.image.delete()
+ #dicom.image.delete()
dicom.delete()
series_list.append(series)
return series_list
+
+@router.get("/import_dicoms", auth=django_auth, response=List[SeriesSchema])
+def import_dicoms(request):
+
+ return import_dicoms_helper(request)
+
+@router.get("/import_dicoms/{case_id}", auth=django_auth, response=List[SeriesSchema])
+def import_dicoms_case(request, case_id: int):
+
+ return import_dicoms_helper(request, case_id=case_id)
+
@router.get("/orphan_series", auth=django_auth, response=List[SeriesSchema])
def orphan_series(request):
#print(request.user.series.filter(case=None))
@@ -137,4 +154,6 @@ def series_remove_duplicate_images(request, series_id: int):
return len(dupes)
-
+@router.get("/get_cases_user", auth=django_auth, response=List[CaseSchema])
+def get_cases_user(request):
+ return Case.objects.filter(author=request.user)
\ No newline at end of file
diff --git a/atlas/migrations/0015_alter_seriesimage_series.py b/atlas/migrations/0015_alter_seriesimage_series.py
new file mode 100644
index 00000000..c2e611cf
--- /dev/null
+++ b/atlas/migrations/0015_alter_seriesimage_series.py
@@ -0,0 +1,19 @@
+# Generated by Django 4.1.4 on 2023-08-14 12:31
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('atlas', '0014_series_series_instance_uid_alter_series_examination_and_more'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='seriesimage',
+ name='series',
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='images', to='atlas.series'),
+ ),
+ ]
diff --git a/atlas/models.py b/atlas/models.py
index b513ae05..3b4f3457 100644
--- a/atlas/models.py
+++ b/atlas/models.py
@@ -392,6 +392,7 @@ def extract_image_dicom_json_from_ds(ds, url, image_index):
else:
d[key] = val
+ # Is it worth trying on fake dicom tags?.....
if d == {}:
d["SOPInstanceUID"] = f"1.2.840.1111.{image_index}"
d["SeriesInstanceUID"] = f"1.2.840.1112.1"
@@ -402,7 +403,7 @@ def extract_image_dicom_json_from_ds(ds, url, image_index):
class SeriesImage(SeriesImageBase):
image = models.FileField(upload_to=image_directory_path)
series = models.ForeignKey(
- "Series", related_name="images", on_delete=models.SET_NULL, null=True
+ "Series", related_name="images", on_delete=models.CASCADE, null=True
)
def get_dicom_data(self):
diff --git a/atlas/templates/atlas/user_uploads.html b/atlas/templates/atlas/user_uploads.html
index ee30fdd3..c9678685 100644
--- a/atlas/templates/atlas/user_uploads.html
+++ b/atlas/templates/atlas/user_uploads.html
@@ -1,36 +1,47 @@
{% extends 'atlas/base.html' %}
{% block content %}
-
Uploaded dicoms
+ Uploaded dicoms
-
-{% if dicoms %}
-
- {% for dicom in dicoms %}
- -
- {{dicom.image}} {{dicom.get_basic_dicom_tags}}
-
- {% endfor %}
-
-
-
-
+ {% if case %}
+ Importing into case {{case}}
+ {% endif %}
-
+
+ {% if case %}
+
-
+ {% else %}
+
+ {% endif %}
+
+
+
+
{% else %}
- No uploads awaiting importing have been found.
-{% endif %}
+ No uploads awaiting importing have been found.
+ {% endif %}
-View orphan series
+ View orphan series
{% endblock %}
diff --git a/atlas/urls.py b/atlas/urls.py
index 90af8aaa..a71da05e 100755
--- a/atlas/urls.py
+++ b/atlas/urls.py
@@ -35,6 +35,7 @@ urlpatterns = [
path("collection/", views.CollectionView.as_view(), name="collection_view"),
path("collection/user", views.user_collections, name="user_collections"),
path("uploads", views.user_uploads, name="user_uploads"),
+ path("uploads/case/", views.user_uploads, name="user_uploads"),
path(
"collection/create",
views.CaseCollectionCreate.as_view(),
diff --git a/atlas/views.py b/atlas/views.py
index b9c8a66e..c11b04c6 100755
--- a/atlas/views.py
+++ b/atlas/views.py
@@ -291,18 +291,39 @@ def author_list(request):
return render(request, "atlas/author_list.html", {"authors": authors})
+
def index(request):
return render(request, "atlas/index.html", {})
+
def user_collections(request):
collections = request.user.user_casecollection_exams.all()
return render(request, "atlas/user_collections.html", {"collections": collections})
-def user_uploads(request):
+
+def user_uploads(request, case_id: int | None = None):
dicoms = UncategorisedDicom.objects.filter(user=request.user)
- return render(request, "atlas/user_uploads.html", {"dicoms": dicoms})
+ data = defaultdict(list)
+ for d in dicoms:
+ tags = d.get_basic_dicom_tags()
+
+ data[tags["SeriesInstanceUID"]].append(tags)
+
+ series_list = []
+ for series in data:
+ series_list.append((series, len(data[series]), data[series][0]))
+ print(series_list)
+
+ case = False
+ if case_id is not None:
+ case = get_object_or_404(Case, pk=case_id)
+
+ return render(
+ request, "atlas/user_uploads.html", {"series_list": series_list, "case": case}
+ )
+
class CaseDelete(RevisionMixin, AuthorOrCheckerRequiredMixin, DeleteView):
model = Case
@@ -1319,7 +1340,6 @@ def collection_take_overview(
return HttpResponse("True")
else:
raise Http404()
-
cases = collection.cases.all().order_by("casedetail__sort_order").prefetch_related()
@@ -1361,7 +1381,6 @@ def collection_take_overview(
)
-
def collection_case_view_take_user(request, pk: int, case_number: int):
return collection_case_view_take(request, pk, case_number)
@@ -1402,9 +1421,7 @@ def collection_case_view_take(
cid_user_exam.start_time = timezone.now()
cid_user_exam.save()
-
if not collection.review_only():
-
if collection.collection_type == "REP":
case_detail = CaseDetail.objects.get(case=case, collection=collection)
@@ -1419,7 +1436,6 @@ def collection_case_view_take(
if request.method == "POST":
if collection.collection_type == "REP":
-
if not collection.publish_results:
if answer:
form = ReportAnswerForm(request.POST, instance=answer)
@@ -1534,7 +1550,6 @@ def collection_case_view(request, pk, case_number):
form = None
answer = None
-
case, case_count = collection.get_case_by_index(case_number, case_count=True)
series_list = case.series.all().prefetch_related("images", "examination", "plane")
@@ -1558,11 +1573,13 @@ def collection_case_view(request, pk, case_number):
},
)
+
def case_dicom_json(request, pk):
case = get_object_or_404(Case, pk=pk)
return JsonResponse(case.get_case_dicom_json())
+
@user_is_collection_author_or_atlas_editor
def delete_collection_cid_answers(request, exam_id, cid):
collection = get_object_or_404(CaseCollection, pk=exam_id)
@@ -1755,6 +1772,7 @@ GenericExamViews = ExamViews(
CaseCollection, Case, None, CidReportAnswer, "atlas", "casecollection"
)
+
class CollectionCloneMixin:
def get_initial(self):
old_object = get_object_or_404(self.model, pk=self.kwargs["exam_id"])
@@ -1777,13 +1795,15 @@ class CollectionCloneMixin:
object.save()
return HttpResponseRedirect(object.get_absolute_url())
+
class CollectionClone(CollectionCloneMixin, CaseCollectionCreate):
"""Clone exam view"""
+
class SelfReviewDelete(DeleteView):
model = SelfReview
template_name = "confirm_delete.html"
- #success_url = reverse_lazy("atlas:finding_view")
+ # success_url = reverse_lazy("atlas:finding_view")
def get_initial(self):
user_exam_id = self.kwargs["user_exam_id"]
@@ -1806,9 +1826,8 @@ class SelfReviewDelete(DeleteView):
def get_success_url(self) -> str:
return self.user_exam.exam.get_case_take_url(self.case)
-class SelfReviewUpdate(
- UpdateView
-):
+
+class SelfReviewUpdate(UpdateView):
model = SelfReview
form_class = SelfReviewForm
@@ -1833,10 +1852,10 @@ class SelfReviewUpdate(
def get_success_url(self) -> str:
return self.user_exam.exam.get_case_take_url(self.case)
- #def get_object(self):
+ # def get_object(self):
# return self.review
# return
- #def get_initial(self):
+ # def get_initial(self):
# user_exam_id = self.kwargs["user_exam_id"]
# case_id = self.kwargs["case_id"]
@@ -1844,6 +1863,7 @@ class SelfReviewUpdate(
# self.case = get_object_or_404(Case, pk=case_id)
# return {"user_exam": user_exam_id, "case": case_id}
+
class AddSelfReview(CreateView):
model = SelfReview
form_class = SelfReviewForm
@@ -1854,7 +1874,7 @@ class AddSelfReview(CreateView):
kwargs = super(AddSelfReview, self).get_form_kwargs()
# update the kwargs for the form init method with yours
kwargs.update(self.kwargs) # self.kwargs contains all url conf params
- #kwargs.update({"user": self.request.user})
+ # kwargs.update({"user": self.request.user})
return kwargs
def get_initial(self):
@@ -1874,7 +1894,8 @@ class AddSelfReview(CreateView):
def get_success_url(self) -> str:
return self.user_exam.exam.get_case_take_url(self.case)
- #return reverse("atlas:collection_take_overview_user", kwargs={"pk": self.user_exam.collection.id })
+ # return reverse("atlas:collection_take_overview_user", kwargs={"pk": self.user_exam.collection.id })
+
# def form_valid(self, form):
# model = form.save(commit=False)
@@ -1892,7 +1913,6 @@ def uncategorised_dicoms(request):
data = []
for d in dicoms:
-
data.append((d.image.name, d.get_basic_dicom_tags()))
- return JsonResponse(data, safe=False)
\ No newline at end of file
+ return JsonResponse(data, safe=False)
diff --git a/longs/migrations/0008_alter_longseriesimage_series.py b/longs/migrations/0008_alter_longseriesimage_series.py
new file mode 100644
index 00000000..0877167b
--- /dev/null
+++ b/longs/migrations/0008_alter_longseriesimage_series.py
@@ -0,0 +1,19 @@
+# Generated by Django 4.1.4 on 2023-08-14 12:31
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('longs', '0007_longseriesimage_image_md5_hash_and_more'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='longseriesimage',
+ name='series',
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='images', to='longs.longseries'),
+ ),
+ ]
diff --git a/longs/models.py b/longs/models.py
index 2d063d86..5df6dc5b 100644
--- a/longs/models.py
+++ b/longs/models.py
@@ -354,7 +354,7 @@ def test_image_validator(file):
class LongSeriesImage(SeriesImageBase):
image = models.FileField(upload_to=image_directory_path)
series = models.ForeignKey(
- "LongSeries", related_name="images", on_delete=models.SET_NULL, null=True
+ "LongSeries", related_name="images", on_delete=models.CASCADE, null=True
)