rstantools/0000755000176200001440000000000013537300535012466 5ustar liggesusersrstantools/NAMESPACE0000644000176200001440000000125213537012702013701 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method(bayes_R2,default) S3method(loo_pit,default) S3method(posterior_interval,default) S3method(predictive_error,default) S3method(predictive_interval,default) S3method(prior_summary,default) export(bayes_R2) export(init_cpp) export(log_lik) export(loo_R2) export(loo_linpred) export(loo_pit) export(loo_predict) export(loo_predictive_interval) export(nsamples) export(posterior_interval) export(posterior_linpred) export(posterior_predict) export(predictive_error) export(predictive_interval) export(prior_summary) export(rstan_config) export(rstan_create_package) export(use_rstan) importFrom(stats,quantile) importFrom(stats,var) rstantools/man/0000755000176200001440000000000013537013650013240 5ustar liggesusersrstantools/man/bayes_R2.Rd0000644000176200001440000000425013536774354015214 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/bayes_R2.R \name{bayes_R2} \alias{bayes_R2} \alias{bayes_R2.default} \alias{loo_R2} \title{Generic function and default method for Bayesian R-squared} \usage{ bayes_R2(object, ...) \method{bayes_R2}{default}(object, y, ...) loo_R2(object, ...) } \arguments{ \item{object}{The object to use.} \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} package for examples.} \item{y}{For the default method, a vector of \code{y} values the same length as the number of columns in the matrix used as \code{object}.} } \value{ \code{bayes_R2()} and \code{loo_R2()} methods should return a vector of length equal to the posterior sample size. The default \code{bayes_R2()} method just takes \code{object} to be a matrix of y-hat values (one column per observation, one row per posterior draw) and \code{y} to be a vector with length equal to \code{ncol(object)}. } \description{ Generic function and default method for Bayesian version of R-squared for regression models. A generic for LOO-adjusted R-squared is also provided. See the \href{https://mc-stan.org/rstanarm/reference/bayes_R2.stanreg.html}{bayes_R2.stanreg()} method in the \pkg{rstanarm} package for an example of defining a method. } \references{ Andrew Gelman, Ben Goodrich, Jonah Gabry, and Aki Vehtari (2018). R-squared for Bayesian regression models. \emph{The American Statistician}, to appear. DOI: 10.1080/00031305.2018.1549100. (\href{http://www.stat.columbia.edu/~gelman/research/published/bayes_R2_v3.pdf}{Preprint}, \href{https://avehtari.github.io/bayes_R2/bayes_R2.html}{Notebook}) } \seealso{ \itemize{ \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) for example methods (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, \href{https://github.com/stan-dev/rstanarm}{GitHub}). } \itemize{ \item Guidelines and recommendations for developers of \R packages interfacing with Stan and a demonstration getting a simple package working can be found in the vignettes included with \pkg{rstantools} and at \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. } } rstantools/man/rstan_config.Rd0000644000176200001440000000200013476233505016200 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/rstan_config.R \name{rstan_config} \alias{rstan_config} \title{Configure system files for compiling Stan source code} \usage{ rstan_config(pkgdir = ".") } \arguments{ \item{pkgdir}{Path to package root folder.} } \value{ Invisibly, whether or not any files were added/removed/modified by the function. } \description{ Creates or update package-specific system files to compile \code{.stan} model files found in \code{inst/stan}. } \details{ The Stan source files for the package should be stored in: \itemize{ \item \code{inst/stan} for \code{.stan} files containing instructions to build a \code{stanmodel} object. \item \code{inst/stan/any_subfolder} for files to be included via the \code{#include "/my_subfolder/mylib.stan"} directive. \item \code{inst/stan/any_subfolder} for a \code{license.stan} file. \item \code{inst/include} for the \code{stan_meta_header.hpp} file, to be used for directly interacting with the Stan C++ libraries. } } rstantools/man/rstantools-package.Rd0000644000176200001440000000321613476240224017333 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/rstantools-package.R \docType{package} \name{rstantools-package} \alias{rstantools-package} \alias{rstantools} \title{Tools for Developing \R Packages Interfacing with Stan} \description{ \if{html}{ \figure{stanlogo.png}{options: width="50px" alt="mc-stan.org"} } \emph{Stan Development Team} The \pkg{rstantools} package provides various tools for developers of \R packages interfacing with Stan (\url{https://mc-stan.org}), including functions to set up the required package structure, S3 generic methods to unify function naming across Stan-based \R packages, and vignettes with guidelines for developers. To get started building a package see \code{\link[=rstan_create_package]{rstan_create_package()}}. } \seealso{ \itemize{ \item Guidelines and recommendations for developers of \R packages interfacing with Stan and a demonstration getting a simple package working can be found in the vignettes included with \pkg{rstantools} and at \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. } \itemize{ \item After reading the guidelines for developers, if you have trouble setting up your package let us know on the the \href{https://discourse.mc-stan.org}{Stan Forums} or at the \pkg{rstantools} GitHub \href{https://github.com/stan-dev/rstantools/issues}{issue tracker}. } \itemize{ \item The useR2016 presentation \href{https://channel9.msdn.com/Events/useR-international-R-User-conferences/useR-International-R-User-2017-Conference/How-to-Use-RStan-to-Estimate-Models-in-External-R-Packages}{How to Use (R)Stan to Estimate Models in External R Packages.} } } rstantools/man/loo-prediction.Rd0000644000176200001440000000362013536774354016475 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/loo-functions.R \name{loo-prediction} \alias{loo-prediction} \alias{loo_linpred} \alias{loo_predict} \alias{loo_predictive_interval} \alias{loo_pit} \alias{loo_pit.default} \title{Generic functions for LOO predictions} \usage{ loo_linpred(object, ...) loo_predict(object, ...) loo_predictive_interval(object, ...) loo_pit(object, ...) \method{loo_pit}{default}(object, y, lw, ...) } \arguments{ \item{object}{The object to use.} \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} package for examples.} \item{y}{For the default method of \code{loo_pit()}, a vector of \code{y} values the same length as the number of columns in the matrix used as \code{object}.} \item{lw}{For the default method of \code{loo_pit()}, a matrix of log-weights of the same length as the number of columns in the matrix used as \code{object}.} } \value{ \code{loo_predict()}, \code{loo_linpred()}, and \code{loo_pit()} (probability integral transform) methods should return a vector with length equal to the number of observations in the data. \code{loo_predictive_interval()} methods should return a two-column matrix formatted in the same way as for \code{\link[=predictive_interval]{predictive_interval()}}. } \description{ See the methods in the \pkg{rstanarm} package for examples. } \seealso{ \itemize{ \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) for example methods (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, \href{https://github.com/stan-dev/rstanarm}{GitHub}). } \itemize{ \item Guidelines and recommendations for developers of \R packages interfacing with Stan and a demonstration getting a simple package working can be found in the vignettes included with \pkg{rstantools} and at \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. } } rstantools/man/prior_summary.Rd0000644000176200001440000000306413536774354016460 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/prior_summary.R \name{prior_summary} \alias{prior_summary} \alias{prior_summary.default} \title{Generic function for extracting information about prior distributions} \usage{ prior_summary(object, ...) \method{prior_summary}{default}(object, ...) } \arguments{ \item{object}{The object to use.} \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} package for examples.} } \value{ \code{prior_summary()} methods should return an object containing information about the prior distribution(s) used for the given model. The structure of this object will depend on the method. The default method just returns \code{object$prior.info}, which is \code{NULL} if there is no \code{'prior.info'} element. } \description{ See \href{https://mc-stan.org/rstanarm/reference/prior_summary.stanreg.html}{prior_summary.stanreg()} in the \pkg{rstanarm} package for an example. } \examples{ # See help("prior_summary", package = "rstanarm") } \seealso{ \itemize{ \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) for example methods (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, \href{https://github.com/stan-dev/rstanarm}{GitHub}). } \itemize{ \item Guidelines and recommendations for developers of \R packages interfacing with Stan and a demonstration getting a simple package working can be found in the vignettes included with \pkg{rstantools} and at \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. } } rstantools/man/use_rstan.Rd0000644000176200001440000000616113476240040015533 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/use_rstan.R \name{use_rstan} \alias{use_rstan} \title{Add Stan infrastructure to an existing package} \usage{ use_rstan(pkgdir = ".", license = TRUE, auto_config = TRUE) } \arguments{ \item{pkgdir}{Path to package root folder.} \item{license}{Logical or character; whether or not to paste the contents of a \code{license.stan} file at the top of all Stan code, or path to such a file. If \code{TRUE} (the default) adds the \code{GPL (>= 3)} license (see \strong{Details}).} \item{auto_config}{Whether to automatically configure Stan functionality whenever the package gets installed (see \strong{Details}). Defaults to \code{TRUE}.} } \value{ Invisibly, \code{TRUE} or \code{FALSE} indicating whether or not any files or folders where created or modified. } \description{ Add Stan infrastructure to an existing \R package. To create a \emph{new} package containing Stan programs use \code{\link[=rstan_create_package]{rstan_create_package()}} instead. } \details{ Prepares a package to compile and use Stan code by performing the following steps: \enumerate{ \item Create \code{inst/stan} folder where all \code{.stan} files defining Stan models should be stored. \item Create \code{inst/stan/include} where optional \code{license.stan} file is stored. \item Create \code{inst/include/stan_meta_header.hpp} to include optional header files used by Stan code. \item Create \code{src} folder (if it doesn't exist) to contain the Stan C++ code. \item Create \code{R} folder (if it doesn't exist) to contain wrapper code to expose Stan C++ classes to \R. \item Update \code{DESCRIPTION} file to contain all needed dependencies to compile Stan C++ code. \item If \code{NAMESPACE} file is generic (i.e., created by \code{\link[=rstan_create_package]{rstan_create_package()}}), append \code{import(Rcpp, methods)}, \code{importFrom(rstan, sampling)}, and \code{useDynLib} directives. If \code{NAMESPACE} is not generic, display message telling user what to add to \code{NAMESPACE} for themselves. } When \code{auto_config = TRUE}, a \code{configure[.win]} file is added to the package, calling \code{\link[=rstan_config]{rstan_config()}} whenever the package is installed. Consequently, the package must list \pkg{rstantools} in the \code{DESCRIPTION} Imports field for this mechanism to work. Setting \code{auto_config = FALSE} removes the package's dependency on \pkg{rstantools}, but the package then must be manually configured by running \code{\link[=rstan_config]{rstan_config()}} whenever \code{stanmodel} files in \code{inst/stan} are added, removed, or modified. } \section{Using the pre-compiled Stan programs in your package}{ The \code{stanmodel} objects corresponding to the Stan programs included with your package are stored in a list called \code{stanmodels}. To run one of the Stan programs from within an R function in your package just pass the appropriate element of the \code{stanmodels} list to one of the \pkg{rstan} functions for model fitting (e.g., \code{sampling()}). For example, for a Stan program \code{"foo.stan"} you would use \code{rstan::sampling(stanmodels$foo, ...)}. } rstantools/man/predictive_error.Rd0000644000176200001440000000407213536774354017117 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/predictive_error.R \name{predictive_error} \alias{predictive_error} \alias{predictive_error.default} \title{Generic function and default method for predictive errors} \usage{ predictive_error(object, ...) \method{predictive_error}{default}(object, y, ...) } \arguments{ \item{object}{The object to use.} \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} package for examples.} \item{y}{For the default method, a vector of \code{y} values the same length as the number of columns in the matrix used as \code{object}.} } \value{ \code{predictive_error()} methods should return a \eqn{D} by \eqn{N} matrix, where \eqn{D} is the number of draws from the posterior predictive distribution and \eqn{N} is the number of data points being predicted per draw. The default method just takes \code{object} to be a matrix and \code{y} to be a vector. } \description{ Generic function and default method for computing predictive errors \eqn{y - y^{rep}}{y - yrep} (in-sample, for observed \eqn{y}) or \eqn{y - \tilde{y}}{y - ytilde} (out-of-sample, for new or held-out \eqn{y}). See \href{https://mc-stan.org/rstanarm/reference/predictive_error.stanreg.html}{predictive_error.stanreg()} in the \pkg{rstanarm} package for an example. } \examples{ # default method y <- rnorm(10) ypred <- matrix(rnorm(500), 50, 10) pred_errors <- predictive_error(ypred, y) dim(pred_errors) head(pred_errors) # Also see help("predictive_error", package = "rstanarm") } \seealso{ \itemize{ \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) for example methods (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, \href{https://github.com/stan-dev/rstanarm}{GitHub}). } \itemize{ \item Guidelines and recommendations for developers of \R packages interfacing with Stan and a demonstration getting a simple package working can be found in the vignettes included with \pkg{rstantools} and at \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. } } rstantools/man/posterior_interval.Rd0000644000176200001440000000470713536774354017507 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/posterior_interval.R \name{posterior_interval} \alias{posterior_interval} \alias{posterior_interval.default} \title{Generic function and default method for posterior uncertainty intervals} \usage{ posterior_interval(object, ...) \method{posterior_interval}{default}(object, prob = 0.9, ...) } \arguments{ \item{object}{The object to use.} \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} package for examples.} \item{prob}{A number \eqn{p \in (0,1)}{p (0 < p < 1)} indicating the desired probability mass to include in the intervals.} } \value{ \code{posterior_interval()} methods should return a matrix with two columns and as many rows as model parameters (or a subset of parameters specified by the user). For a given value of \code{prob}, \eqn{p}, the columns correspond to the lower and upper \eqn{100p}\% interval limits and have the names \eqn{100\alpha/2}\% and \eqn{100(1 - \alpha/2)}\%, where \eqn{\alpha = 1-p}. For example, if \code{prob=0.9} is specified (a \eqn{90}\% interval), then the column names would be \code{"5\%"} and \code{"95\%"}, respectively. The default method just takes \code{object} to be a matrix (one column per parameter) and computes quantiles, with \code{prob} defaulting to \code{0.9}. } \description{ These intervals are often referred to as credible intervals, but we use the term uncertainty intervals to highlight the fact that wider intervals correspond to greater uncertainty. See \href{https://mc-stan.org/rstanarm/reference/posterior_interval.stanreg.html}{posterior_interval.stanreg()} in the \pkg{rstanarm} package for an example. } \examples{ # Default method takes a numeric matrix (of posterior draws) draws <- matrix(rnorm(100 * 5), 100, 5) # fake draws colnames(draws) <- paste0("theta_", 1:5) posterior_interval(draws) # Also see help("posterior_interval", package = "rstanarm") } \seealso{ \itemize{ \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) for example methods (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, \href{https://github.com/stan-dev/rstanarm}{GitHub}). } \itemize{ \item Guidelines and recommendations for developers of \R packages interfacing with Stan and a demonstration getting a simple package working can be found in the vignettes included with \pkg{rstantools} and at \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. } } rstantools/man/posterior_linpred.Rd0000644000176200001440000000332313536774354017311 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/posterior_linpred.R \name{posterior_linpred} \alias{posterior_linpred} \title{Generic function for accessing the posterior distribution of the linear predictor} \usage{ posterior_linpred(object, transform = FALSE, ...) } \arguments{ \item{object}{The object to use.} \item{transform}{Should the linear predictor be transformed using the inverse-link function? The default is \code{FALSE}, in which case the untransformed linear predictor is returned.} \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} package for examples.} } \value{ \code{posterior_linpred()} methods should return a \eqn{D} by \eqn{N} matrix, where \eqn{D} is the number of draws from the posterior distribution distribution and \eqn{N} is the number of data points. } \description{ Extract the posterior draws of the linear predictor, possibly transformed by the inverse-link function. See \href{https://mc-stan.org/rstanarm/reference/posterior_linpred.stanreg.html}{posterior_linpred.stanreg()} in the \pkg{rstanarm} package for an example. } \examples{ # See help("posterior_linpred", package = "rstanarm") } \seealso{ \itemize{ \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) for example methods (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, \href{https://github.com/stan-dev/rstanarm}{GitHub}). } \itemize{ \item Guidelines and recommendations for developers of \R packages interfacing with Stan and a demonstration getting a simple package working can be found in the vignettes included with \pkg{rstantools} and at \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. } } rstantools/man/nsamples.Rd0000644000176200001440000000072313335364621015356 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/nsamples.R \name{nsamples} \alias{nsamples} \title{Generic function for extracting the number of posterior samples} \usage{ nsamples(object, ...) } \arguments{ \item{object}{The object to use.} \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} package for examples.} } \description{ Extract the number of posterior samples stored in a fitted Bayesian model. } rstantools/man/rstan_create_package.Rd0000644000176200001440000001673213476240453017672 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/rstan_create_package.R \name{rstan_create_package} \alias{rstan_create_package} \alias{rstan_package_skeleton} \title{Create a new \R package with compiled Stan programs} \usage{ rstan_create_package(path, fields = NULL, rstudio = TRUE, open = TRUE, stan_files = character(), roxygen = TRUE, travis = TRUE, license = TRUE, auto_config = TRUE) } \arguments{ \item{path}{The path to the new package to be created (terminating in the package name).} \item{fields, rstudio, open}{Same as \code{\link[usethis:create_package]{usethis::create_package()}}. See the documentation for that function, especially the note in the \strong{Description} section about the side effect of changing the active project.} \item{stan_files}{A character vector with paths to \code{.stan} files to include in the package.} \item{roxygen}{Should \pkg{roxygen2} be used for documentation? Defaults to \code{TRUE}. If so, a file `R/{pkgname}-package.R`` is added to the package with roxygen tags for the required import lines. See the \strong{Note} section below for advice specific to the latest versions of \pkg{roxygen2}.} \item{travis}{Should a \code{.travis.yml} file be added to the package directory? Defaults to \code{TRUE}. While the file contains some presets to help with compilation issues, at present it is not guaranteed to work on \href{https://travis-ci.org/}{travis-ci} without manual adjustments.} \item{license}{Logical or character; whether or not to paste the contents of a \code{license.stan} file at the top of all Stan code, or path to such a file. If \code{TRUE} (the default) adds the \code{GPL (>= 3)} license (see \strong{Details}).} \item{auto_config}{Whether to automatically configure Stan functionality whenever the package gets installed (see \strong{Details}). Defaults to \code{TRUE}.} } \description{ \if{html}{\figure{stanlogo.png}{options: width="25px" alt="https://mc-stan.org/about/logo/"}} The \code{rstan_create_package()} function helps get you started developing a new \R package that interfaces with Stan via the \pkg{rstan} package. First the basic package structure is set up via \code{\link[usethis:create_package]{usethis::create_package()}}. Then several adjustments are made so the package can include Stan programs that can be built into binary versions (i.e., pre-compiled Stan C++ code). The \strong{Details} section below describes the process and the \strong{See Also} section provides links to recommendations for developers and a step-by-step walk-through. As of version \code{2.0.0} of \pkg{rstantools} the \code{rstan_package_skeleton()} function is defunct and only \code{rstan_create_package()} is supported. } \details{ This function first creates a regular \R package using \code{usethis::create_package()}, then adds the infrastructure required to compile and export \code{stanmodel} objects. In the package root directory, the user's Stan source code is located in: \preformatted{ inst/ |_stan/ | |_include/ | |_include/ } All \code{.stan} files containing instructions to build a \code{stanmodel} object must be placed in \code{inst/stan}. Other \code{.stan} files go in any \code{stan/} subdirectory, to be invoked by Stan's \code{#include} mechanism, e.g., \preformatted{ #include "include/mylib.stan" #include "data/preprocess.stan" } See \pkg{rstanarm} for many examples. The folder \code{inst/include} is for all user C++ files associated with the Stan programs. In this folder, the only file to directly interact with the Stan C++ library is \code{stan_meta_header.hpp}; all other \code{#include} directives must be channeled through here. The final step of the package creation is to invoke \code{\link[=rstan_config]{rstan_config()}}, which creates the following files for interfacing with Stan objects from \R: \itemize{ \item \code{src} contains the \code{stan_ModelName{.cc/.hpp}} pairs associated with all \code{ModelName.stan} files in \code{inst/stan} which define \code{stanmodel} objects. \item \code{src/Makevars[.win]} which link to the \code{StanHeaders} and Boost (\code{BH}) libraries. \item \code{R/stanmodels.R} loads the C++ modules containing the \code{stanmodel} class definitions, and assigns an \R instance of each \code{stanmodel} object to a \code{stanmodels} list (with names corresponding to the names of the Stan files). } When \code{auto_config = TRUE}, a \code{configure[.win]} file is added to the package, calling \code{\link[=rstan_config]{rstan_config()}} whenever the package is installed. Consequently, the package must list \pkg{rstantools} in the \code{DESCRIPTION} Imports field for this mechanism to work. Setting \code{auto_config = FALSE} removes the package's dependency on \pkg{rstantools}, but the package then must be manually configured by running \code{\link[=rstan_config]{rstan_config()}} whenever \code{stanmodel} files in \code{inst/stan} are added, removed, or modified. In order to enable Stan functionality, \pkg{\link{rstantools}} copies some files to your package. Since these files are licensed as GPL = 3, the same license applies to your package should you choose to distribute it. Even if you don't use \pkg{\link{rstantools}} to create your package, it is likely that you will be linking to \pkg{\link{Rcpp}} to export the Stan C++ \code{stanmodel} objects to \R. Since \pkg{\link{Rcpp}} is released under GPL >= 2, the same license would apply to your package upon distribution. Authors willing to license their Stan programs of general interest under the GPL are invited to contribute their \code{.stan} files and supporting \R code to the \pkg{rstanarm} package. } \note{ For \pkg{devtools} users, because of changes in the latest versions of \pkg{roxygen2} it may be necessary to run \code{pkgbuild::compile_dll()} once before \code{devtools::document()} will work. } \section{Using the pre-compiled Stan programs in your package}{ The \code{stanmodel} objects corresponding to the Stan programs included with your package are stored in a list called \code{stanmodels}. To run one of the Stan programs from within an R function in your package just pass the appropriate element of the \code{stanmodels} list to one of the \pkg{rstan} functions for model fitting (e.g., \code{sampling()}). For example, for a Stan program \code{"foo.stan"} you would use \code{rstan::sampling(stanmodels$foo, ...)}. } \seealso{ \itemize{ \item \code{\link[=use_rstan]{use_rstan()}} for adding Stan functionality to an existing \R package and \code{\link[=rstan_config]{rstan_config()}} for updating an existing package when its Stan files are changed. \item The \pkg{rstanarm} package \href{https://github.com/stan-dev/rstanarm}{repository} on GitHub. } \itemize{ \item Guidelines and recommendations for developers of \R packages interfacing with Stan and a demonstration getting a simple package working can be found in the vignettes included with \pkg{rstantools} and at \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. } \itemize{ \item After reading the guidelines for developers, if you have trouble setting up your package let us know on the the \href{https://discourse.mc-stan.org}{Stan Forums} or at the \pkg{rstantools} GitHub \href{https://github.com/stan-dev/rstantools/issues}{issue tracker}. } \itemize{ \item The useR2016 presentation \href{https://channel9.msdn.com/Events/useR-international-R-User-conferences/useR-International-R-User-2017-Conference/How-to-Use-RStan-to-Estimate-Models-in-External-R-Packages}{How to Use (R)Stan to Estimate Models in External R Packages.} } } rstantools/man/init_cpp.Rd0000644000176200001440000000167113476236523015351 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/init_cpp.R \name{init_cpp} \alias{init_cpp} \title{Register functions implemented in C++} \usage{ init_cpp(name, path) } \arguments{ \item{name}{The name of your package as a string.} \item{path}{The path to the root directory for your package as a string. If not specified it is assumed that this is already the current working directory.} } \value{ This function is only called for its side effect of writing the necessary \code{init.cpp} file to the package's \code{src/} directory. } \description{ If you set up your package using \code{rstan_package_skeleton()} before version \code{1.2.1} of \pkg{rstantools} it may be necessary for you to call this function yourself in order to pass \code{R CMD check} in \R \code{>= 3.4}. If you used \code{rstan_package_skeleton()} in \pkg{rstantools} version \code{1.2.1} or later then this has already been done automatically. } rstantools/man/log_lik.Rd0000644000176200001440000000320513536774354015165 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/log_lik.R \name{log_lik} \alias{log_lik} \title{Generic function for pointwise log-likelihood} \usage{ log_lik(object, ...) } \arguments{ \item{object}{The object to use.} \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} package for examples.} } \value{ \code{log_lik()} methods should return a \eqn{S} by \eqn{N} matrix, where \eqn{S} is the size of the posterior sample (the number of draws from the posterior distribution) and \eqn{N} is the number of data points. } \description{ We define a new function \code{log_lik()} rather than a \code{\link[stats:logLik]{stats::logLik()}} method because (in addition to the conceptual difference) the documentation for \code{logLik()} states that the return value will be a single number, whereas \code{log_lik()} returns a matrix. See the \href{https://mc-stan.org/rstanarm/reference/log_lik.stanreg.html}{log_lik.stanreg()} method in the \pkg{rstanarm} package for an example of defining a method. } \examples{ # See help("log_lik", package = "rstanarm") } \seealso{ \itemize{ \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) for example methods (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, \href{https://github.com/stan-dev/rstanarm}{GitHub}). } \itemize{ \item Guidelines and recommendations for developers of \R packages interfacing with Stan and a demonstration getting a simple package working can be found in the vignettes included with \pkg{rstantools} and at \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. } } rstantools/man/figures/0000755000176200001440000000000013263162464014710 5ustar liggesusersrstantools/man/figures/stanlogo.png0000644000176200001440000003745413263162464017261 0ustar liggesusersPNG  IHDRwx+sBIT|d pHYs&:4tEXtSoftwarewww.inkscape.org< IDATxw|ՙsf$w+$` ؘbQCB ے'7B6R6uq6e7M ل$ ؒm Л$W43+WY{nyޯ/lIw >̙31 B2J #7¡# #a@H P U] ]tuW~V-nUt+ˊ@l sy#/f TILxC&f~I&`= PX]&b.{gʘɋE 邞0t hrh=OuO\Κ;gnnՓ zt2L¾xYIqAsb?l_3bw끳1s+WAŮmZ􇕻OA_LӀsxH`9pO_Can5 j.͠gڪ' UX;i\}2Ə A|g2xEnE٬Z;),V%sNLbALpCfX3j8w5O+~WϪg}1~X%L]PSyL1|/cʽ atC=؟{9ROLl;-!/aKH> `<` 4u-7%ʽNiܻ ;)x+֑|1c^"Qs.ȇ} hLOSq#cʽ-p+5o P;)7Ŵ0o܋|F dS |1J7(`-Nczʽ,a؈#~ܔgw3VE`ܗyBwS o0{V,sQ?|}1K"{/Y.+q5Jy9NZx "j9UX\oӶwa^2[xmoG!F@ǘ,٤׆2O2X{Lã)A¿6ҲwrdgK?%F#c]JF>;H9rϓJ?#ti;/evyʁ{4Qs%AFb_ .YB*2wc K ^;Kri*oC}1@J;-ߙ 0=Q=S8NRJܳZRGӠ_.[|s~5wS JBja킾 ˘ʎ7՞6rfjߣOASdb1E 8y)PF҄we߁ʑ{-aї1hnY@ʽG1a8wc Jл,Exq@f_VsaLy%p",CþYTFnwc r =U[(H_,N?+LpleK鲑;ɕt\/;}g1&V.NpTi/}2W徘 z+YɒdFɒzd˽ ^ r,C<{hyt$CʶR}&{)R{)-`ʲQ} VĘUnw*{9+EԾW¦mDe_鑲*&j&` J5Kgw Sʦܛ -=;r\Ȕ(&j?s^KY;)M%_¿aʚMޕ )|wSvv 9A;[Y;)?%9r^#ࣾ@,]NߙLy+ro?@;)i1"ДܴLfnrdP%Xs(%5roS5sJE2^n1Ţdʽ+\O 7oV.܂9/E)*%Q~ <5}" 9~wc˽F)&̞*"ܔ.%AQd mĉ_1( $W69I1ٗ۩{AP!Ug[S2r_ȸG,003.;1&rA5 Z[hL}15O89}4 5U|'1GNK}؍)/9-SypZ.a0B"Fq xN\t뮐z˘ÑY{sO;hnLƏ Vӕ|bYモc= [܊"&p 4a/71 b؍)5xSLSXHwyܛȋ@U6kЖ&u-y4,er$S''L&o+Hl;#wV7؍g9;U0i S#'!> |*[6rof\<?dϫevA)TiB2k$~*?+/z1ٷqnT 2 =϶vO][V-e쨈j`@6gzF3 9zk|g1X)d"]8&B8ɄY=&(Vy ؍f L z2ȉ'v]qx pe9Xhg7f?ׁ͋la\v(o#y/Vy'r{)w9$`*N2S+'r4/2zYҟ+H35O`F5&sSZjXOG+i2_#b3e­L<"E<]$EO9`-x]Eh]L^o ˜@j'(LKΡSA|BKĻ1sKЇzg;}12ۀ'+:ݡ')LVuG`j=ˋɻ$-T pCNQS]T[?^}'(7&(-3K"_ie&?1G"'55'_{DVA+)\Z]U]yBJ ~ړq rES>lV|*=NHftɚ*7.zX=ZD8Vlk> Cꩂ:8;) NՇ U4p{a۽~\n68Ȕ%Nu]#1\;y͵ԥb*SaG~ȅq{&kuϋLo88d3ɂW}M\Vy߳bYc# z:l8͘Cp!ɥa]!kLOll}(UK86">8]f88"3zOMqpn˽R&IoRHe5h!JR&W=[3߹ɂeF6m;t;rBA$sh 9pTzZÖωHW 6hJKcC}ae%V55ss 3dގw)u̦.%YOd?P-vxΑmph66*7H߬ Z|qȟ&jM4y"i;wBڣ8`&pv1HN͚nF\2Jpe|TQ{<{X87A'eLq.Kn޴ V!e9(3Ag>ksw$g*6Le2|#m#W.5g8$ru9c~;D?WթzUvB$:̍?}ș 5Cs@,!zKqtu;ZE.>v#azblbɳCh=<#?QB + \1>}`;U]oorF&VˠԞ -L˸JTo9vO >ҮɻSW\8G!` \'.慃س}ޠQc;Bڈ.$S#!=g&`TOjuW>fX|a_uLz7:.ΊǎQ#ԖBm)}LxE< zZ>s~c撷"8o8* 83d1Y9z6}0SP"~c_N.ʘqQ`+yc"!5sorדRږ_]~q+UAѱcZ2Jޘ~C'*3 88jB{*zx`.ΑmR2HLX'u{~ V<+EGhn%(/c␩Q@13ݞLF>zn7=η3zsnv\]ld+$!p|r|ƌ) `o7E\½ 4(dBߚ81.wE&o)cB-scae~*m[Dy0ˆcc 6ecʀ1j2Vd]wRuOJݛ\2WrK'Ȉq(({p)aw 2&ϡe{j{ڵo5 q k*:88ҾMQdr,%Ikw?t^n+a vQ ##jqH͛1]a(5M+ { >w s8`R؍v;Miџ*;9m]<FK<-ܘ;YȸG'dҗ]bJcj0(և<~d^ҒyKAĈD8&maSƅ [=/Vw]Edt8P+wpVg :*Xś%_R, eN r/E\Qh?5%V0Q|RÉMQゎ .`x,XVfˎ"i)PF694/\|YivT8W]sA !S P Δ=ӵ<qVgtӣЖ^[nHžw sU*483p^N{8HIKvb'^q / !τ123  A6;W|1sd831]Ɍ(dXsx;*:Xk-EB`&;*T8. &R67ފNBlRxw]Bf)qzgA Agĺx$"R P`j”b^ bۍ-f?/u}_#e{9%dsed 'D!6Ɓ-4X'>;͡WrJ=mSGM.aetM" wWtp~Gm%MQ, Ч|1:y]5U8!VE'ɲ jS3f(mABKK솗25@:*f_TbD`<@Eiq Ͷ /;hnQLAT8Mԧ+9% 9v,§"kX ]7)V\QACΐV%o(:mGҢ E 6r76H)qȔ^vѝ0IDAT .Rgv|G1r+Y0~RLҢuYԊb&{jTbRccbeKX^%0fdaqJne2WgD&Hhu1ĊH)ʃN.IWlrU>ØBLNx9Hhski+1Q cN陂tM,Ua^S(뜲&iu VE!+` zZ=K!Qg2JJu,]ɬt%ӣБV޼:{K$gO7Q 0<ɒK,c=|$OБb\bw5zHUgy]3!P;jbv&$]2g9.x޿٧yr7%Axqe%%촢Ϫ];dL 0:qNu+Niu-Ab ^kSiyv4N0"IqJ]f+M _ ҜzD^3S v42nEct>Bb}P˘0L9J.(d-{wn*\PצnBNBwc|쒁*^nh6Ӣ.aUb6gJQc)/Joc{ bd#&2,,FnØči¿Jճvd2x^GFgeLQ;岢 O.TOeŖ?xL61#j‚8Si Zu..7$2T;v8 A61+E湱oHѐ(Ű[q3Dݦ;*~ R=htܝ"ywci 'D'D] fK(7!$M+_QJ.B7D9cLu.fe&(i)xaz-)TN8g[zWS`|03EcΐE2ms4$Ċ!]lݘz%J.8,إ'U~^y>;C.9Id9]*U\@J=Az[N"`D9C}>ہrsHU 'DJ蘒&?͵ w}KNyc{cU>{97d71$1cgBbuM Wo|mlcYy `rE c鋁*{.cyCƷw}c7L~h7ЃuM> z\"cay*;wHJwmof@%h M_h]7ݘ4> :*CdItŞ+P[ \ϒhNA_AM85Q&jZKk]a+g olߴP_LjGi0onɴ 4e-1&%uTpNg\x Ck+vE?O;LCoN[~2q800"sT"EaCǺ!ȦdAOG從Q< `S)*!prrtH*]RqM?=@9џ]\Ý@0!*Q1:ݛb,2 Y =|u/'&E>Nk]#-}Cw;w!Yzp=MAy8O1S4'Oy8)L߭urG]flnLaFZ>| =-v` 1&T`A@2bM[0Y 7/CAz:cLN$@Sۥ=6S}"bh7/c1~%W+ <+I "z~cX k1/z^ neq+3^(6Tŋ޼3_cCPޓbpDƊ`}|zy0ч17t~-ٖC E_^rn}}1[OhW='3ۚyBo19w_ 4rPGZ=?>Rws֭Դ>z_ OY+D3V8t`}}u:kzc \=`bm_YQ{AgJ_D2vTDq)#i&%[RWǸ )Y ;#YM X<Ê|2"_OB*v +B"ءs{"G3ۂڲHc*l<;̡dls=AۋYK{cJD$$pˌ@Յ\ U؞C[/#0_cSYp pͪuMԾ'KlHS6*̇y_¦T Ɓ2rv4oBЛҶ<|3ɍ}g1;V5S}"1)iл/f߁jW`,WO뙽yRw6rHo ,1$ p.Re߁Vj @;9l;dyǰ.ެ7r@5QȧJy!@yEy\cr(^'pk#k}ʆLJrC?pnVG%dqLYwlzԷZqs@coLYwl[L }حԋm Łs2r̕_\Ø hSi!Sx;Dq_s:mL!ɃaZ)yw ڜ.߁r)˄K}?h=P;ɪ6\ >nstqk^Ϩ?^ÝO!$ﳟ$R@Yyrk?>?Քd K}?S4_ne[@;-FZs~g.4QspIg*;,ͮq@0p* odA@8SΖB>NpwֳY߁e)+#җ]^A६DDNfjyN㝂> !s=XHC\;CFZ)_kgvzmGeB5^S.s@13tu;9M959.p @ܗd` \͡\\Oy>gپ3%)NEt$ֳv@LxE%3L(H{}޼]P[@>od2S-LqoF \Z:@-M):?.7Qn|Vpp#>3=AV*:T%(:[tY@l_g2-GĖy!w[PM30Uq 0))&d[@Q |+w2g"] ^;!H) \( b7י,R}gDR;sdLѻqnK4!""A.dJZ;i":R80w".Kp*S9 Id&91QXƔ0J|,AR@O(,sݻH[.oo#zp>0^2@}o; y{H];Or)d΂|AO@މr@[<~20SLY v(ٴ\;Au[9@c:oȧhSD/{.p"h=ɩn8Aꀩsiw(=яU) /)Kۮ|?0iBBtVW}yNeܱBw{6v5f AuJR'TcKam+QlȻOf98vM|g+~ZNƟ )rt{j1EqWLӺcKymS^Νͪud{7v/?k9rcJIK@xlV$ܻ۬dZq)r}VN{e]pϡe$PN}m+Ӏscf% Xw\)r_DI7KɌk}g2xd@Rc_Qs N#B|lZ7kw|hdwŸ|g1xs_;Y[e2-R&WFo.W^_9ޭvoP63ƔE!o+]av&Y-3crGJG[VʲwkKW)ƔLė/E^!诀c]};Oe_ >! )vil~A|rLxyQY;H!(u=QOۚv4b-Czk2imT+czJ{1\B+9&jjLڮiY;H!rBj:t0wc>^ppZPٴL7.ieY|Y1{4gXwF=DA Ř2+GiyL7{g+fwcʉB$idrYMB=kS.Jd+ޱ{d6 `<Ɣ]|Ra1G'}ifbLy( yl<;Hi~Cˊ!wcJXܳd5 ;1E5z FYHCh?i'[gs 3Z4Y)pwXrR1ǘ +|g.ľÔ"+~Y) H>lLs=O~ A?_Oo})VyC;IY=jLإ*:b\X{̸Z} ]؟)iꕾ+R}f(:Y.}TOF=S&)7&M['>L/^YTB>%9aK$?gNa{Y!~8wc' I;1[|1r/PVm}s-cd^S;9gv+m89{[1[BywO<۫^~y4vq>>̮reoh3q{6s +2邼O@<&o^+zs#m 4z >]]r們w@TUsKo D7~1ʝ{jv8wu nZִˡjWtSw.$qoX

Vf>?+}piܱ++G0YS 4^~әnD r{gC8F05M`U~k'yZ&>00<)Ky#bڴkKup\!S9 Hq;<,VfV14wC8y +Vp{.fzUU ޠ*X|X5j9W/ׯyAEy qK鱽oA )9 3"2p_}x}qOq$sCuO+o}LJNDÖ+w'F CdFg98ɶ)fAy6K|Yk++G 7*=`GPy7/z\lerj5*0MHLf|gˣx^yOͦe 9pQEeˍ#N ԝae4`F,\|Y[jd (0O1.`+dUׯW%z<{5wzΗs6lS]os$7^%LI4!@&&1F(:BHō t3f 3c}f]yJX9Q4Gn@~NERCI;D8'WݴsByK)j0~D%P! d޹EQpm,Fi*RڂX U`$j2G1l?Πɡ"^@p_zNƙa$FF:u5ȏ2IENDB`rstantools/man/predictive_interval.Rd0000644000176200001440000000431113536774354017606 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/predictive_interval.R \name{predictive_interval} \alias{predictive_interval} \alias{predictive_interval.default} \title{Generic function for predictive intervals} \usage{ predictive_interval(object, ...) \method{predictive_interval}{default}(object, prob = 0.9, ...) } \arguments{ \item{object}{The object to use.} \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} package for examples.} \item{prob}{A number \eqn{p \in (0,1)}{p (0 < p < 1)} indicating the desired probability mass to include in the intervals.} } \value{ \code{predictive_interval()} methods should return a matrix with two columns and as many rows as data points being predicted. For a given value of \code{prob}, \eqn{p}, the columns correspond to the lower and upper \eqn{100p}\% interval limits and have the names \eqn{100\alpha/2}\% and \eqn{100(1 - \alpha/2)}\%, where \eqn{\alpha = 1-p}. For example, if \code{prob=0.9} is specified (a \eqn{90}\% interval), then the column names would be \code{"5\%"} and \code{"95\%"}, respectively. The default method just takes \code{object} to be a matrix and computes quantiles, with \code{prob} defaulting to \code{0.9}. } \description{ See \href{https://mc-stan.org/rstanarm/reference/predictive_interval.stanreg.html}{predictive_interval.stanreg()} in the \pkg{rstanarm} package for an example. } \examples{ # Default method takes a numeric matrix (of draws from posterior # predictive distribution) ytilde <- matrix(rnorm(100 * 5, sd = 2), 100, 5) # fake draws predictive_interval(ytilde, prob = 0.8) # Also see help("predictive_interval", package = "rstanarm") } \seealso{ \itemize{ \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) for example methods (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, \href{https://github.com/stan-dev/rstanarm}{GitHub}). } \itemize{ \item Guidelines and recommendations for developers of \R packages interfacing with Stan and a demonstration getting a simple package working can be found in the vignettes included with \pkg{rstantools} and at \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. } } rstantools/man/posterior_predict.Rd0000644000176200001440000000275313536774354017314 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/posterior_predict.R \name{posterior_predict} \alias{posterior_predict} \title{Generic function for drawing from the posterior predictive distribution} \usage{ posterior_predict(object, ...) } \arguments{ \item{object}{The object to use.} \item{...}{Arguments passed to methods. See the methods in the \pkg{rstanarm} package for examples.} } \value{ \code{posterior_predict()} methods should return a \eqn{D} by \eqn{N} matrix, where \eqn{D} is the number of draws from the posterior predictive distribution and \eqn{N} is the number of data points being predicted per draw. } \description{ Draw from the posterior predictive distribution of the outcome. See \href{https://mc-stan.org/rstanarm/reference/posterior_predict.stanreg.html}{posterior_predict.stanreg()} in the \pkg{rstanarm} package for an example. } \examples{ # See help("posterior_predict", package = "rstanarm") } \seealso{ \itemize{ \item The \pkg{rstanarm} package (\href{https://mc-stan.org/rstanarm/}{mc-stan.org/rstanarm}) for example methods (\href{https://CRAN.R-project.org/package=rstanarm}{CRAN}, \href{https://github.com/stan-dev/rstanarm}{GitHub}). } \itemize{ \item Guidelines and recommendations for developers of \R packages interfacing with Stan and a demonstration getting a simple package working can be found in the vignettes included with \pkg{rstantools} and at \href{https://mc-stan.org/rstantools/articles/}{mc-stan.org/rstantools/articles}. } } rstantools/DESCRIPTION0000644000176200001440000000350413537300535014176 0ustar liggesusersPackage: rstantools Type: Package Title: Tools for Developing R Packages Interfacing with 'Stan' Version: 2.0.0 Date: 2019-09-13 Authors@R: c(person(given = "Jonah", family = "Gabry", role = c("aut", "cre"), email = "jsg2201@columbia.edu"), person(given = "Ben", family = "Goodrich", role = "aut", email = "benjamin.goodrich@columbia.edu"), person(given = "Martin", family = "Lysy", role = "aut", email = "mlysy@uwaterloo.ca"), person(given = "Stefan", family = "Siegert", role = "ctb"), person(given = "Trustees of", family = "Columbia University", role = "cph")) Description: Provides various tools for developers of R packages interfacing with 'Stan' , including functions to set up the required package structure, S3 generics and default methods to unify function naming across 'Stan'-based R packages, and vignettes with recommendations for developers. License: GPL (>= 3) URL: https://mc-stan.org/rstantools/, https://discourse.mc-stan.org/ BugReports: https://github.com/stan-dev/rstantools/issues Encoding: UTF-8 LazyData: true SystemRequirements: pandoc, C++14 Imports: stats, utils, Rcpp (>= 0.12.16), desc Suggests: rstan (>= 2.17.2), usethis (>= 1.5.1), testthat (>= 2.0.0), knitr, pkgbuild, pkgload, roxygen2 (>= 6.0.1), rmarkdown, rstudioapi RoxygenNote: 6.1.1 VignetteBuilder: knitr NeedsCompilation: no Packaged: 2019-09-13 22:26:48 UTC; jgabry Author: Jonah Gabry [aut, cre], Ben Goodrich [aut], Martin Lysy [aut], Stefan Siegert [ctb], Trustees of Columbia University [cph] Maintainer: Jonah Gabry Repository: CRAN Date/Publication: 2019-09-15 00:10:05 UTC rstantools/build/0000755000176200001440000000000013537013647013572 5ustar liggesusersrstantools/build/vignette.rds0000644000176200001440000000040013537013647016123 0ustar liggesusersuPn0 Mi$4WTe\1-I4/sC(Cb%>!C8 pWg`0~0Qg *[HT2T%~=XB[h{*zKe9%UힻC##Lqq9~#7 5Xd_K3v`4n? b?gV?*3??פ}?}G!?Ѧ?pf8?? h?ҙO]?sC?e?E!.#?ft?p?x% ?c jC?]-?Y~C?}vŦrstantools/tests/testthat/predictive_error.RDS0000644000176200001440000000237613055357626021431 0ustar liggesusers{4 @riE%ўfv(ڴ%jli)i|W& "͌a13k{?wAdB!dxβ+tBeه(A%qݔ}E6%hwVwV.(B!;8c>.:jgvTaJdKg+ 3Cb7G$ kǑ{6pR(Dv_[}9b< Hc2hIkVIAh_5% S,QGH4OwtIxOa1*W9ofλh7n q3*1w_<(:}N\1USkL-<ʇjG׈p: ϶6)ļR{$_)h`\.䂌\T@b(FJ`Ј WZpNt#6XFҥlPIg94b\HҢtqvJCw耆cP_#Ւ"ɤ =[jǚ [(U" a0h+jlXe[ Dr HX5;] iēn !M o-^~+h=I{"A2}Ze%٬'AlQ$įhImhS|Xg/ƥsa6}. N; int y[N]; } parameters { real theta; } model { y ~ bernoulli(theta); } rstantools/tests/testthat/posterior_interval.RDS0000644000176200001440000000022113055357626021777 0ustar liggesusersb```b`ffd`b1'j^^Ck[R}WLY}7]gp-b``acd`a)@l4 Qp%PuX̆cd c@ rstantools/tests/testthat/RStanTest/0000755000176200001440000000000013476032654017365 5ustar liggesusersrstantools/tests/testthat/RStanTest/RStanTest-package.R0000644000176200001440000000032713462666422022773 0ustar liggesusers#' Tools for Developing R Packages Interfacing with Stan #' #' @name RStanTest #' @docType package #' @import Rcpp #' @import methods #' @importFrom rstan sampling #' @useDynLib RStanTest, .registration = TRUE NULL rstantools/tests/testthat/RStanTest/NAMESPACE0000644000176200001440000000026513462666422020610 0ustar liggesusers# Generated by roxygen2: do not edit by hand export(postsamp1) export(postsamp2) import(Rcpp) import(methods) importFrom(rstan,sampling) useDynLib(RStanTest, .registration = TRUE) rstantools/tests/testthat/RStanTest/test-rstan_package_skeleton_plus.R0000644000176200001440000000644413462666422026247 0ustar liggesusers# walkthrough for using package skeleton require(rstantools) # change directory to where this file is located pkg_path <- getwd() #--- step 0: create a package without Stan code -------------------------------- # if you want to create an entire package with Stan code from scratch, # skip to step 5 pkg_name <- "RStanTest" package.skeleton(name = pkg_name, code_files = "postsamp.R") # delete contents of "man" and NAMESPACE so roxygen2 can be used file.remove(list.files(file.path(pkg_path, pkg_name, "man"), full.names = TRUE)) file.remove(file.path(pkg_path, pkg_name, "NAMESPACE")) # add testthat tests usethis::use_testthat(pkg_name) file.copy(from = "test-postsamp.R", to = file.path(pkg_name, "tests", "testthat", "test-postsamp.R")) # setup documentation with roxygen2 roxygen2::roxygenize(pkg_name) #--- Step 1: add Stan functionality to package --------------------------------- # this sets up the package to do this rstantools::use_rstan(pkg_name) # follow the instructions to add to the NAMESPACE # since we're using roxygen2, the right way to do this is to # add the lines to an R file in the package. # I like to make this the R/RStanTest-package.R file file.copy(from = file.path(pkg_path, "RStanTest-package.R"), to = file.path(pkg_path, pkg_name, "R", "RStanTest-package.R")) #--- Step 2: add Stan files to package ----------------------------------------- # copy stan_files to inst/stan stan_files <- c("SimpleModel.stan", "SimpleModel2.stan") file.copy(from = file.path(pkg_path, stan_files), to = file.path(pkg_path, pkg_name, "inst", "stan", stan_files)) # configure package to create C++ code associated with stan_files # ***NOTE*** You MUST run this every time you # modify/add/delete anything in inst/stan rstantools::rstan_config(pkg_name) # re-roxygen2, which will automatically compile package roxygen2::roxygenize(pkg_name) #--- step 4: install package and run tests ------------------------------------- utils::install.packages(pkg_name, repos = NULL, type = "source") # quit and restart, then: testthat::test_package("RStanTest", reporter = "progress") #--- step 5: create an entire package with Stan code from scratch -------------- pkg_path <- getwd() pkg_name <- "RStanTest" code_files <- c("RStanTest-package.R", "postsamp.R") stan_files <- c("SimpleModel.stan", "SimpleModel2.stan") rstantools::rstan_package_skeleton_plus(name = pkg_name, path = pkg_path, code_files = code_files, stan_files = stan_files) # add tests usethis::use_testthat(pkg_name) file.copy(from = "test-postsamp.R", to = file.path(pkg_name, "tests", "testthat", "test-postsamp.R")) # roxygen2 can't overwrite NAMESPACE unless it created it, # so trick it into thinking it did # (and add the rstan stuff or else you get errors...) cat("# Generated by roxygen2: do not edit by hand", "", "import(Rcpp,methods)", "useDynLib(RStanTest, .registration = TRUE)", sep = "\n", file = file.path(pkg_path, pkg_name, "NAMESPACE")) roxygen2::roxygenize(pkg_name) # run roxygen2 utils::install.packages(pkg_name, repos = NULL, type = "source") # quit and restart, then: testthat::test_package("RStanTest", reporter = "progress") rstantools/tests/testthat/RStanTest/helper.stan0000644000176200001440000000004113462666422021527 0ustar liggesusersreal foo(real x) { return x; } rstantools/tests/testthat/RStanTest/stanExports_SimpleModel.cc0000644000176200001440000000354713462666422024532 0ustar liggesusers// Generated by rstantools. Do not edit by hand. #include using namespace Rcpp ; #include "stanExports_SimpleModel.h" RCPP_MODULE(stan_fit4SimpleModel_mod) { class_ >("model_SimpleModel") .constructor() .method("call_sampler", &rstan::stan_fit ::call_sampler) .method("param_names", &rstan::stan_fit ::param_names) .method("param_names_oi", &rstan::stan_fit ::param_names_oi) .method("param_fnames_oi", &rstan::stan_fit ::param_fnames_oi) .method("param_dims", &rstan::stan_fit ::param_dims) .method("param_dims_oi", &rstan::stan_fit ::param_dims_oi) .method("update_param_oi", &rstan::stan_fit ::update_param_oi) .method("param_oi_tidx", &rstan::stan_fit ::param_oi_tidx) .method("grad_log_prob", &rstan::stan_fit ::grad_log_prob) .method("log_prob", &rstan::stan_fit ::log_prob) .method("unconstrain_pars", &rstan::stan_fit ::unconstrain_pars) .method("constrain_pars", &rstan::stan_fit ::constrain_pars) .method("num_pars_unconstrained", &rstan::stan_fit ::num_pars_unconstrained) .method("unconstrained_param_names", &rstan::stan_fit ::unconstrained_param_names) .method("constrained_param_names", &rstan::stan_fit ::constrained_param_names) ; } rstantools/tests/testthat/RStanTest/test-add_test.R0000644000176200001440000000023413462666422022254 0ustar liggesuserscontext("add_test") test_that("external C++ code works", { n <- sample(1:20, 1) x <- rnorm(n) y <- rnorm(n) expect_equal(add_test(x, y), x + y) }) rstantools/tests/testthat/RStanTest/stanExports_SimpleModel.h0000644000176200001440000002510713476032654024367 0ustar liggesusers// Generated by rstantools. Do not edit by hand. #ifndef MODELS_HPP #define MODELS_HPP #define STAN__SERVICES__COMMAND_HPP #include // Code generated by Stan version 2.18.0 #include namespace model_SimpleModel_namespace { using std::istream; using std::string; using std::stringstream; using std::vector; using stan::io::dump; using stan::math::lgamma; using stan::model::prob_grad; using namespace stan::math; static int current_statement_begin__; stan::io::program_reader prog_reader__() { stan::io::program_reader reader; reader.add_event(0, 0, "start", "model_SimpleModel"); reader.add_event(14, 12, "end", "model_SimpleModel"); return reader; } #include class model_SimpleModel : public prob_grad { private: double x; public: model_SimpleModel(stan::io::var_context& context__, std::ostream* pstream__ = 0) : prob_grad(0) { ctor_body(context__, 0, pstream__); } model_SimpleModel(stan::io::var_context& context__, unsigned int random_seed__, std::ostream* pstream__ = 0) : prob_grad(0) { ctor_body(context__, random_seed__, pstream__); } void ctor_body(stan::io::var_context& context__, unsigned int random_seed__, std::ostream* pstream__) { typedef double local_scalar_t__; boost::ecuyer1988 base_rng__ = stan::services::util::create_rng(random_seed__, 0); (void) base_rng__; // suppress unused var warning current_statement_begin__ = -1; static const char* function__ = "model_SimpleModel_namespace::model_SimpleModel"; (void) function__; // dummy to suppress unused var warning size_t pos__; (void) pos__; // dummy to suppress unused var warning std::vector vals_i__; std::vector vals_r__; local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); (void) DUMMY_VAR__; // suppress unused var warning // initialize member variables try { current_statement_begin__ = 3; context__.validate_dims("data initialization", "x", "double", context__.to_vec()); x = double(0); vals_r__ = context__.vals_r("x"); pos__ = 0; x = vals_r__[pos__++]; // validate, data variables current_statement_begin__ = 3; // initialize data variables // validate transformed data // validate, set parameter ranges num_params_r__ = 0U; param_ranges_i__.clear(); current_statement_begin__ = 7; ++num_params_r__; } catch (const std::exception& e) { stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__()); // Next line prevents compiler griping about no return throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***"); } } ~model_SimpleModel() { } void transform_inits(const stan::io::var_context& context__, std::vector& params_i__, std::vector& params_r__, std::ostream* pstream__) const { stan::io::writer writer__(params_r__,params_i__); size_t pos__; (void) pos__; // dummy call to supress warning std::vector vals_r__; std::vector vals_i__; if (!(context__.contains_r("mu"))) throw std::runtime_error("variable mu missing"); vals_r__ = context__.vals_r("mu"); pos__ = 0U; context__.validate_dims("initialization", "mu", "double", context__.to_vec()); double mu(0); mu = vals_r__[pos__++]; try { writer__.scalar_unconstrain(mu); } catch (const std::exception& e) { throw std::runtime_error(std::string("Error transforming variable mu: ") + e.what()); } params_r__ = writer__.data_r(); params_i__ = writer__.data_i(); } void transform_inits(const stan::io::var_context& context, Eigen::Matrix& params_r, std::ostream* pstream__) const { std::vector params_r_vec; std::vector params_i_vec; transform_inits(context, params_i_vec, params_r_vec, pstream__); params_r.resize(params_r_vec.size()); for (int i = 0; i < params_r.size(); ++i) params_r(i) = params_r_vec[i]; } template T__ log_prob(vector& params_r__, vector& params_i__, std::ostream* pstream__ = 0) const { typedef T__ local_scalar_t__; local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); (void) DUMMY_VAR__; // suppress unused var warning T__ lp__(0.0); stan::math::accumulator lp_accum__; try { // model parameters stan::io::reader in__(params_r__,params_i__); local_scalar_t__ mu; (void) mu; // dummy to suppress unused var warning if (jacobian__) mu = in__.scalar_constrain(lp__); else mu = in__.scalar_constrain(); // transformed parameters // validate transformed parameters const char* function__ = "validate transformed params"; (void) function__; // dummy to suppress unused var warning // model body current_statement_begin__ = 11; lp_accum__.add(normal_log(x, mu, 1)); } catch (const std::exception& e) { stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__()); // Next line prevents compiler griping about no return throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***"); } lp_accum__.add(lp__); return lp_accum__.sum(); } // log_prob() template T_ log_prob(Eigen::Matrix& params_r, std::ostream* pstream = 0) const { std::vector vec_params_r; vec_params_r.reserve(params_r.size()); for (int i = 0; i < params_r.size(); ++i) vec_params_r.push_back(params_r(i)); std::vector vec_params_i; return log_prob(vec_params_r, vec_params_i, pstream); } void get_param_names(std::vector& names__) const { names__.resize(0); names__.push_back("mu"); } void get_dims(std::vector >& dimss__) const { dimss__.resize(0); std::vector dims__; dims__.resize(0); dimss__.push_back(dims__); } template void write_array(RNG& base_rng__, std::vector& params_r__, std::vector& params_i__, std::vector& vars__, bool include_tparams__ = true, bool include_gqs__ = true, std::ostream* pstream__ = 0) const { typedef double local_scalar_t__; vars__.resize(0); stan::io::reader in__(params_r__,params_i__); static const char* function__ = "model_SimpleModel_namespace::write_array"; (void) function__; // dummy to suppress unused var warning // read-transform, write parameters double mu = in__.scalar_constrain(); vars__.push_back(mu); // declare and define transformed parameters double lp__ = 0.0; (void) lp__; // dummy to suppress unused var warning stan::math::accumulator lp_accum__; local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); (void) DUMMY_VAR__; // suppress unused var warning try { // validate transformed parameters // write transformed parameters if (include_tparams__) { } if (!include_gqs__) return; // declare and define generated quantities // validate generated quantities // write generated quantities } catch (const std::exception& e) { stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__()); // Next line prevents compiler griping about no return throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***"); } } template void write_array(RNG& base_rng, Eigen::Matrix& params_r, Eigen::Matrix& vars, bool include_tparams = true, bool include_gqs = true, std::ostream* pstream = 0) const { std::vector params_r_vec(params_r.size()); for (int i = 0; i < params_r.size(); ++i) params_r_vec[i] = params_r(i); std::vector vars_vec; std::vector params_i_vec; write_array(base_rng,params_r_vec,params_i_vec,vars_vec,include_tparams,include_gqs,pstream); vars.resize(vars_vec.size()); for (int i = 0; i < vars.size(); ++i) vars(i) = vars_vec[i]; } static std::string model_name() { return "model_SimpleModel"; } void constrained_param_names(std::vector& param_names__, bool include_tparams__ = true, bool include_gqs__ = true) const { std::stringstream param_name_stream__; param_name_stream__.str(std::string()); param_name_stream__ << "mu"; param_names__.push_back(param_name_stream__.str()); if (!include_gqs__ && !include_tparams__) return; if (include_tparams__) { } if (!include_gqs__) return; } void unconstrained_param_names(std::vector& param_names__, bool include_tparams__ = true, bool include_gqs__ = true) const { std::stringstream param_name_stream__; param_name_stream__.str(std::string()); param_name_stream__ << "mu"; param_names__.push_back(param_name_stream__.str()); if (!include_gqs__ && !include_tparams__) return; if (include_tparams__) { } if (!include_gqs__) return; } }; // model } typedef model_SimpleModel_namespace::model_SimpleModel stan_model; #endif rstantools/tests/testthat/RStanTest/SimpleModel2.stan0000644000176200001440000000030713462666422022551 0ustar liggesusersfunctions { #include /include/helper.stan } data { real x; } parameters { real sigma; } model { x ~ normal(0, sigma); } generated quantities { real alpha; alpha = foo(3.14); } rstantools/tests/testthat/RStanTest/AddTest.cpp0000644000176200001440000000032313462666422021420 0ustar liggesusers// check that additional C++ code in /src can coexist with Stan C++ code #include using namespace Rcpp; //[[Rcpp::export]] NumericVector add_test(NumericVector x, NumericVector y) { return x + y; } rstantools/tests/testthat/RStanTest/postsamp.R0000644000176200001440000000115113462666422021355 0ustar liggesusers#' Posterior Sampler for SimpleModel #' @export postsamp1 <- function(x, nsamples) { sampling(object = stanmodels$SimpleModel, data = list(x = x), iter = nsamples, chains = 1) } #' Posterior Sampler for SimpleModel2 #' @export postsamp2 <- function(x, nsamples) { sampling(object = stanmodels$SimpleModel2, data = list(x = x), iter = nsamples, chains = 1) } ## #' Posterior Sampler for SimpleModel3 ## #' @export ## postsamp3 <- function(x, nsamples) { ## sampling(object = stanmodels$SimpleModel3, data = list(x = x), ## iter = nsamples, chains = 1) ## } rstantools/tests/testthat/RStanTest/stanExports_SimpleModel2.h0000644000176200001440000003147513476032654024456 0ustar liggesusers// Generated by rstantools. Do not edit by hand. #ifndef MODELS_HPP #define MODELS_HPP #define STAN__SERVICES__COMMAND_HPP #include // Code generated by Stan version 2.18.0 #include namespace model_SimpleModel2_namespace { using std::istream; using std::string; using std::stringstream; using std::vector; using stan::io::dump; using stan::math::lgamma; using stan::model::prob_grad; using namespace stan::math; static int current_statement_begin__; stan::io::program_reader prog_reader__() { stan::io::program_reader reader; reader.add_event(0, 0, "start", "model_SimpleModel2"); reader.add_event(1, 1, "include", "/include/helper.stan"); reader.add_event(1, 0, "start", "/include/helper.stan"); reader.add_event(4, 3, "end", "/include/helper.stan"); reader.add_event(4, 2, "restart", "model_SimpleModel2"); reader.add_event(24, 20, "end", "model_SimpleModel2"); return reader; } template typename boost::math::tools::promote_args::type foo(const T0__& x, std::ostream* pstream__) { typedef typename boost::math::tools::promote_args::type local_scalar_t__; typedef local_scalar_t__ fun_return_scalar_t__; const static bool propto__ = true; (void) propto__; local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); (void) DUMMY_VAR__; // suppress unused var warning int current_statement_begin__ = -1; try { current_statement_begin__ = 3; return stan::math::promote_scalar(x); } catch (const std::exception& e) { stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__()); // Next line prevents compiler griping about no return throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***"); } } struct foo_functor__ { template typename boost::math::tools::promote_args::type operator()(const T0__& x, std::ostream* pstream__) const { return foo(x, pstream__); } }; #include class model_SimpleModel2 : public prob_grad { private: double x; public: model_SimpleModel2(stan::io::var_context& context__, std::ostream* pstream__ = 0) : prob_grad(0) { ctor_body(context__, 0, pstream__); } model_SimpleModel2(stan::io::var_context& context__, unsigned int random_seed__, std::ostream* pstream__ = 0) : prob_grad(0) { ctor_body(context__, random_seed__, pstream__); } void ctor_body(stan::io::var_context& context__, unsigned int random_seed__, std::ostream* pstream__) { typedef double local_scalar_t__; boost::ecuyer1988 base_rng__ = stan::services::util::create_rng(random_seed__, 0); (void) base_rng__; // suppress unused var warning current_statement_begin__ = -1; static const char* function__ = "model_SimpleModel2_namespace::model_SimpleModel2"; (void) function__; // dummy to suppress unused var warning size_t pos__; (void) pos__; // dummy to suppress unused var warning std::vector vals_i__; std::vector vals_r__; local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); (void) DUMMY_VAR__; // suppress unused var warning // initialize member variables try { current_statement_begin__ = 8; context__.validate_dims("data initialization", "x", "double", context__.to_vec()); x = double(0); vals_r__ = context__.vals_r("x"); pos__ = 0; x = vals_r__[pos__++]; // validate, data variables current_statement_begin__ = 8; // initialize data variables // validate transformed data // validate, set parameter ranges num_params_r__ = 0U; param_ranges_i__.clear(); current_statement_begin__ = 12; ++num_params_r__; } catch (const std::exception& e) { stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__()); // Next line prevents compiler griping about no return throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***"); } } ~model_SimpleModel2() { } void transform_inits(const stan::io::var_context& context__, std::vector& params_i__, std::vector& params_r__, std::ostream* pstream__) const { stan::io::writer writer__(params_r__,params_i__); size_t pos__; (void) pos__; // dummy call to supress warning std::vector vals_r__; std::vector vals_i__; if (!(context__.contains_r("sigma"))) throw std::runtime_error("variable sigma missing"); vals_r__ = context__.vals_r("sigma"); pos__ = 0U; context__.validate_dims("initialization", "sigma", "double", context__.to_vec()); double sigma(0); sigma = vals_r__[pos__++]; try { writer__.scalar_lb_unconstrain(0,sigma); } catch (const std::exception& e) { throw std::runtime_error(std::string("Error transforming variable sigma: ") + e.what()); } params_r__ = writer__.data_r(); params_i__ = writer__.data_i(); } void transform_inits(const stan::io::var_context& context, Eigen::Matrix& params_r, std::ostream* pstream__) const { std::vector params_r_vec; std::vector params_i_vec; transform_inits(context, params_i_vec, params_r_vec, pstream__); params_r.resize(params_r_vec.size()); for (int i = 0; i < params_r.size(); ++i) params_r(i) = params_r_vec[i]; } template T__ log_prob(vector& params_r__, vector& params_i__, std::ostream* pstream__ = 0) const { typedef T__ local_scalar_t__; local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); (void) DUMMY_VAR__; // suppress unused var warning T__ lp__(0.0); stan::math::accumulator lp_accum__; try { // model parameters stan::io::reader in__(params_r__,params_i__); local_scalar_t__ sigma; (void) sigma; // dummy to suppress unused var warning if (jacobian__) sigma = in__.scalar_lb_constrain(0,lp__); else sigma = in__.scalar_lb_constrain(0); // transformed parameters // validate transformed parameters const char* function__ = "validate transformed params"; (void) function__; // dummy to suppress unused var warning // model body current_statement_begin__ = 16; lp_accum__.add(normal_log(x, 0, sigma)); } catch (const std::exception& e) { stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__()); // Next line prevents compiler griping about no return throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***"); } lp_accum__.add(lp__); return lp_accum__.sum(); } // log_prob() template T_ log_prob(Eigen::Matrix& params_r, std::ostream* pstream = 0) const { std::vector vec_params_r; vec_params_r.reserve(params_r.size()); for (int i = 0; i < params_r.size(); ++i) vec_params_r.push_back(params_r(i)); std::vector vec_params_i; return log_prob(vec_params_r, vec_params_i, pstream); } void get_param_names(std::vector& names__) const { names__.resize(0); names__.push_back("sigma"); names__.push_back("alpha"); } void get_dims(std::vector >& dimss__) const { dimss__.resize(0); std::vector dims__; dims__.resize(0); dimss__.push_back(dims__); dims__.resize(0); dimss__.push_back(dims__); } template void write_array(RNG& base_rng__, std::vector& params_r__, std::vector& params_i__, std::vector& vars__, bool include_tparams__ = true, bool include_gqs__ = true, std::ostream* pstream__ = 0) const { typedef double local_scalar_t__; vars__.resize(0); stan::io::reader in__(params_r__,params_i__); static const char* function__ = "model_SimpleModel2_namespace::write_array"; (void) function__; // dummy to suppress unused var warning // read-transform, write parameters double sigma = in__.scalar_lb_constrain(0); vars__.push_back(sigma); // declare and define transformed parameters double lp__ = 0.0; (void) lp__; // dummy to suppress unused var warning stan::math::accumulator lp_accum__; local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); (void) DUMMY_VAR__; // suppress unused var warning try { // validate transformed parameters // write transformed parameters if (include_tparams__) { } if (!include_gqs__) return; // declare and define generated quantities current_statement_begin__ = 20; local_scalar_t__ alpha; (void) alpha; // dummy to suppress unused var warning stan::math::initialize(alpha, DUMMY_VAR__); stan::math::fill(alpha,DUMMY_VAR__); current_statement_begin__ = 21; stan::math::assign(alpha, foo(3.1400000000000001, pstream__)); // validate generated quantities current_statement_begin__ = 20; // write generated quantities vars__.push_back(alpha); } catch (const std::exception& e) { stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__()); // Next line prevents compiler griping about no return throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***"); } } template void write_array(RNG& base_rng, Eigen::Matrix& params_r, Eigen::Matrix& vars, bool include_tparams = true, bool include_gqs = true, std::ostream* pstream = 0) const { std::vector params_r_vec(params_r.size()); for (int i = 0; i < params_r.size(); ++i) params_r_vec[i] = params_r(i); std::vector vars_vec; std::vector params_i_vec; write_array(base_rng,params_r_vec,params_i_vec,vars_vec,include_tparams,include_gqs,pstream); vars.resize(vars_vec.size()); for (int i = 0; i < vars.size(); ++i) vars(i) = vars_vec[i]; } static std::string model_name() { return "model_SimpleModel2"; } void constrained_param_names(std::vector& param_names__, bool include_tparams__ = true, bool include_gqs__ = true) const { std::stringstream param_name_stream__; param_name_stream__.str(std::string()); param_name_stream__ << "sigma"; param_names__.push_back(param_name_stream__.str()); if (!include_gqs__ && !include_tparams__) return; if (include_tparams__) { } if (!include_gqs__) return; param_name_stream__.str(std::string()); param_name_stream__ << "alpha"; param_names__.push_back(param_name_stream__.str()); } void unconstrained_param_names(std::vector& param_names__, bool include_tparams__ = true, bool include_gqs__ = true) const { std::stringstream param_name_stream__; param_name_stream__.str(std::string()); param_name_stream__ << "sigma"; param_names__.push_back(param_name_stream__.str()); if (!include_gqs__ && !include_tparams__) return; if (include_tparams__) { } if (!include_gqs__) return; param_name_stream__.str(std::string()); param_name_stream__ << "alpha"; param_names__.push_back(param_name_stream__.str()); } }; // model } typedef model_SimpleModel2_namespace::model_SimpleModel2 stan_model; #endif rstantools/tests/testthat/RStanTest/stanExports_SimpleModel2.cc0000644000176200001440000000355213462666422024610 0ustar liggesusers// Generated by rstantools. Do not edit by hand. #include using namespace Rcpp ; #include "stanExports_SimpleModel2.h" RCPP_MODULE(stan_fit4SimpleModel2_mod) { class_ >("model_SimpleModel2") .constructor() .method("call_sampler", &rstan::stan_fit ::call_sampler) .method("param_names", &rstan::stan_fit ::param_names) .method("param_names_oi", &rstan::stan_fit ::param_names_oi) .method("param_fnames_oi", &rstan::stan_fit ::param_fnames_oi) .method("param_dims", &rstan::stan_fit ::param_dims) .method("param_dims_oi", &rstan::stan_fit ::param_dims_oi) .method("update_param_oi", &rstan::stan_fit ::update_param_oi) .method("param_oi_tidx", &rstan::stan_fit ::param_oi_tidx) .method("grad_log_prob", &rstan::stan_fit ::grad_log_prob) .method("log_prob", &rstan::stan_fit ::log_prob) .method("unconstrain_pars", &rstan::stan_fit ::unconstrain_pars) .method("constrain_pars", &rstan::stan_fit ::constrain_pars) .method("num_pars_unconstrained", &rstan::stan_fit ::num_pars_unconstrained) .method("unconstrained_param_names", &rstan::stan_fit ::unconstrained_param_names) .method("constrained_param_names", &rstan::stan_fit ::constrained_param_names) ; } rstantools/tests/testthat/RStanTest/test-postsamp.R0000644000176200001440000000277313462666422022345 0ustar liggesusersrequire(rstan) # for log_prob & unconstrain_pars stan_quiet <- function(expr) { suppressMessages(suppressWarnings(expr)) } context("postsamp") test_that("postsamp1: logposterior", { # data x <- rnorm(1) logpost <- stan_quiet(postsamp1(x = x, nsamples = 1)) # parameter values nsim <- sample(20:30, 1) Pars <- replicate(n = nsim, expr = { list(mu = rnorm(1)) }, simplify = FALSE) # log-posterior in R lpR <- sapply(1:nsim, function(ii) { mu <- Pars[[ii]]$mu dnorm(x, mu, 1, log = TRUE) }) # log-posterior in stan lpStan <- sapply(1:nsim, function(ii) { upars <- unconstrain_pars(object = logpost, pars = Pars[[ii]]) log_prob(object = logpost, upars = upars, adjust_transform = FALSE) }) expect_equal(max(abs(diff(lpR-lpStan))), 0, tolerance = 1e-6) }) test_that("postsamp2: logposterior", { # data x <- rnorm(1) logpost <- stan_quiet(postsamp2(x = x, nsamples = 1)) # parameter values nsim <- sample(20:30, 1) Pars <- replicate(n = nsim, expr = { list(sigma = runif(1, .2, 4)) }, simplify = FALSE) # log-posterior in R lpR <- sapply(1:nsim, function(ii) { sigma <- Pars[[ii]]$sigma dnorm(x, 0, sigma, log = TRUE) }) # log-posterior in stan lpStan <- sapply(1:nsim, function(ii) { upars <- unconstrain_pars(object = logpost, pars = Pars[[ii]]) log_prob(object = logpost, upars = upars, adjust_transform = FALSE) }) expect_equal(max(abs(diff(lpR-lpStan))), 0, tolerance = 1e-6) }) rstantools/tests/testthat/RStanTest/SimpleModel.stan0000644000176200001440000000015213462666422022465 0ustar liggesusers// x ~ N(mu, 1) data { real x; } parameters { real mu; } model { x ~ normal(mu, 1); } rstantools/tests/testthat/test-rstan_create_package.R0000644000176200001440000001372013536766666022744 0ustar liggesusers#--- test rstan_create_package ----------------------------------------------- # 1. create package under various conditions # 2. pkgload::load_all package # 3. run tests on package # 4. delete package source # setup run_all_tests <- FALSE # if TRUE disables skip_on_cran and skip_on_travis source("rstan_package_skeleton-testfunctions.R") # helper functions to run tests pkg_name <- "RStanTest" # base name of package # path to base directory where packages will be created tmp_test_path <- TRUE # put all tests in temporary folder if(tmp_test_path) test_path <- tempfile(pattern = "rstantools_") dir.create(test_path, recursive = TRUE) rand_path <- TRUE # randomize destination path # path to package source files pkg_src_path <- "RStanTest" ## pkg_src_path <- system.file("include", "RStanTest", ## package = "rstantools") # package R files code_files <- file.path(pkg_src_path, "postsamp.R") # package stan files stan_files <- file.path(pkg_src_path, c("SimpleModel.stan", "SimpleModel2.stan")) # package stan/include files incl_files <- file.path(pkg_src_path, "helper.stan") # package C++ files src_files <- file.path(pkg_src_path, "AddTest.cpp") # various test conditions test_descr <- expand.grid( ## create_package = c(TRUE, FALSE), # use create_package or package_skeleton create_package = TRUE, # package_skeleton now depreciated roxygen = c(TRUE, FALSE) # use roxygen for documentation ) ntest <- nrow(test_descr) # run tests for(ii in 1:ntest) { if(rand_path) { pkg_dest_path <- file.path(test_path, basename(tempfile(pattern = pkg_name)), pkg_name) } else { pkg_dest_path <- file.path(test_path, pkg_name) } # specific test condition use_create_package <- test_descr$create_package[ii] use_roxygen <- test_descr$roxygen[ii] context(paste0( ifelse(use_create_package, yes = "rstan_create_package", no = "rstan_package_skeleton"), " -- ", ifelse(use_roxygen, "with", "without"), " roxygen") ) # create package if(rand_path) dir.create(dirname(pkg_dest_path), recursive = TRUE) if(use_create_package) { # use rstan_create_package rstan_create_package(path = pkg_dest_path, rstudio = FALSE, open = FALSE, ## stan_files = stan_files, roxygen = use_roxygen) # add R files file.copy(from = code_files, to = file.path(pkg_dest_path, "R", basename(code_files))) } else { stop("rstan_package_skeleton has been depreciated.") # use rstan_package_skeleton rstan_package_skeleton(name = pkg_name, path = dirname(pkg_dest_path), ## stan_files = stan_files, code_files = code_files, roxygen = use_roxygen) } # add stan files (need to do this separately or else rstan_config complains) file.copy(from = stan_files, to = file.path(pkg_dest_path, "inst", "stan", basename(stan_files))) # add stan/include files file.copy(from = incl_files, to = file.path(pkg_dest_path, "inst", "stan", "include", basename(incl_files))) # add C++ files file.copy(from = src_files, to = file.path(pkg_dest_path, "src", basename(src_files))) rstan_config(pkg_dest_path) ## Rcpp::compileAttributes(pkg_dest_path) # install & load package test_that("Package loads correctly", { if(!run_all_tests) { skip_on_cran() skip_on_travis() } ## if(!use_roxygen) pkgbuild::compile_dll(pkg_dest_path) tmp <- capture.output(load_out <- pkgload::load_all(pkg_dest_path, export_all = TRUE, quiet = TRUE)) expect_type(load_out, "list") }) if(use_roxygen) { # check roxygen documentation # TODO: stop test if roxygen2 not found test_that("roxygen works properly", { if(!run_all_tests) { skip_on_cran() skip_on_travis() } skip_if_not_installed("roxygen2") ## pkgbuild::compile_dll(pkg_dest_path) ## devtools::document(pkg_dest_path) tmp <- capture.output(pkgload::unload(pkg_name)) roxygen2::roxygenize(pkg_dest_path) roxygen2::roxygenize(pkg_dest_path) tmp <- capture.output(load_out <- pkgload::load_all(pkg_dest_path, export_all = TRUE, quiet = TRUE)) expect_identical(readLines(file.path(pkg_dest_path, "NAMESPACE")), readLines(file.path(pkg_src_path, "NAMESPACE"))) }) } # check that functions work as expected test_that("logpost_R == logpost_Stan: postsamp1", { if(!run_all_tests) { skip_on_cran() skip_on_travis() } compare_postsamp1() }) test_that("logpost_R == logpost_Stan: postsamp2", { if(!run_all_tests) { skip_on_cran() skip_on_travis() } compare_postsamp2() }) test_that("external C++ code works", { if(!run_all_tests) { skip_on_cran() skip_on_travis() } n <- sample(1:20, 1) x <- rnorm(n) y <- rnorm(n) expect_equal(add_test(x, y), x + y) }) # uninstall + delete package # tmp <- capture.output(pkgload::unload(pkg_name)) ## detach(paste0("package:", pkg_name), ## unload = TRUE, character.only = TRUE) ## remove.packages(pkgs = pkg_name, lib = lib_path) # remove installed package if(rand_path) { unlink(dirname(pkg_dest_path), recursive = TRUE, force = TRUE) } else { unlink(pkg_dest_path, recursive = TRUE, force = TRUE) } } # make sure everything gets deleted even if there are errors teardown(code = { ## if(isNamespaceLoaded(pkg_name)) { ## detach(paste0("package:", pkg_name), ## unload = TRUE, character.only = TRUE) ## } if(tmp_test_path) unlink(test_path, recursive = TRUE, force = TRUE) }) rstantools/tests/testthat.R0000644000176200001440000000032213536774022015615 0ustar liggesuserslibrary(testthat) library(rstantools) foo <- function(x) {"test function"} if (identical(Sys.getenv("TRAVIS"), "true")) { test_check("rstantools", filter = "methods") } else { test_check("rstantools") } rstantools/vignettes/0000755000176200001440000000000013537013647014503 5ustar liggesusersrstantools/vignettes/developer-guidelines.Rmd0000644000176200001440000002631013537000245021252 0ustar liggesusers--- title: "Guidelines for Developers of R Packages Interfacing with Stan" author: "Stan Development Team" date: "Latest release: `r format(Sys.Date(), format = '%B %Y')` (First version: November 2016)" output: rmarkdown::html_vignette: toc: true vignette: > %\VignetteIndexEntry{Developer Guidelines} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ## Note to developers One of the coolest things about working on a project like Stan has been seeing some of our users begin to develop tools for making Stan more accessible to audiences that may otherwise not benefit from what Stan offers. In particular, recently we have started seeing a growing number of R packages that provide high-level interfaces to Stan, using the [__rstan__](https://mc-stan.org/rstan) package for estimating models without requiring that the user be familiar with the Stan modeling language itself. This is a great development and we would like to support such efforts going forward, but to-date we have made little effort to coordinate the development of these packages. To avoid a Wild West, so to speak, of Stan-based R packages, we think it is important that developers make every effort to adhere to certain guidelines in order to ensure these packages are of the highest possible quality and provide the best possible experience for users. To that end, in this post we present a set of recommendations for the development of R packages that interface with Stan. These recommendations are based on software design principles we value as well as many things we are learning as we continue developing our __rstanarm__ package and review packages being developed by others. Of course anyone is free to develop a package based on Stan, even if they ignore these recommendations. However, both because we feel strongly about these recommendations and because we are seeing an increase in the number of requests for help (and our time is unfortunately limited), we will loosely enforce these guidelines by 1. prioritizing giving feedback to developers who follow them over those who choose not to, and 2. refraining from promoting packages that ignore them. That said, we are open to some limited exceptions (e.g., the __brms__ package is a sensible exception to one of guidelines about Stan code). If you think your package should be an exception definitely let us know. ## Guidelines for R packages providing interfaces to Stan ### General package structure and development * The __rstantools__ package provides the `rstan_create_package()` function, which you should use to create the basic structure of your package. (As of `v2.0.0` this replaces the `rstan_package_skeleton` function.) This will set up a package with functionality for pre-compiled Stan programs, in the style of the [__rstanarm__](https://mc-stan.org/rstanarm) package (source code: https://github.com/stan-dev/rstanarm). * Use version control (e.g., git). * Unless you are developing proprietary private software, organize your code in a repository that is _public_ on [GitHub](https://github.com/) (or a similar service, but preferably GitHub). It should be public even at early stages of development, not only when officially released. We recommend you add a note to your README file on how to install the development version of your package, like in the [__bayesplot__ README](https://github.com/stan-dev/bayesplot#installation) * Unit testing is essential. There are several R packages that make it relatively easy to write tests for your package. Most of our R packages (e.g., __rstanarm__, __brms__, __bayesplot__, __shinystan__, __loo__) use the [__testthat__](https://github.com/r-lib/testthat) package for this purpose, but if you prefer a different testing framework that's fine. The [__covr__](https://github.com/r-lib/covr) package is useful for calculating the line coverage of your tests, and we recommend reaching a high level of coverage before releasing a package. Good line coverage does not guarantee high quality tests, but it's a good first step. ### Stan code * All Stan code for estimating models should be included in pre-written static `.stan` files that are compiled when the package is built (see the Stan programs directory in the __rstanarm__ repo for examples). You can also use subdirectories to include code chunks to be used in multiple `.stan` files (again see the __rstanarm__ repo for examples). If you set up your package using `rstan_create_package` this structure will be created for you. This means that __your package should NOT write a Stan program when the user calls a model fitting function in your package__, but rather use only Stan programs you have written by hand in advance (if you are working on a model for which you don't think this is possible please let us know). There are several reasons for this. * Pre-compiled Stan programs can be run by users of Windows or Mac OSX without having to install a C++ compiler, which dramatically expands the universe of potential users for your package. * Pre-compiled Stan programs will run immediately when called, avoiding compilation time. * CRAN policy permits long installation times but imposes restrictions on the time consumed by examples and unit tests that are much shorter than the time that it takes to compile even a simple Stan program. Thus, it is only possible to adequately test your package if it has pre-compiled Stan programs. * Pre-compiled Stan programs can use custom C++ functions. To provide flexibility to users, your Stan programs can include branching logic (conditional statements) so that even with a small number of .stan files you can still allow for many different specifications to made by the user (see the .stan files in __rstanarm__ for examples). * Use best practices for Stan code. If the models you intend to implement are discussed in the Stan manual or on the Stan users forum then you should follow any recommendations that apply to your case. If you are unsure whether your Stan programs can be made more efficient or more numerically stable then please ask us on the Stan users forum. Especially ask us if you are unsure whether your Stan programs are indeed estimating the intended model. * Relatedly, prioritize safety over speed in your Stan code and sampler settings. For example, if you can write a program that runs faster but is potentially less stable, then at a minimum you should make the more stable version the default. This also means that, with rare exceptions, you should not change our recommended MCMC defaults (e.g. 4 chains, 1000+1000 iterations, NUTS not static HMC), unless you are setting the defaults to something more conservative. __rstanarm__ even goes one step further, making the default value of the `adapt_delta` tuning parameter at least 0.95 for all models (rather than __rstan__'s default of 0.8) in order to reduce the step size and therefore also limit the potential for divergences. This means that __rstanarm__ models may often run a bit slower than they need to if the user doesn't change the defaults, but it also means that users face fewer situations in which they need to know how to change the defaults and what the implications of changing the defaults really are. ### R code and documentation * Functions that provide useful post-estimation functionality should be given the same names as the corresponding functions in __rstanarm__ (if applicable). For example, `posterior_predict()` to draw from the posterior predictive distribution, `posterior_interval()` for posterior uncertainty intervals, etc. To make this easier, these and similar __rstanarm__ functions have been converted to S3 methods for the stanreg objects created by __rstanarm__ and the S3 generic functions are included here in the __rstantools__ package. Your package should import the generics from __rstantools__ for whichever functions you want to include in your package and then provide methods for the fitted model objects returned by your model-fitting functions. For some other functions (e.g. `as.matrix`) the generics are already available in base R or core R packages. To be clear, we are not saying that the naming conventions used in __rstanarm__/__rstantools__ are necessarily optimal. (If you think that one of our function names should be changed please let us know and suggest an alternative. If it is a substantial improvement we may consider renaming the function and deprecating the current version.) Rather, this guideline is intended to make function names consistent across Stan-based R packages, which will improve the user experience for those users who want to take advantage of a variety of these packages. It will be a mess if every R package using Stan has different names for the same functionality. * The [__bayesplot__](https://mc-stan.org/bayesplot/) package serves as the back-end for plotting for __rstanarm__ (see for example `pp_check.stanreg` and `plot.stanreg`), __brms__, and other packages, and we hope developers of other Stan-based R packages will also use it. You can see all the other R packages using __bayesplot__ in the _Reverse dependencies_ section of the __bayesplot__ [CRAN page](https://CRAN.R-project.org/package=bayesplot). For any plot you intend to include in your package, if it is already available in __bayesplot__ then we recommend using the available version or suggesting (or contributing) a better version. If it is not already available then there is a good chance we will be interested in including it in __bayesplot__ if the plot would also be useful for other developers. * Provide thorough and clear documentation. The documentation won't be perfect (we've found many holes in our __rstanarm__ documentation already and there are certainly more), but you should make every effort to provide clear and thorough documentation, using decent grammar and actual sentences wherever possible. The poor quality of the documentation in many (though certainly not all) R packages is insulting to users and an impediment to high quality research. In no way is the current state of R package documentation a reason to insufficiently document your own package. It is unfortunate that this needs to be said, but even a cursory review of popular R packages immediately reveals the necessity for guidelines like this one. Some of our own documentation does not always meet this high standard, but we are consistently making efforts to improve this. ### Recommended resources * Hadley Wickham's [book on R packages](http://r-pkgs.had.co.nz/). If you are interested in developing an R package that interfaces with Stan but are not an experienced package developer, we recommend Hadley's book, which is free to read online. Even if you are an experienced developer of R packages, Hadley's book is still a great resource. * If you need help setting up your package or have questions about these guidelines the best places to go are the [Stan Forums](https://discourse.mc-stan.org) and the [GitHub issue tracker](https://github.com/stan-dev/rstantools/issues) for the __rstantools__ package. ## Concluding remarks These guidelines are not set in stone. We expect them to evolve and we very much appreciate feedback on how they can be improved. And, of course, we look forward to seeing the packages you develop using Stan, so please let us know about them! -- The Stan Development Team rstantools/vignettes/minimal-rstan-package.Rmd0000644000176200001440000002335513537012352021313 0ustar liggesusers--- title: "Step by step guide for creating a package that depends on RStan" author: "Stefan Siegert, Jonah Gabry, Martin Lysy, and Ben Goodrich" date: "`r Sys.Date()`" output: rmarkdown::html_vignette: toc: true params: EVAL: !r identical(Sys.getenv("NOT_CRAN"), "true") vignette: > %\VignetteIndexEntry{Step by step guide} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r SETTINGS-knitr, include=FALSE} stopifnot(require(knitr)) opts_chunk$set( comment=NA, eval = if (isTRUE(exists("params"))) params$EVAL else FALSE ) td <- tempdir() PATH <- file.path(td, "rstanlm") if(dir.exists(PATH)) { unlink(PATH, recursive = TRUE, force = TRUE) } ``` ## Introduction In this vignette we will walk through the steps necessary for creating an R package that depends on Stan by creating a package with one function that fits a simple linear regression. Before continuing, we recommend that you first read the other vignette [_Guidelines for Developers of R Packages Interfacing with Stan_](http://mc-stan.org/rstantools/articles/developer-guidelines.html). ## Creating the package skeleton The **rstantools** package offers two methods for adding Stan functionality to R packages: * `rstan_create_package()`: set up a new R package with Stan programs * `use_rstan()`: add Stan functionality to an _existing_ R package Here we will use `rstan_create_package()` to initialize a bare-bones package directory. The name of our demo package will be __rstanlm__; it will fit a simple linear regression model using Stan. ```{r rstan_create_package, eval=FALSE} library("rstantools") rstan_create_package(path = 'rstanlm') ``` ```{r rstan_create_package-eval, echo=FALSE,warning=FALSE} library("rstantools") rstan_create_package(path = PATH, rstudio=FALSE, open=FALSE) ``` If we had existing `.stan` files to include with the package we could use the optional `stan_files` argument to `rstan_create_package()` to include them. Another option, which we'll use below, is to add the Stan files once the basic structure of the package is in place. We can now set the new working directory to the new package directory and view the contents. (Note: if using RStudio then by default the newly created project for the package will be opened in a new session and you will not need the call to `setwd()`.) ```{r, eval=FALSE} setwd("rstanlm") list.files(all.files = TRUE) ``` ```{r, echo=FALSE} list.files(PATH, all.files = TRUE) ``` ```{r, eval=FALSE} file.show("DESCRIPTION") ``` ```{r, echo=FALSE} DES <- readLines(file.path(PATH, "DESCRIPTION")) cat(DES, sep = "\n") ``` Some of the sections in the `DESCRIPTION` file need to be edited by hand (e.g., `Title`, `Author`, `Maintainer`, and `Description`, but these also can be set with the `fields` argument to `rstan_create_package()`). However, `rstan_create_package()` has added the necessary packages and versions to `Depends`, `Imports`, and `LinkingTo` to enable Stan functionality. ## Read-and-delete-me file Before deleting the `Read-and-delete-me` file in the new package directory make sure to read it because it contains some important instructions about customizing your package: ```{r, eval=FALSE} file.show("Read-and-delete-me") ``` ```{r, echo=FALSE} cat(readLines(file.path(PATH, "Read-and-delete-me")), sep = "\n") ``` You can move this file out of the directory, delete it, or list it in the `.Rbuildignore` file if you want to keep it in the directory. ```{r, eval=FALSE} file.remove('Read-and-delete-me') ``` ```{r, echo=FALSE} file.remove(file.path(PATH, 'Read-and-delete-me')) ``` ## Stan files Our package will call **rstan**'s `sampling()` method to use MCMC to fit a simple linear regression model for an outcome variable `y` with a single predictor `x`. After writing the necessary Stan program, the file should be saved with a `.stan` extension in the `inst/stan` subdirectory. We'll save the following program to `inst/stan/lm.stan`: ```{stan, output.var = "foo", eval = FALSE} // Save this file as inst/stan/lm.stan data { int N; vector[N] x; vector[N] y; } parameters { real intercept; real beta; real sigma; } model { // ... priors, etc. y ~ normal(intercept + beta * x, sigma); } ``` ```{r, include=FALSE} stan_prog <- " data { int N; vector[N] x; vector[N] y; } parameters { real intercept; real beta; real sigma; } model { // ... priors, etc. y ~ normal(intercept + beta * x, sigma); } " cat(stan_prog, file = file.path(PATH, "inst", "stan", "lm.stan")) rstan_config(PATH) ``` The `inst/stan` subdirectory can contain additional Stan programs if required by your package. During installation, all Stan programs will be compiled and saved in the list `stanmodels` that can then be used by R function in the package. The rule is that the Stan program compiled from the model code in `inst/stan/foo.stan` is stored as list element `stanmodels$foo`. Thus, the filename of the Stan program in the `inst/stan` directory should not contain spaces or dashes and nor should it start with a number or utilize non-ASCII characters. ## R files We next create the file `R/lm_stan.R` where we define the function `lm_stan()` in which our compiled Stan model is being used. Setting the `rstan_create_package()` argument `roxygen = TRUE` (the default value) enables [__roxygen2__](https://CRAN.R-project.org/package=roxygen2) documentation for the package functions. The following comment block placed in `lm_stan.R` ensures that the function has a help file and that it is added to the package `NAMESPACE`: ```{r} # Save this file as `R/lm_stan.R` #' Bayesian linear regression with Stan #' #' @export #' @param x Numeric vector of input values. #' @param y Numberic vector of output values. #' @param ... Arguments passed to `rstan::sampling` (e.g. iter, chains). #' @return An object of class `stanfit` returned by `rstan::sampling` #' lm_stan <- function(x, y, ...) { standata <- list(x = x, y = y, N = length(y)) out <- rstan::sampling(stanmodels$lm, data = standata, ...) return(out) } ``` ```{r, include=FALSE} Rcode <- " #' Bayesian linear regression with Stan #' #' @export #' @param x Numeric vector of input values. #' @param y Numberic vector of output values. #' @param ... Arguments passed to `rstan::sampling`. #' @return An object of class `stanfit` returned by `rstan::sampling` lm_stan <- function(x, y, ...) { out <- rstan::sampling(stanmodels$lm, data=list(x=x, y=y, N=length(y)), ...) return(out) } " cat(Rcode, file = file.path(PATH, "R", "lm_stan.R")) ``` When __roxygen2__ documentation is enabled, a top-level package file `R/rstanlm-package.R` is created by `rstan_create_package()` to import necessary functions for other packages and to set up the package for compiling Stan C++ code: ```{r, eval=FALSE} file.show(file.path("R", "rstanlm-package.R")) ``` ```{r, echo=FALSE} cat(readLines(file.path(PATH, "R", "rstanlm-package.R")), sep = "\n") ``` The `#' @description` section can be manually edited to provided specific information about the package. ## Documentation With __roxygen__ documentation enabled, we need to generate the documentation for `lm_stan` and update the `NAMESPACE` so the function is exported, i.e., available to users when the package is installed. This can be done with the function `roxygen2::roxygenize()`. ```{r, eval=FALSE} pkgbuild::compile_dll() # see note below roxygen2::roxygenize() ``` ```{r, include=FALSE} pkgbuild::compile_dll(PATH) # required for newer versions of roxygen2 ``` ```{r, echo=FALSE} roxygen2::roxygenize(PATH) ``` __Note:__ For newer versions of __roxygen__, it is necessary to compile the package C++ code prior to running `roxygen2::roxygenize()`. One way to do this is with `pkgbuild::compile_dll()`, as above. ## Install and use Finally, the package is ready to be installed: ```{r,eval=FALSE} # using ../rstanlm because already inside the rstanlm directory install.packages("../rstanlm", repos = NULL, type = "source") ``` ```{r,echo=FALSE} install.packages(PATH, repos = NULL, type = "source") ``` It is also possible to use `devtools::install(quick=FALSE)` to install the package. The argument `quick=FALSE` is necessary if you want to recompile the Stan models. Going forward, if you only make a change to the R code or the documentation, you can set `quick=TRUE` to speed up the process, or use `devtools::load_all()`. After installation, the package can be loaded and used like any other R package: ```{r, eval=FALSE} library("rstanlm") ``` ```{r} fit <- lm_stan(y = rnorm(10), x = rnorm(10), # arguments passed to sampling iter = 2000, refresh = 500) print(fit) ``` ```{r, echo=FALSE} unlink(PATH, recursive = TRUE, force = TRUE) ``` ## Advanced options Details can be found in the documentation for `rstan_create_package()` so we only mention some of these briefly here: * Running `rstan_create_package()` with `auto_config = TRUE` (the default value) automatically synchronizes the Stan C++ files with the `.stan` model files located in `inst/stan`, although this creates a dependency of your package on __rstantools__ itself (i.e., __rstantools__ must be installed for your package to work). Setting `auto_config = FALSE` removes this dependency, at the cost of having to manually synchronize Stan C++ files by running `rstan_config()` every time a package `.stan` file is added, removed, or even just modified. * The function `use_rstan()` can be used to add Stan functionality to an existing package, instead of building the package from scratch. ## Links * [_Guidelines for Developers of R Packages Interfacing with Stan_](https://mc-stan.org/rstantools/articles/developer-guidelines.html) * Ask a question at the [Stan Forums](https://discourse.mc-stan.org/) * [R packages](http://r-pkgs.had.co.nz/) by Hadley Wickham provides a solid foundation in R package development as well as the release process. rstantools/R/0000755000176200001440000000000013537013650012666 5ustar liggesusersrstantools/R/rstan_package_utils.R0000644000176200001440000001027113476042430017034 0ustar liggesusers# various helper functions for creating rstan-enabled packages # comment to put on top of rstantools system files. # deduce comment character based on file extension .rstantools_noedit <- function(file_name) { # comment character file_name <- basename(file_name) ext <- gsub(".*[.]", "", file_name) if (ext == file_name) ext <- "" com <- ifelse(tolower(ext) %in% c("r", "", "win"), "#", "//") paste0(com, " ", "Generated by rstantools. Do not edit by hand.") } # warning message not overwriting file .warning_nowrite <- function(file_name) { warning("'", file_name, "' already exists. Not overwritten by rstantools.", .call = FALSE) invisible(NULL) } # location of rstantools system files, # i.e., templates to be copied to user's package .system_file <- function(...) { system.file("include", "sys", ..., package = "rstantools") } # taken from Rcpp::compileAttributes # validates package directory .check_pkgdir <- function(pkgdir) { pkgdir <- normalizePath(pkgdir, winslash = "/") descFile <- file.path(pkgdir, "DESCRIPTION") if (!file.exists(descFile)) { stop("pkgdir must refer to the directory containing an R package.", call. = FALSE) } pkgdir } # create a stan directory # msg: display message if attempt to create is made # warn: warning if directory already exists # return value: whether or not directory was created .add_standir <- function(pkgdir, ..., msg = TRUE, warn = FALSE) { dir_name <- file.path(pkgdir, ...) acc <- FALSE if (file.exists(dir_name)) { if (!file.info(dir_name)$isdir) { stop(file.path(...), " exists but is not a directory.", call. = FALSE) } } else { if (msg) message("Creating ", file.path(...), " directory ...") acc <- dir.create(dir_name, recursive = TRUE, showWarnings = TRUE) # this should not happen... if (!acc) stop(file.path(...), " directory not created.", call. = FALSE) } if (warn && !acc) .warning_nowrite(file.path(basename(pkgdir), ...)) invisible(acc) } # add stan file consisting of character vector of file_lines # * don't overwrite unless first line of destination file is .rstantools_noedit # * only overwrite if file is not identical # noedit: add "rstantools file: don't edit" to first line of file # msg: display message if attempt to create is made # warn: waning if non-stan file of same name already exists # return value: whether or not file was successfully added .add_stanfile <- function(file_lines, pkgdir, ..., noedit = TRUE, msg = FALSE, warn = TRUE) { dest_file <- file.path(pkgdir, ...) noedit_msg <- .rstantools_noedit(dest_file) has_file <- file.exists(dest_file) # check if file exists # check if existing file is a stan file is_stanfile <- has_file && (readLines(dest_file, n = 1) == noedit_msg) if (has_file && !is_stanfile) { # non-stan file found: don't overwrite if (warn) .warning_nowrite(file.path(basename(pkgdir), ...)) acc <- FALSE } if (!has_file || is_stanfile) { if (noedit && (file_lines[1] != noedit_msg)) { # add "noedit" to top of file file_lines <- c(noedit_msg, "", file_lines) } if (is_stanfile) { # stan file found: check if it needs to be overwritten old_lines <- readLines(dest_file) acc <- !identical(paste0(old_lines, collapse = "\n"), paste0(file_lines, collapse = "\n")) } else acc <- TRUE if (acc) { # create/overwrite file if (msg) message("Adding ", basename(dest_file), " file ...") cat(file_lines, sep = "\n", file = dest_file) # can't this fail? } } ## acc <- has_file && !is_stanfile # create stan file if acc = TRUE ## if (acc) { ## # non-stan file found: don't overwrite ## if (warn) .warning_nowrite(file.path(basename(pkgdir), ...)) ## } else { ## # stan file found: only overwrite if changed ## if (noedit && (file_lines[1] != noedit_msg)) { ## # add "noedit" to top of file ## file_lines <- c(noedit_msg, "", file_lines) ## } ## old_lines <- readLines(dest_file) ## acc <- !identical(old_lines, file_lines) ## if (acc) { ## cat(file_lines, sep = "\n", file = dest_file) # can't this fail? ## } ## } invisible(acc) } rstantools/R/predictive_interval.R0000644000176200001440000000457013536772717017100 0ustar liggesusers#' Generic function for predictive intervals #' #' See [predictive_interval.stanreg()](https://mc-stan.org/rstanarm/reference/predictive_interval.stanreg.html) #' in the \pkg{rstanarm} package for an example. #' #' @export #' @template args-object #' @template args-dots #' @param prob A number \eqn{p \in (0,1)}{p (0 < p < 1)} indicating the desired #' probability mass to include in the intervals. #' #' @return `predictive_interval()` methods should return a matrix with two #' columns and as many rows as data points being predicted. For a given value #' of `prob`, \eqn{p}, the columns correspond to the lower and upper #' \eqn{100p}\% interval limits and have the names \eqn{100\alpha/2}\% and #' \eqn{100(1 - \alpha/2)}\%, where \eqn{\alpha = 1-p}. For example, if #' `prob=0.9` is specified (a \eqn{90}\% interval), then the column names #' would be `"5%"` and `"95%"`, respectively. #' #' The default method just takes `object` to be a matrix and computes #' quantiles, with `prob` defaulting to `0.9`. #' #' @template seealso-rstanarm-pkg #' @template seealso-vignettes #' #' @examples #' # Default method takes a numeric matrix (of draws from posterior #' # predictive distribution) #' ytilde <- matrix(rnorm(100 * 5, sd = 2), 100, 5) # fake draws #' predictive_interval(ytilde, prob = 0.8) #' #' # Also see help("predictive_interval", package = "rstanarm") #' predictive_interval <- function(object, ...) { UseMethod("predictive_interval") } #' @rdname predictive_interval #' @export predictive_interval.default <- function(object, prob = 0.9, ...) { if (!is.matrix(object)) stop("For the default method 'object' should be a matrix.") .central_intervals(object, prob) } # internal ---------------------------------------------------------------- #' Compute central intervals #' #' @noRd #' @param object A numeric matrix #' @param prob Probability mass to include in intervals (in (0,1)) #' @return See above. #' #' @importFrom stats quantile .central_intervals <- function(object, prob) { stopifnot(is.matrix(object)) if (length(prob) != 1L || prob <= 0 || prob >= 1) stop("'prob' should be a single number greater than 0 and less than 1.", call. = FALSE) alpha <- (1 - prob) / 2 probs <- c(alpha, 1 - alpha) labs <- paste0(100 * probs, "%") out <- t(apply(object, 2, quantile, probs = probs)) structure(out, dimnames = list(colnames(object), labs)) } rstantools/R/use_rstan.R0000644000176200001440000002333013476240016015015 0ustar liggesusers# Part of the rstantools package # Copyright (C) 2018 Martin Lysy # # rstantools is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 3 # of the License, or (at your option) any later version. # # rstantools is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # #' Add Stan infrastructure to an existing package #' #' Add Stan infrastructure to an existing \R package. To create a *new* package #' containing Stan programs use [rstan_create_package()] instead. #' #' @template args-pkgdir #' @template args-license #' @template args-auto_config #' #' @details Prepares a package to compile and use Stan code by performing the #' following steps: #' 1. Create `inst/stan` folder where all `.stan` files defining #' Stan models should be stored. #' 1. Create `inst/stan/include` where optional `license.stan` file is stored. #' 1. Create `inst/include/stan_meta_header.hpp` to include optional header #' files used by Stan code. #' 1. Create `src` folder (if it doesn't exist) to contain the Stan C++ code. #' 1. Create `R` folder (if it doesn't exist) to contain wrapper code to expose #' Stan C++ classes to \R. #' 1. Update `DESCRIPTION` file to contain all needed dependencies to compile #' Stan C++ code. #' 1. If `NAMESPACE` file is generic (i.e., created by [rstan_create_package()]), #' append `import(Rcpp, methods)`, `importFrom(rstan, sampling)`, #' and `useDynLib` directives. If `NAMESPACE` is not generic, display message #' telling user what to add to `NAMESPACE` for themselves. #' #' @template details-auto_config #' @template section-running-stan #' #' @return Invisibly, `TRUE` or `FALSE` indicating whether or not any files or #' folders where created or modified. #' #' @export use_rstan <- function(pkgdir = ".", license = TRUE, auto_config = TRUE) { pkgdir <- .check_pkgdir(pkgdir) # stan folders acc <- .add_standir(pkgdir, "inst", "stan", "include", msg = TRUE, warn = FALSE) acc <- acc | .add_standir(pkgdir, "inst", "include", msg = TRUE, warn = FALSE) acc <- acc | .add_standir(pkgdir, "src", msg = TRUE, warn = FALSE) acc <- acc | .add_standir(pkgdir, "R", msg = TRUE, warn = FALSE) # add license.stan license <- .make_license(pkgdir, license) if (!is.null(license)) { .add_stanfile(license, pkgdir, "inst", "stan", "include", "license.stan", noedit = FALSE, msg = FALSE, warn = FALSE) } # add stan_meta_header.hpp meta_header <- .system_file("stan_meta_header.hpp") .add_stanfile(readLines(meta_header), pkgdir, "inst", "include", "stan_meta_header.hpp", noedit = FALSE, msg = FALSE, warn = FALSE) # add stan_init.cpp # not needed for compiling without src/stan_files subdirectory ## acc <- acc | .add_staninit(pkgdir) # add packages to DESCRIPTION file acc <- acc | .update_description(pkgdir, auto_config = auto_config, msg = TRUE) # add or remove configure files acc <- acc | any(.setup_configure(pkgdir, auto_config)) # modify NAMESPACE, or output instructions for how to do so acc <- acc | .update_namespace(pkgdir, msg = TRUE) if (!acc) { message("Stan functionality is already enabled.") } else { message("Done.") } invisible(acc) } # make (or read) license file from logical/character specification .make_license <- function(pkgdir, license) { if (is.logical(license) && !license) { # license == FALSE license <- NULL } else { if (is.logical(license)) { # default license license <- readLines(system.file("include", "sys", "lice_nse.stan", package = "rstantools")) license <- gsub("RSTAN_PACKAGE_NAME", basename(pkgdir), license) } else if (is.character(license)) { license <- readLines(license) } else { stop("license must be logical or character string.", call. = FALSE) } } license } # either updates the existing NAMESPACE if it is generic, # or produces a message for needed modifications. # msg: display message if NAMESPACE needs to be modified # return value: whether or not NAMESPACE needed to be modified .update_namespace <- function(pkgdir, msg = TRUE) { # read namespace file namespc <- file.path(pkgdir, "NAMESPACE") namespc <- readLines(namespc) # required namespace lines req_lines <- c("import(Rcpp)", "import(methods)", "importFrom(rstan, sampling)", paste0("useDynLib(", basename(pkgdir), ", .registration = TRUE)")) ## lib_req <- c(methods = NA, rcpp = NA, dynlib = NA) if (.is_generic_namespace(namespc)) { # automatically update default NAMESPACE if (msg) message("Updating NAMESPACE ...") cat("# Generated by roxygen2: fake comment so roxygen2 overwrites silently.", namespc[!grepl("^#", namespc)], req_lines, file = file.path(pkgdir, "NAMESPACE"), sep = "\n") acc <- TRUE # namespace was modified } else { # print message stating required dependencies # format existing namespace with no white space # and one directive per line whitespc <- "[ \n\t\r\v\f]*" # any white space namespc <- namespc[!grepl("^#", namespc)] namespc <- paste0(namespc, collapse = "\n") namespc <- gsub(whitespc, "", namespc) namespc <- paste0(strsplit(namespc, split = "[)]")[[1]], ")") # check for namespace dependencies msg_lines <- NULL acc <- FALSE if (!.has_import(namespc, pkg = "Rcpp")) { # import(Rcpp) msg_lines <- c(msg_lines, req_lines[1]) acc <- TRUE } if (!.has_import(namespc, pkg = "methods")) { # import(methods) msg_lines <- c(msg_lines, req_lines[2]) acc <- TRUE } if (!.has_import(namespc, pkg = "rstan", fun = "sampling")) { # importFrom(rstan, sampling) msg_lines <- c(msg_lines, req_lines[3]) acc <- TRUE } dynlib <- paste0("^useDynLib[(]", basename(pkgdir), ",[.]registration=TRUE[)]") if (!any(grepl(dynlib, namespc))) { # useDynLib(RSTAN_PACKAGE_NAME, .registration = TRUE) msg_lines <- c(msg_lines, req_lines[4]) acc <- TRUE } if (acc && msg) { message("\nNext, add the following lines to your NAMESPACE:\n\n", paste0(msg_lines, collapse = "\n"), "\n") } } invisible(acc) } # whether or not namespc imports given pkg, or given fun from pkg # assume namespc has been white space formatted .has_import <- function(namespc, pkg, fun) { # check if whole package is imported import_pkg <- any(grepl("^import[(]", namespc) & grepl(paste0("(,|[(])", pkg, "(,|[)])"), namespc)) if (missing(fun)) { import_pkg } else { # check if given function is imported import_pkg || any(grepl(paste0("^importFrom[(]", pkg, ",", fun, "[)]"), namespc)) } } # check whether namespace is generic .is_generic_namespace <- function(namespc) { # package.skeleton generic gen1 <- "exportPattern(\"^[[:alpha:]]+\")" # create_package generic gen2 <- c("# Generated by roxygen2: fake comment so roxygen2 overwrites silently.", "exportPattern(\"^[^\\\\.]\")") identical(namespc, gen1) || identical(namespc, gen2) } # add or remove configure files .setup_configure <- function(pkgdir, add = TRUE) { conf_names <- c("configure", "configure.win") if (add) { acc <- sapply(conf_names, function(conf_name) { config <- readLines(.system_file(conf_name)) .add_stanfile(config, pkgdir, conf_name, noedit = TRUE, msg = FALSE, warn = TRUE) }) if (any(acc)) message("Adding 'configure' files ...") # make scripts executable sapply(conf_names[acc], function(conf_name) { system(paste0('chmod +x "', file.path(pkgdir, conf_name), '"')) }) } else { acc <- sapply(conf_names, function(conf_name) { noedit_msg <- .rstantools_noedit(conf_name) conf_name <- file.path(pkgdir, conf_name) if (file.exists(conf_name) && (readLines(conf_name, n = 1) == noedit_msg)) { file.remove(conf_name) # Stan file found. remove it } else FALSE # no stan file found }) if (any(acc)) message("Removing 'configure' files ...") } acc } #------------------------------------------------------------------------------- # compile work flow # 0. optionally create package with package.skeleton. # delete man files so install.packages produces no errors. # 1. create necessary dirs. # don't need to warn if they already exist, because nothing happens # then anyways. Add stan_meta_header.hpp and stan_init.cpp at this stage? # 2. update NAMESPACE. if NAMESPACE doesn't exist or is default exportPattern, # add useDynLib and import(Rcpp, methods). # Otherwise, tell user what's left to be done. # 3. add stan_files if any. # 4. configure stan_files specific compile + export instructions, i.e., # Makevars[.win] and stanmodels.R. If no stan_files are present, # these files should be removed. # question: what happens when no stan_files are present? # i think stan_init.cpp should still be present. otherwise, package doesn't # compile if NAMESPACE has useDynLib. how about stan_meta_header.cpp? # let's say for now just have it. rstantools/R/predictive_error.R0000644000176200001440000000355213536772663016404 0ustar liggesusers#' Generic function and default method for predictive errors #' #' Generic function and default method for computing predictive errors #' \eqn{y - y^{rep}}{y - yrep} (in-sample, for observed \eqn{y}) or #' \eqn{y - \tilde{y}}{y - ytilde} (out-of-sample, for new or held-out \eqn{y}). #' See [predictive_error.stanreg()](https://mc-stan.org/rstanarm/reference/predictive_error.stanreg.html) #' in the \pkg{rstanarm} package for an example. #' #' @export #' @template args-object #' @template args-dots #' @return `predictive_error()` methods should return a \eqn{D} by \eqn{N} #' matrix, where \eqn{D} is the number of draws from the posterior predictive #' distribution and \eqn{N} is the number of data points being predicted per #' draw. #' #' The default method just takes `object` to be a matrix and `y` to be a #' vector. #' #' @template seealso-rstanarm-pkg #' @template seealso-vignettes #' #' @examples #' # default method #' y <- rnorm(10) #' ypred <- matrix(rnorm(500), 50, 10) #' pred_errors <- predictive_error(ypred, y) #' dim(pred_errors) #' head(pred_errors) #' #' # Also see help("predictive_error", package = "rstanarm") #' predictive_error <- function(object, ...) { UseMethod("predictive_error") } #' @rdname predictive_error #' @export #' @param y For the default method, a vector of `y` values the same length as #' the number of columns in the matrix used as `object`. predictive_error.default <- function(object, y, ...) { if (!is.matrix(object)) stop("For the default method 'object' should be a matrix.") .pred_errors(object, y) } # internal ---------------------------------------------------------------- # @param object A matrix # @param y A vector the same length as ncol(object) .pred_errors <- function(object, y) { stopifnot(is.matrix(object), length(y) == ncol(object)) sweep(-1 * object, MARGIN = 2, STATS = as.array(y), FUN = "+") } rstantools/R/zzz.R0000644000176200001440000000021013464642671013651 0ustar liggesusers.onAttach <- function(...) { ver <- utils::packageVersion("rstantools") packageStartupMessage("This is rstantools version ", ver) } rstantools/R/posterior_predict.R0000644000176200001440000000150213536772625016564 0ustar liggesusers#' Generic function for drawing from the posterior predictive distribution #' #' Draw from the posterior predictive distribution of the outcome. See #' [posterior_predict.stanreg()](https://mc-stan.org/rstanarm/reference/posterior_predict.stanreg.html) #' in the \pkg{rstanarm} package for an example. #' #' @export #' @template args-object #' @template args-dots #' @return `posterior_predict()` methods should return a \eqn{D} by \eqn{N} #' matrix, where \eqn{D} is the number of draws from the posterior predictive #' distribution and \eqn{N} is the number of data points being predicted per #' draw. #' #' @template seealso-rstanarm-pkg #' @template seealso-vignettes #' #' @examples #' # See help("posterior_predict", package = "rstanarm") #' posterior_predict <- function(object, ...) { UseMethod("posterior_predict") } rstantools/R/rstantools-package.R0000644000176200001440000000177113476240220016615 0ustar liggesusers#' Tools for Developing \R Packages Interfacing with Stan #' #' @name rstantools-package #' @aliases rstantools #' @docType package #' #' @description #' \if{html}{ #' \figure{stanlogo.png}{options: width="50px" alt="mc-stan.org"} #' } *Stan Development Team* #' #' The \pkg{rstantools} package provides various tools for developers of \R #' packages interfacing with Stan (), including #' functions to set up the required package structure, S3 generic methods to #' unify function naming across Stan-based \R packages, and vignettes with #' guidelines for developers. To get started building a package see #' [rstan_create_package()]. #' #' @template seealso-vignettes #' @template seealso-get-help #' @template seealso-useR2016-video #' NULL # internal ---------------------------------------------------------------- # release reminders (for devtools) release_questions <- function() { # nocov start c( "Have you updated the developer guidelines in the vignette?" ) } # nocov end rstantools/R/rstan_config.R0000644000176200001440000002753713536507127015511 0ustar liggesusers# rstan_config # Copyright (C) 2018 Martin Lysy # # rstantools is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 3 # of the License, or (at your option) any later version. # # rstantools is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # #' Configure system files for compiling Stan source code #' #' Creates or update package-specific system files to compile `.stan` model #' files found in `inst/stan`. #' #' @export #' @template args-pkgdir #' @details The Stan source files for the package should be stored in: #' \itemize{ #' \item `inst/stan` for `.stan` files containing instructions to #' build a `stanmodel` object. #' \item `inst/stan/any_subfolder` for files to be included via the #' `#include "/my_subfolder/mylib.stan"` directive. #' \item `inst/stan/any_subfolder` for a `license.stan` file. #' \item `inst/include` for the `stan_meta_header.hpp` file, to be #' used for directly interacting with the Stan C++ libraries. #' } #' #' @return Invisibly, whether or not any files were added/removed/modified by #' the function. #' rstan_config <- function(pkgdir = ".") { pkgdir <- .check_pkgdir(pkgdir) # check if package root directory # get stan model files stan_files <- list.files(file.path(pkgdir, "inst", "stan"), full.names = TRUE, pattern = "\\.stan$") if (length(stan_files) != 0) { # add R & src folders in case run from configure[.win] script .add_standir(pkgdir, "R", msg = FALSE, warn = FALSE) .add_standir(pkgdir, "src", msg = FALSE, warn = FALSE) # convert all .stan files to .cc/.hpp pairs sapply(stan_files, .make_cc, pkgdir = pkgdir) # update package Makevars acc <- .setup_Makevars(pkgdir, add = TRUE) ## .add_Makevars(pkgdir) ## .add_Makevars(pkgdir, win = TRUE) } else { # no stan files, so get rid of Makevars acc <- .setup_Makevars(pkgdir, add = FALSE) ## mkv_files <- file.path(pkgdir, "src", c("Makevars", "Makevars.win")) ## mkv_files <- mkv_files[file.exists(mkv_files)] ## if(length(mkv_files) > 0) file.remove(mkv_files) } # remove any .cc/.hpp/.o triplets with no corresponding .stan file acc <- any(acc) | .rm_cc(pkgdir) # register exported modules as native routines Rcpp::compileAttributes(pkgdir) # update R/stanmodels.R with current set of models stanmodels <- .update_stanmodels(pkgdir) acc <- acc | .add_stanfile(stanmodels, pkgdir, "R", "stanmodels.R") invisible(acc) } #--- helper functions ---------------------------------------------------------- # prefix for stan C++ files .stan_prefix <- function(..., start = FALSE) { paste0(ifelse(start, "^", ""), "stanExports_", ...) } # file basename without extension .basename_noext <- function(file_names) { gsub(pattern = "(.*?)\\..*$", replacement = "\\1", basename(file_names)) } # removes any Stan-generated files in src which don't correspond to a model in # /inst/stan .rm_cc <- function(pkgdir) { # stan model files stan_files <- list.files(file.path(pkgdir, "inst", "stan"), full.names = FALSE, pattern = "*[.]stan$") # all files in src all_files <- list.files(file.path(pkgdir, "src"), full.names = FALSE) # reduce to stan model files src_files <- all_files[grepl("*[.](cc|h)$", all_files)] src_files <- src_files[grepl(.stan_prefix(start=TRUE), src_files)] # make sure 1st line is "don't edit" src_line1 <- sapply(file.path(pkgdir, "src", src_files), readLines, n = 1) src_files <- src_files[(src_line1 == .rstantools_noedit("foo.h")) | (src_line1 == .rstantools_noedit("foo.cc"))] # stan model names corresponding to inactive stan files rm_names <- gsub(.stan_prefix(start=TRUE), "", src_files) rm_names <- unique(gsub("[.](cc|h)$", "", rm_names)) rm_names <- rm_names[!(rm_names %in% gsub("[.]stan$", "", stan_files))] if (length(rm_names) > 0) { # get all cc/h/o files in src corresponding to these models rm_files <- c(outer(.stan_prefix(rm_names), c(".cc", ".h", ".o"), paste0)) # and finally the files to remove rm_files <- all_files[all_files %in% rm_files] acc <- file.remove(file.path(pkgdir, "src", rm_files)) acc <- any(acc) } else { acc <- FALSE } acc } # creates Makevars[.win] file with Stan-specific compile instructions # namely, location of StanHeaders and BH libraries, # and subfolder compile instructions. .add_Makevars <- function(pkgdir, win = FALSE) { mkv_name <- paste0("Makevars", if(win) ".win" else "") makevars <- readLines(.system_file(mkv_name)) # replace generic line "SOURCES = ..." with package-specific line # not needed for compiling without src/stan_files subdirectory ## src_line <- list.files(file.path(pkgdir, "inst", "stan"), ## pattern = "*[.]stan$") ## if(length(src_line) > 0) { ## src_line <- gsub("[.]stan$", ".cc", file.path("stan_files", src_line)) ## makevars[grep("^SOURCES", makevars)] <- paste0(c("SOURCES =", src_line), ## collapse = " ") ## } .add_stanfile(makevars, pkgdir, "src", mkv_name, noedit = TRUE, msg = FALSE, warn = TRUE) ## invisible(makevars) } # if add = TRUE, creates Makevars[.win] file with Stan-specific compile instructions. # if add = FALSE, deletes these files if they have not been modified by user. # return: whether or not file(s) were successfully added/removed .setup_Makevars <- function(pkgdir, add = TRUE) { noedit_msg <- .rstantools_noedit("foo") if (add) { acc <- sapply(c("Makevars", "Makevars.win"), function(mkv_name) { makevars <- readLines(.system_file(mkv_name)) .add_stanfile(makevars, pkgdir, "src", mkv_name, noedit = TRUE, msg = FALSE, warn = TRUE) }) } else { acc <- sapply(c("Makevars", "Makevars.win"), function(mkv_name) { noedit_msg <- .rstantools_noedit(mkv_name) mkv_name <- file.path(pkgdir, "src", mkv_name) if(file.exists(mkv_name) && (readLines(mkv_name, n = 1) == noedit_msg)) { file.remove(mkv_name) # Stan file found. remove it } else FALSE # no stan file found }) } acc } # create .cc/.h pair from .stan file # the .hpp file contains the C++ level class definition of the given stanmodel # the .cc file contains the module definition which Rcpp uses to construct # the corresponding R ReferenceClass. .make_cc <- function(file_name, pkgdir) { model_name <- sub("[.]stan$", "", basename(file_name)) # model name ## path to src/stan_files ## stan_path <- file.path(pkgdir, "src", "stan_files") # create c++ code cppcode <- rstan::stanc(file_name, allow_undefined = TRUE, obfuscate_model_name = FALSE)$cppcode cppcode <- scan(text = cppcode, what = character(), sep = "\n", quiet = TRUE) class_declaration <- grep("^class[[:space:]]+[A-Za-z_]", cppcode) cppcode <- append(cppcode, values = "#include ", after = class_declaration - 1L) # get license file (if any) stan_license <- .read_license(dirname(file_name)) # Stan header file hdr_name <- .stan_prefix(model_name, ".h") .add_stanfile(file_lines = c(stan_license, "#ifndef MODELS_HPP", "#define MODELS_HPP", "#define STAN__SERVICES__COMMAND_HPP", "#include ", cppcode, "#endif"), pkgdir = pkgdir, "src", hdr_name, noedit = TRUE, msg = FALSE, warn = TRUE) # create Rcpp module exposing C++ class as R ReferenceClass suppressMessages({ cpp_lines <- utils::capture.output( Rcpp::exposeClass(class = paste0("model_", model_name), constructors = list(c("SEXP", "SEXP", "SEXP")), fields = character(), methods = c("call_sampler", "param_names", "param_names_oi", "param_fnames_oi", "param_dims", "param_dims_oi", "update_param_oi", "param_oi_tidx", "grad_log_prob", "log_prob", "unconstrain_pars", "constrain_pars", "num_pars_unconstrained", "unconstrained_param_names", "constrained_param_names", "standalone_gqs"), file = stdout(), header = paste0('#include "', hdr_name, '"'), module = paste0("stan_fit4", model_name, "_mod"), CppClass = "rstan::stan_fit ", Rfile = FALSE) ) }) .add_stanfile(file_lines = cpp_lines, pkgdir = pkgdir, "src", .stan_prefix(model_name, ".cc"), noedit = TRUE, msg = FALSE, warn = TRUE) return(invisible(NULL)) } # read license file (if any) .read_license <- function(stan_path) { # look for any file named license.stan stan_license <- dir(stan_path, pattern = "^license[.]stan$", recursive = TRUE, ignore.case = TRUE, full.names = TRUE) if (length(stan_license) > 1) { stop("Multiple license.stan files detected.", call. = FALSE) } else if(length(stan_license) == 0) { stan_license <- NULL } else { stan_license <- readLines(stan_license) } stan_license } # rewrites stanmodels.R reflecting current list of stan files .update_stanmodels <- function(pkgdir) { model_names <- list.files(file.path(pkgdir, "inst", "stan"), pattern = "*.stan$") model_names <- gsub("[.]stan$", "", model_names) if (length(model_names) == 0) { stanmodels <- .rstantools_noedit("stanmodels.R") } else { stanmodels <- readLines(.system_file("stanmodels.R")) # lines for Rcpp::loadModule load_line <- grep("^# load each stan module$", stanmodels) load_module <- sapply(model_names, gsub, pattern = "STAN_MODEL_NAME", x = stanmodels[load_line+1], USE.NAMES = FALSE) # line for stanmodels assignment model_names <- paste0("\"", model_names, "\"") model_names <- paste0(model_names, collapse = ", ") model_names <- paste0("c(", model_names, ")", collapse = "") model_line <- grep("^# names of stan models$", stanmodels) model_names <- gsub("\"STAN_MODEL_NAME\"", model_names, stanmodels[model_line+1]) # add new lines to stanmodels nlines <- length(stanmodels) stanmodels <- c(stanmodels[1:model_line], model_names, stanmodels[(model_line+2):load_line], load_module, stanmodels[(load_line+2):nlines]) } stanmodels } rstantools/R/rstan_create_package.R0000644000176200001440000002532013536745200017142 0ustar liggesusers# Part of the rstantools package # Copyright (C) 2018, 2019 Martin Lysy # Copyright (C) 2019 Trustees of Columbia University # # rstantools is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 3 # of the License, or (at your option) any later version. # # rstantools is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # #' Create a new \R package with compiled Stan programs #' #' @aliases rstan_package_skeleton #' #' @description #' \if{html}{\figure{stanlogo.png}{options: width="25px" alt="https://mc-stan.org/about/logo/"}} #' The `rstan_create_package()` function helps get you started developing a #' new \R package that interfaces with Stan via the \pkg{rstan} package. First #' the basic package structure is set up via [usethis::create_package()]. #' Then several adjustments are made so the package can include Stan programs #' that can be built into binary versions (i.e., pre-compiled Stan C++ code). #' #' The **Details** section below describes the process and the #' **See Also** section provides links to recommendations for developers #' and a step-by-step walk-through. #' #' As of version `2.0.0` of \pkg{rstantools} the #' `rstan_package_skeleton()` function is defunct and only #' `rstan_create_package()` is supported. #' #' @export #' @param path The path to the new package to be created (terminating in the #' package name). #' @param fields,rstudio,open Same as [usethis::create_package()]. See #' the documentation for that function, especially the note in the #' **Description** section about the side effect of changing the active #' project. #' @param stan_files A character vector with paths to `.stan` files to include #' in the package. #' @param roxygen Should \pkg{roxygen2} be used for documentation? Defaults to #' `TRUE`. If so, a file `R/{pkgname}-package.R`` is added to the package with #' roxygen tags for the required import lines. See the **Note** section below #' for advice specific to the latest versions of \pkg{roxygen2}. #' @param travis Should a `.travis.yml` file be added to the package directory? #' Defaults to `TRUE`. While the file contains some presets to help with #' compilation issues, at present it is not guaranteed to work on #' [travis-ci](https://travis-ci.org/) without manual adjustments. #' @template args-license #' @template args-auto_config #' #' @details #' This function first creates a regular \R package using #' `usethis::create_package()`, then adds the infrastructure required to compile #' and export `stanmodel` objects. In the package root directory, the user's #' Stan source code is located in: #' \preformatted{ #' inst/ #' |_stan/ #' | |_include/ #' | #' |_include/ #' } #' All `.stan` files containing instructions to build a `stanmodel` #' object must be placed in `inst/stan`. Other `.stan` files go in #' any `stan/` subdirectory, to be invoked by Stan's `#include` #' mechanism, e.g., #' \preformatted{ #' #include "include/mylib.stan" #' #include "data/preprocess.stan" #' } #' See \pkg{rstanarm} for many examples. #' #' The folder `inst/include` is for all user C++ files associated with the #' Stan programs. In this folder, the only file to directly interact with the #' Stan C++ library is `stan_meta_header.hpp`; all other `#include` #' directives must be channeled through here. #' #' The final step of the package creation is to invoke #' [rstan_config()], which creates the following files for #' interfacing with Stan objects from \R: #' \itemize{ #' \item `src` contains the `stan_ModelName{.cc/.hpp}` pairs #' associated with all `ModelName.stan` files in `inst/stan` which #' define `stanmodel` objects. #' \item `src/Makevars[.win]` which link to the `StanHeaders` and #' Boost (`BH`) libraries. #' \item `R/stanmodels.R` loads the C++ modules containing the #' `stanmodel` class definitions, and assigns an \R instance of each #' `stanmodel` object to a `stanmodels` list (with names #' corresponding to the names of the Stan files). #' } #' @template details-auto_config #' @template details-license #' @details Authors willing to license their Stan programs of general interest #' under the GPL are invited to contribute their `.stan` files and #' supporting \R code to the \pkg{rstanarm} package. #' #' @template section-running-stan #' #' @note For \pkg{devtools} users, because of changes in the latest versions of #' \pkg{roxygen2} it may be necessary to run `pkgbuild::compile_dll()` #' once before `devtools::document()` will work. #' #' @seealso #' * [use_rstan()] for adding Stan functionality to an existing #' \R package and [rstan_config()] for updating an existing package #' when its Stan files are changed. #' * The \pkg{rstanarm} package [repository](https://github.com/stan-dev/rstanarm) #' on GitHub. #' @template seealso-vignettes #' @template seealso-get-help #' @template seealso-useR2016-video #' rstan_create_package <- function(path, fields = NULL, rstudio = TRUE, open = TRUE, stan_files = character(), roxygen = TRUE, travis = TRUE, license = TRUE, auto_config = TRUE) { if (!requireNamespace("usethis", quietly = TRUE)) { stop("Please install package 'usethis' to use function 'rstan_create_package'.", call. = FALSE) } DIR <- dirname(path) name <- basename(path) .check_stan_ext(stan_files) if (rstudio && !requireNamespace("rstudioapi", quietly = TRUE)) { stop("Please install package 'rstudioapi' to use option 'rstudio = TRUE'.", call. = FALSE) rstudio <- rstudio && rstudioapi::isAvailable() } if (open && rstudio) { on.exit(rstudioapi::openProject(file.path(DIR, name), newSession = TRUE)) } # run usethis::create_package() if (file.exists(path)) { stop("Directory '", DIR, "' already exists.", call. = FALSE) } message("Creating package skeleton for package: ", name, domain = NA) suppressMessages( usethis::create_package( path = path, fields = fields, rstudio = rstudio, open = FALSE ) ) # add Stan-specific functionality to the new package pkgdir <- .check_pkgdir(file.path(DIR, name)) .rstan_make_pkg(pkgdir, stan_files, roxygen, travis, license, auto_config) invisible(NULL) } #--- helper functions ---------------------------------------------------------- # check stan extensions .check_stan_ext <- function(stan_files) { if (length(stan_files) && !all(grepl("\\.stan$", stan_files))) { stop("All files named in 'stan_files' must end ", "with a '.stan' extension.", call. = FALSE) } } # add travis file .add_travis <- function(pkgdir) { travis_file <- readLines(.system_file("travis.yml")) .add_stanfile(gsub("RSTAN_PACKAGE_NAME", basename(pkgdir), travis_file), pkgdir, ".travis.yml", noedit = FALSE, msg = TRUE, warn = FALSE) # also create an .Rbuildignore for travis file .add_stanfile("^\\.travis\\.yml$", pkgdir, ".Rbuildignore", noedit = FALSE, msg = FALSE, warn = FALSE) } # add R/mypkg-package.R file with roxygen import comments # also add Encoding: UTF-8 to DESCRIPTION .add_roxygen <- function(pkgdir) { pkg_file <- readLines(.system_file("rstanpkg-package.R")) pkg_file <- gsub("RSTAN_PACKAGE_NAME", basename(pkgdir), pkg_file) pkg_file <- gsub("RSTAN_REFERENCE", .rstan_reference(), pkg_file) .add_stanfile(pkg_file, pkgdir, "R", paste0(basename(pkgdir), "-package.R"), noedit = FALSE, msg = TRUE, warn = FALSE) desc_pkg <- desc::description$new(file.path(pkgdir, "DESCRIPTION")) desc_pkg$set(Encoding = "UTF-8") desc_pkg$write() } # reference to rstan package .rstan_reference <- function() { has_version <- utils::packageDescription("rstan", fields = "Version") version_year <- substr(utils::packageDescription("rstan", fields = "Date"), 1, 4) paste0( "Stan Development Team (", version_year,"). ", "RStan: the R interface to Stan. ", "R package version ", has_version, ". ", "https://mc-stan.org" ) } # add stan functionality to package .rstan_make_pkg <- function(pkgdir, stan_files, roxygen, travis, license, auto_config) { use_rstan(pkgdir, license = license, auto_config = auto_config) file.copy( from = stan_files, to = file.path(pkgdir, "inst", "stan", basename(stan_files)) ) if (roxygen) .add_roxygen(pkgdir) if (travis) .add_travis(pkgdir) message("Configuring Stan compile and module export instructions ...") rstan_config(pkgdir) cat( readLines(.system_file("Read_and_delete_me")), "\n", file = file.path(pkgdir, "Read-and-delete-me"), sep = "\n", append = TRUE ) message( domain = NA, sprintf( "Further Stan-specific steps are described in '%s'.", file.path(basename(pkgdir), "Read-and-delete-me") ) ) } #------------------------------------------------------------------------------- ## outline of steps: ## 1. run package skeleton. ## - rm man files ## 2. create stan_dirs. ## - inst/stan ## - inst/stan/include ## - inst/include ## - src/stan_files ## - if (!exists) message ## 3. add default files. ## - src/stan_init.cpp ## - inst/include/stan_meta_header.cpp ## 4. update NAMESPACE ## - if (default) modify else message(remaining steps) ## 5. update DESCRIPTION ## - if (modified) message else do_nothing ## 4. add stan_files ## 5. configure build ## - make src/stan_files/*.{cc/hpp} ## only overwrite if different ## - add src/Makevars[.win] ## only overwrite if different ## - add R/stanmodels.R ## - if (is_empty(inst/stan)) no Makevars, empty stanmodels.R ## messages: ## - when creating directories ## - when updating DESCRIPTION or NAMESPACE ## - when adding files? sometimes ## warnings: ## - when attempting to overwrite non-stan file with stan file of same name ## error: ## - when {dir/file}.create fails even though it doesn't exist ## ok stan_meta_header.hpp is problematic, because want to warn if already exists, but only if it's there from before... ## so .add_stanfile(file_lines, pkgdir, ..., ## noedit = TRUE, msg = FALSE, warn = TRUE) rstantools/R/posterior_interval.R0000644000176200001440000000367513536772531016767 0ustar liggesusers#' Generic function and default method for posterior uncertainty intervals #' #' These intervals are often referred to as credible intervals, but we use the #' term uncertainty intervals to highlight the fact that wider intervals #' correspond to greater uncertainty. See #' [posterior_interval.stanreg()](https://mc-stan.org/rstanarm/reference/posterior_interval.stanreg.html) #' in the \pkg{rstanarm} package for an example. #' #' @export #' @template args-object #' @template args-dots #' @param prob A number \eqn{p \in (0,1)}{p (0 < p < 1)} indicating the desired #' probability mass to include in the intervals. #' #' @return `posterior_interval()` methods should return a matrix with two #' columns and as many rows as model parameters (or a subset of parameters #' specified by the user). For a given value of `prob`, \eqn{p}, the #' columns correspond to the lower and upper \eqn{100p}\% interval limits and #' have the names \eqn{100\alpha/2}\% and \eqn{100(1 - \alpha/2)}\%, where #' \eqn{\alpha = 1-p}. For example, if `prob=0.9` is specified (a #' \eqn{90}\% interval), then the column names would be `"5%"` and #' `"95%"`, respectively. #' #' The default method just takes `object` to be a matrix (one column per #' parameter) and computes quantiles, with `prob` defaulting to `0.9`. #' #' @template seealso-rstanarm-pkg #' @template seealso-vignettes #' #' @examples #' # Default method takes a numeric matrix (of posterior draws) #' draws <- matrix(rnorm(100 * 5), 100, 5) # fake draws #' colnames(draws) <- paste0("theta_", 1:5) #' posterior_interval(draws) #' #' # Also see help("posterior_interval", package = "rstanarm") #' posterior_interval <- function(object, ...) { UseMethod("posterior_interval") } #' @rdname posterior_interval #' @export posterior_interval.default <- function(object, prob = 0.9, ...) { if (!is.matrix(object)) stop("For the default method 'object' should be a matrix.") .central_intervals(object, prob) } rstantools/R/bayes_R2.R0000644000176200001440000000365013536772316014475 0ustar liggesusers#' Generic function and default method for Bayesian R-squared #' #' Generic function and default method for Bayesian version of R-squared for #' regression models. A generic for LOO-adjusted R-squared is also provided. See #' the [bayes_R2.stanreg()](https://mc-stan.org/rstanarm/reference/bayes_R2.stanreg.html) #' method in the \pkg{rstanarm} package for an example of defining a method. #' #' @export #' @template args-object #' @template args-dots #' #' @return `bayes_R2()` and `loo_R2()` methods should return a vector of #' length equal to the posterior sample size. #' #' The default `bayes_R2()` method just takes `object` to be a matrix of y-hat #' values (one column per observation, one row per posterior draw) and `y` to #' be a vector with length equal to `ncol(object)`. #' #' #' @references #' Andrew Gelman, Ben Goodrich, Jonah Gabry, and Aki Vehtari (2018). R-squared #' for Bayesian regression models. *The American Statistician*, to appear. #' DOI: 10.1080/00031305.2018.1549100. #' ([Preprint](http://www.stat.columbia.edu/~gelman/research/published/bayes_R2_v3.pdf), #' [Notebook](https://avehtari.github.io/bayes_R2/bayes_R2.html)) #' #' #' @template seealso-rstanarm-pkg #' @template seealso-vignettes #' bayes_R2 <- function(object, ...) { UseMethod("bayes_R2") } #' @rdname bayes_R2 #' @export #' @param y For the default method, a vector of `y` values the same length #' as the number of columns in the matrix used as `object`. #' #' @importFrom stats var #' bayes_R2.default <- function(object, y, ...) { if (!is.matrix(object)) stop("For the default method 'object' should be a matrix.") stopifnot(NCOL(y) == 1, ncol(object) == length(y)) ypred <- object e <- -1 * sweep(ypred, 2, y) var_ypred <- apply(ypred, 1, var) var_e <- apply(e, 1, var) var_ypred / (var_ypred + var_e) } #' @rdname bayes_R2 #' @export loo_R2 <- function(object, ...) { UseMethod("loo_R2") } rstantools/R/posterior_linpred.R0000644000176200001440000000206113536772327016567 0ustar liggesusers#' Generic function for accessing the posterior distribution of the linear #' predictor #' #' Extract the posterior draws of the linear predictor, possibly transformed by #' the inverse-link function. See #' [posterior_linpred.stanreg()](https://mc-stan.org/rstanarm/reference/posterior_linpred.stanreg.html) #' in the \pkg{rstanarm} package for an example. #' #' @export #' @template args-object #' @template args-dots #' @param transform Should the linear predictor be transformed using the #' inverse-link function? The default is `FALSE`, in which case the #' untransformed linear predictor is returned. #' @return `posterior_linpred()` methods should return a \eqn{D} by \eqn{N} #' matrix, where \eqn{D} is the number of draws from the posterior #' distribution distribution and \eqn{N} is the number of data points. #' #' @template seealso-rstanarm-pkg #' @template seealso-vignettes #' #' @examples #' # See help("posterior_linpred", package = "rstanarm") #' posterior_linpred <- function(object, transform = FALSE, ...) { UseMethod("posterior_linpred") } rstantools/R/log_lik.R0000644000176200001440000000171613536772311014443 0ustar liggesusers#' Generic function for pointwise log-likelihood #' #' We define a new function `log_lik()` rather than a #' [stats::logLik()] method because (in addition to the conceptual #' difference) the documentation for `logLik()` states that the return value #' will be a single number, whereas `log_lik()` returns a matrix. See #' the [log_lik.stanreg()](https://mc-stan.org/rstanarm/reference/log_lik.stanreg.html) #' method in the \pkg{rstanarm} package for an example of defining a method. #' #' @export #' @template args-object #' @template args-dots #' #' @return `log_lik()` methods should return a \eqn{S} by \eqn{N} matrix, #' where \eqn{S} is the size of the posterior sample (the number of draws from #' the posterior distribution) and \eqn{N} is the number of data points. #' #' @template seealso-rstanarm-pkg #' @template seealso-vignettes #' #' @examples #' # See help("log_lik", package = "rstanarm") #' log_lik <- function(object, ...) { UseMethod("log_lik") } rstantools/R/loo-functions.R0000644000176200001440000000377213476237277015640 0ustar liggesusers#' Generic functions for LOO predictions #' #' See the methods in the \pkg{rstanarm} package for examples. #' #' @name loo-prediction #' #' @template args-object #' @template args-dots #' #' @return `loo_predict()`, `loo_linpred()`, and `loo_pit()` #' (probability integral transform) methods should return a vector with length #' equal to the number of observations in the data. #' `loo_predictive_interval()` methods should return a two-column matrix #' formatted in the same way as for [predictive_interval()]. #' #' @template seealso-rstanarm-pkg #' @template seealso-vignettes #' #' @rdname loo-prediction #' @export loo_linpred <- function(object, ...) { UseMethod("loo_linpred") } #' @rdname loo-prediction #' @export loo_predict <- function(object, ...) { UseMethod("loo_predict") } #' @rdname loo-prediction #' @export loo_predictive_interval <- function(object, ...) { UseMethod("loo_predictive_interval") } #' @rdname loo-prediction #' @export loo_pit <- function(object, ...) { UseMethod("loo_pit") } #' @rdname loo-prediction #' @export #' @param y For the default method of `loo_pit()`, a vector of `y` values the #' same length as the number of columns in the matrix used as `object`. #' @param lw For the default method of `loo_pit()`, a matrix of log-weights of #' the same length as the number of columns in the matrix used as `object`. #' loo_pit.default <- function(object, y, lw, ...) { if (!is.matrix(object)) stop("For the default method 'object' should be a matrix.") stopifnot( is.numeric(object), is.numeric(y), length(y) == ncol(object), is.matrix(lw), identical(dim(lw), dim(object)) ) .loo_pit(y = y, yrep = object, lw = lw) } # internal ---------------------------------------------------------------- .loo_pit <- function(y, yrep, lw) { vapply(seq_len(ncol(yrep)), function(j) { sel <- yrep[, j] <= y[j] .exp_log_sum_exp(lw[sel, j]) }, FUN.VALUE = 1) } .exp_log_sum_exp <- function(x) { m <- suppressWarnings(max(x)) exp(m + log(sum(exp(x - m)))) } rstantools/R/init_cpp.R0000644000176200001440000000466313476234635014641 0ustar liggesusers# Part of the rstantools package # Copyright (C) 2018 Trustees of Columbia University # # rstantools is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 3 # of the License, or (at your option) any later version. # # rstantools is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #' Register functions implemented in C++ #' #' If you set up your package using `rstan_package_skeleton()` before #' version `1.2.1` of \pkg{rstantools} it may be necessary for you to call #' this function yourself in order to pass `R CMD check` in \R #' `>= 3.4`. If you used `rstan_package_skeleton()` in \pkg{rstantools} version #' `1.2.1` or later then this has already been done automatically. #' #' @export #' @param name The name of your package as a string. #' @param path The path to the root directory for your package as a string. If #' not specified it is assumed that this is already the current working #' directory. #' @return This function is only called for its side effect of writing the #' necessary `init.cpp` file to the package's `src/` directory. #' init_cpp <- function(name, path) { file <- file.path("src", "init.cpp") if (!missing(path)) file <- file.path(path, file) cat( "// Generated by the rstantools package\n\n", "#include ", "#include ", "#include ", "#include ", "#include ", sep = "\n", file = file, append = FALSE ) cat( "\n\nstatic const R_CallMethodDef CallEntries[] = {", " {NULL, NULL, 0}", "};", sep = "\n", file = file, append = TRUE ) cat( paste0("\n\nvoid attribute_visible R_init_", name, "(DllInfo *dll) {"), " // next line is necessary to avoid a NOTE from R CMD check", " R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);", " R_useDynamicSymbols(dll, TRUE); // necessary for .onLoad() to work", "}", sep = "\n", file = file, append = TRUE ) } rstantools/R/prior_summary.R0000644000176200001440000000165313536772757015751 0ustar liggesusers#' Generic function for extracting information about prior distributions #' #' See [prior_summary.stanreg()](https://mc-stan.org/rstanarm/reference/prior_summary.stanreg.html) #' in the \pkg{rstanarm} package for an example. #' #' @export #' @template args-object #' @template args-dots #' #' @return `prior_summary()` methods should return an object containing #' information about the prior distribution(s) used for the given model. #' The structure of this object will depend on the method. #' #' The default method just returns `object$prior.info`, which is #' `NULL` if there is no `'prior.info'` element. #' #' @template seealso-rstanarm-pkg #' @template seealso-vignettes #' #' @examples #' # See help("prior_summary", package = "rstanarm") #' prior_summary <- function(object, ...) { UseMethod("prior_summary") } #' @rdname prior_summary #' @export prior_summary.default <- function(object, ...) { object$prior.info } rstantools/R/update_description.R0000644000176200001440000001071113476235453016707 0ustar liggesusers#' Update `DESCRIPTION` to include all packages required to compile Stan code. #' #' @noRd #' @param pkgdir Package root directory. #' @param auto_config Whether or not package should configure itself. This #' means importing `rstantools` for linking via `configure[.win]`) and setting #' `Biarch: true` in the `DESCRIPTION`. #' @param msg Whether or not to display a message if an attempt to update #' `DESCRIPTION` is made. #' #' @return Whether or not `DESCRIPTION` file was modified. #' #' @details Sanitizes the package dependencies as follows: #' \itemize{ #' \item If `rstantools` dependency version is lower, don't update #' existing dependency. #' \item If `rstantools` `Imports` dependency already exists in #' `Depends`, keep the `Depends` package but increase version if #' needed. #' } #' #' Issues the following messages: #' \itemize{ #' \item If `auto_config = FALSE` and `rstantools` is imported. #' \item If `auto_config = FALSE` and `Biarch: true`. #' } #' .update_description <- function(pkgdir, auto_config = FALSE, msg = TRUE) { # current desc file desc_pkg <- desc::description$new(file.path(pkgdir, "DESCRIPTION")) # save a copy desc_old <- desc::description$new(file.path(pkgdir, "DESCRIPTION")) # rstantools desc file desc_rstan <- desc::description$new(.system_file("DESCRIPTION")) # check for Biarch field has_biarch <- desc_pkg$has_fields("Biarch") if(!auto_config) { # check for rstantools dependence has_rstantools <- desc_pkg$has_dep("rstantools", type = "Imports") || desc_pkg$has_dep("rstantools", type = "Depends") # check if Biarch: true has_biarch <- has_biarch && tolower(desc_pkg$get_field("Biarch")) == "true" # don't add dependence on rstantools desc_rstan$del_dep("rstantools", type = "Imports") } else { # use latest version of rstantools desc_rstan$set_dep("rstantools", type = "Imports", version = paste0(">= ", utils::packageVersion("rstantools"))) # add Biarch: true for multiarch Windows desc_pkg$set(Biarch = "true") } # update dependencies dep_pkg <- desc_pkg$get_deps() names(dep_pkg)[3] <- "vpkg" dep_rstan <- desc_rstan$get_deps() names(dep_rstan)[3] <- "vrstan" # convert all rstan Imports to Depends if they are in package Depends di <- dep_rstan$package %in% dep_pkg$package[dep_pkg$type == "Depends"] dep_rstan$type[di & dep_rstan$type == "Imports"] <- "Depends" # combine all dependencies dep_comb <- merge(x = dep_pkg, y = dep_rstan, by = c("type", "package"), all = TRUE) # larger version of each package dep_comb <- cbind(dep_comb[1:2], version = .version_max(dep_comb$vpkg, dep_comb$vrstan)) desc_pkg$set_deps(dep_comb) # add additional elements from template DESCRIPTION file extra_fields <- c("SystemRequirements", "Encoding") do.call(desc_pkg$set, as.list(desc_rstan$get(extra_fields))) # check if description has changed acc <- !identical(desc_pkg$str(), desc_old$str()) if(acc) { if(msg) message("Updating DESCRIPTION ...") desc_pkg$write() ## cat(desc_pkg$str(normalize = FALSE), "\n", ## file = file.path(pkgdir, "DESCRIPTION")) ## dep_fields <- dep_fields[dep_fields %in% colnames(desc_pkg)] ## write.dcf(desc_pkg, file = file.path(pkgdir, "DESCRIPTION"), ## keep.white = dep_fields) } if(!auto_config && msg) { if(has_rstantools) { message("'Import: rstantools' detected in DESCRIPTION with 'auto_config = FALSE'.\n", "If you did not add this dependence yourself then it's safe to remove it.\n") } if(has_biarch) { message("'Biarch: true' detected in DESCRIPTION with 'auto_config = FALSE'.\n", "If you did not add this line yourself then it's safe to remove it.\n") } } invisible(acc) } # return greater of two version numbers in desc::desc_get_dep format .version_max <- function(ver1, ver2) { # convert non-existing/any version packages to 0 ver1 <- gsub("^[^[:digit:]]*([[:digit:]]*)", replacement = "\\1", ver1) ver1[is.na(ver1) | ver1 == ""] <- 0 ver2 <- gsub("^[^[:digit:]]*([[:digit:]]*)", replacement = "\\1", ver2) ver2[is.na(ver2) | ver2 == ""] <- 0 # take greater of two versions vmax <- mapply(function(x, y) utils::compareVersion(x, y) >= 0, x = ver1, y = ver2) vmax <- ifelse(vmax, ver1, ver2) ifelse(vmax == "0", "*", paste0(">= ", vmax)) } rstantools/R/nsamples.R0000644000176200001440000000042313335364554014642 0ustar liggesusers#' Generic function for extracting the number of posterior samples #' #' Extract the number of posterior samples stored in a fitted Bayesian model. #' #' @export #' @template args-object #' @template args-dots #' nsamples <- function(object, ...) { UseMethod("nsamples") } rstantools/NEWS.md0000644000176200001440000000634113476034341013571 0ustar liggesusers# rstantools 2.0.0 * Added Martin Lysy as a coauthor. * New function `rstan_create_package()` (based on `usethis::create_package()`) replaces `rstan_package_skeleton()` for the purpose of starting a new package with Stan functionality. * Stan functionality can be added to an _existing_ package by calling `use_rstan()` instead of starting a new package from scratch. * Stan folder infrastructure now puts all `.stan` files in `inst/stan` and all auto-generated C++ files directly in `src`. This last step ensures that custom **Rcpp** source code can coexist with the Stan C++ code. * Each time a `.stan` file gets added/removed/modified requires a call to `rstan_config()` in order to generate the Stan C++ code and `Rcpp::loadModule()` calls. However, setting `auto_config = TRUE` (the default) in `rstan_create_package()` ensures `rstan_config()` is called whenever the package is installed (including via `devtools::load_all()`), so no need to call it manually unless the user wishes to inspect the Stan C++ code for issues. * **roxygen2** documentation is now optional, but remains the default. * Rather than generating Stan "system files" via `cat` commands, **rstantools** now stores these as template files in `inst/include/sys`, so the build process can be easily modified as improvements become apparent. # rstantools 1.5.1 (Github issue/PR numbers in parentheses) * Fix issue related to changes in the **usethis** package by removing the `fields` argument to `rstan_package_skeleton()` and setting it internally instead. * New generic `nsamples()` (#35) # rstantools 1.5.0 (Github issue/PR numbers in parentheses) * New [vignette](http://mc-stan.org/rstantools/articles/) walking through the package creation process. (#9) (thanks to Stefan Siegert) * `rstan_package_skeleton()` now calls `usethis::create_package()` instead of `utils::package.skeleton()`. (#28) * Update `rstan_package_skeleton()` for latest build process (#19) * `rstan_package_skeleton()` now does a bit more work for the user to make sure the the NAMESPACE file is correct. * Simplify instructions in Read-and-delete-me (related to #19). # rstantools 1.4.0 (Github issue/PR numbers in parentheses) * Update `rstan_package_skeleton()` to correspond to rstanarm 2.17.2. # rstantools 1.3.0 (Github issue/PR numbers in parentheses) * Add `bayes_R2()` generic and default method. (#8) # rstantools 1.2.1 (Github issue/PR numbers in parentheses) * Add `init_cpp()` function for generating `src/init.cpp` in order to pass R CMD check in R 3.4.x. `rstan_package_skeleton()` calls `init_cpp()` internally. (#6) # rstantools 1.2.0 (Github issue/PR numbers in parentheses) * Minor fixes to `rstan_package_skeleton()` for better Windows compatibility. (#1, #2) * Fix some typos in the developer guidelines vignette. (#3, #4) * Add `loo_predict()`, `loo_linpred()`, and `loo_predictive_interval()` generics in preparation for adding methods to the __rstanarm__ package. (#5) # rstantools 1.1.0 Changes to `rstan_package_skeleton`: * Add comment in `Read-and-delete-me` about importing all of __Rcpp__ and __methods__ packages. * Include __methods__ in `Depends` field of `DESCRIPTION` file. * Also download __rstanarm__'s `Makevars.win` file. # rstantools 1.0.0 * Initial CRAN release rstantools/MD50000644000176200001440000001204513537300535013000 0ustar liggesusers4a0f6863caa0eb348a72d5accff51775 *DESCRIPTION 3ad873069c880bb4e609e2a3eb8bf001 *NAMESPACE b98b941d2f26d64564440046439881f7 *NEWS.md a2729001ee333c5ac75021472caeeb61 *R/bayes_R2.R f49b763eb02ee8598eb44667ed6f6c08 *R/init_cpp.R 45561b9fa670d9884d99362f8887de19 *R/log_lik.R ff980b18072694d9a0719e0464aae5d1 *R/loo-functions.R 14b0f921eecaa8aeee0f08fbc069fbed *R/nsamples.R 992d35d7977ff1d704fce459f56cc16b *R/posterior_interval.R 79092614b76b8f9764bd44cfe01ef7ed *R/posterior_linpred.R 8a2e981c66fd6df3b0986e1fc7fdff55 *R/posterior_predict.R 705477b48b5b8abe06ba0eb918953948 *R/predictive_error.R 621f19e1281bd866ec4844fa0d03b623 *R/predictive_interval.R 9ae1775818a277228d8b6b8efcfe8ece *R/prior_summary.R cd83e2c07e2a037f43a7b92f799b31c8 *R/rstan_config.R 3ffee6a322f7e0af551415dbb3185609 *R/rstan_create_package.R 11ad4ed869e46711e9f9afe7f77abde6 *R/rstan_package_utils.R 74be3bdb339b342e26dda0ddb8ff9787 *R/rstantools-package.R d12cdc77151e94ea31c825e76f3d549e *R/update_description.R 883ddb7acfea37a8373517088bf21116 *R/use_rstan.R 48020d152473c6a5bff717745d0167d6 *R/zzz.R 387713d421440632d82f1d21b2cb1dc3 *build/vignette.rds a9d9805c350492e9207498dd1fdc3754 *inst/doc/developer-guidelines.Rmd 8b005ae2b6b77db99b88a35956c4a733 *inst/doc/developer-guidelines.html 2cc5aa04263ab3c2919899d8c99e02f2 *inst/doc/minimal-rstan-package.R c20cd9acaf43f5b0158112207768dd24 *inst/doc/minimal-rstan-package.Rmd f2698d7c8dbc1287e3a8a6720a706fb2 *inst/doc/minimal-rstan-package.html 6e266b5b1e791fb17d914156081a627a *inst/include/sys/DESCRIPTION 6431f3c9054e741340944c0565871316 *inst/include/sys/Makevars bd1c7dfd19c9e861a4f0f478654784fe *inst/include/sys/Makevars.win 949dbefdb5cef3795d4bf215ce1236f1 *inst/include/sys/Read_and_delete_me 9f81dd2a43743a5e4485ed69d4043a3b *inst/include/sys/configure df46ef4eb0907011e9c28549a3bfd2b3 *inst/include/sys/configure.win 75ffb5c994a87f400ca9b9be4559409a *inst/include/sys/lice_nse.stan 34f7c67f3a929e33019ab78504856d6d *inst/include/sys/rstanpkg-package.R 855c064dbf8deaff96c8dc8a87169109 *inst/include/sys/stan_meta_header.hpp 009e845cdd7bcbae6123810390b18acf *inst/include/sys/stanmodels.R bcda1436702c2d39b590818e3bec9129 *inst/include/sys/travis.yml e7340f4f5567b038ba241a2d6e46180f *man/bayes_R2.Rd 5fad10a5cc62c59ea429a5ce90191e2e *man/figures/stanlogo.png bbf9cc7a20064b829f2088456a29ce39 *man/init_cpp.Rd 9aac16966ddd34a169c9828202f77b07 *man/log_lik.Rd d58dc5c8bae99b33e40ec43848323295 *man/loo-prediction.Rd d304e29544efd6632a2a693a840d201c *man/nsamples.Rd c3e4e472fdc87ef69a8657a2b74c7aa8 *man/posterior_interval.Rd aba7c41c550e7edd176e5cbfe37fb2ed *man/posterior_linpred.Rd 7ecd24caf29a9974b484299089273568 *man/posterior_predict.Rd 24730619ce85614a10d7881cdd7e4ffc *man/predictive_error.Rd 5f171287e3533b6a78aff2a9a454b6f5 *man/predictive_interval.Rd 384a986bb7295edcebfd3490c9729c56 *man/prior_summary.Rd 8dbe55b384d48d545794cc20ae710f3b *man/rstan_config.Rd e0a66cdc06d5a4c48499d07eec28dd63 *man/rstan_create_package.Rd b231094a3f0cfb0f02ea2b45dd2cea7d *man/rstantools-package.Rd 2c3f625d6dd482363c5ad48b95a7d383 *man/use_rstan.Rd 7bfe6bc761702dc166dab061923201f2 *tests/testthat.R 31b2f4c84ef26ec1f991556c9b0b7fbc *tests/testthat/RStanTest/AddTest.cpp 2e7b8c4d6d88db0afd3cfff9c5791b9b *tests/testthat/RStanTest/NAMESPACE b246b36b972b2826818733204ad1be09 *tests/testthat/RStanTest/RStanTest-package.R 5b3542df84df018ddffffe6ddbf037d2 *tests/testthat/RStanTest/SimpleModel.stan ce54485879f063efc193171840c2a6cd *tests/testthat/RStanTest/SimpleModel2.stan b713069525a11a2bdf142dc53d77502d *tests/testthat/RStanTest/helper.stan c457739e23c4de32279426a2b857d8c6 *tests/testthat/RStanTest/postsamp.R 2a590807f995f59a852e76bc5f5adb9a *tests/testthat/RStanTest/stanExports_SimpleModel.cc 64dbf7e41488b4961fb3b38662c45a48 *tests/testthat/RStanTest/stanExports_SimpleModel.h 4a3c7ece9e19a2b9dc889826f1186593 *tests/testthat/RStanTest/stanExports_SimpleModel2.cc 7fbefd2e6e9298d4ed0fb1752298f7e6 *tests/testthat/RStanTest/stanExports_SimpleModel2.h c77a9ebd4ac196cb3f1e6dde315329c3 *tests/testthat/RStanTest/test-add_test.R 7212f2a288ad8342076664c73c25b589 *tests/testthat/RStanTest/test-postsamp.R 7074849d234f11737dcc2bafa2493c01 *tests/testthat/RStanTest/test-rstan_package_skeleton_plus.R 5240a7688d03c1e78bf732fae8205f80 *tests/testthat/bayes_R2.RDS fb60e130dde02de0ed070ea7e1ca017d *tests/testthat/loo_pit.RDS cd4e5b56448c46bab1a7c8198aa836ff *tests/testthat/posterior_interval.RDS 9cdb24b6c5e4c8bd007906ae4d542fe7 *tests/testthat/predictive_error.RDS 580bc37134d86759af033e69fe59bb64 *tests/testthat/predictive_interval.RDS 516013d59a1b04743f6174cc9dbc0c68 *tests/testthat/rstan_package_skeleton-testfunctions.R e68986fc8df9b444438460be1de76695 *tests/testthat/test-default-methods.R 4be8d5f8be7a1cd99f1bf204cad5bc36 *tests/testthat/test-generics-with-no-methods.R f5d8838fdaf262191bc5ba8c6ccc83d2 *tests/testthat/test-rstan_config.R 920315e5c793a620a167946e8a28582d *tests/testthat/test-rstan_create_package.R 67b5a06d2aff7fc4c788183227de31d0 *tests/testthat/test.stan a9d9805c350492e9207498dd1fdc3754 *vignettes/developer-guidelines.Rmd c20cd9acaf43f5b0158112207768dd24 *vignettes/minimal-rstan-package.Rmd rstantools/inst/0000755000176200001440000000000013537013647013450 5ustar liggesusersrstantools/inst/doc/0000755000176200001440000000000013537013647014215 5ustar liggesusersrstantools/inst/doc/minimal-rstan-package.html0000644000176200001440000007160313537013647021256 0ustar liggesusers Step by step guide for creating a package that depends on RStan

Step by step guide for creating a package that depends on RStan

Stefan Siegert, Jonah Gabry, Martin Lysy, and Ben Goodrich

2019-09-13

Introduction

In this vignette we will walk through the steps necessary for creating an R package that depends on Stan by creating a package with one function that fits a simple linear regression. Before continuing, we recommend that you first read the other vignette Guidelines for Developers of R Packages Interfacing with Stan.

Creating the package skeleton

The rstantools package offers two methods for adding Stan functionality to R packages:

  • rstan_create_package(): set up a new R package with Stan programs
  • use_rstan(): add Stan functionality to an existing R package

Here we will use rstan_create_package() to initialize a bare-bones package directory. The name of our demo package will be rstanlm; it will fit a simple linear regression model using Stan.

This is rstantools version 2.0.0
Creating package skeleton for package: rstanlm
✔ Creating '/var/folders/h6/14xy_35x4wd2tz542dn0qhtc0000gn/T/Rtmp5FRRjQ/rstanlm/'
✔ Setting active project to '/private/var/folders/h6/14xy_35x4wd2tz542dn0qhtc0000gn/T/Rtmp5FRRjQ/rstanlm'
✔ Creating 'R/'
✔ Writing 'DESCRIPTION'
Package: rstanlm
Title: What the Package Does (One Line, Title Case)
Version: 0.0.0.9000
Authors@R (parsed):
    * First Last <first.last@example.com> [aut, cre] (<https://orcid.org/YOUR-ORCID-ID>)
Description: What the package does (one paragraph).
License: What license it uses
Encoding: UTF-8
LazyData: true
✔ Writing 'NAMESPACE'
✔ Setting active project to '<no active project>'
Creating inst/stan/include directory ...
Creating inst/include directory ...
Creating src directory ...
Updating DESCRIPTION ...
Adding 'configure' files ...
Updating NAMESPACE ...
Done.
Adding rstanlm-package.R file ...
Adding .travis.yml file ...
Configuring Stan compile and module export instructions ...
Further Stan-specific steps are described in 'rstanlm/Read-and-delete-me'.

If we had existing .stan files to include with the package we could use the optional stan_files argument to rstan_create_package() to include them. Another option, which we’ll use below, is to add the Stan files once the basic structure of the package is in place.

We can now set the new working directory to the new package directory and view the contents. (Note: if using RStudio then by default the newly created project for the package will be opened in a new session and you will not need the call to setwd().)

 [1] "."                  ".."                 ".Rbuildignore"     
 [4] ".travis.yml"        "DESCRIPTION"        "NAMESPACE"         
 [7] "R"                  "Read-and-delete-me" "configure"         
[10] "configure.win"      "inst"               "src"               
Package: rstanlm
Title: What the Package Does (One Line, Title Case)
Version: 0.0.0.9000
Authors@R: 
    person(given = "First",
           family = "Last",
           role = c("aut", "cre"),
           email = "first.last@example.com",
           comment = c(ORCID = "YOUR-ORCID-ID"))
Description: What the package does (one paragraph).
License: What license it uses
Encoding: UTF-8
LazyData: true
Biarch: true
Depends: 
    R (>= 3.4.0)
Imports: 
    Rcpp (>= 0.12.0),
    methods,
    rstan (>= 2.18.1),
    rstantools (>= 2.0.0)
LinkingTo: 
    BH (>= 1.66.0),
    Rcpp (>= 0.12.0),
    RcppEigen (>= 0.3.3.3.0),
    StanHeaders (>= 2.18.0),
    rstan (>= 2.18.1)
SystemRequirements: GNU make

Some of the sections in the DESCRIPTION file need to be edited by hand (e.g., Title, Author, Maintainer, and Description, but these also can be set with the fields argument to rstan_create_package()). However, rstan_create_package() has added the necessary packages and versions to Depends, Imports, and LinkingTo to enable Stan functionality.

Read-and-delete-me file

Before deleting the Read-and-delete-me file in the new package directory make sure to read it because it contains some important instructions about customizing your package:

Stan-specific notes:

* All '.stan' files containing stanmodel definitions must be placed in 'inst/stan'.
* Additional files to be included by stanmodel definition files
  (via e.g., #include "mylib.stan") must be placed in any subfolder of 'inst/stan'.
* Additional C++ files needed by any '.stan' file must be placed in 'inst/include',
  and can only interact with the Stan C++ library via '#include' directives
  placed in the file 'inst/include/stan_meta_header.hpp'.
* The precompiled stanmodel objects will appear in a named list called 'stanmodels',
  and you can call them with e.g., 'rstan::sampling(stanmodels$foo, ...)'

You can move this file out of the directory, delete it, or list it in the .Rbuildignore file if you want to keep it in the directory.

[1] TRUE

Stan files

Our package will call rstan’s sampling() method to use MCMC to fit a simple linear regression model for an outcome variable y with a single predictor x. After writing the necessary Stan program, the file should be saved with a .stan extension in the inst/stan subdirectory. We’ll save the following program to inst/stan/lm.stan:

// Save this file as inst/stan/lm.stan
data {
  int<lower=1> N;
  vector[N] x;
  vector[N] y;
}
parameters {
  real intercept;
  real beta;
  real<lower=0> sigma;
}
model {
  // ... priors, etc.

  y ~ normal(intercept + beta * x, sigma);
}

The inst/stan subdirectory can contain additional Stan programs if required by your package. During installation, all Stan programs will be compiled and saved in the list stanmodels that can then be used by R function in the package. The rule is that the Stan program compiled from the model code in inst/stan/foo.stan is stored as list element stanmodels$foo. Thus, the filename of the Stan program in the inst/stan directory should not contain spaces or dashes and nor should it start with a number or utilize non-ASCII characters.

R files

We next create the file R/lm_stan.R where we define the function lm_stan() in which our compiled Stan model is being used. Setting the rstan_create_package() argument roxygen = TRUE (the default value) enables roxygen2 documentation for the package functions. The following comment block placed in lm_stan.R ensures that the function has a help file and that it is added to the package NAMESPACE:

When roxygen2 documentation is enabled, a top-level package file R/rstanlm-package.R is created by rstan_create_package() to import necessary functions for other packages and to set up the package for compiling Stan C++ code:

#' The 'rstanlm' package.
#'
#' @description A DESCRIPTION OF THE PACKAGE
#'
#' @docType package
#' @name rstanlm-package
#' @aliases rstanlm
#' @useDynLib rstanlm, .registration = TRUE
#' @import methods
#' @import Rcpp
#' @importFrom rstan sampling
#'
#' @references
#' Stan Development Team (2019). RStan: the R interface to Stan. R package version 2.19.2. https://mc-stan.org
#'
NULL

The #' @description section can be manually edited to provided specific information about the package.

Documentation

With roxygen documentation enabled, we need to generate the documentation for lm_stan and update the NAMESPACE so the function is exported, i.e., available to users when the package is installed. This can be done with the function roxygen2::roxygenize().

Updating roxygen version in /private/var/folders/h6/14xy_35x4wd2tz542dn0qhtc0000gn/T/Rtmp5FRRjQ/rstanlm/DESCRIPTION
Writing NAMESPACE
Loading rstanlm
Writing NAMESPACE
Writing lm_stan.Rd
Writing rstanlm-package.Rd

Note: For newer versions of roxygen, it is necessary to compile the package C++ code prior to running roxygen2::roxygenize(). One way to do this is with pkgbuild::compile_dll(), as above.

Install and use

Finally, the package is ready to be installed:

Installing package into '/private/var/folders/h6/14xy_35x4wd2tz542dn0qhtc0000gn/T/Rtmp5TldLP/Rinst5344624b1ccd'
(as 'lib' is unspecified)

It is also possible to use devtools::install(quick=FALSE) to install the package. The argument quick=FALSE is necessary if you want to recompile the Stan models. Going forward, if you only make a change to the R code or the documentation, you can set quick=TRUE to speed up the process, or use devtools::load_all().

After installation, the package can be loaded and used like any other R package:


SAMPLING FOR MODEL 'lm' NOW (CHAIN 1).
Chain 1: 
Chain 1: Gradient evaluation took 2e-05 seconds
Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 0.2 seconds.
Chain 1: Adjust your expectations accordingly!
Chain 1: 
Chain 1: 
Chain 1: Iteration:    1 / 2000 [  0%]  (Warmup)
Chain 1: Iteration:  500 / 2000 [ 25%]  (Warmup)
Chain 1: Iteration: 1000 / 2000 [ 50%]  (Warmup)
Chain 1: Iteration: 1001 / 2000 [ 50%]  (Sampling)
Chain 1: Iteration: 1500 / 2000 [ 75%]  (Sampling)
Chain 1: Iteration: 2000 / 2000 [100%]  (Sampling)
Chain 1: 
Chain 1:  Elapsed Time: 0.02515 seconds (Warm-up)
Chain 1:                0.022369 seconds (Sampling)
Chain 1:                0.047519 seconds (Total)
Chain 1: 

SAMPLING FOR MODEL 'lm' NOW (CHAIN 2).
Chain 2: 
Chain 2: Gradient evaluation took 5e-06 seconds
Chain 2: 1000 transitions using 10 leapfrog steps per transition would take 0.05 seconds.
Chain 2: Adjust your expectations accordingly!
Chain 2: 
Chain 2: 
Chain 2: Iteration:    1 / 2000 [  0%]  (Warmup)
Chain 2: Iteration:  500 / 2000 [ 25%]  (Warmup)
Chain 2: Iteration: 1000 / 2000 [ 50%]  (Warmup)
Chain 2: Iteration: 1001 / 2000 [ 50%]  (Sampling)
Chain 2: Iteration: 1500 / 2000 [ 75%]  (Sampling)
Chain 2: Iteration: 2000 / 2000 [100%]  (Sampling)
Chain 2: 
Chain 2:  Elapsed Time: 0.022902 seconds (Warm-up)
Chain 2:                0.020798 seconds (Sampling)
Chain 2:                0.0437 seconds (Total)
Chain 2: 

SAMPLING FOR MODEL 'lm' NOW (CHAIN 3).
Chain 3: 
Chain 3: Gradient evaluation took 5e-06 seconds
Chain 3: 1000 transitions using 10 leapfrog steps per transition would take 0.05 seconds.
Chain 3: Adjust your expectations accordingly!
Chain 3: 
Chain 3: 
Chain 3: Iteration:    1 / 2000 [  0%]  (Warmup)
Chain 3: Iteration:  500 / 2000 [ 25%]  (Warmup)
Chain 3: Iteration: 1000 / 2000 [ 50%]  (Warmup)
Chain 3: Iteration: 1001 / 2000 [ 50%]  (Sampling)
Chain 3: Iteration: 1500 / 2000 [ 75%]  (Sampling)
Chain 3: Iteration: 2000 / 2000 [100%]  (Sampling)
Chain 3: 
Chain 3:  Elapsed Time: 0.021081 seconds (Warm-up)
Chain 3:                0.018546 seconds (Sampling)
Chain 3:                0.039627 seconds (Total)
Chain 3: 

SAMPLING FOR MODEL 'lm' NOW (CHAIN 4).
Chain 4: 
Chain 4: Gradient evaluation took 5e-06 seconds
Chain 4: 1000 transitions using 10 leapfrog steps per transition would take 0.05 seconds.
Chain 4: Adjust your expectations accordingly!
Chain 4: 
Chain 4: 
Chain 4: Iteration:    1 / 2000 [  0%]  (Warmup)
Chain 4: Iteration:  500 / 2000 [ 25%]  (Warmup)
Chain 4: Iteration: 1000 / 2000 [ 50%]  (Warmup)
Chain 4: Iteration: 1001 / 2000 [ 50%]  (Sampling)
Chain 4: Iteration: 1500 / 2000 [ 75%]  (Sampling)
Chain 4: Iteration: 2000 / 2000 [100%]  (Sampling)
Chain 4: 
Chain 4:  Elapsed Time: 0.021034 seconds (Warm-up)
Chain 4:                0.017995 seconds (Sampling)
Chain 4:                0.039029 seconds (Total)
Chain 4: 
Inference for Stan model: lm.
4 chains, each with iter=2000; warmup=1000; thin=1; 
post-warmup draws per chain=1000, total post-warmup draws=4000.

           mean se_mean   sd   2.5%   25%   50%   75% 97.5% n_eff Rhat
intercept  0.03    0.01 0.57  -1.12 -0.32  0.03  0.39  1.17  1990    1
beta      -0.09    0.01 0.54  -1.21 -0.42 -0.10  0.23  1.01  2524    1
sigma      1.56    0.01 0.51   0.90  1.22  1.46  1.78  2.85  1744    1
lp__      -8.09    0.04 1.52 -12.18 -8.79 -7.70 -6.97 -6.35  1232    1

Samples were drawn using NUTS(diag_e) at Fri Sep 13 18:26:47 2019.
For each parameter, n_eff is a crude measure of effective sample size,
and Rhat is the potential scale reduction factor on split chains (at 
convergence, Rhat=1).

Advanced options

Details can be found in the documentation for rstan_create_package() so we only mention some of these briefly here:

  • Running rstan_create_package() with auto_config = TRUE (the default value) automatically synchronizes the Stan C++ files with the .stan model files located in inst/stan, although this creates a dependency of your package on rstantools itself (i.e., rstantools must be installed for your package to work). Setting auto_config = FALSE removes this dependency, at the cost of having to manually synchronize Stan C++ files by running rstan_config() every time a package .stan file is added, removed, or even just modified.

  • The function use_rstan() can be used to add Stan functionality to an existing package, instead of building the package from scratch.

rstantools/inst/doc/developer-guidelines.Rmd0000644000176200001440000002631013537000245020764 0ustar liggesusers--- title: "Guidelines for Developers of R Packages Interfacing with Stan" author: "Stan Development Team" date: "Latest release: `r format(Sys.Date(), format = '%B %Y')` (First version: November 2016)" output: rmarkdown::html_vignette: toc: true vignette: > %\VignetteIndexEntry{Developer Guidelines} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ## Note to developers One of the coolest things about working on a project like Stan has been seeing some of our users begin to develop tools for making Stan more accessible to audiences that may otherwise not benefit from what Stan offers. In particular, recently we have started seeing a growing number of R packages that provide high-level interfaces to Stan, using the [__rstan__](https://mc-stan.org/rstan) package for estimating models without requiring that the user be familiar with the Stan modeling language itself. This is a great development and we would like to support such efforts going forward, but to-date we have made little effort to coordinate the development of these packages. To avoid a Wild West, so to speak, of Stan-based R packages, we think it is important that developers make every effort to adhere to certain guidelines in order to ensure these packages are of the highest possible quality and provide the best possible experience for users. To that end, in this post we present a set of recommendations for the development of R packages that interface with Stan. These recommendations are based on software design principles we value as well as many things we are learning as we continue developing our __rstanarm__ package and review packages being developed by others. Of course anyone is free to develop a package based on Stan, even if they ignore these recommendations. However, both because we feel strongly about these recommendations and because we are seeing an increase in the number of requests for help (and our time is unfortunately limited), we will loosely enforce these guidelines by 1. prioritizing giving feedback to developers who follow them over those who choose not to, and 2. refraining from promoting packages that ignore them. That said, we are open to some limited exceptions (e.g., the __brms__ package is a sensible exception to one of guidelines about Stan code). If you think your package should be an exception definitely let us know. ## Guidelines for R packages providing interfaces to Stan ### General package structure and development * The __rstantools__ package provides the `rstan_create_package()` function, which you should use to create the basic structure of your package. (As of `v2.0.0` this replaces the `rstan_package_skeleton` function.) This will set up a package with functionality for pre-compiled Stan programs, in the style of the [__rstanarm__](https://mc-stan.org/rstanarm) package (source code: https://github.com/stan-dev/rstanarm). * Use version control (e.g., git). * Unless you are developing proprietary private software, organize your code in a repository that is _public_ on [GitHub](https://github.com/) (or a similar service, but preferably GitHub). It should be public even at early stages of development, not only when officially released. We recommend you add a note to your README file on how to install the development version of your package, like in the [__bayesplot__ README](https://github.com/stan-dev/bayesplot#installation) * Unit testing is essential. There are several R packages that make it relatively easy to write tests for your package. Most of our R packages (e.g., __rstanarm__, __brms__, __bayesplot__, __shinystan__, __loo__) use the [__testthat__](https://github.com/r-lib/testthat) package for this purpose, but if you prefer a different testing framework that's fine. The [__covr__](https://github.com/r-lib/covr) package is useful for calculating the line coverage of your tests, and we recommend reaching a high level of coverage before releasing a package. Good line coverage does not guarantee high quality tests, but it's a good first step. ### Stan code * All Stan code for estimating models should be included in pre-written static `.stan` files that are compiled when the package is built (see the Stan programs directory in the __rstanarm__ repo for examples). You can also use subdirectories to include code chunks to be used in multiple `.stan` files (again see the __rstanarm__ repo for examples). If you set up your package using `rstan_create_package` this structure will be created for you. This means that __your package should NOT write a Stan program when the user calls a model fitting function in your package__, but rather use only Stan programs you have written by hand in advance (if you are working on a model for which you don't think this is possible please let us know). There are several reasons for this. * Pre-compiled Stan programs can be run by users of Windows or Mac OSX without having to install a C++ compiler, which dramatically expands the universe of potential users for your package. * Pre-compiled Stan programs will run immediately when called, avoiding compilation time. * CRAN policy permits long installation times but imposes restrictions on the time consumed by examples and unit tests that are much shorter than the time that it takes to compile even a simple Stan program. Thus, it is only possible to adequately test your package if it has pre-compiled Stan programs. * Pre-compiled Stan programs can use custom C++ functions. To provide flexibility to users, your Stan programs can include branching logic (conditional statements) so that even with a small number of .stan files you can still allow for many different specifications to made by the user (see the .stan files in __rstanarm__ for examples). * Use best practices for Stan code. If the models you intend to implement are discussed in the Stan manual or on the Stan users forum then you should follow any recommendations that apply to your case. If you are unsure whether your Stan programs can be made more efficient or more numerically stable then please ask us on the Stan users forum. Especially ask us if you are unsure whether your Stan programs are indeed estimating the intended model. * Relatedly, prioritize safety over speed in your Stan code and sampler settings. For example, if you can write a program that runs faster but is potentially less stable, then at a minimum you should make the more stable version the default. This also means that, with rare exceptions, you should not change our recommended MCMC defaults (e.g. 4 chains, 1000+1000 iterations, NUTS not static HMC), unless you are setting the defaults to something more conservative. __rstanarm__ even goes one step further, making the default value of the `adapt_delta` tuning parameter at least 0.95 for all models (rather than __rstan__'s default of 0.8) in order to reduce the step size and therefore also limit the potential for divergences. This means that __rstanarm__ models may often run a bit slower than they need to if the user doesn't change the defaults, but it also means that users face fewer situations in which they need to know how to change the defaults and what the implications of changing the defaults really are. ### R code and documentation * Functions that provide useful post-estimation functionality should be given the same names as the corresponding functions in __rstanarm__ (if applicable). For example, `posterior_predict()` to draw from the posterior predictive distribution, `posterior_interval()` for posterior uncertainty intervals, etc. To make this easier, these and similar __rstanarm__ functions have been converted to S3 methods for the stanreg objects created by __rstanarm__ and the S3 generic functions are included here in the __rstantools__ package. Your package should import the generics from __rstantools__ for whichever functions you want to include in your package and then provide methods for the fitted model objects returned by your model-fitting functions. For some other functions (e.g. `as.matrix`) the generics are already available in base R or core R packages. To be clear, we are not saying that the naming conventions used in __rstanarm__/__rstantools__ are necessarily optimal. (If you think that one of our function names should be changed please let us know and suggest an alternative. If it is a substantial improvement we may consider renaming the function and deprecating the current version.) Rather, this guideline is intended to make function names consistent across Stan-based R packages, which will improve the user experience for those users who want to take advantage of a variety of these packages. It will be a mess if every R package using Stan has different names for the same functionality. * The [__bayesplot__](https://mc-stan.org/bayesplot/) package serves as the back-end for plotting for __rstanarm__ (see for example `pp_check.stanreg` and `plot.stanreg`), __brms__, and other packages, and we hope developers of other Stan-based R packages will also use it. You can see all the other R packages using __bayesplot__ in the _Reverse dependencies_ section of the __bayesplot__ [CRAN page](https://CRAN.R-project.org/package=bayesplot). For any plot you intend to include in your package, if it is already available in __bayesplot__ then we recommend using the available version or suggesting (or contributing) a better version. If it is not already available then there is a good chance we will be interested in including it in __bayesplot__ if the plot would also be useful for other developers. * Provide thorough and clear documentation. The documentation won't be perfect (we've found many holes in our __rstanarm__ documentation already and there are certainly more), but you should make every effort to provide clear and thorough documentation, using decent grammar and actual sentences wherever possible. The poor quality of the documentation in many (though certainly not all) R packages is insulting to users and an impediment to high quality research. In no way is the current state of R package documentation a reason to insufficiently document your own package. It is unfortunate that this needs to be said, but even a cursory review of popular R packages immediately reveals the necessity for guidelines like this one. Some of our own documentation does not always meet this high standard, but we are consistently making efforts to improve this. ### Recommended resources * Hadley Wickham's [book on R packages](http://r-pkgs.had.co.nz/). If you are interested in developing an R package that interfaces with Stan but are not an experienced package developer, we recommend Hadley's book, which is free to read online. Even if you are an experienced developer of R packages, Hadley's book is still a great resource. * If you need help setting up your package or have questions about these guidelines the best places to go are the [Stan Forums](https://discourse.mc-stan.org) and the [GitHub issue tracker](https://github.com/stan-dev/rstantools/issues) for the __rstantools__ package. ## Concluding remarks These guidelines are not set in stone. We expect them to evolve and we very much appreciate feedback on how they can be improved. And, of course, we look forward to seeing the packages you develop using Stan, so please let us know about them! -- The Stan Development Team rstantools/inst/doc/minimal-rstan-package.R0000644000176200001440000001074213537013647020510 0ustar liggesusersparams <- list(EVAL = TRUE) ## ----SETTINGS-knitr, include=FALSE--------------------------------------- stopifnot(require(knitr)) opts_chunk$set( comment=NA, eval = if (isTRUE(exists("params"))) params$EVAL else FALSE ) td <- tempdir() PATH <- file.path(td, "rstanlm") if(dir.exists(PATH)) { unlink(PATH, recursive = TRUE, force = TRUE) } ## ----rstan_create_package, eval=FALSE------------------------------------ # library("rstantools") # rstan_create_package(path = 'rstanlm') ## ----rstan_create_package-eval, echo=FALSE,warning=FALSE----------------- library("rstantools") rstan_create_package(path = PATH, rstudio=FALSE, open=FALSE) ## ---- eval=FALSE--------------------------------------------------------- # setwd("rstanlm") # list.files(all.files = TRUE) ## ---- echo=FALSE--------------------------------------------------------- list.files(PATH, all.files = TRUE) ## ---- eval=FALSE--------------------------------------------------------- # file.show("DESCRIPTION") ## ---- echo=FALSE--------------------------------------------------------- DES <- readLines(file.path(PATH, "DESCRIPTION")) cat(DES, sep = "\n") ## ---- eval=FALSE--------------------------------------------------------- # file.show("Read-and-delete-me") ## ---- echo=FALSE--------------------------------------------------------- cat(readLines(file.path(PATH, "Read-and-delete-me")), sep = "\n") ## ---- eval=FALSE--------------------------------------------------------- # file.remove('Read-and-delete-me') ## ---- echo=FALSE--------------------------------------------------------- file.remove(file.path(PATH, 'Read-and-delete-me')) ## ---- include=FALSE------------------------------------------------------ stan_prog <- " data { int N; vector[N] x; vector[N] y; } parameters { real intercept; real beta; real sigma; } model { // ... priors, etc. y ~ normal(intercept + beta * x, sigma); } " cat(stan_prog, file = file.path(PATH, "inst", "stan", "lm.stan")) rstan_config(PATH) ## ------------------------------------------------------------------------ # Save this file as `R/lm_stan.R` #' Bayesian linear regression with Stan #' #' @export #' @param x Numeric vector of input values. #' @param y Numberic vector of output values. #' @param ... Arguments passed to `rstan::sampling` (e.g. iter, chains). #' @return An object of class `stanfit` returned by `rstan::sampling` #' lm_stan <- function(x, y, ...) { standata <- list(x = x, y = y, N = length(y)) out <- rstan::sampling(stanmodels$lm, data = standata, ...) return(out) } ## ---- include=FALSE------------------------------------------------------ Rcode <- " #' Bayesian linear regression with Stan #' #' @export #' @param x Numeric vector of input values. #' @param y Numberic vector of output values. #' @param ... Arguments passed to `rstan::sampling`. #' @return An object of class `stanfit` returned by `rstan::sampling` lm_stan <- function(x, y, ...) { out <- rstan::sampling(stanmodels$lm, data=list(x=x, y=y, N=length(y)), ...) return(out) } " cat(Rcode, file = file.path(PATH, "R", "lm_stan.R")) ## ---- eval=FALSE--------------------------------------------------------- # file.show(file.path("R", "rstanlm-package.R")) ## ---- echo=FALSE--------------------------------------------------------- cat(readLines(file.path(PATH, "R", "rstanlm-package.R")), sep = "\n") ## ---- eval=FALSE--------------------------------------------------------- # pkgbuild::compile_dll() # see note below # roxygen2::roxygenize() ## ---- include=FALSE------------------------------------------------------ pkgbuild::compile_dll(PATH) # required for newer versions of roxygen2 ## ---- echo=FALSE--------------------------------------------------------- roxygen2::roxygenize(PATH) ## ----eval=FALSE---------------------------------------------------------- # # using ../rstanlm because already inside the rstanlm directory # install.packages("../rstanlm", repos = NULL, type = "source") ## ----echo=FALSE---------------------------------------------------------- install.packages(PATH, repos = NULL, type = "source") ## ---- eval=FALSE--------------------------------------------------------- # library("rstanlm") ## ------------------------------------------------------------------------ fit <- lm_stan(y = rnorm(10), x = rnorm(10), # arguments passed to sampling iter = 2000, refresh = 500) print(fit) ## ---- echo=FALSE--------------------------------------------------------- unlink(PATH, recursive = TRUE, force = TRUE) rstantools/inst/doc/developer-guidelines.html0000644000176200001440000004211213537013564021214 0ustar liggesusers Guidelines for Developers of R Packages Interfacing with Stan

Guidelines for Developers of R Packages Interfacing with Stan

Stan Development Team

Latest release: September 2019 (First version: November 2016)

Note to developers

One of the coolest things about working on a project like Stan has been seeing some of our users begin to develop tools for making Stan more accessible to audiences that may otherwise not benefit from what Stan offers. In particular, recently we have started seeing a growing number of R packages that provide high-level interfaces to Stan, using the rstan package for estimating models without requiring that the user be familiar with the Stan modeling language itself.

This is a great development and we would like to support such efforts going forward, but to-date we have made little effort to coordinate the development of these packages. To avoid a Wild West, so to speak, of Stan-based R packages, we think it is important that developers make every effort to adhere to certain guidelines in order to ensure these packages are of the highest possible quality and provide the best possible experience for users. To that end, in this post we present a set of recommendations for the development of R packages that interface with Stan. These recommendations are based on software design principles we value as well as many things we are learning as we continue developing our rstanarm package and review packages being developed by others.

Of course anyone is free to develop a package based on Stan, even if they ignore these recommendations. However, both because we feel strongly about these recommendations and because we are seeing an increase in the number of requests for help (and our time is unfortunately limited), we will loosely enforce these guidelines by

  1. prioritizing giving feedback to developers who follow them over those who choose not to, and
  2. refraining from promoting packages that ignore them.

That said, we are open to some limited exceptions (e.g., the brms package is a sensible exception to one of guidelines about Stan code). If you think your package should be an exception definitely let us know.

Guidelines for R packages providing interfaces to Stan

General package structure and development

  • The rstantools package provides the rstan_create_package() function, which you should use to create the basic structure of your package. (As of v2.0.0 this replaces the rstan_package_skeleton function.) This will set up a package with functionality for pre-compiled Stan programs, in the style of the rstanarm package (source code: https://github.com/stan-dev/rstanarm).

  • Use version control (e.g., git).

  • Unless you are developing proprietary private software, organize your code in a repository that is public on GitHub (or a similar service, but preferably GitHub). It should be public even at early stages of development, not only when officially released. We recommend you add a note to your README file on how to install the development version of your package, like in the bayesplot README

  • Unit testing is essential. There are several R packages that make it relatively easy to write tests for your package. Most of our R packages (e.g., rstanarm, brms, bayesplot, shinystan, loo) use the testthat package for this purpose, but if you prefer a different testing framework that’s fine. The covr package is useful for calculating the line coverage of your tests, and we recommend reaching a high level of coverage before releasing a package. Good line coverage does not guarantee high quality tests, but it’s a good first step.

Stan code

  • All Stan code for estimating models should be included in pre-written static .stan files that are compiled when the package is built (see the Stan programs directory in the rstanarm repo for examples). You can also use subdirectories to include code chunks to be used in multiple .stan files (again see the rstanarm repo for examples). If you set up your package using rstan_create_package this structure will be created for you. This means that your package should NOT write a Stan program when the user calls a model fitting function in your package, but rather use only Stan programs you have written by hand in advance (if you are working on a model for which you don’t think this is possible please let us know). There are several reasons for this.

  • Pre-compiled Stan programs can be run by users of Windows or Mac OSX without having to install a C++ compiler, which dramatically expands the universe of potential users for your package.
  • Pre-compiled Stan programs will run immediately when called, avoiding compilation time.
  • CRAN policy permits long installation times but imposes restrictions on the time consumed by examples and unit tests that are much shorter than the time that it takes to compile even a simple Stan program. Thus, it is only possible to adequately test your package if it has pre-compiled Stan programs.
  • Pre-compiled Stan programs can use custom C++ functions.

To provide flexibility to users, your Stan programs can include branching logic (conditional statements) so that even with a small number of .stan files you can still allow for many different specifications to made by the user (see the .stan files in rstanarm for examples).

  • Use best practices for Stan code. If the models you intend to implement are discussed in the Stan manual or on the Stan users forum then you should follow any recommendations that apply to your case. If you are unsure whether your Stan programs can be made more efficient or more numerically stable then please ask us on the Stan users forum. Especially ask us if you are unsure whether your Stan programs are indeed estimating the intended model.

  • Relatedly, prioritize safety over speed in your Stan code and sampler settings. For example, if you can write a program that runs faster but is potentially less stable, then at a minimum you should make the more stable version the default. This also means that, with rare exceptions, you should not change our recommended MCMC defaults (e.g. 4 chains, 1000+1000 iterations, NUTS not static HMC), unless you are setting the defaults to something more conservative. rstanarm even goes one step further, making the default value of the adapt_delta tuning parameter at least 0.95 for all models (rather than rstan’s default of 0.8) in order to reduce the step size and therefore also limit the potential for divergences. This means that rstanarm models may often run a bit slower than they need to if the user doesn’t change the defaults, but it also means that users face fewer situations in which they need to know how to change the defaults and what the implications of changing the defaults really are.

R code and documentation

  • Functions that provide useful post-estimation functionality should be given the same names as the corresponding functions in rstanarm (if applicable). For example, posterior_predict() to draw from the posterior predictive distribution, posterior_interval() for posterior uncertainty intervals, etc. To make this easier, these and similar rstanarm functions have been converted to S3 methods for the stanreg objects created by rstanarm and the S3 generic functions are included here in the rstantools package. Your package should import the generics from rstantools for whichever functions you want to include in your package and then provide methods for the fitted model objects returned by your model-fitting functions. For some other functions (e.g. as.matrix) the generics are already available in base R or core R packages. To be clear, we are not saying that the naming conventions used in rstanarm/rstantools are necessarily optimal. (If you think that one of our function names should be changed please let us know and suggest an alternative. If it is a substantial improvement we may consider renaming the function and deprecating the current version.) Rather, this guideline is intended to make function names consistent across Stan-based R packages, which will improve the user experience for those users who want to take advantage of a variety of these packages. It will be a mess if every R package using Stan has different names for the same functionality.

  • The bayesplot package serves as the back-end for plotting for rstanarm (see for example pp_check.stanreg and plot.stanreg), brms, and other packages, and we hope developers of other Stan-based R packages will also use it. You can see all the other R packages using bayesplot in the Reverse dependencies section of the bayesplot CRAN page. For any plot you intend to include in your package, if it is already available in bayesplot then we recommend using the available version or suggesting (or contributing) a better version. If it is not already available then there is a good chance we will be interested in including it in bayesplot if the plot would also be useful for other developers.

  • Provide thorough and clear documentation. The documentation won’t be perfect (we’ve found many holes in our rstanarm documentation already and there are certainly more), but you should make every effort to provide clear and thorough documentation, using decent grammar and actual sentences wherever possible. The poor quality of the documentation in many (though certainly not all) R packages is insulting to users and an impediment to high quality research. In no way is the current state of R package documentation a reason to insufficiently document your own package. It is unfortunate that this needs to be said, but even a cursory review of popular R packages immediately reveals the necessity for guidelines like this one. Some of our own documentation does not always meet this high standard, but we are consistently making efforts to improve this.

Concluding remarks

These guidelines are not set in stone. We expect them to evolve and we very much appreciate feedback on how they can be improved. And, of course, we look forward to seeing the packages you develop using Stan, so please let us know about them!

– The Stan Development Team

rstantools/inst/doc/minimal-rstan-package.Rmd0000644000176200001440000002335513537012352021025 0ustar liggesusers--- title: "Step by step guide for creating a package that depends on RStan" author: "Stefan Siegert, Jonah Gabry, Martin Lysy, and Ben Goodrich" date: "`r Sys.Date()`" output: rmarkdown::html_vignette: toc: true params: EVAL: !r identical(Sys.getenv("NOT_CRAN"), "true") vignette: > %\VignetteIndexEntry{Step by step guide} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r SETTINGS-knitr, include=FALSE} stopifnot(require(knitr)) opts_chunk$set( comment=NA, eval = if (isTRUE(exists("params"))) params$EVAL else FALSE ) td <- tempdir() PATH <- file.path(td, "rstanlm") if(dir.exists(PATH)) { unlink(PATH, recursive = TRUE, force = TRUE) } ``` ## Introduction In this vignette we will walk through the steps necessary for creating an R package that depends on Stan by creating a package with one function that fits a simple linear regression. Before continuing, we recommend that you first read the other vignette [_Guidelines for Developers of R Packages Interfacing with Stan_](http://mc-stan.org/rstantools/articles/developer-guidelines.html). ## Creating the package skeleton The **rstantools** package offers two methods for adding Stan functionality to R packages: * `rstan_create_package()`: set up a new R package with Stan programs * `use_rstan()`: add Stan functionality to an _existing_ R package Here we will use `rstan_create_package()` to initialize a bare-bones package directory. The name of our demo package will be __rstanlm__; it will fit a simple linear regression model using Stan. ```{r rstan_create_package, eval=FALSE} library("rstantools") rstan_create_package(path = 'rstanlm') ``` ```{r rstan_create_package-eval, echo=FALSE,warning=FALSE} library("rstantools") rstan_create_package(path = PATH, rstudio=FALSE, open=FALSE) ``` If we had existing `.stan` files to include with the package we could use the optional `stan_files` argument to `rstan_create_package()` to include them. Another option, which we'll use below, is to add the Stan files once the basic structure of the package is in place. We can now set the new working directory to the new package directory and view the contents. (Note: if using RStudio then by default the newly created project for the package will be opened in a new session and you will not need the call to `setwd()`.) ```{r, eval=FALSE} setwd("rstanlm") list.files(all.files = TRUE) ``` ```{r, echo=FALSE} list.files(PATH, all.files = TRUE) ``` ```{r, eval=FALSE} file.show("DESCRIPTION") ``` ```{r, echo=FALSE} DES <- readLines(file.path(PATH, "DESCRIPTION")) cat(DES, sep = "\n") ``` Some of the sections in the `DESCRIPTION` file need to be edited by hand (e.g., `Title`, `Author`, `Maintainer`, and `Description`, but these also can be set with the `fields` argument to `rstan_create_package()`). However, `rstan_create_package()` has added the necessary packages and versions to `Depends`, `Imports`, and `LinkingTo` to enable Stan functionality. ## Read-and-delete-me file Before deleting the `Read-and-delete-me` file in the new package directory make sure to read it because it contains some important instructions about customizing your package: ```{r, eval=FALSE} file.show("Read-and-delete-me") ``` ```{r, echo=FALSE} cat(readLines(file.path(PATH, "Read-and-delete-me")), sep = "\n") ``` You can move this file out of the directory, delete it, or list it in the `.Rbuildignore` file if you want to keep it in the directory. ```{r, eval=FALSE} file.remove('Read-and-delete-me') ``` ```{r, echo=FALSE} file.remove(file.path(PATH, 'Read-and-delete-me')) ``` ## Stan files Our package will call **rstan**'s `sampling()` method to use MCMC to fit a simple linear regression model for an outcome variable `y` with a single predictor `x`. After writing the necessary Stan program, the file should be saved with a `.stan` extension in the `inst/stan` subdirectory. We'll save the following program to `inst/stan/lm.stan`: ```{stan, output.var = "foo", eval = FALSE} // Save this file as inst/stan/lm.stan data { int N; vector[N] x; vector[N] y; } parameters { real intercept; real beta; real sigma; } model { // ... priors, etc. y ~ normal(intercept + beta * x, sigma); } ``` ```{r, include=FALSE} stan_prog <- " data { int N; vector[N] x; vector[N] y; } parameters { real intercept; real beta; real sigma; } model { // ... priors, etc. y ~ normal(intercept + beta * x, sigma); } " cat(stan_prog, file = file.path(PATH, "inst", "stan", "lm.stan")) rstan_config(PATH) ``` The `inst/stan` subdirectory can contain additional Stan programs if required by your package. During installation, all Stan programs will be compiled and saved in the list `stanmodels` that can then be used by R function in the package. The rule is that the Stan program compiled from the model code in `inst/stan/foo.stan` is stored as list element `stanmodels$foo`. Thus, the filename of the Stan program in the `inst/stan` directory should not contain spaces or dashes and nor should it start with a number or utilize non-ASCII characters. ## R files We next create the file `R/lm_stan.R` where we define the function `lm_stan()` in which our compiled Stan model is being used. Setting the `rstan_create_package()` argument `roxygen = TRUE` (the default value) enables [__roxygen2__](https://CRAN.R-project.org/package=roxygen2) documentation for the package functions. The following comment block placed in `lm_stan.R` ensures that the function has a help file and that it is added to the package `NAMESPACE`: ```{r} # Save this file as `R/lm_stan.R` #' Bayesian linear regression with Stan #' #' @export #' @param x Numeric vector of input values. #' @param y Numberic vector of output values. #' @param ... Arguments passed to `rstan::sampling` (e.g. iter, chains). #' @return An object of class `stanfit` returned by `rstan::sampling` #' lm_stan <- function(x, y, ...) { standata <- list(x = x, y = y, N = length(y)) out <- rstan::sampling(stanmodels$lm, data = standata, ...) return(out) } ``` ```{r, include=FALSE} Rcode <- " #' Bayesian linear regression with Stan #' #' @export #' @param x Numeric vector of input values. #' @param y Numberic vector of output values. #' @param ... Arguments passed to `rstan::sampling`. #' @return An object of class `stanfit` returned by `rstan::sampling` lm_stan <- function(x, y, ...) { out <- rstan::sampling(stanmodels$lm, data=list(x=x, y=y, N=length(y)), ...) return(out) } " cat(Rcode, file = file.path(PATH, "R", "lm_stan.R")) ``` When __roxygen2__ documentation is enabled, a top-level package file `R/rstanlm-package.R` is created by `rstan_create_package()` to import necessary functions for other packages and to set up the package for compiling Stan C++ code: ```{r, eval=FALSE} file.show(file.path("R", "rstanlm-package.R")) ``` ```{r, echo=FALSE} cat(readLines(file.path(PATH, "R", "rstanlm-package.R")), sep = "\n") ``` The `#' @description` section can be manually edited to provided specific information about the package. ## Documentation With __roxygen__ documentation enabled, we need to generate the documentation for `lm_stan` and update the `NAMESPACE` so the function is exported, i.e., available to users when the package is installed. This can be done with the function `roxygen2::roxygenize()`. ```{r, eval=FALSE} pkgbuild::compile_dll() # see note below roxygen2::roxygenize() ``` ```{r, include=FALSE} pkgbuild::compile_dll(PATH) # required for newer versions of roxygen2 ``` ```{r, echo=FALSE} roxygen2::roxygenize(PATH) ``` __Note:__ For newer versions of __roxygen__, it is necessary to compile the package C++ code prior to running `roxygen2::roxygenize()`. One way to do this is with `pkgbuild::compile_dll()`, as above. ## Install and use Finally, the package is ready to be installed: ```{r,eval=FALSE} # using ../rstanlm because already inside the rstanlm directory install.packages("../rstanlm", repos = NULL, type = "source") ``` ```{r,echo=FALSE} install.packages(PATH, repos = NULL, type = "source") ``` It is also possible to use `devtools::install(quick=FALSE)` to install the package. The argument `quick=FALSE` is necessary if you want to recompile the Stan models. Going forward, if you only make a change to the R code or the documentation, you can set `quick=TRUE` to speed up the process, or use `devtools::load_all()`. After installation, the package can be loaded and used like any other R package: ```{r, eval=FALSE} library("rstanlm") ``` ```{r} fit <- lm_stan(y = rnorm(10), x = rnorm(10), # arguments passed to sampling iter = 2000, refresh = 500) print(fit) ``` ```{r, echo=FALSE} unlink(PATH, recursive = TRUE, force = TRUE) ``` ## Advanced options Details can be found in the documentation for `rstan_create_package()` so we only mention some of these briefly here: * Running `rstan_create_package()` with `auto_config = TRUE` (the default value) automatically synchronizes the Stan C++ files with the `.stan` model files located in `inst/stan`, although this creates a dependency of your package on __rstantools__ itself (i.e., __rstantools__ must be installed for your package to work). Setting `auto_config = FALSE` removes this dependency, at the cost of having to manually synchronize Stan C++ files by running `rstan_config()` every time a package `.stan` file is added, removed, or even just modified. * The function `use_rstan()` can be used to add Stan functionality to an existing package, instead of building the package from scratch. ## Links * [_Guidelines for Developers of R Packages Interfacing with Stan_](https://mc-stan.org/rstantools/articles/developer-guidelines.html) * Ask a question at the [Stan Forums](https://discourse.mc-stan.org/) * [R packages](http://r-pkgs.had.co.nz/) by Hadley Wickham provides a solid foundation in R package development as well as the release process. rstantools/inst/include/0000755000176200001440000000000013462666422015075 5ustar liggesusersrstantools/inst/include/sys/0000755000176200001440000000000013462666422015713 5ustar liggesusersrstantools/inst/include/sys/stanmodels.R0000644000176200001440000000173513462666422020215 0ustar liggesusers# names of stan models stanmodels <- "STAN_MODEL_NAME" # load each stan module Rcpp::loadModule("stan_fit4STAN_MODEL_NAME_mod", what = TRUE) # instantiate each stanmodel object stanmodels <- sapply(stanmodels, function(model_name) { # create C++ code for stan model stan_file <- if(dir.exists("stan")) "stan" else file.path("inst", "stan") stan_file <- file.path(stan_file, paste0(model_name, ".stan")) stanfit <- rstan::stanc_builder(stan_file, allow_undefined = TRUE, obfuscate_model_name = FALSE) stanfit$model_cpp <- list(model_cppname = stanfit$model_name, model_cppcode = stanfit$cppcode) # create stanmodel object methods::new(Class = "stanmodel", model_name = stanfit$model_name, model_code = stanfit$model_code, model_cpp = stanfit$model_cpp, mk_cppmodule = function(x) get(paste0("model_", model_name))) }) rstantools/inst/include/sys/travis.yml0000644000176200001440000000236213462666422017751 0ustar liggesuserslanguage: r sudo: false r: devel cache: packages latex: true env: matrix: - CXX_OLEVEL=2 CXX=clang++ matrix: include: - os: linux compiler: clang addons: apt: sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-5.0' ] packages: - llvm-5.0-dev env: - CXX_OLEVEL=2 CXX=clang++ before_install: - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update -q - mkdir -p ~/.R/ - echo "CXX = `R CMD config CXX`" >> ~/.R/Makevars - echo "CXXFLAGS = `R CMD config CXXFLAGS` -pedantic -g0 -flto -stdlib=libc++" >> ~/.R/Makevars - echo "LDFLAGS += -flto -stdlib=libc++" >> ~/.R/Makevars - export CLANG_EXTRA_ARG="" - if [[ $CXX = "clang++" ]] ; then export CLANG_EXTRA_ARG=" -Qunused-arguments -fcolor-diagnostics " ; fi - sed -i.bak "s/ g++/ ${CXX}${CLANG_EXTRA_ARG}/" ~/.R/Makevars - sed -i.bak "s/O[0-3]/O$CXX_OLEVEL/" ~/.R/Makevars script: - | travis_wait 42 R CMD build . travis_wait 59 R CMD check RSTAN_PACKAGE_NAME*tar.gz after_script: - tar -ztvf RSTAN_PACKAGE_NAME_*.tar.gz - echo ${NOT_CRAN} after_success: - travis_wait 40 tar -C .. -xf $PKG_TARBALL after_failure: - cat RSTAN_PACKAGE_NAME.Rcheck/00* rstantools/inst/include/sys/Read_and_delete_me0000644000176200001440000000116713462666422021343 0ustar liggesusersStan-specific notes: * All '.stan' files containing stanmodel definitions must be placed in 'inst/stan'. * Additional files to be included by stanmodel definition files (via e.g., #include "mylib.stan") must be placed in any subfolder of 'inst/stan'. * Additional C++ files needed by any '.stan' file must be placed in 'inst/include', and can only interact with the Stan C++ library via '#include' directives placed in the file 'inst/include/stan_meta_header.hpp'. * The precompiled stanmodel objects will appear in a named list called 'stanmodels', and you can call them with e.g., 'rstan::sampling(stanmodels$foo, ...)' rstantools/inst/include/sys/DESCRIPTION0000644000176200001440000000114613462676632017427 0ustar liggesusersPackage: RStanTest Type: Package Title: What the Package Does (One Line, Title Case) Version: 0.0.0.9000 Date: 2018-04-04 Authors@R: person(given = "First", family = "Last", role = c("aut", "cre"), email = "first.last@example.com") Description: What the package does (one paragraph). License: What license it uses Depends: R (>= 3.4.0) Imports: Rcpp (>= 0.12.0), methods, rstan (>= 2.18.1), rstantools LinkingTo: StanHeaders (>= 2.18.0), rstan (>= 2.18.1), BH (>= 1.66.0), Rcpp (>= 0.12.0), RcppEigen (>= 0.3.3.3.0) SystemRequirements: GNU make Encoding: UTF-8 LazyData: true rstantools/inst/include/sys/Makevars0000644000176200001440000000123513462666422017410 0ustar liggesusersSTANHEADERS_SRC = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "message()" -e "cat(system.file('include', 'src', package = 'StanHeaders', mustWork = TRUE))" -e "message()" | grep "StanHeaders") PKG_CPPFLAGS = -I"../inst/include" -I"$(STANHEADERS_SRC)" -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DBOOST_MATH_OVERFLOW_ERROR_POLICY=errno_on_error CXX_STD = CXX14 all: $(SHLIB) @if test -e "/usr/bin/install_name_tool" && test -e "/usr/local/clang4/lib/libc++.1.dylib" && test -e "/usr/lib/libc++.1.dylib"; then /usr/bin/install_name_tool -change /usr/local/clang4/lib/libc++.1.dylib /usr/lib/libc++.1.dylib $(SHLIB); fi clean: rm -rf *.so *.o .phony: all clean rstantools/inst/include/sys/stan_meta_header.hpp0000644000176200001440000000006013462666422021703 0ustar liggesusers// Insert all #include statements here rstantools/inst/include/sys/rstanpkg-package.R0000644000176200001440000000052413462666422021261 0ustar liggesusers#' The 'RSTAN_PACKAGE_NAME' package. #' #' @description A DESCRIPTION OF THE PACKAGE #' #' @docType package #' @name RSTAN_PACKAGE_NAME-package #' @aliases RSTAN_PACKAGE_NAME #' @useDynLib RSTAN_PACKAGE_NAME, .registration = TRUE #' @import methods #' @import Rcpp #' @importFrom rstan sampling #' #' @references #' RSTAN_REFERENCE #' NULL rstantools/inst/include/sys/Makevars.win0000644000176200001440000000056613462666422020212 0ustar liggesusersSTANHEADERS_SRC = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "message()" -e "cat(system.file('include', 'src', package = 'StanHeaders', mustWork = TRUE))" -e "message()" | grep "StanHeaders") PKG_CPPFLAGS = -I"../inst/include" -I"$(STANHEADERS_SRC)" -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG CXX_STD = CXX14 all: $(SHLIB) clean: RM -rf *.so *.o .phony: all clean rstantools/inst/include/sys/configure.win0000755000176200001440000000012413462666422020413 0ustar liggesusers#! /bin/sh "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "rstantools::rstan_config()" rstantools/inst/include/sys/lice_nse.stan0000644000176200001440000000124413462666422020364 0ustar liggesusers/* RSTAN_PACKAGE_NAME is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. RSTAN_PACKAGE_NAME is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RSTAN_PACKAGE_NAME. If not, see . */ rstantools/inst/include/sys/configure0000755000176200001440000000010313537013650017604 0ustar liggesusers#! /bin/sh "${R_HOME}/bin/Rscript" -e "rstantools::rstan_config()"