SPB Git

spb/wp10_uqo Public

UQO Working Paper No. 10 — The assessment gap in Quebec: vertical and horizontal inequity in municipal property assessment.

TeX 55.9% Python 44%
2.8 KB · 76 lines python
Raw Blame History
1# Author: Simon-Pierre Boucher — contact@spboucher.ai2"""Shared matplotlib style for all WP10 figures — print-journal calibre.34Conventions (Journal of Finance house style):5  - no titles inside figures (captions carry the message); multi-panel6    figures use bold "Panel A." headers set flush left above each axes;7  - Times-compatible serif text with STIX math, 8–9 pt;8  - thin, recessive axes (0.6 pt), outward ticks, no top/right spines;9  - one accent hue per figure; a second hue only for genuine polarity or a10    second series, always doubled by a linestyle/marker difference;11  - shaded confidence bands rather than cap-heavy error bars;12  - direct labels instead of legend boxes wherever the geometry allows.1314The two data hues (#2e6da4, #c04848) pass the full colour-vision validation15suite (lightness band, chroma floor, CVD separation, contrast) on a white16surface; INK and GREY are reserved for marks-as-ink and reference lines.17"""18import matplotlib1920matplotlib.use("Agg")21import matplotlib.pyplot as plt  # noqa: E4022223INK = "#1a1a1a"       # primary marks (points, bars, text)24BLUE = "#2e6da4"      # accent series / fitted lines25RED = "#c04848"       # contrast series / polarity26GREY = "#8a8a8a"      # reference lines27LIGHT = "#d9d9d9"     # fills, bands28GRID = "#e3e3e3"      # gridlines2930# Sequential blues for ordered series (light → dark, one hue)31BLUES = ["#c6d7e8", "#9dbcd8", "#74a1c8", "#4b86b8", "#2e6da4", "#1d4a75"]3233TEXTWIDTH = 6.3       # \textwidth in inches (1in margins, letter paper)343536def apply_style() -> None:37    plt.rcParams.update({38        "font.family": "serif",39        "font.serif": ["Times New Roman", "Times", "STIXGeneral", "DejaVu Serif"],40        "mathtext.fontset": "stix",41        "font.size": 9,42        "axes.labelsize": 9,43        "xtick.labelsize": 8,44        "ytick.labelsize": 8,45        "legend.fontsize": 8,46        "figure.dpi": 150,47        "savefig.dpi": 300,48        "axes.spines.top": False,49        "axes.spines.right": False,50        "axes.linewidth": 0.6,51        "xtick.major.width": 0.6,52        "ytick.major.width": 0.6,53        "xtick.major.size": 3,54        "ytick.major.size": 3,55        "xtick.direction": "out",56        "ytick.direction": "out",57        "axes.grid": False,58        "grid.color": GRID,59        "grid.linewidth": 0.5,60        "legend.frameon": False,61        "lines.linewidth": 1.3,62        "lines.markersize": 4.5,63        "figure.constrained_layout.use": False,64    })656667def panel_label(ax, text: str) -> None:68    """Bold flush-left panel header above the axes (JoF style)."""69    ax.set_title(text, loc="left", fontsize=9, fontweight="bold", pad=8)707172def ygrid(ax) -> None:73    """Recessive horizontal gridlines drawn beneath the data."""74    ax.grid(axis="y", linewidth=0.5, color=GRID)75    ax.set_axisbelow(True)76