Examples¶
You can find all examples on this page in the doc/examples folder.
Inter-temporal Choice Task¶
This is the exact same example as on the front page.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | import pygame
from pyparadigm.surface_composition import *
from pyparadigm.misc import empty_surface, display, init
from pyparadigm.eventlistener import EventListener
import json
# Scroll to the bottom, and start reading in the main() ;)
def offer_box(title, amount):
# Creates a border around a vertical layout containing 2 cells, where the
# lower one has twice the size of the upper one (layout children are
# automatically wrapped in LLItems with relative_size=1). Both Boxes are
# filled with text, wich is centered in its parent area.
return Border()(
LinLayout("v")(
Text(title, Font(size=50)),
LLItem(2)(Text(f"{amount}€", Font(size=50, bold=True)))
)
)
def make_offer(now, later, delay):
# Create pygame.Surface with a white background.
# The LinLayout splits the available space into (in this case)
# equally sized horizontally aligned parts. 80% of the available
# space of each part is used to display a offer box.
return compose(empty_surface(0xFFFFFF), LinLayout("h"))(
Padding.from_scale(0.8)(offer_box("Now", now)),
Padding.from_scale(0.8)(offer_box(f"In {delay} days", later)),
)
def make_feedback(amount, delay):
# creates a pygame.Surface which only contains the text message
msg = f"{amount}€ " + ("now" if delay == 0 else f"in {delay} days")
return compose(empty_surface(0xFFFFFF))(Text(msg, Font(size=50)))
def main():
# initiate a window with a resolution of 800 x 600 pixels
init((800, 600))
# alternatively, to create a full screen, hardware accelrated window, you
# could use:
# init((1920, 1080), pygame.FULLSCREEN | pygame.HWSURFACE | pygame.DOUBLEBUF)
# Create an Eventlistener object
event_listener = EventListener()
# Initiate the data for the paradigm, and create 2 lists to store
# the results
immediate_offers = ([10] * 3) + ([20] * 3) + ([30] * 3)
delays = [10, 20, 30] * 3
delayed_offers = [delay + im_offer
for delay, im_offer in zip(delays, immediate_offers)]
chosen_amounts = []
chosen_delays = []
# Execute the paradigm
for im_offer, del_offer, delay in zip(immediate_offers, delayed_offers, delays):
# display the offer
display(make_offer(im_offer, del_offer, delay))
# wait for a decision in form of the left or right arrow-key
key = event_listener.wait_for_keys([pygame.K_LEFT, pygame.K_RIGHT])
# store results according to decision
if key == pygame.K_LEFT:
chosen_amounts.append(im_offer)
chosen_delays.append(0)
else:
chosen_amounts.append(del_offer)
chosen_delays.append(delay)
# display a feedback for 2 seconds
display(make_feedback(chosen_amounts[-1], chosen_delays[-1]))
event_listener.wait_for_seconds(2)
# save results to a json File
with open("results.json", "w") as file:
json.dump({"amount": chosen_amounts, "delay": chosen_delays}, file)
if __name__ == '__main__':
main()
|
Flashing Checkerboard¶
This example just alternates the two stimuli with frequency of 2Hz. To make sure, that the interpreter finds the stimuli cd into the examples folder, and execute it from there.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | import pygame
from pyparadigm.misc import init, display, empty_surface
from pyparadigm.surface_composition import compose, Surface, Text, Font
from pyparadigm.eventlistener import EventListener
from functools import lru_cache
from itertools import cycle
def render_frame(screen, frame):
# This time we dont use :py:func:`misc.display` and instead draw directly
# onto the screen, and call flip() then to display it. Usually we would want
# to generate a screen with a function (with lru_cache), and then use
# :py:func:`misc.display` to blit the different screens. This way every
# screen is only computed once. This time though, no screens are computed,
# it is simply displaying an existing image, and no screens are reused.
compose(screen)(Surface(scale=1)(frame))
pygame.display.flip()
def main():
# we want to display the two states with 2Hz, therefore the timeout is 1/2s
timeout = 0.5
# initialize a window, and get a reference to the pygame.Surface
# representing the screen.
screen = init((1024, 800))
# Load the frames. When loading a pygame.Surface from a file, you should
# always call convert() on it, this will change the image format to optimize
# performance. If you have an image that uses transparent pixels, use
# convert_alpha() instead.
# We use itertools.cycle to get an iterator that will alternate between the
# images, see the python-doc (https://docs.python.org/3/library/itertools.html)
frames = cycle([pygame.image.load(f"checkerboard_{i}.png").convert()
for i in range(2)])
# Create an EventListener object. No additional handlers needed here.
event_listener = EventListener()
# Display an initial text
display(compose(empty_surface(0xFFFFFF))(Text(
"""Press Return to start.
Press again to end.""", Font(size=60))))
# Wait for the return key
event_listener.wait_for_n_keypresses(pygame.K_RETURN)
key = None
# Repeat until return is pressed again
while key == None:
# display one of the two checkerboard images
render_frame(screen, next(frames))
# wait for timeout seconds for RETURN to be pressed. If RETURN is
# pressed :py:meth:`EventListener.wait_for_keys` will return
# pygame.K_RETURN otherwise it will return NONE
key = event_listener.wait_for_keys([pygame.K_RETURN], timeout)
if __name__ == '__main__':
main()
|