Exercises — Publication-quality figures — LaTeX labels, colormaps, DPI
Three knobs run through every problem. Keep this picture in mind:

The left dial (Dots) controls sharpness. The middle dial (Letters) controls whether your text matches the paper. The right dial (Colors) controls whether your data is shown honestly. That is the D-L-C mnemonic from the parent note.
Level 1 — Recognition
These test whether you can name the right tool. No arithmetic.
Problem 1.1
A colormap where equal steps in the data value produce equal perceived steps in brightness is called what? Give one example that satisfies this.
Recall Solution 1.1
What is asked: the name of the "honest brightness" property.
Answer: a perceptually uniform colormap. Example: viridis (also cividis, magma, plasma).
Why: "perceptually uniform" literally means perception (what your eye sees) changes uniformly (in equal steps) as the data changes in equal steps — no bright band jumping out to fake an edge.
Problem 1.2
Which single figure setting fixes the physical printed size of a figure — dpi or figsize?
Recall Solution 1.2
Answer: figsize (measured in inches).
Why: figsize=(w,h) is the inch canvas. dpi only says how many dots you pack into each of those inches — it changes sharpness, never the physical width. Cranking dpi on a 3.5-in figure keeps it 3.5 in wide; it just gets crisper.
Problem 1.3
You have data that ranges from to where means "no anomaly". Sequential or diverging colormap?
Recall Solution 1.3
Answer: diverging (e.g. coolwarm, RdBu).
Why: the data has a meaningful center (). A diverging map paints the center a neutral color and pushes both directions to two opposite hues, so a reader instantly sees "which side of zero".
Level 2 — Application
Now plug numbers into the pixel formula from the parent note: Here are the figure width/height in inches and is the DPI (dots per inch). The inches cancel against the "per inch" in DPI (this is Dimensional analysis), leaving pure dots.
Problem 2.1
A figure declared figsize=(4.0, 3.0) is saved at dpi=300. What is the pixel resolution?
Recall Solution 2.1
What: multiply each inch dimension by DPI. Why it works: ; the inch unit cancels.
Problem 2.2
A journal demands a double-column width of in and 600 dpi for fine line art. What pixel width results, and what is the height in pixels if figsize=(7.0, 4.2)?
Recall Solution 2.2
So px. Why 600 not 300? "fine line art" (thin lines, small text) needs more dots per inch so the thin strokes don't get lost between pixels.
Problem 2.3
Your figsize=(3.5, 2.6) and you need at least px wide. What is the minimum DPI?
Recall Solution 2.3
Rearrange . Why rearrange: the same formula solved for the unknown. Anything meets the requirement.
Level 3 — Analysis
Here you must explain the mechanism, not just compute.
Problem 3.1
Explain why the leading r in ax.set_xlabel(r"$\lambda$ (nm)") matters. What breaks without it, and what breaks silently?
Recall Solution 3.1
What r does: makes a raw string, so Python passes every backslash through untouched to matplotlib/LaTeX.
Without r: Python first tries to interpret backslash escapes before the text ever reaches LaTeX.
"\n"→ newline,"\t"→ tab,"\a"→ bell character. So"$\alpha$"becomes$+ bell +lpha$, corrupting the label."\lambda"→\lis not a recognised escape, so on modern Python you get a DeprecationWarning but it may still pass — this is the silent danger: it works today, breaks in a future Python. Fix: always prefix math-label strings withr.
Problem 3.2
A reviewer says your jet heatmap "shows an edge that isn't in the data." Explain, in terms of brightness, exactly how jet manufactured that edge — and why viridis would not.
Recall Solution 3.2
Mechanism: jet runs blue → cyan → yellow → red. Its brightness (how light/dark it prints in grayscale) rises to a peak at the yellow middle, then falls again — it is non-monotonic. Where the data crosses the value that maps to yellow, the picture suddenly gets bright then dark, so your eye reads a hard boundary (a false edge) even in perfectly smooth data.
Why viridis doesn't: its brightness increases monotonically from dark purple to bright yellow. Equal data steps → equal brightness steps → no artificial peaks → no false edges. (See figure below.)

