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) [![priorsense status -badge](https://n-kall.r-universe.dev/badges/priorsense)](https://n-kall.r-universe.dev) +badge](https://stan-dev.r-universe.dev/badges/priorsense)](https://stan-dev.r-universe.dev) [![priorsense CRAN badge](https://www.r-pkg.org/badges/version/priorsense)](https://cran.r-project.org/package=priorsense) -[![R-CMD-check](https://github.com/n-kall/priorsense/workflows/R-CMD-check/badge.svg)](https://github.com/n-kall/priorsense/actions) +[![R-CMD-check](https://github.com/stan-dev/priorsense/workflows/R-CMD-check/badge.svg)](https://github.com/stan-dev/priorsense/actions) [![Status at rOpenSci Software Peer Review](https://badges.ropensci.org/704_status.svg)](https://github.com/ropensci/software-review/issues/704) [![DOI](https://joss.theoj.org/papers/10.21105/joss.11036/status.svg)](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")) [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) -[![priorsense status badge](https://n-kall.r-universe.dev/badges/priorsense)](https://n-kall.r-universe.dev) +[![priorsense status badge](https://stan-dev.r-universe.dev/badges/priorsense)](https://stan-dev.r-universe.dev) [![priorsense CRAN badge](https://www.r-pkg.org/badges/version/priorsense)](https://cran.r-project.org/package=priorsense) -[![R-CMD-check](https://github.com/n-kall/priorsense/workflows/R-CMD-check/badge.svg)](https://github.com/n-kall/priorsense/actions) +[![R-CMD-check](https://github.com/stan-dev/priorsense/workflows/R-CMD-check/badge.svg)](https://github.com/stan-dev/priorsense/actions) [![Status at rOpenSci Software Peer Review](https://badges.ropensci.org/704_status.svg)](https://github.com/ropensci/software-review/issues/704) [![DOI](https://joss.theoj.org/papers/10.21105/joss.11036/status.svg)](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})