I found a tutorial online for this matplotlib and numpy graph. The code runs smoothly, but there is no output. I have tried to save the graph as a file, but that does not seem to work.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
fig = plt.figure()
ax = plt.axes(projection="3d")
zline = np.linspace(0, 15, 1000)
xline = np.sin(zline)
yline = np.cos(zline)
ax.plot3D(xline, yline, zline, "gray") # Data for three-dimensional scattered points
zdata = 15 * np.random.random(100)
xdata = np.sin(zdata) + 0.1 * np.random.randn(100)
ydata = np.cos(zdata) + 0.1 * np.random.randn(100)
ax.scatter3D(xdata, ydata, zdata, c=zdata, cmap="Greens");
def f(x, y):
return np.sin(np.sqrt(x ** 2 + y ** 2))
x = np.linspace(-6, 6, 30)
y = np.linspace(-6, 6, 30)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.contour3D(X, Y, Z, 50, cmap='binary')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z');
theta = 2 * np.pi * np.random.random(1000)
r = 6 * np.random.random(1000)
x = np.ravel(r * np.sin(theta))
y = np.ravel(r * np.cos(theta))
z = f(x, y)
ax = plt.axes(projection="3d")
ax.plot_trisurf(x, y, z,cmap="viridis", edgecolor="none");
The link to the website is https://www.edureka.co/blog/python-projects/. Surely there is some way to access the graphical user interface to display the plots?
Adding plt.show() at the end will display both of the graphs.
Related
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 have a polar contour plot, and I want to add cartesian axes to it. How can I do this? There seems to be no documentation for this.
import numpy as np
import matplotlib.pyplot as plt
def f(x, y):
return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
x = np.linspace(0, 8, 50)
y = np.linspace(0, 8, 40)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
fig, ax = plt.subplots(subplot_kw = dict(projection = 'polar'))
plt.axis('off')
ax.contourf(X, Y, Z)
To add cartesian axes to a polar plot, all you have to do is add a second pair of axes at the same position like so:
import numpy as np
import matplotlib.pyplot as plt
def f(x, y):
return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
x = np.linspace(0, 8, 50)
y = np.linspace(0, 8, 40)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
fig, ax = plt.subplots(subplot_kw = dict(projection = 'polar'))
plt.axis('off')
ax.contourf(X, Y, Z)
new_axis = fig.add_axes(ax.get_position(), frameon = False)
new_axis.plot()
plt.show()
The idea is to plot the following vector field:
I have two main issue with it:
1) I do not know how to make sure that the arrows are not too long (I know I have to use length, but how?).
2) I am told to use Numpyto draw the vector field but again, how?
This is what I have tried:
# The components of the vector field
F_x = y*e**x
F_y = x**2 + e**x
F_z = z**2*e**z
# The grid
xf = np.linspace(-0.15, 2.25, 8)
yf = np.linspace(-0.15, 2.25, 8)
zf = np.linspace(-0.75, 2.50, 8)
X_grid, Y_grid, Z_grid = np.meshgrid(xf, yf, zf)
# The arrows; how to deal with them?
dx = 1
#dy = ...
#dz = ...
# Standardize the arrows; In this way all arrows have the same length.
length = np.sqrt(dx**2 + dy**2 + dz**2)
dx_N = dx/length
dy_N = dy/length
dz_N = dz/length
#how to involve numpy in the process??
# Drawing the figure
fig, ax = plt.subplots(1, 1)
ax.quiver(X_grid, Y_grid, Z_grid, dx_N, dy_N, dz_N, dy, dz, cmap=plt.get_cmap('gnuplot2'))
plt.show()
Thanks
EDIT
Based on the provided link I tried:
from sympy import *
x,y,z = sp.symbols('x y z', real = True)
import matplotlib.pyplot as plt
x, y, z = np.meshgrid(np.arange(0, 2 * np.pi, .2), np.arange(0, 2 * np.pi, .2), np.arange(0, 2 * np.pi, .2))
F_x = y * exp(x)
F_y = x**2 + exp(x)
F_z = z**2 * exp(z)
# Normalize the arrows:
F_x = F_x / np.sqrt(F_x**2 + F_y**2 + F_z**2)
F_y = F_y / np.sqrt(F_x**2 + F_y**2 + F_z**2)
F_z = F_z / np.sqrt(F_x**2 + F_y**2 + F_z**2)
plt.figure()
plt.title('Vector field')
Q = plt.quiver(x, y, z, F_x, F_y, F_z, units='width')
qk = plt.quiverkey(Q, 0.9, 0.9, 2, r'$2 \frac{m}{s}$', labelpos='E',
coordinates='figure')#I don't understand this line
The TypeError: Shape should contain integers only comes up.
The problem is that I don't understand this part of the code:
qk = plt.quiverkey(Q, 0.9, 0.9, 2, r'$2 \frac{m}{s}$', labelpos='E',
coordinates='figure')
I am still stuck on how to plot this vector field
Assume that you want a 3D quiver, you can check out the matplotlib tutorial on quiver3D. And to control the arrow size, check out the Axes3d.quiver library doc, especially the parameters.
A quick snippet:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
x, y, z = np.meshgrid(np.arange(0, 2*np.pi, .5), np.arange(0, 2*np.pi, .5), np.arange(0, 2*np.pi, .5))
F_x = y * np.exp(x)
F_y = x**2 + np.exp(x)
F_z = z**2 * np.exp(z)
fig = plt.figure()
ax = fig.gca(projection='3d')
Q = ax.quiver(x, y, z, F_x, F_y, F_z, length=0.3, normalize=True)
But 3d quiver plot can be very crowded! : )
The quiver() method is a great tool to render vector fields. Since Matplotlib is a two-dimensional plotting library, we need to import the mplot3d toolkit to generate a three-dimensional plot.
Here's a good example:
Dependencies:
Axes3D for 3D rendering
Pyplot to get a MATLAB-like plotting framework
Numpy for numeric-array manipulation
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
x, y, z = np.meshgrid(np.arange(-0.8, 1, 0.25),
np.arange(-0.8, 1, 0.25),
np.arange(-0.8, 1, 0.8))
u = np.sin(np.pi * x) * np.cos(np.pi * y) * np.cos(np.pi * z)
v = -np.cos(np.pi * x) * np.sin(np.pi * y) * np.cos(np.pi * z)
w = (np.sqrt(2.0 / 3.0) * np.cos(np.pi * x) * np.cos(np.pi * y) * np.sin(np.pi * z))
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.quiver(x, y, z, u, v, w,
length=0.15,
color='Purple'
)
ax.view_init(elev=10, azim=30)
ax.dist=8
plt.show()
I am trying to use matplotlib.animation to animate the time evolution of a surface. A working example is found on this stackexchange question/answer. Using plt.show() I can see the animation fine. The problem is when I try to save it. When saving as either a gif or mp4 I get only one from of the animation. I do not get this problem if I am doing 1d animations, for example using plt.plot(). Below is what I am trying:
from mpl_toolkits.mplot3d import axes3d
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import cm
def generate(X, Y, phi):
R = 1 - np.sqrt(X**2 + Y**2)
return np.cos(2 * np.pi * X + phi) * R
fig = plt.figure()
ax = axes3d.Axes3D(fig)
xs = np.linspace(-1, 1, 50)
ys = np.linspace(-1, 1, 50)
X, Y = np.meshgrid(xs, ys)
Z = generate(X, Y, 0.0)
wframe = ax.plot_surface(X, Y, Z, rstride=2, cstride=2, cmap=cm.coolwarm )
ax.set_zlim(-1,1)
def update(i, ax, fig):
ax.cla()
phi = i * 360 / 2 / np.pi / 100
Z = generate(X, Y, phi)
wframe = ax.plot_surface( X, Y, Z, rstride=2,
cstride=2, cmap=cm.coolwarm )
ax.set_zlim(-1,1)
return wframe,
ani = animation.FuncAnimation( fig, update, frames=10,
fargs=(ax, fig), interval=100 )
ani.save('plottest3d2.mp4', fps=30)
ani.save('plottest3d3.gif', fps=30, writer='imagemagick')
plt.show()
Any help explaining the discrepancy between showing the plot and saving would be great.
I plot figures in a for loop which is a loop for my time, basically at each time step I plot a surf out of my data as below:
for time_step in range(0,nt):
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = np.arange(xmin, xmax+dx, dx)
z = np.arange(zmin, zmax+dz, dz)
X, Z = np.meshgrid(x, z)
ax.plot_surface(X, Z, w1[time_step])
plt.show()
Suppose that w1[time_step] changes in the loop and is sth different at each time step, all other assumptions you can have. I plot but don't know only how to make them into a video.
I have done it matlab, but I want to do sth similar in Python
Matplotlib as some animation features you might want to use. Check the following recipe (that I collected from here):
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
import time
def generate(X, Y, phi):
R = 1 - np.sqrt(X**2 + Y**2)
return np.cos(2 * np.pi * X + phi) * R
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
xs = np.linspace(-1, 1, 50)
ys = np.linspace(-1, 1, 50)
X, Y = np.meshgrid(xs, ys)
Z = generate(X, Y, 0.0)
wframe = None
tstart = time.time()
for phi in np.linspace(0, 360 / 2 / np.pi, 100):
oldcol = wframe
Z = generate(X, Y, phi)
wframe = ax.plot_wireframe(X, Y, Z, rstride=2, cstride=2)
# Remove old line collection before drawing
if oldcol is not None:
ax.collections.remove(oldcol)
plt.pause(.001)
print('FPS: %f' % (100 / (time.time() - tstart)))
Just replace the wireframe plot for whatever you want (and also use your data obviously) and you should have what you are looking for.