Preprocessing.jl
This module implements preprocessing for EEG data.
See also Processing.jl
Methods
| Function | Description |
|---|---|
Eegle.Preprocessing.resample | resample EEG data |
Eegle.Preprocessing.standardize | standardize EEG data |
Eegle.Preprocessing.removeChannels | remove channels from EEG data |
Eegle.Preprocessing.removeSamples | remove samples from EEG data |
Eegle.Preprocessing.embedLags | lag embedding of EEG data |
📖
StatsBase.standardize — Function
function standardize(X::AbstractArray{T};
robust::Bool = false,
prop::Real = 0.2)
where T<:RealStandardize the whole $T×N$ EEG recording X, where $T$ and $N$ denotes the number of samples and channels (sensors), respectively, using:
- the arithmetic mean and standard deviation of all data in
Xifrobustis false (default) - the Winsorized (trimmed) mean and standard deviation of all data in
Xifrobustis true.
The trimmed statistics are computed excluding the prop proportion of data at both sides (default=0.2), thus, prop is used only if robust is true.
Example
using Eegle # or using Eegle.Preprocessing
X = randn(1024, 19) # 1024 samples, 19 sensors
stX = standardize(X)
stX = standardize(X; robust=true, prop=0.1)DSP.Filters.resample — Function
function resample( X::AbstractMatrix{T},
sr::S,
rate::Union{T, S, Rational};
Nϕ::Integer = 32,
rel_bw::Float64 = 1.0,
attenuation::Int = 60,
stim::Union{Vector{S}, Nothing} = nothing)
where {T<:Real, S<:Int}Resampling of an EEG data matrix using the polyphase FIR filter with Kaiser window filter taps, as per the resample method in DSP.jl.
Arguments
X: the $T×N$ EEG matrix, where $T$ and $N$ denotes the number of samples and channels (sensors), respectivelysr: the original sampling rate ofXrate: the resampled data will have sampling ratesr*rate.
Optional Keyword Arguments
Nϕ,rel_bwandattenuation: see resamplestim: a stimulation vector. If it is passed, it will be resampled so as to match the resampling ofXas precisely as possible.stimmust be a vector of $T$ integers.
If you need to work with individual trials (or epochs), do not resample trials individually; rather, resample the whole EEG recording and then extract the trials — see Eegle.ERPs.trials. Function Eegle.InOut.readNY allows to read data, do resampling and extract trials at once.
Downsampling must always be preceeded by low-pass filtering to ensure the suppression of energy above the Nyquist frequency ($s/2$), where $s$ is the new sampling rate after downsampling. The cut-off frequency for the filter is usually taken as $s/3$ and a sharp filter is used (see examples). This applies also if you wish to apply downsampling by decimation — see the examples for decimating in Eegle.Miscellaneous.remove and removeSamples.
Return the resampled data matrix.
Examples
using Eegle # or using Eegle.Preprocessing
sr = 512
X = randn(sr*10, 19)
# to downsample by a factor 4, low-pass filter at s/3 = sr/(4*3) Hz
Z = filtfilt(X, sr, Bandpass(1, sr/(4*3)); designMethod = Butterworth(8))
Y = resample(Z, sr, 1//4) # 1//4 is Julia rational number 1/4
# upsample by a factor 2, i.e., double the sampling rate
Y = resample(X, sr, 2)
# upsample to 128 samples per second
sr = 100
X = randn(sr*10, 19)
Y = resample(X, sr, 128/sr) Eegle.Preprocessing.removeChannels — Function
function removeChannels(X::AbstractMatrix{T},
what::Union{Int, Vector{S}},
sensors::Vector{String})
where {T<:Real, S<:Int}
Remove one or more channels, i.e., columns, from the $T×N$ EEG recording X, where $T$ and $N$ denotes the number of samples and channels (sensors), respectively, and remove the corresponding elements from sensors, the provided associated vector of $N$ sensor labels.
For the use of kwarg what, see method Eegle.Miscellaneous.remove, which can be used instead of this function if you do not need to remove channels from a sensor labels vector.
Return the 3-tuple (newX, s, ne), where newX is the new EEG recording, s is the new sensor labels vector and ne is the new number of channels (sensors) in newX.
See Also Eegle.InOut.readSensors
Examples
using Eegle # or using Eegle.Preprocessing
X = randn(128, 7)
sensors = ["F7", "F8", "C3", "Cz", "C4", "P7", "P8"]
# remove second channel
X_, sensors_, ne = removeChannels(X, 2, sensors)
# remove the first five channels
X_, sensors_, ne = removeChannels(X, collect(1:5), sensors)
# remove the channel labeled as "Cz" in `sensors`
X_, sensors_, ne = removeChannels(X, findfirst(x->x=="Cz", sensors), sensors)
# remove the channels labeled as "C3", "Cz", and "C4" in `sensors`
X_, sensors_, ne = removeChannels(X, findall(x->x∈("Cz", "C3", "C4"), sensors), sensors)
# keep only channels labeled as "C3", "Cz", and "C4" in `sensors`
X_, sensors_, ne = removeChannels(X, findall(x->x∉("Cz", "C3", "C4"), sensors), sensors)Eegle.Preprocessing.removeSamples — Function
function removeSamples( X::AbstractMatrix{T},
what::Union{Int, Vector{S}},
stim::Vector{S})
where {T<:Real, S<:Int}
Remove one or more samples, i.e., rows, from the $T×N$ EEG recording X, where $T$ and $N$ denotes the number of samples and channels (sensors), respectively, and remove the corresponding elements from stim, the associated stimulation vector.
For the use of kwarg what, see method Eegle.Miscellaneous.remove, which can be used instead of this function if you do not need to remove tags from a stimulation vector.
Print a warning if elements in what correspond to non-zero tags in stim.
Return the 3-tuple (newX, s, ne), where newX is the new data, s is the new stimulation vector and ns is the new number of samples in newX.
Examples
using Eegle
sr, ne = 256, 7
X = randn(sr, ne)
stim = rand(0:3, sr)
# remove second sample
X_, stim_, ns = removeSamples(X, 2, stim)
# remove the first 128 samples
X_, stim_, ns = removeSamples(X, collect(1:128), stim)
# remove every other sample (decimation by a factor of 2)
X_, stim_, ns = removeSamples(X, collect(1:2:length(stim)), stim)
# NB: before decimating the data must be low-pass filtered,
# see the documentation of `resample`Eegle.Preprocessing.embedLags — Function
function embedLags( X::AbstractMatrix{T},
lags = 0)
where T<:Real Lag embedding (or delay embedding) is a technique to augment the data. Second-order statistics of the augmented data, that is, covariance or cross-spectral matrices, hold information not only of volume conduction and instantaneous connectivity, but also of lagged connectivity. These matrices can be used, for example, in blind source separation and Riemannian classification.
Lag embedding is employed in chaos theory for studying dynamical systems by means of recurrence analysis — see package DelayEmbeddings.jl for advanced delay embedding techniques.
If lags = 0 (default), return X (no lag embedding).
Tutorials xxx, xxx
Description
Given the $T×N$ EEG recording X, where $T$ and $N$ denotes the number of samples and channels (sensors), respectively, and $L>0$ lags, the $T×N(L+1)$ lag-embedded data matrix is
\[X_{\text{lags}} = \left[ X^{(0)} \;\; X^{(1)} \;\; \cdots \;\; X^{(L)} \right],\]
where, letting $\mathbf{0}_{A \times B}$ the $A \times B$ matrix of zeros, for each $l = 0, \ldots, L$, the $T×N$ lagged partition $X^{(l)}$ is defined as
\[X^{(l)} = \left[ \begin{matrix} \mathbf{0}_{(L - l) \times N} \\ X[1:(T - L), \: :] \\ \mathbf{0}_{l \times N} \end{matrix} \right].\]
Notice that the are no zeros appended to the first partition and no zeros prepended to the last partition. Notice also that the lag-embedded data has the same size of the input, however the last $L$ samples are lost.
Return the $T×N(L+1)$ lag-embedded data matrix $X_{\text{lags}}$.
Example
using Eegle # or using Eegle.Preprocessing
X = randn(8, 2) # small example to see the effect
elX = embedLags(X, 3)