Generating Trial Sequences for a Closed-Loop Psychophysics Study¶
In this example, we use SweetPea to generate an experimental sequence for a same-different Psychophysics experiment.
You can find more in-depth tutorials on automated experimental design at the SweetPea Website.
Installation¶
First, we will install SweetPea.
%%capture
!pip install sweetpea
Regular Factors¶
Next, we define the experimental factors of our experiment. In this experiment, select whether the number of dots in the two sets is the same or not.
The experiment has two independent variables: The number of dots in the first set and the number of dots in the second set. Here, we want to counterbalance the number of dots for stimulus 1 and stimulus, respectively.
from sweetpea import Factor
# the first experimental factor indicates the number of dots in the
# left stimulus. It has two levels, i.e., two possible values for the
# number of dots, either 40 and or 70 dots.
num_dots_left = Factor('dots_left', [40, 70])
# the second experimental factor indicates the number of dots in the
# right stimulus. It also has two levels: 40 and 70 dots.
num_dots_right = Factor('dots_right', [70, 40])
The code defines the two variables in terms of two experimental factors, respectively: the number of dots in the left stimulus and the number of dots in the right stimulus. Here, we assume that the number of dots can either be 40 or 70.
Synthesize Trial Sequences¶
Next, we generate an experiment trial sequence. In this sequence, we want to counterbalance the levels of both factors. We also want to specify a constraint to include at least 20 trials.
from sweetpea import MinimumTrials, CrossBlock, synthesize_trials, CMSGen, experiments_to_dicts
# the experimental design includes all relevant factors
# (whether counterbalanced or not)
design = [num_dots_left, num_dots_right]
# the crossing specifies which factors are fully counterbalanced
crossing = [num_dots_left, num_dots_right]
# we also add a constraint to include at least 20 trials
constraints = [MinimumTrials(20)]
# next, we define an experimental block based on the design, crossing,
# and constraints
block = CrossBlock(design, crossing, constraints)
# we then use a SAT-Solver to find one suitable experimental sequence
experiment = synthesize_trials(block, 1, CMSGen)
Printing and Extracting Experimental Sequence¶
We can print the resulting experiment:
from sweetpea import print_experiments
print_experiments(block, experiment)
And we can store the resulting experimental sequence in a dictionary:
# we can export the experimental sequence as a dictionary
sequence = experiments_to_dicts(block, experiment)
print(sequence)
Writing a Function to Automate the Generation of Trial Sequences¶
Next, we wrap the code above into a function that will generate an experimental sequence for an arbitrary set of two stimulus intensities, e.g., number of dots. We will accept the number of trials as an argument.
from sweetpea import Factor, MinimumTrials, CrossBlock, synthesize_trials, CMSGen, experiments_to_dicts
def trial_sequence(num_dots_1, num_dots_2, min_trials):
# define regular factors
num_dots_left = Factor('dots_left', [num_dots_1, num_dots_2])
num_dots_right = Factor('dots_right', [num_dots_1, num_dots_2])
# define experimental block
design = [num_dots_left, num_dots_right]
crossing = [num_dots_left, num_dots_right]
constraints = [MinimumTrials(min_trials)]
block = CrossBlock(design, crossing, constraints)
# synthesize trial sequence
experiment = synthesize_trials(block, 1, CMSGen)
# export as dictionary
return experiments_to_dicts(block, experiment)[0]