added layer operations

This commit is contained in:
Alexander Karpov 2022-10-30 16:40:46 +03:00
parent 3061d1cfac
commit 8c53cb6745
4 changed files with 87 additions and 14 deletions

View File

@ -1,10 +1,11 @@
from dicom.api.views import ( from dicom.api.views import (
CreateCircleApi, CreateCircleApi,
CreateroiApi, CreateRoiApi,
ListCreateDicomApi, ListCreateDicomApi,
ListUpdateDicomImageNumberApi,
RetrieveUpdateDeleteCircleApi, RetrieveUpdateDeleteCircleApi,
RetrieveUpdateDeleteDicomApi, RetrieveUpdateDeleteDicomApi,
RetrieveUpdateDeleteroiApi, RetrieveUpdateDeleteRoiApi,
SmartFileUploadApi, SmartFileUploadApi,
) )
from django.urls import include, path from django.urls import include, path
@ -26,7 +27,7 @@ urlpatterns = [
"dicom/", "dicom/",
include( include(
[ [
path("", ListCreateDicomApi.as_view(), name="list_create_dicom"), path("", ListCreateDicomApi.as_view(), name="dicom_list_create"),
path("upload", SmartFileUploadApi.as_view(), name="upload_dicom_api"), path("upload", SmartFileUploadApi.as_view(), name="upload_dicom_api"),
path( path(
"<str:slug>", "<str:slug>",
@ -34,8 +35,8 @@ urlpatterns = [
name="get_update_delete_dicom", name="get_update_delete_dicom",
), ),
path( path(
"<str:slug>/Roi", "<str:slug>/roi",
CreateroiApi.as_view(), CreateRoiApi.as_view(),
name="create_roi", name="create_roi",
), ),
path( path(
@ -43,6 +44,11 @@ urlpatterns = [
CreateCircleApi.as_view(), CreateCircleApi.as_view(),
name="create_circle", name="create_circle",
), ),
path(
"<str:slug>/<int:layer>",
ListUpdateDicomImageNumberApi.as_view(),
name="update_dicom_layer",
),
] ]
), ),
), ),
@ -51,8 +57,8 @@ urlpatterns = [
include( include(
[ [
path( path(
"Roi/<int:id>", "roi/<int:id>",
RetrieveUpdateDeleteroiApi.as_view(), RetrieveUpdateDeleteRoiApi.as_view(),
name="get_update_delete_roi", name="get_update_delete_roi",
), ),
path( path(

View File

@ -34,11 +34,17 @@ class ListDicomSerializer(serializers.ModelSerializer):
class BaseShapeSerializer(serializers.Serializer): class BaseShapeSerializer(serializers.Serializer):
type = serializers.ChoiceField(choices=["circle", "Roi"]) type = serializers.ChoiceField(choices=["circle", "roi"])
image_number = serializers.IntegerField() image_number = serializers.IntegerField()
coordinates = CoordinateSerializer(many=True) coordinates = CoordinateSerializer(many=True)
class BaseShapeLayerSerializer(serializers.Serializer):
type = serializers.ChoiceField(choices=["circle", "roi"])
radius = serializers.FloatField(required=False)
coordinates = CoordinateSerializer(many=True)
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")

View File

@ -8,11 +8,14 @@ from rest_framework.response import Response
from ..models import Circle, Dicom, Roi from ..models import Circle, Dicom, Roi
from ..services import process_files from ..services import process_files
from .serializers import ( from .serializers import (
BaseShapeLayerSerializer,
BaseShapeSerializer,
CircleSerializer, CircleSerializer,
DicomSerializer, DicomSerializer,
ListDicomSerializer, ListDicomSerializer,
RoiSerializer, RoiSerializer,
SmartFileUploadSerializer, SmartFileUploadSerializer,
create_coordinate,
) )
@ -34,7 +37,7 @@ class RetrieveUpdateDeleteDicomApi(generics.RetrieveUpdateDestroyAPIView):
lookup_field = "slug" lookup_field = "slug"
class CreateroiApi(generics.CreateAPIView): class CreateRoiApi(generics.CreateAPIView):
serializer_class = RoiSerializer serializer_class = RoiSerializer
@ -42,7 +45,7 @@ class CreateCircleApi(generics.CreateAPIView):
serializer_class = CircleSerializer serializer_class = CircleSerializer
class RetrieveUpdateDeleteroiApi(generics.RetrieveUpdateDestroyAPIView): class RetrieveUpdateDeleteRoiApi(generics.RetrieveUpdateDestroyAPIView):
serializer_class = RoiSerializer serializer_class = RoiSerializer
def get_object(self): def get_object(self):
@ -87,5 +90,47 @@ class SmartFileUploadApi(GenericAPIView):
) )
class UpdateDicomLayerApi(GenericAPIView): class ListUpdateDicomImageNumberApi(GenericAPIView):
serializer_class = SmartFileUploadSerializer serializer_class = BaseShapeSerializer(many=True)
@extend_schema(
request=None,
responses={200: BaseShapeSerializer(many=True)},
operation_id="get_dicom_layer",
)
def get(self, request, slug, layer):
shapes = [
x.serialize_self_without_layer()
for x in get_object_or_404(Dicom, slug=slug).shapes.filter(
image_number=layer
)
]
return Response(shapes, status=status.HTTP_200_OK)
@extend_schema(
request=BaseShapeLayerSerializer(many=True),
responses={201: DicomSerializer},
operation_id="update_dicom_layer",
)
def put(self, request, slug, layer):
dicom = get_object_or_404(Dicom, slug=slug)
dicom.shapes.filter(image_number=layer).delete()
serializer = BaseShapeLayerSerializer(data=request.data, many=True)
serializer.is_valid(raise_exception=True)
for shape in serializer.data:
if shape["type"] == "circle":
obj = Circle.objects.create(
dicom=dicom, image_number=layer, radius=shape["radius"]
)
if len(shape["coordinates"]) > 1:
raise ValidationError
elif shape["type"] == "roi":
obj = Roi.objects.create(dicom=dicom, image_number=layer)
create_coordinate(shape["coordinates"], obj)
shapes = [
x.serialize_self_without_layer()
for x in get_object_or_404(Dicom, slug=slug).shapes.filter(
image_number=layer
)
]
return Response(shapes, status=status.HTTP_200_OK)

View File

@ -32,7 +32,7 @@ class Coordinate(models.Model):
class Circle(BaseShape): class Circle(BaseShape):
radius = models.IntegerField() radius = models.FloatField()
def serialize_self(self): def serialize_self(self):
return { return {
@ -43,6 +43,14 @@ class Circle(BaseShape):
"coordinates": self.coordinates, "coordinates": self.coordinates,
} }
def serialize_self_without_layer(self):
return {
"id": self.id,
"type": "circle",
"radius": self.radius,
"coordinates": self.coordinates,
}
def __str__(self): def __str__(self):
return f"circle on {self.dicom.file.name}" return f"circle on {self.dicom.file.name}"
@ -51,10 +59,18 @@ class Roi(BaseShape):
def serialize_self(self): def serialize_self(self):
return { return {
"id": self.id, "id": self.id,
"type": "Roi", "type": "roi",
"image_number": self.image_number, "image_number": self.image_number,
"coordinates": self.coordinates, "coordinates": self.coordinates,
} }
def serialize_self_without_layer(self):
return {
"id": self.id,
"type": "roi",
"radius": self.radius,
"coordinates": self.coordinates,
}
def __str__(self): def __str__(self):
return f"Roi on {self.dicom.file.name}" return f"Roi on {self.dicom.file.name}"