Skip to content

build: modernize Python support and decouple streaming env from PsychoPy & VR deps#324

Open
pellet wants to merge 3 commits intoNeuroTechX:masterfrom
pellet:release/build-fixes
Open

build: modernize Python support and decouple streaming env from PsychoPy & VR deps#324
pellet wants to merge 3 commits intoNeuroTechX:masterfrom
pellet:release/build-fixes

Conversation

@pellet
Copy link
Copy Markdown
Collaborator

@pellet pellet commented May 4, 2026

build / CI:

  • CI matrix expanded — default Python 3.10 (was 3.8); experimental jobs on py3.11 (full env), py3.12 / py3.13 (streaming env).
  • dropped support for Python 3.8 and 3.9 across all conda envs and requirements.
  • matrix now parameterized by env_file / env_name so streaming-only builds can run without psychopy/psychxr.
  • typecheck job moved from py3.9 to py3.10.

dependencies:

  • psychopy bumped to fork pellet/psychopy@v2026.2.0-rift-fix — fixes Rift stereo projection-matrix crash under strict-ndim psychxr.
  • psychopy-sounddevice switched from local editable install to official upstream Git tip (handles macOS arm64 sound).
  • psychxr — prebuilt Windows wheels from pellet/psychxr fork for cp310–cp313 (PyPI only ships 0.2.4 for ≤ py3.9). Adds experimental Quest-link VR support on py3.10–3.13.
  • pyobjc bumped 7.3 → ≥8.0 for newer psychopy.
  • pyxid2 added to streaming requirements.
  • pywinhook removed — obsolete once py3.9 was dropped (modern pynput on py3.10+ doesn't need it).
  • pyo completely removed from dependencies (audio was never needed for Analysis/Streaming, and fails to build on py3.11).
  • numpy py3.8 pin removed (numpy>=1.26 across the board).
  • setuptools<81 pinned in docsbuild reqs — brainflow imports pkg_resources at runtime, which setuptools 81 deprecated and 82 removed.
  • test deps (pytest, pytest-cov, nbval) moved into streaming requirements so streaming-only CI can run them.

streaming env decoupling:

  • new eegnb/devices/vr.py with class VR — encapsulates psychxr/Rift integration (clock sync, per-trial telemetry buffering, telemetry CSV save, optical-axis offset computation) behind a generic VR-device name. Imported lazily so the streaming-only conda env (no psychxr) can still use the package.
  • lazy/optional imports added in eegnb/cli/utils.py, eegnb/cli/introprompt.py, eegnb/experiments/init.py so the package can be imported under a streaming-only env (no VR / no sound libs).
  • new tests/test_acquisition.py (acquisition smoke test) — what the streaming-env CI job actually runs.
  • new conftest.py for shared pytest setup.
  • eegnb/devices/eeg.py — import pyxid2 wrapped in try/except so users without a Cedrus FTDI driver don't crash at import time.

experiment runtime:

  • per-eye stimulus alignment now queried from the HMD runtime instead of being hard-coded to ±0.2. Quest 2/3 lenses are angled inward and offset within their own image, so a single fixed value left the checkerboard slightly off-centre and looking tilted outward. The new compute_optical_axis_offsets() asks the runtime for the actual per-lens position so the stimulus sits where each eye is naturally looking.
  • trial loop now runs at higher OS scheduling priority (psychopy core.rush) with Python's garbage collector paused, so the GC can't pause stimulus rendering mid-trial.
  • HMD-clock to system-clock sync moved into a single VR.sync_vr_clock() call at the start of each run, so per-trial telemetry timestamps line up with EEG markers.

update notes
* added support for VR/PsychXR up to 3.10.
* fixed recording with Thinkpulse electrodes.

build / CI:
* CI matrix expanded — default Python 3.10 (was 3.8); experimental jobs on py3.11 (full env), py3.12 / py3.13 (streaming env).
* dropped support for Python 3.8 and 3.9 across all conda envs and requirements.
* matrix now parameterized by env_file / env_name so streaming-only builds can run without psychopy/psychxr.
* typecheck job moved from py3.9 to py3.10.

dependencies:
* psychopy bumped to fork pellet/psychopy@v2026.2.0-rift-fix — fixes Rift stereo projection-matrix crash under strict-ndim psychxr.
* psychopy-sounddevice switched from local editable install to official upstream Git tip (handles macOS arm64 sound).
* psychxr — prebuilt Windows wheels from pellet/psychxr fork for cp310–cp313 (PyPI only ships 0.2.4 for ≤ py3.9). Adds experimental Quest-link VR support on py3.10–3.13.
* pyobjc bumped 7.3 → ≥8.0 for newer psychopy.
* pyxid2 added to streaming requirements.
* pywinhook removed — obsolete once py3.9 was dropped (modern pynput on py3.10+ doesn't need it).
* pyo removed from Analysis and Streaming sections (audio was never needed in those envs).
* numpy py3.8 pin removed (numpy>=1.26 across the board).
* setuptools<81 pinned in docsbuild reqs — brainflow imports pkg_resources at runtime, which setuptools 81 deprecated and 82 removed.
* test deps (pytest, pytest-cov, nbval) moved into streaming requirements so streaming-only CI can run them.

streaming env decoupling:
* new eegnb/devices/vr.py with class VR — encapsulates psychxr/Rift integration (clock sync, per-trial telemetry buffering, telemetry CSV save, optical-axis offset computation) behind a generic VR-device name. Imported lazily so the streaming-only conda env (no psychxr) can still use the package.
* lazy/optional imports added in eegnb/cli/utils.py, eegnb/cli/introprompt.py, eegnb/experiments/__init__.py so the package can be imported under a streaming-only env (no VR / no sound libs).
* new tests/test_acquisition.py (acquisition smoke test) — what the streaming-env CI job actually runs.
* new conftest.py for shared pytest setup.
* eegnb/devices/eeg.py — `import pyxid2` wrapped in try/except so users without a Cedrus FTDI driver don't crash at import time.

experiment runtime:
* per-eye stimulus alignment now queried from the HMD runtime instead of being hard-coded to ±0.2. Quest 2/3 lenses are angled inward and offset within their own image, so a single fixed value left the checkerboard slightly off-centre and looking tilted outward. The new compute_optical_axis_offsets() asks the runtime for the actual per-lens position so the stimulus sits where each eye is naturally looking.
* trial loop now runs at higher OS scheduling priority (psychopy core.rush) with Python's garbage collector paused, so the GC can't pause stimulus rendering mid-trial.
* end-of-run timing summary added (frame timing stats) for spotting dropped or delayed frames after the fact.
* HMD-clock to system-clock sync moved into a single VR.sync_vr_clock() call at the start of each run, so per-trial telemetry timestamps line up with EEG markers.
@pellet pellet force-pushed the release/build-fixes branch from 5610a7f to da6c007 Compare May 4, 2026 11:57
@pellet pellet marked this pull request as ready for review May 5, 2026 08:33
@pellet pellet changed the title build: modernize Python support and decouple streaming env from VR deps build: modernize Python support and decouple streaming env from PsychoPy & VR deps May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant