Skip to content

Instantly share code, notes, and snippets.

@banditkings
Last active October 6, 2023 23:12
Show Gist options
  • Save banditkings/a6519260f1fc8c49c94153ff2f3a6db5 to your computer and use it in GitHub Desktop.
Save banditkings/a6519260f1fc8c49c94153ff2f3a6db5 to your computer and use it in GitHub Desktop.
Random Walk animation in Plotly
import numpy as np
import plotly.graph_objects as go
# A Random Walk animation in Plotly using a line and a marker for the current position
n = 200
# Random Walk with n points
x = np.arange(n)
i = 0
state = 0 # initial state
y = [state]
while i <= n:
state += np.random.normal(0, 0.001)
y.append(state)
i+=1
# Specify the animation args here for the duration, etc
animation_args = [None,
{'frame': {'duration': 50, 'redraw': False},
'fromcurrent': True,
'transition': {'duration': 10,
'easing': 'quadratic-in-out'}
}]
# Marker Styling
marker_args = {'size':20, 'color':'red', 'line':{'width':2}}
def make_frames(x, y):
"""Make a list of go.Frame() objects with the specified data"""
result = []
n = len(x)
for i in np.arange(n):
data = [go.Scatter(x=x[:i+1], y=y[:i+1], mode='lines'),
go.Scatter(x=[x[i]], y=[y[i]], mode='markers+text',
opacity=0.5, marker=marker_args,
text=['Current Position'],
textposition='top right'),
]
result.append(go.Frame(data=data))
return result
# Now, make the go.Figure() object with the `frames` parameter
fig = go.Figure(
data=[go.Scatter(x=[0], y=[0], mode='lines', name='line'),
go.Scatter(x=[0], y=[0], mode='markers+text', opacity=0.5,
marker=marker_args,
text=['Current Position'],
textposition='top right',
name='current_position')],
layout=go.Layout(
xaxis=dict(range=[0, n], autorange=False),
yaxis=dict(range=[np.min(y) * 1.5, np.max(y) * 1.5], autorange=False),
title="Random Walk Animation",
updatemenus=[dict(
type="buttons",
buttons=[dict(label="Play",
method="animate",
args=animation_args)])]
),
frames=make_frames(x, y)
)
fig.update_layout(template='seaborn')
fig.show()
@banditkings
Copy link
Author

Weirdness here is that we control the speed of the animation in the button arguments. I guess the idea here is that we can make multiple buttons that have different animation properties on playback (i.e. make a 'full speed' button or a 'half speed' button, etc).

Otherwise the animation logic is all in the frames parameter in the go.Figure() object, in which we use a list of go.Frame(data) objects for each frame. Simple!

@banditkings
Copy link
Author

banditkings commented Oct 6, 2023

We can't add annotations because they're not a graph object, so I guess you could instead add a go.Scatter with a text label if you wanted another moving annotation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment