Skip to content

Commit 7de737a

Browse files
committed
Merge branch 'master' into fix_opencl_vignette
2 parents 5f93e8e + 18c0f5d commit 7de737a

27 files changed

+240
-73
lines changed

.github/workflows/cmdstan-tarball-check.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
name: ${{ matrix.config.os }} (${{ matrix.config.r }})
2020

2121
strategy:
22-
fail-fast: true
22+
fail-fast: false
2323
matrix:
2424
config:
2525
- {os: macOS-latest, r: 'release'}

DESCRIPTION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: cmdstanr
22
Title: R Interface to 'CmdStan'
3-
Version: 0.4.0.9000
3+
Version: 0.4.0.9001
44
Date: 2021-04-15
55
Authors@R:
66
c(person(given = "Jonah", family = "Gabry", role = c("aut", "cre"),
@@ -36,7 +36,7 @@ Imports:
3636
R6 (>= 2.4.0)
3737
Suggests:
3838
bayesplot,
39-
knitr,
39+
knitr (>= 1.37),
4040
loo (>= 2.0.0),
4141
rlang (>= 0.4.7),
4242
rmarkdown,

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export(cmdstan_model)
1515
export(cmdstan_path)
1616
export(cmdstan_version)
1717
export(cmdstanr_example)
18+
export(draws_to_csv)
1819
export(eng_cmdstan)
1920
export(install_cmdstan)
2021
export(num_threads)

R/csv.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ read_cmdstan_csv <- function(files,
179179
if (length(uniq_seed) == 1) {
180180
metadata$seed <- uniq_seed
181181
}
182+
metadata$time <- time
182183
if (metadata$method == "diagnose") {
183184
gradients <- metadata$gradients
184185
metadata$gradients <- NULL

R/data.R

Lines changed: 75 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -204,27 +204,77 @@ any_zero_dims <- function(data) {
204204
any(has_zero_dims)
205205
}
206206

207-
#' Write posterior draws objects to csv files
208-
#' @noRd
209-
#' @param draws A `draws_array` from posterior pkg
210-
#' @param sampler_diagnostics Either `NULL` or a `draws_array` of sampler diagnostics
207+
#' Write posterior draws objects to CSV files suitable for running standalone generated
208+
#' quantities with CmdStan.
209+
#'
210+
#' @export
211+
#' @param draws A `posterior::draws_*` object.
212+
#' @param sampler_diagnostics Either `NULL` or a `posterior::draws_*` object
213+
#' of sampler diagnostics.
214+
#' @param dir (string) An optional path to the directory where the CSV files will be
215+
#' written. If not set, [temporary directory][base::tempdir] is used.
216+
#' @param basename (string) If `dir` is specified, `basename`` is used for naming
217+
#' the output CSV files. If not specified, the file names are randomly generated.
218+
#'
211219
#' @return Paths to CSV files (one per chain).
212220
#'
213-
draws_to_csv <- function(draws, sampler_diagnostics = NULL) {
221+
#' @details
222+
#' `draws_to_csv()` generates a CSV suitable for running standalone generated
223+
#' quantities with CmdStan. The CSV file contains a single comment `#num_samples`,
224+
#' which equals the number of iterations in the supplied draws object.
225+
#'
226+
#' The comment is followed by the column names. The first column is the `lp__` value,
227+
#' followed by sampler diagnostics and finnaly other variables of the draws object.
228+
#' #' If the draws object does not contain the `lp__` or sampler diagnostics variables,
229+
#' columns with zeros are created in order to conform with the requirements of the
230+
#' standalone generated quantities method of CmdStan.
231+
#'
232+
#' The column names line is finally followed by the values of the draws in the same
233+
#' order as the column names.
234+
#'
235+
#' @examples
236+
#' \dontrun{
237+
#' draws <- posterior::example_draws()
238+
#'
239+
#' draws_csv_files <- draws_to_csv(draws)
240+
#' print(draws_csv_files)
241+
#'
242+
#' # draws_csv_files <- draws_to_csv(draws,
243+
#' # sampler_diagnostic = sampler_diagnostics,
244+
#' # dir = "~/my_folder",
245+
#' # basename = "my-samples")
246+
#' }
247+
#'
248+
draws_to_csv <- function(draws,
249+
sampler_diagnostics = NULL,
250+
dir = tempdir(),
251+
basename = "fittedParams") {
252+
sampler_diagnostics_names <- c(
253+
"accept_stat__", "stepsize__", "treedepth__",
254+
"n_leapfrog__", "divergent__", "energy__"
255+
)
214256
n <- posterior::niterations(draws)
215257
n_chains <- posterior::nchains(draws)
258+
draws_variables <- posterior::variables(draws)
259+
sampler_diagnostics_variables <- posterior::variables(sampler_diagnostics)
260+
261+
# create dummy sampler diagnostics due to CmdStan requirement for all columns in GQ if needed
216262
zeros <- rep(0, n * n_chains) # filler for creating dummy sampler diagnostics and lp__ if necessary
217263
if (is.null(sampler_diagnostics)) {
218-
# create dummy sampler diagnostics due to CmdStan requirement for all columns in GQ
219-
sampler_diagnostics <- posterior::draws_array(
220-
accept_stat__ = zeros,
221-
stepsize__ = zeros,
222-
treedepth__ = zeros,
223-
n_leapfrog__ = zeros,
224-
divergent__ = zeros,
225-
energy__ = zeros,
226-
.nchains = n_chains
227-
)
264+
missing_sampler_diagnostics <- sampler_diagnostics_names[!(sampler_diagnostics_names %in% draws_variables)]
265+
266+
} else {
267+
missing_sampler_diagnostics <- sampler_diagnostics_names[!(sampler_diagnostics_names %in% draws_variables)]
268+
missing_sampler_diagnostics <- missing_sampler_diagnostics[!(missing_sampler_diagnostics %in% sampler_diagnostics_variables)]
269+
}
270+
if (length(missing_sampler_diagnostics) > 0) {
271+
additional_sampler_diagnostics <- list()
272+
for (name in missing_sampler_diagnostics) {
273+
additional_sampler_diagnostics[[name]] <- zeros
274+
}
275+
additional_sampler_diagnostics[[".nchains"]] <- n_chains
276+
additional_sampler_diagnostics <- do.call(posterior::draws_array, additional_sampler_diagnostics)
277+
sampler_diagnostics <- posterior::bind_draws(sampler_diagnostics, additional_sampler_diagnostics)
228278
}
229279

230280
# the columns must be in order "lp__, sampler_diagnostics, parameters"
@@ -236,26 +286,31 @@ draws_to_csv <- function(draws, sampler_diagnostics = NULL) {
236286
}
237287
all_variables <- c(
238288
"lp__",
239-
posterior::variables(sampler_diagnostics),
240-
draws_variables[!(draws_variables %in% c("lp__", "lp_approx__"))]
289+
sampler_diagnostics_names,
290+
draws_variables[!(draws_variables %in% c("lp__", "lp_approx__", sampler_diagnostics_names))]
241291
)
242292
draws <- posterior::subset_draws(
243293
posterior::bind_draws(draws, sampler_diagnostics, lp__, along = "variable"),
244294
variable = all_variables
245295
)
246296

247297
chains <- posterior::chain_ids(draws)
248-
paths <- generate_file_names(basename = "fittedParams", ids = chains)
249-
paths <- file.path(tempdir(), paths)
298+
paths <- generate_file_names(basename = basename, ids = chains)
299+
paths <- file.path(dir, paths)
250300
chain <- 1
251301
for (path in paths) {
252302
write(
253303
paste0("# num_samples = ", n, "\n", paste0(unrepair_variable_names(all_variables), collapse = ",")),
254304
file = path,
255305
append = FALSE
256306
)
307+
data <- posterior::as_draws_df(posterior::subset_draws(draws, chain = chain))
308+
class(data) <- "data.frame"
309+
data$.chain <- NULL
310+
data$.iteration <- NULL
311+
data$.draw <- NULL
257312
data.table::fwrite(
258-
posterior::as_draws_df(posterior::subset_draws(draws, chain = chain)),
313+
data,
259314
sep = ",",
260315
file = path,
261316
col.names = FALSE,

R/model.R

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,9 @@ compile <- function(quiet = TRUE,
587587
stop("An error occured during compilation! See the message above for more information.",
588588
call. = FALSE)
589589
}
590-
590+
if (file.exists(exe)) {
591+
file.remove(exe)
592+
}
591593
file.copy(tmp_exe, exe, overwrite = TRUE)
592594
private$exe_file_ <- exe
593595
private$cpp_options_ <- cpp_options
@@ -1311,6 +1313,13 @@ CmdStanModel$set("public", name = "variational", value = variational)
13111313
#' VB) object returned by CmdStanR's [`$draws()`][fit-method-draws] method.
13121314
#' * A character vector of paths to CmdStan CSV output files.
13131315
#'
1316+
#' NOTE: if you plan on making many calls to `$generate_quantities()` then the
1317+
#' most efficient option is to pass the paths of the CmdStan CSV output files
1318+
#' (this avoids CmdStanR having to rewrite the draws contained in the fitted
1319+
#' model object to CSV each time). If you no longer have the CSV files you can
1320+
#' use [draws_to_csv()] once to write them and then pass the resulting file
1321+
#' paths to `$generate_quantities()` as many times as needed.
1322+
#'
13141323
#' @return A [`CmdStanGQ`] object.
13151324
#'
13161325
#' @template seealso-docs
@@ -1534,7 +1543,7 @@ cpp_options_to_compile_flags <- function(cpp_options) {
15341543
for (i in seq_along(cpp_options)) {
15351544
option_name <- names(cpp_options)[i]
15361545
if (is.null(option_name) || !nzchar(option_name)) {
1537-
cpp_built_options <- c(cpp_built_options, toupper(cpp_options[[i]]))
1546+
cpp_built_options <- c(cpp_built_options, cpp_options[[i]])
15381547
} else {
15391548
cpp_built_options <- c(cpp_built_options, paste0(toupper(option_name), "=", cpp_options[[i]]))
15401549
}

_pkgdown.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ reference:
107107
- read_cmdstan_csv
108108
- write_stan_json
109109
- write_stan_file
110+
- draws_to_csv
110111
- title: "Using CmdStanR with knitr and R Markdown"
111112
contents:
112113
- register_knitr_engine

inst/logistic.stan

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
data {
22
int<lower=0> N;
33
int<lower=0> K;
4-
int<lower=0,upper=1> y[N];
4+
array[N] int<lower=0, upper=1> y;
55
matrix[N, K] X;
66
}
77
parameters {
@@ -15,5 +15,7 @@ model {
1515
}
1616
generated quantities {
1717
vector[N] log_lik;
18-
for (n in 1:N) log_lik[n] = bernoulli_logit_lpmf(y[n] | alpha + X[n] * beta);
18+
for (n in 1 : N) {
19+
log_lik[n] = bernoulli_logit_lpmf(y[n] | alpha + X[n] * beta);
20+
}
1921
}

man/draws_to_csv.Rd

Lines changed: 61 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/model-method-generate-quantities.Rd

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
12 Bytes
Binary file not shown.
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
data {
22
int<lower=0> N;
3-
int<lower=0,upper=1> y[N];
3+
array[N] int<lower=0, upper=1> y;
44
}
55
parameters {
6-
real<lower=0,upper=1> theta;
6+
real<lower=0, upper=1> theta;
77
}
88
model {
9-
theta ~ beta(1,1); // uniform prior on interval 0,1
9+
theta ~ beta(1, 1); // uniform prior on interval 0,1
1010
y ~ bernoulli(theta);
1111
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
data {
22
int<lower=0> N;
3-
int<lower=0,upper=1> y[N];
3+
array[N] int<lower=0, upper=1> y;
44
}
55
parameters {
6-
real<lower=0,upper=1> theta;
6+
real<lower=0, upper=1> theta;
77
}
88
model {
9-
theta ~ beta(1,1); // uniform prior on interval 0,1
9+
theta ~ beta(1, 1); // uniform prior on interval 0,1
1010
y ~ bernoulli(theta);
1111
}
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
transformed data {
22
int<lower=0> N = 10;
3-
real<lower=0,upper=1> theta = 0.35;
3+
real<lower=0, upper=1> theta = 0.35;
44
}
55
generated quantities {
6-
int y_sim[N];
7-
for (n in 1:N)
6+
array[N] int y_sim;
7+
for (n in 1 : N) {
88
y_sim[n] = bernoulli_rng(theta);
9+
}
910
}

tests/testthat/resources/stan/bernoulli_include.stan

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ functions {
33
}
44
data {
55
int<lower=0> N;
6-
int<lower=0,upper=1> y[N];
6+
array[N] int<lower=0, upper=1> y;
77
}
88
parameters {
9-
real<lower=0,upper=1> theta;
9+
real<lower=0, upper=1> theta;
1010
}
1111
model {
12-
theta ~ beta(divide_real_by_two(2.0),1);
13-
for (n in 1:N)
12+
theta ~ beta(divide_real_by_two(2.0), 1);
13+
for (n in 1 : N) {
1414
y[n] ~ bernoulli(theta);
15+
}
1516
}
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
data {
22
int<lower=0> N;
3-
int<lower=0,upper=1> y[N];
3+
array[N] int<lower=0, upper=1> y;
44
}
55
parameters {
6-
real<lower=0,upper=1> theta;
6+
real<lower=0, upper=1> theta;
77
}
88
model {
9-
theta ~ beta(1,1); // uniform prior on interval 0,1
9+
theta ~ beta(1, 1); // uniform prior on interval 0,1
1010
y ~ bernoulli(theta);
1111
}
1212
generated quantities {
1313
vector[N] log_lik;
14-
for (n in 1:N) log_lik[n] = bernoulli_lpmf(y | theta);
14+
for (n in 1 : N) {
15+
log_lik[n] = bernoulli_lpmf(y | theta);
16+
}
1517
}

0 commit comments

Comments
 (0)