vispy / jupyter_rfb

Remote Frame Buffer for Jupyter
https://jupyter-rfb.readthedocs.io
MIT License
58 stars 10 forks source link

Multiple vispy visualisations in one notebook #99

Open sanjayankur31 opened 1 month ago

sanjayankur31 commented 1 month ago

Hi folks,

I was trying to get multiple visualizations in the same notebook, for example as one would do with matplotlib where one has multiple plots.

Is this expected to work? In the simple examples that I have here, it seems like creating a new vispy canvas/visualization affects the previous one too.

I've taken one of the vispy examples and just split it into two different visualizations:

from vispy import scene
from vispy.geometry.torusknot import TorusKnot

import numpy as np
canvas = scene.SceneCanvas(keys='interactive')
view = canvas.central_widget.add_view()

points1 = TorusKnot(5, 3).first_component[:-1]
points1[:, 0] -= 20.
points1[:, 2] -= 15.

points2 = points1.copy()
points2[:, 2] += 30.

l1 = scene.visuals.Tube(points1,
                        shading='flat',
                        color='red',
                        tube_points=8)

l2 = scene.visuals.Tube(points2,
                        color=['red', 'green', 'blue'],
                        shading='smooth',
                        tube_points=8)

view.add(l1)
view.add(l2)
view.camera = scene.TurntableCamera()
# tube does not expose its limits yet
view.camera.set_range((-20, 20), (-20, 20), (-20, 20))
canvas

and

newcanvas = scene.SceneCanvas(keys='interactive')
newview = newcanvas.central_widget.add_view()

points3 = points1.copy()
points3[:, 0] += 41.
points3[:, 2] += 30

points4 = points1.copy()
points4[:, 0] += 41.

points5 = points1.copy()
points5[:, 0] += 20.4
points5[:, 2] += 15

l3 = scene.visuals.Tube(points3,
                        color='green',
                        shading='flat',
                        tube_points=8,
                        closed=True)

l4 = scene.visuals.Tube(points4,
                        color='blue',
                        shading='smooth',
                        tube_points=8,
                        mode='lines')

# generate sine wave radii
radii = np.sin(2 * np.pi * 440 * np.arange(points5.shape[0]) / 44000)
radii = (radii + 1.5) / 2

l5 = scene.visuals.Tube(points5,
                        radius=radii,
                        color='white',
                        shading='smooth',
                        closed=True,
                        tube_points=8)

newview.add(l3)
newview.add(l4)
newview.add(l5)
newview.camera = scene.TurntableCamera()
# tube does not expose its limits yet
newview.camera.set_range((-20, 20), (-20, 20), (-20, 20))
newcanvas

Until i run the third cell, the second cell works fine. Once I run the third cell, the second cell is also modified. Video attached:

https://github.com/user-attachments/assets/ade109e9-9c10-4b00-88c6-7e0d1291be72

I tried it with vispy outside of a jupyter notebook, and it does work. I get two windows with the expected outputs and they're independent of each other. Here's that script:

#!/usr/bin/env python3

from vispy import scene
from vispy.geometry.torusknot import TorusKnot

import numpy as np

canvas = scene.SceneCanvas(keys='interactive')
view = canvas.central_widget.add_view()

points1 = TorusKnot(5, 3).first_component[:-1]
points1[:, 0] -= 20.
points1[:, 2] -= 15.

points2 = points1.copy()
points2[:, 2] += 30.

l1 = scene.visuals.Tube(points1,
                        shading='flat',
                        color='red',
                        tube_points=8)

l2 = scene.visuals.Tube(points2,
                        color=['red', 'green', 'blue'],
                        shading='smooth',
                        tube_points=8)

view.add(l1)
view.add(l2)
view.camera = scene.TurntableCamera()
# tube does not expose its limits yet
view.camera.set_range((-20, 20), (-20, 20), (-20, 20))
canvas.show()

newcanvas = scene.SceneCanvas(keys='interactive')
newview = newcanvas.central_widget.add_view()

points3 = points1.copy()
points3[:, 0] += 41.
points3[:, 2] += 30

points4 = points1.copy()
points4[:, 0] += 41.

points5 = points1.copy()
points5[:, 0] += 20.4
points5[:, 2] += 15

l3 = scene.visuals.Tube(points3,
                        color='green',
                        shading='flat',
                        tube_points=8,
                        closed=True)

l4 = scene.visuals.Tube(points4,
                        color='blue',
                        shading='smooth',
                        tube_points=8,
                        mode='lines')

# generate sine wave radii
radii = np.sin(2 * np.pi * 440 * np.arange(points5.shape[0]) / 44000)
radii = (radii + 1.5) / 2

l5 = scene.visuals.Tube(points5,
                        radius=radii,
                        color='white',
                        shading='smooth',
                        closed=True,
                        tube_points=8)

newview.add(l3)
newview.add(l4)
newview.add(l5)
newview.camera = scene.TurntableCamera()
# tube does not expose its limits yet
newview.camera.set_range((-20, 20), (-20, 20), (-20, 20))
newcanvas.show()

canvas.app.run()

It's the same as the notebook, but uses canvas.show() and then has the app.run() call at the end.

sanjayankur31 commented 1 month ago

CC: @lej0hn

almarklein commented 2 weeks ago

This is supposed to work. For some reason the first canvas now takes the content of the second. Not sure whether this is related to jupyter_rfb or vispy. Will have to look into this.

sanjayankur31 commented 2 weeks ago

Thanks @almarklein . Please do let me know if there's any more information I can provide. Also happy to help with any testing etc.