181 lines
7.1 KiB
Python
181 lines
7.1 KiB
Python
|
|
"""
|
||
|
|
Registry: Baseline-Vitals (Ruhepuls, HRV, VO2 Max) und Abweichung vs. persönlicher Baseline.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from placeholder_registry import (
|
||
|
|
PlaceholderMetadata,
|
||
|
|
MissingValuePolicy,
|
||
|
|
EvidenceType,
|
||
|
|
OutputType,
|
||
|
|
PlaceholderType,
|
||
|
|
register_placeholder,
|
||
|
|
)
|
||
|
|
|
||
|
|
CAT = "Vitalwerte"
|
||
|
|
MVP = lambda reason, disp: MissingValuePolicy(
|
||
|
|
available=False, value_raw=None, missing_reason=reason, legacy_display=disp
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def _tag(m: PlaceholderMetadata):
|
||
|
|
for f in (
|
||
|
|
"key", "category", "description", "resolver_module", "resolver_function",
|
||
|
|
"data_layer_module", "data_layer_function", "source_tables", "semantic_contract",
|
||
|
|
"unit", "time_window", "output_type", "placeholder_type", "format_hint",
|
||
|
|
"example_output", "minimum_data_requirements", "confidence_logic",
|
||
|
|
"missing_value_policy", "layer_1_decision", "layer_2a_decision",
|
||
|
|
"layer_2b_reuse_possible", "architecture_alignment", "issue_53_alignment",
|
||
|
|
):
|
||
|
|
m.set_evidence(f, EvidenceType.CODE_DERIVED)
|
||
|
|
m.set_evidence("business_meaning", EvidenceType.DRAFT_DERIVED)
|
||
|
|
m.set_evidence("known_limitations", EvidenceType.MIXED)
|
||
|
|
|
||
|
|
|
||
|
|
def register_vitalwerte():
|
||
|
|
m = PlaceholderMetadata(
|
||
|
|
key="vitals_avg_hr",
|
||
|
|
category=CAT,
|
||
|
|
description="Durchschnittlicher Ruhepuls (7d), formatiert",
|
||
|
|
resolver_module="backend/placeholder_resolver.py",
|
||
|
|
resolver_function="get_vitals_avg_hr",
|
||
|
|
data_layer_module="backend/data_layer/health_metrics.py",
|
||
|
|
data_layer_function="get_resting_heart_rate_data",
|
||
|
|
source_tables=["vitals_baseline"],
|
||
|
|
semantic_contract="Mittel RHR aus vitals_baseline im Fenster (siehe health_metrics).",
|
||
|
|
business_meaning="KI-Kontext kardiovaskuläre Ruhelage",
|
||
|
|
unit="bpm (Anzeige mit Einheit)",
|
||
|
|
time_window="7d default im Resolver",
|
||
|
|
output_type=OutputType.STRING,
|
||
|
|
placeholder_type=PlaceholderType.INTERPRETED,
|
||
|
|
format_hint="z. B. 58 bpm",
|
||
|
|
example_output="58 bpm",
|
||
|
|
minimum_data_requirements="vitals_baseline im Fenster",
|
||
|
|
quality_filter_policy=None,
|
||
|
|
confidence_logic="data['confidence'] im Layer1",
|
||
|
|
missing_value_policy=MVP("no_data", "nicht verfügbar"),
|
||
|
|
known_limitations="Nur erfasste Morgen-Baseline-Messungen",
|
||
|
|
layer_1_decision="health_metrics.get_resting_heart_rate_data",
|
||
|
|
layer_2a_decision="get_vitals_avg_hr",
|
||
|
|
layer_2b_reuse_possible=True,
|
||
|
|
architecture_alignment="Phase 0c",
|
||
|
|
issue_53_alignment="Layer 1",
|
||
|
|
evidence={},
|
||
|
|
)
|
||
|
|
_tag(m)
|
||
|
|
register_placeholder(m)
|
||
|
|
|
||
|
|
m = PlaceholderMetadata(
|
||
|
|
key="vitals_avg_hrv",
|
||
|
|
category=CAT,
|
||
|
|
description="Durchschnittliche HRV (7d), formatiert",
|
||
|
|
resolver_module="backend/placeholder_resolver.py",
|
||
|
|
resolver_function="get_vitals_avg_hrv",
|
||
|
|
data_layer_module="backend/data_layer/health_metrics.py",
|
||
|
|
data_layer_function="get_heart_rate_variability_data",
|
||
|
|
source_tables=["vitals_baseline"],
|
||
|
|
semantic_contract="Mittel HRV aus vitals_baseline im Fenster.",
|
||
|
|
business_meaning="KI-Kontext autonome Regulation / Erholung",
|
||
|
|
unit="ms (Anzeige mit Einheit)",
|
||
|
|
time_window="7d default",
|
||
|
|
output_type=OutputType.STRING,
|
||
|
|
placeholder_type=PlaceholderType.INTERPRETED,
|
||
|
|
format_hint="z. B. 45 ms",
|
||
|
|
example_output="45 ms",
|
||
|
|
minimum_data_requirements="vitals_baseline mit HRV",
|
||
|
|
quality_filter_policy=None,
|
||
|
|
confidence_logic="data['confidence'] im Layer1",
|
||
|
|
missing_value_policy=MVP("no_data", "nicht verfügbar"),
|
||
|
|
known_limitations="Geräte-/Messprotokoll kann streuen",
|
||
|
|
layer_1_decision="health_metrics.get_heart_rate_variability_data",
|
||
|
|
layer_2a_decision="get_vitals_avg_hrv",
|
||
|
|
layer_2b_reuse_possible=True,
|
||
|
|
architecture_alignment="Phase 0c",
|
||
|
|
issue_53_alignment="Layer 1",
|
||
|
|
evidence={},
|
||
|
|
)
|
||
|
|
_tag(m)
|
||
|
|
register_placeholder(m)
|
||
|
|
|
||
|
|
m = PlaceholderMetadata(
|
||
|
|
key="vitals_vo2_max",
|
||
|
|
category=CAT,
|
||
|
|
description="Aktueller VO2 Max (letzte Messung), formatiert",
|
||
|
|
resolver_module="backend/placeholder_resolver.py",
|
||
|
|
resolver_function="get_vitals_vo2_max",
|
||
|
|
data_layer_module="backend/data_layer/health_metrics.py",
|
||
|
|
data_layer_function="get_vo2_max_data",
|
||
|
|
source_tables=["vitals_baseline"],
|
||
|
|
semantic_contract="Jüngster vo2_max aus vitals_baseline.",
|
||
|
|
business_meaning="Ausdauer-/Fitness-Kontext",
|
||
|
|
unit="ml/kg/min",
|
||
|
|
time_window="latest",
|
||
|
|
output_type=OutputType.STRING,
|
||
|
|
placeholder_type=PlaceholderType.INTERPRETED,
|
||
|
|
format_hint="eine Dezimalstelle + Einheit",
|
||
|
|
example_output="42.0 ml/kg/min",
|
||
|
|
minimum_data_requirements="mindestens eine VO2-Messung",
|
||
|
|
quality_filter_policy=None,
|
||
|
|
confidence_logic="data['confidence'] im Layer1",
|
||
|
|
missing_value_policy=MVP("no_data", "nicht verfügbar"),
|
||
|
|
known_limitations="Schätzung vs. Labortest je nach Quelle",
|
||
|
|
layer_1_decision="health_metrics.get_vo2_max_data",
|
||
|
|
layer_2a_decision="get_vitals_vo2_max",
|
||
|
|
layer_2b_reuse_possible=True,
|
||
|
|
architecture_alignment="Phase 0c",
|
||
|
|
issue_53_alignment="Layer 1",
|
||
|
|
evidence={},
|
||
|
|
)
|
||
|
|
_tag(m)
|
||
|
|
register_placeholder(m)
|
||
|
|
|
||
|
|
for key, dl_fn, desc, unit, res_fn in [
|
||
|
|
(
|
||
|
|
"hrv_vs_baseline_pct",
|
||
|
|
"calculate_hrv_vs_baseline_pct",
|
||
|
|
"HRV vs. persönlicher Baseline (%)",
|
||
|
|
"%",
|
||
|
|
"_safe_float",
|
||
|
|
),
|
||
|
|
(
|
||
|
|
"rhr_vs_baseline_pct",
|
||
|
|
"calculate_rhr_vs_baseline_pct",
|
||
|
|
"Ruhepuls vs. persönlicher Baseline (%)",
|
||
|
|
"%",
|
||
|
|
"_safe_float",
|
||
|
|
),
|
||
|
|
]:
|
||
|
|
m = PlaceholderMetadata(
|
||
|
|
key=key,
|
||
|
|
category=CAT,
|
||
|
|
description=desc,
|
||
|
|
resolver_module="backend/placeholder_resolver.py",
|
||
|
|
resolver_function=res_fn,
|
||
|
|
data_layer_module="backend/data_layer/recovery_metrics.py",
|
||
|
|
data_layer_function=dl_fn,
|
||
|
|
source_tables=["vitals_baseline"],
|
||
|
|
semantic_contract=f"Vergleich aktueller Wert zu Baseline (siehe {dl_fn}).",
|
||
|
|
business_meaning="Erholungs- und Belastungsindikator relativ zur Norm des Nutzers",
|
||
|
|
unit=unit,
|
||
|
|
time_window="funktionsintern",
|
||
|
|
output_type=OutputType.NUMERIC,
|
||
|
|
placeholder_type=PlaceholderType.INTERPRETED,
|
||
|
|
format_hint="numerischer Prozent-String",
|
||
|
|
example_output="5.2",
|
||
|
|
minimum_data_requirements="Ausreichend Baseline-Historie",
|
||
|
|
quality_filter_policy=None,
|
||
|
|
confidence_logic="Funktionsintern",
|
||
|
|
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
||
|
|
known_limitations="Baseline braucht ausreichend Vorlauf",
|
||
|
|
layer_1_decision=f"recovery_metrics.{dl_fn}",
|
||
|
|
layer_2a_decision=f"Resolver {res_fn}",
|
||
|
|
layer_2b_reuse_possible=True,
|
||
|
|
architecture_alignment="Phase 0c",
|
||
|
|
issue_53_alignment="Layer 1",
|
||
|
|
evidence={},
|
||
|
|
)
|
||
|
|
_tag(m)
|
||
|
|
register_placeholder(m)
|
||
|
|
|
||
|
|
|
||
|
|
register_vitalwerte()
|