
다중 데이터 스트림 동기화를 위한 Lab Streaming Layer (LSL)
로시니 란데니야(Roshini Randeniya) 박사와 루카스 클라이네(Lucas Kleine)
업데이트됨
2024. 5. 17.

다중 데이터 스트림 동기화를 위한 Lab Streaming Layer (LSL)
로시니 란데니야(Roshini Randeniya) 박사와 루카스 클라이네(Lucas Kleine)
업데이트됨
2024. 5. 17.

다중 데이터 스트림 동기화를 위한 Lab Streaming Layer (LSL)
로시니 란데니야(Roshini Randeniya) 박사와 루카스 클라이네(Lucas Kleine)
업데이트됨
2024. 5. 17.
환영합니다! 이 튜토리얼에서는 Python에서 LSL(Lab Streaming Layer)을 사용하여 여러 장치에서 Emotiv EEG 데이터를 수집하고 동기화하는 방법을 배웁니다. 이를 위해서는 Python 프로그래밍 언어에 대한 기본적인 실무 지식이 필요합니다.
배울 내용
Lab Streaming Layer(LSL)가 무엇이며 연구자들이 이를 사용하는 이유
여러 개의 Emotiv EEG 장치에서 동기화된 데이터를 수집하는 방법
수집된 데이터를 가져오고 검사하는 방법
1.1 LSL이란 무엇이며 어떤 용도로 유용한가요?
Lab Streaming Layer(LSL)는 다양한 센서 하드웨어로부터 실시간으로 뉴럴, 생리, 행동 데이터 스트림을 전송, 수신 및 동기화하는 데 사용할 수 있는 오픈 소스 툴박스입니다. 기능이 점점 더 뛰어나고 정밀하며 모바일화된 뇌 및 신체 감지 하드웨어 장치(예: Emotiv EEG 시스템) 덕분에 신경 과학 연구가 실험실 밖의 실시간 데이터 분야로 확장되고 있습니다. 과거에는 EEG 및 MEG와 같은 뇌 측정 장비가 연구실 내부로 제한되었지만, 모바일 장치를 사용하면 보다 자연스러운 환경에서 동시에 여러 사람으로부터 멀티플 데이터를 수집할 수 있습니다.
연구자가 동일한 음악을 듣는 두 사람 사이의 생리적 동기화에 관심이 있을 수 있습니다. LSL을 사용하면 두 개의 EEG 헤드셋에서 개별적으로 데이터를 수집하는 동시에 음원 재생과도 데이터를 동기화할 수 있습니다.
LSL의 기타 사용 예는 다음과 같습니다.
실험 진행 시 실시간 EEG 데이터에 이벤트 마커 추가
단일 참가자에 대한 여러 소스(예: 심박수, EMG, EEG)에서 전송되는 데이터의 시간 동기화
여러 참가자의 데이터 시간 동기화 (예: EEG 하이퍼스캐닝 연구)
1.2 LSL은 어떻게 작동하나요?
Lab Streaming Layer는 여러 장치 간에 시계열 데이터를 실시간으로 교환하기 위한 프로토콜입니다. LSL은 Python, MATLAB, C++, Java 등과 같은 프로그래밍 언어용 오픈 소스 라이브러리를 사용하여 구현할 수 있습니다.

핵심 기능은 LSL 데이터 스트림을 핵심으로 진행됩니다:
1. 수집 장치/소프트웨어가 데이터를 수집하고 데이터 스트림 생성 - 메타데이터(샘플링 속도, 데이터 유형, 채널 정보 등)를 포함하여 EEG 기록 장치, 아이트래커, 모션 캡처 시스템, 심박수 모니터 등에서 생리적 데이터를 LSL로 스트리밍할 수 있습니다. - 실험(예: PsychoPy 사용) 시 생성되는 높은 정밀도의 이벤트 마커 역시 LSL을 사용해 데이터 스트림으로 보낼 수 있습니다.
2. 데이터 스트림이 네트워크에 게시(Publish) 처리됨 - LSL을 사용하여 데이터를 전송하는 방식입니다. 데이터 스트림이 네트워크에 "브로드캐스트"됩니다. - 게시된 스트림은 네트워크에서 사용 가능하게 되며, 동일한 네트워크 상의 다른 LSL 지원 장치가 이를 검색할 수 있습니다. - LSL은 공통 클록(네트워크 시간 프로토콜(NTP) 준수)을 기반으로 각 데이터 청크 또는 샘플에 타임스탬프를 할당합니다. - 스트림은 "아울렛"을 통해 샘플 단위(또는 청크 단위)로 푸시됩니다.
3. 수집 장치들이 데이터 스트림을 "구독(Subscribe)"함 - LSL을 사용하여 데이터를 수신하는 방식입니다. - 동일한 네트워크 상의 수집 장치는 "인렛"을 통해 게시된 데이터 스트림을 수신합니다. - 각 인렛은 하나의 아울렛에서만 스트림 샘플과 메타데이터를 수신합니다.
4. 데이터 저장 - 데이터 스트림을 구독한 후 선호하는 프로그래밍 언어의 변수에 저장하거나, LSL에서 제공하는 LabRecorder 소프트웨어를 사용하여 .xdf와 같은 표준 형식으로 저장할 수 있습니다.
2.0 튜토리얼 개요
이 튜토리얼에서는 가상의 실험 설정을 예로 들어 Python에서 LSL을 사용하여 이를 구현하는 데 필요한 단계와 코드를 안내합니다. Emotiv 헤드셋을 착용한 두 사람으로부터 EEG 데이터를 수집하는 동안 Python으로 사운드를 재생할 것입니다. 각각 EmotivPRO를 실행하는 두 대의 컴퓨터를 사용하여 EEG 데이터를 수집하고, 각 스트림을 별도의 LSL 아울렛을 통해 브로드캐스트합니다. Python 라이브러리를 사용하여 오디오 파일을 재생하고 파일이 시작될 때마다 트리거를 동시에 전송하게 됩니다.
단계:
1. EmotivPRO를 사용하여 EEG 데이터(및/또는 모션, 접촉 품질, 신호 품질 등)를 포함하는 LSL 아울렛으로 데이터를 스트리밍합니다. 2. Python 스크립트를 사용하여 오디오 트랙을 재생하고, 동시에 다른 LSL로 트리거를 전송합니다. LabRecorder를 사용하여 LSL 인렛을 통해 세 개의 데이터 스트림을 모두 캡처하고 저장합니다.

