fmrigds

Format-agnostic group-level analysis for fMRI

fmrigds provides a unified framework for working with first-level fMRI statistical maps across multiple data formats and spatial representations. The package implements a lazy evaluation model that enables efficient, reproducible group and meta-analyses without requiring data format conversions or space transformations upfront.

Key Features

Universal Data Access

Lazy Evaluation

Build analysis pipelines declaratively without loading data into memory:

Statistical Methods

Data Export

Reproducibility

Quick Start

Basic workflow

library(fmrigds)

# Load data from any format (auto-detected)
plan <- gds("roi_stats.csv")

# Build a lazy analysis pipeline
plan <- plan |>
  subset(contrast = "Faces>Places") |>
  derive("t") |>
  reduce(method = "fixed")

# Execute and get results
result <- compute(plan)

# Access results
assays(result)         # Statistical maps
subjects(result)       # "meta" (group-level)
space(result)          # Spatial representation

Command-line interface

This package bundles an fmrigds command wrapper under inst/bin/. After installing fmrigds, resolve its installed path via system.file() and then use the CLI to probe sources, assemble plans, preview small blocks, and run full analyses:

# Show help
"$(Rscript -e 'cat(system.file(\"bin\", \"fmrigds\", package = \"fmrigds\"))')" --help

# Inspect a source
"$(Rscript -e 'cat(system.file(\"bin\", \"fmrigds\", package = \"fmrigds\"))')" probe \
  --input group.csv

# Build and save a plan without executing it
"$(Rscript -e 'cat(system.file(\"bin\", \"fmrigds\", package = \"fmrigds\"))')" plan \
  --input group.csv \
  --derive t,p \
  --reduce fixed \
  --posthoc fdr:bh \
  --save-plan fixed-plan.json

# Run a fixed-effects analysis from a CSV and write an HDF5 GDS
"$(Rscript -e 'cat(system.file(\"bin\", \"fmrigds\", package = \"fmrigds\"))')" run \
  --input group.csv --reduce fixed --out results.h5

# Reuse a saved plan later
"$(Rscript -e 'cat(system.file(\"bin\", \"fmrigds\", package = \"fmrigds\"))')" run \
  --load-plan fixed-plan.json --out results.h5

Main commands:

The CLI is designed around the same lazy grammar as the R API. Common paths are first-class (--derive, --reduce, --posthoc, --out), while more advanced workflows can still be steered through repeatable passthrough flags such as --source-option, --reduce-option, --posthoc-option, and --write-option. For plan-first workflows, --save-plan and --load-plan let you separate plan construction from execution.

Interop Surface (for external packages)

These small, public helpers make it easy to “just use GDS” from other R packages without re-implementing adapters or boilerplate.

Meta-analysis with covariates

# Subject-level covariates for meta-regression
col_data <- data.frame(
  age = c(25, 32, 28, 35),
  group = c("control", "patient", "control", "patient"),
  row.names = c("sub-01", "sub-02", "sub-03", "sub-04")
)

# Fixed-effects meta-regression
plan <- gds("roi_stats.csv", col_data = col_data) |>
  reduce(method = "meta:fe_reg", formula = ~ age + group)

# Or attach covariates later
plan <- with_col_data(plan, col_data)

result <- compute(plan)

# Results include coefficients and SEs for each parameter
names(assays(result))
# "coef:(Intercept)", "coef:age", "coef:grouppatient",
# "se_coef:(Intercept)", "se_coef:age", "se_coef:grouppatient"

Examine the cohort before interpreting the group fit

examine_group() branches from the subject-level prefix of an analysis. It uses the reducer's frozen formula, estimands, variance rules, and subject order to report three different questions: whether the data have a validity concern, whether each subject is unexpected under the fitted model, and how much deleting that subject changes the requested group statistic. It does not change the analysis or classify subjects for removal.

