Skip to content

第8章: 自分のデータに適用する

第1章から第7章までのすべてを、あなた自身の .edf 記録に適用します。このノートブックはすべてあなたのマシン上で完結して動作します。以下の EDF_PATH だけを編集してください。ここでの処理は、あなたのデータをどこにもアップロードも送信もしません。

あなたのファイルに特有の、あらかじめ確認済みの癖(以前の確認結果より、以下ですでに対応済みです):

  • 32個のEEGチャンネルがあり、CPz を基準として、EEG Fp1-CPz のような名前が付いている — 標準モンタージュを適用する前に名前の変更が必要(第3章)。
  • 乳様突起電極 M1/M2 を含む。
  • サンプリングレート1000 Hz、記録時間約944秒。
  • raw.annotations には Impedance ... のようなエントリが含まれていた — これらはアンプのインピーダンスチェックであり、タスクイベントではない。エポック化に意味を持たせるには、まず自分の本当の刺激/反応トリガーがどのようなものかを確認する必要がある(改めて新鮮な目で raw.annotations を確認するか、記録を行った人に使用されたマーカー方式について尋ねること)。
import mne
import matplotlib.pyplot as plt
import re

%matplotlib inline
mne.set_log_level("WARNING")

1. 読み込み(第3章)

EDF_PATH = r"PUT_YOUR_FILE_PATH_HERE.edf"  # <-- この行を編集する

raw = mne.io.read_raw_edf(EDF_PATH, preload=True)
raw

2. 確認

print("チャンネル名:", raw.ch_names)
print("サンプリングレート (Hz):", raw.info["sfreq"])
print("記録時間 (秒):", raw.times[-1])
print("アノテーション:", raw.annotations)

3. チャンネル名の変更とモンタージュの適用(第3章)

EEG という接頭辞と -CPz という基準の接尾辞を取り除き、チャンネル名を標準の10-20名(EEG Fp1-CPzFp1)に合わせます。これはあくまでラベルの修正であり、元の信号やその基準を変えるものではありません。

raw.rename_channels(lambda name: re.sub(r"^EEG\s+", "", name).split("-")[0])
print(raw.ch_names)

montage = mne.channels.make_standard_montage("standard_1020")
raw.set_montage(montage, on_missing="warn")

4. 可視化と不良チャンネルのマーク(第3章)

raw.plot(n_channels=20, duration=10, scalings="auto")
plt.show()
raw.info["bads"] = []  # <-- 上で気づいた不良チャンネルの名前があればここに記入する

5. フィルタリング(第4章)

LINE_FREQ = 50  # <-- あなたの地域の商用電源が60 Hzなら60に設定する

raw_filt = raw.copy().filter(l_freq=1.0, h_freq=40.0)
raw_filt.notch_filter(freqs=LINE_FREQ)

raw_filt.compute_psd(picks="eeg").plot()
plt.show()

6. ICAによるアーティファクト除去(第5章)

あなたのファイルには専用のEOGチャンネルがないため、目視確認に頼ります。強く左右対称な、前頭部のトポグラフィを持つ成分(典型的なまばたきの特徴)を探してください。

ica = mne.preprocessing.ICA(n_components=15, random_state=97, max_iter="auto")
ica.fit(raw_filt)
ica.plot_components()
plt.show()
ica.plot_sources(raw_filt)
plt.show()
ica.exclude = []  # <-- 除去したい成分のインデックスを記入する。例: [0, 3]

raw_clean = raw_filt.copy()
ica.apply(raw_clean)

raw_clean.plot(n_channels=20, duration=10, scalings="auto")
plt.show()

7. イベントを見つける(第6章)

続ける前に、ここで一度立ち止まってしっかり確認してください。 以前の確認で、あなたの raw.annotations にはインピーダンスチェックのマーカーが含まれており、本当のタスクイベントではないことがわかっています。下のセルを実行して、event_id に実際に何が入っているかを確認してください。もしインピーダンス/セットアップのマーカーしか入っていない場合、本当のトリガーは別の場所(ステータス/トリガーチャンネルか、実験ソフトウェアの別のログファイル)にあるはずなので、エポック化に意味を持たせる前に、このステップを調整する必要があります。

events, event_id = mne.events_from_annotations(raw_clean)
print("見つかったイベントコード:", event_id)
print("イベント数:", len(events))

8. エポック化(第6章)

本当の条件ラベルがわかったら、下の event_id を、あなたが本当に関心のある条件だけに調整してください(例: event_id={"stimulus/target": 1})。また、あなたの実験デザインに合わせて tmin/tmax も調整してください。

epochs = mne.Epochs(
    raw_clean,
    events,
    event_id=event_id,
    tmin=-0.2,
    tmax=0.8,
    baseline=(-0.2, 0.0),
    preload=True,
    reject=None,  # 典型的な振幅を確認したら、ピーク・ツー・ピークのしきい値を追加する。例: dict(eeg=150e-6)
)
epochs

9. ERPへの平均化(第7章)

evoked = epochs.average()
evoked.plot()
plt.show()
# 本当の、意味のある条件ラベルが手に入ったら、次のように比較する:
# evoked_condA = epochs["real_label_a"].average()
# evoked_condB = epochs["real_label_b"].average()
# mne.viz.plot_compare_evokeds({"condition A": evoked_condA, "condition B": evoked_condB})

ここから先へ

これを実行しながら、各ステップで観察したこと(チャンネル名、イベントラベル、エポック数、プロットの見た目)を、テキスト/印刷された出力のみで(データファイルそのものは決して共有せずに)説明してください。そうすれば一緒にデバッグと改善を進められます。本当のイベントが正しく組み込まれ、妥当なERPが得られるようになったら、次の自然なステップは、特定の成分のピークを測定すること(第7章の get_peak())、条件を正しく比較すること、そして最終的には正式な統計(第7章で軽く触れた mne.stats)へ進むことです。