بنقرة واحدة
regression-eog
Regression-based EOG removal — fast online ocular artifact suppression
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Regression-based EOG removal — fast online ocular artifact suppression
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Neurodata Without Borders (.nwb) — the de-facto standard for in-vivo electrophysiology (Neuropixels / AIBS / DANDI / IBL)
Index of L0 data-format loader skills by family
Index of all L2 paradigm skills by group + analysis_goal → paradigm matrix
Two-phase BCI data preprocessing pipeline: deep-inspect → plan → propose → user confirm → automated code/execute/QC/export
BIDS-iEEG sidecar (*_channels.tsv / *_electrodes.tsv / *_coordsystem.json / *_ieeg.json) — clinical sEEG / ECoG standard
Multiscale Electrophysiology Format v3 (Mayo Clinic) — long-duration encrypted sEEG
| name | regression_eog |
| description | Regression-based EOG removal — fast online ocular artifact suppression |
| layer | L3 |
| group | adaptive_cleaning |
| metadata | {"tags":["operator","adaptive_cleaning","regression","eog","gratton","fast","online"],"modalities":["eeg","meg"],"step_string":"regression_eog","analysis_goal_allowed":["classification","source_localization","feature_extraction","clinical_screening","exploratory","generic","connectivity","online_inference"],"analysis_goal_forbidden":[]} |
Linear regression of EOG channels out of EEG/MEG channels. Faster than ICA / SSP, no labelled events needed — the de-facto online BCI choice when an EOG channel is present. Originally Gratton et al. 1983.
Input / Output: (n_channels, n_times) → (n_channels, n_times) with
EOG-related variance removed.
β_c = argmin || data[c] − β · eog ||²
out[c] = data[c] − β_c · eog
Optionally per-band (Croft & Barry 2000): bandpass first, then regress per band.
regression_eog:{eog_ch}
| Parameter | Type | Default | Description |
|---|---|---|---|
eog_ch | str | "EOG" | EOG channel substring. |
band (kw) | tuple | None | Optional per-band regression. |
EEG: standard. MEG: viable (cardiac too via separate channel). sEEG / ECoG / fNIRS / spike: forbidden (no EOG analog).
Use when: online BCI; latency-critical; EOG channel present.
Don't use when: no EOG; PAC / connectivity require very precise preservation (use SSP or ICA).
| Failure | Symptom | Detection |
|---|---|---|
| EOG missing | KeyError. | Pre-check; raise recoverable. |
| Cross-talk overcorrection | Frontal EEG flattened. | If frontal alpha drop > 30% warn. |
from __future__ import annotations
import numpy as np
def regression_eog(
data: np.ndarray, eog_idx: int,
) -> np.ndarray:
"""Linear regression of EOG out of EEG."""
eog = data[eog_idx]
out = data.copy()
eog_var = float(np.var(eog)) + 1e-30
for c in range(data.shape[0]):
if c == eog_idx: continue
beta = float(np.dot(data[c], eog)) / (eog_var * data.shape[1])
out[c] = data[c] - beta * eog
return out.astype(data.dtype, copy=False)
from typing import Any, Dict
import time
import numpy as np
from easybci_lib.tools.neural_processing.operator_errors import EasyBCIOperatorError
from easybci_lib.tools.neural_processing.preprocess.step_cache import record_step_elapsed
def operator_regression_eog(
data_dict: Dict[str, Any], *, eog_ch: str = "EOG",
) -> Dict[str, Any]:
"""Regression-based EOG removal.
Parameters
----------
data_dict : dict
eog_ch : str
Returns
-------
dict — cleaned data.
Raises
------
EasyBCIOperatorError
recoverable=True if EOG channel absent.
Modality coverage
-----------------
EEG / MEG: yes. Others: forbidden.
References
----------
Gratton et al. 1983; Croft & Barry 2000.
"""
channels = data_dict.get("channels", [])
eog_idx = next((i for i, c in enumerate(channels) if eog_ch.lower() in c.lower()), None)
if eog_idx is None:
raise EasyBCIOperatorError(
operator="regression_eog", reason=f"no channel matching {eog_ch!r}",
recoverable=True, fallback_step="ica",
)
t0 = time.monotonic()
data = data_dict["data"]
eog = data[eog_idx]
eog_var = float(np.var(eog)) + 1e-30
new_data = data.copy()
for c in range(data.shape[0]):
if c == eog_idx: continue
beta = float(np.dot(data[c], eog)) / (eog_var * data.shape[1])
new_data[c] = data[c] - beta * eog
new_data = new_data.astype(data.dtype, copy=False)
elapsed = time.monotonic() - t0
out = dict(data_dict)
out["data"] = new_data
out["elapsed_s"] = elapsed
out["meta"] = {**out.get("meta", {}), "regression_eog": {"eog_ch": eog_ch}}
record_step_elapsed("regression_eog", elapsed, (data_dict.get("meta") or {}).get("step_cache_key"))
return out