Closed PaulSoderlind closed 2 years ago
I am not a Python expert, but this seems to work with PyCall:
using PyCall
plt = pyimport("matplotlib.pyplot")
plt.figure()
ax = plt.axes(projection="3d")
ax.plot_surface(xb, yb, z)
plt.show()
where xb
and yb
are expanded versions versions of x,y
with the same shapes as z
.
Notice the ax = plt.axes(projection="3d")
For me, this also ends up in not being able to perform 3d plots at all:
using Pyplot
x = range(0,2,length=100)'
y = range(0,4,length=200)
z = @. sin(x) * cos(y)
plot_surface(x,y,z)
yields
sys:1: MatplotlibDeprecationWarning: Calling gca() with keyword arguments was deprecated in Matplotlib 3.4. Starting two minor releases later, gca() will take no keyword arguments. The gca() function should only be used to get the current axes, or if no axes exist, create new axes with default keyword arguments. To create a new axes with non-default arguments, use plt.axes() or plt.subplot().
ERROR: KeyError: key "plot_surface" not found
Stacktrace:
[1] __getproperty
@ ~/.julia/packages/PyCall/tqyST/src/PyCall.jl:307 [inlined]
[2] getproperty(o::PyCall.PyObject, s::String)
@ PyCall ~/.julia/packages/PyCall/tqyST/src/PyCall.jl:311
[3] plot_surface(::Matrix{Float64}, ::Vararg{Matrix{Float64}, N} where N; kws::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ PyPlot ~/.julia/packages/PyPlot/XHEG0/src/plot3d.jl:62
[4] plot_surface
@ ~/.julia/packages/PyPlot/XHEG0/src/plot3d.jl:60 [inlined]
[5] #plot_surface#198
@ ~/.julia/packages/PyPlot/XHEG0/src/PyPlot.jl:253 [inlined]
[6] plot_surface(::LinearAlgebra.Adjoint{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}, ::StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, ::Matrix{Float64})
@ PyPlot ~/.julia/packages/PyPlot/XHEG0/src/PyPlot.jl:249
[7] top-level scope
@ REPL[7]:1
julia> versioninfo()
Julia Version 1.6.2
Commit 1b93d53fc4 (2021-07-14 15:36 UTC)
Platform Info:
OS: Linux (x86_64-pc-linux-gnu)
CPU: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-11.0.1 (ORCJIT, skylake)
(@v1.6) pkg> status
Status `~/.julia/environments/v1.6/Project.toml`
[22c333fb] BracedErrors v0.6.0
[a93c6f00] DataFrames v1.1.1
[f6369f11] ForwardDiff v0.10.17
[28b8d3ca] GR v0.55.0
[d8418881] Intervals v1.5.0
[033835bb] JLD2 v0.4.13
[5d8bcb5e] Julog v0.1.10
[2fda8390] LsqFit v0.12.1
[5fb14364] OhMyREPL v0.5.10
[91a5bcdd] Plots v1.11.0
I have created a Pull Request with this very small change: https://github.com/JuliaPy/PyPlot.jl/pull/533
I now believe that PR https://github.com/JuliaPy/PyPlot.jl/pull/533 has negative side effects: it overwrites subplots.
Simple example:
x = -10:10
y = -11:11
z = x.^2 .+ y'.^2
using3D()
fig1 = figure(figsize=(14,14/1.5))
subplot(221,projection="3d")
surf(x, y, z')
subplot(222,projection="3d")
surf(x, y, -z')
This will only show the 2nd subplot (and it looks centered).
I guess the cause is: the new code uses plt."subplot"(projection="3d")
and thus drops the information on nrows, ncols, index
. Motivation: using PyCall
and things like ax = plt.subplot(2,2,2,projection="3d"); ax.plot_surface(xb, yb, -z)
works well.
Would it fix the problem to use plt."axes"(projection=3d)
instead of subplot
?
Would it fix the problem to use
plt."axes"(projection=3d)
instead ofsubplot
?
I changed lines 61 and 77 in plot3d.jl and tried. The result is that the early subfigures are displayed in the background (sort of broken up in pieces) and the last subplot is overlayed.
For reference, here is how gca
worked in Matplotlib 3.1: https://github.com/matplotlib/matplotlib/blob/782f6ef56acca21a4e1057ef3e9aecf5e22e88a2/lib/matplotlib/figure.py#L1889-L1932
We may have to implement something similar?
We may have to implement something similar?
Edited: Yes, I would now guess so.
Coming back to this (after a teaching period), I might suggest something simpler: change to
ax = PyPlot.version <= v"3.4" ? gca(projection="3d") : gca()
and leave it to the user to specify the projection="3d"
as in
x = collect(-10:10)
y = collect(-11:11)
z = x.^2 .+ y'.^2
figure()
ax = PyPlot.axes(projection="3d")
surf(x, y, z')
#using3D() #does not seem to be needed
figure()
subplot(221,projection="3d")
surf(x, y, z')
subplot(222,projection="3d")
surf(x, y, -z')
title("just surf")
gives the following warning message with PyPlot/matplotlib 3.4.2:
The following is a MWE:
and things like that show up on eg. line 61 of plot3d.jl