2

After following the solution provided here, I see that the plot doesnt look the way I expect it to look.

The max value of z axis is no more than 5.89. Whereas, we see the Z axis to be taking the value of Z1, as far as I can see.

I am wondering where the problem could be.

import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

x = [10.0, 14.0, 18.0, 14.0, 6.0, 6.0, 2.0, 18.0, 18.0, 6.0, 18.0, 14.0, 10.0, 10.0, 6.0, 6.0, 10.0, 14.0, 2.0, 18.0, 10.0, 14.0]
y = [1.8, 1.4, 1.2, 2.0, 2.0, 1.4, 2.0, 1.8, 2.0, 1.8, 1.6, 1.8, 2.0, 1.2, 1.6, 1.2, 1.6, 1.2, 1.8, 1.4, 1.4, 1.6]
z = [1.22, 2.14, 1.66, 0.7, 2.86, 5.89, 3.85, 0.45, 0.4, 4.28, 0.6, 0.92, 0.67, 3.52, 5.25, 4.94, 1.37, 3.76, 4.75, 0.95, 1.99, 1.41]
z1 = [29.0, 26.72, 26.71, 31.33, 29.46, 24.84, 32.54, 31.43, 33.84, 28.14, 29.84, 31.34, 30.51, 25.0, 25.73, 24.06, 27.09, 26.89, 29.85, 28.93, 26.58, 27.53]


# domains
x = np.array(x)
y = np.array(y)
z = np.array(z)
z1 = np.array(z1)

# convert to 2d matrices
Z = np.outer(z.T, z)        # 50x50
Z1 = np.outer(z1.T, z1)        # 50x50
X, Y = np.meshgrid(x, y)    # 50x50

# fourth dimention - colormap
# create colormap according to x-value (can use any 50x50 array)
color_dimension = Z1 # change to desired fourth dimension
minn, maxx = color_dimension.min(), color_dimension.max()
norm = matplotlib.colors.Normalize(minn, maxx)
m = plt.cm.ScalarMappable(norm=norm, cmap='jet')
m.set_array([])
fcolors = m.to_rgba(color_dimension)

# plot
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(X,Y,Z, rstride=1, cstride=1, facecolors=fcolors, vmin=minn, vmax=maxx, shade=False)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
fig.canvas.draw()
fig.savefig('test.pdf')

enter image description here

tandem
  • 2,040
  • 4
  • 25
  • 52

1 Answers1

1

You take the outer product:

Z = np.outer(z.T, z)        # 50x50

thus the largest value in your Z-Matrix is 5.89*5.89=34.69 and your plot seems to be correct.

What you probably want is to use griddata from scipy or matplotlib method for interpolating your irregularly spaced data on a grid, see Contour plot of irregularly spaced data.

As suggested in this post, you can use griddata for the color as well. The complete example (here with interpolation from matplotlib.tri) would look like this:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.tri as tri
from matplotlib.colors import Normalize

x = [10.0, 14.0, 18.0, 14.0, 6.0, 6.0, 2.0, 18.0, 18.0, 6.0, 18.0, 14.0, 10.0, 10.0, 6.0, 6.0, 10.0, 14.0, 2.0, 18.0, 10.0, 14.0]
y = [1.8, 1.4, 1.2, 2.0, 2.0, 1.4, 2.0, 1.8, 2.0, 1.8, 1.6, 1.8, 2.0, 1.2, 1.6, 1.2, 1.6, 1.2, 1.8, 1.4, 1.4, 1.6]
z = [1.22, 2.14, 1.66, 0.7, 2.86, 5.89, 3.85, 0.45, 0.4, 4.28, 0.6, 0.92, 0.67, 3.52, 5.25, 4.94, 1.37, 3.76, 4.75, 0.95, 1.99, 1.41]
z1 = [29.0, 26.72, 26.71, 31.33, 29.46, 24.84, 32.54, 31.43, 33.84, 28.14, 29.84, 31.34, 30.51, 25.0, 25.73, 24.06, 27.09, 26.89, 29.85, 28.93, 26.58, 27.53]


# domains
x = np.array(x)
y = np.array(y)
z = np.array(z)
z1 = np.array(z1)

# Create grid values first.
ngridx = 100
ngridy = 100
xi = np.linspace(x.min(), x.max(), ngridx)
yi = np.linspace(y.min(), y.max(), ngridy)

# Perform linear interpolation of the data (x,y)
# on a grid defined by (xi,yi)
triang = tri.Triangulation(x, y)
interpolator_z = tri.LinearTriInterpolator(triang, z)
interpolator_z1 = tri.LinearTriInterpolator(triang, z1)
Xi, Yi = np.meshgrid(xi, yi)
zi = interpolator_z(Xi, Yi)
z1i = interpolator_z1(Xi, Yi)

X, Y, Z, Z1 = xi, yi, zi, z1i

fig = plt.gcf()
ax1 = fig.add_subplot(111, projection='3d')

minn, maxx = z1.min(), z1.max()
norm = Normalize()
surf = ax1.plot_surface(X,Y,Z, rstride=1, cstride=1, facecolors=cm.jet(norm(Z1)), vmin=minn, vmax=maxx, shade=False)

m = cm.ScalarMappable(cmap=cm.jet)
m.set_array(Z1)
col = plt.colorbar(m)
plt.show()

Thanks to ImportanceOfBeingErnest for pointing out that griddata from matplotlib is deprecated and providing the link to the current example.

CodeZero
  • 1,649
  • 11
  • 18
  • How we actually build it such that the Z axis takes the value of `z` instead of `max(z)*max(z)`? – tandem Oct 09 '18 at 07:29
  • Are you suggesting to use griddata instead of plot_surface? – tandem Oct 09 '18 at 07:47
  • No, instead of meshgrid and the outer product. But thats only what I assume based on the information you gave. – CodeZero Oct 09 '18 at 07:51
  • And `z1` has to defined the way I did it? – tandem Oct 09 '18 at 07:59
  • What is th meaning of z1? What do you want the plot to show? For me it looks like you have some data points, like in a scatter plot, and want to interpolate these to a surface. Thats what you do with griddata. But I don't quite understand the z1 component – CodeZero Oct 09 '18 at 08:12
  • I want to plot the data of X, Y and Z as a surface plot and use the data from Z1 to color the surface plot. – tandem Oct 09 '18 at 08:14
  • thanks for that. but i still do not see any changes in color – tandem Oct 09 '18 at 08:44
  • The Q&A you link to uses `scipy.interpolate.griddata`, which is fine. Here you use `matplotlib.mlab.griddata` which is deprecated. Also, one should probably better link to the [current version of the example](https://matplotlib.org/gallery/images_contours_and_fields/irregulardatagrid.html). – ImportanceOfBeingErnest Oct 09 '18 at 09:12