Clinical Model Module
Clinical model for AMD disease progression and vision changes.
This module implements the clinical aspects of AMD progression, including disease states, vision changes, and treatment effects. It uses a state-based model with probabilistic transitions and configurable parameters for vision changes.
Classes
- DiseaseState
Enumeration of possible AMD disease states
- ClinicalModel
Core class implementing disease progression and vision change logic
Key Features
Four disease states (NAIVE, STABLE, ACTIVE, HIGHLY_ACTIVE)
Configurable transition probabilities between states
- Vision change modeling with:
State-dependent base changes
Time since last injection factor
Vision ceiling effect
Measurement noise
Injection vs non-injection visit differentiation
Mathematical Model
- Vision change is calculated as:
ΔV = (B × T × C) + N
- Where:
ΔV: Vision change (ETDRS letters) B: Base change (state and injection dependent) T: Time factor (1 + weeks_since_injection/max_weeks) C: Ceiling factor (1 - current_vision/max_vision) N: Measurement noise (normally distributed)
State Transitions
NAIVE → STABLE: 30% NAIVE → ACTIVE: 60% NAIVE → HIGHLY_ACTIVE: 10% Other transitions configurable via parameters
Examples
>>> config = SimulationConfig.from_yaml("protocols/eylea.yaml")
>>> model = ClinicalModel(config)
>>> state = {"disease_state": "NAIVE", "injections": 0, ...}
>>> vision_change, new_state = model.simulate_vision_change(state)
Notes
Vision measured in ETDRS letters (0-100 range)
Positive ΔV indicates vision improvement
Time factor increases linearly with weeks since last injection
Ceiling effect reduces changes as vision approaches maximum
- class simulation.clinical_model.DiseaseState(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]
Bases:
EnumDisease states for AMD progression.
Enumeration of possible disease states in the AMD progression model.
- Variables:
NAIVE (Enum) – Initial state for new patients with no prior treatment. Typically transitions to other states in first visit.
STABLE (Enum) – Disease is under control with minimal activity. Patients typically maintain or slightly improve vision.
ACTIVE (Enum) – Disease shows signs of activity with fluid accumulation. Patients typically experience vision decline without treatment.
HIGHLY_ACTIVE (Enum) – Disease shows high levels of activity with significant fluid. Patients experience rapid vision decline without treatment.
Notes
State transitions are probabilistic and configurable via ClinicalModel.
Default transition probabilities from NAIVE state:
STABLE: 30%
ACTIVE: 60%
HIGHLY_ACTIVE: 10%
- NAIVE = 0
- STABLE = 1
- ACTIVE = 2
- HIGHLY_ACTIVE = 3
- class simulation.clinical_model.ClinicalModel(config)[source]
Bases:
objectModels clinical aspects of AMD progression, including disease states and vision changes.
This model includes four disease states: NAIVE, STABLE, ACTIVE, and HIGHLY_ACTIVE. It simulates disease progression and vision changes based on the current state and treatment.
The model uses configurable transition probabilities between states and simulates vision changes with normal distributions, differentiating between injection and non-injection visits.
- Parameters:
config (simulation.config.SimulationConfig) – Configuration object containing clinical model parameters, vision parameters, and transition probabilities between disease states.
- Variables:
config (simulation.config.SimulationConfig) – Configuration object containing model parameters
transition_probabilities (Dict[DiseaseState, Dict[DiseaseState, float]]) – Probability matrix for transitions between disease states
vision_change_params (Dict) – Parameters controlling vision changes under different conditions
Notes
The model captures key clinical aspects of AMD progression:
State-dependent response to treatment
Waning of treatment effect over time
Diminishing returns at higher vision levels
Realistic measurement variability
- __init__(config)[source]
- Parameters:
config (SimulationConfig)
- get_transition_probabilities(current_state)[source]
Get transition probabilities for the current disease state.
- Parameters:
current_state (DiseaseState) – Current disease state (NAIVE, STABLE, ACTIVE, or HIGHLY_ACTIVE)
- Returns:
Dictionary mapping possible next states to their transition probabilities
- Return type:
Dict[DiseaseState, float]
- Raises:
ValueError – If no transition probabilities are defined for the current state
- simulate_disease_progression(current_state)[source]
Simulate disease state progression using configured transition probabilities.
- Parameters:
current_state (DiseaseState) – Current disease state (NAIVE, STABLE, ACTIVE, or HIGHLY_ACTIVE)
- Returns:
New disease state after progression
- Return type:
DiseaseState
- Raises:
ValueError – If current_state is not a valid DiseaseState
Examples
>>> model = ClinicalModel(config) >>> current_state = DiseaseState.NAIVE >>> new_state = model.simulate_disease_progression(current_state) >>> print(f"Transitioned from {current_state} to {new_state}")
Notes
Disease progression follows these rules:
NAIVE state has fixed transition probabilities: - STABLE: 30% - ACTIVE: 60% - HIGHLY_ACTIVE: 10%
Other states use probabilities from configuration
If no probabilities defined, remains in current state
Probabilities are normalized to sum to 1 if needed
The method handles: - Validation of current_state - Special case for NAIVE state - Probability normalization - Random selection of next state - Debug logging of transitions
Transition probabilities represent clinical observations of AMD progression: - NAIVE patients most likely to transition to ACTIVE state - STABLE patients typically remain stable - ACTIVE patients may progress to HIGHLY_ACTIVE or regress to STABLE
- get_initial_vision()[source]
Get initial vision for a new patient.
- Returns:
Initial vision score (ETDRS letters)
- Return type:
int
Notes
Uses normal distribution with configurable mean and standard deviation. Defaults to mean=70, sd=5 if not specified in configuration.
- simulate_vision_change(state)[source]
Calculate vision change and new disease state based on current state and treatment.
- Parameters:
state (Dict) –
- Current patient state dictionary with these required keys:
- disease_state: Current disease state (str or DiseaseState)
Must be one of: NAIVE, STABLE, ACTIVE, HIGHLY_ACTIVE
- injections: Total number of injections (int)
Count of all injections received
- last_recorded_injection: Number of last recorded injection (int)
Used to detect new injections
- weeks_since_last_injection: Weeks since last injection (int)
Used in time factor calculation
- current_vision: Current vision score (ETDRS letters, int)
Must be between 0-100 (will be clamped if outside range)
- treatment_status: Dict containing treatment status information
active: bool - Whether treatment is active
weeks_since_discontinuation: int - Weeks since treatment was discontinued
recurrence_detected: bool - Whether recurrence has been detected
- Optional keys:
debug: bool - Enable debug output if True
- Returns:
- Tuple containing:
Vision change in ETDRS letters (positive = improvement)
New disease state
- Return type:
Tuple[float, DiseaseState]
- Raises:
ValueError – If required vision change parameters are missing from configuration
Examples
>>> state = { ... "disease_state": "NAIVE", ... "injections": 1, ... "last_recorded_injection": 0, ... "weeks_since_last_injection": 4, ... "current_vision": 70, ... "treatment_status": {"active": True, "weeks_since_discontinuation": 0, "recurrence_detected": False} ... } >>> vision_change, new_state = model.simulate_vision_change(state) >>> print(f"Vision changed by {vision_change:.1f} letters")
Notes
- Mathematical Model:
ΔV = (B × T × C) + N
- Where:
- ΔV: Vision change (ETDRS letters)
Positive values indicate vision improvement Negative values indicate vision decline
- B: Base change (state and injection dependent)
Normally distributed: N(μ, σ)
μ and σ configured per state in vision_change_params
Separate distributions for injection vs non-injection visits
- Typical ranges:
Injection: μ = +5 to +15 letters Non-injection: μ = -5 to +5 letters
- T: Time factor (1 + weeks_since_injection/max_weeks)
Models decreasing treatment effect over time
max_weeks typically 52 (1 year) from config
Ranges from 1 (immediate post-injection) to 2 (1 year post-injection)
- C: Ceiling factor (1 - current_vision/max_vision)
max_vision typically 100 letters from config
Ranges from 1 (0 letters) to 0 (100 letters)
Limits unrealistic vision improvements at high acuity
- N: Measurement noise (normally distributed)
Represents test-retest variability
Typically N(0, 0.5) letters from config
- Edge Cases:
If current_vision > max_vision, ceiling_factor is clamped to 0
If weeks_since_injection > max_weeks, time_factor is clamped to 2
- If state missing required keys, uses defaults:
weeks_since_injection=0, current_vision=70
The model captures key clinical aspects: 1. State-dependent response to treatment 2. Waning of treatment effect over time 3. Diminishing returns at higher vision levels 4. Realistic measurement variability 5. Treatment discontinuation and recurrence
- calculate_monitoring_schedule(state)[source]
Calculate appropriate monitoring interval based on treatment status.
- Parameters:
state (Dict) – Patient state dictionary containing treatment status information
- Returns:
Recommended weeks until next monitoring visit
- Return type:
int