Here's the Jupyter notebook: https://plot.ly/~jackp/17018
Running the py.iplot(gif) starts this contour plot animation, but pressing the "Play" button does nothing:

I had to make just a couple subtle changes to get this to work. I've uploaded a modified notebook: https://plot.ly/~rreusser/62

redraw: true. redraw: false is an optimization for scatter plots so that animate just makes some d3-level SVG tweaks without redrawing the whole plot. It's a huge optimization and allows nice easing. For contour plots though, every frame must be a total plot redraw, i.e. redraw: true.[None] (that is, dict(args=[[None]])), which is the pause button notation. The args for a play button are dict(args=[None]). It's a little subtle due to the way they're nested in an array of args, which I think was the problem. A full enumeration for Plotly.animate(X), for X:null: animate all framesundefined: animate all frames (so just Plotly.animate(gd) is also valid)string: animate all frames with group: '<some string>'. This is a way of scoping the animations in case there are other things going on that would break the simplicity of animating without explicitly enumerating all frames.[null]: A simple way to hack together a pause button (requires mode: 'immediate'). In plain english, it says "dump all the currently queued frames (that's the 'immediate' part), and then animate an empty sequence of frames (that's the [null] part). This wasn't specifically crafted; it's just a side effect of the way things are put together.[]: **DON'T DO THIS`. It looks indistinguishable from a pause button since the first argument is undefined-y, but nested properties have some logic that treats empty arrays as entirely removable so it will function as a play button. This really can't change, so this will have to be a matter of documentation.['frame1', 'frame2', ...]: Animate a sequence of named frames[{data: [], layout: {}, traces: []}, {...}]: Nearly identical to animating named frames; just a variant that lets you inline data instead of adding it as named frames. Useful for interactive stuff where it'd be undesirable to add and manage named frames for ephemeral changes.cc @empet
This is awesome @rreusser , thanks for explaining. @cldougl can we get these details in the documentation both for JavaScript and Python?
cc @cpsievert , though it looks like he figured out most of this already for R.
info updated in python docs: https://plot.ly/python/animations/#adding-control-buttons-to-animations
Most helpful comment
I had to make just a couple subtle changes to get this to work. I've uploaded a modified notebook: https://plot.ly/~rreusser/62
redraw: true.redraw: falseis an optimization for scatter plots so thatanimatejust makes some d3-level SVG tweaks without redrawing the whole plot. It's a huge optimization and allows nice easing. For contour plots though, every frame must be a total plot redraw, i.e.redraw: true.[None](that is,dict(args=[[None]])), which is the pause button notation. The args for a play button aredict(args=[None]). It's a little subtle due to the way they're nested in an array of args, which I think was the problem. A full enumeration forPlotly.animate(X), for X:null: animate all framesundefined: animate all frames (so justPlotly.animate(gd)is also valid)string: animate all frames withgroup: '<some string>'. This is a way of scoping the animations in case there are other things going on that would break the simplicity of animating without explicitly enumerating all frames.[null]: A simple way to hack together a pause button (requiresmode: 'immediate'). In plain english, it says "dump all the currently queued frames (that's the 'immediate' part), and then animate an empty sequence of frames (that's the[null]part). This wasn't specifically crafted; it's just a side effect of the way things are put together.[]: **DON'T DO THIS`. It looks indistinguishable from a pause button since the first argument is undefined-y, but nested properties have some logic that treats empty arrays as entirely removable so it will function as a play button. This really can't change, so this will have to be a matter of documentation.['frame1', 'frame2', ...]: Animate a sequence of named frames[{data: [], layout: {}, traces: []}, {...}]: Nearly identical to animating named frames; just a variant that lets you inline data instead of adding it as named frames. Useful for interactive stuff where it'd be undesirable to add and manage named frames for ephemeral changes.