# In tikz externalize: how to get the filename match the Figure label automatically?

I'd like to externalize my Tikz pictures and automatically give them the Name Figure1.pdf, Figure2a.pdf, Figure2b.pdf etc.

Therefore, I'd like to combine \textsetnextfilename with some thing like cleveref which gives me the reference string I like automatically.

The purpose is, that I have to submit all figures individually as a PDF for a journal and I'd like to make sure they know which figure belongs where, without me naming everything manually and keeping track of which pdf is where after I moved stuff in the document.

%MWE
\documentclass{article}
\usepackage{cleveref}
\usepackage{tikz}
\usetikzlibrary{external}
\tikzexternalize
\begin{document}
\tikzsetnextfilename{Figure1 (manually)} %%% Here should be some construct with \cref{fig:Test} that expands to Figure 1...
\begin{figure}
\centering
\begin{tikzpicture}
\draw[fill=gray](0,0)rectangle(0.3\textwidth,0.3\textwidth)node[midway, anchor=center,font=\Huge]{A};
\end{tikzpicture}
\caption{Blababal}\label{fig:Test}
\end{figure}
\Cref{fig:Test} shows a square with a uppercase letter A.
\end{document}


So something based on \cref{fig:Test} has to be entered as an argument to \tikzsetnextfilename to result automatically in having the PDF file names 'Figure 1.pdf'. In the MWE I put it manually, but how to automatize with \cref? If there is a way without \cref that would off also be fine.

• Not answering your question, but: do you really want to send the tex source files of your figures to the journal and let them mess them up? Maybe some high-res png are the better choice? – thewaywewalk Aug 8 '17 at 15:26
• No. That's why I want to have the 'Figure 1.pdf' output by externalize and so on. So I can send them the Zip of the whole thing and also upload the individual compiled Figures as pdfs (but the file names will be more meaningful to them instead of DocumentName-figure3.pdf where it actually is Figure2b that the PDF represents). Converting PDF to PNG is of course possible but that's easily done with mogrify. – Matthias Arras Aug 8 '17 at 19:30
• \cref is not expandable, I think this won't work in order to generate the file name as you desire – user31729 Aug 8 '17 at 21:48
• Can't you just use the figure counter? Increment it by 1, set the name and then decrement it by 1. You can add the Figure as text, as that won't change. But don't include spaces (or other weird characters) in filenames. – cfr Aug 8 '17 at 21:53
• @cfr: As I said: untested – user31729 Aug 9 '17 at 5:25

Using labels for file names can be done. But since \ref-like commands can't be use with \tikzexternalize and the default mode=convert with system call, it is necessary to use \tikzexternalize[mode=list and make]. This will produce a file named main.makefile for main.tex. And the figures have to be build manually in a shell with make -f main.makefile.

If that isn't to much trouble, here is a solution.

Instead of calling \tikzsetnextfilename{...} \NextFigureNameByLabel{<label>} must be called. The file names for the figures will then be e.g. Figure-1 or Figure-2b.

It will produce a warning for undefined labels. In that case there will be files named Figure-??..... This also happens on the first run, when labels are not set yet. This can be ignored.

So run LaTeX twice to get references right, execute make -f main.makefile, and then run LaTeX again.

\documentclass{article}
\usepackage{cleveref}
\usepackage{tikz}
\usetikzlibrary{external}
\usepackage{subcaption}

\makeatletter
% based on LaTeX definition of \ref, only gives out the number
\def\@setvalref#1#2#3{%
\ifx#1\relax
% warning will not work here, moved to \NextFigureNameByLabel
%    \protect\G@refundefinedtrue
??%
%    \@latex@warning{Reference ‘#3’ on page \thepage \space undefined}%
\else
\expandafter#2#1%
\fi}
\def\valref#1{\expandafter\@setvalref\csname r@#1\endcsname\@firstoftwo{#1}}

