脳波研究を行っているYasufumiです。普段はpythonやmatlabをメインに「動けばいいやろ」という精神でやっています。
ニューロテックという言葉と共に脳とテクノロジーへの関心はムーンショットの例を挙げるまでもなく高まっている。今回の記事では脳の生体指標の中でも比較的収集が簡単な脳波に着目して解説する。プログラミング言語についても一般に広まっているPythonを用いる。
【目次】
脳波とPython
脳波とは何か
脳波とは人の頭皮上で観測される脳の電気的な活動[1]のことであり、1929年にハンスベルガーによって報告された。
[図上.実際の脳波データをソフトウェア上で表示した画面]
観測される電気信号は脳内の活動をもとに行っていると捉えられており、実際にその研究においても関連が認められるような現象が観測されている。代表的なものがてんかん発作時の脳波である。てんかん発作は脳内の神経細胞等が異常に動く状態である。恐怖の想起や異常行動などの過剰な神経活動による影響があるがこれらの治療には部位の特定が必要である。そのような異常な活動をする部位特定のために脳波を用いることができる。
[図左.正常な脳波の模式図] [図右.てんかん発作時の脳波の模式図 双方筆者作成]
脳波にはアルファ波(8-12Hz)、デルタ波(1-3Hz)、シータ波(4-7Hz)、ベータ波(13Hz-24Hz)、ガンマ波(25Hz~)と呼ばれる特定の周波数によって発生する波が存在している。これらは主に集中や睡眠、リラックス等で変わってくることがある。
脳波はどのような時に使うのか
前述の通り、てんかんの診療等に使われることがある。また、腫瘍の確認やアルツハイマー等でも特徴的な脳波が観測される[1]。また、疾病以外にも脳内の情報統合の観測などにおいて用いられることが多い。例えばオドポール課題を行うとP300と呼ばれる特有の活動を見ることができる。オドポール課題はある二つ、ないしは複数の条件下において低頻度のものを探す課題である。
[図上.オドポール課題の概略図]
オドポール課題において、低頻度の目標となる刺激が提示された際には多くは300m秒後にP300と呼ばれる陽性の反応が見られる。
[図上.P300の模式図]
このような反応は人が見ているものと想定しているものの参照を行うということで反応を見ることができる。逆に言えば実験後半にこの反応が出なくなったりした場合はその人が他のことをしているか集中力が切れて来ていることを指摘することができる。
また、前述した特定周波数における活動の増減を観測することで脳内の状態遷移について考えることもできる。この文章の第3章ではこれを用いる。
このように脳内の活動についての処理を観測する際には脳波は有用である。
MNE-Pythonについて
MNE-Pythonは、MEG(脳磁図)およびEEG(脳波)のデータ解析を行うための強力なオープンソースのPythonパッケージである。このパッケージは、データの入力と出力、前処理、視覚化、ソース推定、時間-周波数解析、接続性解析、機械学習、統計など、非常に多岐にわたる機能を提供している。MNE-Pythonは、NeuromagのFIF形式を主に使用しており、多様なデータ形式に対応している。また、データのフィルタリング、リサンプリング、アーティファクトの修正など、前処理のための豊富な機能を備えている。
EEGデータの解析においては、刺激イベントに基づいてデータをエポックに分割することが重要である。これにより、イベント関連電位(ERP)の解析が可能となる。エポックデータを平均化してERPを生成し、それを視覚化することも可能である。さらに、頭部モデルとフォワードモデルを構築し、逆解法(dSPMやsLORETAなど)を用いて脳内の信号源を推定することができる。これにより、脳のどの部分が特定の刺激に対して活性化しているかを詳細に分析することができる。
MNE-Pythonはまた、ウェーブレット変換やFourier変換を使用してデータの時間-周波数特性を解析する機能を提供している。これにより、特定の周波数帯域における脳波の活動を詳細に調べることが可能となる。さらに、scikit-learnと統合されており、分類や回帰、クロスバリデーションなどの機械学習手法を脳波データに適用することができる。これにより、データのパターンを学習し、特定の脳活動の特徴を捉えることが可能となる。
MNE-Pythonのインストールは非常に簡単で、pipコマンドを使用することで容易に行うことができる。インストール後は、豊富なドキュメントやチュートリアルを参照することで、基本的な使用方法から高度な解析手法までを学ぶことができる。公式ドキュメントには、インストール方法、使用例、APIリファレンスが詳細に記載されており、初めて使用するユーザーから経験豊富な研究者まで、幅広いユーザーに対応している。
MNE-Pythonを使用することで、脳波データの高度な解析を効率的に行うことが可能となる。その多機能性と柔軟性により、神経科学研究において不可欠なツールとなっている。例えば、研究者は脳波データを用いて脳の機能を詳細に調査し、新しい知見を得ることができる。また、教育現場においても、学生が神経科学の基礎を学ぶための実践的なツールとして利用されている。
さらに、MNE-Pythonはオープンソースであるため、研究コミュニティ全体での共同作業が容易である。世界中の研究者がこのツールを使用してデータを共有し、解析手法を向上させることで、神経科学の発展に寄与している。これにより、再現性のある研究が可能となり、科学的知見の信頼性が向上する。
総じて、MNE-Pythonは脳波解析における強力なツールであり、その多機能性と柔軟性により、研究や教育の現場で広く利用されている。その利用により、神経科学の研究が深化し、新しい発見が生まれることが期待されている。
コネクティビティ解析をする
コネクティビティ解析は、脳内の異なる領域間の相互作用や接続性を理解するための手法である。これにより、特定の認知プロセスや神経活動のネットワーク的側面を明らかにすることができる。
準備
まずは、MNE-Pythonというライブラリについて説明する。MNE-Pythonは、MEGやEEGデータの処理および解析のための強力なツールである。これを用いることで、データの前処理、ソース推定、コネクティビティ解析などを効率的に行うことができる。
この例では、dSPM逆解法とFreeSurfer皮質区分に基づいて、ソーススペースの68領域間の全対全接続性を計算する実験を行う。目的は、特定の周波数帯における脳内の異なる領域間の相互作用を明らかにし、それを視覚化することである。
実行
以下のコードを用いて、実際にコネクティビティ解析を実行する。
データのロード
まず、サンプルデータをロードする。
from mne.datasets import sample data_path = sample.data_path() subjects_dir = data_path / "subjects" fname_inv = data_path / "MEG/sample/sample_audvis-meg-oct-6-meg-inv.fif" fname_raw = data_path / "MEG/sample/sample_audvis_filt-0-40_raw.fif" fname_event = data_path / "MEG/sample/sample_audvis_filt-0-40_raw-eve.fif"# データをロード inverse_operator = read_inverse_operator(fname_inv) raw = mne.io.read_raw_fif(fname_raw) events = mne.read_events(fname_event)
この部分では、逆オペレータ、未処理の生データ、およびイベントデータを読み込む。
チャネルの選択とエポックの定義
次に、MEGチャネルを選択し、エポックを定義する。
# 不良チャネルを追加 raw.info["bads"] += ["MEG 2443"] # MEGチャネルを選択 picks = mne.pick_types(raw.info, meg=True, eeg=False, stim=False, eog=True, exclude="bads") # 左聴覚条件のエポックを定義 event_id, tmin, tmax = 1, -0.2, 0.5 epochs = mne.Epochs( raw, events, event_id, tmin, tmax, picks=picks, baseline=(None, 0), reject=dict(mag=4e-12, grad=4000e-13, eog=150e-6) )
この部分では、不良チャネルを除外し、特定のイベントに基づいてエポックを定義する。
逆解と接続性の計算
逆解を計算し、その接続性を評価する。
# 逆解の計算 snr = 1.0 lambda2 = 1.0 / snr**2 method = "dSPM" stcs = apply_inverse_epochs( epochs, inverse_operator, lambda2, method, pick_ori="normal", return_generator=True ) # ラベルの読み込みとタイムコースの抽出 labels = mne.read_labels_from_annot("sample", parc="aparc", subjects_dir=subjects_dir) src = inverse_operator["src"] label_ts = mne.extract_label_time_course( stcs, labels, src, mode="mean_flip", return_generator=True ) # 接続性の計算 fmin, fmax = 8.0, 13.0 sfreq = raw.info["sfreq"] con_methods = ["pli", "wpli2_debiased", "ciplv"] con = spectral_connectivity_epochs( label_ts, method=con_methods, mode="multitaper", sfreq=sfreq, fmin=fmin, fmax=fmax, faverage=True, mt_adaptive=True, n_jobs=1 ) # 結果の整理 con_res = {method: c.get_data(output="dense")[:, :, 0] for method, c inzip(con_methods, con)}
この部分では、逆解を計算し、各ラベル内のタイムコースを抽出し、接続性を評価する。
接続性の視覚化
最後に、接続性を円グラフレイアウトで視覚化する。
# ラベルの再配置 label_names = [label.name for label in labels] lh_labels = [name for name in label_names if name.endswith("lh")] rh_labels = [name for name in label_names if name.endswith("rh")] # y位置に基づくラベルの並べ替え label_ypos = [np.mean(labels[label_names.index(name)].pos[:, 1]) for name in lh_labels] lh_labels = [lh_labels[i] for i in np.argsort(label_ypos)] label_ypos = [np.mean(labels[label_names.index(name)].pos[:, 1]) for name in rh_labels] rh_labels = [rh_labels[i] for i in np.argsort(label_ypos)] node_order = lh_labels + rh_labels node_colors = [label_colors[label_names.index(name)] for name in node_order] # 円グラフレイアウトの作成 fig, axes = plt.subplots(1, len(con_methods), figsize=(15, 5), subplot_kw=dict(polar=True)) for ax, method inzip(axes, con_methods): plot_connectivity_circle( con_res[method], node_names=node_order, n_lines=300, node_colors=node_colors, title=method, ax=ax, colormap='hot', vmin=0.0, vmax=0.5, colorbar=True ) plt.show()
すると、以下のような画像が表示される。(左の画像は中央と右が表示されていない。私の環境ではなぜか表示されないが普通には表示されるはずである)
これらの結果からどの部位がコネクティビティが強いのかということがわかる。
解説
上記はあくまで例として示されているコードの解説だが、他にもチュートリアルがたくさんある。ぜひ自分の環境で試してみて欲しい。
「paizaラーニング」では、未経験者でもブラウザさえあれば、今すぐプログラミングの基礎が動画で学べるレッスンを多数公開しております。
詳しくはこちら