Skip to content

About

A standalone service that reads EEG from any LSL (Lab Streaming Layer) stream, runs a full processing pipeline, and publishes the user's attention and relaxation levels in real time. Any app or game can consume these values, in any language or engine.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

neurostate

A standalone service that reads EEG from any LSL (Lab Streaming Layer) stream and publishes the user's attention and relaxation levels in real time. See Plan.md for the design and milestones.

Status: neurostate run reads EEG from an LSL stream, cleans it and publishes attention and relaxation levels, scaled against a resting baseline it measures at startup. A proper calibration (milestone M5) and blink handling (M7) aren't built yet. neurostate run --fake publishes made-up values, for building apps without a cap.

Setup

You need uv. It installs Python 3.12 if you don't have it.

uv sync --all-extras

--all-extras adds the gui extra (pyqtgraph and Qt, about 250 MB), which only neurostate check needs. Leave it out on machines that just run the service.

Usage

uv run neurostate --help
uv run neurostate mock                          # fake 32-channel EEG on LSL, until Ctrl+C
uv run neurostate mock --alpha 30 --blinks 15   # strong alpha, 15 blinks per minute
uv run neurostate mock --channels Fp1,Fp2,O1,O2 --line-noise 5
uv run neurostate mock --drops 20               # lose a chunk of samples 20 times a minute
uv run neurostate --config my.yaml mock         # settings from a config file

Publishing values to apps

uv run neurostate run --montage brainaccess-midi   # from the EEG stream
uv run neurostate run --fake              # made-up values: slow waves in attention and relaxation
uv run neurostate run --fake --dropouts   # each minute ends with poor signal, then no signal

With a BrainAccess headset, first connect it in BrainAccess Board with LSL streaming on. For the first minute of good signal, sit still with your eyes open: neurostate measures your resting baseline meanwhile, and reports the state calibrating. After that, attention and relaxation say how far you are from that resting state, with 50 meaning no change. To watch the values, run uv run python examples/python/tcp_client.py in another terminal.

Every 250 ms, neurostate takes the last 2 s of EEG, leaves out flat, noisy and mains-polluted channels, filters and re-references the rest to their average, and skips the window if it goes beyond ±100 µV. Attention comes from beta / (alpha + theta) and frontal theta / parietal alpha; relaxation from the share of alpha, and alpha / beta, over the back of the head.

Apps can receive the values over LSL, JSON over TCP or WebSocket, or the ThinkGear protocol that NeuroSky MindWave apps use, all at once. docs/outputs.md describes the values and each output; examples/ has working clients in Python, C# (including Unity) and JavaScript.

Checking the signal

uv run neurostate check                         # first LSL stream of type EEG
uv run neurostate check --stream MockEEG        # a stream by name
uv run neurostate check --montage my-cap.yaml   # a montage other than standard 10-20

check first prints what the stream reports about itself: name, sampling rate, channel labels, units, which channels it ignores (for example an accelerometer) and which channels cover each brain region. It then opens a live view:

  • Signals, filtered, coloured by channel status: grey for flat, red for noisy, orange for mains hum.
  • Status line: how many good channels each region (frontal, parietal, occipital) has, the received sampling rate, and gaps in the stream.
  • Spectrum over the back of the head (O1, Oz, O2). The alpha peak at 8–13 Hz should grow clearly when you close your eyes.

When you close the window (or press Ctrl+C), it prints how many samples arrived and how many were lost.

Config and montages

config/default.yaml lists every setting with its default. Your own config file only needs the keys it changes.

A montage says which of a cap's channels are EEG and which brain region each one covers. The built-in ones are in src/neurostate/montages/: standard-1020 works for any cap with standard 10-20 labels, and brainaccess-midi for the 16-channel BrainAccess MIDI as BrainAccess Board streams it. You can also pass a path to your own montage file.

The mock stream is a regular LSL stream of type EEG, so any LSL tool (LabRecorder, mne-lsl's viewer, etc.) can see it.

Development

uv run pytest
uv run ruff check
uv run ruff format

CI runs the same checks on Linux and Windows for every push to main and every pull request.

About

A standalone service that reads EEG from any LSL (Lab Streaming Layer) stream, runs a full processing pipeline, and publishes the user's attention and relaxation levels in real time. Any app or game can consume these values, in any language or engine.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages