Plotly Buttons with Dependent Interactions

I am attempting to construct a Plotly 3D scatterplot with a large number of traces and several sets of buttons that determine which subset of the traces is visible. I would like for the buttons to interact in a manner that depends on the state of the other buttons. For example, suppose Button 1 and Button 2 belong to one bar of buttons and Button A and Button B belong to another bar, and that only one button in each bar can be pressed at a time. I’d like pressing Button A while Button 1 is active to display a different subset of traces than pressing Button A while Button 2 is active.

I’ve included a toy example below. It has a data set of four traces and two bars of buttons, but each button’s behavior is currently independent of the other buttons. I’d like the buttons to behave in a dependent manner, for example,

  • Buttons 1 and A pressed: show trace 1
  • Buttons 1 and B pressed: show trace 2
  • Buttons 2 and A pressed: show trace 3
  • Buttons 2 and B pressed: show trace 4
from plotly.offline import plot
import plotly.plotly as py
import plotly.graph_objs as go
import numpy as np

means = [[0,0,0], [1,2,1], [-1,0,1], [-1,1,-1]]
colors = ['rgb(124, 252, 0)', 'rgb(30, 144, 255)', 'rgb(220, 20, 60)', 'rgb(255, 69, 0)']

data = list()
for mean, color in zip(means, colors):
    x, y, z = np.random.multivariate_normal(np.array(mean), np.eye(3), 20).transpose()
    trace = go.Scatter3d(
        x=x,
        y=y,
        z=z,
        mode='markers',
        marker=dict(
            color=color,
            size=12,
            opacity=0.8
        )
    )
    data.append(trace)

layout = go.Layout(
    margin=dict(
        l=0,
        r=0,
        b=0,
        t=0
    )
)

button_layer_1_height = 1.12
button_layer_2_height = 1.065

updatemenus=list([
    dict(
        buttons=list([
            dict(
                args=[{'visible': [True, False, False, False]}],
                label='Button 1',
                method='restyle'
            ),
            dict(
                args=[{'visible': [False, True, False, False]}],
                label='Button 2',
                method='restyle'
            ),
        ]),
        direction = 'left',
        pad = {'r': 10, 't': 10},
        showactive = True,
        type = 'buttons',
        x = 0.1,
        xanchor = 'left',
        y = button_layer_1_height,
        yanchor = 'top'
    ),
    dict(
        buttons=list([
            dict(
                args=[{'visible': [False, False, True, False]}],
                label='Button A',
                method='restyle'
            ),
            dict(
                args=['visible', [False, False, False, True]],
                label='Button B',
                method='restyle'
            )
        ]),
        direction = 'left',
        pad = {'r': 10, 't': 10},
        showactive = True,
        type = 'buttons',
        x = 0.1,
        xanchor = 'left',
        y = button_layer_2_height,
        yanchor = 'top'
    ),
])

layout['updatemenus']=updatemenus
fig = go.Figure(data=data, layout=layout)
plot(fig, filename='localtest.html')

Hi @iamuuriwer1,

Having button/slider interactions that depend on other buttons/sliders is not possible with the widgets that are built-in to plotly.js (i.e. the widgets that you define in the figure.layout hierarchy).

For more sophisticated interactions I recommend you use FigureWidget+ipywidgets if you’re working in the Jupyter Notebook (https://plot.ly/python/figurewidget-app/). Or Dash if you want to build a standalone webpage (https://dash.plot.ly/).

Hope that helps clear things up.

-Jon

2 Likes

Thank you for your help @jmmease. In case it helps anyone else, I implemented an app in Dash and used radio items instead of buttons. I found the examples in the following section of the tutorial relevant to my particular question: https://dash.plot.ly/getting-started-part-2.

1 Like

Is this sort of dependent button interaction still impossible in the Python version of plotly?