JuliaPy / PyPlot.jl

Plotting for Julia based on matplotlib.pyplot
https://github.com/JuliaPy/PyPlot.jl
MIT License
469 stars 85 forks source link

PGF preamble is not used #579

Open jlbosse opened 3 months ago

jlbosse commented 3 months ago

I am trying to define macros in my "pgf.preamble" so I can later change parts of the figure labels when including my figures in a LaTeX document without having to regenerate the figures. This works well in python:

import numpy as np
import matplotlib
import matplotlib.pyplot as plt

matplotlib.use("pgf")

plt.rcParams.update({
    "text.usetex": True,
    "pgf.preamble": "\n".join([
        r"\newcommand{\cmd}{t_a}",
    ])
})

x = np.linspace(0, 10, 100)
y = np.sin(x)

fig, ax = plt.subplots()
ax.plot(x, y, label=r"$\sin(x)$")
ax.legend()
ax.set_ylabel(L"$\cmd$")
fig.savefig("test.pdf")

runs and correctly puts $t_a$ into the y-label of the output PDF. In julia on the other hand:

using PyPlot

PyPlot.matplotlib.use("pgf")
rcParams = PyPlot.PyDict(PyPlot.matplotlib."rcParams")
rcParams["pgf.preamble"] = [
                            raw"\newcommand{\cmd}{t_a}"
                            ]
rcParams["text.usetex"] = true
x = 0:0.1:10
y = sin.(x)
fig, ax = PyPlot.subplots()
ax.plot(x, y, label=L"$\sin(x)$")
ax.legend()
ax.set_ylabel(L"$\cmd$")
fig.savefig("test.pdf")

fails in the last line with

ERROR: PyError ($(Expr(:escape, :(ccall(#= /home/yc20910/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:43 =# @pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, pyargsptr, kw))))) <class 'ValueError'>
ValueError("Error measuring '\\\\sffamily\\\\fontsize{10.000000}{12.000000}\\\\selectfont \\\\(\\\\displaystyle \\\\cmd\\\\)'\nLaTeX Output:\n! Undefined control sequence.\n<argument> ...00}\\selectfont \\(\\displaystyle \\cmd \n                                                  \\)\n<*> ....000000}\\selectfont \\(\\displaystyle \\cmd\\)}\n                                                  \\typeout{\\the\\wd0,\\the\\ht0...\nNo pages of output.\nTranscript written on texput.log.\n")
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/figure.py", line 3012, in savefig
    self.canvas.print_figure(fname, **kwargs)
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/backend_bases.py", line 2314, in print_figure
    result = print_method(
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/backends/backend_pgf.py", line 873, in print_pdf
    self.print_pgf(tmppath / "figure.pgf", **kwargs)
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/backends/backend_pgf.py", line 860, in print_pgf
    self._print_pgf_to_fh(file, **kwargs)
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/backend_bases.py", line 1643, in wrapper
    return func(*args, **kwargs)
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/backends/backend_pgf.py", line 845, in _print_pgf_to_fh
    self.figure.draw(renderer)
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/artist.py", line 73, in draw_wrapper
    result = draw(artist, renderer, *args, **kwargs)
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/artist.py", line 50, in draw_wrapper
    return draw(artist, renderer)
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/figure.py", line 2803, in draw
    mimage._draw_list_compositing_images(
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/image.py", line 132, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/artist.py", line 50, in draw_wrapper
    return draw(artist, renderer)
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/axes/_base.py", line 3082, in draw
    mimage._draw_list_compositing_images(
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/image.py", line 132, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/artist.py", line 50, in draw_wrapper
    return draw(artist, renderer)
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/axis.py", line 1172, in draw
    self.label.draw(renderer)
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/artist.py", line 50, in draw_wrapper
    return draw(artist, renderer)
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/text.py", line 685, in draw
    bbox, info, descent = self._get_layout(renderer)
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/text.py", line 317, in _get_layout
    w, h, d = renderer.get_text_width_height_descent(
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/backends/backend_pgf.py", line 738, in get_text_width_height_descent
    w, h, d = (LatexManager._get_cached_or_new()
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/backends/backend_pgf.py", line 334, in get_width_height_descent
    return self._get_box_metrics(_escape_and_apply_props(text, prop))
  File "/home/yc20910/.local/lib/python3.8/site-packages/matplotlib/backends/backend_pgf.py", line 347, in _get_box_metrics
    raise ValueError("Error measuring {!r}\nLaTeX Output:\n{}"

Stacktrace:
  [1] pyerr_check
    @ ~/.julia/packages/PyCall/1gn3u/src/exception.jl:75 [inlined]
  [2] pyerr_check
    @ ~/.julia/packages/PyCall/1gn3u/src/exception.jl:79 [inlined]
  [3] _handle_error(msg::String)
    @ PyCall ~/.julia/packages/PyCall/1gn3u/src/exception.jl:96
  [4] macro expansion
    @ ~/.julia/packages/PyCall/1gn3u/src/exception.jl:110 [inlined]
  [5] #107
    @ ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:43 [inlined]
  [6] disable_sigint
    @ ./c.jl:473 [inlined]
  [7] __pycall!
    @ ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:42 [inlined]
  [8] _pycall!(ret::PyCall.PyObject, o::PyCall.PyObject, args::Tuple{String}, nargs::Int64, kw::Ptr{Nothing})
    @ PyCall ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:29
  [9] _pycall!
    @ ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:11 [inlined]
 [10] (::PyCall.PyObject)(args::String)
    @ PyCall ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:86
 [11] top-level scope
    @ REPL[41]:1