Disclaimer: I fully understand that the use of text.latex.preamble
in rcparams is not officially supported by matploltib.
Note: the same question was posted on the matplotlib discourse "Community" page. I re-post it here to reach, hopefully, a wider "LaTeX/tikz audience".
Dear hive mind,
I need/want to use the tikz
LaTeX package to draw symbols in matplotlib plt.text()
calls. It all works smoothly (in the sense that I get no LaTeX/matplotlib errors) ... except that no symbols are actually drawn on the figures ?!
Here is a MWE:
from matplotlib import pyplot as plt
plt.style.use('./latex.mplstyle')
plt.close(1)
plt.figure(1, figsize=(4, 3))
plt.text(0.5, 0.7, r'This is regular text', ha='center', va='center')
plt.text(0.5, 0.5, r'$\rightarrow$ \begin{tikzpicture}\draw [thick] (0,0) circle [radius=2ex];\end{tikzpicture}', ha='center', va='center')
plt.savefig('test.png')
plt.show()
The content of latex.mplstyle
is:
text.usetex: True
text.latex.preamble: \usepackage{tikz}
The output looks like that:
Problem: there should be a circle to the right of the arrow.
So what could matplotlib be doing differently compared to pdflatex
that returns the following image:
when processing the following (same) LaTeX code:
\documentclass[11pt]{article}
\usepackage{tikz}
\begin{document}
$\rightarrow$ \begin{tikzpicture}\draw [thick] (0,0) circle [radius=2ex];\end{tikzpicture}
\end{document}
The tikz
package is definitely being loaded correctly, as the \tikzpicture
command does not raise any error when compiling the matplotlib figure.
Side-note 1: as far as I can tell, the same behavior implies that symbols from the tikzsymbols
LaTeX package do not appear either in plt.text()
calls.
Side-note 2: I evidently need to draw more (but not THAT much more) than a circle with tikz
... That's just the MWE!
Edit (after some digging thanks to @samcarter_is_at_topanswers.xyz suggestions)
It turns out that the .dvi
files generated by LaTeX look as expected. However, these seemingly get cropped before being ingested by the matplotlib figure. Whatever is doing this cropping does not seem aware of the tikzpicture
existence. Here's a picture with what I see in the .dvi
, on-screen, in the .png
, and in the .pdf
from matplotlib:
So the question becomes:
What mechanism is responsible for inserting the LaTeX .dvi
inside the matplotlib figure, and why isn't it aware of the \tikzpicture
existence ?
and, possibly:
Could I put the \tikzpicture
inside some sort of LaTeX bounding box to have it become visible to matplotlib ?
See this Matplotlib's discourse question for the full thread leading to the following answer
Cause:
Matplotlib requires font metrics like the baseline, ascends and descends to include text. The \tikzpicture
does not provide any, and so it is not taken into account in the crop of the dvi.
Solution/work-around:
Use the pgf
backend to export the figure to pdf
and/or png
format, i.e.: plt.savefig(..., backend='pgf')
This method can also successfully handle the inclusion of items from the tiksymbols
LaTeX package. However, it does not allow to display these elements on-screen.