
طبقة تدفق المختبر (LSL) لمزامنة تدفقات البيانات المتعددة
د. روشيني راندينيا ولوكاس كلاينه
تم التحديث في
17/05/2024

طبقة تدفق المختبر (LSL) لمزامنة تدفقات البيانات المتعددة
د. روشيني راندينيا ولوكاس كلاينه
تم التحديث في
17/05/2024

طبقة تدفق المختبر (LSL) لمزامنة تدفقات البيانات المتعددة
د. روشيني راندينيا ولوكاس كلاينه
تم التحديث في
17/05/2024
مرحباً! في هذا البرنامج التعليمي سوف نتعلم كيفية استخدام تفاضل طبقة التدفق المخبري (Lab Streaming Layer) أو ما يعرف بـ LSL في Python لجمع ومزامنة بيانات EEG من أجهزة Emotiv المتعددة. ويتطلب ذلك معرفة عملية أساسية بلغة البرمجة Python.
ما ستتعلمه
ما هو الـ Lab Streaming Layer (LSL) ولماذا يستخدمه الباحثون
كيفية جمع البيانات المتزامنة من عدة أجهزة Emotiv EEG
كيفية استيراد وفحص البيانات التي تم جمعها
1.1 ما هو الـ LSL وما هي فائدته؟
تعد طبقة تدفق المختبر (LSL) عبارة عن صندوق أدوات مفتوح المصدر يمكن استخدامه لإرسال واستقبال ومزامنة تدفقات البيانات العصبية والفسيولوجية والسلوكية من أجهزة استشعار مختلفة. حيث أصبحت أجهزة استشعار الدماغ والجسم المتنقلة والدقيقة وذات القدرات المتزايدة (مثل أنظمة Emotiv EEG) تنقل علم الأعصاب خارج المختبر إلى عالم البيانات في الوقت الفعلي. وحيث كانت قياسات الدماغ مثل EEG وMEG مقتصرة في السابق على مختبرات الأبحاث، تتيح لنا الأجهزة المحمولة جمع تدفقات متعددة من البيانات في بيئات طبيعية أكثر، ومن عدة أشخاص في نفس الوقت.
قد يهتم الباحث بالتزامن الفسيولوجي بين شخصين يستمعان إلى نفس الموسيقى. حيث يمكن أن يساعدنا الـ LSL في جمع البيانات من سماعتي رأس EEG بشكل منفصل والتي تتم مزامنتها أيضاً مع عرض الصوت.
بعض الأمثلة على الاستخدامات الأخرى للـ LSL:
إضافة علامات الحدث من تجربة ما إلى بيانات EEG مستمرة
محاذاة البيانات زمنياً من مصادر متعددة لمشارك واحد (مثل معدل ضربات القلب، وتخطيط كهربية العضل EMG، وتخطيط كهربية الدماغ EEG)
محاذاة البيانات زمنياً من عدة مشاركين (مثل دراسات المسح المفرط لتخطيط كهربية الدماغ EEG Hyperscanning)
1.1 كيف يعمل الـ LSL؟
يعد الـ Lab Streaming Layer بروتوكولاً لتبادل البيانات ذات السلاسل الزمنية في الوقت الفعلي بين أجهزة متعددة. ويمكن تنفيذ LSL باستخدام مكتبات مفتوحة المصدر للغات البرمجة مثل Python وMATLAB وC++ وJava وغيرها.

