Event Markers and BCI2000

Forum for software developers to discuss BCI2000 software development
Post Reply
spine
Posts: 13
Joined: 02 Mar 2020, 22:07

Event Markers and BCI2000

Post by spine » 13 Jun 2020, 19:43

Hello BCI2000 Community,

I hope everyone is doing well and is safe.

We are using BCI2000 to record EEG data, so no BCI's just yet ;) However, we do have the typical cursor task paradigm set-up with the signal source module, application module, etc all working with our Dry EEG system if that helps in answering the question. We are using an Arduino controlled device though for this question.

If we record EEG data with BCI2000, how do we send event markers (The event being the stimulation device has turned on) as accurately as possible without the use of a trigger box? The device is controlled using Matlab commands and all event times are stored in Matlab but are misaligned when the recording of BCI2000 starts and when we run Matlab separately.

I think there are three ways we can solve this problem in a real-time recording or offline:

1. In real-time: Connect Matlab and BCI2000, so when a command is sent from Matlab to the device, a command is sent to BCI2000 as well to mark the event (The event, again, is that the device has turned on) in a real-time recording.

2. In real-time: The moment the Arduino device is turned on, a signal is sent to BCI2000 as the data is being recorded and the event is marked in a real-time recording.

I read on the wiki there is this option (Please see attached Event MarkerQuestion.jpg). Is there more to this or is this the solution to our problem? If we do use the C++ or the Matlab implementation presented on the Wiki, how do we check the delay of our system?

3. Offline: After the experiment is done, match up the times in BCI2000 with the times that the commands were sent in Matlab after the recording is finished.

Previous discussions on this forum said to look at the App Connector, but the wiki

