(3) Trial Block¶
Here, we learn how to use a timeline to create a block of trials for the Stroop task, (Stroop, 1935). In the Stroop task, participants are typically asked to name the color in which a color word is displayed (e.g., say green
to the word RED displayed in green). We create an experiment that loops through the following stimulus sequence while varying the ink color and the word of the color word.
Installing sweetbean¶
!pip install sweetbean
Creating a timeline¶
Instead of defining a stimulus for each trial, we can create a timeline of stimulus features. In this case, we define the color and the word of a trial in a timeline. The timeline bellow defines the trial sequence
RED, GREEN, RED, GREEN
timeline = [
{'color': 'red', 'word': 'RED'},
{'color': 'green', 'word': 'RED'},
{'color': 'green', 'word': 'GREEN'},
{'color': 'red', 'word': 'GREEN'},
]
SweetPea¶
Optional: Using SweetPea to produce the timeline
SweetPea is an open-source declarative language in Python, in which researchers can describe their desired experiment as a set of factors and constraints. It has a very similar syntax to SweetBean and there are similar tutorials to this one that can help you to create counterbalanced sequences of trials. For an example of how to use SweetPea in conjunction with SweetBean, see this example.Declare TimelineVariables¶
To use the timeline declared above we need to declare timeline variables. You can use these variables to parameterize stimuli, rather than parameterizing them with static values. In this way, stimuli can be defined in terms of the timeline variables, and the timeline can be used to parameterize the stimuli for each trial.
# import the functionality from sweetbean
from sweetbean.variable import TimelineVariable
## declare the timeline variables
# color: The name has to be color (it is the name in the timeline)
color = TimelineVariable(name="color")
# word: The name has to be word (it is the name in the timeline), and it has the levels RED and GREEN
word = TimelineVariable(name="word")
Optional: Why can we not just use the timeline and have to declare the TimelineVariables separately?
In a real experiment often times, you don't want to use static timelines that you have to declare in the code. Instead you want to load timelines from a file or from a database. For example, you could upload timeline sequences to a database and then use a different one for each participant. Therefore sweetbean needs to be able to handle timelines that are not yet defined. We only need to declare the timeline variables to produce working JavaScript code. The loading of the timeline can be done at runtime (e.g., when a participant visits our page)Creating the stimulus sequence¶
Now we create a stimulus sequence. When using a timeline, sweetbean can loop through a specified sequence of stimuli as often as there are trials defined in the timeline. Here we want to loop through the sequence:
A blank screen first (fixation onset), then the fixation cross, then a blank screen again (stimulus onset), and finally the Stroop stimulus.
Here, we also introduce a (rather boring) stimulus: A blank screen
Optional: Isn't a text stimulus without text a blank screen?
If you want, you can also define a TextStimulus without the text paramater to emulate a blank screen. This is an example to make the programming language easier to read and translate for the use with Natural Language Processing.# importing the functionality
from sweetbean.stimulus import Text, Blank
## declaring the different stimuli
# fixation onset (a blank screen for 600ms)
fixation_onset = Blank(duration=600)
# fixation cross (the character "+" shown for 800ms)
fixation = Text(duration=800, text="+")
# stimulus onset (a blank screen shown for 200ms)
stimulus_onset = Blank(duration=200)
# the Stroop stimulus. Here instead of fixed parameters, we use the timeline variables, that we defined previously.
stroop = Text(duration=2500, text=word, color=color)
Note that for this example, we also used a new parameter color
for the text stimulus that we haven't used before.
Variable Stimulus onset.¶
For the purpouse of sound experimental design, it is often usefull to introduce a variable stimulus onset instead of a fixed one, e.g., to isolate preparation effects from processing effects. With such a variable stimulus onset, a participant can not anticipate the onset of the stimulus.
Can you change the code to accommodate for this? To start we already provide the timeline:
timeline = [
{'color': 'red', 'word': 'RED', 'soa': 300},
{'color': 'green', 'word': 'GREEN', 'soa': 200 },
{'color': 'green', 'word': 'RED', 'soa': 400},
{'color': 'red', 'word': 'GREEN', 'soa': 500},
]
# Enter your code here:
Solution¶
# declare the timeline variable
soa = TimelineVariable(name='soa')
# use the timeline variable in the stimulus instead of the fixed value
stimulus_onset = Blank(duration=soa)
Creating a block¶
To create the block, all we have to do is add the timeline as parameter
# import the functionality from sweetbean to create a block
from sweetbean import Block
# create a list of stimuli for the block
stimulus_sequence = [fixation_onset, fixation, stimulus_onset, stroop]
# create the block
stroop_block = Block(stimulus_sequence, timeline)
Optional: Python keyword arguments
Maybe you have noticed that in the declaration of the stimuli we used a slightly different syntax then in the declaration of the block. When defining the stimuli, we use equal signs to declare the different aspects of the stimulus, while no such equal signs are used in the declaration of the block.
stroop = TextStimulus(duration=2500, text=word, color=color)
block = Block(stimulus_sequence, timeline)
In the stimulus definition, we use so called keyword arguments, while we don't use them in the block. But, we can also define the stimuli without the keywords or define the Block with the use of keyword arguments. If we don't use the keyword arguments, we must enter parameter in the order as they are defined in the class.
stroop = TextStimulus(2500, word, color)
block = Block(stimuli=stimulus_sequence, timeline=timeline)
Creating the experiment and exporting it as a html file¶
# import the functionality from sweetbean to create experiments
from sweetbean import Experiment
# create a list of blocks
block_list = [stroop_block]
# create the experiment
experiment = Experiment(block_list)
# export to html
experiment.to_html('index.html')
Optional: Creating a depiction of the stimulus sequence for the method section¶
SweetBean provides functionality to help document your experiments. For example, you can create a stimulus timeline as the one seen above. This a picture that shows the succesion of stimulu in your experiment and can help others to understand it.
NOTE: This functionality does not work in google colab since we need access to simulate a browser, but you can use it when running SweetBean on your personal computer.
# this functionality depends on addiditional functionalities that are not in the core package of sweetbean. We need to install these optional dependencies
!pip install html2image
!pip install pillow
!pip install numpy
!pip install opencv-python
# import the functionality
from sweetbean.sequence import sequence_to_image
# we can now create the image by providing additional arguments that are the labels of the images
sequence_to_image(stroop_block, durations=['600', '800', '200-500', '2500'])