3

tl;dr: How can I make standalone crop a pgfplot diagram with fixed distance to the plot axes?

Background:

I have four pgfplot diagrams rendered as PDF images by the standalone class. Due to the different ztick labels, the vertical edges of the boxes, e.g. the z-axis, are not aligned well right now (albeit it's not way off) when I put them in subfigures:

enter image description here

Since my actual data is large, it is not feasible to put the four tikzpictures in my main document. There are two elaborate answers: One based on the use of the external library and one using some fancy trimming.

However, I want to keep it simple (the code of my main document as well as no manual copy-pasting of trim parameters).

Can I just have standalone crop the plots with a fixed distance from the plot axes?

In 2D this should not be impossible. In 3D, the distance needs to be defined from the top/bottom vertices of the boxes around the plots.

Here's the MWE of my main file:

% !TeX program = lualatex
\documentclass{scrbook}

\usepackage[partial=upright]{unicode-math}
\usepackage{fontspec}
\usepackage{caption,subcaption}
\usepackage{graphicx}
\usepackage[main=ngerman,english]{babel}

\begin{document}
    \begin{figure}
        %
        \begin{subfigure}{0.5\linewidth}
            \includegraphics{3dplot_a.pdf}
        \end{subfigure}
        %
        \begin{subfigure}{0.5\linewidth}
            \includegraphics{3dplot_b.pdf}
        \end{subfigure}
        %
        \begin{subfigure}{0.5\linewidth}
            \includegraphics{3dplot_c.pdf}
        \end{subfigure}
        %
        \begin{subfigure}{0.5\linewidth}
            \includegraphics{3dplot_d.pdf}
        \end{subfigure}
        %
    \end{figure}
\end{document}

Here is the code that generates the four sample plots (for convenience, all files are available on this GitHub repo):

% !TeX program = lualatex
\RequirePackage{luatex85}
\documentclass[border=1pt]{standalone}

\usepackage{mathtools}
\usepackage{amssymb}

\usepackage[partial=upright]{unicode-math}
\usepackage{fontspec}
\usepackage{xcolor}

\usepackage{tikz}
\usepackage{pgfplots}

\usepackage[main=ngerman,english]{babel}

\begin{document}

% plot a
\begin{tikzpicture}
    \begin{axis}[
        width=7cm,
        grid=both,
        view={60}{45},
        set layers,
        every axis plot/.append style={on layer=pre main},
        xlabel={$x$},
        ylabel={$y$},
        zlabel={some quantity $z$},
        grid=both,
        clip=false,
    ]
    \addplot3 [
        mesh,
        scatter,
        samples=10,
        domain=0:1,
    ] {5*x*sin(2*deg(x)) * y*(1-y)};
    \node at (rel axis cs:0.5,1,1) [above,sloped like x axis] {$x$ explanation};
    \node at (rel axis cs:0,0.5,1) [above,sloped like y axis] {$y$ explanation};
    \end{axis}
\end{tikzpicture}

%% plot b
%\begin{tikzpicture}
%   \begin{axis}[
%       width=7cm,
%       grid=both,
%       view={60}{45},
%       set layers,
%       every axis plot/.append style={on layer=pre main},
%       xlabel={$x$},
%       ylabel={$y$},
%       zlabel={another quantity $z$},
%       grid=both,
%       clip=false,
%   ]
%   \addplot3 [
%       mesh,
%       scatter,
%       samples=10,
%       domain=0:1,
%   ] {5*x*cos (2*deg(x)) * y*(1-y) + 15};
%   \node at (rel axis cs:0.5,1,1) [above,sloped like x axis] {$x$ explanation};
%   \node at (rel axis cs:0,0.5,1) [above,sloped like y axis] {$y$ explanation};
%   \end{axis}
%\end{tikzpicture}

%% plot c
%\begin{tikzpicture}[trim axis left, trim axis right]
%   \begin{axis}[
%       width=7cm,
%       grid=both,
%       view={60}{45},
%       set layers,
%       every axis plot/.append style={on layer=pre main},
%       xlabel={$x$},
%       ylabel={$y$},
%       ztick={0},
%       zlabel={third quantity $z$},
%       grid=both,
%       clip=false,
%   ]
%   \addplot3 [
%       mesh,
%       scatter,
%       samples=10,
%       domain=0:1,
%   ] {5*sin (4*deg(x)) * y*(1-y)};
%   \node at (rel axis cs:0.5,1,1) [above,sloped like x axis] {$x$ explanation};
%   \node at (rel axis cs:0,0.5,1) [above,sloped like y axis] {$y$ explanation};
%   \end{axis}
%\end{tikzpicture}

%% plot d
%\begin{tikzpicture}[trim axis left, trim axis right]
%   \begin{axis}[
%       width=7cm,
%       grid=both,
%       view={60}{45},
%       set layers,
%       every axis plot/.append style={on layer=pre main},
%       xlabel={$x$},
%       ylabel={$y$},
%       ztick={1000},
%       zlabel={fourth quantity $z$},
%       grid=both,
%       clip=false,
%   ]
%   \addplot3 [
%       mesh,
%       scatter,
%       samples=10,
%       domain=0:1,
%   ] {x*y+1000};
%   \node at (rel axis cs:0.5,1,1) [above,sloped like x axis] {$x$ explanation};
%   \node at (rel axis cs:0,0.5,1) [above,sloped like y axis] {$y$ explanation};
%   \end{axis}
%\end{tikzpicture}

\end{document}
  • I think \begin{tikzpicture}[trim axis left,trim axis right] combined with \documentclass[border={1.5cm 2pt 5mm 2pt}]{standalone} (some adjustment of lengths possibly needed) might work, but I haven't tested fully. You might also want to add overlay to the "explanation" nodes, so they don't affect the bounding box. – Torbjørn T. Mar 24 '18 at 16:59
  • Perfect - this is an answer. Overlooking these things makes me doubt my usage of TeX. – Christoph90 Mar 24 '18 at 17:06
4

pgfplots provides the keys trim axis left and trim axis right that will set the bounding box of the tikzpicture so that its left edge is along the left side of the axis box (i.e. ticklabels etc. are outside the bounding box), and similarly for the right side. Note that these must be provided to the tikzpicture environment, not the axis environment, that is

\begin{tikzpicture}[trim axis left,trim axis right]

So those will take care of the horizontal extension of the bounding box. For the vertical extension, you could perhaps add the overlay key to the nodes containing the axis labels, with label style={overlay}. This options means that the node/path will not be taken into account when the bounding box is calculated. Similarly you might want to add overlay to your "explanation" nodes.

The final piece is then to note that standalone lets you set the border individually for each side. I.e. you can do

\documentclass[border={1.5cm 2pt 5mm 2pt}]{standalone}

to have 1.5cm border on the left, 5mm on the right, and 2pt on bottom and top. (The manual says that the order of the values refer to the left, right, bottom, and top sides respectively, but it seemed from my test that it's actually left, bottom, right, top, just like trim for \includegraphics.)

  • It's not working for groupplots unfortunately. – Christoph90 Mar 24 '18 at 18:40
  • 1
    @Christoph90 See manual, there are separate trim axis group left/right that are "tailored for the groupplots library". – Torbjørn T. Mar 24 '18 at 18:41

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.