第3章: データの読み込みと確認¶
この章では、EEGファイルをMNEに読み込む方法と、処理を始める前に行う価値のあるチェック項目を扱います。あなた自身のファイルに対して行ったのと同じチェックを、ここで詳しく説明します。
ファイル形式とそれぞれの読み込み関数¶
MNEには、ほとんどのEEG/MEGファイル形式に対応した専用のリーダーが用意されています。代表的なものをいくつか挙げます。
| 形式 | 拡張子 | 読み込み関数 |
|---|---|---|
| European Data Format | .edf, .bdf |
mne.io.read_raw_edf |
| BrainVision | .vhdr (+ .vmrk, .eeg) |
mne.io.read_raw_brainvision |
| Neuroscan | .cnt |
mne.io.read_raw_cnt |
| EEGLAB | .set |
mne.io.read_raw_eeglab |
| Neuromag/Elekta/MEGIN (MEG、サンプルデータセットで使用) | .fif |
mne.io.read_raw_fif |
これらはすべて同じ種類のオブジェクト、つまり Raw を返します。そのため、一度読み込んでしまえば、元のファイル形式が何であれ、以降の処理(このチュートリアル全体)はまったく同じように動作します。だからこそ、あなた自身の .edf ファイルと、このサンプルデータセットの .fif ファイルが、同じパイプラインを通せるのです。
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)
raw.pick(["eeg", "eog"])
raw
| General | ||
|---|---|---|
| Filename(s) | sample_audvis_raw.fif | |
| MNE object type | Raw | |
| Measurement date | 2002-12-03 at 19:01:10 UTC | |
| Participant | Unknown | |
| Experimenter | MEG | |
| Acquisition | ||
| Duration | 00:04:38 (HH:MM:SS) | |
| Sampling frequency | 600.61 Hz | |
| Time points | 166,800 | |
| Channels | ||
| EEG | and | |
| EOG | ||
| Head & sensor digitization | 146 points | |
| Filters | ||
| Highpass | 0.10 Hz | |
| Lowpass | 172.18 Hz | |
前処理前のチェックリスト¶
データに手を付ける前に、必ず以下を確認します。 1. チャンネル名とチャンネル型 — 想定通りになっているか? 2. サンプリングレートと記録時間。 3. アノテーション/イベントの有無。 4. 電極位置(モンタージュ)がすでに設定されているか。 5. 目で見て明らかに不良なチャンネルがないか。
print("チャンネル名:", raw.ch_names)
print("チャンネル型:", set(raw.get_channel_types()))
print("サンプリングレート (Hz):", raw.info["sfreq"])
print("記録時間 (秒):", raw.times[-1])
チャンネル名: ['EEG 001', 'EEG 002', 'EEG 003', 'EEG 004', 'EEG 005', 'EEG 006', 'EEG 007', 'EEG 008', 'EEG 009', 'EEG 010', 'EEG 011', 'EEG 012', 'EEG 013', 'EEG 014', 'EEG 015', 'EEG 016', 'EEG 017', 'EEG 018', 'EEG 019', 'EEG 020', 'EEG 021', 'EEG 022', 'EEG 023', 'EEG 024', 'EEG 025', 'EEG 026', 'EEG 027', 'EEG 028', 'EEG 029', 'EEG 030', 'EEG 031', 'EEG 032', 'EEG 033', 'EEG 034', 'EEG 035', 'EEG 036', 'EEG 037', 'EEG 038', 'EEG 039', 'EEG 040', 'EEG 041', 'EEG 042', 'EEG 043', 'EEG 044', 'EEG 045', 'EEG 046', 'EEG 047', 'EEG 048', 'EEG 049', 'EEG 050', 'EEG 051', 'EEG 052', 'EEG 053', 'EEG 054', 'EEG 055', 'EEG 056', 'EEG 057', 'EEG 058', 'EEG 059', 'EEG 060', 'EOG 061']
チャンネル型: {'eeg', 'eog'}
サンプリングレート (Hz): 600.614990234375
記録時間 (秒): 277.7136813300495
チャンネル型と picks¶
ファイルには、EEGだけでなく他の種類のチャンネル(眼球運動用のEOG、心拍用のECG、刺激/トリガーチャンネルなど)が混在していることがよくあります。MNEが、例えばトリガーチャンネルを脳の信号として扱ってしまわないようにするには、正しいチャンネル型が必要です。あるチャンネルの型が間違っている場合は、raw.set_channel_types({"chan_name": "eog"}) で修正します。
型が正しく設定されていれば、ほとんどの関数は picks 引数を受け取り、その一部のみを対象に操作できます。picks="eeg" は非常によく使われます。
for ch_name, ch_type in zip(raw.ch_names, raw.get_channel_types()):
print(f"{ch_name:>8} -> {ch_type}")
EEG 001 -> eeg
EEG 002 -> eeg
EEG 003 -> eeg
EEG 004 -> eeg
EEG 005 -> eeg
EEG 006 -> eeg
EEG 007 -> eeg
EEG 008 -> eeg
EEG 009 -> eeg
EEG 010 -> eeg
EEG 011 -> eeg
EEG 012 -> eeg
EEG 013 -> eeg
EEG 014 -> eeg
EEG 015 -> eeg
EEG 016 -> eeg
EEG 017 -> eeg
EEG 018 -> eeg
EEG 019 -> eeg
EEG 020 -> eeg
EEG 021 -> eeg
EEG 022 -> eeg
EEG 023 -> eeg
EEG 024 -> eeg
EEG 025 -> eeg
EEG 026 -> eeg
EEG 027 -> eeg
EEG 028 -> eeg
EEG 029 -> eeg
EEG 030 -> eeg
EEG 031 -> eeg
EEG 032 -> eeg
EEG 033 -> eeg
EEG 034 -> eeg
EEG 035 -> eeg
EEG 036 -> eeg
EEG 037 -> eeg
EEG 038 -> eeg
EEG 039 -> eeg
EEG 040 -> eeg
EEG 041 -> eeg
EEG 042 -> eeg
EEG 043 -> eeg
EEG 044 -> eeg
EEG 045 -> eeg
EEG 046 -> eeg
EEG 047 -> eeg
EEG 048 -> eeg
EEG 049 -> eeg
EEG 050 -> eeg
EEG 051 -> eeg
EEG 052 -> eeg
EEG 053 -> eeg
EEG 054 -> eeg
EEG 055 -> eeg
EEG 056 -> eeg
EEG 057 -> eeg
EEG 058 -> eeg
EEG 059 -> eeg
EEG 060 -> eeg
EOG 061 -> eog
モンタージュ(電極位置)¶
一部のファイル形式・収録システムでは、実際にデジタル化された3次元の電極位置が保存されています(このサンプルデータセットもそうです。下で raw.get_montage() を確認してください)。一方、あなた自身の .edf エクスポートのように、それが保存されていないものもあり、その場合はチャンネル名を一致させることで、汎用の標準モンタージュを自分で当てはめる必要があります。これが、あなたのファイルに raw.set_montage(...) を適用する前に、チャンネル名の変更(EEG Fp1-CPz → Fp1)というステップが必要だった理由です。
montage = raw.get_montage()
print(montage)
montage.plot(kind="topomap", show_names=True)
plt.show()
<DigMontage | 78 extras (headshape), 4 HPIs, 3 fiducials, 60 channels>

