File size: 4,316 Bytes
d454209
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
"""Small multiples: for every ablation setting, the band gap of each returned structure (DFT where Perov-5 has it,
else the CGCNN judge on the relaxed cell) against the target, with the label the engine shows and the diagonal."""
import os
import numpy as np
import pandas as pd
import matplotlib
def main():
    """The script's work; nothing runs on import."""
    matplotlib.use("Agg")
    import matplotlib.pyplot as plt
    from matplotlib.lines import Line2D

    HERE = os.path.dirname(os.path.abspath(__file__))
    RES = f"{HERE}/results"
    SURFACE, INK, INK2, GRID = "#fcfcfb", "#0b0b0b", "#5f5e58", "#e4e3dc"
    TRUE_C, LABEL_C = "#2a78d6", "#eb6834"      # categorical slots 1 and 2 of the reference palette

    allc = pd.read_csv(f"{RES}/all_candidates_enriched.csv")
    tab = pd.read_csv(f"{RES}/ablation_table.csv").set_index("tag")
    order = [t for t in ["R", "O", "G0", "G2", "G5", "AR", "OA", "OAall", "ARs1", "OAs1", "G7", "S0", "G1", "G6", "G3", "G4", "G5w1000",
                         "G8", "G9", "G10", "V2S", "V2S1S"] if t in tab.index]
    allc["truth"] = allc.dft_gap.fillna(allc.cgcnn_gap)
    ncol = 4; nrow = int(np.ceil(len(order) / ncol))
    plt.rcParams.update({"font.size": 9, "axes.edgecolor": GRID, "axes.labelcolor": INK2, "xtick.color": INK2,
                         "ytick.color": INK2, "text.color": INK, "font.family": "DejaVu Sans"})
    fig, axes = plt.subplots(nrow, ncol, figsize=(3.4 * ncol, 2.9 * nrow + 1.1), sharex=True, sharey=True, facecolor=SURFACE)
    axes = np.atleast_2d(axes)
    rng = np.random.RandomState(0)
    for k, ax in enumerate(axes.flat):
        if k >= len(order):
            ax.axis("off"); continue
        tag = order[k]; d = allc[allc.tag == tag]; r = tab.loc[tag]
        ax.set_facecolor(SURFACE); ax.grid(True, color=GRID, linewidth=0.7); ax.set_axisbelow(True)
        for s in ("top", "right"):
            ax.spines[s].set_visible(False)
        ax.plot([0, 6.5], [0, 6.5], color=INK2, linestyle=(0, (4, 3)), linewidth=1.0, zorder=1)
        jit = rng.uniform(-0.16, 0.16, len(d))
        if d.label_gap.notna().any():
            ax.scatter(d.target + jit - 0.1, d.label_gap, s=14, color=LABEL_C, edgecolor=SURFACE, linewidth=0.8, zorder=3)
        ax.scatter(d.target + jit + 0.1, d.truth, s=14, color=TRUE_C, edgecolor=SURFACE, linewidth=0.8, zorder=3)
        m = d.groupby("target").truth.mean()
        if len(m) > 1:
            ax.plot(m.index + 0.1, m.values, color=TRUE_C, linewidth=1.8, zorder=4)
        rho = r.rho_dft
        ax.set_title(f"{tag}: {r.model}", loc="left", fontsize=9.5, color=INK, pad=14)
        ax.text(0.0, 1.015, f"labels {r.labels} 路 latent {r.latent} 路 pull {r.manifold}", transform=ax.transAxes, fontsize=7.5, color=INK2)
        ax.text(0.03, 0.96, f"蟻(DFT) {rho:+.2f}" if np.isfinite(rho) else "蟻(DFT) n/a", transform=ax.transAxes, fontsize=8.5,
                color=INK, va="top", fontweight="bold")
        ax.text(0.03, 0.85, f"{int(r.returned)} returned 路 {int(r.distinct)} distinct", transform=ax.transAxes, fontsize=7.5, color=INK2, va="top")
        ax.set_xlim(-0.5, 6.5); ax.set_ylim(-0.3, 7.3); ax.set_xticks(range(7))
    for ax in axes[-1]:
        ax.set_xlabel("Target gap (eV)")
    for ax in axes[:, 0]:
        ax.set_ylabel("Band gap (eV)")
    handles = [Line2D([], [], marker="o", linestyle="", color=TRUE_C, markersize=5), Line2D([], [], color=TRUE_C, linewidth=1.8),
               Line2D([], [], marker="o", linestyle="", color=LABEL_C, markersize=5), Line2D([], [], color=INK2, linestyle=(0, (4, 3)))]
    labels = ["Gap of the returned structure (DFT, else CGCNN on relaxed cell)", "Mean per target",
              "Gap the engine shows (label)", "Perfect conditioning"]
    fig.suptitle("Ablation: which part of the pipeline makes generation follow the band-gap target?", x=0.01, ha="left",
                 fontsize=12.5, fontweight="bold", color=INK)
    fig.legend(handles, labels, loc="upper left", ncol=4, frameon=False, bbox_to_anchor=(0.005, 1 - 0.55 / fig.get_figheight()),
               fontsize=8.5, labelcolor=INK)
    fig.tight_layout(rect=(0, 0, 1, 1 - 1.0 / fig.get_figheight()))
    fig.savefig(f"{RES}/ablation_chart.png", dpi=150, facecolor=SURFACE)
    print("saved", f"{RES}/ablation_chart.png")


if __name__ == "__main__":
    main()