modeling¶
BrainData modeling functions.
Standalone functions extracted from BrainData class methods for model fitting, GLM estimation, Ridge regression, and contrast computation.
Attributes:
| Name | Type | Description |
|---|---|---|
NEAR_COLLINEAR_CONDITION_THRESHOLD | ||
NEAR_COLLINEAR_CORR_THRESHOLD |
Classes:
| Name | Description |
|---|---|
NearCollinearDesignWarning | The design matrix supplied to fit() is full rank but nearly collinear. |
RankDeficientDesignWarning | The design matrix supplied to fit() is rank deficient. |
Methods:
| Name | Description |
|---|---|
compute_contrasts | Compute contrasts from a fitted GLM. |
compute_ridge_cv | Held-out CV scores under a fixed Ridge α. |
fit | Fit a model to brain imaging data. |
fit_glm | Fit GLM model and extract results. |
fit_ridge | Fit Ridge model and extract results. |
parse_contrast_string | Parse a contrast string into a numeric contrast vector. |
resolve_preprocessing_defaults | Resolve the 'auto' scale/standardize sentinels to concrete values. |
to_fit_dataclass | Convert BrainData fit results to Fit dataclass. |
ttest | One-sample voxelwise t-test across images (axis 0). |
ttest2 | Two-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:
| Name | Type | Description | Default |
|---|---|---|---|
bd | BrainData instance. | required | |
contrasts | Can 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 | |
statistic | str | Which 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:
| Type | Description |
|---|---|
| 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"orres["beta"]fromstatistic="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:
| Name | Type | Description | Default |
|---|---|---|---|
bd | BrainData instance. | required | |
X | ndarray | Training features, shape (n_samples, n_features). | required |
cv | int or sklearn CV splitter | Cross-validation specification. | required |
alpha | float | Fixed regularization strength. If None, extracted from bd.model_.alpha. | None |
device | str | Compute device (‘cpu’/‘gpu’/‘auto’). Default: ‘cpu’. | ‘cpu’ |
Returns:
| Name | Type | Description |
|---|---|---|
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:
| Name | Type | Description | Default |
|---|---|---|---|
bd | BrainData instance. | required | |
model | str | Model type: ‘ridge’, ‘glm’, or future model names | ‘glm’ |
X | array - like or DataFrame | Design 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 |
cv | int, ‘auto’, or sklearn CV splitter | Cross-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 |
device | str, 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_alpha | bool, default=True | Ridge 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_intercept | bool, default=False | Ridge 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 |
inplace | bool, default=True | If 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_bar | bool | Display a progress bar for long-running operations. Default: False. | False |
scale | bool 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’ |
standardize | str 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’ |
**kwargs | dict | Additional arguments passed to model constructor - Ridge: alpha, alphas, random_state (device is a named param above) - Glm: noise_model, minimize_memory, etc. | {} |
Attributes:
| Name | Type | Description |
|---|---|---|
model_ | BaseModel | Fitted model instance (Ridge, Glm, etc.). Set on bd when inplace=True. |
X_ | ndarray | Training data X, stored for predict() default. |
cv_results_ | dict | Cross-validation results dict with keys ‘scores’, ‘mean_score’, ‘predictions’, ‘folds’, ‘best_alpha’, ‘alpha_scores’ (if cv is not None). |
glm_betas | BrainData | Beta coefficients (for model=‘glm’) |
glm_t | BrainData | T-statistics (for model=‘glm’) |
glm_p | BrainData | P-values (for model=‘glm’) |
glm_se | BrainData | Standard errors (for model=‘glm’) |
glm_residual | BrainData | Residuals (for model=‘glm’) |
glm_predicted | BrainData | Fitted values (for model=‘glm’) |
glm_r2 | BrainData | R-squared values (for model=‘glm’) |
ridge_weights | BrainData | Model coefficients (for model=‘ridge’) |
ridge_fitted_values | BrainData | Fitted values (for model=‘ridge’) |
ridge_scores | BrainData | R-squared scores (for model=‘ridge’) |
Returns:
| Type | Description |
|---|---|
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:
| Name | Type | Description | Default |
|---|---|---|---|
bd | BrainData instance. | required | |
X | Design 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:
| Name | Type | Description | Default |
|---|---|---|---|
bd | BrainData instance. | required | |
X | ndarray | Training features | required |
cv | int, ‘auto’, or sklearn CV splitter | Cross-validation specification | None |
device | str, default=‘cpu’ | Compute device (‘cpu’/‘gpu’/‘auto’) for the held-out CV evaluation, forwarded to compute_ridge_cv. | ‘cpu’ |
**kwargs | dict | Additional 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:
| Name | Type | Description | Default |
|---|---|---|---|
bd | BrainData instance. | required | |
contrast_str | str | Contrast string like “A - B” or “2*A - B - C” | required |
Returns:
| Type | Description |
|---|---|
| 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:
| Name | Type | Description | Default |
|---|---|---|---|
model | str | 'ridge' or 'glm'. | required |
scale | bool or auto | Requested scale flag. | required |
standardize | str, None, or ‘auto’ | Requested standardize method. | required |
Returns:
| Name | Type | Description |
|---|---|---|
tuple | (scale, standardize) with any 'auto' resolved. |
to_fit_dataclass¶
to_fit_dataclass(bd, model)Convert BrainData fit results to Fit dataclass.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bd | BrainData instance. | required | |
model | str | Model type (‘ridge’ or ‘glm’) | required |
Returns:
| Name | Type | Description |
|---|---|---|
Fit | Dataclass 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:
| Name | Type | Description | Default |
|---|---|---|---|
bd | BrainData instance (must contain multiple images). | required | |
popmean | Population mean to test against. Default 0.0. | 0.0 | |
permutation | If 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_permute | Number of permutations (used only when permutation=True). Default 5000. | 5000 | |
tail | 2 | ‘two’ (two-tailed, default) or 1 | |
return_null | Currently 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_jobs | Number of parallel jobs. Default -1 (all cores). | -1 | |
random_state | Random seed for reproducibility. | None |
Returns:
| Type | Description |
|---|---|
| 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:
| Name | Type | Description | Default |
|---|---|---|---|
bd | First BrainData (shape (n1, n_voxels)). | required | |
other | Second BrainData (shape (n2, n_voxels)). | required | |
equal_var | If True (default), standard two-sample t-test. If False, Welch’s t-test. | True | |
tail | 2 | ‘two’ (two-tailed, default) or 1 |
Returns:
| Name | Type | Description |
|---|---|---|
dict | {"t": BrainData, "p": BrainData}. |