Plotting A 3D Hyperboloid - python

My teacher in class gave this formula
−0.3𝑥 **2−0.3𝑦 **2+𝑧 **2=1.
and showed its 3d graphic in class seen below. I just perform a half graphic, and I have no idea
how to plot the rest graphic. The following code
from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np
X = np.linspace(-5, 5, 100)
Y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(X, Y)
Z = np.sqrt(0.3*(X **2 + Y **2) + 1)
ax = plt.gca(projection='3d')
plot1 = ax.plot_surface(X, Y, Z, cmap='jet', alpha=0.6, vmin=-5, vmax=5)
plt.colorbar(plot1)
plt.show()
enter image description here

This is because when you change the expression about the z-axis, the result is positive no matter what value you substitute for x,y because of the square. Just adding -Z values is a simple solution.
ax.plot_surface(X, Y, Z, cmap='jet', alpha=0.6, vmin=-5, vmax=5)
ax.plot_surface(X, Y, -Z, cmap='jet', alpha=0.6, vmin=-5, vmax=5)

Related

How to join matplotlib 3D surfaces so that they aren't layers but intersecting planes?

Consider following code that plots the intersection of two planes at the origin
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
def func(x, y, z):
C=np.exp(-5*(x**2 + y**2 + z**2))
return C
x= np.linspace(-1, 1, 20)
y = np.linspace(0, 1, 30)
X, Y = np.meshgrid(x, y)
Z = 2*X + 3*Y
Z1 = 2*X - 3*Y
C = func(X, Y, Z)
C1 = func(X, Y, Z1)
ax = plt.axes(projection='3d')
ax.plot_surface(X, Y, Z, rstride=1, cstride=1,
cmap='viridis', edgecolor='none', facecolors = cm.jet(C/np.amax(C)));
[![enter image description here][1]][1]ax.plot_surface(X, Y, Z1, rstride=1, cstride=1,
cmap='viridis', edgecolor='none', facecolors = cm.jet(C1/np.amax(C1)));
I am trying to plot surfaces that intersect without them showing as layers. I also created other planes and it seems the only way I have found so far is by varying "zorder" but that would still be layers. I recognize that this needs proper 3D plotting but unfortunately, mayavi and vtk cannot be installed on this computer so I am seeking a matplotlib only solution. Is there is way in matplotlib to stitch them together?

Plot 3d in Python

