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.

DesignMatrix

DesignMatrix

DesignMatrix(data: DesignMatrix | pl.DataFrame | pd.DataFrame | np.ndarray | dict | str | Path | None = None, *, sampling_freq: float | None = None, TR: float | None = None, run_length: int | str | None = None, columns: list[str] | None = None, convolved: list[str] | None = None, confounds: list[str] | None = None, hrf_model: str | None = 'glover', n_rows: int | None = None)

Represent experimental designs for neuroimaging with Polars.

This is a Polars-based design matrix for experimental designs in neuroimaging.

Wraps a Polars DataFrame with neuroimaging-specific metadata and methods. Uses composition pattern (not subclassing) for clean metadata preservation.

Parameters:

NameTypeDescriptionDefault
dataDataFrame, ndarray, dict, str/Path, or NoneInput data. Accepts: - Polars DataFrame (zero-copy) - pandas DataFrame (converted to Polars) - numpy ndarray - dict (keys=columns, values=data) - str or Path to a .tsv/.csv file. BIDS events files (containing onset and duration columns) are converted to boxcar regressors — call convolve() afterwards if you want HRF convolution. Any other tabular file is read as-is and is typically used for confounds. - str or Path to a .h5/.hdf5 file written by .write(), which restores the data and the metadata (sampling_freq, .convolved, .confounds, .multi). Neither run_length nor sampling_freq is needed; passing either overrides what the file recorded. - None (empty initialization)None
sampling_freqfloatSampling frequency in Hz (1/TR for fMRI data). Mutually exclusive with TR.None
TRfloatRepetition time in seconds. Convenience for sampling_freq = 1/TR. Mutually exclusive with sampling_freq.None
run_lengthint or ‘infer’Required when data is a path to a text file. Number of TRs in the run. Pass 'infer' for tabular/confounds files to accept whatever row count the file has (not valid for events files). Not used for .h5 inputs, which carry their own length.None
columnslist of strColumn names (used with ndarray input)None
convolvedlist of strNames of convolved columns (tracked internally)None
confoundslist of strNames of nuisance/confound columns (intercept, polynomial drift, DCT cosines, motion, …) tracked internallyNone

Attributes:

NameTypeDescription
sampling_freqfloat or NoneSampling frequency in Hz
convolvedlist of strColumns that have been convolved
confoundslist of strNuisance/confound columns (intercept, polynomial trends, DCT bases, motion, physio, …) — these are skipped by .convolve() and kept separate per run on multi-run vertical append.
multiboolTrue if created from multi-run concatenation

Methods:

NameDescription
add_dct_basisAdd discrete cosine transform basis functions for high-pass filtering.
add_polyAdd Legendre polynomial drift terms.
appendConcatenate design matrices.
cleanRemove highly correlated columns.
convolveConvolve columns with an HRF or custom kernel.
copyCreate a deep copy of the DesignMatrix.
corrCalculate column correlations as a similarity Adjacency.
downsampleReduce temporal resolution using Polars-native operations.
dropDrop specified columns.
fillnaFill NaN/null values with specified value.
plotVisualize the design matrix.
replace_dataReplace data columns while preserving confounds and metadata.
standardizeStandardize columns using the specified method.
sumCompute the sum along an axis.
to_numpyConvert a DesignMatrix to a NumPy array.
to_pandasConvert DesignMatrix to pandas DataFrame.
upsampleIncrease temporal resolution to a target frequency.
vifCompute the variance inflation factor for each column.
with_columnsAdd or replace columns via Polars expressions.
writeWrite DesignMatrix to file.
zscoreZ-score standardize columns to mean zero and unit variance.

Passing another DesignMatrix returns a copy: data, sampling_freq, convolved, confounds, and multi are carried over. Any explicit kwarg overrides the inherited value.

When data is a path to a BIDS events file, the constructor HRF-convolves the regressors by default (hrf_model='glover', matching nilearn’s make_first_level_design_matrix). The output columns are suffixed _c0 and .convolved is populated. Pass hrf_model=None to load raw boxcar regressors instead — useful for FIR designs, PPI flows that build interaction terms before convolution, or pedagogical material that introduces convolution as a separate step. hrf_model is silently ignored when data is anything other than an events file.

