Interactive Graph Click Event

Iā€™m trying to figure out if itā€™s possible to create a PlotLy Pie Chart in python with an on_click event in JupyterLab. Iā€™ve been able to run the scatter plot example:

When I try to adapt this for a pie chart, though, the callback doesnā€™t look like itā€™s ever being called. Iā€™m not sure if this is possible and thereā€™s something missing in my adaptation, or if itā€™s a capability thatā€™s only available for scatter and not for other kinds of plots.

Can anyone advise or provide feedback on this? Thanks!

1 Like

Hi @tdonadio,

Click events on pie charts should work. Hereā€™s an example thatā€™s working for me

import plotly.graph_objs as go
from ipywidgets import Output, VBox

fig = go.FigureWidget()
pie = fig.add_pie(values=[1, 2, 3])

out = Output()
@out.capture(clear_output=True)
def handle_click(trace, points, state):
    print(points.point_inds)

pie.on_click(handle_click)

VBox([fig, out])

pie_click

Hope that helps!
-Jon

2 Likes

Thanks! Yes, that works for me as well. And seeing a successful example allowed me to identify what what I was doing to adapt the scatterplot example that wasnā€™t working.

I noticed two things that donā€™t work following the scatterplot example (that is, it will create plots, but the callback wonā€™t fire on click):

  • iplot wonā€™t work for a callback-based interactive pie chart (or at least, it doesnā€™t when I change the example only to use iplot rather than VBox).
  • it wonā€™t work if I create the ā€œpieā€ object with go.Pie instead of with fig.add_pie (as in: fig = go.FigureWidget([go.Pie(labels=labels, values=values)])).

I can move forward now with a working example, but Iā€™m curious to understand these differences a bit better. Can someone help to explain the reason(s) for them? Iā€™m new to using PlotLy, so it may just be that this isnā€™t clear to me because of my lack of familiarity with the programming model. Thanks!

Hi @tdonadio,

Glad you got it working!

iplot wonā€™t work for a callback-based interactive pie chart (or at least, it doesnā€™t when I change the example only to use iplot rather than VBox).

This is correct, when a FigureWidget is displayed using iplot, the resulting view is not an ipywidget and so the events canā€™t be synced back to the Python side. A FigureWidget should be allowed to display itself (by being the last expression in an input cell), or it can be displayed using the ipywidgets.display method (See Simple Widget Introduction ā€” Jupyter Widgets 8.1.1 documentation).

it wonā€™t work if I create the ā€œpieā€ object with go.Pie instead of with fig.add_pie (as in: fig = go.FigureWidget([go.Pie(labels=labels, values=values)])).

Whatā€™s happening here is that traces are copied when they are passed to figure constructors. So you do need to add a trace to the figure and then access it in order for the callbacks to be synced up. As an alternative to using the add_* methods, you can retrieve the trace from the figureā€™s data property. E.g.

fig = go.FigureWidget([go.Pie(labels=labels, values=values)]))
pie = fig.data[0]

Hope that helps clear things up a bit!
-Jon

Hi, is there an example of click and select points in 3D scatter? !

I try to let ā€œdragmodeā€:ā€˜selectā€™, but this method is not suitable for 3D scatter.

Hi @visual,

Unfortunately 3D point selection isnā€™t supported yet. See https://github.com/plotly/plotly.js/issues/3511 for initial discussion.

-Jon

I tried running the pie example above, but got the following error:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-13-75f1733261e8> in <module>
     10     print(points.point_inds)
     11 
---> 12 pie.on_click(handle_click)
     13 
     14 VBox([fig, out])

AttributeError: 'FigureWidget' object has no attribute 'on_click'
2 Likes

#try this on jupyter notebook. I donā€™t know why indentation doesnā€™t work

import plotly.graph_objects as go
import webbrowser

from ipywidgets import Output, VBox

import numpy as np
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ā€™

create our callback function

out = Output()
@out.capture(clear_output=True)
def update_point(trace, points, selector):
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
webbrowser.open(ā€˜http://example.comā€™)

scatter.on_click(update_point)
VBox([f, out])

Thanks for your reading.

I have some problems about click event in pie chart.
I fellow your post on jupyter notebook, it worked well!

But I want to run this not on jupyter notebook, on py file.

Could you let me know solution?

Warm Regards.
Take care

I canā€™t get the minimal example working, and I wonder if itā€™s because something broke with plotply-ipywidget integration or if itā€™s a configuration issue with my notebook setup (e.g. a missing extension). When I run this minimal example based on the pie chart example, it doesnā€™t render anything (neither the ipywidget nor the figure):

import ipywidgets as widgets
import plotly.graph_objects as go

fig = go.FigureWidget()
fig.add_pie(values=[1, 2, 3])
out = widgets.HTML()
out.value = 'hello'
widgets.VBox([out, fig])

I can render without including a plotly widget., e.g.:

import ipywidgets as widgets

out1 = widgets.HTML()
out2 = widgets.HTML()
out1.value = 'hello'
out2.value = 'world'
widgets.VBox([out1, out2])

I can render the FigureWidget with fig.show(), but I canā€™t capture events if I render that way.

plotly.version is 4.3.0
widgets.version is 7.5.1

Thanks!

Do you have an up to date version of the plotlywidget labextension installed as per https://plotly.com/python/getting-started/ ?

I would recommend updating everything to the latest versions: 4.8.2

Thanks for the reply, Nicolas! Unfortunately this is in a shared development environment where I may not be able to upgrade plotly in short order, but I may have more luck adding extensions.

Iā€™m using a notebook platform based on Jupyter but not JupyterLab, and my understanding from the getting started guide is the plotlywidget extension is just for JupyterLab. Are there installation steps missing from the Jupyter Notebook Support section? https://plotly.com/python/getting-started/#jupyter-notebook-support

I notice in that section there isnā€™t a figure rendering below this code block, which is the same use case Iā€™m having trouble with ā€” is it exhibiting the same problem?

import plotly.graph_objects as go
fig = go.FigureWidget(data=go.Bar(y=[2, 3, 1]))
fig

So in Jupyter, the plotlywidget extension is loaded automatically, and in JupyterLab it must be installed manually. If youā€™re in a custom notebook platform, youā€™ll need to get the extension loaded in one way or the other to get widgets to work :slight_smile:

Can you provide more details on your notebook system? Is it Google Colab or SageMaker or something like that or from some smaller vendor?

Thanks so much, Nicholas. Itā€™s a notebook platform built internally at my company, and I donā€™t know enough about its creation and development to be able to say more about how it differs. Theyā€™re now looking at getting plotlywidget to load properly.

It may take some time for them to get it working, and I need a temporary work-around to be able to do the demo I need (or switch to ggplot or matplotlib). Is there any way, even if very hacky, to capture click events on a figure rendered using show()? Thereā€™s clearly some mouse-to-figure communication going on because hovertext works. I would be grateful for a hint of where to hook into the code base with the understanding that Iā€™m on my own from there. :slight_smile:

For catching click events within the notebook without using FigureWidgets I would recommend using https://github.com/plotly/jupyter-dash