# Author: Simon-Pierre Boucher — contact@spboucher.ai """Shared matplotlib style for all WP10 figures — print-journal calibre. Conventions (Journal of Finance house style): - no titles inside figures (captions carry the message); multi-panel figures use bold "Panel A." headers set flush left above each axes; - Times-compatible serif text with STIX math, 8–9 pt; - thin, recessive axes (0.6 pt), outward ticks, no top/right spines; - one accent hue per figure; a second hue only for genuine polarity or a second series, always doubled by a linestyle/marker difference; - shaded confidence bands rather than cap-heavy error bars; - direct labels instead of legend boxes wherever the geometry allows. The two data hues (#2e6da4, #c04848) pass the full colour-vision validation suite (lightness band, chroma floor, CVD separation, contrast) on a white surface; INK and GREY are reserved for marks-as-ink and reference lines. """ import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt # noqa: E402 INK = "#1a1a1a" # primary marks (points, bars, text) BLUE = "#2e6da4" # accent series / fitted lines RED = "#c04848" # contrast series / polarity GREY = "#8a8a8a" # reference lines LIGHT = "#d9d9d9" # fills, bands GRID = "#e3e3e3" # gridlines # Sequential blues for ordered series (light → dark, one hue) BLUES = ["#c6d7e8", "#9dbcd8", "#74a1c8", "#4b86b8", "#2e6da4", "#1d4a75"] TEXTWIDTH = 6.3 # \textwidth in inches (1in margins, letter paper) def apply_style() -> None: plt.rcParams.update({ "font.family": "serif", "font.serif": ["Times New Roman", "Times", "STIXGeneral", "DejaVu Serif"], "mathtext.fontset": "stix", "font.size": 9, "axes.labelsize": 9, "xtick.labelsize": 8, "ytick.labelsize": 8, "legend.fontsize": 8, "figure.dpi": 150, "savefig.dpi": 300, "axes.spines.top": False, "axes.spines.right": False, "axes.linewidth": 0.6, "xtick.major.width": 0.6, "ytick.major.width": 0.6, "xtick.major.size": 3, "ytick.major.size": 3, "xtick.direction": "out", "ytick.direction": "out", "axes.grid": False, "grid.color": GRID, "grid.linewidth": 0.5, "legend.frameon": False, "lines.linewidth": 1.3, "lines.markersize": 4.5, "figure.constrained_layout.use": False, }) def panel_label(ax, text: str) -> None: """Bold flush-left panel header above the axes (JoF style).""" ax.set_title(text, loc="left", fontsize=9, fontweight="bold", pad=8) def ygrid(ax) -> None: """Recessive horizontal gridlines drawn beneath the data.""" ax.grid(axis="y", linewidth=0.5, color=GRID) ax.set_axisbelow(True)