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:

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.

Presenting stimuli by frames

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.

Presenting stimuli by frames

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.

Getting an early keypress

hardware.keyboard.Keyboard.getKeys()

Uses python-psychtoolbox lib and has some advantages:

Note

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

Getting an early keypress

hardware.keyboard.Keyboard.getKeys():

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

Getting an early keypress

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.

Getting an early keypress

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]

Practice 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…

Practice trials

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')

Practice trials

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: