Skip to content

Commit

Permalink
updates to eeg analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
vatte committed Feb 3, 2019
1 parent 890b62a commit 3204140
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 30 deletions.
2 changes: 1 addition & 1 deletion devices/Bitalino.py
Expand Up @@ -74,7 +74,7 @@ def read(self):
for i, c in enumerate(self.channels):
samples[c] = in_samples[:, -len(self.channels) + i].tolist()
if c == 'eeg': #eeg supports multiple electrodes
samples[c] = [samples[c]]
samples[c] = [ [ s ] for s in samples[c] ]
return samples

#stop streaming
Expand Down
16 changes: 15 additions & 1 deletion devices/OpenBCI.py
Expand Up @@ -7,6 +7,7 @@

import glob
import serial
import serial.tools.list_ports
import struct
import time
import sys
Expand All @@ -32,10 +33,23 @@ def __init__(self, dev_i = 0):

print("Serial established...")




#find all devices
#return as array of device id strings
def list_devices(self):
return glob.glob('/dev/tty.usb*')

def serial_ports():
""" Lists serial port names
:raises EnvironmentError:
On unsupported or unknown platforms
:returns:
A list of the serial ports available on the system
"""
return [comport.device for comport in serial.tools.list_ports.comports()]
#return glob.glob('/dev/tty.usb*')

