# data[].attributes.body
Download
https://drive.google.com/u/0/uc?id=1UM0gvX0VcBjqKoKRD9zZ6zTF22NoATH7&export=download

# data[].attributes.attachment_link.readable_text
is software designed to enclose the different steps from EEG signal preprocessing to brain network visualization. This includes loading the scalp EEG signals, estimation of cortical sources by solving the inverse problem, calculation of connectivity matrices, calculation of various network measures and visualizing the resulting brain networks in an easy and flexible graphical user interface.

# data[].attributes.attachment_link.description
is software designed to enclose the different steps from EEG signal preprocessing to brain network visualization. This includes loading the scalp EEG signals, estimation of cortical sources by solving the inverse problem, calculation of connectivity matrices, calculation of various network measures and visualizing the resulting brain networks in an easy and flexible graphical user interface.

# data[].attributes.attachment_link.readable_text
eeg_recording.zip is a real patient recording aquired with a Nihon Kohden system
and converted to EDF+ by EDFbrowser. The recording contains 37 unipolar signals
plus the EDF+ annotations. Signal 1 to 26 contain the EEG. Signal 27 (X1) and 28 (X2)
contain the ECG. Signal 32 (X6) contains the respiration.
In the zip-file is a montage file included for convenience, after opening the EDF-file in
EDFbrowser, load the montage file. Here is a screenshot.

test_generator_2_edfplus.zip is an EDFplus-file which contains artificial waveforms to test viewers,
filters, and other kinds of software. There are also two annotations in the file. It contains the following signals:

 signal label/waveform  amplitude    f       sf
 ---------------------------------------------------
    1    squarewave        100 uV    0.1Hz   200 Hz
    2    ramp              100 uV    1 Hz    200 Hz
    3    pulse             100 uV    1 Hz    200 Hz
    4    ECG               100 uV    1 Hz    200 Hz
    5    noise             100 uV    - Hz    200 Hz
    6    sine 1 Hz         100 uV    1 Hz    200 Hz
    7    sine 8 Hz         100 uV    8 Hz    200 Hz
    8    sine 8.5 Hz       100 uV    8.5Hz   200 Hz
    9    sine 15 Hz        100 uV   15 Hz    200 Hz
   10    sine 17 Hz        100 uV   17 Hz    200 Hz
   11    sine 50 Hz        100 uV   50 Hz    200 Hz

test_generator_2_bdfplus.zip is a BDFplus-file with the same content.

Here is a screenshot.

test_generator.zip is an (old-type) EDF-file which contains artificial waveforms to test viewers,
filters, and other kinds of software. It contains the following signals:

 signal label  waveform       physical range         f         sf
 --------------------------------------------------------------------
    1    F4     block          +800uV/-800uV          1Hz       200Hz
    2    F3     triangle       +800uV/-800uV          3Hz       100Hz
    3    X10    impulse        +0.8mV/-0.8mV          5Hz       200Hz
    4    FP2    noise          +3200uV/-3200uV        -Hz       200Hz
    5    P4     sine           +800uV/-800uV          1Hz        50Hz
    6    C4     sine           +800uV/-800uV          2Hz       100Hz
    7    P3     sine           +800uV/-800uV          3Hz       200Hz
    8    C3     sine           +800uV/-800uV          4Hz       200Hz
    9    X9     sine           +800uV/-800uV          8Hz       200Hz
   10    FP1    sine           +800uV/-800uV         16Hz       200Hz
   11    F8     sine           +800uV/-800uV         32Hz       200Hz
   12    F7     triangle       +4mV/-4mV              5Hz       200Hz
   13    DC01   sine square    +6V/-0V                5Hz       200Hz
   14    DC04   DC             +100%                  -Hz        25Hz
   15    DC03   DC             +60BPM                 -Hz        25Hz
   16    DC02   DC             +16384                 -Hz        25Hz

Here is a screenshot.

# data[].attributes.attachment_link.description
eeg_recording.zip is a real patient recording aquired with a Nihon Kohden system and converted to EDF+ by EDFbrowser. The recording contains 37 unipolar signals plus the EDF+ annotations. Signal 1 to 26 contain the EEG. Signal 27 (X1) and 28 (X2) contain the ECG. Signal 32 (X6) contains the respiration.

# data[].attributes.attachment_link.readable_text
eeg_recording.zip is a real patient recording aquired with a Nihon Kohden system
and converted to EDF+ by EDFbrowser. The recording contains 37 unipolar signals
plus the EDF+ annotations. Signal 1 to 26 contain the EEG. Signal 27 (X1) and 28 (X2)
contain the ECG. Signal 32 (X6) contains the respiration.
In the zip-file is a montage file included for convenience, after opening the EDF-file in
EDFbrowser, load the montage file. Here is a screenshot.

test_generator_2_edfplus.zip is an EDFplus-file which contains artificial waveforms to test viewers,
filters, and other kinds of software. There are also two annotations in the file. It contains the following signals:

 signal label/waveform  amplitude    f       sf
 ---------------------------------------------------
    1    squarewave        100 uV    0.1Hz   200 Hz
    2    ramp              100 uV    1 Hz    200 Hz
    3    pulse             100 uV    1 Hz    200 Hz
    4    ECG               100 uV    1 Hz    200 Hz
    5    noise             100 uV    - Hz    200 Hz
    6    sine 1 Hz         100 uV    1 Hz    200 Hz
    7    sine 8 Hz         100 uV    8 Hz    200 Hz
    8    sine 8.5 Hz       100 uV    8.5Hz   200 Hz
    9    sine 15 Hz        100 uV   15 Hz    200 Hz
   10    sine 17 Hz        100 uV   17 Hz    200 Hz
   11    sine 50 Hz        100 uV   50 Hz    200 Hz

test_generator_2_bdfplus.zip is a BDFplus-file with the same content.

Here is a screenshot.

test_generator.zip is an (old-type) EDF-file which contains artificial waveforms to test viewers,
filters, and other kinds of software. It contains the following signals:

 signal label  waveform       physical range         f         sf
 --------------------------------------------------------------------
    1    F4     block          +800uV/-800uV          1Hz       200Hz
    2    F3     triangle       +800uV/-800uV          3Hz       100Hz
    3    X10    impulse        +0.8mV/-0.8mV          5Hz       200Hz
    4    FP2    noise          +3200uV/-3200uV        -Hz       200Hz
    5    P4     sine           +800uV/-800uV          1Hz        50Hz
    6    C4     sine           +800uV/-800uV          2Hz       100Hz
    7    P3     sine           +800uV/-800uV          3Hz       200Hz
    8    C3     sine           +800uV/-800uV          4Hz       200Hz
    9    X9     sine           +800uV/-800uV          8Hz       200Hz
   10    FP1    sine           +800uV/-800uV         16Hz       200Hz
   11    F8     sine           +800uV/-800uV         32Hz       200Hz
   12    F7     triangle       +4mV/-4mV              5Hz       200Hz
   13    DC01   sine square    +6V/-0V                5Hz       200Hz
   14    DC04   DC             +100%                  -Hz        25Hz
   15    DC03   DC             +60BPM                 -Hz        25Hz
   16    DC02   DC             +16384                 -Hz        25Hz

Here is a screenshot.

# data[].attributes.attachment_link.description
eeg_recording.zip is a real patient recording aquired with a Nihon Kohden system and converted to EDF+ by EDFbrowser. The recording contains 37 unipolar signals plus the EDF+ annotations. Signal 1 to 26 contain the EEG. Signal 27 (X1) and 28 (X2) contain the ECG. Signal 32 (X6) contains the respiration.

# data[].attributes.attachment_link.readable_text
eeg_recording.zip is a real patient recording aquired with a Nihon Kohden system
and converted to EDF+ by EDFbrowser. The recording contains 37 unipolar signals
plus the EDF+ annotations. Signal 1 to 26 contain the EEG. Signal 27 (X1) and 28 (X2)
contain the ECG. Signal 32 (X6) contains the respiration.
In the zip-file is a montage file included for convenience, after opening the EDF-file in
EDFbrowser, load the montage file. Here is a screenshot.

test_generator_2_edfplus.zip is an EDFplus-file which contains artificial waveforms to test viewers,
filters, and other kinds of software. There are also two annotations in the file. It contains the following signals:

 signal label/waveform  amplitude    f       sf
 ---------------------------------------------------
    1    squarewave        100 uV    0.1Hz   200 Hz
    2    ramp              100 uV    1 Hz    200 Hz
    3    pulse             100 uV    1 Hz    200 Hz
    4    ECG               100 uV    1 Hz    200 Hz
    5    noise             100 uV    - Hz    200 Hz
    6    sine 1 Hz         100 uV    1 Hz    200 Hz
    7    sine 8 Hz         100 uV    8 Hz    200 Hz
    8    sine 8.5 Hz       100 uV    8.5Hz   200 Hz
    9    sine 15 Hz        100 uV   15 Hz    200 Hz
   10    sine 17 Hz        100 uV   17 Hz    200 Hz
   11    sine 50 Hz        100 uV   50 Hz    200 Hz

test_generator_2_bdfplus.zip is a BDFplus-file with the same content.

Here is a screenshot.

test_generator.zip is an (old-type) EDF-file which contains artificial waveforms to test viewers,
filters, and other kinds of software. It contains the following signals:

 signal label  waveform       physical range         f         sf
 --------------------------------------------------------------------
    1    F4     block          +800uV/-800uV          1Hz       200Hz
    2    F3     triangle       +800uV/-800uV          3Hz       100Hz
    3    X10    impulse        +0.8mV/-0.8mV          5Hz       200Hz
    4    FP2    noise          +3200uV/-3200uV        -Hz       200Hz
    5    P4     sine           +800uV/-800uV          1Hz        50Hz
    6    C4     sine           +800uV/-800uV          2Hz       100Hz
    7    P3     sine           +800uV/-800uV          3Hz       200Hz
    8    C3     sine           +800uV/-800uV          4Hz       200Hz
    9    X9     sine           +800uV/-800uV          8Hz       200Hz
   10    FP1    sine           +800uV/-800uV         16Hz       200Hz
   11    F8     sine           +800uV/-800uV         32Hz       200Hz
   12    F7     triangle       +4mV/-4mV              5Hz       200Hz
   13    DC01   sine square    +6V/-0V                5Hz       200Hz
   14    DC04   DC             +100%                  -Hz        25Hz
   15    DC03   DC             +60BPM                 -Hz        25Hz
   16    DC02   DC             +16384                 -Hz        25Hz

Here is a screenshot.

# data[].attributes.attachment_link.description
eeg_recording.zip is a real patient recording aquired with a Nihon Kohden system and converted to EDF+ by EDFbrowser. The recording contains 37 unipolar signals plus the EDF+ annotations. Signal 1 to 26 contain the EEG. Signal 27 (X1) and 28 (X2) contain the ECG. Signal 32 (X6) contains the respiration.

# data[].attributes.attachment_link.readable_text
eeg_recording.zip is a real patient recording aquired with a Nihon Kohden system
and converted to EDF+ by EDFbrowser. The recording contains 37 unipolar signals
plus the EDF+ annotations. Signal 1 to 26 contain the EEG. Signal 27 (X1) and 28 (X2)
contain the ECG. Signal 32 (X6) contains the respiration.
In the zip-file is a montage file included for convenience, after opening the EDF-file in
EDFbrowser, load the montage file. Here is a screenshot.

test_generator_2_edfplus.zip is an EDFplus-file which contains artificial waveforms to test viewers,
filters, and other kinds of software. There are also two annotations in the file. It contains the following signals:

 signal label/waveform  amplitude    f       sf
 ---------------------------------------------------
    1    squarewave        100 uV    0.1Hz   200 Hz
    2    ramp              100 uV    1 Hz    200 Hz
    3    pulse             100 uV    1 Hz    200 Hz
    4    ECG               100 uV    1 Hz    200 Hz
    5    noise             100 uV    - Hz    200 Hz
    6    sine 1 Hz         100 uV    1 Hz    200 Hz
    7    sine 8 Hz         100 uV    8 Hz    200 Hz
    8    sine 8.5 Hz       100 uV    8.5Hz   200 Hz
    9    sine 15 Hz        100 uV   15 Hz    200 Hz
   10    sine 17 Hz        100 uV   17 Hz    200 Hz
   11    sine 50 Hz        100 uV   50 Hz    200 Hz

test_generator_2_bdfplus.zip is a BDFplus-file with the same content.

Here is a screenshot.

test_generator.zip is an (old-type) EDF-file which contains artificial waveforms to test viewers,
filters, and other kinds of software. It contains the following signals:

 signal label  waveform       physical range         f         sf
 --------------------------------------------------------------------
    1    F4     block          +800uV/-800uV          1Hz       200Hz
    2    F3     triangle       +800uV/-800uV          3Hz       100Hz
    3    X10    impulse        +0.8mV/-0.8mV          5Hz       200Hz
    4    FP2    noise          +3200uV/-3200uV        -Hz       200Hz
    5    P4     sine           +800uV/-800uV          1Hz        50Hz
    6    C4     sine           +800uV/-800uV          2Hz       100Hz
    7    P3     sine           +800uV/-800uV          3Hz       200Hz
    8    C3     sine           +800uV/-800uV          4Hz       200Hz
    9    X9     sine           +800uV/-800uV          8Hz       200Hz
   10    FP1    sine           +800uV/-800uV         16Hz       200Hz
   11    F8     sine           +800uV/-800uV         32Hz       200Hz
   12    F7     triangle       +4mV/-4mV              5Hz       200Hz
   13    DC01   sine square    +6V/-0V                5Hz       200Hz
   14    DC04   DC             +100%                  -Hz        25Hz
   15    DC03   DC             +60BPM                 -Hz        25Hz
   16    DC02   DC             +16384                 -Hz        25Hz

Here is a screenshot.

# data[].attributes.attachment_link.description
eeg_recording.zip is a real patient recording aquired with a Nihon Kohden system and converted to EDF+ by EDFbrowser. The recording contains 37 unipolar signals plus the EDF+ annotations. Signal 1 to 26 contain the EEG. Signal 27 (X1) and 28 (X2) contain the ECG. Signal 32 (X6) contains the respiration.

# data[].attributes.headline
FORM QUESTION: We get the dataset visualisation working, how should it be represented / presented in the artwork

# data[].attributes.subject
FORM QUESTION: We get the dataset visualisation working, how should it be represented / presented in the artwork

# data[].attributes.headline
EDFBrowser for visualisations of EEG data (I have this installed now)

# data[].attributes.subject
EDFBrowser for visualisations of EEG data (I have this installed now)

# data[].attributes.attachment_link.readable_text
A free, opensource, multiplatform, universal viewer and toolbox intended for, but not limited to, timeseries storage files
like EEG, EMG, ECG, BioImpedance, etc.

Features

Easy to install, just one executable, works everywhere, no special requirements or dependencies, no Python, Octave or Matlab needed

EDFbrowser is one of the fastest, if not, the fastest EDF viewer available.

Supported fileformats: EDF, EDF+, BDF, BDF+

Nihon Kohden (*.eeg) to EDF+ converter (including annotations)

Unisens to EDF+ converter

MIT to EDF+ converter (including annotations) for Physiobank

