Skip to content

Plotly with callback / widget no longer works since Plotly v6.0.0 #192

@julibeg

Description

@julibeg

Consider the MWE below (adapted from the plotly docs for click events. When rendering a plot outside a module, everything works as expected (i.e. clicking on points updates them):

import plotly.graph_objects as go

import numpy as np

from shiny.express import ui
from shinywidgets import render_plotly


def get_plot():
    np.random.seed(1)

    x = np.random.rand(100)
    y = np.random.rand(100)

    f = go.FigureWidget([go.Scatter(x=x, y=y, mode="markers")])

    scatter = f.data[0]
    colors = ["#a3a7e4"] * 100
    scatter.marker.color = colors
    scatter.marker.size = [10] * 100
    f.layout.hovermode = "closest"

    # callback for clicking
    def update_point(trace, points, selector):
        print('clicked')
        c = list(scatter.marker.color)
        s = list(scatter.marker.size)
        for i in points.point_inds:
            c[i] = "#bae2be"
            s[i] = 20
            with f.batch_update():
                scatter.marker.color = c
                scatter.marker.size = s

    scatter.on_click(update_point)

    return f


@render_plotly
def plot():
    return get_plot()

However, when we put the plot into a module, the callback is no longer called when clicking

import plotly.graph_objects as go

import numpy as np

from shiny.express import ui, module
from shinywidgets import render_plotly


def get_plot():
    np.random.seed(1)

    x = np.random.rand(100)
    y = np.random.rand(100)

    f = go.FigureWidget([go.Scatter(x=x, y=y, mode="markers")])

    scatter = f.data[0]
    colors = ["#a3a7e4"] * 100
    scatter.marker.color = colors
    scatter.marker.size = [10] * 100
    f.layout.hovermode = "closest"

    # callback for clicking
    def update_point(trace, points, selector):
        print('clicked')
        c = list(scatter.marker.color)
        s = list(scatter.marker.size)
        for i in points.point_inds:
            c[i] = "#bae2be"
            s[i] = 20
            with f.batch_update():
                scatter.marker.color = c
                scatter.marker.size = s

    scatter.on_click(update_point)

    return f


@module
def plot_module(input, output, session):
    
    @render_plotly
    def plot():
        return get_plot()


plot_module("module_1")

This only occurs with Plotly 6.0.0+. When downgrading to v5.24.1, the second example works just as expected. My best guess is that this has something to do with Plotly switching to anywidget, but I'm not knowledgeable enough to figure out where exactly the problem lies.

EDIT: Looks like updating Shiny (1.3.0 -> 1.4.0) is the issue and not Plotly v6 . For reproducing it, run the snippets above with the following two environments. With 1.3.0 both examples work, with 1.4.0 only the non-module example works.

$ cat shiny-1.3.yml 
channels:
  - conda-forge
dependencies:
  - python=3.11
  - numpy=2.2.5
  - plotly=6.0.1
  - shiny=1.3.0
  - shinywidgets=0.5.2
  - anywidget=0.9.18
$ cat shiny-1.4.yml 
channels:
  - conda-forge
dependencies:
  - python=3.11
  - numpy=2.2.5
  - plotly=6.0.1
  - shiny=1.4.0
  - shinywidgets=0.5.2
  - anywidget=0.9.18

Any pointers are highly welcome, thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions