Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 20009ae

Browse files
committed
Use luatex in --luaonly mode to query kpsewhich.
`luatex --luaonly` runs a *lua* interpreter with relevant tex libraries available, which avoids the overhead of repeatedly initializing kpathsea (the old approach, very slow on macos and windows). An alternative approach would be to use `luatex` followed by `\directlua` calls, but on windows it appears that one needs to use `lualatex` to get a working interactive prompt, and just loading the latex format takes seconds(!). For the simple following benchmark: ```sh python -c 'from pylab import *; mpl.use("pdf"); rcParams["text.usetex"] = True; plot(); savefig("test.pdf", backend="pdf")' ``` On a macos machine, this patch brings runtime from ~4.5s to ~2.5s. On a windows machine, this patch brings runtime from ~6.5s to ~1.7s. We also need to figure out how to best advertise this (do we emit a warning suggesting to install luatex on windows and macos if luatex is not present?).
1 parent 78e3b5f commit 20009ae

File tree

5 files changed

+69
-19
lines changed

5 files changed

+69
-19
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
The *format* parameter of ``dviread.find_tex_file``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
... is deprecated (with no replacement).

lib/matplotlib/dviread.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from pathlib import Path
2626
import re
2727
import struct
28+
import subprocess
2829
import sys
2930
import textwrap
3031

@@ -970,7 +971,30 @@ def _parse_enc(path):
970971
"Failed to parse {} as Postscript encoding".format(path))
971972

972973

974+
class _LuatexKpsewhich:
975+
@lru_cache() # A singleton.
976+
def __new__(cls):
977+
self = object.__new__(cls)
978+
self._proc = self._new_proc()
979+
return self
980+
981+
def _new_proc(self):
982+
return subprocess.Popen(
983+
["luatex", "--luaonly",
984+
str(cbook._get_data_path("kpsewhich.lua"))],
985+
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
986+
987+
def search(self, filename):
988+
if self._proc.poll() is not None: # Dead, restart it.
989+
self._proc = self._new_proc()
990+
self._proc.stdin.write(os.fsencode(filename) + b"\n")
991+
self._proc.stdin.flush()
992+
out = self._proc.stdout.readline().rstrip()
993+
return "" if out == b"nil" else os.fsdecode(out)
994+
995+
973996
@lru_cache()
997+
@_api.delete_parameter("3.5", "format")
974998
def find_tex_file(filename, format=None):
975999
"""
9761000
Find a file in the texmf tree.
@@ -988,6 +1012,7 @@ def find_tex_file(filename, format=None):
9881012
format : str or bytes
9891013
Used as the value of the ``--format`` option to :program:`kpsewhich`.
9901014
Could be e.g. 'tfm' or 'vf' to limit the search to that type of files.
1015+
Deprecated.
9911016
9921017
References
9931018
----------
@@ -1002,6 +1027,14 @@ def find_tex_file(filename, format=None):
10021027
if isinstance(format, bytes):
10031028
format = format.decode('utf-8', errors='replace')
10041029

1030+
if format is None:
1031+
try:
1032+
lk = _LuatexKpsewhich()
1033+
except FileNotFoundError:
1034+
pass # Fallback to directly calling kpsewhich, as below.
1035+
else:
1036+
return lk.search(filename)
1037+
10051038
if os.name == 'nt':
10061039
# On Windows only, kpathsea can use utf-8 for cmd args and output.
10071040
# The `command_line_encoding` environment variable is set to force it

lib/matplotlib/mpl-data/kpsewhich.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-- see dviread._LuatexKpsewhich
2+
kpse.set_program_name("tex")
3+
while true do print(kpse.lookup(io.read():gsub("\r", ""))); io.flush(); end

lib/matplotlib/texmanager.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
r"""
2-
Support for embedded TeX expressions in Matplotlib via dvipng and dvips for the
3-
raster and PostScript backends. The tex and dvipng/dvips information is cached
4-
in ~/.matplotlib/tex.cache for reuse between sessions.
2+
Support for embedded TeX expressions in Matplotlib.
53
64
Requirements:
75
8-
* LaTeX
9-
* \*Agg backends: dvipng>=1.6
10-
* PS backend: psfrag, dvips, and Ghostscript>=9.0
11-
12-
For raster output, you can get RGBA numpy arrays from TeX expressions
13-
as follows::
14-
15-
texmanager = TexManager()
16-
s = "\TeX\ is Number $\displaystyle\sum_{n=1}^\infty\frac{-e^{i\pi}}{2^n}$!"
17-
Z = texmanager.get_rgba(s, fontsize=12, dpi=80, rgb=(1, 0, 0))
6+
* LaTeX.
7+
* \*Agg backends: dvipng>=1.6.
8+
* PS backend: PSfrag, dvips, and Ghostscript>=9.0.
9+
* PDF and SVG backends: if LuaTeX is present, it will be used to speed up some
10+
post-processing steps, but note that it is not used to parse the TeX string
11+
itself (only LaTeX is supported).
1812
1913
To enable TeX rendering of all text in your Matplotlib figure, set
2014
:rc:`text.usetex` to True.
15+
16+
TeX and dvipng/dvips processing results are cached
17+
in ~/.matplotlib/tex.cache for reuse between sessions.
18+
19+
`TexManager.get_rgba` can also be used to directly obtain raster output as RGBA
20+
numpy arrays.
2121
"""
2222

2323
import functools
@@ -274,7 +274,15 @@ def get_grey(self, tex, fontsize=None, dpi=None):
274274
return alpha
275275

276276
def get_rgba(self, tex, fontsize=None, dpi=None, rgb=(0, 0, 0)):
277-
"""Return latex's rendering of the tex string as an rgba array."""
277+
r"""
278+
Return latex's rendering of the tex string as an rgba array.
279+
280+
Examples
281+
--------
282+
>>> texmanager = TexManager()
283+
>>> s = r"\TeX\ is $\displaystyle\sum_n\frac{-e^{i\pi}}{2^n}$!"
284+
>>> Z = texmanager.get_rgba(s, fontsize=12, dpi=80, rgb=(1, 0, 0))
285+
"""
278286
alpha = self.get_grey(tex, fontsize, dpi)
279287
rgba = np.empty((*alpha.shape, 4))
280288
rgba[..., :3] = mpl.colors.to_rgb(rgb)

tutorials/text/usetex.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111
etc.) can be used. The results can be striking, especially when you take care
1212
to use the same fonts in your figures as in the main document.
1313
14-
Matplotlib's LaTeX support requires a working LaTeX_ installation. For the
15-
\*Agg backends, dvipng_ is additionally required; for the PS backend, psfrag_,
16-
dvips_ and Ghostscript_ are additionally required. The executables for these
17-
external dependencies must all be located on your :envvar:`PATH`.
14+
Matplotlib's LaTeX support requires a working LaTeX_ installation. For
15+
the \*Agg backends, dvipng_ is additionally required; for the PS backend,
16+
PSfrag_, dvips_ and Ghostscript_ are additionally required. For the PDF
17+
and SVG backends, if LuaTeX is present, it will be used to speed up some
18+
post-processing steps, but note that it is not used to parse the TeX string
19+
itself (only LaTeX is supported). The executables for these external
20+
dependencies must all be located on your :envvar:`PATH`.
1821
1922
There are a couple of options to mention, which can be changed using
2023
:doc:`rc settings </tutorials/introductory/customizing>`. Here is an example
@@ -140,6 +143,6 @@
140143
.. _LaTeX: http://www.tug.org
141144
.. _Poppler: https://poppler.freedesktop.org/
142145
.. _PSNFSS: http://www.ctan.org/tex-archive/macros/latex/required/psnfss/psnfss2e.pdf
143-
.. _psfrag: https://ctan.org/pkg/psfrag
146+
.. _PSfrag: https://ctan.org/pkg/psfrag
144147
.. _Xpdf: http://www.xpdfreader.com/
145148
"""

0 commit comments

Comments
 (0)