analysis <- gds(paths, col_data = participants) |>
  subset(contrast = c("faces>places", "tools>faces")) |>
  reduce(
    method = "meta:re_reg",
    formula = ~ group + age + sex + site
  ) |>
  posthoc("fdr:bh")

exam <- examine_group(
  analysis,
  estimands = "grouppatient",
  quality = c("mean_fd", "tsnr")
)

plot(exam)                         # surprise versus influence
plot(exam, type = "embedding")    # model-adjusted residual geometry
plot(exam, subject = "sub-017")   # retained subject maps
write_report(exam, "group-examination.html")

fit <- compute(analysis)

The review queue uses absolute, stability-aware gates. The percentile-based review_priority only orders inspection. For random-effects models, the first pass holds the full-data heterogeneity estimate fixed; retained subjects then receive exact refits, with both modes recorded in the result. See vignette("group-examination") for the result contract, availability states, and interpretation of the plots.

Repeated-measures mixed models

For common neuroimaging repeated-measures workflows, reduce() also supports a restricted but efficient Gaussian mixed-model family. The fast path assumes the same observation layout and the same fixed/random design for every sample:

result <- gds("roi_long.csv", contrast_data_cols = "time") |>
  reduce(
    method = "lmm:ri_slope1",
    formula = ~ time,
    options = list(
      slope = "time",
      covariance = "diag",
      fit = "REML",
      theta_mode = "voxelwise"
    )
  ) |>
  compute()

names(assays(result))
# "coef:(Intercept)", "coef:time", "vc_intercept", "vc_slope",
# "lambda_intercept", "lambda_slope", ...

Available repeated-measures reducers:

The *_knownvar methods fit diag(var) + vc_resid * I + Z G Z' and currently use voxelwise variance components only. All four methods are intentionally narrower than lmer(): one grouping factor, Gaussian outcomes, and no general random-effects formula parser. See vignette("repeated-measures-lmm") for the weighting contract and guidance on first-level variance quality.

Working with different formats

# Tabular data (CSV, TSV, Parquet)
plan1 <- gds("results.csv")

# NIfTI volumes
plan2 <- gds("cope1.nii.gz")

# HDF5 with /gds group
plan3 <- gds("group_data.h5")

# fmristore layouts (auto-detected)
plan4 <- gds("subject01_fmristore.h5")

Efficient streaming for large datasets

# Process in blocks without loading everything into memory
result <- compute(plan, block = list(sample = 10000))

# Or write directly to disk
plan_with_write <- write_out(plan, "output.h5", format = "h5")
compute(plan_with_write)

Installation

# Install from GitHub
# install.packages("remotes")
# remotes::install_github("bbuchsbaum/fmrigds")
install.packages("fmrigds", repos = c('https://bbuchsbaum.r-universe.dev', 'https://cloud.r-project.org'))

# Optional packages for specific workflows
install.packages(c("arrow", "neuroim2", "neurotabs", "neurothresh"))

Development

# Run test coverage (requires the covr package)
make coverage

Documentation

Browse the complete fmrigds documentation website, read the source vignettes directly on GitHub, or run browseVignettes("fmrigds") after installation to open the built articles locally.

Release Focus

The current development branch is focused on a clean path to 1.0.0:

Contributing

Bug reports and feature requests are welcome on the issue tracker.

Citation

If you use fmrigds in your research, please cite:

Buchsbaum, B. R. (2025). fmrigds: Format-agnostic group-level analysis for fMRI.
R package. https://github.com/bbuchsbaum/fmrigds

License

MIT

Albers theme

This package uses the albersdown theme. Existing vignette theme hooks are replaced so albers.css and local albers.js render consistently on CRAN and GitHub Pages. The defaults are configured via params$family and params$preset (family = 'red', preset = 'interaction'). The pkgdown site uses template: { package: albersdown } together with generated pkgdown/extra.css and pkgdown/extra.js so the theme is linked and activated on site pages.