├── .Rbuildignore ├── .github ├── .gitignore ├── ISSUE_TEMPLATE │ ├── bug.md │ ├── config.yml │ ├── feature.md │ ├── maintenance.md │ └── performance.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── check-cran.yaml │ ├── check-fixed.yaml │ ├── check-implicit.yaml │ ├── cover.yaml │ ├── lint.yaml │ └── pkgdown.yaml ├── .gitignore ├── .lintr ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── NOTICE ├── R ├── stan_cmdstan_exists.R ├── stan_cmdstan_path.R ├── stan_cmdstan_version.R ├── stan_package.R ├── stan_package_clean.R ├── stan_package_compile.R ├── stan_package_configure.R ├── stan_package_create.R ├── stan_package_model.R ├── stan_package_model_files.R ├── utils_assert.R ├── utils_cmdstan.R ├── utils_logic.R └── utils_os.R ├── README.Rmd ├── README.md ├── _pkgdown.yml ├── cleanup ├── cleanup.win ├── configure ├── configure.win ├── inst ├── WORDLIST ├── configuration │ ├── cleanup │ ├── cleanup.win │ └── install.libs.R └── example │ ├── DESCRIPTION │ ├── NAMESPACE │ ├── NOTICE │ ├── R │ ├── model.R │ └── package.R │ ├── example.Rproj │ ├── github │ └── workflows │ │ └── check.yaml │ ├── gitignore │ ├── man │ ├── example-package.Rd │ └── run_bernoulli_model.Rd │ ├── rbuildignore │ └── src │ └── stan │ └── bernoulli.stan ├── instantiate.Rproj ├── man ├── instantiate-package.Rd ├── stan_cmdstan_exists.Rd ├── stan_cmdstan_path.Rd ├── stan_cmdstan_version.Rd ├── stan_package_clean.Rd ├── stan_package_compile.Rd ├── stan_package_configure.Rd ├── stan_package_create.Rd ├── stan_package_model.Rd └── stan_package_model_files.Rd ├── src ├── Makevars.win ├── cmdstan.c └── install.libs.R └── tests ├── testthat.R └── testthat ├── helper-utils.R ├── test-stan_cmdstan_exists.R ├── test-stan_cmdstan_path.R ├── test-stan_cmdstan_version.R ├── test-stan_on_windows.R ├── test-stan_package_compile.R ├── test-stan_package_configure.R ├── test-stan_package_create.R ├── test-stan_package_model.R ├── test-utils_assert.R └── test-utils_logic.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.css$ 2 | ^.*code-workspace 3 | ^.*\.gcda$ 4 | ^.*\.gcno$ 5 | ^.*\.js$ 6 | ^.*\.log$ 7 | ^.*\.out$ 8 | ^.*\.nfs.*$ 9 | ^.*\.Rout$ 10 | ^.*\.Rproj$ 11 | ^.*\.svg$ 12 | ^\.DS_Store 13 | ^\.future$ 14 | ^\.git$ 15 | ^\.github$ 16 | ^\.gitignore$ 17 | ^\.gittargets$ 18 | ^\.httr-oauth$ 19 | ^\.lintr$ 20 | ^\.Rapp.history$ 21 | ^\.Rbuildignore$ 22 | ^\.RData$ 23 | ^\.Rhistory$ 24 | ^\.Rproj\.user$ 25 | ^_pkgdown\.yml$ 26 | ^docs$ 27 | ^example$ 28 | ^example\.R$ 29 | ^CODE_OF_CONDUCT.md$ 30 | ^codemeta\.json$ 31 | ^CONTRIBUTING.md$ 32 | ^pkgdown$ 33 | ^README\.md$ 34 | ^README\.Rmd$ 35 | ^revdep$ 36 | ^LICENSE\.md$ 37 | ^paper\.md$ 38 | ^paper\.bib$ 39 | ^NOTICE$ 40 | ^cmdstan$ 41 | ^tests/testthat/test-stan_package_model\.R$ 42 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug 3 | about: Please do not submit a bug report unless your issue is a genuine bug in instantiate and not a known limitation, usage error, or issue from another package that instantiate depends on. 4 | title: "" 5 | labels: "type: bug" 6 | assignees: wlandau 7 | --- 8 | 9 | ## Prework 10 | 11 | * [ ] Read and agree to the [Contributor Code of Conduct](https://github.com/wlandau/instantiate/blob/main/CODE_OF_CONDUCT.md) and [contributing guidelines](https://github.com/ropensci/instantiate/blob/main/CONTRIBUTING.md). 12 | * [ ] Confirm that your issue is a genuine bug in the `instantiate` package itself and not a user error, known limitation, or issue from another package that `instantiate` depends on. For example, if you get errors running `tar_make_clustermq()`, try isolating the problem in a reproducible example that runs `clustermq` and not `instantiate`. And for miscellaneous troubleshooting, please post to [discussions](https://github.com/ropensci/instantiate/discussions) instead of [issues](https://github.com/ropensci/instantiate/issues). 13 | * [ ] If there is [already a relevant issue](https://github.com/ropensci/instantiate/issues), whether open or closed, comment on the existing thread instead of posting a new issue. 14 | * [ ] Post a [minimal reproducible example](https://www.tidyverse.org/help/) so the maintainer can troubleshoot the problems you identify. A reproducible example is: 15 | * [ ] **Runnable**: post enough R code and data so any onlooker can create the error on their own computer. 16 | * [ ] **Minimal**: reduce runtime wherever possible and remove complicated details that are irrelevant to the issue at hand. 17 | * [ ] **Readable**: format your code according to the [tidyverse style guide](https://style.tidyverse.org/). 18 | 19 | ## Description 20 | 21 | Please describe the bug. 22 | 23 | ## Reproducible example 24 | 25 | * [ ] Post a [minimal reproducible example](https://www.tidyverse.org/help/) so the maintainer can troubleshoot the problems you identify. A reproducible example is: 26 | * [ ] **Runnable**: post enough R code and data so any onlooker can create the error on their own computer. 27 | * [ ] **Minimal**: reduce runtime wherever possible and remove complicated details that are irrelevant to the issue at hand. 28 | * [ ] **Readable**: format your code according to the [tidyverse style guide](https://style.tidyverse.org/). 29 | 30 | ## Expected result 31 | 32 | What should have happened? Please be as specific as possible. 33 | 34 | ## Diagnostic information 35 | 36 | * A [reproducible example](https://github.com/tidyverse/reprex). 37 | * Session info, available through `sessionInfo()` or [`reprex(si = TRUE)`](https://github.com/tidyverse/reprex). 38 | * A stack trace from `traceback()` or `rlang::trace_back()`. 39 | * The [SHA-1 hash](https://git-scm.com/book/en/v1/Getting-Started-Git-Basics#Git-Has-Integrity) of the GitHub commit of `instantiate` currently installed. `packageDescription("instantiate")$GithubSHA1` shows you this. 40 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | lank_issues_enabled: true 2 | contact_links: 3 | - name: General 4 | url: https://github.com/wlandau/instantiate/discussions/categories/general 5 | about: General discussion. 6 | - name: Help 7 | url: https://github.com/wlandau/instantiate/discussions/categories/help 8 | about: Ask questions and get help. 9 | - name: Ideas 10 | url: https://github.com/wlandau/instantiate/discussions/categories/ideas 11 | about: Brainstorm ideas for new features or use cases. 12 | - name: Show and tell 13 | url: https://github.com/wlandau/instantiate/discussions/categories/show-and-tell 14 | about: Show off something you have made. 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: New feature 3 | about: Suggest a new feature. 4 | title: "" 5 | labels: "type: new feature" 6 | assignees: wlandau 7 | --- 8 | 9 | ## Prework 10 | 11 | * [ ] Read and agree to the [Contributor Code of Conduct](https://github.com/wlandau/instantiate/blob/main/CODE_OF_CONDUCT.md) and [contributing guidelines](https://github.com/ropensci/instantiate/blob/main/CONTRIBUTING.md). 12 | * [ ] If there is [already a relevant issue](https://github.com/ropensci/instantiate/issues), whether open or closed, comment on the existing thread instead of posting a new issue. 13 | * [ ] New features take time and effort to create, and they take even more effort to maintain. So if the purpose of the feature is to resolve a struggle you are encountering personally, please consider first posting a "trouble" or "other" issue so we can discuss your use case and search for existing solutions first. 14 | * [ ] Format your code according to the [tidyverse style guide](https://style.tidyverse.org/). 15 | 16 | ## Proposal 17 | 18 | Please describe the new feature. If applicable, write a minimal example in R code or pseudo-code to show input, usage, and desired output. 19 | 20 | To help us read any code you include (optional) please try to follow the [tidyverse style guide](https://style.tidyverse.org/). The `style_text()` and `style_file()` functions from the [`styler`](https://github.com/r-lib/styler) package make it easier. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/maintenance.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Maintenance 3 | about: "Something in instantiate needs work: updates, documentation, etc. Not a bug, performance issue, or new feature." 4 | title: "" 5 | labels: "type: maintenance" 6 | assignees: "" 7 | --- 8 | 9 | ## Prework 10 | 11 | * [ ] Read and agree to the [Contributor Code of Conduct](https://github.com/wlandau/instantiate/blob/main/CODE_OF_CONDUCT.md) and [contributing guidelines](https://github.com/ropensci/instantiate/blob/main/CONTRIBUTING.md). 12 | * [ ] If there is [already a relevant issue](https://github.com/ropensci/instantiate/issues), whether open or closed, comment on the existing thread instead of posting a new issue. 13 | * [ ] For any problems you identify, post a [minimal reproducible example](https://www.tidyverse.org/help/) so the maintainer can troubleshoot. A reproducible example is: 14 | * [ ] **Runnable**: post enough R code and data so any onlooker can create the error on their own computer. 15 | * [ ] **Minimal**: reduce runtime wherever possible and remove complicated details that are irrelevant to the issue at hand. 16 | * [ ] **Readable**: format your code according to the [tidyverse style guide](https://style.tidyverse.org/). 17 | 18 | ## Description 19 | 20 | Please describe the issue. 21 | 22 | To help us read any code you include (optional) please try to follow the [tidyverse style guide](https://style.tidyverse.org/). The `style_text()` and `style_file()` functions from the [`styler`](https://github.com/r-lib/styler) package make it easier. 23 | 24 | ## Reproducible example 25 | 26 | * [ ] For any problems you identify, post a [minimal reproducible example](https://www.tidyverse.org/help/) so the maintainer can troubleshoot. A reproducible example is: 27 | * [ ] **Runnable**: post enough R code and data so any onlooker can create the error on their own computer. 28 | * [ ] **Minimal**: reduce runtime wherever possible and remove complicated details that are irrelevant to the issue at hand. 29 | * [ ] **Readable**: format your code according to the [tidyverse style guide](https://style.tidyverse.org/). 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/performance.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Performance 3 | about: "Runtime, memory, or storage inefficiency" 4 | title: "" 5 | labels: "topic: performance" 6 | assignees: wlandau 7 | 8 | --- 9 | 10 | ## Prework 11 | 12 | * [ ] Read and agree to the [Contributor Code of Conduct](https://github.com/wlandau/instantiate/blob/main/CODE_OF_CONDUCT.md) and [contributing guidelines](https://github.com/ropensci/instantiate/blob/main/CONTRIBUTING.md). 13 | * [ ] If there is [already a relevant issue](https://github.com/ropensci/instantiate/issues), whether open or closed, comment on the existing thread instead of posting a new issue. 14 | * [ ] Post a [minimal reproducible example](https://www.tidyverse.org/help/) so the maintainer can troubleshoot the problems you identify. A reproducible example is: 15 | * [ ] **Runnable**: post enough R code and data so any onlooker can create the error on their own computer. 16 | * [ ] **Minimal**: reduce runtime wherever possible and remove complicated details that are irrelevant to the issue at hand. 17 | * [ ] **Readable**: format your code according to the [tidyverse style guide](https://style.tidyverse.org/). 18 | 19 | ## Description 20 | 21 | Please describe the performance issue. 22 | 23 | ## Reproducible example 24 | 25 | * [ ] Post a [minimal reproducible example](https://www.tidyverse.org/help/) so the maintainer can troubleshoot the problems you identify. A reproducible example is: 26 | * [ ] **Runnable**: post enough R code and data so any onlooker can create the error on their own computer. 27 | * [ ] **Minimal**: reduce runtime wherever possible and remove complicated details that are irrelevant to the issue at hand. 28 | * [ ] **Readable**: format your code according to the [tidyverse style guide](https://style.tidyverse.org/). 29 | 30 | ## Benchmarks 31 | 32 | How poorly does `instantiate` perform? To find out, we recommend you use the [`proffer`](https://github.com/r-prof/proffer) package and take screenshots of the results displayed in your browser. 33 | 34 | ```r 35 | library(instantiate) 36 | library(proffer) 37 | px <- pprof({ 38 | # All your instantiate code goes here. 39 | }) 40 | ``` 41 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Prework 2 | 3 | * [ ] I understand and agree to the Contributor Code of Conduct. 4 | * [ ] I have already submitted a GitHub Discussion topic to discuss my idea with the maintainer. 5 | 6 | # Related GitHub issues and pull requests 7 | 8 | * Ref: # 9 | 10 | # Summary 11 | 12 | Please explain the purpose and scope of your contribution. 13 | -------------------------------------------------------------------------------- /.github/workflows/check-cran.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: [push, pull_request] 4 | 5 | name: check-cran 6 | 7 | jobs: 8 | check-cran: 9 | runs-on: ${{ matrix.config.os }} 10 | 11 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 12 | 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | config: 17 | - {os: macOS-latest, r: 'release'} 18 | - {os: windows-latest, r: 'release'} 19 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 20 | - {os: ubuntu-latest, r: 'release'} 21 | - {os: ubuntu-latest, r: 'oldrel-1'} 22 | 23 | env: 24 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 25 | NOT_CRAN: true 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: any::rcmdcheck, local::. 42 | needs: check 43 | cache-version: 2 44 | 45 | - uses: r-lib/actions/check-r-package@v2 46 | with: 47 | upload-snapshots: true 48 | -------------------------------------------------------------------------------- /.github/workflows/check-fixed.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: [push, pull_request] 4 | 5 | name: check-fixed 6 | 7 | jobs: 8 | check-fixed: 9 | runs-on: ${{ matrix.config.os }} 10 | 11 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 12 | 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | config: 17 | - {os: ubuntu-latest, r: 'release'} 18 | 19 | env: 20 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 21 | NOT_CRAN: true 22 | R_KEEP_PKG_SOURCE: yes 23 | 24 | steps: 25 | - uses: actions/checkout@v3 26 | 27 | - uses: r-lib/actions/setup-pandoc@v2 28 | 29 | - uses: r-lib/actions/setup-r@v2 30 | with: 31 | r-version: ${{ matrix.config.r }} 32 | http-user-agent: ${{ matrix.config.http-user-agent }} 33 | use-public-rspm: true 34 | 35 | - name: Repos 36 | run: | 37 | cat("\noptions(repos=c(stan='https://mc-stan.org/r-packages/',CRAN ='https://cloud.r-project.org'))\n", file = "~/.Rprofile", append = TRUE) 38 | shell: Rscript {0} 39 | 40 | - uses: r-lib/actions/setup-r-dependencies@v2 41 | with: 42 | extra-packages: any::rcmdcheck, local::., any::cmdstanr 43 | needs: check 44 | cache-version: 2 45 | 46 | - name: Install CmdStan 47 | shell: Rscript {0} 48 | run: | 49 | cmdstanr::check_cmdstan_toolchain(fix = TRUE) 50 | cmdstanr::install_cmdstan() 51 | cmdstan <- file.path(Sys.getenv("RUNNER_TEMP"), "cmdstan") 52 | file.rename(cmdstanr::cmdstan_path(), cmdstan) 53 | lines <- paste0("\nCMDSTAN=", cmdstan, "\n") 54 | cat(lines, file = "~/.Renviron", append = TRUE) 55 | 56 | - uses: r-lib/actions/check-r-package@v2 57 | with: 58 | upload-snapshots: true 59 | -------------------------------------------------------------------------------- /.github/workflows/check-implicit.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: [push, pull_request] 4 | 5 | name: check-implicit 6 | 7 | jobs: 8 | check-implicit: 9 | runs-on: ${{ matrix.config.os }} 10 | 11 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 12 | 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | config: 17 | - {os: macOS-latest, r: 'release'} 18 | - {os: windows-latest, r: 'release', rtools: '42'} 19 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 20 | - {os: ubuntu-latest, r: 'release'} 21 | - {os: ubuntu-latest, r: 'oldrel-1'} 22 | 23 | env: 24 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 25 | NOT_CRAN: true 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 | rtools-version: '42' 37 | http-user-agent: ${{ matrix.config.http-user-agent }} 38 | use-public-rspm: true 39 | 40 | - name: Repos 41 | run: | 42 | cat("\noptions(repos=c(stan='https://mc-stan.org/r-packages/',CRAN ='https://cloud.r-project.org'))\n", file = "~/.Rprofile", append = TRUE) 43 | shell: Rscript {0} 44 | 45 | - uses: r-lib/actions/setup-r-dependencies@v2 46 | with: 47 | extra-packages: any::rcmdcheck, local::., any::cmdstanr 48 | needs: check 49 | cache-version: 2 50 | 51 | - name: Install CmdStan 52 | shell: Rscript {0} 53 | run: | 54 | cmdstanr::check_cmdstan_toolchain(fix = TRUE) 55 | cmdstanr::install_cmdstan() 56 | 57 | - uses: r-lib/actions/check-r-package@v2 58 | with: 59 | upload-snapshots: true 60 | -------------------------------------------------------------------------------- /.github/workflows/cover.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: [push, pull_request] 4 | 5 | name: cover 6 | 7 | jobs: 8 | cover: 9 | runs-on: ubuntu-latest 10 | env: 11 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 12 | NOT_CRAN: true 13 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | 18 | - uses: r-lib/actions/setup-r@v2 19 | with: 20 | use-public-rspm: true 21 | extra-repositories: 'https://mc-stan.org/r-packages/' 22 | 23 | - name: Repos 24 | run: | 25 | cat("\noptions(repos=c(stan='https://mc-stan.org/r-packages/',CRAN ='https://cloud.r-project.org'))\n", file = "~/.Rprofile", append = TRUE) 26 | shell: Rscript {0} 27 | 28 | - uses: r-lib/actions/setup-r-dependencies@v2 29 | with: 30 | extra-packages: any::covr, local::., any::cmdstanr 31 | needs: coverage 32 | cache-version: 2 33 | 34 | - name: Install CmdStan 35 | shell: Rscript {0} 36 | run: | 37 | cmdstanr::check_cmdstan_toolchain(fix = TRUE) 38 | cmdstanr::install_cmdstan() 39 | 40 | - name: Test coverage 41 | run: | 42 | covr::codecov( 43 | quiet = FALSE, 44 | clean = FALSE, 45 | install_path = file.path(Sys.getenv("RUNNER_TEMP"), "package") 46 | ) 47 | shell: Rscript {0} 48 | 49 | - name: Show testthat output 50 | if: always() 51 | run: | 52 | ## -------------------------------------------------------------------- 53 | find ${{ runner.temp }}/package -name 'testthat.Rout*' -exec cat '{}' \; || true 54 | shell: bash 55 | 56 | - name: Upload test results 57 | if: failure() 58 | uses: actions/upload-artifact@v3 59 | with: 60 | name: coverage-test-failures 61 | path: ${{ runner.temp }}/package 62 | -------------------------------------------------------------------------------- /.github/workflows/lint.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: [push, pull_request] 4 | 5 | name: lint 6 | 7 | jobs: 8 | lint: 9 | runs-on: ubuntu-latest 10 | env: 11 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 12 | steps: 13 | - uses: actions/checkout@v3 14 | 15 | - uses: r-lib/actions/setup-r@v2 16 | with: 17 | use-public-rspm: true 18 | 19 | - uses: r-lib/actions/setup-r-dependencies@v2 20 | with: 21 | extra-packages: any::lintr 22 | needs: lint 23 | cache-version: 2 24 | 25 | - name: Lint 26 | run: lintr::lint_package() 27 | shell: Rscript {0} 28 | env: 29 | LINTR_ERROR_ON_LINT: true 30 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/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 | release: 9 | types: [published] 10 | workflow_dispatch: 11 | 12 | name: pkgdown 13 | 14 | jobs: 15 | pkgdown: 16 | runs-on: ubuntu-latest 17 | concurrency: 18 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} 19 | env: 20 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 21 | steps: 22 | - uses: actions/checkout@v3 23 | 24 | - uses: r-lib/actions/setup-pandoc@v2 25 | 26 | - uses: r-lib/actions/setup-r@v2 27 | with: 28 | use-public-rspm: true 29 | 30 | - name: Repos 31 | run: | 32 | cat("\noptions(repos=c(stan='https://mc-stan.org/r-packages/',CRAN ='https://cloud.r-project.org'))\n", file = "~/.Rprofile", append = TRUE) 33 | shell: Rscript {0} 34 | 35 | - uses: r-lib/actions/setup-r-dependencies@v2 36 | with: 37 | extra-packages: any::pkgdown, local::., any::cmdstanr 38 | needs: website 39 | cache-version: 2 40 | 41 | - name: Install CmdStan 42 | shell: Rscript {0} 43 | run: | 44 | cmdstanr::check_cmdstan_toolchain(fix = TRUE) 45 | cmdstanr::install_cmdstan() 46 | 47 | - name: Build site 48 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) 49 | shell: Rscript {0} 50 | 51 | - name: Deploy to GitHub pages 52 | if: github.event_name != 'pull_request' 53 | uses: JamesIves/github-pages-deploy-action@v4.4.3 54 | with: 55 | clean: false 56 | branch: gh-pages 57 | folder: docs 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.out 3 | *.Rout 4 | *.o 5 | *.so 6 | .gittargets 7 | .DS_Store 8 | .future 9 | .Rapp.history 10 | .RData 11 | .Rhistory 12 | .Rproj.user 13 | docs 14 | inst/doc 15 | vignettes/*.html 16 | revdep 17 | cmdstan 18 | *.dll 19 | Makevars 20 | Makevars.win 21 | -------------------------------------------------------------------------------- /.lintr: -------------------------------------------------------------------------------- 1 | linters: linters_with_defaults( 2 | cyclocomp_linter = NULL, 3 | object_length_linter = NULL, 4 | object_name_linter = NULL, 5 | object_usage_linter = NULL) 6 | exclusions: list("vignettes/launcher_plugins.Rmd") 7 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the overall 26 | community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards 42 | of acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies 54 | when an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail 56 | address, posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at will.landau@gmail.com. 63 | All complaints will be reviewed and investigated promptly and fairly. 64 | 65 | All community leaders are obligated to respect the privacy and security of the 66 | reporter of any incident. 67 | 68 | ## Enforcement Guidelines 69 | 70 | Community leaders will follow these Community Impact Guidelines in determining 71 | the consequences for any action they deem in violation of this Code of Conduct: 72 | 73 | ### 1. Correction 74 | 75 | **Community Impact**: Use of inappropriate language or other behavior deemed 76 | unprofessional or unwelcome in the community. 77 | 78 | **Consequence**: A private, written warning from community leaders, providing 79 | clarity around the nature of the violation and an explanation of why the 80 | behavior was inappropriate. A public apology may be requested. 81 | 82 | ### 2. Warning 83 | 84 | **Community Impact**: A violation through a single incident or series of 85 | actions. 86 | 87 | **Consequence**: A warning with consequences for continued behavior. No 88 | interaction with the people involved, including unsolicited interaction with 89 | those enforcing the Code of Conduct, for a specified period of time. This 90 | includes avoiding interactions in community spaces as well as external channels 91 | like social media. Violating these terms may lead to a temporary or permanent 92 | ban. 93 | 94 | ### 3. Temporary Ban 95 | 96 | **Community Impact**: A serious violation of community standards, including 97 | sustained inappropriate behavior. 98 | 99 | **Consequence**: A temporary ban from any sort of interaction or public 100 | communication with the community for a specified period of time. No public or 101 | private interaction with the people involved, including unsolicited interaction 102 | with those enforcing the Code of Conduct, is allowed during this period. 103 | Violating these terms may lead to a permanent ban. 104 | 105 | ### 4. Permanent Ban 106 | 107 | **Community Impact**: Demonstrating a pattern of violation of community 108 | standards, including sustained inappropriate behavior, harassment of an 109 | individual, or aggression toward or disparagement of classes of individuals. 110 | 111 | **Consequence**: A permanent ban from any sort of public interaction within the 112 | community. 113 | 114 | ## Attribution 115 | 116 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 117 | version 2.0, 118 | available at . 119 | 120 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 121 | enforcement ladder](https://github.com/mozilla/diversity). 122 | 123 | [homepage]: https://www.contributor-covenant.org 124 | 125 | For answers to common questions about this code of conduct, see the FAQ at 126 | . Translations are available at . 127 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Development is a community effort, and we welcome participation. 4 | 5 | ## Code of Conduct 6 | 7 | Please note that the this project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms. 8 | 9 | ## Discussions 10 | 11 | In the GitHub Discussions forum, you can post general questions, brainstorm ideas, and ask for help. 12 | 13 | ## Issues 14 | 15 | The GitHub Issues forum is for bug reports, performance issues, maintenance tasks, and feature requests. When you post, please abide by the following guidelines. 16 | 17 | * Before posting a new issue or discussion topic, please take a moment to search for existing similar threads in order to avoid duplication. 18 | * For bug reports: if you can, please install the latest GitHub version of the package and verify that the issue still persists. 19 | * Describe your issue in prose as clearly and concisely as possible. 20 | * For any problem you identify, post a [minimal reproducible example](https://www.tidyverse.org/help/) like [this one](https://github.com/ropensci/targets/issues/256#issuecomment-754229683) so the maintainer can troubleshoot. A reproducible example is: 21 | * **Runnable**: post enough R code and data so any onlooker can create the error on their own computer. 22 | * **Minimal**: reduce runtime wherever possible and remove complicated details that are irrelevant to the issue at hand. 23 | * **Readable**: format your code according to the [tidyverse style guide](https://style.tidyverse.org/). 24 | 25 | ## Development 26 | 27 | External code contributions are extremely helpful in the right circumstances. Here are the recommended steps. 28 | 29 | 1. Prior to contribution, please propose your idea in a discussion topic or issue thread so you and the maintainer can define the intent and scope of your work. 30 | 2. [Fork the repository](https://help.github.com/articles/fork-a-repo/). 31 | 3. Follow the [GitHub flow](https://guides.github.com/introduction/flow/index.html) to create a new branch, add commits, and open a pull request. 32 | 4. Discuss your code with the maintainer in the pull request thread. 33 | 5. If everything looks good, the maintainer will merge your code into the project. 34 | 35 | Please also follow these additional guidelines. 36 | 37 | * Respect the architecture and reasoning of the package. Depending on the scope of your work, you may want to read the design documents (package vignettes). 38 | * If possible, keep contributions small enough to easily review manually. It is okay to split up your work into multiple pull requests. 39 | * Format your code according to the [tidyverse style guide](https://style.tidyverse.org/) and check your formatting with the `lint_package()` function from the [`lintr`](https://github.com/jimhester/lintr) package. 40 | * For new features or functionality, add tests in `tests`. Tests that can be automated should go in `tests/testthat/`. Tests that cannot be automated should go in `tests/interactive/`. For features affecting performance, it is good practice to add profiling studies to `tests/performance/`. 41 | * Check code coverage with `covr::package_coverage()`. Automated tests should cover all the new or changed functionality in your pull request. 42 | * Run overall package checks with `devtools::check()` and `goodpractice::gp()` 43 | * Describe your contribution in the project's `NEWS.md` file. Be sure to mention relevent GitHub issue numbers and your GitHub name as done in existing news entries. 44 | * If you feel contribution is substantial enough for official author or contributor status, please add yourself to the `Authors@R` field of the `DESCRIPTION` file. 45 | 46 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: instantiate 2 | Title: Pre-Compiled 'CmdStan' Models in R Packages 3 | Description: Similar to 'rstantools' for 'rstan', 4 | the 'instantiate' package builds pre-compiled 5 | 'CmdStan' models into CRAN-ready statistical modeling R packages. 6 | The models compile once during installation, 7 | the executables live inside the file systems of their respective packages, 8 | and users have the full power and convenience of 9 | 'cmdstanr' without any additional compilation after package installation. 10 | This approach saves time and helps R package developers 11 | migrate from 'rstan' to the more modern 'cmdstanr'. 12 | Packages 'rstantools', 'cmdstanr', 'stannis', and 13 | 'stanapi' are similar Stan clients with different objectives. 14 | Version: 0.2.3.9000 15 | License: MIT + file LICENSE 16 | URL: https://wlandau.github.io/instantiate/, 17 | https://github.com/wlandau/instantiate 18 | BugReports: https://github.com/wlandau/instantiate/issues 19 | Authors@R: c( 20 | person( 21 | given = c("William", "Michael"), 22 | family = "Landau", 23 | role = c("aut", "cre"), 24 | email = "will.landau.oss@gmail.com", 25 | comment = c(ORCID = "0000-0003-1878-3253") 26 | ), 27 | person( 28 | family = "Eli Lilly and Company", 29 | role = c("cph", "fnd") 30 | )) 31 | Depends: 32 | R (>= 4.0.0) 33 | Imports: 34 | callr, 35 | fs, 36 | rlang, 37 | utils 38 | Suggests: 39 | knitr (>= 1.30), 40 | markdown (>= 1.1), 41 | rmarkdown (>= 2.4), 42 | testthat (>= 3.0.0), 43 | withr 44 | Encoding: UTF-8 45 | Language: en-US 46 | Config/testthat/edition: 3 47 | Roxygen: list(markdown = TRUE) 48 | RoxygenNote: 7.3.2 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2023 2 | COPYRIGHT HOLDER: Eli Lilly and Company 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2023 Eli Lilly and Company 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(stan_cmdstan_exists) 4 | export(stan_cmdstan_path) 5 | export(stan_cmdstan_version) 6 | export(stan_package_clean) 7 | export(stan_package_compile) 8 | export(stan_package_configure) 9 | export(stan_package_create) 10 | export(stan_package_model) 11 | export(stan_package_model_files) 12 | importFrom(callr,r) 13 | importFrom(fs,dir_copy) 14 | importFrom(rlang,abort) 15 | importFrom(rlang,check_installed) 16 | importFrom(rlang,inform) 17 | importFrom(rlang,is_installed) 18 | importFrom(rlang,warn) 19 | importFrom(utils,capture.output) 20 | importFrom(utils,globalVariables) 21 | importFrom(utils,install.packages) 22 | useDynLib(instantiate, .registration = TRUE) 23 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # instantiate 0.2.3.9000 (development) 2 | 3 | 4 | 5 | # instantiate 0.2.3 6 | 7 | * Set `show = TRUE` and `stderr = "2>&1"` in the `callr` process that compiles models. 8 | * Add a new `compile` argument to `stan_package_model()` (#26, @stemangiola). 9 | 10 | # instantiate 0.2.2 11 | 12 | * Allow downstream packages to install even if `CmdStanR` is not installed (#20, @xinxinc476). 13 | 14 | # instantiate 0.2.1 15 | 16 | * Address CRAN warnings in generated packages about non-portable compilation flags (#19, @xinxinc476). 17 | 18 | # instantiate 0.2.0 19 | 20 | * Remove "internal" installation (#16). 21 | * In the documentation, remove claims that `instantiate` is a good fit for centralized multi-user R environments (c.f. https://github.com/stan-dev/cmdstan/issues/1175). 22 | * Check subdirectories of the fixed CmdStan installation path. 23 | 24 | # instantiate 0.1.0 25 | 26 | * Use `install.libs.R` for both CmdStan in `instantiate` and Stan model compilation in packages (#1, #9, #12). 27 | * Stan models should now be in `src/stan/` instead of `inst/stan/` (#12). `inst/stan/` should still work for the next few versions, but it is now deprecated. When a modeling package is installed, its `install.libs.R` moves `src/stan/` to `bin/stan/` and then compiles models inside `bin/stan/`. 28 | * Disable staged installation for `instantiate` itself to help the hard-coded paths in CmdStan work as expected in "internal" installation. 29 | 30 | # instantiate 0.0.4 31 | 32 | * Relax `cmdstanr` requirement (now minimum version 0.5.2). 33 | 34 | # instantiate 0.0.3 35 | 36 | * Generate a modified tarball of the package which always installs CmdStan internally, regardless of environment variables (#8). The appropriate version of this tarball will be attached to forthcoming releases on GitHub. 37 | * Bug fixes for internal CmdStan installation. 38 | 39 | # instantiate 0.0.2 40 | 41 | * Address CRAN comments from the submission of version 0.0.1. 42 | 43 | # instantiate 0.0.1 44 | 45 | * First version 46 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This package includes components from other open-source software. The projects and licenses are listed below. 2 | 3 | * {cmdstanr} (https://github.com/stan-dev/cmdstanr) by Stan Developers and their Assignees. 4 | 5 | BSD 3-Clause License 6 | ===================== 7 | 8 | Copyright (c) 2019, Stan Developers and their Assignees 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | 14 | 1. Redistributions of source code must retain the above copyright notice, this 15 | list of conditions and the following disclaimer. 16 | 17 | 2. Redistributions in binary form must reproduce the above copyright notice, 18 | this list of conditions and the following disclaimer in the documentation 19 | and/or other materials provided with the distribution. 20 | 21 | 3. Neither the name of the copyright holder nor the names of its 22 | contributors may be used to endorse or promote products derived from 23 | this software without specific prior written permission. 24 | 25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 29 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | 36 | 37 | * CmdStan (https://github.com/stan-dev/cmdstan) by Stan Developers and their Assignees. 38 | 39 | BSD 3-Clause License 40 | ===================== 41 | 42 | Copyright (c) 2014, Stan 43 | All rights reserved. 44 | 45 | Redistribution and use in source and binary forms, with or without modification, 46 | are permitted provided that the following conditions are met: 47 | 48 | * Redistributions of source code must retain the above copyright notice, this 49 | list of conditions and the following disclaimer. 50 | 51 | * Redistributions in binary form must reproduce the above copyright notice, this 52 | list of conditions and the following disclaimer in the documentation and/or 53 | other materials provided with the distribution. 54 | 55 | * Neither the name of the {organization} nor the names of its 56 | contributors may be used to endorse or promote products derived from 57 | this software without specific prior written permission. 58 | 59 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 60 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 61 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 62 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 63 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 64 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 65 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 66 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 67 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 68 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 69 | 70 | 71 | * {configure} (https://github.com/kevinushey/configure) by Kevin Ushey. 72 | 73 | MIT License 74 | ===================== 75 | 76 | Copyright 2021 Kevin Ushey 77 | 78 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 79 | 80 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 81 | 82 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 83 | -------------------------------------------------------------------------------- /R/stan_cmdstan_exists.R: -------------------------------------------------------------------------------- 1 | #' @title Check if `instantiate` can find CmdStanR and CmdStan. 2 | #' @export 3 | #' @family cmdstan 4 | #' @description Check if `instantiate` can find CmdStanR and CmdStan. 5 | #' @inheritParams stan_cmdstan_path 6 | #' @return `TRUE` if `instantiate` can find the CmdStanR R package and the 7 | #' CmdStan command line tool. Returns `FALSE` otherwise. 8 | #' @examples 9 | #' stan_cmdstan_exists() 10 | stan_cmdstan_exists <- function( 11 | cmdstan_install = Sys.getenv("CMDSTAN_INSTALL", unset = "") 12 | ) { 13 | # nocov start 14 | if (!rlang::is_installed("cmdstanr")) { 15 | return(FALSE) # Not possible to cover in regular unit tests. 16 | } 17 | # nocov end 18 | path <- stan_cmdstan_path(cmdstan_install = cmdstan_install) 19 | cmdstan_valid(path) 20 | } 21 | 22 | cmdstan_valid <- function(path) { 23 | length(path) > 0L && 24 | nzchar(path) && 25 | dir.exists(path) && 26 | file.exists(file.path(path, "makefile")) && 27 | makefile_version_exists(file.path(path, "makefile")) 28 | } 29 | 30 | makefile_version_exists <- function(makefile) { 31 | any(grepl(pattern = "^CMDSTAN_VERSION", x = readLines(makefile))) 32 | } 33 | -------------------------------------------------------------------------------- /R/stan_cmdstan_path.R: -------------------------------------------------------------------------------- 1 | #' @title Path to CmdStan for `instantiate` 2 | #' @export 3 | #' @family packages 4 | #' @description Return the directory path to CmdStan that the `instantiate` 5 | #' package uses. 6 | #' @return Character of length 1, directory path to CmdStan. The path 7 | #' may or may not exist. Returns the empty string `""` if the path 8 | #' cannot be determined. 9 | #' @param cmdstan_install Character of length 1, how to look for an installed 10 | #' copy of CmdStan. See for details. 11 | #' Choices: 12 | #' 1. `""` (default): look at the original value that the `CMDSTAN_INSTALL` 13 | #' environment variable contained when `instantiate` at the time 14 | #' when it was installed. 15 | #' If it was `"implicit"` or `"fixed"`, then choose 16 | #' the corresponding option below. Otherwise, default to `"implicit"`. 17 | #' 2. `"implicit"`: Let the `cmdstanr::cmdstan_path()` decide where 18 | #' to look for CmdStan. As explained in the `cmdstanr` documentation, 19 | #' the output of `cmdstanr::cmdstan_path()` depends 20 | #' on the current value of the `CMDSTAN` environment variable. 21 | #' The `cmdstanr` package must be installed. If it 22 | #' is not installed, then `stan_cmdstan_path()` 23 | #' returns the empty string `""`. 24 | #' 3. `"fixed"`: Use the path to CmdStan that was originally 25 | #' contained in `Sys.getenv("CMDSTAN")` at the time when `instantiate` 26 | #' was installed. 27 | #' @examples 28 | #' stan_cmdstan_path() 29 | stan_cmdstan_path <- function( 30 | cmdstan_install = Sys.getenv("CMDSTAN_INSTALL", unset = "") 31 | ) { 32 | # nocov start 33 | if (!rlang::is_installed("cmdstanr")) { 34 | return("") # Not possible to cover in regular unit tests. 35 | } 36 | # nocov end 37 | install <- if_any( 38 | identical(cmdstan_install, ""), 39 | .Call(c_cmdstan_path_install, PACKAGE = "instantiate"), 40 | cmdstan_install 41 | ) 42 | stan_assert_install(install) 43 | path <- if_any( 44 | identical(install, "fixed"), 45 | .Call(c_cmdstan_path_fixed, PACKAGE = "instantiate"), 46 | cmdstanr_path() 47 | ) 48 | if_any( 49 | cmdstan_valid(path), 50 | path, 51 | cmdstanr("cmdstan_default_path")(dir = path) 52 | ) %|||% "" 53 | } 54 | -------------------------------------------------------------------------------- /R/stan_cmdstan_version.R: -------------------------------------------------------------------------------- 1 | #' @title Version of CmdStan that `instantiate` uses. 2 | #' @export 3 | #' @family cmdstan 4 | #' @description Return the version of CmdStan that the `instantiate` 5 | #' package uses. 6 | #' @return Character of length 1, version of CmdStan that the `instantiate` 7 | #' package uses. If CmdStan is not found, then the return value depends 8 | #' on the `error_on_NA` argument. 9 | #' @inheritParams stan_cmdstan_path 10 | #' @param error_on_NA Logical of length 1, whether an error should be thrown 11 | #' if CmdStan is not found. 12 | #' @examples 13 | #' if (stan_cmdstan_exists()) { 14 | #' message(stan_cmdstan_version()) 15 | #' } 16 | stan_cmdstan_version <- function( 17 | cmdstan_install = Sys.getenv("CMDSTAN_INSTALL", unset = ""), 18 | error_on_NA = TRUE 19 | ) { 20 | stan_assert_cmdstanr() 21 | path_old <- cmdstanr_path() 22 | if (cmdstan_valid(path_old)) { 23 | on.exit(suppressMessages(cmdstanr("set_cmdstan_path")(path = path_old))) 24 | } 25 | path_new <- stan_cmdstan_path(cmdstan_install = cmdstan_install) 26 | suppressMessages(cmdstanr("set_cmdstan_path")(path = path_new)) 27 | cmdstanr("cmdstan_version")(error_on_NA = error_on_NA) 28 | } 29 | -------------------------------------------------------------------------------- /R/stan_package.R: -------------------------------------------------------------------------------- 1 | #' instantiate: pre-compiled CmdStan models in R packages 2 | #' @name instantiate-package 3 | #' @family help 4 | #' @description Similar to [`rstantools`](https://mc-stan.org/rstantools/) 5 | #' for [`rstan`](https://mc-stan.org/rstan/), 6 | #' the `instantiate` package builds pre-compiled 7 | #' [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan) 8 | #' models into CRAN-ready statistical modeling R packages. 9 | #' The models compile once during installation, 10 | #' the executables live inside the file systems of their 11 | #' respective packages, and users have the full power 12 | #' and convenience of [`CmdStanR`](https://mc-stan.org/cmdstanr/) 13 | #' without any additional compilation after package installation. 14 | #' This approach saves time and helps R package developers 15 | #' migrate from [`rstan`](https://mc-stan.org/rstan/) 16 | #' to the more modern [`CmdStanR`](https://mc-stan.org/cmdstanr/). 17 | #' @useDynLib instantiate, .registration = TRUE 18 | #' @importFrom callr r 19 | #' @importFrom fs dir_copy 20 | #' @importFrom rlang abort check_installed inform is_installed warn 21 | #' @importFrom utils capture.output globalVariables install.packages 22 | NULL 23 | 24 | utils::globalVariables(".") 25 | -------------------------------------------------------------------------------- /R/stan_package_clean.R: -------------------------------------------------------------------------------- 1 | #' @title Remove one or more compiled Stan models in an R package. 2 | #' @export 3 | #' @family packages 4 | #' @description Remove one or more compiled Stan models from the file system 5 | #' of an R package. 6 | #' @return `NULL` (invisibly). Called for its side effects. 7 | #' @inheritParams stan_package_compile 8 | #' @examples 9 | #' if (identical(Sys.getenv("INSTANTIATE_EXAMPLES"), "true")) { 10 | #' path <- tempfile() 11 | #' stan_package_create(path = path) 12 | #' stan_package_configure(path = path) 13 | #' models <- stan_package_model_files(path) 14 | #' list.files(file.path(path, "inst", "stan")) 15 | #' stan_package_compile(models) 16 | #' list.files(file.path(path, "inst", "stan")) 17 | #' # Clean up the compiled Stan model files: 18 | #' stan_package_clean(models = models) 19 | #' list.files(file.path(path, "inst", "stan")) 20 | #' } 21 | stan_package_clean <- function( 22 | models = instantiate::stan_package_model_files() 23 | ) { 24 | stan_assert( 25 | models, 26 | is.character(.), 27 | !anyNA(.), 28 | nzchar(.), 29 | message = "models arg must be a character vector of Stan model files." 30 | ) 31 | base <- gsub("\\.[[:alnum:]]+$", "", models) 32 | suppressWarnings(file.remove(base)) 33 | suppressWarnings(file.remove(paste0(base, ".exe"))) 34 | suppressWarnings(file.remove(paste0(base, ".EXE"))) 35 | invisible() 36 | } 37 | -------------------------------------------------------------------------------- /R/stan_package_compile.R: -------------------------------------------------------------------------------- 1 | #' @title Compile the Stan models in an R package. 2 | #' @export 3 | #' @family packages 4 | #' @description Compile all Stan models in a directory, usually in a package. 5 | #' @details If building a package using `instantiate`, all Stan model files 6 | #' must live in a folder called `src/stan/` in the package source 7 | #' directory. 8 | #' @return `NULL` (invisibly). Called for its side effects. 9 | #' @inheritParams stan_cmdstan_path 10 | #' @param models Character vector of file paths to Stan model source code 11 | #' files. Defaults to the Stan files in `./src/stan/` 12 | #' because all the Stan model files must live in the `src/stan/` folder 13 | #' for an R package built with `instantiate`. 14 | #' @param verbose Logical of length 1, whether to set the 15 | #' `cmdstanr_verbose` global option to print more compiler messages 16 | #' than usual. 17 | #' @param quiet Argument to `cmdstanr::cmdstan_model()` to control compilation. 18 | #' @param pedantic Logical of length 1, whether to activate pedantic 19 | #' mode when compiling the Stan models. See the `cmdstanr` documentation 20 | #' for details. 21 | #' @param include_paths Argument to `cmdstanr::cmdstan_model()` 22 | #' to control model compilation. 23 | #' @param user_header Argument to `cmdstanr::cmdstan_model()` 24 | #' to control model compilation. 25 | #' @param cpp_options Argument to `cmdstanr::cmdstan_model()` 26 | #' to control model compilation. 27 | #' @param stanc_options Argument to `cmdstanr::cmdstan_model()` 28 | #' to model control compilation. 29 | #' @param force_recompile Argument to `cmdstanr::cmdstan_model()` 30 | #' to model control compilation. 31 | #' @param threads Argument to `cmdstanr::cmdstan_model()` 32 | #' to model control compilation. 33 | #' @param ... Other named arguments to `cmdstanr::cmdstan_model()`. 34 | #' @examples 35 | #' if (identical(Sys.getenv("INSTANTIATE_EXAMPLES"), "true")) { 36 | #' path <- tempfile() 37 | #' stan_package_create(path = path) 38 | #' stan_package_configure(path = path) 39 | #' models <- stan_package_model_files(path) 40 | #' list.files(file.path(path, "inst", "stan")) 41 | #' stan_package_compile(models) 42 | #' list.files(file.path(path, "inst", "stan")) 43 | #' } 44 | stan_package_compile <- function( 45 | models = instantiate::stan_package_model_files(), 46 | cmdstan_install = Sys.getenv("CMDSTAN_INSTALL", unset = ""), 47 | verbose = TRUE, 48 | quiet = FALSE, 49 | pedantic = FALSE, 50 | include_paths = NULL, 51 | user_header = NULL, 52 | cpp_options = list(), 53 | stanc_options = list(), 54 | force_recompile = getOption("cmdstanr_force_recompile", default = FALSE), 55 | threads = FALSE, 56 | ... 57 | ) { 58 | # Not possible to test in automated tests in one coverage run. 59 | # Covered in GitHub Actions workflows. 60 | # nocov start 61 | result <- try(stan_assert_cmdstanr()) 62 | if (inherits(result, "try-error")) { 63 | return(invisible()) 64 | } 65 | if (!stan_cmdstan_exists(cmdstan_install = cmdstan_install)) { 66 | stan_cmdstan_message() 67 | return(invisible()) 68 | } 69 | # nocov end 70 | stan_assert( 71 | models, 72 | is.character(.), 73 | length(.) > 0L, 74 | !anyNA(.), 75 | nzchar(.), 76 | message = "models arg must be a nonempty character vector of Stan files." 77 | ) 78 | models <- models[file.exists(models)] 79 | if (length(models) < 1L) { 80 | stan_message("No Stan models found.") 81 | return(invisible()) 82 | } 83 | path_old <- cmdstanr_path() 84 | if (cmdstan_valid(path_old)) { 85 | on.exit(suppressMessages(cmdstanr("set_cmdstan_path")(path = path_old))) 86 | } 87 | path_new <- stan_cmdstan_path(cmdstan_install = cmdstan_install) 88 | suppressMessages(cmdstanr("set_cmdstan_path")(path = path_new)) 89 | lapply( 90 | X = models, 91 | FUN = stan_compile_model, 92 | verbose = verbose, 93 | quiet = quiet, 94 | pedantic = pedantic, 95 | include_paths = include_paths, 96 | user_header = user_header, 97 | cpp_options = cpp_options, 98 | stanc_options = stanc_options, 99 | force_recompile = force_recompile, 100 | threads = threads, 101 | ... 102 | ) 103 | invisible() 104 | } 105 | 106 | stan_compile_model <- function( 107 | model, 108 | verbose, 109 | quiet, 110 | pedantic, 111 | include_paths, 112 | user_header, 113 | cpp_options, 114 | stanc_options, 115 | force_recompile, 116 | threads, 117 | ... 118 | ) { 119 | if (verbose) { 120 | old <- getOption("cmdstanr_verbose") 121 | on.exit(options("cmdstanr_verbose" = old)) 122 | options("cmdstanr_verbose" = TRUE) 123 | } 124 | cmdstanr("cmdstan_model")( 125 | stan_file = model, 126 | compile = TRUE, 127 | quiet = quiet, 128 | pedantic = pedantic, 129 | include_paths = include_paths, 130 | user_header = user_header, 131 | cpp_options = cpp_options, 132 | stanc_options = stanc_options, 133 | force_recompile = force_recompile, 134 | threads = threads, 135 | ... 136 | ) 137 | invisible() 138 | } 139 | -------------------------------------------------------------------------------- /R/stan_package_configure.R: -------------------------------------------------------------------------------- 1 | #' @title Configure an R package with built-in Stan models. 2 | #' @export 3 | #' @family packages 4 | #' @description Write configuration files in an R package which 5 | #' compile all the Stan models in `src/stan/` when the package installs. 6 | #' @details Writes configuration scripts `configure` and `configure.win` 7 | #' in the directory specified by the `path` argument. 8 | #' @return `NULL` (invisibly). Called for its side effects. 9 | #' @param path Character of length 1, file path to the package which will 10 | #' contain Stan models in `src/stan/` at installation time. 11 | #' @param overwrite Logical of length 1, whether to overwrite any existing 12 | #' configuration files. 13 | #' @examples 14 | #' if (identical(Sys.getenv("INSTANTIATE_EXAMPLES"), "true")) { 15 | #' path <- tempfile() 16 | #' stan_package_create(path = path) 17 | #' list.files(path) 18 | #' stan_package_configure(path = path) 19 | #' list.files(path) 20 | #' } 21 | stan_package_configure <- function(path = getwd(), overwrite = FALSE) { 22 | stan_assert( 23 | dir.exists(path), 24 | message = paste0("package directory \"", path, "\" does not exist") 25 | ) 26 | stan_assert( 27 | overwrite, 28 | isTRUE(.) || isFALSE(.), 29 | message = "overwrite must be a logical of length 1." 30 | ) 31 | in_cleanup <- system.file( 32 | file.path("configuration", "cleanup"), 33 | package = "instantiate", 34 | mustWork = TRUE 35 | ) 36 | in_cleanup_win <- system.file( 37 | file.path("configuration", "cleanup.win"), 38 | package = "instantiate", 39 | mustWork = TRUE 40 | ) 41 | in_install <- system.file( 42 | file.path("configuration", "install.libs.R"), 43 | package = "instantiate", 44 | mustWork = TRUE 45 | ) 46 | src <- file.path(path, "src") 47 | out_cleanup <- file.path(path, "cleanup") 48 | out_cleanup_win <- file.path(path, "cleanup.win") 49 | out_install <- file.path(src, "install.libs.R") 50 | out_makevars <- file.path(src, "Makevars") 51 | out_makevars_win <- file.path(src, "Makevars.win") 52 | file.copy( 53 | from = in_cleanup, 54 | to = out_cleanup, 55 | overwrite = overwrite, 56 | copy.mode = TRUE 57 | ) 58 | file.copy( 59 | from = in_cleanup_win, 60 | to = out_cleanup_win, 61 | overwrite = overwrite 62 | ) 63 | if (!file.exists(src)) { 64 | dir.create(src) 65 | } 66 | file.copy( 67 | from = in_install, 68 | to = out_install, 69 | overwrite = overwrite, 70 | copy.mode = TRUE 71 | ) 72 | if (!file.exists(out_makevars)) { 73 | writeLines("", out_makevars) 74 | } 75 | if (!file.exists(out_makevars_win)) { 76 | writeLines("", out_makevars_win) 77 | } 78 | invisible() 79 | } 80 | -------------------------------------------------------------------------------- /R/stan_package_create.R: -------------------------------------------------------------------------------- 1 | #' @title Create example package with a built-in Stan model. 2 | #' @export 3 | #' @keywords packages 4 | #' @description Create an example package with a Stan model inside. 5 | #' @details After creating the package, the next step is to 6 | #' configure it with [stan_package_configure()]. After that, 7 | #' install it as an ordinary R package to automatically compile the models. 8 | #' @return `NULL` (invisibly). Called for its side effects. 9 | #' @param path Path to write the package. Must not already exist. 10 | #' @examples 11 | #' if (identical(Sys.getenv("INSTANTIATE_EXAMPLES"), "true")) { 12 | #' path <- tempfile() 13 | #' stan_package_create(path = path) 14 | #' list.files(path) 15 | #' } 16 | stan_package_create <- function(path = tempfile()) { 17 | stan_assert( 18 | path, 19 | is.character(.), 20 | length(.) == 1L, 21 | !anyNA(.), 22 | nzchar(.), 23 | !file.exists(path), 24 | message = "path must be a valid file path that does not already exist." 25 | ) 26 | source <- system.file("example", package = "instantiate", mustWork = TRUE) 27 | fs::dir_copy(path = source, new_path = path, overwrite = TRUE) 28 | file.rename( 29 | from = file.path(path, "gitignore"), 30 | to = file.path(path, ".gitignore") 31 | ) 32 | file.rename( 33 | from = file.path(path, "rbuildignore"), 34 | to = file.path(path, ".Rbuildignore") 35 | ) 36 | file.rename( 37 | from = file.path(path, "github"), 38 | to = file.path(path, ".github") 39 | ) 40 | message( 41 | paste0( 42 | "Package with an internal Stan model created at directory path \"", 43 | path, 44 | "\". Configure with stan_package_configure() before installing." 45 | ) 46 | ) 47 | invisible() 48 | } 49 | -------------------------------------------------------------------------------- /R/stan_package_model.R: -------------------------------------------------------------------------------- 1 | #' @title Get a pre-compiled Stan model built into an R package. 2 | #' @export 3 | #' @keywords packages 4 | #' @description Get the `cmdstanr` model object for a pre-compiled Stan 5 | #' model inside a package. 6 | #' @details Packages configured with `instantiate` compile their Stan 7 | #' models on installation. Then the `stan_package_model()` function 8 | #' retrieves the `cmdstanr::cmdstan_model()` object without needing 9 | #' to re-compile the model. Please see the documentation website 10 | #' of the `instantiate` package for examples. 11 | #' @return An `R6` Stan model object from the `cmdstanr` package. 12 | #' Please visit the documentation website at 13 | #' for detailed information on the composition of this model object 14 | #' and how to use it to conduct Bayesian inference. 15 | #' @inheritParams stan_cmdstan_path 16 | #' @param name Character of length 1, base name of the Stan model file 17 | #' (without the containing directory or `.stan` file extension). 18 | #' @param package Character of length 1, name of the R package to look 19 | #' for the built-in Stan model. 20 | #' @param library Character of length 1 or `NULL`, library path 21 | #' to look for the package with the built-in Stan model. 22 | #' Passed to the `lib.loc` argument of `system.file()`. 23 | #' @param compile `TRUE` to compile the model and store the executable file 24 | #' where the package is installed in `.libpaths()`. `FALSE` to 25 | #' skip compilation and assume the model is already compiled, 26 | #' which is usually the case. 27 | #' @param ... Named arguments passed via `cmdstanr::cmdstan_model()` 28 | #' to the `compile()` method of the CmdStan model object. 29 | #' @examples 30 | #' # Please see the documentation website of the {instantiate} package 31 | #' # for examples. 32 | stan_package_model <- function( 33 | name, 34 | package, 35 | library = NULL, 36 | cmdstan_install = Sys.getenv("CMDSTAN_INSTALL", unset = ""), 37 | compile = FALSE, 38 | ... 39 | ) { 40 | stan_assert_cmdstanr() 41 | stan_assert(name, is.character(.), !anyNA(.), nzchar(.)) 42 | stan_assert(package, is.character(.), !anyNA(.), nzchar(.)) 43 | stan_file <- get(x = "system.file", envir = globalenv()) ( 44 | file.path("bin", "stan", paste0(name, ".stan")), 45 | package = package, 46 | lib.loc = library, 47 | mustWork = FALSE 48 | ) 49 | stan_file_inst <- get(x = "system.file", envir = globalenv()) ( 50 | file.path("stan", paste0(name, ".stan")), 51 | package = package, 52 | lib.loc = library, 53 | mustWork = FALSE 54 | ) 55 | if (file.exists(stan_file_inst)) { 56 | stan_deprecate( 57 | name = "Stan files installed to inst/stan/", 58 | date = "2024-01-03", 59 | version = "0.0.4.9001", 60 | alternative = paste( 61 | "Reinstall your Stan modeling package so your", 62 | "compiled models are in bin/stan/ instead." 63 | ) 64 | ) 65 | stan_file <- if_any(file.exists(stan_file), stan_file, stan_file_inst) 66 | } 67 | stan_assert( 68 | file.exists(stan_file), 69 | message = sprintf("Stan model file \"%s\" not found.", stan_file) 70 | ) 71 | exe_file <- file.path(dirname(stan_file), name) 72 | exe_file <- if_any(stan_on_windows(), paste0(exe_file, ".exe"), exe_file) 73 | path_old <- cmdstanr_path() 74 | if (cmdstan_valid(path_old)) { 75 | on.exit(suppressMessages(cmdstanr("set_cmdstan_path")(path = path_old))) 76 | } 77 | path_new <- stan_cmdstan_path(cmdstan_install = cmdstan_install) 78 | suppressMessages(cmdstanr("set_cmdstan_path")(path = path_new)) 79 | cmdstanr("cmdstan_model")( 80 | stan_file = stan_file, 81 | exe_file = exe_file, 82 | compile = compile, 83 | ... 84 | ) 85 | } 86 | -------------------------------------------------------------------------------- /R/stan_package_model_files.R: -------------------------------------------------------------------------------- 1 | #' @title List Stan model file paths. 2 | #' @export 3 | #' @family packages 4 | #' @description List all the paths to the Stan model files in a package. 5 | #' @details All Stan models must live in the `src/stan/` directory in the 6 | #' package file system. 7 | #' @return Character vector of paths to Stan model files in the package. 8 | #' @param path Character of length 1, root path to start from when searching 9 | #' for Stan model files. 10 | #' @examples 11 | #' path <- tempfile() 12 | #' stan_package_create(path = path) 13 | #' stan_package_model_files(path) 14 | stan_package_model_files <- function(path = getwd()) { 15 | stan_assert( 16 | path, 17 | is.character(.), 18 | !anyNA(.), 19 | nzchar(.), 20 | length(.) == 1L, 21 | message = "invalid package directory path in stan_package_model_files()" 22 | ) 23 | out <- list.files( 24 | path, 25 | full.names = TRUE, 26 | recursive = TRUE, 27 | pattern = "\\.stan$" 28 | ) 29 | stan_assert( 30 | length(out) > 0L, 31 | message = paste0( 32 | "No Stan model files found at \"", 33 | path, 34 | "\". Packages built with {instantiate} must put their Stan models here." 35 | ) 36 | ) 37 | out 38 | } 39 | -------------------------------------------------------------------------------- /R/utils_assert.R: -------------------------------------------------------------------------------- 1 | stan_assert <- function( 2 | value = NULL, 3 | ..., 4 | message = NULL, 5 | envir = parent.frame() 6 | ) { 7 | force(envir) 8 | expr <- match.call(expand.dots = FALSE)$... 9 | if (!length(expr)) { 10 | expr <- list(quote(.)) 11 | } 12 | conditions <- lapply( 13 | expr, 14 | function(expr) all(eval(expr, envir = list(. = value), enclos = envir)) 15 | ) 16 | if (!all(unlist(conditions))) { 17 | chr_expr <- lapply(expr, function(x) sprintf("all(%s)", deparse(x))) 18 | chr_expr <- paste(unlist(chr_expr), collapse = " && ") 19 | chr_value <- deparse(substitute(value)) 20 | out <- sprintf("%s is not true on . = %s", chr_expr, chr_value) 21 | stan_error(message %|||% out) 22 | } 23 | invisible() 24 | } 25 | 26 | stan_assert_install <- function(install) { 27 | message <- paste( 28 | "The CMDSTAN_INSTALL environment variable and the cmdstan_install", 29 | "argument must be \"implicit\", \"fixed\", \"\", or unset", 30 | "both when {instantiate} is installed and when {instantiate} is used.", 31 | "If you are using {instantiate} and you get this error even though", 32 | "CMDSTAN_INSTALL is an allowable value, please reinstall {instantiate}", 33 | "with an allowable value of CMDSTAN_INSTALL." 34 | ) 35 | stan_assert( 36 | install, 37 | is.character(.), 38 | !anyNA(.), 39 | length(.) == 1L, 40 | message = message 41 | ) 42 | stan_assert( 43 | install %in% c("implicit", "fixed", ""), 44 | message = message 45 | ) 46 | invisible() 47 | } 48 | 49 | stan_deprecate <- function(name, date, version, alternative) { 50 | message <- sprintf( 51 | "%s was deprecated on %s (instantiate version %s). Alternative: %s.", 52 | name, 53 | date, 54 | version, 55 | alternative 56 | ) 57 | stan_warn( 58 | message = message, 59 | class = c("stan_deprecate", "stan_warning", "stan") 60 | ) 61 | } 62 | 63 | stan_error <- function(message = NULL) { 64 | stan_stop( 65 | message = message, 66 | class = c("stan_error", "stan") 67 | ) 68 | } 69 | 70 | stan_warning <- function(message = NULL) { 71 | stan_warn( 72 | message = message, 73 | class = c("stan_warning", "stan") 74 | ) 75 | } 76 | 77 | stan_stop <- function(message, class) { 78 | old <- getOption("rlang_backtrace_on_error") 79 | on.exit(options(rlang_backtrace_on_error = old)) 80 | options(rlang_backtrace_on_error = "none") 81 | rlang::abort(message = message, class = class, call = emptyenv()) 82 | } 83 | 84 | stan_warn <- function(message, class) { 85 | old <- getOption("rlang_backtrace_on_error") 86 | on.exit(options(rlang_backtrace_on_error = old)) 87 | options(rlang_backtrace_on_error = "none") 88 | rlang::warn(message = message, class = class) 89 | } 90 | 91 | stan_message <- function(message) { 92 | old <- getOption("rlang_backtrace_on_error") 93 | on.exit(options(rlang_backtrace_on_error = old)) 94 | options(rlang_backtrace_on_error = "none") 95 | rlang::inform(message = message, class = c("stan_message", "stan")) 96 | } 97 | 98 | stan_cmdstan_message <- function() { 99 | stan_message(stan_cmdstan_text()) 100 | } 101 | 102 | stan_cmdstan_text <- function() { 103 | paste0( 104 | "CmdStan path not found: \"", 105 | stan_cmdstan_path(), 106 | "\". Please read the installation instructions at ", 107 | "https://wlandau.github.io/instantiate/" 108 | ) 109 | } 110 | 111 | # Not possible to unit-test: 112 | # nocov start 113 | stan_assert_cmdstanr <- function() { 114 | tryCatch( 115 | rlang::check_installed( 116 | pkg = "cmdstanr", 117 | reason = paste( 118 | "The {cmdstanr} package is required in order to install", 119 | "CmdStan and run Stan models. Please install it manually using", 120 | "install.packages(pkgs = \"cmdstanr\",", 121 | "repos = c(\"https://mc-stan.org/r-packages/\", getOption(\"repos\"))" 122 | ) 123 | ), 124 | error = function(e) { 125 | stan_error(conditionMessage(e)) 126 | } 127 | ) 128 | } 129 | # nocov end 130 | 131 | stan_cmdstanr_text <- function() { 132 | paste( 133 | "The {cmdstanr} package is needed to install CmdStan and run Stan models.", 134 | "Please read the installation instructions", 135 | "of the {instantiate} package at https://wlandau.github.io/instantiate/" 136 | ) 137 | } 138 | -------------------------------------------------------------------------------- /R/utils_cmdstan.R: -------------------------------------------------------------------------------- 1 | cmdstanr <- function(name) { 2 | eval(parse(text = paste0("cmdstanr::", name))) 3 | } 4 | 5 | cmdstanr_path <- function() { 6 | if_any( 7 | rlang::is_installed("cmdstanr"), 8 | tryCatch(cmdstanr("cmdstan_path")(), error = function(condition) ""), 9 | "" 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /R/utils_logic.R: -------------------------------------------------------------------------------- 1 | `%||%` <- function(x, y) { 2 | if (length(x) > 0L) { 3 | x 4 | } else { 5 | y 6 | } 7 | } 8 | 9 | `%|||%` <- function(x, y) { 10 | if (is.null(x)) { 11 | y 12 | } else { 13 | x 14 | } 15 | } 16 | 17 | if_any <- function(condition, true, false) { 18 | if (any(condition)) { 19 | true 20 | } else { 21 | false 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /R/utils_os.R: -------------------------------------------------------------------------------- 1 | stan_on_windows <- function() { 2 | identical(tolower(Sys.info()[["sysname"]]), "windows") 3 | } 4 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | ```{r, include = FALSE} 6 | knitr::opts_chunk$set( 7 | eval = FALSE, 8 | collapse = TRUE, 9 | comment = "#>", 10 | fig.path = "man/figures/README-", 11 | out.width = "100%" 12 | ) 13 | ``` 14 | 15 | # instantiate: pre-compiled CmdStan models in R packages 16 | 17 | [![CRAN](https://www.r-pkg.org/badges/version/instantiate)](https://CRAN.R-project.org/package=instantiate) 18 | [![status](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) 19 | [![check-cmdstanr](https://github.com/wlandau/instantiate/workflows/check-cmdstanr/badge.svg)](https://github.com/wlandau/instantiate/actions?query=workflow%3Acheck-cmdstanr) 20 | [![check-cran](https://github.com/wlandau/instantiate/workflows/check-cran/badge.svg)](https://github.com/wlandau/instantiate/actions?query=workflow%3Acheck-cran) 21 | [![check-fixed](https://github.com/wlandau/instantiate/workflows/check-fixed/badge.svg)](https://github.com/wlandau/instantiate/actions?query=workflow%3Acheck-fixed) 22 | [![codecov](https://codecov.io/gh/wlandau/instantiate/branch/main/graph/badge.svg)](https://app.codecov.io/gh/wlandau/instantiate) 23 | [![lint](https://github.com/wlandau/instantiate/workflows/lint/badge.svg)](https://github.com/wlandau/instantiate/actions?query=workflow%3Alint) 24 | 25 | Similar to [`rstantools`](https://mc-stan.org/rstantools/) for [`rstan`](https://mc-stan.org/rstan/), the `instantiate` package builds pre-compiled [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan) models into CRAN-ready statistical modeling R packages. The models compile once during installation, the executables live inside the file systems of their respective packages, and users have the full power and convenience of [`CmdStanR`](https://mc-stan.org/cmdstanr/) without any additional compilation after package installation. This approach saves time and helps R package developers migrate from [`rstan`](https://mc-stan.org/rstan/) to the more modern [`CmdStanR`](https://mc-stan.org/cmdstanr/). 26 | 27 | # Documentation 28 | 29 | The website at includes a [function reference](https://wlandau.github.io/instantiate/reference/index.html) and other documentation. 30 | 31 | # Installing `instantiate` 32 | 33 | The `instantiate` package depends on the R package [`CmdStanR`](https://mc-stan.org/cmdstanr/) and the command line tool [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan), so it is important to follow these stages in order: 34 | 35 | 1. Install the R package [`CmdStanR`](https://mc-stan.org/cmdstanr/). [`CmdStanR`](https://mc-stan.org/cmdstanr/) is not on CRAN, so the recommended way to install it is `install.packages("cmdstanr", repos = c("https://mc-stan.org/r-packages/", getOption("repos")))`. 36 | 2. Optional: set environment variables `CMDSTAN_INSTALL` and/or `CMDSTAN` to manage the [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan) installation. See the "Administering CmdStan" section below for details. 37 | 3. Install `instantiate` using one of the R commands below. 38 | 39 | Type | Source | Command 40 | ---|---|--- 41 | Release | CRAN | `install.packages("instantiate")` 42 | Development | GitHub | `remotes::install_github("wlandau/instantiate")` 43 | Development | R-universe | `install.packages("instantiate", repos = "https://wlandau.r-universe.dev")` 44 | 45 | # Installing packages that use `instantiate` 46 | 47 | Packages that use `instantiate` may be published on CRAN. CRAN does not have `CmdStan`, so the models are not pre-compiled in the Mac OS and Windows binaries. If you install from CRAN, please install from the source. For example: 48 | 49 | ```{r, eval = FALSE} 50 | install.packages("hdbayes", type = "source") 51 | ``` 52 | 53 | # Environment variables 54 | 55 | The `instantiate` package uses environment variables to manage the installation of [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan). An environment variable is an operating system setting with a name and a value (both text strings). In R, there are two ways to set environment variables: 56 | 57 | 1. `Sys.setenv()`, which sets environment variables temporarily for the current R session. 58 | 2. The `.Renviron` text file in you home directory, which passes environment variables to all new R sessions. the [`edit_r_environ()`](https://usethis.r-lib.org/reference/edit.html) function from the [`usethis`](https://usethis.r-lib.org/) package helps. 59 | 60 | # Administering CmdStan 61 | 62 | By default, `instantiate` looks for the copy of [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan) located at `cmdstanr::install_cmdstan()`. If you upgrade [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan), then the path returned by `cmdstanr::install_cmdstan()` will change, which may not be desirable in some cases. To permanently lock the path that `instantiate` uses, follow these steps: 63 | 64 | 1. Set the `CMDSTAN` environment variable to the desired path to [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan). 65 | 2. Set the `CMDSTAN_INSTALL` environment variable to `"fixed"`. 66 | 3. Install `instantiate`. 67 | 68 | Henceforth, `instantiate` will automatically use the [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan) path from (1), regardless of the value of `CMDSTAN` after (3). To prefer `cmdstanr::cmdstan_path()` instead, you could do one of the following: 69 | 70 | * Reinstall `instantiate` with `CMDSTAN_INSTALL` not equal to `"fixed"`, or 71 | * Set `CMDSTAN_INSTALL` to `"implicit"` at runtime, or 72 | * Set the `cmdstan_install` argument to `"implicit"` for the current `instantiate` package function you are using. 73 | 74 | 75 | # Packaging Stan models 76 | 77 | The following section explains how to create an R package with pre-compiled Stan models. This stage of the development workflow is considered "runtime" for the purposes of administering [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan) as described previously. 78 | 79 | ## Structure 80 | 81 | Begin with an R package with one or more Stan model files inside the `src/stan/` directory. `stan_package_create()` is a convenient way to start. 82 | 83 | ```r 84 | stan_package_create(path = "package_folder") 85 | #> Example package named "example" created at "package_folder". Run stan_package_configure(path = "package_folder") so that the built-in Stan model will compile when the package installs. 86 | ``` 87 | 88 | At minimum the package file structure should look something like this: 89 | 90 | ```r 91 | fs::dir_tree("package_folder") 92 | #> package_folder 93 | #> ├── DESCRIPTION 94 | #> └── src 95 | #> └── stan 96 | #> └── bernoulli.stan 97 | ``` 98 | 99 | ## Configuration 100 | 101 | Configure the package so the Stan models compile during installation. `stan_package_configure()` writes required scripts `cleanup`, `cleanup.win`, `src/Makevars`, `src/Makevars.win`, and `src/install.libs.R`. Inside `src/install.libs.R` is a call to `instantiate::stan_package_compile()` which you can manually edit to control how your models are compiled. For example, different calls to `stan_package_compile()` can compile different groups of models using different C++ compiler flags. 102 | 103 | 104 | ```r 105 | fs::dir_tree("package_folder") 106 | #> package_folder 107 | #> ├── DESCRIPTION 108 | #> ├── cleanup 109 | #> ├── cleanup.win 110 | #> └── src 111 | #> ├── Makevars 112 | #> ├── Makevars.win 113 | #> ├── install.libs.R 114 | #> └── stan 115 | #> └── bernoulli.stan 116 | ``` 117 | 118 | ## Installation 119 | 120 | Install the package just like you would any other R package. To install it from your local copy of `package_folder`, open R and run: 121 | 122 | ```r 123 | install.packages(pkgs = "package_folder", type = "source", repos = NULL) 124 | ``` 125 | 126 | ## Models 127 | 128 | A user can now run a model from the package without any additional compilation. See the documentation of [`CmdStanR`](https://mc-stan.org/cmdstanr/index.html) to learn how to use [`CmdStanR`](https://mc-stan.org/cmdstanr/index.html) model objects. 129 | 130 | ```r 131 | library(example) 132 | model <- stan_package_model(name = "bernoulli", package = "example") 133 | print(model) # CmdStanR model object 134 | #> data { 135 | #> int N; 136 | #> array[N] int y; 137 | #> } 138 | #> parameters { 139 | #> real theta; 140 | #> } 141 | #> model { 142 | #> theta ~ beta(1,1); // uniform prior on interval 0,1 143 | #> y ~ bernoulli(theta); 144 | #> } 145 | fit <- model$sample( 146 | data = list(N = 10, y = c(1, 0, 1, 0, 1, 0, 0, 0, 0, 0)), 147 | refresh = 0, 148 | iter_warmup = 2000, 149 | iter_sampling = 4000 150 | ) 151 | #> Running MCMC with 4 sequential chains... 152 | #> 153 | #> Chain 1 finished in 0.0 seconds. 154 | #> Chain 2 finished in 0.0 seconds. 155 | #> Chain 3 finished in 0.0 seconds. 156 | #> Chain 4 finished in 0.0 seconds. 157 | #> 158 | #> All 4 chains finished successfully. 159 | #> Mean chain execution time: 0.0 seconds. 160 | #> Total execution time: 0.6 seconds. 161 | 162 | fit$summary() 163 | #> # A tibble: 2 × 10 164 | #> variable mean median sd mad q5 q95 rhat ess_bulk ess_tail 165 | #> 166 | #> 1 lp__ -8.15 -7.87 0.725 0.317 -9.60 -7.64 1.00 7365. 8498. 167 | #> 2 theta 0.333 0.324 0.130 0.134 0.137 0.563 1.00 6229. 7560. 168 | ``` 169 | 170 | You can write an exported user-side function in your R package to access the model. For example, you might store this code in a `R/model.R` file in the package: 171 | 172 | ```r 173 | #' @title Fit the Bernoulli model. 174 | #' @export 175 | #' @family models 176 | #' @description Fit the Bernoulli Stan model and return posterior summaries. 177 | #' @return A data frame of posterior summaries. 178 | #' @param y Numeric vector of Bernoulli observations (zeroes and ones). 179 | #' @param `...` Named arguments to the `sample()` method of CmdStan model 180 | #' objects: 181 | #' @examples 182 | #' if (instantiate::stan_cmdstan_exists()) { 183 | #' run_bernoulli_model(y = c(1, 0, 1, 0, 1, 0, 0, 0, 0, 0)) 184 | #' } 185 | run_bernoulli_model <- function(y, ...) { 186 | stopifnot(is.numeric(y) && all(y >= 0 & y <= 1)) 187 | model <- stan_package_model(name = "bernoulli", package = "mypackage") 188 | fit <- model$sample(data = list(N = length(y), y = y), ...) 189 | fit$summary() 190 | } 191 | ``` 192 | 193 | ## Development 194 | 195 | 1. In your package `DESCRIPTION` file, list in the `Additional_repositories:` field ([example in `brms`](https://github.com/paul-buerkner/brms/blob/5c09251daabd5416e3d47004cc6c62816dc53cfa/DESCRIPTION#L95-L96)). This step is only necessary while [`cmdstanr`](https://mc-stan.org/cmdstanr/) is not yet on CRAN. 196 | 197 | ``` 198 | Additional_repositories: 199 | https://mc-stan.org/r-packages/ 200 | ``` 201 | 202 | 2. In your package `DESCRIPTION` and `NAMESPACE` files, import the `instantiate` package and function `stan_package_model()`. 203 | 3. Write user-side statistical modeling functions which call the models in your package as mentioned above. 204 | 4. [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan) is too big for [CRAN](https://cran.r-project.org), so `instantiate` will not be able to access it there. So if you plan to submit your package to CRAN, please skip the appropriate code in your examples, vignettes, and tests when `instantiate::stan_cmdstan_exists()` is `FALSE`. Explicit `if()` statements like the above one in the [`roxygen2`](https://roxygen2.r-lib.org/) `@examples` work for examples and vignettes. For tests, it is convenient to use [`testthat::skip_if_not()`](https://testthat.r-lib.org/reference/skip.html), e.g. `skip_if_not(stan_cmdstan_exists())`. 205 | 5. [`pkgload::load_all()`](https://pkgload.r-lib.org/reference/load_all.html) might not compile your models. If you use [`pkgload`](https://pkgload.r-lib.org/) or [`devtools`](https://devtools.r-lib.org/) to load and develop your package, you may need to call `instantiate::stan_package_compile()` from the root directory of your package to compile your models manually. 206 | 6. For [version control](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control), it is best practice to commit only source code files and documentation. Please do not commit any compiled executable Stan model files to your repository. If you do commit them, then other users with different machines will have trouble installing your package, and your commit history will consume too much storage. For [Git](https://git-scm.com), you may add the following lines to the [`.gitigore`](https://git-scm.com/docs/gitignore) file at the root of your package: 207 | 208 | ``` 209 | src/stan/** 210 | !src/stan/**/*.* 211 | src/stan/**/*.exe 212 | src/stan/**/*.EXE 213 | ``` 214 | 215 | 7. For [continuous integration](https://devguide.ropensci.org/ci.html) (e.g. on [GitHub Actions](https://github.com/r-lib/actions)), please use [`cmdstanr`](https://mc-stan.org/cmdstanr/)-based installation as explained above, and tweak your workflow YAML files as explained in that section. 216 | 8. For general information on R package development, please consult the free online book [R Packages (2e)](https://r-pkgs.org/) by [Hadley Wickham](https://github.com/hadley) and [Jennifer Bryan](https://github.com/jennybc), as well as the official manual on [Writing R Extensions](https://cran.r-project.org/doc/manuals/R-exts.html) by the R Core Team. 217 | 218 | # Code of Conduct 219 | 220 | Please note that the `instantiate` project is released with a [Contributor Code of Conduct](https://github.com/wlandau/instantiate/blob/main/CODE_OF_CONDUCT.md). By contributing to this project, you agree to abide by its terms. 221 | 222 | # Citation 223 | 224 | ```{r, eval = FALSE, warning = FALSE, comment = ""} 225 | To cite package ‘instantiate’ in publications use: 226 | 227 | Landau WM (2023). _instantiate: A Minimal CmdStan Client for R Packages_. 228 | https://wlandau.github.io/instantiate/, https://github.com/wlandau/instantiate. 229 | 230 | A BibTeX entry for LaTeX users is 231 | 232 | @Manual{, 233 | title = {instantiate: A Minimal CmdStan Client for R Packages}, 234 | author = {William Michael Landau}, 235 | year = {2023}, 236 | note = {https://wlandau.github.io/instantiate/, 237 | https://github.com/wlandau/instantiate}, 238 | } 239 | ``` 240 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # instantiate: pre-compiled CmdStan models in R packages 3 | 4 | [![CRAN](https://www.r-pkg.org/badges/version/instantiate)](https://CRAN.R-project.org/package=instantiate) 5 | [![status](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) 6 | [![check-cmdstanr](https://github.com/wlandau/instantiate/workflows/check-cmdstanr/badge.svg)](https://github.com/wlandau/instantiate/actions?query=workflow%3Acheck-cmdstanr) 7 | [![check-cran](https://github.com/wlandau/instantiate/workflows/check-cran/badge.svg)](https://github.com/wlandau/instantiate/actions?query=workflow%3Acheck-cran) 8 | [![check-fixed](https://github.com/wlandau/instantiate/workflows/check-fixed/badge.svg)](https://github.com/wlandau/instantiate/actions?query=workflow%3Acheck-fixed) 9 | [![codecov](https://codecov.io/gh/wlandau/instantiate/branch/main/graph/badge.svg)](https://app.codecov.io/gh/wlandau/instantiate) 10 | [![lint](https://github.com/wlandau/instantiate/workflows/lint/badge.svg)](https://github.com/wlandau/instantiate/actions?query=workflow%3Alint) 11 | 12 | Similar to [`rstantools`](https://mc-stan.org/rstantools/) for 13 | [`rstan`](https://mc-stan.org/rstan/), the `instantiate` package builds 14 | pre-compiled [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan) 15 | models into CRAN-ready statistical modeling R packages. The models 16 | compile once during installation, the executables live inside the file 17 | systems of their respective packages, and users have the full power and 18 | convenience of [`CmdStanR`](https://mc-stan.org/cmdstanr/) without any 19 | additional compilation after package installation. This approach saves 20 | time and helps R package developers migrate from 21 | [`rstan`](https://mc-stan.org/rstan/) to the more modern 22 | [`CmdStanR`](https://mc-stan.org/cmdstanr/). 23 | 24 | # Documentation 25 | 26 | The website at includes a 27 | [function 28 | reference](https://wlandau.github.io/instantiate/reference/index.html) 29 | and other documentation. 30 | 31 | # Installing `instantiate` 32 | 33 | The `instantiate` package depends on the R package 34 | [`CmdStanR`](https://mc-stan.org/cmdstanr/) and the command line tool 35 | [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan), so it is 36 | important to follow these stages in order: 37 | 38 | 1. Install the R package [`CmdStanR`](https://mc-stan.org/cmdstanr/). 39 | [`CmdStanR`](https://mc-stan.org/cmdstanr/) is not on CRAN, so the 40 | recommended way to install it is 41 | `install.packages("cmdstanr", repos = c("https://mc-stan.org/r-packages/", getOption("repos")))`. 42 | 2. Optional: set environment variables `CMDSTAN_INSTALL` and/or 43 | `CMDSTAN` to manage the 44 | [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan) 45 | installation. See the “Administering CmdStan” section below for 46 | details. 47 | 3. Install `instantiate` using one of the R commands below. 48 | 49 | | Type | Source | Command | 50 | |-------------|------------|-----------------------------------------------------------------------------| 51 | | Release | CRAN | `install.packages("instantiate")` | 52 | | Development | GitHub | `remotes::install_github("wlandau/instantiate")` | 53 | | Development | R-universe | `install.packages("instantiate", repos = "https://wlandau.r-universe.dev")` | 54 | 55 | # Installing packages that use `instantiate` 56 | 57 | Packages that use `instantiate` may be published on CRAN. CRAN does not 58 | have `CmdStan`, so the models are not pre-compiled in the Mac OS and 59 | Windows binaries. If you install from CRAN, please install from the 60 | source. For example: 61 | 62 | ``` r 63 | install.packages("hdbayes", type = "source") 64 | ``` 65 | 66 | # Environment variables 67 | 68 | The `instantiate` package uses environment variables to manage the 69 | installation of 70 | [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan). An 71 | environment variable is an operating system setting with a name and a 72 | value (both text strings). In R, there are two ways to set environment 73 | variables: 74 | 75 | 1. `Sys.setenv()`, which sets environment variables temporarily for the 76 | current R session. 77 | 2. The `.Renviron` text file in you home directory, which passes 78 | environment variables to all new R sessions. the 79 | [`edit_r_environ()`](https://usethis.r-lib.org/reference/edit.html) 80 | function from the [`usethis`](https://usethis.r-lib.org/) package 81 | helps. 82 | 83 | # Administering CmdStan 84 | 85 | By default, `instantiate` looks for the copy of 86 | [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan) located at 87 | `cmdstanr::install_cmdstan()`. If you upgrade 88 | [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan), then the path 89 | returned by `cmdstanr::install_cmdstan()` will change, which may not be 90 | desirable in some cases. To permanently lock the path that `instantiate` 91 | uses, follow these steps: 92 | 93 | 1. Set the `CMDSTAN` environment variable to the desired path to 94 | [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan). 95 | 2. Set the `CMDSTAN_INSTALL` environment variable to `"fixed"`. 96 | 3. Install `instantiate`. 97 | 98 | Henceforth, `instantiate` will automatically use the 99 | [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan) path from (1), 100 | regardless of the value of `CMDSTAN` after (3). To prefer 101 | `cmdstanr::cmdstan_path()` instead, you could do one of the following: 102 | 103 | - Reinstall `instantiate` with `CMDSTAN_INSTALL` not equal to `"fixed"`, 104 | or 105 | - Set `CMDSTAN_INSTALL` to `"implicit"` at runtime, or 106 | - Set the `cmdstan_install` argument to `"implicit"` for the current 107 | `instantiate` package function you are using. 108 | 109 | # Packaging Stan models 110 | 111 | The following section explains how to create an R package with 112 | pre-compiled Stan models. This stage of the development workflow is 113 | considered “runtime” for the purposes of administering 114 | [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan) as described 115 | previously. 116 | 117 | ## Structure 118 | 119 | Begin with an R package with one or more Stan model files inside the 120 | `src/stan/` directory. `stan_package_create()` is a convenient way to 121 | start. 122 | 123 | ``` r 124 | stan_package_create(path = "package_folder") 125 | #> Example package named "example" created at "package_folder". Run stan_package_configure(path = "package_folder") so that the built-in Stan model will compile when the package installs. 126 | ``` 127 | 128 | At minimum the package file structure should look something like this: 129 | 130 | ``` r 131 | fs::dir_tree("package_folder") 132 | #> package_folder 133 | #> ├── DESCRIPTION 134 | #> └── src 135 | #> └── stan 136 | #> └── bernoulli.stan 137 | ``` 138 | 139 | ## Configuration 140 | 141 | Configure the package so the Stan models compile during installation. 142 | `stan_package_configure()` writes required scripts `cleanup`, 143 | `cleanup.win`, `src/Makevars`, `src/Makevars.win`, and 144 | `src/install.libs.R`. Inside `src/install.libs.R` is a call to 145 | `instantiate::stan_package_compile()` which you can manually edit to 146 | control how your models are compiled. For example, different calls to 147 | `stan_package_compile()` can compile different groups of models using 148 | different C++ compiler flags. 149 | 150 | ``` r 151 | fs::dir_tree("package_folder") 152 | #> package_folder 153 | #> ├── DESCRIPTION 154 | #> ├── cleanup 155 | #> ├── cleanup.win 156 | #> └── src 157 | #> ├── Makevars 158 | #> ├── Makevars.win 159 | #> ├── install.libs.R 160 | #> └── stan 161 | #> └── bernoulli.stan 162 | ``` 163 | 164 | ## Installation 165 | 166 | Install the package just like you would any other R package. To install 167 | it from your local copy of `package_folder`, open R and run: 168 | 169 | ``` r 170 | install.packages(pkgs = "package_folder", type = "source", repos = NULL) 171 | ``` 172 | 173 | ## Models 174 | 175 | A user can now run a model from the package without any additional 176 | compilation. See the documentation of 177 | [`CmdStanR`](https://mc-stan.org/cmdstanr/index.html) to learn how to 178 | use [`CmdStanR`](https://mc-stan.org/cmdstanr/index.html) model objects. 179 | 180 | ``` r 181 | library(example) 182 | model <- stan_package_model(name = "bernoulli", package = "example") 183 | print(model) # CmdStanR model object 184 | #> data { 185 | #> int N; 186 | #> array[N] int y; 187 | #> } 188 | #> parameters { 189 | #> real theta; 190 | #> } 191 | #> model { 192 | #> theta ~ beta(1,1); // uniform prior on interval 0,1 193 | #> y ~ bernoulli(theta); 194 | #> } 195 | fit <- model$sample( 196 | data = list(N = 10, y = c(1, 0, 1, 0, 1, 0, 0, 0, 0, 0)), 197 | refresh = 0, 198 | iter_warmup = 2000, 199 | iter_sampling = 4000 200 | ) 201 | #> Running MCMC with 4 sequential chains... 202 | #> 203 | #> Chain 1 finished in 0.0 seconds. 204 | #> Chain 2 finished in 0.0 seconds. 205 | #> Chain 3 finished in 0.0 seconds. 206 | #> Chain 4 finished in 0.0 seconds. 207 | #> 208 | #> All 4 chains finished successfully. 209 | #> Mean chain execution time: 0.0 seconds. 210 | #> Total execution time: 0.6 seconds. 211 | 212 | fit$summary() 213 | #> # A tibble: 2 × 10 214 | #> variable mean median sd mad q5 q95 rhat ess_bulk ess_tail 215 | #> 216 | #> 1 lp__ -8.15 -7.87 0.725 0.317 -9.60 -7.64 1.00 7365. 8498. 217 | #> 2 theta 0.333 0.324 0.130 0.134 0.137 0.563 1.00 6229. 7560. 218 | ``` 219 | 220 | You can write an exported user-side function in your R package to access 221 | the model. For example, you might store this code in a `R/model.R` file 222 | in the package: 223 | 224 | ``` r 225 | #' @title Fit the Bernoulli model. 226 | #' @export 227 | #' @family models 228 | #' @description Fit the Bernoulli Stan model and return posterior summaries. 229 | #' @return A data frame of posterior summaries. 230 | #' @param y Numeric vector of Bernoulli observations (zeroes and ones). 231 | #' @param `...` Named arguments to the `sample()` method of CmdStan model 232 | #' objects: 233 | #' @examples 234 | #' if (instantiate::stan_cmdstan_exists()) { 235 | #' run_bernoulli_model(y = c(1, 0, 1, 0, 1, 0, 0, 0, 0, 0)) 236 | #' } 237 | run_bernoulli_model <- function(y, ...) { 238 | stopifnot(is.numeric(y) && all(y >= 0 & y <= 1)) 239 | model <- stan_package_model(name = "bernoulli", package = "mypackage") 240 | fit <- model$sample(data = list(N = length(y), y = y), ...) 241 | fit$summary() 242 | } 243 | ``` 244 | 245 | ## Development 246 | 247 | 1. In your package `DESCRIPTION` file, list 248 | in the `Additional_repositories:` 249 | field ([example in 250 | `brms`](https://github.com/paul-buerkner/brms/blob/5c09251daabd5416e3d47004cc6c62816dc53cfa/DESCRIPTION#L95-L96)). 251 | This step is only necessary while 252 | [`cmdstanr`](https://mc-stan.org/cmdstanr/) is not yet on CRAN. 253 | 254 | 255 | 256 | Additional_repositories: 257 | https://mc-stan.org/r-packages/ 258 | 259 | 2. In your package `DESCRIPTION` and `NAMESPACE` files, import the 260 | `instantiate` package and function `stan_package_model()`. 261 | 3. Write user-side statistical modeling functions which call the models 262 | in your package as mentioned above. 263 | 4. [`CmdStan`](https://mc-stan.org/users/interfaces/cmdstan) is too big 264 | for [CRAN](https://cran.r-project.org), so `instantiate` will not be 265 | able to access it there. So if you plan to submit your package to 266 | CRAN, please skip the appropriate code in your examples, vignettes, 267 | and tests when `instantiate::stan_cmdstan_exists()` is `FALSE`. 268 | Explicit `if()` statements like the above one in the 269 | [`roxygen2`](https://roxygen2.r-lib.org/) `@examples` work for 270 | examples and vignettes. For tests, it is convenient to use 271 | [`testthat::skip_if_not()`](https://testthat.r-lib.org/reference/skip.html), 272 | e.g. `skip_if_not(stan_cmdstan_exists())`. 273 | 5. [`pkgload::load_all()`](https://pkgload.r-lib.org/reference/load_all.html) 274 | might not compile your models. If you use 275 | [`pkgload`](https://pkgload.r-lib.org/) or 276 | [`devtools`](https://devtools.r-lib.org/) to load and develop your 277 | package, you may need to call `instantiate::stan_package_compile()` 278 | from the root directory of your package to compile your models 279 | manually. 280 | 6. For [version 281 | control](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control), 282 | it is best practice to commit only source code files and 283 | documentation. Please do not commit any compiled executable Stan 284 | model files to your repository. If you do commit them, then other 285 | users with different machines will have trouble installing your 286 | package, and your commit history will consume too much storage. For 287 | [Git](https://git-scm.com), you may add the following lines to the 288 | [`.gitigore`](https://git-scm.com/docs/gitignore) file at the root 289 | of your package: 290 | 291 | 292 | 293 | src/stan/** 294 | !src/stan/**/*.* 295 | src/stan/**/*.exe 296 | src/stan/**/*.EXE 297 | 298 | 7. For [continuous integration](https://devguide.ropensci.org/ci.html) 299 | (e.g. on [GitHub Actions](https://github.com/r-lib/actions)), please 300 | use [`cmdstanr`](https://mc-stan.org/cmdstanr/)-based installation 301 | as explained above, and tweak your workflow YAML files as explained 302 | in that section. 303 | 8. For general information on R package development, please consult the 304 | free online book [R Packages (2e)](https://r-pkgs.org/) by [Hadley 305 | Wickham](https://github.com/hadley) and [Jennifer 306 | Bryan](https://github.com/jennybc), as well as the official manual 307 | on [Writing R 308 | Extensions](https://cran.r-project.org/doc/manuals/R-exts.html) by 309 | the R Core Team. 310 | 311 | # Code of Conduct 312 | 313 | Please note that the `instantiate` project is released with a 314 | [Contributor Code of 315 | Conduct](https://github.com/wlandau/instantiate/blob/main/CODE_OF_CONDUCT.md). 316 | By contributing to this project, you agree to abide by its terms. 317 | 318 | # Citation 319 | 320 | ``` r 321 | To cite package ‘instantiate’ in publications use: 322 | 323 | Landau WM (2023). _instantiate: A Minimal CmdStan Client for R Packages_. 324 | https://wlandau.github.io/instantiate/, https://github.com/wlandau/instantiate. 325 | 326 | A BibTeX entry for LaTeX users is 327 | 328 | @Manual{, 329 | title = {instantiate: A Minimal CmdStan Client for R Packages}, 330 | author = {William Michael Landau}, 331 | year = {2023}, 332 | note = {https://wlandau.github.io/instantiate/, 333 | https://github.com/wlandau/instantiate}, 334 | } 335 | ``` 336 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | destination: docs/ 2 | reference: 3 | - title: Help 4 | contents: 5 | - 'instantiate-package' 6 | - title: CmdStan 7 | contents: 8 | - 'stan_cmdstan_exists' 9 | - 'stan_cmdstan_path' 10 | - 'stan_cmdstan_version' 11 | - title: R packages with Stan models 12 | contents: 13 | - 'stan_package_clean' 14 | - 'stan_package_compile' 15 | - 'stan_package_configure' 16 | - 'stan_package_create' 17 | - 'stan_package_model' 18 | - 'stan_package_model_files' 19 | -------------------------------------------------------------------------------- /cleanup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # 3 | # This script was copied and modified from the source code of the {configure} 4 | # R package by Kevin Ushey. License and copyright are in the comment below. 5 | # 6 | # MIT License 7 | # ===================== 8 | # 9 | # Copyright 2021 Kevin Ushey 10 | # 11 | # Permission is hereby granted, free of charge, to any person obtaining a copy 12 | # of this software and associated documentation files (the “Software”), to deal 13 | # in the Software without restriction, including without limitation the rights 14 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | # copies of the Software, and to permit persons to whom the Software is 16 | # furnished to do so, subject to the following conditions: 17 | # 18 | # The above copyright notice and this permission notice shall be included 19 | # in all copies or substantial portions of the Software. 20 | # 21 | # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | # THE SOFTWARE. 28 | rm -f src/cmdstan.o src/instantiate.so 29 | rm -fr bin 30 | -------------------------------------------------------------------------------- /cleanup.win: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # 3 | # This script was copied and modified from the source code of the {configure} 4 | # R package by Kevin Ushey. License and copyright are in the comment below. 5 | # 6 | # MIT License 7 | # ===================== 8 | # 9 | # Copyright 2021 Kevin Ushey 10 | # 11 | # Permission is hereby granted, free of charge, to any person obtaining a copy 12 | # of this software and associated documentation files (the “Software”), to deal 13 | # in the Software without restriction, including without limitation the rights 14 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | # copies of the Software, and to permit persons to whom the Software is 16 | # furnished to do so, subject to the following conditions: 17 | # 18 | # The above copyright notice and this permission notice shall be included 19 | # in all copies or substantial portions of the Software. 20 | # 21 | # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | # THE SOFTWARE. 28 | rm -rf bin src/cmdstan.o src/instantiate.dll src/Makevars.win 29 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # 3 | # This script was copied and modified from the source code of the {configure} 4 | # R package by Kevin Ushey. License and copyright are in the comment below. 5 | # 6 | # MIT License 7 | # ===================== 8 | # 9 | # Copyright 2021 Kevin Ushey 10 | # 11 | # Permission is hereby granted, free of charge, to any person obtaining a copy 12 | # of this software and associated documentation files (the “Software”), to deal 13 | # in the Software without restriction, including without limitation the rights 14 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | # copies of the Software, and to permit persons to whom the Software is 16 | # furnished to do so, subject to the following conditions: 17 | # 18 | # The above copyright notice and this permission notice shall be included 19 | # in all copies or substantial portions of the Software. 20 | # 21 | # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | # THE SOFTWARE. 28 | echo "PKG_CFLAGS=-DCMDSTAN='\"${CMDSTAN}\"' -DCMDSTAN_INSTALL='\"${CMDSTAN_INSTALL}\"'" > src/Makevars 29 | touch src/cmdstan.c 30 | -------------------------------------------------------------------------------- /configure.win: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # 3 | # This script was copied and modified from the source code of the {configure} 4 | # R package by Kevin Ushey. License and copyright are in the comment below. 5 | # 6 | # MIT License 7 | # ===================== 8 | # 9 | # Copyright 2021 Kevin Ushey 10 | # 11 | # Permission is hereby granted, free of charge, to any person obtaining a copy 12 | # of this software and associated documentation files (the “Software”), to deal 13 | # in the Software without restriction, including without limitation the rights 14 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | # copies of the Software, and to permit persons to whom the Software is 16 | # furnished to do so, subject to the following conditions: 17 | # 18 | # The above copyright notice and this permission notice shall be included 19 | # in all copies or substantial portions of the Software. 20 | # 21 | # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | # THE SOFTWARE. 28 | echo "PKG_CFLAGS=-DCMDSTAN='\"${CMDSTAN}\"' -DCMDSTAN_INSTALL='\"${CMDSTAN_INSTALL}\"'" > src/Makevars.win 29 | touch src/cmdstan.c 30 | -------------------------------------------------------------------------------- /inst/WORDLIST: -------------------------------------------------------------------------------- 1 | CmdStan 2 | cmdstanr 3 | codecov 4 | pre 5 | README 6 | rstan 7 | rstantools 8 | stanapi 9 | stannis 10 | unsetting 11 | cmdstan 12 | https 13 | makefile 14 | mc 15 | stan 16 | stanc 17 | transpiler 18 | Hadley 19 | Wickham 20 | CmdStanR 21 | YAML 22 | hpp 23 | cran 24 | -------------------------------------------------------------------------------- /inst/configuration/cleanup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # 3 | # This script was copied and modified from the source code of the {configure} 4 | # R package by Kevin Ushey. License and copyright are in the comment below. 5 | # 6 | # MIT License 7 | # ===================== 8 | # 9 | # Copyright 2021 Kevin Ushey 10 | # 11 | # Permission is hereby granted, free of charge, to any person obtaining a copy 12 | # of this software and associated documentation files (the “Software”), to deal 13 | # in the Software without restriction, including without limitation the rights 14 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | # copies of the Software, and to permit persons to whom the Software is 16 | # furnished to do so, subject to the following conditions: 17 | # 18 | # The above copyright notice and this permission notice shall be included 19 | # in all copies or substantial portions of the Software. 20 | # 21 | # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | # THE SOFTWARE. 28 | if [ -d "bin" ]; then 29 | rm -rf bin 30 | fi 31 | -------------------------------------------------------------------------------- /inst/configuration/cleanup.win: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # 3 | # This script was copied and modified from the source code of the {configure} 4 | # R package by Kevin Ushey. License and copyright are in the comment below. 5 | # 6 | # MIT License 7 | # ===================== 8 | # 9 | # Copyright 2021 Kevin Ushey 10 | # 11 | # Permission is hereby granted, free of charge, to any person obtaining a copy 12 | # of this software and associated documentation files (the “Software”), to deal 13 | # in the Software without restriction, including without limitation the rights 14 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | # copies of the Software, and to permit persons to whom the Software is 16 | # furnished to do so, subject to the following conditions: 17 | # 18 | # The above copyright notice and this permission notice shall be included 19 | # in all copies or substantial portions of the Software. 20 | # 21 | # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | # THE SOFTWARE. 28 | if [ -d "bin" ]; then 29 | rm -rf bin 30 | fi 31 | 32 | -------------------------------------------------------------------------------- /inst/configuration/install.libs.R: -------------------------------------------------------------------------------- 1 | libs <- file.path(R_PACKAGE_DIR, "libs", R_ARCH) 2 | dir.create(libs, recursive = TRUE, showWarnings = FALSE) 3 | for (file in c("symbols.rds", Sys.glob(paste0("*", SHLIB_EXT)))) { 4 | if (file.exists(file)) { 5 | file.copy(file, file.path(libs, file)) 6 | } 7 | } 8 | inst_stan <- file.path("..", "inst", "stan") 9 | if (dir.exists(inst_stan)) { 10 | warning( 11 | "Stan models in inst/stan/ are deprecated in {instantiate} ", 12 | ">= 0.0.4.9001 (2024-01-03). Please put them in src/stan/ instead." 13 | ) 14 | if (file.exists("stan")) { 15 | warning("src/stan/ already exists. Not copying models from inst/stan/.") 16 | } else { 17 | message("Copying inst/stan/ to src/stan/.") 18 | fs::dir_copy(path = inst_stan, new_path = "stan") 19 | } 20 | } 21 | bin <- file.path(R_PACKAGE_DIR, "bin") 22 | if (!file.exists(bin)) { 23 | dir.create(bin, recursive = TRUE, showWarnings = FALSE) 24 | } 25 | bin_stan <- file.path(bin, "stan") 26 | fs::dir_copy(path = "stan", new_path = bin_stan) 27 | callr::r( 28 | func = function(bin_stan) { 29 | instantiate::stan_package_compile( 30 | models = instantiate::stan_package_model_files(path = bin_stan) 31 | ) 32 | }, 33 | args = list(bin_stan = bin_stan), 34 | show = TRUE, 35 | stderr = "2>&1" 36 | ) 37 | -------------------------------------------------------------------------------- /inst/example/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: example 2 | Type: Package 3 | Title: Example Package With Instantiate 4 | Version: 0.0.1 5 | Author: You 6 | Maintainer: The package maintainer 7 | Description: Demonstrate how to create an R package with pre-compiled Stan 8 | models. 9 | Depends: 10 | R (>= 4.0.0) 11 | Imports: 12 | instantiate 13 | Additional_repositories: 14 | https://mc-stan.org/r-packages/ 15 | SystemRequirements: CmdStan (https://mc-stan.org/users/interfaces/cmdstan) 16 | Encoding: UTF-8 17 | LazyData: true 18 | RoxygenNote: 7.2.3 19 | -------------------------------------------------------------------------------- /inst/example/NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(run_bernoulli_model) 4 | importFrom(instantiate,stan_package_model) 5 | -------------------------------------------------------------------------------- /inst/example/NOTICE: -------------------------------------------------------------------------------- 1 | This package includes components from other open-source software. The projects and licenses are listed below. 2 | 3 | * CmdStan (https://github.com/stan-dev/cmdstan) by Stan Developers and their Assignees. 4 | 5 | BSD 3-Clause License 6 | ===================== 7 | 8 | Copyright (c) 2014, Stan 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without modification, 12 | are permitted provided that the following conditions are met: 13 | 14 | * Redistributions of source code must retain the above copyright notice, this 15 | list of conditions and the following disclaimer. 16 | 17 | * Redistributions in binary form must reproduce the above copyright notice, this 18 | list of conditions and the following disclaimer in the documentation and/or 19 | other materials provided with the distribution. 20 | 21 | * Neither the name of the {organization} nor the names of its 22 | contributors may be used to endorse or promote products derived from 23 | this software without specific prior written permission. 24 | 25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 26 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 27 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 29 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 30 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 32 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | -------------------------------------------------------------------------------- /inst/example/R/model.R: -------------------------------------------------------------------------------- 1 | #' @title Fit the Bernoulli model. 2 | #' @export 3 | #' @family models 4 | #' @description Fit the Bernoulli Stan model and return posterior summaries. 5 | #' @return A data frame of posterior summaries. 6 | #' @param y Numeric vector of Bernoulli observations (zeroes and ones). 7 | #' @param ... Named arguments to the `sample()` method of CmdStan model 8 | #' objects: 9 | #' @examples 10 | #' if (instantiate::stan_cmdstan_exists()) { 11 | #' run_bernoulli_model(y = c(1, 0, 1, 0, 1, 0, 0, 0, 0, 0)) 12 | #' } 13 | run_bernoulli_model <- function(y, ...) { 14 | stopifnot(is.numeric(y) && all(y >= 0 & y <= 1)) 15 | model <- instantiate::stan_package_model( 16 | name = "bernoulli", 17 | package = "example" 18 | ) 19 | fit <- model$sample(data = list(N = length(y), y = y), ...) 20 | fit$summary() 21 | } 22 | -------------------------------------------------------------------------------- /inst/example/R/package.R: -------------------------------------------------------------------------------- 1 | #' example: Example Package With Instantiate 2 | #' @docType package 3 | #' @name example-package 4 | #' @description An example package using `instantiate`. 5 | #' @family help 6 | #' @importFrom instantiate stan_package_model 7 | NULL 8 | -------------------------------------------------------------------------------- /inst/example/example.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: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | -------------------------------------------------------------------------------- /inst/example/github/workflows/check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: [push, pull_request] 4 | 5 | name: check 6 | 7 | jobs: 8 | check: 9 | runs-on: ${{ matrix.config.os }} 10 | 11 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 12 | 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | config: 17 | - {os: ubuntu-latest, r: 'release'} 18 | 19 | env: 20 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 21 | NOT_CRAN: true 22 | R_KEEP_PKG_SOURCE: yes 23 | 24 | steps: 25 | - uses: actions/checkout@v3 26 | 27 | - uses: r-lib/actions/setup-pandoc@v2 28 | 29 | - uses: r-lib/actions/setup-r@v2 30 | with: 31 | r-version: ${{ matrix.config.r }} 32 | extra-repositories: 'https://mc-stan.org/r-packages/' 33 | http-user-agent: ${{ matrix.config.http-user-agent }} 34 | use-public-rspm: true 35 | 36 | - name: Install CmdStan 37 | shell: Rscript {0} 38 | run: | 39 | install.packages("cmdstanr", repos = c("https://mc-stan.org/r-packages/", getOption("repos"))) 40 | cmdstanr::check_cmdstan_toolchain(fix = TRUE) 41 | cmdstanr::install_cmdstan() 42 | 43 | - uses: r-lib/actions/setup-r-dependencies@v2 44 | with: 45 | extra-packages: any::rcmdcheck, local::. 46 | needs: check 47 | cache-version: 2 48 | 49 | - uses: r-lib/actions/check-r-package@v2 50 | with: 51 | upload-snapshots: true 52 | -------------------------------------------------------------------------------- /inst/example/gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .Rapp.history 3 | .RData 4 | .Rhistory 5 | .Rproj.user/ 6 | inst/stan/** 7 | !inst/stan/**/*.* 8 | inst/stan/**/*.exe 9 | inst/stan/**/*.EXE 10 | *.dll 11 | -------------------------------------------------------------------------------- /inst/example/man/example-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/package.R 3 | \docType{package} 4 | \name{example-package} 5 | \alias{example-package} 6 | \title{example: Example Package With Instantiate} 7 | \description{ 8 | An example package using `instantiate`. 9 | } 10 | \concept{help} 11 | -------------------------------------------------------------------------------- /inst/example/man/run_bernoulli_model.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/model.R 3 | \name{run_bernoulli_model} 4 | \alias{run_bernoulli_model} 5 | \title{Fit the Bernoulli model.} 6 | \usage{ 7 | run_bernoulli_model(y, ...) 8 | } 9 | \arguments{ 10 | \item{y}{Numeric vector of Bernoulli observations (zeroes and ones).} 11 | 12 | \item{...}{Named arguments to the `sample()` method of CmdStan model 13 | objects: } 14 | } 15 | \value{ 16 | A data frame of posterior summaries. 17 | } 18 | \description{ 19 | Fit the Bernoulli Stan model and return posterior summaries. 20 | } 21 | \examples{ 22 | if (instantiate::stan_cmdstan_exists()) { 23 | run_bernoulli_model(y = c(1, 0, 1, 0, 1, 0, 0, 0, 0, 0)) 24 | } 25 | } 26 | \concept{models} 27 | -------------------------------------------------------------------------------- /inst/example/rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.git$ 3 | ^\.github$ 4 | ^\.gitignore$ 5 | ^\.Rbuildignore$ 6 | ^\.RData$ 7 | ^\.Rhistory$ 8 | ^\.Rproj\.user$ 9 | ^NOTICE$ 10 | -------------------------------------------------------------------------------- /inst/example/src/stan/bernoulli.stan: -------------------------------------------------------------------------------- 1 | /* 2 | * This model was borrowed from the CmdStan projec with the BSD 3-Clause License. 3 | 4 | BSD 3-Clause License 5 | ===================== 6 | 7 | Copyright (c) 2019, Stan Developers and their Assignees 8 | All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | 16 | 2. Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | 3. Neither the name of the copyright holder nor the names of its 21 | contributors may be used to endorse or promote products derived from 22 | this software without specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 28 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | 36 | data { 37 | int N; 38 | array[N] int y; 39 | } 40 | parameters { 41 | real theta; 42 | } 43 | model { 44 | theta ~ beta(1,1); // uniform prior on interval 0,1 45 | y ~ bernoulli(theta); 46 | } 47 | -------------------------------------------------------------------------------- /instantiate.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: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | -------------------------------------------------------------------------------- /man/instantiate-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/stan_package.R 3 | \name{instantiate-package} 4 | \alias{instantiate-package} 5 | \title{instantiate: pre-compiled CmdStan models in R packages} 6 | \description{ 7 | Similar to \href{https://mc-stan.org/rstantools/}{\code{rstantools}} 8 | for \href{https://mc-stan.org/rstan/}{\code{rstan}}, 9 | the \code{instantiate} package builds pre-compiled 10 | \href{https://mc-stan.org/users/interfaces/cmdstan}{\code{CmdStan}} 11 | models into CRAN-ready statistical modeling R packages. 12 | The models compile once during installation, 13 | the executables live inside the file systems of their 14 | respective packages, and users have the full power 15 | and convenience of \href{https://mc-stan.org/cmdstanr/}{\code{CmdStanR}} 16 | without any additional compilation after package installation. 17 | This approach saves time and helps R package developers 18 | migrate from \href{https://mc-stan.org/rstan/}{\code{rstan}} 19 | to the more modern \href{https://mc-stan.org/cmdstanr/}{\code{CmdStanR}}. 20 | } 21 | \concept{help} 22 | -------------------------------------------------------------------------------- /man/stan_cmdstan_exists.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/stan_cmdstan_exists.R 3 | \name{stan_cmdstan_exists} 4 | \alias{stan_cmdstan_exists} 5 | \title{Check if \code{instantiate} can find CmdStanR and CmdStan.} 6 | \usage{ 7 | stan_cmdstan_exists( 8 | cmdstan_install = Sys.getenv("CMDSTAN_INSTALL", unset = "") 9 | ) 10 | } 11 | \arguments{ 12 | \item{cmdstan_install}{Character of length 1, how to look for an installed 13 | copy of CmdStan. See \url{https://wlandau.github.io/instantiate/} for details. 14 | Choices: 15 | \enumerate{ 16 | \item \code{""} (default): look at the original value that the \code{CMDSTAN_INSTALL} 17 | environment variable contained when \code{instantiate} at the time 18 | when it was installed. 19 | If it was \code{"implicit"} or \code{"fixed"}, then choose 20 | the corresponding option below. Otherwise, default to \code{"implicit"}. 21 | \item \code{"implicit"}: Let the \code{cmdstanr::cmdstan_path()} decide where 22 | to look for CmdStan. As explained in the \code{cmdstanr} documentation, 23 | the output of \code{cmdstanr::cmdstan_path()} depends 24 | on the current value of the \code{CMDSTAN} environment variable. 25 | The \code{cmdstanr} package must be installed. If it 26 | is not installed, then \code{stan_cmdstan_path()} 27 | returns the empty string \code{""}. 28 | \item \code{"fixed"}: Use the path to CmdStan that was originally 29 | contained in \code{Sys.getenv("CMDSTAN")} at the time when \code{instantiate} 30 | was installed. 31 | }} 32 | } 33 | \value{ 34 | \code{TRUE} if \code{instantiate} can find the CmdStanR R package and the 35 | CmdStan command line tool. Returns \code{FALSE} otherwise. 36 | } 37 | \description{ 38 | Check if \code{instantiate} can find CmdStanR and CmdStan. 39 | } 40 | \examples{ 41 | stan_cmdstan_exists() 42 | } 43 | \seealso{ 44 | Other cmdstan: 45 | \code{\link{stan_cmdstan_version}()} 46 | } 47 | \concept{cmdstan} 48 | -------------------------------------------------------------------------------- /man/stan_cmdstan_path.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/stan_cmdstan_path.R 3 | \name{stan_cmdstan_path} 4 | \alias{stan_cmdstan_path} 5 | \title{Path to CmdStan for \code{instantiate}} 6 | \usage{ 7 | stan_cmdstan_path(cmdstan_install = Sys.getenv("CMDSTAN_INSTALL", unset = "")) 8 | } 9 | \arguments{ 10 | \item{cmdstan_install}{Character of length 1, how to look for an installed 11 | copy of CmdStan. See \url{https://wlandau.github.io/instantiate/} for details. 12 | Choices: 13 | \enumerate{ 14 | \item \code{""} (default): look at the original value that the \code{CMDSTAN_INSTALL} 15 | environment variable contained when \code{instantiate} at the time 16 | when it was installed. 17 | If it was \code{"implicit"} or \code{"fixed"}, then choose 18 | the corresponding option below. Otherwise, default to \code{"implicit"}. 19 | \item \code{"implicit"}: Let the \code{cmdstanr::cmdstan_path()} decide where 20 | to look for CmdStan. As explained in the \code{cmdstanr} documentation, 21 | the output of \code{cmdstanr::cmdstan_path()} depends 22 | on the current value of the \code{CMDSTAN} environment variable. 23 | The \code{cmdstanr} package must be installed. If it 24 | is not installed, then \code{stan_cmdstan_path()} 25 | returns the empty string \code{""}. 26 | \item \code{"fixed"}: Use the path to CmdStan that was originally 27 | contained in \code{Sys.getenv("CMDSTAN")} at the time when \code{instantiate} 28 | was installed. 29 | }} 30 | } 31 | \value{ 32 | Character of length 1, directory path to CmdStan. The path 33 | may or may not exist. Returns the empty string \code{""} if the path 34 | cannot be determined. 35 | } 36 | \description{ 37 | Return the directory path to CmdStan that the \code{instantiate} 38 | package uses. 39 | } 40 | \examples{ 41 | stan_cmdstan_path() 42 | } 43 | \seealso{ 44 | Other packages: 45 | \code{\link{stan_package_clean}()}, 46 | \code{\link{stan_package_compile}()}, 47 | \code{\link{stan_package_configure}()}, 48 | \code{\link{stan_package_model_files}()} 49 | } 50 | \concept{packages} 51 | -------------------------------------------------------------------------------- /man/stan_cmdstan_version.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/stan_cmdstan_version.R 3 | \name{stan_cmdstan_version} 4 | \alias{stan_cmdstan_version} 5 | \title{Version of CmdStan that \code{instantiate} uses.} 6 | \usage{ 7 | stan_cmdstan_version( 8 | cmdstan_install = Sys.getenv("CMDSTAN_INSTALL", unset = ""), 9 | error_on_NA = TRUE 10 | ) 11 | } 12 | \arguments{ 13 | \item{cmdstan_install}{Character of length 1, how to look for an installed 14 | copy of CmdStan. See \url{https://wlandau.github.io/instantiate/} for details. 15 | Choices: 16 | \enumerate{ 17 | \item \code{""} (default): look at the original value that the \code{CMDSTAN_INSTALL} 18 | environment variable contained when \code{instantiate} at the time 19 | when it was installed. 20 | If it was \code{"implicit"} or \code{"fixed"}, then choose 21 | the corresponding option below. Otherwise, default to \code{"implicit"}. 22 | \item \code{"implicit"}: Let the \code{cmdstanr::cmdstan_path()} decide where 23 | to look for CmdStan. As explained in the \code{cmdstanr} documentation, 24 | the output of \code{cmdstanr::cmdstan_path()} depends 25 | on the current value of the \code{CMDSTAN} environment variable. 26 | The \code{cmdstanr} package must be installed. If it 27 | is not installed, then \code{stan_cmdstan_path()} 28 | returns the empty string \code{""}. 29 | \item \code{"fixed"}: Use the path to CmdStan that was originally 30 | contained in \code{Sys.getenv("CMDSTAN")} at the time when \code{instantiate} 31 | was installed. 32 | }} 33 | 34 | \item{error_on_NA}{Logical of length 1, whether an error should be thrown 35 | if CmdStan is not found.} 36 | } 37 | \value{ 38 | Character of length 1, version of CmdStan that the \code{instantiate} 39 | package uses. If CmdStan is not found, then the return value depends 40 | on the \code{error_on_NA} argument. 41 | } 42 | \description{ 43 | Return the version of CmdStan that the \code{instantiate} 44 | package uses. 45 | } 46 | \examples{ 47 | if (stan_cmdstan_exists()) { 48 | message(stan_cmdstan_version()) 49 | } 50 | } 51 | \seealso{ 52 | Other cmdstan: 53 | \code{\link{stan_cmdstan_exists}()} 54 | } 55 | \concept{cmdstan} 56 | -------------------------------------------------------------------------------- /man/stan_package_clean.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/stan_package_clean.R 3 | \name{stan_package_clean} 4 | \alias{stan_package_clean} 5 | \title{Remove one or more compiled Stan models in an R package.} 6 | \usage{ 7 | stan_package_clean(models = instantiate::stan_package_model_files()) 8 | } 9 | \arguments{ 10 | \item{models}{Character vector of file paths to Stan model source code 11 | files. Defaults to the Stan files in \verb{./src/stan/} 12 | because all the Stan model files must live in the \verb{src/stan/} folder 13 | for an R package built with \code{instantiate}.} 14 | } 15 | \value{ 16 | \code{NULL} (invisibly). Called for its side effects. 17 | } 18 | \description{ 19 | Remove one or more compiled Stan models from the file system 20 | of an R package. 21 | } 22 | \examples{ 23 | if (identical(Sys.getenv("INSTANTIATE_EXAMPLES"), "true")) { 24 | path <- tempfile() 25 | stan_package_create(path = path) 26 | stan_package_configure(path = path) 27 | models <- stan_package_model_files(path) 28 | list.files(file.path(path, "inst", "stan")) 29 | stan_package_compile(models) 30 | list.files(file.path(path, "inst", "stan")) 31 | # Clean up the compiled Stan model files: 32 | stan_package_clean(models = models) 33 | list.files(file.path(path, "inst", "stan")) 34 | } 35 | } 36 | \seealso{ 37 | Other packages: 38 | \code{\link{stan_cmdstan_path}()}, 39 | \code{\link{stan_package_compile}()}, 40 | \code{\link{stan_package_configure}()}, 41 | \code{\link{stan_package_model_files}()} 42 | } 43 | \concept{packages} 44 | -------------------------------------------------------------------------------- /man/stan_package_compile.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/stan_package_compile.R 3 | \name{stan_package_compile} 4 | \alias{stan_package_compile} 5 | \title{Compile the Stan models in an R package.} 6 | \usage{ 7 | stan_package_compile( 8 | models = instantiate::stan_package_model_files(), 9 | cmdstan_install = Sys.getenv("CMDSTAN_INSTALL", unset = ""), 10 | verbose = TRUE, 11 | quiet = FALSE, 12 | pedantic = FALSE, 13 | include_paths = NULL, 14 | user_header = NULL, 15 | cpp_options = list(), 16 | stanc_options = list(), 17 | force_recompile = getOption("cmdstanr_force_recompile", default = FALSE), 18 | threads = FALSE, 19 | ... 20 | ) 21 | } 22 | \arguments{ 23 | \item{models}{Character vector of file paths to Stan model source code 24 | files. Defaults to the Stan files in \verb{./src/stan/} 25 | because all the Stan model files must live in the \verb{src/stan/} folder 26 | for an R package built with \code{instantiate}.} 27 | 28 | \item{cmdstan_install}{Character of length 1, how to look for an installed 29 | copy of CmdStan. See \url{https://wlandau.github.io/instantiate/} for details. 30 | Choices: 31 | \enumerate{ 32 | \item \code{""} (default): look at the original value that the \code{CMDSTAN_INSTALL} 33 | environment variable contained when \code{instantiate} at the time 34 | when it was installed. 35 | If it was \code{"implicit"} or \code{"fixed"}, then choose 36 | the corresponding option below. Otherwise, default to \code{"implicit"}. 37 | \item \code{"implicit"}: Let the \code{cmdstanr::cmdstan_path()} decide where 38 | to look for CmdStan. As explained in the \code{cmdstanr} documentation, 39 | the output of \code{cmdstanr::cmdstan_path()} depends 40 | on the current value of the \code{CMDSTAN} environment variable. 41 | The \code{cmdstanr} package must be installed. If it 42 | is not installed, then \code{stan_cmdstan_path()} 43 | returns the empty string \code{""}. 44 | \item \code{"fixed"}: Use the path to CmdStan that was originally 45 | contained in \code{Sys.getenv("CMDSTAN")} at the time when \code{instantiate} 46 | was installed. 47 | }} 48 | 49 | \item{verbose}{Logical of length 1, whether to set the 50 | \code{cmdstanr_verbose} global option to print more compiler messages 51 | than usual.} 52 | 53 | \item{quiet}{Argument to \code{cmdstanr::cmdstan_model()} to control compilation.} 54 | 55 | \item{pedantic}{Logical of length 1, whether to activate pedantic 56 | mode when compiling the Stan models. See the \code{cmdstanr} documentation 57 | for details.} 58 | 59 | \item{include_paths}{Argument to \code{cmdstanr::cmdstan_model()} 60 | to control model compilation.} 61 | 62 | \item{user_header}{Argument to \code{cmdstanr::cmdstan_model()} 63 | to control model compilation.} 64 | 65 | \item{cpp_options}{Argument to \code{cmdstanr::cmdstan_model()} 66 | to control model compilation.} 67 | 68 | \item{stanc_options}{Argument to \code{cmdstanr::cmdstan_model()} 69 | to model control compilation.} 70 | 71 | \item{force_recompile}{Argument to \code{cmdstanr::cmdstan_model()} 72 | to model control compilation.} 73 | 74 | \item{threads}{Argument to \code{cmdstanr::cmdstan_model()} 75 | to model control compilation.} 76 | 77 | \item{...}{Other named arguments to \code{cmdstanr::cmdstan_model()}.} 78 | } 79 | \value{ 80 | \code{NULL} (invisibly). Called for its side effects. 81 | } 82 | \description{ 83 | Compile all Stan models in a directory, usually in a package. 84 | } 85 | \details{ 86 | If building a package using \code{instantiate}, all Stan model files 87 | must live in a folder called \verb{src/stan/} in the package source 88 | directory. 89 | } 90 | \examples{ 91 | if (identical(Sys.getenv("INSTANTIATE_EXAMPLES"), "true")) { 92 | path <- tempfile() 93 | stan_package_create(path = path) 94 | stan_package_configure(path = path) 95 | models <- stan_package_model_files(path) 96 | list.files(file.path(path, "inst", "stan")) 97 | stan_package_compile(models) 98 | list.files(file.path(path, "inst", "stan")) 99 | } 100 | } 101 | \seealso{ 102 | Other packages: 103 | \code{\link{stan_cmdstan_path}()}, 104 | \code{\link{stan_package_clean}()}, 105 | \code{\link{stan_package_configure}()}, 106 | \code{\link{stan_package_model_files}()} 107 | } 108 | \concept{packages} 109 | -------------------------------------------------------------------------------- /man/stan_package_configure.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/stan_package_configure.R 3 | \name{stan_package_configure} 4 | \alias{stan_package_configure} 5 | \title{Configure an R package with built-in Stan models.} 6 | \usage{ 7 | stan_package_configure(path = getwd(), overwrite = FALSE) 8 | } 9 | \arguments{ 10 | \item{path}{Character of length 1, file path to the package which will 11 | contain Stan models in \verb{src/stan/} at installation time.} 12 | 13 | \item{overwrite}{Logical of length 1, whether to overwrite any existing 14 | configuration files.} 15 | } 16 | \value{ 17 | \code{NULL} (invisibly). Called for its side effects. 18 | } 19 | \description{ 20 | Write configuration files in an R package which 21 | compile all the Stan models in \verb{src/stan/} when the package installs. 22 | } 23 | \details{ 24 | Writes configuration scripts \code{configure} and \code{configure.win} 25 | in the directory specified by the \code{path} argument. 26 | } 27 | \examples{ 28 | if (identical(Sys.getenv("INSTANTIATE_EXAMPLES"), "true")) { 29 | path <- tempfile() 30 | stan_package_create(path = path) 31 | list.files(path) 32 | stan_package_configure(path = path) 33 | list.files(path) 34 | } 35 | } 36 | \seealso{ 37 | Other packages: 38 | \code{\link{stan_cmdstan_path}()}, 39 | \code{\link{stan_package_clean}()}, 40 | \code{\link{stan_package_compile}()}, 41 | \code{\link{stan_package_model_files}()} 42 | } 43 | \concept{packages} 44 | -------------------------------------------------------------------------------- /man/stan_package_create.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/stan_package_create.R 3 | \name{stan_package_create} 4 | \alias{stan_package_create} 5 | \title{Create example package with a built-in Stan model.} 6 | \usage{ 7 | stan_package_create(path = tempfile()) 8 | } 9 | \arguments{ 10 | \item{path}{Path to write the package. Must not already exist.} 11 | } 12 | \value{ 13 | \code{NULL} (invisibly). Called for its side effects. 14 | } 15 | \description{ 16 | Create an example package with a Stan model inside. 17 | } 18 | \details{ 19 | After creating the package, the next step is to 20 | configure it with \code{\link[=stan_package_configure]{stan_package_configure()}}. After that, 21 | install it as an ordinary R package to automatically compile the models. 22 | } 23 | \examples{ 24 | if (identical(Sys.getenv("INSTANTIATE_EXAMPLES"), "true")) { 25 | path <- tempfile() 26 | stan_package_create(path = path) 27 | list.files(path) 28 | } 29 | } 30 | \keyword{packages} 31 | -------------------------------------------------------------------------------- /man/stan_package_model.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/stan_package_model.R 3 | \name{stan_package_model} 4 | \alias{stan_package_model} 5 | \title{Get a pre-compiled Stan model built into an R package.} 6 | \usage{ 7 | stan_package_model( 8 | name, 9 | package, 10 | library = NULL, 11 | cmdstan_install = Sys.getenv("CMDSTAN_INSTALL", unset = ""), 12 | compile = FALSE, 13 | ... 14 | ) 15 | } 16 | \arguments{ 17 | \item{name}{Character of length 1, base name of the Stan model file 18 | (without the containing directory or \code{.stan} file extension).} 19 | 20 | \item{package}{Character of length 1, name of the R package to look 21 | for the built-in Stan model.} 22 | 23 | \item{library}{Character of length 1 or \code{NULL}, library path 24 | to look for the package with the built-in Stan model. 25 | Passed to the \code{lib.loc} argument of \code{system.file()}.} 26 | 27 | \item{cmdstan_install}{Character of length 1, how to look for an installed 28 | copy of CmdStan. See \url{https://wlandau.github.io/instantiate/} for details. 29 | Choices: 30 | \enumerate{ 31 | \item \code{""} (default): look at the original value that the \code{CMDSTAN_INSTALL} 32 | environment variable contained when \code{instantiate} at the time 33 | when it was installed. 34 | If it was \code{"implicit"} or \code{"fixed"}, then choose 35 | the corresponding option below. Otherwise, default to \code{"implicit"}. 36 | \item \code{"implicit"}: Let the \code{cmdstanr::cmdstan_path()} decide where 37 | to look for CmdStan. As explained in the \code{cmdstanr} documentation, 38 | the output of \code{cmdstanr::cmdstan_path()} depends 39 | on the current value of the \code{CMDSTAN} environment variable. 40 | The \code{cmdstanr} package must be installed. If it 41 | is not installed, then \code{stan_cmdstan_path()} 42 | returns the empty string \code{""}. 43 | \item \code{"fixed"}: Use the path to CmdStan that was originally 44 | contained in \code{Sys.getenv("CMDSTAN")} at the time when \code{instantiate} 45 | was installed. 46 | }} 47 | 48 | \item{compile}{\code{TRUE} to compile the model and store the executable file 49 | where the package is installed in \code{.libpaths()}. \code{FALSE} to 50 | skip compilation and assume the model is already compiled, 51 | which is usually the case.} 52 | 53 | \item{...}{Named arguments passed via \code{cmdstanr::cmdstan_model()} 54 | to the \code{compile()} method of the CmdStan model object.} 55 | } 56 | \value{ 57 | An \code{R6} Stan model object from the \code{cmdstanr} package. 58 | Please visit the documentation website at \url{https://mc-stan.org/cmdstanr/} 59 | for detailed information on the composition of this model object 60 | and how to use it to conduct Bayesian inference. 61 | } 62 | \description{ 63 | Get the \code{cmdstanr} model object for a pre-compiled Stan 64 | model inside a package. 65 | } 66 | \details{ 67 | Packages configured with \code{instantiate} compile their Stan 68 | models on installation. Then the \code{stan_package_model()} function 69 | retrieves the \code{cmdstanr::cmdstan_model()} object without needing 70 | to re-compile the model. Please see the documentation website 71 | of the \code{instantiate} package for examples. 72 | } 73 | \examples{ 74 | # Please see the documentation website of the {instantiate} package 75 | # for examples. 76 | } 77 | \keyword{packages} 78 | -------------------------------------------------------------------------------- /man/stan_package_model_files.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/stan_package_model_files.R 3 | \name{stan_package_model_files} 4 | \alias{stan_package_model_files} 5 | \title{List Stan model file paths.} 6 | \usage{ 7 | stan_package_model_files(path = getwd()) 8 | } 9 | \arguments{ 10 | \item{path}{Character of length 1, root path to start from when searching 11 | for Stan model files.} 12 | } 13 | \value{ 14 | Character vector of paths to Stan model files in the package. 15 | } 16 | \description{ 17 | List all the paths to the Stan model files in a package. 18 | } 19 | \details{ 20 | All Stan models must live in the \verb{src/stan/} directory in the 21 | package file system. 22 | } 23 | \examples{ 24 | path <- tempfile() 25 | stan_package_create(path = path) 26 | stan_package_model_files(path) 27 | } 28 | \seealso{ 29 | Other packages: 30 | \code{\link{stan_cmdstan_path}()}, 31 | \code{\link{stan_package_clean}()}, 32 | \code{\link{stan_package_compile}()}, 33 | \code{\link{stan_package_configure}()} 34 | } 35 | \concept{packages} 36 | -------------------------------------------------------------------------------- /src/Makevars.win: -------------------------------------------------------------------------------- 1 | PKG_CFLAGS=-DCMDSTAN='""' -DCMDSTAN_INSTALL='"implicit"' 2 | -------------------------------------------------------------------------------- /src/cmdstan.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | SEXP cmdstan_path_fixed(void) { 7 | const char *path = CMDSTAN; 8 | SEXP out = PROTECT(mkString(path)); 9 | UNPROTECT(1); 10 | return out; 11 | } 12 | 13 | SEXP cmdstan_path_install(void) { 14 | const char *path = CMDSTAN_INSTALL; 15 | SEXP out = PROTECT(mkString(path)); 16 | UNPROTECT(1); 17 | return out; 18 | } 19 | 20 | static const R_CallMethodDef call_methods[] = { 21 | {"c_cmdstan_path_fixed", (DL_FUNC) &cmdstan_path_fixed, 0}, 22 | {"c_cmdstan_path_install", (DL_FUNC) &cmdstan_path_install, 0}, 23 | {NULL, NULL, 0} 24 | }; 25 | 26 | void R_init_instantiate(DllInfo *dll) { 27 | R_registerRoutines(dll, NULL, call_methods, NULL, NULL); 28 | R_useDynamicSymbols(dll, FALSE); 29 | R_forceSymbols(dll, TRUE); 30 | } 31 | -------------------------------------------------------------------------------- /src/install.libs.R: -------------------------------------------------------------------------------- 1 | libs <- file.path(R_PACKAGE_DIR, "libs", R_ARCH) 2 | dir.create(libs, recursive = TRUE, showWarnings = FALSE) 3 | for (file in c("symbols.rds", Sys.glob(paste0("*", SHLIB_EXT)))) { 4 | if (file.exists(file)) { 5 | file.copy(file, file.path(libs, file)) 6 | } 7 | } 8 | 9 | choice <- tolower(Sys.getenv("CMDSTAN_INSTALL", "")) 10 | if (identical(choice, "internal")) { 11 | warning( 12 | "'internal' installation in {instantiate} is no longer supported. ", 13 | "Falling back on 'implicit' installation." 14 | ) 15 | choice <- "implicit" 16 | } 17 | if (identical(choice, "fixed")) { 18 | message( 19 | sprintf( 20 | c( 21 | "Fixed installation: the CMDSTAN environment variable is set to ", 22 | "\"%s\". {instantiate} will prefer this copy of CmdStan ", 23 | "when the CMDSTAN_INSTALL environment variable is unset." 24 | ), 25 | Sys.getenv("CMDSTAN") 26 | ) 27 | ) 28 | } else { 29 | message( 30 | "Implicit installation: {instantiate} will use cmdstanr::cmdstan_path() ", 31 | "to find CmdStan when the CMDSTAN_INSTALL environment variable is unset." 32 | ) 33 | } 34 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | # This file is part of the standard setup for testthat. 2 | # It is recommended that you do not modify it. 3 | # 4 | # Where should you do additional test configuration? 5 | # Learn more about the roles of various files in: 6 | # * https://r-pkgs.org/testing-design.html#sec-tests-files-overview 7 | # * https://testthat.r-lib.org/articles/special-files.html 8 | 9 | library(testthat) 10 | library(instantiate) 11 | 12 | test_check("instantiate") 13 | -------------------------------------------------------------------------------- /tests/testthat/helper-utils.R: -------------------------------------------------------------------------------- 1 | stan_test <- function(label, code) { 2 | skip_if_not_installed("withr") 3 | expr <- substitute( 4 | testthat::test_that(label, code), 5 | env = list(label = label, code = substitute(code)) 6 | ) 7 | temp <- tempfile() 8 | dir.create(temp) 9 | on.exit(unlink(temp)) 10 | withr::with_dir( 11 | temp, 12 | suppressMessages(eval(expr, envir = parent.frame())) 13 | ) 14 | } 15 | 16 | skip_cmdstan <- function() { 17 | skip_on_cran() 18 | skip_if_not_installed("cmdstanr") 19 | if (!stan_cmdstan_exists()) { 20 | skip("CmdStan not found.") 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/testthat/test-stan_cmdstan_exists.R: -------------------------------------------------------------------------------- 1 | stan_test("stan_cmdstan_exists()", { 2 | expect_true(is.logical(stan_cmdstan_exists())) 3 | }) 4 | -------------------------------------------------------------------------------- /tests/testthat/test-stan_cmdstan_path.R: -------------------------------------------------------------------------------- 1 | stan_test("stan_cmdstan_path()", { 2 | skip_cmdstan() 3 | expect_true(is.character(stan_cmdstan_path())) 4 | }) 5 | -------------------------------------------------------------------------------- /tests/testthat/test-stan_cmdstan_version.R: -------------------------------------------------------------------------------- 1 | stan_test("stan_cmdstan_path()", { 2 | skip_cmdstan() 3 | expect_true(is.character(stan_cmdstan_version())) 4 | }) 5 | -------------------------------------------------------------------------------- /tests/testthat/test-stan_on_windows.R: -------------------------------------------------------------------------------- 1 | stan_test("stan_on_windows()", { 2 | expect_true(is.logical(stan_on_windows())) 3 | }) 4 | -------------------------------------------------------------------------------- /tests/testthat/test-stan_package_compile.R: -------------------------------------------------------------------------------- 1 | stan_test("stan_package_compile() and stan_package_clean()", { 2 | skip_cmdstan() 3 | cmdstan <- stan_cmdstan_path() 4 | dir <- file.path("inst", "stan") 5 | dir.create(dir, recursive = TRUE) 6 | expect_error(stan_package_compile(), class = "stan_error") 7 | bernoulli <- file.path(cmdstan, "examples", "bernoulli", "bernoulli.stan") 8 | if (!file.exists(bernoulli)) { 9 | skip("missing bernoulli.stan example model from CmdStan") 10 | } 11 | file.copy(from = bernoulli, to = file.path(dir, "bernoulli.stan")) 12 | stan_package_compile(quiet = TRUE, verbose = FALSE) 13 | exe <- file.path(dir, "bernoulli") 14 | if (stan_on_windows()) { 15 | exe <- paste0(exe, ".exe") 16 | } 17 | expect_true(file.exists(exe)) 18 | stan_package_clean() 19 | expect_false(file.exists(exe)) 20 | }) 21 | 22 | stan_test("stan_package_compile() on empty directory", { 23 | skip_cmdstan() 24 | expect_message(stan_package_compile(models = tempfile())) 25 | }) 26 | -------------------------------------------------------------------------------- /tests/testthat/test-stan_package_configure.R: -------------------------------------------------------------------------------- 1 | stan_test("stan_package_create()", { 2 | skip_cmdstan() 3 | temp <- tempfile() 4 | dir.create(temp) 5 | stan_package_configure(path = temp) 6 | cleanup <- file.path(temp, "cleanup") 7 | cleanup_win <- file.path(temp, "cleanup.win") 8 | makevars <- file.path(temp, "src", "Makevars") 9 | makevars_win <- file.path(temp, "src", "Makevars.win") 10 | expect_true(file.exists(cleanup)) 11 | expect_true(file.exists(cleanup_win)) 12 | expect_true(file.exists(makevars)) 13 | expect_true(file.exists(makevars_win)) 14 | lines_cleanup <- paste(readLines(cleanup), collapse = "\n") 15 | lines_cleanup_win <- paste(readLines(cleanup_win), collapse = "\n") 16 | expect_false(any(lines_cleanup == lines_cleanup_win)) 17 | }) 18 | -------------------------------------------------------------------------------- /tests/testthat/test-stan_package_create.R: -------------------------------------------------------------------------------- 1 | stan_test("stan_package_create()", { 2 | skip_cmdstan() 3 | path <- "package" 4 | stan_package_create(path = path) 5 | expect_true(file.exists(file.path(path, "DESCRIPTION"))) 6 | expect_true(file.exists(file.path(path, "src", "stan", "bernoulli.stan"))) 7 | expect_error(stan_package_create(path = path), class = "stan_error") 8 | }) 9 | -------------------------------------------------------------------------------- /tests/testthat/test-stan_package_model.R: -------------------------------------------------------------------------------- 1 | stan_test("stan_package_model()", { 2 | skip_cmdstan() 3 | path <- "example" 4 | stan_package_create(path = path) 5 | stan_package_configure(path = path) 6 | temporary_library <- "library" 7 | dir.create(temporary_library) 8 | tmp <- utils::capture.output( 9 | install.packages( 10 | pkgs = path, 11 | lib = temporary_library, 12 | type = "source", 13 | repos = NULL, 14 | quiet = TRUE 15 | ) 16 | ) 17 | model <- stan_package_model( 18 | name = "bernoulli", 19 | package = "example", 20 | library = temporary_library 21 | ) 22 | tmp <- utils::capture.output( 23 | fit <- model$sample( 24 | data = list(N = 10, y = c(1, 0, 1, 0, 1, 0, 0, 0, 0, 0)), 25 | refresh = 0, 26 | iter_warmup = 2000, 27 | iter_sampling = 4000 28 | ) 29 | ) 30 | expect_true(is.data.frame(fit$summary())) 31 | }) 32 | 33 | stan_test("stan_package_model() with deprecated inst", { 34 | skip_cmdstan() 35 | path <- "example" 36 | stan_package_create(path = path) 37 | file.rename(from = file.path(path, "src"), to = file.path(path, "inst")) 38 | stan_package_configure(path = path) 39 | temporary_library <- "library" 40 | dir.create(temporary_library) 41 | suppressWarnings( 42 | tmp <- utils::capture.output( 43 | install.packages( 44 | pkgs = path, 45 | lib = temporary_library, 46 | type = "source", 47 | repos = NULL, 48 | quiet = TRUE 49 | ) 50 | ) 51 | ) 52 | expect_warning( 53 | model <- stan_package_model( 54 | name = "bernoulli", 55 | package = "example", 56 | library = temporary_library 57 | ), 58 | class = "stan_deprecate" 59 | ) 60 | tmp <- utils::capture.output( 61 | fit <- model$sample( 62 | data = list(N = 10, y = c(1, 0, 1, 0, 1, 0, 0, 0, 0, 0)), 63 | refresh = 0, 64 | iter_warmup = 2000, 65 | iter_sampling = 4000 66 | ) 67 | ) 68 | expect_true(is.data.frame(fit$summary())) 69 | }) 70 | -------------------------------------------------------------------------------- /tests/testthat/test-utils_assert.R: -------------------------------------------------------------------------------- 1 | stan_test("stan_assert()", { 2 | expect_silent(stan_assert(TRUE)) 3 | expect_error(stan_assert(FALSE), class = "stan_error") 4 | expect_silent(stan_assert(c(2, 3), . > 1, . > 0)) 5 | expect_error(stan_assert(2, . < 1), class = "stan_error") 6 | }) 7 | 8 | stan_test("stan_error()", { 9 | expect_error(stan_error("x"), class = "stan_error") 10 | }) 11 | 12 | stan_test("stan_warning()", { 13 | expect_warning(stan_warning("x"), class = "stan_warning") 14 | }) 15 | 16 | stan_test("stan_message()", { 17 | expect_message(stan_message("x"), class = "stan_message") 18 | }) 19 | 20 | stan_test("stan_deprecate()", { 21 | expect_warning( 22 | stan_deprecate( 23 | name = "auto_scale", 24 | date = "2023-05-18", 25 | version = "0.2.0", 26 | alternative = "use the scale argument of push(), pop(), and wait()" 27 | ), 28 | class = "stan_deprecate" 29 | ) 30 | }) 31 | 32 | stan_test("stan_cmdstan_message()", { 33 | expect_message(stan_cmdstan_message()) 34 | }) 35 | 36 | stan_test("stan_cmdstanr_text()", { 37 | expect_true(is.character(stan_cmdstanr_text())) 38 | }) 39 | -------------------------------------------------------------------------------- /tests/testthat/test-utils_logic.R: -------------------------------------------------------------------------------- 1 | stan_test("%||%", { 2 | expect_equal("a" %||% "b", "a") 3 | expect_equal(list() %||% "b", "b") 4 | expect_equal(NULL %||% "b", "b") 5 | }) 6 | 7 | stan_test("%|||%", { 8 | expect_equal("a" %|||% "b", "a") 9 | expect_equal(list() %|||% "b", list()) 10 | expect_equal(NULL %|||% "b", "b") 11 | }) 12 | 13 | stan_test("if_any()", { 14 | expect_equal(if_any(TRUE, "a", "b"), "a") 15 | expect_equal(if_any(FALSE, "a", "b"), "b") 16 | }) 17 | --------------------------------------------------------------------------------