Signal#

Tools for digital signal processing: fft filtering, low-frequency filtering utilizing downsampling etc.

class brainmaze_utils.signal.LowFrequencyFilter(fs=None, cutoff=None, n_decimate=1, n_order=None, dec_cutoff=0.3, filter_type='lp', ftype='fir')#
Parameters:
  • fs (float) – sampling frequency

  • cutoff (float) – frequency cutoff

  • n_decimate (int) – how many times the signal will be downsampled before the low frequency filtering

  • n_order (int) – n-th order filter used for filtration

  • dec_cutoff (float) – relative frequency at which the signal will be filtered when downsampled

  • filter_type (str) – ‘lp’ or ‘hp’

  • ftype (str) – ‘fir’ or ‘iir’

LFFilter = LowFrequencyFilter(fs=fs, cutoff=cutoff_low, n_decimate=2, n_order=101, dec_cutoff=0.3, filter_type='lp')
X_inp = np.random.randn(1e4)
X_outp = LFilter(X_inp)
decimate(X)#

Apply anti-aliasing filter and downsample signal by factor of 2.

Parameters:

X (numpy.ndarray) – Input signal

Returns:

Downsampled signal

Return type:

numpy.ndarray

design_filters()#

Design decimation and filtering coefficients based on filter type (FIR or IIR).

filter_signal(X)#

Apply low-frequency filter using decimation/upsampling strategy.

Parameters:

X (numpy.ndarray) – Input signal

Returns:

Filtered signal

Return type:

numpy.ndarray

upsample(X)#

Upsample signal by factor of 2 using zero-insertion and filtering.

Parameters:

X (numpy.ndarray) – Input signal

Returns:

Upsampled signal

Return type:

numpy.ndarray

brainmaze_utils.signal.PSD(x: ndarray, fs: float, nperseg=None, noverlap=0, nfft=None)#

Estimates PSD of an input signal or signals using Welch’s method. If nperseg is None, the spectrum is estimated from the whole signal in a single window.

Parameters:
  • x (np.ndarray) – A single signal with a shape (n_samples) or set of signals with a shape (n_signals, n_shapes)

  • fs (float) – Sampling frequency

  • nperseg (int) – Number of samples for a segment

  • noverlap (int) – Number of overlap samples.

Returns:

  • freq (np.ndarray) – Frequency axis for estimated PSD

  • psd (np.ndarray) – Power spectral density estimate

brainmaze_utils.signal.buffer(x: ndarray, fs: float = 1, segm_size: float = None, overlap: float = 0, drop: bool = True)#

Buffer signal into matrix

Parameters:
  • x (np.ndarray) – Signal to be

  • fs (float) – Sampling frequency

  • segm_size (float) – Segment size in seconds

  • overlap (float) – Overlap size in seconds

  • drop (bool) – Drop last segment if True, else append zeros

Returns:

buffered_signal

Return type:

np.ndarray

brainmaze_utils.signal.decimate(x, fs, fs_new, cutoff=None, datarate=False)#

Downsample signal with anti-aliasing filter (Butterworth - 16th order). Works for signals with NaN values - replaced by zero. Can return also data-rate. Can take matrix where signals are stacked in 0th dim.

Parameters:
  • x (np ndarray) – shape[n_signal, n_sample], shape[n_sample] - can process multiple signals.

  • fs (float) – Signals fs

  • fs_new (float) – Downsample to fs_new

  • cutoff (float) – Elective cutoff freq. of anti-alias. filter. By default 2/3 of 0.5*fs_new

  • datarate (bool) – If return datarate of signals

Return type:

numpy ndarray / tuple

brainmaze_utils.signal.detrend(y, x=None, y2=None)#

Detrends the input signal by removing the linear trend.

Parameters:
  • y (numpy.ndarray) – The input signal to be detrended.

  • x (numpy.ndarray, optional) – The x-values corresponding to the y-values. If None, a linear space is used.

  • y2 (numpy.ndarray, optional) – An additional signal to be detrended using the same trend as y.

Returns:

  • numpy.ndarray – The detrended signal.

  • tuple of numpy.ndarray – The detrended signals if y2 is provided.

