getPos() Fails To Record Mouse Position Inside While Loop

Hello all,

I am encountering problems getting the mouse position using get getPos() inside of a time while loop. Any help would be greatly appreciated!

I’ve copy pasted code that exemplifies the problem below:

from psychopy import core, visual, event
import pygame as pg

#establish window backend
window_backend = 'pyglet'
win = visual.Window(size = (1920, 1080), fullscr = True, screen = 1, monitor = 'touch_screen', units = 'pix', winType = window_backend)

#make mouse
mouse = event.Mouse(win = win, visible = True)

#declare variables
timing_delay = 5;
looped = False; 

#set clock to control experiment 
timing_control = core.Clock()
timing_control.reset()

#record mouse position before while loop
mouse_loc_before = mouse.getPos()
print(mouse_loc_before)

#run while loop for length of 'timing delay' 
while timing_control.getTime() <= timing_delay:
    #extract mouse position
    mouse_loc_during = mouse.getPos()
    
    #check if the mouse position during the loop deviates from what it was before the loop 
    # THIS IF STATEMENT IS NEVER TRIGGERED DESPITE MOVING MOUSE
    if mouse_loc_before[0] != mouse_loc_during[0] or mouse_loc_before[1] != mouse_loc_during[1]:
        print(mouse_loc_during)
    
    #set flag to true to check the loop ran
    looped = True
    
#print this to demonstrate the loop successfully ran    
if looped:
    print('ran loop')

#record mouse position after the loop
mouse_loc_after = mouse.getPos()
print(mouse_loc_after)

The printed mouse position before and after the while loop is exactly the same, despite moving and clicking the mouse during the timing_delay window of the while loop. Further, the if condition is never triggered meaning that throughout the duration of the while loop getPos() is not detecting the mouse movement. Making me believe either the changing mouse position is somehow not being recording during my while loop or getPos() is unable to extract it. Has anyone else experienced this problem before? Or have suggestions of what I might be doing wrong?

In part of my experiment, I need to know the reaction time of the participants, namely how long it takes them to touch a target on the screen. I was planning to use a while loop reliant on a clock in a similar manner to the above code to check the location of the mouse at each frame and see if it is inside of a shape using .contains, thus recording the exact time they touch the target. However this fails on account of the above issue. So, if anyone has a suggestion of another way of achieving that goal I would also be happy to hear it!

Potentially Relevant Specifications:

  • PsychoPy v2023.1.3 Standalone
  • PC computer running Windows 11 Pro with a NVIDIA GeForce RTX 3070 graphics card
  • The task will be using a touch screen monitor, but I troubleshot this using a standard monitor and mouse and still encounter the problem.

Thank you so much!

Have you tried running the “Demos → input → mouse.py” demo in the coder? That should give you a minimal test of whether psychopy can take input from your mouse at all.

Hi Jonathan, thank you for the feedback! While I haven’t tried the specific demo you mentioned, I can successfully use getPos() and other functions that rely on the mouse position with my setup in other parts of the script without any issue. getPos() only fails inside this specific type of while loop where the condition is checked every frame.

Apologies if that wasn’t clear in my post

The issue in this one is that the event.mouse using pyglet needs to be told to keep checking for updates. In the PsychoPy Window class this gets done during each call to Window.flip()

So, one possibility is that, inside your loop you make calls to pyglets dispatch_events() function like this (untested):

while timing_control.getTime() <= timing_delay:
    win.winHandle.dispatch_events()  # ensure mouse updates are sent
    #extract mouse position
    mouse_loc_during = mouse.getPos()

Alternatively use hardware.Mouse instead, which will use the iohub engine instead of pyglet. It’s higher performance and doesn’t need these steps. That’s what Builder experiments use now for these reasons.