-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathvalidation_runtime.py
More file actions
108 lines (86 loc) · 3.73 KB
/
Copy pathvalidation_runtime.py
File metadata and controls
108 lines (86 loc) · 3.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
from __future__ import annotations
from dataclasses import asdict
import math
from aurora_svmat_lab.models import AuroraAnalysisResult
from metric_definition_catalog import metric_catalog_keys_for_platform
from ucomx_models import AnalysisMode, PlanAnalysisResult
from validation_models import ValidationCaseResult
_UNSUPPORTED_METRIC_VALUE = object()
def analyze_validation_case(source_path: str, domain: str) -> ValidationCaseResult:
normalized_domain = domain.strip().upper()
if normalized_domain == "AURORA":
from aurora_svmat_lab.service import analyze_plan_file as analyze_aurora_plan_file
result = analyze_aurora_plan_file(source_path)
return _normalize_aurora_result(result)
requested_mode = _analysis_mode_for_domain(normalized_domain)
from ucomx_service import analyze_plan_file
result = analyze_plan_file(source_path, requested_mode=requested_mode, full_precision=True)
return _normalize_core_result(result, domain=normalized_domain)
def _analysis_mode_for_domain(domain: str) -> AnalysisMode:
try:
return {
"VMAT_IMRT": AnalysisMode.VMAT_IMRT,
"TOMO": AnalysisMode.TOMO,
"CYBERKNIFE_MLC": AnalysisMode.CYBERKNIFE_MLC,
}[domain]
except KeyError as exc:
raise ValueError(f"Unsupported validation domain '{domain}'.") from exc
def _normalize_core_result(result: PlanAnalysisResult, *, domain: str) -> ValidationCaseResult:
allowed_metric_keys = metric_catalog_keys_for_platform(domain)
metrics = _normalize_metric_mapping(result.flattened_metrics, allowed_metric_keys)
return ValidationCaseResult(
source_path=result.source_path,
domain=domain,
mode=result.mode.value,
supported=result.supported,
reason=result.reason_label,
metadata=dict(result.metadata),
metrics=metrics,
warnings=tuple(result.warnings),
)
def _normalize_aurora_result(result: AuroraAnalysisResult) -> ValidationCaseResult:
allowed_metric_keys = metric_catalog_keys_for_platform("AURORA")
listed_metrics = _normalize_metric_mapping(
{metric.metric_name: metric.value for metric in result.metrics},
allowed_metric_keys,
)
listed_metrics.update(_normalize_metric_mapping(result.plan_metrics, allowed_metric_keys))
return ValidationCaseResult(
source_path=result.source_path,
domain="AURORA",
mode="AURORA",
supported=result.supported,
reason=result.reason,
metadata={**asdict(result.metadata), "numeric_precision": "float64"},
metrics=listed_metrics,
warnings=tuple(result.warnings),
)
def _normalize_metric_mapping(
raw_metrics: dict[str, object],
allowed_metric_keys: set[str],
) -> dict[str, float | int | str | None]:
normalized_metrics: dict[str, float | int | str | None] = {}
for key, value in raw_metrics.items():
if key not in allowed_metric_keys:
continue
normalized_value = _normalize_metric_value(value)
if normalized_value is _UNSUPPORTED_METRIC_VALUE:
continue
normalized_metrics[key] = normalized_value
return normalized_metrics
def _normalize_metric_value(value: object) -> float | int | str | None | object:
item_method = getattr(value, "item", None)
if callable(item_method):
try:
value = item_method()
except (TypeError, ValueError):
return _UNSUPPORTED_METRIC_VALUE
if isinstance(value, bool) or not isinstance(value, (int, float, str)) and value is not None:
return _UNSUPPORTED_METRIC_VALUE
if isinstance(value, float) and not math.isfinite(value):
return None
return value
__all__ = [
"ValidationCaseResult",
"analyze_validation_case",
]