psychopy.org | Reference | Downloads | Github

event.waitKeys() causing freezing issues

Hello,

I developed an experiment script that is being used by both our lab and another lab. In the other lab’s setup, they have been experiencing seemingly random freezes on calls to event.waitKeys(). The freezes occur on anywhere from 10-50% of the runs, and do not follow a consistent pattern. The freezes also never give an error code, which has made this problem difficult to diagnose.

When the program freezes, the CPU spikes to 100% usage, and the program will not respond until forced to quit. We determined that this is likely not a memory leak problem, as it can occur on the very first run of a session and does not increase in frequency throughout a session. We also used Activity Monitor to track memory usage, and did not notice a notable increase during the runs/sessions.

The freezes occur on several (but not all) machines that we tested on. The main computer that will be used to run the program is a Macbook Pro laptop, as well as a Mac mini, both of which exhibit the freezing problem. In my home lab, I have not been able to replicate the freezing issue on either a Mac or PC.

The freezing stops when I replace the event.waitKeys() with core.wait(). This isn’t a real solution for us however, because we need the event.waitKeys() to help sync the program timing with our MRI, using the TTL pulses to trigger the start of the program (the TTL pulses are either a ‘t’ or a ‘5’ depending on the setup).

Does anybody know what could be causing this? Any help is greatly appreciated!

Here’s some sample code from the script in which the freezing occurs:

if calibrate_targ:
    calib_x = [l_marg, 0, r_marg, 0]
    calib_y = [0, t_marg, 0, b_marg]
    calib_text = 'You will now be presented with the target so that you will have an idea of what the image looks like in your peripheral vision. Please press %s to indicate that you have seen the target in each location. Press %s to begin.' % (response_key, response_key)
    inst_text.text = calib_text
    inst_text.draw()
    targ_image.image = image_fns[targ]
    win.flip()
    event.waitKeys(keyList = [response_key], clearEvents = True)
    targ_image.draw()
    win.flip()
    event.waitKeys(keyList = [response_key], clearEvents = True)
    for c in list(range(0, 4)):
        targ_image.pos = (calib_x[c], calib_y[c])
        targ_image.draw()
        fix_circle.draw()
        fix_cross.draw()            
        fix_dot.draw()
        win.flip()
        event.waitKeys(keyList = [response_key], clearEvents = True)
    win.flip()

Here’s a google drive .zip with the full script, images, and environment info:

event.waitKeys() only receives events if the PsychoPy Window is active / in the forground. Perhaps something is causing the psychopy window to loose focus and therefore stop receiving keyboard events via event.waitKeys().

Since you are using iohub for the eye tracker access, one thing you could try is the iohub keyboard device to get keyboard events. iohub uses system wide keyboard hooks to get keyboard events, so it does not matter if the psychopy window has focus or not.

To switch the experiment to use the iohub keyboard device to get keys:

Get the iohub keyboard device:

# From your script
io = launchHubServer(**tracker_config)
et = io.devices.tracker

# get the keyboard device
iokeyboard = io.devices.keyboard

Then you can replace event.waitKeys(keyList = [response_key], clearEvents = True) with:

iokeyboard.waitForPresses(keys=[response_key], clear=True)

Note: the iohub keyboard currently maps some keys to different labels than event.getKeys(), so if you want to wait for the space key, use keys=[' '] instead of keys=['space'].

Thank you

Hi @sol, thanks for your response. Unfortunately, I don’t think that workaround is a solution for us. We also need this waiting functionality when running the script without access to an eyetracker (the eyetracker code is conditional for this reason, determined by an initial GUI menu). I did attempt to test this by trying to simulate the eyetracker via the configuration code, but it looks like you still need to be physically connected to an eyetracker for that to work.

Apart from that, this may not help solve the issue as we do need to collect responses during the experiment (done via event.getKeys()), so the window is losing focus, I think we would need a way to prevent that or re-focus the computer to the program window. Also, is it typical that losing focus from the window should spike the CPU and freeze the program? Hypothetically if the program lost focus, we could click on the window again to re-focus, but instead it instantly freezes.

We did suspect that maybe the peripheral hardware (keyboard-mouse, eyetracker ethernet) or background software was causing the program to lose focus, so we disconnected all hardware from the laptop and closed all background processes, but the program still has a chance to freeze. Do you have any other ideas about how we can fix this problem?

