File size: 2,940 Bytes
f28d994 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | """Shared ACM-style plotting configuration for figures_v2."""
from __future__ import annotations
from pathlib import Path
import matplotlib as mpl
import matplotlib.pyplot as plt
SINGLE_COL = 3.35
DOUBLE_COL = 6.95
TITLE_SIZE = 10
SUBTITLE_SIZE = 9
LABEL_SIZE = 8.5
TICK_SIZE = 7.5
LEGEND_SIZE = 7.5
ANNOTATION_SIZE = 7
PANEL_LABEL_SIZE = 9
LINEWIDTH = 1.6
MARKER_SIZE = 4.5
AXIS_LINEWIDTH = 0.8
GRID_LINEWIDTH = 0.4
BAR_EDGEWIDTH = 0.4
COLORS = {
"blue": "#4C72B0",
"orange": "#DD8452",
"green": "#55A868",
"red": "#C44E52",
"purple": "#8172B2",
"gray": "#7F7F7F",
"dark": "#2B2B2B",
"light_gray": "#EAEAEA",
"pale_blue": "#EAF1FB",
"pale_green": "#ECF6EF",
"pale_orange": "#FBF0E9",
"pale_red": "#F9EDEE",
}
def apply_style() -> None:
"""Apply compact, print-friendly defaults for ACM two-column figures."""
mpl.rcParams.update(
{
"font.family": "DejaVu Sans",
"font.size": LABEL_SIZE,
"axes.titlesize": SUBTITLE_SIZE,
"axes.labelsize": LABEL_SIZE,
"xtick.labelsize": TICK_SIZE,
"ytick.labelsize": TICK_SIZE,
"legend.fontsize": LEGEND_SIZE,
"axes.linewidth": AXIS_LINEWIDTH,
"axes.spines.top": False,
"axes.spines.right": False,
"axes.grid": True,
"grid.color": "#D8D8D8",
"grid.alpha": 0.55,
"grid.linewidth": GRID_LINEWIDTH,
"lines.linewidth": LINEWIDTH,
"lines.markersize": MARKER_SIZE,
"figure.dpi": 150,
"savefig.dpi": 300,
"savefig.bbox": "tight",
"savefig.pad_inches": 0.03,
"pdf.fonttype": 42,
"ps.fonttype": 42,
"svg.fonttype": "none",
"legend.frameon": False,
}
)
def output_dirs(root: Path) -> dict[str, Path]:
base = root / "figures_v2"
dirs = {}
for name in ("pdf", "png", "svg", "data"):
p = base / name
p.mkdir(parents=True, exist_ok=True)
dirs[name] = p
return dirs
def save_all(fig: plt.Figure, name: str, dirs: dict[str, Path]) -> list[str]:
"""Save PDF/SVG as vector output and PNG as a 300 dpi preview."""
if not fig.get_constrained_layout():
fig.tight_layout()
outputs = []
for ext in ("pdf", "png", "svg"):
path = dirs[ext] / f"{name}.{ext}"
if ext == "png":
fig.savefig(path, dpi=300, bbox_inches="tight", pad_inches=0.03)
else:
fig.savefig(path, bbox_inches="tight", pad_inches=0.03)
outputs.append(str(path))
plt.close(fig)
return outputs
def panel_label(ax, label: str) -> None:
ax.text(
-0.10,
1.04,
label,
transform=ax.transAxes,
fontsize=PANEL_LABEL_SIZE,
fontweight="bold",
va="bottom",
ha="left",
color=COLORS["dark"],
)
|