Skip to content

Commit

Permalink
Issue #362: Reduce dependence on cmdstanr (#424)
Browse files Browse the repository at this point in the history
* Switch default to rstan rather than cmdstanr

* Import BH

* Use match.arg as suggested by @jamesmbaazam

* Add RcppEigen to Suggests

* Change backend to cmdstanr in approximate inference vignette

* Use cmdstanr for Laplace test

* Remove erroneous output_dir arg

* drop backend entirely as an arg

* remove cmdstanr using vignettes from cran check

* update cmdstan install instructions

* update epidist docs

* update approx-inference vignette to make it clear we are using cmdstanr and not rstan

* switch ebola vignette over to cmdstanr

* update test fit returns

* update more fit uses in test

* fix helper function

* bring silence to laplace

* fix epidist

* get tests passing

* fix CRAN check

* use fewer cores

* drop additional deps

* drop duplicate prepping

* try and use linking with instead of imports

* Update vignettes/epidist.Rmd

Co-authored-by: Adam Howes <[email protected]>

* Update tests/testthat/test-int-latent_individual.R

Co-authored-by: Adam Howes <[email protected]>

* Update inst/generate_examples.R

Co-authored-by: Adam Howes <[email protected]>

---------

Co-authored-by: Sam <[email protected]>
  • Loading branch information
