Filipe
Filipe

Reputation: 659

Change colorscale of marker with update menu (without repeating data)

I'm trying to create a scatter plot with a menu to change the colorscale. I started from this example on the documentation, and the goal would be to get something similar to this one but without using Dash.

Here is a minimal code to reproduce the issue:

import plotly.graph_objects as go
import math

x = [i*2*math.pi/100 for i in range(100)]
y = [math.sin(i) for i in x]

# Create figure
fig = go.Figure()

# Add surface trace
fig.add_trace(go.Scatter( x=x,
                          y=y, 
                          name = 'sine',
                          mode = 'markers',
                          marker=dict(
                                  size=5,
                                  cmin=(1.0),
                                  cmax=(-1.0),
                                  color=y,
                                  colorscale="Turbo",
                              )))

# Update plot sizing
fig.update_layout(
    width=800,
    height=400,
    autosize=False,
    margin=dict(t=100, b=50, l=50, r=50),
)

# Add dropdowns
button_layer_1_height = 1.0
fig.update_layout(
    updatemenus=[
        dict(
            buttons=list([
                dict(
                    args=[{'marker':{"colorscale":"Viridis"}}],
                    label="Viridis",
                    method="restyle"
                ),
                dict(
                    args=[{'marker':{"colorscale":"Cividis"}}],
                    label="Cividis",
                    method="restyle"
                ),
                dict(
                    args=[{'marker':{"colorscale":"Blues"}}],
                    label="Blues",
                    method="restyle"
                ),
                dict(
                    args=[{'marker':{"colorscale":"Greens"}}],
                    label="Greens",
                    method="restyle"
                ),
                dict(
                    args=[{'marker':{"colorscale":"Inferno"}}],
                    label="Inferno",
                    method="restyle"
                ),
                dict(
                    args=[{'marker':{"colorscale":"Reds"}}],
                    label="Reds",
                    method="restyle"
                ),
                dict(
                    args=[{'marker':{"colorscale":"Turbo"}}],
                    label="Turbo",
                    method="restyle"
                ),
            ]),
            direction="down",
            pad={"r": 10, "t": 10},
            showactive=True,
            x=0.1,
            xanchor="left",
            y=button_layer_1_height,
            yanchor="bottom"
        ),
        dict(
            buttons=list([
                dict(
                    args=[{},{'marker':{"reversescale":False}}],
                    label="False",
                    method="update"
                ),
                dict(
                    args=[{},{'marker':{"reversescale":True}}],
                    label="True",
                    method="update"
                )
            ]),
            direction="down",
            pad={"r": 10, "t": 10},
            showactive=True,
            x=0.37,
            xanchor="left",
            y=button_layer_1_height,
            yanchor="bottom"
        ),
    ]
)

fig.update_layout(
    annotations=[
        dict(text="colorscale", x=0, xref="paper", y=1.06, yref="paper",
                             align="left", showarrow=False),
        dict(text="Reverse", x=0.25, xref="paper", y=1.07,
                             yref="paper", showarrow=False),
    ])

fig.show()

I start with the "Turbo" colorscale: Turbo colorscale but as soon as I change to some other, the colorscale doesn't seem active anymore: No coloscale

If I add again the y values in the updatemenu, that is:

args=[{'marker':{"color":y,"colorscale":"Viridis"}}]

Then it works: Viridis colorscale

However, in my real example I have many graphs with a lot of data, and when I export to HTML, it becomes very big as the y data is added many times (each for each colormap). Since the data is all the same, it seems to me that this should be possible.

Upvotes: 0

Views: 947

Answers (1)

Filipe
Filipe

Reputation: 659

I have found the issue - it was actually a problem with the way I defined the restyle/update: when I use {'marker':{"colorscale":"Viridis"}} as argument, it replaces the whole marker structure (so, the y values get lost).

So, the correct code should be:

import plotly.graph_objects as go
import math

x = [i*2*math.pi/100 for i in range(100)]
y = [math.sin(i) for i in x]

# Create figure
fig = go.Figure()

# Add surface trace
fig.add_trace(go.Scatter( x=x,
                          y=y, 
                          name = 'sine',
                          mode = 'markers',
                          marker=dict(
                                  size=5,
                                  cmin=(1.0),
                                  cmax=(-1.0),
                                  color=y,
                                  colorscale="Turbo",
                              )))

# Update plot sizing
fig.update_layout(
    width=800,
    height=400,
    autosize=False,
    margin=dict(t=100, b=50, l=50, r=50),
)

# Add dropdowns
button_layer_1_height = 1.0
fig.update_layout(
    updatemenus=[
        dict(
            buttons=list([
                dict(
                    args=[{'marker.colorscale':"Viridis"}],
                    label="Viridis",
                    method="restyle"
                ),
                dict(
                    args=[{'marker.colorscale':"Cividis"}],
                    label="Cividis",
                    method="restyle"
                ),
                dict(
                    args=[{'marker.colorscale':"Blues"}],
                    label="Blues",
                    method="restyle"
                ),
                dict(
                    args=[{'marker.colorscale':"Greens"}],
                    label="Greens",
                    method="restyle"
                ),
                dict(
                    args=[{'marker.colorscale':"Inferno"}],
                    label="Inferno",
                    method="restyle"
                ),
                dict(
                    args=[{'marker.colorscale':"Reds"}],
                    label="Reds",
                    method="restyle"
                ),
                dict(
                    args=[{'marker.colorscale':"Turbo"}],
                    label="Turbo",
                    method="restyle"
                ),
            ]),
            direction="down",
            pad={"r": 10, "t": 10},
            showactive=True,
            x=0.1,
            xanchor="left",
            y=button_layer_1_height,
            yanchor="bottom"
        ),
        dict(
            buttons=list([
                dict(
                    args=[{'marker.reversescale':False}],
                    label="False",
                    method="restyle"
                ),
                dict(
                    args=[{'marker.reversescale':True}],
                    label="True",
                    method="restyle"
                )
            ]),
            direction="down",
            pad={"r": 10, "t": 10},
            showactive=True,
            x=0.37,
            xanchor="left",
            y=button_layer_1_height,
            yanchor="bottom"
        ),
    ]
)

fig.update_layout(
    annotations=[
        dict(text="colorscale", x=0, xref="paper", y=1.06, yref="paper",
                             align="left", showarrow=False),
        dict(text="Reverse", x=0.25, xref="paper", y=1.07,
                             yref="paper", showarrow=False),
    ])

fig.show()

(There is still an issue that the turbo colorscale is not recognised when changing in the menu, but that's a different issue)

Upvotes: 1

Related Questions