用於同步多個數據流的實驗室串流層 (LSL)

Roshini Randeniya 博士和 Lucas Kleine

更新於

2024年5月17日

用於同步多個數據流的實驗室串流層 (LSL)

Roshini Randeniya 博士和 Lucas Kleine

更新於

2024年5月17日

用於同步多個數據流的實驗室串流層 (LSL)

Roshini Randeniya 博士和 Lucas Kleine

更新於

2024年5月17日

歡迎!在本教學中,我們將學習如何使用 Python 中的實驗室流層 (Lab Streaming Layer, LSL) 來收集並同步來自多個裝置的 Emotiv EEG 數據。這需要具備 Python 程式語言的基本實作知識。

您將學到什麼

  1. 什麼是實驗室流層 (LSL) 以及研究人員為何使用它

  2. 如何從多個 Emotiv EEG 裝置收集同步數據

  3. 如何匯入和檢查收集到的數據

1.1 什麼是 LSL,它有什麼用處?

實驗室流層 (LSL) 是一個開源工具箱,可用於傳送、接收和同步來自各種感測器硬體的神經、生理和行為數據流。功能日益強大、精確且便攜的大腦與身體感測硬體裝置(如 Emotiv EEG 系統)正將神經科學從實驗室帶入即時數據的世界。過去,EEG 和 MEG 等大腦測量僅限於研究實驗室,而移動裝置讓我們能夠在更自然、更生活化的環境中,同時收集多個人的多種數據。

研究人員可能會對聆聽同一首音樂的兩個人之間的生理同步性感興趣。LSL 可以幫助我們分別收集兩個 EEG 頭戴式裝置的數據,並將這些數據與聲音的播放同步。

LSL 的其他用途範例:

  1. 將實驗中的事件標記加入到持續進行的 EEG 數據中

  2. 為單一受試者對齊來自多個來源的時間數據(例如心率、EMG、EEG)

  3. 對齊來自多個受試者的時間數據(例如 EEG 超掃描研究)

1.2 LSL 如何運作?

實驗室流層 (LSL) 是一種用於在多個裝置之間即時交換時間序列數據的協定。LSL 可以使用 Python、MATLAB、C++、Java 等程式語言的開源函式庫來實現。

核心功能圍繞著 LSL 數據流 (data streams) 展開:

1. 採集裝置/軟體收集數據並建立數據流 - 生理數據可以從 EEG 記錄裝置、眼動儀、動作捕捉系統、心率監測器等串流傳輸到 LSL,其中包含元數據(取樣率、數據類型、通道資訊等)- 來自實驗(例如使用 PsychoPy)的事件標記也可以使用 LSL 作為數據流傳送

2. 數據流被發佈 (published)到網絡 - 這是使用 LSL 傳送數據的方式;數據流被「廣播」到網絡 - 發佈的數據流在網絡上可用,並可被同一網絡上的其他支援 LSL 的裝置發現 - LSL 根據共同的時鐘(遵循網絡時間協定 NTP)為每個數據塊或樣本分配一個時間戳記。- 數據流通過一個「出口 (outlet)」逐個樣本(或逐個數據塊)推送

3. 收集裝置「訂閱 (subscribe)」數據流 - 這是使用 LSL 接收數據的方式 - 同一網絡上的收集裝置通過「入口 (inlets)」接收發佈的數據流。- 每個入口僅接收來自一個出口的數據流樣本和元數據

4. 儲存數據 - 訂閱數據流後,您可以將其儲存到您偏好程式語言的變數中,或使用 LSL 提供的軟體 LabRecorder 將其儲存為 .xdf 等標準格式。

2.0 教學概述

在本教學中,我們將以一個實驗設置為例,引導您完成在 Python 中使用 LSL 進行實作所需的步驟和程式碼。我們將使用 Python 播放聲音,同時從兩名配戴 Emotiv 頭戴式裝置的人員身上收集 EEG 數據。我們將使用兩台各自主行 EmotivPRO 的電腦來收集 EEG 數據,並通過單獨的 LSL 出口廣播每個數據流。我們將使用 Python 函式庫來播放音訊檔案,並在每次檔案開始播放時同步傳送觸發器。

