Surface plotting using PyPlot

Hi,

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 :slight_smile:

Thanks in advance.

Please give a MWE that is copy-pastable and tell us what you have tried so far that doesn’t work.

1 Like

something like this perhaps

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)

Also, see Plots Gallery | [“Julia Plots Gallery”]

I’m not sure why you “don’t like Plots” since the following just works in Plots.jl:

julia> using Plots

julia> x = y = -1:0.1:1;
1:10

julia> z = x .^ 2 .+ y' .^ 2;

julia> surface(x, y, z)
2 Likes

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)
2 Likes

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.

A recent discussion on why one doesn’t need meshgrid in Julia is at Meshgrid function in Julia

1 Like

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.

@Yuktee_Gupta, have you checked this post?

1 Like

Welcome to the Julia Discourse!

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.