Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proof of principle example using napari with full 3D interaction in jupyter notebook #5090

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 140 additions & 0 deletions examples/in_notebook_with_rfb.ipynb

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions napari/_qt/qt_main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,10 @@ def __init__(self, viewer: 'Viewer', parent=None) -> None:
# we need to manually connect them again.
handle = self.windowHandle()
if handle is not None:
handle.screenChanged.connect(
self._qt_viewer.canvas._backend.screen_changed
)
with contextlib.suppress(AttributeError):
handle.screenChanged.connect(
self._qt_viewer.canvas._backend.screen_changed
)

self.status_throttler = QSignalThrottler(parent=self)
self.status_throttler.setTimeout(50)
Expand Down
3 changes: 2 additions & 1 deletion napari/_qt/widgets/qt_welcome.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ def __init__(self, parent, widget):
self._overlay = QtWelcomeWidget(self)

# Widget setup
self.addWidget(widget)
if isinstance(widget, QWidget):
self.addWidget(widget)
self.addWidget(self._overlay)
self.setCurrentIndex(0)

Expand Down
7 changes: 5 additions & 2 deletions napari/_vispy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
from vispy import app

# set vispy application to the appropriate qt backend
app.use_app(qtpy.API_NAME)
del app
try:
app.use_app(qtpy.API_NAME)
del app
except RuntimeError:
pass

# set vispy logger to show warning and errors only
vispy_logger = logging.getLogger('vispy')
Expand Down
15 changes: 13 additions & 2 deletions napari/_vispy/canvas.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
"""VispyCanvas class.
"""

import contextlib
from weakref import WeakSet

from qtpy.QtCore import QSize
from qtpy.QtWidgets import QWidget
from vispy.scene import SceneCanvas, Widget

from ..utils.colormaps.standardize_color import transform_color
Expand Down Expand Up @@ -41,12 +44,16 @@ def __init__(self, *args, **kwargs):
self.max_texture_sizes = get_max_texture_sizes()

self.events.ignore_callback_errors = False
self.native.setMinimumSize(QSize(200, 200))
with contextlib.suppress(AttributeError):
self.native.setMinimumSize(QSize(200, 200))
self.context.set_depth_func('lequal')

@property
def destroyed(self):
return self._backend.destroyed
if hasattr(self._backend, 'destroyed'):
return self._backend.destroyed

return type("Mock", (), {'connect': lambda *_, **__: None})

@property
def background_color_override(self):
Expand All @@ -57,6 +64,10 @@ def background_color_override(self, value):
self._background_color_override = value
self.bgcolor = value or self._last_theme_color

@property
def is_qt(self) -> bool:
return isinstance(self._backend, QWidget)

def _on_theme_change(self, event):
self._set_theme_change(event.value)

Expand Down
5 changes: 4 additions & 1 deletion napari/_vispy/overlays/axes.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from contextlib import suppress

import numpy as np
from vispy.scene.visuals import Compound, Line, Mesh, Text
from vispy.visuals.transforms import STTransform
Expand Down Expand Up @@ -204,7 +206,8 @@ def __init__(self, viewer, parent=None, order=0):
self.text_node.anchors = ('center', 'center')
self.text_node.text = f'{1}'

self.node.canvas._backend.destroyed.connect(self._set_canvas_none)
with suppress(AttributeError):
self.node.canvas._backend.destroyed.connect(self._set_canvas_none)
# End Note

self._viewer.events.theme.connect(self._on_data_change)
Expand Down
14 changes: 11 additions & 3 deletions napari/_vispy/overlays/scale_bar.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Scale Bar overlay."""
import bisect
from contextlib import suppress

import numpy as np
from vispy.scene.visuals import Line, Rectangle, Text
Expand Down Expand Up @@ -59,9 +60,16 @@ def __init__(self, viewer, parent=None, order=0):
self.rect_node.transform = STTransform()

# the two canvas are not the same object, better be safe.
self.rect_node.canvas._backend.destroyed.connect(self._set_canvas_none)
self.line_node.canvas._backend.destroyed.connect(self._set_canvas_none)
self.text_node.canvas._backend.destroyed.connect(self._set_canvas_none)
with suppress(AttributeError):
self.rect_node.canvas._backend.destroyed.connect(
self._set_canvas_none
)
self.line_node.canvas._backend.destroyed.connect(
self._set_canvas_none
)
self.text_node.canvas._backend.destroyed.connect(
self._set_canvas_none
)
assert self.rect_node.canvas is self.line_node.canvas
assert self.line_node.canvas is self.text_node.canvas
# End Note
Expand Down
9 changes: 9 additions & 0 deletions napari/viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,15 @@ def close_all(cls) -> int:
viewer.close()
return ret

def _repr_mimebundle_(self, *a, **k):
rep = getattr(
self.window._qt_viewer.canvas.native, '_repr_mimebundle_', None
)
if rep is not None:
self.camera.zoom = 1
return rep()
raise NotImplementedError()


def current_viewer() -> Optional[Viewer]:
"""Return the currently active napari viewer."""
Expand Down