{
  "filename": "plot_3.png",
  "iteration": 3,
  "description": "Final 2-panel provenance figure: evolutionary tree and GO curation decision summary",
  "timestamp": "2026-07-05 04:13:13",
  "code": "\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as mpatches\nimport numpy as np\n\nfig, axes = plt.subplots(1, 2, figsize=(16, 8))\n\n# Panel A: Evolutionary tree showing when SHG\u2192SHS occurred\nax1 = axes[0]\nax1.set_title(\"A. Evolutionary Timing of CASP12 SHG\u2192SHS Mutation\", fontsize=12, fontweight='bold')\nax1.set_xlim(-2, 10)\nax1.set_ylim(-0.5, 6.5)\nax1.axis('off')\n\n# Simple cladogram\ntree_lines = [\n    ([1, 1], [0.5, 5.5], 'black', 2),\n    ([1, 3], [1.0, 1.0], 'black', 1.5),\n    ([3, 3], [1.0, 0.5], 'black', 1.5),\n    ([3, 3], [1.0, 1.5], 'black', 1.5),\n    ([1, 2], [4.0, 4.0], 'black', 1.5),\n    ([2, 2], [4.0, 3.0], 'black', 1.5),\n    ([2, 3], [4.0, 5.0], 'black', 1.5),\n    ([3, 3], [5.0, 4.5], 'black', 1.5),\n    ([3, 3], [5.0, 5.5], 'red', 2.5),\n]\n\nfor xs, ys, color, lw in tree_lines:\n    ax1.plot(xs, ys, color=color, linewidth=lw)\n\nspecies_labels = [\n    (3.2, 0.5, \"Rat (Q920D5)\", \"SHG \u2713\", \"green\", \"420 aa\"),\n    (3.2, 1.5, \"Mouse (O08736)\", \"SHG \u2713\", \"green\", \"419 aa\"),\n    (2.2, 3.0, \"Macaque (Q153Z0)\", \"SHG \u2713\", \"green\", \"421 aa\"),\n    (3.2, 4.5, \"Chimp (A0A2J8LBR9)\", \"SHG \u2713\", \"green\", \"341 aa\"),\n    (3.2, 5.5, \"HUMAN (Q6UXS9)\", \"SHS \u2717\", \"red\", \"341 aa\"),\n]\n\nfor x, y, name, shg, color, length in species_labels:\n    weight = 'bold' if 'HUMAN' in name else 'normal'\n    ax1.text(x, y, f\"{name}\", fontsize=9, va='center', fontweight=weight, \n             color='black' if 'HUMAN' not in name else 'red')\n    bbox = dict(boxstyle='round,pad=0.2', facecolor='#C8E6C9' if color=='green' else '#FFCDD2',\n                edgecolor=color, linewidth=1.5)\n    ax1.text(x+4.2, y, shg, fontsize=10, fontweight='bold', va='center', color=color, bbox=bbox)\n    ax1.text(x+5.8, y, length, fontsize=8, va='center', color='gray')\n\nax1.annotate('SHG\u2192SHS\\nmutation\\n(human-specific\\n< 6-7 MYA)',\n            xy=(3, 5.25), xytext=(5.5, 6.2),\n            fontsize=9, fontweight='bold', color='red', ha='center',\n            arrowprops=dict(arrowstyle='->', color='red', lw=2),\n            bbox=dict(boxstyle='round', facecolor='#FFCDD2', edgecolor='red'))\n\nax1.text(0, -0.3, \"~80 MYA\", fontsize=8, ha='center', color='gray')\nax1.text(3, -0.3, \"Present\", fontsize=8, ha='center', color='gray')\nax1.annotate('', xy=(3, -0.1), xytext=(0, -0.1),\n            arrowprops=dict(arrowstyle='->', color='gray', lw=1))\n\n# Panel B: GO Decision Table\nax2 = axes[1]\nax2.set_title(\"B. GO:0004197 Curation Decision Summary\", fontsize=12, fontweight='bold')\nax2.axis('off')\n\ntable_data = [\n    [\"Evidence Type\", \"Finding\", \"Direction\", \"Weight\"],\n    [\"SHG box mutation\", \"Gly173\u2192Ser (human-only)\", \"REFUTES\", \"\u2605\u2605\u2605\u2605\u2605\"],\n    [\"Stop codon\", \"Trunc at pos 125 (most)\", \"REFUTES\", \"\u2605\u2605\u2605\u2605\u2605\"],\n    [\"Biochemical (rat)\", \"No substrates cleavable\", \"REFUTES\", \"\u2605\u2605\u2605\u2605\u2606\"],\n    [\"UniProt name\", \"\\\"Inactive caspase-12\\\"\", \"REFUTES\", \"\u2605\u2605\u2605\u2605\u2606\"],\n    [\"IKR annotation\", \"NOT|enables GO:0004197\", \"REFUTES\", \"\u2605\u2605\u2605\u2605\u2605\"],\n    [\"Autoprocess site\", \"ATAD\u2192ASAD (lost)\", \"REFUTES\", \"\u2605\u2605\u2605\u2606\u2606\"],\n    [\"C299A mutant\", \"Non-catalytic role proven\", \"REFUTES\", \"\u2605\u2605\u2605\u2605\u2606\"],\n    [\"AlphaFold\", \"Ser173 adds steric bulk\", \"QUALIFIES\", \"\u2605\u2605\u2605\u2606\u2606\"],\n    [\"Evolution\", \"Chimp retains SHG\", \"REFUTES\", \"\u2605\u2605\u2605\u2605\u2606\"],\n    [\"QACRG motif\", \"Conserved (full-length)\", \"Supports\", \"\u2605\u2606\u2606\u2606\u2606\"],\n    [\"\", \"\", \"\", \"\"],\n    [\"VERDICT\", \"OVER-ANNOTATED\", \"Remove IBA\", \"\"],\n]\n\ny_start = 0.95\nfor i, row in enumerate(table_data):\n    y = y_start - i * 0.072\n    is_header = i == 0\n    is_verdict = i == len(table_data) - 1\n    \n    for j, (val, x_pos) in enumerate(zip(row, [0.0, 0.28, 0.62, 0.82])):\n        if is_header:\n            ax2.text(x_pos, y, val, fontsize=9, fontweight='bold', transform=ax2.transAxes, \n                    va='center', color='darkblue')\n        elif is_verdict and val:\n            ax2.text(x_pos, y, val, fontsize=11, fontweight='bold', transform=ax2.transAxes,\n                    va='center', color='purple',\n                    bbox=dict(boxstyle='round', facecolor='#E1BEE7', edgecolor='purple'))\n        elif j == 2 and val and not is_header:\n            bg = '#FFCDD2' if val == 'REFUTES' else ('#FFF9C4' if val == 'QUALIFIES' else '#C8E6C9')\n            fc = 'darkred' if val == 'REFUTES' else ('darkorange' if val == 'QUALIFIES' else 'darkgreen')\n            ax2.text(x_pos, y, val, fontsize=8, fontweight='bold', transform=ax2.transAxes,\n                    va='center', color=fc,\n                    bbox=dict(boxstyle='round,pad=0.2', facecolor=bg, edgecolor='gray'))\n        else:\n            ax2.text(x_pos, y, val, fontsize=8, transform=ax2.transAxes, va='center')\n\nplt.tight_layout()\nplt.savefig('casp12_final_provenance.png', dpi=150, bbox_inches='tight')\nplt.show()\nprint(\"Final provenance figure saved\")\n",
  "plot_number": 3
}