# TikZ externalize, pgfplots and animate

I gave a very fetching presentation written with beamer today. It included a pgfplot animated with the animate package, and the result was fantastic. The problem? One of my colleagues wants to borrow the plot for a presentation written in something non-LaTeX. In addition, it would be nice to know how to externalise animated pgfplots frame by frame for animation using using convert or mencoder to produce a standalone file for inclusion in websites etc.

Naturally, I turned to externalize to do the job for me. It seems that animate and externalize don't agree... How can I convince them to kiss and make up?

Below is a massively simplified example for the wizards to work with

\documentclass{standalone}
\usepackage{pgfplots}
\usepackage{animate}
% Comment out the following line to see what the plot looks like.
\usepgfplotslibrary{external}\tikzexternalize

\begin{document}
%
\begin{animateinline}[controls]{10}
\multiframe{30}{ind=0+1}{
\begin{tikzpicture}
\begin{axis}[ymin=-1, ymax=1, xmin=0, xmax=3.14]
\end{axis}
\end{tikzpicture}
}
\end{animateinline}
%
\end{document}

-
the idea when doing animate and externalize is to loop (with \foreach or equivalent) externalizing the plots (preferably in a separate document). Then you can animate the pdf's after they have been externalized. I did this also by using the overlay feature which can drastically reduce the size of the ouput pdf. If i have time in the following days i will supply what i did in my bachelor thesis. –  zeroth Dec 21 '11 at 9:56
@zeroth: I already know how to do that, and it's a lot of effort for something that should be simple (in principle). I'd rather be able to do it this way to keep things neat and easily repeatable. –  qubyte Dec 21 '11 at 10:00
i see. I have always done it the other way. I am not sure if what you want is possible, we will see if an answer arrives! :) –  zeroth Dec 21 '11 at 10:08
As a bi-product this would improve the time to compile after the first time as TikZ would grab the externalised images for animate. –  qubyte Dec 21 '11 at 10:09
Can we see the NOT simplified version of the animation? I am interested. –  Manuel Kuehner Oct 19 '12 at 17:03

Does the animate package do things with the shipout routine of TeX? The external lib replaces it -- probably in an incompatible way.

Nevertheless, the following approach also works:

\documentclass{article}
\usepackage{pgfplots}
\usepackage{animate}
% Comment out the following line to see what the plot looks like.
\usepgfplotslibrary{external}

\tikzexternalize

\begin{document}
%
\begin{animateinline}[controls]{10}
\multiframe{30}{ind=0+1}{
\tikzifexternalizing{%
Work-around to make animate happy
}{}%
\begin{tikzpicture}
\begin{axis}[ymin=-1, ymax=1, xmin=0, xmax=3.14]
\end{axis}
\end{tikzpicture}
}
\end{animateinline}
%
\end{document}


the statement \tikzifexternalizing is only true if one of the frames is being converted. In this case, only the picture of interest makes its way into the output pdf - and we can safely generate non-empty content (and the animate package is happy).

-
Very neat! Could be winner. –  qubyte Dec 21 '11 at 16:11
I think shipout is probably affected, but I can handle that with a little bash magic. The important thing is just getting the frames out. –  qubyte Dec 21 '11 at 16:29
Thanks for your elegant solution @Christian. Animate doesn't tinker with the output routines, it just typesets graphics or inline material into saveboxes and produces Form XObjects (special pdf objects) from them. –  AlexG Dec 22 '11 at 8:50
@Alexander thanks for the technical background. In case you know the precise reason for the failure: let me know. Perhaps I can fix the external lib. If it is unrelated to \shipout hackery, there may be a general fix. –  Christian Feuersänger Dec 22 '11 at 11:44
@Mark thanks for the praise :) I'm glad they prove to be useful. –  Christian Feuersänger Dec 22 '11 at 13:57

\usepgfplotslibrary{external} and package animate don't work well together.

\tikzexternalize moves the tikzpicture environment into an external file to be processed separately (therefore, --shell-escape must be activated) and replaces the tikzpicture environment with \includegraphics.

On the first pass when no external pdf graphics are available, the boxes into which the animateinline environment stores the code it encloses have zero size. animate measures the box dimensions of the first frame and scales the animation widget accordingly. There is a built-in stop condition in animate when it finds that the box is empty.

To work-around this, consider the following code:

\documentclass{article}
\usepackage{pgfplots}
\usepackage{animate}
% Comment out the following line to see what the plot looks like.
\usepgfplotslibrary{external}