#start streaming
def start(self, fs, channels):
Expand Down
Binary file modified dist/art-bio.exe
Binary file not shown.
70 changes: 61 additions & 9 deletions examples/receive_eeg_to_pd.pd
@@ -1,15 +1,67 @@
#N canvas 400 90 540 405 10;
#N canvas 50 150 1212 620 10;
#X obj 37 48 mrpeach/unpackOSC;
#X floatatom 45 134 10 0 0 0 - - -;
#X obj 37 73 route /rtbio/eeg/alpha /rtbio/eeg/beta /rtbio/eeg/gamma
/rtbio/eeg/delta;
#X floatatom 125 132 10 0 0 0 - - -;
#X floatatom 227 164 10 0 0 0 - - -;
#X floatatom 200 132 10 0 0 0 - - -;
#X floatatom 291 132 10 0 0 0 - - -;
#X obj 37 23 mrpeach/udpreceive 4810;
#X connect 0 0 2 0;
#X obj 37 73 route /rtbio/eeg/alpha /rtbio/eeg/beta /rtbio/eeg/theta
/rtbio/eeg/delta /rtbio/eeg/raw;
#N canvas 0 50 1377 540 graph 0;
#N canvas 350 172 1009 430 (subpatch) 0;
#X array \$0_array 500 float 1;
#A 0 12 85 7 61 81 -58 103 8 71 -12 -9 31 -55 31 62 96 61 -101 -27
-91 48 83 44 -28 21 84 3 93 -38 4 27 9 -111 -72 -170 -152 -81 -15 23
88 -116 -117 -103 -77 -30 95 26 71 87 5 -40 27 -21 66 -29 78 131 118
164 116 -52 -182 -124 -24 123 -44 135 -131 -322 -205 -125 14 63 -30
-62 85 -165 -48 -89 -23 48 -70 -57 -30 -30 7 -121 -148 -90 -5 -112
-143 -126 -95 -136 -38 143 153 36 103 120 61 19 53 240 98 264 224 62
141 49 102 204 96 299 215 150 186 220 45 -43 -94 -61 -14 95 -78 -13
4 138 158 -9 -153 -92 -139 -129 -126 -69 -159 -111 106 87 85 70 62
0 -125 -26 65 225 -1 95 -71 -182 -265 -246 -213 -167 -12 -125 3 107
-59 -35 -4 -153 -216 -109 -23 21 -25 -116 -204 -112 1 -9 12 56 -8 31
56 2 15 -4 -30 -2 -49 -130 -60 -57 -36 -55 -35 39 13 50 16 -67 -70
77 176 178 211 151 110 97 -119 -109 -45 26 -28 -39 39 102 124 -20 -10
-29 71 -80 -194 -334 -320 -266 -193 -254 -194 -512 -512 -512 -512 -512
-512 -512 -512 -512 -512 -65 307 506 506 506 506 506 506 506 506 506
506 506 506 506 506 506 506 506 506 506 463 336 275 310 411 366 332
385 403 113 -2 -41 55 100 169 198 299 121 40 -185 -153 -175 4 37 11
172 88 103 -89 -330 -292 -212 -121 39 179 56 57 -77 -106 -335 -231
-266 -111 -118 -48 -91 -143 -119 -89 -64 24 38 64 -36 -69 -166 -96
-97 -57 -48 -32 -199 -236 -269 -149 -143 -13 -270 -260 -136 -35 -137
-37 -49 93 32 -84 -86 165 -85 -73 -32 130 -121 -153 -76 -315 -321 -251
-302 -209 -63 -30 -21 163 363 506 506 506 506 476 350 365 506 321 261
278 218 260 271 236 132 178 127 277 103 141 -29 121 3 116 0 139 25
71 34 38 71 1 3 112 14 -8 -25 25 21 47 -11 52 45 17 -160 13 -73 -1
-55 28 -50 -4 -8 -63 -60 4 -84 17 96 -38 -38 -45 -51 110 -3 122 102
44 23 -37 -230 -84 -79 7 -148 77 10 -25 -89 -217 -157 -512 -512 -512
-512 -512 -512 -512 -512 -512 -512 -356 -27 108 355 483 502 506 391
371 337 478 506 506 506 506 506 506 435 506 383 319 308 379 271 248
285 329 164 119 128 146 139 240 33 241 140 77 -100 -123 31 -142 -97
-144 -50 -26 334 198 142 8 41 71 34 39 72 -83;
#X coords 0 400 499 -400 500 100 1 0 0;
#X restore 304 124 graph;
#X obj 172 301 + 1;
#X obj 155 258 0;
#X obj 72 234 t f b;
#X obj 213 259 % 500;
#X obj 52 296 tabwrite \$0_array;
#X obj 61 31 inlet;
#X obj 75 161 - 512;
#X connect 1 0 4 0;
#X connect 2 0 1 0;
#X connect 2 1 3 0;
#X connect 2 2 4 0;
#X connect 2 3 5 0;
#X connect 6 0 0 0;
#X connect 2 0 5 1;
#X connect 3 0 5 0;
#X connect 3 1 2 0;
#X connect 4 0 2 1;
#X connect 6 0 7 0;
#X connect 7 0 3 0;
#X coords 0 -1 1 1 510 130 1 300 100;
#X restore 665 180 pd graph;
#X connect 0 0 6 0;
#X connect 5 0 0 0;
#X connect 6 0 1 0;
#X connect 6 1 2 0;
#X connect 6 2 3 0;
#X connect 6 3 4 0;
#X connect 6 4 7 0;
4 changes: 3 additions & 1 deletion examples/visualize.html
Expand Up @@ -45,12 +45,14 @@
var time_data = event.data.split('|');
var time = time_data[0] * 1000;
var data = time_data[1].split('/');
console.log(data[3]);
if(data[2] == 'raw') {
ts_index = channels[data[1]];
if(ts_index !== undefined) {
var samples = data[3].replace('[', '').replace(']', '').replace('[', '').replace(']', '').split(', ');
console.log(samples);
for(var i=0; i<samples.length; i++) {
var sample = samples[i];
var sample = samples[i].replace('[', '').replace(']', '');
if(data[1] == 'eda') {
sample = prev_eda !== undefined ? 0.995 * prev_eda + 0.005 * sample : sample;
prev_eda = sample;
Expand Down
4 changes: 2 additions & 2 deletions init_sources.py
Expand Up @@ -20,12 +20,12 @@ def init_sources(connections, fs):
#have to get eeg chan numbers from somewhere
num_chans = 1 if fs == 100 else 8
print('number of chans {}'.format(num_chans))
sources[source] = Oscillations(fs, num_chans, 500, 0.75,
sources[source] = Oscillations(fs, num_chans, 256, 0.8,
{
'theta': [4.0, 8.0],
'alpha': [8.0, 13.0],
'beta': [13.0, 30.0],
'delta': [3.0, 4.0],
'delta': [1.0, 4.0],
}
)
else:
Expand Down
7 changes: 4 additions & 3 deletions physiology/Oscillations.py
Expand Up @@ -19,7 +19,8 @@ def add_data(self, samples):
#for c in samples:
# out.append(c[i])
#freqs = self.add_samples(out)
freqs = self.add_samples(samples[i])
freqs_in = self.add_samples(samples[i])
freqs = freqs_in if freqs_in != None else freqs
return freqs

def add_samples(self, samples):
Expand All @@ -45,8 +46,8 @@ def add_samples(self, samples):
for f in self.freqs:
freq = self.freqs[f]
start = np.where((freqC <= freq[0]) & (freqC >= 0))[0][-1]
stop = np.where((freqC >= freq[1]) & (freqC >= 0))[0][-1]
freqpower[f][i] = sum(powerspect[start:stop])
stop = np.where((freqC >= freq[1]) & (freqC >= 0))[0][0]
freqpower[f][i] = np.mean(powerspect[start:stop]) + np.mean(powerspect[-stop-1:-start-1])

self.idx = int(self.fft_size * self.overlap)
raw_electrodes[i] = [float(electrode_data[a]) for a in range(self.idx, len(electrode_data))]
Expand Down
24 changes: 13 additions & 11 deletions router.py
Expand Up @@ -49,7 +49,8 @@ def route_data(self, source, connections, features, raw_data):
for destination in connections['r' + source]:
osc_dest = '/{}/raw'.format(source)
if destination == 'osc':
self.osc_client.send_message(self.osc_prefix + osc_dest, raw_data)
for data in raw_data:
self.osc_client.send_message(self.osc_prefix + osc_dest, data)
elif destination == 'file':
self.file_handle.write('{} {}: {}\n'.format(current_time, osc_dest, str(raw_data)))
elif destination == 'ws':
Expand All @@ -61,15 +62,16 @@ def route_data(self, source, connections, features, raw_data):
for destination in source_connections:
for feature in features.keys():
osc_dest = '/{}/{}'.format(source, feature)
for data in features[feature]:
if destination == 'osc':
self.osc_client.send_message(self.osc_prefix + osc_dest, data)
elif destination == 'file':
self.file_handle.write('{} {}: {}\n'.format(current_time, osc_dest, str(data)))
elif destination == 'ws':
self.ws_server.add_message('{}|{}/{}'.format(current_time, osc_dest, str(raw_data)))
elif destination == 'digital':
if self.digital_out_func:
self.digital_out_func()
#for data in features[feature]:
data = features[feature]
if destination == 'osc':
self.osc_client.send_message(self.osc_prefix + osc_dest, data)
elif destination == 'file':
self.file_handle.write('{} {}: {}\n'.format(current_time, osc_dest, str(data)))
elif destination == 'ws':
self.ws_server.add_message('{}|{}/{}'.format(current_time, osc_dest, str(raw_data)))
elif destination == 'digital':
if self.digital_out_func:
self.digital_out_func()


36 changes: 34 additions & 2 deletions tests/test_Oscillations.py
Expand Up @@ -5,9 +5,41 @@ def test_Oscillations():
'alpha': [8, 13]
})

res = eeg.add_data([[0, 0, 0, 0, 0, 0]])
res = eeg.add_data([[0], [0], [0], [0], [0], [0]])
assert res == None

more_data = [[1 for _ in range(250)]]
more_data = [[1] for _ in range(250)]
res = eeg.add_data(more_data)
assert res['alpha'] == [-10650.084320520564]


def test_Oscillations_10Hz():
sin_10 = [[50], [79] ,[98] ,[98] ,[79] ,[50] ,[21] ,[2] ,[2] ,[21] ]
wave = []
for _ in range(30):
wave += sin_10

eeg = Oscillations(100, 1, 256, 0.5, {
'alpha': [8, 13],
'beta': [13, 30]
})
res = eeg.add_data(wave)
print(res)

import numpy as np

def test_Oscillations_5Hz():
sin_5 = [[50], [98] ,[79] ,[21] ,[2] ]
wave = []
for _ in range(60):
wave += sin_5
wave = np.array(wave) * 100

eeg = Oscillations(100, 1, 256, 0.5, {
'all': [1, 40],
'alpha': [8, 13],
'beta': [4.9, 5.1]
})
res = eeg.add_data(wave)
print(res)

0 comments on commit 3204140

Please sign in to comment.