File size: 1,238 Bytes
dd8acc2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Map raw clinical-test scores to a unitless signal in [-1, 1].

+1 means the test strongly supports the disease being present.
-1 means it strongly supports the disease being absent.
"""
from __future__ import annotations


def _linear_map(value: float, low: float, high: float, *, invert: bool) -> float:
    """Map `value` from [low, high] to [-1, 1]. If invert, flip sign."""
    if high == low:
        return 0.0
    clipped = max(low, min(high, value))
    norm = (clipped - low) / (high - low)
    signal = 2.0 * norm - 1.0
    return -signal if invert else signal


def mmse_to_signal(score: float) -> float:
    """MMSE: 30 = healthy (-1), 18 = severe (+1), 24 = mild cutoff (0)."""
    return _linear_map(score, low=18.0, high=30.0, invert=True)


def moca_to_signal(score: float) -> float:
    """MoCA: same scale as MMSE."""
    return _linear_map(score, low=18.0, high=30.0, invert=True)


def updrs_to_signal(score: float) -> float:
    return _linear_map(score, low=0.0, high=199.0, invert=False)


def gait_to_signal(speed_m_s: float) -> float:
    return _linear_map(speed_m_s, low=0.0, high=1.4, invert=True)


def age_to_signal(years: float) -> float:
    return _linear_map(years, low=30.0, high=90.0, invert=False)