I wish to know how to plot a surface of type $(t,x,u=u(t,x))$ in Python. More precisely, $t,x$ are vectors and $u$ is a matrix that are initialized as np.zeros(), while the function plot does not draw the surface as I desire. Could someone help? The code is as follow:
eps=0.1
m=2000
n=100
dt=1.0/m
dx=1.0/(n*n)
time=np.zeros(m+1)
for i in range(m+1):
time[i]=i*dt
space=np.zeros(2*n+1)
for j in range(2*n+1):
space[j]=(j-n)*dx*n
sol=np.zeros((m+1,2*n+1))
for i in range(m):
index_i=m-1-i
for j in range(1,2*n):
sol[index_i, j] =sol[index_i+1, j]-0.5*dt*math.log(eps+abs(sol[index_i+1, j+1]+sol[index_i+1, j-1]-2*sol[index_i+1, j])/dx)
t_mesh, x_mesh = np.meshgrid(time, space)
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
surf = ax.plot_surface(t_mesh, x_mesh, sol, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
Which format should be used such that plt.plot(time,space,sol) works?
PS : I do research in maths and I code rarely. Sorry if my statement is not clear.
You can plot that function like so:
import numpy as np
import math
import matplotlib.pyplot as plt
from matplotlib import cm
# ... your original code here ...
def plot_surface_from_arrays(X, Y, Z, rotate=0):
assert Y.shape + X.shape == Z.shape, "X and Y shapes don't match Z"
X_mesh, Y_mesh = np.meshgrid(X, Y)
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
ax.view_init(elev=30, azim=-60 + rotate)
surf = ax.plot_surface(X_mesh, Y_mesh, Z, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
plot_surface_from_arrays(space, time, sol, rotate=90)
Result:
Code adapted from this documentation example.

How to get proper views of point cloud data in numpy-stl?

I am trying to get front, back, left, right, top, bottom after projecting the point clouds of 3D data. But the results are not good. Is there any better way to get the required views? I have done up to this using numpy-stl documentation and some research for projection.
import numpy as np
import pandas as pd
import os
import time
import scipy
import math
from scipy import ndimage
from stl import mesh
from matplotlib import pyplot as plt
from mpl_toolkits import mplot3d
from matplotlib import cm
%matplotlib inline
# Load an existing stl file:
my_mesh = mesh.Mesh.from_file('Bolt.stl')
# Create a new plot
figure = pyplot.figure()
axes = mplot3d.Axes3D(figure)
# Load the STL files and add the vectors to the plot
axes.add_collection3d(mplot3d.art3d.Poly3DCollection(my_mesh.vectors))
# Auto scale to the mesh size
scale = my_mesh.points.flatten()
axes.auto_scale_xyz(scale, scale, scale)
# Show the plot to the screen
pyplot.show()
I have download that bolt.stl from grabcad.com.
After that, I have tried to project it's different views like:
points = my_mesh.vectors
x = points[:,0].flatten()
y = points[:,1].flatten()
z = points[:,2].flatten()
fig= plt.figure()
ax= fig.add_subplot(111, projection= '3d')
ax.scatter(x,y,z)
ax.plot(x, z, 'r+', zdir='y', zs=100)
ax.plot(y, z, 'g+', zdir='x', zs=-100)
ax.plot(x, y, 'k+', zdir='z', zs=-100)
ax.set_xlabel('X')
ax.set_xlim([-100, 100])
ax.set_ylabel('Y')
ax.set_ylim([-100, 100])
ax.set_zlabel('Z')
ax.set_zlim([-100, 100])
plt.show()
Result is so bad, I cannot even know, where goes the bolt 3D.
I have also tried:
X = points[:,0]
Y = points[:,1]
Z = points[:,2]
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(X, Y, Z, rstride=8, cstride=8, alpha=0.3)
cset = ax.contourf(X, Y, Z, zdir='z', offset=-100, cmap="gray")
cset = ax.contourf(X, Y, Z, zdir='x', offset=-100, cmap="gray")
cset = ax.contourf(X, Y, Z, zdir='y', offset=100, cmap="gray")
ax.set_xlabel('X')
ax.set_xlim(-100, 100)
ax.set_ylabel('Y')
ax.set_ylim(-100, 100)
ax.set_zlabel('Z')
ax.set_zlim(-100, 100)
plt.show()
I have also tried with this code to, which I have found from "MVCNN for 3D shape recognition "
def point_cloud_to_volume(points, size=32):
vol = np.zeros((size,size,size))
locations = np.copy(points)
locations[:] *= (size-1)
locations = locations.astype(int)
locations[locations >= size] = 0.0
locations[locations < 0] = 0.0
vol[locations[:,0],locations[:,1],locations[:,2]] = 1.0
return vol
def vol2depthmap(volume_array, bg_val=32):
vol = volume_array.argmax(2)
vol[vol == 0] = bg_val
return vol
v = point_cloud_to_volume(points)
%matplotlib inline
from matplotlib import pyplot as plt
plt.imshow(vol2depthmap(v), interpolation='nearest', cmap='Greys')
plt.colorbar()
Finally, I have tried:
front_proj = points[:, :, :].sum(axis=1)
plt.plot(front_proj)
plt.show()
side_proj = points[:, :, :].sum(axis=0)
plt.plot(side_proj)
plt.show()
top_proj = points[:, :, :].sum(axis=2)
plt.plot(top_proj)
plt.show()
I have tried using slicing, but as you have already guessed what will be the result.
front = points[:,:,0]
back = points[:,:,-1]
top = points[0,:,:]
bottom = points[-1,:,:]
r_side = points[:,-1,:]
l_side = points[:,0,:]
How to get the proper views of .stl file like below. Please ignore drafting and dimensions.
Or any other cad format will do. I tried it in .stl file as there is no python-library I found so far, to load other cad formats than stl.
Have you tried this?
figure = plt.figure()
axes = mplot3d.Axes3D(figure)
axes.add_collection3d(mplot3d.art3d.Poly3DCollection(mymesh.vectors))
axes.view_init(90,270) # top view
scale = mymesh.points.flatten('F') #C, F, A, or K
axes.auto_scale_xyz(scale, scale, scale)
plt.show()
Play with the view_init combinations of 0,90,180,270 to get the other projections.
Here's something you can do:
vertices = my_mesh.vectors.reshape(3*len(my_mesh.vectors), 3)
vertices = np.unique(vertices, axis=0)
x, y, z = zip(*vertices)
figure = plt.figure()
axes = mplot3d.Axes3D(figure)
axes.scatter3D(x, y, z)
plt.show()

How to make my surface plot appear using Axes3D?

I'm trying to create a surface plot using Python Matplotlib. I've read the documentation in an attempt to figure out where my code was wrong or if I've left anything out, but was having trouble.
The code that I've written is
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def computeCost(X, y, theta):
m = len(y)
predictions = np.dot(X, theta)
squareErros = (predictions - y) ** 2
J = (1 / (2 * m)) * sum(squareErrors)
return J
data = np.loadtxt("./data1.txt", delimiter=',')
X = data[:, 0].reshape(-1, 1)
y = data[:, 1].reshape(-1, 1)
m = len(y)
X = np.concatenate((np.ones((m, 1)), X), axis=1)
theta0_vals = np.linspace(-10, 10, 100) # size (100,)
theta1_vals = np.linspace(-1, 4, 100) # size (100,)
J_vals = np.zeros((len(theta0_vals), len(theta1_vals)))
for i in range(len(x_values)):
for j in range(len(y_values)):
t = np.array([theta0_vals[i], theta1_vals[j]]).reshape(-1, 1)
J_vals[i][j] = computeCost(X, y, t) # size (100, 100)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(theta0_vals, theta1_vals, J_vals)
plt.show()
When I invoke plt.show() I get no output. The surface plot that I'm expecting to see is similar to this:
Would anybody be kind enough to let me know where my usage of the surface plot library went wrong? Thank you.
EDIT
I've tried to run the demo code provided here and it works fine. Here's the code for that:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
# 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)
# Customize the z axis.
ax.set_zlim(-1.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
I think I've figured out the issue by changing a couple of the last lines of code from
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(theta0_vals, theta1_vals, J_vals)
to
ax = plt.axes(projection='3d')
surf = ax.plot_surface(theta0_vals, theta1_vals, J_vals, rstride=1, cstride=1, cmap='viridis', edgecolor='none')
Making this change gives me a surface plot such that:
The link that gave me reference to this was this.

matplotlib plot surface too slow

I have a matrix S with 60 rows and 2000 columns. I need a 3d plot of this matrix.
This is what I have done:
S.dtype = 'float64'
S = sk.preprocessing.scale(S)
n, p = S.shape
X = np.arange(0, n)
Y = np.arange(0, p)
X, Y = np.meshgrid(X, Y)
def funz(x,y):
return S[x, y]
Z = funz(X, Y)
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1,
cmap=cm.RdBu,linewidth=0, antialiased=False)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
This works but the plot is too heavy in the sense that it is impossible to move it in order to visualize it better. How can I solve this?
In particular I need to find a nice view of the 3d plot to save it as a pdf figure.
matplotlib doesn't have "true" 3D plotting. Typically, you'd use something like mayavi for a complex or large surface, rather than matplotlib.
As a quick example:
import numpy as np
from mayavi import mlab
x, y = np.linspace(-15, 15, 200), np.linspace(-15, 15, 200)
xx, yy = np.meshgrid(x, y)
z = np.cos(np.hypot(xx, yy)) + np.sin(np.hypot(xx + 5, yy + 5))
mlab.figure(bgcolor=(1,1,1))
# We'll use "surf" to display a 2D grid...
# warp_scale='auto' guesses a vertical exaggeration for better display.
# Feel free to remove the "warp_scale" argument for "true" display.
mlab.surf(x, y, z, warp_scale='auto')
mlab.show()

Categories