meshgrid with 2d array as input - python

I have a 2D array of floats, each cell representing a magnitude at the col/row of said array and would like to create a surface plot and contour for it.
How do I use meshgrid on this 2D array?
My apologies for this simple - I am new to both Python and numpy.

Is this what you're looking for?
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
# Generate fake data
x = np.linspace(-1, 1, 500)
y = np.linspace(-1, 1, 500)
X, Y = np.meshgrid(x, y)
Z = np.exp(-(X**2 + Y**2))
fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')
ax1.plot_surface(X, Y, Z, alpha=0.05, color="w")
ax1.contour(X, Y, Z, zorder=10)
plt.show()
All these functions are described in the mplot3d tutorial

Related

Plot 3d points (x,y,z) in 2d plot with colorbar

I have computed a lot (~5000) of 3d points (x,y,z) in a quite complicated way so I have no function such that z = f(x,y). I can plot the 3d surface using
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
X = surface_points[:,0]
Y = surface_points[:,1]
Z = surface_points[:,2]
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
surf = ax.plot_trisurf(X, Y, Z, cmap=cm.coolwarm, vmin=np.nanmin(Z), vmax=np.nanmax(Z))
I would like to plot this also in 2d, with a colorbar indicating the z-value. I know there is a simple solution using ax.contour if my z is a matrix, but here I only have a vector.
Attaching the plot_trisurf result when rotated to xy-plane. This is what I what like to achieve without having to rotate a 3d plot. In this, my variable surface_points is an np.array with size 5024 x 3.
I had the same problems in one of my codes, I solved it this way:
import numpy as np
from scipy.interpolate import griddata
import matplotlib.pylab as plt
from matplotlib import cm
N = 10000
surface_points = np.random.rand(N,3)
X = surface_points[:,0]
Y = surface_points[:,1]
Z = surface_points[:,2]
nx = 10*int(np.sqrt(N))
xg = np.linspace(X.min(), X.max(), nx)
yg = np.linspace(Y.min(), Y.max(), nx)
xgrid, ygrid = np.meshgrid(xg, yg)
ctr_f = griddata((X, Y), Z, (xgrid, ygrid), method='linear')
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.contourf(xgrid, ygrid, ctr_f, cmap=cm.coolwarm)
plt.show()
You could use a scatter plot to display a projection of your z color onto the x-y axis.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
N = 10000
surface_points = np.random.rand(N,3)
X = surface_points[:,0]
Y = surface_points[:,1]
Z = surface_points[:,2]
# fig = plt.figure()
# ax = fig.add_subplot(projection='3d')
# surf = ax.plot_trisurf(X, Y, Z, cmap=cm.coolwarm, vmin=np.nanmin(Z), vmax=np.nanmax(Z))
fig = plt.figure()
cmap = cm.get_cmap('coolwarm')
color = cmap(Z)[..., :3]
plt.scatter(X,Y,c=color)
plt.show()
Since you seem to have a 3D shape that is hollow, you could split the projection into two like if you cur the shape in two pieces.
fig = plt.figure()
plt.subplot(121)
plt.scatter(X[Z<0.5],Y[Z<0.5],c=color[Z<0.5])
plt.title('down part')
plt.subplot(122)
plt.scatter(X[Z>=0.5],Y[Z>=0.5],c=color[Z>+0.5])
plt.title('top part')
plt.show()

3D plot in matplotlib using equation with x and y with Python

I'd like to create a 3D plot from an equation with x and y, similar to Google's 3D graph.
An example:
input: sin(sqrt(x**2 + y**2))
output (3D plot):
The Z will obviously be equal to the given input, but how will x and y be calculated? Thanks for any help given!
You can start by creating a meshgrid for your X and Y. Then compute your Z by doing Z=np.sin(np.sqrt(X**2 + Y**2)). Finally, you can plot the surface by using the matplotlib function ax.plot_surface(X, Y, Z).
You can find the code below:
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
N_points=100
x = np.linspace(-10, 10, N_points)
y = np.linspace(-10, 10, N_points)
X, Y = np.meshgrid(x, y)
Z=np.sin(np.sqrt(X**2 + Y**2))
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.plot_surface(X, Y, Z)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()
And the output of this code gives:

Multiple 2D contour plots in one 3D figure in python

Is there any way available in python to plot multiple 2D contour plots in one 3D plot in python. I am currently using matplotlib for contouring, but not finding any option for what I am searching for. A sample image I have added. But I want to do it on Z-axis.
You can try this.
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
fig = plt.figure()
ax = fig.gca(projection='3d')
x = np.linspace(0, 1, 100)
X, Y = np.meshgrid(x, x)
levels = np.linspace(-0.1, 0.4, 100) #(z_min,z_max,number of contour),
a=0
b=1
c=2
Z1 = a+.1*np.sin(2*X)*np.sin(4*Y)
Z2 = b+.1*np.sin(3*X)*np.sin(4*Y)
Z3 = c+.1*np.sin(4*X)*np.sin(5*Y)
plt.contourf(X, Y,Z1, levels=a+levels,cmap=plt.get_cmap('rainbow'))
plt.contourf(X, Y,Z2, levels=b+levels,cmap=plt.get_cmap('rainbow'))
plt.contourf(X, Y,Z3, levels=c+levels,cmap=plt.get_cmap('rainbow'))
ax.set_xlim3d(0, 1)
ax.set_ylim3d(0, 1)
ax.set_zlim3d(0, 2)
plt.show()
In order to plot true 2-D contour plots in one 3D plot, try this:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.gca(projection='3d')
x = np.linspace(0, 1, 100)
X, Y = np.meshgrid(x, x)
Z1 = .1*np.sin(2*X)*np.sin(4*Y)
Z2 = .1*np.sin(3*X)*np.sin(4*Y)
Z3 = .1*np.sin(4*X)*np.sin(5*Y)
levels=np.linspace(Z1.min(), Z1.max(), 100)
ax.contourf(X, Y,Z1, levels=levels, zdir='z', offset=0, cmap=plt.get_cmap('rainbow'))
levels=np.linspace(Z2.min(), Z2.max(), 100)
ax.contourf(X, Y,Z2, levels=levels, zdir='z', offset=1, cmap=plt.get_cmap('rainbow'))
levels=np.linspace(Z3.min(), Z3.max(), 100)
ax.contourf(X, Y,Z3, levels=levels, zdir='z', offset=2, cmap=plt.get_cmap('rainbow'))
ax.set_xlim3d(0, 1)
ax.set_ylim3d(0, 1)
ax.set_zlim3d(0, 2)
plt.show()
enter image description here

3D Surface Plot where z is a function that takes a vector formed from x and y

I am trying to produce a 3D surface plot where X and Y are values between -50 and 50, and Z is calculated by a function depending on X and Y.
This function takes a vector as a parameter in the form of an np array. The vector's first row is a value from X and the second a value from Y. All combinations of X and Y should produce a Z value, hence the meshgrid.
Here is my implementation, for Z I am currently creating a vector where the first row is the entire dataset of X, and the second the entire dataset of Y. This is of course incorrect.
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
import matplotlib.pyplot as plt
def myFunction(v):
return v.dot(np.array([1, 2]))
fig = plt.figure()
ax = fig.gca(projection='3d')
# Make data.
X = np.linspace(-50,50, 100)
Y = np.linspace(-50,50, 100)
X, Y = np.meshgrid(X, Y)
Z = myFunction(np.array([X, Y])) # <-- Here is the problem
# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.Greens,
linewidth=0, antialiased=False)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
I hope I have made sense,
Thanks
You would probably like to supply an array with all x values in the frst column and all y values in the second column to the function. That would ensure to have the dimensions match for the dot product. The result can then be reshaped to the shape of the mesh.
Z = myFunction(np.array([X.flatten(), Y.flatten()]).T).reshape(X.shape)
Complete example:
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
import matplotlib.pyplot as plt
def myFunction(v):
return v.dot(np.array([1, 2]))
fig = plt.figure()
ax = fig.gca(projection='3d')
# Make data.
X = np.linspace(-50,50, 100)
Y = np.linspace(-50,50, 100)
X, Y = np.meshgrid(X, Y)
Z = myFunction(np.array([X.flatten(), Y.flatten()]).T).reshape(X.shape)
# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.Greens,
linewidth=0, antialiased=False)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()

Plot NumPy ndarray into a 3D surface

I have a numpy.ndarray of size 200x200. I want to plot it as a 3D surface where x and y are indexes of the array and z is the value of that array element. Is there any easy way to do it or do I have to transform my array into a long list?
For example using matplotlib:
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
#your index
x = np.linspace(1, 200, 200);
y = np.linspace(1, 200, 200)
X, Y = np.meshgrid(x, y); #making a grid from it
fig = plt.figure()
ax = fig.gca(projection='3d')
R = np.sqrt(X**2 + Y**2) #make some calculations on the grid
Z = np.sin(R) #some more calculations
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
ax.set_zlim(-5, 5)
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
However, as your array is already quite large, you might want to consider a different plotting tool like mayavi. matplotlib usually puts a copy of your complete array into the plot. That's memory demanding when dealing with big data. But I'm not sure, whether mayavi does the same or not.
You can also use mayavi and plot your array as a plane with different colors representing the values. It would look like this:
import numpy
from mayavi import mlab
mlab.imshow(yourarray)
mlab.show()
Alternative you can create points with an elevation from the ground plane and get a fitting plane through the points. See here:http://docs.enthought.com/mayavi/mayavi/auto/example_surface_from_irregular_data.html#example-surface-from-irregular-data
What is best for you depends on the continuity of your data.
If what you want is to plot a 3D surface on top of a 2D grid what you could do is something similar to this:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
# create some fake data
array_distribution3d = np.ones((200, 200))
array_distribution3d[0:25, 0:25] = -1
# create the meshgrid to plot on
x = np.arange(0, array_distribution3d.shape[0])
y = np.arange(0, array_distribution3d.shape[1])
# here are the x,y and respective z values
X, Y = np.meshgrid(x, y)
z = []
for i in range(0, array_distribution3d.shape[0]):
z_y = []
for j in range(0, array_distribution3d.shape[1]):
z_y.append(array_distribution3d[i, j])
z.append(z_y)
Z = np.array(z)
# create the figure, add a 3d axis, set the viewing angle
fig = plt.figure(figsize=(12, 9))
ax = fig.add_subplot(111, projection='3d')
ax.view_init(45, 60)
# here we create the surface plot
ax.plot_surface(X, Y, Z)
However, to the best of my knowledge, this kind of data can be plotted as a colourmap.
This can be plotted as follows:
import numpy as np
import os.path
import matplotlib.pyplot as plt
array_distribution = np.ones((200, 200))
array_distribution[0:25, 0:25] = -1
fig = plt.imshow(array_distribution)
plt.colorbar(fraction=0.035, pad=0.035, ticks=[-1., 0., 1.])
axes = plt.gca()
axes.set_ylim([0, 200])
figure = plt.gcf()
file = os.path.join('demo1.png')
figure.savefig(file, dpi=250)
plt.close('all')
print('done')

Categories