The Open Python Muse S Athena EEG Decoder
This software allows recording, streaming via LSL and visualizing signals from the Muse S Athena headband.
Warning
OpenMuse is NOT an official product of InteraXon Inc and is not affiliated with or endorsed by the company. It does not come with any warranty and should be considered an experimental software developed for research purposes only.
- Record raw data to a file
- Decode raw data into a pandas DataFrame
- Stream data over LSL
- Visualise live LSL streams
- Stream in battery signal and display battery level in visualizer
- Validate timestamping accuracy experimentally: confirm we get time-locked ERPs
- Validate the best PPG signal extraction method
- Validate fNIRS signal extraction method
Create a virtual environment
python3 -m venv .venv
source .venv/bin/activate # on MacOS or Linux
.venv\Scripts\activate # on WindowsFor users: Install from GitHub by opening a terminal and running:
pip install https://github.com/DominiqueMakowski/OpenMuse/zipball/mainFor contributors: If you want to make changes
git clone https://github.com/DominiqueMakowski/OpenMuse.git
cd OpenMuse
python3 -m venv .venv
source .venv/bin/activate # on MacOS or Linux
.venv\Scripts\activate # on Windows
pip install -e .After installing the package, open a terminal and use the following commands:
Power up the Muse S Athena headband (a blue light should appear on the front) and run:
OpenMuse findThis will print the MAC addresses of nearby Muse devices. Note the address of your device for the next steps.
OpenMuse record --address <your-muse-address> --duration 60 --outfile data.txtAlternatively, omit --address to autodiscover a single nearby device:
OpenMuse record --duration 60 --outfile data.txtIf multiple devices are found (or none), you'll be asked to specify --address.
Tip
By default, recording and streaming use the --preset p1041, which enables all channels. You can change the preset using the --preset argument (see below for the list of documented presets).
Once your file is recorded, you can load it in Python using:
import pandas as pd
import OpenMuse
with open("data.txt", "r", encoding="utf-8") as f:
messages = f.readlines()
data = OpenMuse.decode_rawdata(messages)
# Plot Movement Data
data["ACCGYRO"].plot(
x="time",
y=["ACC_X", "ACC_Y", "ACC_Z", "GYRO_X", "GYRO_Y", "GYRO_Z"],
subplots=True
)Note
OpenMuse uses MNE-LSL, an improved python-binding for the Lab Streaming Layer C++ library, mne_lsl.lsl, replacing pylsl.
To stream data over LSL, use:
OpenMuse stream --address <your-muse-address>This creates separate LSL streams for groups of channels (Muse_EEG, Muse_ACCGYRO, etc.).
The following options are available:
--address: The MAC address of your Muse device (required)--duration: Duration of the recording in seconds (if not specified, streaming will continue until you press Ctrl+C in the terminal)--preset: Preset configuration (default:p1041for all channels)--outfile: Optional JSON file to save the streamed data
To visualize live LSL streams, open a new terminal (while the streaming is running) and run:
OpenMuse viewMuse S Athena specs (From the Muse website):
- Wireless Connection: BLE 5.3, 2.4 GHz
- EEG Channels: 4 EEG channels (TP9, AF7, AF8, TP10) + 4 amplified Aux channels
- Sample Rate: 256 Hz
- Sample Resolution: 14 bits / sample
- Accelerometer: Three-axis at 52Hz, 16-bit resolution, range +/- 2G
- Gyroscope: Three-axis at 52Hz, 16-bit resolution, range +/- 250dps
- PPG Sensor: Triple wavelength: IR (850nm), Near-IR (730nm), Red (660nm), 64 Hz sample rate, 20-bit resolution
- fNIRS Sensor: 5-optode bilateral frontal cortex hemodynamics, 64 Hz sample rate, 20-bit resolution
| Presets | EEG | Optics | ACC/GYRO | Battery | Red LED |
|---|---|---|---|---|---|
| p20, p21, p50, p51, p60, p61 | EEG4 | — | X | X | off |
| p1034, p1043 | EEG8 | Optics8 | X | X | bright |
| p1044 | EEG8 | Optics8 | X | X | dim |
| p1035 | EEG4 | Optics4 | X | X | dim |
| p1041, p1042 | EEG8 | Optics16 | X | X | bright |
| p1045 | EEG8 | Optics4 | X | X | dim |
| p1046 | EEG8 | Optics4 | X | X | — |
| p4129 | EEG8 | Optics4 | X | X | dim |
Table derived from the signature of the data packets present in the data. More presets could exist.
This project would not have been possible without the breakthroughs of amused-Py that identified the communication protocol and AbosaSzakal's parser who documented the data structure.