I programmed an experiment where I track key presses and releases during the response period to make a dial move. Basically, it starts updating the positions of two icons on a circle when a button is pressed, and stops doing this when you release that button (which is the ‘final’ position response of the subject). I used the new psychopy.hardware.keyboard for this.
See full code below. The dial starts turning after a keypress, immediately some triggers are sent to the EEG and eye-tracker, and then the code enters a while loop to track the key release:
while key_release == [] and count < maxTurn:
In this loop the positions are updated while the key has not been released yet and while a certain endpoint is not reached (count < maxTurn
).
Now to the issue: most of the times this works perfectly. But occasionally the key release seems to be missed. So you release the key, but the dial keeps turning until this endpoint is reached.
Any ideas why this happens?
def presentResponse(upperOrRight, trialType, condition):
kb.clearEvents()
triggerProbe = setCorrectTrigger(blockType = 'regular',
trialType = trialType,
condition = condition,
moment = 'probe') # defines the correct trigger
mywin.callOnFlip(portBioSemi.setData, triggerProbe) # send trigger to EEG on flip
mywin.callOnFlip(tracker.send_message, 'trig' + str(triggerProbe)) # send trigger to eye-tracker on flip
if upperOrRight == 0: # upper trial
createSemicircle.pos = upper_semiCircle
createSemicircle.ori = 0
turnUpper.pos = upper_turnUpper
turnLower.pos = upper_turnLower
elif upperOrRight == 1: # right trial
createSemicircle.pos = right_semiCircle
createSemicircle.ori = -90
turnUpper.pos = right_turnUpper
turnLower.pos = right_turnLower
pause = False
stop = False
respTime = []
key_release = []
clockws = False
counterclockws = False
count = 0 # positions not updated yet
responseCircle.setAutoDraw(True)
createSemicircle.setAutoDraw(True)
turnLower.setAutoDraw(True)
turnUpper.setAutoDraw(True)
probe.setAutoDraw(True)
startTime = time.time()
mywin.flip()
core.wait(2/monitorHZ) # two frames, 0.008 s
portBioSemi.setData(0) # turn off probe trigger
key_press = event.waitKeys(keyList = ['z', 'm', 'q', 'escape']) # wait for key press
if 'z' in key_press: # if z, turn to left
respTime = time.time()
triggerResp = setCorrectTrigger(blockType = 'regular',
trialType = trialType,
condition = condition,
moment = 'leftpress')
counterclockws = True
portBioSemi.setData(triggerResp) #count 1
#tracker.send_message('trig' + str(triggerResp))
core.wait(2/monitorHZ) # two frames, 0.008 s
portBioSemi.setData(0) # turn off probe trigger
while key_release == [] and count < maxTurn:
key_release = kb.getKeys(keyList = ['z'], waitRelease = True, clear = False)
positions = turnPositionsCircle(turnUpper.pos, turnLower.pos, thisTurn = -radStep)
turnUpper.pos = positions[0]
turnLower.pos = positions[1]
count += 1 # one step updated
mywin.flip()
endTime = time.time()
elif 'm' in key_press: # if m turn right
respTime = time.time()
triggerResp = setCorrectTrigger(blockType = 'regular',
trialType = trialType,
condition = condition,
moment = 'rightpress')
clockws = True
portBioSemi.setData(triggerResp) #count 1
tracker.send_message('trig' + str(triggerResp))
core.wait(2/monitorHZ) # two frames, 0.008 s
portBioSemi.setData(0) # turn off probe trigger
while key_release == [] and count < maxTurn:
key_release = kb.getKeys(keyList = ['m'], waitRelease = True, clear = False)
positions = turnPositionsCircle(turnUpper.pos, turnLower.pos, thisTurn = radStep)
turnUpper.pos = positions[0]
turnLower.pos = positions[1]
count += 1 # one step updated
mywin.flip()
endTime = time.time()
elif 'q' in key_press:
core.quit()
sys.exit()
elif 'escape' in key_press:
responseCircle.setAutoDraw(False)
createSemicircle.setAutoDraw(False)
turnLower.setAutoDraw(False)
turnUpper.setAutoDraw(False)
probe.setAutoDraw(False)
pauseText.draw()
mywin.flip()
key_pause = event.waitKeys(keyList = 'space')
respTime = 0
endTime = 0
if respTime != [] and endTime != []:
responseTime = respTime - startTime
responseTime *= 100
responseTime = round(responseTime)
responseDuration = endTime - respTime
responseDuration *=100
responseDuration = round(responseDuration)
responseCircle.setAutoDraw(False)
createSemicircle.setAutoDraw(False)
turnLower.setAutoDraw(False)
turnUpper.setAutoDraw(False)
probe.setAutoDraw(False)
return count, counterclockws, startTime, respTime, endTime, responseTime, responseDuration, triggerProbe, triggerResp```