8

I had a research notebook with 40 cells of exploratory plots, half of them relying on variables defined three cells up and a global rcParams tweak that only worked if you ran things in order. Sharing it meant nobody could reproduce the figures.

I used an iterative prompt: first extract a pure data-prep function, then a pure plotting function that takes a DataFrame and an Axes, then a thin CLI. The rule that made it click was 'no top-level state, no implicit figure, every plot function receives its ax'. The figures now regenerate identically from a cold start.

What's your pattern for keeping the styling consistent across a dozen extracted figures without copy-pasting rcParams?

THE PROMPT
Refactor a matplotlib notebook I paste into a reproducible script, iteratively. Turn by turn:

Turn 1: identify every implicit dependency (variables leaking across cells, global rcParams, plt.gcf/gca usage, execution-order assumptions). List them, change nothing yet.

Turn 2: extract data prep into `load_and_prepare() -> pd.DataFrame` with no plotting and no globals; note any nondeterminism (unset random seed, dict ordering) and fix it.

Turn 3: for each figure, write `plot_<name>(df, ax)` that receives an Axes and returns it. Rules: no plt.show inside, no implicit figure, no global rcParams mutation; styling comes from a single passed-in style dict or an mplstyle file. Each function is pure given (df, ax).

Turn 4: a `main()` that builds figures via a config list, saves each to figures/ at 150 DPI with a fixed figsize, and is import-safe (guarded by __main__).

Throughout: keep the visual output identical to the notebook (verify axis limits and labels match), prefer explicit over clever, and flag anything you had to guess.
2'every plot function receives its ax' is the single rule that makes matplotlib testable. Pure functions + a config list beats 40 cells forever.async_annie 3 months ago
add a comment

1 Answer

6

For consistent styling across extracted figures, commit an actual .mplstyle file and load it once in main with plt.style.context, never inside the plot functions. That keeps each plot_ pure and testable, and reviewers can diff the style separately from the logic. I also snapshot-test the figures by comparing saved PNG hashes against a baseline to catch accidental visual drift.

Your Answer