[Tex/LaTex] tikz externalization and multiple axis using \ref and \label for legendentry

cross-referencinglegendpgfplotstikz-external

I have a plot consisting of two y-axis. When I'm adding the legendentries in each axis environment, the first legendentry will be plotted "behind" the plot of the second axis. Thus I thought a solution might be the \ref \label to plot both legendentries at the end of the document, that they will appear in the very front of all plots and not hidden.
Unfortunately using the tikz externalization gives the error "undefined references …." and the legendentries are given with "??" only.
I checked the manual for using \legend \ref with externalization, but it doesn't help. I tried to compile several times.

\documentclass[fontsize=12pt,openright,oneside,DIV11,a4paper,numbers=noenddot,headsepline,parskip=half]{scrbook}
\usepackage[latin1]{inputenc}
\usepackage[cmex10]{amsmath}
\usepackage{siunitx}
\usepackage{tikz}
\usetikzlibrary[shapes.arrows]
\usepackage{pgfplots}
\pgfplotsset{compat=1.3}

% set up externalization
\usetikzlibrary{pgfplots.external}
\tikzset{external/system call={lualatex \tikzexternalcheckshellescape -halt-on-error -interaction=batchmode -jobname "\image" "\texsource"}}
\tikzexternalize


\begin{document}
\thispagestyle{empty}
    \begin{tikzpicture}
        \begin{axis}[
                legend cell align=left,
            bar width=7pt,
            xmin=-3, xmax=30,
            axis y line*=left,
            xlabel=Laser current / \si{\milli\ampere},
            ylabel=Tuning range / \si{\nano\metre},
            nodes near coords align=left,
            nodes near coords,]
        \addplot[ybar, ybar legend, draw=gray, fill=gray, color=gray] table[x=current,y=tuning] {Tun_SMSR.txt};

%          \addlegendentry{Abstimmbereich};
       \label{Abstimmbereich};
    \end{axis}

    \begin{axis}[
            every axis legend/.append style={fill=white, anchor=north west, at={(0.35,0.18)}},
            legend cell align=left,
            ybar=5pt,
            ybar interval=0.6,
            bar width=7pt,
            xmin=-3, xmax=30,
            ymin=30, ymax=60,
            axis y line*=right,
            axis x line=none,
            ylabel=SMSR / \si{\deci\bel},
            nodes near coords align=left,
            nodes near coords,]
        \addplot[ybar, ybar legend, draw=black, color=black] table[x=current,y=SMSR] {Tun_SMSR.txt};
       \label{SMSR};
%          \addlegendentry{SMSR};

    \end{axis}

\node [draw,fill=white] at (rel axis cs: 0.7,0.15) {\shortstack[l]{
\ref{Abstimmbereich} Abstimmbereich\\
\ref{SMSR} SMSR
}};

    \end{tikzpicture}
\end{document}

I'm compiling with the command

lualatex -shell-escape "document name".tex

The resulting figure shows the legends but with no symbols and "??" instead.

Best Answer

You are referring to a label which has been externalized to a separate pdf - which is a complex task.

Here, "complex" means "too complex for the standard -shell-escape image externalization". In order to reference something inside of some external image, you have to take special steps.

To quote from the pgfplots manual: "For point a), a \ref inside of an externalized graphics works only if you issue the required system call manually or by make. The initial configuration mode=convert with system calldoes not support \ref. But you can copy­paste the system call generated by mode=convert with system call and issue it manually. The reason is that \ref information is stored in the main .aux file ­ but this auxiliary file is not completely written when mode=convert with system call is invoked (there is a race condition). Note that \pageref is not supported (sorry). Thus: if you have \ref inside of external graphics, consider using mode=list and make or copy­paste the system call for the image(s) and issue it manually."

Alternatively, you can wait (say) one week until the next version of pgfplots is released. It supports layered graphics such that the first legend will not appear behind the second axis.

Another altivernative solution might be to insert a legend entry for the first plot into the legend of the second image using \addlegendimage{<style>}:

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.3}

\begin{document}
    \begin{tikzpicture}
    \pgfplotsset{
        plot 0/.style={
            ybar, ybar legend, draw=gray, fill=gray, color=gray
        }
    }
       \begin{axis}[
                legend cell align=left,
            bar width=7pt,
            xmin=0, xmax=1,
            axis y line*=left,
            xlabel=Laser current,
            ylabel=Tuning range,
            nodes near coords align=left,
            nodes near coords,]
        \addplot[plot 0] {rand};

%          \addlegendentry{Abstimmbereich};
 %      \label{Abstimmbereich};
    \end{axis}

    \begin{axis}[
            every axis legend/.append style={fill=white, anchor=north west, at={(0.35,0.18)}},
            legend cell align=left,
            ybar=5pt,
            ybar interval=0.6,
            bar width=7pt,
            xmin=0, xmax=1,
            ymin=30, ymax=60,
            axis y line*=right,
            axis x line=none,
            ylabel=SMSR,
            nodes near coords align=left,
            nodes near coords,]

\addlegendentry{Abstimmbereich}
\addlegendimage{plot 0}
        \addplot[ybar, ybar legend, draw=black, color=black] {30 + rand*30};
       \label{SMSR};
          \addlegendentry{SMSR};

    \end{axis}

    \end{tikzpicture}
\end{document}

enter image description here

Note that I have deliberately stripped the example from your data files and some other stuff - the only point here is the special legend construction. This does also work with image externalization.

In order to share the common options, I extracted the style for your first plot and used it at two places (this has the same effect as \label{Abstimmbereich} and refstyle={Abstimmbereich}, but it integrates seamlessly into the image externalization workflow).