In my experiment I would like to have pause after a key press. My necessity is to stop the experiment in any moment at the end of each trial if a problem occurs. To do this I created (within a loop) a routine with a trial followed by a routine with the pause.
First I Inizialize a Pause_check variable set to 0.
Pause_check = 0
Then, what I would like to do is to change the status of Pause_check during the trial routine.
To do this, in the trial routine I added this code (each frame).
if trial_key.status == STARTED:
if (len(theseKeys) > 0 and trial_key.keys == 'p'):
Pause_check = 1
where trial_key is a component in which āpā is an allowed key.
After the trial routine there is a Pause routine in which I put a Code component in the pause routine with the following code (each frame)
if Pause_check == 0:
continueRoutine=False
My problem is that the pause is not working. I presume that my mistake is in the check to create the Pause_check object.
Any hint on how to create this pause? (or where Iām wrong?)
When posting code, itās nice to format it so itās easier for us to read. You can surround code with three backticks (`) like this:
```python
(code here)
```
And it will be easier for us to read.
But to your question, one problem is that if you do this:
if Pause_check == 0:
continueRoutine = False
This wonāt pause your routine if youāre following psychopy customs, it will end it.
Also, thisā¦
trial_key.keys == 'p'
ā¦ is not doing what you think itās doing. ātheseKeysā is a list of keys that were pressed the last time the system checked for them, so could simply do this to see if āpā is in that list:
if 'p' in theseKeys:
So you simply want to pause the routine when they press āpā, and let them unpause it with āpā as well?
You have to understand that computers never really āpauseā, they are always active. Just like if youāre playing a childās āfreezeā game where everyone has to stand still, youāre always actively waiting for the āgoā signal, you donāt actually shut your brain off. To imitate a pause like a computer would you have to think more like this:
Do experiment stuff, check for āpā keypress
āpā has been pressed!
Keep actively checking for another āpā, and do nothing else
āpā has been pressed!
Back to experiment stuff.
So you want something like this:
continueRoutine = True
paused = False
while continueRoutine:
if trial_key.status == STARTED:
theseKeys = event.getKeys()
if 'p' in theseKeys:
if not paused:
paused = True
# the 'continue' statement will
# take us back to the top of the loop
continue
elif paused:
paused = False
# 'p' is not in theseKeys. If we're paused go to
# the top of the loop
elif paused:
continue
# Rest of the code for the routine starts here
I suspect that Daniel is correct in that the problem was that keys are returned as a list rather than as a single value.
But I think that otherwise Giorgio is on the right track. His logic is to have a āpauseā routine after the trial routine, but that pause routine will only run if āpā was pressed on the previous routine. i.e. if āpā wasnāt pushed, continueRoutine for this pause routine is set to False in its āBegin routineā tab, so that the pause routine doesnāt actually start on that iteration of the loop.
This is the recommended way to implement this sort of arrangement, but actually only works properly from the latest release of PsychoPy.
Danielās solution (to implement a āreal timeā pause within a routine) would likely work but could have all sorts of hard-to-foresee consequences. Builder experiments are fundamentally structured on a drawing loop that runs once on every screen refresh. Using code like this would break that structure (i.e. it will pause drawing to the screen and everything else). This means that Builder will lose control of screen re-drawing and break its ability to time stimuli by frame counting. So Iād suggest that Giorgio stick to his original arrangement in this case.
Ah yes! That makes more sense for an experiment. So after each trial, there would be another routine that would last for a certain amount of time (maybe showing a fixation stimulus or something), and pause could be implemented then but not during a trial, right? That would make more sense.
I think so. I guess Giorgio would have a keyboard component on that āpauseā routine so that it would end when a key is pressed, allowing the next iteration of the loop to proceed when the participant is ready.
Actually rereading your post Michael, I guess what I said in my comment would be different: if one were measuring reaction times, having to press a pause key within the trial would ruin that trial, though if itās only for emergencies I guess there would already be a problemā¦
Dear Daniel and Michael,
Thank you both for your help. I managed to achieve what I wanted adding this code in the trial routine (each frame):
''' check if a response is given and if it is p, set Pause_check to 1 '''
if trial_key.status == STARTED:
if (len(theseKeys) > 0 and 'p' in theseKeys):
Pause_check =1
In programming with a separate routine for the pause I actually followed some recommendations I think I found in the old psychopy forum.
Hello @Michael, Iām sorry to bring up a slightly old post, but itās been bugging me. Since my experiments as of yet havenāt had to worry about frame rates my understanding of the issue is not complete.
You said that the solution I suggested would mess up the frame count, so how could we avoid that? Would it simply be by always calling win.flip() before returning to the top of the loop?
When working in Builder rather than Coder, we sacrifice some control for ease of use. Part of that control is that Builder has authority over the screen drawing cycle. Fundamentally, Builder is structured entirely around the screen refresh cycle: it expects to update stimuli, check for responses, execute code components, and so on, on every screen refresh. It also does all its timing checks on that cycle. i.e. even if you are specifying that your stimuli should last a certain period of time rather than a certain number of frames, Builder is checking that time once per frame.
So in our code components, there are certain things we should never do, in order to allow Builder to keep ticking along on the screen refresh cycle (including, but not limited to):
(1) Donāt create āpauseā periods in which the screen wonāt be updated. For example, we can use event.getKeys() because it just makes an instantaneous check of the keyboard. But we should never use even'waitKeys(), as that pauses everything waiting for a keypress, and will break Builderās screen refresh cycle. We also need to avoid any loops that could last more than one screen refresh (e.g. embedding an event.getKeys() check within an infinite while loop).
(2) We should never call win.flip(). This will prevent anything happening until the next screen refresh, including any housekeeping that Builder needs to do during that period. So for example, if the code component was at the top, any stimuli below it would not be updated by Builder on that frame. And Iām not sure sure if Builder would even know it has missed a screen refresh, so its timing could then be thrown out. There would be all sorts of unpredictable effects. So let Builder carry out the one and only win.flip() on each cycle, so it keeps control of the cycle and we get to go along for the ride.
If you find you need more control than fitting into this arrangement provides, then it really is time to switch to Coder, where you have complete flexibility over what happens and when.
Make sense?
Your question is a good one, and Builder should probably provide some automated warnings if it detects win flip() or event.waitKeys() in a code component (checking for potentially long-lasting loops would be harder).