Skip to main content

PsychoPy-Scene

PyPI - Version PyPI - Downloads

English | 简体中文

A lightweight framework based on the Scene architecture, for PsychoPy.

Features

  • Lightweight: Only 2 files, with no additional dependencies
  • Type-safe: Supports generics
  • Beginner-friendly: You only need to understand the concepts of Context and Scene to get started

Installation

pip install psychopy-scene

Quick Start

Context

Context encapsulates data shared across scenes, such as the drawing window Window.

The first step is to create an experiment context.

from psychopy import visual, data
from psychopy_scene import Context

ctx = Context(win=visual.Window(), exp=data.ExperimentHandler())

Scenes

An experiment can be viewed as a composition of a series of scenes. To write an experiment, you only need to:

  1. Create a scene
  2. Define its presentation logic

Create a scene using a decorator:

from psychopy import visual
from psychopy.hardware import keyboard
from psychopy_scene.decorator import duration, hardware_keyboard

# create stimulus
stim_1 = visual.TextStim(ctx.win, text="Hello")
stim_2 = visual.TextStim(ctx.win, text="World")

# create scene
@duration(1)
@ctx.scene
def demo_1(color: str, ori: float):
    print('it will be called before first flip')
    stim_1.color = color
    stim_2.ori = ori
    return stim_1, stim_2

@close_on('key_space')
@hardware_keyboard()
@ctx.scene
class demo_2:
    scene: Scene

    def __call__(self, text: str):
        stim_1.text = text
        return stim_1

    def on_key_space(self, evt: keyboard.KeyPress):
        self.scene.data['rt'] = evt.tDown - self.scene.data['frame_times'][0]

# show scene
data_1 = demo_1.show(color="red", ori=45)
data_2 = demo_2.show(text="test")

Time-related decorators override one another because they work by setting the scene's timer attribute.

This can be useful in situations where the presentation duration is not fixed:

@duration(1)
@ctx.scene
def demo():
    return stim

data = demo.use(duration(0.5)).show()

Data

A scene automatically collects data:

Name Description
frame_times Timestamp of each frame flip

The data can be accessed through scene.data:

@close_on('key_f', 'key_j')
@hardware_keyboard()
@ctx.scene
def demo():
    return stim

data = demo.show() # just a dict
show_time = data["frame_times"][0]

Manual data collection is also supported:

@hardware_keyboard()
@ctx.scene
class demo:
    scene: Scene

    def __call__(self):
        return stim

    def on_key_f(self, evt: keyboard.KeyPress):
        self.scene.data['pressed_duration'] = evt.duration

data = demo.show()
duration = data['pressed_duration']

Events

An event represents a specific time point during scene showing, such as a key press or mouse click.

To execute an action when an event occurs, add a callback for that event:

scene.on('show', lambda _: print('do something'));

These are all the built-in scene events and when they are triggered:

graph TD
Initialization --> s((show)) --> FirstDraw --> f((flipped)) --> c{DrawAgain?}
c -->|No| StopDrawing
c -->|Yes| TimingCheck --> a((frame)) --> Redraw --> p((poll)) --> c

Some event types are provided by decorators associated with input devices. For example, hardware_keyboard provides support for the key_space event, allowing callbacks registered with scene.on('key_space', ...) to be triggered when the space key is pressed.

These decorators trigger other events during the poll event by calling scene.emit('key_space', ...).

Examples

Trial

from psychopy import visual
from psychopy_scene import Context
from psychopy_scene.decorator import duration

def task(ctx: Context, sec=1):
    stim = visual.TextStim(ctx.win, text="")
    scene = ctx.scene(lambda: stim).use(duration(sec))
    data = scene.show()
    ctx.record(time=data['frame_times'][0])

Block

from psychopy import visual
from psychopy_scene import Context
from psychopy_scene.decorator import duration

def task(ctx: Context):
    stim = visual.TextStim(ctx.win, text="")
    scene = ctx.scene(lambda: stim).use(duration(1))
    data = scene.show()
    ctx.record(time=data['frame_times'][0])

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)

Metadata

Release files for psychopy-scene 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for psychopy-scene 0.3.1
File Size Uploaded
psychopy_scene-0.3.1.tar.gz 17.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for psychopy-scene 0.3.1
File Interpreter ABI Platform
psychopy_scene-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 36.1 kB

Release files / psychopy_scene-0.3.1.tar.gz

Download URL psychopy_scene-0.3.1.tar.gz
Size 17.8 kB
Tags Source
SHA-256 checksum
How to use checksums
11c2d4ba9992499dba788fe3db420141cf03b12ae26031e8417f6848a6cb5efe
BLAKE2b-256 checksum
How to use checksums
759f6a39620c773052f7df25c7c032428277f260e5c8220d8fdde6f7079e8d6f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.

Transparency log

Release files / psychopy_scene-0.3.1-py3-none-any.whl

Download URL psychopy_scene-0.3.1-py3-none-any.whl
Size 18.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
83f82e7f2cfc474c24a2a5b4ae2fab23202650fe4bd4964352541cbc48937034
BLAKE2b-256 checksum
How to use checksums
205e31101591a385ac1e28f7122e5b75c1cce3bb14a69219ab52fd8c8a8e81b7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.0

2 release files

This release

0.3.1 This release

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page