Registering time of key release, when same key was pressed and held in previous routine

Hi

In my experiment I am trying to have participants press and hold ‘space’ to start, after which they progress to a ‘fixation’ routine with a variable time lenght after which a routine start where they have to press on of several keys depending on stimuli. In this routine I also want to record the time when ‘space’ is released as a measure of movement start time, but I can’t figure out how. Everything works except I can’t figure out how to register the key release, when the key wasn’t pressed in the same routine.

This is how I regiester key press and hold to progress to ‘fixation’ (in every frame tab):

if kb.getKeys(['space'], waitRelease=False, clear=False):
    continueRoutine=False

this is how I am attempting to register and save key release time (in every frame tab):

if kb.getKeys(['space'], waitRelease=True): 
    trials.addData("RT_release", myClock.getTime())

I don’t get any error messages, I just don’t get my key release time saved.
OS (e.g. Win10): Win10
PsychoPy version (e.g. 1.84.x): 2021.2.3
Standard Standalone? (y/n) y
**What are you trying to achieve?: register and save time of key release, which was pressed and held in a preceding routine.

I tried the approach you suggested in the attached super simple project and I get both the key press and release when in two different routines. Maybe something else in your project is interacting with the keyboard event handling?

hold_key.psyexp (10.6 KB)

Could you send a simple example where it is not working as expected?

Thank you

Rather than having continueRoutine=False being triggered by release, but instead adding a keyboard component waiting for another key press will stop the key release from being registered, see the attached example

hold_key_1.psyexp (15.1 KB)

But if i just use the same code to wait for another key to end routine rather than using a builder keyboard component, it works just fine in the example, but for some reason having the component in the routine will break it.
But I am not quite sure how to implement that in my experiment - maybe i can set it up such that the keyboard component only starts after key release? How might i do that?

Alright I think I have a work around for still using the keyboard component for anyone else running into this:
in the routine with key release, the keyboard component must start after key is released, for the key release to be registered. This can be achieved by the following
in begin routine tab: (this is needed as the keyboard component must have its start condition defined at routine start)

myClock.reset()
kbStart = myClock.getTime() + 100

in the each frame tab: (Here I have also added code to save reaction time for releasing key, but you only need the kbStart command)

if defaultKeyboard.getKeys(['space'], waitRelease=True): 
    RTrelease = myClock.getTime()
    print("Key released")
    trials.addData("RT_release", round(RTrelease,3))
    kbStart = myClock.getTime()

then you just put $kbStart in keyboard component start input.

Another good solution . :wink:

The reason why using the buiilder Keyboard component can be problematic in this type of situation is because when a keyboard component starts it clears the complete keyboard event buffer. In the compiled python code for the hold_key_1 project:

if key_resp.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
    # .....
    win.callOnFlip(key_resp.clock.reset)  # t=0 on next screen flip
    win.callOnFlip(key_resp.clearEvents, eventType='keyboard')  # clear events on next screen flip

This will clear all events from the keyboard event bufffer, not just the ones that they keyboard component is checking for. This explains why using a keyboard component that was checking for a ‘b’ key press was still impacting the detection of the ‘space’ release.

Unchecking the keyboard component → Data → Discard Previous option removes the full clear of the keyboard event buffer at the start of the component, so that may also be an option.