Learn to Work with Next Gen. Neurotech Data ‘fNIRS’ with this Easy Tutorial

John David Chibuk
Nov 26 · 5 min read

This post explains how to get started with fNIRS sensing data specifically oxygenated hemoglobin “HbO2/HbO” data for analyzing a data stream from a sensor, in this case Blueberry.

The goal here is to help with understanding how to take the sensor data signal and get to a point where clear increases and decreases in thinking intensity are shown during a period of use. In this tutorial we will use a sample dataset to start with.

In this post we explore two core concepts with fNIRS data:

  1. Experiments to determine a clean ‘brain activity’ signal
  2. Comparing ‘brain activity’ with a secondary source of data, typing speed

The image below shows the ideal change in HbO2 blood oxygenation for an intensity of thought increase.

If you want to learn more about fNIRS you can read about it here.

Thanks to python and scikit learn this can be done quite fast! This tutorial walks you through an open source Jupyter notebook and a few methods to get started. Find the Github public repo here.

7 Steps to Get to an Estimated Brain Activity Signal

Steps 1–6 Filtration and initial brain activity signal estimation

Step 1 Install the required libraries for scikit learn and pandas (tools for managing the data + performing some of the initial analysis) — this notebook was built using Python 3 Kernel

Step 2 Explore initial types of analysis to run on fNIRS data, most statistical analysis will try out 4 in this tutorial:

  • Standard Deviation
  • Mean/Average
  • Rolling Average
  • Volatility and Change in Rolling Average

In each case a window of time is selected to get a snapshot of what the data looks like.

Hemodynamic responses in fNIRS data typically occur over a 5 to 25 second window of time.

Step 3: Using a rolling average of the HbO change it becomes possible to see a pattern or rhythm of rise and fall of HbO during a task period

In the sample data provided over 2 minutes or 120 seconds it is possible to see the overall rise and fall 2 times. Rhythmic Mayer Waves are present in blood flow data though.


#DATA ANALYSIS#
# calculate rolling window of 100 samples or 20 seconds at 5Hz, 20 seconds and 4 seconds
FNIRSDATA['RA_20'] = FNIRSDATA.HbO2.rolling(20).mean().shift()
FNIRSDATA['RA_100'] = FNIRSDATA.HbO2.rolling(100).mean()
FNIRSDATA['RA_20_100'] = FNIRSDATA.RA_20.rolling(100).mean()
FNIRSDATA['RA_20'].head(12)
FNIRSDATA['STD_20'] = FNIRSDATA.HbO2.rolling(20).std().shift()
FNIRSDATA['STD_100'] = FNIRSDATA.HbO2.rolling(100).std()
FNIRSDATA['STD_20_100'] = FNIRSDATA.STD_20.rolling(100).std()
FNIRSDATA['STD_DIFF_20_100'] = FNIRSDATA['STD_20'] - FNIRSDATA['STD_100']
FNIRSDATA['STD_DIFF_MEAN'] = FNIRSDATA.STD_DIFF_20_100.rolling(100).mean()

Step 4: In this step we explore some potential methods to determine the ‘brain activity’ from the Mayer Waves

To account for this rhythmic signal within the data we can filter the dataset to try to get the overall trend. Utilizing methods such as high pass, rolling average and low pass filters in combination some of the general trend can be determined. In the graph to the left the Mayer Waves are more evident in form however a hypothesis is that the brain activity is evident when the Mayer wave is not uniform.

Step 5: To further expand on the ‘brain activity’ signal we look at the rate of change to provide increasing rates of change of HbO2 to determine a level of brain activity or mental effort/stress — this is one sample set of data from a period of work

####################################################################
# Taking the rolling average of the filtered signal
# To amplify change in signal or our case change in blood flow as a representation of regional activation
# This plot show the rate of change difference in the rolling average filtered signal
####################################################################
FNIRSDATA["RA_20_100"] = FNIRSDATA["RA_20_100"] + 20
FNIRSDATA["change"] = np.log(FNIRSDATA["RA_20_100"] / FNIRSDATA["RA_20_100"].shift())
plt.ylabel('Rate of Change of HbO2 Rolling Average')
plt.xlabel('Time')
plt.plot(FNIRSDATA.change)

Step 6: Expanding on step 5 using volatility and standard deviation to determine an impact of higher or lower rate of change in overall trend of HbO2 changes as measured by the sensor — this step is used to build off of Step 5


Steps 7: Comparing to a Secondary Source of Data — Typing Speed

Step 7: Comparing to WPM to HbO2. Here is the preliminary result which shows an increase in brain activity at points of difficulty during the writing session. This was a fun self assessment to see what changes could be identified.

Comparing a longer wpm per minute exercise session, a clearer trend in mental load tapering during reduce pace of typing speed starts to become evident. An interesting observation here is the large increase in volatility during the last few sessions of lower performance of words per minute rate of typing.

Questions to explore:

  • Could we use HbO2 to predict typing speed or trend?
  • Could we capture an anticipated accuracy of typing from the HbO2 signal?
  • What would it look like to compare accuracy on a minute by minute basis to HbO2?

Find out more about Blueberry, the next gen. light based brain sensing here.

Blueberry

Next Gen. Neurotech for Help With Mental Stress + Open SDK

John David Chibuk

Written by

Founder, building teams and products to shape the future.

Blueberry

Blueberry

Next Gen. Neurotech for Help With Mental Stress + Open SDK

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade