GettingStarted.Rmd
This document is a guide to basics of running a simulation with the Evaluation Platform in COPD (EPIC) using epicR.
EPIC is a discrete-event simulation model for COPD, and models the entire pathway of care, from disease incidence, to diagnosis, treatment, and outcomes.
EPIC simulates random Canadians, known in the model as agents. Agents have demographic and biological/medical characteristics, including symptoms.
The operations of the model is controlled with inputs and settings.
The function get_input()
returns the default set of inputs,
while get_default_settings()
does the same for
settings.
When running the model, the user has the option of changing inputs and settings.
Let’s go over an example.
First, we need to load the model:
library(epicR)
EPIC is a session-based model, which means at beginning and end of our run, we need to open and terminate a session. When a session is initialized, required memory resources are allocated to the model.
Let’s initialize a session and run the model with default parameters:
init_session()
#> Initializing the session
#> [1] 0
run()
#> [1] 0
Both the init_session
and the run
functions
are supposed to return 0 if they encounter no error.
Once we ran the model, we probably want to see the results of that
run. The most basic set of results can be retrieved with
Cget_output()
:
results <- Cget_output()
These are high-level outcomes of the simulation. We can get more
detailed results with the Cget_output_ex()
function, which
includes many tables that give results over time horizon of the model.
Note that we should always have to terminate a session after we are done
with it.
results_ex<-Cget_output_ex()
names(results_ex)
#> [1] "n_alive_by_ctime_sex"
#> [2] "n_alive_by_ctime_age"
#> [3] "n_smoking_status_by_ctime"
#> [4] "n_current_smoker_by_ctime_sex"
#> [5] "annual_cost_ctime"
#> [6] "sum_fev1_ltime"
#> [7] "cumul_time_by_smoking_status"
#> [8] "cumul_non_COPD_time"
#> [9] "sum_p_COPD_by_ctime_sex"
#> [10] "sum_pack_years_by_ctime_sex"
#> [11] "sum_age_by_ctime_sex"
#> [12] "n_death_by_age_sex"
#> [13] "n_alive_by_age_sex"
#> [14] "sum_time_by_ctime_sex"
#> [15] "sum_time_by_age_sex"
#> [16] "sum_weight_by_ctime_sex"
#> [17] "n_COPD_by_ctime_sex"
#> [18] "n_COPD_by_ctime_age"
#> [19] "n_inc_COPD_by_ctime_age"
#> [20] "n_COPD_by_ctime_severity"
#> [21] "n_COPD_by_age_sex"
#> [22] "n_Diagnosed_by_ctime_sex"
#> [23] "n_Overdiagnosed_by_ctime_sex"
#> [24] "n_Diagnosed_by_ctime_severity"
#> [25] "n_case_detection_by_ctime"
#> [26] "n_case_detection_eligible"
#> [27] "n_diagnosed_true_CD"
#> [28] "n_agents_CD"
#> [29] "cumul_time_by_ctime_GOLD"
#> [30] "n_exac_by_ctime_age"
#> [31] "n_severep_exac_by_ctime_age"
#> [32] "n_exac_death_by_ctime_age"
#> [33] "n_exac_death_by_ctime_severity"
#> [34] "n_exac_death_by_age_sex"
#> [35] "n_exac_by_ctime_severity"
#> [36] "n_exac_by_gold_severity"
#> [37] "n_exac_by_gold_severity_diagnosed"
#> [38] "n_exac_by_ctime_severity_female"
#> [39] "n_exac_by_ctime_GOLD"
#> [40] "n_exac_by_ctime_severity_undiagnosed"
#> [41] "n_exac_by_ctime_severity_diagnosed"
#> [42] "n_GPvisits_by_ctime_sex"
#> [43] "n_GPvisits_by_ctime_severity"
#> [44] "n_GPvisits_by_ctime_diagnosis"
#> [45] "n_cough_by_ctime_severity"
#> [46] "n_phlegm_by_ctime_severity"
#> [47] "n_wheeze_by_ctime_severity"
#> [48] "n_dyspnea_by_ctime_severity"
#> [49] "n_mi"
#> [50] "n_incident_mi"
#> [51] "n_mi_by_age_sex"
#> [52] "n_mi_by_ctime_sex"
#> [53] "sum_p_mi_by_ctime_sex"
#> [54] "n_stroke"
#> [55] "n_incident_stroke"
#> [56] "n_stroke_by_age_sex"
#> [57] "n_stroke_by_ctime_sex"
#> [58] "n_hf"
#> [59] "n_incident_hf"
#> [60] "n_hf_by_age_sex"
#> [61] "n_hf_by_ctime_sex"
#> [62] "medication_time_by_class"
#> [63] "medication_time_by_ctime_class"
#> [64] "n_smoking_cessation_by_ctime"
#> [65] "n_exac_by_medication_class"
terminate_session()
#> Terminating the session
#> [1] 0
Here, we managed to run the model with its default inputs and
settings. But what were those inputs? We can explore them using
get_input()
:
inputs <- get_input()
names(inputs)
#> [1] "values" "help" "ref"
names(inputs$values)
#> [1] "global_parameters" "agent" "smoking"
#> [4] "COPD" "lung_function" "exacerbation"
#> [7] "symptoms" "outpatient" "diagnosis"
#> [10] "medication" "comorbidity" "cost"
#> [13] "utility" "manual"
names(inputs$values$global_parameters)
#> [1] "age0" "time_horizon" "discount_cost" "discount_qaly"
#> [5] "closed_cohort"
inputs$values$global_parameters$time_horizon
#> [1] 20
As you can see the example above, input is a list, with values, help, and references. To change any input, we need to change its value. Help and references are there to tell us what each input parameter is, and where did it come from. By changing inputs, we can change parameters such as time horizon, proportion of female patients, costs and utilities, as well as many regression equations that are used in the model.
Similarly, we can retrieve default settings and change them if necessary. The most useful setting is record_mode, which specifies whether the model should record outputs as aggregates or at the individual patient level. If we set record_mode to 2, we can collect individual patient level data from the model.
In the example below, we call the model with modified inputs and settings:
settings <- get_default_settings()
settings$record_mode <- 2
settings$n_base_agents <- 1e4
init_session(settings = settings)
#> Initializing the session
#> [1] 0
input <- get_input()
input$values$global_parameters$time_horizon <- 5
run(input=input$values)
#> [1] 0
results <- Cget_output()
events <- as.data.frame(Cget_all_events_matrix())
head(events)
#> id local_time female time_at_creation age_at_creation pack_years gold event
#> 1 0 0 1 0 65.13593 12.6812 0 0
#> 2 0 1 1 0 65.13593 12.6812 0 1
#> 3 0 2 1 0 65.13593 12.6812 0 1
#> 4 0 3 1 0 65.13593 12.6812 0 1
#> 5 0 4 1 0 65.13593 12.6812 0 1
#> 6 0 5 1 0 65.13593 12.6812 0 14
#> FEV1 FEV1_slope FEV1_acceleration pred_FEV1 smoking_status localtime_at_COPD
#> 1 0 0 0 0 0 0
#> 2 0 0 0 0 0 0
#> 3 0 0 0 0 0 0
#> 4 0 0 0 0 0 0
#> 5 0 0 0 0 0 0
#> 6 0 0 0 0 0 0
#> age_at_COPD weight_at_COPD height followup_after_COPD FEV1_baseline
#> 1 0 0 1.551958 0 3.127854
#> 2 0 0 1.551958 0 3.127854
#> 3 0 0 1.551958 0 3.127854
#> 4 0 0 1.551958 0 3.127854
#> 5 0 0 1.551958 0 3.127854
#> 6 0 0 1.551958 0 3.127854
#> exac_status cough phlegm wheeze dyspnea gpvisits diagnosis medication_status
#> 1 0 0 0 0 0 0 0 0
#> 2 0 0 0 0 0 0 0 0
#> 3 0 0 0 0 0 2 0 0
#> 4 0 0 0 1 0 4 0 0
#> 5 0 0 0 0 1 4 0 0
#> 6 0 0 0 0 1 4 0 0
#> case_detection cumul_cost cumul_qaly time_at_diagnosis
#> 1 0 0 0.0000000 0
#> 2 0 0 0.8349515 0
#> 3 0 0 1.6455839 0
#> 4 0 0 2.4326058 0
#> 5 0 0 3.1967046 0
#> 6 0 0 3.9385482 0
#> exac_history_n_moderate exac_history_n_severe_plus
#> 1 0 0
#> 2 0 0
#> 3 0 0
#> 4 0 0
#> 5 0 0
#> 6 0 0
terminate_session()
#> Terminating the session
#> [1] 0
Note that you might need a large amount of memory available, if you want to collect event history for a large number of patients.
In the events data frame, each type of event has a code corresponding to the table below:
Event | No. |
---|---|
start | 0 |
annual | 1 |
birthday | 2 |
smoking change | 3 |
COPD incidence | 4 |
Exacerbation | 5 |
Exacerbation end | 6 |
Death by Exacerbation | 7 |
Doctor visit | 8 |
Medication change | 9 |
Background death | 13 |
End | 14 |
By default, EPIC is an open population model that captures population trends such as growth, immigration, and emigration. We can change inputs to run a closed-cohort analysis, if need be:
library(epicR)
input <- get_input(closed_cohort = 1)$values
init_session()
#> Initializing the session
#> [1] 0
run(input=input)
#> [1] 0
Cget_output()
#> $n_agents
#> [1] 60001
#>
#> $cumul_time
#> [1] 1000844
#>
#> $n_deaths
#> [1] 20112
#>
#> $n_COPD
#> [1] 11854
#>
#> $total_exac
#> [1] 10061 60089 5649 410
#>
#> $total_exac_time
#> [1] 2.111269 11.526947 12.876768 1.507201
#>
#> $total_pack_years
#> [1] 859916.5
#>
#> $total_doctor_visit
#> [1] 0 0
#>
#> $total_cost
#> [1] 190692324
#>
#> $total_qaly
#> [1] 640094.6
#>
#> $total_diagnosed_time
#> [1] 44510.48
terminate_session()
#> Terminating the session
#> [1] 0
These are the basics of running a simulation in EPIC. There are many other useful functions in the package, including validation functions that allow the user to check model validation.