Creating Animations with Matplotlib | Computational Mechanics Visualization | Skill-Lync Resources

50% OFF - Ends Soon!

Lesson 8 of 11 20 min

Creating Animations with Matplotlib

Matplotlib is the workhorse of Python visualization. With its animation module, you can create professional CAE visualizations that rotate, update, and reveal insights.

Setup

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import Axes3D

Ensure you have a backend that supports animation saving:

pip install pillow  # For GIF output
# or
pip install ffmpeg-python  # For MP4/MOV output

Basic Animation Structure

# Create figure
fig = plt.figure(figsize=(8, 8), facecolor='black')
ax = fig.add_subplot(111, projection='3d', facecolor='black')

# Animation callback - called for each frame
def animate(frame):
    ax.cla()  # Clear previous frame
    ax.view_init(elev=20, azim=frame * 3)  # Rotate view

    # Draw your visualization
    # ...

    return []

# Create animation object
anim = animation.FuncAnimation(
    fig,           # Figure to animate
    animate,       # Callback function
    frames=120,    # Number of frames
    interval=50,   # ms between frames
    blit=False     # Full redraw each frame
)

# Save
anim.save('output.gif', writer='pillow', fps=30)
# Or: anim.save('output.mp4', writer='ffmpeg', fps=30)

Full Example: Stress Tensor on Sphere

Here's a complete script for visualizing stress tensor components:

Sponsored

Srinithin now works at Xitadel as Design Engineer

Mechanical engineering graduate turned automotive designer

See His Journey
"""
Stress Tensor Visualization - Complete Tutorial
Automotive Application: B-pillar stress during NCAP side impact
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

# =============================================================================
# CONFIGURATION
# =============================================================================

# Stress tensor (MPa) - typical B-pillar values
SIGMA = np.array([
    [450, 75, 0],
    [75, 280, 45],
    [0, 45, 120]
])

RADIUS = 0.5
DPI = 150
FRAMES = 120

# =============================================================================
# HELPER FUNCTIONS
# =============================================================================

def create_sphere(radius, resolution=30):
    """Create sphere surface using parametric coordinates."""
    u = np.linspace(0, 2*np.pi, resolution)
    v = np.linspace(0, np.pi, resolution//2)
    u, v = np.meshgrid(u, v)

    x = radius * np.cos(u) * np.sin(v)
    y = radius * np.sin(u) * np.sin(v)
    z = radius * np.cos(v)

    return x, y, z

def fibonacci_sphere(n_points, radius):
    """Generate evenly-distributed points on sphere."""
    points = []
    golden = (1 + np.sqrt(5)) / 2

    for i in range(n_points):
        theta = 2 * np.pi * i / golden
        phi = np.arccos(1 - 2*(i+0.5)/n_points)
        x = radius * np.sin(phi) * np.cos(theta)
        y = radius * np.sin(phi) * np.sin(theta)
        z = radius * np.cos(phi)
        points.append([x, y, z])

    return np.array(points)

def compute_traction(sigma, normal):
    """Cauchy's formula: t = sigma @ n"""
    return sigma @ normal

# =============================================================================
# MAIN ANIMATION
# =============================================================================

# Create geometry
sphere_x, sphere_y, sphere_z = create_sphere(RADIUS)
sample_points = fibonacci_sphere(26, RADIUS)
normals = sample_points / np.linalg.norm(sample_points, axis=1, keepdims=True)
tractions = np.array([compute_traction(SIGMA, n) for n in normals])

# Scale vectors for visualization
traction_scale = 0.15 / np.max(np.linalg.norm(tractions, axis=1))

# Create figure
fig = plt.figure(figsize=(8, 8), dpi=DPI, facecolor='black')
ax = fig.add_subplot(111, projection='3d', facecolor='black')

def animate(frame):
    ax.cla()

    # Rotate view
    ax.view_init(elev=20, azim=-60 + frame*3)

    # Draw sphere surface
    ax.plot_surface(
        sphere_x, sphere_y, sphere_z,
        alpha=0.2, color='white', linewidth=0
    )

    # Draw normal vectors (red)
    for i in range(len(sample_points)):
        ax.quiver(
            sample_points[i,0], sample_points[i,1], sample_points[i,2],
            normals[i,0]*0.15, normals[i,1]*0.15, normals[i,2]*0.15,
            color='red', arrow_length_ratio=0.2
        )

    # Draw traction vectors (cyan)
    for i in range(len(sample_points)):
        ax.quiver(
            sample_points[i,0], sample_points[i,1], sample_points[i,2],
            tractions[i,0]*traction_scale,
            tractions[i,1]*traction_scale,
            tractions[i,2]*traction_scale,
            color='cyan', arrow_length_ratio=0.15
        )

    # Axis settings
    limit = RADIUS * 1.5
    ax.set_xlim(-limit, limit)
    ax.set_ylim(-limit, limit)
    ax.set_zlim(-limit, limit)
    ax.set_box_aspect([1, 1, 1])
    ax.set_axis_off()

    ax.set_title(
        'Stress Tensor on Infinitesimal Sphere\nB-Pillar During Side Impact',
        color='white', fontsize=12
    )

    return []

# Create and save animation
print("Creating animation...")
anim = animation.FuncAnimation(fig, animate, frames=FRAMES, interval=50)
anim.save('stress_sphere.gif', writer='pillow', fps=30)
print("Saved stress_sphere.gif")

plt.close()
🎯 3,000+ Engineers Placed
Sponsored
Harshal Sukenkar

Harshal

Fiat Chrysler

Abhishek

Abhishek

TATA ELXSI

Srinithin

Srinithin

Xitadel

Ranjith

Ranjith

Core Automotive

Gaurav Jadhav

Gaurav

Automotive Company

Bino K Biju

Bino

Design Firm

Aseem Shrivastava

Aseem

EV Company

Puneet

Puneet

Automotive Company

Vishal Kumar

Vishal

EV Startup

Exercises

Exercise 1: Add Coordinate Axes

Add labeled coordinate axes (x₁, x₂, x₃) to the visualization using ax.quiver() and ax.text().

Exercise 2: Stress Component Toggle

Modify the script to visualize individual stress components (σ₁₁, σ₂₂, etc.) one at a time.

Exercise 3: Color by Magnitude

Color the traction vectors based on their magnitude using a colormap:

Sponsored

April batch closing soon — only 42 seats remaining

Join 3,000+ engineers who got placed at top companies

Reserve Your Seat
from matplotlib.colors import Normalize
from matplotlib.cm import ScalarMappable

norm = Normalize(vmin=0, vmax=max_magnitude)
cmap = plt.cm.plasma
colors = cmap(norm(magnitudes))

Output Formats

FormatWriterQualityFile SizeUse Case
GIFpillowMediumLargeWeb, presentations
MP4ffmpegHighSmallVideo, email
MOVffmpegHighMediumMac presentations

Key Takeaways

  • Use FuncAnimation for animated visualizations
  • The animate() callback is called once per frame
  • Clear axes with ax.cla() before each frame
  • view_init(elev, azim) controls the 3D viewing angle
  • Save with pillow for GIF, ffmpeg for video

What's Next

In the next lesson, we'll create mathematical animations with Manim — the library that powers 3Blue1Brown videos.

3,000+ Engineers Placed in Top Companies
Career Growth

3,000+ Engineers Placed in Top Companies

Join the ranks of successful engineers at Bosch, Tata, L&T, and 500+ hiring partners.