2.1 1단계 - 설정 및 설치
데이터 수집을 위해 지원되는 데이터 수집 장치가 필요합니다.
• 모든 Emotiv 브레인웨어 장치는 EmotivPRO 소프트웨어를 통해 LSL에 연결됩니다.장치에 EmotivPRO를 설치합니다. LSL을 사용하려면 유효한 EmotivPRO 라이선스가 필요합니다.
다음 명령을 사용하여 Python LSL 라이브러리를 설치합니다.
pip install pylslLabRecorder 소프트웨어를 다운로드합니다. 이 앱은 명령줄에서 실행하거나 독립형 다운로드를 통해 실행할 수 있는 간편한 무료 앱입니다.
실험 진행용: Python을 사용하여 오디오를 재생하는 데 필요한 패키지를 설치합니다.
pip install sounddevice soundfile
2.2 3단계 - EmotivPRO에서 LSL 스트림을 통해 데이터 전송
앱의 오른쪽 상단에 있는 “...”을 찾아 Settings(설정)로 이동합니다.
‘Lab Streaming Layer’ 섹션과 ‘Outlet’ 하위 섹션을 찾습니다.
브로드캐스트하려는 모든 데이터 유형을 선택합니다.
데이터 형식(32비트 float 또는 64비트 double)을 선택합니다.
데이터를 샘플 단위로 보낼지 아니면 샘플 청크 단위로 보낼지 선택합니다.
LSL 데이터 스트림을 브로드캐스트하려면 'Start'를 클릭합니다.
2.3 4단계 - Python 스크립트를 사용하여 오디오 재생 및 트리거 전송
다음 코드 블록을 복사하여 Python 파일에 붙여넣고 컴퓨터에 저장합니다.
재생하려는 오디오 파일(가급적 .wav 파일)을 찾고, 변수
audio_filepath를 컴퓨터에 있는 해당 오디오 파일의 경로로 변경하여 스크립트를 편집합니다.명령 프롬프트를 열고 Python 파일이 저장된 폴더로 이동합니다.
python3 filename.py입력
• 설치 방식에 따라python3대신python을 사용할 수 있습니다.
참고:/path/to/audio.wav부분을 실험 중에 재생하려는 오디오 파일의 위치로 바꿉니다.
""" LSL Example: Play audio and send a trigger marker This script creates an LSL marker stream, waits for the user to press ENTER, then plays an audio file and sends a marker that can be synchronized with EEG data collected through LabRecorder. """ import sounddevice as sd import soundfile as sf from pylsl import StreamInfo, StreamOutlet def wait_for_keypress(): print("Press ENTER to start audio playback and send an LSL marker.") while True: if input() == "": break def play_audio_and_send_marker(audio_file, outlet): data, fs = sf.read(audio_file) print("Playing audio and sending LSL marker...") marker_val = [1] outlet.push_sample(marker_val) sd.play(data, fs) sd.wait() print("Audio playback finished.") 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 Example: Play audio and send a trigger marker This script creates an LSL marker stream, waits for the user to press ENTER, then plays an audio file and sends a marker that can be synchronized with EEG data collected through LabRecorder. """ import sounddevice as sd import soundfile as sf from pylsl import StreamInfo, StreamOutlet def wait_for_keypress(): print("Press ENTER to start audio playback and send an LSL marker.") while True: if input() == "": break def play_audio_and_send_marker(audio_file, outlet): data, fs = sf.read(audio_file) print("Playing audio and sending LSL marker...") marker_val = [1] outlet.push_sample(marker_val) sd.play(data, fs) sd.wait() print("Audio playback finished.") 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 Example: Play audio and send a trigger marker This script creates an LSL marker stream, waits for the user to press ENTER, then plays an audio file and sends a marker that can be synchronized with EEG data collected through LabRecorder. """ import sounddevice as sd import soundfile as sf from pylsl import StreamInfo, StreamOutlet def wait_for_keypress(): print("Press ENTER to start audio playback and send an LSL marker.") while True: if input() == "": break def play_audio_and_send_marker(audio_file, outlet): data, fs = sf.read(audio_file) print("Playing audio and sending LSL marker...") marker_val = [1] outlet.push_sample(marker_val) sd.play(data, fs) sd.wait() print("Audio playback finished.") 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 스트림 보기 및 저장
LabRecorder 열기
Update를 누릅니다. 사용 가능한 LSL 스트림이 스트림 목록에 표시되어야 합니다.
• 두 EmotivPRO의 스트림(대개 “Emotiv-DataStream”으로 표시)과 마커 스트림(“AudioMarkers”로 표시)이 나타나야 합니다.Browse를 클릭하여 데이터를 저장할 위치를 선택합니다(필요 시 다른 매개변수도 설정).모든 스트림을 선택하고
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 # Give the path to your LSL output file here. data_path = "/path/to/your/file.xdf" # Load the XDF file. 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 Name:", stream["info"]["name"][0]) print("Stream Type:", stream["info"]["type"][0]) print("Number of Channels:", stream["info"]["channel_count"][0]) sfreq = float(stream["info"]["nominal_srate"][0]) print("Sampling Rate:", sfreq) print("Number of Samples:", len(stream["time_series"])) print("First 5 data points:", 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"
import pyxdf import mne import matplotlib.pyplot as plt import numpy as np # Give the path to your LSL output file here. data_path = "/path/to/your/file.xdf" # Load the XDF file. 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 Name:", stream["info"]["name"][0]) print("Stream Type:", stream["info"]["type"][0]) print("Number of Channels:", stream["info"]["channel_count"][0]) sfreq = float(stream["info"]["nominal_srate"][0]) print("Sampling Rate:", sfreq) print("Number of Samples:", len(stream["time_series"])) print("First 5 data points:", 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"
import pyxdf import mne import matplotlib.pyplot as plt import numpy as np # Give the path to your LSL output file here. data_path = "/path/to/your/file.xdf" # Load the XDF file. 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 Name:", stream["info"]["name"][0]) print("Stream Type:", stream["info"]["type"][0]) print("Number of Channels:", stream["info"]["channel_count"][0]) sfreq = float(stream["info"]["nominal_srate"][0]) print("Sampling Rate:", sfreq) print("Number of Samples:", len(stream["time_series"])) print("First 5 data points:", 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"
4.0 추가 리소스
공식 문서
GitHub의 공식 README 파일을 포함하여 온라인 문서를 확인하십시오.
추가 리소스:
• 예제 스크립트와 함께 Emotiv 장치를 사용하여 LSL을 실행할 수 있는 코드
• 유용한 YouTube 상의 LSL 데모
• 모든 관련 라이브러리가 포함된 SCCN LSL GitHub 리포지토리
• 서브모듈 및 앱 컬렉션을 확인할 수 있는 LSL GitHub 리포지토리하이퍼스캐닝 연구를 위한 HyPyP 분석 파이프라인
환영합니다! 이 튜토리얼에서는 Python에서 LSL(Lab Streaming Layer)을 사용하여 여러 장치에서 Emotiv EEG 데이터를 수집하고 동기화하는 방법을 배웁니다. 이를 위해서는 Python 프로그래밍 언어에 대한 기본적인 실무 지식이 필요합니다.
배울 내용
Lab Streaming Layer(LSL)가 무엇이며 연구자들이 이를 사용하는 이유
여러 개의 Emotiv EEG 장치에서 동기화된 데이터를 수집하는 방법
수집된 데이터를 가져오고 검사하는 방법
1.1 LSL이란 무엇이며 어떤 용도로 유용한가요?
Lab Streaming Layer(LSL)는 다양한 센서 하드웨어로부터 실시간으로 뉴럴, 생리, 행동 데이터 스트림을 전송, 수신 및 동기화하는 데 사용할 수 있는 오픈 소스 툴박스입니다. 기능이 점점 더 뛰어나고 정밀하며 모바일화된 뇌 및 신체 감지 하드웨어 장치(예: Emotiv EEG 시스템) 덕분에 신경 과학 연구가 실험실 밖의 실시간 데이터 분야로 확장되고 있습니다. 과거에는 EEG 및 MEG와 같은 뇌 측정 장비가 연구실 내부로 제한되었지만, 모바일 장치를 사용하면 보다 자연스러운 환경에서 동시에 여러 사람으로부터 멀티플 데이터를 수집할 수 있습니다.
연구자가 동일한 음악을 듣는 두 사람 사이의 생리적 동기화에 관심이 있을 수 있습니다. LSL을 사용하면 두 개의 EEG 헤드셋에서 개별적으로 데이터를 수집하는 동시에 음원 재생과도 데이터를 동기화할 수 있습니다.
LSL의 기타 사용 예는 다음과 같습니다.
실험 진행 시 실시간 EEG 데이터에 이벤트 마커 추가
단일 참가자에 대한 여러 소스(예: 심박수, EMG, EEG)에서 전송되는 데이터의 시간 동기화
여러 참가자의 데이터 시간 동기화 (예: EEG 하이퍼스캐닝 연구)
1.2 LSL은 어떻게 작동하나요?
Lab Streaming Layer는 여러 장치 간에 시계열 데이터를 실시간으로 교환하기 위한 프로토콜입니다. LSL은 Python, MATLAB, C++, Java 등과 같은 프로그래밍 언어용 오픈 소스 라이브러리를 사용하여 구현할 수 있습니다.

핵심 기능은 LSL 데이터 스트림을 핵심으로 진행됩니다:
1. 수집 장치/소프트웨어가 데이터를 수집하고 데이터 스트림 생성 - 메타데이터(샘플링 속도, 데이터 유형, 채널 정보 등)를 포함하여 EEG 기록 장치, 아이트래커, 모션 캡처 시스템, 심박수 모니터 등에서 생리적 데이터를 LSL로 스트리밍할 수 있습니다. - 실험(예: PsychoPy 사용) 시 생성되는 높은 정밀도의 이벤트 마커 역시 LSL을 사용해 데이터 스트림으로 보낼 수 있습니다.
2. 데이터 스트림이 네트워크에 게시(Publish) 처리됨 - LSL을 사용하여 데이터를 전송하는 방식입니다. 데이터 스트림이 네트워크에 "브로드캐스트"됩니다. - 게시된 스트림은 네트워크에서 사용 가능하게 되며, 동일한 네트워크 상의 다른 LSL 지원 장치가 이를 검색할 수 있습니다. - LSL은 공통 클록(네트워크 시간 프로토콜(NTP) 준수)을 기반으로 각 데이터 청크 또는 샘플에 타임스탬프를 할당합니다. - 스트림은 "아울렛"을 통해 샘플 단위(또는 청크 단위)로 푸시됩니다.
3. 수집 장치들이 데이터 스트림을 "구독(Subscribe)"함 - LSL을 사용하여 데이터를 수신하는 방식입니다. - 동일한 네트워크 상의 수집 장치는 "인렛"을 통해 게시된 데이터 스트림을 수신합니다. - 각 인렛은 하나의 아울렛에서만 스트림 샘플과 메타데이터를 수신합니다.
4. 데이터 저장 - 데이터 스트림을 구독한 후 선호하는 프로그래밍 언어의 변수에 저장하거나, LSL에서 제공하는 LabRecorder 소프트웨어를 사용하여 .xdf와 같은 표준 형식으로 저장할 수 있습니다.
2.0 튜토리얼 개요
이 튜토리얼에서는 가상의 실험 설정을 예로 들어 Python에서 LSL을 사용하여 이를 구현하는 데 필요한 단계와 코드를 안내합니다. Emotiv 헤드셋을 착용한 두 사람으로부터 EEG 데이터를 수집하는 동안 Python으로 사운드를 재생할 것입니다. 각각 EmotivPRO를 실행하는 두 대의 컴퓨터를 사용하여 EEG 데이터를 수집하고, 각 스트림을 별도의 LSL 아울렛을 통해 브로드캐스트합니다. Python 라이브러리를 사용하여 오디오 파일을 재생하고 파일이 시작될 때마다 트리거를 동시에 전송하게 됩니다.
단계:
1. EmotivPRO를 사용하여 EEG 데이터(및/또는 모션, 접촉 품질, 신호 품질 등)를 포함하는 LSL 아울렛으로 데이터를 스트리밍합니다. 2. Python 스크립트를 사용하여 오디오 트랙을 재생하고, 동시에 다른 LSL로 트리거를 전송합니다. LabRecorder를 사용하여 LSL 인렛을 통해 세 개의 데이터 스트림을 모두 캡처하고 저장합니다.

2.1 1단계 - 설정 및 설치
데이터 수집을 위해 지원되는 데이터 수집 장치가 필요합니다.
• 모든 Emotiv 브레인웨어 장치는 EmotivPRO 소프트웨어를 통해 LSL에 연결됩니다.장치에 EmotivPRO를 설치합니다. LSL을 사용하려면 유효한 EmotivPRO 라이선스가 필요합니다.
다음 명령을 사용하여 Python LSL 라이브러리를 설치합니다.
pip install pylslLabRecorder 소프트웨어를 다운로드합니다. 이 앱은 명령줄에서 실행하거나 독립형 다운로드를 통해 실행할 수 있는 간편한 무료 앱입니다.
실험 진행용: Python을 사용하여 오디오를 재생하는 데 필요한 패키지를 설치합니다.
pip install sounddevice soundfile
2.2 3단계 - EmotivPRO에서 LSL 스트림을 통해 데이터 전송
앱의 오른쪽 상단에 있는 “...”을 찾아 Settings(설정)로 이동합니다.
‘Lab Streaming Layer’ 섹션과 ‘Outlet’ 하위 섹션을 찾습니다.
브로드캐스트하려는 모든 데이터 유형을 선택합니다.
데이터 형식(32비트 float 또는 64비트 double)을 선택합니다.
데이터를 샘플 단위로 보낼지 아니면 샘플 청크 단위로 보낼지 선택합니다.
LSL 데이터 스트림을 브로드캐스트하려면 'Start'를 클릭합니다.
2.3 4단계 - Python 스크립트를 사용하여 오디오 재생 및 트리거 전송
다음 코드 블록을 복사하여 Python 파일에 붙여넣고 컴퓨터에 저장합니다.
재생하려는 오디오 파일(가급적 .wav 파일)을 찾고, 변수
audio_filepath를 컴퓨터에 있는 해당 오디오 파일의 경로로 변경하여 스크립트를 편집합니다.명령 프롬프트를 열고 Python 파일이 저장된 폴더로 이동합니다.
python3 filename.py입력
• 설치 방식에 따라python3대신python을 사용할 수 있습니다.
참고:/path/to/audio.wav부분을 실험 중에 재생하려는 오디오 파일의 위치로 바꿉니다.
""" LSL Example: Play audio and send a trigger marker This script creates an LSL marker stream, waits for the user to press ENTER, then plays an audio file and sends a marker that can be synchronized with EEG data collected through LabRecorder. """ import sounddevice as sd import soundfile as sf from pylsl import StreamInfo, StreamOutlet def wait_for_keypress(): print("Press ENTER to start audio playback and send an LSL marker.") while True: if input() == "": break def play_audio_and_send_marker(audio_file, outlet): data, fs = sf.read(audio_file) print("Playing audio and sending LSL marker...") marker_val = [1] outlet.push_sample(marker_val) sd.play(data, fs) sd.wait() print("Audio playback finished.") 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 스트림 보기 및 저장
LabRecorder 열기
Update를 누릅니다. 사용 가능한 LSL 스트림이 스트림 목록에 표시되어야 합니다.
• 두 EmotivPRO의 스트림(대개 “Emotiv-DataStream”으로 표시)과 마커 스트림(“AudioMarkers”로 표시)이 나타나야 합니다.Browse를 클릭하여 데이터를 저장할 위치를 선택합니다(필요 시 다른 매개변수도 설정).모든 스트림을 선택하고
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 # Give the path to your LSL output file here. data_path = "/path/to/your/file.xdf" # Load the XDF file. 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 Name:", stream["info"]["name"][0]) print("Stream Type:", stream["info"]["type"][0]) print("Number of Channels:", stream["info"]["channel_count"][0]) sfreq = float(stream["info"]["nominal_srate"][0]) print("Sampling Rate:", sfreq) print("Number of Samples:", len(stream["time_series"])) print("First 5 data points:", 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"
4.0 추가 리소스
공식 문서
GitHub의 공식 README 파일을 포함하여 온라인 문서를 확인하십시오.
추가 리소스:
• 예제 스크립트와 함께 Emotiv 장치를 사용하여 LSL을 실행할 수 있는 코드
• 유용한 YouTube 상의 LSL 데모
• 모든 관련 라이브러리가 포함된 SCCN LSL GitHub 리포지토리
• 서브모듈 및 앱 컬렉션을 확인할 수 있는 LSL GitHub 리포지토리하이퍼스캐닝 연구를 위한 HyPyP 분석 파이프라인
환영합니다! 이 튜토리얼에서는 Python에서 LSL(Lab Streaming Layer)을 사용하여 여러 장치에서 Emotiv EEG 데이터를 수집하고 동기화하는 방법을 배웁니다. 이를 위해서는 Python 프로그래밍 언어에 대한 기본적인 실무 지식이 필요합니다.
배울 내용
Lab Streaming Layer(LSL)가 무엇이며 연구자들이 이를 사용하는 이유
여러 개의 Emotiv EEG 장치에서 동기화된 데이터를 수집하는 방법
수집된 데이터를 가져오고 검사하는 방법
1.1 LSL이란 무엇이며 어떤 용도로 유용한가요?
Lab Streaming Layer(LSL)는 다양한 센서 하드웨어로부터 실시간으로 뉴럴, 생리, 행동 데이터 스트림을 전송, 수신 및 동기화하는 데 사용할 수 있는 오픈 소스 툴박스입니다. 기능이 점점 더 뛰어나고 정밀하며 모바일화된 뇌 및 신체 감지 하드웨어 장치(예: Emotiv EEG 시스템) 덕분에 신경 과학 연구가 실험실 밖의 실시간 데이터 분야로 확장되고 있습니다. 과거에는 EEG 및 MEG와 같은 뇌 측정 장비가 연구실 내부로 제한되었지만, 모바일 장치를 사용하면 보다 자연스러운 환경에서 동시에 여러 사람으로부터 멀티플 데이터를 수집할 수 있습니다.
연구자가 동일한 음악을 듣는 두 사람 사이의 생리적 동기화에 관심이 있을 수 있습니다. LSL을 사용하면 두 개의 EEG 헤드셋에서 개별적으로 데이터를 수집하는 동시에 음원 재생과도 데이터를 동기화할 수 있습니다.
LSL의 기타 사용 예는 다음과 같습니다.
실험 진행 시 실시간 EEG 데이터에 이벤트 마커 추가
단일 참가자에 대한 여러 소스(예: 심박수, EMG, EEG)에서 전송되는 데이터의 시간 동기화
여러 참가자의 데이터 시간 동기화 (예: EEG 하이퍼스캐닝 연구)
1.2 LSL은 어떻게 작동하나요?
Lab Streaming Layer는 여러 장치 간에 시계열 데이터를 실시간으로 교환하기 위한 프로토콜입니다. LSL은 Python, MATLAB, C++, Java 등과 같은 프로그래밍 언어용 오픈 소스 라이브러리를 사용하여 구현할 수 있습니다.

