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:
| Name | Type | Description | Default |
|---|---|---|---|
data | DataFrame, ndarray, dict, str/Path, or None | Input 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_freq | float | Sampling frequency in Hz (1/TR for fMRI data). Mutually exclusive with TR. | None |
TR | float | Repetition time in seconds. Convenience for sampling_freq = 1/TR. Mutually exclusive with sampling_freq. | None |
run_length | int 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 |
columns | list of str | Column names (used with ndarray input) | None |
convolved | list of str | Names of convolved columns (tracked internally) | None |
confounds | list of str | Names of nuisance/confound columns (intercept, polynomial drift, DCT cosines, motion, …) tracked internally | None |
Attributes:
| Name | Type | Description |
|---|---|---|
sampling_freq | float or None | Sampling frequency in Hz |
convolved | list of str | Columns that have been convolved |
confounds | list of str | Nuisance/confound columns (intercept, polynomial trends, DCT bases, motion, physio, …) — these are skipped by .convolve() and kept separate per run on multi-run vertical append. |
multi | bool | True if created from multi-run concatenation |
Methods:
| Name | Description |
|---|---|
add_dct_basis | Add discrete cosine transform basis functions for high-pass filtering. |
add_poly | Add Legendre polynomial drift terms. |
append | Concatenate design matrices. |
clean | Remove highly correlated columns. |
convolve | Convolve columns with an HRF or custom kernel. |
copy | Create a deep copy of the DesignMatrix. |
corr | Calculate column correlations as a similarity Adjacency. |
downsample | Reduce temporal resolution using Polars-native operations. |
drop | Drop specified columns. |
fillna | Fill NaN/null values with specified value. |
plot | Visualize the design matrix. |
replace_data | Replace data columns while preserving confounds and metadata. |
standardize | Standardize columns using the specified method. |
sum | Compute the sum along an axis. |
to_numpy | Convert a DesignMatrix to a NumPy array. |
to_pandas | Convert DesignMatrix to pandas DataFrame. |
upsample | Increase temporal resolution to a target frequency. |
vif | Compute the variance inflation factor for each column. |
with_columns | Add or replace columns via Polars expressions. |
write | Write DesignMatrix to file. |
zscore | Z-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_0Methods¶
add_dct_basis¶
add_dct_basis(duration: float = 180, drop: int = 0, *, include_constant: bool = True) -> DesignMatrixAdd discrete cosine transform basis functions for high-pass filtering.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
duration | float | Filter duration in seconds. Default: 180. | 180 |
drop | int | Number of low-frequency bases to drop. Default: 0. | 0 |
include_constant | bool | If 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:
| Name | Type | Description |
|---|---|---|
DesignMatrix | DesignMatrix | New DesignMatrix with DCT basis columns appended. |
add_poly¶
add_poly(order: int = 0, include_lower: bool = True) -> DesignMatrixAdd Legendre polynomial drift terms.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
order | int | Polynomial order (0=intercept, 1=linear, 2=quadratic, ...). Default: 0. | 0 |
include_lower | bool | If True, include all orders from 0 to order. Default: True. | True |
Returns:
| Name | Type | Description |
|---|---|---|
DesignMatrix | DesignMatrix | New 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) -> DesignMatrixConcatenate design matrices.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dm | DesignMatrix or list of DesignMatrix | Design matrix/matrices to append. | required |
axis | int | 0 for row-wise (vertical), 1 for column-wise (horizontal). Default: 0. | 0 |
keep_separate | bool | Whether to separate confound columns across runs (only applies when axis=0). Default: True. | True |
unique_cols | list of str | Additional columns to keep separated (supports wildcards). | None |
fill_na | int, float, or None | Value to fill NaN values during vertical concatenation, or None to preserve nulls. Default: 0. | 0 |
as_confounds | bool | Only 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_bar | bool | Print messages about confound separation. Default: False. | False |
Returns:
| Name | Type | Description |
|---|---|---|
DesignMatrix | DesignMatrix | Concatenated design matrix. |
clean¶
clean(*, fill_na: int | float | None = 0, exclude_confounds: bool = False, thresh: float = 0.95, progress_bar: bool = False) -> DesignMatrixRemove highly correlated columns.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fill_na | int, float, or None | Fill NaN values before checking correlations (default 0) | 0 |
exclude_confounds | bool | Skip confound/nuisance columns from correlation check | False |
thresh | float | Correlation threshold (drop if abs(r) >= thresh, default 0.95) | 0.95 |
progress_bar | bool | Print dropped column names. Default: False | False |
Returns:
| Name | Type | Description |
|---|---|---|
DesignMatrix | DesignMatrix | Cleaned matrix with highly correlated columns removed |
convolve¶
convolve(conv_func: str | np.ndarray = 'hrf', columns: list[str] | None = None) -> DesignMatrixConvolve 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:
| Name | Type | Description | Default |
|---|---|---|---|
conv_func | str or ndarray | ‘hrf’ for canonical Glover HRF, or custom kernel(s). Can be 1D array (single kernel) or 2D (samples x kernels). | ‘hrf’ |
columns | list of str | Columns to convolve (default: all non-confound columns). | None |
Returns:
| Name | Type | Description |
|---|---|---|
DesignMatrix | DesignMatrix | New DesignMatrix with convolved columns renamed. |
copy¶
copy() -> DesignMatrixCreate a deep copy of the DesignMatrix.
Returns:
| Name | Type | Description |
|---|---|---|
DesignMatrix | DesignMatrix | Copy of the current DesignMatrix |
corr¶
corr(*, metric: str = 'pearson', columns: list[str] | None = None)Calculate column correlations as a similarity Adjacency.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metric | str | 'pearson' (default) or 'spearman'. | ‘pearson’ |
columns | list of str | Subset of columns to correlate. Defaults to all columns. | None |
Returns:
| Name | Type | Description |
|---|---|---|
Adjacency | Similarity 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') -> DesignMatrixReduce temporal resolution using Polars-native operations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target | float | Target sampling frequency in Hz (must be < current sampling_freq) | required |
method | str | Aggregation method - ‘mean’ or ‘median’ (default: ‘mean’) | ‘mean’ |
Returns:
| Name | Type | Description |
|---|---|---|
DesignMatrix | DesignMatrix | Downsampled DesignMatrix with updated sampling_freq |
drop¶
drop(columns: list[str]) -> DesignMatrixDrop specified columns.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
columns | list of str | Column names to remove. | required |
Returns:
| Name | Type | Description |
|---|---|---|
DesignMatrix | DesignMatrix | New DesignMatrix without the specified columns. |
fillna¶
fillna(value: int | float) -> DesignMatrixFill NaN/null values with specified value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value | int or float | Value to replace NaN/null entries with. | required |
Returns:
| Name | Type | Description |
|---|---|---|
DesignMatrix | DesignMatrix | New 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) -> FigureVisualize the design matrix.
Dispatches over method (mirroring BrainData.plot):
'matrix'(default): SPM-style heatmap (rows=TRs, cols=regressors).'timeseries': overlaid line plot of regressor time courses. Pass the sameaxacross calls to overlay multiple DesignMatrices (e.g. original vs. convolved).'corr': labeled correlation heatmap of the columns (reusescorr; diagonal restored to 1.0 for display).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
method | str | 'matrix' | 'timeseries' |
columns | list of str | Subset of columns to plot. Defaults to all columns. | None |
rescale | bool | 'matrix' only. Rescale each column by its L2 norm so columns with different native magnitudes are visually comparable (SPM/nilearn convention). Default: True. | True |
metric | str | 'corr' only. 'pearson' (default) or 'spearman'. | ‘pearson’ |
ax | Axes | Existing axis to draw on; a new figure is created if omitted. | None |
figsize | tuple | Figure size; sensible per-method default when omitted. | None |
title | str | Axis title. | None |
cmap | str | Colormap ('matrix' / 'corr'). | None |
save | str | Path to save the figure. | None |
**kwargs | Forwarded to the underlying plotter (seaborn.heatmap for 'matrix' / 'corr'; Axes.plot for 'timeseries'). | {} |
Returns:
| Type | Description |
|---|---|
Figure | matplotlib.figure.Figure: The figure containing the plot. |
replace_data¶
replace_data(data: np.ndarray, column_names: list[str] | None = None) -> DesignMatrixReplace data columns while preserving confounds and metadata.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data | ndarray | New data array (must match number of rows in current DesignMatrix) | required |
column_names | list of str | Names for new data columns. | None |
Returns:
| Name | Type | Description |
|---|---|---|
DesignMatrix | DesignMatrix | New DesignMatrix with replaced data columns, preserved confounds |
standardize¶
standardize(method: str = 'zscore', columns: list[str] | None = None) -> DesignMatrixStandardize columns using the specified method.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
method | str | Standardization method (‘zscore’ or ‘center’). Default: ‘zscore’. | ‘zscore’ |
columns | list [ str ] | None | Columns to standardize. If None, standardize all non-confound columns. | None |
Returns:
| Name | Type | Description |
|---|---|---|
DesignMatrix | DesignMatrix | New DesignMatrix with standardized columns. |
sum¶
sum(axis: int = 0) -> pl.SeriesCompute the sum along an axis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
axis | int, default=0 | 0: sum down columns, 1: sum across rows. | 0 |
Returns:
| Type | Description |
|---|---|
Series | pl.Series: Sums along specified axis. |
to_numpy¶
to_numpy() -> np.ndarrayConvert a DesignMatrix to a NumPy array.
Returns:
| Type | Description |
|---|---|
ndarray | np.ndarray: 2D array with shape (n_samples, n_columns) |
to_pandas¶
to_pandas() -> pd.DataFrameConvert DesignMatrix to pandas DataFrame.
Returns:
| Type | Description |
|---|---|
DataFrame | pd.DataFrame: Pandas DataFrame with same data and column names. |
upsample¶
upsample(target: float, method: str = 'linear') -> DesignMatrixIncrease temporal resolution to a target frequency.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target | float | Target sampling frequency in Hz (must be > current sampling_freq) | required |
method | str | Interpolation method - ‘linear’ or ‘nearest’ (default: ‘linear’) | ‘linear’ |
Returns:
| Name | Type | Description |
|---|---|---|
DesignMatrix | DesignMatrix | Upsampled DesignMatrix with updated sampling_freq |
vif¶
vif(exclude_confounds: bool = True) -> np.ndarray | NoneCompute the variance inflation factor for each column.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
exclude_confounds | bool | Skip confound/nuisance columns. Default: True. | True |
Returns:
| Type | Description |
|---|---|
ndarray | None | np.ndarray: VIF values for each included column. Returns None if the correlation matrix is singular. |
with_columns¶
with_columns(*exprs, **named_exprs) -> DesignMatrixAdd 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:
int/float→ broadcast scalar viapl.litlist/np.ndarray→ wrapped aspl.Series
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) -> NoneWrite 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:
| Name | Type | Description | Default |
|---|---|---|---|
file_name | str | Output file path. Use .tsv, .csv, or .h5/.hdf5 extension. | required |
sep | str | None | Column 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) -> DesignMatrixZ-score standardize columns to mean zero and unit variance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
columns | list of str | Columns to standardize. If None, standardize all non-confound columns. | None |
Returns:
| Name | Type | Description |
|---|---|---|
DesignMatrix | DesignMatrix | New DesignMatrix with standardized columns |