I want to use PyPlot (I don’t like Plots) for plotting a surface, but I seem to miss how this is done.
I have a 1D-array of x values, a 1D-array of y values, and a 2D array z of f(x,y) values. In this case length(x)=length(y) and size(z)=(length(x),length(y)).
What is the proper way to generate the 3D-plot? I can’t understand the logic of things like plot_surface(x,y,z) or plot_wireframe(x,y,z), where the help states that x,y,z must be 2D arrays… why 2D-arrays? x and y are 1D values, right?
Ok something escapes me. Nay help would be great
x = range(-3,stop=3,length=20)
y = range(1,stop=7,length=25)
z = fill(NaN,(length(x),length(y))) #to put results in, initialized as NaNs
for j = 1:length(y) #create z column by column
z[:,j] = 2*x.^2 .+ (y[j]-4)^2
end
#notice the arguments: x,y,z'
println(size(x),size(y),size(z'))
figure()
surf(x,y,z',rstride=1,cstride=1,cmap=ColorMap("cool"),alpha=0.8)
Haven’t used it in a while but indeed I kind of remember this being the case, but maybe it was changed to allow 1D arrays, e.g. on matplotlib 3.2.2 / PyPlot 2.9.0 basically the identical to the Plots code works:
julia> using PyPlot
julia> x = y = -1:0.1:1
julia> z = x .^ 2 .+ y' .^ 2
julia> plot_surface(x, y, z)
In python those functions receive 2D arrays for the coordinates (unless they have changed it in recent versions as mentioned by @marius311). This is, you specify the x and y positions for each point of the array, and not only for each row and each column. A function that is useful to build those arrays in python was called if I remember meshgrid. You can mock this function as expressed in Utilizing ndgrid/meshgrid functionality in Julia - Stack Overflow
function meshgrid(x, y)
X = [i for i in x, j in 1:length(y)]
Y = [j for i in 1:length(x), j in y]
return X, Y
end
Then you can do:
x = range(-3,stop=3,length=20)
y = range(1,stop=7,length=25)
x_grd,y_grd = meshgrid(x, y)
z = fill(NaN,(length(x),length(y))) #to put results in, initialized as NaNs
for j = 1:length(y) #create z column by column
z[:,j] = 2*x.^2 .+ (y[j]-4)^2
end
#notice the arguments: x,y,z'
println(size(x),size(y),size(z'))
figure()
surf(x_grd,y_grd,z',rstride=1,cstride=1,cmap=ColorMap("cool"),alpha=0.8)
This sometimes is a waste of memory, but it will work fine.
I seem to be having a similar problem as the OP, but I cannot figure out a solution for unequal x and y array lengths, the .^ or .* operators don’t work, or as suggested as a replacement to meshgrid, using a z = [f(xs, ys) for xs in x, ys in y] and then plotting doesn’t work either.
Please post a MWE, i.e. a Minimal Working Example (or in this case, a non-working example!) – in other words, a simple version of the data you want to plot and what exactly you tried.