Axes Method - contourf¶
The contourf method creates filled contour plots, where regions between contour levels are filled with colors. This is in contrast to contour which only draws contour lines.
Basic Usage¶
Create filled contour plots from meshgrid data.
1. Simple Filled Contour¶
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
X, Y = np.meshgrid(x, y)
Z = np.exp(-(X**2 + Y**2))
fig, ax = plt.subplots()
ax.contourf(X, Y, Z)
plt.show()
2. With Colorbar¶
fig, ax = plt.subplots()
cf = ax.contourf(X, Y, Z)
plt.colorbar(cf, ax=ax)
plt.show()
3. With Labels¶
fig, ax = plt.subplots()
cf = ax.contourf(X, Y, Z)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('Gaussian: $e^{-(x^2+y^2)}$')
plt.colorbar(cf, ax=ax, label='Value')
plt.show()
contour vs contourf¶
Compare line contours with filled contours.
Side-by-Side Comparison¶
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# Line contours
axes[0].contour(X, Y, Z)
axes[0].set_title('contour (lines only)')
# Filled contours
cf = axes[1].contourf(X, Y, Z)
axes[1].set_title('contourf (filled)')
plt.colorbar(cf, ax=axes[1])
plt.tight_layout()
plt.show()
Combined contour and contourf¶
fig, ax = plt.subplots(figsize=(8, 6))
# Filled contours as background
cf = ax.contourf(X, Y, Z, cmap='Blues')
# Line contours on top
cs = ax.contour(X, Y, Z, colors='black', linewidths=0.5)
ax.clabel(cs, inline=True, fontsize=8)
plt.colorbar(cf, ax=ax)
ax.set_title('Filled Contours with Line Overlay')
plt.show()
Number of Levels¶
Control the number of contour levels.
1. Default Levels¶
fig, ax = plt.subplots()
cf = ax.contourf(X, Y, Z)
ax.set_title('Default Levels')
plt.colorbar(cf, ax=ax)
plt.show()
2. Specify Number of Levels¶
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
levels_list = [5, 10, 20]
for ax, n in zip(axes, levels_list):
cf = ax.contourf(X, Y, Z, levels=n)
ax.set_title(f'levels={n}')
plt.colorbar(cf, ax=ax)
plt.tight_layout()
plt.show()
3. Explicit Level Values¶
fig, ax = plt.subplots()
levels = [0, 0.1, 0.2, 0.4, 0.6, 0.8, 1.0]
cf = ax.contourf(X, Y, Z, levels=levels)
ax.set_title('Custom Level Values')
plt.colorbar(cf, ax=ax, ticks=levels)
plt.show()
4. Non-Uniform Levels¶
fig, ax = plt.subplots()
# More resolution at higher values
levels = [0, 0.05, 0.1, 0.2, 0.5, 0.7, 0.9, 1.0]
cf = ax.contourf(X, Y, Z, levels=levels)
ax.set_title('Non-Uniform Levels')
plt.colorbar(cf, ax=ax)
plt.show()
Colormap Options¶
Apply different colormaps to filled contours.
1. Sequential Colormaps¶
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
cmaps = ['viridis', 'plasma', 'inferno']
for ax, cmap in zip(axes, cmaps):
cf = ax.contourf(X, Y, Z, cmap=cmap)
ax.set_title(f"cmap='{cmap}'")
plt.colorbar(cf, ax=ax)
plt.tight_layout()
plt.show()
2. Diverging Colormaps¶
Z_div = np.sin(X) * np.cos(Y)
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
cmaps = ['coolwarm', 'RdBu', 'seismic']
for ax, cmap in zip(axes, cmaps):
cf = ax.contourf(X, Y, Z_div, cmap=cmap)
ax.set_title(f"cmap='{cmap}'")
plt.colorbar(cf, ax=ax)
plt.tight_layout()
plt.show()
3. Perceptually Uniform¶
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
cmaps = ['cividis', 'magma', 'YlOrRd']
for ax, cmap in zip(axes, cmaps):
cf = ax.contourf(X, Y, Z, cmap=cmap)
ax.set_title(f"cmap='{cmap}'")
plt.colorbar(cf, ax=ax)
plt.tight_layout()
plt.show()
Alpha Transparency¶
Control the transparency of filled regions.
1. Opaque Fill¶
fig, ax = plt.subplots()
cf = ax.contourf(X, Y, Z, alpha=1.0)
ax.set_title('alpha=1.0 (opaque)')
plt.colorbar(cf, ax=ax)
plt.show()
2. Semi-Transparent Fill¶
fig, ax = plt.subplots()
cf = ax.contourf(X, Y, Z, alpha=0.7)
ax.set_title('alpha=0.7')
plt.colorbar(cf, ax=ax)
plt.show()
3. Alpha Comparison¶
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
alphas = [1.0, 0.6, 0.3]
for ax, alpha in zip(axes, alphas):
cf = ax.contourf(X, Y, Z, alpha=alpha)
ax.set_title(f'alpha={alpha}')
plt.colorbar(cf, ax=ax)
plt.tight_layout()
plt.show()
Extend Option¶
Handle values outside the specified level range.
1. extend='neither'¶
fig, ax = plt.subplots()
levels = [0.2, 0.4, 0.6, 0.8]
cf = ax.contourf(X, Y, Z, levels=levels, extend='neither')
ax.set_title("extend='neither'")
plt.colorbar(cf, ax=ax)
plt.show()
2. extend='both'¶
fig, ax = plt.subplots()
cf = ax.contourf(X, Y, Z, levels=levels, extend='both')
ax.set_title("extend='both'")
plt.colorbar(cf, ax=ax)
plt.show()
3. Extend Comparison¶
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
extends = ['neither', 'min', 'max', 'both']
levels = [0.2, 0.4, 0.6, 0.8]
for ax, extend in zip(axes.flat, extends):
cf = ax.contourf(X, Y, Z, levels=levels, extend=extend)
ax.set_title(f"extend='{extend}'")
plt.colorbar(cf, ax=ax)
plt.tight_layout()
plt.show()
Mathematical Functions¶
Visualize various mathematical functions.
1. Bivariate Normal PDF¶
def bivariate_normal(X, Y, mu_x=0, mu_y=0, sigma_x=1, sigma_y=1, rho=0):
z = ((X - mu_x) / sigma_x)**2 - 2 * rho * (X - mu_x) * (Y - mu_y) / (sigma_x * sigma_y) + ((Y - mu_y) / sigma_y)**2
return np.exp(-z / (2 * (1 - rho**2))) / (2 * np.pi * sigma_x * sigma_y * np.sqrt(1 - rho**2))
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
X, Y = np.meshgrid(x, y)
Z = bivariate_normal(X, Y, rho=0.5)
fig, ax = plt.subplots(figsize=(8, 6))
cf = ax.contourf(X, Y, Z, levels=20, cmap='Blues')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('Bivariate Normal (ρ=0.5)')
ax.set_aspect('equal')
plt.colorbar(cf, ax=ax, label='Density')
plt.show()
2. Saddle Function¶
Z = X**2 - Y**2
fig, ax = plt.subplots(figsize=(8, 6))
cf = ax.contourf(X, Y, Z, levels=20, cmap='coolwarm')
cs = ax.contour(X, Y, Z, levels=20, colors='black', linewidths=0.3)
ax.set_title('Saddle: $z = x^2 - y^2$')
ax.set_aspect('equal')
plt.colorbar(cf, ax=ax)
plt.show()
3. Sinusoidal Surface¶
Z = np.sin(X) * np.cos(Y)
fig, ax = plt.subplots(figsize=(8, 6))
cf = ax.contourf(X, Y, Z, levels=20, cmap='RdBu')
ax.set_title('$z = \\sin(x)\\cos(y)$')
ax.set_aspect('equal')
plt.colorbar(cf, ax=ax)
plt.show()
4. Function Gallery¶
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
functions = [
(np.exp(-(X**2 + Y**2)), 'Gaussian', 'viridis'),
(X**2 - Y**2, 'Saddle', 'coolwarm'),
(np.sin(X) * np.cos(Y), 'sin(x)cos(y)', 'RdBu'),
(np.sin(np.sqrt(X**2 + Y**2)), 'Ripple', 'plasma')
]
for ax, (Z, title, cmap) in zip(axes.flat, functions):
cf = ax.contourf(X, Y, Z, levels=15, cmap=cmap)
ax.set_title(title)
ax.set_aspect('equal')
plt.colorbar(cf, ax=ax)
plt.tight_layout()
plt.show()
Correlation Comparison¶
Visualize bivariate normal distributions with different correlations.
from scipy import stats
rhos = [-0.8, 0, 0.8]
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
X, Y = np.meshgrid(x, y)
pos = np.dstack((X, Y))
for ax, rho in zip(axes, rhos):
rv = stats.multivariate_normal([0, 0], [[1, rho], [rho, 1]])
Z = rv.pdf(pos)
cf = ax.contourf(X, Y, Z, levels=15, cmap='Blues')
ax.set_title(f'ρ = {rho}')
ax.set_aspect('equal')
plt.colorbar(cf, ax=ax)
plt.tight_layout()
plt.show()
Hatching Patterns¶
Add hatching patterns to filled regions.
1. Basic Hatching¶
fig, ax = plt.subplots()
cf = ax.contourf(X, Y, Z, levels=5, hatches=['', '/', '\\', '//', '\\\\'])
ax.set_title('Contourf with Hatching')
plt.colorbar(cf, ax=ax)
plt.show()
2. Hatching Styles¶
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
hatch_patterns = [
['', '/', '//', '///', '////'],
['', '.', '..', 'o', 'O'],
['', '-', '--', '+', 'x']
]
for ax, hatches in zip(axes, hatch_patterns):
cf = ax.contourf(X, Y, Z, levels=5, hatches=hatches, cmap='Greys', alpha=0.5)
ax.set_title(f'hatches={hatches}')
plt.tight_layout()
plt.show()
Colorbar Customization¶
1. Horizontal Colorbar¶
fig, ax = plt.subplots()
cf = ax.contourf(X, Y, Z, levels=10, cmap='viridis')
plt.colorbar(cf, ax=ax, orientation='horizontal', label='Value')
plt.show()
2. Custom Ticks¶
fig, ax = plt.subplots()
levels = np.linspace(0, 1, 11)
cf = ax.contourf(X, Y, Z, levels=levels, cmap='viridis')
cbar = plt.colorbar(cf, ax=ax, ticks=[0, 0.25, 0.5, 0.75, 1.0])
cbar.set_label('Intensity')
plt.show()
3. Discrete Colorbar¶
fig, ax = plt.subplots()
levels = [0, 0.2, 0.4, 0.6, 0.8, 1.0]
cf = ax.contourf(X, Y, Z, levels=levels, cmap='RdYlGn')
cbar = plt.colorbar(cf, ax=ax, ticks=levels)
cbar.set_ticklabels(['Very Low', 'Low', 'Medium', 'High', 'Very High', ''])
plt.show()
Full Customization¶
1. Complete Example¶
x = np.linspace(-4, 4, 150)
y = np.linspace(-4, 4, 150)
X, Y = np.meshgrid(x, y)
Z = np.exp(-(X**2 + Y**2) / 2) / (2 * np.pi)
fig, ax = plt.subplots(figsize=(9, 7))
cf = ax.contourf(X, Y, Z, levels=20, cmap='Blues')
cs = ax.contour(X, Y, Z, levels=10, colors='navy', linewidths=0.5, alpha=0.7)
ax.clabel(cs, inline=True, fontsize=8, fmt='%.3f')
ax.set_xlabel('$x$', fontsize=12)
ax.set_ylabel('$y$', fontsize=12)
ax.set_title('Standard Bivariate Normal PDF', fontsize=14)
ax.set_aspect('equal')
cbar = plt.colorbar(cf, ax=ax)
cbar.set_label('Probability Density', fontsize=11)
plt.tight_layout()
plt.show()
2. Publication-Quality Figure¶
from scipy import stats
x = np.linspace(-3, 3, 150)
y = np.linspace(-3, 3, 150)
X, Y = np.meshgrid(x, y)
pos = np.dstack((X, Y))
rv = stats.multivariate_normal([0, 0], [[1, 0.6], [0.6, 1]])
Z = rv.pdf(pos)
fig, ax = plt.subplots(figsize=(9, 7))
cf = ax.contourf(X, Y, Z, levels=15, cmap='viridis')
cs = ax.contour(X, Y, Z, levels=8, colors='white', linewidths=0.5, alpha=0.8)
ax.set_xlabel('$X$', fontsize=13)
ax.set_ylabel('$Y$', fontsize=13)
ax.set_title('Bivariate Normal Distribution ($\\rho = 0.6$)', fontsize=14, fontweight='bold')
ax.set_aspect('equal')
ax.tick_params(labelsize=11)
cbar = plt.colorbar(cf, ax=ax, shrink=0.85)
cbar.set_label('Probability Density', fontsize=12)
plt.tight_layout()
plt.show()
Practical Applications¶
1. Terrain Map¶
np.random.seed(42)
from scipy.ndimage import gaussian_filter
# Generate terrain-like data
Z_terrain = np.random.rand(100, 100)
Z_terrain = gaussian_filter(Z_terrain, sigma=10) * 1000
x = np.linspace(0, 10, 100)
y = np.linspace(0, 10, 100)
X, Y = np.meshgrid(x, y)
fig, ax = plt.subplots(figsize=(10, 8))
cf = ax.contourf(X, Y, Z_terrain, levels=20, cmap='terrain')
cs = ax.contour(X, Y, Z_terrain, levels=10, colors='black', linewidths=0.3)
ax.clabel(cs, inline=True, fontsize=7, fmt='%.0f m')
ax.set_title('Topographic Map')
ax.set_xlabel('Distance (km)')
ax.set_ylabel('Distance (km)')
plt.colorbar(cf, ax=ax, label='Elevation (m)')
plt.show()
2. Temperature Field¶
# Simulated temperature field
Z_temp = 20 + 10 * np.exp(-((X - 1)**2 + Y**2) / 2) - 5 * np.exp(-((X + 1)**2 + (Y - 1)**2) / 1)
fig, ax = plt.subplots(figsize=(10, 8))
cf = ax.contourf(X, Y, Z_temp, levels=20, cmap='coolwarm')
cs = ax.contour(X, Y, Z_temp, levels=10, colors='black', linewidths=0.3)
ax.clabel(cs, inline=True, fontsize=8, fmt='%.1f°C')
ax.set_title('Temperature Distribution')
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.colorbar(cf, ax=ax, label='Temperature (°C)')
plt.show()