A general-purpose respiratory motor control tracking toolbox for interoception research
Project description
respyra
A general-purpose respiratory motor control tracking toolbox for interoception research
respyra is a Python toolbox that integrates a Vernier Go Direct Respiration Belt (GDX-RB) with PsychoPy to enable real-time respiratory motor control tracking experiments. Participants follow a sinusoidal target dot with their breathing while receiving continuous visual biofeedback. The toolbox supports configurable experimental conditions including multi-frequency target waveforms and visuomotor perturbations (visual gain manipulation).
Full documentation | PyPI | Paper
Task Schematic
Task Screenshots
| Range Calibration | Baseline |
|---|---|
| Countdown | Tracking (good) | Tracking (poor) |
|---|---|---|
Installation
From PyPI (recommended)
pip install respyra
For post-session visualization (adds pandas and matplotlib):
pip install "respyra[vis]"
Development install
git clone https://github.com/embodied-computation-group/respyra.git
cd respyra
Create a virtual environment with Python 3.10:
# Windows (with Python Launcher)
py -3.10 -m venv .venv
.venv\Scripts\activate
# macOS / Linux
python3.10 -m venv .venv
source .venv/bin/activate
Install in editable mode:
pip install -e ".[vis]"
Requirements
- Python 3.10 -- PsychoPy does not yet support 3.11+
- Vernier Go Direct Respiration Belt (GDX-RB) -- required for hardware experiments; display demos run without a belt
Quick start
Run a no-hardware display demo to verify PsychoPy is working:
python -m respyra.demos.demo_display
With a belt connected, run the full experiment:
respyra-task
See the full documentation for detailed installation, quickstart, and user guide.
Running the experiment
python -m respyra.scripts.breath_tracking_task
# or, after pip install:
respyra-task
Session flow
- Belt connection -- BLE with automatic USB fallback (connects before PsychoPy to avoid Windows COM conflicts)
- Participant info dialog -- enter participant ID and session number
- Range calibration (15 s) -- comfortable deep breaths to establish breathing range, with percentile-based outlier rejection and sensor saturation detection
- Trial loop (per condition x N reps):
- Baseline (10 s) -- breathe naturally
- Countdown (3 s) -- target dot blends from current position into the target waveform
- Tracking (30 s) -- follow the sinusoidal target dot with breathing
- Feedback -- mean absolute tracking error for the trial
- Data saved to
data/as CSV (one row per sample, flushed incrementally)
Experimental conditions
Conditions are defined in respyra/configs/breath_tracking.py using composable frequency segments:
| Condition | Pattern | Feedback gain |
|---|---|---|
slow_steady |
3 cycles at 0.1 Hz (30 s) | 1.0 (veridical) |
mixed_rhythm |
3 cycles at 0.1 Hz + 1 cycle at 0.3 Hz | 1.0 (veridical) |
perturbed_slow |
3 cycles at 0.1 Hz (30 s) | 1.5 (amplified trace) |
The feedback gain perturbation multiplies the displayed breathing trace around the participant's center, similar to cursor rotation in visuomotor reaching studies. The target dot, tracking error, and color feedback remain based on the true (unperturbed) signal -- only the visual trace is distorted.
Visual feedback
The target dot changes color based on real-time tracking error:
- Graded mode (default) -- continuous green (good) to yellow to red (poor) using HSV interpolation
- Binary mode -- yellow/red threshold
- Trinary mode -- yellow/orange/red with two thresholds
Post-session visualization
python -m respyra.utils.vis.plot_session data/sub-01_ses-001_2026-02-24.csv
# or, after pip install:
respyra-plot data/sub-01_ses-001_2026-02-24.csv
Generates a 6-panel summary figure saved as {csv_stem}_summary.png:
- Full session force trace with target overlay
- Signed tracking error per trial
- Per-trial mean absolute error (bar chart)
- Error distribution by condition (box plot)
- Baseline calibration stability across trials
- Summary statistics (MAE, RMSE, per-condition breakdown)
Project structure
respyra/
core/ Reusable modules
breath_belt.py Non-blocking belt I/O (threaded reader + queue)
display.py PsychoPy window, SignalTrace waveform renderer
data_logger.py Incremental CSV logging with crash resilience
events.py Keyboard input helpers
target_generator.py Sinusoidal target waveform from segment definitions
gdx/ Vernier gdx wrapper (from godirect-examples, not on PyPI)
configs/ Experiment parameters (no magic numbers in scripts)
scripts/ Runnable experiment sessions
demos/ Standalone single-feature test scripts
utils/vis/ Post-session visualization
docs/ Sphinx documentation source
media/ Stimulus assets and icons
data/ Session output (gitignored)
Demos
python -m respyra.demos.demo_belt_connection # Test belt connectivity (terminal only)
python -m respyra.demos.demo_display # PsychoPy display with synthetic data
python -m respyra.demos.demo_threaded_belt # Threaded belt queue-draining pattern
Documentation
Full documentation is available at embodied-computation-group.github.io/respyra, including:
- Installation guide with platform-specific notes
- Quick start tutorial
- User guide with detailed experiment configuration
- API reference generated from source docstrings
- Troubleshooting for common issues
Platform notes
Windows BLE: The Vernier belt's BLE scanner (Bleak) requires COM in MTA mode on the main thread. PsychoPy sets COM to STA on import. The framework handles this by connecting the belt before importing PsychoPy.
Linux: Requires udev rules for USB access. See the installation guide.
macOS: Works with both BLE and USB out of the box.
License
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 respyra-0.2.0.tar.gz.
File metadata
- Download URL: respyra-0.2.0.tar.gz
- Upload date:
- Size: 33.8 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4c1d908b62fe8ed4e0fa8e08e92120a84170e4e33e0e18d5dd6e1f338c543795
|
|
| MD5 |
2458849a9f3b84118374927d2336c1e2
|
|
| BLAKE2b-256 |
8a881738d9ec9f2ebd85b4e1b1ef753ceff593bb5543aed965a41998a4abd437
|
Provenance
The following attestation bundles were made for respyra-0.2.0.tar.gz:
Publisher:
publish.yml on embodied-computation-group/respyra
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
respyra-0.2.0.tar.gz -
Subject digest:
4c1d908b62fe8ed4e0fa8e08e92120a84170e4e33e0e18d5dd6e1f338c543795 - Sigstore transparency entry: 991441328
- Sigstore integration time:
-
Permalink:
embodied-computation-group/respyra@2f0f4dfdd4038eb7aaa5bc10ebccce712e6d482f -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/embodied-computation-group
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2f0f4dfdd4038eb7aaa5bc10ebccce712e6d482f -
Trigger Event:
release
-
Statement type:
File details
Details for the file respyra-0.2.0-py3-none-any.whl.
File metadata
- Download URL: respyra-0.2.0-py3-none-any.whl
- Upload date:
- Size: 59.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ad1dffc58b95e0ecc3dc012b3d50c311c5b8c3cc60e3ead78ad64dcc3ce0230
|
|
| MD5 |
5806afa425d8c7841868dec32f0b7ab7
|
|
| BLAKE2b-256 |
ef8693b5c5ff2f0d255c77a50a50b1f5c14dcf8633e9eeb98131f00054585387
|
Provenance
The following attestation bundles were made for respyra-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on embodied-computation-group/respyra
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
respyra-0.2.0-py3-none-any.whl -
Subject digest:
4ad1dffc58b95e0ecc3dc012b3d50c311c5b8c3cc60e3ead78ad64dcc3ce0230 - Sigstore transparency entry: 991441331
- Sigstore integration time:
-
Permalink:
embodied-computation-group/respyra@2f0f4dfdd4038eb7aaa5bc10ebccce712e6d482f -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/embodied-computation-group
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2f0f4dfdd4038eb7aaa5bc10ebccce712e6d482f -
Trigger Event:
release
-
Statement type: