| """Ubuntu plots from explicit evaluation records; never invent missing measurements.""" |
| from pathlib import Path |
| import numpy as np |
| import pandas as pd |
| import matplotlib |
| matplotlib.use("Agg") |
| import matplotlib.pyplot as plt |
| from matplotlib import font_manager |
|
|
| GOLD = "#C68B25" |
| INK = "#302B25" |
|
|
| def configure_fonts(font_dir=None): |
| if font_dir is None: |
| font_dir = Path(__file__).resolve().parent/"fonts" |
| for path in Path(font_dir).glob("*.ttf"): |
| font_manager.fontManager.addfont(str(path)) |
| available = {f.name for f in font_manager.fontManager.ttflist} |
| if "Ubuntu" not in available: |
| raise ValueError("Ubuntu is unavailable; provide --font-dir pointing to the included fonts") |
| plt.rcParams.update({"font.family": "Ubuntu", "font.size": 10, "mathtext.fontset": "cm", |
| "pdf.fonttype": 42, "ps.fonttype": 42, "axes.spines.top": False, |
| "axes.spines.right": False, "axes.labelcolor": INK, "text.color": INK, |
| "savefig.bbox": "tight", "figure.dpi": 160}) |
|
|
| def plot_summary(summary, output, font_dir=None, title="Retrospective endpoint evaluation"): |
| configure_fonts(font_dir) |
| frame = pd.read_csv(summary) if not isinstance(summary, pd.DataFrame) else summary |
| output = Path(output); output.mkdir(parents=True, exist_ok=True) |
| for metric in frame.metric.unique(): |
| group = frame[frame.metric == metric].sort_values("mean", ascending=metric != "success") |
| fig, ax = plt.subplots(figsize=(6.6, max(2.8, .38*len(group)))) |
| y = np.arange(len(group)) |
| colors = [GOLD if m == "remedi" else "#8C8982" for m in group.method] |
| ax.barh(y, group["mean"], color=colors, height=.65) |
| ax.errorbar(group["mean"], y, xerr=np.vstack([np.maximum(0, group["mean"]-group.ci_low), np.maximum(0, group.ci_high-group["mean"])]), |
| fmt="none", ecolor=INK, capsize=2, linewidth=.8) |
| ax.set_yticks(y, group.method); ax.invert_yaxis() |
| ax.set_xlabel(metric.replace("_", " ")); ax.set_title(title, loc="left", fontsize=11) |
| fig.savefig(output/f"{metric}.pdf"); fig.savefig(output/f"{metric}.png"); plt.close(fig) |
|
|
| def plot_curve(csv, output, x, y, hue="method", lower=None, upper=None, font_dir=None): |
| configure_fonts(font_dir) |
| frame = pd.read_csv(csv) |
| for field in [x, y, hue]: |
| if field not in frame: raise ValueError(f"Missing plot column {field}") |
| fig, ax = plt.subplots(figsize=(5.2, 3.4)) |
| palette = [GOLD, "#74716B", "#9E4A35", "#457679", "#756589"] |
| for i, (name, group) in enumerate(frame.groupby(hue, sort=True)): |
| group = group.sort_values(x) |
| ax.plot(group[x], group[y], marker="o", markersize=3.5, label=name, |
| color=GOLD if name == "remedi" else palette[(i+1) % len(palette)]) |
| if lower and upper: |
| ax.fill_between(group[x], group[lower], group[upper], alpha=.13) |
| ax.set_xlabel(x.replace("_", " ")); ax.set_ylabel(y.replace("_", " ")); ax.legend(frameon=False) |
| output = Path(output); output.parent.mkdir(parents=True, exist_ok=True) |
| fig.savefig(output); plt.close(fig) |
|
|
|
|