複数データストリーム同期のためのLab Streaming Layer (LSL)

ロシニ・ランデニヤ博士とルーカス・クライネ

更新日

2024/05/17

複数データストリーム同期のためのLab Streaming Layer (LSL)

ロシニ・ランデニヤ博士とルーカス・クライネ

更新日

2024/05/17

複数データストリーム同期のためのLab Streaming Layer (LSL)

ロシニ・ランデニヤ博士とルーカス・クライネ

更新日

2024/05/17

ようこそ!このチュートリアルでは、PythonでLab Streaming Layer(LSL)を使用して、複数のデバイスからEmotivのEEGデータを収集および同期する方法について学びます。本チュートリアルの受講には、Pythonプログラミング言語に関する基本的な知識が必要となります。

学習内容

  1. Lab Streaming Layer(LSL)とは何か、そしてなぜ研究者がそれを使用するのか

  2. 複数のEmotiv EEGデバイスから同期されたデータを収集する方法

  3. 収集したデータのインポートと検証方法

1.1 LSLとは何か、そして何に役立つのか?

Lab Streaming Layer(LSL)は、さまざまなセンサーハードウェアからの神経、生理、行動データストリームの送信、受信、同期に使用できるオープンソースのツールボックスです。Emotiv EEGシステムのような、ますます高機能で高精度、かつモバイルな脳・身体測定ハードウェアデバイスの登場により、神経科学はラボから飛び出し、リアルタイムデータの世界へと移行しつつあります。かつて、EEGやMEGなどの脳測定は研究ラボ内に限定されていましたが、モバイルデバイスの登場により、より自然な環境下で、同時に複数人から多様なデータを収集することが可能になりました。

研究者は、同じ音楽を聴いている2人の間の生理的な同調(シンクロニー)に関心を持つかもしれません。LSLを使用すれば、音の提示に同期させながら、2つのEEGヘッドセットから個別にデータを収集できます。

LSLのその他の活用例:

  1. 実験中のイベントマーカーを、進行中のEEGデータに追加する

  2. 単一の被験者に対する複数のソース(心拍数、EMG、EEGなど)からのデータを時間調整する

  3. 複数の被験者からのデータを時間調整する(例:EEGハイパースキャニング研究)

1.2 LSLはどのように機能するのか?

Lab Streaming Layerは、複数のデバイス間で時系列データをリアルタイムで交換するためのプロトコルです。LSLは、Python、MATLAB、C++、Javaなどのプログラミング言語用のオープンソースライブラリを使用して実装できます。

主な機能は、LSLのデータストリームを中心に展開します:

1. 計測デバイス/ソフトウェアがデータを収集し、データストリームを作成する - 生理データは、EEG記録デバイス、アイトラッカー、モーションキャプチャシステム、心拍モニターなどから、メタデータ(サンプリングレート、データタイプ、チャネル情報など)とともにLSLへストリーミングできます。実験からのイベントマーカー(PsychoPyなどを使用)も、LSLを使用してデータストリームとして送信できます。

2. データストリームがネットワークに公開(パブリッシュ)される - これがLSLを使用したデータ送信方法です。データストリームはネットワークに「ブロードキャスト」されます。公開されたストリームはネットワーク上で利用可能になり、同じネットワーク上の他のLSL対応デバイスから検出できるようになります。LSLは、共通のクロック(Network Time Protocolに準拠)に基づいて、各データチャンクまたはサンプルにタイムスタンプを割り当てます。ストリームは「アウトレット(outlet)」を通じてサンプルごと(またはチャンクごと)にプッシュされます。

3. 収集デバイスがデータストリームを「購読(サブスクライブ)」する - これがLSLを使用したデータ受信方法です。同じネットワーク上の収集デバイスは、「インレット(inlet)」を介して公開されたデータストリームを受信します。各インレットは、1つのアウトレットのみからストリームのサンプルとメタデータを受信します。

4. データを保存する - データストリームを購読すると、好みのプログラミング言語の変数に保存したり、LSLが提供するソフトウェア「LabRecorder」を使用して.xdfなどの標準フォーマットに保存したりできます。

2.0 チュートリアルの概要

このチュートリアルでは、実験セットアップの例を取り上げ、PythonでLSLを使用してそれを実装するために必要な手順とコードを案内します。Pythonを使用してEmotivヘッドセットを装着した2人からEEGデータを収集しながら、音声を再生します。それぞれEmotivPROを実行している2台のコンピュータを使用してEEGデータを収集し、各ストリームを別々のLSLアウトレットからブロードキャストします。Pythonライブラリを使用してオーディオファイルを再生し、ファイルが開始されるたびに同時にトリガーを送信します。

手順:

