Wednesday, 28 November 2018

eeg data processing in python

eeg data processing in python

introduction - basics

 --------------------------------------------------------------------------------

My first task with eeg (OpenBCI Ganglion: https://openbci.com ) was to do the basic live visualization (as OpenBCI_GUI: https://github.com/OpenBCI/OpenBCI_GUI ), which receives, interprets, filters data and additionaly create a fft plot, all in python. For now, lets focus on data processing.

data

 There are many datasets of eeg data: https://github.com/meagmohit/EEG-Datasets , but I recommend for learning to record data on your own. Data recorded with openbci devices, looks like this: https://github.com/J77M/eeg-datasets or https://github.com/Vyachez/Project_BCI/tree/master/SavedData . If you recorded data or used one of the datasets, raw data should be in this form:  (n+k)xm  matrix, where m is the number of time points, n is the number of channel data and k is aditional (time, id, ...).


Lets insert data: https://github.com/J77M/eeg-datasets/blob/master/alpha-one-channel/01.csv 
Visualization of channel with index 0:

 

filters

Most used basic filters for eeg are: notch and bandpass (bandpass is composed of lowpass and highpass).
Bandpass is filtering frequency above or under given band, if minimum value is bigger than 0, then bandpass removes DC offset (which is a mean amplitude of signal displacement from zero). Notch is filtering just given frequency value - usually frequency of AC power supply - in US 60 Hz and in Europe 50 Hz. Because it makes big noise in data and must be filtered out.

Filters designed in python: bandpass is a 5th order IIR butterworth filter and notch is 3th order IIR butterworth filter.
(fs = recording frequency -> for this data fs = 200Hz)


def bandpass(start, stop, data, fs):
    bp_Hz = np.array([start, stop])
    b, a = signal.butter(5, bp_Hz / (fs / 2.0), btype='bandpass')
    return signal.lfilter(b, a, data, axis=0)


def notch(val, data, fs):
    bp_stop_Hz = [float(val)] + 3.0 * np.array([-1, 1])
    b, a = signal.butter(3, bp_stop_Hz / (fs / 2.0), 'bandstop')
    fin = signal.lfilter(b, a, data)
    return fin


Visualization of channel 0 after applied notch with value = 50  and bandpass with band = (7,13) :
(in this case the result is same if notch would not be applied - after bandpass signal has only frequencies from 7 Hz to 13 Hz, so filtering 50 Hz does nothing)

FFT

Fast Fourier Transform. Good basic explanation: https://www.youtube.com/watch?v=spUNpyF58BY
Other easy to watch video with basics:  https://www.youtube.com/watch?v=z7X6jgFnB6Y

One option is to put into fft all our data, and the result will be frequencies of all our data, which is in most cases useless (can be used in frontal asymmetry - detecting emotions states). Better way to analyze frequencies is to split data into n chunks and then put each one into fft and analyze it. From the result we can see dynamic changing of frequencies in our brain.
We can conduct Fourier transform at any sampling rate,but more samples for fft we have, more is it precise. The resolution of fft can be calculated: resolution = fs / chunk lenght , if we will choose the chunk lenght to be 200 samples, then resolution will be 1Hz. It means there will be difference between frequency components which are at least this far apart. For better precision, chunk of lenght 400 samples = 2 seconds is good option.

visualization of fft of all chunks:

JUPYTER NOTEBOOK:  

https://github.com/J77M/blg-plusdata/blob/master/eeg-data-processing-in-python/process_data.ipynb


JM

No comments:

Post a Comment

closed eyes detection

closed eyes detection turn off the lights by closing your eyes  --------------------------------------------------------------------...