Extending mixpower with custom backends

This vignette describes the backend contract used by mp_power() so you can plug in custom simulators, fitters, and tests without modifying the core loop.

The three-function contract

An mp_scenario stores an engine with:

  1. simulate_fun(scenario, seed = NULL) — returns a data.frame of simulated data.
    mp_power() passes seed when the function accepts it (see ?mp_power).

  2. fit_fun(data, scenario) — returns a fitted model object.

  3. test_fun(fit, scenario) — returns list(p_value = <scalar>).
    Use NA_real_ for p_value when the test cannot be computed.

mp_power() records fit_ok, optional singular from attr(fit, "singular"), and aggregates power using alpha and failure_policy.

Building a validated backend with mp_backend()

Use mp_backend() to wrap the three functions with a name and optional metadata.
validate_mp_backend() checks formal argument names before you run simulations:

library(mixpower)

sim_fun <- function(scenario, seed = NULL) {
  n <- scenario$design$clusters$subject
  x <- stats::rbinom(n, 1, 0.5)
  y <- scenario$assumptions$fixed_effects$condition * x +
    stats::rnorm(n, sd = scenario$assumptions$residual_sd)
  data.frame(y = y, condition = x)
}
fit_fun <- function(data, scenario) stats::lm(scenario$formula, data = data)
test_fun <- function(fit, scenario) {
  sm <- summary(fit)
  p <- sm$coefficients["condition", "Pr(>|t|)"]
  list(p_value = as.numeric(p))
}

eng <- mp_backend(sim_fun, fit_fun, test_fun, name = "toy_lm")
eng
#> <mp_backend>
#>   name: toy_lm 
#>   simulate_fun: list(scenario = ) ...

Using mp_scenario() and mp_power()

d <- mp_design(list(subject = 25), trials_per_cell = 1)
a <- mp_assumptions(list(`(Intercept)` = 0, condition = 0.2), residual_sd = 1)
scn <- mp_scenario(
  y ~ condition, d, a,
  test = "custom",
  simulate_fun = eng$simulate_fun,
  fit_fun = eng$fit_fun,
  test_fun = eng$test_fun
)
mp_power(scn, nsim = 12, seed = 1)
#> <mp_power>
#>   nsim: 12
#>   alpha: 0.05
#>   failure_policy: count_as_nondetect
#>   power: 0.000
#>   mcse: 0.000
#>   95% CI (clopper-pearson): [0.000, 0.265]
#>   diagnostics:
#>     - fail_rate: 0.000
#>     - singular_rate: 0.000
#>     - type_s: NA
#>     - type_m: NA

Built-in backends

  • lme4: mp_backend_lme4(), mp_backend_lme4_binomial(), etc., return mp_backend objects.
    Scenario helpers (mp_scenario_lme4(), …) copy the three functions into the scenario.

  • glmmTMB (optional): mp_backend_glmmtmb() when package glmmTMB is installed — see ?mp_backend_glmmtmb.

Parallel grids

Sensitivity and power-curve grids can be evaluated in parallel outside mp_power() (e.g. mp_sensitivity_parallel(), mp_power_curve_parallel()) using per-cell seeds seed + cell_index - 1L for reproducibility.

Further reading

  • ?mp_backend, ?validate_mp_backend, ?mp_scenario, ?mp_power
  • Vignette mixpower-intro for Wald vs LRT and design-first workflows.