Examples:

>>> # Create from numpy array
>>> dm = DesignMatrix(np.zeros((100, 2)), sampling_freq=0.5, columns=['a', 'b'])
>>> # Add columns
>>> dm['stim'] = [0, 1, 1, 0] * 25
>>> # Convolve with HRF — convolved columns get a `_c0` suffix
>>> dm_conv = dm.convolve()  # 'stim' → 'stim_c0'
>>> # Add polynomial drift terms
>>> dm_conv = dm_conv.add_poly(order=2)
>>> # Multi-run concatenation (auto-separates polynomials)
>>> dm_run1 = DesignMatrix(...).add_poly(0)
>>> dm_run2 = DesignMatrix(...).add_poly(0)
>>> dm_multi = dm_run1.append(dm_run2, axis=0)  # Creates .nl_r0_poly_0, .nl_r1_poly_0

Methods

add_dct_basis

add_dct_basis(duration: float = 180, drop: int = 0, *, include_constant: bool = True) -> DesignMatrix

Add discrete cosine transform basis functions for high-pass filtering.

Parameters:

NameTypeDescriptionDefault
durationfloatFilter duration in seconds. Default: 180.180
dropintNumber of low-frequency bases to drop. Default: 0.0
include_constantboolIf True, also add a constant/intercept column named .nl_cosine_0 (analogous to .nl_poly_0 in add_poly). The underlying DCT basis drops the constant per SPM convention; set False to match SPM behavior. Default: True.True

Returns:

NameTypeDescription
DesignMatrixDesignMatrixNew DesignMatrix with DCT basis columns appended.

add_poly

add_poly(order: int = 0, include_lower: bool = True) -> DesignMatrix

Add Legendre polynomial drift terms.

Parameters:

NameTypeDescriptionDefault
orderintPolynomial order (0=intercept, 1=linear, 2=quadratic, ...). Default: 0.0
include_lowerboolIf True, include all orders from 0 to order. Default: True.True

Returns:

NameTypeDescription
DesignMatrixDesignMatrixNew DesignMatrix with polynomial columns appended.

append

append(dm: DesignMatrix | list[DesignMatrix], *, axis: int = 0, keep_separate: bool = True, unique_cols: list[str] | None = None, fill_na: int | float | None = 0, as_confounds: bool = False, progress_bar: bool = False) -> DesignMatrix

Concatenate design matrices.

Parameters:

NameTypeDescriptionDefault
dmDesignMatrix or list of DesignMatrixDesign matrix/matrices to append.required
axisint0 for row-wise (vertical), 1 for column-wise (horizontal). Default: 0.0
keep_separateboolWhether to separate confound columns across runs (only applies when axis=0). Default: True.True
unique_colslist of strAdditional columns to keep separated (supports wildcards).None
fill_naint, float, or NoneValue to fill NaN values during vertical concatenation, or None to preserve nulls. Default: 0.0
as_confoundsboolOnly applies when axis=1. If True, mark all columns from dm as nuisance/confounds in the result — they get skipped by .convolve() and separated across runs on later vertical appends. Default: False.False
progress_barboolPrint messages about confound separation. Default: False.False

Returns:

NameTypeDescription
DesignMatrixDesignMatrixConcatenated design matrix.

clean

clean(*, fill_na: int | float | None = 0, exclude_confounds: bool = False, thresh: float = 0.95, progress_bar: bool = False) -> DesignMatrix

Remove highly correlated columns.

Parameters:

NameTypeDescriptionDefault
fill_naint, float, or NoneFill NaN values before checking correlations (default 0)0
exclude_confoundsboolSkip confound/nuisance columns from correlation checkFalse
threshfloatCorrelation threshold (drop if abs(r) >= thresh, default 0.95)0.95
progress_barboolPrint dropped column names. Default: FalseFalse

Returns:

NameTypeDescription
DesignMatrixDesignMatrixCleaned matrix with highly correlated columns removed