1. EmotivPROを使用して、EEGデータ(および/またはモーション、コンタクトクオリティ、シグナルクオリティなど)を含むLSLアウトレット経由でデータをストリーミングします。2. Pythonスクリプトを使用してオーディオトラックを再生し、同時に別のLSL経由でトリガーを送信します。LabRecorderを使用して、LSLインレット経由ですべての3つのデータストリームをキャプチャして保存します。

2.1 ステップ 1 - セットアップとインストール

  1. データを収集するためにサポートされているデータ計測デバイスが必要になります。
    • すべてのEmotivのブレインウェアデバイスは、EmotivPROソフトウェアを介してLSLに接続します。

  2. デバイスにEmotivPROをインストールします。LSLを使用するには、有効なEmotivPROライセンスが必要です。

  3. 次のコマンドでPython LSLライブラリをインストールします:
    pip install pylsl

  4. LabRecorderソフトウェアをダウンロードします。これはコマンドラインから実行するか、スタンドアロン版をダウンロードして実行できる、シンプルで無料のアプリです。

  5. 今回の実験用:Pythonを使用してオーディオを再生するために必要なパッケージをインストールします。
    pip install sounddevice soundfile

2.2 ステップ 2 (3) - EmotivPROからLSLストリーム経由でデータを送信する

  1. アプリの右上隅にある「...」を見つけ、Settings(設定)に移動します

  2. 「Lab Streaming Layer」セクションと「Outlet」サブセクションを見つけます

  3. ブロードキャストしたいすべてのデータタイプを選択します

  4. データフォーマットを選択します(32ビット浮動小数点数または64ビット倍精度小数点数)

  5. データをサンプルごとに送信するか、サンプルのチャンクごとに送信するかを選択します

  6. 「Start」をクリックして、LSLデータストリームのブロードキャストを開始します


2.3 ステップ 3 (4) - Pythonスクリプトを使用してオーディオを再生しトリガーを送信する

  1. 以下のコードブロックをコピーしてpythonファイルに貼り付け、コンピュータに保存します。

  2. 再生したいオーディオファイル(できれば.wavファイル)を用意し、変数 audio_filepath をコンピュータ上のオーディオファイルへのパスに変更して、スクリプトを編集します。

  3. コマンドプロンプトを開いてコマンドラインを操作し、Pythonファイルが保存されているフォルダに移動します

  4. python3 ファイル名.py」と入力します。
    • Pythonのインストール状況によっては、python3 の代わりに python を使用する場合もあります。

    重要:/path/to/audio.wav を、実験中に再生したいオーディオファイルの場所(パス)に置き換えてください。

"""
LSLの実例: オーディオを再生しトリガーマーカーを送信する

このスクリプトは、LSLマーカーストリームを作成し、ユーザーが
ENTERキーを押すのを待ってから、オーディオファイルを再生し、
LabRecorderを介して収集されたEEGデータと同期できるマーカーを送信します。
"""

import sounddevice as sd
import soundfile as sf
from pylsl import StreamInfo, StreamOutlet


def wait_for_keypress():
    print("ENTERを押すとオーディオ再生を開始し、LSLマーカーを送信します。")
    while True:
        if input() == "":
            break


def play_audio_and_send_marker(audio_file, outlet):
    data, fs = sf.read(audio_file)

    print("オーディオを再生し、LSLマーカーを送信中...")

    marker_val = [1]
    outlet.push_sample(marker_val)

    sd.play(data, fs)
    sd.wait()

    print("オーディオ再生が完了しました。")


if __name__ == "__main__":

    info = StreamInfo(
        name="AudioMarkers",
        type="Markers",
        channel_count=1,
        nominal_srate=0,
        channel_format="int32",
        source_id="uniqueMarkerID12345"
    )

    outlet = StreamOutlet(info)

    while True:
        wait_for_keypress()

        audio_filepath = "/path/to/audio.wav"

        play_audio_and_send_marker(
            audio_filepath,
            outlet
        )
"""
LSLの実例: オーディオを再生しトリガーマーカーを送信する

このスクリプトは、LSLマーカーストリームを作成し、ユーザーが
ENTERキーを押すのを待ってから、オーディオファイルを再生し、
LabRecorderを介して収集されたEEGデータと同期できるマーカーを送信します。
"""

import sounddevice as sd
import soundfile as sf
from pylsl import StreamInfo, StreamOutlet


def wait_for_keypress():
    print("ENTERを押すとオーディオ再生を開始し、LSLマーカーを送信します。")
    while True:
        if input() == "":
            break


def play_audio_and_send_marker(audio_file, outlet):
    data, fs = sf.read(audio_file)

    print("オーディオを再生し、LSLマーカーを送信中...")

    marker_val = [1]
    outlet.push_sample(marker_val)

    sd.play(data, fs)
    sd.wait()

    print("オーディオ再生が完了しました。")


