import os import json import pandas as pd import seaborn as sns import matplotlib.pyplot as plt def main(): data = [] out_dir = "outputs" if not os.path.exists(out_dir): return for d in os.listdir(out_dir): json_path = os.path.join(out_dir, d, "metrics.json") if os.path.exists(json_path): try: with open(json_path, 'r') as f: j = json.load(f) flags = j.get("pathology_flags", []) row = { "method": j.get("method", "unknown"), "scene": j.get("scene", "unknown"), "PSNR": j.get("photometric", {}).get("PSNR", 0.0), "LPIPS": j.get("photometric", {}).get("LPIPS", 0.0), "N_gaussians": j.get("geometric", {}).get("N_gaussians", 0), "gamma_median": j.get("geometric", {}).get("gamma_median", 0.0), "alpha_mean": j.get("geometric", {}).get("alpha_mean", 0.0), "is_collapsed": len(flags) > 0, "flags": ",".join(flags) } data.append(row) except Exception: pass if not data: return df = pd.DataFrame(data) df.to_csv("SplatAtlas_Full_Report.csv", index=False) plt.figure(figsize=(10, 6)) sns.scatterplot( data=df, x="PSNR", y="gamma_median", hue="method", style="is_collapsed", s=150, alpha=0.8 ) plt.axhline(18.0, color='red', linestyle='--', label='Pathology Threshold (\u03b3=18)') plt.yscale('log') plt.title("Photometric-to-Geometric Compensation (Cat 1-5)") plt.xlabel("PSNR (Higher is better)") plt.ylabel("Anisotropy \u03b3 (Lower is better, log scale)") plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left') plt.tight_layout() plt.savefig("compensation_dynamics.png", dpi=300) if __name__ == "__main__": main()