Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

modeling

modeling

BrainData modeling functions.

Standalone functions extracted from BrainData class methods for model fitting, GLM estimation, Ridge regression, and contrast computation.

Attributes:

NameTypeDescription
NEAR_COLLINEAR_CONDITION_THRESHOLD
NEAR_COLLINEAR_CORR_THRESHOLD

Classes:

NameDescription
NearCollinearDesignWarningThe design matrix supplied to fit() is full rank but nearly collinear.
RankDeficientDesignWarningThe design matrix supplied to fit() is rank deficient.

Methods:

NameDescription
compute_contrastsCompute contrasts from a fitted GLM.
compute_ridge_cvHeld-out CV scores under a fixed Ridge α.
fitFit a model to brain imaging data.
fit_glmFit GLM model and extract results.
fit_ridgeFit Ridge model and extract results.
parse_contrast_stringParse a contrast string into a numeric contrast vector.
resolve_preprocessing_defaultsResolve the 'auto' scale/standardize sentinels to concrete values.
to_fit_dataclassConvert BrainData fit results to Fit dataclass.
ttestOne-sample voxelwise t-test across images (axis 0).
ttest2Two-sample voxelwise t-test between two BrainData stacks.

Classes

NearCollinearDesignWarning

Bases: UserWarning

The design matrix supplied to fit() is full rank but nearly collinear.

Subclasses UserWarning so it participates in default filtering, while remaining individually silenceable: warnings.filterwarnings("ignore", category=NearCollinearDesignWarning).

RankDeficientDesignWarning

Bases: UserWarning

The design matrix supplied to fit() is rank deficient.

Subclasses UserWarning so it participates in default filtering, while remaining individually silenceable: warnings.filterwarnings("ignore", category=RankDeficientDesignWarning).

Methods

compute_contrasts

compute_contrasts(bd, contrasts, statistic = 't')

Compute contrasts from a fitted GLM.

Uses nilearn’s functional compute_contrast on the fitted (labels_, results_) so t-statistics are computed with the full per-voxel parameter covariance (correct for OLS and AR) — a linear combination of stored betas cannot do this for multi-regressor contrasts (it would ignore off-diagonal covariance and produce an effect-size map, not a t-map). Contrast maps stay in masked-array space; no unmasking to a Nifti.

Must be called after .fit(model='glm', X=design_matrix) has been run.

Parameters:

NameTypeDescriptionDefault
bdBrainData instance.required
contrastsCan be:
- str: a contrast expressed in terms of column names, e.g. "conditionA - conditionB" or "2*conditionA - conditionB - conditionC" - array-like: a numeric contrast vector, one weight per regressor (e.g. [1, -1, 0, 0]) - dict: {name: contrast} for multiple contrasts at once
required
statisticstrWhich statistic to return per contrast. One of:
- "t" (default): t-statistic map (for thresholding / single-subject inference) - "z": z-score map - "p": p-value map. Note: contrast p-values are one-sided (the nilearn/SPM directional-contrast convention — a contrast tests “A > B”; flip the contrast for the other direction). This is the documented exception to the library’s two-tailed default. - "beta" / "effect_size": effect-size (β) map — use this when feeding into a second-level (group) analysis - "all": a bundle dict {"beta", "t", "z", "p", "se"} of BrainData maps for this one contrast. One fit, one call, every view — effect size and inferential maps together so group-level code never has to recompute beta separately.
‘t’

Returns:

TypeDescription
Depends on inputs:
- single contrast (str or array) + scalar statistic: a single BrainData. - single contrast + statistic="all": a flat dict of five BrainData keyed by "beta"/"t"/"z"/"p"/"se". - dict of contrasts + scalar statistic: a dict {name: BrainData}. - dict of contrasts + statistic="all": a nested dict {name: {"beta", "t", "z", "p", "se"}}.

Examples:

>>> data.fit(model="glm", X=dm)
>>> # Single-subject t-map, ready to threshold
>>> tmap = data.compute_contrasts("conditionA - conditionB")
>>> # Effect-size map for use as input to a group-level analysis
>>> beta = data.compute_contrasts(
...     "conditionA - conditionB", statistic="beta"
... )
>>> # Everything at once: threshold on res["t"], feed group on res["beta"]
>>> res = data.compute_contrasts(
...     "conditionA - conditionB", statistic="all"
... )
>>> res["t"].plot(threshold=3.09)
>>> group_effects.append(res["beta"])
Note
  • String contrasts support coefficients: "2*A - B" or "0.5*A + 0.5*B".

  • Column names must match design matrix columns exactly (case-sensitive).

  • For group analysis, stack per-subject effect-size maps (statistic="beta" or res["beta"] from statistic="all") and run a second-level test (e.g. BrainData.ttest). Mixing first-level t-maps into a group one-sample test conflates effect magnitude with precision.

compute_ridge_cv

compute_ridge_cv(bd, X, cv, alpha = None, device = 'cpu')

Held-out CV scores under a fixed Ridge α.

Used only for the fixed-α + CV branch — alpha selection is now handled by Ridge.fit (which delegates to solve_ridge_cv) and assembled into cv_results_ by _assemble_ridge_cv_results.

Parameters:

NameTypeDescriptionDefault
bdBrainData instance.required
XndarrayTraining features, shape (n_samples, n_features).required
cvint or sklearn CV splitterCross-validation specification.required
alphafloatFixed regularization strength. If None, extracted from bd.model_.alpha.None
devicestrCompute device (‘cpu’/‘gpu’/‘auto’). Default: ‘cpu’.‘cpu’

Returns:

NameTypeDescription
dict{"scores", "mean_score", "predictions", "folds"}.

fit

fit(bd, model = 'glm', *, X = None, cv = None, device = 'cpu', local_alpha = True, fit_intercept = False, inplace = True, progress_bar = False, scale = 'auto', standardize = 'auto', **kwargs)

Fit a model to brain imaging data.

Creates and fits a model from string specification. The brain data (bd.data) is always used as the target variable. Model and results are stored for later use with predict().

For model='glm' the design is diagnosed before estimation, as warnings only — nothing is ever dropped, modified, or raised on. An exactly rank-deficient design fires RankDeficientDesignWarning; a full-rank but near-collinear design (a column pair with |r| >= 0.95, or a column-standardized condition number above 30) fires NearCollinearDesignWarning instead — never both. Each has its own category so it can be silenced surgically with warnings.filterwarnings.

Parameters:

NameTypeDescriptionDefault
bdBrainData instance.required
modelstrModel type: ‘ridge’, ‘glm’, or future model names‘glm’
Xarray - like or DataFrameDesign matrix or feature matrix, shape (n_samples, n_features) - For GLM: Design matrix with regressors (n_samples must match bd.data) - For Ridge: Feature matrix for prediction (n_samples must match bd.data)None
cvint, ‘auto’, or sklearn CV splitterCross-validation specification (Ridge only): - int: Number of folds for k-fold CV (returns CV scores) - ‘auto’: Triggers alpha selection via CV (implies alpha=‘auto’) - sklearn CV object: Custom CV splitter (e.g., KFold(3, shuffle=True)) - None: No CV (default, backward compatible)None
devicestr, default=‘cpu’Ridge only. Compute device for the ridge solve/CV: 'cpu' (NumPy), 'gpu' (PyTorch on CUDA/MPS when available), or 'auto' (GPU if present, else CPU). Forwarded to Ridge and the CV evaluation. Ignored for model='glm'.‘cpu’
local_alphabool, default=TrueRidge only. If True, select a separate best alpha per voxel; if False, select a single shared alpha across all voxels. Forwarded to Ridge.True
fit_interceptbool, default=FalseRidge only. If True, fit an intercept term. Redundant (and warned against) when the data is already centered via scale or standardize. Forwarded to Ridge.False
inplacebool, default=TrueIf True, mutate bd and return bd (backward compatible). If False, return a Fit dataclass with the results. In this case bd’s .data and the result attributes (ridge_* / glm_* / cv_results_) are left unchanged, but bd.model_ and bd.X_ (plus bd.design_matrix for GLM) ARE updated on bd so that predict() / compute_contrasts() still work off bd. Successive inplace=False fits therefore overwrite the model used by a later bd.predict().True
progress_barboolDisplay a progress bar for long-running operations. Default: False.False
scalebool or ‘auto’, default=‘auto’Apply percent-signal-change scaling to the data before fitting, via nilearn’s per-voxel mean_scaling (each voxel’s time-series is divided by its own temporal mean, de-meaned, and multiplied by 100). 'auto' resolves to False for both models — PSC is opt-in. Useful for GLM (interpretable % betas); for ridge it is redundant with standardize='zscore' (a warning is raised for that combination). Applied before standardize.‘auto’
standardizestr or None or ‘auto’, default=‘auto’Standardize each voxel across observations after scaling. One of 'center' (subtract the mean), 'zscore' (subtract mean, divide by std), or None (off). 'auto' resolves to 'zscore' for model='ridge' (so a shared alpha regularizes voxels fairly) and None for model='glm'.‘auto’
**kwargsdictAdditional arguments passed to model constructor - Ridge: alpha, alphas, random_state (device is a named param above) - Glm: noise_model, minimize_memory, etc.{}