if __name__ == "__main__":

    info = StreamInfo(
        name="AudioMarkers",
        type="Markers",
        channel_count=1,
        nominal_srate=0,
        channel_format="int32",
        source_id="uniqueMarkerID12345"
    )

    outlet = StreamOutlet(info)

    while True:
        wait_for_keypress()

        audio_filepath = "/path/to/audio.wav"

        play_audio_and_send_marker(
            audio_filepath,
            outlet
        )
"""
LSLの実例: オーディオを再生しトリガーマーカーを送信する

このスクリプトは、LSLマーカーストリームを作成し、ユーザーが
ENTERキーを押すのを待ってから、オーディオファイルを再生し、
LabRecorderを介して収集されたEEGデータと同期できるマーカーを送信します。
"""

import sounddevice as sd
import soundfile as sf
from pylsl import StreamInfo, StreamOutlet


def wait_for_keypress():
    print("ENTERを押すとオーディオ再生を開始し、LSLマーカーを送信します。")
    while True:
        if input() == "":
            break


def play_audio_and_send_marker(audio_file, outlet):
    data, fs = sf.read(audio_file)

    print("オーディオを再生し、LSLマーカーを送信中...")

    marker_val = [1]
    outlet.push_sample(marker_val)

    sd.play(data, fs)
    sd.wait()

    print("オーディオ再生が完了しました。")


if __name__ == "__main__":

    info = StreamInfo(
        name="AudioMarkers",
        type="Markers",
        channel_count=1,
        nominal_srate=0,
        channel_format="int32",
        source_id="uniqueMarkerID12345"
    )

    outlet = StreamOutlet(info)

    while True:
        wait_for_keypress()

        audio_filepath = "/path/to/audio.wav"

        play_audio_and_send_marker(
            audio_filepath,
            outlet
        )

2.4 ステップ 4 (5) - LabRecorderを使用して、すべてのLSLストリームを表示および保存する

  1. LabRecorderを開きます

  2. Update を押します。利用可能なLSLストリームがストリームリストに表示されるはずです
    • 両方のEmotivPRO(通常は「Emotiv-DataStream」と呼ばれる)からのストリームと、マーカーストリーム(「AudioMarkers」と呼ばれる)が表示されるはずです

  3. Browse をクリックしてデータを保存する場所を選択します(他のパラメータの設定も行います)

  4. すべてのストリームを選択し、Record を押して録画/録音を開始します

3.0 データの操作方法

LabRecorderは、すべてのストリームからのデータを含むXDFファイル(Extensible Data Format)を出力します。XDFファイルは複数のストリームで構成されており、各ストリームには含まれる内容(デバイス名、データタイプ、サンプリングレート、チャネルなど)を説明する異なるヘッダーがあります。以下のコードブロックを使用して、XDFファイルを開き、基本情報を表示できます。

注意:/path/to/your/file.xdf を、LabRecorderで出力されたXDFファイルのパスに置き換えてください。

import pyxdf
import mne
import matplotlib.pyplot as plt
import numpy as np

# ここにLSL出力ファイルへのパスを指定します。
data_path = "/path/to/your/file.xdf"

# XDFファイルを読み込みます。
streams, fileheader = pyxdf.load_xdf(data_path)

print("XDF File Header:", fileheader)
print("Number of streams found:", len(streams))

for i, stream in enumerate(streams):
    print("\nStream", i + 1)
    print("ストリーム名:", stream["info"]["name"][0])
    print("ストリームタイプ:", stream["info"]["type"][0])
    print("チャネル数:", stream["info"]["channel_count"][0])

    sfreq = float(stream["info"]["nominal_srate"][0])
    print("サンプリングレート:", sfreq)

    print("サンプル数:", len(stream["time_series"]))
    print("最初の5つのデータポイント:", stream["time_series"][:5])

    channel_names = [
        chan["label"][0]
        for chan in stream["info"]["desc"][0]["channels"][0]["channel"]
    ]

    print("チャネル名:", channel_names)

    channel_types = "eeg"
import pyxdf
import mne
import matplotlib.pyplot as plt
import numpy as np

# ここにLSL出力ファイルへのパスを指定します。
data_path = "/path/to/your/file.xdf"

# XDFファイルを読み込みます。
streams, fileheader = pyxdf.load_xdf(data_path)

print("XDF File Header:", fileheader)
print("Number of streams found:", len(streams))

for i, stream in enumerate(streams):
    print("\nStream", i + 1)
    print("ストリーム名:", stream["info"]["name"][0])
    print("ストリームタイプ:", stream["info"]["type"][0])
    print("チャネル数:", stream["info"]["channel_count"][0])

    sfreq = float(stream["info"]["nominal_srate"][0])
    print("サンプリングレート:", sfreq)

    print("サンプル数:", len(stream["time_series"]))
    print("最初の5つのデータポイント:", stream["time_series"][:5])

    channel_names = [
        chan["label"][0]
        for chan in stream["info"]["desc"][0]["channels"][0]["channel"]
    ]

    print("チャネル名:", channel_names)

    channel_types = "eeg"
