{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a0f1b2c3",
   "metadata": {},
   "source": [
    "# Phase 1 — Pipeline Selection Analysis\n",
    "\n",
    "DCGAN at 64×64 used as a cheap proxy to compare data pipeline variants. Each experiment varies one factor:\n",
    "\n",
    "- **1A** — Resolution: 64×64 vs 128×128\n",
    "- **1B** — Face crop + alignment: Full image vs MTCNN-aligned\n",
    "- **1C** — Augmentation: H-flip only vs H-flip + rotation + color jitter\n",
    "- **1D** — Combined dataset: Aligned only vs aligned + raw mixed\n",
    "\n",
    "All runs used 50 epochs, batch size 64, lr=2e-4, latent_dim=100, ngf=ndf=64."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b1c2d3e4",
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "from pathlib import Path\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import matplotlib.image as mpimg\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "plt.rcParams.update({\"figure.dpi\": 120, \"font.size\": 10})\n",
    "\n",
    "OUTPUTS = Path(\"../outputs\")\n",
    "LOGS = OUTPUTS / \"logs\"\n",
    "SAMPLES = OUTPUTS / \"samples\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2d3e4f5",
   "metadata": {},
   "source": [
    "## 1. Load all experiment logs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "d3e4f5a6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loaded 7 experiments:\n",
      "  p1a_dcgan_128\n",
      "  p1a_dcgan_64\n",
      "  p1b_dcgan_aligned\n",
      "  p1b_dcgan_full\n",
      "  p1c_dcgan_full_aug\n",
      "  p1c_dcgan_hflip\n",
      "  p1d_dcgan_combined\n"
     ]
    }
   ],
   "source": [
    "run_names = sorted(p.stem for p in LOGS.glob(\"p1*.json\"))\n",
    "runs = {}\n",
    "for name in run_names:\n",
    "    with open(LOGS / f\"{name}.json\") as f:\n",
    "        runs[name] = json.load(f)\n",
    "\n",
    "print(f\"Loaded {len(runs)} experiments:\")\n",
    "for name in run_names:\n",
    "    print(f\"  {name}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "e4f5a6b7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Parse metadata about each experiment\n",
    "experiment_groups = {\n",
    "    \"1A — Resolution\": {\n",
    "        \"p1a_dcgan_64\": \"64×64 (raw)\",\n",
    "        \"p1a_dcgan_128\": \"128×128 (raw)\",\n",
    "    },\n",
    "    \"1B — Alignment\": {\n",
    "        \"p1b_dcgan_full\": \"Full image (raw)\",\n",
    "        \"p1b_dcgan_aligned\": \"MTCNN-aligned\",\n",
    "    },\n",
    "    \"1C — Augmentation\": {\n",
    "        \"p1c_dcgan_hflip\": \"H-flip only\",\n",
    "        \"p1c_dcgan_full_aug\": \"H-flip + rot + color\",\n",
    "    },\n",
    "    \"1D — Dataset mixing\": {\n",
    "        \"p1b_dcgan_aligned\": \"Aligned only\",\n",
    "        \"p1d_dcgan_combined\": \"Aligned + raw mixed\",\n",
    "    },\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f5a6b7c8",
   "metadata": {},
   "source": [
    "## 2. FID Comparison Table"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "a6b7c8d9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style type=\"text/css\">\n",
       "</style>\n",
       "<table id=\"T_ce5f9\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"blank level0\" >&nbsp;</th>\n",
       "      <th id=\"T_ce5f9_level0_col0\" class=\"col_heading level0 col0\" >Experiment</th>\n",
       "      <th id=\"T_ce5f9_level0_col1\" class=\"col_heading level0 col1\" >Data</th>\n",
       "      <th id=\"T_ce5f9_level0_col2\" class=\"col_heading level0 col2\" >Size</th>\n",
       "      <th id=\"T_ce5f9_level0_col3\" class=\"col_heading level0 col3\" >Augment</th>\n",
       "      <th id=\"T_ce5f9_level0_col4\" class=\"col_heading level0 col4\" >FID@25</th>\n",
       "      <th id=\"T_ce5f9_level0_col5\" class=\"col_heading level0 col5\" >FID@50</th>\n",
       "      <th id=\"T_ce5f9_level0_col6\" class=\"col_heading level0 col6\" >G loss (ep50)</th>\n",
       "      <th id=\"T_ce5f9_level0_col7\" class=\"col_heading level0 col7\" >D loss (ep50)</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th id=\"T_ce5f9_level0_row0\" class=\"row_heading level0 row0\" >4</th>\n",
       "      <td id=\"T_ce5f9_row0_col0\" class=\"data row0 col0\" >p1c_dcgan_full_aug</td>\n",
       "      <td id=\"T_ce5f9_row0_col1\" class=\"data row0 col1\" >cropped/generator</td>\n",
       "      <td id=\"T_ce5f9_row0_col2\" class=\"data row0 col2\" >64×64</td>\n",
       "      <td id=\"T_ce5f9_row0_col3\" class=\"data row0 col3\" >True</td>\n",
       "      <td id=\"T_ce5f9_row0_col4\" class=\"data row0 col4\" >48.0</td>\n",
       "      <td id=\"T_ce5f9_row0_col5\" class=\"data row0 col5\" >33.4</td>\n",
       "      <td id=\"T_ce5f9_row0_col6\" class=\"data row0 col6\" >3.480</td>\n",
       "      <td id=\"T_ce5f9_row0_col7\" class=\"data row0 col7\" >0.412</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_ce5f9_level0_row1\" class=\"row_heading level0 row1\" >5</th>\n",
       "      <td id=\"T_ce5f9_row1_col0\" class=\"data row1 col0\" >p1c_dcgan_hflip</td>\n",
       "      <td id=\"T_ce5f9_row1_col1\" class=\"data row1 col1\" >cropped/generator</td>\n",
       "      <td id=\"T_ce5f9_row1_col2\" class=\"data row1 col2\" >64×64</td>\n",
       "      <td id=\"T_ce5f9_row1_col3\" class=\"data row1 col3\" >False</td>\n",
       "      <td id=\"T_ce5f9_row1_col4\" class=\"data row1 col4\" >48.9</td>\n",
       "      <td id=\"T_ce5f9_row1_col5\" class=\"data row1 col5\" >37.9</td>\n",
       "      <td id=\"T_ce5f9_row1_col6\" class=\"data row1 col6\" >3.739</td>\n",
       "      <td id=\"T_ce5f9_row1_col7\" class=\"data row1 col7\" >0.392</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_ce5f9_level0_row2\" class=\"row_heading level0 row2\" >2</th>\n",
       "      <td id=\"T_ce5f9_row2_col0\" class=\"data row2 col0\" >p1b_dcgan_aligned</td>\n",
       "      <td id=\"T_ce5f9_row2_col1\" class=\"data row2 col1\" >cropped/generator</td>\n",
       "      <td id=\"T_ce5f9_row2_col2\" class=\"data row2 col2\" >64×64</td>\n",
       "      <td id=\"T_ce5f9_row2_col3\" class=\"data row2 col3\" >False</td>\n",
       "      <td id=\"T_ce5f9_row2_col4\" class=\"data row2 col4\" >47.5</td>\n",
       "      <td id=\"T_ce5f9_row2_col5\" class=\"data row2 col5\" >42.0</td>\n",
       "      <td id=\"T_ce5f9_row2_col6\" class=\"data row2 col6\" >3.965</td>\n",
       "      <td id=\"T_ce5f9_row2_col7\" class=\"data row2 col7\" >0.312</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_ce5f9_level0_row3\" class=\"row_heading level0 row3\" >1</th>\n",
       "      <td id=\"T_ce5f9_row3_col0\" class=\"data row3 col0\" >p1a_dcgan_64</td>\n",
       "      <td id=\"T_ce5f9_row3_col1\" class=\"data row3 col1\" >data</td>\n",
       "      <td id=\"T_ce5f9_row3_col2\" class=\"data row3 col2\" >64×64</td>\n",
       "      <td id=\"T_ce5f9_row3_col3\" class=\"data row3 col3\" >False</td>\n",
       "      <td id=\"T_ce5f9_row3_col4\" class=\"data row3 col4\" >120.9</td>\n",
       "      <td id=\"T_ce5f9_row3_col5\" class=\"data row3 col5\" >86.7</td>\n",
       "      <td id=\"T_ce5f9_row3_col6\" class=\"data row3 col6\" >4.019</td>\n",
       "      <td id=\"T_ce5f9_row3_col7\" class=\"data row3 col7\" >0.283</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_ce5f9_level0_row4\" class=\"row_heading level0 row4\" >6</th>\n",
       "      <td id=\"T_ce5f9_row4_col0\" class=\"data row4 col0\" >p1d_dcgan_combined</td>\n",
       "      <td id=\"T_ce5f9_row4_col1\" class=\"data row4 col1\" >['data', 'cropped/generator']</td>\n",
       "      <td id=\"T_ce5f9_row4_col2\" class=\"data row4 col2\" >64×64</td>\n",
       "      <td id=\"T_ce5f9_row4_col3\" class=\"data row4 col3\" >False</td>\n",
       "      <td id=\"T_ce5f9_row4_col4\" class=\"data row4 col4\" >95.5</td>\n",
       "      <td id=\"T_ce5f9_row4_col5\" class=\"data row4 col5\" >87.4</td>\n",
       "      <td id=\"T_ce5f9_row4_col6\" class=\"data row4 col6\" >5.265</td>\n",
       "      <td id=\"T_ce5f9_row4_col7\" class=\"data row4 col7\" >0.198</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_ce5f9_level0_row5\" class=\"row_heading level0 row5\" >3</th>\n",
       "      <td id=\"T_ce5f9_row5_col0\" class=\"data row5 col0\" >p1b_dcgan_full</td>\n",
       "      <td id=\"T_ce5f9_row5_col1\" class=\"data row5 col1\" >data</td>\n",
       "      <td id=\"T_ce5f9_row5_col2\" class=\"data row5 col2\" >64×64</td>\n",
       "      <td id=\"T_ce5f9_row5_col3\" class=\"data row5 col3\" >False</td>\n",
       "      <td id=\"T_ce5f9_row5_col4\" class=\"data row5 col4\" >109.6</td>\n",
       "      <td id=\"T_ce5f9_row5_col5\" class=\"data row5 col5\" >89.0</td>\n",
       "      <td id=\"T_ce5f9_row5_col6\" class=\"data row5 col6\" >3.960</td>\n",
       "      <td id=\"T_ce5f9_row5_col7\" class=\"data row5 col7\" >0.370</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_ce5f9_level0_row6\" class=\"row_heading level0 row6\" >0</th>\n",
       "      <td id=\"T_ce5f9_row6_col0\" class=\"data row6 col0\" >p1a_dcgan_128</td>\n",
       "      <td id=\"T_ce5f9_row6_col1\" class=\"data row6 col1\" >data</td>\n",
       "      <td id=\"T_ce5f9_row6_col2\" class=\"data row6 col2\" >128×128</td>\n",
       "      <td id=\"T_ce5f9_row6_col3\" class=\"data row6 col3\" >False</td>\n",
       "      <td id=\"T_ce5f9_row6_col4\" class=\"data row6 col4\" >143.1</td>\n",
       "      <td id=\"T_ce5f9_row6_col5\" class=\"data row6 col5\" >115.0</td>\n",
       "      <td id=\"T_ce5f9_row6_col6\" class=\"data row6 col6\" >5.013</td>\n",
       "      <td id=\"T_ce5f9_row6_col7\" class=\"data row6 col7\" >0.185</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x7f54145ac8c0>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rows = []\n",
    "for name in run_names:\n",
    "    r = runs[name]\n",
    "    cfg = r[\"config\"]\n",
    "    fid = r[\"history\"][\"fid\"]\n",
    "    rows.append({\n",
    "        \"Experiment\": name,\n",
    "        \"Data\": cfg.get(\"data_dir\"),\n",
    "        \"Size\": f\"{cfg.get('image_size')}×{cfg.get('image_size')}\",\n",
    "        \"Augment\": cfg.get(\"augment\", False),\n",
    "        \"FID@25\": fid.get(\"25\", None),\n",
    "        \"FID@50\": fid.get(\"50\", None),\n",
    "        \"G loss (ep50)\": r[\"history\"][\"g_loss\"][-1],\n",
    "        \"D loss (ep50)\": r[\"history\"][\"d_loss\"][-1],\n",
    "    })\n",
    "\n",
    "df = pd.DataFrame(rows).sort_values(\"FID@50\")\n",
    "df.style.format({\"FID@25\": \"{:.1f}\", \"FID@50\": \"{:.1f}\", \"G loss (ep50)\": \"{:.3f}\", \"D loss (ep50)\": \"{:.3f}\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "b7c8d9ea",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 81632 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# FID bar chart — all experiments ranked\n",
    "fig, ax = plt.subplots(figsize=(10, 5))\n",
    "labels = df[\"Experiment\"].values\n",
    "fid25 = df[\"FID@25\"].values\n",
    "fid50 = df[\"FID@50\"].values\n",
    "x = np.arange(len(labels))\n",
    "width = 0.35\n",
    "\n",
    "bars1 = ax.bar(x - width / 2, fid25, width, label=\"FID @ 25\", color=\"#5B8DB8\", alpha=0.85)\n",
    "bars2 = ax.bar(x + width / 2, fid50, width, label=\"FID @ 50\", color=\"#E8705A\", alpha=0.85)\n",
    "\n",
    "ax.set_ylabel(\"FID (lower is better)\")\n",
    "ax.set_title(\"Phase 1 — FID Scores Across All Experiments\")\n",
    "ax.set_xticks(x)\n",
    "ax.set_xticklabels(labels, rotation=30, ha=\"right\")\n",
    "ax.legend()\n",
    "ax.set_ylim(0, None)\n",
    "\n",
    "for bar in bars1:\n",
    "    ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 1,\n",
    "            f\"{bar.get_height():.0f}\", ha=\"center\", va=\"bottom\", fontsize=8)\n",
    "for bar in bars2:\n",
    "    ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 1,\n",
    "            f\"{bar.get_height():.0f}\", ha=\"center\", va=\"bottom\", fontsize=8)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c8d9ea0f",
   "metadata": {},
   "source": [
    "## 3. Per-Experiment Group Comparisons"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "d9ea0f1a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 214796 characters]",
      "text/plain": [
       "<Figure size 1680x1200 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, axes = plt.subplots(2, 2, figsize=(14, 10))\n",
    "axes = axes.flatten()\n",
    "colors = [\"#5B8DB8\", \"#E8705A\"]\n",
    "\n",
    "for idx, (group_title, experiments) in enumerate(experiment_groups.items()):\n",
    "    ax = axes[idx]\n",
    "    for i, (run_name, label) in enumerate(experiments.items()):\n",
    "        h = runs[run_name][\"history\"]\n",
    "        fid_dict = h[\"fid\"]\n",
    "        epochs = sorted(int(k) for k in fid_dict)\n",
    "        fid_vals = [fid_dict[str(e)] for e in epochs]\n",
    "        ax.plot(epochs, fid_vals, \"o-\", label=f\"{label} (FID@50={fid_dict.get('50', '?'):.1f})\",\n",
    "                color=colors[i], linewidth=2, markersize=8)\n",
    "\n",
    "    ax.set_xlabel(\"Epoch\")\n",
    "    ax.set_ylabel(\"FID\")\n",
    "    ax.set_title(group_title)\n",
    "    ax.legend(fontsize=9)\n",
    "    ax.set_xlim(20, 55)\n",
    "\n",
    "fig.suptitle(\"Phase 1 — FID per Experiment Group\", fontsize=14, fontweight=\"bold\", y=1.01)\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea0f1a2b",
   "metadata": {},
   "source": [
    "## 4. Training Loss Curves"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "f0f1a2b3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 279996 characters]",
      "text/plain": [
       "<Figure size 2160x960 with 8 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, axes = plt.subplots(2, 4, figsize=(18, 8))\n",
    "loss_keys = [\"g_loss\", \"d_loss\", \"d_real\", \"d_fake\"]\n",
    "loss_titles = [\"Generator Loss (BCE)\", \"Discriminator Loss\", \"D(real) mean logit\", \"D(fake) mean logit\"]\n",
    "\n",
    "for col, (key, title) in enumerate(zip(loss_keys, loss_titles)):\n",
    "    for row_idx, (run_name, label) in enumerate([\n",
    "        (\"p1c_dcgan_full_aug\", \"Best: aligned + full aug\"),\n",
    "        (\"p1a_dcgan_128\", \"Worst: raw 128×128\"),\n",
    "    ]):\n",
    "        ax = axes[row_idx][col]\n",
    "        h = runs[run_name][\"history\"]\n",
    "        vals = h[key]\n",
    "        epochs = range(1, len(vals) + 1)\n",
    "        ax.plot(epochs, vals, linewidth=1.2)\n",
    "        ax.set_title(f\"{title}\", fontsize=9)\n",
    "        ax.set_xlabel(\"Epoch\", fontsize=8)\n",
    "        if col == 0:\n",
    "            ax.set_ylabel(label, fontsize=9, fontweight=\"bold\")\n",
    "\n",
    "fig.suptitle(\"Training Dynamics: Best vs Worst Experiment\", fontsize=13, fontweight=\"bold\", y=1.01)\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "a1b2c3d5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 277848 characters]",
      "text/plain": [
       "<Figure size 1680x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# All experiments overlaid — G loss and D loss\n",
    "fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n",
    "cmap = plt.cm.tab10\n",
    "\n",
    "for i, name in enumerate(run_names):\n",
    "    h = runs[name][\"history\"]\n",
    "    epochs = range(1, len(h[\"g_loss\"]) + 1)\n",
    "    color = cmap(i / len(run_names))\n",
    "    axes[0].plot(epochs, h[\"g_loss\"], label=name, color=color, linewidth=1.2, alpha=0.8)\n",
    "    axes[1].plot(epochs, h[\"d_loss\"], label=name, color=color, linewidth=1.2, alpha=0.8)\n",
    "\n",
    "axes[0].set_title(\"Generator Loss (all experiments)\")\n",
    "axes[0].set_xlabel(\"Epoch\")\n",
    "axes[0].set_ylabel(\"BCE Loss\")\n",
    "axes[0].legend(fontsize=7)\n",
    "\n",
    "axes[1].set_title(\"Discriminator Loss (all experiments)\")\n",
    "axes[1].set_xlabel(\"Epoch\")\n",
    "axes[1].set_ylabel(\"BCE Loss\")\n",
    "axes[1].legend(fontsize=7)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2c3d4e6",
   "metadata": {},
   "source": [
    "## 5. Sample Image Grids — Epoch 50"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "c3d4e5f7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 232076 characters]",
      "text/plain": [
       "<Figure size 1920x960 with 8 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, axes = plt.subplots(2, 4, figsize=(16, 8))\n",
    "sample_runs = run_names  # all 7, plus one empty\n",
    "\n",
    "for idx, name in enumerate(sample_runs):\n",
    "    row, col = divmod(idx, 4)\n",
    "    ax = axes[row][col]\n",
    "    img_path = SAMPLES / name / \"epoch_0050.png\"\n",
    "    if img_path.exists():\n",
    "        img = mpimg.imread(str(img_path))\n",
    "        fid50 = runs[name][\"history\"][\"fid\"].get(\"50\", None)\n",
    "        ax.imshow(img)\n",
    "        ax.set_title(f\"{name}\\nFID@50={fid50:.1f}\" if fid50 else name, fontsize=8)\n",
    "    else:\n",
    "        ax.set_visible(False)\n",
    "    ax.axis(\"off\")\n",
    "\n",
    "# Hide unused subplot\n",
    "if len(sample_runs) < 8:\n",
    "    axes[1][3].axis(\"off\")\n",
    "\n",
    "fig.suptitle(\"Phase 1 — Epoch 50 Samples (4×4 grids)\", fontsize=13, fontweight=\"bold\")\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4e5f6a8",
   "metadata": {},
   "source": [
    "## 6. Per-Group Side-by-Side Visual Comparisons"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "e5f6a7b9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 107260 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 61904 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 134448 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 49232 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "for group_title, experiments in experiment_groups.items():\n",
    "    fig, axes = plt.subplots(1, 2, figsize=(10, 5))\n",
    "    for i, (run_name, label) in enumerate(experiments.items()):\n",
    "        ax = axes[i]\n",
    "        img_path = SAMPLES / run_name / \"epoch_0050.png\"\n",
    "        if img_path.exists():\n",
    "            img = mpimg.imread(str(img_path))\n",
    "            fid50 = runs[run_name][\"history\"][\"fid\"].get(\"50\", None)\n",
    "            ax.imshow(img)\n",
    "            ax.set_title(f\"{label}\\nFID@50 = {fid50:.1f}\", fontsize=10)\n",
    "        ax.axis(\"off\")\n",
    "    fig.suptitle(group_title, fontsize=13, fontweight=\"bold\")\n",
    "    plt.tight_layout()\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f6a7b8c0",
   "metadata": {},
   "source": [
    "## 7. Conclusions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "a7b8c9d1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "======================================================================\n",
      "PHASE 1 CONCLUSIONS\n",
      "======================================================================\n",
      "\n",
      "1A — Resolution:\n",
      "  64×64 (FID 86.7) outperforms 128×128 (FID 115.0). DCGAN lacks capacity for 128×128 in 50 epochs.\n",
      "\n",
      "1B — Alignment:\n",
      "  MTCNN-aligned (FID 42.0) massively outperforms full images (FID 89.0). ~2× improvement — strongest pipeline lever.\n",
      "\n",
      "1C — Augmentation:\n",
      "  Full augmentation (FID 33.4) > H-flip only (37.9) > none (42.0). Gap is moderate; treat as indicative for GANs, validate per-family.\n",
      "\n",
      "1D — Combined dataset:\n",
      "  Aligned-only (FID 42.0) clearly beats combined (87.4). Mixing raw+aligned doubles variance, hurts generation.\n",
      "\n",
      "======================================================================\n",
      "SELECTED PIPELINE FOR DOWNSTREAM PHASES:\n",
      "======================================================================\n",
      "  Data: MTCNN-aligned crops\n",
      "  Resolution: 64×64\n",
      "  Augmentation (GAN): H-flip + rotation ±5° + mild color jitter\n",
      "  Augmentation (VAE/DDPM): H-flip only (validate per-family)\n",
      "  Dataset: Aligned only (no mixing)\n"
     ]
    }
   ],
   "source": [
    "conclusions = {\n",
    "    \"1A — Resolution\": \"64×64 (FID 86.7) outperforms 128×128 (FID 115.0). DCGAN lacks capacity for 128×128 in 50 epochs.\",\n",
    "    \"1B — Alignment\": \"MTCNN-aligned (FID 42.0) massively outperforms full images (FID 89.0). ~2× improvement — strongest pipeline lever.\",\n",
    "    \"1C — Augmentation\": \"Full augmentation (FID 33.4) > H-flip only (37.9) > none (42.0). Gap is moderate; treat as indicative for GANs, validate per-family.\",\n",
    "    \"1D — Combined dataset\": \"Aligned-only (FID 42.0) clearly beats combined (87.4). Mixing raw+aligned doubles variance, hurts generation.\",\n",
    "}\n",
    "\n",
    "pipeline = {\n",
    "    \"Data\": \"MTCNN-aligned crops\",\n",
    "    \"Resolution\": \"64×64\",\n",
    "    \"Augmentation (GAN)\": \"H-flip + rotation ±5° + mild color jitter\",\n",
    "    \"Augmentation (VAE/DDPM)\": \"H-flip only (validate per-family)\",\n",
    "    \"Dataset\": \"Aligned only (no mixing)\",\n",
    "}\n",
    "\n",
    "print(\"=\" * 70)\n",
    "print(\"PHASE 1 CONCLUSIONS\")\n",
    "print(\"=\" * 70)\n",
    "for title, conclusion in conclusions.items():\n",
    "    print(f\"\\n{title}:\")\n",
    "    print(f\"  {conclusion}\")\n",
    "\n",
    "print(f\"\\n{'=' * 70}\")\n",
    "print(\"SELECTED PIPELINE FOR DOWNSTREAM PHASES:\")\n",
    "print(\"=\" * 70)\n",
    "for key, val in pipeline.items():\n",
    "    print(f\"  {key}: {val}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "drl",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