핵심 기능은 LSL 데이터 스트림을 핵심으로 진행됩니다:
1. 수집 장치/소프트웨어가 데이터를 수집하고 데이터 스트림 생성 - 메타데이터(샘플링 속도, 데이터 유형, 채널 정보 등)를 포함하여 EEG 기록 장치, 아이트래커, 모션 캡처 시스템, 심박수 모니터 등에서 생리적 데이터를 LSL로 스트리밍할 수 있습니다. - 실험(예: PsychoPy 사용) 시 생성되는 높은 정밀도의 이벤트 마커 역시 LSL을 사용해 데이터 스트림으로 보낼 수 있습니다.
2. 데이터 스트림이 네트워크에 게시(Publish) 처리됨 - LSL을 사용하여 데이터를 전송하는 방식입니다. 데이터 스트림이 네트워크에 "브로드캐스트"됩니다. - 게시된 스트림은 네트워크에서 사용 가능하게 되며, 동일한 네트워크 상의 다른 LSL 지원 장치가 이를 검색할 수 있습니다. - LSL은 공통 클록(네트워크 시간 프로토콜(NTP) 준수)을 기반으로 각 데이터 청크 또는 샘플에 타임스탬프를 할당합니다. - 스트림은 "아울렛"을 통해 샘플 단위(또는 청크 단위)로 푸시됩니다.
3. 수집 장치들이 데이터 스트림을 "구독(Subscribe)"함 - LSL을 사용하여 데이터를 수신하는 방식입니다. - 동일한 네트워크 상의 수집 장치는 "인렛"을 통해 게시된 데이터 스트림을 수신합니다. - 각 인렛은 하나의 아울렛에서만 스트림 샘플과 메타데이터를 수신합니다.
4. 데이터 저장 - 데이터 스트림을 구독한 후 선호하는 프로그래밍 언어의 변수에 저장하거나, LSL에서 제공하는 LabRecorder 소프트웨어를 사용하여 .xdf와 같은 표준 형식으로 저장할 수 있습니다.
2.0 튜토리얼 개요
이 튜토리얼에서는 가상의 실험 설정을 예로 들어 Python에서 LSL을 사용하여 이를 구현하는 데 필요한 단계와 코드를 안내합니다. Emotiv 헤드셋을 착용한 두 사람으로부터 EEG 데이터를 수집하는 동안 Python으로 사운드를 재생할 것입니다. 각각 EmotivPRO를 실행하는 두 대의 컴퓨터를 사용하여 EEG 데이터를 수집하고, 각 스트림을 별도의 LSL 아울렛을 통해 브로드캐스트합니다. Python 라이브러리를 사용하여 오디오 파일을 재생하고 파일이 시작될 때마다 트리거를 동시에 전송하게 됩니다.
단계:
1. EmotivPRO를 사용하여 EEG 데이터(및/또는 모션, 접촉 품질, 신호 품질 등)를 포함하는 LSL 아울렛으로 데이터를 스트리밍합니다. 2. Python 스크립트를 사용하여 오디오 트랙을 재생하고, 동시에 다른 LSL로 트리거를 전송합니다. LabRecorder를 사용하여 LSL 인렛을 통해 세 개의 데이터 스트림을 모두 캡처하고 저장합니다.

