Lab Streaming Layer (LSL) để đồng bộ hóa nhiều luồng dữ liệu

Roshini Randeniya

1 thg 10, 2025

Chia sẻ:

của Roshini RandeniyaLucas Kleine

Hoạt động:
Một khi được chạy trong dòng lệnh, kịch bản này sẽ ngay lập tức khởi tạo một luồng LSL. Mỗi khi phím 'Enter' được nhấn, nó sẽ gửi một tín hiệu kích hoạt và phát một tệp âm thanh."""

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

def wait_for_keypress():
print("Nhấn ENTER để bắt đầu phát âm thanh và gửi một marker LSL.")

while True: # This loop waits for a keyboard input
    input_str = input()  # Wait for input from the terminal
    if input_str == "":  # If the enter key is pressed, proceed
        break

def AudioMarker(audio_file, outlet): # hàm để phát âm thanh và gửi marker
data, fs = sf.read(audio_file) # Tải tệp âm thanh

print("Playing audio and sending LSL marker...")
marker_val = [1]
outlet.push_sample(marker_val) # Send marker indicating the start of audio playback
sd.play(data, fs) # play the audio
sd.wait()  # Wait until audio is done playing
print("Audio playback finished.")

if name == "main": # VÒNG LẶP CHÍNH
# Thiết lập luồng LSL cho các marker
stream_name = 'AudioMarkers'
stream_type = 'Markers'
n_chans = 1
sr = 0 # Đặt tần suất lấy mẫu thành 0 vì các marker là không đều
chan_format = 'int32'
marker_id = 'uniqueMarkerID12345'

info = StreamInfo(stream_name, stream_type, n_chans, sr, chan_format, marker_id)
outlet = StreamOutlet(info) # create LSL outlet

# Keep the script running and wait for ENTER key to play audio and send marker
while True:
    wait_for_keypress()
    audio_filepath = "/path/to/your/audio_file.wav"  # replace with correct path to your audio file
    AudioMarker(audio_filepath, outlet)
    # After playing audio and sending a marker, the script goes back to waiting for the next keypress</code></pre><p><em><strong>**By running this file (even before playing the audio), you've initiated an LSL stream through an outlet</strong></em><strong>. Now we'll view that stream in LabRecorder</strong></p><p><strong>STEP 5 - Use LabRecorder to view and save all LSL streams</strong></p><ol><li data-preset-tag="p"><p>Open LabRecorder</p></li><li data-preset-tag="p"><p>Press <em><strong>Update</strong></em>. The available LSL streams should be visible in the stream list<br> • You should be able to see streams from both EmotivPROs (usually called "EmotivDataStream") and the marker stream (called "AudioMarkers")</p></li><li data-preset-tag="p"><p>Click <em><strong>Browse</strong></em> to select a location to store data (and set other parameters)</p></li><li data-preset-tag="p"><p>Select all streams and press <em><strong>Record</strong></em> to start recording</p></li><li data-preset-tag="p"><p>Click Stop when you want to end the recording</p></li></ol><p><br></p><img alt="" src="https://framerusercontent.com/images/HFGuJF9ErVu2Jxrgtqt11tl0No.jpg"><h2><strong>Working with the data</strong></h2><p><strong>LabRecorder outputs an XDF file (Extensible Data Format) that contains data from all the streams. XDF files are structured into, </strong><em><strong>streams</strong></em><strong>, each with a different </strong><em><strong>header</strong></em><strong> that describes what it contains (device name, data type, sampling rate, channels, and more). You can use the below codeblock to open your XDF file and display some basic information.</strong></p><pre data-language="JSX"><code>

Kịch bản ví dụ này cho thấy một vài chức năng cơ bản để nhập và chú thích dữ liệu EEG được thu thập từ phần mềm EmotivPRO. Nó sử dụng MNE để tải một tệp XDF, in một số dữ liệu siêu thông tin cơ bản, tạo một đối tượng info và vẽ phổ công suất."""

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

Đường dẫn đến tệp XDF của bạn

data_path = '/path/to/your/xdf_file.xdf'

Tải tệp XDF

streams, fileheader = pyxdf.load_xdf(data_path)
print("Tiêu đề tệp XDF:", fileheader)
print("Số lượng luồng được tìm thấy:", len(streams))

for i, stream in enumerate(streams):
print("\nLuồng", i + 1)
print("Tên Luồng:", stream['info']['name'][0])
print("Loại Luồng:", stream['info']['type'][0])
print("Số Kênh:", stream['info']['channel_count'][0])
sfreq = float(stream['info']['nominal_srate'][0])
print("Tần suất lấy mẫu:", sfreq)
print("Số lượng mẫu:", len(stream['time_series']))
print("In 5 điểm dữ liệu đầu tiên:", stream['time_series'][:5])

channel_names = [chan['label'][0] for chan in stream['info']['desc'][0]['channels'][0]['channel']]
print("Channel Names:", channel_names)
channel_types = 'eeg'

Tạo đối tượng thông tin MNE

info = mne.create_info(channel_names, sfreq, channel_types)
data = np.array(stream['time_series']).T # Dữ liệu cần được chuyển vị: kênh x mẫu
raw = mne.io.RawArray(data, info)
raw.plot_psd(fmax=50) # vẽ một phổ đồ đơn giản (mật độ phổ công suất)Tài nguyên bổ sungTải hướng dẫn này dưới dạng sổ tay Jupyter từ GitHub EMOTIVTìm hiểu tài liệu trực tuyến LSL, bao gồm tệp README chính thức trên GitHubBạn sẽ cần một hoặc nhiều thiết bị thu thập dữ liệu được hỗ trợ để thu thập dữ liệuTất cả các thiết bị não của EMOTIV đều kết nối với phần mềm EmotivPRO, mà có các khả năng tích hợp LSL để gửi và nhận luồng dữ liệuTài nguyên bổ sung:Mã để chạy LSL với các thiết bị của Emotiv, với các kịch bản ví dụBản demo LSL hữu ích trên YouTubeKho lưu trữ GitHub SCCN LSL cho tất cả các thư viện liên quanKho lưu trữ GitHub cho bộ sưu tập các mô-đun con và ứng dụngĐường ống phân tích HyPyP cho các nghiên cứu Hyperscanning

của Roshini RandeniyaLucas Kleine

Hoạt động:
Một khi được chạy trong dòng lệnh, kịch bản này sẽ ngay lập tức khởi tạo một luồng LSL. Mỗi khi phím 'Enter' được nhấn, nó sẽ gửi một tín hiệu kích hoạt và phát một tệp âm thanh."""

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

def wait_for_keypress():
print("Nhấn ENTER để bắt đầu phát âm thanh và gửi một marker LSL.")

while True: # This loop waits for a keyboard input
    input_str = input()  # Wait for input from the terminal
    if input_str == "":  # If the enter key is pressed, proceed
        break

def AudioMarker(audio_file, outlet): # hàm để phát âm thanh và gửi marker
data, fs = sf.read(audio_file) # Tải tệp âm thanh

print("Playing audio and sending LSL marker...")
marker_val = [1]
outlet.push_sample(marker_val) # Send marker indicating the start of audio playback
sd.play(data, fs) # play the audio
sd.wait()  # Wait until audio is done playing
print("Audio playback finished.")

if name == "main": # VÒNG LẶP CHÍNH
# Thiết lập luồng LSL cho các marker
stream_name = 'AudioMarkers'
stream_type = 'Markers'
n_chans = 1
sr = 0 # Đặt tần suất lấy mẫu thành 0 vì các marker là không đều
chan_format = 'int32'
marker_id = 'uniqueMarkerID12345'

info = StreamInfo(stream_name, stream_type, n_chans, sr, chan_format, marker_id)
outlet = StreamOutlet(info) # create LSL outlet

# Keep the script running and wait for ENTER key to play audio and send marker
while True:
    wait_for_keypress()
    audio_filepath = "/path/to/your/audio_file.wav"  # replace with correct path to your audio file
    AudioMarker(audio_filepath, outlet)
    # After playing audio and sending a marker, the script goes back to waiting for the next keypress</code></pre><p><em><strong>**By running this file (even before playing the audio), you've initiated an LSL stream through an outlet</strong></em><strong>. Now we'll view that stream in LabRecorder</strong></p><p><strong>STEP 5 - Use LabRecorder to view and save all LSL streams</strong></p><ol><li data-preset-tag="p"><p>Open LabRecorder</p></li><li data-preset-tag="p"><p>Press <em><strong>Update</strong></em>. The available LSL streams should be visible in the stream list<br> • You should be able to see streams from both EmotivPROs (usually called "EmotivDataStream") and the marker stream (called "AudioMarkers")</p></li><li data-preset-tag="p"><p>Click <em><strong>Browse</strong></em> to select a location to store data (and set other parameters)</p></li><li data-preset-tag="p"><p>Select all streams and press <em><strong>Record</strong></em> to start recording</p></li><li data-preset-tag="p"><p>Click Stop when you want to end the recording</p></li></ol><p><br></p><img alt="" src="https://framerusercontent.com/images/HFGuJF9ErVu2Jxrgtqt11tl0No.jpg"><h2><strong>Working with the data</strong></h2><p><strong>LabRecorder outputs an XDF file (Extensible Data Format) that contains data from all the streams. XDF files are structured into, </strong><em><strong>streams</strong></em><strong>, each with a different </strong><em><strong>header</strong></em><strong> that describes what it contains (device name, data type, sampling rate, channels, and more). You can use the below codeblock to open your XDF file and display some basic information.</strong></p><pre data-language="JSX"><code>

Kịch bản ví dụ này cho thấy một vài chức năng cơ bản để nhập và chú thích dữ liệu EEG được thu thập từ phần mềm EmotivPRO. Nó sử dụng MNE để tải một tệp XDF, in một số dữ liệu siêu thông tin cơ bản, tạo một đối tượng info và vẽ phổ công suất."""

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