تتمحور الوظيفة الأساسية حول تدفقات بيانات LSL:
1. يقوم جهاز/برنامج لجمع البيانات بإنشاء تدفق للبيانات - حيث يمكن دفق البيانات الفسيولوجية إلى LSL من أجهزة تسجيل EEG، وأجهزة تتبع العين، وأنظمة التقاط الحركة، وأجهزة مراقبة معدل ضربات القلب، وما إلى ذلك، بما في ذلك البيانات الوصفية (معدل أخذ العينات، ونوع البيانات، ومعلومات القناة، وما إلى ذلك) - ويمكن أيضاً إرسال علامات الحدث من التجارب (على سبيل المثال باستخدام PsychoPy) كتدفق بيانات باستخدام LSL.
2. يتم نشر تدفق البيانات على الشبكة - هذه هي طريقة إرسال البيانات باستخدام LSL؛ حيث يتم "بث" تدفق البيانات إلى الشبكة - وتكون التدفقات المنشورة متاحة على الشبكة ويمكن اكتشافها بواسطة الأجهزة الأخرى التي تدعم LSL على نفس الشبكة - كما يعين LSL لكل جزء بيانات أو عينة طابعاً زمنياً بناءً على ساعة مشتركة (باتباع بروتوكول وقت الشبكة). - ويتم دفع التدفق عينة بعينة (أو جزءاً بجزء) من خلال "منفذ مخرج".
3. تقوم أجهزة الجمع "بالاشتراك" في تدفق (تدفقات) البيانات - هذه هي كيفية تلقي البيانات باستخدام LSL - وتتلقى أجهزة الجمع الموجودة على الشبكة نفسها تدفقات البيانات المنشورة عبر "منافذ المداخل". - يتلقى كل مدخل عينات التدفق والبيانات الوصفية من منفذ مخرج واحد فقط.
4. حفظ البيانات - عند الاشتراك في تدفق البيانات، يمكنك حفظه في متغير بلغة البرمجة المفضلة لديك، أو استخدام برنامج LabRecorder المتوفر من LSL لحفظه بصيغة قياسية مثل .xdf.
2.0 نظرة عامة على البرنامج التعليمي
سنأخذ في هذا البرنامج التعليمي مثالاً لإعداد تجريبي ونرشدك عبر الخطوات والرموز البرمجية اللازمة لتنفيذه باستخدام LSL في Python. حيث سنستخدم لغة Python لتشغيل صوت أثناء جمع بيانات EEG من شخصين يرتديان سماعات رأس Emotiv. وسنستخدم جهازي كمبيوتر يعمل كل منهما بنظام EmotivPRO لجمع بيانات EEG وبث كل تيار تدفق من خلال مخرج LSL منفصل. وسنستخدم مكتبة Python لتشغيل ملف صوتي وإرسال محفز في نفس الوقت في كل مرة يبدأ فيها الملف.
الخطوات:
1. استخدام EmotivPRO لدفق البيانات عبر مخارج LSL التي تتضمن بيانات EEG (و/أو الحركة، وجودة الاتصال، وجودة الإشارة، وما إلى ذلك) 2. تشغيل مسار صوتي باستخدام برنامج Python النصي، وإرسال محفز في نفس الوقت عبر LSL آخر واستخدام LabRecorder لالتقاط وحفظ جميع تدفقات البيانات الثلاثة من خلال مدخل LSL.

