Skip to main content

signalino

signalino is the high-level Python API for Signalino 4 EEG devices. It wraps the Signalino board implemented in BrainFlow and adds a non-destructive sample buffer, typed battery and impedance results, Lab Streaming Layer publishing, and conversion to MNE-Python.

This is research software. It is not a medical device and must not be used for diagnosis or patient monitoring.

Installation

Linux x86_64 (Intel/AMD 64-bit)

Python 3.10+ and glibc 2.35+ are required for the current Linux wheels.

python -m pip install --upgrade signalino

Starting with 0.1.2, this installs brainflow-signalino automatically. It contains the compiled Signalino driver and uses the brainflow_signalino Python module, so it can coexist with official brainflow without overwriting files. No compiler, CMake or private repository access is required. ARM/Raspberry Pi, Alpine/musl and older glibc are not covered by these wheels. USB/RFCOMM permissions and Bluetooth adapter setup remain host OS requirements.

macOS Apple Silicon

Starting with 0.1.3, the same command installs a precompiled ARM64 backend on Apple Silicon Macs running macOS 12 or later:

python -m pip install --upgrade signalino

It supports USB/serial, paired Bluetooth Classic serial ports and BLE through CoreBluetooth. Like the Linux package, it uses the isolated brainflow_signalino module and can coexist with official brainflow.

Windows and Intel Mac

Precompiled brainflow-signalino wheels are not available for these platforms in this release. Keep using the existing Signalino-enabled BrainFlow build from JABarios/brainflow-signalino. The wrapper uses the existing brainflow module on these platforms. Official BrainFlow alone does not yet include board 69; a matching native build is needed.

Optional integrations and examples

python -m pip install 'signalino[viewer]'
python -m pip install 'signalino[lsl]'
python -m pip install 'signalino[mne]'

Examples live in this repository's examples/ directory and are not included in the installed wheel. examples/check_import.py does not connect hardware.

For development, install .[dev,all] and run pytest.

USB

import time

from signalino import Signalino

with Signalino.usb() as device:  # Automatically chooses the most probable port
    device.start_streaming()
    time.sleep(2)
    eeg_uv = device.get_data()

print(eeg_uv.shape)  # (8, approximately 500)

Use COM3-style names on Windows and /dev/ttyACM0-style names on Linux. Pass one explicitly as Signalino.usb("/dev/cu.usbmodem1101") when needed. Discovery only examines port names and USB descriptors; it does not open ports. Use find_usb_ports() to display every probable candidate. If two devices are equally likely, automatic selection refuses to guess.

Bluetooth LE

from signalino import Signalino

device = Signalino.ble("Signalino-852960")
device.connect()
device.start_streaming()

When only one Signalino is advertising, Signalino.ble() lets BrainFlow choose it automatically. Provide the advertised name whenever multiple devices may be present.

Bluetooth Classic

Signalino devices fitted with an HC-06 appear as a serial port after pairing. The example can locate a probable paired port automatically:

python examples/basic_classic_bluetooth.py

The example automatically selects a probable Signalino port. Pass the port as an argument if several paired devices are plausible. On Linux the port is commonly /dev/rfcomm0; on Windows it is a COM port. On macOS the example uses the RFCOMM bridge bundled with Signalino Suite.

Measure the effective rate and detect packet-counter gaps over 30 seconds:

python examples/measure_classic_bluetooth.py

Live viewer

Install the viewer extra and open the eight-channel rolling display:

python -m pip install "matplotlib>=3.9,<4"
python examples/live_viewer.py

Bluetooth Classic is selected by default. Use --transport usb or --transport ble for the other connections. Press Space to pause the display without stopping acquisition, and press Q or Escape to close it.

Data

get_data() returns a NumPy array in microvolts with shape (channels, samples). Data is consumed oldest first by default:

latest_copy = device.get_data(250, clear=False)
oldest_consumed = device.get_data(250)

For timestamps, use get_data_batch():

batch = device.get_data_batch()
print(batch.samples_uv.shape)
print(batch.timestamps)

The package continuously drains BrainFlow into its own bounded buffer. LSL and get_data() therefore receive the same samples without stealing data from one another.

Public API

The stable top-level API is:

