start working torwards stack modificaiton

This commit is contained in:
Ross
2023-12-18 09:17:05 +00:00
parent bdeb2210e1
commit ada3a8906f
4 changed files with 63 additions and 20 deletions
-3
View File
@@ -183,7 +183,6 @@ def series_remove_duplicate_images(request, series_id: int):
@router.get("/get_cases_user", auth=django_auth, response=List[CaseSchema]) @router.get("/get_cases_user", auth=django_auth, response=List[CaseSchema])
def get_cases_user(request): def get_cases_user(request):
print("HELLO")
return Case.objects.filter(author=request.user) return Case.objects.filter(author=request.user)
@@ -250,8 +249,6 @@ def series_split_by_tag(request, series_id: int, dicom_tag:str):
if dicom_tag.startswith("(") and dicom_tag.endswith(")"): if dicom_tag.startswith("(") and dicom_tag.endswith(")"):
dicom_tag = tuple([hex(int(i.strip(),16)) for i in dicom_tag[1:-1].split(",")]) dicom_tag = tuple([hex(int(i.strip(),16)) for i in dicom_tag[1:-1].split(",")])
print("1", dicom_tag)
image_map = defaultdict(list) image_map = defaultdict(list)
# Split teh associated images # Split teh associated images
+55 -16
View File
@@ -32,7 +32,12 @@ from sortedm2m.fields import SortedManyToManyField
import string import string
from collections import defaultdict from collections import defaultdict
from helpers.images import get_image_dicom_hash, get_image_hash, image_as_base64, pretty_print_dicom from helpers.images import (
get_image_dicom_hash,
get_image_hash,
image_as_base64,
pretty_print_dicom,
)
from generic.models import ( from generic.models import (
@@ -143,16 +148,42 @@ class Finding(SynMixin, models.Model):
class Condition(SynMixin, models.Model): class Condition(SynMixin, models.Model):
name = models.CharField(max_length=255, unique=True) name = models.CharField(max_length=255, unique=True)
synonym = models.ManyToManyField("self", blank=True, help_text="Use if a direct synonym for the condition exists, e.g. 'Wegener granulomatosis' and 'Granulomatosis with Polyangitis'.") synonym = models.ManyToManyField(
parent = models.ManyToManyField("self", blank=True, related_name="child", symmetrical=False, through="ConditionRelationship", help_text="Use if the condition could be considered a subset of another, e.g. 'Alzheimer disease' and 'Dementia'.") "self",
blank=True,
help_text="Use if a direct synonym for the condition exists, e.g. 'Wegener granulomatosis' and 'Granulomatosis with Polyangitis'.",
)
parent = models.ManyToManyField(
"self",
blank=True,
related_name="child",
symmetrical=False,
through="ConditionRelationship",
help_text="Use if the condition could be considered a subset of another, e.g. 'Alzheimer disease' and 'Dementia'.",
)
primary = models.BooleanField(default="True", help_text="Sets if this should be the canonical item, all other synonyms will then redirect to this by default.") primary = models.BooleanField(
default="True",
help_text="Sets if this should be the canonical item, all other synonyms will then redirect to this by default.",
)
subspecialty = models.ManyToManyField("subspecialty", blank=True, help_text="Sets the subspecialty(/ies) that this condition falls under.") subspecialty = models.ManyToManyField(
"subspecialty",
blank=True,
help_text="Sets the subspecialty(/ies) that this condition falls under.",
)
rcr_curriculum_map = models.ManyToManyField("self", blank=True, limit_choices_to={"rcr_curriculum": True}, help_text="Specifies the related RCR curriculum condition (if it exists).") rcr_curriculum_map = models.ManyToManyField(
"self",
blank=True,
limit_choices_to={"rcr_curriculum": True},
help_text="Specifies the related RCR curriculum condition (if it exists).",
)
rcr_curriculum = models.BooleanField(default=False, help_text="The condition is from the (non exhaustive) RCR curriculum") rcr_curriculum = models.BooleanField(
default=False,
help_text="The condition is from the (non exhaustive) RCR curriculum",
)
def get_absolute_url(self): def get_absolute_url(self):
return reverse("atlas:condition_detail", kwargs={"pk": self.pk}) return reverse("atlas:condition_detail", kwargs={"pk": self.pk})
@@ -163,10 +194,10 @@ class Condition(SynMixin, models.Model):
def get_descendents(self): def get_descendents(self):
"""TODO""" """TODO"""
def get_parents(self): def get_parents(self):
return self.parent.all() return self.parent.all()
class ConditionRelationship(models.Model): class ConditionRelationship(models.Model):
child = models.ForeignKey(Condition, on_delete=models.CASCADE) child = models.ForeignKey(Condition, on_delete=models.CASCADE)
parent = models.ForeignKey(Condition, on_delete=models.CASCADE, related_name="+") parent = models.ForeignKey(Condition, on_delete=models.CASCADE, related_name="+")
@@ -263,7 +294,6 @@ class Case(models.Model):
ALMOST_CERTAIN = 3 ALMOST_CERTAIN = 3
CERTAIN = 4 CERTAIN = 4
title = models.CharField(max_length=255, help_text="Title of the case", default="") title = models.CharField(max_length=255, help_text="Title of the case", default="")
description = models.TextField( description = models.TextField(
blank=True, blank=True,
@@ -293,7 +323,9 @@ class Case(models.Model):
Condition, through=Differential, related_name="casedifferential" Condition, through=Differential, related_name="casedifferential"
) )
diagnostic_certainty = models.IntegerField(choices=CertaintyChoices.choices, default=CertaintyChoices.NONE) diagnostic_certainty = models.IntegerField(
choices=CertaintyChoices.choices, default=CertaintyChoices.NONE
)
verified = models.BooleanField(default=False) verified = models.BooleanField(default=False)
created_date = models.DateTimeField(default=timezone.now) created_date = models.DateTimeField(default=timezone.now)
@@ -348,7 +380,7 @@ class Case(models.Model):
return authors return authors
def get_link(self): def get_link(self):
#return f"{self.pk}: {self.title}" # return f"{self.pk}: {self.title}"
return format_html("<a href='{}'>{}</a>", self.get_absolute_url(), str(self)) return format_html("<a href='{}'>{}</a>", self.get_absolute_url(), str(self))
def __str__(self): def __str__(self):
@@ -439,8 +471,14 @@ class SeriesImage(SeriesImageBase):
"Series", related_name="images", on_delete=models.CASCADE, null=True "Series", related_name="images", on_delete=models.CASCADE, null=True
) )
replaced = models.ForeignKey(
"self",
null=True,
blank=True,
help_text="Reference to the object that has replaced this one.",
)
def get_dicom_data(self): def get_dicom_data(self):
print(self.image)
try: try:
with pydicom.dcmread(self.image) as d: with pydicom.dcmread(self.image) as d:
return d return d
@@ -844,7 +882,11 @@ class UncategorisedDicom(models.Model):
) )
series = models.ForeignKey( series = models.ForeignKey(
"Series", related_name="imported_dicoms", on_delete=models.SET_NULL, null=True, blank=True "Series",
related_name="imported_dicoms",
on_delete=models.SET_NULL,
null=True,
blank=True,
) )
series_instance_uid = models.CharField(max_length=255, blank=True, null=True) series_instance_uid = models.CharField(max_length=255, blank=True, null=True)
@@ -864,13 +906,11 @@ class UncategorisedDicom(models.Model):
if obj := SeriesImage.objects.filter(image_md5_hash=image_hash).first(): if obj := SeriesImage.objects.filter(image_md5_hash=image_hash).first():
duplicate = obj duplicate = obj
return duplicate return duplicate
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
"""Override save method to add image hash""" """Override save method to add image hash"""
if self.image: if self.image:
ds = self.get_dicom_info() ds = self.get_dicom_info()
self.series_instance_uid = ds["SeriesInstanceUID"].value self.series_instance_uid = ds["SeriesInstanceUID"].value
@@ -886,7 +926,6 @@ class UncategorisedDicom(models.Model):
if duplicate is not None: if duplicate is not None:
raise DuplicateDicom raise DuplicateDicom
# Hack for tests # Hack for tests
if image_hash != "1234": if image_hash != "1234":
super().save(*args, **kwargs) # Call the "real" save() method. super().save(*args, **kwargs) # Call the "real" save() method.
+2
View File
@@ -398,6 +398,8 @@ def user_uploads(request, case_id: int | None = None):
series_list.append((series, len(data[series]), tags, date)) series_list.append((series, len(data[series]), tags, date))
print(series_list) print(series_list)
series_list.sort(key=lambda l: l[-1])
case = False case = False
if case_id is not None: if case_id is not None:
case = get_object_or_404(Case, pk=case_id) case = get_object_or_404(Case, pk=case_id)
+5
View File
@@ -183,6 +183,11 @@ class QuestionBase(models.Model):
class SeriesImageBase(models.Model): class SeriesImageBase(models.Model):
"""
Series Images may be modified (usually downsampled to save space), in this case the
(larger) original file will be deleted but the model object will be persisted so that
the duplicate check continues to function.
"""
position = models.IntegerField(default=0) position = models.IntegerField(default=0)
upload_filename = models.CharField(max_length=255, blank=True) upload_filename = models.CharField(max_length=255, blank=True)
series = models.ForeignKey( series = models.ForeignKey(