import os import glob import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from PIL import Image from umap import UMAP sns.set_theme(style="whitegrid") def load_ood_renders(method_dir): ood_dir = os.path.join(method_dir, "renders_ood") if not os.path.exists(ood_dir): return None images = sorted(glob.glob(os.path.join(ood_dir, "*.png"))) if not images: return None feature_vector = [] for img_path in images: img = Image.open(img_path).convert("RGB").resize((64, 64)) feature_vector.append(np.array(img).flatten()) return np.concatenate(feature_vector) def main(): outputs_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "outputs")) plots_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "plots")) os.makedirs(plots_dir, exist_ok=True) features = [] labels = [] for folder in os.listdir(outputs_dir): method_dir = os.path.join(outputs_dir, folder) if not os.path.isdir(method_dir) or folder == "pathology_archive": continue vec = load_ood_renders(method_dir) if vec is not None: features.append(vec) labels.append(folder.split('_')[0]) if not features: return X = np.stack(features) reducer = UMAP(n_components=2, random_state=42) embedding = reducer.fit_transform(X) df = pd.DataFrame({ 'UMAP_1': embedding[:, 0], 'UMAP_2': embedding[:, 1], 'Method': labels }) plt.figure(figsize=(10, 8)) sns.scatterplot(data=df, x='UMAP_1', y='UMAP_2', hue='Method', s=200, palette='tab10', edgecolor='k') plt.title("Functional Space Convergence (OOD Renders)") plt.tight_layout() plt.savefig(os.path.join(plots_dir, "fig3_functional_manifold.png")) plt.close() if __name__ == "__main__": main()