Programming Reference:Environment Class

From BCI2000 Wiki
Jump to: navigation, search

Environment is a mix-in class that provides access to system-wide parameters and states. Though client classes may directly inherit from it, most do so via interface classes that themselves do inherit from the Environment class, most importantly the GenericFilter and EnvironmentExtension classes.

Your code's Environment

In each BCI2000 core module, there exist system wide parameters and states. In the BCI2000 C++ framework, access to parameters and states is mediated through a class Environment. This class provides functions for convenient access to parameters and states, and transparently handles a number of error conditions that might occur. The services provided by the Environment class interface are available to all classes that inherit from it. For GenericFilter descendants, this is automatically the case; for other classes, you need to explicitly state the inheritance as in

#include "Environment.h"
MyClass : private Environment

Access to Parameters and States

From any code inside MyClass, you may then read or set parameter and state values simply by writing

int numberOfItems = Parameter( "NumberOfItems" );
float listValue = Parameter( "ListParam" )( index );
float matrixValue = Parameter( "MatrixParam" )( index1, index2 );
float nestedMatrixValue
  = Parameter( "NestedMatrices" )( index1, index2 )( index3, index4 );
short feedbackState = State( "Feedback" );
State( "Feedback" ) = 0;

State values are treated as unsigned integers, unless accessed with AsFloat() or AsSigned():

float stateValue = State( "Floatstate" ).AsFloat();
State( "Floatstate" ).AsFloat() = 1.2345e6;

When accessed with AsSigned(), a state's most significant bit is treated as a sign bit, and extended to all leading bits of the value returned. E.g., for a 3-bit-state, a unsigned value of 7 will be interpreted as a signed value of -1, and an unsigned value of 6 will be interpreted as a signed value of -2.

In more recent versions of BCI2000, state values are maintained individually for each sample position. Typically, this is used to record information such as mouse or keyboard input on a per-sample basis, while filter code acts per sample block, and will rarely need to access state information per-sample. Still, this is possible using an additional sample index in its own pair of brackets.

int mousePosX = State( "MousePosX" )( 3 );
State( "Artifact" )( 5 ) = 1;

Note that setting a state at a certain sample position will set all future state samples to that value. To set a single sample, or range within the current sample block, use

State( "Artifact" )( 5 ) = 1;
State( "Artifact" )( 6 ) = 0;

In addition to the state vector information provided for sample positions of the current data block there is an additional state vector sample appended, representing the subsequent block's first sample. Modifying this state vector sample allows to specify an initial value for the next block's state vector.

If you try to access a parameter or state that does not exist, an appropriate error message will be sent to bcierr, so you don't need to handle this type of error explicitly. For a greater independence between modules, it is sometimes desirable to read a parameter or state if it exists, and use a default value otherwise.

You achieve this by writing
int numberOfItems = OptionalParameter( "NumberOfItems", defaultValue );
short itiState = OptionalState( "IntertrialInterval", 0 );

Omitting the default value from the OptionalState or OptionalParameter call implies a default value of 0, or the empty string, whichever is appropriate.

The Environment class imposes rules for parameter and state access intended to help avoid parameterization inconsistencies.

See also

Programming Reference:Errors and Warnings, Programming Reference:ApplicationWindowClient Class