I’d like to generate a 3D line plot using data in three vectors labelled x
, y
and z
. I’ve tried using PyPlot’s plot3D and I received the error:
PyError ($(Expr(:escape, :(ccall(#= /home/fusion809/.julia/packages/PyCall/zqDXB/src/pyfncall.jl:43 =# @pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, pyargsptr, kw))))) <class 'ValueError'>
ValueError('input operand has more dimensions than allowed by the axis remapping')
File "/usr/lib/python3.8/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 1421, in plot
zs = np.broadcast_to(zs, len(xs))
File "<__array_function__ internals>", line 5, in broadcast_to
File "/usr/lib/python3.8/site-packages/numpy/lib/stride_tricks.py", line 182, in broadcast_to
return _broadcast_to(array, shape, subok=subok, readonly=True)
File "/usr/lib/python3.8/site-packages/numpy/lib/stride_tricks.py", line 125, in _broadcast_to
it = np.nditer(
Stacktrace:
[1] pyerr_check at /home/fusion809/.julia/packages/PyCall/zqDXB/src/exception.jl:60 [inlined]
[2] pyerr_check at /home/fusion809/.julia/packages/PyCall/zqDXB/src/exception.jl:64 [inlined]
[3] _handle_error(::String) at /home/fusion809/.julia/packages/PyCall/zqDXB/src/exception.jl:81
[4] macro expansion at /home/fusion809/.julia/packages/PyCall/zqDXB/src/exception.jl:95 [inlined]
[5] #110 at /home/fusion809/.julia/packages/PyCall/zqDXB/src/pyfncall.jl:43 [inlined]
[6] disable_sigint at ./c.jl:446 [inlined]
[7] __pycall! at /home/fusion809/.julia/packages/PyCall/zqDXB/src/pyfncall.jl:42 [inlined]
[8] _pycall!(::PyCall.PyObject, ::PyCall.PyObject, ::Tuple{Array{Float64,2},Array{Float64,2},Array{Float64,2}}, ::Int64, ::Ptr{Nothing}) at /home/fusion809/.julia/packages/PyCall/zqDXB/src/pyfncall.jl:29
[9] _pycall!(::PyCall.PyObject, ::PyCall.PyObject, ::Tuple{Array{Float64,2},Array{Float64,2},Array{Float64,2}}, ::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /home/fusion809/.julia/packages/PyCall/zqDXB/src/pyfncall.jl:11
[10] pycall(::PyCall.PyObject, ::Type{PyCall.PyAny}, ::Array{Float64,2}, ::Vararg{Array{Float64,2},N} where N; kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /home/fusion809/.julia/packages/PyCall/zqDXB/src/pyfncall.jl:83
[11] pycall(::PyCall.PyObject, ::Type{PyCall.PyAny}, ::Array{Float64,2}, ::Vararg{Array{Float64,2},N} where N) at /home/fusion809/.julia/packages/PyCall/zqDXB/src/pyfncall.jl:83
[12] plot3D(::Array{Float64,2}, ::Vararg{Array{Float64,2},N} where N; kws::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /home/fusion809/.julia/packages/PyPlot/XHEG0/src/plot3d.jl:62
[13] plot3D(::Array{Float64,2}, ::Vararg{Array{Float64,2},N} where N) at /home/fusion809/.julia/packages/PyPlot/XHEG0/src/plot3d.jl:60
[14] top-level scope at In[25]:1
and I must admit I’m a little stumped as to how I am meant to get around this error. If you need to know how x
, y
and z
were created in order to help me, here’s the Julia script I’m using to create them:
using Pkg;
# Import PyPlots
Pkg.add("PyPlot")
using PyPlot;
N = 10000;
sigma = 10.0
rho = 28.0
beta = 8.0/3.0;
t0 = 0;
tf = 100;
dt = (tf-t0)/N;
t = t0:dt:tf;
function f(beta, rho, sigma, t, x, y, z)
# The Lorenz equations
dx_dt = sigma.*(y - x);
dy_dt = -y + x.*(-z + rho);
dz_dt = - beta*z + x*y;
# Return the derivatives as a vector
return dx_dt, dy_dt, dz_dt
end;
function RK4(beta, rho, sigma, dt, t, x, y, z)
K1 = dt.*f(beta, rho, sigma, t, x, y, z);
k1 = K1[1];
l1 = K1[2];
m1 = K1[3];
K2 = dt.*f(beta, rho, sigma, t + dt/2, x + k1/2, y + l1/2, z + m1/2);
k2 = K2[1];
l2 = K2[2];
m2 = K2[3];
K3 = dt.*f(beta, rho, sigma, t + dt/2, x + k2/2, y + l2/2, z + m2/2);
k3 = K3[1];
l3 = K3[2];
m3 = K3[3];
K4 = dt.*f(beta, rho, sigma, t + dt/2, x + k3, y + l3, z + m3);
k4 = K4[1];
l4 = K4[2];
m4 = K4[3];
dx = 1/6 * (k1 + 2*k2 + 2*k3 + k4);
dy = 1/6 * (l1 + 2*l2 + 2*l3 + l4);
dz = 1/6 * (m1 + 2*m2 + 2*m3 + m4);
return dx, dy, dz
end
x = zeros(N+1,1);
x[1] = -2.0;
y = zeros(N+1,1);
y[1] = 3.0;
z = zeros(N+1,1);
z[1] = 0.5;
for i=1:N
diff = RK4(beta, rho, sigma, dt, t[i], x[i], y[i], z[i]);
x[i+1] = x[i] + diff[1];
y[i+1] = y[i] + diff[2];
z[i+1] = z[i] + diff[3];
end
PyPlot.figure(1)
PyPlot.plot3D(x, y, z);
PyPlot.xlabel("x")
PyPlot.ylabel("y")
PyPlot.zlabel("z")
From what little I gathered from the error it seems like my x, y and z are of the wrong type for this plotting function but I have no idea how I’m meant to correct this. I have tried adding the lines:
convert(Array{Float64,1}, x)
convert(Array{Float64,1}, y)
convert(Array{Float64,1}, z)
before I called the plotting function, based on this answer on StackOverflow and the fact that another script of mine who’s x, y, and z are of the Array{Float64,1} type runs plot3D without a problem, but I just received the error:
MethodError: no method matching Array{Float64,1}(::Array{Float64,2})
Closest candidates are:
Array{Float64,1}(::AbstractArray{S,N}) where {T, N, S} at array.jl:541
Array{Float64,1}() where T at boot.jl:424
Array{Float64,1}(!Matched::UndefInitializer, !Matched::Int64) where T at boot.jl:405
...
Stacktrace:
[1] convert(::Type{Array{Float64,1}}, ::Array{Float64,2}) at ./array.jl:533
[2] top-level scope at /data/GitHub/mine/maths/julia-scripts/Chaos/Lorenz/RK4.jl:65
[3] top-level scope at In[33]:1
which suggests to me that this bit of code on StackOverflow is likely invalid for my usecase.
Thanks for your time.