From 196b21441039cce7fdbb28fc681549f1a4af9f01 Mon Sep 17 00:00:00 2001 From: amyheather Date: Mon, 30 Jun 2025 13:42:57 +0100 Subject: [PATCH 01/13] feat(parameters): add parameters for the stroke model (in functions, but otherwise similar to https://github.com/pythonhealthdatascience/pydesrap_stroke/simulation/parameters.py) --- R/parameters.R | 229 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 R/parameters.R diff --git a/R/parameters.R b/R/parameters.R new file mode 100644 index 0000000..df93157 --- /dev/null +++ b/R/parameters.R @@ -0,0 +1,229 @@ +#' Acute Stroke Unit (ASU) arrival intervals (days). +#' +#' For example, a value of 1.2 means a new admission every 1.2 days. +#' +#' @param stroke Numeric. Mean days between stroke patient arrivals. +#' @param tia Numeric. Mean days between transient ischaemic attack (TIA) +#' patient arrivals. +#' @param neuro Numeric. Mean days between complex neurological patient +#' arrivals. +#' @param other Numeric. Mean days between other patient arrivals. +#' +#' @return A named list of arrival intervals for ASU. +create_asu_arrivals <- function( + stroke = 1.2, tia = 9.3, neuro = 3.6, other = 3.2 +) { + list( + stroke = stroke, + tia = tia, + neuro = neuro, + other = other + ) +} + +#' Rehabilitation unit arrival intervals (days). +#' +#' For example, a value of 21.8 means a new admission every 21.8 days. +#' +#' @param stroke Numeric. Mean days between stroke patient arrivals. +#' @param neuro Numeric. Mean days between complex neurological patient +#' arrivals. +#' @param other Numeric. Mean days between other patient arrivals. +#' +#' @return A named list of arrival intervals for rehabilitation unit. +create_rehab_arrivals <- function( + stroke = 21.8, neuro = 31.7, other = 28.6 +) { + list( + stroke = stroke, + neuro = neuro, + other = other + ) +} + +#' Acute Stroke Unit (ASU) length of stay (LOS) distributions (days). +#' +#' Mean and standard deviation (SD) of LOS in days in the ASU. +#' +#' @param stroke_noesd_mean Numeric. Mean LOS for stroke patients without early +#' supported discharged (ESD). +#' @param stroke_noesd_sd Numeric. SD LOS for stroke patients without ESD. +#' @param stroke_esd_mean Numeric. Mean LOS for stroke patients with ESD. +#' @param stroke_esd_sd Numeric. SD LOS for stroke patients with ESD. +#' @param stroke_mortality_mean Numeric. Mean LOS for stroke patients who pass +#' away. +#' @param stroke_mortality_sd Numeric. SD LOS for stroke patients who pass +#' away. +#' @param tia_mean Numeric. Mean LOS for transient ischemic attack (TIA) +#' patients. +#' @param tia_sd Numeric. SD LOS for TIA patients. +#' @param neuro_mean Numeric. Mean LOS for complex neurological patients +#' @param neuro_sd Numeric. SD LOS for complex neurological patients +#' @param other_mean Numeric. Mean LOS for other patients. +#' @param other_sd Numeric. SD LOS for other patients. +#' +#' @return A named list of LOS distributions for ASU. +create_asu_los <- function( + stroke_noesd_mean = 7.4, stroke_noesd_sd = 8.61, + stroke_esd_mean = 4.6, stroke_esd_sd = 4.8, + stroke_mortality_mean = 7.0, stroke_mortality_sd = 8.7, + tia_mean = 1.8, tia_sd = 2.3, + neuro_mean = 4.0, neuro_sd = 5.0, + other_mean = 3.8, other_sd = 5.2 +) { + list( + stroke_noesd = list(mean = stroke_noesd_mean, sd = stroke_noesd_sd), + stroke_esd = list(mean = stroke_esd_mean, sd = stroke_esd_sd), + stroke_mortality = list(mean = stroke_mortality_mean, sd = stroke_mortality_sd), + tia = list(mean = tia_mean, sd = tia_sd), + neuro = list(mean = neuro_mean, sd = neuro_sd), + other = list(mean = other_mean, sd = other_sd) + ) +} + +#' Rehabilitation unit length of stay (LOS) distributions (days). +#' +#' @param stroke_noesd_mean Numeric. Mean LOS for stroke patients without early +#' supported discharged (ESD). +#' @param stroke_noesd_sd Numeric. SD LOS for stroke patients without ESD. +#' @param stroke_esd_mean Numeric. Mean LOS for stroke patients with ESD. +#' @param stroke_esd_sd Numeric. SD LOS for stroke patients with ESD. +#' @param tia_mean Numeric. Mean LOS for transient ischemic attack (TIA) +#' patients. +#' @param tia_sd Numeric. SD LOS for TIA patients. +#' @param neuro_mean Numeric. Mean LOS for complex neurological patients +#' @param neuro_sd Numeric. SD LOS for complex neurological patients +#' @param other_mean Numeric. Mean LOS for other patients. +#' @param other_sd Numeric. SD LOS for other patients. +#' +#' @return A named list of LOS distributions for rehabilitation unit. +create_rehab_los <- function( + stroke_noesd_mean = 28.4, stroke_noesd_sd = 27.2, + stroke_esd_mean = 30.3, stroke_esd_sd = 23.1, + tia_mean = 18.7, tia_sd = 23.5, + neuro_mean = 27.6, neuro_sd = 28.4, + other_mean = 16.1, other_sd = 14.1 +) { + list( + stroke_noesd = list(mean = stroke_noesd_mean, sd = stroke_noesd_sd), + stroke_esd = list(mean = stroke_esd_mean, sd = stroke_esd_sd), + tia = list(mean = tia_mean, sd = tia_sd), + neuro = list(mean = neuro_mean, sd = neuro_sd), + other = list(mean = other_mean, sd = other_sd) + ) +} + +#' ASU routing probabilities. +#' +#' Probabilities of each patient type being transferred from the acute +#' stroke unit (ASU) to other destinations. +#' +#' @param stroke_rehab Numeric. Probability stroke patient to rehab. +#' @param stroke_esd Numeric. Probability stroke patient to early supported +#' discharge (ESD) services. +#' @param stroke_other Numeric. Probability stroke patient to other +#' destinations (e.g., own home, care home, mortality). +#' @param tia_rehab Numeric. Probability transient ischemic attack (TIA) +#' patient to rehab. +#' @param tia_esd Numeric. Probability TIA patient to ESD. +#' @param tia_other Numeric. Probability TIA patient to other. +#' @param neuro_rehab Numeric. Probability complex neurological patient to +#' rehab. +#' @param neuro_esd Numeric. Probability complex neurological patient to ESD. +#' @param neuro_other Numeric. Probability complex neurological patient to +#' other. +#' @param other_rehab Numeric. Probability other patient to rehab. +#' @param other_esd Numeric. Probability other patient to ESD. +#' @param other_other Numeric. Probability other patient to other. +#' +#' @return A named list of routing probabilities for ASU. +create_asu_routing <- function( + stroke_rehab = 0.24, stroke_esd = 0.13, stroke_other = 0.63, + tia_rehab = 0.01, tia_esd = 0.01, tia_other = 0.98, + neuro_rehab = 0.11, neuro_esd = 0.05, neuro_other = 0.84, + other_rehab = 0.05, other_esd = 0.10, other_other = 0.85 +) { + list( + stroke = list(rehab = stroke_rehab, esd = stroke_esd, other = stroke_other), + tia = list(rehab = tia_rehab, esd = tia_esd, other = tia_other), + neuro = list(rehab = neuro_rehab, esd = neuro_esd, other = neuro_other), + other = list(rehab = other_rehab, esd = other_esd, other = other_other) + ) +} + +#' Rehabilitation unit routing probabilities. +#' +#' Probabilities of each patient type being transferred from the rehabilitation +#' unit to other destinations. +#' +#' @param stroke_esd Numeric. Probability stroke patient to early supported +#' discharge (ESD) services. +#' @param stroke_other Numeric. Probability stroke patient to other +#' destinations (e.g., own home, care home, mortality). +#' @param tia_esd Numeric. Probability transient ischemic attack (TIA) patient +#' to ESD. +#' @param tia_other Numeric. Probability TIA patient to other. +#' @param neuro_esd Numeric. Probability complex neurological patient to ESD. +#' @param neuro_other Numeric. Probability complex neurological patient to +#' other. +#' @param other_esd Numeric. Probability other patient to ESD. +#' @param other_other Numeric. Probability other patient to other. +#' +#' @return A named list of routing probabilities for rehabilitation unit. +create_rehab_routing <- function( + stroke_esd = 0.40, stroke_other = 0.60, + tia_esd = 0, tia_other = 1, + neuro_esd = 0.09, neuro_other = 0.91, + other_esd = 0.13, other_other = 0.88 +) { + list( + stroke = list(esd = stroke_esd, other = stroke_other), + tia = list(esd = tia_esd, other = tia_other), + neuro = list(esd = neuro_esd, other = neuro_other), + other = list(esd = other_esd, other = other_other) + ) +} + +#' Generate complete parameter list for simulation. +#' +#' @param asu_arrivals List. Acute stroke unit (ASU) arrival intervals. +#' @param rehab_arrivals List. Rehabilitation unit arrival intervals. +#' @param asu_los List. ASU length of stay (LOS) distributions. +#' @param rehab_los List. Rehabilitation unit LOS distributions. +#' @param asu_routing List. ASU routing probabilities. +#' @param rehab_routing List. Rehabilitation unit routing probabilities. +#' @param warm_up_period Integer. Length of warm-up period (days). +#' @param data_collection_period Integer. Length of data collection period +#' (days). +#' @param number_of_runs Integer. Number of simulation runs. +#' @param audit_interval Numeric. Audit interval (days). +#' @param cores Integer. Number of CPU cores to use. +#' +#' @return A named list of all simulation parameters. +create_parameters <- function( + asu_arrivals = create_asu_arrivals(), + rehab_arrivals = create_rehab_arrivals(), + asu_los = create_asu_los(), + rehab_los = create_rehab_los(), + asu_routing = create_asu_routing(), + rehab_routing = create_rehab_routing(), + warm_up_period = 365 * 3, + data_collection_period = 365 * 5, + number_of_runs = 150, + audit_interval = 1, + cores = 1 +) { + list( + asu_arrivals = asu_arrivals, + rehab_arrivals = rehab_arrivals, + asu_los = asu_los, + rehab_los = rehab_los, + asu_routing = asu_routing, + rehab_routing = rehab_routing, + warm_up_period = warm_up_period, + data_collection_period = data_collection_period, + number_of_runs = number_of_runs, + audit_interval = audit_interval, + cores = cores + ) +} From 9380de40e0848e363aae9dd2a03580fc91724168 Mon Sep 17 00:00:00 2001 From: amyheather Date: Tue, 1 Jul 2025 10:00:38 +0100 Subject: [PATCH 02/13] feat(package): add basic Rmd using parameters, add devtools to DESCRIPTION, ran devtools::document() and devtools::check(), then renv::install() and renv::snapshot() --- DESCRIPTION | 5 +- NAMESPACE | 2 + man/create_asu_arrivals.Rd | 25 + man/create_asu_los.Rd | 56 ++ man/create_asu_routing.Rd | 58 ++ man/create_parameters.Rd | 50 ++ man/create_rehab_arrivals.Rd | 22 + man/create_rehab_los.Rd | 48 ++ man/create_rehab_routing.Rd | 45 ++ renv.lock | 1265 +++++++++++++++++++++++++++++++++- rmarkdown/analysis.Rmd | 16 + 11 files changed, 1570 insertions(+), 22 deletions(-) create mode 100644 NAMESPACE create mode 100644 man/create_asu_arrivals.Rd create mode 100644 man/create_asu_los.Rd create mode 100644 man/create_asu_routing.Rd create mode 100644 man/create_parameters.Rd create mode 100644 man/create_rehab_arrivals.Rd create mode 100644 man/create_rehab_los.Rd create mode 100644 man/create_rehab_routing.Rd create mode 100644 rmarkdown/analysis.Rmd diff --git a/DESCRIPTION b/DESCRIPTION index d9a0e4b..3524c51 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -17,9 +17,6 @@ License: MIT + file LICENSE Encoding: UTF-8 LazyData: true RoxygenNote: 7.3.2 -Imports: - simmer Suggests: - testthat (>= 3.0.0), - lintr + devtools Config/testthat/edition: 3 diff --git a/NAMESPACE b/NAMESPACE new file mode 100644 index 0000000..6ae9268 --- /dev/null +++ b/NAMESPACE @@ -0,0 +1,2 @@ +# Generated by roxygen2: do not edit by hand + diff --git a/man/create_asu_arrivals.Rd b/man/create_asu_arrivals.Rd new file mode 100644 index 0000000..e6fcc5d --- /dev/null +++ b/man/create_asu_arrivals.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/parameters.R +\name{create_asu_arrivals} +\alias{create_asu_arrivals} +\title{Acute Stroke Unit (ASU) arrival intervals (days).} +\usage{ +create_asu_arrivals(stroke = 1.2, tia = 9.3, neuro = 3.6, other = 3.2) +} +\arguments{ +\item{stroke}{Numeric. Mean days between stroke patient arrivals.} + +\item{tia}{Numeric. Mean days between transient ischaemic attack (TIA) +patient arrivals.} + +\item{neuro}{Numeric. Mean days between complex neurological patient +arrivals.} + +\item{other}{Numeric. Mean days between other patient arrivals.} +} +\value{ +A named list of arrival intervals for ASU. +} +\description{ +For example, a value of 1.2 means a new admission every 1.2 days. +} diff --git a/man/create_asu_los.Rd b/man/create_asu_los.Rd new file mode 100644 index 0000000..ac609ad --- /dev/null +++ b/man/create_asu_los.Rd @@ -0,0 +1,56 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/parameters.R +\name{create_asu_los} +\alias{create_asu_los} +\title{Acute Stroke Unit (ASU) length of stay (LOS) distributions (days).} +\usage{ +create_asu_los( + stroke_noesd_mean = 7.4, + stroke_noesd_sd = 8.61, + stroke_esd_mean = 4.6, + stroke_esd_sd = 4.8, + stroke_mortality_mean = 7, + stroke_mortality_sd = 8.7, + tia_mean = 1.8, + tia_sd = 2.3, + neuro_mean = 4, + neuro_sd = 5, + other_mean = 3.8, + other_sd = 5.2 +) +} +\arguments{ +\item{stroke_noesd_mean}{Numeric. Mean LOS for stroke patients without early +supported discharged (ESD).} + +\item{stroke_noesd_sd}{Numeric. SD LOS for stroke patients without ESD.} + +\item{stroke_esd_mean}{Numeric. Mean LOS for stroke patients with ESD.} + +\item{stroke_esd_sd}{Numeric. SD LOS for stroke patients with ESD.} + +\item{stroke_mortality_mean}{Numeric. Mean LOS for stroke patients who pass +away.} + +\item{stroke_mortality_sd}{Numeric. SD LOS for stroke patients who pass +away.} + +\item{tia_mean}{Numeric. Mean LOS for transient ischemic attack (TIA) +patients.} + +\item{tia_sd}{Numeric. SD LOS for TIA patients.} + +\item{neuro_mean}{Numeric. Mean LOS for complex neurological patients} + +\item{neuro_sd}{Numeric. SD LOS for complex neurological patients} + +\item{other_mean}{Numeric. Mean LOS for other patients.} + +\item{other_sd}{Numeric. SD LOS for other patients.} +} +\value{ +A named list of LOS distributions for ASU. +} +\description{ +Mean and standard deviation (SD) of LOS in days in the ASU. +} diff --git a/man/create_asu_routing.Rd b/man/create_asu_routing.Rd new file mode 100644 index 0000000..8b11597 --- /dev/null +++ b/man/create_asu_routing.Rd @@ -0,0 +1,58 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/parameters.R +\name{create_asu_routing} +\alias{create_asu_routing} +\title{ASU routing probabilities.} +\usage{ +create_asu_routing( + stroke_rehab = 0.24, + stroke_esd = 0.13, + stroke_other = 0.63, + tia_rehab = 0.01, + tia_esd = 0.01, + tia_other = 0.98, + neuro_rehab = 0.11, + neuro_esd = 0.05, + neuro_other = 0.84, + other_rehab = 0.05, + other_esd = 0.1, + other_other = 0.85 +) +} +\arguments{ +\item{stroke_rehab}{Numeric. Probability stroke patient to rehab.} + +\item{stroke_esd}{Numeric. Probability stroke patient to early supported +discharge (ESD) services.} + +\item{stroke_other}{Numeric. Probability stroke patient to other +destinations (e.g., own home, care home, mortality).} + +\item{tia_rehab}{Numeric. Probability transient ischemic attack (TIA) +patient to rehab.} + +\item{tia_esd}{Numeric. Probability TIA patient to ESD.} + +\item{tia_other}{Numeric. Probability TIA patient to other.} + +\item{neuro_rehab}{Numeric. Probability complex neurological patient to +rehab.} + +\item{neuro_esd}{Numeric. Probability complex neurological patient to ESD.} + +\item{neuro_other}{Numeric. Probability complex neurological patient to +other.} + +\item{other_rehab}{Numeric. Probability other patient to rehab.} + +\item{other_esd}{Numeric. Probability other patient to ESD.} + +\item{other_other}{Numeric. Probability other patient to other.} +} +\value{ +A named list of routing probabilities for ASU. +} +\description{ +Probabilities of each patient type being transferred from the acute +stroke unit (ASU) to other destinations. +} diff --git a/man/create_parameters.Rd b/man/create_parameters.Rd new file mode 100644 index 0000000..7f570a1 --- /dev/null +++ b/man/create_parameters.Rd @@ -0,0 +1,50 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/parameters.R +\name{create_parameters} +\alias{create_parameters} +\title{Generate complete parameter list for simulation.} +\usage{ +create_parameters( + asu_arrivals = create_asu_arrivals(), + rehab_arrivals = create_rehab_arrivals(), + asu_los = create_asu_los(), + rehab_los = create_rehab_los(), + asu_routing = create_asu_routing(), + rehab_routing = create_rehab_routing(), + warm_up_period = 365 * 3, + data_collection_period = 365 * 5, + number_of_runs = 150, + audit_interval = 1, + cores = 1 +) +} +\arguments{ +\item{asu_arrivals}{List. Acute stroke unit (ASU) arrival intervals.} + +\item{rehab_arrivals}{List. Rehabilitation unit arrival intervals.} + +\item{asu_los}{List. ASU length of stay (LOS) distributions.} + +\item{rehab_los}{List. Rehabilitation unit LOS distributions.} + +\item{asu_routing}{List. ASU routing probabilities.} + +\item{rehab_routing}{List. Rehabilitation unit routing probabilities.} + +\item{warm_up_period}{Integer. Length of warm-up period (days).} + +\item{data_collection_period}{Integer. Length of data collection period +(days).} + +\item{number_of_runs}{Integer. Number of simulation runs.} + +\item{audit_interval}{Numeric. Audit interval (days).} + +\item{cores}{Integer. Number of CPU cores to use.} +} +\value{ +A named list of all simulation parameters. +} +\description{ +Generate complete parameter list for simulation. +} diff --git a/man/create_rehab_arrivals.Rd b/man/create_rehab_arrivals.Rd new file mode 100644 index 0000000..88ad3ca --- /dev/null +++ b/man/create_rehab_arrivals.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/parameters.R +\name{create_rehab_arrivals} +\alias{create_rehab_arrivals} +\title{Rehabilitation unit arrival intervals (days).} +\usage{ +create_rehab_arrivals(stroke = 21.8, neuro = 31.7, other = 28.6) +} +\arguments{ +\item{stroke}{Numeric. Mean days between stroke patient arrivals.} + +\item{neuro}{Numeric. Mean days between complex neurological patient +arrivals.} + +\item{other}{Numeric. Mean days between other patient arrivals.} +} +\value{ +A named list of arrival intervals for rehabilitation unit. +} +\description{ +For example, a value of 21.8 means a new admission every 21.8 days. +} diff --git a/man/create_rehab_los.Rd b/man/create_rehab_los.Rd new file mode 100644 index 0000000..8e509f4 --- /dev/null +++ b/man/create_rehab_los.Rd @@ -0,0 +1,48 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/parameters.R +\name{create_rehab_los} +\alias{create_rehab_los} +\title{Rehabilitation unit length of stay (LOS) distributions (days).} +\usage{ +create_rehab_los( + stroke_noesd_mean = 28.4, + stroke_noesd_sd = 27.2, + stroke_esd_mean = 30.3, + stroke_esd_sd = 23.1, + tia_mean = 18.7, + tia_sd = 23.5, + neuro_mean = 27.6, + neuro_sd = 28.4, + other_mean = 16.1, + other_sd = 14.1 +) +} +\arguments{ +\item{stroke_noesd_mean}{Numeric. Mean LOS for stroke patients without early +supported discharged (ESD).} + +\item{stroke_noesd_sd}{Numeric. SD LOS for stroke patients without ESD.} + +\item{stroke_esd_mean}{Numeric. Mean LOS for stroke patients with ESD.} + +\item{stroke_esd_sd}{Numeric. SD LOS for stroke patients with ESD.} + +\item{tia_mean}{Numeric. Mean LOS for transient ischemic attack (TIA) +patients.} + +\item{tia_sd}{Numeric. SD LOS for TIA patients.} + +\item{neuro_mean}{Numeric. Mean LOS for complex neurological patients} + +\item{neuro_sd}{Numeric. SD LOS for complex neurological patients} + +\item{other_mean}{Numeric. Mean LOS for other patients.} + +\item{other_sd}{Numeric. SD LOS for other patients.} +} +\value{ +A named list of LOS distributions for rehabilitation unit. +} +\description{ +Rehabilitation unit length of stay (LOS) distributions (days). +} diff --git a/man/create_rehab_routing.Rd b/man/create_rehab_routing.Rd new file mode 100644 index 0000000..53423e3 --- /dev/null +++ b/man/create_rehab_routing.Rd @@ -0,0 +1,45 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/parameters.R +\name{create_rehab_routing} +\alias{create_rehab_routing} +\title{Rehabilitation unit routing probabilities.} +\usage{ +create_rehab_routing( + stroke_esd = 0.4, + stroke_other = 0.6, + tia_esd = 0, + tia_other = 1, + neuro_esd = 0.09, + neuro_other = 0.91, + other_esd = 0.13, + other_other = 0.88 +) +} +\arguments{ +\item{stroke_esd}{Numeric. Probability stroke patient to early supported +discharge (ESD) services.} + +\item{stroke_other}{Numeric. Probability stroke patient to other +destinations (e.g., own home, care home, mortality).} + +\item{tia_esd}{Numeric. Probability transient ischemic attack (TIA) patient +to ESD.} + +\item{tia_other}{Numeric. Probability TIA patient to other.} + +\item{neuro_esd}{Numeric. Probability complex neurological patient to ESD.} + +\item{neuro_other}{Numeric. Probability complex neurological patient to +other.} + +\item{other_esd}{Numeric. Probability other patient to ESD.} + +\item{other_other}{Numeric. Probability other patient to other.} +} +\value{ +A named list of routing probabilities for rehabilitation unit. +} +\description{ +Probabilities of each patient type being transferred from the rehabilitation +unit to other destinations. +} diff --git a/renv.lock b/renv.lock index d52570c..c060c2c 100644 --- a/renv.lock +++ b/renv.lock @@ -4,11 +4,21 @@ "Repositories": [ { "Name": "CRAN", - "URL": "https://packagemanager.posit.co/cran/latest" + "URL": "https://cloud.r-project.org" } ] }, "Packages": { + "R6": { + "Package": "R6", + "Version": "2.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "470851b6d5d0ac559e9d01bb352b4021" + }, "Rcpp": { "Package": "Rcpp", "Version": "1.0.14", @@ -20,49 +30,1268 @@ ], "Hash": "e7bdd9ee90e96921ca8a0f1972d66682" }, - "codetools": { - "Package": "codetools", - "Version": "0.2-20", + "askpass": { + "Package": "askpass", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "sys" + ], + "Hash": "c39f4155b3ceb1a9a2799d700fbd4b6a" + }, + "base64enc": { + "Package": "base64enc", + "Version": "0.1-3", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "R" ], - "Hash": "61e097f35917d342622f21cdc79c256e" + "Hash": "543776ae6848fde2f48ff3816d0628bc" }, - "magrittr": { - "Package": "magrittr", - "Version": "2.0.3", + "brew": { + "Package": "brew", + "Version": "1.0-10", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "8f4a384e19dccd8c65356dc096847b76" + }, + "brio": { + "Package": "brio", + "Version": "1.1.5", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "R" ], - "Hash": "7ce2733a9826b3aeb1775d56fd305472" + "Hash": "c1ee497a6d999947c2c224ae46799b1a" }, - "renv": { - "Package": "renv", - "Version": "1.0.7", + "bslib": { + "Package": "bslib", + "Version": "0.9.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "cachem", + "fastmap", + "grDevices", + "htmltools", + "jquerylib", + "jsonlite", + "lifecycle", + "memoise", + "mime", + "rlang", + "sass" + ], + "Hash": "70a6489cc254171fb9b4a7f130f44dca" + }, + "cachem": { + "Package": "cachem", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "fastmap", + "rlang" + ], + "Hash": "cd9a672193789068eb5a2aad65a0dedf" + }, + "callr": { + "Package": "callr", + "Version": "3.7.6", "Source": "Repository", "Repository": "CRAN", "Requirements": [ + "R", + "R6", + "processx", "utils" ], - "Hash": "397b7b2a265bc5a7a06852524dabae20" + "Hash": "d7e13f49c19103ece9e58ad2d83a7354" + }, + "cli": { + "Package": "cli", + "Version": "3.6.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "b21916dd77a27642b447374a5d30ecf3" + }, + "clipr": { + "Package": "clipr", + "Version": "0.8.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "utils" + ], + "Hash": "3f038e5ac7f41d4ac41ce658c85e3042" + }, + "commonmark": { + "Package": "commonmark", + "Version": "1.9.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "14eb0596f987c71535d07c3aff814742" + }, + "cpp11": { + "Package": "cpp11", + "Version": "0.5.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "2720e3fd3dad08f34b19b56b3d6f073d" + }, + "crayon": { + "Package": "crayon", + "Version": "1.5.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "grDevices", + "methods", + "utils" + ], + "Hash": "859d96e65ef198fd43e82b9628d593ef" + }, + "credentials": { + "Package": "credentials", + "Version": "2.0.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "askpass", + "curl", + "jsonlite", + "openssl", + "sys" + ], + "Hash": "09fd631e607a236f8cc7f9604db32cb8" + }, + "curl": { + "Package": "curl", + "Version": "6.4.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "a331a41f5a999c2b59fdff9f48ac579f" + }, + "desc": { + "Package": "desc", + "Version": "1.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "cli", + "utils" + ], + "Hash": "99b79fcbd6c4d1ce087f5c5c758b384f" + }, + "devtools": { + "Package": "devtools", + "Version": "2.4.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "desc", + "ellipsis", + "fs", + "lifecycle", + "memoise", + "miniUI", + "pkgbuild", + "pkgdown", + "pkgload", + "profvis", + "rcmdcheck", + "remotes", + "rlang", + "roxygen2", + "rversions", + "sessioninfo", + "stats", + "testthat", + "tools", + "urlchecker", + "usethis", + "utils", + "withr" + ], + "Hash": "ea5bc8b4a6a01e4f12d98b58329930bb" + }, + "diffobj": { + "Package": "diffobj", + "Version": "0.3.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "crayon", + "methods", + "stats", + "tools", + "utils" + ], + "Hash": "e036ce354ab60e705ac5f40bac87e8cb" + }, + "digest": { + "Package": "digest", + "Version": "0.6.36", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "fd6824ad91ede64151e93af67df6376b" + }, + "downlit": { + "Package": "downlit", + "Version": "0.4.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "brio", + "desc", + "digest", + "evaluate", + "fansi", + "memoise", + "rlang", + "vctrs", + "withr", + "yaml" + ], + "Hash": "45a6a596bf0108ee1ff16a040a2df897" + }, + "ellipsis": { + "Package": "ellipsis", + "Version": "0.3.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "rlang" + ], + "Hash": "bb0eec2fe32e88d9e2836c2f73ea2077" + }, + "evaluate": { + "Package": "evaluate", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "3fd29944b231036ad67c3edb32e02201" + }, + "fansi": { + "Package": "fansi", + "Version": "1.0.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "utils" + ], + "Hash": "962174cf2aeb5b9eea581522286a911f" + }, + "fastmap": { + "Package": "fastmap", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "aa5e1cd11c2d15497494c5292d7ffcc8" + }, + "fontawesome": { + "Package": "fontawesome", + "Version": "0.5.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "htmltools", + "rlang" + ], + "Hash": "bd1297f9b5b1fc1372d19e2c4cd82215" + }, + "fs": { + "Package": "fs", + "Version": "1.6.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "15aeb8c27f5ea5161f9f6a641fafd93a" + }, + "gert": { + "Package": "gert", + "Version": "2.1.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "askpass", + "credentials", + "openssl", + "rstudioapi", + "sys", + "zip" + ], + "Hash": "b886f9838f82444c47a9962adc5ab8e8" + }, + "gh": { + "Package": "gh", + "Version": "1.5.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "gitcreds", + "glue", + "httr2", + "ini", + "jsonlite", + "lifecycle", + "rlang" + ], + "Hash": "d92acb7afad09df6839e4e456e538d03" + }, + "gitcreds": { + "Package": "gitcreds", + "Version": "0.1.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "ab08ac61f3e1be454ae21911eb8bc2fe" + }, + "glue": { + "Package": "glue", + "Version": "1.7.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "e0b3a53876554bd45879e596cdb10a52" + }, + "highr": { + "Package": "highr", + "Version": "0.11", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "xfun" + ], + "Hash": "d65ba49117ca223614f71b60d85b8ab7" + }, + "htmltools": { + "Package": "htmltools", + "Version": "0.5.8.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "digest", + "fastmap", + "grDevices", + "rlang", + "utils" + ], + "Hash": "81d371a9cc60640e74e4ab6ac46dcedc" + }, + "htmlwidgets": { + "Package": "htmlwidgets", + "Version": "1.6.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "grDevices", + "htmltools", + "jsonlite", + "knitr", + "rmarkdown", + "yaml" + ], + "Hash": "04291cc45198225444a397606810ac37" }, - "simmer": { - "Package": "simmer", - "Version": "4.4.7", + "httpuv": { + "Package": "httpuv", + "Version": "1.6.16", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "R", + "R6", "Rcpp", - "codetools", + "later", + "promises", + "utils" + ], + "Hash": "6c3c8728e40326de6529a5c46e377e5c" + }, + "httr2": { + "Package": "httr2", + "Version": "1.1.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "cli", + "curl", + "glue", + "lifecycle", "magrittr", + "openssl", + "rappdirs", + "rlang", + "vctrs", + "withr" + ], + "Hash": "ade531519694081d91036b509eb30594" + }, + "ini": { + "Package": "ini", + "Version": "0.3.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "6154ec2223172bce8162d4153cda21f7" + }, + "jquerylib": { + "Package": "jquerylib", + "Version": "0.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "htmltools" + ], + "Hash": "5aab57a3bd297eee1c1d862735972182" + }, + "jsonlite": { + "Package": "jsonlite", + "Version": "2.0.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "methods" + ], + "Hash": "b0776f526d36d8bd4a3344a88fe165c4" + }, + "knitr": { + "Package": "knitr", + "Version": "1.49", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "evaluate", + "highr", + "methods", + "tools", + "xfun", + "yaml" + ], + "Hash": "9fcb189926d93c636dea94fbe4f44480" + }, + "later": { + "Package": "later", + "Version": "1.4.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "Rcpp", + "rlang" + ], + "Hash": "9591aabef9cf988f05bde9324fd3ad99" + }, + "lifecycle": { + "Package": "lifecycle", + "Version": "1.0.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "rlang" + ], + "Hash": "b8552d117e1b808b09a832f589b79035" + }, + "magrittr": { + "Package": "magrittr", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "7ce2733a9826b3aeb1775d56fd305472" + }, + "memoise": { + "Package": "memoise", + "Version": "2.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "cachem", + "rlang" + ], + "Hash": "e2817ccf4a065c5d9d7f2cfbe7c1d78c" + }, + "mime": { + "Package": "mime", + "Version": "0.13", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "tools" + ], + "Hash": "0ec19f34c72fab674d8f2b4b1c6410e1" + }, + "miniUI": { + "Package": "miniUI", + "Version": "0.1.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "htmltools", + "shiny", "utils" ], - "Hash": "6e993f252a8a2a7bf19856c82af1414b" + "Hash": "96b7fedb0964cc6b86631fb2fee23afa" + }, + "openssl": { + "Package": "openssl", + "Version": "2.3.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "askpass" + ], + "Hash": "05ce1ed077e8c97fbb3ec1cb078f1159" + }, + "pillar": { + "Package": "pillar", + "Version": "1.10.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "cli", + "glue", + "lifecycle", + "rlang", + "utf8", + "utils", + "vctrs" + ], + "Hash": "1098920a19b5cd5a15bacdc74a89979d" + }, + "pkgbuild": { + "Package": "pkgbuild", + "Version": "1.4.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "callr", + "cli", + "desc", + "processx" + ], + "Hash": "30eaaab94db72652e72e3475c1b55278" + }, + "pkgconfig": { + "Package": "pkgconfig", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "utils" + ], + "Hash": "01f28d4278f15c76cddbea05899c5d6f" + }, + "pkgdown": { + "Package": "pkgdown", + "Version": "2.1.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bslib", + "callr", + "cli", + "desc", + "downlit", + "fontawesome", + "fs", + "httr2", + "jsonlite", + "openssl", + "purrr", + "ragg", + "rlang", + "rmarkdown", + "tibble", + "whisker", + "withr", + "xml2", + "yaml" + ], + "Hash": "c03e900e6971a37e6f987be186fd213b" + }, + "pkgload": { + "Package": "pkgload", + "Version": "1.4.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "desc", + "fs", + "glue", + "lifecycle", + "methods", + "pkgbuild", + "processx", + "rlang", + "rprojroot", + "utils", + "withr" + ], + "Hash": "2ec30ffbeec83da57655b850cf2d3e0e" + }, + "praise": { + "Package": "praise", + "Version": "1.0.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "a555924add98c99d2f411e37e7d25e9f" + }, + "prettyunits": { + "Package": "prettyunits", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "6b01fc98b1e86c4f705ce9dcfd2f57c7" + }, + "processx": { + "Package": "processx", + "Version": "3.8.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "ps", + "utils" + ], + "Hash": "0c90a7d71988856bad2a2a45dd871bb9" + }, + "profvis": { + "Package": "profvis", + "Version": "0.4.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "htmlwidgets", + "rlang", + "vctrs" + ], + "Hash": "bffa126bf92987e677c12cfb5651fc1d" + }, + "promises": { + "Package": "promises", + "Version": "1.3.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R6", + "Rcpp", + "fastmap", + "later", + "magrittr", + "rlang", + "stats" + ], + "Hash": "70157a4a73963da5779f9c67f4d31fd1" + }, + "ps": { + "Package": "ps", + "Version": "1.8.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "b4404b1de13758dea1c0484ad0d48563" + }, + "purrr": { + "Package": "purrr", + "Version": "1.0.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "lifecycle", + "magrittr", + "rlang", + "vctrs" + ], + "Hash": "1cba04a4e9414bdefc9dcaa99649a8dc" + }, + "ragg": { + "Package": "ragg", + "Version": "1.4.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "systemfonts", + "textshaping" + ], + "Hash": "1591adde9ce8ff7de58072e4a32b66ce" + }, + "rappdirs": { + "Package": "rappdirs", + "Version": "0.3.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "5e3c5dc0b071b21fa128676560dbe94d" + }, + "rcmdcheck": { + "Package": "rcmdcheck", + "Version": "1.4.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R6", + "callr", + "cli", + "curl", + "desc", + "digest", + "pkgbuild", + "prettyunits", + "rprojroot", + "sessioninfo", + "utils", + "withr", + "xopen" + ], + "Hash": "8f25ebe2ec38b1f2aef3b0d2ef76f6c4" + }, + "remotes": { + "Package": "remotes", + "Version": "2.5.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods", + "stats", + "tools", + "utils" + ], + "Hash": "3ee025083e66f18db6cf27b56e23e141" + }, + "renv": { + "Package": "renv", + "Version": "1.0.7", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "utils" + ], + "Hash": "397b7b2a265bc5a7a06852524dabae20" + }, + "rlang": { + "Package": "rlang", + "Version": "1.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "3eec01f8b1dee337674b2e34ab1f9bc1" + }, + "rmarkdown": { + "Package": "rmarkdown", + "Version": "2.29", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bslib", + "evaluate", + "fontawesome", + "htmltools", + "jquerylib", + "jsonlite", + "knitr", + "methods", + "tinytex", + "tools", + "utils", + "xfun", + "yaml" + ], + "Hash": "df99277f63d01c34e95e3d2f06a79736" + }, + "roxygen2": { + "Package": "roxygen2", + "Version": "7.3.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "brew", + "cli", + "commonmark", + "cpp11", + "desc", + "knitr", + "methods", + "pkgload", + "purrr", + "rlang", + "stringi", + "stringr", + "utils", + "withr", + "xml2" + ], + "Hash": "6ee25f9054a70f44d615300ed531ba8d" + }, + "rprojroot": { + "Package": "rprojroot", + "Version": "2.0.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "4c8415e0ec1e29f3f4f6fc108bef0144" + }, + "rstudioapi": { + "Package": "rstudioapi", + "Version": "0.17.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "5f90cd73946d706cfe26024294236113" + }, + "rversions": { + "Package": "rversions", + "Version": "2.1.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "curl", + "utils", + "xml2" + ], + "Hash": "a9881dfed103e83f9de151dc17002cd1" + }, + "sass": { + "Package": "sass", + "Version": "0.4.10", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R6", + "fs", + "htmltools", + "rappdirs", + "rlang" + ], + "Hash": "3fb78d066fb92299b1d13f6a7c9a90a8" + }, + "sessioninfo": { + "Package": "sessioninfo", + "Version": "1.2.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "tools", + "utils" + ], + "Hash": "bf169c6e52cdbded916e448dc1254913" + }, + "shiny": { + "Package": "shiny", + "Version": "1.11.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "bslib", + "cachem", + "cli", + "commonmark", + "fastmap", + "fontawesome", + "glue", + "grDevices", + "htmltools", + "httpuv", + "jsonlite", + "later", + "lifecycle", + "methods", + "mime", + "promises", + "rlang", + "sourcetools", + "tools", + "utils", + "withr", + "xtable" + ], + "Hash": "011db3556755012e632ed99d083d7d75" + }, + "sourcetools": { + "Package": "sourcetools", + "Version": "0.1.7-1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "5f5a7629f956619d519205ec475fe647" + }, + "stringi": { + "Package": "stringi", + "Version": "1.8.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "stats", + "tools", + "utils" + ], + "Hash": "39e1144fd75428983dc3f63aa53dfa91" + }, + "stringr": { + "Package": "stringr", + "Version": "1.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "magrittr", + "rlang", + "stringi", + "vctrs" + ], + "Hash": "960e2ae9e09656611e0b8214ad543207" + }, + "sys": { + "Package": "sys", + "Version": "3.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "de342ebfebdbf40477d0758d05426646" + }, + "systemfonts": { + "Package": "systemfonts", + "Version": "1.2.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "cpp11", + "grid", + "jsonlite", + "lifecycle", + "tools", + "utils" + ], + "Hash": "fe31683d2c6fd9a5724bcdf8ed44ded9" + }, + "testthat": { + "Package": "testthat", + "Version": "3.2.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "brio", + "callr", + "cli", + "desc", + "digest", + "evaluate", + "jsonlite", + "lifecycle", + "magrittr", + "methods", + "pkgload", + "praise", + "processx", + "ps", + "rlang", + "utils", + "waldo", + "withr" + ], + "Hash": "42f889439ccb14c55fc3d75c9c755056" + }, + "textshaping": { + "Package": "textshaping", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cpp11", + "lifecycle", + "stats", + "stringi", + "systemfonts", + "utils" + ], + "Hash": "75b5813527f4154cb467e4cf60911333" + }, + "tibble": { + "Package": "tibble", + "Version": "3.3.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "lifecycle", + "magrittr", + "methods", + "pillar", + "pkgconfig", + "rlang", + "utils", + "vctrs" + ], + "Hash": "784b27d0801c3829de602105757b2cd7" + }, + "tinytex": { + "Package": "tinytex", + "Version": "0.57", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "xfun" + ], + "Hash": "02d65e0c0415bf36a7ddc0d2ba50a840" + }, + "urlchecker": { + "Package": "urlchecker", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "curl", + "tools", + "xml2" + ], + "Hash": "409328b8e1253c8d729a7836fe7f7a16" + }, + "usethis": { + "Package": "usethis", + "Version": "3.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "clipr", + "crayon", + "curl", + "desc", + "fs", + "gert", + "gh", + "glue", + "jsonlite", + "lifecycle", + "purrr", + "rappdirs", + "rlang", + "rprojroot", + "rstudioapi", + "stats", + "tools", + "utils", + "whisker", + "withr", + "yaml" + ], + "Hash": "0d7f5ca181f9b1e68b217bd93b6cc703" + }, + "utf8": { + "Package": "utf8", + "Version": "1.2.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "d526d558be176e9ceb68c3d1e83479b7" + }, + "vctrs": { + "Package": "vctrs", + "Version": "0.6.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "rlang" + ], + "Hash": "c03fa420630029418f7e6da3667aac4a" + }, + "waldo": { + "Package": "waldo", + "Version": "0.6.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "diffobj", + "glue", + "methods", + "rlang" + ], + "Hash": "52f574062a7b66e56926988c3fbdb3b7" + }, + "whisker": { + "Package": "whisker", + "Version": "0.4.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "c6abfa47a46d281a7d5159d0a8891e88" + }, + "withr": { + "Package": "withr", + "Version": "3.0.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics" + ], + "Hash": "cc2d62c76458d425210d1eb1478b30b4" + }, + "xfun": { + "Package": "xfun", + "Version": "0.49", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "stats", + "tools" + ], + "Hash": "8687398773806cfff9401a2feca96298" + }, + "xml2": { + "Package": "xml2", + "Version": "1.3.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "methods", + "rlang" + ], + "Hash": "1d0336142f4cd25d8d23cd3ba7a8fb61" + }, + "xopen": { + "Package": "xopen", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "processx" + ], + "Hash": "423df1e86d5533fcb73c6b02b4923b49" + }, + "xtable": { + "Package": "xtable", + "Version": "1.8-4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "stats", + "utils" + ], + "Hash": "b8acdf8af494d9ec19ccb2481a9b11c2" + }, + "yaml": { + "Package": "yaml", + "Version": "2.3.10", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "51dab85c6c98e50a18d7551e9d49f76c" + }, + "zip": { + "Package": "zip", + "Version": "2.3.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "6ebe4b1dc74c3e50e74e316323629583" } } } diff --git a/rmarkdown/analysis.Rmd b/rmarkdown/analysis.Rmd new file mode 100644 index 0000000..f197b03 --- /dev/null +++ b/rmarkdown/analysis.Rmd @@ -0,0 +1,16 @@ +--- +title: "analysis" +output: html_document +--- + +```{r} +# Load the package from the local directory +devtools::load_all() + +# Load the package +library(simulation) +``` + +```{r} +create_parameters() +``` From 22bec6eebac846c63fb0405c85541b25357d8334 Mon Sep 17 00:00:00 2001 From: amyheather Date: Tue, 1 Jul 2025 10:13:06 +0100 Subject: [PATCH 03/13] feat(parameters): amend create_parameters for R, add @export throughout, and simplify returns --- NAMESPACE | 7 ++ R/parameters.R | 144 ++++++++++++++++----------------------- man/create_parameters.Rd | 15 +++- 3 files changed, 79 insertions(+), 87 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 6ae9268..d740a54 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,2 +1,9 @@ # Generated by roxygen2: do not edit by hand +export(create_asu_arrivals) +export(create_asu_los) +export(create_asu_routing) +export(create_parameters) +export(create_rehab_arrivals) +export(create_rehab_los) +export(create_rehab_routing) \ No newline at end of file diff --git a/R/parameters.R b/R/parameters.R index df93157..59d779b 100644 --- a/R/parameters.R +++ b/R/parameters.R @@ -10,15 +10,12 @@ #' @param other Numeric. Mean days between other patient arrivals. #' #' @return A named list of arrival intervals for ASU. +#' @export + create_asu_arrivals <- function( - stroke = 1.2, tia = 9.3, neuro = 3.6, other = 3.2 + stroke = 1.2, tia = 9.3, neuro = 3.6, other = 3.2 ) { - list( - stroke = stroke, - tia = tia, - neuro = neuro, - other = other - ) + return(as.list(environment())) } #' Rehabilitation unit arrival intervals (days). @@ -31,14 +28,12 @@ create_asu_arrivals <- function( #' @param other Numeric. Mean days between other patient arrivals. #' #' @return A named list of arrival intervals for rehabilitation unit. +#' @export + create_rehab_arrivals <- function( - stroke = 21.8, neuro = 31.7, other = 28.6 + stroke = 21.8, neuro = 31.7, other = 28.6 ) { - list( - stroke = stroke, - neuro = neuro, - other = other - ) + return(as.list(environment())) } #' Acute Stroke Unit (ASU) length of stay (LOS) distributions (days). @@ -63,22 +58,17 @@ create_rehab_arrivals <- function( #' @param other_sd Numeric. SD LOS for other patients. #' #' @return A named list of LOS distributions for ASU. +#' @export + create_asu_los <- function( - stroke_noesd_mean = 7.4, stroke_noesd_sd = 8.61, - stroke_esd_mean = 4.6, stroke_esd_sd = 4.8, - stroke_mortality_mean = 7.0, stroke_mortality_sd = 8.7, - tia_mean = 1.8, tia_sd = 2.3, - neuro_mean = 4.0, neuro_sd = 5.0, - other_mean = 3.8, other_sd = 5.2 + stroke_noesd_mean = 7.4, stroke_noesd_sd = 8.61, + stroke_esd_mean = 4.6, stroke_esd_sd = 4.8, + stroke_mortality_mean = 7.0, stroke_mortality_sd = 8.7, + tia_mean = 1.8, tia_sd = 2.3, + neuro_mean = 4.0, neuro_sd = 5.0, + other_mean = 3.8, other_sd = 5.2 ) { - list( - stroke_noesd = list(mean = stroke_noesd_mean, sd = stroke_noesd_sd), - stroke_esd = list(mean = stroke_esd_mean, sd = stroke_esd_sd), - stroke_mortality = list(mean = stroke_mortality_mean, sd = stroke_mortality_sd), - tia = list(mean = tia_mean, sd = tia_sd), - neuro = list(mean = neuro_mean, sd = neuro_sd), - other = list(mean = other_mean, sd = other_sd) - ) + return(as.list(environment())) } #' Rehabilitation unit length of stay (LOS) distributions (days). @@ -97,20 +87,16 @@ create_asu_los <- function( #' @param other_sd Numeric. SD LOS for other patients. #' #' @return A named list of LOS distributions for rehabilitation unit. +#' @export + create_rehab_los <- function( - stroke_noesd_mean = 28.4, stroke_noesd_sd = 27.2, - stroke_esd_mean = 30.3, stroke_esd_sd = 23.1, - tia_mean = 18.7, tia_sd = 23.5, - neuro_mean = 27.6, neuro_sd = 28.4, - other_mean = 16.1, other_sd = 14.1 + stroke_noesd_mean = 28.4, stroke_noesd_sd = 27.2, + stroke_esd_mean = 30.3, stroke_esd_sd = 23.1, + tia_mean = 18.7, tia_sd = 23.5, + neuro_mean = 27.6, neuro_sd = 28.4, + other_mean = 16.1, other_sd = 14.1 ) { - list( - stroke_noesd = list(mean = stroke_noesd_mean, sd = stroke_noesd_sd), - stroke_esd = list(mean = stroke_esd_mean, sd = stroke_esd_sd), - tia = list(mean = tia_mean, sd = tia_sd), - neuro = list(mean = neuro_mean, sd = neuro_sd), - other = list(mean = other_mean, sd = other_sd) - ) + return(as.list(environment())) } #' ASU routing probabilities. @@ -137,18 +123,15 @@ create_rehab_los <- function( #' @param other_other Numeric. Probability other patient to other. #' #' @return A named list of routing probabilities for ASU. +#' @export + create_asu_routing <- function( - stroke_rehab = 0.24, stroke_esd = 0.13, stroke_other = 0.63, - tia_rehab = 0.01, tia_esd = 0.01, tia_other = 0.98, - neuro_rehab = 0.11, neuro_esd = 0.05, neuro_other = 0.84, - other_rehab = 0.05, other_esd = 0.10, other_other = 0.85 + stroke_rehab = 0.24, stroke_esd = 0.13, stroke_other = 0.63, + tia_rehab = 0.01, tia_esd = 0.01, tia_other = 0.98, + neuro_rehab = 0.11, neuro_esd = 0.05, neuro_other = 0.84, + other_rehab = 0.05, other_esd = 0.10, other_other = 0.85 ) { - list( - stroke = list(rehab = stroke_rehab, esd = stroke_esd, other = stroke_other), - tia = list(rehab = tia_rehab, esd = tia_esd, other = tia_other), - neuro = list(rehab = neuro_rehab, esd = neuro_esd, other = neuro_other), - other = list(rehab = other_rehab, esd = other_esd, other = other_other) - ) + return(as.list(environment())) } #' Rehabilitation unit routing probabilities. @@ -170,18 +153,15 @@ create_asu_routing <- function( #' @param other_other Numeric. Probability other patient to other. #' #' @return A named list of routing probabilities for rehabilitation unit. +#' @export + create_rehab_routing <- function( - stroke_esd = 0.40, stroke_other = 0.60, - tia_esd = 0, tia_other = 1, - neuro_esd = 0.09, neuro_other = 0.91, - other_esd = 0.13, other_other = 0.88 + stroke_esd = 0.40, stroke_other = 0.60, + tia_esd = 0L, tia_other = 1L, + neuro_esd = 0.09, neuro_other = 0.91, + other_esd = 0.13, other_other = 0.88 ) { - list( - stroke = list(esd = stroke_esd, other = stroke_other), - tia = list(esd = tia_esd, other = tia_other), - neuro = list(esd = neuro_esd, other = neuro_other), - other = list(esd = other_esd, other = other_other) - ) + return(as.list(environment())) } #' Generate complete parameter list for simulation. @@ -196,34 +176,30 @@ create_rehab_routing <- function( #' @param data_collection_period Integer. Length of data collection period #' (days). #' @param number_of_runs Integer. Number of simulation runs. -#' @param audit_interval Numeric. Audit interval (days). +#' @param scenario_name Label for scenario (int|float|string). #' @param cores Integer. Number of CPU cores to use. +#' @param log_to_console Whether to print activity log to console. +#' @param log_to_file Whether to save activity log to file. +#' @param file_path Path to save log to file. #' #' @return A named list of all simulation parameters. +#' @export + create_parameters <- function( - asu_arrivals = create_asu_arrivals(), - rehab_arrivals = create_rehab_arrivals(), - asu_los = create_asu_los(), - rehab_los = create_rehab_los(), - asu_routing = create_asu_routing(), - rehab_routing = create_rehab_routing(), - warm_up_period = 365 * 3, - data_collection_period = 365 * 5, - number_of_runs = 150, - audit_interval = 1, - cores = 1 + asu_arrivals = create_asu_arrivals(), + rehab_arrivals = create_rehab_arrivals(), + asu_los = create_asu_los(), + rehab_los = create_rehab_los(), + asu_routing = create_asu_routing(), + rehab_routing = create_rehab_routing(), + warm_up_period = 365L * 3L, # 3 years + data_collection_period = 365L * 5L, # 5 years + number_of_runs = 150L, + scenario_name = NULL, + cores = 1L, + log_to_console = FALSE, + log_to_file = FALSE, + file_path = NULL ) { - list( - asu_arrivals = asu_arrivals, - rehab_arrivals = rehab_arrivals, - asu_los = asu_los, - rehab_los = rehab_los, - asu_routing = asu_routing, - rehab_routing = rehab_routing, - warm_up_period = warm_up_period, - data_collection_period = data_collection_period, - number_of_runs = number_of_runs, - audit_interval = audit_interval, - cores = cores - ) + return(as.list(environment())) } diff --git a/man/create_parameters.Rd b/man/create_parameters.Rd index 7f570a1..9910314 100644 --- a/man/create_parameters.Rd +++ b/man/create_parameters.Rd @@ -14,8 +14,11 @@ create_parameters( warm_up_period = 365 * 3, data_collection_period = 365 * 5, number_of_runs = 150, - audit_interval = 1, - cores = 1 + scenario_name = NULL, + cores = 1, + log_to_console = FALSE, + log_to_file = FALSE, + file_path = NULL ) } \arguments{ @@ -38,9 +41,15 @@ create_parameters( \item{number_of_runs}{Integer. Number of simulation runs.} -\item{audit_interval}{Numeric. Audit interval (days).} +\item{scenario_name}{Label for scenario (int|float|string).} \item{cores}{Integer. Number of CPU cores to use.} + +\item{log_to_console}{Whether to print activity log to console.} + +\item{log_to_file}{Whether to save activity log to file.} + +\item{file_path}{Path to save log to file.} } \value{ A named list of all simulation parameters. From 7eaa2913d4e8571e2af05364c580d3ec222e6a91 Mon Sep 17 00:00:00 2001 From: amyheather Date: Tue, 1 Jul 2025 10:38:47 +0100 Subject: [PATCH 04/13] feat(model): very basic model which generates stroke patient ASU arrivals (with mini run time and no trajectory) --- DESCRIPTION | 2 ++ NAMESPACE | 10 ++++++++- R/model.R | 45 +++++++++++++++++++++++++++++++++++++ man/create_parameters.Rd | 8 +++---- man/create_rehab_routing.Rd | 4 ++-- man/model.Rd | 23 +++++++++++++++++++ renv.lock | 24 ++++++++++++++++++++ rmarkdown/analysis.Rmd | 2 +- 8 files changed, 110 insertions(+), 8 deletions(-) create mode 100644 R/model.R create mode 100644 man/model.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 3524c51..9709a0a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -17,6 +17,8 @@ License: MIT + file LICENSE Encoding: UTF-8 LazyData: true RoxygenNote: 7.3.2 +Imports: + simmer Suggests: devtools Config/testthat/edition: 3 diff --git a/NAMESPACE b/NAMESPACE index d740a54..e0a0d4e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -6,4 +6,12 @@ export(create_asu_routing) export(create_parameters) export(create_rehab_arrivals) export(create_rehab_los) -export(create_rehab_routing) \ No newline at end of file +export(create_rehab_routing) +export(model) +importFrom(simmer,add_generator) +importFrom(simmer,get_mon_arrivals) +importFrom(simmer,get_mon_resources) +importFrom(simmer,simmer) +importFrom(simmer,timeout) +importFrom(simmer,trajectory) +importFrom(simmer,wrap) diff --git a/R/model.R b/R/model.R new file mode 100644 index 0000000..d68a6b7 --- /dev/null +++ b/R/model.R @@ -0,0 +1,45 @@ +#' Run simulation. +#' +#' @param run_number Integer representing index of current simulation run. +#' @param param Named list of model parameters. +#' @param set_seed Whether to set seed within the model function (which we +#' may not wish to do if being set elsewhere - such as done in runner()). +#' Default is TRUE. +#' +#' @importFrom simmer add_generator get_mon_arrivals get_mon_resources simmer +#' @importFrom simmer timeout trajectory wrap +#' +#' @return TBC +#' @export + +model <- function(run_number, param, set_seed = TRUE) { + + # Set random seed based on run number + if (set_seed) { + set.seed(run_number) + } + + # Create simmer environment + env <- simmer("simulation", verbose = TRUE) + + # Define the stroke patient trajectory + stroke_patient <- trajectory("stroke_patient_path") |> + timeout(1) + + # Add patient generator + env <- env |> + add_generator("stroke_patient", stroke_patient, function () { + rexp(n = 1L, rate = 1L / param[["asu_arrivals"]][["stroke"]]) + }) |> + simmer::run(20) |> + wrap() + + # Extract the monitored arrivals and resources information from the simmer + # environment object + result <- list( + arrivals = get_mon_arrivals(env, per_resource = TRUE, ongoing = TRUE), + resources = get_mon_resources(env) + ) + + return(result) +} diff --git a/man/create_parameters.Rd b/man/create_parameters.Rd index 9910314..587b046 100644 --- a/man/create_parameters.Rd +++ b/man/create_parameters.Rd @@ -11,11 +11,11 @@ create_parameters( rehab_los = create_rehab_los(), asu_routing = create_asu_routing(), rehab_routing = create_rehab_routing(), - warm_up_period = 365 * 3, - data_collection_period = 365 * 5, - number_of_runs = 150, + warm_up_period = 365L * 3L, + data_collection_period = 365L * 5L, + number_of_runs = 150L, scenario_name = NULL, - cores = 1, + cores = 1L, log_to_console = FALSE, log_to_file = FALSE, file_path = NULL diff --git a/man/create_rehab_routing.Rd b/man/create_rehab_routing.Rd index 53423e3..b2f5129 100644 --- a/man/create_rehab_routing.Rd +++ b/man/create_rehab_routing.Rd @@ -7,8 +7,8 @@ create_rehab_routing( stroke_esd = 0.4, stroke_other = 0.6, - tia_esd = 0, - tia_other = 1, + tia_esd = 0L, + tia_other = 1L, neuro_esd = 0.09, neuro_other = 0.91, other_esd = 0.13, diff --git a/man/model.Rd b/man/model.Rd new file mode 100644 index 0000000..401c42f --- /dev/null +++ b/man/model.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/model.R +\name{model} +\alias{model} +\title{Run simulation.} +\usage{ +model(run_number, param, set_seed = TRUE) +} +\arguments{ +\item{run_number}{Integer representing index of current simulation run.} + +\item{param}{Named list of model parameters.} + +\item{set_seed}{Whether to set seed within the model function (which we +may not wish to do if being set elsewhere - such as done in runner()). +Default is TRUE.} +} +\value{ +TBC +} +\description{ +Run simulation. +} diff --git a/renv.lock b/renv.lock index c060c2c..72f1aba 100644 --- a/renv.lock +++ b/renv.lock @@ -134,6 +134,16 @@ ], "Hash": "3f038e5ac7f41d4ac41ce658c85e3042" }, + "codetools": { + "Package": "codetools", + "Version": "0.2-20", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "61e097f35917d342622f21cdc79c256e" + }, "commonmark": { "Package": "commonmark", "Version": "1.9.2", @@ -988,6 +998,20 @@ ], "Hash": "011db3556755012e632ed99d083d7d75" }, + "simmer": { + "Package": "simmer", + "Version": "4.4.7", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "Rcpp", + "codetools", + "magrittr", + "utils" + ], + "Hash": "6e993f252a8a2a7bf19856c82af1414b" + }, "sourcetools": { "Package": "sourcetools", "Version": "0.1.7-1", diff --git a/rmarkdown/analysis.Rmd b/rmarkdown/analysis.Rmd index f197b03..4082293 100644 --- a/rmarkdown/analysis.Rmd +++ b/rmarkdown/analysis.Rmd @@ -12,5 +12,5 @@ library(simulation) ``` ```{r} -create_parameters() +model(run_number = 1L, param = create_parameters(), set_seed = TRUE) ``` From f4d0615b5fec9de23605310c01e5624215dd0cfd Mon Sep 17 00:00:00 2001 From: amyheather Date: Tue, 1 Jul 2025 11:18:41 +0100 Subject: [PATCH 05/13] feat(patients): created add_patient_generator() function which can be used to set up the exponential patient generation for each unit and patient type --- NAMESPACE | 2 + R/add_patient_generator.R | 35 ++++++++++++ R/model.R | 28 ++++++--- man/add_patient_generator.Rd | 34 +++++++++++ rmarkdown/analysis.Rmd | 7 ++- rmarkdown/analysis.md | 107 +++++++++++++++++++++++++++++++++++ 6 files changed, 203 insertions(+), 10 deletions(-) create mode 100644 R/add_patient_generator.R create mode 100644 man/add_patient_generator.Rd create mode 100644 rmarkdown/analysis.md diff --git a/NAMESPACE b/NAMESPACE index e0a0d4e..81f778d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,6 @@ # Generated by roxygen2: do not edit by hand +export(add_patient_generator) export(create_asu_arrivals) export(create_asu_los) export(create_asu_routing) @@ -15,3 +16,4 @@ importFrom(simmer,simmer) importFrom(simmer,timeout) importFrom(simmer,trajectory) importFrom(simmer,wrap) +importFrom(stats,rexp) diff --git a/R/add_patient_generator.R b/R/add_patient_generator.R new file mode 100644 index 0000000..b08e332 --- /dev/null +++ b/R/add_patient_generator.R @@ -0,0 +1,35 @@ +#' Add patient generator to Simmer environment. +#' +#' Creates a patient generator using an exponential inter-arrival distribution. +#' The generator name is automatically constructed as \{unit\}_\{patient_type\}. +#' +#' @param env Simmer environment object. The simulation environment where +#' generators will be added. +#' @param trajectory Simmer trajectory object. Defines patient journey logic +#' through the healthcare system. +#' @param unit Character string specifying the care unit. Must be either "asu" +#' (Acute Stroke Unit) or "rehab" (Rehabilitation Unit). Used to access correct +#' parameter set and name the generator. +#' @param patient_type Character string specifying patient category. Must be +#' one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate +#' parameter is used. +#' @param param Nested list containing simulation parameters. Must have +#' structure `param$_arrivals$` containing numeric +#' arrival intervals (e.g., `param$asu_arrivals$stroke = 10`). +#' +#' @importFrom simmer add_generator +#' @importFrom stats rexp +#' +#' @return The modified Simmer environment with the new patient generator added. +#' @export + +add_patient_generator <- function(env, trajectory, unit, patient_type, param) { + add_generator( + .env = env, + name_prefix = paste0(unit, "_", patient_type), + trajectory = trajectory, + distribution = function() { + rexp(1L, 1L / param[[paste0(unit, "_arrivals")]][[patient_type]]) + } + ) +} diff --git a/R/model.R b/R/model.R index d68a6b7..e83368f 100644 --- a/R/model.R +++ b/R/model.R @@ -6,8 +6,8 @@ #' may not wish to do if being set elsewhere - such as done in runner()). #' Default is TRUE. #' -#' @importFrom simmer add_generator get_mon_arrivals get_mon_resources simmer -#' @importFrom simmer timeout trajectory wrap +#' @importFrom simmer get_mon_arrivals get_mon_resources simmer timeout +#' @importFrom simmer trajectory wrap #' #' @return TBC #' @export @@ -23,15 +23,25 @@ model <- function(run_number, param, set_seed = TRUE) { env <- simmer("simulation", verbose = TRUE) # Define the stroke patient trajectory - stroke_patient <- trajectory("stroke_patient_path") |> - timeout(1) + patient <- trajectory("patient_path") |> + timeout(1L) - # Add patient generator + # Add ASU and rehab direct admission patient generators + for (unit in c("asu", "rehab")) { + for (patient_type in names(param[[paste0(unit, "_arrivals")]])) { + env <- add_patient_generator( + env = env, + trajectory = patient, + unit = unit, + patient_type = patient_type, + param = param + ) + } + } + + # Run the model env <- env |> - add_generator("stroke_patient", stroke_patient, function () { - rexp(n = 1L, rate = 1L / param[["asu_arrivals"]][["stroke"]]) - }) |> - simmer::run(20) |> + simmer::run(20L) |> wrap() # Extract the monitored arrivals and resources information from the simmer diff --git a/man/add_patient_generator.Rd b/man/add_patient_generator.Rd new file mode 100644 index 0000000..dea999f --- /dev/null +++ b/man/add_patient_generator.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/add_patient_generator.R +\name{add_patient_generator} +\alias{add_patient_generator} +\title{Add patient generator to Simmer environment.} +\usage{ +add_patient_generator(env, trajectory, unit, patient_type, param) +} +\arguments{ +\item{env}{Simmer environment object. The simulation environment where +generators will be added.} + +\item{trajectory}{Simmer trajectory object. Defines patient journey logic +through the healthcare system.} + +\item{unit}{Character string specifying the care unit. Must be either "asu" +(Acute Stroke Unit) or "rehab" (Rehabilitation Unit). Used to access correct +parameter set and name the generator.} + +\item{patient_type}{Character string specifying patient category. Must be +one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate +parameter is used.} + +\item{param}{Nested list containing simulation parameters. Must have +structure `param$_arrivals$` containing numeric +arrival intervals (e.g., `param$asu_arrivals$stroke = 10`).} +} +\value{ +The modified Simmer environment with the new patient generator added. +} +\description{ +Creates a patient generator using an exponential inter-arrival distribution. +The generator name is automatically constructed as \{unit\}_\{patient_type\}. +} diff --git a/rmarkdown/analysis.Rmd b/rmarkdown/analysis.Rmd index 4082293..6f19e03 100644 --- a/rmarkdown/analysis.Rmd +++ b/rmarkdown/analysis.Rmd @@ -1,6 +1,11 @@ --- title: "analysis" -output: html_document +author: "Amy Heather" +date: "`r Sys.Date()`" +output: + github_document: + toc: true + html_preview: false --- ```{r} diff --git a/rmarkdown/analysis.md b/rmarkdown/analysis.md new file mode 100644 index 0000000..6c79889 --- /dev/null +++ b/rmarkdown/analysis.md @@ -0,0 +1,107 @@ +analysis +================ +Amy Heather +2025-07-01 + +``` r +# Load the package from the local directory +devtools::load_all() +``` + + ## ℹ Loading simulation + +``` r +# Load the package +library(simulation) +``` + +``` r +model(run_number = 1L, param = create_parameters(), set_seed = TRUE) +``` + + ## 0 | source: asu_stroke | new: asu_stroke0 | 0.906218 + ## 0 | source: asu_tia | new: asu_tia0 | 10.9893 + ## 0 | source: asu_neuro | new: asu_neuro0 | 0.524544 + ## 0 | source: asu_other | new: asu_other0 | 0.447345 + ## 0 | source: rehab_stroke | new: rehab_stroke0 | 9.5063 + ## 0 | source: rehab_neuro | new: rehab_neuro0 | 91.7705 + ## 0 | source: rehab_other | new: rehab_other0 | 35.1655 + ## 0.447345 | arrival: asu_other0 | activity: Timeout | 1 + ## 0.447345 | source: asu_other | new: asu_other1 | 2.17433 + ## 0.524544 | arrival: asu_neuro0 | activity: Timeout | 1 + ## 0.524544 | source: asu_neuro | new: asu_neuro1 | 3.96819 + ## 0.906218 | arrival: asu_stroke0 | activity: Timeout | 1 + ## 0.906218 | source: asu_stroke | new: asu_stroke1 | 1.08267 + ## 1.08267 | arrival: asu_stroke1 | activity: Timeout | 1 + ## 1.08267 | source: asu_stroke | new: asu_stroke2 | 2.75156 + ## 2.17433 | arrival: asu_other1 | activity: Timeout | 1 + ## 2.17433 | source: asu_other | new: asu_other2 | 4.61283 + ## 2.75156 | arrival: asu_stroke2 | activity: Timeout | 1 + ## 2.75156 | source: asu_stroke | new: asu_stroke3 | 4.23668 + ## 3.96819 | arrival: asu_neuro1 | activity: Timeout | 1 + ## 3.96819 | source: asu_neuro | new: asu_neuro2 | 19.8944 + ## 4.23668 | arrival: asu_stroke3 | activity: Timeout | 1 + ## 4.23668 | source: asu_stroke | new: asu_stroke4 | 5.50213 + ## 4.61283 | arrival: asu_other2 | activity: Timeout | 1 + ## 4.61283 | source: asu_other | new: asu_other3 | 7.92561 + ## 5.50213 | arrival: asu_stroke4 | activity: Timeout | 1 + ## 5.50213 | source: asu_stroke | new: asu_stroke5 | 7.75337 + ## 7.75337 | arrival: asu_stroke5 | activity: Timeout | 1 + ## 7.75337 | source: asu_stroke | new: asu_stroke6 | 8.53907 + ## 7.92561 | arrival: asu_other3 | activity: Timeout | 1 + ## 7.92561 | source: asu_other | new: asu_other4 | 9.00379 + ## 8.53907 | arrival: asu_stroke6 | activity: Timeout | 1 + ## 8.53907 | source: asu_stroke | new: asu_stroke7 | 9.24525 + ## 9.00379 | arrival: asu_other4 | activity: Timeout | 1 + ## 9.00379 | source: asu_other | new: asu_other5 | 16.5702 + ## 9.24525 | arrival: asu_stroke7 | activity: Timeout | 1 + ## 9.24525 | source: asu_stroke | new: asu_stroke8 | 10.0155 + ## 9.5063 | arrival: rehab_stroke0 | activity: Timeout | 1 + ## 9.5063 | source: rehab_stroke | new: rehab_stroke1 | 15.9181 + ## 10.0155 | arrival: asu_stroke8 | activity: Timeout | 1 + ## 10.0155 | source: asu_stroke | new: asu_stroke9 | 10.6946 + ## 10.6946 | arrival: asu_stroke9 | activity: Timeout | 1 + ## 10.6946 | source: asu_stroke | new: asu_stroke10 | 10.8218 + ## 10.8218 | arrival: asu_stroke10 | activity: Timeout | 1 + ## 10.8218 | source: asu_stroke | new: asu_stroke11 | 10.8932 + ## 10.8932 | arrival: asu_stroke11 | activity: Timeout | 1 + ## 10.8932 | source: asu_stroke | new: asu_stroke12 | 11.5876 + ## 10.9893 | arrival: asu_tia0 | activity: Timeout | 1 + ## 10.9893 | source: asu_tia | new: asu_tia1 | 47.8074 + ## 11.5876 | arrival: asu_stroke12 | activity: Timeout | 1 + ## 11.5876 | source: asu_stroke | new: asu_stroke13 | 12.9956 + ## 12.9956 | arrival: asu_stroke13 | activity: Timeout | 1 + ## 12.9956 | source: asu_stroke | new: asu_stroke14 | 14.1918 + ## 14.1918 | arrival: asu_stroke14 | activity: Timeout | 1 + ## 14.1918 | source: asu_stroke | new: asu_stroke15 | 15.9141 + ## 15.9141 | arrival: asu_stroke15 | activity: Timeout | 1 + ## 15.9141 | source: asu_stroke | new: asu_stroke16 | 15.9588 + ## 15.9181 | arrival: rehab_stroke1 | activity: Timeout | 1 + ## 15.9181 | source: rehab_stroke | new: rehab_stroke2 | 22.9815 + ## 15.9588 | arrival: asu_stroke16 | activity: Timeout | 1 + ## 15.9588 | source: asu_stroke | new: asu_stroke17 | 17.5434 + ## 16.5702 | arrival: asu_other5 | activity: Timeout | 1 + ## 16.5702 | source: asu_other | new: asu_other6 | 17.2215 + ## 17.2215 | arrival: asu_other6 | activity: Timeout | 1 + ## 17.2215 | source: asu_other | new: asu_other7 | 20.4942 + ## 17.5434 | arrival: asu_stroke17 | activity: Timeout | 1 + ## 17.5434 | source: asu_stroke | new: asu_stroke18 | 17.9055 + ## 17.9055 | arrival: asu_stroke18 | activity: Timeout | 1 + ## 17.9055 | source: asu_stroke | new: asu_stroke19 | 18.7757 + ## 18.7757 | arrival: asu_stroke19 | activity: Timeout | 1 + ## 18.7757 | source: asu_stroke | new: asu_stroke20 | 19.6776 + ## 19.6776 | arrival: asu_stroke20 | activity: Timeout | 1 + ## 19.6776 | source: asu_stroke | new: asu_stroke21 | 19.9596 + ## 19.8944 | arrival: asu_neuro2 | activity: Timeout | 1 + ## 19.8944 | source: asu_neuro | new: asu_neuro3 | 23.7819 + ## 19.9596 | arrival: asu_stroke21 | activity: Timeout | 1 + ## 19.9596 | source: asu_stroke | new: asu_stroke22 | 21.1935 + + ## $arrivals + ## [1] name start_time end_time activity_time resource + ## <0 rows> (or 0-length row.names) + ## + ## $resources + ## [1] resource time server queue capacity queue_size system + ## [8] limit + ## <0 rows> (or 0-length row.names) From db9212cf12c94c691cf23bb63172324c1e037f23 Mon Sep 17 00:00:00 2001 From: amyheather Date: Tue, 1 Jul 2025 14:19:00 +0100 Subject: [PATCH 06/13] feat(model): add creation of ASU and rehab trajectories (create_asu/rehab_trajectory), with ASU sampling the routing destination (sample_routing) --- NAMESPACE | 5 + R/create_asu_trajectory.R | 22 +++++ R/create_rehab_trajectory.R | 19 ++++ R/model.R | 14 +-- R/parameters.R | 32 ++++++- R/sample_routing.R | 15 +++ man/create_asu_trajectory.Rd | 24 +++++ man/create_rehab_trajectory.Rd | 24 +++++ man/sample_routing.Rd | 20 ++++ rmarkdown/analysis.Rmd | 1 + rmarkdown/analysis.md | 167 ++++++++++++++++++++------------- 11 files changed, 267 insertions(+), 76 deletions(-) create mode 100644 R/create_asu_trajectory.R create mode 100644 R/create_rehab_trajectory.R create mode 100644 R/sample_routing.R create mode 100644 man/create_asu_trajectory.Rd create mode 100644 man/create_rehab_trajectory.Rd create mode 100644 man/sample_routing.Rd diff --git a/NAMESPACE b/NAMESPACE index 81f778d..34e3efa 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -4,14 +4,19 @@ export(add_patient_generator) export(create_asu_arrivals) export(create_asu_los) export(create_asu_routing) +export(create_asu_trajectory) export(create_parameters) export(create_rehab_arrivals) export(create_rehab_los) export(create_rehab_routing) +export(create_rehab_trajectory) export(model) +export(sample_routing) importFrom(simmer,add_generator) +importFrom(simmer,get_attribute) importFrom(simmer,get_mon_arrivals) importFrom(simmer,get_mon_resources) +importFrom(simmer,set_attribute) importFrom(simmer,simmer) importFrom(simmer,timeout) importFrom(simmer,trajectory) diff --git a/R/create_asu_trajectory.R b/R/create_asu_trajectory.R new file mode 100644 index 0000000..101981b --- /dev/null +++ b/R/create_asu_trajectory.R @@ -0,0 +1,22 @@ +#' Create ASU patient trajectory +#' +#' @param patient_type Character string specifying patient category. Must be +#' one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate +#' parameter is used. +#' @param param Nested list containing simulation parameters. Must have +#' structure `param$asu_routing$` containing the probability of +#' routing to each destination (e.g.`param$asu_routing_stroke$rehab = 0.24`). +#' +#' @importFrom simmer trajectory +#' +#' @return Simmer trajectory object. Defines patient journey logic through the +#' healthcare system. +#' @export + +create_asu_trajectory <- function(patient_type, param) { + trajectory(paste0("ASU_", patient_type, "_path")) |> + set_attribute("post_asu_destination", function(env) { + sample_routing(prob_list = param[["asu_routing"]][[patient_type]]) + }) |> + timeout(1L) +} diff --git a/R/create_rehab_trajectory.R b/R/create_rehab_trajectory.R new file mode 100644 index 0000000..8cb55fc --- /dev/null +++ b/R/create_rehab_trajectory.R @@ -0,0 +1,19 @@ +#' Create rehab patient trajectory +#' +#' @param patient_type Character string specifying patient category. Must be +#' one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate +#' parameter is used. +#' @param param Nested list containing simulation parameters. Must have +#' structure `param$asu_routing$` containing the probability of +#' routing to each destination (e.g.`param$asu_routing_stroke$rehab = 0.24`). +#' +#' @importFrom simmer trajectory +#' +#' @return Simmer trajectory object. Defines patient journey logic through the +#' healthcare system. +#' @export + +create_rehab_trajectory <- function(patient_type, param) { + trajectory(paste0("rehab_", patient_type, "_path")) |> + timeout(1L) +} diff --git a/R/model.R b/R/model.R index e83368f..760cbb1 100644 --- a/R/model.R +++ b/R/model.R @@ -6,8 +6,8 @@ #' may not wish to do if being set elsewhere - such as done in runner()). #' Default is TRUE. #' -#' @importFrom simmer get_mon_arrivals get_mon_resources simmer timeout -#' @importFrom simmer trajectory wrap +#' @importFrom simmer get_attribute get_mon_arrivals get_mon_resources +#' @importFrom simmer set_attribute simmer timeout wrap #' #' @return TBC #' @export @@ -22,16 +22,16 @@ model <- function(run_number, param, set_seed = TRUE) { # Create simmer environment env <- simmer("simulation", verbose = TRUE) - # Define the stroke patient trajectory - patient <- trajectory("patient_path") |> - timeout(1L) - # Add ASU and rehab direct admission patient generators for (unit in c("asu", "rehab")) { for (patient_type in names(param[[paste0(unit, "_arrivals")]])) { env <- add_patient_generator( env = env, - trajectory = patient, + # Get trajectory given unit and patient type + trajectory = ( + if (unit == "asu") create_asu_trajectory(patient_type, param) + else create_rehab_trajectory(patient_type, param) + ), unit = unit, patient_type = patient_type, param = param diff --git a/R/parameters.R b/R/parameters.R index 59d779b..9bc6dcd 100644 --- a/R/parameters.R +++ b/R/parameters.R @@ -68,7 +68,15 @@ create_asu_los <- function( neuro_mean = 4.0, neuro_sd = 5.0, other_mean = 3.8, other_sd = 5.2 ) { - return(as.list(environment())) + list( + stroke_noesd = list(mean = stroke_noesd_mean, sd = stroke_noesd_sd), + stroke_esd = list(mean = stroke_esd_mean, sd = stroke_esd_sd), + stroke_mortality = list(mean = stroke_mortality_mean, + sd = stroke_mortality_sd), + tia = list(mean = tia_mean, sd = tia_sd), + neuro = list(mean = neuro_mean, sd = neuro_sd), + other = list(mean = other_mean, sd = other_sd) + ) } #' Rehabilitation unit length of stay (LOS) distributions (days). @@ -96,7 +104,13 @@ create_rehab_los <- function( neuro_mean = 27.6, neuro_sd = 28.4, other_mean = 16.1, other_sd = 14.1 ) { - return(as.list(environment())) + list( + stroke_noesd = list(mean = stroke_noesd_mean, sd = stroke_noesd_sd), + stroke_esd = list(mean = stroke_esd_mean, sd = stroke_esd_sd), + tia = list(mean = tia_mean, sd = tia_sd), + neuro = list(mean = neuro_mean, sd = neuro_sd), + other = list(mean = other_mean, sd = other_sd) + ) } #' ASU routing probabilities. @@ -131,7 +145,12 @@ create_asu_routing <- function( neuro_rehab = 0.11, neuro_esd = 0.05, neuro_other = 0.84, other_rehab = 0.05, other_esd = 0.10, other_other = 0.85 ) { - return(as.list(environment())) + list( + stroke = list(rehab = stroke_rehab, esd = stroke_esd, other = stroke_other), + tia = list(rehab = tia_rehab, esd = tia_esd, other = tia_other), + neuro = list(rehab = neuro_rehab, esd = neuro_esd, other = neuro_other), + other = list(rehab = other_rehab, esd = other_esd, other = other_other) + ) } #' Rehabilitation unit routing probabilities. @@ -161,7 +180,12 @@ create_rehab_routing <- function( neuro_esd = 0.09, neuro_other = 0.91, other_esd = 0.13, other_other = 0.88 ) { - return(as.list(environment())) + list( + stroke = list(esd = stroke_esd, other = stroke_other), + tia = list(esd = tia_esd, other = tia_other), + neuro = list(esd = neuro_esd, other = neuro_other), + other = list(esd = other_esd, other = other_other) + ) } #' Generate complete parameter list for simulation. diff --git a/R/sample_routing.R b/R/sample_routing.R new file mode 100644 index 0000000..84ac3ab --- /dev/null +++ b/R/sample_routing.R @@ -0,0 +1,15 @@ +#' Sample a destination based on probabilities +#' +#' Randomly selects a destination from a list, where each destination has an +#' associated probability. +#' +#' @param prob_list Named list. The names are destination labels (character), +#' and the values are their corresponding probabilities (numeric, non-negative, +#' sum to 1). +#' +#' @return A character string. The name of the selected destination. +#' @export + +sample_routing <- function(prob_list) { + sample(seq_along(prob_list), size = 1L, prob = unlist(prob_list)) +} diff --git a/man/create_asu_trajectory.Rd b/man/create_asu_trajectory.Rd new file mode 100644 index 0000000..aadb094 --- /dev/null +++ b/man/create_asu_trajectory.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/create_asu_trajectory.R +\name{create_asu_trajectory} +\alias{create_asu_trajectory} +\title{Create ASU patient trajectory} +\usage{ +create_asu_trajectory(patient_type, param) +} +\arguments{ +\item{patient_type}{Character string specifying patient category. Must be +one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate +parameter is used.} + +\item{param}{Nested list containing simulation parameters. Must have +structure `param$asu_routing$` containing the probability of +routing to each destination (e.g.`param$asu_routing_stroke$rehab = 0.24`).} +} +\value{ +Simmer trajectory object. Defines patient journey logic through the +healthcare system. +} +\description{ +Create ASU patient trajectory +} diff --git a/man/create_rehab_trajectory.Rd b/man/create_rehab_trajectory.Rd new file mode 100644 index 0000000..e52ac46 --- /dev/null +++ b/man/create_rehab_trajectory.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/create_rehab_trajectory.R +\name{create_rehab_trajectory} +\alias{create_rehab_trajectory} +\title{Create rehab patient trajectory} +\usage{ +create_rehab_trajectory(patient_type, param) +} +\arguments{ +\item{patient_type}{Character string specifying patient category. Must be +one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate +parameter is used.} + +\item{param}{Nested list containing simulation parameters. Must have +structure `param$asu_routing$` containing the probability of +routing to each destination (e.g.`param$asu_routing_stroke$rehab = 0.24`).} +} +\value{ +Simmer trajectory object. Defines patient journey logic through the +healthcare system. +} +\description{ +Create rehab patient trajectory +} diff --git a/man/sample_routing.Rd b/man/sample_routing.Rd new file mode 100644 index 0000000..c85ada7 --- /dev/null +++ b/man/sample_routing.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/sample_routing.R +\name{sample_routing} +\alias{sample_routing} +\title{Sample a destination based on probabilities} +\usage{ +sample_routing(prob_list) +} +\arguments{ +\item{prob_list}{Named list. The names are destination labels (character), +and the values are their corresponding probabilities (numeric, non-negative, +sum to 1).} +} +\value{ +A character string. The name of the selected destination. +} +\description{ +Randomly selects a destination from a list, where each destination has an +associated probability. +} diff --git a/rmarkdown/analysis.Rmd b/rmarkdown/analysis.Rmd index 6f19e03..87d39d1 100644 --- a/rmarkdown/analysis.Rmd +++ b/rmarkdown/analysis.Rmd @@ -16,6 +16,7 @@ devtools::load_all() library(simulation) ``` + ```{r} model(run_number = 1L, param = create_parameters(), set_seed = TRUE) ``` diff --git a/rmarkdown/analysis.md b/rmarkdown/analysis.md index 6c79889..ff718c4 100644 --- a/rmarkdown/analysis.md +++ b/rmarkdown/analysis.md @@ -26,76 +26,113 @@ model(run_number = 1L, param = create_parameters(), set_seed = TRUE) ## 0 | source: rehab_stroke | new: rehab_stroke0 | 9.5063 ## 0 | source: rehab_neuro | new: rehab_neuro0 | 91.7705 ## 0 | source: rehab_other | new: rehab_other0 | 35.1655 + ## 0.447345 | arrival: asu_other0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 0.447345 | source: asu_other | new: asu_other1 | 3.50836 ## 0.447345 | arrival: asu_other0 | activity: Timeout | 1 - ## 0.447345 | source: asu_other | new: asu_other1 | 2.17433 + ## 0.524544 | arrival: asu_neuro0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 0.524544 | source: asu_neuro | new: asu_neuro1 | 5.82851 ## 0.524544 | arrival: asu_neuro0 | activity: Timeout | 1 - ## 0.524544 | source: asu_neuro | new: asu_neuro1 | 3.96819 + ## 0.906218 | arrival: asu_stroke0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 0.906218 | source: asu_stroke | new: asu_stroke1 | 2.39134 ## 0.906218 | arrival: asu_stroke0 | activity: Timeout | 1 - ## 0.906218 | source: asu_stroke | new: asu_stroke1 | 1.08267 - ## 1.08267 | arrival: asu_stroke1 | activity: Timeout | 1 - ## 1.08267 | source: asu_stroke | new: asu_stroke2 | 2.75156 - ## 2.17433 | arrival: asu_other1 | activity: Timeout | 1 - ## 2.17433 | source: asu_other | new: asu_other2 | 4.61283 - ## 2.75156 | arrival: asu_stroke2 | activity: Timeout | 1 - ## 2.75156 | source: asu_stroke | new: asu_stroke3 | 4.23668 - ## 3.96819 | arrival: asu_neuro1 | activity: Timeout | 1 - ## 3.96819 | source: asu_neuro | new: asu_neuro2 | 19.8944 - ## 4.23668 | arrival: asu_stroke3 | activity: Timeout | 1 - ## 4.23668 | source: asu_stroke | new: asu_stroke4 | 5.50213 - ## 4.61283 | arrival: asu_other2 | activity: Timeout | 1 - ## 4.61283 | source: asu_other | new: asu_other3 | 7.92561 - ## 5.50213 | arrival: asu_stroke4 | activity: Timeout | 1 - ## 5.50213 | source: asu_stroke | new: asu_stroke5 | 7.75337 - ## 7.75337 | arrival: asu_stroke5 | activity: Timeout | 1 - ## 7.75337 | source: asu_stroke | new: asu_stroke6 | 8.53907 - ## 7.92561 | arrival: asu_other3 | activity: Timeout | 1 - ## 7.92561 | source: asu_other | new: asu_other4 | 9.00379 - ## 8.53907 | arrival: asu_stroke6 | activity: Timeout | 1 - ## 8.53907 | source: asu_stroke | new: asu_stroke7 | 9.24525 - ## 9.00379 | arrival: asu_other4 | activity: Timeout | 1 - ## 9.00379 | source: asu_other | new: asu_other5 | 16.5702 - ## 9.24525 | arrival: asu_stroke7 | activity: Timeout | 1 - ## 9.24525 | source: asu_stroke | new: asu_stroke8 | 10.0155 + ## 2.39134 | arrival: asu_stroke1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 2.39134 | source: asu_stroke | new: asu_stroke2 | 3.85858 + ## 2.39134 | arrival: asu_stroke1 | activity: Timeout | 1 + ## 3.50836 | arrival: asu_other1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 3.50836 | source: asu_other | new: asu_other2 | 6.8829 + ## 3.50836 | arrival: asu_other1 | activity: Timeout | 1 + ## 3.85858 | arrival: asu_stroke2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 3.85858 | source: asu_stroke | new: asu_stroke3 | 4.09754 + ## 3.85858 | arrival: asu_stroke2 | activity: Timeout | 1 + ## 4.09754 | arrival: asu_stroke3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 4.09754 | source: asu_stroke | new: asu_stroke4 | 6.34878 + ## 4.09754 | arrival: asu_stroke3 | activity: Timeout | 1 + ## 5.82851 | arrival: asu_neuro1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 5.82851 | source: asu_neuro | new: asu_neuro2 | 7.04147 + ## 5.82851 | arrival: asu_neuro1 | activity: Timeout | 1 + ## 6.34878 | arrival: asu_stroke4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 6.34878 | source: asu_stroke | new: asu_stroke5 | 9.1862 + ## 6.34878 | arrival: asu_stroke4 | activity: Timeout | 1 + ## 6.8829 | arrival: asu_other2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 6.8829 | source: asu_other | new: asu_other3 | 7.82408 + ## 6.8829 | arrival: asu_other2 | activity: Timeout | 1 + ## 7.04147 | arrival: asu_neuro2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 7.04147 | source: asu_neuro | new: asu_neuro3 | 7.42333 + ## 7.04147 | arrival: asu_neuro2 | activity: Timeout | 1 + ## 7.42333 | arrival: asu_neuro3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 7.42333 | source: asu_neuro | new: asu_neuro4 | 9.50669 + ## 7.42333 | arrival: asu_neuro3 | activity: Timeout | 1 + ## 7.82408 | arrival: asu_other3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 7.82408 | source: asu_other | new: asu_other4 | 11.5787 + ## 7.82408 | arrival: asu_other3 | activity: Timeout | 1 + ## 9.1862 | arrival: asu_stroke5 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 9.1862 | source: asu_stroke | new: asu_stroke6 | 9.38982 + ## 9.1862 | arrival: asu_stroke5 | activity: Timeout | 1 + ## 9.38982 | arrival: asu_stroke6 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 9.38982 | source: asu_stroke | new: asu_stroke7 | 12.5949 + ## 9.38982 | arrival: asu_stroke6 | activity: Timeout | 1 ## 9.5063 | arrival: rehab_stroke0 | activity: Timeout | 1 - ## 9.5063 | source: rehab_stroke | new: rehab_stroke1 | 15.9181 - ## 10.0155 | arrival: asu_stroke8 | activity: Timeout | 1 - ## 10.0155 | source: asu_stroke | new: asu_stroke9 | 10.6946 - ## 10.6946 | arrival: asu_stroke9 | activity: Timeout | 1 - ## 10.6946 | source: asu_stroke | new: asu_stroke10 | 10.8218 - ## 10.8218 | arrival: asu_stroke10 | activity: Timeout | 1 - ## 10.8218 | source: asu_stroke | new: asu_stroke11 | 10.8932 - ## 10.8932 | arrival: asu_stroke11 | activity: Timeout | 1 - ## 10.8932 | source: asu_stroke | new: asu_stroke12 | 11.5876 + ## 9.5063 | source: rehab_stroke | new: rehab_stroke1 | 30.3958 + ## 9.50669 | arrival: asu_neuro4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 9.50669 | source: asu_neuro | new: asu_neuro5 | 10.6731 + ## 9.50669 | arrival: asu_neuro4 | activity: Timeout | 1 + ## 10.6731 | arrival: asu_neuro5 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 10.6731 | source: asu_neuro | new: asu_neuro6 | 11.4058 + ## 10.6731 | arrival: asu_neuro5 | activity: Timeout | 1 + ## 10.9893 | arrival: asu_tia0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 10.9893 | source: asu_tia | new: asu_tia1 | 13.7955 ## 10.9893 | arrival: asu_tia0 | activity: Timeout | 1 - ## 10.9893 | source: asu_tia | new: asu_tia1 | 47.8074 - ## 11.5876 | arrival: asu_stroke12 | activity: Timeout | 1 - ## 11.5876 | source: asu_stroke | new: asu_stroke13 | 12.9956 - ## 12.9956 | arrival: asu_stroke13 | activity: Timeout | 1 - ## 12.9956 | source: asu_stroke | new: asu_stroke14 | 14.1918 - ## 14.1918 | arrival: asu_stroke14 | activity: Timeout | 1 - ## 14.1918 | source: asu_stroke | new: asu_stroke15 | 15.9141 - ## 15.9141 | arrival: asu_stroke15 | activity: Timeout | 1 - ## 15.9141 | source: asu_stroke | new: asu_stroke16 | 15.9588 - ## 15.9181 | arrival: rehab_stroke1 | activity: Timeout | 1 - ## 15.9181 | source: rehab_stroke | new: rehab_stroke2 | 22.9815 - ## 15.9588 | arrival: asu_stroke16 | activity: Timeout | 1 - ## 15.9588 | source: asu_stroke | new: asu_stroke17 | 17.5434 - ## 16.5702 | arrival: asu_other5 | activity: Timeout | 1 - ## 16.5702 | source: asu_other | new: asu_other6 | 17.2215 - ## 17.2215 | arrival: asu_other6 | activity: Timeout | 1 - ## 17.2215 | source: asu_other | new: asu_other7 | 20.4942 - ## 17.5434 | arrival: asu_stroke17 | activity: Timeout | 1 - ## 17.5434 | source: asu_stroke | new: asu_stroke18 | 17.9055 - ## 17.9055 | arrival: asu_stroke18 | activity: Timeout | 1 - ## 17.9055 | source: asu_stroke | new: asu_stroke19 | 18.7757 - ## 18.7757 | arrival: asu_stroke19 | activity: Timeout | 1 - ## 18.7757 | source: asu_stroke | new: asu_stroke20 | 19.6776 - ## 19.6776 | arrival: asu_stroke20 | activity: Timeout | 1 - ## 19.6776 | source: asu_stroke | new: asu_stroke21 | 19.9596 - ## 19.8944 | arrival: asu_neuro2 | activity: Timeout | 1 - ## 19.8944 | source: asu_neuro | new: asu_neuro3 | 23.7819 - ## 19.9596 | arrival: asu_stroke21 | activity: Timeout | 1 - ## 19.9596 | source: asu_stroke | new: asu_stroke22 | 21.1935 + ## 11.4058 | arrival: asu_neuro6 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 11.4058 | source: asu_neuro | new: asu_neuro7 | 14.1113 + ## 11.4058 | arrival: asu_neuro6 | activity: Timeout | 1 + ## 11.5787 | arrival: asu_other4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 11.5787 | source: asu_other | new: asu_other5 | 14.9369 + ## 11.5787 | arrival: asu_other4 | activity: Timeout | 1 + ## 12.5949 | arrival: asu_stroke7 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 12.5949 | source: asu_stroke | new: asu_stroke8 | 13.8908 + ## 12.5949 | arrival: asu_stroke7 | activity: Timeout | 1 + ## 13.7955 | arrival: asu_tia1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 13.7955 | source: asu_tia | new: asu_tia2 | 25.8135 + ## 13.7955 | arrival: asu_tia1 | activity: Timeout | 1 + ## 13.8908 | arrival: asu_stroke8 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 13.8908 | source: asu_stroke | new: asu_stroke9 | 14.5563 + ## 13.8908 | arrival: asu_stroke8 | activity: Timeout | 1 + ## 14.1113 | arrival: asu_neuro7 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 14.1113 | source: asu_neuro | new: asu_neuro8 | 17.6048 + ## 14.1113 | arrival: asu_neuro7 | activity: Timeout | 1 + ## 14.5563 | arrival: asu_stroke9 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 14.5563 | source: asu_stroke | new: asu_stroke10 | 15.1733 + ## 14.5563 | arrival: asu_stroke9 | activity: Timeout | 1 + ## 14.9369 | arrival: asu_other5 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 14.9369 | source: asu_other | new: asu_other6 | 16.2881 + ## 14.9369 | arrival: asu_other5 | activity: Timeout | 1 + ## 15.1733 | arrival: asu_stroke10 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 15.1733 | source: asu_stroke | new: asu_stroke11 | 16.8859 + ## 15.1733 | arrival: asu_stroke10 | activity: Timeout | 1 + ## 16.2881 | arrival: asu_other6 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 16.2881 | source: asu_other | new: asu_other7 | 18.0158 + ## 16.2881 | arrival: asu_other6 | activity: Timeout | 1 + ## 16.8859 | arrival: asu_stroke11 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 16.8859 | source: asu_stroke | new: asu_stroke12 | 18.4861 + ## 16.8859 | arrival: asu_stroke11 | activity: Timeout | 1 + ## 17.6048 | arrival: asu_neuro8 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 17.6048 | source: asu_neuro | new: asu_neuro9 | 18.3603 + ## 17.6048 | arrival: asu_neuro8 | activity: Timeout | 1 + ## 18.0158 | arrival: asu_other7 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 18.0158 | source: asu_other | new: asu_other8 | 21.5547 + ## 18.0158 | arrival: asu_other7 | activity: Timeout | 1 + ## 18.3603 | arrival: asu_neuro9 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 18.3603 | source: asu_neuro | new: asu_neuro10 | 18.6831 + ## 18.3603 | arrival: asu_neuro9 | activity: Timeout | 1 + ## 18.4861 | arrival: asu_stroke12 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 18.4861 | source: asu_stroke | new: asu_stroke13 | 18.9841 + ## 18.4861 | arrival: asu_stroke12 | activity: Timeout | 1 + ## 18.6831 | arrival: asu_neuro10 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 18.6831 | source: asu_neuro | new: asu_neuro11 | 22.7153 + ## 18.6831 | arrival: asu_neuro10 | activity: Timeout | 1 + ## 18.9841 | arrival: asu_stroke13 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 18.9841 | source: asu_stroke | new: asu_stroke14 | 20.8705 + ## 18.9841 | arrival: asu_stroke13 | activity: Timeout | 1 ## $arrivals ## [1] name start_time end_time activity_time resource From 528173cf5460e9cfa821f8b639ce222abba27350 Mon Sep 17 00:00:00 2001 From: amyheather Date: Tue, 1 Jul 2025 14:23:26 +0100 Subject: [PATCH 07/13] chore(docstrings): corrections to the create_..._trajectory and sample_routing docstrings --- R/create_asu_trajectory.R | 2 +- R/create_rehab_trajectory.R | 4 ++-- R/sample_routing.R | 5 +++-- man/create_asu_trajectory.Rd | 2 +- man/create_rehab_trajectory.Rd | 4 ++-- man/sample_routing.Rd | 5 +++-- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/R/create_asu_trajectory.R b/R/create_asu_trajectory.R index 101981b..7a72d2a 100644 --- a/R/create_asu_trajectory.R +++ b/R/create_asu_trajectory.R @@ -5,7 +5,7 @@ #' parameter is used. #' @param param Nested list containing simulation parameters. Must have #' structure `param$asu_routing$` containing the probability of -#' routing to each destination (e.g.`param$asu_routing_stroke$rehab = 0.24`). +#' routing to each destination (e.g.`param$asu_routing$stroke$rehab = 0.24`). #' #' @importFrom simmer trajectory #' diff --git a/R/create_rehab_trajectory.R b/R/create_rehab_trajectory.R index 8cb55fc..1225051 100644 --- a/R/create_rehab_trajectory.R +++ b/R/create_rehab_trajectory.R @@ -4,8 +4,8 @@ #' one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate #' parameter is used. #' @param param Nested list containing simulation parameters. Must have -#' structure `param$asu_routing$` containing the probability of -#' routing to each destination (e.g.`param$asu_routing_stroke$rehab = 0.24`). +#' structure `param$rehab_routing$` containing the probability of +#' routing to each destination (e.g.`param$rehab_routing$stroke$esd = 0.40`). #' #' @importFrom simmer trajectory #' diff --git a/R/sample_routing.R b/R/sample_routing.R index 84ac3ab..e06a528 100644 --- a/R/sample_routing.R +++ b/R/sample_routing.R @@ -1,13 +1,14 @@ #' Sample a destination based on probabilities #' #' Randomly selects a destination from a list, where each destination has an -#' associated probability. +#' associated probability. The destination is returned as a numeric index, as +#' `simmer::set_attribute()` requires a numeric or function. #' #' @param prob_list Named list. The names are destination labels (character), #' and the values are their corresponding probabilities (numeric, non-negative, #' sum to 1). #' -#' @return A character string. The name of the selected destination. +#' @return An integer. The index of the selected destination within `prob_list`. #' @export sample_routing <- function(prob_list) { diff --git a/man/create_asu_trajectory.Rd b/man/create_asu_trajectory.Rd index aadb094..2848a05 100644 --- a/man/create_asu_trajectory.Rd +++ b/man/create_asu_trajectory.Rd @@ -13,7 +13,7 @@ parameter is used.} \item{param}{Nested list containing simulation parameters. Must have structure `param$asu_routing$` containing the probability of -routing to each destination (e.g.`param$asu_routing_stroke$rehab = 0.24`).} +routing to each destination (e.g.`param$asu_routing$stroke$rehab = 0.24`).} } \value{ Simmer trajectory object. Defines patient journey logic through the diff --git a/man/create_rehab_trajectory.Rd b/man/create_rehab_trajectory.Rd index e52ac46..17dd1c4 100644 --- a/man/create_rehab_trajectory.Rd +++ b/man/create_rehab_trajectory.Rd @@ -12,8 +12,8 @@ one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate parameter is used.} \item{param}{Nested list containing simulation parameters. Must have -structure `param$asu_routing$` containing the probability of -routing to each destination (e.g.`param$asu_routing_stroke$rehab = 0.24`).} +structure `param$rehab_routing$` containing the probability of +routing to each destination (e.g.`param$rehab_routing$stroke$esd = 0.40`).} } \value{ Simmer trajectory object. Defines patient journey logic through the diff --git a/man/sample_routing.Rd b/man/sample_routing.Rd index c85ada7..7e5ae76 100644 --- a/man/sample_routing.Rd +++ b/man/sample_routing.Rd @@ -12,9 +12,10 @@ and the values are their corresponding probabilities (numeric, non-negative, sum to 1).} } \value{ -A character string. The name of the selected destination. +An integer. The index of the selected destination within `prob_list`. } \description{ Randomly selects a destination from a list, where each destination has an -associated probability. +associated probability. The destination is returned as a numeric index, as +`simmer::set_attribute()` requires a numeric or function. } From ead2f90852e0ede36a98efbb7b868154db710444 Mon Sep 17 00:00:00 2001 From: amyheather Date: Tue, 1 Jul 2025 15:36:26 +0100 Subject: [PATCH 08/13] chore(docstrings): change from `` to \code{} in docstrings, and add full stops --- R/add_patient_generator.R | 4 ++-- R/create_rehab_trajectory.R | 7 ++++--- R/model.R | 23 +++++++++++++++++------ R/sample_routing.R | 7 ++++--- man/add_patient_generator.Rd | 4 ++-- man/create_rehab_trajectory.Rd | 9 +++++---- man/model.Rd | 2 +- man/sample_routing.Rd | 7 ++++--- 8 files changed, 39 insertions(+), 24 deletions(-) diff --git a/R/add_patient_generator.R b/R/add_patient_generator.R index b08e332..9ee4295 100644 --- a/R/add_patient_generator.R +++ b/R/add_patient_generator.R @@ -14,8 +14,8 @@ #' one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate #' parameter is used. #' @param param Nested list containing simulation parameters. Must have -#' structure `param$_arrivals$` containing numeric -#' arrival intervals (e.g., `param$asu_arrivals$stroke = 10`). +#' structure \code{param$_arrivals$} containing numeric +#' arrival intervals (e.g., \code{param$asu_arrivals$stroke = 10}). #' #' @importFrom simmer add_generator #' @importFrom stats rexp diff --git a/R/create_rehab_trajectory.R b/R/create_rehab_trajectory.R index 1225051..f687f59 100644 --- a/R/create_rehab_trajectory.R +++ b/R/create_rehab_trajectory.R @@ -1,11 +1,12 @@ -#' Create rehab patient trajectory +#' Create rehab patient trajectory. #' #' @param patient_type Character string specifying patient category. Must be #' one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate #' parameter is used. #' @param param Nested list containing simulation parameters. Must have -#' structure `param$rehab_routing$` containing the probability of -#' routing to each destination (e.g.`param$rehab_routing$stroke$esd = 0.40`). +#' structure \code{param$rehab_routing$} containing the +#' probability of routing to each destination (e.g. +#' \code{param$rehab_routing$stroke$esd = 0.40}). #' #' @importFrom simmer trajectory #' diff --git a/R/model.R b/R/model.R index 760cbb1..6cb4be0 100644 --- a/R/model.R +++ b/R/model.R @@ -3,7 +3,7 @@ #' @param run_number Integer representing index of current simulation run. #' @param param Named list of model parameters. #' @param set_seed Whether to set seed within the model function (which we -#' may not wish to do if being set elsewhere - such as done in runner()). +#' may not wish to do if being set elsewhere - such as done in \code{runner()}). #' Default is TRUE. #' #' @importFrom simmer get_attribute get_mon_arrivals get_mon_resources @@ -19,19 +19,30 @@ model <- function(run_number, param, set_seed = TRUE) { set.seed(run_number) } + # Transform LOS parameters to lognormal scale + param[["asu_los_lnorm"]] <- transform_to_lnorm(param[["asu_los"]]) + param[["rehab_los_lnorm"]] <- transform_to_lnorm(param[["rehab_los"]]) + # Create simmer environment env <- simmer("simulation", verbose = TRUE) # Add ASU and rehab direct admission patient generators for (unit in c("asu", "rehab")) { for (patient_type in names(param[[paste0(unit, "_arrivals")]])) { + + # Create patient trajectory + traj <- if (unit == "asu") { + create_asu_trajectory( + env = env, patient_type = patient_type, param = param + ) + } else { + create_rehab_trajectory(patient_type, param) + } + + # Add patient generator using the created trajectory env <- add_patient_generator( env = env, - # Get trajectory given unit and patient type - trajectory = ( - if (unit == "asu") create_asu_trajectory(patient_type, param) - else create_rehab_trajectory(patient_type, param) - ), + trajectory = traj, unit = unit, patient_type = patient_type, param = param diff --git a/R/sample_routing.R b/R/sample_routing.R index e06a528..a0359d5 100644 --- a/R/sample_routing.R +++ b/R/sample_routing.R @@ -1,14 +1,15 @@ -#' Sample a destination based on probabilities +#' Sample a destination based on probabilities. #' #' Randomly selects a destination from a list, where each destination has an #' associated probability. The destination is returned as a numeric index, as -#' `simmer::set_attribute()` requires a numeric or function. +#' \code{simmer::set_attribute()} requires a numeric or function. #' #' @param prob_list Named list. The names are destination labels (character), #' and the values are their corresponding probabilities (numeric, non-negative, #' sum to 1). #' -#' @return An integer. The index of the selected destination within `prob_list`. +#' @return An integer. The index of the selected destination within +#' \code{prob_list}. #' @export sample_routing <- function(prob_list) { diff --git a/man/add_patient_generator.Rd b/man/add_patient_generator.Rd index dea999f..4cbcc10 100644 --- a/man/add_patient_generator.Rd +++ b/man/add_patient_generator.Rd @@ -22,8 +22,8 @@ one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate parameter is used.} \item{param}{Nested list containing simulation parameters. Must have -structure `param$_arrivals$` containing numeric -arrival intervals (e.g., `param$asu_arrivals$stroke = 10`).} +structure \code{param$_arrivals$} containing numeric +arrival intervals (e.g., \code{param$asu_arrivals$stroke = 10}).} } \value{ The modified Simmer environment with the new patient generator added. diff --git a/man/create_rehab_trajectory.Rd b/man/create_rehab_trajectory.Rd index 17dd1c4..9d5de11 100644 --- a/man/create_rehab_trajectory.Rd +++ b/man/create_rehab_trajectory.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/create_rehab_trajectory.R \name{create_rehab_trajectory} \alias{create_rehab_trajectory} -\title{Create rehab patient trajectory} +\title{Create rehab patient trajectory.} \usage{ create_rehab_trajectory(patient_type, param) } @@ -12,13 +12,14 @@ one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate parameter is used.} \item{param}{Nested list containing simulation parameters. Must have -structure `param$rehab_routing$` containing the probability of -routing to each destination (e.g.`param$rehab_routing$stroke$esd = 0.40`).} +structure \code{param$rehab_routing$} containing the +probability of routing to each destination (e.g. +\code{param$rehab_routing$stroke$esd = 0.40}).} } \value{ Simmer trajectory object. Defines patient journey logic through the healthcare system. } \description{ -Create rehab patient trajectory +Create rehab patient trajectory. } diff --git a/man/model.Rd b/man/model.Rd index 401c42f..69476e7 100644 --- a/man/model.Rd +++ b/man/model.Rd @@ -12,7 +12,7 @@ model(run_number, param, set_seed = TRUE) \item{param}{Named list of model parameters.} \item{set_seed}{Whether to set seed within the model function (which we -may not wish to do if being set elsewhere - such as done in runner()). +may not wish to do if being set elsewhere - such as done in \code{runner()}). Default is TRUE.} } \value{ diff --git a/man/sample_routing.Rd b/man/sample_routing.Rd index 7e5ae76..a789a7b 100644 --- a/man/sample_routing.Rd +++ b/man/sample_routing.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/sample_routing.R \name{sample_routing} \alias{sample_routing} -\title{Sample a destination based on probabilities} +\title{Sample a destination based on probabilities.} \usage{ sample_routing(prob_list) } @@ -12,10 +12,11 @@ and the values are their corresponding probabilities (numeric, non-negative, sum to 1).} } \value{ -An integer. The index of the selected destination within `prob_list`. +An integer. The index of the selected destination within +\code{prob_list}. } \description{ Randomly selects a destination from a list, where each destination has an associated probability. The destination is returned as a numeric index, as -`simmer::set_attribute()` requires a numeric or function. +\code{simmer::set_attribute()} requires a numeric or function. } From fa8931b3fc0b7926b558ae6d4776816ace1adc93 Mon Sep 17 00:00:00 2001 From: amyheather Date: Tue, 1 Jul 2025 15:38:26 +0100 Subject: [PATCH 09/13] feat(model): in ASU trajectory (create_asu_trajectory), add sampling of ASU LOS (transform_to_lnorm) --- NAMESPACE | 2 + R/create_asu_trajectory.R | 50 +++++++- R/transform_to_lnorm.R | 25 ++++ man/create_asu_trajectory.Rd | 15 ++- man/transform_to_lnorm.Rd | 24 ++++ rmarkdown/analysis.md | 218 +++++++++++++++++++---------------- 6 files changed, 223 insertions(+), 111 deletions(-) create mode 100644 R/transform_to_lnorm.R create mode 100644 man/transform_to_lnorm.Rd diff --git a/NAMESPACE b/NAMESPACE index 34e3efa..1888784 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -12,6 +12,7 @@ export(create_rehab_routing) export(create_rehab_trajectory) export(model) export(sample_routing) +export(transform_to_lnorm) importFrom(simmer,add_generator) importFrom(simmer,get_attribute) importFrom(simmer,get_mon_arrivals) @@ -22,3 +23,4 @@ importFrom(simmer,timeout) importFrom(simmer,trajectory) importFrom(simmer,wrap) importFrom(stats,rexp) +importFrom(stats,rlnorm) diff --git a/R/create_asu_trajectory.R b/R/create_asu_trajectory.R index 7a72d2a..e977355 100644 --- a/R/create_asu_trajectory.R +++ b/R/create_asu_trajectory.R @@ -1,22 +1,60 @@ -#' Create ASU patient trajectory +#' Create acute stroke unit (ASU) patient trajectory. #' +#' Represents patient stay in the ASU - samples their (1) destination after +#' the ASU, and (2) length of stay (LOS) on the ASU. +#' +#' @param env Simmer environment object. The simulation environment where +#' generators will be added. #' @param patient_type Character string specifying patient category. Must be #' one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate #' parameter is used. #' @param param Nested list containing simulation parameters. Must have -#' structure `param$asu_routing$` containing the probability of -#' routing to each destination (e.g.`param$asu_routing$stroke$rehab = 0.24`). +#' structure \code{param$asu_routing$} containing the probability +#' of routing to each destination (e.g. +#' \code{param$asu_routing$stroke$rehab = 0.24}). #' #' @importFrom simmer trajectory +#' @importFrom stats rlnorm #' #' @return Simmer trajectory object. Defines patient journey logic through the #' healthcare system. #' @export -create_asu_trajectory <- function(patient_type, param) { +create_asu_trajectory <- function(env, patient_type, param) { + + # Set up simmer trajectory object... trajectory(paste0("ASU_", patient_type, "_path")) |> - set_attribute("post_asu_destination", function(env) { + + # Sample destination after ASU (we do this immediately on arrival in the + # ASU, as the destination influences the length of stay) + set_attribute("post_asu_destination", function() { sample_routing(prob_list = param[["asu_routing"]][[patient_type]]) }) |> - timeout(1L) + + timeout(function() { + + # Retrieve attribute, and use to get post-ASU destination as a string + dest_index <- get_attribute(env, "post_asu_destination") + dest_names <- names(param[["asu_routing"]][[patient_type]]) + dest <- dest_names[dest_index] + + # Determine which LOS distribution to use + if (patient_type == "stroke") { + los_params <- switch( + dest, + "esd" = param[["asu_los_lnorm"]][["stroke_esd"]], + "rehab" = param[["asu_los_lnorm"]][["stroke_noesd"]], + param[["asu_los_lnorm"]][["stroke_mortality"]] # Default case + ) + } else { + los_params <- param[["asu_los_lnorm"]][[patient_type]] + } + + # Sample LOS from lognormal + rlnorm( + n = 1L, + meanlog = los_params[["meanlog"]], + sdlog = los_params[["sdlog"]] + ) + }) } diff --git a/R/transform_to_lnorm.R b/R/transform_to_lnorm.R new file mode 100644 index 0000000..af4ba6f --- /dev/null +++ b/R/transform_to_lnorm.R @@ -0,0 +1,25 @@ +#' Convert LOS mean/sd to lognormal parameters for all patient types. +#' +#' Given a named list of length of stay (LOS) distributions (each with +#' \code{mean} and \code{sd} on the original scale), this function returns a +#' new named list where each entry contains the corresponding \code{meanlog} +#' and \code{sdlog} parameters required by R's \code{rlnorm()} and related +#' functions. +#' +#' @param los_list Named list. Each element should itself be a list with +#' elements \code{mean} and \code{sd} (e.g., as produced by +#' \code{create_asu_los()} or \code{create_rehab_los()}). +#' +#' @return A named list of the same structure, but with elements \code{meanlog} +#' and \code{sdlog} for each patient type. +#' @export + +transform_to_lnorm <- function(los_list) { + lapply(los_list, function(x) { + variance <- x$sd^2 + sigma_sq <- log(variance / (x$mean^2) + 1) + sdlog <- sqrt(sigma_sq) + meanlog <- log(x$mean) - sigma_sq / 2 + list(meanlog = meanlog, sdlog = sdlog) + }) +} diff --git a/man/create_asu_trajectory.Rd b/man/create_asu_trajectory.Rd index 2848a05..045d3e4 100644 --- a/man/create_asu_trajectory.Rd +++ b/man/create_asu_trajectory.Rd @@ -2,23 +2,28 @@ % Please edit documentation in R/create_asu_trajectory.R \name{create_asu_trajectory} \alias{create_asu_trajectory} -\title{Create ASU patient trajectory} +\title{Create acute stroke unit (ASU) patient trajectory.} \usage{ -create_asu_trajectory(patient_type, param) +create_asu_trajectory(env, patient_type, param) } \arguments{ +\item{env}{Simmer environment object. The simulation environment where +generators will be added.} + \item{patient_type}{Character string specifying patient category. Must be one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate parameter is used.} \item{param}{Nested list containing simulation parameters. Must have -structure `param$asu_routing$` containing the probability of -routing to each destination (e.g.`param$asu_routing$stroke$rehab = 0.24`).} +structure \code{param$asu_routing$} containing the probability +of routing to each destination (e.g. +\code{param$asu_routing$stroke$rehab = 0.24}).} } \value{ Simmer trajectory object. Defines patient journey logic through the healthcare system. } \description{ -Create ASU patient trajectory +Represents patient stay in the ASU - samples their (1) destination after +the ASU, and (2) length of stay (LOS) on the ASU. } diff --git a/man/transform_to_lnorm.Rd b/man/transform_to_lnorm.Rd new file mode 100644 index 0000000..59d5929 --- /dev/null +++ b/man/transform_to_lnorm.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/transform_to_lnorm.R +\name{transform_to_lnorm} +\alias{transform_to_lnorm} +\title{Convert LOS mean/sd to lognormal parameters for all patient types.} +\usage{ +transform_to_lnorm(los_list) +} +\arguments{ +\item{los_list}{Named list. Each element should itself be a list with +elements \code{mean} and \code{sd} (e.g., as produced by +\code{create_asu_los()} or \code{create_rehab_los()}).} +} +\value{ +A named list of the same structure, but with elements \code{meanlog} +and \code{sdlog} for each patient type. +} +\description{ +Given a named list of length of stay (LOS) distributions (each with +\code{mean} and \code{sd} on the original scale), this function returns a +new named list where each entry contains the corresponding \code{meanlog} +and \code{sdlog} parameters required by R's \code{rlnorm()} and related +functions. +} diff --git a/rmarkdown/analysis.md b/rmarkdown/analysis.md index ff718c4..7c3a383 100644 --- a/rmarkdown/analysis.md +++ b/rmarkdown/analysis.md @@ -28,111 +28,129 @@ model(run_number = 1L, param = create_parameters(), set_seed = TRUE) ## 0 | source: rehab_other | new: rehab_other0 | 35.1655 ## 0.447345 | arrival: asu_other0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 ## 0.447345 | source: asu_other | new: asu_other1 | 3.50836 - ## 0.447345 | arrival: asu_other0 | activity: Timeout | 1 + ## 0.447345 | arrival: asu_other0 | activity: Timeout | function() ## 0.524544 | arrival: asu_neuro0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 0.524544 | source: asu_neuro | new: asu_neuro1 | 5.82851 - ## 0.524544 | arrival: asu_neuro0 | activity: Timeout | 1 + ## 0.524544 | source: asu_neuro | new: asu_neuro1 | 5.53119 + ## 0.524544 | arrival: asu_neuro0 | activity: Timeout | function() ## 0.906218 | arrival: asu_stroke0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 0.906218 | source: asu_stroke | new: asu_stroke1 | 2.39134 - ## 0.906218 | arrival: asu_stroke0 | activity: Timeout | 1 - ## 2.39134 | arrival: asu_stroke1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 2.39134 | source: asu_stroke | new: asu_stroke2 | 3.85858 - ## 2.39134 | arrival: asu_stroke1 | activity: Timeout | 1 + ## 0.906218 | source: asu_stroke | new: asu_stroke1 | 2.37346 + ## 0.906218 | arrival: asu_stroke0 | activity: Timeout | function() + ## 2.37346 | arrival: asu_stroke1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 2.37346 | source: asu_stroke | new: asu_stroke2 | 2.61241 + ## 2.37346 | arrival: asu_stroke1 | activity: Timeout | function() + ## 2.61241 | arrival: asu_stroke2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 2.61241 | source: asu_stroke | new: asu_stroke3 | 3.01674 + ## 2.61241 | arrival: asu_stroke2 | activity: Timeout | function() + ## 3.01674 | arrival: asu_stroke3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 3.01674 | source: asu_stroke | new: asu_stroke4 | 4.62263 + ## 3.01674 | arrival: asu_stroke3 | activity: Timeout | function() ## 3.50836 | arrival: asu_other1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 3.50836 | source: asu_other | new: asu_other2 | 6.8829 - ## 3.50836 | arrival: asu_other1 | activity: Timeout | 1 - ## 3.85858 | arrival: asu_stroke2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 3.85858 | source: asu_stroke | new: asu_stroke3 | 4.09754 - ## 3.85858 | arrival: asu_stroke2 | activity: Timeout | 1 - ## 4.09754 | arrival: asu_stroke3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 4.09754 | source: asu_stroke | new: asu_stroke4 | 6.34878 - ## 4.09754 | arrival: asu_stroke3 | activity: Timeout | 1 - ## 5.82851 | arrival: asu_neuro1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 5.82851 | source: asu_neuro | new: asu_neuro2 | 7.04147 - ## 5.82851 | arrival: asu_neuro1 | activity: Timeout | 1 - ## 6.34878 | arrival: asu_stroke4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 6.34878 | source: asu_stroke | new: asu_stroke5 | 9.1862 - ## 6.34878 | arrival: asu_stroke4 | activity: Timeout | 1 - ## 6.8829 | arrival: asu_other2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 6.8829 | source: asu_other | new: asu_other3 | 7.82408 - ## 6.8829 | arrival: asu_other2 | activity: Timeout | 1 - ## 7.04147 | arrival: asu_neuro2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 7.04147 | source: asu_neuro | new: asu_neuro3 | 7.42333 - ## 7.04147 | arrival: asu_neuro2 | activity: Timeout | 1 - ## 7.42333 | arrival: asu_neuro3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 7.42333 | source: asu_neuro | new: asu_neuro4 | 9.50669 - ## 7.42333 | arrival: asu_neuro3 | activity: Timeout | 1 - ## 7.82408 | arrival: asu_other3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 7.82408 | source: asu_other | new: asu_other4 | 11.5787 - ## 7.82408 | arrival: asu_other3 | activity: Timeout | 1 - ## 9.1862 | arrival: asu_stroke5 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 9.1862 | source: asu_stroke | new: asu_stroke6 | 9.38982 - ## 9.1862 | arrival: asu_stroke5 | activity: Timeout | 1 - ## 9.38982 | arrival: asu_stroke6 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 9.38982 | source: asu_stroke | new: asu_stroke7 | 12.5949 - ## 9.38982 | arrival: asu_stroke6 | activity: Timeout | 1 + ## 3.50836 | source: asu_other | new: asu_other2 | 3.84779 + ## 3.50836 | arrival: asu_other1 | activity: Timeout | function() + ## 3.84779 | arrival: asu_other2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 3.84779 | source: asu_other | new: asu_other3 | 7.60239 + ## 3.84779 | arrival: asu_other2 | activity: Timeout | function() + ## 4.62263 | arrival: asu_stroke4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 4.62263 | source: asu_stroke | new: asu_stroke5 | 6.34497 + ## 4.62263 | arrival: asu_stroke4 | activity: Timeout | function() + ## 5.53119 | arrival: asu_neuro1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 5.53119 | source: asu_neuro | new: asu_neuro2 | 6.26383 + ## 5.53119 | arrival: asu_neuro1 | activity: Timeout | function() + ## 6.26383 | arrival: asu_neuro2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 6.26383 | source: asu_neuro | new: asu_neuro3 | 8.96938 + ## 6.26383 | arrival: asu_neuro2 | activity: Timeout | function() + ## 6.34497 | arrival: asu_stroke5 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 6.34497 | source: asu_stroke | new: asu_stroke6 | 7.64083 + ## 6.34497 | arrival: asu_stroke5 | activity: Timeout | function() + ## 7.60239 | arrival: asu_other3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 7.60239 | source: asu_other | new: asu_other4 | 8.46742 + ## 7.60239 | arrival: asu_other3 | activity: Timeout | function() + ## 7.64083 | arrival: asu_stroke6 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 7.64083 | source: asu_stroke | new: asu_stroke7 | 9.19258 + ## 7.64083 | arrival: asu_stroke6 | activity: Timeout | function() + ## 8.46742 | arrival: asu_other4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 8.46742 | source: asu_other | new: asu_other5 | 9.81859 + ## 8.46742 | arrival: asu_other4 | activity: Timeout | function() + ## 8.96938 | arrival: asu_neuro3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 8.96938 | source: asu_neuro | new: asu_neuro4 | 14.1071 + ## 8.96938 | arrival: asu_neuro3 | activity: Timeout | function() + ## 9.19258 | arrival: asu_stroke7 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 9.19258 | source: asu_stroke | new: asu_stroke8 | 10.3655 + ## 9.19258 | arrival: asu_stroke7 | activity: Timeout | function() ## 9.5063 | arrival: rehab_stroke0 | activity: Timeout | 1 - ## 9.5063 | source: rehab_stroke | new: rehab_stroke1 | 30.3958 - ## 9.50669 | arrival: asu_neuro4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 9.50669 | source: asu_neuro | new: asu_neuro5 | 10.6731 - ## 9.50669 | arrival: asu_neuro4 | activity: Timeout | 1 - ## 10.6731 | arrival: asu_neuro5 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 10.6731 | source: asu_neuro | new: asu_neuro6 | 11.4058 - ## 10.6731 | arrival: asu_neuro5 | activity: Timeout | 1 + ## 9.5063 | source: rehab_stroke | new: rehab_stroke1 | 33.6157 + ## 9.81859 | arrival: asu_other5 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 9.81859 | source: asu_other | new: asu_other6 | 10.1055 + ## 9.81859 | arrival: asu_other5 | activity: Timeout | function() + ## 10.1055 | arrival: asu_other6 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 10.1055 | source: asu_other | new: asu_other7 | 10.8968 + ## 10.1055 | arrival: asu_other6 | activity: Timeout | function() + ## 10.3655 | arrival: asu_stroke8 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 10.3655 | source: asu_stroke | new: asu_stroke9 | 13.6419 + ## 10.3655 | arrival: asu_stroke8 | activity: Timeout | function() + ## 10.8968 | arrival: asu_other7 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 10.8968 | source: asu_other | new: asu_other8 | 13.4996 + ## 10.8968 | arrival: asu_other7 | activity: Timeout | function() ## 10.9893 | arrival: asu_tia0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 10.9893 | source: asu_tia | new: asu_tia1 | 13.7955 - ## 10.9893 | arrival: asu_tia0 | activity: Timeout | 1 - ## 11.4058 | arrival: asu_neuro6 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 11.4058 | source: asu_neuro | new: asu_neuro7 | 14.1113 - ## 11.4058 | arrival: asu_neuro6 | activity: Timeout | 1 - ## 11.5787 | arrival: asu_other4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 11.5787 | source: asu_other | new: asu_other5 | 14.9369 - ## 11.5787 | arrival: asu_other4 | activity: Timeout | 1 - ## 12.5949 | arrival: asu_stroke7 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 12.5949 | source: asu_stroke | new: asu_stroke8 | 13.8908 - ## 12.5949 | arrival: asu_stroke7 | activity: Timeout | 1 - ## 13.7955 | arrival: asu_tia1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 13.7955 | source: asu_tia | new: asu_tia2 | 25.8135 - ## 13.7955 | arrival: asu_tia1 | activity: Timeout | 1 - ## 13.8908 | arrival: asu_stroke8 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 13.8908 | source: asu_stroke | new: asu_stroke9 | 14.5563 - ## 13.8908 | arrival: asu_stroke8 | activity: Timeout | 1 - ## 14.1113 | arrival: asu_neuro7 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 14.1113 | source: asu_neuro | new: asu_neuro8 | 17.6048 - ## 14.1113 | arrival: asu_neuro7 | activity: Timeout | 1 - ## 14.5563 | arrival: asu_stroke9 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 14.5563 | source: asu_stroke | new: asu_stroke10 | 15.1733 - ## 14.5563 | arrival: asu_stroke9 | activity: Timeout | 1 - ## 14.9369 | arrival: asu_other5 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 14.9369 | source: asu_other | new: asu_other6 | 16.2881 - ## 14.9369 | arrival: asu_other5 | activity: Timeout | 1 - ## 15.1733 | arrival: asu_stroke10 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 15.1733 | source: asu_stroke | new: asu_stroke11 | 16.8859 - ## 15.1733 | arrival: asu_stroke10 | activity: Timeout | 1 - ## 16.2881 | arrival: asu_other6 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 16.2881 | source: asu_other | new: asu_other7 | 18.0158 - ## 16.2881 | arrival: asu_other6 | activity: Timeout | 1 - ## 16.8859 | arrival: asu_stroke11 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 16.8859 | source: asu_stroke | new: asu_stroke12 | 18.4861 - ## 16.8859 | arrival: asu_stroke11 | activity: Timeout | 1 - ## 17.6048 | arrival: asu_neuro8 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 17.6048 | source: asu_neuro | new: asu_neuro9 | 18.3603 - ## 17.6048 | arrival: asu_neuro8 | activity: Timeout | 1 - ## 18.0158 | arrival: asu_other7 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 18.0158 | source: asu_other | new: asu_other8 | 21.5547 - ## 18.0158 | arrival: asu_other7 | activity: Timeout | 1 - ## 18.3603 | arrival: asu_neuro9 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 18.3603 | source: asu_neuro | new: asu_neuro10 | 18.6831 - ## 18.3603 | arrival: asu_neuro9 | activity: Timeout | 1 - ## 18.4861 | arrival: asu_stroke12 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 18.4861 | source: asu_stroke | new: asu_stroke13 | 18.9841 - ## 18.4861 | arrival: asu_stroke12 | activity: Timeout | 1 - ## 18.6831 | arrival: asu_neuro10 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 18.6831 | source: asu_neuro | new: asu_neuro11 | 22.7153 - ## 18.6831 | arrival: asu_neuro10 | activity: Timeout | 1 - ## 18.9841 | arrival: asu_stroke13 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 18.9841 | source: asu_stroke | new: asu_stroke14 | 20.8705 - ## 18.9841 | arrival: asu_stroke13 | activity: Timeout | 1 + ## 10.9893 | source: asu_tia | new: asu_tia1 | 27.5876 + ## 10.9893 | arrival: asu_tia0 | activity: Timeout | function() + ## 13.4996 | arrival: asu_other8 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 13.4996 | source: asu_other | new: asu_other9 | 14.7437 + ## 13.4996 | arrival: asu_other8 | activity: Timeout | function() + ## 13.6419 | arrival: asu_stroke9 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 13.6419 | source: asu_stroke | new: asu_stroke10 | 14.0806 + ## 13.6419 | arrival: asu_stroke9 | activity: Timeout | function() + ## 14.0806 | arrival: asu_stroke10 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 14.0806 | source: asu_stroke | new: asu_stroke11 | 14.631 + ## 14.0806 | arrival: asu_stroke10 | activity: Timeout | function() + ## 14.1071 | arrival: asu_neuro4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 14.1071 | source: asu_neuro | new: asu_neuro5 | 24.0404 + ## 14.1071 | arrival: asu_neuro4 | activity: Timeout | function() + ## 14.631 | arrival: asu_stroke11 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 14.631 | source: asu_stroke | new: asu_stroke12 | 15.8409 + ## 14.631 | arrival: asu_stroke11 | activity: Timeout | function() + ## 14.7437 | arrival: asu_other9 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 14.7437 | source: asu_other | new: asu_other10 | 14.9333 + ## 14.7437 | arrival: asu_other9 | activity: Timeout | function() + ## 14.9333 | arrival: asu_other10 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 14.9333 | source: asu_other | new: asu_other11 | 17.5967 + ## 14.9333 | arrival: asu_other10 | activity: Timeout | function() + ## 15.8409 | arrival: asu_stroke12 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 15.8409 | source: asu_stroke | new: asu_stroke13 | 15.8939 + ## 15.8409 | arrival: asu_stroke12 | activity: Timeout | function() + ## 15.8939 | arrival: asu_stroke13 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 15.8939 | source: asu_stroke | new: asu_stroke14 | 16.2069 + ## 15.8939 | arrival: asu_stroke13 | activity: Timeout | function() + ## 16.2069 | arrival: asu_stroke14 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 16.2069 | source: asu_stroke | new: asu_stroke15 | 17.6651 + ## 16.2069 | arrival: asu_stroke14 | activity: Timeout | function() + ## 17.5967 | arrival: asu_other11 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 17.5967 | source: asu_other | new: asu_other12 | 18.2707 + ## 17.5967 | arrival: asu_other11 | activity: Timeout | function() + ## 17.6651 | arrival: asu_stroke15 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 17.6651 | source: asu_stroke | new: asu_stroke16 | 18.0837 + ## 17.6651 | arrival: asu_stroke15 | activity: Timeout | function() + ## 18.0837 | arrival: asu_stroke16 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 18.0837 | source: asu_stroke | new: asu_stroke17 | 18.5393 + ## 18.0837 | arrival: asu_stroke16 | activity: Timeout | function() + ## 18.2707 | arrival: asu_other12 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 18.2707 | source: asu_other | new: asu_other13 | 20.9141 + ## 18.2707 | arrival: asu_other12 | activity: Timeout | function() + ## 18.5393 | arrival: asu_stroke17 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 18.5393 | source: asu_stroke | new: asu_stroke18 | 19.6973 + ## 18.5393 | arrival: asu_stroke17 | activity: Timeout | function() + ## 19.6973 | arrival: asu_stroke18 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 19.6973 | source: asu_stroke | new: asu_stroke19 | 19.7376 + ## 19.6973 | arrival: asu_stroke18 | activity: Timeout | function() + ## 19.7376 | arrival: asu_stroke19 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 19.7376 | source: asu_stroke | new: asu_stroke20 | 19.8883 + ## 19.7376 | arrival: asu_stroke19 | activity: Timeout | function() + ## 19.8883 | arrival: asu_stroke20 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 19.8883 | source: asu_stroke | new: asu_stroke21 | 19.9716 + ## 19.8883 | arrival: asu_stroke20 | activity: Timeout | function() + ## 19.9716 | arrival: asu_stroke21 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 + ## 19.9716 | source: asu_stroke | new: asu_stroke22 | 20.3305 + ## 19.9716 | arrival: asu_stroke21 | activity: Timeout | function() ## $arrivals ## [1] name start_time end_time activity_time resource From 438cce7d9b6146b57f87b4c0babf389522197d63 Mon Sep 17 00:00:00 2001 From: amyheather Date: Tue, 1 Jul 2025 15:57:25 +0100 Subject: [PATCH 10/13] feat(model): set up rehab sampling destination + LOS (like ASU) + linting --- R/create_asu_trajectory.R | 11 +++++---- R/create_rehab_trajectory.R | 44 ++++++++++++++++++++++++++++++++-- R/model.R | 6 ++--- R/transform_to_lnorm.R | 6 ++--- man/create_rehab_trajectory.Rd | 8 +++++-- 5 files changed, 59 insertions(+), 16 deletions(-) diff --git a/R/create_asu_trajectory.R b/R/create_asu_trajectory.R index e977355..e32ffe5 100644 --- a/R/create_asu_trajectory.R +++ b/R/create_asu_trajectory.R @@ -25,8 +25,7 @@ create_asu_trajectory <- function(env, patient_type, param) { # Set up simmer trajectory object... trajectory(paste0("ASU_", patient_type, "_path")) |> - # Sample destination after ASU (we do this immediately on arrival in the - # ASU, as the destination influences the length of stay) + # Sample destination after ASU (as destination influences length of stay) set_attribute("post_asu_destination", function() { sample_routing(prob_list = param[["asu_routing"]][[patient_type]]) }) |> @@ -42,9 +41,11 @@ create_asu_trajectory <- function(env, patient_type, param) { if (patient_type == "stroke") { los_params <- switch( dest, - "esd" = param[["asu_los_lnorm"]][["stroke_esd"]], - "rehab" = param[["asu_los_lnorm"]][["stroke_noesd"]], - param[["asu_los_lnorm"]][["stroke_mortality"]] # Default case + esd = param[["asu_los_lnorm"]][["stroke_esd"]], + rehab = param[["asu_los_lnorm"]][["stroke_noesd"]], + other = param[["asu_los_lnorm"]][["stroke_mortality"]], + stop("Stroke post-asu destination '", dest, "' invalid", + call. = FALSE) ) } else { los_params <- param[["asu_los_lnorm"]][[patient_type]] diff --git a/R/create_rehab_trajectory.R b/R/create_rehab_trajectory.R index f687f59..325e257 100644 --- a/R/create_rehab_trajectory.R +++ b/R/create_rehab_trajectory.R @@ -1,5 +1,10 @@ #' Create rehab patient trajectory. #' +#' Represents patient stay on the rehabilitation unit - samples their (1) +#' destination after rehab, and (2) length of stay (LOS) on the unit. +#' +#' @param env Simmer environment object. The simulation environment where +#' generators will be added. #' @param patient_type Character string specifying patient category. Must be #' one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate #' parameter is used. @@ -9,12 +14,47 @@ #' \code{param$rehab_routing$stroke$esd = 0.40}). #' #' @importFrom simmer trajectory +#' @importFrom stats rlnorm #' #' @return Simmer trajectory object. Defines patient journey logic through the #' healthcare system. #' @export -create_rehab_trajectory <- function(patient_type, param) { +create_rehab_trajectory <- function(env, patient_type, param) { + + # Set up simmer trajectory object... trajectory(paste0("rehab_", patient_type, "_path")) |> - timeout(1L) + + # Sample destination after rehab (as destination influences length of stay) + set_attribute("post_rehab_destination", function() { + sample_routing(prob_list = param[["rehab_routing"]][[patient_type]]) + }) |> + + timeout(function() { + + # Retrieve attribute, and use to get post-rehab destination as a string + dest_index <- get_attribute(env, "post_rehab_destination") + dest_names <- names(param[["rehab_routing"]][[patient_type]]) + dest <- dest_names[dest_index] + + # Determine which LOS distribution to use + if (patient_type == "stroke") { + los_params <- switch( + dest, + esd = param[["rehab_los_lnorm"]][["stroke_esd"]], + other = param[["rehab_los_lnorm"]][["stroke_noesd"]], + stop("Stroke post-rehab destination '", dest, "' invalid", + call. = FALSE) + ) + } else { + los_params <- param[["rehab_los_lnorm"]][[patient_type]] + } + + # Sample LOS from lognormal + rlnorm( + n = 1L, + meanlog = los_params[["meanlog"]], + sdlog = los_params[["sdlog"]] + ) + }) } diff --git a/R/model.R b/R/model.R index 6cb4be0..91d9178 100644 --- a/R/model.R +++ b/R/model.R @@ -32,11 +32,9 @@ model <- function(run_number, param, set_seed = TRUE) { # Create patient trajectory traj <- if (unit == "asu") { - create_asu_trajectory( - env = env, patient_type = patient_type, param = param - ) + create_asu_trajectory(env, patient_type, param) } else { - create_rehab_trajectory(patient_type, param) + create_rehab_trajectory(env, patient_type, param) } # Add patient generator using the created trajectory diff --git a/R/transform_to_lnorm.R b/R/transform_to_lnorm.R index af4ba6f..2784fcd 100644 --- a/R/transform_to_lnorm.R +++ b/R/transform_to_lnorm.R @@ -16,10 +16,10 @@ transform_to_lnorm <- function(los_list) { lapply(los_list, function(x) { - variance <- x$sd^2 - sigma_sq <- log(variance / (x$mean^2) + 1) + variance <- x$sd^2L + sigma_sq <- log(variance / (x$mean^2L) + 1L) sdlog <- sqrt(sigma_sq) - meanlog <- log(x$mean) - sigma_sq / 2 + meanlog <- log(x$mean) - sigma_sq / 2L list(meanlog = meanlog, sdlog = sdlog) }) } diff --git a/man/create_rehab_trajectory.Rd b/man/create_rehab_trajectory.Rd index 9d5de11..25e3225 100644 --- a/man/create_rehab_trajectory.Rd +++ b/man/create_rehab_trajectory.Rd @@ -4,9 +4,12 @@ \alias{create_rehab_trajectory} \title{Create rehab patient trajectory.} \usage{ -create_rehab_trajectory(patient_type, param) +create_rehab_trajectory(env, patient_type, param) } \arguments{ +\item{env}{Simmer environment object. The simulation environment where +generators will be added.} + \item{patient_type}{Character string specifying patient category. Must be one of: "stroke", "tia", "neuro", or "other". Determines which arrival rate parameter is used.} @@ -21,5 +24,6 @@ Simmer trajectory object. Defines patient journey logic through the healthcare system. } \description{ -Create rehab patient trajectory. +Represents patient stay on the rehabilitation unit - samples their (1) + destination after rehab, and (2) length of stay (LOS) on the unit. } From d045809e1e9c4d20aa06b11e2746af99d8a345c7 Mon Sep 17 00:00:00 2001 From: amyheather Date: Tue, 1 Jul 2025 16:05:00 +0100 Subject: [PATCH 11/13] feat(model): modify trajectory to send ASU patients to rehab (plus minor docstring change in rehab traj) --- NAMESPACE | 1 + R/create_asu_trajectory.R | 18 ++++++++++++++++-- R/create_rehab_trajectory.R | 4 ++-- man/create_rehab_trajectory.Rd | 2 +- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 1888784..f0c97e0 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -14,6 +14,7 @@ export(model) export(sample_routing) export(transform_to_lnorm) importFrom(simmer,add_generator) +importFrom(simmer,branch) importFrom(simmer,get_attribute) importFrom(simmer,get_mon_arrivals) importFrom(simmer,get_mon_resources) diff --git a/R/create_asu_trajectory.R b/R/create_asu_trajectory.R index e32ffe5..4dd37dc 100644 --- a/R/create_asu_trajectory.R +++ b/R/create_asu_trajectory.R @@ -13,7 +13,7 @@ #' of routing to each destination (e.g. #' \code{param$asu_routing$stroke$rehab = 0.24}). #' -#' @importFrom simmer trajectory +#' @importFrom simmer branch trajectory #' @importFrom stats rlnorm #' #' @return Simmer trajectory object. Defines patient journey logic through the @@ -57,5 +57,19 @@ create_asu_trajectory <- function(env, patient_type, param) { meanlog = los_params[["meanlog"]], sdlog = los_params[["sdlog"]] ) - }) + }) |> + + # If that patient's destination is rehab, then start on that trajectory + branch( + option = function() { + # Retrieve attribute, and use to get post-ASU destination as a string + dest_index <- get_attribute(env, "post_asu_destination") + dest_names <- names(param[["asu_routing"]][[patient_type]]) + dest <- dest_names[dest_index] + # Return 1 for rehab and 0 otherwise + if (dest == "rehab") 1L else 0L + }, + continue = FALSE, # Do not continue main trajectory after branch + create_rehab_trajectory(env, patient_type, param) + ) } diff --git a/R/create_rehab_trajectory.R b/R/create_rehab_trajectory.R index 325e257..14fc571 100644 --- a/R/create_rehab_trajectory.R +++ b/R/create_rehab_trajectory.R @@ -1,7 +1,7 @@ #' Create rehab patient trajectory. #' -#' Represents patient stay on the rehabilitation unit - samples their (1) -#' destination after rehab, and (2) length of stay (LOS) on the unit. +#' Represents patient stay on the rehabilitation unit - samples their (1) +#' destination after rehab, and (2) length of stay (LOS) on the unit. #' #' @param env Simmer environment object. The simulation environment where #' generators will be added. diff --git a/man/create_rehab_trajectory.Rd b/man/create_rehab_trajectory.Rd index 25e3225..52b8b60 100644 --- a/man/create_rehab_trajectory.Rd +++ b/man/create_rehab_trajectory.Rd @@ -25,5 +25,5 @@ healthcare system. } \description{ Represents patient stay on the rehabilitation unit - samples their (1) - destination after rehab, and (2) length of stay (LOS) on the unit. +destination after rehab, and (2) length of stay (LOS) on the unit. } From 72436c7090e4704315ffda2940ec3f1a70591801 Mon Sep 17 00:00:00 2001 From: amyheather Date: Tue, 1 Jul 2025 16:15:26 +0100 Subject: [PATCH 12/13] feat(logging): add control of logging, to log_to_console and log_to_file control whether logs are shown and where, and the log message is appended with the parameters used --- R/model.R | 46 ++++-- rmarkdown/analysis.Rmd | 3 +- rmarkdown/analysis.md | 310 +++++++++++++++++++++++------------------ 3 files changed, 213 insertions(+), 146 deletions(-) diff --git a/R/model.R b/R/model.R index 91d9178..060aaba 100644 --- a/R/model.R +++ b/R/model.R @@ -6,8 +6,8 @@ #' may not wish to do if being set elsewhere - such as done in \code{runner()}). #' Default is TRUE. #' -#' @importFrom simmer get_attribute get_mon_arrivals get_mon_resources -#' @importFrom simmer set_attribute simmer timeout wrap +#' @importFrom simmer get_mon_arrivals get_mon_resources simmer wrap +#' @importFrom utils capture.output #' #' @return TBC #' @export @@ -19,12 +19,15 @@ model <- function(run_number, param, set_seed = TRUE) { set.seed(run_number) } + # Determine whether to get verbose activity logs + verbose <- any(c(param[["log_to_console"]], param[["log_to_file"]])) + # Transform LOS parameters to lognormal scale param[["asu_los_lnorm"]] <- transform_to_lnorm(param[["asu_los"]]) param[["rehab_los_lnorm"]] <- transform_to_lnorm(param[["rehab_los"]]) # Create simmer environment - env <- simmer("simulation", verbose = TRUE) + env <- simmer("simulation", verbose = verbose) # Add ASU and rehab direct admission patient generators for (unit in c("asu", "rehab")) { @@ -38,20 +41,39 @@ model <- function(run_number, param, set_seed = TRUE) { } # Add patient generator using the created trajectory - env <- add_patient_generator( - env = env, - trajectory = traj, - unit = unit, - patient_type = patient_type, - param = param + sim_log <- capture.output( + env <- add_patient_generator( + env = env, + trajectory = traj, + unit = unit, + patient_type = patient_type, + param = param + ) ) } } # Run the model - env <- env |> - simmer::run(20L) |> - wrap() + sim_log <- capture.output( + env <- env |> + simmer::run(20L) |> + wrap() + ) + + # Save and/or display the log + if (isTRUE(verbose)) { + # Create full log message by adding parameters + param_string <- paste(names(param), param, sep = "=", collapse = ";\n ") + full_log <- append(c("Parameters:", param_string, "Log:"), sim_log) + # Print to console + if (isTRUE(param[["log_to_console"]])) { + print(full_log) + } + # Save to file + if (isTRUE(param[["log_to_file"]])) { + writeLines(full_log, param[["file_path"]]) + } + } # Extract the monitored arrivals and resources information from the simmer # environment object diff --git a/rmarkdown/analysis.Rmd b/rmarkdown/analysis.Rmd index 87d39d1..713878d 100644 --- a/rmarkdown/analysis.Rmd +++ b/rmarkdown/analysis.Rmd @@ -18,5 +18,6 @@ library(simulation) ```{r} -model(run_number = 1L, param = create_parameters(), set_seed = TRUE) +param <- create_parameters(log_to_console = TRUE) +model(run_number = 1L, param = param, set_seed = TRUE) ``` diff --git a/rmarkdown/analysis.md b/rmarkdown/analysis.md index 7c3a383..8887df1 100644 --- a/rmarkdown/analysis.md +++ b/rmarkdown/analysis.md @@ -16,141 +16,185 @@ library(simulation) ``` ``` r -model(run_number = 1L, param = create_parameters(), set_seed = TRUE) +param <- create_parameters(log_to_console = TRUE) +model(run_number = 1L, param = param, set_seed = TRUE) ``` - ## 0 | source: asu_stroke | new: asu_stroke0 | 0.906218 - ## 0 | source: asu_tia | new: asu_tia0 | 10.9893 - ## 0 | source: asu_neuro | new: asu_neuro0 | 0.524544 - ## 0 | source: asu_other | new: asu_other0 | 0.447345 - ## 0 | source: rehab_stroke | new: rehab_stroke0 | 9.5063 - ## 0 | source: rehab_neuro | new: rehab_neuro0 | 91.7705 - ## 0 | source: rehab_other | new: rehab_other0 | 35.1655 - ## 0.447345 | arrival: asu_other0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 0.447345 | source: asu_other | new: asu_other1 | 3.50836 - ## 0.447345 | arrival: asu_other0 | activity: Timeout | function() - ## 0.524544 | arrival: asu_neuro0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 0.524544 | source: asu_neuro | new: asu_neuro1 | 5.53119 - ## 0.524544 | arrival: asu_neuro0 | activity: Timeout | function() - ## 0.906218 | arrival: asu_stroke0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 0.906218 | source: asu_stroke | new: asu_stroke1 | 2.37346 - ## 0.906218 | arrival: asu_stroke0 | activity: Timeout | function() - ## 2.37346 | arrival: asu_stroke1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 2.37346 | source: asu_stroke | new: asu_stroke2 | 2.61241 - ## 2.37346 | arrival: asu_stroke1 | activity: Timeout | function() - ## 2.61241 | arrival: asu_stroke2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 2.61241 | source: asu_stroke | new: asu_stroke3 | 3.01674 - ## 2.61241 | arrival: asu_stroke2 | activity: Timeout | function() - ## 3.01674 | arrival: asu_stroke3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 3.01674 | source: asu_stroke | new: asu_stroke4 | 4.62263 - ## 3.01674 | arrival: asu_stroke3 | activity: Timeout | function() - ## 3.50836 | arrival: asu_other1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 3.50836 | source: asu_other | new: asu_other2 | 3.84779 - ## 3.50836 | arrival: asu_other1 | activity: Timeout | function() - ## 3.84779 | arrival: asu_other2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 3.84779 | source: asu_other | new: asu_other3 | 7.60239 - ## 3.84779 | arrival: asu_other2 | activity: Timeout | function() - ## 4.62263 | arrival: asu_stroke4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 4.62263 | source: asu_stroke | new: asu_stroke5 | 6.34497 - ## 4.62263 | arrival: asu_stroke4 | activity: Timeout | function() - ## 5.53119 | arrival: asu_neuro1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 5.53119 | source: asu_neuro | new: asu_neuro2 | 6.26383 - ## 5.53119 | arrival: asu_neuro1 | activity: Timeout | function() - ## 6.26383 | arrival: asu_neuro2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 6.26383 | source: asu_neuro | new: asu_neuro3 | 8.96938 - ## 6.26383 | arrival: asu_neuro2 | activity: Timeout | function() - ## 6.34497 | arrival: asu_stroke5 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 6.34497 | source: asu_stroke | new: asu_stroke6 | 7.64083 - ## 6.34497 | arrival: asu_stroke5 | activity: Timeout | function() - ## 7.60239 | arrival: asu_other3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 7.60239 | source: asu_other | new: asu_other4 | 8.46742 - ## 7.60239 | arrival: asu_other3 | activity: Timeout | function() - ## 7.64083 | arrival: asu_stroke6 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 7.64083 | source: asu_stroke | new: asu_stroke7 | 9.19258 - ## 7.64083 | arrival: asu_stroke6 | activity: Timeout | function() - ## 8.46742 | arrival: asu_other4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 8.46742 | source: asu_other | new: asu_other5 | 9.81859 - ## 8.46742 | arrival: asu_other4 | activity: Timeout | function() - ## 8.96938 | arrival: asu_neuro3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 8.96938 | source: asu_neuro | new: asu_neuro4 | 14.1071 - ## 8.96938 | arrival: asu_neuro3 | activity: Timeout | function() - ## 9.19258 | arrival: asu_stroke7 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 9.19258 | source: asu_stroke | new: asu_stroke8 | 10.3655 - ## 9.19258 | arrival: asu_stroke7 | activity: Timeout | function() - ## 9.5063 | arrival: rehab_stroke0 | activity: Timeout | 1 - ## 9.5063 | source: rehab_stroke | new: rehab_stroke1 | 33.6157 - ## 9.81859 | arrival: asu_other5 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 9.81859 | source: asu_other | new: asu_other6 | 10.1055 - ## 9.81859 | arrival: asu_other5 | activity: Timeout | function() - ## 10.1055 | arrival: asu_other6 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 10.1055 | source: asu_other | new: asu_other7 | 10.8968 - ## 10.1055 | arrival: asu_other6 | activity: Timeout | function() - ## 10.3655 | arrival: asu_stroke8 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 10.3655 | source: asu_stroke | new: asu_stroke9 | 13.6419 - ## 10.3655 | arrival: asu_stroke8 | activity: Timeout | function() - ## 10.8968 | arrival: asu_other7 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 10.8968 | source: asu_other | new: asu_other8 | 13.4996 - ## 10.8968 | arrival: asu_other7 | activity: Timeout | function() - ## 10.9893 | arrival: asu_tia0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 10.9893 | source: asu_tia | new: asu_tia1 | 27.5876 - ## 10.9893 | arrival: asu_tia0 | activity: Timeout | function() - ## 13.4996 | arrival: asu_other8 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 13.4996 | source: asu_other | new: asu_other9 | 14.7437 - ## 13.4996 | arrival: asu_other8 | activity: Timeout | function() - ## 13.6419 | arrival: asu_stroke9 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 13.6419 | source: asu_stroke | new: asu_stroke10 | 14.0806 - ## 13.6419 | arrival: asu_stroke9 | activity: Timeout | function() - ## 14.0806 | arrival: asu_stroke10 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 14.0806 | source: asu_stroke | new: asu_stroke11 | 14.631 - ## 14.0806 | arrival: asu_stroke10 | activity: Timeout | function() - ## 14.1071 | arrival: asu_neuro4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 14.1071 | source: asu_neuro | new: asu_neuro5 | 24.0404 - ## 14.1071 | arrival: asu_neuro4 | activity: Timeout | function() - ## 14.631 | arrival: asu_stroke11 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 14.631 | source: asu_stroke | new: asu_stroke12 | 15.8409 - ## 14.631 | arrival: asu_stroke11 | activity: Timeout | function() - ## 14.7437 | arrival: asu_other9 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 14.7437 | source: asu_other | new: asu_other10 | 14.9333 - ## 14.7437 | arrival: asu_other9 | activity: Timeout | function() - ## 14.9333 | arrival: asu_other10 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 14.9333 | source: asu_other | new: asu_other11 | 17.5967 - ## 14.9333 | arrival: asu_other10 | activity: Timeout | function() - ## 15.8409 | arrival: asu_stroke12 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 15.8409 | source: asu_stroke | new: asu_stroke13 | 15.8939 - ## 15.8409 | arrival: asu_stroke12 | activity: Timeout | function() - ## 15.8939 | arrival: asu_stroke13 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 15.8939 | source: asu_stroke | new: asu_stroke14 | 16.2069 - ## 15.8939 | arrival: asu_stroke13 | activity: Timeout | function() - ## 16.2069 | arrival: asu_stroke14 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 16.2069 | source: asu_stroke | new: asu_stroke15 | 17.6651 - ## 16.2069 | arrival: asu_stroke14 | activity: Timeout | function() - ## 17.5967 | arrival: asu_other11 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 17.5967 | source: asu_other | new: asu_other12 | 18.2707 - ## 17.5967 | arrival: asu_other11 | activity: Timeout | function() - ## 17.6651 | arrival: asu_stroke15 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 17.6651 | source: asu_stroke | new: asu_stroke16 | 18.0837 - ## 17.6651 | arrival: asu_stroke15 | activity: Timeout | function() - ## 18.0837 | arrival: asu_stroke16 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 18.0837 | source: asu_stroke | new: asu_stroke17 | 18.5393 - ## 18.0837 | arrival: asu_stroke16 | activity: Timeout | function() - ## 18.2707 | arrival: asu_other12 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 18.2707 | source: asu_other | new: asu_other13 | 20.9141 - ## 18.2707 | arrival: asu_other12 | activity: Timeout | function() - ## 18.5393 | arrival: asu_stroke17 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 18.5393 | source: asu_stroke | new: asu_stroke18 | 19.6973 - ## 18.5393 | arrival: asu_stroke17 | activity: Timeout | function() - ## 19.6973 | arrival: asu_stroke18 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 19.6973 | source: asu_stroke | new: asu_stroke19 | 19.7376 - ## 19.6973 | arrival: asu_stroke18 | activity: Timeout | function() - ## 19.7376 | arrival: asu_stroke19 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 19.7376 | source: asu_stroke | new: asu_stroke20 | 19.8883 - ## 19.7376 | arrival: asu_stroke19 | activity: Timeout | function() - ## 19.8883 | arrival: asu_stroke20 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 19.8883 | source: asu_stroke | new: asu_stroke21 | 19.9716 - ## 19.8883 | arrival: asu_stroke20 | activity: Timeout | function() - ## 19.9716 | arrival: asu_stroke21 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0 - ## 19.9716 | source: asu_stroke | new: asu_stroke22 | 20.3305 - ## 19.9716 | arrival: asu_stroke21 | activity: Timeout | function() + ## [1] "Parameters:" + ## [2] "asu_arrivals=list(stroke = 1.2, tia = 9.3, neuro = 3.6, other = 3.2);\n rehab_arrivals=list(stroke = 21.8, neuro = 31.7, other = 28.6);\n asu_los=list(stroke_noesd = list(mean = 7.4, sd = 8.61), stroke_esd = list(mean = 4.6, sd = 4.8), stroke_mortality = list(mean = 7, sd = 8.7), tia = list(mean = 1.8, sd = 2.3), neuro = list(mean = 4, sd = 5), other = list(mean = 3.8, sd = 5.2));\n rehab_los=list(stroke_noesd = list(mean = 28.4, sd = 27.2), stroke_esd = list(mean = 30.3, sd = 23.1), tia = list(mean = 18.7, sd = 23.5), neuro = list(mean = 27.6, sd = 28.4), other = list(mean = 16.1, sd = 14.1));\n asu_routing=list(stroke = list(rehab = 0.24, esd = 0.13, other = 0.63), tia = list(rehab = 0.01, esd = 0.01, other = 0.98), neuro = list(rehab = 0.11, esd = 0.05, other = 0.84), other = list(rehab = 0.05, esd = 0.1, other = 0.85));\n rehab_routing=list(stroke = list(esd = 0.4, other = 0.6), tia = list(esd = 0, other = 1), neuro = list(esd = 0.09, other = 0.91), other = list(esd = 0.13, other = 0.88));\n warm_up_period=1095;\n data_collection_period=1825;\n number_of_runs=150;\n scenario_name=NULL;\n cores=1;\n log_to_console=TRUE;\n log_to_file=FALSE;\n file_path=NULL;\n asu_los_lnorm=list(stroke_noesd = list(meanlog = 1.57347219029677, sdlog = 0.925211121759084), stroke_esd = list(meanlog = 1.15775021244827, sdlog = 0.858261138636461), stroke_mortality = list(meanlog = 1.47890496960638, sdlog = 0.966442113578391), tia = list(meanlog = 0.103778649052444, sdlog = 0.983878057331979), neuro = list(meanlog = 0.915802688887627, sdlog = 0.970042960112864), other = list(meanlog = 0.807396441784017, sdlog = 1.02723378541433));\n rehab_los_lnorm=list(stroke_noesd = list(meanlog = 3.02093582638726, sdlog = 0.806787851643665), stroke_esd = list(meanlog = 3.18205014379696, sdlog = 0.676901128257839), tia = list(meanlog = 2.45477304821951, sdlog = 0.973396605337238), neuro = list(meanlog = 2.95675141458562, sdlog = 0.849781569743057), other = list(meanlog = 2.49418211833932, sdlog = 0.754502688730926))" + ## [3] "Log:" + ## [4] " 0 | source: asu_stroke | new: asu_stroke0 | 0.906218" + ## [5] " 0 | source: asu_tia | new: asu_tia0 | 10.9893" + ## [6] " 0 | source: asu_neuro | new: asu_neuro0 | 0.524544" + ## [7] " 0 | source: asu_other | new: asu_other0 | 0.447345" + ## [8] " 0 | source: rehab_stroke | new: rehab_stroke0 | 9.5063" + ## [9] " 0 | source: rehab_neuro | new: rehab_neuro0 | 91.7705" + ## [10] " 0 | source: rehab_other | new: rehab_other0 | 35.1655" + ## [11] " 0.447345 | arrival: asu_other0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [12] " 0.447345 | source: asu_other | new: asu_other1 | 3.50836" + ## [13] " 0.447345 | arrival: asu_other0 | activity: Timeout | function()" + ## [14] " 0.524544 | arrival: asu_neuro0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [15] " 0.524544 | source: asu_neuro | new: asu_neuro1 | 5.53119" + ## [16] " 0.524544 | arrival: asu_neuro0 | activity: Timeout | function()" + ## [17] " 0.906218 | arrival: asu_stroke0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [18] " 0.906218 | source: asu_stroke | new: asu_stroke1 | 2.37346" + ## [19] " 0.906218 | arrival: asu_stroke0 | activity: Timeout | function()" + ## [20] " 1.8923 | arrival: asu_neuro0 | activity: Branch | function(), 1 paths" + ## [21] " 2.37346 | arrival: asu_stroke1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [22] " 2.37346 | source: asu_stroke | new: asu_stroke2 | 2.61241" + ## [23] " 2.37346 | arrival: asu_stroke1 | activity: Timeout | function()" + ## [24] " 2.61241 | arrival: asu_stroke2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [25] " 2.61241 | source: asu_stroke | new: asu_stroke3 | 3.01674" + ## [26] " 2.61241 | arrival: asu_stroke2 | activity: Timeout | function()" + ## [27] " 3.01674 | arrival: asu_stroke3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [28] " 3.01674 | source: asu_stroke | new: asu_stroke4 | 4.62263" + ## [29] " 3.01674 | arrival: asu_stroke3 | activity: Timeout | function()" + ## [30] " 3.50836 | arrival: asu_other1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [31] " 3.50836 | source: asu_other | new: asu_other2 | 3.84779" + ## [32] " 3.50836 | arrival: asu_other1 | activity: Timeout | function()" + ## [33] " 3.84779 | arrival: asu_other2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [34] " 3.84779 | source: asu_other | new: asu_other3 | 7.60239" + ## [35] " 3.84779 | arrival: asu_other2 | activity: Timeout | function()" + ## [36] " 4.62263 | arrival: asu_stroke4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [37] " 4.62263 | source: asu_stroke | new: asu_stroke5 | 6.34497" + ## [38] " 4.62263 | arrival: asu_stroke4 | activity: Timeout | function()" + ## [39] " 5.53119 | arrival: asu_neuro1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [40] " 5.53119 | source: asu_neuro | new: asu_neuro2 | 6.26383" + ## [41] " 5.53119 | arrival: asu_neuro1 | activity: Timeout | function()" + ## [42] " 5.9289 | arrival: asu_other1 | activity: Branch | function(), 1 paths" + ## [43] " 5.96424 | arrival: asu_other2 | activity: Branch | function(), 1 paths" + ## [44] " 6.26383 | arrival: asu_neuro2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [45] " 6.26383 | source: asu_neuro | new: asu_neuro3 | 8.96938" + ## [46] " 6.26383 | arrival: asu_neuro2 | activity: Timeout | function()" + ## [47] " 6.34497 | arrival: asu_stroke5 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [48] " 6.34497 | source: asu_stroke | new: asu_stroke6 | 7.64083" + ## [49] " 6.34497 | arrival: asu_stroke5 | activity: Timeout | function()" + ## [50] " 6.69347 | arrival: asu_stroke1 | activity: Branch | function(), 1 paths" + ## [51] " 7.17247 | arrival: asu_neuro1 | activity: Branch | function(), 1 paths" + ## [52] " 7.60239 | arrival: asu_other3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [53] " 7.60239 | source: asu_other | new: asu_other4 | 8.46742" + ## [54] " 7.60239 | arrival: asu_other3 | activity: Timeout | function()" + ## [55] " 7.64083 | arrival: asu_stroke6 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [56] " 7.64083 | source: asu_stroke | new: asu_stroke7 | 9.19258" + ## [57] " 7.64083 | arrival: asu_stroke6 | activity: Timeout | function()" + ## [58] " 8.46742 | arrival: asu_other4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [59] " 8.46742 | source: asu_other | new: asu_other5 | 9.81859" + ## [60] " 8.46742 | arrival: asu_other4 | activity: Timeout | function()" + ## [61] " 8.96938 | arrival: asu_neuro3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [62] " 8.96938 | source: asu_neuro | new: asu_neuro4 | 14.1071" + ## [63] " 8.96938 | arrival: asu_neuro3 | activity: Timeout | function()" + ## [64] " 9.14383 | arrival: asu_other4 | activity: Branch | function(), 1 paths" + ## [65] " 9.19258 | arrival: asu_stroke7 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [66] " 9.19258 | source: asu_stroke | new: asu_stroke8 | 10.3655" + ## [67] " 9.19258 | arrival: asu_stroke7 | activity: Timeout | function()" + ## [68] " 9.21347 | arrival: asu_stroke4 | activity: Branch | function(), 1 paths" + ## [69] " 9.5063 | arrival: rehab_stroke0 | activity: SetAttribute | [post_rehab_destination], function(), 0, N, 0" + ## [70] " 9.5063 | source: rehab_stroke | new: rehab_stroke1 | 26.3836" + ## [71] " 9.5063 | arrival: rehab_stroke0 | activity: Timeout | function()" + ## [72] " 9.58662 | arrival: asu_stroke5 | activity: Branch | function(), 1 paths" + ## [73] " 9.58662 | arrival: asu_stroke5 | activity: SetAttribute | [post_rehab_destination], function(), 0, N, 0" + ## [74] " 9.58662 | arrival: asu_stroke5 | activity: Timeout | function()" + ## [75] " 9.81859 | arrival: asu_other5 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [76] " 9.81859 | source: asu_other | new: asu_other6 | 10.4507" + ## [77] " 9.81859 | arrival: asu_other5 | activity: Timeout | function()" + ## [78] " 10.3655 | arrival: asu_stroke8 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [79] " 10.3655 | source: asu_stroke | new: asu_stroke9 | 11.2081" + ## [80] " 10.3655 | arrival: asu_stroke8 | activity: Timeout | function()" + ## [81] " 10.4507 | arrival: asu_other6 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [82] " 10.4507 | source: asu_other | new: asu_other7 | 11.3473" + ## [83] " 10.4507 | arrival: asu_other6 | activity: Timeout | function()" + ## [84] " 10.8134 | arrival: asu_stroke6 | activity: Branch | function(), 1 paths" + ## [85] " 10.8134 | arrival: asu_stroke6 | activity: SetAttribute | [post_rehab_destination], function(), 0, N, 0" + ## [86] " 10.8134 | arrival: asu_stroke6 | activity: Timeout | function()" + ## [87] " 10.9893 | arrival: asu_tia0 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [88] " 10.9893 | source: asu_tia | new: asu_tia1 | 11.197" + ## [89] " 10.9893 | arrival: asu_tia0 | activity: Timeout | function()" + ## [90] " 11.042 | arrival: asu_other0 | activity: Branch | function(), 1 paths" + ## [91] " 11.197 | arrival: asu_tia1 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [92] " 11.197 | source: asu_tia | new: asu_tia2 | 12.5897" + ## [93] " 11.197 | arrival: asu_tia1 | activity: Timeout | function()" + ## [94] " 11.2081 | arrival: asu_stroke9 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [95] " 11.2081 | source: asu_stroke | new: asu_stroke10 | 11.6747" + ## [96] " 11.2081 | arrival: asu_stroke9 | activity: Timeout | function()" + ## [97] " 11.3473 | arrival: asu_other7 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [98] " 11.3473 | source: asu_other | new: asu_other8 | 12.5172" + ## [99] " 11.3473 | arrival: asu_other7 | activity: Timeout | function()" + ## [100] " 11.47 | arrival: asu_tia1 | activity: Branch | function(), 1 paths" + ## [101] " 11.4868 | arrival: asu_tia0 | activity: Branch | function(), 1 paths" + ## [102] " 11.6747 | arrival: asu_stroke10 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [103] " 11.6747 | source: asu_stroke | new: asu_stroke11 | 12.225" + ## [104] " 11.6747 | arrival: asu_stroke10 | activity: Timeout | function()" + ## [105] " 12.225 | arrival: asu_stroke11 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [106] " 12.225 | source: asu_stroke | new: asu_stroke12 | 15.5361" + ## [107] " 12.225 | arrival: asu_stroke11 | activity: Timeout | function()" + ## [108] " 12.5172 | arrival: asu_other8 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [109] " 12.5172 | source: asu_other | new: asu_other9 | 15.7436" + ## [110] " 12.5172 | arrival: asu_other8 | activity: Timeout | function()" + ## [111] " 12.5897 | arrival: asu_tia2 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [112] " 12.5897 | source: asu_tia | new: asu_tia3 | 13.1408" + ## [113] " 12.5897 | arrival: asu_tia2 | activity: Timeout | function()" + ## [114] " 12.8593 | arrival: asu_tia2 | activity: Branch | function(), 1 paths" + ## [115] " 12.9241 | arrival: asu_stroke2 | activity: Branch | function(), 1 paths" + ## [116] " 12.9241 | arrival: asu_stroke2 | activity: SetAttribute | [post_rehab_destination], function(), 0, N, 0" + ## [117] " 12.9241 | arrival: asu_stroke2 | activity: Timeout | function()" + ## [118] " 13.1408 | arrival: asu_tia3 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [119] " 13.1408 | source: asu_tia | new: asu_tia4 | 18.3485" + ## [120] " 13.1408 | arrival: asu_tia3 | activity: Timeout | function()" + ## [121] " 13.9024 | arrival: asu_neuro2 | activity: Branch | function(), 1 paths" + ## [122] " 13.921 | arrival: asu_stroke0 | activity: Branch | function(), 1 paths" + ## [123] " 14.1071 | arrival: asu_neuro4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [124] " 14.1071 | source: asu_neuro | new: asu_neuro5 | 17.8335" + ## [125] " 14.1071 | arrival: asu_neuro4 | activity: Timeout | function()" + ## [126] " 14.2678 | arrival: asu_other7 | activity: Branch | function(), 1 paths" + ## [127] " 14.3045 | arrival: asu_stroke3 | activity: Branch | function(), 1 paths" + ## [128] " 14.3045 | arrival: asu_stroke3 | activity: SetAttribute | [post_rehab_destination], function(), 0, N, 0" + ## [129] " 14.3045 | arrival: asu_stroke3 | activity: Timeout | function()" + ## [130] " 14.5038 | arrival: asu_other8 | activity: Branch | function(), 1 paths" + ## [131] " 15.3626 | arrival: asu_stroke7 | activity: Branch | function(), 1 paths" + ## [132] " 15.3626 | arrival: asu_stroke7 | activity: SetAttribute | [post_rehab_destination], function(), 0, N, 0" + ## [133] " 15.3626 | arrival: asu_stroke7 | activity: Timeout | function()" + ## [134] " 15.5361 | arrival: asu_stroke12 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [135] " 15.5361 | source: asu_stroke | new: asu_stroke13 | 16.1147" + ## [136] " 15.5361 | arrival: asu_stroke12 | activity: Timeout | function()" + ## [137] " 15.5854 | arrival: asu_stroke10 | activity: Branch | function(), 1 paths" + ## [138] " 15.7436 | arrival: asu_other9 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [139] " 15.7436 | source: asu_other | new: asu_other10 | 21.876" + ## [140] " 15.7436 | arrival: asu_other9 | activity: Timeout | function()" + ## [141] " 16.1147 | arrival: asu_stroke13 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [142] " 16.1147 | source: asu_stroke | new: asu_stroke14 | 18.3945" + ## [143] " 16.1147 | arrival: asu_stroke13 | activity: Timeout | function()" + ## [144] " 16.3318 | arrival: asu_stroke9 | activity: Branch | function(), 1 paths" + ## [145] " 16.3318 | arrival: asu_stroke9 | activity: SetAttribute | [post_rehab_destination], function(), 0, N, 0" + ## [146] " 16.3318 | arrival: asu_stroke9 | activity: Timeout | function()" + ## [147] " 16.6423 | arrival: asu_neuro3 | activity: Branch | function(), 1 paths" + ## [148] " 16.6764 | arrival: asu_tia3 | activity: Branch | function(), 1 paths" + ## [149] " 17.8335 | arrival: asu_neuro5 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [150] " 17.8335 | source: asu_neuro | new: asu_neuro6 | 27.5297" + ## [151] " 17.8335 | arrival: asu_neuro5 | activity: Timeout | function()" + ## [152] " 17.9758 | arrival: asu_stroke8 | activity: Branch | function(), 1 paths" + ## [153] " 18.3485 | arrival: asu_tia4 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [154] " 18.3485 | source: asu_tia | new: asu_tia5 | 39.737" + ## [155] " 18.3485 | arrival: asu_tia4 | activity: Timeout | function()" + ## [156] " 18.3945 | arrival: asu_stroke14 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [157] " 18.3945 | source: asu_stroke | new: asu_stroke15 | 18.4348" + ## [158] " 18.3945 | arrival: asu_stroke14 | activity: Timeout | function()" + ## [159] " 18.4348 | arrival: asu_stroke15 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [160] " 18.4348 | source: asu_stroke | new: asu_stroke16 | 18.5855" + ## [161] " 18.4348 | arrival: asu_stroke15 | activity: Timeout | function()" + ## [162] " 18.5529 | arrival: asu_neuro4 | activity: Branch | function(), 1 paths" + ## [163] " 18.5855 | arrival: asu_stroke16 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [164] " 18.5855 | source: asu_stroke | new: asu_stroke17 | 18.6688" + ## [165] " 18.5855 | arrival: asu_stroke16 | activity: Timeout | function()" + ## [166] " 18.6688 | arrival: asu_stroke17 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [167] " 18.6688 | source: asu_stroke | new: asu_stroke18 | 19.0278" + ## [168] " 18.6688 | arrival: asu_stroke17 | activity: Timeout | function()" + ## [169] " 19.0278 | arrival: asu_stroke18 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [170] " 19.0278 | source: asu_stroke | new: asu_stroke19 | 19.9194" + ## [171] " 19.0278 | arrival: asu_stroke18 | activity: Timeout | function()" + ## [172] " 19.9066 | arrival: asu_stroke15 | activity: Branch | function(), 1 paths" + ## [173] " 19.9194 | arrival: asu_stroke19 | activity: SetAttribute | [post_asu_destination], function(), 0, N, 0" + ## [174] " 19.9194 | source: asu_stroke | new: asu_stroke20 | 20.1337" + ## [175] " 19.9194 | arrival: asu_stroke19 | activity: Timeout | function()" ## $arrivals ## [1] name start_time end_time activity_time resource From e89333c722e93a9be3ee6d21834574f4e5b046c2 Mon Sep 17 00:00:00 2001 From: amyheather Date: Tue, 1 Jul 2025 16:42:12 +0100 Subject: [PATCH 13/13] feat(logs): add custom logs (as felt this would particularly benefit, as the default are so hard to read, and I wanted to be sure everything was set up right - which it looks to be!) :) --- NAMESPACE | 2 ++ R/create_asu_trajectory.R | 23 +++++++++++++++++++++-- R/create_rehab_trajectory.R | 25 ++++++++++++++++++++++--- R/model.R | 8 ++++---- 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index f0c97e0..b9c4cbd 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -18,6 +18,7 @@ importFrom(simmer,branch) importFrom(simmer,get_attribute) importFrom(simmer,get_mon_arrivals) importFrom(simmer,get_mon_resources) +importFrom(simmer,log_) importFrom(simmer,set_attribute) importFrom(simmer,simmer) importFrom(simmer,timeout) @@ -25,3 +26,4 @@ importFrom(simmer,trajectory) importFrom(simmer,wrap) importFrom(stats,rexp) importFrom(stats,rlnorm) +importFrom(utils,capture.output) diff --git a/R/create_asu_trajectory.R b/R/create_asu_trajectory.R index 4dd37dc..ae974dd 100644 --- a/R/create_asu_trajectory.R +++ b/R/create_asu_trajectory.R @@ -13,7 +13,7 @@ #' of routing to each destination (e.g. #' \code{param$asu_routing$stroke$rehab = 0.24}). #' -#' @importFrom simmer branch trajectory +#' @importFrom simmer branch get_attribute log_ set_attribute timeout trajectory #' @importFrom stats rlnorm #' #' @return Simmer trajectory object. Defines patient journey logic through the @@ -25,13 +25,23 @@ create_asu_trajectory <- function(env, patient_type, param) { # Set up simmer trajectory object... trajectory(paste0("ASU_", patient_type, "_path")) |> + log_("🚶 Arrived at ASU") |> + # Sample destination after ASU (as destination influences length of stay) set_attribute("post_asu_destination", function() { sample_routing(prob_list = param[["asu_routing"]][[patient_type]]) }) |> - timeout(function() { + log_(function() { + # Retrieve attribute, and use to get post-ASU destination as a string + dest_index <- get_attribute(env, "post_asu_destination") + dest_names <- names(param[["asu_routing"]][[patient_type]]) + dest <- dest_names[dest_index] + # Create log message + paste0("🎯 Planned ASU -> ", dest_index, " (", dest, ")") + }) |> + set_attribute("asu_los", function() { # Retrieve attribute, and use to get post-ASU destination as a string dest_index <- get_attribute(env, "post_asu_destination") dest_names <- names(param[["asu_routing"]][[patient_type]]) @@ -59,6 +69,15 @@ create_asu_trajectory <- function(env, patient_type, param) { ) }) |> + log_(function() { + paste0("⏳ ASU length of stay: ", + round(get_attribute(env, "asu_los"), 3L)) + }) |> + + timeout(function() get_attribute(env, "asu_los")) |> + + log_("🏁 ASU stay completed") |> + # If that patient's destination is rehab, then start on that trajectory branch( option = function() { diff --git a/R/create_rehab_trajectory.R b/R/create_rehab_trajectory.R index 14fc571..7459137 100644 --- a/R/create_rehab_trajectory.R +++ b/R/create_rehab_trajectory.R @@ -13,7 +13,7 @@ #' probability of routing to each destination (e.g. #' \code{param$rehab_routing$stroke$esd = 0.40}). #' -#' @importFrom simmer trajectory +#' @importFrom simmer get_attribute log_ set_attribute timeout trajectory #' @importFrom stats rlnorm #' #' @return Simmer trajectory object. Defines patient journey logic through the @@ -25,13 +25,23 @@ create_rehab_trajectory <- function(env, patient_type, param) { # Set up simmer trajectory object... trajectory(paste0("rehab_", patient_type, "_path")) |> + log_("🚶 Arrived at rehab") |> + # Sample destination after rehab (as destination influences length of stay) set_attribute("post_rehab_destination", function() { sample_routing(prob_list = param[["rehab_routing"]][[patient_type]]) }) |> - timeout(function() { + log_(function() { + # Retrieve attribute, and use to get post-rehab destination as a string + dest_index <- get_attribute(env, "post_rehab_destination") + dest_names <- names(param[["rehab_routing"]][[patient_type]]) + dest <- dest_names[dest_index] + # Create log message + paste0("🎯 Planned rehab -> ", dest_index, " (", dest, ")") + }) |> + set_attribute("rehab_los", function() { # Retrieve attribute, and use to get post-rehab destination as a string dest_index <- get_attribute(env, "post_rehab_destination") dest_names <- names(param[["rehab_routing"]][[patient_type]]) @@ -56,5 +66,14 @@ create_rehab_trajectory <- function(env, patient_type, param) { meanlog = los_params[["meanlog"]], sdlog = los_params[["sdlog"]] ) - }) + }) |> + + log_(function() { + paste0("⏳ Rehab length of stay: ", + round(get_attribute(env, "rehab_los"), 3L)) + }) |> + + timeout(function() get_attribute(env, "rehab_los")) |> + + log_("🏁 Rehab stay completed") } diff --git a/R/model.R b/R/model.R index 060aaba..4efea74 100644 --- a/R/model.R +++ b/R/model.R @@ -26,8 +26,8 @@ model <- function(run_number, param, set_seed = TRUE) { param[["asu_los_lnorm"]] <- transform_to_lnorm(param[["asu_los"]]) param[["rehab_los_lnorm"]] <- transform_to_lnorm(param[["rehab_los"]]) - # Create simmer environment - env <- simmer("simulation", verbose = verbose) + # Create simmer environment - set verbose to FALSE as using custom logs + env <- simmer("simulation", verbose = FALSE) # Add ASU and rehab direct admission patient generators for (unit in c("asu", "rehab")) { @@ -42,7 +42,7 @@ model <- function(run_number, param, set_seed = TRUE) { # Add patient generator using the created trajectory sim_log <- capture.output( - env <- add_patient_generator( + env <- add_patient_generator( # nolint env = env, trajectory = traj, unit = unit, @@ -55,7 +55,7 @@ model <- function(run_number, param, set_seed = TRUE) { # Run the model sim_log <- capture.output( - env <- env |> + env <- env |> # nolint simmer::run(20L) |> wrap() )