Jump to content

Technical Reference:State Definition

From BCI2000 Wiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

This page describes the concept of BCI2000 states, in conjunction with their textual representation as a "state line".

For information about how to access state values from code, please refer to Programming Reference:Environment Class. For information about individual states, please refer to User Reference:States.

State Concept

States are variables that represent the internal state of a BCI2000 system as it is evolving over time in response to:

  • brain signal input
  • user interaction through the operator interface
  • trial sequencing by the application module.

Typical quantities/qualities encoded by states are:

  • whether the system is running or suspended
  • the time when a block of data was recorded
  • stimulus or task being presented
  • the classification result
  • the state of an external marker (trigger) to be saved for off-line analysis.

Typically, state values change once per block of data, or once per trial, but are recorded per-sample in case better resolution is required. In a BCI2000 data file, the full set of states is stored along with the data, allowing for reconstruction of on-line system state off-line.

Setting a state at a particular sample position in the current data block will set it to that value for all future time points. To ensure proper behavior of states at block boundaries, a special carryover value exists at the end of the state vector that does not correspond to any sample position but is used to initialize a state's values when a new block of brain signal data arrives.

Kinds of States

Depending on subtle differences in behavior, states come in three different flavors, or kinds. All of them are recorded per-sample (of the original brain signal data), and all of them are available as "States" when reading a data file.

Events

Events are states that can be written to asynchronously, using the bcievent interface. Event data are collected in a queue along with time stamps, and aligned to samples with a maximum resolution of 1ms immediately after a new block of data has been recorded.

Use an event state if you want to record the time of processing or of a physical input.

Streams

Streams are states that are intended to be used like additional source channels, being recorded synchronously with incoming brain signals. For an example how to use streams in conjunction with the BufferedADC class in a BCI2000 source module, see this tutorial.

Another use of streams is "annotation" of data samples during processing, e.g. with an "Artifact" marker. This cannot be done with plain states because they are delayed by a block (see below).

Use a stream state if you want to mark a certain sample or store synchronous information with the recorded brain signal.

States

The third kind of states is called Plain State, or just State.

With regard to brain data, plain states are delayed by one block. The original BCI2000 standard required that the plain states saved with a data block are the ones that existed when the data left the ADC, i.e. the previous state data but with the current timestamp. Thus, for backward compatibility, plain states are delayed by one block.

Use plain states to control the state of processing and/or application.

State Vector

In a BCI2000 system, a collection of states is maintained as a State List. For each state present in that state list, its value is kept as a range of bits in a bit vector called State Vector. BCI2000 modules and filters may read and write state values during processing. The state vector's content is saved, in its binary form, into BCI2000 data files per-block. Using the ByteLocation, BitLocation, and Length fields from the state definitions present in a file, a state's value may be read from the data file.

A state vector is a narrowly packed bit field in little endian ordering. This implies that, for a state containing more than a single bit, more significant bits are placed at higher bit and byte locations.

As an example, consider a state vector consisting of a 1-bit state "Running", and a 16-bit state "SourceTime". This will result in a three-byte state vector layout like this:

State Vector Byte 0 State Vector Byte 1 State Vector Byte 2
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
Running SourceTime unused
0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  

To make reading and writing of state values more efficient, padding states may be present in a state vector. They don't carry information but avoid states to extend across byte boundaries, and provide additional bytes required to access full 4-byte values. To separate padding states from actual states, padding states' names are formed from two underscores, the word "pad", and a current number as in __pad0, __pad1, __pad2, and so on.

State Lines

State lines are a human-readable format used to represent individual states in

Core modules and the operator module use this format to communicate in the system initialization phase, as well as during system performance and for system termination.

The format of a state line is

Name Length Value ByteLocation BitLocation CRLF

where Length refers to the number of bits used to represent the state's value, and ByteLocation and BitLocation refer to its position in the State Vector, with BitLocation ranging from 0 to 7.

Depending on the context of a state line, one or more of its fields will be redundant:

  • In a State message sent from a core module to the operator module, ByteLocation will be ignored, and BitLocation will change its meaning, and transport information about the state kind (see below).
  • In a State line contained in a data file, the Value field matches the state's value stored with the first block of data samples.
  • If BitLocation is negative, it represents the state variable's kind. The following values are defined:
-1 Padding state, -2 State kind, -3 Event kind, -4 Stream kind.

Generally, the Value field specifies an initial value of a state. Actual values are stored in the State Vector data structure.

State values are interpreted as unsigned integers, and limited to 32 bit in the current implementation (as defined by the State::ValueType typedef in BCI2000/src/shared/types/State.h).

Alternate version of State Lines

With the existence of different kinds of states, and the need to transfer those between modules, a new version of state lines was introduced. It is only used between core modules that support it, and the Operator module.

Its format is

Name Kind Length Value Location CRLF

where Kind may be one of

  • 0: Padding state,
  • 1: State kind,
  • 2: Event kind,
  • 3: Stream kind,

and Length refers to the number of bits used to represent the state in the state vector. As before, the Value field specifies the state's initial value. Finally, the Location field represents the same information as the BitLocation and ByteLocation fields above, albeit in a single number:

Location = ByteLocation * 8 + BitLocation

See also

User Reference:States, Technical Reference:Parameter Definition, Programming Reference:Events, Programming Reference:States