import pyxdf
import mne
import matplotlib.pyplot as plt
import numpy as np

# ここにLSL出力ファイルへのパスを指定します。
data_path = "/path/to/your/file.xdf"

# XDFファイルを読み込みます。
streams, fileheader = pyxdf.load_xdf(data_path)

print("XDF File Header:", fileheader)
print("Number of streams found:", len(streams))

for i, stream in enumerate(streams):
    print("\nStream", i + 1)
    print("ストリーム名:", stream["info"]["name"][0])
    print("ストリームタイプ:", stream["info"]["type"][0])
    print("チャネル数:", stream["info"]["channel_count"][0])

    sfreq = float(stream["info"]["nominal_srate"][0])
    print("サンプリングレート:", sfreq)

    print("サンプル数:", len(stream["time_series"]))
    print("最初の5つのデータポイント:", stream["time_series"][:5])

    channel_names = [
        chan["label"][0]
        for chan in stream["info"]["desc"][0]["channels"][0]["channel"]
    ]

    print("チャネル名:", channel_names)

    channel_types = "eeg"


4.0 その他のリソース

公式ドキュメント

  1. オンラインドキュメントや、GitHubにある公式のREADMEファイルを確認してください

  2. その他のリソース:
    • サンプルスクリプトを含む、Emotivのデバイスを使用してLSLを実行するためのコード
    • 有益なYouTube上のLSLデモ
    • すべての関連ライブラリを網羅したSCCN LSL GitHubリポジトリ
    • サブモジュールやアプリがまとめられたLSL GitHubリポジトリ

  3. ハイパースキャニング研究用のHyPyP解析パイプライン

ようこそ!このチュートリアルでは、PythonでLab Streaming Layer(LSL)を使用して、複数のデバイスからEmotivのEEGデータを収集および同期する方法について学びます。本チュートリアルの受講には、Pythonプログラミング言語に関する基本的な知識が必要となります。

学習内容

  1. Lab Streaming Layer(LSL)とは何か、そしてなぜ研究者がそれを使用するのか

  2. 複数のEmotiv EEGデバイスから同期されたデータを収集する方法

  3. 収集したデータのインポートと検証方法

1.1 LSLとは何か、そして何に役立つのか?

Lab Streaming Layer(LSL)は、さまざまなセンサーハードウェアからの神経、生理、行動データストリームの送信、受信、同期に使用できるオープンソースのツールボックスです。Emotiv EEGシステムのような、ますます高機能で高精度、かつモバイルな脳・身体測定ハードウェアデバイスの登場により、神経科学はラボから飛び出し、リアルタイムデータの世界へと移行しつつあります。かつて、EEGやMEGなどの脳測定は研究ラボ内に限定されていましたが、モバイルデバイスの登場により、より自然な環境下で、同時に複数人から多様なデータを収集することが可能になりました。

研究者は、同じ音楽を聴いている2人の間の生理的な同調(シンクロニー)に関心を持つかもしれません。LSLを使用すれば、音の提示に同期させながら、2つのEEGヘッドセットから個別にデータを収集できます。

LSLのその他の活用例:

  1. 実験中のイベントマーカーを、進行中のEEGデータに追加する

  2. 単一の被験者に対する複数のソース(心拍数、EMG、EEGなど)からのデータを時間調整する

  3. 複数の被験者からのデータを時間調整する(例:EEGハイパースキャニング研究)

1.2 LSLはどのように機能するのか?

Lab Streaming Layerは、複数のデバイス間で時系列データをリアルタイムで交換するためのプロトコルです。LSLは、Python、MATLAB、C++、Javaなどのプログラミング言語用のオープンソースライブラリを使用して実装できます。

主な機能は、LSLのデータストリームを中心に展開します:

1. 計測デバイス/ソフトウェアがデータを収集し、データストリームを作成する - 生理データは、EEG記録デバイス、アイトラッカー、モーションキャプチャシステム、心拍モニターなどから、メタデータ(サンプリングレート、データタイプ、チャネル情報など)とともにLSLへストリーミングできます。実験からのイベントマーカー(PsychoPyなどを使用)も、LSLを使用してデータストリームとして送信できます。

2. データストリームがネットワークに公開(パブリッシュ)される - これがLSLを使用したデータ送信方法です。データストリームはネットワークに「ブロードキャスト」されます。公開されたストリームはネットワーク上で利用可能になり、同じネットワーク上の他のLSL対応デバイスから検出できるようになります。LSLは、共通のクロック(Network Time Protocolに準拠)に基づいて、各データチャンクまたはサンプルにタイムスタンプを割り当てます。ストリームは「アウトレット(outlet)」を通じてサンプルごと(またはチャンクごと)にプッシュされます。

3. 収集デバイスがデータストリームを「購読(サブスクライブ)」する - これがLSLを使用したデータ受信方法です。同じネットワーク上の収集デバイスは、「インレット(inlet)」を介して公開されたデータストリームを受信します。各インレットは、1つのアウトレットのみからストリームのサンプルとメタデータを受信します。

4. データを保存する - データストリームを購読すると、好みのプログラミング言語の変数に保存したり、LSLが提供するソフトウェア「LabRecorder」を使用して.xdfなどの標準フォーマットに保存したりできます。

2.0 チュートリアルの概要

このチュートリアルでは、実験セットアップの例を取り上げ、PythonでLSLを使用してそれを実装するために必要な手順とコードを案内します。Pythonを使用してEmotivヘッドセットを装着した2人からEEGデータを収集しながら、音声を再生します。それぞれEmotivPROを実行している2台のコンピュータを使用してEEGデータを収集し、各ストリームを別々のLSLアウトレットからブロードキャストします。Pythonライブラリを使用してオーディオファイルを再生し、ファイルが開始されるたびに同時にトリガーを送信します。

手順:

1. EmotivPROを使用して、EEGデータ(および/またはモーション、コンタクトクオリティ、シグナルクオリティなど)を含むLSLアウトレット経由でデータをストリーミングします。2. Pythonスクリプトを使用してオーディオトラックを再生し、同時に別のLSL経由でトリガーを送信します。LabRecorderを使用して、LSLインレット経由ですべての3つのデータストリームをキャプチャして保存します。

2.1 ステップ 1 - セットアップとインストール

  1. データを収集するためにサポートされているデータ計測デバイスが必要になります。
    • すべてのEmotivのブレインウェアデバイスは、EmotivPROソフトウェアを介してLSLに接続します。

  2. デバイスにEmotivPROをインストールします。LSLを使用するには、有効なEmotivPROライセンスが必要です。

  3. 次のコマンドでPython LSLライブラリをインストールします:
    pip install pylsl

  4. LabRecorderソフトウェアをダウンロードします。これはコマンドラインから実行するか、スタンドアロン版をダウンロードして実行できる、シンプルで無料のアプリです。

  5. 今回の実験用:Pythonを使用してオーディオを再生するために必要なパッケージをインストールします。
    pip install sounddevice soundfile

2.2 ステップ 2 (3) - EmotivPROからLSLストリーム経由でデータを送信する

  1. アプリの右上隅にある「...」を見つけ、Settings(設定)に移動します

  2. 「Lab Streaming Layer」セクションと「Outlet」サブセクションを見つけます

  3. ブロードキャストしたいすべてのデータタイプを選択します

  4. データフォーマットを選択します(32ビット浮動小数点数または64ビット倍精度小数点数)

  5. データをサンプルごとに送信するか、サンプルのチャンクごとに送信するかを選択します

  6. 「Start」をクリックして、LSLデータストリームのブロードキャストを開始します


2.3 ステップ 3 (4) - Pythonスクリプトを使用してオーディオを再生しトリガーを送信する

  1. 以下のコードブロックをコピーしてpythonファイルに貼り付け、コンピュータに保存します。

  2. 再生したいオーディオファイル(できれば.wavファイル)を用意し、変数 audio_filepath をコンピュータ上のオーディオファイルへのパスに変更して、スクリプトを編集します。

  3. コマンドプロンプトを開いてコマンドラインを操作し、Pythonファイルが保存されているフォルダに移動します

  4. python3 ファイル名.py」と入力します。
    • Pythonのインストール状況によっては、python3 の代わりに python を使用する場合もあります。

    重要:/path/to/audio.wav を、実験中に再生したいオーディオファイルの場所(パス)に置き換えてください。

"""
LSLの実例: オーディオを再生しトリガーマーカーを送信する

このスクリプトは、LSLマーカーストリームを作成し、ユーザーが
ENTERキーを押すのを待ってから、オーディオファイルを再生し、
LabRecorderを介して収集されたEEGデータと同期できるマーカーを送信します。
"""

import sounddevice as sd
import soundfile as sf
from pylsl import StreamInfo, StreamOutlet


def wait_for_keypress():
    print("ENTERを押すとオーディオ再生を開始し、LSLマーカーを送信します。")
    while True:
        if input() == "":
            break


def play_audio_and_send_marker(audio_file, outlet):
    data, fs = sf.read(audio_file)

    print("オーディオを再生し、LSLマーカーを送信中...")

    marker_val = [1]
    outlet.push_sample(marker_val)

    sd.play(data, fs)
    sd.wait()

    print("オーディオ再生が完了しました。")


