Lightweight framework for PsychoPy
Project description
PsychoPy-Scene
English | 简体中文
Lightweight experimental framework based on PsychoPy, with only 200 lines of source code.
[!NOTE] The project is in early development. Please pin the version when using it.
Features
- Lightweight: only one file, no extra dependencies
- Type-safe: all parameters use type annotations
- Beginner-friendly: only requires understanding
ContextandScene
Installation
pip install psychopy-scene
Quick Start
Experiment Context
The experiment context Context represents the global parameters of the experiment, including environment parameters and task parameters.
The first step of writing an experiment is to create the experiment context:
from psychopy import visual, data
from psychopy_scene import Context
win = visual.Window()
ctx = Context(win, exp=data.ExperimentHandler())
Scenes
An experiment can be considered as a sequence of scenes. Writing an experiment involves two steps:
- Creating scenes
- Writing scene presentation logic
Scenes provide configuration parameters such as:
duration: duration in secondsclose_on: names of events that close the scene (e.g.,key_fcloses the scene on F key press)on_key_[name]: callback on specific keyboard key presson_mouse_[name]: callback on specific mouse button presson_scene_[name]: callback at specific phases of the scene lifecycle
Creating a scene only requires a function that receives parameters and returns stimuli:
from psychopy import visual
# create stimulus
stim_1 = visual.TextStim(ctx.win, text="Hello")
stim_2 = visual.TextStim(ctx.win, text="World")
# create scene
@ctx.scene(
duration=1,
close_on=["key_f", "mouse_right"],
on_key_escape=lambda: print("escape key was pressed"),
on_mouse_left=lambda: print("left mouse button was pressed"),
on_scene_drawn=lambda: print("it will be called after first drawing"),
on_scene_frame=lambda: print("it will be called each frame"),
)
def demo(color: str, ori: float): # used as on_scene_setup
print('it will be called before first drawing')
stim_1.color = color
stim_2.ori = ori
return stim_1, stim_2
# show scene
demo.show(color="red", ori=45)
Scenes can also be configured dynamically, useful for cases where the display duration is not fixed:
@ctx.scene()
def demo():
return stim
demo.config(duration=0.5).show()
demo.config is equivalent to calling ctx.scene with the same parameters.
Events
Events represent specific runtime moments, such as key presses or mouse clicks.
To perform operations on events, callbacks must be registered:
demo = ctx.scene(close_on="key_f") # or
demo = ctx.scene(on_key_f=lambda: demo.close()) # or
demo = ctx.scene().on("key_f", lambda: demo.close())
[!WARNING] Each event can have only one callback. Adding a duplicate will raise an error.
Callback naming follows on_[type]_[name].
Currently supported event types:
| Type | Name |
|---|---|
| scene | setup, drawn, frame |
| key | any, values from keyboard.KeyPress |
| mouse | left, right, middle |
After calling show, events are triggered in the following order:
graph TD
Initialization --> on_scene_setup --> FirstDrawing --> on_scene_drawn --> c{Draw?}
c -->|No| Stop
c -->|Yes| on_scene_frame --> Redraw --> _["on_key_[name]<br>on_mouse_[name]"] --> c
Data
During scene presentation, data are collected automatically:
| Name | Description |
|---|---|
| show_time | timestamp of first flip |
| events | list of interaction events: keyboard & mouse |
Data can be accessed via scene.get:
@ctx.scene(close_on=["key_f", "key_j"])
def demo():
return stim
demo.show()
close_event = demo.get("events")[-1]
close_key = close_event.data # keyboard.KeyPress
close_time = demo.get("show_time") + close_event.rt
Manual data logging is also supported:
@ctx.scene(
on_key_f=lambda: demo.set('pressed_duration', demo.get('events')[-1].data.duration)),
)
def demo():
return stim
demo.show()
duration = demo.get('pressed_duration')
Shortcuts
Context provides shortcuts to simplify experiment writing:
ctx.text('Welcome to the experiment!', pos=(0, 0)).show() # show static text
ctx.record(a='', b=1, c=True) # record a row to ExperimentHandler
Examples
Trial
from psychopy_scene import Context
from psychopy import visual
def task(ctx: Context, duration = 1):
stim = visual.TextStim(ctx.win, text="")
scene = ctx.scene(duration, on_scene_setup=lambda: stim)
scene.show()
ctx.record(time=scene.get('show_time'))
Block
from psychopy_scene import Context
from psychopy import visual
def task(ctx: Context):
stim = visual.TextStim(ctx.win, text="")
scene = ctx.scene(1, on_scene_setup=lambda: stim)
scene.show()
ctx.record(time=scene.get('show_time'))
win = visual.Window()
data = []
for block_index in range(10):
ctx = Context(win)
ctx.exp.extraInfo['block_index'] = block_index
task(ctx)
block_data = ctx.exp.getAllEntries()
data.extends(block_data)
Project details
Release history Release notifications | RSS feed
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 psychopy_scene-0.2.0.tar.gz.
File metadata
- Download URL: psychopy_scene-0.2.0.tar.gz
- Upload date:
- Size: 17.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c0df442c05161184788e6b1e779ec04eb595f2455eb47206a0371a5cc178e433
|
|
| MD5 |
bcf42b584227602be891b081e8ede140
|
|
| BLAKE2b-256 |
95964f4676a0ded691ba45686e5aa2e9b0b279b30f461fd753c221a9405d26b0
|
Provenance
The following attestation bundles were made for psychopy_scene-0.2.0.tar.gz:
Publisher:
pypi.yaml on bluebonesx/psychopy-scene
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
psychopy_scene-0.2.0.tar.gz -
Subject digest:
c0df442c05161184788e6b1e779ec04eb595f2455eb47206a0371a5cc178e433 - Sigstore transparency entry: 857190133
- Sigstore integration time:
-
Permalink:
bluebonesx/psychopy-scene@5749febae8a76c5bb7ccbcd2a2be51746c7e1d94 -
Branch / Tag:
refs/tags/0.2.0 - Owner: https://github.com/bluebonesx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yaml@5749febae8a76c5bb7ccbcd2a2be51746c7e1d94 -
Trigger Event:
push
-
Statement type:
File details
Details for the file psychopy_scene-0.2.0-py3-none-any.whl.
File metadata
- Download URL: psychopy_scene-0.2.0-py3-none-any.whl
- Upload date:
- Size: 18.1 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 |
01d6893680f2fac7e32c4d95a9757b94cb5038ef553cb91927874caef9f40244
|
|
| MD5 |
577d118a7d526f0a9fdb0659344c6b4e
|
|
| BLAKE2b-256 |
b15e538da5ded62a6ffc3071b7191b065ec2701527ad41f36ffc5093fd887a95
|
Provenance
The following attestation bundles were made for psychopy_scene-0.2.0-py3-none-any.whl:
Publisher:
pypi.yaml on bluebonesx/psychopy-scene
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
psychopy_scene-0.2.0-py3-none-any.whl -
Subject digest:
01d6893680f2fac7e32c4d95a9757b94cb5038ef553cb91927874caef9f40244 - Sigstore transparency entry: 857190135
- Sigstore integration time:
-
Permalink:
bluebonesx/psychopy-scene@5749febae8a76c5bb7ccbcd2a2be51746c7e1d94 -
Branch / Tag:
refs/tags/0.2.0 - Owner: https://github.com/bluebonesx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yaml@5749febae8a76c5bb7ccbcd2a2be51746c7e1d94 -
Trigger Event:
push
-
Statement type: