Python library to communicate with STM32 for loading FPGA and camera sensors (OpenMOTION).
Project description
openmotion-sdk
Host-side Python SDK for Open-Motion — Openwater's optical speckle imaging
system for non-invasive blood-flow monitoring. The package omotion (PyPI:
openmotion-sdk) is the library every other host tool talks through: it
discovers and connects the hardware, drives scans, and turns the camera
histogram streams into Blood Flow Index (BFI) / Blood Volume Index (BVI) plus a
queryable scan database.
It talks to an Open-Motion Console over UART and to up to two sensor
modules (8 × OV2312 cameras each) over USB bulk. The console and sensor
firmware live in the openmotion-console-fw and openmotion-sensor-fw repos;
this library just speaks their wire protocol.
The one front door: MotionInterface
Everything goes through the MotionInterface facade — discover, connect, scan,
configure, calibrate, read results back. Application code never touches the
transport or device classes directly.
from omotion import MotionInterface
from omotion.ScanWorkflow import ScanRequest
iface = MotionInterface(
data_dir="C:/scans", # output root (optional)
operator_id="alice",
)
iface.start(wait=True, wait_timeout=3.0) # discover + connect (spawns daemons)
console_ok, left_ok, right_ok = iface.is_device_connected()
iface.start_scan(ScanRequest(
subject_id="subj-001",
duration_sec=60,
left_camera_mask=0xFF, right_camera_mask=0xFF,
))
iface.scan_workflow.await_complete() # scans run on a worker thread
if iface.scan_workflow.last_scan_error:
print("scan failed:", iface.scan_workflow.last_scan_error)
iface.stop()
Where the scan data goes
- No database configured (the common dev case): the SDK runs in a convenient
CSV mode — a corrected CSV is written under
data_dirso a scan is never silently unrecorded. scan_db_pathset: the SQLite scan database is the system of record (per-camera BFI/BVI + raw frames + metadata), read back viaScanDatabase/SessionPlayback. The corrected CSV becomes opt-in.
See docs/API.md §"Where the data goes" for the full model.
Without hardware
Pass demo_mode=True (or set OPENMOTION_DEMO=1) to skip USB/serial discovery
and generate synthetic data. The same API works headless — signals fall back
from pyqtSignal to MotionSignal automatically.
iface = MotionInterface(demo_mode=True)
iface.start()
Runnable examples
scripts/sdk_examples.py drives each operation
against connected hardware and prints the result:
python scripts/sdk_examples.py connect # connect + version
python scripts/sdk_examples.py configure # configure cameras
python scripts/sdk_examples.py contact-quality # per-camera contact-quality verdicts
python scripts/sdk_examples.py scan # run a short scan (laser on)
python scripts/sdk_examples.py read-scan # summarize the scan DB (read-only, no hw)
python scripts/sdk_examples.py # all of the above on one connection
Plot a finished scan with
scripts/visualize_scan.py:
python scripts/visualize_scan.py --csv <scan_id>_<subject>.csv # -> <stem>_viz.png
Install
# Editable install for local dev
pip install -e ".[dev]"
# Or build a wheel for an app to consume
python -m build # -> dist/openmotion_sdk-*.whl
pip install --force-reinstall dist/openmotion_sdk-*.whl
- Python 3.12+. Version is computed from git tags via
setuptools_scm— never edit a version string by hand; tag and push to release. - Windows USB: sensors need WinUSB via Zadig (
pyusb+libusb); the console uses the OS VCP driver.dfu-utilis vendored underomotion/dfu-util/.
# quick runtime check (device bound to WinUSB/libusbK)
python -c "import usb, omotion.usb_backend as ub; print(ub.get_libusb1_backend())"
Documentation
| Doc | What it covers |
|---|---|
docs/API.md |
Public API guide — start here for consumer usage. |
docs/Architecture.md |
Layer diagram, module reference, transport details. |
docs/SciencePipeline.md |
BFI/BVI computation — the omotion/pipeline/ stage chain. |
docs/ScanDatabase.md |
SQLite scan-database schema. |
docs/scan-sequencing.md |
Frame-ID unwrapping + histogram packet ordering. |
docs/ConsoleTelemetry.md |
PDC (dark correction) + TEC telemetry. |
docs/TestPlan.md |
Hardware-in-the-loop test plan. |
docs/Releasing.md |
Release process (next → main gate before tagging). |
License
AGPL-3.0.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file openmotion_sdk-1.8.0.tar.gz.
File metadata
- Download URL: openmotion_sdk-1.8.0.tar.gz
- Upload date:
- Size: 37.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e7b000f95da2c87bc6c44aec8cdf25374037e6c6db4c1536510b4505546d076
|
|
| MD5 |
3e5742d5ba26ae3f3308a3048c15a0d8
|
|
| BLAKE2b-256 |
8286d006139daa8f73eb8b532b944ef82d37d31e187986d1ad0312ef3f76219c
|
Provenance
The following attestation bundles were made for openmotion_sdk-1.8.0.tar.gz:
Publisher:
publish-pypi.yml on OpenwaterHealth/openmotion-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
openmotion_sdk-1.8.0.tar.gz -
Subject digest:
0e7b000f95da2c87bc6c44aec8cdf25374037e6c6db4c1536510b4505546d076 - Sigstore transparency entry: 1864714078
- Sigstore integration time:
-
Permalink:
OpenwaterHealth/openmotion-sdk@d5f56b2815dc754476083476f66c817cc1962c63 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/OpenwaterHealth
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@d5f56b2815dc754476083476f66c817cc1962c63 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file openmotion_sdk-1.8.0-py3-none-any.whl.
File metadata
- Download URL: openmotion_sdk-1.8.0-py3-none-any.whl
- Upload date:
- Size: 7.1 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9f9a3ba2f5533a76eca87d6bd8b318387719a630c66d978903ab4d7eeb5acebd
|
|
| MD5 |
8deede8fb6f76a20b98e322ed81f021e
|
|
| BLAKE2b-256 |
bf79cc1e9ad40b18f9a163c9fde5bbf6e015234aaf2c5eb71463e324dfa0edf9
|
Provenance
The following attestation bundles were made for openmotion_sdk-1.8.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on OpenwaterHealth/openmotion-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
openmotion_sdk-1.8.0-py3-none-any.whl -
Subject digest:
9f9a3ba2f5533a76eca87d6bd8b318387719a630c66d978903ab4d7eeb5acebd - Sigstore transparency entry: 1864714126
- Sigstore integration time:
-
Permalink:
OpenwaterHealth/openmotion-sdk@d5f56b2815dc754476083476f66c817cc1962c63 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/OpenwaterHealth
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@d5f56b2815dc754476083476f66c817cc1962c63 -
Trigger Event:
workflow_dispatch
-
Statement type: