3

I want to place 3 pictures next to each other using subcaption. The two right pictures are external graphics files that I include using \includegraphics. The left one is supposed to be a pgfplots chart. Naturally, I want them and the captions to align vertically. To achieve set I use a common height for all three pictures which is defined in \figheight. As a dry run, everything seems to work with example-image-a, etc:

enter image description here

However, when I replace the left figure by a pgfplot and specify its exact height to the height of the external figures right next, the result is somehow curious:

enter image description here

Why is the height not exactly the value of \figheight? Is there a difference between the height of the axis environment and the height of the tikzpicture? From the manual:

If scale only axis=false (the default), pgfplots will try to produce the desired width including labels, titles and ticks.

I guess the same holds for the height?! How can I fix this for a proper alignment of the pictures as well as the subcaptions?


MWE

\documentclass{article}

\usepackage{graphicx}
\usepackage{pgfplots}
\usepackage{subcaption}

\pgfplotsset{compat=newest}

\newlength{\figheight}
\setlength{\figheight}{5cm}

\begin{document}

Works:

\begin{figure}[htbp]
  \begin{subfigure}{0.65\linewidth}
    \centering
    \includegraphics[width=\linewidth,height=\figheight]{example-image-a}
    \caption{Test1}
  \end{subfigure}
  \hfill
  \begin{subfigure}{0.16\linewidth}
    \centering
    \includegraphics[angle=90,width=\linewidth,height=\figheight]{example-image-b}
    \caption{Test2}
  \end{subfigure}
  \hfill
  \begin{subfigure}{0.16\linewidth}
    \centering
    \includegraphics[angle=90,width=\linewidth,height=\figheight]{example-image-c}
    \caption{Test3}
  \end{subfigure}
  \caption{Overall caption}
\end{figure}

Weird size and resulting caption position:

\begin{figure}[htbp]
  \begin{subfigure}{0.65\linewidth}
    \centering
    \begin{tikzpicture}
      \begin{axis}[
        width=\linewidth,
        height=\figheight,
      ]
        \addplot+ {x};
        \addlegendentry{$f(x)=x$}
      \end{axis}
    \end{tikzpicture}
    \caption{Test1}
  \end{subfigure}
  \hfill
  \begin{subfigure}{0.16\linewidth}
    \centering
    \includegraphics[angle=90,width=\linewidth,height=\figheight]{example-image-b}
    \caption{Test2}
  \end{subfigure}
  \hfill
  \begin{subfigure}{0.16\linewidth}
    \centering
    \includegraphics[angle=90,width=\linewidth,height=\figheight]{example-image-c}
    \caption{Test3}
  \end{subfigure}
  \caption{Overall caption}
\end{figure}

\end{document}
1

The problem is that the axis environment will take into account, for the height, also the minimum size of the title and of the xlabel. See:

\documentclass{article}

\usepackage{graphicx}
\usepackage{pgfplots}
\usepackage{subcaption}

