Pause for a sec before ending routine (WaitSecs for PsychoPy)

I have a code that has participants type in two letters, they display on the screen, and then the next routine begins (where they have to type in two more letters).

keysT1 = event.getKeys(keyList = ['q','w','e','r','t','y','u','i','o','p','a','s','d','f','g','h','j','k','l','z','x','c','v','b','n','m'])

if len(keysT1) :
    
    if len(textResp1_training.text) == 0 :
        
        textResp1_training.text = textResp1_training.text + keysT1[0]
    
    elif len(textResp1_training.text) == 1 :
        
        textResp1_training.text = textResp1_training.text + keysT1[0]

        continueRoutine = False    

However, the routine ends as soon as the second key is pressed, so the participant can’t see their second letter before it moves on. So I’m essentially looking for the PsychoPy version of PsychToolbox’s WaitSecs function. I also want to use a function that’s able to translate to JS easily, if possible (why I’m avoiding clock or core functions). I’ve tried:

#begin routine
endTime = 9999999

#each frame
#everything from first code...

    elif len(textResp1_training.text) == 1 :
        
        textResp1_training.text = textResp1_training.text + keysT1[0]

        endTime = t + .5

if t > endTime
    continueRoutine = False    

Which sort of works, but isn’t super reliable. I’m also not sure if t translates to JS. I’ve also tried inserting a static component (also tried with an invisible polygon) with the code:

#begin routine
startISI = 0

#each frame
#everything from first code...

    elif len(textResp1_training.text) == 1 :
        
        textResp1_training.text = textResp1_training.text + keysT1[0]

        startISI = 1

if ISI.status == Finished
    continueRoutine = False    

Then I put $startISI == 1 in the start of the ISI (and polygon) and .5s in the end time. But that’s not working because I’m not sure if .status works for static or polygon components. Anyone have an idea about how to do this? Thanks!

The approach of taking the current time and adding 0.5 is basically correct. But you say that it is unreliable - I would guess that it is because the code will still accept further key presses. That could be fixed by restructuring the code, but that will mean more to translate to JavaScript.

You can avoid some of the difficulties by splitting the task across two routines. Have the first one end immediately after the second key press. The next one then just has a fixed duration of 0.5 seconds. By re-displaying the text from the previous routine, the subject won’t see any difference. But you won’t be responding to keypresses in that second routine, so things should be very reliable.

In answer to your main question, yes, there is a core.wait() function in PsychoPy, but it should never be used in Builder experiments, as it will break its active drawing/response checking cycle.

Thanks for the response! I think there’s a bit of a delay after the keypress before it presents itself on the screen, which I think is why the time method is unreliable. I might just increase the time to +.7 or something. But does t translate as “current time” from PsychoPy to JS or am I going to have to have two separate codes in the builder? I have this routine copied four times with slight variations that I have to keep up with if I make changes in one of them (I am definitely prone to copy/paste errors), which is why I’m trying to avoid adding any more routines for the responses. But if that ends up being the best solution, I will.

That issue really needs to be fixed: there should be no such unreliability - it should all work like clockwork. If not, there is a problem with the code. e.g:

    elif len(textResp1_training.text) == 1 :

This could keep triggering and re-setting the end time for example. The code probably needs to be restructured so that it stops doing anything after two keypresses.

Is there a “stop listening” function?

Also, does t translate to js as current time?

Yes.

That’s not really how PsychoPy works. Rather than calling some function (to do nothing), you alter the logic of your code. e.g. What you could do is set a flag like this at the beginning of the routine:

keypresses_complete = False

and then incorporate that in your logic, like:

if not keypresses_complete:
    # check for keypresses.

When you have received two keypresses, set keypresses_complete = True

Ah, I see. Thank you! Not sure which of these to mark as the solution