Showing posts with label Signals. Show all posts
Showing posts with label Signals. Show all posts

Saturday, October 25, 2014

Alpha Detection - Comparison Across EEG Recordings

In the previous analysis, I used ROC curves to determine that the a good trade-off between good detection sensitivity and low false alarms occurs when my alpha detection threshold is at 3.55 uVrms and my guard rejection threshold is at 2.55 uVrms.  These threshold values allowed me to successfully detection 56% of the eyes closed data blocks, while having zero false detections.  As follow-up, I promised that I'd look at more additional recordings of my Alpha waves to see if these threshold values were also appropriate for other EEG recordings.  Well, below are the results on 6 recordings.  As you can see, the results are mixed.

Sensitivity and False Alarm Rate for an Alpha Detection Threshold of 3.75 uV and a Guard Rejection Threshold of 2.5.  As you can see, there is a large variation in detection sensitivity and false alarm rate across the six different EEG recordings.
Multiple Files:  The plot above includes data from six EEG recordings.  The data files are specified in my Python analysis code here.  File 1-3 were from Oct 4, File 4 was from Oct 5 and was the subject of all my recent posts, File 5 was from May 31 (from my robot control) and File 6 was from May 8.  As you can see in the plots above, File 4 (the one discussed in my recent posts) was a very high quality recording because it was easy to detect the Alpha waves with high sensitivity (left plot) and with few false alarms (right plot).  By comparison, File 3 and 5 were much more challenging becuase, for the same detection thresholds, we get far lower sensitivity (left) plot) and far higher false alarms (right plot).  How do we decide the best thresholds to use for all files?

Lumped ROC Curve:  If we lump together all 6 sets of data, we can compute the receiver operating characteristic (ROC) curve, as we discussed in my previous post.  The plot below shows the ROC curve for all of the EEG data lumped together.  It shows that, if we were to target a false alarm rate of 1 false alarm per minute, we could achieve an Alpha detection sensitivity where we detection ~40% of all the data blocks where my eyes are closed.  It's not great, but it's not bad, either.

Lumping Together All 6 EEG Recordings, We Can Evaluate the Relationship Between Sensitivity and False Alarms When using Our Alpha Band vs Guard Band Detection Approach.

Detection Thresholds to Use:  If we wish to achieve a target false alarm rate of 1.0 per minute, our ROC analysis also yields the results below, which shows which threshold values to use for our Alpha detection criteria (3.8 uVrms) and for our guard rejection criteria (1.6 uVrms).

Thresholds to Use for Achieving 1.0 False Alarms Per Minute for All Six EEG Files Lumped Together Using the Alpha
+ Guard Discrimination Approach.

Better Detection Performance:  Using these two detection thresholds determined through the lumped data analysis above, we can evaluate the sensitivity and false alarm rate for each individual EEG recording.  These results are shown below.  As expected, File 3 and File 5 still have the lowest sensitivity.  File 2, however, now has the highest false alarm rate.

Detection Sensitivity (Left) and False Alarm Rate (Right) When Using the Detection and Rejection Thresholds That Should Yield an Overall False Alarm Rate of 1.0 Incorrect Detections Per Minute.

Is it Good Enough:  While these plots seem OK enough, is it good enough?  Well, that can only be answered by looking at the detection plots for the individual recordings.  Plots of the six recordings are presented blow, if you really want to see the details...click on any one of them to see a bigger version.  When I look at these figures, I'm feeling pretty good about these detection thresholds.


Files 1,2: 
Files 3,4: 


Files 5,6:


Next Steps:  Having established a good set of detection thresholds, we have two paths forward.  One path would be to continue this analysis to find other types of detection algorithms that, via the ROC curve, might show better detection performance.  Another approach would be to implement these detection threshold values in the real-time GUI to see if it give good performance.  I'm not sure which direction I'll take, but given that the Air Force Hackathon is starting shortly (which I and OpenBCI will be attending), I bet my next step will indeed involve actual hacking.  Let's do it!

Sunday, October 19, 2014

Detected Alpha Waves - ROC Curves

In my previous post, I improved my Alpha detection processing by introducing "guard bands", which allowed me to reject most of the non-Alpha activity that looked like Alpha waves.  In finding the best thresholds to use for detecting and rejection, I had to find the right balance between keeping good sensitivity (ie, detecting most of the true Alpha activity) while minimizing false alarms (ie, avoiding detecting non-Alpha activity as if it were Alpha).  Finding the right balance can be tough and can involve lots of guesswork.  In this post, I'll show how that process can be formalized...by making a ROC curve!

Example EEG data (top) and some example processing (middle and botom).  True Alpha activity is limited to the "Eyes Closed" period.  I used the amplitude in the Alpha band (blue trace) to detect the Alpha activity.  I used the amplitude in the Guard Band (green trace) to reject activity that is not specific to the Alpha band.  For my given detection threshold (Alpha > 3.5 uVrms) and rejection threshold (Guard > 2.5 uV), the red circles show when my algorithm detects Alpha activity.

Background:  The plot above shows the final result from the last post.  It shows the raw EEG data in the spectrogram at the top, as recorded from the back of my head (O1 with earlobe reference).  As you can see, when my eyes are closed, the horizontal stripe of color shows my Alpha rhythm.  The middle plot shows the amplitude of the EEG signal in the Guard band (I picked 3-6.5 Hz and 13-18 Hz) and the bottom plot shows the amplitude of the EEG signal in the Alpha band (7.5-11.5 Hz).  You can also see that, by eye, I picked a Guard rejection threshold of 2.5 uVrms and an Alpha detection threshold of 3.5 uVrms.  The red circles show the "detections" when the EEG signal satisfies the Alpha detection threshold (ie, is > 3.5 uVrms) and avoids the Guard rejection threshold (ie, is < 2.5 uVrms).  This works algorithm works way better than the Alpha-only detection approach that I used in my first attempt.  Theis Alpha+Guard algorithm isn't perfect, however.  You see that I still have a pair of false detections around 84 seconds.

Choosing the Thresholds, By Eye:  One of the key decisions in this algorithm is what value to use for the Alpha detection threshold and what value to use for the Guard rejection threshold.  Initially, I choose them by eye from the plots above and then used trial-and-error to tune them further.