convolve

convolve(conv_func: str | np.ndarray = 'hrf', columns: list[str] | None = None) -> DesignMatrix

Convolve columns with an HRF or custom kernel.

Convolved columns are always renamed to <col>_c{i} (where i is the kernel index, 0 for a single 1-D kernel). The source columns are dropped, and self.convolved lists the post-suffix names so downstream metadata stays in sync with the dataframe.

Parameters:

NameTypeDescriptionDefault
conv_funcstr or ndarray‘hrf’ for canonical Glover HRF, or custom kernel(s). Can be 1D array (single kernel) or 2D (samples x kernels).‘hrf’
columnslist of strColumns to convolve (default: all non-confound columns).None

Returns:

NameTypeDescription
DesignMatrixDesignMatrixNew DesignMatrix with convolved columns renamed.

copy

copy() -> DesignMatrix

Create a deep copy of the DesignMatrix.

Returns:

NameTypeDescription
DesignMatrixDesignMatrixCopy of the current DesignMatrix

corr

corr(*, metric: str = 'pearson', columns: list[str] | None = None)

Calculate column correlations as a similarity Adjacency.

Parameters:

NameTypeDescriptionDefault
metricstr'pearson' (default) or 'spearman'.‘pearson’
columnslist of strSubset of columns to correlate. Defaults to all columns.None

Returns:

NameTypeDescription
AdjacencySimilarity matrix whose labels are the column names. The unit diagonal is dropped (self-correlation isn’t an edge); use .plot(method='corr') for a heatmap with the diagonal restored.

downsample

downsample(target: float, method: str = 'mean') -> DesignMatrix

Reduce temporal resolution using Polars-native operations.

Parameters:

NameTypeDescriptionDefault
targetfloatTarget sampling frequency in Hz (must be < current sampling_freq)required
methodstrAggregation method - ‘mean’ or ‘median’ (default: ‘mean’)‘mean’

Returns:

NameTypeDescription
DesignMatrixDesignMatrixDownsampled DesignMatrix with updated sampling_freq

drop

drop(columns: list[str]) -> DesignMatrix

Drop specified columns.

Parameters:

NameTypeDescriptionDefault
columnslist of strColumn names to remove.required

Returns:

NameTypeDescription
DesignMatrixDesignMatrixNew DesignMatrix without the specified columns.

fillna

fillna(value: int | float) -> DesignMatrix

Fill NaN/null values with specified value.

Parameters:

NameTypeDescriptionDefault
valueint or floatValue to replace NaN/null entries with.required

Returns:

NameTypeDescription
DesignMatrixDesignMatrixNew DesignMatrix with NaN/null values replaced.

plot

plot(method: str = 'matrix', *, columns: list[str] | None = None, rescale: bool = True, metric: str = 'pearson', ax: str = None, figsize: tuple | None = None, title: str | None = None, cmap: str | None = None, save: str | None = None, **kwargs: str | None) -> Figure

Visualize the design matrix.

Dispatches over method (mirroring BrainData.plot):

Parameters:

NameTypeDescriptionDefault
methodstr'matrix''timeseries'
columnslist of strSubset of columns to plot. Defaults to all columns.None
rescalebool'matrix' only. Rescale each column by its L2 norm so columns with different native magnitudes are visually comparable (SPM/nilearn convention). Default: True.True
metricstr'corr' only. 'pearson' (default) or 'spearman'.‘pearson’
axAxesExisting axis to draw on; a new figure is created if omitted.None
figsizetupleFigure size; sensible per-method default when omitted.None
titlestrAxis title.None
cmapstrColormap ('matrix' / 'corr').None
savestrPath to save the figure.None
**kwargsForwarded to the underlying plotter (seaborn.heatmap for 'matrix' / 'corr'; Axes.plot for 'timeseries').{}

Returns:

TypeDescription
Figurematplotlib.figure.Figure: The figure containing the plot.

replace_data

replace_data(data: np.ndarray, column_names: list[str] | None = None) -> DesignMatrix

Replace data columns while preserving confounds and metadata.

Parameters:

