add a normals feature
This commit is contained in:
@@ -456,6 +456,8 @@ def case_detail(request, pk):
|
||||
case = get_case_for_case_detail(pk)
|
||||
can_edit = case.check_user_can_edit(request.user)
|
||||
|
||||
is_atlas_editor = request.user.is_superuser or request.user.groups.filter(name="atlas_editor").exists()
|
||||
|
||||
return render(
|
||||
request,
|
||||
"atlas/case_detail.html",
|
||||
@@ -463,9 +465,98 @@ def case_detail(request, pk):
|
||||
"case": case,
|
||||
"cimar_sid": request.user.userprofile.cimar_sid,
|
||||
"can_edit": can_edit,
|
||||
"is_atlas_editor": is_atlas_editor,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
@require_POST
|
||||
def toggle_case_normal(request, pk):
|
||||
"""HTMX endpoint to toggle the NormalCase mark for a Case.
|
||||
|
||||
- Only users in the 'atlas_editor' group or superusers may toggle.
|
||||
- On create, attempt to auto-extract age_years from DICOM metadata.
|
||||
- Returns an HTML fragment that replaces the toggle block.
|
||||
"""
|
||||
case = get_case_for_case_detail(pk)
|
||||
|
||||
# Permission: atlas editors or superusers
|
||||
if not (request.user.is_superuser or request.user.groups.filter(name="atlas_editor").exists()):
|
||||
return HttpResponse(status=403)
|
||||
|
||||
# If already marked normal, unmark (delete the NormalCase)
|
||||
try:
|
||||
normal = case.normal_case
|
||||
except Exception:
|
||||
normal = None
|
||||
|
||||
if normal is not None:
|
||||
normal.delete()
|
||||
else:
|
||||
# Attempt to auto-extract age from DICOM
|
||||
age = None
|
||||
try:
|
||||
from datetime import datetime
|
||||
import re
|
||||
|
||||
# Iterate series then images to find first usable DICOM
|
||||
for series in case.series.all():
|
||||
img = series.images.filter(removed=False).first()
|
||||
if not img:
|
||||
continue
|
||||
ds = img.get_dicom_data()
|
||||
if not ds:
|
||||
continue
|
||||
|
||||
# Try PatientAge (format often like '045Y' or '45Y')
|
||||
try:
|
||||
pa = getattr(ds, "PatientAge", None)
|
||||
except Exception:
|
||||
pa = None
|
||||
|
||||
if pa:
|
||||
s = str(pa)
|
||||
m = re.search(r"(\d+)", s)
|
||||
if m:
|
||||
age = int(m.group(1))
|
||||
break
|
||||
|
||||
# Try birthdate + studydate
|
||||
try:
|
||||
pbd = getattr(ds, "PatientBirthDate", None)
|
||||
sdate = getattr(ds, "StudyDate", None) or getattr(ds, "AcquisitionDate", None) or getattr(ds, "SeriesDate", None)
|
||||
except Exception:
|
||||
pbd = None
|
||||
sdate = None
|
||||
|
||||
if pbd and sdate:
|
||||
try:
|
||||
bd = datetime.strptime(str(pbd), "%Y%m%d")
|
||||
sd = datetime.strptime(str(sdate), "%Y%m%d")
|
||||
years = round((sd - bd).days / 365.25)
|
||||
age = int(years)
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
except Exception:
|
||||
age = None
|
||||
|
||||
# Create NormalCase
|
||||
from .models import NormalCase
|
||||
|
||||
NormalCase.objects.create(case=case, age_years=age, added_by=request.user)
|
||||
|
||||
# Render the updated fragment
|
||||
is_atlas_editor = request.user.is_superuser or request.user.groups.filter(name="atlas_editor").exists()
|
||||
html = render_to_string(
|
||||
"atlas/partials/_normal_toggle.html",
|
||||
{"case": case, "user": request.user, "is_atlas_editor": is_atlas_editor},
|
||||
request=request,
|
||||
)
|
||||
return HttpResponse(html)
|
||||
|
||||
@login_required
|
||||
@user_is_author_or_atlas_series_checker_or_atlas_marker_or_open_access
|
||||
def series_thumbnail_fail(request, pk):
|
||||
|
||||
Reference in New Issue
Block a user