\newlength\mywidth
\newlength\myheight
\newsavebox\mybox
\begin{lrbox}{\mybox}
\def\ind{0}%
\begin{tikzpicture}
\begin{axis}[ymin=-1, ymax=1, xmin=0, xmax=3.14]
\end{axis}
\end{tikzpicture}
\end{lrbox}
\settowidth\mywidth{\usebox\mybox}
\settoheight\myheight{\usebox\mybox}

\tikzexternalize
\begin{document}
%
\begin{animateinline}[controls]{10}
\multiframe{30}{ind=0+1}{
\makebox[\mywidth][l]{\rule{0pt}{\myheight}%
\begin{tikzpicture}
\begin{axis}[ymin=-1, ymax=1, xmin=0, xmax=3.14]
\end{axis}
\end{tikzpicture}%
}
}
\end{animateinline}
%
\end{document}


An easy way to produce a standalone, correctly sized multipage PDF of all animation frames is:

\documentclass{article}
\usepackage{pgfplots}
\usepackage{ifthen}
\usepackage[tightpage,active]{preview}
\PreviewEnvironment{tikzpicture}

\begin{document}
%
\newcounter{ind}%
\whiledo{\theind<30}{%
\begin{tikzpicture}
\begin{axis}[ymin=-1, ymax=1, xmin=0, xmax=3.14]
\end{axis}
\end{tikzpicture}%
\stepcounter{ind}%
\newpage%
}
%
\end{document}


This multipage PDF can be further converted to other formats, such as SWF:

pdf2swf frames.pdf
swfcombine -r10 --output frames10fps.swf --dummy frames.swf

-
I actually debated whether or not to use article or standalone with myself (my code didn't work with either) and should have stuck with the former as being in article is fine as far as the code is concerned. Note however that the original diagram is in beamer which I ruled out immediately. I like your answer, but as noted in the comments I already know of a way to do it independently of animate. I'd rather use animate and external together if it can be achieved. –  qubyte Dec 21 '11 at 10:17
@Mark: See my edit which makes animate and external work more or less smoothly together. –  AlexG Dec 21 '11 at 11:56
Thanks, but your first block of code gives me some errors... –  qubyte Dec 21 '11 at 13:26
@Mark. Everything ok on my side (copied back the code into a new file and ran pdflatex --shell-escape on it.) –  AlexG Dec 21 '11 at 13:41
Oh strange. It works perfectly now! It even works in standalone. ;) This is exactly what I was looking for. Thanks! –  qubyte Dec 21 '11 at 14:00

## All in one approach

\documentclass{article}

\usepackage{filecontents}

% create a parameterized template
\begin{filecontents*}{template.tex}
\documentclass[tikz,border=12pt]{standalone}
\usepackage{pgfplots}
\begin{document}
\foreach \ind in {1,2,...,30}
{
\begin{tikzpicture}
\begin{axis}[ymin=-1, ymax=1, xmin=0, xmax=3.14]
\end{axis}
\end{tikzpicture}
}
\end{document}
\end{filecontents*}

\usepackage{animate}

% creater a PDF file containing frames
%\def\param{red}
%\immediate\write18{pdflatex -jobname=frames "\def\noexpand\clr{\param} \noexpand\input{template}"}

% just another way with \unexpanded to save more keystrokes!
\def\param#1{%
\immediate\write18{\unexpanded{pdflatex -jobname=frames "\def\clr{#1} \input{template}"}}}
\param{blue}

% create a GIF animation (needs ImageMagick installed)
\immediate\write18{convert -delay 5 -loop 0 -density 100 -alpha remove frames.pdf frames.gif}

% create a list of PNG images, one for each frame (needs ImageMagick installed)
\makeatletter
\immediate\write18{convert -density 100 -alpha remove frames.pdf frames-\@percentchar02d.png}
\makeatother

% create a MP4 video (needs both ImageMagick and FFMPEG installed)
\makeatletter
\immediate\write18{convert -density 100 -alpha remove frames.pdf frames-\@percentchar02d.png}
\immediate\write18{ffmpeg -r 5 -i frames-\@percentchar02d.png -vcodec libx264 frames.mp4}
\makeatother

\begin{document}
% create a PDF animation
\begin{center}
\animategraphics[controls,autoplay,loop,scale=1]{10}{frames}{}{}
\end{center}
\end{document}


## PNG output

I will not show all as they will waste your bandwidth.

...

-
Don't forget to use pdflatex -shell-escape inputfilename.tex to compile the given code above. –  kiss my armpit Oct 25 '13 at 14:19
I know it's "against the rules", but I just had to thank you for this – awesome answer! –  sudosensei May 13 '14 at 13:35