Alpha-Guard Scatter Plot:  Another approach for choosing these thresholds is to use a dedicated plot such as the one below.  Here, I take the exact same Alpha and Guard values as plotted above and I re-plot the data.  But, instead of plotting the data as a smooth trace as a function of time, I plot the the data as a scatter plot of the Alpha and Guard value for each moment of time.  For each moment in time when my eyes are closed (which mean that true Alpha waves are likely present), I plotted the data point in blue.  For each data point outside of this time period (so Alpha are likely not present), I plotted the values in red.

For each moment in time, I measure the amplitude of the EEG signal in both the Alpha band and the Guard band.  Each dot in this plot represents the Alpha and Guard values for one moment in time.  The blue dots are from the time when my eyes were closed, so they should contain Alpha activity.  You can see how the Alpha threshold (black line) and Guard threshold (red line) can be used to try to discriminate between the two types of activity.

Choosing the Thresholds, Graphically:  With the Alpha-Guard scatter plot shown above, it is much easier to visually move the Alpha threshold (the horizontal black line) up-and-down, or to move the Guard threshold (the vertical red line) left-and-right.  Any points in the upper-left quadrant satisfy our detection rules (measured Alpha > Alpha Threshold and measured Guard < Guard Threshold).  The thresholds are currently shown at the values from my previous post -- Alpha Threshold at 3.5 uVrms and Guard Threshold at 2.5 uVrms.  We see that the vast majority of the detections are blue dots, which is good because that is the eyes-closed activity.  We also see the two false detections as the two red circles.  With this plot, we clearly see that if we raise our Alpha band a little bit, we could eliminate those two false detections...at the expense of losing more of the desired (blue dot) detections.  Again, we see that it's a balance between high sensitivity and a low rate of false alarms.

Try All Alpha and Guard Threshold Values:  To get a better picture of the effect that these two threshold values have on the sensitivity and false alarm rate, we can have the computer brute-force reprocess the data trying a wide range of threshold values.  By stepping through all the combinations of Alpha and Guard thresholds, the computer forms a dense table of the number of correct detections and the number of incorrect detections for our given EEG recording.  We can then use a contour plot to visualize this dense table of values.  These are shown below.

Effect on Sensitivity: The first plot below shows how the Alpha and Guard thresholds affect our detection sensitivity (the fraction of eyes-closed EEG activity was correctly detected).  The black "x" shows our current threshold values (3.5 uV for Alpha, and 2.5 uV for the Guard).  At the end of my previous post, I said that this achieved a sensitivity of 65%, which agrees with the plot below.  If I want higher sensitivity, this plot clearly shows that the ideal is toward the upper-left, which means lowering my Alpha detection threshold and raising my Guard rejection threshold.

After trying all combinations of Alpha and Guard thresholds (as shown by the black dots), we can see how the threshold values affect our sensitivity in detecting the true Alpha activity.  The highest sensitivity is in the top-left of this plot, meaning we want the lowest threshold for Alpha detection and the highest threshold for Guard rejection.

Effect on False Alarms:  The desire for high sensitivity, however, must be balanced by the need for a low false alarm rate.  The plot below shows how the threshold values affect the number of false alarms for this data set.  As before, the black "x" shows our current threshold values: 3.5 uV for Alpha, and 2.5 uV for the Guard.  In my previous post, I said that this point resulted in 2 false alarms, and the plot below agrees with that finding.  This plot says that if we want to further lower the false alarm rate, we need to move down and to the right, which is to lower our Guard rejection threshold and to raise the Alpha detection threshold.  This is exactly the opposite direction that was needed to increase our sensitivity.  Again, we're seeing that it is a struggle to optimize sensitivity versus false alarms

After trying all combinations of Alpha and Guard thresholds (as shown by the black dots), we can see how the threshold values affect the number of  false alarms (incorrect detection of non-Alpha activity).  The fewest false alarms are seen in the bottom-right of this plot, meaning we want the highest threshold for Alpha detection and the lowest threshold for Guard rejection.

Best Sensitivity for a Given False Alarm Rate:  Given that it is a trade between sensitivity and false alarm rate, how does one choose where to set the detection and rejection thresholds?  One approach would be to simply start by picking a number of false alarms that would seem to be be acceptable.  Then, one can search through the threshold values to find the combination that achieves the best sensitivity at the given false alarm rate.  That's what I did to make the plot below.  I used the dense grid of values before and directly plotted the sensitivity and false alarm count for every combination of threshold values.  Clearly, there is an upper limit running across this plot.  So, I added the green line to define the maximum sensitivity (for this detection algorithm) that can be achieved for any given false alarm rate.

A plot of the sensitivity versus number of false alarms for every combination of threshold values analyzed earlier.  There is clearly a maximum sensitivity value that occurs for each given false alarm rate.  This is Receiver Operating Characteristic (ROC) curve for this detection algorithm.
ROC Curve:  The green line in the plot above is a very useful tool for understanding the performance of the detection algorithm.  It is so useful that it has a name -- it is the "receiver operating characteristic" (ROC) curve for this detection algorithm.  The name is kinda funny because it originated in World War II during the development of radar.  In radar, one is trying to detect pulses of radio energy that have been reflected off distant aircraft.  When comparing different radar receivers, one can always appear to be more sensitive, though at the cost of increasing the rate of false alarms.  So, they developed the ROC curve as a way to make it easier to understand, compare, and optimize detection systems.  It was such an effective tool, that it has became a core technique in the general field signal detection and classification.

Comparing Alpha Detection Systems:  As an example of how useful it is in comparing detection "systems", the ROC curves below show the performance of "Alpha+Guard" algorithm versus my original "Alpha Only" detection algorithm.  As can be seen, the ROC curve for the Alpha+Guard algorithm is higher at point.  It is superior at any allowed false alarm rate.  Alpha+Guard is clearly superior.  Interestingly, this plot also exposes how the "Alpha Only" algorithm was never able to have less than 10 false alarms in this EEG recording.  If one cares about a low false alarm rate (which I certainly do), the ROC curve exposes this critical information.

