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
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.
Workflow YAML specifies the states, transitions, utilities, resources, and other parameters of your workflow.
(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).
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:
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.
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:
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