brainmaze_utils.signal.downsample_min_max(signal: ndarray, original_fs: float, final_fs: float) tuple[ndarray, float]#

Downsamples an iEEG signal using the min-max method, preserving the temporal order of min and max values within each downsampling window.

The method processes the input signal in non-overlapping windows. For each window, it finds the minimum and maximum values and their original temporal order. These two values (min and max) are then placed in the output signal in their temporal order of appearance within the window.

Parameters:
  • signal (np.ndarray) – The input iEEG signal. Can be 1D (samples,) or 2D (channels, samples).

  • original_fs (float) – The original sampling rate of the signal in Hz.

  • final_fs (float) – The desired final sampling rate of the output points in Hz. Since each original window produces two points (a min and a max), the number of original signal windows processed per second is final_fs / 2.

Returns:

  • np.ndarray: The downsampled iEEG signal. If the input was 1D,

    the output is 1D. If 2D, output is 2D.

  • float: The actual final sampling rate of the output signal in Hz.

    This will be close to the requested final_fs but may differ slightly due to integer window sizes.

Return type:

tuple[np.ndarray, float]

Raises:
  • TypeError – If the input signal is not a NumPy array.

  • ValueError – If signal dimensions are incorrect, sampling rates are not positive, or if final_fs implies a window_size less than 1.

Note

The signal is processed in full windows. Any remaining samples at the end of the signal that do not form a complete window are ignored.

brainmaze_utils.signal.fft_filter(X: ndarray, fs: float, cutoff: float, type: str = 'lp')#

FFT filter

Parameters:
  • X (numpy.ndarray)

  • fs (float)

  • cutoff (float)

  • type (str) – ‘lp’ or ‘hp’

Return type:

numpy.ndarray

brainmaze_utils.signal.find_peaks(y)#

Finds the peaks in a given signal.

Parameters:

y (numpy.ndarray) – The input signal in which to find peaks.

Returns:

  • position (numpy.ndarray) – The positions of the peaks in the input signal.

  • value (numpy.ndarray) – The values of the peaks in the input signal.

brainmaze_utils.signal.get_datarate(x)#

Calculates datarate based on NaN values

Parameters:

x (numpy ndarray / list)

Returns:

  • numpy ndarray

  • flaot values 0-1 with relative NaN count per signal.

brainmaze_utils.signal.nandecimate(x, fs, fs_new, cutoff=None, datarate=False)#

Downsample signal with anti-aliasing filter (Butterworth - 16th order). Works for signals with NaN values - replaced by zero. Can return also data-rate. Can take matrix where signals are stacked in 0th dim.

Parameters:
  • x (np ndarray) – shape[n_signal, n_sample], shape[n_sample] - can process multiple signals.

  • fs (float) – Signals fs

  • fs_new (float) – Downsample to fs_new

  • cutoff (float) – Elective cutoff freq. of anti-alias. filter. By default 2/3 of 0.5*fs_new

  • datarate (bool) – If return datarate of signals

Return type:

numpy ndarray / tuple

brainmaze_utils.signal.resample(x, fsamp_orig, fsamp_new)#

Resample a signal from an old sampling frequency to a new sampling frequency. Works with nans.

Parameters:
  • x (numpy.ndarray) – The input signal to be resampled.

  • fsamp_orig (float) – The original sampling frequency of the signal.

  • fsamp_new (float) – The new sampling frequency to resample the signal to.

Returns:

The resampled signal.

Return type:

numpy.ndarray

brainmaze_utils.signal.unify_sampling_frequency(x: list, sampling_frequency: list, fs_new=None) tuple#

Takes list of signals and list of frequencies and downsamples to the same sampling frequency. If all frequencies are same and fs_new is not specified, no operation performed. If not all frequencies are the same and fs_new is not specified, downsamples all signals on the lowest fs present in the list. If fs_new is specified, signals will be processed and downsampled on that frequency. If all sampling frequencies == fs_new, nothing is performed.

Parameters:
  • x (list) – list of numpy signals for downsampling

  • sampling_frequency (list) – for each signal

  • fs_new (float) – new sampling frequency

Return type:

tuple - (numpy ndarray, new_freq)