| Title: | Lazy, Format-Agnostic Group Analysis for fMRI |
|---|---|
| Description: | Provides a Group Data Set (GDS) abstraction and lazy analysis pipeline for first-level fMRI statistical outputs. Unifies tabular, NIfTI, HDF5, and fmristore inputs under a common sample x subject x contrast representation; supports space-aware transformations, group and meta-analytic reducers, provenance tracking, and reproducible export. |
| Authors: | Brad Buchsbaum [aut, cre] |
| Maintainer: | Brad Buchsbaum <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.0.9000 |
| Built: | 2026-05-07 17:01:10 UTC |
| Source: | https://github.com/bbuchsbaum/fmrigds |
Lazy, format-agnostic group analysis for fMRI.
fmrigds provides a common Group Data Set (GDS) abstraction for first-level
fMRI outputs together with a lazy, plan-based workflow for group analysis.
The package centers on a compact public grammar:
gds() to open supported sources and create a plan
subset(), derive(), align(), mask(), map_to(), reduce(),
posthoc(), and write_out() to describe analysis steps
compute() to execute the plan and return a realised GDS
Core capabilities include:
Constructors for GDS objects and spaces
Storage adapters (tabular, NIfTI, HDF5, fmristore)
Statistical derivations and variance propagation helpers
Reducer and post-hoc registries for group and meta-analytic workflows
Provenance-aware export and inspection helpers
See the package reference and vignettes for supported workflows and release guidance.
Maintainer: Brad Buchsbaum [email protected]
Useful links:
Append an operation to a plan
add_op(plan, node)add_op(plan, node)
plan |
A |
node |
Operation node (list) |
Updated plan
Append a provenance node to metadata
add_provenance_node(metadata, op_name, params, inputs = list())add_provenance_node(metadata, op_name, params, inputs = list())
metadata |
Metadata list from |
op_name |
Operation name |
params |
Named list of parameters |
inputs |
Parent node identifiers |
Updated metadata list
Align subjects into a consensus space
align(x, family)align(x, family)
x |
A plan, source, or realised GDS |
family |
A |
Updated plan
Eagerly align subjects and compute immediately
align_eager(x, ...)align_eager(x, ...)
x |
Plan, source, or realized GDS |
... |
Arguments passed to align(), then compute() |
A realized GDS object
Syntactic sugar around the map-family registry helpers.
register_alignment(x, family, overwrite = FALSE) list_alignments(x) get_alignment(x, name)register_alignment(x, family, overwrite = FALSE) list_alignments(x) get_alignment(x, name)
x |
A |
family |
A |
overwrite |
Logical; overwrite existing family with the same name |
name |
Alignment family name |
The updated object with the family registered
A character vector of registered alignment family names
The MapFamily entry or NULL if not found
Apply a common mask to two realised GDS objects
apply_common_mask(g1, g2, rule = c("intersection", "union"))apply_common_mask(g1, g2, rule = c("intersection", "union"))
g1 |
First GDS |
g2 |
Second GDS |
rule |
Mask rule ("intersection" or "union") |
A list with subsetted g1, g2, and indices idx1, idx2
Provides a lightweight front door for external packages holding data in memory (lists, arrays, data.frames) to construct a validated GDS without going through on-disk adapters.
as_gds(x, ...) ## S3 method for class 'list' as_gds( x, space = NULL, subjects = NULL, contrasts = NULL, col_data = NULL, row_data = NULL, metadata = list(), ... ) ## S3 method for class 'array' as_gds( x, space = NULL, subjects = NULL, contrasts = NULL, assay_name = "beta", col_data = NULL, row_data = NULL, metadata = list(), ... ) ## S3 method for class 'data.frame' as_gds( x, mapping = NULL, space = NULL, col_data = NULL, row_data = NULL, contrast_data = NULL, metadata = list(), ... ) ## S3 method for class 'nftab' as_gds(x, feature = NULL, ...)as_gds(x, ...) ## S3 method for class 'list' as_gds( x, space = NULL, subjects = NULL, contrasts = NULL, col_data = NULL, row_data = NULL, metadata = list(), ... ) ## S3 method for class 'array' as_gds( x, space = NULL, subjects = NULL, contrasts = NULL, assay_name = "beta", col_data = NULL, row_data = NULL, metadata = list(), ... ) ## S3 method for class 'data.frame' as_gds( x, mapping = NULL, space = NULL, col_data = NULL, row_data = NULL, contrast_data = NULL, metadata = list(), ... ) ## S3 method for class 'nftab' as_gds(x, feature = NULL, ...)
x |
Object to coerce (list/array/data.frame) |
... |
Additional arguments passed to methods |
space |
Optional space for sample axis; defaults to sample labels from data |
subjects |
Optional subject identifiers |
contrasts |
Optional contrast identifiers |
col_data |
Optional subject-level covariates |
row_data |
Optional sample-level metadata |
metadata |
Optional metadata list merged into |
assay_name |
Name to use for the single-array input (default: "beta") |
mapping |
Optional list mapping column names for axes and assays. Default: list(sample="sample", subject="subject", contrast="contrast", assays=list(beta="beta", var="var"), contrast_data=NULL) |
contrast_data |
Optional contrast-level metadata. When omitted,
|
feature |
Name of the neurotabs feature to use as the primary assay |
A gds object
Create a GDS plan from an image catalog. The catalog's assay mappings determine which files are used for beta and se assays, and subject-level metadata from the catalog is attached as col_data.
## S3 method for class 'image_catalog' as_gds(x, mask = NULL, ...)## S3 method for class 'image_catalog' as_gds(x, mask = NULL, ...)
x |
An image_catalog object with assay mappings set via |
mask |
Optional mask file path or NeuroVol object. |
... |
Additional arguments passed to |
A gds_plan object.
## Not run: catalog <- image_catalog("study/", "sub-*/stats/*.nii.gz", path_regex = "sub-(?<subject>[^/]+)") |> map_assays(beta = "cope", se = "varcope") plan <- as_gds(catalog, mask = "mask.nii.gz") result <- compute(plan) ## End(Not run)## Not run: catalog <- image_catalog("study/", "sub-*/stats/*.nii.gz", path_regex = "sub-(?<subject>[^/]+)") |> map_assays(beta = "cope", se = "varcope") plan <- as_gds(catalog, mask = "mask.nii.gz") result <- compute(plan) ## End(Not run)
Import a neuroim2::NeuroVec (4D brain volume) as a GDS object.
The 4th dimension can represent subjects OR contrasts.
## S3 method for class 'NeuroVec' as_gds( x, assay_name = "beta", along = c("subject", "contrast"), subjects = NULL, contrasts = NULL, mask = NULL, ... ) ## S3 method for class 'DenseNeuroVec' as_gds( x, assay_name = "beta", along = c("subject", "contrast"), subjects = NULL, contrasts = NULL, mask = NULL, ... )## S3 method for class 'NeuroVec' as_gds( x, assay_name = "beta", along = c("subject", "contrast"), subjects = NULL, contrasts = NULL, mask = NULL, ... ) ## S3 method for class 'DenseNeuroVec' as_gds( x, assay_name = "beta", along = c("subject", "contrast"), subjects = NULL, contrasts = NULL, mask = NULL, ... )
x |
A |
assay_name |
Name for the assay (default: |
along |
What does the 4th dimension represent? One of:
|
subjects |
Character vector of subject IDs. Length must match the 4th
dimension when |
contrasts |
Character vector of contrast names. Length must match the 4th
dimension when |
mask |
Optional mask. See |
... |
Additional arguments passed to |
A gds object with voxel space.
## Not run: # 4D volume where each volume is a subject vec4d <- neuroim2::read_vec("all_subjects.nii.gz") gds_obj <- as_gds(vec4d, along = "subject", subjects = c("sub-01", "sub-02", "sub-03")) # 4D volume where each volume is a contrast gds_obj <- as_gds(vec4d, along = "contrast", contrasts = c("faces", "places", "objects")) ## End(Not run)## Not run: # 4D volume where each volume is a subject vec4d <- neuroim2::read_vec("all_subjects.nii.gz") gds_obj <- as_gds(vec4d, along = "subject", subjects = c("sub-01", "sub-02", "sub-03")) # 4D volume where each volume is a contrast gds_obj <- as_gds(vec4d, along = "contrast", contrasts = c("faces", "places", "objects")) ## End(Not run)
Import a single neuroim2::NeuroVol (3D brain volume) as a GDS object.
The volume becomes a single subject with a single contrast.
## S3 method for class 'NeuroVol' as_gds( x, assay_name = "beta", subject = "subject1", contrast = "contrast1", mask = NULL, ... ) ## S3 method for class 'DenseNeuroVol' as_gds( x, assay_name = "beta", subject = "subject1", contrast = "contrast1", mask = NULL, ... )## S3 method for class 'NeuroVol' as_gds( x, assay_name = "beta", subject = "subject1", contrast = "contrast1", mask = NULL, ... ) ## S3 method for class 'DenseNeuroVol' as_gds( x, assay_name = "beta", subject = "subject1", contrast = "contrast1", mask = NULL, ... )
x |
A |
assay_name |
Name for the assay (default: |
subject |
Subject identifier (default: |
contrast |
Contrast identifier (default: |
mask |
Optional mask. Can be:
|
... |
Additional arguments passed to |
A gds object with voxel space.
## Not run: vol <- neuroim2::read_vol("beta.nii.gz") gds_obj <- as_gds(vol, subject = "sub-01", contrast = "faces") ## End(Not run)## Not run: vol <- neuroim2::read_vol("beta.nii.gz") gds_obj <- as_gds(vol, subject = "sub-01", contrast = "faces") ## End(Not run)
Extract a single assay from a GDS object and return it as a
neuroim2::NeuroVec (4D neuroimaging array), stacking along the 4th
dimension.
as_neurovec( x, assay = "beta", along = c("subject", "contrast", "both"), subset_subjects = NULL, subset_contrasts = NULL )as_neurovec( x, assay = "beta", along = c("subject", "contrast", "both"), subset_subjects = NULL, subset_contrasts = NULL )
x |
A GDS object with a voxel space. |
assay |
Name of the assay to extract (default: |
along |
Which dimension to stack along the 4th dimension. One of:
|
subset_subjects |
Optional character vector of subject IDs to include. |
subset_contrasts |
Optional character vector of contrast names to include |
A neuroim2::NeuroVec object with dimensions [x, y, z, n] where
n depends on the along parameter.
## Not run: # Stack all subjects into a 4D volume vec4d <- as_neurovec(gds, assay = "beta", along = "subject") # Stack specific contrasts vec4d <- as_neurovec(gds, assay = "t", along = "contrast", subset_contrasts = c("faces", "places")) ## End(Not run)## Not run: # Stack all subjects into a 4D volume vec4d <- as_neurovec(gds, assay = "beta", along = "subject") # Stack specific contrasts vec4d <- as_neurovec(gds, assay = "t", along = "contrast", subset_contrasts = c("faces", "places")) ## End(Not run)
Extract a single assay from a GDS object and return it as a list of
neuroim2::NeuroVol objects, one per subject/contrast combination.
as_neurovol_list( x, assay = "beta", by = c("subject", "contrast"), drop_dim = TRUE )as_neurovol_list( x, assay = "beta", by = c("subject", "contrast"), drop_dim = TRUE )
x |
A GDS object with a voxel space. |
assay |
Name of the assay to extract (default: |
by |
How to organize the output list. One of:
|
drop_dim |
If |
A named list of neuroim2::NeuroVol objects. The structure depends
on the by parameter and the dimensions of the data:
Single contrast, by = "subject": list of NeuroVol named by subject
Single subject, by = "contrast": list of NeuroVol named by contrast
Multiple of both: nested list [[subject]][[contrast]]
## Not run: # Extract beta maps as list of NeuroVols (one per subject) vols <- as_neurovol_list(gds, assay = "beta") vols$sub01 # NeuroVol for subject "sub01" # Extract by contrast vols_by_con <- as_neurovol_list(gds, assay = "t", by = "contrast") ## End(Not run)## Not run: # Extract beta maps as list of NeuroVols (one per subject) vols <- as_neurovol_list(gds, assay = "beta") vols$sub01 # NeuroVol for subject "sub01" # Extract by contrast vols_by_con <- as_neurovol_list(gds, assay = "t", by = "contrast") ## End(Not run)
Ensure an object is a plan
as_plan(x)as_plan(x)
x |
Plan, source, or realized GDS |
A plan object
Extract a single assay from a GDS object
assay(x, name = "beta", ...)assay(x, name = "beta", ...)
x |
A GDS object |
name |
Assay name (default: "beta") |
... |
Additional arguments |
A 3D array
Retrieve assay metadata
assay_info(name)assay_info(name)
name |
Assay name |
Assay metadata list or NULL if not found
Extract assays from a GDS object
assays(x)assays(x)
x |
A GDS object |
Named list of 3D arrays
Assert compatibility between two spaces
assert_compatible_spaces(g1, g2, fields = c("type", "dim", "template_id"))assert_compatible_spaces(g1, g2, fields = c("type", "dim", "template_id"))
g1 |
First GDS or space |
g2 |
Second GDS or space |
fields |
Fields to compare (subset of c("type","dim","template_id")) |
TRUE if compatible; otherwise errors
sp1 <- space_voxel(c(2,2,2), diag(4), storage = "dense") sp2 <- space_voxel(c(2,2,2), diag(4), storage = "dense") assert_compatible_spaces(sp1, sp2)sp1 <- space_voxel(c(2,2,2), diag(4), storage = "dense") sp2 <- space_voxel(c(2,2,2), diag(4), storage = "dense") assert_compatible_spaces(sp1, sp2)
Apply regex patterns to filenames or paths to extract values for new metadata columns.
assign_meta( catalog, column, pattern, source = "basename", replacement = "\\1" )assign_meta( catalog, column, pattern, source = "basename", replacement = "\\1" )
catalog |
An image_catalog object. |
column |
Name of new column to create. |
pattern |
Regex pattern to match (should contain a capture group). |
source |
Which existing column to match against. Default |
replacement |
Replacement string using backreferences. Default |
Updated image_catalog.
## Not run: catalog <- assign_meta(catalog, "run", "run-([0-9]+)", source = "basename") catalog <- assign_meta(catalog, "contrast", "([^_]+)\\.nii", replacement = "\\1") ## End(Not run)## Not run: catalog <- assign_meta(catalog, "run", "run-([0-9]+)", source = "basename") catalog <- assign_meta(catalog, "contrast", "([^_]+)\\.nii", replacement = "\\1") ## End(Not run)
Attach a custom weight array to a GDS
attach_weight(g, name, array)attach_weight(g, name, array)
g |
A realised GDS |
name |
Assay-like name for the weights (e.g., "n_eff" or "w_custom") |
array |
Numeric 3D array matching |
Updated GDS with weights stored in assays
beta <- array(0, dim = c(2,2,1)); var <- array(1, dim = c(2,2,1)) g <- new_gds(list(beta = beta, var = var), space_sample_labels(c("a","b")), c("s1","s2"), "c1") w <- array(1, dim = c(2,2,1)) g2 <- attach_weight(g, "w_custom", w)beta <- array(0, dim = c(2,2,1)); var <- array(1, dim = c(2,2,1)) g <- new_gds(list(beta = beta, var = var), space_sample_labels(c("a","b")), c("s1","s2"), "c1") w <- array(1, dim = c(2,2,1)) g2 <- attach_weight(g, "w_custom", w)
Test whether an assay can be linearly mapped
can_map_linear(name)can_map_linear(name)
name |
Assay name |
Logical, TRUE if assay can be linearly mapped
Canonicalize an operation node
canonicalize_node(node)canonicalize_node(node)
node |
Operation node list |
Canonicalized node list
Returns a samples x terms x contrasts array by stacking per-term coefficient assays (e.g., coef:(Intercept), coef:age, ...) along a new terms dimension.
coef_array(gds, prefix = "coef:")coef_array(gds, prefix = "coef:")
gds |
A realised GDS |
prefix |
Assay name prefix to stack (default: "coef:") |
A 3D numeric array samples x terms x contrasts
Retrieve packed covariance triangles for OLS coefficients
coef_cov_tri(gds, method = "ols:voxelwise", contrast)coef_cov_tri(gds, method = "ols:voxelwise", contrast)
gds |
A realised GDS |
method |
Reducer method key (default: "ols:voxelwise") |
contrast |
Contrast name to retrieve |
A list with fields type, terms, pack, and cov_tri (L x samples)
Extract column (subject) metadata from a GDS object
col_data(x)col_data(x)
x |
A GDS object |
Data frame with subject-level metadata
Compute a common mask between two spaces
common_mask(g1, g2, rule = c("intersection", "union"))common_mask(g1, g2, rule = c("intersection", "union"))
g1 |
First GDS or space |
g2 |
Second GDS or space |
rule |
Either "intersection" or "union" |
A list with integer indices idx1 and idx2 for subsetting each
m1 <- array(c(TRUE, FALSE, TRUE, TRUE), c(2, 2, 1)) m2 <- array(c(TRUE, TRUE, FALSE, TRUE), c(2, 2, 1)) sp1 <- space_voxel(c(2,2,1), diag(4), mask_bitmap = m1, storage = "packed") sp2 <- space_voxel(c(2,2,1), diag(4), mask_bitmap = m2, storage = "packed") common_mask(sp1, sp2, rule = "intersection")m1 <- array(c(TRUE, FALSE, TRUE, TRUE), c(2, 2, 1)) m2 <- array(c(TRUE, TRUE, FALSE, TRUE), c(2, 2, 1)) sp1 <- space_voxel(c(2,2,1), diag(4), mask_bitmap = m1, storage = "packed") sp2 <- space_voxel(c(2,2,1), diag(4), mask_bitmap = m2, storage = "packed") common_mask(sp1, sp2, rule = "intersection")
Materialise a plan into a realised GDS
compute( x, sink = c("memory", "h5"), path = NULL, sink_options = list(), block = NULL, assays = NULL, ... )compute( x, sink = c("memory", "h5"), path = NULL, sink_options = list(), block = NULL, assays = NULL, ... )
x |
Plan or source |
sink |
Storage sink ("memory" for in-memory data, "h5" to write a GDS HDF5 store) |
path |
Output path when |
sink_options |
Optional list of sink-specific options |
block |
Optional list specifying block indices to request from the adapter |
assays |
Optional character vector to return raw arrays instead of GDS object |
... |
Reserved for future use |
A realised gds object
Extract contrast-level metadata from a GDS object
contrast_data(x)contrast_data(x)
x |
A GDS object or plan |
Data frame with one row per contrast/repeated-measure level
Extract contrast identifiers from a GDS object
contrasts(x)contrasts(x)
x |
A GDS object |
Character vector of contrast names
Record a derivation operation in a plan
derive(x, what = c("var", "se", "t", "z"), options = list())derive(x, what = c("var", "se", "t", "z"), options = list())
x |
Plan or source |
what |
Character vector of assays to derive |
options |
Optional named list of options |
Updated plan
Eagerly derive statistics and compute immediately
derive_eager(...)derive_eager(...)
... |
Arguments passed to derive(), then compute() |
A realized GDS object
Detect the best adapter for a source
detect_adapter(source, prefer = NULL)detect_adapter(source, prefer = NULL)
source |
Source specification (path, list, etc.) |
prefer |
Optional adapter name to prefer when available |
Adapter name
Compute a stable digest for a plan
digest_plan(plan)digest_plan(plan)
plan |
A gds_plan object |
Character digest hash
Human-readable summary of a realised GDS or a lazy gds_plan.
explain(x) ## S3 method for class 'gds' print(x, ...) ## S3 method for class 'gds_plan' print(x, ...)explain(x) ## S3 method for class 'gds' print(x, ...) ## S3 method for class 'gds_plan' print(x, ...)
x |
A |
... |
Additional arguments ignored. |
Invisibly returns x (and prints a summary)
Explain a plan's operations in a tidy table
explain_plan(plan)explain_plan(plan)
plan |
A |
A data.frame with one row per node (printed and returned invisibly)
Convenience function that combines split.gds() and as_neurovol_list()
to extract neuroimaging volumes for subjects in a specific group.
extract_group(x, group_var, group_level, assay = "beta", ...)extract_group(x, group_var, group_level, assay = "beta", ...)
x |
A GDS object. |
group_var |
Column name in |
group_level |
The specific group level to extract. |
assay |
Name of the assay to extract (default: |
... |
Additional arguments passed to |
A named list of neuroim2::NeuroVol objects for subjects in the
specified group.
## Not run: # Get beta maps for all patients patient_vols <- extract_group(gds, "diagnosis", "patient", assay = "beta") # Get t-maps for controls control_ts <- extract_group(gds, "diagnosis", "control", assay = "t") ## End(Not run)## Not run: # Get beta maps for all patients patient_vols <- extract_group(gds, "diagnosis", "patient", assay = "beta") # Get t-maps for controls control_ts <- extract_group(gds, "diagnosis", "control", assay = "t") ## End(Not run)
Convenience helper to discover NIfTI map files on disk using a flexible
regular-expression pattern. This is intended for quick "scooping up" of
first-level maps spread across a directory tree (e.g. .*/maps/AUC.nii).
find_maps( root, pattern = "\\.nii(\\.gz)?$", recursive = TRUE, subject_fun = NULL, contrast_fun = NULL )find_maps( root, pattern = "\\.nii(\\.gz)?$", recursive = TRUE, subject_fun = NULL, contrast_fun = NULL )
root |
Root directory to search. |
pattern |
Regular expression passed to |
recursive |
Logical; whether to search subdirectories (default |
subject_fun |
Optional function applied to the character vector of file paths, expected to return a character vector of subject identifiers. |
contrast_fun |
Optional function applied to the character vector of file paths, expected to return a character vector of contrast labels. |
The function does not impose any file naming convention. Instead, callers
can provide optional subject_fun and contrast_fun hooks to derive
subject and contrast labels from file paths.
A data.frame with columns file, subject, and contrast.
Create a Group Data Set (GDS)
Adapter front door for building a plan
new_gds( assays, space, subjects, contrasts, col_data = NULL, row_data = NULL, metadata = list() ) gds(source, format = c("auto", ls(.adapter_registry)), prefer = NULL, ...)new_gds( assays, space, subjects, contrasts, col_data = NULL, row_data = NULL, metadata = list() ) gds(source, format = c("auto", ls(.adapter_registry)), prefer = NULL, ...)
assays |
Named list of 3-D arrays (sample x subject x contrast) |
space |
A space object describing the sample axis |
subjects |
Character vector of subject identifiers |
contrasts |
Character vector of contrast identifiers |
col_data |
Optional data frame keyed by subjects |
row_data |
Optional data frame keyed by samples |
metadata |
Optional list merged with |
source |
Source specification (paths, etc.) |
format |
Optional adapter name or "auto" |
prefer |
Optional preferred adapter when multiple match |
... |
Adapter-specific arguments forwarded to |
An object of class c("gds", "group_data")
A gds_plan
The most flexible import function for creating GDS objects from neuroim2 data. Supports multiple subjects and multiple contrasts, with proper variance/SE handling.
gds_from_neurovol_nested( beta, var = NULL, se = NULL, contrasts = NULL, mask = NULL, col_data = NULL, metadata = list(), ... )gds_from_neurovol_nested( beta, var = NULL, se = NULL, contrasts = NULL, mask = NULL, col_data = NULL, metadata = list(), ... )
beta |
A nested list structure for beta/effect estimates. Can be:
|
var |
Optional matching structure for variance estimates. |
se |
Optional matching structure for standard errors (alternative to var). |
contrasts |
Character vector of contrast names. Required when using NeuroVec inputs; inferred from inner list names otherwise. |
mask |
Optional mask. See |
col_data |
Optional data frame of subject-level covariates. |
metadata |
Optional list of additional metadata to attach. |
... |
Additional arguments passed to |
A gds object with dimensions samples x subjects x contrasts.
## Not run: # Example 1: Nested list structure (subjects x contrasts) beta <- list( `sub-01` = list( faces = neuroim2::read_vol("sub-01_faces_beta.nii.gz"), places = neuroim2::read_vol("sub-01_places_beta.nii.gz") ), `sub-02` = list( faces = neuroim2::read_vol("sub-02_faces_beta.nii.gz"), places = neuroim2::read_vol("sub-02_places_beta.nii.gz") ) ) var <- list( `sub-01` = list( faces = neuroim2::read_vol("sub-01_faces_var.nii.gz"), places = neuroim2::read_vol("sub-01_places_var.nii.gz") ), `sub-02` = list( faces = neuroim2::read_vol("sub-02_faces_var.nii.gz"), places = neuroim2::read_vol("sub-02_places_var.nii.gz") ) ) gds_obj <- gds_from_neurovol_nested(beta, var = var) # Example 2: List of 4D NeuroVecs (each subject has multi-contrast 4D file) beta_vecs <- list( `sub-01` = neuroim2::read_vec("sub-01_allcons_beta.nii.gz"), `sub-02` = neuroim2::read_vec("sub-02_allcons_beta.nii.gz") ) gds_obj <- gds_from_neurovol_nested(beta_vecs, contrasts = c("faces", "places", "objects")) ## End(Not run)## Not run: # Example 1: Nested list structure (subjects x contrasts) beta <- list( `sub-01` = list( faces = neuroim2::read_vol("sub-01_faces_beta.nii.gz"), places = neuroim2::read_vol("sub-01_places_beta.nii.gz") ), `sub-02` = list( faces = neuroim2::read_vol("sub-02_faces_beta.nii.gz"), places = neuroim2::read_vol("sub-02_places_beta.nii.gz") ) ) var <- list( `sub-01` = list( faces = neuroim2::read_vol("sub-01_faces_var.nii.gz"), places = neuroim2::read_vol("sub-01_places_var.nii.gz") ), `sub-02` = list( faces = neuroim2::read_vol("sub-02_faces_var.nii.gz"), places = neuroim2::read_vol("sub-02_places_var.nii.gz") ) ) gds_obj <- gds_from_neurovol_nested(beta, var = var) # Example 2: List of 4D NeuroVecs (each subject has multi-contrast 4D file) beta_vecs <- list( `sub-01` = neuroim2::read_vec("sub-01_allcons_beta.nii.gz"), `sub-02` = neuroim2::read_vec("sub-02_allcons_beta.nii.gz") ) gds_obj <- gds_from_neurovol_nested(beta_vecs, contrasts = c("faces", "places", "objects")) ## End(Not run)
Import matched lists of NeuroVol objects (e.g., beta and variance maps)
into a GDS. This handles the common case of multiple subjects with a
single contrast. For multiple contrasts, use gds_from_neurovol_nested().
gds_from_neurovols( beta, var = NULL, se = NULL, contrast = "contrast1", mask = NULL, col_data = NULL, ... )gds_from_neurovols( beta, var = NULL, se = NULL, contrast = "contrast1", mask = NULL, col_data = NULL, ... )
beta |
A named list of |
var |
Optional named list of |
se |
Optional named list of |
contrast |
Contrast name (default: |
mask |
Optional mask. See |
col_data |
Optional data frame of subject-level covariates.
Row names must match subject IDs (names of |
... |
Additional arguments passed to |
A gds object.
## Not run: # Load beta and variance maps for each subject beta_vols <- list( `sub-01` = neuroim2::read_vol("sub-01_beta.nii.gz"), `sub-02` = neuroim2::read_vol("sub-02_beta.nii.gz") ) var_vols <- list( `sub-01` = neuroim2::read_vol("sub-01_var.nii.gz"), `sub-02` = neuroim2::read_vol("sub-02_var.nii.gz") ) gds_obj <- gds_from_neurovols(beta_vols, var = var_vols) # With subject covariates covars <- data.frame(age = c(25, 30), group = c("A", "B"), row.names = c("sub-01", "sub-02")) gds_obj <- gds_from_neurovols(beta_vols, var = var_vols, col_data = covars) ## End(Not run)## Not run: # Load beta and variance maps for each subject beta_vols <- list( `sub-01` = neuroim2::read_vol("sub-01_beta.nii.gz"), `sub-02` = neuroim2::read_vol("sub-02_beta.nii.gz") ) var_vols <- list( `sub-01` = neuroim2::read_vol("sub-01_var.nii.gz"), `sub-02` = neuroim2::read_vol("sub-02_var.nii.gz") ) gds_obj <- gds_from_neurovols(beta_vols, var = var_vols) # With subject covariates covars <- data.frame(age = c(25, 30), group = c("A", "B"), row.names = c("sub-01", "sub-02")) gds_obj <- gds_from_neurovols(beta_vols, var = var_vols, col_data = covars) ## End(Not run)
This helper builds on the NIfTI adapter to materialise a realised GDS from
a set of NIfTI map files, typically obtained via find_maps(). The heavy
lifting (reading NIfTI, spatial metadata, masking) is delegated to the
existing NIfTI adapter and the neuroim2 package.
gds_from_nifti_maps(maps, mask = NULL, ...)gds_from_nifti_maps(maps, mask = NULL, ...)
maps |
A data.frame (or tibble) with at least a |
mask |
Optional mask passed through to |
... |
Additional arguments forwarded to |
Subject and contrast labels can be injected post-hoc using the subject and
contrast columns when available in maps. This avoids hard-coding any
filename convention while still allowing callers to impose semantics via
hooks.
Beta-only raw maps are accepted. When no variance or standard-error maps are
available, the realised GDS contains a synthetic var assay filled with 1 and
a warning is emitted. This placeholder variance is useful for satisfying the
GDS assay contract, but it is not meaningful subject-level uncertainty. For
group analyses over subject-level searchlight or stat-map metrics, prefer an
unweighted reducer such as method = "ols:voxelwise" instead of
fixed/random-effects meta-analysis.
A realised GDS object.
## Not run: maps <- data.frame( file = c("1001_era_partition/maps/naive_diag_mean.nii.gz", "1002_era_partition/maps/naive_diag_mean.nii.gz"), subject = c("1001", "1002"), contrast = "naive_diag_mean" ) group_info <- data.frame( group = c("control", "patient"), row.names = maps$subject ) g <- gds_from_nifti_maps(maps) |> with_col_data(group_info) fit <- reduce(g, method = "ols:voxelwise", formula = ~ group) |> compute() ## End(Not run)## Not run: maps <- data.frame( file = c("1001_era_partition/maps/naive_diag_mean.nii.gz", "1002_era_partition/maps/naive_diag_mean.nii.gz"), subject = c("1001", "1002"), contrast = "naive_diag_mean" ) group_info <- data.frame( group = c("control", "patient"), row.names = maps$subject ) g <- gds_from_nifti_maps(maps) |> with_col_data(group_info) fit <- reduce(g, method = "ols:voxelwise", formula = ~ group) |> compute() ## End(Not run)
gds_from_scalar_maps() is a semantic wrapper for beta-only/stat-map
workflows: each NIfTI is a subject-level metric map rather than a first-level
beta image with meaningful uncertainty. The resulting GDS uses the NIfTI
adapter's unit-variance placeholder behavior for beta-only sources.
gds_from_scalar_maps( files, subject = NULL, contrast = "map", col_data = NULL, mask = NULL, ... ) as_scalar_map_gds( files, subject = NULL, contrast = "map", col_data = NULL, mask = NULL, ... )gds_from_scalar_maps( files, subject = NULL, contrast = "map", col_data = NULL, mask = NULL, ... ) as_scalar_map_gds( files, subject = NULL, contrast = "map", col_data = NULL, mask = NULL, ... )
files |
Character vector of NIfTI paths, a data.frame with a |
subject |
Optional subject identifiers. Required for character |
contrast |
Contrast label(s). A scalar value is recycled across files.
Ignored when |
col_data |
Optional subject-level covariates. If a |
mask |
Optional mask passed to |
... |
Additional arguments forwarded to |
A realised gds object.
## Not run: g <- gds_from_scalar_maps( files = c("sub-01/maps/auc.nii.gz", "sub-02/maps/auc.nii.gz"), subject = c("sub-01", "sub-02"), contrast = "auc", col_data = participants ) fit <- group_ols(g, ~ group) |> compute() ## End(Not run)## Not run: g <- gds_from_scalar_maps( files = c("sub-01/maps/auc.nii.gz", "sub-02/maps/auc.nii.gz"), subject = c("sub-01", "sub-02"), contrast = "auc", col_data = participants ) fit <- group_ols(g, ~ group) |> compute() ## End(Not run)
Construct default metadata for a GDS object
gds_metadata( schema_version = "0.1.0", units = list(), provenance = list(graph = list(), log = character(), digest = NULL), software = list(package = "fmrigds", version = .pkg_version(), R_version = getRversion()), alignment = NULL, map_families = list(), mask_info = NULL, contrast_info = NULL, design_mats = NULL, notes = NULL, created = Sys.time() )gds_metadata( schema_version = "0.1.0", units = list(), provenance = list(graph = list(), log = character(), digest = NULL), software = list(package = "fmrigds", version = .pkg_version(), R_version = getRversion()), alignment = NULL, map_families = list(), mask_info = NULL, contrast_info = NULL, design_mats = NULL, notes = NULL, created = Sys.time() )
schema_version |
Schema version string |
units |
Named list of assay units |
provenance |
Provenance structure ( |
software |
Software metadata (package name, version, R version) |
alignment |
Optional alignment metadata |
map_families |
Named list of registered map families |
mask_info |
Optional mask metadata |
contrast_info |
Optional contrast metadata |
design_mats |
Optional design matrices metadata |
notes |
Optional user notes |
created |
Timestamp for when the metadata was created |
Metadata list
Construct a lazy GDS plan
gds_plan(source, nodes = list(), meta = list())gds_plan(source, nodes = list(), meta = list())
source |
A |
nodes |
List of operation nodes |
meta |
Metadata list (planner bookkeeping) |
A plan object (gds_plan)
Define a plan source (adapter binding)
gds_source(adapter, source_spec, probe_result = NULL)gds_source(adapter, source_spec, probe_result = NULL)
adapter |
Adapter identifier string |
source_spec |
Source specification (paths, handles, etc.) |
probe_result |
Optional probe metadata |
Source descriptor
Public wrapper around the internal tidy frame builder used by CSV/Parquet
exporters. Returns a data.frame; if you prefer a tibble, wrap with
tibble::as_tibble().
gds_to_tibble(gds, assays = NULL, drop_na = FALSE, include_col_data = FALSE)gds_to_tibble(gds, assays = NULL, drop_na = FALSE, include_col_data = FALSE)
gds |
A realised GDS object |
assays |
Character vector of assay names to include (default: all assays in the GDS) |
drop_na |
If TRUE, drop rows with all-NA assays |
include_col_data |
If TRUE, join columns from |
A data.frame in long form with columns sample, subject,
contrast, plus one column per requested assay.
Retrieve a registered adapter
get_adapter(name)get_adapter(name)
name |
Adapter name |
Adapter list
Retrieve a registered map family by name
get_map_family(x, name)get_map_family(x, name)
x |
A plan or realised GDS |
name |
Map family name |
A MapFamily object
Get post-hoc method by name
get_posthoc(name)get_posthoc(name)
name |
Method identifier (e.g., "fdr:bh") |
A list with fields name, fun, requires, provides, or NULL if not found
Get reducer by name
get_reducer(name)get_reducer(name)
name |
Reducer name |
Reducer list or NULL if not found
These helpers wrap reduce(method = "ols:voxelwise") for subject-level map
workflows. They return a lazy GDS plan; call compute() to
materialise the fitted maps.
group_ols(x, formula = ~1, col_data = NULL, options = list(), ...) one_sample(x, subset = NULL, col_data = NULL, options = list(), ...) two_sample( x, group = "group", baseline = NULL, level = NULL, col_data = NULL, options = list(), ... )group_ols(x, formula = ~1, col_data = NULL, options = list(), ...) one_sample(x, subset = NULL, col_data = NULL, options = list(), ...) two_sample( x, group = "group", baseline = NULL, level = NULL, col_data = NULL, options = list(), ... )
x |
|
formula |
One-sided model formula for |
col_data |
Optional subject-level covariates to attach before fitting. |
options |
Reducer options passed to |
... |
Additional arguments passed to |
subset |
Optional expression evaluated in |
group |
Name of the grouping column in |
baseline |
Optional reference level for the grouping factor. |
level |
Optional non-baseline level to compare against |
A gds_plan with an OLS reduce node.
## Not run: fit <- group_ols(g, ~ group) |> compute() one <- one_sample(g) |> compute() two <- two_sample(g, group = "diagnosis", baseline = "control") |> compute() ## End(Not run)## Not run: fit <- group_ols(g, ~ group) |> compute() one <- one_sample(g) |> compute() two <- two_sample(g, group = "diagnosis", baseline = "control") |> compute() ## End(Not run)
Harmonise contrast names in a GDS
harmonise_contrasts(g, map)harmonise_contrasts(g, map)
g |
A realised GDS |
map |
Named character vector mapping old -> new contrast names |
Updated GDS with renamed contrasts
beta <- array(0, dim = c(2,1,2), dimnames = list(NULL, "s1", c("a","b"))) var <- beta g <- new_gds(list(beta = beta, var = var), space_sample_labels(c("x","y")), "s1", c("a","b")) harmonise_contrasts(g, c(a = "A", b = "B"))beta <- array(0, dim = c(2,1,2), dimnames = list(NULL, "s1", c("a","b"))) var <- beta g <- new_gds(list(beta = beta, var = var), space_sample_labels(c("x","y")), "s1", c("a","b")) harmonise_contrasts(g, c(a = "A", b = "B"))
Sweeps a directory tree for files matching a glob pattern and extracts metadata from file paths using regex capture groups.
image_catalog(root, pattern = "**/*.nii*", path_regex = NULL, recursive = TRUE)image_catalog(root, pattern = "**/*.nii*", path_regex = NULL, recursive = TRUE)
root |
Root directory to search. |
pattern |
Glob pattern for file discovery (e.g., |
path_regex |
Optional regex with named capture groups for metadata extraction.
Named groups like |
recursive |
Whether to search subdirectories. Default |
An image_catalog object.
## Not run: # Discover files with subject extraction catalog <- image_catalog( root = "study", pattern = "sub-*/analysis/*.nii.gz", path_regex = "sub-(?<subject>[^/]+)" ) ## End(Not run)## Not run: # Discover files with subject extraction catalog <- image_catalog( root = "study", pattern = "sub-*/analysis/*.nii.gz", path_regex = "sub-(?<subject>[^/]+)" ) ## End(Not run)
Merge a data frame with the catalog metadata by a key column.
join_meta(catalog, data, by, suffix = ".external")join_meta(catalog, data, by, suffix = ".external")
catalog |
An image_catalog object. |
data |
External data.frame to join. |
by |
Column name(s) for joining (must exist in both catalog$metadata and data). |
suffix |
Suffix for duplicate column names from data. Default |
Updated image_catalog.
## Not run: demographics <- data.frame(subject = c("01", "02"), age = c(25, 30)) catalog <- join_meta(catalog, demographics, by = "subject") ## End(Not run)## Not run: demographics <- data.frame(subject = c("01", "02"), age = c(25, 30)) catalog <- join_meta(catalog, demographics, by = "subject") ## End(Not run)
List registered map families
list_map_families(x)list_map_families(x)
x |
A plan or realised GDS |
Character vector of family names
List registered post-hoc methods
list_posthoc()list_posthoc()
Load a plan from JSON
load_plan(file)load_plan(file)
file |
JSON file produced by save_plan |
A gds_plan
Convenience helpers to create and register alignments
make_linear_family( name, from, to, operators_by_subject, uncertainty = UncertaintyRule("independent") )make_linear_family( name, from, to, operators_by_subject, uncertainty = UncertaintyRule("independent") )
name |
Family name |
from |
Source space |
to |
Target space |
operators_by_subject |
Named list of per-subject linear operators (matrices) |
uncertainty |
Uncertainty rule for variance propagation |
A MapFamily
from <- space_parcels(c("R1","R2")) to <- space_parcels(c("G1","G2")) ops <- list(s1 = diag(2), s2 = diag(2)) fam <- make_linear_family("lin", from, to, ops)from <- space_parcels(c("R1","R2")) to <- space_parcels(c("G1","G2")) ops <- list(s1 = diag(2), s2 = diag(2)) fam <- make_linear_family("lin", from, to, ops)
Create a warp-based alignment family from on-disk paths
make_warp_family( name, from, to, warp_paths, loader, uncertainty = UncertaintyRule("independent") )make_warp_family( name, from, to, warp_paths, loader, uncertainty = UncertaintyRule("independent") )
name |
Family name |
from |
Source space |
to |
Target space |
warp_paths |
Named character vector of file paths per subject |
loader |
Function(path) -> operator (e.g., matrix) for a single subject |
uncertainty |
Uncertainty rule |
A MapFamily (type = deform3d)
loader <- function(path) as.matrix(utils::read.csv(path, header = FALSE)) # paths <- c(s1 = "warp_s1.csv", s2 = "warp_s2.csv") # fam <- make_warp_family("warp", from, to, paths, loader)loader <- function(path) as.matrix(utils::read.csv(path, header = FALSE)) # paths <- c(s1 = "warp_s1.csv", s2 = "warp_s2.csv") # fam <- make_warp_family("warp", from, to, paths, loader)
Specify which files correspond to which statistical assays (beta, se, var, t).
This mapping is used by as_gds.image_catalog() to construct the GDS.
map_assays(catalog, ...)map_assays(catalog, ...)
catalog |
An image_catalog object. |
... |
Named arguments where names are assay types and values are either:
|
Updated image_catalog with assay_map.
## Not run: # By filename pattern catalog <- map_assays(catalog, beta = "cope[0-9]+\\.nii", se = "varcope[0-9]+\\.nii" ) # By metadata column value catalog <- map_assays(catalog, beta = list(stat_type = "cope"), se = list(stat_type = "varcope") ) ## End(Not run)## Not run: # By filename pattern catalog <- map_assays(catalog, beta = "cope[0-9]+\\.nii", se = "varcope[0-9]+\\.nii" ) # By metadata column value catalog <- map_assays(catalog, beta = list(stat_type = "cope"), se = list(stat_type = "varcope") ) ## End(Not run)
Create a linear map between spaces
map_linear( from_space, to_space, operator, by_subject = NULL, traits = list(orthogonal = FALSE, mass_preserving = FALSE), uncertainty = UncertaintyRule("independent"), name = NULL )map_linear( from_space, to_space, operator, by_subject = NULL, traits = list(orthogonal = FALSE, mass_preserving = FALSE), uncertainty = UncertaintyRule("independent"), name = NULL )
from_space |
Source space descriptor or name |
to_space |
Target space descriptor or name |
operator |
Mapping operator (matrix/function) |
by_subject |
Optional named list of subject-specific operator descriptors/functions |
traits |
List of map traits (orthogonal, mass_preserving) |
uncertainty |
|
name |
Optional map name |
Object of class c("map_linear", "gds_map")
Add a space transformation to a plan
map_to( x, target_space, map, uncertainty = UncertaintyRule("independent"), combine = NULL )map_to( x, target_space, map, uncertainty = UncertaintyRule("independent"), combine = NULL )
x |
Plan, source, or realised GDS |
target_space |
Target space descriptor or identifier |
map |
Mapping object ( |
uncertainty |
|
combine |
Optional evidence combiner when effect scale absent |
Updated plan
Eagerly apply space transformation and compute immediately
map_to_eager(x, ...)map_to_eager(x, ...)
x |
Plan, source, or realized GDS |
... |
Arguments passed to map_to(), then compute() |
A realized GDS object
Create a subject-aware map family
MapFamily( name, from_space, to_space, type = c("linear", "orthogonal", "affine3d", "deform3d", "ot"), by_subject, traits = list(orthogonal = FALSE, mass_preserving = FALSE), uncertainty = UncertaintyRule("independent") )MapFamily( name, from_space, to_space, type = c("linear", "orthogonal", "affine3d", "deform3d", "ot"), by_subject, traits = list(orthogonal = FALSE, mass_preserving = FALSE), uncertainty = UncertaintyRule("independent") )
name |
Family name |
from_space |
Source space |
to_space |
Target space |
type |
Map type identifier |
by_subject |
Named list of per-subject operator descriptors |
traits |
Map traits |
uncertainty |
Object of class c("gds_map_family", "gds_map")
Apply a mask policy lazily
mask(x, policy = MaskPolicy())mask(x, policy = MaskPolicy())
x |
Plan, source, or realised GDS |
policy |
Mask policy created by |
Updated plan
Eagerly apply mask policy and compute immediately
mask_eager(x, ...)mask_eager(x, ...)
x |
Plan, source, or realized GDS |
... |
Arguments passed to mask(), then compute() |
A realized GDS object
Define a mask policy
MaskPolicy( scope = c("group", "subject"), rule = c("intersection", "union", "threshold", "custom"), threshold = 0.95, custom = NULL )MaskPolicy( scope = c("group", "subject"), rule = c("intersection", "union", "threshold", "custom"), threshold = 0.95, custom = NULL )
scope |
Scope of mask computation ("group" or "subject") |
rule |
Mask rule ("intersection", "union", "threshold", "custom") |
threshold |
Fraction for threshold rule |
custom |
Custom function returning logical mask |
A mask policy object
Extract metadata from a GDS object
metadata(x)metadata(x)
x |
A GDS object |
Metadata list
Convenience helper to construct a model matrix using subject-level
covariates already attached to a plan via with_col_data() or stored in a
realised GDS.
model_matrix(x, formula)model_matrix(x, formula)
x |
A |
formula |
Model formula (or string convertible via stats::as.formula) |
A numeric model matrix
Low-level constructor for image_catalog objects. Users should typically
use image_catalog() for file discovery instead.
new_image_catalog( files, metadata = NULL, root_dir = NULL, pattern = NULL, assay_map = list() )new_image_catalog( files, metadata = NULL, root_dir = NULL, pattern = NULL, assay_map = list() )
files |
Character vector of absolute file paths. |
metadata |
Data frame with one row per file containing extracted path components and user-assigned metadata. |
root_dir |
Root directory used for discovery (for relative path display). |
pattern |
Original glob pattern used for discovery. |
assay_map |
Named list mapping assay names to file selection criteria. |
An object of class c("image_catalog", "list").
Build an explicit NIfTI source list for use with gds(..., format = "nifti").
If beta is provided without se, materialising the GDS creates a unit
variance placeholder with a warning. This supports raw beta/stat-map
workflows; the synthetic variance should not be interpreted as subject-level
uncertainty.
nifti_source(beta = NULL, se = NULL)nifti_source(beta = NULL, se = NULL)
beta |
Character vector of NIfTI paths or a directory containing beta/effect images
(optional, can be |
se |
Character vector of NIfTI paths or a directory containing standard error images
(optional, can be |
A list suitable for gds(source = <returned>, format = "nifti")
src <- nifti_source(beta = c("sub-01_beta.nii.gz", "sub-02_beta.nii.gz"), se = c("sub-01_se.nii.gz", "sub-02_se.nii.gz")) str(src)src <- nifti_source(beta = c("sub-01_beta.nii.gz", "sub-02_beta.nii.gz"), se = c("sub-01_se.nii.gz", "sub-02_se.nii.gz")) str(src)
Create an align-to-group operation node
op_align_to_group(family = NULL, family_name = NULL)op_align_to_group(family = NULL, family_name = NULL)
family |
MapFamily object for alignment |
family_name |
Name of registered map family |
Operation node list
Create a derive operation node
op_derive(what, options = list())op_derive(what, options = list())
what |
Character vector of statistics to derive (e.g., "t", "z", "p") |
options |
Optional list of derivation options |
Operation node list
Create a map operation node
op_map(target_space, map, uncertainty, combine = NULL)op_map(target_space, map, uncertainty, combine = NULL)
target_space |
Target space descriptor |
map |
Mapping operator (matrix or function) |
uncertainty |
UncertaintyRule for variance propagation |
combine |
Optional combine method |
Operation node list
Create a mask policy operation node
op_mask_policy(policy)op_mask_policy(policy)
policy |
MaskPolicy object |
Operation node list
Create a reduce operation node
op_reduce(method, weights, by, options = list(), formula = NULL)op_reduce(method, weights, by, options = list(), formula = NULL)
method |
Reduction method (e.g., "fixed", "random") |
weights |
Optional weight vector or method |
by |
Optional grouping variable |
options |
Optional reduction options |
formula |
Optional model formula for meta-regression |
Operation node list
Create a subset operation node
op_subset_axis(sample = NULL, subject = NULL, contrast = NULL)op_subset_axis(sample = NULL, subject = NULL, contrast = NULL)
sample |
Sample indices or labels |
subject |
Subject indices or IDs |
contrast |
Contrast indices or names |
Operation node list
Create a write operation node
op_write(path, format, options = list())op_write(path, format, options = list())
path |
Output file path |
format |
Output format (e.g., "h5", "csv", "parquet") |
options |
Optional format-specific options |
Operation node list
Orthogonal map family helper
OrthogonalFamily( name, from_space, to_space, matrices_by_subject, uncertainty = UncertaintyRule("independent") )OrthogonalFamily( name, from_space, to_space, matrices_by_subject, uncertainty = UncertaintyRule("independent") )
name |
Family name |
from_space |
Source space |
to_space |
Target space |
matrices_by_subject |
Named list of per-subject orthogonal matrices |
uncertainty |
Uncertainty rule (default: independent) |
A MapFamily object with orthogonal traits
Optimal transport family helper
OTFamily( name, from_space, to_space, plans_by_subject, uncertainty = UncertaintyRule("independent") )OTFamily( name, from_space, to_space, plans_by_subject, uncertainty = UncertaintyRule("independent") )
name |
Family name |
from_space |
Source space |
to_space |
Target space |
plans_by_subject |
Named list of per-subject optimal transport plans |
uncertainty |
Uncertainty rule (default: independent) |
A MapFamily object with mass-preserving traits
Alias for as_plan() to improve ergonomics when converting realized GDS
objects or sources into a gds_plan.
plan(x)plan(x)
x |
A |
A gds_plan
Add a post-hoc operation to a plan
posthoc(x, method, options = list())posthoc(x, method, options = list())
x |
A plan or object coercible via |
method |
Post-hoc method name (e.g., "fdr:bh", "fdr:by") |
options |
Optional list of method-specific options |
Updated gds_plan
df <- data.frame( sample = rep(c("ROI_1","ROI_2"), each = 2), subject = rep(c("s1","s2"), times = 2), contrast = "c1", beta = c(0.5,0.6,0.7,0.8), var = c(0.04,0.05,0.06,0.07) ) tmp <- tempfile(fileext = ".csv"); utils::write.csv(df, tmp, row.names = FALSE) plan <- gds(tmp) |> reduce(method = "fixed") |> posthoc("fdr:bh") # g <- compute(plan) # returns q-valuesdf <- data.frame( sample = rep(c("ROI_1","ROI_2"), each = 2), subject = rep(c("s1","s2"), times = 2), contrast = "c1", beta = c(0.5,0.6,0.7,0.8), var = c(0.04,0.05,0.06,0.07) ) tmp <- tempfile(fileext = ".csv"); utils::write.csv(df, tmp, row.names = FALSE) plan <- gds(tmp) |> reduce(method = "fixed") |> posthoc("fdr:bh") # g <- compute(plan) # returns q-values
Executes the plan with a small sample block to quickly inspect shapes or
values. If assays is provided, returns raw arrays from the adapter stage
(pre-operations); otherwise returns a realised GDS of the small block after
applying plan nodes.
preview(plan, n = 3, assays = NULL)preview(plan, n = 3, assays = NULL)
plan |
A |
n |
Number of samples to preview (from start) |
assays |
Optional assays to request as raw arrays |
Either a list of arrays (when assays provided) or a small gds
Print validation report
## S3 method for class 'catalog_validation_report' print(x, ...)## S3 method for class 'catalog_validation_report' print(x, ...)
x |
A catalog_validation_report object. |
... |
Additional arguments (ignored). |
Invisibly returns the report.
Print method for image_catalog
## S3 method for class 'image_catalog' print(x, ...)## S3 method for class 'image_catalog' print(x, ...)
x |
An image_catalog object. |
... |
Additional arguments (ignored). |
Invisibly returns the catalog.
Create a provenance node
provenance_node( op_name, params, inputs = list(), timestamp = Sys.time(), software = list(package = "fmrigds", version = .pkg_version()), hash = NULL )provenance_node( op_name, params, inputs = list(), timestamp = Sys.time(), software = list(package = "fmrigds", version = .pkg_version()), hash = NULL )
op_name |
Operation name |
params |
Named list of parameters |
inputs |
Vector/list of parent hashes/ids |
timestamp |
Timestamp of operation |
software |
Software metadata |
hash |
Optional pre-computed hash |
A provenance node list
Load an image catalog previously saved with write_catalog().
read_catalog(file)read_catalog(file)
file |
Path to catalog JSON file. |
An image_catalog object.
## Not run: catalog <- read_catalog("my_study_manifest.json") ## End(Not run)## Not run: catalog <- read_catalog("my_study_manifest.json") ## End(Not run)
Reduce across subjects (meta-analysis)
reduce( x, method = c("fixed", "random", "stouffer", "fisher"), weights = c("1/var", "n_eff", "equal", "custom"), by = "contrast", options = list(), formula = NULL, data = NULL )reduce( x, method = c("fixed", "random", "stouffer", "fisher"), weights = c("1/var", "n_eff", "equal", "custom"), by = "contrast", options = list(), formula = NULL, data = NULL )
x |
A |
method |
Reduction method. Built-ins include |
weights |
Weighting scheme ( |
by |
Grouping variable (e.g., |
options |
Additional reducer options. Common examples include
Note: Current grouping is per-contrast. Values other than "contrast" are
not interpreted yet; future versions may extend grouping to other
factors in Restricted repeated-measures LMM contract:
Permutation reducer contract:
|
formula |
Optional model formula. For meta-regression reducers the design
is built from subject-level |
data |
Optional data frame for building |
reduce() always works on a lazy plan internally, so x is whichever stage
of the fmrigds workflow you already have:
Start from files or another external source with gds(). That returns a
gds_plan you can pipe directly into reduce().
Start from an in-memory result with a realised gds returned by
compute() or created directly with new_gds(). reduce() will convert
it with as_plan() for you.
You can also pass a low-level gds_source created by gds_source(), but
most users do not need this because gds() creates the source binding
automatically.
If you want that conversion to be explicit, use as_plan() or its alias
plan() before calling reduce().
For worked examples, see vignette("fmrigds") for the basic source -> plan
-> compute workflow and vignette("as-plan-and-spatial-fdr") for chaining
verbs on realised GDS objects.
Updated plan
gds(), compute(), as_plan(), plan(), new_gds(), gds_source()
Eagerly reduce across subjects and compute immediately
reduce_eager(x, ...)reduce_eager(x, ...)
x |
Plan, source, or realized GDS |
... |
Arguments passed to reduce(), then compute() |
A realized GDS object
fmrigds includes two specialized repeated-measures Gaussian mixed-model
reducers that are optimized for the case where every sample shares the same
observation layout and the same fixed/random design.
method = "lmm:ri" fits a random-intercept model.
method = "lmm:ri_slope1" fits a random intercept plus one within-subject
slope supplied through options$slope.
These reducers operate on the full contrast axis jointly. Repeated-measure
metadata therefore needs to be attached as contrast-level metadata, either
with with_contrast_data() or during tabular ingestion via
gds(..., contrast_data_cols = ...).
Supported contract:
one grouping factor only
Gaussian outcomes only
shared observation layout and shared fixed/random design across samples
theta_mode = "pooled" for one shared variance structure across samples
theta_mode = "voxelwise" for sample-specific variance parameters
no crossed random effects and no general lmer() random-effects grammar
Output assays follow the same naming conventions as the regression reducers:
coef:<term>, se_coef:<term>, t_coef:<term>, p_coef:<term>, plus
variance-component assays such as sigma2, vc_intercept, vc_slope,
lambda_intercept, and lambda_slope.
rm_df <- data.frame(
sample = rep(c("ROI_1", "ROI_2"), each = 12),
subject = rep(paste0("sub-", sprintf("%02d", 1:4)), each = 3, times = 2),
contrast = rep(c("pre", "mid", "post"), times = 8),
time = rep(c(-1, 0, 1), times = 8),
beta = c(
0.40, 0.80, 1.20, 0.55, 0.95, 1.35, 0.65, 1.05, 1.45, 0.85, 1.25, 1.65,
0.70, 1.20, 1.70, 0.85, 1.35, 1.85, 0.95, 1.45, 1.95, 1.15, 1.65, 2.15
),
var = 0.04
)
g <- gds(rm_df, 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(g))
assay(g, "coef:time")
The reducer identified by method = "ols:voxelwise" performs unweighted
ordinary least squares across subjects independently for each sample and
contrast. It accepts a model formula via reduce(..., formula = ~ 1 + cov)
(design is built from with_col_data() or gds(..., col_data=...)).
Outputs are expanded into per-term assays to preserve the 3-axis invariant:
coef:<term> and se_coef:<term> (one assay per model term)
t_coef:<term> and p_coef:<term> convenience statistics
sigma2 (residual variance) and df_res (residual degrees of freedom)
Optionally, a packed triangular covariance for the coefficient vector can be
attached per contrast using options = list(return_cov = "tri"). Retrieve
it from a realised GDS via coef_cov_tri().
# Attach subject-level covariates; build design via formula
plan <- gds("group.csv", col_data = subj_cov) |
reduce(method = "ols:voxelwise", formula = ~ 1 + age + sex,
options = list(return_cov = "tri"))
g <- compute(plan)
# Per-term assays
assay(g, "coef:(Intercept)"); assay(g, "coef:age"); assay(g, "coef:sex")
# Packed covariance for first contrast
cov_info <- coef_cov_tri(g, contrast = contrasts(g)[1])
cov_info$terms # term order
cov_info$cov_tri # L x samples packed upper triangle
# Stack all coefficients into [samples x terms x contrasts]
coef_arr <- coef_array(g)
Register a storage adapter
register_adapter(name, detect, open, probe, read, close, ...)register_adapter(name, detect, open, probe, read, close, ...)
name |
Adapter name |
detect |
Function (source) -> score in |
open |
Function (source, ...) -> handle |
probe |
Function (handle, ...) -> list(metadata) |
read |
Function (handle, assays, block = NULL, ...) -> named list of arrays |
close |
Function (handle) -> NULL |
... |
Additional elements stored with adapter entry |
Invisibly, the adapter entry
Register an assay type
register_assay( name, role, units = NULL, variance_of = NULL, derive_from = NULL )register_assay( name, role, units = NULL, variance_of = NULL, derive_from = NULL )
name |
Assay name |
role |
Semantic category (e.g., "location", "variance", "stdev", "z", "t", "F", "df", "n_eff", "p", "chi2", "evidence", "log_evidence", "posterior") |
units |
Optional units string/list |
variance_of |
Optional name of the assay whose variance this represents |
derive_from |
Optional character vector of prerequisite assays |
Invisibly, the registered assay definition
Register a map family on a plan or realised GDS
register_map(x, family, overwrite = FALSE)register_map(x, family, overwrite = FALSE)
x |
|
family |
A |
overwrite |
Whether to overwrite an existing family with the same name |
Updated object (gds_plan or gds)
Makes nftab objects from the neurotabs package a first-class
data source for gds(). Called automatically during
.onLoad() when neurotabs is installed; can also be called
manually.
register_nftab_adapter()register_nftab_adapter()
Invisibly, the adapter entry.
Register or replace a post-hoc handler identified by name.
register_posthoc(name, fun, requires, provides, overwrite = TRUE)register_posthoc(name, fun, requires, provides, overwrite = TRUE)
name |
String identifier, e.g., "fdr:bh" |
fun |
Function(arrays, opts) -> list of arrays (delta or full arrays) |
requires |
Character vector of required input assays, e.g., c("p") |
provides |
Character vector of output assay names, e.g., c("q") |
overwrite |
Logical; if FALSE and a handler with |
The handler fun is called as fun(arrays, opts) where arrays is a
named list of assays shaped sample x subject x contrast. It should return
either (a) a named list of new/updated assays to merge (e.g., list(q = ...)),
or (b) the full arrays list with modifications. Implementations must
preserve the input array dimensions.
Register a reducer kernel
register_reducer( name, fun, requires, provides, options_schema = list(), input_shape = c("contrastwise", "joint_contrast") )register_reducer( name, fun, requires, provides, options_schema = list(), input_shape = c("contrastwise", "joint_contrast") )
name |
String identifier, e.g., "meta:fe" |
fun |
Function(beta, var, X, z, p, df, df1, df2, opts) -> named list |
requires |
Character vector of required inputs, e.g., c("beta","var") |
provides |
Character vector of outputs to be written |
options_schema |
Optional schema for options |
input_shape |
Reducer execution mode: |
Relabel subjects in a GDS
relabel_subjects(g, mapping)relabel_subjects(g, mapping)
g |
A realised GDS |
mapping |
Named character vector mapping old -> new subject ids |
Updated GDS with relabeled subjects
beta <- array(0, dim = c(2,2,1), dimnames = list(NULL, c("u1","u2"), "c1")) var <- beta g <- new_gds(list(beta = beta, var = var), space_sample_labels(c("x","y")), c("u1","u2"), "c1") relabel_subjects(g, c(u1 = "s1", u2 = "s2"))beta <- array(0, dim = c(2,2,1), dimnames = list(NULL, c("u1","u2"), "c1")) var <- beta g <- new_gds(list(beta = beta, var = var), space_sample_labels(c("x","y")), c("u1","u2"), "c1") relabel_subjects(g, c(u1 = "s1", u2 = "s2"))
Extract row (sample) metadata from a GDS object
row_data(x)row_data(x)
x |
A GDS object |
Data frame with sample-level metadata
Extract sample-group metadata from a GDS object
sample_groups( x, vars = c("feature_group", "spatial_group", "group", "parcel", "parcel_id") )sample_groups( x, vars = c("feature_group", "spatial_group", "group", "parcel", "parcel_id") )
x |
A GDS object or plan |
vars |
Candidate column names searched in |
A vector of group labels or NULL when unavailable
Extract sample labels from a GDS object
sample_labels(x)sample_labels(x)
x |
A GDS object or plan |
Character vector of sample labels
Save a plan to JSON
save_plan(plan, file)save_plan(plan, file)
plan |
Plan or object coercible via |
file |
Path to JSON file |
Extract space descriptor from a GDS object
space(x)space(x)
x |
A GDS object |
A space object
Create a latent basis space descriptor
space_basis(k, basis_name = NULL, projector = NULL, voxel_space = NULL)space_basis(k, basis_name = NULL, projector = NULL, voxel_space = NULL)
k |
Number of components |
basis_name |
Optional name for the basis (e.g., "ICA") |
projector |
Optional matrix/function for voxel projection |
voxel_space |
Optional reference voxel space descriptor |
Space object
Create a voxel space from a NIfTI file
space_from_nifti(path, mask = NULL)space_from_nifti(path, mask = NULL)
path |
Path to a NIfTI file (.nii or .nii.gz) |
mask |
Optional path to a mask NIfTI or a neuroim2::NeuroVol |
A space_voxel object
# if (requireNamespace("neuroim2", quietly = TRUE)) { # sp <- space_from_nifti(system.file("extdata", "tiny.nii", package = "fmrigds")) # }# if (requireNamespace("neuroim2", quietly = TRUE)) { # sp <- space_from_nifti(system.file("extdata", "tiny.nii", package = "fmrigds")) # }
Create a parcels/ROI space descriptor
space_parcels(labels, lookup = NULL, membership = NULL)space_parcels(labels, lookup = NULL, membership = NULL)
labels |
Character vector of parcel labels |
lookup |
Optional lookup information (data frame or list) |
membership |
Optional mapping (list or sparse matrix) from parcels to voxels |
Space object
Create a simple label space for tabular samples
space_sample_labels(labels)space_sample_labels(labels)
labels |
Character vector of sample labels |
Space object of type "sample_labels"
Subset a space by sample indices
space_subset(space, idx, pack = FALSE)space_subset(space, idx, pack = FALSE)
space |
A |
idx |
Integer or logical index for the sample axis |
pack |
Logical; when TRUE and |
A new space object with samples restricted
sp <- space_parcels(letters[1:5]) space_subset(sp, 2:4)sp <- space_parcels(letters[1:5]) space_subset(sp, 2:4)
Create a surface space descriptor
space_surface(vertices, faces, hemi, template_id = NULL)space_surface(vertices, faces, hemi, template_id = NULL)
vertices |
Matrix (n x 3) of vertex coordinates |
faces |
Integer matrix (m x 3) of triangle indices (1-based) |
hemi |
Hemisphere identifier ("L", "R", "LR") |
template_id |
Optional template identifier |
Space object
Create a voxel space descriptor
Alias for space_voxel
space_voxel( dim, affine, mask_bitmap = NULL, mask_idx = NULL, storage = c("dense", "packed"), template_id = NULL ) space_voxels( dim, affine, mask_bitmap = NULL, mask_idx = NULL, storage = c("dense", "packed"), template_id = NULL )space_voxel( dim, affine, mask_bitmap = NULL, mask_idx = NULL, storage = c("dense", "packed"), template_id = NULL ) space_voxels( dim, affine, mask_bitmap = NULL, mask_idx = NULL, storage = c("dense", "packed"), template_id = NULL )
dim |
Integer vector of length 3 (x, y, z) |
affine |
4x4 affine matrix |
mask_bitmap |
Optional logical array matching |
mask_idx |
Optional integer vector of active voxel indices (mask order) |
storage |
Either "dense" or "packed" |
template_id |
Optional template identifier string |
An object of class c("space_voxel", "gds_space")
Divide a GDS object into a list of GDS objects based on a grouping factor
from col_data (subject-level metadata).
## S3 method for class 'gds' split(x, f, drop = TRUE, ...)## S3 method for class 'gds' split(x, f, drop = TRUE, ...)
x |
A GDS object. |
f |
A factor or character vector for splitting, OR a column name
(as a string) from |
drop |
Logical; if |
... |
Additional arguments (ignored). |
A named list of GDS objects, one per level of f.
## Not run: # Split by group column in col_data gds_by_group <- split(gds, "group") gds_by_group$patients # GDS with only patient subjects gds_by_group$controls # GDS with only control subjects # Or provide a factor directly groups <- factor(c("A", "B", "A", "B")) gds_split <- split(gds, groups) ## End(Not run)## Not run: # Split by group column in col_data gds_by_group <- split(gds, "group") gds_by_group$patients # GDS with only patient subjects gds_by_group$controls # GDS with only control subjects # Or provide a factor directly groups <- factor(c("A", "B", "A", "B")) gds_split <- split(gds, groups) ## End(Not run)
Extract subject identifiers from a GDS object
subjects(x)subjects(x)
x |
A GDS object |
Character vector of subject IDs
Eagerly subset a GDS and compute immediately
subset_eager(...)subset_eager(...)
... |
Arguments passed to subset(), then compute() |
A realized GDS object
Filter catalog files based on metadata conditions.
## S3 method for class 'image_catalog' subset(x, subset, ...)## S3 method for class 'image_catalog' subset(x, subset, ...)
x |
An image_catalog object. |
subset |
Logical expression evaluated in the context of metadata columns. |
... |
Additional arguments (ignored). |
A filtered image_catalog.
## Not run: # Keep only files from subject "01" sub_catalog <- subset(catalog, subject == "01") # Multiple conditions sub_catalog <- subset(catalog, subject %in% c("01", "02") & run == "1") ## End(Not run)## Not run: # Keep only files from subject "01" sub_catalog <- subset(catalog, subject == "01") # Multiple conditions sub_catalog <- subset(catalog, subject %in% c("01", "02") & run == "1") ## End(Not run)
Summary method for image_catalog
## S3 method for class 'image_catalog' summary(object, ...)## S3 method for class 'image_catalog' summary(object, ...)
object |
An image_catalog object. |
... |
Additional arguments (ignored). |
Invisibly returns the catalog.
Specify how uncertainty is propagated through a map
UncertaintyRule( mode = c("independent", "cov_provider", "kernel", "none"), df_rule = c("satterthwaite", "none"), cov_provider = NULL, kernel = NULL )UncertaintyRule( mode = c("independent", "cov_provider", "kernel", "none"), df_rule = c("satterthwaite", "none"), cov_provider = NULL, kernel = NULL )
mode |
One of "independent", "cov_provider", "kernel", "none" |
df_rule |
Degrees of freedom aggregation rule |
cov_provider |
Optional covariance provider function |
kernel |
Optional kernel function |
Uncertainty rule descriptor
Get unique values of a metadata column
## S3 method for class 'image_catalog' unique(x, incomparables = FALSE, column = "subject", ...)## S3 method for class 'image_catalog' unique(x, incomparables = FALSE, column = "subject", ...)
x |
An image_catalog object. |
incomparables |
Passed to base unique (ignored for catalog method). |
column |
Name of metadata column to get unique values from. |
... |
Additional arguments (ignored). |
Unique values from the specified column.
Unregister a post-hoc method
unregister_posthoc(name)unregister_posthoc(name)
name |
Method identifier to remove |
Invisibly, TRUE if removed, FALSE if not found
Convenience helper to use a stored weight array for reduction
use_weight(g, name)use_weight(g, name)
g |
A realised GDS containing the weight assay |
name |
Assay name to use as custom weights |
A list(list) suitable to splice into reduce():
list(weights = "custom", options = list(custom_weights =
# opts <- use_weight(g2, "w_custom")# opts <- use_weight(g2, "w_custom")
Validate a GDS or plan
validate(x, ...)validate(x, ...)
x |
A |
... |
Additional arguments passed to methods |
TRUE if valid; otherwise errors with a descriptive message
Check that the catalog has consistent file coverage across subjects and report any missing or extra files.
## S3 method for class 'image_catalog' validate(x, by = "subject", expect = NULL, ...)## S3 method for class 'image_catalog' validate(x, by = "subject", expect = NULL, ...)
x |
An image_catalog object. |
by |
Column name to group by for consistency check. Default |
expect |
Optional character vector of expected file basenames per subject. |
... |
Additional arguments (ignored). |
A catalog_validation_report object.
## Not run: report <- validate(catalog) print(report) report <- validate(catalog, expect = c("cope1.nii.gz", "varcope1.nii.gz")) ## End(Not run)## Not run: report <- validate(catalog) print(report) report <- validate(catalog, expect = c("cope1.nii.gz", "varcope1.nii.gz")) ## End(Not run)
Deformable warp family helper
WarpFamily( name, from_space, to_space, warps_by_subject, uncertainty = UncertaintyRule("independent") )WarpFamily( name, from_space, to_space, warps_by_subject, uncertainty = UncertaintyRule("independent") )
name |
Family name |
from_space |
Source space |
to_space |
Target space |
warps_by_subject |
Named list of per-subject deformation fields |
uncertainty |
Uncertainty rule (default: independent) |
A MapFamily object for deformable warps
Attach subject-level covariates to a plan or GDS
with_col_data(x, col_data)with_col_data(x, col_data)
x |
Plan, source, or realised GDS |
col_data |
Data frame keyed by subject identifiers (rownames) |
A gds_plan (for plans/sources) or a gds (for realised objects)
Attach contrast-level metadata to a plan or GDS
with_contrast_data(x, contrast_data)with_contrast_data(x, contrast_data)
x |
Plan, source, or realised GDS |
contrast_data |
Data frame keyed by contrast identifiers (rownames) |
A gds_plan (for plans/sources) or a gds (for realised objects)
Attach sample-level metadata to a plan or GDS
with_row_data(x, row_data)with_row_data(x, row_data)
x |
Plan, source, or realised GDS |
row_data |
Data frame keyed by sample identifiers (rownames) when available |
A gds_plan (for plans/sources) or a gds (for realised objects)
Save an image catalog to a JSON file for later retrieval with read_catalog().
write_catalog(catalog, file)write_catalog(catalog, file)
catalog |
An image_catalog object. |
file |
Output file path (should end in |
Invisibly returns the file path.
## Not run: write_catalog(catalog, "my_study_manifest.json") ## End(Not run)## Not run: write_catalog(catalog, "my_study_manifest.json") ## End(Not run)
Writes each selected assay/subject/contrast image in a voxel-space GDS to a
separate NIfTI file and returns a manifest describing written and skipped
outputs. This is intended for model outputs such as coef:*, t_coef:*,
and p_coef:* assays.
write_nifti_assays( g, out_dir, prefix = NULL, assays = NULL, subjects = NULL, contrasts = NULL, sanitize = TRUE, overwrite = FALSE )write_nifti_assays( g, out_dir, prefix = NULL, assays = NULL, subjects = NULL, contrasts = NULL, sanitize = TRUE, overwrite = FALSE )
g |
A realised |
out_dir |
Output directory. |
prefix |
Optional filename prefix. |
assays |
Character vector of assays to write. Defaults to all assays. |
subjects |
Optional subject labels to write. Defaults to all subjects. |
contrasts |
Optional contrast labels to write. Defaults to all contrasts. |
sanitize |
Logical; if |
overwrite |
Logical; if |
A data.frame manifest with assay, subject, contrast, path,
written, and skipped_reason columns.
## Not run: fit <- group_ols(g, ~ group) |> compute() manifest <- write_nifti_assays(fit, "group_maps", prefix = "auc") ## End(Not run)## Not run: fit <- group_ols(g, ~ group) |> compute() manifest <- write_nifti_assays(fit, "group_maps", prefix = "auc") ## End(Not run)
Adds a lazy write operation to the plan. Data are only written when
compute() executes.
write_out( x, path, format = c("h5", "csv", "parquet", "nifti"), options = list() )write_out( x, path, format = c("h5", "csv", "parquet", "nifti"), options = list() )
x |
A plan or object coercible via |
path |
Output file path |
format |
Output format ( |
options |
Optional list of format-specific options |
Updated plan with a write node appended