SPB Git

Repository Public Research preview

style.py 3.1 KB 61 lines python

1"""Publication figure style: validated palette (categorical fixed order, one-hue sequential ramp,2blue-red diverging pair with neutral grey midpoint), vector output, recessive axes.34Palette values follow the project data-visualization reference (light surface). Categorical hues5are assigned in fixed slot order to fixed entities and never cycled.6"""7from __future__ import annotations89import matplotlib10import matplotlib.pyplot as plt11from matplotlib.colors import LinearSegmentedColormap1213CATEGORICAL = ["#2a78d6", "#eb6834", "#1baf7a", "#eda100", "#e87ba4", "#008300", "#6250d6", "#e34948"]14ENTITY_COLORS = {"donor": CATEGORICAL[0], "recipient": CATEGORICAL[1], "graft": CATEGORICAL[2], "sham": CATEGORICAL[3],15                 "random": CATEGORICAL[4], "chance": "#9a9892"}16SEQUENTIAL_STEPS = ["#fcfcfb", "#cde2fb", "#9ec5f4", "#6da7ec", "#3987e5", "#256abf", "#184f95", "#0d366b"]17DIVERGING_STEPS = ["#0d366b", "#3987e5", "#9ec5f4", "#f0efec", "#f2a09f", "#e34948", "#8f1d1c"]18TEXT_PRIMARY, TEXT_SECONDARY, GRID = "#0b0b0b", "#52514e", "#e2e1dd"1920SEQUENTIAL_CMAP = LinearSegmentedColormap.from_list("wp_seq_blue", SEQUENTIAL_STEPS)21DIVERGING_CMAP = LinearSegmentedColormap.from_list("wp_div_blue_red", DIVERGING_STEPS)2223COLUMN_WIDTH_IN = 3.35  # single journal column24DOUBLE_WIDTH_IN = 6.9252627def apply_style() -> None:28    matplotlib.rcParams.update({29        "pdf.fonttype": 42, "ps.fonttype": 42, "svg.fonttype": "none",30        "font.family": "sans-serif", "font.size": 8, "axes.titlesize": 8.5, "axes.labelsize": 8,31        "xtick.labelsize": 7, "ytick.labelsize": 7, "legend.fontsize": 7,32        "axes.edgecolor": GRID, "axes.linewidth": 0.6, "xtick.color": TEXT_SECONDARY, "ytick.color": TEXT_SECONDARY,33        "axes.labelcolor": TEXT_PRIMARY, "text.color": TEXT_PRIMARY, "axes.grid": False,34        "axes.spines.top": False, "axes.spines.right": False, "legend.frameon": False,35        "figure.dpi": 150, "savefig.bbox": "tight", "savefig.pad_inches": 0.02,36    })373839def heatmap(ax, data, row_labels, col_labels, *, cmap, vmin, vmax, cbar_label: str, title: str | None = None, annotate: bool = False):40    im = ax.imshow(data, cmap=cmap, vmin=vmin, vmax=vmax, aspect="auto", interpolation="nearest")41    ax.set_xticks(range(len(col_labels)))42    ax.set_xticklabels(col_labels, rotation=90 if max(len(str(c)) for c in col_labels) > 3 else 0)43    ax.set_yticks(range(len(row_labels)))44    ax.set_yticklabels(row_labels)45    ax.tick_params(length=0)46    for s in ax.spines.values():47        s.set_visible(False)48    if title:49        ax.set_title(title, loc="left", color=TEXT_PRIMARY)50    if annotate:51        for i in range(data.shape[0]):52            for j in range(data.shape[1]):53                v = data[i, j]54                ax.text(j, i, f"{v:.2f}", ha="center", va="center", fontsize=5.5,55                        color="#ffffff" if (v - vmin) / max(vmax - vmin, 1e-9) > 0.6 else TEXT_PRIMARY)56    cb = plt.colorbar(im, ax=ax, fraction=0.046, pad=0.03)57    cb.set_label(cbar_label, color=TEXT_SECONDARY)58    cb.outline.set_visible(False)59    cb.ax.tick_params(length=0, labelsize=6.5, colors=TEXT_SECONDARY)60    return im61
Files main
Menu

Theme