send group info from server

This commit is contained in:
Ross
2026-05-20 21:38:48 +01:00
parent 679ce2fd00
commit 8f74b66b97
2 changed files with 188 additions and 45 deletions
+161 -18
View File
@@ -105,6 +105,157 @@ def findMiddle(input_list):
return (input_list[int(middle)], input_list[int(middle - 1)])
def _normalise_group_rule_value(value):
if value is None:
return ""
if isinstance(value, pydicom.multival.MultiValue):
value = list(value)
if isinstance(value, (list, tuple)):
return ",".join([str(v).strip() for v in value if str(v).strip()])
text = str(value).strip()
if text == "":
return ""
try:
numeric = float(text)
if abs(numeric - round(numeric)) < 1e-6:
return str(int(round(numeric)))
return f"{numeric:.1f}"
except (TypeError, ValueError):
return text
def _build_declared_series_groups(series, series_images_with_urls):
rules = [
"dwiBValue",
"dwiDirection",
"temporalPosition",
"triggerTime",
"contentTime",
"echoTime",
"echoNumber",
]
rows = []
for image_obj, image_url in series_images_with_urls:
ds = image_obj.get_dicom_data()
def get_value(*keys):
for key in keys:
if key in ds:
normalized = _normalise_group_rule_value(ds[key].value)
if normalized != "":
return normalized
return ""
rule_values = {
"dwiBValue": get_value("DiffusionBValue", "DiffusionbValue"),
"dwiDirection": get_value("DiffusionGradientDirection", "DiffusionGradientOrientation"),
"temporalPosition": get_value("TemporalPositionIdentifier"),
"triggerTime": get_value("TriggerTime"),
"contentTime": get_value("ContentTime", "AcquisitionTime"),
"echoTime": get_value("EchoTime"),
"echoNumber": get_value("EchoNumbers", "EchoNumber"),
}
b_value = None
try:
if rule_values["dwiBValue"] != "":
b_value = float(rule_values["dwiBValue"])
except (TypeError, ValueError):
b_value = None
rows.append(
{
"imageId": image_url,
"ruleValues": rule_values,
"bValue": b_value,
}
)
if len(rows) == 0:
return []
active_rules = []
for rule_id in rules:
values = [row["ruleValues"][rule_id] for row in rows if row["ruleValues"][rule_id] != ""]
distinct = set(values)
coverage = len(values) / len(rows)
if len(distinct) > 1 and len(distinct) < max(2, len(rows)) and coverage >= 0.7:
active_rules.append(rule_id)
if len(active_rules) == 0:
return [
{
"key": f"SERVER_SERIES_{series.pk}_0",
"label": "Series 1",
"imageIds": [row["imageId"] for row in rows],
"seriesInstanceUID": series.series_instance_uid,
"bValue": None,
"groupValues": {},
}
]
grouped = {}
for row in rows:
key_parts = []
for rule_id in active_rules:
value = row["ruleValues"][rule_id]
key_parts.append(f"{rule_id}:{value}" if value != "" else f"{rule_id}:")
group_key = "|".join(key_parts)
if group_key not in grouped:
grouped[group_key] = {
"imageIds": [],
"groupValues": {rule_id: row["ruleValues"][rule_id] for rule_id in active_rules if row["ruleValues"][rule_id] != ""},
"bValue": row["bValue"],
}
grouped[group_key]["imageIds"].append(row["imageId"])
if grouped[group_key]["bValue"] is None and row["bValue"] is not None:
grouped[group_key]["bValue"] = row["bValue"]
ordered_groups = []
for idx, (_, payload) in enumerate(grouped.items()):
details = []
group_values = payload.get("groupValues", {})
if group_values.get("dwiBValue"):
details.append(f"b={group_values['dwiBValue']}")
if group_values.get("dwiDirection"):
details.append(f"dir={group_values['dwiDirection']}")
if group_values.get("temporalPosition"):
details.append(f"tp={group_values['temporalPosition']}")
if group_values.get("triggerTime"):
details.append(f"tr={group_values['triggerTime']}")
if group_values.get("contentTime"):
details.append(f"t={group_values['contentTime']}")
if group_values.get("echoTime"):
details.append(f"TE={group_values['echoTime']}")
if group_values.get("echoNumber"):
details.append(f"echo={group_values['echoNumber']}")
label = "".join(details) if len(details) > 0 else f"Series {idx + 1}"
ordered_groups.append(
{
"key": f"SERVER_SERIES_{series.pk}_{idx}",
"label": label,
"imageIds": payload["imageIds"],
"seriesInstanceUID": series.series_instance_uid,
"bValue": payload.get("bValue"),
"groupValues": group_values,
}
)
return ordered_groups
class SynMixin(object):
# class Meta:
# abstract = True
@@ -837,21 +988,17 @@ class Case(models.Model, AuthorMixin, QuestionMixin):
logger.debug(f"Building stacks for case {case_obj.pk} with prefix '{prefix}'")
stacks = []
for series in case_obj.get_ordered_series():
images = [f"{REMOTE_URL}{img.image.url}" for img in series.get_images()]
series_images = list(series.get_images())
series_images_with_urls = [(img, f"{REMOTE_URL}{img.image.url}") for img in series_images]
images = [url for _, url in series_images_with_urls]
declared_groups = _build_declared_series_groups(series, series_images_with_urls)
name = f"{prefix}: {series}" if prefix else str(series)
stacks.append(
{
"name": name,
"imageIds": images,
"seriesId": series.pk,
"series": [
{
"name": name,
"imageIds": images,
"seriesId": series.pk,
"seriesInstanceUID": series.series_instance_uid,
}
],
"series": declared_groups,
}
)
return stacks
@@ -1943,21 +2090,17 @@ class CaseDetail(models.Model):
def build_stacks_for(case_obj, prefix=None):
stacks = []
for series in case_obj.get_ordered_series():
images = [f"{REMOTE_URL}{img.image.url}" for img in series.get_images()]
series_images = list(series.get_images())
series_images_with_urls = [(img, f"{REMOTE_URL}{img.image.url}") for img in series_images]
images = [url for _, url in series_images_with_urls]
declared_groups = _build_declared_series_groups(series, series_images_with_urls)
name = f"{prefix}: {series}" if prefix else str(series)
stacks.append(
{
"name": name,
"imageIds": images,
"seriesId": series.pk,
"series": [
{
"name": name,
"imageIds": images,
"seriesId": series.pk,
"seriesInstanceUID": series.series_instance_uid,
}
],
"series": declared_groups,
}
)
return stacks
File diff suppressed because one or more lines are too long