13

Summary

I am exporting matplotlib figures as PGF to use in LaTeX.

matplotlib seems to add a \sffamily addition to every text entry (axes labels, ticks, legend entries, annotations) when saving the figure as a PGF. This will stop it from properly inheriting the font from the global document font.

The text can inheret the font from the global document font if it is from the same family, but it will revert to the default sffamily font if the global font is from a different family.

Where I got to

I believe I have isolated the problem: if I edit the PGF document and simply remove the \sffamily part of any text entry, the problem no longer persists and the global font is inherited. The deletion doesn't prevent LaTeX from compiling it properly, and I get no errors.

Because of the above finding, I believe the problem has nothing to do with rcParams or any LaTeX preamble (both in python or in the actual LaTeX document).

MWE

I just tried it on the simplest possible plot and was able to reproduce the problem:

import matplotlib.pyplot as plt

fig = plt.figure()
plt.xlabel('a label')
fig.savefig('fig.pgf')

And pgf document will contain the following line:

\pgftext[x=3.280000in,y=0.240809in,,top]{\color{textcolor}\sffamily\fontsize{10.000000}{12.000000}\selectfont a label}%

so the \sffamily is added. Rendering this in LaTeX will force a sans-serif font. Removing the \sffamily and rendering it will allow it to inherit the font family.

TLDR

Is there a way to avoid the inclusion of a font family in the PGF output of matplotlib?

Community
  • 1
  • 1
krg
  • 317
  • 3
  • 11

3 Answers3

4

I cannot offer a solution but a workaround building on @samcarter's comment: You can redefine \sffamily locally, e.g.:

\documentclass{article}

\usepackage{pgf}
\usepackage{fontspec}
\setmainfont{DejaVu Serif}
\setsansfont{DejaVu Sans}
\setmonofont{DejaVu Sans Mono}

\begin{document}
Lorem ipsum {\sffamily Lorem ipsum}
\begin{center}
    \renewcommand\sffamily{}
    \input{fig.pgf}
\end{center}
Lorem ipsum {\sffamily Lorem ipsum}
\end{document}

Instead of center you can use any environment or \begingroup and \endgroup.

Ralf Stubner
  • 26,263
  • 3
  • 40
  • 75
2

Building on https://matplotlib.org/users/pgf.html#font-specification you could use:

import matplotlib as mpl
import matplotlib.pyplot as plt

pgf_with_rc_fonts = {
    "font.family": "serif",
}
mpl.rcParams.update(pgf_with_rc_fonts)


fig = plt.figure()
plt.xlabel('a label')
fig.savefig('fig.pgf')

This way \rmfamily is used instead of \sffamily.

Ralf Stubner
  • 26,263
  • 3
  • 40
  • 75
  • Well the idea is to not specify the font family at all in the PGF file, so that if I change in the LaTeX file the figure's font would change as well. – krg May 24 '19 at 09:58
  • @krg From the linked doc: "If the font configuration used by matplotlib differs from the font setting in yout LaTeX document, the alignment of text elements in imported figures may be off. Check the header of your .pgf file if you are unsure about the fonts matplotlib used for the layout." So `mathplotlib` needs to know which fonts you are using. – Ralf Stubner May 24 '19 at 10:02
  • Indeed, `matplotlib` needs a font, and if I try to remove the font specification it will revert to the default of DejaVu (as specified by `rcParamsDefault`). So I understand why a font specification is required for `matplotlib` but it's annoying that it forces it onto the pgf document. Your other answer deals with the problem nicely though. – krg May 24 '19 at 10:11
2

There is another workaround by replacing the font specification with sed before importing the pgf file in your tex-document.

\documentclass{article}
\usepackage{pgf}
\usepackage{pgfplots}
\pgfplotsset{compat=1.8}
\usepackage{filecontents}

\begin{document}
\begin{figure}
    \begin{filecontents*}{tmpfile.sed}
# sed command file
s/\\color{textcolor}\\sffamily\\fontsize{.*}{.*}\\selectfont //\end{filecontents*}
    \immediate\write18{sed -i -f tmpfile.sed yourplot.pgf}
    \import{yourplot.pgf}
\end{figure}
\end{document}
mailx
  • 21
  • 2