NameTypeDescriptionDefault
datandarrayNew data array (must match number of rows in current DesignMatrix)required
column_nameslist of strNames for new data columns.None

Returns:

NameTypeDescription
DesignMatrixDesignMatrixNew DesignMatrix with replaced data columns, preserved confounds

standardize

standardize(method: str = 'zscore', columns: list[str] | None = None) -> DesignMatrix

Standardize columns using the specified method.

Parameters:

NameTypeDescriptionDefault
methodstrStandardization method (‘zscore’ or ‘center’). Default: ‘zscore’.‘zscore’
columnslist [ str ] | NoneColumns to standardize. If None, standardize all non-confound columns.None

Returns:

NameTypeDescription
DesignMatrixDesignMatrixNew DesignMatrix with standardized columns.

sum

sum(axis: int = 0) -> pl.Series

Compute the sum along an axis.

Parameters:

NameTypeDescriptionDefault
axisint, default=00: sum down columns, 1: sum across rows.0

Returns:

TypeDescription
Seriespl.Series: Sums along specified axis.

to_numpy

to_numpy() -> np.ndarray

Convert a DesignMatrix to a NumPy array.

Returns:

TypeDescription
ndarraynp.ndarray: 2D array with shape (n_samples, n_columns)

to_pandas

to_pandas() -> pd.DataFrame

Convert DesignMatrix to pandas DataFrame.

Returns:

TypeDescription
DataFramepd.DataFrame: Pandas DataFrame with same data and column names.

upsample

upsample(target: float, method: str = 'linear') -> DesignMatrix

Increase temporal resolution to a target frequency.

Parameters:

NameTypeDescriptionDefault
targetfloatTarget sampling frequency in Hz (must be > current sampling_freq)required
methodstrInterpolation method - ‘linear’ or ‘nearest’ (default: ‘linear’)‘linear’

Returns:

NameTypeDescription
DesignMatrixDesignMatrixUpsampled DesignMatrix with updated sampling_freq

vif

vif(exclude_confounds: bool = True) -> np.ndarray | None

Compute the variance inflation factor for each column.

Parameters:

NameTypeDescriptionDefault
exclude_confoundsboolSkip confound/nuisance columns. Default: True.True

Returns:

TypeDescription
ndarray | Nonenp.ndarray: VIF values for each included column. Returns None if the correlation matrix is singular.

with_columns

with_columns(*exprs, **named_exprs) -> DesignMatrix

Add or replace columns via Polars expressions.

Mirrors DataFrame.with_columns. Named kwargs become named columns; positional pl.Expr arguments are accepted as-is (including pl.Expr.alias("name")). Returns a new DesignMatrix with metadata preserved; new columns are not auto-tagged as convolved or confounds.

For convenience, named-kwarg values that aren’t pl.Expr / pl.Series are coerced:

Examples:

>>> dm = dm.with_columns(motor=pl.sum_horizontal(motor_cols)).drop(motor_cols)
>>> dm = dm.with_columns(
...     vmpfc=seed_signal,
...     vmpfc_motor=pl.col("vmpfc") * pl.col("motor_c0"),
... )

write

write(file_name: str, sep: str | None = None) -> None

Write DesignMatrix to file.

Supports TSV, CSV, and HDF5 formats. Format is auto-detected from the file extension. Text formats carry the data only; .h5 also preserves sampling_freq, .convolved, .confounds, and .multi, so DesignMatrix(path) restores the whole object.

Parameters:

NameTypeDescriptionDefault
file_namestrOutput file path. Use .tsv, .csv, or .h5/.hdf5 extension.required
sepstr | NoneColumn separator for text files. Defaults to the delimiter the extension implies (comma for .csv, tab otherwise); pass a value to override.None

zscore

zscore(columns: list[str] | None = None) -> DesignMatrix

Z-score standardize columns to mean zero and unit variance.

Parameters:

NameTypeDescriptionDefault
columnslist of strColumns to standardize. If None, standardize all non-confound columns.None

Returns:

NameTypeDescription
DesignMatrixDesignMatrixNew DesignMatrix with standardized columns