Initialize NeuroAnalyzer
using NeuroAnalyzer
using Plots
eeg = load("files/eeg.hdf")using NeuroAnalyzer
using Plots
eeg = load("files/eeg.hdf")Independent Component Analysis (ICA) is a computational technique used to separate a complex signal like EEG into statistically independent subcomponents. ICA helps isolate artifacts (e.g., eye blinks, muscle activity) and neural sources from mixed EEG signals, enabling cleaner data for further analysis.
Key Concepts
Why Use ICA for EEG?
Understand the ICA Model
The relationship is:
\[ X = A \cdot S \]
where:
\(X\) is the original signal (10×2560),
\(A\) is the mixing matrix (10×5),
\(S\) is the matrix of independent components (5×2560).
Component Types
Component Selection Criteria
Common Artifacts
| Artifact Type | Characteristics |
|---|---|
| Eye Blinks | Frontal topography, low frequency (1-4 Hz) |
| Eye Movements | Lateral topography, low frequency |
| Muscle Activity | High frequency (20-60 Hz), temporal sites |
| Line Noise | Narrow peak at 50/60 Hz |
| ECG/Heartbeat | Periodic, ~1 Hz, often at temporal sites |
Data Requirements
ICA Parameters
tanh usually works well for EEG dataTroubleshooting
Validation
ICA vs PCA vs Other Methods
| Method | Type | Independence | Use Case |
|---|---|---|---|
| ICA | Blind Source Separation | Statistical independence | Artifact removal, source separation |
| PCA | Dimensionality Reduction | Uncorrelated components | Noise reduction, feature extraction |
| SSD | Source Separation | Spatially smooth sources | Blink/eye movement detection |
| Beamforming | Source Localization | Spatial filters | Source localization |
Key Differences:
Studying Brain Networks
Event-Related Potentials (ERPs)
Oscillatory Dynamics
Step 1: Decomposition
Deconstructing all EEG channels into defined number (3) of components:
ic, ic_mw, ic_var = ica_decompose(eeg, ch = "eeg", n = 3)ic is the matrix of independent components and ic_mw is the mixing matrix.
Components are sorted in the order of decreasing variance (ic_var) accounted for (the higher the value, the higher the component accounts for all the data).
By default, 100 iterations per each tolerance value ([0.000001, 0.00001, 0.0001, 0.001, 0.01, 0.1, 0.5, 0.9, 0.99]); hence the default 100 iterations gives 900 steps.
Step 2: Component Selection
Sort components by variance explained (higher = more significant).
println("Variance explained by each component: ", round.(ic_var, digits=2))Step 3: Reconstruction
To remove ICA (Independent Component Analysis) components from your EEG signal, you need to reconstruct the original signal without the unwanted components. Here’s a step-by-step explanation of the process:
Reconstruct the Signal Without Specific Components
To remove a component (say, component \(i\)), you set its row in \(S\) to zero and reconstruct \(X\):
\[ X_{\text{reconstructed}} = A \cdot S_{\text{modified}} \]
where \(S_{\text{modified}}\) is the matrix \(S\) with the \(i\)-th row set to zero.
Practical Steps
Result
The reconstructed signal \(X_{\text{reconstructed}}\) will be a 10×2560 matrix, just like your original signal, but with the unwanted components removed.
Reconstructing the source signal without a specific component(s):
ica_remove!(eeg,
ch = "eeg",
ic = ic,
ic_mw = ic_mw,
ic_idx = [1, 3])To reconstruct the source signal keeping only the selected component(s), use keep=true option:
ica_remove!(eeg,
ch = "eeg",
ic = ic,
ic_mw = ic_mw,
ic_idx = 1,
keep = true)which is equivalent to
ica_remove!(eeg,
ch = "eeg",
ic = ic,
ic_mw = ic_mw,
ic_idx = [2, 3])Plotting the first components:
ica1 = ic[1, :]
NeuroAnalyzer.plot(eeg.time_pts,
ica1)Plot the first component power spectrum:
psd_data = psd(ica1, fs = sr(eeg), db = true)
NeuroAnalyzer.plot_psd(psd_data.f,
psd_data.p,
xlabel = "Frequency [Hz]",
ylabel = "Power [dB]")Plot the first component spectrogram:
spec_data = spectrogram(ica1, fs = sr(eeg), db = true)
NeuroAnalyzer.plot_spectrogram(spec_data.t,
spec_data.f,
spec_data.p,
xlabel = "Time [s]",
ylabel = "Frequency [Hz]")EEG has already been filtered at 1 Hz and 40 hz:
NeuroAnalyzer.plot(eeg,
ch="all",
gui = false)Decompose all channels:
ic, ic_mw, ic_var = ica_decompose(eeg, ch = "all", n = 5)Preview the first component:
ica1 = ic[1, :]
t1 = t2s(eeg, t = 0)
t2 = t2s(eeg, t = 10)
NeuroAnalyzer.plot(eeg.time_pts[t1:t2],
ica1[t1:t2])Removing the first component:
eeg_clean = ica_remove(eeg,
ch = "all",
ic = ic,
ic_mw = ic_mw,
ic_idx = 1)Comparing the original and processed signals:
NeuroAnalyzer.plot(eeg,
eeg_clean,
ch="all",
gui = false)