Hi @jeffkravitz. thanks for the update.

we also need this waiting functionality when running the script without access to an eyetracker

You can start iohub and access the keyboard (no eye tracker) by calling launchHubServer without any arguements. For example:

io = launchHubServer()
# get the keyboard device
iokeyboard = io.devices.keyboard

we do need to collect responses during the experiment (done via event.getKeys() ),

That is another reason to use iohub instead. iohub has better event timing than event.getKeys() because iohub runs async to win.flip(). Replace event.getKeys() with iokeyboard.getPresses() for example, which will return a list of any key presses, each as an object with .key and .time attributes.

Also, is it typical that losing focus from the window should spike the CPU and freeze the program?

Running a psychopy script will spike the CPU unless your script is calling time.sleep(0.0xx) frequently, in or out of focus. :wink: The event.waitKeys() ‘freezing’ is ( I’m guessing ) from the window loosing focus.

If the issue is because the window is loosing focus, I really think using iohub for the keyboard event timing is the easiest way to solve it. Since you have iohub running in the eye tracker condition already, adapting the script to use it without the eye tracker just for keyboard events should be pretty easy.

If you decide to give this route another go and run into any specific issues moving away from event.get\wait.. please let us know.

thanks again

Hi @sol thanks for your reply. I’ve tried to implement the changes you suggested, but I’ve run into some trouble. I now get the following error when trying to launch ioHub:

 *** iohub warning: Display / Monitor unit type has not been set.
Traceback (most recent call last):
  File "rsvp_sweep.py", line 625, in <module>
    io = launchHubServer()
  File "/Users/jeff/.conda/envs/ioWait_test_env/lib/python3.6/site-packages/psychopy/contrib/lazy_import.py", line 120, in __call__
    return obj(*args, **kwargs)
  File "/Users/jeff/.conda/envs/ioWait_test_env/lib/python3.6/site-packages/psychopy/iohub/client/connect.py", line 290, in launchHubServer
    return ioHubConnection(iohub_config)
  File "/Users/jeff/.conda/envs/ioWait_test_env/lib/python3.6/site-packages/psychopy/iohub/client/__init__.py", line 289, in __init__
    raise RuntimeError('Error starting ioHub server: {}'.format(self.iohub_status))
RuntimeError: Error starting ioHub server: ioHub startup failed.
ioHub Server Process Completed With Code:  Negsignal.SIGSEGV

I’ve tried downgrading pyglet to 1.3.1 (as you suggest here), but I get some error messages when trying to setup the environment. It looks like pyglet 1.3.1 isn’t available for Mac, and isn’t compatible with my psychopy version (which isn’t as important). Do you know which version of psychopy I can download to make io = launchHubServer() work properly? Also, I use Anaconda to manage the environment, if that helps at all.

 pip install pyglet==1.3.1
Collecting pyglet==1.3.1
  Using cached pyglet-1.3.1-py2.py3-none-any.whl (1.0 MB)
Requirement already satisfied: future in /Users/jeff/.conda/envs/ioWait_test_env/lib/python3.6/site-packages (from pyglet==1.3.1) (0.18.2)
Installing collected packages: pyglet
  Attempting uninstall: pyglet
    Found existing installation: pyglet 1.5.16
    Uninstalling pyglet-1.5.16:
      Successfully uninstalled pyglet-1.5.16
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
psychopy 2021.2.3 requires jedi>=0.16, which is not installed.
psychopy 2021.2.3 requires psychtoolbox, which is not installed.
psychopy 2021.2.3 requires pygame, which is not installed.
psychopy 2021.2.3 requires pyo, which is not installed.
psychopy 2021.2.3 requires pyobjc; platform_system == "Darwin", which is not installed.
psychopy 2021.2.3 requires python-vlc>=3.0.12118; platform_system != "Windows", which is not installed.
psychopy 2021.2.3 requires tobii-research; python_version <= "3.6", which is not installed.
psychopy 2021.2.3 requires ujson, which is not installed.
psychopy 2021.2.3 requires pyglet>=1.5; platform_system == "Darwin", but you have pyglet 1.3.1 which is incompatible.
Successfully installed pyglet-1.3.1