I was trying to generate an animated 3D scatter plot using plotly and display it on a dashboard I created using Shiny (Python) Express. When checking the code for an animated plotly graph on a jupyter notebook - it works perfectly, but I am not able to get the animation running on Shiny.
The graph is interactive - that is the tool tip shows the data but there's no animation when clicking on Play.
import io
from pathlib import Path
from shiny import reactive
from shiny.express import input, ui, render
from shiny.types import FileInfo
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
from shinywidgets import render_widget
import asyncio
ui.page_opts(
title="Visualisation",
fillable=True,
id="page",
)
with ui.card(full_screen=True):
@render_widget
def coordinate_space():
try:
with ui.Progress(min=1, max=5) as p:
data = {
'X': [1, 2, 3, 4, 5],
'Y': [5, 4, 3, 2, 1],
'Z': [2, 3, 4, 5, 6],
'FZ_new': [10, 20, 30, 40, 50],
'FZ': [5, 10, 15, 20, 25]
}
scaled_coordinate_system = pd.DataFrame(data)
p.set(2, message="Data loaded, preparing plot...")
fig = px.scatter_3d(scaled_coordinate_system, x='X', y='Y', z='Z',
size='FZ_new', color='FZ_new', opacity=0.7)
fig1 = go.Figure(fig)
p.set(3, message="Adding traces to the plot...")
frames = [
go.Frame(data=[go.Scatter3d(
x=scaled_coordinate_system['X'],
y=scaled_coordinate_system['Y'],
z=scaled_coordinate_system['Z'],
mode='markers',
marker=dict(size=scaled_coordinate_system['FZ_new'] * 10, color="Red"),
opacity=0.9,
name='Frame 1',
)]),
go.Frame(data=[go.Scatter3d(
x=scaled_coordinate_system['X'],
y=scaled_coordinate_system['Y'],
z=scaled_coordinate_system['Z'],
mode='markers',
marker=dict(size=scaled_coordinate_system['FZ'], color=scaled_coordinate_system['FZ']),
opacity=0.7,
name='Frame 2'
)])
]
print("Frames")
fig1.frames = frames
p.set(4, message="Updating layout...")
fig1.update_layout(
scene=dict(
xaxis_title='X AXIS',
yaxis_title='Y AXIS',
zaxis_title='Z AXIS'
),
updatemenus=[dict(
type='buttons',
direction = "down",
showactive=True,
buttons=[
dict(
label='Play',
method='animate',
args=[None, dict(
frame=dict(duration=500, redraw=True),
fromcurrent=True,
transition=dict(duration=0)
)]
),
dict(
label='Pause',
method='animate',
args=[[None], dict(
frame=dict(duration=0, redraw=False),
mode='immediate'
)]
)
]
)]
)
fig1.update_layout(margin=dict(l=0, r=0, b=0, t=0))
camera = dict(
eye=dict(x=2, y=2, z=0.5)
)
fig1.update_layout(scene_camera=camera)
p.set(5, message="Rendering plot...")
return fig1
except Exception as e:
ui.notification_show(f"{e}", duration=20, type="error")
return None
Above is my code for the function to render a plot. I was thinking if the animation rendering issue has something to do with async functions so I changed this to sync. I'm not sure what to do.
My animation just affects the size of the markers in the scatter plot.
Could someone help me out?
Edit: Minimal reproducible code inserted