Đường dẫn đến tệp XDF của bạn

data_path = '/path/to/your/xdf_file.xdf'

Tải tệp XDF

streams, fileheader = pyxdf.load_xdf(data_path)
print("Tiêu đề tệp XDF:", fileheader)
print("Số lượng luồng được tìm thấy:", len(streams))

for i, stream in enumerate(streams):
print("\nLuồng", i + 1)
print("Tên Luồng:", stream['info']['name'][0])
print("Loại Luồng:", stream['info']['type'][0])
print("Số Kênh:", stream['info']['channel_count'][0])
sfreq = float(stream['info']['nominal_srate'][0])
print("Tần suất lấy mẫu:", sfreq)
print("Số lượng mẫu:", len(stream['time_series']))
print("In 5 điểm dữ liệu đầu tiên:", stream['time_series'][:5])

channel_names = [chan['label'][0] for chan in stream['info']['desc'][0]['channels'][0]['channel']]
print("Channel Names:", channel_names)
channel_types = 'eeg'

Tạo đối tượng thông tin MNE

info = mne.create_info(channel_names, sfreq, channel_types)
data = np.array(stream['time_series']).T # Dữ liệu cần được chuyển vị: kênh x mẫu
raw = mne.io.RawArray(data, info)
raw.plot_psd(fmax=50) # vẽ một phổ đồ đơn giản (mật độ phổ công suất)Tài nguyên bổ sungTải hướng dẫn này dưới dạng sổ tay Jupyter từ GitHub EMOTIVTìm hiểu tài liệu trực tuyến LSL, bao gồm tệp README chính thức trên GitHubBạn sẽ cần một hoặc nhiều thiết bị thu thập dữ liệu được hỗ trợ để thu thập dữ liệuTất cả các thiết bị não của EMOTIV đều kết nối với phần mềm EmotivPRO, mà có các khả năng tích hợp LSL để gửi và nhận luồng dữ liệuTài nguyên bổ sung:Mã để chạy LSL với các thiết bị của Emotiv, với các kịch bản ví dụBản demo LSL hữu ích trên YouTubeKho lưu trữ GitHub SCCN LSL cho tất cả các thư viện liên quanKho lưu trữ GitHub cho bộ sưu tập các mô-đun con và ứng dụngĐường ống phân tích HyPyP cho các nghiên cứu Hyperscanning

của Roshini RandeniyaLucas Kleine

