refactor: consume psyexp-core for shared experiment infrastructure#4
Open
ericwang401 wants to merge 16 commits into
Open
refactor: consume psyexp-core for shared experiment infrastructure#4ericwang401 wants to merge 16 commits into
ericwang401 wants to merge 16 commits into
Conversation
Replace mid_det's own copies of generic plumbing with the shared psyexp-core harness (pinned by git tag v0.5.0): - screen setup + ScreenDiagnostics -> psyexp_core.screen / .diagnostics - timestamped run dirs -> psyexp_core.rundir.make_run_dir - CsvWriter base -> psyexp_core.recording.CsvWriter - manifest writers delegate to psyexp_core.manifest.write_manifest (runs now record psyexp_core_version) - setup-wizard primitives -> psyexp_core.wizard - instruction pager -> psyexp_core.instructions.page_through - full keyboard adoption: configure_psychopy_backend / build_keyboard for setup, and get_keys / wait_for_keys / clear_events plus the new timed get_presses / reset_clock_on_flip / clock_time in the timing-critical response window io/bootstrap.py keeps only the task-specific SessionInfo. All 97 tests pass against the editable psyexp-core overlay. uv.lock regen is deferred until psyexp-core v0.5.0 is tagged.
…from lock Two CI fixes: - phases.py: the per-frame hot-loop reads (_poll_hotkeys, run_fixation early-press) used the backend-switching get_keys, whose event-backend branch imports PsychoPy. CI runs without PsychoPy/psychtoolbox (event backend), so the trial-boundary tests' fake keyboard tripped that import. mid_det is PTB-only and these loops always hold a real Keyboard, so read it directly via the PsychoPy-free get_presses instead. - tests.yml: install psyexp-core --no-deps (its light modules are PsychoPy-free) with the pinned source read from uv.lock via 'uv export' rather than a hardcoded git ref in the workflow.
The parity test parametrized into ~17 cases, each spawning a fresh octave/matlab subprocess — slow startup per case and, on macOS, incessant dock churn as the engine app opened/closed. Batch every case into one program (results delimited by '===') computed in a single session-scoped launch. Same parity coverage; engine starts once (verified) and the file runs in ~0.5s.
- pin psyexp-core>=0.7.0 from PyPI; regenerate uv.lock (was git@v0.5.0) - CI: match the new uv export format (== not @) and install pydantic, which core 0.7.0 now imports for its manifest models - tests: add monitor field to the ScreenDiagnostics fake (core 0.7.0) - docs: describe PyPI consumption + uv lock --upgrade-package flow
Both entry points now call screen.prompt_screen() before opening the window and pass the chosen index to setup_screen(), so on multi-monitor rigs the operator picks the display (auto-returns 0 when there's only one). The selected monitor's OS-level detail (name/refresh/size/HiDPI) flows into screen_diag.monitor and the run manifest via psyexp-core 0.7.0.
uv.lock is authoritative, so any uv sync (including --inexact) reverts an editable psyexp-core overlay to the locked PyPI version; only skipping the sync (uv run --no-sync / UV_NO_SYNC=1) preserves it. Drop the false '--inexact keeps the overlay' claim from AGENTS.md, docs/development.md and the pyproject comment, and document the --no-sync flow plus the durable [tool.uv.sources] + git skip-worktree alternative. Add a justfile with sync/run/ratings/test and core-dev/core-run/core-test/ core-release/core-upgrade recipes wrapping the --no-sync flow.
ericwang401
commented
Jun 30, 2026
…rd helpers Keymaps (config.py): replace the str-valued KEYS_FMRI/KEYS_BEHAVIORAL + EXP_KEYS with the heat-task-aligned list[str] schema — INSTRUCTION_KEYS / START_KEYS / END_KEYS / QUIT_KEYS / OVERLAY_TOGGLE_KEYS / RESPONSE_KEYS — incl. numpad variants. Route instructions, the start/end gates, and _poll_hotkeys through it; drop the dead update_instr_keys and the vestigial fMRI/behavioral split. Ratings: dedup _wait_keys onto psyexp_core.keyboard.wait_for_key, annotate kb as Keyboard|None, and replace core.wait(1.5) with an end-screen "press <key> to exit" wait (mirrors heat-task). Resolves the three todos. Lock: pin psyexp-core 0.8.0 — fixes test_ratings_manifest_written, which failed because HEAD's lock kept 0.7.0 after the session_started_at rename bumped the pyproject floor to >=0.8.0 without re-locking. Docs: add docs/STANDARDIZATION.md (keymap schema, core-extraction migration plan, run() flexibility a/b via contextlib.ExitStack, hand-rolled-vs-library appendix). The ratings entry point now imports the keyboard helpers from psyexp-core 0.9.0; finalize the pin (>=0.9.0 + relock) after that release.
Contributor
Author
|
Pushed
The keyboard helpers were extracted into psyexp-core (HAPNlab/psyexp-core#4, v0.9.0), so |
Wrap the run body in a contextlib.ExitStack, registering the CSV writers, logging, and window close as they are acquired. Previously the cleanup block ran only on the happy path, so a quit key (core.quit -> SystemExit from _poll_hotkeys) or a mid-run error skipped logging.flush()/win.close(). core.quit() is called after the block so genuine errors still propagate with a traceback.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Refactors
mid_detto consume the sharedpsyexp-coreharness (pinned by git tag v0.5.0) instead of carrying its own copies of generic experiment plumbing.mid_detnow keeps only MID-specific logic; the common infrastructure lives in one versioned place, and every run recordspsyexp_core_versionfor reproducibility.Generic infra → psyexp-core
ScreenDiagnostics→psyexp_core.screen/psyexp_core.diagnosticspsyexp_core.rundir.make_run_dirCsvWriterbase →psyexp_core.recording.CsvWriterpsyexp_core.manifest.write_manifest(runs now recordpsyexp_core_version)psyexp_core.wizard(the MID-specific frame-stepping RT prompt stays here)psyexp_core.instructions.page_throughFull keyboard adoption
configure_psychopy_backend+build_keyboardfor setup (replacing manualprefs/backend asserts)get_keys/wait_for_keys/clear_eventsfor name readsget_presses/reset_clock_on_flip/clock_timein the timing-critical response window — no more directpsychopy.hardware.keyboardreads, while preserving the exact frame-counting RT logicio/bootstrap.pykeeps only the task-specificSessionInfo.Why
The same plumbing was duplicated across this task and
heat-task. Centralizing it inpsyexp-coreremoves the duplication, pins a reproducible shared version per run, and lets the timing-critical MID response window read frame-accurate RT through the shared abstraction (enabled by the new timed-keyboard API added in psyexp-core v0.5.0).Notes
psyexp-core v0.5.0(uv run pytest).psyexp_core_version.AGENTS.mddocuments the git-tag pin + editable-overlay co-dev workflow.Update (
71ff9fb): this PR now also standardizes the keymap schema, resolves the ratings todos, and extracts the sharedwait_for_key/check_quitinto psyexp-core. It therefore also depends on psyexp-core#4 (v0.9.0) —ratings/__main__.pyimports those helpers from core. Finalize after that release: bumppsyexp-core>=0.9.0anduv lock --upgrade-package psyexp-core. Seedocs/STANDARDIZATION.mdand the comment below.