Suppose that we want to plot an n-by-n meshgrid using Axes3d. if we have an n-by-n labeling matrix containing 0 and 1, how can we set the meshgrid pixel colors according to the labeling matrix that we have in a 3D plot?
(Edited). There is a tutorial on matplotlib: http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html. Look up plot_surface function. All you need to do is to convert your labeling mask to favorite colors. You can either do it via tuple method described in the tutorial, or through pregenerated char matrices as I've done below:
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator
import matplotlib.pyplot as plt
import numpy as np
N=10 # matrix size
c1=np.random.randint(2,size=(N,N)) # your mask of 0 and 1
c2=1-c1 # inverted mask
char1 = np.chararray((N, N))
char1[:] = 'r' # color1
char2=np.chararray((N, N))
char2[:]='b' # color2
colors=c1*char1+c2*char2 # color mask for plotting
data=np.random.rand(N,N)*5 # data you are plotting
X=linspace(-3,3,N)
Y=linspace(0,4,N)
X,Y=meshgrid(X,Y)
Z=data
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=colors,linewidth=0, antialiased=False)
plt.show()
Related
I have 4 columns and plot a 3D map with a color map using the 4th column values.
Here is my script.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
input = np.loadtxt("data.txt",delimiter=',')
x = input[:,0]
y = input[:,1]
Z = input[:,2]
V = input[:,3]
# create the figure, add a 3d axis, set the viewing angle
fig = plt.figure(figsize=(12, 9), dpi=80)
ax = fig.add_subplot(111, projection='3d')
ax.view_init(20,20)
my_cmap = plt.get_cmap('hot')
ax.plot_trisurf(x,y,, cmap = my_cmap, linewidth=0, antialiased=False)
Is it possible to convert it into a 3D meshgrid and extract 2D slices from each value of Z?
Ouput:
I'm trying to make a 3D representation of an image as a surface using wireframes with matplotlib.
ig= mpimg.imread('testIMG.png');
X = np.linspace(0,len(ig[0]),len(ig[0])); #List of discrete x values
Y = np.linspace(0,len(ig[1]),len(ig[1])); #List of discrete y values
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
#Plot the wireframe
#I want to plot the image as f(x,y) and I can't understand why wireframe won't let me
ax.plot_wireframe(X, Y, ig[:,:,2], rstride=10, cstride=10)
plt.show()
The imread function gives me an MxNx3 array of M rows, N columns, and an RGB value for each point in the matrix. I don't understand how to use wireframe to plot that data properly. These z values aren't plotting what I expected (a checkerboard pattern), but instead a y=x line alternating between 0 and 1.
What do I need to do here? I want a series of cuboids in a 3D checkerboard pattern.
Image of what I have currently
You may use np.meshgrid(), so:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
import mpl_toolkits.mplot3d
ig = mpimg.imread('testIMG.png')
x = np.linspace(0, ig.shape[1], ig.shape[1]) #List of discrete x values
y = np.linspace(0, ig.shape[0], ig.shape[0]) #List of discrete y values
X, Y = np.meshgrid(x, y)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
#Plot the wireframe
#I want to plot the image as f(x,y) and I can't understand why wireframe won't let me
ax.plot_wireframe(X, Y, ig[:,:,2], rstride=10, cstride=10)
plt.show()
I haven't found an answer to this yet: I have a grid defined in a text file with four columns: (lon,lat,depth,slip). Each row is a grid point.
I can generate a scatter plot of these points using the following simple code:
# Main imports:
import numpy as np
from pylab import *
from mpl_toolkits.mplot3d import Axes3D
# Read the grid:
points = np.loadtxt("grid.txt")
# Retrieve parameters from the grid:
lon = points[:,0]
lat = points[:,1]
depth = points[:,2]
slip = points[:,3]
# 3-D plot of the model:
fig = figure(1)
ax = fig.add_subplot(111, projection='3d')
p = ax.scatter(lon, lat, depth, c=slip, vmin=0, vmax=max(slip), s=30, edgecolor='none', marker='o')
fig.colorbar(p)
title("Published finite fault in 3-D")
ax.set_xlabel("Longitude [degrees]")
ax.set_ylabel("Latitude [degrees]")
ax.set_zlabel("Depth [km]")
ax.invert_zaxis()
jet()
grid()
show()
And I get the following figure:
What I want to do is to be able to interpolate those points to create a "continuous" surface grid and plot it in both 2-D and 3-D plots. Therefore, somehow I've to consider all (lon,lat,depth,slip) in the interpolation. I'd appreciate your suggestions. Thanks in advance!
I'm a bit late, but if your data grid is properly ordered, you could resolve your iusse using plot_surface reshaping your 1D data to 2D.
An example supposing you're using a 10x10 grid:
# Main imports:
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
# Set the fourth dimension`
color_dimension = slip.reshape(10,10)
# normalize the colours
minn, maxx = color_dimension.min(), color_dimension.max()
norm = matplotlib.colors.Normalize(minn, maxx)
# color map
m = plt.cm.ScalarMappable(norm=norm, cmap='hot')
m.set_array([])
fcolors = m.to_rgba(color_dimension)
# plot
fig = plt.figure()
ax = fig.gca(projection='3d')
#reshape 1D data to 2D
g=ax.plot_surface(lat.reshape(10, 10), lon.reshape(10, 10), depth.reshape(10, 10), cmap='hot',rstride=1, cstride=1, facecolors=fcolors, vmin=minn, vmax=maxx, shade=False)
cbar=fig.colorbar(g,aspect=50)
cbar.set_label('slip', rotation=270, fontsize=14)
title("Published finite fault in 3-D")
ax.set_xlabel("Longitude [degrees]")
ax.set_ylabel("Latitude [degrees]")
ax.set_zlabel("Depth [km]")
ax.invert_zaxis()
plt.show()
I have this following python code, which displays the following 3D plot.
My code is:
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
# Generate data example
X,Y = np.meshgrid(np.arange(-99,-90), np.arange(-200,250,50))
Z = np.zeros_like(X)
Z[:,0] = 100.
Z[4][7] = 10
# Normalize to [0,1]
Z = (Z-Z.min())/(Z.max()-Z.min())
colors = cm.viridis(Z)
rcount, ccount, _ = colors.shape
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, rcount=rcount, ccount=ccount,
facecolors=colors, shade=False)
surf.set_facecolor((0,0,0,0))
plt.show()
I want to color the irregularities on the XY plane in a different color. I want to be able to highlight the bumps on the XY plane.
How do I do that?
The problem is that the grid is not very dense. The bump consist of a single pixel. So there are 4 cells in the grid, 3 of which have their lower left corner at 0, and would hence not receive a different color according to their value. Only the one pixel which actually is the bump gets colorized.
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
X,Y = np.meshgrid(np.arange(-99,-90), np.arange(-200,250,50))
Z = np.zeros_like(X)
Z[:,0] = 100.
Z[4][7] = 10
norm = plt.Normalize(Z.min(),Z.min()+10 )
colors = cm.viridis(norm(Z))
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, facecolors=colors, shade=False)
surf.set_facecolor((0,0,0,0))
plt.show()
Now you may expand the colorized part of the plot, e.g. using scipy.ndimage.grey_dilation, such that all pixels that are adjacent also become yellow.
from scipy import ndimage
C = ndimage.grey_dilation(Z, size=(2,2), structure=np.ones((2, 2)))
norm = plt.Normalize(Z.min(),Z.min()+10 )
colors = cm.viridis(norm(C))
I am looking to make a plot similar to the one found here, with the simple difference that I would like to to set the distance from the center for each point. Ie, given a slice of the plot is a circle, where I would like each of the points to be at a definable distance from the center.
What I a starting with, given a simple modification of the previously mentioned answer:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib
import numpy as np
from scipy.interpolate import interp1d
from matplotlib import cm
from matplotlib import pyplot as plt
step = 0.04
maxval = 1.0
fig = plt.figure()
ax = Axes3D(fig)
# u here would define the desired distance from radial axis
# u=np.array([0,1,2,1,0,2,4,6,4,2,1])
v=np.array([4,4,6,3,6,4,1,4,4,4,4])
r=np.array([0,1,2,3,4,5,6,7,8,9,10])
f=interp1d(r,u)
# walk along the circle
p = np.linspace(0,2*np.pi,len(r))
R,P = np.meshgrid(r,p)
# transform them to cartesian system
X,Y = R*np.cos(P),R*np.sin(P)
Z=f(R)
ax.scatter(X, Y, Z)#, rstride=1, cstride=1, cmap=cm.jet)
ax.set_xticks([])
fig.savefig(str(output_prefix + '3d..png'), dpi=(200))
What I would like to plot (apologies for the blurred sketch):
I have tried using interp2d to add the u variable commented out above, but no luck. Changing Z to the array u threw the error that X, Y, and Z must be the same size ("Argument 'zs' must be of same size as 'xs' ", understandably as X and Y are now interpolated) What do I need to do? Any tips would be appreciated!
I don't know exactly what you meant in your question.
I made v to be the offset of the center of the circles in x-axis.
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from scipy.interpolate import interp1d
from matplotlib import pyplot as plt
step = 0.04
maxval = 1.0
fig = plt.figure()
ax = Axes3D(fig)
# v here would define the desired distance from radial axis
u=np.array([0,1,2,1,0,2,4,6,4,2,1])
v=np.array([4,4,6,3,6,4,1,4,4,4,4])
r=np.array([0,1,2,3,4,5,6,7,8,9,10])
f=interp1d(r,u)
# walk along the circle
V = np.tile(v, (len(u), 1))
p = np.linspace(0,2*np.pi,len(r))
R,P = np.meshgrid(r,p)
# transform them to cartesian system
X,Y = V + R*np.cos(P),R*np.sin(P)
Z=f(R)
ax.scatter(X, Y, Z)#, rstride=1, cstride=1, cmap=cm.jet)
ax.set_xticks([])
plt.show()