Skip to content
This repository has been archived by the owner on Feb 22, 2020. It is now read-only.

Commit

Permalink
add backend lung orientation selection
Browse files Browse the repository at this point in the history
  • Loading branch information
WGierke authored and lamby committed Sep 23, 2017
1 parent 44d5016 commit 30b3818
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 1 deletion.
8 changes: 8 additions & 0 deletions docs/apidoc_interface/backend.cases.migrations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ backend.cases.migrations.0001_initial module
:undoc-members:
:show-inheritance:

backend.cases.migrations.0002_nodule_lung_orientation module
------------------------------------------------------------

.. automodule:: backend.cases.migrations.0002_nodule_lung_orientation
:members:
:undoc-members:
:show-inheritance:


Module contents
---------------
Expand Down
2 changes: 2 additions & 0 deletions interface/backend/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
candidate_mark,
candidate_dismiss,
case_report,
nodule_update
)
from django.conf.urls import (
include,
Expand All @@ -27,6 +28,7 @@
url(r'^images/available$', ImageAvailableApiView.as_view(), name='images-available'),
url(r'^candidates/(?P<candidate_id>\d+)/dismiss$', candidate_dismiss, name='candidate-dismiss'),
url(r'^candidates/(?P<candidate_id>\d+)/mark$', candidate_mark, name='candidate-mark'),
url(r'^nodules/(?P<nodule_id>\d+)/update$', nodule_update, name='nodule-update'),
]

# Support different suffixes
Expand Down
20 changes: 20 additions & 0 deletions interface/backend/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,23 @@ def case_report(request, case_id, format=None):
case = get_object_or_404(Case, pk=case_id)

return Response(CaseSerializer(case).data)


@api_view(['POST'])
def nodule_update(request, nodule_id):
try:
lung_orientation = json.loads(request.body)['lung_orientation']
except Exception as e:
return Response({'response': "An error occurred: {}".format(e)}, 500)

if lung_orientation is None:
lung_orientation = 'NONE'

orientation_choices = [orientation.name for orientation in Nodule.LungOrientation]

if lung_orientation not in orientation_choices:
return Response({'response': "ValueError: lung_orientation must be one of {}".format(orientation_choices)}, 500)

Nodule.objects.filter(pk=nodule_id).update(lung_orientation=Nodule.LungOrientation[lung_orientation].value)
return Response(
{'response': "Lung orientation of nodule {} has been changed to '{}'".format(nodule_id, lung_orientation)})
20 changes: 20 additions & 0 deletions interface/backend/cases/migrations/0002_nodule_lung_orientation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.3 on 2017-09-15 11:46
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('cases', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='nodule',
name='lung_orientation',
field=models.IntegerField(choices=[(0, 'NONE'), (1, 'LEFT'), (2, 'RIGHT')], default=0),
),
]
22 changes: 21 additions & 1 deletion interface/backend/cases/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from enum import IntEnum, unique

from backend.images.models import ImageSeriesSerializer, ImageLocationSerializer
from django.core.validators import (
MaxValueValidator,
Expand Down Expand Up @@ -30,10 +32,24 @@ class Candidate(models.Model):
probability_concerning = models.FloatField(validators=[MinValueValidator(0.0), MaxValueValidator(1.0)])


def django_enum(cls):
# decorator needed to enable enums in django templates
cls.do_not_call_in_templates = True
return cls


class Nodule(models.Model):
"""
Actual nodule, either confirmed as concerning from prediciton or manually added.
Actual nodule, either confirmed as concerning from prediction or manually added.
"""

@unique # ensures all variables are unique
@django_enum
class LungOrientation(IntEnum):
NONE = 0
LEFT = 1
RIGHT = 2

created = models.DateTimeField(default=timezone.now)

case = models.ForeignKey(Case, on_delete=models.CASCADE, related_name='nodules')
Expand All @@ -42,6 +58,10 @@ class Nodule(models.Model):

centroid = models.OneToOneField('images.ImageLocation', on_delete=models.CASCADE)

lung_orientation = models.IntegerField(
choices=[(choice.value, choice.name.replace("_", " ")) for choice in LungOrientation],
default=LungOrientation.NONE.value)


class CandidateSerializer(serializers.ModelSerializer):
centroid = ImageLocationSerializer(read_only=True)
Expand Down
18 changes: 18 additions & 0 deletions interface/backend/cases/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,21 @@ def assertDictContainsNestedSubset(superset, subset):
self.assertEqual(nodule2_dict['centroid']['x'], 10)
self.assertEqual(nodule2_dict['centroid']['y'], 20)
self.assertEqual(nodule2_dict['centroid']['z'], 30)

def test_update_nodule_lung_orientation(self):
nodule = NoduleFactory()
url = reverse('nodule-update', kwargs={'nodule_id': nodule.id})

self.assertEquals(nodule.lung_orientation, Nodule.LungOrientation.NONE.value)

self.client.post(url, json.dumps({'lung_orientation': 'LEFT'}), 'application/json')
nodule.refresh_from_db()
self.assertEquals(nodule.lung_orientation, Nodule.LungOrientation.LEFT.value)

self.client.post(url, json.dumps({'lung_orientation': 'RIGHT'}), 'application/json')
nodule.refresh_from_db()
self.assertEquals(nodule.lung_orientation, Nodule.LungOrientation.RIGHT.value)

self.client.post(url, json.dumps({'lung_orientation': 'NONE'}), 'application/json')
nodule.refresh_from_db()
self.assertEquals(nodule.lung_orientation, Nodule.LungOrientation.NONE.value)

0 comments on commit 30b3818

Please sign in to comment.