Skip to main content

Open-source toolbox for respiratory motor control tracking with visuomotor perturbation

Project description

respyra

Python framework for respiratory motor control experiments integrating the Vernier Go Direct Respiration Belt (GDX-RB) with PsychoPy. All experiments are written in pure Python (no PsychoPy Builder/GUI).

Participants follow a sinusoidal target dot with their breathing while their live respiratory waveform is displayed. The framework supports multiple experimental conditions including frequency changes and visuomotor perturbations (visual gain manipulation).

Task Schematic

Task schematic

Task Screenshots

Range Calibration Baseline
Range Calibration Baseline
Countdown Tracking (good) Tracking (poor)
Countdown Tracking veridical Tracking bad

Requirements

  • Python 3.10 (PsychoPy does not support 3.11+)
  • Vernier Go Direct Respiration Belt (GDX-RB) connected via BLE or USB

Installation

  1. Clone the repository:

    git clone https://github.com/embodied-computation-group/respyra.git
    cd respyra
    
  2. 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
    
  3. Install in development mode:

    pip install -e .
    

    For post-session visualization (optional):

    pip install -e ".[vis]"
    

Running the experiment

python -m respyra.scripts.breath_tracking_task
# or, after pip install:
respyra-task

Session flow

  1. Belt connection -- BLE with automatic USB fallback (connects before PsychoPy to avoid Windows COM conflicts)
  2. Participant info dialog -- enter participant ID and session number
  3. Range calibration (15 s) -- comfortable deep breaths to establish breathing range, with percentile-based outlier rejection and sensor saturation detection
  4. 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
  5. 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:

  1. Full session force trace with target overlay
  2. Signed tracking error per trial
  3. Per-trial mean absolute error (bar chart)
  4. Error distribution by condition (box plot)
  5. Baseline calibration stability across trials
  6. 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/context/       Reference docs (PsychoPy API, Vernier belt interface)
media/              Stimulus assets
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

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 docs/context/vernier/vernier.md.

macOS: Works with both BLE and USB out of the box.

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

respyra-0.1.0.tar.gz (21.8 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

respyra-0.1.0-py3-none-any.whl (58.7 kB view details)

Uploaded Python 3

File details

Details for the file respyra-0.1.0.tar.gz.

File metadata

  • Download URL: respyra-0.1.0.tar.gz
  • Upload date:
  • Size: 21.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for respyra-0.1.0.tar.gz
Algorithm Hash digest
SHA256 8e686d5921f36ccfbbd87ee51db0b15c992f7534af2694e33432f56735dc33fb
MD5 5d4cbb4a77a9473a7c48bc8dd86e5f85
BLAKE2b-256 82e1be598efe2a723996a789361f770ebe0cf3ece87461371610d2eb74ea0a26

See more details on using hashes here.

File details

Details for the file respyra-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: respyra-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 58.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for respyra-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a1cf5f5ff4c1cf7765375f2d7383c94bc3b738819357f80cfbc7acaef5463d5a
MD5 f272065b1e966cde9ed298b1e22bb01e
BLAKE2b-256 d22e55f4aefd695df82a6df5e2a095254b253fc0d29e20a01e8e2e27838bac74

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page