EEGLAB ببساطة

معالجة دفعات (batch)

المحطة 9 · الدرس 3 · EEGLAB 2026.1

من الواجهة

  1. FileImport dataUsing EEGLAB functions and pluginsFrom BIDS folder structureOk rawdatatrial_type
  2. Datasets EEG061EEG062EEG063EEG064

السكربت

eeglab nogui
projectRoot = pwd;
bidsRoot    = fullfile(projectRoot, 'rawdata');
derivRoot   = fullfile(projectRoot, 'derivatives', 'eeglab');
logRoot     = fullfile(projectRoot, 'logs');
subjects    = {'sub-002', 'sub-003', 'sub-004'};
cfg.lineFreq    = 50;                          % UK recording: 50 Hz mains
cfg.eogLabels   = {'EEG061', 'EEG062'};        % HEOG, VEOG
cfg.dropLabels  = {'EEG063', 'EEG064'};        % ECG channels
cfg.epochEvents = {'famous_new', 'unfamiliar_new', 'scrambled_new'};
cfg.epochWindow = [-1 2];
cfg.thresholdUv = 100;
if ~exist(logRoot, 'dir'), mkdir(logRoot); end
logFile = fullfile(logRoot, 'batch_log.txt');
[STUDY, ALLEEG] = pop_importbids(bidsRoot, 'eventtype', 'trial_type', ...
    'bidsevent', 'on', 'bidschanloc', 'on', 'subjects', subjects, ...
    'outputdir', derivRoot, 'studyName', 'faces');
clear STUDY ALLEEG   % each subject is reloaded from disk inside the loop
nSub    = numel(subjects);
status  = repmat({'not run'}, nSub, 1);
nBad    = nan(nSub, 1);
nIcRem  = nan(nSub, 1);
nEpochs = nan(nSub, 1);
for s = 1:nSub
    subj = subjects{s};
    fprintf('\n===== %s (%d of %d) =====\n', subj, s, nSub);
    try
        inFile = fullfile(derivRoot, subj, 'eeg', sprintf('%s_task-FaceRecognition_eeg.set', subj));
        res = process_subject(inFile, cfg);
        status{s}  = 'ok';
        nBad(s)    = res.nBadChans;
        nIcRem(s)  = res.nIcRemoved;
        nEpochs(s) = res.nEpochs;
    catch err
        status{s} = 'failed';
        fid = fopen(logFile, 'a');
        fprintf(fid, '%s  %s  %s\n', datestr(now, 'yyyy-mm-dd HH:MM'), subj, err.message);
        fclose(fid);
        fprintf(2, 'FAILED %s: %s\n', subj, err.message);
    end
end
summary = table(subjects(:), status, nBad, nIcRem, nEpochs, ...
    'VariableNames', {'subject', 'status', 'bad_channels', 'ics_removed', 'epochs_kept'});
disp(summary);
writetable(summary, fullfile(derivRoot, 'batch_summary.csv'));
function res = process_subject(inFile, cfg)
[inDir, baseName] = fileparts(inFile);
baseName = strrep(baseName, '_eeg', '');
EEG = pop_loadset('filename', [baseName '_eeg.set'], 'filepath', inDir);
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');
fprintf('Bad channels: %s\n', strjoin(badChans, ', '));
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);
EEG_main = EEG;
EEG_ica = pop_eegfiltnew(EEG_main, 'locutoff', 1);
EEG_ica = pop_runica(EEG_ica, 'icatype', 'runica', 'extended', 1);
EEG_main.icaweights  = EEG_ica.icaweights;
EEG_main.icasphere   = EEG_ica.icasphere;
EEG_main.icachansind = EEG_ica.icachansind;
EEG_main.icawinv     = [];   % recomputed by eeg_checkset
EEG_main.icaact      = [];
EEG = eeg_checkset(EEG_main);
clear EEG_main EEG_ica
EEG = pop_iclabel(EEG, 'default');
thresh = [NaN NaN; 0.9 1; 0.9 1; NaN NaN; NaN NaN; NaN NaN; NaN NaN];
EEG = pop_icflag(EEG, thresh);
artifactComps = find(EEG.reject.gcompreject);
if ~isempty(artifactComps)
    EEG = pop_subcomp(EEG, artifactComps, 0);
end
EEG = pop_eegfiltnew(EEG, 'hicutoff', 30);
EEG.setname = [baseName ' clean'];
EEG = pop_saveset(EEG, 'filename', [baseName '_desc-clean_eeg.set'], 'filepath', inDir);
EEG = pop_epoch(EEG, cfg.epochEvents, cfg.epochWindow, 'epochinfo', 'yes');
EEG = pop_rmbase(EEG, [-200 0]);
EEG = pop_eegthresh(EEG, 1, 1:EEG.nbchan, -cfg.thresholdUv, cfg.thresholdUv, EEG.xmin, EEG.xmax, 0, 0);
if any(EEG.reject.rejthresh)
    EEG = pop_rejepoch(EEG, EEG.reject.rejthresh, 0);
end
EEG.setname = [baseName ' epochs'];
EEG = pop_saveset(EEG, 'filename', [baseName '_desc-epochs_eeg.set'], 'filepath', inDir);
res.nBadChans  = numel(badChans);
res.nIcRemoved = numel(artifactComps);
res.nEpochs    = EEG.trials;
end

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

الإعدادالقيمة في الدرس
تردد الكهرباء50 هرتز
قنوات العين والقلبEEG061 و EEG062 للعين، و EEG063 و EEG064 للقلب
الأحداث للتقطيعfamous_new و unfamiliar_new و scrambled_new
الاستيرادpop_importbids مرة واحدة قبل الحلقة
مكان الإعداداتالمتغيّر cfg في الأعلى
ما يحدث عند الخطأسطر في batch_log.txt، والحالة failed، ثم المشارك التالي

لقسم Methods

Data from [n] participants (ds002718; EEG-BIDS plugin 10.5, EEGLAB 2026.1) were high-pass filtered (passband edge 0.1 Hz; firfilt plugin 2.8), and line noise was attenuated with a band-stop filter (passband edges 48 and 52 Hz). Bad channels were identified with clean_rawdata (clean_rawdata plugin 2.11; flatline 5 s, channel correlation 0.8) and interpolated, then data were average-referenced, EOG excluded. Independent component analysis (extended Infomax; Lee et al., 1999) was computed on a 1 Hz high-passed copy, and components labelled Eye or Muscle with probability ≥ 0.9 (ICLabel 1.7; Pion-Tonachini et al., 2019) were removed. After low-pass filtering (passband edge 30 Hz), epochs from −1 to 2 s were baseline-corrected (−200 to 0 ms), and epochs beyond ±100 µV were rejected.

النسخة الكاملة: https://simplyeeglab.pages.dev/lesson/batch-processing/

رخصة المحتوى: CC BY-NC-SA 4.0 · MIT (code)

موقع تعليمي مستقل، غير تابع رسمياً لـ EEGLAB أو SCCN.