(https://www.bci2000.org/mediawiki/index ... _Connector)

says it's superseded by other BCI2000 code, so if there is another wiki link it would help:

Thank you so much, everyone!
Attachments
Event MarkerQuestion.JPG
Event MarkerQuestion.JPG (50.33 KiB) Viewed 1639 times

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

Re: Event Markers and BCI2000

Post by mellinger » 15 Jun 2020, 10:48

Hi,

for writing triggers to BCI2000, do the following:
  • define a state variable of type "event" in your batch file before modules are started:

    Code: Select all

    Add event Foo 1 0
  • open a TCP socket connection to localhost on port 3999 when the operator module has been started
  • send the following text through the socket connection to record a trigger:

    Code: Select all

    Pulse event Foo CRLF
    CRLF means send a carriage return followed with a line feed character to end the line.
BCI2000 will take a timestamp of the moment in which the "Pulse event" command is received, and will use the timestamp to align the command with incoming samples. Then, it will set the "Foo" event to 1 for the duration of the sample which is closest to the timestamp.

When loading the recorded data file into Matlab, you will find an entry "Foo" under "States". find(filedata.States.Foo==1) will give you the sample positions where the trigger occurred.

HTH,
Juergen

spine
Posts: 13
Joined: 02 Mar 2020, 22:07

Re: Event Markers and BCI2000

Post by spine » 16 Jun 2020, 22:51

Hi Juergen,

So the data can be saved and there is a marker titled Foo under states.

But, there doesn't seem to be the marker of event type "1" in Foo.

So either the TCP/IP connection did not send the "Pulse event Foo CRLF" properly or the operator did not receive it properly. I think it is the latter.

I am not sure which of the two is occurring, so here is my Matlab code:

Code: Select all


t = tcpip('localhost',3999);

fopen(t);

fprintf(t,'Pulse event Foo CRLF');

%Event sent to Arduino

and here is the batch file code:

Code: Select all



Change directory $BCI2000LAUNCHDIR
	Show window; Set title ${Extract file base $0}
		Reset system

Add event Foo 1 0

Startup system localhost

Start executable DSISerial		 --local --DSISerialPort=COM3
Start executable DummySignalProcessing --local
Start executable DummyApplication --local

Wait for Connected

I did check my firewall to allow everything through and I have admin rights.

Let me know your thoughts!

Thanks!

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

Re: Event Markers and BCI2000

Post by mellinger » 17 Jun 2020, 08:30

Hi,

CRLF means send a carriage return followed with a line feed control character. In a Matlab string, this is written as

Code: Select all

'\r\n'


HTH,
Juergen

spine
Posts: 13
Joined: 02 Mar 2020, 22:07

Re: Event Markers and BCI2000

Post by spine » 17 Jun 2020, 17:13

Hi Juergen,

Following the last post, I now have:

Code: Select all

    fprintf(t,'Pulse event Foo \r\n');
And...there isn't an event listed for Foo.

This should be independent of what has been discussed thus far, but are things not working yet because we don't have an Eventlogger in the source module?

Could you point me in the right direction as to where I should look for a bug or at least what more information you would need to better address the issue?

Thanks again!

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

Re: Event Markers and BCI2000

Post by mellinger » 18 Jun 2020, 09:44

are things not working yet because we don't have an Eventlogger in the source module?
You need the EventLogger extension in the source module. If you don't have it, it won't work.

-Jürgen

spine
Posts: 13
Joined: 02 Mar 2020, 22:07

Re: Event Markers and BCI2000

Post by spine » 18 Jun 2020, 10:11

Hi Jürgen,

If the Matlab to BCI2000 approach will not work (Even if we use LSL as a source module-it doesn't have an EventLogger), then do you have any other recommendations on how to resolve this issue? There is a trigger channel in the DSIserial module, so could we send event signals to a channel in BCI2000 from Matlab?

If it helps, when I use TCP/IP view for windows, there is a port for the Operator module 3999.

Would we need to code up an application module on our own to connect to the Arduino device to get the timings correct? Would BCI2000 even be applicable to our issue at this point? If not, from your experience do you know of any other way to record events for EEG in general?

Thank you once more for answering my questions. It really means a lot!

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

Re: Event Markers and BCI2000

Post by mellinger » 18 Jun 2020, 11:14

Even if we use LSL as a source module-it doesn't have an EventLogger
How do you know it doesn't have the EventLink component? In the Operator, check for presence of the System->EventLink parameter. If it is present, you have the EventLink component in the source module. Make sure it is enabled. Also, any recent build of BCI2000 should have it in all source modules. In case you received an outdated build of the DSISource module from DSI, you might consider switching to a more current one from the BCI2000 website.
There is a trigger channel in the DSIserial module, so could we send event signals to a channel in BCI2000 from Matlab?
The trigger channel will record signals from the EEG amplifier's digital inputs. You would need to control a matching digital output from the Matlab side.

-Jürgen

spine
Posts: 13
Joined: 02 Mar 2020, 22:07

Re: Event Markers and BCI2000

Post by spine » 18 Jun 2020, 11:45

Hi Jürgen,

There is an Eventlink component! Is there something I am doing wrong in the Matlab code in sending a signal I shared earlier in our discussion even after changing the CRLF command string as you suggested? Should I be using UDP instead of TCP/IP?

I think the signal is being sent by Matlab. Most likely, BCI2000 isn't receiving/interpreting the signal properly. Should all strings sent to 'localhost',3999 be converted to uint8 first? Perhaps it would help, if you are familiar with opening connections in Matlab, if you could point me in the right direction on the syntax of opening and sending the right connection in Matlab.

Thanks! I think we are very close to resolving this issue.
Attachments
EventLink.PNG
EventLink.PNG (46.42 KiB) Viewed 1576 times

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

Re: Event Markers and BCI2000

Post by mellinger » 19 Jun 2020, 05:45

Hi,

it seems that Matlab doesn not interpret the control characters properly.
Following https://www.mathworks.com/help/instrume ... -host.html, you might try

Code: Select all

t.Terminator = {'LF', 'CR/LF'}; % example code uses double quotes but I think that is an error
fprintf(t, '%s\n', 'Pulse event Foo');
Maybe that helps.
-Jürgen

spine
Posts: 13
Joined: 02 Mar 2020, 22:07

Re: Event Markers and BCI2000

Post by spine » 19 Jun 2020, 10:17

Hi Jürgen,

Still not seeing the events being registered...Any other potential ideas?

From this current setup, everything is done on the PC recording the data: The recording and the timing. Theoretically, would this mean that each trigger would not lead to a constant event marker each time an event occurs? Here is an example of what I mean:

If an event occurs at t=5s, the current set-up places a marker at 4.98 seconds Another event occurs at t=10s, and the current set-up places a marker at t=9.90s. Thus, the delays are not constant across these two events (0.02s vs 0.1s).

Thanks!

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

Re: Event Markers and BCI2000

Post by mellinger » 21 Jun 2020, 13:59

I think it might be a good idea to read any error messages arriving through the socket, e.g. using fgetl().
Also, are you sure your Matlab fprintf() code is called at all?
If an event occurs at t=5s, the current set-up places a marker at 4.98 seconds Another event occurs at t=10s, and the current set-up places a marker at t=9.90s. Thus, the delays are not constant across these two events (0.02s vs 0.1s).
Sure, the Windows scheduler uses time slices of up to 20ms but typically timing is much better than that, as you may see in the BCI2000 timing window when considering the variance of block duration. If you need high precision trigger information, then you need to use the amplifier's digital inputs.

-Juergen

spine
Posts: 13
Joined: 02 Mar 2020, 22:07

Re: Event Markers and BCI2000

Post by spine » 22 Jun 2020, 23:49

Hi Jürgen,

Here are the most recent updates:

1. I have attached the fgetl() output (Titled TCPIPCheck).

2. When I have 'Pulse event Foo', there 's still no record of a "Foo" event occurring (No value of 1 in the event vector).

3. After doing more digging on the documentation, I tried to do 'Pulse event Foo 1' instead of 'Pulse event Foo': With the timings, window displayed and repeatedly running fprintf with an open socket, I occasionally get the following: Matlab will take a bit longer to run and a warning appears (Timeout2). Timeout1 shows a flat line during the time that Matlab takes to run. This effect is occasional, even when running the section in the code trying to fprintf. Is this something that is probably to be expected?

So it does seem the signal is, indeed, being sent by Matlab and, BCI2000 creates the event Foo.

The question is, why is Foo not being registered during the experiment? Is there something wrong with the way Foo is setup with the binwidth? Should we be using a UDP connection instead? I have been running this one section of code each time, independent of the device:

Code: Select all

%% Open tcpip
t = tcpip('localhost',3999);
fopen(t);

%% Test stimulus
t.Terminator = {'LF', 'CR/LF'}; 
fprintf(t, '%s\n', 'Pulse event Foo');
Perhaps you can try it out yourself with a dummy signal source module to catch anything, as I am not sure where to move on from here.

Thanks again Jürgen!
Attachments
TCPIPCheck.PNG
TCPIPCheck.PNG (44.86 KiB) Viewed 1512 times
Timeout2.PNG
Timeout2.PNG (7.26 KiB) Viewed 1514 times
Timeout1.PNG
Timeout1.PNG (37.62 KiB) Viewed 1516 times

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest