Skip to content

Result types

What the analysis methods hand back. These are read, not constructed: BrainData.fit leaves a FitResult on BrainData.model, BrainData.predict returns a PredictResult, BrainData.bootstrap a BootstrapResult, a GLM contrast a ContrastResult, and the brain-space functions a BrainSpaceConfig. The fit and contrast records also write themselves to a directory of NIfTI maps with write.

Data classes for neuroimaging analysis.

BrainData (masked voxel data), Adjacency (similarity/distance matrices), DesignMatrix (regressors), the Roc analysis class, the Simulator/SimulateGrid data simulators, and the frozen result records those classes return (FitResult, PredictResult, BootstrapResult, ContrastResult) plus the brain-space configuration record (BrainSpaceConfig).

Classes:

Name Description
FitResult

Frozen record of one BrainData.fit, held on BrainData.model.

PredictResult

Frozen structural record for BrainData.predict decoding results.

BootstrapResult

Frozen record of one bootstrap statistic's estimate and uncertainty.

ContrastResult

Frozen record of the inferential outputs of one contrast.

BrainSpaceConfig

Immutable MNI template configuration.

Classes

FitResult dataclass

FitResult(
    kind: str,
    betas: BrainData,
    predicted: BrainData,
    residual: BrainData,
    r2: BrainData,
    design: Any,
    alpha: BrainData | None = None,
    cv: Any = None,
    _estimator: Any = None,
)

Frozen record of one BrainData.fit, held on BrainData.model.

fit still returns the BrainData it fitted, so chaining survives; this record is the one declared attribute it sets. Every map is a BrainData on the fitted object's mask, so result.betas.plot() works directly and .data gives the array.

Field bindings cannot be rebound, and every map and design the record holds is independently owned: the producer builds them, so they never alias the fitted data or the caller's design. The fitted estimator is the exception: it is internal state the facade methods drive, not a payload to read, so it is not shown in the repr, and it is None on a record restored from HDF5.

Attributes:

Name Type Description
kind str

Which estimator produced the fit, 'glm' or 'ridge'.

betas BrainData

One coefficient map per column of design, in column order. Ridge users know these as the model's weights.

predicted BrainData

The fitted response, one row per training observation, with the training row metadata retained.

residual BrainData

Response minus predicted, in the same shape.

r2 BrainData

One in-sample fit-quality map. A GLM's carries Nilearn's whitened variance-ratio semantics: conventional R-squared for an OLS fit with an intercept, a pseudo-R-squared in the whitened space for an autoregressive one.

design DesignMatrix | ndarray | dict[str, ndarray]

What the model was fit on — the DesignMatrix for a GLM, the feature matrix for ridge, or the named feature spaces for banded ridge.

alpha BrainData | None

Ridge only: the penalty the fit used, one value per voxel, broadcast when a single alpha was shared. None for a GLM.

cv BaseCrossValidator | None

Ridge only: the cross-validator alpha selection resolved to. None for a GLM and for a fixed-alpha fit.

Note

A record restored from HDF5 has no estimator, so it serves what it stored and refuses the rest: the no-argument predict() still returns predicted and a contrast effect is still a linear combination of betas, while predict(X=...), bootstrap and compute_contrasts(inference=True) ask for a refit from design.

Methods:

Name Description
write

Write the fit to directory as NIfTI maps, a design CSV and a sidecar.

Methods:

write
write(directory, prefix=None) -> list[Path]

Write the fit to directory as NIfTI maps, a design CSV and a sidecar.

The whole "fit, then save" workflow in one call. Each map becomes <prefix>_betas.nii.gz, _predicted, _residual, _r2 and — for ridge — _alpha; the design becomes <prefix>_design.csv (one _design-<space>.csv per feature space for a banded ridge, with the space name percent-encoded); and <prefix>_fit.json records the kind of fit, the design's column names, and every feature space's real name. Files with the same names are replaced. Nothing here is BIDS.

Parameters:

Name Type Description Default
directory str | Path

Where to write. Created if it does not exist.

required
prefix str | None

Prepended to every filename as <prefix>_. Default None writes the bare names. A path separator raises: it names files, not subdirectories.

None

Returns:

Type Description
list[Path]

Every file written.

Raises:

Type Description
ValueError

If prefix contains a path separator.

Examples:

