-
Notifications
You must be signed in to change notification settings - Fork 186
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e0f2bad
commit b8b1922
Showing
4 changed files
with
314 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
"""Test.""" | ||
import numpy as np | ||
import pandas as pd | ||
from time import time, strftime, gmtime | ||
from optparse import OptionParser | ||
from pylsl import StreamInlet, resolve_byprop | ||
|
||
default_fname = ("data_%s.csv" % strftime("%Y-%m-%d-%H:%M:%S", gmtime())) | ||
parser = OptionParser() | ||
parser.add_option("-d", "--duration", | ||
dest="duration", type='int', default=60, | ||
help="duration of the recording in seconds.") | ||
parser.add_option("-f", "--filename", | ||
dest="filename", type='str', default=default_fname, | ||
help="Name of the recording file.") | ||
|
||
(options, args) = parser.parse_args() | ||
|
||
|
||
print("looking for an EEG stream...") | ||
streams = resolve_byprop('type', 'EEG', timeout=2) | ||
|
||
if len(streams) == 0: | ||
raise(RuntimeError, "Cant find EEG stream") | ||
|
||
print("Start aquiring data") | ||
inlet = StreamInlet(streams[0], max_chunklen=12) | ||
eeg_time_correction = inlet.time_correction() | ||
|
||
print("looking for a Markers stream...") | ||
marker_streams = resolve_byprop('type', 'Markers', timeout=2) | ||
|
||
if marker_streams: | ||
inlet_marker = StreamInlet(marker_streams[0]) | ||
marker_time_correction = inlet_marker.time_correction() | ||
else: | ||
inlet_marker = False | ||
print("Cant find Markers stream") | ||
|
||
info = inlet.info() | ||
description = info.desc() | ||
|
||
freq = info.nominal_srate() | ||
Nchan = info.channel_count() | ||
|
||
ch = description.child('channels').first_child() | ||
ch_names = [ch.child_value('label')] | ||
for i in range(1, Nchan): | ||
ch = ch.next_sibling() | ||
ch_names.append(ch.child_value('label')) | ||
|
||
res = [] | ||
timestamps = [] | ||
markers = [] | ||
t_init = time() | ||
print('Start recording at time t=%.3f' % t_init) | ||
while (time() - t_init) < options.duration: | ||
try: | ||
data, timestamp = inlet.pull_chunk(timeout=1.0, | ||
max_samples=12) | ||
if timestamp: | ||
res.append(data) | ||
timestamps.extend(timestamp) | ||
if inlet_marker: | ||
marker, timestamp = inlet_marker.pull_sample(timeout=0.0) | ||
if timestamp: | ||
markers.append([marker, timestamp]) | ||
except KeyboardInterrupt: | ||
break | ||
|
||
res = np.concatenate(res, axis=0) | ||
timestamps = np.array(timestamps) | ||
res = np.c_[timestamps, res] | ||
print res.shape | ||
data = pd.DataFrame(data=res, columns=['timestamps'] + ch_names) | ||
|
||
data['Marker'] = 0 | ||
# process markers: | ||
for marker in markers: | ||
# find index of margers | ||
ix = np.argmin(np.abs(marker[1] - timestamps)) | ||
val = timestamps[ix] | ||
data.loc[ix, 'Marker'] = marker[0][0] | ||
|
||
|
||
data.to_csv(options.filename, float_format='%.3f', index=False) | ||
|
||
print('Done !') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
"""Test.""" | ||
import numpy as np | ||
import matplotlib.pyplot as plt | ||
from scipy.signal import butter, filtfilt | ||
from time import time | ||
from pylsl import StreamInlet, resolve_byprop | ||
import seaborn as sns | ||
sns.set(style="whitegrid") | ||
|
||
from optparse import OptionParser | ||
|
||
parser = OptionParser() | ||
|
||
parser.add_option("-w", "--window", | ||
dest="window", type='float', default=5., | ||
help="window lenght to display in seconds.") | ||
parser.add_option("-s", "--scale", | ||
dest="scale", type='float', default=100, | ||
help="scale in uV") | ||
parser.add_option("-r", "--refresh", | ||
dest="refresh", type='float', default=0.2, | ||
help="refresh rate in seconds.") | ||
parser.add_option("-f", "--figure", | ||
dest="figure", type='string', default="15x6", | ||
help="window size.") | ||
parser.add_option("-a", "--avgref", | ||
dest="avgref", action="store_false", default=False, | ||
help="Activate average reference.") | ||
|
||
filt = True | ||
subsample = 2 | ||
buf = 12 | ||
|
||
(options, args) = parser.parse_args() | ||
|
||
figsize = np.int16(options.figure.split('x')) | ||
print figsize | ||
|
||
print("looking for an EEG stream...") | ||
streams = resolve_byprop('type', 'EEG', timeout=2) | ||
|
||
if len(streams) == 0: | ||
raise(RuntimeError, "Cant find EEG stream") | ||
print("Start aquiring data") | ||
|
||
inlet = StreamInlet(streams[0], max_chunklen=buf) | ||
|
||
info = inlet.info() | ||
description = info.desc() | ||
|
||
freq = info.nominal_srate() | ||
Nchan = info.channel_count() | ||
|
||
ch = description.child('channels').first_child() | ||
ch_names = [ch.child_value('label')] | ||
for i in range(Nchan): | ||
ch = ch.next_sibling() | ||
ch_names.append(ch.child_value('label')) | ||
|
||
picks = range(Nchan) | ||
# create a new inlet to read from the stream | ||
|
||
frs = np.fft.fftfreq(n=128, d=1.0/freq) | ||
|
||
ix_noise = (frs > 55) & (frs < 65) | ||
ix_signal = (frs > 25) & (frs < 35) | ||
|
||
to_read = int(options.window * (freq / buf)) | ||
Nchan_plot = len(ch_names) | ||
|
||
res = [] | ||
t_init = time() | ||
k = 0 | ||
while k < to_read: | ||
data, timestamps = inlet.pull_chunk(timeout=1.0, max_samples=buf) | ||
if timestamps: | ||
res.append(data) | ||
k += 1 | ||
dur = time() - t_init | ||
data = np.concatenate(res, axis=0) | ||
print data.shape | ||
if options.avgref: | ||
data -= np.atleast_2d(data.mean(1)).T | ||
ffts = np.abs(np.fft.fft(data[:, 0:], n=128, axis=0)) | ||
dur = data[-1, 0] - data[0, 0] | ||
|
||
bf, af = butter(4, np.array([1, 40])/(freq/2.), 'bandpass') | ||
|
||
# You probably won't need this if you're embedding things in a tkinter plot... | ||
plt.ion() | ||
|
||
fig, axes = plt.subplots(1, 1, figsize=figsize, | ||
sharex=True) | ||
sns.despine(left=True) | ||
|
||
|
||
time = np.arange(len(data))/freq | ||
|
||
lines = [] | ||
impedances = np.log(ffts[ix_noise].mean(0)) / np.log(ffts[ix_signal].mean(0)) | ||
print impedances | ||
for i, ix in enumerate(picks): | ||
line, = axes.plot(time[::subsample], | ||
data[::subsample, ix] - (i * options.scale * 2), | ||
lw=1) | ||
lines.append(line) | ||
vmin = 0 | ||
vmax = 0 | ||
axes.set_ylim(-len(picks) * options.scale * 2, | ||
2 * options.scale) | ||
ticks = np.arange(0, -Nchan * options.scale * 2, -options.scale * 2) | ||
|
||
axes.set_yticks(ticks) | ||
axes.get_xaxis().set_visible(False) | ||
|
||
ticks_labels = ['%s - %.1f' % (ch_names[i], impedances[i]) | ||
for i in picks] | ||
axes.set_yticklabels(ticks_labels) | ||
plt.show() | ||
|
||
display_every = int(options.refresh / (buf/freq)) | ||
k = 0 | ||
while 1: | ||
try: | ||
data, timestamps = inlet.pull_chunk(timeout=1.0, max_samples=buf) | ||
if timestamps: | ||
res.append(data) | ||
res.pop(0) | ||
k += 1 | ||
if k == display_every: | ||
data = np.concatenate(res, axis=0) | ||
if options.avgref: | ||
data -= np.atleast_2d(data.mean(1)).T | ||
#ffts = np.abs(np.fft.fft(data[:, 1:], n=128, axis=0)) | ||
|
||
if filt: | ||
data = filtfilt(bf, af, data, axis=0) | ||
for i, ix in enumerate(picks): | ||
lines[i].set_ydata(data[::subsample, ix] - | ||
(i * options.scale * 2)) | ||
# axes.relim() | ||
# axes.autoscale_view() | ||
#impedances = (np.log(ffts[ix_noise].mean(0)) / | ||
# np.log(ffts[ix_signal].mean(0))) | ||
impedances = np.std(data[:, 0:], 0) | ||
ticks_labels = ['%s - %.2f' % (ch_names[i], impedances[i]) | ||
for i in picks] | ||
axes.set_yticklabels(ticks_labels) | ||
fig.canvas.draw() | ||
k = 0 | ||
except KeyboardInterrupt: | ||
break |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
from muse import Muse | ||
from time import sleep | ||
from pylsl import StreamInfo, StreamOutlet | ||
|
||
YOUR_DEVICE_ADDRESS = "00:55:DA:B0:06:D6" | ||
|
||
info = info = StreamInfo('Muse', 'EEG', 5, 256, 'float32', | ||
'Muse%s' % YOUR_DEVICE_ADDRESS) | ||
|
||
info.desc().append_child_value("manufacturer", "Muse") | ||
channels = info.desc().append_child("channels") | ||
|
||
for c in ['TP9', 'AF7', 'AF8', 'TP10', 'Right AUX']: | ||
channels.append_child("channel") \ | ||
.append_child_value("label", c) \ | ||
.append_child_value("unit", "microvolts") \ | ||
.append_child_value("type", "EEG") | ||
outlet = StreamOutlet(info, 12, 360) | ||
|
||
|
||
def process(data, timestamps): | ||
for ii in range(12): | ||
outlet.push_sample(data[:, ii], timestamps[ii]) | ||
|
||
muse = Muse(address=YOUR_DEVICE_ADDRESS, callback=process) | ||
|
||
muse.connect() | ||
print('Connected') | ||
muse.start() | ||
print('Streaming') | ||
|
||
while 1: | ||
try: | ||
sleep(1) | ||
except: | ||
break | ||
|
||
muse.stop() | ||
muse.disconnect() | ||
print('Disonnected') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from muse import Muse | ||
from time import time, sleep | ||
import numpy as np | ||
import pandas as pd | ||
YOUR_DEVICE_ADDRESS = "00:55:DA:B0:06:D6" | ||
|
||
full_time = [] | ||
full_data = [] | ||
|
||
def process(data, timestamps): | ||
full_time.append(timestamps) | ||
full_data.append(data) | ||
|
||
muse = Muse(YOUR_DEVICE_ADDRESS, process) | ||
|
||
muse.connect() | ||
muse.start() | ||
|
||
while 1: | ||
try: | ||
sleep(1) | ||
except: | ||
break | ||
|
||
muse.stop() | ||
muse.disconnect() | ||
|
||
full_time = np.concatenate(full_time) | ||
full_data = np.concatenate(full_data, 1).T | ||
res = pd.DataFrame(data=full_data, | ||
columns=['TP9', 'AF7', 'AF8', 'TP10', 'Right AUX']) | ||
|
||
res['timestamps'] = full_time | ||
res.to_csv('dump.csv', float_format='%.3f') |