Improvements

In this session we’ll work through ways of improving the task we made earlier.

Improvements

Previously we mentioned a few problems that we will work on in this session:

  • we should time our stimulus presentations by number of frames, for brief stimuli, not by a clock

  • a very fast response gets ignored because we only start looking at the keyboard after the probe has gone

  • we don’t have any practice trials (to learn that the cue is ‘informative’)

Presenting stimuli by frames

Previously we used the:

probe.draw()
win.flip()

This is fine, but as soon as you flip the window again, the stimulus will disappear. setAutoDraw() allows you to continue drawing on every frame.

We could draw something on a set number of frames using a ‘for’ loop:

for frameN in range(5):
    probe.setAutoDraw(True)
    win.flip()
probe.setAutoDraw(False)

This should look pretty similar when we run it. Exercise: Reset our stimulus timings by adapting our ‘info’ dictionary.

We could use several for loops OR we could use one large for loop with ‘if’ statements:

for frameN in range(totalFrames):
    if frameN<info['fixTime']:
        fixation.setAutoDraw(True)
    elif info['fixTime']<=frameN<info['fixTime']+info['cueTime']:
        fixation.setAutoDraw(False)
        cue.setAutoDraw(True)
    else:
        cue.setAutoDraw(False)
        probe.setAutoDraw(True)
    win.flip()
probe.setAutoDraw(False)
win.flip()

Getting an early keypress

For more precise keypress measurements, we can use the Keyboard class rather than the event module.

hardware.keyboard.Keyboard.getKeys()

Uses python-psychtoolbox lib and has some advantages:

  • polling is performed and timestamped asynchronously with the main thread (times relate to when the key was pressed, not when the call was made)

  • it’s faster

  • can detect the KeyUp events (enabling) keypress duration

  • on Linux and Mac you can distinguish between different keyboard devices (see getKeyboards())

Note

On 32 bit installations and Python2 older psychopy.event.getKeys() is used.

hardware.keyboard.Keyboard.getKeys():

#at the start of your script
from psychopy.hardware import keyboard
kb = keyboard.Keyboard()

We can reset this clock and get keypresses using:

kb.clock.reset()
keys = kb.getKeys(keyList = ['left','right','escape'])

If a response has not been made by the end of the trial time wait for a key press:

while not keys:
    keys =  kb.getKeys(keyList = ['left','right','escape'],
                    clear=True)
resp = keys[0].name
rt = keys[0].rt

This will function much like our old code… we need to position the first call to getKeys to make a response earlier.

If we get negative rts… this is because a response is logged before the clock is reset. We might need to clear the event buffer:

elif frameN==info['fixTime']+info['cueTime']:
    #reset clock and listen for keypress
    kb.clearEvents()
    kb.clock.reset()
    keys = kb.getKeys(keyList = ['left', 'right', 'escape'])

Practice trials

We want a practice block, in which one trial for each condition is presented. For this, we can use our Experiment Handler:

    #Create two sets of trial handlers
    trials = data.TrialHandler(trialList=conditions, nReps=1, name='mainBlock')
pracTrials = data.TrialHandler(trialList=conditions, nReps=1, name='practiceBlock')
outerLoop = [pracTrials, trials]

Then, put our trial loop inside a block loop (indent the whole block), create the trial list at the start of the block and add it to the experiment handler:

for trials in outerLoop:
    thisExp.addLoop(trials)
    for trial in trials:
        print(trials.name)#check this is the set of trials we were expecting

Now lets run that and look at the output…

We can add a message to warn participants when they will start the next block:

Continue = visual.TextStim(win,
        units='norm', height = 0.1,
        pos=(0, 0), text='That was the end of the practice, are you ready to continue?\nPress the left arrow if the circle is on the left\n press the right arrow if it is on the right\nPress space to start',
        color='White')

Solution present the text stimuli in the relevant places:

#Before your block loop
Instructions.draw()
win.flip()
event.waitKeys()

for trials in outerLoop:
thisExp.addLoop(trials)
if trials.name=='mainTrials'
        Continue.draw()
            win.flip()
            event.waitKeys()

Further improvements

Exercises:

  • Add trial-by-trial feedback on correctness and RT

  • End the practice trials early if the participant scores 5 correct in a row


Back to top