7

I've used tikz to build all the charts in a manuscript I'm preparing for submission to a journal. As a last step prior to submission, I wanted to take all the tikz code out and just \includegraphics the externalized graphic files. The problem is that several of my graphics are groupplots where several plots share a common legend. I've accomplished this using legend to name=xxx and then placing \ref{xxx} after the figure. Here's an example. If you want to build it yourself the data is here and here

\documentclass{article}


\usepackage{pgfplots}
\usepgfplotslibrary{groupplots}
\usetikzlibrary{pgfplots.groupplots}
\usetikzlibrary{plotmarks}
\usetikzlibrary{patterns}
\usepgfplotslibrary{external}
\tikzexternalize



\pgfplotsset{compat = 1.12}

\begin{document}

\begin{figure}
    \centering
    \begin{tikzpicture}
        \begin{groupplot}[
                group style={group size=2 by 1,
                             xlabels at=edge bottom,
                             ylabels at=edge left},
                xlabel = {\footnotesize $\alpha_{++}$},
                ylabel = {\footnotesize Departure Rate},
                view={0}{90},
                colorbar horizontal,
                colorbar to name=ContourColorbar,
                colormap/blackwhite,
                y tick label style={/pgf/number format/.cd,
                                    fixed,
                                    fixed zerofill,
                                    precision=2,
                                    /tikz/.cd},
                x tick label style={/pgf/number format/.cd,
                                    fixed,
                                    fixed zerofill,
                                    precision=0,
                                    /tikz/.cd}]
                \nextgroupplot[title={\scriptsize Come and Go}]
                     \addplot3[surf, shader=interp,colormap/blackwhite] file {ComeAndGoSurface.txt};
                \nextgroupplot[title={\scriptsize ++Resources}]
                     \addplot3[surf, shader=interp,colormap/blackwhite] file {PPResourcesSurface.txt};
        \end{groupplot}
    \end{tikzpicture}
    \ref{ContourColorbar}
    \caption{++Resources and Come and Go}
    \label{HeatMap}
\end{figure}

\end{document}

This code produces the following document, which is fine.

enter image description here

But the externally generated image is this

enter image description here

Note, no colorbar.

The TikZ manual 50.4.1 offers this advice if there is a \ref inside of externalized graphics:

"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."

At this point I'm out of my depth. I'm using MikTex and TexNicCenter and that's the only way I've ever used Latex. I'm not really sure what "using mode=list and make or copy-paste the system call" even means. Is there a guide someone could point me to that spells this out? I did try some googling and found some references to using Make, but again I have no experience with this.

Alternatively, is there another method to achieve a single legend in a groupplot that avoids the \ref in the externalized image? I have several of these in this document in addition to the one shown here.

Thanks!

Addition: As I try to figure this out, I found this question whose answer boiled down to

Add

\pgfkeys{
    /tikz/external/mode=list and make
}

And then run make -B -f <filename>.makefile after the first compile run

So I download GNU make and tried this. After the first compile run, there is indeed a file called MWE.makefile. From the command prompt, I ran make -B -f MWE.makefile and I get the following output

process_begin: CreateProcess(NULL, cat mwe.figlist, ...) failed.
process_begin: CreateProcess(NULL, cat mwe.figlist, ...) failed. 
All images exist now.  Use make -B to re-generate them.

The resulting pdf file looks like this

enter image description here

So....any suggestions on how to proceed? Am I doing something wrong? Are there issues with make on a windows system?

Second addition: I'm piling on the questions here as I try to puzzle this out. I can't imagine I'm the first person to encounter this...maybe I'm just really dumb.

In another post here I found a very similar problem, just not using a groupplot. The solution involved inserting a node and replacing the \ref. Combing the MWE from that post with the changes provided in its answer provides the following code.

\documentclass{standalone}
\usepackage{tikz,pgfplots}
\pgfplotsset{compat=1.12}
\usetikzlibrary{external}
\tikzexternalize
\begin{document}
\begin{tikzpicture}
  \begin{axis}[%
      legend entries={$\sin(x)$},
      legend to name = named,
      name = plt 
    ]   
    \addplot {sin(deg(x))}; 
  \end{axis}
  \node[at=(plt.south),anchor=north] {\pgfplotslegendfromname{named}};
\end{tikzpicture}
\end{document}

I thought I had my answer...except that I can't figure out how to "name" a groupplot. You'll note in the above code the line name = plt in the axis environment. This allows you to later use node[at=(plt.south). Although the manual indicates that the groupplot environment should function basically the same as the axis environment, I can't figure out how to achieve that naming. And so I when I try to build I get No shape named plt is known. So if anyone knows how THAT can be accomplished then maybe that's my answer...

Third edit, I guess it's a process. Above I said I'd been unable to name a group plot. Figured that one out, but still no joy. Code now looks like this

\documentclass{article}


\usepackage{pgfplots}
\usepgfplotslibrary{groupplots}
\usetikzlibrary{pgfplots.groupplots}
\usetikzlibrary{plotmarks}
\usetikzlibrary{patterns}
\usepgfplotslibrary{external}
\tikzexternalize
%\pgfkeys{/tikz/external/mode=list and make}



\pgfplotsset{compat = 1.12}

\begin{document}

\begin{figure}
    \centering
    \begin{tikzpicture}
        \begin{groupplot}[group style={group size=2 by 1,
                                        group name = plots,
                            xlabels at=edge bottom,
                            ylabels at=edge left},
                            xlabel = {\footnotesize $\alpha_{++}$},
                            ylabel = {\footnotesize Departure Rate},
                                        view={0}{90},
                                        colorbar horizontal,
                                        colorbar to name=ContourColorbar,
                                        colormap/blackwhite,
                                        y tick label style={
                                            /pgf/number format/.cd,
                                            fixed,
                                            fixed zerofill,
                                            precision=2,
                                            /tikz/.cd
                                        },
                                        x tick label style={
                                            /pgf/number format/.cd,
                                            fixed,
                                            fixed zerofill,
                                            precision=0,
                                            /tikz/.cd
                                        }]
                            \nextgroupplot[title={\scriptsize Come and Go}]
                                            \addplot3[surf, shader=interp,colormap/blackwhite] file {ComeAndGoSurface.txt};
                                        \nextgroupplot[title={\scriptsize ++Resources}]
                                            \addplot3[surf, shader=interp,colormap/blackwhite] file {PPResourcesSurface.txt};
        \end{groupplot}
        \node[at=(plots c2r1.south),anchor=north] {\pgfplotslegendfromname{ContourColorbar}};
    \end{tikzpicture}
    %\ref{ContourColorbar}
    \caption{++Resources and Come and Go}
    \label{HeatMap}
\end{figure}

\end{document}

And the output looks like this

enter image description here

I'm guessing the ?? is my node with no colorbar.

  • Normally a legend is written to the aux file (as a huge macro definition), which shows up as ?? the first run. I have no idea what externalize does for an aux file. – John Kormylo May 18 '15 at 3:12
  • Just asking out of curiosity: why do you use the external library in the standalone document? Does it have to do with compiling the standalone-.tex in the figures subfolder? – henry May 18 '15 at 7:34
2

A possible solution would be to get externalize to compile twice to insert the reference on the second run. I could not figure out how to do this automatically.

But I can offer an alternative externalization using the tcolorbox package. This alternative may be used parallel to the TikZ way or as replacement.

In the following examples, I used the parallel setup. For this, the correct sequence of \tcbEXTERNALIZE and \tikzexternalize is important. \tikzexternalize is NOT needed for the following examples, but I left it in case you want to externalize other pictures the TikZ way.

The first variant encloses the picture plus legend with an tcbexternal environment:

\documentclass{article}

\usepackage[width=18cm]{geometry}
\usepackage{pgfplots,lipsum}
\usepgfplotslibrary{groupplots}
\usetikzlibrary{pgfplots.groupplots}
\usetikzlibrary{plotmarks}
\usetikzlibrary{patterns}
\usepgfplotslibrary{external}

\usepackage[external]{tcolorbox}
\tcbset{
  external/prefix=\jobname-,
  external/safety=0mm,
  external/input source on error=false,
}

\pgfplotsset{compat = 1.12}

%--- use this AFTER \pgfplotsset and BEFORE \tikzexternalize
\tcbEXTERNALIZE
%---

\tikzexternalize
\pgfkeys{/tikz/external/mode=list and make}

\begin{document}

\begin{figure}
    \begin{tcbexternal}[minipage,runs=2]{contour}
    \centering
    \begin{tikzpicture}
        \begin{groupplot}[group style={group size=2 by 1,
                                        group name = plots,
                            xlabels at=edge bottom,
                            ylabels at=edge left},
                            xlabel = {\footnotesize $\alpha_{++}$},
                            ylabel = {\footnotesize Departure Rate},
                                        view={0}{90},
                                        colorbar horizontal,
                                        colorbar to name=ContourColorbar,
                                        colormap/blackwhite,
                                        y tick label style={
                                            /pgf/number format/.cd,
                                            fixed,
                                            fixed zerofill,
                                            precision=2,
                                            /tikz/.cd
                                        },
                                        x tick label style={
                                            /pgf/number format/.cd,
                                            fixed,
                                            fixed zerofill,
                                            precision=0,
                                            /tikz/.cd
                                        }]
                            \nextgroupplot[title={\scriptsize Come and Go}]
                                            \addplot3[surf, shader=interp,colormap/blackwhite] file {ComeAndGoSurface.txt};
                                        \nextgroupplot[title={\scriptsize ++Resources}]
                                            \addplot3[surf, shader=interp,colormap/blackwhite] file {PPResourcesSurface.txt};
        \end{groupplot}
    \end{tikzpicture}
    \ref{ContourColorbar}
    \end{tcbexternal}
    \caption{++Resources and Come and Go}
    \label{HeatMap}
\end{figure}

\lipsum[1]

\end{document}

The second variant puts the legend as node inside the picture and replaces tikzpicture by extikzpicture:

\documentclass{article}

\usepackage[width=18cm]{geometry}
\usepackage{pgfplots,lipsum}
\usepgfplotslibrary{groupplots}
\usetikzlibrary{pgfplots.groupplots}
\usetikzlibrary{plotmarks}
\usetikzlibrary{patterns}
\usepgfplotslibrary{external}

\usepackage[external]{tcolorbox}
\tcbset{
  external/prefix=\jobname-,
  external/safety=0mm,
  external/input source on error=false,
}

\pgfplotsset{compat = 1.12}

%--- use this AFTER \pgfplotsset and BEFORE \tikzexternalize
\tcbEXTERNALIZE
%---

\tikzexternalize
\pgfkeys{/tikz/external/mode=list and make}

\begin{document}

\begin{figure}
    \centering
    \begin{extikzpicture}[runs=2]{contour}
        \begin{groupplot}[group style={group size=2 by 1,
                                        group name = plots,
                            xlabels at=edge bottom,
                            ylabels at=edge left},
                            xlabel = {\footnotesize $\alpha_{++}$},
                            ylabel = {\footnotesize Departure Rate},
                                        view={0}{90},
                                        colorbar horizontal,
                                        colorbar to name=ContourColorbar,
                                        colormap/blackwhite,
                                        y tick label style={
                                            /pgf/number format/.cd,
                                            fixed,
                                            fixed zerofill,
                                            precision=2,
                                            /tikz/.cd
                                        },
                                        x tick label style={
                                            /pgf/number format/.cd,
                                            fixed,
                                            fixed zerofill,
                                            precision=0,
                                            /tikz/.cd
                                        }]
                            \nextgroupplot[title={\scriptsize Come and Go}]
                                            \addplot3[surf, shader=interp,colormap/blackwhite] file {ComeAndGoSurface.txt};
                                        \nextgroupplot[title={\scriptsize ++Resources}]
                                            \addplot3[surf, shader=interp,colormap/blackwhite] file {PPResourcesSurface.txt};
        \end{groupplot}
        \node[at=(plots c1r1.south),below=1cm] {\ref{ContourColorbar}};
    \end{extikzpicture}
    \caption{++Resources and Come and Go}
    \label{HeatMap}
\end{figure}

\lipsum[1]

\end{document}

Note the run=2 option which compiles the snippet twice to get the legend reference correct. contour is the name part for the externalized snippet which will be \jobname-contour.pdf

  • Tried the first method and bizarrely it worked fine for some of the plots, and for some it stuck the legend off to the right hand side. I'll try the second approach tomorrow. Thanks for your help! – jerH May 19 '15 at 3:04
  • @user1922959 The second approach has the advantage that the legend can be placed quite arbitrarily using node coordinates. Maybe, that's what you need. – Thomas F. Sturm May 19 '15 at 7:15
0

Finally managed to work it out based on Thomas' answer with a few modifications to the second variant.

First, I didn't use mode=list and make. For whatever reason I was never able to do anything with the makefile that generated. Second, had to usetikzlibrary{calc} so that I could manipulate the node positions to get some of the legends to line up where I wanted them. So code that looks like

\documentclass{article}

\usepackage[width=18cm]{geometry}
\usepackage{caption}
\usepackage{placeins}
\usepackage{pgfplots}
\usepgfplotslibrary{groupplots}
\usetikzlibrary{pgfplots.groupplots}
\usetikzlibrary{plotmarks}
\usetikzlibrary{patterns}
\usetikzlibrary{calc}
\usepgfplotslibrary{external}

\usepackage[external]{tcolorbox}
\tcbset{
    external/prefix=\jobname-,
    external/safety=0mm,
    external/input source on error=false,
    }

\pgfplotsset{compat = 1.12}

\tcbEXTERNALIZE

\tikzexternalize

\begin{document}

\begin{figure}
    \centering
    \begin{extikzpicture}[runs=2]{fig4}
        \begin{groupplot}[
                legend columns=5,
                legend entries={{\tiny +Method},{\tiny Hold All},{\tiny Random},{\tiny Come and Go}},
                legend to name=CombinedLegendAlpha,
                group style={
                group name = fig4_plots,
                group size=2 by 1,
                xlabels at=edge bottom,
                ylabels at=edge left
                },
                legend style={draw=none},
                %legend style={at={(0.98,0.825)}},
                xlabel = {\footnotesize $\alpha_{+}$},
                ylabel = {\footnotesize Avg Portfolio Value},
                ]
            \nextgroupplot[title={\scriptsize +Cost Method},
                    y tick label style={
                    font=\tiny,
                    /pgf/number format/.cd,
                            fixed,
                            fixed zerofill,
                            precision=0,
                    /tikz/.cd
                    },
                    footnotesize,
                    x tick label style={
                            font=\tiny,
                            /pgf/number format/.cd,
                                    fixed,
                                    fixed zerofill,
                                    precision=1,
                            /tikz/.cd
                    }]
                \addplot+[black, mark=o,line join=round, mark repeat=15] table[col sep=comma, y=PlusCost, x=CostAlpha]{PlusMethodsAlpha.csv};
                \addplot+[black, mark=x,line join=round, mark repeat=15] table[col sep=comma, y=HoldAll, x=CostAlpha]{PlusMethodsAlpha.csv};
                \addplot+[black, mark=|,line join=round, mark repeat=15] table[col sep=comma, y=Random, x=CostAlpha]{PlusMethodsAlpha.csv};
                \addplot+[black, mark=square,line join=round, mark repeat=15] table[col sep=comma, y=ComeAndGo, x=CostAlpha]{PlusMethodsAlpha.csv};
            \nextgroupplot[title={\scriptsize +FTE Method},
                        y tick label style={
                        font=\tiny,
                        /pgf/number format/.cd,
                                fixed,
                                fixed zerofill,
                                precision=0,
                        /tikz/.cd
                },
                footnotesize,
                x tick label style={
                        font=\tiny,
                        /pgf/number format/.cd,
                                fixed,
                                fixed zerofill,
                                precision=0,
                        /tikz/.cd
                }]
                \addplot+[black, mark=o,line join=round, mark repeat=15] table[col sep=comma, y=PlusFTE, x=FTEAlpha]{PlusMethodsAlpha.csv};
                \addplot+[black, mark=x,line join=round, mark repeat=15] table[col sep=comma, y=HoldAll, x=FTEAlpha]{PlusMethodsAlpha.csv};
                \addplot+[black, mark=|,line join=round, mark repeat=15] table[col sep=comma, y=Random, x=FTEAlpha]{PlusMethodsAlpha.csv};
                \addplot+[black, mark=square,line join=round, mark repeat=15] table[col sep=comma, y=ComeAndGo, x=FTEAlpha]{PlusMethodsAlpha.csv};
        \end{groupplot}
        %\node[at=(fig4_plots c1r1.south),below=1cm]{\ref{CombinedLegendAlpha}};
        \node (fig4_Legend) at ($(fig4_plots c1r1.center)!0.5!(fig4_plots c2r1.center)-(0,2.5cm)$){\ref{CombinedLegendAlpha}};
    \end{extikzpicture}
    \caption{Triage+ Performance}
    \label{PlusAlpha}
\end{figure}

\end{document}

Gives me a pdf file containing

enter image description here

which is exactly what I need. Ignore the red box...it's an artifact of the pdf viewer.

Thanks so much for the help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.