From 3e0e5687647acb1639b55f79f297a83e1a01e89c Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Fri, 20 Feb 2026 22:39:44 +0200 Subject: [PATCH 001/120] add helper functions for correlation-aware uniformity test --- R/helpers-ppc.R | 106 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index e268b315..d085c498 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -595,3 +595,109 @@ create_rep_ids <- function(ids) paste('italic(y)[rep] (', ids, ")") y_label <- function() expression(italic(y)) yrep_label <- function() expression(italic(y)[rep]) ypred_label <- function() expression(italic(y)[pred]) + +# Dependence-aware uniformity tests ------------------------------------- + +#' Compute Shapley values for mean value function (closed form) +#' +#' Computes Shapley values for the mean value function using a closed-form +#' formula. This is used to assess the marginal contribution of each ordered +#' PIT value to the overall uniformity test statistic. +#' +#' @param x Numeric vector of values (typically Cauchy-transformed PIT values). +#' @return Numeric vector of Shapley values with the same length as `x`. +#' @noRd +shapley_mean_closedform <- function(x) { + n <- length(x) + if (n == 0) { + return(numeric(0)) + } + if (n == 1) { + return(0) + } + + # Harmonic number H_n = sum(1/i) for i = 1 to n + Hn <- sum(1 / seq_len(n)) + + Sh <- numeric(n) + for (i in seq_len(n)) { + mean_others <- sum(x[-i]) / (n - 1) + Sh[i] <- (1 / n) * x[i] + ((Hn - 1) / n) * (x[i] - mean_others) + } + return(Sh) +} + +.piet <- function(x) { + pe <- pexp(-log(x), rate = 1) + 2 * pmin(pe, 1 - pe) +} + +.pot <- function(x) { + n <- length(x) + pb <- pbeta(sort(x), 1:n, seq(n, 1, by = -1)) + 2 * pmin(pb, 1 - pb) +} + +.prit <- function(x) { + n <- length(x) + # Ranks: R = N * F(x) - evaluate and scale ECDF at each point x_i + ranks <- colSums(outer(x, x, "<=")) + # P(R <= r_i) where R follows Binom(N, x_i) + probs1 <- pbinom(ranks, n, x) + # P(R > r_i - 1) = 1 - P(R <= r_i - 1) + probs2 <- pbinom(ranks - 1, n, x) + # Individual test p-values + 2 * pmin(probs1, 1 - probs2) +} + +#' Transform Test values to Cauchy space +#' +#' @param x Numeric vector of PIT values in [0, 1]. +#' @return Numeric vector of Cauchy-transformed values. +#' @noRd +cauchy_space <- function(x_test) { + tan((0.5 - x_test) * pi) +} + +#' Truncated Cauchy combination test +#' +#' Combines dependent p-values using the Cauchy combination method. +#' If truncate, only p-values less than 0.5 are included. +#' +#' @param x Numeric vector of p-values (dependent PITs). +#' @param truncate Boolean; If TRUE only p-values less than 0.5 are +#' included. +#' @return Combined p-value. +#' @noRd +cauchy_agg <- function(x, truncate = NULL) { + if (truncate) { + mask <- as.numeric(x < 0.5) + 1 - pcauchy(mean(tan((0.5 - x) * pi) * mask)) + } else { + 1 - pcauchy(mean(tan((0.5 - x) * pi))) + } +} + +#' Identify influential points for uniformity test +#' +#' Identifies the minimal set of points that need to be removed to bring +#' the test statistic below the critical threshold. +#' +#' @param x Numeric vector of Shapley values (typically from Cauchy space). +#' @param alpha Significance level (default 0.05). +#' @return Integer vector of indices of influential points to remove. +#' @noRd +influential_points_idx <- function(x, alpha = 0.05) { + stopifnot(is.numeric(x), is.numeric(alpha), length(alpha) == 1, + alpha > 0 && alpha < 1) + + target <- qcauchy(1 - alpha) + pos_idx <- order(x, decreasing = TRUE) + pos_idx <- pos_idx[x[pos_idx] > 0] + pos_vals <- x[pos_idx] + + cumsum_remove <- cumsum(pos_vals) + needed <- which(sum(x) - cumsum_remove <= target)[1] + removed_idx <- pos_idx[seq_len(needed)] + return(removed_idx) +} \ No newline at end of file From c02215c0edeb1e78cd73d06d5348b4fe50884cc2 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Fri, 20 Feb 2026 22:41:08 +0200 Subject: [PATCH 002/120] incorporate in ppc_loo_pit_ecdf correlation-aware uniformity test --- R/ppc-loo.R | 227 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 215 insertions(+), 12 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 88a6692c..50c67b3b 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -400,6 +400,21 @@ ppc_loo_pit_qq <- function(y, #' computationally intensive and the approximation gives a fast method for #' assessing the ECDF trajectory. The default is to use interpolation if `K` #' is greater than 200. +#' @param method For `ppc_loo_pit_ecdf()`, the method used to calculate the +#' uniformity test: +#' * `"independent"`: (Current default) Assumes independence (Säilynoja et al., 2022). +#' * `"correlated"`: (Recommended) Accounts for correlation (Tesso & Vehtari, 2026). +#' @param test For `ppc_loo_pit_ecdf()` when `method = "correlated"`, which +#' dependence-aware test to use: `"POT-C"`, `"PRIT-C"`, or `"PIET-C"`. +#' Defaults to `"POT-C"`. +#' @param gamma For `ppc_loo_pit_ecdf()` when `method = "correlated"`, tolerance +#' threshold controlling how strongly suspicious points are flagged. Larger +#' values highlight only the most influential points. If `NULL`, automatically +#' determined based on p-value. +#' @param infl_points_only For `ppc_loo_pit_ecdf()` when `method = "correlated"`, +#' logical; if `TRUE` only the most influential points are colored (in case of +#' rejection), otherwise all suspicious points (regions) are highlighted +#' (recommended). ppc_loo_pit_ecdf <- function(y, yrep, lw = NULL, @@ -409,8 +424,31 @@ ppc_loo_pit_ecdf <- function(y, K = NULL, prob = .99, plot_diff = FALSE, - interpolate_adj = NULL) { + interpolate_adj = NULL, + method = NULL, + test = c("POT", "PRIT", "PIET"), + gamma = NULL, + infl_points_only = FALSE) { check_ignored_arguments(..., ok_args = list("moment_match")) + if (is.null(method)) { + inform( + c( + "i" = "In the next major release, the default `method` will change to 'correlated'.", + "*" = "To silence this message, explicitly set `method = 'independent'` or `method = 'correlated'`." + ) + ) + method <- "independent" + } else { + method <- match.arg(method, choices = c("independent", "correlated")) + if (method == "independent") { + inform( + paste( + "The 'independent' method is superseded by the 'correlated' method.", + "The new 'correlated' approach provides an updated uniformity test and graphical representation." + ) + ) + } + } if (!is.null(pit)) { inform("'pit' specified so ignoring 'y','yrep','lw' if specified.") @@ -431,33 +469,196 @@ ppc_loo_pit_ecdf <- function(y, } n_obs <- length(pit) - gamma <- adjust_gamma( + alpha = 1 - prob + if (is.null(K)) { + K <- length(pit) + } + x_eval <- seq(0, 1, length.out = K) + + # Correlated method: use dependence-aware tests + if (method == "correlated") { + test <- match.arg(test) + + # Compute test p-value and Cauchy-transformed values + if (test == "POT") { + cauchy_vals <- cauchy_space(.pot(sort(pit))) + pval <- cauchy_agg(.pot(pit), truncate = FALSE) + } else if (test == "PIET") { + cauchy_vals <- cauchy_space(.piet(sort(pit))) + pval <- cauchy_agg(.piet(pit), truncate = FALSE) + } else { # PRIT + cauchy_vals <- cauchy_space(.prit(sort(pit))) + pval <- cauchy_agg(.prit(pit), truncate = TRUE) + } + sh_val_sorted <- shapley_mean_closedform(cauchy_vals) + # Determine color based on p-value + highlight_color <- ifelse(pval < alpha, "red", "#F97316") + + # Combine x_eval and pit values, then sort to ensure step function aligns properly + # This ensures the ECDF has jumps at actual data points + x_combined <- sort(unique(c(x_eval, pit))) + + # Create main data frame for plotting + df_main <- tibble( + x = x_combined, + ecdf_pit = ecdf(pit)(x_combined) - (plot_diff == TRUE) * x_combined + ) + + # Create data frame with actual pit values for highlighting + # Extract the exact y-values from df_main to ensure perfect alignment + # This ensures highlights use the exact same values as the main plot at pit positions + pit_indices <- match(pit, x_combined) + df_pit <- tibble( + pit = pit, + ecdf_pit = ecdf(pit)(pit) - (plot_diff == TRUE) * pit + ) + df_pit <- df_pit[order(df_pit$pit), ] + + # Base plot with ECDF using geom_step to match independent method + p <- ggplot(df_main, aes( + x = x, + y = ecdf_pit)) + + geom_step(show.legend = FALSE) + + labs( + y = ifelse(plot_diff, "ECDF difference", "ECDF"), + x = "LOO PIT" + ) + + # Add reference line (matching independent method style) + if (plot_diff) { + p <- p + geom_abline( + intercept = 0, + slope = 0, + linetype = 2, + color = get_color("m") + ) + } else { + p <- p + geom_abline( + intercept = 0, + slope = 1, + linetype = 2, + color = get_color("m") + ) + } + + if (infl_points_only) { + if(pval < alpha){ + pos_idx <- influential_points_idx( + x = sh_val_sorted, alpha = alpha + ) + # Use actual PIT values and their ECDF values for highlighting + df_points <- df_pit[pos_idx, ] + + p <- p + geom_point( + data = df_points, + aes(x = pit, y = ecdf_pit), + color = highlight_color, + size = 2, + show.legend = FALSE + ) + } + } else { + # Auto-determine gamma if not provided + if (is.null(gamma) || gamma < 0) { + gamma <- ifelse( + pval <= 0.5, 0, + ifelse(pval <= 0.9, 0.05, 0.2) + ) + } + + red_idx <- which(sh_val_sorted > gamma) + + if (length(red_idx) != 0) { + df_red <- df_pit[red_idx, ] + + # Groups of consecutive suspicious points + consec_groups <- cumsum(c(1, diff(red_idx) != 1)) + df_red$segment <- consec_groups + + # Separate isolated vs grouped points + df_isolated <- df_red[ + stats::ave(df_red$pit, df_red$segment, FUN = length) == 1, + ] + df_grouped <- df_red[ + stats::ave(df_red$pit, df_red$segment, FUN = length) > 1, + ] + + # Create segments based on x_combined values for grouped points + if (nrow(df_grouped) > 0) { + # Create data frame with x_combined values for each group + segments_list <- lapply(split(df_grouped, df_grouped$segment), function(group) { + # Map pit values to x_combined indices + group_indices <- match(group$pit, x_combined) + # Find the range in x_combined that covers this group + min_idx <- min(group_indices) + max_idx <- max(group_indices) + + # Extract all x_combined values in this range (inclusive) + idx_range <- min_idx:max_idx + tibble( + x = df_main$x[idx_range], + ecdf_pit = df_main$ecdf_pit[idx_range], + segment = group$segment[1] + ) + }) + df_segments <- do.call(rbind, segments_list) + + p <- p + + geom_step( + data = df_segments, + aes(x = x, y = ecdf_pit, group = segment), + color = highlight_color, + linewidth = 1 + ) + } + + # Add isolated points + if (nrow(df_isolated) > 0) { + p <- p + geom_point( + data = df_isolated, + aes(x = pit, y = ecdf_pit), + color = highlight_color, + size = 1.5 + ) + } + } + } + + # Apply bayesplot theme and styling + p <- p + + yaxis_ticks(FALSE) + + scale_color_ppc() + + bayesplot_theme_get() + + return(p) + } + + # Independent method: use confidence bands + gamma_indep <- adjust_gamma( N = n_obs, K = K, prob = prob, interpolate_adj = interpolate_adj ) - lims <- ecdf_intervals(gamma = gamma, N = n_obs, K = K) - ggplot() + + lims <- ecdf_intervals(gamma = gamma_indep, N = n_obs, K = K) + + p <- ggplot() + aes( - x = seq(0, 1, length.out = K), - y = ecdf(pit)(seq(0, 1, length.out = K)) - - (plot_diff == TRUE) * seq(0, 1, length.out = K), + x = x_eval, + y = ecdf(pit)(x_eval) - (plot_diff == TRUE) * x_eval, color = "y" ) + geom_step(show.legend = FALSE) + geom_step( aes( - y = lims$upper[-1] / n_obs - - (plot_diff == TRUE) * seq(0, 1, length.out = K), + y = lims$upper[-1] / n_obs - (plot_diff == TRUE) * x_eval, color = "yrep" ), linetype = 2, show.legend = FALSE ) + geom_step( aes( - y = lims$lower[-1] / n_obs - - (plot_diff == TRUE) * seq(0, 1, length.out = K), + y = lims$lower[-1] / n_obs - (plot_diff == TRUE) * x_eval, color = "yrep" ), linetype = 2, show.legend = FALSE @@ -466,6 +667,8 @@ ppc_loo_pit_ecdf <- function(y, yaxis_ticks(FALSE) + scale_color_ppc() + bayesplot_theme_get() + + return(p) } @@ -836,7 +1039,7 @@ ppc_loo_ribbon <- bc_mat <- matrix(0, nrow(unifs), ncol(unifs)) # Generate boundary corrected reference values - for (i in 1:nrow(unifs)) { + for (i in seq_len(nrow(unifs))) { bc_list <- .kde_correction(unifs[i, ], bw = bw, grid_len = grid_len From 0d5817695620b80f9093c5996f257d4af8968c92 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Fri, 20 Feb 2026 22:41:50 +0200 Subject: [PATCH 003/120] add tests for updated ppc_loo_pit_ecdf function --- tests/testthat/test-ppc-loo.R | 105 ++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/tests/testthat/test-ppc-loo.R b/tests/testthat/test-ppc-loo.R index 9381692f..a530b71d 100644 --- a/tests/testthat/test-ppc-loo.R +++ b/tests/testthat/test-ppc-loo.R @@ -103,6 +103,111 @@ test_that("ppc_loo_pit_ecdf returns a ggplot object", { expect_equal(ll3$y, "ECDF difference") }) +test_that("ppc_loo_pit_ecdf with method='correlated' returns ggplot object", { + skip_if_not_installed("rstanarm") + skip_if_not_installed("loo") + + # Test with POT-C (default) + expect_gg(p1 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated")) + expect_gg(p2 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "POT")) + + # Test with PRIT-C + expect_gg(p3 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "PRIT")) + + # Test with PIET-C + expect_gg(p4 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "PIET")) + + # Test with plot_diff = TRUE + expect_gg(p5 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", plot_diff = TRUE)) + + # Test with infl_points_only = TRUE + expect_gg(p6 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", infl_points_only = TRUE)) + + # Test with gamma specified + expect_gg(p7 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", gamma = 0.1)) +}) + +test_that("ppc_loo_pit_ecdf method argument works correctly", { + skip_if_not_installed("rstanarm") + skip_if_not_installed("loo") + + # Test default (should inform about upcoming change) + expect_message( + p1 <- ppc_loo_pit_ecdf(y, yrep, lw), + "In the next major release" + ) + expect_gg(p1) + + # Test explicit independent method (should inform about supersession) + expect_message( + p2 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "independent"), + "superseded by the 'correlated' method" + ) + expect_gg(p2) + + # Test correlated method (no message expected) + expect_gg(p3 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated")) + + # Test that independent and correlated produce different plots + expect_true(!identical(p2$data, p3$data) || !identical(p2$layers, p3$layers)) +}) + +test_that("dependence-aware uniformity tests work with example data", { + # TODO +}) + +test_that("helper functions for dependence-aware tests work correctly", { + # Test Cauchy space transformation + x <- runif(100) + + cauchy_piet <- bayesplot:::cauchy_space(x) + expect_true(is.numeric(cauchy_piet)) + expect_true(length(cauchy_piet) == length(x)) + expect_true(all(is.finite(cauchy_piet))) + + # Test Shapley values + sh_val <- bayesplot:::shapley_mean_closedform(cauchy_pot) + expect_true(is.numeric(sh_val)) + expect_true(length(sh_val) == length(cauchy_pot)) + + # Test influential points + infl_idx <- bayesplot:::influential_points_idx(sh_val, alpha = 0.05) + expect_true(is.integer(infl_idx) || is.numeric(infl_idx)) + expect_true(all(infl_idx >= 1 & infl_idx <= length(sh_val))) + + # Test Cauchy aggregation + pvals <- runif(50, 0, 0.5) + agg_pval <- bayesplot:::cauchy_agg(pvals, truncate = FALSE) + expect_true(is.numeric(agg_pval)) + expect_true(agg_pval >= 0 && agg_pval <= 1) + + # Test truncated Cauchy aggregation + t_agg_pval <- bayesplot:::cauchy_agg(pvals, truncate = TRUE) + expect_true(is.numeric(t_agg_pval)) + expect_true(t_agg_pval >= 0 && t_agg_pval <= 1) +}) + +test_that("ppc_loo_pit_ecdf correlated method handles edge cases", { + skip_if_not_installed("rstanarm") + skip_if_not_installed("loo") + + # Test with small sample + small_pit <- runif(10) + expect_gg(p1 <- ppc_loo_pit_ecdf(pit = small_pit, method = "correlated")) + + # Test with perfect uniform + uniform_pit <- seq(0, 1, length.out = 100) + expect_gg(p2 <- ppc_loo_pit_ecdf(pit = uniform_pit, method = "correlated")) + + # Test with extreme values + extreme_pit <- c(rep(0, 10), rep(1, 10), runif(80)) + expect_gg(p3 <- ppc_loo_pit_ecdf(pit = extreme_pit, method = "correlated")) + + # Test with single value (edge case) + single_pit <- 0.5 + expect_gg(p4 <- ppc_loo_pit_ecdf(pit = single_pit, method = "correlated")) +}) + test_that("ppc_loo_pit functions work when pit specified instead of y, yrep, and lw", { skip_if_not_installed("rstanarm") skip_if_not_installed("loo") From ee2a3fc26363fcfa243b008020eb8dfb0b42ec43 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Sat, 21 Feb 2026 09:46:31 +0200 Subject: [PATCH 004/120] formatting and efficiency improvements --- R/ppc-loo.R | 230 ++++++++++++++++++++++++---------------------------- 1 file changed, 108 insertions(+), 122 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 50c67b3b..4558fb54 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -394,19 +394,19 @@ ppc_loo_pit_qq <- function(y, #' expectation for uniform PIT values rather than plotting the regular ECDF. #' The default is `FALSE`, but for large samples we recommend setting #' `plot_diff = TRUE` to better use the plot area. -#' @param interpolate_adj For `ppc_loo_pit_ecdf()`, a boolean defining if the -#' simultaneous confidence bands should be interpolated based on precomputed -#' values rather than computed exactly. Computing the bands may be -#' computationally intensive and the approximation gives a fast method for -#' assessing the ECDF trajectory. The default is to use interpolation if `K` -#' is greater than 200. +#' @param interpolate_adj For `ppc_loo_pit_ecdf()` when `method = "independent"`, +#' a boolean defining if the simultaneous confidence bands should be +#' interpolated based on precomputed values rather than computed exactly. +#' Computing the bands may be computationally intensive and the approximation +#' gives a fast method for assessing the ECDF trajectory. The default is to use +#' interpolation if `K` is greater than 200. #' @param method For `ppc_loo_pit_ecdf()`, the method used to calculate the #' uniformity test: #' * `"independent"`: (Current default) Assumes independence (Säilynoja et al., 2022). #' * `"correlated"`: (Recommended) Accounts for correlation (Tesso & Vehtari, 2026). #' @param test For `ppc_loo_pit_ecdf()` when `method = "correlated"`, which -#' dependence-aware test to use: `"POT-C"`, `"PRIT-C"`, or `"PIET-C"`. -#' Defaults to `"POT-C"`. +#' dependence-aware test to use: `"POT"`, `"PRIT"`, or `"PIET"`. +#' Defaults to `"POT"`. #' @param gamma For `ppc_loo_pit_ecdf()` when `method = "correlated"`, tolerance #' threshold controlling how strongly suspicious points are flagged. Larger #' values highlight only the most influential points. If `NULL`, automatically @@ -429,12 +429,21 @@ ppc_loo_pit_ecdf <- function(y, test = c("POT", "PRIT", "PIET"), gamma = NULL, infl_points_only = FALSE) { + check_ignored_arguments(..., ok_args = list("moment_match")) + + # input validation if (is.null(method)) { inform( c( - "i" = "In the next major release, the default `method` will change to 'correlated'.", - "*" = "To silence this message, explicitly set `method = 'independent'` or `method = 'correlated'`." + "i" = paste( + "In the next major release, the default `method`", + "will change to 'correlated'." + ), + "*" = paste( + "To silence this message, explicitly set", + "`method = 'independent'` or `method = 'correlated'`." + ) ) ) method <- "independent" @@ -444,12 +453,14 @@ ppc_loo_pit_ecdf <- function(y, inform( paste( "The 'independent' method is superseded by the 'correlated' method.", - "The new 'correlated' approach provides an updated uniformity test and graphical representation." + "The new 'correlated' approach provides an updated uniformity test", + "and graphical representation." ) ) } } + # PIT calculation or validation if (!is.null(pit)) { inform("'pit' specified so ignoring 'y','yrep','lw' if specified.") pit <- validate_pit(pit) @@ -462,6 +473,7 @@ ppc_loo_pit_ecdf <- function(y, yrep <- validate_predictions(yrep, length(y)) lw <- .get_lw(lw, psis_object) stopifnot(identical(dim(yrep), dim(lw))) + pit <- pmin(1, rstantools::loo_pit(object = yrep, y = y, lw = lw)) if (is.null(K)) { K <- min(nrow(yrep) + 1, 1000) @@ -469,15 +481,13 @@ ppc_loo_pit_ecdf <- function(y, } n_obs <- length(pit) - alpha = 1 - prob - if (is.null(K)) { - K <- length(pit) - } x_eval <- seq(0, 1, length.out = K) + ecdf_pit_fn <- ecdf(pit) - # Correlated method: use dependence-aware tests + # Correlated method -------------------------------------------------- if (method == "correlated") { test <- match.arg(test) + alpha <- 1 - prob # Compute test p-value and Cauchy-transformed values if (test == "POT") { @@ -490,132 +500,104 @@ ppc_loo_pit_ecdf <- function(y, cauchy_vals <- cauchy_space(.prit(sort(pit))) pval <- cauchy_agg(.prit(pit), truncate = TRUE) } + sh_val_sorted <- shapley_mean_closedform(cauchy_vals) - # Determine color based on p-value - highlight_color <- ifelse(pval < alpha, "red", "#F97316") - - # Combine x_eval and pit values, then sort to ensure step function aligns properly - # This ensures the ECDF has jumps at actual data points + highlight_color <- dplyr::if_else(pval < alpha, "red", "#F97316") x_combined <- sort(unique(c(x_eval, pit))) - # Create main data frame for plotting - df_main <- tibble( + # Evaluate at 0-1 interval b´values + df_main <- tibble::tibble( x = x_combined, - ecdf_pit = ecdf(pit)(x_combined) - (plot_diff == TRUE) * x_combined + ecdf_pit = ecdf_pit_fn(x_combined) - plot_diff * x_combined ) - # Create data frame with actual pit values for highlighting - # Extract the exact y-values from df_main to ensure perfect alignment - # This ensures highlights use the exact same values as the main plot at pit positions - pit_indices <- match(pit, x_combined) - df_pit <- tibble( + # Evaluate at pit values (used for highlighing) + df_pit <- tibble::tibble( pit = pit, - ecdf_pit = ecdf(pit)(pit) - (plot_diff == TRUE) * pit + ecdf_pit = ecdf_pit_fn(pit) - plot_diff * pit ) df_pit <- df_pit[order(df_pit$pit), ] - # Base plot with ECDF using geom_step to match independent method - p <- ggplot(df_main, aes( - x = x, - y = ecdf_pit)) + + # Plot ECDF + p <- ggplot(df_main, aes(x = x, y = ecdf_pit)) + geom_step(show.legend = FALSE) + labs( - y = ifelse(plot_diff, "ECDF difference", "ECDF"), + y = dplyr::if_else(plot_diff, "ECDF difference", "ECDF"), x = "LOO PIT" ) - # Add reference line (matching independent method style) - if (plot_diff) { - p <- p + geom_abline( - intercept = 0, - slope = 0, - linetype = 2, - color = get_color("m") - ) - } else { - p <- p + geom_abline( - intercept = 0, - slope = 1, - linetype = 2, - color = get_color("m") - ) - } + # Add reference line + p <- p + geom_abline( + intercept = 0, + slope = dplyr::if_else(plot_diff, 0, 1), + linetype = 2, + color = get_color("m") + ) - if (infl_points_only) { - if(pval < alpha){ - pos_idx <- influential_points_idx( - x = sh_val_sorted, alpha = alpha - ) - # Use actual PIT values and their ECDF values for highlighting - df_points <- df_pit[pos_idx, ] + if (infl_points_only) { + if (pval < alpha) { + pos_idx <- influential_points_idx(x = sh_val_sorted, alpha = alpha) + df_points <- df_pit[pos_idx, ] - p <- p + geom_point( - data = df_points, - aes(x = pit, y = ecdf_pit), - color = highlight_color, - size = 2, - show.legend = FALSE - ) - } + p <- p + geom_point( + data = df_points, + aes(x = pit, y = ecdf_pit), + color = highlight_color, + size = 2, + show.legend = FALSE + ) + } } else { - # Auto-determine gamma if not provided if (is.null(gamma) || gamma < 0) { - gamma <- ifelse( - pval <= 0.5, 0, - ifelse(pval <= 0.9, 0.05, 0.2) - ) + if (pval <= 0.5) { + gamma <- 0 + } else if (pval <= 0.9) { + gamma <- 0.05 + } else { + gamma <- 0.2 + } } - + red_idx <- which(sh_val_sorted > gamma) - if (length(red_idx) != 0) { + if (length(red_idx) > 0) { df_red <- df_pit[red_idx, ] # Groups of consecutive suspicious points - consec_groups <- cumsum(c(1, diff(red_idx) != 1)) - df_red$segment <- consec_groups + df_red$segment <- cumsum(c(1, diff(red_idx) != 1)) # Separate isolated vs grouped points - df_isolated <- df_red[ - stats::ave(df_red$pit, df_red$segment, FUN = length) == 1, - ] - df_grouped <- df_red[ - stats::ave(df_red$pit, df_red$segment, FUN = length) > 1, - ] + segment_lengths <- stats::ave(df_red$pit, df_red$segment, FUN = length) + df_isolated <- df_red[segment_lengths == 1, ] + df_grouped <- df_red[segment_lengths > 1, ] # Create segments based on x_combined values for grouped points if (nrow(df_grouped) > 0) { - # Create data frame with x_combined values for each group - segments_list <- lapply(split(df_grouped, df_grouped$segment), function(group) { - # Map pit values to x_combined indices - group_indices <- match(group$pit, x_combined) - # Find the range in x_combined that covers this group - min_idx <- min(group_indices) - max_idx <- max(group_indices) + segments_list <- lapply( + split(df_grouped, df_grouped$segment), function(group) { + group_indices <- match(group$pit, x_combined) + idx_range <- min(group_indices):max(group_indices) - # Extract all x_combined values in this range (inclusive) - idx_range <- min_idx:max_idx - tibble( - x = df_main$x[idx_range], - ecdf_pit = df_main$ecdf_pit[idx_range], - segment = group$segment[1] - ) - }) + tibble::tibble( + x = df_main$x[idx_range], + ecdf_pit = df_main$ecdf_pit[idx_range], + segment = group$segment[1] + ) + } + ) df_segments <- do.call(rbind, segments_list) - p <- p + - geom_step( - data = df_segments, - aes(x = x, y = ecdf_pit, group = segment), - color = highlight_color, - linewidth = 1 - ) + p <- p + geom_step( + data = df_segments, + aes(x = x, y = ecdf_pit, group = segment), + color = highlight_color, + linewidth = 1 + ) } - # Add isolated points if (nrow(df_isolated) > 0) { p <- p + geom_point( - data = df_isolated, + data = df_isolated, aes(x = pit, y = ecdf_pit), color = highlight_color, size = 1.5 @@ -633,37 +615,41 @@ ppc_loo_pit_ecdf <- function(y, return(p) } - # Independent method: use confidence bands + # Independent method -------------------------------------------------- gamma_indep <- adjust_gamma( N = n_obs, K = K, prob = prob, interpolate_adj = interpolate_adj ) + lims <- ecdf_intervals(gamma = gamma_indep, N = n_obs, K = K) + ecdf_eval <- ecdf_pit_fn(x_eval) - plot_diff * x_eval + + # Precompute division by n_obs + n_obs_inv <- 1 / n_obs + lims_upper_scaled <- lims$upper[-1] * n_obs_inv - plot_diff * x_eval + lims_lower_scaled <- lims$lower[-1] * n_obs_inv - plot_diff * x_eval p <- ggplot() + - aes( - x = x_eval, - y = ecdf(pit)(x_eval) - (plot_diff == TRUE) * x_eval, - color = "y" + geom_step( + aes(x = x_eval, y = ecdf_eval, color = "y"), + show.legend = FALSE ) + - geom_step(show.legend = FALSE) + geom_step( - aes( - y = lims$upper[-1] / n_obs - (plot_diff == TRUE) * x_eval, - color = "yrep" - ), - linetype = 2, show.legend = FALSE + aes(x = x_eval, y = lims_upper_scaled, color = "yrep"), + linetype = 2, + show.legend = FALSE ) + geom_step( - aes( - y = lims$lower[-1] / n_obs - (plot_diff == TRUE) * x_eval, - color = "yrep" - ), - linetype = 2, show.legend = FALSE + aes(x = x_eval, y = lims_lower_scaled, color = "yrep"), + linetype = 2, + show.legend = FALSE + ) + + labs( + y = dplyr::if_else(plot_diff, "ECDF difference", "ECDF"), + x = "LOO PIT" ) + - labs(y = ifelse(plot_diff, "ECDF difference", "ECDF"), x = "LOO PIT") + yaxis_ticks(FALSE) + scale_color_ppc() + bayesplot_theme_get() From 583b3e2b2caae5e34d8e3e12b4e617b58a315cad Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Sat, 21 Feb 2026 12:33:56 +0200 Subject: [PATCH 005/120] improve description and computation of uniformity tests for pcc_loo_pit_ecdf --- R/helpers-ppc.R | 75 ++++++++++++++++++++++++++++++++++++------------- R/ppc-loo.R | 26 ++++++++--------- 2 files changed, 68 insertions(+), 33 deletions(-) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index d085c498..43050a51 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -616,38 +616,73 @@ shapley_mean_closedform <- function(x) { return(0) } - # Harmonic number H_n = sum(1/i) for i = 1 to n - Hn <- sum(1 / seq_len(n)) + # Harmonic number + # H_n = sum(1/i) for i = 1 to n + harmonic_number <- sum(1 / seq_len(n)) - Sh <- numeric(n) + shapley_values <- numeric(n) for (i in seq_len(n)) { mean_others <- sum(x[-i]) / (n - 1) - Sh[i] <- (1 / n) * x[i] + ((Hn - 1) / n) * (x[i] - mean_others) + shapley_values[i] <- (1 / n) * x[i] + ((harmonic_number - 1) / n) * (x[i] - mean_others) } - return(Sh) + + return(shapley_values) } -.piet <- function(x) { - pe <- pexp(-log(x), rate = 1) - 2 * pmin(pe, 1 - pe) +#' Pointwise Inverse-CDF Evaluation Tests Combination (PIET) +#' +#' Uniformity test with respect to any continuous distribution. +#' H0: The value obtained via the inverse CDF transformation F^(-1)(x_i) +#' follows the distribution of X under uniformity. +#' HA: The p-value p_(i) provides evidence against uniformity. +#' +#' @param x Numeric vector of PIT values in [0, 1]. +#' @return Numeric vector of p-values. +#' @noRd +piet_test <- function(x) { + cdf_exp <- pexp(-log(x), rate = 1) # same as 1-x but numerically more stable + p_values <- 2 * pmin(cdf_exp, 1 - cdf_exp) + + return(p_values) } -.pot <- function(x) { +#' Pointwise Order Tests Combination (POT) +#' +#' Uniformity test based on a beta distribution. +#' H0: The i-th order statistic u_(i) follows a beta distribution +#' under uniformity. +#' HA: The p-value p_(i) provides evidence against uniformity +#' at the i-th order statistic u_(i). +#' +#' @param x Numeric vector of PIT values in [0, 1]. +#' @return Numeric vector of p-values. +#' @noRd +pot_test <- function(x) { n <- length(x) - pb <- pbeta(sort(x), 1:n, seq(n, 1, by = -1)) - 2 * pmin(pb, 1 - pb) + cdf_beta <- pbeta(sort(x), 1:n, seq(n, 1, by = -1)) + p_value <- 2 * pmin(cdf_beta, 1 - cdf_beta) + + return(p_value) } -.prit <- function(x) { +#' Pointwise Rank-based Individual Tests Combination (PRIT) +#' +#' Uniformity test based on a binomial distribution. +#' H0: The number of observations falling at or below x_i +#' follows a binomial distribution under uniformity. +#' HA: The p-value p_i provides evidence against uniformity. +#' +#' @param x Numeric vector of PIT values in [0, 1]. +#' @return Numeric vector of p-values. +#' @noRd +prit_test <- function(x) { n <- length(x) - # Ranks: R = N * F(x) - evaluate and scale ECDF at each point x_i - ranks <- colSums(outer(x, x, "<=")) - # P(R <= r_i) where R follows Binom(N, x_i) - probs1 <- pbinom(ranks, n, x) - # P(R > r_i - 1) = 1 - P(R <= r_i - 1) - probs2 <- pbinom(ranks - 1, n, x) - # Individual test p-values - 2 * pmin(probs1, 1 - probs2) + scaled_ecdf <- n * ecdf(x)(x) + probs1 <- pbinom(scaled_ecdf - 1, n, x) + probs2 <- pbinom(scaled_ecdf, n, x) + p_values <- 2 * pmin(1 - probs1, probs2) + + return(p_values) } #' Transform Test values to Cauchy space diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 4558fb54..41423ab0 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -432,7 +432,7 @@ ppc_loo_pit_ecdf <- function(y, check_ignored_arguments(..., ok_args = list("moment_match")) - # input validation + # Input validation if (is.null(method)) { inform( c( @@ -491,14 +491,14 @@ ppc_loo_pit_ecdf <- function(y, # Compute test p-value and Cauchy-transformed values if (test == "POT") { - cauchy_vals <- cauchy_space(.pot(sort(pit))) - pval <- cauchy_agg(.pot(pit), truncate = FALSE) + cauchy_vals <- cauchy_space(pot_test(sort(pit))) + pval <- cauchy_agg(pot_test(pit), truncate = FALSE) } else if (test == "PIET") { - cauchy_vals <- cauchy_space(.piet(sort(pit))) - pval <- cauchy_agg(.piet(pit), truncate = FALSE) + cauchy_vals <- cauchy_space(piet_test(sort(pit))) + pval <- cauchy_agg(piet_test(pit), truncate = FALSE) } else { # PRIT - cauchy_vals <- cauchy_space(.prit(sort(pit))) - pval <- cauchy_agg(.prit(pit), truncate = TRUE) + cauchy_vals <- cauchy_space(prit_test(sort(pit))) + pval <- cauchy_agg(prit_test(pit), truncate = TRUE) } sh_val_sorted <- shapley_mean_closedform(cauchy_vals) @@ -540,7 +540,7 @@ ppc_loo_pit_ecdf <- function(y, df_points <- df_pit[pos_idx, ] p <- p + geom_point( - data = df_points, + data = df_points, aes(x = pit, y = ecdf_pit), color = highlight_color, size = 2, @@ -588,7 +588,7 @@ ppc_loo_pit_ecdf <- function(y, df_segments <- do.call(rbind, segments_list) p <- p + geom_step( - data = df_segments, + data = df_segments, aes(x = x, y = ecdf_pit, group = segment), color = highlight_color, linewidth = 1 @@ -597,7 +597,7 @@ ppc_loo_pit_ecdf <- function(y, if (nrow(df_isolated) > 0) { p <- p + geom_point( - data = df_isolated, + data = df_isolated, aes(x = pit, y = ecdf_pit), color = highlight_color, size = 1.5 @@ -633,17 +633,17 @@ ppc_loo_pit_ecdf <- function(y, p <- ggplot() + geom_step( - aes(x = x_eval, y = ecdf_eval, color = "y"), + aes(x = x_eval, y = ecdf_eval, color = "y"), show.legend = FALSE ) + geom_step( aes(x = x_eval, y = lims_upper_scaled, color = "yrep"), - linetype = 2, + linetype = 2, show.legend = FALSE ) + geom_step( aes(x = x_eval, y = lims_lower_scaled, color = "yrep"), - linetype = 2, + linetype = 2, show.legend = FALSE ) + labs( From 317a7530fb1b6891c32943dafbfa7801b4eff2d1 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Sat, 21 Feb 2026 14:04:28 +0200 Subject: [PATCH 006/120] add unit-tests for dependence-aware uniformity tests --- tests/testthat/test-ppc-loo.R | 87 +++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 3 deletions(-) diff --git a/tests/testthat/test-ppc-loo.R b/tests/testthat/test-ppc-loo.R index a530b71d..d5a5f22e 100644 --- a/tests/testthat/test-ppc-loo.R +++ b/tests/testthat/test-ppc-loo.R @@ -106,7 +106,10 @@ test_that("ppc_loo_pit_ecdf returns a ggplot object", { test_that("ppc_loo_pit_ecdf with method='correlated' returns ggplot object", { skip_if_not_installed("rstanarm") skip_if_not_installed("loo") - + + x <- 1 - (1 - runif(300))^(1.2) + ppc_loo_pit_ecdf(pit=x, method = "correlated", prob = 0.95, plot_diff = TRUE) + # Test with POT-C (default) expect_gg(p1 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated")) expect_gg(p2 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "POT")) @@ -152,8 +155,86 @@ test_that("ppc_loo_pit_ecdf method argument works correctly", { expect_true(!identical(p2$data, p3$data) || !identical(p2$layers, p3$layers)) }) -test_that("dependence-aware uniformity tests work with example data", { - # TODO +# Tests for the dependence-aware uniformity tests ------------------------------ +test_that("piet_test computes correct p-values", { + x <- c(0.1, 0.25, 0.5, 0.75, 0.9) + # Equivalent to 2 * min(1-x, x) + expected <- c(0.2, 0.5, 1.0, 0.5, 0.2) + + expect_equal(piet_test(x), expected, tolerance = 1e-7) +}) + +test_that("piet_test handles boundary values of 0 and 1", { + x <- c(0, 1) + expected <- c(0, 0) + + expect_equal(piet_test(x), expected) +}) + +test_that("piet_test handles extreme values stably", { + # Testing values very close to 0 and 1 + x <- c(1e-17, 1 - 1e-17) + expected <- c(2e-17, 2e-17) + + # Tolerance needs to be adjusted for very small numbers + expect_equal(piet_test(x), expected, tolerance = 1e-16) +}) + +test_that("piet_test handles NA, NaN, and empty inputs correctly", { + # NA and NaN propagation + x_na <- c(0.5, NA, NaN) + res_na <- piet_test(x_na) + + expect_equal(res_na[1], 1.0) + expect_true(is.na(res_na[2])) + expect_true(is.nan(res_na[3])) +}) + +test_that("pot_test calculates correct p-values", { + # Manually calculating expected values for x = c(0.2, 0.8), n = 2. + # Note: If X ~ Beta(1, b) then X ~ Kumaraswamy(1, b) with CDF 1 - (1 - x)^b + # and if X ~ Beta(a, 1) then X ~ Kumaraswamy(a, 1) with CDF to x^a + # Beta(1, 2) CDF at 0.2 is 1 - (1 - 0.2)^2 = 0.36 + # Beta(2, 1) CDF at 0.8 is 0.8^2 = 0.64 + # p-values: 2 * min(0.36, 1-0.36) = 0.72; 2 * min(0.64, 1-0.64) = 0.72 + x <- c(0.8, 0.2) + expected <- c(0.72, 0.72) + + expect_equal(pot_test(x), expected) +}) + +test_that("pot_test handles boundary values correctly", { + x <- c(0, 1) + expected <- c(0, 0) + + expect_equal(pot_test(x), expected) +}) + +test_that("pot_test bounds p-values between 0 and 1 for extreme out-of-bounds inputs", { + # pbeta handles values outside [0, 1] by returning 0 + x <- c(-0.5, 1.5) + expected <- c(0, 0) + + expect_equal(pot_test(x), expected) +}) + +test_that("pot_test handles NAs", { + x_na <- c(0.5, NA) # resulting in a = 2, b = 1 + # Beta(2, 1) at 0.5 = 0.25 -> 2 * min(0.25, 0.75) = 0.5 + expected <- c(0.5, NA) + + expect_equal(pot_test(x_na), expected) +}) + +test_that("prit_test computes correct p-values", { + # Let n = 2, x = c(0.5, 0.5) + # scaled_ecdf = 2 * c(1, 1) = c(2, 2) + # probs1 = pbinom(1, 2, 0.5) = 0.75 + # probs2 = pbinom(2, 2, 0.5) = 1.00 + # p_val = 2 * min(1 - 0.75, 1.00) = 2 * 0.25 = 0.5 + + x <- c(0.5, 0.5) + expect_equal(prit_test(x), c(0.5, 0.5)) }) test_that("helper functions for dependence-aware tests work correctly", { From 3afa4ace2628bdcfe6f04a3d4388cbf02c2b4ab9 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Sat, 21 Feb 2026 14:06:34 +0200 Subject: [PATCH 007/120] do not remove NA when using sort() in pot_test --- R/helpers-ppc.R | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index 43050a51..4f3d7920 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -659,10 +659,12 @@ piet_test <- function(x) { #' @noRd pot_test <- function(x) { n <- length(x) - cdf_beta <- pbeta(sort(x), 1:n, seq(n, 1, by = -1)) - p_value <- 2 * pmin(cdf_beta, 1 - cdf_beta) + # keep NA values instead of silent recycling via sort() + # TODO: Can PIT values be NAN at this point? + cdf_beta <- pbeta(sort(x, na.last = TRUE), 1:n, seq(n, 1, by = -1)) + p_values <- 2 * pmin(cdf_beta, 1 - cdf_beta) - return(p_value) + return(p_values) } #' Pointwise Rank-based Individual Tests Combination (PRIT) From c8e63fde4e4416043c6ae7802e119cacf4d832a4 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Sat, 21 Feb 2026 14:31:33 +0200 Subject: [PATCH 008/120] move unittest for uniformity tests from test-ppc-loo.R to test-helpers-ppc.R --- tests/testthat/test-ppc-loo.R | 82 ----------------------------------- 1 file changed, 82 deletions(-) diff --git a/tests/testthat/test-ppc-loo.R b/tests/testthat/test-ppc-loo.R index d5a5f22e..670571b0 100644 --- a/tests/testthat/test-ppc-loo.R +++ b/tests/testthat/test-ppc-loo.R @@ -155,88 +155,6 @@ test_that("ppc_loo_pit_ecdf method argument works correctly", { expect_true(!identical(p2$data, p3$data) || !identical(p2$layers, p3$layers)) }) -# Tests for the dependence-aware uniformity tests ------------------------------ -test_that("piet_test computes correct p-values", { - x <- c(0.1, 0.25, 0.5, 0.75, 0.9) - # Equivalent to 2 * min(1-x, x) - expected <- c(0.2, 0.5, 1.0, 0.5, 0.2) - - expect_equal(piet_test(x), expected, tolerance = 1e-7) -}) - -test_that("piet_test handles boundary values of 0 and 1", { - x <- c(0, 1) - expected <- c(0, 0) - - expect_equal(piet_test(x), expected) -}) - -test_that("piet_test handles extreme values stably", { - # Testing values very close to 0 and 1 - x <- c(1e-17, 1 - 1e-17) - expected <- c(2e-17, 2e-17) - - # Tolerance needs to be adjusted for very small numbers - expect_equal(piet_test(x), expected, tolerance = 1e-16) -}) - -test_that("piet_test handles NA, NaN, and empty inputs correctly", { - # NA and NaN propagation - x_na <- c(0.5, NA, NaN) - res_na <- piet_test(x_na) - - expect_equal(res_na[1], 1.0) - expect_true(is.na(res_na[2])) - expect_true(is.nan(res_na[3])) -}) - -test_that("pot_test calculates correct p-values", { - # Manually calculating expected values for x = c(0.2, 0.8), n = 2. - # Note: If X ~ Beta(1, b) then X ~ Kumaraswamy(1, b) with CDF 1 - (1 - x)^b - # and if X ~ Beta(a, 1) then X ~ Kumaraswamy(a, 1) with CDF to x^a - # Beta(1, 2) CDF at 0.2 is 1 - (1 - 0.2)^2 = 0.36 - # Beta(2, 1) CDF at 0.8 is 0.8^2 = 0.64 - # p-values: 2 * min(0.36, 1-0.36) = 0.72; 2 * min(0.64, 1-0.64) = 0.72 - x <- c(0.8, 0.2) - expected <- c(0.72, 0.72) - - expect_equal(pot_test(x), expected) -}) - -test_that("pot_test handles boundary values correctly", { - x <- c(0, 1) - expected <- c(0, 0) - - expect_equal(pot_test(x), expected) -}) - -test_that("pot_test bounds p-values between 0 and 1 for extreme out-of-bounds inputs", { - # pbeta handles values outside [0, 1] by returning 0 - x <- c(-0.5, 1.5) - expected <- c(0, 0) - - expect_equal(pot_test(x), expected) -}) - -test_that("pot_test handles NAs", { - x_na <- c(0.5, NA) # resulting in a = 2, b = 1 - # Beta(2, 1) at 0.5 = 0.25 -> 2 * min(0.25, 0.75) = 0.5 - expected <- c(0.5, NA) - - expect_equal(pot_test(x_na), expected) -}) - -test_that("prit_test computes correct p-values", { - # Let n = 2, x = c(0.5, 0.5) - # scaled_ecdf = 2 * c(1, 1) = c(2, 2) - # probs1 = pbinom(1, 2, 0.5) = 0.75 - # probs2 = pbinom(2, 2, 0.5) = 1.00 - # p_val = 2 * min(1 - 0.75, 1.00) = 2 * 0.25 = 0.5 - - x <- c(0.5, 0.5) - expect_equal(prit_test(x), c(0.5, 0.5)) -}) - test_that("helper functions for dependence-aware tests work correctly", { # Test Cauchy space transformation x <- runif(100) From 609f48f7a1c456637decc475dd5f5ca3c2354df1 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Sat, 21 Feb 2026 14:33:12 +0200 Subject: [PATCH 009/120] improve descripting and naming of function to compute shapley values --- R/ppc-loo.R | 4 +- tests/testthat/test-helpers-ppc.R | 83 +++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 41423ab0..7a4bdb95 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -501,7 +501,7 @@ ppc_loo_pit_ecdf <- function(y, pval <- cauchy_agg(prit_test(pit), truncate = TRUE) } - sh_val_sorted <- shapley_mean_closedform(cauchy_vals) + pointwise_contribution <- compute_shapley_values(cauchy_vals) highlight_color <- dplyr::if_else(pval < alpha, "red", "#F97316") x_combined <- sort(unique(c(x_eval, pit))) @@ -536,7 +536,7 @@ ppc_loo_pit_ecdf <- function(y, if (infl_points_only) { if (pval < alpha) { - pos_idx <- influential_points_idx(x = sh_val_sorted, alpha = alpha) + pos_idx <- influential_points_idx(x = pointwise_contribution, alpha = alpha) df_points <- df_pit[pos_idx, ] p <- p + geom_point( diff --git a/tests/testthat/test-helpers-ppc.R b/tests/testthat/test-helpers-ppc.R index 36f921d3..a147205f 100644 --- a/tests/testthat/test-helpers-ppc.R +++ b/tests/testthat/test-helpers-ppc.R @@ -124,3 +124,86 @@ test_that("ecdf_intervals returns right dimensions and values", { expect_equal(min(lims$lower), 0) expect_equal(max(lims$lower), 100) }) + +# Tests for the dependence-aware uniformity tests ------------------------------ +test_that("piet_test computes correct p-values", { + x <- c(0.1, 0.25, 0.5, 0.75, 0.9) + # Equivalent to 2 * min(1-x, x) + expected <- c(0.2, 0.5, 1.0, 0.5, 0.2) + + expect_equal(piet_test(x), expected, tolerance = 1e-7) +}) + +test_that("piet_test handles boundary values of 0 and 1", { + x <- c(0, 1) + expected <- c(0, 0) + + expect_equal(piet_test(x), expected) +}) + +test_that("piet_test handles extreme values stably", { + # Testing values very close to 0 and 1 + x <- c(1e-17, 1 - 1e-17) + expected <- c(2e-17, 2e-17) + + # Tolerance needs to be adjusted for very small numbers + expect_equal(piet_test(x), expected, tolerance = 1e-16) +}) + +test_that("piet_test handles NA, NaN, and empty inputs correctly", { + # NA and NaN propagation + x_na <- c(0.5, NA, NaN) + res_na <- piet_test(x_na) + + expect_equal(res_na[1], 1.0) + expect_true(is.na(res_na[2])) + expect_true(is.nan(res_na[3])) +}) + +test_that("pot_test calculates correct p-values", { + # Manually calculating expected values for x = c(0.2, 0.8), n = 2. + # Note: If X ~ Beta(1, b) then X ~ Kumaraswamy(1, b) with CDF 1 - (1 - x)^b + # and if X ~ Beta(a, 1) then X ~ Kumaraswamy(a, 1) with CDF to x^a + # Beta(1, 2) CDF at 0.2 is 1 - (1 - 0.2)^2 = 0.36 + # Beta(2, 1) CDF at 0.8 is 0.8^2 = 0.64 + # p-values: 2 * min(0.36, 1-0.36) = 0.72; 2 * min(0.64, 1-0.64) = 0.72 + x <- c(0.8, 0.2) + expected <- c(0.72, 0.72) + + expect_equal(pot_test(x), expected) +}) + +test_that("pot_test handles boundary values correctly", { + x <- c(0, 1) + expected <- c(0, 0) + + expect_equal(pot_test(x), expected) +}) + +test_that("pot_test bounds p-values between 0 and 1 for extreme out-of-bounds inputs", { + # pbeta handles values outside [0, 1] by returning 0 + x <- c(-0.5, 1.5) + expected <- c(0, 0) + + expect_equal(pot_test(x), expected) +}) + +test_that("pot_test handles NAs", { + x_na <- c(0.5, NA) # resulting in a = 2, b = 1 + # Beta(2, 1) at 0.5 = 0.25 -> 2 * min(0.25, 0.75) = 0.5 + expected <- c(0.5, NA) + + expect_equal(pot_test(x_na), expected) +}) + +test_that("prit_test computes correct p-values", { + # Let n = 2, x = c(0.5, 0.5) + # scaled_ecdf = 2 * c(1, 1) = c(2, 2) + # probs1 = pbinom(1, 2, 0.5) = 0.75 + # probs2 = pbinom(2, 2, 0.5) = 1.00 + # p_val = 2 * min(1 - 0.75, 1.00) = 2 * 0.25 = 0.5 + + x <- c(0.5, 0.5) + expect_equal(prit_test(x), c(0.5, 0.5)) +}) + From bbfedc5c59d42ec1dc743b20c05eb6cdd5714ad7 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Sat, 21 Feb 2026 14:33:44 +0200 Subject: [PATCH 010/120] improve descripting and naming of function to compute shapley values --- R/helpers-ppc.R | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index 4f3d7920..1a738a7b 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -598,16 +598,17 @@ ypred_label <- function() expression(italic(y)[pred]) # Dependence-aware uniformity tests ------------------------------------- -#' Compute Shapley values for mean value function (closed form) +#' Compute Shapley values #' -#' Computes Shapley values for the mean value function using a closed-form -#' formula. This is used to assess the marginal contribution of each ordered -#' PIT value to the overall uniformity test statistic. +#' Calculates the average marginal contribution of players across +#' all random arrival orders in a cooperative game. +#' Used to provide a principled approach for quantifying +#' point-specific influences in a way that reflects local miscalibration. #' -#' @param x Numeric vector of values (typically Cauchy-transformed PIT values). +#' @param x Numeric vector of Cauchy-transformed PIT values. #' @return Numeric vector of Shapley values with the same length as `x`. #' @noRd -shapley_mean_closedform <- function(x) { +compute_shapley_values <- function(x) { n <- length(x) if (n == 0) { return(numeric(0)) @@ -623,6 +624,7 @@ shapley_mean_closedform <- function(x) { shapley_values <- numeric(n) for (i in seq_len(n)) { mean_others <- sum(x[-i]) / (n - 1) + # Applies the closed-form formula to assign player i their fair share. shapley_values[i] <- (1 / n) * x[i] + ((harmonic_number - 1) / n) * (x[i] - mean_others) } From 18f6539f9025601d07c48021fb1b2ca01d0ecb21 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Sat, 21 Feb 2026 14:41:35 +0200 Subject: [PATCH 011/120] add unittest for compute_shapley_values --- tests/testthat/test-helpers-ppc.R | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/testthat/test-helpers-ppc.R b/tests/testthat/test-helpers-ppc.R index a147205f..fdd5462c 100644 --- a/tests/testthat/test-helpers-ppc.R +++ b/tests/testthat/test-helpers-ppc.R @@ -207,3 +207,37 @@ test_that("prit_test computes correct p-values", { expect_equal(prit_test(x), c(0.5, 0.5)) }) +# Test for computation of Shapley values ------------------------------------- + +test_that("compute_shapley_values handles empty vector and single element", { + result_empty <- compute_shapley_values(numeric(0)) + result_single <- compute_shapley_values(5) + + expect_equal(result_empty, numeric(0)) + expect_equal(length(result_empty), 0) + expect_equal(result_single, 0) + expect_equal(length(result_single), 1) +}) + +test_that("compute_shapley_values for simple case", { + x <- c(1, 2) + result <- compute_shapley_values(x) + + # Manual calculation for n=2: + # harmonic_number = 1 + 1/2 = 1.5 + # For i=1: mean_others = 2/1 = 2 + # shapley[1] = (1/2)*1 + ((1.5-1)/2)*(1-2) = 0.5 - 0.25 = 0.25 + # For i=2: mean_others = 1/1 = 1 + # shapley[2] = (1/2)*2 + ((1.5-1)/2)*(2-1) = 1 + 0.25 = 1.25 + + expected <- c(0.25, 1.25) + expect_equal(result, expected, tolerance = 1e-10) + expect_equal(length(result), 2) +}) + +test_that("compute_shapley_values handles mixed input values", { + x <- c(-0.2, 0, 2, 3.1, 4.2) + result <- compute_shapley_values(x) + expect_equal(length(result), 5) + expect_true(all(is.finite(result))) +}) \ No newline at end of file From 2ca91a3db1b7666151427a38c4b37130cf02cd69 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Sat, 21 Feb 2026 20:02:54 +0200 Subject: [PATCH 012/120] improve computation of Cauchy combination test and std. Cauchy values --- R/helpers-ppc.R | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index 1a738a7b..8cc33b32 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -689,31 +689,23 @@ prit_test <- function(x) { return(p_values) } -#' Transform Test values to Cauchy space -#' -#' @param x Numeric vector of PIT values in [0, 1]. -#' @return Numeric vector of Cauchy-transformed values. -#' @noRd -cauchy_space <- function(x_test) { - tan((0.5 - x_test) * pi) -} - #' Truncated Cauchy combination test #' #' Combines dependent p-values using the Cauchy combination method. #' If truncate, only p-values less than 0.5 are included. #' -#' @param x Numeric vector of p-values (dependent PITs). +#' @param x Numeric vector of p-values transformed to follow a standard +#' Cauchy distribution. #' @param truncate Boolean; If TRUE only p-values less than 0.5 are #' included. -#' @return Combined p-value. +#' @return p-value of the Cauchy combination method. #' @noRd -cauchy_agg <- function(x, truncate = NULL) { +cauchy_combination_test <- function(x, truncate = NULL) { if (truncate) { - mask <- as.numeric(x < 0.5) - 1 - pcauchy(mean(tan((0.5 - x) * pi) * mask)) + idx <- which(x < 0.5) + 1 - pcauchy(mean(-qcauchy(x[idx]))) } else { - 1 - pcauchy(mean(tan((0.5 - x) * pi))) + 1 - pcauchy(mean(-qcauchy(x))) } } From d6a18cef7178ae2f59a0bb0a6fed41ad8375448e Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Sat, 21 Feb 2026 20:03:54 +0200 Subject: [PATCH 013/120] make variable namings more descriptive --- R/ppc-loo.R | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 7a4bdb95..8f455af1 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -481,7 +481,7 @@ ppc_loo_pit_ecdf <- function(y, } n_obs <- length(pit) - x_eval <- seq(0, 1, length.out = K) + unit_interval <- seq(0, 1, length.out = K) ecdf_pit_fn <- ecdf(pit) # Correlated method -------------------------------------------------- @@ -491,24 +491,24 @@ ppc_loo_pit_ecdf <- function(y, # Compute test p-value and Cauchy-transformed values if (test == "POT") { - cauchy_vals <- cauchy_space(pot_test(sort(pit))) - pval <- cauchy_agg(pot_test(pit), truncate = FALSE) + std_cauchy_values <- -qcauchy(pot_test(sort(pit))) + p_value_CCT <- cauchy_combination_test(pot_test(pit), truncate = FALSE) } else if (test == "PIET") { - cauchy_vals <- cauchy_space(piet_test(sort(pit))) - pval <- cauchy_agg(piet_test(pit), truncate = FALSE) + std_cauchy_values <- -qcauchy(piet_test(sort(pit))) + p_value_CCT <- cauchy_combination_test(piet_test(pit), truncate = FALSE) } else { # PRIT - cauchy_vals <- cauchy_space(prit_test(sort(pit))) - pval <- cauchy_agg(prit_test(pit), truncate = TRUE) + std_cauchy_values <- -qcauchy(prit_test(sort(pit))) + p_value_CCT <- cauchy_combination_test(prit_test(pit), truncate = TRUE) } - pointwise_contribution <- compute_shapley_values(cauchy_vals) - highlight_color <- dplyr::if_else(pval < alpha, "red", "#F97316") - x_combined <- sort(unique(c(x_eval, pit))) + pointwise_contribution <- compute_shapley_values(std_cauchy_values) + highlight_color <- dplyr::if_else(p_value_CCT < alpha, "red", "#F97316") + x_axis_combined <- sort(unique(c(unit_interval, pit))) # Evaluate at 0-1 interval b´values df_main <- tibble::tibble( - x = x_combined, - ecdf_pit = ecdf_pit_fn(x_combined) - plot_diff * x_combined + x = x_axis_combined, + ecdf_pit = ecdf_pit_fn(x_axis_combined) - plot_diff * x_axis_combined ) # Evaluate at pit values (used for highlighing) @@ -535,7 +535,7 @@ ppc_loo_pit_ecdf <- function(y, ) if (infl_points_only) { - if (pval < alpha) { + if (p_value_CCT < alpha) { pos_idx <- influential_points_idx(x = pointwise_contribution, alpha = alpha) df_points <- df_pit[pos_idx, ] @@ -549,16 +549,16 @@ ppc_loo_pit_ecdf <- function(y, } } else { if (is.null(gamma) || gamma < 0) { - if (pval <= 0.5) { + if (p_value_CCT <= 0.5) { gamma <- 0 - } else if (pval <= 0.9) { + } else if (p_value_CCT <= 0.9) { gamma <- 0.05 } else { gamma <- 0.2 } } - red_idx <- which(sh_val_sorted > gamma) + red_idx <- which(pointwise_contribution > gamma) if (length(red_idx) > 0) { df_red <- df_pit[red_idx, ] @@ -575,7 +575,7 @@ ppc_loo_pit_ecdf <- function(y, if (nrow(df_grouped) > 0) { segments_list <- lapply( split(df_grouped, df_grouped$segment), function(group) { - group_indices <- match(group$pit, x_combined) + group_indices <- match(group$pit, x_axis_combined) idx_range <- min(group_indices):max(group_indices) tibble::tibble( @@ -624,25 +624,25 @@ ppc_loo_pit_ecdf <- function(y, ) lims <- ecdf_intervals(gamma = gamma_indep, N = n_obs, K = K) - ecdf_eval <- ecdf_pit_fn(x_eval) - plot_diff * x_eval + ecdf_eval <- ecdf_pit_fn(unit_interval) - plot_diff * unit_interval # Precompute division by n_obs n_obs_inv <- 1 / n_obs - lims_upper_scaled <- lims$upper[-1] * n_obs_inv - plot_diff * x_eval - lims_lower_scaled <- lims$lower[-1] * n_obs_inv - plot_diff * x_eval + lims_upper_scaled <- lims$upper[-1] * n_obs_inv - plot_diff * unit_interval + lims_lower_scaled <- lims$lower[-1] * n_obs_inv - plot_diff * unit_interval p <- ggplot() + geom_step( - aes(x = x_eval, y = ecdf_eval, color = "y"), + aes(x = unit_interval, y = ecdf_eval, color = "y"), show.legend = FALSE ) + geom_step( - aes(x = x_eval, y = lims_upper_scaled, color = "yrep"), + aes(x = unit_interval, y = lims_upper_scaled, color = "yrep"), linetype = 2, show.legend = FALSE ) + geom_step( - aes(x = x_eval, y = lims_lower_scaled, color = "yrep"), + aes(x = unit_interval, y = lims_lower_scaled, color = "yrep"), linetype = 2, show.legend = FALSE ) + From 8b55c2f56bad9c87cd27c9eb90d51fc9c79f71a0 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Sat, 21 Feb 2026 20:04:26 +0200 Subject: [PATCH 014/120] add unittests for Cauchy combination test --- tests/testthat/test-helpers-ppc.R | 39 +++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/testthat/test-helpers-ppc.R b/tests/testthat/test-helpers-ppc.R index fdd5462c..5ba8a904 100644 --- a/tests/testthat/test-helpers-ppc.R +++ b/tests/testthat/test-helpers-ppc.R @@ -240,4 +240,43 @@ test_that("compute_shapley_values handles mixed input values", { result <- compute_shapley_values(x) expect_equal(length(result), 5) expect_true(all(is.finite(result))) +}) + +# Test for (truncated) Cauchy combination test ---------------------------------- +test_that("cauchy_combination_test handles truncate = FALSE", { + # avg = mean(-qcauchy(x)) + # result = 1 - pcauchy(avg) + + x <- c(0.1, 0.2, 0.3) + result <- cauchy_combination_test(x, truncate = FALSE) + expected <- 1 - pcauchy(mean(-qcauchy(x))) + + expect_equal(result, expected, tolerance = 1e-10) + expect_true(is.finite(result)) + expect_true(result >= 0 && result <= 1) +}) + +test_that("cauchy_combination_test handles truncate = TRUE", { + # avg = mean(-qcauchy(x)) + # result = 1 - pcauchy(avg) + + x <- c(0.1, 0.2, 0.3, 0.4, 0.7, 0.8) + result <- cauchy_combination_test(x, truncate = TRUE) + expected <- 1 - pcauchy(mean(-qcauchy(c(0.1, 0.2, 0.3, 0.4)))) + + expect_equal(result, expected, tolerance = 1e-10) + expect_true(is.finite(result)) + expect_true(result >= 0 && result <= 1) +}) + +test_that("cauchy_combination_test handles boundary values", { + # x = 0: -qdf(0) = Inf and cdf(Inf) = 1 -> 1 - 1 = 0 + # x = 1: -qdf(1) = -Inf and cdf(-Inf) = 0 -> 1 - 0 = 1 + + expect_equal(cauchy_combination_test(0, truncate = FALSE), 0) + expect_equal(cauchy_combination_test(1, truncate = FALSE), 1) + expect_true(is.nan(cauchy_combination_test(c(0, 1), truncate = FALSE))) + # TODO: if 1 included in vector, CCT will always evaluate to 0 + # as the mean evaluates to Inf and 1 - cdf(Inf) = 1 - 1 = 0 + expect_equal(cauchy_combination_test(c(0, 0.3, 0.4, 1), truncate = TRUE), 0) }) \ No newline at end of file From da23cdf4c02ed8913085b8477fcbdcbdce8eabf7 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Sat, 21 Feb 2026 20:54:45 +0200 Subject: [PATCH 015/120] improve efficiency of influential_points_idx --- R/helpers-ppc.R | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index 8cc33b32..95c7a0ee 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -714,21 +714,28 @@ cauchy_combination_test <- function(x, truncate = NULL) { #' Identifies the minimal set of points that need to be removed to bring #' the test statistic below the critical threshold. #' -#' @param x Numeric vector of Shapley values (typically from Cauchy space). -#' @param alpha Significance level (default 0.05). +#' @param x Numeric vector of Shapley values. +#' @param alpha Significance level. #' @return Integer vector of indices of influential points to remove. #' @noRd -influential_points_idx <- function(x, alpha = 0.05) { +influential_points_idx <- function(x, alpha) { stopifnot(is.numeric(x), is.numeric(alpha), length(alpha) == 1, alpha > 0 && alpha < 1) target <- qcauchy(1 - alpha) - pos_idx <- order(x, decreasing = TRUE) - pos_idx <- pos_idx[x[pos_idx] > 0] + pos_idx <- which(x > 0) pos_vals <- x[pos_idx] - - cumsum_remove <- cumsum(pos_vals) - needed <- which(sum(x) - cumsum_remove <= target)[1] - removed_idx <- pos_idx[seq_len(needed)] - return(removed_idx) + + ord <- order(pos_vals, decreasing = TRUE) + sorted_idx <- pos_idx[ord] + sorted_vals <- pos_vals[ord] + + cumsum_remove <- cumsum(sorted_vals) + needed <- which(cumsum_remove >= sum(x) - target)[1L] + + if (is.na(needed)) { + return(integer(0)) + } + + return(sorted_idx[seq_len(needed)]) } \ No newline at end of file From 32a4087c83fb1fd256b037a2eac8875d6f07ab00 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Sat, 21 Feb 2026 20:55:05 +0200 Subject: [PATCH 016/120] add unittests for influential_points_idx --- tests/testthat/test-helpers-ppc.R | 38 +++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/testthat/test-helpers-ppc.R b/tests/testthat/test-helpers-ppc.R index 5ba8a904..3f7f3574 100644 --- a/tests/testthat/test-helpers-ppc.R +++ b/tests/testthat/test-helpers-ppc.R @@ -279,4 +279,42 @@ test_that("cauchy_combination_test handles boundary values", { # TODO: if 1 included in vector, CCT will always evaluate to 0 # as the mean evaluates to Inf and 1 - cdf(Inf) = 1 - 1 = 0 expect_equal(cauchy_combination_test(c(0, 0.3, 0.4, 1), truncate = TRUE), 0) +}) + +# Test for influential_points_idx -------------------------------------------- + +test_that("influential_points_idx handles empty and no positive values", { + # Empty vector + result <- influential_points_idx(numeric(0), 0.05) + expect_equal(result, integer(0)) + expect_type(result, "integer") + + # Mixed with no positive values + result <- influential_points_idx(c(-1, 0, -2), 0.05) + expect_equal(result, integer(0)) +}) + +test_that("influential_points_idx handles simple cases", { + # x = c(1, 2, 3), alpha = 0.05 + # target = qcauchy(0.95) ~= 6.314 + # sum(x) = 6 + # we need cumsum >= 6 - 6.314 = -0.314 + # So we need at least 1 element + x <- c(1, 2, 3) + result <- influential_points_idx(x, 0.05) + expect_type(result, "integer") + expect_true(length(result) >= 1) + expect_true(all(result %in% seq_along(x))) +}) + +test_that("influential_points_idx returns indices in correct order", { + # Values should be sorted by decreasing value + # x = c(1, 5, 2, 4, 3) -> positive indices: 1, 2, 3, 4, 5 + # Sorted by value: 5, 4, 3, 2, 1 -> indices: 2, 4, 5, 3, 1 + x <- c(1, 5, 2, 4, 3) + result <- influential_points_idx(x, 0.5) + if (length(result) > 1) { + values <- x[result] + expect_equal(values, sort(values, decreasing = TRUE)) + } }) \ No newline at end of file From 7ca5b9b2723fa14287b9ea3f67dfb638c9e79ac0 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Sat, 21 Feb 2026 21:31:02 +0200 Subject: [PATCH 017/120] update unittests for ppc_loo_pit_ecdf --- tests/testthat/test-ppc-loo.R | 36 ++--------------------------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/tests/testthat/test-ppc-loo.R b/tests/testthat/test-ppc-loo.R index 670571b0..4f19fddb 100644 --- a/tests/testthat/test-ppc-loo.R +++ b/tests/testthat/test-ppc-loo.R @@ -107,9 +107,6 @@ test_that("ppc_loo_pit_ecdf with method='correlated' returns ggplot object", { skip_if_not_installed("rstanarm") skip_if_not_installed("loo") - x <- 1 - (1 - runif(300))^(1.2) - ppc_loo_pit_ecdf(pit=x, method = "correlated", prob = 0.95, plot_diff = TRUE) - # Test with POT-C (default) expect_gg(p1 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated")) expect_gg(p2 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "POT")) @@ -155,41 +152,12 @@ test_that("ppc_loo_pit_ecdf method argument works correctly", { expect_true(!identical(p2$data, p3$data) || !identical(p2$layers, p3$layers)) }) -test_that("helper functions for dependence-aware tests work correctly", { - # Test Cauchy space transformation - x <- runif(100) - - cauchy_piet <- bayesplot:::cauchy_space(x) - expect_true(is.numeric(cauchy_piet)) - expect_true(length(cauchy_piet) == length(x)) - expect_true(all(is.finite(cauchy_piet))) - - # Test Shapley values - sh_val <- bayesplot:::shapley_mean_closedform(cauchy_pot) - expect_true(is.numeric(sh_val)) - expect_true(length(sh_val) == length(cauchy_pot)) - - # Test influential points - infl_idx <- bayesplot:::influential_points_idx(sh_val, alpha = 0.05) - expect_true(is.integer(infl_idx) || is.numeric(infl_idx)) - expect_true(all(infl_idx >= 1 & infl_idx <= length(sh_val))) - - # Test Cauchy aggregation - pvals <- runif(50, 0, 0.5) - agg_pval <- bayesplot:::cauchy_agg(pvals, truncate = FALSE) - expect_true(is.numeric(agg_pval)) - expect_true(agg_pval >= 0 && agg_pval <= 1) - - # Test truncated Cauchy aggregation - t_agg_pval <- bayesplot:::cauchy_agg(pvals, truncate = TRUE) - expect_true(is.numeric(t_agg_pval)) - expect_true(t_agg_pval >= 0 && t_agg_pval <= 1) -}) - test_that("ppc_loo_pit_ecdf correlated method handles edge cases", { skip_if_not_installed("rstanarm") skip_if_not_installed("loo") + set.seed(2026) + # Test with small sample small_pit <- runif(10) expect_gg(p1 <- ppc_loo_pit_ecdf(pit = small_pit, method = "correlated")) From a66358f64485d2a8d6603f1aacce50709bc3b6f6 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 09:35:46 +0200 Subject: [PATCH 018/120] remove influential_points_idx function --- R/helpers-ppc.R | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index 95c7a0ee..e4e60c8b 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -707,35 +707,4 @@ cauchy_combination_test <- function(x, truncate = NULL) { } else { 1 - pcauchy(mean(-qcauchy(x))) } -} - -#' Identify influential points for uniformity test -#' -#' Identifies the minimal set of points that need to be removed to bring -#' the test statistic below the critical threshold. -#' -#' @param x Numeric vector of Shapley values. -#' @param alpha Significance level. -#' @return Integer vector of indices of influential points to remove. -#' @noRd -influential_points_idx <- function(x, alpha) { - stopifnot(is.numeric(x), is.numeric(alpha), length(alpha) == 1, - alpha > 0 && alpha < 1) - - target <- qcauchy(1 - alpha) - pos_idx <- which(x > 0) - pos_vals <- x[pos_idx] - - ord <- order(pos_vals, decreasing = TRUE) - sorted_idx <- pos_idx[ord] - sorted_vals <- pos_vals[ord] - - cumsum_remove <- cumsum(sorted_vals) - needed <- which(cumsum_remove >= sum(x) - target)[1L] - - if (is.na(needed)) { - return(integer(0)) - } - - return(sorted_idx[seq_len(needed)]) } \ No newline at end of file From d62cd06062538b5f0369e010f37203c8eeaba9c3 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 09:38:02 +0200 Subject: [PATCH 019/120] remove unittests for influential_points_idx --- tests/testthat/test-helpers-ppc.R | 38 ------------------------------- 1 file changed, 38 deletions(-) diff --git a/tests/testthat/test-helpers-ppc.R b/tests/testthat/test-helpers-ppc.R index 3f7f3574..5ba8a904 100644 --- a/tests/testthat/test-helpers-ppc.R +++ b/tests/testthat/test-helpers-ppc.R @@ -279,42 +279,4 @@ test_that("cauchy_combination_test handles boundary values", { # TODO: if 1 included in vector, CCT will always evaluate to 0 # as the mean evaluates to Inf and 1 - cdf(Inf) = 1 - 1 = 0 expect_equal(cauchy_combination_test(c(0, 0.3, 0.4, 1), truncate = TRUE), 0) -}) - -# Test for influential_points_idx -------------------------------------------- - -test_that("influential_points_idx handles empty and no positive values", { - # Empty vector - result <- influential_points_idx(numeric(0), 0.05) - expect_equal(result, integer(0)) - expect_type(result, "integer") - - # Mixed with no positive values - result <- influential_points_idx(c(-1, 0, -2), 0.05) - expect_equal(result, integer(0)) -}) - -test_that("influential_points_idx handles simple cases", { - # x = c(1, 2, 3), alpha = 0.05 - # target = qcauchy(0.95) ~= 6.314 - # sum(x) = 6 - # we need cumsum >= 6 - 6.314 = -0.314 - # So we need at least 1 element - x <- c(1, 2, 3) - result <- influential_points_idx(x, 0.05) - expect_type(result, "integer") - expect_true(length(result) >= 1) - expect_true(all(result %in% seq_along(x))) -}) - -test_that("influential_points_idx returns indices in correct order", { - # Values should be sorted by decreasing value - # x = c(1, 5, 2, 4, 3) -> positive indices: 1, 2, 3, 4, 5 - # Sorted by value: 5, 4, 3, 2, 1 -> indices: 2, 4, 5, 3, 1 - x <- c(1, 5, 2, 4, 3) - result <- influential_points_idx(x, 0.5) - if (length(result) > 1) { - values <- x[result] - expect_equal(values, sort(values, decreasing = TRUE)) - } }) \ No newline at end of file From 753053fc0b558711116de643a72a3a677bdd4991 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 09:38:55 +0200 Subject: [PATCH 020/120] remove infl_points_only argument, add linewith, color arguments, and improve input validation checks --- R/ppc-loo.R | 95 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 40 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 8f455af1..75b69ecb 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -411,10 +411,9 @@ ppc_loo_pit_qq <- function(y, #' threshold controlling how strongly suspicious points are flagged. Larger #' values highlight only the most influential points. If `NULL`, automatically #' determined based on p-value. -#' @param infl_points_only For `ppc_loo_pit_ecdf()` when `method = "correlated"`, -#' logical; if `TRUE` only the most influential points are colored (in case of -#' rejection), otherwise all suspicious points (regions) are highlighted -#' (recommended). +#' @param lw For `ppc_loo_pit_ecdf()`, linewidth for the ECDF plot. Defaults to 0.3. +#' @param color For `ppc_loo_pit_ecdf()`. Vector with base color and highlight color +#' for the ECDF plot. Defaults to c(ecdf = "gray60", highlight = "gray30"). ppc_loo_pit_ecdf <- function(y, yrep, lw = NULL, @@ -426,13 +425,14 @@ ppc_loo_pit_ecdf <- function(y, plot_diff = FALSE, interpolate_adj = NULL, method = NULL, - test = c("POT", "PRIT", "PIET"), + test = NULL, gamma = NULL, - infl_points_only = FALSE) { + linewidth = NULL, + color = NULL) { check_ignored_arguments(..., ok_args = list("moment_match")) - # Input validation + # Input validation ------------------------------------------------------- if (is.null(method)) { inform( c( @@ -480,6 +480,37 @@ ppc_loo_pit_ecdf <- function(y, } } + # Input validation dependent on method + if (method == "correlated") { + inform("method = 'correlated' specified so ignoring 'interpolate_adj' if specified.") + if (is.null(test)) { + # TODO: No default value for 'test'. Is this desired? + stop(paste( + "method = 'correlated' requires 'test' argument.", + "Possible values: 'POT', 'PRIT', 'PIET'." + )) + + # set default arguments + gamma <- gamma %||% 0 + linewidth <- linewidth %||% 0.3 + color <- color %||% c(ecdf = "gray60", highlight = "gray30") + } + # TODO: Shall we inform the user about the used default arguments? + pointwise_contribution <- compute_shapley_values(std_cauchy_values) + + if (gamma < 0 || gamma > max(pointwise_contribution)) { + stop(sprintf( + "gamma must be in the interval [0, %.2f], but gamma = %s was provided", + max(pointwise_contribution), gamma + )) + } + + } else if (method == "independent") { + inform(paste("method = 'independent' is specified so ignoring", + "'test', 'gamma' if specified." + )) + } + n_obs <- length(pit) unit_interval <- seq(0, 1, length.out = K) ecdf_pit_fn <- ecdf(pit) @@ -501,8 +532,9 @@ ppc_loo_pit_ecdf <- function(y, p_value_CCT <- cauchy_combination_test(prit_test(pit), truncate = TRUE) } - pointwise_contribution <- compute_shapley_values(std_cauchy_values) - highlight_color <- dplyr::if_else(p_value_CCT < alpha, "red", "#F97316") + + + # highlight_color <- dplyr::if_else(p_value_CCT < alpha, "red", "#F97316") x_axis_combined <- sort(unique(c(unit_interval, pit))) # Evaluate at 0-1 interval b´values @@ -520,7 +552,7 @@ ppc_loo_pit_ecdf <- function(y, # Plot ECDF p <- ggplot(df_main, aes(x = x, y = ecdf_pit)) + - geom_step(show.legend = FALSE) + + geom_step(show.legend = FALSE, linewidth = linewidth, color = color[1]) + labs( y = dplyr::if_else(plot_diff, "ECDF difference", "ECDF"), x = "LOO PIT" @@ -534,30 +566,8 @@ ppc_loo_pit_ecdf <- function(y, color = get_color("m") ) - if (infl_points_only) { - if (p_value_CCT < alpha) { - pos_idx <- influential_points_idx(x = pointwise_contribution, alpha = alpha) - df_points <- df_pit[pos_idx, ] - - p <- p + geom_point( - data = df_points, - aes(x = pit, y = ecdf_pit), - color = highlight_color, - size = 2, - show.legend = FALSE - ) - } - } else { - if (is.null(gamma) || gamma < 0) { - if (p_value_CCT <= 0.5) { - gamma <- 0 - } else if (p_value_CCT <= 0.9) { - gamma <- 0.05 - } else { - gamma <- 0.2 - } - } - + # Identify and highlight suspecious points (regions) of the ECDF + if (p_value_CCT < alpha) { red_idx <- which(pointwise_contribution > gamma) if (length(red_idx) > 0) { @@ -590,8 +600,8 @@ ppc_loo_pit_ecdf <- function(y, p <- p + geom_step( data = df_segments, aes(x = x, y = ecdf_pit, group = segment), - color = highlight_color, - linewidth = 1 + color = color[2], + linewidth = linewidth + 0.8 ) } @@ -599,8 +609,8 @@ ppc_loo_pit_ecdf <- function(y, p <- p + geom_point( data = df_isolated, aes(x = pit, y = ecdf_pit), - color = highlight_color, - size = 1.5 + color = color[2], + size = linewidth + 1 ) } } @@ -612,6 +622,11 @@ ppc_loo_pit_ecdf <- function(y, scale_color_ppc() + bayesplot_theme_get() + message(sprintf( + "Using tolerance \u03b3 = %s (valid range: [0, %.2f]).\nSetting \u03b3 > 0 emphasizes points with larger deviations.", + gamma, max(pointwise_contribution) + )) + return(p) } @@ -633,8 +648,8 @@ ppc_loo_pit_ecdf <- function(y, p <- ggplot() + geom_step( - aes(x = unit_interval, y = ecdf_eval, color = "y"), - show.legend = FALSE + aes(x = unit_interval, y = ecdf_eval, color = "y", linewidth = linewidth), + color = color[1], show.legend = FALSE ) + geom_step( aes(x = unit_interval, y = lims_upper_scaled, color = "yrep"), From 1ae2595310474a9f0ab11838ea9d6b3a71751c74 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 11:30:46 +0200 Subject: [PATCH 021/120] minor fixes in plotting behavior (fontsize, linestyle) and input validation --- R/ppc-loo.R | 55 ++++++++++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 75b69ecb..07290d43 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -411,7 +411,7 @@ ppc_loo_pit_qq <- function(y, #' threshold controlling how strongly suspicious points are flagged. Larger #' values highlight only the most influential points. If `NULL`, automatically #' determined based on p-value. -#' @param lw For `ppc_loo_pit_ecdf()`, linewidth for the ECDF plot. Defaults to 0.3. +#' @param linewidth For `ppc_loo_pit_ecdf()`, linewidth for the ECDF plot. Defaults to 0.3. #' @param color For `ppc_loo_pit_ecdf()`. Vector with base color and highlight color #' for the ECDF plot. Defaults to c(ecdf = "gray60", highlight = "gray30"). ppc_loo_pit_ecdf <- function(y, @@ -489,21 +489,16 @@ ppc_loo_pit_ecdf <- function(y, "method = 'correlated' requires 'test' argument.", "Possible values: 'POT', 'PRIT', 'PIET'." )) - - # set default arguments - gamma <- gamma %||% 0 - linewidth <- linewidth %||% 0.3 - color <- color %||% c(ecdf = "gray60", highlight = "gray30") } - # TODO: Shall we inform the user about the used default arguments? - pointwise_contribution <- compute_shapley_values(std_cauchy_values) - if (gamma < 0 || gamma > max(pointwise_contribution)) { - stop(sprintf( - "gamma must be in the interval [0, %.2f], but gamma = %s was provided", - max(pointwise_contribution), gamma - )) - } + test <- match.arg(test, choices = c("POT", "PRIT", "PIET")) + + # set default arguments + alpha <- 1 - prob + gamma <- gamma %||% 0 + linewidth <- linewidth %||% 0.3 + color <- color %||% c(ecdf = "gray60", highlight = "gray30") + # TODO: Shall we inform the user about the used default arguments? } else if (method == "independent") { inform(paste("method = 'independent' is specified so ignoring", @@ -517,9 +512,6 @@ ppc_loo_pit_ecdf <- function(y, # Correlated method -------------------------------------------------- if (method == "correlated") { - test <- match.arg(test) - alpha <- 1 - prob - # Compute test p-value and Cauchy-transformed values if (test == "POT") { std_cauchy_values <- -qcauchy(pot_test(sort(pit))) @@ -527,14 +519,19 @@ ppc_loo_pit_ecdf <- function(y, } else if (test == "PIET") { std_cauchy_values <- -qcauchy(piet_test(sort(pit))) p_value_CCT <- cauchy_combination_test(piet_test(pit), truncate = FALSE) - } else { # PRIT + } else if (test == "PRIT") { std_cauchy_values <- -qcauchy(prit_test(sort(pit))) p_value_CCT <- cauchy_combination_test(prit_test(pit), truncate = TRUE) } - + pointwise_contribution <- compute_shapley_values(std_cauchy_values) - # highlight_color <- dplyr::if_else(p_value_CCT < alpha, "red", "#F97316") + if (gamma < 0 || gamma > max(pointwise_contribution)) { + stop(sprintf( + "gamma must be in the interval [0, %.2f], but gamma = %s was provided", + max(pointwise_contribution), gamma + )) + } x_axis_combined <- sort(unique(c(unit_interval, pit))) # Evaluate at 0-1 interval b´values @@ -563,7 +560,7 @@ ppc_loo_pit_ecdf <- function(y, intercept = 0, slope = dplyr::if_else(plot_diff, 0, 1), linetype = 2, - color = get_color("m") + color = "darkgrey" ) # Identify and highlight suspecious points (regions) of the ECDF @@ -620,7 +617,7 @@ ppc_loo_pit_ecdf <- function(y, p <- p + yaxis_ticks(FALSE) + scale_color_ppc() + - bayesplot_theme_get() + bayesplot::theme_default(base_family = "sans", base_size = 16) message(sprintf( "Using tolerance \u03b3 = %s (valid range: [0, %.2f]).\nSetting \u03b3 > 0 emphasizes points with larger deviations.", @@ -647,18 +644,16 @@ ppc_loo_pit_ecdf <- function(y, lims_lower_scaled <- lims$lower[-1] * n_obs_inv - plot_diff * unit_interval p <- ggplot() + - geom_step( - aes(x = unit_interval, y = ecdf_eval, color = "y", linewidth = linewidth), - color = color[1], show.legend = FALSE - ) + geom_step( aes(x = unit_interval, y = lims_upper_scaled, color = "yrep"), - linetype = 2, - show.legend = FALSE + linetype = 1, show.legend = FALSE ) + geom_step( aes(x = unit_interval, y = lims_lower_scaled, color = "yrep"), - linetype = 2, + linetype = 1, show.legend = FALSE + ) + + geom_step( + aes(x = unit_interval, y = ecdf_eval, color = "y", linewidth = linewidth), show.legend = FALSE ) + labs( @@ -667,7 +662,7 @@ ppc_loo_pit_ecdf <- function(y, ) + yaxis_ticks(FALSE) + scale_color_ppc() + - bayesplot_theme_get() + bayesplot::theme_default(base_family = "sans", base_size = 16) return(p) } From 270f67e4e4bacffb7afaa145fe292336971318e1 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 11:33:31 +0200 Subject: [PATCH 022/120] adjust tests to new ppc_loo_pit_ecdf implementation --- tests/testthat/test-ppc-loo.R | 59 ++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/tests/testthat/test-ppc-loo.R b/tests/testthat/test-ppc-loo.R index 4f19fddb..99c5a94f 100644 --- a/tests/testthat/test-ppc-loo.R +++ b/tests/testthat/test-ppc-loo.R @@ -103,28 +103,34 @@ test_that("ppc_loo_pit_ecdf returns a ggplot object", { expect_equal(ll3$y, "ECDF difference") }) +test_that("ppc_loo_pit_ecdf with method='correlated' validates input correctly", { + set.seed(2025) + pit <- 1 - (1 - runif(300))^(1.2) + + expect_error( + expect_gg(ppc_loo_pit_ecdf(pit = pit, method = "correlated", test="PRIT"), + "method = 'correlated' requires 'test' argument. Possible values: 'POT', 'PRIT', 'PIET'." + )) +}) + test_that("ppc_loo_pit_ecdf with method='correlated' returns ggplot object", { skip_if_not_installed("rstanarm") skip_if_not_installed("loo") # Test with POT-C (default) - expect_gg(p1 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated")) - expect_gg(p2 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "POT")) + expect_gg(p1 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "POT")) # Test with PRIT-C - expect_gg(p3 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "PRIT")) + expect_gg(p2 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "PRIT")) # Test with PIET-C - expect_gg(p4 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "PIET")) + expect_gg(p3 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "PIET")) # Test with plot_diff = TRUE - expect_gg(p5 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", plot_diff = TRUE)) - - # Test with infl_points_only = TRUE - expect_gg(p6 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", infl_points_only = TRUE)) + expect_gg(p4 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", plot_diff = TRUE)) # Test with gamma specified - expect_gg(p7 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", gamma = 0.1)) + expect_gg(p5 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", gamma = 0.1)) }) test_that("ppc_loo_pit_ecdf method argument works correctly", { @@ -160,19 +166,19 @@ test_that("ppc_loo_pit_ecdf correlated method handles edge cases", { # Test with small sample small_pit <- runif(10) - expect_gg(p1 <- ppc_loo_pit_ecdf(pit = small_pit, method = "correlated")) + expect_gg(p1 <- ppc_loo_pit_ecdf(pit = small_pit, method = "correlated", test = "POT")) # Test with perfect uniform uniform_pit <- seq(0, 1, length.out = 100) - expect_gg(p2 <- ppc_loo_pit_ecdf(pit = uniform_pit, method = "correlated")) + expect_gg(p2 <- ppc_loo_pit_ecdf(pit = uniform_pit, method = "correlated", test = "POT")) # Test with extreme values extreme_pit <- c(rep(0, 10), rep(1, 10), runif(80)) - expect_gg(p3 <- ppc_loo_pit_ecdf(pit = extreme_pit, method = "correlated")) + expect_gg(p3 <- ppc_loo_pit_ecdf(pit = extreme_pit, method = "correlated", test = "POT")) # Test with single value (edge case) single_pit <- 0.5 - expect_gg(p4 <- ppc_loo_pit_ecdf(pit = single_pit, method = "correlated")) + expect_gg(p4 <- ppc_loo_pit_ecdf(pit = single_pit, method = "correlated", test = "POT")) }) test_that("ppc_loo_pit functions work when pit specified instead of y, yrep, and lw", { @@ -208,7 +214,6 @@ test_that("ppc_loo_pit functions work when pit specified instead of y, yrep, and ) }) - test_that("ppc_loo_intervals returns ggplot object", { skip_if_not_installed("rstanarm") skip_if_not_installed("loo") @@ -371,6 +376,32 @@ test_that("ppc_loo_ribbon renders correctly", { vdiffr::expect_doppelganger("ppc_loo_ribbon (subset)", p_custom) }) +test_that("ppc_loo_pit_ecdf with minimal examples", { + set.seed(2025) + pit <- 1 - (1 - runif(300))^(1.2) + + p_cor_pot <- ppc_loo_pit_ecdf( + pit = pit, + method = "correlated", + test = "POT" + ) + vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (correlated pot)", p_cor_pot) + + p_cor_prit <- ppc_loo_pit_ecdf( + pit = pit, + method = "correlated", + test = "PRIT" + ) + vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (correlated prit)", p_cor_prit) + + p_cor_piet <- ppc_loo_pit_ecdf( + pit = pit, + method = "correlated", + test = "PIET" + ) + vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (correlated piet)", p_cor_piet) +}) + test_that("ppc_loo_pit_ecdf renders correctly", { skip_on_cran() skip_if_not_installed("vdiffr") From 7489701e6157e98b85b784351e89e0ef04c45225 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 12:31:43 +0200 Subject: [PATCH 023/120] add compute_cauchy function --- R/helpers-ppc.R | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index e4e60c8b..c3abb5bb 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -707,4 +707,15 @@ cauchy_combination_test <- function(x, truncate = NULL) { } else { 1 - pcauchy(mean(-qcauchy(x))) } +} + +#' Compute Cauchy transformation +#' +#' Transforms PIT values to follow a standard Cauchy distribution. +#' +#' @param x Numeric vector of PIT values in [0, 1]. +#' @return Numeric vector of Cauchy-transformed values. +#' @noRd +compute_cauchy <- function(x) { + tan((0.5 - x) * pi) } \ No newline at end of file From 22048bd8f6605638193ffca93edf94324616e299 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 12:32:52 +0200 Subject: [PATCH 024/120] transition from -qcauchy(x) to compute_cauchy(x) --- R/ppc-loo.R | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 07290d43..f57669c6 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -514,13 +514,13 @@ ppc_loo_pit_ecdf <- function(y, if (method == "correlated") { # Compute test p-value and Cauchy-transformed values if (test == "POT") { - std_cauchy_values <- -qcauchy(pot_test(sort(pit))) + std_cauchy_values <- compute_cauchy(pot_test(sort(pit))) p_value_CCT <- cauchy_combination_test(pot_test(pit), truncate = FALSE) } else if (test == "PIET") { - std_cauchy_values <- -qcauchy(piet_test(sort(pit))) + std_cauchy_values <- compute_cauchy(piet_test(sort(pit))) p_value_CCT <- cauchy_combination_test(piet_test(pit), truncate = FALSE) - } else if (test == "PRIT") { - std_cauchy_values <- -qcauchy(prit_test(sort(pit))) + } else { # PRIT + std_cauchy_values <- compute_cauchy(prit_test(sort(pit))) p_value_CCT <- cauchy_combination_test(prit_test(pit), truncate = TRUE) } @@ -646,11 +646,11 @@ ppc_loo_pit_ecdf <- function(y, p <- ggplot() + geom_step( aes(x = unit_interval, y = lims_upper_scaled, color = "yrep"), - linetype = 1, show.legend = FALSE + linetype = 2, show.legend = FALSE ) + geom_step( aes(x = unit_interval, y = lims_lower_scaled, color = "yrep"), - linetype = 1, show.legend = FALSE + linetype = 2, show.legend = FALSE ) + geom_step( aes(x = unit_interval, y = ecdf_eval, color = "y", linewidth = linewidth), From 8180cb7a188189bbda8d0a5fc24c9a71497e4a63 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 12:33:27 +0200 Subject: [PATCH 025/120] add unittests for compute_cauchy --- tests/testthat/test-helpers-ppc.R | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/testthat/test-helpers-ppc.R b/tests/testthat/test-helpers-ppc.R index 5ba8a904..ae0b4eef 100644 --- a/tests/testthat/test-helpers-ppc.R +++ b/tests/testthat/test-helpers-ppc.R @@ -279,4 +279,31 @@ test_that("cauchy_combination_test handles boundary values", { # TODO: if 1 included in vector, CCT will always evaluate to 0 # as the mean evaluates to Inf and 1 - cdf(Inf) = 1 - 1 = 0 expect_equal(cauchy_combination_test(c(0, 0.3, 0.4, 1), truncate = TRUE), 0) +}) + +# Test for compute_cauchy ----------------------------------------------------- + +test_that("compute_cauchy computes correct transformations", { + # For x = 0.5: tan((0.5 - 0.5) * pi) = tan(0) = 0 + expect_equal(compute_cauchy(0.5), 0, tolerance = 1e-10) + + # For x = 0.25: tan((0.5 - 0.25) * pi) = tan(0.25 * pi) = 1 + expect_equal(compute_cauchy(0.25), 1, tolerance = 1e-10) + + # For x = 0.75: tan((0.5 - 0.75) * pi) = tan(-0.25 * pi) = -1 + expect_equal(compute_cauchy(0.75), -1, tolerance = 1e-10) +}) + +skip("evaluates currently to FALSE") +test_that("compute_cauchy handles boundary values", { + # For x = 0: tan((0.5 - 0) * pi) = tan(π/2) = Inf + result_0 <- compute_cauchy(0) + # working alternative computation: result_0 = -qcauchy(0) + expect_true(is.infinite(result_0)) + expect_true(result_0 > 0) + + # For x = 1: tan((0.5 - 1) * pi) = tan(-π/2) = -Inf + result_1 <- compute_cauchy(1) + expect_true(is.infinite(result_1)) + expect_true(result_1 < 0) }) \ No newline at end of file From 703b9f0199974652775789c1b7aed053c2de5179 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 12:34:18 +0200 Subject: [PATCH 026/120] minor adjustments for regression-tests --- tests/testthat/test-ppc-loo.R | 41 ++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/tests/testthat/test-ppc-loo.R b/tests/testthat/test-ppc-loo.R index 99c5a94f..497a42eb 100644 --- a/tests/testthat/test-ppc-loo.R +++ b/tests/testthat/test-ppc-loo.R @@ -108,7 +108,7 @@ test_that("ppc_loo_pit_ecdf with method='correlated' validates input correctly", pit <- 1 - (1 - runif(300))^(1.2) expect_error( - expect_gg(ppc_loo_pit_ecdf(pit = pit, method = "correlated", test="PRIT"), + expect_gg(ppc_loo_pit_ecdf(pit = pit, method = "correlated"), "method = 'correlated' requires 'test' argument. Possible values: 'POT', 'PRIT', 'PIET'." )) }) @@ -127,10 +127,12 @@ test_that("ppc_loo_pit_ecdf with method='correlated' returns ggplot object", { expect_gg(p3 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "PIET")) # Test with plot_diff = TRUE - expect_gg(p4 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", plot_diff = TRUE)) + expect_gg(p4 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "POT", + plot_diff = TRUE)) # Test with gamma specified - expect_gg(p5 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", gamma = 0.1)) + expect_gg(p5 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "POT", + gamma = 0.1)) }) test_that("ppc_loo_pit_ecdf method argument works correctly", { @@ -152,7 +154,7 @@ test_that("ppc_loo_pit_ecdf method argument works correctly", { expect_gg(p2) # Test correlated method (no message expected) - expect_gg(p3 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated")) + expect_gg(p3 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "POT")) # Test that independent and correlated produce different plots expect_true(!identical(p2$data, p3$data) || !identical(p2$layers, p3$layers)) @@ -376,7 +378,7 @@ test_that("ppc_loo_ribbon renders correctly", { vdiffr::expect_doppelganger("ppc_loo_ribbon (subset)", p_custom) }) -test_that("ppc_loo_pit_ecdf with minimal examples", { +test_that("ppc_loo_pit_ecdf with method correlated renders different tests correctly", { set.seed(2025) pit <- 1 - (1 - runif(300))^(1.2) @@ -402,6 +404,35 @@ test_that("ppc_loo_pit_ecdf with minimal examples", { vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (correlated piet)", p_cor_piet) }) +test_that("ppc_loo_pit_ecdf renders different linewidths and colors correctly", { + set.seed(2025) + pit <- 1 - (1 - runif(300))^(1.2) + + p_cor_lw1 <- ppc_loo_pit_ecdf( + pit = pit, + method = "correlated", + test = "POT", + linewidth = 1. + ) + vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (linewidth = 1)", p_cor_lw1) + + p_cor_lw2 <- ppc_loo_pit_ecdf( + pit = pit, + method = "correlated", + test = "POT", + linewidth = 2. + ) + vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (linewidth = 2)", p_cor_lw2) + + p_cor_col <- ppc_loo_pit_ecdf( + pit = pit, + method = "correlated", + test = "POT", + color = c(ecdf = "darkblue", highlight = "red") + ) + vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (color change)", p_cor_col) +}) + test_that("ppc_loo_pit_ecdf renders correctly", { skip_on_cran() skip_if_not_installed("vdiffr") From 7f6fb129d4f94cb7ae033766b02eb9672a5d5684 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 12:34:43 +0200 Subject: [PATCH 027/120] change svg snapshots for regression tests --- .../ppc-loo/ppc-loo-pit-ecdf-color-change.svg | 62 + .../ppc-loo-pit-ecdf-correlated-piet.svg | 58 + .../ppc-loo-pit-ecdf-correlated-pot.svg | 62 + .../ppc-loo-pit-ecdf-correlated-prit.svg | 64 + .../ppc-loo/ppc-loo-pit-ecdf-default.svg | 62 +- .../ppc-loo-pit-ecdf-ecdf-difference.svg | 54 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg | 62 +- .../ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg | 62 + .../ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg | 62 + .../_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg | 62 +- tests/vdiffr.Rout.fail | 15891 ++++++++++++++++ 11 files changed, 16381 insertions(+), 120 deletions(-) create mode 100644 tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg create mode 100644 tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg create mode 100644 tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg create mode 100644 tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg create mode 100644 tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg create mode 100644 tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg create mode 100644 tests/vdiffr.Rout.fail diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg new file mode 100644 index 00000000..01fd0d57 --- /dev/null +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (color change) + + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg new file mode 100644 index 00000000..d54510e2 --- /dev/null +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (correlated piet) + + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg new file mode 100644 index 00000000..5f1c535c --- /dev/null +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (correlated pot) + + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg new file mode 100644 index 00000000..caf47149 --- /dev/null +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (correlated prit) + + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg index 9bdd3960..6135a6e7 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg @@ -20,40 +20,40 @@ - - + + - - - - + + + + - -0.00 -0.25 -0.50 -0.75 -1.00 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF -ppc_loo_pit_ecdf (default) + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (default) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg index 5441468f..cbcada47 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg @@ -20,36 +20,36 @@ - - + + - - - - + + + + - --0.1 -0.0 -0.1 - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF difference -ppc_loo_pit_ecdf (ecdf difference) + +-0.1 +0.0 +0.1 + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF difference +ppc_loo_pit_ecdf (ecdf difference) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg index 48f3cb24..4cb88f33 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg @@ -20,40 +20,40 @@ - - + + - - - - + + + + - -0.00 -0.25 -0.50 -0.75 -1.00 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF -ppc_loo_pit_ecdf (K) + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (K) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg new file mode 100644 index 00000000..379f73f7 --- /dev/null +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (linewidth = 1) + + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg new file mode 100644 index 00000000..91a8dea1 --- /dev/null +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (linewidth = 2) + + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg index dadcb9e6..8e1e5c79 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg @@ -20,40 +20,40 @@ - - + + - - - - + + + + - -0.00 -0.25 -0.50 -0.75 -1.00 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF -ppc_loo_pit_ecdf (prob) + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (prob) diff --git a/tests/vdiffr.Rout.fail b/tests/vdiffr.Rout.fail new file mode 100644 index 00000000..bef52f75 --- /dev/null +++ b/tests/vdiffr.Rout.fail @@ -0,0 +1,15891 @@ +Environment: +- vdiffr-svg-engine: 2.0 +- vdiffr: 1.0.9 + + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) + +< before +> after +@@ 58,5 / 58,5 @@ + LOO PIT + + ECDF +< ppc_loo_pit_ecdf (correlated- +: POT) +> ppc_loo_pit_ecdf (correlated +: pot) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-default (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (default) +> ppc_loo_pit_ecdf (default) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-k (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (K) +> ppc_loo_pit_ecdf (K) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-prob (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (prob) +> ppc_loo_pit_ecdf (prob) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-ecdf-difference (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg) + +< before +> after +@@ 21,35 / 21,35 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< -0.1 +> -0.1 +< 0.0 +> 0.0 +< 0.1 +> 0.1 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF difference +> ECDF difference +< ppc_loo_pit_ecdf (ecdf differ +: ence) +> ppc_loo_pit_ecdf (ecdf differ +: ence) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) + +< before +> after +@@ 58,5 / 58,5 @@ + LOO PIT + + ECDF +< ppc_loo_pit_ecdf (correlated- +: POT) +> ppc_loo_pit_ecdf (correlated +: pot) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-default (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (default) +> ppc_loo_pit_ecdf (default) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-k (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (K) +> ppc_loo_pit_ecdf (K) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-prob (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (prob) +> ppc_loo_pit_ecdf (prob) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-ecdf-difference (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg) + +< before +> after +@@ 21,35 / 21,35 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< -0.1 +> -0.1 +< 0.0 +> 0.0 +< 0.1 +> 0.1 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF difference +> ECDF difference +< ppc_loo_pit_ecdf (ecdf differ +: ence) +> ppc_loo_pit_ecdf (ecdf differ +: ence) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) + +< before +> after +@@ 58,5 / 58,5 @@ + LOO PIT + + ECDF +< ppc_loo_pit_ecdf (correlated- +: POT) +> ppc_loo_pit_ecdf (correlated +: pot) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-default (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (default) +> ppc_loo_pit_ecdf (default) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-k (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (K) +> ppc_loo_pit_ecdf (K) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-prob (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (prob) +> ppc_loo_pit_ecdf (prob) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-ecdf-difference (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg) + +< before +> after +@@ 21,35 / 21,35 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< -0.1 +> -0.1 +< 0.0 +> 0.0 +< 0.1 +> 0.1 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF difference +> ECDF difference +< ppc_loo_pit_ecdf (ecdf differ +: ence) +> ppc_loo_pit_ecdf (ecdf differ +: ence) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) + +< before +> after +@@ 58,5 / 58,5 @@ + LOO PIT + + ECDF +< ppc_loo_pit_ecdf (correlated- +: POT) +> ppc_loo_pit_ecdf (correlated +: pot) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-default (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (default) +> ppc_loo_pit_ecdf (default) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-k (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (K) +> ppc_loo_pit_ecdf (K) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-prob (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (prob) +> ppc_loo_pit_ecdf (prob) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-ecdf-difference (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg) + +< before +> after +@@ 21,35 / 21,35 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< -0.1 +> -0.1 +< 0.0 +> 0.0 +< 0.1 +> 0.1 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF difference +> ECDF difference +< ppc_loo_pit_ecdf (ecdf differ +: ence) +> ppc_loo_pit_ecdf (ecdf differ +: ence) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) + +< before +> after +@@ 58,5 / 58,5 @@ + LOO PIT + + ECDF +< ppc_loo_pit_ecdf (correlated- +: POT) +> ppc_loo_pit_ecdf (correlated +: pot) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-default (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (default) +> ppc_loo_pit_ecdf (default) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-k (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (K) +> ppc_loo_pit_ecdf (K) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-prob (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (prob) +> ppc_loo_pit_ecdf (prob) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-ecdf-difference (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg) + +< before +> after +@@ 21,35 / 21,35 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< -0.1 +> -0.1 +< 0.0 +> 0.0 +< 0.1 +> 0.1 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF difference +> ECDF difference +< ppc_loo_pit_ecdf (ecdf differ +: ence) +> ppc_loo_pit_ecdf (ecdf differ +: ence) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-default (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (default) +> ppc_loo_pit_ecdf (default) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-k (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (K) +> ppc_loo_pit_ecdf (K) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-prob (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (prob) +> ppc_loo_pit_ecdf (prob) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-ecdf-difference (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg) + +< before +> after +@@ 21,35 / 21,35 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< -0.1 +> -0.1 +< 0.0 +> 0.0 +< 0.1 +> 0.1 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF difference +> ECDF difference +< ppc_loo_pit_ecdf (ecdf differ +: ence) +> ppc_loo_pit_ecdf (ecdf differ +: ence) + + + From 11086f9d59648f140a2a8e9ce3a36c0bff8ee0ab Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 12:48:08 +0200 Subject: [PATCH 028/120] improve documentation for arguments linewidth, color in ppc_loo_pit_ecdf --- R/ppc-loo.R | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index f57669c6..5e8fc61b 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -411,9 +411,13 @@ ppc_loo_pit_qq <- function(y, #' threshold controlling how strongly suspicious points are flagged. Larger #' values highlight only the most influential points. If `NULL`, automatically #' determined based on p-value. -#' @param linewidth For `ppc_loo_pit_ecdf()`, linewidth for the ECDF plot. Defaults to 0.3. -#' @param color For `ppc_loo_pit_ecdf()`. Vector with base color and highlight color -#' for the ECDF plot. Defaults to c(ecdf = "gray60", highlight = "gray30"). +#' @param linewidth For `ppc_loo_pit_ecdf()`, linewidth for the ECDF plot. When +#' `method = "correlated"`, defaults to 0.3. When `method = "independent"`, +#' if `NULL` no linewidth is specified for the ECDF line. +#' @param color For `ppc_loo_pit_ecdf()` when `method = "correlated"`, a vector +#' with base color and highlight color for the ECDF plot. Defaults to +#' `c(ecdf = "gray60", highlight = "gray30")`. The first element is used for +#' the main ECDF line, the second for highlighted suspicious regions. ppc_loo_pit_ecdf <- function(y, yrep, lw = NULL, From 5321ac04c8bf301583320ce5e4c014c88fe5c5a2 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 12:49:29 +0200 Subject: [PATCH 029/120] update PPC-loo.Rd file with new arguments --- man/PPC-loo.Rd | 44 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/man/PPC-loo.Rd b/man/PPC-loo.Rd index 555898d8..da675680 100644 --- a/man/PPC-loo.Rd +++ b/man/PPC-loo.Rd @@ -65,7 +65,12 @@ ppc_loo_pit_ecdf( K = NULL, prob = 0.99, plot_diff = FALSE, - interpolate_adj = NULL + interpolate_adj = NULL, + method = NULL, + test = NULL, + gamma = NULL, + linewidth = NULL, + color = NULL ) ppc_loo_pit( @@ -192,12 +197,37 @@ expectation for uniform PIT values rather than plotting the regular ECDF. The default is \code{FALSE}, but for large samples we recommend setting \code{plot_diff = TRUE} to better use the plot area.} -\item{interpolate_adj}{For \code{ppc_loo_pit_ecdf()}, a boolean defining if the -simultaneous confidence bands should be interpolated based on precomputed -values rather than computed exactly. Computing the bands may be -computationally intensive and the approximation gives a fast method for -assessing the ECDF trajectory. The default is to use interpolation if \code{K} -is greater than 200.} +\item{interpolate_adj}{For \code{ppc_loo_pit_ecdf()} when \code{method = "independent"}, +a boolean defining if the simultaneous confidence bands should be +interpolated based on precomputed values rather than computed exactly. +Computing the bands may be computationally intensive and the approximation +gives a fast method for assessing the ECDF trajectory. The default is to use +interpolation if \code{K} is greater than 200.} + +\item{method}{For \code{ppc_loo_pit_ecdf()}, the method used to calculate the +uniformity test: +\itemize{ +\item \code{"independent"}: (Current default) Assumes independence (Säilynoja et al., 2022). +\item \code{"correlated"}: (Recommended) Accounts for correlation (Tesso & Vehtari, 2026). +}} + +\item{test}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, which +dependence-aware test to use: \code{"POT"}, \code{"PRIT"}, or \code{"PIET"}. +Defaults to \code{"POT"}.} + +\item{gamma}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, tolerance +threshold controlling how strongly suspicious points are flagged. Larger +values highlight only the most influential points. If \code{NULL}, automatically +determined based on p-value.} + +\item{linewidth}{For \code{ppc_loo_pit_ecdf()}, linewidth for the ECDF plot. When +\code{method = "correlated"}, defaults to 0.3. When \code{method = "independent"}, +if \code{NULL} no linewidth is specified for the ECDF line.} + +\item{color}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, a vector +with base color and highlight color for the ECDF plot. Defaults to +\code{c(ecdf = "gray60", highlight = "gray30")}. The first element is used for +the main ECDF line, the second for highlighted suspicious regions.} \item{subset}{For \code{ppc_loo_intervals()} and \code{ppc_loo_ribbon()}, an optional integer vector indicating which observations in \code{y} (and \code{yrep}) to From 478e96e646b736568f7a73bc5b278e9783e6d637 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 12:59:54 +0200 Subject: [PATCH 030/120] add tests for plot_diff=TRUE and method=correlated --- tests/testthat/test-ppc-loo.R | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/testthat/test-ppc-loo.R b/tests/testthat/test-ppc-loo.R index 497a42eb..c85f6103 100644 --- a/tests/testthat/test-ppc-loo.R +++ b/tests/testthat/test-ppc-loo.R @@ -404,6 +404,35 @@ test_that("ppc_loo_pit_ecdf with method correlated renders different tests corre vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (correlated piet)", p_cor_piet) }) +test_that("ppc_loo_pit_ecdf with plot_diff=TRUE and method correlated renders different tests correctly", { + set.seed(2025) + pit <- 1 - (1 - runif(300))^(1.2) + + p_cor_pot <- ppc_loo_pit_ecdf( + pit = pit, + method = "correlated", + test = "POT", + plot_diff = TRUE + ) + vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (diff, correlated pot)", p_cor_pot) + + p_cor_prit <- ppc_loo_pit_ecdf( + pit = pit, + method = "correlated", + test = "PRIT", + plot_diff = TRUE + ) + vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (diff, correlated prit)", p_cor_prit) + + p_cor_piet <- ppc_loo_pit_ecdf( + pit = pit, + method = "correlated", + test = "PIET", + plot_diff = TRUE + ) + vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (diff, correlated piet)", p_cor_piet) +}) + test_that("ppc_loo_pit_ecdf renders different linewidths and colors correctly", { set.seed(2025) pit <- 1 - (1 - runif(300))^(1.2) From 779ef51838ebd2e70b2ddcedc395297a55479a6a Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 13:00:25 +0200 Subject: [PATCH 031/120] add svg for regression testing for new test --- .../ppc-loo-pit-ecdf-diff-correlated-piet.svg | 56 +++++++++++++++++ .../ppc-loo-pit-ecdf-diff-correlated-pot.svg | 60 ++++++++++++++++++ .../ppc-loo-pit-ecdf-diff-correlated-prit.svg | 62 +++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg create mode 100644 tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg create mode 100644 tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg new file mode 100644 index 00000000..7afc9be5 --- /dev/null +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + +-0.09 +-0.06 +-0.03 +0.00 + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF difference +ppc_loo_pit_ecdf (diff, correlated piet) + + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg new file mode 100644 index 00000000..05181c21 --- /dev/null +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-0.09 +-0.06 +-0.03 +0.00 + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF difference +ppc_loo_pit_ecdf (diff, correlated pot) + + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg new file mode 100644 index 00000000..325b1f22 --- /dev/null +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-0.09 +-0.06 +-0.03 +0.00 + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF difference +ppc_loo_pit_ecdf (diff, correlated prit) + + From 5a033148f13e9215344443919f1b0fc86e3b876f Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 13:42:03 +0200 Subject: [PATCH 032/120] add note section to ppc_loo_pit_ecdf to announce new method --- R/ppc-loo.R | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 5e8fc61b..173c6f74 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -418,6 +418,10 @@ ppc_loo_pit_qq <- function(y, #' with base color and highlight color for the ECDF plot. Defaults to #' `c(ecdf = "gray60", highlight = "gray30")`. The first element is used for #' the main ECDF line, the second for highlighted suspicious regions. +#' @note +#' Note that the default "independent" method is **superseded** by +#' the "correlated" method (Tesso & Vehtari, 2026) which accounts for dependent +#' LOO-PIT values. ppc_loo_pit_ecdf <- function(y, yrep, lw = NULL, From b7c7f17dad3801b443872f0bb203218a40690eb0 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 13:44:56 +0200 Subject: [PATCH 033/120] update documentation file (.Rd) incl. note section for ppc_loo_pit_ecdf --- man/PPC-loo.Rd | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/man/PPC-loo.Rd b/man/PPC-loo.Rd index da675680..20a12111 100644 --- a/man/PPC-loo.Rd +++ b/man/PPC-loo.Rd @@ -260,6 +260,11 @@ Leave-One-Out (LOO) predictive checks. See the \strong{Plot Descriptions} sectio below, and \href{https://github.com/jgabry/bayes-vis-paper#readme}{Gabry et al. (2019)} for details. } +\note{ +Note that the default "independent" method is \strong{superseded} by +the "correlated" method (Tesso & Vehtari, 2026) which accounts for dependent +LOO-PIT values. +} \section{Plot Descriptions}{ \describe{ From 430f624def88f09cdc7c8b1a4130c91eab627582 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 17:36:13 +0200 Subject: [PATCH 034/120] remove TODOs from comments --- R/ppc-loo.R | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 173c6f74..941c5340 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -492,7 +492,7 @@ ppc_loo_pit_ecdf <- function(y, if (method == "correlated") { inform("method = 'correlated' specified so ignoring 'interpolate_adj' if specified.") if (is.null(test)) { - # TODO: No default value for 'test'. Is this desired? + # TODO: No default value for 'test'. Is this desired? Default should be POT stop(paste( "method = 'correlated' requires 'test' argument.", "Possible values: 'POT', 'PRIT', 'PIET'." @@ -506,7 +506,6 @@ ppc_loo_pit_ecdf <- function(y, gamma <- gamma %||% 0 linewidth <- linewidth %||% 0.3 color <- color %||% c(ecdf = "gray60", highlight = "gray30") - # TODO: Shall we inform the user about the used default arguments? } else if (method == "independent") { inform(paste("method = 'independent' is specified so ignoring", From 31f0263849fc3267c80f5866bc0b3f53a75e724c Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 21:56:36 +0200 Subject: [PATCH 035/120] fix ticks around interval in documentation --- R/helpers-ppc.R | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index c3abb5bb..31c50ae3 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -638,7 +638,7 @@ compute_shapley_values <- function(x) { #' follows the distribution of X under uniformity. #' HA: The p-value p_(i) provides evidence against uniformity. #' -#' @param x Numeric vector of PIT values in [0, 1]. +#' @param x Numeric vector of PIT values in `[0, 1]`. #' @return Numeric vector of p-values. #' @noRd piet_test <- function(x) { @@ -656,7 +656,7 @@ piet_test <- function(x) { #' HA: The p-value p_(i) provides evidence against uniformity #' at the i-th order statistic u_(i). #' -#' @param x Numeric vector of PIT values in [0, 1]. +#' @param x Numeric vector of PIT values in `[0, 1]`. #' @return Numeric vector of p-values. #' @noRd pot_test <- function(x) { @@ -676,7 +676,7 @@ pot_test <- function(x) { #' follows a binomial distribution under uniformity. #' HA: The p-value p_i provides evidence against uniformity. #' -#' @param x Numeric vector of PIT values in [0, 1]. +#' @param x Numeric vector of PIT values in `[0, 1]`. #' @return Numeric vector of p-values. #' @noRd prit_test <- function(x) { @@ -713,7 +713,7 @@ cauchy_combination_test <- function(x, truncate = NULL) { #' #' Transforms PIT values to follow a standard Cauchy distribution. #' -#' @param x Numeric vector of PIT values in [0, 1]. +#' @param x Numeric vector of PIT values in `[0, 1]`. #' @return Numeric vector of Cauchy-transformed values. #' @noRd compute_cauchy <- function(x) { From c9312f08ec2ff3d64e7021794a418d950c7eb644 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 21:57:25 +0200 Subject: [PATCH 036/120] adjust data, mapping in gggplot --- R/ppc-loo.R | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 941c5340..7b8c3d4a 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -21,7 +21,9 @@ #' [ggplot2::geom_density()], respectively. For `ppc_loo_intervals()`, `size` #' `linewidth` and `fatten` are passed to [ggplot2::geom_pointrange()]. For #' `ppc_loo_ribbon()`, `alpha` and `size` are passed to -#' [ggplot2::geom_ribbon()]. +#' [ggplot2::geom_ribbon()]. For `ppc_loo_pit_ecdf()`, linewidth for the ECDF plot. When +#' `method = "correlated"`, defaults to 0.3. When `method = "independent"`, +#' if `NULL` no linewidth is specified for the ECDF line. #' #' @template return-ggplot #' @@ -411,9 +413,6 @@ ppc_loo_pit_qq <- function(y, #' threshold controlling how strongly suspicious points are flagged. Larger #' values highlight only the most influential points. If `NULL`, automatically #' determined based on p-value. -#' @param linewidth For `ppc_loo_pit_ecdf()`, linewidth for the ECDF plot. When -#' `method = "correlated"`, defaults to 0.3. When `method = "independent"`, -#' if `NULL` no linewidth is specified for the ECDF line. #' @param color For `ppc_loo_pit_ecdf()` when `method = "correlated"`, a vector #' with base color and highlight color for the ECDF plot. Defaults to #' `c(ecdf = "gray60", highlight = "gray30")`. The first element is used for @@ -555,8 +554,10 @@ ppc_loo_pit_ecdf <- function(y, df_pit <- df_pit[order(df_pit$pit), ] # Plot ECDF - p <- ggplot(df_main, aes(x = x, y = ecdf_pit)) + - geom_step(show.legend = FALSE, linewidth = linewidth, color = color[1]) + + p <- ggplot() + + geom_step( + data = df_main, aes(x = .data$x, y = .data$ecdf_pit), + show.legend = FALSE, linewidth = linewidth, color = color[1]) + labs( y = dplyr::if_else(plot_diff, "ECDF difference", "ECDF"), x = "LOO PIT" @@ -603,7 +604,7 @@ ppc_loo_pit_ecdf <- function(y, p <- p + geom_step( data = df_segments, - aes(x = x, y = ecdf_pit, group = segment), + aes(x = .data$x, y = .data$ecdf_pit, group = .data$segment), color = color[2], linewidth = linewidth + 0.8 ) @@ -612,7 +613,7 @@ ppc_loo_pit_ecdf <- function(y, if (nrow(df_isolated) > 0) { p <- p + geom_point( data = df_isolated, - aes(x = pit, y = ecdf_pit), + aes(x = .data$pit, y = .data$ecdf_pit), color = color[2], size = linewidth + 1 ) From 81e667c9fa0dad62f61b11f609be0b91d32d9738 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 23 Feb 2026 21:59:18 +0200 Subject: [PATCH 037/120] update information for 'linewidth' argument --- man/PPC-loo.Rd | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/man/PPC-loo.Rd b/man/PPC-loo.Rd index 20a12111..5337d4d2 100644 --- a/man/PPC-loo.Rd +++ b/man/PPC-loo.Rd @@ -153,7 +153,9 @@ and \code{alpha} are passed to \code{\link[ggplot2:geom_point]{ggplot2::geom_poi \code{\link[ggplot2:geom_density]{ggplot2::geom_density()}}, respectively. For \code{ppc_loo_intervals()}, \code{size} \code{linewidth} and \code{fatten} are passed to \code{\link[ggplot2:geom_linerange]{ggplot2::geom_pointrange()}}. For \code{ppc_loo_ribbon()}, \code{alpha} and \code{size} are passed to -\code{\link[ggplot2:geom_ribbon]{ggplot2::geom_ribbon()}}.} +\code{\link[ggplot2:geom_ribbon]{ggplot2::geom_ribbon()}}. For \code{ppc_loo_pit_ecdf()}, linewidth for the ECDF plot. When +\code{method = "correlated"}, defaults to 0.3. When \code{method = "independent"}, +if \code{NULL} no linewidth is specified for the ECDF line.} \item{boundary_correction}{For \code{ppc_loo_pit_overlay()}, when set to \code{TRUE} (the default) the function will compute boundary corrected density values @@ -220,10 +222,6 @@ threshold controlling how strongly suspicious points are flagged. Larger values highlight only the most influential points. If \code{NULL}, automatically determined based on p-value.} -\item{linewidth}{For \code{ppc_loo_pit_ecdf()}, linewidth for the ECDF plot. When -\code{method = "correlated"}, defaults to 0.3. When \code{method = "independent"}, -if \code{NULL} no linewidth is specified for the ECDF line.} - \item{color}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, a vector with base color and highlight color for the ECDF plot. Defaults to \code{c(ecdf = "gray60", highlight = "gray30")}. The first element is used for From 1bee0b430f89fcebfa4d284319e03d52b3887c9c Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Tue, 24 Feb 2026 11:18:25 +0200 Subject: [PATCH 038/120] add POT as default test and reduce user info messages --- R/ppc-loo.R | 68 ++++++++++++++++++----------------- tests/testthat/test-ppc-loo.R | 56 ++++++++++++++++------------- 2 files changed, 67 insertions(+), 57 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 7b8c3d4a..379999e4 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -411,7 +411,7 @@ ppc_loo_pit_qq <- function(y, #' Defaults to `"POT"`. #' @param gamma For `ppc_loo_pit_ecdf()` when `method = "correlated"`, tolerance #' threshold controlling how strongly suspicious points are flagged. Larger -#' values highlight only the most influential points. If `NULL`, automatically +#' values (gamma > 0) emphasizes points with larger deviations. If `NULL`, automatically #' determined based on p-value. #' @param color For `ppc_loo_pit_ecdf()` when `method = "correlated"`, a vector #' with base color and highlight color for the ECDF plot. Defaults to @@ -440,6 +440,13 @@ ppc_loo_pit_ecdf <- function(y, check_ignored_arguments(..., ok_args = list("moment_match")) # Input validation ------------------------------------------------------- + # internal helper for printing user information if needed + .warn_ignored <- function(method, args) { + msg <- paste0("As method = ", method, " specified; ignoring: ", + paste(args, collapse = ", "), ".") + inform(msg) + } + if (is.null(method)) { inform( c( @@ -459,9 +466,7 @@ ppc_loo_pit_ecdf <- function(y, if (method == "independent") { inform( paste( - "The 'independent' method is superseded by the 'correlated' method.", - "The new 'correlated' approach provides an updated uniformity test", - "and graphical representation." + "The 'independent' method is superseded by the 'correlated' method." ) ) } @@ -469,11 +474,19 @@ ppc_loo_pit_ecdf <- function(y, # PIT calculation or validation if (!is.null(pit)) { - inform("'pit' specified so ignoring 'y','yrep','lw' if specified.") pit <- validate_pit(pit) if (is.null(K)) { K <- length(pit) } + # print user info only if corresponding args are specified + ignored <- character(0) + if (!missing(y) && !is.null(y)) ignored <- c(ignored, "y") + if (!missing(yrep) && !is.null(yrep)) ignored <- c(ignored, "yrep") + if (!is.null(lw)) ignored <- c(ignored, "lw") + if (length(ignored) > 0) { + inform(paste0("As 'pit' specified; ignoring: ", paste(ignored, collapse = ", "), ".")) + } + } else { suggested_package("rstantools") y <- validate_y(y) @@ -488,29 +501,25 @@ ppc_loo_pit_ecdf <- function(y, } # Input validation dependent on method - if (method == "correlated") { - inform("method = 'correlated' specified so ignoring 'interpolate_adj' if specified.") - if (is.null(test)) { - # TODO: No default value for 'test'. Is this desired? Default should be POT - stop(paste( - "method = 'correlated' requires 'test' argument.", - "Possible values: 'POT', 'PRIT', 'PIET'." - )) - } - - test <- match.arg(test, choices = c("POT", "PRIT", "PIET")) + switch(method, + "correlated" = { + if (!is.null(interpolate_adj)) .warn_ignored("'correlated'", "interpolate_adj") + + test <- match.arg(test %||% "POT", choices = c("POT", "PRIT", "PIET")) + + alpha <- 1 - prob + gamma <- gamma %||% 0 + linewidth <- linewidth %||% 0.3 + color <- color %||% c(ecdf = "gray60", highlight = "gray30") + }, - # set default arguments - alpha <- 1 - prob - gamma <- gamma %||% 0 - linewidth <- linewidth %||% 0.3 - color <- color %||% c(ecdf = "gray60", highlight = "gray30") - - } else if (method == "independent") { - inform(paste("method = 'independent' is specified so ignoring", - "'test', 'gamma' if specified." - )) - } + "independent" = { + ignored <- character(0) + if (!is.null(test)) ignored <- c(ignored, "test") + if (!is.null(gamma)) ignored <- c(ignored, "gamma") + if (length(ignored) > 0) .warn_ignored("'independent'", ignored) + } + ) n_obs <- length(pit) unit_interval <- seq(0, 1, length.out = K) @@ -626,11 +635,6 @@ ppc_loo_pit_ecdf <- function(y, yaxis_ticks(FALSE) + scale_color_ppc() + bayesplot::theme_default(base_family = "sans", base_size = 16) - - message(sprintf( - "Using tolerance \u03b3 = %s (valid range: [0, %.2f]).\nSetting \u03b3 > 0 emphasizes points with larger deviations.", - gamma, max(pointwise_contribution) - )) return(p) } diff --git a/tests/testthat/test-ppc-loo.R b/tests/testthat/test-ppc-loo.R index c85f6103..5ca60a8c 100644 --- a/tests/testthat/test-ppc-loo.R +++ b/tests/testthat/test-ppc-loo.R @@ -106,11 +106,24 @@ test_that("ppc_loo_pit_ecdf returns a ggplot object", { test_that("ppc_loo_pit_ecdf with method='correlated' validates input correctly", { set.seed(2025) pit <- 1 - (1 - runif(300))^(1.2) + y_mock <- 1:length(pit) - expect_error( - expect_gg(ppc_loo_pit_ecdf(pit = pit, method = "correlated"), - "method = 'correlated' requires 'test' argument. Possible values: 'POT', 'PRIT', 'PIET'." - )) + expect_message( + ppc_loo_pit_ecdf(pit = pit, method = "correlated", interpolate_adj = FALSE), + "As method = 'correlated' specified; ignoring: interpolate_adj." + ) + expect_message( + ppc_loo_pit_ecdf(pit = pit, method = "independent", y = y_mock), + "As 'pit' specified; ignoring: y." + ) + expect_message( + ppc_loo_pit_ecdf(pit = pit, method = "independent", gamma = 1.0), + "As method = 'independent' specified; ignoring: gamma." + ) + expect_message( + ppc_loo_pit_ecdf(pit = pit, method = "independent", test = "POT"), + "As method = 'independent' specified; ignoring: test." + ) }) test_that("ppc_loo_pit_ecdf with method='correlated' returns ggplot object", { @@ -118,7 +131,7 @@ test_that("ppc_loo_pit_ecdf with method='correlated' returns ggplot object", { skip_if_not_installed("loo") # Test with POT-C (default) - expect_gg(p1 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "POT")) + expect_gg(p1 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated")) # Test with PRIT-C expect_gg(p2 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "PRIT")) @@ -127,12 +140,10 @@ test_that("ppc_loo_pit_ecdf with method='correlated' returns ggplot object", { expect_gg(p3 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "PIET")) # Test with plot_diff = TRUE - expect_gg(p4 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "POT", - plot_diff = TRUE)) + expect_gg(p4 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", plot_diff = TRUE)) # Test with gamma specified - expect_gg(p5 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "POT", - gamma = 0.1)) + expect_gg(p5 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", gamma = 0.1)) }) test_that("ppc_loo_pit_ecdf method argument works correctly", { @@ -154,7 +165,7 @@ test_that("ppc_loo_pit_ecdf method argument works correctly", { expect_gg(p2) # Test correlated method (no message expected) - expect_gg(p3 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated", test = "POT")) + expect_gg(p3 <- ppc_loo_pit_ecdf(y, yrep, lw, method = "correlated")) # Test that independent and correlated produce different plots expect_true(!identical(p2$data, p3$data) || !identical(p2$layers, p3$layers)) @@ -168,19 +179,19 @@ test_that("ppc_loo_pit_ecdf correlated method handles edge cases", { # Test with small sample small_pit <- runif(10) - expect_gg(p1 <- ppc_loo_pit_ecdf(pit = small_pit, method = "correlated", test = "POT")) + expect_gg(p1 <- ppc_loo_pit_ecdf(pit = small_pit, method = "correlated")) # Test with perfect uniform uniform_pit <- seq(0, 1, length.out = 100) - expect_gg(p2 <- ppc_loo_pit_ecdf(pit = uniform_pit, method = "correlated", test = "POT")) + expect_gg(p2 <- ppc_loo_pit_ecdf(pit = uniform_pit, method = "correlated")) # Test with extreme values extreme_pit <- c(rep(0, 10), rep(1, 10), runif(80)) - expect_gg(p3 <- ppc_loo_pit_ecdf(pit = extreme_pit, method = "correlated", test = "POT")) + expect_gg(p3 <- ppc_loo_pit_ecdf(pit = extreme_pit, method = "correlated")) # Test with single value (edge case) single_pit <- 0.5 - expect_gg(p4 <- ppc_loo_pit_ecdf(pit = single_pit, method = "correlated", test = "POT")) + expect_gg(p4 <- ppc_loo_pit_ecdf(pit = single_pit, method = "correlated")) }) test_that("ppc_loo_pit functions work when pit specified instead of y, yrep, and lw", { @@ -201,7 +212,7 @@ test_that("ppc_loo_pit functions work when pit specified instead of y, yrep, and expect_gg(ppc_loo_pit_ecdf(pit = rep(pits, 4))) expect_message( p1 <- ppc_loo_pit_ecdf(y = y, yrep = yrep, lw = lw, pit = rep(pits, 4)), - "'pit' specified so ignoring 'y','yrep','lw' if specified" + "As 'pit' specified; ignoring: y, yrep, lw." ) expect_message( p2 <- ppc_loo_pit_ecdf(pit = rep(pits, 4)) @@ -384,8 +395,7 @@ test_that("ppc_loo_pit_ecdf with method correlated renders different tests corre p_cor_pot <- ppc_loo_pit_ecdf( pit = pit, - method = "correlated", - test = "POT" + method = "correlated" ) vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (correlated pot)", p_cor_pot) @@ -410,8 +420,7 @@ test_that("ppc_loo_pit_ecdf with plot_diff=TRUE and method correlated renders di p_cor_pot <- ppc_loo_pit_ecdf( pit = pit, - method = "correlated", - test = "POT", + method = "correlated", plot_diff = TRUE ) vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (diff, correlated pot)", p_cor_pot) @@ -439,24 +448,21 @@ test_that("ppc_loo_pit_ecdf renders different linewidths and colors correctly", p_cor_lw1 <- ppc_loo_pit_ecdf( pit = pit, - method = "correlated", - test = "POT", + method = "correlated", linewidth = 1. ) vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (linewidth = 1)", p_cor_lw1) p_cor_lw2 <- ppc_loo_pit_ecdf( pit = pit, - method = "correlated", - test = "POT", + method = "correlated", linewidth = 2. ) vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (linewidth = 2)", p_cor_lw2) p_cor_col <- ppc_loo_pit_ecdf( pit = pit, - method = "correlated", - test = "POT", + method = "correlated", color = c(ecdf = "darkblue", highlight = "red") ) vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (color change)", p_cor_col) From e4ad57fdc8ab42831b77f5e8292b86bfcf222966 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Tue, 24 Feb 2026 11:23:20 +0200 Subject: [PATCH 039/120] update documentation for gamma arg in ppc_loo_pit_ecdf --- man/PPC-loo.Rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/PPC-loo.Rd b/man/PPC-loo.Rd index 5337d4d2..aff3a8cc 100644 --- a/man/PPC-loo.Rd +++ b/man/PPC-loo.Rd @@ -219,7 +219,7 @@ Defaults to \code{"POT"}.} \item{gamma}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, tolerance threshold controlling how strongly suspicious points are flagged. Larger -values highlight only the most influential points. If \code{NULL}, automatically +values (gamma > 0) emphasizes points with larger deviations. If \code{NULL}, automatically determined based on p-value.} \item{color}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, a vector From 0b5d109ff33afec237862682a7f8f9d01a1d8cda Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Tue, 24 Feb 2026 11:34:23 +0200 Subject: [PATCH 040/120] use dot prefix for internal functions --- R/helpers-ppc.R | 12 ++++++------ R/ppc-loo.R | 22 +++++++++++----------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index 31c50ae3..d5272641 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -608,7 +608,7 @@ ypred_label <- function() expression(italic(y)[pred]) #' @param x Numeric vector of Cauchy-transformed PIT values. #' @return Numeric vector of Shapley values with the same length as `x`. #' @noRd -compute_shapley_values <- function(x) { +.compute_shapley_values <- function(x) { n <- length(x) if (n == 0) { return(numeric(0)) @@ -641,7 +641,7 @@ compute_shapley_values <- function(x) { #' @param x Numeric vector of PIT values in `[0, 1]`. #' @return Numeric vector of p-values. #' @noRd -piet_test <- function(x) { +.piet_test <- function(x) { cdf_exp <- pexp(-log(x), rate = 1) # same as 1-x but numerically more stable p_values <- 2 * pmin(cdf_exp, 1 - cdf_exp) @@ -659,7 +659,7 @@ piet_test <- function(x) { #' @param x Numeric vector of PIT values in `[0, 1]`. #' @return Numeric vector of p-values. #' @noRd -pot_test <- function(x) { +.pot_test <- function(x) { n <- length(x) # keep NA values instead of silent recycling via sort() # TODO: Can PIT values be NAN at this point? @@ -679,7 +679,7 @@ pot_test <- function(x) { #' @param x Numeric vector of PIT values in `[0, 1]`. #' @return Numeric vector of p-values. #' @noRd -prit_test <- function(x) { +.prit_test <- function(x) { n <- length(x) scaled_ecdf <- n * ecdf(x)(x) probs1 <- pbinom(scaled_ecdf - 1, n, x) @@ -700,7 +700,7 @@ prit_test <- function(x) { #' included. #' @return p-value of the Cauchy combination method. #' @noRd -cauchy_combination_test <- function(x, truncate = NULL) { +.cauchy_combination_test <- function(x, truncate = NULL) { if (truncate) { idx <- which(x < 0.5) 1 - pcauchy(mean(-qcauchy(x[idx]))) @@ -716,6 +716,6 @@ cauchy_combination_test <- function(x, truncate = NULL) { #' @param x Numeric vector of PIT values in `[0, 1]`. #' @return Numeric vector of Cauchy-transformed values. #' @noRd -compute_cauchy <- function(x) { +.compute_cauchy <- function(x) { tan((0.5 - x) * pi) } \ No newline at end of file diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 379999e4..1d42d10b 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -523,23 +523,23 @@ ppc_loo_pit_ecdf <- function(y, n_obs <- length(pit) unit_interval <- seq(0, 1, length.out = K) - ecdf_pit_fn <- ecdf(pit) + .ecdf_pit_fn <- ecdf(pit) # Correlated method -------------------------------------------------- if (method == "correlated") { # Compute test p-value and Cauchy-transformed values if (test == "POT") { - std_cauchy_values <- compute_cauchy(pot_test(sort(pit))) - p_value_CCT <- cauchy_combination_test(pot_test(pit), truncate = FALSE) + std_cauchy_values <- .compute_cauchy(.pot_test(sort(pit))) + p_value_CCT <- .cauchy_combination_test(.pot_test(pit), truncate = FALSE) } else if (test == "PIET") { - std_cauchy_values <- compute_cauchy(piet_test(sort(pit))) - p_value_CCT <- cauchy_combination_test(piet_test(pit), truncate = FALSE) + std_cauchy_values <- .compute_cauchy(.piet_test(sort(pit))) + p_value_CCT <- .cauchy_combination_test(.piet_test(pit), truncate = FALSE) } else { # PRIT - std_cauchy_values <- compute_cauchy(prit_test(sort(pit))) - p_value_CCT <- cauchy_combination_test(prit_test(pit), truncate = TRUE) + std_cauchy_values <- .compute_cauchy(.prit_test(sort(pit))) + p_value_CCT <- .cauchy_combination_test(.prit_test(pit), truncate = TRUE) } - pointwise_contribution <- compute_shapley_values(std_cauchy_values) + pointwise_contribution <- .compute_shapley_values(std_cauchy_values) if (gamma < 0 || gamma > max(pointwise_contribution)) { stop(sprintf( @@ -552,13 +552,13 @@ ppc_loo_pit_ecdf <- function(y, # Evaluate at 0-1 interval b´values df_main <- tibble::tibble( x = x_axis_combined, - ecdf_pit = ecdf_pit_fn(x_axis_combined) - plot_diff * x_axis_combined + ecdf_pit = .ecdf_pit_fn(x_axis_combined) - plot_diff * x_axis_combined ) # Evaluate at pit values (used for highlighing) df_pit <- tibble::tibble( pit = pit, - ecdf_pit = ecdf_pit_fn(pit) - plot_diff * pit + ecdf_pit = .ecdf_pit_fn(pit) - plot_diff * pit ) df_pit <- df_pit[order(df_pit$pit), ] @@ -648,7 +648,7 @@ ppc_loo_pit_ecdf <- function(y, ) lims <- ecdf_intervals(gamma = gamma_indep, N = n_obs, K = K) - ecdf_eval <- ecdf_pit_fn(unit_interval) - plot_diff * unit_interval + ecdf_eval <- .ecdf_pit_fn(unit_interval) - plot_diff * unit_interval # Precompute division by n_obs n_obs_inv <- 1 / n_obs From 765d7462a68e99d21196131f5e819e2bccc34c9e Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Tue, 24 Feb 2026 12:22:27 +0200 Subject: [PATCH 041/120] fix changed variable names in test file --- tests/testthat/test-helpers-ppc.R | 58 ++++++++++++------------------- 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/tests/testthat/test-helpers-ppc.R b/tests/testthat/test-helpers-ppc.R index ae0b4eef..0f34d0ce 100644 --- a/tests/testthat/test-helpers-ppc.R +++ b/tests/testthat/test-helpers-ppc.R @@ -131,14 +131,14 @@ test_that("piet_test computes correct p-values", { # Equivalent to 2 * min(1-x, x) expected <- c(0.2, 0.5, 1.0, 0.5, 0.2) - expect_equal(piet_test(x), expected, tolerance = 1e-7) + expect_equal(.piet_test(x), expected, tolerance = 1e-7) }) test_that("piet_test handles boundary values of 0 and 1", { x <- c(0, 1) expected <- c(0, 0) - expect_equal(piet_test(x), expected) + expect_equal(.piet_test(x), expected) }) test_that("piet_test handles extreme values stably", { @@ -147,13 +147,13 @@ test_that("piet_test handles extreme values stably", { expected <- c(2e-17, 2e-17) # Tolerance needs to be adjusted for very small numbers - expect_equal(piet_test(x), expected, tolerance = 1e-16) + expect_equal(.piet_test(x), expected, tolerance = 1e-16) }) test_that("piet_test handles NA, NaN, and empty inputs correctly", { # NA and NaN propagation x_na <- c(0.5, NA, NaN) - res_na <- piet_test(x_na) + res_na <- .piet_test(x_na) expect_equal(res_na[1], 1.0) expect_true(is.na(res_na[2])) @@ -170,14 +170,14 @@ test_that("pot_test calculates correct p-values", { x <- c(0.8, 0.2) expected <- c(0.72, 0.72) - expect_equal(pot_test(x), expected) + expect_equal(.pot_test(x), expected) }) test_that("pot_test handles boundary values correctly", { x <- c(0, 1) expected <- c(0, 0) - expect_equal(pot_test(x), expected) + expect_equal(.pot_test(x), expected) }) test_that("pot_test bounds p-values between 0 and 1 for extreme out-of-bounds inputs", { @@ -185,7 +185,7 @@ test_that("pot_test bounds p-values between 0 and 1 for extreme out-of-bounds in x <- c(-0.5, 1.5) expected <- c(0, 0) - expect_equal(pot_test(x), expected) + expect_equal(.pot_test(x), expected) }) test_that("pot_test handles NAs", { @@ -193,7 +193,7 @@ test_that("pot_test handles NAs", { # Beta(2, 1) at 0.5 = 0.25 -> 2 * min(0.25, 0.75) = 0.5 expected <- c(0.5, NA) - expect_equal(pot_test(x_na), expected) + expect_equal(.pot_test(x_na), expected) }) test_that("prit_test computes correct p-values", { @@ -204,14 +204,14 @@ test_that("prit_test computes correct p-values", { # p_val = 2 * min(1 - 0.75, 1.00) = 2 * 0.25 = 0.5 x <- c(0.5, 0.5) - expect_equal(prit_test(x), c(0.5, 0.5)) + expect_equal(.prit_test(x), c(0.5, 0.5)) }) # Test for computation of Shapley values ------------------------------------- test_that("compute_shapley_values handles empty vector and single element", { - result_empty <- compute_shapley_values(numeric(0)) - result_single <- compute_shapley_values(5) + result_empty <- .compute_shapley_values(numeric(0)) + result_single <- .compute_shapley_values(5) expect_equal(result_empty, numeric(0)) expect_equal(length(result_empty), 0) @@ -221,7 +221,7 @@ test_that("compute_shapley_values handles empty vector and single element", { test_that("compute_shapley_values for simple case", { x <- c(1, 2) - result <- compute_shapley_values(x) + result <- .compute_shapley_values(x) # Manual calculation for n=2: # harmonic_number = 1 + 1/2 = 1.5 @@ -237,7 +237,7 @@ test_that("compute_shapley_values for simple case", { test_that("compute_shapley_values handles mixed input values", { x <- c(-0.2, 0, 2, 3.1, 4.2) - result <- compute_shapley_values(x) + result <- .compute_shapley_values(x) expect_equal(length(result), 5) expect_true(all(is.finite(result))) }) @@ -248,7 +248,7 @@ test_that("cauchy_combination_test handles truncate = FALSE", { # result = 1 - pcauchy(avg) x <- c(0.1, 0.2, 0.3) - result <- cauchy_combination_test(x, truncate = FALSE) + result <- .cauchy_combination_test(x, truncate = FALSE) expected <- 1 - pcauchy(mean(-qcauchy(x))) expect_equal(result, expected, tolerance = 1e-10) @@ -261,7 +261,7 @@ test_that("cauchy_combination_test handles truncate = TRUE", { # result = 1 - pcauchy(avg) x <- c(0.1, 0.2, 0.3, 0.4, 0.7, 0.8) - result <- cauchy_combination_test(x, truncate = TRUE) + result <- .cauchy_combination_test(x, truncate = TRUE) expected <- 1 - pcauchy(mean(-qcauchy(c(0.1, 0.2, 0.3, 0.4)))) expect_equal(result, expected, tolerance = 1e-10) @@ -273,37 +273,23 @@ test_that("cauchy_combination_test handles boundary values", { # x = 0: -qdf(0) = Inf and cdf(Inf) = 1 -> 1 - 1 = 0 # x = 1: -qdf(1) = -Inf and cdf(-Inf) = 0 -> 1 - 0 = 1 - expect_equal(cauchy_combination_test(0, truncate = FALSE), 0) - expect_equal(cauchy_combination_test(1, truncate = FALSE), 1) - expect_true(is.nan(cauchy_combination_test(c(0, 1), truncate = FALSE))) + expect_equal(.cauchy_combination_test(0, truncate = FALSE), 0) + expect_equal(.cauchy_combination_test(1, truncate = FALSE), 1) + expect_true(is.nan(.cauchy_combination_test(c(0, 1), truncate = FALSE))) # TODO: if 1 included in vector, CCT will always evaluate to 0 # as the mean evaluates to Inf and 1 - cdf(Inf) = 1 - 1 = 0 - expect_equal(cauchy_combination_test(c(0, 0.3, 0.4, 1), truncate = TRUE), 0) + expect_equal(.cauchy_combination_test(c(0, 0.3, 0.4, 1), truncate = TRUE), 0) }) # Test for compute_cauchy ----------------------------------------------------- test_that("compute_cauchy computes correct transformations", { # For x = 0.5: tan((0.5 - 0.5) * pi) = tan(0) = 0 - expect_equal(compute_cauchy(0.5), 0, tolerance = 1e-10) + expect_equal(.compute_cauchy(0.5), 0, tolerance = 1e-10) # For x = 0.25: tan((0.5 - 0.25) * pi) = tan(0.25 * pi) = 1 - expect_equal(compute_cauchy(0.25), 1, tolerance = 1e-10) + expect_equal(.compute_cauchy(0.25), 1, tolerance = 1e-10) # For x = 0.75: tan((0.5 - 0.75) * pi) = tan(-0.25 * pi) = -1 - expect_equal(compute_cauchy(0.75), -1, tolerance = 1e-10) -}) - -skip("evaluates currently to FALSE") -test_that("compute_cauchy handles boundary values", { - # For x = 0: tan((0.5 - 0) * pi) = tan(π/2) = Inf - result_0 <- compute_cauchy(0) - # working alternative computation: result_0 = -qcauchy(0) - expect_true(is.infinite(result_0)) - expect_true(result_0 > 0) - - # For x = 1: tan((0.5 - 1) * pi) = tan(-π/2) = -Inf - result_1 <- compute_cauchy(1) - expect_true(is.infinite(result_1)) - expect_true(result_1 < 0) + expect_equal(.compute_cauchy(0.75), -1, tolerance = 1e-10) }) \ No newline at end of file From eac060d9285a2f9c28c2b0d5a9172df9f2c489cd Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Wed, 25 Feb 2026 07:01:01 +0200 Subject: [PATCH 042/120] add truncate=TRUE in pot_test --- R/ppc-loo.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 1d42d10b..ebe0b408 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -530,7 +530,7 @@ ppc_loo_pit_ecdf <- function(y, # Compute test p-value and Cauchy-transformed values if (test == "POT") { std_cauchy_values <- .compute_cauchy(.pot_test(sort(pit))) - p_value_CCT <- .cauchy_combination_test(.pot_test(pit), truncate = FALSE) + p_value_CCT <- .cauchy_combination_test(.pot_test(pit), truncate = TRUE) } else if (test == "PIET") { std_cauchy_values <- .compute_cauchy(.piet_test(sort(pit))) p_value_CCT <- .cauchy_combination_test(.piet_test(pit), truncate = FALSE) From 06cdc7b78204fc3a2f0e043af4456b48043975ee Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Wed, 25 Feb 2026 11:08:18 +0200 Subject: [PATCH 043/120] add p-value information in title of ppc_loo_pit_ecdf --- R/ppc-loo.R | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index ebe0b408..7856c158 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -561,7 +561,7 @@ ppc_loo_pit_ecdf <- function(y, ecdf_pit = .ecdf_pit_fn(pit) - plot_diff * pit ) df_pit <- df_pit[order(df_pit$pit), ] - + # Plot ECDF p <- ggplot() + geom_step( @@ -629,11 +629,12 @@ ppc_loo_pit_ecdf <- function(y, } } } - + # Apply bayesplot theme and styling p <- p + yaxis_ticks(FALSE) + scale_color_ppc() + + labs(title = sprintf("Uniformity p-value = %.3f", p_value_CCT)) + bayesplot::theme_default(base_family = "sans", base_size = 16) return(p) From 2b760241cb345a8f61a9bd17d563d8dc3eb62a0e Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Wed, 25 Feb 2026 11:09:03 +0200 Subject: [PATCH 044/120] add check for length of p-values for truncated CCT --- R/helpers-ppc.R | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index d5272641..ee9fee6a 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -703,6 +703,10 @@ ypred_label <- function() expression(italic(y)[pred]) .cauchy_combination_test <- function(x, truncate = NULL) { if (truncate) { idx <- which(x < 0.5) + if (length(idx) == 0) { + stop("Cannot compute truncated Cauchy combination test. ", + "No p-values below 0.5 found.") + } 1 - pcauchy(mean(-qcauchy(x[idx]))) } else { 1 - pcauchy(mean(-qcauchy(x))) From 7db2b65dddb693714b278987823dfbb863b1e530 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Wed, 25 Feb 2026 11:10:23 +0200 Subject: [PATCH 045/120] adjust ppc_loo_pit_ecdf test for single value --- tests/testthat/test-ppc-loo.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-ppc-loo.R b/tests/testthat/test-ppc-loo.R index 5ca60a8c..d749f066 100644 --- a/tests/testthat/test-ppc-loo.R +++ b/tests/testthat/test-ppc-loo.R @@ -191,7 +191,8 @@ test_that("ppc_loo_pit_ecdf correlated method handles edge cases", { # Test with single value (edge case) single_pit <- 0.5 - expect_gg(p4 <- ppc_loo_pit_ecdf(pit = single_pit, method = "correlated")) + expect_error(ppc_loo_pit_ecdf(pit = single_pit, method = "correlated")) + expect_gg(p5 <- ppc_loo_pit_ecdf(pit = single_pit, method = "correlated", test = "PIET")) }) test_that("ppc_loo_pit functions work when pit specified instead of y, yrep, and lw", { From 494675329690888b5ccac7e5f028c5c21e606e97 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Wed, 25 Feb 2026 11:10:48 +0200 Subject: [PATCH 046/120] update refernce svgs for visual regression test (incl. title) --- .../ppc-loo/ppc-loo-pit-ecdf-color-change.svg | 2 +- .../ppc-loo-pit-ecdf-correlated-piet.svg | 2 +- .../ppc-loo-pit-ecdf-correlated-pot.svg | 2 +- .../ppc-loo-pit-ecdf-correlated-prit.svg | 2 +- .../ppc-loo-pit-ecdf-diff-correlated-piet.svg | 2 +- .../ppc-loo-pit-ecdf-diff-correlated-pot.svg | 2 +- .../ppc-loo-pit-ecdf-diff-correlated-prit.svg | 2 +- .../ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg | 2 +- .../ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg | 2 +- tests/vdiffr.Rout.fail | 189 ++++++++++++++++++ 10 files changed, 198 insertions(+), 9 deletions(-) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg index 01fd0d57..ef0622f4 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg @@ -57,6 +57,6 @@ 1.00 LOO PIT ECDF -ppc_loo_pit_ecdf (color change) +Uniformity p-value = 0.000 diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg index d54510e2..70debc21 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg @@ -53,6 +53,6 @@ 1.00 LOO PIT ECDF -ppc_loo_pit_ecdf (correlated piet) +Uniformity p-value = 0.188 diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg index 5f1c535c..c7306dab 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg @@ -57,6 +57,6 @@ 1.00 LOO PIT ECDF -ppc_loo_pit_ecdf (correlated pot) +Uniformity p-value = 0.000 diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg index caf47149..448436cf 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg @@ -59,6 +59,6 @@ 1.00 LOO PIT ECDF -ppc_loo_pit_ecdf (correlated prit) +Uniformity p-value = 0.001 diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg index 7afc9be5..728ed0a0 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg @@ -51,6 +51,6 @@ 1.00 LOO PIT ECDF difference -ppc_loo_pit_ecdf (diff, correlated piet) +Uniformity p-value = 0.188 diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg index 05181c21..16585ff8 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg @@ -55,6 +55,6 @@ 1.00 LOO PIT ECDF difference -ppc_loo_pit_ecdf (diff, correlated pot) +Uniformity p-value = 0.000 diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg index 325b1f22..41f521b3 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg @@ -57,6 +57,6 @@ 1.00 LOO PIT ECDF difference -ppc_loo_pit_ecdf (diff, correlated prit) +Uniformity p-value = 0.001 diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg index 379f73f7..1801aec9 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg @@ -57,6 +57,6 @@ 1.00 LOO PIT ECDF -ppc_loo_pit_ecdf (linewidth = 1) +Uniformity p-value = 0.000 diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg index 91a8dea1..c58ee024 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg @@ -57,6 +57,6 @@ 1.00 LOO PIT ECDF -ppc_loo_pit_ecdf (linewidth = 2) +Uniformity p-value = 0.000 diff --git a/tests/vdiffr.Rout.fail b/tests/vdiffr.Rout.fail index bef52f75..a83999fc 100644 --- a/tests/vdiffr.Rout.fail +++ b/tests/vdiffr.Rout.fail @@ -15889,3 +15889,192 @@ Failed doppelganger: ppc-loo-pit-ecdf-ecdf-difference (C:\Users\flore\Documents\ + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) + +< before +> after +@@ 58,5 / 58,5 @@ + LOO PIT + + ECDF +< ppc_loo_pit_ecdf (correlated +: pot) +> Uniformity p-value = 0.000 + + + + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-prit (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg) + +< before +> after +@@ 60,5 / 60,5 @@ + LOO PIT + + ECDF +< ppc_loo_pit_ecdf (correlated +: prit) +> Uniformity p-value = 0.001 + + + + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-piet (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg) + +< before +> after +@@ 54,5 / 54,5 @@ + LOO PIT + + ECDF +< ppc_loo_pit_ecdf (correlated +: piet) +> Uniformity p-value = 0.188 + + + + +Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-pot (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg) + +< before +> after +@@ 56,5 / 56,5 @@ + LOO PIT + + ECDF difference +< ppc_loo_pit_ecdf (diff, corre +: lated pot) +> Uniformity p-value = 0.000 + + + + +Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-prit (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg) + +< before +> after +@@ 58,5 / 58,5 @@ + LOO PIT + + ECDF difference +< ppc_loo_pit_ecdf (diff, corre +: lated prit) +> Uniformity p-value = 0.001 + + + + +Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-piet (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg) + +< before +> after +@@ 52,5 / 52,5 @@ + LOO PIT + + ECDF difference +< ppc_loo_pit_ecdf (diff, corre +: lated piet) +> Uniformity p-value = 0.188 + + + + +Failed doppelganger: ppc-loo-pit-ecdf-linewidth-1 (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg) + +< before +> after +@@ 58,5 / 58,5 @@ + LOO PIT + + ECDF +< ppc_loo_pit_ecdf (linewidth = +: 1) +> Uniformity p-value = 0.000 + + + + +Failed doppelganger: ppc-loo-pit-ecdf-linewidth-2 (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg) + +< before +> after +@@ 58,5 / 58,5 @@ + LOO PIT + + ECDF +< ppc_loo_pit_ecdf (linewidth = +: 2) +> Uniformity p-value = 0.000 + + + + +Failed doppelganger: ppc-loo-pit-ecdf-color-change (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg) + +< before +> after +@@ 58,5 / 58,5 @@ + LOO PIT + + ECDF +< ppc_loo_pit_ecdf (color chang +: e) +> Uniformity p-value = 0.000 + + + From ccfbc1a303cb4044d63a5e040f43ff93a7da4e14 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 2 Mar 2026 11:18:19 +0200 Subject: [PATCH 047/120] change highlighting color to red --- R/ppc-loo.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 7856c158..94bba187 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -510,7 +510,7 @@ ppc_loo_pit_ecdf <- function(y, alpha <- 1 - prob gamma <- gamma %||% 0 linewidth <- linewidth %||% 0.3 - color <- color %||% c(ecdf = "gray60", highlight = "gray30") + color <- color %||% c(ecdf = "black", highlight = "red") }, "independent" = { From c00ad959fc803fb9f2ebf7b198aa2bd19b449058 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 2 Mar 2026 11:23:16 +0200 Subject: [PATCH 048/120] add knitting output to gitignore --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index 695e6e77..8e789a32 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,9 @@ release-prep.R # vscode/positron/etc settings .vscode/* + +# knitting of vignettes +*_cache +*_files +vignettes/*.quarto +vignettes/*.html \ No newline at end of file From 90a13838329c6c01ae014dc30d42f455aced4815 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Mon, 2 Mar 2026 11:23:53 +0200 Subject: [PATCH 049/120] add initial draft for ppc-loo-pit vignette --- vignettes/ppc_loo_pit.Rmd | 236 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 vignettes/ppc_loo_pit.Rmd diff --git a/vignettes/ppc_loo_pit.Rmd b/vignettes/ppc_loo_pit.Rmd new file mode 100644 index 00000000..73d00e53 --- /dev/null +++ b/vignettes/ppc_loo_pit.Rmd @@ -0,0 +1,236 @@ +--- +title: "Model checking with (LOO-)PIT using bayesplot" +author: "TODO" +date: "`r Sys.Date()`" +output: + rmarkdown::html_vignette: + toc: true + toc_depth: 3 +params: + EVAL: true + MESSAGE: false + WARNING: false +vignette: > + %\VignetteIndexEntry{Model checking with (LOO-)PIT using bayesplot} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, child="children/SETTINGS-knitr.txt"} +``` +```{r setup-width, include=FALSE} +# Override global width setting for this vignette +knitr::opts_chunk$set(out.width = "100%") +``` +```{r pkgs, include=FALSE} +library("ggplot2") +library("rstanarm") +library("brms") +library("tinytable") +library("posterior") +library("patchwork") +devtools::load_all() +bayesplot::bayesplot_theme_set() +set.seed(1840) +``` + +## Conceptual Introduction +One approach to check a model's (in)adequacy involves comparing the model's predictive simultations with the actual observed data. In the following, we focus on predictive check techniques that lead to the examination of the observed data with respect to the collection of univariate (or pointwise) conditional distributions arising from this joint distribution, that is, pointwise predictive checks. + +### Using PIT for model checking +Pointwise checks utilize the **probability integral transformation (PIT)** to recast model evaluation into a problem of testing for uniformity: PIT corresponds to the model's predictive univariate cumulative distributions function (CDF) evaluated given the observation, resulting in values that, for a well-calibrated model, should be near uniformly distributed between 0 and 1. + +**Leave-one-out (LOO) cross-validation** approach termed LOO-PIT is an approach that iteratively holds out each data point, conditioning on the remaining data, and compares the corresponding LOO predictive distribution to the heldout point, by testing for departures from uniformity of the associated LOO-PIT values. + +The LOO folds—each consisting of all but one observation—overlap, meaning that the posterior distributions used to compute the LOO predictive densities are conditioned on nearly but not exactly identical data sets. As a result, the posterior draws across folds are correlated, which in turn induces dependence among the LOO-PIT values. + +## Implementation in `bayesplot` +A graphical uniformity test which assumes independence of PIT values has been developed by [Säilynoja et al. (2022)](#saeilynoja2022) and provides simultaneous confidence bands for the whole empirical cumulative distribution function (ECDF) of the PIT values. However, the dependency in LOO-PIT values reduces the variability of ECDF compared to independent uniform variables, and the confidence bands based on the independence assumption are too wide, reducing the test’s ability to reveal model miscalibration. + +This visual test developed by [Säilynoja et al. (2022)](#saeilynoja2022) is implemented in `bayesplot` through the function `ppc_pit_ecdf` and for the LOO-approach through the function `ppc_pit_loo_ecdf`. In both cases the uniformity test assumes independence. + +From `bayesplot (x.x.x)` onwards an updated `ppc_pit_loo_ecdf` function is provided that provides an alternative method for computing the uniformity test that is dependence aware [(Tesso & Vehtari, 2026)](#tesso2016). + +## Practical Example: Sleep Study +[Belenky et al., 2003](#belenky2003) collected data on the effect of chronic sleep restriction. We use a subset of data in the R package `lme4` [(Bates et al., 2015)](#bates2015). The data contains average reaction times (in milliseconds) for 18 subjects with sleep restricted to 3 hours per night for 7 consecutive nights (days 0 and 1 were adaptation and training and removed from this analysis). + +```{r sleep-data} +data(sleepstudy, package = "lme4") + +sleepstudy2 <- sleepstudy |> + dplyr::filter(Days >= 2) +``` + +The compared models are a linear model, a linear model with varying intercept for each subject, and a linear model with varying intercept and slope for each subject. All models use a normal data model. The models were fitted using `brms` [(Bürkner, 2017)](#buerkner2017), and the default `brms` priors; prior for the coefficient for Days is uniform, the prior for the varying intercept is normal with unknown scale having a half-normal prior, and the prior for the varying intercept and slope is bivariate normal with unknown scales having half-normal priors and correlation having LKJ prior [(Lewandowski, Kurowicka, & Joe, 2009)](#lewandowski2009). + +Using the `brms` formula notation, the compared models are + +$$ +\begin{align*} + \mathrm{M}_1: \quad & \mathrm{Reaction} \sim \mathrm{Days} \\ + \mathrm{M}_2: \quad & \mathrm{Reaction} \sim \mathrm{Days} + (1\,\mid\,\mathrm{Subject}) \\ + \mathrm{M}_3: \quad & \mathrm{Reaction} \sim \mathrm{Days} + (\mathrm{Days}\,\mid\, \mathrm{Subject}). +\end{align*} +$$ + +Based on the study design, $\mathrm{M}_3$ is the appropriate model for the analysis, but comparing models is useful for assessing how much information the data has about the varying intercepts and slopes. For a few LOO-folds with high Pareto-$\hat{k}$ diagnostic value ($>0.7$, [Vehtari et al., 2024](#vehtari2024)) we re-ran MCMC (with `reloo=TRUE` in `brms`). We use `add_criterion()` to store the loo object inside the brmsfit objects. + +```{r model-fitting, cache=TRUE, echo=FALSE} +M_1 <- brms::brm(Reaction ~ Days, + data = sleepstudy2, + family = gaussian(), + refresh = 0) |> + brms::add_criterion(criterion = "loo", save_psis = TRUE, reloo = TRUE) +M_2 <- brms::brm(Reaction ~ Days + (1 | Subject), + data = sleepstudy2, + family = gaussian(), + refresh = 0) |> + brms::add_criterion(criterion = "loo", save_psis = TRUE, reloo = TRUE) +M_3 <- brms::brm(Reaction ~ Days + (Days | Subject), + data = sleepstudy2, + family = gaussian(), + refresh = 0) |> + brms::add_criterion(criterion = "loo", save_psis = TRUE, reloo = TRUE) +``` + +We compare the models $\mathrm{M}_1, \mathrm{M}_2,\mathrm{M}_3,\mathrm{M}_4$ + +```{r model-comparison} +brms::loo_compare(M_1, M_2, M_3) |> + as.data.frame() |> + tibble::rownames_to_column(var = "model") |> + dplyr::select(model, elpd_diff, se_diff) |> + tinytable::tt() |> + tinytable::format_tt(j = 2:3, digits = 5) +``` + +Model $\mathrm{M}_3$ is estimated to have better predictive performance. Model-checking reveals that two observations are clear outliers with respect to these models, making the normal approximation likely to be poorly calibrated. +We see the outliers, for example, by comparing LOO predictive intervals to observations. + +```{r pp-check, out.width="100%", warning=FALSE, message=FALSE} +p1 <- pp_check(M_2, type = "loo_intervals") + + ggplot2::labs(y = "Reaction time (ms)", subtitle = "M2") + + bayesplot::theme_default(base_family = "sans") + +p2 <- pp_check(M_3, type = "loo_intervals") + + ggplot2::labs(subtitle = "M3") + + bayesplot::theme_default(base_family = "sans") + +p1 + p2 + plot_layout(ncol = 2, guides = "collect") & theme_bw(base_size = 6) +``` + +We see miscalibration also with LOO-PIT plots + +```{r calibration-plots-helper} +plot_ppc <- function(qp, method = "correlated", diff, prob = 0.95) { + + p1 <- ppc_loo_pit_ecdf( + pit = qp, method = method, test = "PRIT", plot_diff = diff, + prob = prob + ) + + labs(subtitle = "PRIT Test") + p2 <- ppc_loo_pit_ecdf( + pit = qp, method = method, test = "POT", plot_diff = diff, + prob = prob + ) + + labs(subtitle = "POT Test") + p3 <- ppc_loo_pit_ecdf( + pit = qp, method = method, test = "PIET", plot_diff = diff, + prob = prob + ) + + labs(subtitle = "PIET Test") + + p1 + p2 + p3 + + plot_layout(ncol = 3, guides = "collect") & theme_bw(base_size = 6) +} +``` + +```{r calibration-plots-1} +qp <- posterior::pit(posterior_predict(M_2), sleepstudy2$Reaction) + +plot_ppc(qp, method = "correlated", diff = FALSE) +plot_ppc(qp, method = "independent", diff = FALSE) +``` + +```{r calibration-plots-2} +qp <- posterior::pit( + posterior_predict(M_2), sleepstudy2$Reaction, + weights(brms::loo(M_2), log = TRUE), log = TRUE + ) + +plot_ppc(qp, diff = FALSE) +plot_ppc(qp, diff = TRUE) +``` + +```{r calibration-plots-3} +qp <- posterior::pit( + posterior_predict(M_3), sleepstudy2$Reaction, + weights(brms::loo(M_3), log = TRUE), log = TRUE + ) + +plot_ppc(qp, diff = FALSE) +plot_ppc(qp, diff = TRUE) +``` + +## Independent vs. dependence-aware uniformity tests + +```{r} +qp <- posterior::pit( + posterior_predict(M_2), sleepstudy2$Reaction, + weights(brms::loo(M_2), log = TRUE), log = TRUE + ) + +p1 <- ppc_loo_pit_ecdf( + pit = qp, method = "independent", plot_diff = FALSE) + + labs(subtitle = "Independent uniformity test") +p2 <- ppc_loo_pit_ecdf( + pit = qp, method = "correlated", plot_diff = FALSE) + + labs(subtitle = "Dependence-aware uniformity test") + +p1 + p2 + +plot_layout(ncol = 2, guides = "collect") & theme_bw(base_size = 6) +``` + +```{r} +qp <- posterior::pit( + posterior_predict(M_2), sleepstudy2$Reaction, + weights(brms::loo(M_2), log = TRUE), log = TRUE + ) + +p1 <- ppc_loo_pit_ecdf( + pit = qp, method = "independent", plot_diff = TRUE) + + labs(subtitle = "Säilynoja et al. (2022); independence") +p2 <- ppc_loo_pit_ecdf( + pit = qp, method = "correlated", plot_diff = TRUE) + + labs(subtitle = "Tesso & Vehtari (2026); dependence-aware") + +p1 + p2 + + plot_layout(ncol = 2, guides = "collect") & theme_bw(base_size = 6) +``` + +```{r} +qp <- posterior::pit( + posterior_predict(M_2), sleepstudy2$Reaction, + weights(brms::loo(M_2), log = TRUE), log = TRUE + ) + +ppc_loo_pit_ecdf(pit = qp, method = "correlated", plot_diff = TRUE) + + ggplot2::labs(subtitle = "POT test") + + ggplot2::ylim(c(-0.2, 0.2)) + + theme_bw(base_size = 6) +``` + +## References + +Bates, D., Maechler, M., Bolker, B., Walker, S., Christensen, R. H. B., Singmann, H., ... & Bolker, M. B. (2015). Package ‘lme4’. Convergence, 12(1), 2. + +Belenky, G., Wesensten, N. J., Thorne, D. R., Thomas, M. L., Sing, H. C., Redmond, D. P., ... & Balkin, T. J. (2003). Patterns of performance degradation and restoration during sleep restriction and subsequent recovery: A sleep dose‐response study. Journal of sleep research, 12(1), 1-12. + +Buerkner, P. (2017). brms: Bayesian Regression Models using Stan. R package +version 1.7.0. https://CRAN.R-project.org/package=brms + +Lewandowski, D., Kurowicka, D., & Joe, H. (2009). Generating random correlation +matrices based on vines and extended onion method. Journal of Multivariate +Analysis, 100 (9), 1989–2001. + +Vehtari, A., Simpson, D., Gelman, A., Yao, Y., & Gabry, J. (2024). Pareto smoothed importance sampling. Journal of Machine Learning Research, 25(72), 1-58. \ No newline at end of file From d853acb6042638f6b243cd04291be9d25ab0eab6 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Mon, 2 Mar 2026 12:03:41 +0200 Subject: [PATCH 050/120] add p-value info as text instead of title to plot --- R/ppc-loo.R | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 94bba187..d1cd36dd 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -634,7 +634,13 @@ ppc_loo_pit_ecdf <- function(y, p <- p + yaxis_ticks(FALSE) + scale_color_ppc() + - labs(title = sprintf("Uniformity p-value = %.3f", p_value_CCT)) + + annotate( + "text", + x = -Inf, y = Inf, + label = sprintf("Uniformity p-value = %.3f", p_value_CCT), + hjust = -0.1, vjust = 1.5, + size = 6, color = "black" + ) + bayesplot::theme_default(base_family = "sans", base_size = 16) return(p) From b513a07f4e61b95d87d1add0390a9b8adbba8a06 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Mon, 2 Mar 2026 12:37:19 +0200 Subject: [PATCH 051/120] add automatic scaling to y-axis --- R/ppc-loo.R | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index d1cd36dd..f74d9100 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -642,6 +642,17 @@ ppc_loo_pit_ecdf <- function(y, size = 6, color = "black" ) + bayesplot::theme_default(base_family = "sans", base_size = 16) + + if (plot_diff) { + epsilon = max( + sqrt(log(2 / (1 - prob)) / (2 * length(pit))), + max(abs(df_main$ecdf_pit)) + ) + + p <- p + scale_y_continuous( + limits = c(-epsilon, epsilon) + ) + } return(p) } From 4129c0dc9d04c1b150b7bf0c9af10dbcb8ba12fe Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Mon, 2 Mar 2026 12:38:17 +0200 Subject: [PATCH 052/120] add updated snapshots for visual regression tests --- .../ppc-loo/ppc-loo-pit-ecdf-color-change.svg | 3 +- .../ppc-loo-pit-ecdf-correlated-piet.svg | 5 +- .../ppc-loo-pit-ecdf-correlated-pot.svg | 13 +- .../ppc-loo-pit-ecdf-correlated-prit.svg | 17 +- .../ppc-loo-pit-ecdf-diff-correlated-piet.svg | 25 +- .../ppc-loo-pit-ecdf-diff-correlated-pot.svg | 33 +- .../ppc-loo-pit-ecdf-diff-correlated-prit.svg | 37 +- .../ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg | 13 +- .../ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg | 13 +- .../ppc-loo/ppc-loo-pit-overlay-boundary.svg | 202 +- tests/vdiffr.Rout.fail | 41602 ++++++++++++++++ 11 files changed, 41790 insertions(+), 173 deletions(-) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg index ef0622f4..b5affffe 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg @@ -31,6 +31,7 @@ +Uniformity p-value = 0.000 @@ -57,6 +58,6 @@ 1.00 LOO PIT ECDF -Uniformity p-value = 0.000 +ppc_loo_pit_ecdf (color change) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg index 70debc21..3d3bdd11 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg @@ -25,8 +25,9 @@ - + +Uniformity p-value = 0.188 @@ -53,6 +54,6 @@ 1.00 LOO PIT ECDF -Uniformity p-value = 0.188 +ppc_loo_pit_ecdf (correlated piet) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg index c7306dab..0164d8f9 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg @@ -25,12 +25,13 @@ - + - - - - + + + + +Uniformity p-value = 0.000 @@ -57,6 +58,6 @@ 1.00 LOO PIT ECDF -Uniformity p-value = 0.000 +ppc_loo_pit_ecdf (correlated pot) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg index 448436cf..36752bbd 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg @@ -25,14 +25,15 @@ - + - - - - - - + + + + + + +Uniformity p-value = 0.001 @@ -59,6 +60,6 @@ 1.00 LOO PIT ECDF -Uniformity p-value = 0.001 +ppc_loo_pit_ecdf (correlated prit) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg index 728ed0a0..8b92725a 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg @@ -25,19 +25,22 @@ - - + + +Uniformity p-value = 0.188 --0.09 --0.06 --0.03 -0.00 - - - - +-0.10 +-0.05 +0.00 +0.05 +0.10 + + + + + @@ -51,6 +54,6 @@ 1.00 LOO PIT ECDF difference -Uniformity p-value = 0.188 +ppc_loo_pit_ecdf (diff, correlated piet) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg index 16585ff8..f8677b41 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg @@ -25,23 +25,26 @@ - - - - - - + + + + + + +Uniformity p-value = 0.000 --0.09 --0.06 --0.03 -0.00 - - - - +-0.10 +-0.05 +0.00 +0.05 +0.10 + + + + + @@ -55,6 +58,6 @@ 1.00 LOO PIT ECDF difference -Uniformity p-value = 0.000 +ppc_loo_pit_ecdf (diff, correlated pot) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg index 41f521b3..0efc9fb7 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg @@ -25,25 +25,28 @@ - - - - - - - - + + + + + + + + +Uniformity p-value = 0.001 --0.09 --0.06 --0.03 -0.00 - - - - +-0.10 +-0.05 +0.00 +0.05 +0.10 + + + + + @@ -57,6 +60,6 @@ 1.00 LOO PIT ECDF difference -Uniformity p-value = 0.001 +ppc_loo_pit_ecdf (diff, correlated prit) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg index 1801aec9..e479563b 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg @@ -25,12 +25,13 @@ - + - - - - + + + + +Uniformity p-value = 0.000 @@ -57,6 +58,6 @@ 1.00 LOO PIT ECDF -Uniformity p-value = 0.000 +ppc_loo_pit_ecdf (linewidth = 1) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg index c58ee024..12f6f327 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg @@ -25,12 +25,13 @@ - + - - - - + + + + +Uniformity p-value = 0.000 @@ -57,6 +58,6 @@ 1.00 LOO PIT ECDF -Uniformity p-value = 0.000 +ppc_loo_pit_ecdf (linewidth = 2) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.svg index 3426f2c2..07009b87 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.svg @@ -25,107 +25,107 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/vdiffr.Rout.fail b/tests/vdiffr.Rout.fail index a83999fc..59e731db 100644 --- a/tests/vdiffr.Rout.fail +++ b/tests/vdiffr.Rout.fail @@ -16078,3 +16078,41605 @@ Failed doppelganger: ppc-loo-pit-ecdf-color-change (C:\Users\flore\Documents\Git + +Failed doppelganger: ppc-loo-pit-overlay-boundary (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.svg) + +< before +> after +@@ 26,105 / 26,105 @@ + + +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +< +> + + + + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) + +< before +> after +@@ 26,10 / 26,11 @@ + + +< +> + +< +> +< +> +< +> +< +> +> Uniformity p-value = 0.000 + + +@@ 58,5 / 59,5 @@ + LOO PIT + + ECDF +< Uniformity p-value = 0.000 +> ppc_loo_pit_ecdf (correlated +: pot) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-prit (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg) + +< before +> after +@@ 26,12 / 26,13 @@ + + +< +> + +< +> +< +> +< +> +< +> +< +> +< +> +> Uniformity p-value = 0.001 + + +@@ 60,5 / 61,5 @@ + LOO PIT + + ECDF +< Uniformity p-value = 0.001 +> ppc_loo_pit_ecdf (correlated +: prit) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-piet (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg) + +< before +> after +@@ 26,6 / 26,7 @@ + + +< +> + +> Uniformity p-value = 0.188 + + +@@ 54,5 / 55,5 @@ + LOO PIT + + ECDF +< Uniformity p-value = 0.188 +> ppc_loo_pit_ecdf (correlated +: piet) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-pot (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg) + +< before +> after +@@ 26,21 / 26,24 @@ + + +< +> +< +> +< +> +< +> +< +> +< +> +> Uniformity p-value = 0.000 + + + +< -0.09 +> -0.10 +< -0.06 +> -0.05 +< -0.03 +> 0.00 +< 0.00 +> 0.05 +> 0.10 +< +> +< +> +< +> +< +> +> + + +@@ 56,5 / 59,5 @@ + LOO PIT + + ECDF difference +< Uniformity p-value = 0.000 +> ppc_loo_pit_ecdf (diff, corre +: lated pot) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-prit (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg) + +< before +> after +@@ 26,23 / 26,26 @@ + + +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +> Uniformity p-value = 0.001 + + + +< -0.09 +> -0.10 +< -0.06 +> -0.05 +< -0.03 +> 0.00 +< 0.00 +> 0.05 +> 0.10 +< +> +< +> +< +> +< +> +> + + +@@ 58,5 / 61,5 @@ + LOO PIT + + ECDF difference +< Uniformity p-value = 0.001 +> ppc_loo_pit_ecdf (diff, corre +: lated prit) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-piet (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg) + +< before +> after +@@ 26,17 / 26,20 @@ + + +< +> +< +> +> Uniformity p-value = 0.188 + + + +< -0.09 +> -0.10 +< -0.06 +> -0.05 +< -0.03 +> 0.00 +< 0.00 +> 0.05 +> 0.10 +< +> +< +> +< +> +< +> +> + + +@@ 52,5 / 55,5 @@ + LOO PIT + + ECDF difference +< Uniformity p-value = 0.188 +> ppc_loo_pit_ecdf (diff, corre +: lated piet) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-linewidth-1 (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg) + +< before +> after +@@ 26,10 / 26,11 @@ + + +< +> + +< +> +< +> +< +> +< +> +> Uniformity p-value = 0.000 + + +@@ 58,5 / 59,5 @@ + LOO PIT + + ECDF +< Uniformity p-value = 0.000 +> ppc_loo_pit_ecdf (linewidth = +: 1) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-linewidth-2 (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg) + +< before +> after +@@ 26,10 / 26,11 @@ + + +< +> + +< +> +< +> +< +> +< +> +> Uniformity p-value = 0.000 + + +@@ 58,5 / 59,5 @@ + LOO PIT + + ECDF +< Uniformity p-value = 0.000 +> ppc_loo_pit_ecdf (linewidth = +: 2) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-color-change (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg) + +< before +> after +@@ 32,4 / 32,5 @@ + + +> Uniformity p-value = 0.000 + + +@@ 58,5 / 59,5 @@ + LOO PIT + + ECDF +< Uniformity p-value = 0.000 +> ppc_loo_pit_ecdf (color chang +: e) + + + From 27359763b8a7080bfeb3ca3b5f58adbc4f72f9d6 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Mon, 2 Mar 2026 12:51:48 +0200 Subject: [PATCH 053/120] add draft vignette to gitignore --- .gitignore | 5 +- R/ppc-loo.R | 4 +- vignettes/ppc_loo_pit.Rmd | 236 -------------------------------------- 3 files changed, 5 insertions(+), 240 deletions(-) delete mode 100644 vignettes/ppc_loo_pit.Rmd diff --git a/.gitignore b/.gitignore index 8e789a32..ee6e310c 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,7 @@ release-prep.R *_cache *_files vignettes/*.quarto -vignettes/*.html \ No newline at end of file +vignettes/*.html + +# draft vignette +ppc-loo-draft.Rmd \ No newline at end of file diff --git a/R/ppc-loo.R b/R/ppc-loo.R index f74d9100..211c360b 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -649,9 +649,7 @@ ppc_loo_pit_ecdf <- function(y, max(abs(df_main$ecdf_pit)) ) - p <- p + scale_y_continuous( - limits = c(-epsilon, epsilon) - ) + p <- p + scale_y_continuous(limits = c(-epsilon, epsilon)) } return(p) diff --git a/vignettes/ppc_loo_pit.Rmd b/vignettes/ppc_loo_pit.Rmd deleted file mode 100644 index 73d00e53..00000000 --- a/vignettes/ppc_loo_pit.Rmd +++ /dev/null @@ -1,236 +0,0 @@ ---- -title: "Model checking with (LOO-)PIT using bayesplot" -author: "TODO" -date: "`r Sys.Date()`" -output: - rmarkdown::html_vignette: - toc: true - toc_depth: 3 -params: - EVAL: true - MESSAGE: false - WARNING: false -vignette: > - %\VignetteIndexEntry{Model checking with (LOO-)PIT using bayesplot} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - -```{r, child="children/SETTINGS-knitr.txt"} -``` -```{r setup-width, include=FALSE} -# Override global width setting for this vignette -knitr::opts_chunk$set(out.width = "100%") -``` -```{r pkgs, include=FALSE} -library("ggplot2") -library("rstanarm") -library("brms") -library("tinytable") -library("posterior") -library("patchwork") -devtools::load_all() -bayesplot::bayesplot_theme_set() -set.seed(1840) -``` - -## Conceptual Introduction -One approach to check a model's (in)adequacy involves comparing the model's predictive simultations with the actual observed data. In the following, we focus on predictive check techniques that lead to the examination of the observed data with respect to the collection of univariate (or pointwise) conditional distributions arising from this joint distribution, that is, pointwise predictive checks. - -### Using PIT for model checking -Pointwise checks utilize the **probability integral transformation (PIT)** to recast model evaluation into a problem of testing for uniformity: PIT corresponds to the model's predictive univariate cumulative distributions function (CDF) evaluated given the observation, resulting in values that, for a well-calibrated model, should be near uniformly distributed between 0 and 1. - -**Leave-one-out (LOO) cross-validation** approach termed LOO-PIT is an approach that iteratively holds out each data point, conditioning on the remaining data, and compares the corresponding LOO predictive distribution to the heldout point, by testing for departures from uniformity of the associated LOO-PIT values. - -The LOO folds—each consisting of all but one observation—overlap, meaning that the posterior distributions used to compute the LOO predictive densities are conditioned on nearly but not exactly identical data sets. As a result, the posterior draws across folds are correlated, which in turn induces dependence among the LOO-PIT values. - -## Implementation in `bayesplot` -A graphical uniformity test which assumes independence of PIT values has been developed by [Säilynoja et al. (2022)](#saeilynoja2022) and provides simultaneous confidence bands for the whole empirical cumulative distribution function (ECDF) of the PIT values. However, the dependency in LOO-PIT values reduces the variability of ECDF compared to independent uniform variables, and the confidence bands based on the independence assumption are too wide, reducing the test’s ability to reveal model miscalibration. - -This visual test developed by [Säilynoja et al. (2022)](#saeilynoja2022) is implemented in `bayesplot` through the function `ppc_pit_ecdf` and for the LOO-approach through the function `ppc_pit_loo_ecdf`. In both cases the uniformity test assumes independence. - -From `bayesplot (x.x.x)` onwards an updated `ppc_pit_loo_ecdf` function is provided that provides an alternative method for computing the uniformity test that is dependence aware [(Tesso & Vehtari, 2026)](#tesso2016). - -## Practical Example: Sleep Study -[Belenky et al., 2003](#belenky2003) collected data on the effect of chronic sleep restriction. We use a subset of data in the R package `lme4` [(Bates et al., 2015)](#bates2015). The data contains average reaction times (in milliseconds) for 18 subjects with sleep restricted to 3 hours per night for 7 consecutive nights (days 0 and 1 were adaptation and training and removed from this analysis). - -```{r sleep-data} -data(sleepstudy, package = "lme4") - -sleepstudy2 <- sleepstudy |> - dplyr::filter(Days >= 2) -``` - -The compared models are a linear model, a linear model with varying intercept for each subject, and a linear model with varying intercept and slope for each subject. All models use a normal data model. The models were fitted using `brms` [(Bürkner, 2017)](#buerkner2017), and the default `brms` priors; prior for the coefficient for Days is uniform, the prior for the varying intercept is normal with unknown scale having a half-normal prior, and the prior for the varying intercept and slope is bivariate normal with unknown scales having half-normal priors and correlation having LKJ prior [(Lewandowski, Kurowicka, & Joe, 2009)](#lewandowski2009). - -Using the `brms` formula notation, the compared models are - -$$ -\begin{align*} - \mathrm{M}_1: \quad & \mathrm{Reaction} \sim \mathrm{Days} \\ - \mathrm{M}_2: \quad & \mathrm{Reaction} \sim \mathrm{Days} + (1\,\mid\,\mathrm{Subject}) \\ - \mathrm{M}_3: \quad & \mathrm{Reaction} \sim \mathrm{Days} + (\mathrm{Days}\,\mid\, \mathrm{Subject}). -\end{align*} -$$ - -Based on the study design, $\mathrm{M}_3$ is the appropriate model for the analysis, but comparing models is useful for assessing how much information the data has about the varying intercepts and slopes. For a few LOO-folds with high Pareto-$\hat{k}$ diagnostic value ($>0.7$, [Vehtari et al., 2024](#vehtari2024)) we re-ran MCMC (with `reloo=TRUE` in `brms`). We use `add_criterion()` to store the loo object inside the brmsfit objects. - -```{r model-fitting, cache=TRUE, echo=FALSE} -M_1 <- brms::brm(Reaction ~ Days, - data = sleepstudy2, - family = gaussian(), - refresh = 0) |> - brms::add_criterion(criterion = "loo", save_psis = TRUE, reloo = TRUE) -M_2 <- brms::brm(Reaction ~ Days + (1 | Subject), - data = sleepstudy2, - family = gaussian(), - refresh = 0) |> - brms::add_criterion(criterion = "loo", save_psis = TRUE, reloo = TRUE) -M_3 <- brms::brm(Reaction ~ Days + (Days | Subject), - data = sleepstudy2, - family = gaussian(), - refresh = 0) |> - brms::add_criterion(criterion = "loo", save_psis = TRUE, reloo = TRUE) -``` - -We compare the models $\mathrm{M}_1, \mathrm{M}_2,\mathrm{M}_3,\mathrm{M}_4$ - -```{r model-comparison} -brms::loo_compare(M_1, M_2, M_3) |> - as.data.frame() |> - tibble::rownames_to_column(var = "model") |> - dplyr::select(model, elpd_diff, se_diff) |> - tinytable::tt() |> - tinytable::format_tt(j = 2:3, digits = 5) -``` - -Model $\mathrm{M}_3$ is estimated to have better predictive performance. Model-checking reveals that two observations are clear outliers with respect to these models, making the normal approximation likely to be poorly calibrated. -We see the outliers, for example, by comparing LOO predictive intervals to observations. - -```{r pp-check, out.width="100%", warning=FALSE, message=FALSE} -p1 <- pp_check(M_2, type = "loo_intervals") + - ggplot2::labs(y = "Reaction time (ms)", subtitle = "M2") + - bayesplot::theme_default(base_family = "sans") - -p2 <- pp_check(M_3, type = "loo_intervals") + - ggplot2::labs(subtitle = "M3") + - bayesplot::theme_default(base_family = "sans") - -p1 + p2 + plot_layout(ncol = 2, guides = "collect") & theme_bw(base_size = 6) -``` - -We see miscalibration also with LOO-PIT plots - -```{r calibration-plots-helper} -plot_ppc <- function(qp, method = "correlated", diff, prob = 0.95) { - - p1 <- ppc_loo_pit_ecdf( - pit = qp, method = method, test = "PRIT", plot_diff = diff, - prob = prob - ) + - labs(subtitle = "PRIT Test") - p2 <- ppc_loo_pit_ecdf( - pit = qp, method = method, test = "POT", plot_diff = diff, - prob = prob - ) + - labs(subtitle = "POT Test") - p3 <- ppc_loo_pit_ecdf( - pit = qp, method = method, test = "PIET", plot_diff = diff, - prob = prob - ) + - labs(subtitle = "PIET Test") - - p1 + p2 + p3 + - plot_layout(ncol = 3, guides = "collect") & theme_bw(base_size = 6) -} -``` - -```{r calibration-plots-1} -qp <- posterior::pit(posterior_predict(M_2), sleepstudy2$Reaction) - -plot_ppc(qp, method = "correlated", diff = FALSE) -plot_ppc(qp, method = "independent", diff = FALSE) -``` - -```{r calibration-plots-2} -qp <- posterior::pit( - posterior_predict(M_2), sleepstudy2$Reaction, - weights(brms::loo(M_2), log = TRUE), log = TRUE - ) - -plot_ppc(qp, diff = FALSE) -plot_ppc(qp, diff = TRUE) -``` - -```{r calibration-plots-3} -qp <- posterior::pit( - posterior_predict(M_3), sleepstudy2$Reaction, - weights(brms::loo(M_3), log = TRUE), log = TRUE - ) - -plot_ppc(qp, diff = FALSE) -plot_ppc(qp, diff = TRUE) -``` - -## Independent vs. dependence-aware uniformity tests - -```{r} -qp <- posterior::pit( - posterior_predict(M_2), sleepstudy2$Reaction, - weights(brms::loo(M_2), log = TRUE), log = TRUE - ) - -p1 <- ppc_loo_pit_ecdf( - pit = qp, method = "independent", plot_diff = FALSE) + - labs(subtitle = "Independent uniformity test") -p2 <- ppc_loo_pit_ecdf( - pit = qp, method = "correlated", plot_diff = FALSE) + - labs(subtitle = "Dependence-aware uniformity test") - -p1 + p2 + -plot_layout(ncol = 2, guides = "collect") & theme_bw(base_size = 6) -``` - -```{r} -qp <- posterior::pit( - posterior_predict(M_2), sleepstudy2$Reaction, - weights(brms::loo(M_2), log = TRUE), log = TRUE - ) - -p1 <- ppc_loo_pit_ecdf( - pit = qp, method = "independent", plot_diff = TRUE) + - labs(subtitle = "Säilynoja et al. (2022); independence") -p2 <- ppc_loo_pit_ecdf( - pit = qp, method = "correlated", plot_diff = TRUE) + - labs(subtitle = "Tesso & Vehtari (2026); dependence-aware") - -p1 + p2 + - plot_layout(ncol = 2, guides = "collect") & theme_bw(base_size = 6) -``` - -```{r} -qp <- posterior::pit( - posterior_predict(M_2), sleepstudy2$Reaction, - weights(brms::loo(M_2), log = TRUE), log = TRUE - ) - -ppc_loo_pit_ecdf(pit = qp, method = "correlated", plot_diff = TRUE) + - ggplot2::labs(subtitle = "POT test") + - ggplot2::ylim(c(-0.2, 0.2)) + - theme_bw(base_size = 6) -``` - -## References - -Bates, D., Maechler, M., Bolker, B., Walker, S., Christensen, R. H. B., Singmann, H., ... & Bolker, M. B. (2015). Package ‘lme4’. Convergence, 12(1), 2. - -Belenky, G., Wesensten, N. J., Thorne, D. R., Thomas, M. L., Sing, H. C., Redmond, D. P., ... & Balkin, T. J. (2003). Patterns of performance degradation and restoration during sleep restriction and subsequent recovery: A sleep dose‐response study. Journal of sleep research, 12(1), 1-12. - -Buerkner, P. (2017). brms: Bayesian Regression Models using Stan. R package -version 1.7.0. https://CRAN.R-project.org/package=brms - -Lewandowski, D., Kurowicka, D., & Joe, H. (2009). Generating random correlation -matrices based on vines and extended onion method. Journal of Multivariate -Analysis, 100 (9), 1989–2001. - -Vehtari, A., Simpson, D., Gelman, A., Yao, Y., & Gabry, J. (2024). Pareto smoothed importance sampling. Journal of Machine Learning Research, 25(72), 1-58. \ No newline at end of file From 921c7ce12d41f1679205b047e9f523d2cbc58f9c Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Mon, 2 Mar 2026 12:54:50 +0200 Subject: [PATCH 054/120] fix typo in .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ee6e310c..091a639c 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,4 @@ vignettes/*.quarto vignettes/*.html # draft vignette -ppc-loo-draft.Rmd \ No newline at end of file +ppc_loo_pit.Rmd \ No newline at end of file From 5f4e55b6edff73838d00fe509e71953bc07da3f5 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Mon, 2 Mar 2026 13:21:38 +0200 Subject: [PATCH 055/120] change geom_abline to geom_segment to adhere to 0-1 intervall --- R/ppc-loo.R | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 211c360b..c3284e9c 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -573,11 +573,12 @@ ppc_loo_pit_ecdf <- function(y, ) # Add reference line - p <- p + geom_abline( - intercept = 0, - slope = dplyr::if_else(plot_diff, 0, 1), - linetype = 2, - color = "darkgrey" + p <- p + geom_segment( + aes( + x = 0, y = 0, xend = 1, + yend = dplyr::if_else(plot_diff, 0, 1) + ), + linetype = 2, color = "darkgrey" ) # Identify and highlight suspecious points (regions) of the ECDF From 6bede236a3a89c86a295308cda095dd37ea9e31a Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Mon, 2 Mar 2026 13:22:25 +0200 Subject: [PATCH 056/120] update snapshots for visual regression test --- .../ppc-loo/ppc-loo-pit-ecdf-color-change.svg | 2 +- .../ppc-loo-pit-ecdf-correlated-piet.svg | 2 +- .../ppc-loo-pit-ecdf-correlated-pot.svg | 2 +- .../ppc-loo-pit-ecdf-correlated-prit.svg | 2 +- .../ppc-loo-pit-ecdf-diff-correlated-piet.svg | 2 +- .../ppc-loo-pit-ecdf-diff-correlated-pot.svg | 2 +- .../ppc-loo-pit-ecdf-diff-correlated-prit.svg | 2 +- .../ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg | 2 +- .../ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg | 2 +- tests/vdiffr.Rout.fail | 2173 +++++++++++++++++ 10 files changed, 2182 insertions(+), 9 deletions(-) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg index b5affffe..bdda44f4 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg @@ -26,7 +26,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg index 3d3bdd11..f98d0b01 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg @@ -26,7 +26,7 @@ - + Uniformity p-value = 0.188 diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg index 0164d8f9..ce3f477d 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg @@ -26,7 +26,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg index 36752bbd..64addae2 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg @@ -26,7 +26,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg index 8b92725a..244296bf 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg @@ -26,7 +26,7 @@ - + Uniformity p-value = 0.188 diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg index f8677b41..31bae272 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg @@ -26,7 +26,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg index 0efc9fb7..5f400222 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg @@ -26,7 +26,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg index e479563b..c2e0a025 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg @@ -26,7 +26,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg index 12f6f327..e9e577a0 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg @@ -26,7 +26,7 @@ - + diff --git a/tests/vdiffr.Rout.fail b/tests/vdiffr.Rout.fail index 59e731db..8bfa5ad3 100644 --- a/tests/vdiffr.Rout.fail +++ b/tests/vdiffr.Rout.fail @@ -57680,3 +57680,2176 @@ Failed doppelganger: ppc-loo-pit-ecdf-color-change (/u/21/wa.bocktif1/unix/GitHu + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) + +< before +> after +@@ 27,5 / 27,5 @@ + + +< +> + + + + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-prit (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg) + +< before +> after +@@ 27,5 / 27,5 @@ + + +< +> + + + + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-piet (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg) + +< before +> after +@@ 27,5 / 27,5 @@ + + +< +> + Uniformity p-value = 0.188 + + + +Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-pot (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg) + +< before +> after +@@ 27,5 / 27,5 @@ + + +< +> + + + + +Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-prit (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg) + +< before +> after +@@ 27,5 / 27,5 @@ + + +< +> + + + + +Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-piet (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg) + +< before +> after +@@ 27,5 / 27,5 @@ + + +< +> + Uniformity p-value = 0.188 + + + +Failed doppelganger: ppc-loo-pit-ecdf-linewidth-1 (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg) + +< before +> after +@@ 27,5 / 27,5 @@ + + +< +> + + + + +Failed doppelganger: ppc-loo-pit-ecdf-linewidth-2 (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg) + +< before +> after +@@ 27,5 / 27,5 @@ + + +< +> + + + + +Failed doppelganger: ppc-loo-pit-ecdf-color-change (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg) + +< before +> after +@@ 27,5 / 27,5 @@ + + +< +> + + + From 2e1576752988e390679bff1c8e4cc0abdbc48b82 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Mon, 2 Mar 2026 13:44:31 +0200 Subject: [PATCH 057/120] update snapshot for ppc-loo-pit-overlay-boundary --- .../ppc-loo/ppc-loo-pit-overlay-boundary.svg | 202 +++++++++--------- 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.svg index 07009b87..3426f2c2 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.svg @@ -25,107 +25,107 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From a7e26a69c5469e686a1eddb88dd65251a75c9faa Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Mon, 2 Mar 2026 14:16:55 +0200 Subject: [PATCH 058/120] add draft vignette to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 695e6e77..c02b505b 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ release-prep.R # vscode/positron/etc settings .vscode/* + +# ignore draft vignette +vignettes/ppc_loo_pit.Rmd \ No newline at end of file From d4461a6368e08fdfcddeece99956fd4d7bab3252 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Mon, 2 Mar 2026 14:17:48 +0200 Subject: [PATCH 059/120] add additional arguments required for method='correlated' --- R/ppc-distributions.R | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/R/ppc-distributions.R b/R/ppc-distributions.R index d86a8b4c..b8d45e71 100644 --- a/R/ppc-distributions.R +++ b/R/ppc-distributions.R @@ -657,7 +657,13 @@ ppc_pit_ecdf <- function(y, K = NULL, prob = .99, plot_diff = FALSE, - interpolate_adj = NULL) { + interpolate_adj = NULL, + method = "independent", + test = NULL, + gamma = NULL, + linewidth = NULL, + color = NULL + ) { check_ignored_arguments(..., ok_args = c("K", "pit", "prob", "plot_diff", "interpolate_adj") ) From 04cd4dd95b147ba67c2edf7033befc0b43a2d609 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Mon, 2 Mar 2026 14:28:46 +0200 Subject: [PATCH 060/120] modify ppc_pit_ecdf to support method='correlated' --- R/ppc-distributions.R | 216 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 192 insertions(+), 24 deletions(-) diff --git a/R/ppc-distributions.R b/R/ppc-distributions.R index b8d45e71..6b72944c 100644 --- a/R/ppc-distributions.R +++ b/R/ppc-distributions.R @@ -665,7 +665,33 @@ ppc_pit_ecdf <- function(y, color = NULL ) { check_ignored_arguments(..., - ok_args = c("K", "pit", "prob", "plot_diff", "interpolate_adj") + ok_args = c("K", "pit", "prob", "plot_diff", "interpolate_adj", + "method", "test", "gamma", "linewidth", "color") + ) + + method <- match.arg(method, choices = c("independent", "correlated")) + + .warn_ignored <- function(method, args) { + msg <- paste0("As method = ", method, " specified; ignoring: ", + paste(args, collapse = ", "), ".") + inform(msg) + } + + switch(method, + "correlated" = { + if (!is.null(interpolate_adj)) .warn_ignored("'correlated'", "interpolate_adj") + test <- match.arg(test %||% "POT", choices = c("POT", "PRIT", "PIET")) + alpha <- 1 - prob + gamma <- gamma %||% 0 + linewidth <- linewidth %||% 0.3 + color <- color %||% c(ecdf = "black", highlight = "red") + }, + "independent" = { + ignored <- character(0) + if (!is.null(test)) ignored <- c(ignored, "test") + if (!is.null(gamma)) ignored <- c(ignored, "gamma") + if (length(ignored) > 0) .warn_ignored("'independent'", ignored) + } ) if (is.null(pit)) { @@ -686,36 +712,178 @@ ppc_pit_ecdf <- function(y, K <- length(pit) } } - N <- length(pit) - gamma <- adjust_gamma( - N = N, + + n_obs <- length(pit) + unit_interval <- seq(0, 1, length.out = K) + .ecdf_pit_fn <- ecdf(pit) + + # Correlated method -------------------------------------------------- + if (method == "correlated") { + # Compute test p-value and Cauchy-transformed values + if (test == "POT") { + std_cauchy_values <- .compute_cauchy(.pot_test(sort(pit))) + p_value_CCT <- .cauchy_combination_test(.pot_test(pit), truncate = TRUE) + } else if (test == "PIET") { + std_cauchy_values <- .compute_cauchy(.piet_test(sort(pit))) + p_value_CCT <- .cauchy_combination_test(.piet_test(pit), truncate = FALSE) + } else { # PRIT + std_cauchy_values <- .compute_cauchy(.prit_test(sort(pit))) + p_value_CCT <- .cauchy_combination_test(.prit_test(pit), truncate = TRUE) + } + + pointwise_contribution <- .compute_shapley_values(std_cauchy_values) + + if (gamma < 0 || gamma > max(pointwise_contribution)) { + stop(sprintf( + "gamma must be in the interval [0, %.2f], but gamma = %s was provided", + max(pointwise_contribution), gamma + )) + } + x_axis_combined <- sort(unique(c(unit_interval, pit))) + + # Evaluate at 0-1 interval b´values + df_main <- tibble::tibble( + x = x_axis_combined, + ecdf_pit = .ecdf_pit_fn(x_axis_combined) - plot_diff * x_axis_combined + ) + + # Evaluate at pit values (used for highlighing) + df_pit <- tibble::tibble( + pit = pit, + ecdf_pit = .ecdf_pit_fn(pit) - plot_diff * pit + ) + df_pit <- df_pit[order(df_pit$pit), ] + + # Plot ECDF + p <- ggplot() + + geom_step( + data = df_main, aes(x = .data$x, y = .data$ecdf_pit), + show.legend = FALSE, linewidth = linewidth, color = color[1]) + + labs( + y = dplyr::if_else(plot_diff, "ECDF difference", "ECDF"), + x = "PIT" + ) + + # Add reference line + p <- p + geom_segment( + aes( + x = 0, y = 0, xend = 1, + yend = dplyr::if_else(plot_diff, 0, 1) + ), + linetype = 2, color = "darkgrey" + ) + + # Identify and highlight suspecious points (regions) of the ECDF + if (p_value_CCT < alpha) { + red_idx <- which(pointwise_contribution > gamma) + + if (length(red_idx) > 0) { + df_red <- df_pit[red_idx, ] + + # Groups of consecutive suspicious points + df_red$segment <- cumsum(c(1, diff(red_idx) != 1)) + + # Separate isolated vs grouped points + segment_lengths <- stats::ave(df_red$pit, df_red$segment, FUN = length) + df_isolated <- df_red[segment_lengths == 1, ] + df_grouped <- df_red[segment_lengths > 1, ] + + # Create segments based on x_combined values for grouped points + if (nrow(df_grouped) > 0) { + segments_list <- lapply( + split(df_grouped, df_grouped$segment), function(group) { + group_indices <- match(group$pit, x_axis_combined) + idx_range <- min(group_indices):max(group_indices) + + tibble::tibble( + x = df_main$x[idx_range], + ecdf_pit = df_main$ecdf_pit[idx_range], + segment = group$segment[1] + ) + } + ) + df_segments <- do.call(rbind, segments_list) + + p <- p + geom_step( + data = df_segments, + aes(x = .data$x, y = .data$ecdf_pit, group = .data$segment), + color = color[2], + linewidth = linewidth + 0.8 + ) + } + + if (nrow(df_isolated) > 0) { + p <- p + geom_point( + data = df_isolated, + aes(x = .data$pit, y = .data$ecdf_pit), + color = color[2], + size = linewidth + 1 + ) + } + } + } + + # Apply bayesplot theme and styling + p <- p + + yaxis_ticks(FALSE) + + scale_color_ppc() + + annotate( + "text", + x = -Inf, y = Inf, + label = sprintf("Uniformity p-value = %.3f", p_value_CCT), + hjust = -0.1, vjust = 1.5, + size = 6, color = "black" + ) + + bayesplot::theme_default(base_family = "sans", base_size = 16) + + if (plot_diff) { + epsilon = max( + sqrt(log(2 / (1 - prob)) / (2 * length(pit))), + max(abs(df_main$ecdf_pit)) + ) + + p <- p + scale_y_continuous(limits = c(-epsilon, epsilon)) + } + + return(p) + } + + # Independent method -------------------------------------------------- + gamma_indep <- adjust_gamma( + N = n_obs, K = K, prob = prob, interpolate_adj = interpolate_adj ) - lims <- ecdf_intervals(gamma = gamma, N = N, K = K) - ggplot() + - aes( - x = seq(0,1,length.out = K), - y = ecdf(pit)(seq(0, 1, length.out = K)) - - (plot_diff == TRUE) * seq(0, 1, length.out = K), - color = "y" + + lims <- ecdf_intervals(gamma = gamma_indep, N = n_obs, K = K) + ecdf_eval <- .ecdf_pit_fn(unit_interval) - plot_diff * unit_interval + + lims_upper_scaled <- lims$upper[-1] * (1 / n_obs) - plot_diff * unit_interval + lims_lower_scaled <- lims$lower[-1] * (1 / n_obs) - plot_diff * unit_interval + + p <- ggplot() + + geom_step( + aes(x = unit_interval, y = lims_upper_scaled, color = "yrep"), + linetype = 2, show.legend = FALSE + ) + + geom_step( + aes(x = unit_interval, y = lims_lower_scaled, color = "yrep"), + linetype = 2, show.legend = FALSE + ) + + geom_step( + aes(x = unit_interval, y = ecdf_eval, color = "y", linewidth = linewidth), + show.legend = FALSE + ) + + labs( + y = dplyr::if_else(plot_diff, "ECDF difference", "ECDF"), + x = "PIT" ) + - geom_step(show.legend = FALSE) + - geom_step(aes( - y = lims$upper[-1] / N - (plot_diff == TRUE) * seq(0, 1, length.out = K), - color = "yrep" - ), - linetype = 2, show.legend = FALSE) + - geom_step(aes( - y = lims$lower[-1] / N - (plot_diff == TRUE) * seq(0, 1, length.out = K), - color = "yrep" - ), - linetype = 2, show.legend = FALSE) + - labs(y = ifelse(plot_diff,"ECDF - difference","ECDF"), x = "PIT") + yaxis_ticks(FALSE) + scale_color_ppc() + - bayesplot_theme_get() + bayesplot::theme_default(base_family = "sans", base_size = 16) + + return(p) } #' @export From 9ff1038ae630a1e2dbe14924ec6314a2a6c8e049 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Mon, 2 Mar 2026 20:29:31 +0200 Subject: [PATCH 061/120] add helper functions for uniformity tests --- R/helpers-ppc.R | 128 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index e268b315..ee9fee6a 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -595,3 +595,131 @@ create_rep_ids <- function(ids) paste('italic(y)[rep] (', ids, ")") y_label <- function() expression(italic(y)) yrep_label <- function() expression(italic(y)[rep]) ypred_label <- function() expression(italic(y)[pred]) + +# Dependence-aware uniformity tests ------------------------------------- + +#' Compute Shapley values +#' +#' Calculates the average marginal contribution of players across +#' all random arrival orders in a cooperative game. +#' Used to provide a principled approach for quantifying +#' point-specific influences in a way that reflects local miscalibration. +#' +#' @param x Numeric vector of Cauchy-transformed PIT values. +#' @return Numeric vector of Shapley values with the same length as `x`. +#' @noRd +.compute_shapley_values <- function(x) { + n <- length(x) + if (n == 0) { + return(numeric(0)) + } + if (n == 1) { + return(0) + } + + # Harmonic number + # H_n = sum(1/i) for i = 1 to n + harmonic_number <- sum(1 / seq_len(n)) + + shapley_values <- numeric(n) + for (i in seq_len(n)) { + mean_others <- sum(x[-i]) / (n - 1) + # Applies the closed-form formula to assign player i their fair share. + shapley_values[i] <- (1 / n) * x[i] + ((harmonic_number - 1) / n) * (x[i] - mean_others) + } + + return(shapley_values) +} + +#' Pointwise Inverse-CDF Evaluation Tests Combination (PIET) +#' +#' Uniformity test with respect to any continuous distribution. +#' H0: The value obtained via the inverse CDF transformation F^(-1)(x_i) +#' follows the distribution of X under uniformity. +#' HA: The p-value p_(i) provides evidence against uniformity. +#' +#' @param x Numeric vector of PIT values in `[0, 1]`. +#' @return Numeric vector of p-values. +#' @noRd +.piet_test <- function(x) { + cdf_exp <- pexp(-log(x), rate = 1) # same as 1-x but numerically more stable + p_values <- 2 * pmin(cdf_exp, 1 - cdf_exp) + + return(p_values) +} + +#' Pointwise Order Tests Combination (POT) +#' +#' Uniformity test based on a beta distribution. +#' H0: The i-th order statistic u_(i) follows a beta distribution +#' under uniformity. +#' HA: The p-value p_(i) provides evidence against uniformity +#' at the i-th order statistic u_(i). +#' +#' @param x Numeric vector of PIT values in `[0, 1]`. +#' @return Numeric vector of p-values. +#' @noRd +.pot_test <- function(x) { + n <- length(x) + # keep NA values instead of silent recycling via sort() + # TODO: Can PIT values be NAN at this point? + cdf_beta <- pbeta(sort(x, na.last = TRUE), 1:n, seq(n, 1, by = -1)) + p_values <- 2 * pmin(cdf_beta, 1 - cdf_beta) + + return(p_values) +} + +#' Pointwise Rank-based Individual Tests Combination (PRIT) +#' +#' Uniformity test based on a binomial distribution. +#' H0: The number of observations falling at or below x_i +#' follows a binomial distribution under uniformity. +#' HA: The p-value p_i provides evidence against uniformity. +#' +#' @param x Numeric vector of PIT values in `[0, 1]`. +#' @return Numeric vector of p-values. +#' @noRd +.prit_test <- function(x) { + n <- length(x) + scaled_ecdf <- n * ecdf(x)(x) + probs1 <- pbinom(scaled_ecdf - 1, n, x) + probs2 <- pbinom(scaled_ecdf, n, x) + p_values <- 2 * pmin(1 - probs1, probs2) + + return(p_values) +} + +#' Truncated Cauchy combination test +#' +#' Combines dependent p-values using the Cauchy combination method. +#' If truncate, only p-values less than 0.5 are included. +#' +#' @param x Numeric vector of p-values transformed to follow a standard +#' Cauchy distribution. +#' @param truncate Boolean; If TRUE only p-values less than 0.5 are +#' included. +#' @return p-value of the Cauchy combination method. +#' @noRd +.cauchy_combination_test <- function(x, truncate = NULL) { + if (truncate) { + idx <- which(x < 0.5) + if (length(idx) == 0) { + stop("Cannot compute truncated Cauchy combination test. ", + "No p-values below 0.5 found.") + } + 1 - pcauchy(mean(-qcauchy(x[idx]))) + } else { + 1 - pcauchy(mean(-qcauchy(x))) + } +} + +#' Compute Cauchy transformation +#' +#' Transforms PIT values to follow a standard Cauchy distribution. +#' +#' @param x Numeric vector of PIT values in `[0, 1]`. +#' @return Numeric vector of Cauchy-transformed values. +#' @noRd +.compute_cauchy <- function(x) { + tan((0.5 - x) * pi) +} \ No newline at end of file From 23ae49f19f311d59b3601f3238d7016a5c04ada7 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Mon, 2 Mar 2026 20:30:11 +0200 Subject: [PATCH 062/120] update parameter description --- R/ppc-distributions.R | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/R/ppc-distributions.R b/R/ppc-distributions.R index 6b72944c..3bf754bc 100644 --- a/R/ppc-distributions.R +++ b/R/ppc-distributions.R @@ -648,6 +648,27 @@ ppc_violin_grouped <- #' @param pit An optional vector of probability integral transformed values for #' which the ECDF is to be drawn. If NULL, PIT values are computed to `y` with #' respect to the corresponding values in `yrep`. +#' @param interpolate_adj For `ppc_loo_pit_ecdf()` when `method = "independent"`, +#' a boolean defining if the simultaneous confidence bands should be +#' interpolated based on precomputed values rather than computed exactly. +#' Computing the bands may be computationally intensive and the approximation +#' gives a fast method for assessing the ECDF trajectory. The default is to use +#' interpolation if `K` is greater than 200. +#' @param method For `ppc_loo_pit_ecdf()`, the method used to calculate the +#' uniformity test: +#' * `"independent"`: (default) Assumes independence (Säilynoja et al., 2022). +#' * `"correlated"`: Accounts for correlation (Tesso & Vehtari, 2026). +#' @param test For `ppc_loo_pit_ecdf()` when `method = "correlated"`, which +#' dependence-aware test to use: `"POT"`, `"PRIT"`, or `"PIET"`. +#' Defaults to `"POT"`. +#' @param gamma For `ppc_loo_pit_ecdf()` when `method = "correlated"`, tolerance +#' threshold controlling how strongly suspicious points are flagged. Larger +#' values (gamma > 0) emphasizes points with larger deviations. If `NULL`, automatically +#' determined based on p-value. +#' @param color For `ppc_loo_pit_ecdf()` when `method = "correlated"`, a vector +#' with base color and highlight color for the ECDF plot. Defaults to +#' `c(ecdf = "black", highlight = "red")`. The first element is used for +#' the main ECDF line, the second for highlighted suspicious regions. #' @rdname PPC-distributions #' ppc_pit_ecdf <- function(y, From d0630886de728fb32a7e4abfaa13af3208203ba0 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Mon, 2 Mar 2026 20:30:57 +0200 Subject: [PATCH 063/120] add tests for updated ppc_pit_ecdf() --- tests/testthat/test-ppc-distributions.R | 63 ++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-ppc-distributions.R b/tests/testthat/test-ppc-distributions.R index 9062515f..28cc589f 100644 --- a/tests/testthat/test-ppc-distributions.R +++ b/tests/testthat/test-ppc-distributions.R @@ -104,13 +104,60 @@ test_that("ppc_dots returns a ggplot object", { }) test_that("ppc_pit_ecdf, ppc_pit_ecdf_grouped returns a ggplot object", { + # Independent method (default) expect_gg(ppc_pit_ecdf(y, yrep, interpolate_adj = FALSE)) + expect_gg(ppc_pit_ecdf(y, yrep, method = "independent", interpolate_adj = FALSE)) expect_gg(ppc_pit_ecdf_grouped(y, yrep, group = group, interpolate_adj = FALSE)) + + # Correlated method + expect_gg(ppc_pit_ecdf(y, yrep, method = "correlated")) + expect_gg(ppc_pit_ecdf(y, yrep, method = "correlated", plot_diff = TRUE)) + expect_gg(ppc_pit_ecdf(y, yrep, method = "correlated", test = "PRIT")) + expect_gg(ppc_pit_ecdf(y, yrep, method = "correlated", test = "PIET")) + + # Specify 'pit' directly expect_message(ppc_pit_ecdf(pit = runif(100)), "'pit' specified") expect_message( ppc_pit_ecdf_grouped(pit = runif(length(group)), group = group, interpolate_adj = FALSE), "'pit' specified" ) + expect_message(ppc_pit_ecdf(pit = runif(100), method = "correlated"), + "'pit' specified") +}) + +test_that("ppc_pit_ecdf method validation and ignored-argument warnings", { + # Invalid method + expect_error(ppc_pit_ecdf(y, yrep, method = "bogus")) + + # method = "correlated" warns about interpolate_adj + expect_message( + ppc_pit_ecdf(y, yrep, method = "correlated", interpolate_adj = TRUE), + "ignoring.*interpolate_adj" + ) + + # method = "independent" warns about test and gamma + expect_message( + ppc_pit_ecdf(y, yrep, method = "independent", test = "POT", + interpolate_adj = FALSE), + "ignoring.*test" + ) + expect_message( + ppc_pit_ecdf(y, yrep, method = "independent", test = "POT", gamma = 0.5, + interpolate_adj = FALSE), + "ignoring.*test, gamma" + ) + + # Invalid test type for correlated + expect_error( + ppc_pit_ecdf(y, yrep, method = "correlated", test = "INVALID") + ) +}) + +test_that("ppc_pit_ecdf correlated method validates gamma", { + expect_error( + ppc_pit_ecdf(y, yrep, method = "correlated", gamma = -1), + "gamma must be in the interval" + ) }) test_that("ppc_freqpoly_grouped returns a ggplot object", { @@ -412,6 +459,7 @@ test_that("ppc_pit_ecdf, ppc_pit_ecdf_grouped renders correctly", { testthat::skip_if_not_installed("vdiffr") skip_on_r_oldrel() + # Independent method p_base <- ppc_pit_ecdf(y, yrep, interpolate_adj = FALSE) g_base <- ppc_pit_ecdf_grouped(y, yrep, group = group, interpolate_adj = FALSE) p_diff <- ppc_pit_ecdf(y, yrep, plot_diff = TRUE, interpolate_adj = FALSE) @@ -421,4 +469,17 @@ test_that("ppc_pit_ecdf, ppc_pit_ecdf_grouped renders correctly", { vdiffr::expect_doppelganger("ppc_pit_ecdf_grouped (default)", g_base) vdiffr::expect_doppelganger("ppc_pit_ecdf (diff)", p_diff) vdiffr::expect_doppelganger("ppc_pit_ecdf_grouped (diff)", g_diff) -}) + + # Correlated method + p_corr <- ppc_pit_ecdf(y, yrep, method = "correlated") + vdiffr::expect_doppelganger("ppc_pit_ecdf (correlated)", p_corr) + + p_corr_diff <- ppc_pit_ecdf(y, yrep, method = "correlated", plot_diff = TRUE) + vdiffr::expect_doppelganger("ppc_pit_ecdf (correlated diff)", p_corr_diff) + + p_corr_prit <- ppc_pit_ecdf(y, yrep, method = "correlated", test = "PRIT") + vdiffr::expect_doppelganger("ppc_pit_ecdf (correlated PRIT)", p_corr_prit) + + p_corr_piet <- ppc_pit_ecdf(y, yrep, method = "correlated", test = "PIET") + vdiffr::expect_doppelganger("ppc_pit_ecdf (correlated PIET)", p_corr_piet) +}) \ No newline at end of file From c11b41371152a9514476fe240319b42efa85340e Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Tue, 3 Mar 2026 08:01:12 +0200 Subject: [PATCH 064/120] minor theme adjustments and add help_text arg --- R/ppc-loo.R | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index c3284e9c..0e620632 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -417,6 +417,8 @@ ppc_loo_pit_qq <- function(y, #' with base color and highlight color for the ECDF plot. Defaults to #' `c(ecdf = "gray60", highlight = "gray30")`. The first element is used for #' the main ECDF line, the second for highlighted suspicious regions. +#' @param help_text For `ppc_loo_pit_ecdf()` when `method = "correlated"`, a boolean +#' defining whether to add informative text to the plot. Defaults to `TRUE`. #' @note #' Note that the default "independent" method is **superseded** by #' the "correlated" method (Tesso & Vehtari, 2026) which accounts for dependent @@ -435,7 +437,8 @@ ppc_loo_pit_ecdf <- function(y, test = NULL, gamma = NULL, linewidth = NULL, - color = NULL) { + color = NULL, + help_text = NULL) { check_ignored_arguments(..., ok_args = list("moment_match")) @@ -511,12 +514,14 @@ ppc_loo_pit_ecdf <- function(y, gamma <- gamma %||% 0 linewidth <- linewidth %||% 0.3 color <- color %||% c(ecdf = "black", highlight = "red") + help_text <- help_text %||% TRUE }, "independent" = { ignored <- character(0) if (!is.null(test)) ignored <- c(ignored, "test") if (!is.null(gamma)) ignored <- c(ignored, "gamma") + if (!is.null(help_text)) ignored <- c(ignored, "help_text") if (length(ignored) > 0) .warn_ignored("'independent'", ignored) } ) @@ -578,7 +583,7 @@ ppc_loo_pit_ecdf <- function(y, x = 0, y = 0, xend = 1, yend = dplyr::if_else(plot_diff, 0, 1) ), - linetype = 2, color = "darkgrey" + linetype = "dashed", color = "darkgrey", linewidth = 0.3 ) # Identify and highlight suspecious points (regions) of the ECDF @@ -635,15 +640,18 @@ ppc_loo_pit_ecdf <- function(y, p <- p + yaxis_ticks(FALSE) + scale_color_ppc() + - annotate( + bayesplot::theme_default(base_family = "sans") + + if (help_text) { + p <- p + annotate( "text", x = -Inf, y = Inf, - label = sprintf("Uniformity p-value = %.3f", p_value_CCT), - hjust = -0.1, vjust = 1.5, - size = 6, color = "black" - ) + - bayesplot::theme_default(base_family = "sans", base_size = 16) - + label = sprintf("p[unif] == '%.3f' ~ (alpha == '%.2f')", p_value_CCT, alpha), + hjust = -0.05, vjust = 1.5, color = "black", + parse = TRUE, size = 0.7 * bayesplot_theme_get()$text@size / ggplot2::.pt + ) + } + if (plot_diff) { epsilon = max( sqrt(log(2 / (1 - prob)) / (2 * length(pit))), @@ -675,11 +683,11 @@ ppc_loo_pit_ecdf <- function(y, p <- ggplot() + geom_step( aes(x = unit_interval, y = lims_upper_scaled, color = "yrep"), - linetype = 2, show.legend = FALSE + linetype = "dashed", linewidth = 0.3, show.legend = FALSE ) + geom_step( aes(x = unit_interval, y = lims_lower_scaled, color = "yrep"), - linetype = 2, show.legend = FALSE + linetype = "dashed", linewidth = 0.3, show.legend = FALSE ) + geom_step( aes(x = unit_interval, y = ecdf_eval, color = "y", linewidth = linewidth), @@ -691,7 +699,7 @@ ppc_loo_pit_ecdf <- function(y, ) + yaxis_ticks(FALSE) + scale_color_ppc() + - bayesplot::theme_default(base_family = "sans", base_size = 16) + bayesplot::theme_default(base_family = "sans") return(p) } From faa3371d903c872e37b8df93afb7d538bc084102 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Tue, 3 Mar 2026 08:01:59 +0200 Subject: [PATCH 065/120] add new tests for adjusted themes --- tests/testthat/test-ppc-loo.R | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/testthat/test-ppc-loo.R b/tests/testthat/test-ppc-loo.R index d749f066..c69d85ce 100644 --- a/tests/testthat/test-ppc-loo.R +++ b/tests/testthat/test-ppc-loo.R @@ -508,4 +508,36 @@ test_that("ppc_loo_pit_ecdf renders correctly", { K = 100 ) vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (ecdf difference)", p_custom) + + p_custom <- ppc_loo_pit_ecdf( + vdiff_loo_y, + vdiff_loo_yrep, + psis_object = psis_object, + method = "correlated", + plot_diff = TRUE, + prob = 0.95 + ) + vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (alpha=0.05)", p_custom) + + p_custom <- ppc_loo_pit_ecdf( + vdiff_loo_y, + vdiff_loo_yrep, + psis_object = psis_object, + method = "correlated", + plot_diff = TRUE, + prob = 0.95, + help_text = FALSE + ) + vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (no help_text)", p_custom) + + + setheme_set(bayesplot::theme_default(base_family = "sans", base_size = 12)) + p_custom <- ppc_loo_pit_ecdf( + vdiff_loo_y, + vdiff_loo_yrep, + psis_object = psis_object, + method = "correlated", + plot_diff = TRUE + ) + vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (changed theme)", p_custom) }) From 3c9de38c23b6155b6a682f2d2e94cf0960ef9fa4 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Tue, 3 Mar 2026 08:03:31 +0200 Subject: [PATCH 066/120] add updated snapshots for visual regression tests --- .../ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg | 73 + .../ppc-loo/ppc-loo-pit-ecdf-color-change.svg | 82 +- .../ppc-loo-pit-ecdf-correlated-piet.svg | 74 +- .../ppc-loo-pit-ecdf-correlated-pot.svg | 82 +- .../ppc-loo-pit-ecdf-correlated-prit.svg | 86 +- .../ppc-loo/ppc-loo-pit-ecdf-default.svg | 62 +- .../ppc-loo-pit-ecdf-diff-correlated-piet.svg | 74 +- .../ppc-loo-pit-ecdf-diff-correlated-pot.svg | 82 +- .../ppc-loo-pit-ecdf-diff-correlated-prit.svg | 86 +- .../ppc-loo-pit-ecdf-ecdf-difference.svg | 54 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg | 62 +- .../ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg | 82 +- .../ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg | 82 +- .../ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg | 60 + .../_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg | 62 +- tests/vdiffr.Rout.fail | 83860 ++++++++++++++++ 16 files changed, 84532 insertions(+), 431 deletions(-) create mode 100644 tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg create mode 100644 tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg new file mode 100644 index 00000000..2640d048 --- /dev/null +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.05 +) + + + +-0.10 +-0.05 +0.00 +0.05 +0.10 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF difference +ppc_loo_pit_ecdf (alpha=0.05) + + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg index bdda44f4..ae37137b 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg @@ -20,44 +20,56 @@ - - + + - - - - - - - -Uniformity p-value = 0.000 + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.01 +) - -0.00 -0.25 -0.50 -0.75 -1.00 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF -ppc_loo_pit_ecdf (color change) + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (color change) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg index f98d0b01..a0c8eafd 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg @@ -20,40 +20,52 @@ - - + + - - - -Uniformity p-value = 0.188 + + + +p +u +n +i +f += +0.188 + +( +α += +0.01 +) - -0.00 -0.25 -0.50 -0.75 -1.00 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF -ppc_loo_pit_ecdf (correlated piet) + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (correlated piet) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg index ce3f477d..d81ea6c0 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg @@ -20,44 +20,56 @@ - - + + - - - - - - - -Uniformity p-value = 0.000 + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.01 +) - -0.00 -0.25 -0.50 -0.75 -1.00 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF -ppc_loo_pit_ecdf (correlated pot) + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (correlated pot) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg index 64addae2..3dea271a 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg @@ -20,46 +20,58 @@ - - + + - - - - - - - - - -Uniformity p-value = 0.001 + + + + + + + + + +p +u +n +i +f += +0.001 + +( +α += +0.01 +) - -0.00 -0.25 -0.50 -0.75 -1.00 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF -ppc_loo_pit_ecdf (correlated prit) + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (correlated prit) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg index 6135a6e7..71e51c5e 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg @@ -20,40 +20,40 @@ - - + + - - - - + + + + - -0.00 -0.25 -0.50 -0.75 -1.00 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF -ppc_loo_pit_ecdf (default) + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (default) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg index 244296bf..9f5604d5 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg @@ -20,40 +20,52 @@ - - + + - - - -Uniformity p-value = 0.188 + + + +p +u +n +i +f += +0.188 + +( +α += +0.01 +) - --0.10 --0.05 -0.00 -0.05 -0.10 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF difference -ppc_loo_pit_ecdf (diff, correlated piet) + +-0.10 +-0.05 +0.00 +0.05 +0.10 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF difference +ppc_loo_pit_ecdf (diff, correlated piet) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg index 31bae272..84ed6e7c 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg @@ -20,44 +20,56 @@ - - + + - - - - - - - -Uniformity p-value = 0.000 + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.01 +) - --0.10 --0.05 -0.00 -0.05 -0.10 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF difference -ppc_loo_pit_ecdf (diff, correlated pot) + +-0.10 +-0.05 +0.00 +0.05 +0.10 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF difference +ppc_loo_pit_ecdf (diff, correlated pot) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg index 5f400222..61ea66db 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg @@ -20,46 +20,58 @@ - - + + - - - - - - - - - -Uniformity p-value = 0.001 + + + + + + + + + +p +u +n +i +f += +0.001 + +( +α += +0.01 +) - --0.10 --0.05 -0.00 -0.05 -0.10 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF difference -ppc_loo_pit_ecdf (diff, correlated prit) + +-0.10 +-0.05 +0.00 +0.05 +0.10 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF difference +ppc_loo_pit_ecdf (diff, correlated prit) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg index cbcada47..cdf67834 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg @@ -20,36 +20,36 @@ - - + + - - - - + + + + - --0.1 -0.0 -0.1 - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF difference -ppc_loo_pit_ecdf (ecdf difference) + +-0.1 +0.0 +0.1 + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF difference +ppc_loo_pit_ecdf (ecdf difference) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg index 4cb88f33..8e860dba 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg @@ -20,40 +20,40 @@ - - + + - - - - + + + + - -0.00 -0.25 -0.50 -0.75 -1.00 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF -ppc_loo_pit_ecdf (K) + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (K) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg index c2e0a025..d2214885 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg @@ -20,44 +20,56 @@ - - + + - - - - - - - -Uniformity p-value = 0.000 + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.01 +) - -0.00 -0.25 -0.50 -0.75 -1.00 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF -ppc_loo_pit_ecdf (linewidth = 1) + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (linewidth = 1) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg index e9e577a0..8512ff8e 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg @@ -20,44 +20,56 @@ - - + + - - - - - - - -Uniformity p-value = 0.000 + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.01 +) - -0.00 -0.25 -0.50 -0.75 -1.00 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF -ppc_loo_pit_ecdf (linewidth = 2) + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (linewidth = 2) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg new file mode 100644 index 00000000..4f040ad6 --- /dev/null +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +-0.10 +-0.05 +0.00 +0.05 +0.10 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF difference +ppc_loo_pit_ecdf (no help_text) + + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg index 8e1e5c79..6b0d9552 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg @@ -20,40 +20,40 @@ - - + + - - - - + + + + - -0.00 -0.25 -0.50 -0.75 -1.00 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -LOO PIT -ECDF -ppc_loo_pit_ecdf (prob) + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF +ppc_loo_pit_ecdf (prob) diff --git a/tests/vdiffr.Rout.fail b/tests/vdiffr.Rout.fail index 8bfa5ad3..e6a20ece 100644 --- a/tests/vdiffr.Rout.fail +++ b/tests/vdiffr.Rout.fail @@ -59853,3 +59853,83863 @@ Failed doppelganger: ppc-loo-pit-ecdf-color-change (/u/21/wa.bocktif1/unix/GitHu ,171.96 579.29,170.45 ' style='stroke-width: 2.35; stroke: #FF0000; stroke-lin ecap: butt;' /> + +Failed doppelganger: ppc-loo-pit-overlay-boundary (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.svg) + +< before +> after +@@ 26,105 / 26,105 @@ + + +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +< +> + + + + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) + +< before +> after +@@ 21,43 / 21,55 @@ + + +< +> +< +> + + +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< Uniformity p-value = 0.000 +> p +> u +> n +> i +> f +> = +> 0.000 +> +> ( +> α +> = +> 0.01 +> ) + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (correlated +: pot) +> ppc_loo_pit_ecdf (correlated +: pot) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-prit (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg) + +< before +> after +@@ 21,45 / 21,57 @@ + + +< +> +< +> + + +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< Uniformity p-value = 0.001 +> p +> u +> n +> i +> f +> = +> 0.001 +> +> ( +> α +> = +> 0.01 +> ) + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (correlated +: prit) +> ppc_loo_pit_ecdf (correlated +: prit) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-correlated-piet (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg) + +< before +> after +@@ 21,39 / 21,51 @@ + + +< +> +< +> + + +< +> +< +> +< +> +< Uniformity p-value = 0.188 +> p +> u +> n +> i +> f +> = +> 0.188 +> +> ( +> α +> = +> 0.01 +> ) + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (correlated +: piet) +> ppc_loo_pit_ecdf (correlated +: piet) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-pot (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg) + +< before +> after +@@ 21,43 / 21,55 @@ + + +< +> +< +> + + +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< Uniformity p-value = 0.000 +> p +> u +> n +> i +> f +> = +> 0.000 +> +> ( +> α +> = +> 0.01 +> ) + + +< +> +< -0.10 +> -0.10 +< -0.05 +> -0.05 +< 0.00 +> 0.00 +< 0.05 +> 0.05 +< 0.10 +> 0.10 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF difference +> ECDF difference +< ppc_loo_pit_ecdf (diff, corre +: lated pot) +> ppc_loo_pit_ecdf (diff, corre +: lated pot) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-prit (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg) + +< before +> after +@@ 21,45 / 21,57 @@ + + +< +> +< +> + + +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< Uniformity p-value = 0.001 +> p +> u +> n +> i +> f +> = +> 0.001 +> +> ( +> α +> = +> 0.01 +> ) + + +< +> +< -0.10 +> -0.10 +< -0.05 +> -0.05 +< 0.00 +> 0.00 +< 0.05 +> 0.05 +< 0.10 +> 0.10 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF difference +> ECDF difference +< ppc_loo_pit_ecdf (diff, corre +: lated prit) +> ppc_loo_pit_ecdf (diff, corre +: lated prit) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-piet (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg) + +< before +> after +@@ 21,39 / 21,51 @@ + + +< +> +< +> + + +< +> +< +> +< +> +< Uniformity p-value = 0.188 +> p +> u +> n +> i +> f +> = +> 0.188 +> +> ( +> α +> = +> 0.01 +> ) + + +< +> +< -0.10 +> -0.10 +< -0.05 +> -0.05 +< 0.00 +> 0.00 +< 0.05 +> 0.05 +< 0.10 +> 0.10 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF difference +> ECDF difference +< ppc_loo_pit_ecdf (diff, corre +: lated piet) +> ppc_loo_pit_ecdf (diff, corre +: lated piet) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-linewidth-1 (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg) + +< before +> after +@@ 21,43 / 21,55 @@ + + +< +> +< +> + + +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< Uniformity p-value = 0.000 +> p +> u +> n +> i +> f +> = +> 0.000 +> +> ( +> α +> = +> 0.01 +> ) + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (linewidth = +: 1) +> ppc_loo_pit_ecdf (linewidth = +: 1) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-linewidth-2 (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg) + +< before +> after +@@ 21,43 / 21,55 @@ + + +< +> +< +> + + +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< Uniformity p-value = 0.000 +> p +> u +> n +> i +> f +> = +> 0.000 +> +> ( +> α +> = +> 0.01 +> ) + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (linewidth = +: 2) +> ppc_loo_pit_ecdf (linewidth = +: 2) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-color-change (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg) + +< before +> after +@@ 21,43 / 21,55 @@ + + +< +> +< +> + + +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< Uniformity p-value = 0.000 +> p +> u +> n +> i +> f +> = +> 0.000 +> +> ( +> α +> = +> 0.01 +> ) + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (color chang +: e) +> ppc_loo_pit_ecdf (color chang +: e) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-default (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (default) +> ppc_loo_pit_ecdf (default) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-k (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (K) +> ppc_loo_pit_ecdf (K) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-prob (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg) + +< before +> after +@@ 21,39 / 21,39 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF +> ECDF +< ppc_loo_pit_ecdf (prob) +> ppc_loo_pit_ecdf (prob) + + + + +Failed doppelganger: ppc-loo-pit-ecdf-ecdf-difference (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg) + +< before +> after +@@ 21,35 / 21,35 @@ + + +< +> +< +> + + +< +> +< +< +< +> +> +> + + +< +> +< -0.1 +> -0.1 +< 0.0 +> 0.0 +< 0.1 +> 0.1 +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< +> +< 0.00 +> 0.00 +< 0.25 +> 0.25 +< 0.50 +> 0.50 +< 0.75 +> 0.75 +< 1.00 +> 1.00 +< LOO PIT +: +> LOO PIT +: +< ECDF difference +> ECDF difference +< ppc_loo_pit_ecdf (ecdf differ +: ence) +> ppc_loo_pit_ecdf (ecdf differ +: ence) + + + + +Failed doppelganger: ppc-loo-pit-overlay-boundary (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.svg) + +< before +> after +@@ 26,105 / 26,105 @@ + + +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +< +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +< +> + + + + +Failed doppelganger: ppc-loo-pit-ecdf-alpha-0-05 (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg) + +< before +> after +@@ 26,24 / 26,34 @@ + + +< +< +< +> +> +> +> +> p +> u +> n +> i +> f +> = +> 0.000 +> +> ( +> α +> = +> 0.05 +> ) + + + +< -0.15 +< -0.10 +> -0.10 +< -0.05 +> -0.05 +< 0.00 +> 0.00 +< 0.05 +> 0.05 +< 0.10 +> 0.10 +< 0.15 +< +< +< +> +< +> +< +> +< +> +< +> + + + + +Failed doppelganger: ppc-loo-pit-ecdf-no-help-text (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg) + +< before +> after +@@ 26,24 / 26,21 @@ + + +< +< +< +> +> +> +> + + + +< -0.15 +< -0.10 +> -0.10 +< -0.05 +> -0.05 +< 0.00 +> 0.00 +< 0.05 +> 0.05 +< 0.10 +> 0.10 +< 0.15 +< +< +< +> +< +> +< +> +< +> +< +> + + + From 916f998d9a69a56e4f9ff9141b0e9060f28a01ab Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Tue, 3 Mar 2026 08:13:30 +0200 Subject: [PATCH 067/120] update snapshots --- .../ppc-pit-ecdf-default.svg | 62 +++++++++---------- .../ppc-distributions/ppc-pit-ecdf-diff.svg | 58 ++++++++--------- .../ppc-loo/ppc-loo-pit-ecdf-default.svg | 4 +- .../ppc-loo-pit-ecdf-ecdf-difference.svg | 4 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg | 4 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg | 4 +- 6 files changed, 68 insertions(+), 68 deletions(-) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg index 8de07070..47bf9bab 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg @@ -20,40 +20,40 @@ - - + + - - - - + + + + - -0.00 -0.25 -0.50 -0.75 -1.00 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -PIT -ECDF -ppc_pit_ecdf (default) + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF +ppc_pit_ecdf (default) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg index 94693daf..1ff3a8fc 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg @@ -20,38 +20,38 @@ - - + + - - - - + + + + - --0.1 -0.0 -0.1 -0.2 - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -PIT -ECDF - difference -ppc_pit_ecdf (diff) + +-0.1 +0.0 +0.1 +0.2 + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF difference +ppc_pit_ecdf (diff) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg index 71e51c5e..9bdd3960 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg @@ -25,9 +25,9 @@ - - + + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg index cdf67834..5441468f 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg @@ -25,9 +25,9 @@ - - + + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg index 8e860dba..48f3cb24 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg @@ -25,9 +25,9 @@ - - + + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg index 6b0d9552..dadcb9e6 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg @@ -25,9 +25,9 @@ - - + + From bf8314c97938f740c212c7d09fed8766b203ffad Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Tue, 3 Mar 2026 08:21:10 +0200 Subject: [PATCH 068/120] add updated documentation --- man/PPC-loo.Rd | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/man/PPC-loo.Rd b/man/PPC-loo.Rd index aff3a8cc..c83114d4 100644 --- a/man/PPC-loo.Rd +++ b/man/PPC-loo.Rd @@ -70,7 +70,8 @@ ppc_loo_pit_ecdf( test = NULL, gamma = NULL, linewidth = NULL, - color = NULL + color = NULL, + help_text = NULL ) ppc_loo_pit( @@ -227,6 +228,9 @@ with base color and highlight color for the ECDF plot. Defaults to \code{c(ecdf = "gray60", highlight = "gray30")}. The first element is used for the main ECDF line, the second for highlighted suspicious regions.} +\item{help_text}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, a boolean +defining whether to add informative text to the plot. Defaults to \code{TRUE}.} + \item{subset}{For \code{ppc_loo_intervals()} and \code{ppc_loo_ribbon()}, an optional integer vector indicating which observations in \code{y} (and \code{yrep}) to include. Dropping observations from \code{y} and \code{yrep} manually before passing From 2314080e7d284a3e2ac2d9d84d643b6bebf887e9 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Tue, 3 Mar 2026 08:40:55 +0200 Subject: [PATCH 069/120] update snapshots for visual regression test --- .../ppc-pit-ecdf-default.svg | 62 +- .../ppc-distributions/ppc-pit-ecdf-diff.svg | 58 +- .../ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg | 29 +- .../ppc-loo/ppc-loo-pit-ecdf-color-change.svg | 26 +- .../ppc-loo-pit-ecdf-correlated-piet.svg | 26 +- .../ppc-loo-pit-ecdf-correlated-pot.svg | 26 +- .../ppc-loo-pit-ecdf-correlated-prit.svg | 26 +- .../ppc-loo/ppc-loo-pit-ecdf-default.svg | 4 +- .../ppc-loo-pit-ecdf-diff-correlated-piet.svg | 26 +- .../ppc-loo-pit-ecdf-diff-correlated-pot.svg | 26 +- .../ppc-loo-pit-ecdf-diff-correlated-prit.svg | 26 +- .../ppc-loo-pit-ecdf-ecdf-difference.svg | 4 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg | 4 +- .../ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg | 26 +- .../ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg | 26 +- .../ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg | 3 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg | 4 +- tests/vdiffr.Rout.fail | 143715 --------------- 18 files changed, 200 insertions(+), 143917 deletions(-) delete mode 100644 tests/vdiffr.Rout.fail diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg index 47bf9bab..8de07070 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg @@ -20,40 +20,40 @@ - - + + - - - - + + + + - -0.00 -0.25 -0.50 -0.75 -1.00 - - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -PIT -ECDF -ppc_pit_ecdf (default) + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF +ppc_pit_ecdf (default) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg index 1ff3a8fc..94693daf 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg @@ -20,38 +20,38 @@ - - + + - - - - + + + + - --0.1 -0.0 -0.1 -0.2 - - - - - - - - - - -0.00 -0.25 -0.50 -0.75 -1.00 -PIT -ECDF difference -ppc_pit_ecdf (diff) + +-0.1 +0.0 +0.1 +0.2 + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF - difference +ppc_pit_ecdf (diff) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg index 2640d048..1d588359 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg @@ -25,23 +25,22 @@ - + - -p -u -n -i -f -= -0.000 - -( -α -= -0.05 -) +p +u +n +i +f += +0.000 + +( +α += +0.05 +) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg index ae37137b..578e3ace 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg @@ -31,19 +31,19 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f += +0.000 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg index a0c8eafd..b498a227 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg @@ -27,19 +27,19 @@ -p -u -n -i -f -= -0.188 - -( -α -= -0.01 -) +p +u +n +i +f += +0.188 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg index d81ea6c0..cfb2571d 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg @@ -31,19 +31,19 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f += +0.000 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg index 3dea271a..364331c4 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg @@ -33,19 +33,19 @@ -p -u -n -i -f -= -0.001 - -( -α -= -0.01 -) +p +u +n +i +f += +0.001 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg index 9bdd3960..71e51c5e 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg @@ -25,9 +25,9 @@ + + - - diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg index 9f5604d5..2933f413 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg @@ -27,19 +27,19 @@ -p -u -n -i -f -= -0.188 - -( -α -= -0.01 -) +p +u +n +i +f += +0.188 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg index 84ed6e7c..07be187c 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg @@ -31,19 +31,19 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f += +0.000 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg index 61ea66db..6f67a728 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg @@ -33,19 +33,19 @@ -p -u -n -i -f -= -0.001 - -( -α -= -0.01 -) +p +u +n +i +f += +0.001 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg index 5441468f..cdf67834 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg @@ -25,9 +25,9 @@ + + - - diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg index 48f3cb24..8e860dba 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg @@ -25,9 +25,9 @@ + + - - diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg index d2214885..53cfd77d 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg @@ -31,19 +31,19 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f += +0.000 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg index 8512ff8e..462a1fec 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg @@ -31,19 +31,19 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f += +0.000 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg index 4f040ad6..84866363 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg @@ -25,10 +25,9 @@ - + - diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg index dadcb9e6..6b0d9552 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg @@ -25,9 +25,9 @@ + + - - diff --git a/tests/vdiffr.Rout.fail b/tests/vdiffr.Rout.fail deleted file mode 100644 index e6a20ece..00000000 --- a/tests/vdiffr.Rout.fail +++ /dev/null @@ -1,143715 +0,0 @@ -Environment: -- vdiffr-svg-engine: 2.0 -- vdiffr: 1.0.9 - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) - -< before -> after -@@ 58,5 / 58,5 @@ - LOO PIT - - ECDF -< ppc_loo_pit_ecdf (correlated- -: POT) -> ppc_loo_pit_ecdf (correlated -: pot) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-default (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (default) -> ppc_loo_pit_ecdf (default) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-k (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (K) -> ppc_loo_pit_ecdf (K) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-prob (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (prob) -> ppc_loo_pit_ecdf (prob) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-ecdf-difference (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg) - -< before -> after -@@ 21,35 / 21,35 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< -0.1 -> -0.1 -< 0.0 -> 0.0 -< 0.1 -> 0.1 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF difference -> ECDF difference -< ppc_loo_pit_ecdf (ecdf differ -: ence) -> ppc_loo_pit_ecdf (ecdf differ -: ence) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) - -< before -> after -@@ 58,5 / 58,5 @@ - LOO PIT - - ECDF -< ppc_loo_pit_ecdf (correlated- -: POT) -> ppc_loo_pit_ecdf (correlated -: pot) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-default (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (default) -> ppc_loo_pit_ecdf (default) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-k (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (K) -> ppc_loo_pit_ecdf (K) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-prob (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (prob) -> ppc_loo_pit_ecdf (prob) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-ecdf-difference (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg) - -< before -> after -@@ 21,35 / 21,35 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< -0.1 -> -0.1 -< 0.0 -> 0.0 -< 0.1 -> 0.1 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF difference -> ECDF difference -< ppc_loo_pit_ecdf (ecdf differ -: ence) -> ppc_loo_pit_ecdf (ecdf differ -: ence) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) - -< before -> after -@@ 58,5 / 58,5 @@ - LOO PIT - - ECDF -< ppc_loo_pit_ecdf (correlated- -: POT) -> ppc_loo_pit_ecdf (correlated -: pot) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-default (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (default) -> ppc_loo_pit_ecdf (default) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-k (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (K) -> ppc_loo_pit_ecdf (K) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-prob (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (prob) -> ppc_loo_pit_ecdf (prob) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-ecdf-difference (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg) - -< before -> after -@@ 21,35 / 21,35 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< -0.1 -> -0.1 -< 0.0 -> 0.0 -< 0.1 -> 0.1 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF difference -> ECDF difference -< ppc_loo_pit_ecdf (ecdf differ -: ence) -> ppc_loo_pit_ecdf (ecdf differ -: ence) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) - -< before -> after -@@ 58,5 / 58,5 @@ - LOO PIT - - ECDF -< ppc_loo_pit_ecdf (correlated- -: POT) -> ppc_loo_pit_ecdf (correlated -: pot) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-default (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (default) -> ppc_loo_pit_ecdf (default) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-k (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (K) -> ppc_loo_pit_ecdf (K) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-prob (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (prob) -> ppc_loo_pit_ecdf (prob) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-ecdf-difference (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg) - -< before -> after -@@ 21,35 / 21,35 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< -0.1 -> -0.1 -< 0.0 -> 0.0 -< 0.1 -> 0.1 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF difference -> ECDF difference -< ppc_loo_pit_ecdf (ecdf differ -: ence) -> ppc_loo_pit_ecdf (ecdf differ -: ence) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) - -< before -> after -@@ 58,5 / 58,5 @@ - LOO PIT - - ECDF -< ppc_loo_pit_ecdf (correlated- -: POT) -> ppc_loo_pit_ecdf (correlated -: pot) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-default (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (default) -> ppc_loo_pit_ecdf (default) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-k (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (K) -> ppc_loo_pit_ecdf (K) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-prob (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (prob) -> ppc_loo_pit_ecdf (prob) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-ecdf-difference (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg) - -< before -> after -@@ 21,35 / 21,35 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< -0.1 -> -0.1 -< 0.0 -> 0.0 -< 0.1 -> 0.1 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF difference -> ECDF difference -< ppc_loo_pit_ecdf (ecdf differ -: ence) -> ppc_loo_pit_ecdf (ecdf differ -: ence) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-default (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (default) -> ppc_loo_pit_ecdf (default) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-k (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (K) -> ppc_loo_pit_ecdf (K) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-prob (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (prob) -> ppc_loo_pit_ecdf (prob) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-ecdf-difference (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg) - -< before -> after -@@ 21,35 / 21,35 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< -0.1 -> -0.1 -< 0.0 -> 0.0 -< 0.1 -> 0.1 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF difference -> ECDF difference -< ppc_loo_pit_ecdf (ecdf differ -: ence) -> ppc_loo_pit_ecdf (ecdf differ -: ence) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) - -< before -> after -@@ 58,5 / 58,5 @@ - LOO PIT - - ECDF -< ppc_loo_pit_ecdf (correlated -: pot) -> Uniformity p-value = 0.000 - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-prit (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg) - -< before -> after -@@ 60,5 / 60,5 @@ - LOO PIT - - ECDF -< ppc_loo_pit_ecdf (correlated -: prit) -> Uniformity p-value = 0.001 - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-piet (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg) - -< before -> after -@@ 54,5 / 54,5 @@ - LOO PIT - - ECDF -< ppc_loo_pit_ecdf (correlated -: piet) -> Uniformity p-value = 0.188 - - - - -Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-pot (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg) - -< before -> after -@@ 56,5 / 56,5 @@ - LOO PIT - - ECDF difference -< ppc_loo_pit_ecdf (diff, corre -: lated pot) -> Uniformity p-value = 0.000 - - - - -Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-prit (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg) - -< before -> after -@@ 58,5 / 58,5 @@ - LOO PIT - - ECDF difference -< ppc_loo_pit_ecdf (diff, corre -: lated prit) -> Uniformity p-value = 0.001 - - - - -Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-piet (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg) - -< before -> after -@@ 52,5 / 52,5 @@ - LOO PIT - - ECDF difference -< ppc_loo_pit_ecdf (diff, corre -: lated piet) -> Uniformity p-value = 0.188 - - - - -Failed doppelganger: ppc-loo-pit-ecdf-linewidth-1 (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg) - -< before -> after -@@ 58,5 / 58,5 @@ - LOO PIT - - ECDF -< ppc_loo_pit_ecdf (linewidth = -: 1) -> Uniformity p-value = 0.000 - - - - -Failed doppelganger: ppc-loo-pit-ecdf-linewidth-2 (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg) - -< before -> after -@@ 58,5 / 58,5 @@ - LOO PIT - - ECDF -< ppc_loo_pit_ecdf (linewidth = -: 2) -> Uniformity p-value = 0.000 - - - - -Failed doppelganger: ppc-loo-pit-ecdf-color-change (C:\Users\flore\Documents\GitHub\bayesplot\tests\testthat\_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg) - -< before -> after -@@ 58,5 / 58,5 @@ - LOO PIT - - ECDF -< ppc_loo_pit_ecdf (color chang -: e) -> Uniformity p-value = 0.000 - - - - -Failed doppelganger: ppc-loo-pit-overlay-boundary (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.svg) - -< before -> after -@@ 26,105 / 26,105 @@ - - -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -< -> - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) - -< before -> after -@@ 26,10 / 26,11 @@ - - -< -> - -< -> -< -> -< -> -< -> -> Uniformity p-value = 0.000 - - -@@ 58,5 / 59,5 @@ - LOO PIT - - ECDF -< Uniformity p-value = 0.000 -> ppc_loo_pit_ecdf (correlated -: pot) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-prit (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg) - -< before -> after -@@ 26,12 / 26,13 @@ - - -< -> - -< -> -< -> -< -> -< -> -< -> -< -> -> Uniformity p-value = 0.001 - - -@@ 60,5 / 61,5 @@ - LOO PIT - - ECDF -< Uniformity p-value = 0.001 -> ppc_loo_pit_ecdf (correlated -: prit) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-piet (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg) - -< before -> after -@@ 26,6 / 26,7 @@ - - -< -> - -> Uniformity p-value = 0.188 - - -@@ 54,5 / 55,5 @@ - LOO PIT - - ECDF -< Uniformity p-value = 0.188 -> ppc_loo_pit_ecdf (correlated -: piet) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-pot (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg) - -< before -> after -@@ 26,21 / 26,24 @@ - - -< -> -< -> -< -> -< -> -< -> -< -> -> Uniformity p-value = 0.000 - - - -< -0.09 -> -0.10 -< -0.06 -> -0.05 -< -0.03 -> 0.00 -< 0.00 -> 0.05 -> 0.10 -< -> -< -> -< -> -< -> -> - - -@@ 56,5 / 59,5 @@ - LOO PIT - - ECDF difference -< Uniformity p-value = 0.000 -> ppc_loo_pit_ecdf (diff, corre -: lated pot) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-prit (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg) - -< before -> after -@@ 26,23 / 26,26 @@ - - -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -> Uniformity p-value = 0.001 - - - -< -0.09 -> -0.10 -< -0.06 -> -0.05 -< -0.03 -> 0.00 -< 0.00 -> 0.05 -> 0.10 -< -> -< -> -< -> -< -> -> - - -@@ 58,5 / 61,5 @@ - LOO PIT - - ECDF difference -< Uniformity p-value = 0.001 -> ppc_loo_pit_ecdf (diff, corre -: lated prit) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-piet (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg) - -< before -> after -@@ 26,17 / 26,20 @@ - - -< -> -< -> -> Uniformity p-value = 0.188 - - - -< -0.09 -> -0.10 -< -0.06 -> -0.05 -< -0.03 -> 0.00 -< 0.00 -> 0.05 -> 0.10 -< -> -< -> -< -> -< -> -> - - -@@ 52,5 / 55,5 @@ - LOO PIT - - ECDF difference -< Uniformity p-value = 0.188 -> ppc_loo_pit_ecdf (diff, corre -: lated piet) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-linewidth-1 (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg) - -< before -> after -@@ 26,10 / 26,11 @@ - - -< -> - -< -> -< -> -< -> -< -> -> Uniformity p-value = 0.000 - - -@@ 58,5 / 59,5 @@ - LOO PIT - - ECDF -< Uniformity p-value = 0.000 -> ppc_loo_pit_ecdf (linewidth = -: 1) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-linewidth-2 (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg) - -< before -> after -@@ 26,10 / 26,11 @@ - - -< -> - -< -> -< -> -< -> -< -> -> Uniformity p-value = 0.000 - - -@@ 58,5 / 59,5 @@ - LOO PIT - - ECDF -< Uniformity p-value = 0.000 -> ppc_loo_pit_ecdf (linewidth = -: 2) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-color-change (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg) - -< before -> after -@@ 32,4 / 32,5 @@ - - -> Uniformity p-value = 0.000 - - -@@ 58,5 / 59,5 @@ - LOO PIT - - ECDF -< Uniformity p-value = 0.000 -> ppc_loo_pit_ecdf (color chang -: e) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) - -< before -> after -@@ 27,5 / 27,5 @@ - - -< -> - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-prit (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg) - -< before -> after -@@ 27,5 / 27,5 @@ - - -< -> - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-piet (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg) - -< before -> after -@@ 27,5 / 27,5 @@ - - -< -> - Uniformity p-value = 0.188 - - - -Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-pot (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg) - -< before -> after -@@ 27,5 / 27,5 @@ - - -< -> - - - - -Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-prit (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg) - -< before -> after -@@ 27,5 / 27,5 @@ - - -< -> - - - - -Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-piet (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg) - -< before -> after -@@ 27,5 / 27,5 @@ - - -< -> - Uniformity p-value = 0.188 - - - -Failed doppelganger: ppc-loo-pit-ecdf-linewidth-1 (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg) - -< before -> after -@@ 27,5 / 27,5 @@ - - -< -> - - - - -Failed doppelganger: ppc-loo-pit-ecdf-linewidth-2 (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg) - -< before -> after -@@ 27,5 / 27,5 @@ - - -< -> - - - - -Failed doppelganger: ppc-loo-pit-ecdf-color-change (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg) - -< before -> after -@@ 27,5 / 27,5 @@ - - -< -> - - - - -Failed doppelganger: ppc-loo-pit-overlay-boundary (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.svg) - -< before -> after -@@ 26,105 / 26,105 @@ - - -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -< -> - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-pot (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg) - -< before -> after -@@ 21,43 / 21,55 @@ - - -< -> -< -> - - -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< Uniformity p-value = 0.000 -> p -> u -> n -> i -> f -> = -> 0.000 -> -> ( -> α -> = -> 0.01 -> ) - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (correlated -: pot) -> ppc_loo_pit_ecdf (correlated -: pot) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-prit (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg) - -< before -> after -@@ 21,45 / 21,57 @@ - - -< -> -< -> - - -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< Uniformity p-value = 0.001 -> p -> u -> n -> i -> f -> = -> 0.001 -> -> ( -> α -> = -> 0.01 -> ) - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (correlated -: prit) -> ppc_loo_pit_ecdf (correlated -: prit) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-correlated-piet (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg) - -< before -> after -@@ 21,39 / 21,51 @@ - - -< -> -< -> - - -< -> -< -> -< -> -< Uniformity p-value = 0.188 -> p -> u -> n -> i -> f -> = -> 0.188 -> -> ( -> α -> = -> 0.01 -> ) - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (correlated -: piet) -> ppc_loo_pit_ecdf (correlated -: piet) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-pot (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg) - -< before -> after -@@ 21,43 / 21,55 @@ - - -< -> -< -> - - -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< Uniformity p-value = 0.000 -> p -> u -> n -> i -> f -> = -> 0.000 -> -> ( -> α -> = -> 0.01 -> ) - - -< -> -< -0.10 -> -0.10 -< -0.05 -> -0.05 -< 0.00 -> 0.00 -< 0.05 -> 0.05 -< 0.10 -> 0.10 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF difference -> ECDF difference -< ppc_loo_pit_ecdf (diff, corre -: lated pot) -> ppc_loo_pit_ecdf (diff, corre -: lated pot) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-prit (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg) - -< before -> after -@@ 21,45 / 21,57 @@ - - -< -> -< -> - - -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< Uniformity p-value = 0.001 -> p -> u -> n -> i -> f -> = -> 0.001 -> -> ( -> α -> = -> 0.01 -> ) - - -< -> -< -0.10 -> -0.10 -< -0.05 -> -0.05 -< 0.00 -> 0.00 -< 0.05 -> 0.05 -< 0.10 -> 0.10 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF difference -> ECDF difference -< ppc_loo_pit_ecdf (diff, corre -: lated prit) -> ppc_loo_pit_ecdf (diff, corre -: lated prit) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-diff-correlated-piet (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg) - -< before -> after -@@ 21,39 / 21,51 @@ - - -< -> -< -> - - -< -> -< -> -< -> -< Uniformity p-value = 0.188 -> p -> u -> n -> i -> f -> = -> 0.188 -> -> ( -> α -> = -> 0.01 -> ) - - -< -> -< -0.10 -> -0.10 -< -0.05 -> -0.05 -< 0.00 -> 0.00 -< 0.05 -> 0.05 -< 0.10 -> 0.10 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF difference -> ECDF difference -< ppc_loo_pit_ecdf (diff, corre -: lated piet) -> ppc_loo_pit_ecdf (diff, corre -: lated piet) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-linewidth-1 (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg) - -< before -> after -@@ 21,43 / 21,55 @@ - - -< -> -< -> - - -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< Uniformity p-value = 0.000 -> p -> u -> n -> i -> f -> = -> 0.000 -> -> ( -> α -> = -> 0.01 -> ) - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (linewidth = -: 1) -> ppc_loo_pit_ecdf (linewidth = -: 1) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-linewidth-2 (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg) - -< before -> after -@@ 21,43 / 21,55 @@ - - -< -> -< -> - - -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< Uniformity p-value = 0.000 -> p -> u -> n -> i -> f -> = -> 0.000 -> -> ( -> α -> = -> 0.01 -> ) - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (linewidth = -: 2) -> ppc_loo_pit_ecdf (linewidth = -: 2) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-color-change (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg) - -< before -> after -@@ 21,43 / 21,55 @@ - - -< -> -< -> - - -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< Uniformity p-value = 0.000 -> p -> u -> n -> i -> f -> = -> 0.000 -> -> ( -> α -> = -> 0.01 -> ) - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (color chang -: e) -> ppc_loo_pit_ecdf (color chang -: e) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-default (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (default) -> ppc_loo_pit_ecdf (default) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-k (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (K) -> ppc_loo_pit_ecdf (K) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-prob (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg) - -< before -> after -@@ 21,39 / 21,39 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF -> ECDF -< ppc_loo_pit_ecdf (prob) -> ppc_loo_pit_ecdf (prob) - - - - -Failed doppelganger: ppc-loo-pit-ecdf-ecdf-difference (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg) - -< before -> after -@@ 21,35 / 21,35 @@ - - -< -> -< -> - - -< -> -< -< -< -> -> -> - - -< -> -< -0.1 -> -0.1 -< 0.0 -> 0.0 -< 0.1 -> 0.1 -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< -> -< 0.00 -> 0.00 -< 0.25 -> 0.25 -< 0.50 -> 0.50 -< 0.75 -> 0.75 -< 1.00 -> 1.00 -< LOO PIT -: -> LOO PIT -: -< ECDF difference -> ECDF difference -< ppc_loo_pit_ecdf (ecdf differ -: ence) -> ppc_loo_pit_ecdf (ecdf differ -: ence) - - - - -Failed doppelganger: ppc-loo-pit-overlay-boundary (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.svg) - -< before -> after -@@ 26,105 / 26,105 @@ - - -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -< -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -< -> - - - - -Failed doppelganger: ppc-loo-pit-ecdf-alpha-0-05 (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg) - -< before -> after -@@ 26,24 / 26,34 @@ - - -< -< -< -> -> -> -> -> p -> u -> n -> i -> f -> = -> 0.000 -> -> ( -> α -> = -> 0.05 -> ) - - - -< -0.15 -< -0.10 -> -0.10 -< -0.05 -> -0.05 -< 0.00 -> 0.00 -< 0.05 -> 0.05 -< 0.10 -> 0.10 -< 0.15 -< -< -< -> -< -> -< -> -< -> -< -> - - - - -Failed doppelganger: ppc-loo-pit-ecdf-no-help-text (/u/21/wa.bocktif1/unix/GitHub/bayesplot-private/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg) - -< before -> after -@@ 26,24 / 26,21 @@ - - -< -< -< -> -> -> -> - - - -< -0.15 -< -0.10 -> -0.10 -< -0.05 -> -0.05 -< 0.00 -> 0.00 -< 0.05 -> 0.05 -< 0.10 -> 0.10 -< 0.15 -< -< -< -> -< -> -< -> -< -> -< -> - - - From fccc4b5ee73b18b5d79695489320b0900b6e6913 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Tue, 3 Mar 2026 08:54:43 +0200 Subject: [PATCH 070/120] fix function call in tests --- tests/testthat/test-ppc-loo.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-ppc-loo.R b/tests/testthat/test-ppc-loo.R index c69d85ce..147a2c08 100644 --- a/tests/testthat/test-ppc-loo.R +++ b/tests/testthat/test-ppc-loo.R @@ -531,7 +531,7 @@ test_that("ppc_loo_pit_ecdf renders correctly", { vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (no help_text)", p_custom) - setheme_set(bayesplot::theme_default(base_family = "sans", base_size = 12)) + theme_set(bayesplot::theme_default(base_family = "sans", base_size = 12)) p_custom <- ppc_loo_pit_ecdf( vdiff_loo_y, vdiff_loo_yrep, From 23e76298ef3f19cc213cc7347918519b04f40ce5 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Tue, 3 Mar 2026 09:38:06 +0200 Subject: [PATCH 071/120] update snapshots --- .../ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg | 3 +- .../ppc-loo-pit-ecdf-changed-theme.svg | 69 +++++++++++++++++++ .../ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg | 3 +- 3 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg index 1d588359..b498afa0 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg @@ -25,9 +25,10 @@ - + + p u n diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg new file mode 100644 index 00000000..dd2bdb5e --- /dev/null +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.01 +) + + + +-0.1 +0.0 +0.1 + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +LOO PIT +ECDF difference +ppc_loo_pit_ecdf (changed theme) + + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg index 84866363..4f040ad6 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg @@ -25,9 +25,10 @@ - + + From cf491d5bc2dcf70fca9c3a7edc92996051a0735d Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Tue, 3 Mar 2026 10:31:01 +0200 Subject: [PATCH 072/120] update default colors in description --- R/ppc-loo.R | 2 +- man/PPC-loo.Rd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 0e620632..4884cb4a 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -415,7 +415,7 @@ ppc_loo_pit_qq <- function(y, #' determined based on p-value. #' @param color For `ppc_loo_pit_ecdf()` when `method = "correlated"`, a vector #' with base color and highlight color for the ECDF plot. Defaults to -#' `c(ecdf = "gray60", highlight = "gray30")`. The first element is used for +#' `c(ecdf = "black", highlight = "red")`. The first element is used for #' the main ECDF line, the second for highlighted suspicious regions. #' @param help_text For `ppc_loo_pit_ecdf()` when `method = "correlated"`, a boolean #' defining whether to add informative text to the plot. Defaults to `TRUE`. diff --git a/man/PPC-loo.Rd b/man/PPC-loo.Rd index c83114d4..1367d3fc 100644 --- a/man/PPC-loo.Rd +++ b/man/PPC-loo.Rd @@ -225,7 +225,7 @@ determined based on p-value.} \item{color}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, a vector with base color and highlight color for the ECDF plot. Defaults to -\code{c(ecdf = "gray60", highlight = "gray30")}. The first element is used for +\code{c(ecdf = "black", highlight = "red")}. The first element is used for the main ECDF line, the second for highlighted suspicious regions.} \item{help_text}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, a boolean From 8c3cbf9510ee08eb9d231cfdf2a16fb632660827 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Tue, 3 Mar 2026 13:34:26 +0200 Subject: [PATCH 073/120] update gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 091a639c..074cf4d9 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,5 @@ vignettes/*.quarto vignettes/*.html # draft vignette -ppc_loo_pit.Rmd \ No newline at end of file +ppc_loo_pit.Rmd +test_greyscale.qmd \ No newline at end of file From 9f054bf48fba9f93fa386d5b2c10664d3d6d69b0 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Tue, 3 Mar 2026 13:35:09 +0200 Subject: [PATCH 074/120] update default color from black to grey60 --- R/ppc-loo.R | 4 ++-- man/PPC-loo.Rd | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 4884cb4a..4afa9d4a 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -415,7 +415,7 @@ ppc_loo_pit_qq <- function(y, #' determined based on p-value. #' @param color For `ppc_loo_pit_ecdf()` when `method = "correlated"`, a vector #' with base color and highlight color for the ECDF plot. Defaults to -#' `c(ecdf = "black", highlight = "red")`. The first element is used for +#' `c(ecdf = "grey60", highlight = "red")`. The first element is used for #' the main ECDF line, the second for highlighted suspicious regions. #' @param help_text For `ppc_loo_pit_ecdf()` when `method = "correlated"`, a boolean #' defining whether to add informative text to the plot. Defaults to `TRUE`. @@ -513,7 +513,7 @@ ppc_loo_pit_ecdf <- function(y, alpha <- 1 - prob gamma <- gamma %||% 0 linewidth <- linewidth %||% 0.3 - color <- color %||% c(ecdf = "black", highlight = "red") + color <- color %||% c(ecdf = "grey60", highlight = "red") help_text <- help_text %||% TRUE }, diff --git a/man/PPC-loo.Rd b/man/PPC-loo.Rd index 1367d3fc..cd1bb767 100644 --- a/man/PPC-loo.Rd +++ b/man/PPC-loo.Rd @@ -225,7 +225,7 @@ determined based on p-value.} \item{color}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, a vector with base color and highlight color for the ECDF plot. Defaults to -\code{c(ecdf = "black", highlight = "red")}. The first element is used for +\code{c(ecdf = "grey60", highlight = "red")}. The first element is used for the main ECDF line, the second for highlighted suspicious regions.} \item{help_text}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, a boolean From 65acdcbde6aacb9110321c38b0db28ad4e4b3244 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Wed, 4 Mar 2026 10:21:44 +0200 Subject: [PATCH 075/120] update gitignore --- .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 074cf4d9..96a6e51a 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,8 @@ vignettes/*.html # draft vignette ppc_loo_pit.Rmd -test_greyscale.qmd \ No newline at end of file +test_greyscale.qmd +vignettes/.gitignore + +# visual regression test +tests/vdiffr.Rout.fail \ No newline at end of file From 4fd02e146eae357b1979eced56ed2f1384d693ee Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Wed, 4 Mar 2026 10:22:10 +0200 Subject: [PATCH 076/120] update theme for ppc_loo_pit_ecdf --- R/ppc-loo.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 4afa9d4a..994f1526 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -699,7 +699,7 @@ ppc_loo_pit_ecdf <- function(y, ) + yaxis_ticks(FALSE) + scale_color_ppc() + - bayesplot::theme_default(base_family = "sans") + bayesplot_theme_get() return(p) } From 8d2f2ff125c645585c71eb216f04692c49a4fda4 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Wed, 4 Mar 2026 10:22:24 +0200 Subject: [PATCH 077/120] update snapshots for regression test --- tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg | 2 +- .../testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg | 2 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg | 2 +- .../testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg | 2 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg | 2 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg | 2 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg | 2 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg | 2 +- tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg | 2 +- tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg | 2 +- tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg index b498afa0..2ad02eff 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg @@ -25,7 +25,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg index dd2bdb5e..f5e8438f 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg @@ -25,7 +25,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg index b498a227..d6c38358 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg @@ -25,7 +25,7 @@ - + p u diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg index cfb2571d..bf9ed31e 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg @@ -25,7 +25,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg index 364331c4..02eedb80 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg @@ -25,7 +25,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg index 2933f413..e123b73f 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg @@ -25,7 +25,7 @@ - + p u diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg index 07be187c..dce93313 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg @@ -25,7 +25,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg index 6f67a728..9617b002 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg @@ -25,7 +25,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg index 53cfd77d..0475f139 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg @@ -25,7 +25,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg index 462a1fec..0f0a588e 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg @@ -25,7 +25,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg index 4f040ad6..8afea555 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg @@ -25,7 +25,7 @@ - + From 237daba10bacdbc9481b8fc09132b237dbe54005 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Wed, 4 Mar 2026 10:27:21 +0200 Subject: [PATCH 078/120] udpate theme for correlated method --- R/ppc-loo.R | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 994f1526..2add4c35 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -637,11 +637,6 @@ ppc_loo_pit_ecdf <- function(y, } # Apply bayesplot theme and styling - p <- p + - yaxis_ticks(FALSE) + - scale_color_ppc() + - bayesplot::theme_default(base_family = "sans") - if (help_text) { p <- p + annotate( "text", @@ -661,6 +656,11 @@ ppc_loo_pit_ecdf <- function(y, p <- p + scale_y_continuous(limits = c(-epsilon, epsilon)) } + p <- p + + yaxis_ticks(FALSE) + + scale_color_ppc() + + bayesplot_theme_get() + return(p) } From 73f04e7a080d38ab83712cfeed1a4001ac531f1c Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Wed, 4 Mar 2026 12:19:49 +0200 Subject: [PATCH 079/120] update gitignore --- .gitignore | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c02b505b..1e896959 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,15 @@ release-prep.R .vscode/* # ignore draft vignette -vignettes/ppc_loo_pit.Rmd \ No newline at end of file +vignettes/ppc_loo_pit.Rmd +vignettes/test_greyscale.qmd + +# internal knitting of vignettes +*_cache +*_files +vignettes/*.quarto +vignettes/*.html +vignettes/.gitignore + +# visual regression test +tests/vdiffr.Rout.fail \ No newline at end of file From f14ac9cdd85ea21d5ed9c3569ae80c469eca695c Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Wed, 4 Mar 2026 12:20:48 +0200 Subject: [PATCH 080/120] update ppc_pit_ecdf to match changes in ppc_loo_pit_ecdf --- R/ppc-distributions.R | 85 +++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/R/ppc-distributions.R b/R/ppc-distributions.R index 3bf754bc..7d4c9c7f 100644 --- a/R/ppc-distributions.R +++ b/R/ppc-distributions.R @@ -667,8 +667,10 @@ ppc_violin_grouped <- #' determined based on p-value. #' @param color For `ppc_loo_pit_ecdf()` when `method = "correlated"`, a vector #' with base color and highlight color for the ECDF plot. Defaults to -#' `c(ecdf = "black", highlight = "red")`. The first element is used for +#' `c(ecdf = "grey60", highlight = "red")`. The first element is used for #' the main ECDF line, the second for highlighted suspicious regions. +#' @param help_text For 'ppc_pit_ecdf()' when `method = "correlated"`, a boolean +#' defining whether to add informative text to the plot. Defaults to `TRUE`. #' @rdname PPC-distributions #' ppc_pit_ecdf <- function(y, @@ -683,11 +685,12 @@ ppc_pit_ecdf <- function(y, test = NULL, gamma = NULL, linewidth = NULL, - color = NULL + color = NULL, + help_text = NULL ) { check_ignored_arguments(..., ok_args = c("K", "pit", "prob", "plot_diff", "interpolate_adj", - "method", "test", "gamma", "linewidth", "color") + "method", "test", "gamma", "linewidth", "color", "help_text") ) method <- match.arg(method, choices = c("independent", "correlated")) @@ -698,23 +701,6 @@ ppc_pit_ecdf <- function(y, inform(msg) } - switch(method, - "correlated" = { - if (!is.null(interpolate_adj)) .warn_ignored("'correlated'", "interpolate_adj") - test <- match.arg(test %||% "POT", choices = c("POT", "PRIT", "PIET")) - alpha <- 1 - prob - gamma <- gamma %||% 0 - linewidth <- linewidth %||% 0.3 - color <- color %||% c(ecdf = "black", highlight = "red") - }, - "independent" = { - ignored <- character(0) - if (!is.null(test)) ignored <- c(ignored, "test") - if (!is.null(gamma)) ignored <- c(ignored, "gamma") - if (length(ignored) > 0) .warn_ignored("'independent'", ignored) - } - ) - if (is.null(pit)) { pit <- ppc_data(y, yrep) %>% group_by(.data$y_id) %>% @@ -727,13 +713,38 @@ ppc_pit_ecdf <- function(y, K <- min(nrow(yrep) + 1, 1000) } } else { - inform("'pit' specified so ignoring 'y', and 'yrep' if specified.") pit <- validate_pit(pit) if (is.null(K)) { K <- length(pit) } + ignored <- character(0) + if (!missing(y) && !is.null(y)) ignored <- c(ignored, "y") + if (!missing(yrep) && !is.null(yrep)) ignored <- c(ignored, "yrep") + if (length(ignored) > 0) { + inform(paste0("As 'pit' specified; ignoring: ", paste(ignored, collapse = ", "), ".")) + } } + # input validation and setting of defaults dependent on method + switch(method, + "correlated" = { + if (!is.null(interpolate_adj)) .warn_ignored("'correlated'", "interpolate_adj") + test <- match.arg(test %||% "POT", choices = c("POT", "PRIT", "PIET")) + alpha <- 1 - prob + gamma <- gamma %||% 0 + linewidth <- linewidth %||% 0.3 + color <- color %||% c(ecdf = "grey60", highlight = "red") + help_text <- help_text %||% TRUE + }, + "independent" = { + ignored <- character(0) + if (!is.null(test)) ignored <- c(ignored, "test") + if (!is.null(gamma)) ignored <- c(ignored, "gamma") + if (!is.null(help_text)) ignored <- c(ignored, "help_text") + if (length(ignored) > 0) .warn_ignored("'independent'", ignored) + } + ) + n_obs <- length(pit) unit_interval <- seq(0, 1, length.out = K) .ecdf_pit_fn <- ecdf(pit) @@ -791,7 +802,7 @@ ppc_pit_ecdf <- function(y, x = 0, y = 0, xend = 1, yend = dplyr::if_else(plot_diff, 0, 1) ), - linetype = 2, color = "darkgrey" + linetype = "dashed", color = "darkgrey", linewidth = 0.3 ) # Identify and highlight suspecious points (regions) of the ECDF @@ -845,27 +856,29 @@ ppc_pit_ecdf <- function(y, } # Apply bayesplot theme and styling - p <- p + - yaxis_ticks(FALSE) + - scale_color_ppc() + - annotate( + if (help_text) { + p <- p + annotate( "text", x = -Inf, y = Inf, - label = sprintf("Uniformity p-value = %.3f", p_value_CCT), - hjust = -0.1, vjust = 1.5, - size = 6, color = "black" - ) + - bayesplot::theme_default(base_family = "sans", base_size = 16) - + label = sprintf("p[unif] == '%.3f' ~ (alpha == '%.2f')", p_value_CCT, alpha), + hjust = -0.05, vjust = 1.5, color = "black", + parse = TRUE, size = 0.7 * bayesplot_theme_get()$text@size / ggplot2::.pt + ) + } + if (plot_diff) { epsilon = max( sqrt(log(2 / (1 - prob)) / (2 * length(pit))), max(abs(df_main$ecdf_pit)) ) - p <- p + scale_y_continuous(limits = c(-epsilon, epsilon)) } + p <- p + + yaxis_ticks(FALSE) + + scale_color_ppc() + + bayesplot_theme_get() + return(p) } @@ -886,11 +899,11 @@ ppc_pit_ecdf <- function(y, p <- ggplot() + geom_step( aes(x = unit_interval, y = lims_upper_scaled, color = "yrep"), - linetype = 2, show.legend = FALSE + linetype = "dashed", linewidth = 0.3, show.legend = FALSE ) + geom_step( aes(x = unit_interval, y = lims_lower_scaled, color = "yrep"), - linetype = 2, show.legend = FALSE + linetype = "dashed", linewidth = 0.3, show.legend = FALSE ) + geom_step( aes(x = unit_interval, y = ecdf_eval, color = "y", linewidth = linewidth), @@ -902,7 +915,7 @@ ppc_pit_ecdf <- function(y, ) + yaxis_ticks(FALSE) + scale_color_ppc() + - bayesplot::theme_default(base_family = "sans", base_size = 16) + bayesplot_theme_get() return(p) } From 3b28269a304c7a0fa065489cfbf8893ceb66dfe4 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Wed, 4 Mar 2026 12:21:16 +0200 Subject: [PATCH 081/120] update unittests for ppc_pit_ecdf --- tests/testthat/test-ppc-distributions.R | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/testthat/test-ppc-distributions.R b/tests/testthat/test-ppc-distributions.R index 28cc589f..1f436a40 100644 --- a/tests/testthat/test-ppc-distributions.R +++ b/tests/testthat/test-ppc-distributions.R @@ -116,13 +116,10 @@ test_that("ppc_pit_ecdf, ppc_pit_ecdf_grouped returns a ggplot object", { expect_gg(ppc_pit_ecdf(y, yrep, method = "correlated", test = "PIET")) # Specify 'pit' directly - expect_message(ppc_pit_ecdf(pit = runif(100)), "'pit' specified") expect_message( ppc_pit_ecdf_grouped(pit = runif(length(group)), group = group, interpolate_adj = FALSE), "'pit' specified" ) - expect_message(ppc_pit_ecdf(pit = runif(100), method = "correlated"), - "'pit' specified") }) test_that("ppc_pit_ecdf method validation and ignored-argument warnings", { From 7e7d0fdd11eca8f590c5af91a64218aa0970aff9 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Wed, 4 Mar 2026 12:21:41 +0200 Subject: [PATCH 082/120] add new snapshots for visual regression tests --- .../ppc-pit-ecdf-correlated-diff.svg | 68 ++++++++++++++++++ .../ppc-pit-ecdf-correlated-piet.svg | 72 +++++++++++++++++++ .../ppc-pit-ecdf-correlated-prit.svg | 72 +++++++++++++++++++ .../ppc-pit-ecdf-correlated.svg | 72 +++++++++++++++++++ .../ppc-pit-ecdf-default.svg | 4 +- .../ppc-distributions/ppc-pit-ecdf-diff.svg | 6 +- 6 files changed, 289 insertions(+), 5 deletions(-) create mode 100644 tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-diff.svg create mode 100644 tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet.svg create mode 100644 tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit.svg create mode 100644 tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated.svg diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-diff.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-diff.svg new file mode 100644 index 00000000..dc6a6a75 --- /dev/null +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-diff.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.01 +) + + + +-0.1 +0.0 +0.1 + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF difference +ppc_pit_ecdf (correlated diff) + + diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet.svg new file mode 100644 index 00000000..8a4f3bd2 --- /dev/null +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.01 +) + + + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF +ppc_pit_ecdf (correlated PIET) + + diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit.svg new file mode 100644 index 00000000..b04839b4 --- /dev/null +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.01 +) + + + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF +ppc_pit_ecdf (correlated PRIT) + + diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated.svg new file mode 100644 index 00000000..5e7efdfe --- /dev/null +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.01 +) + + + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF +ppc_pit_ecdf (correlated) + + diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg index 8de07070..f3b71ce0 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg @@ -25,9 +25,9 @@ + + - - diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg index 94693daf..472e39ef 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg @@ -25,9 +25,9 @@ + + - - @@ -51,7 +51,7 @@ 0.75 1.00 PIT -ECDF - difference +ECDF difference ppc_pit_ecdf (diff) From 0a7726bb2745538b46150a9c8b5ef60dbc9cee0a Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Wed, 4 Mar 2026 12:51:36 +0200 Subject: [PATCH 083/120] update documentation for ppc_pit_ecdf --- man/PPC-distributions.Rd | 43 ++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/man/PPC-distributions.Rd b/man/PPC-distributions.Rd index c31242e8..d875e368 100644 --- a/man/PPC-distributions.Rd +++ b/man/PPC-distributions.Rd @@ -131,7 +131,13 @@ ppc_pit_ecdf( K = NULL, prob = 0.99, plot_diff = FALSE, - interpolate_adj = NULL + interpolate_adj = NULL, + method = "independent", + test = NULL, + gamma = NULL, + linewidth = NULL, + color = NULL, + help_text = NULL ) ppc_pit_ecdf_grouped( @@ -239,11 +245,36 @@ values rather than plotting the regular ECDF. The default is \code{FALSE}, but for large samples we recommend setting \code{plot_diff=TRUE} as the difference plot will visually show a more dynamic range.} -\item{interpolate_adj}{A boolean defining if the simultaneous confidence -bands should be interpolated based on precomputed values rather than -computed exactly. Computing the bands may be computationally intensive and -the approximation gives a fast method for assessing the ECDF trajectory. -The default is to use interpolation if \code{K} is greater than 200.} +\item{interpolate_adj}{For \code{ppc_loo_pit_ecdf()} when \code{method = "independent"}, +a boolean defining if the simultaneous confidence bands should be +interpolated based on precomputed values rather than computed exactly. +Computing the bands may be computationally intensive and the approximation +gives a fast method for assessing the ECDF trajectory. The default is to use +interpolation if \code{K} is greater than 200.} + +\item{method}{For \code{ppc_loo_pit_ecdf()}, the method used to calculate the +uniformity test: +\itemize{ +\item \code{"independent"}: (default) Assumes independence (Säilynoja et al., 2022). +\item \code{"correlated"}: Accounts for correlation (Tesso & Vehtari, 2026). +}} + +\item{test}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, which +dependence-aware test to use: \code{"POT"}, \code{"PRIT"}, or \code{"PIET"}. +Defaults to \code{"POT"}.} + +\item{gamma}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, tolerance +threshold controlling how strongly suspicious points are flagged. Larger +values (gamma > 0) emphasizes points with larger deviations. If \code{NULL}, automatically +determined based on p-value.} + +\item{color}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, a vector +with base color and highlight color for the ECDF plot. Defaults to +\code{c(ecdf = "grey60", highlight = "red")}. The first element is used for +the main ECDF line, the second for highlighted suspicious regions.} + +\item{help_text}{For 'ppc_pit_ecdf()' when \code{method = "correlated"}, a boolean +defining whether to add informative text to the plot. Defaults to \code{TRUE}.} } \value{ The plotting functions return a ggplot object that can be further From d20319a5f3f9a2e826e029cf63a82323fa670e8b Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Wed, 4 Mar 2026 12:51:56 +0200 Subject: [PATCH 084/120] add further visual regression tests --- tests/testthat/test-ppc-distributions.R | 79 +++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/tests/testthat/test-ppc-distributions.R b/tests/testthat/test-ppc-distributions.R index 1f436a40..479de62e 100644 --- a/tests/testthat/test-ppc-distributions.R +++ b/tests/testthat/test-ppc-distributions.R @@ -479,4 +479,83 @@ test_that("ppc_pit_ecdf, ppc_pit_ecdf_grouped renders correctly", { p_corr_piet <- ppc_pit_ecdf(y, yrep, method = "correlated", test = "PIET") vdiffr::expect_doppelganger("ppc_pit_ecdf (correlated PIET)", p_corr_piet) +}) + +test_that("ppc_pit_ecdf with method correlated renders different tests correctly", { + set.seed(2025) + pit <- 1 - (1 - runif(300))^(1.2) + + p_cor_pot <- ppc_pit_ecdf( + pit = pit, + method = "correlated" + ) + vdiffr::expect_doppelganger("ppc_pit_ecdf (correlated pot)", p_cor_pot) + + p_cor_prit <- ppc_pit_ecdf( + pit = pit, + method = "correlated", + test = "PRIT" + ) + vdiffr::expect_doppelganger("ppc_pit_ecdf (correlated prit 2)", p_cor_prit) + + p_cor_piet <- ppc_pit_ecdf( + pit = pit, + method = "correlated", + test = "PIET" + ) + vdiffr::expect_doppelganger("ppc_pit_ecdf (correlated piet)", p_cor_piet) +}) + +test_that("ppc_pit_ecdf with plot_diff=TRUE and method correlated renders different tests correctly", { + set.seed(2025) + pit <- 1 - (1 - runif(300))^(1.2) + + p_cor_pot <- ppc_pit_ecdf( + pit = pit, + method = "correlated", + plot_diff = TRUE + ) + vdiffr::expect_doppelganger("ppc_pit_ecdf (diff, correlated pot)", p_cor_pot) + + p_cor_prit <- ppc_pit_ecdf( + pit = pit, + method = "correlated", + test = "PRIT", + plot_diff = TRUE + ) + vdiffr::expect_doppelganger("ppc_pit_ecdf (diff, correlated prit)", p_cor_prit) + + p_cor_piet <- ppc_pit_ecdf( + pit = pit, + method = "correlated", + test = "PIET", + plot_diff = TRUE + ) + vdiffr::expect_doppelganger("ppc_pit_ecdf (diff, correlated piet)", p_cor_piet) +}) + +test_that("ppc_pit_ecdf renders different linewidths and colors correctly", { + set.seed(2025) + pit <- 1 - (1 - runif(300))^(1.2) + + p_cor_lw1 <- ppc_pit_ecdf( + pit = pit, + method = "correlated", + linewidth = 1. + ) + vdiffr::expect_doppelganger("ppc_pit_ecdf (linewidth = 1)", p_cor_lw1) + + p_cor_lw2 <- ppc_pit_ecdf( + pit = pit, + method = "correlated", + linewidth = 2. + ) + vdiffr::expect_doppelganger("ppc_pit_ecdf (linewidth = 2)", p_cor_lw2) + + p_cor_col <- ppc_pit_ecdf( + pit = pit, + method = "correlated", + color = c(ecdf = "darkblue", highlight = "red") + ) + vdiffr::expect_doppelganger("ppc_pit_ecdf (color change)", p_cor_col) }) \ No newline at end of file From 55db9feefd13a09c9fe4e84a56109f3945987a8d Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Wed, 4 Mar 2026 13:00:44 +0200 Subject: [PATCH 085/120] fix duplicate naming in visual regression tests --- tests/testthat/test-ppc-distributions.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-ppc-distributions.R b/tests/testthat/test-ppc-distributions.R index 479de62e..385db16d 100644 --- a/tests/testthat/test-ppc-distributions.R +++ b/tests/testthat/test-ppc-distributions.R @@ -503,7 +503,7 @@ test_that("ppc_pit_ecdf with method correlated renders different tests correctly method = "correlated", test = "PIET" ) - vdiffr::expect_doppelganger("ppc_pit_ecdf (correlated piet)", p_cor_piet) + vdiffr::expect_doppelganger("ppc_pit_ecdf (correlated piet 2)", p_cor_piet) }) test_that("ppc_pit_ecdf with plot_diff=TRUE and method correlated renders different tests correctly", { From 6a876fc77aa05130dd9fb381caea3b25e337d527 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Wed, 4 Mar 2026 13:01:01 +0200 Subject: [PATCH 086/120] update snapshots for visual regression tests --- .../ppc-pit-ecdf-color-change.svg | 75 ++++++++++++++++++ .../ppc-pit-ecdf-correlated-piet-2.svg | 71 +++++++++++++++++ .../ppc-pit-ecdf-correlated-pot.svg | 75 ++++++++++++++++++ .../ppc-pit-ecdf-correlated-prit-2.svg | 77 +++++++++++++++++++ .../ppc-pit-ecdf-diff-correlated-piet.svg | 71 +++++++++++++++++ .../ppc-pit-ecdf-diff-correlated-pot.svg | 75 ++++++++++++++++++ .../ppc-pit-ecdf-diff-correlated-prit.svg | 77 +++++++++++++++++++ .../ppc-pit-ecdf-linewidth-1.svg | 75 ++++++++++++++++++ .../ppc-pit-ecdf-linewidth-2.svg | 75 ++++++++++++++++++ 9 files changed, 671 insertions(+) create mode 100644 tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-color-change.svg create mode 100644 tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet-2.svg create mode 100644 tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-pot.svg create mode 100644 tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit-2.svg create mode 100644 tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-piet.svg create mode 100644 tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-pot.svg create mode 100644 tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-prit.svg create mode 100644 tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-1.svg create mode 100644 tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-2.svg diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-color-change.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-color-change.svg new file mode 100644 index 00000000..7d6fc9dd --- /dev/null +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-color-change.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.01 +) + + + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF +ppc_pit_ecdf (color change) + + diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet-2.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet-2.svg new file mode 100644 index 00000000..44d075ad --- /dev/null +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet-2.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + +p +u +n +i +f += +0.188 + +( +α += +0.01 +) + + + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF +ppc_pit_ecdf (correlated piet 2) + + diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-pot.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-pot.svg new file mode 100644 index 00000000..9763250d --- /dev/null +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-pot.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.01 +) + + + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF +ppc_pit_ecdf (correlated pot) + + diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit-2.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit-2.svg new file mode 100644 index 00000000..31f7189b --- /dev/null +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit-2.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +p +u +n +i +f += +0.001 + +( +α += +0.01 +) + + + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF +ppc_pit_ecdf (correlated prit 2) + + diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-piet.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-piet.svg new file mode 100644 index 00000000..8ec9dace --- /dev/null +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-piet.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + +p +u +n +i +f += +0.188 + +( +α += +0.01 +) + + + +-0.10 +-0.05 +0.00 +0.05 +0.10 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF difference +ppc_pit_ecdf (diff, correlated piet) + + diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-pot.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-pot.svg new file mode 100644 index 00000000..e7cff9d1 --- /dev/null +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-pot.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.01 +) + + + +-0.10 +-0.05 +0.00 +0.05 +0.10 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF difference +ppc_pit_ecdf (diff, correlated pot) + + diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-prit.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-prit.svg new file mode 100644 index 00000000..1645ac6c --- /dev/null +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-prit.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +p +u +n +i +f += +0.001 + +( +α += +0.01 +) + + + +-0.10 +-0.05 +0.00 +0.05 +0.10 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF difference +ppc_pit_ecdf (diff, correlated prit) + + diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-1.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-1.svg new file mode 100644 index 00000000..c8e891d6 --- /dev/null +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-1.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.01 +) + + + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF +ppc_pit_ecdf (linewidth = 1) + + diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-2.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-2.svg new file mode 100644 index 00000000..d4a71e76 --- /dev/null +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-2.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +p +u +n +i +f += +0.000 + +( +α += +0.01 +) + + + +0.00 +0.25 +0.50 +0.75 +1.00 + + + + + + + + + + + +0.00 +0.25 +0.50 +0.75 +1.00 +PIT +ECDF +ppc_pit_ecdf (linewidth = 2) + + From 494dce871fcbb1430c97dd1f4ca0ffbdf9c36104 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Thu, 5 Mar 2026 10:16:09 +0200 Subject: [PATCH 087/120] add pareto_pit function temporarily until available via posterior --- R/helpers-ppc.R | 460 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 460 insertions(+) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index ee9fee6a..d0a76476 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -722,4 +722,464 @@ ypred_label <- function() expression(italic(y)[pred]) #' @noRd .compute_cauchy <- function(x) { tan((0.5 - x) * pi) +} + +# Support pareto_pit in ppc_loo_pit_ecdf and ppc_pit_ecdf -------------- + +#' Pareto-smoothed probability integral transform +#' +#' Compute PIT values using the empirical CDF, then refine values in +#' the tails by fitting a generalized Pareto distribution (GPD) to +#' the tail draws. This gives smoother, more accurate PIT values in +#' the tails where the ECDF is coarse, and avoids PIT values of 0 and 1. +#' Due to use of generalized Pareto distribution CDF in tails, the +#' PIT values are not anymore rank based and continuous uniformity +#' test is appropriate. +#' +#' @name pareto_pit +#' +#' @param x (draws) A [`draws_matrix`] object or one coercible to a +#' `draws_matrix` object, or an [`rvar`] object. +#' +#' @param y (observations) A 1D vector, or an array of dim(x), if x is `rvar`. +#' Each element of `y` corresponds to a variable in `x`. +#' +#' @param weights A matrix of weights for each draw and variable. `weights` +#' should have one column per variable in `x`, and `ndraws(x)` rows. +#' +#' @param log (logical) Are the weights passed already on the log scale? The +#' default is `FALSE`, that is, expecting `weights` to be on the standard +#' (non-log) scale. +#' +#' @param ndraws_tail (integer) Number of tail draws to use for GPD +#' fitting. If `NULL` (the default), computed using [ps_tail_length()]. +#' +#' @template args-methods-dots +#' +#' @details The function first computes raw PIT values identically to +#' [pit()] (including support for weighted draws). It then fits a +#' GPD to both tails of the draws (using the same approach as +#' [pareto_smooth()]) and replaces PIT values for observations falling in +#' the tail regions: +#' +#' For a right-tail observation \eqn{y_i > c_R} (where \eqn{c_R} is +#' the right-tail cutoff): +#' +#' \deqn{PIT(y_i) = 1 - p_{tail}(1 - F_{GPD}(y_i; c_R, \sigma_R, k_R))} +#' +#' For a left-tail observation \eqn{y_i < c_L}: +#' +#' \deqn{PIT(y_i) = p_{tail}(1 - F_{GPD}(-y_i; -c_L, \sigma_L, k_L))} +#' +#' where \eqn{p_{tail}} is the proportion of (weighted) mass in the +#' tail. +#' +#' When (log-)weights in `weights` are provided, they are used for +#' the raw PIT computation (as in [pit()]) and for GPD fit. +#' +#' @return A numeric vector of length `length(y)` containing the PIT values, or +#' an array of shape `dim(y)`, if `x` is an `rvar`. +#' +#' @seealso [pit()] for the unsmoothed version, [pareto_smooth()] for +#' Pareto smoothing of draws. +#' +#' @examples +#' x <- example_draws() +#' y <- rnorm(nvariables(x), 5, 5) +#' pareto_pit(x, y) +#' +NULL + +#' @rdname pareto_pit +#' @export +pareto_pit <- function(x, y, ...) UseMethod("pareto_pit") + +#' @rdname pareto_pit +#' @export +pareto_pit.default <- function(x, y, weights = NULL, log = FALSE, + ndraws_tail = NULL, ...) { + x <- posterior::as_draws_matrix(x) + if (!is.null(weights)) { + weights <- posterior::as_draws_matrix(weights) + } + pareto_pit(x, y, weights = weights, log = log, + ndraws_tail = ndraws_tail, ...) +} + +#' @rdname pareto_pit +#' @export +pareto_pit.draws_matrix <- function(x, y, weights = NULL, log = FALSE, + ndraws_tail = NULL, ...) { + y <- pareto_pit_validate_y(y, x) + + # validate and normalize weights to log scale (same as pit.draws_matrix) + if (!is.null(weights)) { + weights <- sapply(seq_len(posterior::nvariables(x)), function(var_idx) { + posterior:::validate_weights(weights[, var_idx], x[, var_idx], log) + }) + weights <- normalize_log_weights(weights) + } + + ndraws <- posterior:::ndraws(x) + + if (is.null(ndraws_tail)) { + ndraws_tail <- posterior::ps_tail_length(ndraws, 1) + } else { + ndraws_tail <- posterior::as_one_integer(ndraws_tail) + } + + # validate ndraws_tail once for all variables + gpd_ok <- !is.na(ndraws_tail) && ndraws_tail >= 5 + if (gpd_ok && ndraws_tail > ndraws / 2) { + ndraws_tail <- floor(ndraws / 2) + } + if (gpd_ok && ndraws_tail >= ndraws) { + gpd_ok <- FALSE + } + + # precompute tail indices (shared across all variables) + if (gpd_ok) { + tail_ids <- seq(ndraws - ndraws_tail + 1, ndraws) + } + + pit_values <- vapply(seq_len(ncol(x)), function(j) { + draws <- x[, j] + + # --- raw PIT (same logic as pit.draws_matrix) --- + sel_min <- draws < y[j] + if (!any(sel_min)) { + raw_pit <- 0 + } else { + if (is.null(weights)) { + raw_pit <- mean(sel_min) + } else { + raw_pit <- exp(posterior:::log_sum_exp(weights[sel_min, j])) + } + } + + sel_sup <- draws == y[j] + if (any(sel_sup)) { + if (is.null(weights)) { + pit_sup <- raw_pit + mean(sel_sup) + } else { + pit_sup <- raw_pit + exp(posterior:::log_sum_exp(weights[sel_sup, j])) + } + raw_pit <- runif(1, raw_pit, pit_sup) + } + + # --- GPD tail refinement --- + if (!gpd_ok || posterior:::should_return_NA(draws)) { + return(raw_pit) + } + + # sort draws and carry weights along + ord <- sort.int(draws, index.return = TRUE) + sorted <- ord$x + log_wt_sorted <- if (!is.null(weights)) weights[ord$ix, j] else NULL + + # tail proportion: sum of (normalized) weights in the tail + if (!is.null(log_wt_sorted)) { + tail_proportion <- exp(posterior:::log_sum_exp(log_wt_sorted[tail_ids])) + } else { + tail_proportion <- ndraws_tail / ndraws + } + + # --- right tail --- + right_replaced <- FALSE + right_tail <- sorted[tail_ids] + if (!posterior:::is_constant(right_tail)) { + right_cutoff <- sorted[min(tail_ids) - 1] + if (right_cutoff == right_tail[1]) { + right_cutoff <- right_cutoff - .Machine$double.eps + } + right_tail_wt <- if (!is.null(log_wt_sorted)) { + exp(log_wt_sorted[tail_ids]) + } else { + NULL + } + right_fit <- gpdfit(right_tail - right_cutoff, sort_x = FALSE, + weights = right_tail_wt) + if (is.finite(right_fit$k) && !is.na(right_fit$sigma)) { + if (y[j] > right_cutoff) { + gpd_cdf <- pgeneralized_pareto( + y[j], mu = right_cutoff, sigma = right_fit$sigma, k = right_fit$k + ) + raw_pit <- 1 - tail_proportion * (1 - gpd_cdf) + right_replaced <- TRUE + } + } + } + + # --- left tail (negate trick, same as ps_tail) --- + if (!right_replaced) { + left_draws <- -draws + left_ord <- sort.int(left_draws, index.return = TRUE) + left_sorted <- left_ord$x + log_wt_left_sorted <- if (!is.null(weights)) weights[left_ord$ix, j] else NULL + + left_tail <- left_sorted[tail_ids] + if (!posterior:::is_constant(left_tail)) { + left_cutoff <- left_sorted[min(tail_ids) - 1] + if (left_cutoff == left_tail[1]) { + left_cutoff <- left_cutoff - .Machine$double.eps + } + left_tail_wt <- if (!is.null(log_wt_left_sorted)) { + exp(log_wt_left_sorted[tail_ids]) + } else { + NULL + } + left_fit <- gpdfit(left_tail - left_cutoff, sort_x = FALSE, + weights = left_tail_wt) + if (is.finite(left_fit$k) && !is.na(left_fit$sigma)) { + if (-y[j] > left_cutoff) { + gpd_cdf <- pgeneralized_pareto( + -y[j], mu = left_cutoff, sigma = left_fit$sigma, k = left_fit$k + ) + if (!is.null(log_wt_left_sorted)) { + left_tail_proportion <- exp(posterior:::log_sum_exp(log_wt_left_sorted[tail_ids])) + } else { + left_tail_proportion <- tail_proportion + } + raw_pit <- left_tail_proportion * (1 - gpd_cdf) + } + } + } + } + + raw_pit + }, FUN.VALUE = 1.0) + + min_tail_prob <- 1/ndraws/1e4 + pit_values <- pmin(pmax(pit_values, min_tail_prob), 1-min_tail_prob) + setNames(pit_values, posterior::variables(x)) +} + +#' @rdname pareto_pit +#' @export +pareto_pit.rvar <- function(x, y, weights = NULL, log = FALSE, + ndraws_tail = NULL, ...) { + y <- pareto_pit_validate_y(y, x) + out <- array( + data = pareto_pit( + x = as_draws_matrix(c(x)), + y = c(y), + weights = weights, + log = log, + ndraws_tail = ndraws_tail, + ... + ), + dim = dim(x), + dimnames = dimnames(x) + ) + out +} + +# internal ---------------------------------------------------------------- + +pareto_pit_validate_y <- function(y, x = NULL) { + if (!is.numeric(y)) { + posterior:::stop_no_call("`y` must be numeric.") + } + if (anyNA(y)) { + posterior:::stop_no_call("NAs not allowed in `y`.") + } + if (posterior::is_rvar(x)) { + if (length(x) != length(y) || any(dim(y) != dim(x))) { + posterior:::stop_no_call("`dim(y)` must match `dim(x)`.") + } + } else if (posterior::is_draws(x)) { + if (!is.vector(y, mode = "numeric") || length(y) != posterior::nvariables(x)) { + posterior:::stop_no_call("`y` must be a vector of length `nvariables(x)`.") + } + } + y +} + +normalize_log_weights <- function(log_weights) { + apply(log_weights, 2, function(col) col - posterior:::log_sum_exp(col)) +} + + +#' Quantile function for the generalized Pareto distribution +#' +#' Computes the quantile function for a generalized Pareto distribution +#' with location `mu`, scale `sigma`, and shape `k`. +#' +#' @param p Numeric vector of probabilities. +#' @param mu Location parameter. +#' @param sigma Scale parameter (must be positive). +#' @param k Shape parameter. +#' @param lower.tail Logical; if `TRUE` (default), probabilities are `P[X <= x]`. +#' @param log.p Logical; if `TRUE`, probabilities are given as `log(p)`. +#' @return A numeric vector of quantiles. +#' @keywords internal +#' @export +#' @examples +#' qgeneralized_pareto(p = c(0.1, 0.5, 0.9), mu = 0, sigma = 1, k = 0.2) +qgeneralized_pareto <- function(p, mu = 0, sigma = 1, k = 0, lower.tail = TRUE, log.p = FALSE) { + stopifnot(length(mu) == 1 && length(sigma) == 1 && length(k) == 1) + if (is.na(sigma) || sigma <= 0) { + return(rep(NaN, length(p))) + } + if (log.p) { + p <- exp(p) + } + if (!lower.tail) { + p <- 1 - p + } + if (k == 0) { + q <- mu - sigma * log1p(-p) + } else { + q <- mu + sigma * expm1(-k * log1p(-p)) / k + } + q +} + +#' Distribution function for the generalized Pareto distribution +#' +#' Computes the cumulative distribution function (CDF) for a generalized +#' Pareto distribution with location `mu`, scale `sigma`, and shape `k`. +#' +#' @param q Numeric vector of quantiles. +#' @param mu Location parameter. +#' @param sigma Scale parameter (must be positive). +#' @param k Shape parameter. +#' @param lower.tail Logical; if `TRUE` (default), probabilities are `P[X <= x]`. +#' @param log.p Logical; if `TRUE`, probabilities are returned as `log(p)`. +#' @return A numeric vector of probabilities. +#' @keywords internal +#' @export +#' @examples +#' pgeneralized_pareto(q = c(1, 2, 5), mu = 0, sigma = 1, k = 0.2) +pgeneralized_pareto <- function(q, mu = 0, sigma = 1, k = 0, lower.tail = TRUE, log.p = FALSE) { + stopifnot(length(mu) == 1 && length(sigma) == 1 && length(k) == 1) + if (is.na(sigma) || sigma <= 0) { + return(rep(NaN, length(q))) + } + z <- (q - mu) / sigma + if (abs(k) < 1e-15) { + # for very small values of indistinguishable in floating point accuracy from the case k=0 + p <- -expm1(-z) + } else { + # pmax handles values outside the support + p <- -expm1(log1p(pmax(k * z, -1)) / -k) + } + # force to [0, 1] for values outside the support + p <- pmin(pmax(p, 0), 1) + if (!lower.tail) { + p <- 1 - p + } + if (log.p) { + p <- log(p) + } + p +} + +#' Estimate parameters of the Generalized Pareto distribution +#' +#' Given a sample \eqn{x}, Estimate the parameters \eqn{k} and +#' \eqn{\sigma} of the generalized Pareto distribution (GPD), assuming +#' the location parameter is 0. By default the fit uses a prior for +#' \eqn{k} (this is in addition to the prior described by Zhang and +#' Stephens, 2009), which will stabilize estimates for very small +#' sample sizes (and low effective sample sizes in the case of MCMC +#' samples). The weakly informative prior is a Gaussian prior centered +#' at 0.5 (see details in Vehtari et al., 2024). This is used +#' internally but is exported for use by other packages. +#' @family helper-functions +#' @param x A numeric vector. The sample from which to estimate the +#' parameters. +#' @param wip Logical indicating whether to adjust \eqn{k} based on a +#' weakly informative Gaussian prior centered on 0.5. Defaults to +#' `TRUE`. +#' @param min_grid_pts The minimum number of grid points used in the +#' fitting algorithm. The actual number used is `min_grid_pts + +#' floor(sqrt(length(x)))`. +#' @param sort_x If `TRUE` (the default), the first step in the +#' fitting algorithm is to sort the elements of `x`. If `x` is +#' already sorted in ascending order then `sort_x` can be set to +#' `FALSE` to skip the initial sorting step. +#' @param weights An optional numeric vector of positive weights the same +#' length as `x`. If `NULL` (the default), all observations are +#' weighted equally and the result is identical to the unweighted fit. +#' Weights are normalized internally to sum to `length(x)`. +#' @return A named list with components `k` and `sigma`. +#' +#' @details Here the parameter \eqn{k} is the negative of \eqn{k} in Zhang & +#' Stephens (2009). +#' +#' +#' @references +#' Zhang, J., and Stephens, M. A. (2009). A new and efficient estimation method +#' for the generalized Pareto distribution. *Technometrics* **51**, 316-325. +#' +#' @keywords internal +#' @export +gpdfit <- function(x, wip = TRUE, min_grid_pts = 30, sort_x = TRUE, + weights = NULL) { + # see section 4 of Zhang and Stephens (2009) + if (sort_x) { + if (!is.null(weights)) { + ord <- sort.int(x, index.return = TRUE) + x <- ord$x + weights <- weights[ord$ix] + } else { + x <- sort.int(x) + } + } + N <- length(x) + + # normalize weights to sum to N so the log-likelihood scale is preserved + if (!is.null(weights)) { + weights <- weights / sum(weights) * N + } + + prior <- 3 + M <- min_grid_pts + floor(sqrt(N)) + jj <- seq_len(M) + xstar <- x[floor(N / 4 + 0.5)] # first quartile of sample + if (xstar > x[1]) { + # first quantile is bigger than the minimum + theta <- 1 / x[N] + (1 - sqrt(M / (jj - 0.5))) / prior / xstar + + # log1p(-theta %o% x) is M x N matrix + log1p_mat <- log1p(-theta %o% x) + + if (!is.null(weights)) { + # weighted mean across observations for each theta value + k <- drop(log1p_mat %*% weights) / N + } else { + k <- matrixStats::rowMeans2(log1p_mat) + } + + l_theta <- N * (log(-theta / k) - k - 1) # profile log-lik + w_theta <- exp(l_theta - matrixStats::logSumExp(l_theta)) # normalize + theta_hat <- sum(theta * w_theta) + + if (!is.null(weights)) { + k_hat <- sum(weights * log1p(-theta_hat * x)) / N + } else { + k_hat <- mean.default(log1p(-theta_hat * x)) + } + sigma_hat <- -k_hat / theta_hat + + # adjust k_hat based on weakly informative prior, Gaussian centered on 0.5. + # this stabilizes estimates for very small Monte Carlo sample sizes and low ess + # (see Vehtari et al., 2024 for details) + if (wip) { + k_hat <- (k_hat * N + 0.5 * 10) / (N + 10) + } + if (is.na(k_hat)) { + k_hat <- Inf + sigma_hat <- NaN + } + } else { + # first quantile is not bigger than the minimum, which indicates + # that the distribution is far from a generalized Pareto + # distribution + k_hat <- NA + sigma_hat <- NA + } + + list(k = k_hat, sigma = sigma_hat) } \ No newline at end of file From 7858120985bc0138e8a1794f0597603a8e247ac2 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Thu, 5 Mar 2026 10:17:41 +0200 Subject: [PATCH 088/120] add pareto_pit function temporarily until available via posterior --- R/helpers-ppc.R | 2 ++ 1 file changed, 2 insertions(+) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index d0a76476..a7d83ee1 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -725,6 +725,8 @@ ypred_label <- function() expression(italic(y)[pred]) } # Support pareto_pit in ppc_loo_pit_ecdf and ppc_pit_ecdf -------------- +# TODO: Once this function is available via posterior, remove this internal implementation +# and import from posterior. #' Pareto-smoothed probability integral transform #' From 1a6d84ce389665ef465e5ce0220e6956fcaaea2a Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Thu, 5 Mar 2026 10:19:03 +0200 Subject: [PATCH 089/120] update ppc_loo_pit_ecdf to support pareto_pit & minor refactoring to clean up new code structure --- R/ppc-loo.R | 395 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 228 insertions(+), 167 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 2add4c35..993af51f 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -419,6 +419,10 @@ ppc_loo_pit_qq <- function(y, #' the main ECDF line, the second for highlighted suspicious regions. #' @param help_text For `ppc_loo_pit_ecdf()` when `method = "correlated"`, a boolean #' defining whether to add informative text to the plot. Defaults to `TRUE`. +#' @param pareto_pit For `ppc_loo_pit_ecdf()`. Computes PIT values using Pareto-PIT method. +#' Defaults to `TRUE` if `test` is either `"POT"` or `"PIET"` and no `pit` values are +#' provided otherwise `FALSE`. This argument should not normally be modified by the user, +#' except for development purposes. #' @note #' Note that the default "independent" method is **superseded** by #' the "correlated" method (Tesso & Vehtari, 2026) which accounts for dependent @@ -438,59 +442,125 @@ ppc_loo_pit_ecdf <- function(y, gamma = NULL, linewidth = NULL, color = NULL, - help_text = NULL) { - + help_text = NULL, + pareto_pit = NULL) { + # Expected input combinations for ppc_loo_pit_ecdf() based on method and test choices: + # | yrep | y | lw | psis_object | pit | method | test | pareto_pit | approach | + # |------|---|----|-------------|-----|-------------|------|------------|--------------------| + # | x | x | x | | | independent | NULL | TRUE | compute pareto-pit | + # | x | x | | x | | independent | NULL | TRUE | compute pareto-pit | + # | | | | | x | independent | NULL | FALSE | | + # | x | x | x | | | correlated | POT | TRUE | compute pareto-pit | + # | x | x | | x | | correlated | POT | TRUE | compute pareto-pit | + # | | | | | x | correlated | POT | FALSE | | + # | x | x | x | | | correlated | PIET | TRUE | compute pareto-pit | + # | x | x | | x | | correlated | PIET | TRUE | compute pareto-pit | + # | | | | | x | correlated | PIET | FALSE | | + # | x | x | x | | | correlated | PRIT | FALSE | compute loo-pit | + # | x | x | | x | | correlated | PRIT | FALSE | compute loo-pit | + # | | | | | x | correlated | PRIT | FALSE | | + check_ignored_arguments(..., ok_args = list("moment_match")) - - # Input validation ------------------------------------------------------- - # internal helper for printing user information if needed - .warn_ignored <- function(method, args) { - msg <- paste0("As method = ", method, " specified; ignoring: ", - paste(args, collapse = ", "), ".") - inform(msg) + + # --------------------------------------------------------------------------- + # Internal helpers + # --------------------------------------------------------------------------- + + .warn_ignored <- function(method_name, args) { + inform(paste0( + "As method = ", method_name, " specified; ignoring: ", + paste(args, collapse = ", "), "." + )) } + + # --------------------------------------------------------------------------- + # Resolve and validate `method` + # --------------------------------------------------------------------------- if (is.null(method)) { - inform( - c( - "i" = paste( - "In the next major release, the default `method`", - "will change to 'correlated'." - ), - "*" = paste( - "To silence this message, explicitly set", - "`method = 'independent'` or `method = 'correlated'`." - ) + inform(c( + "i" = paste( + "In the next major release, the default `method`", + "will change to 'correlated'." + ), + "*" = paste( + "To silence this message, explicitly set", + "`method = 'independent'` or `method = 'correlated'`." ) - ) + )) method <- "independent" } else { method <- match.arg(method, choices = c("independent", "correlated")) if (method == "independent") { - inform( - paste( - "The 'independent' method is superseded by the 'correlated' method." - ) - ) + inform("The 'independent' method is superseded by the 'correlated' method.") } } + + # --------------------------------------------------------------------------- + # Method-specific defaults and validation + # --------------------------------------------------------------------------- - # PIT calculation or validation - if (!is.null(pit)) { - pit <- validate_pit(pit) - if (is.null(K)) { - K <- length(pit) + switch(method, + "correlated" = { + if (!is.null(interpolate_adj)) .warn_ignored("'correlated'", "interpolate_adj") + + test <- match.arg(test %||% "POT", choices = c("POT", "PRIT", "PIET")) + alpha <- 1 - prob + gamma <- gamma %||% 0 + linewidth <- linewidth %||% 0.3 + color <- color %||% c(ecdf = "grey60", highlight = "red") + help_text <- help_text %||% TRUE + + # Pareto PIT applies only when `pit` is not already supplied and the + # test is POT or PIET. + pareto_pit <- is.null(pit) && test %in% c("POT", "PIET") + }, + "independent" = { + # Collect args that are meaningless under the independent method. + ignored <- c( + if (!is.null(test)) "test", + if (!is.null(gamma)) "gamma", + if (!is.null(help_text)) "help_text" + ) + if (length(ignored) > 0) .warn_ignored("'independent'", ignored) } - # print user info only if corresponding args are specified - ignored <- character(0) - if (!missing(y) && !is.null(y)) ignored <- c(ignored, "y") - if (!missing(yrep) && !is.null(yrep)) ignored <- c(ignored, "yrep") - if (!is.null(lw)) ignored <- c(ignored, "lw") + ) + + # --------------------------------------------------------------------------- + # Compute PIT values + # --------------------------------------------------------------------------- + + if (isTRUE(pareto_pit) && is.null(pit)) { + # --- Pareto-smoothed LOO PIT --- + suggested_package("rstantools") + y <- validate_y(y) + yrep <- validate_predictions(yrep, length(y)) + lw <- .get_lw(lw, psis_object) + stopifnot(identical(dim(yrep), dim(lw))) + + pit <- pareto_pit(x = yrep, y = y, weights = lw, log = TRUE) + K <- K %||% length(pit) + + } else if (!is.null(pit)) { + # --- Pre-supplied PIT values --- + pit <- validate_pit(pit) + K <- K %||% length(pit) + + # Warn about any ignored arguments. + ignored <- c( + if (!missing(y) && !is.null(y)) "y", + if (!missing(yrep) && !is.null(yrep)) "yrep", + if (!is.null(lw)) "lw" + ) if (length(ignored) > 0) { - inform(paste0("As 'pit' specified; ignoring: ", paste(ignored, collapse = ", "), ".")) + inform(paste0( + "As 'pit' specified; ignoring: ", + paste(ignored, collapse = ", "), "." + )) } } else { + # --- Standard LOO PIT --- suggested_package("rstantools") y <- validate_y(y) yrep <- validate_predictions(yrep, length(y)) @@ -498,161 +568,151 @@ ppc_loo_pit_ecdf <- function(y, stopifnot(identical(dim(yrep), dim(lw))) pit <- pmin(1, rstantools::loo_pit(object = yrep, y = y, lw = lw)) - if (is.null(K)) { - K <- min(nrow(yrep) + 1, 1000) - } + K <- K %||% min(nrow(yrep) + 1, 1000) } - # Input validation dependent on method - switch(method, - "correlated" = { - if (!is.null(interpolate_adj)) .warn_ignored("'correlated'", "interpolate_adj") - - test <- match.arg(test %||% "POT", choices = c("POT", "PRIT", "PIET")) - - alpha <- 1 - prob - gamma <- gamma %||% 0 - linewidth <- linewidth %||% 0.3 - color <- color %||% c(ecdf = "grey60", highlight = "red") - help_text <- help_text %||% TRUE - }, - - "independent" = { - ignored <- character(0) - if (!is.null(test)) ignored <- c(ignored, "test") - if (!is.null(gamma)) ignored <- c(ignored, "gamma") - if (!is.null(help_text)) ignored <- c(ignored, "help_text") - if (length(ignored) > 0) .warn_ignored("'independent'", ignored) - } - ) + # --------------------------------------------------------------------------- + # Shared ECDF setup + # --------------------------------------------------------------------------- + + n_obs <- length(pit) + unit_interval <- seq(0, 1, length.out = K) + ecdf_pit_fn <- ecdf(pit) + y_label <- if (plot_diff) "ECDF difference" else "ECDF" - n_obs <- length(pit) - unit_interval <- seq(0, 1, length.out = K) - .ecdf_pit_fn <- ecdf(pit) + # =========================================================================== + # Correlated method + # =========================================================================== - # Correlated method -------------------------------------------------- if (method == "correlated") { - # Compute test p-value and Cauchy-transformed values - if (test == "POT") { - std_cauchy_values <- .compute_cauchy(.pot_test(sort(pit))) - p_value_CCT <- .cauchy_combination_test(.pot_test(pit), truncate = TRUE) - } else if (test == "PIET") { - std_cauchy_values <- .compute_cauchy(.piet_test(sort(pit))) - p_value_CCT <- .cauchy_combination_test(.piet_test(pit), truncate = FALSE) - } else { # PRIT - std_cauchy_values <- .compute_cauchy(.prit_test(sort(pit))) - p_value_CCT <- .cauchy_combination_test(.prit_test(pit), truncate = TRUE) - } - pointwise_contribution <- .compute_shapley_values(std_cauchy_values) + # Compute the per-observation test statistics (sorted for Shapley values) + # and the combined Cauchy p-value. + test_fn <- switch(test, + POT = .pot_test, + PIET = .piet_test, + PRIT = .prit_test + ) + + pit_sorted <- sort(pit) + std_cauchy_values <- .compute_cauchy(test_fn(pit_sorted)) + p_value_CCT <- .cauchy_combination_test( + test_fn(pit), + truncate = test != "PIET" + ) + pointwise_contrib <- .compute_shapley_values(std_cauchy_values) - if (gamma < 0 || gamma > max(pointwise_contribution)) { + # Validate gamma against computed Shapley values. + max_contrib <- max(pointwise_contrib) + if (gamma < 0 || gamma > max_contrib) { stop(sprintf( - "gamma must be in the interval [0, %.2f], but gamma = %s was provided", - max(pointwise_contribution), gamma + "gamma must be in [0, %.2f], but gamma = %s was provided.", + max_contrib, gamma )) } - x_axis_combined <- sort(unique(c(unit_interval, pit))) - - # Evaluate at 0-1 interval b´values + + # Build the main ECDF data frame over a dense grid that includes pit values + # so step discontinuities are rendered exactly. + x_combined <- sort(unique(c(unit_interval, pit))) + df_main <- tibble::tibble( - x = x_axis_combined, - ecdf_pit = .ecdf_pit_fn(x_axis_combined) - plot_diff * x_axis_combined + x = x_combined, + ecdf_val = ecdf_pit_fn(x_combined) - plot_diff * x_combined ) - - # Evaluate at pit values (used for highlighing) + + # Sorted pit data frame (used for highlighting suspicious points). df_pit <- tibble::tibble( - pit = pit, - ecdf_pit = .ecdf_pit_fn(pit) - plot_diff * pit + pit = pit_sorted, + ecdf_val = ecdf_pit_fn(pit_sorted) - plot_diff * pit_sorted ) - df_pit <- df_pit[order(df_pit$pit), ] - # Plot ECDF + # --- Base plot ----------------------------------------------------------- + p <- ggplot() + geom_step( - data = df_main, aes(x = .data$x, y = .data$ecdf_pit), - show.legend = FALSE, linewidth = linewidth, color = color[1]) + - labs( - y = dplyr::if_else(plot_diff, "ECDF difference", "ECDF"), - x = "LOO PIT" - ) - - # Add reference line - p <- p + geom_segment( - aes( - x = 0, y = 0, xend = 1, - yend = dplyr::if_else(plot_diff, 0, 1) - ), - linetype = "dashed", color = "darkgrey", linewidth = 0.3 - ) - - # Identify and highlight suspecious points (regions) of the ECDF + data = df_main, + mapping = aes(x = .data$x, y = .data$ecdf_val), + show.legend = FALSE, + linewidth = linewidth, + color = color["ecdf"] + ) + + geom_segment( + mapping = aes(x = 0, y = 0, xend = 1, yend = if (plot_diff) 0 else 1), + linetype = "dashed", + color = "darkgrey", + linewidth = 0.3 + ) + + labs(x = "PIT", y = y_label) + + # --- Highlight suspicious regions ---------------------------------------- + if (p_value_CCT < alpha) { - red_idx <- which(pointwise_contribution > gamma) + red_idx <- which(pointwise_contrib > gamma) if (length(red_idx) > 0) { - df_red <- df_pit[red_idx, ] - - # Groups of consecutive suspicious points + df_red <- df_pit[red_idx, ] df_red$segment <- cumsum(c(1, diff(red_idx) != 1)) - # Separate isolated vs grouped points - segment_lengths <- stats::ave(df_red$pit, df_red$segment, FUN = length) - df_isolated <- df_red[segment_lengths == 1, ] - df_grouped <- df_red[segment_lengths > 1, ] + seg_sizes <- stats::ave(df_red$pit, df_red$segment, FUN = length) + df_isolated <- df_red[seg_sizes == 1, ] + df_grouped <- df_red[seg_sizes > 1, ] - # Create segments based on x_combined values for grouped points + # Highlight contiguous groups as coloured step segments. if (nrow(df_grouped) > 0) { - segments_list <- lapply( - split(df_grouped, df_grouped$segment), function(group) { - group_indices <- match(group$pit, x_axis_combined) - idx_range <- min(group_indices):max(group_indices) - + df_segments <- do.call(rbind, lapply( + split(df_grouped, df_grouped$segment), + function(grp) { + pit_idx <- match(grp$pit, x_combined) + idx_range <- seq(min(pit_idx), max(pit_idx)) tibble::tibble( - x = df_main$x[idx_range], - ecdf_pit = df_main$ecdf_pit[idx_range], - segment = group$segment[1] + x = df_main$x[idx_range], + ecdf_val = df_main$ecdf_val[idx_range], + segment = grp$segment[1L] ) } - ) - df_segments <- do.call(rbind, segments_list) - + )) + p <- p + geom_step( - data = df_segments, - aes(x = .data$x, y = .data$ecdf_pit, group = .data$segment), - color = color[2], + data = df_segments, + mapping = aes(x = .data$x, y = .data$ecdf_val, group = .data$segment), + color = color["highlight"], linewidth = linewidth + 0.8 ) } + # Highlight isolated suspicious points as dots. if (nrow(df_isolated) > 0) { p <- p + geom_point( data = df_isolated, - aes(x = .data$pit, y = .data$ecdf_pit), - color = color[2], + mapping = aes(x = .data$pit, y = .data$ecdf_val), + color = color["highlight"], size = linewidth + 1 ) } } } - # Apply bayesplot theme and styling - if (help_text) { + # --- Annotation and axis scaling ----------------------------------------- + + if (isTRUE(help_text)) { + label_size <- 0.7 * bayesplot_theme_get()$text@size / ggplot2::.pt p <- p + annotate( "text", - x = -Inf, y = Inf, - label = sprintf("p[unif] == '%.3f' ~ (alpha == '%.2f')", p_value_CCT, alpha), - hjust = -0.05, vjust = 1.5, color = "black", - parse = TRUE, size = 0.7 * bayesplot_theme_get()$text@size / ggplot2::.pt + x = -Inf, y = Inf, + label = sprintf( + "p[unif] == '%.3f' ~ (alpha == '%.2f')", + p_value_CCT, alpha + ), + hjust = -0.05, vjust = 1.5, + color = "black", parse = TRUE, size = label_size ) } if (plot_diff) { - epsilon = max( - sqrt(log(2 / (1 - prob)) / (2 * length(pit))), - max(abs(df_main$ecdf_pit)) + epsilon <- max( + sqrt(log(2 / (1 - prob)) / (2 * n_obs)), + max(abs(df_main$ecdf_val)) ) - p <- p + scale_y_continuous(limits = c(-epsilon, epsilon)) } @@ -664,43 +724,44 @@ ppc_loo_pit_ecdf <- function(y, return(p) } - # Independent method -------------------------------------------------- - gamma_indep <- adjust_gamma( - N = n_obs, - K = K, - prob = prob, - interpolate_adj = interpolate_adj - ) + # =========================================================================== + # Independent method + # =========================================================================== + + gamma_indep <- adjust_gamma(N = n_obs, K = K, prob = prob, + interpolate_adj = interpolate_adj) lims <- ecdf_intervals(gamma = gamma_indep, N = n_obs, K = K) - ecdf_eval <- .ecdf_pit_fn(unit_interval) - plot_diff * unit_interval - - # Precompute division by n_obs - n_obs_inv <- 1 / n_obs - lims_upper_scaled <- lims$upper[-1] * n_obs_inv - plot_diff * unit_interval - lims_lower_scaled <- lims$lower[-1] * n_obs_inv - plot_diff * unit_interval - + + # `lims` contains K + 1 elements (including the boundary at 0); drop it so + # lengths match `unit_interval`. + lims_upper <- lims$upper[-1L] / n_obs - plot_diff * unit_interval + lims_lower <- lims$lower[-1L] / n_obs - plot_diff * unit_interval + ecdf_eval <- ecdf_pit_fn(unit_interval) - plot_diff * unit_interval + p <- ggplot() + geom_step( - aes(x = unit_interval, y = lims_upper_scaled, color = "yrep"), - linetype = "dashed", linewidth = 0.3, show.legend = FALSE + mapping = aes(x = unit_interval, y = lims_upper, color = "yrep"), + linetype = "dashed", + linewidth = 0.3, + show.legend = FALSE ) + geom_step( - aes(x = unit_interval, y = lims_lower_scaled, color = "yrep"), - linetype = "dashed", linewidth = 0.3, show.legend = FALSE + mapping = aes(x = unit_interval, y = lims_lower, color = "yrep"), + linetype = "dashed", + linewidth = 0.3, + show.legend = FALSE ) + geom_step( - aes(x = unit_interval, y = ecdf_eval, color = "y", linewidth = linewidth), + mapping = aes(x = unit_interval, y = ecdf_eval, color = "y"), + linewidth = 0.5, show.legend = FALSE ) + - labs( - y = dplyr::if_else(plot_diff, "ECDF difference", "ECDF"), - x = "LOO PIT" - ) + + labs(x = x_label, y = y_label) + yaxis_ticks(FALSE) + scale_color_ppc() + bayesplot_theme_get() - + return(p) } From 06c5480029d7616b739f7bbd92d3bab3b25cbdfe Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Thu, 5 Mar 2026 10:19:38 +0200 Subject: [PATCH 090/120] add test for ppc_loo_pit_ecdf with pareto_pit support --- tests/testthat/test-ppc-loo.R | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/testthat/test-ppc-loo.R b/tests/testthat/test-ppc-loo.R index 147a2c08..a980146b 100644 --- a/tests/testthat/test-ppc-loo.R +++ b/tests/testthat/test-ppc-loo.R @@ -290,6 +290,44 @@ test_that("error if subset is bigger than num obs", { ) }) +test_that("ppc_loo_pit_ecdf works with pareto_pit method", { + skip_if_not_installed("brms") + skip_if_not_installed("rstanarm") + + data("roaches", package = "rstanarm") + roaches$sqrt_roach1 <- sqrt(roaches$roach1) + + fit_zinb <- + brms::brm(brms::bf(y ~ sqrt_roach1 + treatment + senior + offset(log(exposure2)), + zi ~ sqrt_roach1 + treatment + senior + offset(log(exposure2))), + family = brms::zero_inflated_negbinomial(), data = roaches, + prior = c(brms::prior(normal(0, 1), class = "b"), + brms::prior(normal(0, 1), class = "b", dpar = "zi"), + brms::prior(normal(0, 1), class = "Intercept", dpar = "zi")), + seed = 1704009, refresh = 1000) + + fit_zinb <- brms::add_criterion(fit_zinb, criterion = "loo", save_psis = TRUE) + fit_zinb <- brms::add_criterion(fit_zinb, criterion = "loo", save_psis = TRUE, + moment_match = TRUE, overwrite = TRUE) + + draws <- brms::posterior_predict(fit_zinb) + psis_object <- brms::loo(fit_zinb, save_psis = TRUE)$psis_object + y <- roaches$y + + expect_gg(ppc_loo_pit_ecdf( + y = y, yrep = draws, psis_object = psis_object, method = "correlated" + )) + + expect_gg(brms::pp_check( + fit_zinb, type = "loo_pit_ecdf", moment_match = TRUE, method = "correlated" + )) + # prit -> pareto_pit should not be default (doesn't matter whether y, yrep, pit is provided) + # y, yrep + pot, piet -> pareto_pit + # pit -> no additional pareto_pit + # add in the docs that the pareto_pit on/off should usually not be touched by the user. Default is okay + # secondary step: ppcheck in brms -> cdf based pit +}) + # Visual tests ------------------------------------------------------------ From 17e2f2e1a49be2090c391a1115f95470126ee5de Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Thu, 5 Mar 2026 11:02:16 +0200 Subject: [PATCH 091/120] fix typo in x-label --- R/ppc-loo.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 993af51f..2b562d28 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -757,7 +757,7 @@ ppc_loo_pit_ecdf <- function(y, linewidth = 0.5, show.legend = FALSE ) + - labs(x = x_label, y = y_label) + + labs(x = "PIT", y = y_label) + yaxis_ticks(FALSE) + scale_color_ppc() + bayesplot_theme_get() From 2d9892961bb1913afd2d041b3701c47b92f3be1d Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Thu, 5 Mar 2026 11:19:10 +0200 Subject: [PATCH 092/120] add test name in helper text --- R/ppc-loo.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 2b562d28..137a54c4 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -700,8 +700,8 @@ ppc_loo_pit_ecdf <- function(y, "text", x = -Inf, y = Inf, label = sprintf( - "p[unif] == '%.3f' ~ (alpha == '%.2f')", - p_value_CCT, alpha + "p[unif]^{%s} == '%.3f' ~ (alpha == '%.2f')", + test, p_value_CCT, alpha ), hjust = -0.05, vjust = 1.5, color = "black", parse = TRUE, size = label_size From cefd75bc95670739837c622174dd86a8ec04870b Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Thu, 5 Mar 2026 11:20:08 +0200 Subject: [PATCH 093/120] fix test regarding xlabel (changed from LOO PIT to PIT) --- tests/testthat/test-ppc-loo.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-ppc-loo.R b/tests/testthat/test-ppc-loo.R index a980146b..8e16856d 100644 --- a/tests/testthat/test-ppc-loo.R +++ b/tests/testthat/test-ppc-loo.R @@ -91,7 +91,7 @@ test_that("ppc_loo_pit_ecdf returns a ggplot object", { } else { ll1 <- p1$labels } - expect_equal(ll1$x, "LOO PIT") + expect_equal(ll1$x, "PIT") expect_equal(ll1$y, "ECDF") expect_equal(p1$data, p2$data) expect_gg(p3 <- ppc_loo_pit_ecdf(y, yrep, lw, plot_diff = TRUE)) From 0e69933470add39f3d574e50dcd3635b0f333c65 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Thu, 5 Mar 2026 11:20:35 +0200 Subject: [PATCH 094/120] update snapshots for visual regression test --- .../ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg | 35 ++-- .../ppc-loo-pit-ecdf-changed-theme.svg | 35 ++-- .../ppc-loo/ppc-loo-pit-ecdf-color-change.svg | 31 ++-- .../ppc-loo-pit-ecdf-correlated-piet.svg | 32 ++-- .../ppc-loo-pit-ecdf-correlated-pot.svg | 31 ++-- .../ppc-loo-pit-ecdf-correlated-prit.svg | 32 ++-- .../ppc-loo/ppc-loo-pit-ecdf-default.svg | 4 +- .../ppc-loo-pit-ecdf-diff-correlated-piet.svg | 32 ++-- .../ppc-loo-pit-ecdf-diff-correlated-pot.svg | 31 ++-- .../ppc-loo-pit-ecdf-diff-correlated-prit.svg | 32 ++-- .../ppc-loo-pit-ecdf-ecdf-difference.svg | 4 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg | 4 +- .../ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg | 31 ++-- .../ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg | 31 ++-- .../ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg | 6 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg | 4 +- .../ppc-loo-pit-overlay-boundary.new.svg | 149 ++++++++++++++++++ 17 files changed, 352 insertions(+), 172 deletions(-) create mode 100644 tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.new.svg diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg index 2ad02eff..20437e0d 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg @@ -25,23 +25,24 @@ - + - - -p -u -n -i -f -= -0.000 - -( -α -= -0.05 -) +p +u +n +i +f +P +O +T += +0.365 + +( +α += +0.05 +) @@ -66,7 +67,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF difference ppc_loo_pit_ecdf (alpha=0.05) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg index f5e8438f..e808491b 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg @@ -25,23 +25,24 @@ - + - - -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f +P +O +T += +0.365 + +( +α += +0.01 +) @@ -62,7 +63,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF difference ppc_loo_pit_ecdf (changed theme) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg index 578e3ace..0c8338ac 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg @@ -31,19 +31,22 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f +P +O +T += +0.000 + +( +α += +0.01 +) @@ -68,7 +71,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF ppc_loo_pit_ecdf (color change) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg index d6c38358..042ceb71 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg @@ -27,19 +27,23 @@ -p -u -n -i -f -= -0.188 - -( -α -= -0.01 -) +p +u +n +i +f +P +I +E +T += +0.188 + +( +α += +0.01 +) @@ -64,7 +68,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF ppc_loo_pit_ecdf (correlated piet) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg index bf9ed31e..68e55568 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg @@ -31,19 +31,22 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f +P +O +T += +0.000 + +( +α += +0.01 +) @@ -68,7 +71,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF ppc_loo_pit_ecdf (correlated pot) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg index 02eedb80..1a6be2aa 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg @@ -33,19 +33,23 @@ -p -u -n -i -f -= -0.001 - -( -α -= -0.01 -) +p +u +n +i +f +P +R +I +T += +0.001 + +( +α += +0.01 +) @@ -70,7 +74,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF ppc_loo_pit_ecdf (correlated prit) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg index 71e51c5e..deefd121 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-default.svg @@ -27,7 +27,7 @@ - + @@ -52,7 +52,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF ppc_loo_pit_ecdf (default) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg index e123b73f..be85fdb6 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg @@ -27,19 +27,23 @@ -p -u -n -i -f -= -0.188 - -( -α -= -0.01 -) +p +u +n +i +f +P +I +E +T += +0.188 + +( +α += +0.01 +) @@ -64,7 +68,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF difference ppc_loo_pit_ecdf (diff, correlated piet) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg index dce93313..ffd601d6 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg @@ -31,19 +31,22 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f +P +O +T += +0.000 + +( +α += +0.01 +) @@ -68,7 +71,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF difference ppc_loo_pit_ecdf (diff, correlated pot) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg index 9617b002..89de7335 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg @@ -33,19 +33,23 @@ -p -u -n -i -f -= -0.001 - -( -α -= -0.01 -) +p +u +n +i +f +P +R +I +T += +0.001 + +( +α += +0.01 +) @@ -70,7 +74,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF difference ppc_loo_pit_ecdf (diff, correlated prit) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg index cdf67834..8f4da5ef 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-ecdf-difference.svg @@ -27,7 +27,7 @@ - + @@ -48,7 +48,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF difference ppc_loo_pit_ecdf (ecdf difference) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg index 8e860dba..294aac36 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-k.svg @@ -27,7 +27,7 @@ - + @@ -52,7 +52,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF ppc_loo_pit_ecdf (K) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg index 0475f139..8cf9b740 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg @@ -31,19 +31,22 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f +P +O +T += +0.000 + +( +α += +0.01 +) @@ -68,7 +71,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF ppc_loo_pit_ecdf (linewidth = 1) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg index 0f0a588e..35f5c9ae 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg @@ -31,19 +31,22 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f +P +O +T += +0.000 + +( +α += +0.01 +) @@ -68,7 +71,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF ppc_loo_pit_ecdf (linewidth = 2) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg index 8afea555..1e64e37a 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg @@ -25,10 +25,8 @@ - + - - @@ -53,7 +51,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF difference ppc_loo_pit_ecdf (no help_text) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg index 6b0d9552..8127fd63 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-prob.svg @@ -27,7 +27,7 @@ - + @@ -52,7 +52,7 @@ 0.50 0.75 1.00 -LOO PIT +PIT ECDF ppc_loo_pit_ecdf (prob) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.new.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.new.svg new file mode 100644 index 00000000..07009b87 --- /dev/null +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.new.svg @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0.1 +0.3 +0.5 +0.7 +0.9 + + +PIT +Unif +ppc_loo_pit_overlay (boundary) + + From 5d6527276dc6c1c6ac92c2d0043cf85ebb7d4f0a Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Thu, 5 Mar 2026 13:02:59 +0200 Subject: [PATCH 095/120] fix that pareto_pit default can be changed by the user --- R/ppc-loo.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 137a54c4..e9f9a451 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -513,7 +513,7 @@ ppc_loo_pit_ecdf <- function(y, # Pareto PIT applies only when `pit` is not already supplied and the # test is POT or PIET. - pareto_pit <- is.null(pit) && test %in% c("POT", "PIET") + pareto_pit <- pareto_pit %||% is.null(pit) && test %in% c("POT", "PIET") }, "independent" = { # Collect args that are meaningless under the independent method. From d252f41ad0315afd401c034ad4a3228d16b1092d Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Thu, 5 Mar 2026 13:03:41 +0200 Subject: [PATCH 096/120] add pareto_pit support for ppc_pit_ecdf --- R/ppc-distributions.R | 367 +++++++++++++++++++++++++++--------------- 1 file changed, 233 insertions(+), 134 deletions(-) diff --git a/R/ppc-distributions.R b/R/ppc-distributions.R index 7d4c9c7f..103bd2cc 100644 --- a/R/ppc-distributions.R +++ b/R/ppc-distributions.R @@ -648,6 +648,17 @@ ppc_violin_grouped <- #' @param pit An optional vector of probability integral transformed values for #' which the ECDF is to be drawn. If NULL, PIT values are computed to `y` with #' respect to the corresponding values in `yrep`. +#' @param lw A matrix of (smoothed) log weights with the same dimensions as +#' `yrep`. See [loo::psis()] and the associated `weights()` method as well as +#' the **Examples** section, below. If `lw` is not specified then +#' `psis_object` can be provided and log weights will be extracted. +#' Only required if `pareto_pit = TRUE`. `pareto_pit` defaults to `TRUE` if +#' `method = "correlated"` and `test` is `"POT"` or `"PIET"`. +#' @param psis_object If using **loo** version `2.0.0` or greater, an +#' object returned by the `psis()` function (or by the `loo()` function +#' with argument `save_psis` set to `TRUE`). +#' Only required if `pareto_pit = TRUE`. `pareto_pit` defaults to `TRUE` if +#' `method = "correlated"` and `test` is `"POT"` or `"PIET"`. #' @param interpolate_adj For `ppc_loo_pit_ecdf()` when `method = "independent"`, #' a boolean defining if the simultaneous confidence bands should be #' interpolated based on precomputed values rather than computed exactly. @@ -669,13 +680,20 @@ ppc_violin_grouped <- #' with base color and highlight color for the ECDF plot. Defaults to #' `c(ecdf = "grey60", highlight = "red")`. The first element is used for #' the main ECDF line, the second for highlighted suspicious regions. -#' @param help_text For 'ppc_pit_ecdf()' when `method = "correlated"`, a boolean +#' @param help_text For `ppc_pit_ecdf()` when `method = "correlated"`, a boolean #' defining whether to add informative text to the plot. Defaults to `TRUE`. +#' @param pareto_pit For `ppc_pit_ecdf()`, a boolean defining whether to compute +#' the PIT values using Pareto-smoothed importance sampling (if `TRUE` and no pit values are provided). +#' Defaults to `TRUE` when `method = "correlated"` and `test` is `"POT"` or `"PIET"`. +#' Otherwise defaults to `FALSE`. If `TRUE` requires the specification of `lw` or `psis_object`. +#' The defaults should not be changed by the user, but the option is provided for developers. #' @rdname PPC-distributions #' ppc_pit_ecdf <- function(y, yrep, + lw = NULL, ..., + psis_object = NULL, pit = NULL, K = NULL, prob = .99, @@ -686,190 +704,268 @@ ppc_pit_ecdf <- function(y, gamma = NULL, linewidth = NULL, color = NULL, - help_text = NULL + help_text = NULL, + pareto_pit = NULL ) { + # Expected input combinations for ppc_pit_ecdf() based on method and test choices: + # | yrep | y | lw | psis_object | pit | method | test | pareto_pit | approach | + # |------|---|----|-------------|-----|-------------|------|------------|--------------------| + # | x | x | | | | independent | NULL | FALSE | empirical pit | + # | | | | | x | independent | NULL | FALSE | | + # | x | x | | x | | independent | NULL | TRUE | compute pareto-pit | + # | x | x | x | | | independent | NULL | TRUE | compute pareto-pit | + # | x | x | x | | | correlated | POT | TRUE | compute pareto-pit | + # | x | x | | x | | correlated | POT | TRUE | compute pareto-pit | + # | | | | | x | correlated | POT | FALSE | | + # | x | x | x | | | correlated | PIET | TRUE | compute pareto-pit | + # | x | x | | x | | correlated | PIET | TRUE | compute pareto-pit | + # | | | | | x | correlated | PIET | FALSE | | + # | x | x | | | | correlated | PRIT | FALSE | empirical pit | + # | | | | | x | correlated | PRIT | FALSE | | + check_ignored_arguments(..., - ok_args = c("K", "pit", "prob", "plot_diff", "interpolate_adj", - "method", "test", "gamma", "linewidth", "color", "help_text") + ok_args = c("K", "lw", "psis_object", "pareto_pit", "pit", "prob", "plot_diff", + "interpolate_adj", "method", "test", "gamma", "linewidth", "color", + "help_text") ) - method <- match.arg(method, choices = c("independent", "correlated")) + # --------------------------------------------------------------------------- + # Internal helpers + # --------------------------------------------------------------------------- - .warn_ignored <- function(method, args) { - msg <- paste0("As method = ", method, " specified; ignoring: ", - paste(args, collapse = ", "), ".") - inform(msg) + .warn_ignored <- function(method_name, args) { + inform(paste0( + "As method = ", method_name, " specified; ignoring: ", + paste(args, collapse = ", "), "." + )) } - if (is.null(pit)) { - pit <- ppc_data(y, yrep) %>% - group_by(.data$y_id) %>% - dplyr::group_map( - ~ mean(.x$value[.x$is_y] > .x$value[!.x$is_y]) + - runif(1, max = mean(.x$value[.x$is_y] == .x$value[!.x$is_y])) - ) %>% - unlist() - if (is.null(K)) { - K <- min(nrow(yrep) + 1, 1000) - } - } else { - pit <- validate_pit(pit) - if (is.null(K)) { - K <- length(pit) - } - ignored <- character(0) - if (!missing(y) && !is.null(y)) ignored <- c(ignored, "y") - if (!missing(yrep) && !is.null(yrep)) ignored <- c(ignored, "yrep") - if (length(ignored) > 0) { - inform(paste0("As 'pit' specified; ignoring: ", paste(ignored, collapse = ", "), ".")) - } - } + # --------------------------------------------------------------------------- + # Resolve and validate `method` + # --------------------------------------------------------------------------- + + method <- match.arg(method, choices = c("independent", "correlated")) + + + # --------------------------------------------------------------------------- + # Method-specific defaults, validation, and pareto_pit flag + # --------------------------------------------------------------------------- - # input validation and setting of defaults dependent on method switch(method, "correlated" = { if (!is.null(interpolate_adj)) .warn_ignored("'correlated'", "interpolate_adj") - test <- match.arg(test %||% "POT", choices = c("POT", "PRIT", "PIET")) + + test <- match.arg(test %||% "POT", choices = c("POT", "PRIT", "PIET")) alpha <- 1 - prob - gamma <- gamma %||% 0 + gamma <- gamma %||% 0 linewidth <- linewidth %||% 0.3 - color <- color %||% c(ecdf = "grey60", highlight = "red") + color <- color %||% c(ecdf = "grey60", highlight = "red") help_text <- help_text %||% TRUE + + # Pareto PIT applies for correlated only when lw/psis_object is supplied + # and the test is POT or PIET (not PRIT, which uses empirical PIT). + pareto_pit <- pareto_pit %||% is.null(pit) && !is.null(lw %||% psis_object) && + test %in% c("POT", "PIET") }, "independent" = { - ignored <- character(0) - if (!is.null(test)) ignored <- c(ignored, "test") - if (!is.null(gamma)) ignored <- c(ignored, "gamma") - if (!is.null(help_text)) ignored <- c(ignored, "help_text") + ignored <- c( + if (!is.null(test)) "test", + if (!is.null(gamma)) "gamma", + if (!is.null(help_text)) "help_text" + ) if (length(ignored) > 0) .warn_ignored("'independent'", ignored) + + # Pareto PIT applies for independent whenever lw/psis_object is supplied. + pareto_pit <- pareto_pit %||% is.null(pit) && !is.null(lw %||% psis_object) } ) - n_obs <- length(pit) + # --------------------------------------------------------------------------- + # Compute PIT values + # --------------------------------------------------------------------------- + + if (isTRUE(pareto_pit) && is.null(pit)) { + # --- Pareto-smoothed PIT --- + suggested_package("rstantools") + y <- validate_y(y) + yrep <- validate_predictions(yrep, length(y)) + lw <- .get_lw(NULL, psis_object) + stopifnot(identical(dim(yrep), dim(lw))) + + pit <- pareto_pit(x = yrep, y = y, weights = lw, log = TRUE) + K <- K %||% length(pit) + + } else if (!is.null(pit)) { + # --- Pre-supplied PIT values --- + pit <- validate_pit(pit) + K <- K %||% length(pit) + + # Warn about any ignored arguments. + ignored <- c( + if (!missing(y) && !is.null(y)) "y", + if (!missing(yrep) && !is.null(yrep)) "yrep", + if (!missing(lw) && !is.null(lw)) "lw", + if (!missing(psis_object) && !is.null(psis_object)) "psis_object" + ) + if (length(ignored) > 0) { + inform(paste0( + "As 'pit' specified; ignoring: ", + paste(ignored, collapse = ", "), "." + )) + } + + } else { + # --- Empirical PIT --- + pit <- ppc_data(y, yrep) %>% + group_by(.data$y_id) %>% + dplyr::group_map( + ~ mean(.x$value[.x$is_y] > .x$value[!.x$is_y]) + + runif(1, max = mean(.x$value[.x$is_y] == .x$value[!.x$is_y])) + ) %>% + unlist() + K <- K %||% min(nrow(yrep) + 1, 1000) + } + + # --------------------------------------------------------------------------- + # Shared ECDF setup + # --------------------------------------------------------------------------- + + n_obs <- length(pit) unit_interval <- seq(0, 1, length.out = K) - .ecdf_pit_fn <- ecdf(pit) + ecdf_pit_fn <- ecdf(pit) + y_label <- if (plot_diff) "ECDF difference" else "ECDF" + + # =========================================================================== + # Correlated method + # =========================================================================== - # Correlated method -------------------------------------------------- if (method == "correlated") { - # Compute test p-value and Cauchy-transformed values - if (test == "POT") { - std_cauchy_values <- .compute_cauchy(.pot_test(sort(pit))) - p_value_CCT <- .cauchy_combination_test(.pot_test(pit), truncate = TRUE) - } else if (test == "PIET") { - std_cauchy_values <- .compute_cauchy(.piet_test(sort(pit))) - p_value_CCT <- .cauchy_combination_test(.piet_test(pit), truncate = FALSE) - } else { # PRIT - std_cauchy_values <- .compute_cauchy(.prit_test(sort(pit))) - p_value_CCT <- .cauchy_combination_test(.prit_test(pit), truncate = TRUE) - } - pointwise_contribution <- .compute_shapley_values(std_cauchy_values) + # Compute the per-observation test statistics (sorted for Shapley values) + # and the combined Cauchy p-value. + test_fn <- switch(test, + POT = .pot_test, + PIET = .piet_test, + PRIT = .prit_test + ) + + pit_sorted <- sort(pit) + std_cauchy_values <- .compute_cauchy(test_fn(pit_sorted)) + p_value_CCT <- .cauchy_combination_test( + test_fn(pit), + truncate = test != "PIET" + ) + pointwise_contrib <- .compute_shapley_values(std_cauchy_values) - if (gamma < 0 || gamma > max(pointwise_contribution)) { + # Validate gamma against computed Shapley values. + max_contrib <- max(pointwise_contrib) + if (gamma < 0 || gamma > max_contrib) { stop(sprintf( - "gamma must be in the interval [0, %.2f], but gamma = %s was provided", - max(pointwise_contribution), gamma + "gamma must be in [0, %.2f], but gamma = %s was provided.", + max_contrib, gamma )) } - x_axis_combined <- sort(unique(c(unit_interval, pit))) - - # Evaluate at 0-1 interval b´values + + # Build the main ECDF data frame over a dense grid that includes pit values + # so step discontinuities are rendered exactly. + x_combined <- sort(unique(c(unit_interval, pit))) + df_main <- tibble::tibble( - x = x_axis_combined, - ecdf_pit = .ecdf_pit_fn(x_axis_combined) - plot_diff * x_axis_combined + x = x_combined, + ecdf_val = ecdf_pit_fn(x_combined) - plot_diff * x_combined ) - - # Evaluate at pit values (used for highlighing) + + # Sorted pit data frame (used for highlighting suspicious points). df_pit <- tibble::tibble( - pit = pit, - ecdf_pit = .ecdf_pit_fn(pit) - plot_diff * pit + pit = pit_sorted, + ecdf_val = ecdf_pit_fn(pit_sorted) - plot_diff * pit_sorted ) - df_pit <- df_pit[order(df_pit$pit), ] - # Plot ECDF + # --- Base plot ----------------------------------------------------------- + p <- ggplot() + geom_step( - data = df_main, aes(x = .data$x, y = .data$ecdf_pit), - show.legend = FALSE, linewidth = linewidth, color = color[1]) + - labs( - y = dplyr::if_else(plot_diff, "ECDF difference", "ECDF"), - x = "PIT" - ) - - # Add reference line - p <- p + geom_segment( - aes( - x = 0, y = 0, xend = 1, - yend = dplyr::if_else(plot_diff, 0, 1) - ), - linetype = "dashed", color = "darkgrey", linewidth = 0.3 - ) - - # Identify and highlight suspecious points (regions) of the ECDF + data = df_main, + mapping = aes(x = .data$x, y = .data$ecdf_val), + show.legend = FALSE, + linewidth = linewidth, + color = color["ecdf"] + ) + + geom_segment( + mapping = aes(x = 0, y = 0, xend = 1, yend = if (plot_diff) 0 else 1), + linetype = "dashed", + color = "darkgrey", + linewidth = 0.3 + ) + + labs(x = "PIT", y = y_label) + + # --- Highlight suspicious regions ---------------------------------------- + if (p_value_CCT < alpha) { - red_idx <- which(pointwise_contribution > gamma) + red_idx <- which(pointwise_contrib > gamma) if (length(red_idx) > 0) { df_red <- df_pit[red_idx, ] - - # Groups of consecutive suspicious points df_red$segment <- cumsum(c(1, diff(red_idx) != 1)) - # Separate isolated vs grouped points - segment_lengths <- stats::ave(df_red$pit, df_red$segment, FUN = length) - df_isolated <- df_red[segment_lengths == 1, ] - df_grouped <- df_red[segment_lengths > 1, ] + seg_sizes <- stats::ave(df_red$pit, df_red$segment, FUN = length) + df_isolated <- df_red[seg_sizes == 1, ] + df_grouped <- df_red[seg_sizes > 1, ] - # Create segments based on x_combined values for grouped points + # Highlight contiguous groups as coloured step segments. if (nrow(df_grouped) > 0) { - segments_list <- lapply( - split(df_grouped, df_grouped$segment), function(group) { - group_indices <- match(group$pit, x_axis_combined) - idx_range <- min(group_indices):max(group_indices) - + df_segments <- do.call(rbind, lapply( + split(df_grouped, df_grouped$segment), + function(grp) { + pit_idx <- match(grp$pit, x_combined) + idx_range <- seq(min(pit_idx), max(pit_idx)) tibble::tibble( - x = df_main$x[idx_range], - ecdf_pit = df_main$ecdf_pit[idx_range], - segment = group$segment[1] + x = df_main$x[idx_range], + ecdf_val = df_main$ecdf_val[idx_range], + segment = grp$segment[1L] ) } - ) - df_segments <- do.call(rbind, segments_list) + )) p <- p + geom_step( data = df_segments, - aes(x = .data$x, y = .data$ecdf_pit, group = .data$segment), - color = color[2], + mapping = aes(x = .data$x, y = .data$ecdf_val, group = .data$segment), + color = color["highlight"], linewidth = linewidth + 0.8 ) } + # Highlight isolated suspicious points as dots. if (nrow(df_isolated) > 0) { p <- p + geom_point( data = df_isolated, - aes(x = .data$pit, y = .data$ecdf_pit), - color = color[2], + aes(x = .data$pit, y = .data$ecdf_val), + color = color["highlight"], size = linewidth + 1 ) } } } - # Apply bayesplot theme and styling - if (help_text) { + # --- Annotation and axis scaling ----------------------------------------- + + if (isTRUE(help_text)) { + label_size <- 0.7 * bayesplot_theme_get()$text@size / ggplot2::.pt p <- p + annotate( "text", x = -Inf, y = Inf, - label = sprintf("p[unif] == '%.3f' ~ (alpha == '%.2f')", p_value_CCT, alpha), - hjust = -0.05, vjust = 1.5, color = "black", - parse = TRUE, size = 0.7 * bayesplot_theme_get()$text@size / ggplot2::.pt + label = sprintf("p[unif]^{%s} == '%.3f' ~ (alpha == '%.2f')", + test, p_value_CCT, alpha + ), + hjust = -0.05, vjust = 1.5, + color = "black", parse = TRUE, size = label_size ) } if (plot_diff) { epsilon = max( - sqrt(log(2 / (1 - prob)) / (2 * length(pit))), - max(abs(df_main$ecdf_pit)) + sqrt(log(2 / (1 - prob)) / (2 * n_obs)), + max(abs(df_main$ecdf_val)) ) p <- p + scale_y_continuous(limits = c(-epsilon, epsilon)) } @@ -882,37 +978,40 @@ ppc_pit_ecdf <- function(y, return(p) } - # Independent method -------------------------------------------------- - gamma_indep <- adjust_gamma( - N = n_obs, - K = K, - prob = prob, - interpolate_adj = interpolate_adj - ) + # =========================================================================== + # Independent method + # =========================================================================== + + gamma_indep <- adjust_gamma(N = n_obs, K = K, prob = prob, + interpolate_adj = interpolate_adj) lims <- ecdf_intervals(gamma = gamma_indep, N = n_obs, K = K) - ecdf_eval <- .ecdf_pit_fn(unit_interval) - plot_diff * unit_interval - lims_upper_scaled <- lims$upper[-1] * (1 / n_obs) - plot_diff * unit_interval - lims_lower_scaled <- lims$lower[-1] * (1 / n_obs) - plot_diff * unit_interval + # `lims` contains K + 1 elements (including the boundary at 0); drop it so + # lengths match `unit_interval`. + lims_upper <- lims$upper[-1] / n_obs - plot_diff * unit_interval + lims_lower <- lims$lower[-1] / n_obs - plot_diff * unit_interval + ecdf_eval <- ecdf_pit_fn(unit_interval) - plot_diff * unit_interval p <- ggplot() + geom_step( - aes(x = unit_interval, y = lims_upper_scaled, color = "yrep"), - linetype = "dashed", linewidth = 0.3, show.legend = FALSE + mapping = aes(x = unit_interval, y = lims_upper, color = "yrep"), + linetype = "dashed", + linewidth = 0.3, + show.legend = FALSE ) + geom_step( - aes(x = unit_interval, y = lims_lower_scaled, color = "yrep"), - linetype = "dashed", linewidth = 0.3, show.legend = FALSE + mapping = aes(x = unit_interval, y = lims_lower, color = "yrep"), + linetype = "dashed", + linewidth = 0.3, + show.legend = FALSE ) + geom_step( - aes(x = unit_interval, y = ecdf_eval, color = "y", linewidth = linewidth), + mapping = aes(x = unit_interval, y = ecdf_eval, color = "y"), + linewidth = 0.5, show.legend = FALSE ) + - labs( - y = dplyr::if_else(plot_diff, "ECDF difference", "ECDF"), - x = "PIT" - ) + + labs(x = "PIT", y = y_label) + yaxis_ticks(FALSE) + scale_color_ppc() + bayesplot_theme_get() From 353b56b67647d68267dd13e34877e1c5e438c072 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Thu, 5 Mar 2026 13:04:13 +0200 Subject: [PATCH 097/120] add test for checking correct PIT computation --- tests/testthat/test-ppc-loo.R | 223 ++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) diff --git a/tests/testthat/test-ppc-loo.R b/tests/testthat/test-ppc-loo.R index 8e16856d..78bed29b 100644 --- a/tests/testthat/test-ppc-loo.R +++ b/tests/testthat/test-ppc-loo.R @@ -579,3 +579,226 @@ test_that("ppc_loo_pit_ecdf renders correctly", { ) vdiffr::expect_doppelganger("ppc_loo_pit_ecdf (changed theme)", p_custom) }) + +# Test PIT computation branches ------------------------------------------------ +# use monkey-patching to test whether the correct branch of the +# PIT computation is taken + +ppc_loo_pit_ecdf_patched <- ppc_loo_pit_ecdf # copy + +body(ppc_loo_pit_ecdf_patched)[[ + # Replace the PIT computation block (the large if/else if/else) + # with a version that emits diagnostics + which(sapply(as.list(body(ppc_loo_pit_ecdf)), function(e) { + is.call(e) && deparse(e[[1]]) == "if" && + grepl("pareto_pit", deparse(e[[2]])) + })) +]] <- quote({ + + if (isTRUE(pareto_pit) && is.null(pit)) { + message("[PIT BRANCH] Pareto-smoothed LOO PIT") + suggested_package("rstantools") + y <- validate_y(y) + yrep <- validate_predictions(yrep, length(y)) + lw <- .get_lw(lw, psis_object) + stopifnot(identical(dim(yrep), dim(lw))) + pit <- pareto_pit(x = yrep, y = y, weights = lw, log = TRUE) + K <- K %||% length(pit) + + } else if (!is.null(pit)) { + message("[PIT BRANCH] Pre-supplied PIT") + pit <- validate_pit(pit) + K <- K %||% length(pit) + + ignored <- c( + if (!missing(y) && !is.null(y)) "y", + if (!missing(yrep) && !is.null(yrep)) "yrep", + if (!is.null(lw)) "lw" + ) + if (length(ignored) > 0) { + inform(paste0("As 'pit' specified; ignoring: ", + paste(ignored, collapse = ", "), ".")) + } + + } else { + message("[PIT BRANCH] Standard LOO PIT") + suggested_package("rstantools") + y <- validate_y(y) + yrep <- validate_predictions(yrep, length(y)) + lw <- .get_lw(lw, psis_object) + stopifnot(identical(dim(yrep), dim(lw))) + pit <- pmin(1, rstantools::loo_pit(object = yrep, y = y, lw = lw)) + K <- K %||% min(nrow(yrep) + 1, 1000) + } +}) + +testthat::test_that("ppc_loo_pit_ecdf takes correct PIT computation branch", { + skip_on_cran() + skip_if_not_installed("loo") + skip_on_r_oldrel() + skip_if(packageVersion("rstantools") <= "2.4.0") + + # | yrep | y | lw | psis_object | pit | method | test | pareto_pit | approach | + # |------|---|----|-------------|-----|-------------|------|------------|--------------------| + # | x | x | x | | | independent | NULL | FALSE (D) | compute loo-pit | + # | x | x | | x | | independent | NULL | FALSE (D) | compute loo-pit | + # | x | x | x | | | independent | NULL | TRUE | compute pareto-pit | + # | x | x | | x | | independent | NULL | TRUE | compute pareto-pit | + # | | | | | x | independent | NULL | FALSE | | + # | x | x | x | | | correlated | POT | TRUE | compute pareto-pit | + # | x | x | | x | | correlated | POT | TRUE | compute pareto-pit | + # | | | | | x | correlated | POT | FALSE | | + # | x | x | x | | | correlated | PIET | TRUE | compute pareto-pit | + # | x | x | | x | | correlated | PIET | TRUE | compute pareto-pit | + # | | | | | x | correlated | PIET | FALSE | | + # | x | x | x | | | correlated | PRIT | FALSE | compute loo-pit | + # | x | x | | x | | correlated | PRIT | FALSE | compute loo-pit | + # | | | | | x | correlated | PRIT | FALSE | | + + psis_object <- suppressWarnings(loo::psis(-vdiff_loo_lw)) + pits <- rstantools::loo_pit(vdiff_loo_yrep, vdiff_loo_y, vdiff_loo_lw) + + # method = independent ------------------------------------------ + expect_message( + ppc_loo_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "independent", + lw = vdiff_loo_lw + ), + regexp = "\\[PIT BRANCH\\] Standard LOO PIT" + ) + + expect_message( + ppc_loo_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "independent", + psis_object = psis_object, + ), + regexp = "\\[PIT BRANCH\\] Standard LOO PIT" + ) + + expect_message( + ppc_loo_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "independent", + psis_object = psis_object, + pareto_pit = TRUE + ), + regexp = "\\[PIT BRANCH\\] Pareto-smoothed LOO PIT" + ) + + expect_message( + ppc_loo_pit_ecdf_patched( + method = "independent", + pit = pits, + ), + regexp = "\\[PIT BRANCH\\] Pre-supplied PIT" + ) + + # method = correlated + POT test ------------------------------- + expect_message( + ppc_loo_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "correlated", + lw = vdiff_loo_lw + ), + regexp = "\\[PIT BRANCH\\] Pareto-smoothed LOO PIT" + ) + + expect_message( + ppc_loo_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "correlated", + lw = vdiff_loo_lw, + pareto_pit = FALSE + ), + regexp = "\\[PIT BRANCH\\] Standard LOO PIT" + ) + + expect_message( + ppc_loo_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "correlated", + psis_object = psis_object, + ), + regexp = "\\[PIT BRANCH\\] Pareto-smoothed LOO PIT" + ) + + expect_message( + ppc_loo_pit_ecdf_patched( + method = "correlated", + pit = pits, + ), + regexp = "\\[PIT BRANCH\\] Pre-supplied PIT" + ) + + # method = correlated + PIET test ------------------------------- + expect_message( + ppc_loo_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "correlated", + test = "PIET", + lw = vdiff_loo_lw + ), + regexp = "\\[PIT BRANCH\\] Pareto-smoothed LOO PIT" + ) + + expect_message( + ppc_loo_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "correlated", + test = "PIET", + psis_object = psis_object, + ), + regexp = "\\[PIT BRANCH\\] Pareto-smoothed LOO PIT" + ) + + expect_message( + ppc_loo_pit_ecdf_patched( + method = "correlated", + test = "PIET", + pit = pits, + ), + regexp = "\\[PIT BRANCH\\] Pre-supplied PIT" + ) + + # method = correlated + PRIT test ------------------------------- + expect_message( + ppc_loo_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "correlated", + test = "PRIT", + lw = vdiff_loo_lw + ), + regexp = "\\[PIT BRANCH\\] Standard LOO PIT" + ) + + expect_message( + ppc_loo_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "correlated", + test = "PRIT", + psis_object = psis_object, + ), + regexp = "\\[PIT BRANCH\\] Standard LOO PIT" + ) + + expect_message( + ppc_loo_pit_ecdf_patched( + method = "correlated", + test = "PRIT", + pit = pits, + ), + regexp = "\\[PIT BRANCH\\] Pre-supplied PIT" + ) +}) \ No newline at end of file From 846efae573f0138c002f8cfe2cd225351b3516d2 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Thu, 5 Mar 2026 13:04:43 +0200 Subject: [PATCH 098/120] add test for correct PIT comptutation with ppc_pit_ecdf --- tests/testthat/test-ppc-distributions.R | 213 ++++++++++++++++++++++++ 1 file changed, 213 insertions(+) diff --git a/tests/testthat/test-ppc-distributions.R b/tests/testthat/test-ppc-distributions.R index 385db16d..8a55d0c5 100644 --- a/tests/testthat/test-ppc-distributions.R +++ b/tests/testthat/test-ppc-distributions.R @@ -558,4 +558,217 @@ test_that("ppc_pit_ecdf renders different linewidths and colors correctly", { color = c(ecdf = "darkblue", highlight = "red") ) vdiffr::expect_doppelganger("ppc_pit_ecdf (color change)", p_cor_col) +}) + + +# Test PIT computation branches ------------------------------------------------ +# use monkey-patching to test whether the correct branch of the +# PIT computation is taken + +ppc_pit_ecdf_patched <- ppc_pit_ecdf # copy + +body(ppc_pit_ecdf_patched)[[ + # Replace the PIT computation block (the large if/else if/else) + # with a version that emits diagnostics + which(sapply(as.list(body(ppc_pit_ecdf)), function(e) { + is.call(e) && deparse(e[[1]]) == "if" && + grepl("pareto_pit", deparse(e[[2]])) + })) +]] <- quote({ + + if (isTRUE(pareto_pit) && is.null(pit)) { + message("[PIT BRANCH] Pareto-smoothed LOO PIT") + suggested_package("rstantools") + y <- validate_y(y) + yrep <- validate_predictions(yrep, length(y)) + lw <- .get_lw(lw, psis_object) + stopifnot(identical(dim(yrep), dim(lw))) + pit <- pareto_pit(x = yrep, y = y, weights = lw, log = TRUE) + K <- K %||% length(pit) + + } else if (!is.null(pit)) { + message("[PIT BRANCH] Pre-supplied PIT") + pit <- validate_pit(pit) + K <- K %||% length(pit) + + ignored <- c( + if (!missing(y) && !is.null(y)) "y", + if (!missing(yrep) && !is.null(yrep)) "yrep", + if (!is.null(lw)) "lw" + ) + if (length(ignored) > 0) { + inform(paste0("As 'pit' specified; ignoring: ", + paste(ignored, collapse = ", "), ".")) + } + + } else { + message("[PIT BRANCH] Empirical PIT") + pit <- ppc_data(y, yrep) %>% + group_by(.data$y_id) %>% + dplyr::group_map( + ~ mean(.x$value[.x$is_y] > .x$value[!.x$is_y]) + + runif(1, max = mean(.x$value[.x$is_y] == .x$value[!.x$is_y])) + ) %>% + unlist() + K <- K %||% min(nrow(yrep) + 1, 1000) + } +}) + +testthat::test_that("ppc_pit_ecdf takes correct PIT computation branch", { + skip_on_cran() + skip_if_not_installed("loo") + skip_on_r_oldrel() + skip_if(packageVersion("rstantools") <= "2.4.0") + + # | yrep | y | lw | psis_object | pit | method | test | pareto_pit | approach | + # |------|---|----|-------------|-----|-------------|------|------------|--------------------| + # | x | x | | | | independent | NULL | FALSE (D) | empirical pit | + # | x | x | x | | | independent | NULL | TRUE | compute pareto-pit | + # | x | x | | x | | independent | NULL | TRUE | compute pareto-pit | + # | | | | | x | independent | NULL | FALSE | | + # | x | x | x | | | correlated | POT | TRUE | compute pareto-pit | + # | x | x | | x | | correlated | POT | TRUE | compute pareto-pit | + # | | | | | x | correlated | POT | FALSE | | + # | x | x | x | | | correlated | PIET | TRUE | compute pareto-pit | + # | x | x | | x | | correlated | PIET | TRUE | compute pareto-pit | + # | | | | | x | correlated | PIET | FALSE | | + # | x | x | x | | | correlated | PRIT | FALSE | empirical pit | + # | x | x | | x | | correlated | PRIT | FALSE | empirical pit | + # | | | | | x | correlated | PRIT | FALSE | | + + psis_object <- suppressWarnings(loo::psis(-vdiff_loo_lw)) + pits <- rstantools::loo_pit(vdiff_loo_yrep, vdiff_loo_y, vdiff_loo_lw) + + # method = independent ------------------------------------------ + expect_message( + ppc_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "independent" + ), + regexp = "\\[PIT BRANCH\\] Empirical PIT" + ) + + expect_message( + ppc_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "independent", + psis_object = psis_object, + pareto_pit = TRUE + ), + regexp = "\\[PIT BRANCH\\] Pareto-smoothed LOO PIT" + ) + + expect_message( + ppc_pit_ecdf_patched( + method = "independent", + pit = pits, + ), + regexp = "\\[PIT BRANCH\\] Pre-supplied PIT" + ) + + # method = correlated + POT test ------------------------------- + expect_message( + ppc_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "correlated", + lw = vdiff_loo_lw + ), + regexp = "\\[PIT BRANCH\\] Pareto-smoothed LOO PIT" + ) + + expect_message( + ppc_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "correlated", + lw = vdiff_loo_lw, + pareto_pit = FALSE + ), + regexp = "\\[PIT BRANCH\\] Empirical PIT" + ) + + expect_message( + ppc_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "correlated", + psis_object = psis_object, + ), + regexp = "\\[PIT BRANCH\\] Pareto-smoothed LOO PIT" + ) + + expect_message( + ppc_pit_ecdf_patched( + method = "correlated", + pit = pits, + ), + regexp = "\\[PIT BRANCH\\] Pre-supplied PIT" + ) + + # method = correlated + PIET test ------------------------------- + expect_message( + ppc_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "correlated", + test = "PIET", + lw = vdiff_loo_lw + ), + regexp = "\\[PIT BRANCH\\] Pareto-smoothed LOO PIT" + ) + + expect_message( + ppc_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "correlated", + test = "PIET", + psis_object = psis_object, + ), + regexp = "\\[PIT BRANCH\\] Pareto-smoothed LOO PIT" + ) + + expect_message( + ppc_pit_ecdf_patched( + method = "correlated", + test = "PIET", + pit = pits, + ), + regexp = "\\[PIT BRANCH\\] Pre-supplied PIT" + ) + + # method = correlated + PRIT test ------------------------------- + expect_message( + ppc_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "correlated", + test = "PRIT", + lw = vdiff_loo_lw + ), + regexp = "\\[PIT BRANCH\\] Empirical PIT" + ) + + expect_message( + ppc_pit_ecdf_patched( + vdiff_loo_y, + vdiff_loo_yrep, + method = "correlated", + test = "PRIT", + psis_object = psis_object, + ), + regexp = "\\[PIT BRANCH\\] Empirical PIT" + ) + + expect_message( + ppc_pit_ecdf_patched( + method = "correlated", + test = "PRIT", + pit = pits, + ), + regexp = "\\[PIT BRANCH\\] Pre-supplied PIT" + ) }) \ No newline at end of file From 90ecc79fd65860130b1cce08af9c1d3990264f80 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Thu, 5 Mar 2026 13:05:02 +0200 Subject: [PATCH 099/120] update snapshots for visual regression test --- .../ppc-pit-ecdf-color-change.svg | 29 ++-- .../ppc-pit-ecdf-correlated-diff.svg | 29 ++-- .../ppc-pit-ecdf-correlated-piet-2.svg | 30 ++-- .../ppc-pit-ecdf-correlated-piet.svg | 30 ++-- .../ppc-pit-ecdf-correlated-pot.svg | 29 ++-- .../ppc-pit-ecdf-correlated-prit-2.svg | 30 ++-- .../ppc-pit-ecdf-correlated-prit.svg | 30 ++-- .../ppc-pit-ecdf-correlated.svg | 29 ++-- .../ppc-pit-ecdf-default.svg | 2 +- .../ppc-pit-ecdf-diff-correlated-piet.svg | 30 ++-- .../ppc-pit-ecdf-diff-correlated-pot.svg | 29 ++-- .../ppc-pit-ecdf-diff-correlated-prit.svg | 30 ++-- .../ppc-distributions/ppc-pit-ecdf-diff.svg | 2 +- .../ppc-pit-ecdf-linewidth-1.svg | 29 ++-- .../ppc-pit-ecdf-linewidth-2.svg | 29 ++-- .../ppc-loo-pit-overlay-boundary.new.svg | 149 ------------------ 16 files changed, 216 insertions(+), 320 deletions(-) delete mode 100644 tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.new.svg diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-color-change.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-color-change.svg index 7d6fc9dd..18b5da8f 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-color-change.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-color-change.svg @@ -31,19 +31,22 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f +P +O +T += +0.000 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-diff.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-diff.svg index dc6a6a75..9a55a76c 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-diff.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-diff.svg @@ -28,19 +28,22 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f +P +O +T += +0.000 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet-2.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet-2.svg index 44d075ad..d0bbbee5 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet-2.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet-2.svg @@ -27,19 +27,23 @@ -p -u -n -i -f -= -0.188 - -( -α -= -0.01 -) +p +u +n +i +f +P +I +E +T += +0.188 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet.svg index 8a4f3bd2..5cd9dd58 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet.svg @@ -28,19 +28,23 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f +P +I +E +T += +0.000 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-pot.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-pot.svg index 9763250d..41a31cbe 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-pot.svg @@ -31,19 +31,22 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f +P +O +T += +0.000 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit-2.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit-2.svg index 31f7189b..3e3bda99 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit-2.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit-2.svg @@ -33,19 +33,23 @@ -p -u -n -i -f -= -0.001 - -( -α -= -0.01 -) +p +u +n +i +f +P +R +I +T += +0.001 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit.svg index b04839b4..12d47b39 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-prit.svg @@ -28,19 +28,23 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f +P +R +I +T += +0.000 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated.svg index 5e7efdfe..b3340b7a 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated.svg @@ -28,19 +28,22 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f +P +O +T += +0.000 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg index f3b71ce0..8a46a332 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-default.svg @@ -27,7 +27,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-piet.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-piet.svg index 8ec9dace..40ba9439 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-piet.svg @@ -27,19 +27,23 @@ -p -u -n -i -f -= -0.188 - -( -α -= -0.01 -) +p +u +n +i +f +P +I +E +T += +0.188 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-pot.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-pot.svg index e7cff9d1..0b7d33b0 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-pot.svg @@ -31,19 +31,22 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f +P +O +T += +0.000 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-prit.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-prit.svg index 1645ac6c..4f44596c 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-prit.svg @@ -33,19 +33,23 @@ -p -u -n -i -f -= -0.001 - -( -α -= -0.01 -) +p +u +n +i +f +P +R +I +T += +0.001 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg index 472e39ef..36e743b5 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff.svg @@ -27,7 +27,7 @@ - + diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-1.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-1.svg index c8e891d6..6452a003 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-1.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-1.svg @@ -31,19 +31,22 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f +P +O +T += +0.000 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-2.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-2.svg index d4a71e76..f851d807 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-2.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-linewidth-2.svg @@ -31,19 +31,22 @@ -p -u -n -i -f -= -0.000 - -( -α -= -0.01 -) +p +u +n +i +f +P +O +T += +0.000 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.new.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.new.svg deleted file mode 100644 index 07009b87..00000000 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-overlay-boundary.new.svg +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0.1 -0.3 -0.5 -0.7 -0.9 - - -PIT -Unif -ppc_loo_pit_overlay (boundary) - - From eb39bd88bf29febfbdba125d0808e06a09f134d1 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Thu, 5 Mar 2026 15:32:51 +0200 Subject: [PATCH 100/120] change default pareto_pit from True to False for method='independent' --- R/ppc-distributions.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/ppc-distributions.R b/R/ppc-distributions.R index 103bd2cc..4f1adae7 100644 --- a/R/ppc-distributions.R +++ b/R/ppc-distributions.R @@ -776,7 +776,7 @@ ppc_pit_ecdf <- function(y, if (length(ignored) > 0) .warn_ignored("'independent'", ignored) # Pareto PIT applies for independent whenever lw/psis_object is supplied. - pareto_pit <- pareto_pit %||% is.null(pit) && !is.null(lw %||% psis_object) + pareto_pit <- pareto_pit %||% FALSE } ) From 7864f9756c79c65d0c638f4a1780c143af837af6 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Thu, 5 Mar 2026 15:34:05 +0200 Subject: [PATCH 101/120] add test for using ppc_pit_ecdf with brms::pp_check() --- tests/testthat/test-ppc-distributions.R | 33 ++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-ppc-distributions.R b/tests/testthat/test-ppc-distributions.R index 8a55d0c5..0a7d2ebf 100644 --- a/tests/testthat/test-ppc-distributions.R +++ b/tests/testthat/test-ppc-distributions.R @@ -153,7 +153,7 @@ test_that("ppc_pit_ecdf method validation and ignored-argument warnings", { test_that("ppc_pit_ecdf correlated method validates gamma", { expect_error( ppc_pit_ecdf(y, yrep, method = "correlated", gamma = -1), - "gamma must be in the interval" + regexp = "gamma must be in" ) }) @@ -771,4 +771,35 @@ testthat::test_that("ppc_pit_ecdf takes correct PIT computation branch", { ), regexp = "\\[PIT BRANCH\\] Pre-supplied PIT" ) +}) + +test_that("ppc_pit_ecdf works with pareto_pit method", { + skip_if_not_installed("brms") + skip_if_not_installed("rstanarm") + + data("roaches", package = "rstanarm") + roaches$sqrt_roach1 <- sqrt(roaches$roach1) + + fit_p <- brms::brm(y ~ sqrt_roach1 + treatment + senior + offset(log(exposure2)), + data = roaches, + family = poisson, + prior = brms::prior(normal(0, 1), class = b), + refresh = 0) + + fit_p <- brms::add_criterion(fit_p, criterion = "loo") + fit_p <- brms::add_criterion(fit_p, criterion = "loo", moment_match = TRUE, overwrite = TRUE) + fit_nb <- update(fit_p, family = brms::negbinomial) + + expect_gg(brms::pp_check(fit_nb, type = "pit_ecdf")) + + draws <- brms::posterior_predict(fit_nb) + psis_object <- brms::loo(fit_nb, save_psis = TRUE)$psis_object + y <- roaches$y + + expect_gg(ppc_pit_ecdf( + y = y, yrep = draws, psis_object = psis_object, method = "correlated" + )) + + expect_gg(brms::pp_check(fit_nb, type = "pit_ecdf", method = "correlated", + psis_object = psis_object)) }) \ No newline at end of file From caa00b911b48ef87037a87ca49bb6fd45e218983 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Thu, 5 Mar 2026 15:34:48 +0200 Subject: [PATCH 102/120] add args-methods-dots to man-roxygen folder --- man-roxygen/args-methods-dots.R | 1 + 1 file changed, 1 insertion(+) create mode 100644 man-roxygen/args-methods-dots.R diff --git a/man-roxygen/args-methods-dots.R b/man-roxygen/args-methods-dots.R new file mode 100644 index 00000000..4e0e6c4a --- /dev/null +++ b/man-roxygen/args-methods-dots.R @@ -0,0 +1 @@ +#' @param ... Arguments passed to individual methods (if applicable). From dcb7663f2194a6ea7be29bd4d316986bfc44b668 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Thu, 5 Mar 2026 15:35:03 +0200 Subject: [PATCH 103/120] update documentation --- NAMESPACE | 7 ++++ man/PPC-distributions.Rd | 26 +++++++++++- man/PPC-loo.Rd | 8 +++- man/gpdfit.Rd | 53 +++++++++++++++++++++++++ man/pareto_pit.Rd | 81 ++++++++++++++++++++++++++++++++++++++ man/pgeneralized_pareto.Rd | 39 ++++++++++++++++++ man/qgeneralized_pareto.Rd | 39 ++++++++++++++++++ 7 files changed, 250 insertions(+), 3 deletions(-) create mode 100644 man/gpdfit.Rd create mode 100644 man/pareto_pit.Rd create mode 100644 man/pgeneralized_pareto.Rd create mode 100644 man/qgeneralized_pareto.Rd diff --git a/NAMESPACE b/NAMESPACE index b8cf818b..abc7365e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -27,6 +27,9 @@ S3method(nuts_params,stanreg) S3method(parameter_names,array) S3method(parameter_names,default) S3method(parameter_names,matrix) +S3method(pareto_pit,default) +S3method(pareto_pit,draws_matrix) +S3method(pareto_pit,rvar) S3method(plot,bayesplot_grid) S3method(plot,bayesplot_scheme) S3method(pp_check,default) @@ -55,6 +58,7 @@ export(example_y_data) export(example_yrep_draws) export(facet_bg) export(facet_text) +export(gpdfit) export(grid_lines) export(hline_0) export(hline_at) @@ -115,6 +119,8 @@ export(panel_bg) export(param_glue) export(param_range) export(parcoord_style_np) +export(pareto_pit) +export(pgeneralized_pareto) export(plot_bg) export(pp_check) export(ppc_bars) @@ -190,6 +196,7 @@ export(ppd_stat_data) export(ppd_stat_freqpoly) export(ppd_stat_freqpoly_grouped) export(ppd_stat_grouped) +export(qgeneralized_pareto) export(rhat) export(scatter_style_np) export(theme_default) diff --git a/man/PPC-distributions.Rd b/man/PPC-distributions.Rd index d875e368..cde64441 100644 --- a/man/PPC-distributions.Rd +++ b/man/PPC-distributions.Rd @@ -126,7 +126,9 @@ ppc_violin_grouped( ppc_pit_ecdf( y, yrep, + lw = NULL, ..., + psis_object = NULL, pit = NULL, K = NULL, prob = 0.99, @@ -137,7 +139,8 @@ ppc_pit_ecdf( gamma = NULL, linewidth = NULL, color = NULL, - help_text = NULL + help_text = NULL, + pareto_pit = NULL ) ppc_pit_ecdf_grouped( @@ -224,6 +227,19 @@ to to the \code{size}, \code{alpha}, and \code{width} arguments of \code{\link[g to control the appearance of \code{y} points. The default of \code{y_jitter=NULL} will let \strong{ggplot2} determine the amount of jitter.} +\item{lw}{A matrix of (smoothed) log weights with the same dimensions as +\code{yrep}. See \code{\link[loo:psis]{loo::psis()}} and the associated \code{weights()} method as well as +the \strong{Examples} section, below. If \code{lw} is not specified then +\code{psis_object} can be provided and log weights will be extracted. +Only required if \code{pareto_pit = TRUE}. \code{pareto_pit} defaults to \code{TRUE} if +\code{method = "correlated"} and \code{test} is \code{"POT"} or \code{"PIET"}.} + +\item{psis_object}{If using \strong{loo} version \verb{2.0.0} or greater, an +object returned by the \code{psis()} function (or by the \code{loo()} function +with argument \code{save_psis} set to \code{TRUE}). +Only required if \code{pareto_pit = TRUE}. \code{pareto_pit} defaults to \code{TRUE} if +\code{method = "correlated"} and \code{test} is \code{"POT"} or \code{"PIET"}.} + \item{pit}{An optional vector of probability integral transformed values for which the ECDF is to be drawn. If NULL, PIT values are computed to \code{y} with respect to the corresponding values in \code{yrep}.} @@ -273,8 +289,14 @@ with base color and highlight color for the ECDF plot. Defaults to \code{c(ecdf = "grey60", highlight = "red")}. The first element is used for the main ECDF line, the second for highlighted suspicious regions.} -\item{help_text}{For 'ppc_pit_ecdf()' when \code{method = "correlated"}, a boolean +\item{help_text}{For \code{ppc_pit_ecdf()} when \code{method = "correlated"}, a boolean defining whether to add informative text to the plot. Defaults to \code{TRUE}.} + +\item{pareto_pit}{For \code{ppc_pit_ecdf()}, a boolean defining whether to compute +the PIT values using Pareto-smoothed importance sampling (if \code{TRUE} and no pit values are provided). +Defaults to \code{TRUE} when \code{method = "correlated"} and \code{test} is \code{"POT"} or \code{"PIET"}. +Otherwise defaults to \code{FALSE}. If \code{TRUE} requires the specification of \code{lw} or \code{psis_object}. +The defaults should not be changed by the user, but the option is provided for developers.} } \value{ The plotting functions return a ggplot object that can be further diff --git a/man/PPC-loo.Rd b/man/PPC-loo.Rd index cd1bb767..52aa4010 100644 --- a/man/PPC-loo.Rd +++ b/man/PPC-loo.Rd @@ -71,7 +71,8 @@ ppc_loo_pit_ecdf( gamma = NULL, linewidth = NULL, color = NULL, - help_text = NULL + help_text = NULL, + pareto_pit = NULL ) ppc_loo_pit( @@ -231,6 +232,11 @@ the main ECDF line, the second for highlighted suspicious regions.} \item{help_text}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, a boolean defining whether to add informative text to the plot. Defaults to \code{TRUE}.} +\item{pareto_pit}{For \code{ppc_loo_pit_ecdf()}. Computes PIT values using Pareto-PIT method. +Defaults to \code{TRUE} if \code{test} is either \code{"POT"} or \code{"PIET"} and no \code{pit} values are +provided otherwise \code{FALSE}. This argument should not normally be modified by the user, +except for development purposes.} + \item{subset}{For \code{ppc_loo_intervals()} and \code{ppc_loo_ribbon()}, an optional integer vector indicating which observations in \code{y} (and \code{yrep}) to include. Dropping observations from \code{y} and \code{yrep} manually before passing diff --git a/man/gpdfit.Rd b/man/gpdfit.Rd new file mode 100644 index 00000000..e0567025 --- /dev/null +++ b/man/gpdfit.Rd @@ -0,0 +1,53 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/helpers-ppc.R +\name{gpdfit} +\alias{gpdfit} +\title{Estimate parameters of the Generalized Pareto distribution} +\usage{ +gpdfit(x, wip = TRUE, min_grid_pts = 30, sort_x = TRUE, weights = NULL) +} +\arguments{ +\item{x}{A numeric vector. The sample from which to estimate the +parameters.} + +\item{wip}{Logical indicating whether to adjust \eqn{k} based on a +weakly informative Gaussian prior centered on 0.5. Defaults to +\code{TRUE}.} + +\item{min_grid_pts}{The minimum number of grid points used in the +fitting algorithm. The actual number used is \code{min_grid_pts + floor(sqrt(length(x)))}.} + +\item{sort_x}{If \code{TRUE} (the default), the first step in the +fitting algorithm is to sort the elements of \code{x}. If \code{x} is +already sorted in ascending order then \code{sort_x} can be set to +\code{FALSE} to skip the initial sorting step.} + +\item{weights}{An optional numeric vector of positive weights the same +length as \code{x}. If \code{NULL} (the default), all observations are +weighted equally and the result is identical to the unweighted fit. +Weights are normalized internally to sum to \code{length(x)}.} +} +\value{ +A named list with components \code{k} and \code{sigma}. +} +\description{ +Given a sample \eqn{x}, Estimate the parameters \eqn{k} and +\eqn{\sigma} of the generalized Pareto distribution (GPD), assuming +the location parameter is 0. By default the fit uses a prior for +\eqn{k} (this is in addition to the prior described by Zhang and +Stephens, 2009), which will stabilize estimates for very small +sample sizes (and low effective sample sizes in the case of MCMC +samples). The weakly informative prior is a Gaussian prior centered +at 0.5 (see details in Vehtari et al., 2024). This is used +internally but is exported for use by other packages. +} +\details{ +Here the parameter \eqn{k} is the negative of \eqn{k} in Zhang & +Stephens (2009). +} +\references{ +Zhang, J., and Stephens, M. A. (2009). A new and efficient estimation method +for the generalized Pareto distribution. \emph{Technometrics} \strong{51}, 316-325. +} +\concept{helper-functions} +\keyword{internal} diff --git a/man/pareto_pit.Rd b/man/pareto_pit.Rd new file mode 100644 index 00000000..ed931555 --- /dev/null +++ b/man/pareto_pit.Rd @@ -0,0 +1,81 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/helpers-ppc.R +\name{pareto_pit} +\alias{pareto_pit} +\alias{pareto_pit.default} +\alias{pareto_pit.draws_matrix} +\alias{pareto_pit.rvar} +\title{Pareto-smoothed probability integral transform} +\usage{ +pareto_pit(x, y, ...) + +\method{pareto_pit}{default}(x, y, weights = NULL, log = FALSE, ndraws_tail = NULL, ...) + +\method{pareto_pit}{draws_matrix}(x, y, weights = NULL, log = FALSE, ndraws_tail = NULL, ...) + +\method{pareto_pit}{rvar}(x, y, weights = NULL, log = FALSE, ndraws_tail = NULL, ...) +} +\arguments{ +\item{x}{(draws) A \code{\link[posterior:draws_matrix]{posterior::draws_matrix}} object or one coercible to a +\code{draws_matrix} object, or an \code{\link[posterior:rvar]{posterior::rvar}} object.} + +\item{y}{(observations) A 1D vector, or an array of dim(x), if x is \code{rvar}. +Each element of \code{y} corresponds to a variable in \code{x}.} + +\item{...}{Arguments passed to individual methods (if applicable).} + +\item{weights}{A matrix of weights for each draw and variable. \code{weights} +should have one column per variable in \code{x}, and \code{ndraws(x)} rows.} + +\item{log}{(logical) Are the weights passed already on the log scale? The +default is \code{FALSE}, that is, expecting \code{weights} to be on the standard +(non-log) scale.} + +\item{ndraws_tail}{(integer) Number of tail draws to use for GPD +fitting. If \code{NULL} (the default), computed using \code{\link[posterior:ps_tail_length]{posterior::ps_tail_length()}}.} +} +\value{ +A numeric vector of length \code{length(y)} containing the PIT values, or +an array of shape \code{dim(y)}, if \code{x} is an \code{rvar}. +} +\description{ +Compute PIT values using the empirical CDF, then refine values in +the tails by fitting a generalized Pareto distribution (GPD) to +the tail draws. This gives smoother, more accurate PIT values in +the tails where the ECDF is coarse, and avoids PIT values of 0 and 1. +Due to use of generalized Pareto distribution CDF in tails, the +PIT values are not anymore rank based and continuous uniformity +test is appropriate. +} +\details{ +The function first computes raw PIT values identically to +\code{\link[posterior:pit]{posterior::pit()}} (including support for weighted draws). It then fits a +GPD to both tails of the draws (using the same approach as +\code{\link[posterior:pareto_smooth]{posterior::pareto_smooth()}}) and replaces PIT values for observations falling in +the tail regions: + +For a right-tail observation \eqn{y_i > c_R} (where \eqn{c_R} is +the right-tail cutoff): + +\deqn{PIT(y_i) = 1 - p_{tail}(1 - F_{GPD}(y_i; c_R, \sigma_R, k_R))} + +For a left-tail observation \eqn{y_i < c_L}: + +\deqn{PIT(y_i) = p_{tail}(1 - F_{GPD}(-y_i; -c_L, \sigma_L, k_L))} + +where \eqn{p_{tail}} is the proportion of (weighted) mass in the +tail. + +When (log-)weights in \code{weights} are provided, they are used for +the raw PIT computation (as in \code{\link[posterior:pit]{posterior::pit()}}) and for GPD fit. +} +\examples{ +x <- example_draws() +y <- rnorm(nvariables(x), 5, 5) +pareto_pit(x, y) + +} +\seealso{ +\code{\link[posterior:pit]{posterior::pit()}} for the unsmoothed version, \code{\link[posterior:pareto_smooth]{posterior::pareto_smooth()}} for +Pareto smoothing of draws. +} diff --git a/man/pgeneralized_pareto.Rd b/man/pgeneralized_pareto.Rd new file mode 100644 index 00000000..f723656f --- /dev/null +++ b/man/pgeneralized_pareto.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/helpers-ppc.R +\name{pgeneralized_pareto} +\alias{pgeneralized_pareto} +\title{Distribution function for the generalized Pareto distribution} +\usage{ +pgeneralized_pareto( + q, + mu = 0, + sigma = 1, + k = 0, + lower.tail = TRUE, + log.p = FALSE +) +} +\arguments{ +\item{q}{Numeric vector of quantiles.} + +\item{mu}{Location parameter.} + +\item{sigma}{Scale parameter (must be positive).} + +\item{k}{Shape parameter.} + +\item{lower.tail}{Logical; if \code{TRUE} (default), probabilities are \code{P[X <= x]}.} + +\item{log.p}{Logical; if \code{TRUE}, probabilities are returned as \code{log(p)}.} +} +\value{ +A numeric vector of probabilities. +} +\description{ +Computes the cumulative distribution function (CDF) for a generalized +Pareto distribution with location \code{mu}, scale \code{sigma}, and shape \code{k}. +} +\examples{ +pgeneralized_pareto(q = c(1, 2, 5), mu = 0, sigma = 1, k = 0.2) +} +\keyword{internal} diff --git a/man/qgeneralized_pareto.Rd b/man/qgeneralized_pareto.Rd new file mode 100644 index 00000000..c589071f --- /dev/null +++ b/man/qgeneralized_pareto.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/helpers-ppc.R +\name{qgeneralized_pareto} +\alias{qgeneralized_pareto} +\title{Quantile function for the generalized Pareto distribution} +\usage{ +qgeneralized_pareto( + p, + mu = 0, + sigma = 1, + k = 0, + lower.tail = TRUE, + log.p = FALSE +) +} +\arguments{ +\item{p}{Numeric vector of probabilities.} + +\item{mu}{Location parameter.} + +\item{sigma}{Scale parameter (must be positive).} + +\item{k}{Shape parameter.} + +\item{lower.tail}{Logical; if \code{TRUE} (default), probabilities are \code{P[X <= x]}.} + +\item{log.p}{Logical; if \code{TRUE}, probabilities are given as \code{log(p)}.} +} +\value{ +A numeric vector of quantiles. +} +\description{ +Computes the quantile function for a generalized Pareto distribution +with location \code{mu}, scale \code{sigma}, and shape \code{k}. +} +\examples{ +qgeneralized_pareto(p = c(0.1, 0.5, 0.9), mu = 0, sigma = 1, k = 0.2) +} +\keyword{internal} From 49edab2bc9834f54ee0e0b9bbb8555f4710128c9 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Thu, 5 Mar 2026 16:12:43 +0200 Subject: [PATCH 104/120] remove necessary weights for method='independent' and pareto_pit=True --- R/ppc-distributions.R | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/R/ppc-distributions.R b/R/ppc-distributions.R index 4f1adae7..8555e5fa 100644 --- a/R/ppc-distributions.R +++ b/R/ppc-distributions.R @@ -789,10 +789,8 @@ ppc_pit_ecdf <- function(y, suggested_package("rstantools") y <- validate_y(y) yrep <- validate_predictions(yrep, length(y)) - lw <- .get_lw(NULL, psis_object) - stopifnot(identical(dim(yrep), dim(lw))) - pit <- pareto_pit(x = yrep, y = y, weights = lw, log = TRUE) + pit <- pareto_pit(x = yrep, y = y, weights = NULL, log = TRUE) K <- K %||% length(pit) } else if (!is.null(pit)) { @@ -804,8 +802,8 @@ ppc_pit_ecdf <- function(y, ignored <- c( if (!missing(y) && !is.null(y)) "y", if (!missing(yrep) && !is.null(yrep)) "yrep", - if (!missing(lw) && !is.null(lw)) "lw", - if (!missing(psis_object) && !is.null(psis_object)) "psis_object" + #if (!missing(lw) && !is.null(lw)) "lw", + #if (!missing(psis_object) && !is.null(psis_object)) "psis_object" ) if (length(ignored) > 0) { inform(paste0( From a22e857adf844b0e980fabd274d2cb33628f533a Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Thu, 5 Mar 2026 16:13:13 +0200 Subject: [PATCH 105/120] adjust test for ppc_pit with pp_check --- tests/testthat/test-ppc-distributions.R | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/testthat/test-ppc-distributions.R b/tests/testthat/test-ppc-distributions.R index 0a7d2ebf..a149a074 100644 --- a/tests/testthat/test-ppc-distributions.R +++ b/tests/testthat/test-ppc-distributions.R @@ -800,6 +800,5 @@ test_that("ppc_pit_ecdf works with pareto_pit method", { y = y, yrep = draws, psis_object = psis_object, method = "correlated" )) - expect_gg(brms::pp_check(fit_nb, type = "pit_ecdf", method = "correlated", - psis_object = psis_object)) + expect_gg(brms::pp_check(fit_nb, type = "pit_ecdf", method = "correlated")) }) \ No newline at end of file From 53338ad925a58743491b6970af9d3bd5c34ad0b8 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Thu, 5 Mar 2026 16:28:16 +0200 Subject: [PATCH 106/120] change x-axis to LOO PIT --- R/ppc-loo.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index e9f9a451..50b63caf 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -642,7 +642,7 @@ ppc_loo_pit_ecdf <- function(y, color = "darkgrey", linewidth = 0.3 ) + - labs(x = "PIT", y = y_label) + labs(x = "LOO PIT", y = y_label) # --- Highlight suspicious regions ---------------------------------------- From 67d2efa8d60d73ada55c271b3cf53dfda566c104 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Thu, 5 Mar 2026 21:27:59 +0200 Subject: [PATCH 107/120] adjust p-value formatting for ppc_loo_pit_ecdf --- R/ppc-loo.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 50b63caf..94240c74 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -700,8 +700,8 @@ ppc_loo_pit_ecdf <- function(y, "text", x = -Inf, y = Inf, label = sprintf( - "p[unif]^{%s} == '%.3f' ~ (alpha == '%.2f')", - test, p_value_CCT, alpha + "p[unif]^{%s} == '%s' ~ (alpha == '%.2f')", + test, fmt_p(p_value_CCT), alpha ), hjust = -0.05, vjust = 1.5, color = "black", parse = TRUE, size = label_size From c25db1100034aa34f590b83d360640eda9cce25c Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Thu, 5 Mar 2026 21:28:42 +0200 Subject: [PATCH 108/120] remove weights from arguments for ppc_pit_ecdf --- R/ppc-distributions.R | 57 +++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 38 deletions(-) diff --git a/R/ppc-distributions.R b/R/ppc-distributions.R index 8555e5fa..3c74dbf7 100644 --- a/R/ppc-distributions.R +++ b/R/ppc-distributions.R @@ -648,17 +648,6 @@ ppc_violin_grouped <- #' @param pit An optional vector of probability integral transformed values for #' which the ECDF is to be drawn. If NULL, PIT values are computed to `y` with #' respect to the corresponding values in `yrep`. -#' @param lw A matrix of (smoothed) log weights with the same dimensions as -#' `yrep`. See [loo::psis()] and the associated `weights()` method as well as -#' the **Examples** section, below. If `lw` is not specified then -#' `psis_object` can be provided and log weights will be extracted. -#' Only required if `pareto_pit = TRUE`. `pareto_pit` defaults to `TRUE` if -#' `method = "correlated"` and `test` is `"POT"` or `"PIET"`. -#' @param psis_object If using **loo** version `2.0.0` or greater, an -#' object returned by the `psis()` function (or by the `loo()` function -#' with argument `save_psis` set to `TRUE`). -#' Only required if `pareto_pit = TRUE`. `pareto_pit` defaults to `TRUE` if -#' `method = "correlated"` and `test` is `"POT"` or `"PIET"`. #' @param interpolate_adj For `ppc_loo_pit_ecdf()` when `method = "independent"`, #' a boolean defining if the simultaneous confidence bands should be #' interpolated based on precomputed values rather than computed exactly. @@ -691,9 +680,7 @@ ppc_violin_grouped <- #' ppc_pit_ecdf <- function(y, yrep, - lw = NULL, ..., - psis_object = NULL, pit = NULL, K = NULL, prob = .99, @@ -708,23 +695,20 @@ ppc_pit_ecdf <- function(y, pareto_pit = NULL ) { # Expected input combinations for ppc_pit_ecdf() based on method and test choices: - # | yrep | y | lw | psis_object | pit | method | test | pareto_pit | approach | - # |------|---|----|-------------|-----|-------------|------|------------|--------------------| - # | x | x | | | | independent | NULL | FALSE | empirical pit | - # | | | | | x | independent | NULL | FALSE | | - # | x | x | | x | | independent | NULL | TRUE | compute pareto-pit | - # | x | x | x | | | independent | NULL | TRUE | compute pareto-pit | - # | x | x | x | | | correlated | POT | TRUE | compute pareto-pit | - # | x | x | | x | | correlated | POT | TRUE | compute pareto-pit | - # | | | | | x | correlated | POT | FALSE | | - # | x | x | x | | | correlated | PIET | TRUE | compute pareto-pit | - # | x | x | | x | | correlated | PIET | TRUE | compute pareto-pit | - # | | | | | x | correlated | PIET | FALSE | | - # | x | x | | | | correlated | PRIT | FALSE | empirical pit | - # | | | | | x | correlated | PRIT | FALSE | | + # | yrep | y | pit | method | test | pareto_pit | approach | + # |------|---|-----|-------------|------|------------|--------------------| + # | x | x | | independent | NULL | FALSE | empirical pit | + # | | | x | independent | NULL | FALSE | | + # | x | x | | independent | NULL | TRUE | compute pareto-pit | + # | x | x | | correlated | POT | TRUE | compute pareto-pit | + # | | | x | correlated | POT | FALSE | | + # | x | x | | correlated | PIET | TRUE | compute pareto-pit | + # | | | x | correlated | PIET | FALSE | | + # | x | x | | correlated | PRIT | FALSE | empirical pit | + # | | | x | correlated | PRIT | FALSE | | check_ignored_arguments(..., - ok_args = c("K", "lw", "psis_object", "pareto_pit", "pit", "prob", "plot_diff", + ok_args = c("K", "pareto_pit", "pit", "prob", "plot_diff", "interpolate_adj", "method", "test", "gamma", "linewidth", "color", "help_text") ) @@ -762,10 +746,9 @@ ppc_pit_ecdf <- function(y, color <- color %||% c(ecdf = "grey60", highlight = "red") help_text <- help_text %||% TRUE - # Pareto PIT applies for correlated only when lw/psis_object is supplied - # and the test is POT or PIET (not PRIT, which uses empirical PIT). - pareto_pit <- pareto_pit %||% is.null(pit) && !is.null(lw %||% psis_object) && - test %in% c("POT", "PIET") + # Pareto PIT applies for correlated only when the test is POT or PIET + # (not PRIT, which uses empirical PIT). + pareto_pit <- pareto_pit %||% is.null(pit) && test %in% c("POT", "PIET") }, "independent" = { ignored <- c( @@ -775,7 +758,7 @@ ppc_pit_ecdf <- function(y, ) if (length(ignored) > 0) .warn_ignored("'independent'", ignored) - # Pareto PIT applies for independent whenever lw/psis_object is supplied. + # Pareto PIT applies for independent whenever pareto_pit = TRUE. pareto_pit <- pareto_pit %||% FALSE } ) @@ -801,9 +784,7 @@ ppc_pit_ecdf <- function(y, # Warn about any ignored arguments. ignored <- c( if (!missing(y) && !is.null(y)) "y", - if (!missing(yrep) && !is.null(yrep)) "yrep", - #if (!missing(lw) && !is.null(lw)) "lw", - #if (!missing(psis_object) && !is.null(psis_object)) "psis_object" + if (!missing(yrep) && !is.null(yrep)) "yrep" ) if (length(ignored) > 0) { inform(paste0( @@ -952,8 +933,8 @@ ppc_pit_ecdf <- function(y, p <- p + annotate( "text", x = -Inf, y = Inf, - label = sprintf("p[unif]^{%s} == '%.3f' ~ (alpha == '%.2f')", - test, p_value_CCT, alpha + label = sprintf("p[unif]^{%s} == '%s' ~ (alpha == '%.2f')", + test, fmt_p(p_value_CCT), alpha ), hjust = -0.05, vjust = 1.5, color = "black", parse = TRUE, size = label_size From 86b7cc7df554c86c7dd3786dd0151cc6637d66a9 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Thu, 5 Mar 2026 21:29:08 +0200 Subject: [PATCH 109/120] add helper for formatting p-value --- R/helpers-ppc.R | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index a7d83ee1..0bd85be6 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -1184,4 +1184,9 @@ gpdfit <- function(x, wip = TRUE, min_grid_pts = 30, sort_x = TRUE, } list(k = k_hat, sigma = sigma_hat) +} + +# helper function for formatting p-value +fmt_p <- function(x) { + dplyr::if_else(x < 0.0005, "0.000", as.character(round(signif(x, 2) + 1e-10, 3))) } \ No newline at end of file From ab01660c9a11332311ed81bbf9b2378949bd99bd Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Thu, 5 Mar 2026 21:29:41 +0200 Subject: [PATCH 110/120] add unittest for p-value-formatting helper --- tests/testthat/test-helpers-ppc.R | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/testthat/test-helpers-ppc.R b/tests/testthat/test-helpers-ppc.R index 0f34d0ce..67bc194a 100644 --- a/tests/testthat/test-helpers-ppc.R +++ b/tests/testthat/test-helpers-ppc.R @@ -292,4 +292,11 @@ test_that("compute_cauchy computes correct transformations", { # For x = 0.75: tan((0.5 - 0.75) * pi) = tan(-0.25 * pi) = -1 expect_equal(.compute_cauchy(0.75), -1, tolerance = 1e-10) +}) + +test_that("formatting of p-values works as expected", { + expect_equal(fmt_p(0.446), "0.45") + expect_equal(fmt_p(0.045), "0.045") + expect_equal(fmt_p(0.0045), "0.005") + expect_equal(fmt_p(0.00045), "0.000") }) \ No newline at end of file From ad98d4b0d35bf72d85273b2ec64eb29ebf388274 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Thu, 5 Mar 2026 21:30:19 +0200 Subject: [PATCH 111/120] update tests for ppc_pit_ecdf --- tests/testthat/test-ppc-distributions.R | 86 ++++++------------------- 1 file changed, 21 insertions(+), 65 deletions(-) diff --git a/tests/testthat/test-ppc-distributions.R b/tests/testthat/test-ppc-distributions.R index a149a074..fa09be52 100644 --- a/tests/testthat/test-ppc-distributions.R +++ b/tests/testthat/test-ppc-distributions.R @@ -565,7 +565,7 @@ test_that("ppc_pit_ecdf renders different linewidths and colors correctly", { # use monkey-patching to test whether the correct branch of the # PIT computation is taken -ppc_pit_ecdf_patched <- ppc_pit_ecdf # copy +ppc_pit_ecdf_patched <- ppc_pit_ecdf body(ppc_pit_ecdf_patched)[[ # Replace the PIT computation block (the large if/else if/else) @@ -581,9 +581,8 @@ body(ppc_pit_ecdf_patched)[[ suggested_package("rstantools") y <- validate_y(y) yrep <- validate_predictions(yrep, length(y)) - lw <- .get_lw(lw, psis_object) - stopifnot(identical(dim(yrep), dim(lw))) - pit <- pareto_pit(x = yrep, y = y, weights = lw, log = TRUE) + + pit <- pareto_pit(x = yrep, y = y, weights = NULL, log = TRUE) K <- K %||% length(pit) } else if (!is.null(pit)) { @@ -593,8 +592,7 @@ body(ppc_pit_ecdf_patched)[[ ignored <- c( if (!missing(y) && !is.null(y)) "y", - if (!missing(yrep) && !is.null(yrep)) "yrep", - if (!is.null(lw)) "lw" + if (!missing(yrep) && !is.null(yrep)) "yrep" ) if (length(ignored) > 0) { inform(paste0("As 'pit' specified; ignoring: ", @@ -620,23 +618,19 @@ testthat::test_that("ppc_pit_ecdf takes correct PIT computation branch", { skip_on_r_oldrel() skip_if(packageVersion("rstantools") <= "2.4.0") - # | yrep | y | lw | psis_object | pit | method | test | pareto_pit | approach | - # |------|---|----|-------------|-----|-------------|------|------------|--------------------| - # | x | x | | | | independent | NULL | FALSE (D) | empirical pit | - # | x | x | x | | | independent | NULL | TRUE | compute pareto-pit | - # | x | x | | x | | independent | NULL | TRUE | compute pareto-pit | - # | | | | | x | independent | NULL | FALSE | | - # | x | x | x | | | correlated | POT | TRUE | compute pareto-pit | - # | x | x | | x | | correlated | POT | TRUE | compute pareto-pit | - # | | | | | x | correlated | POT | FALSE | | - # | x | x | x | | | correlated | PIET | TRUE | compute pareto-pit | - # | x | x | | x | | correlated | PIET | TRUE | compute pareto-pit | - # | | | | | x | correlated | PIET | FALSE | | - # | x | x | x | | | correlated | PRIT | FALSE | empirical pit | - # | x | x | | x | | correlated | PRIT | FALSE | empirical pit | - # | | | | | x | correlated | PRIT | FALSE | | - - psis_object <- suppressWarnings(loo::psis(-vdiff_loo_lw)) + # | yrep | y | pit | method | test | pareto_pit | approach | + # |------|---|-----|-------------|------|------------|--------------------| + # | x | x | | independent | NULL | FALSE | empirical pit | + # | | | x | independent | NULL | FALSE | | + # | x | x | | independent | NULL | TRUE | compute pareto-pit | + # | x | x | | independent | NULL | TRUE | compute pareto-pit | + # | x | x | | correlated | POT | TRUE | compute pareto-pit | + # | | | x | correlated | POT | FALSE | | + # | x | x | | correlated | PIET | TRUE | compute pareto-pit | + # | | | x | correlated | PIET | FALSE | | + # | x | x | | correlated | PRIT | FALSE | empirical pit | + # | | | x | correlated | PRIT | FALSE | | + pits <- rstantools::loo_pit(vdiff_loo_yrep, vdiff_loo_y, vdiff_loo_lw) # method = independent ------------------------------------------ @@ -654,7 +648,6 @@ testthat::test_that("ppc_pit_ecdf takes correct PIT computation branch", { vdiff_loo_y, vdiff_loo_yrep, method = "independent", - psis_object = psis_object, pareto_pit = TRUE ), regexp = "\\[PIT BRANCH\\] Pareto-smoothed LOO PIT" @@ -673,8 +666,7 @@ testthat::test_that("ppc_pit_ecdf takes correct PIT computation branch", { ppc_pit_ecdf_patched( vdiff_loo_y, vdiff_loo_yrep, - method = "correlated", - lw = vdiff_loo_lw + method = "correlated" ), regexp = "\\[PIT BRANCH\\] Pareto-smoothed LOO PIT" ) @@ -684,22 +676,11 @@ testthat::test_that("ppc_pit_ecdf takes correct PIT computation branch", { vdiff_loo_y, vdiff_loo_yrep, method = "correlated", - lw = vdiff_loo_lw, pareto_pit = FALSE ), regexp = "\\[PIT BRANCH\\] Empirical PIT" ) - expect_message( - ppc_pit_ecdf_patched( - vdiff_loo_y, - vdiff_loo_yrep, - method = "correlated", - psis_object = psis_object, - ), - regexp = "\\[PIT BRANCH\\] Pareto-smoothed LOO PIT" - ) - expect_message( ppc_pit_ecdf_patched( method = "correlated", @@ -714,19 +695,7 @@ testthat::test_that("ppc_pit_ecdf takes correct PIT computation branch", { vdiff_loo_y, vdiff_loo_yrep, method = "correlated", - test = "PIET", - lw = vdiff_loo_lw - ), - regexp = "\\[PIT BRANCH\\] Pareto-smoothed LOO PIT" - ) - - expect_message( - ppc_pit_ecdf_patched( - vdiff_loo_y, - vdiff_loo_yrep, - method = "correlated", - test = "PIET", - psis_object = psis_object, + test = "PIET" ), regexp = "\\[PIT BRANCH\\] Pareto-smoothed LOO PIT" ) @@ -746,19 +715,7 @@ testthat::test_that("ppc_pit_ecdf takes correct PIT computation branch", { vdiff_loo_y, vdiff_loo_yrep, method = "correlated", - test = "PRIT", - lw = vdiff_loo_lw - ), - regexp = "\\[PIT BRANCH\\] Empirical PIT" - ) - - expect_message( - ppc_pit_ecdf_patched( - vdiff_loo_y, - vdiff_loo_yrep, - method = "correlated", - test = "PRIT", - psis_object = psis_object, + test = "PRIT" ), regexp = "\\[PIT BRANCH\\] Empirical PIT" ) @@ -793,11 +750,10 @@ test_that("ppc_pit_ecdf works with pareto_pit method", { expect_gg(brms::pp_check(fit_nb, type = "pit_ecdf")) draws <- brms::posterior_predict(fit_nb) - psis_object <- brms::loo(fit_nb, save_psis = TRUE)$psis_object y <- roaches$y expect_gg(ppc_pit_ecdf( - y = y, yrep = draws, psis_object = psis_object, method = "correlated" + y = y, yrep = draws, method = "correlated" )) expect_gg(brms::pp_check(fit_nb, type = "pit_ecdf", method = "correlated")) From 19a33276fb47ec5f9e1ed87319a114963db3c213 Mon Sep 17 00:00:00 2001 From: florence-bockting Date: Thu, 5 Mar 2026 21:30:40 +0200 Subject: [PATCH 112/120] add snapshots for visual regression tests --- .../ppc-pit-ecdf-correlated-diff.svg | 4 +-- .../ppc-pit-ecdf-correlated-piet-2.svg | 34 +++++++++--------- .../ppc-pit-ecdf-correlated-piet.svg | 2 +- .../ppc-pit-ecdf-correlated.svg | 4 +-- .../ppc-pit-ecdf-diff-correlated-piet.svg | 34 +++++++++--------- .../ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg | 34 +++++++++--------- .../ppc-loo-pit-ecdf-changed-theme.svg | 34 +++++++++--------- .../ppc-loo/ppc-loo-pit-ecdf-color-change.svg | 2 +- .../ppc-loo-pit-ecdf-correlated-piet.svg | 36 +++++++++---------- .../ppc-loo-pit-ecdf-correlated-pot.svg | 2 +- .../ppc-loo-pit-ecdf-correlated-prit.svg | 2 +- .../ppc-loo-pit-ecdf-diff-correlated-piet.svg | 36 +++++++++---------- .../ppc-loo-pit-ecdf-diff-correlated-pot.svg | 2 +- .../ppc-loo-pit-ecdf-diff-correlated-prit.svg | 2 +- .../ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg | 2 +- .../ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg | 2 +- .../ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg | 2 +- 17 files changed, 117 insertions(+), 117 deletions(-) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-diff.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-diff.svg index 9a55a76c..9b25f423 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-diff.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-diff.svg @@ -25,9 +25,9 @@ - + - + p u n diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet-2.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet-2.svg index d0bbbee5..5be35332 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet-2.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet-2.svg @@ -27,23 +27,23 @@ -p -u -n -i -f -P -I -E -T -= -0.188 - -( -α -= -0.01 -) +p +u +n +i +f +P +I +E +T += +0.19 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet.svg index 5cd9dd58..3b47aa76 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated-piet.svg @@ -25,7 +25,7 @@ - + p diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated.svg index b3340b7a..980e8bd7 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-correlated.svg @@ -25,9 +25,9 @@ - + - + p u n diff --git a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-piet.svg b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-piet.svg index 40ba9439..e7ed2ab4 100644 --- a/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-distributions/ppc-pit-ecdf-diff-correlated-piet.svg @@ -27,23 +27,23 @@ -p -u -n -i -f -P -I -E -T -= -0.188 - -( -α -= -0.01 -) +p +u +n +i +f +P +I +E +T += +0.19 + +( +α += +0.01 +) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg index 20437e0d..248ddd84 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg @@ -27,22 +27,22 @@ -p -u -n -i -f -P -O -T -= -0.365 - -( -α -= -0.05 -) +p +u +n +i +f +P +O +T += +0.37 + +( +α += +0.05 +) @@ -67,7 +67,7 @@ 0.50 0.75 1.00 -PIT +LOO PIT ECDF difference ppc_loo_pit_ecdf (alpha=0.05) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg index e808491b..08beb4e7 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg @@ -27,22 +27,22 @@ -p -u -n -i -f -P -O -T -= -0.365 - -( -α -= -0.01 -) +p +u +n +i +f +P +O +T += +0.37 + +( +α += +0.01 +) @@ -63,7 +63,7 @@ 0.50 0.75 1.00 -PIT +LOO PIT ECDF difference ppc_loo_pit_ecdf (changed theme) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg index 0c8338ac..b6c40ab8 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg @@ -71,7 +71,7 @@ 0.50 0.75 1.00 -PIT +LOO PIT ECDF ppc_loo_pit_ecdf (color change) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg index 042ceb71..d1321734 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg @@ -27,23 +27,23 @@ -p -u -n -i -f -P -I -E -T -= -0.188 - -( -α -= -0.01 -) +p +u +n +i +f +P +I +E +T += +0.19 + +( +α += +0.01 +) @@ -68,7 +68,7 @@ 0.50 0.75 1.00 -PIT +LOO PIT ECDF ppc_loo_pit_ecdf (correlated piet) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg index 68e55568..1733a560 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg @@ -71,7 +71,7 @@ 0.50 0.75 1.00 -PIT +LOO PIT ECDF ppc_loo_pit_ecdf (correlated pot) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg index 1a6be2aa..ac7584b9 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg @@ -74,7 +74,7 @@ 0.50 0.75 1.00 -PIT +LOO PIT ECDF ppc_loo_pit_ecdf (correlated prit) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg index be85fdb6..36ef17d0 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg @@ -27,23 +27,23 @@ -p -u -n -i -f -P -I -E -T -= -0.188 - -( -α -= -0.01 -) +p +u +n +i +f +P +I +E +T += +0.19 + +( +α += +0.01 +) @@ -68,7 +68,7 @@ 0.50 0.75 1.00 -PIT +LOO PIT ECDF difference ppc_loo_pit_ecdf (diff, correlated piet) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg index ffd601d6..1cc6df2d 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg @@ -71,7 +71,7 @@ 0.50 0.75 1.00 -PIT +LOO PIT ECDF difference ppc_loo_pit_ecdf (diff, correlated pot) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg index 89de7335..0b8913cd 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg @@ -74,7 +74,7 @@ 0.50 0.75 1.00 -PIT +LOO PIT ECDF difference ppc_loo_pit_ecdf (diff, correlated prit) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg index 8cf9b740..043e78e4 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg @@ -71,7 +71,7 @@ 0.50 0.75 1.00 -PIT +LOO PIT ECDF ppc_loo_pit_ecdf (linewidth = 1) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg index 35f5c9ae..62a40b93 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg @@ -71,7 +71,7 @@ 0.50 0.75 1.00 -PIT +LOO PIT ECDF ppc_loo_pit_ecdf (linewidth = 2) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg index 1e64e37a..925100c1 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg @@ -51,7 +51,7 @@ 0.50 0.75 1.00 -PIT +LOO PIT ECDF difference ppc_loo_pit_ecdf (no help_text) From 12dda8ce778e15c037ba794cfc77b5b1570bae4e Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Fri, 6 Mar 2026 08:35:01 +0200 Subject: [PATCH 113/120] fix x-axis label to LOO-PIT --- R/ppc-loo.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 94240c74..8a16458f 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -642,7 +642,7 @@ ppc_loo_pit_ecdf <- function(y, color = "darkgrey", linewidth = 0.3 ) + - labs(x = "LOO PIT", y = y_label) + labs(x = "LOO-PIT", y = y_label) # --- Highlight suspicious regions ---------------------------------------- From 309cbe3671f49157b8f387e9f70250878e952332 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Fri, 6 Mar 2026 11:23:10 +0200 Subject: [PATCH 114/120] adjust internal referencing --- R/helpers-ppc.R | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index 0bd85be6..28d21158 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -786,8 +786,8 @@ ypred_label <- function() expression(italic(y)[pred]) #' Pareto smoothing of draws. #' #' @examples -#' x <- example_draws() -#' y <- rnorm(nvariables(x), 5, 5) +#' x <- posterior::example_draws() +#' y <- rnorm(posterior::nvariables(x), 5, 5) #' pareto_pit(x, y) #' NULL @@ -827,7 +827,7 @@ pareto_pit.draws_matrix <- function(x, y, weights = NULL, log = FALSE, if (is.null(ndraws_tail)) { ndraws_tail <- posterior::ps_tail_length(ndraws, 1) } else { - ndraws_tail <- posterior::as_one_integer(ndraws_tail) + ndraws_tail <- posterior:::as_one_integer(ndraws_tail) } # validate ndraws_tail once for all variables @@ -889,7 +889,7 @@ pareto_pit.draws_matrix <- function(x, y, weights = NULL, log = FALSE, # --- right tail --- right_replaced <- FALSE right_tail <- sorted[tail_ids] - if (!posterior:::is_constant(right_tail)) { + if (!posterior::is_constant(right_tail)) { right_cutoff <- sorted[min(tail_ids) - 1] if (right_cutoff == right_tail[1]) { right_cutoff <- right_cutoff - .Machine$double.eps @@ -920,7 +920,7 @@ pareto_pit.draws_matrix <- function(x, y, weights = NULL, log = FALSE, log_wt_left_sorted <- if (!is.null(weights)) weights[left_ord$ix, j] else NULL left_tail <- left_sorted[tail_ids] - if (!posterior:::is_constant(left_tail)) { + if (!posterior::is_constant(left_tail)) { left_cutoff <- left_sorted[min(tail_ids) - 1] if (left_cutoff == left_tail[1]) { left_cutoff <- left_cutoff - .Machine$double.eps @@ -963,7 +963,7 @@ pareto_pit.rvar <- function(x, y, weights = NULL, log = FALSE, y <- pareto_pit_validate_y(y, x) out <- array( data = pareto_pit( - x = as_draws_matrix(c(x)), + x = posterior::as_draws_matrix(c(x)), y = c(y), weights = weights, log = log, @@ -1151,11 +1151,11 @@ gpdfit <- function(x, wip = TRUE, min_grid_pts = 30, sort_x = TRUE, # weighted mean across observations for each theta value k <- drop(log1p_mat %*% weights) / N } else { - k <- matrixStats::rowMeans2(log1p_mat) + k <- rowMeans(log1p_mat) } l_theta <- N * (log(-theta / k) - k - 1) # profile log-lik - w_theta <- exp(l_theta - matrixStats::logSumExp(l_theta)) # normalize + w_theta <- exp(l_theta - posterior:::log_sum_exp(l_theta)) # normalize theta_hat <- sum(theta * w_theta) if (!is.null(weights)) { From 30cf5c64470de008020c4ded6be300cee75d1d77 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Fri, 6 Mar 2026 11:23:44 +0200 Subject: [PATCH 115/120] update documentation for ppc_pit_ecdf --- R/ppc-distributions.R | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/R/ppc-distributions.R b/R/ppc-distributions.R index 3c74dbf7..c82fefa8 100644 --- a/R/ppc-distributions.R +++ b/R/ppc-distributions.R @@ -648,24 +648,26 @@ ppc_violin_grouped <- #' @param pit An optional vector of probability integral transformed values for #' which the ECDF is to be drawn. If NULL, PIT values are computed to `y` with #' respect to the corresponding values in `yrep`. -#' @param interpolate_adj For `ppc_loo_pit_ecdf()` when `method = "independent"`, +#' @param interpolate_adj For `ppc_pit_ecdf()` when `method = "independent"`, #' a boolean defining if the simultaneous confidence bands should be #' interpolated based on precomputed values rather than computed exactly. #' Computing the bands may be computationally intensive and the approximation #' gives a fast method for assessing the ECDF trajectory. The default is to use #' interpolation if `K` is greater than 200. -#' @param method For `ppc_loo_pit_ecdf()`, the method used to calculate the +#' @param method For `ppc_pit_ecdf()`, the method used to calculate the #' uniformity test: #' * `"independent"`: (default) Assumes independence (Säilynoja et al., 2022). #' * `"correlated"`: Accounts for correlation (Tesso & Vehtari, 2026). -#' @param test For `ppc_loo_pit_ecdf()` when `method = "correlated"`, which +#' @param test For `ppc_pit_ecdf()` when `method = "correlated"`, which #' dependence-aware test to use: `"POT"`, `"PRIT"`, or `"PIET"`. #' Defaults to `"POT"`. -#' @param gamma For `ppc_loo_pit_ecdf()` when `method = "correlated"`, tolerance +#' @param gamma For `ppc_pit_ecdf()` when `method = "correlated"`, tolerance #' threshold controlling how strongly suspicious points are flagged. Larger #' values (gamma > 0) emphasizes points with larger deviations. If `NULL`, automatically #' determined based on p-value. -#' @param color For `ppc_loo_pit_ecdf()` when `method = "correlated"`, a vector +#' @param linewidth For `ppc_pit_ecdf()` when `method = "correlated"`, the line width of the ECDF +#' and highlighting points. Defaults to 0.3. +#' @param color For `ppc_pit_ecdf()` when `method = "correlated"`, a vector #' with base color and highlight color for the ECDF plot. Defaults to #' `c(ecdf = "grey60", highlight = "red")`. The first element is used for #' the main ECDF line, the second for highlighted suspicious regions. From 116ce8f3738b4cf3297675e1bd364310eabef3e4 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Fri, 6 Mar 2026 11:24:20 +0200 Subject: [PATCH 116/120] minor change in code comment --- tests/testthat/test-ppc-distributions.R | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/testthat/test-ppc-distributions.R b/tests/testthat/test-ppc-distributions.R index fa09be52..edda6cfb 100644 --- a/tests/testthat/test-ppc-distributions.R +++ b/tests/testthat/test-ppc-distributions.R @@ -623,7 +623,6 @@ testthat::test_that("ppc_pit_ecdf takes correct PIT computation branch", { # | x | x | | independent | NULL | FALSE | empirical pit | # | | | x | independent | NULL | FALSE | | # | x | x | | independent | NULL | TRUE | compute pareto-pit | - # | x | x | | independent | NULL | TRUE | compute pareto-pit | # | x | x | | correlated | POT | TRUE | compute pareto-pit | # | | | x | correlated | POT | FALSE | | # | x | x | | correlated | PIET | TRUE | compute pareto-pit | From 133d2922e8c70a5db4f568e29427f4846a5124df Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Fri, 6 Mar 2026 11:24:37 +0200 Subject: [PATCH 117/120] update documentation files --- man/PPC-distributions.Rd | 28 ++++++++-------------------- man/pareto_pit.Rd | 4 ++-- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/man/PPC-distributions.Rd b/man/PPC-distributions.Rd index cde64441..5cd1b4ee 100644 --- a/man/PPC-distributions.Rd +++ b/man/PPC-distributions.Rd @@ -126,9 +126,7 @@ ppc_violin_grouped( ppc_pit_ecdf( y, yrep, - lw = NULL, ..., - psis_object = NULL, pit = NULL, K = NULL, prob = 0.99, @@ -227,19 +225,6 @@ to to the \code{size}, \code{alpha}, and \code{width} arguments of \code{\link[g to control the appearance of \code{y} points. The default of \code{y_jitter=NULL} will let \strong{ggplot2} determine the amount of jitter.} -\item{lw}{A matrix of (smoothed) log weights with the same dimensions as -\code{yrep}. See \code{\link[loo:psis]{loo::psis()}} and the associated \code{weights()} method as well as -the \strong{Examples} section, below. If \code{lw} is not specified then -\code{psis_object} can be provided and log weights will be extracted. -Only required if \code{pareto_pit = TRUE}. \code{pareto_pit} defaults to \code{TRUE} if -\code{method = "correlated"} and \code{test} is \code{"POT"} or \code{"PIET"}.} - -\item{psis_object}{If using \strong{loo} version \verb{2.0.0} or greater, an -object returned by the \code{psis()} function (or by the \code{loo()} function -with argument \code{save_psis} set to \code{TRUE}). -Only required if \code{pareto_pit = TRUE}. \code{pareto_pit} defaults to \code{TRUE} if -\code{method = "correlated"} and \code{test} is \code{"POT"} or \code{"PIET"}.} - \item{pit}{An optional vector of probability integral transformed values for which the ECDF is to be drawn. If NULL, PIT values are computed to \code{y} with respect to the corresponding values in \code{yrep}.} @@ -261,30 +246,33 @@ values rather than plotting the regular ECDF. The default is \code{FALSE}, but for large samples we recommend setting \code{plot_diff=TRUE} as the difference plot will visually show a more dynamic range.} -\item{interpolate_adj}{For \code{ppc_loo_pit_ecdf()} when \code{method = "independent"}, +\item{interpolate_adj}{For \code{ppc_pit_ecdf()} when \code{method = "independent"}, a boolean defining if the simultaneous confidence bands should be interpolated based on precomputed values rather than computed exactly. Computing the bands may be computationally intensive and the approximation gives a fast method for assessing the ECDF trajectory. The default is to use interpolation if \code{K} is greater than 200.} -\item{method}{For \code{ppc_loo_pit_ecdf()}, the method used to calculate the +\item{method}{For \code{ppc_pit_ecdf()}, the method used to calculate the uniformity test: \itemize{ \item \code{"independent"}: (default) Assumes independence (Säilynoja et al., 2022). \item \code{"correlated"}: Accounts for correlation (Tesso & Vehtari, 2026). }} -\item{test}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, which +\item{test}{For \code{ppc_pit_ecdf()} when \code{method = "correlated"}, which dependence-aware test to use: \code{"POT"}, \code{"PRIT"}, or \code{"PIET"}. Defaults to \code{"POT"}.} -\item{gamma}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, tolerance +\item{gamma}{For \code{ppc_pit_ecdf()} when \code{method = "correlated"}, tolerance threshold controlling how strongly suspicious points are flagged. Larger values (gamma > 0) emphasizes points with larger deviations. If \code{NULL}, automatically determined based on p-value.} -\item{color}{For \code{ppc_loo_pit_ecdf()} when \code{method = "correlated"}, a vector +\item{linewidth}{For \code{ppc_pit_ecdf()} when \code{method = "correlated"}, the line width of the ECDF +and highlighting points. Defaults to 0.3.} + +\item{color}{For \code{ppc_pit_ecdf()} when \code{method = "correlated"}, a vector with base color and highlight color for the ECDF plot. Defaults to \code{c(ecdf = "grey60", highlight = "red")}. The first element is used for the main ECDF line, the second for highlighted suspicious regions.} diff --git a/man/pareto_pit.Rd b/man/pareto_pit.Rd index ed931555..c8af5a70 100644 --- a/man/pareto_pit.Rd +++ b/man/pareto_pit.Rd @@ -70,8 +70,8 @@ When (log-)weights in \code{weights} are provided, they are used for the raw PIT computation (as in \code{\link[posterior:pit]{posterior::pit()}}) and for GPD fit. } \examples{ -x <- example_draws() -y <- rnorm(nvariables(x), 5, 5) +x <- posterior::example_draws() +y <- rnorm(posterior::nvariables(x), 5, 5) pareto_pit(x, y) } From 152bf29a5a60ae13eac954229223700591197a10 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Fri, 6 Mar 2026 11:39:42 +0200 Subject: [PATCH 118/120] update snapshots for regression test --- tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg | 2 +- .../testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg | 2 +- tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg | 2 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg | 2 +- .../testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg | 2 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg | 2 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg | 2 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg | 2 +- .../_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg | 2 +- tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg | 2 +- tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg | 2 +- tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg index 248ddd84..82ae233c 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-alpha-0-05.svg @@ -67,7 +67,7 @@ 0.50 0.75 1.00 -LOO PIT +LOO-PIT ECDF difference ppc_loo_pit_ecdf (alpha=0.05) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg index 08beb4e7..bf39eb07 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-changed-theme.svg @@ -63,7 +63,7 @@ 0.50 0.75 1.00 -LOO PIT +LOO-PIT ECDF difference ppc_loo_pit_ecdf (changed theme) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg index b6c40ab8..49763437 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-color-change.svg @@ -71,7 +71,7 @@ 0.50 0.75 1.00 -LOO PIT +LOO-PIT ECDF ppc_loo_pit_ecdf (color change) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg index d1321734..9eb513f8 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-piet.svg @@ -68,7 +68,7 @@ 0.50 0.75 1.00 -LOO PIT +LOO-PIT ECDF ppc_loo_pit_ecdf (correlated piet) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg index 1733a560..dedf7b1b 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-pot.svg @@ -71,7 +71,7 @@ 0.50 0.75 1.00 -LOO PIT +LOO-PIT ECDF ppc_loo_pit_ecdf (correlated pot) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg index ac7584b9..70141b36 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-correlated-prit.svg @@ -74,7 +74,7 @@ 0.50 0.75 1.00 -LOO PIT +LOO-PIT ECDF ppc_loo_pit_ecdf (correlated prit) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg index 36ef17d0..66599f42 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-piet.svg @@ -68,7 +68,7 @@ 0.50 0.75 1.00 -LOO PIT +LOO-PIT ECDF difference ppc_loo_pit_ecdf (diff, correlated piet) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg index 1cc6df2d..8de13006 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-pot.svg @@ -71,7 +71,7 @@ 0.50 0.75 1.00 -LOO PIT +LOO-PIT ECDF difference ppc_loo_pit_ecdf (diff, correlated pot) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg index 0b8913cd..5a26e10d 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-diff-correlated-prit.svg @@ -74,7 +74,7 @@ 0.50 0.75 1.00 -LOO PIT +LOO-PIT ECDF difference ppc_loo_pit_ecdf (diff, correlated prit) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg index 043e78e4..3fa8cd92 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-1.svg @@ -71,7 +71,7 @@ 0.50 0.75 1.00 -LOO PIT +LOO-PIT ECDF ppc_loo_pit_ecdf (linewidth = 1) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg index 62a40b93..ff6e2f74 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-linewidth-2.svg @@ -71,7 +71,7 @@ 0.50 0.75 1.00 -LOO PIT +LOO-PIT ECDF ppc_loo_pit_ecdf (linewidth = 2) diff --git a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg index 925100c1..310a4987 100644 --- a/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg +++ b/tests/testthat/_snaps/ppc-loo/ppc-loo-pit-ecdf-no-help-text.svg @@ -51,7 +51,7 @@ 0.50 0.75 1.00 -LOO PIT +LOO-PIT ECDF difference ppc_loo_pit_ecdf (no help_text) From 16dbbeebb278020c2bca3a819e1c25cb6edd6cc5 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Fri, 6 Mar 2026 13:16:56 +0200 Subject: [PATCH 119/120] update references in documentation --- R/helpers-ppc.R | 22 +++++++++++----------- man/pareto_pit.Rd | 18 +++++++++--------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/R/helpers-ppc.R b/R/helpers-ppc.R index 28d21158..9f00fb27 100644 --- a/R/helpers-ppc.R +++ b/R/helpers-ppc.R @@ -740,28 +740,28 @@ ypred_label <- function() expression(italic(y)[pred]) #' #' @name pareto_pit #' -#' @param x (draws) A [`draws_matrix`] object or one coercible to a -#' `draws_matrix` object, or an [`rvar`] object. +#' @param x (draws) A `posterior::draws_matrix` object or one coercible to a +#' `posterior::draws_matrix` object, or an `posterior::rvar` object. #' -#' @param y (observations) A 1D vector, or an array of dim(x), if x is `rvar`. +#' @param y (observations) A 1D vector, or an array of dim(x), if x is `posterior::rvar`. #' Each element of `y` corresponds to a variable in `x`. #' #' @param weights A matrix of weights for each draw and variable. `weights` -#' should have one column per variable in `x`, and `ndraws(x)` rows. +#' should have one column per variable in `x`, and `posterior::ndraws(x)` rows. #' #' @param log (logical) Are the weights passed already on the log scale? The #' default is `FALSE`, that is, expecting `weights` to be on the standard #' (non-log) scale. #' #' @param ndraws_tail (integer) Number of tail draws to use for GPD -#' fitting. If `NULL` (the default), computed using [ps_tail_length()]. +#' fitting. If `NULL` (the default), computed using `posterior::ps_tail_length()`. #' #' @template args-methods-dots #' #' @details The function first computes raw PIT values identically to -#' [pit()] (including support for weighted draws). It then fits a +#' `posterior::pit()` (including support for weighted draws). It then fits a #' GPD to both tails of the draws (using the same approach as -#' [pareto_smooth()]) and replaces PIT values for observations falling in +#' `posterior::pareto_smooth()`) and replaces PIT values for observations falling in #' the tail regions: #' #' For a right-tail observation \eqn{y_i > c_R} (where \eqn{c_R} is @@ -777,12 +777,12 @@ ypred_label <- function() expression(italic(y)[pred]) #' tail. #' #' When (log-)weights in `weights` are provided, they are used for -#' the raw PIT computation (as in [pit()]) and for GPD fit. +#' the raw PIT computation (as in `posterior::pit()`) and for GPD fit. #' #' @return A numeric vector of length `length(y)` containing the PIT values, or #' an array of shape `dim(y)`, if `x` is an `rvar`. #' -#' @seealso [pit()] for the unsmoothed version, [pareto_smooth()] for +#' @seealso `posterior::pit()` for the unsmoothed version, `posterior::pareto_smooth()` for #' Pareto smoothing of draws. #' #' @examples @@ -889,7 +889,7 @@ pareto_pit.draws_matrix <- function(x, y, weights = NULL, log = FALSE, # --- right tail --- right_replaced <- FALSE right_tail <- sorted[tail_ids] - if (!posterior::is_constant(right_tail)) { + if (!posterior:::is_constant(right_tail)) { right_cutoff <- sorted[min(tail_ids) - 1] if (right_cutoff == right_tail[1]) { right_cutoff <- right_cutoff - .Machine$double.eps @@ -920,7 +920,7 @@ pareto_pit.draws_matrix <- function(x, y, weights = NULL, log = FALSE, log_wt_left_sorted <- if (!is.null(weights)) weights[left_ord$ix, j] else NULL left_tail <- left_sorted[tail_ids] - if (!posterior::is_constant(left_tail)) { + if (!posterior:::is_constant(left_tail)) { left_cutoff <- left_sorted[min(tail_ids) - 1] if (left_cutoff == left_tail[1]) { left_cutoff <- left_cutoff - .Machine$double.eps diff --git a/man/pareto_pit.Rd b/man/pareto_pit.Rd index c8af5a70..b99bfc68 100644 --- a/man/pareto_pit.Rd +++ b/man/pareto_pit.Rd @@ -16,23 +16,23 @@ pareto_pit(x, y, ...) \method{pareto_pit}{rvar}(x, y, weights = NULL, log = FALSE, ndraws_tail = NULL, ...) } \arguments{ -\item{x}{(draws) A \code{\link[posterior:draws_matrix]{posterior::draws_matrix}} object or one coercible to a -\code{draws_matrix} object, or an \code{\link[posterior:rvar]{posterior::rvar}} object.} +\item{x}{(draws) A \code{posterior::draws_matrix} object or one coercible to a +\code{posterior::draws_matrix} object, or an \code{posterior::rvar} object.} -\item{y}{(observations) A 1D vector, or an array of dim(x), if x is \code{rvar}. +\item{y}{(observations) A 1D vector, or an array of dim(x), if x is \code{posterior::rvar}. Each element of \code{y} corresponds to a variable in \code{x}.} \item{...}{Arguments passed to individual methods (if applicable).} \item{weights}{A matrix of weights for each draw and variable. \code{weights} -should have one column per variable in \code{x}, and \code{ndraws(x)} rows.} +should have one column per variable in \code{x}, and \code{posterior::ndraws(x)} rows.} \item{log}{(logical) Are the weights passed already on the log scale? The default is \code{FALSE}, that is, expecting \code{weights} to be on the standard (non-log) scale.} \item{ndraws_tail}{(integer) Number of tail draws to use for GPD -fitting. If \code{NULL} (the default), computed using \code{\link[posterior:ps_tail_length]{posterior::ps_tail_length()}}.} +fitting. If \code{NULL} (the default), computed using \code{posterior::ps_tail_length()}.} } \value{ A numeric vector of length \code{length(y)} containing the PIT values, or @@ -49,9 +49,9 @@ test is appropriate. } \details{ The function first computes raw PIT values identically to -\code{\link[posterior:pit]{posterior::pit()}} (including support for weighted draws). It then fits a +\code{posterior::pit()} (including support for weighted draws). It then fits a GPD to both tails of the draws (using the same approach as -\code{\link[posterior:pareto_smooth]{posterior::pareto_smooth()}}) and replaces PIT values for observations falling in +\code{posterior::pareto_smooth()}) and replaces PIT values for observations falling in the tail regions: For a right-tail observation \eqn{y_i > c_R} (where \eqn{c_R} is @@ -67,7 +67,7 @@ where \eqn{p_{tail}} is the proportion of (weighted) mass in the tail. When (log-)weights in \code{weights} are provided, they are used for -the raw PIT computation (as in \code{\link[posterior:pit]{posterior::pit()}}) and for GPD fit. +the raw PIT computation (as in \code{posterior::pit()}) and for GPD fit. } \examples{ x <- posterior::example_draws() @@ -76,6 +76,6 @@ pareto_pit(x, y) } \seealso{ -\code{\link[posterior:pit]{posterior::pit()}} for the unsmoothed version, \code{\link[posterior:pareto_smooth]{posterior::pareto_smooth()}} for +\code{posterior::pit()} for the unsmoothed version, \code{posterior::pareto_smooth()} for Pareto smoothing of draws. } From 4a7704fa28d36f69461212d5d12b0dd69ba6ff02 Mon Sep 17 00:00:00 2001 From: Florence Bockting Date: Fri, 6 Mar 2026 13:50:10 +0200 Subject: [PATCH 120/120] add brms as testing dependeny --- DESCRIPTION | 1 + 1 file changed, 1 insertion(+) diff --git a/DESCRIPTION b/DESCRIPTION index 9f47b08b..26dd4dbf 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -43,6 +43,7 @@ Imports: tidyselect, utils Suggests: + brms (>= 2.23.0), ggdist, ggfortify, gridExtra (>= 2.2.1),