import json import pprint from dal import autocomplete from django.shortcuts import render, get_object_or_404, redirect from django import forms from django.utils import timezone # from django.contrib.auth.models import User from django.contrib.auth.decorators import login_required, user_passes_test from django.contrib.auth.models import User from django.core.exceptions import ( FieldError, ObjectDoesNotExist, PermissionDenied, ViewDoesNotExist, ) from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin from django.views.generic import View from django.views.generic.detail import DetailView import pydicom from generic.mixins import SuperuserRequiredMixin from django.views.generic.edit import CreateView, UpdateView, DeleteView, FormView from django.views.generic import ListView from django.views.decorators.csrf import csrf_exempt from django.urls import reverse_lazy, reverse from django.http import Http404, JsonResponse from django.http import HttpResponseRedirect, HttpResponse from generic.models import CidUser, CidUserExam from .forms import ( AddCollectionToCaseForm, CaseCollectionCaseFormSet, CaseCollectionForm, CaseForm, CidReportAnswerForm, CidReportAnswerMarkForm, ConditionAutocompleteForm, ConditionForm, FindingForm, SelfReviewForm, SeriesForm, SeriesImageFormSet, SeriesFormSet, SeriesFindingForm, CaseDifferentialFormSet, StructureForm, UserReportAnswerForm, ) from .models import ( Case, CaseCollection, CaseDetail, CidReportAnswer, Condition, Differential, PathologicalProcess, Presentation, SelfReview, Series, Examination, Finding, Structure, Subspecialty, SeriesFinding, SeriesImage, UncategorisedDicom, UserReportAnswer, ) from .tables import ( CaseCollectionTable, CaseTable, ConditionTable, FindingTable, PathologicalProcessTable, PresentationTable, SeriesTable, StructureTable, SubspecialtyTable, ) from .filters import ( CaseCollectionFilter, CaseFilter, ConditionFilter, FindingFilter, PathologicalProcessFilter, PresentationFilter, SeriesFilter, StructureFilter, SubspecialtyFilter, ) from django_tables2 import SingleTableView, SingleTableMixin from django_filters.views import FilterView from autocomplete import HTMXAutoComplete from .decorators import ( user_is_author_or_atlas_editor, user_has_case_view_access, user_is_author_or_atlas_series_checker_or_atlas_marker, user_is_atlas_editor, user_is_author_or_atlas_series_checker, user_is_atlas_marker, user_is_collection_author_or_atlas_editor, ) from collections import defaultdict import json import statistics import plotly.express as px from django.core.cache import cache from django.conf import settings from helpers.images import compare_dicom_datasets, image_as_base64, print_dicom import logging from copy import deepcopy from django.forms.models import model_to_dict from generic.views import ExamCloneMixin, ExamViews, SeriesImagesZipViewBase from reversion.views import RevisionMixin import reversion from rest_framework import viewsets import os import difflib logger = logging.getLogger(__name__) def get_cases_available_to_user(user): """Returns a queryset of cases available to the user""" return Case.objects.filter(author=user) | Case.objects.filter(open_access=True) if user.is_superuser: return Case.objects.all() else: return Case.objects.filter(author=user) | Case.objects.filter(open_access=True) class AuthorOrCheckerRequiredMixin(object): def get_object(self, *args, **kwargs): obj = super().get_object(*args, **kwargs) if ( self.request.user.groups.filter(name="atlas_editor").exists() or self.request.user.is_superuser ): return obj if self.request.user not in obj.get_author_objects(): raise PermissionDenied() # or Http404 return obj class AtlasEditorRequiredMixin(object): def get_object(self, *args, **kwargs): obj = super().get_object(*args, **kwargs) if ( self.request.user.groups.filter(name="atlas_editor").exists() or self.request.user.is_superuser ): return obj raise PermissionDenied("You must be an atlas editor to do this.") # or Http404 @login_required @user_has_case_view_access def case_detail(request, pk): case = get_object_or_404(Case, pk=pk) # if request.user not in atlas.author.all(): # raise PermissionDenied # logging.debug(atlas.subspecialty.first().name.all()) return render(request, "atlas/case_detail.html", {"case": case}) @login_required @user_is_author_or_atlas_series_checker_or_atlas_marker def series_detail(request, pk, finding_pk=None): series = get_object_or_404(Series, pk=pk) editing_finding = -1 if finding_pk is not None: finding = get_object_or_404(SeriesFinding, pk=finding_pk) series_finding_form = SeriesFindingForm(None, instance=finding) editing_finding = finding.pk else: series_finding_form = SeriesFindingForm(series_id=series.id) # logging.debug(atlas.subspecialty.first().name.all()) return render( request, "atlas/series.html", { "series": series, "series_finding_form": series_finding_form, "editing_finding": editing_finding, }, ) @login_required #@user_is_atlas_editor def condition_detail(request, pk): condition = get_object_or_404(Condition, pk=pk) form = ConditionAutocompleteForm() can_merge = False if request.user.is_superuser or request.user.groups.filter(name="atlas_editor").exists(): can_merge = True # logging.debug(atlas.subspecialty.first().name.all()) return render( request, "atlas/condition_detail.html", {"condition": condition, "form": form, "can_merge": can_merge}, ) # class GetConditionAutocomplete(HTMXAutoComplete): # name = "conditions" # multiselect = False # # class Meta: # model = Condition @login_required @user_is_atlas_editor def condition_merge(request, pk_to_merge): if not request.htmx: raise Http404 condition_to_merge = get_object_or_404(Condition, pk=pk_to_merge) # condition_to_merge_into = get_object_or_404(Condition, pk=pk_to_merge_into) print(condition_to_merge.case_set) if condition_to_merge.rcr_curriculum: return HttpResponse("You cannot merge rcr curriculum items") condition_to_merge_into = request.POST.get("conditions") if not condition_to_merge_into: return HttpResponse("You need to select a condition to merge into.") condition_to_merge_into = get_object_or_404(Condition, pk=condition_to_merge_into) if condition_to_merge == condition_to_merge_into: return HttpResponse("You cannot merge into the same condition.") # move all relevant relationships cases = condition_to_merge.case_set.all().values_list("id", flat=True) condition_to_merge_into.case_set.add(cases) # cases = Case.objects.filter(condition=condition_to_merge) # cases.update(condition=condition_to_merge_into) differentials = Differential.objects.filter(condition=condition_to_merge) differentials.update(condition=condition_to_merge_into) return HttpResponse("Merged") # conditions = Condition.objects.all() # return render(request, "atlas/condition_options.html", {"conditions": conditions}) @login_required #@user_is_atlas_editor def subspecialty_detail(request, pk): subspecialty = get_object_or_404(Subspecialty, pk=pk) # logging.debug(atlas.subspecialty.first().name.all()) return render( request, "atlas/subspecialty_detail.html", { "subspecialty": subspecialty, }, ) @login_required #@user_is_atlas_editor def presentation_detail(request, pk): presentation = get_object_or_404(Presentation, pk=pk) # logging.debug(atlas.subspecialty.first().name.all()) return render( request, "atlas/presentation_detail.html", { "presentation": presentation, }, ) @login_required #@user_is_atlas_editor def pathological_process_detail(request, pk): pathological_process = get_object_or_404(PathologicalProcess, pk=pk) # logging.debug(atlas.subspecialty.first().name.all()) return render( request, "atlas/pathological_process_detail.html", { "pathological_process": pathological_process, }, ) @login_required #@user_is_atlas_editor def structure_detail(request, pk): structure = get_object_or_404(Structure, pk=pk) # logging.debug(atlas.subspecialty.first().name.all()) return render( request, "atlas/structure_detail.html", { "structure": structure, }, ) @login_required #@user_is_atlas_editor def finding_detail(request, pk): finding = get_object_or_404(Finding, pk=pk) # logging.debug(atlas.subspecialty.first().name.all()) return render( request, "atlas/finding_detail.html", { "finding": finding, }, ) @login_required def author_detail(request, pk): # logging.debug(Author.objects.all()) # author = get_object_or_404(Author, pk=pk) author = User.objects.get(pk=pk) if request.user.pk == pk: atlas = Case.objects.filter(author=pk) else: atlas = Case.objects.filter(author=pk, open_access=True) return render( request, "atlas/category_detail.html", {"category": author, "atlas": atlas} ) @user_is_author_or_atlas_editor def author_list(request): authors = User.objects.all() 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 add_case_to_collection(request, collection_id): if not request.htmx: return Http404 collection = get_object_or_404(CaseCollection, pk=collection_id) if request.method == "POST": case = get_object_or_404(Case, pk=request.POST["case"]) print(case) collection.cases.add(case) return HttpResponse("Case added to collection") #if request.method == "POST": cases = get_cases_available_to_user(request.user) return render(request, "atlas/add_case_to_collection.html", {"cases": cases, "collection": collection}) @login_required def user_uploads_series(request, series_instance_uid: str): # We don't restrict to teh uploading user here. Should we? dicoms = UncategorisedDicom.objects.filter(series_instance_uid=series_instance_uid) if not dicoms: raise Http404("Series not found") return render( request, "atlas/user_upload_viewer.html", {"dicoms": dicoms, "series_id": series_instance_uid}, ) @login_required @user_passes_test(lambda u: u.is_superuser) def all_uploads(request, case_id: int | None = None): return user_uploads(request, case_id, user_only=False) @login_required def user_uploads(request, case_id: int | None = None, user_only: bool = True): if user_only: dicoms = UncategorisedDicom.objects.filter(user=request.user) else: dicoms = UncategorisedDicom.objects.filter() data = defaultdict(list) for d in dicoms: tags = d.basic_dicom_tags if tags is None: d.save() tags = d.basic_dicom_tags data[tags["SeriesInstanceUID"]].append((tags, d.created_date)) series_list = [] for series in data: tags, date = data[series][0] series_list.append((series, len(data[series]), tags, date)) print(series_list) series_list.sort(key=lambda l: l[-1]) 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 success_url = reverse_lazy("atlas:case_view") template_name = "confirm_delete.html" class SeriesFindingDelete(RevisionMixin, PermissionRequiredMixin, DeleteView): permission_required = "atlas.delete_seriesfinding" model = SeriesFinding template_name = "confirm_delete.html" # success_url = reverse_lazy("atlas:case_view") def get_success_url(self): pk = self.kwargs["pk"] series_id = get_object_or_404(SeriesFinding, pk=pk).series.id return reverse("atlas:series_detail", kwargs={"pk": series_id}) class SeriesDelete(RevisionMixin, AtlasEditorRequiredMixin, DeleteView): model = Series template_name = "confirm_delete.html" success_url = reverse_lazy("atlas:series_view") class CaseCollectionDelete(RevisionMixin, AtlasEditorRequiredMixin, DeleteView): model = CaseCollection template_name = "confirm_delete.html" success_url = reverse_lazy("atlas:collection_view") class ConditionDelete(RevisionMixin, AtlasEditorRequiredMixin, DeleteView): model = Condition template_name = "confirm_delete.html" success_url = reverse_lazy("atlas:condition_view") class FindingDelete(RevisionMixin, AtlasEditorRequiredMixin, DeleteView): model = Finding template_name = "confirm_delete.html" success_url = reverse_lazy("atlas:finding_view") class StructureDelete(RevisionMixin, AtlasEditorRequiredMixin, DeleteView): model = Structure template_name = "confirm_delete.html" success_url = reverse_lazy("atlas:structure_view") class CaseCollectionCreate(RevisionMixin, LoginRequiredMixin, CreateView): model = CaseCollection form_class = CaseCollectionForm def get_initial(self): # print(self.request) if "pk" in self.kwargs: initial = super(CaseCollectionCreate, self).get_initial() # case = get_object_or_404(Case, pk=self.kwargs["pk"]) # initial["case"] = case.id return initial def get_form_kwargs(self): kwargs = super(CaseCollectionCreate, self).get_form_kwargs() kwargs.update({"user": self.request.user}) return kwargs def get_context_data(self, **kwargs): context = super(CaseCollectionCreate, self).get_context_data(**kwargs) if self.request.POST: context["case_formset"] = CaseCollectionCaseFormSet( self.request.POST, self.request.FILES, form_kwargs={"user": self.request.user}, ) context["case_formset"].full_clean() else: context["case_formset"] = CaseCollectionCaseFormSet( form_kwargs={"user": self.request.user} ) return context def form_valid(self, form): self.object = form.save(commit=False) self.object.save() form.instance.author.add(self.request.user.id) context = self.get_context_data(form=form) case_formset = context["case_formset"] if case_formset.is_valid(): response = super().form_valid(form) case_formset.instance = self.object case_formset.save() return response else: return super().form_invalid(form) class SeriesCreate(RevisionMixin, LoginRequiredMixin, CreateView): model = Series form_class = SeriesForm def get_initial(self): # print(self.request) if "pk" in self.kwargs: initial = super().get_initial() case = get_object_or_404(Case, pk=self.kwargs["pk"]) initial["case"] = case.id return initial def get_form_kwargs(self): kwargs = super(SeriesCreate, self).get_form_kwargs() kwargs.update({"user": self.request.user}) return kwargs def get_context_data(self, **kwargs): context = super(SeriesCreate, self).get_context_data(**kwargs) if self.request.POST: context["image_formset"] = SeriesImageFormSet( self.request.POST, self.request.FILES ) context["image_formset"].full_clean() else: context["image_formset"] = SeriesImageFormSet() return context def form_valid(self, form): self.object = form.save(commit=False) self.object.save() form.instance.author.add(self.request.user.id) context = self.get_context_data(form=form) series_formset = context["image_formset"] if series_formset.is_valid(): response = super().form_valid(form) series_formset.instance = self.object series_formset.save() return response else: return super().form_invalid(form) class CaseCollectionUpdate(RevisionMixin, AuthorOrCheckerRequiredMixin, UpdateView): model = CaseCollection form_class = CaseCollectionForm template_name = "atlas/collection_update_form.html" # fields = '__all__' # #fields = [ 'condition' ] # #initial = {'date_of_death': '05/01/2018'} # exclude = [ 'created_date', 'published_date' ] def get_form_kwargs(self): kwargs = super(CaseCollectionUpdate, self).get_form_kwargs() kwargs.update({"user": self.request.user}) return kwargs def get_context_data(self, **kwargs): context = super(CaseCollectionUpdate, self).get_context_data(**kwargs) if self.request.POST: context["case_formset"] = CaseCollectionCaseFormSet( self.request.POST, self.request.FILES, instance=self.object, form_kwargs={"user": self.request.user}, ) context["case_formset"].full_clean() else: context["case_formset"] = CaseCollectionCaseFormSet( instance=self.object, form_kwargs={"user": self.request.user} ) context["collection"] = context["casecollection"] return context def form_valid(self, form): # save exam orders (there must be a better way to do this) # exam_orders = {} # for exam in self.object.exams.all(): # exam_orders[exam] = list(exam.exam_questions.all()) self.object = form.save(commit=False) self.object.save() form.instance.author.add(self.request.user.id) context = self.get_context_data(form=form) case_formset = context["case_formset"] # logger.debug(formset.is_valid()) if case_formset.is_valid(): response = super().form_valid(form) case_formset.instance = self.object case_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 SeriesUpdate( RevisionMixin, LoginRequiredMixin, AuthorOrCheckerRequiredMixin, UpdateView ): model = Series form_class = SeriesForm # fields = '__all__' # #fields = [ 'condition' ] # #initial = {'date_of_death': '05/01/2018'} # exclude = [ 'created_date', 'published_date' ] def get_context_data(self, **kwargs): context = super(SeriesUpdate, self).get_context_data(**kwargs) if self.request.POST: context["image_formset"] = SeriesImageFormSet( self.request.POST, self.request.FILES, instance=self.object ) context["image_formset"].full_clean() else: context["image_formset"] = SeriesImageFormSet(instance=self.object) return context def get_form_kwargs(self): kwargs = super(SeriesUpdate, self).get_form_kwargs() kwargs.update({"user": self.request.user}) return kwargs def form_valid(self, form): self.object = form.save(commit=False) self.object.save() form.instance.author.add(self.request.user.id) context = self.get_context_data(form=form) image_formset = context["image_formset"] # logger.debug(formset.is_valid()) if image_formset.is_valid(): response = super().form_valid(form) image_formset.instance = self.object image_formset.save() return response else: return super().form_invalid(form) class ConditionUpdate(RevisionMixin, LoginRequiredMixin, UpdateView): model = Condition form_class = ConditionForm class ConditionCreate(RevisionMixin, LoginRequiredMixin, CreateView): model = Condition form_class = ConditionForm class FindingUpdate(RevisionMixin, LoginRequiredMixin, UpdateView): model = Finding form_class = FindingForm class FindingCreate(RevisionMixin, LoginRequiredMixin, CreateView): model = Finding form_class = FindingForm class StructureUpdate(RevisionMixin, LoginRequiredMixin, UpdateView): model = Structure form_class = StructureForm class StructureCreate(RevisionMixin, LoginRequiredMixin, CreateView): model = Structure form_class = StructureForm class AtlasCreateBase(RevisionMixin, LoginRequiredMixin): model = Case form_class = CaseForm def get_form_kwargs(self): kwargs = super(AtlasCreateBase, self).get_form_kwargs() kwargs.update({"user": self.request.user}) return kwargs def get_context_data(self, **kwargs): context = super(AtlasCreateBase, self).get_context_data(**kwargs) if self.request.POST: context["series_formset"] = SeriesFormSet( self.request.POST, self.request.FILES, form_kwargs={"user": self.request.user}, ) context["casedifferential_formset"] = CaseDifferentialFormSet( self.request.POST, self.request.FILES ) context["series_formset"].full_clean() context["casedifferential_formset"].full_clean() else: # context["series_formset"] = SeriesFormSet(instance=Case.objects.filter(author__id=self.request.user.id), queryset=Series.objects.filter(author__id=self.request.user.id)) context["series_formset"] = SeriesFormSet( form_kwargs={"user": self.request.user} ) context["casedifferential_formset"] = CaseDifferentialFormSet() return context def form_valid(self, form): self.object = form.save(commit=False) # Add exam objects self.object.save() form.instance.author.add(self.request.user.id) context = self.get_context_data(form=form) series_formset = context["series_formset"] casedifferential_formset = context["casedifferential_formset"] if series_formset.is_valid() and casedifferential_formset.is_valid(): response = super().form_valid(form) series_formset.instance = self.object series_formset.save() casedifferential_formset.instance = self.object casedifferential_formset.save() # If the normal submit button is pressed we save as normal if "submit" in self.request.POST: return response # else we redirect to the clone url else: return redirect("atlas:case_clone", pk=self.object.pk) else: return super().form_invalid(form) # @login_required class AtlasCreate(AtlasCreateBase, CreateView): def get_initial(self): if "pk" in self.kwargs: initial = super().get_initial() exam = get_object_or_404(CaseCollection, pk=self.kwargs["pk"]) initial["exams"] = [exam.id] return initial ## There has to be a better way... # try: # s = (i.pk for i in self.request.user.atlas_default.site.all()) # self.initial.update({"site": s}) # except AttributeError: # pass # return self.initial class AtlasUpdate( RevisionMixin, LoginRequiredMixin, AuthorOrCheckerRequiredMixin, UpdateView ): model = Case form_class = CaseForm # fields = '__all__' # #fields = [ 'condition' ] # #initial = {'date_of_death': '05/01/2018'} # exclude = [ 'created_date', 'published_date' ] def get_form_kwargs(self): kwargs = super(AtlasUpdate, self).get_form_kwargs() kwargs.update({"user": self.request.user}) return kwargs def get_context_data(self, **kwargs): context = super(AtlasUpdate, self).get_context_data(**kwargs) if self.request.POST: context["series_formset"] = SeriesFormSet( self.request.POST, self.request.FILES, instance=self.object, form_kwargs={"user": self.request.user}, ) context["casedifferential_formset"] = CaseDifferentialFormSet( self.request.POST, self.request.FILES, instance=self.object ) context["series_formset"].full_clean() context["casedifferential_formset"].full_clean() else: context["series_formset"] = SeriesFormSet( instance=self.object, form_kwargs={"user": self.request.user} ) context["casedifferential_formset"] = CaseDifferentialFormSet( instance=self.object ) return context def form_valid(self, form): self.object = form.save(commit=False) self.object.save() form.instance.author.add(self.request.user.id) context = self.get_context_data(form=form) series_formset = context["series_formset"] casedifferential_formset = context["casedifferential_formset"] # logger.debug(formset.is_valid()) if series_formset.is_valid() and casedifferential_formset.is_valid(): response = super().form_valid(form) series_formset.instance = self.object series_formset.save() casedifferential_formset.instance = self.object casedifferential_formset.save() return response else: return super().form_invalid(form) def add_collection_to_case_form(request, case_id): if request.method == "POST": form = AddCollectionToCaseForm(request.POST, user=request.user) if form.is_valid(): case = get_object_or_404(Case, pk=case_id) case.casecollection_set.add(*form.cleaned_data["casecollection"]) # do_something_with_form_data(form.cleaned_data) return HttpResponse("Done") return render(request, "web/htmx_contact_form_confirm.html") else: form = AddCollectionToCaseForm(user=request.user) return render( request, "generic_form.html", { "form": form, "target_url": reverse("atlas:case_collection_form", args=(case_id,)), }, ) # class AddCollectionToCaseView(FormView): # form_class = AddCollectionToCaseForm # template_name = "generic_form.html" # # def form_valid(self, form): # form.save() # return super(AddCollectionToCaseView, self).form_valid(form) # # def get_form_kwargs(self): # kwargs = super(AddCollectionToCaseView, self).get_form_kwargs() # kwargs.update({"user": self.request.user}) # return kwargs # # def get_success_url(self) -> str: # pk = self.kwargs["pk"] # return reverse("atlas:case_detail", kwargs={"pk": pk}) class AtlasClone(AtlasCreateBase, AuthorOrCheckerRequiredMixin, CreateView): """Clones a existing atlas""" # fields = '__all__' # #fields = [ 'condition' ] # #initial = {'date_of_death': '05/01/2018'} # exclude = [ 'created_date', 'published_date' ] def get_initial(self): # print(self.request) old_object = get_object_or_404(Case, pk=self.kwargs["pk"]) if ( self.request.user.groups.filter(name="atlas_editor").exists() or self.request.user.is_superuser ): pass else: if self.request.user not in old_object.get_author_objects(): raise PermissionDenied() # or Http404 else: pass initial_data = model_to_dict(old_object, exclude=["id"]) return initial_data @login_required @user_is_author_or_atlas_editor def atlas_scrap(request, pk): try: atlas = Case.objects.get(pk=pk) except Case.DoesNotExist: raise Http404("Case does not exist") atlas.scrapped = not atlas.scrapped atlas.save() return HttpResponseRedirect(reverse("atlas:case_detail", args=(pk,))) # @login_required # def edit_abnormality_popup(request): # instance = get_object_or_404(Abnormality, pk = pk) # form = AbnormalityForm(request.POST or None) # if form.is_valid(): # instance = form.save() # return HttpResponse('' % (instance.pk, instance)) # return render(request, "atlas/create_simple.html", {'form': form}) @csrf_exempt def get_examination_id(request): if request.accepts("application/json")(): examination_name = request.GET["examination_name"] examination_id = Examination.objects.get(name=examination_name).id data = { "examination_id": examination_id, } return HttpResponse(json.dumps(data), content_type="application/json") return HttpResponse("/") class CaseView(LoginRequiredMixin, SingleTableMixin, FilterView): model = Case table_class = CaseTable template_name = "atlas/view.html" filterset_class = CaseFilter class SeriesView(LoginRequiredMixin, SingleTableMixin, FilterView): model = Series table_class = SeriesTable template_name = "atlas/view.html" filterset_class = SeriesFilter class ConditionView(LoginRequiredMixin, SingleTableMixin, FilterView): model = Condition table_class = ConditionTable template_name = "atlas/view.html" filterset_class = ConditionFilter class SubspecialtyView(LoginRequiredMixin, SingleTableMixin, FilterView): model = Subspecialty table_class = SubspecialtyTable template_name = "atlas/view.html" filterset_class = SubspecialtyFilter class PresentationView(LoginRequiredMixin, SingleTableMixin, FilterView): model = Presentation table_class = PresentationTable template_name = "atlas/view.html" filterset_class = PresentationFilter class PathologicalProcessView(LoginRequiredMixin, SingleTableMixin, FilterView): model = PathologicalProcess table_class = PathologicalProcessTable template_name = "atlas/view.html" filterset_class = PathologicalProcessFilter class StructureView(LoginRequiredMixin, SingleTableMixin, FilterView): model = Structure table_class = StructureTable template_name = "atlas/view.html" filterset_class = StructureFilter class FindingView(LoginRequiredMixin, SingleTableMixin, FilterView): model = Finding table_class = FindingTable template_name = "atlas/view.html" filterset_class = FindingFilter @login_required def case_order_dicom(request, pk): if request.htmx: case = get_object_or_404(Case, pk=pk) fail = [] for series in case.series.all(): try: if request.user in series.get_author_objects(): series.order_by_dicom() else: fail.append(series.pk) except: fail.append(series.pk) if fail: return HttpResponse(f"Unable to order series {','.join([str(i) for i in fail])}") else: return HttpResponse("Series reordered") raise Http404 @login_required @user_is_author_or_atlas_series_checker def series_order_dicom(request, pk): series = get_object_or_404(Series, pk=pk) try: series.order_by_dicom() except: return HttpResponse("
{dict_diff}{dict_diff}")
return HttpResponse("Fail")
@login_required
def series_image_dicom(request, pk):
image = get_object_or_404(SeriesImage, pk=pk)
return render(request, "atlas/series_image_dicom.html", {"image": image})
@login_required
@user_is_author_or_atlas_series_checker
def series_anonymise_dicom(request, pk):
series = get_object_or_404(Series, pk=pk)
series.anonymise_images()
return redirect("atlas:series_detail", pk=pk)
@login_required
@user_is_author_or_atlas_series_checker
def series_order_dicom_instance(request, pk):
series = get_object_or_404(Series, pk=pk)
try:
series.order_by_dicom("InstanceNumber")
except:
return HttpResponse(
"