pyhealth.tasks.eegbci#

Tasks and signal helpers for PhysioNet EEGBCI recordings.

class pyhealth.tasks.eegbci.Any(*args, **kwargs)[source]#

Bases: object

Special type indicating an unconstrained type.

  • Any is compatible with every type.

  • Any assumed to have all methods.

  • All values assumed to be instances of Any.

Note that all the above statements are true from the point of view of static type checkers. At runtime, Any should not be used with instance checks.

class pyhealth.tasks.eegbci.BaseTask(code_mapping=None)[source]#

Bases: ABC

task_name: str#
output_schema: Dict[str, Union[str, Type]]#
input_schema: Dict[str, Union[str, Type]]#
pre_filter(df)[source]#
Return type:

LazyFrame

pyhealth.tasks.eegbci.run_type_for_run(run)[source]#

Return the experimental condition for an EEGBCI run.

Parameters:

run (int) – EEGBCI run identifier.

Return type:

str

Returns:

The experimental condition name.

Raises:

ValueError – If the run is not supported.

Examples

>>> run_type_for_run(3)
'motor_execution_left_right'
pyhealth.tasks.eegbci.label_family_for_run(run)[source]#

Return the execution, imagery, or baseline family for a run.

Parameters:

run (int) – EEGBCI run identifier.

Return type:

str

Returns:

The label family.

Raises:

ValueError – If the run is not supported.

Examples

>>> label_family_for_run(4)
'motor_imagery'
pyhealth.tasks.eegbci.task_label_for_event(run, event_code)[source]#

Decode a T0/T1/T2 annotation using its run context.

Parameters:
  • run (int) – EEGBCI run identifier.

  • event_code (str) – Annotation code such as "T0", "T1", or "T2".

Return type:

str

Returns:

The semantic motor-task label.

Raises:

ValueError – If the run or event code is not supported.

Examples

>>> task_label_for_event(3, "T1")
'execute_left_fist'
pyhealth.tasks.eegbci.numeric_label_for_task(task_label)[source]#

Return the stable PyHealth 0-8 task-class identifier.

Parameters:

task_label (str) – Semantic EEGBCI task label.

Return type:

int

Returns:

The PyHealth task-class identifier.

Raises:

ValueError – If the task label is not supported.

Examples

>>> numeric_label_for_task("imagine_both_feet")
8
pyhealth.tasks.eegbci.normalize_eegbci_channel_name(name)[source]#

Normalize an EDF channel name and known aliases.

Parameters:

name (str) – Source channel name.

Return type:

str

Returns:

The normalized channel name.

Examples

>>> normalize_eegbci_channel_name("EEG C3-REF")
'C3'
pyhealth.tasks.eegbci.select_eegbci_channels(data, ch_names, channel_mode='compat16')[source]#

Select all EEG channels or the compatibility montage.

Parameters:
  • data (ndarray) – EEG data with shape (channels, time).

  • ch_names (List[str]) – Channel names matching the first data dimension.

  • channel_mode (str) – "compat16" or "all".

Return type:

Tuple[ndarray, List[str]]

Returns:

The selected data and corresponding channel names.

Raises:

ValueError – If the mode is invalid or required channels are missing.

Examples

>>> data = np.zeros((len(EEGBCI_COMPAT_CHANNELS), 400))
>>> selected, _ = select_eegbci_channels(
...     data, list(EEGBCI_COMPAT_CHANNELS)
... )
>>> selected.shape
(16, 400)
pyhealth.tasks.eegbci.normalize_signal(signal, mode)[source]#

Apply the configured per-channel signal normalization.

Parameters:
  • signal (ndarray) – EEG signal with time on the final dimension.

  • mode (Optional[str]) – "95th_percentile", "div_by_100", or None.

Return type:

ndarray

Returns:

The normalized signal.

Raises:

ValueError – If the normalization mode is unsupported.

Examples

>>> normalize_signal(np.array([[0.0, 100.0]]), "div_by_100").tolist()
[[0.0, 1.0]]
pyhealth.tasks.eegbci.compute_band_powers(data, sfreq)[source]#

Compute absolute and relative Welch band powers and ratios.

Parameters:
  • data (ndarray) – EEG data with shape (channels, time).

  • sfreq (float) – Sampling rate in hertz.

Return type:

Dict[str, float | str]

Returns:

Band powers, relative powers, ratios, and the dominant band.

Raises:

ValueError – If data is not two-dimensional.

Examples

