Dataslope logoDataslope

Scientific Visualization

Plot the right thing the right way — communicate data and computations clearly

A scientific plot is not decoration. It is evidence. Done well, a single figure can establish a result more convincingly than ten pages of equations. Done badly, it can mislead an entire field.

This chapter is about producing publication-quality figures with matplotlib, choosing the right encoding for the data at hand, and avoiding the common pitfalls (chiefly: bad colormaps).

A taxonomy of plot types

The single most important sentence in this chapter is: pick the plot type that matches the structure of your data. A heatmap for a 2-D field, a contour for a smooth surface, a small-multiples grid for many similar series. Don't decorate; encode.

The matplotlib object model

Stop using plt.plot() calls in isolation. Adopt the Figure / Axes style — it scales from one panel to a 4 × 4 grid without breaking a sweat.

Code Block
Python 3.13.2

Three habits that pay off forever:

  • fig, ax = plt.subplots(...) — explicit container variables
  • constrained_layout=True — eliminates 90% of "labels are cut off" pain
  • A small loop at the end to apply consistent styling to every panel

2-D fields: heatmaps and contours

Whenever the data is a function of two variables — temperature on a grid, a 2-D probability density, a confusion matrix — you have two great options.

Code Block
Python 3.13.2

Contours are great when the level set (the "ridges and valleys") is what you want to convey. A pcolormesh / imshow is better when the absolute value at every point matters.

Colormaps: choose perceptually uniform

Avoid the legacy jet colormap. It is perceptually nonuniform — it has bright cyan and yellow bands that look like ridges even where the data is flat. Use the modern perceptually uniform colormaps:

  • sequential (low → high): viridis, plasma, magma, cividis
  • diverging (centered around zero): coolwarm, RdBu_r, seismic
  • cyclic (wraps around): twilight, hsv
Code Block
Python 3.13.2

Look at the jet ramp — you'll see false "bands" of bright cyan and yellow. viridis and cividis look like smooth gradients, because they actually are.

Vector fields and 3-D

Two more specialized plots that are widely useful in physics and engineering.

Code Block
Python 3.13.2
Code Block
Python 3.13.2

3-D is genuinely useful for surfaces and for tracing 3-dimensional trajectories (like the Lorenz attractor). It is almost always worse than 2-D contours or small multiples for quantitative comparison — humans cannot read depth accurately.

Small multiples

When you want to compare many similar things, the single most effective layout is the small-multiples grid (Edward Tufte's "trellis"). Same axes, same scales, faceted by group.

Code Block
Python 3.13.2

sharex=True, sharey=True is what makes the comparison fair: your eye reads differences in the data, not differences in scaling.

A multi-file figure pipeline

Code Block
Python 3.13.2

Separating the plotting logic from the computation lets you reuse the same visualization for many systems — and makes it trivial to restyle every figure in a paper from a single place.

A short checklist before you publish a figure

  • Every axis has a label with units
  • Every plot has a legend or a clear title explaining the series
  • The colormap is perceptually uniform (no jet!)
  • Diverging data is shown with a diverging colormap centered at zero
  • Font sizes are readable at the final print size
  • dpi=150 or higher when saving for screens; vector formats (PDF, SVG) for print
  • Aspect ratio matches the data (square for xyx \approx y ranges, wide for time series)

Check your understanding

QuestionSelect one

You are visualizing temperature anomalies (deviation from a baseline) which can be positive or negative. Which colormap should you choose?

A sequential map like viridis

A diverging map like coolwarm or RdBu_r, centered at zero

The default jet

A grayscale ramp

QuestionSelect one

You need to compare model fits across 12 different patient datasets. What's the most effective layout?

One big plot with 12 overlapping lines and a legend

A 3 × 4 grid of small multiples with shared axes

A 3-D plot with patient ID on the z-axis

A pie chart per patient

On this page