Look at the jet curve (burnt orange): it humps in the middle. The viridis curve (teal) climbs steadily. That hump is the false edge.
Problem 3.3
Why is fig.savefig("fig.pdf") preferred over fig.savefig("fig.png", dpi=300) for a line plot, but the reverse is true for a dense photograph-like heatmap?
Recall Solution 3.3
Line plot → PDF (vector): a vector format stores shapes (this line goes from point A to B; this text is this glyph). DPI is irrelevant — zoom in infinitely and lines/text stay razor sharp. (See Raster vs vector graphics.) Dense heatmap → PNG/TIFF (raster): a heatmap is already a grid of coloured pixels. Storing it as vector would mean one tiny rectangle per pixel — a gigantic file and often slower rendering. A raster format at high DPI stores the pixel grid directly and efficiently. Rule: shapes → vector (PDF); pixels/photos → raster (PNG/TIFF) at high DPI.
Level 4 — Synthesis
Combine multiple rules into one decision.
Problem 4.1
A journal specifies: single column in, min dpi for line art, body font pt. Write the rcParams + subplots + savefig block that satisfies all three knobs and produces a vector output. Justify each line.
Recall Solution 4.1
plt.rcParams.update({
"font.size": 9, # matches 9-pt body text
"axes.labelsize": 9, # axis labels same size
"savefig.dpi": 300, # meets 300-dpi minimum (matters only if raster)
"savefig.bbox": "tight", # trims white margin so column width is used well
"text.usetex": True, # exact paper fonts (final run)
})
fig, ax = plt.subplots(figsize=(3.5, 2.6)) # PHYSICAL size = column width, set FIRST
# ... plot ...
ax.set_xlabel(r"$\lambda$ (nm)") # raw string so \lambda survives
fig.savefig("fig.pdf") # vector: DPI-independent line artJustification: figsize first fixes the inch canvas so the -pt font keeps its true size. usetex + raw string handle the Letters knob. Saving .pdf handles the Dots knob for line art (vector = infinite effective DPI); the savefig.dpi=300 is a safety net if any raster element sneaks in.
Problem 4.2
You must show a temperature anomaly field (values in , zero = normal) as a heatmap with a labelled scale. Pick the colormap and write the imshow + colorbar lines, labelling the bar in LaTeX with units.
Recall Solution 4.2
Colormap choice: the data has a meaningful center () → diverging → coolwarm (or RdBu), and set symmetric limits so maps to the neutral middle.
im = ax.imshow(Z, cmap="coolwarm", origin="lower",
vmin=-3, vmax=3, # symmetric -> 0 sits at neutral centre
extent=[x0, x1, y0, y1], aspect="auto")
cbar = fig.colorbar(im, ax=ax)
cbar.set_label(r"$\Delta T$ ($^{\circ}$C)") # LaTeX label with unitsWhy vmin=-vmax: without symmetric limits the neutral color drifts off zero, defeating the whole point of a diverging map (see Colormaps and color theory in visualization).
Level 5 — Mastery
Debug and design under full constraints.
Problem 5.1
A colleague's figure looks pixelated in the printed journal even though they used dpi=300. Their code:
fig, ax = plt.subplots() # default figsize 6.4 x 4.8
ax.imshow(photo) # a real photo, raster
fig.savefig("fig.png", dpi=300) # 1920 x 1440 pxThe journal prints it at in wide. Compute the effective printed DPI and explain the pixelation. What is the fix?
Recall Solution 5.1
What happens: the file is px wide. The journal shrinks it to in, so the effective DPI is
That's actually high — so pixelation here is not from too few dots on the printed page. If it still looks blocky, the culprit is the source photo array: if photo is only, say, pixels, imshow upscales it to fill the axes and the printed DPI can't rescue detail that was never captured.
Deeper case — the reverse failure: had they used figsize=(3.5, ...), the file would be px; printed at in that is exactly dpi — fine for the page but risky if the source photo is low-res.
Fix: (a) ensure the source raster has enough native pixels; (b) set figsize to the true column width so file DPI = printed DPI and you can reason about it directly.
Problem 5.2
Design goal: one figure block, single column ( in), that must run on a CI server with no LaTeX installed, still show math labels, use a colorblind-safe sequential map, and export razor-sharp line art. Write it and defend every choice.
Recall Solution 5.2
plt.rcParams.update({
"font.size": 9,
"axes.labelsize": 9,
"mathtext.fontset": "cm", # Computer-Modern-like math WITHOUT external LaTeX
"text.usetex": False, # CI has no LaTeX -> must stay off, else crash
"savefig.bbox": "tight",
})
fig, ax = plt.subplots(figsize=(3.5, 2.6)) # column width first
# ... line plot ...
ax.set_xlabel(r"$\lambda$ (nm)") # mathtext renders $...$ natively
ax.set_ylabel(r"$I/I_0$")
fig.savefig("fig.pdf") # vector: sharp line art, DPI-freeDefense:
text.usetex=False+mathtext.fontset="cm"→ math still renders and looks LaTeX-like, but uses matplotlib's built-in engine, so no external LaTeX is needed — the CI job won't crash.- Colorblind-safe sequential =
viridis/cividis(pickcividisfor the strongest colorblind safety); no diverging map because the data is plain low→high. .pdf= vector line art, DPI-independent, so no DPI decision is even required.figsizefirst so the -pt font keeps its true size.
Recap
Recall Quick self-test
Pixel width of figsize=(4.0,3.0) at 300 dpi? ::: px.
Min DPI for 1050 px across a 3.5-in canvas? ::: dpi.
Which knob sets physical printed size? ::: figsize (inches), never DPI.
Why does raw string r"$\lambda$" matter? ::: Backslashes reach LaTeX untouched; without r, Python mangles escapes like \a, \n.
How does jet fake an edge? ::: Non-monotonic brightness humps at yellow, reading as a false boundary.
Colormap for data centered on a meaningful zero? ::: Diverging (coolwarm) with symmetric vmin=-vmax.
Format for line plots vs dense photos? ::: PDF (vector) for lines; PNG/TIFF (raster, high DPI) for photos.
Effective printed DPI of a 1920-px file printed at 3.5 in? ::: dpi.
Connections
- Publication-quality figures — LaTeX labels, colormaps, DPI (parent)
- Matplotlib basics — figure and axes objects
- Colormaps and color theory in visualization
- LaTeX typesetting
- Raster vs vector graphics
- Dimensional analysis
- Reproducible research and rcParams