Attributes:

NameTypeDescription
model_BaseModelFitted model instance (Ridge, Glm, etc.). Set on bd when inplace=True.
X_ndarrayTraining data X, stored for predict() default.
cv_results_dictCross-validation results dict with keys ‘scores’, ‘mean_score’, ‘predictions’, ‘folds’, ‘best_alpha’, ‘alpha_scores’ (if cv is not None).
glm_betasBrainDataBeta coefficients (for model=‘glm’)
glm_tBrainDataT-statistics (for model=‘glm’)
glm_pBrainDataP-values (for model=‘glm’)
glm_seBrainDataStandard errors (for model=‘glm’)
glm_residualBrainDataResiduals (for model=‘glm’)
glm_predictedBrainDataFitted values (for model=‘glm’)
glm_r2BrainDataR-squared values (for model=‘glm’)
ridge_weightsBrainDataModel coefficients (for model=‘ridge’)
ridge_fitted_valuesBrainDataFitted values (for model=‘ridge’)
ridge_scoresBrainDataR-squared scores (for model=‘ridge’)

Returns:

TypeDescription
BrainData or Fit: If inplace=True, returns bd (fitted BrainData). If inplace=False, returns Fit dataclass with results.

Examples:

>>> # Old behavior (backward compatible): mutate self
>>> brain_data.fit(model='ridge', alpha=1.0, cv=5, X=features)
>>> print(f"CV R2: {brain_data.cv_results_['mean_score'].mean():.3f}")
>>> weights = brain_data.ridge_weights  # Access as attribute
>>>
>>> # New behavior: return Fit dataclass (result attrs / data unchanged)
>>> fit = brain_data.fit(model='ridge', alpha=1.0, cv=5, X=features, inplace=False)
>>> assert isinstance(fit, Fit)
>>> assert 'weights' in fit.available()
>>> assert not hasattr(brain_data, 'ridge_weights')  # result attrs not set
>>> # (model_/X_ ARE updated on brain_data so predict() works)
>>> print(f"CV R2: {fit.cv_mean_score.mean():.3f}")
>>>
>>> # GLM with Fit dataclass
>>> fit_glm = brain_data.fit(model='glm', X=design_matrix, inplace=False)
>>> assert 'betas' in fit_glm.available()
>>> assert 't_stats' in fit_glm.available()

fit_glm

fit_glm(bd, X)

Fit GLM model and extract results.

Parameters:

NameTypeDescriptionDefault
bdBrainData instance.required
XDesign matrix (DataFrame or DesignMatrix).required
Note

Sets glm_betas, glm_t, glm_p, glm_se, glm_residual, glm_predicted, glm_r2, and design_matrix on bd.

fit_ridge

fit_ridge(bd, X, cv = None, device = 'cpu', **kwargs)

Fit Ridge model and extract results.

Parameters:

