How to perform a BCI experiment using the MD-BCI toolbox

How to perform a BCI experiment using the MD-BCI toolbox
Preparing the experiment
After starting MATLAB, please make sure that all the paths are set correctly on your system.
Start all required further programs (e.g. VR applications, etc.)
The scripts are designed to be executed in a folder created for the present experiment. Thus, create a
folder for each BCI-session and copy the latest bciGetParam.m file to this folder. In the Matlab
command window, change the working directory to this folder. With this procedure you make sure
to save the configuration of the experiment for each BCI-session for post processing. Pay attention
that no other version of bciGetParam.m is on the Matlab path (using which bciGetParam)
The parameter file is the central file to configure the experiment. Make sure to open the parameter
file bciGetParam.m of the current session and modify it according to your requirements.
After the first recording block you may want to select frequencies if you use a frequency
decomposition approach. For this purpose set bci.param.freq to an empty matrix []. This causes
the use of all possible frequencies (up to 100 Hz) regarding the interval length and sampling rate.
In the parameter block of your recording system define bci.preprocChan, where channel indices
have to be set according to the buffer the corresponding recording function is reading.
Example: The recording function reads 256 channels. We only want to process the first 64 channels
and exclude channel 1. Then set bci.preprocChan = 2:64;
If you want to use all these channels for classification, use
bci.chanOfInterest = bci.preprocChan;
Run an Experiment
All the data that are required for processing are stored in global variables to be available during the
whole BCI session and to avoid manual keeping of variables. At the end of each block the data
additionally will be saved on disk. Make sure that bci.param.saveRawDat is set true.
Calibration
In order to determine the signal strength and frequency range of the channels to process, start a
calibration measurement. It is recommended that any kind of movement (in particular eye
movements or blinks) is prevented during this measurement.
bciCalib;
starts the measurement of 10 seconds duration. This function opens a figure that depicts the ratio of
standard deviation of frequency bins and channels to the average standard deviation over channels.
Channels with high differences will be marked. The values in parentheses are the channel indices that
you may want to exclude from bci.preprocChan (eg. channel 9(10) is marked, then change
bci.preprocChan = 2:64; to bci.preprocChan = setdiff([2:64],[10]));.
Furthermore, an artifact threshold will be suggested in the title of the figure. Set
bci.param.artifactThresh
to this threshold. If the artifact threshold is too high artifacts will not be detected; if it is to low many
or even all epochs will be excluded.
The calibration measurement can be repeated to secure reliable estimates.
Record a train block
To run a block, make sure that your matlab working folder is the desired session path and then start
the run with the command
bciRun(‘subjID_run_’,1,’train’);
The second argument is the number of the run and therefore must be changed for each new
recording block. Otherwise data in memory and on disk will be overwritten. Data will be saved in the
working directory (use absolute path to save it somewhere else).
You can run another training run by changing just the second argument of the function call.
bciRun(‘subjID_run_’,2,’train’);
Feature and parameter selection (manually)
Selection of features can be made by selecting channels and frequencies by hand. The function
bciCheckFeatures([1 2]);
shows T-values of the train data of run 1 and 2 (optionally you can use run 1 only) for each
combination of condition pairs. With the help of the color coded plots you can decide which channels
and frequencies you are interested in. The function also displays suggestions of informative
frequencies in the command windows by selecting frequencies of defined bands and fulfilling
threshold criterions. However, the final frequency selection you have to do by hand. Use help
function to read about additional arguments.
A more general function for selecting features is bciFeatureRanking. See helpful functions
section for more details.
bciCheckClassifier([1 2]);
gives an estimate of the accuracy the classification can achieve. The recall values give an estimate if a
particular class is biased. The number of bad epochs and bad channels can signal an over or under
estimate of the artifact threshold. When checking several runs a leave-one-run-out cross validation is
performed, 3-fold crossvalidation otherwise.
Before you apply the selected frequencies, you can test several combinations by selecting
frequencies for the classifier only.
bciSelectFrequencies([ 10 20 30]);
selects the given frequencies as features of interest. All selected frequencies must be defined in
bci.param.freq (if empty in the parameter file, frequencies were automatically determined).
An empty matrix as argument bciSelectFrequencies([]) reselects all available frequencies
from bci.param.freq. A repeated bciCheckClassifier call will give you a cross validation
estimate when using these frequencies for classification.
However, it is recommended to enter the best performing frequency set into the parameter file
instead of selecting it as features of interest to reduce memory consumption.
In order to test or apply your feature selection, change the corresponding parameters in
bciGetParam (e.g. you selected channels 40, 50-60 and frequencies 10 and 30 Hz, then set
bci.chanOfInterest = [40,50:60] and bci.param.freq=[10,30]).
Then test your selection by recreating the epoched data from raw data:
bciRecreate(‘subjID_run_’,1:2)
Repeat the procedure of checking features and classifier, respectively.
You can also use this procedure by changing other essential parameters, as bci.param.tapers,
bci.refChanCAR or bci.param.artifactThresh.
Some changes of parameters don’t need the recreation of epochs. (e.g. classifier related
parameters). In this case it is sufficient to refresh the parameter file after a change was made:
bciRefreshParam
After that, checking the classifier would use the new parameters.
If you have decided which runs and feature set you want to use for the classifier training, run
bciTrain([1 2]);
Note that it is not sufficient to run bciCheckClassifier(<runs>) to train the classifier
because this function performs a cross validation and trains only subsets which are not globally
saved.
Feature selection (unsupervised)
Alternatively or additionally to the subjective selection of frequencies and channels you can enable a
feature selection that automatically selects the specified number or ratio of features using a specified
method at the specified dimension. Specification is done by defining a string
bci.param.featureSelection with the following substrings. As method you can define ‘svm’,
‘tval’ and ‘rsqu’, followed by the dimension ‘chan’, ‘freq’ or ‘raw’, followed by the destination
number or ratio of features. When defining a cell string of feature selections, multiple feature
selection methods can be applied sequentially. Theoretically the following combination would by
possible:
bci.param.featureSelection = {‘rsquchan16’,’tvalfreq3’,’svmraw0.3’};
This example first selects 16 channels with highest R² values, then selects out of this feature set the 3
frequency bands with highest t-values and finally selects from this feature set 30 percent of highest
weights using a support vector machine training.
See bciFeatureRanking description for detailed information on arguments.
Start a feedback Run
Before you can start a feedback run you have to call bciTrain(<runs>) to train on the whole
run(s) and make the classifier available for the test function.
bciRun(‘subjID_run_’,3,’test’);
starts a feedback run.
Again the data are stored in the global cell array and saved on disk. Don’t forget to change the run
number for each test run to avoid overwriting.
Further helpful functions
bciGlobals()
makes the global variables visible.
bciLoad(‘subjID_run_’,<runs>,doLoadRawdata,doLoadEpochedData)
loads the data of runs into the global structures. Useful for post processing or if something went
wrong during an experiment.
bciRefreshParam()
must be called if something was changed in the bciGetParam file to accept the new settings.
bciFeatureRanking(<runs>,nFeat,method,category,validation)
calculates highest ranked features of a channel-frequency feature space. At multi class mode, for
each class pair same number of features are selected and padded to total number if intersections
appear. You can specify nFeat as a fix number of features or as ratio of available features by
defining between 0 and 1. Comparison method can be ‘tval’, ‘rsqu’ and ‘svm’. Feature category
can be ‘freq’ for frequencies ‘chan’ for channels and ‘raw’ for the reshaped feature vector
representing the classifier space. Finally, different validation methods induce different results. If you
like to apply a validation method different from the absolute maximum (‘max’) you can define
validation also as ‘mean’ for absolute mean value and ‘ssq’ for the sum of squares measure. The
result is given as parameter-file-conform output in selectedFeat.
See help for default values of the arguments.
bciTopoplot(<runs>,method,conds)
shows the SVM weighting or t-value maps for the feature space (e.g. a spectrogram if using multi
taper). If you have specified a channel location file, additional topographic maps are shown. Define
method as ‘svm’, ‘tval’ or ‘rsqu’ and define the conditions to compare as a two element vector
conds (in the Motor paradigms the conditions match 1,2,3 representing left, base, right; default is
[1 3]).
Important parameters
The following parameters are suggested to be checked:
bci.recordingSystem – your recording system
bci.paradigm.id – paradigm you want to use
bci.numTrials – number of trials per block and class, usually 15
bci.testRunDur – length of a feedback run, usually 300 to 360 seconds
bci.param.artifactThresh – threshold to detect artifacts. if unsure, set a high value
bci.param.freq – frequencies for creating spectral epochs, if empty, all possible frequencies are used
bci.param.specMethod – most promising is 2 (multi tapers)
bci.param.balanceTrainSet – balancing prevents biasing
bci.param.bootstrapSize - number of maximum samples after bootstrap, 0 if no bootstrap
bci.param.maxTrainSamp - maximum number of train data per class
bci.param.retrainClassifierTrialLength - trial length(in sec) of feedback data to include for retraining
the classifier after each trial; 0 for no retraining
bci.refChanCAR – define the channels for calculating CAR generally bci.preProcChan, current
implementation ignores channels: empty means no CAR, not empty means CAR on bci.preProcChan
bci.param.doSendTrigger – set true if you use a working trigger system
bci.param.doReceiveTrigger – set to false if your recording system is not configured to provide the
trigger in the real time buffer
bci.param.saveRawDat – set always to true in experiments, in order to reuse the data
Implemented Paradigms
Continuous Cursor control
In the train phase, a matlab figure will open and show a cross to indicate the baseline condition and a
left or right pointing arrow to indicate the respective direction condition. In the feedback phase, a
circle has to be moved to a target cross. If the classifier detects right or left movement condition the
cursor moves to the respective direction, if baseline was classified, the cursor stops. This paradigm
can be performed in 3 class and 2 class mode. Set bci. eventsToClassify to the conditions you wish to
use. If you use two conditions set bci.param.classifier to a two class classifier (e.g. ‘svm’), if you use
three conditions, set the classifier parameter to ‘svmmulti’ or ‘logreg’. To activate this paradigm, set
bci.paradigm.id=1.
Continuous Virtual Arm control
The parameter setting is identical to the continuous cursor control paradigm except bci.paradigm.id
must be set to 2. Instead of a cursor, the virtual arm of the Fraunhofer VR Grasping application can
be controlled. The target is an object on a table to reach. See “Fraunhofer virtual arm manual” for
instructions to start the application.
Actuated Virtual Arm grasp in two directions
This paradigm is designated to control the grasp by three classes. Two targets are located on the
virtual table. The color of the targets signalizes the action to perform. Baseline condition: both
targets appear yellow, grip condition: one target changes color, indicating that the respective
direction condition must be performed. A threshold bci.paradigm.fbPredRate defines the rate of
classifier windows that must be classified as one class to start the feedback action. A minimum
duration of bci.paradigm.fbPredictionWindow will be met but a timeout bci.paradigm.fbTrialTimeOut
terminates the trial if only baseline was classified.
Actuated Virtual Arm grasp in one direction
Here only one target is shown in the VR application. An attention event is signalized by a yellow
target, followed by a GO (green target) or STOP (red target) event. The parameter
bci.eventsToClassify must be set to baseline condition and one direction condition (depending on
where the target may appear), bci.param.classifier must be set to ‘svm’ (or another 2 class classifier).
Trial durations are fixed (parameters bci.numTrials, bci.movDur, bci.fixDur, and the feedback
parameter define the duration of a run).
Further parameters for actuated grasp paradigms:
bci.stimulation.targetColor – first triplet defines GO-color, second triplet defines STOP color
bci.stimulation.armSystem - activates left or right arm
bci.paradigm.fbPredictionWindow – length of interval used to train on feedback data
bci.paradigm.stimVelocityToDestination – set non-zero to get feedback in train runs, too
Utilities
Signal generator
In order to simulate the data transfer the signal generator can be used to send predefined signals
and modulate it with the mouse cursor. Data are sent to a fieldtrip buffer, i.e. you have to run a
buffer.exe application on the local or a remote machine. By default the function
bciSignalGenerator(nChan,srate)
sends noisy sine waves of nChans channels at a sampling rate of srate Hz. However, as a third
argument you can define a parameter struct. The fields of the struct overwrite the default
parameters. Thus you are able to simulate your data recorder properties and experimental setup as
similar as possible. Fields of the parameter struct are:
Fs – sampling rate
mouseXChan – modulation channel for horizontal position of the mouse pointer (default: 1)
mouseYChan – modulation channel for vertical position of the mouse pointer (default: 2)
amplitudeInChans - vector of length nChans that defines amplitude per channel (default: 1 each)
SNRdB – white noise strength in decibel (default: 1 (snr≈1.26))
freqsInChans: - vector of length nChans that defines a sine signal frequency per channel (default:
channel ID as frequency in Hz)
offsetInChans - vector of length nChans that defines an offset per channel (default: channel ID as
offset)
blockSize – length of a data sample block in seconds (default: 0.1)
duration- length of simulation in seconds (default: 300)
IP – host address where the fieldtrip buffer is running (default: 127.0.0.1)
Mapping Tool
Christoph Reichert, last update 07/29/2011