work on case priors
This commit is contained in:
@@ -24,6 +24,7 @@ from atlas.models import (
|
|||||||
Case,
|
Case,
|
||||||
CaseCollection,
|
CaseCollection,
|
||||||
CaseDetail,
|
CaseDetail,
|
||||||
|
CasePrior,
|
||||||
CidReportAnswer,
|
CidReportAnswer,
|
||||||
Differential,
|
Differential,
|
||||||
Finding,
|
Finding,
|
||||||
@@ -858,10 +859,19 @@ class QuestionSchemaForm(ModelForm):
|
|||||||
"schema": SvelteJSONEditorWidgetOverride(),
|
"schema": SvelteJSONEditorWidgetOverride(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#class ModelPriorCaseForm(ModelForm):
|
||||||
|
# class Meta:
|
||||||
|
# model = CasePrior
|
||||||
|
# fields = ["case_detail", "prior_case", "relation_text", "prior_visibility"]
|
||||||
|
|
||||||
class PriorCaseForm(Form):
|
class PriorCaseForm(Form):
|
||||||
|
|
||||||
relation = CharField(max_length=255, required=True)
|
relation = CharField(max_length=255, required=True)
|
||||||
|
|
||||||
|
prior_visibility = CharField(max_length=2, required=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#def __init__(self, *args, **kwargs):
|
#def __init__(self, *args, **kwargs):
|
||||||
# self.case_detail = kwargs.pop(
|
# self.case_detail = kwargs.pop(
|
||||||
# "case_detail"
|
# "case_detail"
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.1.4 on 2025-04-28 15:04
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('atlas', '0068_alter_seriesfinding_description'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='caseprior',
|
||||||
|
name='prior_visibility',
|
||||||
|
field=models.CharField(choices=[('NO', 'None'), ('AL', 'Always'), ('RE', 'Review')], default='AL', help_text='Defines when the prior case is shown to the user', max_length=2),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -1118,6 +1118,19 @@ class CasePrior(models.Model):
|
|||||||
|
|
||||||
relation_text = models.CharField(max_length=255, blank=True, help_text="Text to describe the relationship between the cases")
|
relation_text = models.CharField(max_length=255, blank=True, help_text="Text to describe the relationship between the cases")
|
||||||
|
|
||||||
|
class PriorVisibility(models.TextChoices):
|
||||||
|
NONE = "NO", _("None")
|
||||||
|
ALWAYS = "AL", _("Always")
|
||||||
|
REVIEW = "RE", _("Review")
|
||||||
|
|
||||||
|
|
||||||
|
prior_visibility = models.CharField(
|
||||||
|
max_length=2,
|
||||||
|
choices=PriorVisibility.choices,
|
||||||
|
default=PriorVisibility.ALWAYS,
|
||||||
|
help_text="Defines when the prior case is shown to the user",
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ("case_detail", "prior_case")
|
unique_together = ("case_detail", "prior_case")
|
||||||
|
|
||||||
|
|||||||
@@ -253,7 +253,7 @@
|
|||||||
<button
|
<button
|
||||||
hx-get="{% url 'atlas:case_collection_form' case.pk %}"
|
hx-get="{% url 'atlas:case_collection_form' case.pk %}"
|
||||||
hx-target="#collection-form">
|
hx-target="#collection-form">
|
||||||
Add collection</button>
|
Add to collection</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div id="collection-form"></div>
|
<div id="collection-form"></div>
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<h3>Available priors</h3>
|
<h3>Available priors</h3>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
{% for case, added, relation in available_priors %}
|
{% for case, added, relation, visibility in available_priors %}
|
||||||
|
|
||||||
<li class='
|
<li class='
|
||||||
{% if added %}
|
{% if added %}
|
||||||
@@ -38,24 +38,63 @@
|
|||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
{% if not added %}
|
{% if not added %}
|
||||||
<form hx-post="{% url 'atlas:collection_case_priors' collection.id case_detail.case.pk %}"
|
<form hx-post="{% url 'atlas:collection_case_priors' collection.id case_detail.case.pk %}"
|
||||||
hx-target="#htmx-response-{{case.id}}"
|
hx-target="#htmx-response-{{case.id}}"
|
||||||
_="on htmx:afterRequest log 'test' then remove me"
|
_="on htmx:afterRequest log 'test' then remove me">
|
||||||
>
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="prior_case_id" value="{{case.id}}" />
|
<input type="hidden" name="prior_case_id" value="{{case.id}}" />
|
||||||
<input type="text" name="relation" value="{{relation}}" placeholder="relation to case" />
|
<input type="text" name="relation" value="{{relation}}" placeholder="relation to case" />
|
||||||
|
<br />
|
||||||
|
<label for="prior_visibility_{{case.id}}">Visibility:</label>
|
||||||
|
<select name="prior_visibility" id="prior_visibility_{{case.id}}">
|
||||||
|
<option value="AL"
|
||||||
|
{% if visibility == 'AL' %}
|
||||||
|
selected
|
||||||
|
{% endif %}
|
||||||
|
>Always</option>
|
||||||
|
<option value="RE"
|
||||||
|
{% if visibility == 'RE' %}
|
||||||
|
selected
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
>Review</option>
|
||||||
|
<option value="NO"
|
||||||
|
{% if visibility == 'NO' %}
|
||||||
|
selected
|
||||||
|
{% endif %}
|
||||||
|
>None</option>
|
||||||
|
</select>
|
||||||
|
<br />
|
||||||
<button class="btn primary">Add to case</button>
|
<button class="btn primary">Add to case</button>
|
||||||
</form>
|
</form>
|
||||||
{% else %}
|
{% else %}
|
||||||
<form hx-post="{% url 'atlas:collection_case_priors' collection.id case_detail.case.pk %}"
|
<form hx-post="{% url 'atlas:collection_case_priors' collection.id case_detail.case.pk %}"
|
||||||
hx-target="#htmx-response-{{case.id}}"
|
hx-target="#htmx-response-{{case.id}}"
|
||||||
_="on htmx:afterRequest log 'test' then remove me"
|
_="on htmx:afterRequest log 'test' then remove me">
|
||||||
>
|
|
||||||
Case available: {{relation}}
|
Case available: {{relation}}
|
||||||
<input type="hidden" name="remove" value="{{case.id}}" />
|
<input type="hidden" name="remove" value="{{case.id}}" />
|
||||||
|
<br />
|
||||||
|
<label for="prior_visibility_{{case.id}}">Visibility:</label>
|
||||||
|
<select name="prior_visibility" id="prior_visibility_{{case.id}}" disabled>
|
||||||
|
<option value="AL"
|
||||||
|
{% if visibility == 'AL' %}
|
||||||
|
selected
|
||||||
|
{% endif %}
|
||||||
|
>Always</option>
|
||||||
|
<option value="RE"
|
||||||
|
{% if visibility == 'RE' %}
|
||||||
|
selected
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
>Review</option>
|
||||||
|
<option value="NO"
|
||||||
|
{% if visibility == 'NO' %}
|
||||||
|
selected
|
||||||
|
{% endif %}
|
||||||
|
>None</option>
|
||||||
|
</select>
|
||||||
|
<br />
|
||||||
<button class="btn primary">Remove from case</button>
|
<button class="btn primary">Remove from case</button>
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -49,14 +49,24 @@
|
|||||||
|
|
||||||
{% if collection.show_ohif_viewer %}
|
{% if collection.show_ohif_viewer %}
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
|
{% if question_completed %}
|
||||||
|
<iframe id="viewer" style="width: 100%; height: 100%; border: none; padding: 0px; min-height: 700px" src="/ohif/viewer/dicomjson?url=https://www.penracourses.org.uk{% url 'atlas:collection_case_dicom_json_review' collection.pk case.pk %}"></iframe>
|
||||||
|
{% else %}
|
||||||
<iframe id="viewer" style="width: 100%; height: 100%; border: none; padding: 0px; min-height: 700px" src="/ohif/viewer/dicomjson?url=https://www.penracourses.org.uk{% url 'atlas:collection_case_dicom_json' collection.pk case.pk %}"></iframe>
|
<iframe id="viewer" style="width: 100%; height: 100%; border: none; padding: 0px; min-height: 700px" src="/ohif/viewer/dicomjson?url=https://www.penracourses.org.uk{% url 'atlas:collection_case_dicom_json' collection.pk case.pk %}"></iframe>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
{% if collection.show_ohif_viewer_link %}
|
{% if collection.show_ohif_viewer_link %}
|
||||||
<div>
|
<div>
|
||||||
|
{% if question_completed %}
|
||||||
|
<a target="_blank" href="/ohif/viewer/dicomjson?url=https://www.penracourses.org.uk{% url 'atlas:collection_case_dicom_json_review' collection.pk case.pk %}" title="Click to open the case in the advanced viewer. This will open in a new tab/window."><button class="viewer"><i class="bi bi-collection"></i> Launch advanced viewer.</button></a>
|
||||||
|
{% else %}
|
||||||
<a target="_blank" href="/ohif/viewer/dicomjson?url=https://www.penracourses.org.uk{% url 'atlas:collection_case_dicom_json' collection.pk case.pk %}" title="Click to open the case in the advanced viewer. This will open in a new tab/window."><button class="viewer"><i class="bi bi-collection"></i> Launch advanced viewer.</button></a>
|
<a target="_blank" href="/ohif/viewer/dicomjson?url=https://www.penracourses.org.uk{% url 'atlas:collection_case_dicom_json' collection.pk case.pk %}" title="Click to open the case in the advanced viewer. This will open in a new tab/window."><button class="viewer"><i class="bi bi-collection"></i> Launch advanced viewer.</button></a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|||||||
@@ -138,6 +138,11 @@ urlpatterns = [
|
|||||||
views.collection_case_dicom_json,
|
views.collection_case_dicom_json,
|
||||||
name="collection_case_dicom_json",
|
name="collection_case_dicom_json",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"collection/<int:exam_id>/case/<int:case_id>/dicom_json/review",
|
||||||
|
views.collection_case_dicom_json_review,
|
||||||
|
name="collection_case_dicom_json_review",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"collection/<int:exam_id>/question_schemas",
|
"collection/<int:exam_id>/question_schemas",
|
||||||
views.collection_question_schemas,
|
views.collection_question_schemas,
|
||||||
|
|||||||
+33
-17
@@ -56,6 +56,7 @@ from .forms import (
|
|||||||
ExamGroupsForm,
|
ExamGroupsForm,
|
||||||
FindingForm,
|
FindingForm,
|
||||||
JsonAnswerForm,
|
JsonAnswerForm,
|
||||||
|
#ModelPriorCaseForm,
|
||||||
PriorCaseForm,
|
PriorCaseForm,
|
||||||
QuestionSchemaForm,
|
QuestionSchemaForm,
|
||||||
ResourceForm,
|
ResourceForm,
|
||||||
@@ -493,7 +494,7 @@ def add_case_to_collection(request, collection_id):
|
|||||||
return HttpResponse("Case already in collection")
|
return HttpResponse("Case already in collection")
|
||||||
print(case)
|
print(case)
|
||||||
collection.add_case(case)
|
collection.add_case(case)
|
||||||
return HttpResponse("Case added to collection (refresh to see)")
|
return HttpResponse(f"Case added to collection {collection.name} (refresh to see)")
|
||||||
|
|
||||||
# if request.method == "POST":
|
# if request.method == "POST":
|
||||||
|
|
||||||
@@ -1766,6 +1767,7 @@ def collection_case_priors(request, exam_id, case_id):
|
|||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
"You need to enter text to describe the relationship between the cases"
|
"You need to enter text to describe the relationship between the cases"
|
||||||
)
|
)
|
||||||
|
p.prior_visibility = request.POST["prior_visibility"]
|
||||||
|
|
||||||
p.save()
|
p.save()
|
||||||
|
|
||||||
@@ -1780,7 +1782,7 @@ def collection_case_priors(request, exam_id, case_id):
|
|||||||
|
|
||||||
added_relation_map = {}
|
added_relation_map = {}
|
||||||
for prior in added_priors:
|
for prior in added_priors:
|
||||||
added_relation_map[prior.prior_case] = prior.relation_text
|
added_relation_map[prior.prior_case] = (prior.relation_text, prior.prior_visibility)
|
||||||
|
|
||||||
case = case_detail.case
|
case = case_detail.case
|
||||||
|
|
||||||
@@ -1789,9 +1791,9 @@ def collection_case_priors(request, exam_id, case_id):
|
|||||||
available_priors = []
|
available_priors = []
|
||||||
for case in available_cases:
|
for case in available_cases:
|
||||||
if case in added_relation_map:
|
if case in added_relation_map:
|
||||||
available_priors.append((case, True, added_relation_map[case]))
|
available_priors.append((case, True, added_relation_map[case][0], added_relation_map[case][1]))
|
||||||
else:
|
else:
|
||||||
available_priors.append((case, False, ""))
|
available_priors.append((case, False, "", "AL"))
|
||||||
|
|
||||||
form = PriorCaseForm()
|
form = PriorCaseForm()
|
||||||
|
|
||||||
@@ -1808,6 +1810,7 @@ def collection_case_priors(request, exam_id, case_id):
|
|||||||
{
|
{
|
||||||
"case_detail": case_detail,
|
"case_detail": case_detail,
|
||||||
"form": form,
|
"form": form,
|
||||||
|
#"model_form": model_form,
|
||||||
# "example_form": example_form,
|
# "example_form": example_form,
|
||||||
"collection": collection,
|
"collection": collection,
|
||||||
"case": case_detail.case,
|
"case": case_detail.case,
|
||||||
@@ -2302,17 +2305,6 @@ def collection_case_view_take(
|
|||||||
|
|
||||||
series_list = case.series.all().prefetch_related("images", "examination", "plane")
|
series_list = case.series.all().prefetch_related("images", "examination", "plane")
|
||||||
|
|
||||||
prior_cases = case_detail.caseprior_set.all()
|
|
||||||
|
|
||||||
series_to_load = []
|
|
||||||
|
|
||||||
for series in series_list:
|
|
||||||
series_to_load.append((series, False, ""))
|
|
||||||
|
|
||||||
for prior in prior_cases:
|
|
||||||
for series in prior.prior_case.get_series():
|
|
||||||
series_to_load.append((series, True, prior.relation_text))
|
|
||||||
|
|
||||||
previous = case_number > 0
|
previous = case_number > 0
|
||||||
next = case_number < (case_count - 1)
|
next = case_number < (case_count - 1)
|
||||||
|
|
||||||
@@ -2348,6 +2340,25 @@ def collection_case_view_take(
|
|||||||
|
|
||||||
resources = case.caseresource_set.filter(pre_review=True)
|
resources = case.caseresource_set.filter(pre_review=True)
|
||||||
|
|
||||||
|
prior_cases = case_detail.caseprior_set.all()
|
||||||
|
|
||||||
|
series_to_load = []
|
||||||
|
|
||||||
|
for series in series_list:
|
||||||
|
series_to_load.append((series, False, ""))
|
||||||
|
|
||||||
|
for prior in prior_cases:
|
||||||
|
match prior.prior_visibility:
|
||||||
|
case "AL":
|
||||||
|
for series in prior.prior_case.get_series():
|
||||||
|
series_to_load.append((series, True, prior.relation_text))
|
||||||
|
case "RE":
|
||||||
|
if question_completed:
|
||||||
|
for series in prior.prior_case.get_series():
|
||||||
|
series_to_load.append((series, True, prior.relation_text))
|
||||||
|
case _:
|
||||||
|
continue
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"atlas/collection_case_view_take.html",
|
"atlas/collection_case_view_take.html",
|
||||||
@@ -2437,11 +2448,16 @@ def use_dates_as_descriptions(request, pk):
|
|||||||
|
|
||||||
return HttpResponse("Done")
|
return HttpResponse("Done")
|
||||||
|
|
||||||
|
def collection_case_dicom_json_review(request, exam_id, case_id):
|
||||||
|
return collection_case_dicom_json(request, exam_id, case_id, review=True)
|
||||||
|
|
||||||
def collection_case_dicom_json(request, exam_id, case_id):
|
def collection_case_dicom_json(request, exam_id, case_id, review=False):
|
||||||
case_detail = CaseDetail.objects.get(case=case_id, collection=exam_id)
|
case_detail = CaseDetail.objects.get(case=case_id, collection=exam_id)
|
||||||
|
|
||||||
priors = case_detail.caseprior_set.all()
|
if review:
|
||||||
|
priors = case_detail.caseprior_set.exclude(prior_visibility="NO")
|
||||||
|
else:
|
||||||
|
priors = case_detail.caseprior_set.exclude(prior_visibility__in=["NO", "RE"])
|
||||||
|
|
||||||
return JsonResponse(case_detail.case.get_case_dicom_json(priors=priors))
|
return JsonResponse(case_detail.case.get_case_dicom_json(priors=priors))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user