2.1 الخطوة 1 - الإعداد والتثبيت
ستحتاج إلى أجهزة معتمدة لجمع البيانات لجمع البيانات
• تتصل جميع أجهزة Emotiv الدماغية بـ LSL عبر برنامج EmotivPROقم بتثبيت EmotivPRO على جهازك (أجهزتك). ستحتاج إلى ترخيص EmotivPRO صالح لاستخدام LSL.
قم بتثبيت مكتبة Python LSL باستخدام الأمر التالي:
pip install pylslقم بتنزيل برنامج LabRecorder. وهو تطبيق بسيط ومجاني يمكن تشغيله من
خلال سطر الأوامر أو باستخدام تنزيل مستقلبالنسبة لتجربتنا: قم بتثبيت الحزم اللازمة لتشغيل الصوت باستخدام Python
pip install sounddevice soundfile
2.2 الخطوة 3 - إرسال البيانات من EmotivPRO عبر تدفق LSL
حدد موقع الرمز “...” في الزاوية العلوية اليمنى من التطبيق، وانتقل إلى الإعدادات
ابحث عن قسم 'Lab Streaming Layer' والقسم الفرعي 'Outlet'
حدد جميع أنواع البيانات التي ترغب في بثها
حدد تنسيق البيانات (32-bit float او 64-bit double)
حدد ما إذا كنت تريد إرسال البيانات عينة بعينة أو في أجزاء من العينات
انقر فوق 'Start' لبث تدفق بيانات LSL
2.3 الخطوة 4 - استخدام برنامج Python النصي لتشغيل الصوت وإرسال المحفزات
انسخ كتل الأكواد البرمجية التالية وانشرها في ملف python واحفظها على جهاز الكمبيوتر الخاص بك.
حدد موقع ملف صوتي (يفضل أن يكون ملف بتنسيق .wav) تريد تشغيله وقم بتحرير البرنامج النصي عن طريق تغيير
المتغيرaudio_filepathإلى مسار الملف لملفك الصوتي على جهاز الكمبيوتر الخاص بكافتح موجه الأوامر للتفاعل مع سطر الأوامر وانتقل إلى المجلد الموجود فيه
ملف Python الخاص بكأدخل:
python3 filename.py
• اعتماداً على تثبيت Python الخاص بك، قد تستخدمpythonبدلاً منpython3
ملاحظة: استبدل/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 من تدفقات بيانات بملفات ترويسة (Header) مختلفة تصف ما تحتويه (اسم الجهاز، ونوع البيانات، ومعدل أخذ العينات، والقنوات، والمزيد). ويمكنك استخدام الكود البرمجي أدناه لفتح ملف 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 مصادر إضافية
الوثائق الرسمية
تحقق من الوثائق عبر الإنترنت، بما في ذلك ملف README الرسمي على GitHub
مصادر إضافية:
• كود لتشغيل LSL باستخدام أجهزة Emotiv، مع سيناريوهات أمثلة برمجة نصية
• عرض LSL مفيد على YouTube
• مستودع SCCN LSL على GitHub لجميع المكتبات المرتبطة
• مستودع LSL على GitHub لمجموعة من الوحدات الفرعية والتطبيقاتمسار تحليل HyPyP لدراسات المسح المفرط Hyperscanning
مرحباً! في هذا البرنامج التعليمي سوف نتعلم كيفية استخدام تفاضل طبقة التدفق المخبري (Lab Streaming Layer) أو ما يعرف بـ LSL في Python لجمع ومزامنة بيانات EEG من أجهزة Emotiv المتعددة. ويتطلب ذلك معرفة عملية أساسية بلغة البرمجة Python.
ما ستتعلمه
ما هو الـ Lab Streaming Layer (LSL) ولماذا يستخدمه الباحثون
كيفية جمع البيانات المتزامنة من عدة أجهزة Emotiv EEG
كيفية استيراد وفحص البيانات التي تم جمعها
1.1 ما هو الـ LSL وما هي فائدته؟
تعد طبقة تدفق المختبر (LSL) عبارة عن صندوق أدوات مفتوح المصدر يمكن استخدامه لإرسال واستقبال ومزامنة تدفقات البيانات العصبية والفسيولوجية والسلوكية من أجهزة استشعار مختلفة. حيث أصبحت أجهزة استشعار الدماغ والجسم المتنقلة والدقيقة وذات القدرات المتزايدة (مثل أنظمة Emotiv EEG) تنقل علم الأعصاب خارج المختبر إلى عالم البيانات في الوقت الفعلي. وحيث كانت قياسات الدماغ مثل EEG وMEG مقتصرة في السابق على مختبرات الأبحاث، تتيح لنا الأجهزة المحمولة جمع تدفقات متعددة من البيانات في بيئات طبيعية أكثر، ومن عدة أشخاص في نفس الوقت.
قد يهتم الباحث بالتزامن الفسيولوجي بين شخصين يستمعان إلى نفس الموسيقى. حيث يمكن أن يساعدنا الـ LSL في جمع البيانات من سماعتي رأس EEG بشكل منفصل والتي تتم مزامنتها أيضاً مع عرض الصوت.
بعض الأمثلة على الاستخدامات الأخرى للـ LSL:
إضافة علامات الحدث من تجربة ما إلى بيانات EEG مستمرة
محاذاة البيانات زمنياً من مصادر متعددة لمشارك واحد (مثل معدل ضربات القلب، وتخطيط كهربية العضل EMG، وتخطيط كهربية الدماغ EEG)
محاذاة البيانات زمنياً من عدة مشاركين (مثل دراسات المسح المفرط لتخطيط كهربية الدماغ EEG Hyperscanning)
1.1 كيف يعمل الـ LSL؟
يعد الـ Lab Streaming Layer بروتوكولاً لتبادل البيانات ذات السلاسل الزمنية في الوقت الفعلي بين أجهزة متعددة. ويمكن تنفيذ LSL باستخدام مكتبات مفتوحة المصدر للغات البرمجة مثل Python وMATLAB وC++ وJava وغيرها.

