Station 9 · Lesson 3
Batch processing
sub-002_task-FaceRecognition_eeg.set (D4) · Nothing yet: the data as downloaded.Download the data (opens in a new tab)Script to reach this state
% Start from a fresh MATLAB session: the batch script loads every subject itself
clear
[ALLEEG, EEG, CURRENTSET, ALLCOM] = eeglab;Your browser's back button takes you to the exact place you were, so open anything you like.
The idea in brief
The single-participantThe person whose data were recorded in the study. scriptA MATLAB file of commands that runs processing steps in order. works on D1. Your real project has twenty participants or more, with the same steps and the same settings for each one. Running the script twenty times and changing the file name by hand each time is slow, and it invites mistakes.
Before and after
Your next questions, each answered in its own section:
Why do I need this step?
The reasons in detail, and the terms you need
The solution is a loop: a list of participant names, with the same steps applied to each name. This is called batch processing.
But a simple loop has a problem: if the seventh participant fails for some reason (a missing file, an odd channelThe signal recorded from one electrode, as shown in EEGLAB., memory), everything stops, and in the morning you find that only six finished. That is why we wrap each participant in try and catch: if it fails, the error is written to a file, and the loop moves on to the next participant.
In this lesson we process only three participants from D4 (about 700 MB to download). The same script works on all eighteen if you download them.
Why do I need this step?
The solution is a loop: a list of participant names, with the same steps applied to each name. This is called batch processing.
But a simple loop has a problem: if the seventh participant fails for some reason (a missing file, an odd channel, memory), everything stops, and in the morning you find that only six finished. That is why we wrap each participant in try and catch: if it fails, the error is written to a file, and the loop moves on to the next participant.
In this lesson we process only three participants from D4 (about 700 MB to download). The same script works on all eighteen if you download them.
How do I do it in EEGLAB?
10 steps in the menus
First: download three participants from D4
- Create a folder named
faces_projectwith arawdatafolder inside it, and makefaces_projectthe MATLAB working folder (cd). Run every script in station 9 from inside this folder. The file organization lesson explains the other folders. - From the ds002718 page on OpenNeuro, download into
rawdatathe top-level files (dataset_description.json,READMEandtask-FaceRecognition_events.json) and the fullsub-002,sub-003andsub-004folders. Or, from the system command line, if you have the AWS CLI:
aws s3 sync --no-sign-request s3://openneuro.org/ds002718 rawdata --exclude "sub-*" --include "sub-002/*" --include "sub-003/*" --include "sub-004/*"Second: try the pipelineThe fixed sequence of processing steps from raw data to results. on one participant in the GUIThe windows and menus used with the mouse instead of typed commands.
- Open File then Import data then Using EEGLAB functions and plugins then From BIDS folder structure and choose the
rawdatafolder. Enable importing events and electrodeThe physical sensor placed on the scalp to pick up the signal. locations from the BIDSA standard for naming and organizing neuroimaging data files. files, and take the event typeThe name or code that identifies what kind of event it is. from thetrial_typecolumn. Click Ok. A STUDYAn EEGLAB structure that groups many participants' datasets for joint analysis. is created with the three participants. - Pick one participant from the Datasets and apply the steps in the GUI as in stations 3 to 5, changing only three settings: mains powerThe squared amplitude; how strong a signal is at a given frequency. in the UK is 50 Hz, not 60; the eye channels are
EEG061andEEG062; and the heart channelsEEG063andEEG064are removed. - Type
eegh. These lines are what you will put inside the loop.
Third: turn the pipeline into a loop
- Copy the single-subject script into a new file
batch_d4.m. Move the processing steps into a function at the end of the file namedprocess_subject, which takes the participant file and the settings, saves the results, and returns a summary. - At the top of the file: the list of participants, the settings, and a
forloop that calls the function insidetry. - In
catch: write the participant name and the error message tologs/batch_log.txt, and record the statusfailedin the summary table. - Run the file. ICAA method that separates the recording into independent sources, some brain and some artifact. on 72 channels (70 EEG and 2 EOG) and fifty minutes of recording takes time for each participant, so let it run. If you have many participants, see the HPC lesson.
- When it finishes, open
batch_summary.csv. Each row is one participant: status, bad channels, removed components, and remaining epochs.
How do I do it in EEGLAB?
First: download three participants from D4
- Create a folder named
faces_projectwith arawdatafolder inside it, and makefaces_projectthe MATLAB working folder (cd). Run every script in station 9 from inside this folder. The file organization lesson explains the other folders. - From the ds002718 page on OpenNeuro, download into
rawdatathe top-level files (dataset_description.json,READMEandtask-FaceRecognition_events.json) and the fullsub-002,sub-003andsub-004folders. Or, from the system command line, if you have the AWS CLI:
aws s3 sync --no-sign-request s3://openneuro.org/ds002718 rawdata --exclude "sub-*" --include "sub-002/*" --include "sub-003/*" --include "sub-004/*"Second: try the pipeline on one participant in the GUI
- Open File then Import data then Using EEGLAB functions and plugins then From BIDS folder structure and choose the
rawdatafolder. Enable importing events and electrode locations from the BIDS files, and take the event type from thetrial_typecolumn. Click Ok. A STUDY is created with the three participants. - Pick one participant from the Datasets menu and apply the steps in the GUI as in stations 3 to 5, changing only three settings: mains power in the UK is 50 Hz, not 60; the eye channels are
EEG061andEEG062; and the heart channelsEEG063andEEG064are removed. - Type
eegh. These lines are what you will put inside the loop.
Third: turn the pipeline into a loop
- Copy the single-subject script into a new file
batch_d4.m. Move the processing steps into a function at the end of the file namedprocess_subject, which takes the participant file and the settings, saves the results, and returns a summary. - At the top of the file: the list of participants, the settings, and a
forloop that calls the function insidetry. - In
catch: write the participant name and the error message tologs/batch_log.txt, and record the statusfailedin the summary table. - Run the file. ICA on 72 channels (70 EEG and 2 EOG) and fifty minutes of recording takes time for each participant, so let it run. If you have many participants, see the HPC lesson.
- When it finishes, open
batch_summary.csv. Each row is one participant: status, bad channels, removed components, and remaining epochs.
How do I write it as code?
The same steps in 118 lines of MATLAB
%% D4 batch pipeline: same steps for every subject, errors logged
eeglab nogui
%% Settings
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');
%% Import BIDS data once: events from trial_type, locations from electrodes.tsv
[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
%% Loop over subjects
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, one row per subject
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)
% Single-subject pipeline from stations 3 to 5, with project settings in cfg
[inDir, baseName] = fileparts(inFile);
baseName = strrep(baseName, '_eeg', '');
EEG = pop_loadset('filename', [baseName '_eeg.set'], 'filepath', inDir);
% Remove ECG channels, keep EOG for ICA
EEG = pop_select(EEG, 'rmchannel', cfg.dropLabels);
fullLocs = EEG.chanlocs;
% High-pass: passband edge at 0.1 Hz (removes slow drift)
EEG = pop_eegfiltnew(EEG, 'locutoff', 0.1);
% Notch: remove a narrow band around the line frequency (revfilt = 1)
EEG = pop_eegfiltnew(EEG, 'locutoff', cfg.lineFreq - 2, 'hicutoff', cfg.lineFreq + 2, 'revfilt', 1);
% Detection with clean_rawdata channel criteria only:
% no drift removal, no ASR, no window rejection, EOG channels ignored
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
% Average reference, EOG channels excluded
eogIdx = find(ismember({EEG.chanlocs.labels}, cfg.eogLabels));
EEG = pop_reref(EEG, [], 'exclude', eogIdx);
% ICA copy: same data, high-pass at 1 Hz
EEG_main = EEG;
EEG_ica = pop_eegfiltnew(EEG_main, 'locutoff', 1);
EEG_ica = pop_runica(EEG_ica, 'icatype', 'runica', 'extended', 1);
% Copy the decomposition back to the main dataset
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
% Flag components above 90% Muscle or Eye, then remove them
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
% Low-pass at 30 Hz, postponed until after ICA cleaning
EEG = pop_eegfiltnew(EEG, 'hicutoff', 30);
EEG.setname = [baseName ' clean'];
EEG = pop_saveset(EEG, 'filename', [baseName '_desc-clean_eeg.set'], 'filepath', inDir);
% Epochs, baseline, rejection of epochs beyond the threshold
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;
endHow do I write it as code?
%% D4 batch pipeline: same steps for every subject, errors logged
eeglab nogui
%% Settings
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');
%% Import BIDS data once: events from trial_type, locations from electrodes.tsv
[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
%% Loop over subjects
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, one row per subject
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)
% Single-subject pipeline from stations 3 to 5, with project settings in cfg
[inDir, baseName] = fileparts(inFile);
baseName = strrep(baseName, '_eeg', '');
EEG = pop_loadset('filename', [baseName '_eeg.set'], 'filepath', inDir);
% Remove ECG channels, keep EOG for ICA
EEG = pop_select(EEG, 'rmchannel', cfg.dropLabels);
fullLocs = EEG.chanlocs;
% High-pass: passband edge at 0.1 Hz (removes slow drift)
EEG = pop_eegfiltnew(EEG, 'locutoff', 0.1);
% Notch: remove a narrow band around the line frequency (revfilt = 1)
EEG = pop_eegfiltnew(EEG, 'locutoff', cfg.lineFreq - 2, 'hicutoff', cfg.lineFreq + 2, 'revfilt', 1);
% Detection with clean_rawdata channel criteria only:
% no drift removal, no ASR, no window rejection, EOG channels ignored
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
% Average reference, EOG channels excluded
eogIdx = find(ismember({EEG.chanlocs.labels}, cfg.eogLabels));
EEG = pop_reref(EEG, [], 'exclude', eogIdx);
% ICA copy: same data, high-pass at 1 Hz
EEG_main = EEG;
EEG_ica = pop_eegfiltnew(EEG_main, 'locutoff', 1);
EEG_ica = pop_runica(EEG_ica, 'icatype', 'runica', 'extended', 1);
% Copy the decomposition back to the main dataset
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
% Flag components above 90% Muscle or Eye, then remove them
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
% Low-pass at 30 Hz, postponed until after ICA cleaning
EEG = pop_eegfiltnew(EEG, 'hicutoff', 30);
EEG.setname = [baseName ' clean'];
EEG = pop_saveset(EEG, 'filename', [baseName '_desc-clean_eeg.set'], 'filepath', inDir);
% Epochs, baseline, rejection of epochs beyond the threshold
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;
endWhich value should I choose?
Suitable values for your analysis goal
| Setting | Value in this lesson | Why |
|---|---|---|
| Line frequency | 50 Hz | D4 was recorded in Cambridge, UK, and PowerLineFrequency in the eeg.json file is 50. Your data from Saudi Arabia are 60. This setting is the clearest difference between D1 and D4. |
| Eye and heart channels | EEG061 and EEG062 for the eyes, EEG063 and EEG064 for the heart | From the channels.tsv file in D4. Heart channels are removed; eye channels stay to help ICA and do not enter the reference. |
| Events for epoching | famous_new, unfamiliar_new and scrambled_new | The first presentation of each image, 150 of each type in sub-002. Repetitions have other names (_second_early and _second_late). |
| Import | pop_importbids once before the loop | Reads events from events.tsv and electrode locations from electrodes.tsv, as in the official EEGLAB tutorial on the same data. |
| Where settings live | The cfg variable at the top | Everything that differs between projects is in one place, and the function itself does not change. |
| What happens on error | A line in batch_log.txt, status failed, then the next participant | In the morning you know who failed and why, and you rerun that participant alone. |
Which value should I choose?
| Setting | Value in this lesson | Why |
|---|---|---|
| Line frequency | 50 Hz | D4 was recorded in Cambridge, UK, and PowerLineFrequency in the eeg.json file is 50. Your data from Saudi Arabia are 60. This setting is the clearest difference between D1 and D4. |
| Eye and heart channels | EEG061 and EEG062 for the eyes, EEG063 and EEG064 for the heart | From the channels.tsv file in D4. Heart channels are removed; eye channels stay to help ICA and do not enter the reference. |
| Events for epoching | famous_new, unfamiliar_new and scrambled_new | The first presentation of each image, 150 of each type in sub-002. Repetitions have other names (_second_early and _second_late). |
| Import | pop_importbids once before the loop | Reads events from events.tsv and electrode locations from electrodes.tsv, as in the official EEGLAB tutorial on the same data. |
| Where settings live | The cfg variable at the top | Everything that differs between projects is in one place, and the function itself does not change. |
| What happens on error | A line in batch_log.txt, status failed, then the next participant | In the morning you know who failed and why, and you rerun that participant alone. |
How do I check it worked?
4 quick checks
- The table printed at the end has three rows, with status
okin each row. logs/batch_log.txtdoes not exist or is empty. If there is a line, it holds the participant name and the reason.- In each participant’s folder inside
derivatives/eeglabthere are two new files:desc-cleananddesc-epochs. - The number of remaining epochs for each participant is close to 450 (150 of each type), minus the rejected ones and any epoch that crosses a
boundaryevent (5 in sub-002), becausepop_epochdrops those. If it is much lower for one participant, review it.
How do I check it worked?
- The table printed at the end has three rows, with status
okin each row. logs/batch_log.txtdoes not exist or is empty. If there is a line, it holds the participant name and the reason.- In each participant’s folder inside
derivatives/eeglabthere are two new files:desc-cleananddesc-epochs. - The number of remaining epochs for each participant is close to 450 (150 of each type), minus the rejected ones and any epoch that crosses a
boundaryevent (5 in sub-002), becausepop_epochdrops those. If it is much lower for one participant, review it.
What mistakes do people make?
5 mistakes and how to avoid them
- A loop without
tryandcatch. One error in one participant stops all processing, and the night’s hours are lost. - A silent
catch. Catching an error without logging it is worse than stopping: you think every participant finished. Always log the name and the message, and look at the summary table. - Settings written inside the function. If you write 60 inside
process_subjectand forget it, you process UK data with a Saudi filter. Every setting goes incfg. - Forgetting the differences between datasets. The eye channels in D1 are named
EOG1andEOG2, and in D4EEG061andEEG062. Copying the script without checking these names makes ICA and the reference treat eye channels as scalp channels. - Trusting the loop without checking. A summary saying
okdoes not mean the cleaning is good. Open one or two files in the GUI, and look at the number of removed components and remaining epochs for each participant. The odd value in the table is the participant you review first.
What mistakes do people make?
- A loop without
tryandcatch. One error in one participant stops all processing, and the night’s hours are lost. - A silent
catch. Catching an error without logging it is worse than stopping: you think every participant finished. Always log the name and the message, and look at the summary table. - Settings written inside the function. If you write 60 inside
process_subjectand forget it, you process UK data with a Saudi filter. Every setting goes incfg. - Forgetting the differences between datasets. The eye channels in D1 are named
EOG1andEOG2, and in D4EEG061andEEG062. Copying the script without checking these names makes ICA and the reference treat eye channels as scalp channels. - Trusting the loop without checking. A summary saying
okdoes not mean the cleaning is good. Open one or two files in the GUI, and look at the number of removed components and remaining epochs for each participant. The odd value in the table is the participant you review first.
Your browser doesn't allow saving progress. All lessons are open, but completion marks won't be saved.
Done. Your progress is saved in this browser.UndoHow do I write it in my paper?
A Methods template: edit the data, settings and versions to match what you ran
A template: edit the data, settings and versions to match what you ran.
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.How do I write it in my paper?
A template: edit the data, settings and versions to match what you ran.
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.Where can I read more?
3 sources, official docs first
- EEGLAB TutorialDocumentation10. Group analysis > a. Batch processing
- EEGLAB TutorialDocumentation11. Scripting > f. BIDS pipeline
- Makoto's preprocessing pipelineBatch processing (§17.4)
Written for EEGLAB 2026.1 · 2026-10-28
Going further
- EEGLAB Tutorial: https://eeglab.org/tutorials/10_Group_analysis/multiple_subject_proccessing_overview.html (10. Group analysis > a. Batch processing)
- EEGLAB Tutorial: https://eeglab.org/tutorials/11_Scripting/Analyzing_EEG_BIDS_data_in_EEGLAB.html (11. Scripting > f. BIDS pipeline)
- Makoto's preprocessing pipeline: https://eeglab.ucsd.edu/wiki/Makoto%27s_preprocessing_pipeline (Batch processing (§17.4))
Need help?
Ask, share feedback, or report an error
- Report a scientific error · Needs a GitHub account. Don't have one? Use "Share your thoughts".