Skip to content

第2章: MNE-Pythonのコアとなる概念

MNE-Pythonは、MEG/EEG解析のための標準的なオープンソースPythonライブラリです。Pythonを使って発表されているEEG論文の多くがこれを利用しています。公式のドキュメントとチュートリアルは mne.tools にあり、このチュートリアルシリーズの内容はすべて、そのドキュメントに基づいて、最初の一歩として書き直したものです。

MNEで行うことのほとんどすべては、4つのオブジェクト型を中心に回っています。これらを覚えてしまえば、ライブラリの残りの部分も自然に読めるようになります。すべての関数は、この4つのどれかを作る・変換する・そこから情報を取り出す、という仕事をしているからです。

4つのコアオブジェクト

オブジェクト 元となるデータの形 表すもの
Info (メタデータのみ) チャンネル名/型、サンプリングレート、フィルタ履歴、不良チャンネル、モンタージュなど、記録を説明する「ヘッダー」情報
Raw (n_channels, n_times) 連続記録全体
Epochs (n_epochs, n_channels, n_times) イベントの周辺を切り出した、多数の短いスニペット
Evoked (n_channels, n_times) エポック群の平均 — これがあなたのERPです

RawEpochsEvoked のどのオブジェクトも .info という属性を持っています。これはどれも同じ種類のメタデータ格納庫で、そのオブジェクトが保持しているデータについて説明します。一度 .info の中身を確認すれば、3つのどれについても同じように調べ方がわかります。

実際のデータ(前の章までで使った公開サンプルデータセット)を読み込んで、それぞれを見てみましょう。

Raw、Epochs、Evokedのデータ形状

import mne
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"])  # あなた自身のデータと同様に、このチュートリアルはEEGに焦点を絞る
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

Info: メタデータ

raw.info は辞書のように振る舞います。特に役立つキーをいくつか紹介します。

print("サンプリングレート:", raw.info["sfreq"])
print("チャンネル数:", raw.info["nchan"])
print("不良チャンネル:", raw.info["bads"])
print("すでに適用済みのハイパス/ローパス:", raw.info["highpass"], raw.info["lowpass"])
raw.info  # そのまま表示すると、読みやすい要約全体が得られる
サンプリングレート: 600.614990234375
チャンネル数: 61
不良チャンネル: ['EEG 053']
すでに適用済みのハイパス/ローパス: 0.10000000149011612 172.17630004882812
General
MNE object type Info
Measurement date 2002-12-03 at 19:01:10 UTC
Participant Unknown
Experimenter MEG
Acquisition
Sampling frequency 600.61 Hz
Channels
EEG and
EOG
Head & sensor digitization 146 points
Filters
Highpass 0.10 Hz
Lowpass 172.18 Hz

Raw: 連続記録

内部的には、Raw は普通の2次元NumPy配列をラップしています。行がチャンネル、列が時間サンプルです。.get_data() でその配列を直接取得できます。MNEが行っていることは、最終的にはすべてメタデータの付いた配列演算にすぎない、ということを覚えておくと役立ちます。

data = raw.get_data()
print("データの形状 (チャンネル数, 時間サンプル数):", data.shape)
print("データはデフォルトでボルト単位。例えば最初のチャンネルの最初の5サンプル:", data[0, :5])
データの形状 (チャンネル数, 時間サンプル数): (61, 166800)
データはデフォルトでボルト単位。例えば最初のチャンネルの最初の5サンプル: [1.13989260e-05 9.85015885e-06 7.68188489e-06 5.82336435e-06
 6.81457530e-07]

いたるところに出てくるコードパターン

MNEのいたるところで登場するお決まりの書き方がいくつかあります。今のうちに見分けられるようになっておくと、後々の混乱を防げます。

1. 多くのメソッドはオブジェクトをその場で(in place)変更します(そして連鎖できるように、そのオブジェクト自身も返します)。raw.filter(...)raw そのものを変更します。元のものをそのまま残しておきたい場合は、先に .copy() します。

raw_filtered = raw.copy().filter(l_freq=1, h_freq=40)  # raw自体は変更されない
raw.filter(l_freq=1, h_freq=40)                         # raw自体が変更される
これはまさに、あなた自身のデータのノートブックで使ったパターンです(raw_filt = raw.copy().filter(...))。フィルタをかけていない raw を比較用にそのまま残しておくために、あえてこうしています。

2. preload: preload=False(場合によってはこれがデフォルト)でファイルを読み込むと、実際の信号ではなくヘッダー/メタデータのみが読み込まれます。.info を調べたいだけの場合や、全体を読み込む前にクロップ(切り出し)したい場合は、この方が高速です。ほとんどの処理ステップは preload=True(読み込み時に指定するか、後で raw.load_data() を呼ぶ)を必要とします。

3. picks: 多くの関数は picks 引数を受け取り、チャンネルの一部だけを対象に操作できます。例: picks="eeg"picks=["Fz", "Cz"]picks="eog"

4. verbose: ほとんどすべての関数が verbose=... を受け取り、上で設定したグローバルな mne.set_log_level(...) とは独立に、その関数自身のログ出力を制御できます。

ノートブックを離れずにヘルプを見る

Jupyterでは、任意の関数・メソッドの後ろに ? を付けると、そのdocstring(パラメータの完全な一覧、デフォルト値、説明)がポップアップ表示されます。「この引数は何をするんだっけ?」という疑問に、VS Codeを離れずに答える最速の方法です。

raw.filter?

まとめ

  • Info = メタデータ。すべてのオブジェクトに付いてくる。
  • Raw = 連続記録(2次元: チャンネル × 時間)。
  • Epochs = 試行のスニペット(3次元: 試行 × チャンネル × 時間) — 第6章。
  • Evoked = Epochs の平均 = あなたのERP — 第7章。
  • インプレースなメソッドの前には .copy()、データを実際に読み込むには preload=True、チャンネルを選ぶには picks、その場でドキュメントを見るには function? を使うことを忘れずに。

次へ: 第3章 — データの読み込みと確認