if __name__ == "__main__":

    info = StreamInfo(
        name="AudioMarkers",
        type="Markers",
        channel_count=1,
        nominal_srate=0,
        channel_format="int32",
        source_id="uniqueMarkerID12345"
    )

    outlet = StreamOutlet(info)

    while True:
        wait_for_keypress()

        audio_filepath = "/path/to/audio.wav"

        play_audio_and_send_marker(
            audio_filepath,
            outlet
        )

2.4 ステップ 4 (5) - LabRecorderを使用して、すべてのLSLストリームを表示および保存する

  1. LabRecorderを開きます

  2. Update を押します。利用可能なLSLストリームがストリームリストに表示されるはずです
    • 両方のEmotivPRO(通常は「Emotiv-DataStream」と呼ばれる)からのストリームと、マーカーストリーム(「AudioMarkers」と呼ばれる)が表示されるはずです

  3. Browse をクリックしてデータを保存する場所を選択します(他のパラメータの設定も行います)

  4. すべてのストリームを選択し、Record を押して録画/録音を開始します

3.0 データの操作方法

LabRecorderは、すべてのストリームからのデータを含むXDFファイル(Extensible Data Format)を出力します。XDFファイルは複数のストリームで構成されており、各ストリームには含まれる内容(デバイス名、データタイプ、サンプリングレート、チャネルなど)を説明する異なるヘッダーがあります。以下のコードブロックを使用して、XDFファイルを開き、基本情報を表示できます。

注意:/path/to/your/file.xdf を、LabRecorderで出力されたXDFファイルのパスに置き換えてください。

import pyxdf
import mne
import matplotlib.pyplot as plt
import numpy as np

# ここにLSL出力ファイルへのパスを指定します。
data_path = "/path/to/your/file.xdf"

# XDFファイルを読み込みます。
streams, fileheader = pyxdf.load_xdf(data_path)

print("XDF File Header:", fileheader)
print("Number of streams found:", len(streams))

for i, stream in enumerate(streams):
    print("\nStream", i + 1)
    print("ストリーム名:", stream["info"]["name"][0])
    print("ストリームタイプ:", stream["info"]["type"][0])
    print("チャネル数:", stream["info"]["channel_count"][0])

    sfreq = float(stream["info"]["nominal_srate"][0])
    print("サンプリングレート:", sfreq)

    print("サンプル数:", len(stream["time_series"]))
    print("最初の5つのデータポイント:", stream["time_series"][:5])

    channel_names = [
        chan["label"][0]
        for chan in stream["info"]["desc"][0]["channels"][0]["channel"]
    ]

    print("チャネル名:", channel_names)

    channel_types = "eeg"


4.0 その他のリソース

公式ドキュメント

  1. オンラインドキュメントや、GitHubにある公式のREADMEファイルを確認してください

  2. その他のリソース:
    • サンプルスクリプトを含む、Emotivのデバイスを使用してLSLを実行するためのコード
    • 有益なYouTube上のLSLデモ
    • すべての関連ライブラリを網羅したSCCN LSL GitHubリポジトリ
    • サブモジュールやアプリがまとめられたLSL GitHubリポジトリ

  3. ハイパースキャニング研究用のHyPyP解析パイプライン

ようこそ!このチュートリアルでは、PythonでLab Streaming Layer(LSL)を使用して、複数のデバイスからEmotivのEEGデータを収集および同期する方法について学びます。本チュートリアルの受講には、Pythonプログラミング言語に関する基本的な知識が必要となります。

学習内容

  1. Lab Streaming Layer(LSL)とは何か、そしてなぜ研究者がそれを使用するのか

  2. 複数のEmotiv EEGデバイスから同期されたデータを収集する方法

  3. 収集したデータのインポートと検証方法

1.1 LSLとは何か、そして何に役立つのか?

Lab Streaming Layer(LSL)は、さまざまなセンサーハードウェアからの神経、生理、行動データストリームの送信、受信、同期に使用できるオープンソースのツールボックスです。Emotiv EEGシステムのような、ますます高機能で高精度、かつモバイルな脳・身体測定ハードウェアデバイスの登場により、神経科学はラボから飛び出し、リアルタイムデータの世界へと移行しつつあります。かつて、EEGやMEGなどの脳測定は研究ラボ内に限定されていましたが、モバイルデバイスの登場により、より自然な環境下で、同時に複数人から多様なデータを収集することが可能になりました。

研究者は、同じ音楽を聴いている2人の間の生理的な同調(シンクロニー)に関心を持つかもしれません。LSLを使用すれば、音の提示に同期させながら、2つのEEGヘッドセットから個別にデータを収集できます。

