File size: 3,032 Bytes
41c8683
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
"""
读 evaluate_masks.py 产出的 CSV, 画箱线图.

每个 sample 一个分数 -> 3 个 metric 各画一个箱体, 合并展示.
另外可选: 同时画 3 张独立子图(--mode separate).

用法:
    python plot_boxplot.py --csv mask_scores.csv --out_dir plots
    python plot_boxplot.py --csv mask_scores.csv --out_dir plots --mode separate
"""

import argparse
import os

import matplotlib.pyplot as plt
import pandas as pd


METRICS = ["dice", "iou", "ms_ssim"]
COLORS = ["#4C72B0", "#55A868", "#C44E52"]


def plot_combined(df, out_dir):
    os.makedirs(out_dir, exist_ok=True)
    data = [df[m].dropna().values for m in METRICS]

    fig, ax = plt.subplots(figsize=(7, 6))
    bp = ax.boxplot(
        data,
        labels=[m.upper() for m in METRICS],
        patch_artist=True,
        showmeans=True,
        meanprops=dict(marker="D", markerfacecolor="white",
                       markeredgecolor="black", markersize=6),
    )
    for patch, c in zip(bp["boxes"], COLORS):
        patch.set_facecolor(c)
        patch.set_alpha(0.6)

    ax.set_ylabel("score")
    ax.set_title(f"Per-sample metric distribution (n={len(df)})")
    ax.grid(axis="y", alpha=0.3)
    plt.tight_layout()

    out_path = os.path.join(out_dir, "boxplot_combined.png")
    plt.savefig(out_path, dpi=150)
    plt.close()
    print(f"[saved] {out_path}")


def plot_separate(df, out_dir):
    os.makedirs(out_dir, exist_ok=True)
    fig, axes = plt.subplots(1, 3, figsize=(15, 5))
    for ax, m, c in zip(axes, METRICS, COLORS):
        vals = df[m].dropna().values
        bp = ax.boxplot(
            [vals],
            labels=[m.upper()],
            patch_artist=True,
            showmeans=True,
            meanprops=dict(marker="D", markerfacecolor="white",
                           markeredgecolor="black", markersize=6),
        )
        bp["boxes"][0].set_facecolor(c)
        bp["boxes"][0].set_alpha(0.6)
        ax.set_title(f"{m.upper()}  (n={len(vals)})\nmean={vals.mean():.3f}  median={pd.Series(vals).median():.3f}")
        ax.grid(axis="y", alpha=0.3)
    plt.tight_layout()
    out_path = os.path.join(out_dir, "boxplot_separate.png")
    plt.savefig(out_path, dpi=150)
    plt.close()
    print(f"[saved] {out_path}")


def main():
    p = argparse.ArgumentParser()
    p.add_argument("--csv", required=True)
    p.add_argument("--out_dir", default="plots")
    p.add_argument("--mode", choices=["combined", "separate", "both"], default="both")
    args = p.parse_args()

    df = pd.read_csv(args.csv)
    df = df[df["status"] == "ok"].copy()
    print(f"[info] {len(df)} ok samples")

    if args.mode in ("combined", "both"):
        plot_combined(df, args.out_dir)
    if args.mode in ("separate", "both"):
        plot_separate(df, args.out_dir)

    if "dataset_fid" in df.columns:
        fid = df["dataset_fid"].dropna().unique()
        if len(fid):
            print(f"[info] dataset FID = {fid[0]}")


if __name__ == "__main__":
    main()


"""
python plot_box.py --csv mask_scores.csv --out_dir figs
"""