psychopy.org | Reference | Downloads | Github

Pause and resume

Hello,
I need some help to “pause” and “resume” a trial at any time?
In my experiment, each trial consists of a sequence of 30 images, each of the images being presented for 500 ms. I would like the participants to be able to pause at any time (to give an oral answer), and then to resume the sequence, starting again at the next image. Each sequence of 30 images must go on till the end of the trial, and the participants must be able to pause and resume at any time of the sequence. I just need to identify on which images participants pressed the pause key, that’s why I created a keyboard component for each image, to identify when key was pressed.
I don’t know much about coding, and I don’t need to use it very often, so I found a code to pause and resume:

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

It enables to pause and resume, but the problem is that during the pause, the sequence keeps going on (invisibly of course) and as a consequence, when I press “resume”, it starts again several images later (according to the duration of the pause). Yet I need it to start again on the next image of the sequence.

Thank you very much for your help!

Could you read this post and edit yours Please surround python code with backticks

thanks

  1. Only create the txt stimulus once, at the start of the experiment (as it has constant content, and creating text stimuli has a time penalty).

  2. We can’t diagnose the problem here as we can’t see this code in the context of your wider drawing loop. My guess is that you have defined your stimulus drawing in terms of time, and are relying on auto draw. I think it might be best to switch to explicitly drawing each stimulus and control the duration on screen by explicitly counting each frame (e.g 30 frames at 60 Hz = 500 ms) rather than using a timeline. That way, if drawing the stimuli is interrupted, when you restart, you know how many frames remain for that particular stimulus. Look at some of the demos under the Demo menu in Coder, named something like “draw by frames”.

Hello,

Thank you very much for your answer. You are right, my stimuli are drawn in terms of time, and the fact that they are relying on auto-draw is most probably the problem here. Theoretically, what I would like to achieve seems quite easy. But the thing is that I don’t know much about code, and I would like to know if there would be an easy way to achieve what you explain.

To make it simple, each trial consists of 30 consecutive images. For each trials, I would like to do that:
Image 1 appears, then:

  • If nothing happens within 500 ms: image 1 is replaced by image 2
  • If space bar is pressed within 500 ms: image 1 is paused, until space bar is pressed again, then image 1 is replaced by image 2

And so on, until image 30. Space bar (and pauses) can occur as many times as wanted during the trial.
The only information I need to record is for which images space bar was pressed. I don’t need precise reaction times, as I just need to know during which images space bar occurred.

Thanks again for your precious help,

Sab

Something like this (where images is a list of 30 pre-created image stimuli):

image_presses = [] # keep track of which images were paused

for trial in trials: # on each trial,
    for image in images: # draw 30 images
        for frame in range(30): # for 30 frames each (= 500 ms at 60 Hz)
            # draw the stimulus:
            image.draw()
            win.flip()

            # check whether to pause
            if event.getKeys('space'):
                paused = True # stop right here
                image_presses.append(frame) # store the current image number 
                # or could append(image.image) to store the actual image name.

                while paused:
                    if event.getKeys('space'):
                       paused = False
                    else:
                        # need to let the rest of system time to do stuff in this tight loop 
                        time.sleep(0.001) # 1 ms per iteration should do
                else:
                    # when exiting the while loop, also terminate the enclosing 500 ms 
                    # for loop and go on to the next image:
                    break 

Note that as this code is based on drawing frames rather than keeping time, you can be paused indefinitely without issues.