Skip to content

Commit

Permalink
Reconciled branch differences; added smart filenames to both record a…
Browse files Browse the repository at this point in the history
…nd recordlsl
  • Loading branch information
jdpigeon committed May 9, 2018
1 parent 5bb1e1e commit cfbf828
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 58 deletions.
9 changes: 6 additions & 3 deletions muselsl/muselsl/lsl_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
import pandas as pd
from pylsl import StreamInlet, resolve_byprop
from sklearn.linear_model import LinearRegression
from time import time, strftime, gmtime

def record(duration, filename):
# dejitter timestamps
dejitter = False

def record(duration, filename=None, dejitter=False):
if not filename:
filename = ("recording_%s.csv" %
strftime("%Y-%m-%d-%H.%M.%S", gmtime()))

print("looking for an EEG stream...")
streams = resolve_byprop('type', 'EEG', timeout=2)
Expand Down
24 changes: 14 additions & 10 deletions muselsl/muselsl/muse-lsl.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import re
import os
import configparser
from time import time, strftime, gmtime


class Program:
Expand All @@ -28,7 +27,7 @@ def __init__(self):
-a --address device MAC address
-n --name device name (e.g. Muse-41D2)
-b --backend pygatt backend to use. can be auto, gatt or bgapi
-i --interface The interfact to use, 'hci0' for gatt or a com port for bgapi.
-i --interface the interfact to use, 'hci0' for gatt or a com port for bgapi.
viewlsl Visualize EEG data from an LSL stream.
-w --window window length to display in seconds.
Expand All @@ -40,6 +39,7 @@ def __init__(self):
recordlsl Record EEG data from an LSL stream.
-d --duration duration of the recording in seconds.
-f --filename name of the recording file.
-dj --dejitter whether to apply dejitter correction to timestamps.
''')

parser.add_argument('command', help='Command to run.')
Expand All @@ -62,7 +62,7 @@ def list(self):
help="pygatt backend to use. can be auto, gatt or bgapi.")
parser.add_argument("-i", "--interface",
dest="interface", type=str, default=None,
help="The interface to use, 'hci0' for gatt or a com port for bgapi.")
help="the interface to use, 'hci0' for gatt or a com port for bgapi.")
args = parser.parse_args(sys.argv[2:])
import muse_stream
muses = muse_stream.list_muses(args.backend, args.interface)
Expand Down Expand Up @@ -107,10 +107,13 @@ def record(self):
help="pygatt backend to use. can be auto, gatt or bgapi")
parser.add_argument("-i", "--interface",
dest="interface", type=str, default=None,
help="The interface to use, 'hci0' for gatt or a com port for bgapi")
help="the interface to use, 'hci0' for gatt or a com port for bgapi")
parser.add_argument("-f", "--filename",
dest="filename", type=str, default=None,
help="name of the recording file.")
args = parser.parse_args(sys.argv[2:])
import muse_record
muse_record.record(args.address, args.backend, args.interface, args.name)
muse_record.record(args.address, args.backend, args.interface, args.name, args.filename)

def viewlsl(self):
parser = argparse.ArgumentParser(
Expand Down Expand Up @@ -140,17 +143,18 @@ def viewlsl(self):

def recordlsl(self):
parser = argparse.ArgumentParser(description='Record data from Muse.')
default_fname = ("data_%s.csv" %
strftime("%Y-%m-%d-%H.%M.%S", gmtime()))
parser.add_argument("-d", "--duration",
dest="duration", type=int, default=60,
help="duration of the recording in seconds.")
parser.add_argument("-f", "--filename",
dest="filename", type=str, default=default_fname,
help="Name of the recording file.")
dest="filename", type=str, default=None,
help="name of the recording file.")
parser.add_argument("-dj", "--dejitter",
dest="dejitter", type=bool, default=False,
help="whether to apply dejitter correction to timestamps.")
args = parser.parse_args(sys.argv[2:])
import lsl_record
lsl_record.record(args.duration, args.filename)
lsl_record.record(args.duration, args.filename, args.dejitter)


if __name__ == '__main__':
Expand Down
30 changes: 1 addition & 29 deletions muselsl/muselsl/muse.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,6 @@ def connect(self, interface=None, backend='auto'):
self.adapter = pygatt.BGAPIBackend(serial_port=self.interface)

self.adapter.start()
print('started')

if self.address is None:
address = self.find_muse_address(self.name)
if address is None:
raise(ValueError("Can't find Muse Device"))
else:
self.address = address
self.device = self.adapter.connect(self.address)

# subscribes to EEG stream
Expand All @@ -94,31 +86,11 @@ def connect(self, interface=None, backend='auto'):
self._subscribe_gyro()

return True

except (pygatt.exceptions.NotConnectedError, pygatt.exceptions.NotificationTimeout):
print('Connection to', self.address, 'failed')
return False

def find_muse_address(self, name=None):
if self.backend == 'bluemuse':
print('Not supported by bluemuse backend.')
return None

"""look for ble device with a muse in the name"""
list_devices = self.adapter.scan(timeout=10.5)
for device in list_devices:
if name:
if device['name'] == name:
print('Found device %s : %s' % (device['name'],
device['address']))
return device['address']

elif 'Muse' in device['name']:
print('Found device %s : %s' % (device['name'],
device['address']))
return device['address']

return None

def _write_cmd(self, cmd):
"""Wrapper to write a command to the Muse device.
Expand Down
37 changes: 21 additions & 16 deletions muselsl/muselsl/muse_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,24 @@
import numpy as np
import pandas as pd

full_time = []
full_data = []

def __process__(data, timestamps):
full_time.append(timestamps)
full_data.append(data)

def record(address, backend, interface, name):
def record(address, backend, interface, name, filename):
if backend == 'bluemuse':
raise(NotImplementedError('Direct record not supported with BlueMuse background. Use lslrecord with BlueMuse instead.'))
return
raise(NotImplementedError(
'Direct record not supported with BlueMuse backend. Use lslrecord instead.'))

if not filename:
filename = ("recording_%s.csv" %
strftime("%Y-%m-%d-%H.%M.%S", gmtime()))

eeg_samples = []
timestamps = []

def save_eeg(new_samples, new_timestamps):
eeg_samples.append(new_samples)
timestamps.append(new_timestamps)

muse = Muse(address, __process__)
muse = Muse(address, save_eeg)

muse.connect()
muse.start()
Expand All @@ -29,10 +34,10 @@ def record(address, backend, interface, name):
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'])
timestamps = np.concatenate(timestamps)
eeg_samples = np.concatenate(eeg_samples, 1).T
recording = pd.DataFrame(data=eeg_samples,
columns=['TP9', 'AF7', 'AF8', 'TP10', 'Right AUX'])

res['timestamps'] = full_time
res.to_csv('dump.csv', float_format='%.3f')
recording['timestamps'] = timestamps
recording.to_csv(filename, float_format='%.3f')

0 comments on commit cfbf828

Please sign in to comment.