LSLのその他の活用例:

  1. 実験中のイベントマーカーを、進行中のEEGデータに追加する

  2. 単一の被験者に対する複数のソース(心拍数、EMG、EEGなど)からのデータを時間調整する

  3. 複数の被験者からのデータを時間調整する(例:EEGハイパースキャニング研究)

1.2 LSLはどのように機能するのか?

Lab Streaming Layerは、複数のデバイス間で時系列データをリアルタイムで交換するためのプロトコルです。LSLは、Python、MATLAB、C++、Javaなどのプログラミング言語用のオープンソースライブラリを使用して実装できます。

主な機能は、LSLのデータストリームを中心に展開します:

1. 計測デバイス/ソフトウェアがデータを収集し、データストリームを作成する - 生理データは、EEG記録デバイス、アイトラッカー、モーションキャプチャシステム、心拍モニターなどから、メタデータ(サンプリングレート、データタイプ、チャネル情報など)とともにLSLへストリーミングできます。実験からのイベントマーカー(PsychoPyなどを使用)も、LSLを使用してデータストリームとして送信できます。

2. データストリームがネットワークに公開(パブリッシュ)される - これがLSLを使用したデータ送信方法です。データストリームはネットワークに「ブロードキャスト」されます。公開されたストリームはネットワーク上で利用可能になり、同じネットワーク上の他のLSL対応デバイスから検出できるようになります。LSLは、共通のクロック(Network Time Protocolに準拠)に基づいて、各データチャンクまたはサンプルにタイムスタンプを割り当てます。ストリームは「アウトレット(outlet)」を通じてサンプルごと(またはチャンクごと)にプッシュされます。

3. 収集デバイスがデータストリームを「購読(サブスクライブ)」する - これがLSLを使用したデータ受信方法です。同じネットワーク上の収集デバイスは、「インレット(inlet)」を介して公開されたデータストリームを受信します。各インレットは、1つのアウトレットのみからストリームのサンプルとメタデータを受信します。

4. データを保存する - データストリームを購読すると、好みのプログラミング言語の変数に保存したり、LSLが提供するソフトウェア「LabRecorder」を使用して.xdfなどの標準フォーマットに保存したりできます。

2.0 チュートリアルの概要

このチュートリアルでは、実験セットアップの例を取り上げ、PythonでLSLを使用してそれを実装するために必要な手順とコードを案内します。Pythonを使用してEmotivヘッドセットを装着した2人からEEGデータを収集しながら、音声を再生します。それぞれEmotivPROを実行している2台のコンピュータを使用してEEGデータを収集し、各ストリームを別々のLSLアウトレットからブロードキャストします。Pythonライブラリを使用してオーディオファイルを再生し、ファイルが開始されるたびに同時にトリガーを送信します。

手順:

1. EmotivPROを使用して、EEGデータ(および/またはモーション、コンタクトクオリティ、シグナルクオリティなど)を含むLSLアウトレット経由でデータをストリーミングします。2. Pythonスクリプトを使用してオーディオトラックを再生し、同時に別のLSL経由でトリガーを送信します。LabRecorderを使用して、LSLインレット経由ですべての3つのデータストリームをキャプチャして保存します。

2.1 ステップ 1 - セットアップとインストール

  1. データを収集するためにサポートされているデータ計測デバイスが必要になります。
    • すべてのEmotivのブレインウェアデバイスは、EmotivPROソフトウェアを介してLSLに接続します。

  2. デバイスにEmotivPROをインストールします。LSLを使用するには、有効なEmotivPROライセンスが必要です。

  3. 次のコマンドでPython LSLライブラリをインストールします:
    pip install pylsl

  4. LabRecorderソフトウェアをダウンロードします。これはコマンドラインから実行するか、スタンドアロン版をダウンロードして実行できる、シンプルで無料のアプリです。

  5. 今回の実験用:Pythonを使用してオーディオを再生するために必要なパッケージをインストールします。
    pip install sounddevice soundfile

2.2 ステップ 2 (3) - EmotivPROからLSLストリーム経由でデータを送信する

  1. アプリの右上隅にある「...」を見つけ、Settings(設定)に移動します

  2. 「Lab Streaming Layer」セクションと「Outlet」サブセクションを見つけます

  3. ブロードキャストしたいすべてのデータタイプを選択します

  4. データフォーマットを選択します(32ビット浮動小数点数または64ビット倍精度小数点数)

  5. データをサンプルごとに送信するか、サンプルのチャンクごとに送信するかを選択します

  6. 「Start」をクリックして、LSLデータストリームのブロードキャストを開始します


