"""Render heatmaps (concept P by layer x position) and the layer profile."""

import os, sys
from pathlib import Path

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import torch

RES = Path(__file__).resolve().parent.parent / os.environ.get("JLENS_RESULTS", "results")


def plot_heat(path):
    d = torch.load(path)
    m, words, toks = d["map"].detach(), d["words"], d["tokens"]
    fig, ax = plt.subplots(figsize=(min(16, 0.28 * m.shape[1] + 2), 6))
    im = ax.imshow(m.numpy(), aspect="auto", origin="lower", cmap="magma",
                   vmin=0)
    ax.set_ylabel("layer")
    ax.set_xlabel("position")
    if toks and len(toks) <= 60:
        ax.set_xticks(range(len(toks)))
        ax.set_xticklabels([t.replace("\n", "\\n") for t in toks],
                           rotation=90, fontsize=6)
    ax.set_title(f"J-lens P({'/'.join(words)})")
    fig.colorbar(im)
    out = path.with_suffix(".png")
    fig.tight_layout()
    fig.savefig(out, dpi=130)
    plt.close(fig)
    print("wrote", out)


def plot_profile(path):
    d = torch.load(path)
    fig, ax1 = plt.subplots(figsize=(8, 4.5))
    L = len(d["entropy"])
    ax1.plot(range(L), d["entropy"], "k-", label="lens entropy")
    ax1.set_xlabel("layer")
    ax1.set_ylabel("entropy (nats)")
    ax2 = ax1.twinx()
    ax2.plot(range(L), d["agree_in"], "b--", label="top tok == current input")
    ax2.plot(range(L), d["agree_next"], "r--", label="top tok == next output")
    ax2.set_ylabel("agreement")
    fig.legend(loc="upper center", ncol=3, fontsize=8)
    fig.tight_layout()
    out = path.with_suffix(".png")
    fig.savefig(out, dpi=130)
    plt.close(fig)
    print("wrote", out)


if __name__ == "__main__":
    for p in sorted(RES.glob("heat_*.pt")):
        plot_heat(p)
    lp = RES / "layer_profile.pt"
    if lp.exists():
        plot_profile(lp)
