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}%
}

2. Full example