\newcommand{\NextFigureNameByLabel}[1]{%
% to get a proper warning for undefined labels
\expandafter\ifx\csname r@#1\endcsname\relax
\protect\G@refundefinedtrue
\@latex@warning{Reference ‘#1’ on page \thepage \space undefined}%
\fi
\edef\NFNtemp{Figure-\valref{#1}}%
\expandafter\tikzsetnextfilename\expandafter{\NFNtemp}%
}
\makeatother

\tikzexternalize[mode=list and make]
\begin{document}
\begin{figure}
\centering
\NextFigureNameByLabel{fig:SubA}
\begin{subfigure}{0.42\textwidth}
\centering
\begin{tikzpicture}
\draw[fill=gray](0,0)rectangle(0.3\textwidth,0.3\textwidth)node[midway, anchor=center,font=\Huge]{A};
\end{tikzpicture}
\caption{Blababal}\label{fig:SubA}
\end{subfigure}
\NextFigureNameByLabel{fig:SubB}
\begin{subfigure}{0.42\textwidth}
\centering
\begin{tikzpicture}
\draw[fill=gray](0,0)rectangle(0.3\textwidth,0.3\textwidth)node[midway, anchor=center,font=\Huge]{B};
\end{tikzpicture}
\caption{Blababal}\label{fig:SubB}
\end{subfigure}
\caption{Blababal}\label{fig:Test}
\end{figure}
\Cref{fig:Test} shows two squares with a uppercase letters. (\ref{fig:Test})
\Cref{fig:SubA} shows a square with a uppercase letter A. (\ref{fig:SubA})
\Cref{fig:SubB} shows a square with a uppercase letter B. (\ref{fig:SubB})
\end{document}

• This sounds very promising, I will test and report back. In following tex.stackexchange.com/questions/1966/… I am trying to consistently using subfloat instead of subfigure, but I don't think the subcaption package will be a prerequisite for your solution. – Matthias Arras Aug 10 '17 at 5:21

The following produces externalised PDFs named Figure1.pdf and Figure2.pdf. \arrastikzsetnextfilename increments the figure counter, sets the filename and then decrements the counter, which \caption will then increment so that the figure's number matches the externalised filename.

\documentclass{article}
\usepackage{tikz}
\usepackage{cleveref}
\usetikzlibrary{external}
\tikzexternalize
\newcommand*\arrastikzsetnextfilename{%
\refstepcounter{figure}\edef\tempa{Figure\thefigure}%
\expandafter\tikzsetnextfilename{\tempa}%
}
\begin{document}
\arrastikzsetnextfilename
\begin{figure}
\tikz{\node {first};}

\caption{first}\label{fig:first}
\end{figure}
\arrastikzsetnextfilename
\begin{figure}
\tikz{\node {second};}

\caption{second}\label{fig:second}
\end{figure}
\end{document}

• I did mention only indirectly that I will have subfloats (Figure2a.pdf and Figure2b.pdf). But in contrast to moving floats around which can happen without me actually intervening, changing the order of subfloats does only happen so often. Thus I propose as a workaround for now to use an additional optional argument and changing the first two lines of your new command to \newcommand*{\arrastikzsetnextfilename}[1][]{\refstepcounter{figure}\edef\tempa{Figure\thefigure#1}%... and then use \arrastikzsetnextfilename[a] or \arrastikzsetnextfilename[b] etc in the file. – Matthias Arras Aug 8 '17 at 23:49
• @MatthiasArras The problem with automating the sub-figures is that you don't (automatically) know whether there will be a sub-figure or not. And you presumably don't want to have '1a' if, say, you only have 'Figure 1'. So the only way to track this automatically would be to write stuff to file and claw it back on the next run, which would introduce a great deal more complexity. You could, potentially, use something like \arrastikzsetnextfilename and \arrastikzsetnextfilename* and have it automatically generate the names. That would probably be not too much more complicated ...? – cfr Aug 9 '17 at 1:44
• I see. Write a \arrastikzsetnextfilename* when to use with subfigures and otherwise fall back to the unstarred. That would work I guess. Your solution with my addition of hard-coding the subfigure label a,b,c works for now. – Matthias Arras Aug 9 '17 at 2:37
• @MatthiasArras Mike's solution is probably better than either of the strategies I suggested. – cfr Aug 9 '17 at 22:52