イベントはどこにあるか: アノテーション 対 刺激チャンネル¶
イベントマーカーは、記録システムによって次の2箇所のどちらかに現れます。
raw.annotations— ファイルに付随する、ラベル付きの時刻のリスト(あなたのものと同様、.edfエクスポートによく見られます)。- 専用の刺激/トリガーチャンネル — どのイベントが起きたかを符号化するために値が変化するチャンネルで、
mne.find_events()で読み取ります(このサンプルデータセットで使われており、チャンネル名はSTI 014です)。
第6章で実際に両方の方法を使います。今はまず、何が存在するかだけ確認しましょう。
print("アノテーション:", raw.annotations)
print("'stim' 型のチャンネルはあるか?", "stim" in raw.get_channel_types())
# 注: 上ですでにeeg/eogのみをpickしたため、このファイルの刺激チャンネルはここで意図的に除外されている
アノテーション: <Annotations | 0 segments>
'stim' 型のチャンネルはあるか? False
生データの可視化¶
補完的な2つの見方があります。時間経過に沿った生の波形と、パワースペクトル密度(各周波数にどれだけの信号パワーがあるか)です。後者は電源ノイズや過剰な高周波の筋混入をすばやく見つける手段です。
raw.plot(n_channels=20, duration=10, scalings="auto")
plt.show()

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

50 Hzまたは60 Hz付近のスパイク(電源ノイズ。第4章のノッチフィルタのターゲットです)がないか探し、高い周波数に向かってパワーがなめらかに減衰しているか、それとも不自然な盛り上がりがあるか(筋混入の可能性)を確認してください。
不良チャンネルのマーク¶
上の raw.plot() でスクロールしている間に、平坦だったり、ずっと極端にノイズが多かったり、周囲のチャンネルと明らかに異なっていたりするチャンネルがあれば、「不良(bad)」としてマークする候補です。不良チャンネルは、デフォルトではほとんどの解析やプロットから除外され、後で周囲の良好なチャンネルから補間して再構成することもできます(raw.interpolate_bads()。モンタージュが必要です)。
raw.info["bads"] = [] # 例えば上で不良なものを見つけたら ["EEG 053"] のように指定する
まとめ¶
- どの形式にも専用の
mne.io.read_raw_*関数がありますが、いずれも同じRawオブジェクトを生成します。 - 処理を始める前に、必ずチャンネル名/型、サンプリングレート、モンタージュ、イベントの所在を確認します。
- 時間領域の確認には
raw.plot()、周波数領域の確認にはraw.compute_psd().plot()を使います。
次へ: 第4章 — 前処理