> Developed by [Yeison Nolberto Cardona Álvarez](https://github.com/yeisonCardona)
> [Andrés Marino Álvarez Meza, PhD.](https://github.com/amalvarezme)
> César Germán Castellanos Dominguez, PhD.
> _Digital Signal Processing and Control Group_ | _Grupo de Control y Procesamiento Digital de Señales ([GCPDS](https://github.com/UN-GCPDS/))_
> _Universidad Nacional de Colombia sede Manizales_
----
# OpenBCI-Stream
High level Python module for EEG/EMG/ECG acquisition and distributed streaming for OpenBCI Cyton board.
![GitHub top language](https://img.shields.io/github/languages/top/un-gcpds/openbci-stream?)
![PyPI - License](https://img.shields.io/pypi/l/openbci-stream?)
![PyPI](https://img.shields.io/pypi/v/openbci-stream?)
![PyPI - Status](https://img.shields.io/pypi/status/openbci-stream?)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/openbci-stream?)
![GitHub last commit](https://img.shields.io/github/last-commit/un-gcpds/openbci-stream?)
![CodeFactor Grade](https://img.shields.io/codefactor/grade/github/UN-GCPDS/openbci-stream?)
[![Documentation Status](https://readthedocs.org/projects/openbci-stream/badge/?version=latest)](https://openbci-stream.readthedocs.io/en/latest/?badge=latest)
Comprise a set of scripts that deals with the configuration and connection with the board, also is compatible with both connection modes supported by [Cyton](https://shop.openbci.com/products/cyton-biosensing-board-8-channel?variant=38958638542): RFduino (Serial dongle) and Wi-Fi (with the OpenBCI Wi-Fi Shield). These drivers are a stand-alone library that can handle the board from three different endpoints: (i) a [Command-Line Interface](06-command_line_interface.ipynb) (CLI) with simple instructions configure, start and stop data acquisition, debug stream status, and register events markers; (ii) a [Python Module](03-data_acuisition.ipynb) with high-level instructions and asynchronous acquisition; (iii) an object-proxying using Remote Python Call (RPyC) for [distributed implementations](A4-server-based-acquisition.ipynb) that can manipulate the Python modules as if they were local, this last mode needs a daemon running in the remote host that will listen to connections and driving instructions.
The main functionality of the drivers live on to serve real-time and distributed access to data flow, even on single machine implementations, this is achieved by implementing [Kafka](https://kafka.apache.org/) and their capabilities to create multiple topics for classifying the streaming, these topics are used to separate the neurophysiological data from the [event markers](05-stream_markers), so the clients can subscribe to a specific topic for injecting or read content, this means that is possible to implement an event register in a separate process that stream markers for all clients in real-time without handle dense time-series data. A crucial issue that stays on [time synchronization](A4-server-based_acquisition.ipynb#Step-5---Configure-time-server), all systems components in the network should have the same real-time protocol (RTP) server reference.
## Main features
* **Asynchronous acquisition:** Acquisition and deserialization are done in uninterrupted parallel processes. In this way, the sampling rate keeps stable as long as possible.
* **Distributed streaming system:** The acquisition, processing, visualizations, and any other system that needs to be fed with EEG/EMG/ECG real-time data can run with their architecture.
* **Remote board handle:** Same code syntax for developing and debug Cython boards connected to any node in the distributed system.
* **Command-line interface:** A simple interface for handle the start, stop, and access to data stream directly from the command line.
* **Markers/Events handler:** Besides the marker boardmode available in Cyton, a stream channel for the reading and writing of markers is available for use in any development.
* **Multiple boards:** Is possible to use multiple OpenBCI boards just by adding multiple endpoints to the commands.
## Examples
```python
# Acquisition with blocking call
from openbci_stream.acquisition import Cyton
openbci = Cyton('serial', endpoint='/dev/ttyUSB0', capture_stream=True)
# blocking call
openbci.stream(15) # collect data for 15 seconds
# openbci.eeg_time_series
# openbci.aux_time_series
# openbci.timestamp_time_series
```
```python
# Acquisition with asynchronous call
from openbci_stream.acquisition import Cyton
openbci = Cyton('wifi', endpoint='192.68.1.113', capture_stream=True)
openbci.stream(15) # collect data for 15 seconds
# asynchronous call
openbci.start_stream()
time.sleep(15) # collect data for 15 seconds
openbci.stop_stream()
```
```python
# Remote acquisition
from openbci_stream.acquisition import Cyton
openbci = Cyton('serial', endpoint='/dev/ttyUSB0', host='192.168.1.1', capture_stream=True)
# blocking call
openbci.stream(15) # collect data for 15 seconds
```
```python
# Consumer for active streamming
from openbci_stream.acquisition import OpenBCIConsumer
with OpenBCIConsumer() as stream:
for i, message in enumerate(stream):
if message.topic == 'eeg':
print(f"received {message.value['samples']} samples")
if i == 9:
break
```
```python
# Create stream then consume data
from openbci_stream.acquisition import OpenBCIConsumer
with OpenBCIConsumer(mode='serial', endpoint='/dev/ttyUSB0', streaming_package_size=250) as (stream, openbci):
t0 = time.time()
for i, message in enumerate(stream):
if message.topic == 'eeg':
print(f"{i}: received {message.value['samples']} samples")
t0 = time.time()
if i == 9:
break
```
```python
# Acquisition with multiple boards
from openbci_stream.acquisition import Cyton
openbci = Cyton('wifi', endpoint=['192.68.1.113', '192.68.1.185'], capture_stream=True)
openbci.stream(15) # collect data for 15 seconds
# asynchronous call
openbci.start_stream()
time.sleep(15) # collect data for 15 seconds
openbci.stop_stream()
```
Raw data
{
"_id": null,
"home_page": "",
"name": "openbci-stream",
"maintainer": "Yeison Cardona",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "yencardonaal@unal.edu.co",
"keywords": "",
"author": "Yeison Cardona",
"author_email": "yencardonaal@unal.edu.co",
"download_url": "https://files.pythonhosted.org/packages/55/0e/1f0145af38123c415ab00a4c681b69533679002a3d0668c6681d66339250/openbci-stream-1.1.0.tar.gz",
"platform": null,
"description": "> Developed by [Yeison Nolberto Cardona \u00c1lvarez](https://github.com/yeisonCardona) \n> [Andr\u00e9s Marino \u00c1lvarez Meza, PhD.](https://github.com/amalvarezme) \n> C\u00e9sar Germ\u00e1n Castellanos Dominguez, PhD. \n> _Digital Signal Processing and Control Group_ | _Grupo de Control y Procesamiento Digital de Se\u00f1ales ([GCPDS](https://github.com/UN-GCPDS/))_ \n> _Universidad Nacional de Colombia sede Manizales_\n\n----\n\n# OpenBCI-Stream \nHigh level Python module for EEG/EMG/ECG acquisition and distributed streaming for OpenBCI Cyton board.\n\n![GitHub top language](https://img.shields.io/github/languages/top/un-gcpds/openbci-stream?)\n![PyPI - License](https://img.shields.io/pypi/l/openbci-stream?)\n![PyPI](https://img.shields.io/pypi/v/openbci-stream?)\n![PyPI - Status](https://img.shields.io/pypi/status/openbci-stream?)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/openbci-stream?)\n![GitHub last commit](https://img.shields.io/github/last-commit/un-gcpds/openbci-stream?)\n![CodeFactor Grade](https://img.shields.io/codefactor/grade/github/UN-GCPDS/openbci-stream?)\n[![Documentation Status](https://readthedocs.org/projects/openbci-stream/badge/?version=latest)](https://openbci-stream.readthedocs.io/en/latest/?badge=latest)\n\nComprise a set of scripts that deals with the configuration and connection with the board, also is compatible with both connection modes supported by [Cyton](https://shop.openbci.com/products/cyton-biosensing-board-8-channel?variant=38958638542): RFduino (Serial dongle) and Wi-Fi (with the OpenBCI Wi-Fi Shield). These drivers are a stand-alone library that can handle the board from three different endpoints: (i) a [Command-Line Interface](06-command_line_interface.ipynb) (CLI) with simple instructions configure, start and stop data acquisition, debug stream status, and register events markers; (ii) a [Python Module](03-data_acuisition.ipynb) with high-level instructions and asynchronous acquisition; (iii) an object-proxying using Remote Python Call (RPyC) for [distributed implementations](A4-server-based-acquisition.ipynb) that can manipulate the Python modules as if they were local, this last mode needs a daemon running in the remote host that will listen to connections and driving instructions.\n\nThe main functionality of the drivers live on to serve real-time and distributed access to data flow, even on single machine implementations, this is achieved by implementing [Kafka](https://kafka.apache.org/) and their capabilities to create multiple topics for classifying the streaming, these topics are used to separate the neurophysiological data from the [event markers](05-stream_markers), so the clients can subscribe to a specific topic for injecting or read content, this means that is possible to implement an event register in a separate process that stream markers for all clients in real-time without handle dense time-series data. A crucial issue that stays on [time synchronization](A4-server-based_acquisition.ipynb#Step-5---Configure-time-server), all systems components in the network should have the same real-time protocol (RTP) server reference. \n\n## Main features\n\n * **Asynchronous acquisition:** Acquisition and deserialization are done in uninterrupted parallel processes. In this way, the sampling rate keeps stable as long as possible.\n * **Distributed streaming system:** The acquisition, processing, visualizations, and any other system that needs to be fed with EEG/EMG/ECG real-time data can run with their architecture.\n * **Remote board handle:** Same code syntax for developing and debug Cython boards connected to any node in the distributed system.\n * **Command-line interface:** A simple interface for handle the start, stop, and access to data stream directly from the command line.\n * **Markers/Events handler:** Besides the marker boardmode available in Cyton, a stream channel for the reading and writing of markers is available for use in any development. \n * **Multiple boards:** Is possible to use multiple OpenBCI boards just by adding multiple endpoints to the commands.\n\n## Examples\n\n\n```python\n# Acquisition with blocking call\n\nfrom openbci_stream.acquisition import Cyton\nopenbci = Cyton('serial', endpoint='/dev/ttyUSB0', capture_stream=True)\n\n# blocking call\nopenbci.stream(15) # collect data for 15 seconds\n\n# openbci.eeg_time_series \n# openbci.aux_time_series\n# openbci.timestamp_time_series \n```\n\n\n```python\n# Acquisition with asynchronous call\n\nfrom openbci_stream.acquisition import Cyton\nopenbci = Cyton('wifi', endpoint='192.68.1.113', capture_stream=True)\nopenbci.stream(15) # collect data for 15 seconds\n\n# asynchronous call\nopenbci.start_stream()\ntime.sleep(15) # collect data for 15 seconds\nopenbci.stop_stream()\n```\n\n\n```python\n# Remote acquisition\n\nfrom openbci_stream.acquisition import Cyton\nopenbci = Cyton('serial', endpoint='/dev/ttyUSB0', host='192.168.1.1', capture_stream=True)\n\n# blocking call\nopenbci.stream(15) # collect data for 15 seconds\n```\n\n\n```python\n# Consumer for active streamming\n\nfrom openbci_stream.acquisition import OpenBCIConsumer\nwith OpenBCIConsumer() as stream:\n for i, message in enumerate(stream):\n if message.topic == 'eeg':\n print(f\"received {message.value['samples']} samples\")\n if i == 9:\n break\n```\n\n\n```python\n# Create stream then consume data\n\nfrom openbci_stream.acquisition import OpenBCIConsumer\nwith OpenBCIConsumer(mode='serial', endpoint='/dev/ttyUSB0', streaming_package_size=250) as (stream, openbci):\n t0 = time.time()\n for i, message in enumerate(stream):\n if message.topic == 'eeg':\n print(f\"{i}: received {message.value['samples']} samples\")\n t0 = time.time()\n if i == 9:\n break\n```\n\n\n```python\n# Acquisition with multiple boards\n\nfrom openbci_stream.acquisition import Cyton\nopenbci = Cyton('wifi', endpoint=['192.68.1.113', '192.68.1.185'], capture_stream=True)\nopenbci.stream(15) # collect data for 15 seconds\n\n# asynchronous call\nopenbci.start_stream()\ntime.sleep(15) # collect data for 15 seconds\nopenbci.stop_stream()\n```\n",
"bugtrack_url": null,
"license": "BSD-2-Clause",
"summary": "High level Python module for EEG/EMG/ECG acquisition and distributed streaming for OpenBCI Cyton board.",
"version": "1.1.0",
"project_urls": {
"Download": "https://github.com/UN-GCPDS/openbci_stream"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "4281691cb1dc982cf220e77a69fd89a5059e51eff0333a92336a03f4eb06548a",
"md5": "2a3583fa60654a2ad04c3282fc146098",
"sha256": "05dfd6c23480e6b0ad674768f375e32a0218e29d2a2b71ac69f219dab78fe6c4"
},
"downloads": -1,
"filename": "openbci_stream-1.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "2a3583fa60654a2ad04c3282fc146098",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 58181,
"upload_time": "2023-06-08T22:17:21",
"upload_time_iso_8601": "2023-06-08T22:17:21.162514Z",
"url": "https://files.pythonhosted.org/packages/42/81/691cb1dc982cf220e77a69fd89a5059e51eff0333a92336a03f4eb06548a/openbci_stream-1.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "550e1f0145af38123c415ab00a4c681b69533679002a3d0668c6681d66339250",
"md5": "d520da55e6b0ad0777632363d52d428a",
"sha256": "d4bf9f20489d06df3b914638ab5e83e9174a2b410035f884fc25b440d5eaf967"
},
"downloads": -1,
"filename": "openbci-stream-1.1.0.tar.gz",
"has_sig": false,
"md5_digest": "d520da55e6b0ad0777632363d52d428a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 50237,
"upload_time": "2023-06-08T22:17:23",
"upload_time_iso_8601": "2023-06-08T22:17:23.626453Z",
"url": "https://files.pythonhosted.org/packages/55/0e/1f0145af38123c415ab00a4c681b69533679002a3d0668c6681d66339250/openbci-stream-1.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-06-08 22:17:23",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "UN-GCPDS",
"github_project": "openbci_stream",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "rpyc",
"specs": []
},
{
"name": "colorama",
"specs": []
},
{
"name": "ntplib",
"specs": []
},
{
"name": "requests",
"specs": []
},
{
"name": "numpy",
"specs": []
},
{
"name": "netifaces",
"specs": []
},
{
"name": "rawutil",
"specs": []
},
{
"name": "kafka_python",
"specs": []
},
{
"name": "tables",
"specs": []
},
{
"name": "scipy",
"specs": []
},
{
"name": "mne",
"specs": []
},
{
"name": "nmap",
"specs": []
},
{
"name": "pyserial",
"specs": []
}
],
"lcname": "openbci-stream"
}