data.fit(model="glm", X=design)
data.model.write("derivatives/sub-01", prefix="sub-01_task-rest")

PredictResult dataclass

PredictResult(
    spatial_scale: str,
    scoring: Any = None,
    classes: ndarray | None = None,
    predictions: ndarray | None = None,
    cv_folds: ndarray | None = None,
    scores: ndarray | None = None,
    estimator: Any = None,
    weight_map: BrainData | None = None,
    roi_labels: ndarray | None = None,
    score_map: BrainData | None = None,
)

Frozen structural record for BrainData.predict decoding results.

spatial_scale is the discriminator: it decides which fields carry a value and which stay None. Construction validates that combination, so an empty or mixed-mode record cannot exist; the shapes within it are the producer's responsibility. Field bindings cannot be rebound, but the payloads they hold remain usable, and the record takes independent ownership of every array, brain map, and estimator it stores.

Brain-space outputs are BrainData objects, not raw arrays, so result.weight_map.plot() works directly (.data gives the array). Non-spatial fields are numpy.

Populated by spatial_scale. 'whole_brain': predictions, cv_folds, scores, estimator, weight_map. 'roi': scores, roi_labels, score_map, weight_map. 'searchlight': score_map. classes accompanies any classifier; scoring records the caller's scoring specification in every mode.

Why the all-data fit is the canonical map. The mean of per-fold coef_ vectors corresponds to no actual fitted estimator (each fold saw a different subset), and fits on overlapping training folds are not independent uncertainty samples. The record therefore exposes one coefficient map, from the estimator refitted on all observations after cross-validation: cross-validation gives the honest score, the refit gives the publishable map.

Attributes:

Name Type Description
spatial_scale str

'whole_brain', 'roi', or 'searchlight'.

scoring str | callable | None

The scoring specification the caller passed. None records that the estimator's own score method was used; it does not by itself name that method's metric.

classes ndarray | None

Classifier class labels, (n_classes,). None for regression.

predictions ndarray | None

Out-of-fold predictions, one per row, (n_samples,) (whole-brain only).

cv_folds ndarray | None

Fold index per row, (n_samples,) (whole-brain only).

scores ndarray | None

Per-fold score — (n_folds,) for whole-brain, (n_folds, n_rois) for ROI.

estimator Any

The all-data fitted sklearn estimator (whole-brain only); use it to .predict() on new data.

weight_map BrainData | None

Coefficients of the estimator refit on all data, (n_voxels,) or (n_classes, n_voxels) for multiclass — one map for regression and binary classification, one map per class in classes order for multiclass. For ROI, each parcel's coefficients are written into its voxels (NaN outside parcels); magnitudes are not comparable across parcels.

roi_labels ndarray | None

Atlas integer ids, (n_rois,), in the order of the scores parcel axis (ROI only).

score_map BrainData | None

(n_voxels,) map of cross-validated scores — for ROI, every voxel of parcel i holds that parcel's mean fold score (NaN outside parcels); for searchlight, the sphere-centered mean fold score at each voxel.

mean_score float | ndarray

Mean of scores across folds, computed on demand — a float for whole-brain, (n_rois,) for ROI. Accessing it on a searchlight result raises AttributeError.

std_score float | ndarray

Standard deviation of scores across folds, in mean_score's form and with the same searchlight rule.

Note

Encoding-model timeseries prediction (bd.predict(X=...)) returns a BrainData directly rather than a PredictResult — the natural container for a voxel timeseries.

Methods:

Name Description
asdict

Convert to dictionary.

available

Return names of the fields this result carries (excludes private).

Attributes

mean_score property
mean_score

Mean score across folds — a float for whole-brain, per parcel for ROI.

std_score property
std_score

Score standard deviation across folds, in mean_score's form.

Methods:

asdict
asdict(include_none: bool = False) -> dict

Convert to dictionary.

Parameters:

Name Type Description Default
include_none bool

If True, include every field that does not apply to this spatial scale, whose value is None. spatial_scale and scoring are always included. Private fields (starting with _) are always excluded.

False

Returns:

Type Description
dict

Dictionary of field names to values.

available
available() -> list

Return names of the fields this result carries (excludes private).

spatial_scale and scoring always count: a scoring of None records that the estimator's own score method was used, which is a value, not an absent field.

BootstrapResult dataclass