Signalino.usb(...) / Signalino.ble(...)
find_usb_port() / find_usb_ports()
connect() / disconnect()
start_streaming() / stop_streaming()
get_data() / get_data_batch() / clear_data()
device.info / get_auxiliary_data() / clear_auxiliary_data()
battery() / impedance()
start_lsl() / stop_lsl()
to_mne()

Public result types and exceptions are importable directly from signalino. Implementation modules whose names begin with an underscore are private.

Hardware and sensors

Every compatible controller uses the same Signalino/BrainFlow board and EEG API. Sensor inventory is read from the physical unit at connection time:

from signalino import Capability, Sensor

with Signalino.usb() as device:
    print(device.info.hardware, device.info.firmware)
    print(device.info.sensors, device.info.sensor_source)
    if Capability.SD_CARD in device.info.capabilities:
        print("microSD supported")
    if Sensor.ACCELEROMETER in device.info.sensors:
        print("accelerometer available")

Sensor packets have their own buffer and never consume EEG data:

from signalino import AuxiliaryPacketType

device.start_streaming()
auxiliary = device.get_auxiliary_data(clear=False)
acceleration = auxiliary.select(AuxiliaryPacketType.ACCELEROMETER)
print(acceleration.raw_values, acceleration.timestamps)

raw_values contains the three signed AUX words from the original 33-byte frame. packet_types preserves byte 32: 0xC0 accelerometer, 0xC1 gyroscope, 0xC2 environment, and 0xCF no auxiliary sensor data. Physical unit conversion remains explicit because calibration can vary between sensor assemblies.

Run python examples/hardware_and_sensors.py for a complete probe of the connected unit.

Battery

status = device.battery()
print(status.volts, status.percent, status.charging)

With the current USB BrainFlow bridge, battery replies cannot be collected while binary EEG is streaming. Stop USB streaming before refreshing the value. BLE uses a separate control characteristic and can refresh battery state while EEG is active.

Impedance

reading = device.impedance()
print(reading.kiloohms)

The ADS1299 cannot emit normal EEG while measuring impedance. If streaming is active, impedance() pauses EEG, takes one reading, exits impedance mode, and restores both EEG acquisition and the previous LSL outlet. This produces a short, timestamp-visible gap by design.

LSL

device.start_streaming()
stream = device.start_lsl()
print(stream.name, stream.source_id)

The outlet contains eight float32 EEG channels in microvolts. It is closed automatically before acquisition stops, so Signalino never leaves an advertised but empty LSL stream behind.

MNE

raw = device.to_mne(clear=False)
print(raw.info["sfreq"])

MNE stores EEG in volts; conversion from Signalino's microvolts is automatic. Pass an MNE montage with device.to_mne(montage=montage) when channel names have been assigned to physical electrode positions.

Development and release checks

ruff check .
ruff format --check .
pytest --cov=signalino
python -m build
python -m twine check dist/*

Building creates an sdist and a platform-independent wrapper wheel. The native backend is distributed separately as a platform wheel. Publishing is deliberately not part of the local build process.

License

MIT

Release files for signalino 0.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for signalino 0.1.4
File Size Uploaded
signalino-0.1.4.tar.gz 29.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for signalino 0.1.4
File Interpreter ABI Platform
signalino-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size:49.3 kB

Release files / signalino-0.1.4.tar.gz

Download URL signalino-0.1.4.tar.gz
Size 29.6 kB
Tags Source
SHA-256 checksum
How to use checksums
e7f2cec48727eb1e202dd28d53ea64f4b23753789549c8046d71e596582ae579
BLAKE2b-256 checksum
How to use checksums
9c82d408a4147ceaf41425f0c15d1f0891560e3d1fe247ac93c0d3d5f1e2aa70
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.12

Release files / signalino-0.1.4-py3-none-any.whl

Download URL signalino-0.1.4-py3-none-any.whl
Size 19.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2b2c5c8e32f3822529097f3cdc7f45925a7711ca58765b75daea3c33a3b54fd1
BLAKE2b-256 checksum
How to use checksums
0536ad4ce94f098e5e50147e7de606b36203bb1719a4d9d544f5c918c915553e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.12

Release history Release notifications | RSS feed

0.2.1

2 release files

0.2.0

2 release files

This release

0.1.4 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page