[Tex/LaTex] How to import and scale matplotlib plots, keeping fonts the correct size

matplotlibplotscalingtikz-pgf

I'm working on several pieces of coursework involving lots of plots generated with matplotlib in python scripts.

Currently I'm doing this with an iterative process where I set a plot size in the latex code, generate the correctly sized plot in my python script and run latex to generate the document. This is then repeated when it inevitably doesn't quite look how I want it.

This is quite time consuming so I've been looking for some way of speeding things up. What would be ideal would be to run my python script once to produce the graph and then import it in latex using some command to scale it appropriately while keeping the font settings consistent with the rest of the document. I'd then play with the settings within latex without needing to modify and re-run the python script each time.

The first and second answers to this question seem to be what I'm looking for, but unfortunately they are for Matlab.

I've tried using the same procedure with the matplotlib equivalent commands but have had the following problems:

1. Generating pgf with matplotlib, scaling with tikzscale:

I generate a pgf plot from matplotlib called test.pgf and use the following latex code:

\documentclass{article}
\usepackage{pgf}
\usepackage{tikz}
\usepackage{tikzscale}
\usepackage{pgfplots}

\begin{document}
    \begin{figure}
        \centering
        \includegraphics[width=0.5\textwidth]{test.pgf}
        \caption{Some figure}
        \label{fig:figure}
    \end{figure}
\end{document}

Fails with the following error:

! Package tikzscale Error: Requested to scale unscalable graphic.

2. Generating .svg with matplotlib, converting to .pdf, scaling with \includegraphics:

As before except just include test.pdf.

Fails as text in plots is not scaled correctly…

I'd of course be happy to look into some other method too if you can suggest anything!

Best Answer

The matplotlib PGF backend saves as raw PGF. What you probably want instead is pgfplots, which you can get using tikzplotlib, assuming your plots aren't too complex and all the features are supported.

Sample Python script for creating figure:

from pylab import *
from tikzplotlib import save as tikz_save
x = linspace(0, 10, 101)
plot(x, sin(x))
xlabel('$x$-axis')
ylabel('$y$-axis')
tikz_save('fig.tikz',
           figureheight = '\\figureheight',
           figurewidth = '\\figurewidth')

Sample accompanying LaTeX document that brings in the plots with two different dimensions (you could use \input; I'm using \InputIfFileExists so that missing figures won't kill compilation):

\documentclass{article}

\usepackage{pgfplots}

\newlength\figureheight
\newlength\figurewidth

\begin{document}

\setlength\figureheight{2in}
\setlength\figurewidth{3in}
\InputIfFileExists{fig.tikz}{}{\textbf{!! Missing graphics !!}}

\setlength\figureheight{3in}
\setlength\figurewidth{4in}
\InputIfFileExists{fig.tikz}{}{\textbf{!! Missing graphics !!}}

\end{document}

Output:

enter image description here

Depending on what you are doing, you could also consider using my PythonTeX package to put everything in the LaTeX source:

\documentclass{article}

\usepackage{pgfplots}
\usepackage[stdout=false]{pythontex}
% matplotlib2tikz prints messages to stdout, so don't include
% stdout automatically; could also redirect stdout to avoid this
\setpythontexworkingdir{.}
% set PythonTeX to use the document root directory as the working
% directory, so that all plots will be saved there; could use 
% another location, but then would need to specify a path when
% using \input and \InputIfFileExists

\newlength\figureheight
\newlength\figurewidth

\begin{document}

\begin{pycode}
from pylab import *
from tikzplotlib import save as tikz_save
x = linspace(0, 10, 101)
plot(x, sin(x))
xlabel('$x$-axis')
ylabel('$y$-axis')
tikz_save('fig.tikz',
       figureheight = '\\figureheight',
       figurewidth = '\\figurewidth')
\end{pycode}

\setlength\figureheight{2in}
\setlength\figurewidth{3in}
\InputIfFileExists{fig.tikz}{}{\textbf{!! Missing graphics !!}}

\setlength\figureheight{3in}
\setlength\figurewidth{4in}
\InputIfFileExists{fig.tikz}{}{\textbf{!! Missing graphics !!}}

\end{document}
Related Question