第6章: イベントとエポック化¶
きれいにフィルタ済みの連続データができたので、いよいよそれを短い試行のスニペット(Epochs)に切り出します。ERPに関するすべては、ここから組み立てられています。この章では、イベントの見つけ方と、Epochs を正しく構築する方法を扱います。
import mne
import matplotlib.pyplot as plt
from pathlib import Path
mne.set_log_level("WARNING")
sample_folder = Path(mne.datasets.sample.data_path()) / "MEG" / "sample"
raw = mne.io.read_raw_fif(sample_folder / "sample_audvis_raw.fif", preload=True)
# 刺激チャンネルを削除する前にイベントを見つける -- トリガーを見つけるにはこのチャンネルが必要
events = mne.find_events(raw, stim_channel="STI 014")
raw.pick(["eeg", "eog"])
raw.filter(l_freq=1.0, h_freq=40.0)
print("見つかったイベント数:", len(events))
print(events[:10])
見つかったイベント数: 320
[[27977 0 2]
[28345 0 3]
[28771 0 1]
[29219 0 4]
[29652 0 2]
[30025 0 3]
[30450 0 1]
[30839 0 4]
[31240 0 2]
[31665 0 3]]
イベントを見つける2つの方法¶
第3章で見た通り、イベントは次の2箇所のどちらかにあります。
# 方法1: 専用の刺激/トリガーチャンネル(このデータセット)
events = mne.find_events(raw, stim_channel="STI 014")
# 方法2: ファイルに付随するアノテーション(あなた自身の.edf記録)
events, event_id = mne.events_from_annotations(raw)
どちらの方法でも、最終的に events 配列が得られます。1行が1つのイベントに対応し、列は [sample_number, 0, event_code] です。event_code は単なる整数で、人間にわかりやすい意味は event_id 辞書を通じて付与します。
# このデータセットのイベントコードはMNEによって文書化されている:
event_id = {
"auditory/left": 1,
"auditory/right": 2,
"visual/left": 3,
"visual/right": 4,
"smiley": 5,
"button": 32,
}
fig = mne.viz.plot_events(events, sfreq=raw.info["sfreq"], event_id=event_id)
plt.show()

"auditory/left" のような名前に含まれる / に注目してください。MNEはこれを階層的なものとして扱います。後で epochs["auditory"] とすると auditory/left と auditory/right の両方がまとめて選ばれ、epochs["auditory/left"] とすればその1つだけが選ばれます。これは単に、event_id を作るときにあなたが選ぶ命名規則です。関連する条件をグループ化するために使ってください。
Epochs を作成する¶
mne.Epochs は、すべてのイベントの周辺で固定の時間窓を切り出します。主なパラメータは以下の通りです。
tmin、tmax: イベントを基準とした時間窓の範囲(秒)。例えば-0.2から0.5は、イベントの200ms前から500ms後まで。baseline: 平均値をすべてのチャンネルから差し引く時間窓(通常はイベント前の期間)。任意の電圧オフセットを補正し、エポック同士を比較可能にします。(-0.2, 0.0)が典型的な選択です。reject: チャンネル型ごとのピーク・ツー・ピーク振幅のしきい値を指定する辞書。これを超えるエポックは自動的に破棄されます。ICAで取り切れなかったアーティファクトに対する、大まかながら効果的な第2の防衛線です。preload:Rawの場合と同じ意味で、データを即座に読み込みます。
epochs = mne.Epochs(
raw,
events,
event_id=event_id,
tmin=-0.2,
tmax=0.5,
baseline=(-0.2, 0.0),
preload=True,
reject=dict(eeg=150e-6, eog=250e-6),
)
epochs
| General | ||
|---|---|---|
| MNE object type | Epochs | |
| Measurement date | 2002-12-03 at 19:01:10 UTC | |
| Participant | Unknown | |
| Experimenter | MEG | |
| Acquisition | ||
| Total number of events | 300 | |
| Events counts |
auditory/left: 63
auditory/right: 69 button: 16 smiley: 15 visual/left: 72 visual/right: 65 |
|
| Time range | -0.200 – 0.499 s | |
| Baseline | -0.200 – 0.000 s | |
| Sampling frequency | 600.61 Hz | |
| Time points | 421 | |
| Metadata | No metadata set | |
| Channels | ||
| EEG | and | |
| EOG | ||
| Head & sensor digitization | 146 points | |
| Filters | ||
| Highpass | 1.00 Hz | |
| Lowpass | 40.00 Hz | |
何が除外されたかを確認する¶
reject のしきい値は、汚染されたエポックを自動的に破棄します。どれだけの割合が、なぜ破棄されたのかを必ず確認してください。破棄される試行の割合が大きすぎる場合、しきい値が厳しすぎるか、上流のアーティファクト除去ステップに改善の余地があるサインです。
print(epochs.drop_log_stats(), "% のエポックが除外された")
epochs.plot_drop_log()
plt.show()
6.25 % のエポックが除外された

エポックの選択とブラウズ¶
event_id のラベルを使って条件名でインデックス指定でき、raw.plot() と同じ感覚で個々の試行をブラウズできます。
print("全auditory試行 (leftとrightを合わせたもの):", len(epochs["auditory"]))
print("auditory/leftのみ:", len(epochs["auditory/left"]))
epochs.plot(n_epochs=10, scalings="auto")
plt.show()
全auditory試行 (leftとrightを合わせたもの): 132
auditory/leftのみ: 63

エポックの保存(任意)¶
Epochs オブジェクトの内容に満足したら、保存しておくことで次回パイプライン全体を再実行する手間を省けます。
epochs.save("my-epo.fif", overwrite=True)
epochs = mne.read_epochs("my-epo.fif")
-epo.fif という命名規則は単なる提案ではなく、MNEの要件です。)
まとめ¶
- イベントは、刺激チャンネル(
mne.find_events)かアノテーション(mne.events_from_annotations)のいずれかから得られます。 event_idは、人間にわかりやすい条件名(/で階層化することも可能)を整数コードに対応づけます。mne.Epochs(raw, events, event_id, tmin, tmax, baseline, reject)が、試行のスニペットを切り出してクリーンにします。- 除外しきい値を適用した後は、必ず
epochs.plot_drop_log()を確認してください。
次へ: 第7章 — ERP解析 — これらのエポックを平均してERPそのものを作ります。