BootstrapResult(
    estimate: Payload,
    standard_error: Payload,
    ci_lower: Payload,
    ci_upper: Payload,
    samples: ndarray | None = None,
)

Bases: Generic[Payload]

Frozen record of one bootstrap statistic's estimate and uncertainty.

The single result structure every supported bootstrap statistic returns. Its payload is whatever the producer works in: BrainData for the BrainData facade, Adjacency for the Adjacency facade. The four summary payloads share one data shape.

Field bindings cannot be rebound. The payloads stay usable, but the record takes independent ownership of each one, so mutating a returned payload never reaches the source object or a sibling payload.

The record deliberately exposes no replicate mean and no z, p, or tail output: those need a separately defined bootstrap hypothesis test. For a normal-approximation stand-in, users compute it themselves from estimate and standard_error.

Attributes:

Name Type Description
estimate Payload

The statistic evaluated once on the original full sample — not the mean of the replicates.

standard_error Payload

Elementwise standard deviation of the bootstrap replicates, with ddof=1.

ci_lower Payload

Lower bound of the central percentile interval at the requested confidence_level.

ci_upper Payload

Upper bound of that interval. The bounds are elementwise marginal: the nominal level applies separately to each voxel, feature, or test row, with no simultaneous-coverage claim.

samples ndarray | None

Every replicate, bootstrap axis first, when return_samples=True; None otherwise.

ContrastResult dataclass

ContrastResult(
    effect: Payload,
    variance: Payload,
    standard_error: Payload,
    statistic: Payload,
    z_score: Payload,
    p_value: Payload,
    degrees_of_freedom: float | ndarray,
)

Bases: Generic[Payload]

Frozen record of the inferential outputs of one contrast.

The one result type inferential contrast methods return. Its payload is whatever the producer works in: float or np.ndarray for a _Glm, BrainData for the BrainData facade.

Fields cannot be rebound. Array payloads stay mutable, but each result owns its arrays: they never alias the input contrast, a model's retained state, or another result.

Every statistic describes the directional hypothesis that effect is zero, so p_value is one-sided; negating the contrast tests the other direction.

Attributes:

Name Type Description
effect Payload

The estimated linear combination of coefficients.

variance Payload

The estimated variance of effect.

standard_error Payload

np.sqrt of variance, with no absolute value or clipping, so it may be non-finite.

statistic Payload

The signed t-statistic for the null hypothesis that effect is zero.

z_score Payload

The signed normal-score equivalent of the directional p-value.

p_value Payload

The one-sided upper-tail p-value.

degrees_of_freedom float | ndarray

The residual degrees of freedom used for inference.

Methods:

Name Description
write

Write the contrast to directory as NIfTI maps and a sidecar.

Methods:

write
write(directory, prefix=None) -> list[Path]

Write the contrast to directory as NIfTI maps and a sidecar.

The whole "fit, contrast, then save" workflow in one call. Each map becomes <prefix>_effect.nii.gz, _variance, _se, _t, _z and _p, and <prefix>_contrast.json records the degrees of freedom. Files with the same names are replaced. Nothing here is BIDS.

Parameters:

Name Type Description Default
directory str | Path

Where to write. Created if it does not exist.

required
prefix str | None

Prepended to every filename as <prefix>_. Default None writes the bare names. A path separator raises: it names files, not subdirectories.

None

Returns:

Type Description
list[Path]

Every file written.

Raises:

Type Description
TypeError

If the payloads are bare arrays rather than brain maps, which only a contrast computed outside BrainData can be.

ValueError

If prefix contains a path separator.

Examples:

result = data.compute_contrasts("a - b", inference=True)
result.write("derivatives/contrasts", prefix="a-gt-b")

BrainSpaceConfig dataclass

BrainSpaceConfig(
    template: TemplateName = "default",
    resolution: Resolution = 2,
)

Immutable MNI template configuration.

Attributes:

Name Type Description
template str

Template variant ('default', 'nilearn', 'fmriprep').

resolution int

Resolution in mm (1, 2, or 3).

mask str

Path to the brain mask file.

brain str

Path to the brain-extracted image.

plot str

Path to the full T1 image used for plotting.

Attributes

brain property
brain: str

Path to the brain-extracted image.

mask property
mask: str

Path to the brain mask file.

plot property
plot: str

Path to the full T1 image used for plotting.