بنقرة واحدة
comb-filter
Multi-harmonic comb filter — remove power-line fundamental + all harmonics in one pass
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Multi-harmonic comb filter — remove power-line fundamental + all harmonics in one pass
التثبيت باستخدام 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 | comb_filter |
| description | Multi-harmonic comb filter — remove power-line fundamental + all harmonics in one pass |
| layer | L3 |
| group | filter |
| metadata | {"tags":["operator","filter","comb","powerline","harmonics"],"modalities":["eeg","meg","seeg","ecog","fnirs"],"step_string":"comb","analysis_goal_allowed":["classification","feature_extraction","clinical_screening","exploratory","generic","online_inference"],"analysis_goal_forbidden":["phase_amplitude_coupling"]} |
A single-pass digital comb filter that creates equispaced notches at a
fundamental frequency (e.g., 50 Hz) and all its integer harmonics
up to Nyquist (100, 150, 200, ... 50 · k Hz). Cheaper than chaining 5–10
notch_filter calls, and the harmonic alignment guarantees that the
notch widths are uniformly Q-bound.
Input / Output: (n_channels, n_times) → same shape.
A digital comb (notch-mode) with fundamental f0 and N harmonics is
H(z) = (1 − r^N · z^(−N)) / (1 − r · z^(−1)) # band-stop variant
implemented via scipy.signal.iircomb(w0=f0/(sfreq/2), Q=Q, ftype="notch").
The Q parameter sets the notch width — higher Q is a sharper notch
(less neighbour bleeding) but rings longer.
Zero-phase is enforced via filtfilt.
comb:{f0},{Q}
| Parameter | Type | Default | Description |
|---|---|---|---|
f0 | float | 50.0 | Fundamental frequency (50 EU / 60 US). |
Q | float | 30.0 | Notch sharpness; 20 = wider, 50 = tighter. |
max_harmonics (kw) | int | None | Stop after N harmonics; default = up to Nyquist. |
| Modality | Q | Notes |
|---|---|---|
| EEG | 30 | Standard line-noise removal; minimal alpha/beta impact. |
| MEG | 30 | SQUID baseline; line noise dominant. |
| sEEG | 25 | High-gamma analysis: keep Q moderate so 100 / 150 Hz notch doesn't drink into the analysis band. |
| fNIRS | n/a | Hemodynamic band has no line noise. |
Hard exclusion for phase_amplitude_coupling: comb's harmonic notches
land at frequencies that may be the PAC carrier; use selective notch:f0
on the fundamental only instead.
Use when: line noise + many harmonics dominate; you want one-pass cleanup; downstream is classification / ERP / band-power.
Don't use when: PAC / cross-frequency analysis (use single notch); the harmonic frequencies coincide with paradigm-relevant content (SSVEP at 25/50/75 Hz hits 50 Hz fundamental).
bandpass to avoid notch side-lobes folding into the
analysis band.| Failure | Symptom | Detection |
|---|---|---|
| Notch too wide (Q low) | Visible dip in PSD around f0 ± 2 Hz. | Compute PSD; if mean(PSD[f0-2:f0+2]) < 0.7 * neighbour raise warning. |
| Harmonic above signal of interest | SSVEP / response peaks attenuated. | If SSVEP paradigm + f0 divides response → log warning. |
| Recording too short | Edge transients dominate. | If n_t · sfreq / 1000 < 50 · Q / f0 raise recoverable. |
notch:60 if
US power, or notch_filter:50,Q=50 (high-Q single notch).from __future__ import annotations
import numpy as np
from scipy.signal import iircomb, filtfilt
def comb_filter(
data: np.ndarray, sfreq: float, f0: float = 50.0, Q: float = 30.0
) -> np.ndarray:
"""Multi-harmonic notch via digital comb."""
w0 = f0 / (sfreq / 2)
if w0 >= 1.0:
raise ValueError(f"comb: f0={f0} >= Nyquist {sfreq/2}")
b, a = iircomb(w0, Q, ftype="notch", fs=sfreq)
return filtfilt(b, a, data, axis=-1, padtype="even").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_comb(
data_dict: Dict[str, Any], *, f0: float = 50.0, Q: float = 30.0,
) -> Dict[str, Any]:
"""Multi-harmonic comb notch.
Parameters
----------
data_dict : dict
OperatorIO.
f0 : float
Fundamental frequency (default 50.0 Hz).
Q : float
Notch sharpness (default 30.0).
Returns
-------
dict
OperatorIO with line-noise + harmonics removed.
Raises
------
EasyBCIOperatorError
recoverable=True for f0 >= Nyquist.
Modality coverage
-----------------
EEG / MEG / sEEG / ECoG: yes.
fNIRS: no (no line noise in hemodynamic band).
PAC tasks: forbidden — use selective `notch:f0` instead.
References
----------
Mitra & Bokil 2007 — comb filter for line noise harmonics.
"""
sfreq = float(data_dict["frequency"])
if f0 >= sfreq / 2:
raise EasyBCIOperatorError(
operator="comb", reason=f"f0={f0} >= Nyquist {sfreq/2}",
recoverable=True, fallback_step=f"notch:{f0}",
)
t0 = time.monotonic()
from scipy.signal import iircomb, filtfilt
w0 = f0 / (sfreq / 2)
b, a = iircomb(w0, Q, ftype="notch", fs=sfreq)
new_data = filtfilt(b, a, data_dict["data"], axis=-1, padtype="even").astype(
data_dict["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", {}), "comb": {"f0": f0, "Q": Q}}
record_step_elapsed("comb", elapsed, (data_dict.get("meta") or {}).get("step_cache_key"))
return out