Skip to content

Commit d56eae6

Browse files
committed
Add matplotlib pgf example
1 parent 1044b57 commit d56eae6

File tree

9 files changed

+231
-0
lines changed

9 files changed

+231
-0
lines changed

matplotlib_pgf/Makefile

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# * We use the modern lualatex engine which allows choosing opentype system fonts
2+
# * All LaTeX output will go to the `build` directory which is gitignored
3+
# * We stop at the first error
4+
# * We don't allow LaTeX to prompt us, Makefiles should be noninteractive
5+
texopts = --lualatex \
6+
--output-directory=build \
7+
--halt-on-error \
8+
--interaction=nonstopmode
9+
10+
11+
all: build/proceeding.pdf
12+
13+
14+
# latexmk is an awesome tool, that automagically
15+
# determines, which files have changed and which
16+
# programs need to be run on the inputfiles
17+
# latexmk does its own dependency management, so we FORCE it to always run
18+
# by using this pseudo target
19+
build/proceeding.pdf: FORCE build/plot.pdf
20+
latexmk $(texopts) proceeding.tex
21+
22+
build/plot.pdf: matplotlibrc matplotlib_header.tex settings.tex plot.py | build
23+
# matplotlib runs latex in /tmp, so we need to add the
24+
# current working directory to the TEXINPUTS, so LaTeX can find
25+
# our header file
26+
TEXINPUTS=$(shell pwd): python plot.py
27+
28+
build:
29+
mkdir -p build
30+
31+
clean:
32+
rm -rf build
33+
34+
FORCE:
35+
36+
.PHONY: clean all FORCE

matplotlib_pgf/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Using the system LaTeX installation with matplotlib
2+
3+
We use the pgf backend of matplotlib to create publication quality pdf
4+
plots.
5+
6+
The example uses the modern `lualatex` engine, so you'll need a relatively
7+
recent `TeXLive`, everything >= 2016 should work.
8+
9+
The method itself also supports `pdflatex` and `xelatex`.
10+
11+
For more information see:
12+
13+
* https://matplotlib.org/users/pgf.html
14+
* https://matplotlib.org/users/customizing.html

matplotlib_pgf/before.pdf

21 KB
Binary file not shown.

matplotlib_pgf/matplotlib_header.tex

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
% In this file, we only use the packages that
2+
% have an influence on our plot appearance, like math packages
3+
% and font settings
4+
\usepackage{fontspec}
5+
\usepackage{polyglossia}
6+
7+
\usepackage{amsmath}
8+
\usepackage{mathtools}
9+
10+
\usepackage[per-mode=reciprocal]{siunitx}
11+
12+
\usepackage[
13+
math-style=ISO,
14+
bold-style=ISO,
15+
nabla=upright,
16+
partial=upright,
17+
mathrm=sym,
18+
]{unicode-math}
19+
20+
\input{settings.tex}

matplotlib_pgf/matplotlibrc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
backend: pgf # use system latex and the pgf graphics package
2+
figure.figsize: 5.781, 3.573 # size in inch
3+
4+
text.usetex: true
5+
pgf.rcfonts: false # set fonts in matplotlib_header.tex, not here
6+
pgf.texsystem: lualatex # also supported: pdflatex, xelatex
7+
pgf.preamble: \input{matplotlib_header.tex} # just input the actual header
8+
9+
font.size: 11
10+
legend.fontsize: 11
11+
xtick.labelsize: 9
12+
ytick.labelsize: 9
13+
font.family: serif

matplotlib_pgf/plot.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import matplotlib.pyplot as plt
2+
import numpy as np
3+
4+
5+
formula = (
6+
r'$\displaystyle '
7+
r'N = \int_{E_\text{min}}^{E_\text{max}} '
8+
r'\int_0^A'
9+
r'\int_{t_\text{min}}^{t_\text{max}} '
10+
r'Φ_0 \left(\frac{E}{\SI{1}{\GeV}}\right)^{\!\!-γ}'
11+
r' \, \symup{d}A \, \symup{d}t \, \symup{d}E'
12+
r'$'
13+
)
14+
15+
16+
def power_law_spectrum(energy, normalisation, spectral_index):
17+
return normalisation * energy**(-spectral_index)
18+
19+
20+
bin_edges = np.logspace(2, 5, 15)
21+
bin_centers = 0.5 * (bin_edges[:-1] + bin_edges[1:])
22+
23+
y = power_law_spectrum(bin_centers, 1e-5, 2.5)
24+
relative_error = np.random.normal(1, 0.2, size=len(y))
25+
y_with_err = relative_error * y
26+
27+
plt.errorbar(
28+
np.log10(bin_centers),
29+
y_with_err,
30+
xerr=[
31+
np.log10(bin_centers) - np.log10(bin_edges[:-1]),
32+
np.log10(bin_edges[1:]) - np.log10(bin_centers)
33+
],
34+
yerr=0.5 * y_with_err,
35+
linestyle='',
36+
)
37+
38+
plt.xlabel(r'$\log_{10}\bigl(E \mathbin{/} \si{\giga\electronvolt}\bigr)$')
39+
plt.ylabel(
40+
r'$\Phi_0'
41+
r'\mathbin{/}'
42+
r'\bigl(\si{\per\GeV\per\second\per\steradian\per\meter\squared}\bigr)$'
43+
)
44+
45+
plt.text(0.1, 0.1, formula, transform=plt.gca().transAxes)
46+
plt.yscale('log')
47+
48+
plt.tight_layout(pad=0)
49+
plt.savefig('build/plot.pdf')

matplotlib_pgf/plot_before.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import matplotlib.pyplot as plt
2+
import numpy as np
3+
4+
5+
formula = (
6+
r'$'
7+
r'N = \int_{E_\mathrm{min}}^{E_\mathrm{max}} '
8+
r'\int_0^A'
9+
r'\int_{t_\mathrm{min}}^{t_\mathrm{max}} '
10+
r'\Phi_0 \left(\frac{E}{1\,\mathrm{GeV}}\right)^{\!\!-\gamma}'
11+
r' \, \mathrm{d}A \, \mathrm{d}t \, \mathrm{d}E'
12+
r'$'
13+
)
14+
15+
16+
def power_law_spectrum(energy, normalisation, spectral_index):
17+
return normalisation * energy**(-spectral_index)
18+
19+
20+
bin_edges = np.logspace(2, 5, 15)
21+
bin_centers = 0.5 * (bin_edges[:-1] + bin_edges[1:])
22+
23+
y = power_law_spectrum(bin_centers, 1e-5, 2.5)
24+
relative_error = np.random.normal(1, 0.2, size=len(y))
25+
y_with_err = relative_error * y
26+
27+
plt.errorbar(
28+
np.log10(bin_centers),
29+
y_with_err,
30+
xerr=[
31+
np.log10(bin_centers) - np.log10(bin_edges[:-1]),
32+
np.log10(bin_edges[1:]) - np.log10(bin_centers)
33+
],
34+
yerr=0.5 * y_with_err,
35+
linestyle='',
36+
)
37+
38+
plt.xlabel(r'$\log_{10}(E \,\,/ \,\, \mathrm{GeV})$')
39+
plt.ylabel(
40+
r'$\Phi_0'
41+
r'\,\,/\,\,'
42+
r'(\mathrm{GeV}^{-1} \, \mathrm{s}^{-1} \, \mathrm{sr}^{-1} \mathrm{m}^{-2})$'
43+
)
44+
45+
plt.text(0.1, 0.1, formula, transform=plt.gca().transAxes)
46+
plt.yscale('log')
47+
48+
plt.tight_layout(pad=0)
49+
plt.savefig('build/before.pdf')

matplotlib_pgf/proceeding.tex

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
\documentclass{scrartcl}
2+
3+
\usepackage{fontspec}
4+
5+
\usepackage{polyglossia}
6+
\setmainlanguage{english}
7+
8+
\usepackage{amsmath}
9+
\usepackage{mathtools}
10+
11+
\usepackage[per-mode=fraction]{siunitx}
12+
13+
\usepackage[
14+
math-style=ISO,
15+
bold-style=ISO,
16+
nabla=upright,
17+
partial=upright,
18+
]{unicode-math}
19+
20+
\usepackage{blindtext}
21+
\usepackage{graphicx}
22+
23+
\input{settings.tex}
24+
\recalctypearea % after changing the font, recalculate margin sizes
25+
26+
27+
\begin{document}
28+
% get LaTeX to print the textwidth to use it as plot width
29+
\section{Get the textwidth}
30+
Textwidth: \the\textwidth \\
31+
$\SI{1}{in} = \SI{72.27}{pt}$
32+
33+
\section{Awesome plot}
34+
35+
\blindtext
36+
37+
\begin{figure}[htbp]
38+
\centering
39+
% note we don't use any of width= or scale=, the plot as the correct size
40+
\includegraphics{build/plot.pdf}
41+
\caption{%
42+
Plot with same font family and size as main document
43+
}\label{fig:plot}
44+
\end{figure}
45+
46+
\blindtext
47+
48+
\end{document}

matplotlib_pgf/settings.tex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
\setromanfont{Libertinus Serif}
2+
\setmathfont{Libertinus Math}

0 commit comments

Comments
 (0)