26

I would like to use the beamer \only with tikz while external is activated. The problem is, that the \only get ignored. (see also the MWE).

I would love to cache the tikz pictures, because it would definitely speed up the compile time.

\documentclass{beamer}
% main document, called main.tex
\usepackage{tikz}
\usetikzlibrary{external}
\tikzexternalize % activate!
\begin{document}

\begin{frame}
    \begin{tikzpicture}
        \node at (1,1) {test};
        \only<2>{\node at (2,2) {test2};}
    \end{tikzpicture}
\end{frame}

\end{document}

I tried the current version and also the cvs version (which is nicer because it uses checksums for the images).

lockstep
  • 250,273
someonr
  • 8,531

2 Answers2

33

The problem is that once the first graphics has been created, beamer is "blind": it does not know that a further slide has to be generated to fulfill the \only<2>.

I had the same problem some time ago... if I remember correctly, I solved it by adding \only<1-2> around the external picture:

\documentclass{beamer}
% main document, called main.tex
\usepackage{tikz}
\usetikzlibrary{external}
\tikzexternalize % activate!
\begin{document}

\begin{frame}
    \noindent % create a new paragraph here - otherwise, we might end up with different hspace.
    \only<1-2>{%
        \begin{tikzpicture}
            \node at (1,1) {test};
            \only<2>{\node at (2,2) {test2};}
        \end{tikzpicture}%
    }%
\end{frame}

\end{document}

This will create two external .pdf files. The idea is that the outer range <1-2> contains the maximal slide index.

Another solution might be to implement support for the combination external + beamer. If there is some beamer guy who can tell me which switch communicates the need to create a further picture to beamer, I could try to set it under certain conditions from within the external library.

  • 1
    I got something working, but suspect it is a long way from a "perfect" solution. – Andrew Stacey Oct 29 '12 at 14:35
  • @Andrew do you mean that you managed to implement something along the lines of my last paragraph? – Christian Feuersänger Oct 29 '12 at 15:26
  • As in my answer (below). The important part was to pass the T/F value of beamer@anotherslide back from the subprocess to the main process, but it also needs passing to the other subprocesses. I suspect that there is a better way to do this than the one I found (since it switches off the optimisation), but I thought it a good idea to post what I had so far! – Andrew Stacey Oct 29 '12 at 15:33
  • @Andrew Ah - I see. I already suspected this boolean switch; good to know. I will look into it as well; perhaps I can come up with a suggestion. – Christian Feuersänger Oct 29 '12 at 15:41
  • I cannot say whether this is the best answer or not; at the moment it solved my problem! – Dror Sep 24 '13 at 09:26
  • 1
    Note that this is incompatible with \tikzsetnextfilename. If that option is used, the externalised file will have multiple slides, but the first one will be embedded in every slide of the main file. – Ruud Jun 03 '15 at 10:44
  • 1
    @RuudvA this problem got solved! – Robert Seifert Sep 08 '15 at 10:53
12

Here's a not-all-that-optimal solution. It gets round the main problem but introduces a few suboptimal pieces. (Hopefully someone who understood the externalisation process better than I do would be able to fix those ... looking at no Feuersängers in particular.)

The main problem is when the command \only<2>{...} refers to a frame that is not referenced in the rest of the picture. Then beamer has to know that a new frame is required. It does this by setting a flag when processing a version of the frame that says "I've encountered an overlay specification that refers to a slide in the future so keep going.". However, when this is done inside the picture then this information is only known to the tex process doing the picture. It is not communicated back to the main process. All the main process knows is that there is a picture there so it doesn't know to rerun the frame. If it did rerun the frame it would generate the next version of the picture: that is what Christian's trick is doing (incidentally, it doesn't need the \only<1-2>{...} around the picture; anywhere on the frame will do; even \begin{frame}<1-2> will do). So we need to get that information back. Fortunately, the external library does produce a communication channel: the .dpth file. Unfortunately, due to some internal optimisation stuff, when processing a particular picture the relevant .dpth files for other pictures don't get read. So, in the above example, we can make the first run flag that another run is needed. The main tex process gets that and does another run but when the second subprocess runs it doesn't know that two runs are needed and so complains vociferously.

It is possible to turn off this optimisation which ensures that the .dpth file is read. A better solution would be to have only partial optimisation where the .dpth file was read but the rest thrown away.

The other drawback of this solution is that a new picture is generated even if it hasn't actually changed. So if the same picture appears on slides 1 and 2 but changes on 3 then 3 versions are generated. Again, some wizard could probably fix this with md5s.

Lastly, there's some weird hspacing issues creeping in: run it two or three times to see them. Fortunately not cumulative but presumably some space didn't get %'ed out.

\documentclass{beamer}
% main document, called main.tex
\usepackage{tikz}
\usetikzlibrary{external}
\tikzexternalize % activate!
\makeatletter
\tikzset{
  beamer externalising/.style={%
    execute at end picture={%
      \tikzifexternalizing{%
        \ifbeamer@anotherslide
        \pgfexternalstorecommand{\string\global\string\beamer@anotherslidetrue}%
        \fi
      }{}%
    }%
  },
  external/optimize=false
}
\makeatother
\begin{document}

\begin{frame}
\noindent % create a new paragraph here - otherwise, we might end up
with different hspace.
\begin{tikzpicture}[beamer externalising]
\node at (1,1) {test};
\only<2>{\node at (2,2) {test2};}
\end{tikzpicture}%
\end{frame}

\end{document}
Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751