Use buttons instead of slider for px.imshow animation

I have a small number of images (~5) I want to flip between. I can create a px.imshow animation, e.g.:

fig = px.imshow(
    np.random.rand(5,10,10), # 5 example 10x10 images
    animation_frame=0,
)
fig.show()

which gives me a slider I can use to flip to a given frame with. But instead I’d like to remove the slider and have it be 5 β€œradio” buttons with some custom labels that let me click on a button to flip to the appropriate frame. Any suggestions how to go about this? Thanks.

1 Like

@marius Yes, it is possible to flip between a few images. Here I give an example with two images:

import plotly.express as px
import plotly.graph_objects as go
import skimage.io as sio

img1=sio.imread("circular-lotus.jpg")#https://raw.githubusercontent.com/empet/Datasets/master/Images/circular-lotus.jpg
fig1=px.imshow(img1)
img2=sio.imread("Alfred-circular.jpg")#https://raw.githubusercontent.com/empet/Datasets/master/Images/Alfred-circular.jpg
fig2=px.imshow(img2)
fig=go.Figure([fig1.data[0], fig2.data[0]])
fig.data[1].visible=False
fig.update_layout(width=500, height=500, xaxis_visible=False, yaxis_visible=False)

fig.update_layout(
    updatemenus=[
        dict(
            active=0,
            buttons=[
                dict(label="Lotus",
                     method="restyle",
                     args=[{"visible": [True, False]},
                           ]),
                dict(label="Alfred",
                     method="restyle",
                     args=[{"visible": [ False, True]},
                           ])],
              x=1.1,
              xanchor="left",
              y=1.1,
              yanchor="top")])
fig.show()

Perfect, thank you!

@marius Meanwhile I translated this code in PlotlyJS.jl (the Julia version of plotly.py):

using Base64, PlotlyJS
getbase64(data:: Vector{UInt8}) = "data:image/png;base64,"*base64encode(data)
vecuint8 = [read("circular-lotus.jpg"), read("Alfred-circular.jpg")];
fig = Plot([PlotlyJS.image(; source=getbase64(vecuint8[k])) for k in 1:length(vecuint8)],
            Layout(width=500, height=500, xaxis_visible=false, yaxis_visible=false,
                updatemenus=[
                        attr(active=0,
                             buttons = [PlotlyJS.attr(; label, method="restyle", 
                                        args=[attr(visible=circshift([true, false],i-1))]) 
                                                   for (i,label) in enumerate(["Lotus", "Alfred"])], 
                              x=1.1,
                              xanchor="left",
                              y=0.95,
                              yanchor="top")]))
restyle!(fig, visible=false, 2) #set invisible the second trace(image here)
relayout!(fig, title_text="Flipping between two images", title_x=0.45, 
               margin_t=90, font_family="Balto")
display(fig)

Ooh that’s really interesting, thanks! I do use Julia but had been calling into plotly.express via PyCall since it was easier. But would be nice to remove the Python dependency. One of the main showstoppers was needing imshow-like binarystring, but I see above now that you can do that byhand with base64encodeand PlotlyJS.image(; source)thats super helpful.

1 Like