2.1 1단계 - 설정 및 설치
데이터 수집을 위해 지원되는 데이터 수집 장치가 필요합니다.
• 모든 Emotiv 브레인웨어 장치는 EmotivPRO 소프트웨어를 통해 LSL에 연결됩니다.장치에 EmotivPRO를 설치합니다. LSL을 사용하려면 유효한 EmotivPRO 라이선스가 필요합니다.
다음 명령을 사용하여 Python LSL 라이브러리를 설치합니다.
pip install pylslLabRecorder 소프트웨어를 다운로드합니다. 이 앱은 명령줄에서 실행하거나 독립형 다운로드를 통해 실행할 수 있는 간편한 무료 앱입니다.
실험 진행용: Python을 사용하여 오디오를 재생하는 데 필요한 패키지를 설치합니다.
pip install sounddevice soundfile
2.2 3단계 - EmotivPRO에서 LSL 스트림을 통해 데이터 전송
앱의 오른쪽 상단에 있는 “...”을 찾아 Settings(설정)로 이동합니다.
‘Lab Streaming Layer’ 섹션과 ‘Outlet’ 하위 섹션을 찾습니다.
브로드캐스트하려는 모든 데이터 유형을 선택합니다.
데이터 형식(32비트 float 또는 64비트 double)을 선택합니다.
데이터를 샘플 단위로 보낼지 아니면 샘플 청크 단위로 보낼지 선택합니다.
LSL 데이터 스트림을 브로드캐스트하려면 'Start'를 클릭합니다.
2.3 4단계 - Python 스크립트를 사용하여 오디오 재생 및 트리거 전송
다음 코드 블록을 복사하여 Python 파일에 붙여넣고 컴퓨터에 저장합니다.
재생하려는 오디오 파일(가급적 .wav 파일)을 찾고, 변수
audio_filepath를 컴퓨터에 있는 해당 오디오 파일의 경로로 변경하여 스크립트를 편집합니다.명령 프롬프트를 열고 Python 파일이 저장된 폴더로 이동합니다.
python3 filename.py입력
• 설치 방식에 따라python3대신python을 사용할 수 있습니다.
참고:/path/to/audio.wav부분을 실험 중에 재생하려는 오디오 파일의 위치로 바꿉니다.
""" LSL Example: Play audio and send a trigger marker This script creates an LSL marker stream, waits for the user to press ENTER, then plays an audio file and sends a marker that can be synchronized with EEG data collected through LabRecorder. """ import sounddevice as sd import soundfile as sf from pylsl import StreamInfo, StreamOutlet def wait_for_keypress(): print("Press ENTER to start audio playback and send an LSL marker.") while True: if input() == "": break def play_audio_and_send_marker(audio_file, outlet): data, fs = sf.read(audio_file) print("Playing audio and sending LSL marker...") marker_val = [1] outlet.push_sample(marker_val) sd.play(data, fs) sd.wait() print("Audio playback finished.") 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 스트림 보기 및 저장
LabRecorder 열기
Update를 누릅니다. 사용 가능한 LSL 스트림이 스트림 목록에 표시되어야 합니다.
• 두 EmotivPRO의 스트림(대개 “Emotiv-DataStream”으로 표시)과 마커 스트림(“AudioMarkers”로 표시)이 나타나야 합니다.Browse를 클릭하여 데이터를 저장할 위치를 선택합니다(필요 시 다른 매개변수도 설정).모든 스트림을 선택하고
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 # Give the path to your LSL output file here. data_path = "/path/to/your/file.xdf" # Load the XDF file. 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 Name:", stream["info"]["name"][0]) print("Stream Type:", stream["info"]["type"][0]) print("Number of Channels:", stream["info"]["channel_count"][0]) sfreq = float(stream["info"]["nominal_srate"][0]) print("Sampling Rate:", sfreq) print("Number of Samples:", len(stream["time_series"])) print("First 5 data points:", 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"
4.0 추가 리소스
공식 문서
GitHub의 공식 README 파일을 포함하여 온라인 문서를 확인하십시오.
추가 리소스:
• 예제 스크립트와 함께 Emotiv 장치를 사용하여 LSL을 실행할 수 있는 코드
• 유용한 YouTube 상의 LSL 데모
• 모든 관련 라이브러리가 포함된 SCCN LSL GitHub 리포지토리
• 서브모듈 및 앱 컬렉션을 확인할 수 있는 LSL GitHub 리포지토리하이퍼스캐닝 연구를 위한 HyPyP 분석 파이프라인

계속 읽기