Metadata-Version: 2.5
Name: signalino
Version: 0.2.0
Summary: Native Python API for Signalino EEG devices
Project-URL: Homepage, https://github.com/JABarios/signalino-python
Project-URL: Repository, https://github.com/JABarios/signalino-python
Project-URL: Issues, https://github.com/JABarios/signalino-python/issues
Author: Scignals
License-Expression: MIT
License-File: LICENSE
Keywords: BCI,Bluetooth,EEG,LSL,MNE,Signalino
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Healthcare Industry
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.10
Requires-Dist: bleak<2,>=0.22
Requires-Dist: numpy>=1.26
Requires-Dist: pyserial<4,>=3.5
Provides-Extra: all
Requires-Dist: matplotlib<4,>=3.9; extra == 'all'
Requires-Dist: mne<2,>=1.12; extra == 'all'
Requires-Dist: pylsl<2,>=1.18.2; extra == 'all'
Provides-Extra: dev
Requires-Dist: build<2,>=1.3; extra == 'dev'
Requires-Dist: pytest-cov<8,>=6; extra == 'dev'
Requires-Dist: pytest<10,>=8.4; extra == 'dev'
Requires-Dist: ruff<1,>=0.12; extra == 'dev'
Requires-Dist: twine<8,>=7; extra == 'dev'
Provides-Extra: lsl
Requires-Dist: pylsl<2,>=1.18.2; extra == 'lsl'
Provides-Extra: mne
Requires-Dist: mne<2,>=1.12; extra == 'mne'
Provides-Extra: viewer
Requires-Dist: matplotlib<4,>=3.9; extra == 'viewer'
Description-Content-Type: text/markdown

# signalino

Native Python API for Signalino EEG devices. It connects directly over USB,
Bluetooth Classic or Bluetooth LE and decodes the Signalino S4CP control
protocol and stable 33-byte OpenBCI-compatible EEG frames.

This package does not depend on BrainFlow. Applications that specifically need
the BrainFlow API can install the separate `brainflow-signalino` integration.

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

## Installation

```bash
python -m pip install signalino
```

Python 3.10 or newer is supported on macOS, Linux and Windows. Optional
integrations are installed separately:

```bash
python -m pip install "signalino[lsl]"
python -m pip install "signalino[mne]"
python -m pip install "signalino[viewer]"
```

## USB

```python
import time

from signalino import Signalino

with Signalino.usb() as device:
    print(device.info.name, device.info.hardware)
    device.start_streaming()
    time.sleep(2)
    eeg_uv = device.get_data()

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

`Signalino.usb()` chooses the most probable port. Select it explicitly when
several boards are connected:

```python
device = Signalino.usb("/dev/cu.usbmodem1101")  # macOS
device = Signalino.usb("/dev/ttyACM0")  # Linux
device = Signalino.usb("COM3")  # Windows
```

## Bluetooth Classic

Pair the HC-06 (or equivalent serial Bluetooth module) with the computer first:

```python
with Signalino.bluetooth_classic() as device:
    device.start_streaming()
```

The package finds likely paired serial ports automatically. An explicit port
can also be passed to `Signalino.bluetooth_classic(port)`.

On macOS, Classic Bluetooth uses the native RFCOMM helper installed with
Signalino Suite. Its location can instead be supplied through the
`SIGNALINO_CLASSIC_CONNECT` environment variable. Linux normally exposes
`/dev/rfcomm0`; Windows exposes a paired `COM` port.

## Bluetooth LE

```python
with Signalino.ble("Signalino-852960") as device:
    device.start_streaming()
```

Use `Signalino.ble()` when only one Signalino is advertising. With several
units in the room, select one by advertised name or address:

```python
Signalino.ble(name="Signalino-852960")
Signalino.ble(address="AA:BB:CC:12:34:56")
```

## Data and losses

`get_data()` returns microvolts as a NumPy array shaped `(channels, samples)`.
It consumes the oldest samples by default. Use `clear=False` to inspect without
consuming:

```python
latest = device.get_data(250, clear=False)
batch = device.get_data_batch()
print(batch.samples_uv, batch.timestamps)

print(device.stats.received_samples)
print(device.stats.lost_samples)
print(device.stats.loss_percent)
```

The package validates frame headers and footers, recovers alignment after
corrupt input, and uses the 8-bit sample counter to detect losses and
duplicates. Buffers are bounded and LSL does not consume data requested by
`get_data()`.

## Battery, impedance and sensors

```python
battery = device.battery()
print(battery.volts, battery.percent, battery.charging)

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

auxiliary = device.get_auxiliary_data()
print(auxiliary.raw_values, auxiliary.packet_types)
```

Normal EEG acquisition pauses while impedances are measured and resumes
automatically afterward. USB and Bluetooth Classic share control and binary
data on one serial channel, so battery queries on those transports also require
streaming to be stopped. BLE has separate control and EEG characteristics.

Hardware, firmware, available sensors and capabilities are reported by the
physical unit through `device.info`; they are not inferred from a board number.

## S4CP control

High-level operations use S4CP internally. Documented low-level commands remain
available for diagnostics:

```python
print(device.command("STS;"))
device.command("SRC1;SMP250;GAN24;")
```

Control replies are compact strings such as `STS SRC=1 REC=0 SMP=250 ...;`.
The EEG data plane remains the 33-byte OpenBCI-compatible frame.

## LSL

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

The LSL outlet contains eight `float32` EEG channels in microvolts and closes
automatically when acquisition stops.

## MNE

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

MNE stores EEG in volts; conversion from Signalino microvolts is automatic.

## Examples

The `examples/` directory contains minimal USB, BLE and Bluetooth Classic
programs, an LSL publisher, impedance acquisition, MNE conversion, a rolling
viewer, and a Classic Bluetooth loss measurement.

For local development:

```bash
python -m pip install -e ".[dev,all]"
ruff check .
ruff format --check .
pytest --cov=signalino
python -m build
twine check dist/*
```

## License

MIT. Copyright Scignals 2026.
