Configuration

APLUS simulations can be specified in two ways – via the Config object or via a (1) Workflow YAML and (2) Patient Properties CSV.

1. Pythonic Config object

Documentation for the Config object is available API Reference

script.py
 1import aplusml
 2
 3# Create Config object
 4config = aplusml.config.Config(
 5  metadata = aplusml.config.ConfigMetadata(
 6    name = 'My Simulation',
 7  ),
 8  variables = {
 9    'variable_id': aplusml.config.ConfigVariable(
10      type = 'scalar',
11      value = 1,
12    ),
13  },
14  states = {
15    'start' : aplusml.config.ConfigState(
16      type = 'start',
17      transitions = [
18        aplusml.config.ConfigTransition(
19          dest = 'end',
20        ),
21      ],
22    ),
23    'end' : aplusml.config.ConfigState(
24      type = 'end',
25    ),
26  },
27)
28
29# Create Simulation object
30simulation = aplusml.Simulation.create_from_config(config)

2. Workflow YAML + Patient Properties CSV

For improved readability, an APLUS simulation can also be specified via a (1) Workflow YAML and (2) Patient Properties CSV.

  1. Workflow YAML specifies the states, transitions, utilities, resources, and other parameters of your workflow.

  2. (Optional) Patient Properties CSV contains individual-level properties for each patient that will be run through your workflow.

This is equivalent to the Pythonic Config object (i.e. it gets converted to a :class:aplusml.config.Config object under the hood).

script.py
1import aplusml
2
3PATH_TO_CONFIG_YAML: str = 'config.yaml'
4PATH_TO_PATIENT_PROPERTIES: str = 'patient_properties.csv'
5
6# Create Simulation object
7simulation = aplusml.Simulation.create_from_yaml(PATH_TO_CONFIG_YAML, PATH_TO_PATIENT_PROPERTIES)

🔧 Workflow YAML

  • Format: YAML

  • Purpose: Specifies the states, transitions, utilities, resources, and other parameters of your workflow

  • Schema: Listed below

The YAML must be formatted as follows:

config.yaml
 1metadata:
 2  name: Optional[str]  # Name of the simulation
 3  path_to_properties: Optional[str]  # Path to CSV file where each row is a patient, each column is a property. Note: Only properties explicitly enumerated in the 'variables' section will be imported
 4  properties_col_for_patient_id: Optional[str]  # Column name in the CSV that contains unique patient IDs.
 5  patient_sort_preference_property: Optional[dict]  # Determines priority order for resource allocation.
 6    variable: str  # Name of a property (must be defined in `variables`) that will be used to sort patients when prioritizing allocation of a finite resource
 7    is_ascending: bool  # True = ascending order, False = descending.
 8
 9variables:  # Dictionary of variables, each with a unique key.
10  [key]: # `key` is the ID of the variable. It must be unique.
11    type: Enum(scalar, resource, property, simulation)  # Type of variable. Default: "scalar".
12
13    # If type == 'scalar'
14    #   This is a scalar value that is shared across all patients.
15    #   It can be used to model things like the sensitivity of a screening test, the prevalence of a disease, etc.
16    value: Union[int, float, bool, str, list, dict, set]  # Scalar value. Use '!!set' tag for sets.
17
18    # If type == 'resource'
19    #   This is a finite resource that is shared across all patients.
20    #   It can be decremented, incremented, and reset by the simulation.
21    #   It can be used to model things like hospital beds, lab capacity, etc.
22    init_amount: int  # Initial amount of the resource.
23    max_amount: int  # Maximum amount of resource allowed.
24    refill_amount: int  # Amount added per refill.
25    refill_duration: int  # Time interval between refills.
26
27    # If type == 'property'
28    #   This is a property that is UNIQUE to each patient (i.e. each patient may have a different value for this property).
29    #   It can be used to model things like the age of a patient, the gender of a patient, etc.
30    ## Either load from file...
31    column: str  # If loaded from a CSV file, specify the column name (e.g. 'y' or 'y_hat_dl'). Each row of the CSV will be a patient, and the value of this property for each patient will be the value of the column in the CSV file.
32    ## or constant...
33    value: Any  # If constant, specify value.
34    ## or randomly sample...
35    distribution: Enum(bernoulli, exponential, binomial, normal, poisson, uniform)  # If randomly sampled.
36    mean: Optional[float]  # Mean value for distribution.
37    std: Optional[float]  # Standard deviation.
38    start: Optional[float]  # Minimum value.
39    end: Optional[float]  # Maximum value.
40
41states:  # Dictionary of states, each with a unique key.
42  [key]: str # `key` is the ID of the state. It must be unique.
43    label: Optional[str]  # Human-readable label for the state. Default: value of `key`.
44    type: Optional[Enum(start, end, intermediate)]  # Whether the state is a start, end, or intermediate state within the workflow. Default: "intermediate".
45    duration: Optional[float]  # Number of timesteps to wait before transitions are evaluated. Default: 0.0.
46
47    utilities: Optional[Union[str, float, bool, list[dict]]]  # If string, it's evaluated as a Python expression. Default: 0.0.
48      # If list[dict], then multiple utilities can be defined. Note: These 'if' statements are not mutually exclusive (i.e. if multiple conditions evaluate to TRUE, then they will simply be summed together)
49      - value: Optional[Union[float, str]]  # If string, it's evaluated as a Python expression.
50        if: Optional[Union[str, bool]]  # A Python expression. If it evaluates to TRUE, then the `value` for this utility is set to this `value`.
51        unit: Optional[str]  # Measurement unit.
52
53    resource_deltas: Optional[Dict[str, float]]  # Changes to resource levels from entering this state. Default: {}.
54      [key]: str # `key` is the name of a resource defined in `variables`.
55        [value] # Required. How much to change each resource level AS SOON AS this state is hit
56
57    transitions: Optional[List[Dict]]  # List of possible state transitions.
58      - dest: str  # Required. ID of the destination state.
59        label: Optional[str] # Default: "".
60
61        # Transition conditions
62        ## Can either have...
63        ## - All transitions have an 'if' condition (where if the last transition doesn't have an 'if', it defaults to always TRUE)
64        ## - All transitions have a 'prob' condition (where if the last transition doesn't have a 'prob', it defaults to = 1 - (sum of other probs))
65        ## - The first set of transitions have an 'if' condition, but the second set have a 'prob'
66        if: Optional[Union[str, bool]]  # Conditional expression. If string, it's evaluated as a Python expression. Must come before 'prob' (if mixed). Must always be at least one TRUE condition across all transitions for this state (unless mixed with 'prob'). `if` conditionals will be evaluated in order and break on first TRUE. If the last `if` doesn't have a condition, then it defaults to TRUE.
67        prob: Optional[float]  # Probability of transition. If string, it's evaluated as a Python expression. Must come after 'if' (if mixed). If mixed, then 'prob' is conditional probability given all 'if' are FALSE. Must sum to 1 across all 'prob' transitions for this state. If the last `prob` doesn't have a condition, then it defaults to = 1 - (sum of other probs).
68
69        duration: Optional[float]  # Number of timesteps to wait before transitions are evaluated. Default: 0.0.
70
71        utilities: Optional[Union[str, float, bool, list[dict]]]  # Same specification as the utilities for states.
72
73        resource_deltas: Optional[Dict[str, float]] # Changes to resource levels from taking this transition. Default: {}.
74          [key]: str # `key` is the name of a resource defined in `variables`.
75            [value] # How much to change each resource level AS SOON AS this transition is taken

NOTE: APLUS makes the following simulation-level variables available to the user. To use them, you must include them in the variables section of the YAML file:

  • sim_current_timestep: The current timestep of the simulation.

  • time_left_in_sim: The number of timesteps remaining in the simulation.

  • time_already_in_sim: The number of timesteps that have passed in the simulation.

e.g.

config.yaml
variables:
  sim_current_timestep:
    type: simulation
  time_left_in_sim:
    type: simulation
  time_already_in_sim:
    type: simulation

📄 Patient Properties CSV

  • Format: CSV

  • Purpose: Contains individual-level properties for each patient that will be run through your workflow

  • Schema: Listed below

The CSV must be formatted as follows:

Each row is a unique patient, and each column is a property. Properties can be anything – e.g. demographic information, model predictions, clinical measurements, etc.

Example properties include:

  • id: The unique identifier for the patient.

  • age: The age of the patient.

  • gender: The gender of the patient.

  • y: The ground truth label for the patient.

  • y_hat: The predicted label for the patient.

  • random_resource_priority: A random number that we will use to sort patients when prioritizing them to access a finite resource.

Here is an excerpt from an example properties CSV file:

patient_properties.csv
 id,y,y_hat_dl,y_hat_rf,y_hat_lr,abi_test_pred,random_resource_priority
 1,0,0.95,0.9,0.85,0.9,0.1
 2,1,0.85,0.8,0.75,0.8,0.2
 3,0,0.75,0.7,0.65,0.7,0.3