Hi community,
I just downloaded psychopy 3.1.5 on my laptop (dell XPS 15) running windows 10 and was playing with the new keyboard functions from Psychtoolbox when I discovered something strange. It looks like the pressed keys remain in the buffer despite attempts to clear them via clear = True and clearEvents().
Consider the following piece of code that implements a lexical decision task:
from psychopy import core, data, event, visual, gui
import numpy as np
import os
from psychopy.hardware import keyboard
words_list = np.array(['brother', 'tennis', 'fishing'], dtype='str')
nonwords_list = np.array(['eotif', 'aptas', 'tubai'], dtype='str')
stimuli_list = np.concatenate((words_list , nonwords_list))
win = visual.Window(fullscr=True,
color=[255, 255, 255], colorSpace='rgb255', units='cm')
police = 'Consolas'
win.setMouseVisible(False)
height_letters = 1.
#template stimulus
target = visual.TextStim(win=win, ori=0,
text=u'template',
font=police,
pos=[0,0],
color=[0,0,0], colorSpace=u'rgb255', height = height_letters)
instr = visual.TextStim(win=win,
ori=0.0,#orientation
text =u"Press 'f' key if stimulus is a word, press 'j' key otherwise. Press spacebar key to start",
font=police,
pos=[0, 0],
height=.7,
color=[0,0,0],
colorSpace='rgb255')
# initialize keyboards
resp = keyboard.Keyboard()
defaultKeyboard = keyboard.Keyboard()#for escaping only
ITI = 1. #intertrial interval
#present instructions
while True:
theseKeys = resp.getKeys(keyList=['space'], waitRelease=False)
if len(theseKeys):
break
if defaultKeyboard.getKeys(keyList=["escape"], waitRelease=False):
core.quit()
instr.draw()
win.flip()
win.flip()#clear screen
core.wait(2)
#present stimuli
for i in stimuli_list:
if i in words_list:
correct_resp = 'f'
if i in nonwords_list:
correct_resp = 'j'
target.setText(text = i)
win.callOnFlip(resp.clock.reset)
kb_delay = 0
resp.clearEvents()
while True:
if kb_delay==1:#check keyboard buffer after first draw of stimulus and clock reset
theseKeys = resp.getKeys(keyList=['f', 'j'], waitRelease=False)
if len(theseKeys):
theseKeys = theseKeys[0]
key_pressed = theseKeys.name
RT = theseKeys.rt
break
if defaultKeyboard.getKeys(keyList=["escape"], waitRelease=False):
core.quit()
target.draw()
win.flip()
if kb_delay == 0:
kb_delay = 1
win.flip()#clear screen
core.wait(ITI)
#Shutting down:
win.close()
core.quit()
When I press ‘f’ or ‘j’ in the intertrial interval, the next stimulus is skipped, suggesting that the key stays in the buffer despite the call to resp.clearEvents(). I wonder if it could due to an incompatibility between laptop’s built-in keyboard and the USB HID library in C. I would be very grateful if anyone could provide an explanation for this issue.
Below are details of my built-in keyboard (output of keyboard.getKeyboards())
[{'usagePageValue': 1.0, 'usageValue': 6.0, 'usageName': 'slave keyboard', 'index': 0.0, 'transport': 'Clavier', 'vendorID': None, 'productID': -1.0, 'version': None, 'manufacturer': None, 'product': 'Clavier', 'serialNumber': None, 'locationID': -1.0, 'interfaceID': -1.0, 'totalElements': 0.0, 'features': 0.0, 'inputs': 0.0, 'outputs': 0.0, 'collections': 0.0, 'axes': 0.0, 'buttons': 0.0, 'hats': 0.0, 'sliders': 0.0, 'dials': 0.0, 'wheels': 0.0, 'touchDeviceType': -1.0, 'maxTouchpoints': -1.0}]
EDIT: the problem remains when I use a USB-connected keyboard.
The new keyboard, while super-fast, is pretty complicated. We’ve now got multiple levels of buffer and check, which has caused this issue, but your fix looks right to me. In this case the keypress was still on the device buffer while we were only clearing our own software buffer.