athowes and seabbs authored Nov 14, 2024
1 parent c4913af commit 4afb056
Show file tree
Hide file tree
Showing 38 changed files with 202 additions and 236 deletions.
4 changes: 3 additions & 1 deletion .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@
^doc$
^Meta$
README.Rmd
^pkgdown$
^pkgdown$
^vignettes/approx-inference\.Rmd$
^vignettes/ebola\.Rmd$
6 changes: 5 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Imports:
stats,
cli,
checkmate,
rstan,
rstan (>= 2.26.0),
dplyr
Suggests:
bookdown,
Expand All @@ -52,6 +52,10 @@ Suggests:
patchwork,
cmdstanr,
priorsense
LinkingTo:
BH (>= 1.66.0),
Rcpp (>= 0.12.0),
RcppEigen (>= 0.3.3.3.0)
Additional_repositories:
https://stan-dev.r-universe.dev
Config/Needs/website:
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@ importFrom(dplyr,filter)
importFrom(dplyr,mutate)
importFrom(dplyr,select)
importFrom(stats,as.formula)
importFrom(stats,setNames)
11 changes: 4 additions & 7 deletions R/fit.R → R/epidist.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,15 @@
#' @param prior One or more `brmsprior` objects created by [brms::set_prior()]
#' or related functions. These priors are passed to [epidist_prior()] in the
#' `prior` argument.
#' @param backend Character string naming the package to use as the backend for
#' fitting the Stan model. Options are `"rstan"` and `"cmdstanr"` (the default).
#' This option is passed directly through to `fn`.
#' @param fn The internal function to be called. By default this is
#' [brms::brm()] which performs inference for the specified model. Other options
#' are [brms::make_stancode()] which returns the Stan code for the specified
#' model, or [brms::make_standata()] which returns the data passed to Stan.
#' These two later options may be useful for model debugging and extensions.
#' @param ... Additional arguments passed to method.
#' @param ... Additional arguments passed to `fn` method.
#' @family fit
#' @export
epidist <- function(data, formula, family, prior, backend, fn, ...) {
epidist <- function(data, formula, family, prior, fn, ...) {
UseMethod("epidist")
}

Expand All @@ -38,7 +35,7 @@ epidist <- function(data, formula, family, prior, backend, fn, ...) {
#' @export
epidist.default <- function(data, formula = mu ~ 1,
family = "lognormal", prior = NULL,
backend = "cmdstanr", fn = brms::brm, ...) {
fn = brms::brm, ...) {
epidist_validate_model(data)
epidist_family <- epidist_family(data, family)
epidist_formula <- epidist_formula(
Expand All @@ -52,7 +49,7 @@ epidist.default <- function(data, formula = mu ~ 1,
)
fit <- fn(
formula = epidist_formula, family = epidist_family, prior = epidist_prior,
stanvars = epidist_stancode, backend = backend, data = data, ...
stanvars = epidist_stancode, data = data, ...
)
class(fit) <- c(class(fit), "epidist_fit")
return(fit)
Expand Down
1 change: 1 addition & 0 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
#' @param new_names ...
#' @param old_names ...
#' @keywords internal
#' @importFrom stats setNames
.rename_columns <- function(df, new_names, old_names) {
are_char <- is.character(new_names) & is.character(old_names)
valid_new_names <- new_names[are_char]
Expand Down
14 changes: 5 additions & 9 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,16 @@ remotes::install_github(

</details>

<details><summary>Installing CmdStan</summary>
<details><summary>Installing CmdStan (optional)</summary>

If you wish to do model fitting, you will need to install [CmdStan](https://mc-stan.org/users/interfaces/cmdstan), which also entails having a suitable C++ toolchain setup. We recommend using the [`cmdstanr` package](https://mc-stan.org/cmdstanr/). The Stan team provides instructions in the [_Getting started with
By default `epidist` uses the `rstan` package for fitting models. If you wish to use the `cmdstanr` package instead, you will need to install [CmdStan](https://mc-stan.org/users/interfaces/cmdstan), which also entails having a suitable C++ toolchain setup. We recommend using the [`cmdstanr` package](https://mc-stan.org/cmdstanr/) to manage CmdStan. The Stan team provides instructions in the [_Getting started with
`cmdstanr`_](https://mc-stan.org/cmdstanr/articles/cmdstanr.html) vignette, with other details and support at the [package site](https://mc-stan.org/cmdstanr/), but the brief version is:

```{r, eval = FALSE}
# if you not yet installed `epidist`, or you installed it without `Suggests` dependencies
install.packages("cmdstanr", repos = c("https://mc-stan.org/r-packages/", getOption("repos")))
install.packages(
"cmdstanr", repos = c("https://mc-stan.org/r-packages/", getOption("repos"))
)
# once `cmdstanr` is installed:
cmdstanr::install_cmdstan()
```
Expand All @@ -92,12 +94,6 @@ cmdstanr::install_cmdstan()

</details>

<!-- <details><summary>Alternative: Docker</summary> -->

<!-- We also provide a [Docker](https://www.docker.com/get-started/) image with [all dependencies installed](https://github.com/orgs/epinowcast/packages/container/package/epidist). You can use this image to run `epidist` without installing dependencies. -->

<!-- </details> -->

## Resources

<details><summary>Organisation Website</summary>
Expand Down
10 changes: 1 addition & 9 deletions inst/generate_examples.R
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
source("tests/testthat/setup.R")
set.seed(1)
prep_obs <- as_latent_individual(sim_obs)
fit <- epidist(prep_obs, seed = 1)

saveRDS(fit, "inst/extdata/fit.rds")
prep_obs_gamma <- as_latent_individual(sim_obs_gamma)
fit_gamma <- epidist(
prep_obs_gamma,
family = stats::Gamma(link = "log"),
seed = 1
)
saveRDS(fit_gamma, "inst/extdata/fit_gamma.rds")
10 changes: 3 additions & 7 deletions man/epidist.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 2 additions & 7 deletions man/epidist.default.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/epidist_family.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/epidist_family_model.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/epidist_family_model.default.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/epidist_family_prior.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/epidist_family_prior.default.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/epidist_family_prior.lognormal.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/epidist_family_reparam.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/epidist_family_reparam.default.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/epidist_family_reparam.gamma.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/epidist_formula.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/epidist_formula_model.default.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/epidist_model_prior.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/epidist_model_prior.default.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/epidist_stancode.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/epidist_stancode.default.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions tests/testthat/helper-functions.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
on_ci <- function() {
isTRUE(as.logical(Sys.getenv("CI")))
}

not_on_cran <- function() {
identical(Sys.getenv("NOT_CRAN"), "true")
}

skip_on_local <- function() {
if (on_ci()) {
return(invisible(TRUE))
}
testthat::skip("Not on CI")
}

as_string_formula <- function(formula) {
form <- paste(deparse(formula), collapse = " ")
form <- gsub("\\s+", " ", form, perl = FALSE)
return(form)
}

extract_normal_parameters_brms <- function(prior) {
pattern <- "normal\\(([^,]+), ([^\\)]+)\\)"
match <- regmatches(prior, regexec(pattern, prior))
mean <- as.numeric(match[[1]][2])
sd <- as.numeric(match[[1]][3])
return(list(mean = mean, sd = sd))
}
29 changes: 29 additions & 0 deletions tests/testthat/setup.R
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,32 @@ sim_obs_sex <- dplyr::bind_rows(sim_obs_sex_m, sim_obs_sex_f) |>

# Temporary solution for classing time data
sim_obs_sex <- as_epidist_linelist_time(sim_obs_sex)

prep_obs <- as_latent_individual(sim_obs)
prep_direct_obs <- as_direct_model(sim_obs)
prep_obs_gamma <- as_latent_individual(sim_obs_gamma)
prep_obs_sex <- as_latent_individual(sim_obs_sex)

if (not_on_cran()) {
set.seed(1)
fit <- epidist(
data = prep_obs, seed = 1, chains = 2, cores = 2, silent = 2, refresh = 0,
backend = "cmdstanr"
)
fit_rstan <- epidist(
data = prep_obs, seed = 1, chains = 2, cores = 2, silent = 2, refresh = 0
)

fit_gamma <- epidist(
data = prep_obs_gamma, family = stats::Gamma(link = "log"),
seed = 1, chains = 2, cores = 2, silent = 2, refresh = 0,
backend = "cmdstanr"
)

fit_sex <- epidist(
data = prep_obs_sex,
formula = brms::bf(mu ~ 1 + sex, sigma ~ 1 + sex),
seed = 1, silent = 2, refresh = 0,
cores = 2, chains = 2, backend = "cmdstanr"
)
}
Loading

0 comments on commit 4afb056

Please sign in to comment.