步驟:

1. 使用 EmotivPRO 通過 LSL 出口串流傳輸數據,其中包括 EEG 數據(和/或動作、接觸品質、訊號品質等)。2. 使用 Python 腳本播放音軌,同時通過另一個 LSL 傳送觸發器。使用 LabRecorder 通過 LSL 入口擷取並儲存所有三個數據流。

2.1 步驟 1 - 設定與安裝

  1. 您需要準備支援的數據採集裝置來收集數據
    • 所有 Emotiv 的導電裝置均通過 EmotivPRO 軟體連接到 LSL

  2. 在您的裝置上安裝 EmotivPRO。您需要有效的 EmotivPRO 授權才能使用 LSL。

  3. 使用以下指令安裝 Python LSL 函式庫
    pip install pylsl

  4. 下載 LabRecorder 軟體。這是一個簡單、免費的應用程式,可以從
    命令列運行或使用獨立下載

  5. 針對我們的實驗:安裝使用 Python 播放音訊所需的套件
    pip install sounddevice soundfile

2.2 步驟 3 - 通過 LSL 數據流從 EmotivPRO 傳送數據

  1. 在應用程式右上角找到「...」,導覽至 Settings(設定)

  2. 找到「Lab Streaming Layer」區段和「Outlet」子區段

  3. 選擇您想要廣播的所有數據類型

  4. 選擇數據格式(32 位元浮點數或 64 位元雙精度浮點數)

  5. 選擇是要逐個樣本還是成塊樣本傳送數據

  6. 點擊「Start」以廣播 LSL 數據流


2.3 步驟 4 - 使用 Python 腳本播放音訊並傳送觸發器

  1. 將以下程式碼區塊複製並貼到 python 檔案中,然後儲存到您的電腦。

  2. 尋找您想要播放的音訊檔案(最好是 .wav 檔案),並點擊修改腳本,將
    變數 audio_filepath 變更為您電腦上音訊檔案的檔案路徑

  3. 開啟命令提示字元以與命令列進行互動,並導覽至儲存您的
    Python 檔案的資料夾

  4. 輸入:python3 filename.py
    • 根據您的 Python 安裝情況,您可能需要使用 python 而非 python3

    注意:請將 /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 步驟 5 - 使用 LabRecorder 檢視並儲存所有 LSL 數據流

  1. 開啟 LabRecorder

  2. 按下 Update。可用的 LSL 數據流應會顯示在數據流清單中
    • 您應該能看到來自兩個 EmotivPRO 的數據流(通常稱為「Emotiv-DataStream」)以及標記流(稱為「AudioMarkers」)

  3. 點擊 Browse 以選取儲存數據的位置(並設定其他參數)

  4. 選取所有數據流,然後按下 Record 開始記錄

3.0 使用數據

LabRecorder 會輸出一個 XDF 檔案(可延伸數據格式),其中包含來自所有數據流的數據。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 檔案標頭:", fileheader)
print("找到的數據流數量:", len(streams))

