# Trame + VTK + Plotly Application - vue2 or vue3?

**URL:** https://discourse.vtk.org/t/trame-vtk-plotly-application-vue2-or-vue3/15954
**Category:** Development
**Tags:** trame, python, vtkjs
**Created:** [August 12, 2025, 1:47pm UTC](https://discourse.vtk.org/t/trame-vtk-plotly-application-vue2-or-vue3/15954 "2025-08-12T13:47:59Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![firinini](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/f/9f8e36/32.png) [@firinini](https://discourse.vtk.org/u/firinini)
#### Post date: [August 12, 2025, 1:47pm UTC](https://discourse.vtk.org/t/trame-vtk-plotly-application-vue2-or-vue3/15954/1 "2025-08-12T13:47:59Z")

</div>

Hi,

I am trying to utilize both the vtk and plotly widgets in my trame application and have issues getting the right dependencies in place.

As a layer of abstraction, I tried to install the dependencies for running this example:

> **[trame | trame](https://kitware.github.io/trame/examples/vtk/selection.html)**
>
> Trame lets you weave various components and technologies into a Web Application solely written in Python

When I just install things via pip I get

```auto
trame 3.11.0
trame-client 3.9.2
trame-common 1.0.1
trame-components 2.5.0
trame-plotly 3.1.0
trame-server 3.6.0
trame-vtk 2.9.1
trame-vuetify 3.0.2

```

with a JS error while TRAME is in loading state:

```auto
JS Error => error: Uncaught TypeError: r.a.extend is not a function

```

When I manually downgrade to `trame==2.5.2` I get

```auto
trame 2.5.2
trame-client 3.9.2
trame-common 1.0.1
trame-components 2.5.0
trame-deckgl 2.0.3
trame-markdown 2.0.2
trame-matplotlib 2.0.3
trame-plotly 2.1.1
trame-rca 2.1.3
trame-router 2.3.0
trame-server 3.6.0
trame-simput 2.6.0
trame-vega 2.1.1
trame-vtk 2.9.1
trame-vuetify 2.9.0

```

with error:

```auto
python3.13/site-packages/trame/ui/ __init__.py", line 1, in <module>
    __import__ ("pkg_resources").declare_namespace( __name__ )
ModuleNotFoundError: No module named 'pkg_resources'

```

To me it appears that both errors have to do with version conflicts of vuetify?  
Is there a recommended environment to run trame-plotly and trame-vtk widgets within the same application?

Thanks!

---

<div class="post-metadata">

### Author: ![firinini](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/f/9f8e36/32.png) [@firinini](https://discourse.vtk.org/u/firinini)
#### Post date: [August 12, 2025, 1:54pm UTC](https://discourse.vtk.org/t/trame-vtk-plotly-application-vue2-or-vue3/15954/2 "2025-08-12T13:54:28Z")

</div>

Just found this requirements file on the repo, but it gives me the same issues as with the first trame vs. 3 installation …

> <https://github.com/Kitware/trame/blob/master/examples/06_vtk/Applications/RemoteSelection/requirements.txt>

---

<div class="post-metadata">

### Author: ![firinini](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/f/9f8e36/32.png) [@firinini](https://discourse.vtk.org/u/firinini)
#### Post date: [August 12, 2025, 6:33pm UTC](https://discourse.vtk.org/t/trame-vtk-plotly-application-vue2-or-vue3/15954/3 "2025-08-12T18:33:51Z")

</div>

To answer my own question:

I made it work by going with vuetify3 and updating the code example ever so slightly:

```auto
import pandas as pd

# Plotly/chart imports
import plotly.express as px
import vtkmodules.vtkRenderingOpenGL2 # noqa

# Trame imports
from trame.app import get_server
from trame.assets.remote import HttpFile
from trame.widgets import plotly, trame
from trame.widgets import vtk as vtk_widgets
from trame.widgets import vuetify3 as v3
from trame_vuetify.ui.vuetify3 import SinglePageLayout
from vtkmodules.numpy_interface import dataset_adapter as dsa
from vtkmodules.vtkCommonCore import vtkIdTypeArray
from vtkmodules.vtkCommonDataModel import vtkDataObject, vtkSelection, vtkSelectionNode
from vtkmodules.vtkFiltersExtraction import vtkExtractSelection
from vtkmodules.vtkFiltersGeometry import vtkGeometryFilter
from vtkmodules.vtkInteractionStyle import (
    vtkInteractorStyleRubberBandPick,
) # noqa

# VTK imports
from vtkmodules.vtkIOXML import vtkXMLUnstructuredGridReader
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkDataSetMapper,
    vtkHardwareSelector,
    vtkRenderedAreaPicker,
    vtkRenderer,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
)

# -----------------------------------------------------------------------------
# Data file information
# -----------------------------------------------------------------------------

dataset_file = HttpFile(
    "./data/disk_out_ref.vtu",
    "https://github.com/Kitware/trame/raw/master/examples/data/disk_out_ref.vtu",
    __file__ ,
)

# -------------------------------------------------------------------
# Server
# -------------------------------------------------------------------
server = get_server()
state, ctrl = server.state, server.controller
state.trame__title = "VTK & Plotly"

# -----------------------------------------------------------------------------
# VTK
# -----------------------------------------------------------------------------

reader = vtkXMLUnstructuredGridReader()
reader.SetFileName(dataset_file.path)
reader.Update()
dataset = reader.GetOutput()

renderer = vtkRenderer()
renderer.SetBackground(1, 1, 1)
render_window = vtkRenderWindow()
render_window.AddRenderer(renderer)

rw_interactor = vtkRenderWindowInteractor()
rw_interactor.SetRenderWindow(render_window)
rw_interactor.GetInteractorStyle().SetCurrentStyleToTrackballCamera()

interactor_trackball = rw_interactor.GetInteractorStyle()
interactor_selection = vtkInteractorStyleRubberBandPick()
area_picker = vtkRenderedAreaPicker()
rw_interactor.SetPicker(area_picker)

surface_filter = vtkGeometryFilter()
surface_filter.SetInputConnection(reader.GetOutputPort())
surface_filter.SetPassThroughPointIds(True)

mapper = vtkDataSetMapper()
mapper.SetInputConnection(surface_filter.GetOutputPort())
actor = vtkActor()
actor.GetProperty().SetOpacity(0.5)
actor.SetMapper(mapper)

# Selection
selection_extract = vtkExtractSelection()
selection_mapper = vtkDataSetMapper()
selection_mapper.SetInputConnection(selection_extract.GetOutputPort())
selection_actor = vtkActor()
selection_actor.GetProperty().SetColor(1, 0, 1)
selection_actor.GetProperty().SetPointSize(5)
selection_actor.SetMapper(selection_mapper)
selection_actor.SetVisibility(0)

renderer.AddActor(actor)
renderer.AddActor(selection_actor)
renderer.ResetCamera()

selector = vtkHardwareSelector()
selector.SetRenderer(renderer)
selector.SetFieldAssociation(vtkDataObject.FIELD_ASSOCIATION_POINTS)

# vtkDataSet to DataFrame
py_ds = dsa.WrapDataObject(dataset)
pt_data = py_ds.PointData
cols = {}
for name in pt_data.keys():
    array = pt_data[name]
    shp = array.shape
    if len(shp) == 1:
        cols[name] = array
    else:
        for i in range(shp[1]):
            cols[name + "_%d" % i] = array[:, i]
DATAFRAME = pd.DataFrame(cols)
FIELD_NAMES = list(cols.keys())
SELECTED_IDX = []

# -----------------------------------------------------------------------------
# Callbacks
# -----------------------------------------------------------------------------

@state.change("figure_size", "scatter_x", "scatter_y")
def update_figure(figure_size, scatter_x, scatter_y, **kwargs):
    if figure_size is None:
        return

    # Generate figure
    bounds = figure_size.get("size", {})
    fig = px.scatter(
        DATAFRAME,
        x=scatter_x,
        y=scatter_y,
        width=bounds.get("width", 200),
        height=bounds.get("height", 200),
    )

    # Update selection settings
    fig.data[0].update(
        selectedpoints=SELECTED_IDX,
        selected={"marker": {"color": "red"}},
        unselected={"marker": {"opacity": 0.5}},
    )

    # Update chart
    ctrl.update_figure(fig)

# -----------------------------------------------------------------------------

@state.change("vtk_selection")
def update_interactor(vtk_selection, **kwargs):
    if vtk_selection:
        # remote view
        rw_interactor.SetInteractorStyle(interactor_selection)
        interactor_selection.StartSelect()
        # local view
        state.interactorSettings = VIEW_SELECT
    else:
        # remote view
        rw_interactor.SetInteractorStyle(interactor_trackball)
        # local view
        state.interactorSettings = VIEW_INTERACT

# -----------------------------------------------------------------------------

def on_chart_selection(selected_point_idxs):
    global SELECTED_IDX
    SELECTED_IDX = selected_point_idxs if selected_point_idxs else []
    npts = len(SELECTED_IDX)

    ids = vtkIdTypeArray()
    ids.SetNumberOfTuples(npts)
    for idx, p_id in enumerate(SELECTED_IDX):
        ids.SetTuple1(idx, p_id)
        idx += 1

    sel_node = vtkSelectionNode()
    sel_node.GetProperties().Set(
        vtkSelectionNode.CONTENT_TYPE(), vtkSelectionNode.INDICES
    )
    sel_node.GetProperties().Set(vtkSelectionNode.FIELD_TYPE(), vtkSelectionNode.POINT)
    sel_node.SetSelectionList(ids)
    sel = vtkSelection()
    sel.AddNode(sel_node)

    selection_extract.SetInputDataObject(0, py_ds.VTKObject)
    selection_extract.SetInputDataObject(1, sel)
    selection_extract.Update()
    selection_actor.SetVisibility(1)

    # Update 3D view
    ctrl.view_update()

def on_box_selection_change(selection):
    global SELECTED_IDX
    if selection.get("mode") == "remote":
        actor.GetProperty().SetOpacity(1)
        selector.SetArea(
            int(renderer.GetPickX1()),
            int(renderer.GetPickY1()),
            int(renderer.GetPickX2()),
            int(renderer.GetPickY2()),
        )
    elif selection.get("mode") == "local":
        camera = renderer.GetActiveCamera()
        camera_props = selection.get("camera")

        # Sync client view to server one
        camera.SetPosition(camera_props.get("position"))
        camera.SetFocalPoint(camera_props.get("focalPoint"))
        camera.SetViewUp(camera_props.get("viewUp"))
        camera.SetParallelProjection(camera_props.get("parallelProjection"))
        camera.SetParallelScale(camera_props.get("parallelScale"))
        camera.SetViewAngle(camera_props.get("viewAngle"))
        render_window.SetSize(selection.get("size"))

        actor.GetProperty().SetOpacity(1)
        render_window.Render()

        area = selection.get("selection")
        selector.SetArea(
            int(area[0]),
            int(area[2]),
            int(area[1]),
            int(area[3]),
        )

    # Common server selection
    s = selector.Select()
    n = s.GetNode(0)
    ids = dsa.vtkDataArrayToVTKArray(n.GetSelectionData().GetArray("SelectedIds"))
    surface = dsa.WrapDataObject(surface_filter.GetOutput())
    SELECTED_IDX = surface.PointData["vtkOriginalPointIds"][ids].tolist()

    selection_extract.SetInputConnection(surface_filter.GetOutputPort())
    selection_extract.SetInputDataObject(1, s)
    selection_extract.Update()
    selection_actor.SetVisibility(1)
    actor.GetProperty().SetOpacity(0.5)

    # Update scatter plot with selection
    update_figure(**state.to_dict())

    # Update 3D view
    ctrl.view_update()

    # disable selection mode
    state.vtk_selection = False

# -----------------------------------------------------------------------------
# Settings
# -----------------------------------------------------------------------------

DROPDOWN_STYLES = {
    "dense": True,
    "hide_details": True,
    "classes": "px-2",
    "style": "max-width: calc(25vw - 10px);",
}

CHART_STYLE = {
    "style": "position: absolute; left: 50%; transform: translateX(-50%);",
    "display_mode_bar": ("true",),
    "mode_bar_buttons_to_remove": (
        "chart_buttons",
        [
            "toImage",
            "resetScale2d",
            "zoomIn2d",
            "zoomOut2d",
            "toggleSpikelines",
            "hoverClosestCartesian",
            "hoverCompareCartesian",
        ],
    ),
    "display_logo": ("false",),
}

VTK_VIEW_SETTINGS = {
    "interactive_ratio": 1,
    "interactive_quality": 80,
}

VIEW_INTERACT = [
    {"button": 1, "action": "Rotate"},
    {"button": 2, "action": "Pan"},
    {"button": 3, "action": "Zoom", "scrollEnabled": True},
    {"button": 1, "action": "Pan", "alt": True},
    {"button": 1, "action": "Zoom", "control": True},
    {"button": 1, "action": "Pan", "shift": True},
    {"button": 1, "action": "Roll", "alt": True, "shift": True},
]

VIEW_SELECT = [{"button": 1, "action": "Select"}]

# -------------------------------------------------------------------
# UI
# -------------------------------------------------------------------
with SinglePageLayout(server) as layout:
    layout.title.set_text("VTK & plotly")
    layout.icon.click = ctrl.view_reset_camera

    with layout.toolbar as tb:
        tb.dense = True
        v3.VSpacer()
        v3.VSelect(
            label="Scatter Y",
            items=("fields", []), # fill from your FIELD_NAMES
            model_value=("scatter_y", None),
            density="compact",
            hide_details=True,
            style="max-width: calc(25vw - 10px);",
        )
        v3.VSelect(
            label="Scatter X",
            items=("fields", []),
            model_value=("scatter_x", None),
            density="compact",
            hide_details=True,
            style="max-width: calc(25vw - 10px);",
        )

    with layout.content:
        with v3.VContainer(fluid=True, classes="fill-height pa-0 ma-0"):
            with v3.VRow(dense=True, style="height: 100%;"):
                with v3.VCol(
                    classes="pa-0",
                    style="border-right: 1px solid #ccc; position: relative;",
                ):
                    view = vtk_widgets.VtkRemoteView(
                        render_window, # your VTK render_window
                        box_selection=("vtk_selection",),
                        box_selection_change=(on_box_selection_change, "[$event]"),
                        interactive_ratio=1,
                        interactive_quality=80,
                    )
                    ctrl.view_update = view.update
                    ctrl.view_reset_camera = view.reset_camera
                    v3.VCheckbox(
                        density="compact",
                        hide_details=True,
                        on_icon="mdi-selection-drag",
                        off_icon="mdi-rotate-3d",
                        model_value=("vtk_selection", False),
                        style="position: absolute; top: 0; right: 0; z-index: 1;",
                    )

                with v3.VCol(classes="pa-0"):
                    with trame.SizeObserver("figure_size"):
                        html_plot = plotly.Figure(
                            selected=(
                                on_chart_selection,
                                "[$event?.points.map(({pointIndex}) => pointIndex)]",
                            ),
                            style="position: absolute; left: 50%; transform: translateX(-50%);",
                            display_mode_bar=True,
                        )
                        ctrl.update_figure = html_plot.update

# -------------------------------------------------------------------
# Main
# -------------------------------------------------------------------
if __name__ == " __main__":
    server.start()

```

Anyways, if there are further comments or recommendations I would be happy to learn about them!

---

<div class="post-metadata">

### Author: ![Sebastien\_Jourdain](https://discourse.vtk.org/user_avatar/discourse.vtk.org/sebastien_jourdain/32/100_2.png) [@Sebastien\_Jourdain](https://discourse.vtk.org/u/Sebastien_Jourdain)
#### Post date: [August 15, 2025, 8:42pm UTC](https://discourse.vtk.org/t/trame-vtk-plotly-application-vue2-or-vue3/15954/4 "2025-08-15T20:42:59Z")

</div>

I think vuetify2 expects `pkg_resources` to do some introspection and that used to be there in previous version of Python. So you could have solved it by googling the error and installing the now missing package.
