BCI2000Tools.EventRelated
Analysis of Event-Related Potentials from BCI2000 Files with Python
These instructions assume you are OK with typing commands at a command prompt. If you are not, read this: https://bitbucket.org/jezhill/doc/wiki/CommandLine
1. Obtain the code
BCI2000Tools is a set of Python modules and command-line programs. It is part of the BCI2000 distribution, where it resides inside the tools/python directory. If you already have these files, that's great. If you still need to download them, the best way to do it is by using Subversion, a.k.a. svn:
- On Windows, you should download and install TortoiseSVN, and during installation, remember to explicitly select "command line client tools" because the installer might not include this by default. After installation, start a whole new Command Prompt.
- macOS may already come with a command-line
svnbuilt-in, or you may need to install the "XCode Command-line Tools" withsudo xcode-select --install. If all else fails you can install https://brew.sh and thenbrew install svn.
Once you have subversion, you will need a BCI2000 username and password: if you do not already have one, go to https://www.bci2000.org/useradmin/
When you are ready, decide where you're going to put the BCI2000 files and cd to that location. You
do not need a separate copy for every project (you could do it that way, but that would lead to version-confusion very easily in future). Pick a place, then choose whether to download the whole (quite large) BCI2000 source distribution:
svn checkout https://bci2000.org/svn/trunk bci2000-svn
or just the minimal set of files needed for Python:
svn checkout https://bci2000.org/svn/trunk/tools/python bci2000-tools-python
If you are going to use the real-time BCI2000 system on this computer, there are advantages to going the first route and keeping everything in one place. If this computer is only going to be used for analysis, then the second route is fine.
2. Tell Python where the code is
Let's assume that when you type python at the command-line, you get the intended
version of Python, in the environment you are comfortable with (with all the sciencey
third-party packages you're accustomed to for your other analyses). To support BCI2000Tools.EventRelated, you will need numpy, scipy and matplotlib, and it is also recommended to get IPython. Getting to this
point is non-trivial in itself and will not be covered here, except to say:
on Windows, maybe download and install Anaconda, then launch the "Anaconda Prompt"?
On a non-Windows system, maybe you need to be typing python3 instead of python? Maybe it's a good idea to set up a virtual environment first, then activate it, before installing anything?
The hardest program to write in Python is "Hello World" and this document unfortunately
cannot help with that. Things have got somewhat better since https://xkcd.com/1987
but there's probably still some way to go.
First change your working directory to the directory you just checked out with svn. For example:
cd bci2000-tools-python
if that's what you called it on the checkout line. Or maybe it's:
cd C:\Somewhere\Somewhere\Somewhere\bci2000-svn\tools\python
if you're on Windows and you checked out the whole distro. Either way, you should now
be working in the directory that contains the file setup.py. From there, you type:
python -m pip install -e .
Make sure to include the -e. And the space and the dot at the end. In fact, include
all the words and all punctuation: computers don't do the right thing unless the
command is exactly right, you know that. Copy-and-paste is your friend.
The -e causes your Python distribution (or virtual environment) to make a note of
where the BCI2000Tools reside, so in future Python will be able know what to reach for
when you import BCI2000Tools.EventRelated or %run -m BCI2000Tools.EventRelated.
The advantage of doing it this way is that you can later get bugfixes and updates simply
by running the command svn update from that directory. The one thing that could go
wrong is that, after telling Python where the files are, you decide to drag and move them
somewhere else. In that case, Python will not know where to find them any more, and you will have to
tell it again.
3. Invoke BCI2000Tools.EventRelated
You can invoke the BCI2000Tools.EventRelated code in various different ways. From your system command prompt:
python -m BCI2000Tools.EventRelated ...
or from the IPython command prompt (after launching with python -m IPython):
%run -m BCI2000Tools.EventRelated ...
or from your own Python program:
from BCI2000Tools.EventRelated import EpochSet x = EpochSet( ... )
These are all roughly equivalent. The command-line invocations that use
-m BCI2000Tools.EventRelated merely translate your command-line arguments into
parameters that get passed to the EpochSet constructor, creating an EpochSet instance that happens to be called self (if you're in IPython, you can then reassign it to a more meaningfully-named variable and continue from there).
In all cases the ... stands for additional arguments. The main arguments will be names of (or paths to) BCI2000 .dat files. Various other options are explained from the command-line help (let's assume you're using IPython):
%run -m BCI2000Tools.EventRelated . --help
Note that BCI2000Tools.EventRelated produces interactive plots by default: you can click on the raster-plot to see the waveform an scalp topography that cut through the time and place you select. If you are running IPython in a
"notebook" interface, you may need to run the %matplotlib notebook or
%matplotlib widget command, or otherwise enable interactivity in your notebook after consulting the relevant documentation.
Here is a simple example command-line:
%run -m BCI2000Tools.EventRelated testS001R@.dat -t DigitalInput1 -p 2-1B
The @ symbol is equivalent to * (so, this example will match all files that conform to the pattern testS001R*.dat) but unlike * it will not get intercepted and expanded by IPython itself.
The -t option (a.k.a. --trigger) is critical. It specifies the name of a channel or state variable whose value becomes non-zero whenever a stimulus event occurs. You could use the StimulusCode state variable itself here, but then you are relying on software timing; you will get much better results if you use a digital trigger activated by some kind of trigger box that senses the light or sound signal in hardware. In the example above, we are imagining that the trigger pulse got digitized into the DigitalInput1 state variable (which is provided by the
BCI2000 modules that support various g.tec devices). Once the program has used this to establish when an event occurred, it will work backwards to find the most
recent change of the StimulusCode state variable to a non-zero value, and read that value to determine what kind of event occurred.
The -p option (a.k.a. --plot) signifies that a plot is required, but it also takes an argument that specifies what should be plotted. The example string here, 2-1B, is a densely coded shorthand that translates to "subtract the average of StimulusCode=1 events from the average of StimulusCode=2 events, and perform subtractive baseline correction". Obviously, you need to know what StimulusCode value corresponds to what stimulus in your experiment, and adjust accordingly. You can pool stimulus codes, you can plot average responses with or without contrasting, you can turn baseline correction on or off, you can z-score, you can plot signed r-squared values. All of these options are explained in the documentation for the Processing class, which in IPython can be examined by saying:
from BCI2000Tools.EventRelated import Processing Processing?
or:
%run -m BCI2000Tools.EventRelated . --help-processing
It is also worth emphasizing the role of the -c option (a.k.a.
--highlightChannel), which we did not use in the example above: this gives you versatile options for automatically picking positive and/or negative peaks within certain spatial and temporal constraints, and initializing the interactive plot at that location. In doing so, the program also attaches the results of its search to self.highlighted for later examination and processing. Like the -p option, the -c option also takes a shorthand argument: read the --help.
Example Output
> python -m IPython
In [1]: run -m BCI2000Tools.EventRelated S05S005R@.dat -t DigitalInput3 -d A2 -p 1-2ZN -c Pz+@250-600 -s "Auditory (Sham Stim.)"