"""Shared plotting style: seaborn modern look + vector PDF output (fonttype=42). Used by every fig*.py under code/figures/. Import `apply`, `save`, and the palettes. """ from __future__ import annotations from pathlib import Path import matplotlib as mpl import matplotlib.pyplot as plt import seaborn as sns PALETTE_DEEP = list(sns.color_palette("deep")) PALETTE_MUTED = list(sns.color_palette("muted")) PALETTE_COLORBLIND = list(sns.color_palette("colorblind")) def apply() -> None: """Apply the paper figure style. Call once at the top of each fig script.""" sns.set_theme(style="whitegrid", context="paper", font_scale=1.15) mpl.rcParams.update( { "figure.dpi": 150, "savefig.dpi": 300, "savefig.format": "pdf", "savefig.bbox": "tight", # TrueType embedding -> accepted by IEEE / Nature / ACM venues (no Type-3). "pdf.fonttype": 42, "ps.fonttype": 42, "font.family": "DejaVu Sans", "axes.labelsize": 12, "axes.titlesize": 13, "xtick.labelsize": 10.5, "ytick.labelsize": 10.5, "legend.fontsize": 10, "legend.frameon": False, "axes.grid": True, "grid.alpha": 0.3, "axes.spines.top": False, "axes.spines.right": False, "lines.linewidth": 1.8, "lines.markersize": 5, } ) def save(fig, name: str, out_dir) -> None: """Save a figure as both vector PDF and 300-dpi PNG. Closes the figure.""" out_dir = Path(out_dir) out_dir.mkdir(parents=True, exist_ok=True) fig.savefig(out_dir / f"{name}.pdf") fig.savefig(out_dir / f"{name}.png", dpi=300) plt.close(fig)