for i, stream in enumerate(streams):
    print("\n數據流", 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 檔案標頭:", fileheader)
print("找到的數據流數量:", len(streams))

for i, stream in enumerate(streams):
    print("\n數據流", 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 檔案標頭:", fileheader)
print("找到的數據流數量:", len(streams))

for i, stream in enumerate(streams):
    print("\n數據流", 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. 什麼是實驗室流層 (LSL) 以及研究人員為何使用它

  2. 如何從多個 Emotiv EEG 裝置收集同步數據

  3. 如何匯入和檢查收集到的數據

1.1 什麼是 LSL,它有什麼用處?

實驗室流層 (LSL) 是一個開源工具箱,可用於傳送、接收和同步來自各種感測器硬體的神經、生理和行為數據流。功能日益強大、精確且便攜的大腦與身體感測硬體裝置(如 Emotiv EEG 系統)正將神經科學從實驗室帶入即時數據的世界。過去,EEG 和 MEG 等大腦測量僅限於研究實驗室,而移動裝置讓我們能夠在更自然、更生活化的環境中,同時收集多個人的多種數據。

研究人員可能會對聆聽同一首音樂的兩個人之間的生理同步性感興趣。LSL 可以幫助我們分別收集兩個 EEG 頭戴式裝置的數據,並將這些數據與聲音的播放同步。

LSL 的其他用途範例:

  1. 將實驗中的事件標記加入到持續進行的 EEG 數據中

  2. 為單一受試者對齊來自多個來源的時間數據(例如心率、EMG、EEG)

  3. 對齊來自多個受試者的時間數據(例如 EEG 超掃描研究)

1.2 LSL 如何運作?

實驗室流層 (LSL) 是一種用於在多個裝置之間即時交換時間序列數據的協定。LSL 可以使用 Python、MATLAB、C++、Java 等程式語言的開源函式庫來實現。

核心功能圍繞著 LSL 數據流 (data streams) 展開:

1. 採集裝置/軟體收集數據並建立數據流 - 生理數據可以從 EEG 記錄裝置、眼動儀、動作捕捉系統、心率監測器等串流傳輸到 LSL,其中包含元數據(取樣率、數據類型、通道資訊等)- 來自實驗(例如使用 PsychoPy)的事件標記也可以使用 LSL 作為數據流傳送

2. 數據流被發佈 (published)到網絡 - 這是使用 LSL 傳送數據的方式;數據流被「廣播」到網絡 - 發佈的數據流在網絡上可用,並可被同一網絡上的其他支援 LSL 的裝置發現 - LSL 根據共同的時鐘(遵循網絡時間協定 NTP)為每個數據塊或樣本分配一個時間戳記。- 數據流通過一個「出口 (outlet)」逐個樣本(或逐個數據塊)推送

3. 收集裝置「訂閱 (subscribe)」數據流 - 這是使用 LSL 接收數據的方式 - 同一網絡上的收集裝置通過「入口 (inlets)」接收發佈的數據流。- 每個入口僅接收來自一個出口的數據流樣本和元數據

4. 儲存數據 - 訂閱數據流後,您可以將其儲存到您偏好程式語言的變數中,或使用 LSL 提供的軟體 LabRecorder 將其儲存為 .xdf 等標準格式。

2.0 教學概述

在本教學中,我們將以一個實驗設置為例,引導您完成在 Python 中使用 LSL 進行實作所需的步驟和程式碼。我們將使用 Python 播放聲音,同時從兩名配戴 Emotiv 頭戴式裝置的人員身上收集 EEG 數據。我們將使用兩台各自主行 EmotivPRO 的電腦來收集 EEG 數據,並通過單獨的 LSL 出口廣播每個數據流。我們將使用 Python 函式庫來播放音訊檔案,並在每次檔案開始播放時同步傳送觸發器。

步驟:

1. 使用 EmotivPRO 通過 LSL 出口串流傳輸數據,其中包括 EEG 數據(和/或動作、接觸品質、訊號品質等)。2. 使用 Python 腳本播放音軌,同時通過另一個 LSL 傳送觸發器。使用 LabRecorder 通過 LSL 入口擷取並儲存所有三個數據流。

2.1 步驟 1 - 設定與安裝

  1. 您需要準備支援的數據採集裝置來收集數據
    • 所有 Emotiv 的導電裝置均通過 EmotivPRO 軟體連接到 LSL

  2. 在您的裝置上安裝 EmotivPRO。您需要有效的 EmotivPRO 授權才能使用 LSL。

  3. 使用以下指令安裝 Python LSL 函式庫
    pip install pylsl

  4. 下載 LabRecorder 軟體。這是一個簡單、免費的應用程式,可以從
    命令列運行或使用獨立下載

  5. 針對我們的實驗:安裝使用 Python 播放音訊所需的套件
    pip install sounddevice soundfile

2.2 步驟 3 - 通過 LSL 數據流從 EmotivPRO 傳送數據

  1. 在應用程式右上角找到「...」,導覽至 Settings(設定)

  2. 找到「Lab Streaming Layer」區段和「Outlet」子區段

  3. 選擇您想要廣播的所有數據類型

  4. 選擇數據格式(32 位元浮點數或 64 位元雙精度浮點數)

  5. 選擇是要逐個樣本還是成塊樣本傳送數據

  6. 點擊「Start」以廣播 LSL 數據流


2.3 步驟 4 - 使用 Python 腳本播放音訊並傳送觸發器

  1. 將以下程式碼區塊複製並貼到 python 檔案中,然後儲存到您的電腦。

  2. 尋找您想要播放的音訊檔案(最好是 .wav 檔案),並點擊修改腳本,將
    變數 audio_filepath 變更為您電腦上音訊檔案的檔案路徑

  3. 開啟命令提示字元以與命令列進行互動,並導覽至儲存您的
    Python 檔案的資料夾

  4. 輸入:python3 filename.py
    • 根據您的 Python 安裝情況,您可能需要使用 python 而非 python3

    注意:請將 /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 步驟 5 - 使用 LabRecorder 檢視並儲存所有 LSL 數據流

  1. 開啟 LabRecorder

  2. 按下 Update。可用的 LSL 數據流應會顯示在數據流清單中
    • 您應該能看到來自兩個 EmotivPRO 的數據流(通常稱為「Emotiv-DataStream」)以及標記流(稱為「AudioMarkers」)

  3. 點擊 Browse 以選取儲存數據的位置(並設定其他參數)

  4. 選取所有數據流,然後按下 Record 開始記錄

3.0 使用數據

LabRecorder 會輸出一個 XDF 檔案(可延伸數據格式),其中包含來自所有數據流的數據。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 檔案標頭:", fileheader)
print("找到的數據流數量:", len(streams))

for i, stream in enumerate(streams):
    print("\n數據流", 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. 什麼是實驗室流層 (LSL) 以及研究人員為何使用它

  2. 如何從多個 Emotiv EEG 裝置收集同步數據

  3. 如何匯入和檢查收集到的數據

1.1 什麼是 LSL,它有什麼用處?

實驗室流層 (LSL) 是一個開源工具箱,可用於傳送、接收和同步來自各種感測器硬體的神經、生理和行為數據流。功能日益強大、精確且便攜的大腦與身體感測硬體裝置(如 Emotiv EEG 系統)正將神經科學從實驗室帶入即時數據的世界。過去,EEG 和 MEG 等大腦測量僅限於研究實驗室,而移動裝置讓我們能夠在更自然、更生活化的環境中,同時收集多個人的多種數據。

研究人員可能會對聆聽同一首音樂的兩個人之間的生理同步性感興趣。LSL 可以幫助我們分別收集兩個 EEG 頭戴式裝置的數據,並將這些數據與聲音的播放同步。

LSL 的其他用途範例:

  1. 將實驗中的事件標記加入到持續進行的 EEG 數據中

  2. 為單一受試者對齊來自多個來源的時間數據(例如心率、EMG、EEG)

  3. 對齊來自多個受試者的時間數據(例如 EEG 超掃描研究)

1.2 LSL 如何運作?

實驗室流層 (LSL) 是一種用於在多個裝置之間即時交換時間序列數據的協定。LSL 可以使用 Python、MATLAB、C++、Java 等程式語言的開源函式庫來實現。

核心功能圍繞著 LSL 數據流 (data streams) 展開:

1. 採集裝置/軟體收集數據並建立數據流 - 生理數據可以從 EEG 記錄裝置、眼動儀、動作捕捉系統、心率監測器等串流傳輸到 LSL,其中包含元數據(取樣率、數據類型、通道資訊等)- 來自實驗(例如使用 PsychoPy)的事件標記也可以使用 LSL 作為數據流傳送

2. 數據流被發佈 (published)到網絡 - 這是使用 LSL 傳送數據的方式;數據流被「廣播」到網絡 - 發佈的數據流在網絡上可用,並可被同一網絡上的其他支援 LSL 的裝置發現 - LSL 根據共同的時鐘(遵循網絡時間協定 NTP)為每個數據塊或樣本分配一個時間戳記。- 數據流通過一個「出口 (outlet)」逐個樣本(或逐個數據塊)推送

3. 收集裝置「訂閱 (subscribe)」數據流 - 這是使用 LSL 接收數據的方式 - 同一網絡上的收集裝置通過「入口 (inlets)」接收發佈的數據流。- 每個入口僅接收來自一個出口的數據流樣本和元數據

4. 儲存數據 - 訂閱數據流後,您可以將其儲存到您偏好程式語言的變數中,或使用 LSL 提供的軟體 LabRecorder 將其儲存為 .xdf 等標準格式。

2.0 教學概述

在本教學中,我們將以一個實驗設置為例,引導您完成在 Python 中使用 LSL 進行實作所需的步驟和程式碼。我們將使用 Python 播放聲音,同時從兩名配戴 Emotiv 頭戴式裝置的人員身上收集 EEG 數據。我們將使用兩台各自主行 EmotivPRO 的電腦來收集 EEG 數據,並通過單獨的 LSL 出口廣播每個數據流。我們將使用 Python 函式庫來播放音訊檔案,並在每次檔案開始播放時同步傳送觸發器。

步驟:

1. 使用 EmotivPRO 通過 LSL 出口串流傳輸數據,其中包括 EEG 數據(和/或動作、接觸品質、訊號品質等)。2. 使用 Python 腳本播放音軌,同時通過另一個 LSL 傳送觸發器。使用 LabRecorder 通過 LSL 入口擷取並儲存所有三個數據流。

2.1 步驟 1 - 設定與安裝

  1. 您需要準備支援的數據採集裝置來收集數據
    • 所有 Emotiv 的導電裝置均通過 EmotivPRO 軟體連接到 LSL

  2. 在您的裝置上安裝 EmotivPRO。您需要有效的 EmotivPRO 授權才能使用 LSL。

  3. 使用以下指令安裝 Python LSL 函式庫
    pip install pylsl

  4. 下載 LabRecorder 軟體。這是一個簡單、免費的應用程式,可以從
    命令列運行或使用獨立下載

  5. 針對我們的實驗:安裝使用 Python 播放音訊所需的套件
    pip install sounddevice soundfile

2.2 步驟 3 - 通過 LSL 數據流從 EmotivPRO 傳送數據

  1. 在應用程式右上角找到「...」,導覽至 Settings(設定)

  2. 找到「Lab Streaming Layer」區段和「Outlet」子區段

  3. 選擇您想要廣播的所有數據類型

  4. 選擇數據格式(32 位元浮點數或 64 位元雙精度浮點數)

  5. 選擇是要逐個樣本還是成塊樣本傳送數據

  6. 點擊「Start」以廣播 LSL 數據流


2.3 步驟 4 - 使用 Python 腳本播放音訊並傳送觸發器

  1. 將以下程式碼區塊複製並貼到 python 檔案中,然後儲存到您的電腦。

  2. 尋找您想要播放的音訊檔案(最好是 .wav 檔案),並點擊修改腳本,將
    變數 audio_filepath 變更為您電腦上音訊檔案的檔案路徑

  3. 開啟命令提示字元以與命令列進行互動,並導覽至儲存您的
    Python 檔案的資料夾

  4. 輸入:python3 filename.py
    • 根據您的 Python 安裝情況,您可能需要使用 python 而非 python3

    注意:請將 /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 步驟 5 - 使用 LabRecorder 檢視並儲存所有 LSL 數據流

  1. 開啟 LabRecorder

  2. 按下 Update。可用的 LSL 數據流應會顯示在數據流清單中
    • 您應該能看到來自兩個 EmotivPRO 的數據流(通常稱為「Emotiv-DataStream」)以及標記流(稱為「AudioMarkers」)

  3. 點擊 Browse 以選取儲存數據的位置(並設定其他參數)

  4. 選取所有數據流,然後按下 Record 開始記錄

3.0 使用數據

LabRecorder 會輸出一個 XDF 檔案(可延伸數據格式),其中包含來自所有數據流的數據。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 檔案標頭:", fileheader)
print("找到的數據流數量:", len(streams))

for i, stream in enumerate(streams):
    print("\n數據流", 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