├── .Rbuildignore ├── .github ├── CONTRIBUTING.md ├── FUNDING.yml └── workflows │ ├── check-standalone.yaml │ └── check-standard.yaml ├── .gitignore ├── CRAN-SUBMISSION ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── NEWS.md ├── R ├── bayes_R2.R ├── init_cpp.R ├── log_lik.R ├── loo-functions.R ├── nsamples.R ├── posterior_epred.R ├── posterior_interval.R ├── posterior_linpred.R ├── posterior_predict.R ├── predictive_error.R ├── predictive_interval.R ├── prior_summary.R ├── rstan_config.R ├── rstan_create_package.R ├── rstan_package_utils.R ├── rstantools-package.R ├── update_description.R ├── use_rstan.R └── zzz.R ├── README.md ├── inst └── include │ └── sys │ ├── DESCRIPTION │ ├── Makevars │ ├── Makevars.win │ ├── Read_and_delete_me │ ├── configure │ ├── configure.win │ ├── lice_nse.stan │ ├── rstanpkg-package.R │ ├── stan_meta_header.hpp │ ├── stanmodels.R │ └── travis.yml ├── man-roxygen ├── args-auto_config.R ├── args-dots.R ├── args-license.R ├── args-object.R ├── args-pkgdir.R ├── details-auto_config.R ├── details-license.R ├── reference-randomised-pit.R ├── section-running-stan.R ├── seealso-get-help.R ├── seealso-rstanarm-pkg.R └── seealso-vignettes.R ├── man ├── bayes_R2.Rd ├── figures │ ├── logo.svg │ └── stanlogo.png ├── init_cpp.Rd ├── log_lik.Rd ├── loo-prediction.Rd ├── nsamples.Rd ├── posterior_epred.Rd ├── posterior_interval.Rd ├── posterior_linpred.Rd ├── posterior_predict.Rd ├── predictive_error.Rd ├── predictive_interval.Rd ├── prior_summary.Rd ├── rstan_config.Rd ├── rstan_create_package.Rd ├── rstantools-package.Rd ├── rstantools_load_code.Rd └── use_rstan.Rd ├── rstantools.Rproj ├── tests ├── testthat.R └── testthat │ ├── RStanTest │ ├── AddTest.cpp │ ├── NAMESPACE │ ├── RStanTest-package.R │ ├── SimpleModel.stan │ ├── SimpleModel2.stan │ ├── helper.stan │ ├── postsamp.R │ ├── stanExports_SimpleModel.cc │ ├── stanExports_SimpleModel.h │ ├── stanExports_SimpleModel2.cc │ ├── stanExports_SimpleModel2.h │ ├── test-add_test.R │ ├── test-postsamp.R │ └── test-rstan_package_skeleton_plus.R │ ├── bayes_R2.RDS │ ├── loo_pit.RDS │ ├── loo_pit_discrete.RDS │ ├── posterior_interval.RDS │ ├── predictive_error.RDS │ ├── predictive_interval.RDS │ ├── rstan_package_skeleton-testfunctions.R │ ├── test-default-methods.R │ ├── test-generics-with-no-methods.R │ ├── test-rstan_config.R │ ├── test-rstan_create_package.R │ └── test.stan └── vignettes ├── developer-guidelines.Rmd └── minimal-rstan-package.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^Meta$ 2 | ^doc$ 3 | ^.*\.Rproj$ 4 | ^\.Rproj\.user$ 5 | LICENSE 6 | ^\.travis\.yml$ 7 | ^README\.md$ 8 | ^README_package_skeleton\.md$ 9 | .gitignore 10 | ^cran-comments\.md$ 11 | ^revdep$ 12 | man-roxygen/* 13 | vignettes/rstanlm 14 | ^CRAN-RELEASE$ 15 | .github/* 16 | rstanlm 17 | ^CRAN-SUBMISSION$ 18 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to rstantools 2 | 3 | This outlines how to propose a change to rstantools and is based on similar 4 | instructions for tidyverse packages, including the contributing guidelines 5 | generated by `usethis::use_tidy_contributing()`. 6 | 7 | ## Fixing typos 8 | 9 | You can fix typos, spelling mistakes, or grammatical errors in the documentation 10 | directly using the GitHub web interface, as long as the changes are made in the 11 | _source_ file. This generally means you'll need to edit 12 | [roxygen2 comments](https://roxygen2.r-lib.org/articles/roxygen2.html) in an `.R`, 13 | not a `.Rd` file. You can find the `.R` file that generates the `.Rd` by reading 14 | the comment in the first line. 15 | 16 | ## Bigger changes 17 | 18 | If you want to make a bigger change, it's a good idea to first file an issue and 19 | make sure someone from the team agrees that it’s needed. If you’ve found a bug, 20 | please file an issue that illustrates the bug with a minimal reproducible 21 | example (see e.g. the [tidyverse reprex instructions](https://www.tidyverse.org/help/#reprex)). 22 | The tidyverse guide on [how to create a great issue](https://code-review.tidyverse.org/issues/) 23 | has more advice. 24 | 25 | ### Pull request process 26 | 27 | If you are new to creating pull requests here are some tips. Using the functions 28 | from the `usethis` package is not required but can be helpful if this process is 29 | new to you. 30 | 31 | * Fork the package and clone onto your computer. If you haven't done this before, we recommend using `usethis::create_from_github("stan-dev/rstantools", fork = TRUE)`. 32 | 33 | * Install all development dependencies with `devtools::install_dev_deps()`, and then make sure the package passes R CMD check by running `devtools::check()`. 34 | If R CMD check doesn't pass cleanly, it's a good idea to ask for help before continuing. 35 | * Create a Git branch for your pull request (PR). We recommend using `usethis::pr_init("brief-description-of-change")`. 36 | 37 | * Make your changes, commit to git, and then create a PR by running `usethis::pr_push()`, and following the prompts in your browser. 38 | The title of your PR should briefly describe the change. 39 | The body of your PR should contain `Fixes #issue-number`. 40 | 41 | * For user-facing changes, add a bullet to the top of `NEWS.md` (i.e. just below the first header). Follow the style already used in `NEWS.md`. 42 | 43 | ### Code style 44 | 45 | * New code should attempt to follow the style used in the package. When in doubt follow the tidyverse [style guide](https://style.tidyverse.org). 46 | 47 | * We use [roxygen2](https://cran.r-project.org/package=roxygen2), with [Markdown syntax](https://cran.r-project.org/web/packages/roxygen2/vignettes/rd-formatting.html), for documentation. 48 | 49 | * We use [testthat](https://cran.r-project.org/package=testthat) for unit tests. 50 | Contributions with test cases included are easier to accept. 51 | 52 | ## Code of Conduct 53 | 54 | Please note that the rstantools project follows the Stan project's 55 | [Code of Conduct](https://discourse.mc-stan.org/t/announcing-our-new-stan-code-of-conduct/23764). 56 | By contributing to this project you agree to abide by its terms. 57 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: stan-dev 2 | custom: https://mc-stan.org/support/ 3 | -------------------------------------------------------------------------------- /.github/workflows/check-standalone.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/master/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: Stanfunctions Support 10 | 11 | jobs: 12 | stanfunctions-support: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 22 | - {os: ubuntu-latest, r: 'release'} 23 | 24 | env: 25 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 26 | R_KEEP_PKG_SOURCE: yes 27 | 28 | steps: 29 | - uses: actions/checkout@v3 30 | 31 | - uses: r-lib/actions/setup-pandoc@v2 32 | 33 | - uses: r-lib/actions/setup-r@v2 34 | with: 35 | r-version: ${{ matrix.config.r }} 36 | http-user-agent: ${{ matrix.config.http-user-agent }} 37 | use-public-rspm: true 38 | 39 | - uses: r-lib/actions/setup-r-dependencies@v2 40 | with: 41 | extra-packages: local::. rcmdcheck BH RcppParallel RcppEigen Rcpp rstan StanHeaders RCurl remotes V8 42 | 43 | - name: Checkout lgpr package 44 | run: | 45 | git clone https://github.com/jtimonen/lgpr 46 | 47 | - name: Check against CRAN StanHeaders and CRAN RStan 48 | run: | 49 | rcmdcheck::rcmdcheck(path = "lgpr", args = c("--no-manual", "--as-cran"), build_args = "--no-manual") 50 | shell: Rscript {0} 51 | 52 | - name: Install Development StanHeaders and CRAN RStan 53 | run: | 54 | Sys.setenv(MAKEFLAGS=paste0("-j",parallel::detectCores())) 55 | install.packages("StanHeaders", repos = c("https://mc-stan.org/r-packages/", getOption("repos"))) 56 | install.packages('rstan', type='source') 57 | shell: Rscript {0} 58 | 59 | - name: Check against Development StanHeaders and CRAN RStan 60 | run: | 61 | rcmdcheck::rcmdcheck(path = "lgpr", args = c("--no-manual", "--as-cran"), build_args = "--no-manual") 62 | shell: Rscript {0} 63 | 64 | - name: Install Development StanHeaders and Development RStan 65 | run: | 66 | Sys.setenv(MAKEFLAGS=paste0("-j",parallel::detectCores())) 67 | install.packages("StanHeaders", repos = c("https://mc-stan.org/r-packages/", getOption("repos"))) 68 | install.packages("rstan", repos = c("https://mc-stan.org/r-packages/", getOption("repos"))) 69 | shell: Rscript {0} 70 | 71 | - name: Check against Development StanHeaders and Development RStan 72 | run: | 73 | rcmdcheck::rcmdcheck(path = "lgpr", args = c("--no-manual", "--as-cran"), build_args = "--no-manual") 74 | shell: Rscript {0} 75 | 76 | - name: Checkout RStan Experimental branch 77 | uses: actions/checkout@v3 78 | with: 79 | repository: stan-dev/rstan 80 | ref: experimental 81 | path: rstan 82 | submodules: 'recursive' 83 | 84 | - name: Install Experimental StanHeaders and Experimental RStan 85 | run: | 86 | Sys.setenv(MAKEFLAGS=paste0("-j",parallel::detectCores())) 87 | install.packages("rstan/StanHeaders", type = "source", repos = NULL) 88 | install.packages("rstan/rstan/rstan", type = "source", repos = NULL) 89 | shell: Rscript {0} 90 | 91 | - name: Check against Experimental StanHeaders and Experimental RStan 92 | run: | 93 | rcmdcheck::rcmdcheck(path = "lgpr", args = c("--no-manual", "--as-cran"), build_args = "--no-manual") 94 | shell: Rscript {0} 95 | 96 | -------------------------------------------------------------------------------- /.github/workflows/check-standard.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/master/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - {os: macOS-latest, r: 'release'} 22 | # Vignette building hangs infinitely on Windows GHA, so disable for now 23 | #- {os: windows-latest, r: 'release'} 24 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 25 | - {os: ubuntu-latest, r: 'release'} 26 | - {os: ubuntu-latest, r: 'oldrel-1'} 27 | 28 | env: 29 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 30 | R_KEEP_PKG_SOURCE: yes 31 | 32 | steps: 33 | - uses: actions/checkout@v3 34 | 35 | - uses: r-lib/actions/setup-pandoc@v2 36 | 37 | - uses: r-lib/actions/setup-r@v2 38 | with: 39 | r-version: ${{ matrix.config.r }} 40 | http-user-agent: ${{ matrix.config.http-user-agent }} 41 | use-public-rspm: true 42 | 43 | - uses: r-lib/actions/setup-r-dependencies@v2 44 | with: 45 | extra-packages: rcmdcheck BH RcppParallel RcppEigen Rcpp rstan StanHeaders V8 46 | 47 | - name: Check against CRAN StanHeaders and CRAN RStan 48 | uses: r-lib/actions/check-r-package@v2 49 | 50 | - name: Install Development StanHeaders and CRAN RStan 51 | run: | 52 | Sys.setenv(MAKEFLAGS=paste0("-j",parallel::detectCores())) 53 | install.packages("StanHeaders", repos = c("https://mc-stan.org/r-packages/", getOption("repos"))) 54 | install.packages('rstan', type='source') 55 | shell: Rscript {0} 56 | 57 | - name: Check against Development StanHeaders and CRAN RStan 58 | uses: r-lib/actions/check-r-package@v2 59 | 60 | - name: Install Development StanHeaders and Development RStan 61 | run: | 62 | Sys.setenv(MAKEFLAGS=paste0("-j",parallel::detectCores())) 63 | install.packages("StanHeaders", repos = c("https://mc-stan.org/r-packages/", getOption("repos"))) 64 | install.packages("rstan", repos = c("https://mc-stan.org/r-packages/", getOption("repos"))) 65 | shell: Rscript {0} 66 | 67 | - name: Check against Development StanHeaders and Development RStan 68 | uses: r-lib/actions/check-r-package@v2 69 | 70 | - name: Show testthat output 71 | if: always() 72 | run: find check -name 'testthat.Rout*' -exec cat '{}' \; || true 73 | shell: bash 74 | 75 | - name: Upload check results 76 | if: failure() 77 | uses: actions/upload-artifact@main 78 | with: 79 | name: ${{ runner.os }}-r${{ matrix.config.r }}-results 80 | path: check 81 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Meta 2 | doc 3 | .Rproj.user 4 | .Rhistory 5 | .RData 6 | .Ruserdata 7 | inst/doc 8 | vignettes/rstanlm 9 | inst/include/sys/devel/ 10 | old/ 11 | 12 | tests/testthat/Rplots.pdf 13 | .DS_Store 14 | cran-comments.md 15 | /revdep/.cache.rds 16 | /revdep/ 17 | -------------------------------------------------------------------------------- /CRAN-SUBMISSION: -------------------------------------------------------------------------------- 1 | Version: 2.4.0 2 | Date: 2024-01-22 17:11:17 UTC 3 | SHA: 77fe5082f8cf826cfb42380885ea05b0d14a03e1 4 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: rstantools 2 | Type: Package 3 | Title: Tools for Developing R Packages Interfacing with 'Stan' 4 | Version: 2.4.0.9000 5 | Date: 2024-01-22 6 | Authors@R: 7 | c(person(given = "Jonah", 8 | family = "Gabry", 9 | role = c("aut", "cre"), 10 | email = "jsg2201@columbia.edu"), 11 | person(given = "Ben", 12 | family = "Goodrich", 13 | role = "aut", 14 | email = "benjamin.goodrich@columbia.edu"), 15 | person(given = "Martin", 16 | family = "Lysy", 17 | role = "aut", 18 | email = "mlysy@uwaterloo.ca"), 19 | person(given = "Andrew", 20 | family = "Johnson", 21 | role = "aut"), 22 | person(given = "Hamada S.", 23 | family = "Badr", 24 | role = "ctb"), 25 | person(given = "Marco", 26 | family = "Colombo", 27 | role = "ctb"), 28 | person(given = "Stefan", 29 | family = "Siegert", 30 | role = "ctb"), 31 | person(given = "Trustees of", 32 | family = "Columbia University", 33 | role = "cph")) 34 | Description: Provides various tools for developers of R packages interfacing 35 | with 'Stan' , including functions to set up the required 36 | package structure, S3 generics and default methods to unify function naming 37 | across 'Stan'-based R packages, and vignettes with recommendations for 38 | developers. 39 | License: GPL (>=3) 40 | URL: https://mc-stan.org/rstantools/, https://discourse.mc-stan.org/ 41 | BugReports: https://github.com/stan-dev/rstantools/issues 42 | Encoding: UTF-8 43 | LazyData: true 44 | SystemRequirements: pandoc, C++14 45 | Imports: desc, stats, utils, Rcpp (>= 0.12.16), RcppParallel (>= 5.0.1) 46 | Suggests: 47 | rstan (>= 2.17.2), 48 | usethis (>= 1.5.1), 49 | testthat (>= 2.0.0), 50 | knitr, 51 | pkgbuild, 52 | pkgload, 53 | roxygen2 (>= 6.0.1), 54 | rmarkdown, 55 | rstudioapi 56 | RoxygenNote: 7.3.0 57 | VignetteBuilder: knitr 58 | Roxygen: list(markdown = TRUE) 59 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(bayes_R2,default) 4 | S3method(loo_pit,default) 5 | S3method(posterior_interval,default) 6 | S3method(predictive_error,default) 7 | S3method(predictive_interval,default) 8 | S3method(prior_summary,default) 9 | export(bayes_R2) 10 | export(init_cpp) 11 | export(log_lik) 12 | export(loo_R2) 13 | export(loo_linpred) 14 | export(loo_pit) 15 | export(loo_predict) 16 | export(loo_predictive_interval) 17 | export(nsamples) 18 | export(posterior_epred) 19 | export(posterior_interval) 20 | export(posterior_linpred) 21 | export(posterior_predict) 22 | export(predictive_error) 23 | export(predictive_interval) 24 | export(prior_summary) 25 | export(rstan_config) 26 | export(rstan_create_package) 27 | export(rstantools_load_code) 28 | export(use_rstan) 29 | importFrom(RcppParallel,RcppParallelLibs) 30 | importFrom(stats,quantile) 31 | importFrom(stats,var) 32 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # rstantools 2.4.0.9000 2 | 3 | Items for next release go here 4 | 5 | Extended `loo_pit()` for discrete data. 6 | 7 | # rstantools 2.4.0 8 | 9 | * Update to match CRAN's patched version by @jgabry in #114 10 | * Include additional template imports to suppress NOTEs by @andrjohns in #115 11 | * Fix packages with stanfunctions under rstan 2.33+ by @andrjohns in #117 12 | 13 | 14 | # rstantools 2.3.1 15 | 16 | * Deprecated `init_cpp`. (#105) 17 | * Bugfix for standalone functions under 2.31 (#110) 18 | * Only add Makevars for current platform. (#109) 19 | * Suppress false-positive warning for standalone functions. (#111) 20 | 21 | # rstantools 2.3.0 22 | 23 | * Updated C++ standard to C++17 (#100) 24 | * Updated the handling of exporting standalone stan functions in packages for compatibility with the 2.26 (and beyond) versions of StanHeaders and rstan (#101) 25 | * Added Andrew Johnson (@andrjohns) as an author 26 | 27 | # rstantools 2.2.0 28 | 29 | (Github issue/PR numbers in parentheses) 30 | 31 | * Updated "Step by step guide" vignette with instructions for adding new Stan 32 | models to an existing R package that already has Stan models. (#79, @rerickson-usgs) 33 | 34 | * Fixed R CMD check NOTE "configure does not appear to have a #! interpreter line". (#83) 35 | 36 | * Use writeLines instead of cat to fix line endings issue reported by CRAN. (#87) 37 | 38 | * Switch to GitHub Actions for CI. (#90, @andrjohns) 39 | 40 | * Deprecate automatic creation of `.travis.yml` file. We now recommend the use 41 | of GitHub Actions. (#89) 42 | 43 | * Ensure compatibility with future versions of RStan. (#85, #94, @andrjohns, @hsbadr) 44 | 45 | 46 | # rstantools 2.1.1 47 | 48 | (Github issue/PR numbers in parentheses) 49 | 50 | * Compatibility with StanHeaders 2.21.0-5 51 | 52 | # rstantools 2.1.0 53 | 54 | * Compatibility with StanHeaders 2.21.0-3 55 | * Improve messaging around updating NAMESPACE file (#75, @mikekaminsky) 56 | * More informative error message for `rstan_create_package()` when directory 57 | already exists. (#68, @mcol) 58 | * Add generated C++ files to .gitignore and .Rbuildignore (#66, @mcol) 59 | * New generic `posterior_epred()` (#74) 60 | 61 | # rstantools 2.0.0 62 | 63 | * Added Martin Lysy as a coauthor. 64 | 65 | * New function `rstan_create_package()` (based on 66 | `usethis::create_package()`) replaces `rstan_package_skeleton()` 67 | for the purpose of starting a new package with Stan functionality. 68 | 69 | * Stan functionality can be added to an _existing_ package by calling 70 | `use_rstan()` instead of starting a new package from scratch. 71 | 72 | * Stan folder infrastructure now puts all `.stan` files in `inst/stan` and all 73 | auto-generated C++ files directly in `src`. This last step ensures that custom 74 | **Rcpp** source code can coexist with the Stan C++ code. 75 | 76 | * Each time a `.stan` file gets added/removed/modified requires a call to 77 | `rstan_config()` in order to generate the Stan C++ code and `Rcpp::loadModule()` 78 | calls. However, setting `auto_config = TRUE` (the default) in 79 | `rstan_create_package()` ensures `rstan_config()` is called whenever the package 80 | is installed (including via `devtools::load_all()`), so no need to call it 81 | manually unless the user wishes to inspect the Stan C++ code for issues. 82 | 83 | * **roxygen2** documentation is now optional, but remains the default. 84 | 85 | * Rather than generating Stan "system files" via `cat` commands, **rstantools** 86 | now stores these as template files in `inst/include/sys`, so the build process 87 | can be easily modified as improvements become apparent. 88 | 89 | 90 | # rstantools 1.5.1 91 | 92 | (Github issue/PR numbers in parentheses) 93 | 94 | * Fix issue related to changes in the **usethis** package by removing the 95 | `fields` argument to `rstan_package_skeleton()` and setting it internally 96 | instead. 97 | * New generic `nsamples()` (#35) 98 | 99 | 100 | # rstantools 1.5.0 101 | 102 | (Github issue/PR numbers in parentheses) 103 | 104 | * New [vignette](https://mc-stan.org/rstantools/articles/) walking through the package creation process. (#9) (thanks to Stefan Siegert) 105 | 106 | * `rstan_package_skeleton()` now calls `usethis::create_package()` instead of `utils::package.skeleton()`. (#28) 107 | 108 | * Update `rstan_package_skeleton()` for latest build process (#19) 109 | 110 | * `rstan_package_skeleton()` now does a bit more work for the user to make sure the the NAMESPACE file is correct. 111 | 112 | * Simplify instructions in Read-and-delete-me (related to #19). 113 | 114 | # rstantools 1.4.0 115 | 116 | (Github issue/PR numbers in parentheses) 117 | 118 | * Update `rstan_package_skeleton()` to correspond to rstanarm 2.17.2. 119 | 120 | # rstantools 1.3.0 121 | 122 | (Github issue/PR numbers in parentheses) 123 | 124 | * Add `bayes_R2()` generic and default method. (#8) 125 | 126 | # rstantools 1.2.1 127 | 128 | (Github issue/PR numbers in parentheses) 129 | 130 | * Add `init_cpp()` function for generating `src/init.cpp` in order to pass R CMD 131 | check in R 3.4.x. `rstan_package_skeleton()` calls `init_cpp()` internally. (#6) 132 | 133 | # rstantools 1.2.0 134 | 135 | (Github issue/PR numbers in parentheses) 136 | 137 | * Minor fixes to `rstan_package_skeleton()` for better Windows compatibility. (#1, #2) 138 | 139 | * Fix some typos in the developer guidelines vignette. (#3, #4) 140 | 141 | * Add `loo_predict()`, `loo_linpred()`, and `loo_predictive_interval()` generics in 142 | preparation for adding methods to the __rstanarm__ package. (#5) 143 | 144 | # rstantools 1.1.0 145 | 146 | Changes to `rstan_package_skeleton`: 147 | 148 | * Add comment in `Read-and-delete-me` about importing all of __Rcpp__ and __methods__ packages. 149 | 150 | * Include __methods__ in `Depends` field of `DESCRIPTION` file. 151 | 152 | * Also download __rstanarm__'s `Makevars.win` file. 153 | 154 | # rstantools 1.0.0 155 | 156 | * Initial CRAN release 157 | -------------------------------------------------------------------------------- /R/bayes_R2.R: -------------------------------------------------------------------------------- 1 | #' Generic function and default method for Bayesian R-squared 2 | #' 3 | #' Generic function and default method for Bayesian version of R-squared for 4 | #' regression models. A generic for LOO-adjusted R-squared is also provided. See 5 | #' the [bayes_R2.stanreg()](https://mc-stan.org/rstanarm/reference/bayes_R2.stanreg.html) 6 | #' method in the \pkg{rstanarm} package for an example of defining a method. 7 | #' 8 | #' @export 9 | #' @template args-object 10 | #' @template args-dots 11 | #' 12 | #' @return `bayes_R2()` and `loo_R2()` methods should return a vector of 13 | #' length equal to the posterior sample size. 14 | #' 15 | #' The default `bayes_R2()` method just takes `object` to be a matrix of y-hat 16 | #' values (one column per observation, one row per posterior draw) and `y` to 17 | #' be a vector with length equal to `ncol(object)`. 18 | #' 19 | #' 20 | #' @references 21 | #' Andrew Gelman, Ben Goodrich, Jonah Gabry, and Aki Vehtari (2019). R-squared 22 | #' for Bayesian regression models. *The American Statistician*, 73(3):307-309. 23 | #' DOI: 10.1080/00031305.2018.1549100. 24 | #' ([Preprint](http://www.stat.columbia.edu/~gelman/research/published/bayes_R2_v3.pdf), 25 | #' [Notebook](https://avehtari.github.io/bayes_R2/bayes_R2.html)) 26 | #' 27 | #' 28 | #' @template seealso-rstanarm-pkg 29 | #' @template seealso-vignettes 30 | #' 31 | bayes_R2 <- function(object, ...) { 32 | UseMethod("bayes_R2") 33 | } 34 | 35 | #' @rdname bayes_R2 36 | #' @export 37 | #' @param y For the default method, a vector of `y` values the same length 38 | #' as the number of columns in the matrix used as `object`. 39 | #' 40 | #' @importFrom stats var 41 | #' 42 | bayes_R2.default <- 43 | function(object, y, 44 | ...) { 45 | if (!is.matrix(object)) 46 | stop("For the default method 'object' should be a matrix.") 47 | stopifnot(NCOL(y) == 1, ncol(object) == length(y)) 48 | ypred <- object 49 | e <- -1 * sweep(ypred, 2, y) 50 | var_ypred <- apply(ypred, 1, var) 51 | var_e <- apply(e, 1, var) 52 | var_ypred / (var_ypred + var_e) 53 | } 54 | 55 | 56 | #' @rdname bayes_R2 57 | #' @export 58 | loo_R2 <- function(object, ...) { 59 | UseMethod("loo_R2") 60 | } 61 | -------------------------------------------------------------------------------- /R/init_cpp.R: -------------------------------------------------------------------------------- 1 | # Part of the rstantools package 2 | # Copyright (C) 2018 Trustees of Columbia University 3 | # 4 | # rstantools is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU General Public License 6 | # as published by the Free Software Foundation; either version 3 7 | # of the License, or (at your option) any later version. 8 | # 9 | # rstantools is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #' Register functions implemented in C++ 19 | #' 20 | #' If you set up your package using `rstan_package_skeleton()` before 21 | #' version `1.2.1` of \pkg{rstantools} it may be necessary for you to call 22 | #' this function yourself in order to pass `R CMD check` in \R 23 | #' `>= 3.4`. If you used `rstan_package_skeleton()` in \pkg{rstantools} version 24 | #' `1.2.1` or later then this has already been done automatically. 25 | #' 26 | #' @export 27 | #' @keywords internal 28 | #' @param name The name of your package as a string. 29 | #' @param path The path to the root directory for your package as a string. If 30 | #' not specified it is assumed that this is already the current working 31 | #' directory. 32 | #' @return This function is only called for its side effect of writing the 33 | #' necessary `init.cpp` file to the package's `src/` directory. 34 | #' 35 | init_cpp <- function(name, path) { 36 | .Deprecated() 37 | file <- file.path("src", "init.cpp") 38 | if (!missing(path)) 39 | file <- file.path(path, file) 40 | 41 | writeLines(c( 42 | "// Generated by the rstantools package", 43 | "", "", 44 | "#include ", 45 | "#include ", 46 | "#include ", 47 | "#include ", 48 | "#include ", 49 | "", "", 50 | "static const R_CallMethodDef CallEntries[] = {", 51 | " {NULL, NULL, 0}", 52 | "};", 53 | "", "", 54 | paste0("void attribute_visible R_init_", name, "(DllInfo *dll) {"), 55 | " // next line is necessary to avoid a NOTE from R CMD check", 56 | " R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);", 57 | " R_useDynamicSymbols(dll, TRUE); // necessary for .onLoad() to work", 58 | "}" 59 | ), 60 | con = file 61 | ) 62 | return(invisible(NULL)) 63 | } 64 | -------------------------------------------------------------------------------- /R/log_lik.R: -------------------------------------------------------------------------------- 1 | #' Generic function for pointwise log-likelihood 2 | #' 3 | #' We define a new function `log_lik()` rather than a 4 | #' [stats::logLik()] method because (in addition to the conceptual 5 | #' difference) the documentation for `logLik()` states that the return value 6 | #' will be a single number, whereas `log_lik()` returns a matrix. See 7 | #' the [log_lik.stanreg()](https://mc-stan.org/rstanarm/reference/log_lik.stanreg.html) 8 | #' method in the \pkg{rstanarm} package for an example of defining a method. 9 | #' 10 | #' @export 11 | #' @template args-object 12 | #' @template args-dots 13 | #' 14 | #' @return `log_lik()` methods should return a \eqn{S} by \eqn{N} matrix, 15 | #' where \eqn{S} is the size of the posterior sample (the number of draws from 16 | #' the posterior distribution) and \eqn{N} is the number of data points. 17 | #' 18 | #' @template seealso-rstanarm-pkg 19 | #' @template seealso-vignettes 20 | #' 21 | #' @examples 22 | #' # See help("log_lik", package = "rstanarm") 23 | #' 24 | log_lik <- function(object, ...) { 25 | UseMethod("log_lik") 26 | } 27 | -------------------------------------------------------------------------------- /R/loo-functions.R: -------------------------------------------------------------------------------- 1 | #' Generic functions for LOO predictions 2 | #' 3 | #' See the methods in the \pkg{rstanarm} package for examples. 4 | #' 5 | #' @name loo-prediction 6 | #' 7 | #' @template args-object 8 | #' @template args-dots 9 | #' 10 | #' @return `loo_predict()`, `loo_epred()`, `loo_linpred()`, and `loo_pit()` 11 | #' (probability integral transform) methods should return a vector with 12 | #' length equal to the number of observations in the data. 13 | #' For discrete observations, probability integral transform is randomised to 14 | #' ensure theoretical uniformity. Fix random seed for reproducible results 15 | #' with discrete data. For more details, see Czado et al. (2009). 16 | #' `loo_predictive_interval()` methods should return a two-column matrix 17 | #' formatted in the same way as for [predictive_interval()]. 18 | #' 19 | #' @template seealso-rstanarm-pkg 20 | #' @template seealso-vignettes 21 | #' @template reference-randomised-pit 22 | 23 | #' @rdname loo-prediction 24 | #' @export 25 | loo_linpred <- function(object, ...) { 26 | UseMethod("loo_linpred") 27 | } 28 | 29 | #' @rdname loo-prediction 30 | #' @export 31 | loo_epred <- function(object, ...) { 32 | UseMethod("loo_epred") 33 | } 34 | 35 | #' @rdname loo-prediction 36 | #' @export 37 | loo_predict <- function(object, ...) { 38 | UseMethod("loo_predict") 39 | } 40 | 41 | #' @rdname loo-prediction 42 | #' @export 43 | loo_predictive_interval <- function(object, ...) { 44 | UseMethod("loo_predictive_interval") 45 | } 46 | 47 | #' @rdname loo-prediction 48 | #' @export 49 | loo_pit <- function(object, ...) { 50 | UseMethod("loo_pit") 51 | } 52 | 53 | #' @rdname loo-prediction 54 | #' @export 55 | #' @param y For the default method of `loo_pit()`, a vector of `y` values the 56 | #' same length as the number of columns in the matrix used as `object`. 57 | #' @param lw For the default method of `loo_pit()`, a matrix of log-weights of 58 | #' the same length as the number of columns in the matrix used as `object`. 59 | #' 60 | loo_pit.default <- function(object, y, lw, ...) { 61 | if (!is.matrix(object)) 62 | stop("For the default method 'object' should be a matrix.") 63 | stopifnot( 64 | is.numeric(object), is.numeric(y), length(y) == ncol(object), 65 | is.matrix(lw), identical(dim(lw), dim(object)) 66 | ) 67 | .loo_pit(y = y, yrep = object, lw = lw) 68 | } 69 | 70 | # internal ---------------------------------------------------------------- 71 | .loo_pit <- function(y, yrep, lw) { 72 | if (is.null(lw) || !all(is.finite(lw))) { 73 | stop("lw needs to be not null and finite.") 74 | } 75 | pits <- vapply(seq_len(ncol(yrep)), function(j) { 76 | sel_min <- yrep[, j] < y[j] 77 | pit <- .exp_log_sum_exp(lw[sel_min, j]) 78 | sel_sup <- yrep[, j] == y[j] 79 | if (any(sel_sup)) { 80 | # randomized PIT for discrete y (see, e.g., Czado, C., Gneiting, T., 81 | # Held, L.: Predictive model assessment for count data. 82 | # Biometrics 65(4), 1254–1261 (2009).) 83 | pit_sup <- pit + .exp_log_sum_exp(lw[sel_sup, j]) 84 | pit <- stats::runif(1, pit, pit_sup) 85 | } 86 | pit 87 | }, FUN.VALUE = 1) 88 | if (any(pits > 1)) { 89 | warning(cat( 90 | "Some PIT values larger than 1! Largest: ", 91 | max(pits), 92 | "\nRounding PIT > 1 to 1." 93 | )) 94 | } 95 | pmin(1, pits) 96 | } 97 | 98 | .exp_log_sum_exp <- function(x) { 99 | m <- suppressWarnings(max(x)) 100 | exp(m + log(sum(exp(x - m)))) 101 | } 102 | -------------------------------------------------------------------------------- /R/nsamples.R: -------------------------------------------------------------------------------- 1 | #' Generic function for extracting the number of posterior samples 2 | #' 3 | #' @export 4 | #' @keywords internal 5 | #' @template args-object 6 | #' @template args-dots 7 | #' 8 | nsamples <- function(object, ...) { 9 | UseMethod("nsamples") 10 | } 11 | -------------------------------------------------------------------------------- /R/posterior_epred.R: -------------------------------------------------------------------------------- 1 | #' Generic function for accessing the posterior distribution of the 2 | #' conditional expectation 3 | #' 4 | #' Extract the posterior draws of the conditional expectation. 5 | #' See the \pkg{rstanarm} package for an example. 6 | #' 7 | #' @export 8 | #' @template args-object 9 | #' @template args-dots 10 | #' @return `posterior_epred()` methods should return a \eqn{D} by \eqn{N} 11 | #' matrix, where \eqn{D} is the number of draws from the posterior 12 | #' distribution distribution and \eqn{N} is the number of data points. 13 | #' 14 | #' @template seealso-rstanarm-pkg 15 | #' @template seealso-vignettes 16 | #' 17 | posterior_epred <- function(object, ...) { 18 | UseMethod("posterior_epred") 19 | } 20 | 21 | -------------------------------------------------------------------------------- /R/posterior_interval.R: -------------------------------------------------------------------------------- 1 | #' Generic function and default method for posterior uncertainty intervals 2 | #' 3 | #' These intervals are often referred to as credible intervals, but we use the 4 | #' term uncertainty intervals to highlight the fact that wider intervals 5 | #' correspond to greater uncertainty. See 6 | #' [posterior_interval.stanreg()](https://mc-stan.org/rstanarm/reference/posterior_interval.stanreg.html) 7 | #' in the \pkg{rstanarm} package for an example. 8 | #' 9 | #' @export 10 | #' @template args-object 11 | #' @template args-dots 12 | #' @param prob A number \eqn{p \in (0,1)}{p (0 < p < 1)} indicating the desired 13 | #' probability mass to include in the intervals. 14 | #' 15 | #' @return `posterior_interval()` methods should return a matrix with two 16 | #' columns and as many rows as model parameters (or a subset of parameters 17 | #' specified by the user). For a given value of `prob`, \eqn{p}, the 18 | #' columns correspond to the lower and upper \eqn{100p}\% interval limits and 19 | #' have the names \eqn{100\alpha/2}\% and \eqn{100(1 - \alpha/2)}\%, where 20 | #' \eqn{\alpha = 1-p}. For example, if `prob=0.9` is specified (a 21 | #' \eqn{90}\% interval), then the column names would be `"5%"` and 22 | #' `"95%"`, respectively. 23 | #' 24 | #' The default method just takes `object` to be a matrix (one column per 25 | #' parameter) and computes quantiles, with `prob` defaulting to `0.9`. 26 | #' 27 | #' @template seealso-rstanarm-pkg 28 | #' @template seealso-vignettes 29 | #' 30 | #' @examples 31 | #' # Default method takes a numeric matrix (of posterior draws) 32 | #' draws <- matrix(rnorm(100 * 5), 100, 5) # fake draws 33 | #' colnames(draws) <- paste0("theta_", 1:5) 34 | #' posterior_interval(draws) 35 | #' 36 | #' # Also see help("posterior_interval", package = "rstanarm") 37 | #' 38 | posterior_interval <- function(object, ...) { 39 | UseMethod("posterior_interval") 40 | } 41 | 42 | #' @rdname posterior_interval 43 | #' @export 44 | posterior_interval.default <- function(object, prob = 0.9, ...) { 45 | if (!is.matrix(object)) 46 | stop("For the default method 'object' should be a matrix.") 47 | .central_intervals(object, prob) 48 | } 49 | -------------------------------------------------------------------------------- /R/posterior_linpred.R: -------------------------------------------------------------------------------- 1 | #' Generic function for accessing the posterior distribution of the linear 2 | #' predictor 3 | #' 4 | #' Extract the posterior draws of the linear predictor, possibly transformed by 5 | #' the inverse-link function. See 6 | #' [posterior_linpred.stanreg()](https://mc-stan.org/rstanarm/reference/posterior_linpred.stanreg.html) 7 | #' in the \pkg{rstanarm} package for an example. 8 | #' 9 | #' @export 10 | #' @template args-object 11 | #' @template args-dots 12 | #' @param transform Should the linear predictor be transformed using the 13 | #' inverse-link function? The default is `FALSE`, in which case the 14 | #' untransformed linear predictor is returned. 15 | #' @return `posterior_linpred()` methods should return a \eqn{D} by \eqn{N} 16 | #' matrix, where \eqn{D} is the number of draws from the posterior 17 | #' distribution distribution and \eqn{N} is the number of data points. 18 | #' 19 | #' @template seealso-rstanarm-pkg 20 | #' @template seealso-vignettes 21 | #' 22 | #' @examples 23 | #' # See help("posterior_linpred", package = "rstanarm") 24 | #' 25 | posterior_linpred <- function(object, transform = FALSE, ...) { 26 | UseMethod("posterior_linpred") 27 | } 28 | -------------------------------------------------------------------------------- /R/posterior_predict.R: -------------------------------------------------------------------------------- 1 | #' Generic function for drawing from the posterior predictive distribution 2 | #' 3 | #' Draw from the posterior predictive distribution of the outcome. See 4 | #' [posterior_predict.stanreg()](https://mc-stan.org/rstanarm/reference/posterior_predict.stanreg.html) 5 | #' in the \pkg{rstanarm} package for an example. 6 | #' 7 | #' @export 8 | #' @template args-object 9 | #' @template args-dots 10 | #' @return `posterior_predict()` methods should return a \eqn{D} by \eqn{N} 11 | #' matrix, where \eqn{D} is the number of draws from the posterior predictive 12 | #' distribution and \eqn{N} is the number of data points being predicted per 13 | #' draw. 14 | #' 15 | #' @template seealso-rstanarm-pkg 16 | #' @template seealso-vignettes 17 | #' 18 | #' @examples 19 | #' # See help("posterior_predict", package = "rstanarm") 20 | #' 21 | posterior_predict <- function(object, ...) { 22 | UseMethod("posterior_predict") 23 | } 24 | -------------------------------------------------------------------------------- /R/predictive_error.R: -------------------------------------------------------------------------------- 1 | #' Generic function and default method for predictive errors 2 | #' 3 | #' Generic function and default method for computing predictive errors 4 | #' \eqn{y - y^{rep}}{y - yrep} (in-sample, for observed \eqn{y}) or 5 | #' \eqn{y - \tilde{y}}{y - ytilde} (out-of-sample, for new or held-out \eqn{y}). 6 | #' See [predictive_error.stanreg()](https://mc-stan.org/rstanarm/reference/predictive_error.stanreg.html) 7 | #' in the \pkg{rstanarm} package for an example. 8 | #' 9 | #' @export 10 | #' @template args-object 11 | #' @template args-dots 12 | #' @return `predictive_error()` methods should return a \eqn{D} by \eqn{N} 13 | #' matrix, where \eqn{D} is the number of draws from the posterior predictive 14 | #' distribution and \eqn{N} is the number of data points being predicted per 15 | #' draw. 16 | #' 17 | #' The default method just takes `object` to be a matrix and `y` to be a 18 | #' vector. 19 | #' 20 | #' @template seealso-rstanarm-pkg 21 | #' @template seealso-vignettes 22 | #' 23 | #' @examples 24 | #' # default method 25 | #' y <- rnorm(10) 26 | #' ypred <- matrix(rnorm(500), 50, 10) 27 | #' pred_errors <- predictive_error(ypred, y) 28 | #' dim(pred_errors) 29 | #' head(pred_errors) 30 | #' 31 | #' # Also see help("predictive_error", package = "rstanarm") 32 | #' 33 | predictive_error <- function(object, ...) { 34 | UseMethod("predictive_error") 35 | } 36 | 37 | #' @rdname predictive_error 38 | #' @export 39 | #' @param y For the default method, a vector of `y` values the same length as 40 | #' the number of columns in the matrix used as `object`. 41 | predictive_error.default <- function(object, y, ...) { 42 | if (!is.matrix(object)) 43 | stop("For the default method 'object' should be a matrix.") 44 | .pred_errors(object, y) 45 | } 46 | 47 | 48 | # internal ---------------------------------------------------------------- 49 | 50 | # @param object A matrix 51 | # @param y A vector the same length as ncol(object) 52 | .pred_errors <- function(object, y) { 53 | stopifnot(is.matrix(object), length(y) == ncol(object)) 54 | sweep(-1 * object, MARGIN = 2, STATS = as.array(y), FUN = "+") 55 | } 56 | -------------------------------------------------------------------------------- /R/predictive_interval.R: -------------------------------------------------------------------------------- 1 | #' Generic function for predictive intervals 2 | #' 3 | #' See [predictive_interval.stanreg()](https://mc-stan.org/rstanarm/reference/predictive_interval.stanreg.html) 4 | #' in the \pkg{rstanarm} package for an example. 5 | #' 6 | #' @export 7 | #' @template args-object 8 | #' @template args-dots 9 | #' @param prob A number \eqn{p \in (0,1)}{p (0 < p < 1)} indicating the desired 10 | #' probability mass to include in the intervals. 11 | #' 12 | #' @return `predictive_interval()` methods should return a matrix with two 13 | #' columns and as many rows as data points being predicted. For a given value 14 | #' of `prob`, \eqn{p}, the columns correspond to the lower and upper 15 | #' \eqn{100p}\% interval limits and have the names \eqn{100\alpha/2}\% and 16 | #' \eqn{100(1 - \alpha/2)}\%, where \eqn{\alpha = 1-p}. For example, if 17 | #' `prob=0.9` is specified (a \eqn{90}\% interval), then the column names 18 | #' would be `"5%"` and `"95%"`, respectively. 19 | #' 20 | #' The default method just takes `object` to be a matrix and computes 21 | #' quantiles, with `prob` defaulting to `0.9`. 22 | #' 23 | #' @template seealso-rstanarm-pkg 24 | #' @template seealso-vignettes 25 | #' 26 | #' @examples 27 | #' # Default method takes a numeric matrix (of draws from posterior 28 | #' # predictive distribution) 29 | #' ytilde <- matrix(rnorm(100 * 5, sd = 2), 100, 5) # fake draws 30 | #' predictive_interval(ytilde, prob = 0.8) 31 | #' 32 | #' # Also see help("predictive_interval", package = "rstanarm") 33 | #' 34 | predictive_interval <- function(object, ...) { 35 | UseMethod("predictive_interval") 36 | } 37 | 38 | #' @rdname predictive_interval 39 | #' @export 40 | predictive_interval.default <- function(object, prob = 0.9, ...) { 41 | if (!is.matrix(object)) 42 | stop("For the default method 'object' should be a matrix.") 43 | .central_intervals(object, prob) 44 | } 45 | 46 | 47 | # internal ---------------------------------------------------------------- 48 | 49 | #' Compute central intervals 50 | #' 51 | #' @noRd 52 | #' @param object A numeric matrix 53 | #' @param prob Probability mass to include in intervals (in (0,1)) 54 | #' @return See above. 55 | #' 56 | #' @importFrom stats quantile 57 | .central_intervals <- function(object, prob) { 58 | stopifnot(is.matrix(object)) 59 | if (length(prob) != 1L || prob <= 0 || prob >= 1) 60 | stop("'prob' should be a single number greater than 0 and less than 1.", 61 | call. = FALSE) 62 | alpha <- (1 - prob) / 2 63 | probs <- c(alpha, 1 - alpha) 64 | labs <- paste0(100 * probs, "%") 65 | out <- t(apply(object, 2, quantile, probs = probs)) 66 | structure(out, dimnames = list(colnames(object), labs)) 67 | } 68 | -------------------------------------------------------------------------------- /R/prior_summary.R: -------------------------------------------------------------------------------- 1 | #' Generic function for extracting information about prior distributions 2 | #' 3 | #' See [prior_summary.stanreg()](https://mc-stan.org/rstanarm/reference/prior_summary.stanreg.html) 4 | #' in the \pkg{rstanarm} package for an example. 5 | #' 6 | #' @export 7 | #' @template args-object 8 | #' @template args-dots 9 | #' 10 | #' @return `prior_summary()` methods should return an object containing 11 | #' information about the prior distribution(s) used for the given model. 12 | #' The structure of this object will depend on the method. 13 | #' 14 | #' The default method just returns `object$prior.info`, which is 15 | #' `NULL` if there is no `'prior.info'` element. 16 | #' 17 | #' @template seealso-rstanarm-pkg 18 | #' @template seealso-vignettes 19 | #' 20 | #' @examples 21 | #' # See help("prior_summary", package = "rstanarm") 22 | #' 23 | prior_summary <- function(object, ...) { 24 | UseMethod("prior_summary") 25 | } 26 | 27 | #' @rdname prior_summary 28 | #' @export 29 | prior_summary.default <- function(object, ...) { 30 | object$prior.info 31 | } 32 | -------------------------------------------------------------------------------- /R/rstan_create_package.R: -------------------------------------------------------------------------------- 1 | # Part of the rstantools package 2 | # Copyright (C) 2018, 2019 Martin Lysy 3 | # Copyright (C) 2019 Trustees of Columbia University 4 | # 5 | # rstantools is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU General Public License 7 | # as published by the Free Software Foundation; either version 3 8 | # of the License, or (at your option) any later version. 9 | # 10 | # rstantools is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | # 19 | #' Create a new \R package with compiled Stan programs 20 | #' 21 | #' @aliases rstan_package_skeleton 22 | #' 23 | #' @description 24 | #' \if{html}{\figure{stanlogo.png}{options: width="25" alt="https://mc-stan.org/about/logo/"}} 25 | #' The `rstan_create_package()` function helps get you started developing a 26 | #' new \R package that interfaces with Stan via the \pkg{rstan} package. First 27 | #' the basic package structure is set up via [usethis::create_package()]. 28 | #' Then several adjustments are made so the package can include Stan programs 29 | #' that can be built into binary versions (i.e., pre-compiled Stan C++ code). 30 | #' 31 | #' The **Details** section below describes the process and the 32 | #' **See Also** section provides links to recommendations for developers 33 | #' and a step-by-step walk-through. 34 | #' 35 | #' As of version `2.0.0` of \pkg{rstantools} the 36 | #' `rstan_package_skeleton()` function is defunct and only 37 | #' `rstan_create_package()` is supported. 38 | #' 39 | #' @export 40 | #' @param path The path to the new package to be created (terminating in the 41 | #' package name). 42 | #' @param fields,rstudio,open Same as [usethis::create_package()]. See 43 | #' the documentation for that function, especially the note in the 44 | #' **Description** section about the side effect of changing the active 45 | #' project. 46 | #' @param stan_files A character vector with paths to `.stan` files to include 47 | #' in the package. 48 | #' @param roxygen Should \pkg{roxygen2} be used for documentation? Defaults to 49 | #' `TRUE`. If so, a file `R/{pkgname}-package.R` is added to the package with 50 | #' roxygen tags for the required import lines. See the **Note** section below 51 | #' for advice specific to the latest versions of \pkg{roxygen2}. 52 | #' @param travis Should a `.travis.yml` file be added to the package directory? 53 | #' This argument is now deprecated. We recommend using GitHub Actions to set 54 | #' up automated testings for your package. See 55 | #' https://github.com/r-lib/actions for useful templates. 56 | #' @template args-license 57 | #' @template args-auto_config 58 | #' 59 | #' @details 60 | #' This function first creates a regular \R package using 61 | #' `usethis::create_package()`, then adds the infrastructure required to compile 62 | #' and export `stanmodel` objects. In the package root directory, the user's 63 | #' Stan source code is located in: 64 | #' \preformatted{ 65 | #' inst/ 66 | #' |_stan/ 67 | #' | |_include/ 68 | #' | 69 | #' |_include/ 70 | #' } 71 | #' All `.stan` files containing instructions to build a `stanmodel` 72 | #' object must be placed in `inst/stan`. Other `.stan` files go in 73 | #' any `stan/` subdirectory, to be invoked by Stan's `#include` 74 | #' mechanism, e.g., 75 | #' \preformatted{ 76 | #' #include "include/mylib.stan" 77 | #' #include "data/preprocess.stan" 78 | #' } 79 | #' See \pkg{rstanarm} for many examples. 80 | #' 81 | #' The folder `inst/include` is for all user C++ files associated with the 82 | #' Stan programs. In this folder, the only file to directly interact with the 83 | #' Stan C++ library is `stan_meta_header.hpp`; all other `#include` 84 | #' directives must be channeled through here. 85 | #' 86 | #' The final step of the package creation is to invoke 87 | #' [rstan_config()], which creates the following files for 88 | #' interfacing with Stan objects from \R: 89 | #' \itemize{ 90 | #' \item `src` contains the `stan_ModelName{.cc/.hpp}` pairs 91 | #' associated with all `ModelName.stan` files in `inst/stan` which 92 | #' define `stanmodel` objects. 93 | #' \item `src/Makevars[.win]` which link to the `StanHeaders` and 94 | #' Boost (`BH`) libraries. 95 | #' \item `R/stanmodels.R` loads the C++ modules containing the 96 | #' `stanmodel` class definitions, and assigns an \R instance of each 97 | #' `stanmodel` object to a `stanmodels` list (with names 98 | #' corresponding to the names of the Stan files). 99 | #' } 100 | #' @template details-auto_config 101 | #' @template details-license 102 | #' @details Authors willing to license their Stan programs of general interest 103 | #' under the GPL are invited to contribute their `.stan` files and 104 | #' supporting \R code to the \pkg{rstanarm} package. 105 | #' 106 | #' @template section-running-stan 107 | #' 108 | #' @note For \pkg{devtools} users, because of changes in the latest versions of 109 | #' \pkg{roxygen2} it may be necessary to run `pkgbuild::compile_dll()` 110 | #' once before `devtools::document()` will work. 111 | #' 112 | #' @seealso 113 | #' * [use_rstan()] for adding Stan functionality to an existing 114 | #' \R package and [rstan_config()] for updating an existing package 115 | #' when its Stan files are changed. 116 | #' * The \pkg{rstanarm} package [repository](https://github.com/stan-dev/rstanarm) 117 | #' on GitHub. 118 | #' @template seealso-vignettes 119 | #' @template seealso-get-help 120 | #' 121 | rstan_create_package <- function(path, 122 | fields = NULL, 123 | rstudio = TRUE, 124 | open = TRUE, 125 | stan_files = character(), 126 | roxygen = TRUE, 127 | travis = FALSE, 128 | license = TRUE, 129 | auto_config = TRUE) { 130 | if (!requireNamespace("usethis", quietly = TRUE)) { 131 | stop("Please install package 'usethis' to use function 'rstan_create_package'.", 132 | call. = FALSE) 133 | } 134 | DIR <- dirname(path) 135 | name <- basename(path) 136 | .check_stan_ext(stan_files) 137 | 138 | if (rstudio && !requireNamespace("rstudioapi", quietly = TRUE)) { 139 | stop("Please install package 'rstudioapi' to use option 'rstudio = TRUE'.", 140 | call. = FALSE) 141 | rstudio <- rstudio && rstudioapi::isAvailable() 142 | } 143 | if (open && rstudio) { 144 | on.exit(rstudioapi::openProject(file.path(DIR, name), newSession = TRUE)) 145 | } 146 | 147 | # run usethis::create_package() 148 | if (file.exists(path)) { 149 | stop("Directory '", path, "' already exists.", call. = FALSE) 150 | } 151 | message("Creating package skeleton for package: ", name, domain = NA) 152 | suppressMessages( 153 | usethis::create_package( 154 | path = path, 155 | fields = fields, 156 | rstudio = rstudio, 157 | open = FALSE 158 | ) 159 | ) 160 | 161 | # add Stan-specific functionality to the new package 162 | pkgdir <- .check_pkgdir(file.path(DIR, name)) 163 | .rstan_make_pkg(pkgdir, stan_files, roxygen, travis, license, auto_config) 164 | invisible(NULL) 165 | } 166 | 167 | #--- helper functions ---------------------------------------------------------- 168 | 169 | # check stan extensions 170 | .check_stan_ext <- function(stan_files) { 171 | if (length(stan_files) && !all(grepl("\\.stan$", stan_files))) { 172 | stop("All files named in 'stan_files' must end ", 173 | "with a '.stan' extension.", call. = FALSE) 174 | } 175 | } 176 | 177 | # add travis file 178 | .add_travis <- function(pkgdir) { 179 | travis_file <- readLines(.system_file("travis.yml")) 180 | .add_stanfile(gsub("RSTAN_PACKAGE_NAME", basename(pkgdir), travis_file), 181 | pkgdir, ".travis.yml", 182 | noedit = FALSE, msg = TRUE, warn = FALSE) 183 | } 184 | 185 | # add .gitignore and .Rbuildignore files 186 | .add_gitignore_Rbuildignore <- function(pkgdir, travis) { 187 | gitignore_files <- c("^rcppExports.cpp$", "^stanExports_*") 188 | .add_stanfile(gitignore_files, pkgdir, ".gitignore", 189 | noedit = FALSE, msg = TRUE, warn = FALSE) 190 | 191 | Rbuildignore_files <- c(gitignore_files, if (travis) "^\\.travis\\.yml$") 192 | .add_stanfile(Rbuildignore_files, pkgdir, ".Rbuildignore", 193 | noedit = FALSE, msg = TRUE, warn = FALSE) 194 | } 195 | 196 | # add R/mypkg-package.R file with roxygen import comments 197 | # also add Encoding: UTF-8 to DESCRIPTION 198 | .add_roxygen <- function(pkgdir) { 199 | pkg_file <- readLines(.system_file("rstanpkg-package.R")) 200 | pkg_file <- gsub("RSTAN_PACKAGE_NAME", basename(pkgdir), pkg_file) 201 | pkg_file <- gsub("RSTAN_REFERENCE", .rstan_reference(), pkg_file) 202 | .add_stanfile(pkg_file, pkgdir, 203 | "R", paste0(basename(pkgdir), "-package.R"), 204 | noedit = FALSE, msg = TRUE, warn = FALSE) 205 | desc_pkg <- desc::description$new(file.path(pkgdir, "DESCRIPTION")) 206 | desc_pkg$set(Encoding = "UTF-8") 207 | desc_pkg$write() 208 | } 209 | 210 | # reference to rstan package 211 | .rstan_reference <- function() { 212 | has_version <- utils::packageDescription("rstan", fields = "Version") 213 | version_year <- substr(utils::packageDescription("rstan", fields = "Date"), 1, 4) 214 | paste0( 215 | "Stan Development Team (", version_year,"). ", 216 | "RStan: the R interface to Stan. ", 217 | "R package version ", has_version, ". ", 218 | "https://mc-stan.org" 219 | ) 220 | } 221 | 222 | # add stan functionality to package 223 | .rstan_make_pkg <- function(pkgdir, stan_files, 224 | roxygen, travis, license, auto_config) { 225 | 226 | use_rstan(pkgdir, license = license, auto_config = auto_config) 227 | file.copy( 228 | from = stan_files, 229 | to = file.path(pkgdir, "inst", "stan", basename(stan_files)) 230 | ) 231 | if (roxygen) .add_roxygen(pkgdir) 232 | if (travis) { 233 | .add_travis(pkgdir) 234 | warning( 235 | "The 'travis' argument is deprecated. ", 236 | "We recommend using GitHub Actions instead.", 237 | call. = FALSE 238 | ) 239 | } 240 | .add_gitignore_Rbuildignore(pkgdir, travis) 241 | 242 | message("Configuring Stan compile and module export instructions ...") 243 | rstan_config(pkgdir) 244 | 245 | # open = "at" implies text is appended 246 | con <- file(file.path(pkgdir, "Read-and-delete-me"), open = "at") 247 | writeLines(readLines(.system_file("Read_and_delete_me")), con) 248 | close(con) 249 | 250 | message( 251 | domain = NA, 252 | sprintf( 253 | "Further Stan-specific steps are described in '%s'.", 254 | file.path(basename(pkgdir), "Read-and-delete-me") 255 | ) 256 | ) 257 | } 258 | 259 | #------------------------------------------------------------------------------- 260 | 261 | ## outline of steps: 262 | 263 | ## 1. run package skeleton. 264 | ## - rm man files 265 | 266 | ## 2. create stan_dirs. 267 | ## - inst/stan 268 | ## - inst/stan/include 269 | ## - inst/include 270 | ## - src/stan_files 271 | ## - if (!exists) message 272 | 273 | ## 3. add default files. 274 | ## - src/stan_init.cpp 275 | ## - inst/include/stan_meta_header.cpp 276 | 277 | ## 4. update NAMESPACE 278 | ## - if (default) modify else message(remaining steps) 279 | 280 | ## 5. update DESCRIPTION 281 | ## - if (modified) message else do_nothing 282 | 283 | ## 4. add stan_files 284 | 285 | ## 5. configure build 286 | ## - make src/stan_files/*.{cc/hpp} 287 | ## only overwrite if different 288 | ## - add src/Makevars[.win] 289 | ## only overwrite if different 290 | ## - add R/stanmodels.R 291 | ## - if (is_empty(inst/stan)) no Makevars, empty stanmodels.R 292 | 293 | ## messages: 294 | ## - when creating directories 295 | ## - when updating DESCRIPTION or NAMESPACE 296 | ## - when adding files? sometimes 297 | 298 | ## warnings: 299 | ## - when attempting to overwrite non-stan file with stan file of same name 300 | 301 | ## error: 302 | ## - when {dir/file}.create fails even though it doesn't exist 303 | 304 | 305 | ## ok stan_meta_header.hpp is problematic, because want to warn if already exists, but only if it's there from before... 306 | 307 | ## so .add_stanfile(file_lines, pkgdir, ..., 308 | ## noedit = TRUE, msg = FALSE, warn = TRUE) 309 | -------------------------------------------------------------------------------- /R/rstan_package_utils.R: -------------------------------------------------------------------------------- 1 | # various helper functions for creating rstan-enabled packages 2 | 3 | # comment to put on top of rstantools system files. 4 | # deduce comment character based on file extension 5 | .rstantools_noedit <- function(file_name) { 6 | # comment character 7 | file_name <- basename(file_name) 8 | ext <- gsub(".*[.]", "", file_name) 9 | if (ext == file_name) ext <- "" 10 | com <- ifelse(tolower(ext) %in% c("r", "", "win"), "#", "//") 11 | paste0(com, " ", "Generated by rstantools. Do not edit by hand.") 12 | } 13 | 14 | # warning message not overwriting file 15 | .warning_nowrite <- function(file_name) { 16 | warning("'", file_name, 17 | "' already exists. Not overwritten by rstantools.", 18 | .call = FALSE) 19 | invisible(NULL) 20 | } 21 | 22 | # location of rstantools system files, 23 | # i.e., templates to be copied to user's package 24 | .system_file <- function(...) { 25 | system.file("include", "sys", ..., package = "rstantools") 26 | } 27 | 28 | # taken from Rcpp::compileAttributes 29 | # validates package directory 30 | .check_pkgdir <- function(pkgdir) { 31 | pkgdir <- normalizePath(pkgdir, winslash = "/") 32 | descFile <- file.path(pkgdir, "DESCRIPTION") 33 | if (!file.exists(descFile)) { 34 | stop("pkgdir must refer to the directory containing an R package.", 35 | call. = FALSE) 36 | } 37 | pkgdir 38 | } 39 | 40 | # create a stan directory 41 | # msg: display message if attempt to create is made 42 | # warn: warning if directory already exists 43 | # return value: whether or not directory was created 44 | .add_standir <- function(pkgdir, ..., msg = TRUE, warn = FALSE) { 45 | dir_name <- file.path(pkgdir, ...) 46 | acc <- FALSE 47 | if (file.exists(dir_name)) { 48 | if (!file.info(dir_name)$isdir) { 49 | stop(file.path(...), " exists but is not a directory.", call. = FALSE) 50 | } 51 | } else { 52 | if (msg) message("Creating ", file.path(...), " directory ...") 53 | acc <- dir.create(dir_name, recursive = TRUE, 54 | showWarnings = TRUE) 55 | # this should not happen... 56 | if (!acc) stop(file.path(...), " directory not created.", call. = FALSE) 57 | } 58 | if (warn && !acc) .warning_nowrite(file.path(basename(pkgdir), ...)) 59 | invisible(acc) 60 | } 61 | 62 | # add stan file consisting of character vector of file_lines 63 | # * don't overwrite unless first line of destination file is .rstantools_noedit 64 | # * only overwrite if file is not identical 65 | # noedit: add "rstantools file: don't edit" to first line of file 66 | # msg: display message if attempt to create is made 67 | # warn: waning if non-stan file of same name already exists 68 | # return value: whether or not file was successfully added 69 | .add_stanfile <- function(file_lines, pkgdir, ..., 70 | noedit = TRUE, msg = FALSE, warn = TRUE) { 71 | dest_file <- file.path(pkgdir, ...) 72 | noedit_msg <- .rstantools_noedit(dest_file) 73 | has_file <- file.exists(dest_file) # check if file exists 74 | # check if existing file is a stan file 75 | is_stanfile <- has_file && (noedit_msg %in% readLines(dest_file, n = 5)) 76 | if (has_file && !is_stanfile) { 77 | # non-stan file found: don't overwrite 78 | if (warn) .warning_nowrite(file.path(basename(pkgdir), ...)) 79 | acc <- FALSE 80 | } 81 | if (!has_file || is_stanfile) { 82 | if (noedit && (file_lines[1] != noedit_msg)) { 83 | # add "noedit" to top of file 84 | if (startsWith(file_lines[1], "#!")) { 85 | # in this case noedit_msg goes on 2nd line so file starts with #! interpreter line 86 | # see https://github.com/stan-dev/rstantools/issues/82 87 | file_lines <- c(file_lines[1], "", noedit_msg, "", file_lines[-1]) 88 | } else { 89 | file_lines <- c(noedit_msg, "", file_lines) 90 | } 91 | } 92 | if (is_stanfile) { 93 | # stan file found: check if it needs to be overwritten 94 | old_lines <- readLines(dest_file) 95 | acc <- !identical(paste0(old_lines, collapse = "\n"), 96 | paste0(file_lines, collapse = "\n")) 97 | } else acc <- TRUE 98 | if (acc) { 99 | # create/overwrite file 100 | if (msg) message("Adding ", basename(dest_file), " file ...") 101 | writeLines(file_lines, con = dest_file) 102 | } 103 | } 104 | invisible(acc) 105 | } 106 | 107 | #' Helper function for loading code in roxygenise 108 | #' 109 | #' Adapted from the \code{sourceDir} function defined 110 | #' by \code{example(source)}. 111 | #' 112 | #' @param path Path to directory containing code to load 113 | #' @param trace Whether to print file names as they are loaded 114 | #' @param ... Additional arguments passed to \code{\link{source}} 115 | #' 116 | #' @return \code{NULL} 117 | #' @export 118 | rstantools_load_code <- function(path, trace = TRUE, ...) { 119 | op <- options(); on.exit(options(op)) # to reset after each 120 | for (nm in list.files(path, pattern = "[.][RrSsQq]$")) { 121 | if (trace) cat(nm, ":") 122 | source(file.path(path, nm), ...) 123 | if (trace) cat("\n") 124 | options(op) 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /R/rstantools-package.R: -------------------------------------------------------------------------------- 1 | #' Tools for Developing \R Packages Interfacing with Stan 2 | #' 3 | #' @name rstantools-package 4 | #' @aliases rstantools 5 | #' @docType package 6 | #' 7 | #' @description 8 | #' \if{html}{ 9 | #' \figure{stanlogo.png}{options: width="50" alt="mc-stan.org"} 10 | #' } *Stan Development Team* 11 | #' 12 | #' The \pkg{rstantools} package provides various tools for developers of \R 13 | #' packages interfacing with Stan (), including 14 | #' functions to set up the required package structure, S3 generic methods to 15 | #' unify function naming across Stan-based \R packages, and vignettes with 16 | #' guidelines for developers. To get started building a package see 17 | #' [rstan_create_package()]. 18 | #' 19 | #' @template seealso-vignettes 20 | #' @template seealso-get-help 21 | #' 22 | #' @importFrom RcppParallel RcppParallelLibs 23 | #' 24 | NULL 25 | 26 | 27 | # internal ---------------------------------------------------------------- 28 | 29 | # release reminders (for devtools) 30 | release_questions <- function() { # nocov start 31 | c( 32 | "Have you updated the developer guidelines in the vignette?" 33 | ) 34 | } # nocov end 35 | -------------------------------------------------------------------------------- /R/update_description.R: -------------------------------------------------------------------------------- 1 | #' Update `DESCRIPTION` to include all packages required to compile Stan code. 2 | #' 3 | #' @noRd 4 | #' @param pkgdir Package root directory. 5 | #' @param auto_config Whether or not package should configure itself. This 6 | #' means importing `rstantools` for linking via `configure[.win]`) and setting 7 | #' `Biarch: true` in the `DESCRIPTION`. 8 | #' @param msg Whether or not to display a message if an attempt to update 9 | #' `DESCRIPTION` is made. 10 | #' 11 | #' @return Whether or not `DESCRIPTION` file was modified. 12 | #' 13 | #' @details Sanitizes the package dependencies as follows: 14 | #' \itemize{ 15 | #' \item If `rstantools` dependency version is lower, don't update 16 | #' existing dependency. 17 | #' \item If `rstantools` `Imports` dependency already exists in 18 | #' `Depends`, keep the `Depends` package but increase version if 19 | #' needed. 20 | #' } 21 | #' 22 | #' Issues the following messages: 23 | #' \itemize{ 24 | #' \item If `auto_config = FALSE` and `rstantools` is imported. 25 | #' \item If `auto_config = FALSE` and `Biarch: true`. 26 | #' } 27 | #' 28 | .update_description <- function(pkgdir, auto_config = FALSE, msg = TRUE) { 29 | # current desc file 30 | desc_pkg <- desc::description$new(file.path(pkgdir, "DESCRIPTION")) 31 | # save a copy 32 | desc_old <- desc::description$new(file.path(pkgdir, "DESCRIPTION")) 33 | # rstantools desc file 34 | desc_rstan <- desc::description$new(.system_file("DESCRIPTION")) 35 | # check for Biarch field 36 | has_biarch <- desc_pkg$has_fields("Biarch") 37 | if(!auto_config) { 38 | # check for rstantools dependence 39 | has_rstantools <- desc_pkg$has_dep("rstantools", type = "Imports") || 40 | desc_pkg$has_dep("rstantools", type = "Depends") 41 | # check if Biarch: true 42 | has_biarch <- has_biarch && tolower(desc_pkg$get_field("Biarch")) == "true" 43 | # don't add dependence on rstantools 44 | desc_rstan$del_dep("rstantools", type = "Imports") 45 | } else { 46 | # use latest version of rstantools 47 | desc_rstan$set_dep("rstantools", type = "Imports", 48 | version = paste0(">= ", 49 | utils::packageVersion("rstantools"))) 50 | # add Biarch: true for multiarch Windows 51 | desc_pkg$set(Biarch = "true") 52 | } 53 | # update dependencies 54 | dep_pkg <- desc_pkg$get_deps() 55 | names(dep_pkg)[3] <- "vpkg" 56 | dep_rstan <- desc_rstan$get_deps() 57 | names(dep_rstan)[3] <- "vrstan" 58 | # convert all rstan Imports to Depends if they are in package Depends 59 | di <- dep_rstan$package %in% dep_pkg$package[dep_pkg$type == "Depends"] 60 | dep_rstan$type[di & dep_rstan$type == "Imports"] <- "Depends" 61 | # combine all dependencies 62 | dep_comb <- merge(x = dep_pkg, y = dep_rstan, 63 | by = c("type", "package"), all = TRUE) 64 | # larger version of each package 65 | dep_comb <- cbind(dep_comb[1:2], 66 | version = .version_max(dep_comb$vpkg, dep_comb$vrstan)) 67 | desc_pkg$set_deps(dep_comb) 68 | # add additional elements from template DESCRIPTION file 69 | extra_fields <- c("SystemRequirements", "Encoding") 70 | do.call(desc_pkg$set, as.list(desc_rstan$get(extra_fields))) 71 | # check if description has changed 72 | acc <- !identical(desc_pkg$str(), desc_old$str()) 73 | if(acc) { 74 | if(msg) message("Updating DESCRIPTION ...") 75 | desc_pkg$write() 76 | } 77 | if(!auto_config && msg) { 78 | if(has_rstantools) { 79 | message("'Import: rstantools' detected in DESCRIPTION with 'auto_config = FALSE'.\n", 80 | "If you did not add this dependence yourself then it's safe to remove it.\n") 81 | } 82 | if(has_biarch) { 83 | message("'Biarch: true' detected in DESCRIPTION with 'auto_config = FALSE'.\n", 84 | "If you did not add this line yourself then it's safe to remove it.\n") 85 | } 86 | } 87 | invisible(acc) 88 | } 89 | 90 | # return greater of two version numbers in desc::desc_get_dep format 91 | .version_max <- function(ver1, ver2) { 92 | # convert non-existing/any version packages to 0 93 | ver1 <- gsub("^[^[:digit:]]*([[:digit:]]*)", 94 | replacement = "\\1", ver1) 95 | ver1[is.na(ver1) | ver1 == ""] <- 0 96 | ver2 <- gsub("^[^[:digit:]]*([[:digit:]]*)", 97 | replacement = "\\1", ver2) 98 | ver2[is.na(ver2) | ver2 == ""] <- 0 99 | # take greater of two versions 100 | vmax <- mapply(function(x, y) utils::compareVersion(x, y) >= 0, 101 | x = ver1, y = ver2) 102 | vmax <- ifelse(vmax, ver1, ver2) 103 | ifelse(vmax == "0", "*", paste0(">= ", vmax)) 104 | } 105 | -------------------------------------------------------------------------------- /R/use_rstan.R: -------------------------------------------------------------------------------- 1 | # Part of the rstantools package 2 | # Copyright (C) 2018 Martin Lysy 3 | # 4 | # rstantools is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU General Public License 6 | # as published by the Free Software Foundation; either version 3 7 | # of the License, or (at your option) any later version. 8 | # 9 | # rstantools is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | # 18 | 19 | #' Add Stan infrastructure to an existing package 20 | #' 21 | #' Add Stan infrastructure to an existing \R package. To create a *new* package 22 | #' containing Stan programs use [rstan_create_package()] instead. 23 | #' 24 | #' @template args-pkgdir 25 | #' @template args-license 26 | #' @template args-auto_config 27 | #' 28 | #' @details Prepares a package to compile and use Stan code by performing the 29 | #' following steps: 30 | #' 1. Create `inst/stan` folder where all `.stan` files defining 31 | #' Stan models should be stored. 32 | #' 1. Create `inst/stan/include` where optional `license.stan` file is stored. 33 | #' 1. Create `inst/include/stan_meta_header.hpp` to include optional header 34 | #' files used by Stan code. 35 | #' 1. Create `src` folder (if it doesn't exist) to contain the Stan C++ code. 36 | #' 1. Create `R` folder (if it doesn't exist) to contain wrapper code to expose 37 | #' Stan C++ classes to \R. 38 | #' 1. Update `DESCRIPTION` file to contain all needed dependencies to compile 39 | #' Stan C++ code. 40 | #' 1. If `NAMESPACE` file is generic (i.e., created by [rstan_create_package()]), 41 | #' append `import(Rcpp, methods)`, `importFrom(rstan, sampling)`, 42 | #' `importFrom(rstantools, rstan_config)`, `importFrom(RcppParallel, RcppParallelLibs)`, 43 | #' and `useDynLib` directives. If `NAMESPACE` is not generic, display message 44 | #' telling user what to add to `NAMESPACE` for themselves. 45 | #' 46 | #' @template details-auto_config 47 | #' @template section-running-stan 48 | #' 49 | #' @return Invisibly, `TRUE` or `FALSE` indicating whether or not any files or 50 | #' folders where created or modified. 51 | #' 52 | #' @export 53 | use_rstan <- function(pkgdir = ".", license = TRUE, auto_config = TRUE) { 54 | pkgdir <- .check_pkgdir(pkgdir) 55 | 56 | # stan folders 57 | acc <- .add_standir(pkgdir, "inst", "stan", "include", 58 | msg = TRUE, warn = FALSE) 59 | acc <- acc | .add_standir(pkgdir, "inst", "include", 60 | msg = TRUE, warn = FALSE) 61 | acc <- acc | .add_standir(pkgdir, "src", 62 | msg = TRUE, warn = FALSE) 63 | acc <- acc | .add_standir(pkgdir, "R", 64 | msg = TRUE, warn = FALSE) 65 | 66 | # add license.stan 67 | license <- .make_license(pkgdir, license) 68 | if (!is.null(license)) { 69 | .add_stanfile(license, pkgdir, 70 | "inst", "stan", "include", "license.stan", 71 | noedit = FALSE, msg = FALSE, warn = FALSE) 72 | } 73 | 74 | # add stan_meta_header.hpp 75 | meta_header <- .system_file("stan_meta_header.hpp") 76 | .add_stanfile(readLines(meta_header), pkgdir, 77 | "inst", "include", "stan_meta_header.hpp", 78 | noedit = FALSE, msg = FALSE, warn = FALSE) 79 | 80 | # add stan_init.cpp 81 | # not needed for compiling without src/stan_files subdirectory 82 | ## acc <- acc | .add_staninit(pkgdir) 83 | 84 | # add packages to DESCRIPTION file 85 | acc <- acc | .update_description(pkgdir, 86 | auto_config = auto_config, msg = TRUE) 87 | 88 | # add or remove configure files 89 | acc <- acc | any(.setup_configure(pkgdir, auto_config)) 90 | 91 | # modify NAMESPACE, or output instructions for how to do so 92 | acc <- acc | .update_namespace(pkgdir, msg = TRUE) 93 | if (!acc) { 94 | message("Stan functionality is already enabled.") 95 | } else { 96 | message("Done.") 97 | } 98 | invisible(acc) 99 | } 100 | 101 | # make (or read) license file from logical/character specification 102 | .make_license <- function(pkgdir, license) { 103 | if (is.logical(license) && !license) { 104 | # license == FALSE 105 | license <- NULL 106 | } else { 107 | if (is.logical(license)) { 108 | # default license 109 | license <- readLines(system.file("include", "sys", "lice_nse.stan", 110 | package = "rstantools")) 111 | license <- gsub("RSTAN_PACKAGE_NAME", basename(pkgdir), license) 112 | } else if (is.character(license)) { 113 | license <- readLines(license) 114 | } else { 115 | stop("license must be logical or character string.", call. = FALSE) 116 | } 117 | } 118 | license 119 | } 120 | 121 | 122 | # either updates the existing NAMESPACE if it is generic, 123 | # or produces a message for needed modifications. 124 | # msg: display message if NAMESPACE needs to be modified 125 | # return value: whether or not NAMESPACE needed to be modified 126 | .update_namespace <- function(pkgdir, msg = TRUE) { 127 | # read namespace file 128 | namespc <- file.path(pkgdir, "NAMESPACE") 129 | namespc <- readLines(namespc) 130 | # required namespace lines 131 | req_lines <- c("import(Rcpp)", 132 | "import(methods)", 133 | "importFrom(rstan, sampling)", 134 | "importFrom(rstantools, rstan_config)", 135 | "importFrom(RcppParallel, RcppParallelLibs)", 136 | paste0("useDynLib(", basename(pkgdir), 137 | ", .registration = TRUE)")) 138 | ## lib_req <- c(methods = NA, rcpp = NA, dynlib = NA) 139 | if (.is_generic_namespace(namespc)) { 140 | # automatically update default NAMESPACE 141 | if (msg) message("Updating NAMESPACE ...") 142 | writeLines(c("# Generated by roxygen2: fake comment so roxygen2 overwrites silently.", 143 | namespc[!grepl("^#", namespc)], 144 | req_lines), 145 | con = file.path(pkgdir, "NAMESPACE")) 146 | acc <- TRUE # namespace was modified 147 | } else { 148 | # print message stating required dependencies 149 | # format existing namespace with no white space 150 | # and one directive per line 151 | whitespc <- "[ \n\t\r\v\f]*" # any white space 152 | namespc <- namespc[!grepl("^#", namespc)] 153 | namespc <- paste0(namespc, collapse = "\n") 154 | namespc <- gsub(whitespc, "", namespc) 155 | namespc <- paste0(strsplit(namespc, split = "[)]")[[1]], ")") 156 | # check for namespace dependencies 157 | msg_lines <- NULL 158 | acc <- FALSE 159 | if (!.has_import(namespc, pkg = "Rcpp")) { 160 | # import(Rcpp) 161 | msg_lines <- c(msg_lines, req_lines[1]) 162 | acc <- TRUE 163 | } 164 | if (!.has_import(namespc, pkg = "methods")) { 165 | # import(methods) 166 | msg_lines <- c(msg_lines, req_lines[2]) 167 | acc <- TRUE 168 | } 169 | if (!.has_import(namespc, pkg = "rstan", fun = "sampling")) { 170 | # importFrom(rstan, sampling) 171 | msg_lines <- c(msg_lines, req_lines[3]) 172 | acc <- TRUE 173 | } 174 | if (!.has_import(namespc, pkg = "rstantools", fun = "rstan_config")) { 175 | # importFrom(rstantools, rstan_config) 176 | msg_lines <- c(msg_lines, req_lines[4]) 177 | acc <- TRUE 178 | } 179 | if (!.has_import(namespc, pkg = "RcppParallel", fun = "RcppParallelLibs")) { 180 | # importFrom(RcppParallel, RcppParallelLibs) 181 | msg_lines <- c(msg_lines, req_lines[5]) 182 | acc <- TRUE 183 | } 184 | dynlib <- paste0("^useDynLib[(]", basename(pkgdir), 185 | ",[.]registration=TRUE[)]") 186 | if (!any(grepl(dynlib, namespc))) { 187 | # useDynLib(RSTAN_PACKAGE_NAME, .registration = TRUE) 188 | msg_lines <- c(msg_lines, req_lines[6]) 189 | acc <- TRUE 190 | } 191 | if (acc && msg) { 192 | message("\nNext, add the following lines (e.g., via -package.R if using roxygen) to your NAMESPACE:\n\n", 193 | paste0(msg_lines, collapse = "\n"), "\n") 194 | } 195 | } 196 | invisible(acc) 197 | } 198 | 199 | # whether or not namespc imports given pkg, or given fun from pkg 200 | # assume namespc has been white space formatted 201 | .has_import <- function(namespc, pkg, fun) { 202 | # check if whole package is imported 203 | import_pkg <- any(grepl("^import[(]", namespc) & 204 | grepl(paste0("(,|[(])", pkg, "(,|[)])"), namespc)) 205 | if (missing(fun)) { 206 | import_pkg 207 | } else { 208 | # check if given function is imported 209 | import_pkg || any(grepl(paste0("^importFrom[(]", pkg, ",", fun, "[)]"), 210 | namespc)) 211 | } 212 | } 213 | 214 | # check whether namespace is generic 215 | .is_generic_namespace <- function(namespc) { 216 | # package.skeleton generic 217 | gen1 <- "exportPattern(\"^[[:alpha:]]+\")" 218 | # create_package generic 219 | gen2 <- c("# Generated by roxygen2: fake comment so roxygen2 overwrites silently.", 220 | "exportPattern(\"^[^\\\\.]\")") 221 | identical(namespc, gen1) || identical(namespc, gen2) 222 | } 223 | 224 | # add or remove configure files 225 | .setup_configure <- function(pkgdir, add = TRUE) { 226 | conf_names <- c("configure", "configure.win") 227 | if (add) { 228 | acc <- sapply(conf_names, function(conf_name) { 229 | config <- readLines(.system_file(conf_name)) 230 | .add_stanfile(config, pkgdir, conf_name, 231 | noedit = TRUE, msg = FALSE, warn = TRUE) 232 | }) 233 | if (any(acc)) message("Adding 'configure' files ...") 234 | # make scripts executable 235 | sapply(conf_names[acc], function(conf_name) { 236 | system(paste0('chmod +x "', file.path(pkgdir, conf_name), '"')) 237 | }) 238 | } else { 239 | acc <- sapply(conf_names, function(conf_name) { 240 | noedit_msg <- .rstantools_noedit(conf_name) 241 | conf_name <- file.path(pkgdir, conf_name) 242 | if (file.exists(conf_name) && 243 | (noedit_msg %in% readLines(conf_name, n = 5))) { 244 | file.remove(conf_name) # Stan file found. remove it 245 | } else FALSE # no stan file found 246 | }) 247 | if (any(acc)) message("Removing 'configure' files ...") 248 | } 249 | acc 250 | } 251 | 252 | #------------------------------------------------------------------------------- 253 | 254 | # compile work flow 255 | # 0. optionally create package with package.skeleton. 256 | # delete man files so install.packages produces no errors. 257 | # 1. create necessary dirs. 258 | # don't need to warn if they already exist, because nothing happens 259 | # then anyways. Add stan_meta_header.hpp and stan_init.cpp at this stage? 260 | # 2. update NAMESPACE. if NAMESPACE doesn't exist or is default exportPattern, 261 | # add useDynLib and import(Rcpp, methods). 262 | # Otherwise, tell user what's left to be done. 263 | # 3. add stan_files if any. 264 | # 4. configure stan_files specific compile + export instructions, i.e., 265 | # Makevars[.win] and stanmodels.R. If no stan_files are present, 266 | # these files should be removed. 267 | 268 | # question: what happens when no stan_files are present? 269 | # i think stan_init.cpp should still be present. otherwise, package doesn't 270 | # compile if NAMESPACE has useDynLib. how about stan_meta_header.cpp? 271 | # let's say for now just have it. 272 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | .onAttach <- function(...) { 2 | ver <- utils::packageVersion("rstantools") 3 | packageStartupMessage("This is rstantools version ", ver) 4 | } 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rstantools 2 | 3 | 4 | [![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/rstantools?color=blue)](https://cran.r-project.org/web/packages/rstantools) 5 | [![RStudio_CRAN_mirror_downloads_badge](https://cranlogs.r-pkg.org/badges/rstantools?color=blue)](https://cran.r-project.org/web/packages/rstantools) 6 | [![R-CMD-check](https://github.com/stan-dev/rstantools/workflows/R-CMD-check/badge.svg)](https://github.com/stan-dev/rstantools/actions) 7 | 8 | 9 | ### Overview 10 | 11 | The __rstantools__ package provides tools for developing R packages interfacing 12 | with [Stan](https://mc-stan.org/). The package vignettes provide guidelines and 13 | recommendations for developers as well as a demonstration of creating a working 14 | R package with a pre-compiled Stan program. 15 | 16 | * [Guidelines for developers of R Packages interfacing with Stan](https://mc-stan.org/rstantools/articles/developer-guidelines.html) 17 | 18 | * [Step by step guide for creating a package that depends on RStan](https://mc-stan.org/rstantools/articles/minimal-rstan-package.html) 19 | 20 | ### Resources 21 | 22 | * [mc-stan.org/rstantools](https://mc-stan.org/rstantools) (online documentation, vignettes) 23 | * [Ask a question](https://discourse.mc-stan.org) (Stan Forums on Discourse) 24 | * [Open an issue](https://github.com/stan-dev/rstantools/issues) (GitHub issues for bug reports, feature requests) 25 | 26 | ### Installation 27 | 28 | 29 | * Install from CRAN: 30 | 31 | ```r 32 | install.packages("rstantools") 33 | ``` 34 | 35 | * Install latest development version from GitHub: 36 | 37 | ```r 38 | # install.packages("remotes") 39 | remotes::install_github("stan-dev/rstantools") 40 | ``` 41 | 42 | This installation from GitHub will not build the vignettes, but we recommend 43 | viewing them online at [mc-stan.org/rstantools/articles](https://mc-stan.org/rstantools/articles/). 44 | -------------------------------------------------------------------------------- /inst/include/sys/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: RStanTest 2 | Type: Package 3 | Title: What the Package Does (One Line, Title Case) 4 | Version: 0.0.0.9000 5 | Date: 2018-04-04 6 | Authors@R: 7 | person(given = "First", 8 | family = "Last", 9 | role = c("aut", "cre"), 10 | email = "first.last@example.com") 11 | Description: What the package does (one paragraph). 12 | License: What license it uses 13 | Depends: R (>= 3.4.0) 14 | Imports: Rcpp (>= 0.12.0), methods, rstan (>= 2.18.1), rstantools, RcppParallel (>= 5.0.1) 15 | LinkingTo: StanHeaders (>= 2.18.0), rstan (>= 2.18.1), BH (>= 1.66.0), Rcpp (>= 0.12.0), RcppEigen (>= 0.3.3.3.0), RcppParallel (>= 5.0.1) 16 | SystemRequirements: GNU make 17 | Encoding: UTF-8 18 | LazyData: true 19 | -------------------------------------------------------------------------------- /inst/include/sys/Makevars: -------------------------------------------------------------------------------- 1 | STANHEADERS_SRC = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "message()" -e "cat(system.file('include', 'src', package = 'StanHeaders', mustWork = TRUE))" -e "message()" | grep "StanHeaders") 2 | 3 | STANC_FLAGS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "cat(ifelse(utils::packageVersion('rstan') >= '2.26', '-DUSE_STANC3',''))") 4 | PKG_CPPFLAGS = -I"../inst/include" -I"$(STANHEADERS_SRC)" -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DBOOST_MATH_OVERFLOW_ERROR_POLICY=errno_on_error $(STANC_FLAGS) -D_HAS_AUTO_PTR_ETC=0 5 | PKG_CXXFLAGS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::CxxFlags()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::CxxFlags()") 6 | PKG_LIBS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::RcppParallelLibs()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::LdFlags()") 7 | 8 | CXX_STD = CXX17 9 | -------------------------------------------------------------------------------- /inst/include/sys/Makevars.win: -------------------------------------------------------------------------------- 1 | STANHEADERS_SRC = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "message()" -e "cat(system.file('include', 'src', package = 'StanHeaders', mustWork = TRUE))" -e "message()" | grep "StanHeaders") 2 | 3 | STANC_FLAGS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "cat(ifelse(utils::packageVersion('rstan') >= '2.26', '-DUSE_STANC3',''))") 4 | PKG_CPPFLAGS = -I"../inst/include" -I"$(STANHEADERS_SRC)" -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DRCPP_PARALLEL_USE_TBB=1 $(STANC_FLAGS) -D_HAS_AUTO_PTR_ETC=0 5 | PKG_CXXFLAGS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::CxxFlags()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::CxxFlags()") 6 | PKG_LIBS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::RcppParallelLibs()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::LdFlags()") 7 | 8 | CXX_STD = CXX17 9 | -------------------------------------------------------------------------------- /inst/include/sys/Read_and_delete_me: -------------------------------------------------------------------------------- 1 | Stan-specific notes: 2 | 3 | * All '.stan' files containing stanmodel definitions must be placed in 'inst/stan'. 4 | * Additional files to be included by stanmodel definition files 5 | (via e.g., #include "mylib.stan") must be placed in any subfolder of 'inst/stan'. 6 | * Additional C++ files needed by any '.stan' file must be placed in 'inst/include', 7 | and can only interact with the Stan C++ library via '#include' directives 8 | placed in the file 'inst/include/stan_meta_header.hpp'. 9 | * The precompiled stanmodel objects will appear in a named list called 'stanmodels', 10 | and you can call them with e.g., 'rstan::sampling(stanmodels$foo, ...)' 11 | -------------------------------------------------------------------------------- /inst/include/sys/configure: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | "${R_HOME}/bin/Rscript" -e "rstantools::rstan_config()" 3 | -------------------------------------------------------------------------------- /inst/include/sys/configure.win: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "rstantools::rstan_config()" 3 | -------------------------------------------------------------------------------- /inst/include/sys/lice_nse.stan: -------------------------------------------------------------------------------- 1 | /* 2 | RSTAN_PACKAGE_NAME is free software: you can redistribute it and/or modify 3 | it under the terms of the GNU General Public License as published by 4 | the Free Software Foundation, either version 3 of the License, or 5 | (at your option) any later version. 6 | 7 | RSTAN_PACKAGE_NAME is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with RSTAN_PACKAGE_NAME. If not, see . 14 | */ 15 | -------------------------------------------------------------------------------- /inst/include/sys/rstanpkg-package.R: -------------------------------------------------------------------------------- 1 | #' The 'RSTAN_PACKAGE_NAME' package. 2 | #' 3 | #' @description A DESCRIPTION OF THE PACKAGE 4 | #' 5 | #' @docType package 6 | #' @name RSTAN_PACKAGE_NAME-package 7 | #' @aliases RSTAN_PACKAGE_NAME 8 | #' @useDynLib RSTAN_PACKAGE_NAME, .registration = TRUE 9 | #' @import methods 10 | #' @import Rcpp 11 | #' @importFrom rstan sampling 12 | #' @importFrom rstantools rstan_config 13 | #' @importFrom RcppParallel RcppParallelLibs 14 | #' 15 | #' @references 16 | #' RSTAN_REFERENCE 17 | #' 18 | NULL 19 | -------------------------------------------------------------------------------- /inst/include/sys/stan_meta_header.hpp: -------------------------------------------------------------------------------- 1 | // Insert all #include statements here 2 | -------------------------------------------------------------------------------- /inst/include/sys/stanmodels.R: -------------------------------------------------------------------------------- 1 | # names of stan models 2 | stanmodels <- "STAN_MODEL_NAME" 3 | 4 | # load each stan module 5 | Rcpp::loadModule("stan_fit4STAN_MODEL_NAME_mod", what = TRUE) 6 | 7 | # instantiate each stanmodel object 8 | stanmodels <- sapply(stanmodels, function(model_name) { 9 | # create C++ code for stan model 10 | stan_file <- if(dir.exists("stan")) "stan" else file.path("inst", "stan") 11 | stan_file <- file.path(stan_file, paste0(model_name, ".stan")) 12 | stanfit <- rstan::stanc_builder(stan_file, 13 | allow_undefined = TRUE, 14 | obfuscate_model_name = FALSE) 15 | stanfit$model_cpp <- list(model_cppname = stanfit$model_name, 16 | model_cppcode = stanfit$cppcode) 17 | # create stanmodel object 18 | methods::new(Class = "stanmodel", 19 | model_name = stanfit$model_name, 20 | model_code = stanfit$model_code, 21 | model_cpp = stanfit$model_cpp, 22 | mk_cppmodule = function(x) get(paste0("rstantools_model_", model_name))) 23 | }) 24 | -------------------------------------------------------------------------------- /inst/include/sys/travis.yml: -------------------------------------------------------------------------------- 1 | language: r 2 | sudo: false 3 | r: devel 4 | cache: packages 5 | 6 | latex: true 7 | 8 | 9 | env: 10 | matrix: 11 | - CXX_OLEVEL=2 CXX=clang++ 12 | 13 | matrix: 14 | include: 15 | - os: linux 16 | compiler: clang 17 | addons: 18 | apt: 19 | sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-5.0' ] 20 | packages: 21 | - llvm-5.0-dev 22 | env: 23 | - CXX_OLEVEL=2 CXX=clang++ 24 | 25 | 26 | before_install: 27 | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y 28 | - sudo apt-get update -q 29 | - mkdir -p ~/.R/ 30 | - echo "CXX = `R CMD config CXX`" >> ~/.R/Makevars 31 | - echo "CXXFLAGS = `R CMD config CXXFLAGS` -pedantic -g0 -flto -stdlib=libc++" >> ~/.R/Makevars 32 | - echo "LDFLAGS += -flto -stdlib=libc++" >> ~/.R/Makevars 33 | - export CLANG_EXTRA_ARG="" 34 | - if [[ $CXX = "clang++" ]] ; then export CLANG_EXTRA_ARG=" -Qunused-arguments -fcolor-diagnostics " ; fi 35 | - sed -i.bak "s/ g++/ ${CXX}${CLANG_EXTRA_ARG}/" ~/.R/Makevars 36 | - sed -i.bak "s/O[0-3]/O$CXX_OLEVEL/" ~/.R/Makevars 37 | 38 | script: 39 | - | 40 | travis_wait 42 R CMD build . 41 | travis_wait 59 R CMD check RSTAN_PACKAGE_NAME*tar.gz 42 | 43 | after_script: 44 | - tar -ztvf RSTAN_PACKAGE_NAME_*.tar.gz 45 | - echo ${NOT_CRAN} 46 | 47 | after_success: 48 | - travis_wait 40 tar -C .. -xf $PKG_TARBALL 49 | 50 | after_failure: 51 | - cat RSTAN_PACKAGE_NAME.Rcheck/00* 52 | -------------------------------------------------------------------------------- /man-roxygen/args-auto_config.R: -------------------------------------------------------------------------------- 1 | #' @param auto_config Whether to automatically configure Stan functionality 2 | #' whenever the package gets installed (see **Details**). Defaults to `TRUE`. 3 | -------------------------------------------------------------------------------- /man-roxygen/args-dots.R: -------------------------------------------------------------------------------- 1 | #' @param ... Arguments passed to methods. See the methods in the \pkg{rstanarm} 2 | #' package for examples. 3 | -------------------------------------------------------------------------------- /man-roxygen/args-license.R: -------------------------------------------------------------------------------- 1 | #' @param license Logical or character; whether or not to paste the contents of 2 | #' a \code{license.stan} file at the top of all Stan code, or path to such a 3 | #' file. If `TRUE` (the default) adds the `GPL (>= 3)` license (see 4 | #' **Details**). 5 | -------------------------------------------------------------------------------- /man-roxygen/args-object.R: -------------------------------------------------------------------------------- 1 | #' @param object The object to use. 2 | -------------------------------------------------------------------------------- /man-roxygen/args-pkgdir.R: -------------------------------------------------------------------------------- 1 | #' @param pkgdir Path to package root folder. 2 | -------------------------------------------------------------------------------- /man-roxygen/details-auto_config.R: -------------------------------------------------------------------------------- 1 | #' @details When `auto_config = TRUE`, a `configure[.win]` file is added to the 2 | #' package, calling [rstan_config()] whenever the package is installed. 3 | #' Consequently, the package must list \pkg{rstantools} in the `DESCRIPTION` 4 | #' Imports field for this mechanism to work. Setting `auto_config = FALSE` 5 | #' removes the package's dependency on \pkg{rstantools}, but the package then 6 | #' must be manually configured by running [rstan_config()] whenever 7 | #' `stanmodel` files in `inst/stan` are added, removed, or modified. 8 | -------------------------------------------------------------------------------- /man-roxygen/details-license.R: -------------------------------------------------------------------------------- 1 | #' @details In order to enable Stan functionality, \pkg{\link{rstantools}} 2 | #' copies some files to your package. Since these files are licensed as 3 | #' GPL >= 3, the same license applies to your package should you choose to 4 | #' distribute it. Even if you don't use \pkg{\link{rstantools}} to create 5 | #' your package, it is likely that you will be linking to \pkg{\link{Rcpp}} to 6 | #' export the Stan C++ `stanmodel` objects to \R. Since 7 | #' \pkg{\link{Rcpp}} is released under GPL >= 2, the same license would apply 8 | #' to your package upon distribution. 9 | -------------------------------------------------------------------------------- /man-roxygen/reference-randomised-pit.R: -------------------------------------------------------------------------------- 1 | #' @references Czado, C., Gneiting, T., and Held, L. (2009). 2 | #' Predictive Model Assessment for Count Data. 3 | #' *Biometrics*. 65(4), 1254-1261. 4 | #' doi:10.1111/j.1541-0420.2009.01191.x. 5 | #' Journal version: 6 | -------------------------------------------------------------------------------- /man-roxygen/section-running-stan.R: -------------------------------------------------------------------------------- 1 | #' @section Using the pre-compiled Stan programs in your package: The 2 | #' `stanmodel` objects corresponding to the Stan programs included with your 3 | #' package are stored in a list called `stanmodels`. To run one of the Stan 4 | #' programs from within an R function in your package just pass the 5 | #' appropriate element of the `stanmodels` list to one of the \pkg{rstan} 6 | #' functions for model fitting (e.g., `sampling()`). For example, for a Stan 7 | #' program `"foo.stan"` you would use `rstan::sampling(stanmodels$foo, ...)`. 8 | -------------------------------------------------------------------------------- /man-roxygen/seealso-get-help.R: -------------------------------------------------------------------------------- 1 | #' @seealso 2 | #' * After reading the guidelines for developers, if you have trouble setting up 3 | #' your package let us know on the the [Stan Forums](https://discourse.mc-stan.org) 4 | #' or at the \pkg{rstantools} GitHub [issue tracker](https://github.com/stan-dev/rstantools/issues). 5 | -------------------------------------------------------------------------------- /man-roxygen/seealso-rstanarm-pkg.R: -------------------------------------------------------------------------------- 1 | #' @seealso 2 | #' * The \pkg{rstanarm} package ([mc-stan.org/rstanarm](https://mc-stan.org/rstanarm/)) 3 | #' for example methods 4 | #' ([CRAN](https://CRAN.R-project.org/package=rstanarm), 5 | #' [GitHub](https://github.com/stan-dev/rstanarm)). 6 | -------------------------------------------------------------------------------- /man-roxygen/seealso-vignettes.R: -------------------------------------------------------------------------------- 1 | #' @seealso 2 | #' * Guidelines and recommendations for developers of \R packages 3 | #' interfacing with Stan and a demonstration getting a simple package working 4 | #' can be found in the vignettes included with \pkg{rstantools} and at 5 | #' [mc-stan.org/rstantools/articles](https://mc-stan.org/rstantools/articles/). 6 | -------------------------------------------------------------------------------- /man/bayes_R2.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/bayes_R2.R 3 | \name{bayes_R2} 4 | \alias{bayes_R2} 5 | \alias{bayes_R2.default} 6 | \alias{loo_R2} 7 | \title{Generic function and default method for Bayesian R-squared} 8 | \usage{ 9 | bayes_R2(object, ...) 10 | 11 | \method{bayes_R2}{default}(object, y, ...) 12 | 13 | loo_R2(object, ...) 14 | } 15 | \arguments{ 16 | \item{object}{The object to use.} 17 | 18 | \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} 19 | package for examples.} 20 | 21 | \item{y}{For the default method, a vector of \code{y} values the same length 22 | as the number of columns in the matrix used as \code{object}.} 23 | } 24 | \value{ 25 | \code{bayes_R2()} and \code{loo_R2()} methods should return a vector of 26 | length equal to the posterior sample size. 27 | 28 | The default \code{bayes_R2()} method just takes \code{object} to be a matrix of y-hat 29 | values (one column per observation, one row per posterior draw) and \code{y} to 30 | be a vector with length equal to \code{ncol(object)}. 31 | } 32 | \description{ 33 | Generic function and default method for Bayesian version of R-squared for 34 | regression models. A generic for LOO-adjusted R-squared is also provided. See 35 | the \href{https://mc-stan.org/rstanarm/reference/bayes_R2.stanreg.html}{bayes_R2.stanreg()} 36 | method in the \pkg{rstanarm} package for an example of defining a method. 37 | } 38 | \references{ 39 | Andrew Gelman, Ben Goodrich, Jonah Gabry, and Aki Vehtari (2018). R-squared 40 | for Bayesian regression models. \emph{The American Statistician}, to appear. 41 | DOI: 10.1080/00031305.2018.1549100. 42 | (\href{http://www.stat.columbia.edu/~gelman/research/published/bayes_R2_v3.pdf}{Preprint}, 43 | \href{https://avehtari.github.io/bayes_R2/bayes_R2.html}{Notebook}) 44 | } 45 | \seealso{ 46 | \itemize{ 47 | \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) 48 | for example methods 49 | (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, 50 | \href{https://github.com/stan-dev/rstanarm}{GitHub}). 51 | } 52 | 53 | \itemize{ 54 | \item Guidelines and recommendations for developers of \R packages 55 | interfacing with Stan and a demonstration getting a simple package working 56 | can be found in the vignettes included with \pkg{rstantools} and at 57 | \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /man/figures/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 97 | -------------------------------------------------------------------------------- /man/figures/stanlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stan-dev/rstantools/e5506cb154db04afd232405dda1a6c0537f41e7f/man/figures/stanlogo.png -------------------------------------------------------------------------------- /man/init_cpp.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/init_cpp.R 3 | \name{init_cpp} 4 | \alias{init_cpp} 5 | \title{Register functions implemented in C++} 6 | \usage{ 7 | init_cpp(name, path) 8 | } 9 | \arguments{ 10 | \item{name}{The name of your package as a string.} 11 | 12 | \item{path}{The path to the root directory for your package as a string. If 13 | not specified it is assumed that this is already the current working 14 | directory.} 15 | } 16 | \value{ 17 | This function is only called for its side effect of writing the 18 | necessary \code{init.cpp} file to the package's \verb{src/} directory. 19 | } 20 | \description{ 21 | If you set up your package using \code{rstan_package_skeleton()} before 22 | version \verb{1.2.1} of \pkg{rstantools} it may be necessary for you to call 23 | this function yourself in order to pass \verb{R CMD check} in \R 24 | \verb{>= 3.4}. If you used \code{rstan_package_skeleton()} in \pkg{rstantools} version 25 | \verb{1.2.1} or later then this has already been done automatically. 26 | } 27 | \keyword{internal} 28 | -------------------------------------------------------------------------------- /man/log_lik.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/log_lik.R 3 | \name{log_lik} 4 | \alias{log_lik} 5 | \title{Generic function for pointwise log-likelihood} 6 | \usage{ 7 | log_lik(object, ...) 8 | } 9 | \arguments{ 10 | \item{object}{The object to use.} 11 | 12 | \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} 13 | package for examples.} 14 | } 15 | \value{ 16 | \code{log_lik()} methods should return a \eqn{S} by \eqn{N} matrix, 17 | where \eqn{S} is the size of the posterior sample (the number of draws from 18 | the posterior distribution) and \eqn{N} is the number of data points. 19 | } 20 | \description{ 21 | We define a new function \code{log_lik()} rather than a 22 | \code{\link[stats:logLik]{stats::logLik()}} method because (in addition to the conceptual 23 | difference) the documentation for \code{logLik()} states that the return value 24 | will be a single number, whereas \code{log_lik()} returns a matrix. See 25 | the \href{https://mc-stan.org/rstanarm/reference/log_lik.stanreg.html}{log_lik.stanreg()} 26 | method in the \pkg{rstanarm} package for an example of defining a method. 27 | } 28 | \examples{ 29 | # See help("log_lik", package = "rstanarm") 30 | 31 | } 32 | \seealso{ 33 | \itemize{ 34 | \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) 35 | for example methods 36 | (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, 37 | \href{https://github.com/stan-dev/rstanarm}{GitHub}). 38 | } 39 | 40 | \itemize{ 41 | \item Guidelines and recommendations for developers of \R packages 42 | interfacing with Stan and a demonstration getting a simple package working 43 | can be found in the vignettes included with \pkg{rstantools} and at 44 | \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /man/loo-prediction.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/loo-functions.R 3 | \name{loo-prediction} 4 | \alias{loo-prediction} 5 | \alias{loo_linpred} 6 | \alias{loo_predict} 7 | \alias{loo_predictive_interval} 8 | \alias{loo_pit} 9 | \alias{loo_pit.default} 10 | \title{Generic functions for LOO predictions} 11 | \usage{ 12 | loo_linpred(object, ...) 13 | 14 | loo_predict(object, ...) 15 | 16 | loo_predictive_interval(object, ...) 17 | 18 | loo_pit(object, ...) 19 | 20 | \method{loo_pit}{default}(object, y, lw, ...) 21 | } 22 | \arguments{ 23 | \item{object}{The object to use.} 24 | 25 | \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} 26 | package for examples.} 27 | 28 | \item{y}{For the default method of \code{loo_pit()}, a vector of \code{y} values the 29 | same length as the number of columns in the matrix used as \code{object}.} 30 | 31 | \item{lw}{For the default method of \code{loo_pit()}, a matrix of log-weights of 32 | the same length as the number of columns in the matrix used as \code{object}.} 33 | } 34 | \value{ 35 | \code{loo_predict()}, \code{loo_linpred()}, and \code{loo_pit()} 36 | (probability integral transform) methods should return a vector with length 37 | equal to the number of observations in the data. 38 | For discrete observations, probability integral transform is randomised to 39 | ensure theoretical uniformity. Fix random seed for reproducible results 40 | with discrete data. For more details, see Czado et al. (2009). 41 | \code{loo_predictive_interval()} methods should return a two-column matrix 42 | formatted in the same way as for \code{\link[=predictive_interval]{predictive_interval()}}. 43 | } 44 | \description{ 45 | See the methods in the \pkg{rstanarm} package for examples. 46 | } 47 | \references{ 48 | Czado, C., Gneiting, T., and Held, L. (2009). 49 | Predictive Model Assessment for Count Data. 50 | \emph{Biometrics}. 65(4), 1254-1261. 51 | doi:10.1111/j.1541-0420.2009.01191.x. 52 | Journal version: \url{https://doi.org/10.1111/j.1541-0420.2009.01191.x} 53 | } 54 | \seealso{ 55 | \itemize{ 56 | \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) 57 | for example methods 58 | (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, 59 | \href{https://github.com/stan-dev/rstanarm}{GitHub}). 60 | } 61 | 62 | \itemize{ 63 | \item Guidelines and recommendations for developers of \R packages 64 | interfacing with Stan and a demonstration getting a simple package working 65 | can be found in the vignettes included with \pkg{rstantools} and at 66 | \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /man/nsamples.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/nsamples.R 3 | \name{nsamples} 4 | \alias{nsamples} 5 | \title{Generic function for extracting the number of posterior samples} 6 | \usage{ 7 | nsamples(object, ...) 8 | } 9 | \arguments{ 10 | \item{object}{The object to use.} 11 | 12 | \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} 13 | package for examples.} 14 | } 15 | \description{ 16 | Generic function for extracting the number of posterior samples 17 | } 18 | \keyword{internal} 19 | -------------------------------------------------------------------------------- /man/posterior_epred.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/posterior_epred.R 3 | \name{posterior_epred} 4 | \alias{posterior_epred} 5 | \title{Generic function for accessing the posterior distribution of the 6 | conditional expectation} 7 | \usage{ 8 | posterior_epred(object, ...) 9 | } 10 | \arguments{ 11 | \item{object}{The object to use.} 12 | 13 | \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} 14 | package for examples.} 15 | } 16 | \value{ 17 | \code{posterior_epred()} methods should return a \eqn{D} by \eqn{N} 18 | matrix, where \eqn{D} is the number of draws from the posterior 19 | distribution distribution and \eqn{N} is the number of data points. 20 | } 21 | \description{ 22 | Extract the posterior draws of the conditional expectation. 23 | See the \pkg{rstanarm} package for an example. 24 | } 25 | \seealso{ 26 | \itemize{ 27 | \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) 28 | for example methods 29 | (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, 30 | \href{https://github.com/stan-dev/rstanarm}{GitHub}). 31 | } 32 | 33 | \itemize{ 34 | \item Guidelines and recommendations for developers of \R packages 35 | interfacing with Stan and a demonstration getting a simple package working 36 | can be found in the vignettes included with \pkg{rstantools} and at 37 | \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /man/posterior_interval.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/posterior_interval.R 3 | \name{posterior_interval} 4 | \alias{posterior_interval} 5 | \alias{posterior_interval.default} 6 | \title{Generic function and default method for posterior uncertainty intervals} 7 | \usage{ 8 | posterior_interval(object, ...) 9 | 10 | \method{posterior_interval}{default}(object, prob = 0.9, ...) 11 | } 12 | \arguments{ 13 | \item{object}{The object to use.} 14 | 15 | \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} 16 | package for examples.} 17 | 18 | \item{prob}{A number \eqn{p \in (0,1)}{p (0 < p < 1)} indicating the desired 19 | probability mass to include in the intervals.} 20 | } 21 | \value{ 22 | \code{posterior_interval()} methods should return a matrix with two 23 | columns and as many rows as model parameters (or a subset of parameters 24 | specified by the user). For a given value of \code{prob}, \eqn{p}, the 25 | columns correspond to the lower and upper \eqn{100p}\\% interval limits and 26 | have the names \eqn{100\alpha/2}\\% and \eqn{100(1 - \alpha/2)}\\%, where 27 | \eqn{\alpha = 1-p}. For example, if \code{prob=0.9} is specified (a 28 | \eqn{90}\\% interval), then the column names would be \code{"5\%"} and 29 | \code{"95\%"}, respectively. 30 | 31 | The default method just takes \code{object} to be a matrix (one column per 32 | parameter) and computes quantiles, with \code{prob} defaulting to \code{0.9}. 33 | } 34 | \description{ 35 | These intervals are often referred to as credible intervals, but we use the 36 | term uncertainty intervals to highlight the fact that wider intervals 37 | correspond to greater uncertainty. See 38 | \href{https://mc-stan.org/rstanarm/reference/posterior_interval.stanreg.html}{posterior_interval.stanreg()} 39 | in the \pkg{rstanarm} package for an example. 40 | } 41 | \examples{ 42 | # Default method takes a numeric matrix (of posterior draws) 43 | draws <- matrix(rnorm(100 * 5), 100, 5) # fake draws 44 | colnames(draws) <- paste0("theta_", 1:5) 45 | posterior_interval(draws) 46 | 47 | # Also see help("posterior_interval", package = "rstanarm") 48 | 49 | } 50 | \seealso{ 51 | \itemize{ 52 | \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) 53 | for example methods 54 | (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, 55 | \href{https://github.com/stan-dev/rstanarm}{GitHub}). 56 | } 57 | 58 | \itemize{ 59 | \item Guidelines and recommendations for developers of \R packages 60 | interfacing with Stan and a demonstration getting a simple package working 61 | can be found in the vignettes included with \pkg{rstantools} and at 62 | \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /man/posterior_linpred.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/posterior_linpred.R 3 | \name{posterior_linpred} 4 | \alias{posterior_linpred} 5 | \title{Generic function for accessing the posterior distribution of the linear 6 | predictor} 7 | \usage{ 8 | posterior_linpred(object, transform = FALSE, ...) 9 | } 10 | \arguments{ 11 | \item{object}{The object to use.} 12 | 13 | \item{transform}{Should the linear predictor be transformed using the 14 | inverse-link function? The default is \code{FALSE}, in which case the 15 | untransformed linear predictor is returned.} 16 | 17 | \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} 18 | package for examples.} 19 | } 20 | \value{ 21 | \code{posterior_linpred()} methods should return a \eqn{D} by \eqn{N} 22 | matrix, where \eqn{D} is the number of draws from the posterior 23 | distribution distribution and \eqn{N} is the number of data points. 24 | } 25 | \description{ 26 | Extract the posterior draws of the linear predictor, possibly transformed by 27 | the inverse-link function. See 28 | \href{https://mc-stan.org/rstanarm/reference/posterior_linpred.stanreg.html}{posterior_linpred.stanreg()} 29 | in the \pkg{rstanarm} package for an example. 30 | } 31 | \examples{ 32 | # See help("posterior_linpred", package = "rstanarm") 33 | 34 | } 35 | \seealso{ 36 | \itemize{ 37 | \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) 38 | for example methods 39 | (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, 40 | \href{https://github.com/stan-dev/rstanarm}{GitHub}). 41 | } 42 | 43 | \itemize{ 44 | \item Guidelines and recommendations for developers of \R packages 45 | interfacing with Stan and a demonstration getting a simple package working 46 | can be found in the vignettes included with \pkg{rstantools} and at 47 | \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /man/posterior_predict.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/posterior_predict.R 3 | \name{posterior_predict} 4 | \alias{posterior_predict} 5 | \title{Generic function for drawing from the posterior predictive distribution} 6 | \usage{ 7 | posterior_predict(object, ...) 8 | } 9 | \arguments{ 10 | \item{object}{The object to use.} 11 | 12 | \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} 13 | package for examples.} 14 | } 15 | \value{ 16 | \code{posterior_predict()} methods should return a \eqn{D} by \eqn{N} 17 | matrix, where \eqn{D} is the number of draws from the posterior predictive 18 | distribution and \eqn{N} is the number of data points being predicted per 19 | draw. 20 | } 21 | \description{ 22 | Draw from the posterior predictive distribution of the outcome. See 23 | \href{https://mc-stan.org/rstanarm/reference/posterior_predict.stanreg.html}{posterior_predict.stanreg()} 24 | in the \pkg{rstanarm} package for an example. 25 | } 26 | \examples{ 27 | # See help("posterior_predict", package = "rstanarm") 28 | 29 | } 30 | \seealso{ 31 | \itemize{ 32 | \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) 33 | for example methods 34 | (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, 35 | \href{https://github.com/stan-dev/rstanarm}{GitHub}). 36 | } 37 | 38 | \itemize{ 39 | \item Guidelines and recommendations for developers of \R packages 40 | interfacing with Stan and a demonstration getting a simple package working 41 | can be found in the vignettes included with \pkg{rstantools} and at 42 | \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /man/predictive_error.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/predictive_error.R 3 | \name{predictive_error} 4 | \alias{predictive_error} 5 | \alias{predictive_error.default} 6 | \title{Generic function and default method for predictive errors} 7 | \usage{ 8 | predictive_error(object, ...) 9 | 10 | \method{predictive_error}{default}(object, y, ...) 11 | } 12 | \arguments{ 13 | \item{object}{The object to use.} 14 | 15 | \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} 16 | package for examples.} 17 | 18 | \item{y}{For the default method, a vector of \code{y} values the same length as 19 | the number of columns in the matrix used as \code{object}.} 20 | } 21 | \value{ 22 | \code{predictive_error()} methods should return a \eqn{D} by \eqn{N} 23 | matrix, where \eqn{D} is the number of draws from the posterior predictive 24 | distribution and \eqn{N} is the number of data points being predicted per 25 | draw. 26 | 27 | The default method just takes \code{object} to be a matrix and \code{y} to be a 28 | vector. 29 | } 30 | \description{ 31 | Generic function and default method for computing predictive errors 32 | \eqn{y - y^{rep}}{y - yrep} (in-sample, for observed \eqn{y}) or 33 | \eqn{y - \tilde{y}}{y - ytilde} (out-of-sample, for new or held-out \eqn{y}). 34 | See \href{https://mc-stan.org/rstanarm/reference/predictive_error.stanreg.html}{predictive_error.stanreg()} 35 | in the \pkg{rstanarm} package for an example. 36 | } 37 | \examples{ 38 | # default method 39 | y <- rnorm(10) 40 | ypred <- matrix(rnorm(500), 50, 10) 41 | pred_errors <- predictive_error(ypred, y) 42 | dim(pred_errors) 43 | head(pred_errors) 44 | 45 | # Also see help("predictive_error", package = "rstanarm") 46 | 47 | } 48 | \seealso{ 49 | \itemize{ 50 | \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) 51 | for example methods 52 | (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, 53 | \href{https://github.com/stan-dev/rstanarm}{GitHub}). 54 | } 55 | 56 | \itemize{ 57 | \item Guidelines and recommendations for developers of \R packages 58 | interfacing with Stan and a demonstration getting a simple package working 59 | can be found in the vignettes included with \pkg{rstantools} and at 60 | \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /man/predictive_interval.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/predictive_interval.R 3 | \name{predictive_interval} 4 | \alias{predictive_interval} 5 | \alias{predictive_interval.default} 6 | \title{Generic function for predictive intervals} 7 | \usage{ 8 | predictive_interval(object, ...) 9 | 10 | \method{predictive_interval}{default}(object, prob = 0.9, ...) 11 | } 12 | \arguments{ 13 | \item{object}{The object to use.} 14 | 15 | \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} 16 | package for examples.} 17 | 18 | \item{prob}{A number \eqn{p \in (0,1)}{p (0 < p < 1)} indicating the desired 19 | probability mass to include in the intervals.} 20 | } 21 | \value{ 22 | \code{predictive_interval()} methods should return a matrix with two 23 | columns and as many rows as data points being predicted. For a given value 24 | of \code{prob}, \eqn{p}, the columns correspond to the lower and upper 25 | \eqn{100p}\\% interval limits and have the names \eqn{100\alpha/2}\\% and 26 | \eqn{100(1 - \alpha/2)}\\%, where \eqn{\alpha = 1-p}. For example, if 27 | \code{prob=0.9} is specified (a \eqn{90}\\% interval), then the column names 28 | would be \code{"5\%"} and \code{"95\%"}, respectively. 29 | 30 | The default method just takes \code{object} to be a matrix and computes 31 | quantiles, with \code{prob} defaulting to \code{0.9}. 32 | } 33 | \description{ 34 | See \href{https://mc-stan.org/rstanarm/reference/predictive_interval.stanreg.html}{predictive_interval.stanreg()} 35 | in the \pkg{rstanarm} package for an example. 36 | } 37 | \examples{ 38 | # Default method takes a numeric matrix (of draws from posterior 39 | # predictive distribution) 40 | ytilde <- matrix(rnorm(100 * 5, sd = 2), 100, 5) # fake draws 41 | predictive_interval(ytilde, prob = 0.8) 42 | 43 | # Also see help("predictive_interval", package = "rstanarm") 44 | 45 | } 46 | \seealso{ 47 | \itemize{ 48 | \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) 49 | for example methods 50 | (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, 51 | \href{https://github.com/stan-dev/rstanarm}{GitHub}). 52 | } 53 | 54 | \itemize{ 55 | \item Guidelines and recommendations for developers of \R packages 56 | interfacing with Stan and a demonstration getting a simple package working 57 | can be found in the vignettes included with \pkg{rstantools} and at 58 | \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /man/prior_summary.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/prior_summary.R 3 | \name{prior_summary} 4 | \alias{prior_summary} 5 | \alias{prior_summary.default} 6 | \title{Generic function for extracting information about prior distributions} 7 | \usage{ 8 | prior_summary(object, ...) 9 | 10 | \method{prior_summary}{default}(object, ...) 11 | } 12 | \arguments{ 13 | \item{object}{The object to use.} 14 | 15 | \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} 16 | package for examples.} 17 | } 18 | \value{ 19 | \code{prior_summary()} methods should return an object containing 20 | information about the prior distribution(s) used for the given model. 21 | The structure of this object will depend on the method. 22 | 23 | The default method just returns \code{object$prior.info}, which is 24 | \code{NULL} if there is no \code{'prior.info'} element. 25 | } 26 | \description{ 27 | See \href{https://mc-stan.org/rstanarm/reference/prior_summary.stanreg.html}{prior_summary.stanreg()} 28 | in the \pkg{rstanarm} package for an example. 29 | } 30 | \examples{ 31 | # See help("prior_summary", package = "rstanarm") 32 | 33 | } 34 | \seealso{ 35 | \itemize{ 36 | \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) 37 | for example methods 38 | (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, 39 | \href{https://github.com/stan-dev/rstanarm}{GitHub}). 40 | } 41 | 42 | \itemize{ 43 | \item Guidelines and recommendations for developers of \R packages 44 | interfacing with Stan and a demonstration getting a simple package working 45 | can be found in the vignettes included with \pkg{rstantools} and at 46 | \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /man/rstan_config.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rstan_config.R 3 | \name{rstan_config} 4 | \alias{rstan_config} 5 | \title{Configure system files for compiling Stan source code} 6 | \usage{ 7 | rstan_config(pkgdir = ".") 8 | } 9 | \arguments{ 10 | \item{pkgdir}{Path to package root folder.} 11 | } 12 | \value{ 13 | Invisibly, whether or not any files were added/removed/modified by 14 | the function. 15 | } 16 | \description{ 17 | Creates or update package-specific system files to compile \code{.stan} model 18 | files found in \code{inst/stan}. 19 | } 20 | \details{ 21 | The Stan source files for the package should be stored in: 22 | \itemize{ 23 | \item \code{inst/stan} for \code{.stan} files containing instructions to 24 | build a \code{stanmodel} object. 25 | \item \code{inst/stan/any_subfolder} for files to be included via the 26 | \verb{#include "/my_subfolder/mylib.stan"} directive. 27 | \item \code{inst/stan/any_subfolder} for a \code{license.stan} file. 28 | \item \code{inst/include} for the \code{stan_meta_header.hpp} file, to be 29 | used for directly interacting with the Stan C++ libraries. 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /man/rstan_create_package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rstan_create_package.R 3 | \name{rstan_create_package} 4 | \alias{rstan_create_package} 5 | \alias{rstan_package_skeleton} 6 | \title{Create a new \R package with compiled Stan programs} 7 | \usage{ 8 | rstan_create_package( 9 | path, 10 | fields = NULL, 11 | rstudio = TRUE, 12 | open = TRUE, 13 | stan_files = character(), 14 | roxygen = TRUE, 15 | travis = FALSE, 16 | license = TRUE, 17 | auto_config = TRUE 18 | ) 19 | } 20 | \arguments{ 21 | \item{path}{The path to the new package to be created (terminating in the 22 | package name).} 23 | 24 | \item{fields, rstudio, open}{Same as \code{\link[usethis:create_package]{usethis::create_package()}}. See 25 | the documentation for that function, especially the note in the 26 | \strong{Description} section about the side effect of changing the active 27 | project.} 28 | 29 | \item{stan_files}{A character vector with paths to \code{.stan} files to include 30 | in the package.} 31 | 32 | \item{roxygen}{Should \pkg{roxygen2} be used for documentation? Defaults to 33 | \code{TRUE}. If so, a file \code{R/{pkgname}-package.R} is added to the package with 34 | roxygen tags for the required import lines. See the \strong{Note} section below 35 | for advice specific to the latest versions of \pkg{roxygen2}.} 36 | 37 | \item{travis}{Should a \code{.travis.yml} file be added to the package directory? 38 | This argument is now deprecated. We recommend using GitHub Actions to set 39 | up automated testings for your package. See 40 | https://github.com/r-lib/actions for useful templates.} 41 | 42 | \item{license}{Logical or character; whether or not to paste the contents of 43 | a \code{license.stan} file at the top of all Stan code, or path to such a 44 | file. If \code{TRUE} (the default) adds the \verb{GPL (>= 3)} license (see 45 | \strong{Details}).} 46 | 47 | \item{auto_config}{Whether to automatically configure Stan functionality 48 | whenever the package gets installed (see \strong{Details}). Defaults to \code{TRUE}.} 49 | } 50 | \description{ 51 | \if{html}{\figure{stanlogo.png}{options: width="25" alt="https://mc-stan.org/about/logo/"}} 52 | The \code{rstan_create_package()} function helps get you started developing a 53 | new \R package that interfaces with Stan via the \pkg{rstan} package. First 54 | the basic package structure is set up via \code{\link[usethis:create_package]{usethis::create_package()}}. 55 | Then several adjustments are made so the package can include Stan programs 56 | that can be built into binary versions (i.e., pre-compiled Stan C++ code). 57 | 58 | The \strong{Details} section below describes the process and the 59 | \strong{See Also} section provides links to recommendations for developers 60 | and a step-by-step walk-through. 61 | 62 | As of version \verb{2.0.0} of \pkg{rstantools} the 63 | \code{rstan_package_skeleton()} function is defunct and only 64 | \code{rstan_create_package()} is supported. 65 | } 66 | \details{ 67 | This function first creates a regular \R package using 68 | \code{usethis::create_package()}, then adds the infrastructure required to compile 69 | and export \code{stanmodel} objects. In the package root directory, the user's 70 | Stan source code is located in: 71 | \preformatted{ 72 | inst/ 73 | |_stan/ 74 | | |_include/ 75 | | 76 | |_include/ 77 | } 78 | All \code{.stan} files containing instructions to build a \code{stanmodel} 79 | object must be placed in \code{inst/stan}. Other \code{.stan} files go in 80 | any \verb{stan/} subdirectory, to be invoked by Stan's \verb{#include} 81 | mechanism, e.g., 82 | \preformatted{ 83 | #include "include/mylib.stan" 84 | #include "data/preprocess.stan" 85 | } 86 | See \pkg{rstanarm} for many examples. 87 | 88 | The folder \code{inst/include} is for all user C++ files associated with the 89 | Stan programs. In this folder, the only file to directly interact with the 90 | Stan C++ library is \code{stan_meta_header.hpp}; all other \verb{#include} 91 | directives must be channeled through here. 92 | 93 | The final step of the package creation is to invoke 94 | \code{\link[=rstan_config]{rstan_config()}}, which creates the following files for 95 | interfacing with Stan objects from \R: 96 | \itemize{ 97 | \item \code{src} contains the \verb{stan_ModelName\{.cc/.hpp\}} pairs 98 | associated with all \code{ModelName.stan} files in \code{inst/stan} which 99 | define \code{stanmodel} objects. 100 | \item \code{src/Makevars[.win]} which link to the \code{StanHeaders} and 101 | Boost (\code{BH}) libraries. 102 | \item \code{R/stanmodels.R} loads the C++ modules containing the 103 | \code{stanmodel} class definitions, and assigns an \R instance of each 104 | \code{stanmodel} object to a \code{stanmodels} list (with names 105 | corresponding to the names of the Stan files). 106 | } 107 | 108 | When \code{auto_config = TRUE}, a \code{configure[.win]} file is added to the 109 | package, calling \code{\link[=rstan_config]{rstan_config()}} whenever the package is installed. 110 | Consequently, the package must list \pkg{rstantools} in the \code{DESCRIPTION} 111 | Imports field for this mechanism to work. Setting \code{auto_config = FALSE} 112 | removes the package's dependency on \pkg{rstantools}, but the package then 113 | must be manually configured by running \code{\link[=rstan_config]{rstan_config()}} whenever 114 | \code{stanmodel} files in \code{inst/stan} are added, removed, or modified. 115 | 116 | In order to enable Stan functionality, \pkg{\link{rstantools}} 117 | copies some files to your package. Since these files are licensed as 118 | GPL >= 3, the same license applies to your package should you choose to 119 | distribute it. Even if you don't use \pkg{\link{rstantools}} to create 120 | your package, it is likely that you will be linking to \pkg{\link{Rcpp}} to 121 | export the Stan C++ \code{stanmodel} objects to \R. Since 122 | \pkg{\link{Rcpp}} is released under GPL >= 2, the same license would apply 123 | to your package upon distribution. 124 | 125 | Authors willing to license their Stan programs of general interest 126 | under the GPL are invited to contribute their \code{.stan} files and 127 | supporting \R code to the \pkg{rstanarm} package. 128 | } 129 | \note{ 130 | For \pkg{devtools} users, because of changes in the latest versions of 131 | \pkg{roxygen2} it may be necessary to run \code{pkgbuild::compile_dll()} 132 | once before \code{devtools::document()} will work. 133 | } 134 | \section{Using the pre-compiled Stan programs in your package}{ 135 | The 136 | \code{stanmodel} objects corresponding to the Stan programs included with your 137 | package are stored in a list called \code{stanmodels}. To run one of the Stan 138 | programs from within an R function in your package just pass the 139 | appropriate element of the \code{stanmodels} list to one of the \pkg{rstan} 140 | functions for model fitting (e.g., \code{sampling()}). For example, for a Stan 141 | program \code{"foo.stan"} you would use \code{rstan::sampling(stanmodels$foo, ...)}. 142 | } 143 | 144 | \seealso{ 145 | \itemize{ 146 | \item \code{\link[=use_rstan]{use_rstan()}} for adding Stan functionality to an existing 147 | \R package and \code{\link[=rstan_config]{rstan_config()}} for updating an existing package 148 | when its Stan files are changed. 149 | \item The \pkg{rstanarm} package \href{https://github.com/stan-dev/rstanarm}{repository} 150 | on GitHub. 151 | } 152 | 153 | \itemize{ 154 | \item Guidelines and recommendations for developers of \R packages 155 | interfacing with Stan and a demonstration getting a simple package working 156 | can be found in the vignettes included with \pkg{rstantools} and at 157 | \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. 158 | } 159 | 160 | \itemize{ 161 | \item After reading the guidelines for developers, if you have trouble setting up 162 | your package let us know on the the \href{https://discourse.mc-stan.org}{Stan Forums} 163 | or at the \pkg{rstantools} GitHub \href{https://github.com/stan-dev/rstantools/issues}{issue tracker}. 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /man/rstantools-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rstantools-package.R 3 | \docType{package} 4 | \name{rstantools-package} 5 | \alias{rstantools-package} 6 | \alias{rstantools} 7 | \title{Tools for Developing \R Packages Interfacing with Stan} 8 | \description{ 9 | \if{html}{ 10 | \figure{stanlogo.png}{options: width="50" alt="mc-stan.org"} 11 | } \emph{Stan Development Team} 12 | 13 | The \pkg{rstantools} package provides various tools for developers of \R 14 | packages interfacing with Stan (\url{https://mc-stan.org}), including 15 | functions to set up the required package structure, S3 generic methods to 16 | unify function naming across Stan-based \R packages, and vignettes with 17 | guidelines for developers. To get started building a package see 18 | \code{\link[=rstan_create_package]{rstan_create_package()}}. 19 | } 20 | \seealso{ 21 | \itemize{ 22 | \item Guidelines and recommendations for developers of \R packages 23 | interfacing with Stan and a demonstration getting a simple package working 24 | can be found in the vignettes included with \pkg{rstantools} and at 25 | \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. 26 | } 27 | 28 | \itemize{ 29 | \item After reading the guidelines for developers, if you have trouble setting up 30 | your package let us know on the the \href{https://discourse.mc-stan.org}{Stan Forums} 31 | or at the \pkg{rstantools} GitHub \href{https://github.com/stan-dev/rstantools/issues}{issue tracker}. 32 | } 33 | 34 | Useful links: 35 | \itemize{ 36 | \item \url{https://mc-stan.org/rstantools/} 37 | \item \url{https://discourse.mc-stan.org/} 38 | \item Report bugs at \url{https://github.com/stan-dev/rstantools/issues} 39 | } 40 | 41 | } 42 | \author{ 43 | \strong{Maintainer}: Jonah Gabry \email{jsg2201@columbia.edu} 44 | 45 | Authors: 46 | \itemize{ 47 | \item Ben Goodrich \email{benjamin.goodrich@columbia.edu} 48 | \item Martin Lysy \email{mlysy@uwaterloo.ca} 49 | \item Andrew Johnson 50 | } 51 | 52 | Other contributors: 53 | \itemize{ 54 | \item Hamada S. Badr [contributor] 55 | \item Marco Colombo [contributor] 56 | \item Stefan Siegert [contributor] 57 | \item Trustees of Columbia University [copyright holder] 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /man/rstantools_load_code.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rstan_package_utils.R 3 | \name{rstantools_load_code} 4 | \alias{rstantools_load_code} 5 | \title{Helper function for loading code in roxygenise} 6 | \usage{ 7 | rstantools_load_code(path, trace = TRUE, ...) 8 | } 9 | \arguments{ 10 | \item{path}{Path to directory containing code to load} 11 | 12 | \item{trace}{Whether to print file names as they are loaded} 13 | 14 | \item{...}{Additional arguments passed to \code{\link{source}}} 15 | } 16 | \value{ 17 | \code{NULL} 18 | } 19 | \description{ 20 | Adapted from the \code{sourceDir} function defined 21 | by \code{example(source)}. 22 | } 23 | -------------------------------------------------------------------------------- /man/use_rstan.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/use_rstan.R 3 | \name{use_rstan} 4 | \alias{use_rstan} 5 | \title{Add Stan infrastructure to an existing package} 6 | \usage{ 7 | use_rstan(pkgdir = ".", license = TRUE, auto_config = TRUE) 8 | } 9 | \arguments{ 10 | \item{pkgdir}{Path to package root folder.} 11 | 12 | \item{license}{Logical or character; whether or not to paste the contents of 13 | a \code{license.stan} file at the top of all Stan code, or path to such a 14 | file. If \code{TRUE} (the default) adds the \verb{GPL (>= 3)} license (see 15 | \strong{Details}).} 16 | 17 | \item{auto_config}{Whether to automatically configure Stan functionality 18 | whenever the package gets installed (see \strong{Details}). Defaults to \code{TRUE}.} 19 | } 20 | \value{ 21 | Invisibly, \code{TRUE} or \code{FALSE} indicating whether or not any files or 22 | folders where created or modified. 23 | } 24 | \description{ 25 | Add Stan infrastructure to an existing \R package. To create a \emph{new} package 26 | containing Stan programs use \code{\link[=rstan_create_package]{rstan_create_package()}} instead. 27 | } 28 | \details{ 29 | Prepares a package to compile and use Stan code by performing the 30 | following steps: 31 | \enumerate{ 32 | \item Create \code{inst/stan} folder where all \code{.stan} files defining 33 | Stan models should be stored. 34 | \item Create \code{inst/stan/include} where optional \code{license.stan} file is stored. 35 | \item Create \code{inst/include/stan_meta_header.hpp} to include optional header 36 | files used by Stan code. 37 | \item Create \code{src} folder (if it doesn't exist) to contain the Stan C++ code. 38 | \item Create \code{R} folder (if it doesn't exist) to contain wrapper code to expose 39 | Stan C++ classes to \R. 40 | \item Update \code{DESCRIPTION} file to contain all needed dependencies to compile 41 | Stan C++ code. 42 | \item If \code{NAMESPACE} file is generic (i.e., created by \code{\link[=rstan_create_package]{rstan_create_package()}}), 43 | append \code{import(Rcpp, methods)}, \code{importFrom(rstan, sampling)}, 44 | \code{importFrom(rstantools, rstan_config)}, \code{importFrom(RcppParallel, RcppParallelLibs)}, 45 | and \code{useDynLib} directives. If \code{NAMESPACE} is not generic, display message 46 | telling user what to add to \code{NAMESPACE} for themselves. 47 | } 48 | 49 | When \code{auto_config = TRUE}, a \code{configure[.win]} file is added to the 50 | package, calling \code{\link[=rstan_config]{rstan_config()}} whenever the package is installed. 51 | Consequently, the package must list \pkg{rstantools} in the \code{DESCRIPTION} 52 | Imports field for this mechanism to work. Setting \code{auto_config = FALSE} 53 | removes the package's dependency on \pkg{rstantools}, but the package then 54 | must be manually configured by running \code{\link[=rstan_config]{rstan_config()}} whenever 55 | \code{stanmodel} files in \code{inst/stan} are added, removed, or modified. 56 | } 57 | \section{Using the pre-compiled Stan programs in your package}{ 58 | The 59 | \code{stanmodel} objects corresponding to the Stan programs included with your 60 | package are stored in a list called \code{stanmodels}. To run one of the Stan 61 | programs from within an R function in your package just pass the 62 | appropriate element of the \code{stanmodels} list to one of the \pkg{rstan} 63 | functions for model fitting (e.g., \code{sampling()}). For example, for a Stan 64 | program \code{"foo.stan"} you would use \code{rstan::sampling(stanmodels$foo, ...)}. 65 | } 66 | 67 | -------------------------------------------------------------------------------- /rstantools.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageCheckArgs: --run-donttest 22 | PackageRoxygenize: rd,collate,namespace 23 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(rstantools) 3 | 4 | foo <- function(x) {"test function"} 5 | 6 | if (identical(Sys.getenv("TRAVIS"), "true")) { 7 | test_check("rstantools", filter = "methods") 8 | } else { 9 | test_check("rstantools") 10 | } 11 | 12 | -------------------------------------------------------------------------------- /tests/testthat/RStanTest/AddTest.cpp: -------------------------------------------------------------------------------- 1 | // check that additional C++ code in /src can coexist with Stan C++ code 2 | 3 | #include 4 | using namespace Rcpp; 5 | 6 | //[[Rcpp::export]] 7 | NumericVector add_test(NumericVector x, NumericVector y) { 8 | return x + y; 9 | } 10 | -------------------------------------------------------------------------------- /tests/testthat/RStanTest/NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(postsamp1) 4 | export(postsamp2) 5 | import(Rcpp) 6 | import(methods) 7 | importFrom(RcppParallel,RcppParallelLibs) 8 | importFrom(rstan,sampling) 9 | importFrom(rstantools,rstan_config) 10 | useDynLib(RStanTest, .registration = TRUE) 11 | -------------------------------------------------------------------------------- /tests/testthat/RStanTest/RStanTest-package.R: -------------------------------------------------------------------------------- 1 | #' Tools for Developing R Packages Interfacing with Stan 2 | #' 3 | #' @name RStanTest 4 | #' @docType package 5 | #' @import Rcpp 6 | #' @import methods 7 | #' @importFrom rstan sampling 8 | #' @useDynLib RStanTest, .registration = TRUE 9 | NULL 10 | -------------------------------------------------------------------------------- /tests/testthat/RStanTest/SimpleModel.stan: -------------------------------------------------------------------------------- 1 | // x ~ N(mu, 1) 2 | data { 3 | real x; 4 | } 5 | 6 | parameters { 7 | real mu; 8 | } 9 | 10 | model { 11 | x ~ normal(mu, 1); 12 | } 13 | -------------------------------------------------------------------------------- /tests/testthat/RStanTest/SimpleModel2.stan: -------------------------------------------------------------------------------- 1 | functions { 2 | #include /include/helper.stan 3 | } 4 | 5 | data { 6 | real x; 7 | } 8 | 9 | parameters { 10 | real sigma; 11 | } 12 | 13 | model { 14 | x ~ normal(0, sigma); 15 | } 16 | 17 | generated quantities { 18 | real alpha; 19 | alpha = foo(3.14); 20 | } 21 | -------------------------------------------------------------------------------- /tests/testthat/RStanTest/helper.stan: -------------------------------------------------------------------------------- 1 | real foo(real x) { 2 | return x; 3 | } 4 | -------------------------------------------------------------------------------- /tests/testthat/RStanTest/postsamp.R: -------------------------------------------------------------------------------- 1 | #' Posterior Sampler for SimpleModel 2 | #' @export 3 | postsamp1 <- function(x, nsamples) { 4 | sampling(object = stanmodels$SimpleModel, data = list(x = x), 5 | iter = nsamples, chains = 1) 6 | } 7 | 8 | #' Posterior Sampler for SimpleModel2 9 | #' @export 10 | postsamp2 <- function(x, nsamples) { 11 | sampling(object = stanmodels$SimpleModel2, data = list(x = x), 12 | iter = nsamples, chains = 1) 13 | } 14 | 15 | ## #' Posterior Sampler for SimpleModel3 16 | ## #' @export 17 | ## postsamp3 <- function(x, nsamples) { 18 | ## sampling(object = stanmodels$SimpleModel3, data = list(x = x), 19 | ## iter = nsamples, chains = 1) 20 | ## } 21 | -------------------------------------------------------------------------------- /tests/testthat/RStanTest/stanExports_SimpleModel.cc: -------------------------------------------------------------------------------- 1 | // Generated by rstantools. Do not edit by hand. 2 | 3 | #include 4 | using namespace Rcpp ; 5 | #include "stanExports_SimpleModel.h" 6 | 7 | RCPP_MODULE(stan_fit4SimpleModel_mod) { 8 | 9 | 10 | class_ >("model_SimpleModel") 11 | 12 | .constructor() 13 | 14 | 15 | .method("call_sampler", &rstan::stan_fit ::call_sampler) 16 | .method("param_names", &rstan::stan_fit ::param_names) 17 | .method("param_names_oi", &rstan::stan_fit ::param_names_oi) 18 | .method("param_fnames_oi", &rstan::stan_fit ::param_fnames_oi) 19 | .method("param_dims", &rstan::stan_fit ::param_dims) 20 | .method("param_dims_oi", &rstan::stan_fit ::param_dims_oi) 21 | .method("update_param_oi", &rstan::stan_fit ::update_param_oi) 22 | .method("param_oi_tidx", &rstan::stan_fit ::param_oi_tidx) 23 | .method("grad_log_prob", &rstan::stan_fit ::grad_log_prob) 24 | .method("log_prob", &rstan::stan_fit ::log_prob) 25 | .method("unconstrain_pars", &rstan::stan_fit ::unconstrain_pars) 26 | .method("constrain_pars", &rstan::stan_fit ::constrain_pars) 27 | .method("num_pars_unconstrained", &rstan::stan_fit ::num_pars_unconstrained) 28 | .method("unconstrained_param_names", &rstan::stan_fit ::unconstrained_param_names) 29 | .method("constrained_param_names", &rstan::stan_fit ::constrained_param_names) 30 | ; 31 | } 32 | -------------------------------------------------------------------------------- /tests/testthat/RStanTest/stanExports_SimpleModel.h: -------------------------------------------------------------------------------- 1 | // Generated by rstantools. Do not edit by hand. 2 | 3 | #ifndef MODELS_HPP 4 | #define MODELS_HPP 5 | #define STAN__SERVICES__COMMAND_HPP 6 | #include 7 | // Code generated by Stan version 2.18.0 8 | 9 | #include 10 | 11 | namespace model_SimpleModel_namespace { 12 | 13 | using std::istream; 14 | using std::string; 15 | using std::stringstream; 16 | using std::vector; 17 | using stan::io::dump; 18 | using stan::math::lgamma; 19 | using stan::model::prob_grad; 20 | using namespace stan::math; 21 | 22 | static int current_statement_begin__; 23 | 24 | stan::io::program_reader prog_reader__() { 25 | stan::io::program_reader reader; 26 | reader.add_event(0, 0, "start", "model_SimpleModel"); 27 | reader.add_event(14, 12, "end", "model_SimpleModel"); 28 | return reader; 29 | } 30 | 31 | #include 32 | class model_SimpleModel : public prob_grad { 33 | private: 34 | double x; 35 | public: 36 | model_SimpleModel(stan::io::var_context& context__, 37 | std::ostream* pstream__ = 0) 38 | : prob_grad(0) { 39 | ctor_body(context__, 0, pstream__); 40 | } 41 | 42 | model_SimpleModel(stan::io::var_context& context__, 43 | unsigned int random_seed__, 44 | std::ostream* pstream__ = 0) 45 | : prob_grad(0) { 46 | ctor_body(context__, random_seed__, pstream__); 47 | } 48 | 49 | void ctor_body(stan::io::var_context& context__, 50 | unsigned int random_seed__, 51 | std::ostream* pstream__) { 52 | typedef double local_scalar_t__; 53 | 54 | boost::ecuyer1988 base_rng__ = 55 | stan::services::util::create_rng(random_seed__, 0); 56 | (void) base_rng__; // suppress unused var warning 57 | 58 | current_statement_begin__ = -1; 59 | 60 | static const char* function__ = "model_SimpleModel_namespace::model_SimpleModel"; 61 | (void) function__; // dummy to suppress unused var warning 62 | size_t pos__; 63 | (void) pos__; // dummy to suppress unused var warning 64 | std::vector vals_i__; 65 | std::vector vals_r__; 66 | local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); 67 | (void) DUMMY_VAR__; // suppress unused var warning 68 | 69 | // initialize member variables 70 | try { 71 | current_statement_begin__ = 3; 72 | context__.validate_dims("data initialization", "x", "double", context__.to_vec()); 73 | x = double(0); 74 | vals_r__ = context__.vals_r("x"); 75 | pos__ = 0; 76 | x = vals_r__[pos__++]; 77 | 78 | // validate, data variables 79 | current_statement_begin__ = 3; 80 | // initialize data variables 81 | 82 | 83 | // validate transformed data 84 | 85 | // validate, set parameter ranges 86 | num_params_r__ = 0U; 87 | param_ranges_i__.clear(); 88 | current_statement_begin__ = 7; 89 | ++num_params_r__; 90 | } catch (const std::exception& e) { 91 | stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__()); 92 | // Next line prevents compiler griping about no return 93 | throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***"); 94 | } 95 | } 96 | 97 | ~model_SimpleModel() { } 98 | 99 | 100 | void transform_inits(const stan::io::var_context& context__, 101 | std::vector& params_i__, 102 | std::vector& params_r__, 103 | std::ostream* pstream__) const { 104 | stan::io::writer writer__(params_r__,params_i__); 105 | size_t pos__; 106 | (void) pos__; // dummy call to supress warning 107 | std::vector vals_r__; 108 | std::vector vals_i__; 109 | 110 | if (!(context__.contains_r("mu"))) 111 | throw std::runtime_error("variable mu missing"); 112 | vals_r__ = context__.vals_r("mu"); 113 | pos__ = 0U; 114 | context__.validate_dims("initialization", "mu", "double", context__.to_vec()); 115 | double mu(0); 116 | mu = vals_r__[pos__++]; 117 | try { 118 | writer__.scalar_unconstrain(mu); 119 | } catch (const std::exception& e) { 120 | throw std::runtime_error(std::string("Error transforming variable mu: ") + e.what()); 121 | } 122 | 123 | params_r__ = writer__.data_r(); 124 | params_i__ = writer__.data_i(); 125 | } 126 | 127 | void transform_inits(const stan::io::var_context& context, 128 | Eigen::Matrix& params_r, 129 | std::ostream* pstream__) const { 130 | std::vector params_r_vec; 131 | std::vector params_i_vec; 132 | transform_inits(context, params_i_vec, params_r_vec, pstream__); 133 | params_r.resize(params_r_vec.size()); 134 | for (int i = 0; i < params_r.size(); ++i) 135 | params_r(i) = params_r_vec[i]; 136 | } 137 | 138 | 139 | template 140 | T__ log_prob(vector& params_r__, 141 | vector& params_i__, 142 | std::ostream* pstream__ = 0) const { 143 | 144 | typedef T__ local_scalar_t__; 145 | 146 | local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); 147 | (void) DUMMY_VAR__; // suppress unused var warning 148 | 149 | T__ lp__(0.0); 150 | stan::math::accumulator lp_accum__; 151 | 152 | try { 153 | // model parameters 154 | stan::io::reader in__(params_r__,params_i__); 155 | 156 | local_scalar_t__ mu; 157 | (void) mu; // dummy to suppress unused var warning 158 | if (jacobian__) 159 | mu = in__.scalar_constrain(lp__); 160 | else 161 | mu = in__.scalar_constrain(); 162 | 163 | 164 | // transformed parameters 165 | 166 | 167 | 168 | // validate transformed parameters 169 | 170 | const char* function__ = "validate transformed params"; 171 | (void) function__; // dummy to suppress unused var warning 172 | 173 | // model body 174 | 175 | current_statement_begin__ = 11; 176 | lp_accum__.add(normal_log(x, mu, 1)); 177 | 178 | } catch (const std::exception& e) { 179 | stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__()); 180 | // Next line prevents compiler griping about no return 181 | throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***"); 182 | } 183 | 184 | lp_accum__.add(lp__); 185 | return lp_accum__.sum(); 186 | 187 | } // log_prob() 188 | 189 | template 190 | T_ log_prob(Eigen::Matrix& params_r, 191 | std::ostream* pstream = 0) const { 192 | std::vector vec_params_r; 193 | vec_params_r.reserve(params_r.size()); 194 | for (int i = 0; i < params_r.size(); ++i) 195 | vec_params_r.push_back(params_r(i)); 196 | std::vector vec_params_i; 197 | return log_prob(vec_params_r, vec_params_i, pstream); 198 | } 199 | 200 | 201 | void get_param_names(std::vector& names__) const { 202 | names__.resize(0); 203 | names__.push_back("mu"); 204 | } 205 | 206 | 207 | void get_dims(std::vector >& dimss__) const { 208 | dimss__.resize(0); 209 | std::vector dims__; 210 | dims__.resize(0); 211 | dimss__.push_back(dims__); 212 | } 213 | 214 | template 215 | void write_array(RNG& base_rng__, 216 | std::vector& params_r__, 217 | std::vector& params_i__, 218 | std::vector& vars__, 219 | bool include_tparams__ = true, 220 | bool include_gqs__ = true, 221 | std::ostream* pstream__ = 0) const { 222 | typedef double local_scalar_t__; 223 | 224 | vars__.resize(0); 225 | stan::io::reader in__(params_r__,params_i__); 226 | static const char* function__ = "model_SimpleModel_namespace::write_array"; 227 | (void) function__; // dummy to suppress unused var warning 228 | // read-transform, write parameters 229 | double mu = in__.scalar_constrain(); 230 | vars__.push_back(mu); 231 | 232 | // declare and define transformed parameters 233 | double lp__ = 0.0; 234 | (void) lp__; // dummy to suppress unused var warning 235 | stan::math::accumulator lp_accum__; 236 | 237 | local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); 238 | (void) DUMMY_VAR__; // suppress unused var warning 239 | 240 | try { 241 | 242 | 243 | 244 | // validate transformed parameters 245 | 246 | // write transformed parameters 247 | if (include_tparams__) { 248 | } 249 | if (!include_gqs__) return; 250 | // declare and define generated quantities 251 | 252 | 253 | 254 | // validate generated quantities 255 | 256 | // write generated quantities 257 | } catch (const std::exception& e) { 258 | stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__()); 259 | // Next line prevents compiler griping about no return 260 | throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***"); 261 | } 262 | } 263 | 264 | template 265 | void write_array(RNG& base_rng, 266 | Eigen::Matrix& params_r, 267 | Eigen::Matrix& vars, 268 | bool include_tparams = true, 269 | bool include_gqs = true, 270 | std::ostream* pstream = 0) const { 271 | std::vector params_r_vec(params_r.size()); 272 | for (int i = 0; i < params_r.size(); ++i) 273 | params_r_vec[i] = params_r(i); 274 | std::vector vars_vec; 275 | std::vector params_i_vec; 276 | write_array(base_rng,params_r_vec,params_i_vec,vars_vec,include_tparams,include_gqs,pstream); 277 | vars.resize(vars_vec.size()); 278 | for (int i = 0; i < vars.size(); ++i) 279 | vars(i) = vars_vec[i]; 280 | } 281 | 282 | static std::string model_name() { 283 | return "model_SimpleModel"; 284 | } 285 | 286 | 287 | void constrained_param_names(std::vector& param_names__, 288 | bool include_tparams__ = true, 289 | bool include_gqs__ = true) const { 290 | std::stringstream param_name_stream__; 291 | param_name_stream__.str(std::string()); 292 | param_name_stream__ << "mu"; 293 | param_names__.push_back(param_name_stream__.str()); 294 | 295 | if (!include_gqs__ && !include_tparams__) return; 296 | 297 | if (include_tparams__) { 298 | } 299 | 300 | 301 | if (!include_gqs__) return; 302 | } 303 | 304 | 305 | void unconstrained_param_names(std::vector& param_names__, 306 | bool include_tparams__ = true, 307 | bool include_gqs__ = true) const { 308 | std::stringstream param_name_stream__; 309 | param_name_stream__.str(std::string()); 310 | param_name_stream__ << "mu"; 311 | param_names__.push_back(param_name_stream__.str()); 312 | 313 | if (!include_gqs__ && !include_tparams__) return; 314 | 315 | if (include_tparams__) { 316 | } 317 | 318 | 319 | if (!include_gqs__) return; 320 | } 321 | 322 | }; // model 323 | 324 | } 325 | 326 | typedef model_SimpleModel_namespace::model_SimpleModel stan_model; 327 | 328 | 329 | #endif 330 | -------------------------------------------------------------------------------- /tests/testthat/RStanTest/stanExports_SimpleModel2.cc: -------------------------------------------------------------------------------- 1 | // Generated by rstantools. Do not edit by hand. 2 | 3 | #include 4 | using namespace Rcpp ; 5 | #include "stanExports_SimpleModel2.h" 6 | 7 | RCPP_MODULE(stan_fit4SimpleModel2_mod) { 8 | 9 | 10 | class_ >("model_SimpleModel2") 11 | 12 | .constructor() 13 | 14 | 15 | .method("call_sampler", &rstan::stan_fit ::call_sampler) 16 | .method("param_names", &rstan::stan_fit ::param_names) 17 | .method("param_names_oi", &rstan::stan_fit ::param_names_oi) 18 | .method("param_fnames_oi", &rstan::stan_fit ::param_fnames_oi) 19 | .method("param_dims", &rstan::stan_fit ::param_dims) 20 | .method("param_dims_oi", &rstan::stan_fit ::param_dims_oi) 21 | .method("update_param_oi", &rstan::stan_fit ::update_param_oi) 22 | .method("param_oi_tidx", &rstan::stan_fit ::param_oi_tidx) 23 | .method("grad_log_prob", &rstan::stan_fit ::grad_log_prob) 24 | .method("log_prob", &rstan::stan_fit ::log_prob) 25 | .method("unconstrain_pars", &rstan::stan_fit ::unconstrain_pars) 26 | .method("constrain_pars", &rstan::stan_fit ::constrain_pars) 27 | .method("num_pars_unconstrained", &rstan::stan_fit ::num_pars_unconstrained) 28 | .method("unconstrained_param_names", &rstan::stan_fit ::unconstrained_param_names) 29 | .method("constrained_param_names", &rstan::stan_fit ::constrained_param_names) 30 | ; 31 | } 32 | -------------------------------------------------------------------------------- /tests/testthat/RStanTest/test-add_test.R: -------------------------------------------------------------------------------- 1 | context("add_test") 2 | 3 | test_that("external C++ code works", { 4 | n <- sample(1:20, 1) 5 | x <- rnorm(n) 6 | y <- rnorm(n) 7 | expect_equal(add_test(x, y), x + y) 8 | }) 9 | -------------------------------------------------------------------------------- /tests/testthat/RStanTest/test-postsamp.R: -------------------------------------------------------------------------------- 1 | require(rstan) # for log_prob & unconstrain_pars 2 | 3 | stan_quiet <- function(expr) { 4 | suppressMessages(suppressWarnings(expr)) 5 | } 6 | 7 | context("postsamp") 8 | 9 | test_that("postsamp1: logposterior", { 10 | # data 11 | x <- rnorm(1) 12 | logpost <- stan_quiet(postsamp1(x = x, nsamples = 1)) 13 | # parameter values 14 | nsim <- sample(20:30, 1) 15 | Pars <- replicate(n = nsim, expr = { 16 | list(mu = rnorm(1)) 17 | }, simplify = FALSE) 18 | # log-posterior in R 19 | lpR <- sapply(1:nsim, function(ii) { 20 | mu <- Pars[[ii]]$mu 21 | dnorm(x, mu, 1, log = TRUE) 22 | }) 23 | # log-posterior in stan 24 | lpStan <- sapply(1:nsim, function(ii) { 25 | upars <- unconstrain_pars(object = logpost, pars = Pars[[ii]]) 26 | log_prob(object = logpost, upars = upars, adjust_transform = FALSE) 27 | }) 28 | expect_equal(max(abs(diff(lpR-lpStan))), 0, tolerance = 1e-6) 29 | }) 30 | 31 | test_that("postsamp2: logposterior", { 32 | # data 33 | x <- rnorm(1) 34 | logpost <- stan_quiet(postsamp2(x = x, nsamples = 1)) 35 | # parameter values 36 | nsim <- sample(20:30, 1) 37 | Pars <- replicate(n = nsim, expr = { 38 | list(sigma = runif(1, .2, 4)) 39 | }, simplify = FALSE) 40 | # log-posterior in R 41 | lpR <- sapply(1:nsim, function(ii) { 42 | sigma <- Pars[[ii]]$sigma 43 | dnorm(x, 0, sigma, log = TRUE) 44 | }) 45 | # log-posterior in stan 46 | lpStan <- sapply(1:nsim, function(ii) { 47 | upars <- unconstrain_pars(object = logpost, pars = Pars[[ii]]) 48 | log_prob(object = logpost, upars = upars, adjust_transform = FALSE) 49 | }) 50 | expect_equal(max(abs(diff(lpR-lpStan))), 0, tolerance = 1e-6) 51 | }) 52 | -------------------------------------------------------------------------------- /tests/testthat/RStanTest/test-rstan_package_skeleton_plus.R: -------------------------------------------------------------------------------- 1 | # walkthrough for using package skeleton 2 | 3 | require(rstantools) 4 | 5 | # change directory to where this file is located 6 | pkg_path <- getwd() 7 | 8 | #--- step 0: create a package without Stan code -------------------------------- 9 | 10 | # if you want to create an entire package with Stan code from scratch, 11 | # skip to step 5 12 | 13 | pkg_name <- "RStanTest" 14 | package.skeleton(name = pkg_name, 15 | code_files = "postsamp.R") 16 | # delete contents of "man" and NAMESPACE so roxygen2 can be used 17 | file.remove(list.files(file.path(pkg_path, pkg_name, "man"), 18 | full.names = TRUE)) 19 | file.remove(file.path(pkg_path, pkg_name, "NAMESPACE")) 20 | 21 | # add testthat tests 22 | usethis::use_testthat(pkg_name) 23 | file.copy(from = "test-postsamp.R", 24 | to = file.path(pkg_name, "tests", "testthat", "test-postsamp.R")) 25 | 26 | # setup documentation with roxygen2 27 | roxygen2::roxygenize(pkg_name) 28 | 29 | #--- Step 1: add Stan functionality to package --------------------------------- 30 | 31 | # this sets up the package to do this 32 | rstantools::use_rstan(pkg_name) 33 | 34 | # follow the instructions to add to the NAMESPACE 35 | # since we're using roxygen2, the right way to do this is to 36 | # add the lines to an R file in the package. 37 | # I like to make this the R/RStanTest-package.R file 38 | 39 | file.copy(from = file.path(pkg_path, "RStanTest-package.R"), 40 | to = file.path(pkg_path, pkg_name, "R", "RStanTest-package.R")) 41 | 42 | #--- Step 2: add Stan files to package ----------------------------------------- 43 | 44 | # copy stan_files to inst/stan 45 | stan_files <- c("SimpleModel.stan", "SimpleModel2.stan") 46 | file.copy(from = file.path(pkg_path, stan_files), 47 | to = file.path(pkg_path, pkg_name, "inst", "stan", stan_files)) 48 | 49 | # configure package to create C++ code associated with stan_files 50 | # ***NOTE*** You MUST run this every time you 51 | # modify/add/delete anything in inst/stan 52 | rstantools::rstan_config(pkg_name) 53 | 54 | 55 | # re-roxygen2, which will automatically compile package 56 | roxygen2::roxygenize(pkg_name) 57 | 58 | #--- step 4: install package and run tests ------------------------------------- 59 | 60 | utils::install.packages(pkg_name, repos = NULL, type = "source") 61 | 62 | # quit and restart, then: 63 | testthat::test_package("RStanTest", reporter = "progress") 64 | 65 | 66 | #--- step 5: create an entire package with Stan code from scratch -------------- 67 | 68 | pkg_path <- getwd() 69 | pkg_name <- "RStanTest" 70 | code_files <- c("RStanTest-package.R", "postsamp.R") 71 | stan_files <- c("SimpleModel.stan", "SimpleModel2.stan") 72 | 73 | rstantools::rstan_package_skeleton_plus(name = pkg_name, 74 | path = pkg_path, 75 | code_files = code_files, 76 | stan_files = stan_files) 77 | # add tests 78 | usethis::use_testthat(pkg_name) 79 | file.copy(from = "test-postsamp.R", 80 | to = file.path(pkg_name, "tests", "testthat", "test-postsamp.R")) 81 | 82 | # roxygen2 can't overwrite NAMESPACE unless it created it, 83 | # so trick it into thinking it did 84 | # (and add the rstan stuff or else you get errors...) 85 | writeLines(c("# Generated by roxygen2: do not edit by hand", 86 | "", 87 | "import(Rcpp,methods)", 88 | "useDynLib(RStanTest, .registration = TRUE)"), 89 | con = file.path(pkg_path, pkg_name, "NAMESPACE")) 90 | 91 | roxygen2::roxygenize(pkg_name) # run roxygen2 92 | utils::install.packages(pkg_name, repos = NULL, type = "source") 93 | 94 | # quit and restart, then: 95 | testthat::test_package("RStanTest", reporter = "progress") 96 | 97 | -------------------------------------------------------------------------------- /tests/testthat/bayes_R2.RDS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stan-dev/rstantools/e5506cb154db04afd232405dda1a6c0537f41e7f/tests/testthat/bayes_R2.RDS -------------------------------------------------------------------------------- /tests/testthat/loo_pit.RDS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stan-dev/rstantools/e5506cb154db04afd232405dda1a6c0537f41e7f/tests/testthat/loo_pit.RDS -------------------------------------------------------------------------------- /tests/testthat/loo_pit_discrete.RDS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stan-dev/rstantools/e5506cb154db04afd232405dda1a6c0537f41e7f/tests/testthat/loo_pit_discrete.RDS -------------------------------------------------------------------------------- /tests/testthat/posterior_interval.RDS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stan-dev/rstantools/e5506cb154db04afd232405dda1a6c0537f41e7f/tests/testthat/posterior_interval.RDS -------------------------------------------------------------------------------- /tests/testthat/predictive_error.RDS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stan-dev/rstantools/e5506cb154db04afd232405dda1a6c0537f41e7f/tests/testthat/predictive_error.RDS -------------------------------------------------------------------------------- /tests/testthat/predictive_interval.RDS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stan-dev/rstantools/e5506cb154db04afd232405dda1a6c0537f41e7f/tests/testthat/predictive_interval.RDS -------------------------------------------------------------------------------- /tests/testthat/rstan_package_skeleton-testfunctions.R: -------------------------------------------------------------------------------- 1 | # run things silently 2 | eval_quiet <- function(expr, no_warnings = FALSE) { 3 | if(no_warnings) { 4 | suppressMessages(suppressWarnings(expr)) 5 | } else { 6 | suppressMessages(expr) 7 | } 8 | } 9 | 10 | eval_quiet(require(rstan)) # for log_prob & unconstrain_pars 11 | 12 | 13 | #--------------------------------------------------------------------------- 14 | 15 | # return R and Stan log-posteriors for same parameter values 16 | 17 | # R/Stan diff check for postsamp1 18 | compare_postsamp1 <- function() { 19 | # simulate data 20 | x <- rnorm(1) 21 | logpost <- eval_quiet(postsamp1(x = x, nsamples = 1), no_warnings = TRUE) 22 | # parameter values 23 | ntest <- sample(20:30, 1) 24 | Pars <- replicate(n = ntest, expr = { 25 | list(mu = rnorm(1)) 26 | }, simplify = FALSE) 27 | # log-posterior in R 28 | lpR <- sapply(1:ntest, function(ii) { 29 | mu <- Pars[[ii]]$mu 30 | dnorm(x, mu, 1, log = TRUE) 31 | }) 32 | # log-posterior in Stan 33 | lpStan <- sapply(1:ntest, function(ii) { 34 | upars <- unconstrain_pars(object = logpost, pars = Pars[[ii]]) 35 | log_prob(object = logpost, upars = upars, adjust_transform = FALSE) 36 | }) 37 | # check that they differ by only a constant 38 | expect_equal(max(abs(diff(lpR-lpStan))), 0, tolerance = 1e-6) 39 | } 40 | 41 | # R/Stan diff check for postsamp2 42 | compare_postsamp2 <- function() { 43 | # simulate data 44 | x <- rnorm(1) 45 | logpost <- eval_quiet(postsamp2(x = x, nsamples = 1), no_warnings = TRUE) 46 | # parameter values 47 | ntest <- sample(20:30, 1) 48 | Pars <- replicate(n = ntest, expr = { 49 | list(sigma = runif(1, .2, 4)) 50 | }, simplify = FALSE) 51 | # log-posterior in R 52 | lpR <- sapply(1:ntest, function(ii) { 53 | sigma <- Pars[[ii]]$sigma 54 | dnorm(x, 0, sigma, log = TRUE) 55 | }) 56 | # log-posterior in Stan 57 | lpStan <- sapply(1:ntest, function(ii) { 58 | upars <- unconstrain_pars(object = logpost, pars = Pars[[ii]]) 59 | log_prob(object = logpost, upars = upars, adjust_transform = FALSE) 60 | }) 61 | # check that they differ by only a constant 62 | expect_equal(max(abs(diff(lpR-lpStan))), 0, tolerance = 1e-6) 63 | } 64 | 65 | #------------------------------------------------------------------------------- 66 | 67 | # check contents of src files 68 | check_lines <- function(stan_file, pkg_src_path, pkg_dest_path) { 69 | sf <- sub("\\.stan$", "", basename(stan_file)) 70 | for(ext in c(".cc", ".h")) { 71 | src_files <- rstantools:::.stan_prefix(sf, ext) 72 | src_files <- c(file.path(pkg_src_path, src_files), 73 | file.path(pkg_dest_path, "src", src_files)) 74 | # v3 75 | expect_known_output(object = cat(readLines(src_files[2]), sep = "\n"), 76 | file = src_files[1]) 77 | ## # v2 78 | ## expect_identical(readLines(src_files[1]), readLines(src_files[2])) 79 | ## # v1 80 | ## src_md5 <- tools::md5sum(src_files) 81 | ## names(src_md5) <- NULL 82 | ## expect_identical(src_md5[1], src_md5[2]) 83 | } 84 | } 85 | 86 | # check modification times for src files 87 | check_mtime <- function(stan_file, pkg_dest_path) { 88 | sf <- sub("\\.stan$", "", basename(stan_file)) 89 | src_files <- rstantools:::.stan_prefix(sf, c(".cc", ".h")) 90 | file.mtime(file.path(pkg_dest_path, "src", src_files)) 91 | } 92 | 93 | #------------------------------------------------------------------------------- 94 | 95 | # unload, uninstall, and delete source for given package 96 | remove_package <- function(pkg_name, pkg_path, lib_path, 97 | unload = TRUE, 98 | uninstall = TRUE, 99 | unlink = TRUE) { 100 | if(unload && isNamespaceLoaded(pkg_name)) { 101 | # unload package from R session 102 | detach(paste0("package:", pkg_name), 103 | unload = TRUE, character.only = TRUE) 104 | } 105 | if(uninstall && dir.exists(file.path(lib_path, pkg_name))) { 106 | # uninstall package 107 | remove.packages(pkg_name, lib_path) 108 | } 109 | if(unlink && dir.exists(file.path(pkg_path, pkg_name))) { 110 | unlink(file.path(pkg_path, pkg_name), recursive = TRUE, force = TRUE) 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /tests/testthat/test-default-methods.R: -------------------------------------------------------------------------------- 1 | context("default methods") 2 | set.seed(1111) 3 | x <- matrix(rnorm(150), 50, 3) 4 | y <- rnorm(ncol(x)) 5 | lw <- matrix(rnorm(150), 50, 3) 6 | lw <- sweep( 7 | lw, 8 | MARGIN = 2, 9 | STATS = apply(lw, 2, function(col) log(sum(exp(col)))), 10 | check.margin = FALSE 11 | ) 12 | 13 | test_that("posterior_interval.default hasn't changed", { 14 | expect_equal_to_reference( 15 | posterior_interval(x, prob = 0.5), 16 | "posterior_interval.RDS" 17 | ) 18 | }) 19 | test_that("predictive_interval.default hasn't changed", { 20 | expect_equal_to_reference( 21 | predictive_interval(x, prob = 0.8), 22 | "predictive_interval.RDS" 23 | ) 24 | }) 25 | test_that("predictive_error.default works", { 26 | expect_equal_to_reference( 27 | predictive_error(x, y), 28 | "predictive_error.RDS" 29 | ) 30 | }) 31 | test_that("prior_summary.default works", { 32 | obj <- list(prior.info = "prior info") 33 | expect_identical(prior_summary(obj), obj[[1]]) 34 | 35 | expect_null(prior_summary(list(abc = "prior_info"))) 36 | }) 37 | test_that("loo_pit.default works", { 38 | expect_equal_to_reference( 39 | loo_pit(x, y, lw), 40 | "loo_pit.RDS" 41 | ) 42 | }) 43 | test_that("loo_pit-default works for discrete data", { 44 | set.seed(1111) 45 | expect_equal_to_reference( 46 | loo_pit(round(x), round(y), lw), 47 | "loo_pit_discrete.RDS" 48 | ) 49 | }) 50 | test_that("bayes_R2.default hasn't changed", { 51 | expect_equal_to_reference( 52 | bayes_R2(x, y), 53 | "bayes_R2.RDS" 54 | ) 55 | }) 56 | 57 | test_that("default methods throw correct errors", { 58 | expect_error(posterior_interval(1:10), "should be a matrix") 59 | expect_error(predictive_interval(1:10), "should be a matrix") 60 | expect_error(predictive_error(1:10, 1:10), "should be a matrix") 61 | expect_error(bayes_R2(1:10, 1:10), "should be a matrix") 62 | expect_error(bayes_R2(cbind(1:10, 1:10), 1:9), 63 | "ncol(object) == length(y) is not TRUE", 64 | fixed = TRUE) 65 | }) 66 | 67 | 68 | # helper functions -------------------------------------------------------- 69 | test_that(".central_intervals returns correct structure", { 70 | a <- .central_intervals(x, prob = 0.5) 71 | expect_equal(dim(a), c(ncol(x), 2)) 72 | expect_identical(colnames(a), c("25%", "75%")) 73 | }) 74 | test_that("central_intervals throws errors", { 75 | err_msg <- "'prob' should be a single number greater than 0 and less than 1" 76 | expect_error(.central_intervals(x, prob = c(0.5, 0.25)), err_msg) 77 | expect_error(.central_intervals(x, prob = 0, err_msg)) 78 | expect_error(.central_intervals(x, prob = 1, err_msg)) 79 | }) 80 | test_that(".central_intervals returns correct structure", { 81 | a <- .central_intervals(x, prob = 0.5) 82 | expect_equal(dim(a), c(ncol(x), 2)) 83 | expect_identical(colnames(a), c("25%", "75%")) 84 | }) 85 | 86 | test_that(".pred_errors returns correct structure", { 87 | err <- .pred_errors(x, y) 88 | expect_true(is.matrix(err)) 89 | expect_equal(dim(err), dim(x)) 90 | }) 91 | test_that(".pred_errors throws errors", { 92 | expect_error(.pred_errors(x, y[-1]), "length(y) == ncol(object) is not TRUE", 93 | fixed = TRUE) 94 | expect_error(.pred_errors(x[,1], y), "is.matrix(object) is not TRUE", 95 | fixed = TRUE) 96 | }) 97 | 98 | -------------------------------------------------------------------------------- /tests/testthat/test-generics-with-no-methods.R: -------------------------------------------------------------------------------- 1 | context("generics with no methods") 2 | set.seed(1111) 3 | x <- matrix(rnorm(150), 50, 3) 4 | y <- rnorm(ncol(x)) 5 | 6 | 7 | generics_w_no_default <- 8 | c( 9 | "log_lik", 10 | "posterior_predict", 11 | "posterior_linpred", 12 | "loo_predict", 13 | "loo_linpred", 14 | "loo_predictive_interval" 15 | ) 16 | 17 | test_that("generics without defaults ok", { 18 | for (f in generics_w_no_default) { 19 | expect_true(exists(f, mode = "function"), info = f) 20 | expect_error(get(f, mode = "function")(2), "no applicable method", info = f) 21 | expect_output(print(methods(f)), "no methods found", info = f) 22 | } 23 | }) 24 | -------------------------------------------------------------------------------- /tests/testthat/test-rstan_config.R: -------------------------------------------------------------------------------- 1 | #--- test rstan_config --------------------------------------------- 2 | 3 | context("rstan_config") 4 | 5 | # 0. setup 6 | # 1. create empty package 7 | # 2. add stan files and (weakly) check them via expect_known_output. 8 | # 3. rerun config, check that file.mtimes are identical 9 | # 4. create fake .o files to mimick contents of src without compiling package. also add other files to src. 10 | # 5. remove one stan file, rerun config, check that files are removed and other files are the same. 11 | # 6. delete package source 12 | 13 | #--- 0. setup ----------------------------------------------------------------- 14 | 15 | run_all_tests <- FALSE # if TRUE disables skip_on_cran and skip_on_travis 16 | backtest_stan_cpp <- FALSE # if FALSE disables check of stan cc/h files 17 | # against what is on record. typically this test only fails 18 | # when the user and package stan C++ library are out of sync. 19 | # helper functions to run tests 20 | source("rstan_package_skeleton-testfunctions.R") 21 | pkg_name <- "RStanTest" # name of package 22 | # path to directory where package will be created 23 | tmp_test_path <- TRUE # put tests in temporary folder 24 | if(tmp_test_path) test_path <- tempfile(pattern = "rstantools_") 25 | dir.create(test_path, recursive = TRUE) 26 | pkg_dest_path <- file.path(test_path, pkg_name) 27 | # path to package source files 28 | pkg_src_path <- "RStanTest" 29 | ## pkg_src_path <- system.file("include", "RStanTest", 30 | ## package = "rstantools") 31 | # package R files 32 | code_files <- file.path(pkg_src_path, "postsamp.R") 33 | # package stan files 34 | stan_files <- file.path(pkg_src_path, c("SimpleModel.stan", "SimpleModel2.stan")) 35 | # package stan/include files 36 | incl_files <- file.path(pkg_src_path, "helper.stan") 37 | 38 | #--- 1. create package -------------------------------------------------------- 39 | 40 | rstan_create_package(path = pkg_dest_path, 41 | rstudio = FALSE, open = FALSE, 42 | stan_files = character(), roxygen = FALSE, 43 | license = FALSE, auto_config = FALSE) 44 | # copy R files 45 | file.copy(from = code_files, 46 | to = file.path(pkg_dest_path, "R", basename(code_files))) 47 | 48 | 49 | #--- 2. add stan files, check contents ---------------------------------------- 50 | 51 | # copy stan files 52 | file.copy(from = stan_files, 53 | to = file.path(pkg_dest_path, "inst", "stan", 54 | basename(stan_files))) 55 | # copy stan/include files 56 | file.copy(from = incl_files, 57 | to = file.path(pkg_dest_path, "inst", "stan", "include", 58 | basename(incl_files))) 59 | 60 | 61 | # add Stan C++ code 62 | rstan_config(pkg_dest_path) 63 | 64 | # check that Stan C++ source code lines match those on record 65 | # this should only fail when output from rstan::stanc gets modified, e.g., 66 | # because stan version has changed. 67 | # subsequent runs (in interactive mode) will pass as records get overwritten. 68 | # R CMD check will not overwrite record: see testthat::expect_known_output 69 | if(backtest_stan_cpp) { 70 | test_that("Stan src files are created properly", { 71 | if (!run_all_tests) { 72 | skip_on_cran() 73 | skip_on_travis() 74 | } 75 | for(sf in stan_files) { 76 | check_lines(sf, 77 | pkg_src_path = pkg_src_path, 78 | pkg_dest_path = pkg_dest_path) 79 | } 80 | }) 81 | } 82 | 83 | #--- 3. rerun config, check that file.mtimes are identical -------------------- 84 | 85 | test_that("Unmodified Stan src files are not overwritten", { 86 | if (!run_all_tests) { 87 | skip_on_cran() 88 | skip_on_travis() 89 | } 90 | pre_mtime <- lapply(stan_files, check_mtime, pkg_dest_path = pkg_dest_path) 91 | pre_mtime <- do.call(c, pre_mtime) 92 | rstan_config(pkg_dest_path) 93 | post_mtime <- lapply(stan_files, check_mtime, pkg_dest_path = pkg_dest_path) 94 | post_mtime <- do.call(c, post_mtime) 95 | expect_identical(pre_mtime, post_mtime) 96 | }) 97 | 98 | #--- 4. create fake .o files and other src files ------------------------------ 99 | 100 | # fake .o files 101 | invisible(sapply(gsub("\\.stan$", "", basename(stan_files)), function(sf) { 102 | writeLines("fake .o file", 103 | con = file.path(pkg_dest_path, "src", 104 | rstantools:::.stan_prefix(sf, ".o"))) 105 | })) 106 | 107 | # dummy src files 108 | src_files <- c("foo.cpp", "stanExports_foo.txt", "abcstanExports_foo.cc") 109 | invisible(sapply(src_files, function(sf) { 110 | writeLines("// fake source file\n", 111 | con = file.path(pkg_dest_path, "src", sf)) 112 | })) 113 | 114 | 115 | #--- 5. remove stan file(s) rerun config -------------------------------------- 116 | 117 | test_that("src is properly updated after removing one inst/stan files", { 118 | if (!run_all_tests) { 119 | skip_on_cran() 120 | skip_on_travis() 121 | } 122 | 123 | # check modification time of all files in src 124 | pre_files <- list.files(file.path(pkg_dest_path, "src"), 125 | full.names = TRUE) 126 | pre_mtime <- file.mtime(pre_files) 127 | # remove files associated with one stan file 128 | rm_file <- sample(basename(stan_files), 1) # file to remove 129 | file.remove(file.path(pkg_dest_path, "inst", "stan", rm_file)) 130 | rstan_config(pkg_dest_path) # re-configure 131 | # calculate modification times 132 | post_files <- list.files(file.path(pkg_dest_path, "src"), full.names = TRUE) 133 | post_mtime <- file.mtime(post_files) 134 | # deduce which of pre_files should remain 135 | rm_file <- tools::file_path_sans_ext(rm_file) 136 | pre_filter <- !grepl(paste0("^stanExports_", rm_file, "\\.(cc|h|o)"), 137 | basename(pre_files)) 138 | expect_identical(pre_files[pre_filter], post_files) 139 | # now check modification times 140 | pre_filter <- pre_filter & (basename(pre_files) != "RcppExports.cpp") 141 | post_filter <- basename(post_files) != "RcppExports.cpp" 142 | expect_identical(pre_mtime[pre_filter], post_mtime[post_filter]) 143 | }) 144 | 145 | test_that("src is properly updated after removing all inst/stan files", { 146 | if (!run_all_tests) { 147 | skip_on_cran() 148 | skip_on_travis() 149 | } 150 | 151 | rm_files <- list.files(file.path(pkg_dest_path, "inst", "stan"), 152 | pattern = "[.]stan$", 153 | full.names = TRUE) 154 | file.remove(rm_files) 155 | rstan_config(pkg_dest_path) # re-configure 156 | curr_files <- sort(list.files(file.path(pkg_dest_path, "src"), 157 | full.names = TRUE)) 158 | exp_files <- sort(file.path(pkg_dest_path, "src", src_files)) 159 | expect_identical(curr_files, exp_files) 160 | }) 161 | 162 | #--- 6. delete package source ------------------------------------------------- 163 | 164 | unlink(pkg_dest_path, recursive = TRUE, force = TRUE) 165 | 166 | # make sure everything gets deleted even if there are errors 167 | teardown(code = { 168 | if(tmp_test_path) unlink(test_path, recursive = TRUE, force = TRUE) 169 | }) 170 | 171 | 172 | #--- scratch ------------------------------------------------------------------- 173 | 174 | ## sf <- "stanExports_SimpleModel.h" 175 | ## setNames(c(tools::md5sum(file.path(pkg_dest_path, sf)), 176 | ## tools::md5sum(file.path(pkg_dest_path, "src", sf)), 177 | ## tools::md5sum(file.path(pkg_src_path, sf))), NULL) 178 | -------------------------------------------------------------------------------- /tests/testthat/test-rstan_create_package.R: -------------------------------------------------------------------------------- 1 | #--- test rstan_create_package ----------------------------------------------- 2 | 3 | # 1. create package under various conditions 4 | # 2. pkgload::load_all package 5 | # 3. run tests on package 6 | # 4. delete package source 7 | 8 | # setup 9 | run_all_tests <- FALSE # if TRUE disables skip_on_cran and skip_on_travis 10 | source("rstan_package_skeleton-testfunctions.R") # helper functions to run tests 11 | pkg_name <- "RStanTest" # base name of package 12 | # path to base directory where packages will be created 13 | tmp_test_path <- TRUE # put all tests in temporary folder 14 | if(tmp_test_path) test_path <- tempfile(pattern = "rstantools_") 15 | dir.create(test_path, recursive = TRUE) 16 | rand_path <- TRUE # randomize destination path 17 | # path to package source files 18 | pkg_src_path <- "RStanTest" 19 | ## pkg_src_path <- system.file("include", "RStanTest", 20 | ## package = "rstantools") 21 | # package R files 22 | code_files <- file.path(pkg_src_path, "postsamp.R") 23 | # package stan files 24 | stan_files <- file.path(pkg_src_path, c("SimpleModel.stan", "SimpleModel2.stan")) 25 | # package stan/include files 26 | incl_files <- file.path(pkg_src_path, "helper.stan") 27 | # package C++ files 28 | src_files <- file.path(pkg_src_path, "AddTest.cpp") 29 | 30 | # various test conditions 31 | test_descr <- expand.grid( 32 | ## create_package = c(TRUE, FALSE), # use create_package or package_skeleton 33 | create_package = TRUE, # package_skeleton now depreciated 34 | roxygen = c(TRUE, FALSE) # use roxygen for documentation 35 | ) 36 | ntest <- nrow(test_descr) 37 | 38 | # run tests 39 | for(ii in 1:ntest) { 40 | if(rand_path) { 41 | pkg_dest_path <- file.path(test_path, 42 | basename(tempfile(pattern = pkg_name)), 43 | pkg_name) 44 | } else { 45 | pkg_dest_path <- file.path(test_path, pkg_name) 46 | } 47 | # specific test condition 48 | use_create_package <- test_descr$create_package[ii] 49 | use_roxygen <- test_descr$roxygen[ii] 50 | if (!use_roxygen) next # FIXME 51 | context(paste0( 52 | ifelse(use_create_package, 53 | yes = "rstan_create_package", 54 | no = "rstan_package_skeleton"), 55 | " -- ", 56 | ifelse(use_roxygen, "with", "without"), 57 | " roxygen") 58 | ) 59 | # create package 60 | if(rand_path) dir.create(dirname(pkg_dest_path), recursive = TRUE) 61 | if(use_create_package) { 62 | # use rstan_create_package 63 | rstan_create_package(path = pkg_dest_path, 64 | rstudio = FALSE, open = FALSE, 65 | ## stan_files = stan_files, 66 | roxygen = use_roxygen) 67 | # add R files 68 | file.copy(from = code_files, 69 | to = file.path(pkg_dest_path, "R", basename(code_files))) 70 | } else { 71 | stop("rstan_package_skeleton has been depreciated.") 72 | # use rstan_package_skeleton 73 | rstan_package_skeleton(name = pkg_name, path = dirname(pkg_dest_path), 74 | ## stan_files = stan_files, 75 | code_files = code_files, 76 | roxygen = use_roxygen) 77 | } 78 | # add stan files (need to do this separately or else rstan_config complains) 79 | file.copy(from = stan_files, 80 | to = file.path(pkg_dest_path, 81 | "inst", "stan", basename(stan_files))) 82 | # add stan/include files 83 | file.copy(from = incl_files, 84 | to = file.path(pkg_dest_path, 85 | "inst", "stan", "include", basename(incl_files))) 86 | # add C++ files 87 | file.copy(from = src_files, 88 | to = file.path(pkg_dest_path, "src", basename(src_files))) 89 | rstan_config(pkg_dest_path) 90 | ## Rcpp::compileAttributes(pkg_dest_path) 91 | # install & load package 92 | test_that("Package loads correctly", { 93 | if(!run_all_tests) { 94 | skip_on_cran() 95 | skip_on_travis() 96 | } 97 | try(roxygen2::roxygenize(pkg_dest_path, load_code = rstantools_load_code), silent = TRUE) 98 | pkgbuild::compile_dll(pkg_dest_path) 99 | tmp <- capture.output(load_out <- pkgload::load_all(pkg_dest_path, 100 | export_all = TRUE, 101 | quiet = TRUE)) 102 | expect_type(load_out, "list") 103 | }) 104 | if(use_roxygen) { 105 | # check roxygen documentation 106 | # TODO: stop test if roxygen2 not found 107 | test_that("roxygen works properly", { 108 | if(!run_all_tests) { 109 | skip_on_cran() 110 | skip_on_travis() 111 | } 112 | skip_if_not_installed("roxygen2") 113 | ## devtools::document(pkg_dest_path) 114 | tmp <- capture.output(pkgload::unload(pkg_name)) 115 | pkgbuild::compile_dll(pkg_dest_path) 116 | roxygen2::roxygenize(pkg_dest_path) 117 | tmp <- capture.output(load_out <- pkgload::load_all(pkg_dest_path, 118 | export_all = TRUE, 119 | quiet = TRUE)) 120 | expect_identical(readLines(file.path(pkg_dest_path, "NAMESPACE")), 121 | readLines(file.path(pkg_src_path, "NAMESPACE"))) 122 | }) 123 | } 124 | # check that functions work as expected 125 | test_that("logpost_R == logpost_Stan: postsamp1", { 126 | if(!run_all_tests) { 127 | skip_on_cran() 128 | skip_on_travis() 129 | } 130 | compare_postsamp1() 131 | }) 132 | test_that("logpost_R == logpost_Stan: postsamp2", { 133 | if(!run_all_tests) { 134 | skip_on_cran() 135 | skip_on_travis() 136 | } 137 | compare_postsamp2() 138 | }) 139 | test_that("external C++ code works", { 140 | if(!run_all_tests) { 141 | skip_on_cran() 142 | skip_on_travis() 143 | } 144 | n <- sample(1:20, 1) 145 | x <- rnorm(n) 146 | y <- rnorm(n) 147 | expect_equal(add_test(x, y), x + y) 148 | }) 149 | # uninstall + delete package 150 | # tmp <- capture.output(pkgload::unload(pkg_name)) 151 | ## detach(paste0("package:", pkg_name), 152 | ## unload = TRUE, character.only = TRUE) 153 | ## remove.packages(pkgs = pkg_name, lib = lib_path) # remove installed package 154 | if(rand_path) { 155 | unlink(dirname(pkg_dest_path), 156 | recursive = TRUE, force = TRUE) 157 | } else { 158 | unlink(pkg_dest_path, 159 | recursive = TRUE, force = TRUE) 160 | } 161 | } 162 | 163 | # make sure everything gets deleted even if there are errors 164 | teardown(code = { 165 | ## if(isNamespaceLoaded(pkg_name)) { 166 | ## detach(paste0("package:", pkg_name), 167 | ## unload = TRUE, character.only = TRUE) 168 | ## } 169 | if(tmp_test_path) unlink(test_path, recursive = TRUE, force = TRUE) 170 | }) 171 | -------------------------------------------------------------------------------- /tests/testthat/test.stan: -------------------------------------------------------------------------------- 1 | data { 2 | int N; 3 | int y[N]; 4 | } 5 | parameters { 6 | real theta; 7 | } 8 | model { 9 | y ~ bernoulli(theta); 10 | } 11 | -------------------------------------------------------------------------------- /vignettes/developer-guidelines.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Guidelines for Developers of R Packages Interfacing with Stan" 3 | author: "Stan Development Team" 4 | date: "Latest release: `r format(Sys.Date(), format = '%B %Y')` (First version: November 2016)" 5 | output: 6 | rmarkdown::html_vignette: 7 | toc: true 8 | vignette: > 9 | %\VignetteIndexEntry{Guidelines for Developers of R Packages Interfacing with Stan} 10 | %\VignetteEngine{knitr::rmarkdown} 11 | %\VignetteEncoding{UTF-8} 12 | --- 13 | 14 | ## Note to developers 15 | 16 | One of the coolest things about working on a project like Stan has been seeing 17 | some of our users begin to develop tools for making Stan more accessible to 18 | audiences that may otherwise not benefit from what Stan offers. In particular, 19 | recently we have started seeing a growing number of R packages that provide 20 | high-level interfaces to Stan, using the [__rstan__](https://mc-stan.org/rstan/) 21 | package for estimating models without requiring that the user be familiar with 22 | the Stan modeling language itself. 23 | 24 | This is a great development and we would like to support such efforts going 25 | forward, but to-date we have made little effort to coordinate the development of 26 | these packages. To avoid a Wild West, so to speak, of Stan-based R packages, we 27 | think it is important that developers make every effort to adhere to certain 28 | guidelines in order to ensure these packages are of the highest possible quality 29 | and provide the best possible experience for users. To that end, in this post we 30 | present a set of recommendations for the development of R packages that 31 | interface with Stan. These recommendations are based on software design 32 | principles we value as well as many things we are learning as we continue 33 | developing our own packages and review packages being developed by others. There 34 | are exceptions to some of these recommendations (e.g., the __brms__ package is a 35 | sensible exception to one of guidelines about Stan code), but we strongly 36 | recommend trying to follow them whenever possible. 37 | 38 | These recommendations are not set in stone. We expect them to evolve and we very 39 | much appreciate feedback on how they can be improved. And, of course, we look 40 | forward to seeing the packages you develop using Stan, so please let us know 41 | about them! 42 | 43 | 44 | ## Guidelines for R packages providing interfaces to Stan 45 | 46 | ### General package structure and development 47 | 48 | * The __rstantools__ package provides the `rstan_create_package()` function, 49 | which you should use to create the basic structure of your package. (As of 50 | `v2.0.0` this replaces the `rstan_package_skeleton` function.) This will set up 51 | a package with functionality for pre-compiled Stan programs, in the style of the 52 | [__rstanarm__](https://mc-stan.org/rstanarm/) package (source code: 53 | https://github.com/stan-dev/rstanarm). 54 | 55 | * Use version control (e.g., git). 56 | 57 | * Unless you are developing proprietary private software, organize your code in 58 | a repository that is _public_ on [GitHub](https://github.com/) (or a similar 59 | service, but preferably GitHub). It should be public even at early stages of 60 | development, not only when officially released. We recommend you add a note to 61 | your README file on how to install the development version of your package, like 62 | in the [__bayesplot__ README](https://github.com/stan-dev/bayesplot#installation) 63 | 64 | * Unit testing is essential. There are several R packages that make it 65 | relatively easy to write tests for your package. Most of our R packages (e.g., 66 | __rstanarm__, __brms__, __bayesplot__, __shinystan__, __loo__ and others) use 67 | the [__testthat__](https://github.com/r-lib/testthat) package for this purpose, 68 | but if you prefer a different testing framework that's fine. The 69 | [__covr__](https://github.com/r-lib/covr) package is useful for calculating the 70 | line coverage of your tests, and we recommend reaching a high level of coverage 71 | before releasing a package. Good line coverage does not guarantee high quality 72 | tests, but it's a good first step. We also recommend setting up automatic 73 | testing of your package using GitHub Actions. See 74 | https://github.com/r-lib/actions for useful templates. 75 | 76 | ### Stan code 77 | 78 | * All Stan code for estimating models should be included in pre-written static 79 | `.stan` files that are compiled when the package is built (see the Stan programs 80 | directory in the __rstanarm__ repo for examples). You can also use 81 | subdirectories to include code chunks to be used in multiple `.stan` files (again 82 | see the __rstanarm__ repo for examples). If you set up your package using 83 | `rstan_create_package` this structure will be created for you. This means that 84 | __your package should NOT write a Stan program when the user calls a model 85 | fitting function in your package__, but rather use only Stan programs you have 86 | written by hand in advance (if you are working on a model for which you don't 87 | think this is possible please let us know). There are several reasons for this. 88 | 89 | * Pre-compiled Stan programs can be run by users of Windows or Mac OSX without 90 | having to install a C++ compiler, which dramatically expands the universe of 91 | potential users for your package. 92 | * Pre-compiled Stan programs will run immediately when called, avoiding compilation time. 93 | * CRAN policy permits long installation times but imposes restrictions on the 94 | time consumed by examples and unit tests that are much shorter than the time 95 | that it takes to compile even a simple Stan program. Thus, it is only possible 96 | to adequately test your package if it has pre-compiled Stan programs. 97 | * Pre-compiled Stan programs can use custom C++ functions. 98 | 99 | To provide flexibility to users, your Stan programs can include branching logic 100 | (conditional statements) so that even with a small number of .stan files you can still 101 | allow for many different specifications to made by the user (see the .stan files in 102 | __rstanarm__ for examples). 103 | 104 | * Use best practices for Stan code. If the models you intend to implement are 105 | discussed in the Stan manual or on the Stan users forum then you should follow 106 | any recommendations that apply to your case. If you are unsure whether your Stan 107 | programs can be made more efficient or more numerically stable then please ask 108 | us on the Stan users forum. Especially ask us if you are unsure whether your 109 | Stan programs are indeed estimating the intended model. 110 | 111 | * Relatedly, prioritize safety over speed in your Stan code and sampler 112 | settings. For example, if you can write a program that runs faster but is 113 | potentially less stable, then at a minimum you should make the more stable 114 | version the default. This also means that, with rare exceptions, you should not 115 | change our recommended MCMC defaults (e.g. 4 chains, 1000+1000 iterations, NUTS 116 | not static HMC), unless you are setting the defaults to something more 117 | conservative. __rstanarm__ even goes one step further, making the default value 118 | of the `adapt_delta` tuning parameter at least 0.95 for all models (rather than 119 | __rstan__'s default of 0.8) in order to reduce the step size and therefore also 120 | limit the potential for divergences. This means that __rstanarm__ models may 121 | often run a bit slower than they need to if the user doesn't change the 122 | defaults, but it also means that users face fewer situations in which they need 123 | to know how to change the defaults and what the implications of changing the 124 | defaults really are. 125 | 126 | ### R code and documentation 127 | 128 | * Functions/methods that provide useful post-estimation functionality should be given 129 | the same names as the corresponding functions in __rstanarm__ (if applicable). 130 | For example, `posterior_predict()` to draw from the posterior predictive 131 | distribution, `posterior_interval()` for posterior uncertainty intervals, etc. To 132 | make this easier, these and similar __rstanarm__ functions have been converted 133 | to S3 methods for the stanreg objects created by __rstanarm__ and the S3 generic 134 | functions are included here in the __rstantools__ package. Your package should 135 | import the generics from __rstantools__ for whichever functions you want to 136 | include in your package and then provide methods for the fitted model objects 137 | returned by your model-fitting functions. For some other functions (e.g. 138 | `as.matrix`) the generics are already available in base R or core R packages. To 139 | be clear, we are not saying that the naming conventions used in 140 | __rstanarm__/__rstantools__ are necessarily optimal. (If you think that one of 141 | our function names should be changed please let us know and suggest an 142 | alternative. If it is a substantial improvement we may consider renaming the 143 | function and deprecating the current version.) Rather, this guideline is 144 | intended to make function names consistent across Stan-based R packages, which 145 | will improve the user experience for those users who want to take advantage of a 146 | variety of these packages. It will be a mess if every R package using Stan has 147 | different names for the same functionality. 148 | 149 | * The [__bayesplot__](https://mc-stan.org/bayesplot/) package serves as the 150 | back-end for plotting for __rstanarm__ (see for example `pp_check.stanreg` and 151 | `plot.stanreg`), __brms__, and other packages, and we hope developers of other 152 | Stan-based R packages will also use it. You can see all the other R packages 153 | using __bayesplot__ in the _Reverse dependencies_ section of the __bayesplot__ 154 | [CRAN page](https://CRAN.R-project.org/package=bayesplot). For any plot you 155 | intend to include in your package, if it is already available in __bayesplot__ 156 | then we recommend using the available version or suggesting (or contributing) a 157 | better version. If it is not already available then there is a good chance we 158 | will be interested in including it in __bayesplot__ if the plot would also be 159 | useful for other developers. 160 | 161 | * The [__posterior__](https://mc-stan.org/posterior/) package (new in 2021) 162 | provides state of the art posterior inference diagnostics, various summaries of 163 | draws in convenient formats, and functionality for converting between (and 164 | manipulating) many different useful formats of draws from posterior or prior 165 | distributions. We recommend using this functionality in your package or 166 | recommending it to your users. 167 | 168 | * Take documentation seriously. The documentation won't be perfect (we 169 | constantly find holes in the doc for the R packages in the Stan ecosystem), but 170 | you should make every effort to provide clear and thorough documentation. 171 | 172 | 173 | ### Recommended resources 174 | 175 | * Hadley Wickham and Jenny Bryan's [book on R packages](https://r-pkgs.org/). If you 176 | are interested in developing an R package that interfaces with Stan but are not an 177 | experienced package developer, we recommend this book, which is free to read 178 | online. Even if you are an experienced developer of R packages, the book is 179 | still a great resource. 180 | 181 | * If you need help setting up your package or have questions about these 182 | guidelines the best places to go are the [Stan 183 | Forums](https://discourse.mc-stan.org) and the [GitHub issue 184 | tracker](https://github.com/stan-dev/rstantools/issues) for the __rstantools__ 185 | package. 186 | -------------------------------------------------------------------------------- /vignettes/minimal-rstan-package.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Step by step guide for creating a package that depends on RStan" 3 | author: "Stefan Siegert, Jonah Gabry, Martin Lysy, and Ben Goodrich" 4 | date: "`r Sys.Date()`" 5 | output: 6 | rmarkdown::html_vignette: 7 | toc: true 8 | params: 9 | EVAL: !r identical(Sys.getenv("NOT_CRAN"), "true") 10 | vignette: > 11 | %\VignetteIndexEntry{Step by step guide} 12 | %\VignetteEngine{knitr::rmarkdown} 13 | %\VignetteEncoding{UTF-8} 14 | --- 15 | 16 | ```{r SETTINGS-knitr, include=FALSE} 17 | stopifnot(require(knitr)) 18 | opts_chunk$set( 19 | comment=NA, 20 | eval = if (isTRUE(exists("params"))) params$EVAL else FALSE 21 | ) 22 | td <- tempdir() 23 | PATH <- file.path(td, "rstanlm") 24 | if(dir.exists(PATH)) { 25 | unlink(PATH, recursive = TRUE, force = TRUE) 26 | } 27 | ``` 28 | 29 | ## Introduction 30 | 31 | In this vignette we will walk through the steps necessary for creating an 32 | R package that depends on Stan by creating a package with one function 33 | that fits a simple linear regression. Before continuing, we recommend that you first read the other vignette [_Guidelines for Developers of R Packages Interfacing with Stan_](https://mc-stan.org/rstantools/articles/developer-guidelines.html). 34 | 35 | ## Creating the package skeleton 36 | 37 | The **rstantools** package offers two methods for adding Stan functionality 38 | to R packages: 39 | 40 | * `rstan_create_package()`: set up a new R package with Stan programs 41 | * `use_rstan()`: add Stan functionality to an _existing_ R package 42 | 43 | Here we will use `rstan_create_package()` to initialize a bare-bones package 44 | directory. The name of our demo package will be __rstanlm__; it will fit a 45 | simple linear regression model using Stan. 46 | 47 | ```{r rstan_create_package, eval=FALSE} 48 | library("rstantools") 49 | rstan_create_package(path = 'rstanlm') 50 | ``` 51 | ```{r rstan_create_package-eval, echo=FALSE,warning=FALSE} 52 | library("rstantools") 53 | rstan_create_package(path = PATH, rstudio=FALSE, open=FALSE) 54 | ``` 55 | 56 | If we had existing `.stan` files to include with the package we could use the 57 | optional `stan_files` argument to `rstan_create_package()` to include them. 58 | Another option, which we'll use below, is to add the Stan files once the 59 | basic structure of the package is in place. 60 | 61 | We can now set the new working directory to the new package directory and view 62 | the contents. (Note: if using RStudio then by default the newly created project 63 | for the package will be opened in a new session and you will not need the call 64 | to `setwd()`.) 65 | 66 | 67 | ```{r, eval=FALSE} 68 | setwd("rstanlm") 69 | list.files(all.files = TRUE) 70 | ``` 71 | ```{r, echo=FALSE} 72 | list.files(PATH, all.files = TRUE) 73 | ``` 74 | 75 | ```{r, eval=FALSE} 76 | file.show("DESCRIPTION") 77 | ``` 78 | ```{r, echo=FALSE} 79 | DES <- readLines(file.path(PATH, "DESCRIPTION")) 80 | cat(DES, sep = "\n") 81 | ``` 82 | 83 | Some of the sections in the `DESCRIPTION` file need to be edited by hand (e.g., 84 | `Title`, `Author`, `Maintainer`, and `Description`, but these also can be set 85 | with the `fields` argument to `rstan_create_package()`). However, 86 | `rstan_create_package()` has added the necessary packages and versions to 87 | `Depends`, `Imports`, and `LinkingTo` to enable Stan functionality. 88 | 89 | ## Read-and-delete-me file 90 | 91 | Before deleting the `Read-and-delete-me` file in the new package directory make 92 | sure to read it because it contains some important instructions about 93 | customizing your package: 94 | 95 | ```{r, eval=FALSE} 96 | file.show("Read-and-delete-me") 97 | ``` 98 | ```{r, echo=FALSE} 99 | cat(readLines(file.path(PATH, "Read-and-delete-me")), sep = "\n") 100 | ``` 101 | 102 | You can move this file out of the directory, delete it, or list it in the 103 | `.Rbuildignore` file if you want to keep it in the directory. 104 | 105 | ```{r, eval=FALSE} 106 | file.remove('Read-and-delete-me') 107 | ``` 108 | ```{r, echo=FALSE} 109 | file.remove(file.path(PATH, 'Read-and-delete-me')) 110 | ``` 111 | 112 | 113 | ## Stan files 114 | 115 | Our package will call **rstan**'s `sampling()` method to use MCMC to fit a simple 116 | linear regression model for an outcome variable `y` with a single predictor `x`. 117 | After writing the necessary Stan program, the file should be saved with a 118 | `.stan` extension in the `inst/stan` subdirectory. We'll save the 119 | following program to `inst/stan/lm.stan`: 120 | 121 | ```{stan, output.var = "foo", eval = FALSE} 122 | // Save this file as inst/stan/lm.stan 123 | data { 124 | int N; 125 | vector[N] x; 126 | vector[N] y; 127 | } 128 | parameters { 129 | real intercept; 130 | real beta; 131 | real sigma; 132 | } 133 | model { 134 | // ... priors, etc. 135 | 136 | y ~ normal(intercept + beta * x, sigma); 137 | } 138 | 139 | ``` 140 | 141 | ```{r, include=FALSE} 142 | stan_prog <- " 143 | data { 144 | int N; 145 | vector[N] x; 146 | vector[N] y; 147 | } 148 | parameters { 149 | real intercept; 150 | real beta; 151 | real sigma; 152 | } 153 | model { 154 | // ... priors, etc. 155 | 156 | y ~ normal(intercept + beta * x, sigma); 157 | } 158 | " 159 | writeLines(stan_prog, con = file.path(PATH, "inst", "stan", "lm.stan")) 160 | rstan_config(PATH) 161 | ``` 162 | 163 | The `inst/stan` subdirectory can contain additional Stan programs if 164 | required by your package. During installation, all Stan programs will be 165 | compiled and saved in the list `stanmodels` that can then be used by R function 166 | in the package. The rule is that the Stan program compiled from the model code 167 | in `inst/stan/foo.stan` is stored as list element `stanmodels$foo`. Thus, the 168 | filename of the Stan program in the `inst/stan` directory should not contain 169 | spaces or dashes and nor should it start with a number or utilize non-ASCII 170 | characters. 171 | 172 | ## R files 173 | 174 | We next create the file `R/lm_stan.R` where we define the function `lm_stan()` 175 | in which our compiled Stan model is being used. Setting the 176 | `rstan_create_package()` argument `roxygen = TRUE` (the default value) enables 177 | [__roxygen2__](https://CRAN.R-project.org/package=roxygen2) documentation for 178 | the package functions. The following comment block placed in `lm_stan.R` 179 | ensures that the function has a help file and that it is added to the package 180 | `NAMESPACE`: 181 | 182 | ```{r} 183 | # Save this file as `R/lm_stan.R` 184 | 185 | #' Bayesian linear regression with Stan 186 | #' 187 | #' @export 188 | #' @param x Numeric vector of input values. 189 | #' @param y Numeric vector of output values. 190 | #' @param ... Arguments passed to `rstan::sampling` (e.g. iter, chains). 191 | #' @return An object of class `stanfit` returned by `rstan::sampling` 192 | #' 193 | lm_stan <- function(x, y, ...) { 194 | standata <- list(x = x, y = y, N = length(y)) 195 | out <- rstan::sampling(stanmodels$lm, data = standata, ...) 196 | return(out) 197 | } 198 | 199 | ``` 200 | 201 | 202 | ```{r, include=FALSE} 203 | Rcode <- " 204 | #' Bayesian linear regression with Stan 205 | #' 206 | #' @export 207 | #' @param x Numeric vector of input values. 208 | #' @param y Numeric vector of output values. 209 | #' @param ... Arguments passed to `rstan::sampling`. 210 | #' @return An object of class `stanfit` returned by `rstan::sampling` 211 | lm_stan <- function(x, y, ...) { 212 | out <- rstan::sampling(stanmodels$lm, data=list(x=x, y=y, N=length(y)), ...) 213 | return(out) 214 | } 215 | " 216 | writeLines(Rcode, con = file.path(PATH, "R", "lm_stan.R")) 217 | ``` 218 | 219 | When __roxygen2__ documentation is enabled, a top-level package file 220 | `R/rstanlm-package.R` is created by `rstan_create_package()` to import necessary 221 | functions for other packages and to set up the package for compiling Stan C++ 222 | code: 223 | 224 | ```{r, eval=FALSE} 225 | file.show(file.path("R", "rstanlm-package.R")) 226 | ``` 227 | ```{r, echo=FALSE} 228 | cat(readLines(file.path(PATH, "R", "rstanlm-package.R")), sep = "\n") 229 | ``` 230 | 231 | The `#' @description` section can be manually edited to provided specific 232 | information about the package. 233 | 234 | ## Documentation 235 | 236 | With __roxygen__ documentation enabled, we need to generate the documentation 237 | for `lm_stan` and update the `NAMESPACE` so the function is exported, i.e., 238 | available to users when the package is installed. This can be done with the 239 | function `roxygen2::roxygenize()`, which needs to be called twice initially. 240 | 241 | ```{r, eval = FALSE} 242 | try(roxygen2::roxygenize(load_code = rstantools_load_code), silent = TRUE) 243 | roxygen2::roxygenize() 244 | ``` 245 | ```{r, echo=FALSE, results="hide"} 246 | try(roxygen2::roxygenize(PATH, load_code = rstantools_load_code), silent = TRUE) 247 | roxygen2::roxygenize(PATH) 248 | ``` 249 | 250 | ## Install and use 251 | 252 | Finally, the package is ready to be installed: 253 | 254 | ```{r,eval=FALSE} 255 | # using ../rstanlm because already inside the rstanlm directory 256 | install.packages("../rstanlm", repos = NULL, type = "source") 257 | ``` 258 | ```{r,echo=FALSE} 259 | install.packages(PATH, repos = NULL, type = "source") 260 | ``` 261 | 262 | It is also possible to use `devtools::install(quick=FALSE)` to install the 263 | package. The argument `quick=FALSE` is necessary if you want to recompile the 264 | Stan models. Going forward, if you only make a change to the R code or the 265 | documentation, you can set `quick=TRUE` to speed up the process, or use 266 | `devtools::load_all()`. 267 | 268 | After installation, the package can be loaded and used like any other R package: 269 | 270 | ```{r, eval=FALSE} 271 | library("rstanlm") 272 | ``` 273 | 274 | ```{r} 275 | fit <- lm_stan(y = rnorm(10), x = rnorm(10), 276 | # arguments passed to sampling 277 | iter = 2000, refresh = 500) 278 | print(fit) 279 | ``` 280 | 281 | ```{r, echo=FALSE} 282 | unlink(PATH, recursive = TRUE, force = TRUE) 283 | ``` 284 | 285 | ## Advanced options 286 | 287 | Details can be found in the documentation for `rstan_create_package()` so we 288 | only mention some of these briefly here: 289 | 290 | * Running `rstan_create_package()` with `auto_config = TRUE` (the default value) 291 | automatically synchronizes the Stan C++ files with the `.stan` model files 292 | located in `inst/stan`, although this creates a dependency of your package on 293 | __rstantools__ itself (i.e., __rstantools__ must be installed for your package 294 | to work). Setting `auto_config = FALSE` removes this dependency, at the cost of 295 | having to manually synchronize Stan C++ files by running `rstan_config()` every 296 | time a package `.stan` file is added, removed, or even just modified. 297 | 298 | * The function `use_rstan()` can be used to add Stan functionality to an 299 | existing package, instead of building the package from scratch. 300 | * Note: If you are already using roxygen in your package, you'll have to use 301 | roxygen to update your Namespace file via the `R/-package.R` file. 302 | Check the roxygen documentation for more details. 303 | 304 | ## Adding additional Stan models to an existing R package with Stan models 305 | 306 | One may add additional Stan models to an existing package. 307 | The following steps are required if one is using `devtools`: 308 | 309 | 1. Add new Stan file, e.g., `inst/stan/new.stan` 310 | 2. Run `pkgbuild::compile_dll()` to preform a fake R CMD install. 311 | 3. Run `roxygen2::roxygenize()` to update the documentation. 312 | 4. Run ` devtools::install()` to install the package locally. 313 | 314 | ## Links 315 | 316 | * [_Guidelines for Developers of R Packages Interfacing with Stan_](https://mc-stan.org/rstantools/articles/developer-guidelines.html) 317 | 318 | * Ask a question at the [Stan Forums](https://discourse.mc-stan.org/) 319 | 320 | * [R packages](https://r-pkgs.org/) by Hadley Wickham and Jenny Bryan provides 321 | a solid foundation in R package development as well as the release process. 322 | 323 | --------------------------------------------------------------------------------