mouse.getPos() doesn't reflect recently set mouse.setPos()

Hi all,

I’m trying to track the position of the mouse cursor on the screen whilst drawing a line. I want to store the values of the position of the mouse to then later play back the drawing of the line with no input from the mouse itself.

I have two problems:

  1. I set the mouse to zero and then get the position of the mouse, which does not return [0,0]. Instead it returns [-960,-450], the bottom left of the screen. This means it draws a line to the bottom left on the first few frames

  2. I move the mouse to draw a line and record the position (all good here). I then set the mouse position to zero again and the cursor on the screen moves to [0,0]. Immediately after, I get the position of the mouse. This time, it just returns the last position of the mouse before I set it to zero.

Here’s the code:

import numpy as np 
from psychopy import visual, core, event

winSize=(1152,870)
# ** draw a line with the mouse and press space when done. Cursor will move back to fixation point. Will then replay your line-drawing**

win = visual.Window(size=winSize, monitor='testMonitor',
units='pix',bitsMode=None, allowGUI=False, winType='pyglet', fullscr=True)	

mouse = event.Mouse(visible = True) 
respLine = visual.Line(win, start=(0,0), end=(0,0))
respLine.end = (0,0)
Fixation = visual.GratingStim(win,units='pix',sf=0,mask='circle',size=10)

recordedMousePos = np.zeros((2,300))

mouse.setPos([0,0])
for nFrames in range(300):
    Fixation.draw()
    respLine.end = mouse.getPos() # should start at [0,0] on first frame but starts at bottom left
    respLine.draw()
    win.flip()
    for key in event.getKeys():
        if key in ['escape','q']:
            core.quit()
        elif key in ['space']:
            mouse.setPos([0,0])
            print 'setToZero',mouse.getPos() # should be [0,0] but it is not
    recordedMousePos[:,nFrames] = mouse.getPos()
#    print 'recordedPos',recordedMousePos[:,nFrames] #uncomment to see recorded pos of mouse on every frame


# play the line drawing back ** should show cursor moving back to centre following space, but doesn't. 
mouse.setPos([0,0])
for nFrames in range(300):
    mouse.setPos(recordedMousePos[:,nFrames])
    Fixation.color = 'blue'
    Fixation.draw()
    respLine.end = recordedMousePos[:,nFrames]
    respLine.draw()
    win.flip()
    for key in event.getKeys():
        if key in ['escape','q']:
            core.quit()

Any help would be greatly appreciated!

Thank you,

Sarah

1 Like

Try assigning the mouse to your window.

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

Otherwise, it may not be operating according to the window units.

Thank you for the suggestion :slight_smile:

Tried but no difference.

Appears to be a problem where mouse.setPos moves the mouse on the screen but does not update the logged position of the mouse when calling mouse.getPos.

Nice script. Is strangely satisfying seeing one’s mouse movements repeating. Very cool.

I think your diagnosis was correct. Pyglet (not our code!) is updating the mouse but not storing its updated location. We can get around it by doing it ourselves on pyglet’s behalf and I’ve just made that change in PsychoPy here:
https://github.com/psychopy/psychopy/pull/1488/commits/f9fc6706bc76dcab90cba3c6558dc9b291d8fa0c

You could either make that change in your own copy of psychopy or do it in your script. e.g. you could add a function like this:

def moveMouse(x,y):
    mouse.setPos([x,y])
    win.winHandle._mouse_x = x  # hack to change pyglet window
    win.winHandle._mouse_y = y

and then you’d call moveMouse(x,y) in the rest of your script instead of the psychopy function.

This actually solves one part of a post ages ago where @lindeloev, @rob.stone and @porcu.emanuele were battling with the mouse. @lindeloev noticed the issue you mention and now it’s one part of that puzzle that’s fixed. :slight_smile:

cheers,
Jon

I’m recently dowloaded PcychoPy 1.85.3 and I’m running it on MacBook Pro with OS 10.10.5. With this version of PsychoPy I’m not able to set the position of my mouse to the center of the screen. But in the earlier version (1.84.2) it worked. I tested this with a small script which had the only purpose to move the mouse-pointer to the center of the screen. But I only got error message … whether or not I included the moveMose() function

This is the code:

from psychopy import visual, core, event

def moveMouse(x,y): # copied from this tread
    myMouse.setPos([x,y])
    myWin.winHandle._myMouse_x = x  # hack to change pyglet window
    myWin.winHandle._myMouse_y = y
 
myWin = visual.Window([1000, 600], monitor = "testMonitor", units = "deg", color = (255, 255, 255)) # , winType='pyglet' I tried to have this definition in myWin definition but the same error was reported

myMouse = event.Mouse(visible = True, win = myWin) #, newPos = [0, 0]

moveMouse(0, 0)

'''
error message:
newPosPix = self.win.size / 2 + newPosPix
TypeError: unsupported operand type(s) for /: 'tuple' and 'int'
'''

core.wait(1)
core.quit()

I would be grateful if this problem of mine could be solved …

Yes, this is a mac-only issue (I believe) and can be fixed by the following:

in psychopy/visual/window.py change the line (around line 1500) from:
self.size = (int(bounds.width), int(bounds.height))
to
self.size = numpy.array([int(bounds.width), int(bounds.height)])

or (possibly) you can provide the argument when you create the window: useRetina=False and I think that should fix it too

Jon

Thanks a lot! I used the second option and now everything is OK