Hoạt động:
Một khi được chạy trong dòng lệnh, kịch bản này sẽ ngay lập tức khởi tạo một luồng LSL. Mỗi khi phím 'Enter' được nhấn, nó sẽ gửi một tín hiệu kích hoạt và phát một tệp âm thanh."""

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

def wait_for_keypress():
print("Nhấn ENTER để bắt đầu phát âm thanh và gửi một marker LSL.")

while True: # This loop waits for a keyboard input
    input_str = input()  # Wait for input from the terminal
    if input_str == "":  # If the enter key is pressed, proceed
        break

def AudioMarker(audio_file, outlet): # hàm để phát âm thanh và gửi marker
data, fs = sf.read(audio_file) # Tải tệp âm thanh

print("Playing audio and sending LSL marker...")
marker_val = [1]
outlet.push_sample(marker_val) # Send marker indicating the start of audio playback
sd.play(data, fs) # play the audio
sd.wait()  # Wait until audio is done playing
print("Audio playback finished.")

if name == "main": # VÒNG LẶP CHÍNH
# Thiết lập luồng LSL cho các marker
stream_name = 'AudioMarkers'
stream_type = 'Markers'
n_chans = 1
sr = 0 # Đặt tần suất lấy mẫu thành 0 vì các marker là không đều
chan_format = 'int32'
marker_id = 'uniqueMarkerID12345'

info = StreamInfo(stream_name, stream_type, n_chans, sr, chan_format, marker_id)
outlet = StreamOutlet(info) # create LSL outlet

# Keep the script running and wait for ENTER key to play audio and send marker
while True:
    wait_for_keypress()
    audio_filepath = "/path/to/your/audio_file.wav"  # replace with correct path to your audio file
    AudioMarker(audio_filepath, outlet)
    # After playing audio and sending a marker, the script goes back to waiting for the next keypress</code></pre><p><em><strong>**By running this file (even before playing the audio), you've initiated an LSL stream through an outlet</strong></em><strong>. Now we'll view that stream in LabRecorder</strong></p><p><strong>STEP 5 - Use LabRecorder to view and save all LSL streams</strong></p><ol><li data-preset-tag="p"><p>Open LabRecorder</p></li><li data-preset-tag="p"><p>Press <em><strong>Update</strong></em>. The available LSL streams should be visible in the stream list<br> • You should be able to see streams from both EmotivPROs (usually called "EmotivDataStream") and the marker stream (called "AudioMarkers")</p></li><li data-preset-tag="p"><p>Click <em><strong>Browse</strong></em> to select a location to store data (and set other parameters)</p></li><li data-preset-tag="p"><p>Select all streams and press <em><strong>Record</strong></em> to start recording</p></li><li data-preset-tag="p"><p>Click Stop when you want to end the recording</p></li></ol><p><br></p><img alt="" src="https://framerusercontent.com/images/HFGuJF9ErVu2Jxrgtqt11tl0No.jpg"><h2><strong>Working with the data</strong></h2><p><strong>LabRecorder outputs an XDF file (Extensible Data Format) that contains data from all the streams. XDF files are structured into, </strong><em><strong>streams</strong></em><strong>, each with a different </strong><em><strong>header</strong></em><strong> that describes what it contains (device name, data type, sampling rate, channels, and more). You can use the below codeblock to open your XDF file and display some basic information.</strong></p><pre data-language="JSX"><code>

Kịch bản ví dụ này cho thấy một vài chức năng cơ bản để nhập và chú thích dữ liệu EEG được thu thập từ phần mềm EmotivPRO. Nó sử dụng MNE để tải một tệp XDF, in một số dữ liệu siêu thông tin cơ bản, tạo một đối tượng info và vẽ phổ công suất."""

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

Đường dẫn đến tệp XDF của bạn

data_path = '/path/to/your/xdf_file.xdf'

Tải tệp XDF

streams, fileheader = pyxdf.load_xdf(data_path)
print("Tiêu đề tệp XDF:", fileheader)
print("Số lượng luồng được tìm thấy:", len(streams))

for i, stream in enumerate(streams):
print("\nLuồng", i + 1)
print("Tên Luồng:", stream['info']['name'][0])
print("Loại Luồng:", stream['info']['type'][0])
print("Số Kênh:", stream['info']['channel_count'][0])
sfreq = float(stream['info']['nominal_srate'][0])
print("Tần suất lấy mẫu:", sfreq)
print("Số lượng mẫu:", len(stream['time_series']))
print("In 5 điểm dữ liệu đầu tiên:", stream['time_series'][:5])

channel_names = [chan['label'][0] for chan in stream['info']['desc'][0]['channels'][0]['channel']]
print("Channel Names:", channel_names)
channel_types = 'eeg'

Tạo đối tượng thông tin MNE

