Skip to content

Commit b0dc180

Browse files
authored
Merge pull request #7 from pythonhealthdatascience/defaults
feat(defaults)+style(notebooks): extract parameter list within model(), and set .Rmd output as github_document
2 parents bb9fc38 + d5ee5e6 commit b0dc180

24 files changed

+1489
-4710
lines changed

.Rbuildignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
^\.github$
1010
^\.lintr$
1111
^outputs$
12-
^notebooks$
12+
^rmarkdown$
1313
^CITATION\.cff$

.github/workflows/R-CMD-check.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
push:
55
branches: [main, master]
66
pull_request:
7+
workflow_dispatch:
78

89
name: R-CMD-check.yaml
910

.github/workflows/lint.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
on:
55
push:
6+
branches: [main]
7+
pull_request:
68
workflow_dispatch:
79

810
name: lint
@@ -30,6 +32,6 @@ jobs:
3032
run: lintr::lint_package()
3133
shell: Rscript {0}
3234

33-
- name: Lint notebooks
34-
run: lintr::lint_dir("notebooks")
35+
- name: Lint rmarkdown
36+
run: lintr::lint_dir("rmarkdown")
3537
shell: Rscript {0}

NAMESPACE

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
export(Defaults)
44
export(defaults)
5-
export(get_param)
65
export(model)
76
export(process_replications)
87
export(trial)

R/defaults.R

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -92,25 +92,11 @@ Defaults <- R6Class( # nolint
9292
#' `defaults()` is a wrapper which enables us to create a new instance of
9393
#' the class without needing to run `Defaults[["new"]]()` every time.
9494
#'
95+
#' @return Instance of the Defaults class.
96+
#'
9597
#' @export
9698
#' @rdname defaults
9799

98100
defaults <- function() {
99101
return(Defaults[["new"]]())
100102
}
101-
102-
#' Wrapper for Defaults() R6 class, to get the list of parameters.
103-
#'
104-
#' `get_param()` is a wrapper which enables us to extract the list of
105-
#' parameters from the class more easily. For example, if we create
106-
#' `param_class <- defaults()`, we can then run `get_param(param_class)`
107-
#' instead of `param_class[["get]]()`.
108-
#'
109-
#' @param param_class Instance of the Defaults parameter class.
110-
#'
111-
#' @export
112-
#' @rdname defaults
113-
114-
get_param <- function(param_class) {
115-
return(param_class[["get"]]())
116-
}

R/model.R

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#' Run simulation
22
#'
33
#' @param run_number Integer representing index of current simulation run.
4-
#' @param param List containing parameters for the simulation.
4+
#' @param param_class Instance of Defaults containing model parameters.
55
#'
66
#' @importFrom simmer trajectory seize timeout release simmer add_resource
77
#' @importFrom simmer add_generator run wrap get_mon_arrivals
@@ -12,7 +12,14 @@
1212
#' @return Named list with two tables: monitored arrivals and resources
1313
#' @export
1414

15-
model <- function(run_number, param) {
15+
model <- function(run_number, param_class) {
16+
17+
# Extract parameter list from the parameter class
18+
# It is important to do this within the model function (rather than
19+
# beforehand), to ensure any updates to the parameter list undergo
20+
# checks from the Defaults R6 class (i.e. ensuring they are replacing
21+
# existing keys in the list)
22+
param <- param_class[["get"]]()
1623

1724
# Check all inputs are valid
1825
valid_inputs(run_number, param)

R/trial.R

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,35 @@
44
#' `mcLapply`` does not work on Windows and `future_lapply`` would often get
55
#' stuck.
66
#'
7-
#' @param param List containing parameters for the simulations.
7+
#' @param param_class Instance of Defaults containing model parameters.
88
#'
99
#' @importFrom parallel detectCores makeCluster stopCluster clusterEvalQ
1010
#' @importFrom parallel clusterExport parLapply
1111
#'
1212
#' @return Named list with two tables: monitored arrivals and resources.
1313
#' @export
1414

15-
trial <- function(param) {
16-
if (param[["cores"]] == 1L) {
15+
trial <- function(param_class) {
16+
# Get specified number of cores
17+
n_cores <- param_class[["get"]]()[["cores"]]
18+
n_runs <- param_class[["get"]]()[["number_of_runs"]]
19+
20+
if (n_cores == 1L) {
1721

1822
# Sequential execution
1923
results <- lapply(
20-
1L:param[["number_of_runs"]],
21-
function(i) simulation::model(run_number = i, param = param)
24+
1L:n_runs,
25+
function(i) simulation::model(run_number = i, param_class = param_class)
2226
)
2327

2428
} else {
2529
# Parallel execution
2630

2731
# Create a cluster with specified number of cores
28-
if (param[["cores"]] == -1L) {
32+
if (n_cores == -1L) {
2933
cores <- detectCores() - 1L
3034
} else {
31-
cores <- param[["cores"]]
35+
cores <- n_cores
3236
}
3337
cl <- makeCluster(cores)
3438

@@ -37,13 +41,13 @@ trial <- function(param) {
3741

3842
# Run simulations in parallel
3943
results <- parLapply(
40-
cl, 1L:param[["number_of_runs"]],
41-
function(i) simulation::model(run_number = i, param = param)
44+
cl, 1L:n_runs,
45+
function(i) simulation::model(run_number = i, param_class = param_class)
4246
)
4347
}
4448

4549
# Combine the results from multiple replications into just two dataframes
46-
if (param[["number_of_runs"]] > 1L) {
50+
if (n_runs > 1L) {
4751
all_arrivals <- do.call(
4852
rbind, lapply(results, function(x) x[["arrivals"]])
4953
)

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ This repository provides a template for building discrete-event simulation (DES)
4646

4747
**Design practices:** Functions are documented with `roxygen2` docstrings and `lintr` is used to lint `.R` and `.Rmd` files.
4848

49-
🧱 **Package structure:** The simulation code (`R/`) is structured as a little local R package. It is installed in our environment using `devtools::install()` and then `library(simulation)`. This means it can easily be used anywhere else in the directory - here, in `notebooks/` and `tests/` - without needing any additional code (e.g. no need to run `source()` with paths to the files).
49+
🧱 **Package structure:** The simulation code (`R/`) is structured as a little local R package. It is installed in our environment using `devtools::install()` and then `library(simulation)`. This means it can easily be used anywhere else in the directory - here, in `rmarkdown/` and `tests/` - without needing any additional code (e.g. no need to run `source()` with paths to the files).
5050

5151
<details markdown="1">
5252
<summary><b>More information about the package structure</b></summary>
@@ -57,7 +57,7 @@ This repository provides a template for building discrete-event simulation (DES)
5757

5858
* Encourages well-organised repository following **standardised** established R package structure, which ensures that the model and analysis code are kept seperate.
5959
* Useful "built-in" features like **tests**, documentation of functions using **Roxygen**, documentation of data, and **package checks** (e.g. checking all imports are declared).
60-
* If your analysis has a short run time, the `.Rmd` files could be stored in a `vignettes/` folder which will mean they **re-run with every package build/check**, and so any new run issues will be identified. However, in this project, the analysis was instead stored in `notebooks/` as the file paths to save outputs cause errors in `vignettes/` (as they will differ between your runs of the notebook, and runs during the package build process).
60+
* If your analysis has a short run time, the `.Rmd` files could be stored in a `vignettes/` folder which will mean they **re-run with every package build/check**, and so any new run issues will be identified. However, in this project, the analysis was instead stored in `rmarkdown/` as the file paths to save outputs cause errors in `vignettes/` (as they will differ between your runs of the notebook, and runs during the package build process).
6161
* Meet packaging **requirement** on the NHS "Levels of RAP" framework.
6262

6363
For more information on the rationale behind structuring research as an R package, check out:
@@ -156,7 +156,7 @@ sudo apt install libglpk-dev libxml2-dev
156156

157157
🔎 Choose your desired licence (e.g. <https://choosealicense.com/>). If keeping an MIT licence, just modify the copyright holder in `LICENSE` and `LICENSE.md`.
158158

159-
🔎 Review the example DES implementation in `R/` and `notebooks/`. Modify and extend the code as needed for your specific use case.
159+
🔎 Review the example DES implementation in `R/` and `rmarkdown/`. Modify and extend the code as needed for your specific use case.
160160

161161
🔎 Check you still fulfil the criteria in `docs/nhs_rap.md` and `docs/heather_2025.md`.
162162

@@ -188,10 +188,10 @@ You can lint the `.R` and `.Rmd` files by running:
188188

189189
```
190190
lintr::lint_package()
191-
lintr::lint_dir("notebooks")
191+
lintr::lint_dir("rmarkdown")
192192
```
193193

194-
The `lint_package()` function will run on files typically included in a package (i.e. `R/`, `tests/`). This will not include `notebooks/` as it is not typical/excluded from our package build, and so we can lint that by specifying the directory for `lint_dir()`.
194+
The `lint_package()` function will run on files typically included in a package (i.e. `R/`, `tests/`). This will not include `rmarkdown/` as it is not typical/excluded from our package build, and so we can lint that by specifying the directory for `lint_dir()`.
195195

196196
<br>
197197

@@ -211,10 +211,10 @@ repo/
211211
├── docs/ # Documentation
212212
├── images/ # Image files and GIFs
213213
├── man/ # Function documentation generated by roxygen
214-
├── notebooks/ # Run DES model and analyse results
215214
├── outputs/ # Folder to save any outputs from model
216215
├── R/ # Local package containing code for the DES model
217216
├── renv/ # Instructions for creation of R environment
217+
├── rmarkdown/ # .Rmd files to run DES model and analyse results
218218
├── tests/ # Unit and back testing of the DES model
219219
├── .gitignore # Untracked files
220220
├── .lintr # Lintr settings
@@ -236,7 +236,7 @@ repo/
236236

237237
## ⏰ Run time and machine specification
238238

239-
The overall run time will vary depending on how the template model is used. A few example implementations are provided in `notebooks/` and the run times for these were:
239+
The overall run time will vary depending on how the template model is used. A few example implementations are provided in `rmarkdown/` and the run times for these were:
240240

241241
* `analysis.Rmd`: 42s
242242
* `choosing_parameters.Rmd`: 56s

man/defaults.Rd

Lines changed: 2 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/model.Rd

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)