How to Animate Matplotlib 3D Plots in Python
In this tutorial, you’ll learn various methods to animate different types of 3D plots using Matplotlib and Python.
To get started, you’ll need to import the necessary libraries:
import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation from mpl_toolkits.mplot3d import Axes3D
This code imports NumPy for numerical operations, Matplotlib for plotting, FuncAnimation for creating animations, and Axes3D for 3D plotting capabilities.
Rotate 3D surface plot
You can create a rotating 3D surface plot to showcase different angles of your data:
def generate_surface(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 = generate_surface(X, Y) fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, projection='3d') surf = ax.plot_surface(X, Y, Z, cmap='viridis') def rotate(frame): ax.view_init(elev=10, azim=frame) return surf, ani = FuncAnimation(fig, rotate, frames=np.linspace(0, 360, 100), interval=50, blit=False) plt.show()
This code creates a 3D surface plot of a sine function and animates it by rotating the view around the z-axis.
The rotate
function updates the viewing angle for each frame, creating a smooth rotation effect.
You can also create a video from the animated plot and this goes for any of the coming examples.
Update 3D scatter plot data
You can animate a 3D scatter plot by updating the data points in each frame:
fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, projection='3d') n_points = 100 scatter = ax.scatter([], [], []) def update_scatter(frame): x = np.random.normal(0, 1, n_points) y = np.random.normal(0, 1, n_points) z = np.random.normal(0, 1, n_points) scatter._offsets3d = (x, y, z) return scatter, ani = FuncAnimation(fig, update_scatter, frames=100, interval=50, blit=False) plt.show()
The update_scatter
function updates the positions of the scatter points, giving the illusion of movement.
Animate 3D line plot
To create an animated 3D line plot, you can update the line data in each frame:
fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, projection='3d') line, = ax.plot([], [], []) def update_line(frame): t = np.linspace(0, 10, 1000) x = np.sin(t + frame/10) y = np.cos(t + frame/10) z = t line.set_data(x, y) line.set_3d_properties(z) return line, ani = FuncAnimation(fig, update_line, frames=100, interval=50, blit=False) plt.show()
The update_line
function calculates new x, y, and z coordinates for each frame, updating the line’s position.
Animate 3D bar chart
You can create an animated 3D bar chart by updating the heights of the bars in each frame:
fig = plt.figure() ax = fig.add_subplot(111, projection='3d') x = np.arange(5) y = np.arange(5) x, y = np.meshgrid(x, y) x = x.flatten() y = y.flatten() z = np.zeros_like(x) dx = dy = 0.8 dz = np.random.rand(25) bars = ax.bar3d(x, y, z, dx, dy, dz, shade=True) # Function to update the bars def update_bars(frame): new_dz = np.random.rand(25) ax.clear() ax.bar3d(x, y, z, dx, dy, new_dz, shade=True) ani = FuncAnimation(fig, update_bars, frames=100, interval=100) plt.show()
The update_bars
function generates new heights for each bar and redraws the entire chart in each frame.
Evolving 3D contour plot
To create an evolving 3D contour plot, you can update the contour data in each frame:
fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, projection='3d') x = np.linspace(-5, 5, 100) y = np.linspace(-5, 5, 100) X, Y = np.meshgrid(x, y) contour = ax.contour3D(X, Y, np.zeros_like(X)) def update_contour(frame): Z = np.sin(np.sqrt(X**2 + Y**2) - frame/10) ax.clear() ax.contour3D(X, Y, Z, 50, cmap='viridis') ax.set_zlim(-1, 1) ani = FuncAnimation(fig, update_contour, frames=100, interval=50) plt.show()
The update_contour
function calculates new Z values for each frame and redraws the contour plot.
Animated 3D Vector Field
You can create an animated 3D vector field by updating the vectors in each frame:
fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, projection='3d') x, y, z = np.meshgrid(np.arange(-2, 3), np.arange(-2, 3), np.arange(-2, 3)) quiver = ax.quiver(x, y, z, np.zeros_like(x), np.zeros_like(y), np.zeros_like(z), length=0.5, normalize=True) def update_quiver(frame): global quiver # Remove the old quiver quiver.remove() # Calculate new vector components u = np.sin(x + frame / 10) v = np.cos(y + frame / 10) w = np.sin(z + frame / 10) # Create a new quiver quiver = ax.quiver(x, y, z, u, v, w, length=0.5, normalize=True) return quiver, ani = FuncAnimation(fig, update_quiver, frames=100, interval=50, blit=False) plt.show()
The update_quiver
function calculates new vector components for each frame and redraws the entire vector field.
Growing 3D Network Graph
To create a growing 3D network graph, you can add nodes and edges in each frame:
import networkx as nx fig = plt.figure() ax = fig.add_subplot(111, projection='3d') G = nx.Graph() num_nodes = 20 for i in range(num_nodes): G.add_node(i) def update_graph(num): ax.clear() ax.set_title('3D Growing Network Graph') # Add edges randomly if num > 0: for _ in range(2): # Add two edges per frame n1, n2 = np.random.choice(num_nodes, 2, replace=False) G.add_edge(n1, n2) # Get node positions pos = {i: (np.random.rand(), np.random.rand(), np.random.rand()) for i in range(num_nodes)} xs, ys, zs = zip(*pos.values()) ax.scatter(xs, ys, zs, s=50, c='blue', alpha=0.6) for edge in G.edges(): x = [pos[edge[0]][0], pos[edge[1]][0]] y = [pos[edge[0]][1], pos[edge[1]][1]] z = [pos[edge[0]][2], pos[edge[1]][2]] ax.plot(x, y, z, c='black', alpha=0.4) ax.set_xlim([0, 1]) ax.set_ylim([0, 1]) ax.set_zlim([0, 1]) ani = FuncAnimation(fig, update_graph, frames=range(num_nodes), interval=500, repeat=False) plt.show()
The update_graph
function adds new nodes and edges in each frame and puts them randomly in 3D space.
Animate Highlighting Certain Points
You can create an animation that highlights specific points or regions in a 3D plot:
fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, projection='3d') x = np.random.rand(100) * 4 - 2 y = np.random.rand(100) * 4 - 2 z = np.random.rand(100) * 4 - 2 scatter = ax.scatter(x, y, z, c='blue', s=50) highlight = ax.scatter([], [], [], c='red', s=100) def update_highlight(frame): center = np.array([np.sin(frame/10), np.cos(frame/10), np.sin(frame/5)]) distances = np.sqrt(np.sum((np.array([x, y, z]).T - center)**2, axis=1)) highlighted = distances < 0.5 highlight._offsets3d = (x[highlighted], y[highlighted], z[highlighted]) return highlight, ani = FuncAnimation(fig, update_highlight, frames=100, interval=50, blit=False) plt.show()
The update_highlight
function calculates the distance of each point from a moving center and highlights points within a certain radius.
Mokhtar is the founder of LikeGeeks.com. He is a seasoned technologist and accomplished author, with expertise in Linux system administration and Python development. Since 2010, Mokhtar has built an impressive career, transitioning from system administration to Python development in 2015. His work spans large corporations to freelance clients around the globe. Alongside his technical work, Mokhtar has authored some insightful books in his field. Known for his innovative solutions, meticulous attention to detail, and high-quality work, Mokhtar continually seeks new challenges within the dynamic field of technology.