Exporting Matplotlib plots to LaTeX.
We're starting with the following Python script:
#!/usr/bin/env python3
import locale
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
import sys
locale.setlocale(locale.LC_NUMERIC, 'en_US.UTF-8')
matplotlib.use('pgf')
matplotlib.rcParams.update({
'pgf.texsystem': 'pdflatex',
'pgf.preamble': '\n'.join([
r'\usepackage[T1]{fontenc}',
]),
'pgf.rcfonts': False,
'font.family': 'serif',
'font.size' : 11,
'axes.formatter.use_locale': True,
})
np.random.seed(19680801)
mu = 100
sigma = 15
x = mu + sigma * np.random.randn(437)
num_bins = 50
fig, ax = plt.subplots()
n, bins, patches = ax.hist(x, num_bins, density=1)
y = ((1 / (np.sqrt(2 * np.pi) * sigma)) *
np.exp(-0.5 * (1 / sigma * (bins - mu))**2))
ax.plot(bins, y, '--')
ax.set_xlabel('Smarts')
ax.set_ylabel('Probability density')
ax.set_title(rf'Histogram of IQ: $\mu={mu}$, $\sigma={sigma}$')
fig.tight_layout(pad=1.5)
fig.set_size_inches(4.7747, 3.5)
plt.savefig(sys.stdout.buffer, format='pgf')
The script has been adapted to accomodate various languages and locales. Running it outputs the plot to stdout which can be redirected to a file (here it's histogram.pgf), and included in a document like so:
\documentclass[a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage{pgf}
\begin{document}
\section{Histogram}
\begin{figure}[h]
\begin{center}
\input{histogram.pgf}
\end{center}
\caption{A PGF histogram from \texttt{matplotlib}.}
\end{figure}
\end{document}
1. Automatic rebuilding
Any modifications to the script require a manual rebuild of the plot, which is not ideal when done frequently. We can utilize the pdffilemoddate and write18 primitives to create a very basic Makefile-style dependency system from within LaTeX, which (prior to \inputing a file) rebuilds it if its source is newer:
\newcommand{\includepyplot}[1]{%
\ifnum\pdfstrcmp{\pdffilemoddate{#1.py}}{\pdffilemoddate{pyplot-output/#1.pgf}}>0%
\immediate\write18{%
mkdir -p $(dirname pyplot-output/#1);%
python3 #1.py > pyplot-output/#1.pgf%
}%
\fi%
\noindent\input{pyplot-output/#1.pgf}%
}
Usage:
\begin{figure}[h]
\begin{center}
\includepyplot{histogram}
\end{center}
\caption{A PGF histogram from \texttt{matplotlib}.}
\end{figure}
The condition in \includepyplot can be expanded upon to consider more files if necessary:
\newcommand{\includepyplot}[1]{%
\ifnum%
\ifnum%
\pdfstrcmp{\pdffilemoddate{#1.py}}{\pdffilemoddate{pyplot-output/#1.pgf}}>0%
1%
\else%
\ifnum%
\pdfstrcmp{\pdffilemoddate{utils.py}}{\pdffilemoddate{pyplot-output/#1.pgf}}>0%
1%
\else%
0%
\fi%
\fi=1%
\immediate\write18{%
mkdir -p $(dirname pyplot-output/#1);%
python3 #1.py > pyplot-output/#1.pgf%
}%
\fi%
\noindent\input{pyplot-output/#1.pgf}%
}