NameTypeDescriptionDefault
bdBrainData instance.required
XndarrayTraining featuresrequired
cvint, ‘auto’, or sklearn CV splitterCross-validation specificationNone
devicestr, default=‘cpu’Compute device (‘cpu’/‘gpu’/‘auto’) for the held-out CV evaluation, forwarded to compute_ridge_cv.‘cpu’
**kwargsdictAdditional arguments for CV (alpha, etc.){}
Note

Sets ridge_weights, ridge_fitted_values, ridge_scores, and cv_results_ (if cv provided) on bd.

parse_contrast_string

parse_contrast_string(bd, contrast_str)

Parse a contrast string into a numeric contrast vector.

Parameters:

NameTypeDescriptionDefault
bdBrainData instance.required
contrast_strstrContrast string like “A - B” or “2*A - B - C”required

Returns:

TypeDescription
np.array: Numeric contrast vector

resolve_preprocessing_defaults

resolve_preprocessing_defaults(model, scale, standardize)

Resolve the 'auto' scale/standardize sentinels to concrete values.

Single source of truth shared by BrainData.fit and BrainCollection.fit so both facades agree on per-model defaults. scale (percent-signal-change) is opt-in for both models. Ridge standardizes its targets by default so a shared alpha regularizes voxels fairly; GLM does neither so betas stay in native units.

Parameters:

NameTypeDescriptionDefault
modelstr'ridge' or 'glm'.required
scalebool or autoRequested scale flag.required
standardizestr, None, or ‘auto’Requested standardize method.required

Returns:

NameTypeDescription
tuple(scale, standardize) with any 'auto' resolved.

to_fit_dataclass

to_fit_dataclass(bd, model)

Convert BrainData fit results to Fit dataclass.

Parameters:

NameTypeDescriptionDefault
bdBrainData instance.required
modelstrModel type (‘ridge’ or ‘glm’)required

Returns:

NameTypeDescription
FitDataclass containing fit results

ttest

ttest(bd, *, popmean = 0.0, permutation = False, n_permute = 5000, tail = 2, return_null = False, n_jobs = -1, random_state = None)

One-sample voxelwise t-test across images (axis 0).

For a BrainData stack of images (e.g. subject-level contrast maps with shape (n_samples, n_voxels)), test whether the per-voxel mean differs from popmean.

Parameters:

NameTypeDescriptionDefault
bdBrainData instance (must contain multiple images).required
popmeanPopulation mean to test against. Default 0.0.0.0
permutationIf True, use a sign-flip permutation test on images - popmean via nltools.algorithms.inference.one_sample_permutation_test; the p-values come from the empirical null and the parametric t-statistic is still reported alongside for reference.False
n_permuteNumber of permutations (used only when permutation=True). Default 5000.5000
tail2‘two’ (two-tailed, default) or 1
return_nullCurrently has no effect. The returned dict always contains exactly {"mean", "t", "z", "p"} and the null distribution is discarded even when this is True. Default False.False
n_jobsNumber of parallel jobs. Default -1 (all cores).-1
random_stateRandom seed for reproducibility.None

Returns:

TypeDescription
dict with four BrainData keys:
- "mean": voxelwise mean across images minus popmean (i.e. mean(images) - popmean, an effect-size estimate; equals the raw voxelwise mean only when popmean=0). - "t": parametric one-sample t-statistic. - "z": signed z-score, sign(t) * norm.isf(p/2), matching nilearn’s output_type='z_score'. Useful for thresholding on z at small df where t tails are heavier than normal. - "p": p-value (parametric, or permutation-based when permutation=True).
The effect size is always returned alongside the inferential maps so
group-level code never has to compute the mean separately.

ttest2

ttest2(bd, other, equal_var = True, tail = 2)

Two-sample voxelwise t-test between two BrainData stacks.

Parameters:

NameTypeDescriptionDefault
bdFirst BrainData (shape (n1, n_voxels)).required
otherSecond BrainData (shape (n2, n_voxels)).required
equal_varIf True (default), standard two-sample t-test. If False, Welch’s t-test.True
tail2‘two’ (two-tailed, default) or 1

Returns:

NameTypeDescription
dict{"t": BrainData, "p": BrainData}.