I'm trying to create a 3d plot using matplot lib with some data taken from rectangular surface. Coordinates of all measurments are saved on two lists processed by np.meshgrid. The problem is matplotlib ax.plot_srface() seems to accept only square grid (then it works). Is there any way to force matplotlib to work with rectangular shape or append mesh to be square? Code and error are below:
def graph3d(a_div, b_div, res):
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
side_div=get_side(b_div, res)
print(f"{a_div}\n\n{side_div}")
X, Y = np.meshgrid(a_div, side_div)
z = random_test(X, Y)
surf = ax.plot_surface(X, Y, z, cmap=cm.hsv, linewidth=0, antialiased=False)
ax.set_zlim(-2.5, 2.5)
ax.set_title("Measurement results 3D plot")
ax.zaxis.set_major_locator(LinearLocator(10))
# A StrMethodFormatter is used automatically
ax.zaxis.set_major_formatter('{x:.02f}')
# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=3, aspect=5)
plt.show()
raise TypeError('Dimensions of C %s are incompatible with'
TypeError: Dimensions of C (21, 2) are incompatible with X (21) and/or Y (2); see help(pcolor)
Related
I am trying to plot a 3D surface with matplotlib for a bunch of math functions. These functions are defined to take in a 1-D numpy array with arbitrary length as input.
When plotted as contours plot, the plot looks correct.
. However, the 3D surface plot shows a surface that has been squashed onto a single line. I am using the same values for plotting, so they should be the same, but that's not what I'm getting and I'm very puzzled by this
Please see my code below:
from mpl_toolkits.mplot3d import Axes3D
# build the meshgrid
x = np.linspace(bounds[0][0],bounds[0][1])
y = np.linspace(bounds[1][0], bounds[1][1])
xv, yv = np.meshgrid(x, y)
# populate z
z = np.zeros_like(xv)
for row_idx in range(xv.shape[0]):
for col_idx in range(xv.shape[1]):
z[row_idx][col_idx] = function(np.array([xv[row_idx][col_idx], yv[row_idx][col_idx]]))
# plot 3D surface
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.plot_surface(x, y, z, cmap='viridis', edgecolor='none')
# plot a contour
ax.contourf(x, y, z, cmap='viridis')
plt.show()
# function that I'm plotting -> bowl shaped for 2D x
def function(x):
return sum(x**2)
I might have this wrong but if you are just wanting the surface mesh you need to plot the gridded data as opposed to the linear one so just change this line:
ax.plot_surface(xv, yv, z, cmap='viridis', edgecolor='none')
Note I'm using xv, yv instead of X,Y.
Here is my output.
I have this set of data, which I would like to plot it in a 3D surface and in a contour by using python (numpy and matplotlib, basically). In this case, I have the X and Y axis as my free coordinates, and the results are described as a dataset on the z-axis.
I've checked many times the data, and it is formatted correctly to my needs.
Here is a plot of the set in a scatter manner
The problem is when I try to use the surface plot, where the end points of the (X, Y) mesh are connected, closing the surface and making not visible the part of the image that contains the information I would like to have. Here is the output I have regarding the surface plot and here is the output regarding the contour plot.
The code related to the surface plot (only ploting part) is
#...
#X and Y are the coordinates values
#E is the results I am trying to plot
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, E, cmap=cm.coolwarm, linewidth=0, antialiased=False)
ax.scatter3D(X, Y, E, cmap='Greens')
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
Here is the code related to the contour plot
fig, ax = plt.subplots()
CS = ax.contourf(X, Y, E, 10, cmap='RdGy')
ax.clabel(CS, inline=1, fontsize=10)
ax.set_title('Simplest default with labels')
fig.colorbar(CS, shrink=0.5, aspect=5)
plt.show()
This is the chart I did in 3D using Google Sheets.
I want to achieve the same scale on matplotlib but using a 3D surface.
The problem is that the ticks on logscale are being placed where they "should be" if it was a normal scale.
Here is my code:
X, Y = np.meshgrid(numrec, numtreino)
Z = (numerador/(((rec[0])+(treino[0]*60))/((rec[1])+(treino[1]*60))))*X
# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
linewidth=2, antialiased=True, alpha=0.8)
ax.set_xscale('symlog')
ax.set_yscale('symlog')
ax.invert_xaxis()
# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
As pointed out by ImportanceOfBeingErnest, it seems to be a bug in matplotlib.
If you enable a log scale when doing a 3D scatter plot, nothing is created and the program crashes.
Instead of ax.set_xscale('log'), ax.set_xscale('symlog') should be used.
To fix the scaling problem I've changed:
Z = (numerador/(((rec[0])+(treino[0]*60))/((rec[1])+(treino[1]*60))))*X
# Plot the surface.
to:
Z = (numerador/(((rec[0])+(treino[0]*60))/((rec[1])+(treino[1]*60))))*X
X = np.log10(X)
Y = np.log10(Y)
# Plot the surface.
To set the ticks I've added:
zticks = [ 1e3, 1e2, 1e1]
ax.set_xticks(np.log10(zticks))
ax.set_xticklabels(zticks)
I search for the correct implementation for this a long time now.
I have a 3D delaunay triangulation and want to plot this in 2D.
In 3D i manage to do so:
I need a 2D plot though. What i get using matplotlib.tripcolor method or the matplotlib.collections.PolyCollection is:
How do i plot this in 2D without the top and back triangles all mixed up? With all methods tried so far, some triangles are hidden by triangles that should be in the back of the structure.
I see, that the methods just do not have the information necessary to plot in the correct order, since i have to provide 2D arrays already. The depth information is lost.
Does anybody know how to do this?
Thanks a lot!
You can mimic a 2D plot with Axes3d by setting an orthographic projection, initialising the view to face the desired plane, and removing unwanted plot elements along the axis orthogonal to the chosen plane of view. In addition, you can plot 2D elements using the zdir keyword argument.
Here's one of the matplotlib 3D plot examples I modified to demonstrate
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
# Enable orthographic projection
# https://stackoverflow.com/questions/23840756/how-to-disable-perspective-in-mplot3d
from mpl_toolkits.mplot3d import proj3d
def orthogonal_proj(zfront, zback):
a = (zfront+zback)/(zfront-zback)
b = -2*(zfront*zback)/(zfront-zback)
return np.array([[1,0,0,0],
[0,1,0,0],
[0,0,a,b],
[0,0,-0.000001,zback]])
proj3d.persp_transformation = orthogonal_proj
fig = plt.figure()
ax = fig.gca(projection='3d')
# Init view to YZ plane
ax.view_init(azim=0, elev=0)
# Hide the X axis
ax.w_xaxis.line.set_lw(0.)
ax.set_xticks([])
# Change YZ plane colour to white
ax.w_xaxis.set_pane_color((1.0, 1.0, 1.0, 1.0))
# Make data.
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
ax.set_zlim(-1.1, 1.1)
ax.set_ylabel('y')
ax.set_zlabel('z')
# Plot 2D elements with zdir argument
# https://stackoverflow.com/questions/29549905/pylab-3d-scatter-plots-with-2d-projections-of-plotted-data
stepsize = 0.1
t = np.arange(-4, 4+stepsize, step=stepsize)
ax.plot(t, 0.5*np.sin(t), 'k', zdir='x', linewidth=1.0)
ax.text(0, 0, 1, 'Text', zdir='y', ha='center', va='top')
plt.show()
I am trying to make a 3D plot from x, y, z points list, and I want to plot color depending on the values of a fourth variable rho.
Currently I have ;
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot3D(cell_x, cell_y, cell_z, linestyle='None', marker='o', markersize = 5, antialiased=True)
ax.set_xlim3d(0.45, 0.55)
ax.set_ylim3d(0.45, 0.55)
ax.set_zlim3d(0.45, 0.55)
How to add cell_rho (my fourth array) as the color of my x, y, z points ? (for example for a jet colormap).
Thank you very much.
EDIT : I can't use scatter plots because for my 18000 points scatter plots are very slow compared to plot3d with markers only.
If you want to display a simple 3D scatterplot, can't you just use scatter?
E.g.,
x, y, z = randn(100), randn(100), randn(100)
fig = plt.figure()
from mpl_toolkits.mplot3d import Axes3D
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x, y, z, c=randn(100))
plt.show()
(I'm running the above code under python -pylab.)
It seems, on the contrary, that with plot3D you must convert your fourth dimension to RGB tuples.