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:
Related
see picture
Hey, I want to plot a function in 3d matplotlib python. The functions I want to plot are x = i where i stretches from 0 to 1 with increments of 0.20. So basically 4 vertical planes just as in the picture I shared.
You can create the planes as surface plots.
Here's an example:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
X, Y = np.meshgrid(np.arange(-6, 6), np.arange(-6, 6))
Z = 0*X
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, Z, alpha=0.5) # the horizontal plane
ax.plot_surface(Z, Y, X, alpha=0.5) # the vertical plane
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 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))
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()
I am using matplotlib for doing this
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
fig = plt.figure()
ax = Axes3D(fig)
x = [6,3,6,9,12,24]
y = [3,5,78,12,23,56]
ax.plot(x, y, zs=0, zdir='z', label='zs=0, zdir=z')
plt.show()
Now this builds a graph that is horizontal in the 3d space. How do I make the graph vertical so that it faces the user?
What I want to do is build multiple such vertical graphs that are separated by some distance and are facing the user.
bp's answer might work fine, but there's a much simpler way.
Your current graph is 'flat' on the z-axis, which is why it's horizontal. You want it to be vertical, which means that you want it to be 'flat' on the y-axis. This involves the tiniest modification to your code:
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
fig = plt.figure()
ax = Axes3D(fig)
x = [6,3,6,9,12,24]
y = [3,5,78,12,23,56]
# put 0s on the y-axis, and put the y axis on the z-axis
ax.plot(xs=x, ys=[0]*len(x), zs=y, zdir='z', label='ys=0, zdir=z')
plt.show()
Then you can easily have multiple such graphs by using different values for the ys parameter (for example, ys=[2]*len(x) instead would put the graph slightly behind).
Mayavi, in particular the mlab module, provides powerful 3D plotting that will work on large and or complex data, and should be easy to use on numpy arrays.
You can set the view angle of the 3d plot with the view_init() function. The example below is for version 1.1 of matplotlib.
from mpl_toolkits.mplot3d import axes3d
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = [6,3,6,9,12,24]
y = [3,5,78,12,23,56]
ax.plot(x, y, zs=0, zdir='z', label='zs=0, zdir=z')
ax.view_init(90, -90)
plt.show()
According to the documentation you want to use the ax.plot_surface(x,y,z) method. More information and chart types here.
The following should work:
x = [1,2,3]
y = [4,5,6]
z = [7,8,9]
data = zip(x,y,z)
#map data on the plane
X, Y = numpy.meshgrid(arange(0, max(x), 1), arange(0, max(y), 1))
Z = numpy.zeros((len(Y), len(X)), 'Float32')
for x_,y_,z_ in data:
Z[x_, y_] = z_ #this should work, but only because x and y are integers
#and arange was done with a step of 1, starting from 0
fig = p.figure()
ax = p3.Axes3D(fig)
ax.plot_surface(X, Y, Z)