Example Experiments¶
Here you can find some code examples to see Expyriment in action. All examples are fully working experiments.
For offline usage, all example experiments are also included in Expyriment itself, and and can be found at {prefix}/share/expyriment/examples/ after installation (where {prefix} is the directory of the Python binary; see also sys.prefix).
Simon task¶
An experiment to asses a spatial stimulus-response compatibility effect (see wikipedia).
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
A simple experiment to assess a Simon effect.
See also: http://en.wikipedia.org/wiki/Simon_effect
"""
from expyriment import design, control, stimuli, io, misc
# Create and initialize an Experiment
exp = design.Experiment("Simon Task")
control.initialize(exp)
# Define and preload standard stimuli
fixcross = stimuli.FixCross()
fixcross.preload()
# left and right arrow keys for responses
response_keys = [misc.constants.K_LEFT, misc.constants.K_RIGHT]
# Create design
for mapping in ["left4green", "left4red"]:
b = design.Block()
b.set_factor("Mapping", mapping)
for where in [["left", -300], ["right", 300]]:
for what in [["red", misc.constants.C_RED],
["green", misc.constants.C_GREEN]]:
t = design.Trial()
t.set_factor("Position", where[0])
t.set_factor("Colour", what[0])
s = stimuli.Rectangle([50, 50], position=[where[1], 0],
colour=what[1])
t.add_stimulus(s)
b.add_trial(t, copies=20)
b.shuffle_trials()
exp.add_block(b)
exp.add_bws_factor("OrderOfMapping", [1, 2])
exp.data_variable_names = ["Mapping", "Colour", "Position", "Button", "RT"]
# Start Experiment
control.start()
if exp.get_permuted_bws_factor_condition("OrderOfMapping") == 2:
exp.swap_blocks(0,1)
for block in exp.blocks:
stimuli.TextScreen("Instructions", block.get_factor("Mapping")).present()
exp.keyboard.wait()
for trial in block.trials:
fixcross.present()
exp.clock.wait(1000 - trial.stimuli[0].preload())
trial.stimuli[0].present()
button, rt = exp.keyboard.wait(keys=response_keys)
exp.data.add([block.get_factor("Mapping"), trial.get_factor("Colour"),
trial.get_factor("Position"), button, rt])
# End Experiment
control.end()
Word fragment completion task¶
Task as used for instance in Weldon, 1991.
The script read in a stimulus list file (demo stimulus list
).
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Word fragment completion task as used in the study of Weldon (1991).
Stimulus list: "word_fragment_completion_stimuluslist.csv"!
Weldon, M. S. (1991). Mechanisms underlying priming on
perceptual tests. Journal of Experimental Psychology: Learning, Memory, and
Cognition, 17, 526-541.
"""
import csv
from expyriment import design, control, stimuli, io, misc
control.set_develop_mode(True)
#### read in wordlist file and make design
exp = design.Experiment("word fragment completion test")
block = design.Block()
with open("word_fragment_completion_stimuluslist.csv", "rb") as f:
reader = csv.reader(f)
for row in reader:
trial = design.Trial()
trial.set_factor("word", row[0].strip())
trial.set_factor("fragment", row[1].strip())
block.add_trial(trial)
block.shuffle_trials()
exp.add_block(block)
exp.add_data_variable_names(["word", "fragment", "RT", "RT2", "answer"])
control.initialize(exp)
#prepare some stimuli
fixcross = stimuli.FixCross(line_width=1)
fixcross.preload()
blank = stimuli.BlankScreen()
blank.preload()
txt_input = io.TextInput("")
control.start(exp)
#run experiment
for trial in exp.blocks[0].trials:
#present blank inter-trial-screen and prepare stimulus
blank.present()
fragment = ""
for c in trial.get_factor("fragment").upper():
fragment += c + " "
target = stimuli.TextLine(fragment.strip())
target.preload()
exp.clock.wait(1000)
#present fixcross
fixcross.present()
exp.clock.wait(500)
#present target
target.present()
key, rt = exp.keyboard.wait(misc.constants.K_SPACE)
#ask response
exp.clock.reset_stopwatch()
answer = txt_input.get()
rt2 = exp.clock.stopwatch_time
#process answer and save data
blank.present()
answer = answer.strip()
exp.data.add([trial.get_factor("word"), trial.get_factor("fragment"),
rt, rt2, answer])
target.unload()
control.end()
Number classification task¶
A full experiment to access SNARC and SNARC-like effects in a number and a letter classification task (e.g., Gevers, Reynvoer, & Fias (2003)) with two response mappings, error feedback and between-subject factors.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
A parity judgment task to assess the SNARC effect.
See e.g.:
Gevers, W., Reynvoet, B., & Fias, W. (2003). The mental representation of
ordinal sequences is spatially organized. Cognition, 87(3), B87-95.
"""
from expyriment import design, control, stimuli
from expyriment.misc import constants
control.set_develop_mode(False)
########### DESIGN ####################
exp = design.Experiment(name="SNARC")
# Design: 2 response mappings x 8 stimuli x 10 repetitions
for response_mapping in ["left_odd", "right_odd"]:
block = design.Block()
block.set_factor("mapping", response_mapping)
#add trials to block
for digit in [1, 2, 3, 4, 6, 7, 8, 9]:
trial = design.Trial()
trial.set_factor("digit", digit)
block.add_trial(trial, copies=10)
block.shuffle_trials()
exp.add_block(block)
exp.add_experiment_info("This a just a SNARC experiment.")
#add between subject factors
exp.add_bws_factor('mapping_order', ['left_odd_first', 'right_odd_first'])
#prepare data output
exp.data_variable_names = ["block", "mapping", "trial", "digit", "ISI",
"btn", "RT", "error"]
#set further variables
t_fixcross = 500
min_max_ISI = [200, 750] # [min, max] inter_stimulus interval
ITI = 1000
t_error_screen = 2000
no_training_trials = 10
######### INITIALIZE ##############
control.initialize(exp)
# Prepare and preload some stimuli
blankscreen = stimuli.BlankScreen()
blankscreen.preload()
fixcross = stimuli.FixCross()
fixcross.preload()
error_beep = stimuli.Tone(duration=200, frequency=2000)
error_beep.preload()
#define a trial
def run_trial(cnt, trial):
# present Fixation cross and prepare trial in the meantime
fixcross.present()
exp.clock.reset_stopwatch()
ISI = design.randomize.rand_int(min_max_ISI[0], min_max_ISI[1])
digit = trial.get_factor("digit")
target = stimuli.TextLine(text=str(digit), text_size=60)
target.preload()
exp.clock.wait(t_fixcross - exp.clock.stopwatch_time)
#present blankscreen for a random interval
blankscreen.present()
exp.clock.wait(ISI)
# Present target & record button response
target.present()
btn, rt = exp.keyboard.wait([constants.K_LEFT, constants.K_RIGHT])
#Error feedback if required
if block.get_factor("mapping") == "left_odd":
error = (digit % 2 == 0 and btn == constants.K_LEFT) or \
(digit % 2 == 1 and btn == constants.K_RIGHT)
else:
error = (digit % 2 == 1 and btn == constants.K_LEFT) or \
(digit % 2 == 0 and btn == constants.K_RIGHT)
#write data and clean up while inter-trial-interval
blankscreen.present()
if error:
error_beep.present()
exp.clock.wait(t_error_screen)
exp.clock.reset_stopwatch()
exp.data.add([block.id, block.get_factor("mapping"),
cnt, target.text, ISI,
btn, rt, int(error)])
exp.data.save()
target.unload()
exp.clock.wait(ITI - exp.clock.stopwatch_time)
######### START ##############
control.start(exp)
# permute block order across subjects
if exp.get_permuted_bws_factor_condition('mapping_order') == "right_odd_first":
exp.swap_blocks(0, 1)
# Run the actual experiment
for block in exp.blocks:
# Show instruction screen
if block.get_factor("mapping") == "left_odd":
instruction = "Press LEFT arrow key for ODD\n" + \
"and RIGHT arrow key for EVEN numbers."
else:
instruction = "Press RIGHT arrow key for ODD\n" + \
"and LEFT arrow key for EVEN numbers."
stimuli.TextScreen("Indicate the parity of the numbers", instruction +
"\n\nPress space bar to start training.").present()
exp.keyboard.wait(constants.K_SPACE)
#training trials
for cnt in range(0, no_training_trials):
trial = block.get_random_trial()
run_trial(-1 * (1 + cnt), trial) #training trails has negative trial numbers
# Show instruction screen
stimuli.TextScreen("Attention!", instruction +
"\n\nThe experimental block starts now.").present()
exp.keyboard.wait(constants.K_SPACE)
# experimental trials
for cnt, trial in enumerate(block.trials):
run_trial(cnt, trial)
####### END EXPERIMENT ########
control.end(goodbye_text="Thank you very much for participating in our experiment",
goodbye_delay=5000)
Line bisection task¶
Example of a line bisection task that is optimized for the use of touchscreens and the Expyriment Android Runtime.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
A line bisection task.
This example is appropriate to illustrates the use of the Android runtime environment for Exypriment on tablet PC.
"""
from expyriment import control, stimuli, io, design, misc
# settings
design.defaults.experiment_background_colour = misc.constants.C_GREY
design.defaults.experiment_foreground_colour = misc.constants.C_BLACK
line_length = 200
def line_bisection_task(line_length, position):
# make button
button = stimuli.Rectangle(size=(40,20),
position=(exp.screen.size[0]/2-25, 15-exp.screen.size[1]/2))
button_text = stimuli.TextLine(text="ok", position=button.position,
text_colour=misc.constants.C_WHITE)
mark_position = None
while True:
canvas = stimuli.BlankScreen()
line = stimuli.Rectangle(size=(line_length,3), position=position,
colour=misc.constants.C_BLACK)
line.plot(canvas)
if mark_position is not None:
# plot button and mark line on canvas
button.plot(canvas)
button_text.plot(canvas)
markline = stimuli.Rectangle(size=(1,25),
position=(mark_position, line.position[1]),
colour=misc.constants.C_RED)
markline.plot(canvas)
# present stimulus
canvas.present()
# wait for mouse or touch screen response
_id, pos, _rt = exp.mouse.wait_press()
# process clicked position position
if abs(pos[1]-line.position[1])<=50 and\
abs(pos[0]-line.position[0])<=line_length/2:
mark_position = pos[0]
else:
if button.overlapping_with_position(pos): # is button pressed
return mark_position - line.position[0]
### init ###
exp = control.initialize()
# create touch button box
buttonA = stimuli.Rectangle(size=(80, 40), position=(-60, 0))
buttonB = stimuli.Rectangle(size=(80, 40), position=(60, 0))
textA = stimuli.TextLine(text="quit", position=buttonA.position,
text_colour=misc.constants.C_WHITE)
textB = stimuli.TextLine(text="next", position=buttonB.position,
text_colour=misc.constants.C_WHITE)
touchButtonBox = io.TouchScreenButtonBox(button_fields=[buttonA, buttonB],
stimuli=[textA, textB])
### start ###
control.start(exp)
exp.mouse.show_cursor()
# trial loop
while True:
# find random position
rx, ry = ((exp.screen.size[0]-line_length)/2, (exp.screen.size[1]-50)/2)
pos = [design.randomize.rand_int(-rx, rx), design.randomize.rand_int(-ry, ry)]
# present task
judgment = line_bisection_task(line_length, position=pos)
# save data
exp.data.add(pos +[judgment])
# ask for new trail
touchButtonBox.show()
btn, _rt = touchButtonBox.wait()
if btn==buttonA:
break
## end##
control.end()
Really short example¶
Expyriment is efficient! See here a very short example of an functioning experiment in less than 20 lines of pure code.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
A very short example experiment in 16 lines of pure code.
Participants have to indicate the parity of digits by pressing
the left arrow key for odd and the right arrow key for even numbers.
"""
from expyriment import control, stimuli, design, misc
digit_list = [1, 2, 3, 4, 6, 7, 8, 9]*12
design.randomize.shuffle_list(digit_list)
exp = control.initialize()
exp.data_variable_names = ["digit", "btn", "rt", "error"]
control.start(exp)
for digit in digit_list:
target = stimuli.TextLine(text=str(digit), text_size=80)
exp.clock.wait(500 - stimuli.FixCross().present() - target.preload())
target.present()
button, rt = exp.keyboard.wait([misc.constants.K_LEFT, misc.constants.K_RIGHT])
error = (button == misc.constants.K_LEFT) == digit%2
if error: stimuli.Tone(duration=200, frequency=2000).play()
exp.data.add([digit, button, rt, int(error)])
exp.clock.wait(1000 - stimuli.BlankScreen().present() - target.unload())
control.end(goodbye_text="Thank you very much...", goodbye_delay=2000)
Data preprocessing¶
Preprocessing the data of the SNARC experiment for further statistical analysis.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Example analysis script for snarc_experiment.py
The current script produces two files for different analysis of the SNARC
effect (ANOVA vs. slopes analysis) using mean and median RTs
"""
from expyriment.misc import data_preprocessing, constants
agg = data_preprocessing.Aggregator(data_folder="./data/",
file_name="snarc_experiment")
agg.set_subject_variables(["mapping_order"])
agg.set_computed_variables(["parity = digit % 2", #0:odd, 1:even
"size = digit > 5", #0:small, 1:large
"space = btn == {0}".format(constants.K_RIGHT) #0:left, 1:right
])
# RTs: space x size
agg.set_exclusions(["RT > 1000", "RT < 200", "error == 1", "trial<0"])
agg.set_dependent_variables(["mean(RT)"])
agg.set_independent_variables(["size", "space"])
print agg
agg.aggregate(output_file="rt_size_space.csv")
# RTs: slopes analysis
agg.set_independent_variables(["digit"])
agg.aggregate(output_file="rt_digits.csv")