This commit is contained in:
Ross
2021-11-25 22:16:42 +00:00
parent 2ed684baed
commit 141265d37a
3 changed files with 87 additions and 40 deletions
+8 -6
View File
@@ -1,5 +1,5 @@
from django.contrib import admin
from .models import Case, Series, SeriesImage
from .models import Case, Series, SeriesImage, Condition
import tagulous.admin
@@ -11,13 +11,13 @@ from django.forms.widgets import RadioSelect
from tinymce.widgets import TinyMCE
# from generic.models import Examination, Sign, Site, Condition
from generic.models import Examination, Sign, Condition
from generic.models import Examination, Sign
# Register your models here.
# admin.site.register(Examination)
# admin.site.register(Site)
admin.site.register(SeriesImage)
admin.site.register(Condition)
class AtlasAdminForm(ModelForm):
@@ -37,10 +37,11 @@ class AtlasAdminForm(ModelForm):
# "normal": RadioSelect(
# choices=[(True, 'Yes'),
# (False, 'No')])
"findings" : TinyMCE(attrs={'cols': 80, 'rows': 30}),
"mark_scheme" : TinyMCE(attrs={'cols': 80, 'rows': 30}),
"findings": TinyMCE(attrs={"cols": 80, "rows": 30}),
"mark_scheme": TinyMCE(attrs={"cols": 80, "rows": 30}),
}
class AtlasAdmin(VersionAdmin):
form = AtlasAdminForm
@@ -55,4 +56,5 @@ admin.site.register(Case, AtlasAdmin)
class SeriesAdmin(VersionAdmin):
pass
admin.site.register(Series, SeriesAdmin)
admin.site.register(Series, SeriesAdmin)
@@ -0,0 +1,26 @@
# Generated by Django 3.2.8 on 2021-11-25 22:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('atlas', '0003_rename_subpecialty_case_subspecialty'),
]
operations = [
migrations.CreateModel(
name='Condition',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('synonym', models.ManyToManyField(blank=True, related_name='_atlas_condition_synonym_+', to='atlas.Condition')),
],
),
migrations.AlterField(
model_name='case',
name='condition',
field=models.ManyToManyField(blank=True, to='atlas.Condition'),
),
]
+53 -34
View File
@@ -28,7 +28,15 @@ from helpers.images import image_as_base64, pretty_print_dicom
from anatomy.models import Modality
from generic.models import Examination, Condition, Sign, ExamBase, Plane, Contrast, QuestionNote
from generic.models import (
Examination,
Condition,
Sign,
ExamBase,
Plane,
Contrast,
QuestionNote,
)
# from generic.models import Examination, Site, Condition, Sign
@@ -66,20 +74,26 @@ def findMiddle(input_list):
return (input_list[int(middle)], input_list[int(middle - 1)])
class Condition(models.Model):
name = models.CharField(max_length=255)
synonym = models.ManyToManyField("self", blank=True)
@reversion.register
class Case(models.Model):
class SubspecialtyChoices(models.TextChoices):
BREAST = 'BR', _('Breast')
CARDIAC = 'CA', _('Cardiac')
GASTRO = 'GI', _('Gastrointestinal and hepatobiliary')
HEADNECK = 'HN', _('Head and Neck')
MSK = 'MS', _('Musculoskeletal')
NEURO = 'NE', _('Neuroradiology')
OBSGYN = 'OG', _('Obstectric and Gynaecological')
PAED = 'PA', _('Paediatric')
URO = 'UR', _('Uroradiology')
VASC = 'VA', _('Vascular')
HAEMONC = 'HA', _('Haemotology and Oncology')
BREAST = "BR", _("Breast")
CARDIAC = "CA", _("Cardiac")
GASTRO = "GI", _("Gastrointestinal and hepatobiliary")
HEADNECK = "HN", _("Head and Neck")
MSK = "MS", _("Musculoskeletal")
NEURO = "NE", _("Neuroradiology")
OBSGYN = "OG", _("Obstectric and Gynaecological")
PAED = "PA", _("Paediatric")
URO = "UR", _("Uroradiology")
VASC = "VA", _("Vascular")
HAEMONC = "HA", _("Haemotology and Oncology")
title = models.CharField(max_length=255, help_text="Title of the case", default="")
# author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
@@ -95,11 +109,7 @@ class Case(models.Model):
subspecialty = models.CharField(max_length=2, choices=SubspecialtyChoices.choices)
condition = tagulous.models.TagField(
to=Condition,
blank=True,
help_text='Associated condition. Will allow searching / filtering and tips / hints to be displayed. Conditions with spaces must be enclosed in quotes "..."',
)
condition = models.ManyToManyField(Condition, blank=True)
sign = tagulous.models.TagField(
to=Sign, blank=True, help_text="Radiological signs in the question"
@@ -127,7 +137,7 @@ class Case(models.Model):
notes = GenericRelation(QuestionNote)
#question_file = models.FileField(upload_to=question_file_directory_path, blank=True, null=True)
# question_file = models.FileField(upload_to=question_file_directory_path, blank=True, null=True)
def get_absolute_url(self):
return reverse("atlas:case_detail", kwargs={"pk": self.pk})
@@ -158,11 +168,19 @@ class Case(models.Model):
def get_image_urls(self):
return ",".join(
["https://www.penracourses.org.uk{}".format(i.url) for i in self.get_images()]
[
"https://www.penracourses.org.uk{}".format(i.url)
for i in self.get_images()
]
)
def get_image_url_array(self):
return json.dumps(["https://www.penracourses.org.uk{}".format(i.url) for i in self.get_images()])
return json.dumps(
[
"https://www.penracourses.org.uk{}".format(i.url)
for i in self.get_images()
]
)
class SeriesImage(models.Model):
@@ -174,20 +192,23 @@ class SeriesImage(models.Model):
)
class Meta:
ordering = ['position']
ordering = ["position"]
def get_dicom_info(self):
try:
info = pretty_print_dicom(pydicom.read_file(self.image))
except pydicom.errors.InvalidDicomError:
info = "File is not a dicom."
return(info)
return info
@reversion.register
class Series(models.Model):
modality = models.ForeignKey(
Modality, related_name="atlas_series_modality", on_delete=models.SET_NULL, null=True
Modality,
related_name="atlas_series_modality",
on_delete=models.SET_NULL,
null=True,
)
examination = models.ForeignKey(
Examination,
@@ -227,15 +248,14 @@ class Series(models.Model):
help_text="If a question should be freely available to browse", default=True
)
def __str__(self):
if self.case:
case_id = ", ".format([case.pk for case in self.case.all()])
#case_id = self.case.pk
# case_id = self.case.pk
else:
case_id = "None"
return "{}/{} : {} [{}]".format(self.pk,
self.get_examination(), self.description, case_id
return "{}/{} : {} [{}]".format(
self.pk, self.get_examination(), self.description, case_id
)
def get_author_objects(self):
@@ -295,7 +315,9 @@ class Series(models.Model):
thumbnailer = get_thumbnailer(img)
thumbnail = thumbnailer["exam-list"]
except InvalidImageFormatError:
return format_html('<span title="{}">Invalid image url<span>', img), len(images)
return format_html('<span title="{}">Invalid image url<span>', img), len(
images
)
return format_html('<img src="/media/{}" />', thumbnail), len(images)
def get_block(self):
@@ -323,8 +345,6 @@ class Series(models.Model):
i.position = n
i.save()
n = n + 1
def order_by_dicom(self, field="SliceLocation"):
images = self.images.all()
@@ -334,7 +354,7 @@ class Series(models.Model):
for i in images:
files.append((i, pydicom.dcmread(i.image.path)))
#print("file count: {}".format(len(files)))
# print("file count: {}".format(len(files)))
# skip files with no SliceLocation (eg scout views)
slices = []
@@ -343,7 +363,7 @@ class Series(models.Model):
for i, f in files:
if hasattr(f, field):
slices.append(f)
#map[f.SliceLocation] = i
# map[f.SliceLocation] = i
map[f[field].value] = i
else:
skipcount = skipcount + 1
@@ -353,8 +373,7 @@ class Series(models.Model):
# ensure they are in the correct order
slices = sorted(slices, key=lambda s: s[field].value)
#print(slices)
# print(slices)
n = 1
for f in slices:
i = map[f[field].value]