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.
Related
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)
I want to calculate and add R^2 and R in my line chart as a legend, but I only know how to add equations in the chart. Here is my code.My English is poor,I make a mistake in the last question,I don't want to reject your approve.I'm sorry,I hope you can see this question.
import matplotlib.pyplot as plt
import numpy as np
import pylab as pl
y = df["rain"]
x = df["SITE"]
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set(xlabel='year', ylabel='P', title='rain')
ax.grid()
z = np.polyfit(x, y, 1)
p = np.poly1d(z)
plt.plot(x,p(x), "y--")
plt.plot(x, y, 'og-', label=("y=%.6fx+(%.6f)"%(z[0],z[1])))
plt.legend()
You can calculate and plot R^2 as follows given your code:
from sklearn.metrics import r2_score
import matplotlib.pyplot as plt
import numpy as np
import pylab as pl
import pylab
y = df["rain"]
x = df["SITE"]
z = np.polyfit(x, y, 1)
p = np.poly1d(z)
r_squared = r2_score(x, y)
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set(xlabel='year', ylabel='P', title='rain')
ax.grid()
pylab.plot(x,p(x), "y--")
pl.plot(x, y, 'og-', label=("y=%.6fx+(%.6f) - $R^2$=%.6f"%(z[0],z[1], r_squared)))
pl.legend()
You can try "$r^2$" (or any combination in a f-string). The $ renders Latex chars in matplotlib labels:
x = np.arange(0, 100)
y = x**2
plt.figure(figsize=(15,10))
plt.plot(x, y, label="y=$x^2$")
plt.legend()
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()
At the moment I have a figure that looks like this,
Generated by the code:
import matplotlib.pyplot as plt
import numpy as np
data = np.random.rand(20,5)
rows,cols = data.shape
plt.imshow(data, interpolation='nearest', extent=[0.5, 0.5+cols, 0.5, 0.5+cols], cmap='bwr')
plt.show()
However I would like to 'fold' this up into a 3D cylinder, joining the left and right edges (as one would do with a sheet of paper). In other words the left edge and the right edges are actually the same edge and so I would like to join them together to form a cylinder.
How would I go about doing this?
The Poly3DCollection is the method of choice for arbitrary 3D polygons in mplot3d.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
nphi,nz=12,20
r=1 # radius of cylinder
phi = np.linspace(0,360, nphi)/180.0*np.pi
z= np.linspace(0,1.0,nz)
print z
facecolors=['r','g','b','y']
cols=[]
verts2 = []
for i in range(len(phi)-1):
cp0= r*np.cos(phi[i])
cp1= r*np.cos(phi[i+1])
sp0= r*np.sin(phi[i])
sp1= r*np.sin(phi[i+1])
for j in range(len(z)-1):
z0=z[j]
z1=z[j+1]
verts=[]
verts.append((cp0, sp0, z0))
verts.append((cp1, sp1, z0))
verts.append((cp1, sp1, z1))
verts.append((cp0, sp0, z1))
verts2.append(verts)
value=np.random.rand()
print value
col=plt.cm.bwr(value)
print col
cols.append(col)
poly3= Poly3DCollection(verts2, facecolor=cols )
poly3.set_alpha(0.8)
ax.add_collection3d(poly3)
ax.set_xlabel('X')
ax.set_xlim3d(-1, 1)
ax.set_ylabel('Y')
ax.set_ylim3d(-1, 1)
ax.set_zlabel('Z')
ax.set_zlim3d(0, 1)
plt.show()
You could use plot_surface:
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as axes3d
np.random.seed(2016)
data = np.random.rand(12, 20)
h, w = data.shape
theta, z = np.linspace(0, 2 * np.pi, w), np.linspace(0, 1, h)
THETA, Z = np.meshgrid(theta, z)
X = np.cos(THETA)
Y = np.sin(THETA)
fig = plt.figure()
ax = fig.add_subplot(1,1,1, projection='3d')
cmap = plt.get_cmap('bwr')
plot = ax.plot_surface(
X, Y, Z, rstride=1, cstride=1, facecolors=cmap(data),
linewidth=0, antialiased=False, alpha=0.75)
plt.show()
yields
So I have some 3D data that I am able to plot just fine except the edges look jagged.
The relevant code:
import numpy as np
from matplotlib import cm
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
x = np.arange(-1, 1, 0.01)
y = np.arange(-1, 1, 0.01)
x, y = np.meshgrid(x, y)
rho = np.sqrt(x**2 + y**2)
# Attempts at masking shown here
# My Mask
row=0
while row<np.shape(x)[0]:
col=0
while col<np.shape(x)[1]:
if rho[row][col] > 1:
rho[row][col] = None
col=col+1
row=row+1
# Calculate & Plot
z = rho**2
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(x, y, z, rstride=8, cstride=8, cmap=cm.bone, alpha=0.15, linewidth=0.25)
plt.show()
Produces:
This is so close to what I want except the edges are jagged.
If I disable my mask in the code above & replace it with rho = np.ma.masked_where(rho > 1, rho) it gives:
It isn't jagged but not want I want in the corners.
Any suggestions on different masking or plotting methods to get rid of this jaggedness?
Did you consider using polar coordinates (like in this example) ?
Something like:
import numpy as np
from matplotlib import cm
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# create supporting points in polar coordinates
r = np.linspace(0,1.25,50)
p = np.linspace(0,2*np.pi,50)
R,P = np.meshgrid(r,p)
# transform them to cartesian system
x, y = R * np.cos(P), R * np.sin(P)
rho = np.sqrt(x**2 + y**2)
# Calculate & Plot
z = rho**2
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(x, y, z, rstride=1, cstride=1, cmap=cm.bone, alpha=0.15, linewidth=0.25)
plt.show()