تتمحور الوظيفة الأساسية حول تدفقات بيانات LSL:
1. يقوم جهاز/برنامج لجمع البيانات بإنشاء تدفق للبيانات - حيث يمكن دفق البيانات الفسيولوجية إلى LSL من أجهزة تسجيل EEG، وأجهزة تتبع العين، وأنظمة التقاط الحركة، وأجهزة مراقبة معدل ضربات القلب، وما إلى ذلك، بما في ذلك البيانات الوصفية (معدل أخذ العينات، ونوع البيانات، ومعلومات القناة، وما إلى ذلك) - ويمكن أيضاً إرسال علامات الحدث من التجارب (على سبيل المثال باستخدام PsychoPy) كتدفق بيانات باستخدام LSL.
2. يتم نشر تدفق البيانات على الشبكة - هذه هي طريقة إرسال البيانات باستخدام LSL؛ حيث يتم "بث" تدفق البيانات إلى الشبكة - وتكون التدفقات المنشورة متاحة على الشبكة ويمكن اكتشافها بواسطة الأجهزة الأخرى التي تدعم LSL على نفس الشبكة - كما يعين LSL لكل جزء بيانات أو عينة طابعاً زمنياً بناءً على ساعة مشتركة (باتباع بروتوكول وقت الشبكة). - ويتم دفع التدفق عينة بعينة (أو جزءاً بجزء) من خلال "منفذ مخرج".
3. تقوم أجهزة الجمع "بالاشتراك" في تدفق (تدفقات) البيانات - هذه هي كيفية تلقي البيانات باستخدام LSL - وتتلقى أجهزة الجمع الموجودة على الشبكة نفسها تدفقات البيانات المنشورة عبر "منافذ المداخل". - يتلقى كل مدخل عينات التدفق والبيانات الوصفية من منفذ مخرج واحد فقط.
4. حفظ البيانات - عند الاشتراك في تدفق البيانات، يمكنك حفظه في متغير بلغة البرمجة المفضلة لديك، أو استخدام برنامج LabRecorder المتوفر من LSL لحفظه بصيغة قياسية مثل .xdf.
2.0 نظرة عامة على البرنامج التعليمي
سنأخذ في هذا البرنامج التعليمي مثالاً لإعداد تجريبي ونرشدك عبر الخطوات والرموز البرمجية اللازمة لتنفيذه باستخدام LSL في Python. حيث سنستخدم لغة Python لتشغيل صوت أثناء جمع بيانات EEG من شخصين يرتديان سماعات رأس Emotiv. وسنستخدم جهازي كمبيوتر يعمل كل منهما بنظام EmotivPRO لجمع بيانات EEG وبث كل تيار تدفق من خلال مخرج LSL منفصل. وسنستخدم مكتبة Python لتشغيل ملف صوتي وإرسال محفز في نفس الوقت في كل مرة يبدأ فيها الملف.
الخطوات:
1. استخدام EmotivPRO لدفق البيانات عبر مخارج LSL التي تتضمن بيانات EEG (و/أو الحركة، وجودة الاتصال، وجودة الإشارة، وما إلى ذلك) 2. تشغيل مسار صوتي باستخدام برنامج Python النصي، وإرسال محفز في نفس الوقت عبر LSL آخر واستخدام LabRecorder لالتقاط وحفظ جميع تدفقات البيانات الثلاثة من خلال مدخل LSL.

