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: Enum

Disease 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: object

Models 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:

  1. State-dependent response to treatment

  2. Waning of treatment effect over time

  3. Diminishing returns at higher vision levels

  4. 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:

  1. NAIVE state has fixed transition probabilities: - STABLE: 30% - ACTIVE: 60% - HIGHLY_ACTIVE: 10%

  2. Other states use probabilities from configuration

  3. If no probabilities defined, remains in current state

  4. 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