ROC curves for two different detection algorithms: "Alpha+Guard" detects in the Alpha band and rejects based on the Guard bands, while "Alpha Only" does not include the rejection based on the Guard band.  The ROC curve for "Alpha+Guard" is higher at all false alarm rates, thereby showing its performance is superior.

Selecting the Operating Point:  The ROC curve is an excellent visualization for deciding which detection algorithm to use.  It is also helpful for understanding where the steepest trade-off exists between sensitivity and false alarms.  For the Alpha+Guard algorithm (unlike the Alpha Only algorithm), we see that the curve is generally quite flat, so there is not a severe penalty in targeting a very low false alarm rate.  As an experiment, let's target zero false alarms.  The plot above tells me that, at zero false alarms, it is possible to achieve a sensitivity of 56%.  Fine.  But what threshold values should I use to get this performance?  The ROC curve itself does not tell me that information.

Finding the Threshold Values:  When I made the ROC curve, I built it up by plotting the data generated through a brute-force assessment of all pairs of Alpha and Guard threshold values. These were the green circles shown two plots ago.  The ROC curve came from a subset of those green circles.  So, I can go back and find the threshold values that correspond to the green circles that just fall on the ROC curve.  These threshold values would be the optimal threshold values for a given false alarm rate.  The figure below plots these optimal threshold values as a function of allowed false alarms (ie, allowed number of incorrect detections).  If we are targeting zero false alarms, this plot says that we should choose an Alpha detection threshold of about 3.75 uV and a Guard rejection threshold of about 2.55 uV.

For a given number of allowed incorrect detections (ie, false alarms), this plot shows the Alpha and Guard threshold values that result in the highest sensitivity (ie, most number of correctly identified Alpha activity).  As with all figures in this analysis, the curves above are derived from a single EEG recording, which is why the curves are noisy.

Re-Process the EEG Data:  If we use these two threshold values and reprocess our EEG data, we get the detection performance seen below.  Again, the top plot is the raw EEG recording.  The middle plot shows the EEG amplitude in the Guard band along with (in red) the Guard rejection threshold.  The bottom plot shows the EEG amplitude in the Alpha band along with (in black) the Alpha detection threshold.  The red circles show those points that satisfy both thresholds -- the are the "detections" resulting from our algorithm.  You'll note that there are only detections when my eyes are closed -- there are no false detections.  This looks really good!  I think that I'm getting close to being able to deploy this into my OpenBCI GUI for real-time operation in detecting Alpha waves.

Detection Performance Using the Detection Thresholds for Zero False Alarms.  The detections (rec circles) resulting from this approach look pretty good!

Summary:  In this post I introduced a number of new ways of analyzing and plotting EEG data so that we can optimize the performance of our Alpha detection algorithm.  Specifically, I showed how the ROC curve is a great way of visualizing system performance in a way that smoothly handles the inherent trade-off between sensitivity and false alarms.  I showed how the ROC curve is a simple way to quickly see how one detection algorithm is better than another ("Alpha+Guard" is clearly superior to "Alpha Only") and to quickly see that there is little penalty for driving to an even lower false alarm rate.

Next Steps:  Up until now, we've just been looking at one EEG recording.  Therefore, all of our conclusions on which algorithm to use and which detection thresholds to use have been based upon a very small amount of data.  The results seen here might not generalize well, which means that my algorithm might not perform well when faced with future data.  To address this possibility, my next step is to bring in some of my other EEG recordings, all of which are noisier and more challenging.  With the additional data, we can better optimize our algorithm and have greater confidence that it'll work well on future data that has not been part of its training.

Follow Up:  I examine the performance on six different EEG recordings here.

Wednesday, October 15, 2014

Detecting Alpha Waves - Guard Bands

In my previous post, I discussed a simple algorithm for detecting Alpha rhythms: (1) use an FFT spectrum to measure the EEG amplitude in the Alpha band and (2) compare this value to a fixed detection threshold to decide if Alpha are present.  As shown in the figure below, this approach yields good detection sensitivity (it correctly flags 66% of the eyes-closed data blocks) and a reasonably low number false alarms (it incorrectly flags 15 data blocks).  While this is good, I think that I can do better.  Let's talk about how...

Example EEG data (top) showing Alpha rhythms when my eyes are closed.  At each time slice, I measure the peak of the spectrum in the Alpha band (7.5-11.5 Hz), which yields the blue trace on the bottom.  By looking for any value above 3.5 uVrms, we are able to detect the presence of Alpha waves (as indicated by the red circles)

Alpha Band Detection is Not Specific Enough:  In the simple Alpha band detection algorithm discussed above, we are sensitive to any signal with lots of energy in the Alpha (7.5-11.5 Hz) band.  The problem is that there are signals besides Alpha rhythms that have energy in the Alpha band.  For example, the bottom plot below shows the spectrum (black line) for a segment of eyes-closed Alpha waves.  The plot  also shows the spectrum (red line) for a segment of "other" activity that is no an Alpha rhythm (it is probably motion artifact from the EEG lead wires).  As can be seen, both spectra show substantial energy in the Alpha band, and so they would both be flagged as "Alpha!" using my simple threshold detection approach.  For the segment of "other" activity, this would be a false alarm.  I don't want that.  I want to improve my algorithm to reject this kind of false alarm.

Two spectra: (1) a segment of eyes-closed Alpha rhythm that I do want to detect and (2) a segment of "other" EEG activity that I do not want to detect.  Both, however, show a high amplitude in the Alpha band.  So, my original detection rule that is simply based on the Alpha amplitude would not reject the "other" activity.

Introduce "Guard" Bands:  One way of distinguishing between the two example spectra above is to introduce "guard" bands on either side of the Alpha band.  The idea is that we measure the signal amplitude both in the Alpha band and in the guard bands.  Based on the plots above, we know that true eyes-closed Alpha activity will not show much energy in the guard bands whereas the confusing "other" activity can be rejected because it does show energy in the guard bands.

If we measure the mean EEG amplitude in the guard bands, as well as in the Alpha band, we can distinguish between the two signals.  True Alpha rhythms will not have much energy in the guard bands whereas most of our confusing "other" activity will show substantial energy in the guard bands.

Evaluating the Guard Amplitude:  To quantify the amplitude in the guard bands, I simply take the average of all the spectrum values that fall within our two guard bands (3-6.5 Hz and 13-18 Hz).  When I apply do this for our EEG data, I get the green trace shown in the middle plot below.  As you can see, it stays low during all of the legitimate eyes-closed Alpha activity and it jumps high only during the confusing other activity.  This looks promising!


Combined Detection Rules:  Based on this graphs above of the guard amplitude (green line) and of the Alpha amplitude (blue line), it looks like a good combination of rules would be to look for points where the Alpha amplitude is greater than 3.5 uVrms and, simultaneously, where the guard amplitude is less than 2.5 uVrms.  When I apply these detection rules, I get the red circles shown in the figure above.  Looks pretty good!  You'll note that the addition of the guard band has successfully rejected the false alarms that we had been getting at t=58, t=77, and t=123.  This is exactly what I was hoping for.

Quantifying the Improvement:  Compared to yesterday's results (tabulated below), this new detection algorithm obtains nearly the same sensitivity (65% vs 66%) with a greatly reduced number of false alarms (2 vs 15).  This is definitely an improvement in my Alpha detecting algorithm.
      
Guard       N_TRUE      N_FALSE
None        101 (66%)   15
2.5 uVrms   100 (65%)   2


Moving Forward:  For this example EEG recording, I am satisfied with the performance of this algorithm.  It would give me quite reliable performance while still being nicely sensitive.  This EEG recording was pretty "clean", however -- its Alpha was pretty strong and there was not too much confusing "other" activity.  I have other EEG recordings that are more difficult.  Next time, we'll look at those harder recordings, you'll see that even the combined Alpha+Guard algorithm is insufficient, and I'll discuss yet another extension (hopefully an improvement!) on this detection approach.

Follow-Up:  I further optimize this algorithm by using ROC curves to attack, head-on, the trade-off between sensitivity and false alarms.  Check it out here.


Tuesday, October 14, 2014

Detecting Alpha Waves - Threshold Detection

In my previous post, I showed some EEG data that I recorded from the brand-new OpenBCI V3 board.  The data that I showed included some Alpha waves that my brain generated (like most people's brains) simply by closing my eyes.  I've copied a spectrogram of that EEG data below.  You can see the Alpha waves as the horizontal stripe of energy near 10 Hz.  While it is pretty easy to see (to "detect") this signal by eye, it might be fun to get the computer to automatically detect these Alpha waves, so that you can use Alpha waves to make a brain-controlled light, or a brain-controlled robot, or to do some other cool hacking shenanigan.  How do we get the computer to detect the Alpha waves?  In this post, and in some follow-up posts, I'm going to discuss a few ways...

Spectrogram of the EEG Signals from the Back of my Head ("O1").  Note the horizontal stripe of energy near 10 Hz when my eyes are closed.  These are the Alpha waves being generated in my occipital lobe.

Simple Approach First:  There is a huge body of literature out there on the various signal processing techniques to address the "detection" problem.  Most approaches (or, at least, the language used to describe the approaches) get very technical very fast, even in introductory material, so I'm going to take a simple approach first, and only add additional complication as needed to solve particular problems.

Average EEG Spectrum when My Eyes are Closed.  The Alpha rhythm clearly shows up around 10 Hz.

Frequency View:  As a human being looking at the spectrogram at the top of this post, I easily see the horizontal stripe of energy that represents my Alpha waves.  Since the frequency is nearly constant, the Alpha waves should show up in a simple spectrum view of signal.  The spectrum view plotted above shows the EEG spectrum averaged entire period when my eyes are closed.  Clearly, there is a strong peak in the Alpha Band (7.5-12 Hz).  This is the tool that we will use to measure the Alpha waves.

Alpha Through Time:  Since the Alpha waves are clearly identifiable in the spectrum, and since the OpenBCI GUI already computes the spectrum as the EEG data arrives from the OpenBCI board, let's use the spectrum as our tool for focusing on just the Alpha waves.  To quantify the amplitude of the Alpha waves, I find the maximum value of the spectrum within the 7.5-12 Hz band.  Since the OpenBCI GUI computes a new spectrum every 200 msec, I get a new estimate of the Alpha amplitude five times a second.  The plot below shows the estimate of Alpha amplitude that results from this process.

Looking at the Alpha Band (7.5-11.5 Hz) through Time.  Notice that the amplitude is highly variable.  When my eyes are closed, the amplitude is generally much higher.

Choose a Detection Threshold:  As you can see in the plot above, the EEG amplitude in the Alpha band increases greatly when my eyes are closed (and, a bit surprisingly, we also see that my Alpha amplitude is not very steady...it varies a lot when my eyes are closed).  To have the computer decided when Alpha waves are present, the simplest approach is to pick a threshold value such that, when the signal amplitude is above the threshold, we declare that Alpha waves are present.  Looking at the plot, I picked a threshold value of 3.5 uVrms.

The red circles shows those data points where the Alpha amplitude is greater than my detection threshold of 3.5 uVrms.   It correctly captures most of the data when my eyes are closed, yet it also incorrectly captures a few moments of strong non-Alpha activity.

Detection Results:  The plot above shows the effect of setting the detection threshold at 3.5 uVrms.  The red circles shows those data points where amplitude in the Alpha band is above the threshold and we would declare that Alpha is present.  Based on the good coverage during the "eyes closed" portion of the data, I'd say that this detection threshold yields good sensitivity.

False Alarms.  To improve our sensitivity further, one could imagine lowering the detection threshold so that we capture more of the points within the "eyes closed" region.  Doing this, though, would also cause more points outside of the "eyes closed" region to be falsely detected as Alpha waves.  Even with our 3.5 uVrms threshold, there are several moments (t = 58, t = 77, t = 123) when strong broadband EEG activity happens to be strong enough to cross our detection threshold.  Since these detections are not due specifically to Alpha activity, we call these false alarms.

Balancing Sensitivity with False Alarms:  Selecting a good detection threshold requires one to balance the desire for high sensitivity with the requirement for a low false alarm rate.  After trying several different threshold values (see table below), 3.5 uVrms seems like it provides a decent balance for this EEG recording.  Other recordings might require a different threshold value.

Threshold    N_TRUE     N_FALSE
2.5 uVrms    126 (82%)  43
3.0 uVrms    112 (73%)  20      
3.5 uVrms    101 (66%)  15
4.0 uVrms    75 (49%)   12
4.5 uVrms    59 (39%)   11

Moving Forward:  With this simple method of quantifying the Alpha amplitude (ie, take the maximum value from the spectrum in the 7.5-12 Hz band) and with this simple method of deciding whether Alpha is present (ie, using a pre-defined detection threshold), we can easily have the computer detect our eyes-closed Alpha waves.  Sure, we might have a few false alarms but this is just our first try!  In the next post, I'll try adding a few techniques to be more selective to reduce our false alarms, without significantly degrading our sensitivity.

Follow-Up:  See how I reduce the false alarms by introducing Guard Bands!

Monday, October 6, 2014

First Alpha with OpenBCI V3

OK, I'm back to work now.  After my previous post, where I got my first data ever with the new OpenBCI board (aka, "V3"), I took a little hiatus while Joel worked through some issues with the Bluetooth link.  Everything appears to be working well now, so I'm back on the case.  Yesterday, I connected everything up and recorded my first real EEG data with the V3.  Exciting!

My Little OpenBCI V3 Board (8-Bit Version) with Homemade Electrode Adapter

EEG Setup:  To get started, I set an easy goal for myself -- just record some eyes-closed alpha waves.  So, I got out my trusty gold electrodes, my trusty Ten20 electrode paste, and put on a few electrodes.  I attached one electrode to the back-left of my head ("O1"), the reference electrode to my left earlobe, and the bias electrode to my right earlob.  So far, this is just like normal.

Software Setup:  For software, I used Arduino software for the OpenBCI Bluetooth dongle (aka, the RFduino "Host"), for the remote Bluetooth module on the OpenBCI V3 board itself (aka, the RFduino "Device"), and for the Atmel microcontroller that is the core of the OpenBCI V3 board (and which is programmed like an Arduino Uno).  The software is surely going to change with time, but right now I'm working with this code here.  On the PC side, I used a version of our Processing GUI that we modified to accept the new binary data format being generated by the V3 board.

Data and Analysis:  I did a couple of recordings of my eyes-closed alpha waves.  My data and analysis files are here.  Some example plots of the data that I recorded are shown below.  This is my first time trying to analyze the data using Python instead of Matlab.  Because I'm so new with Python, I was a lot slower in doing the analysis, but now that I've completed this one little task, I'm feeling pretty OK about the switch.  Maybe, just maybe, it is possible to learn new tricks!

EEG Data Recorded from the Back-Left of my Head ("O1") After Closing my Eyes
around t = 88 seconds.  By closing my eyes, I get alpha waves appear near 10 Hz.

Time-Domain Plot:  The top plot is a simple plot of the recorded EEG signal as a function of time.  Actually, it's not a totally "simple" plot because I have done some processing of the data.  I highpass filtered it to remove the DC component and I notch filtered it at 60 Hz and 120 Hz to get rid of power line interference.  In my opinion, though, time-domain plots are not very useful when zoomed out to a wide range of time (like we're doing here).  So, there's not much to say.

