Skip to content

Commit

Permalink
Improve Reproducibility(#470)
Browse files Browse the repository at this point in the history
  • Loading branch information
gowerc authored Jan 13, 2025
1 parent 7d42cdb commit 994bb0f
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 1 deletion.
23 changes: 22 additions & 1 deletion R/utilities.R
Original file line number Diff line number Diff line change
Expand Up @@ -556,11 +556,30 @@ clear_model_cache <- function(cache_dir = getOption("rbmi.cache_dir")) {
unlink(files)
}


#' Get Compiled Stan Object
#'
#' Gets a compiled Stan object that can be used with `rstan::sampling()`
#' @keywords internal
get_stan_model <- function() {

# Compiling Stan models updates the current seed state. This can lead to
# non-reproducibility as compiling is conditional on wether there is a cached
# model available or not. Thus we save the current seed state and restore it
# at the end of this function so that it is in the same state regardless of
# whether the model was compiled or not.
# See https://github.com/insightsengineering/rbmi/issues/469
# Note that .Random.seed is only set if the seed has been set or if a random number
# has been generated.
current_seed_state <- globalenv()$.Random.seed
on.exit({
if (is.null(current_seed_state) && exists(".Random.seed", envir = globalenv())) {
rm(".Random.seed", envir = globalenv(), inherits = FALSE)
} else {
assign(".Random.seed", value = current_seed_state, envir = globalenv(), inherits = FALSE)
}
})

ensure_rstan()
local_file <- file.path("inst", "stan", "MMRM.stan")
system_file <- system.file(file.path("stan", "MMRM.stan"), package = "rbmi")
Expand All @@ -580,11 +599,13 @@ get_stan_model <- function() {
file.copy(file_loc, model_file, overwrite = TRUE)
}

rstan::stan_model(
model <- rstan::stan_model(
file = model_file,
auto_write = TRUE,
model_name = "rbmi_mmrm"
)

return(model)
}


Expand Down
74 changes: 74 additions & 0 deletions tests/testthat/test-reproducibility.R
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,77 @@ test_that("bayes - set.seed produces identical results", {
})
expect_equal(x$samples, y$samples)
})


test_that("Results are if model is recompiled", {

skip_if_not(is_full_test())

run_test <- function() {
set.seed(4642)
sigma <- as_vcov(c(2, 1, 0.7), c(0.5, 0.3, 0.2))
dat <- get_sim_data(40, sigma, trt = 8) %>%
mutate(outcome = if_else(rbinom(n(), 1, 0.3) == 1, NA_real_, outcome))

dat_ice <- dat %>%
group_by(id) %>%
arrange(id, visit) %>%
filter(is.na(outcome)) %>%
slice(1) %>%
ungroup() %>%
select(id, visit) %>%
mutate(strategy = "JR")

vars <- set_vars(
outcome = "outcome",
group = "group",
strategy = "strategy",
subjid = "id",
visit = "visit",
covariates = c("age", "sex", "visit * group")
)

vars2 <- vars
vars2$covariates <- c("age", "sex")

set.seed(984)
drawobj <- suppressWarnings({
draws(
data = dat,
data_ice = dat_ice,
vars = vars,
method = method_bayes(n_samples = 20),
quiet = TRUE
)
})
imputeobj <- impute(draws = drawobj, references = c("A" = "B", "B" = "B"))
anaobj <- analyse(imputeobj, fun = rbmi::ancova, vars = vars2)
poolobj <- pool(results = anaobj)

## Tidy up things that will never be the same:
drawobj$formula <- NULL # Formulas contain environments specific to their build
drawobj$fit <- NULL # Bayes object has "fit" which contains a timestamp
anaobj$call <- NULL # Argument names are different (imputeobj2)

return(list(
draws = drawobj,
impute = imputeobj,
analyse = anaobj,
pool = poolobj
))
}

old_cache <- options("rbmi.cache_dir")
tmp_dir <- tempfile(tmpdir = tempdir(check = TRUE))
dir.create(tmp_dir)
options("rbmi.cache_dir" = tmp_dir)
results_no_cache <- run_test()
results_cache <- run_test() # Now rerun but using the same cache
options("rbmi.cache_dir" = old_cache)

expect_equal(results_no_cache$draws, results_cache$draws)
expect_equal(results_no_cache$impute, results_cache$impute)
expect_equal(results_no_cache$analyse, results_cache$analyse)
expect_equal(results_no_cache$pool, results_cache$pool)

})

0 comments on commit 994bb0f

Please sign in to comment.