psychopy.org | Reference | Downloads | Github

Key presses are not recording properly

If this template helps then use it. If not then just delete and start from scratch.

OS (e.g. Win10): MacOS Big Sur
PsychoPy version (e.g. 1.84.x): 2020.2.10
Standard Standalone? (y/n) If not then what?: y
What are you trying to achieve?:
I am trying to collect responses in my experiment. Our visual stimulus is presented as a sequence of images so it is perceived as a drifting grating. This means in the routine each image is only presented for a small fraction of a second (0.1s). As the images are being presented I am collecting a keyboard response. Everything seems to be working, but I have noticed that not every response is being recorded. The way I verified this is to have every keypress print out and I have noticed that sometimes I have to press the key 2-3 times really fast before the press is recorded. Is this the case because the time window is so short (0.1s). If so is there a way to get around this?

Presenting multiple images in rapid succession can indeed cause performance issues: it can take a non-negligible amount of time to load images from disk and apply them to a stimulus.

Is there a reason why you aren’t able to use the grating stimulus to achieve what you want, rather than presenting a series of pre-generated images? In fact this (presenting dynamically controllable gratings) was the initial impetus for Jon Peirce to create PsychoPy in the first place way back in the day - this was one of its first features.

use event.getKeys() in code or remove the option to clear the keyboard buffer in your keyboard response.

Or present all your images in a single routine so your keyboard response can span the whole sequence.

Our experiment will be presented in pavlovia and so we have to use pre-generated images rather than the grating stimulus built into builder.

I am fairly new to PsychoPy I am not sure how I would use event.getKeys() in code and if this would be compatible with Pavlovia. Also is there a way to clear the keyboard using the keyboard component?

All the images are currently presented in one routine that loops through a CSV file with the names of the images. Since this is the case the timing of the image and the timing of the keyboard have to be the same.

Ahh. I know ways to optimise a rapid image presentation task like this to run locally using Python, but am not familiar enough with the online environment to venture into offering advice there.

One the keyboard component, there is a checkbox called discard previous. I don’t think you want it ticked.

However, here’s some sample Each Frame code from one of my experiments, which you can try out here: https://run.pavlovia.org/Wake/change-detection-rsvp:

if drawn == nObjects*2+2:
    continueRoutine=False
elif drawn > nObjects+1:
    if hidden==1 and myClock.getTime() > gapTime:
        pic[drawn-nObjects-2].setAutoDraw(True)
        print('waxon',drawn,'t',t)
        hidden=0
        myClock.reset()
    elif hidden==0 and myClock.getTime() > frameSpeed:
        pic[drawn-nObjects-2].setAutoDraw(False)
        print('waxoff',drawn,'t',t)
        drawn+=1
        hidden=1
        myClock.reset()
elif drawn == nObjects+1:
    if myClock.getTime() > maskTime:
        imageNoise.setAutoDraw(False)
        drawn+=1
        hidden=1
        myClock.reset()
elif drawn == nObjects:
    imageNoise.setAutoDraw(True)
    drawn+=1
    print('drawn2',drawn,'t',t)
    if thisCondition[1]==1:
        shuffle(thisOrder)
        pic[thisOrder[0]].fillColor=colours[thisOrder[1]][1]
        pic[thisOrder[1]].fillColor=colours[thisOrder[0]][1]
        pic[thisOrder[0]].lineColor=colours[thisOrder[1]][1]
        pic[thisOrder[1]].lineColor=colours[thisOrder[0]][1]
        thisExp.addData('Swap1',thisOrder[0])
        thisExp.addData('Swap2',thisOrder[1])
        print('Swap1',thisOrder[0])
        print('Swap2',thisOrder[1])
    if thisCondition[0]==1:
        shuffle(thisOrder)
    else:
        thisOrder=[0,1,2,3,4]
    print('Order',thisOrder)
    thisExp.addData('Order',thisOrder)
    myClock.reset()
elif hidden==1 and myClock.getTime() > gapTime:
    pic[drawn].setAutoDraw(True)
    print('waxon',drawn,'t',t)
    hidden=0
    myClock.reset()
elif hidden==0 and myClock.getTime() > frameSpeed:
    pic[drawn].setAutoDraw(False)
    print('waxoff',drawn,'t',t)
    drawn+=1
    hidden=1
    myClock.reset()

This uses an array of polygon objects created in Begin Routine

shuffle(shapes)
shuffle(colours)
pic=[]
for Idx in range(nObjects):
        pic.append(visual.ShapeStim(
        win=win,
        fillColor=colours[Idx][1],
        lineColor=colours[Idx][1],
        vertices=shapes[Idx],
        pos = (0,0),
        size=scale
        ))

Alternatively, you could have load the images into a list before the trial using my interleaved list principle and then .setImage at intervals in the Each Frame code.