Documentation: A Gentle Introduction to the BBCI Toolbox
IN CONSTRUCTION
To follow this tutorial, you should have the BBCI Matlab toolbox installed (../ToolboxSetup) and know about its data structures (../ToolboxData). Here, you will be animated, to explore the data structures, do some initial analysis (e.g. plotting ERPs) manually (i.e., without using the toolbox functions), and then see how it can be done with the toolbox. Some the manual analysis serves the following purpose: Many of the toolbox function are in principle simple, but the code sometimes gets quite complicated, because it should be very general. The manual analysis demonstrates this simplicity. So don't be afraid of the toolbox - it's no magic.
This is a hands-on tutorial. It only makes sense, if you have it side-by-side with a running matlab where you execute all the code.
Exploring the data structure
A first look at the data structure cnt which holds the continuous (un-segmented) EEG signals.
file= 'VPibv_10_11_02/CenterSpellerMVEP_VPibv';
[cnt, mrk, mnt]= eegfile_loadMatlab(file);
cnt
% Fields of cnt - most important are clab (channel labels), x (data) and fs (sampling rate).
% The data cnt.x is a two dimensional array with dimension TIME x CHANNELS.
cnt.clab
% This is a cell array of strings that hold the channel labels. It corresponds to the second dimension of cnt.x.
strmatch('Cz', cnt.clab)
% Index of channel Cz
strmatch('P1', cnt.clab)
% Index of channel P1? Why are there two?
cnt.clab([49 55])
% Ah, it matches also P10. To avoid that, use option 'exact' in strmatch
strmatch('P1', cnt.clab, 'exact')
% Now it works. The toolbox function 'chanind' does exact match by default:
chanind(cnt, 'P1')
% But it is also more powerful. And hopefully intuitive:
idx= chanind(cnt, 'F3,z,4', 'C#', 'P3-4')
cnt.clab(idx)
% Be aware that intervals like 'P3-4' correspond to the rows on the scalps layout, i.e.
% P3-4 -> P3, P1, Pz, P2, P4; and F7-z -> F7,F5,F3,F1,Fz
% Furthermore, # matches all channels in the respective row: but C# does not match CP2.
% (but not the temporal locations, i.e. CP# does not match TP7)
idx= chanind(cnt, 'P*')
% The asterix * literally matches channel labels starting with the given string.
cnt.clab(idx)
% Fields other than x, fs, clab are optional (but might be required by some functions).
cnt.T
% This is the number of time points in each run (when cnt is the contatenation of several runs).
sum(cnt.T)
% This should then be the total number of data points, corresponding to the first dimension of cnt.x.
plot(cnt.x(1:5*cnt.fs,15))
% displays the first 5s of channel nr. 15
Next, we have a look at the structure mnt, which defines the electrode montage (and also a grid layout, but that will come later).
mnt
% Fields of mnt, most importantly clab, x, y which define the electrode montage.
mnt.clab
% Again a cell array of channel labels. This corresponds to cnt.clab. Having those information in both
% data structure allows to match corresponding channels, even if they are in different order, or one
% structure only has a subset of channels of the other structure.
mnt.x(1:10)
% x-coordinates of the first 10 channels in the two projects (from above with nose pointing up).
mnt.y(1:10)
% and the corresponding y coordinates.
clf
text(mnt.x, mnt.y, mnt.clab); axis([-1 1 -1 1])
% displays the electrode layout.
% The function scalpPlot can be used to display distributions (e.g. of voltage) on the scalp:
scalpPlot(mnt, cnt.x(cnt.fs,:))
% -> topography of scalp potentials at time point t= 1s.
% You can use this also to make a simple movie:
for t=1000+[1:cnt.fs], scalpPlot(mnt, cnt.x(t,:)); title(int2str(t)); drawnow; end
To make sense of the data, we need to know what happened when. This is stored