mirror of
https://github.com/leaders-of-digital-9-task/backend.git
synced 2024-11-24 10:13:46 +03:00
added layers
This commit is contained in:
parent
23db12cf8a
commit
9019d31d48
|
@ -2,6 +2,7 @@ from dicom.api.views import (
|
||||||
AddDicomProjectApi,
|
AddDicomProjectApi,
|
||||||
CreateCircleApi,
|
CreateCircleApi,
|
||||||
CreateFreeHandApi,
|
CreateFreeHandApi,
|
||||||
|
CreateLayerApi,
|
||||||
CreateRoiApi,
|
CreateRoiApi,
|
||||||
CreateRulerApi,
|
CreateRulerApi,
|
||||||
DeleteDicomProjectApi,
|
DeleteDicomProjectApi,
|
||||||
|
@ -12,6 +13,7 @@ from dicom.api.views import (
|
||||||
RetrieveUpdateDeleteCircleApi,
|
RetrieveUpdateDeleteCircleApi,
|
||||||
RetrieveUpdateDeleteDicomApi,
|
RetrieveUpdateDeleteDicomApi,
|
||||||
RetrieveUpdateDeleteFreeHandApi,
|
RetrieveUpdateDeleteFreeHandApi,
|
||||||
|
RetrieveUpdateDeleteLayerApi,
|
||||||
RetrieveUpdateDeleteProjectApi,
|
RetrieveUpdateDeleteProjectApi,
|
||||||
RetrieveUpdateDeleteRoiApi,
|
RetrieveUpdateDeleteRoiApi,
|
||||||
RetrieveUpdateDeleteRulerApi,
|
RetrieveUpdateDeleteRulerApi,
|
||||||
|
@ -129,4 +131,17 @@ urlpatterns = [
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"layer/<str:dicom_slug>/",
|
||||||
|
include(
|
||||||
|
[
|
||||||
|
path("", CreateLayerApi.as_view(), name="create_layer"),
|
||||||
|
path(
|
||||||
|
"<str:slug>",
|
||||||
|
RetrieveUpdateDeleteLayerApi.as_view(),
|
||||||
|
name="get_update_delete_project",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -4,6 +4,7 @@ from dicom.models import (
|
||||||
Coordinate,
|
Coordinate,
|
||||||
Dicom,
|
Dicom,
|
||||||
FreeHand,
|
FreeHand,
|
||||||
|
Layer,
|
||||||
Project,
|
Project,
|
||||||
Roi,
|
Roi,
|
||||||
Ruler,
|
Ruler,
|
||||||
|
@ -20,6 +21,27 @@ class CoordinateSerializer(serializers.ModelSerializer):
|
||||||
fields = ["x", "y"]
|
fields = ["x", "y"]
|
||||||
|
|
||||||
|
|
||||||
|
class ListProjectSerializer(serializers.ModelSerializer):
|
||||||
|
url = serializers.HyperlinkedIdentityField(
|
||||||
|
view_name="get_update_delete_project", lookup_field="slug"
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Project
|
||||||
|
fields = ["name", "pathology_type", "slug", "url", "created"]
|
||||||
|
extra_kwargs = {
|
||||||
|
"slug": {"read_only": True},
|
||||||
|
"created": {"read_only": True},
|
||||||
|
}
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
return Project.objects.create(
|
||||||
|
user=self.context["request"].user,
|
||||||
|
name=validated_data["name"],
|
||||||
|
pathology_type=validated_data["pathology_type"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ListDicomSerializer(serializers.ModelSerializer):
|
class ListDicomSerializer(serializers.ModelSerializer):
|
||||||
url = serializers.HyperlinkedIdentityField(
|
url = serializers.HyperlinkedIdentityField(
|
||||||
view_name="get_update_delete_dicom", lookup_field="slug"
|
view_name="get_update_delete_dicom", lookup_field="slug"
|
||||||
|
@ -28,17 +50,25 @@ class ListDicomSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Dicom
|
model = Dicom
|
||||||
fields = ["file", "uploaded", "pathology_type", "url"]
|
fields = ["file", "uploaded", "url"]
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
return Dicom.objects.create(**validated_data, user=self.context["request"].user)
|
return Dicom.objects.create(**validated_data, user=self.context["request"].user)
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectSerializer(serializers.ModelSerializer):
|
||||||
|
files = ListDicomSerializer(many=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Project
|
||||||
|
fields = ["files", "slug", "created", "stl"]
|
||||||
|
|
||||||
|
|
||||||
class BaseShapeSerializer(serializers.Serializer):
|
class BaseShapeSerializer(serializers.Serializer):
|
||||||
model = BaseShape
|
model = BaseShape
|
||||||
|
|
||||||
type = serializers.ChoiceField(choices=["circle", "roi", "free_hand"])
|
type = serializers.ChoiceField(choices=["circle", "roi", "free_hand", "ruler"])
|
||||||
image_number = serializers.IntegerField()
|
layer = serializers.SlugField(max_length=8, required=False, allow_blank=True)
|
||||||
coordinates = CoordinateSerializer(many=True)
|
coordinates = CoordinateSerializer(many=True)
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
|
@ -51,9 +81,12 @@ class BaseShapeSerializer(serializers.Serializer):
|
||||||
dicom = get_object_or_404(
|
dicom = get_object_or_404(
|
||||||
Dicom, slug=self.context["request"].parser_context["kwargs"]["slug"]
|
Dicom, slug=self.context["request"].parser_context["kwargs"]["slug"]
|
||||||
)
|
)
|
||||||
obj = self.model.objects.create(
|
if validated_data["layer"]:
|
||||||
dicom=dicom, image_number=validated_data["image_number"]
|
layer = get_object_or_404(Layer, slug=validated_data["layer"])
|
||||||
)
|
else:
|
||||||
|
layer = dicom.layers.filter(parent__isnull=True).first()
|
||||||
|
|
||||||
|
obj = self.model.objects.create(layer_fk=layer)
|
||||||
|
|
||||||
create_coordinate(validated_data["coordinates"], obj)
|
create_coordinate(validated_data["coordinates"], obj)
|
||||||
return obj
|
return obj
|
||||||
|
@ -66,65 +99,121 @@ class BaseShapeSerializer(serializers.Serializer):
|
||||||
if self.model.min_coordinates:
|
if self.model.min_coordinates:
|
||||||
if len(validated_data["coordinates"]) < self.model.min_coordinates:
|
if len(validated_data["coordinates"]) < self.model.min_coordinates:
|
||||||
raise serializers.ValidationError
|
raise serializers.ValidationError
|
||||||
|
if validated_data["layer"]:
|
||||||
|
layer = get_object_or_404(Layer, slug=validated_data["layer"])
|
||||||
|
else:
|
||||||
|
layer = obj.dicom.layers.filter(parent__isnull=True).first()
|
||||||
|
if obj.layer_fk != layer:
|
||||||
|
obj.layer_fk = layer
|
||||||
|
obj.save()
|
||||||
create_coordinate(validated_data["coordinates"], obj)
|
create_coordinate(validated_data["coordinates"], obj)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
class BaseShapeLayerSerializer(serializers.Serializer):
|
class BaseShapeLayerSerializer(serializers.Serializer):
|
||||||
type = serializers.ChoiceField(choices=["circle", "roi", "free_hand"])
|
type = serializers.ChoiceField(choices=["circle", "roi", "free_hand", "ruler"])
|
||||||
|
layer = serializers.SlugField(max_length=8, required=False, allow_blank=True)
|
||||||
radius = serializers.FloatField(required=False)
|
radius = serializers.FloatField(required=False)
|
||||||
coordinates = CoordinateSerializer(many=True)
|
coordinates = CoordinateSerializer(many=True)
|
||||||
|
|
||||||
|
|
||||||
|
class LayerChildSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Layer
|
||||||
|
fields = ["name", "slug"]
|
||||||
|
|
||||||
|
|
||||||
|
class LayerSerializer(serializers.ModelSerializer):
|
||||||
|
children = LayerChildSerializer(many=True, read_only=True)
|
||||||
|
parent = serializers.SlugField(max_length=8, allow_blank=True, write_only=True)
|
||||||
|
|
||||||
|
def validate_parent(self, val):
|
||||||
|
if val:
|
||||||
|
return get_object_or_404(Layer, slug=val)
|
||||||
|
return (
|
||||||
|
get_object_or_404(
|
||||||
|
Dicom,
|
||||||
|
slug=self.context["request"].parser_context["kwargs"]["dicom_slug"],
|
||||||
|
)
|
||||||
|
.layers.filter(parent__isnull=True)
|
||||||
|
.first()
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Layer
|
||||||
|
fields = ["name", "slug", "children", "parent"]
|
||||||
|
extra_kwargs = {
|
||||||
|
"children": {"read_only": True},
|
||||||
|
"slug": {"read_only": True},
|
||||||
|
"parent": {"write_only": True},
|
||||||
|
}
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
return Layer.objects.create(
|
||||||
|
name=validated_data["name"],
|
||||||
|
dicom=validated_data["parent"].dicom,
|
||||||
|
parent=validated_data["parent"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class DicomSerializer(serializers.ModelSerializer):
|
class DicomSerializer(serializers.ModelSerializer):
|
||||||
file = serializers.FileField()
|
file = serializers.FileField()
|
||||||
shapes = serializers.SerializerMethodField("get_dicom_shapes")
|
shapes = serializers.SerializerMethodField("get_dicom_shapes")
|
||||||
|
layers = serializers.SerializerMethodField("get_dicom_layers")
|
||||||
|
|
||||||
@extend_schema_field(field=BaseShapeSerializer)
|
@extend_schema_field(field=BaseShapeSerializer(many=True))
|
||||||
def get_dicom_shapes(self, obj):
|
def get_dicom_shapes(self, obj):
|
||||||
return [x.serialize_self() for x in obj.shapes.all()]
|
return [x.serialize_self() for x in obj.shapes.all()]
|
||||||
|
|
||||||
|
@extend_schema_field(field=LayerSerializer(many=True))
|
||||||
|
def get_dicom_layers(self, obj):
|
||||||
|
return obj.get_layers()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Dicom
|
model = Dicom
|
||||||
fields = ["file", "uploaded", "pathology_type", "shapes"]
|
fields = ["file", "uploaded", "shapes", "layers"]
|
||||||
|
|
||||||
|
|
||||||
class RoiSerializer(BaseShapeSerializer, serializers.ModelSerializer):
|
class RoiSerializer(BaseShapeSerializer, serializers.ModelSerializer):
|
||||||
coordinates = CoordinateSerializer(many=True)
|
coordinates = CoordinateSerializer(many=True)
|
||||||
|
layer = serializers.SlugField(max_length=8, required=False, allow_blank=True)
|
||||||
model = Roi
|
model = Roi
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Roi
|
model = Roi
|
||||||
fields = ["id", "image_number", "coordinates"]
|
fields = ["id", "layer", "coordinates"]
|
||||||
extra_kwargs = {"id": {"read_only": True}}
|
extra_kwargs = {"id": {"read_only": True}}
|
||||||
|
|
||||||
|
|
||||||
class FreeHandSerializer(BaseShapeSerializer, serializers.ModelSerializer):
|
class FreeHandSerializer(BaseShapeSerializer, serializers.ModelSerializer):
|
||||||
|
layer = serializers.SlugField(max_length=8, required=False, allow_blank=True)
|
||||||
coordinates = CoordinateSerializer(many=True)
|
coordinates = CoordinateSerializer(many=True)
|
||||||
model = FreeHand
|
model = FreeHand
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = FreeHand
|
model = FreeHand
|
||||||
fields = ["id", "image_number", "coordinates"]
|
fields = ["id", "layer", "coordinates"]
|
||||||
extra_kwargs = {"id": {"read_only": True}}
|
extra_kwargs = {"id": {"read_only": True}}
|
||||||
|
|
||||||
|
|
||||||
class RulerSerializer(BaseShapeSerializer, serializers.ModelSerializer):
|
class RulerSerializer(BaseShapeSerializer, serializers.ModelSerializer):
|
||||||
coordinates = CoordinateSerializer(many=True)
|
coordinates = CoordinateSerializer(many=True)
|
||||||
|
layer = serializers.SlugField(max_length=8, required=False, allow_blank=True)
|
||||||
model = Ruler
|
model = Ruler
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = FreeHand
|
model = FreeHand
|
||||||
fields = ["id", "image_number", "coordinates"]
|
fields = ["id", "layer", "coordinates"]
|
||||||
extra_kwargs = {"id": {"read_only": True}}
|
extra_kwargs = {"id": {"read_only": True}}
|
||||||
|
|
||||||
|
|
||||||
class CircleSerializer(serializers.ModelSerializer):
|
class CircleSerializer(serializers.ModelSerializer):
|
||||||
coordinates = CoordinateSerializer(many=True)
|
coordinates = CoordinateSerializer(many=True)
|
||||||
|
layer = serializers.SlugField(max_length=8, required=False, allow_blank=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Circle
|
model = Circle
|
||||||
fields = ["id", "image_number", "radius", "coordinates"]
|
fields = ["id", "layer", "radius", "coordinates"]
|
||||||
extra_kwargs = {"id": {"read_only": True}}
|
extra_kwargs = {"id": {"read_only": True}}
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
|
@ -136,9 +225,12 @@ class CircleSerializer(serializers.ModelSerializer):
|
||||||
dicom = get_object_or_404(
|
dicom = get_object_or_404(
|
||||||
Dicom, slug=self.context["request"].parser_context["kwargs"]["slug"]
|
Dicom, slug=self.context["request"].parser_context["kwargs"]["slug"]
|
||||||
)
|
)
|
||||||
|
if validated_data["layer"]:
|
||||||
|
layer = get_object_or_404(Layer, slug=validated_data["layer"])
|
||||||
|
else:
|
||||||
|
layer = dicom.layers.filter(parent__isnull=True).first()
|
||||||
circle = Circle.objects.create(
|
circle = Circle.objects.create(
|
||||||
dicom=dicom,
|
layer_fk=layer,
|
||||||
image_number=validated_data["image_number"],
|
|
||||||
radius=validated_data["radius"],
|
radius=validated_data["radius"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -148,8 +240,13 @@ class CircleSerializer(serializers.ModelSerializer):
|
||||||
def update(self, obj: Circle, validated_data):
|
def update(self, obj: Circle, validated_data):
|
||||||
Coordinate.objects.filter(shape=obj).delete()
|
Coordinate.objects.filter(shape=obj).delete()
|
||||||
create_coordinate(validated_data["coordinates"], obj)
|
create_coordinate(validated_data["coordinates"], obj)
|
||||||
|
if validated_data["layer"]:
|
||||||
|
layer = get_object_or_404(Layer, slug=validated_data["layer"])
|
||||||
|
else:
|
||||||
|
layer = obj.dicom.layers.filter(parent__isnull=True).first()
|
||||||
if "radius" in validated_data:
|
if "radius" in validated_data:
|
||||||
obj.radius = validated_data["radius"]
|
obj.radius = validated_data["radius"]
|
||||||
|
obj.layer_fk = layer
|
||||||
obj.save()
|
obj.save()
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
@ -158,31 +255,6 @@ class SmartFileUploadSerializer(serializers.Serializer):
|
||||||
file = serializers.FileField()
|
file = serializers.FileField()
|
||||||
|
|
||||||
|
|
||||||
class ListProjectSerializer(serializers.ModelSerializer):
|
|
||||||
url = serializers.HyperlinkedIdentityField(
|
|
||||||
view_name="get_update_delete_project", lookup_field="slug"
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Project
|
|
||||||
fields = ["slug", "url", "created"]
|
|
||||||
extra_kwargs = {
|
|
||||||
"slug": {"read_only": True},
|
|
||||||
"created": {"read_only": True},
|
|
||||||
}
|
|
||||||
|
|
||||||
def create(self, validated_data):
|
|
||||||
return Project.objects.create(user=self.context["request"].user)
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectSerializer(serializers.ModelSerializer):
|
|
||||||
files = ListDicomSerializer(many=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Project
|
|
||||||
fields = ["files", "slug", "created", "stl"]
|
|
||||||
|
|
||||||
|
|
||||||
class PatologyGenerateSerializer(serializers.Serializer):
|
class PatologyGenerateSerializer(serializers.Serializer):
|
||||||
project_slug = serializers.CharField()
|
project_slug = serializers.CharField()
|
||||||
points = serializers.ListField(child=CoordinateSerializer())
|
points = serializers.ListField(child=CoordinateSerializer())
|
||||||
|
|
|
@ -5,7 +5,7 @@ from rest_framework.generics import GenericAPIView, get_object_or_404
|
||||||
from rest_framework.parsers import FormParser, MultiPartParser
|
from rest_framework.parsers import FormParser, MultiPartParser
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from ..models import Circle, Dicom, Project, Roi
|
from ..models import Circle, Dicom, Layer, Project, Roi
|
||||||
from ..services import process_files
|
from ..services import process_files
|
||||||
from .serializers import (
|
from .serializers import (
|
||||||
BaseShapeLayerSerializer,
|
BaseShapeLayerSerializer,
|
||||||
|
@ -13,6 +13,7 @@ from .serializers import (
|
||||||
CircleSerializer,
|
CircleSerializer,
|
||||||
DicomSerializer,
|
DicomSerializer,
|
||||||
FreeHandSerializer,
|
FreeHandSerializer,
|
||||||
|
LayerSerializer,
|
||||||
ListDicomSerializer,
|
ListDicomSerializer,
|
||||||
ListProjectSerializer,
|
ListProjectSerializer,
|
||||||
PatologyGenerateSerializer,
|
PatologyGenerateSerializer,
|
||||||
|
@ -29,12 +30,12 @@ class ListCreateDicomApi(generics.ListCreateAPIView):
|
||||||
parser_classes = [MultiPartParser, FormParser]
|
parser_classes = [MultiPartParser, FormParser]
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return Dicom.objects.filter(user=self.request.user)
|
return Dicom.objects.all()
|
||||||
|
|
||||||
|
|
||||||
class RetrieveUpdateDeleteDicomApi(generics.RetrieveUpdateDestroyAPIView):
|
class RetrieveUpdateDeleteDicomApi(generics.RetrieveUpdateDestroyAPIView):
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return Dicom.objects.filter(user=self.request.user)
|
return Dicom.objects.all()
|
||||||
|
|
||||||
serializer_class = DicomSerializer
|
serializer_class = DicomSerializer
|
||||||
parser_classes = [MultiPartParser, FormParser]
|
parser_classes = [MultiPartParser, FormParser]
|
||||||
|
@ -211,6 +212,23 @@ class ListCreateProjectApi(generics.ListCreateAPIView):
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return Project.objects.filter(user=self.request.user)
|
return Project.objects.filter(user=self.request.user)
|
||||||
|
|
||||||
|
@extend_schema(
|
||||||
|
description="""(0, 'Без патологий'),
|
||||||
|
(1, 'COVID-19; все доли; многочисленные; размер любой'),
|
||||||
|
(2, 'COVID-19; Нижняя доля правого лёгкого, Нижняя доля левого лёгкого'),
|
||||||
|
(3, 'Немногочисленные; 10-20 мм'),
|
||||||
|
(4, 'Рак лёгкого; Нижняя доля правого лёгкого, Единичное; 10-20 мм'),
|
||||||
|
(5, 'Рак лёгкого; Средняя доля правого лёгкого, Единичное; >20 мм'),
|
||||||
|
(6, 'Рак лёгкого; Нижняя доля левого лёгкого, Единичное; 10-20 мм'),
|
||||||
|
(7, 'Рак лёгкого; Верхняя доля правого лёгкого, Единичное; 5-10 мм'),
|
||||||
|
(8, 'Рак лёгкого; Верхняя доля левого лёгкого, Единичное; 5-10 мм'),
|
||||||
|
(9, 'Метастатическое поражение лёгких; Все доли; Многочисленные; 5-10 мм'),
|
||||||
|
(10, 'Метастатическое поражение лёгких; Все доли; Многочисленные; 10-20 мм'),
|
||||||
|
(11, 'Метастатическое поражение лёгких; Все доли; Немногочисленные; 5-10 мм')"""
|
||||||
|
)
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
return self.create(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class RetrieveUpdateDeleteProjectApi(generics.RetrieveUpdateDestroyAPIView):
|
class RetrieveUpdateDeleteProjectApi(generics.RetrieveUpdateDestroyAPIView):
|
||||||
serializer_class = ProjectSerializer
|
serializer_class = ProjectSerializer
|
||||||
|
@ -226,3 +244,14 @@ class GeneratePatology(generics.CreateAPIView):
|
||||||
# data = self.get_serializer(request.data).data
|
# data = self.get_serializer(request.data).data
|
||||||
# bbox = get_bbox(data["project_slug"], data["points"], data["depth"])
|
# bbox = get_bbox(data["project_slug"], data["points"], data["depth"])
|
||||||
return Response(data={}, status=200)
|
return Response(data={}, status=200)
|
||||||
|
|
||||||
|
|
||||||
|
class CreateLayerApi(generics.CreateAPIView):
|
||||||
|
serializer_class = LayerSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class RetrieveUpdateDeleteLayerApi(generics.RetrieveUpdateDestroyAPIView):
|
||||||
|
serializer_class = LayerSerializer
|
||||||
|
queryset = Layer.objects.all()
|
||||||
|
|
||||||
|
lookup_field = "slug"
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from dicom.models.shapes import BaseShape
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
@ -75,6 +76,13 @@ class Dicom(models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.file.name
|
return self.file.name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def shapes(self):
|
||||||
|
return BaseShape.objects.filter(layer_fk__dicom=self)
|
||||||
|
|
||||||
|
def get_layers(self):
|
||||||
|
return self.layers.filter(parent__isnull=True).first().serialize_self()
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("get_update_delete_dicom", kwargs={"slug": self.slug})
|
return reverse("get_update_delete_dicom", kwargs={"slug": self.slug})
|
||||||
|
|
||||||
|
@ -87,5 +95,12 @@ class Layer(models.Model):
|
||||||
name = models.CharField(max_length=200)
|
name = models.CharField(max_length=200)
|
||||||
slug = models.SlugField(max_length=8)
|
slug = models.SlugField(max_length=8)
|
||||||
|
|
||||||
|
def serialize_self(self):
|
||||||
|
return {
|
||||||
|
"slug": self.slug,
|
||||||
|
"name": self.name,
|
||||||
|
"children": [x.serialize_self() for x in self.children.all()],
|
||||||
|
}
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"layer on {self.dicom}"
|
return f"layer on {self.dicom}"
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
from dicom.models import Layer
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from polymorphic.models import PolymorphicModel
|
from polymorphic.models import PolymorphicModel
|
||||||
|
|
||||||
|
@ -7,14 +6,16 @@ class BaseShape(PolymorphicModel):
|
||||||
TYPE = "no_type"
|
TYPE = "no_type"
|
||||||
min_coordinates = None
|
min_coordinates = None
|
||||||
max_coordinates = None
|
max_coordinates = None
|
||||||
layer = models.ForeignKey(Layer, related_name="shapes", on_delete=models.CASCADE)
|
layer_fk = models.ForeignKey(
|
||||||
|
"dicom.Layer", related_name="shapes", on_delete=models.CASCADE
|
||||||
|
)
|
||||||
|
|
||||||
def serialize_self(self):
|
def serialize_self(self):
|
||||||
return {
|
return {
|
||||||
"id": self.id,
|
"id": self.id,
|
||||||
"type": self.TYPE,
|
"type": self.TYPE,
|
||||||
"image_number": self.image_number,
|
|
||||||
"coordinates": self.coordinates,
|
"coordinates": self.coordinates,
|
||||||
|
"layer": self.layer,
|
||||||
}
|
}
|
||||||
|
|
||||||
def serialize_self_without_layer(self):
|
def serialize_self_without_layer(self):
|
||||||
|
@ -24,12 +25,16 @@ class BaseShape(PolymorphicModel):
|
||||||
"coordinates": self.coordinates,
|
"coordinates": self.coordinates,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def layer(self):
|
||||||
|
return self.layer_fk.slug
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def coordinates(self) -> [(int, int)]:
|
def coordinates(self) -> [(int, int)]:
|
||||||
return self.shape_coordinates.all().values("x", "y")
|
return self.shape_coordinates.all().values("x", "y")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.dicom.file.name
|
return f"{self.TYPE} on {self.layer}"
|
||||||
|
|
||||||
|
|
||||||
class Coordinate(models.Model):
|
class Coordinate(models.Model):
|
||||||
|
@ -53,7 +58,6 @@ class Circle(BaseShape):
|
||||||
return {
|
return {
|
||||||
"id": self.id,
|
"id": self.id,
|
||||||
"type": "circle",
|
"type": "circle",
|
||||||
"image_number": self.image_number,
|
|
||||||
"radius": self.radius,
|
"radius": self.radius,
|
||||||
"coordinates": self.coordinates,
|
"coordinates": self.coordinates,
|
||||||
}
|
}
|
||||||
|
@ -66,28 +70,16 @@ class Circle(BaseShape):
|
||||||
"coordinates": self.coordinates,
|
"coordinates": self.coordinates,
|
||||||
}
|
}
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f"circle on {self.dicom.file.name}"
|
|
||||||
|
|
||||||
|
|
||||||
class Roi(BaseShape):
|
class Roi(BaseShape):
|
||||||
TYPE = "roi"
|
TYPE = "roi"
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f"Roi on {self.dicom.file.name}"
|
|
||||||
|
|
||||||
|
|
||||||
class FreeHand(BaseShape):
|
class FreeHand(BaseShape):
|
||||||
TYPE = "free_hand"
|
TYPE = "free_hand"
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f"FreeHand on {self.dicom.file.name}"
|
|
||||||
|
|
||||||
|
|
||||||
class Ruler(BaseShape):
|
class Ruler(BaseShape):
|
||||||
TYPE = "ruler"
|
TYPE = "ruler"
|
||||||
max_coordinates = 2
|
max_coordinates = 2
|
||||||
min_coordinates = 2
|
min_coordinates = 2
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f"Ruler on {self.dicom.file.name}"
|
|
||||||
|
|
|
@ -43,7 +43,6 @@ def process_files(
|
||||||
Dicom.objects.create(
|
Dicom.objects.create(
|
||||||
file=File(f, name=file_in_d.split("/")[-1]),
|
file=File(f, name=file_in_d.split("/")[-1]),
|
||||||
project=project,
|
project=project,
|
||||||
user=user,
|
|
||||||
)
|
)
|
||||||
shutil.rmtree(dit_path)
|
shutil.rmtree(dit_path)
|
||||||
tasks.process_project.apply_async(kwargs={"pk": project.pk}, countdown=3)
|
tasks.process_project.apply_async(kwargs={"pk": project.pk}, countdown=3)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from dicom.models import Dicom, Project
|
from dicom.models import Dicom, Layer, Project
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from utils.generators import generate_charset
|
from utils.generators import generate_charset
|
||||||
|
@ -22,3 +22,14 @@ def create_dicom(sender, instance: Dicom, created, **kwargs):
|
||||||
slug = generate_charset(5)
|
slug = generate_charset(5)
|
||||||
instance.slug = slug
|
instance.slug = slug
|
||||||
instance.save()
|
instance.save()
|
||||||
|
Layer.objects.create(parent=None, dicom=instance, name="root")
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_save, sender=Layer)
|
||||||
|
def create_layer(sender, instance: Layer, created, **kwargs):
|
||||||
|
if created:
|
||||||
|
slug = generate_charset(8)
|
||||||
|
while Layer.objects.filter(slug=slug):
|
||||||
|
slug = generate_charset(8)
|
||||||
|
instance.slug = slug
|
||||||
|
instance.save()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user