Spectrogram:  The middle plot is a spectrogram of the same data.  I love spectrograms.  Here, time is again on the horizontal axis, but now frequency is on the vertical axis.  The intensity of the color of each pixel shows how much signal energy is at the pixel's time and frequency.  Here, by the red horizontal line that appears ~10 Hz, you can clearly see the alpha waves.  Cool!

Frequency-Domain Plot:  Unfortunately, it is difficult to be quantitative about the amplitude of signals that are seen in the spectrogram.  So, once I located my alpha waves (t = 90 sec to t = 118 seconds), I plotted the mean spectrum for the data just in that time period.  The bottom plot shows this spectrum -- it shows the spectrum of my brain waves during t = 90 sec to t = 118 sec  You can see the prominent bump around 10 Hz.  These are my alpha waves.  As can be seen. the amplitude is approximately 4.1 uVrms and the peak is focused at 9.38 Hz.  That's my brain!  Specifically, that's my visual cortex when it's bored because my eyes are closed!

So, that's the quick fun that I had using the new OpenBCI V3 hardware and the fun that I had using Python for the first time to make decent graphs.  Learning new things makes me feel pretty empowered.  To celebrate, I'm going to go eat some breakfast now.  Mmm...Wheat Chex...I really know how to party.  ;)

Follow-Up:  Here's some additional discussion on how to detect these Alpha waves

Monday, August 18, 2014

First Data with OpenBCI V3

It's here!  It's here!  The (near) future has arrived!  I have received an early OpenBCI V3 board from my friends over at OpenBCI.  Check out the photo below.  It's a little smaller than I expected.  Very cool!  Let's get it running and see what it can do!

The OpenBCI V3 board is a smaller than I expected.  Looks great!

Note that the V3 board includes a built-in microprocessor.  This means that you no longer have to buy a separate Arduino to act as host.  That's pretty sweet.  OpenBCI gives you two choices of microprocessor: at ATmega 328 (the 8-bit option) or a PIC32 (the 32-bit option).  While the power of the 32-bit PIC is appealing, I chose the ATmega because that allows me to program the OpenBCI board as if it were an Arduino Uno.  I hear that the 32-bit PIC version can also be programmed from the Arduino IDE, but the Uno is my friend, and I chose to stick with him.  

Another change with the V3 version is that it has a built-in Bluetooth module.  In fact, to maximize electrical safety for the user, the wireless Bluetooth link is now the only way to get data off the device in real-time (though it does have a built-in SD card for those looking to simply log data).  This is quite a change...and a change for the better, in my opinion.

OpenBCI says that the Bluetooth module is compatible with standard protocols (to enable connection to your mobile device) and that it has a special high-speed mode, if you have a mating BT module for your PC.  To enable these high-speed modes, OpenBCI includes a BT USB dongle, which is shown at the bottom of the picture below.

