Display 3D skeletons in napari#
There are two ways to display 3D skeletons in napari. First, we demonstrate how to use the napari Shapes layer to draw Paths for each skeleton path. As of napari 0.4.14, however, 3D interactivity in the Shapes layer is not ideal, so we also demonstrate how to use the Labels layer.
Using the Shapes layer#
The napari Shapes layer allows displaying of 2D and 3D paths, and coloring them by tabular properties, which makes it ideal for displaying skeletons, and the measurements provided by skan.
import napari
import numpy as np
import skan
from skimage.data import binary_blobs
from skimage.morphology import skeletonize
import scipy.ndimage as ndi
Note
We use synthetic data here. If you have a cool 3D skeleton dataset that you’d like to show off in these docs, let us know!
blobs = binary_blobs(64, volume_fraction=0.3, n_dim=3)
binary_skeleton = skeletonize(blobs)
skeleton = skan.Skeleton(binary_skeleton)
all_paths = [
skeleton.path_coordinates(i)
for i in range(skeleton.n_paths)
]
paths_table = skan.summarize(skeleton)
paths_table['path-id'] = np.arange(skeleton.n_paths)
First, we color by random path ID, showing each path in a distinct color using the matplotlib “tab10” qualitative palette. (Coloring by path ID directly results in “bands” of nearby paths receiving the same color.)
paths_table['random-path-id'] = np.random.default_rng().permutation(skeleton.n_paths)
viewer = napari.Viewer(ndisplay=3)
skeleton_layer = viewer.add_shapes(
all_paths,
shape_type='path',
properties=paths_table,
edge_width=0.5,
edge_color='random-path-id',
edge_colormap='tab10',
)
We can also demonstrate that most of these branches are in one skeleton, with a few stragglers around the edges, by coloring by skeleton ID:
skeleton_layer.edge_color = 'skeleton-id'
# for now, we need to set the face color as well
skeleton_layer.face_color = 'skeleton-id'
Finally, we can color the paths by a numerical property, such as their length.
skeleton_layer.edge_color = 'branch-distance'
skeleton_layer.edge_colormap = 'viridis'
# for now, we need to set the face color as well
skeleton_layer.face_color = 'branch-distance'
skeleton_layer.face_colormap = 'viridis'
Using the Labels layer#
We can also visualize the pixels of the skeleton as a Labels layer, with each path ID appearing as a different label. The downside with this approach is that junction pixels are arbitrarily assigned to one of the branches incident on that junction. Therefore, removing that branch would cause the junction pixel to be removed, which could incorrectly disconnect the skeleton at that point.
However, the rich 3D interactivity of the labels layer does allow prunning of branches in 3D, which could be extremely useful for manual curation of the skeleton, as long as propert care is taken in downstream processing of the edits.
labels = np.asarray(skeleton)
viewer2 = napari.view_labels(
labels,
properties=paths_table,
opacity=1,
ndisplay=3,
)
WARNING: Error drawing visual <Volume at 0x7f8db42bb010>
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/app/backends/_qt.py:903, in CanvasBackendDesktop.paintGL(self)
901 # (0, 0, self.width(), self.height()))
902 self._vispy_canvas.set_current()
--> 903 self._vispy_canvas.events.draw(region=None)
905 # Clear the alpha channel with QOpenGLWidget (Qt >= 5.4), otherwise the
906 # window is translucent behind non-opaque objects.
907 # Reference: MRtrix3/mrtrix3#266
908 if QT5_NEW_API or PYSIDE6_API or PYQT6_API:
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:453, in EventEmitter.__call__(self, *args, **kwargs)
450 if self._emitting > 1:
451 raise RuntimeError('EventEmitter loop detected!')
--> 453 self._invoke_callback(cb, event)
454 if event.blocked:
455 break
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:471, in EventEmitter._invoke_callback(self, cb, event)
469 cb(event)
470 except Exception:
--> 471 _handle_exception(self.ignore_callback_errors,
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:469, in EventEmitter._invoke_callback(self, cb, event)
467 def _invoke_callback(self, cb, event):
468 try:
--> 469 cb(event)
470 except Exception:
471 _handle_exception(self.ignore_callback_errors,
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:218, in SceneCanvas.on_draw(self, event)
215 # Now that a draw event is going to be handled, open up the
216 # scheduling of further updates
217 self._update_pending = False
--> 218 self._draw_scene()
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:277, in SceneCanvas._draw_scene(self, bgcolor)
275 bgcolor = self._bgcolor
276 self.context.clear(color=bgcolor, depth=True)
--> 277 self.draw_visual(self.scene)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:315, in SceneCanvas.draw_visual(self, visual, event)
313 else:
314 if hasattr(node, 'draw'):
--> 315 node.draw()
316 prof.mark(str(node))
317 else:
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/visuals.py:103, in VisualNode.draw(self)
101 if self.picking and not self.interactive:
102 return
--> 103 self._visual_superclass.draw(self)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/visuals/visual.py:451, in Visual.draw(self)
449 self._configure_gl_state()
450 try:
--> 451 self._program.draw(self._vshare.draw_mode,
452 self._vshare.index_buffer)
453 except Exception:
454 logger.warning("Error drawing visual %r" % self)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/visuals/shaders/program.py:102, in ModularProgram.draw(self, *args, **kwargs)
100 self.build_if_needed()
101 self.update_variables()
--> 102 Program.draw(self, *args, **kwargs)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/program.py:526, in Program.draw(self, mode, indices, check_error)
522 raise TypeError("Invalid index: %r (must be IndexBuffer)" %
523 indices)
525 # Process GLIR commands
--> 526 canvas.context.flush_commands()
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/context.py:172, in GLContext.flush_commands(self, event)
170 fbo = 0
171 self.shared.parser.parse([('CURRENT', 0, fbo)])
--> 172 self.glir.flush(self.shared.parser)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:582, in GlirQueue.flush(self, parser)
580 def flush(self, parser):
581 """Flush all current commands to the GLIR interpreter."""
--> 582 self._shared.flush(parser)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:504, in _GlirQueueShare.flush(self, parser)
502 show = self._verbose if isinstance(self._verbose, str) else None
503 self.show(show)
--> 504 parser.parse(self._filter(self.clear(), parser))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:822, in GlirParser.parse(self, commands)
819 self._objects.pop(id_)
821 for command in commands:
--> 822 self._parse(command)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:794, in GlirParser._parse(self, command)
792 ob.set_data(*args)
793 elif cmd == 'SIZE': # VertexBuffer, IndexBuffer,
--> 794 ob.set_size(*args) # Texture[1D, 2D, 3D], RenderBuffer
795 elif cmd == 'ATTACH': # FrameBuffer, Program
796 ob.attach(*args)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:1631, in GlirTexture3D.set_size(self, shape, format, internalformat)
1629 self.activate()
1630 self._shape_formats = shape, format, internalformat
-> 1631 glTexImage3D(self._target, 0, internalformat, format,
1632 gl.GL_BYTE, shape[:3])
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:1576, in glTexImage3D(target, level, internalformat, format, type, pixels)
1574 def glTexImage3D(target, level, internalformat, format, type, pixels):
1575 # Import from PyOpenGL
-> 1576 _gl = _check_pyopengl_3D()
1577 border = 0
1578 assert isinstance(pixels, (tuple, list)) # the only way we use this now
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:1568, in _check_pyopengl_3D()
1566 USE_TEX_3D = True
1567 try:
-> 1568 import OpenGL.GL as _gl
1569 except ImportError:
1570 raise ImportError('PyOpenGL is required for 3D texture support')
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/OpenGL/GL/__init__.py:4
2 # early import of our modules to prevent import loops...
3 from OpenGL import error as _error
----> 4 from OpenGL.GL.VERSION.GL_1_1 import *
5 from OpenGL.GL.pointers import *
6 from OpenGL.GL.images import *
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/OpenGL/GL/VERSION/GL_1_1.py:14
12 import ctypes
13 from OpenGL.raw.GL import _types, _glgets
---> 14 from OpenGL.raw.GL.VERSION.GL_1_1 import *
15 from OpenGL.raw.GL.VERSION.GL_1_1 import _EXTENSION_NAME
17 def glInitGl11VERSION():
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/OpenGL/raw/GL/VERSION/GL_1_1.py:7
5 # End users want this...
6 from OpenGL.raw.GL._types import *
----> 7 from OpenGL.raw.GL import _errors
8 from OpenGL.constant import Constant as _C
9 # Spec mixes constants from 1.0 and 1.1
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/OpenGL/raw/GL/_errors.py:4
2 from OpenGL.error import _ErrorChecker
3 if _ErrorChecker:
----> 4 _error_checker = _ErrorChecker( _p, _p.GL.glGetError )
5 else:
6 _error_checker = None
AttributeError: 'NoneType' object has no attribute 'glGetError'
WARNING: Error drawing visual <Volume at 0x7f8db42bb010>
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/app/backends/_qt.py:903, in CanvasBackendDesktop.paintGL(self)
901 # (0, 0, self.width(), self.height()))
902 self._vispy_canvas.set_current()
--> 903 self._vispy_canvas.events.draw(region=None)
905 # Clear the alpha channel with QOpenGLWidget (Qt >= 5.4), otherwise the
906 # window is translucent behind non-opaque objects.
907 # Reference: MRtrix3/mrtrix3#266
908 if QT5_NEW_API or PYSIDE6_API or PYQT6_API:
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:453, in EventEmitter.__call__(self, *args, **kwargs)
450 if self._emitting > 1:
451 raise RuntimeError('EventEmitter loop detected!')
--> 453 self._invoke_callback(cb, event)
454 if event.blocked:
455 break
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:471, in EventEmitter._invoke_callback(self, cb, event)
469 cb(event)
470 except Exception:
--> 471 _handle_exception(self.ignore_callback_errors,
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:469, in EventEmitter._invoke_callback(self, cb, event)
467 def _invoke_callback(self, cb, event):
468 try:
--> 469 cb(event)
470 except Exception:
471 _handle_exception(self.ignore_callback_errors,
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:218, in SceneCanvas.on_draw(self, event)
215 # Now that a draw event is going to be handled, open up the
216 # scheduling of further updates
217 self._update_pending = False
--> 218 self._draw_scene()
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:277, in SceneCanvas._draw_scene(self, bgcolor)
275 bgcolor = self._bgcolor
276 self.context.clear(color=bgcolor, depth=True)
--> 277 self.draw_visual(self.scene)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:315, in SceneCanvas.draw_visual(self, visual, event)
313 else:
314 if hasattr(node, 'draw'):
--> 315 node.draw()
316 prof.mark(str(node))
317 else:
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/visuals.py:103, in VisualNode.draw(self)
101 if self.picking and not self.interactive:
102 return
--> 103 self._visual_superclass.draw(self)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/visuals/visual.py:451, in Visual.draw(self)
449 self._configure_gl_state()
450 try:
--> 451 self._program.draw(self._vshare.draw_mode,
452 self._vshare.index_buffer)
453 except Exception:
454 logger.warning("Error drawing visual %r" % self)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/visuals/shaders/program.py:102, in ModularProgram.draw(self, *args, **kwargs)
100 self.build_if_needed()
101 self.update_variables()
--> 102 Program.draw(self, *args, **kwargs)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/program.py:526, in Program.draw(self, mode, indices, check_error)
522 raise TypeError("Invalid index: %r (must be IndexBuffer)" %
523 indices)
525 # Process GLIR commands
--> 526 canvas.context.flush_commands()
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/context.py:172, in GLContext.flush_commands(self, event)
170 fbo = 0
171 self.shared.parser.parse([('CURRENT', 0, fbo)])
--> 172 self.glir.flush(self.shared.parser)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:582, in GlirQueue.flush(self, parser)
580 def flush(self, parser):
581 """Flush all current commands to the GLIR interpreter."""
--> 582 self._shared.flush(parser)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:504, in _GlirQueueShare.flush(self, parser)
502 show = self._verbose if isinstance(self._verbose, str) else None
503 self.show(show)
--> 504 parser.parse(self._filter(self.clear(), parser))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:822, in GlirParser.parse(self, commands)
819 self._objects.pop(id_)
821 for command in commands:
--> 822 self._parse(command)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:778, in GlirParser._parse(self, command)
776 if ob is None:
777 if id_ not in self._invalid_objects:
--> 778 raise RuntimeError('Cannot %s object %i because it '
779 'does not exist' % (cmd, id_))
780 return
781 # Triage over command. Order of commands is set so most
782 # common ones occur first.
RuntimeError: Cannot SIZE object 131 because it does not exist
WARNING: Error drawing visual <Volume at 0x7f8db42bb010>
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/app/backends/_qt.py:903, in CanvasBackendDesktop.paintGL(self)
901 # (0, 0, self.width(), self.height()))
902 self._vispy_canvas.set_current()
--> 903 self._vispy_canvas.events.draw(region=None)
905 # Clear the alpha channel with QOpenGLWidget (Qt >= 5.4), otherwise the
906 # window is translucent behind non-opaque objects.
907 # Reference: MRtrix3/mrtrix3#266
908 if QT5_NEW_API or PYSIDE6_API or PYQT6_API:
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:453, in EventEmitter.__call__(self, *args, **kwargs)
450 if self._emitting > 1:
451 raise RuntimeError('EventEmitter loop detected!')
--> 453 self._invoke_callback(cb, event)
454 if event.blocked:
455 break
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:471, in EventEmitter._invoke_callback(self, cb, event)
469 cb(event)
470 except Exception:
--> 471 _handle_exception(self.ignore_callback_errors,
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:469, in EventEmitter._invoke_callback(self, cb, event)
467 def _invoke_callback(self, cb, event):
468 try:
--> 469 cb(event)
470 except Exception:
471 _handle_exception(self.ignore_callback_errors,
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:218, in SceneCanvas.on_draw(self, event)
215 # Now that a draw event is going to be handled, open up the
216 # scheduling of further updates
217 self._update_pending = False
--> 218 self._draw_scene()
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:277, in SceneCanvas._draw_scene(self, bgcolor)
275 bgcolor = self._bgcolor
276 self.context.clear(color=bgcolor, depth=True)
--> 277 self.draw_visual(self.scene)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:315, in SceneCanvas.draw_visual(self, visual, event)
313 else:
314 if hasattr(node, 'draw'):
--> 315 node.draw()
316 prof.mark(str(node))
317 else:
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/visuals.py:103, in VisualNode.draw(self)
101 if self.picking and not self.interactive:
102 return
--> 103 self._visual_superclass.draw(self)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/visuals/visual.py:451, in Visual.draw(self)
449 self._configure_gl_state()
450 try:
--> 451 self._program.draw(self._vshare.draw_mode,
452 self._vshare.index_buffer)
453 except Exception:
454 logger.warning("Error drawing visual %r" % self)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/visuals/shaders/program.py:102, in ModularProgram.draw(self, *args, **kwargs)
100 self.build_if_needed()
101 self.update_variables()
--> 102 Program.draw(self, *args, **kwargs)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/program.py:526, in Program.draw(self, mode, indices, check_error)
522 raise TypeError("Invalid index: %r (must be IndexBuffer)" %
523 indices)
525 # Process GLIR commands
--> 526 canvas.context.flush_commands()
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/context.py:172, in GLContext.flush_commands(self, event)
170 fbo = 0
171 self.shared.parser.parse([('CURRENT', 0, fbo)])
--> 172 self.glir.flush(self.shared.parser)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:582, in GlirQueue.flush(self, parser)
580 def flush(self, parser):
581 """Flush all current commands to the GLIR interpreter."""
--> 582 self._shared.flush(parser)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:504, in _GlirQueueShare.flush(self, parser)
502 show = self._verbose if isinstance(self._verbose, str) else None
503 self.show(show)
--> 504 parser.parse(self._filter(self.clear(), parser))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:822, in GlirParser.parse(self, commands)
819 self._objects.pop(id_)
821 for command in commands:
--> 822 self._parse(command)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:778, in GlirParser._parse(self, command)
776 if ob is None:
777 if id_ not in self._invalid_objects:
--> 778 raise RuntimeError('Cannot %s object %i because it '
779 'does not exist' % (cmd, id_))
780 return
781 # Triage over command. Order of commands is set so most
782 # common ones occur first.
RuntimeError: Cannot SIZE object 131 because it does not exist
WARNING: Error drawing visual <Volume at 0x7f8db42bb010>
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/app/backends/_qt.py:903, in CanvasBackendDesktop.paintGL(self)
901 # (0, 0, self.width(), self.height()))
902 self._vispy_canvas.set_current()
--> 903 self._vispy_canvas.events.draw(region=None)
905 # Clear the alpha channel with QOpenGLWidget (Qt >= 5.4), otherwise the
906 # window is translucent behind non-opaque objects.
907 # Reference: MRtrix3/mrtrix3#266
908 if QT5_NEW_API or PYSIDE6_API or PYQT6_API:
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:453, in EventEmitter.__call__(self, *args, **kwargs)
450 if self._emitting > 1:
451 raise RuntimeError('EventEmitter loop detected!')
--> 453 self._invoke_callback(cb, event)
454 if event.blocked:
455 break
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:471, in EventEmitter._invoke_callback(self, cb, event)
469 cb(event)
470 except Exception:
--> 471 _handle_exception(self.ignore_callback_errors,
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:469, in EventEmitter._invoke_callback(self, cb, event)
467 def _invoke_callback(self, cb, event):
468 try:
--> 469 cb(event)
470 except Exception:
471 _handle_exception(self.ignore_callback_errors,
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:218, in SceneCanvas.on_draw(self, event)
215 # Now that a draw event is going to be handled, open up the
216 # scheduling of further updates
217 self._update_pending = False
--> 218 self._draw_scene()
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:277, in SceneCanvas._draw_scene(self, bgcolor)
275 bgcolor = self._bgcolor
276 self.context.clear(color=bgcolor, depth=True)
--> 277 self.draw_visual(self.scene)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:315, in SceneCanvas.draw_visual(self, visual, event)
313 else:
314 if hasattr(node, 'draw'):
--> 315 node.draw()
316 prof.mark(str(node))
317 else:
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/visuals.py:103, in VisualNode.draw(self)
101 if self.picking and not self.interactive:
102 return
--> 103 self._visual_superclass.draw(self)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/visuals/visual.py:451, in Visual.draw(self)
449 self._configure_gl_state()
450 try:
--> 451 self._program.draw(self._vshare.draw_mode,
452 self._vshare.index_buffer)
453 except Exception:
454 logger.warning("Error drawing visual %r" % self)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/visuals/shaders/program.py:102, in ModularProgram.draw(self, *args, **kwargs)
100 self.build_if_needed()
101 self.update_variables()
--> 102 Program.draw(self, *args, **kwargs)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/program.py:526, in Program.draw(self, mode, indices, check_error)
522 raise TypeError("Invalid index: %r (must be IndexBuffer)" %
523 indices)
525 # Process GLIR commands
--> 526 canvas.context.flush_commands()
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/context.py:172, in GLContext.flush_commands(self, event)
170 fbo = 0
171 self.shared.parser.parse([('CURRENT', 0, fbo)])
--> 172 self.glir.flush(self.shared.parser)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:582, in GlirQueue.flush(self, parser)
580 def flush(self, parser):
581 """Flush all current commands to the GLIR interpreter."""
--> 582 self._shared.flush(parser)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:504, in _GlirQueueShare.flush(self, parser)
502 show = self._verbose if isinstance(self._verbose, str) else None
503 self.show(show)
--> 504 parser.parse(self._filter(self.clear(), parser))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:822, in GlirParser.parse(self, commands)
819 self._objects.pop(id_)
821 for command in commands:
--> 822 self._parse(command)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:778, in GlirParser._parse(self, command)
776 if ob is None:
777 if id_ not in self._invalid_objects:
--> 778 raise RuntimeError('Cannot %s object %i because it '
779 'does not exist' % (cmd, id_))
780 return
781 # Triage over command. Order of commands is set so most
782 # common ones occur first.
RuntimeError: Cannot SIZE object 131 because it does not exist
WARNING: Error drawing visual <Volume at 0x7f8db42bb010>
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/app/backends/_qt.py:903, in CanvasBackendDesktop.paintGL(self)
901 # (0, 0, self.width(), self.height()))
902 self._vispy_canvas.set_current()
--> 903 self._vispy_canvas.events.draw(region=None)
905 # Clear the alpha channel with QOpenGLWidget (Qt >= 5.4), otherwise the
906 # window is translucent behind non-opaque objects.
907 # Reference: MRtrix3/mrtrix3#266
908 if QT5_NEW_API or PYSIDE6_API or PYQT6_API:
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:453, in EventEmitter.__call__(self, *args, **kwargs)
450 if self._emitting > 1:
451 raise RuntimeError('EventEmitter loop detected!')
--> 453 self._invoke_callback(cb, event)
454 if event.blocked:
455 break
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:471, in EventEmitter._invoke_callback(self, cb, event)
469 cb(event)
470 except Exception:
--> 471 _handle_exception(self.ignore_callback_errors,
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:469, in EventEmitter._invoke_callback(self, cb, event)
467 def _invoke_callback(self, cb, event):
468 try:
--> 469 cb(event)
470 except Exception:
471 _handle_exception(self.ignore_callback_errors,
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:218, in SceneCanvas.on_draw(self, event)
215 # Now that a draw event is going to be handled, open up the
216 # scheduling of further updates
217 self._update_pending = False
--> 218 self._draw_scene()
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:277, in SceneCanvas._draw_scene(self, bgcolor)
275 bgcolor = self._bgcolor
276 self.context.clear(color=bgcolor, depth=True)
--> 277 self.draw_visual(self.scene)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:315, in SceneCanvas.draw_visual(self, visual, event)
313 else:
314 if hasattr(node, 'draw'):
--> 315 node.draw()
316 prof.mark(str(node))
317 else:
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/visuals.py:103, in VisualNode.draw(self)
101 if self.picking and not self.interactive:
102 return
--> 103 self._visual_superclass.draw(self)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/visuals/visual.py:451, in Visual.draw(self)
449 self._configure_gl_state()
450 try:
--> 451 self._program.draw(self._vshare.draw_mode,
452 self._vshare.index_buffer)
453 except Exception:
454 logger.warning("Error drawing visual %r" % self)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/visuals/shaders/program.py:102, in ModularProgram.draw(self, *args, **kwargs)
100 self.build_if_needed()
101 self.update_variables()
--> 102 Program.draw(self, *args, **kwargs)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/program.py:526, in Program.draw(self, mode, indices, check_error)
522 raise TypeError("Invalid index: %r (must be IndexBuffer)" %
523 indices)
525 # Process GLIR commands
--> 526 canvas.context.flush_commands()
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/context.py:172, in GLContext.flush_commands(self, event)
170 fbo = 0
171 self.shared.parser.parse([('CURRENT', 0, fbo)])
--> 172 self.glir.flush(self.shared.parser)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:582, in GlirQueue.flush(self, parser)
580 def flush(self, parser):
581 """Flush all current commands to the GLIR interpreter."""
--> 582 self._shared.flush(parser)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:504, in _GlirQueueShare.flush(self, parser)
502 show = self._verbose if isinstance(self._verbose, str) else None
503 self.show(show)
--> 504 parser.parse(self._filter(self.clear(), parser))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:822, in GlirParser.parse(self, commands)
819 self._objects.pop(id_)
821 for command in commands:
--> 822 self._parse(command)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:778, in GlirParser._parse(self, command)
776 if ob is None:
777 if id_ not in self._invalid_objects:
--> 778 raise RuntimeError('Cannot %s object %i because it '
779 'does not exist' % (cmd, id_))
780 return
781 # Triage over command. Order of commands is set so most
782 # common ones occur first.
RuntimeError: Cannot SIZE object 131 because it does not exist
WARNING: Error drawing visual <Volume at 0x7f8db42bb010>
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/app/backends/_qt.py:903, in CanvasBackendDesktop.paintGL(self)
901 # (0, 0, self.width(), self.height()))
902 self._vispy_canvas.set_current()
--> 903 self._vispy_canvas.events.draw(region=None)
905 # Clear the alpha channel with QOpenGLWidget (Qt >= 5.4), otherwise the
906 # window is translucent behind non-opaque objects.
907 # Reference: MRtrix3/mrtrix3#266
908 if QT5_NEW_API or PYSIDE6_API or PYQT6_API:
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:453, in EventEmitter.__call__(self, *args, **kwargs)
450 if self._emitting > 1:
451 raise RuntimeError('EventEmitter loop detected!')
--> 453 self._invoke_callback(cb, event)
454 if event.blocked:
455 break
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:471, in EventEmitter._invoke_callback(self, cb, event)
469 cb(event)
470 except Exception:
--> 471 _handle_exception(self.ignore_callback_errors,
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:469, in EventEmitter._invoke_callback(self, cb, event)
467 def _invoke_callback(self, cb, event):
468 try:
--> 469 cb(event)
470 except Exception:
471 _handle_exception(self.ignore_callback_errors,
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:218, in SceneCanvas.on_draw(self, event)
215 # Now that a draw event is going to be handled, open up the
216 # scheduling of further updates
217 self._update_pending = False
--> 218 self._draw_scene()
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:277, in SceneCanvas._draw_scene(self, bgcolor)
275 bgcolor = self._bgcolor
276 self.context.clear(color=bgcolor, depth=True)
--> 277 self.draw_visual(self.scene)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:315, in SceneCanvas.draw_visual(self, visual, event)
313 else:
314 if hasattr(node, 'draw'):
--> 315 node.draw()
316 prof.mark(str(node))
317 else:
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/visuals.py:103, in VisualNode.draw(self)
101 if self.picking and not self.interactive:
102 return
--> 103 self._visual_superclass.draw(self)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/visuals/visual.py:451, in Visual.draw(self)
449 self._configure_gl_state()
450 try:
--> 451 self._program.draw(self._vshare.draw_mode,
452 self._vshare.index_buffer)
453 except Exception:
454 logger.warning("Error drawing visual %r" % self)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/visuals/shaders/program.py:102, in ModularProgram.draw(self, *args, **kwargs)
100 self.build_if_needed()
101 self.update_variables()
--> 102 Program.draw(self, *args, **kwargs)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/program.py:526, in Program.draw(self, mode, indices, check_error)
522 raise TypeError("Invalid index: %r (must be IndexBuffer)" %
523 indices)
525 # Process GLIR commands
--> 526 canvas.context.flush_commands()
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/context.py:172, in GLContext.flush_commands(self, event)
170 fbo = 0
171 self.shared.parser.parse([('CURRENT', 0, fbo)])
--> 172 self.glir.flush(self.shared.parser)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:582, in GlirQueue.flush(self, parser)
580 def flush(self, parser):
581 """Flush all current commands to the GLIR interpreter."""
--> 582 self._shared.flush(parser)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:504, in _GlirQueueShare.flush(self, parser)
502 show = self._verbose if isinstance(self._verbose, str) else None
503 self.show(show)
--> 504 parser.parse(self._filter(self.clear(), parser))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:822, in GlirParser.parse(self, commands)
819 self._objects.pop(id_)
821 for command in commands:
--> 822 self._parse(command)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:778, in GlirParser._parse(self, command)
776 if ob is None:
777 if id_ not in self._invalid_objects:
--> 778 raise RuntimeError('Cannot %s object %i because it '
779 'does not exist' % (cmd, id_))
780 return
781 # Triage over command. Order of commands is set so most
782 # common ones occur first.
RuntimeError: Cannot SIZE object 131 because it does not exist
WARNING: Error drawing visual <Volume at 0x7f8db42bb010>
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/app/backends/_qt.py:903, in CanvasBackendDesktop.paintGL(self)
901 # (0, 0, self.width(), self.height()))
902 self._vispy_canvas.set_current()
--> 903 self._vispy_canvas.events.draw(region=None)
905 # Clear the alpha channel with QOpenGLWidget (Qt >= 5.4), otherwise the
906 # window is translucent behind non-opaque objects.
907 # Reference: MRtrix3/mrtrix3#266
908 if QT5_NEW_API or PYSIDE6_API or PYQT6_API:
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:453, in EventEmitter.__call__(self, *args, **kwargs)
450 if self._emitting > 1:
451 raise RuntimeError('EventEmitter loop detected!')
--> 453 self._invoke_callback(cb, event)
454 if event.blocked:
455 break
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:471, in EventEmitter._invoke_callback(self, cb, event)
469 cb(event)
470 except Exception:
--> 471 _handle_exception(self.ignore_callback_errors,
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/util/event.py:469, in EventEmitter._invoke_callback(self, cb, event)
467 def _invoke_callback(self, cb, event):
468 try:
--> 469 cb(event)
470 except Exception:
471 _handle_exception(self.ignore_callback_errors,
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:218, in SceneCanvas.on_draw(self, event)
215 # Now that a draw event is going to be handled, open up the
216 # scheduling of further updates
217 self._update_pending = False
--> 218 self._draw_scene()
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:277, in SceneCanvas._draw_scene(self, bgcolor)
275 bgcolor = self._bgcolor
276 self.context.clear(color=bgcolor, depth=True)
--> 277 self.draw_visual(self.scene)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/canvas.py:315, in SceneCanvas.draw_visual(self, visual, event)
313 else:
314 if hasattr(node, 'draw'):
--> 315 node.draw()
316 prof.mark(str(node))
317 else:
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/scene/visuals.py:103, in VisualNode.draw(self)
101 if self.picking and not self.interactive:
102 return
--> 103 self._visual_superclass.draw(self)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/visuals/visual.py:451, in Visual.draw(self)
449 self._configure_gl_state()
450 try:
--> 451 self._program.draw(self._vshare.draw_mode,
452 self._vshare.index_buffer)
453 except Exception:
454 logger.warning("Error drawing visual %r" % self)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/visuals/shaders/program.py:102, in ModularProgram.draw(self, *args, **kwargs)
100 self.build_if_needed()
101 self.update_variables()
--> 102 Program.draw(self, *args, **kwargs)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/program.py:526, in Program.draw(self, mode, indices, check_error)
522 raise TypeError("Invalid index: %r (must be IndexBuffer)" %
523 indices)
525 # Process GLIR commands
--> 526 canvas.context.flush_commands()
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/context.py:172, in GLContext.flush_commands(self, event)
170 fbo = 0
171 self.shared.parser.parse([('CURRENT', 0, fbo)])
--> 172 self.glir.flush(self.shared.parser)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:582, in GlirQueue.flush(self, parser)
580 def flush(self, parser):
581 """Flush all current commands to the GLIR interpreter."""
--> 582 self._shared.flush(parser)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:504, in _GlirQueueShare.flush(self, parser)
502 show = self._verbose if isinstance(self._verbose, str) else None
503 self.show(show)
--> 504 parser.parse(self._filter(self.clear(), parser))
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:822, in GlirParser.parse(self, commands)
819 self._objects.pop(id_)
821 for command in commands:
--> 822 self._parse(command)
File /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/vispy/gloo/glir.py:778, in GlirParser._parse(self, command)
776 if ob is None:
777 if id_ not in self._invalid_objects:
--> 778 raise RuntimeError('Cannot %s object %i because it '
779 'does not exist' % (cmd, id_))
780 return
781 # Triage over command. Order of commands is set so most
782 # common ones occur first.
RuntimeError: Cannot SIZE object 131 because it does not exist