## Synopsis

BCI2000PresentationLink contains two plug-ins for the NBS Presentation stimulus delivery software, a so-called DataPort Extension which allows to record Presentation events into BCI2000 state variables, and a PCL Language Extension that allows to control BCI2000 from Presentation scripts written in the PCL language.

Before you can use it, BCI2000PresentationLink must be installed on your system, and must be registered with the Presentation software. This is possible even if your user account has no administrative privileges. For details, see the Installation section below.

## Versioning

### Author

juergen.mellinger@uni-tuebingen.de

Sergio Ruiz and Ranga Sitaram

### Source Code Revisions

• Initial development: BCI2000 r3918; Presentation Version 15 Build 11.15.11
• Tested under: BCI2000 r3967; Presentation Version 15 Build 11.15.11

## Functional Description

### Data Port Extension

The BCI2000PresentationLink DataPort extension provides a BCI2000 specific kind of Data Port in Presentation. In Presentation, Data Ports are objects that receive information about Presentation Events, which are triggered on Stimulus display, or from PCL scripts.

#### Recording Events

When receiving notification about an event from Presentation, a BCI2000 Data Port transmits it to BCI2000, such that it gets recorded in the BCI2000 data file. By default, events of the following types are recorded: Picture Sound Video Nothing Response. Other Presentation event types are ignored, unless added to the Event Types list in the Data Port's settings dialog. In BCI2000 data files, events are represented as numeric values of state variables that have names matching the corresponding Presentation event type. Thus, events are best represented when their Presentation event code is an integer number in the range between 0 and 2^32; in this case, the BCI2000 state value matches the Presentation event code at the point in time when the event was received. When the Presentation event code is a string, or does not fit into the above range, its first four characters are translated into their ASCII values, and concatenated to form a 32-bit integer. While this preserves as much information as possible about events, it may make it impossible for you to distinguish events whose event codes agree in their first four characters.

#### Timing Precision

Presentation achieves millisecond-accuracy when measuring the time at which an event has occurred. Unfortunately, this precision does not carry over to BCI2000 because, as stated in the Presentation documentation, the time when Presentation actually reports an event may be delayed by up to 50ms with regard to the time when it occurred. Although a Data Port object is provided with the time stamp of the event's occurrence, this information can not be utilized by BCI2000 because events cannot be dated back in time due to the way they are recorded in BCI2000. Thus, event information in a BCI2000 data file reflects the time when that event was reported to the Data Port object, not the time when its occurrence was detected. Presentation guarantees that the difference between these two time points, i.e. the delay, is below 50ms. Beyond that, they do not make any statement about how delay varies between events (timing jitter). However, in practice, one may assume that timing jitter is low, and that the delay is significantly less than the guaranteed value of 50ms.

On a typical LCD display, frame duration is 1/(60Hz) = 16.7ms. When presenting stimuli on such a display, the delay jitter between Presentation's detection of the stimulus, and BCI2000's recording of the associated event, will be less than the duration of a single display frame, and the absolute value of the delay will correspond to about a single frame. This may be a problem when you need to measure detect features in evoked activity on a time scale below 1/60s, or a frequency scale above 60Hz, which is not the case in most experiments. Also note that the temporal resolution of evoked activity is only affected by jitter, not by the absolute value of the delay. When doing exact latency measurements, you should perform measurements with a light or audio sensor in order to establish an estimate for the delay, so you can correct latency measurements for the delay, as well as for its jitter, to obtain an upper limit for temporal resolution.

#### Controlling BCI2000

Presentation provides "Resume" and "Pause" event types. By default, when a "Resume" event is received, the BCI2000 Data Port starts a BCI2000 recording (a "Run"), and when a "Pause" event is received, it stops recording. It is possible to set a subject ID, session ID, and data directory by providing this information in the "Resume" event's event code, separated by white space, where session ID and data directory may also be omitted. E.g., when sending a "Resume" event with an event code of "SUB 001 C:\my data", the recording will be stored as "C:\my data\SUB001\SUBS001R01.dat". For more information about the naming and location of data files, see the data storage parameters reference.

### PCL Extension

The BCI2000PresentationLink PCL extension is a PCL Library that contains a single class called BCI2000Controller. This is an interface to the BCI2000 Operator module, and allows to start up, configure, and run BCI2000 from PCL scripts.

To use it, instantiate an object of type "bci2000::controller" by writing

bci2000::controller bci = new bci2000::controller;


This will start up the Operator module residing in the same directory as BCI2000PresentationLink. You may then use the startup_modules() method in order to start up BCI2000 core modules. In case you have configured a BCI2000 DataPort for your experiment, the controller object's default properties are taken from the settings of the DataPort object.

Alternatively, you may specify the path to a BCI2000 batch file in the BCI2000/batch directory as an argument to the bci2000::controller operator. The path will be interpreted relative to Presentation's working directory:

bci2000::controller bci = new bci2000::controller( "path\to\bci2000\batch\CursorTask_SignalGenerator.bat" );


An appropriate batch file should start up Operator and core modules, and needs to forward its command line arguments to the Operator module. All batch files coming with BCI2000 fulfil this condition. When a batch file is specified, there is no need to call the startup_modules() method.

As yet another option, you may connect to an Operator module that is already running, e.g., on a remote machine on the network. In this case, call the controller's constructor with an appropriate network address and port, i.e. the telnet address the remote Operator module is listening on, i.e. the remote machine's IP address, followed with a colon, and the port specified when starting up the remote Operator module:

bci2000::controller bci = new bci2000::controller( "134.2.131.129:3999" );


The remote Operator module must have been started with the --Telnet command line option, followed with an external address to listen on. On the remote machine, this would typically be "*:3999". Don't use any of the ports between 4000 and 4002, as this will interfere with the communication between the Operator module, and BCI2000 core modules. Depending on whether the remote Operator module has been started up together with its core modules, or not, you may then call the startup_modules() method in order to start up BCI2000 core modules on the remote machine.

Once all BCI2000 modules are running, you may load parameter files locally or remotely using the load_parameters_local() and load_parameters_remote() methods. Subject ID, Session ID, and data directory are set using the respective bci2000::controller methods.

A recording may then be started by calling the start() method. Depending on configuration, the recording will terminate automatically, or needs to be terminated by a call to the stop() method.

To run BCI2000 in a different configuration (i.e., with different core modules), it is not necessary to terminate the Operator module. Rather, you may execute startup_modules() multiple times in order to terminate currently running core modules, and start different ones.

The bci2000::controller object will be deleted once its last reference goes out of scope in a PCL script. Depending on whether the Operator module was started up by the object's constructor, this will terminate the Operator module as well. Thus, you should declare that reference in the outermost scope of your PCL script. When connection was made to an already running Operator module, local or remote, the connection will be closed but the Operator module will remain running. The same applies when connection was made to an Operator module associated with a BCI2000 DataPort; then, the connection's life time corresponds to the life time of the DataPort object, i.e. the duration of the experiment.

## Installation

### Installation Steps

Before you can use BCI2000PresentationLink, it must be made known to your Windows system, and to Presentation. Each time when you are using BCI2000 on a new machine, under a different user account, or when you moved BCI2000 from its original installation location, you will need to manually install BCI2000PresentationLink in the system. This can be done by double-clicking the InstallPresentationLink.cmd batch file located in BCI2000/prog.

As a second step, BCI2000PresentationLink must be registered with Presentation. You will need to repeat this step each time you are using Presentation on a new machine, or under a different user account.

• In the Presentation main window, choose "Extension Manager" from the "Tools" menu.
• In the Extension Manager window, click the "Select Extension File" button, and select your BCI2000 installation's BCI2000/prog/BCI2000PresentationLink.dll file. When you have more than one BCI2000 installation, then select the BCI2000PresentationLink file from the installation you want to be used by default.
• After clicking "OK", you will see two extensions listed under "Available Extensions", one that is a "PCL Extension", and one that is a "Data Port". Click the first entry in the list of available extensions, and enter its name into the "Register As:" field.
• Make sure the "Dont 't register server with Windows" checkbox is checked. Then, click "Register Extension".
• When you get an error message, make sure you are not trying to register an extension twice, and make sure that you performed installation into Windows as described above.
• Again, click the "Select Extension File" button, and select your BCI2000PresentationLink file.
• This time, click the second entry in the "Available Extensions" list, enter its name into the "Register As:" field, make sure the "Don't register ..." checkbox is checked, and click "Register Extension".
• Both the BCI2000DataPortExtension, and the BCI2000PCLLibrary should now appear in the "Registered Extensions" list at the top of the Extension Manager window.

As a third step, you will need to create a BCI2000 Data Port in your experiment. You will need to do this each time you are creating a new experiment that uses BCI2000.

• In the Presentation window, go to the "Settings" tab.
• In the icon band on the left, click "Port".
• Click "Add" under "Data Ports" to the right.
• Right to that drop-down menu, a "Properties" button appears. Click it.
• Read the description of the dialog elements in order to get an idea of your more advanced options.
• BCI2000 must be started up in a certain configuration defined by the core module executables which to run. Such a configuration may be chosen in the Data Port properties, by clicking "Choose ..." and selecting an appropriate batch file from BCI2000/batch. Alternatively, you may start up a selection of core modules from a PCL script by instantiating a bci2000::controller object, and calling its startup_modules() method.
• Click "OK".

You may now record events into BCI2000 from your own experiments. For examples how to do this from both scenarios written in SDL, and PCL scripts, see the examples section below.

### Troubleshooting

• Presentation displays an error message "An attempt was made to create a COM object for a class that is not registered":
Execute BCI2000/prog/InstallPresentationLink.cmd under the user account that is going to run the Presentation program.
• When trying to register an extension, Presentation displays an error message "DLL registration failed ...":
Make sure the "Don't register server with Windows" check box is checked when clicking "Register Extension". You may need to follow the advice of the previous troubleshooting entry as well.

### Deinstallation

BCI2000Presentation installation adds a few registry keys to the current user's, or the machine's, "Software/Classes" key. When these keys remain on your machine after removing BCI2000, they will not do any harm, so you need not bother removing them. To remove those keys anyway, log in as the user for whom installation was performed, and execute

InstallPresentationLink /u


from a command prompt inside the BCI2000/prog directory.

### Windows installation options

BCI2000PresentationLink may be installed or deinstalled for all users of a machine, or only for the user who runs the installation script. Selection between the two is done automatically, by determining whether the user has administrator rights. If so, installation is performed per-machine; if not, installation is done per-user. To manually choose the type of installation, you will need to execute the following command from the command prompt, inside the BCI2000/prog directory:

regsvr32 /n /i:<option> BCI2000PresentationLink.dll


There, <option> may be one of the following:

• user to install for the current user only,
• system to install for all users,
• any to try installation for all users, and switch to per-user installation when that fails,
• both to install both for all users, and the current user (this option only makes sense for deinstallation).

Note that per-user installation overrides system-wide installation. This may lead to confusing behavior of BCI2000PresentationLink when switching between multiple users, and executing the installation program for those users, or when granting a certain user administrative privileges at one time, and later removing those privileges. To completely remove all references to BCI2000PresentationLink from your machine under such circumstances, execute

rgsvr32 /n /u /s /i:both BCI2000PresentationLink.dll


under all user accounts that may have executed the installation script, and make sure that at least one of those accounts has administrative privileges.

## BCI2000PCLLibrary Reference

The BCI2000 PCL Extension contains a single class type called bci2000::controller. To use it, instantiate a controller object by writing

bci2000::controller bci = new bci2000::controller();


This type has the following methods:

### Constructors

#### controller()

Creates a controller connecting to the first BCI2000 data port, or to the BCI2000 installation in which BCI2000PresentationLink resides.

#### controller( string location )

Creates a controller connecting to a BCI2000 Operator module, or to a network address. In the "location" argument, provide a path to a BCI2000 Operator module, or network address in form <ip>:<port>.

### Properties

#### hide_window()

Hides the BCI2000 Operator main window.

#### show_window()

Shows the BCI2000 Operator main window.

#### set_window_title( string window_title )

Sets the title of the BCI2000 Operator main window.

#### set_subject( string subject_id )

Sets a subject ID for the BCI2000 recording.

#### set_session( string session_id )

Sets a session ID for the BCI2000 recording.

#### set_data_directory( string data_directory )

Sets a data directory for the BCI2000 recording, relative to the BCI2000 prog directory. Data files will be placed into a subject and session specific directory below the data directory.

### Control of operation

#### startup_modules( array( string ) list_of_modules )

Starts up a given set of core modules (typically, a Source, SignalProcessing, and Application module). In the argument, provide a list of module executables, optionally with their command line options.

#### set_config()

Applies current set of parameters to the BCI2000 system.

#### start()

Starts operation.

#### stop()

Suspends operation.

### Parameter access

#### string get_parameter( string name )

Returns the value of the specified parameter.

#### set_parameter( string name, string value )

Sets the value of the specified parameter.

Loads a parameter file relative to Presentation's working directory.

Loads a parameter file relative to the BCI2000/prog directory.

### State variable access

#### add_state_variable( string name, int bit_width, int initial_value )

Adds a state variable to the system. This is only possible before core modules have connected to the Operator module.

#### double get_state_variable( string name )

Returns the value of a BCI2000 state variable.

#### set_state_variable( string name, double value )

Sets the value of a BCI2000 state variable.

#### double get_control_signal( int channel, int element )

Returns the value of an element in the control signal. Indices are 1-based.

### Operator scripting

#### int execute( string command, string byRef output )

Execute an arbitrary BCI2000 scripting command. The meaning of the return value depends on which command has been executed, and is the exit code of the command, as defined in the BCI2000Remote Class Document.

A full documentation of BCI2000 Operator scripting commands is available under User Reference:Operator Module Scripting.

#### set_script( string handler, string script )

Associates BCI2000 Operator scripting commands, given in "script", with a handler whose name is given in the "handler" argument. See User Reference:Operator Module Scripting#Handlers for a list of handler names.

#### string get_script( string event )

Returns BCI2000 Operator scripting commands associated with an event.

## Examples

Full examples for both stimulus presentation and feedback paradigms are available in the Examples subdirectory of the BCI2000PresentationLink directory.

scenario = "Minimal BCI2000 example";

begin;
# Trial definitions
...

begin_pcl;

# Create a BCI2000 controller object.
bci2000::controller bci = new bci2000::controller;

# Start up modules.
array<string> modules[3] =
{ "SignalGenerator", "DummySignalProcessing", "DummyApplication" };
bci.startup_modules( modules );

# Synchronize BCI2000 subject id with Presentation's.
bci.set_subject( logfile.subject() );
bci.set_session( "001" );

# Suppress display of default visualization windows.
bci.set_parameter( "VisualizeTiming", "0" );
bci.set_parameter( "VisualizeSource", "0" );

bci.set_config();
bci.start();

# Trial presentation
...

bci.stop();