| Reference | Downloads | Github

Pausing in a loop and continuing from where it was paused

Win 10
PsychoPy3: 3.0.0

Hi everyone. I am pretty new in coding, and trying to build an experiment by using the builder.
I am trying to build a routine in which participants will watch lines on the screen and hear sound stimuli. While doing so, I want them to stop the routine if they remember something (this is an involuntary memory task) by pressing a key, and then continue without messing up with the timing and the rest of the stimuli.

I have used this code:

pauseKey = event.getKeys()
txt = visual.TextStim(win,text='paused, press R to resume')
txt2 = visual.TextStim(win,text='press P to pause')
if 'p' in pauseKey:
  td = win._toDraw
  win._toDraw = []  # hides whatever was being auto-drawn
  while not event.getKeys(keyList=['r']):
  win._toDraw = td  # restore auto-draw
  pauseKey = NOT_STARTED
  pauseKey = []  

if 'escape' in pauseKey:

It works in terms of pausing, but it actually continues to run at the background (without showing me of course). How can I achieve pausing without the code running at the background?

(Sorry if I’m messing up with the terms here…:slight_smile:

Can you explain what you mean by that? Most particularly, what is “it” referring to?

EDIT: now that I think about it, I can make a guess as below:

It looks like what you are doing above is (quite cleverly) interrupting the drawing loop to make everything disappear. The reason I wouldn’t normally advise having while loops and win.flip() in your own custom code, though, is precisely because it will interrupt Builder’s normal event loop cycle and timing.

So I think if you want to do this, you would have to also pause all of the relevant timers that otherwise will continue to run in the background. e.g. let’s say that you pause the routine at t = 1.0 s and un-pause it 2 seconds later. I guess you want things to continue as if the timeline had been paused, so that current time re-starts at 1.0 seconds. But as the trial and experiment clocks continue to run in the background, the time will be the actual elapsed time of 3.0 seconds.

So take a look through a Builder-generated script and watch what timers it uses (the routine-specific one and potentially I think what is called the globalClock instance). Note that some count up, and some count down. I think when you enter the pause period, you should store the current timer values, and then when you finish the pause, set them back to those times:

I’d normally advise people not to muck around with this sort of thing in Builder, but it looks like you know what you are doing :+1:

But test, test, test, to make sure that nothing unexpected is happening to the experiment timing as a result.

I think I kind of understand what you are suggesting. But the problem is the participant will decide the duration of the pause period, so I cannot precisely assess a time period for pauses. In the coding script, the pause looks like this but I don’t know where I need to change:

pause updates

    if t >= 0.0 and pause.status == NOT_STARTED:
        # keep track of start time/frame for later
        pause.tStart = t
        pause.frameNStart = frameN  # exact frame index
        pause.status = STARTED
        # keyboard checking is just starting
        win.callOnFlip(pause.clock.reset)  # t=0 on next screen flip
    frameRemains = 0.0 + 1- win.monitorFramePeriod * 0.75  # most of one frame period left
    if pause.status == STARTED and t >= frameRemains:
        pause.status = STOPPED
    if pause.status == STARTED:
        theseKeys = event.getKeys(keyList=['p', 'r'])
        # check for quit:
        if "escape" in theseKeys:
            endExpNow = True
        if len(theseKeys) > 0:  # at least one key was pressed
            pause.keys = theseKeys[-1]  # just the last key pressed
            pause.rt = pause.clock.getTime()