JuliaPy / PyPlot.jl

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

PyPlot should not depend on matplotlib.gif #344

Closed mvhulten closed 6 years ago

mvhulten commented 6 years ago

I installed the latest PyPlot in Julia 0.6.2. Then I found out that I needed matplotlib, which is quite obvious. So I installed python3-matplotlib 2.0.0 (Ubuntu 16.04). Plotting something resulted in a PyError:

julia> x = linspace(0,2*pi,1000); y = sin.(3 * x + 4 * cos.(2 * x));

julia> plot(x, y, color="red", linewidth=2.0, linestyle="--")
ERROR: PyError (ccall(@pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, arg, kw)) <class '_tkinter.TclError'>
TclError('couldn\'t open "/usr/share/matplotlib/mpl-data/images/matplotlib.gif": no such file or directory',)
  File "/usr/lib/python2.7/dist-packages/matplotlib/pyplot.py", line 3147, in plot
    ax = gca()
  File "/usr/lib/python2.7/dist-packages/matplotlib/pyplot.py", line 928, in gca
    return gcf().gca(**kwargs)
  File "/usr/lib/python2.7/dist-packages/matplotlib/pyplot.py", line 578, in gcf
    return figure()
  File "/usr/lib/python2.7/dist-packages/matplotlib/pyplot.py", line 527, in figure
    **kwargs)
  File "/usr/lib/python2.7/dist-packages/matplotlib/backends/backend_tkagg.py", line 84, in new_figure_manager
    return new_figure_manager_given_figure(num, figure)
  File "/usr/lib/python2.7/dist-packages/matplotlib/backends/backend_tkagg.py", line 101, in new_figure_manager_given_figure
    icon_img = Tk.PhotoImage(file=icon_fname)
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 3370, in __init__
    Image.__init__(self, 'photo', name, cnf, master, **kw)
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 3324, in __init__
    self.tk.call(('image', 'create', imgtype, name,) + options)

Stacktrace:
 [1] pyerr_check at /home/mhu027/.julia/v0.6/PyCall/src/exception.jl:56 [inlined]
 [2] pyerr_check at /home/mhu027/.julia/v0.6/PyCall/src/exception.jl:61 [inlined]
 [3] macro expansion at /home/mhu027/.julia/v0.6/PyCall/src/exception.jl:81 [inlined]
 [4] #_pycall#67(::Array{Any,1}, ::Function, ::PyCall.PyObject, ::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::Vararg{Any,N} where N) at /home/mhu027/.julia/v0.6/PyCall/src/PyCall.jl:658
 [5] (::PyCall.#kw##_pycall)(::Array{Any,1}, ::PyCall.#_pycall, ::PyCall.PyObject, ::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::Vararg{Any,N} where N) at ./<missing>:0
 [6] #pycall#71(::Array{Any,1}, ::Function, ::PyCall.PyObject, ::Type{PyCall.PyAny}, ::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::Vararg{Any,N} where N) at /home/mhu027/.julia/v0.6/PyCall/src/PyCall.jl:675
 [7] (::PyCall.#kw##pycall)(::Array{Any,1}, ::PyCall.#pycall, ::PyCall.PyObject, ::Type{PyCall.PyAny}, ::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::Vararg{Any,N} where N) at ./<missing>:0
 [8] #plot#85(::Array{Any,1}, ::Function, ::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::Vararg{Any,N} where N) at /home/mhu027/.julia/v0.6/PyPlot/src/PyPlot.jl:172
 [9] (::PyPlot.#kw##plot)(::Array{Any,1}, ::PyPlot.#plot, ::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::Vararg{Any,N} where N) at ./<missing>:0

There is no gif file, only /usr/share/matplotlib/mpl-data/images/matplotlib.{pdf,png,ppm,svg}. I realise that this is not a standard installation method for a functioning PyPlot. However, — and this is a quite open question as I don't know how the binding between Python and Julia is done — is it the PyPlot.jl package or Python/matplotlib who is asking for matplotlib.gif? If it is the former, is this part of the glue code and should this actually look for such a file? If it is the latter, it would be a matplotlib bug. I tried to test the latter but that resulted in issues, and I was not really planning running Python with matplotlib.

After a Pkg.update() and restarting Julia, I tried again:

julia> using PyPlot
INFO: Recompiling stale cache file /home/mhu027/.julia/lib/v0.6/URIParser.ji for module URIParser.
INFO: Recompiling stale cache file /home/mhu027/.julia/lib/v0.6/PyPlot.ji for module PyPlot.

Bad key "patch.force_edgecolor" on line 33 in
/usr/share/matplotlib/mpl-data/stylelib/classic.mplstyle.
You probably need to get an updated matplotlibrc file from
http://github.com/matplotlib/matplotlib/blob/master/matplotlibrc.template
or from the matplotlib source distribution
...

The, after removing python3-matplotlib from Ubuntu, and executing

ENV["PYTHON"]=""
Pkg.build("PyCall")

according to the README.md, it still looks for files in /usr/lib/python2.7/dist-packages/matplotlib/. Strangely, the path still exists after removing python3-matplotlib, and also /usr/share/matplotlib/ exists. These are directories only root can write to (and should write to only through the system distributions package manager, dpkg in my case).

stevengj commented 6 years ago

PyPlot.jl package or Python/matplotlib who is asking for matplotlib.gif?

It's clearly the latter, from the traceback. Could it be a problem in your distro packaging?

Try it from Python. Make sure you are using the same backend (PyPlot.backend, probably tkagg) by setting the MPLBACKEND environment variable before running python.

See also e.g. matplotlib/matplotlib#5388