Nothing
box::use(
testthat[
expect_equal,
expect_gte,
expect_lte,
expect_null,
expect_setequal,
expect_true,
skip_if_not_installed,
test_that
],
withr[local_options]
)
box::use(
artma / econometric / bma[run_bma],
artma / visualization / bma[build_bma_inclusion_data, create_bma_inclusion_plot]
)
# A model space wide enough that BMS retains far more models than carry any
# posterior mass, which is the situation the upstream image plot cannot draw.
fit_demo_bma <- function(n = 150, n_moderators = 8, seed = 4) {
set.seed(seed)
bma_data <- data.frame(effect = stats::rnorm(n))
for (j in seq_len(n_moderators)) {
bma_data[[paste0("moderator", j)]] <- stats::rnorm(n)
}
bma_data$effect <- 0.7 * bma_data$moderator1 -
0.5 * bma_data$moderator2 +
0.3 * bma_data$moderator3 +
stats::rnorm(n) * 0.6
run_bma(bma_data, list(
burn = 500L, iter = 2000L, nmodel = 200L,
g = "UIP", mprior = "uniform", mcmc = "bd"
))
}
test_that("the inclusion grid builds where BMS's own image plot aborts", {
skip_if_not_installed("BMS")
local_options("artma.verbose" = 1)
model <- fit_demo_bma()
# BMS lays its image columns out on cumsum() of unnormalised posterior
# weights, which span enough orders of magnitude to saturate in double
# precision; graphics::image() then rejects the non-monotonic boundaries.
upstream <- tryCatch(
{
grDevices::pdf(NULL)
on.exit(grDevices::dev.off(), add = TRUE)
graphics::image(model, yprop2pip = FALSE, order.by.pip = TRUE)
"rendered"
},
error = function(e) conditionMessage(e)
)
built <- build_bma_inclusion_data(model)
expect_true(!is.null(built))
expect_true(nrow(built$cells) > 0)
# Whether or not this particular fit trips the upstream failure, the
# replacement must produce a grid either way.
expect_true(is.character(upstream))
})
test_that("regressors are ordered by posterior inclusion probability", {
skip_if_not_installed("BMS")
local_options("artma.verbose" = 1)
model <- fit_demo_bma()
built <- build_bma_inclusion_data(model)
bms_order <- rownames(stats::coef(model, order.by.pip = TRUE, exact = TRUE))
expect_equal(built$regressors, bms_order)
})
test_that("cell signs match the coefficients of the model they belong to", {
skip_if_not_installed("BMS")
local_options("artma.verbose" = 1)
model <- fit_demo_bma()
built <- build_bma_inclusion_data(model)
betas <- as.matrix(model$topmod$betas())
weights <- exp(model$topmod$lik() - max(model$topmod$lik()))
best <- order(weights, decreasing = TRUE)[1]
best_betas <- stats::setNames(betas[, best], model$reg.names)
top_cells <- built$cells[built$cells$model == 1, , drop = FALSE]
observed <- stats::setNames(top_cells$inclusion, built$regressors[top_cells$row])
expected <- vapply(names(observed), function(name) {
value <- best_betas[[name]]
if (value == 0) "Excluded" else if (value > 0) "Positive" else "Negative"
}, character(1))
expect_equal(observed[names(expected)], expected)
})
test_that("the grid truncates to the models that carry the posterior mass", {
skip_if_not_installed("BMS")
local_options("artma.verbose" = 1)
model <- fit_demo_bma()
built <- build_bma_inclusion_data(model, max_models = 12L, coverage = 0.99)
expect_lte(built$n_models_shown, 12L)
expect_lte(built$n_models_shown, built$n_models_total)
expect_gte(built$mass_shown, 0)
expect_lte(built$mass_shown, 1 + 1e-9)
# Columns tile the full width exactly once, with no gaps or overlaps.
first_row <- built$cells[built$cells$row == 1, , drop = FALSE]
first_row <- first_row[order(first_row$model), , drop = FALSE]
expect_equal(min(first_row$xmin), 0)
expect_equal(max(first_row$xmax), 1)
expect_equal(first_row$xmin[-1], utils::head(first_row$xmax, -1))
})
test_that("create_bma_inclusion_plot returns a ggplot with the three cell states", {
skip_if_not_installed("BMS")
local_options("artma.verbose" = 1)
model <- fit_demo_bma()
plot <- create_bma_inclusion_plot(model, theme_name = "blue")
expect_true(ggplot2::is_ggplot(plot))
expect_setequal(
unique(plot$data$inclusion),
intersect(c("Positive", "Negative", "Excluded"), unique(plot$data$inclusion))
)
expect_true(all(plot$data$inclusion %in% c("Positive", "Negative", "Excluded")))
})
test_that("build_bma_inclusion_data returns NULL when there is nothing to draw", {
empty <- structure(
list(
reg.names = character(0),
topmod = list(betas = function() matrix(numeric(0), nrow = 0, ncol = 0))
),
class = "bma"
)
expect_null(build_bma_inclusion_data(empty))
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.