% modified from @egreg idea https://tex.stackexchange.com/a/88624/38080
\usepackage{xparse}
\newsavebox{\fminipagebox}
\NewDocumentEnvironment{fminipage}{O{c} O{} O{c} m O{\fboxsep}}
 {\par\kern#5\noindent\begin{lrbox}{\fminipagebox}
     \begin{minipage}[#1][#2][#3]{#4}\ignorespaces}
 {\end{minipage}\end{lrbox}%
  \makebox[#4]{%
    \kern\dimexpr-\fboxsep-\fboxrule\relax
    \fbox{\usebox{\fminipagebox}}%
    \kern\dimexpr-\fboxsep-\fboxrule\relax
  }\par\kern#5
 }

\pgfplotsset{compat=newest}

\newlength{\figheight}
\setlength{\figheight}{5cm}

\begin{document}

\begin{figure}[htbp]
  \begin{subfigure}{0.65\linewidth}
    \centering
    \setlength{\fboxsep}{0pt}
    \begin{fminipage}[t][\figheight][t]{\linewidth}%
    \begin{tikzpicture}
      \begin{axis}[
        height=\figheight,
        width=\linewidth,
        xlabel=$x$,
        title = title,
      ]
        \addplot+ {x};
        \addlegendentry{$f(x)=x$}
      \end{axis}
    \end{tikzpicture}
\end{fminipage}
    \caption{Test1 \the\linewidth \the\figheight}
  \end{subfigure}
  \hfill
  \begin{subfigure}{0.16\linewidth}
    \centering
    \includegraphics[angle=90,width=\linewidth,height=\figheight]{example-image-b}
    \caption{Test2}
  \end{subfigure}
  \hfill
  \begin{subfigure}{0.16\linewidth}
    \centering
    \includegraphics[angle=90,width=\linewidth,height=\figheight]{example-image-c}
    \caption{Test3}
  \end{subfigure}
  \caption{Overall caption}
\end{figure}

\end{document}

which gives (notice I added a "no size" frame around):

perfectly aligned things...

I do not know how to remove these sizes from the graph. Something on the line of

\begin{axis}[
        height=\figheight+\baselineskip,
        width=\linewidth,
        xlabel = \empty,
        title = \empty,
      ]

gives a better appearance:

try one

but I feel this is a bit of an hack...

The best I can suggest is to add the external (zero size) frame and remove the graph one, like:

\setlength{\fboxsep}{0pt}
\begin{fminipage}[t][\figheight][t]{\linewidth}%
    \centering
    \begin{tikzpicture}
      \begin{axis}[
        height=\figheight+\baselineskip,
        width=\linewidth,
        xlabel = \empty,
        title = \empty,
        axis x line = center, 
        axis y line = center,
        ]
        \addplot+ {x};
        \addlegendentry{$f(x)=x$}
      \end{axis}
    \end{tikzpicture}
\end{fminipage}

which gives:

second try

1

Not exactly aligned but fairly close:

enter image description here

\documentclass{article}
\usepackage{graphicx}
\usepackage{pgfplots}
\usepackage{subcaption}
\pgfplotsset{compat=newest}

\newlength{\figheight}
\setlength{\figheight}{5cm}

\begin{document}

Works:
\begin{figure}[htbp]
  \begin{subfigure}{0.65\linewidth}
    \centering
    \includegraphics[width=\linewidth,height=\figheight]{example-image-a}
    \caption{Test1}
  \end{subfigure}
  \hfill
  \begin{subfigure}{0.16\linewidth}
    \centering
    \includegraphics[angle=90,width=\linewidth,height=\figheight]{example-image-b}
    \caption{Test2}
  \end{subfigure}
  \hfill
  \begin{subfigure}{0.16\linewidth}
    \centering
    \includegraphics[angle=90,width=\linewidth,height=\figheight]{example-image-c}
    \caption{Test3}
  \end{subfigure}
  \caption{Overall caption}
\end{figure}

Weird size and resulting caption position:

\begin{figure}[htbp]
  \begin{subfigure}{0.65\linewidth}
    \centering
    \begin{tikzpicture}
      \begin{axis}[
 %       width=\linewidth,
        height=\figheight-\baselineskip, % changed
        scale only axis                  % added
      ]
        \addplot+ {x};
        \addlegendentry{$f(x)=x$}
      \end{axis}
    \end{tikzpicture}
    \caption{Test1}
  \end{subfigure}
  \hfill
  \begin{subfigure}{0.16\linewidth}
    \centering
    \includegraphics[angle=90,width=\linewidth,height=\figheight]{example-image-b}
    \caption{Test2}
  \end{subfigure}
  \hfill
  \begin{subfigure}{0.16\linewidth}
    \centering
    \includegraphics[angle=90,width=\linewidth,height=\figheight]{example-image-c}
    \caption{Test3}
  \end{subfigure}
  \caption{Overall caption}
\end{figure}
\end{document}
1

Assuming you want to align the bounding box of the (whole) axis environment (and not only the "box" of the axis environment) you have to tweek the height a little bit. The PGFPlots manual states in section 4.10.1 at the height key:

[...]
Please note that pgfplots only estimates the size needed for axis and tick labels. The estimate assumes a fixed amount of space for anything which is outside of the axis box. This has the effect that the final images may be slightly larger or slightly smaller than the prescribed dimensions. However, the fixed amount is always the same; it is set to 45pt.
[...]

As Rmano already stated in his answer this is approximately the additional size of the

  • ticklabels,
  • axis labels, and
  • title.

Thus, if some of them are missing, we have to "compensate" for that.

Please find attached some code how I would do it together with a lot of comments.

% used PGFPlots v1.15
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
    \pgfplotsset{
        % use layers to show the bounding boxes of the `axis' environments
        set layers={
            background,
            main,
        },
    }
    \newlength{\figheight}
    \setlength{\figheight}{5cm}
\begin{document}
    % by default the `width' and `height' are reduced by 45pt which is used
    % for ticklabels, axis labels and the title
    \begin{tikzpicture}
        \begin{axis}[
            width=\figheight,
            height=\figheight,
            xlabel=$x$,
            ylabel=$y$,
            title=title,
            name=p,
        ]
            \addplot {x};
        \end{axis}

        \begin{pgfonlayer}{background}
            \fill [yellow!10] (p.outer south west)
                rectangle (p.outer north east);
        \end{pgfonlayer}

        \draw [red] (p.outer south east)
            -- +(0,\figheight) circle (1.5pt);
        \draw [red] (p.outer south east)
            -- +(-\figheight,0) circle (1.5pt);
    \end{tikzpicture}
    %
    \includegraphics[angle=90,height=\figheight]{example-image-a}
    %
    % so if no title and y label are given and we want to align the bounding
    % box of the whole `axis' environment (not only the box of the `axis'
    % environment) with the bounding box of the graphics, we have to enlarge
    % the `height' (manually) to fit to the desired `height'.
    \begin{tikzpicture}
        \begin{axis}[
            width=\figheight,
            % -----------------------------------------------------------------
            height=\figheight + 30pt,
%            % -------------------------
%            % equivalently we have to reduce the `height' if `scale only axis'
%            % is given
%            scale only axis,
%            height=\figheight - 15pt,
            % -----------------------------------------------------------------
            name=q,
        ]
            \addplot {x};
        \end{axis}

        \begin{pgfonlayer}{background}
            \fill [yellow!10] (q.outer south west)
                rectangle (q.outer north east);
        \end{pgfonlayer}

        \draw [red] (q.outer south west)
            -- +(0,\figheight) circle (1.5pt);
        \fill [green] (q.outer north west) circle (1pt);
    \end{tikzpicture}
\end{document}

image showing the result of above code

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.