Gridlines Above 3D Scatter Plot in matplotlib - python

When making a 3D scatter plot with matplotlib I cannot seem to control whether the axes are above or below the plot. For example the following code will always have the x and y axes above the plot if ax1.elev < 0
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
fig = plt.figure('Test')
X = np.random.rand(1,100)
Y = np.random.rand(1,100)
Z = np.random.rand(1,100)
ax1 = fig.add_subplot(111, projection = '3d')
ax1.scatter(X,Y,Z)
ax1.view_init(-10,45)
Is it possible to force the x and y axes and the gridlines and planes to be below the plot even though ax1.elev < 0?

I take as an example the code of this question (thanks crayzeewulf). Except for the z-axis, we do it for the x- and y-axis
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
fig = plt.figure('Test')
X = np.random.rand(1,100)
Y = np.random.rand(1,100)*10
Z = np.random.rand(1,100)
ax1 = fig.add_subplot(111, projection = '3d')
ax1.scatter(X,Y,Z)
ax1.view_init(-10,45)
tmp_planes = ax1.zaxis._PLANES
ax1.xaxis._PLANES = ( tmp_planes[3], tmp_planes[2],
tmp_planes[1], tmp_planes[0],
tmp_planes[5], tmp_planes[4])
ax1.yaxis._PLANES = ( tmp_planes[3], tmp_planes[2],
tmp_planes[1], tmp_planes[0],
tmp_planes[5], tmp_planes[4])
view_1 = (25, -135)
view_2 = (-10, 45)
init_view = view_2
ax1.view_init(*init_view)

Related

get 2D slice at Z from 3D meshgrid

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:

Axes3D.text() Annotate 3D Scatter Plot

Can't get the 3D text working to annotate the scatter plot points.
Tried Axes3D.text, plt.text but keep getting 'missing required positional argument 's'. How do you annotate in 3D in a loop?
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
import pandas as pd
import numpy as np
df = pd.read_csv (r'J:\Temp\Michael\Python\9785.csv')
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
#Scatter plot
for i in df.index:
x = df.at[i,'x']
y = df.at[i,'y']
z = df.at[i,'h']
ax.scatter(xs=x, ys=y, zs=z, s=20,color='red',marker='^')
label = df.at[i,'to']
Axes3D.text(x+0.8,y+0.8,z+0.8, label, zdir=x)
TypeError: text() missing 1 required positional argument: 's'
Changing: ax = fig.add_subplot(111, projection='3d')
to: ax = fig.gca(projection='3d')
solved the problem. Used ax.text.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
import pandas as pd
import numpy as np
df = pd.read_csv (r'J:\Temp\Michael\Python\9785.csv')
fig = plt.figure()
ax = fig.gca(projection='3d')
#Scatter plot
for i in df.index:
df.set_index('to')
x = df.at[i,'x']
y = df.at[i,'y']
z = df.at[i,'h']
ax.scatter(xs=x, ys=y, zs=z, s=20,color='red',marker='^')
ax.text(x+0.8,y+0.8,z+0.8, df.at[i,'to'], size=10, zorder=1)

Way of plotting data into boxes instead of pyramids using mplot3d

So I have an array of values that I am trying to plot using the plot_surface command. Specifically I have a 30x30 array with one in the middle and zeros elsewhere. When I plot it this is what I obtain:
I would like however for the value to be represented as a cuboid. Is that possible?
Thank you
edit: Code that shows the figure
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
N=30
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = y = np.arange(0, N)
z = np.zeros((N,N))
z[15,15] = 1
X, Y = np.meshgrid(x, y)
ax.plot_surface(X, Y, z, cmap='YlOrBr')
plt.show(block=False)
I think a 3D bar plot will give what you're looking for.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
N=30
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = y = np.arange(0, N)
z_bottom = np.zeros((N,N))
z_top = z_bottom.copy()
z_top[15,15] = 1
X, Y = np.meshgrid(x, y)
ax.bar3d(X.ravel(), Y.ravel(), z_bottom.ravel(), 1, 1, z_top.ravel())
plt.show(block=False)
The full documentation is here if you want to play with the colors and so forth.

matplotlib plot_surface 3D plot with non-linear color map

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))

Plot serial port 3d points data on 3d coordinate system using python

I have searched for this in google, but found solutions for 2d points in real time.How can I achieve this for stream of 3d point.
Here I should be able to add new points to plot.
I tried this, its just plots series of data. How to update?
You could just plot in interactive mode, for example the following keeps adding new points,
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
plt.ion()
plt.show()
x = np.linspace(0.,np.pi*4.,100)
ax.set_xlim([0.,13.])
ax.set_ylim([-1.5,1.5])
ax.set_zlim([-1.5,1.5])
for i in x:
ax.scatter(i, np.sin(i), np.cos(i))
print(i)
plt.pause(0.01)
UPDATE: added example of labelling
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
plt.ion()
plt.show()
lsp = np.linspace(0.,np.pi*4.,100)
ax.set_xlim([0.,13.])
ax.set_ylim([-1.5,1.5])
ax.set_zlim([-1.5,1.5])
for i, x in enumerate(lsp):
y = np.sin(x)
z = np.cos(x)
ax.scatter(x, y, z)
if i%10 == 0:
ax.text(x, y, z, str(np.round(x,3))+", "
+str(np.round(y,3))+", "
+str(np.round(z,3)))
plt.pause(0.01)

Categories

Resources