Synchronizing Ganglion data with corresponding task data? [resolved]


I have a set of timestamps related to my task which include the timestamps for suspected event-related potentials (ERPs). I should mention that task timestamps are tied to whenever a subject makes an input action in the task. The tasks (mainly programmed in Python) and EEG recording are all done on that same computer simultaneously. What I would like to do is then sync the task timestamps with the EEG data recorded via OpenBCI GUI on a Ganglion board. Below are the approaches I have tried so far (both which are flawed). In essence, I'm wondering if there is a better way to sync my EEG data and potentially get the actual "latent" timestamps for when every EEG data sample was recorded (maybe even better approximate the latent timestamps). In addition, I have added some potential misconceptions on my part at the end of this post that might be contributing to my flawed approaches.

Approach 1: syncing based on the assumption of a static sampling rate

The first approach, maybe the most flawed, I tested for synchronizing was assuming that every sample was recorded 200 Hz. Thus, each sample could then be represented as (1/200) * sample_number. For instance, if I wanted the theoretical timestamp of the 1000th sample I would compute (1/200) * 1000 = 5 or the timestamp corresponding to the 5th second.

After syncing the EEG data recording with the start of my task I then attempted to use the aforementioned theoretical formula for computing timestamps for each EEG data sample. Once doing so I attempted to sync these "synthetic" timestamps with my actual task timestamps. This leads to no ERP signal averages being observed (see image below). This indicates to me that my synthetic timestamps are not accurate in computing the actual latent EEG timestamps for the onset of my ERPs.

Example of ERP synced via theoretical timestamps

Approach 2: syncing based on OpenBCI text file timestamps

From what I understand syncing with the timestamps provided by the OpenBCI GUI text file is not advised. It sounds like these timestamps are not the timestamps for when an EEG sample was recorded, rather when an EEG sample was received and processed by the host computer. I have tried using these timestamps to sync to my data regardless for testing purposes. In doing so, I have achieved the plotting of signal averages for my ERPs although they seem slightly distorted (Ne peak, around 200ms, is shorter than reported). I'm assuming this distortion is due to the jitter in the delay of the recorded EEG timestamps (since the recorded timestamp for the EEG is tied to when the computer receives and processes a sample).

I've also read this post regarding syncing with timestamps. It sounds like they ended up using some form of external trigger. If I can, I'd like to avoid this. As I have mentioned, both the task and BCI recording are done on the same computer. So, I'm wondering if there is way to integrate the task and BCI recordings to get more accurate EEG timestamps. The aforementioned post also mentioned using LSL and triggers although I'm quite unclear how LSL and OpenBCI interact (any help or clarification around this interaction would be greatly appreciated).

Example of ERP synced via EEG recorded timestamps


Board: Ganglion
Firmware: 1.0.0 (Updated to 2.0.1 as of making this post)
GUI: 4.2.0
OS: Ubuntu 18.04
Dongle: BLED112
Computer for recording: Lenovo YOGA 720

Potential misconceptions I have related to the Ganglion board

My first potential misunderstanding about the Ganglion board is that it seems to record 201 samples per second in the OpenBCI text files. Although the claimed recording rate is 200 Hz. I saw a similar post but the explanation didn't quite click in my head. Any further clarification on this discrepancy would be greatly appreciated.

Another observation I noticed is that if I record EEG for 3 minutes the theoretical samples recorded are 180 * 201 = 36180 samples. The actual number of samples recorded by the OpenBCI text file tends to be 100-200 samples less than the theoretical. Is this a typical or might there be an issue on my end?

If anyone notices any other misconceptions I have displayed here please feel free to point them out!


  • wjcroftwjcroft Mount Shasta, CA

    BPoole, hi.

    Many other threads mention the inaccuracy of the GUI csv text file timestamps. These are not generated at the Ganglion, but instead when the packets arrive in the GUI or Hub, and hence have considerable jitter or drift. This is because of buffering in the OS, usb serial port, BLED112, and OS scheduling latencies. In the near future when the Hub is eliminated and replaced with direct BrainFlow library access by the GUI, timestamps will improve somewhat but still never be as reliable as an external trigger approach.

    Neither Cyton nor Ganglion have onboard crystal controlled clocks. So sample rate can be slightly different than specified. This is typically on the order of a tenth of a hertz or less.

    A suggestion would be to devote one of your Ganglion channels as an external trigger, using the approach mentioned at the end of this thread, TSL257 device:

    You would need to use a voltage divider (two resistors) to bring the trigger level down to say 20 to 50 microvolts.

    Regards, William

  • wjcroftwjcroft Mount Shasta, CA

    Note the minuscule sample rate difference I mentioned in the last comment IS CONSTANT. It does not jitter. So the technical term for this would be 'drift'.

  • wjcroftwjcroft Mount Shasta, CA

    Regarding your initial comment: "I should mention that task timestamps are tied to whenever a subject makes an input action in the task."

    Many P300 experiments are done using the oddball paradigm. In those cases there are 'output' actions that correspond to either a control or oddball stimulus. So an external trigger based on an external voltage or (portion of) screen illumination would be more applicable.

    In your case since you are doing 'input' operations, you might benefit from performing this with some type of Arduino single board computer, tied to the laptop via usb serial port. When the input button is pressed, this could simultaneously act as both input to your laptop program, AND also send a signal over to the Ganglion as an external trigger. Again you would need a voltage divider to get the input level at the Ganglion down to a low level, for example 50 microvolts.

    So the screen illumination / photodiode approach previously linked, might not be your best match for an external trigger idea.

  • edited March 2020

    Thanks for all your help, this clears up most of my questions!

    Even if the sampling rate varies by a tenth of a hertz or less is it not reasonable assume that if I record for 3 minutes I should have approximately 36000 samples? Then I could say every sample occurs approximately every 1/200th of a second. Or, is this still flawed thinking due to the variable sampling rate compounding over time?

  • wjcroftwjcroft Mount Shasta, CA

    Each individual Cyton or Ganglion is likely to have a sample rate differing slightly from the exact 250.000 or 200.000. I don't know what that number is in your case. But if you divide it out and find (for example), 200.23, then that value is a constant and will not change over the course of a session. Thus as I said, 'jitter' is very small if at all. This slight difference from exactly 200.000, is considered a constant 'drift' factor.

    200 * 180 seconds = 36000 samples
    200.2 * 180 seconds = 36036
    199.8 * 180 seconds = 35964

    "Then I could say every sample occurs approximately every 1/200th of a second."

    It's not 'approximate', it is very stable at the 1/ figure you arrive at.

  • edited March 2020

    Ahhh I see, this makes more sense. Thanks for bearing with me!

Sign In or Register to comment.