A07: Contributing to EEGLAB
From SCCN
Contents |
Adding capabilities to EEGLAB
EEGLAB operates in the very rich Matlab environment. The structure of EEGLAB functions makes it easy to combine them in new ways in original Matlab _scripts_ which may use any of the wide variety of processing tools and methods available in Matlab. Thus, the most straightforward way to add to EEGLAB capabilities is to use EEGLAB functions and data structures in your own Matlab scripts, something many or most EEGLAB users do routinely.
Matlab functions provide a level of encapsulation and isolation that minimize the possibility of interference with variable names and processing outside the functions themselves, e.g. in Matlab scripts that call them. EEGLAB is, in essence, a large set of Matlab functions. Please send us (eeglab@sccn.ucsd.edu) any EEGLAB-compatible functions you think would be of interest to other researchers. We will consider any functions sent us for inclusion in the EEGLAB distribution. Include a succinct explanation and references for the signal processing methods used. If possible, use EEGLAB help message style.
Open source policy
- EEGLAB is distributed under the GPL GNU license, which states that the software cannot be modified for commercial purposes. Any contributed functions we add to EEGLAB will be made available for free non-commercial use under this license.
- We will credit your authorship of the functions on the function help pages. The authors will retain all commercial rights to the functions.
- Functions that we find to be accurate, stable, of some general interest and complementary to existing EEGLAB functions will first be included in a 'contributed' directory distributed as a part of EEGLAB. If a contributed function proves to be stable and of widespread interest, we may integrate it into the main EEGLAB menu.
Also consider the 'plug-in' option (described in Section below). EEGLAB _plug-ins_ allow authors to flexibly incorporate new functions in the EEGLAB menu of all users who have also downloaded their plug-in.
How to write EEGLAB functions
Adding new functionality to EEGLAB requires a pair of functions, a signal processing function (Ex: sample.m) and an accompanying pop_function (Ex: pop_sample.m). The pop_function pops up a text input window allowing the user to specify arguments to the signal processing function. The Matlab help messages for each function should state clearly what input arguments the functions require and what they output, using the help message format explained below. You should read the beginning of the script section to understand the different levels of functions in EEGLAB.
The signal processing function
This function should comply with the EEGLAB help-message syntax to allow the header to be converted into an .html help page by (functions makehtml() and help2html(). We propose this sample header. Below is the GNU license disclaimer to include in the function header.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
The associated pop_ function
The pop_function creates a graphic interface to the signal processing function. It should include the same disclaimer as the signal processing function and
- It must take the EEGLAB data structure 'EEG' as a first input. The second parameter may specify whether the signal processing function will be applied to ICA component activations or to the raw EEG data channels.
- Additional parameters should be optional. If they are left blank in the pop_function call, a window should pop-up to ask for their values.
- The pop_function must return a 'string' containing the resulting call to the signal processing function (or in some cases to the pop_function). When this string is evaluated (using the Matlab function 'eval()'), the result must be the same as that of the pop_function itself, e.g. including all the parameters the user may enter into the pop window. This string will be pushed into the EEGLAB command history stack.
- By convention, if the function draws a figure, calling the function without enough arguments should pop up a new figure. However, with enough arguments (macro call), the function should directly draw the output graphic in the current figure (thus allowing the user to build multi-part figures, e.g. using 'sbplot()' commands). Writing the pop_function is easy and can usually be done in a few minutes if you just modify the [BROKEN LINK pop_sample.m*|download/pop_sample.m] function source.
How to write an EEGLAB plug-in
EEGLAB also has a _plug-in_ facility that automatically searches for functions loaded into a specified plug-in directory, causing them to appear in the EEGLAB menu. EEGLAB plug-in functions can be offered for download and use by anyone, independent of the EEGLAB distribution, or may be included in the EEGLAB distribution itself.
EEGLAB will automatically incorporate any appropriately named "plugin" functions (Ex: 'eegplugin_myfunc.m') that EEGLAB finds in the same directory as 'eeglab.m'. Creating an EEGLAB plugin will add a menu item with the menu label(s) specified in your plugin to the bottom of an EEGLAB menu (the top menu label possibly linked to an unlimited number of sub-menus). These menu item(s) can call standard or custom data processing and "pop" functions (see examples below). When a user downloads an EEGLAB plugin (either from the main EEGLAB site or from any other site), he or she simply has to uncompress the plugin files into the plugin sub-directory or into the main EEGLAB directory (where eeglab.m is located). The plugin will be detected by EEGLAB at startup by looking for a file or directory name beginning with eegplugin_ in the main EEGLAB directory (i.e., the same directory as 'eeglab.m'). You may also place this file in a sub-directory of the EEGLAB plugin directory.
The plugin function
To create a new EEGLAB plugin, simply create a Matlab function file whose name begins with "eegplugin_" and place it into the plugin subdirecotry or your main EEGLAB directory. This function must take three arguments, as in the 'test' plugin below:
>>eegplugin_test (fig, try_strings, catch_strings);
The three arguments above are provided to the plugin by eeglab(). The first argument ('fig') is the handle of the main EEGLAB window. The second and third arguments are structures passed by EEGLAB that allow the plugin to check parameters, detect errors, etc. (see below). If you do not want your plugin to alter EEGLAB history and error message handling, you can ignore the latter two parameters (although the plugin function definition still must list all three arguments).
Adding a sub-menu
To create a new submenu under a top-level EEGLAB menu, simply add a command like this to your plugin function:
>>uimenu( fig, 'label', 'My function', 'callback', ... [ 'EEG = pop_myfunc(EEG, ...); [ALLEEG EEG CURRENTSET] ... = eeg_store(ALLEEG, EEG, CURRENTSET);' ]);
The statement [ALLEEG EEG CURRENTSET] = eeg_store(ALLEEG, EEG, CURRENTSET); above insures that your modified EEG dataset will be stored in the EEGLAB ALLEEG structure.
Plugins and EEGLAB history
If you want your plugin to interact with the EEGLAB history mechanism, you should take advantage of the second ('try_strings') and third ('catch_strings') arguments to your plugin function. The second argument (see eegplugin_test() above) contains commands (organized into a Matlab structure) that check the input dataset and attempt to execute your command. The third argument ('catch_strings') contains commands to handle errors and add the contents of the LASTCOM (i.e., last command) variable to the EEGLAB history.
Plugin functions should declare one or more EEGLAB menu items. Each menu declaration should look like this:
uimenu( submenu, 'label', 'My function', 'callback', ... [ try_strings.anyfield '[EEG LASTCOM] ... = pop_myfunc(EEG, ...);' arg3.anyfield ]);
Possible fields for 'try_strings' (above) are:
- try_strings.no_check : check for the presence of a non-empty EEG dataset only
- try_strings.check_ica : check that the dataset includes ICA weights
- try_strings.check_cont : check that the dataset is continuous
- try_strings.check_epoch : check that the dataset is epoched
- try_strings.check_event : check that the dataset contains events
- try_strings.check_epoch_ica : check that the dataset is epoched _and_ includes ICA weights
- try_strings.check_chanlocs : check that the dataset contains a channel location file
- try_strings.check_epoch_chanlocs : check that the dataset is epoched _and_ includes a channel location file
- try_strings.check_epoch_ica_chanlocs : check that the dataset is epoched _and_ includes ICA weights and a channel location file.
Possible fields for 'catch_strings' are:
- catch_strings.add_to_hist : add the LASTCOM variable content (if not empty) to the EEGLAB history
- catch_strings.store_and_hist : add the LASTCOM variable content (if not empty) to the EEGLAB history _and_ store the EEG dataset in the ALLEEG variable.
- catch_strings.new_and_hist : add the LASTCOM variable content (if not empty) to the EEGLAB history _and_ pop up a window for a new dataset.
Plugin examples
A simplest type of plugin function might only call a plotting function. For instance, to write a simple plugin to plot the ERP trial average at every channel in a different color (without performing any data checking):
% eegplugin_erp() - plot ERP plugin function eegplugin_erp( fig, try_strings, catch_strings); % create menu plotmenu = findobj(fig, 'tag', 'plot'); uimenu( plotmenu, 'label', 'ERP plugin', ...'callback', 'figure; plot(EEG.times, mean(EEG.data,3));');
Save the text above as a file, 'eegplugin_erp.m' into the plugin sub-directory of EEGLAB (or the EEGLAB directory where _eeglab.m_ is located) and restart EEGLAB (click here to download this .m file). Then select the menu item Plot > ERP plugin to plot the ERP of an epoched dataset.
Another, more complete example: To create a plugin named 'PCA' that would apply PCA to your data and store the PCA weights in place of the ICA weights, save the Matlab commands below as file 'eegplugin_pca.m' into the plugin sub-directory of EEGLAB (or the EEGLAB directory where _eeglab.m_ is located) and restart EEGLAB (click here to download this .m file).
% eegplugin_pca() - pca plugin function eegplugin_pca( fig, try_strings, catch_strings); % create menu toolsmenu = findobj(fig, 'tag', 'tools'); submenu = uimenu( toolsmenu, 'label', 'PCA plugin'); % build command for menu callback\\ cmd = [ '[tmp1 EEG.icawinv] = runpca(EEG.data(:,:));' ]; cmd = [ cmd 'EEG.icaweights = pinv(EEG.icawinv);' ]; cmd = [ cmd 'EEG.icasphere = eye(EEG.nbchan);' ]; cmd = [ cmd 'clear tmp1;' ]; finalcmd = [ try_strings.no_check cmd ]; finalcmd = [ finalcmd 'LASTCOM = ''' cmd ''';' ]; finalcmd = [ finalcmd catch_strings.store_and_hist ]; % add new submenu uimenu( submenu, 'label', 'Run PCA', 'callback', finalcmd);
Note: As of EEGLAB v4.3 you may add plugin menu items to different EEGLAB menus. Above, we add a sub-menu to the Tools menu by specifying 'tag','tools' in the findobj() call. If the specified tag were import data, EEGLAB would add the plugin to the File > Import data menu. Using the tag import epoch would add the plugin to the File > Import epoch info menu. The tag import event would add the plugin to the File > Import event info menu. The tag export would add the plugin to the File > Export data menu. Finally, the tag plot would add the plugin to the Plot menu. (Note that the tag call should be in lower case).
After installing the plugin above, a new EEGLAB menu item Tools > PCA plugin will be created. Use this menu item to run PCA on the current EEG dataset. The resulting PCA decomposition will be stored in place of the ICA decomposition. (Note: This is possible since both PCA and ICA are linear decompositions).
See the EEGLAB DIPFIT plugin eegplugin_dipfit() for an example of a more elaborate plugin.
Note: In EEGLAB4.3 we slightly modified how EEGLAB handles plugins. As a result, EEGLAB might not be compatible with earlier plugin functions. Subsequent versions of EEGLAB have and will support backwards compatibility of the plugin conventions.
