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?
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.