ICA, ICLabel, Rejection, and Visual Diagnostics#
EEGPrep follows the EEGLAB component-review workflow: compute ICA, label components, inspect labels and diagnostic displays, flag likely artifacts, then remove flagged components when review is complete.
Use the Sample ICA Dataset#
The fastest way to learn the workflow is to load the ICA tutorial data:
from pathlib import Path
from eegprep import pop_loadset
EEG = pop_loadset(Path("sample_data") / "eeglab_data_epochs_ica.set")
The GUI equivalent is File > Load existing dataset.
Run ICA When Needed#
For datasets without ICA fields, use Tools > Decompose data by ICA or call:
from eegprep import pop_runica
EEG, com = pop_runica(EEG, icatype="picard", gui=False, return_com=True)
The default GUI offers runica, robust runica, AMICA, and Picard choices. Standalone AMICA requires an AMICA executable configured outside the Python package.
AMICA input uses a channels-by-frames matrix. EEGPrep writes its binary input
as little-endian float32 values, with all channels of each frame together,
matching MATLAB’s runamica15. Versions affected by issue #435 wrote entire channels consecutively,
scrambling the samples read by AMICA. Recompute affected AMICA decompositions
and downstream component labels and rejection decisions from the original data.
Picard accepts EEGLAB’s PCA option through options. A positive value is the
requested component count; a negative value subtracts dimensions from the
selected channel count. For example, options={"pca": -1} computes one
fewer component than channels, which is useful after average referencing. The
initial unmixing matrix is sized to the reduced decomposition while remaining
deterministic.
Picard starts from an identity matrix by default. To choose a reproducible
random starting point, call eeg_picard(EEG, random_state=42) or pass
options={"seed": 42} to pop_runica with icatype="picard".
An explicit w_init matrix takes precedence over the seed. Passing
random_state=None explicitly uses NumPy’s global random state, as in
Python Picard. Different starts can converge to equivalent ICA solutions.
eeg_picard and eeg_runica then scale each component so the RMS of its
mixing column is 1, matching EEGLAB eeg_checkset with
option_scaleicarms on. The unscaled weights and sphere are stored in
EEG["etc"]["icaweights_beforerms"] and
EEG["etc"]["icasphere_beforerms"]. ICLabel uses those scaled activations
and topographies, so label probabilities change if the scale is skipped.
ICLabel Workflow#
Run ICLabel after ICA:
from eegprep import eeg_icalabelstat, pop_icflag, pop_iclabel, pop_subcomp, pop_viewprops
EEG, label_com = pop_iclabel(EEG, "default", return_com=True)
stats = eeg_icalabelstat(EEG, threshold=0.9, verbose=False)
figures = pop_viewprops(EEG, typecomp=0, chanorcomp=[1, 2, 3])
EEG, flag_com = pop_icflag(EEG, return_com=True)
EEG, remove_com = pop_subcomp(EEG, [], return_com=True)
pop_iclabel stores class probabilities in
EEG["etc"]["ic_classification"]["ICLabel"]["classifications"]. The class
order is Brain, Muscle, Eye, Heart, Line Noise, Channel Noise, and Other.
GUI Review#
Choose Tools > Classify components using ICLabel.
Choose Plot > Component properties.
Review scalp maps, activity, spectra, ICLabel probabilities, and any stored DIPFIT projection.
Toggle component rejection marks and press OK.
Inspect EEG["reject"]["gcompreject"],
LASTCOM, and ALLCOM[-1] from
eegprep-console.
Choose Tools > Remove components from data only after review.
Dashboard reject toggles write pending marks to EEG.reject.gcompreject only
when the user presses OK, so GUI review and eegprep-console history remain
synchronized.
Label Statistics#
eeg_icalabelstat mirrors EEGLAB’s threshold-count summary and returns the
same information in a Python dictionary:
stats = eeg_icalabelstat(EEG, threshold=0.9, verbose=False)
print(stats["counts"])
print(stats["component_indices"])
Returned values include per-class counts above threshold, one-based component
indices, mean probabilities, dominant-class counts, and rejected/kept tallies
from EEG.reject.gcompreject.
Flagging Rules#
Use pop_icflag defaults for an EEGLAB-like first pass, or pass a 7-by-2
threshold matrix in ICLabel class order:
import numpy as np
from eegprep import pop_icflag
EEG, com = pop_icflag(
EEG,
threshold=np.array(
[
[0, 0],
[0.8, 1.0],
[0.8, 1.0],
[0, 0],
[0, 0],
[0, 0],
[0, 0],
]
),
return_com=True,
)
Review flags visually before removing components. Automatic labels are a guide, not a replacement for expert inspection.
Visual Diagnostics#
pop_viewprops(EEG, typecomp=0) opens EEGPrep’s native component-property
browser. With ICLabel classifications present, component mode opens the
pop_prop_extended dashboard with scalp map, activity browser, ERP/image
summary, spectrum, class probabilities, component accept/reject controls, and
DIPFIT projections when localized dipoles are already stored in EEG.dipfit.
The activity browser uses EEGLAB-facing one-based component indices and
preserves event display state through the scroll_event option.
Network Availability#
The standalone Python engine ships the default ICLabel network
(netICL.mat). EEGLAB lite and beta network artifacts are not
bundled in the Python package; requesting them with engine=None raises a
clear limitation. They can still be requested through engine="matlab" or
engine="octave" when that runtime has an EEGLAB ICLabel checkout with those
artifacts.