Hi everybody,
I’m new to python so I apologize in advance if my question is trivial.
When I present the probe for my task, I want the response to be made with two key presses. I want the two key presses to force the end of the routine, but also if a time limit is reached the routine has to finish.
In other words, I’d want the same as event.waitKeys(), but with two key presses.
I tried using core.wait() like this:
core.wait(5)
x=event.getKeys('v, b, n, m')
if len(x)>=2:
continueRoutine=False
elif len(x)<2
continueRoutine=True
But it always waits the 5 seconds, even with two key presses. I guess core.wait() is not “overridden” by the ContinueRoutine=False.
I also tried to use a while loop and a timer:
timer=core.CountdownTimer(5)
while timer.getTime()>0:
x=event.getKeys('v, b, n, m')
if len(x)<2:
continueRoutine=True
elif len(x)>=2:
continueRoutine=False
But it’s not working. I guess it depends on the timing and order in which the operations are carried out, because if I try to print x I get many empty lists.
This is the usual case of computers frustratingly doing exactly what you tell them
In the first case, you ask to wait for 5 s and only then check for any key presses which may have occurred. So naturally, this will always lead to a 5 second delay before any responses can be dealt with.
So your instinct of checking more frequently within a loop is the correct one. The issue this creates is the opposite: the checking is now so fast that it is unlikely that you will ever detect a pair of keys simultaneously. i.e. the first key will be detected, but the second key will likely not be detected until a subsequent iteration. With frequent checking like this, even if the subject pushes two keys, your code will register them in two separate single-element lists. Hence, the length of the list will hardly ever be > 1.
So you need to add some extra logic. Set a flag (e.g. first_key_detected) to be False initially and True when the first key is found. Only quit the routine when both a key press is detected and first_key_detected == True.
Hi Michael,
thank you for your kind and very clear response. I tried to implement your suggestion but I didn’t manage to make it work. My problem is that I get again an empty list for every iteration in which it checks for a key press. Also, psychopy seems to freeze for a few seconds.
timer=core.CountdownTimer(5)
first_key_detected=False
while timer.getTime()>0:
x=event.getKeys('v, b, n, m')
if x!=[]
first_key_detected=True
if len(x)<0 and first_key_detected==True:
continueRoutine=False
else:
continueRoutine=True
By many trial and errors, I found an alternative and very simple solution:
xTimer=core.Clock()
first_key_detected=event.waitKeys(x_dur, 'v, b, n, m', timeStamped=xTimer)
print first_key_detected
second_key_detected=event.waitKeys(x_dur,'v, b, n, m', timeStamped=xTimer)
print second_key_detected
x=first_key_detected+second_key_detected
print x
I didn’t even try this solution earlier because I expected the first event.waitKeys to skip the routine, but this is not the case. It behaves exactly as I wanted and I get a list of two tuples (pressed key and corresponding time stamp).
Nevertheless, I think the solution you suggested might be very useful in other contexts, so I would really appreciate if you could point out what I was doing wrong when trying to implement it!
Just to check: I’ve been assuming that this experiment is entirely your own code.
If using Code components in Builder, we can’t use waitKeys() or loops, as Builder is structured around a screen refresh drawing loop that we can’t interrupt with code that will take longer than one screen refresh.