2.1 الخطوة 1 - الإعداد والتثبيت
ستحتاج إلى أجهزة معتمدة لجمع البيانات لجمع البيانات
• تتصل جميع أجهزة Emotiv الدماغية بـ LSL عبر برنامج EmotivPROقم بتثبيت EmotivPRO على جهازك (أجهزتك). ستحتاج إلى ترخيص EmotivPRO صالح لاستخدام LSL.
قم بتثبيت مكتبة Python LSL باستخدام الأمر التالي:
pip install pylslقم بتنزيل برنامج LabRecorder. وهو تطبيق بسيط ومجاني يمكن تشغيله من
خلال سطر الأوامر أو باستخدام تنزيل مستقلبالنسبة لتجربتنا: قم بتثبيت الحزم اللازمة لتشغيل الصوت باستخدام Python
pip install sounddevice soundfile
2.2 الخطوة 3 - إرسال البيانات من EmotivPRO عبر تدفق LSL
حدد موقع الرمز “...” في الزاوية العلوية اليمنى من التطبيق، وانتقل إلى الإعدادات
ابحث عن قسم 'Lab Streaming Layer' والقسم الفرعي 'Outlet'
حدد جميع أنواع البيانات التي ترغب في بثها
حدد تنسيق البيانات (32-bit float او 64-bit double)
حدد ما إذا كنت تريد إرسال البيانات عينة بعينة أو في أجزاء من العينات
انقر فوق 'Start' لبث تدفق بيانات LSL
2.3 الخطوة 4 - استخدام برنامج Python النصي لتشغيل الصوت وإرسال المحفزات
انسخ كتل الأكواد البرمجية التالية وانشرها في ملف python واحفظها على جهاز الكمبيوتر الخاص بك.
حدد موقع ملف صوتي (يفضل أن يكون ملف بتنسيق .wav) تريد تشغيله وقم بتحرير البرنامج النصي عن طريق تغيير
المتغيرaudio_filepathإلى مسار الملف لملفك الصوتي على جهاز الكمبيوتر الخاص بكافتح موجه الأوامر للتفاعل مع سطر الأوامر وانتقل إلى المجلد الموجود فيه
ملف Python الخاص بكأدخل:
python3 filename.py
• اعتماداً على تثبيت Python الخاص بك، قد تستخدمpythonبدلاً منpython3
ملاحظة: استبدل/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 من تدفقات بيانات بملفات ترويسة (Header) مختلفة تصف ما تحتويه (اسم الجهاز، ونوع البيانات، ومعدل أخذ العينات، والقنوات، والمزيد). ويمكنك استخدام الكود البرمجي أدناه لفتح ملف 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 مصادر إضافية
الوثائق الرسمية
تحقق من الوثائق عبر الإنترنت، بما في ذلك ملف README الرسمي على GitHub
مصادر إضافية:
• كود لتشغيل LSL باستخدام أجهزة Emotiv، مع سيناريوهات أمثلة برمجة نصية
• عرض LSL مفيد على YouTube
• مستودع SCCN LSL على GitHub لجميع المكتبات المرتبطة
• مستودع LSL على GitHub لمجموعة من الوحدات الفرعية والتطبيقاتمسار تحليل HyPyP لدراسات المسح المفرط Hyperscanning
مرحباً! في هذا البرنامج التعليمي سوف نتعلم كيفية استخدام تفاضل طبقة التدفق المخبري (Lab Streaming Layer) أو ما يعرف بـ LSL في Python لجمع ومزامنة بيانات EEG من أجهزة Emotiv المتعددة. ويتطلب ذلك معرفة عملية أساسية بلغة البرمجة Python.
ما ستتعلمه
ما هو الـ Lab Streaming Layer (LSL) ولماذا يستخدمه الباحثون
كيفية جمع البيانات المتزامنة من عدة أجهزة Emotiv EEG
كيفية استيراد وفحص البيانات التي تم جمعها
1.1 ما هو الـ LSL وما هي فائدته؟
تعد طبقة تدفق المختبر (LSL) عبارة عن صندوق أدوات مفتوح المصدر يمكن استخدامه لإرسال واستقبال ومزامنة تدفقات البيانات العصبية والفسيولوجية والسلوكية من أجهزة استشعار مختلفة. حيث أصبحت أجهزة استشعار الدماغ والجسم المتنقلة والدقيقة وذات القدرات المتزايدة (مثل أنظمة Emotiv EEG) تنقل علم الأعصاب خارج المختبر إلى عالم البيانات في الوقت الفعلي. وحيث كانت قياسات الدماغ مثل EEG وMEG مقتصرة في السابق على مختبرات الأبحاث، تتيح لنا الأجهزة المحمولة جمع تدفقات متعددة من البيانات في بيئات طبيعية أكثر، ومن عدة أشخاص في نفس الوقت.
قد يهتم الباحث بالتزامن الفسيولوجي بين شخصين يستمعان إلى نفس الموسيقى. حيث يمكن أن يساعدنا الـ LSL في جمع البيانات من سماعتي رأس EEG بشكل منفصل والتي تتم مزامنتها أيضاً مع عرض الصوت.
بعض الأمثلة على الاستخدامات الأخرى للـ LSL:
إضافة علامات الحدث من تجربة ما إلى بيانات EEG مستمرة
محاذاة البيانات زمنياً من مصادر متعددة لمشارك واحد (مثل معدل ضربات القلب، وتخطيط كهربية العضل EMG، وتخطيط كهربية الدماغ EEG)
محاذاة البيانات زمنياً من عدة مشاركين (مثل دراسات المسح المفرط لتخطيط كهربية الدماغ EEG Hyperscanning)
1.1 كيف يعمل الـ LSL؟
يعد الـ Lab Streaming Layer بروتوكولاً لتبادل البيانات ذات السلاسل الزمنية في الوقت الفعلي بين أجهزة متعددة. ويمكن تنفيذ LSL باستخدام مكتبات مفتوحة المصدر للغات البرمجة مثل Python وMATLAB وC++ وJava وغيرها.