Using the new OpenBCI V3 board to record my ECG.  I used one disposable ECG electrode
on each wrist.  The OpenBCI board was powered by a 9V battery, which is in the black
battery case.  The OpenBCI board transferred the data to the PC via Bluetooth.
OpenBCI includes a BT dongle for the PC, which is shown in the bottom-left.

Once I got my hardware, I started in.  Unfortunately, as part of the deal with me getting this hardware so early, the software to run the hardware is not yet complete.  So, I had a little work to do.

When diving into new hardware, it's best to take baby steps.  Start from something that works and then add features incrementally, with lots of tests along the way.  This makes it much easier to identify and squash the bugs as they pop up.  For my first work with OpenBCI V3, here's my approach

  1. Test the wireless link using pre-defined dummy data
  2. Test getting data from the ADS1299 using its built-in test signals
  3. Test getting real data from the ADS1299 by recording my ECG
  4. Test the full system by recording my EEG

Dummy Data:  To get this process started, Joel (of OpenBCI) provided some example code that exercised the wireless link using dummy data.  He even pre-loaded this software on to the V3 board for me.  So, all I had to do was plug in the USB BT dongle, connect a battery to the OpenBCI board, and I was good to go.  I started my Terminal program on my PC and was immediately interacting with the OpenBCI V3 board.  It correctly transferred the pre-defined dummy data.  Success!

Built-In Test Signals:  Building from this working code base, and building from OpenBCI's initial code for configuring the ADS1299 EEG chip, I added the ability to grab data from the ADS1299 and send it out the wireless link.  I started with the ADS1299's built-in test signals.  After some fiddling with 24-bit vs 32-bit number formats (and then discovering that Joel already programmed the solution for me), I got the nice square wave signal as shown below.  This proves that I can communicate with the ADS1299 chip and that I've got all the number formats correct.  Success again!

Data from my OpenBCI V3 board...this is a built-in test signal being generated
by the ADS1299 EEG chip.  Since it looks beautiful, it means that I have confirmed
that I can configure the chip and that all my number formats are correct.

ECG Data:  As you may know from my previous "getting started" post, I like to start my collection of real data by recording my ECG (ie, heart signals).  I do this because ECG signals are so much stronger and simpler than EEG signals.  Having strong signals makes it more obvious when the system is working correctly (and when it is not working correctly).  So, I got out my disposable ECG electrodes, put one on each wrist, and started recording.  As you can see in the plot below, I got a nice sample of my ECG.  My code for OpenBCI V3 might be rough, and my code is definitely not feature-complete, but it does work.

My wrist-to-wrist ECG looks pretty good.

The sample of data shows that my heart rate was about 80 beats per minute, which is a little high for simply sitting in a chair at my computer.  Maybe I was just excited to be having success playing with the new hardware!  I'm like that.

So, returning to my four step process described earlier, I've got 3 of the steps completed.  Before I do the last step -- collected actual EEG data -- I'd like to revise the code a little more.  Right now, I cannot view the streaming data in real time because the data format is a little different then before.  To move forward, I need to adjust the code in my Processing GUI so that it can interpret the data packets and plot the data in real time.  Once I get that to happen, I'll hook up some electrodes to my head and maybe make my robot dance some more!  Wish me luck!

Follow-Up: Raw data and analysis code is here.
Follow-Up:  First EEG Data from the V3 Board is here.

Saturday, May 10, 2014

Controlling Entrainment Through Attention

In a previous post, I showed that I could induce (entrain) brain waves at different frequencies simply by staring at blinking movies playing on my computer.  Having demonstrated this basic feasibility, my goal now is to exploit this phenomenon to make a brain-computer interface (BCI) to control future hacks.  My idea is to play two blinking movies simultaneously -- one at a slow speed and one at a fast speed.  I'm hoping that my brainwaves will only entrain with the blinking from the one movie that I choose to focus on.  Does my brain work this way?  Will my brain successfully reject the blinking from the movie that I'm ignoring?  Let's find out!



Simultaneous Blinking at Two Speeds:  Previously, I made some blinking movies where the whole screen would blink black or white at a given speed.  To make this idea work for a BCI, I want my screen to blink at two different rates at the same time.  So, as you can see in the video above, I made the left side of my screen blink at one rate while the right side of my screen blinks at a different rate.  I'm hoping that, if I focus my attention on the left side of my screen, by brainwaves will only become entrained at the left-side blink frequency, whereas if I were to focus on the right side of the screen, my brainwaves would follow the right-side blink frequency.

Swapping Sides:  To help with this test, I wanted to remove any effect of turning my head to change my gaze between the two sides of my screen.  So, in creating my dual-rate blinking movie, I had the movie automatically swap sides every 20 seconds.  As a result, it starts with fast blinking on the left and slow blinking on the right.  After 20 seconds, it swaps so that slow is on the left and fast is on the right.  It does this swap a few times.  The Matlab code that I used to make these movies is here.

I created a movie where the left and right sides blink independently -- left is fast and right is slow.
For this test, the two blink rates swapped sides every 20 seconds.

