Python: How to plot these 3d lines as an isosurface? - python

I have some x, y, z data for which I can plot multiple 3d lines/traces into order to build the following image:
The python code building this is like so:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=[20, 20])
ax = fig.add_subplot(111, projection='3d')
midpoint = len(t)/2 - 10000
for i in range(100):
x = xs_array[i]
y = ys_array[i]
ax.plot(t[midpoint:midpoint+20000], x[midpoint:midpoint+20000], y[midpoint:midpoint+20000], alpha=0.4)
I want to build a isosurface like the one shown below as it is hard to interpret the shape in the current form, how might I go about that?

Related

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)

Python matplotlib wireframe distortion

I am trying to create a plot composed of multiple wireframe spheres using matplotlib. I found a code fragment to plot one such sphere here so I thought it would be easy to extend it to multiple spheres by just calling plot_wireframe multiple times. I was wrong. Here's a code fragment:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
u, v = np.mgrid[0:2*np.pi:20j, 0:np.pi:10j]
x=np.cos(u)*np.sin(v)
y=np.sin(u)*np.sin(v)
z=np.cos(v)
fig = plt.figure(figsize=(8,6))
ax = fig.gca(projection='3d')
ax.plot_wireframe(x*3.+5., y*3., z*3.,linewidths=.2)
ax.view_init(azim=30,elev=40)
ax.set_aspect("equal")
plt.show()
fig = plt.figure(figsize=(8,6))
ax = fig.gca(projection='3d')
ax.plot_wireframe(x*3.+5., y*3., z*3.,linewidths=.2)
spheres = [ [0,0,0,1], [3,0,0,1.6] ]
for v in spheres:
ax.plot_wireframe(x*v[3]+v[0], y*v[3]+v[1], z*v[3]+v[2],linewidths=.2)
ax.view_init(azim=30,elev=40)
ax.set_aspect("equal")
plt.show()
If you run that code, the first plot will show a nice sphere, while in the second all the spheres are distorted and shifted. I searched to make sure plot_wireframe can be called multiple time on the same axis but couldn't find anything. Also, I'm a Python noob, but I don't think I'm doing anything wrong.
Thank you for the help!
Short answer: adjust the axes limits manually:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
u, v = np.mgrid[0:2*np.pi:20j, 0:np.pi:10j]
x=np.cos(u)*np.sin(v)
y=np.sin(u)*np.sin(v)
z=np.cos(v)
# I'm not sure what was this for.
'''
fig = plt.figure(figsize=(8,6))
ax = fig.gca(projection='3d')
ax.plot_wireframe(x*3.+5., y*3., z*3.,linewidths=.2)
ax.view_init(azim=30,elev=40)
ax.set_aspect("equal")
plt.show()
'''
fig = plt.figure(figsize=(8,6))
ax = fig.gca(projection='3d')
ax.plot_wireframe(x*3.+5., y*3., z*3.,linewidths=.2)
spheres = [ [0,0,0,1], [3,0,0,1.6] ]
for v in spheres:
ax.plot_wireframe(x*v[3]+v[0], y*v[3]+v[1], z*v[3]+v[2],linewidths=.2)
ax.view_init(azim=30,elev=40)
ax.set_xlim([0,7]) # Like so.
ax.set_ylim([-3,3])
ax.set_zlim([-3,3])
ax.set_aspect("equal")
plt.show()

Python : How to plot 3d graphs using Python?

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)

Categories

Resources