المحطة 9 · الدرس 6

الحوسبة على HPC

اختياري12 دقيقةقبل هذا الدرس: معالجة دفعات (batch)اطبع البطاقة
تبدأ من: sub-002_task-FaceRecognition_eeg.set (D4) · لا شيء: البيانات كما نزّلتها.تنزيل البيانات (يفتح في نافذة جديدة)
سكربت الوصول لهذه الحالة
MATLAB
[ALLEEG, EEG, CURRENTSET, ALLCOM] = eeglab;

% Run from inside faces_project, where ds002718 sits in rawdata
bidsRoot = fullfile(pwd, 'rawdata');
EEG = pop_loadset('sub-002_task-FaceRecognition_eeg.set', fullfile(bidsRoot, 'sub-002', 'eeg'));

% Show the dataset in the main EEGLAB window
[ALLEEG, EEG, CURRENTSET] = pop_newset(ALLEEG, EEG, 0, 'setname', 'sub-002 raw', 'gui', 'off');
eeglab redraw;

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

سكربتscriptملف أوامر MATLAB ينفّذ خطوات المعالجة بالترتيب. الدفعات من الدرس السابق يعمل على جهازك مشاركاً بعد مشاركparticipantالشخص الذي سُجّلت بياناته في التجربة.. هذا يكفي لأغلب المشاريع. لكن بعض الخطوات بطيئة: ICAطريقة تفصل الإشارة المسجّلة إلى مصادر مستقلة، بعضها دماغي وبعضها آرتفاكت. على 72 قناةchannelالإشارة المسجّلة من قطب واحد، وهي ما يعرضه EEGLAB. وخمسين دقيقة من التسجيل قد تأخذ وقتاً طويلاً لكل مشارك، و AMICA و DIPFIT أبطأ. ضربها في 18 مشاركاً، أو في 100، فيصبح جهازك مشغولاً أياماً.

قبل وبعد

أربعة صناديق متتالية: جهازك فيه مجلد المشروع والسكربت، ثم السكربت run_ica_d4.m يعمل بلا واجهة، ثم العنقود بثلاث مهام متوازية sub-002 و sub-003 و sub-004 في جامعتك أو NSG، ثم النتائج: ملف أوزان ICA لكل مشارك ومجلد السجلات logs.

أسئلتك بعد هذا، كل جواب في قسمه:

لماذا أحتاج هذه الخطوة؟

السبب بالتفصيل، والمصطلحات التي تحتاجها

عنقود الحوسبة (الحوسبة عالية الأداء (HPC)HPCتشغيل التحليل على حواسيب قوية مشتركة بدل جهازك.، الحوسبة عالية الأداء) مجموعة أجهزة كثيرة تشغّل مهامك في نفس الوقت. عشرون مشاركاً يصبحون عشرين مهمة متوازية، فتنتهي في وقت مشارك واحد تقريباً.

لكن العنقود لا يعرض نوافذ، ولا تستطيع أن تضغط فيه شيئاً. السكربت يجب أن يعمل من البداية للنهاية وحده. هذا الدرس يجهّز سكربتك لذلك.

متى يستحق الانتقال؟ احسب: وقت مشارك واحد × عدد المشاركين. إذا كان الناتج ساعات قليلة، شغّله على جهازك ليلاً. إذا كان أياماً، أو تكرّر التشغيل كثيراً، فالعنقود يستحق.

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

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

العنقود يعمل بلا واجهة، فالخطوات هنا تجهيز وإرسال.

أولاً: جهّز السكربت

  1. ابدأ من سكربت الدفعات، وتأكد من أربعة شرطconditionحالة تجريبية نقارن بينها وبين غيرها، مثل "مألوف" و"غير مألوف".:
    • يبدأ بـ eeglab nogui، فلا تُفتح أي نافذة.
    • لا يرسم، أو يحفظ الرسم في ملف بـ print ثم يغلقه.
    • كل المسارات مبنية من مجلد المشروع بـ fullfile، لا مسارات من جهازك مثل C:\Users\....
    • يعالج مشاركاً واحداً يختاره من رقم يعطيه له العنقود. هكذا يرسل العنقود نفس السكربت عشرين مرة بأرقام مختلفة.
  2. جرّبه على جهازك من سطر أوامر النظام (لا من MATLAB):
MATLAB
matlab -batch "run_ica_d4"

-batch يشغّل السكربت بلا واجهة، ثم يغلق MATLAB. إذا حدثeventعلامة في التسجيل تحدد لحظة شيء مهم، مثل ظهور مثير. خطأ، يخرج برمز خطأ يراه العنقود.

ثانياً: عنقود جامعتك

  1. اسأل قسم الحوسبة في جامعتك: هل MATLAB مثبّت؟ أي نظام مهام يستخدمون (SLURM هو الأشهر)؟ وأين تضع EEGLAB؟
  2. انسخ مجلد المشروع والسكربت و EEGLAB إلى حسابك على العنقود.
  3. اكتب ملف المهمة. هذا مثال بنظام SLURM لثلاث مهام، واحدة لكل مشارك. الأسماء والقيم تختلف بين الجامعات، فعدّلها حسب تعليماتهم:
MATLAB
#!/bin/bash
#SBATCH --job-name=d4-ica
#SBATCH --array=1-3
#SBATCH --cpus-per-task=4
#SBATCH --mem=16G
#SBATCH --time=04:00:00
#SBATCH --output=logs/ica_%a.out

module load matlab
matlab -batch "run_ica_d4"
  1. أرسله بـ sbatch job_ica.sh، وتابعه بـ squeue -u مع اسم مستخدمك.

ثالثاً: بوابة NSG (بديل مجاني)

  1. إذا لم يكن عند جامعتك عنقود، فبوابة Neuroscience Gateway (NSG) مجانية للباحثين الأكاديميين، وفيها MATLAB و EEGLAB جاهزان. سجّل حساباً في موقعها.
  2. ثبّت pluginحزمة تضيف وظائف أو قوائم جديدة إلى EEGLAB. nsgportal من File ثم Manage EEGLAB extensions (آخر إصدار عند كتابة الدرس 2.1.1).
  3. افتح Tools ثم NSG Tools ثم NSG account info، واكتب اسم المستخدم وكلمة المرور.
  4. ضع السكربت والبيانات التي يحتاجها في مجلد واحد، ثم افتح Tools ثم NSG Tools ثم Manage NSG jobs، واختر المجلد، واكتب اسم السكربت، وأرسل المهمة. من نفس النافذة تتابع حالتها وتنزّل النتائج.

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

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

يقرأ السكربت الملفات التي كتبها pop_importbids في derivatives/eeglab في درس الدفعات، فشغّل ذلك الاستيراد مرة واحدة أولاً. شغّله من داخل faces_project.

MATLAB
% run_ica_d4.m - one subject per job, no display
% Local test:  matlab -batch "run_ica_d4"
% On SLURM:    the array index selects the subject
eeglab nogui

projectRoot = pwd;
outRoot     = fullfile(projectRoot, 'derivatives', 'eeglab');
logRoot     = fullfile(projectRoot, 'logs');
subjects    = {'sub-002', 'sub-003', 'sub-004'};

% Subject index from the cluster, or 1 when run locally
taskId = str2double(getenv('SLURM_ARRAY_TASK_ID'));
if isnan(taskId), taskId = 1; end
subj = subjects{taskId};
fprintf('Job %d: %s\n', taskId, subj);

cfg.lineFreq  = 50;                     % same settings as the batch lesson
cfg.eogLabels = {'EEG061', 'EEG062'};
cfg.dropLabels = {'EEG063', 'EEG064'};

try
    % File written by pop_importbids in the batch processing lesson
    outDir = fullfile(outRoot, subj, 'eeg');
    EEG = pop_loadset('filename', sprintf('%s_task-FaceRecognition_eeg.set', subj), ...
        'filepath', outDir);

    % Same steps as process_subject up to ICA, so the weights fit its main dataset
    EEG = pop_select(EEG, 'rmchannel', cfg.dropLabels);
    fullLocs = EEG.chanlocs;
    EEG = pop_eegfiltnew(EEG, 'locutoff', 0.1);
    EEG = pop_eegfiltnew(EEG, 'locutoff', cfg.lineFreq - 2, 'hicutoff', cfg.lineFreq + 2, 'revfilt', 1);
    EEG_test = pop_clean_rawdata(EEG, 'FlatlineCriterion', 5, 'ChannelCriterion', 0.8, ...
        'LineNoiseCriterion', 4, 'Highpass', 'off', 'BurstCriterion', 'off', ...
        'WindowCriterion', 'off', 'BurstRejection', 'off', 'Distance', 'Euclidian', ...
        'channels_ignore', cfg.eogLabels);
    badChans = setdiff({EEG.chanlocs.labels}, {EEG_test.chanlocs.labels}, 'stable');
    if ~isempty(badChans)
        EEG = pop_select(EEG, 'rmchannel', badChans);
    end
    if ~isempty(badChans)
        EEG = pop_interp(EEG, fullLocs, 'spherical');
    end
    clear EEG_test
    eogIdx = find(ismember({EEG.chanlocs.labels}, cfg.eogLabels));
    EEG = pop_reref(EEG, [], 'exclude', eogIdx);

    % ICA on a 1-Hz high-passed copy (the slow step worth a cluster)
    EEG_ica = pop_eegfiltnew(EEG, 'locutoff', 1);
    tic;
    EEG_ica = pop_runica(EEG_ica, 'icatype', 'runica', 'extended', 1);
    fprintf('ICA finished in %.1f min\n', toc / 60);

    % Save only the small result: the ICA weights and the bad channel list
    icaInfo = struct('icaweights', EEG_ica.icaweights, 'icasphere', EEG_ica.icasphere, ...
                     'icachansind', EEG_ica.icachansind, 'badChans', {badChans});
    save(fullfile(outDir, sprintf('%s_task-FaceRecognition_desc-ica.mat', subj)), ...
         '-struct', 'icaInfo');