info = mne.create_info(channel_names, sfreq, channel_types)
data = np.array(stream['time_series']).T # Dữ liệu cần được chuyển vị: kênh x mẫu
raw = mne.io.RawArray(data, info)
raw.plot_psd(fmax=50) # vẽ một phổ đồ đơn giản (mật độ phổ công suất)Tài nguyên bổ sungTải hướng dẫn này dưới dạng sổ tay Jupyter từ GitHub EMOTIVTìm hiểu tài liệu trực tuyến LSL, bao gồm tệp README chính thức trên GitHubBạn sẽ cần một hoặc nhiều thiết bị thu thập dữ liệu được hỗ trợ để thu thập dữ liệuTất cả các thiết bị não của EMOTIV đều kết nối với phần mềm EmotivPRO, mà có các khả năng tích hợp LSL để gửi và nhận luồng dữ liệuTài nguyên bổ sung:Mã để chạy LSL với các thiết bị của Emotiv, với các kịch bản ví dụBản demo LSL hữu ích trên YouTubeKho lưu trữ GitHub SCCN LSL cho tất cả các thư viện liên quanKho lưu trữ GitHub cho bộ sưu tập các mô-đun con và ứng dụngĐường ống phân tích HyPyP cho các nghiên cứu Hyperscanning

Tiếp tục đọc

Cơ bản về Dao động Thần kinh

© 2025 EMOTIV, Tất cả các quyền được bảo lưu.

Consent

Lựa Chọn Riêng Tư Của Bạn (Cài Đặt Cookie)

*Lưu ý – Sản phẩm EMOTIV được sử dụng cho các ứng dụng nghiên cứu và sử dụng cá nhân mà thôi. Sản phẩm của chúng tôi không được bán như là Thiết bị Y tế theo định nghĩa trong chỉ thị EU 93/42/EEC. Sản phẩm của chúng tôi không được thiết kế hoặc dự định để sử dụng cho việc chẩn đoán hoặc điều trị bệnh.

Lưu ý về Dịch thuật: Các phiên bản không tiếng Anh của trang web này đã được dịch để thuận tiện cho bạn bằng cách sử dụng trí tuệ nhân tạo. Mặc dù chúng tôi cố gắng đạt được độ chính xác, các bản dịch tự động có thể chứa lỗi hoặc sắc thái khác với văn bản gốc. Để có thông tin chính xác nhất, vui lòng tham khảo phiên bản tiếng Anh của trang web này.

© 2025 EMOTIV, Tất cả các quyền được bảo lưu.

Consent

Lựa Chọn Riêng Tư Của Bạn (Cài Đặt Cookie)

*Lưu ý – Sản phẩm EMOTIV được sử dụng cho các ứng dụng nghiên cứu và sử dụng cá nhân mà thôi. Sản phẩm của chúng tôi không được bán như là Thiết bị Y tế theo định nghĩa trong chỉ thị EU 93/42/EEC. Sản phẩm của chúng tôi không được thiết kế hoặc dự định để sử dụng cho việc chẩn đoán hoặc điều trị bệnh.

Lưu ý về Dịch thuật: Các phiên bản không tiếng Anh của trang web này đã được dịch để thuận tiện cho bạn bằng cách sử dụng trí tuệ nhân tạo. Mặc dù chúng tôi cố gắng đạt được độ chính xác, các bản dịch tự động có thể chứa lỗi hoặc sắc thái khác với văn bản gốc. Để có thông tin chính xác nhất, vui lòng tham khảo phiên bản tiếng Anh của trang web này.

© 2025 EMOTIV, Tất cả các quyền được bảo lưu.

Consent

Lựa Chọn Riêng Tư Của Bạn (Cài Đặt Cookie)

*Lưu ý – Sản phẩm EMOTIV được sử dụng cho các ứng dụng nghiên cứu và sử dụng cá nhân mà thôi. Sản phẩm của chúng tôi không được bán như là Thiết bị Y tế theo định nghĩa trong chỉ thị EU 93/42/EEC. Sản phẩm của chúng tôi không được thiết kế hoặc dự định để sử dụng cho việc chẩn đoán hoặc điều trị bệnh.

Lưu ý về Dịch thuật: Các phiên bản không tiếng Anh của trang web này đã được dịch để thuận tiện cho bạn bằng cách sử dụng trí tuệ nhân tạo. Mặc dù chúng tôi cố gắng đạt được độ chính xác, các bản dịch tự động có thể chứa lỗi hoặc sắc thái khác với văn bản gốc. Để có thông tin chính xác nhất, vui lòng tham khảo phiên bản tiếng Anh của trang web này.