Obtaining the current Run number in a filter

Forum for software developers to discuss BCI2000 software development
Locked
pieterlaurens
Posts: 4
Joined: 16 May 2006, 06:02

Obtaining the current Run number in a filter

Post by pieterlaurens » 31 Oct 2006, 07:22

Is it possible to obtain the value of the current Run in the StatFilter (or any filter during SignalProcessing)? Parameter("SubjectRun") apparently keeps returning the initial value. Using the object BCIDirectory has not solved my problem (possibly due to insufficient c++ skills for which i apologize).

I want to write log files from filters. They should create a new log file each time the system enters the Resting state, and incorporate R0x in the filename , similar to the .dat file. (Of course I would prefer the R0x in the log file to correspond to the R0x in the .dat file). So I plan to call the same code in Initialize() and in Resting(). This would make analysis of the relation between logs and obtained data easier.

Best,
Pieter Laurens Baljon
Groningen

mellinger
Posts: 1341
Joined: 12 Feb 2003, 11:06

Post by mellinger » 31 Oct 2006, 15:19

Peter,

unfortunately, there is no simple solution to your problem.
Basically, file i/o is considered a task that should be handled transparently by the Source module, such that any change in file format, or directory structure is possible without affecting other modules.

Also, BCI2000 is designed such that its modules may be distributed over multiple machines. This means that a SignalProcessing module cannot be sure to write to the same directory as the Source module does, even if their absolute paths are identical!

At the same time, there exists code that actually does write log files into the data directory. To alleviate the problem, there is a LogFile class in BCI2000/shared/LogFile.* which is intended to build an abstraction layer around such behavior, and allow for future implementation changes without breaking filter code. In the future, all log file i/o in the "core" BCI2000 filters will be rewritten to use this class.

Unfortunately, the LogFile class considers a log file a per-session entity, and thus does not give you exactly what you want.
If you can't modify your log file concept to fit the functionality provided in the LogFile class, you might use the following code to obtain the run number during your filter's Process() member function (assuming your filter has an int member called mRunNumber, and a constant called unknown=-1 to indicate an invalid run number):

Code: Select all

MyFilter::MyFilter()
: mRunNumber( unknown ),
  ...
{
  ...
}

void MyFilter::StartRun()
{
  mRunNumber = unknown;
}

void MyFilter::Process(...)
{
  if( mRunNumber == unknown )
  {
    mRunNumber = BCIDirectory()
                 .SubjectDirectory( Parameter( "FileInitials" ) )
                 .SubjectName( Parameter( "SubjectName" ) )
                 .SessionNumber( Parameter( "SubjectSession" ) )
                 .RunNumber( Parameter( "SubjectRun" ) )
                 .FileExtension( ".dat" )
                 .RunNumber() - 1;
    ... // open the current log file here
  }
  ...
}
The reason why you need to initialize the run number (and probably open the log file as well) from Process() is that there is no guarantee that the Source modules' StartRun() functions will be called before the SignalProcessing modules' StartRun() functions, so you cannot be sure that the current data file exists at the time when BCIDirectory::RunNumber() is called.

The code is a hack, and will definitely break under the following circumstances:
(1) Source and SignalProcessing run on different machines.
(2) The Source module is configured to use a file format different from BCI2000 dat files for output (currently, EDF/GDF and "no output" are available as well via a --FileFormat-<format> command line switch).

Hope this helps,
Juergen

Locked

Who is online

Users browsing this forum: No registered users and 0 guests