Station 10 · Lesson 4

Writing an EEGLAB plugin

Optional15 minBefore this lesson: A single-subject scriptPrint the card
Starts from: eeglab_data.set (D1) · Nothing yet: the data as downloaded.Download the data (opens in a new tab)
Script to reach this state
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;

The idea in brief

Almost every menuA list of commands that opens from its name at the top of the window. in EEGLAB comes from a plugin: DIPFIT, ICLabelA tool that classifies each ICA component into seven classes with a probability for each. and firfilt are all plugins. If you write a tool you use in every project, turning it into a pluginA package that adds new functions or menus to EEGLAB. makes it a menu item like any official tool, and lets your colleagues use it the same way.

Before and after

Image coming soon.

Two screenshots side by side. Left: the plugins folder inside the EEGLAB folder, holding the chanvar1.0 folder with the two files eegplugin_chanvar.m and pop_chanvar.m. Right: the EEGLAB Plot menu open, ending with the new Channel variance item below a separator line. Source: screenshot from EEGLAB 2026.1 on the project owner’s computer.

Your next questions, each answered in its own section:

Why do I need this step?

The reasons in detail, and the terms you need

A plugin is simpler than you might expect. It is a folder inside the EEGLAB plugins folder, holding two files:

  • A file whose name starts with eegplugin_. EEGLAB runs it at every startup, and its only job is to add the item to the menu.
  • A function whose name starts with pop_. This is the tool itself: it opens a window when arguments are missing, and it returns the command string that reproduces the same result, so it appears in the command historyThe list of commands the GUI has run, shown by the eegh command..

The second rule is what makes your tool part of your scriptA MATLAB file of commands that runs processing steps in order.. Every click on your item appears in eegh as a line of code, as you learned in the command history lesson.

In this lesson we write a plugin called chanvar: it plots the standard deviation of each channelThe signal recorded from one electrode, as shown in EEGLAB. and colors in red the channels far from the rest. A quick check tool, before or after the bad channels lesson.

How do I do it in EEGLAB?

7 steps in the menus

First: create the plugin folder

  1. Type in the command window:
MATLAB
pluginDir = fullfile(fileparts(which('eeglab')), 'plugins', 'chanvar1.0');
mkdir(pluginDir); cd(pluginDir);

The folder name carries the version: EEGLAB reads chanvar1.0 as a plugin named chanvar, version 1.0.

Second: write the pop_ function

  1. Type edit pop_chanvar.m, paste this code, and save:
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);

Third: write the eegplugin_ file

  1. Type edit eegplugin_chanvar.m, paste this code, and save:
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');

Fourth: try the plugin

  1. Close the EEGLAB window and type eeglab again, because EEGLAB looks for plugins only at startup. The command window prints a line containing adding "chanvar" v1.0.
  2. Load D1 as in “Starting point”, but from the GUIThe windows and menus used with the mouse instead of typed commands.: File then Load existing dataset.
  3. Open Plot then Channel variance. Your window appears with 3 in it. Click Ok. The plot appears.
  4. Type eegh. The last line is pop_chanvar(EEG, 3);. Your tool is now part of the command history like any official tool.

How do I write it as code?

The same steps in 10 lines of MATLAB

The pop_ function also works from a script, without the menu. This test checks the basic rule: the string the function returns reproduces the same result.

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

Which value should I choose?

Suitable values for your analysis goal
SettingValue in this lessonWhy
Folder locationplugins inside the EEGLAB folderThis is where EEGLAB looks at every startup for folders holding a file that starts with eegplugin (eeglab.m).
Folder namechanvar1.0Digits at the end of the name are read as a version. If it differs from the version eegplugin_ returns, EEGLAB prints a warning.
Data checktrystrs.check_dataMakes sure a datasetOne EEG data file loaded in EEGLAB together with its information. is loaded before running. For functions that need epochA short time segment cut out around an event. use trystrs.check_epoch, and for ones that need ICAA method that separates the recording into independent sources, some brain and some artifact. trystrs.check_ica.
Historycatchstrs.add_to_histAdds LASTCOM to the history and stores the dataset in ALLEEG. If the command starts with EEG =, EEGLAB creates a new dataset automatically.
Highlight thresholdA value beyond which the signal is treated as a problem.z = 3A common starting value for outliers. The tool is for visual checking, not for removing channels automatically.

How do I check it worked?

4 quick checks
  • When you start eeglab, the command window prints a line containing adding "chanvar" v1.0.
  • The Plot then Channel variance item exists and opens a window with the threshold box.
  • After clicking Ok, a bar plot appears with one bar per channel (32 in D1).
  • eegh shows pop_chanvar(EEG, 3);, and the script above runs without error.

What mistakes do people make?

5 mistakes and how to avoid them
  • Putting the two files outside the plugins folder. EEGLAB does not look anywhere else, so the item does not appear.
  • A pop_ function that returns nothing. Without com, nothing is recorded in eegh, so your click cannot be repeated in your script.
  • A command string that does not reproduce the result. If the user types 2.5 in the window, the string must be pop_chanvar(EEG, 2.5);, not the default value. That is why com is built from the values actually used.
  • Expecting the item to appear with eeglab nogui. In this mode EEGLAB adds the plugin folder to the path but does not run eegplugin_, so there are no menus. This is normal.
  • Testing the plugin from the menu only. EEGLAB catches errors coming from menus. To trace an error, type dbstop if error and call the function from the command window (advice from the official documentation).

Where can I read more?

2 sources, official docs first

Written for EEGLAB 2026.1 · 2026-10-28

Need help?

Ask, share feedback, or report an error