psychopy.org | Reference | Downloads | Github

Playing with multiple mice in Psychopy

I’m trying to manage an experiment using several mice. With pyglet I can associate specific events to each button of each mouse. The following code shows it.

#!/usr/bin/env python

from __future__ import print_function

import pyglet

window = pyglet.window.Window()

mice = list()
selected_mouse = -1

def watch_control(mouse_number, control):
    if isinstance(control, pyglet.input.base.Button):
        @control.event
        def on_press():
            global selected_mouse
            selected_mouse = mouse_number
            print('%r: %r.on_press()' % (mouse_number, control))

mouse_number = 0
for device in pyglet.input.get_devices():
    if u"mouse" in str(device.name).lower():
        mice.append(device)

for mouse in mice:
    try:
        mouse.open(window=window)
        for control in mouse.get_controls():
            watch_control(mouse_number, control)
        mouse_number = mouse_number + 1
    except pyglet.input.DeviceException:
        print('Fail')

pyglet.app.run()

print("selected_mouse: %r" % (selected_mouse))

With each click on a mouse button, the mouse number appears correctly on the output.
When I try to do the same thing with Psychopy, the events don’t appear.
With the following code, nothing is displayed when you click on the mouse button.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import absolute_import, division, print_function

from psychopy import core, event , visual, gui

import pyglet

win = visual.Window((600.0, 600.0), unit = 'pix', fullscr = False, winType='pyglet', color = [1,1,1],
    monitor='testMonitor')

mice = list()
selected_mouse = -1

def watch_mouse(mouse_number, control):
    if isinstance(control, pyglet.input.base.Button):
        print('press event associated with a button of mouse #%r' % (mouse_number))
        @control.event
        def on_press():
            global selected_mouse
            selected_mouse = mouse_number
            print('button pressed on mouse #%s' % (mouse_number)) 

for device in pyglet.input.get_devices():
    if u"mouse" in str(device.name).lower():
        mice.append(device)

mouse_number = 0
for mouse in mice:
    try:
        mouse.open(window=win, exclusive=True)
        for control in mouse.get_controls():
            watch_mouse(mouse_number, control)
        mouse_number = mouse_number + 1
    except pyglet.input.DeviceException:
        myDlg = gui.Dlg(title="Initialization error")
        myDlg.addText("Can't initialize mice.")
        ok_data = myDlg.show()  # show dialog and wait for OK or Cancel
        win.close()
        core.quit()

# Continue until keypress
print('selected_mouse : %r' % (selected_mouse))
print('found %r mice' % (len(mice)))
event.clearEvents()
while not event.getKeys():
    win.flip()
print('selected_mouse : %r' % (selected_mouse))
for mouse in mice:
    mouse.close()

win.close()

Is there a particular way to ask Psychopy to take into account the events associated with the buttons?

On a MacBook Pro, macOS 10.15.1
python 3.7 and pyglet 1.4.6
Psychopy3 standalone macOS 3.2.4

I just saw that pyglet windows implementation doesn’t distinguish multiple mice and make no distinction at all for buttons of different mice. At least in Windows 10.

1 Like