المحطة 10 · الدرس 4

كتابة plugin

اختياري15 دقيقةقبل هذا الدرس: سكربت لمشارك واحداطبع البطاقة
تبدأ من: eeglab_data.set (D1) · لا شيء: البيانات كما نزّلتها.تنزيل البيانات (يفتح في نافذة جديدة)
سكربت الوصول لهذه الحالة
MATLAB
[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;

الفكرة باختصار

كل قائمةmenuمجموعة أوامر تظهر عند الضغط على اسمها في أعلى النافذة. في 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.، وتلوّن بالأحمر القنوات البعيدة عن البقية. أداة فحص سريعة قبل درس القنوات السيئة أو بعده.

كيف أطبّقها في EEGLAB؟

7 خطوة من القوائم

أولاً: أنشئ مجلد الإضافة

  1. اكتب في نافذة الأوامر:
MATLAB
pluginDir = fullfile(fileparts(which('eeglab')), 'plugins', 'chanvar1.0');
mkdir(pluginDir); cd(pluginDir);

اسم المجلد يحمل الإصدار: EEGLAB يقرأ chanvar1.0 كإضافة اسمها chanvar وإصدارها 1.0.

ثانياً: اكتب دالة pop_

  1. اكتب edit pop_chanvar.m، والصق هذا الكود، واحفظ:
MATLAB
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_

  1. اكتب edit eegplugin_chanvar.m، والصق هذا الكود، واحفظ:
MATLAB
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');

رابعاً: جرّب الإضافة

  1. أغلق نافذة EEGLAB واكتب eeglab من جديد، لأن EEGLAB يبحث عن الإضافات عند البداية فقط. تطبع نافذة الأوامر سطراً فيه adding "chanvar" v1.0.
  2. حمّل D1 كما في “نقطة البداية”، لكن من الواجهةGUIالنوافذ والقوائم التي نستخدمها بالفأرة بدل كتابة الأوامر.: File ثم Load existing dataset.
  3. افتح Plot ثم Channel variance. تظهر نافذتك وفيها 3. اضغط Ok. يظهر الرسم.
  4. اكتب eegh. آخر سطر: pop_chanvar(EEG, 3);. أداتك الآن جزء من سجل الأوامر مثل أي أداة رسمية.

كيف أكتبها بالكود؟

نفس الخطوات في 10 أسطر MATLAB

الدالة pop_ تعمل أيضاً من سكربتscriptملف أوامر MATLAB ينفّذ خطوات المعالجة بالترتيب. بلا قائمة. هذا الاختبار يتأكد من القاعدة الأساسية: النص الذي تُرجعه الدالة يعيد نفس النتيجة.

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);

أي قيمة أختار؟

القيم المناسبة حسب هدف تحليلك
الإعدادالقيمة في الدرسلماذا
مكان المجلد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قيمة بداية شائعة للقيم الشاذة. الأداة للفحص بالعين، لا لحذف القنوات آلياً.

كيف أتأكد أنها نجحت؟

4 فحوص سريعة
  • عند تشغيل eeglab تطبع نافذة الأوامر سطراً فيه adding "chanvar" v1.0.
  • البند Plot ثم Channel variance موجود، ويفتح نافذة فيها خانةfield (in a dialog)مكان في نافذة نكتب فيه قيمة أو نختارها. العتبة.
  • بعد الضغط على 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 ثم استدعِ الدالة من نافذة الأوامر (نصيحة التوثيق الرسمي).

أين أقرأ أكثر؟

2 مراجع: التوثيق الرسمي أولاً

مكتوب لـ EEGLAB 2026.1 · 2026-10-28

تحتاج مساعدة؟

اسأل، أو شاركنا رأيك، أو بلّغ عن خطأ