Skip to content

Commit

Permalink
add examples and stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandrebarachant committed Jan 27, 2017
1 parent e0f2bad commit b8b1922
Show file tree
Hide file tree
Showing 4 changed files with 314 additions and 0 deletions.
88 changes: 88 additions & 0 deletions lsl-record.py
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 !')
152 changes: 152 additions & 0 deletions lsl-viewer.py
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
40 changes: 40 additions & 0 deletions muse_lsl.py
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')
34 changes: 34 additions & 0 deletions muse_record.py
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')

0 comments on commit b8b1922

Please sign in to comment.