المحطة 10 · الدرس 4
كتابة plugin
eeglab_data.set (D1) · لا شيء: البيانات كما نزّلتها.تنزيل البيانات (يفتح في نافذة جديدة)سكربت الوصول لهذه الحالة
[ALLEEG, EEG, CURRENTSET, ALLCOM] = eeglab;
eeglabRoot = fileparts(which('eeglab'));
EEG = pop_loadset('eeglab_data.set', fullfile(eeglabRoot, 'sample_data'));
% Show the dataset in the main EEGLAB window
[ALLEEG, EEG, CURRENTSET] = pop_newset(ALLEEG, EEG, 0, 'setname', 'D1 raw', 'gui', 'off');
eeglab redraw;زر الرجوع في متصفحك يعيدك لنفس المكان الذي كنت فيه، فافتح ما تشاء بلا قلق.
الفكرة باختصار
كل في EEGLAB تقريباً تأتي من pluginحزمة تضيف وظائف أو قوائم جديدة إلى EEGLAB. (plugin): DIPFIT و ICLabelأداة تصنّف كل مكوّن ICA إلى سبع فئات مع احتمال لكل فئة. و firfilt كلها إضافات. وإذا كتبت أداة تستخدمها في كل مشروع، فتحويلها لإضافة يجعلها بنداً في القائمة مثل أي أداة رسمية، ويجعل زملاءك يستخدمونها بنفس الطريقة.
الإضافة أبسط مما تتوقع. هي مجلد داخل مجلد plugins في EEGLAB، وفيه ملفان:
قبل وبعد
الصورة تُضاف قريباً.
لقطتان جنباً إلى جنب. اليسرى: مجلد plugins داخل مجلد EEGLAB، وفيه المجلد chanvar1.0 وبداخله الملفان eegplugin_chanvar.m و pop_chanvar.m. اليمنى: قائمة Plot في EEGLAB مفتوحة، وآخرها البند الجديد Channel variance تحت خط فاصل. المصدر: لقطة من EEGLAB 2026.1 على جهاز صاحب المشروع.
أسئلتك بعد هذا، كل جواب في قسمه:
لماذا أحتاج هذه الخطوة؟
السبب بالتفصيل، والمصطلحات التي تحتاجها
- ملف يبدأ اسمه بـ
eegplugin_. يشغّله EEGLAB عند كل بداية، ووظيفته الوحيدة أن يضيف البند للقائمة. - دالة تبدأ بـ
pop_. هي الأداة نفسها: تفتح نافذة إذا نقصت المعاملات، وتُرجع نص الأمر الذي يعيد نفس النتيجة، فيظهر في سجل الأوامرcommand historyقائمة الأوامر التي نفّذتها الواجهة، ويعرضها الأمر eegh..
القاعدة الثانية هي ما يجعل أداتك جزءاً من سكربتك. كل ضغطة على بندك تظهر في eegh كسطر كود، كما تعلّمت في درس سجل الأوامر.
في هذا الدرس نكتب إضافة اسمها chanvar: ترسم الانحراف المعياري لكل قناةchannelالإشارة المسجّلة من قطب واحد، وهي ما يعرضه EEGLAB.، وتلوّن بالأحمر القنوات البعيدة عن البقية. أداة فحص سريعة قبل درس القنوات السيئة أو بعده.
لماذا أحتاج هذه الخطوة؟
- ملف يبدأ اسمه بـ
eegplugin_. يشغّله EEGLAB عند كل بداية، ووظيفته الوحيدة أن يضيف البند للقائمة. - دالة تبدأ بـ
pop_. هي الأداة نفسها: تفتح نافذة إذا نقصت المعاملات، وتُرجع نص الأمر الذي يعيد نفس النتيجة، فيظهر في سجل الأوامر.
القاعدة الثانية هي ما يجعل أداتك جزءاً من سكربتك. كل ضغطة على بندك تظهر في eegh كسطر كود، كما تعلّمت في درس سجل الأوامر.
في هذا الدرس نكتب إضافة اسمها chanvar: ترسم الانحراف المعياري لكل قناة، وتلوّن بالأحمر القنوات البعيدة عن البقية. أداة فحص سريعة قبل درس القنوات السيئة أو بعده.
كيف أطبّقها في EEGLAB؟
7 خطوة من القوائم
أولاً: أنشئ مجلد الإضافة
- اكتب في نافذة الأوامر:
pluginDir = fullfile(fileparts(which('eeglab')), 'plugins', 'chanvar1.0');
mkdir(pluginDir); cd(pluginDir);اسم المجلد يحمل الإصدار: EEGLAB يقرأ chanvar1.0 كإضافة اسمها chanvar وإصدارها 1.0.
ثانياً: اكتب دالة pop_
- اكتب
edit pop_chanvar.m، والصق هذا الكود، واحفظ:
function com = pop_chanvar(EEG, zThresh)
% POP_CHANVAR - Plot the standard deviation of each channel and
% highlight channels far from the others.
%
% Usage:
% >> pop_chanvar(EEG); % ask for the threshold in a window
% >> pop_chanvar(EEG, zThresh); % plot directly
%
% Inputs:
% EEG - EEGLAB dataset
% zThresh - robust z-score above which a channel is highlighted
% (default in the window: 3)
%
% Output:
% com - command string for the EEGLAB history
com = '';
if nargin < 1
help pop_chanvar;
return;
end
% Missing threshold: ask for it
if nargin < 2
res = inputgui('geometry', {[2 1]}, ...
'uilist', { {'style', 'text', 'string', 'Robust z-score threshold'}, ...
{'style', 'edit', 'string', '3'} }, ...
'title', 'Channel variance -- pop_chanvar()');
if isempty(res), return; end % user pressed Cancel
zThresh = str2double(res{1});
end
% Standard deviation of each channel over all samples (and epochs)
data = double(reshape(EEG.data, EEG.nbchan, []));
sd = std(data, 0, 2);
% Robust z-score based on the median absolute deviation
medSd = median(sd);
z = (sd - medSd) / (1.4826 * median(abs(sd - medSd)));
flagged = find(z > zThresh);
% Plot
figure('Name', 'Channel variance');
bar(sd, 'FaceColor', [0.6 0.6 0.6]); hold on;
if ~isempty(flagged)
bar(flagged, sd(flagged), 'FaceColor', [0.85 0.2 0.2]);
end
set(gca, 'XTick', 1:EEG.nbchan, 'XTickLabel', {EEG.chanlocs.labels});
xtickangle(90);
ylabel('Standard deviation (\muV)');
title(sprintf('%s: %d channel(s) above z = %g', EEG.setname, ...
numel(flagged), zThresh), 'Interpreter', 'none');
if ~isempty(flagged)
fprintf('Channels above threshold: %s\n', ...
strjoin({EEG.chanlocs(flagged).labels}, ' '));
end
% Command that reproduces this call
com = sprintf('pop_chanvar(EEG, %g);', zThresh);ثالثاً: اكتب ملف eegplugin_
- اكتب
edit eegplugin_chanvar.m، والصق هذا الكود، واحفظ:
function vers = eegplugin_chanvar(fig, trystrs, catchstrs)
% EEGPLUGIN_CHANVAR - Add "Channel variance" to the EEGLAB Plot menu.
vers = 'chanvar1.0';
% Find the Plot menu of the main EEGLAB window
plotmenu = findobj(fig, 'tag', 'plot');
% Check the data, run the function, then add its command to the history
cmd = [trystrs.check_data 'LASTCOM = pop_chanvar(EEG);' catchstrs.add_to_hist];
uimenu(plotmenu, 'Label', 'Channel variance', 'CallBack', cmd, 'Separator', 'on');رابعاً: جرّب الإضافة
- أغلق نافذة EEGLAB واكتب
eeglabمن جديد، لأن EEGLAB يبحث عن الإضافات عند البداية فقط. تطبع نافذة الأوامر سطراً فيهadding "chanvar" v1.0. - حمّل D1 كما في “نقطة البداية”، لكن من الواجهةGUIالنوافذ والقوائم التي نستخدمها بالفأرة بدل كتابة الأوامر.: File ثم Load existing dataset.
- افتح Plot ثم Channel variance. تظهر نافذتك وفيها
3. اضغط Ok. يظهر الرسم. - اكتب
eegh. آخر سطر:pop_chanvar(EEG, 3);. أداتك الآن جزء من سجل الأوامر مثل أي أداة رسمية.
كيف أطبّقها في EEGLAB؟
أولاً: أنشئ مجلد الإضافة
- اكتب في نافذة الأوامر:
pluginDir = fullfile(fileparts(which('eeglab')), 'plugins', 'chanvar1.0');
mkdir(pluginDir); cd(pluginDir);اسم المجلد يحمل الإصدار: EEGLAB يقرأ chanvar1.0 كإضافة اسمها chanvar وإصدارها 1.0.
ثانياً: اكتب دالة pop_
- اكتب
edit pop_chanvar.m، والصق هذا الكود، واحفظ:
function com = pop_chanvar(EEG, zThresh)
% POP_CHANVAR - Plot the standard deviation of each channel and
% highlight channels far from the others.
%
% Usage:
% >> pop_chanvar(EEG); % ask for the threshold in a window
% >> pop_chanvar(EEG, zThresh); % plot directly
%
% Inputs:
% EEG - EEGLAB dataset
% zThresh - robust z-score above which a channel is highlighted
% (default in the window: 3)
%
% Output:
% com - command string for the EEGLAB history
com = '';
if nargin < 1
help pop_chanvar;
return;
end
% Missing threshold: ask for it
if nargin < 2
res = inputgui('geometry', {[2 1]}, ...
'uilist', { {'style', 'text', 'string', 'Robust z-score threshold'}, ...
{'style', 'edit', 'string', '3'} }, ...
'title', 'Channel variance -- pop_chanvar()');
if isempty(res), return; end % user pressed Cancel
zThresh = str2double(res{1});
end
% Standard deviation of each channel over all samples (and epochs)
data = double(reshape(EEG.data, EEG.nbchan, []));
sd = std(data, 0, 2);
% Robust z-score based on the median absolute deviation
medSd = median(sd);
z = (sd - medSd) / (1.4826 * median(abs(sd - medSd)));
flagged = find(z > zThresh);
% Plot
figure('Name', 'Channel variance');
bar(sd, 'FaceColor', [0.6 0.6 0.6]); hold on;
if ~isempty(flagged)
bar(flagged, sd(flagged), 'FaceColor', [0.85 0.2 0.2]);
end
set(gca, 'XTick', 1:EEG.nbchan, 'XTickLabel', {EEG.chanlocs.labels});
xtickangle(90);
ylabel('Standard deviation (\muV)');
title(sprintf('%s: %d channel(s) above z = %g', EEG.setname, ...
numel(flagged), zThresh), 'Interpreter', 'none');
if ~isempty(flagged)
fprintf('Channels above threshold: %s\n', ...
strjoin({EEG.chanlocs(flagged).labels}, ' '));
end
% Command that reproduces this call
com = sprintf('pop_chanvar(EEG, %g);', zThresh);ثالثاً: اكتب ملف eegplugin_
- اكتب
edit eegplugin_chanvar.m، والصق هذا الكود، واحفظ:
function vers = eegplugin_chanvar(fig, trystrs, catchstrs)
% EEGPLUGIN_CHANVAR - Add "Channel variance" to the EEGLAB Plot menu.
vers = 'chanvar1.0';
% Find the Plot menu of the main EEGLAB window
plotmenu = findobj(fig, 'tag', 'plot');
% Check the data, run the function, then add its command to the history
cmd = [trystrs.check_data 'LASTCOM = pop_chanvar(EEG);' catchstrs.add_to_hist];
uimenu(plotmenu, 'Label', 'Channel variance', 'CallBack', cmd, 'Separator', 'on');رابعاً: جرّب الإضافة
- أغلق نافذة EEGLAB واكتب
eeglabمن جديد، لأن EEGLAB يبحث عن الإضافات عند البداية فقط. تطبع نافذة الأوامر سطراً فيهadding "chanvar" v1.0. - حمّل D1 كما في “نقطة البداية”، لكن من الواجهة: File ثم Load existing dataset.
- افتح Plot ثم Channel variance. تظهر نافذتك وفيها
3. اضغط Ok. يظهر الرسم. - اكتب
eegh. آخر سطر:pop_chanvar(EEG, 3);. أداتك الآن جزء من سجل الأوامر مثل أي أداة رسمية.
كيف أكتبها بالكود؟
نفس الخطوات في 10 أسطر MATLAB
الدالة pop_ تعمل أيضاً من سكربتscriptملف أوامر MATLAB ينفّذ خطوات المعالجة بالترتيب. بلا قائمة. هذا الاختبار يتأكد من القاعدة الأساسية: النص الذي تُرجعه الدالة يعيد نفس النتيجة.
eeglab nogui
eeglabRoot = fileparts(which('eeglab'));
EEG = pop_loadset('eeglab_data.set', fullfile(eeglabRoot, 'sample_data'));
% The plugin folder is on the path even without the GUI
assert(exist('pop_chanvar', 'file') == 2, 'pop_chanvar not found: check the plugins folder');
% Call with all arguments: no window, direct plot
com = pop_chanvar(EEG, 3);
disp(com); % pop_chanvar(EEG, 3);
% Running the returned command must reproduce the same figure
eval(com);كيف أكتبها بالكود؟
الدالة pop_ تعمل أيضاً من السكربت بلا قائمة. هذا الاختبار يتأكد من القاعدة الأساسية: النص الذي تُرجعه الدالة يعيد نفس النتيجة.
eeglab nogui
eeglabRoot = fileparts(which('eeglab'));
EEG = pop_loadset('eeglab_data.set', fullfile(eeglabRoot, 'sample_data'));
% The plugin folder is on the path even without the GUI
assert(exist('pop_chanvar', 'file') == 2, 'pop_chanvar not found: check the plugins folder');
% Call with all arguments: no window, direct plot
com = pop_chanvar(EEG, 3);
disp(com); % pop_chanvar(EEG, 3);
% Running the returned command must reproduce the same figure
eval(com);أي قيمة أختار؟
القيم المناسبة حسب هدف تحليلك
| الإعداد | القيمة في الدرس | لماذا |
|---|---|---|
| مكان المجلد | plugins داخل مجلد EEGLAB | هنا يبحث EEGLAB عند كل بداية عن مجلدات فيها ملف يبدأ بـ eegplugin (eeglab.m). |
| اسم المجلد | chanvar1.0 | الأرقام في آخر الاسم تُقرأ كإصدار. إذا اختلف عن الإصدار الذي يُرجعه eegplugin_ يطبع EEGLAB تحذيراً. |
| فحص البيانات | trystrs.check_data | يتأكد أن داتاستdatasetملف بيانات EEG واحد محمّل في EEGLAB مع معلوماته. محمّلة قبل التشغيل. للدوال التي تحتاج epochمقطع زمني قصير مقتطع حول حدث. استخدم trystrs.check_epoch، وللتي تحتاج ICAطريقة تفصل الإشارة المسجّلة إلى مصادر مستقلة، بعضها دماغي وبعضها آرتفاكت. trystrs.check_ica. |
| التسجيل | catchstrs.add_to_hist | يضيف LASTCOM إلى السجل ويحفظ الداتاست في ALLEEG. إذا كان الأمر يبدأ بـ EEG = ينشئ EEGLAB داتاست جديدة تلقائياً. |
| عتبة الإبراز | z = 3 | قيمة بداية شائعة للقيم الشاذة. الأداة للفحص بالعين، لا لحذف القنوات آلياً. |
أي قيمة أختار؟
| الإعداد | القيمة في الدرس | لماذا |
|---|---|---|
| مكان المجلد | plugins داخل مجلد EEGLAB | هنا يبحث EEGLAB عند كل بداية عن مجلدات فيها ملف يبدأ بـ eegplugin (eeglab.m). |
| اسم المجلد | chanvar1.0 | الأرقام في آخر الاسم تُقرأ كإصدار. إذا اختلف عن الإصدار الذي يُرجعه eegplugin_ يطبع EEGLAB تحذيراً. |
| فحص البيانات | trystrs.check_data | يتأكد أن داتاست محمّلة قبل التشغيل. للدوال التي تحتاج epochs استخدم trystrs.check_epoch، وللتي تحتاج ICA trystrs.check_ica. |
| التسجيل | catchstrs.add_to_hist | يضيف LASTCOM إلى السجل ويحفظ الداتاست في ALLEEG. إذا كان الأمر يبدأ بـ EEG = ينشئ EEGLAB داتاست جديدة تلقائياً. |
| عتبة الإبراز | z = 3 | قيمة بداية شائعة للقيم الشاذة. الأداة للفحص بالعين، لا لحذف القنوات آلياً. |
كيف أتأكد أنها نجحت؟
4 فحوص سريعة
- عند تشغيل
eeglabتطبع نافذة الأوامر سطراً فيهadding "chanvar" v1.0. - البند Plot ثم Channel variance موجود، ويفتح نافذة فيها خانةfield (in a dialog)مكان في نافذة نكتب فيه قيمة أو نختارها. العتبة.
- بعد الضغط على Ok يظهر رسم أعمدة بعدد القنوات (32 في D1).
eeghيعرضpop_chanvar(EEG, 3);، والسكربت أعلاه يعمل بلا خطأ.
كيف أتأكد أنها نجحت؟
- عند تشغيل
eeglabتطبع نافذة الأوامر سطراً فيهadding "chanvar" v1.0. - البند Plot ثم Channel variance موجود، ويفتح نافذة فيها خانة العتبة.
- بعد الضغط على Ok يظهر رسم أعمدة بعدد القنوات (32 في D1).
eeghيعرضpop_chanvar(EEG, 3);، والسكربت أعلاه يعمل بلا خطأ.
ما الأخطاء التي يقع فيها كثيرون؟
5 أخطاء، وكيف تتجنّبها
- وضع الملفين خارج مجلد
plugins. EEGLAB لا يبحث في أي مكان آخر، فلا يظهر البند. - دالة
pop_لا تُرجع شيئاً. بدونcomلا يُسجَّل شيء فيeegh، فلا تعيد الضغطة نفسها في سكربتك. - نص أمر لا يعيد نفس النتيجة. إذا كتب المستخدم 2.5 في النافذة، يجب أن يكون النص
pop_chanvar(EEG, 2.5);، لا القيمة الافتراضية. لهذا يُبنىcomمن القيم التي استُخدمت فعلاً. - انتظار ظهور البند مع
eeglab nogui. في هذا الوضع يضيف EEGLAB مجلد الإضافة للمسار، لكنه لا يشغّلeegplugin_، فلا توجد قوائم. هذا طبيعي. - اختبار الإضافة من القائمة فقط. EEGLAB يلتقط الأخطاء القادمة من القوائم. لتتبّع خطأ، اكتب
dbstop if errorثم استدعِ الدالة من نافذة الأوامر (نصيحة التوثيق الرسمي).
ما الأخطاء التي يقع فيها كثيرون؟
- وضع الملفين خارج مجلد
plugins. EEGLAB لا يبحث في أي مكان آخر، فلا يظهر البند. - دالة
pop_لا تُرجع شيئاً. بدونcomلا يُسجَّل شيء فيeegh، فلا تعيد الضغطة نفسها في سكربتك. - نص أمر لا يعيد نفس النتيجة. إذا كتب المستخدم 2.5 في النافذة، يجب أن يكون النص
pop_chanvar(EEG, 2.5);، لا القيمة الافتراضية. لهذا يُبنىcomمن القيم التي استُخدمت فعلاً. - انتظار ظهور البند مع
eeglab nogui. في هذا الوضع يضيف EEGLAB مجلد الإضافة للمسار، لكنه لا يشغّلeegplugin_، فلا توجد قوائم. هذا طبيعي. - اختبار الإضافة من القائمة فقط. EEGLAB يلتقط الأخطاء القادمة من القوائم. لتتبّع خطأ، اكتب
dbstop if errorثم استدعِ الدالة من نافذة الأوامر (نصيحة التوثيق الرسمي).
متصفحك لا يسمح بحفظ التقدّم. كل الدروس متاحة، لكن علامات الإكمال لن تُحفظ.
تم. حُفظ تقدّمك في هذا المتصفح.تراجعأين أقرأ أكثر؟
2 مراجع: التوثيق الرسمي أولاً
- EEGLAB TutorialتوثيقContribute > Create an EEGLAB plugin
- EEGLAB TutorialتوثيقConcepts guide > EEGLAB functions
مكتوب لـ EEGLAB 2026.1 · 2026-10-28
للتوسّع
- EEGLAB Tutorial: https://eeglab.org/tutorials/contribute/design_plugin.html (Contribute > Create an EEGLAB plugin)
- EEGLAB Tutorial: https://eeglab.org/tutorials/ConceptsGuide/EEGLAB_functions.html (Concepts guide > EEGLAB functions)
تحتاج مساعدة؟
اسأل، أو شاركنا رأيك، أو بلّغ عن خطأ
- بلّغ عن خطأ علمي · يحتاج حساباً على GitHub. لا تملك حساباً؟ استخدم "شاركنا رأيك".