In this tutorial, you will get to know how to use the PsychoPy function TrialHandler to create trials and correct responses to your targets in these trials. PsychoPy is an application for creating experiments for Psychology experiments. The application is written in Python, an easy programming language to learn. You can learn more about PsychoPy in my two previous posts (Free and Useful software – PsychoPy and Python apps and libraries…”).

TrialHandler Tutorial

We start by importing data from PsychoPy. In the data, we found the routine we want to use (e.g., TrialHandler):

Preparatory Work

First, we start out by importing data, as previously mentioned.

from psychopy import data
Code language: Python (python)

We start with a simple list of trials. In this example, the subjects are going to categorize digits as odd or even (like in a cross-modal oddball task). Here we will create the target list with digits from 1-8:

visual_targets = [digit for digit in xrange(1,9)]
Code language: Python (python)

Note that you can create the same list using a for loop::

visual_targets = [] for digit in range(1, 9): visual_targets.append(digit)

Let’s create a new list containing a dictionary for each trial. Each dictionary (i.e., trial) contain the keys ‘Target’ and ‘CorrectResponse’. This is where we store each Target and its correct response. In the example, the response keys can be ‘z’ and ‘x’ (odd and even, respectively)
We start to loop through our list of targets,

argets_responses = [] for target in visual_targets: if target %2 == 0: correct_response = 'x' else: correct_response = 'z' targets_responses.append({'Target':target, 'CorrectResponse':correct_response})
Code language: Python (python)

TrialHandler

Now that we have our list with the targets and correct responses, we can use that list with PsychoPy’s TrialHandler. In our example, we are going to randomize our targets and present them 160 times

trials = data.TrialHandler(targets_responses,20, method='random')
Code language: Python (python)

We also want to record what the subjects responded if a correct response (Accuracy) was given:

trials.data.addDataType('Response') trials.data.addDataType('Accuracy')
Code language: Python (python)

Window, stimuli, & timing

When we run the experiment, we can just do a for-loop. However, we will create a window first (we need somewhere to present our targets).
Therefore, we need to import visuals and create a window. Typically, you would import everything at the beginning of your script.

from psychopy import visual experiment_window = visual.Window(size=(800,600),winType='pyglet',fullscr=False, screen=0, monitor='testMonitor', color="black", colorSpace='rgb')
Code language: Python (python)

We also need to create an object for the text stimuli. We use the routine TextStim for this:

screen_text = visual.TextStim(experiment_window,text=None, alignHoriz="center", color = 'white')
Code language: JavaScript (javascript)

We are almost there… However, we need to add timing for the stimuli. We use Clock from the core for this and create a trial time. Furthermore, we use events to collect responses from the keyboard.

from psychopy import core, event trial_timer = core.Clock()
Code language: Python (python)

Presenting stimuli

We are now ready to start our experiment loop. TrialHandler makes it possible to loop through each trial we created with it.
At the beginning of the loop, we set the current_time to zero, trial_still_running to True, and reset the trial_timer. This is done to present our target for 400ms after a 400ms fixation cross. The target is followed by a response window of 1000ms in which the fixation cross is presented again.  In the loop, the response will be collected in a list (i.e., “responded”). The first item of this list is controlled against the correct response (i.e., trial[‘CorrectResponse’]).

for trial in trials: current_time = 0 trial_still_running = True trial_timer.reset() while trial_still_running: current_time = trial_timer.getTime() if current_time <=.4: screen_text.setText('+') screen_text.draw() elif current_time >= .4 and current_time <=.8: screen_text.setText(trial['Target']) screen_text.draw() elif current_time >= .8 and current_time <=1.8: screen_text.setText('+') screen_text.draw() responded = event.getKeys() elif responded: if trial['CorrectResponse'] == responded[0]: accuracy = 1 else: accuracy = 0 elif current_time >= 1.8: if not responded: accuracy = 0 trial_still_running = False experiment_window.flip()
Code language: PHP (php)

Here’s a snippet of the experiment we just created:

  • Save

We end by closing the window and quitting:

experiment_window.close() core.quit()
Code language: Python (python)

Data also contains routines for saving data, but I have not included that in the above script. However, if you want to store your data, add the following code at the end of the for-loop:

trials.data.add('Accuracy', accuracy) trials.data.add('Response', responded[0])
Code language: Python (python)

It is also pretty easy to save your data as an Excel-fie (e.g., .csv or .xlsx):

trials.saveAsExcel(fileName='data.csv', sheetName = 'rawData', stimOut=[], dataOut=['all_raw'])
Code language: Python (python)

Note that if the timing is important for your experiment, it is better to control stimulus timing by presenting them for a specified number of frames instead (see here for more information).

If you want to see a more complete example of a task written in Python and PsychoPy, look at my Sustained Attention to Response Task (SART). In the SART, I randomize the stimuli with my method, however. That is, if you need randomization with constraints, you might need to do that before using TrialHandler and, also, use “method=’sequential'” instead.

Finally, I uploaded the complete script, including data saving, to pastebin. Hopefully, this tutorial helped you to understand how to use TrialHandler. Please let me know what you think or if something does not work as expected.

More Python Resources

Here are some more Python resources you might find useful:

  • Save
Share via
Copy link
Powered by Social Snap