i should break these commits up
This commit is contained in:
+67
-33
@@ -311,20 +311,32 @@ class Case(models.Model, AuthorMixin, QuestionMixin):
|
||||
# findings = models.TextField(null=True, blank=True)
|
||||
|
||||
# subspecialty = models.CharField(max_length=2, choices=SubspecialtyChoices.choices)
|
||||
subspecialty = models.ManyToManyField(Subspecialty, blank=True)
|
||||
subspecialty = models.ManyToManyField(
|
||||
Subspecialty,
|
||||
blank=True,
|
||||
help_text="The subspecialties the case is associated with. Multiple subspecialties can be selected.",
|
||||
)
|
||||
|
||||
condition = models.ManyToManyField(Condition, blank=True)
|
||||
condition = models.ManyToManyField(
|
||||
Condition, blank=True, help_text="The condition(s) the case demonstrates."
|
||||
)
|
||||
|
||||
presentation = models.ManyToManyField(Presentation, blank=True)
|
||||
presentation = models.ManyToManyField(
|
||||
Presentation,
|
||||
blank=True,
|
||||
help_text="The presentation(s) the case is associated with.",
|
||||
)
|
||||
|
||||
pathological_process = models.ManyToManyField(PathologicalProcess, blank=True)
|
||||
|
||||
differential = models.ManyToManyField(
|
||||
Condition, through=Differential, related_name="casedifferential"
|
||||
Condition, through=Differential, related_name="casedifferential",
|
||||
help_text="The differential diagnosis for the case.",
|
||||
)
|
||||
|
||||
diagnostic_certainty = models.IntegerField(
|
||||
choices=CertaintyChoices.choices, default=CertaintyChoices.NONE
|
||||
choices=CertaintyChoices.choices, default=CertaintyChoices.NONE,
|
||||
help_text="The diagnostic certainty of the case.",
|
||||
)
|
||||
|
||||
verified = models.BooleanField(default=False)
|
||||
@@ -352,7 +364,9 @@ class Case(models.Model, AuthorMixin, QuestionMixin):
|
||||
help_text="If a case should be freely available to browse", default=True
|
||||
)
|
||||
|
||||
series = models.ManyToManyField("Series", through="SeriesDetail", related_name="case")
|
||||
series = models.ManyToManyField(
|
||||
"Series", through="SeriesDetail", related_name="case"
|
||||
)
|
||||
|
||||
notes = GenericRelation(QuestionNote)
|
||||
|
||||
@@ -362,6 +376,7 @@ class Case(models.Model, AuthorMixin, QuestionMixin):
|
||||
null=True,
|
||||
related_name="next_case",
|
||||
blank=True,
|
||||
help_text="If this case is related to another case on the system (e.g. follow up), link them here.",
|
||||
)
|
||||
|
||||
resource = models.ManyToManyField("Resource", through="CaseResource")
|
||||
@@ -378,12 +393,15 @@ class Case(models.Model, AuthorMixin, QuestionMixin):
|
||||
# return f"{self.pk}: {self.title}"
|
||||
return format_html("<a href='{}'>{}</a>", self.get_absolute_url(), str(self))
|
||||
|
||||
#def get_base_template(self):
|
||||
# def get_base_template(self):
|
||||
|
||||
#def get_edit_template_links(self):
|
||||
# def get_edit_template_links(self):
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.pk}: {self.title}"
|
||||
if self.open_access:
|
||||
return f"{self.pk}: {self.title} [OA]"
|
||||
else:
|
||||
return f"{self.pk}: {self.title}"
|
||||
|
||||
def get_series_blocks(self):
|
||||
html = ""
|
||||
@@ -396,7 +414,7 @@ class Case(models.Model, AuthorMixin, QuestionMixin):
|
||||
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, case_title_as_patient_name = True):
|
||||
def get_case_dicom_json(self, case_title_as_patient_name=True):
|
||||
series_json = []
|
||||
for series in self.series.all():
|
||||
series_json.append(series.get_series_dicom_json())
|
||||
@@ -435,7 +453,6 @@ class Case(models.Model, AuthorMixin, QuestionMixin):
|
||||
return json.dumps(self.get_viva_details())
|
||||
|
||||
|
||||
|
||||
def extract_image_dicom_json_from_ds(ds, url, image_index):
|
||||
to_keep = [
|
||||
"Columns",
|
||||
@@ -597,7 +614,7 @@ class Series(SeriesBase):
|
||||
"<a href='{}'>{}</a>", self.get_absolute_url(), self.get_full_str()
|
||||
)
|
||||
|
||||
#@lru_cache(maxsize=128)
|
||||
# @lru_cache(maxsize=128)
|
||||
def get_series_dicom_json(self):
|
||||
instances = []
|
||||
|
||||
@@ -662,12 +679,13 @@ class Series(SeriesBase):
|
||||
image = self.images.first()
|
||||
|
||||
with pydicom.dcmread(image.image) as ds:
|
||||
date = ds.get("StudyDate", "No date")
|
||||
date = ds.get("StudyDate", "No date")
|
||||
|
||||
self.description = f"{date[:4]}-{date[4:6]}-{date[6:]}"
|
||||
|
||||
self.save()
|
||||
|
||||
|
||||
class CaseCollection(ExamOrCollectionGenericBase):
|
||||
app_name = "atlas"
|
||||
|
||||
@@ -806,9 +824,13 @@ class CaseCollection(ExamOrCollectionGenericBase):
|
||||
self.VIEWER_MODE_CHOICES.BUILT_IN_WITH_OHIF,
|
||||
)
|
||||
|
||||
def show_ohif_viewer_link(self) -> bool:
|
||||
def show_ohif_viewer(self) -> bool:
|
||||
return self.viewer_mode in (
|
||||
self.VIEWER_MODE_CHOICES.OHIF,
|
||||
)
|
||||
|
||||
def show_ohif_viewer_link(self) -> bool:
|
||||
return self.viewer_mode in (
|
||||
self.VIEWER_MODE_CHOICES.BUILT_IN_WITH_OHIF,
|
||||
)
|
||||
|
||||
@@ -843,9 +865,7 @@ class CaseCollection(ExamOrCollectionGenericBase):
|
||||
) -> 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.get_cases().prefetch_related()
|
||||
)
|
||||
cases = list(self.get_cases().prefetch_related())
|
||||
|
||||
try:
|
||||
case = cases[case_index]
|
||||
@@ -859,16 +879,14 @@ class CaseCollection(ExamOrCollectionGenericBase):
|
||||
return case
|
||||
|
||||
def get_case_take_url(self, case):
|
||||
cases = list(
|
||||
self.get_cases().prefetch_related()
|
||||
)
|
||||
cases = list(self.get_cases().prefetch_related())
|
||||
|
||||
return reverse(
|
||||
"atlas:collection_case_view_take_user",
|
||||
kwargs={"pk": self.pk, "case_number": cases.index(case)},
|
||||
)
|
||||
|
||||
def get_ohif_dicom_json(self, case_title_as_patient_name = True):
|
||||
def get_ohif_dicom_json(self, case_title_as_patient_name=True):
|
||||
studies = []
|
||||
for n, case in enumerate(self.cases.all()):
|
||||
series_json = []
|
||||
@@ -880,7 +898,6 @@ class CaseCollection(ExamOrCollectionGenericBase):
|
||||
patient_name = case.title
|
||||
|
||||
studies.append(
|
||||
|
||||
{
|
||||
"StudyInstanceUID": f"1.3.6.1.4.1.14519.5.2.1.6279.6001.{n}",
|
||||
"StudyDate": "20000101",
|
||||
@@ -894,21 +911,16 @@ class CaseCollection(ExamOrCollectionGenericBase):
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
||||
return {
|
||||
"studies": studies
|
||||
}
|
||||
return {"studies": studies}
|
||||
|
||||
def add_case(self, case):
|
||||
"""Adds a case to the collection and makes sure order is maintained"""
|
||||
# We might be better off adding via the case detail model direct
|
||||
#CaseDetail.objects.create(case=case, collection=self)
|
||||
# CaseDetail.objects.create(case=case, collection=self)
|
||||
self.cases.add(case)
|
||||
self.order_cases()
|
||||
|
||||
|
||||
def order_cases(self):
|
||||
def order_cases(self):
|
||||
"""Modifies the casedetail sort_order to sequentially order the cases"""
|
||||
for n, c in enumerate(self.casedetail_set.all().order_by("sort_order")):
|
||||
c.sort_order = n
|
||||
@@ -921,11 +933,15 @@ class SeriesDetail(models.Model):
|
||||
|
||||
sort_order = models.IntegerField(default=1000)
|
||||
|
||||
feedback = models.BooleanField(default=False, help_text="Set to true if the series should only be shown for feedback purposes.")
|
||||
feedback = models.BooleanField(
|
||||
default=False,
|
||||
help_text="Set to true if the series should only be shown for feedback purposes.",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
ordering = ("sort_order",)
|
||||
|
||||
|
||||
class CaseDetail(models.Model):
|
||||
case = models.ForeignKey(Case, on_delete=models.CASCADE)
|
||||
collection = models.ForeignKey(CaseCollection, on_delete=models.CASCADE)
|
||||
@@ -950,6 +966,8 @@ class BaseReportAnswer(models.Model):
|
||||
blank=True, null=True, validators=[MaxValueValidator(10), MinValueValidator(0)]
|
||||
)
|
||||
|
||||
completed = models.BooleanField(default=False)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.clean()
|
||||
return super(BaseReportAnswer, self).save(*args, **kwargs)
|
||||
@@ -1145,6 +1163,7 @@ class UncategorisedDicom(models.Model):
|
||||
class DuplicateDicom(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Resource(models.Model, AuthorMixin):
|
||||
name = models.CharField(max_length=255)
|
||||
description = models.TextField(blank=True, null=True)
|
||||
@@ -1166,11 +1185,26 @@ class Resource(models.Model, AuthorMixin):
|
||||
def get_link(self):
|
||||
return format_html("<a href='{}'>{}</a>", self.get_absolute_url(), self.name)
|
||||
|
||||
def get_display(self) -> str:
|
||||
if self.url:
|
||||
html = f"<a target='_blank' href='{self.url}'>{self.name}</a>"
|
||||
elif self.file:
|
||||
html = f"<a target='_blank' href='{self.file.url}'>{self.name}</a>"
|
||||
else:
|
||||
html = self.name
|
||||
|
||||
return format_html(html)
|
||||
|
||||
|
||||
|
||||
class CaseResource(models.Model):
|
||||
resource = models.ForeignKey(Resource, on_delete=models.CASCADE)
|
||||
case = models.ForeignKey(Case, on_delete=models.CASCADE)
|
||||
|
||||
pre_review = models.BooleanField(default=False)
|
||||
pre_review = models.BooleanField(
|
||||
default=False,
|
||||
help_text="Defines if the resource should be shown pre review (i.e. for pre reading before the case is taken)",
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.resource} - {self.case}"
|
||||
return f"{self.resource} - {self.case} (Pre: {self.pre_review})"
|
||||
|
||||
Reference in New Issue
Block a user