>>> time = np.arange(400) / 200
>>> signal = np.sin(2 * np.pi * 10 * time)
>>> compute_band_powers(signal[None, :], 200)["dominant_band"]
'alpha'
pyhealth.tasks.eegbci.interpret_band_profile(features)[source]#

Produce cautious exploratory interpretation metadata.

Parameters:

features (Dict[str, float | str]) – Band-power features from compute_band_powers().

Return type:

Dict[str, str]

Returns:

A signal-pattern hypothesis, confidence, quality flags, and summary.

Examples

>>> features = {
...     "dominant_band": "alpha",
...     "alpha_relative": 0.6,
...     "alpha_beta_ratio": 3.0,
... }
>>> interpret_band_profile(features)["brain_state_hypothesis"]
'relaxed_or_idle'
pyhealth.tasks.eegbci.iter_annotation_windows(raw, run, window_size=2.0)[source]#

Convert T0/T1/T2 annotations into complete fixed-duration windows.

Parameters:
  • raw (BaseRaw) – Loaded MNE recording with annotations.

  • run (int) – EEGBCI run identifier used to decode task labels.

  • window_size (float) – Window duration in seconds.

Return type:

List[Dict[str, Any]]

Returns:

Window metadata dictionaries for complete annotation windows.

Raises:

ValueError – If a supported annotation cannot be decoded for the run.

Examples

>>> info = mne.create_info(["C3"], 200, "eeg")
>>> raw = mne.io.RawArray(np.zeros((1, 400)), info, verbose="error")
>>> _ = raw.set_annotations(mne.Annotations([0.0], [2.0], ["T0"]))
>>> len(iter_annotation_windows(raw, run=3))
1
class pyhealth.tasks.eegbci.EEGMotorImageryEEGBCI(window_size=2.0, resample_rate=200, bandpass_filter=(0.5, 45.0), channel_mode='compat16', normalization='95th_percentile', compute_stft=True)[source]#

Bases: BaseTask

Build fixed-duration EEGBCI motor-task samples.

Parameters:
  • window_size (float) – Window duration in seconds.

  • resample_rate (Optional[float]) – Target sampling rate, or None to retain the source rate.

  • bandpass_filter (Optional[Tuple[float, float]]) – Low and high cutoff frequencies, or None to disable filtering.

  • channel_mode (str) – "compat16" for the shared 16-channel montage or "all" for all EEG channels.

  • normalization (Optional[str]) – "95th_percentile", "div_by_100", or None.

  • compute_stft (bool) – Whether to include an STFT tensor.

Each emitted sample includes patient/run/trial metadata, signal, semantic task_label and processor label strings, integer eegbci_label as a PyHealth task-class identifier, channel names, sample rate, and window timing. When enabled, stft is also included.

Examples

>>> task = EEGMotorImageryEEGBCI(compute_stft=False)
>>> task.task_name
'EEGBCI_motor_imagery'
task_name: str = 'EEGBCI_motor_imagery'#
output_schema: Dict[str, str] = {'label': 'multiclass'}#
input_schema: Dict[str, str] = {'signal': 'tensor', 'stft': 'tensor'}#
read_raw(signal_file)[source]#

Load an EDF and apply configured filtering and resampling.

Parameters:

signal_file (str) – EDF file path.

Return type:

BaseRaw

Returns:

The preprocessed MNE recording.

pre_filter(df)#
Return type:

LazyFrame

class pyhealth.tasks.eegbci.EEGBCIPatternDiscovery(window_size=2.0, resample_rate=200, bandpass_filter=(0.5, 45.0), channel_mode='compat16', normalization='95th_percentile', compute_stft=True)[source]#

Bases: EEGMotorImageryEEGBCI

Extend EEGBCI motor-task samples with exploratory band metadata.

Each emitted sample contains the supervised-task fields from EEGMotorImageryEEGBCI plus bandpower, brain_state_hypothesis, confidence, quality_flags, and interpretation. These fields describe signal patterns and are not clinical diagnoses.

Examples

>>> task = EEGBCIPatternDiscovery(compute_stft=False)
>>> task.task_name
'EEGBCI_pattern_discovery'
task_name: str = 'EEGBCI_pattern_discovery'#
input_schema: Dict[str, str] = {'signal': 'tensor', 'stft': 'tensor'}#
output_schema: Dict[str, str] = {'label': 'multiclass'}#
pre_filter(df)#
Return type:

LazyFrame

read_raw(signal_file)#

Load an EDF and apply configured filtering and resampling.

Parameters:

signal_file (str) – EDF file path.

Return type:

BaseRaw

Returns:

The preprocessed MNE recording.