Choosing my Blink Rates:  Based on my previous results, it looks like my brain (coupled with my computer's limited ability to blink steadily) is most easily entrained in the 6-10 Hz frequency range. So, for this dual-rate movie, I chose "slow" to toggle between black and white at 10 Hz (ie, a 5 Hz white-white rate) and "fast" to toggle at 15 Hz (ie, a 7.5 Hz white-white rate).  In truth, I made a bunch of movies at different rates, but the the 10/15Hz movie worked the best, so I'll only show its results.

EEG Setup:  With my movies prepared, I gathered up my EEG stuff.  Like usual, I used my OpenBCI board and a few cup electrodes with Ten20 paste. I put one electrode on the left side of my forehead (Fp1), on one the left side of the back of my head (O1) and one on the right side of the back of my head (O2).  Using the impedance measuring feature, my impedances were 11 kOhm, 67 kOhm, and 28 kOhm (I seem to have an on-going problem getting a low impedance at O1).  My reference electrode was on my left ear lobe and my bias electrode was on my right ear lobe.  My OpenBCI board was connected to the PC via USB and I was logging data using my OpenBCI GUI in Processing.  For this test, I also used my photocell to confirm that my computer's blinking was sufficiently steady.

I used my OpenBCI V1 board to record my EEG into the computer.  I also attached a
photocell to confirm that the screen was blinking at the right rate.

Results:  After setting everything up, I started recording my EEG data and then I started playing the dual-rate blinking movie.  It was night time, so my room was pretty dark.  I focused my attention at the center of the left-hand movie. As described above, the left movie toggled fast-slow-fast-slow every 20 seconds, while the right movie played the opposite -- slow-fast-slow-fast.  Spectrograms of the EEG signals from my head are shown in the figure below.  As you can see, there was no entrainment seen in the signals from my forehead (as expected) but there was entrainment in the back of my head (also as expected).  The best entrainment was seen on the left side of my head.

Spectrograms of my EEG signals recorded while watching my dual-rate blinking movie.  The left-back
of my head exhibited the strongest entrainment to the blinking of my movie.  


Only Seeing the Left Blink Rate:  Because the left-back of my head (O1) gave the best entrainment, let's just focus on its results. The figure below shows just the results for the left-back of my head.  Note how,once the movie starts playing, my EEG signals seem to toggle between a fast blink rate (~7.5 Hz) and a slow link rate (~5 Hz).  This exactly follows the white-white blink rate of the left movie. So, my brainwaves successfully entrained to the movie that I was watching. Most importantly, there seems to be no signature in my EEG data from the blinking of the right movie.  This is success!

Spectrogram of my EEG data from the left-back of my head (O1) while watching my dual-rate
blinking movie.  I was focused just on the left movie.  Because of this focus, my brainwaves
appear to have entrained only with the left movie's blink rate.

Purposely Shifting My Attention:  OK,so I've demonstrated that my mind can successfully ignore one of the movies.  That's really good.  But, maybe I'm just biased to looking left. To really make this work for a BCI, I need to be able to shift my attention to either movie and have my brainwaves follow.  So, for my 2nd test, I started the same movie playing back.  But, this time, when the movies swapped sides every 20 seconds, I switched my attention to follow the movie that blinked faster. This means that I started by watching the left movie, then I watched the right, then left, then right.  My EEG response is shown below. Note that I showed strong entrainment and,most importantly, that my brainwaves only show the fast blink rate (7.5 Hz). So, by shifting my attention to follow the faster movie, I successfully rejected the effect of the slower blinking movie. Success again!

Spectrogram of my EEG data from the left-back of my head (O1) while watching my dual-rate blinking
movie.  While watching the movie, I switched my attention between left and right to follow the movie
 that blinked faster. Because of this focus, my brainwaves remained entrained only at the faster rate.

All the Elements are In Place:  It looks like I now have the elements in place for a 3-state BCI.  If I don't look at the movie at all, I get State 1: "Nothing". If I watch the blinking of the left movie, I get State 2: "Left".  If I watch the blinking of the right movie, I get State 3: "Right".  It may be possible to further divide my screen to get more blinking regions to add more BCI states. Maybe that's a good experiment for the future. Right now, though, I think that I'm going to turn my attention to a little robot that I got (thanks for the pointer Conor!) to see if I can control it with visual entrainment.  This is gonna be fun!

Follow-Up:  Interested in getting the EEG data from this post?  Try downloading it from my github!

Follow-Up:  I successfully used visual entrainment to control a six-legged robot!

Sunday, May 4, 2014

Inducing Brain Waves with Visual Entrainment

A while back, I had a friend come over and I measured his EEG in response to staring at a blinking light.  We saw (as we hoped) that his brainwaves oscillated in sync with the blinking of the light.  I thought that this visual entrainment (aka "steady-stead visual evoked potential") was pretty cool.  Since then, I've learned that it can be used as the basis for a brain-computer interface (BCI).  Because I'm still searching for a good BCI paradigm, I decided to return to my exploration of visual entrainment.  Today, I'm going to show how I successfully used visual stimuli to induce brainwaves at different frequencies.  As a result, I can now see an good avenue for an EEG-based BCI.  Yes!  Let's go!

Inducing SSVEP Using a Toggling Checkerboard Pattern on my Computer Screen
Goal:  My goal today is to use visual stimuli to induce brainwaves across a range of frequencies.  Because I want to use this for a BCI, I'm trying to determine what kind of visual stimuli I should use and what EEG frequencies I can induce.  What does it take to make this work reliably?

Visual Setup:  In my previous post, my visual stimulation was simply a blinking head-lamp.  It was effective (and really bright!), but I had no control over its blink frequency.  As a result, I also had no control over the frequency of the brainwaves that it induced.  So, for today's test, I needed to get fancier.  I ditched the head-lamp and, instead, created a series of blinking movies that I could playback on my computer.  I controlled the "blinking rate" by saving my movies at different frame rates.  What exactly did the movie look like?  Well, at first, because of a paper that I read in the VEP literature, my movie used the checkerboard pattern shown in the picture above.  The movie toggled back-and-forth between this image and the inverse image (swap blacks and whites).  While this worked OK, I later switched to a simpler movie (code here) where the screen was simply all-white or all-black.  That seemed to work better.

EEG Setup:  Once I made my movies, I set myself up with my EEG system (OpenBCI ).  I my usual gold cup electrodes with Ten20 EEG paste.  I put one electrode on the back of my head (near O1) and I put another electrode on my forehead.  My reference electrode was on my left ear lobe and my bias electrode was on my right ear lobe.  Using the impedance-measuring feature of OpenBCI, the electrode on my forehead had an impedance of 24 kOhm and the one on the back of my head was about 65 kOhm.  I couldn't seem to get the back electrode to a lower value.

Channel 1 was on my Forehead, Channel 2 was on the back of my head.
My left ear lobe was my reference.  My right ear lobe was the bias.

I used my OpenBCI V1 board with Ten20 Paste.
I think that those owl napkins are fun!

Test Method:  Once I got everything setup, I launched the OpenBCI GUI in Processing and started an EEG recording.  To playback my homemade blinking movies, I opened up Windows Media Player and set it to full-screen mode.  I had ten movies, with each movie blinking at a different rate.  I had WMP play all 10 movies continuously in sequence.  Each movie was 20 seconds long, so the whole test took about 200 seconds.  It was nighttime when I did this test and my room was dimly lit.  I tried to stare at the screen and I tried to only blink my eyes at the transition between the different blinking rates.

Results, Checkerboard:  As usual, my preferred way to view the data is to make spectrograms.  In the figure below, the top plot is the data from my forehead and the bottom plot is the data from the back of my head.  From my forehead, there is nothing interesting except my eye blinks.  From the back of my head, we see several interesting features, which I've marked with blue and white arrows.  Note that these interesting features change every 20 seconds, which is the same as my 20-second movies.  It seems clear to me that these features are my brainwaves responding to changing of the blink rate in my movies.  Excellent!


Spectrogram of EEG Signal Recorded While Watching the Blinking Checkerboard Pattern.
The top plot is the signal from my forehead.  The bottom plot is from the back of my head.
"W-B" is the rate at which the movie switched from either white-to-black or black-to-white.
"W-W" is the rate if you measure just from white-to-white.

Entrained with the Blink Rate?  Looking at the three blue arrows, it appears that I have entrained brainwaves at 2 Hz, 4 Hz, and 6 Hz.  At these times, any given square in my movie was blinking at 1 Hz, 2 Hz, and then 3 Hz, if you count from white period to white period ("W-W").  Because I have entrained brainwaves as 2x the white-to-white frequency, it suggests that it is NOT white-to-white that matters, but that it is the transition between white/black or black/white that matters.  At least, that is what is implied for these three (out of 10) cases for the checkerboard stimuli.

Complications:  While that would be a fine conclusion, why does this rule not continue through the other 7 cases in this checkerboard test?  Why does it only work for the three cases with the blue arrows?  The cases with the white arrows do show some sort of EEG response, but not at any frequency that makes sense given the speed of my movies.  What is going on?  I've got two possible explanations: (1) either my movies are not playing back reliably during these other cases, or (2) the checkerboard pattern is too complicated to be a good starting point for learning about my brainwaves.

Modifying the Test:  Of these two possible explanations, it's easier for me to simplify the checkerboard than it is for me to fix the reliability of my movie playback.  So, I changed my movies so that the whole screen is either all all black or all white.  Hopefully, this simpler visual stimuli will make my EEG response easier to understand.

Results, Whole-Screen Blinking:  After recording my EEG while staring at the new movies, the spectrograms of my data are shown below.  Again, all of the interesting action is in the back of my head.  The bottom plot shows that I got good entrainment of my brainwaves for nearly *all* of the new movies.  I'm very pleased.  I'm also very curious about the jump between the cases marked with blue arrows versus the cases marked with red arrows.  What is happening here?

Spectrogram of EEG Signal Recorded While Watching the Whole Screen Toggle White or Black.
The top plot is the signal from my forehead.  The bottom plot is from the back of my head.

What Blink Rate Matters?  Looking at the first half of this plot, the blue arrows indicate cases that have results similar to the checkerboard data shown earlier.  Here, my brain seems to respond to every transition from white to black and from black to white (aka, the "W-B-W" speed).  But, for the second half of this plot, when the blinking is faster, it looks like my brainwaves follow the slower rate resulting from just the white-to-white frequency ("W-W").  Based on this weird result, I'm thinking that my brain doesn't actually care so much about whether the stimuli is W-B-W or W-W...it is simply sensitive to rhythmic visual stimuli in a certain frequency range.  I'm thinking that, whatever rhythmic stimuli falls in this frequency range, my brain will become entrained with it.

Quantifying Entrainment vs Frequency:  If it's simply the frequency that matters, it would be good to see which frequencies yield the strongest entrainment.  Sure, the spectrograms above suggest which frequencies are best, but I took the next step and actually measured the EEG response at each of the stimulation frequencies.  The plot below shows the EEG amplitude that I measured for each of the visual blinking frequencies.  Note that there are two lines, one for if you count based on the white-to-white frequency (blue line) or whether you're counting based on all the white/black and black/white transitions (red line).  This graph suggests that I seem to yield decent responses in the 6-10 Hz frequency range.  So, if I'm looking to use visual entrainment for a BCI, I should focus on the 6-10 Hz band.

Amplitude of EEG Signals Induced by Visual Entrainment.
My best responses seem to be in the 6-10 Hz band.
That could be a good target frequency range for use in a BCI.

Computer Could be Limiting my Performance:  As mentioned earlier, all of these results could be confounded by the possibility that my computer cannot reliably and steadily refresh my screen.  Perhaps it can reliably handle the frequencies at 10 Hz and below, but is not steady above 10 Hz.  Perhaps that's why my apparent response above 10 Hz falls off.  Sure, my computer claims that the screen has a 60 Hz refresh rate, but that doesn't mean that Windows or that Windows Media Player can keep up.  So, any next steps should include some method of assessing whether the computer is actually displaying my movies smoothly at the rate that I expect.

Entrainment for BCI:  My overall goal is to make a cool brain-computer interface (BCI).  Because I am showing that I can successfully measure visual entrainment, I would like to further explore how visual entrainment could be exploited for a BCI.  One idea is that I could simultaneously show two movies side-by-side, each blinking at its own rate.  Perhaps, if I'm lucky, my brainwaves will only respond to the one movie that I'm actually watching.  If that's the case, then I would have conscious control over my brainwaves (and, therefore, the BCI) simply by selecting which of the two movies that I watch.  That could be very cool.


Follow-Up:  I setup a photocell and my Arduino to measure the actual blink rate of the movies on my computer.  In my results, I found that I can't generate steady blinking faster than 10 Hz.  This is probably a strong reason why my EEG recordings exhibited no entrainment above 10 Hz...how can I entrain to signals that aren't there?!?

Follow-Up: I extended this work by having one movie blink at two different rates.  I found that I could control my entrained brainwaves by choosing which of the blink rates I focused on.  Pretty cool!  If you're interested, you can see the results in this post.

Follow-Up:  Interested in getting the EEG data from this post?  Try downloading it from my github!