Skip to main content

Task-agnostic harness for PsychoPy experiments: screen/frame-timing setup, run manifests, CSV writers, setup-wizard primitives, instruction pager, and keyboard abstraction.

Project description

psyexp-core

PyPI Python

Task-agnostic harness for PsychoPy experiments, shared across the lab's task repos (heat-task, mid-task, mid-task-deterministic). It owns the plumbing that every task duplicates; each task repo keeps only its own stimuli, trial logic, and record schemas.

What's in here

Module Responsibility
screen setup_screen() — open a fullscreen PsychoPy window, enable VSYNC, run a frame-timing calibration, and return a ScreenDiagnostics.
diagnostics The ScreenDiagnostics dataclass (import-light; no PsychoPy).
rundir make_run_dir(data_dir, label, session_time) — timestamped output directory.
manifest write_manifest(...) + system_info() — JSON run manifest with system/display/process diagnostics and the resolved psyexp_core_version. App-specific fields are injected via header / study_params.
recording CsvWriter base class (maps a dataclass record onto a fixed column schema).
wizard questionary / prompt_toolkit setup-wizard primitives: shared styles, ask_text / ask_select / ask_confirm, PosFloatValidator, prompt_unique_name, quit_app.
instructions page_through(...) — a self-paced, keypress-driven instruction pager.
keyboard PTB / PsychoPy-event keyboard abstraction: build_keyboard / get_keys / wait_for_keys / clear_events, plus the timed-press API for response windows — get_presses (name + rt), reset_clock_on_flip / reset_clock / clock_time.

Install

psyexp-core is published on PyPI, so the released harness installs like any other dependency:

uv add psyexp-core          # or: pip install psyexp-core
# your-task/pyproject.toml
dependencies = ["psyexp-core>=0.5"]

Requires Python 3.11+. On macOS the pyobjc-framework-quartz dependency is pulled in automatically for display diagnostics.

Use from a task repo

You can keep the plain PyPI dependency above, or override the source while developing. For day-to-day work, point at a local checkout so edits are live without reinstalling:

# your-task/pyproject.toml
dependencies = ["psyexp-core"]

[tool.uv.sources]
psyexp-core = { path = "../psyexp-core", editable = true }

For a reproducible build pinned ahead of (or instead of) a PyPI release, pin a tagged git ref instead:

[tool.uv.sources]
psyexp-core = { git = "ssh://git@github.com/HAPNlab/psyexp-core.git", tag = "v0.5.1" }

write_manifest records the resolved psyexp_core_version so each run is traceable back to a core version.

Co-developing core while a task repo keeps the git pin

Lab task repos (e.g. heat-task) commit the git-tag source above so clones reproduce exactly, then overlay a local editable install for development:

uv pip install -e ../psyexp-core

Gotcha: uv run re-syncs the task venv from its uv.lock on every launch, which reverts that editable install straight back to the pinned tag (symptoms: your local core edits silently don't take effect). Set UV_NO_SYNC=1 in the task repo (export it in your shell, or use uv run --no-sync) so the editable overlay sticks; run a manual uv sync only when you change other deps, then re-run the editable install. See heat-task's README ("Co-developing psyexp-core locally") for the full workflow.

Releasing

Tagging and publishing are deliberately separate, so tags stay cheap to iterate on:

  1. Bump + lock + changelog, then tag vX.Y.Z. The tag runs the checks and creates a draft GitHub Release — it does not publish anything.
  2. Review the draft Release and publish it. That triggers publish.yml, which uploads to PyPI via Trusted Publishing (OIDC; no API token stored).

PyPI versions are immutable, so retagging never republishes; bump the version to ship new code. See docs/releasing.md for the full process, SemVer policy, pre-releases, retag semantics, and the one-time PyPI setup.

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

psyexp_core-0.5.2.tar.gz (126.2 kB view details)

Uploaded Source

Built Distribution

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

psyexp_core-0.5.2-py3-none-any.whl (14.8 kB view details)

Uploaded Python 3

File details

Details for the file psyexp_core-0.5.2.tar.gz.

File metadata

  • Download URL: psyexp_core-0.5.2.tar.gz
  • Upload date:
  • Size: 126.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for psyexp_core-0.5.2.tar.gz
Algorithm Hash digest
SHA256 00fdd03c45f6343b754039e7dd9bc814cb6cf7f5a5b965f37bf4212cb357d670
MD5 63be17b6c17871d34691dc919715b565
BLAKE2b-256 74178a08880b6629e665f240cc43e3046b41ab4db6ff9bd3b96ccbc98ee1fd15

See more details on using hashes here.

Provenance

The following attestation bundles were made for psyexp_core-0.5.2.tar.gz:

Publisher: publish.yml on HAPNlab/psyexp-core

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file psyexp_core-0.5.2-py3-none-any.whl.

File metadata

  • Download URL: psyexp_core-0.5.2-py3-none-any.whl
  • Upload date:
  • Size: 14.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for psyexp_core-0.5.2-py3-none-any.whl
Algorithm Hash digest
SHA256 5f1d3436be724a009e45bb44ea9901585c60408188ecb47eb9de75f71727503d
MD5 fce0429156234bb414865051bf0ed169
BLAKE2b-256 c4001e63781a5f3c174cd1dc4b1dca25085edfa649f3e9bc197af871294aedbc

See more details on using hashes here.

Provenance

The following attestation bundles were made for psyexp_core-0.5.2-py3-none-any.whl:

Publisher: publish.yml on HAPNlab/psyexp-core

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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