Programming Tutorial:Working with the FieldTrip buffer

From BCI2000 Wiki
Jump to navigation Jump to search

One of the user-contributed Signal Processing filters is the FieldTripBuffer. The FieldTripBuffer allows you to use BCI2000 in conjunction with MATLAB, just as with the MatlabFilter. The difference between the two interfaces to MATLAB is that the MatlabFilter causes some MATLAB code to be executed in the BCI2000 pipeline, i.e. BCI2000 stays in control over the timing and the MATLAB session only sees a small fragment of the data. That also forces you to write your MATLAB code to use recursive/incremental updating schemes. The FieldTripBuffer interface to MATLAB allows you to control the timing from within MATLAB and read arbitrary sections of data from the ongoing data stream as if it were a continuously growing file, giving more flexibility in the MATLAB code that you can employ.

The advantage of the FieldTripBuffer interface is that you have all control in MATLAB that you are used to. You can write your MATLAB code for offline-analysis (i.e. reading data from a file) and apply exactly the same code to online analysis (i.e. reading from BCI2000). Of course for the online analysis to make some sense, your analysis script has to be meaningful and has to work with relatively small data fragments (e.g. one second or less), otherwise the MATLAB code would not really run in real-time. Another interesting feature is that in MATLAB you can use the profiler (type "help profile") to determine which parts of your code take a long time to execute and speed those parts up.

The remainder of this page gives an example of how to get the data into MATLAB, plot the data using standard MATLAB code, and how to close the BCI loop by writing an event back to BCI2000. The example below does not do any useful processing, it is up to you to decide how you want to process the data in MATLAB. A number of realtime applications are included in the realtime module of the FieldTrip toolbox. Additional documentation for that can be found on the FieldTrip website, under development->realtime.

Getting the data in Matlab

The FieldTrip buffer is a multi-threaded and network transparent buffer that allows data to be streamed to it by BCI2000, while at the same time allowing a seperate MATLAB session on the same or another computer to read data from the buffer for analysis. Besides writing the data, BCI2000 also writes the changed status variables as events.

To use the FieldTrip buffer, you start BCI2000 with the FieldTripBuffer as the Signal Processing application. Subsequently you start MATLAB yourself, i.e. your MATLAB session is a normal standalone application. You should have a recent copy of the FieldTrip toolbox installed, or at least a copy of the FieldTrip fileio module. The FieldTrip toolbox and its components are available for download from http://www.ru.nl/neuroimaging/fieldtrip. Please make sure that the correct version of the fileio module is on your MATLAB search path.

Subsequently you can do something like the following code below. You should be able to copy and paste the code into the MATLAB command window and get a real-time updating MATLAB figure with the data from BCI2000.

filename = 'buffer://localhost:1972';

% read the header for the first time to determine number of channels and sampling rate
hdr = read_header(filename, 'cache', true);

count      = 0;
prevSample = 0
blocksize  = hdr.Fs;
chanindx   = 1:hdr.nChans;

while true
  % determine number of samples available in buffer
  hdr = read_header(filename, 'cache', true);

  % see whether new samples are available
  newsamples = (hdr.nSamples*hdr.nTrials-prevSample);

  if newsamples>=blocksize

    % determine the samples to process
    begsample  = prevSample+1;
    endsample  = prevSample+blocksize ;

    % remember up to where the data was read
    prevSample  = endsample;
    count       = count + 1;
    fprintf('processing segment %d from sample %d to %d\n', count, begsample, endsample);

    % read data segment from buffer
    dat = read_data(filename, 'header', hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx);

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % subsequently the data can be processed, here it is only plotted
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    % create a matching time-axis
    time = (begsample:endsample)/hdr.Fs;

    % plot the data just like a standard FieldTrip raw data strucute
    plot(time, dat);

    % ensure tight axes
    xlim([time(1) time(end)]);

    % force Matlab to update the figure
    drawnow

  end % if new samples available
end % while true

Closing the loop, writing a control signal from Matlab to BCI2000

To close the loop, you have to write the control signal back to BCI2000. Since the FieldTrip buffer can only hold raw data, the control signal cannot be written as data. Instead, the control signal is written as an event. This is easily demonstrated if you run the Feedback Demo Task.

event.type = 'Signal';
event.sample = 1;
event.offset = 0;
event.duration = 1;
event_up = event;
event_up.value = 1;
event_down = event;
event_down.value = -1;
event_null = event;
event_null.value = 0;

You can write the events to the buffer according to the following example code:

filename = 'buffer://localhost:1972';

ft_write_event(filename, event_up);    % ... the cursor will move up ...

ft_write_event(filename, event_down);  % ... the cursor will move down ...

ft_write_event(filename, event_null);  % ... the cursor will stay at a constant value ...

The control signal in BCI2000 remains at a constant value as long as you don't write another event with another control signal.

See also

Contributions:FieldTripBuffer, Programming Reference:MatlabFilter, User Reference:MatlabFilter