تتمحور الوظيفة الأساسية حول تدفقات بيانات LSL:
1. يقوم جهاز/برنامج لجمع البيانات بإنشاء تدفق للبيانات - حيث يمكن دفق البيانات الفسيولوجية إلى LSL من أجهزة تسجيل EEG، وأجهزة تتبع العين، وأنظمة التقاط الحركة، وأجهزة مراقبة معدل ضربات القلب، وما إلى ذلك، بما في ذلك البيانات الوصفية (معدل أخذ العينات، ونوع البيانات، ومعلومات القناة، وما إلى ذلك) - ويمكن أيضاً إرسال علامات الحدث من التجارب (على سبيل المثال باستخدام PsychoPy) كتدفق بيانات باستخدام LSL.
2. يتم نشر تدفق البيانات على الشبكة - هذه هي طريقة إرسال البيانات باستخدام LSL؛ حيث يتم "بث" تدفق البيانات إلى الشبكة - وتكون التدفقات المنشورة متاحة على الشبكة ويمكن اكتشافها بواسطة الأجهزة الأخرى التي تدعم LSL على نفس الشبكة - كما يعين LSL لكل جزء بيانات أو عينة طابعاً زمنياً بناءً على ساعة مشتركة (باتباع بروتوكول وقت الشبكة). - ويتم دفع التدفق عينة بعينة (أو جزءاً بجزء) من خلال "منفذ مخرج".
3. تقوم أجهزة الجمع "بالاشتراك" في تدفق (تدفقات) البيانات - هذه هي كيفية تلقي البيانات باستخدام LSL - وتتلقى أجهزة الجمع الموجودة على الشبكة نفسها تدفقات البيانات المنشورة عبر "منافذ المداخل". - يتلقى كل مدخل عينات التدفق والبيانات الوصفية من منفذ مخرج واحد فقط.
4. حفظ البيانات - عند الاشتراك في تدفق البيانات، يمكنك حفظه في متغير بلغة البرمجة المفضلة لديك، أو استخدام برنامج LabRecorder المتوفر من LSL لحفظه بصيغة قياسية مثل .xdf.
2.0 نظرة عامة على البرنامج التعليمي
سنأخذ في هذا البرنامج التعليمي مثالاً لإعداد تجريبي ونرشدك عبر الخطوات والرموز البرمجية اللازمة لتنفيذه باستخدام LSL في Python. حيث سنستخدم لغة Python لتشغيل صوت أثناء جمع بيانات EEG من شخصين يرتديان سماعات رأس Emotiv. وسنستخدم جهازي كمبيوتر يعمل كل منهما بنظام EmotivPRO لجمع بيانات EEG وبث كل تيار تدفق من خلال مخرج LSL منفصل. وسنستخدم مكتبة Python لتشغيل ملف صوتي وإرسال محفز في نفس الوقت في كل مرة يبدأ فيها الملف.
الخطوات:
1. استخدام EmotivPRO لدفق البيانات عبر مخارج LSL التي تتضمن بيانات EEG (و/أو الحركة، وجودة الاتصال، وجودة الإشارة، وما إلى ذلك) 2. تشغيل مسار صوتي باستخدام برنامج Python النصي، وإرسال محفز في نفس الوقت عبر LSL آخر واستخدام LabRecorder لالتقاط وحفظ جميع تدفقات البيانات الثلاثة من خلال مدخل LSL.

