mne-tools / mne-lsl Goto Github PK
View Code? Open in Web Editor NEWA framework for real-time brain signal streaming with MNE-Python.
Home Page: https://mne.tools/mne-lsl
License: BSD 3-Clause "New" or "Revised" License
A framework for real-time brain signal streaming with MNE-Python.
Home Page: https://mne.tools/mne-lsl
License: BSD 3-Clause "New" or "Revised" License
Stream filter API should allow:
stream = StreamLSL(...).connect()
stream.filter(1., 100., picks="eeg")
stream.filter(1., 15., picks="ecg")
stream.notch_filter(np.arange(50, 150, 50), picks="all")
In practice, we have:
The API should support:
MNE annotation offers a great way to visualize events, expected or not, that occurred during a paradigm.
A system to annotate in real-time on the recorder of a StreamViewer would be beneficial. Proposal: left click + hold initiate annotation and detect beginning on the timeline. Release detect ending on the timeline. The display should not freeze.
PsychoPy should be used for the LPT triggers: https://psychopy.org/api/parallel.html
LPT triggers should be re-organized around the keyword ParallelPort
to match PsychoPy.
from bsl.triggers import ParallelPortTrigger
trigger = ParallelPortTrigger(portaddr=None, arduino=True, delay=50)
# -> If Arduino is set to True, then use Arduino2LPT converter
# -> If Arduino is set to False, then portaddr must be provided with the address of the parallel port
from bsl.triggers import SoftwareTrigger
trigger = SoftwareTrigger(recorder)
from bsl.triggers import MockTrigger
trigger = MockTrigger()
Aside from clear installation notes; pylsl
and liblsl
could be bundled with BSL
.
New versions of both should be included as they are released.
Maybe in a module .externals
?
The packaging needs to be improved. For now, common versions of liblsl
are distributed in bsl.lsl.lib
, which does not feel optimal and does not comply with the requirement for a conda-forge
release.
Add simple and complex examples in folder examples
.
MNE has nicely build one-liner function to test type/value for arguments.
Bonus:
Now that all attributes are in the initialization, the StreamPlayer can be a context manager.
The StreamViewer API needs an overhaul. It will be rename as Viewer
to match the new Stream
and Player
API. The new Viewer
API will interface with one or more Stream
and will use methods from Stream
to edit the stream properties:
Moreover, the Viewer should be able to connect to multiple streams. Streams with a regular sampling rate should be displayed as channels (/!\ identical channel names between streams must be covered) while streams with an irregular sampling rate should be displayed as vertical lines.
For the filter, some thinking is required to compensate or ignore the causal delay introduced on one or all channels (and between a regular sampling rate stream and the vertical lines from an irregular one).
The backend should be pyqtgraph
with OpenGL for better display.
The StreamViewer backend is actually pyqtgraph
and not pyqt5
. To be renamed.
events
should be renamed into trigger_def
for consistency.
A short dataset with a test where the StreamPlayer would loop at least once would increase coverage.
A short dataset with a trigger channel and some events should be added to tests the logging of events from a StreamPlayer with a defined TriggerDef.
For high channel count, the plotting interface becomes too messy. The display could be split into 2 columns (or more), e.g. by using 2 plot handlers in the backend.
Idea: Each plot handler could display up to 64 channels (default) or a user-specified number of channels.
The StreamViewer will not work properly when:
The Arduino to LPT converter repository from FCBG is messy.
A complete tutorial on how to build one would be a nice addition to the documentation.
Proposed structure for triggers:
Add page placeholder for the arduino 2 lpt converter design.
Preparing future development of the stream viewer to integrate a real-time FFT viewer for a selection of channels, the right-click functionalities of the pyqtgraph backend should be disabled.
Add a workflow that runs the test suit on Apple ARM Silicon (M1 chips).
Maybe with https://cirrus-ci.org/?
The argument verbose
from the get_xxx
methods of the StreamReceiver
is useless.
The only use case, is for the ``StreamViewerto limit the spamming in the console when there are no new samples available on the network. A faster private method should be used by the
StreamViewer`.
The current vispy
backend for the StreamViewer is incomplete and implemented with the low-level gloo interface. The gloo interface is set to be deprecated in a couple of years. A backend designed around the higher-level vispy function should be implemented.
Move the path as a global variable; as the MD5 hash and the URL.
from pathlib import Path
from ._fetching import fetch_file, _hashfunc
from .. import logger
from ..utils.io._file_dir import make_dirs
MD5 = '8925f81af22390fd17bb3341d553430f'
URL = 'https://github.com/bsl-tools/bsl-datasets/raw/main/eeg/resting-state-sample-raw.fif'
def data_path():
"""
Return the path to the sample dataset.
If the dataset is not locally present, it is downloaded in the user home
directory in the folder bsl-datasets.
"""
path = Path('~/bsl_data/eeg/resting-state-sample-raw.fif').expanduser()
make_dirs(path.parent)
logger.debug('URL: %s' % (URL,))
logger.debug('Hash: %s' % (MD5,))
logger.debug('Path: %s' % (path,))
if path.exists() and _hashfunc(path) == MD5:
download = False
elif path.exists() and not _hashfunc(path) == MD5:
logger.warning(
'Dataset existing but with different hash. Re-downloading.')
download = True
else:
logger.info('Fetching dataset..')
download = True
if download:
fetch_file(URL, path, hash_=MD5, hash_type='md5', timeout=10.)
return path
Add the doc
directory with the configuration for sphinx.
Remove export function as this is now supported by MNE directly.
Add a test suite to test the code automatically.
Check the code coverage by the test suite.
LSL supports additional devices besides EEG amplifiers. c.f. here.
Each new device need:
Stream
class in bsl.stream_receiver._stream
Scope
class in bsl.stream_viewer.scope
bsl.stream_viewer.control_gui
Possible future additions:
Add method to turn stream player and stream recorder instance into possible context manager.
Remove testing utility function to create a stream and replace it directly with a call to a stream player.
my new issue
The LPT trigger have been tested:
pyparallel
and via Arduino.They need to be tested on Windows, both via Arduino (which should yield a COMx port, which was working in previous versions and should continue to work) and via LPT.
Fix the syntax for the logo to render it both on GitHub and on Pypi.
https://pypi.org/project/bsl/
pooch
is a library specialized in dataset fetching and should replace the current fetching code.
Add a representation method to the stream player and call it when it is started.
Failed Run
Workflow name - pylsl
Job - sha256
status - failure
Please visit https://github.com/labstreaminglayer/pylsl and review the changes.
Depending on OS/Python version, the python wheel for pylsl
might not ship with liblsl
..
In this case, it has to be downloaded manually from the release page and setup either in the correct directory or with the path provided in the correct environment variable.
Hello!
Hope all is well thanks for the library. Im attempting to do a pip install on python 3.10 and it keeps hanging on the getting meta process. Any ideas? I also tried pip install with verbose and it looks like theres a license agreement that needs to be accepted but after typing yes nothing happens
The StreamReceiver should not assumes information from the connected streams. The current API should be replaced with a Stream
API that enables to:
Support for marker stream using string
datatype should not be added. It is inherently slower than using string-to-number mapping. If a user wants to use string
, then it is still possible via the low-level bsl.lsl
API.
Depends on:
Currently, the trigger definition argument of the stream player supports a path to a compatible event file.
Support for an already initialized instance of trigger def should be added.
The StreamRecorder API was removed in favor of LabRecorder.
A Recorder
API should complement the Stream
, Player
and Viewer
API. The recorder API must be able to control a LabRecorder instance to record to XDF. Additionaly, other file formats could be supported, e.g. a real-time writing to a FIFF file, segment per segment.
The TextItem position of a trigger event is not properly displayed in the StreamViewer when the signal scale is changed. It is not fixed on the window and can even go out of the plotting window.
Modified trigger definition instance can not be saved for now.
Add a .save()
method to save the config to disk.
my new issue
The documentation build is not up-to-date. After the rework of the different API, the website needs to be improved:
Feature to add: return a mne raw instance instead of a numpy array with the get_window()
and get_buffer
methods of the StreamReceiver
. Add an argument to select between numpy array and mne raw.
Parallel port triggers are not covered by tests, not even locally.
The test will require a @require_pport
decorator to prevent execution on system which do not have an LPT port.
On CIs, it might be possible to create a virtual parallel port card.
This is not relevant at the moment since recorded files are exported to MNE .fif which does not take into account timestamps and assumes equally spaced samples in time, but it might be a nice feature in the future.
Software triggers should be added on dejitter timestamps.
Add a downloader similar to MNE to retrieve a sample dataset in a default location and update the examples with a stream player using a fif file from the dataset.
This method is not yet implemented:
The player should support both:
The API should be rework and concatenated in a single object.
Add real-time FFT capabilities to the stream viewer. The user should be able to select a (limited?) number of channels from which the spectral content will be displayed in an additional plot handler.
Layout is a duplicate of mne.Info.
make_dirs doesn't add much value to os.makedirs().
Just stumbled upon this repo, and this line caught my interest: "improved python-binding for the Lab Streaming Layer C++ library, bsl.lsl, replacing pylsl"
I am currently using pylsl to stream mostly some EEG and bodily signals data that I then record & save using the LabRecorder app.
And I was wondering if I should consider swapping pylsl in favour bsl? Any details on the existing/planned improvements or features?
Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.