Event Markers and BCI2000
Event Markers and BCI2000
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!
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 (50.33 KiB) Viewed 34875 times
Re: Event Markers and BCI2000
Hi,
for writing triggers to BCI2000, do the following:
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
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:
CRLF means send a carriage return followed with a line feed character to end the line.
Code: Select all
Pulse event Foo CRLF
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
Re: Event Markers and BCI2000
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:
and here is the batch file code:
I did check my firewall to allow everything through and I have admin rights.
Let me know your thoughts!
Thanks!
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
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
Let me know your thoughts!
Thanks!
Re: Event Markers and BCI2000
Hi,
CRLF means send a carriage return followed with a line feed control character. In a Matlab string, this is written as
HTH,
Juergen
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
Re: Event Markers and BCI2000
Hi Juergen,
Following the last post, I now have:
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!
Following the last post, I now have:
Code: Select all
fprintf(t,'Pulse event Foo \r\n');
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!
Re: Event Markers and BCI2000
You need the EventLogger extension in the source module. If you don't have it, it won't work.are things not working yet because we don't have an Eventlogger in the source module?
-Jürgen
Re: Event Markers and BCI2000
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!
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!
Re: Event Markers and BCI2000
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.Even if we use LSL as a source module-it doesn't have an EventLogger
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.There is a trigger channel in the DSIserial module, so could we send event signals to a channel in BCI2000 from Matlab?
-Jürgen
Re: Event Markers and BCI2000
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.
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 (46.42 KiB) Viewed 34812 times
Re: Event Markers and BCI2000
Hi,
it seems that Matlab doesn not interpret the control characters properly.
Following https://www.mathworks.com/help/instrume ... -host.html, you might try
Maybe that helps.
-Jürgen
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');
-Jürgen
Re: Event Markers and BCI2000
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!
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!
Re: Event Markers and BCI2000
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?
-Juergen
Also, are you sure your Matlab fprintf() code is called at all?
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.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).
-Juergen
Re: Event Markers and BCI2000
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:
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!
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');
Thanks again Jürgen!
- Attachments
-
- Timeout1.PNG (37.62 KiB) Viewed 34752 times
-
- Timeout2.PNG (7.26 KiB) Viewed 34750 times
-
- TCPIPCheck.PNG (44.86 KiB) Viewed 34748 times
Who is online
Users browsing this forum: Google [Bot] and 17 guests