SPB Git forge

spb/wp22_uqo

Public
6commits 1branches 0releases
142.4 MBsize
maindefault branch
3 h agolast push
TeX 55.1% Python 44.2%
2.2 KB · 33 lines python
Raw Blame History
1# Author: Simon-Pierre Boucher — simon-pierre.boucher@uqo.ca2"""Figure style: validated categorical palette (fixed slot order, never cycled), thin marks, single axis per panel."""3from __future__ import annotations45import matplotlib6import matplotlib.pyplot as plt78matplotlib.use("Agg")9SERIES = ["#2a78d6", "#eb6834", "#1baf7a", "#eda100", "#e87ba4", "#008300", "#6250d6", "#e34948"]10INK = "#0b0b0b"; INK2 = "#52514e"; GRID = "#e4e3df"11METHOD_COLORS = {  # fixed assignment: colour follows the entity12    "S_sharp": SERIES[0], "C_pooled_td": SERIES[1], "A_median": SERIES[2], "H_repeat_sales_cs": SERIES[3], "D_rtd_w13_mean": SERIES[4],13    "E_hi_fisher_chained": SERIES[5], "F_geks_w25_movement": SERIES[7], "K_qhpi": SERIES[6], "G_hmts_w13": "#7a7a7a", "B_stratified_median": "#a0a0a0",14}15METHOD_LABELS = {"S_sharp": "SHARP-HPI", "C_pooled_td": "Pooled time dummy (Huber)", "A_median": "Median price", "H_repeat_sales_cs": "Repeat sales (Case–Shiller)",16                 "D_rtd_w13_mean": "Rolling TD, 13 m, mean splice", "E_hi_fisher_chained": "Hedonic imputation Fisher (chained)", "F_geks_w25_movement": "GEKS-Fisher, 25 m",17                 "K_qhpi": "QHPI v2.1 architecture", "G_hmts_w13": "HMTS, 13 m", "B_stratified_median": "Stratified median", "J_gbm_oot_residual": "GBM out-of-time residual",18                 "S_sharp_filtered": "SHARP-HPI (real-time filtered)"}19CLASS_LABELS = {"house": "Single-family houses", "condo": "Condominiums", "plex": "Plexes (2–5 units)"}202122def style() -> None:23    plt.rcParams.update({24        "font.family": "serif", "font.size": 9, "axes.edgecolor": INK2, "axes.labelcolor": INK, "axes.spines.top": False, "axes.spines.right": False,25        "axes.grid": True, "grid.color": GRID, "grid.linewidth": 0.6, "xtick.color": INK2, "ytick.color": INK2, "legend.frameon": False, "legend.fontsize": 8,26        "lines.linewidth": 1.4, "figure.dpi": 150, "savefig.bbox": "tight", "axes.titlesize": 9.5, "axes.titleweight": "bold",27    })282930def month_ticks(ax, months: list[str], every: int = 12) -> None:31    idx = [i for i, m in enumerate(months) if m.endswith("-01")][::max(1, every // 12)]32    ax.set_xticks(idx); ax.set_xticklabels([months[i][:4] for i in idx])33