2.3 ステップ 3 (4) - Pythonスクリプトを使用してオーディオを再生しトリガーを送信する

  1. 以下のコードブロックをコピーしてpythonファイルに貼り付け、コンピュータに保存します。

  2. 再生したいオーディオファイル(できれば.wavファイル)を用意し、変数 audio_filepath をコンピュータ上のオーディオファイルへのパスに変更して、スクリプトを編集します。

  3. コマンドプロンプトを開いてコマンドラインを操作し、Pythonファイルが保存されているフォルダに移動します

  4. python3 ファイル名.py」と入力します。
    • Pythonのインストール状況によっては、python3 の代わりに python を使用する場合もあります。

    重要:/path/to/audio.wav を、実験中に再生したいオーディオファイルの場所(パス)に置き換えてください。

"""
LSLの実例: オーディオを再生しトリガーマーカーを送信する

このスクリプトは、LSLマーカーストリームを作成し、ユーザーが
ENTERキーを押すのを待ってから、オーディオファイルを再生し、
LabRecorderを介して収集されたEEGデータと同期できるマーカーを送信します。
"""

import sounddevice as sd
import soundfile as sf
from pylsl import StreamInfo, StreamOutlet


def wait_for_keypress():
    print("ENTERを押すとオーディオ再生を開始し、LSLマーカーを送信します。")
    while True:
        if input() == "":
            break


def play_audio_and_send_marker(audio_file, outlet):
    data, fs = sf.read(audio_file)

    print("オーディオを再生し、LSLマーカーを送信中...")

    marker_val = [1]
    outlet.push_sample(marker_val)

    sd.play(data, fs)
    sd.wait()

    print("オーディオ再生が完了しました。")


if __name__ == "__main__":

    info = StreamInfo(
        name="AudioMarkers",
        type="Markers",
        channel_count=1,
        nominal_srate=0,
        channel_format="int32",
        source_id="uniqueMarkerID12345"
    )

    outlet = StreamOutlet(info)

    while True:
        wait_for_keypress()

        audio_filepath = "/path/to/audio.wav"

        play_audio_and_send_marker(
            audio_filepath,
            outlet
        )

2.4 ステップ 4 (5) - LabRecorderを使用して、すべてのLSLストリームを表示および保存する

  1. LabRecorderを開きます

  2. Update を押します。利用可能なLSLストリームがストリームリストに表示されるはずです
    • 両方のEmotivPRO(通常は「Emotiv-DataStream」と呼ばれる)からのストリームと、マーカーストリーム(「AudioMarkers」と呼ばれる)が表示されるはずです

  3. Browse をクリックしてデータを保存する場所を選択します(他のパラメータの設定も行います)

  4. すべてのストリームを選択し、Record を押して録画/録音を開始します

3.0 データの操作方法

LabRecorderは、すべてのストリームからのデータを含むXDFファイル(Extensible Data Format)を出力します。XDFファイルは複数のストリームで構成されており、各ストリームには含まれる内容(デバイス名、データタイプ、サンプリングレート、チャネルなど)を説明する異なるヘッダーがあります。以下のコードブロックを使用して、XDFファイルを開き、基本情報を表示できます。

注意:/path/to/your/file.xdf を、LabRecorderで出力されたXDFファイルのパスに置き換えてください。

import pyxdf
import mne
import matplotlib.pyplot as plt
import numpy as np

# ここにLSL出力ファイルへのパスを指定します。
data_path = "/path/to/your/file.xdf"

# XDFファイルを読み込みます。
streams, fileheader = pyxdf.load_xdf(data_path)

print("XDF File Header:", fileheader)
print("Number of streams found:", len(streams))

for i, stream in enumerate(streams):
    print("\nStream", i + 1)
    print("ストリーム名:", stream["info"]["name"][0])
    print("ストリームタイプ:", stream["info"]["type"][0])
    print("チャネル数:", stream["info"]["channel_count"][0])

    sfreq = float(stream["info"]["nominal_srate"][0])
    print("サンプリングレート:", sfreq)

    print("サンプル数:", len(stream["time_series"]))
    print("最初の5つのデータポイント:", stream["time_series"][:5])

    channel_names = [
        chan["label"][0]
        for chan in stream["info"]["desc"][0]["channels"][0]["channel"]
    ]

    print("チャネル名:", channel_names)

    channel_types = "eeg"


4.0 その他のリソース

公式ドキュメント

  1. オンラインドキュメントや、GitHubにある公式のREADMEファイルを確認してください

  2. その他のリソース:
    • サンプルスクリプトを含む、Emotivのデバイスを使用してLSLを実行するためのコード
    • 有益なYouTube上のLSLデモ
    • すべての関連ライブラリを網羅したSCCN LSL GitHubリポジトリ
    • サブモジュールやアプリがまとめられたLSL GitHubリポジトリ

  3. ハイパースキャニング研究用のHyPyP解析パイプライン

A technician fits an Emotiv saline EEG headset on a test participant.

読むのを続ける

Basics of Neural Oscillations