Creating great looking animations in Julia is shockingly easy thanks for the Plots package and some macro magic. Here we will learn how to turn data into high quality animations. We will learn about the
@animate macro, frames and the
Two Steps to Animations
To create animations we simply generate frames with the
@animate macro and then generate a file with the
gif function. Both are part of the Plots package from Julia, so we have to start with
using Plots to make that package available. Next create the data we will plot, which is a simple sine wave. Then we generate the frame with the
@animate macro and animate them with the
gif function. This is the code and the resulting animation.
using Plots x = collect(1:0.1:30) y = sin.(x) df = 2 anim = @animate for i = 1:df:length(x) plot(x[1:i], y[1:i], legend=false) end gif(anim, "tutorial_anim_fps30.gif", fps = 30)
Macros and Meta-Programming
@animate macro deserves some extra attention, because it looks like magic. Macros are related to a concept called meta-programming. In Julia, all code is a data structure that can be manipulated in a similar way to all other data structures. This effectively means that we can write code that manipulates our code. That’s what a macro is, a function that modifies code. In our case, the code being modified is the for loop behind our
@animate macro. It is modified in a way that it catches the frame at the end of each loop iteration and saves it into
anim. We can create code that does the same job ourselves.
anim = Plots.Animation() for i = 1:df:length(x) plot(x[1:i], y[1:i], legend=false) Plots.frame(anim) end gif(anim, "tutorial_anim_fps30.gif", fps = 30)
We use the
Plots.Animation() function to create our animation object where we will store our frames. During the for loop we then call
Plots.frame(anim) to store the frame after each iteration in our
anim object. These are the essential steps that the
@animate macro takes care of. If you want to learn what the macro does in detail you can call
@macroexpand on it.
@macroexpand @animate for i = 1:df:length(x) plot(x[1:i], y[1:i], legend=false) end
There is another macro that is even more convenient. The
@gif macro. It saves us from having to call
gif() on our
@gif for i = 1:df:length(x) plot(x[1:i], y[1:i], legend=false) end
This directly displays the animation if interactive Julia is available for it. The downside of this is that we do not save the animation to disk and we do not have an
anim object available to do more animations later. It is most useful to quickly troubleshoot animations interactively.
The @animate macro supports animations of anything that can be plotted with Plots. For example, we can animate a heatmap.
anim = @animate for i = 1:100 mat = rand(0:100, 32, 32) heatmap(mat, clim=(0,255)) end gif(anim, "tutorial_heatmap_anim.gif", fps = 10)
The frame that is being caught is the state of the active figure at the end of the for loop. The for loop itself gives us a great deal of control, how many frames we want to create. For example in the previous examples, I skipped frames with the
That’s it for animations. To learn more you can take a look at the official Plots documentation.