"""Shared style for the publication figure package. Each plotter draws its figure at a natural size, then calls finalize(fig) to render it at 18.4 cm (full 2-column) with journal-spec fonts (panel 9 pt, axis 10 pt, ticks/legend 8 pt, title 10 pt), embedded TrueType (Type42) fonts, and line weights scaled so they stay bold on the wider canvas. This reproduces the promoted publication look without any per-figure font tuning. """ import matplotlib matplotlib.rcParams["pdf.fonttype"] = 42 matplotlib.rcParams["ps.fonttype"] = 42 matplotlib.rcParams["font.family"] = "sans-serif" matplotlib.rcParams["axes.spines.top"] = False matplotlib.rcParams["axes.spines.right"] = False # canonical colors OBS = "black"; ERA5 = "#d62728"; CLEAR = "#1f77b4"; CLOUDY = "#ff7f0e" C_LWP = "#009E73"; C_SW = "#CC79A7" TARGET_W_CM = 18.4 T_AXIS, T_TICK, T_LEG, T_PANEL, T_TITLE = 10.0, 8.0, 8.0, 9.0, 10.0 def finalize(fig, out_pdf, target_w_cm=TARGET_W_CM): """Rescale fig to target width, retarget fonts per role, bold the lines, and save (+ .png). Returns the saved native (w, h) in cm.""" import matplotlib.pyplot as plt # scale the canvas to the target width (uniform, preserves layout); if that # would exceed the 19.9 cm recommended page depth, fit the depth instead. DEPTH_CM = 19.9 w_in, h_in = fig.get_size_inches() s = (target_w_cm / 2.54) / w_in if h_in * s * 2.54 > DEPTH_CM: s = (DEPTH_CM / 2.54) / h_in fig.set_size_inches(w_in * s, h_in * s) RS = target_w_cm / (fig.get_figwidth() * 2.54) # font scale ref (>1 if depth-capped) def setpt(t, pt): try: t.set_fontsize(pt / RS) except Exception: pass for ax in fig.get_axes(): if ax.xaxis.get_label().get_text(): setpt(ax.xaxis.get_label(), T_AXIS) if ax.yaxis.get_label().get_text(): setpt(ax.yaxis.get_label(), T_AXIS) for t in ax.get_xticklabels() + ax.get_yticklabels(): setpt(t, T_TICK) if ax.get_title(): setpt(ax.title, T_TITLE) leg = ax.get_legend() if leg: for t in leg.get_texts(): setpt(t, T_LEG) for ln in leg.get_lines(): ln.set_linewidth(ln.get_linewidth() * s) for t in ax.texts: setpt(t, T_PANEL) for ln in ax.get_lines(): ln.set_linewidth(ln.get_linewidth() * s) if ln.get_marker() not in (None, "None", ""): ln.set_markersize(ln.get_markersize() * s) for sp in ax.spines.values(): sp.set_linewidth(sp.get_linewidth() * s) ax.tick_params(width=0.8 * s) for leg in fig.legends: for t in leg.get_texts(): setpt(t, T_LEG) for t in fig.texts: setpt(t, T_PANEL) from pathlib import Path out = Path(out_pdf) out.parent.mkdir(parents=True, exist_ok=True) fig.savefig(out, bbox_inches="tight") fig.savefig(out.with_suffix(".png"), dpi=300, bbox_inches="tight") plt.close(fig) return target_w_cm, fig.get_figheight() * 2.54