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.

outliers

outliers

Outlier detection, robust statistics, and data normalization.

Methods:

NameDescription
find_spikesIdentify spikes (motion artifacts, intensity outliers) in 4D fMRI data.
trimTrim a Polars DataFrame/Series by replacing outlier values with NaNs.
winsorizeWinsorize a Polars DataFrame/Series with the largest/lowest value not considered outlier.
zscoreZ-score every column of a Polars or pandas DataFrame/Series.

Methods

find_spikes

find_spikes(data, global_spike_cutoff = 3, diff_spike_cutoff = 3, *, TR: float | None = None, sampling_freq: float | None = None)

Identify spikes (motion artifacts, intensity outliers) in 4D fMRI data.

Parameters:

NameTypeDescriptionDefault
dataBrainData or nibabel instancerequired
global_spike_cutoff(int, None) cutoff in std-deviations for spikes in the per-TR global signal. None to skip.3
diff_spike_cutoff(int, None) cutoff in std-deviations for spikes in the per-TR mean absolute frame-to-frame difference. None to skip.3
TRfloat | NoneRepetition time in seconds. Sets the returned DesignMatrix’s sampling_freq for downstream .append(...) / .convolve(). Pass exactly one of TR or sampling_freq.None
sampling_freqfloat | NoneSampling frequency in Hz (= 1/TR). See TR.None

Returns:

NameTypeDescription
DesignMatrixone indicator column per detected spike TR, named
.nl_global_spike{n} / .nl_diff_spike{n} in the reserved
namespace for generated columns (see RESERVED_PREFIX), with all
spike columns pre-marked as confounds. The two detectors run
independently, so a single bad volume is routinely caught by both;
those detections are bitwise-identical one-hot columns, and only one
is kept (the .nl_global_spike* name, a deterministic tie-break —
the column values are the same either way). Row position is the time
axis (no separate TR index column — that was a pandas-era
artifact). When TR / sampling_freq aren’t provided the DM has
sampling_freq=None; you can still .append() it onto a DM that
does have one.

trim

trim(data, cutoff = None)

Trim a Polars DataFrame/Series by replacing outlier values with NaNs.

Parameters:

NameTypeDescriptionDefault
data(pl.DataFrame, pl.Series) data to trimrequired
cutoff(dict) a dictionary with keys {‘std’:[low,high]} or {‘quantile’:[low,high]}None

Returns: out: (pl.DataFrame, pl.Series) trimmed data (same type as input)

winsorize

winsorize(data, cutoff = None, replace_with_cutoff = True)

Winsorize a Polars DataFrame/Series with the largest/lowest value not considered outlier.

Parameters:

NameTypeDescriptionDefault
data(pl.DataFrame, pl.Series) data to winsorizerequired
cutoff(dict) a dictionary with keys {‘std’:[low,high]} or {‘quantile’:[low,high]}None
replace_with_cutoff(bool) If True, replace outliers with cutoff. If False, replaces outliers with closest existing values; (default: True)True

Returns: out: (pl.DataFrame, pl.Series) winsorized data (same type as input)

zscore

zscore(data)

Z-score every column of a Polars or pandas DataFrame/Series.

Accepts pandas inputs at the boundary for convenience and converts to Polars internally. Always returns Polars output (DataFrame or Series, matching the input shape).

Parameters:

NameTypeDescriptionDefault
datapl.DataFrame, pl.Series, pd.DataFrame, or pd.Series.required

Returns:

TypeDescription
pl.DataFrame or pl.Series with each column z-scored using sample
standard deviation (ddof=1), matching the input shape.