Skillversitas

Displaying Images and Contours

Beyond lines and marks, matplotlib renders two-dimensional fields: images (a grid of color values) and contours (level sets of a surface). The entry points are imshow for the grid itself and contour/contourf for the isolines of a function or gridded dataset. Together they cover heatmaps, satellite imagery, error surfaces, and any "value over a plane" visualization.

imshow: The Value Grid

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-3, 3, 300)
y = np.linspace(-3, 3, 300)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X ** 2 + Y ** 2)) / (np.sqrt(X ** 2 + Y ** 2) + 0.3)

fig, ax = plt.subplots()
im = ax.imshow(Z, extent=(-3, 3, -3, 3), origin="lower",
               cmap="viridis", aspect="equal", interpolation="bilinear")
fig.colorbar(im, ax=ax, label="value")
plt.show()

Key parameters: extent=(left, right, bottom, top) maps the pixel grid onto data coordinates; origin="lower" flips the default (image row 0 at top) so math conventions hold; aspect="equal" keeps units square; interpolation controls smoothing (none for pixel-perfect, bilinear/bicubic for smooth surfaces). For real images, plt.imread("photo.png") loads a file and imshow displays it with the same controls.

contour: Level Lines

import numpy as np
import matplotlib.pyplot as plt

X, Y = np.meshgrid(np.linspace(-3, 3, 200), np.linspace(-3, 3, 200))
Z = np.sin(X) * np.cos(Y)

fig, ax = plt.subplots()
cs = ax.contourf(X, Y, Z, levels=15, cmap="viridis")
ax.contour(X, Y, Z, levels=15, colors="black", linewidths=0.4)
ax.clabel(ax.contour(X, Y, Z, levels=5, colors="white", linewidths=0.6),
          inline=True, fontsize=7)
fig.colorbar(cs, ax=ax)
plt.show()

contourf fills the bands between levels; contour draws the lines. Overlaying both (filled bands plus thin isolines) is the standard "topography" look, and clabel writes the level values on the lines. For scattered (ungridded) data, build the grid first with a triangulation or an interpolation like scipy.interpolate.griddata.

Heatmaps from Matrices

import numpy as np
import matplotlib.pyplot as plt

rng = np.random.default_rng(11)
corr = rng.normal(size=(6, 6))
corr = (corr + corr.T) / 2
np.fill_diagonal(corr, 1.0)

fig, ax = plt.subplots()
im = ax.imshow(corr, cmap="RdYlBu_r", vmin=-1, vmax=1)
ax.set_xticks(range(6), [f"f{i}" for i in range(6)])
ax.set_yticks(range(6), [f"f{i}" for i in range(6)])
for i in range(6):
    for j in range(6):
        ax.text(j, i, f"{corr[i, j]:.2f}", ha="center", va="center", fontsize=7)
fig.colorbar(im, ax=ax)
plt.show()

The correlation-matrix heatmap is the canonical small example: imshow with a diverging colormap centered at zero, cell values written with ax.text, and a fixed vmin/vmax so the color scale means the same thing on every render.

Choosing Between Them

  • imshow when the value at every grid cell is the message (an image, a density, a matrix).
  • contour when the message is "where the value crosses these thresholds" (isobars, decision boundaries, error surfaces).
  • Combining both: filled contours for magnitude plus isolines for the thresholds that matter.

Summary

Render 2D fields with imshow (data coordinates via extent, origin="lower", aspect="equal", a colorbar) and with contourf+contour for level sets. Use diverging colormaps with symmetric limits for centered data, write cell values with ax.text for small matrices, and fix the color scale explicitly so colors mean the same thing every time.