{
  "filename": "plot_3.png",
  "iteration": 3,
  "description": "Final comprehensive 4-panel visualization: active site, nearest neighbors, GO hierarchy, and verdict",
  "timestamp": "2026-06-24 04:41:57",
  "code": "\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as mpatches\nimport numpy as np\n\nfig = plt.figure(figsize=(18, 12))\n\n# Create a 2x2 grid\ngs = fig.add_gridspec(2, 2, hspace=0.35, wspace=0.3)\n\n# ========== Panel A: Active Site Conservation ==========\nax1 = fig.add_subplot(gs[0, 0])\n\nresidues = ['C47\\n(CP)', 'C166\\n(CR)', 'T44', 'E50', 'R120']\nx = np.arange(len(residues))\n\n# All conserved\nbars = ax1.bar(x, [1]*5, color=['#e74c3c', '#e74c3c', '#3498db', '#3498db', '#3498db'], \n               alpha=0.85, width=0.6, edgecolor='white', linewidth=2)\n\n# Labels on bars\nres_labels = ['C', 'C', 'T', 'E', 'R']\nfor i, (bar, label) in enumerate(zip(bars, res_labels)):\n    ax1.text(i, 0.5, label, ha='center', va='center', fontsize=18, fontweight='bold', color='white')\n\nax1.set_xticks(x)\nax1.set_xticklabels(residues, fontsize=10)\nax1.set_ylim(0, 1.4)\nax1.set_yticks([0, 1])\nax1.set_yticklabels(['Absent', 'Present'])\nax1.set_title('A. Catalytic Residue Conservation\\n(Q88K52 vs S. typhimurium AhpC)', fontsize=11, fontweight='bold')\n\nax1.text(2, 1.2, '5/5 CONSERVED \u2014 Active peroxidase', ha='center', fontsize=11, fontweight='bold', color='#27ae60',\n         bbox=dict(boxstyle='round,pad=0.3', facecolor='#d5f5e3', edgecolor='#27ae60', linewidth=1.5))\n\nlegend1 = [mpatches.Patch(color='#e74c3c', alpha=0.85, label='Essential Cys (CP/CR)'),\n           mpatches.Patch(color='#3498db', alpha=0.85, label='Active-site proximal')]\nax1.legend(handles=legend1, fontsize=8, loc='upper left')\n\n# ========== Panel B: Nearest Neighbor Ranking ==========\nax2 = fig.add_subplot(gs[0, 1])\n\nproteins = [\n    ('S. typhimurium AhpC', 69.0, '#e74c3c', 'AhpF-dep'),\n    ('E. coli AhpC', 67.9, '#e74c3c', 'AhpF-dep'),\n    ('Human PRDX2', 47.6, '#3498db', 'Trx-dep'),\n    ('P. putida tsaA', 47.3, '#3498db', 'Trx-dep'),\n    ('S. cerevisiae TSA1', 46.5, '#3498db', 'Trx-dep'),\n    ('H. pylori AhpC', 42.9, '#3498db', 'Trx-dep'),\n    ('M. tuberculosis AhpC', 38.3, '#f39c12', 'AhpD-dep'),\n]\n\nnames = [p[0] for p in proteins]\nidentities = [p[1] for p in proteins]\ncolors = [p[2] for p in proteins]\n\ny_pos = np.arange(len(proteins))\nbars2 = ax2.barh(y_pos, identities, color=colors, alpha=0.85, height=0.65, edgecolor='white')\n\nfor i, (bar, val) in enumerate(zip(bars2, identities)):\n    ax2.text(val + 0.8, i, f'{val:.1f}%', va='center', fontsize=9, fontweight='bold')\n\nax2.set_yticks(y_pos)\nax2.set_yticklabels(names, fontsize=9)\nax2.set_xlabel('Sequence Identity (%)', fontsize=10)\nax2.set_title('B. Nearest Characterized Homologs', fontsize=11, fontweight='bold')\nax2.set_xlim(0, 82)\nax2.invert_yaxis()\n\n# Gap annotation\nax2.axhline(y=1.5, color='gray', linestyle='--', alpha=0.6, linewidth=1.5)\nax2.annotate('~20 pp gap', xy=(57, 1.5), fontsize=9, color='gray', fontweight='bold',\n             ha='center', va='center', bbox=dict(boxstyle='round', facecolor='white', edgecolor='gray'))\n\nlegend2 = [mpatches.Patch(color='#e74c3c', alpha=0.85, label='AhpF-dependent'),\n           mpatches.Patch(color='#3498db', alpha=0.85, label='Trx-dependent'),\n           mpatches.Patch(color='#f39c12', alpha=0.85, label='AhpD-dependent')]\nax2.legend(handles=legend2, fontsize=8, loc='lower right')\n\n# ========== Panel C: GO Term Hierarchy ==========\nax3 = fig.add_subplot(gs[1, 0])\nax3.set_xlim(0, 10)\nax3.set_ylim(0, 10)\nax3.axis('off')\nax3.set_title('C. GO Term Hierarchy & Assessment', fontsize=11, fontweight='bold')\n\n# Draw hierarchy\nterms = [\n    (0.3, 8.5, 'GO:0051920', 'peroxiredoxin activity', '#27ae60', '\u2713 RECOMMENDED'),\n    (1.0, 7.2, 'GO:0140824', 'Trx-dependent Prx activity', '#e67e22', '\u25b3 Not demonstrated'),\n    (1.7, 5.9, 'GO:0008379', 'thioredoxin peroxidase activity', '#e74c3c', '\u25b3 SEED (too specific)'),\n    (0.3, 4.3, 'GO:0102039', 'NADH-dependent Prx activity', '#27ae60', '\u2713 ALSO APPROPRIATE'),\n]\n\nfor x, y, go_id, name, color, verdict in terms:\n    ax3.text(x, y, f'{go_id}', fontsize=9, fontweight='bold', color='#2c3e50')\n    ax3.text(x, y - 0.45, f'{name}', fontsize=8.5, color='#555')\n    ax3.text(8.5, y - 0.2, verdict, fontsize=8, ha='center', fontweight='bold', color=color,\n             bbox=dict(boxstyle='round,pad=0.2', facecolor=color+'18', edgecolor=color, linewidth=1.5))\n\n# Arrows for hierarchy\nax3.annotate('', xy=(0.9, 7.7), xytext=(0.5, 8.2), arrowprops=dict(arrowstyle='->', color='gray', lw=1.5))\nax3.annotate('', xy=(1.6, 6.4), xytext=(1.2, 6.9), arrowprops=dict(arrowstyle='->', color='gray', lw=1.5))\nax3.text(0.3, 4.9, '(sibling \u2014 separate branch)', fontsize=7.5, color='gray', style='italic')\n\n# Key quote box\nax3.text(5, 2.5, '\"Tp lacks AhpF, the typical reductant\\nfor such enzymes\"', \n         ha='center', fontsize=9, style='italic', color='#8e44ad',\n         bbox=dict(boxstyle='round,pad=0.4', facecolor='#f4ecf7', edgecolor='#8e44ad', linewidth=1.5))\nax3.text(5, 1.6, '\u2014 Parsonage et al. 2010 (Poole lab), PMID:20304799', \n         ha='center', fontsize=7.5, color='#8e44ad')\n\n# ========== Panel D: Verdict Summary ==========\nax4 = fig.add_subplot(gs[1, 1])\nax4.set_xlim(0, 10)\nax4.set_ylim(0, 10)\nax4.axis('off')\nax4.set_title('D. Verdict & Failure Mode Analysis', fontsize=11, fontweight='bold')\n\n# Verdict box\nax4.text(5, 9, 'PARTIALLY SUPPORTED / TOO GENERAL', ha='center', fontsize=13, fontweight='bold', color='#e67e22',\n         bbox=dict(boxstyle='round,pad=0.5', facecolor='#fdebd0', edgecolor='#e67e22', linewidth=2.5))\n\n# Failure mode\nax4.text(5, 7.8, 'Failure mode #1: Granularity (family-vs-subfamily)', ha='center', fontsize=10, \n         fontweight='bold', color='#d35400')\n\n# Checklist\nchecks = [\n    ('\u2713', 'Peroxidase activity confirmed (5/5 catalytic residues)', '#27ae60'),\n    ('\u2713', 'Correct fold & subfamily (AhpC/Prx1, cd03015)', '#27ae60'),\n    ('\u2713', 'Not a pseudo-enzyme (failure mode #2 ruled out)', '#27ae60'),\n    ('\u2713', 'Not mis-placed (failure mode #3 ruled out)', '#27ae60'),\n    ('\u2717', 'Thioredoxin as reductant: NOT demonstrated', '#e74c3c'),\n    ('\u2717', 'AhpF is \"the typical reductant\" (Poole lab)', '#e74c3c'),\n    ('\u2717', 'Separate Trx-dep Prx (tsaA) in same organism', '#e74c3c'),\n]\n\nfor i, (sym, text, color) in enumerate(checks):\n    y = 6.8 - i * 0.65\n    ax4.text(0.5, y, sym, fontsize=12, fontweight='bold', color=color)\n    ax4.text(1.2, y, text, fontsize=8.5, color='#2c3e50')\n\n# Recommendation\nax4.text(5, 2.2, 'Recommended: GENERALIZE to\\nGO:0051920 (peroxiredoxin activity)', \n         ha='center', fontsize=10, fontweight='bold', color='#2980b9',\n         bbox=dict(boxstyle='round,pad=0.4', facecolor='#d6eaf8', edgecolor='#2980b9', linewidth=2))\n\nplt.savefig('final_verdict_summary.png', dpi=150, bbox_inches='tight')\nplt.show()\nprint(\"Final summary figure saved.\")\n",
  "plot_number": 3
}