Can not use second display on a Ubuntu system

If this template helps then use it. If not then just delete and start from scratch.

OS Ubuntu 22.04 LTS
PsychoPy version 2024.2.4:
Standard Standalone Installation? (y)
Do you want it to also run online? (n)
What are you trying to achieve?:

I want to display an experiment on a second monitor. The Ubuntu system does not seem to recognise that a second monitor is connected. As a result, PsychoPy throws an error trying to address a non-existent monitor. However, running a Psychotoolbox experiment on the same computer runs fine on the second monitor. Ideas how to “convince” PsychoPy to do the same are welcome.

What specifically went wrong when you tried that?:
10.8084 INFO Loaded monitor calibration from [‘2025_04_11 11:34’]
10.8230 INFO Loaded monitor calibration from [‘2025_04_11 11:34’]
13.5732 ERROR User requested non-existent screen
Generating PsychoPy script…

Running: /home/busch/Documents/JEBAR/PermissiveSubjectsEEG/PermissiveSubjectBase_lastrun.py

26.2316 INFO Loaded monitor calibration from [‘2025_04_11 11:34’]
26.2457 INFO Loaded monitor calibration from [‘2025_04_11 11:34’]
Traceback (most recent call last):
File “/home/busch/.psychopy_py310/lib/python3.10/site-packages/psychopy/plugins/init.py”, line 202, in resolveObjectFromName
importlib.import_module(path)
File “/usr/lib/python3.10/importlib/init.py”, line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File “”, line 1050, in _gcd_import
File “”, line 1027, in _find_and_load
File “”, line 1001, in _find_and_load_unlocked
ModuleNotFoundError: No module named ‘psychopy.visual.backends.glfwbackend.GLFWBackend’; ‘psychopy.visual.backends.glfwbackend’ is not a package

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “/home/busch/Documents/JEBAR/PermissiveSubjectsEEG/PermissiveSubjectBase_lastrun.py”, line 2690, in
win = setupWindow(expInfo=expInfo)
File “/home/busch/Documents/JEBAR/PermissiveSubjectsEEG/PermissiveSubjectBase_lastrun.py”, line 199, in setupWindow
win = visual.Window(
File “/home/busch/.psychopy_py310/lib/python3.10/site-packages/psychopy/visual/window.py”, line 480, in init
self.backend = backends.getBackend(win=self, backendConf=backendConf)
File “/home/busch/.psychopy_py310/lib/python3.10/site-packages/psychopy/visual/backends/init.py”, line 48, in getBackend
Backend = plugins.resolveObjectFromName(useBackend, name)
File “/home/busch/.psychopy_py310/lib/python3.10/site-packages/psychopy/plugins/init.py”, line 206, in resolveObjectFromName
raise NameError(
NameError: Specified name does not reference a valid object or is unreachable.
Exception ignored in: <function Window.del at 0x709a2c13b7f0>
Traceback (most recent call last):
File “/home/busch/.psychopy_py310/lib/python3.10/site-packages/psychopy/visual/window.py”, line 665, in del
self.close()
File “/home/busch/.psychopy_py310/lib/python3.10/site-packages/psychopy/visual/window.py”, line 2657, in close
self.backend.close() # moved here, dereferencing the window prevents
AttributeError: ‘NoneType’ object has no attribute ‘close’
################ Experiment ended with exit code 1 [pid:19625] #################

Best wishes Jens

Is this a system with two X screens (i.e. there’s a file in /etc/X11/xorg.conf.d/ or similar that specifies where screens should be)? Assuming yes…

If you want to use GLFW as the window, you’ll need to install the psychopy-glfw package. Note that GLFW doesn’t understand multiple X screens, and one way to specify which screen it should be on is with the DISPLAY environment variable (e.g. DISPLAY=:0.1 for the second X screen of display 0).

Pyglet does understand multiple X screens, but you may need to explicitly disable the shadow window before running a task (e.g. set the PYGLET_SHADOW_WINDOW=0 in the environment).

Hello

as a matter of fact it is not my system and I do not know anything about Ubuntu which makes debugging complicated.

I’ ll give it a try.

Best wishes Jens

Hello @aforren1

I updated PsychoPy in the meantime to 2025.1.0.

I tried setting PYGLET_SHADOW_WINDOW=0. When I then test for the number of monitors detected by PsychoPy via Experiment properties, PsychoPy throws the following error message. It is the same error message I get when trying to address a second monitor.

Traceback (most recent call last):
File “/home/busch/Documents/JEBAR/PsychoPy-2025.1.0-Python3.10/lib/python3.10/site-packages/psychopy/app/builder/dialogs/init.py”, line 973, in showScreenNumbers
DeviceManager.showScreenNumbers(dur=5)
File “/home/busch/Documents/JEBAR/PsychoPy-2025.1.0-Python3.10/lib/python3.10/site-packages/psychopy/hardware/manager.py”, line 860, in showScreenNumbers
from psychopy import visual
File “/home/busch/Documents/JEBAR/PsychoPy-2025.1.0-Python3.10/lib/python3.10/site-packages/psychopy/visual/init.py”, line 34, in
from .image import ImageStim
File “/home/busch/Documents/JEBAR/PsychoPy-2025.1.0-Python3.10/lib/python3.10/site-packages/psychopy/visual/image.py”, line 27, in
from psychopy.tools import gltools as gt
File “/home/busch/Documents/JEBAR/PsychoPy-2025.1.0-Python3.10/lib/python3.10/site-packages/psychopy/tools/gltools.py”, line 408, in
MAX_TEXTURE_UNITS = getOpenGLInfo().maxTextureUnits
File “/home/busch/Documents/JEBAR/PsychoPy-2025.1.0-Python3.10/lib/python3.10/site-packages/psychopy/tools/gltools.py”, line 404, in getOpenGLInfo
return OpenGLInfo()
File “/home/busch/Documents/JEBAR/PsychoPy-2025.1.0-Python3.10/lib/python3.10/site-packages/psychopy/tools/gltools.py”, line 348, in init
self.vendor = getString(GL.GL_VENDOR)
File “/home/busch/Documents/JEBAR/PsychoPy-2025.1.0-Python3.10/lib/python3.10/site-packages/psychopy/tools/gltools.py”, line 302, in getString
val = ctypes.cast(GL.glGetString(parName), ctypes.c_char_p).value
File “/home/busch/Documents/JEBAR/PsychoPy-2025.1.0-Python3.10/lib/python3.10/site-packages/pyglet/gl/lib.py”, line 102, in errcheck
raise GLException(‘No GL context; create a Window first’)
pyglet.gl.lib.GLException: No GL context; create a Window first

I installed glfw and set the environment variable DISPLAY. but that throws the following error message, when starting.

unable to access the X Display, is $DISPLAY set properly? followed by the same error message. Neither pyglet nor glfw allow to access the second screen.

There is a file in /etc/X11/xorg.conf.d with the following content

Auto generated xorg.conf - Created by Psychtoolbox XOrgConfCreator.

Section “ServerFlags”
Option “AutoAddGPU” “false”
EndSection

Section “ServerLayout”
Identifier “PTB-Hydra”
Screen 0 “Screen0” 0 0
Screen 1 “Screen1” RightOf “Screen0”
EndSection

Section “Monitor”
Identifier “HDMI-A-0”
EndSection

Section “Monitor”
Identifier “DisplayPort-0”
EndSection

Section “Device”
Identifier “Card0”
Driver “amdgpu”
Option “VariableRefresh” “on”
Option “ZaphodHeads” “HDMI-A-0”
Option “Monitor-HDMI-A-0” “HDMI-A-0”
Screen 0
EndSection

Section “Device”
Identifier “Card1”
Driver “amdgpu”
Option “VariableRefresh” “on”
Option “ZaphodHeads” “DisplayPort-0”
Option “Monitor-DisplayPort-0” “DisplayPort-0”
Screen 1
EndSection

Section “Screen”
Identifier “Screen0”
Device “Card0”
Monitor “HDMI-A-0”
EndSection

Section “Screen”
Identifier “Screen1”
Device “Card1”
Monitor “DisplayPort-0”
EndSection

Any idea?

Best wishes Jens

Sorry, just a partial answer for the moment.

Great, so it is configured to have two separate X screens.

As far as I can tell, this change was introduced in 2025.1.0 and implicitly assumes the shadow window is always available (which in this case, it won’t be). 2024.2.4 or 2024.2.5 should work in the meanwhile.

Additionally, it looks like DeviceManager.showScreenNumbers wouldn’t quite work anyway. Displays/screens require different handling on Linux, see e.g. here. If you happen to use ioHub, you’d run into similar issues. You can just set the screen number to 2 in the Builder dialog. Generally improving PsychoPy’s compatibility with multiple X screens is on my TODO list…

I’d suggest not bothering with GLFW unless you knew you needed it, because it’s kind of a pain to set DISPLAY in the Builder context. If you wanted to continue down that route, a few things:

  • I think you’d leave the screen number as 1 in the Builder settings (since it thinks it’s the only screen)
  • To only have the DISPLAY apply to a Builder task (and not the whole GUI), you’d have to insert an os.environ['DISPLAY'] = ':0.1' before the PsychoPy window is created (or run the generated script as DISPLAY=:0.1 python <script>.py)
  • AFAIR GLFW needs Pyglet’s shadow window to provide the GL context? So you’d leave the shadow window on in that case.