start integrating cimar
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.1.4 on 2025-02-10 12:47
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('generic', '0020_remove_examuserstatus_share_with_supervisor_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='userprofile',
|
||||
name='cimar_sid',
|
||||
field=models.CharField(blank=True, max_length=100),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,22 @@
|
||||
# Generated by Django 5.1.4 on 2025-02-10 13:46
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('generic', '0021_userprofile_cimar_sid'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CimarCase',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('uuid', models.CharField(max_length=255, unique=True)),
|
||||
('viewer_link', models.URLField(blank=True)),
|
||||
('study_details', models.JSONField(blank=True)),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.1.4 on 2025-02-17 10:26
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('generic', '0022_cimarcase'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='cimarcase',
|
||||
name='valid_uuid',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cimarcase',
|
||||
name='study_details',
|
||||
field=models.JSONField(blank=True, default=dict),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.1.4 on 2025-02-17 11:49
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('generic', '0023_cimarcase_valid_uuid_alter_cimarcase_study_details'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='cimarcase',
|
||||
name='series_data',
|
||||
field=models.JSONField(blank=True, default=dict),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cimarcase',
|
||||
name='study_schema',
|
||||
field=models.JSONField(blank=True, default=dict),
|
||||
),
|
||||
]
|
||||
+119
-2
@@ -7,6 +7,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.db import models
|
||||
from django.forms import ValidationError
|
||||
from django.http import Http404, HttpRequest
|
||||
from django.shortcuts import render
|
||||
from django.utils import timezone
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from smtplib import SMTPException
|
||||
@@ -29,7 +30,8 @@ from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from generic.mixins import AuthorMixin, QuestionMixin
|
||||
from helpers.images import get_image_hash, pretty_print_dicom
|
||||
from rad.settings import REMOTE_URL
|
||||
from helpers.cimar import CimarAPI, STORAGE_API_URL
|
||||
from rad.settings import REMOTE_URL, CIMAR_USERNAME, CIMAR_PASSWORD
|
||||
from django.utils.html import format_html
|
||||
|
||||
from easy_thumbnails.files import get_thumbnailer
|
||||
@@ -45,6 +47,34 @@ from django.forms.utils import from_current_timezone, to_current_timezone
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from pygments import highlight
|
||||
from pygments.lexers import JsonLexer
|
||||
from pygments.formatters import HtmlFormatter
|
||||
|
||||
from django.contrib import admin
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
|
||||
def get_pretty_json(data):
|
||||
"""Function to display pretty version of our data"""
|
||||
if not data:
|
||||
return "No data"
|
||||
|
||||
# Convert the data to sorted, indented JSON
|
||||
response = json.dumps(data, sort_keys=True, indent=2)
|
||||
|
||||
# Get the Pygments formatter
|
||||
formatter = HtmlFormatter(style='colorful')
|
||||
|
||||
# Highlight the data
|
||||
response = highlight(response, JsonLexer(), formatter)
|
||||
|
||||
# Get the stylesheet
|
||||
style = "<style>" + formatter.get_style_defs() + "</style><br>"
|
||||
|
||||
# Safe the output
|
||||
return mark_safe(style + response)
|
||||
|
||||
def findMiddle(input_list):
|
||||
"""Returns the middle element of a list"""
|
||||
@@ -1690,6 +1720,8 @@ class UserProfile(models.Model):
|
||||
|
||||
username = property(getusername)
|
||||
|
||||
cimar_sid = models.CharField(max_length=100, blank=True)
|
||||
|
||||
def get_exams(self):
|
||||
available_exams = defaultdict(list)
|
||||
|
||||
@@ -1826,4 +1858,89 @@ class ExamCollection(models.Model, AuthorMixin):
|
||||
# settings.AUTH_USER_MODEL,
|
||||
# blank=True,
|
||||
# help_text="Author/Manager(s) of the exam collection",
|
||||
# )
|
||||
# )
|
||||
|
||||
class CimarCase(models.Model):
|
||||
uuid = models.CharField(max_length=255, unique=True)
|
||||
|
||||
viewer_link = models.URLField(blank=True)
|
||||
|
||||
study_details = models.JSONField(blank=True, default=dict)
|
||||
|
||||
study_schema = models.JSONField(blank=True, default=dict)
|
||||
|
||||
series_data = models.JSONField(blank=True, default=dict)
|
||||
|
||||
valid_uuid = models.BooleanField(default=False)
|
||||
|
||||
def load_series_data(self, api=None):
|
||||
if api is None:
|
||||
api = CimarAPI()
|
||||
api.login(username=CIMAR_USERNAME, password=CIMAR_PASSWORD)
|
||||
|
||||
|
||||
|
||||
|
||||
def refresh_study(self):
|
||||
api = CimarAPI()
|
||||
api.login(username=CIMAR_USERNAME, password=CIMAR_PASSWORD)
|
||||
|
||||
self.study_details = api.get_study_by_uuid(self.uuid)
|
||||
self.study_schema = api.get_study_schema_by_uuid(self.uuid)
|
||||
|
||||
self.viewer_link = api.get_study_viewer_url_by_uuid(self.uuid)
|
||||
|
||||
series_data = []
|
||||
|
||||
for series in self.study_schema["series"]:
|
||||
series_data.append({
|
||||
"series_id" : series["id"],
|
||||
"series_description" : series["description"],
|
||||
"image_count": len(series["images"]),
|
||||
"thumbnail": self.get_series_image_thumbnail_link(series)
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
self.series_data = {}
|
||||
self.series_data["series"] = series_data
|
||||
|
||||
self.valid_uuid = True
|
||||
self.save()
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.uuid} ({self.valid_uuid})"
|
||||
|
||||
def get_user_viewer_link(self, user):
|
||||
return self.viewer_link + f"?sid={user.userprofile.cimar_sid}"
|
||||
|
||||
|
||||
def get_pretty_study_details(self):
|
||||
"""Function to display pretty version of our data"""
|
||||
return get_pretty_json(self.study_details)
|
||||
|
||||
def get_pretty_study_schema(self):
|
||||
"""Function to display pretty version of our data"""
|
||||
return get_pretty_json(self.study_schema)
|
||||
|
||||
def get_pretty_study_series(self):
|
||||
"""Function to display pretty version of our data"""
|
||||
return get_pretty_json(self.series_data)
|
||||
|
||||
#def get_series_details_block(self, cimar_sid=None):
|
||||
# if "series" in self.series_data:
|
||||
# return render_to_string("cimar_series.html", {"series_data": self.series_data["series"], cimar_sid: cimar_sid})
|
||||
#
|
||||
# return "No series data available"
|
||||
|
||||
# return render_to_string("cimar_series.html", {"series_data": self.series_data["series"]})
|
||||
|
||||
|
||||
|
||||
def get_series_image_thumbnail_link(self,series):
|
||||
|
||||
middle_point = len(series["images"]) // 2
|
||||
|
||||
image = series["images"][middle_point]
|
||||
|
||||
return STORAGE_API_URL + f"/study/{self.study_details["storage_namespace"]}/{self.study_details["study_uid"]}/image/{image["id"]}/version/{image["version"]}/frame/0/thumbnail"
|
||||
|
||||
@@ -243,6 +243,13 @@ urlpatterns = [
|
||||
views.toggle_share_with_supervisor,
|
||||
name="toggle_share_with_supervisor",
|
||||
),
|
||||
path(
|
||||
"cimar_case/<str:uuid>/refresh",
|
||||
views.cimar_case_refresh,
|
||||
name="cimar_case_refresh"
|
||||
),
|
||||
|
||||
|
||||
]
|
||||
|
||||
|
||||
|
||||
+15
-1
@@ -84,6 +84,7 @@ from .models import (
|
||||
CidUser,
|
||||
CidUserExam,
|
||||
CidUserGroup,
|
||||
CimarCase,
|
||||
ExamBase,
|
||||
ExamCollection,
|
||||
ExamUserStatus,
|
||||
@@ -4084,4 +4085,17 @@ def exam_collection_add_marker(request, collection_id, exam_type):
|
||||
|
||||
collection.add_marker_to_exams(users, exam_types=(exam_type,))
|
||||
|
||||
return HttpResponse("Marker added to exams")
|
||||
return HttpResponse("Marker added to exams")
|
||||
|
||||
|
||||
def cimar_case_refresh(request, uuid):
|
||||
try:
|
||||
CimarCase.objects.get(uuid=uuid).refresh_study()
|
||||
except CimarCase.DoesNotExist:
|
||||
CimarCase(uuid=uuid).save()
|
||||
|
||||
|
||||
|
||||
return HttpResponse("Case refreshed")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user