Using a VTK panel with a Pipeline

Hi Everyone,

I am trying to use a VTK pane with a pipeline but when I click next or back the VTK pane remains on the screen and if I revisit the VTK pane another VTK view is added. Can anyone help me, please? He is some example code:

import pyvista as pv
import panel as pn
import param
import vtk
from vtk.util.colors import tomato
import pyvista as pv

pn.extension('katex', 'vtk')

class Stage1(param.Parameterized):

    a = param.Integer(default=2, bounds=(0, 10))
    b = param.Integer(default=3, bounds=(0, 10))

    @param.output(('c', param.Integer), ('d', param.Integer))
    def output(self):
        return self.a * self.b, self.a ** self.b

    @param.depends('a', 'b')
    def view(self):
        c, d = self.output()
        c_out = pn.pane.LaTeX('${a} * {b} = {c}$'.format(
            a=self.a, b=self.b, c=c), styles={'font-size': '2em'})
        d_out = pn.pane.LaTeX('${a}^{{{b}}} = {d}$'.format(
            a=self.a, b=self.b, d=d), styles={'font-size': '2em'})
        return pn.Column(
		    c_out, d_out,  margin=(40, 10), styles={'background': '#f0f0f0'}
		)

    def panel(self):
        return pn.Row(self.param, self.view,)
    

class Stage2(param.Parameterized):

    c = param.Integer(default=6, bounds=(0, None))
    exp = param.Number(default=0.1, bounds=(0, 3))

    @param.depends('c', 'exp')
    def view(self):
        out = pn.pane.LaTeX('${%s}^{%s}={%.3f}$' % (self.c, self.exp, self.c**self.exp),
                      styles={'font-size': '2em'})
        return pn.Column(out, margin=(40, 10), styles={'background': '#f0f0f0'})

    def panel(self):
        return pn.Row(self.param, self.view)
    
class Stage3(param.Parameterized):

    def panel(self):
        plotter = pv.Plotter() # we define a pyvista plotter
        plotter.background_color = (0.1, 0.2, 0.4)
        # we create a `VTK` panel around the render window
        geo_pan_pv = pn.panel(plotter.ren_win, width=500, height=500)
        pvcylinder = pv.Cylinder(resolution=8, direction=(0,1,0))
        cylinder_actor = plotter.add_mesh(pvcylinder, color=tomato, smooth_shading=True)
        return geo_pan_pv


pipeline = pn.pipeline.Pipeline()

pipeline.add_stage('Stage 1', Stage1)
pipeline.add_stage('Stage 2', Stage2)
pipeline.add_stage('Stage 3', Stage3)
pipeline.servable()

Thanks,
Dave

Some suggestions
https://panel.holoviz.org/how_to/best_practices/user_experience.html#reuse-objects-for-efficiency
https://panel.holoviz.org/how_to/best_practices/dev_experience.html#refreshing-layout-objects

Maybe placeholder too
https://panel.holoviz.org/reference/panes/Placeholder.html

Thank you for your suggestions. I have updated my code using some of your suggestions but the same behaviour still occurs. The issue is not waiting for the pane to appear when I am on the VTK stage of the pipeline but when I click ‘next’ or ‘previous’ to change stage away from the VTK stage. It is like there is a call to ‘synchronize’ on the VTK pane that is missing but I do not know where the call is missing from.

import pyvista as pv
import panel as pn
import param
import vtk
from vtk.util.colors import tomato
import pyvista as pv

pn.extension('katex', 'vtk')

class Stage1(param.Parameterized):

    a = param.Integer(default=2, bounds=(0, 10))
    b = param.Integer(default=3, bounds=(0, 10))

    @param.output(('c', param.Integer), ('d', param.Integer))
    def output(self):
        return self.a * self.b, self.a ** self.b

    @param.depends('a', 'b')
    def view(self):
        c, d = self.output()
        c_out = pn.pane.LaTeX('${a} * {b} = {c}$'.format(
            a=self.a, b=self.b, c=c), styles={'font-size': '2em'})
        d_out = pn.pane.LaTeX('${a}^{{{b}}} = {d}$'.format(
            a=self.a, b=self.b, d=d), styles={'font-size': '2em'})
        return pn.Column(
		    c_out, d_out,  margin=(40, 10), styles={'background': '#f0f0f0'}
		)

    def panel(self):
        return pn.Row(self.param, self.view,)
    

class Stage2(param.Parameterized):

    c = param.Integer(default=6, bounds=(0, None))
    exp = param.Number(default=0.1, bounds=(0, 3))

    @param.depends('c', 'exp')
    def view(self):
        out = pn.pane.LaTeX('${%s}^{%s}={%.3f}$' % (self.c, self.exp, self.c**self.exp),
                      styles={'font-size': '2em'})
        return pn.Column(out, margin=(40, 10), styles={'background': '#f0f0f0'})

    def panel(self):
        return pn.Row(self.param, self.view)
    
class Stage3(param.Parameterized):

    resolution = param.Integer(default=8, bounds=(6, 30))


    def __init__(self, **params):
        super().__init__(**params)
        self.plotter = pv.Plotter()
        _ = self.plotter.add_bounding_box(line_width=5, color='black')
        self.geo_pan_pv = pn.pane.VTK(self.plotter.ren_win, width=500, height=500, orientation_widget=True)

        pvcylinder = pv.Cylinder(resolution=self.resolution, direction=(0,1,0))
        cylinder_actor = self.plotter.add_mesh(pvcylinder, color=tomato, smooth_shading=True)

    @param.depends('resolution')
    def view(self):
        self.plotter.clear()
        pvcylinder = pv.Cylinder(resolution=self.resolution, direction=(0,1,0))
        cylinder_actor = self.plotter.add_mesh(pvcylinder, color=tomato, smooth_shading=True)
        self.geo_pan_pv.synchronize()
        return self.geo_pan_pv

    def panel(self):
        return pn.Row(self.param, self.view, width=500, height=500)

class Stage4(param.Parameterized):

    f = param.Integer(default=20, bounds=(0, None))

    def panel(self):
        return pn.Row(self.param)

pipeline = pn.pipeline.Pipeline()

pipeline.add_stage('Stage 1', Stage1)
pipeline.add_stage('Stage 2', Stage2)
pipeline.add_stage('Stage 3', Stage3)
pipeline.add_stage('Stage 4', Stage4)
pipeline.servable()