Animation removes background plot

I’m creating an animated plot of Scatter frames laid over a Contour. Both of these work fine when separate. But if I try to put them on the same figure, the background Contour disappears after the first frame. I’m not the first one to deal with this:

Unfortunately, their suggestions did not help. I tried adding a “decoy” trace in data. I tried adding frames + 1 clones of the background. I tried with an empty trace. Empty trace of Scatter type. Tried with and without traces = [1] in the frame. Tried setting it to 2 and 0. Swapping orders of “decoy” and normal traces. Nothing worked. It always did the same thing: show up on the first frame and then disappear.

Something that I have noticed is that all of them has the same type of base and frame plots. Mine are different. Could that be the problem? They are compatible with each other if I don’t try to animate them.

Code used to generate the files:

figure = plotly.graph_objects.Figure(
	data=[
		plotly.graph_objects.Scatter(x=[], y=[], showlegend=False),
		plotly.graph_objects.Contour(
			x=frame["x"],
			y=frame["y"],
			z=numpy.log10(frame["z"]),
		),
	],
	frames=[
		plotly.graph_objects.Frame(
			data = plotly.graph_objects.Scatter(
				x = [particle["x"] for particle in frame],
				y = [particle["y"] for particle in frame],
				mode="markers",
			),
			traces=[1]
		) for frame in frames
	],
)
figure.update_layout(width = 1500, height = 1500)
figure.write_html("fig.html")

frames is a list of lists of dictionaries containing x, y keys. frame is a DataFrame that represents a function: f(x, y) = z

Documentation for this part of the library is somewhat lacking, and examples I’ve found online hasn’t been helpful. Is this something I can do or should I look into different solutions?

This was an old bug, but now it works not as expected, because of the frame redraw set on True in updatemenus:

import plotly.graph_objects as go
import numpy as np
from scipy.stats import multivariate_normal
def get_updatemenus(x_pos=0.0, fr_duration=500):
    return [dict(x= x_pos,
                 y= -0.1,
                 
                 type='buttons',
                 showactive= False,
                 buttons= [dict(label='Play',
                                method='animate',
                                args= [ None,
                                        dict(mode='immediate',
                                             transition= { 'duration': 0 },
                                             fromcurrent= True,
                                             frame= dict( redraw=True, duration=fr_duration)
                                            )
                                       ]
                                ),
                           dict(label='Pause',
                                method='animate',
                                args= [ [None],
                                        dict(mode='immediate',
                                             transition= { 'duration': 0 },
                                             frame= dict( redraw=True, duration=0 )
                                            )
                                       ]
                                )
                           ]
               )
        ]
mean=[0,0]
cov=[[1, 0.7], [0.7, 1]]
nrv = multivariate_normal(mean, cov)
X= np.linspace(-3,3, 300)
x, y= np.meshgrid(X,X)
pos = np.dstack((x, y))
z= nrv.pdf(pos)
xs= -2+4*np.random.rand(10)
ys= -2+4*np.random.rand(10)
fig=go.Figure([go.Contour(), go.Contour(x=X, y=X, z=z, colorscale='algae', y0=-3, x0=-3),
go.Scatter(x=xs, y=ys, mode ="markers", marker_color='red',
                         marker_size=6)])
fig.update_layout(width=600, height=500)

n_frames=20
frames=[]
for k in range(n_frames):
    frames.append(go.Frame(data=[
                                 go.Scatter(x=-2+4*np.random.rand(10), y=-2+4*np.random.rand(10))],
                          traces=[2]))

fig.update_layout(updatemenus=get_updatemenus())
fig.update(frames=frames)
fig.show()