ワンクリックで
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