2.1 الخطوة 1 - الإعداد والتثبيت
ستحتاج إلى أجهزة معتمدة لجمع البيانات لجمع البيانات
• تتصل جميع أجهزة Emotiv الدماغية بـ LSL عبر برنامج EmotivPROقم بتثبيت EmotivPRO على جهازك (أجهزتك). ستحتاج إلى ترخيص EmotivPRO صالح لاستخدام LSL.
قم بتثبيت مكتبة Python LSL باستخدام الأمر التالي:
pip install pylslقم بتنزيل برنامج LabRecorder. وهو تطبيق بسيط ومجاني يمكن تشغيله من
خلال سطر الأوامر أو باستخدام تنزيل مستقلبالنسبة لتجربتنا: قم بتثبيت الحزم اللازمة لتشغيل الصوت باستخدام Python
pip install sounddevice soundfile
2.2 الخطوة 3 - إرسال البيانات من EmotivPRO عبر تدفق LSL
حدد موقع الرمز “...” في الزاوية العلوية اليمنى من التطبيق، وانتقل إلى الإعدادات
ابحث عن قسم 'Lab Streaming Layer' والقسم الفرعي 'Outlet'
حدد جميع أنواع البيانات التي ترغب في بثها
حدد تنسيق البيانات (32-bit float او 64-bit double)
حدد ما إذا كنت تريد إرسال البيانات عينة بعينة أو في أجزاء من العينات
انقر فوق 'Start' لبث تدفق بيانات LSL
2.3 الخطوة 4 - استخدام برنامج Python النصي لتشغيل الصوت وإرسال المحفزات
انسخ كتل الأكواد البرمجية التالية وانشرها في ملف python واحفظها على جهاز الكمبيوتر الخاص بك.
حدد موقع ملف صوتي (يفضل أن يكون ملف بتنسيق .wav) تريد تشغيله وقم بتحرير البرنامج النصي عن طريق تغيير
المتغيرaudio_filepathإلى مسار الملف لملفك الصوتي على جهاز الكمبيوتر الخاص بكافتح موجه الأوامر للتفاعل مع سطر الأوامر وانتقل إلى المجلد الموجود فيه
ملف Python الخاص بكأدخل:
python3 filename.py
• اعتماداً على تثبيت Python الخاص بك، قد تستخدمpythonبدلاً منpython3
ملاحظة: استبدل/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 من تدفقات بيانات بملفات ترويسة (Header) مختلفة تصف ما تحتويه (اسم الجهاز، ونوع البيانات، ومعدل أخذ العينات، والقنوات، والمزيد). ويمكنك استخدام الكود البرمجي أدناه لفتح ملف 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 مصادر إضافية
الوثائق الرسمية
تحقق من الوثائق عبر الإنترنت، بما في ذلك ملف README الرسمي على GitHub
مصادر إضافية:
• كود لتشغيل LSL باستخدام أجهزة Emotiv، مع سيناريوهات أمثلة برمجة نصية
• عرض LSL مفيد على YouTube
• مستودع SCCN LSL على GitHub لجميع المكتبات المرتبطة
• مستودع LSL على GitHub لمجموعة من الوحدات الفرعية والتطبيقاتمسار تحليل HyPyP لدراسات المسح المفرط Hyperscanning

تابع القراءة