catch err
    % Write the error to a log file, then exit with an error code
    if ~exist(logRoot, 'dir'), mkdir(logRoot); end
    fid = fopen(fullfile(logRoot, sprintf('%s_error.txt', subj)), 'w');
    fprintf(fid, '%s\n', getReport(err, 'extended', 'hyperlinks', 'off'));
    fclose(fid);
    rethrow(err);
end

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

القيم المناسبة حسب هدف تحليلك
الإعدادالقيمة في الدرسلماذا
مشاركون لكل مهمةواحدإذا فشل مشارك لا يتوقف الباقون، وتعيد تشغيله وحده. نفس فكرة تسجيل الأخطاء في درس الدفعات.
طريقة التشغيلmatlab -batchيعمل بلا واجهة، ويغلق MATLAB في النهاية، ويعطي رمز خطأ عند الفشل.
الذاكرة16G في المثالبيانات مشارك واحد من D4 حوالي 234 ميجابايت على القرص، لكن فلترfilterأداة تُضعف ترددات معيّنة في الإشارة وتُبقي غيرها. و ICA ينشئان نسخاً في الذاكرة. ابدأ بقيمة واسعة، ثم اقرأ ما استُخدم فعلاً في تقرير المهمة.
الوقت المسموح4 ساعات في المثالقِس وقت مشارك واحد على جهازك، واطلب ضعفه. المهمة التي تتجاوز وقتها يوقفها العنقود.
ما يُحفظأوزان ICA فقطملف صغير يُنقل بسرعة من العنقود. حُسب بعد نفس خطوات process_subject في درس الدفعات (نفس القنوات المرجعreferenceالنقطة التي يُقاس جهد كل قناة بالنسبة لها. الاستيفاءinterpolationتقدير إشارة قناة محذوفة من القنوات المحيطة بها.)، فتنسخه إلى النسخة الرئيسية في ذلك الدرس كما في درس نسخ أوزان ICA. الأوزانweights (ICA)المصفوفة التي تحوّل القنوات إلى مكوّنات ICA. لا تناسب إلا بيانات بنفس القنوات ونفس المعالجة المكانية.

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

4 فحوص سريعة
  • matlab -batch "run_ica_d4" على جهازك يطبع Job 1: sub-002 ثم مدة ICA، ويُنهي MATLAB بلا خطأ.
  • في derivatives/eeglab/sub-002/eeg ملف sub-002_task-FaceRecognition_desc-ica.mat.
  • على العنقود: ثلاث مهام، وثلاثة ملفات أوزان، ولا ملف خطأ في logs.
  • size(icaweights) في كل ملف رتبة البيانات × 72، أي 71 × 72 إذا لم تُستوفَ قناة (المرجع المتوسط ينقص الرتبة واحداً).

ما الأخطاء التي يقع فيها كثيرون؟

5 أخطاء، وكيف تتجنّبها
  • أمر يفتح نافذة. أي pop_ بلا معاملات كافية، أو eeglab بدل eeglab nogui، يحاول فتح نافذة فيتوقف السكربت أو يفشل. جرّب بـ matlab -batch على جهازك قبل الإرسال.
  • مسارات من جهازك. C:\Users\... لا يوجد على العنقود. ابنِ كل مسار من مجلد المشروع.
  • حلقة على كل المشاركين في مهمة واحدة. تفقد التوازي، وخطأ في مشارك واحد يوقف الكل إذا لم تلتقطه.
  • طلب وقت أو ذاكرة أقل من الحاجة. يُوقَف العنقود المهمة بلا نتيجة. اقرأ ملف logs وتقرير المهمة قبل إعادة الإرسال.
  • نسيان الإصدارات. إصدار EEGLAB أو MATLAB على العنقود قد يختلف عن جهازك. اطبع eeg_getversion و version في بداية السكربت، واكتبهما في Methods.

كيف أكتبها في ورقتي؟

قالب Methods: عدّل البيانات والإعدادات والإصدارات لتطابق ما نفّذته

قالب: عدّل البيانات والإعدادات والإصدارات لتطابق ما نفّذته.

Independent component analysis (extended Infomax; Lee et al., 1999) was computed with runica (EEGLAB 2026.1) for each participant on a copy of the preprocessed data high-pass filtered at 1 Hz, and the resulting weights were applied to the 0.1 Hz high-pass filtered data; jobs ran one per participant on [computing cluster] with MATLAB [version].

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

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

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

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

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