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
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 have an issue with smoothing out the mesh representation of my 3D surface with matplotlib. Below, please see my example. I am having a hard time figuring out how to make the plot look nicer/smoother if possible. Thank you for your time in advance!
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.colors import LightSource
import numpy as np
X = [1,1,1,1,1,1,50,50,50,50,50,50]
Y = [3,5,7,8,9,10,3,5,7,8,9,10]
Z = [5.23,3.11,17.54,0.93,40.11,10.15,1.47,14.32,5.46,55.93,40.8,10.2]
x = np.reshape(X, (2, 6))
y = np.reshape(Y, (2, 6))
z = np.reshape(Z, (2, 6))
X, Y = np.meshgrid(x, y)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(x, y, z)
ax.set_xlabel('Persistence Length')
ax.set_ylabel('Complexity')
ax.set_zlabel('Relative number of configurational states')
surf = ax.plot_surface(x, y, z, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
To obtain smooth line/surface you can set antialiased=True on the surface plot. Note that you were plotting two identical surface: in the following example I have eliminated the first.
To obtain a smoother mesh, you probably want to interpolate between your data points. One way to do that is to use griddata from the scipy.interpolate module.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
from scipy.interpolate import griddata
X = [1,1,1,1,1,1,50,50,50,50,50,50]
Y = [3,5,7,8,9,10,3,5,7,8,9,10]
Z = [5.23,3.11,17.54,0.93,40.11,10.15,1.47,14.32,5.46,55.93,40.8,10.2]
points = np.array([X, Y]).T
# create a grid of coordinates between the minimum and
# maximum of your X and Y. 50j indicates 50 discretization
# points between the minimum and maximum.
X_grid, Y_grid = np.mgrid[1:50:50j, 3:10:50j]
# interpolate your values on the grid defined above
Z_grid = griddata(points, Z, (X_grid, Y_grid), method='cubic')
fig = plt.figure(constrained_layout=True)
ax = fig.add_subplot(111, projection='3d')
ax.set_xlabel('Persistence Length')
ax.set_ylabel('Complexity')
ax.set_zlabel('Relative number of configurational states')
surf = ax.plot_surface(X_grid, Y_grid, Z_grid, cmap=cm.coolwarm,
linewidth=0, antialiased=True)
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
Here is an example of antialiased=False on the left, vs antialiased=True on the right:
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 want to work with only one figure, with multiples, different and modifiable plots, whithout the subplots formalism.
Is there a way to superimpose two differents plots, in the same way as text boxes, i.e anywhere on the figure ?
Here a "gimp made" example :
Thanks !
You can use figure.add_axes to place an axes at an arbitrary location.
fig = plt.figure()
fig.add_axes([0.1,0.2,0.3,0.4])
places an axes at x=0.1, y=0.2, width=0.3, height=0.4 in figure coordinates.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_axes([0.4,0.1,0.5,0.6], projection='3d')
X, Y = np.meshgrid(np.arange(-5, 5, 0.25), np.arange(-5, 5, 0.25))
Z = np.sin(np.sqrt(X**2 + Y**2))
surf = ax.plot_surface(X, Y, Z, cmap="plasma")
ax = fig.add_axes([0.3,0.4,0.3,.4])
plt.plot([1,2,3])
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)