psychopy.org | Reference | Downloads | Github

Getting frame-accurate timings for keypresses

Hello everyone,

I’m on Windows 10, using PsychoPy 3.0.0.
I’m trying to code a simple experiment. A square is shown on the screen, for X number of frames, every Y number of frames. The goal is to press a button when the square is shown on the screen, not before or after.

Right now the code looks like this:

# import modules
from psychopy import visual, event, core

# create a visual window:
win = visual.Window(
    size = (800,600),
    fullscr=False, color=(-1,-1,-1))

winFrames = 60 # your screen framerate
screenRatio = win.size[1]/win.size[0]

# draw square
squareSideL = 0.3
graySquare = visual.Rect(win, width=squareSideL*screenRatio, height=squareSideL,
    lineColor=(0,0,0), fillColor=(0,0,0))

# draw feedback dot
feedback = visual.Circle(win, units='pix', radius=10, edges=90,
    fillColor=(0,0,0), lineColor=(-1,-1,-1))

# stimuli timings
ISI = 1.3 # in seconds
ISIframes = int(ISI*winFrames) # in frames
squareTime = 0.15 # in seconds
squareTimeFrames = int(squareTime*winFrames) # in frames
feedbackISI = 0.3 # in seconds
feedbackISIframes = int(feedbackISI*winFrames) # in frames
feedbTime = 0.1 # in seconds
feedbTimeFrames = int(feedbTime*winFrames) # in frames

# initialise variables
getResp = False

while not event.getKeys(keyList=['escape']):
    for frameN in range(ISIframes):
        if feedbackISIframes < frameN < feedbTimeFrames + feedbackISIframes:
            feedback.draw() # draw feedback
        if ISIframes - squareTimeFrames <= frameN < ISIframes: # critical time frame to draw stimulus and collect responses
            graySquare.draw()
            getResp = event.getKeys(keyList=['space'], timeStamped=True) # get keyboard response
        if getResp: # if we got a response in the correct timeframe... 
            feedback.fillColor=(-1, 1, -1) # ... the feedback will be green
        else:
            feedback.fillColor=(1, -1, -1) # ... if not it will be red
        win.flip()

This kind of works to a certain degree, in the sense that I am collecting keyboard responses only when I’m drawing the square on the screen. Nevertheless there seem to be many cases in which I seem to be pressing at the right moment, but the keys don’t seem to register. Can this be due to the standard hardware/keyboard timing inaccuracies?

The second issue is that I would like to be able to record any keypresses happening during the trial, even if they happen when the square is not drawn. For this I would have to put the event.getKeys one level above in the loop, but then how can I check if a keypress happens when the square is drawn? I would like to use frames to be as accurate as possible, and avoid using clocks.

I would be grateful if anyone had an on how to solve any of these two problems!