Programming Reference:Events: Difference between revisions

From BCI2000 Wiki
Jump to navigation Jump to search
Line 17: Line 17:
*Time stamps have millisecond resolution. Up to sampling rates of 1kHz, this is not a practical restriction though.
*Time stamps have millisecond resolution. Up to sampling rates of 1kHz, this is not a practical restriction though.
*Association of event time stamps with sample positions cannot be more accurate than [[User Reference:Timing|time stamps assigned to data blocks]] by the data acquisition module. If data transmission latency between data acquisition hardware, and its associated jitter, are large compared to a single sample's duration, then event positions cannot be expected to be precise. Still, for data acquisition devices that are connected directly to the machine running the data acquisition module (i.e., not over a network connection), and for sampling rates below 1kHz, transmission latency and jitter may be expected to be below a sample's duration.
*Association of event time stamps with sample positions cannot be more accurate than [[User Reference:Timing|time stamps assigned to data blocks]] by the data acquisition module. If data transmission latency between data acquisition hardware, and its associated jitter, are large compared to a single sample's duration, then event positions cannot be expected to be precise. Still, for data acquisition devices that are connected directly to the machine running the data acquisition module (i.e., not over a network connection), and for sampling rates below 1kHz, transmission latency and jitter may be expected to be below a sample's duration.
*Event time stamps must refer to the same physical time base that is used to stamp acquired data packets. This limits the use of events to BCI2000 modules that run on the same machine as the data acquisition module. While the event API is available to all BCI2000 modules, it is advisable to use events in data acquisition modules only, thereby ensuring correct operation also in situations where processing modules are distributed across multiple machines in a network.
*Event time stamps must refer to the same physical time base that is used to stamp acquired data packets. This limits the use of events to BCI2000 modules that run on the same machine as the data acquisition module. To ensure correct operation also in situations where processing modules are distributed across multiple machines in a network, the event API may be used only in data acquisition modules.
*The <tt>bcievent</tt> asynchronous stream interface should only be called between "StartRun" and "StopRun".  Logging events with <tt>bcievent</tt> outside of a run could result in delayed state logging through the <tt>bcievent</tt> interface.
*The <tt>bcievent</tt> asynchronous stream interface should only be called between "StartRun" and "StopRun".  Logging events with <tt>bcievent</tt> outside of a run could result in delayed state logging through the <tt>bcievent</tt> interface.



Revision as of 18:09, 7 November 2011

This page describes how to record asynchronous information ("events") along with brain signal data. This usage of the term "event" is unrelated to "events" as part of BCI2000 API class interfaces.

As data are recorded by data acquisition hardware in chunks, BCI2000 processes them synchronously. Still, recording information that is asynchronous to brain signal data acquisition may be of interest to an experimenter. Typically, mouse or keyboard input may be of interest to record in an experiment, and ideally should provide a temporal resolution that corresponds to the brain signal's sampling rate.

Concept

In the BCI2000 programming API, asynchronous information may be represented as Events.

Here, an Event is an object that

  • consists of two elements: a string descriptor and a time stamp, and
  • is recorded in a data file together with brain signals.

Implementation

In the current version of BCI2000, events are mapped to state variables. By comparing an event's time stamp to data acquisition time stamps, it is possible to associate events with single samples, and to map an event to a change in a state variable's value.

Limitations

  • Time stamps have millisecond resolution. Up to sampling rates of 1kHz, this is not a practical restriction though.
  • Association of event time stamps with sample positions cannot be more accurate than time stamps assigned to data blocks by the data acquisition module. If data transmission latency between data acquisition hardware, and its associated jitter, are large compared to a single sample's duration, then event positions cannot be expected to be precise. Still, for data acquisition devices that are connected directly to the machine running the data acquisition module (i.e., not over a network connection), and for sampling rates below 1kHz, transmission latency and jitter may be expected to be below a sample's duration.
  • Event time stamps must refer to the same physical time base that is used to stamp acquired data packets. This limits the use of events to BCI2000 modules that run on the same machine as the data acquisition module. To ensure correct operation also in situations where processing modules are distributed across multiple machines in a network, the event API may be used only in data acquisition modules.
  • The bcievent asynchronous stream interface should only be called between "StartRun" and "StopRun". Logging events with bcievent outside of a run could result in delayed state logging through the bcievent interface.

Event API

When including the src/shared/accessors/BCIEvent.h header file into a source code file, a symbol bcievent will be available. The bcievent symbol behaves like a std::ostream; writing to that stream creates an event, fills its descriptor with whatever has been written into the stream, and stamps the event with current time. The bcievent symbol's ostream behavior makes it convenient to include numeric information into the event's string descriptor. To allow for true asynchrony, BCI2000 events may be issued from any thread within a BCI2000 module, i.e. the bcievent interface is thread-safe.

Descriptor Syntax

An event descriptor consists of a name, a value, and optionally a duration, with data fields being separated with white space:

<name> <value> [<duration>]

Currently, events are mapped to state variables, so the following restrictions apply:

  • The name field must match the name of a state variable, and that state variable must exist in the system before it appears in an event.
  • The value field must specify an unsigned integer value that "fits into" the number of bits reserved for the corresponding state variable.
  • Currently, the duration must either be omitted, or 0. When mapping the event to a state variable, a duration of 0 means that the state variable is set to the specified value for a single sample only, and to zero for subsequent samples. A non-specified duration means that the state variable is changed, and keeps its value for subsequent samples.

Example

In this example, an event "MyEvent" will be created, its value field set to currentValue, and its duration field empty. Please note that the name is followed with a space character separating name and value. The event will be time stamped either when the stream is flushed explicitly, as indicated for the "AnotherEvent" event, or when the bcievent object goes out of scope, as indicated for the "MyEvent" event. Unless there is time-consuming code between the bcievent statement, and the next closing brace, there is no need to explicitly flush the bcievent stream object.

#include "BCIEvent.h"
...
using namespace std;
...
{
  int currentValue;
  ...
  bcievent << "MyEvent " << currentValue; 
  bcievent << "AnotherEvent " << currentValue << flush; // AnotherEvent is time stamped here
  ...
 } // MyEvent is time stamped here

See also

Programming Reference:Environment Class, Technical Reference:State Definition, Programming Tutorial:Implementing an Input Logger

Events are used to implement keyboard, mouse, and joystick logging: User Reference:Logging Input