I would like to draw two lines on a surface (the pink surface) to represent the two cutting lines of this pink surface and two 2d planes (x = y and x = -y), like the blue lines in the figure below. Does anyone know how to do it?
The code to generate the pink surface is as below:
import numpy as NP
import matplotlib.pyplot as PLT
def f(x1, x2):
return 0.5 * x1 + 0.6 * x2 + 0.2 * x1 * x1 + 0.1 * x1 * x2 + 0.3 * x2 * x2 + 4
x = NP.linspace(-3, 3, 100)
y = NP.linspace(-3, 3, 100)
xx, yy = NP.meshgrid(x,y)
z = f(xx, yy)
# set up the figure
fig = PLT.figure()
ax = fig.gca(projection='3d')
ax.set_xlim(-3, 3)
ax.set_ylim(3, -3)
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
# plot the figure
ax.plot_surface(xx, yy, z, cmap="spring", alpha = 0.7)
# add the x=y line to the ground plane
ax.plot([-3, 3], [-3, 3], color = 'grey', linewidth = 1, linestyle='dashed')
# add the x=-y line to the ground plane
ax.plot([3, -3], [-3, 3], color = 'grey', linewidth = 1, linestyle='dashed')
PLT.show()
You can just use plot(x, -x, f(x, -x)) and plot(x, x, f(x, x)) to draw the curves. Note that matplotlib doesn't perfectly hide elements that are partially obscured by other elements.
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
import numpy as np
def f(x1, x2):
return 0.5 * x1 + 0.6 * x2 + 0.2 * x1 * x1 + 0.1 * x1 * x2 + 0.3 * x2 * x2 + 4
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
xx, yy = np.meshgrid(x,y)
z = f(xx, yy)
# set up the figure
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_xlim(-3, 3)
ax.set_ylim(3, -3)
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
# plot the figure
ax.plot_surface(xx, yy, z, cmap="spring", alpha = 0.7)
# add the x=y line to the ground plane
ax.plot([-3, 3], [-3, 3], color='grey', linewidth=1, linestyle='dashed')
# add the x=-y line to the ground plane
ax.plot([3, -3], [-3, 3], color='grey', linewidth=1, linestyle='dashed')
ax.plot(x, x, f(x, x), color='dodgerblue')
ax.plot(x, -x, f(x, -x), color='dodgerblue')
plt.show()
Related
I wonder how to create two slicing planes with a surface to two 2d figures.
For example, I created a surface as below:
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
import numpy as np
def f(x1, x2):
return 0.5 * x1 + 0.6 * x2 + 0.2 * x1 * x1 + 0.1 * x1 * x2 + 0.3 * x2 * x2 + 4
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
xx, yy = np.meshgrid(x,y)
z = f(xx, yy)
# set up the figure
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_xlim(-3, 3)
ax.set_ylim(3, -3)
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
# plot the figure
ax.plot_surface(xx, yy, z, cmap="spring", alpha = 0.7)
# add the x=y line to the ground plane
ax.plot([-3, 3], [-3, 3], color='grey', linewidth=1, linestyle='dashed')
# add the x=-y line to the ground plane
ax.plot([3, -3], [-3, 3], color='grey', linewidth=1, linestyle='dashed')
ax.plot(x, x, f(x, x), color='dodgerblue')
ax.plot(x, -x, f(x, -x), color='dodgerblue')
plt.show()
The surface created by the above code looks like this
After this, I want to add two slicing planes, which are x = y and x = -y planes. And plot the cutting lines of the two planes and the surface to two different 2d figures.
For example, one 2d figure of the cutting line of the surface and the x = y plane would be something like the figure in the red box below, but no surface, just the red curve.
Actually, just need to plot them in two 2d figures
# slicing figure 1
fig2, ax2 = plt.subplots()
ax2.plot(x, f(x, y, b1, b2, b3, b4, b5, con))
ax2.set_title("x=y plane")
ax2.set_xlim(-3, 3)
ax2.set_ylim(1, 15)
# slicing figure 2
fig3, ax3 = plt.subplots()
ax3.plot(x, f(x, -y, b1, b2, b3, b4, b5, con))
ax3.set_title("x=-y plane")
ax3.set_xlim(-3, 3)
ax3.set_ylim(1, 15)
I'm making multiple density plots in 3D with a circle shape, using contourf.
What I want to do is similar to a clip_path for a pcolormesh plot.
How can I clip the plot in 3D in particular for a contourf plot?
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
fig = plt.figure()
ax = fig.gca(projection='3d')
x = np.linspace(0, 1, 100)
X, Y = np.meshgrid(x, x)
levels = np.linspace(-0.1, 0.4, 100) #(z_min,z_max,number of contour),
a=0
b=1
c=2
Z1 = a+.1*np.sin(2*X)*np.sin(4*Y)
Z2 = b+.1*np.sin(3*X)*np.sin(4*Y)
Z3 = c+.1*np.sin(4*X)*np.sin(5*Y)
plt.contourf(X, Y,Z1, levels=a+levels,cmap=plt.get_cmap('rainbow'))
plt.contourf(X, Y,Z2, levels=b+levels,cmap=plt.get_cmap('rainbow'))
plt.contourf(X, Y,Z3, levels=c+levels,cmap=plt.get_cmap('rainbow'))
ax.set_xlim3d(0, 1)
ax.set_ylim3d(0, 1)
ax.set_zlim3d(0, 2)
plt.show()
Are you sure your code generated that output image with the given parameters? I only got some blue squares. Tweaking a bit, it starts looking like yours.
To clip the contours, consider masking the Z arrays. As in:
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
import numpy.ma as ma
fig = plt.figure()
ax = fig.gca(projection='3d')
x = np.linspace(0, 1, 100)
X, Y = np.meshgrid(x, x)
levels = np.linspace(-0.1, 0.4, 100) #(z_min,z_max,number of contour),
a = 0
b = 1
c = 2
Z1 = a + .3 * np.sin(2 * X) * np.sin(4 * Y)
Z2 = b + .3 * np.sin(3 * X) * np.sin(4 * Y)
Z3 = c + .3 * np.sin(4 * X) * np.sin(5 * Y)
mask_cond = (X - .5) ** 2 + (Y - .5) ** 2 > .25
Z1 = ma.masked_where(mask_cond, Z1)
Z2 = ma.masked_where(mask_cond, Z2)
Z3 = ma.masked_where(mask_cond, Z3)
plt.contourf(X, Y, Z1, levels=a + levels, cmap='rainbow')
plt.contourf(X, Y, Z2, levels=b + levels, cmap='rainbow')
plt.contourf(X, Y, Z3, levels=c + levels, cmap='rainbow')
ax.set_xlim3d(0, 1)
ax.set_ylim3d(0, 1)
ax.set_zlim3d(0, 3)
plt.show()
I use matplot3d(ax.bar3d() and ax.plot) to plot two lines around a cuboid, when looking in bird viewbird view, this figure shows the read 3d relationship of all the objects. When looking from sideside view, some part of blue line that behind the green cylinder should be hidden, but this part still can be seen. I tried using parameter alpha, and it failed too. Does any body know how to deal with this ?
My matplotlib version is 2.1.0, and my python version is 3.4.7
# import
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
# global set
XMAX = 4
ZMAX = 15
mpl.rcParams['legend.fontsize'] = 10
fig = plt.figure()
ax = fig.gca(projection='3d')
print(mpl.__version__)
z = np.linspace(0, ZMAX, 5)
if True:
arrowstartt = np.zeros((3))
arrowstartx = np.zeros((3))
arrowstarty = np.zeros((3))
arrowendt = np.zeros((3))
arrowendx = np.zeros((3))
arrowendy = np.zeros((3))
arrowcolor= 'black'
fontsizes = 25
# x cors
x = (XMAX + 1) / np.max(z) * z
y = 0. * z
zz = 0. * z
ax.plot(x, y, zz, color=arrowcolor, linewidth=1)
arrowstartx[0] = x[-1]
arrowstarty[0] = y[-1]
arrowstartt[0] = zz[-1]
ax.text(x[-1], y[-1], zz[-1], "x", color='k', fontsize=fontsizes)
# y cors
x = 0. * z
y = 2 * XMAX / np.max(z) * z
zz = 0. * z
ax.plot(x, y, zz, color=arrowcolor, linewidth=1)
arrowstartx[1] = x[-1]
arrowstarty[1] = y[-1]
arrowstartt[1] = zz[-1]
ax.text(x[-1], y[-1], zz[-1]-1, "y", color='k', fontsize=fontsizes)
#z cor
x = 0. * z
y = 0. * z
zz = (XMAX) / np.max(z) * z
ax.plot(x, y, zz, color=arrowcolor, linewidth=1)
arrowstartx[2] = x[-1]
arrowstarty[2] = y[-1]
arrowstartt[2] = zz[-1]
ax.text(x[-1], y[-1], zz[-1], "z", color='k', fontsize=fontsizes)
# arrow end
arrowendx = arrowstartx + [1, 0, 0]
arrowendy = arrowstarty + [0, 1, 0]
arrowendt = arrowstartt + [0, 0, 1]
ax.quiver(arrowstartx, arrowstarty, arrowstartt, arrowendx, arrowendy, arrowendt,2, color=arrowcolor, linewidth=1)
# ax.set_xlabel('x')
# ax.set_ylabel('y')
# ax.set_zlabe('z')
# ax.arrow()
''' draw bar as a cylinder '''
if True:
# draw bar
xpos = 0.
ypos = 30.
dx = 1.4
dy = 2
ax.bar3d(xpos, ypos, 0, dx, dy, ZMAX, color='g', zsort='average')
#ax.bar3d(xpos, ypos, 0, dx, dy, ZMAX, alpha=0.8, color='g',zsort='average')
''' draw two lines'''
if True:
# the blue line
y = np.arange(0, 50, 1)
x = np.ones(len(y)) * (-2)
z = np.linspace(0, ZMAX, len(y))
ax.plot(x, y, z, 'b')
#ax.plot(x, y, z, 'b',alpha=0.8)
# the red line
y = np.arange(0, 50, 1)
x = np.ones(len(y)) * 2
z = np.linspace(0, ZMAX, len(y))
ax.plot(x, y, z, 'r')
plt.axis('off')
ax.legend()
plt.show()
I'm trying to plot a 3D Decision Boundary, but it does not seem to be working the way it looks, see how it is:
I want it to appear as in this example here:
I do not know how to explain, but in the example above it literally looks like a "wall". And this is what I want to do in my code.
Then follow my code:
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_title('Hello World')
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
ax.set_zlim(-1, 1)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
w = [3,2,1]
x = 1
y = 1
z = 1
x_plan = (- w[1] * y - w[2] * z) / w[0]
y_plan = (- w[0] * x - w[2] * z) / w[1]
z_plan = (- w[0] * x - w[1] * y) / w[2]
ax.plot3D([x_plan, 1, 1], [1, y_plan, 1], [1, 1, z_plan], "lightblue")
plt.show()
P.S.: I'm using:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
I believe that the problem should be in the calculation, or else in the:
ax.plot3D([x_plan, 1, 1], [1, y_plan, 1], [1, 1, z_plan], "lightblue")
P.S.2: I know that my Boundary Decision is not separating the data correctly, but at the moment this is a detail for me, later I will fix it.
To plot a 3d surface you actually need to use plt3d.plot_surface, see reference.
As an example, this piece of code will generate the following image (Notice the comment on plt3d.plot_surface line):
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
def randrange(n, vmin, vmax):
'''
Helper function to make an array of random numbers having shape (n, )
with each number distributed Uniform(vmin, vmax).
'''
return (vmax - vmin)*np.random.rand(n) + vmin
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
n = 10
for c, m, zlow, zhigh in [('r', 'o', 0, 100)]:
xs = randrange(n, 0, 50)
ys = randrange(n, 0, 50)
zs = randrange(n, zlow, zhigh)
ax.scatter(xs, ys, zs, c=c, marker=m)
for c, m, zlow, zhigh in [('b', '^', 0, 100)]:
xs = randrange(n, 60, 100)
ys = randrange(n, 60, 100)
zs = randrange(n, zlow, zhigh)
ax.scatter(xs, ys, zs, c=c, marker=m)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
xm,ym = np.meshgrid(xs, ys)
ax.plot_surface(xm, ym, xm, color='green', alpha=0.5) # Data values as 2D arrays as stated in reference - The first 3 arguments is what you need to change in order to turn your plane into a boundary decision plane.
plt.show()
I draw a plane and a line crossing the plane.
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
def plot_x_axis(ax):
x = np.array([-1, 1])
y = np.array([0, 0])
z = np.array([0, 0])
ax.plot(x, y, z, color='green')
def plot_yz_plane(ax):
a = np.array([0, 1, 0])
b = np.array([0, 0, 1])
U, V = np.meshgrid(np.linspace(-0.5, 0.5, 3), np.linspace(-0.5, 0.5, 3))
x = a[0] * U + b[0] * V
y = a[1] * U + b[1] * V
z = a[2] * U + b[2] * V
surf = ax.plot_surface(x, y, z, rstride=1, cstride=1, alpha=1.0, color='red')
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
plot_x_axis(ax)
plot_yz_plane(ax)
plt.show()
I expect that a part of this line (placed behind the plane) will be covered by the plane, but actually matplotlib shows all the objects as if the plane is transparent. How to fix this problem?