#!/usr/bin/env python3
"""Pareto figures from analysis.json (no recomputation)."""
import json
from pathlib import Path
import matplotlib; matplotlib.use("Agg"); import matplotlib.pyplot as plt
W = Path(__file__).resolve().parents[1]; A = json.load(open(W / "results/analysis.json"))
COL = {"jpeg": "#d95f02", "webp": "#7570b3", "bpg": "#1b9e77", "mbt2018mean": "#e7298a"}
def plot(metric, fname, ylabel):
    fig, ax = plt.subplots(figsize=(7, 4.6))
    base = A["arms"]["orig"]["pope"]["acc"] if metric == "pope" else A["arms"]["orig"]["vqa_acc"]
    for codec, c in COL.items():
        xs, ys, lo, hi = [], [], [], []
        for t in ("t1", "t2"):
            arm = f"{codec}_{t}"; y = A["arms"][arm]["pope"]["acc"] if metric == "pope" else A["arms"][arm]["vqa_acc"]
            ci = A["vs_orig"][arm]["pope_delta_ci95_cluster_boot" if metric == "pope" else "vqa_delta_ci95_cluster_boot"]
            xs.append(A["rate"][arm]["mean_bpp"]); ys.append(y); lo.append(y - (base + ci[0])); hi.append(base + ci[1] - y)
        ax.errorbar(xs, ys, yerr=[lo, hi], color=c, marker="o", capsize=3, label=codec)
    y = A["arms"]["bpg_q51"]["pope"]["acc"] if metric == "pope" else A["arms"]["bpg_q51"]["vqa_acc"]
    ax.scatter([A["rate"]["bpg_q51"]["mean_bpp"]], [y], marker="x", color="k", label="BPG q51 (positive control)")
    ax.scatter([A["rate"]["orig"]["mean_bpp"]], [base], marker="*", s=140, color="k", label="COCO original (already JPEG)")
    # y range follows the data; the null baseline sits far below and is annotated instead of drawn,
    # otherwise every real point is squeezed into a thin band at the top of the axes.
    ys = [A["arms"][a]["pope"]["acc"] if metric == "pope" else A["arms"][a]["vqa_acc"] for a in A["arms"]]
    lo_y, hi_y = min(ys), max(ys); pad = max(0.02, (hi_y - lo_y) * 0.25)
    ax.set_ylim(lo_y - pad, hi_y + pad)
    if metric == "pope":
        ax.annotate(f"null baseline (always \u201cyes\u201d) = {A['null_pope_all_yes_acc']:.3f}, below the plotted range",
                    xy=(0.01, 0.02), xycoords="axes fraction", fontsize=7.5, color="dimgrey")
    ax.set_xscale("log"); ax.set_xlabel("storage bits per pixel at ORIGINAL resolution (mean over 102 images, log scale)\nthe model itself only sees a 336x336 resize, so its effective input rate is much higher")
    ax.set_ylabel(ylabel)
    ax.set_title(f"LLaVA-1.5-7B (Q8_0, CPU): {ylabel} vs rate - two rate points, not a Pareto curve\n"
                 "error bars = 95% image-cluster bootstrap CI of the paired\ndifference vs the original, drawn around each arm",
                 fontsize=9.5)
    ax.grid(alpha=.3); ax.legend(fontsize=7.5, loc="lower right", framealpha=.92)
    fig.tight_layout(); fig.savefig(W / "figs" / fname, dpi=150); plt.close(fig)
plot("pope", "rate_accuracy_pope.png", "POPE-random accuracy"); plot("vqa", "rate_accuracy_vqa.png", "VQA-v2 accuracy"); print("figs ok")