Manscan Microamps (*.mbi/*.mb2) to EDF+ converter (including annotations)

SCP-ECG (*.scp, EN 1064) to EDF+ converter

ISHNE (*.ecg) to EDF+ converter

Synchronized video playback

Emsa (*.PLG) to EDF+ converter (including annotations)

ASCII to EDF/BDF converter

Finometer (Beatscope) to EDF converter

Bmeye Nexfin (FrameInspector) to EDF converter

WAV to EDF converter

Mortara XML ECG to EDF converter

reads Biosemi's trigger inputs from the BDF "Status" signal

Annotation editor

Header editor, fixes also lot's of different format-errors

1th to 8th order Butterworth, Chebyshev, Bessel and "moving average" filters

Notchfilter with adjustable Q-factor

Customizable FIR filter

ECG powerline interference removal filter

Spike filter removes spikes, glitches, fast transients or pacemaker impulses.

Powerspectrum (FFT) with selectable window funtions and window lengths

Color Density Spectral Array (CDSA)

Hypnogram

Pan-Tompkins QRS detector with possibility to export beats and RR-intervals

FM modulated (transtelephonic) ECG recording to EDF converter

Z-EEG measurement

Waveform averaging using triggers, events or annotations, with export possibility

Supports montages

Import or export Annotations/events

File reducer/cropper/decimator

Downsampling signals

Precise measurements by using crosshairs

Zoomfunction by drawing a rectangle with the mouse

Shows signals from different files at the same time

EDF/EDF+/BDF/BDF+ to ASCII converter

EDF/EDF+/BDF/BDF+ compatibility checker

EDF+D to EDF+C converter

BDF(+) to EDF(+) converter

Prints to a printer, image or PDF

Combine several files and export it to one new EDF file

Export a part of a file to a new file

Reads from a streaming file (monitor)

Available for Linux and Windows
(the source can be compiled on Mac OS X)

More info

Download

This is free software, it is experimental and available under the GPL License version 3.
No charge, no warranty, no taxes, no maintenance fees, no advertising, no adware, no spyware, no telemetry or data collection,
no automatic updates, no sales calls, no spam...
Even though this program is free, it is not cheap. A great deal of effort went into making this program useful,
so if you find a problem, please use the email address given in the program's about menu to report it.
Disclaimer:
Despite this software is intend to be usefull, there is no warranty, use this software at your own risk!
EDFbrowser may NOT be used in safety-critical applications, such as life-support medical systems.
The author is NOT responsible for any consequences. For research and educational purpose only.

Linux

Arch Linux users can install from the user repository: https://aur.archlinux.org/packages/edfbrowser/

Ubuntu Linux users can install from the user repository: https://packages.ubuntu.com/groovy/edfbrowser
Unfortunately, the versions offered from Ubuntu (and Debian) are rather old and I don't recommend them.
Compile from source instead as described below, it's very easy.

Mac

I don't have a Mac so I can't support it. Fortunately there's a volunteer who is so kind to compile EDFbrowser for the Mac.
A ready to install Mac OS X Disk Image File (dmg) can be foundhere or via Homebrew:

 brew cask install edfbrowser

Linux (sourcecode)

Click here (GitLab) for the latest revision/patch/pre-release

64-bit Windows 7 and later

If there's a 32-bit version present on your system, remove it first before installing the 64-bit version.

32-bit Windows 2000, XP, and later

Docker

Version info

Older versions

Latest patches & additions

The following bugfixes / additions will be available in the next version (you can pull them from Gitlab):
- Fixed a regression bug that caused the background of the signallabels not being cleared before drawing.
- BDF to EDF converter: Offer the possibility to disable the highpass-filter.

Compiling and installing on Ubuntu Linux and derivatives

Simply execute the following commands in a terminal:

  sudo apt-get update
  sudo apt-get install g++ make git qtbase5-dev-tools qtbase5-dev qt5-default
  git clone https://gitlab.com/Teuniz/EDFbrowser.git
  cd EDFbrowser
  qmake
  make -j4
  sudo make install
  edfbrowser

Other EDF software

Some commandline format converters (without graphical user interface) for scripts or batchfiles.
Note that these converters are also in EDFbrowser.

A very convenient open-source programming library for C/C++ and Java programmers who want to implement EDF(+) and/or BDF(+).

EDF for Labview, a collection of VI's to write files in the European Data Format.

# data[].attributes.attachment_link.description
A free, opensource, multiplatform, universal viewer and toolbox intended for, but not limited to, timeseries storage files like EEG, EMG, ECG, BioImpedance, etc. Easy to install, just one executable, works everywhere, no special requirements or dependencies, no Python, Octave or Matlab needed EDFbrowser is one of the fastest, if not, the fastest EDF viewer available.

# data[].attributes.attachment_link.provider_name
Neuroelectrics Blog - Latest news about EEG & Brain Stimulation

# data[].attributes.attachment_link.readable_text
In the previous post 5 Basic Guidelines to Carry Out a Proper EEG Recording Experiment Alejandro Riera explained how to perform a good EEG recording, with useful tips and common mistakes to avoid. Let's say you followed the advices, and you already have a good EEG recorded. What now? Well, if you have experience with EEG, you'll probably want to visualise the data you recorded. Or maybe even go one step further and analyse it. Perfect, that sounds like a good plan... but how? What tools should we use?

EEG software

Today we'll try to go over the different options you have, both for visualizing and for analyzing your EEG data.

Disclaimer note: This is only a brief overview covering the software we commonly use. This post intends to be collaborative, so do not hesitate to contribute to it through your comments!

The first thing you may want to do once you finished recording your EEG data, or maybe even in between different recordings, is to visualize your data. This will enable you to visually inspect possible problems with your setup, identify artifacts like eye-blinks, or even identify artifacts from external devices. If you're experienced, you may even be able to spot some event-related potentials on your signal, or make an estimation of the power of the signal in low frequency bands (like alpha).

Besides the proprietary applications that many commercial EEG kits bundle (like Neuroelectrics Instrument Controller, NIC, bundled with Enobio and Starstim), there are some other options of software available that you can use to visualize EEG data.

The EDF browser supports a wide range of common EEG file-formats as input, and converts them to EDF. It offers a graphic visualization of the signal, as well as an integrated list of trigger marks present in the file. It also provides filtering functionalities, power on the frequency bands computation, as well as the possibility of down-sampling your signal. An interesting capability is that it offers the possibility to load a streaming file, so if the software bundled with your EEG package doesn't provide any monitoring software (on-line visualization), you can use this one to monitor the signal while recording it.

EEGLab "is an interactive Matlab toolbox for processing continuous and event-related EEG (...) data". Besides being a processing data toolbox, it also provides visualization functionalities, both in signal plotting form for the time domain, or in a graphical-scalp drawing for the activation domain.

Biosig is another large toolbox for Matlab (and Octave) that offers a vizualisation tool.

Bioelectromagnetism is a "toolbox [that] has been developed to facilitate quick and easy import, visualization and measurement for ERP data." It is specially indicated for event-related data, and is able to import/export file-formats that other software can't (.avg, .eeg, .cnt, .tri, .3dd).

There are other more specific software like , "an open source software for 3D visualization" providing graphical-scalp drawing for the activation domain, or EEG-Visualisation, implementing different methodologies for EEG visualization (see the webpage and the linked scientific publication there for more details).

Photo credits: Patrick.kramer and MrSandman

But visualization is only the first step to take with your data. In order to work with your data and get your results, you'll need to analyze it to detect event-related potentials, perform a time-frequency analysis, or extract some features from the signal to be used later. There is a wide range of available software, but we want to cover here the most transversal ones that we know, in the sense that it's software that can be used in a wide range of applications.

, of course, is a powerful tool, especially with the signal processing toolbox. Many functionalities that you may need (computation of power bands on frequency domains, detection of event-related potentials, filtering of data, feature extraction, classification, etc.) can be developed using the framework of the processing toolbox. As usual, is also suitable for a lot of the work that can be developed under Matlab, with the advantage of being open source.

If Matlab provides you the basic tools to develop, EEGLab is an open source package that already implements a vast range of different functionalities under Matlab that are commonly (and not so much) used while analyzing and processing EEG data: semi-automatic artifact removal, filtering, independent component analysis (ICA), time/frequency transforms, feature extraction, etc.

Biosig, as we mentioned earlier, is another Matlab (and Octave) complete toolbox that provides filtering, feature extraction and classification functionalities.

EEG-analysis-toolbox is a "MATLAB-based toolbox for exploratory analysis of EEG data. It supports both univariate analysis and multivariate pattern analysis, and can process large amounts of data in parallel."

Photo credits: Patrick.kramer and MrSandman

But if you don't want or can't use Matlab or Octave and you need to use a programming language, there are also software packages available that you can use to analyse EEG data in python.

PyEEG is a Python module to extract EEG features that was initially developed for epilepsy detection, and is being upgraded. It is especially interesting for the re-projection and decomposing functionalities that it offers.

Last but not least, we would like to ask you: What software do you use for EEG analysis and which would you suggest to others? Again, this post intends to be collaborative, so don't hesitate to contribute to it through your comments!

# data[].attributes.attachment_link.authors[].name
View all posts by Anton Albajes-Eizagirre

# data[].attributes.attachment_link.title
What software do I use for EEG analysis? - Neuroelectrics Neuroelectrics Blog - Latest news about EEG & Brain Stimulation

# data[].attributes.attachment_link.description
In the previous post 5 Basic Guidelines to Carry Out a Proper EEG Recording Experiment Alejandro Riera explained how to perform a good EEG recording, with useful tips and common mistakes to avoid. Let's say you followed the advices, and you already have a good EEG recorded. What now?

# data[].attributes.body
BCI++ is a framework dedicated to the development and fast prototyping of Brain-Computer Interface systems

# data[].attributes.body
Open Source Matlab Toolbox for Brain-Computer Interface research.

# data[].attributes.attachment_link.readable_text
Open Source Matlab Toolbox for Brain-Computer Interface research.

Download the code from ftp://sccn.ucsd.edu/pub/bcilab.

Extract the file to some folder that is not your EEGLAB folder. Start MATLAB (2008a+ required for the GUI), and reset you path to default settings by clicking File / Set Path / Default, and then Save. If you have misc toolboxes in your path, you run the risk of creating unexpected errors (due to name conflicts), but you can add your directories back later once you know what outputs to expect. Enter in MATLAB's command line:

You should now be getting a menu in the upper left corner of the screen. For BCI newcomers, it is highly recommended to watch the BCI introduction video (from the EEGLAB workshop 2010) before diving into the GUI. It is found at: http://thesciencenetwork.org/programs/12th-eeglab-workshop/eeg-classification-and-cross-validation-using-the-bcilab-toolbox-overview Once you are familiar with the BCI principles, please follow the extended practicum slides from ftp://sccn.ucsd.edu/pub/bcilab to get familiar with the GUI. The rest of this page gives a more in-depth background on the toolbox use, organization, and especially on working with the script and plugin interfaces.

Important notes: The data sets that the practicum slides refer to were only distributed for use in workshops; instead, we now have alternative data sets packaged with the toolbox. The tutorials are essentially the same, except for the different files to use (and different marker names). The updated file names are userdata/tutorial/imag_movements/calib/DanielS001R01.dat for imagined movements training, userdata/tutorial/imag_movements/feedback/DanielS001R01.dat for testing, and userdata/tutorial/flanker_task/12-08-001_ERN.vhdr for the error perception data set. The second difference are the marker types that need to be specified: they are {'StimulusCode_2','StimulusCode_3'} instead of {'S 1','S 2'} for imagined movements, and { {'S101','S102'},{'S201','S202'} } instead of {'S 11',{'S 12','S 13'} } for the error perception. Also, the feedback session in the imag_movements1 directory contains no labels - therefore it is not possible to apply a model to it and get error rates ("Apply model to data"). Real-time playback is possible, however. The slides will be updated at the next opportunity to reflect these changes.

You need at least ~2.5gb of free memory to be able to run all tutorials. If you have Windows Vista and many gadgets etc. installed, you may run into memory issues under 32-bit Windows, as the data sets are quite large.

BCILAB is a MATLAB toolbox and EEGLAB plugin for the design, prototyping, testing, experimentation with, and evaluation of Brain-Computer Interfaces (BCIs), and other systems in the same computational framework. The toolbox has been developed by C. Kothe at the Swartz Center, inspired by the preceding PhyPA BCI toolbox created by C. Kothe and T. Zander at the Chair for Human-Machine Systems, Berlin Institute of Technology.

A Brain-Computer Interface is, most generally, a system which receives biosignals measured from a person and which predicts from these (in real time) some aspect of the person's cognitive state.

The most important case is the clinical BCI, developed for tetraplegic or locked-in patients (who have lost some or all their muscular control) in order to control devices [orig-def], such as wheelchairs or spellers. [wheelchair/speller] In these, the input is the Electroencephalogram (EEG) or some other direct measure of brain activity, and the output is taken as a control signal. In the most commonplace settings, control is exerted by means of imagining limb movements which are translated into movements of a virtual cursor ("motor imagery BCI"), or by attending to letters in an on-screen letter matrix in which rows and columns are flashed at random ("P300 speller"). Various other designs have been proposed, such as spellers controlled by attending to directional sound cues. [audiospeller]

Besides the clinical context, BCI technology can be used to control Human-Computer interfaces via brain activity alone -- in principle allowing for hands-free operation [HCII]. An even more practically relevant use case is the assessment of aspects of user state "in the background", i.e., without requiring voluntary control commands by the operator. Instead, a spectrum of user state can be passively tracked, such as the level of arousal, the level of some aspect of cognitive load, the probability of being surprised, or of perceiving some event as an error, and so on. [Tan/Halo, us/Error] The idea is that this kind of information, when made accessible to applications, can allow for a better (e.g., higher-bandwidth) Human-Computer Interaction, perhaps approaching that of Human-to-Human interaction. [BCI+HCI] For example, if software in a multi-screen workplace can determine which of the information it presented was likely missed by an operator, it could subsequently re-display that information, potentially preventing costly user errors.

Lastly, since BCI technology comes with an ability to derive latent information from highly complex and noisy brain-/biosignals, it can be applied as a science tool, for the purposes of pattern recognitition and analysis, structure and novelty discovery, and other data analysis tasks. Here, the analysis tools would be used on previously recorded data sets, just like any other tool in EEGLAB. This approach is quite new to the EEG field, but is becoming a staple of fMRI analysis, there often called multivariate pattern analysis (MVPA). [ref] This methodology allows to integrate multiple weak information sources (such as multiple channels of EEG) to derive strong statistical statements from them and guide the search for (or validate) scientific hypotheses.

BCILAB aims at facilitating and accelerating research in these areas, and supplies tools that simplify all aspects of Brain-Computer Interface research, from design to field testing, and from clinical applications to the general HCI context. We hope that BCILAB is useful for students, experimental scientists, engineers and developers alike. For these reasons, the toolbox offers multiple different interfaces which link to the same backend functionality, including a GUI, scripting support (MATLAB-based), APIs for real-time processing, and a variety of extension component interfaces. MATLAB programming is not strictly necessary, as most BCILAB features can be accessed from the GUI, although it is required for batch scripting and custom extensions. The strength of MATLAB-based software lies in its resources for leading-edge scientific computing, as well as in the good support for rapid prototyping, but BCI systems developed in it can be used for real-time out-of-lab experimentation, and can in principle be deployed without the need for a MATLAB license. However, due to the complexity and overhead of the MATLAB environment, the system is best used as a research platform, and not as a product development environment -- end-user software is ideally re-implemented in a compiled language, after a suitable approach has been identified and extensively tested. The process of identifying and testing an approach involves more than just computation, but also data exploration and investigation - an area which is helped by the deep integration with the EEGLAB platform. In the future, this integration will be further strengthened, bringing rich statistical learning and signal processing into routine EEG analysis workflows.

Brain-Computer Interfacing is fundamentally an inference problem: the task is to infer, from observed data (for example, a person's EEG), the value or distribution of some latent variable (e.g., the person's movement intent), usually in real time. This inferential step, however, cannot be done without additional information about the relation between the two regimes. Depending on assumptions imposed, different approaches follow (e.g., relying on oscillatory idle processes of the brain, or on slow-changing cortical potentials), but the bulk of the required information are highly person-specific details, which are themselves hard to obtain (e.g., rooted in physiology and functional allocation within the brain). Obtaining this information amounts to a second inference problem - inferring the optimal parameter settings of the BCI on the basis of data at hand. The (by far) most relevant data to compute these parameters is example data: simultaneous recordings of both the biosignals (such as EEG) serving as source data, as well as the variables to be predicted (= estimated) from them (e.g., level of user workload). From these data, a predictive model can be computed (encompassing the individualized parameters), which can then make new predictions based on raw data. A highly recommended introduction to the principles and concrete technology behind BCIs is given in the EEGLAB Workshop 2010 Talk and associated Slides. [ref]

Standard analyses. As the optimal learned parameters vary with cap montage, time of day, medication and various other factors, the best results are obtained by recording example data (usually called training data, or calibration data) immediately before the experiment in which the system is put to the test; thus, a typical BCI experiment consists of at least two subsequent sessions: the "training" session and the "test" session. Both can be set up as standard psychological experiments, where in the training session the variable to be predicted must be known (via instructions and/or stimuli in the experimental design), so that a predictive model can be computed from it. In the test session, these quantities will be predicted by the BCI. The prediction can be done in real time ("online analysis"), and can be made accessible to the user/subject, thus forming a closed-loop system, or in a post-hoc analysis of the recorded data ("offline analysis").

Advanced analyses. Accurate predictions are harder to obtain if the test session is recorded with a different cap montage or on a different day than the training session, but the ability to use BCIs without the need for a per-session calibration is critical for many HCI use cases. Therefore, research is ongoing to improve this session-to-session transfer, e.g., by integrating multiple calibration data sets across persons, sessions and/or tasks to learn predictive models that generalize well across these boundaries. For example, a joint predictive model may be computed from the pooled data of a multi-subject study, and its performance with no (or minimal) individualization can be evaluated in a subsequent study with different subjects. In future iterations, BCILAB will add facilities to streamline this type of analysis, as well. At this point, it requires advanced MATLAB programming.

Cross-validation analysis. The simplest experimental settings are studies comprising a single session per subject (e.g., a standard psychological experiment). BCI performance on this type of data can be assessed via cross-validation, a mode of analysis in which a recording is partitioned into multiple sections (e.g., k=10), and all but one are used to learn a predictive model, which is then applied on the held-out section (where its outputs are compared to the expected/known value of the latent variable to obtain accuracy scores). This procedure is repeated with each section held out once (and training being done on the remaining sections).

Neuroscience questions. Under some considerations, the internal structure of predictive models learned from data can be investigated and yield insights. For example, the relative weighting of different sensor channels, time points, brain territories, spectrum portions, etc. can give insight into the underlying processes that relate to a particular aspect of cognitive state. Thus, BCI technology may be applied to answer questions about the most likely expression of certain underlying brain processes. These applications are, however, only in their infancy.

Most of BCILAB's functionality is contained in (plugin) components, of which there are five types. Most plugin types reside in their own directory and are automatically identified and loaded by BCILAB.

Signal Processing. Signal processing components are implemented as single MATLAB functions that translate input signals into output signals; they can be adaptive or static, linear or non-linear, causal or non-causal, they can operate both in real time or offline, and on continuous or epoched data -- thus they can implement arbitrary processing, as long as the inputs and outputs are both signals. Signals are represented as extended EEGLAB datasets. The majority of signal processing components serve to filter the input signals (e.g., spatially, spectrally, or in time), thereby discarding unwanted information and "amplifying" information of interest, i.e., improving the signal/noise ratio of the data. Other filters may implement more specialized processing, such re-representing the data in a more interpretable basis (ICA, sparse reconstruction, or the Fourier transform). [picture] Most signal processing components reside in code/filters and some are in code/dataset_editing.

Feature Extraction. Feature extraction components take off where signal processing ends; they accept epoched or continuous signals and output sequences of feature vectors, thereby transforming segments of data into some abstract domain (referred to as the feature space). Feature extraction often simplifies the data and can drastically reduce its dimensionality. The processing may be static or adaptive, and, if adaptive, it frequently uses information about the value of the variables to be predicted (called supervised learning). Typical algorithm choices are certain simple mathematical transformations (e.g., PCA, wavelet decomposition, etc), or in other cases, the data is transformed into a space which is more amenable to interpretation and robust association (e.g., if it is neurophysiologically meaningful). [picture] Feature extraction functions are frequently contained in the BCI Paradigm components that use them.

Machine Learning. Machine learning components come in two parts, one to learn a predictive model from some data, and the other to apply a previously learned model to data, in order to make predictions. The learning function ultimately summarizes the data (the pre-processed example data gathered in the calibration session), for example its structure (in what is known as unsupervised learning) or the relationship between observed and latent variables (in supervised learning) under some implementation-specific assumptions. It learns from a set of feature vectors as produced by the feature extraction stage, as well as usually their associated target values (i.e., desired predictions, if known by the design of the calibration experiment) and produces a MATLAB structure which encodes the learned model. The prediction function takes that model and a set of feature vectors and outputs the estimated target value for each vector. Target values are often referred to as labels in the machine learning literature. All machine learning components reside in code/machine_learning.

BCI Paradigms. BCI paradigm components are MATLAB functions that tie together all stages of a BCI approach, including any signal processing, feature extraction, machine learning functions, as well as their default parameters or allowed parameter ranges. They do not nececssarily need to be implemented in terms of these stages, however; they can do completely arbitrary processing of their input datasets. Thus, BCI paradigms codify the entire computational approach, including learning of a model from a dataset (or collection of datasets), as well as prediction, given a dataset or given real-time data. In addition, they may support visualization of their learned models. Most BCI paradigms are heavily customizable implementations of common standard BCI approaches. These components reside in code/paradigms.

Online Plugins. Online plugins are MATLAB functions that link certain hardware and drivers to BCILAB's processing facilities. There are three types of online plugins: Input plugins, which receive data from a source and provide it to BCILAB, output plugins, which receive processed data from BCILAB and output the result over some interface, and input/output ("processing") plugins, which handle both input and output via some interface, and do the intermediate processing through BCILAB.

Framework. In addition to the plugins, there is common low-level infrastructure which makes various functionality available to the plugins, such as distributed cluster computation, disk caching of intermediate results, or a platform-independent file interface. Lastly, the toolbox has high-level facilities that offer functionality on top of the plugins. These handle the design and customization of BCI approaches, the learning, offline/online application, evalution and visualization of predictive models, as well as the user and application programming interfaces to these (i.e., the GUI, script language, as well as the processing API).

GUI. The graphical user interface of BCILAB supports almost all functionality provided by the toolbox, and reflects all parameters of every plugin. As most of the BCI paradigms have reasonable default parameters, working BCI systems can be set up with very little customization -- but if necessary, every setting can be changed through the GUI. Offline analysis, including prototyping, performance analysis and visualization, as well as online processing can be done via the GUI. The GUI functions reside in code/gui.

Scripting. The scripting system gives access to all functionality of BCILAB. It consists of an offline scripting language (learning and application / evaluation of predictive models, visualization) and an online scripting language (feeding chunks of raw data into BCILAB, and getting results out of BCILAB in real time). The respective facilities reside in code/offline_analysis, code/online_analysis, with additional tools in code/dataset_editing.

Plugins. The plugin authoring interface consists of the utilities and contracts provided to implement BCILAB plugins, see also the plugin authoring guides for more information. Since all plugin types (except for feature extraction) need to be accessible from the GUI, a subsystem for the GUI-friendly declaration of function arguments is provided in code/arguments, used by all of these plugins. For the definition of signal processing plugins, a (trivial) contract needs to be followed by the user, supported by two functions in code/expressions. Machine learning functions, BCI paradigms, and online plugins have specific interface contracts, as well, and additional helper tools exist to simplify the definition of the respective functionality, found in code/helpers.

The toolbox core is structured into several layers and groups of related functions, which will be explained from bottom to top in the following. [picture]

Dependencies. BCILAB ships with a set of externally maintained dependencies. Some of these had been minimally modified; see the respective readme file in each sub-directory for details. Dependencies are automatically loaded, and added to the MATLAB path by BCILAB's startup script (controlled by marker files env_add.m / env_exec.m in the respective dependency folders).

Miscellaneous functions. BCILAB contains several groups of miscellaneous functions. This includes convenience keywords (code/keywords -- note: the capital-letter keywords should currently not be used), useful additions to the MATLAB language (code/misc), as well as "query" functions to tell different BCILAB data structures apart (code/queries).

Helpers. Helper functions (code/helpers) implement compact stand-alone functionality and can be used without the rest of the toolbox (though they may depend on other helpers, and possibly some keywords). Among others, distributed computation, data fingerprinting, function memoization, directory traversing, as well as a few useful MATLAB hacks are provided.

Utility functions. Utility functions (code/utils) are more complex and interwoven functions than helpers; as their functionality is strongly tied to the toolbox architecture, they are only useful to BCILAB experts. Some core functionality used by the GUI functions, etc., is implemented in these (such as cross-validation and parameter search).

Argument sub-system. BCILAB contains a sub-system of functions (code/arguments) to declare function arguments in a way that allows these functions to be displayed in a GUI. Among others, they allow to auto-generate dialog windows for user functions, or display their parameters in a property grid widget. All plugins (except for feature extractors) use the argument sub-system to declare their arguments.

Expression sub-system. A small sub-system for the construction of algebraic expressions (code/expressions), their manipulation (in the style of Mathematica) and their lazy evaluation is included with BCILAB. Signal processing plugins follow are contract that makes them compatible with this framework, which allows the BCILAB framework functions to do heavy manipulation of user-defined signal processing chains (e.g., reordering, caching of intermediate results, or piecewise online execution).

Input/Output functions. Functions to load/save data sets in a variety of formats (containing time series data, such as EEG), as well as generic MATLAB variables. Found in code/io.

Dataset editing plugins. Dataset editing (code/dataset_editing) functions are Signal Processing plugins which do not primarily transform the signal contents but rather the meta-data of the data sets (e.g. marker annotations, channel names, etc.). Their use in scripts is occasionally necessary (concatenating datasets, changing event markers, etc.)

Signal Processing plugins. Signal processing plugins (code/filters) transform data sets, and particularly the signals stored in them. See Functionality:Signal Processing. These functions are only rarely invoked directly by users -- instead, they are used as part of a data processing pipeline, which is configured via BCILAB's high-level prototyping tools and then executed by high-level processing tools. A special signal processing plugin, which sits on top of all the others, is flt_pipeline; this function allows to apply any subset of signal processing functions in sequence (with automatic ordering).

Machine Learning plugins. Like signal processing plugins, these functions (code/machine_learning) are rarely invoked directly (although they can be used without the rest of BCILAB, as long as the respective dependencies are properly loaded). Instead, they are used as part of a processing pipeline, configured and executed via GUI, scripts and/or programming APIs. A special machine learning plugin is ml_train/ml_predict; these functions dispatch to one of the user-supplied signal processing functions.

BCI Paradigm plugins. BCI paradigms (code/paradigms) make use of signal processing, machine learning, feature extraction and dataset editing functions, and are therefore a layer above these other plugins. These functions are exclusively ran by the framework, and not by the user. A special paradigm function is para_dataflow, which allows to set up a sequence of signal processing steps, feature extraction and machine learning as a processing chain; most (but not all) other paradigms use para_dataflow with appropriate parameters to implement such a three-stage design.

Offline analysis tools. BCILAB currently contains four core functions for offline (i.e., post-hoc) analysis of recorded data (code/offline_analysis). The most important function is bci_train, which learns ("trains") predictive models from user-supplied calibration datasets, estimates their likely predictive performance (online / real time) on new data, and can also search for optimal parameters within certain ranges. The function bci_predict applies predictive models to previously recorded data sets to obtain cognitive state estimates. Models can also be visualized, using bci_visualize. The function bci_preproc is a specialty function which allows to partially pre-process previously recorded data according to some BCI paradigm or predictive model, in order to analyze and explore the result in EEGLAB or other tools. These functions make use of BCI paradigms (customizing them, running them, etc).

Online analysis facilities. Online analysis (code/online_analysis) involves receiving raw signal chunks in real time from external sources, feeding them through a (previously loaded) predictive model, and obtaining the output estimates for the most recent signal time point. This is handled by a small language of scriptable functions, onl_newstream / onl_append / onl_clear to manage streams of raw data (create, update, clear), onl_newpredictor / onl_predict to load and invoke predictive models on raw data streams, and optionally onl_simulate to test the online processing pipeline on a previously loaded dataset. These functions can not only be used in user scripts, but they are also the basis which is used to implement online plugins.

Online processing plugins. These user-defined functions (code/online_plugins) allow to link external hard/software to BCILAB for the purpose of real-time data processing. They are implemented in terms of online analysis facilities (which in turn invoke BCI paradigms, which invoke machine learning, signal processing, and feature extraction functions, etc.).

Graphical User Interface. The GUI (code/gui) functions sit on top of all other facilities. It is organized into IO, offline analysis (with approach design, model learning & evaluation, visualization, and model testing), and online analysis (loading of predictive models, real-time input / output via certain supported interfaces).

Environment support. The environment functions (code/environment) bring up the BCILAB environment from the MATLAB command line (env_startup), load its dependencies, and set any global variables (such as default directories for data, etc.). The function env_showmenu opens the BCILAB main menu, and some others manage directory / file name translation and error handling.

Data structures. The main data structure used by the toolbox is the data set, which is an extension of the EEGLAB data set format (->REF). A data set encapsulates a multi-channel time series, together with meta-data. The time series data may come from different types of sensors (such as EEG, EMG, EOG), but has a uniform sampling rate. EEGLAB's standard meta-data involves time information (e.g., sampling rate), channel information (e.g., channel labels), dataset information (e.g., subject name), event marker information (e.g., event types & latencies), possibly epoch information, internal bookkeeping data, as well as some domain-specific data (e.g., a decomposition into independent components). BCILAB adds the tracking field (for internal tracking), as well as the target field as a field of EEGLAB's epoch sub-structure. The target field is critical, as it stores information about the cognitive state to be predicted for a given segment of sensor data. In future iterations, BCILAB will standardize the format of dataset collections (possibly adopting EEGLAB's STUDY data structure). Additional data structures include the predictive models learned by BCI paradigm plugins as well as machine learning plugins - these are, however, largely user-defined (except for another tracking field that is automatically added to model structures).

Top-level directories. The resources directory contains resource files (e.g., channel locations), as well as user-supplied approaches, workspaces, documentation, and test cases. The userscripts directory contains user-written scripts.The userdata directory contains data as needed by user scripts, but preferably not entire studies (as this makes copying the BCILAB folder tedious). The root folder contains the startup scripts, as well as the bcilab configuration file.

The standard data flow inside BCILAB is best explained by working backwards from the outputs to the inputs. The desired output of any BCI is a real-time measure of an aspect of a person's cognitive state: this may be a real number (e.g., an index of the user's working-memory load), a categorial value (e.g., the most likely type of movement imagined), a probability (e.g., the probability of being surprised), or a probability distribution (e.g., the area of the person's auditory attention focus).

The computation of this value is periodically scheduled by a running online (output) plugin of the toolbox (e.g. in a loop or via a timer) or a script, and then forwarded by it to an external destination. This code requests an estimate from the online prediction function of the toolbox (onl_predict), part of the online analysis interface, which in turn obtains the most recent data from any input data streams to which it has been linked and then pipes the new data through the signal processing of the (loaded) predictive model to pre-process it. The input data streams used by onl_predict are usually updated independently, e.g., scheduled by some other online plugin interfacing to an external source (and updated via the function onl_append).

While sending the data through the signal processing chain, onl_predict distinguishes between stateful, stateless and epoch-based signal processing plugins, and passes appropriate signal portions to each of the functions. Additional parameters to these functions are held in the predictive model, and can be defined by the signal processing function. Once up-to-date pre-processed data is available, onl_predict takes the most recent segment of the processed data and delegates any further calculation to the prediction function of its loaded predictive model.

This model's prediction function then maps the data segment onto the output value. The implemented mapping is completely up to the respective BCI paradigm, but most paradigms use para_dataflow to send the input data through a feature extraction plugin, followed by a machine learning plugin. The feature extraction function takes the data segment and maps it onto a feature vector (which can be viewed as a point in a high-dimensional space). This feature vector is then sent through the prediction function of the respective machine learning plugin and mapped onto the final output value (both stages depending on parameters previously learned from calibration data).

[picture: processing?]

More generally, the recording of user-specific calibration data, learning of predictive models from them, and application of these models in online processing is also a part of the data flow. Details of the learning process can be involved, but in most (current) designs, the raw data is sent through the same sequence of processing stages as online, whereas each stage has access to the desired outputs (the target labels, if available) and may adapt itself based on this information before passing the data on. Also, because typically the entire recording is available by the time the learning is done, its processing does not have to be causal. Any additional piece of information on which the outputs depend (e.g., MR images when doing advanced source localization) are also part of the data flow of BCILAB.

System Requirements. BCILAB requires MATLAB 2008a+ (with support back to MATLAB 7.1 in the works for the non-GUI parts), and a Windows / Linux / Mac computer with at least 1GB of memory. For fast online processing or advanced offline analysis, a 1 GHz processor or faster is required, and multiple cores are recommended. As a very important consideration, the MATLAB path should be pristine, i.e. it ideally contains only MATLAB toolboxes and as little extra material as possible, since clutter in the path can lead to unexpected errors (this can be achieved by clicking File / Set Path ... / Default, and then Save). Also, the BCILAB directory itself should NOT be added to the path.

Obtaining the code. Current BCILAB releases (including betas) can be downloaded from ftp://sccn.ucsd.edu/pub/bcilab. The packages contain a single directory and can be unpacked in any place (however, if BCILAB is placed inside an EEGLAB folder, special considerations apply, as the toolbox is then loaded in plugin mode -- for now, it is better to run BCILAB in standalone mode).

Setup and Startup. The toolbox is loaded by moving into the BCILAB directory (via the MATLAB command cd your/path/to/bcilab, or the directory picker in MATLAB's GUI, and then entering startup at the command line. If the command line is not visible, it can be enabled via Desktop / Command Window. The startup script automatically loads all dependency modules (including EEGLAB), and uses the variables specified in the file bcilab_config.m as default configuration parameters. These parameters can be changed to customize the BCILAB setup - see code/environment/env_startup for a description of the configuration parameters. In particular, the directory in which studies are located (the 'data' directory) may be adapted.

For a GUI walkthrough with example data, see the extended Practicum slides at ftp://sccn.ucsd.edu/pub/bcilab. The GUI tools are split into data sources, offline analysis and online analyis. The data sources menu allows to select recordings for further analysis. Offline analysis allows to design computational approaches (specializations of standard or user-defined BCI paradigms), learn predictive models from recordings (according to a previously defined computational approach), evaluate their estimated performances, and visualize aspects of their structure. The online analysis menu allows to load predictive models for real-time use, and link external sources (such as EEG amplifiers) and destinations (such as stimulus presentation software) with loaded predictive models for online processing.

Naming things. Most of the steps that are offered by the GUI produce some data item (e.g., a model, a dataset, or a result), and in general these data items are assigned names and stored as variables in the MATLAB workspace. The MATLAB workspace is a collection of objects of various types, and it can be viewed by checking, in the MATLAB menu, the item Desktop / Workspace. The default names proposed by BCILAB for storing things are lastmodel, lastresult, lastdata, etc., but custom names can be given. When a subsequent processing step depends on an item of one of these types, the one called 'last***' (if any) is usually proposed by BCILAB as the default choice.

Saving things. All data items produced in a BCILAB session can be saved for later reuse. The easiest way is to save the entire workspace (note to EEGLAB experts: BCILAB usually only keeps references to datasets in its workspace, which take up very little space), but various GUI dialogs include a dedicated "Save" button to save a computational approach, a model, etc. These items are by default stored in subdiretories of resources. Things can also be saved and loaded with MATLABs load and save commands; type help load or help save in the command line for details.

Writing scripts in BCILAB is relatively straight-forward and rarely requires more than 3-10 lines of code for standard analyses. It allows to automate entire workflows (e.g., load a dataset, define an approach, learn a model from the data and estimate performances, visualize model properties, save the model for later use or load a model for real-time use, connect to an EEG amplifier, connect to a simulus presentation software, run), which is essential for reproducibility and can greatly boosts productivity, especially in batch analyses. Most importantly, it allows to do custom dataset formatting (see also EEGLAB scripting wiki), and to define custom analysis modules that fit seamlessly into the BCILAB pipeline.

It is highly recommended to first proceed through the GUI example (REF) before going through the scripting guide, to get an quick initial overview of the provided functionality. We also strongly recommend working through the MATLAB "Getting Started" help file, which contains invaluable knowledge, of which the essentials can be picked up in as little as an hour. It is accessible from the main menu via Help / Product Help / MATLAB / Getting Started.

A basic script is a sequence of commands that operate on the contents of the MATLAB workspace, may invoke built-in or user-defined functions, and/or interact with any hardware connected to the computer. Commands may create or overwrite (or, if desired, remove) variables, such as data sets, models, results, data streams, or other MATLAB data structures (arrays, etc.). Whenever MATLAB is first started, BCILAB must be loaded by entering the appropriate directory, and then invoking the startup command in it. This is best done in the MATLAB command line (in a script it would lead to the toolbox being reloaded whenever the script is executed).

A new script is created by selecting File / New... / Script in the MATLAB main menu (not the BCILAB menu), and then saving it under some name via File / Save As.... Scripts are by default saved in the current folder, which is set to your/path/to/bcilab/userscripts after BCILAB has been loaded. It is good practice to prefix script names (e.g., with 'do_') to avoid name conflicts with functions used by the toolbox or other MATLAB code. The same lines that can be written in a script can also be entered in the MATLAB command line to get instant feedback. Running a script is in fact equivalent to typing its contents into the command line.

The first step in any analysis would be to learn a predictive model from calibration data, and to estimate/evaluate its accuracy. The standard function to load datasets from disk is io_loadset, which takes a file path and some optional arguments. The file path can be an operating system specific path, such as 'C:\Projects\bcilab-0.9\userdata\test\imag.vhdr' on a particular Windows installation, or a platform-independent path, such as 'bcilab:/userdata/test/imag.vhdr' (where bcilab:/ refers to the BCILAB base directory). It is generally recommended to use the platform-independent version, as the same script is then almost guaranteed to work on different machines, installations and operating systems. Other base directories include data:/, temp:/ and store:/. The defaults for these directories can be set in the file bcilab_config.m. The result shall be stored in the variable 'mytrainset'.
Note: if this dataset is not in your distribution, you may download it here and put it in the userdata folder of BCILAB
A data set, as loaded by io_loadset holds some biosignal, which may or may not include additional annotations, such as event markers. Datasets to be used for calibrating predictive models typically require that event markers are present to indicate the type of user state that is expected (in accordance with the experimental design) at certain time points. The learned model would then likely produce a corresponding output when fed this or a similar piece of raw data (note that the output is usually not the exact marker id used, but more flexible). As the entire data processing must take place inside BCILAB (or else it could not reproduce the results online / on new data), the data to start with should always be continuous (i.e. not epoched).

The loaded dataset contains the EEG of a person who was imagining different types of hand movements for 20 minutes. A stimulus presentation software presented an instruction every 7.5 seconds, which was either the letter "L" or "R", and the user was instructed to imagine either a certain left-hand movement or a right-hand movement. The goal in the subsequent analysis is to learn from these data (and the respective stimulus event markers) how to estimate the type of hand movement that the user is imagining from his raw EEG. This knowledge will be distilled into a predictive model, which can then be applied to datasets (giving a time course) or in real time (e.g., to control a cursor).

The most important distinction (and possible stumbling block) between EEGLAB's functions at the signal level and BCILAB's is that the former ones immediately compute and return the requested result (i.e., they evaluate "eagerly"), whereas BCILAB's functions by default only return a data structure that can subsequently be evaluated (by the user or by the BCILAB framework) to get that result (i.e., they evaluate "lazily"). This data structure (an "expression") only captures what has to be done in order to get the result. Only when the contents of a result are to be manually processed or inspected by the user script, it is necessary evaluate it -- in other cases, BCILAB makes sure that it data that it actually needs is obtained fast as possible (e.g., it may skip an intermediate step if it knows the outcome already, or it may store intermediate results to disk for later retrieval). The function which turns an expression into a value (e.g. a dataset) is called exp_eval. For example, the previous result can be obtained by the command: mytrainsetnew = exp_eval(mytrainset) which then assigns the corresponding EEGLAB dataset to the variable mytrainsetnew.

The next step is to specify the computational approach that should be used to learn a predictive model, and thereby, which assumptions should be made while learning that model. For example, one might assume that the relevant contents of the raw signal (for the purpose of making the desired estimates) are primarily its oscillatory properties, which is usually the case if neural idle rhythms correlate to the cognitive state of interest. Alternatively, one might assume that certain slow-changing cortical potentials relate to the user state of interest in a way that can be exploited for predicting that user state. These assumptions are expressed in the chosen algorithms and their parameters.

A convenient way to specify an approach is to reuse one that is known to work under similar conditions, and to customize it as necessary. BCILAB contains a collection of "reference" approaches, many of which have been used in many different scenarios, and most of which are customizable beyond recognition. These are called "BCI paradigms" in BCILAB. In addition, the user can save their own approaches (i.e., customizations of these paradigms) and use these as starting points for later designs, or define their own paradigms. Customization of an approach in many cases comes down to setting particular parameters, such as the set of sensors to be used, or the frequency bands of interest, but it may also involve replacing particular components (e.g. exchange one type of machine learning component by another one) and their parameters.

In the following, a new approach will be designed based on the CSP (Common Spatial Patterns) paradigm (file paradigms/para_csp), with one of its default parameters replaced by a new value. CSP is a fast and powerful method for learning and exploiting spatial patterns in the expression of oscillatory processes in the brain (in the context of imagined movements, these processes are an effect of Event-Related Synchronization / Desynchronization, ERD/ERS). As there may be many different types of event markers in the data set, it is necessary to specify which ones indicate that a left/hand movement imagination happens in their proximity.

In this case, the process of interest takes place after each stimulus event 'S 1' (for left) and 'S 2' (for right), respectively. Note: there are 2 spaces between the S and the number. These are standard marker types assigned by BrainProducts recording software, indicating Stimulus Type #1 and Stimulus Type #2. The parameter that needs to be changed to accomodate for this is called EventTypes, and it belongs to the EpochExtraction group of parameters (as it controls which segments / epochs of the data are extracted for further processing), which in turn is part of the SignalProcessing group of parameters (as this processing is implemented as a signal processing module in BCILAB). In the GUI's approach review panel, the respective parameter is found in SignalProcessing / EpochExtraction / EventTypes.

The following material assumes basic familiarity with the MATLAB language (and its data structures, such as cell arrays); these can be read up in the MATLAB help. A BCILAB convention is that a list of parameter assignments should be expressed as {'name1',value1, 'name2', value2, ...} - also called name-value pairs. In the previous assignment, {'S 1','S 2'} is a list of marker names, and {'EventTypes',{'S 1','S 2'} } is a list of parameter assignments (here for one parameter). The expression 'SignalProcessing',{'EpochExtraction',{'EventTypes',{'S 1','S 2'} }} is another parameter specification, here specifying the group of parameters that is to be assigned to the SignalProcessing parameter of the BCI paradigm.

Finally, approaches are declared as a cell array that has the paradigm name (here 'CSP') as its first entry, followed by parameter assignments. Thus, approach declarations are always of the form approachname = {'paradigmname', 'param1',value1, 'param2', value2, ...}. The main parameters of this paradigm itself are SignalProcessing, FeatureExtraction, MachineLearning, and all others are sub-parameters of these. All parameters have defaults, which apply if not explicitly overridden. The approach review panel in the GUI (see GUI walkthrough) gives an good overview of the complete hierarchy of parameters for any paradigm and approach, as well as their default values.

It is possible to specify parameters with short forms (for experts), which can be found in the respective functions. For example, code/paradigms/para_dataflow.m defines both the 'SignalProcessing' argument as well as its 'flt' alias. MATLAB provides a search tool (in the bottom-left corner under Start / Find Files...), which can be used to search for such aliases in the code directory (and sub-directories). The short form for the previous command is:

Predictive models are learned via the function bci_train, which expects the data, as well as the approach to be used as arguments. This function does not learn just a predictive model given an approach and calibration data, but it also produces (by default) an estimate of the performance of the model when making new predictions (on future data). Therefore, it returns two results, which are here assigned to the variables loss and model. Loss is the so-called "loss estimate" for the model. Here, it is the mis-classification rate (a.k.a. error rate), which is an estimate of the fraction of trials (in this case: movement imagination events) that it will likely mis-classify.

If there are only two possible outcomes (e.g. 0=Left / 1=Right) and both appear with equal chance, deciding by throwing a coin will have a mis-classification rate of 50% (0.5), which gives the chance level in this situation. A loss estimate of 0 would mean that all events are correctly classified. However, due to the high variability of the EEG, errors made by the subject when executing the task, artifacts, etc., perfect classification is almost never attained. This statistic is obtained via cross-validation (ref), a procedure in which the original data set is repeatedly split into training and test sets. Additional statistics (such as the loss estimate for every split, the confusion matrix, etc.), can be obtained by invoking the bci_train function with three output arguments instead:

The variable model in both cases contains the learned predictive model, which is a data structure which specifies both the algorithms to be used for online processing, as well as the parameters to be used in these algorithms. It can be saved to disk for later use (by entering save model), or it can be directly loaded into one of the online plugins. The training function supports additional arguments to control the type of loss metric to use (e.g., mean-square error), the cross-validation partitioning scheme, etc. Type doc bci_train to get additional information on these parameters (reference table at the very end). By typing stats or stats.fieldname, different aspects of the statistics can be investigated (depending on the field name chosen). MATLAB also provides a graphical array editor which can be used to explore data structures such as stats; it can be invoked with the command openvar stats.

The structure of predictive models can be visualized. Depending on the BCI paradigm used, this may involve different types of visualizations to present the respective parameters. For example, the CSP model learned consists of six sets of parameters that can be interpreted as per-channel weights, and thus, as topographic maps. In the case of CSP, the 6 maps are rows of a matrix, and the columns of its inverse matrix happen to be more interpretable (akin to mixing and unmixing matrices in ICA); therefore, the inverse maps are being displayed by default. [picture] In addition, this model also contains the overall weighting of these six maps, which is however not separately displayed. Other possible visualizations involve per-frequency weighting, per-timepoint weighting, weights per cortical area, etc. The following command brings up a visualization:

Predictive models, once learned, represent the structure of the data set on which they were learned. Applying the model to this data set to obtain performance estimates yields results which are practically meaningless (roughly comparable to circular reasoning). For this reason, bci_train uses cross-validation to arrive at performance estimates from a single data set. However, applying a model to new ("unseen") data is a valid case of offline analysis. The following code loads a second dataset from the same person and day, and then applies the previously learned model to it, obtaining predictions. This second data set was recorded under the same type of experimental paradigm as the first one, so that event markers are available which encode the types and time points of presented stimuli throughout the recording. Following the same procedure as the during calibration, the actual cognitive state labels are known for each trial -- bci_predict optionally returns this information in its fourth output. Given the known labels and the model's predictions, it is possible to compute the discrepancy between the two in the form of a loss measure, returned in the second output, here assigned to the variable testloss. By default, a loss measure is chosen which is compatible with both the type of target variable and prediction variable (categorical, continuous, etc.). Additional parameters of bci_predict allow to change this default, though.

The same could also have been written in one line:

The following lines print a part of this information in human-readable form:

The test mis-classification rate is usually worse than the training mis-classification rate, as many conditions are likely to have changed between the two sessions, and some of these might affect the model's outputs. It is possible to factor out large quantities of these session-specific details, either by means of fairly strong regularizing (or simplifying) assumptions in the learning approach, or by using far larger quantities of training data, e.g., spanning many different sessions. Overly strong regularization may constrain the expressive power of the model (i.e., what types of structure it can capture) to an extent that it fails to capture much of what is characteristic in the data at hand, thus leading to worse training and test performances. Overly lax regularization in turn tends to result in the model learning the peculiarities of the specific data sample used for training (which is of course a random draw out of an infinitely large pool of possible alternative recordings), which in turn also leads to poor performance. This phenomenon is called overfitting. Therefore, a good tradeoff must be chosen, and ideally, the remaining modeling assumptions should be in good agreement with reality, as far as that is possible. Also, it is generally a good idea to choose a computational approach that allows to incorporate as much information about the person (and task) as possible. The current version of BCILAB offers relatively little in this particular direction, but future versions will add more support.

An important trade-off when analyzing data is that of accuracy versus computational expense. The toolbox contains several BCI paradigms that can be applied in roughly the same circumstances, but primarily differ in terms of their simplicity, computation time, and attainable performance. For oscillatory processes, these are log-BP, CSP, and Spec-CSP (in increasing complexity), as well as DAL_Hifreq. The following code performs the same analysis as the basic scripting example, but uses the Spec-CSP (spectrally weighted common spatial patterns) instead of the CSP approach (which is, essentially, a more advaned feature extraction component which is sandwiched between the signal processing and machine learning stages).

Spec-CSP learns not just optimized spatial (i.e. topographic) weights, but also optimized spectral weights. As both sets of parameters are updated repeatedly in alternation, this takes significantly longer than CSP alone, but with the added benefit of learning individualized frequency bands that exhibit the oscillatory processes of interest (whereas CSP uses "a priori" fixed bands).

In some cases, BCI paradigms have parameters that are not known precisely for a given person (although some reasonable defaults usually exist). Though it is always possible to try several settings for these parameters and taking the one that gives the best results, the resulting loss estimates are systematically biased, and cannot be reported in a publication (for the same reason that multiple hypothesis tests require a correction). The correct way to calculate loss estimates in the presence of a parameter search is to run the entire search procedure itself inside one large cross-validation (i.e., partition the data set into k sections, take all but one section for training and compare all possible parameters on it, each time computing loss estimates via a nested cross-validation within these k-1 sections, and then testing the best model on the held-out section). This procedure is called a nested cross-validation and is natively supported by BCILAB. It is conducted by specifying values for unknown parameters in a special way, using a so-called "search clause", which lists all possibilities to be compared. After loading a data set,

a typical CSP approach may be specified with an additional custom parameter -- the number of CSP patterns to compute (this is the number of columns in the CSP visualization, and controls the simplicity of the model), which is part of the 'FeatureExtraction' (or short, 'fex') parameter group of the approach, and is called patterns. The below code sets it to 3 (also the default value).

Common choices of this parameter are 2,3, or 4, and it is not known in advance which one to use. Therefore, one may alternatively specify the parameter as to be searched, using a search clause:

If this approach is now applied by BCILAB, using the same code as before, the computation takes significantly longer, but with the added benefit that the resulting accuracy of the model may well be better than before, as this parameter is now individualized.

It is also possible to specify multiple parameters to be searched at the same time, though this will increase the running time of bci_train combinatorially. Some paradigms and, especially, machine learning components have parameters that are by default specified as a search range.

While the previous examples operated exclusively on oscillatory processes, another relevant type of brain process is slow cortical potentials (SCPs), i.e. changes in the cortical voltage distribution throughout some time period. The characteristic feature of these SCPs is their structure within a time window, which is usually locked to certain events (then called event-related potentials, or ERPs). For this reason, the applications of many SCP-based BCIs are constrained to situations where such event information is available in real time. One example are human-computer interfaces which occasionally exhibit erroneous or unexpected behavior, triggering a characteristic brain response that can be detected. The following script learns a predictive model for the detection of such error responses.

First, a calibration data set is loaded. The recorded data contained periods in which expected (normal) events happened (tagged in the data set with the marker S 11), as well as periods in which various types of error events happened (some tagged with S 12 and others tagged with S 13). Also, a list of marker types is created, which contains the marker for expected events as its first entry, and a sub-list of markers (identifying unexpected events) as its second entry).

Then, a computational approach is specified. A standard BCI paradigm for use with slow cortical potentials is para_windowmeans, which, however requires some knowledge about the expected time course of the responses. Instead, a newer approach is being used, called in BCILAB the Dual-Augmented Lagrange method. The only information that needs to be specified for this approach is the list of relevant event types and the time window around these event markers that is of interest (i.e. which assumed to be holding information about the cognitive state of interest, here: whether the user was perceiving an expected or erroneous event). In addition, it is important to use a low sampling rate in order to keep the complexity of the learned model low.

Finally, a model is being learned. It can subsequently be used for the real-time estimation of whether the user is perceiving an event as being erroneous or not. The paradigm contains one parameter which is by default set to a search range; for this reason, the computation will a relatively long time.

A faster to compute, but more involved to specify, way to achieve comparable precision is via the WindowMeans paradigm (this is the "classical" approach to handle SCPs). Here, it is necessary to specify the time window of interest relative to an event (as before), but also sub-windows within that time segment, within which the signal's average shall be computed for further processing. As these are slow-changing potentials, this is a way of reducing the dimensionality / complexity of the data without losing significant information, and selecting the portions of the data that are likely relevant. The resulting values for each event are concatenated into a feature vector (#time windows * #channels) and then picked up by the machine learning stage. First, the time segments within the window are defined (in seconds relative to the event, here 0.25s to 0.3s, 0.3s to 0.35s, etc.), as well as the event types.

Then, an approach is defined, based on WindowMeans, with custom epoch extraction and spectral selection specified. The seven sub-windows are specified via the 'TimeWindows' parameter that is part of the 'FeatureExtraction' group of parameters (see also the documentation of paradigms/para_windowmeans, or its review/edit panel in the GUI).

A shorter form for the previous definition, using the short-hand names, is:

Note to experts: If all parameters in a parameter list are specified (as here in for the EpochExtraction), then it is often possible to specify these parameters not by their name but by their position in the parameter list of the function that processes them; in other words, the order determines which value gets associated with what parameter. The following line of code specifies the same approach as before, but the parameters in the 'epoch' list are specified by position, instead. The order is as in the review/edit panel in the GUI (under EpochExtraction), but the canonical reference is the argument declaration in the respective function, here dataset_editing/set_makepos.m.

Finally, the model is learned and visualized. The visualization now yields a different output than for CSP; displayed are the weights (relevances) for each channel and time window, displayed as #windows topographic maps.

A core part of modern BCI approaches is the component which does statistical learning based on the calibration data. A good introduction to the underlying problem and the surrounding mathematical setting is given in the EEGLAB Workshop 2010 talk and slides. It is this part which handles most of the individualization and optimization of predictive performance. In almost all cases, this component can be swapped out against a great variety of drop-in replacements, using different sets of underlying assumptions, or having a different performance/computation tradeoff, and is therefore a major opportunity for customization. In the previous example, the default machine learning component is a special type of Linear Discriminant Analysis (LDA) classifier. The standard LDA tends to break down as the number of dimensions (independent variables) approaches the number of data points (trials), leading to degraded performance (this problem is called the "curse of dimensionality" in statistics). The WindowMeans paradigm uses by default a regularized variant of LDA which is robust against this situation, by restricting (or regularizing) the problem to the point that it can be solved with the given amount of data. The root problem with LDA is that, given enough degrees of freedom, spurious correlations between variables will be learned (originating from the small sample size), and regularization overcomes this by dampening these parameters towards zero.

An alternative assumption that can be used in classifiers is that only a sparse subset the features (and thus feature space dimensions) is actually carrying information about the variable to be estimated. Thus, all but a small set of learned parameters will be dampened towards zero, which is a very powerful tool if the assumption is true for the underling data. The most practical sparse classifier offered by the toolbox is sparse logistic regression, which learns a sparse linear model. There are two different implementations in the toolbox: first, the variational Bayesian approach (using automatic relevance determination), which is fast and very effective, but occasionally prone to numerical problems, illustrated below:

Given the ERP data fed into this classifier (where each feature corresponds to an averaged signal value within some channel and time window), the assumption translates into a model that uses as few of these time windows as possible, also seen in the visualization:

An alternative approach uses not the Bayesian method, but instead the regularization approach using the l1 norm. Here, a parameter search over a set of possible values for the regularization parameter is used (which takes far longer, unless a cluster is being used for the computation).

Editing data sets for use with BCILAB. The most frequent problem when preparing data for use with BCILAB is to ensure that there exist markers (in the calibration data sets) that indicate the time points at which information about the subject's cognitive state is available. These markers are the main tool in BCILAB to encode this type of information. In many cases, the stimulus presentation software can be configured to emit events of appropriate types into the data stream, and in other cases, they can be added via the EEGLAB GUI or ad hoc EEGLAB-style script code (editing the data set structure). In addition to these tools, BCILAB provides functions to split and concatenate continuous data sets, and to merge, sort or subset epoched data sets. Below are a few examples.

Inserting events into a data set. An important and frequent editing task is the insertion of an array of markers into one or multiple intervals of the data set, especially when a standard machine learning toolchain is used. The reason is that most machine learning components are trial-based, i.e., if there is significant variability within a particular condition (of cognitive state), its different aspects need to be captured by specific trials. Therefore, it makes sense to cover prolonged calibration periods that have no intrinsic trial structure with an array of markers (e.g., placed at random, or in regular intervals), whose density depends on the computational work that the user is willing to invest (up to one marker per sample). Another case is when the exact timing of an event is not known (only an approximate interval), or when it cannot be guaranteed that the BCI will be queried (online) at a precise event-related time point, but rather only within some short interval after an event, for example. There, the interval in question (often relative to a particular event) can be covered with markers to make sure that all data that is potentially of interest is captured by the model. In the following are a few examples.

Once a model has been learned, it can be used to estimate certain aspects of a user's cognitive state on raw continuous data. This can happen in real time within a live experimentation environment, in a real-time simulation using a previously recorded data, in a pseudo-online analysis, and for the purpose of annotating a dataset with BCI estimates.

The simplest use case is the augmentation of a previously recorded data set with additional channels that hold the estimates of a predictive model. The following code illustrates this use case. First, a calibration data set is loaded, a computational approach is defined, and finally, a predictive model is computed.

Then, another data set is loaded (for which perhaps some information about the user's cognitive state shall be deduced from the EEG), and the predictive model is applied to it, yielding additional channel which hold its outputs (in this case, the probabilities for either the left-hand movement imagination or the right-hand movement imagination).The function bci_annotate supports additional options, such as the rate at which predictions should be made (possibly saving time).

Now, the time course of this channel (and its relationship to the rest of the data) can be investigated using standard EEGLAB tools.

pop_eegplot(dataset)
pop_saveset(dataset)

A more elaborate way to obtain BCI outputs for a data set is the so-called pseudo-online analysis. Here, the user has more control over the exact time points (within the data set) at which predictions should be made, which can save time over the annotation of an entire dataset. The following code demonstrates how to obtain the BCI's output at particular time points (here: 3.5s after each occurrence of a particular marker), which is one of the main use cases for onl_simulate.

The real-time behavior of a previously learned predictive model can be simulated via the functions run_readdataset (which plays back a data set in the background, creating and updating a buffer variable named by default 'laststream'), and run_writevisualization (which reads by default from the laststream variable, invokes its specified predictive model, and calls the given visualization function / code with the result, all in the background).

Using BCILAB's real-time processing tools within some experimentation environment comes down to using online plugins which communicate with that interface. There are three categories of online plugins: Input plugins, which read from external sources in the background, output plugins which write to external destinations in the background, and processing plugins, which read from an external source, send data through BCILAB's processing pipeline, and write the results back to an external destination (which is usually in the same framework as the source). The processing plugins do usually not run in the background, but block until terminated by the user. At present, solid support exists for reading from BioSemi amplifier and DataRiver (as well as from files for simulations), processing within the DataRiver environment, as well as writing data to either a MATLAB-based visualization function, or directly to an EEGLAB dataset file.

Reading data from BioSemi devices (tested on Windows/Linux, hopefully working on Mac, as well) is done using the function run_readbiosemi, as demonstrated below:

Reading data from DataRiver in the background (which in turns allows to use a variety of lab hardware for data acquisition, transport, synchronization, and storage) is done via the function run_readdatariver. The following code assumes that some model calibration code as above was executed, and that an acquisition device was set up in the DataRiver GUI to produce a stream named C:/tmp/DataRiver. As DataRiver does not (yet) supply its own meta-data (e.g., channel names), these are supplied in form of either an EEGLAB data set with appropriate fields (e.g., srate, chanlocs), or a cell array of name-value pairs, defining these fields.

Processing can also be done within DataRiver (in lock-step between input and output), using run_pipedatariver, as shown below:

Raw data can also be written to a .set file (possibly in parallel to being processed), using the function run_writedataset, as below:

Support is planned for BCI2000 (untested code available) and OpenViBE environments, as well as BrainProducts and g.Tec amplifiers (and possibly others, depending on hardware availability).

Using the online processing language of BCILAB (onl_* functions), it is very easy to connect to further external systems using custom script code. The general concept of an online script is a loop which reads a chunk of data from some source (formatted as a numeric array with #Channels x #Samples entries), sends it to the BCILAB processing chain, queries a processed output from BCILAB (which is usually a number or a row vector, depending on the type of the provided/requested prediction), and forwards that output to some destination. In addition, the input stream(s) must have been opened beforehand (which is the place to declare meta-data such as channel names and sampling rate), and a predictive model must have been loaded. The following code demonstrates this concept (requesting a row vector of per-class probabilities from BCILAB, by calling onl_predict with the format set to 'distribution'):

When creating a new stream, any kind of meta-data can be assigned in the form of name-value pairs (ideally adhering to the EEGLAB dataset / field name formats where appropriate). The only required data is the sampling rate and channel names. When a new predictor is loaded, the list of channels used by the predictor (determined according to the original calibration data set(s)) is matched against the channels held by the currently existing streams, and the appropriate source stream is chosen automatically. However, if there are multiple concurrent streams with the same channel names, the stream name(s) to consider can be specified in onl_newpredictor to avoid ambiguities.

In many cases, other tasks should be run on the same machine in parallel to doing real-time processing. In these cases, it is usually necessary to conserve CPU resources by using the pause function in between loop cycles. An example implementation is as follows. The variable next shall hold the time, in seconds, when the next output should be produced. At the end of each loop, a pause command is introduced which waits until the appropriate amount of time has elapsed.

Some devices do not support polling of new data since the last request, but instead block until new data has arrived. The following example shows how to handle a source which produces sample-by-sample data; it is also an example of how to use the stream's clock (dictated by the source device, instead of the local timer).

Feeding individual samples into a BCI stream can be inefficient, especially at very high sampling rates. To maximize the performance of online code, it can be good idea to collect samples into a block which is then fed into the BCI at once. The following code illustrates this variant.

It is possible to process multiple concurrent streams with the same predictor (although at present no predefined BCI paradigms exist which allow to calibrate such a predictor); in this case, it becomes important to ensure that the relative timing of the input streams is properly matched (especially if the relative timing is accounted for by the predictor). By default, it is assumed that the first sample of each stream is recorded at exactly the same time, and the time points of all other samples are calculated based on the respective sampling rates. If this is not the case, the xmin field can be specified for each stream to define the correct times (in seconds, and in some arbitrary time domain which must, however, be the same for all streams in question), or, alternatively, it is possible to pass a time stamp that marks the time of the last supplied sample with each (or some) of the onl_append calls, again in seconds and in some arbitrary time domain. As these may be prone to jitter, BCILAB takes into account the last few time stamps (their number can be specified in onl_newstream).

BCILAB has been created from the ground up for easy extensibility. This means that new plugins can be written as simple MATLAB functions, often requiring just a few lines of code. The interface that these functions should adhere to in order to be compatible with all others is generally quite simple, yet at the same time non-constraining. It is therefore possible to implement just about any type of brain-computer interface for use within the toolbox. Only minimal knowledge of the BCILAB system is required - in fact, it is possible to create useful plugins without even knowing how a Brain-Computer Interface works. Given an entry barrier this low, BCILAB is one of the easiest to extend BCI research environments.

BCILAB has been created from the ground up for easy extensibility. This means that new plugins can be written as simple MATLAB functions, often requiring just a few lines of code. The interface that these functions should adhere to in order to be compatible with all others is generally quite simple, yet at the same time non-constraining. It is therefore possible to implement just about any type of brain-computer interface for use within the toolbox. Only minimal knowledge of the BCILAB system is required - in fact, it is possible to create useful plugins without even knowing how a Brain-Computer Interface works. Given an entry barrier this low, BCILAB is one of the first BCI research environments that can be meaningfully extended by its users.

Readers who are not yet familiar with writing MATLAB functions are referred to MATLAB's function help, accessible via Help / MATLAB / Getting Started / Prgramming / Scripts-and-Functions / Functions. Creating a plugin boils down to creating a new .m file in an appropriate directory, and using the same type of file name prefix as used by the other files in that directory, as listed in the following table:

Signal processing: code/filters/flt_*.m Dataset editing: code/dataset_editing/set_*.m Machine learning: code/machine_learning/ml_train*.m and ml_predict*.m BCI paradigms: code/paradigms/para_*.m Online plugins: code/online_plugins/*/run_read*.m or run_write*.m or run_pipe*.m

Each type of plugin function has a different set of required input and output arguments. These carry the data that is always passed by BCILAB, or that is always expected in return by BCILAB. In addition to these, a plugin can have any number of optional input arguments which the plugin user may or may not specify, if desired. The reason for making all other parameters optional (by default) is that any plugin should ideally be usable without the user having to specify parameters first. For example, if a sampling rate converter is invoked without a target sampling rate, it will simply return the input signal unmodified.

Because most plugins have at least one or two optional parameters, and some have dozens (such as independent component analysis or some machine learning tools), every plugin function needs solid and convenient support for handling optional parameters. In addition, every plugin will be displayed by BCILAB's graphical user interface in one place or another. This can be a dialog window that let users review/change optional parameters, or it can be entries in a graphical property table (such as the Review/edit approach panel in the main GUI). For these reasons, the input arguments of every plugin are declared using a descriptive mini-language within MATLAB, which allows to specify every argument's name, position in the argument list, default value, type constraints (if any), a human-readable name and optional help text, as well as some optional features. The functions that form this mini-language begin with the prefix arg and are found in code/arguments.

In addition to custom argument declarations, some types of plugins can declare special properties (properties of the plugin), such as the human-readable name, a description text, etc. This is done via the function declare_properties.

In the following, the various plugin categories are introduced, going from the simple to the complex. It is thus recommended to read through the sections in order. Complete example code for plugins of each type is given. In addition, the functions in the previously mentioned directories are all open source, and can be used for reference and modified as desired.

Online processing plugins are very similar to online processing scripts (see section "Writing online processing scripts" for the processing basics), except that they are functions which declare their arguments in a form that is compatible with BCILAB. The function code/online_plugins/Examples/run_pipetcpip.m is a complete online plugin, and will be analyzed in detail in the following.

The function declaration line for online plugins usually looks like the following (no return values, and no input arguments except for varargin). The portion run_pipe indicates to BCILAB that this is a pipelining online plugin, which reads, in a loop, a block of data from some source, pipes the data through BCILAB, and then forwards the result to some destination. The other two types of BCILAB plugins are input plugins (which read from a source in the background) and output plugins (which write to a destination in the background). The first line is called (in MATLAB) the "H1 header"; this is the executive summary of the function, also displayed by the built-in help and doc commands when run on directories.

The next comment lines list the input (and output) arguments and their meaning, if any. This material will be displayed when typing help run_pipetcpip or doc run_pipetcpip in the command line, and it is therefore critical that the parameter names and descriptions match the actual usage. Although not always the case throughout the toolbox, it shall be adhered to for all new code. The format for parameter names should ideally be CamelCase, and parameter names should be reasonably informative (as they are displayed to users in the GUI); if there are precedents for some parameters in other functions, please use the same names to reduce the amount of terminology that the users need to deal with. Also, please make sure that all parameters have reasonable defaults.

The remaining lines contain a command-line usage example and authorship notice.

The comment block is followed by a declaration of a property -- here: the human-readable name of the plugin -- which is displayed in the GUI menu, and thus mandatory.

Next, the function arguments are formally declared; this is initiated with the following line (the ... indicate that the statement continues in the next line).

A list of formal argument declarations follows (this is an advanced alternative to the usual declaration of function arguments in the function declaration line), where each argument is declared by the function arg(). See also help arg_define and help arg The first element in the arg() declaration is the list of names of the current argument to be declared (each can have multiple names). In particular, the first name is the one that is used throughout the function's code (thus, it can be short, and may be in any naming scheme), and the second name (if any) is the human-readable name, which is displayed in GUIs, and in the preceding help text. Any other names are optional, and useful for legacy support/compatibility. The following elements are all optional, but are used in most cases. The next element is the default value (here the string '127.0.0.1'). The default value determines the MATLAB type of the argument, if not otherwise specified (the MATLAB type controls the type of widget that is used in GUIs to display/manipulate the argument). The next element (here: []) is the range constraint on the argument, if any (it allows to restrict the permitted range of the argument). The next element is the help text of the argument. This is split into an executive summary (which must be at most 60 characters), analogous to the H1 line in the function's help, and, following the full stop, any additional help text. If this argument is shown in a dialog (click Online Analysis / Process data within... / TCP (Instrument Control Toolbox) in the BCILAB main menu to see how the function under discussion is rendered), the executive summary will be shown next to the edit field, and the remaining help will be displayed as tool tip if the user hovers the mouse over the edit field.

The next argument has a default that is a number; therefore, an error message will pop up if the user types in a non-numeric string in the edit field.

The follwing argument (InputMetadata) is special; it lists an empty default, but uses a function as its range constraint (and is declared via arg_sub instead of arg). The result is that whatever arguments that other function declares, will be "sub-arguments" of InputMetadata; they will be displayed as subordinate arguments in a GUI panel or spliced into the argument list in a GUI dialog. To pass the sub-arguments of this parameter in the command line, a cell array containing name-value pairs is used where the value for InputMetadata would be expected (see also code example). A struct with subfields for the respective parameters can also be passed. InputMetadata allows to specify the list of meta-data fields of the online stream (i.e., srate, chanlocs, etc.), but can also be used to refer to some existing data set from which the meta-data shall be taken (e.g., from the calibration set).

The next argument, Model, holds a string (default: 'lastmodel') that refers to the name of the predictive model to be used; an appropriately-named variable is expected to exist in the workspace by the time this function is executed. Following the help text, the type of the argument is changed from 'char' (string) to 'expression', which indicates that any MATLAB expression can be used in this place, and will be evaluated by the GUI (e.g., 'load( mydetector.mat)')).

The following three arguments are a string, a number, and another number.

The last argument, OutputFormat, has a string as its default, but lists a cell array of strings as its type constraint. Since the possible input strings are thereby constrained, the parameter is editable via a pull-down menu in any GUI that is rendered for this plugin. The trailing ");" terminates the arg_define( clause.

An important caveat holds for the first name of each argument: if any function with the same name exists in MATLAB's path, this is very likely to lead to errors in current MATLAB versions (up to 7.10). For this reason, attempt to use names that are unlikely to clash with functions that people might have in their path (e.g., use underscores, or use the CamelCase parameters as the sole declared name.

Following the argument declarations, the actual function code begins. First, the meta-data is turned into a struct with fields srate, chanlocs, etc., using a convenience function specifically for online plugins (other plugins use the same function). This function allows to pass both a listing of meta-data fields, such as srate, chanlocs, etc., manually, or allows to specify them in a GUI, but it also allows to pass an entire data set for the parameter from which the relevant meta-data fields shall be taken.

meta = utl_parse_metadata(in_metadata);

Then, a new online stream is opened and a new predictor is loaded, nearly identical to online script example.

Next, the actual TCP/IP connections are established. For simplicity, the Instrument Control Toolbox is used here, but an alternative would have been Java code as used in the (unrelated) function hlp_worker.

Finally, the online processing loop is entered, which uses essentially the same pattern as the previous one-sample-at-a-time online scripting example. However, the sample is obtained using the appropriate TCP interface code, and the estimate (here called result) is sent to a destination using the appropriate TCP code, as well (and custom message formatting).

An entirely different form of online plugin are those that read or write their data in the background - i.e., any other code, including other data acquisition, processing or sending code (even certain offline analysis scripts) can be run in parallel to it. This is only easy to implement for data sources which do not block the calling function when no samples are available (possible for TCP, but too complicated with MATLAB's Instrument Control Toolbox to serve as example). The BioSemi input plugin (code/online_plugins/BioSemi/run_readbiosemi.m) is a simple example of such a source, and will be analyzed in detail in the following.

First, the plugin function is defined, and input arguments are documented.

Then, the name of the plugin is declared

and the arguments are parsed. If the output of arg_define is captured in a variable (as below), the declared arguments will be returned as subfields of this variable. The arguments are comparable to the input arguments of the previously shown plugin, with the exception of the MatlabStream argument. This argument allows the user to specify the name of the stream variable which will be created in the workspace, and be updated in the background. This makes it possible to launch other plugins later which periodically read from this variable (perhaps also in the background).

Then, a connection to the amplifier is established

and an online stream with meta-data is created (like in the previous plugin case).

With stream and connection having been set up, the background acquisition is initiated via the function onl_read_background. This function expects the name of the stream variable to write to, a function which will be periodically called to obtain blocks of new samples, and the rate at which the stream variable should be updated. The function which reads a block is here given as @()read_block(conn,opts), which is an inline definition of an unnamed function (a.k.a. lambda function) with no arguments (empty brackets), whose only statement is read_block(conn,opts). The return value of that statement is taken as the return value of the newly defined function.

onl_read_background(new_stream,@()read_block(conn,opts),update_freq);

The actual work is done in the read_block sub-function, which takes two arguments - a handle to the BioSemi amplifier, and the options structure that was originally created by arg_define.

function block = read_block(conn,opts)
block = bs_read(conn);
if ~isempty(block)
    block = block(opts.channel_range,1:double(bshandle.srate)/opts.sample_rate:end); end

This function fetches a new block from the amplifier connection, sub-samples it (poorly) for performance reasons, and returns the result. The background processing will be automatically terminated if this function throws an error, or if the stream that should be updated is deleted or replaced.

Background output plugins are programmed in a very similar way to input plugins. In the following, the function code/online_plugins/TCP/run_writetcp.m will be analyzed in detail, which sends processed BCI outputs to a remote machine via TCP (this time using Java code from within MATLAB).

First, the function is declared as usual, and parameters are documented (not shown).

Then, the mandatory GUI name of the function is declared.

Next, the parameters of this function are introduced. This holds no surprises - note, however, that the Model parameter has its type set to 'expression', which means that, if a string is passed, it will be evaluated (against what is defined in the MATLAB workspace), and otherwise, any data structure passed for this argument is taken as-is. Thus, both the name of a model in the workspace can be passed here (or entered in the respective GUI edit field), as well as the actual data structure itself (e.g. in script code). In addition, it is possible to type an expression which, e.g., loads the model from disk in the GUI dialogs. The message format is also an expression, which allows to define formatting functions in the GUI, using MATLAB code (but does not rule out passing function handles directly from scripts or the command line).

In the following, some special input handling is done, which allows to pass standard formatting strings (e.g. '%0.3f %0.3f /n') in place of a formatting function (for convenience).laststream

Next, the TCP connection is established using Java code (see Java documentation of Socket and DataOutputStream), is configured, and a so-called Java Stream is obtained, which allows to send formatted data over the connection.

Finally, a background writer job is started, which periodically processes data and calls the the send_message function to send the result to some remote device. The function onl_write_background loads the predictor, connects it to a stream, and launches a timer which periodically processes data and calls the message sending function. As before, the message-sending function is declared here as an in-line unnamed function (or lambda function), which takes one parameter (y, which is the BCI output) and determines its result by calling send_message with that parameter and a few others that were obtained before.

onl_write_background(@(y)send_message(y,conn,strm,msg_format),in_stream,pred_model,out_form,update_freq,0,pred_name);

The message sending function is implemented as follows:

Any data processing step that can be described as taking a signal as input (plus optional parameters) and producing another signal as output can be implemented in BCILAB as a signal processing plugin, and can subsequently be used with other plugins and parts of the toolbox for brain-computer interfacing, cognitive monitoring, etc.. All signal processing plugins are single MATLAB functions (found in the code/filters directory, starting with flt_) that follow a simple contract of only a few lines.

Types of signal processing plugins. Just like EEGLAB, BCILAB supports two signals formats - continuous signals and epoched signals. Accordingly, there are two broad groups of signal processing plugins: those, which operate on continuous signals, and those which operate on epoched signals. While epoched signals are usually processed each epoch by itself (i.e., not moving information across epochs), continuous signals are often not just processed each sample by itself - instead, there are three distinct sub-types of signal processors (including those whose emitted samples depend on more than one source sample, e.g., spectral filters). According to whether emitted samples depend on source samples that lie in the future or not, these signal processing plugins are called in BCILAB non-causal/stateful (taking information from the future) or causal/stateful (taking samples exclusively from the present and past samples). Finally, plugins which process strictly each sample by itself are called stateless. All four types of signal processing functions will be illustrated with examples in the following.

Features of signal processing plugins. Signal processing plugins can be applied either to full pre-recorded data sets (i.e. very long signals), or they can be applied incrementally to blocks of data as they become available "online" from some acquisition device, often using the same code path in both cases. In some cases, however, some data structures may be pre-computed for more efficient online processing (e.g., computing an efficient filter kernel from some given frequency specification), so the parameters used to apply some processing step offline (e.g., the convenient filter frequency specs) may be different from the parameters used to achieve the same effect in real time (e.g., the efficient filter kernel). The solution used in BCILAB is to automatically annotate every data set with a formal description of how to replicate the entire processing (that generated the data set) both offline, and online - i.e., there are two different annotations stored with each data set. A plugin (when called with some parameters) may then specify an alternative set of parameters used to achieve the same effect in real time instead of offline.

Integration into a processing pipeline. Like in other plugins, input arguments are declared in a way that allows GUI dialogs and/or panels to be generated. Since signal processing is usually one (subordinate) step in a larger pipeline, the arguments of signal processing functions are mostly displayed in large parameter tables, also called property grids (see the Review/Edit approach panel in the BCILAB main menu), where the user can configure an entire approach at once. It is, however, also possible to apply a signal processing function individually to an EEGLAB dataset, just like in standard EEGLAB scripting on the command line or from an analysis script (e.g., for artifact rejection, exploratory filtering, etc.). A special feature of BCILAB is that the user typically does not need to care about the order in which to apply signal processing functions when they are run inside the BCILAB pipeline. To make this possible, each plugin specifies a set of ordering relationships, i.e., its preferences as to when it should be applied w.r.t. other filters (explained later).

These plugins operate on epoched signals, that is, signals which are split into segments of data (of uniform length). A standard example of epoch-based processing is the FFT filter; it transforms each given epoch from the time domain into the frequency domain. A full-fledged version of this is supplied as standard filter named flt_fourier, but a simpler example (here called flt_fft) will be worked out in the following. To be able to test the function, create a file called flt_fft.m in the directory code/filters and paste the following code sections into it. A usage example will be shown later.

The function declaration of any epoched signal processor has a single return value, namely the output signal. The input is always declared as varargin.

Any signal processing plugin uses the following line as its prologue. The line allows exp_beginfun to record the used input parameters (among others, to be able to annotate the resulting data set after processing, but also to be able to look up the result from a cache without having to do the computation in the first place, in case the same computation had been run already at some earlier time). If the plugin is designed for pure offline analysis and thus should give an error when applied in an online processing setting, use 'offline' instead of 'filter' in the prologue line.

Next, the properties of the filter are being declared, including the GUI name (here: EpochedFFT), and its ordering relationships w.r.t. other filter stages in the toolbox. There are four types of possible ordering relationships: follows, precedes, cannot_follow and cannot_precede. The first two are 'soft' preferences - for example, if the data is resampled (using flt_resample), it is generally a good idea to run any heavy-duty processing after that (e.g. flt_reconstruct), since it will be faster. The latter two are 'hard' constraints - for example, a continuous-data filter (such as flt_iir) cannot be run after the signal has been converted to epochs (via set_makepos. A special type of ordering relationship is 'depends', which means that the filter requires that some other filter has been run on the data in a previous step - for example, an epoched filter like the one being defined here cannot be run on non-epoched data; therefore, it depends on set_makepos. Depends implies cannot_precede. These relationships are by default transitive; i.e., if C follows B and B follows A, C will follow A, if possible (even if B was not used). Spectral filters such as the one being defined here are most useful when applied to properly spatially filtered data, and on properly temporally filtered data; therefore, this filter follows by default after both flt_project and flt_window. Any such relationship can be overridden by the user (except for the hard constraints) both in the command line and in the GUI, and also when defining a new paradigm.

Finally, a special property that a filter may or may not have is that any channel that it outputs depends only on the data of the channel with the same name in the input signal. This is true, for example, for most spectral and temporal filters (e.g. the output channel 'C3' is computed on the raw data of 'C3', and nothing else), but it is false for most spatial filters (such as the surface laplacian or ICA). This property is optional, but makes the filter easier to handle in online settings, as it allows the toolbox to resolve which channels of raw data any given predictive model actually depends on - so it can automatically identify the correct streams to use as data sources when a new predictor is loaded for online use, or it can give meaningful error messages when a required channel is not present in any of the source streams being recorded.

Now, argument declaration of the filter begins, using the function arg_define. In normal usage, the first input is always the varargin of the function.

... and the first argument being declared is generally called 'signal' (and carries the input signal). It is usually being declared via arg_norep instead of arg, which denotes that the parameter is not reported in user interfaces (the user is supposed to specify the optional parameters there, rather than the actual signal data).

The second argument is optional, and it allows to toggle whether the logarithm of the spectral power density should be taken, or not (default: no). See also the online plugin authoring guide (or enter doc arg_define in the MATLAB command line) for a documentation on the argument declaration format.

Following these declarations, the actual signal processing implementation begins. In the case of an FFT filter, this is relatively simple and equals exactly the type of code that would be required for an EEGLAB plugin.

Any signal processing function is concluded by an epilogue using the function exp_endfun. This is the place where alternative parameters for the online processing case could be specified (example later). The function serves to incorporate any annotations into the resulting data, and may also cache the result on disk or in memory (if the toolbox is configured appropriately).

Testing the function from the GUI. The function is now ready to be used from the graphical user interface. As the function transforms the raw signal of each channel into the frequency domain (within some epoch window), a possible use case might be as pre-processing for some multi-band spectral classification. As testing data for this, the imagined movements dataset in userdata/test/imag.set will be used. It contains the marker 'S 1' whenever a symbol was presented which instructed the subject to imagine a movement of her left hand, and the marker 'S 2' whenever, she was instructed to imagine a movement of her right hand; in total, there are approx. 80 such trials per condition in the recording.

Computational approach / calibration stage. For learning, the raw data will be resampled to 100 Hz, and a surface laplacian with 8 neighbors around each electrode will be computed (yielding a spatially filtered signal). Then, epochs will be extracted following 0.5s after each stimulus marker (to account for the delayed reaction of the subject) and spanning 3s until 3.5s after the respective stimulus. Each epoch will be labelled according to the type of marker from which it was derived. Then, each epoch will be transformed into the frequency domain via FFT (using the new plugin). ThenNext, spectral power features are being extracted for each epoch; specifically, the spectral power in a set of frequency windows (6-15 Hz, 15-30 Hz, 6-30 Hz) will be averaged for each channel (yielding 3x #channels = 96 features per epoch). A non-linear classifier will be learned on the resulting data using regularized quadratic discriminant analysis.

Computational approach / prediction stage. During online processing, the incoming data will be resampled to 100Hz, a surface laplacian with 8 neighbor electrodes will be derived for each channel, and the most recent 3s of the incoming data will be transformed into the spectral domain (using the new plugin). From these data, spectral power features will be computed as described before, and the resulting features will be classified using the previously learned quadratic classifier.

Evaluation approach. The performance of the newly defined method will be evaluated offline using 10x blockwise cross-validation, where 5 trials around any test trial will be excluded from the training set, using mis-classification rate as the loss measure.

Instructions. Follow the steps from the extended practicum (ftp) to load the toolbox and the data, but stop at the point where Common Spatial Patterns would be selected as the BCI paradigm to use. Select instead the Windowed Means (para_windowmeans) paradigm, and click "Refine". Use [0.5 3.5] as the epoch time window, and choose {'S 1','S 2'} as event marker types (note: there are 2 spaces between the S and the respective digit). Choose [] as the frequency-domain selection. The time windows are more difficult to specify, as the unit of measure is seconds (in time), rather than Hz (in frequency): use [2 5; 5 10; 2 10]. Choose qda as the classifier, and click OK. In the next screen, uncheck the checkbox labeled SpectralSelection, and check instead EpochedFFT. Click OK to finalize the approach, type in a descriptive name for the approach (e.g., Multi-band QDA) and click "Save on disk..." if you like to re-use what was just defined at a later time. Choose a file name, click Ok, and also click OK in the Save approach dialog.

Click Offline Analysis / Train new model..., and click ok. Wait for the Review Results dialog to pop up.

Stateless signal processing plugins operate on continuous signals, produce one output sample for every input sample, and each output sample Y(t) depends only on the respective input sample X(t). Thus, they cannot implement any spectral or temporal filtering; instead, they are restricted to spatial filtering operations on the data (such as channel selection, re-referencing, linear projection or decomposition, surface laplacian, non-linear reconstruction, etc.). They are called "stateless", because there is no information that must be maintained after having processed any sample, in order to process the next sample.

One of the simplest examples for stateless signal processors is the channel selector - a filter which allows to select a subset of channels from a data set. In the following, the standard function code/filters/flt_selchans.m will be analyzed.

First, the function's signature is defined. The only return value of any stateless signal processor is its output signal. The input arguments are always declared as varargin.

Next, the inputs and outputs are documented. In almost all BCILAB plugins, these arguments can be passed either in order of appearance, i.e., flt_selchans(mysignal,{'C3','C4','Cz'}) or in the form of name-value pairs (in any order), using the names listed in the documentation, i.e., flt_selchans('Signal',mysignal,'Channels',{'C3','C4','Cz'}). This is enabled by using arg_define to specify the function's input arguments. A mixture of the two modes, i.e. passing the first n arguments in order of appearance, followed by some of the remaining arguments passed as name-value pairs is usually not allowed, unless the function explicitly accounts for it (enter doc arg_define for more information). For any type of signal processor, it is, however, generally disallowed. Since arguments often have multiple names, these alternative names may be used to specify arguments when calling a function, e.g. flt_selchans('signal',sysignal,'channels',{'C3','C4','Cz'}) uses the lower-case versions of these parameters, as declared later in the code.

Next, the standard prologue line for all filters is invoked (see epoched plugins for additional details).

Then, the properties of the function are being declared; the properties must always be declared before the function arguments. Here, the GUI name, and certain ordering preferences are specified. Recall that if no ordering relationships are declared, the function will not show up by itself in any of the standard paradigms (but only in custom paradigms which explicitly make use of (and know when/where to apply) the filter in question). The channel selection prefers to precede any surface laplacian, ICA decomposition and Re-Referencing (as it serves to remove missing or broken channels which should not affect any of those operations). Not every possibly reasonable ordering relationship has to be written down explicitly, as these are transitive (e.g. whatever prefers to follow flt_laplace also follows flt_selchans).

Next, the two arguments of the function and their defaults are being declared. The second argument, 'channels', has an empty default value, but should be a cell array of strings (namely the channel labels to be retained). To specify this, the type and shape properties of the argument are explicitly defined.

Finally, the actual signal processing code follows. Here, the EEGLAB function pop_select is being used to select the channels from signal (and produce the appropriate return value). If you use EEGLAB functions extensively, you may have to benchmark (and perhaps optimize) their online performance, as they will be called many times a second - thus, use them with care. However, if you implement certain operations such as channel selection manually, please make sure that you update meta-data accordingly, as well (this makes up the majority of code); for example, pop_select does not just update the signal.data field, but also its chanlocs, ica matrices, etc. Otherwise, some subtle bugs may be introduced into later processing stages that depend on these meta-data.

Any filter is concluded with the epilogue function, exp_endfun (see the epoch signal processor example for more details).

In the following, a special type of spatial filter, which demonstrates how to use signal meta-data to implement complex processing, will serve as an advanced example. The function flt_selvolume (code/filters/flt_selvolume.m) assumes that the input signal has an associated ICA decomposition in its meta-data, and in addition, that equivalent dipole coordinates for every independent component have been fitted and that their corresponding anatomical structure labels have already been looked up (also stored in the signal meta-data). Thus, this filter depends on set_fit_dipoles to fit the dipoles (using the dipfit plugin to EEGLAB) and look up the anatomical labels (using Talairach), which in turn depends on flt_ica to compute the ICA decomposition (e.g., using Infomax or AMICA).

First, the function signature is defined as below. For any stateless filter, there must be exactly one output argument (the name is arbitrary, but using the same name as the input signal is convenient). The input arguments are always declared as varargin.

Next, the input arguments are declared.

Then, the standard prologue line for signal processing functions follows (see also epoch-based filters).

Next, the plugin's GUI name is declared, and some ordering relationships w.r.t. other filters are expressed. In this example, the function depends on set_fit_dipoles, and prefers to precedes set_makepos (among others, for efficiency reasons - as this is a data reduction step, and because the code has not been written to handle epoched data).

Then, the function's arguments are being declared. As for the epoched plugins, the first input must be named 'signal', and be treated by the function as the method's input signal; all other inputs are optional (see also: epoched signal processors).

The subsequent three arguments of the function are of a rare (though useful) type. The range is a cell array of strings, which is interpreted as a set of possible strings that the value can take on. However, the default value is not one of the strings in the range - instead it is a logical value. If the default value is either a logical value or a cell array of strings (while the range is also a cell array of strings), the type of the argument is inferred to be a subset of the strings specified in range. In other words, the value is a cell array of strings, each of which must be listed in the range; if the value is true or false, it is translated to either the full set (range) or the empty set ({}). In the GUI, arguments of this type are displayed as an array of checkboxes - one for each string in range, or a multi-select list.

The first such argument allows to specify from which hemispheres of the brain ICs should be retained. By default, all hemispheres are checked.

The second and third argument (not shown here for brevity) are similar, but allow to specify the lobes and gyri to retain. The fourth argument is a typical boolean argument, letting the user specify whether the output should be channel data with a reduced ICA annotation, or directly the reduced IC data itself.

The last argument is invisible to the user, and has no default value assigned (i.e., the argument will not be present in the function's workspace unless manually assigned). Generally, the default value is being assigned to an argument when no value for it was passed to the function, and there are two default values with special behavior: unassigned, meaning that the argument does not show up in the function workspace when not overridden with a value, and mandatory, meaning that a value must be passed for the respective argument, or else an error message is being generated. If no default is specified (such as for the initial 'signal' argument), it defaults to []. In this function, retain_ics allows to bypass the (computationally costly) logic of the function which determines what ICs should be retain.

If that variable does not exist in the workspace, it needs to be computed (which is the regular case). The following code analyzes the .dipfit.model sub-structure of the signal (which is being filled in by set_fit_dipoles), and in particular checks, for each independent component of the data, whether a volume around its equivalent dipole coordinates in the brain contains any of the labels that were checked in the three selection arguments. If so, it is retained, otherwise, it is discarded. This test is done separately for each of the three criteria (i.e., not being in any of the checked hemispheres leads to a component being discarded, but not being in any of the checked lobes, as well).

Next, the actual signal processing code follows (which is essentially component-based rejection). This code is always executed, regardless of whether retain_ics was passed or computed (above) on demand.

The previous changes to the signal only affected the meta-data, and not the signal time series itself. Thus, the processing step will be ignored by any subsequent processing step that ignores these meta-data and operates only on the raw signal. Ideally, all filters were advanced enough to take care of the meta-data that is relevant to them, however, for rapid prototyping (and some simple filtering), this is often not the case - thus, it is desirable to be able to replace the actual sensor-space signal by its independent component decomposition (restricted to those components that are associated with desired brain territories). If the optional parameter do_transform (a.k.a. TransformData) is enabled, the following code will do that. To avoid any inconsistencies, all subtle meta-data that related to the original raw signal is scrubbed.

Finally, the function epilogue follows, concluding the plugin code. In this example, a special remark is passed to exp_endfun - the fact that to replicate this processing step in real time, the name-value pair 'retain_ics',retain_ics should be appended to the parameters that are passed to the function (in addition to those that were passed by the user during the present invocation). The value of retain_ics that matches the three selection criteria has been pre-computed above, so a computational shortcut (using this value) can be taken if the function is later invoked in real time.

For example, if this function was called as:

... then, NEWEEG will have two annotations: first, the expression that were used to compute it in the first place (offline):

and second, the expression that may be used to replicate the same processing (efficiently) on real-time data, which will skip the "if ~exist('retain_ics') ..." part:

Stateful plugins differ from stateless ones in that they carry some state over from one sample to the next. In particular, as real-time data needs to be processed one chunk at a time, the plugin functions must be run on one chunk at a time, as well - and, for a given data stream, produce the same collective results as if invoked on the entire recorded data set. Therefore, the function must be able to carry over some state from one of its invocations to the next. This feature is the only difference between stateful and stateless filters. A simple analog is found in MATLAB's built-in function filter(), which has the ability to return state (in a second output value) after it processed a piece of signal, and can accept this state value (as an additional input parameter) when called the next time on a continuation of the signal. Likewise, all stateful filters in BCILAB have a mandatory additional output (a state value) and must be able to take an additional input (again, a state value).

A simple example of a stateful filter is the IIR (Infinite Impulse Response) filter. It is one of the most versatile frequency filters in BCILAB as long as the desired filter function can be expressed as a series of bandpass, bandstop, highpass, and lowpass filters. The following example will analyze the function code/filters/flt_iir.m in detail, which uses the Signal Processing toolbox to implement
is functionality.
First, the function signature is defined. In any stateful function, there are generally two outputs, the first being the output signal, and the second being the state after having consumed the input signal. The input arguments are always specified as varargin. The documentation of parameters is omitted here.

Next, the mandatory filter prologue line follows; it looks the same in all filters.

Then, the plugin properties are being declared. Here, the GUI name shall be IIRFilter. Some ordering relationships are declared: The filter prefers to follow flt_fir (because the signal will be more well-behaved after that stage than before it, which is helpful in preventing numeric inaccuracies). Second, the filter can not follow set_makepos, because it can only be (reasonably) applied to continuous data. The filter treats each channel independently.

Next, the definition of the function's input arguments begins...

The first argument is, as always, the signal, and it must always be named 'signal'. It is not reported to user interfaces.

The following argument is the frequency specification (default: []), and two multi-option parameters (displayed as pulldown menues in GUIs).

The remaining two user arguments are numeric, but have a special kind of range value, encoded as an unnamed function (a few standard forms of such range functions are supported by arg; please consult the documentation for an overview).

The last argument is for internal purposes: it is the optional state input argument, not visible in user interface, and by default unassigned. The state argument should always be the last listed one (users may want to specify parameters in order of appearance, which is less transparent if there are internal parameters in between), and it must be called state (as the online system generally passes the state under this name).

Next, the actual code begins. If no state was passed (the variable is not assigned, i.e. does not exist), it must be generated. The state object encapsulates the filter design, as well - thus, this is also the place where the filter is designed according to the specified parameters. If a plugin depends on a Mathworks toolbox, it is good practice to generate informative error messages, as below.

Next, the long forms of some values are being transcribed into short forms. The function hlp_rewrite is a convenient way to unify multiple possibly syntaxes (it works for any value type).

Then, the filter order is being computed. This generally involves a function like buttord, ellipord, etc., and the order of frequency band edges depends on the filtering mode (band-pass, band-stop, etc.). Note that most signal processing plugins will not attempt to support every possible filter design, and thus be somewhat simpler. The label variable is for convenience in the subsequent section.

Next, the filter coefficients are designed (depending on order and specs). The Z-P-K form is best used with the (very convenient) dfilt object.

As dfilt objects will not by default memorize their state across invocations, this needs to be enabled manually:

Finally, in case the state was already passed as an argument, this type of filter design pre-computation has already been performed, and nothing needs to be done. However, dfilt objects in particular have handle semantics, i.e., writing y = x and modifying y also modifies x, unless y is turned into a genuine copy. To avoid accidentally manipulating the function's parameters, the state is being copied, if it was passed. Accidentally modifying handle parameters can lead to extremely hard-to-find bugs, as BCILAB tracks its filter arguments in various data structures, annotations, and caches.

else
    state = copy(state);
end

Then, the actual signal processing is being performed, by calling the filter() function for dfilt objects. This updates the state (which subsequently being returned as the second output).

signal.data = filter(state,double(signal.data),2);

The plugin definition is concluded by the standard filter epilogue line.

Generally, any adaptive signal processing method can be implemented as a stateful filter. A typical adaptive statistical filter is flt_standardize, which standardizes the signal in a moving window. In many cases, however, such fine-grained sample-by-sample updating is not necessary, and it can be very costly to do the update computations incrementally, so that real time operation would not be possible. As an alternative, a filter may also be adapted on the calibration data set "en block", and then be used with its adapted parameters held fixed in an online setting. Currently, there is no such example in the toolbox, but, for instance, independent component analysis could be implemented as such a filter (see code/filters/flt_ica.m). In this case, the decomposition would be computed if ICA is applied to a calibration dataset, and the resulting processed data set would be annotated with an additional parameter for online use, which holds the computed decomposition. If re-run in real time with this additional parameter, the data would only be transformed by the decomposition, without updating the composition dynamically. Another example would be artifact rejection functions, which often first need to learn the statistics of the data from the calibration set, but then can use a fixed criterion for online processing.

Machine learning is a field of theoretical computer science with large overlaps with statistical learning theory, probability theory, optimization and decision theory, and diverse other fields. The theory is still in rapid development and still quite fragmented, however, the interface through which machine learning methods interact with their data is consistent and mature (perhaps as a side effect of the computer science background). This interface is closely reflected in the machine learning plugin interface adopted by BCILAB.

The role of machine learning in brain-computer interfacing is to learn the central person-specific (and/or montage/session/task-specific) properties of the data, and to exploit that learned information for producing optimized, robustified and individualized outputs. Machine learning operates by convention on abstract representations of data (usually a set of feature vectors, or equivalently, of distinct points in a high-dimensional space) rather than signals, and therefore requires that the raw signals have been mapped into some appropriate representation in a prior step (this task is often handled by signal processing and/or feature extraction components). In addition, since machine learning usually operates on a set of items (feature vectors), the recorded signals must necessarily be chopped up into a set of trials, as well. This is the reason why epoching (segmentation) of data plays such a central role in BCI signal processing, and also why an experimental design that naturally gives rise to trials plays a critical role for the calibration session.

Given such appropriate data, machine learning methods can learn (estimate/derive) parameters, which are collectively called a model of the data. Given such a model, and similar (but new) data, they can make inferences about and output predictions with those data (using the previously learned information). The most common situation in BCIs is that the training data contains not just readily observable information (i.e., representations of measured biosignals), but also information that the system should learn to predict, namely information on the latent or hidden (hard to observe) cognitive state of the person that gave rise to (aspects of) the measured signals. Thus, the method receives both a feature vector and a so-called "label" (or target value) for each trial, and should learn the relationships between the two, condense them into a model, and use that model to predict the label for future feature vectors. This is called supervised learning (the "supervisor" is supplying the labels by virtue of the experiment design that was used to produce the training data). If the label indexes cognitive state and the feature vectors are derived from bio-signals, the system is set up to learn how to predict cognitive state from these bio-signals.

In the simplest (and most common) use case, information about the cognitive state of interest is not available during the practical use of a BCI (which is why the BCI is necessary in the first place), but only during the (artificially set up) calibration session. Following this constraint, the majority of learning can be done in a single step, after the entire calibration session has been recorded, yielding a model. This model can then be held fixed and be used to make predictions (from newly recorded data) throughout any subsequent use of the BCI.

In more advanced scenarios, the model could also be updated during use of the system (for example, to track changes in the statistical properties of the data), which is called (semi-supervised) online learning, or adaptation. It is also conceivable (though rare) that the outputs of the model should be available throughout the calibration phase, for example, if the user wants to interact with the system while it is learning to interpret his/her commands (called co-adaptive learning). Further, an existing model can also be updated (perhaps efficiently) given an additional newly recorded calibration set, then called incremental learning. Finally, as any type of information can in principle be used to enhance the performance of a model (given an appropriate algorithm), multiple pools of calibration data, e.g., from other persons, other tasks, other sessions, etc., can be exploited. This is a form of multi-task learning (though currently in its very infancy).

The interface of a machine learning plugin largely depends on the type of outputs that it should be able to make, and in some special cases on additional properties of the training data. Any machine learning plugin consists of two MATLAB functions, one for learning a model (given training data), and one for making predictions given a model. Both are placed in code/machine_learning/, and one is called ml_train.m, the other is called ml_predict.m. is usually the acronym for the method (e.g. SVM, GMM, LDA, etc.). The learning function always receives a set of feature vectors (trials) as its first input, optionally a set of target values (one per trial) as its second input, plus further optional user parameters, and always has one output (the model structure). The prediction function always receives a set of feature vectors (trials) as input and has one output, the set of predictions (one per trial). Machine learning functions are not expected to support all possible output formats; instead, they should support what the method can naturally handle, without unnecessary restrictions. Since the performance estimates that BCILAB can compute for a given method are depending on the format of the method's outputs, different formats allow for different types of performance (or more correctly, loss) measures and prohibit others. Thus, not every possible loss measure can be used with every possible algorithm -- for example, mis-classification rate is inappropriate for regression outputs, and mean-square error is inappropriate for classification outputs.

Classification. The most common type of output is the discrete target label, i.e., a set of cognitive state classes is assumed (e.g., surprised and not surprised), and the BCI should output which class holds true for the user (at any given time). This case is called classification. Here, the targets are passed as a vector of numbers (one number for each class, but not necessarily consecutive integers). The simplest possible output is a vector of the most probable target value per trial. The preferred output is fully probabilistic, and is a cell array which contains a set of discrete probability distributions (one per trial). Each distribution describes the probability that each of the possible outcomes was the true one for the given trial. The formats are specified more precisely in the function code/machine_learning/ml_predict.m. Generally, each method should be able to handle the multi-class case, i.e., more than 2 classes (possibly using the provided voting utilities internally).

Regression. In regression, the space of possible outputs is continuous, i.e., both the target values and the prediction values are real numbers (for example, the degree of cognitive workload). Accordingly, the target argument passed to the learning function are a vector of real numbers (one per trial), and the output produced by the prediction function is, in the simple case, a vector of real numbers (one point estimate per trial, for example a maximum-likelihood or maximum-a-posteriori estimate). In the advanced case, the output is a univariate statistical distribution per trial (returned as a specially formatted cell array, see ml_predict for more details), preferably using standard distributions of the Statistics toolbox.

Multivariate regression. In multivariate regression, the target values and prediction values are vectors, and accordingly, the target argument passed to the learning function is a matrix (one row per trial), as is the output of the prediction function (one row per trial). In the advanced case, the output is a multivariate distribution per trial (returned as a specially formatted cell array, see ml_predict), in most cases of Gaussian type (though custom distribution functions are possible).

Structured prediction. It is theoretically possible to use arbitrary data types for target values (both in learning and prediction); these are passed as a cell array (one element per trial, both in the targets argument passed to the learning function, and in the output of the prediction function).

Uncertain targets. It is in principle possible to learn from incomplete knowledge about the target values (e.g., from a discrete probability distribution over possible target values for a given trial in a calibration dataset, or from a multivariate distribution in the case of regression with uncertain training data). In this case, the set of target values passed to the learning function will themselves be in the previously mentioned distribution formats (see code/machine_learning/ml_train.m).

Weighted trials. Especially in complex machine learning settings, where a learning function is used in a larger framework (for example meta-learning, Adaboost, multiple-model ICA) the inputs to the learning function may have an associated weight (determining the influence of each trial on the model). Many standard learning functions, especially those based on statistics, optimization and probabilistic inference, can be extended to supported weighted trials (though only few of them are), and are therefore applicable in the weighted learning setting. If a method can easily support weighted trials, it is worth considering the implementation.

In the following, the SVM plugin (code/machine_learning/ml_trainsvm.m & ml_predictsvm.m) will be analyzed and explained in detail. Support vector machines are some of the most frequently used machine learning methods both for classification and regression, and have proven to be useful in BCI settings, as well (see also documentation of the method).

First, the learning function is defined, beginning with the function signature. In general, the only output is the learned model (whose format is left to the implementation), and the inputs are always declared as varargin.

Following the function's description (omitted), the input parameters are documented. As for any other plugin, the names of input arguments should match the names that are displayed in the GUI, and those that can be used in name-value pairs. When called from a script or the command line, this function allows to pass the first three parameters (Trials, Targets and Cost) as positional arguments (i.e., in order of appearance), where all remaining parameters must be passed via name-value pairs. Alternatively, all parameters (including the first three) can be passed via name-value pairs. Especially for machine learning, it is good practice to include full references in the documentation (these are being referred to in the omitted description).

Next, the definition of function arguments begins. The function arg_define allows for a special first parameter to describe how many of the arguments can be passed as positional arguments (i.e., by passing values in order of appearance); here, either 0 or 3 parameters can be passed positionally (as described earlier). Currently, only values of the form [0 x] are allowed, but more flexibility may be added in the future.

For any supervised learning function, the first two parameters must be called 'trials' and 'targets', and should not be reported in user interfaces, as follows:

The 'Cost' parameter has a special default value, which is being recognized by the BCILAB machine learning framework as denoting a range of possible values, out of which the optimal one should be determined via parameter search. Whenever a parameter in a plugin function defaults to search(...) or is specified by the user as search(...), the framework will try all possibilities and take the one which yields the best performance in a cross-validation. As this process can be extremely costly (computationally), such expressions should only be used as defaults when it is absolutely necessary to search over them - the user usually knows better how much time he/she wants to invest in learning a classifier. In the case of support vector machines, this is called the regularization parameter, and searching for it via cross-validation is a core ingredient of the algorithm.

The next two parameters are standard multi-option strings.

The following parameter is another search parameter; if multiple parameters need to be searched, BCILAB will try all possible combinations (implying combinatorial running time). In some cases it is practical for the user to just make an educated guess and learn a model with it - if it performs sufficiently well, no costly search optimization will be necessary. However -- when searching manually for optimal parameters (or methods, in fact), treat the results with extreme care, since the manual search procedure is prone to producing systematically biased (towards the positive) results, if the results are noisy (which they are). Automatic parameter search does not have this bias (which is why it is so expensive to compute).

Five misc parameters follow, of which the first is type-constrained to be an integer. It can be very helpful to constrain argument types as much as is reasonable (to prevent mis-use), but using integers tends to lead to extremely hard-to-find bugs. The reason is that integer arithmetic in MATLAB is so counter-intuitive that one might consider it broken: most operations involving one or more integers produce integer-valued results (even if real numbers are also involved).

Next, the actual implementation of the method begins. To make the function usable without running it inside the machine learning framework of bcilab, it should be checked for any parameter defaulting to search(...) whether the search was actually expanded by the framework. If not (the function was called by itself), the parameter must be replaced by an educated guess, as below (except if the subsequent code can handle the search() format itself).

Most functions that are used for classification will contain a line similar to the following. Since target values are not necessarily 0,1,2,3 but can be anything (e.g. -3.4), the unique target values must be obtained.

classes = unique(targets);

Most machine learning plugins will make use of an external library, among others for performance reasons (in the case of this plugin, the library LIBLINEAR is used to perform the actual work), and the remaining code only adapts the parameter format appropriately. Dependencies should generally be placed in the directory "dependencies", as they can then be automatically loaded (or compiled, or downloaded) when the BCILAB toolbox is started (see dependencies.README therein for a brief guide). As binary code tends to fail on all but one platform, external dependencies are notoriously flaky when used in a cross-platform environment such as BCILAB. To guarantee stability nevertheless, it is good practice to provide native MATLAB fallback code for the remaining platforms (which would typically be slower, but would at least run), or to use a library which ships with pre-compiled binaries for all three platforms (Windows, Linux, Mac). In some cases (see dependencies/CStrAinBP*/fast_setdiff.m), an elaborate auto-compile script can be packaged with the library to compile it transparently on demand - this is, however, very tough, as the code needs to work with both modern versions of GCC (on Linux, very strict), mcc (on Win64, very low-end), and a variety of others.

The following code is the native MATLAB version. Here, it requires different parameters, as the behavior is not identical to the LIBLINEAR version (a function should behave identical across all platforms on which it runs, for a given parameter combination).

The following code section is a good example of code which supports only two classes, and which is (transparently) adapted to the multi-class case using the voting tools provided by BCILAB. It applies nearly unmodified to almost any other machine learning function which only supports binary classification. The follwing case calls the function with identical arguments, but chops up the trials and targets such that each call only involves two classes. During prediction, these two-class models are then combined via voting.

A key consideration in many machine learning methods (especially regularized ones) is to scale and center the data appropriately. If in doubt, always add these two lines. It is also possible to perform very customized scaling as a tool in a regularized framework, for certain types of algorithms (e.g. if the natural scale / importance of features is known and can be used). Recall that the scaling parameter was a declared as a user parameter (defaulting to 'std').

The following two lines map the data into a kernel space. This is a way to use linear methods to perform non-linear classification, but can be computationally quite costly if there are many trials involved (unless the more advanced "kernel trick" is used, which is, however, only applicable to certain types of methods). Kernelization yields remarkably powerful non-linear methods when used with strong and robust linear methods as a starting point. The three last parameters are all user-accessible.

    basis = trials;
    trials = utl_kernelize(trials,basis,kernel,gammap,polydegree);

Many of the methods that support only two classes also require that the target values are {0,1} or {-1,+1}; forgetting this can lead to very hard-to-find bugs.

Next, the actual machine learning code follows. This section solves a non-linear (but convex) optimization problem, using the CVX toolbox. CVX is very well supported across all platforms (and reasonably recent MATLAB versions), and is used extensively for fallback code throughout BCILAB. Because a large fraction of (efficiently solvable) machine learning problems can be formulated as such optimization problems, CVX is one of the methods of choice to implement fallbacks (or to prototype new algorithms). The problem formulation can be copied almost unmodified from any paper describing support vector machines.

Finally, the model (result) structure is built from the computed parameters.

The remaining code section does approx. the same computation, but using the LIBLINEAR library; it is therefore omitted here.

The learning function is concluded by storing the remaining variables in the model structure (whatever is needed to be able to make predictions).

model.sc_info = sc_info;
model.classes = classes;
model.variant = variant;
model.basis = basis;
model.kernel = kernel;
model.gammap = gammap;
model.degree = polydegree;

The prediction function is usually much more compact than the training function (and most prediction functions for different methods look very similar). The prediction function here is called ml_predictsvm.m. The function signature is essentially identical across all machine learning plugins:

As the training function made use of ml_trainvote, the following boilerplate code is necessary:

if isfield(model,)
    pred = ml_predictvote(trials,model);
else

The remaining code will operate in a two-class regime, if that was necessary for training. First, if the data was scaled during training, it must be scaled here, as well (which requires the previously learned scaling parameters to be part of the model). Likewise, if the data was kernelized in the learning function, it must be kernelized here, as well (which requires, among others, the original data points as basis vectors).

    trials = hlp_applyscaling(trials,model.sc_info);
    trials = utl_kernelize(trials,model.basis,model.kernel,model.gammap,model.degree);

Here, a distinction is made according to which code path was chosen during learning. In both cases, the most likely class label (in {0,1,2,...}) is estimated for the trials. These predictive maps are usually very compact, as they need to be very fast.

Finally, the class indices are translated into a discrete probability distribution. Even if a function does not support probabilistic outputs (SVMs do not natively handle probabilities, unless a "trick" is used), it is a good idea to generate such a distribution (then containing only 0's and one 1), since almost all higher-level evaluation code is being tested extensively with this format, and less extensively with the more primitive class labels (as basically no method actually outputs it).

In the following, a few code snippets from selected functions will be analzed to illustrate noteworthy points for the creation of machine learning plugins.

Weighted learners. The function ml_traingauss is an example for a function that optionally supports weights for every trial. To unify code in such functions, weights (which are packaged with trials) can be extracted in the following way from the parameters:

Matrix-shaped features. A special-purpose format for trial data are feature matrices instead of feature vectors. This may be practical for to impose certain types of groupwise sparsity assumptions. For example, the function ml_traindal supports row-sparse, column-sparse and low-rank regularization on the respective feature spaces. The code in the function is a good example of handling shape parameters appropriately, even if features are passed in vectorized form.

Built-in cross-validation. Some external machine learning tools support built-in parameter search (via cross-validation) on the trials passed to them. In many cases, this is orders of magnitude faster as if computed using the search() expressions. Thus, any such feature should be exploited to find parameters efficiently -- however, most such methods implement randomized cross-validation, which is not the ideal choice in BCI situations (since the trials come from signals, nearby trials are not statistically independent, but tend to be similar to each other so that any parameters learned with randomized CV may easily be biased towards overfitting). The function ml_trainhkl allows to pass a vector of possible regularization values, which are internally searched (using blockwise CV).

Randomized algorithms. Some algorithms are intrinsically randomized (e.g. certain clustering methods). These methods tend to give non-reproducible results (which is catastrophic in science, but also for mundane test cases). Therefore, the random seed used by these methods should first be backed up, replaced by a fixed (or user-accessible) value, and finally be restored. The restoration should be bulletproof, if possible (and in particular, should even execute if the user presses Ctrl+C), which is only possible since MATLAB 2008a. See the following code (from ml_traingmm) for how to support this robustly.

... randomized code

Using command-line tools. Many high-end machine learning packages support only command line interfaces, and constructing GUIs that expose every possible command line parameter in a human-readable form can be very tedious to write. See ml_trainsvmperf for an example of how to expose expressive parameter names and values to the user, but internally construct a command line from them, using argument declarations, hlp_rewrite, and sprintf.

# data[].attributes.attachment_link.description
Open Source Matlab Toolbox for Brain-Computer Interface research. Download the code from ftp://sccn.ucsd.edu/pub/bcilab. Extract the file to some folder that is not your EEGLAB folder. Start MATLAB (2008a+ required for the GUI), and reset you path to default settings by clicking File / Set Path / Default, and then Save.

# data[].attributes.attachment_link.readable_text
This part of the tutorial will demonstrate how to create an EEGLAB STUDY. For these datasets, the measures needed for data visualization, clustering and cluster visualization have already been computed, as described below in the following section, and are stored with the datasets - download the full studyset here (~450Mb). Another dataset often used in EEGLAB tutorial is the STERN dataset download the full studyset here (2.3Gb). Both datasets are downloadable using the FTP protocol which is outdated so let us know if you experience problems (we will soon migrate all downloads to HTTPS).

Description of 5-subject experiment for tutorial data: These data were acquired by Peter Ullsberger and colleagues from five subjects performing an auditory task in which they were asked to distinguish between synonymous and non-synonymous word pairs (the second word presented 1 second after the first). Data epochs were extracted from 2 sec before the second word onset to 2 sec after the second word onset. After decomposing each subject's data by ICA, two EEG datasets were extracted, one (Synonyms) comprising trials in which the second word was synonymous with the first one, and one (Non-synonyms) in which the second word was not a synonym of the first. Thus the study includes 10 datasets, two condition datasets for each of five subjects. Since both datasets of each subject were recorded in a single session, the decompositions and resulting independent component maps are the same across both conditions for each subject.

After downloading the sample STUDY data, unzip it in a folder of your choice (preferably in the 'sample_data' sub-folder of the EEGLAB release you are currently using; under Linux use the 'unzip' command). This will create a sub-folder '5subjects' containing several studysets. Then open a Matlab session and run >> eeglab.

Data organization

The tutorial data is already optimally organized. However, when creating a new STUDY, it is preferable to organize your data before running the STUDY functions. We suggest creating one directory or folder per subject, then storing the EEG dataset (".set") files for that subject in this folder. The STUDY functions will then automatically add measure files to the same subject directories.

We also advise modifying the default EEGLAB memory options. Selecting menu item File > Memory and other options will pop-up the following window:

Set the first option so that no more than one dataset is stored in memory at a time. Dataset data arrays are then read from disk whenever EEGLAB requires access to the data, but without cluttering memory. This will allow Matlab to load and hold a large number of dataset structures forming a large STUDY. Also, unset the third option so ICA component activations do not get recomputed automatically. This saves time as datasets are re-saved automatically during computation of measures and clustering of ICA components.

Creating a new STUDY structure and studyset

Exploratory Step: Creating a Studyset

To create a studyset, select menu item File > Create study > Browse for datasets. (Else, you may load into EEGLAB all the datasets you want to include in the study and select menu item File > Create study > Using all loaded datasets). A blank interface similar to the one described above will appear. In this window, first enter a name for the studyset ('N400STUDY'), a short description of the study ('Auditory task: Synonyms Vs. Non-synonyms, N400'). Here, we do not add notes about the study, but we recommend that you do so for your own studies. The accumulated notes will always be loaded with the study, easing later analysis and re-analysis. Click on the Browse button in the first blank location and select a dataset name. The interface window should then look like the following:

Warning: Under Matlab 7.x and Linux, do not copy and paste information into the edit boxes. Though it appears that this works, Matlab 7 does not correctly register such inputs. Enter all information manually (except the 'browsed' dataset names). This problem does not seem to arise under Windows. -> The fieldsSubject and Condition (below) have been filled automatically. This is because the datasets already contained this information. For instance, if you were to load this dataset into EEGLAB by selecting menu item Edit > Dataset info, you would be able to edit the Subject and Condition information for this dataset (as shown below). You may also edit it within the study itself, since dataset information and study dataset information may be different to ensure maximum flexibility. For instance, if you want one dataset to belong to several studies, but play different roles in each.

Note: Use the checkbox Update dataset information... to maintain consistency between dataset and studyset fields. However, if you check this option, datasets may be modified on disk by clustering functions.

Enter all datasets for all subjects in the STUDY, so that the STUDY creation gui looks like this:

After you have finished adding datasets to the study, press OK in the pop_study.m gui to import all the dataset information. We strongly recommend that you also save the STUDY as a studyset by filling in the bottom edit box in the gui, or by selecting the EEGLAB menu item File > Save study as after closing the pop_study.m window.

Important note: Continuous data collected in one task or experiment session are often separated into epochs defining different task conditions (for example, separate sets of epochs time locked to targets and non-targets respectively). Datasets from different conditions collected in the same session are assumed by the clustering functions to have the same ICA component weights (i.e., the same ICA decomposition is assumed to have been applied to the data from all session conditions at once). If this was not the case, then datasets from the different conditions must be assigned to different sessions.

KEY STEP 1: Loading Studysets

Either use the studyset created in the previous section or load another studyset. To load a studyset, select menu item File > Load existing study. Select the file N400.study in the folder 5subjects. After loading or creating a study, the main EEGLAB interface should look like this:

An EEGLAB STUDY (or study) contains descriptions of and links to data contained in one to many epoched datasets, for example a set of datasets from a group of subjects in one or more conditions of the same task, or performing different tasks in the same or different sessions. Other designs are possible, for instance a number of different task conditions from the same subject collected during one or more sessions. The term STUDY indicates that these datasets should originate from a single experimental STUDY and have comparable structure and significance. When in use, studyset datasets are partially or totally loaded into EEGLAB. They thus may also be accessed and modified individually, when desired, through the main EEGLAB graphic interface or using EEGLAB command line functions or custom dataset processing scripts.

In the EEGLAB gui (above), Epoch consistency indicates whether or not the data epochs in all the datasets have the same lengths and limits. Channels per frame indicates the number of channels in each of the datasets ( It is possible to process datasets with different numbers of channels). Channel location indicates whether or not channel locations are present for all datasets. Note that channel locations may be edited for all datasets at the same time (simply call menu item Edit > Channel locations). The Clusters entry indicates the number of component clusters associated with this STUDY. There is always at least one cluster associated with a STUDY. This contains all the pre-selected ICA components from all datasets. The Status entry indicates the current status of the STUDY. In the case above, this line indicates that the STUDY is ready for pre-clustering. Below, we detail what the STUDY terms "subjects", "conditions", "sessions", and "groups" mean.

To list the datasets in the STUDY, use menu item Study > Edit study info. The following window will pop up:

The top of the window contains information about the STUDY, namely its running name, the extended task name for the STUDY, and some notes. The next section contains information about the 10 datasets that are part of the STUDY. For each dataset, we have specified a subject code and condition name. We chose to leave the session and group labels empty, as they were irrelevant for this STUDY. (For this STUDY, there was only one subject group and data for both experimental conditions were collected in a single session, so the same ICA decomposition was used for both conditions). Uniform default values will be used by EEGLAB for those fields. The Components column contains the components for each dataset that will be clustered. Note that if you change the component selection (by pressing the relevant push button), all datasets with the same subject name and the same session number will also be updated (as these datasets are assumed to have the same ICA components).

Each of the datasets EEG structures may also contain subject, group, session, and condition fields. They do not necessarily have to be the same as those present in the STUDY. For example, the same dataset may represent one condition in one STUDY and a different condition in another STUDY.

In general, we prefer the dataset information to be consistent with the studyset information -- thus we check the first checkbox above.

The second checkbox removes all current cluster information. When cluster information is present, it is not possible to add or remove datasets and to edit certain fields (because this would not be consistent with the already computed clusters). Re-clustering the altered STUDY does not take much time, once the pre-clustering information for the new datasets (if any) has been computed and stored.

The third checkbox allows the STUDY to be saved (or re-saved) as a studyset (for example, MyName.std).

Both raw data and ICA component data may be processed in STUDY. Below we focus on processing component data. If you with to skip this part and only process raw data, jump to section on STUDY data visualization tools.

KEY STEP 2: Pre-selecting components for clustering.

Simply press the Select by r.v. (r.v. = residual variance) push button in the gui above. The entry box below will appear. This allows you to set a threshold for residual variance of the dipole model associated with each component.
Note: Using this option requires that dipole model information is present in each dataset. Use EEGLAB plug-in dipfit.m options and save the resulting dipole models into each dataset before calling the study guis. Otherwise, options related to dipole localization will not be available.

This interface allows specifying that components used in clustering will only be those whose equivalent dipole models have residual dipole variance of their component map, compared to the best-fitting equivalent dipole model projection to the scalp electrodes, less than a specified threshold (0% to 100%). The default r.v. value is 15%, meaning that only components with dipole model residual variance of less than 15% will be included in clusters. This is useful because of the modeled association between components with near 'dipolar' (or sometimes dual-dipolar) scalp maps with physiologically plausible components, those that may represent the activation in one (or two coupled) brain area(s). For instance, in the interface above, the default residual variance threshold is set to 15%. This means that only component that have an equivalent dipole model with less than 15% residual variance will be selected for clustering. Pressing OK will cause the component column to be updated in the main study-editing window. Then press OK to save your changes.

Editing STUDY datasets

Selecting an individual dataset from the Datasets menu allows editing individual datasets in a STUDY. Note, however, that creating new datasets or removing datasets will also remove the STUDY from memory since the study must remain consistent with datasets loaded in memory (here, however, EEGLAB will prompt you to save the study before it is deleted).

EEGLAB (v5.0b) also allows limited parallel processing of datasets of a STUDY in addition to computing clustering measures during pre-clustering. You may, for instance, filter all datasets of a STUDY. To do so, simply select menu item Tools > Filter data. You may also perform ICA decomposition of all datasets by running ICA individually on each of the datasets.

You may also select specific datasets using the Datasets > Select multiple datasets menu item and run ICA on all the datasets concatenated together (the ICA graphic interface contains a self-explanatory checkbox to perform that operation). This is useful, for example, when you have two datasets for two conditions from a subject that were collected in the same session, and want to perform ICA decomposition on their combined data. Using this option, you do not have to concatenate the datasets yourself; EEGLAB will do it for you.

# data[].attributes.attachment_link.description
This part of the tutorial will demonstrate how to create an EEGLAB STUDY. For these datasets, the measures needed for data visualization, clustering and cluster visualization have already been computed, as described below in the following section, and are stored with the datasets - download the full studyset here (~450Mb).

# data[].attributes.attachment_link.readable_text
Learning Matlab

The EEGLAB graphic interface is built on top of the powerful Matlab scripting language. Enjoying the full capabilities of EEGLAB for building macro commands and performing custom and automated processing requires the ability to manipulate EEGLAB data structures in Matlab. Because of time constraints, this wiki NOT provide an introduction to the Matlab scripting language. Instead users need to familiarize themselves with Matlab prior to the workshop. Users of Matlab 7: We recommend running the following demos and reading the following help sections.

In the Matlab help, you should perform the first 3 tutorials (Matlab 2018)

Getting Started with MATLAB

Language Fundamentals

Mathematics

Graphics (first section 2-D plot only)

Each section or demo (if read thoroughly) should take you about 40 minutes, for a total here of about 2 hours. We encourage you to read these sections over several days.

Installing EEGLAB and tutorial files

First download EEGLAB (30MB) which contains the tutorial dataset (also available here (4MB) - press the right mouse button and select 'Save link as' if strange characters appear).

When you uncompress EEGLAB you will obtain a folder named "eeglabxxxx" (note: current version number 'xxxx' will vary). Under Windows, Matlab usually recommends (although does not require) that you place toolboxes in the Application/MatlabRxxxx/toolbox/ folder (note: this name should vary with the Matlab version 'xxxx'). In Linux, the Matlab toolbox folder is typically located at /usr/local/pkgs/Matlab-rxxxx/toolbox/ and in Mac in "/Application/MATLAB_Rxxxx". You may also place the folder anywhere else on your path.

Starting Matlab and EEGLAB

Here we will start Matlab and EEGLAB. Note that paragraphs that begin with KEY STEP are necessary to what follows in the tutorial. Paragraphs that begin with Exploratory Step are written to help you explore various EEGLAB features.

KEY STEP 1: Start Matlab.

WINDOWS: Go to Start, find Matlab and run it.
Mac Option 1: Start from the Matlab icon in the dock or in the application folder.
Linux: Open a terminal window and type "matlab" and hit enter.

KEY STEP 2: Switch to the EEGLAB directory (folder).

You may browse for the directory by clicking on the button marked "..." in the upper right of the screen.

This opens the window below. Double-click on a directory to enter it. Double-clicking on ".." in the folder list takes you up one level. Hit OK once you find the folder or directory you wish to be in. Alternatively, from the command line use "cd" (change directory) to get to the desired directory.

KEY STEP 3: Start EEGLAB.

Type "eeglab" at the Matlab command line and hit enter. EEGLAB will automatically add itself to the Matlab path.

The blue main EEGLAB window below should pop up, with its seven menu headings: File, Edit, Tools, Plot, Study, Datasets, Help arranged in typical (left-to-right) order of use.

Exploratory step (optional): Add EEGLAB to the Matlab path

You may want to add the EEGLAB folder to the Matlab search path so the next time you start Matlab, you will be able able to open EEGLAB directly. If you started Matlab through its graphical interface, go to menu item file and select set path. This will open the following window.

Or, if you are running Matlab from the command line, type "pathtool" and hit return; this will also call up this window. Click on the button markedAdd folder and select the folder "eeglabxxxxx", then hit OK (EEGLAB will take care of adding its subfolder itself). Hitsave in the pathtool window/ This will make the EEGLAB call-up function "eeglab" available in future Matlab sessions. Note that if you are installing a more recent version of EEGLAB, it is best to remove the old version from the Matlab path (select, then hit Remove) to avoid the possibility of calling up outdated routines. It is preferable NOT to add the "eeglab" path with its subfolder and let eeglab manage paths (when you start "eeglab", it automatically adds the path it needs.

Opening an existing dataset

KEY STEP 4: Load the sample EEGLAB dataset.

Select menu item File and press sub-menu item Load existing dataset.

In the rest of the tutorial, we will use the convention: Menu_item > Submenu_item to refer to a menu selection (e.g., here select submenu item Load existing dataset under the top-level File submenu).

In Unix, the following window will pop up (the aspect ratio of this window may differ in Windows and MacOS):

To learn how to create EEGLAB datasets from your own data, see the tutorial on Importing data and data events.

Select the tutorial file "eeglab_data.set" which is distributed with the toolbox, located in the "sample_data" folder of EEGLAB (also available here - Press the right mouse button and select Save link as" if strange characters appear'). Then press Open.

When the dataset is loaded by EEGLAB, the main EEGLAB window shows relevant information about it -- its number of channels, sampling rate, etc...

Exploring event values

In the tutorial dataset, the EEG.event structure fields type, position, and latency are specified for each of the 154 events marked in the dataset.

Exploratory Step: Editing Event Values.

Select menu Edit > Event Values to call up a window where we can read and edit these values:

We will now briefly describe the experiment that produced the sample dataset to motivate the analysis steps we demonstrate in the rest of the tutorial.

Sample experiment description

In this experiment, there were two types of events "square" and "rt"; "square" events correspond to the appearance of a filled disk in a green colored square in the display and "rt" to subject's button press. The disk could be presented in any of the five squares on the screen, one with green outline and the others blue, distributed along the horizontal axis. Here we only considered presentation on the left, i.e. position 1 and 2 as indicated by the position field (at about 5.5 degree and 2.7 degree of horizontal visual angle respectively). In this experiment, the subject covertly attended to a selected location on the computer screen (the green square) and responded with a quick thumb button press only when the disk was presented at this location. They were to ignore circles presented at the unattended locations (the blue squares). To reduce the amount of data required to download and process, this dataset contains only targets (i.e., "square") stimuli presented at the two left-visual-field attended locations for a single subject. For more details about the experiment see Makeig, et al., Science, 2002, 295:690-694.

When using events in an EEGLAB dataset, there are two required event fields: type and latency, plus any number of additional user-defined information fields. It is important to understand here that the names of the fields were defined by the user creating the dataset, and that it is possible to create, save, and load as many event fields as desired.

Note also that type and latency (lowercase) are two keywords explicitly recognized by EEGLAB and that these fields must be defined by the user unless importing epoch event information (Note: If only field latency is defined, then EEGLAB will create field type with a constant default value of 1 for each event). Unless these two fields are defined, EEGLAB will not be able to handle events appropriately to extract epochs, plot reaction times, etc. The Importing data tutorial explains how to import event information and define fields.

About this dataset

Here we describe how to edit and view the text field which describes the current dataset, and is stored as a part of that dataset.

Exploratory Step: Editing the Dataset Description.

Select Edit > About this dataset. A text-editing window pops up which allows the user to edit a description of the current dataset. For the sample data, we entered the following description of the task. Press SAVE when done.

Scrolling through the data

Here we learn how to visualize and to reject selected portions of continuous EEG channel data.

Exploratory Step: Scrolling data.

To scroll through the channel data of the current dataset, select Plot > Channel data (scroll). This pops up the eegplot() the scrolling data display window below. Note that this sample data file contains as-if-continuous EEG data. To reduce (your) download time, this "pseudo-continuous" EEG dataset was actually constructed by concatenating eighty separate three-second data epochs (which we will later separate again). This explains some sudden jumps you may see in some data channels.

To the right of the plot window is the vertical scale value (and its unit, microvolts) that indicates the "amplitude" of the vertical scale bar. In this case, that value is 80 (microvolts). The same value is also shown in the lower right-hand edit box, where we can change it as explained below.

Exploratory Step: Voltage Scale.

Change the "Scale" edit-text box value to about 50, either by repeatedly clicking on the "-" button or by editing the text value from the keyboard, and press the Enter key to update the scrolling window.

Exploratory Step: Adjusting the width of the scrolling time window.

To adjust the time range displayed (i.e., the horizontal scale), select the eegplot() menu item Settings > Time range to display, and set the desired window length to "10" seconds as shown below,

Then press OK to make the indicated change take effect.

Exploratory Step: Number of Channels to Display.

To adjust the number of channels displayed, select eegplot() menu item Settings > Number of channels to display and enter the desired number of channels to display in the screen (for instance "16").

Reducing the number of channels shown will return a scrolling eegplot() window with a vertical channel-set slider to the left of the plot. Use it to scroll the display (vertically) through all the channels.

Exploratory Step: Zoom.

To zoom in on a particular area of a data window, select eegplot() menu item Settings > Zoom off/on > Zoom on. Now using your mouse, drag a rectangle around an area of the data to zoom in on it. The scrolling window may now look similar to the one below. Click the right button on the mouse to zoom out again. Use menu item Setting > Zoom off/on > Zoom off to turn off the zoom option.

Exploratory Step: Grid Lines.

To display horizontal (x) and vertical (y) grid lines on the data, select Display > Grid > X grid on or Display > Grid > Y grid on. Repeat this process to turn off either set of grid lines.

The eegplot() window also allows you to reject (erase) arbitrary portions of the continuous data. The function eegplot() can be called from both menu items Plot > Scroll data and Tools > Reject continuous data using the REJECT button on the bottom right corner.

Exploratory Step: Rejecting Data.

Close the current eegplot() window and select item Tools > Reject Continuous Data by eye in the main EEGLAB window. A warning message appears; click on continue. To erase a selected portion of the data, first drag the mouse (holding down the left mouse button) horizontally across the time region of interest to mark it for rejection. If you like, mark multiple regions for rejection in this way. To undo a rejection mark, click once on the marked region.

Note: Zooming must be disabled to select a portion of the data.

Now, to erase the marked data regions, click the (lower right) REJECT button (above). A new dataset will be created with the marked regions removed. Note: EEGLAB will also add new "rejection boundary" events to the new dataset event list and will link these events to added "rejection boundary" events in a backup copy of the experiment event record contained in the EEG.urevent structure. Rejection boundary events insure that subsequent epoch selections do not cross non-contiguous rejection boundaries. For more details about rejecting continuous data regions and data epochs, see the data rejection tutorial.

Click OK (below) to create the new dataset with the marked data portions removed.

Press OK to create the new dataset. The EEGLAB main window now looks like:

Since we only performed this rejection for illustrative purposes, switch back to the original dataset by selecting main window menu item Datasets > Dataset 1: Continous EEG data.

Exploratory Step: Deleting a Dataset from Memory.

To delete the newly created second dataset, select File > Clear dataset(s) or Edit > Delete dataset(s) and enter the dataset index, "2" as shown below, and press OK.

The second dataset will now be removed from the EEGLAB/Matlab workspace. (Note: It is not necessary to switch back to the first dataset before deleting the second. It is also possible to delete several datasets at once from this window by entering their indices separated by spaces.)

# data[].attributes.attachment_link.description
The EEGLAB graphic interface is built on top of the powerful Matlab scripting language. Enjoying the full capabilities of EEGLAB for building macro commands and performing custom and automated processing requires the ability to manipulate EEGLAB data structures in Matlab. Because of time constraints, this wiki NOT provide an introduction to the Matlab scripting language.

# data[].attributes.attachment_link.readable_text
Since there was no public database for EEG data to our knowledge (as of 2002), we had decided to release some of our data on the Internet. We have kept the page as it seems to still be usefull (if you know any database or if you want us to add a link to data you are distributing on the Internet, send us an email at arno sccn.ucsd.edu).

Data originally distributed on this page
On this page was a collection of 32-channel data from 14 subjects (7 males, 7 females) acquired using the Neuroscan software. Subjects are performing a go-nogo categorization task and a go-no recognition task on natural photographs presented very briefly (20 ms). Each subject responded to a total of 2500 trials. Data is CZ referenced and is sampled at 1000 Hz (total data size is 4Gb; more details are given later). The original distribution is available here for historical purposes. The current data is availlable on Openneuro.

The OpenNeuro and NEMAR databases

OpenNeuro is well known data archive created by Poldrack and his team at Stanford University. OpenNeuro is a free and open platform that allows researchers to upload and share neuroimaging data. Submitted datasets can then be analyzed by anyone who logs in. OpenNeuro has been designated by the NIMH as a repository for data collected from BRAIN Initiative projects as well as other types of human neuroimaging data; however, to date workflows only exist for fMRI data. This means that even if other types of brain scans were uploaded to OpenNeuro, there is no infrastructure in place for data analysis. We invite you to explore Partnering with Stanford University, we have received Datasets in Matlab (from the EEG BIDS formatted datasets available on OpenNeuro.

$4.4M from NIMH to create the Neuroelectromagnetic Data Archive and Tools Resource (NEMAR). Researchers will create the Neuroelectromagnetic Data Archive and Tools Resource at San Diego Supercomputer Center. The NEMAR platform is in its testing phase and will soon expand OpenNeuro capabilities to archive and visualize BIDS EEG dataset.

Other data available on the Internet
EEGLAB software tutorial) are Other EEG databases or datasets known to us are
Some datasets used in Brain Computer Interface competitions are also available at You may also look at a message ciculated on the EEGLABLIST that may point to other databases.

# data[].attributes.attachment_link.title
free EEG data database freely ERP data publicly available

# data[].attributes.attachment_link.description
Since there was no public database for EEG data to our knowledge (as of 2002), we had decided to release some of our data on the Internet. We have kept the page as it seems to still be usefull (if you know any database or if you want us to add a link to data you are distributing on the Internet, send us an email at arnosccn.ucsd.edu).

# data[].attributes.headline
Superhuman / optional add on / required to stay competitive

# data[].attributes.subject
Superhuman / optional add on / required to stay competitive

# data[].attributes.body
Differences between enhancement.
What might this look like in 15years
eg if you have enhanced reactions your car insurance is less.

# data[].attributes.body
Investors, marketing people, scientists

# data[].attributes.body
Biologically merged with the machine.

# data[].attributes.body
Shows us how we become enhanced.

# data[].attributes.body
BCI Enhancement becomes a necessity to compete effectively and we become dependent on it.
Then we can be cut of from it.
Then it becomes a source of power.

# data[].attributes.body
Does the machine afford the human, or the human afford the machine?

# data[].attributes.body
Parasitic machines

# data[].attributes.attachment_link.readable_text
Ad infinitum is a parasitical entity which lives off human energy. It lives untethered and off the grid. This parasite reverses the dominant role that mankind has with respect to technologies: the parasite shifts humans from "users" to "used".

Ad infinitum co-exists in our world by parasitically attaching electrodes onto the human visitors and harvesting their kinetic energy by electrically persuading them to move their muscles.

The only way a visitor can be freed is by seducing another visitor to sit on the opposite chair and take their place.

Being trapped in the parasite's cuffs means getting our muscles electrically stimulated in order to perform a cranking motion as to feed it our kinetic energy. This reminds us that, in the cusp of artificially thinking machines, we are no longer just "users"; the shock we feel in our muscles, the involuntary gesture, acknowledges our intricate relationship to uncanny technological realm around us.

Visitor's reactions to Ad Infinitum

Watch how the parasite gathers new hosts

Pedro & Robert demonstrate Ad Infinitum at "Byte-sized Artist Talks" at Science Gallery

Exhibition at Ars Electronica 2017

Opening night at Science Gallery Dublin (Humans Need Not to Apply, Jan-May 2017)

Interview at Science Gallery Dublin with Luke Clancy from Culture File Podcast (audio).

Ad Infinitum in the Press

Artists left-to-right: Patrick Baudisch, Pedro Lopes, Alexandra Ion, Robert Kovacs and David Lindlbauer (not in photo).

Stand-alone & interactive installation: custom electronics, steel, battery, energy harvesting dynamos, motors, electrical muscle stimulation units, micro-controllers, pressure sensors, electrodes, CNC'd acrylic, copper tape. Production date: 2016.

Background / Artistic framing:

Ad infinitum is a machine on top of a human. While interacting with it you experience the shift from user to used, this question arose from the artists' own line of research in the field of human-computer interaction. In their research, instead of envisioning technological dystopias based on the divide between human and machine, their working prototypes demonstrate the interface and the human becoming closer, blurred, increasingly physical and intimate.

Acknowledgments

Astrid Thomschke, Roland Fischer, Hasso Plattner Institute & VIDA16 Incentive Award.

Photo Credits & Presskit

All pictures in this webpage were taken by Arthur Silber, 2017.

Here you can get hi-res imagery of our piece (as a .zip file).

# data[].attributes.attachment_link.title
Ad Infinitum: a parasite [Ars Electronica'17] - pedro lopes research

# data[].attributes.attachment_link.description
Exhibited at: Przemiany Festival, Copernicus Science Center Warsaw [13-16 September 2018] World Economic Forum, Center for the Fourth Industrial Revolution in San Francisco [December 2017 - May 2018] Ars Electronica [7-11 September 2017] Science Gallery Dublin [February 2017 - May 2017] Natural History Museum Bern [9th September 2016] Ad infinitum is a parasitical entity which ...

# data[].attributes.body
Machine uses you. Loss of agency

# data[].attributes.headline
from“Know Thyself” to “Construct Thyself.”

# data[].attributes.subject
from“Know Thyself” to “Construct Thyself.”

# data[].attributes.headline
In one demonstration, he implanted a stimoceiver in a macaque who terrorized his cage-mates. Delgado installed a lever in the cage that, when pressed, would activate the stimoceiver in the bully and pacify him. A female in the cage soon figured out the lever’s significance and yanked it often and with gusto. “The old dream of an individual overpowering the strength of a dictator by remote control has been fulfilled, at least in our monkey colonies,”

# data[].attributes.subject
In one demonstration, he implanted a stimoceiver in a macaque who terrorized his cage-mates. Delgado installed a lever in the cage that, when pressed, would activate the stimoceiver in the bully and pacify him. A female in the cage soon figured out the lever’s significance and yanked it often and with gusto. “The old dream of an individual overpowering the strength of a dictator by remote control has been fulfilled, at least in our monkey colonies,”

# data[].attributes.body
Pioneered the use of electrodes to stimulate the brain. Nobel Prize in 1949

# data[].attributes.attachment_link.readable_text
This article was most recently revised and updated by

Walter Rudolf Hess, (born March 17, 1881, Frauenfeld, Switz.-died Aug. 12, 1973, Ascona), Swiss physiologist, who received (with António Egas Moniz) the 1949 Nobel Prize for Physiology or Medicine for discovering the role played by certain parts of the brain in determining and coordinating the functions of internal organs.

Originally an ophthalmologist (1906-12), Hess turned to the study of physiology, becoming a research assistant first at the Physiological Institute at the University of Zürich in 1912 and then at the University of Bonn in 1915. In 1917 he was appointed professor of physiology and later director of the Physiological Institute (1917-51) at Zürich. He became interested in the study of the autonomic nervous system-those nerves originating at the base of the brain and extending throughout the spinal cord that control the automatic functions such as digestion and excretion. They also trigger the activities of a group of organs that respond to complex stimuli, such as stress.

Using fine electrodes to stimulate or destroy specific areas of the brain in freely moving conscious cats, Hess found that the seat of autonomous function lies at the base of the brain, in the medulla oblongata and the diencephalon (interbrain), particularly that part of the interbrain known as the hypothalamus. He mapped the control centres for each function to such a degree that he could induce the physical behaviour pattern of a cat confronted by a dog simply by stimulating the proper points on the animal's hypothalamus. He also studied the mechanisms of goal-directed movements and established the concept of anticipatory motor control on posture to enable voluntary motor action. Among Hess's books is The Biology of Mind (1964).

Kara Rogers, Senior Editor.

Learn More in these related Britannica articles:

# data[].attributes.attachment_link.description
Walter Rudolf Hess, Swiss physiologist, who received (with António Egas Moniz) the 1949 Nobel Prize for Physiology or Medicine for discovering the role played by certain parts of the brain in determining and coordinating the functions of internal organs. Originally an ophthalmologist (1906-12),

# data[].attributes.body
pioneered electrically stimulating neural tissue with implanted electrodes

# data[].attributes.attachment_link.readable_text
"The Forgotten Era of Brain Chips," published in Scientific American in October 2005, has provoked as much interest as anything I've ever written. It focuses on Jose Manuel Rodriguez Delgado, a pioneer in brain-stimulation research. I keep hearing from journalists and others wanting more information on Delgado, whom I interviewed in 2005 and who died in 2011. Delgado fascinates conspiracy theorists, too. An article on Infowars.com describes him as a "madman" who believed that "no human being has an inherent right to his own personality." Given widespread interest in and misinformation about Delgado, whose work prefigures current research on brain implants (see "Further Reading"), I'm posting an edited version of my 2005 article. --John Horgan

Once among the world's most acclaimed scientists, Jose Manuel Rodriguez Delgado has become an urban legend, whose career is shrouded in misinformation. Delgado pioneered that most unnerving of technologies, the brain chip, which manipulates the mind by electrically stimulating neural tissue with implanted electrodes. Long a McGuffin of science fictions, from The Terminal Man to The Matrix, brain chips are now being tested as treatments for epilepsy, Parkinson's disease, paralysis, depression, and other disorders.

In part because it was relatively unencumbered by ethical regulations, Delgado's research rivaled and even surpassed much of what is being done today. In 1965, The New York Times reported on its front page that he had stopped a charging bull in its tracks by sending a radio signal to a device implanted in its brain. He also implanted radio-equipped electrode arrays, which he called "stimoceivers," in dogs, cats, monkeys, chimpanzees, gibbons, and humans. With the push of a button, he could evoke smiles, snarls, bliss, terror, hunger, garrulousness, lust, and other responses.

Delgado described his results in hundreds of peer-reviewed papers and in a widely reviewed 1969 book, but these are rarely if ever cited by modern researchers. One reason may be that in 1974 he left Yale, his base for more than two decades, to return to Spain, his birthplace. He was at the peak of his career. A cover story in The New York Times Magazine had just hailed him as the "impassioned prophet of a new 'psychocivilized society' whose members would influence and alter their own mental functions."

In Madrid, Delgado switched his focus to non-invasive brain-stimulation methods, anticipating current exploration of techniques such as transcranial magnetic stimulation. Because he published primarily in Spanish journals, his work fell into obscurity. Brain-implant studies back in the U.S. became engulfed in ethical controversies. Grants dried up, researchers drifted to other fields, and little work was done until the recent revival. Meanwhile, conspiracy theorists began depicting Delgado as a fascist who sought to enslave people by means of neurotechnology.

In 2004, Delgado and his wife Caroline--a Yale administrator's daughter whom he married in 1956, when she was 22 and he was 41--moved to San Diego, California, to be closer to their son and daughter. Delgado recently allowed me to visit him at his elegant, one-story home. Over the course of two days, Delgado, who at 89 is charming, courtly, and keen of mind, told me his life story and vigorously defended his legacy. He describes himself as a libertarian and pacifist, whose goal as a scientist was to liberate us from our biology, and especially from mental illnesses and violent aggression.

Delgado understands why many people are offended by research into the physiological processes that underpin thoughts and behavior. They think, "How is it possible that I am mainly the result of chemicals in the brain! This is very distasteful, I don't like this at all!" But if the research leads to better treatments for brain disorders, he says, "this is wonderful."

Born in Ronda, Spain, in 1915, Delgado has been dogged by rumors that he supported the fascist regime of Francisco Franco. Someone at a scientific conference threw a pie in Delgado's face for this alleged offense. But when Franco led a military coup against the Republican government of Spain in 1936, Delgado, then a medical student, enlisted in the Republican army and served as an officer in the medical corp. After Franco's fascist troops crushed the Republicans, Delgado spent five months in prison before being released to resume his medical studies.

Delgado originally intended to become an eye doctor, like his father. But a stint in a physiology laboratory--plus exposure to the writings of the great Spanish neuroscientist Ramon y Cajal--left him entranced by "the many mysteries of the brain. How little was known then. How little is known now!" Delgado was fascinated by experiments by Swiss physiologist Walter Rudolph Hess. Beginning in the 1920s, Hess had demonstrated that he could elicit behavioral responses such as rage, hunger, and sleepiness in cats by electrically stimulating specific regions of their brains with wires.

After earning an M.D. and doctorate in physiology from the University of Madrid, Delgado joined its physiology laboratory, where he carried out brain-stimulation experiments on cats, dogs, and primates. In 1946, he won a fellowship at Yale, and in 1950 he accepted a permanent position in its department of physiology.

The department was headed by John Fulton, who played a crucial role in the history of psychiatry. In a 1935 lecture in London, Fulton reported that destroying the prefrontal lobes of a violent, "neurotic" chimpanzee made her calm and compliant. In the audience was Portuguese psychiatrist Edgar Moniz, who started performing lobotomies on psychotic patients and claimed excellent results. After Moniz won a Nobel Prize in 1949, lobotomies became an increasingly popular treatment for mental illness.

Initially shocked that his method of pacifying a chimpanzee had been applied to humans, Fulton later became a proponent of psychosurgery. Delgado never shared his mentor's enthusiasm. "I thought Fulton and Moniz's idea of destroying the brain was absolutely horrendous," Delgado recalls. He felt it would be "far more conservative" to treat mental illness by applying electrical-stimulation methods pioneered by Hess, who shared the 1949 Nobel Prize with Moniz. "My idea was to avoid lobotomy," Delgado says, "with the help of electrodes implanted in the brain."

One key to Delgado's scientific success was his talent as an inventor. A Yale colleague called him a "technological wizard." In his early experiments, wires ran from the implanted electrodes through the skull and skin to bulky electronic devices that recorded data and delivered electrical pulses. This set-up restricted subjects' movements and left them prone to infections. Delgado thus designed radio-equipped stimoceivers as small as quarters, which could be fully implanted in subjects. A battery pack strapped to the head or worn around the neck supplied the power transdermally. Delgado also invented implantable "chemotrodes" that could release precise amounts of drugs directly into the brain.

In 1952, Delgado co-authored what he claims is the first peer-reviewed paper describing deep brain stimulation of humans. Over the next two decades, he implanted electrodes in some 25 subjects. Most were schizophrenics and epileptics at the now-defunct State Hospital for Mental Diseases in Howard, Rhode Island, where Delgado's occasional collaborator Hannibal Hamlin was a staff psychiatrist.

One striking reaction to stimulation was pleasure and sexual arousal. A 36-year-old female epileptic, whose behavior was normally "quite proper," responded to stimulation by "giggling and making funny comments" and flirting with researchers. A sullen 11-year-old epileptic boy became chatty and friendly when stimulated. "Hey! You can keep me here longer when you give me these," he exclaimed. He also announced, "I'd like to be a girl."

The therapeutic benefits were mixed, however, and Delgado turned away more patients than he treated. One was a young woman whose parents had committed her to a mental hospital because she was so violent and promiscuous. Both the parents and the daughter herself pleaded with Delgado to operate on her, but he refused, saying that electrical stimulation was too unreliable. He achieved his best results treating people afflicted with chronic pain, including a man injured in an automobile accident. His pain had resisted drug treatment, but the stimoceiver relieved both his pain and the depression it had caused, so much so that he could return to work.

Delgado seems reticent discussing his experiments on humans. He is more enthusiastic recalling research on monkeys, chimpanzees, and gibbons, which he kept both at Yale and in open-air compounds in the Bahamas and New Mexico. He explored the effects of stimulation not only on individuals but also on groups, and he did not shy away from anthropomorphic interpretations.

In one demonstration, he implanted a stimoceiver in a macaque who terrorized his cage-mates. Delgado installed a lever in the cage that, when pressed, would activate the stimoceiver in the bully and pacify him. A female in the cage soon figured out the lever's significance and yanked it often and with gusto. "The old dream of an individual overpowering the strength of a dictator by remote control has been fulfilled, at least in our monkey colonies," Delgado wrote.

Delgado's fascination with violent behavior led him to conceive his famous bull experiment. "I thought: Which is the animal which is characterized by his aggressive behavior? The fighting bull!" A Spanish university supplied the funds for the experiment, and a bull-breeder in Cordoba supplied four bulls and a bullring. Working with his wife and several assistants over three days in 1963, Delgado tranquilized the bulls, fitted stereotactic frames over their skulls, and inserted stimoceivers into their brains. Delgado then stood in a bullring with the bulls and stimulated their brains by pressing buttons on a hand-held radio.

Asked if he took bull-fighting lessons for these sessions, Delgado responds in mock outrage, "What do you mean! I know how to fight a bull!" He grew up, after all, in Ronda, a bastion of bullfighting. He admitted that he was "frightened" when one bull charged him and stopped in response to his frantic button-pushing just a few feet away from him. As word spread in Cordoba about the strange activities at the ranch, a Spanish television crew and hundreds of others gathered to watch Delgado carry out tests with different bulls.

The episode received its most significant media coverage two years later, after Delgado showed slides from the bull experiment during a lecture at the Museum of Natural History in New York City. Afterwards, a New York Times reporter approached him. "He said, 'That was very interesting. Can I borrow your pictures?' I said, 'Sure, no problem.'"

The next day the Times published a front-page story, illustrated with a photograph of a bull just a few feet away from Delgado, about "the most spectacular demonstration ever performed of the deliberate modification of animal behavior through external control of the brain." Delgado was swamped with media inquiries about how he had created a real-life version of "Ferdinand," the gentle bull in a popular children's story.

Not everyone was impressed. Elliot Valenstein, a neurophysiologist at the University of Michigan, contended that stimulation had not inhibited the bulls' aggressive instinct, as Delgado had claimed, but had merely prevented it from charging straight ahead. In other words, the effect was strictly muscular. Valenstein offered a similar critique of an experiment in which Delgado claimed to have suppressed the "maternal instinct" of female monkeys. Asked now about Valenstein's objections, Delgado shrugs. His experiment, he says, "naturally could be interpreted in one way or the other," but he stands by his initial claims.

In terms of scientific significance, Delgado believes his experiment on a female chimpanzee named Paddy deserved more attention. Delgado programmed Paddy's stimoceiver to detect distinctive signals, called spindles, emitted by her amygdala. Whenever the stimoceiver detected a spindle, it stimulated another part of Paddy's brain, producing an "aversive reaction"--that is, a painful or unpleasant sensation. After two hours of this negative feedback, Paddy's amygdala produced 50 percent fewer spindles; the frequency dropped by 99 percent within six days. Delgado speculated that this "automatic learning" technique could be used to quell epileptic seizures, panic attacks, or other brain disorders.

In 1969, Delgado described brain-stimulation research and discussed its implications in Physical Control of the Mind: Toward a Psychocivilized Society. Ashley Montagu, a leading psychologist, called the book "an invaluable and authoritative analysis of the nature of human nature." Scientific American 's Phillip Morrison called it "a thoughtful, up-to-date account" of electrical-stimulation experiments but added that the research was "somewhat ominous." Indeed, many readers found Delgado's book-illustrated with photographs of monkeys, cats, and two young women with stimoceivers affixed to their skulls-horrifying.

Some of Delgado's rhetoric had an alarmingly apocalyptic tone. He declared that humanity was on the verge of "conquering the mind," and should shift its mission from the ancient dictum "Know Thyself" to "Construct Thyself." Used wisely, neurotechnology could help create "a less cruel, happier, and better man." His attempts to extol brain electrodes could be almost comically clumsy. He noted that female patients "have shown their feminine adaptability to circumstance by wearing attractive hats or wigs to conceal their electrical headgear."

The sponsorship of his experiments by the Office of Naval Research and the Air Force Aeromedical Research Laboratory (as well as several civilian agencies) raised eyebrows as well. Critics speculated that the military wanted to create cyborg soldiers that could kill on command, like the brainwashed assassin in The Manchurian Candidate. Delgado says his military sponsors never expressed interest in such applications. "At that time, the technology was very crude. The only thing we could do was to increase or decrease aggressive behavior, but not to direct aggressive behavior to any specific target. Maybe they expected that. I don't know."

The 1970 book Violence and the Brain, which explored potential applications of neurotechnologies, also attracted unwanted attention. The book was by Frank Ervin and Vernon Mark, brain-implant researchers at Harvard with whom Delgado briefly collaborated. (One of Ervin's students was Michael Crichton, whose first bestseller, The Terminal Man, about a bionic experiment gone awry, was inspired by the research of Ervin, Mark, and Delgado.)

Ervin and Mark suggested that neurotechnologies might quell the violent tendencies of African-Americans who rioted in inner cities. Brain-implant experiments of Robert Heath, a psychiatrist at Tulane University, provoked still more controversy. In 1972 Heath claimed that he had changed the sexual orientation of a male homosexual by stimulating his brain's septal region while he had intercourse with a female prostitute.

The fiercest critic of brain implants was psychiatrist Peter Breggin (who later focused on the dangers of psychiatric drugs). In testimony submitted into the Congressional Record in 1972, Breggin lumped Delgado, Ervin, Mark, and Heath together with proponents of lobotomies and accused them of seeking "a society in which everyone who deviates from the norm" will be "surgically mutilated." Quoting liberally from Physical Control, Breggin singled out Delgado as "the great apologist for Technological Totalitarianism." (Breggin's testimony is apparently the source of erroneous Internet claims that Delgado once testified before Congress.)

As Delgado's notoriety grew, strangers started accusing him of having implanted "stimoceivers" in their brains. One woman who made this claim sued Delgado and Yale University for $1 million, although he had never met her. In the midst of this brouhaha, the Spanish minister of health asked Delgado to help organize a new medical school in Madrid, and Delgado accepted. He and his family moved to Spain in 1974. Delgado insists he was not fleeing the controversy triggered by his research. The Spanish minister just gave him an offer too good to refuse. "I said, 'Could I have the facilities I have at Yale?' And he said, 'Oh no, much better!'"

In Spain Delgado shifted his focus to noninvasive neurostimulation methods--"because implanting electrodes, this is brutal," he says in a mock-growly voice. He invented a halo-like device and a helmet that could deliver electromagnetic pulses to specific neural regions. Testing the gadgets on animals and human volunteers, including himself and his daughter, Delgado discovered that he could induce drowsiness, alertness, and other states. He and his colleagues also had success treating tremors of Parkinson's.

This research, too, attracted controversy. The 1984 BBC documentary Opening Pandora's Box cited Delgado's work as evidence that the U.S. and Russia were developing methods for remotely modifying peoples' thoughts. Noting that the power and precision of electromagnetic pulses falls off dramatically with distance, Delgado doubts whether remote mind-control is possible. "This was science fiction, probably."

Delgado is not upset that modern scientists seldom mention his work. "Always there are antecedents in a field," he says. He doubts that modern brain-stimulation researchers avoid citing him because he is so controversial. Simple ignorance, he says, is a more likely explanation. After all, most modern databases do not include publications from his heyday in the 1950s and 60s.

Looking back over his career, Delgado acknowledges "a great defect: I have been able to do many important things, but I have not been able to follow in depth in any of these fields." He is thus thrilled that a new generation of scientists--equipped with increasingly sophisticated computers, electrodes, and brain-scanning technologies--is exploring paths that he trail-blazed. "In the near future," he says, "I think we will be able to help many human beings, especially with the non-invasive methods. Maybe invasive also."

Delgado has constructive criticism for his scientific descendants. He believes some neuroscientists are too obsessed with linking specific cognitive mechanisms to specific neural regions. Just because you can stimulate a spot in the motor cortex and get a finger to flex does not mean that region alone is responsible for moving the finger.

"People are trying to investigate: Where is the area of the brain essential to consciousness? That's a silly question," because consciousness and cognition in general almost certainly stem from the workings of the entire brain. "The whole brain is involved in everything!"

Delgado's appreciation of the brain's complexities leads him to doubt whether neurotechnologies will ever advance as far as some of us fear, or hope. "We know far more than 20 years ago, but there are so many things we don't know." He points out that neuroscientists have no idea how complex information is encoded in the firing of neurons. Moreover, brain stimulation can only modify skills and capacities that we already possess. It cannot make us instant experts in, say, quantum physics or French, as some critics have feared.

"Learning a language means slowly changing connections which are already there," Delgado explained. "I don't think you can do that suddenly." Delgado is even more doubtful that we will soon transcend our biology entirely, as the artificial-intelligence researcher Ray Kurzweil and others have prophesied. "In 300,000 years maybe," he says.

But Delgado looks askance at the suggestion of the White House Council of Bioethics and others that some scientific goals should not be pursued, particularly if they threaten to alter human nature. To be sure, technology "has two sides, for good and for bad," and we should do what we can to "avoid the adverse consequences." We should try to prevent potentially destructive technologies from being abused by authoritarian governments to gain more power, or by terrorists to wreak destruction.

But human nature, Delgado asserts, echoing one of the exhilarating and slightly scary themes of Physical Control, is not static but "dynamic," constantly changing as a result of our compulsive self-exploration. "Can you avoid knowledge?" Delgado asks. "You cannot! Can you avoid technology? You cannot! Things are going to go ahead in spite of ethics, in spite of your personal beliefs, in spite of everything."

Further Reading:
The Singularity and the Neural Code
Return of Electro-Cures Exposes Psychiatry's Weakness.

Much-Hyped Brain-Implant Treatment for Depression Suffers Setback.
Much-touted Deep-Brain-Stimulation Treatment for Depression Fails Another Trial
Patient in Failed Depression-Implant Trial Tells His Painful Story.
Why "Optogenetic" Methods for Manipulating Brains Don't Light Me Up Why Optogenetics Doesn't Light Me Up: The Sequel
Do Big New Brain Projects Make Sense When We Don't Even Know the "Neural Code"?

Why You Should Care about Pentagon Funding of Obama's BRAIN Initiative.

Two More Reasons Why Big Brain Projects Are Premature.

Artificial brains are imminent... not!

What's the Biggest Science News? We're Still Human, for Ill or Good.

What Are Science's Ugliest Experiments?

# data[].attributes.attachment_link.title
Tribute to Jose Delgado, Legendary and Slightly Scary Pioneer of Mind Control

# data[].attributes.attachment_link.description
"The Forgotten Era of Brain Chips," published in Scientific American in October 2005, has provoked as much interest as anything I've ever written. It focuses on Jose Manuel Rodriguez Delgado, a pioneer in brain-stimulation research. I keep hearing from journalists and others wanting more information on Delgado, whom I interviewed in 2005 and who died in 2011.

# data[].attributes.body
An emotional body is a less productive one

# data[].attributes.headline
Fragmentation - naked man triggers abstract patterns

# data[].attributes.subject
Fragmentation - naked man triggers abstract patterns

# data[].attributes.attachment_link.title
Fragmentation - a brainwave-controlled performance (EXTENDED PROMO)

# data[].attributes.attachment_link.description
With this piece Alberto Novello a.k.a. JesterN explores the fragmentation of personality of the "post-modern man". Exposed to aggressive stimulation and overwhelming data streams, he must make important choices to follow a rational "mind path" while his time quickly runs out. The performer, impersonating the post-modern man, wears an electro-encephalographic headset which detects his mind activity. The analysis of its output reveals the power of the performer's three thoughts which are used to move the pacman in the maze. Music is generated form the position of the pacman inside the maze and visuals are generated from the music. The time and structure of the composition is thus entirely determined by the choices and concentration of the performer.

# data[].attributes.body
INTIMACY & BIG DATA: in an online kiss, this intimacy is influenced and shaped by technologies, institutions and social processes. Now when our embodied private kiss data are to be quantified, on what data design do we validate this interaction? Who is responsible for and who will benefit from our quantified kisses?

# data[].attributes.attachment_link.readable_text
E.E.G KISS

Karen Lancel, Hermen Maat, 2016

Can I kiss you online? How does your kiss feel in E.E.G. data? Can we transfer a kiss and it's intimacy online? Can we measure a kiss and what kissers feel together? Do we want to save our private kisses in a transparent database - to be used by others?

In E.E.G. KISS the artists investigate how a kiss can be translated into bio-feedback data. They deconstruct the kiss, to reconstruct a new synesthetic kissing ritual. In a Global Kiss-In, through feeling, seeing, hearing, touching all participants together share a kiss. The artists: "Tele-presence technologies extend our bodies beyond biological boundaries in time and space, but they prevent us from touching. In a poetic, electric environment for kissing and measuring, for synchronizing and merging, we research a shared neuro-feedback system for networked kissing."

Performance installation In performances and live kissing experiments with Brain Computer Interfaces, visitors are invited to kiss. While kissing and wearing E.E.G. headsets, their brainwaves are measured and visible as E.E.G. data. A floor projection encircles the kissers with the real time streaming E.E.G. data, as an immersive data scape. A soundscape is generated by the Brain Computer Interface, which translates the real time E.E.G. data of 'kissing brains' into a algorithm for a music score: an E.E.G. KISS symphony. The public around is part of the kiss, of the sound and of the immersive E.E.G.-data-visualization; both as an aesthetic experience as well as based on acts of kissing resonating when mirrored in the brain.

How does your kiss feel in E.E.G. data? In EEG KISS, data are researched as 'Co-Actors' shaping our intimate relations. The artists: "In a participatory process of sense-making, we invite participants to give meaning to the very abstract, sometimes mystifying E.E.G. data-visualization of their kisses. Instead of scientific interpretation and validation, people who kissed interprete the data-visualization based on their shared memories of kissing and on imagination. Often the kisses are remembered as intimate processes of 'co-creation' and the data are perceived as 'A portrait of our kiss'." Share your private kiss Each unique E.E.G. KISS visual data sequence is saved in a database, and can be printed as an E.E.G. KISS Portrait. Each E.E.G. KISS soundscape is saved in a public database on the website; to be downloaded and shared. The soundscape is developed with Tijs Ham at STEIM Amsterdam.

INTIMACY & BIG DATA: critical reflections The artists: "A kiss is an obvious case of intimate, emotional interaction, based on bio synchronizing, spatial nearness, touch, sight, fluids, smell, endurance. But in an online kiss, this intimacy is influenced and shaped by technologies, institutions and social processes. Now when our embodied private kiss data are to be quantified, on what data design do we validate this interaction? Who is responsible for and who will benefit from our quantified kisses?

Can we trust our own E.E.G. Kiss data? Or should we rather protect our intimacy? In E.E.G. KISS we do not protect our intimate, private data. Instead, we create with these data a new hybrid, relational ritual allowing for public intimacy. Rather than focussing on the privacy of the kiss intimacy, we focus on how intimacy is embedded in publicness and public cultural negotation. In communal intimate orchestrations, 'kissers' and spectators witness and share their perception of embodied, tele-matic kissing. Instead of looking for private prosthaetic interfaces for networked touch, we focus on mirror processes, brain interface and shared neuro-feedback systems. In this way, we aim to create a shared sensitive public space, response-ability for the power of synchronizing through touching, watching, breathing, kissing, sharing presence - in today's merging realities. Worldwide, we invite our audiences for this ungoing artistic research, in hosted performances, installations, lectures, collaborations, workshops.

Art, Science & Technology E.E.G. KISS emerges from the artistic research Shared Senses, further conducted at Delft University of Technology in the context of Lancel's PhD trajectory (Promotor: Prof. dr. Frances Brazier). In Meeting Spaces and Meeting Rituals the artists deconstruct automated control technologies (surveillance, social media, brain computer interfaces, quantifying biometric technologies) to rethink and inspire sensitive relations based on intimacy, tacit knowledge, digital synesthesia, bio-synchronisation, sensory and aesthetic perception. In EEG KISS, artistic experiments are conducted for designing reflection on BCI mediated social relations. At the same time, these experiments propose a future vision on orchestration of BCI mediated ,social syntheses. Lancel/Maat propose that participants experimentally kiss each other to connect with observers and thus be part of a 'communal neuro feedback system for kissing'. The familiar relation between 'who you kiss and who is being kissed, what you see and what you hear' is disrupted, for a new reflective synthesis.

In collaboration with and generous support: Mondriaan Foundation, STEIM Amsterdam, EYE Film Institute Amsterdam, Waag Society Amsterdam AILlab, Angewandte Innovation Lab University of of Applied Arts Vienna Artists-in-residency TASML - (Tsinghua University Art and Science Media Laboratory Beijing), Tsinghua University Beijing Neuro-engineering lab, University of of Applied Arts Vienna, Digital Synesthesia Group, University for Technology, Delft / Participatory Systems Initiative UvA University of Amsterdam - Neuro-aesthetics and Neuro-cultures research group NWO, The Netherlands Organisation for Scientific Research, TNO (Netherlands Organisation for Applied Scientific Research). Baltan Laboratories Eindhoven, Fourtress Eindhoven, Holst Centre Eindhoven (sponsor E.E.G. headsets IMEC) Fourtress.nl Eindhoven (sponsor end development E.E.G.KISS software) Eagle Science Amsterdam

source:
Karen Lancel
http://www.lancelmaat.nl/work/e.e.g-kiss/

# data[].attributes.attachment_link.description
Karen Lancel, Hermen Maat, 2016 Can I kiss you online? How does your kiss feel in E.E.G. data? Can we transfer a kiss and it's intimacy online? Can we measure a kiss and what kissers feel together? Do we want to save our private kisses in a transparent database - to be used by others?

# data[].attributes.body
Eunoia II

# data[].attributes.attachment_link.description
http://www.wired.com/2014/11/watch-artist-control-pools-water-brainwaves/

http://thecreatorsproject.vice.com/blog/artist-manipulates-48-pools-of-water-with-her-mind
http://www.wired.com/2014/11/watch-artist-control-pools-water-brainwaves/

I have always believed that human emotions come with corresponding waves of energy that we carry within. When I am happy or sad there is an indescribable energy that somehow resonates in others. They feel my vibe, as if my energy is echoing off them. That is why I started “Eunoia” and “Eunoia II” in an attempt to create an audio-visualization of my emotional states. These performances have been therapeutic for me, providing a means of emptying my mind of thoughts.

For “Eunoia II”, I am using the emotional values (excitement, engagement, meditation, frustration, boredom) picked up by the EEG headset, which then gets translated into sound waves that create vibrations in the pools of water placed atop speakers.

Throughout the performance of “Eunoia II”, the intensity of my feelings at the time are mirrored in the intensity of the sound in terms of volume, pitch, feedback, speed, and the panning of the sound output. The result was that the water responded in real-time creating different formations of ripples and droplets in unpredictable patterns.

“Eunoia II” is comprised of 48 speakers with metal plates in various sizes, all containing pools of water. The number 48 symbolizes philosopher Baruch Spinoza’s definitions of 48 different emotions. In his book Ethics, he describes emotions as states of mind and body related to feelings and says that all emotions are derived from three primary emotions: joy, pain, and desire.

# data[].attributes.headline
Mind Art: Disabled people make wonderfully abstract paintings by using their mind to blow up balloons of paint

# data[].attributes.subject
Mind Art: Disabled people make wonderfully abstract paintings by using their mind to blow up balloons of paint

# data[].attributes.body
The project asked participants to recall traumatic events from their past. They were asked to emote anger, and other primary emotions. Each participant was wired to EEG and EKG sensors and monitored

# data[].attributes.attachment_link.readable_text
An interesting sci-art collaboration between University of Calgary researchers and artists Alan Dunning and Paul Woodrow, attempting to visualize thought in 3D space. They completed a number of projects under the umbrella of the Einstein's Brain Project; this one titled The Shapes of Thought.

The project asked participants to recall traumatic events from their past. They were asked to emote anger, and other primary emotions. Each participant was wired to EEG and EKG sensors and monitored [for as long as 8-14 hours]. The resulting information was visualized as still images using Iris Explorer and visualized in realtime, interactive space using specially developed data acquisition modules.

Other images on the site include that of a man repeatedly asked to recall an incident in which he was severely injured, including a period of agitation, and couple of animations.

# data[].attributes.attachment_link.description
An interesting sci-art collaboration between University of Calgary researchers and artists Alan Dunning and Paul Woodrow, attempting to visualize thought in 3D space. They completed a number of projects under the umbrella of the Einstein's Brain Project; this one titled The Shapes of Thought. The project asked participants to recall traumatic events from their past.

# data[].attributes.headline
Brain synchronicity, with Marina leading. Such bollocks

# data[].attributes.subject
Brain synchronicity, with Marina leading. Such bollocks

# data[].attributes.headline
Lots of staring, nothing happens, nothing is captured. WTF

# data[].attributes.subject
Lots of staring, nothing happens, nothing is captured. WTF

# data[].attributes.headline
Individual to individual / individual to machine

# data[].attributes.subject
Individual to individual / individual to machine

# data[].attributes.body
In many cases these artworks seek to visualise affect, but using emotive and abstract visualisations.
...That the mind could be calculable remains elusive in these artworks (despite the artists using this technology)

# data[].attributes.headline
Marina Abramovic, Measuring the Magic, Emotiv prformance 2012

# data[].attributes.subject
Marina Abramovic, Measuring the Magic, Emotiv prformance 2012

# data[].attributes.attachment_link.title
Marina Abramovic, Measuring the Magic of Mutual Gaze

# data[].attributes.attachment_link.description
Marina Abramovic
Video documentation of the Neuroscience Experiment: Measuring the Magic of Mutual Gaze   
Laboratoria Art&Science Space, 2012 
Special program of the symposium ‘Brainstorms. The Artist in the Context of Neuroscience’, Polytechnic Museum, Moscow, 2012



Curated by Daria Parkhomenko
The experiment was prepared by professor Alexander Kaplan and senior scientist Arina Kochetova, Laboratory for Neurophysiology and Neuro-Computer Interfaces, Lomonosov Moscow State University.

Together with the group of American and Russian scientists Marina Abramovic researches the non-verbal communication, a phenomenon that she has dealt with more than once in her previous artwork. Being a continuation of the performance The Artist Is Present at the Museum of Modern Art (MoMA), this artistic and scientific experiment is a result of collaboration between the artist, the curator Daria Parkhomenko and neuroscientists. Abramovic wonders whether there could be any scientific explanation of the tense contact that occurs when two people stare into each other eyes incessantly, and whether this non-verbal contact leads to the synchronization in brain activity. The experiment’s outcomes are studied by the Laboratory for Neurophysiology and Neuro-Computer Interfaces, Moscow State University.

Марина Абрамович
Измеряя магию взгляда, научно-художественный перформанс-эксперимент, Laboratoria Art&Science Space, 2012 
Специальная программа симпозиума “Brainstorm. Художник в контексте нейронаук”, Политехнический музей, Москва, 2012

Куратор: Дарья Пархоменко 
Эксперимент подготовлен профессором Александром Капланом и научным сотрудником Ариной Кочетовой, лаборатория нейрофизиологии и нейро-компьютерных интерфейсов, МГУ им. М.В.Ломоносова.

Марина Абрамович вместе с группой американских и российских ученых обратилась к научному исследованию невербальной коммуникации, феномену который не раз рассматривался в ее предыдущих работах. Являясь продолжением художественного перформанса «Artist Is Present» в Музее современного искусства в Нью-Йорке (MoMA), этот научно-художественный эксперимент стал результатом сотрудничества художницы, куратора Дарьи Пархоменко и нейроученых. Абрамович интересовало, возможно ли научное обоснование и объяснение напряженного контакта, который устанавливается между людьми, непрерывно смотрящими друг другу в глаза, и ведет ли этот контакт к синхронизации активности мозга смотрящих. Изучение полученных в результате эксперимента данных проводит лаборатория нейрофизиологии и нейро-компьютерных интерфейсов, МГУ им. М.В.Ломоносова.

# data[].attributes.headline
I'm Autumn and my role is animal care, and our philopshohy is to set up a system where the animals are able to volunteer to particapte in our project

# data[].attributes.subject
I'm Autumn and my role is animal care, and our philopshohy is to set up a system where the animals are able to volunteer to particapte in our project

# data[].attributes.body
https://bci-art.tumblr.com/

# data[].attributes.headline
Translate affect into a numerical system. Remove emotion.

# data[].attributes.subject
Translate affect into a numerical system. Remove emotion.

# data[].attributes.body
Counting the Affects: Discoursing in Numbers
OTNIEL E. DROR

# data[].attributes.headline
Focus on physiological impact. Quadriplegics, blindness 

# data[].attributes.subject
Focus on physiological impact. Quadriplegics, blindness 

# data[].attributes.body
(Sarah you could do with this)

# data[].attributes.headline
format of silicon valley/expo events / Musk 3 little pigs

# data[].attributes.subject
format of silicon valley/expo events / Musk 3 little pigs

# data[].attributes.attachment_link.title
Watch Elon Musk's ENTIRE live Neuralink demonstration