figure.Figure vs. pyplot.figure when using PGF preamble

In the documentation I found an example for a PGF preamble:

import matplotlib as mpl
mpl.use("pgf")
import matplotlib.pyplot as plt
plt.rcParams.update({
    "font.family": "serif",  # use serif/main font for text elements
    "text.usetex": True,     # use inline math for ticks
    "pgf.rcfonts": False,    # don't setup fonts from rc parameters
    "pgf.preamble": "\n".join([
         r"\usepackage{url}",            # load additional packages
         r"\usepackage{unicode-math}",   # unicode math setup
         r"\setmainfont{DejaVu Serif}",  # serif font via preamble
    ])
})

fig, ax = plt.subplots(figsize=(4.5, 2.5))

ax.plot(range(5))

ax.set_xlabel("unicode text: я, ψ, €, ü")
ax.set_ylabel(r"\url{https://matplotlib.org}")
ax.legend(["unicode math: $λ=∑_i^∞ μ_i^2$"])

fig.tight_layout(pad=.5)

fig.savefig("pgf_preamble.pdf")
fig.savefig("pgf_preamble.png")

I noticed that this does not work if I replace the line

fig, ax = plt.subplots(figsize=(4.5, 2.5))

with

from matplotlib.figure import Figure                                                                            
fig = Figure(figsize=(4.5, 2.5))                                                
ax = fig.add_subplot()

and I don’t understand why this happens. What does work is if I only output a pgf file instead of a png and a pdf file but only if I comment out this line:

fig.tight_layout(pad=.5)

Can anyone tell me what is happening here?

This is because at the moment where tight_layout is called, the figure doesn’t know yet which backend will be used (standalone Figures created without pyplot intentionally don’t read the global backend setting), and for the better or the worse, defaults to agg, which cannot handle the unicode input.

To work around this, you can instead pass tight_layout={"pad": 0.5} to the Figure constructor (so that tight layout gets applied at draw (=saving) time, but not earlier) and explicitly pass backend="pgf" to the savefig calls.

1 Like

Thank you for your quick reply and the great answers! Now it is all clear to me.