From a5cb5f7c66769e81af9994a2c79820f311a9b7ec Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Sat, 1 Aug 2026 09:58:22 +0300
Subject: [PATCH 01/40] improve tests for log lik and log prior selection
---
tests/testthat/test_component_name.R | 65 ++++++++++++++++++++++++----
1 file changed, 56 insertions(+), 9 deletions(-)
diff --git a/tests/testthat/test_component_name.R b/tests/testthat/test_component_name.R
index c21a5e4..745bd89 100644
--- a/tests/testthat/test_component_name.R
+++ b/tests/testthat/test_component_name.R
@@ -1,26 +1,73 @@
ex <- example_powerscale_model()$draws
ex_renamed <- posterior::rename_variables(
- ex,
- log_prior = lprior,
- log_prior_sigma = lprior_sigma,
- log_prior_mu = lprior_mu
+ ex,
+ ll = log_lik,
+ log_prior = lprior,
+ log_prior_sigma = lprior_sigma,
+ log_prior_mu = lprior_mu
)
psd <- create_priorsense_data(ex)
-psd_r <- create_priorsense_data(ex_renamed, log_prior_name = "log_prior")
+psd_r <- create_priorsense_data(
+ ex_renamed,
+ log_prior_name = "log_prior",
+ log_lik_name = "ll"
+)
testthat::expect_error(powerscale_sensitivity(ex, log_lik_name = "ll"))
testthat::expect_error(powerscale_sensitivity(ex_renamed))
testthat::expect_equal(
- powerscale_sensitivity(psd_r),
- powerscale_sensitivity(psd)
+ powerscale_sensitivity(psd_r),
+ powerscale_sensitivity(psd)
+)
+
+testthat::expect_equal(
+ powerscale_sensitivity(ex),
+ powerscale_sensitivity(
+ ex_renamed,
+ log_prior_name = "log_prior",
+ log_lik_name = "ll"
+ )
+)
+
+
+ex_new_var <- posterior::mutate_variables(
+ ex,
+ log_prior = lprior,
+ log_lik1 = `log_lik[1]`,
+ log_lik2 = `log_lik[1]`,
+)
+
+testthat::expect_equal(
+ powerscale_sensitivity(
+ ex_new_var,
+ log_lik_name = "log_lik1",
+ variable = "mu"
+ ),
+ powerscale_sensitivity(
+ ex_new_var,
+ log_lik_name = "log_lik2",
+ variable = "mu"
+ )
)
testthat::expect_equal(
- powerscale_sensitivity(ex),
- powerscale_sensitivity(ex_renamed, log_prior_name = "log_prior")
+ powerscale_sensitivity(
+ ex_new_var,
+ log_lik_name = "log_lik",
+ likelihood_selection = "1",
+ separator = "",
+ variable = "mu"
+ )$likelihood,
+ powerscale_sensitivity(
+ ex_new_var,
+ log_lik_name = "log_lik",
+ likelihood_selection = "2",
+ separator = "",
+ variable = "mu"
+ )$likelihood
)
From 56b1fd55725fcce8a733ee18686a042f176997cb Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Sun, 2 Aug 2026 23:54:12 +0300
Subject: [PATCH 02/40] formatting
---
R/log_prior_draws.R | 118 ++++++++++++++++++++++----------------------
1 file changed, 59 insertions(+), 59 deletions(-)
diff --git a/R/log_prior_draws.R b/R/log_prior_draws.R
index d3dede0..7447956 100644
--- a/R/log_prior_draws.R
+++ b/R/log_prior_draws.R
@@ -20,93 +20,93 @@
##'
##' @export
log_prior_draws <- function(x, ...) {
- UseMethod("log_prior_draws")
+ UseMethod("log_prior_draws")
}
##' @rdname log_prior_draws
##' @export
log_prior_draws.stanfit <- function(
- x,
- joint = FALSE,
- log_prior_name = "lprior",
- ...
+ x,
+ joint = FALSE,
+ log_prior_name = "lprior",
+ ...
) {
- if (!inherits(x, "stanfit")) {
- stop("Not a stanfit object.", call. = FALSE)
- }
- if (x@mode != 0) {
- stop("Stan model does not contain posterior draws.", call. = FALSE)
- }
- if (!requireNamespace("rstan", quietly = TRUE)) {
- stop("Please load the 'rstan' package.", call. = FALSE)
- }
+ if (!inherits(x, "stanfit")) {
+ stop("Not a stanfit object.", call. = FALSE)
+ }
+ if (x@mode != 0) {
+ stop("Stan model does not contain posterior draws.", call. = FALSE)
+ }
+ if (!requireNamespace("rstan", quietly = TRUE)) {
+ stop("Please load the 'rstan' package.", call. = FALSE)
+ }
- checkmate::assert_logical(joint, len = 1)
- checkmate::assert_character(log_prior_name, len = 1)
+ checkmate::assert_logical(joint, len = 1)
+ checkmate::assert_character(log_prior_name)
- log_prior <- posterior::subset_draws(
- posterior::as_draws_array(x),
- variable = paste0("^", log_prior_name),
- regex = TRUE
- )
+ log_prior <- posterior::subset_draws(
+ posterior::as_draws_array(x),
+ variable = paste0("^", log_prior_name),
+ regex = TRUE
+ )
- if (joint) {
- log_prior <- rowsums_draws(log_prior)
- posterior::variables(log_prior) <- log_prior_name
- }
+ if (joint) {
+ log_prior <- rowsums_draws(log_prior)
+ posterior::variables(log_prior) <- log_prior_name
+ }
- return(log_prior)
+ return(log_prior)
}
##' @rdname log_prior_draws
##' @export
log_prior_draws.CmdStanFit <- function(
- x,
- joint = FALSE,
- log_prior_name = "lprior",
- ...
+ x,
+ joint = FALSE,
+ log_prior_name = "lprior",
+ ...
) {
- checkmate::assert_logical(joint, len = 1)
- checkmate::assert_character(log_prior_name, len = 1)
+ checkmate::assert_logical(joint, len = 1)
+ checkmate::assert_character(log_prior_name, len = 1)
- all_draws <- x$draws()
+ all_draws <- x$draws()
- log_prior <- posterior::subset_draws(
- all_draws,
- variable = paste0("^", log_prior_name),
- regex = TRUE
- )
+ log_prior <- posterior::subset_draws(
+ all_draws,
+ variable = paste0("^", log_prior_name),
+ regex = TRUE
+ )
- if (joint) {
- log_prior <- rowsums_draws(log_prior)
- posterior::variables(log_prior) <- log_prior_name
- }
+ if (joint) {
+ log_prior <- rowsums_draws(log_prior)
+ posterior::variables(log_prior) <- log_prior_name
+ }
- return(log_prior)
+ return(log_prior)
}
##' @rdname log_prior_draws
##' @export
log_prior_draws.draws <- function(
- x,
- joint = FALSE,
- log_prior_name = "lprior",
- ...
+ x,
+ joint = FALSE,
+ log_prior_name = "lprior",
+ ...
) {
- checkmate::assert_logical(joint, len = 1)
- checkmate::assert_character(log_prior_name, len = 1)
+ checkmate::assert_logical(joint, len = 1)
+ checkmate::assert_character(log_prior_name)
- log_prior <- posterior::subset_draws(
- x,
- variable = paste0("^", log_prior_name),
- regex = TRUE
- )
+ log_prior <- posterior::subset_draws(
+ x,
+ variable = paste0("^", log_prior_name),
+ regex = TRUE
+ )
- if (joint) {
- log_prior <- rowsums_draws(log_prior)
- posterior::variables(log_prior) <- log_prior_name
- }
+ if (joint) {
+ log_prior <- rowsums_draws(log_prior)
+ posterior::variables(log_prior) <- log_prior_name
+ }
- return(log_prior)
+ return(log_prior)
}
From f75467b443e347e05af0511a13ea7b6d7794f1ee Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Sun, 2 Aug 2026 23:54:18 +0300
Subject: [PATCH 03/40] allow variables to be used as an alias of variable in
more funs
---
R/powerscale_sensitivity.R | 340 +++++++++++++++++++------------------
1 file changed, 179 insertions(+), 161 deletions(-)
diff --git a/R/powerscale_sensitivity.R b/R/powerscale_sensitivity.R
index 9eb0760..77e3f97 100644
--- a/R/powerscale_sensitivity.R
+++ b/R/powerscale_sensitivity.R
@@ -8,6 +8,7 @@
##' @param x Model fit object or priorsense_data object.
##' @param ... Further arguments passed to functions.
##' @param variable Character vector of variables to check.
+##' @param variables alias of `variable`.
##' @param lower_alpha Lower alpha value for gradient calculation.
##' @param upper_alpha Upper alpha value for gradient calculation.
##' @param component Character vector specifying component(s) to scale
@@ -32,195 +33,212 @@
##' powerscale_sensitivity(ex$draws)
##' @export
powerscale_sensitivity <- function(x, ...) {
- UseMethod("powerscale_sensitivity")
+ UseMethod("powerscale_sensitivity")
}
##' @rdname powerscale-sensitivity
##' @export
powerscale_sensitivity.default <- function(
- x,
- variable = NULL,
- lower_alpha = 0.99,
- upper_alpha = 1.01,
- div_measure = "cjs_dist",
- measure_args = list(),
- component = c(
- "prior",
- "likelihood"
- ),
- sensitivity_threshold = 0.05,
- moment_match = FALSE,
- k_threshold = 0.5,
- resample = FALSE,
- transform = NULL,
- prediction = NULL,
- prior_selection = NULL,
- likelihood_selection = NULL,
- log_prior_name = "lprior",
- log_lik_name = "log_lik",
- separator = "_",
- num_args = NULL,
- ...
-) {
- psd <- create_priorsense_data(
- x = x,
- log_prior_name = log_prior_name,
- log_lik_name = log_lik_name,
- ...
- )
-
- powerscale_sensitivity.priorsense_data(
- psd,
- variable = variable,
- lower_alpha = lower_alpha,
- upper_alpha = upper_alpha,
- div_measure = div_measure,
- measure_args = measure_args,
- component = component,
- sensitivity_threshold = sensitivity_threshold,
- moment_match = moment_match,
- k_threshold = k_threshold,
- resample = resample,
- transform = transform,
- prediction = prediction,
- prior_selection = prior_selection,
- likelihood_selection = likelihood_selection,
- separator = separator,
- num_args = num_args,
+ x,
+ variable = NULL,
+ variables = NULL,
+ lower_alpha = 0.99,
+ upper_alpha = 1.01,
+ div_measure = "cjs_dist",
+ measure_args = list(),
+ component = c(
+ "prior",
+ "likelihood"
+ ),
+ sensitivity_threshold = 0.05,
+ moment_match = FALSE,
+ k_threshold = 0.5,
+ resample = FALSE,
+ transform = NULL,
+ prediction = NULL,
+ prior_selection = NULL,
+ likelihood_selection = NULL,
+ log_prior_name = "lprior",
+ log_lik_name = "log_lik",
+ separator = "_",
+ num_args = NULL,
...
- )
+) {
+ psd <- create_priorsense_data(
+ x = x,
+ log_prior_name = log_prior_name,
+ log_lik_name = log_lik_name,
+ ...
+ )
+
+ powerscale_sensitivity.priorsense_data(
+ psd,
+ variable = variable,
+ lower_alpha = lower_alpha,
+ upper_alpha = upper_alpha,
+ div_measure = div_measure,
+ measure_args = measure_args,
+ component = component,
+ sensitivity_threshold = sensitivity_threshold,
+ moment_match = moment_match,
+ k_threshold = k_threshold,
+ resample = resample,
+ transform = transform,
+ prediction = prediction,
+ prior_selection = prior_selection,
+ likelihood_selection = likelihood_selection,
+ separator = separator,
+ num_args = num_args,
+ ...
+ )
}
##' @rdname powerscale-sensitivity
##' @export
powerscale_sensitivity.priorsense_data <- function(
- x,
- variable = NULL,
- lower_alpha = 0.99,
- upper_alpha = 1.01,
- div_measure = "cjs_dist",
- measure_args = list(),
- component = c(
- "prior",
- "likelihood"
- ),
- sensitivity_threshold = 0.05,
- moment_match = FALSE,
- k_threshold = 0.5,
- resample = FALSE,
- transform = NULL,
- prediction = NULL,
- prior_selection = NULL,
- likelihood_selection = NULL,
- separator = "_",
- num_args = NULL,
- ...
-) {
- component <- tolower(component)
-
- # input checks
- checkmate::assertCharacter(variable, null.ok = TRUE)
- checkmate::assertNumber(lower_alpha, lower = 0, upper = 1)
- checkmate::assertNumber(upper_alpha, lower = 1)
- checkmate::assertCharacter(div_measure, len = 1)
- checkmate::assertList(measure_args)
- checkmate::assertLogical(moment_match, len = 1)
- checkmate::assertSubset(component, c("prior", "likelihood"))
- checkmate::assertNumber(sensitivity_threshold, lower = 0)
- checkmate::assertNumber(k_threshold, null.ok = TRUE)
- checkmate::assertLogical(resample, len = 1)
- checkmate::assertCharacter(transform, null.ok = TRUE, len = 1)
- checkmate::assertFunction(prediction, null.ok = TRUE)
- checkmate::assertCharacter(separator)
-
- gradients <- powerscale_gradients(
- x = x,
- variable = variable,
- component = component,
- type = "divergence",
- lower_alpha = lower_alpha,
- upper_alpha = upper_alpha,
- moment_match = moment_match,
- div_measure = div_measure,
- measure_args = measure_args,
- transform = transform,
- resample = resample,
- prediction = prediction,
- prior_selection = prior_selection,
- likelihood_selection = likelihood_selection,
- separator = separator,
+ x,
+ variable = NULL,
+ variables = NULL,
+ lower_alpha = 0.99,
+ upper_alpha = 1.01,
+ div_measure = "cjs_dist",
+ measure_args = list(),
+ component = c(
+ "prior",
+ "likelihood"
+ ),
+ sensitivity_threshold = 0.05,
+ moment_match = FALSE,
+ k_threshold = 0.5,
+ resample = FALSE,
+ transform = NULL,
+ prediction = NULL,
+ prior_selection = NULL,
+ likelihood_selection = NULL,
+ separator = "_",
+ num_args = NULL,
...
- )
-
- prior_sense <- gradients$divergence$prior[[2]]
- lik_sense <- gradients$divergence$likelihood[[2]]
-
- if (is.null(lik_sense)) {
- lik_sense <- NA
- }
-
- if (is.null(prior_sense)) {
- prior_sense <- NA
- }
-
- varnames <- unique(c(
- as.character(gradients$divergence$prior$variable),
- as.character(gradients$divergence$likelihood$variable)
- ))
-
- sense <- data.frame(
- variable = varnames,
- prior = prior_sense,
- likelihood = lik_sense
- )
-
- # categorise variables has prior-data conflict or uninformative
- # likelihood
-
- sense$diagnosis <- ifelse(
- sense$prior >= sensitivity_threshold &
- sense$likelihood >= sensitivity_threshold,
- "potential prior-likelihood conflict",
- ifelse(
- sense$prior > sensitivity_threshold &
- sense$likelihood < sensitivity_threshold,
- "potential strong prior / weak likelihood",
- "-"
+) {
+ component <- tolower(component)
+
+ # input checks
+ checkmate::assertCharacter(variable, null.ok = TRUE)
+ checkmate::assertNumber(lower_alpha, lower = 0, upper = 1)
+ checkmate::assertNumber(upper_alpha, lower = 1)
+ checkmate::assertCharacter(div_measure, len = 1)
+ checkmate::assertList(measure_args)
+ checkmate::assertLogical(moment_match, len = 1)
+ checkmate::assertSubset(component, c("prior", "likelihood"))
+ checkmate::assertNumber(sensitivity_threshold, lower = 0)
+ checkmate::assertNumber(k_threshold, null.ok = TRUE)
+ checkmate::assertLogical(resample, len = 1)
+ checkmate::assertCharacter(transform, null.ok = TRUE, len = 1)
+ checkmate::assertFunction(prediction, null.ok = TRUE)
+ checkmate::assertCharacter(separator)
+
+ if (!is.null(variable) && !is.null(variables)) {
+ checkmate::assert(
+ if (identical(variable, variables)) {
+ TRUE
+ } else {
+ "must be identical if both provided"
+ },
+ .var.name = "`variable` and `variables`"
+ )
+ }
+ if (is.null(variable)) {
+ variable <- variables
+ print(variable)
+ }
+
+ gradients <- powerscale_gradients(
+ x = x,
+ variable = variable,
+ component = component,
+ type = "divergence",
+ lower_alpha = lower_alpha,
+ upper_alpha = upper_alpha,
+ moment_match = moment_match,
+ div_measure = div_measure,
+ measure_args = measure_args,
+ transform = transform,
+ resample = resample,
+ prediction = prediction,
+ prior_selection = prior_selection,
+ likelihood_selection = likelihood_selection,
+ separator = separator,
+ ...
+ )
+
+ prior_sense <- gradients$divergence$prior[[2]]
+ lik_sense <- gradients$divergence$likelihood[[2]]
+
+ if (is.null(lik_sense)) {
+ lik_sense <- NA
+ }
+
+ if (is.null(prior_sense)) {
+ prior_sense <- NA
+ }
+
+ varnames <- unique(c(
+ as.character(gradients$divergence$prior$variable),
+ as.character(gradients$divergence$likelihood$variable)
+ ))
+
+ sense <- data.frame(
+ variable = varnames,
+ prior = prior_sense,
+ likelihood = lik_sense
+ )
+
+ # categorise variables has prior-data conflict or uninformative
+ # likelihood
+
+ sense$diagnosis <- ifelse(
+ sense$prior >= sensitivity_threshold &
+ sense$likelihood >= sensitivity_threshold,
+ "potential prior-likelihood conflict",
+ ifelse(
+ sense$prior > sensitivity_threshold &
+ sense$likelihood < sensitivity_threshold,
+ "potential strong prior / weak likelihood",
+ "-"
+ )
)
- )
- out <- sense
+ out <- sense
- class(out) <- c("powerscaled_sensitivity_summary", class(out))
+ class(out) <- c("powerscaled_sensitivity_summary", class(out))
- attr(out, "num_args") <- num_args
- attr(out, "div_measure") <- div_measure
- attr(out, "loadings") <- gradients$loadings
- attr(out, "prior_selection") <- prior_selection
- attr(out, "likelihood_selection") <- likelihood_selection
+ attr(out, "num_args") <- num_args
+ attr(out, "div_measure") <- div_measure
+ attr(out, "loadings") <- gradients$loadings
+ attr(out, "prior_selection") <- prior_selection
+ attr(out, "likelihood_selection") <- likelihood_selection
- return(out)
+ return(out)
}
##' @rdname powerscale-sensitivity
##' @export
powerscale_sensitivity.CmdStanFit <- function(x, ...) {
- psd <- create_priorsense_data.CmdStanFit(x)
+ psd <- create_priorsense_data.CmdStanFit(x)
- powerscale_sensitivity.priorsense_data(
- psd,
- ...
- )
+ powerscale_sensitivity.priorsense_data(
+ psd,
+ ...
+ )
}
##' @rdname powerscale-sensitivity
##' @export
powerscale_sensitivity.stanfit <- function(x, ...) {
- psd <- create_priorsense_data.stanfit(x, ...)
+ psd <- create_priorsense_data.stanfit(x, ...)
- powerscale_sensitivity.priorsense_data(
- psd,
- ...
- )
+ powerscale_sensitivity.priorsense_data(
+ psd,
+ ...
+ )
}
From 156ca45ff6ef1b5478c710e170286518eeb7d9b5 Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Sun, 2 Aug 2026 23:57:35 +0300
Subject: [PATCH 04/40] fix variable(s) passing
---
R/powerscale_sensitivity.R | 3 ++-
man/powerscale-sensitivity.Rd | 4 ++++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/R/powerscale_sensitivity.R b/R/powerscale_sensitivity.R
index 77e3f97..abc2b62 100644
--- a/R/powerscale_sensitivity.R
+++ b/R/powerscale_sensitivity.R
@@ -74,6 +74,7 @@ powerscale_sensitivity.default <- function(
powerscale_sensitivity.priorsense_data(
psd,
variable = variable,
+ variables = variables,
lower_alpha = lower_alpha,
upper_alpha = upper_alpha,
div_measure = div_measure,
@@ -123,6 +124,7 @@ powerscale_sensitivity.priorsense_data <- function(
# input checks
checkmate::assertCharacter(variable, null.ok = TRUE)
+ checkmate::assertCharacter(variables, null.ok = TRUE)
checkmate::assertNumber(lower_alpha, lower = 0, upper = 1)
checkmate::assertNumber(upper_alpha, lower = 1)
checkmate::assertCharacter(div_measure, len = 1)
@@ -148,7 +150,6 @@ powerscale_sensitivity.priorsense_data <- function(
}
if (is.null(variable)) {
variable <- variables
- print(variable)
}
gradients <- powerscale_gradients(
diff --git a/man/powerscale-sensitivity.Rd b/man/powerscale-sensitivity.Rd
index ff071f6..26647b7 100644
--- a/man/powerscale-sensitivity.Rd
+++ b/man/powerscale-sensitivity.Rd
@@ -14,6 +14,7 @@ powerscale_sensitivity(x, ...)
\method{powerscale_sensitivity}{default}(
x,
variable = NULL,
+ variables = NULL,
lower_alpha = 0.99,
upper_alpha = 1.01,
div_measure = "cjs_dist",
@@ -37,6 +38,7 @@ powerscale_sensitivity(x, ...)
\method{powerscale_sensitivity}{priorsense_data}(
x,
variable = NULL,
+ variables = NULL,
lower_alpha = 0.99,
upper_alpha = 1.01,
div_measure = "cjs_dist",
@@ -66,6 +68,8 @@ powerscale_sensitivity(x, ...)
\item{variable}{Character vector of variables to check.}
+\item{variables}{alias of \code{variable}.}
+
\item{lower_alpha}{Lower alpha value for gradient calculation.}
\item{upper_alpha}{Upper alpha value for gradient calculation.}
From bfa26c949c640188ecc7e5f4893534497d9bb6ac Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Fri, 11 Sep 2026 10:53:45 +0300
Subject: [PATCH 05/40] display help text in console only
---
R/plots.R | 1986 +++++++++++++++++++++++++++--------------------------
1 file changed, 999 insertions(+), 987 deletions(-)
diff --git a/R/plots.R b/R/plots.R
index 1049983..cd42e2d 100644
--- a/R/plots.R
+++ b/R/plots.R
@@ -42,112 +42,114 @@ NULL
##' @keywords internal
##' @noRd
prepare_plot_data <- function(x, variable, resample, ...) {
- base_draws <- posterior::merge_chains(x$base_draws)
-
- if (!resample && !(x$resampled)) {
- base_draws <- posterior::weight_draws(
- x = base_draws,
- weights = rep(
- 1 / posterior::ndraws(base_draws),
- posterior::ndraws(base_draws)
- )
- )
- }
+ base_draws <- posterior::merge_chains(x$base_draws)
+
+ if (!resample && !(x$resampled)) {
+ base_draws <- posterior::weight_draws(
+ x = base_draws,
+ weights = rep(
+ 1 / posterior::ndraws(base_draws),
+ posterior::ndraws(base_draws)
+ )
+ )
+ }
- likelihood_draws <- list()
- prior_draws <- list()
- base_draws_prior <- data.frame()
- base_draws_lik <- data.frame()
+ likelihood_draws <- list()
+ prior_draws <- list()
+ base_draws_prior <- data.frame()
+ base_draws_lik <- data.frame()
- if (!(is.null(x$prior_scaled))) {
- prior_scaled <- x$prior_scaled$draws_sequence
+ if (!(is.null(x$prior_scaled))) {
+ prior_scaled <- x$prior_scaled$draws_sequence
- for (i in seq_along(prior_scaled)) {
- prior_draws[[i]] <- posterior::merge_chains(prior_scaled[[i]])
+ for (i in seq_along(prior_scaled)) {
+ prior_draws[[i]] <- posterior::merge_chains(prior_scaled[[i]])
- if (resample && !x$resampled) {
- prior_draws[[i]] <- posterior::resample_draws(prior_draws[[i]])
- }
+ if (resample && !x$resampled) {
+ prior_draws[[i]] <- posterior::resample_draws(prior_draws[[i]])
+ }
- prior_ps_details <- get_powerscaling_details(prior_scaled[[i]])
+ prior_ps_details <- get_powerscaling_details(prior_scaled[[i]])
- prior_draws[[i]][[".powerscale_alpha"]] <- prior_ps_details$alpha
- prior_draws[[i]]$component <- "prior"
- prior_draws[[i]]$pareto_k <- prior_ps_details$diagnostics$khat
- prior_draws[[i]]$pareto_k_threshold <-
- prior_ps_details$diagnostics$khat_threshold
+ prior_draws[[i]][[".powerscale_alpha"]] <- prior_ps_details$alpha
+ prior_draws[[i]]$component <- "prior"
+ prior_draws[[i]]$pareto_k <- prior_ps_details$diagnostics$khat
+ prior_draws[[i]]$pareto_k_threshold <-
+ prior_ps_details$diagnostics$khat_threshold
+ }
+
+ base_draws_prior <- base_draws
+ base_draws_prior[[".powerscale_alpha"]] <- 1
+ base_draws_prior$component <- "prior"
+ base_draws_prior$pareto_k <- -Inf
+ base_draws_prior$pareto_k_threshold <- Inf
}
- base_draws_prior <- base_draws
- base_draws_prior[[".powerscale_alpha"]] <- 1
- base_draws_prior$component <- "prior"
- base_draws_prior$pareto_k <- -Inf
- base_draws_prior$pareto_k_threshold <- Inf
- }
+ if (!(is.null(x$likelihood_scaled))) {
+ likelihood_scaled <- x$likelihood_scaled$draws_sequence
- if (!(is.null(x$likelihood_scaled))) {
- likelihood_scaled <- x$likelihood_scaled$draws_sequence
+ for (i in seq_along(likelihood_scaled)) {
+ likelihood_draws[[i]] <- posterior::merge_chains(
+ likelihood_scaled[[i]]
+ )
- for (i in seq_along(likelihood_scaled)) {
- likelihood_draws[[i]] <- posterior::merge_chains(
- likelihood_scaled[[i]]
- )
+ if (resample && !x$resampled) {
+ likelihood_draws[[i]] <- posterior::resample_draws(
+ likelihood_draws[[i]]
+ )
+ }
- if (resample && !x$resampled) {
- likelihood_draws[[i]] <- posterior::resample_draws(
- likelihood_draws[[i]]
- )
- }
+ likelihood_ps_details <- get_powerscaling_details(
+ likelihood_scaled[[i]]
+ )
- likelihood_ps_details <- get_powerscaling_details(
- likelihood_scaled[[i]]
- )
+ likelihood_draws[[i]][[".powerscale_alpha"]] <-
+ likelihood_ps_details$alpha
- likelihood_draws[[i]][[".powerscale_alpha"]] <-
- likelihood_ps_details$alpha
+ likelihood_draws[[i]]$component <- "likelihood"
- likelihood_draws[[i]]$component <- "likelihood"
+ likelihood_draws[[
+ i
+ ]]$pareto_k <- likelihood_ps_details$diagnostics$khat
- likelihood_draws[[i]]$pareto_k <- likelihood_ps_details$diagnostics$khat
+ likelihood_draws[[i]]$pareto_k_threshold <-
+ likelihood_ps_details$diagnostics$khat_threshold
+ }
- likelihood_draws[[i]]$pareto_k_threshold <-
- likelihood_ps_details$diagnostics$khat_threshold
+ base_draws_lik <- base_draws
+ base_draws_lik[[".powerscale_alpha"]] <- 1
+ base_draws_lik$component <- "likelihood"
+ base_draws_lik$pareto_k <- -Inf
+ base_draws_lik$pareto_k_threshold <- Inf
}
- base_draws_lik <- base_draws
- base_draws_lik[[".powerscale_alpha"]] <- 1
- base_draws_lik$component <- "likelihood"
- base_draws_lik$pareto_k <- -Inf
- base_draws_lik$pareto_k_threshold <- Inf
- }
-
- d <- rbind(
- do.call("rbind", prior_draws),
- do.call("rbind", likelihood_draws),
- base_draws_lik,
- base_draws_prior
- )
-
- d$pareto_k_value <- ifelse(d$pareto_k > d$pareto_k_threshold, "High", "OK")
-
- d$pareto_k_value <- factor(
- d$pareto_k_value,
- levels = c("OK", "High")
- )
-
- d$component <- factor(d$component, levels = c("prior", "likelihood"))
-
- # prepare for plotting
- d <- stats::reshape(
- data = as.data.frame(d),
- varying = variable,
- direction = "long",
- times = variable,
- v.names = "value",
- timevar = "variable"
- )
-
- return(d)
+ d <- rbind(
+ do.call("rbind", prior_draws),
+ do.call("rbind", likelihood_draws),
+ base_draws_lik,
+ base_draws_prior
+ )
+
+ d$pareto_k_value <- ifelse(d$pareto_k > d$pareto_k_threshold, "High", "OK")
+
+ d$pareto_k_value <- factor(
+ d$pareto_k_value,
+ levels = c("OK", "High")
+ )
+
+ d$component <- factor(d$component, levels = c("prior", "likelihood"))
+
+ # prepare for plotting
+ d <- stats::reshape(
+ data = as.data.frame(d),
+ varying = variable,
+ direction = "long",
+ times = variable,
+ v.names = "value",
+ timevar = "variable"
+ )
+
+ return(d)
}
##' prepare plot
##' @param d data frame of data from plotting
@@ -159,816 +161,805 @@ prepare_plot_data <- function(x, variable, resample, ...) {
##' @keywords internal
##' @noRd
prepare_plot <- function(d, resample, variable, colors, ...) {
- if (resample) {
- p <- ggplot2::ggplot(
- data = d,
- ggplot2::aes(
- x = .data$value,
- group = .data[[".powerscale_alpha"]],
- color = .data[[".powerscale_alpha"]],
- linetype = .data$pareto_k_value
- )
- )
- } else {
- p <- ggplot2::ggplot(
- data = d,
- ggplot2::aes(
- x = .data$value,
- weight = exp(.data$.log_weight),
- group = .data[[".powerscale_alpha"]],
- color = .data[[".powerscale_alpha"]],
- linetype = .data$pareto_k_value
- )
- )
- }
-
- p <- p +
- ggplot2::scale_linetype_manual(
- values = c("solid", "dashed"),
- drop = TRUE,
- name = "Pareto k"
- ) +
- ggplot2::scale_color_gradientn(
- name = "Power-scaling alpha",
- colours = colors[1:3],
- trans = "log",
- limits = c(
- min(d[[".powerscale_alpha"]]) - 0.01,
- max(d[[".powerscale_alpha"]]) + 0.01
- ),
- breaks = c(
- min(d[[".powerscale_alpha"]]),
- 1,
- max(d[[".powerscale_alpha"]])
- ),
- labels = c(
- round(min(d[[".powerscale_alpha"]]), digits = 3),
- "1",
- round(max(d[[".powerscale_alpha"]]), digits = 3)
- )
- ) +
- ggplot2::scale_fill_gradientn(
- colours = c(colors[1:3]),
- trans = "log",
- limits = c(
- min(d[[".powerscale_alpha"]]) - 0.01,
- max(d[[".powerscale_alpha"]]) + 0.01
- ),
- breaks = c(
- min(d[[".powerscale_alpha"]]),
- 1,
- max(d[[".powerscale_alpha"]])
- ),
- labels = c(
- round(min(d[[".powerscale_alpha"]]), digits = 3),
- "1",
- round(max(d[[".powerscale_alpha"]]), digits = 3)
- )
- )
+ if (resample) {
+ p <- ggplot2::ggplot(
+ data = d,
+ ggplot2::aes(
+ x = .data$value,
+ group = .data[[".powerscale_alpha"]],
+ color = .data[[".powerscale_alpha"]],
+ linetype = .data$pareto_k_value
+ )
+ )
+ } else {
+ p <- ggplot2::ggplot(
+ data = d,
+ ggplot2::aes(
+ x = .data$value,
+ weight = exp(.data$.log_weight),
+ group = .data[[".powerscale_alpha"]],
+ color = .data[[".powerscale_alpha"]],
+ linetype = .data$pareto_k_value
+ )
+ )
+ }
- if (length(unique(d[[".powerscale_alpha"]])) == 3) {
p <- p +
- ggplot2::guides(
- color = ggplot2::guide_legend(
- override.aes = ggplot2::aes(linetype = "solid")
+ ggplot2::scale_linetype_manual(
+ values = c("solid", "dashed"),
+ drop = TRUE,
+ name = "Pareto k"
+ ) +
+ ggplot2::scale_color_gradientn(
+ name = "Power-scaling alpha",
+ colours = colors[1:3],
+ trans = "log",
+ limits = c(
+ min(d[[".powerscale_alpha"]]) - 0.01,
+ max(d[[".powerscale_alpha"]]) + 0.01
+ ),
+ breaks = c(
+ min(d[[".powerscale_alpha"]]),
+ 1,
+ max(d[[".powerscale_alpha"]])
+ ),
+ labels = c(
+ round(min(d[[".powerscale_alpha"]]), digits = 3),
+ "1",
+ round(max(d[[".powerscale_alpha"]]), digits = 3)
+ )
+ ) +
+ ggplot2::scale_fill_gradientn(
+ colours = c(colors[1:3]),
+ trans = "log",
+ limits = c(
+ min(d[[".powerscale_alpha"]]) - 0.01,
+ max(d[[".powerscale_alpha"]]) + 0.01
+ ),
+ breaks = c(
+ min(d[[".powerscale_alpha"]]),
+ 1,
+ max(d[[".powerscale_alpha"]])
+ ),
+ labels = c(
+ round(min(d[[".powerscale_alpha"]]), digits = 3),
+ "1",
+ round(max(d[[".powerscale_alpha"]]), digits = 3)
+ )
)
- )
- }
- if (!(any(d$pareto_k_value == "High"))) {
- p <- p +
- ggplot2::guides(
- linetype = "none"
- )
- }
+ if (length(unique(d[[".powerscale_alpha"]])) == 3) {
+ p <- p +
+ ggplot2::guides(
+ color = ggplot2::guide_legend(
+ override.aes = ggplot2::aes(linetype = "solid")
+ )
+ )
+ }
- return(p)
+ if (!(any(d$pareto_k_value == "High"))) {
+ p <- p +
+ ggplot2::guides(
+ linetype = "none"
+ )
+ }
+
+ return(p)
}
##' @rdname powerscale-plots
##' @export
powerscale_plot_dens <- function(x, ...) {
- UseMethod("powerscale_plot_dens")
+ UseMethod("powerscale_plot_dens")
}
##' @export
powerscale_plot_dens.default <-
- function(
- x,
- variable = NULL,
- variables = NULL,
- length = 3,
- resample = FALSE,
- intervals = c(0.5, 0.8, 0.95),
- trim = NULL,
- facet_rows = "component",
- help_text = getOption("priorsense.plot_help_text", TRUE),
- colors = NULL,
- colours = NULL,
- variables_per_page = 6,
- ...
- ) {
- ps <- powerscale_sequence(x, length = length, ...)
- powerscale_plot_dens(
- ps,
- variable = variable,
- variables = variables,
- length = length,
- resample = resample,
- intervals = intervals,
- trim = trim,
- facet_rows = facet_rows,
- help_text = help_text,
- colors = colors,
- colours = colours,
- variables_per_page = variables_per_page
- )
- }
+ function(
+ x,
+ variable = NULL,
+ variables = NULL,
+ length = 3,
+ resample = FALSE,
+ intervals = c(0.5, 0.8, 0.95),
+ trim = NULL,
+ facet_rows = "component",
+ help_text = getOption("priorsense.plot_help_text", TRUE),
+ colors = NULL,
+ colours = NULL,
+ variables_per_page = 6,
+ ...
+ ) {
+ ps <- powerscale_sequence(x, length = length, ...)
+ powerscale_plot_dens(
+ ps,
+ variable = variable,
+ variables = variables,
+ length = length,
+ resample = resample,
+ intervals = intervals,
+ trim = trim,
+ facet_rows = facet_rows,
+ help_text = help_text,
+ colors = colors,
+ colours = colours,
+ variables_per_page = variables_per_page
+ )
+ }
draw_key_path2 <- function(data, params, size) {
- grid::segmentsGrob(
- x0 = 0.1,
- x1 = 0.9,
- y0 = 0.5,
- y1 = 0.5,
- gp = grid::gpar(col = data$colour)
- )
+ grid::segmentsGrob(
+ x0 = 0.1,
+ x1 = 0.9,
+ y0 = 0.5,
+ y1 = 0.5,
+ gp = grid::gpar(col = data$colour)
+ )
}
##' @export
powerscale_plot_dens.powerscaled_sequence <-
- function(
- x,
- variable = NULL,
- variables = NULL,
- resample = FALSE,
- intervals = c(0.5, 0.8, 0.95),
- trim = NULL,
- facet_rows = "component",
- help_text = getOption("priorsense.plot_help_text", TRUE),
- colors = NULL,
- colours = NULL,
- variables_per_page = getOption(
- "priorsense.plot_variables_per_page",
- 6
- ),
- ...
- ) {
- # input checks
- if (!is.null(variable) && !is.null(variables)) {
- checkmate::assert(
- if (identical(variable, variables)) {
- TRUE
- } else {
- "must be identical if both provided"
- },
- .var.name = "`variable` and `variables`"
- )
- }
- if (is.null(variable)) {
- variable <- variables
- }
-
- if (!is.null(colors) && !is.null(colours)) {
- checkmate::assert(
- if (identical(colors, colours)) {
- TRUE
- } else {
- "must be identical if both provided"
- },
- .var.name = "`colors` and `colours`"
- )
- }
- if (is.null(colors)) {
- colors <- colours
- }
-
- checkmate::assert_character(variable, null.ok = TRUE)
- checkmate::assert_logical(resample, len = 1)
- checkmate::assert_logical(help_text, len = 1)
- checkmate::assert_character(colors, len = 3, null.ok = TRUE)
- checkmate::assert_numeric(intervals, null.ok = TRUE)
- checkmate::assert_choice(facet_rows, c("component", "variable"))
- checkmate::assert_number(variables_per_page, lower = 1, null.ok = TRUE)
-
- if (is.null(colors)) {
- colors <- default_priorsense_colors()[1:3]
- }
-
- if (is.null(variable)) {
- variable <- posterior::variables(x$base_draws)
- } else {
- variable <- posterior::variables(
- posterior::subset_draws(x$base_draws, variable = variable)
- )
- }
-
- nvars <- length(variable)
+ function(
+ x,
+ variable = NULL,
+ variables = NULL,
+ resample = FALSE,
+ intervals = c(0.5, 0.8, 0.95),
+ trim = NULL,
+ facet_rows = "component",
+ help_text = getOption("priorsense.plot_help_text", TRUE),
+ colors = NULL,
+ colours = NULL,
+ variables_per_page = getOption(
+ "priorsense.plot_variables_per_page",
+ 6
+ ),
+ ...
+ ) {
+ # input checks
+ if (!is.null(variable) && !is.null(variables)) {
+ checkmate::assert(
+ if (identical(variable, variables)) {
+ TRUE
+ } else {
+ "must be identical if both provided"
+ },
+ .var.name = "`variable` and `variables`"
+ )
+ }
+ if (is.null(variable)) {
+ variable <- variables
+ }
- if (is.null(variables_per_page) || is.infinite(variables_per_page)) {
- variables_per_page <- nvars
- }
+ if (!is.null(colors) && !is.null(colours)) {
+ checkmate::assert(
+ if (identical(colors, colours)) {
+ TRUE
+ } else {
+ "must be identical if both provided"
+ },
+ .var.name = "`colors` and `colours`"
+ )
+ }
+ if (is.null(colors)) {
+ colors <- colours
+ }
- variables_per_page <- floor(variables_per_page)
+ checkmate::assert_character(variable, null.ok = TRUE)
+ checkmate::assert_logical(resample, len = 1)
+ checkmate::assert_logical(help_text, len = 1)
+ checkmate::assert_character(colors, len = 3, null.ok = TRUE)
+ checkmate::assert_numeric(intervals, null.ok = TRUE)
+ checkmate::assert_choice(facet_rows, c("component", "variable"))
+ checkmate::assert_number(variables_per_page, lower = 1, null.ok = TRUE)
- n_plots <- ceiling(nvars / variables_per_page)
- plots <- vector(mode = "list", length = n_plots)
+ if (is.null(colors)) {
+ colors <- default_priorsense_colors()[1:3]
+ }
- d <- prepare_plot_data(x, variable = variable, resample = resample, ...)
+ if (is.null(variable)) {
+ variable <- posterior::variables(x$base_draws)
+ } else {
+ variable <- posterior::variables(
+ posterior::subset_draws(x$base_draws, variable = variable)
+ )
+ }
- interval_positions <- data.frame(
- ".powerscale_alpha" = unique(d[[".powerscale_alpha"]]),
- interval_y = as.numeric(as.factor(unique(d[[".powerscale_alpha"]])))
- )
+ nvars <- length(variable)
- interval_positions$interval_y <- (0.5 - (interval_positions$interval_y)) /
- (6 * nrow(interval_positions))
+ if (is.null(variables_per_page) || is.infinite(variables_per_page)) {
+ variables_per_page <- nvars
+ }
- d <- merge(d, interval_positions)
+ variables_per_page <- floor(variables_per_page)
- n_components <- length(unique(d$component))
+ n_plots <- ceiling(nvars / variables_per_page)
+ plots <- vector(mode = "list", length = n_plots)
- for (i in seq_len(n_plots)) {
- sub <- ((i - 1) *
- variables_per_page +
- 1):min(i * variables_per_page, nvars)
- sub_variable <- variable[sub]
-
- if (resample || x$resample) {
- resample <- TRUE
- }
-
- dsub <- d[d$variable %in% sub_variable, ]
-
- plot <- prepare_plot(dsub, resample = resample, colors = colors, ...) +
- ggplot2::ylab("Density")
-
- # here we have to draw 2 stat slabs (one with alpha 0 and black fill,
- # one with fill as NA) to get the legend correct see
- # https://github.com/mjskay/ggdist/issues/134
- plot <- plot +
- ggdist::stat_slab(
- fill = NA,
- linewidth = 0.5,
- trim = FALSE,
- normalize = "xy",
- key_glyph = draw_key_path2
- ) +
- ggplot2::xlab(NULL) +
- ggplot2::ylab(NULL)
-
- if (!is.null(intervals)) {
- plot <- plot +
- ggdist::stat_pointinterval(
- ggplot2::aes(y = .data$interval_y),
- .width = intervals,
- fill = NA,
- trim = FALSE,
- normalize = "xy",
- show.legend = FALSE
- )
- }
-
- if (facet_rows == "component") {
- plot <- plot +
- ggh4x::facet_grid2(
- rows = ggplot2::vars(.data$component),
- cols = ggplot2::vars(.data$variable),
- labeller = ggplot2::labeller(
- component = c(
- likelihood = "Likelihood\npower-scaling",
- prior = "Prior\npower-scaling"
- )
- ),
- independent = "all",
- scales = "free",
- switch = "y"
- )
- } else {
- plot <- plot +
- ggh4x::facet_grid2(
- rows = ggplot2::vars(.data$variable),
- cols = ggplot2::vars(.data$component),
- labeller = ggplot2::labeller(
- component = c(
- likelihood = "Likelihood\npower-scaling",
- prior = "Prior\npower-scaling"
- )
- ),
- independent = "all",
- scales = "free",
- switch = "y"
- )
- }
-
- if (help_text) {
- plot <- plot +
- ggplot2::ggtitle(
- label = "Power-scaling sensitivity",
- subtitle = paste0(
- "Posterior density estimates depending on ",
- "amount of power-scaling (alpha).\n",
- "Overlapping lines indicate low sensitivity.\n",
- "Wider gaps between lines indicate greater sensitivity.\n",
- "Estimates with high Pareto k (dashed lines) may be inaccurate."
- )
- )
- }
-
- # additional theming
- plot <- plot +
- ggplot2::theme(
- axis.line.y = ggplot2::element_blank(),
- axis.text.y = ggplot2::element_blank(),
- axis.ticks.y = ggplot2::element_blank()
- )
+ d <- prepare_plot_data(x, variable = variable, resample = resample, ...)
- if (facet_rows == "component") {
- plot <- plot +
- ggplot2::theme(legend.position = "bottom")
- }
-
- if (!is.null(trim)) {
- position_scales <- lapply(
- variable,
- FUN = function(.x, prob) {
- limits <- posterior::quantile2(
- x$base_draws[[.x]],
- probs = c((1 - prob) / 2, prob + (1 - prob) / 2)
- )
- return(ggplot2::scale_x_continuous(limits = limits))
- },
- prob = trim
+ interval_positions <- data.frame(
+ ".powerscale_alpha" = unique(d[[".powerscale_alpha"]]),
+ interval_y = as.numeric(as.factor(unique(d[[".powerscale_alpha"]])))
)
- if (facet_rows == "component") {
- plot <- plot +
- ggh4x::facetted_pos_scales(
- x = rep(
- position_scales,
- times = 2
- )
- )
- } else {
- plot <- plot +
- ggh4x::facetted_pos_scales(
- x = rep(
- position_scales,
- each = 2
- )
- )
+ interval_positions$interval_y <- (0.5 -
+ (interval_positions$interval_y)) /
+ (6 * nrow(interval_positions))
+
+ d <- merge(d, interval_positions)
+
+ n_components <- length(unique(d$component))
+
+ for (i in seq_len(n_plots)) {
+ sub <- ((i - 1) *
+ variables_per_page +
+ 1):min(i * variables_per_page, nvars)
+ sub_variable <- variable[sub]
+
+ if (resample || x$resample) {
+ resample <- TRUE
+ }
+
+ dsub <- d[d$variable %in% sub_variable, ]
+
+ plot <- prepare_plot(
+ dsub,
+ resample = resample,
+ colors = colors,
+ ...
+ ) +
+ ggplot2::ylab("Density")
+
+ # here we have to draw 2 stat slabs (one with alpha 0 and black fill,
+ # one with fill as NA) to get the legend correct see
+ # https://github.com/mjskay/ggdist/issues/134
+ plot <- plot +
+ ggdist::stat_slab(
+ fill = NA,
+ linewidth = 0.5,
+ trim = FALSE,
+ normalize = "xy",
+ key_glyph = draw_key_path2
+ ) +
+ ggplot2::xlab(NULL) +
+ ggplot2::ylab(NULL)
+
+ if (!is.null(intervals)) {
+ plot <- plot +
+ ggdist::stat_pointinterval(
+ ggplot2::aes(y = .data$interval_y),
+ .width = intervals,
+ fill = NA,
+ trim = FALSE,
+ normalize = "xy",
+ show.legend = FALSE
+ )
+ }
+
+ if (facet_rows == "component") {
+ plot <- plot +
+ ggh4x::facet_grid2(
+ rows = ggplot2::vars(.data$component),
+ cols = ggplot2::vars(.data$variable),
+ labeller = ggplot2::labeller(
+ component = c(
+ likelihood = "Likelihood\npower-scaling",
+ prior = "Prior\npower-scaling"
+ )
+ ),
+ independent = "all",
+ scales = "free",
+ switch = "y"
+ )
+ } else {
+ plot <- plot +
+ ggh4x::facet_grid2(
+ rows = ggplot2::vars(.data$variable),
+ cols = ggplot2::vars(.data$component),
+ labeller = ggplot2::labeller(
+ component = c(
+ likelihood = "Likelihood\npower-scaling",
+ prior = "Prior\npower-scaling"
+ )
+ ),
+ independent = "all",
+ scales = "free",
+ switch = "y"
+ )
+ }
+
+ if (help_text) {
+ plot_help_text(type = "density")
+ }
+
+ # additional theming
+ plot <- plot +
+ ggplot2::theme(
+ axis.line.y = ggplot2::element_blank(),
+ axis.text.y = ggplot2::element_blank(),
+ axis.ticks.y = ggplot2::element_blank()
+ )
+
+ if (facet_rows == "component") {
+ plot <- plot +
+ ggplot2::theme(legend.position = "bottom")
+ }
+
+ if (!is.null(trim)) {
+ position_scales <- lapply(
+ variable,
+ FUN = function(.x, prob) {
+ limits <- posterior::quantile2(
+ x$base_draws[[.x]],
+ probs = c((1 - prob) / 2, prob + (1 - prob) / 2)
+ )
+ return(ggplot2::scale_x_continuous(limits = limits))
+ },
+ prob = trim
+ )
+
+ if (facet_rows == "component") {
+ plot <- plot +
+ ggh4x::facetted_pos_scales(
+ x = rep(
+ position_scales,
+ times = 2
+ )
+ )
+ } else {
+ plot <- plot +
+ ggh4x::facetted_pos_scales(
+ x = rep(
+ position_scales,
+ each = 2
+ )
+ )
+ }
+ }
+
+ plots[[i]] <- plot
}
- }
- plots[[i]] <- plot
- }
+ class(plots) <- c("priorsense_plot", class(plots))
- class(plots) <- c("priorsense_plot", class(plots))
+ if (length(plots) == 1) {
+ plots <- plots[[1]]
+ }
- if (length(plots) == 1) {
- plots <- plots[[1]]
+ return(plots)
}
- return(plots)
- }
-
##' @rdname powerscale-plots
##' @export
powerscale_plot_ecdf <- function(x, ...) {
- UseMethod("powerscale_plot_ecdf")
+ UseMethod("powerscale_plot_ecdf")
}
##' @export
powerscale_plot_ecdf.default <-
- function(
- x,
- variable = NULL,
- variables = NULL,
- length = 3,
- resample = FALSE,
- facet_rows = "component",
- help_text = getOption("priorsense.plot_help_text", TRUE),
- colors = NULL,
- colours = NULL,
- variables_per_page = getOption(
- "priorsense.plot_variables_per_page",
- 6
- ),
- ...
- ) {
- ps <- powerscale_sequence(x, length = length, ...)
- powerscale_plot_ecdf(
- ps,
- variable = variable,
- variables = variables,
- resample = resample,
- facet_rows = facet_rows,
- help_text = help_text,
- colors = colors,
- colours = colours,
- variables_per_page = variables_per_page
- )
- }
+ function(
+ x,
+ variable = NULL,
+ variables = NULL,
+ length = 3,
+ resample = FALSE,
+ facet_rows = "component",
+ help_text = getOption("priorsense.plot_help_text", TRUE),
+ colors = NULL,
+ colours = NULL,
+ variables_per_page = getOption(
+ "priorsense.plot_variables_per_page",
+ 6
+ ),
+ ...
+ ) {
+ ps <- powerscale_sequence(x, length = length, ...)
+ powerscale_plot_ecdf(
+ ps,
+ variable = variable,
+ variables = variables,
+ resample = resample,
+ facet_rows = facet_rows,
+ help_text = help_text,
+ colors = colors,
+ colours = colours,
+ variables_per_page = variables_per_page
+ )
+ }
##' @rdname powerscale-plots
##' @export
powerscale_plot_ecdf.powerscaled_sequence <-
- function(
- x,
- variable = NULL,
- variables = NULL,
- resample = FALSE,
- length = 3,
- facet_rows = "component",
- help_text = getOption("priorsense.plot_help_text", TRUE),
- colors = NULL,
- colours = NULL,
- variables_per_page = getOption(
- "priorsense.plot_variables_per_page",
- 6
- ),
- ...
- ) {
- # input checks
- if (!is.null(variable) && !is.null(variables)) {
- checkmate::assert(
- if (identical(variable, variables)) {
- TRUE
- } else {
- "must be identical if both provided"
- },
- .var.name = "`variable` and `variables`"
- )
- }
- if (is.null(variable)) {
- variable <- variables
- }
-
- if (!is.null(colors) && !is.null(colours)) {
- checkmate::assert(
- if (identical(colors, colours)) {
- TRUE
- } else {
- "must be identical if both provided"
- },
- .var.name = "`colors` and `colours`"
- )
- }
- if (is.null(colors)) {
- colors <- colours
- }
-
- checkmate::assert_character(variable, null.ok = TRUE)
- checkmate::assert_logical(resample, len = 1)
- checkmate::assert_logical(help_text, len = 1)
- checkmate::assertCharacter(colors, len = 3, null.ok = TRUE)
- checkmate::assert_choice(facet_rows, c("component", "variable"))
- checkmate::assert_number(variables_per_page, lower = 1, null.ok = TRUE)
-
- if (is.null(colors)) {
- colors <- default_priorsense_colors()[1:3]
- }
-
- if (is.null(variable)) {
- variable <- posterior::variables(x$base_draws)
- } else {
- variable <- posterior::variables(
- posterior::subset_draws(x$base_draws, variable = variable)
- )
- }
+ function(
+ x,
+ variable = NULL,
+ variables = NULL,
+ resample = FALSE,
+ length = 3,
+ facet_rows = "component",
+ help_text = getOption("priorsense.plot_help_text", TRUE),
+ colors = NULL,
+ colours = NULL,
+ variables_per_page = getOption(
+ "priorsense.plot_variables_per_page",
+ 6
+ ),
+ ...
+ ) {
+ # input checks
+ if (!is.null(variable) && !is.null(variables)) {
+ checkmate::assert(
+ if (identical(variable, variables)) {
+ TRUE
+ } else {
+ "must be identical if both provided"
+ },
+ .var.name = "`variable` and `variables`"
+ )
+ }
+ if (is.null(variable)) {
+ variable <- variables
+ }
- d <- prepare_plot_data(x, variable = variable, resample = resample, ...)
+ if (!is.null(colors) && !is.null(colours)) {
+ checkmate::assert(
+ if (identical(colors, colours)) {
+ TRUE
+ } else {
+ "must be identical if both provided"
+ },
+ .var.name = "`colors` and `colours`"
+ )
+ }
+ if (is.null(colors)) {
+ colors <- colours
+ }
- n_components <- length(unique(d$component))
+ checkmate::assert_character(variable, null.ok = TRUE)
+ checkmate::assert_logical(resample, len = 1)
+ checkmate::assert_logical(help_text, len = 1)
+ checkmate::assertCharacter(colors, len = 3, null.ok = TRUE)
+ checkmate::assert_choice(facet_rows, c("component", "variable"))
+ checkmate::assert_number(variables_per_page, lower = 1, null.ok = TRUE)
- if (resample || x$resample) {
- resample <- TRUE
- }
+ if (is.null(colors)) {
+ colors <- default_priorsense_colors()[1:3]
+ }
- nvars <- length(variable)
+ if (is.null(variable)) {
+ variable <- posterior::variables(x$base_draws)
+ } else {
+ variable <- posterior::variables(
+ posterior::subset_draws(x$base_draws, variable = variable)
+ )
+ }
- if (is.null(variables_per_page) || is.infinite(variables_per_page)) {
- variables_per_page <- nvars
- }
+ d <- prepare_plot_data(x, variable = variable, resample = resample, ...)
- variables_per_page <- floor(variables_per_page)
+ n_components <- length(unique(d$component))
- n_plots <- ceiling(nvars / variables_per_page)
- plots <- vector(mode = "list", length = n_plots)
+ if (resample || x$resample) {
+ resample <- TRUE
+ }
- for (i in seq_len(n_plots)) {
- sub <- ((i - 1) * variables_per_page + 1):min(
- i * variables_per_page,
- nvars
- )
- sub_variable <- variable[sub]
-
- dsub <- d[d$variable %in% sub_variable, ]
-
- p <- prepare_plot(dsub, resample = resample, colors = colors, ...) +
- ggplot2::guides(
- linetype = ggplot2::guide_legend(
- title = "Pareto k"
- )
- ) +
- ggplot2::ylab("ECDF") +
- ggplot2::xlab(NULL)
+ nvars <- length(variable)
- p <- p +
- ggplot2::stat_ecdf(ggplot2::aes(color = .data[[".powerscale_alpha"]]))
+ if (is.null(variables_per_page) || is.infinite(variables_per_page)) {
+ variables_per_page <- nvars
+ }
- if (facet_rows == "component") {
- p <- p +
- ggh4x::facet_grid2(
- rows = ggplot2::vars(.data$component),
- cols = ggplot2::vars(.data$variable),
- labeller = ggplot2::labeller(
- component = c(
- likelihood = "Likelihood\npower-scaling",
- prior = "Prior\npower-scaling"
- )
- ),
- scales = "free",
- independent = "all",
- switch = "y"
- )
- } else {
- p <- p +
- ggh4x::facet_grid2(
- rows = ggplot2::vars(.data$variable),
- cols = ggplot2::vars(.data$component),
- labeller = ggplot2::labeller(
- component = c(
- likelihood = "Likelihood\npower-scaling",
- prior = "Prior\npower-scaling"
- )
- ),
- scales = "free",
- independent = "all",
- switch = "y"
- )
- }
+ variables_per_page <- floor(variables_per_page)
- if (!(any(d$pareto_k_value == "High"))) {
- p <- p +
- ggplot2::guides(linetype = "none")
- }
+ n_plots <- ceiling(nvars / variables_per_page)
+ plots <- vector(mode = "list", length = n_plots)
- if (help_text) {
- p <- p +
- ggplot2::ggtitle(
- label = "Power-scaling sensitivity",
- subtitle = paste0(
- "Posterior ECDF depending on amount of power-scaling (alpha).\n",
- "Overlapping lines indicate low sensitivity.\n",
- "Wider gaps between lines indicate greater sensitivity.\n",
- "Estimates with high Pareto k (dashed lines) may be inaccurate."
+ for (i in seq_len(n_plots)) {
+ sub <- ((i - 1) * variables_per_page + 1):min(
+ i * variables_per_page,
+ nvars
)
- )
- }
- if (facet_rows == "component") {
- p <- p +
- ggplot2::theme(legend.position = "bottom")
- }
+ sub_variable <- variable[sub]
+
+ dsub <- d[d$variable %in% sub_variable, ]
+
+ p <- prepare_plot(dsub, resample = resample, colors = colors, ...) +
+ ggplot2::guides(
+ linetype = ggplot2::guide_legend(
+ title = "Pareto k"
+ )
+ ) +
+ ggplot2::ylab("ECDF") +
+ ggplot2::xlab(NULL)
+
+ p <- p +
+ ggplot2::stat_ecdf(ggplot2::aes(
+ color = .data[[".powerscale_alpha"]]
+ ))
+
+ if (facet_rows == "component") {
+ p <- p +
+ ggh4x::facet_grid2(
+ rows = ggplot2::vars(.data$component),
+ cols = ggplot2::vars(.data$variable),
+ labeller = ggplot2::labeller(
+ component = c(
+ likelihood = "Likelihood\npower-scaling",
+ prior = "Prior\npower-scaling"
+ )
+ ),
+ scales = "free",
+ independent = "all",
+ switch = "y"
+ )
+ } else {
+ p <- p +
+ ggh4x::facet_grid2(
+ rows = ggplot2::vars(.data$variable),
+ cols = ggplot2::vars(.data$component),
+ labeller = ggplot2::labeller(
+ component = c(
+ likelihood = "Likelihood\npower-scaling",
+ prior = "Prior\npower-scaling"
+ )
+ ),
+ scales = "free",
+ independent = "all",
+ switch = "y"
+ )
+ }
+
+ if (!(any(d$pareto_k_value == "High"))) {
+ p <- p +
+ ggplot2::guides(linetype = "none")
+ }
+
+ if (help_text) {
+ plot_help_text("ECDF")
+ }
+ if (facet_rows == "component") {
+ p <- p +
+ ggplot2::theme(legend.position = "bottom")
+ }
+
+ plots[[i]] <- p
+ }
- plots[[i]] <- p
- }
+ class(plots) <- c("priorsense_plot", class(plots))
- class(plots) <- c("priorsense_plot", class(plots))
+ if (length(plots) == 1) {
+ plots <- plots[[1]]
+ }
- if (length(plots) == 1) {
- plots <- plots[[1]]
+ return(plots)
}
- return(plots)
- }
-
##' @rdname powerscale-plots
##' @export
powerscale_plot_quantities <- function(x, ...) {
- UseMethod("powerscale_plot_quantities")
+ UseMethod("powerscale_plot_quantities")
}
##' @export
powerscale_plot_quantities.default <-
- function(
- x,
- variable = NULL,
- variables = NULL,
- quantity = c("mean", "sd"),
- div_measure = "cjs_dist",
- length = 11,
- resample = FALSE,
- measure_args = NULL,
- mcse = TRUE,
- quantity_args = NULL,
- help_text = getOption("priorsense.plot_help_text", TRUE),
- colors = NULL,
- colours = NULL,
- variables_per_page = getOption(
- "priorsense.plot_variables_per_page",
- 6
- ),
- ...
- ) {
- ps <- powerscale_sequence(x, length = length, ...)
-
- powerscale_plot_quantities(
- ps,
- variable = variable,
- variables = variables,
- quantity = quantity,
- div_measure = div_measure,
- resample = resample,
- measure_args = measure_args,
- mcse = mcse,
- quantity_args = quantity_args,
- help_text = help_text,
- colors = colors,
- colours = colours,
- variables_per_page = variables_per_page
- )
- }
+ function(
+ x,
+ variable = NULL,
+ variables = NULL,
+ quantity = c("mean", "sd"),
+ div_measure = "cjs_dist",
+ length = 11,
+ resample = FALSE,
+ measure_args = NULL,
+ mcse = TRUE,
+ quantity_args = NULL,
+ help_text = getOption("priorsense.plot_help_text", TRUE),
+ colors = NULL,
+ colours = NULL,
+ variables_per_page = getOption(
+ "priorsense.plot_variables_per_page",
+ 6
+ ),
+ ...
+ ) {
+ ps <- powerscale_sequence(x, length = length, ...)
+
+ powerscale_plot_quantities(
+ ps,
+ variable = variable,
+ variables = variables,
+ quantity = quantity,
+ div_measure = div_measure,
+ resample = resample,
+ measure_args = measure_args,
+ mcse = mcse,
+ quantity_args = quantity_args,
+ help_text = help_text,
+ colors = colors,
+ colours = colours,
+ variables_per_page = variables_per_page
+ )
+ }
##' @rdname powerscale-plots
##' @export
powerscale_plot_quantities.powerscaled_sequence <-
- function(
- x,
- variable = NULL,
- variables = NULL,
- quantity = c("mean", "sd"),
- div_measure = "cjs_dist",
- resample = FALSE,
- measure_args = NULL,
- mcse = TRUE,
- quantity_args = NULL,
- help_text = getOption("priorsense.plot_help_text", TRUE),
- colors = NULL,
- colours = NULL,
- variables_per_page = getOption(
- "priorsense.plot_variables_per_page",
- 6
- ),
- ...
- ) {
- if (!is.null(variable) && !is.null(variables)) {
- checkmate::assert(
- if (identical(variable, variables)) {
- TRUE
- } else {
- "must be identical if both provided"
- },
- .var.name = "`variable` and `variables`"
- )
- }
- if (is.null(variable)) {
- variable <- variables
- }
+ function(
+ x,
+ variable = NULL,
+ variables = NULL,
+ quantity = c("mean", "sd"),
+ div_measure = "cjs_dist",
+ resample = FALSE,
+ measure_args = NULL,
+ mcse = TRUE,
+ quantity_args = NULL,
+ help_text = getOption("priorsense.plot_help_text", TRUE),
+ colors = NULL,
+ colours = NULL,
+ variables_per_page = getOption(
+ "priorsense.plot_variables_per_page",
+ 6
+ ),
+ ...
+ ) {
+ if (!is.null(variable) && !is.null(variables)) {
+ checkmate::assert(
+ if (identical(variable, variables)) {
+ TRUE
+ } else {
+ "must be identical if both provided"
+ },
+ .var.name = "`variable` and `variables`"
+ )
+ }
+ if (is.null(variable)) {
+ variable <- variables
+ }
- if (!is.null(colors) && !is.null(colours)) {
- checkmate::assert(
- if (identical(colors, colours)) {
- TRUE
- } else {
- "must be identical if both provided"
- },
- .var.name = "`colors` and `colours`"
- )
- }
- if (is.null(colors)) {
- colors <- colours
- }
+ if (!is.null(colors) && !is.null(colours)) {
+ checkmate::assert(
+ if (identical(colors, colours)) {
+ TRUE
+ } else {
+ "must be identical if both provided"
+ },
+ .var.name = "`colors` and `colours`"
+ )
+ }
+ if (is.null(colors)) {
+ colors <- colours
+ }
- checkmate::assertCharacter(variable, null.ok = TRUE)
- checkmate::assertCharacter(quantity)
- checkmate::assertCharacter(div_measure, null.ok = TRUE)
- checkmate::assertLogical(resample, len = 1)
- checkmate::assertList(measure_args, null.ok = TRUE)
- checkmate::assertLogical(mcse, len = 1)
- checkmate::assertList(quantity_args, null.ok = TRUE)
- checkmate::assertLogical(help_text, len = 1)
- checkmate::assertCharacter(colors, len = 2, null.ok = TRUE)
- checkmate::assert_number(variables_per_page, lower = 1, null.ok = TRUE)
-
- if (is.null(colors)) {
- colors <- default_priorsense_colors()[4:5]
- }
+ checkmate::assertCharacter(variable, null.ok = TRUE)
+ checkmate::assertCharacter(quantity)
+ checkmate::assertCharacter(div_measure, null.ok = TRUE)
+ checkmate::assertLogical(resample, len = 1)
+ checkmate::assertList(measure_args, null.ok = TRUE)
+ checkmate::assertLogical(mcse, len = 1)
+ checkmate::assertList(quantity_args, null.ok = TRUE)
+ checkmate::assertLogical(help_text, len = 1)
+ checkmate::assertCharacter(colors, len = 2, null.ok = TRUE)
+ checkmate::assert_number(variables_per_page, lower = 1, null.ok = TRUE)
+
+ if (is.null(colors)) {
+ colors <- default_priorsense_colors()[4:5]
+ }
- names(quantity) <- quantity
+ names(quantity) <- quantity
- summ <- summarise_draws(
- x,
- quantity,
- .args = quantity_args,
- resample = resample,
- div_measures = div_measure,
- measure_args = measure_args
- )
+ summ <- summarise_draws(
+ x,
+ quantity,
+ .args = quantity_args,
+ resample = resample,
+ div_measures = div_measure,
+ measure_args = measure_args
+ )
- if (is.null(variable)) {
- variable <- posterior::variables(x$base_draws)
- } else {
- # Efficient variable expansion avoiding heavy subset_draws operations
- base_vars <- posterior::variables(x$base_draws)
+ if (is.null(variable)) {
+ variable <- posterior::variables(x$base_draws)
+ } else {
+ # Efficient variable expansion avoiding heavy subset_draws operations
+ base_vars <- posterior::variables(x$base_draws)
- expanded_vars <- lapply(variable, function(v) {
- # Keep variable if it matches exactly
- if (v %in% base_vars) {
- return(v)
- }
+ expanded_vars <- lapply(variable, function(v) {
+ # Keep variable if it matches exactly
+ if (v %in% base_vars) {
+ return(v)
+ }
+
+ # Check for indexed variables (e.g., "a" -> "a[1]", "a[2]")
+ prefix <- paste0(v, "[")
+ indexed_matches <- base_vars[startsWith(base_vars, prefix)]
- # Check for indexed variables (e.g., "a" -> "a[1]", "a[2]")
- prefix <- paste0(v, "[")
- indexed_matches <- base_vars[startsWith(base_vars, prefix)]
+ if (length(indexed_matches) > 0) {
+ return(indexed_matches)
+ }
- if (length(indexed_matches) > 0) {
- return(indexed_matches)
+ # Return original string if no match (downstream handles errors)
+ return(v)
+ })
+
+ variable <- unique(unlist(expanded_vars))
}
- # Return original string if no match (downstream handles errors)
- return(v)
- })
+ if (mcse) {
+ quants <- setdiff(
+ colnames(summ[[1]]),
+ c(
+ "variable",
+ ".powerscale_alpha",
+ "component",
+ "pareto_k",
+ "pareto_kf",
+ "pareto_k_threshold",
+ "n_eff",
+ div_measure
+ )
+ )
- variable <- unique(unlist(expanded_vars))
- }
+ mcse_functions <- paste0("mcse_", quantity)
- if (mcse) {
- quants <- setdiff(
- colnames(summ[[1]]),
- c(
- "variable",
- ".powerscale_alpha",
- "component",
- "pareto_k",
- "pareto_kf",
- "pareto_k_threshold",
- "n_eff",
- div_measure
- )
- )
+ base_quantities <- summ[[1]][
+ which(summ[[1]][[".powerscale_alpha"]] == 1),
+ ]
- mcse_functions <- paste0("mcse_", quantity)
+ base_quantities <- unique(base_quantities[c("variable", quants)])
- base_quantities <- summ[[1]][
- which(summ[[1]][[".powerscale_alpha"]] == 1),
- ]
+ base_q <- as.data.frame(base_quantities)
- base_quantities <- unique(base_quantities[c("variable", quants)])
+ base_q <- as.data.frame(base_quantities)
- base_q <- as.data.frame(base_quantities)
+ base_q <- stats::reshape(
+ data = base_q,
+ varying = quants,
+ direction = "long",
+ times = quants,
+ v.names = "value",
+ timevar = "quantity",
+ idvar = "variable"
+ )
- base_q <- as.data.frame(base_quantities)
+ base_mcse <- posterior::summarise_draws(
+ x$base_draws,
+ mcse_functions,
+ .args = quantity_args
+ )
+ base_mcse <- base_mcse[which(base_mcse$variable %in% variable), ]
+ base_mcse <- as.data.frame(base_mcse)
+
+ mcse_names <- colnames(base_mcse)[-1]
+
+ base_mcse <- stats::reshape(
+ data = base_mcse,
+ varying = mcse_names,
+ direction = "long",
+ times = quants,
+ v.names = "mcse",
+ timevar = "quantity",
+ idvar = "variable"
+ )
- base_q <- stats::reshape(
- data = base_q,
- varying = quants,
- direction = "long",
- times = quants,
- v.names = "value",
- timevar = "quantity",
- idvar = "variable"
- )
-
- base_mcse <- posterior::summarise_draws(
- x$base_draws,
- mcse_functions,
- .args = quantity_args
- )
- base_mcse <- base_mcse[which(base_mcse$variable %in% variable), ]
- base_mcse <- as.data.frame(base_mcse)
-
- mcse_names <- colnames(base_mcse)[-1]
-
- base_mcse <- stats::reshape(
- data = base_mcse,
- varying = mcse_names,
- direction = "long",
- times = quants,
- v.names = "mcse",
- timevar = "quantity",
- idvar = "variable"
- )
-
- base_mcse <- merge(base_q, base_mcse)
- base_mcse$mcse_min <- base_mcse$value - 2 * base_mcse$mcse
- base_mcse$mcse_max <- base_mcse$value + 2 * base_mcse$mcse
- } else {
- base_mcse <- NULL
- }
+ base_mcse <- merge(base_q, base_mcse)
+ base_mcse$mcse_min <- base_mcse$value - 2 * base_mcse$mcse
+ base_mcse$mcse_max <- base_mcse$value + 2 * base_mcse$mcse
+ } else {
+ base_mcse <- NULL
+ }
- powerscale_summary_plot(
- summ,
- variable = variable,
- base_mcse = base_mcse,
- help_text = help_text,
- colors = colors,
- variables_per_page = variables_per_page,
- ...
- )
- }
+ powerscale_summary_plot(
+ summ,
+ variable = variable,
+ base_mcse = base_mcse,
+ help_text = help_text,
+ colors = colors,
+ variables_per_page = variables_per_page,
+ ...
+ )
+ }
##' power-scale summary plot
##'
##' internal function for powerscale_plot_quantities
@@ -985,212 +976,209 @@ powerscale_plot_quantities.powerscaled_sequence <-
##' @keywords internal
##' @noRd
powerscale_summary_plot <- function(
- x,
- variable,
- base_mcse = NULL,
- help_text,
- colors,
- variables_per_page,
- ...
+ x,
+ variable,
+ base_mcse = NULL,
+ help_text,
+ colors,
+ variables_per_page,
+ ...
) {
- nvars <- length(variable)
-
- if (is.null(variables_per_page) || is.infinite(variables_per_page)) {
- variables_per_page <- nvars
- }
-
- variables_per_page <- floor(variables_per_page)
-
- n_plots <- ceiling(nvars / variables_per_page)
- plots <- vector(mode = "list", length = n_plots)
-
- pareto_k_colours <- colors
-
- # get default quantities
- quantities <- setdiff(
- colnames(x[[1]]),
- c(
- "variable",
- ".powerscale_alpha",
- "component",
- "pareto_k",
- "pareto_kf",
- "n_eff",
- "pareto_k_threshold"
- )
- )
-
- for (i in seq_len(n_plots)) {
- sub <- ((i - 1) * variables_per_page + 1):min(i * variables_per_page, nvars)
- sub_variable <- variable[sub]
- # select only specified variables
- xsub <- x[[1]][x[[1]][["variable"]] %in% sub_variable, ]
-
- sub_mcse <- base_mcse[base_mcse$variable %in% sub_variable, ]
-
- # reshape quantities for plotting
- summaries <- stats::reshape(
- data = xsub,
- varying = quantities,
- direction = "long",
- times = quantities,
- v.names = "value",
- timevar = "quantity"
- )
+ nvars <- length(variable)
- summaries$pareto_k_value <- ifelse(
- summaries$pareto_k > summaries$pareto_k_threshold,
- "High",
- "OK"
- )
+ if (is.null(variables_per_page) || is.infinite(variables_per_page)) {
+ variables_per_page <- nvars
+ }
- summaries$pareto_k_value <- factor(
- summaries$pareto_k_value,
- levels = c("OK", "High")
+ variables_per_page <- floor(variables_per_page)
+
+ n_plots <- ceiling(nvars / variables_per_page)
+ plots <- vector(mode = "list", length = n_plots)
+
+ pareto_k_colours <- colors
+
+ # get default quantities
+ quantities <- setdiff(
+ colnames(x[[1]]),
+ c(
+ "variable",
+ ".powerscale_alpha",
+ "component",
+ "pareto_k",
+ "pareto_kf",
+ "n_eff",
+ "pareto_k_threshold"
+ )
)
- # subset for plotting points at ends of lines
- points <- summaries[
- summaries[[".powerscale_alpha"]] ==
- min(summaries[[".powerscale_alpha"]]) |
- summaries[[".powerscale_alpha"]] ==
- max(summaries[[".powerscale_alpha"]]),
- ]
-
- p <- ggplot2::ggplot(
- data = summaries,
- mapping = ggplot2::aes(x = .data[[".powerscale_alpha"]], y = .data$value)
- ) +
- ggplot2::geom_line(ggplot2::aes(
- color = .data$pareto_k_value,
- group = .data$component
- )) +
- ggh4x::facet_grid2(
- rows = ggplot2::vars(factor(
- .data$variable,
- levels = unique(.data$variable)
- )),
- cols = ggplot2::vars(factor(
- .data$quantity,
- levels = unique(.data$quantity)
- )),
- scales = "free",
- switch = "y",
- independent = "all"
- ) +
- ggplot2::geom_point(
- ggplot2::aes(
- x = .data[[".powerscale_alpha"]],
- y = .data$value,
- shape = .data$component,
- colour = .data$pareto_k_value
- ),
- fill = "white",
- size = 3,
- data = points
- ) +
- ggplot2::scale_shape_manual(
- values = c("likelihood" = 22, "prior" = 15)
- ) +
- ggplot2::scale_color_manual(values = pareto_k_colours) +
- ggplot2::guides(
- color = ggplot2::guide_legend(
- title = "Pareto k",
- override.aes = list(shape = 15)
+ for (i in seq_len(n_plots)) {
+ sub <- ((i - 1) * variables_per_page + 1):min(
+ i * variables_per_page,
+ nvars
+ )
+ sub_variable <- variable[sub]
+ # select only specified variables
+ xsub <- x[[1]][x[[1]][["variable"]] %in% sub_variable, ]
+
+ sub_mcse <- base_mcse[base_mcse$variable %in% sub_variable, ]
+
+ # reshape quantities for plotting
+ summaries <- stats::reshape(
+ data = xsub,
+ varying = quantities,
+ direction = "long",
+ times = quantities,
+ v.names = "value",
+ timevar = "quantity"
)
- ) +
- ggplot2::ylab(NULL) +
- ggplot2::scale_x_continuous(
- trans = "log2",
- limits = c(
- 0.95 * min(summaries[[".powerscale_alpha"]]),
- 1.05 * max(summaries[[".powerscale_alpha"]])
- ),
- breaks = c(
- min(summaries[[".powerscale_alpha"]]),
- 1,
- max(summaries[[".powerscale_alpha"]])
- ),
- labels = round(
- c(
- min(summaries[[".powerscale_alpha"]]),
- 1,
- max(summaries[[".powerscale_alpha"]])
- ),
- digits = 3
- ),
- name = "Power-scaling alpha"
- )
- if (!(any(summaries$pareto_k_value == "High"))) {
- p <- p +
- ggplot2::guides(
- colour = "none"
+ summaries$pareto_k_value <- ifelse(
+ summaries$pareto_k > summaries$pareto_k_threshold,
+ "High",
+ "OK"
)
- }
- if (help_text) {
- p <- p +
- ggplot2::ggtitle(
- label = "Power-scaling sensitivity",
- subtitle = paste0(
- "Posterior quantities depending on amount of power-scaling (alpha).\n",
- "Horizontal lines indicate low sensitivity.\n",
- "Steeper lines indicate greater sensitivity.\n",
- "Estimates with high Pareto k (highlighted) may be inaccurate."
- )
+ summaries$pareto_k_value <- factor(
+ summaries$pareto_k_value,
+ levels = c("OK", "High")
)
- }
- if (!is.null(sub_mcse)) {
- p <- p +
- ggplot2::scale_linetype_manual(values = "dashed", name = NULL) +
- ggplot2::geom_hline(
- ggplot2::aes(
- yintercept = .data$mcse_min,
- linetype = "+/-2MCSE"
- ),
- data = sub_mcse,
- color = "black"
+ # subset for plotting points at ends of lines
+ points <- summaries[
+ summaries[[".powerscale_alpha"]] ==
+ min(summaries[[".powerscale_alpha"]]) |
+ summaries[[".powerscale_alpha"]] ==
+ max(summaries[[".powerscale_alpha"]]),
+ ]
+
+ p <- ggplot2::ggplot(
+ data = summaries,
+ mapping = ggplot2::aes(
+ x = .data[[".powerscale_alpha"]],
+ y = .data$value
+ )
) +
- ggplot2::geom_hline(
- ggplot2::aes(
- yintercept = .data$mcse_max,
- linetype = "+/-2MCSE"
- ),
- data = sub_mcse,
- color = "black"
- )
- }
+ ggplot2::geom_line(ggplot2::aes(
+ color = .data$pareto_k_value,
+ group = .data$component
+ )) +
+ ggh4x::facet_grid2(
+ rows = ggplot2::vars(factor(
+ .data$variable,
+ levels = unique(.data$variable)
+ )),
+ cols = ggplot2::vars(factor(
+ .data$quantity,
+ levels = unique(.data$quantity)
+ )),
+ scales = "free",
+ switch = "y",
+ independent = "all"
+ ) +
+ ggplot2::geom_point(
+ ggplot2::aes(
+ x = .data[[".powerscale_alpha"]],
+ y = .data$value,
+ shape = .data$component,
+ colour = .data$pareto_k_value
+ ),
+ fill = "white",
+ size = 3,
+ data = points
+ ) +
+ ggplot2::scale_shape_manual(
+ values = c("likelihood" = 22, "prior" = 15)
+ ) +
+ ggplot2::scale_color_manual(values = pareto_k_colours) +
+ ggplot2::guides(
+ color = ggplot2::guide_legend(
+ title = "Pareto k",
+ override.aes = list(shape = 15)
+ )
+ ) +
+ ggplot2::ylab(NULL) +
+ ggplot2::scale_x_continuous(
+ trans = "log2",
+ limits = c(
+ 0.95 * min(summaries[[".powerscale_alpha"]]),
+ 1.05 * max(summaries[[".powerscale_alpha"]])
+ ),
+ breaks = c(
+ min(summaries[[".powerscale_alpha"]]),
+ 1,
+ max(summaries[[".powerscale_alpha"]])
+ ),
+ labels = round(
+ c(
+ min(summaries[[".powerscale_alpha"]]),
+ 1,
+ max(summaries[[".powerscale_alpha"]])
+ ),
+ digits = 3
+ ),
+ name = "Power-scaling alpha"
+ )
+
+ if (!(any(summaries$pareto_k_value == "High", na.rm = TRUE))) {
+ p <- p +
+ ggplot2::guides(
+ colour = "none"
+ )
+ }
- plots[[i]] <- p
- }
+ if (help_text) {
+ plot_help_text("quantities")
+ }
+
+ if (!is.null(sub_mcse)) {
+ p <- p +
+ ggplot2::scale_linetype_manual(values = "dashed", name = NULL) +
+ ggplot2::geom_hline(
+ ggplot2::aes(
+ yintercept = .data$mcse_min,
+ linetype = "+/-2MCSE"
+ ),
+ data = sub_mcse,
+ color = "black"
+ ) +
+ ggplot2::geom_hline(
+ ggplot2::aes(
+ yintercept = .data$mcse_max,
+ linetype = "+/-2MCSE"
+ ),
+ data = sub_mcse,
+ color = "black"
+ )
+ }
+
+ plots[[i]] <- p
+ }
- class(plots) <- c("priorsense_plot", class(plots))
+ class(plots) <- c("priorsense_plot", class(plots))
- if (length(plots) == 1) {
- plots <- plots[[1]]
- }
+ if (length(plots) == 1) {
+ plots <- plots[[1]]
+ }
- return(plots)
+ return(plots)
}
##' @exportS3Method
plot.priorsense_plot <- function(
- x,
- ask = getOption("priorsense.plot_ask", TRUE),
- ...
+ x,
+ ask = getOption("priorsense.plot_ask", TRUE),
+ ...
) {
- grDevices::devAskNewPage(ask = FALSE)
- on.exit(grDevices::devAskNewPage(ask = FALSE))
+ grDevices::devAskNewPage(ask = FALSE)
+ on.exit(grDevices::devAskNewPage(ask = FALSE))
- for (i in seq_along(x)) {
- plot(x[[i]], newpage = TRUE)
- if (i == 1) {
- grDevices::devAskNewPage(ask = ask)
+ for (i in seq_along(x)) {
+ plot(x[[i]], newpage = TRUE, help_text = FALSE)
+ if (i == 1) {
+ grDevices::devAskNewPage(ask = ask)
+ }
}
- }
- invisible(x)
+ invisible(x)
}
@@ -1201,10 +1189,34 @@ print.priorsense_plot <- plot.priorsense_plot
##' @exportS3Method
##' @rdname powerscale-plots
plot.powerscaled_sequence <- function(
- x,
- type = c("dens", "ecdf", "quantities"),
- ...
+ x,
+ type = c("dens", "ecdf", "quantities"),
+ ...
) {
- type <- match.arg(type)
- do.call(paste0("powerscale_plot_", type), args = list(x = x, ...))
+ type <- match.arg(type)
+ do.call(paste0("powerscale_plot_", type), args = list(x = x, ...))
+}
+
+
+plot_help_text <- function(type) {
+ cli::cli_h2("Power-scaling sensitivity {type} plot:")
+ if (type %in% c("density", "ECDF")) {
+ cli::cli_text(
+ "The plot shows posterior {type} depending on ",
+ "the degree of power-scaling (alpha).\n",
+ "Overlapping lines indicate low sensitivity.\n",
+ "Wider gaps between lines indicate greater sensitivity.\n",
+ "Estimates with high Pareto k (dashed lines) may be inaccurate.\n"
+ )
+ } else if (type == "quantities") {
+ cli::cli_text(
+ "Posterior quantities depending on amount of power-scaling (alpha).\n",
+ "Horizontal lines indicate low sensitivity.\n",
+ "Steeper lines indicate greater sensitivity.\n",
+ "Estimates with high Pareto k (highlighted) may be inaccurate.\n"
+ )
+ }
+ cli::cli_text(
+ "Disable this help text with `help_text = FALSE` or `options(priorsense.plot_help_text = FALSE)`"
+ )
}
From aaa816ca650e5f9edd95f5d96b7b09d4c5794bab Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Fri, 11 Sep 2026 10:54:01 +0300
Subject: [PATCH 06/40] prepare migration to stan-dev
---
CONTRIBUTING.md | 6 ---
DESCRIPTION | 11 +++---
README.md | 10 ++---
README.qmd | 10 ++---
_pkgdown.yml | 97 ++++++++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 111 insertions(+), 23 deletions(-)
delete mode 100644 CONTRIBUTING.md
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index 7e1fd12..0000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# Contributing
-
-Contributions are welcome! If you find an bug or have an idea for a feature, open an issue. If you are able to fix an issue, fork the repository and make a pull request to the `development` branch.
-
-## Lifecycle
-priorsense is in a stable state of development, with some degree of active subsequent development as envisioned by the primary authors and in response to user feedback.
diff --git a/DESCRIPTION b/DESCRIPTION
index eb16057..f806d8d 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,6 +1,6 @@
Package: priorsense
Title: Prior Diagnostics and Sensitivity Analysis
-Version: 1.3.1
+Version: 1.3.1.9000
Authors@R: c(person("Noa", "Kallioinen", email = "noa.kallioinen@helsinki.fi", role = c("aut", "cre", "cph"), comment = c(ORCID = "0000-0003-1586-8382")),
person("Topi", "Paananen", role = c("aut"), comment = c(ORCID = "0000-0002-6542-407X")),
person("Paul-Christian", "Bürkner", role = c("aut"), comment = c(ORCID = "0000-0001-5765-8995")),
@@ -14,9 +14,9 @@ License: GPL (>= 3)
Encoding: UTF-8
LazyData: true
Roxygen: list(markdown = TRUE, roclets = c ("namespace", "rd", "srr::srr_stats_roclet"))
-RoxygenNote: 8.0.0
Imports:
checkmate (>= 2.3.4),
+ cli,
ggdist (>= 3.3.3),
ggh4x (>= 0.3.1),
ggplot2 (>= 4.0.3),
@@ -48,6 +48,7 @@ VignetteBuilder: quarto
Additional_repositories:
https://topipa.r-universe.dev,
https://stan-dev.r-universe.dev
-URL: https://n-kall.github.io/priorsense/, https://github.com/n-kall/priorsense
-BugReports: https://github.com/n-kall/priorsense/issues
-Config/Needs/website: quarto
+URL: https://mc-stan.org/priorsense/, https://mc-stan.org/priorsense
+BugReports: https://github.com/stan-dev/priorsense/issues
+Config/Needs/website: quarto, stan-dev/pkgdown-config
+Config/roxygen2/version: 8.1.0
diff --git a/README.md b/README.md
index 4a52b48..4a512da 100644
--- a/README.md
+++ b/README.md
@@ -9,10 +9,10 @@
state and is being actively
developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
[](https://n-kall.r-universe.dev)
+badge](https://stan-dev.r-universe.dev/badges/priorsense)](https://stan-dev.r-universe.dev)
[](https://cran.r-project.org/package=priorsense)
-[](https://github.com/n-kall/priorsense/actions)
+[](https://github.com/stan-dev/priorsense/actions)
[](https://github.com/ropensci/software-review/issues/704)
[](https://doi.org/10.21105/joss.11036)
@@ -42,11 +42,11 @@ al. (2023)](https://doi.org/10.1007/s11222-023-10366-5).
### Resources
- Check the [getting started
- vignette](https://n-kall.github.io/priorsense/articles/getting_started.html)
+ vignette](https://mc-stan.org/priorsense/articles/getting_started.html)
for a simple example
- For a more detailed modelling example see
- [here](https://n-kall.github.io/priorsense/articles/airquality.html)
+ [here](https://mc-stan.org/priorsense/articles/airquality.html)
### Installation
@@ -61,7 +61,7 @@ with:
``` r
# install.packages("pak")
-pak::pkg_install("n-kall/priorsense@development")
+pak::pkg_install("stan-dev/priorsense@development")
```
### Contributing
diff --git a/README.qmd b/README.qmd
index 935067a..d0081f9 100644
--- a/README.qmd
+++ b/README.qmd
@@ -13,9 +13,9 @@ ggplot2::theme_set(bayesplot::theme_default(base_family = "sans"))
[](https://www.repostatus.org/#active)
-[](https://n-kall.r-universe.dev)
+[](https://stan-dev.r-universe.dev)
[](https://cran.r-project.org/package=priorsense)
-[](https://github.com/n-kall/priorsense/actions)
+[](https://github.com/stan-dev/priorsense/actions)
[](https://github.com/ropensci/software-review/issues/704)
[](https://doi.org/10.21105/joss.11036)
@@ -41,11 +41,11 @@ from other software. Power-scaling sensitivity analysis checks are described in
### Resources
- Check the [getting started
- vignette](https://n-kall.github.io/priorsense/articles/getting_started.html)
+ vignette](https://mc-stan.org/priorsense/articles/getting_started.html)
for a simple example
- For a more detailed modelling example see
- [here](https://n-kall.github.io/priorsense/articles/airquality.html)
+ [here](https://mc-stan.org/priorsense/articles/airquality.html)
### Installation
@@ -61,7 +61,7 @@ Download the development version from [GitHub](https://github.com/) with:
```{r}
#| eval: false
# install.packages("pak")
-pak::pkg_install("n-kall/priorsense@development")
+pak::pkg_install("stan-dev/priorsense@development")
```
### Contributing
diff --git a/_pkgdown.yml b/_pkgdown.yml
index 4f6227a..808fbb3 100644
--- a/_pkgdown.yml
+++ b/_pkgdown.yml
@@ -1,4 +1,97 @@
-url: https://n-kall.github.io/priorsense/
+url: https://mc-stan.org/priorsense/
+
+destination: "."
+
+development:
+ mode: auto
+
template:
- bootstrap: 5
+ package: pkgdownconfig
+
+navbar:
+ title: "priorsense"
+
+ structure:
+ left: [home, vignettes, functions, news, pkgs, stan]
+ right: [search, bluesky, forum, github, lightswitch]
+
+ components:
+ pkgs:
+ text: Other Packages
+ menu:
+ - text: bayesplot
+ href: https://mc-stan.org/bayesplot
+ - text: cmdstanr
+ href: https://mc-stan.org/cmdstanr
+ - text: loo
+ href: https://mc-stan.org/loo
+ - text: posterior
+ href: https://mc-stan.org/posterior
+ - text: projpred
+ href: https://mc-stan.org/projpred
+ - text: rstan
+ href: https://mc-stan.org/rstan
+ - text: rstanarm
+ href: https://mc-stan.org/rstanarm
+ - text: rstantools
+ href: https://mc-stan.org/rstantools
+ - text: shinystan
+ href: https://mc-stan.org/shinystan
+
+articles:
+ - title: Getting started
+ desc: |
+ These vignettes demonstrate how to use the **priorsense** package to check prior and likelihood sensitivity for Bayesian models fit using MCMC.
+ contents:
+ - getting_started
+ - priorsense_with_stan
+ - priorsense_with_brms
+ - priorsense_with_jags
+ - priorsense_with_nimble
+ - title: Additional topics
+ desc: |
+ These vignettes demonstrate how to use the **priorsense** package in more detail.
+ contents:
+ - airquality
+ - title: Further details
+ contents:
+ - sensitivity_diagnostic
+ - quantity_of_interest
+ - used_by
+
+reference:
+ - title: Package description
+ contents:
+ - priorsense-package
+ - title: Primary power-scaling sensitivity checks
+ desc: |
+ Numerical sensitivity checks for prior and likelihood
+ contents:
+ - powerscale_sensitivity
+ - title: Graphical checks
+ desc: |
+ Plots for power-scaling sensitivity checks
+ contents:
+ - powerscale_plot_dens
+ - powerscale_plot_ecdf
+ - powerscale_plot_quantities
+ - title: Example models
+ desc: |
+ Provides example model code and data for different PPLs compatible with priorsense
+ contents:
+ - example_powerscale_model
+ - title: Other functions for exploring sensitivity
+ contents:
+ - powerscale
+ - powerscale_sequence
+ - powerscale_derivative
+ - powerscale_gradients
+ - create_priorsense_data
+ - title: Helper functions
+ contents:
+ - create_priorsense_data
+ - log_lik_draws
+ - log_prior_draws
+ - predictions_as_draws
+ - cjs_dist
From f8029323f1eb31f2fa8d765546dbb67e0f5b2e3e Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Fri, 11 Sep 2026 11:24:54 +0300
Subject: [PATCH 07/40] change title
---
_pkgdown.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/_pkgdown.yml b/_pkgdown.yml
index 808fbb3..857f883 100644
--- a/_pkgdown.yml
+++ b/_pkgdown.yml
@@ -48,7 +48,7 @@ articles:
- priorsense_with_brms
- priorsense_with_jags
- priorsense_with_nimble
- - title: Additional topics
+ - title: Additional examples
desc: |
These vignettes demonstrate how to use the **priorsense** package in more detail.
contents:
From b20b6fb1d4f93df82cc665c1684555465d034df5 Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Fri, 11 Sep 2026 11:25:39 +0300
Subject: [PATCH 08/40] add stan contributing guide
---
.github/CONTRIBUTING.md | 58 +++++++++++++++++++++++++++++++++++++++++
man/figures/logo.svg | 1 +
2 files changed, 59 insertions(+)
create mode 100644 .github/CONTRIBUTING.md
create mode 100644 man/figures/logo.svg
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
new file mode 100644
index 0000000..62d32fa
--- /dev/null
+++ b/.github/CONTRIBUTING.md
@@ -0,0 +1,58 @@
+# Contributing to priorsense
+
+This outlines how to propose a change to priorsense and is based on similar
+instructions for tidyverse packages, including the contributing guidelines
+generated by `usethis::use_tidy_contributing()`.
+
+## Fixing typos
+
+You can fix typos, spelling mistakes, or grammatical errors in the documentation
+directly using the GitHub web interface, as long as the changes are made in the
+_source_ file. This generally means you'll need to edit
+[roxygen2 comments](https://roxygen2.r-lib.org/articles/roxygen2.html) in an `.R`,
+not a `.Rd` file. You can find the `.R` file that generates the `.Rd` by reading
+the comment in the first line.
+
+## Bigger changes
+
+If you want to make a bigger change, it's a good idea to first file an issue and
+make sure someone from the team agrees that it’s needed. If you’ve found a bug,
+please file an issue that illustrates the bug with a minimal reproducible
+example (see e.g. the [tidyverse reprex instructions](https://www.tidyverse.org/help/#reprex)).
+The tidyverse guide on [how to create a great issue](https://code-review.tidyverse.org/issues/)
+has more advice.
+
+### Pull request process
+
+If you are new to creating pull requests here are some tips. Using the functions
+from the `usethis` package is not required but can be helpful if this process is
+new to you.
+
+* Fork the package and clone onto your computer. If you haven't done this before, we recommend using `usethis::create_from_github("stan-dev/priorsense", fork = TRUE)`.
+
+* Install all development dependencies with `devtools::install_dev_deps()`, and then make sure the package passes R CMD check by running `devtools::check()`.
+ If R CMD check doesn't pass cleanly, it's a good idea to ask for help before continuing.
+* Create a Git branch for your pull request (PR). We recommend using `usethis::pr_init("brief-description-of-change")`.
+
+* Make your changes, commit to git, and then create a PR by running `usethis::pr_push()`, and following the prompts in your browser.
+ The title of your PR should briefly describe the change.
+ The body of your PR should contain `Fixes #issue-number`.
+
+* For user-facing changes, add a bullet to the top of `NEWS.md` (i.e. just below the first header). Follow the style already used in `NEWS.md`.
+
+### Code style
+
+* New code should attempt to follow the style used in the package. When in doubt follow the tidyverse [style guide](https://style.tidyverse.org).
+
+* We use [roxygen2](https://cran.r-project.org/package=roxygen2), with [Markdown syntax](https://cran.r-project.org/web/packages/roxygen2/vignettes/rd-formatting.html), for documentation.
+
+* We use [testthat](https://cran.r-project.org/package=testthat) for unit tests.
+ Contributions with test cases included are easier to accept.
+
+## Code of Conduct
+
+Please note that the priorsense project follows the Stan project's
+[Code of Conduct](https://discourse.mc-stan.org/t/announcing-our-new-stan-code-of-conduct/23764).
+By contributing to this project you agree to abide by its terms.
+
+All contributions must follow the [Stan AI Contribution Policy](https://github.com/stan-dev/stan/wiki/AI-Contribution-Policy).
diff --git a/man/figures/logo.svg b/man/figures/logo.svg
new file mode 100644
index 0000000..496f040
--- /dev/null
+++ b/man/figures/logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
From 86e4f58130cd5648c7e85affad19db82c4184e60 Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Fri, 11 Sep 2026 13:57:40 +0300
Subject: [PATCH 09/40] further update description and readme for stan transfer
---
DESCRIPTION | 2 +-
NEWS.md | 5 +++++
README.md | 4 +++-
README.qmd | 6 +++---
pkgdown/favicon/favicon.svg | 3 +++
5 files changed, 15 insertions(+), 5 deletions(-)
create mode 100644 pkgdown/favicon/favicon.svg
diff --git a/DESCRIPTION b/DESCRIPTION
index f806d8d..0abd7b9 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,7 +1,7 @@
Package: priorsense
Title: Prior Diagnostics and Sensitivity Analysis
Version: 1.3.1.9000
-Authors@R: c(person("Noa", "Kallioinen", email = "noa.kallioinen@helsinki.fi", role = c("aut", "cre", "cph"), comment = c(ORCID = "0000-0003-1586-8382")),
+Authors@R: c(person("Noa", "Kallioinen", email = "noa.kallioinen@helsinki.fi", role = c("aut", "cre"), comment = c(ORCID = "0000-0003-1586-8382")),
person("Topi", "Paananen", role = c("aut"), comment = c(ORCID = "0000-0002-6542-407X")),
person("Paul-Christian", "Bürkner", role = c("aut"), comment = c(ORCID = "0000-0001-5765-8995")),
person("Aki", "Vehtari", role = c("aut"), comment = c(ORCID = "0000-0003-2164-9469")),
diff --git a/NEWS.md b/NEWS.md
index 3701c43..5c13b85 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,3 +1,8 @@
+priorsense 1.3.1.9000
+---
++ `priorsense` is now an official Stan package, and links to pages and repositories have been updated
++ Plot help text now prints to the console rather than on the plot
+
priorsense 1.3.1
---
+ Add new JOSS paper as primary citation for the package.
diff --git a/README.md b/README.md
index 4a512da..d13961b 100644
--- a/README.md
+++ b/README.md
@@ -68,7 +68,9 @@ pak::pkg_install("stan-dev/priorsense@development")
Contributions are welcome! If you find a bug or have an idea for a
feature, open an issue. If you are able to fix an issue, fork the
-repository and make a pull request to the `development` branch.
+repository and make a pull request to the `development` branch. Read
+[CONTRIBUTING.md](https://github.com/stan-dev/priorsense/blob/main/.github/CONTRIBUTING.md)
+for more details.
### References
diff --git a/README.qmd b/README.qmd
index d0081f9..ce093ce 100644
--- a/README.qmd
+++ b/README.qmd
@@ -66,9 +66,9 @@ pak::pkg_install("stan-dev/priorsense@development")
### Contributing
-Contributions are welcome! If you find a bug or have an idea for a feature,
-open an issue. If you are able to fix an issue, fork the repository and make a
-pull request to the `development` branch.
+Contributions are welcome! If you find a bug or have an idea for a feature, open
+an issue. If you are able to fix an issue, fork the repository and make a pull
+request to the `development` branch. Read [CONTRIBUTING.md](https://github.com/stan-dev/priorsense/blob/main/.github/CONTRIBUTING.md) for more details.
### References
diff --git a/pkgdown/favicon/favicon.svg b/pkgdown/favicon/favicon.svg
new file mode 100644
index 0000000..c9fa0f5
--- /dev/null
+++ b/pkgdown/favicon/favicon.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
From b216655d18650c21b3c0d5f2f4a34a7afa0304c0 Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Fri, 11 Sep 2026 14:16:05 +0300
Subject: [PATCH 10/40] update ignored files and filenames
---
.Rbuildignore | 3 ++-
.gitignore | 1 +
vignettes/{used_by.bib => papers.bib} | 0
vignettes/{used_by.csl => papers.csl} | 0
vignettes/{used_by.qmd => papers.qmd} | 8 ++++++--
5 files changed, 9 insertions(+), 3 deletions(-)
rename vignettes/{used_by.bib => papers.bib} (100%)
rename vignettes/{used_by.csl => papers.csl} (100%)
rename vignettes/{used_by.qmd => papers.qmd} (57%)
diff --git a/.Rbuildignore b/.Rbuildignore
index 596581d..fd782ba 100644
--- a/.Rbuildignore
+++ b/.Rbuildignore
@@ -33,4 +33,5 @@
^vignettes/used_by*$
^revdep$
^data-raw$
-^paper$
\ No newline at end of file
+^paper$
+^dev$
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index a5d43d4..ad6361b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ priorsense.Rcheck
.DS_Store
docs
/doc/
+/dev/
/Meta/
/pkgdown/
/..Rcheck/
diff --git a/vignettes/used_by.bib b/vignettes/papers.bib
similarity index 100%
rename from vignettes/used_by.bib
rename to vignettes/papers.bib
diff --git a/vignettes/used_by.csl b/vignettes/papers.csl
similarity index 100%
rename from vignettes/used_by.csl
rename to vignettes/papers.csl
diff --git a/vignettes/used_by.qmd b/vignettes/papers.qmd
similarity index 57%
rename from vignettes/used_by.qmd
rename to vignettes/papers.qmd
index c98101f..c0630d0 100644
--- a/vignettes/used_by.qmd
+++ b/vignettes/papers.qmd
@@ -1,7 +1,11 @@
---
title: "Published papers using priorsense"
-bibliography: used_by.bib
-csl: used_by.csl
+vignette: >
+ %\VignetteIndexEntry{Published papers using priorsense}
+ %\VignetteEngine{quarto::html}
+ %\VignetteEncoding{UTF-8}
+bibliography: papers.bib
+csl: papers.csl
nocite: |
@*
---
From b235110cecf0ad0415ccf6addb99fc26db54d2a8 Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Fri, 11 Sep 2026 14:34:11 +0300
Subject: [PATCH 11/40] update tests for plots, as help text no longer is
plotted
---
.../plots/normal-model-density-plot.svg | 434 +++++++++---------
.../_snaps/plots/normal-model-ecdf-plot.svg | 348 +++++++-------
.../plots/normal-model-quantities-plot.svg | 370 ++++++++-------
tests/testthat/test_plots.R | 181 +++-----
4 files changed, 641 insertions(+), 692 deletions(-)
diff --git a/tests/testthat/_snaps/plots/normal-model-density-plot.svg b/tests/testthat/_snaps/plots/normal-model-density-plot.svg
index c699a61..87d8e91 100644
--- a/tests/testthat/_snaps/plots/normal-model-density-plot.svg
+++ b/tests/testthat/_snaps/plots/normal-model-density-plot.svg
@@ -21,246 +21,246 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-mu
+
+
+mu
-
-
+
+
-
-
-sigma
+
+
+sigma
-
-
+
+
-
-
-Prior
-power-scaling
+
+
+Prior
+power-scaling
-
-
+
+
-
-
-Likelihood
-power-scaling
+
+
+Likelihood
+power-scaling
@@ -281,24 +281,24 @@
1.0
1.5
2.0
-
-
-
-
-
-8.0
-8.5
-9.0
-9.5
-10.0
-
-
-
-
-0.5
-1.0
-1.5
-2.0
+
+
+
+
+
+8.0
+8.5
+9.0
+9.5
+10.0
+
+
+
+
+0.5
+1.0
+1.5
+2.0
Power-scaling alpha
@@ -310,10 +310,6 @@
0.8
1
1.25
-Posterior density estimates depending on amount of power-scaling (alpha).
-Overlapping lines indicate low sensitivity.
-Wider gaps between lines indicate greater sensitivity.
-Estimates with high Pareto k (dashed lines) may be inaccurate.
-Power-scaling sensitivity
+Normal model density plot
diff --git a/tests/testthat/_snaps/plots/normal-model-ecdf-plot.svg b/tests/testthat/_snaps/plots/normal-model-ecdf-plot.svg
index af71114..53bb07d 100644
--- a/tests/testthat/_snaps/plots/normal-model-ecdf-plot.svg
+++ b/tests/testthat/_snaps/plots/normal-model-ecdf-plot.svg
@@ -21,166 +21,166 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-mu
+
+
+mu
-
-
+
+
-
-
-sigma
+
+
+sigma
-
-
+
+
-
-
-Prior
-power-scaling
+
+
+Prior
+power-scaling
-
-
+
+
-
-
-Likelihood
-power-scaling
+
+
+Likelihood
+power-scaling
@@ -197,61 +197,61 @@
0.5
1.0
1.5
-
-
-
-
-8.5
-9.0
-9.5
-10.0
-
-
-
-0.5
-1.0
-1.5
-0.00
-0.25
-0.50
-0.75
-1.00
-
-
-
-
-
-0.00
-0.25
-0.50
-0.75
-1.00
-
-
-
-
-
-0.00
-0.25
-0.50
-0.75
-1.00
-
-
-
-
-
-0.00
-0.25
-0.50
-0.75
-1.00
-
-
-
-
-
-ECDF
+
+
+
+
+8.5
+9.0
+9.5
+10.0
+
+
+
+0.5
+1.0
+1.5
+0.00
+0.25
+0.50
+0.75
+1.00
+
+
+
+
+
+0.00
+0.25
+0.50
+0.75
+1.00
+
+
+
+
+
+0.00
+0.25
+0.50
+0.75
+1.00
+
+
+
+
+
+0.00
+0.25
+0.50
+0.75
+1.00
+
+
+
+
+
+ECDF
Power-scaling alpha
@@ -263,10 +263,6 @@
0.8
1
1.25
-Posterior ECDF depending on amount of power-scaling (alpha).
-Overlapping lines indicate low sensitivity.
-Wider gaps between lines indicate greater sensitivity.
-Estimates with high Pareto k (dashed lines) may be inaccurate.
-Power-scaling sensitivity
+Normal model ecdf plot
diff --git a/tests/testthat/_snaps/plots/normal-model-quantities-plot.svg b/tests/testthat/_snaps/plots/normal-model-quantities-plot.svg
index 954c72a..d47aab1 100644
--- a/tests/testthat/_snaps/plots/normal-model-quantities-plot.svg
+++ b/tests/testthat/_snaps/plots/normal-model-quantities-plot.svg
@@ -21,167 +21,167 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-mean
+
+
+mean
-
-
+
+
-
-
-sd
+
+
+sd
-
-
+
+
-
-
-cjs_dist
+
+
+cjs_dist
-
-
+
+
-
-
-mu
+
+
+mu
-
-
+
+
-
-
-sigma
+
+
+sigma
@@ -202,94 +202,90 @@
0.8
1
1.25
-
-
-
-0.8
-1
-1.25
-
-
-
-0.8
-1
-1.25
-
-
-
-0.8
-1
-1.25
-0.00
-0.05
-0.10
-0.15
-0.20
-
-
-
-
-
-0.00
-0.05
-0.10
-0.15
-0.20
-
-
-
-
-
-0.20
-0.25
-0.30
-0.35
-
-
-
-
-0.15
-0.20
-0.25
-
-
-
-9.35
-9.40
-9.45
-9.50
-9.55
-9.60
-
-
-
-
-
-
-0.85
-0.90
-0.95
-
-
-
+
+
+
+0.8
+1
+1.25
+
+
+
+0.8
+1
+1.25
+
+
+
+0.8
+1
+1.25
+0.00
+0.05
+0.10
+0.15
+0.20
+
+
+
+
+
+0.00
+0.05
+0.10
+0.15
+0.20
+
+
+
+
+
+0.20
+0.25
+0.30
+0.35
+
+
+
+
+0.15
+0.20
+0.25
+
+
+
+9.35
+9.40
+9.45
+9.50
+9.55
+9.60
+
+
+
+
+
+
+0.85
+0.90
+0.95
+
+
+
Power-scaling alpha
-
-
-
-
-+/-2MCSE
-
-component
-
-
-
-
-prior
-likelihood
-Posterior quantities depending on amount of power-scaling (alpha).
-Horizontal lines indicate low sensitivity.
-Steeper lines indicate greater sensitivity.
-Estimates with high Pareto k (highlighted) may be inaccurate.
-Power-scaling sensitivity
+
+
+
+
++/-2MCSE
+
+component
+
+
+
+
+prior
+likelihood
+Normal model quantities plot
diff --git a/tests/testthat/test_plots.R b/tests/testthat/test_plots.R
index 98c56cd..03ce113 100644
--- a/tests/testthat/test_plots.R
+++ b/tests/testthat/test_plots.R
@@ -3,121 +3,82 @@ eight_schools_example <- example_powerscale_model("eight_schools")
ps <- powerscale_sequence(eight_schools_example$draws, length = 3)
test_that("diagnostic plots give no errors", {
- expect_error(
- powerscale_plot_ecdf(
- ps,
- variable = c("mu", "tau")
- ),
- NA
- )
- expect_error(
- powerscale_plot_dens(
- x = ps,
- variable = c("mu", "tau")
- ),
- NA
- )
- expect_error(
- powerscale_plot_quantities(
- ps,
- variable = c("mu", "tau")
- ),
- NA
- )
+ expect_error(
+ powerscale_plot_ecdf(
+ ps,
+ variable = c("mu", "tau")
+ ),
+ NA
+ )
+ expect_error(
+ powerscale_plot_dens(
+ x = ps,
+ variable = c("mu", "tau")
+ ),
+ NA
+ )
+ expect_error(
+ powerscale_plot_quantities(
+ ps,
+ variable = c("mu", "tau")
+ ),
+ NA
+ )
})
test_that("plots contain expected data", {
- psq <- powerscale_plot_quantities(
- ps,
- variable = c("mu"),
- quantity = c("quantile", "mean"),
- quantity_args = list(probs = c(0.1, 0.9))
- )
- expect_equal(
- colnames(psq$data),
- c(
- "variable",
- ".powerscale_alpha",
- "pareto_k_threshold",
- "pareto_k",
- "component",
- "quantity",
- "value",
- "id",
- "pareto_k_value"
+ psq <- powerscale_plot_quantities(
+ ps,
+ variable = c("mu"),
+ quantity = c("quantile", "mean"),
+ quantity_args = list(probs = c(0.1, 0.9))
+ )
+ expect_equal(
+ colnames(psq$data),
+ c(
+ "variable",
+ ".powerscale_alpha",
+ "pareto_k_threshold",
+ "pareto_k",
+ "component",
+ "quantity",
+ "value",
+ "id",
+ "pareto_k_value"
+ )
)
- )
- expect_equal(
- unique(psq$data$quantity),
- c("q10", "q90", "mean", "cjs_dist")
- )
+ expect_equal(
+ unique(psq$data$quantity),
+ c("q10", "q90", "mean", "cjs_dist")
+ )
})
-test_that("help_text behaves as expected in plots", {
- psq_title <- powerscale_plot_quantities(
- ps,
- variable = c("mu"),
- help_text = TRUE
- )
-
- psq_notitle <- powerscale_plot_quantities(
- ps,
- variable = c("mu"),
- help_text = FALSE
- )
-
- expect_false(is.null(psq_title$labels$title))
- expect_false(is.null(psq_title$labels$subtitle))
-
- expect_null(psq_notitle$labels$title)
- expect_null(psq_notitle$labels$subtitle)
-
- psecdf_title <- powerscale_plot_ecdf(ps, variable = "mu")
-
- psecdf_notitle <- powerscale_plot_ecdf(ps, variable = "mu", help_text = FALSE)
-
- expect_false(is.null(psecdf_title$labels$title))
- expect_false(is.null(psecdf_title$labels$subtitle))
-
- expect_null(psecdf_notitle$labels$title)
- expect_null(psecdf_notitle$labels$subtitle)
-
- psdens_title <- powerscale_plot_dens(ps, variable = "mu")
- psdens_notitle <- powerscale_plot_dens(ps, variable = "mu", help_text = FALSE)
-
- expect_false(is.null(psdens_title$labels$title))
- expect_false(is.null(psdens_title$labels$subtitle))
-
- expect_null(psdens_notitle$labels$title)
- expect_null(psdens_notitle$labels$subtitle)
-})
-
test_that("pagination of plots works as expected", {
- expect_length(
- powerscale_plot_quantities(
- ps,
- variables_per_page = 1
- ),
- 18
- )
+ expect_length(
+ powerscale_plot_quantities(
+ ps,
+ variables_per_page = 1
+ ),
+ 18
+ )
- expect_length(
- powerscale_plot_quantities(
- ps,
- variables_per_page = 2
- ),
- 9
- )
+ expect_length(
+ powerscale_plot_quantities(
+ ps,
+ variables_per_page = 2
+ ),
+ 9
+ )
- expect_length(
- powerscale_plot_quantities(
- ps,
- variables_per_page = Inf
- ),
- 1
- )
+ expect_length(
+ powerscale_plot_quantities(
+ ps,
+ variables_per_page = Inf
+ ),
+ 1
+ )
})
@@ -125,17 +86,17 @@ test_that("pagination of plots works as expected", {
ps_normal <- powerscale_sequence(example_powerscale_model()$draws)
vdiffr::expect_doppelganger(
- "Normal model density plot",
- powerscale_plot_dens(ps_normal)
+ "Normal model density plot",
+ powerscale_plot_dens(ps_normal)
)
vdiffr::expect_doppelganger(
- "Normal model ecdf plot",
- powerscale_plot_ecdf(ps_normal)
+ "Normal model ecdf plot",
+ powerscale_plot_ecdf(ps_normal)
)
vdiffr::expect_doppelganger(
- "Normal model quantities plot",
- powerscale_plot_quantities(ps_normal)
+ "Normal model quantities plot",
+ powerscale_plot_quantities(ps_normal)
)
From d8dc6dcc7d66c990764d8aeebdbdc2c041235aeb Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Fri, 11 Sep 2026 14:34:26 +0300
Subject: [PATCH 12/40] update webpage docs
---
_pkgdown.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/_pkgdown.yml b/_pkgdown.yml
index 857f883..32d6ead 100644
--- a/_pkgdown.yml
+++ b/_pkgdown.yml
@@ -41,7 +41,7 @@ navbar:
articles:
- title: Getting started
desc: |
- These vignettes demonstrate how to use the **priorsense** package to check prior and likelihood sensitivity for Bayesian models fit using MCMC.
+ These pages demonstrate how to use the **priorsense** package to check prior and likelihood sensitivity for Bayesian models fit using MCMC.
contents:
- getting_started
- priorsense_with_stan
@@ -50,7 +50,7 @@ articles:
- priorsense_with_nimble
- title: Additional examples
desc: |
- These vignettes demonstrate how to use the **priorsense** package in more detail.
+ These pages demonstrate how to use the **priorsense** package in more detail.
contents:
- airquality
- title: Further details
@@ -63,11 +63,12 @@ reference:
- title: Package description
contents:
- priorsense-package
- - title: Primary power-scaling sensitivity checks
+ - title: Numerical power-scaling sensitivity checks
desc: |
Numerical sensitivity checks for prior and likelihood
contents:
- powerscale_sensitivity
+ - powerscale_derivative
- title: Graphical checks
desc: |
Plots for power-scaling sensitivity checks
@@ -84,7 +85,6 @@ reference:
contents:
- powerscale
- powerscale_sequence
- - powerscale_derivative
- powerscale_gradients
- create_priorsense_data
- title: Helper functions
From bd12112c6083d73410595a0d40000be2c8a7eb31 Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Tue, 15 Sep 2026 10:04:04 +0300
Subject: [PATCH 13/40] Update R-CMD-check.yaml
---
.github/workflows/R-CMD-check.yaml | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml
index e62ca74..80c02aa 100644
--- a/.github/workflows/R-CMD-check.yaml
+++ b/.github/workflows/R-CMD-check.yaml
@@ -1,4 +1,4 @@
-# Workflow derived from https://github.com/r-lib/actions/tree/master/examples
+# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
push:
@@ -6,7 +6,9 @@ on:
pull_request:
branches: [main, development]
-name: R-CMD-check
+name: R-CMD-check.yaml
+
+permissions: read-all
jobs:
R-CMD-check:
@@ -18,12 +20,11 @@ jobs:
fail-fast: false
matrix:
config:
- #- {os: macOS-latest, r: 'devel', rtools: ''}
- #- {os: macOS-latest, r: 'release', rtools: ''}
- #- {os: windows-latest, r: 'devel', rtools: '45'}
- #- {os: windows-latest, r: 'release', rtools: '45'}
- - {os: ubuntu-22.04, r: 'devel', rtools: ''}
- - {os: ubuntu-22.04, r: 'release', rtools: ''}
+ - {os: macos-latest, r: 'release'}
+ - {os: windows-latest, r: 'release'}
+ - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'}
+ - {os: ubuntu-latest, r: 'release'}
+ - {os: ubuntu-latest, r: 'oldrel-1'}
env:
R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
@@ -40,12 +41,13 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v7
- uses: r-lib/actions/setup-r@v2
with:
r-version: ${{ matrix.config.r }}
rtools-version: ${{ matrix.config.rtools }}
+ http-user-agent: ${{ matrix.config.http-user-agent }}
use-public-rspm: true
- uses: r-lib/actions/setup-pandoc@v2
with:
@@ -85,6 +87,6 @@ jobs:
- uses: r-lib/actions/check-r-package@v2
with:
- args: 'c("--no-manual", "--as-cran")'
- error-on: '"warning"'
- check-dir: '"check"'
+ upload-snapshots: true
+ args: 'c("--no-manual")'
+ build_args: 'c("--no-manual")
From cf6fb54977465215b3d4f4d8fc81bd30a3eb1d3e Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Tue, 15 Sep 2026 10:06:40 +0300
Subject: [PATCH 14/40] Update R-CMD-check.yaml
---
.github/workflows/R-CMD-check.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml
index 80c02aa..cdcf5c1 100644
--- a/.github/workflows/R-CMD-check.yaml
+++ b/.github/workflows/R-CMD-check.yaml
@@ -89,4 +89,4 @@ jobs:
with:
upload-snapshots: true
args: 'c("--no-manual")'
- build_args: 'c("--no-manual")
+ build_args: 'c("--no-manual")'
From 0eb7f4f9d0a72cec2168f3aef2aafd7cfef783bd Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Tue, 15 Sep 2026 10:46:23 +0300
Subject: [PATCH 15/40] test on ubuntu
---
.github/workflows/R-CMD-check.yaml | 2 --
1 file changed, 2 deletions(-)
diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml
index cdcf5c1..1afc240 100644
--- a/.github/workflows/R-CMD-check.yaml
+++ b/.github/workflows/R-CMD-check.yaml
@@ -20,8 +20,6 @@ jobs:
fail-fast: false
matrix:
config:
- - {os: macos-latest, r: 'release'}
- - {os: windows-latest, r: 'release'}
- {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'}
- {os: ubuntu-latest, r: 'release'}
- {os: ubuntu-latest, r: 'oldrel-1'}
From cdc947b403c2b327d5850d8811788f13bfe528f2 Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Tue, 15 Sep 2026 16:01:00 +0300
Subject: [PATCH 16/40] fixes to plots and new test snapshots
---
R/plots.R | 75 +++++++++++++------
.../plots/normal-model-quantities-plot.svg | 24 +++---
2 files changed, 65 insertions(+), 34 deletions(-)
diff --git a/R/plots.R b/R/plots.R
index cd42e2d..2b912b7 100644
--- a/R/plots.R
+++ b/R/plots.R
@@ -187,8 +187,7 @@ prepare_plot <- function(d, resample, variable, colors, ...) {
p <- p +
ggplot2::scale_linetype_manual(
values = c("solid", "dashed"),
- drop = TRUE,
- name = "Pareto k"
+ drop = TRUE
) +
ggplot2::scale_color_gradientn(
name = "Power-scaling alpha",
@@ -210,6 +209,7 @@ prepare_plot <- function(d, resample, variable, colors, ...) {
)
) +
ggplot2::scale_fill_gradientn(
+ name = "Power-scaling alpha",
colours = c(colors[1:3]),
trans = "log",
limits = c(
@@ -232,18 +232,33 @@ prepare_plot <- function(d, resample, variable, colors, ...) {
p <- p +
ggplot2::guides(
color = ggplot2::guide_legend(
- override.aes = ggplot2::aes(linetype = "solid")
+ title = "Power-scaling alpha",
+ override.aes = ggplot2::aes(linetype = "solid"),
+ order = 5
+ )
+ )
+ } else {
+ p <- p +
+ ggplot2::guides(
+ fill = ggplot2::guide_legend(
+ title = "Power-scaling alpha",
+ order = 5
)
)
}
- if (!(any(d$pareto_k_value == "High"))) {
+ if (any(d$pareto_k_value == "High")) {
p <- p +
ggplot2::guides(
- linetype = "none"
+ linetype = ggplot2::guide_legend(
+ title = "Pareto k",
+ order = 10
+ )
)
+ } else {
+ p <- p +
+ ggplot2::guides(linetype = "none")
}
-
return(p)
}
@@ -287,16 +302,6 @@ powerscale_plot_dens.default <-
)
}
-draw_key_path2 <- function(data, params, size) {
- grid::segmentsGrob(
- x0 = 0.1,
- x1 = 0.9,
- y0 = 0.5,
- y1 = 0.5,
- gp = grid::gpar(col = data$colour)
- )
-}
-
##' @export
powerscale_plot_dens.powerscaled_sequence <-
function(
@@ -530,6 +535,20 @@ powerscale_plot_dens.powerscaled_sequence <-
return(plots)
}
+draw_key_path2 <- function(data, params, size) {
+ grid::segmentsGrob(
+ x0 = 0.1,
+ x1 = 0.9,
+ y0 = 0.5,
+ y1 = 0.5,
+ gp = grid::gpar(
+ col = data$colour,
+ lty = data$linetype,
+ lwd = 2 * data$linewidth
+ )
+ )
+}
+
##' @rdname powerscale-plots
##' @export
powerscale_plot_ecdf <- function(x, ...) {
@@ -665,11 +684,6 @@ powerscale_plot_ecdf.powerscaled_sequence <-
dsub <- d[d$variable %in% sub_variable, ]
p <- prepare_plot(dsub, resample = resample, colors = colors, ...) +
- ggplot2::guides(
- linetype = ggplot2::guide_legend(
- title = "Pareto k"
- )
- ) +
ggplot2::ylab("ECDF") +
ggplot2::xlab(NULL)
@@ -710,7 +724,23 @@ powerscale_plot_ecdf.powerscaled_sequence <-
)
}
- if (!(any(d$pareto_k_value == "High"))) {
+ p <- p +
+ ggplot2::guides(
+ colour = ggplot2::guide_legend(
+ title = "Power-scaling alpha",
+ order = 5
+ )
+ )
+
+ if (any(d$pareto_k_value == "High")) {
+ p <- p +
+ ggplot2::guides(
+ linetype = ggplot2::guide_legend(
+ title = "Pareto k",
+ order = 10
+ )
+ )
+ } else {
p <- p +
ggplot2::guides(linetype = "none")
}
@@ -1087,6 +1117,7 @@ powerscale_summary_plot <- function(
data = points
) +
ggplot2::scale_shape_manual(
+ name = "Component",
values = c("likelihood" = 22, "prior" = 15)
) +
ggplot2::scale_color_manual(values = pareto_k_colours) +
diff --git a/tests/testthat/_snaps/plots/normal-model-quantities-plot.svg b/tests/testthat/_snaps/plots/normal-model-quantities-plot.svg
index d47aab1..79a8922 100644
--- a/tests/testthat/_snaps/plots/normal-model-quantities-plot.svg
+++ b/tests/testthat/_snaps/plots/normal-model-quantities-plot.svg
@@ -273,19 +273,19 @@
Power-scaling alpha
-
-
-
-
-+/-2MCSE
-
-component
-
-
+
+Component
+
+
+
+
+prior
+likelihood
+
-
-prior
-likelihood
+
+
++/-2MCSE
Normal model quantities plot
From 3e4171dead5512e74dbf549d52bbe7b70f7c7d7c Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Tue, 15 Sep 2026 16:01:40 +0300
Subject: [PATCH 17/40] bump dependency versions
---
DESCRIPTION | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/DESCRIPTION b/DESCRIPTION
index 0abd7b9..46e73a8 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -29,18 +29,18 @@ Imports:
tibble (>= 3.3.1),
utils
Suggests:
- bayesplot (>= 1.15.0),
+ bayesplot (>= 1.16.0),
brms (>= 2.23.0),
cmdstanr (>= 0.8.1),
iwmm (>= 0.0.1),
- nimble (>= 1.4.2),
+ nimble (>= 1.4.3),
philentropy (>= 0.10.0),
- quarto (>= 1.4.4),
+ quarto (>= 1.5.1),
R2jags (>= 0.8),
- rstan (>= 2.32.6),
- testthat (>= 3.0.0),
+ rstan (>= 2.32.7),
+ testthat (>= 3.3.2),
transport (>= 0.15),
- vdiffr (>= 1.0.8)
+ vdiffr (>= 1.0.9)
Config/testthat/edition: 3
Depends:
R (>= 4.1.0)
From bb74ccccfdc8c5990b7f7b0ada0c248ff5386c52 Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Tue, 15 Sep 2026 16:01:49 +0300
Subject: [PATCH 18/40] add resources to readme
---
README.md | 9 +++++++++
README.qmd | 6 ++++++
2 files changed, 15 insertions(+)
diff --git a/README.md b/README.md
index d13961b..76cd803 100644
--- a/README.md
+++ b/README.md
@@ -48,6 +48,15 @@ al. (2023)](https://doi.org/10.1007/s11222-023-10366-5).
- For a more detailed modelling example see
[here](https://mc-stan.org/priorsense/articles/airquality.html)
+### Resources
+
+- [mc-stan.org/priorsense](https://mc-stan.org/priorsense) (online
+ documentation, vignettes)
+- [Ask a question](https://discourse.mc-stan.org) (Stan Forums on
+ Discourse)
+- [Open an issue](https://github.com/stan-dev/priorsense/issues) (GitHub
+ issues for bug reports, feature requests)
+
### Installation
Download the stable version from CRAN with:
diff --git a/README.qmd b/README.qmd
index ce093ce..5439c45 100644
--- a/README.qmd
+++ b/README.qmd
@@ -47,6 +47,12 @@ from other software. Power-scaling sensitivity analysis checks are described in
- For a more detailed modelling example see
[here](https://mc-stan.org/priorsense/articles/airquality.html)
+### Resources
+
+* [mc-stan.org/priorsense](https://mc-stan.org/priorsense) (online documentation, vignettes)
+* [Ask a question](https://discourse.mc-stan.org) (Stan Forums on Discourse)
+* [Open an issue](https://github.com/stan-dev/priorsense/issues) (GitHub issues for bug reports, feature requests)
+
### Installation
Download the stable version from CRAN with:
From 18ffc691aa3220643d256a6fd6e4cf6d39fd4051 Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Wed, 16 Sep 2026 10:42:24 +0300
Subject: [PATCH 19/40] add dependency for workflow
---
.github/workflows/pkgdown.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml
index 1057d11..a3ef101 100644
--- a/.github/workflows/pkgdown.yaml
+++ b/.github/workflows/pkgdown.yaml
@@ -41,6 +41,7 @@ jobs:
local::.
XML
stan-dev/cmdstanr
+ stan-dev/pkgdown-config
paul-buerkner/brms
topipa/iwmm
rcmdcheck
From 9efd87b4efab4c7e7d5d6b092c9a2859ba1e0d56 Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Wed, 16 Sep 2026 10:45:24 +0300
Subject: [PATCH 20/40] update workflow
---
.github/workflows/pkgdown.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml
index a3ef101..ee5d5be 100644
--- a/.github/workflows/pkgdown.yaml
+++ b/.github/workflows/pkgdown.yaml
@@ -42,6 +42,7 @@ jobs:
XML
stan-dev/cmdstanr
stan-dev/pkgdown-config
+ n-kall/priorsense
paul-buerkner/brms
topipa/iwmm
rcmdcheck
From 9429b38d34e717c62fc36512c1b29ee6ab011b6e Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Wed, 16 Sep 2026 10:52:41 +0300
Subject: [PATCH 21/40] update workflow
---
.github/workflows/pkgdown.yaml | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml
index ee5d5be..9bc91b5 100644
--- a/.github/workflows/pkgdown.yaml
+++ b/.github/workflows/pkgdown.yaml
@@ -42,8 +42,7 @@ jobs:
XML
stan-dev/cmdstanr
stan-dev/pkgdown-config
- n-kall/priorsense
- paul-buerkner/brms
+ brms
topipa/iwmm
rcmdcheck
rstan
From 27a2f1439575b2cd399fcc4ae1642bdedbf41609 Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Wed, 16 Sep 2026 11:26:53 +0300
Subject: [PATCH 22/40] Update pkgdown.yaml
---
.github/workflows/pkgdown.yaml | 33 ++++++---------------------------
1 file changed, 6 insertions(+), 27 deletions(-)
diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml
index 9bc91b5..027d9bc 100644
--- a/.github/workflows/pkgdown.yaml
+++ b/.github/workflows/pkgdown.yaml
@@ -34,36 +34,15 @@ jobs:
with:
use-public-rspm: true
- - uses: r-lib/actions/setup-r-dependencies@v2
+ - name: Install dependencies
+ uses: r-lib/actions/setup-r-dependencies@v2
with:
- extra-packages: |
+ packages: |
+ deps::.
+ any::sessioninfo
any::pkgdown
- local::.
- XML
- stan-dev/cmdstanr
- stan-dev/pkgdown-config
- brms
- topipa/iwmm
- rcmdcheck
- rstan
- checkmate
- jsonlite
- nimble
- posterior
- processx
- R6
- BH
- R2jags
- RcppEigen
- StanHeaders
- RcppParallel
- withr
- testthat
- quarto
- any::XML
- any::textshaping
needs: website
-
+ dependencies: '"all"'
- name: Build site
run: |
From 13b00851f2d2aa222ebc518757a7947ef5bb3355 Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Wed, 16 Sep 2026 11:37:32 +0300
Subject: [PATCH 23/40] Update pkgdown.yaml
---
.github/workflows/pkgdown.yaml | 32 +++++++++++++++++++++-----------
1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml
index 027d9bc..293e1c7 100644
--- a/.github/workflows/pkgdown.yaml
+++ b/.github/workflows/pkgdown.yaml
@@ -33,26 +33,36 @@ jobs:
- uses: r-lib/actions/setup-r@v2
with:
use-public-rspm: true
-
- - name: Install dependencies
+
+ - name: Set up R
+ uses: r-lib/actions/setup-r@v2
+ with:
+ use-public-rspm: true
+ extra-repositories: |
+ https://stan-dev.r-universe.dev
+ https://topipa.r-universe.dev
+
+ - name: Install pkgdown dependencies
uses: r-lib/actions/setup-r-dependencies@v2
with:
+ cache-version: 4
packages: |
deps::.
any::sessioninfo
any::pkgdown
needs: website
dependencies: '"all"'
-
- - name: Build site
+ extra-packages: |
+ stan-dev/cmdstanr
+ topipa/iwmm
+ stan-dev/pkgdown-config
+ any::textshaping
+
+ - name: Build pkgdown site
run: |
- withr::with_envvar(
- c("NOT_CRAN" = "true"), # this should already be set by setup-r@v2? keeping because vignettes don't build otherwise
- pkgdown::build_site_github_pages(
- lazy = FALSE, # change to TRUE if runner times out.
- run_dont_run = TRUE,
- new_process = TRUE
- )
+ pkgdown::build_site_github_pages(
+ new_process = FALSE,
+ install = FALSE
)
shell: Rscript {0}
From 94f8288a4ad021a715acaf19328ec50f1fc42e66 Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Wed, 16 Sep 2026 12:35:44 +0300
Subject: [PATCH 24/40] Update DESCRIPTION
---
DESCRIPTION | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/DESCRIPTION b/DESCRIPTION
index 46e73a8..1228bf2 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -50,5 +50,5 @@ Additional_repositories:
https://stan-dev.r-universe.dev
URL: https://mc-stan.org/priorsense/, https://mc-stan.org/priorsense
BugReports: https://github.com/stan-dev/priorsense/issues
-Config/Needs/website: quarto, stan-dev/pkgdown-config
+Config/Needs/website: quarto
Config/roxygen2/version: 8.1.0
From 8eec745861498c657de6aa44bfb454e31a5de286 Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Wed, 16 Sep 2026 12:45:15 +0300
Subject: [PATCH 25/40] Update pkgdown.yaml
---
.github/workflows/pkgdown.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml
index 293e1c7..71ce5b4 100644
--- a/.github/workflows/pkgdown.yaml
+++ b/.github/workflows/pkgdown.yaml
@@ -61,6 +61,7 @@ jobs:
- name: Build pkgdown site
run: |
pkgdown::build_site_github_pages(
+ install = TRUE,
new_process = FALSE,
install = FALSE
)
From c6035a220ac899243de25744d58737cc109cef3f Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Wed, 16 Sep 2026 13:53:39 +0300
Subject: [PATCH 26/40] Update pkgdown.yaml
---
.github/workflows/pkgdown.yaml | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml
index 71ce5b4..54d22fc 100644
--- a/.github/workflows/pkgdown.yaml
+++ b/.github/workflows/pkgdown.yaml
@@ -62,8 +62,7 @@ jobs:
run: |
pkgdown::build_site_github_pages(
install = TRUE,
- new_process = FALSE,
- install = FALSE
+ new_process = FALSE
)
shell: Rscript {0}
From 6022d036566d04add25e5e86157dc0b0d4cb4ecc Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Wed, 16 Sep 2026 14:03:49 +0300
Subject: [PATCH 27/40] Update _pkgdown.yml
---
_pkgdown.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/_pkgdown.yml b/_pkgdown.yml
index 32d6ead..5d5d35e 100644
--- a/_pkgdown.yml
+++ b/_pkgdown.yml
@@ -57,7 +57,7 @@ articles:
contents:
- sensitivity_diagnostic
- quantity_of_interest
- - used_by
+ - papers
reference:
- title: Package description
From 5aaa5e880a9c08771f98579df4ba42831bf4b8ff Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Thu, 17 Sep 2026 11:26:13 +0300
Subject: [PATCH 28/40] fix order of legends in quantities plot
---
R/plots.R | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/R/plots.R b/R/plots.R
index 2b912b7..f17d494 100644
--- a/R/plots.R
+++ b/R/plots.R
@@ -1117,14 +1117,18 @@ powerscale_summary_plot <- function(
data = points
) +
ggplot2::scale_shape_manual(
- name = "Component",
values = c("likelihood" = 22, "prior" = 15)
) +
ggplot2::scale_color_manual(values = pareto_k_colours) +
ggplot2::guides(
color = ggplot2::guide_legend(
title = "Pareto k",
- override.aes = list(shape = 15)
+ override.aes = list(shape = 15),
+ order = 2
+ ),
+ shape = ggplot2::guide_legend(
+ title = "Component",
+ order = 1
)
) +
ggplot2::ylab(NULL) +
@@ -1179,7 +1183,8 @@ powerscale_summary_plot <- function(
),
data = sub_mcse,
color = "black"
- )
+ ) +
+ ggplot2::guides(linetype = ggplot2::guide_legend(order = 3))
}
plots[[i]] <- p
From 2c1c66192ea4a698cba26c6fc6b0e1d06bd9d9b9 Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Thu, 17 Sep 2026 11:26:31 +0300
Subject: [PATCH 29/40] rename vignettes to articles
---
_pkgdown.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/_pkgdown.yml b/_pkgdown.yml
index 5d5d35e..81e9b0b 100644
--- a/_pkgdown.yml
+++ b/_pkgdown.yml
@@ -12,7 +12,7 @@ navbar:
title: "priorsense"
structure:
- left: [home, vignettes, functions, news, pkgs, stan]
+ left: [home, articles, functions, news, pkgs, stan]
right: [search, bluesky, forum, github, lightswitch]
components:
From d598917706d474063a3af77819c9890f76286326 Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Thu, 17 Sep 2026 11:29:47 +0300
Subject: [PATCH 30/40] Update pkgdown.yaml
---
.github/workflows/pkgdown.yaml | 4 ----
1 file changed, 4 deletions(-)
diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml
index 54d22fc..df78349 100644
--- a/.github/workflows/pkgdown.yaml
+++ b/.github/workflows/pkgdown.yaml
@@ -29,10 +29,6 @@ jobs:
- uses: r-lib/actions/setup-pandoc@v2
- uses: quarto-dev/quarto-actions/setup@v2
-
- - uses: r-lib/actions/setup-r@v2
- with:
- use-public-rspm: true
- name: Set up R
uses: r-lib/actions/setup-r@v2
From 2238cde355430e70024bf1593982a6e8ec7aee13 Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Thu, 17 Sep 2026 11:34:46 +0300
Subject: [PATCH 31/40] Update pkgdown.yaml
---
.github/workflows/pkgdown.yaml | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml
index df78349..84d2641 100644
--- a/.github/workflows/pkgdown.yaml
+++ b/.github/workflows/pkgdown.yaml
@@ -53,6 +53,32 @@ jobs:
topipa/iwmm
stan-dev/pkgdown-config
any::textshaping
+
+ - name: Build pkgdown articles with diagnostics
+ shell: Rscript {0}
+ env:
+ QUARTO_LOG_LEVEL: DEBUG
+ QUARTO_PRINT_STACK: "true"
+ run: |
+ options(
+ warn = 1,
+ error = function() {
+ cat("\n=== R traceback ===\n")
+ traceback(20)
+
+ cat("\n=== rlang traceback ===\n")
+ try(rlang::last_trace(drop = FALSE))
+
+ quit(status = 1, save = "no")
+ }
+ )
+
+ cat("Quarto executable: ", quarto::quarto_path(), "\n")
+ system2(quarto::quarto_path(), "--version")
+
+ pkgdown::build_articles(
+ new_process = FALSE, quiet = FALSE
+ )
- name: Build pkgdown site
run: |
From 86b5e7320d2363d32fb76584f4635fa64a678312 Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Thu, 17 Sep 2026 11:41:58 +0300
Subject: [PATCH 32/40] Update pkgdown.yaml
---
.github/workflows/pkgdown.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml
index 84d2641..fe1976d 100644
--- a/.github/workflows/pkgdown.yaml
+++ b/.github/workflows/pkgdown.yaml
@@ -77,7 +77,7 @@ jobs:
system2(quarto::quarto_path(), "--version")
pkgdown::build_articles(
- new_process = FALSE, quiet = FALSE
+ quiet = FALSE
)
- name: Build pkgdown site
From ed6cf5b4ac39413b45d2313d6c8786ea3fcd90f9 Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Thu, 17 Sep 2026 11:56:39 +0300
Subject: [PATCH 33/40] Update pkgdown.yaml
---
.github/workflows/pkgdown.yaml | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml
index fe1976d..1aa24c4 100644
--- a/.github/workflows/pkgdown.yaml
+++ b/.github/workflows/pkgdown.yaml
@@ -54,6 +54,22 @@ jobs:
stan-dev/pkgdown-config
any::textshaping
+ - name: Install package for article build
+ shell: Rscript {0}
+ run: |
+ pak::pkg_install(
+ "local::.",
+ dependencies = FALSE,
+ upgrade = FALSE
+ )
+
+ stopifnot(requireNamespace("priorsense", quietly = TRUE))
+
+ message(
+ "Installed priorsense version: ",
+ as.character(packageVersion("priorsense"))
+ )
+
- name: Build pkgdown articles with diagnostics
shell: Rscript {0}
env:
@@ -67,17 +83,16 @@ jobs:
traceback(20)
cat("\n=== rlang traceback ===\n")
- try(rlang::last_trace(drop = FALSE))
+ try(print(rlang::last_trace(drop = FALSE)))
quit(status = 1, save = "no")
}
)
- cat("Quarto executable: ", quarto::quarto_path(), "\n")
- system2(quarto::quarto_path(), "--version")
-
pkgdown::build_articles(
- quiet = FALSE
+ pkg = ".",
+ quiet = FALSE,
+ lazy = FALSE
)
- name: Build pkgdown site
From d089d6848cbb2193388a60762c8f0b5cff3e5885 Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Thu, 17 Sep 2026 12:13:12 +0300
Subject: [PATCH 34/40] Update pkgdown.yaml
---
.github/workflows/pkgdown.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml
index 1aa24c4..4ff35cf 100644
--- a/.github/workflows/pkgdown.yaml
+++ b/.github/workflows/pkgdown.yaml
@@ -49,6 +49,7 @@ jobs:
needs: website
dependencies: '"all"'
extra-packages: |
+ BH
stan-dev/cmdstanr
topipa/iwmm
stan-dev/pkgdown-config
From 23354212537f06b6b426fb4d4b31dfc2fc1c8063 Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Thu, 17 Sep 2026 13:04:22 +0300
Subject: [PATCH 35/40] Update pkgdown.yaml
---
.github/workflows/pkgdown.yaml | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml
index 4ff35cf..de955be 100644
--- a/.github/workflows/pkgdown.yaml
+++ b/.github/workflows/pkgdown.yaml
@@ -50,6 +50,9 @@ jobs:
dependencies: '"all"'
extra-packages: |
BH
+ RcppEigen
+ StanHeaders
+ RcppParallel
stan-dev/cmdstanr
topipa/iwmm
stan-dev/pkgdown-config
@@ -60,7 +63,7 @@ jobs:
run: |
pak::pkg_install(
"local::.",
- dependencies = FALSE,
+ dependencies = TRUE,
upgrade = FALSE
)
From 8dbd1f87167fc30bd96c33b8a575de9fa4cd5822 Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Thu, 17 Sep 2026 13:42:26 +0300
Subject: [PATCH 36/40] Update pkgdown.yaml
---
.github/workflows/pkgdown.yaml | 41 ----------------------------------
1 file changed, 41 deletions(-)
diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml
index de955be..deea88f 100644
--- a/.github/workflows/pkgdown.yaml
+++ b/.github/workflows/pkgdown.yaml
@@ -57,47 +57,6 @@ jobs:
topipa/iwmm
stan-dev/pkgdown-config
any::textshaping
-
- - name: Install package for article build
- shell: Rscript {0}
- run: |
- pak::pkg_install(
- "local::.",
- dependencies = TRUE,
- upgrade = FALSE
- )
-
- stopifnot(requireNamespace("priorsense", quietly = TRUE))
-
- message(
- "Installed priorsense version: ",
- as.character(packageVersion("priorsense"))
- )
-
- - name: Build pkgdown articles with diagnostics
- shell: Rscript {0}
- env:
- QUARTO_LOG_LEVEL: DEBUG
- QUARTO_PRINT_STACK: "true"
- run: |
- options(
- warn = 1,
- error = function() {
- cat("\n=== R traceback ===\n")
- traceback(20)
-
- cat("\n=== rlang traceback ===\n")
- try(print(rlang::last_trace(drop = FALSE)))
-
- quit(status = 1, save = "no")
- }
- )
-
- pkgdown::build_articles(
- pkg = ".",
- quiet = FALSE,
- lazy = FALSE
- )
- name: Build pkgdown site
run: |
From 55582dc58d155a86d5c67359a72209dd93a8f66f Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Thu, 17 Sep 2026 13:50:04 +0300
Subject: [PATCH 37/40] update quantities plot so high k-hat is coloured before
the point
---
R/plots.R | 82 ++++++++++++++++++-
.../plots/normal-model-quantities-plot.svg | 36 +++++---
2 files changed, 102 insertions(+), 16 deletions(-)
diff --git a/R/plots.R b/R/plots.R
index f17d494..e4c89d6 100644
--- a/R/plots.R
+++ b/R/plots.R
@@ -766,6 +766,72 @@ powerscale_plot_ecdf.powerscaled_sequence <-
}
+powerscale_quantity_segments <- function(summaries) {
+ group_vars <- interaction(
+ summaries$variable,
+ summaries$quantity,
+ summaries$component,
+ drop = TRUE,
+ lex.order = TRUE
+ )
+
+ grouped_summaries <- split(summaries, group_vars)
+
+ segments <- lapply(grouped_summaries, function(group_data) {
+ group_data <- group_data[
+ order(group_data[[".powerscale_alpha"]]),
+ ,
+ drop = FALSE
+ ]
+
+ if (nrow(group_data) < 2) {
+ return(NULL)
+ }
+
+ segment_data <- group_data[-nrow(group_data), , drop = FALSE]
+
+ segment_data$x <- group_data[[".powerscale_alpha"]][-nrow(group_data)]
+ segment_data$xend <- group_data[[".powerscale_alpha"]][-1]
+ segment_data$y <- group_data$value[-nrow(group_data)]
+ segment_data$yend <- group_data$value[-1]
+
+ lower_distance <- abs(log(segment_data$x))
+ upper_distance <- abs(log(segment_data$xend))
+
+ lower_status <- group_data$pareto_k_value[-nrow(group_data)]
+ upper_status <- group_data$pareto_k_value[-1]
+
+ segment_status <- ifelse(
+ lower_distance > upper_distance,
+ as.character(lower_status),
+ ifelse(
+ upper_distance > lower_distance,
+ as.character(upper_status),
+ ifelse(
+ lower_status == "High" | upper_status == "High",
+ "High",
+ "OK"
+ )
+ )
+ )
+
+ segment_data$pareto_k_value <- factor(
+ segment_status,
+ levels = c("OK", "High")
+ )
+
+ segment_data
+ })
+
+ segments <- Filter(Negate(is.null), segments)
+
+ if (length(segments) == 0) {
+ return(summaries[FALSE, , drop = FALSE])
+ }
+
+ do.call(rbind, segments)
+}
+
##' @rdname powerscale-plots
##' @export
powerscale_plot_quantities <- function(x, ...) {
@@ -1081,6 +1147,8 @@ powerscale_summary_plot <- function(
max(summaries[[".powerscale_alpha"]]),
]
+ line_segments <- powerscale_quantity_segments(summaries)
+
p <- ggplot2::ggplot(
data = summaries,
mapping = ggplot2::aes(
@@ -1088,10 +1156,16 @@ powerscale_summary_plot <- function(
y = .data$value
)
) +
- ggplot2::geom_line(ggplot2::aes(
- color = .data$pareto_k_value,
- group = .data$component
- )) +
+ ggplot2::geom_segment(
+ data = line_segments,
+ mapping = ggplot2::aes(
+ x = .data$x,
+ xend = .data$xend,
+ y = .data$y,
+ yend = .data$yend,
+ color = .data$pareto_k_value
+ )
+ ) +
ggh4x::facet_grid2(
rows = ggplot2::vars(factor(
.data$variable,
diff --git a/tests/testthat/_snaps/plots/normal-model-quantities-plot.svg b/tests/testthat/_snaps/plots/normal-model-quantities-plot.svg
index 79a8922..a9503f8 100644
--- a/tests/testthat/_snaps/plots/normal-model-quantities-plot.svg
+++ b/tests/testthat/_snaps/plots/normal-model-quantities-plot.svg
@@ -27,8 +27,10 @@
-
-
+
+
+
+
@@ -46,8 +48,10 @@
-
-
+
+
+
+
@@ -65,8 +69,10 @@
-
-
+
+
+
+
@@ -82,8 +88,10 @@
-
-
+
+
+
+
@@ -101,8 +109,10 @@
-
-
+
+
+
+
@@ -120,8 +130,10 @@
-
-
+
+
+
+
From b04b3c222bc2622a9c9ce0b326f075516a40c6ab Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Thu, 17 Sep 2026 13:51:10 +0300
Subject: [PATCH 38/40] update news
---
NEWS.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/NEWS.md b/NEWS.md
index 5c13b85..b5c91b9 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -2,6 +2,7 @@ priorsense 1.3.1.9000
---
+ `priorsense` is now an official Stan package, and links to pages and repositories have been updated
+ Plot help text now prints to the console rather than on the plot
++ `powerscale_plot_quantities()` now highlights the line segment closer to 1 when k-hat is high
priorsense 1.3.1
---
From d5b2ee4e305e41e55c190410088565545c8ec25c Mon Sep 17 00:00:00 2001
From: Noa Kallioinen <33577035+n-kall@users.noreply.github.com>
Date: Thu, 17 Sep 2026 21:22:40 +0300
Subject: [PATCH 39/40] bump version
---
DESCRIPTION | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/DESCRIPTION b/DESCRIPTION
index 1228bf2..4d9d7b3 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,6 +1,6 @@
Package: priorsense
Title: Prior Diagnostics and Sensitivity Analysis
-Version: 1.3.1.9000
+Version: 1.4.0
Authors@R: c(person("Noa", "Kallioinen", email = "noa.kallioinen@helsinki.fi", role = c("aut", "cre"), comment = c(ORCID = "0000-0003-1586-8382")),
person("Topi", "Paananen", role = c("aut"), comment = c(ORCID = "0000-0002-6542-407X")),
person("Paul-Christian", "Bürkner", role = c("aut"), comment = c(ORCID = "0000-0001-5765-8995")),
From c7c39c6cbfb4a833df9a8326b846cdda11063263 Mon Sep 17 00:00:00 2001
From: Kallioinen Noa <33577035+n-kall@users.noreply.github.com>
Date: Thu, 17 Sep 2026 21:24:58 +0300
Subject: [PATCH 40/40] update docs
---
man/priorsense-package.Rd | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/man/priorsense-package.Rd b/man/priorsense-package.Rd
index f1faec0..b26db28 100644
--- a/man/priorsense-package.Rd
+++ b/man/priorsense-package.Rd
@@ -59,11 +59,11 @@ Computing}. 31(16). \code{doi:10.1007/s11222-020-09982-2}
\link{powerscale-plots}
}
\author{
-\strong{Maintainer}: Noa Kallioinen \email{noa.kallioinen@helsinki.fi} (\href{https://orcid.org/0000-0003-1586-8382}{ORCID}) [copyright holder]
+\strong{Maintainer}: Noa Kallioinen \email{noa.kallioinen@helsinki.fi} (\href{https://orcid.org/0000-0003-1586-8382}{ORCID})
Authors:
\itemize{
- \item Noa Kallioinen \email{noa.kallioinen@helsinki.fi} (\href{https://orcid.org/0000-0003-1586-8382}{ORCID}) [copyright holder]
+ \item Noa Kallioinen \email{noa.kallioinen@helsinki.fi} (\href{https://orcid.org/0000-0003-1586-8382}{ORCID})
\item Topi Paananen (\href{https://orcid.org/0000-0002-6542-407X}{ORCID})
\item Paul-Christian Bürkner (\href{https://orcid.org/0000-0001-5765-8995}{ORCID})
\item Aki Vehtari (\href{https://orcid.org/0000-0003-2164-9469}{ORCID})