From e08b7442ec31be16450d0b42604cf8d83939169f Mon Sep 17 00:00:00 2001 From: jdpigeon Date: Thu, 17 May 2018 16:30:46 -0400 Subject: [PATCH] Implemented CLI functionality; changed references of muse-lsl to muselsl --- LICENSE.txt | 2 +- README.md | 29 +++++++++++++---- examples/startMuseStream.py | 10 ++++-- muselsl/__main__.py | 2 ++ muselsl/{muse-lsl.py => cli.py} | 20 +++++------- setup.py | 57 ++++++++++++++++++--------------- 6 files changed, 72 insertions(+), 48 deletions(-) create mode 100644 muselsl/__main__.py rename muselsl/{muse-lsl.py => cli.py} (95%) diff --git a/LICENSE.txt b/LICENSE.txt index 0288f10..968085c 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -8,7 +8,7 @@ modification, are permitted provided that the following conditions are met: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the names of muse-lsl authors nor the names of any + * Neither the names of muselsl authors nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/README.md b/README.md index adb6212..5a2c8f1 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This is a Python package for streaming and visualizing EEG data from the Muse 20 The code relies on [pygatt](https://github.com/peplin/pygatt) for the BLE communication. pygatt works on Linux and should work on Windows and macOS provided that you have a BLED112 Bluetooth dongle. -*Note: Another option for connecting to a Muse on Windows is via [BlueMuse](https://github.com/kowalej/BlueMuse/tree/master/Dist) which will output the same LSL stream format as muse-lsl.* +*Note: Another option for connecting to a Muse on Windows is via [BlueMuse](https://github.com/kowalej/BlueMuse/tree/master/Dist) which will output the same LSL stream format as muselsl.* You will need to find the MAC address or name of your Muse headset. @@ -18,25 +18,40 @@ Compatible with Python 2.7 and Python 3.x. ## Usage -*Everything can be run as a CLI using muse-lsl.py +Install with pip + +`pip install muselsl` + +*Everything can be run directly from the command line* + +To print a list of available muses: + +`muselsl list` To stream data with LSL: -`python muse-lsl.py stream` +`muselsl stream` The script will auto detect and connect to the first Muse device. In case you want a specific device or if the detection fails, find the name of the device and pass it to the script: -`python muse-lsl.py stream --name YOUR_DEVICE_NAME` +`muselsl stream --name YOUR_DEVICE_NAME` You can also directly pass the MAC address (this option is also faster at startup): -`python muse-lsl.py stream --address YOUR_DEVICE_ADDRESS` +`muselsl stream --address YOUR_DEVICE_ADDRESS` -Once the stream is up and running, from another prompt, you can visualize it with: +Once a stream is up and running, you now have access to the following commands in another prompt: -`python muse-lsl.py lslview` +To view data +`muselsl viewlsl` + +To record data + +`muselsl record` + + ### Backends You can choose between gatt, bgapi, and bluemuse backends. diff --git a/examples/startMuseStream.py b/examples/startMuseStream.py index 776d9df..1779f10 100644 --- a/examples/startMuseStream.py +++ b/examples/startMuseStream.py @@ -1,7 +1,11 @@ from muselsl import muse_stream muses = muse_stream.list_muses() -muse_stream.stream(muses[0]['address']) -# Note: Streaming is synchronous, so code here will not execute until the stream has been closed -print('Stream has ended') \ No newline at end of file +if not muses: + print('No Muses found') +else: + muse_stream.stream(muses[0]['address']) + + # Note: Streaming is synchronous, so code here will not execute until the stream has been closed + print('Stream has ended') diff --git a/muselsl/__main__.py b/muselsl/__main__.py new file mode 100644 index 0000000..f13026c --- /dev/null +++ b/muselsl/__main__.py @@ -0,0 +1,2 @@ +from .cli import main +main() \ No newline at end of file diff --git a/muselsl/muse-lsl.py b/muselsl/cli.py similarity index 95% rename from muselsl/muse-lsl.py rename to muselsl/cli.py index 887eb4f..2798dc8 100644 --- a/muselsl/muse-lsl.py +++ b/muselsl/cli.py @@ -3,11 +3,11 @@ import argparse -class Program: +class main: def __init__(self): parser = argparse.ArgumentParser( description='Python package for streaming, recording, and visualizing EEG data from the Muse 2016 headset.', - usage='''muse-lsl [] + usage='''muselsl [] Available commands: list List available Muse devices. -b --backend pygatt backend to use. can be auto, gatt or bgapi. @@ -61,7 +61,7 @@ def list(self): dest="interface", type=str, default=None, help="the interface to use, 'hci0' for gatt or a com port for bgapi.") args = parser.parse_args(sys.argv[2:]) - import muse_stream + import muselsl.muse_stream as muse_stream muses = muse_stream.list_muses(args.backend, args.interface) if(muses): for muse in muses: @@ -86,7 +86,7 @@ def stream(self): dest="interface", type=str, default=None, help="The interface to use, 'hci0' for gatt or a com port for bgapi.") args = parser.parse_args(sys.argv[2:]) - import muse_stream + import muselsl.muse_stream as muse_stream muse_stream.stream(args.address, args.backend, args.interface, args.name) @@ -109,7 +109,7 @@ def record(self): dest="filename", type=str, default=None, help="name of the recording file.") args = parser.parse_args(sys.argv[2:]) - import muse_record + import muselsl.muse_record as muse_record muse_record.record(args.address, args.backend, args.interface, args.name, args.filename) @@ -133,10 +133,10 @@ def viewlsl(self): help="viewer version (1 or 2) - 1 is the default stable version, 2 is in development (and takes no arguments).") args = parser.parse_args(sys.argv[2:]) if args.version == 2: - import lsl_viewer_v2 + import muselsl.lsl_viewer_v2 as lsl_viewer_v2 lsl_viewer_v2.view() else: - import lsl_viewer + import muselsl.lsl_viewer as lsl_viewer lsl_viewer.view(args.window, args.scale, args.refresh, args.figure) def recordlsl(self): @@ -151,9 +151,5 @@ def recordlsl(self): dest="dejitter", type=bool, default=False, help="whether to apply dejitter correction to timestamps.") args = parser.parse_args(sys.argv[2:]) - import lsl_record + import muselsl.lsl_record as lsl_record lsl_record.record(args.duration, args.filename, args.dejitter) - - -if __name__ == '__main__': - Program() diff --git a/setup.py b/setup.py index 7024f2e..cdabc67 100644 --- a/setup.py +++ b/setup.py @@ -2,6 +2,7 @@ from shutil import copyfile import os + def copy_docs(): docs_dir = 'muselsl/docs' if not os.path.exists(docs_dir): @@ -10,6 +11,7 @@ def copy_docs(): copyfile('README.md', docs_dir + '/README.md') #copyfile('blinks.png', docs_dir + '/blinks.png') + copy_docs() setup(name='muselsl', @@ -20,33 +22,38 @@ def copy_docs(): author='Alexandre Barachant', author_email='alexandre.barachant@gmail.com', license='BSD (3-clause)', - scripts=['muselsl/muse-lsl.py'], + entry_points={ + 'console_scripts': [ + 'muselsl=muselsl.cli:main', + ], + }, packages=find_packages(), - package_data={'muselsl': ['docs/README.md']}, + package_data={'muselsl': ['docs/README.md', 'docs/examples/*']}, include_package_data=True, zip_safe=False, - install_requires=['bitstring', 'pylsl', 'pygatt', 'pandas', 'scikit-learn', 'numpy', 'seaborn', 'pexpect'], + install_requires=['bitstring', 'pylsl', 'pygatt', + 'pandas', 'scikit-learn', 'numpy', 'seaborn', 'pexpect'], extras_require={'Viewer V2': ['mne', 'vispy']}, classifiers=[ - # How mature is this project? Common values are - # 3 - Alpha - # 4 - Beta - # 5 - Production/Stable - 'Development Status :: 4 - Beta', - - # Indicate who your project is intended for - 'Intended Audience :: Science/Research', - 'Topic :: Software Development :: Utilities', - - # Pick your license as you wish (should match "license" above) - 'License :: OSI Approved :: BSD License', - - # Specify the Python versions you support here. In particular, ensure - # that you indicate whether you support Python 2, Python 3 or both. - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX', - 'Operating System :: Unix', - 'Operating System :: MacOS' - - 'Programming Language :: Python'] - ) + # How mature is this project? Common values are + # 3 - Alpha + # 4 - Beta + # 5 - Production/Stable + 'Development Status :: 4 - Beta', + + # Indicate who your project is intended for + 'Intended Audience :: Science/Research', + 'Topic :: Software Development :: Utilities', + + # Pick your license as you wish (should match "license" above) + 'License :: OSI Approved :: BSD License', + + # Specify the Python versions you support here. In particular, ensure + # that you indicate whether you support Python 2, Python 3 or both. + 'Operating System :: Microsoft :: Windows', + 'Operating System :: POSIX', + 'Operating System :: Unix', + 'Operating System :: MacOS' + + 'Programming Language :: Python'] + )