Skip to content

Commit 7472dd4

Browse files
committed
docs(notebook): redraw shell-zoom diagram for clarity
Original diagram failed to communicate the message: - The inner-zone circle was tiny and visually dominated by the ligand bulk inside the shell band, which made the diagram look like "shell band covers the whole ligand → no benefit." - The "guaranteed bulk - skipped" label sat over the ligand body rather than inside the inner circle, suggesting the wrong region was being skipped. - Did not show that ligand bulk inside the shell band is what gets SAS-rejected (different mechanism than the shell envelope itself). Redrawn: - Larger, clearly elongated ligand (R_max=15, R_min=5, ratio 3:1) at honest scale where R_min is meaningful. - Ligand bulk shown in dark red INSIDE the shell band, with explicit "SAS-rejected within shell band" callout (separates the two rejection mechanisms). - Inner zone is small, dark, and clearly inside the bulk — its callout explicitly says shell preemptively skips just that tiny deep-interior zone. - Three green surface-point markers along short/diagonal/long axes with distance-from-COM labels — each visibly inside the shell band, demonstrating no surface direction is missed.
1 parent 4b24a9c commit 7472dd4

1 file changed

Lines changed: 98 additions & 67 deletions

File tree

notebooks/maws/space_analysis.ipynb

Lines changed: 98 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -542,104 +542,135 @@
542542
"metadata": {},
543543
"outputs": [],
544544
"source": [
545+
"import math as _math\n",
546+
"\n",
545547
"from matplotlib.patches import Circle, Ellipse\n",
546548
"\n",
547-
"# Elongated ligand: long axis along x.\n",
548-
"R_long = 6.0 # tip-of-blob distance from COM (R_max)\n",
549-
"R_short = 2.0 # short-axis blob distance from COM (R_min)\n",
550-
"buffer = 1.0 # smaller than real 5 Å for visual clarity\n",
551-
"reach = 2.0\n",
549+
"# Elongated ligand. Half-axes large enough that R_min is a meaningful\n",
550+
"# fraction of R_max (~ a 3:1 cigar) — typical of an elongated protein.\n",
551+
"R_long = 15.0 # x half-axis = R_max (long-axis surface distance)\n",
552+
"R_short = 5.0 # y half-axis = R_min (short-axis surface distance)\n",
553+
"buffer = 4.0 # close to the real 5 Å SHELL_INNER_BUFFER\n",
554+
"reach = 4.0 # smaller than real 10 Å for a tight figure\n",
552555
"\n",
553-
"inner = max(0.0, R_short - buffer)\n",
554-
"outer = R_long + reach\n",
556+
"inner = max(0.0, R_short - buffer) # = 1.0\n",
557+
"outer = R_long + reach # = 19.0\n",
555558
"\n",
556-
"fig, ax = plt.subplots(figsize=(10, 6))\n",
559+
"fig, ax = plt.subplots(figsize=(12, 7))\n",
557560
"\n",
558-
"# Outside (not sampled) — light blue background\n",
559-
"ax.add_patch(Circle((0, 0), 12, facecolor=\"#e8f4ff\", edgecolor=\"none\", zorder=0))\n",
560-
"# Shell band (sampled, SAS decides) — light green\n",
561-
"ax.add_patch(\n",
562-
" Circle((0, 0), outer, facecolor=\"#d8f5d8\", edgecolor=\"green\", lw=2, zorder=1)\n",
563-
")\n",
564-
"# Inner zone (guaranteed bulk, not sampled) — light gray\n",
565-
"ax.add_patch(\n",
566-
" Circle(\n",
567-
" (0, 0), inner, facecolor=\"#cccccc\", edgecolor=\"orange\", lw=2, ls=\"--\", zorder=2\n",
568-
" )\n",
569-
")\n",
570-
"# Ligand blob: elongated ellipse along x\n",
561+
"# Background tiers (drawn back-to-front).\n",
562+
"# Outside the envelope — solvent we don't sample.\n",
563+
"ax.add_patch(Circle((0, 0), 24, facecolor=\"#e8f4ff\", edgecolor=\"none\"))\n",
564+
"# Shell band [inner, outer] — sampling region.\n",
565+
"ax.add_patch(Circle((0, 0), outer, facecolor=\"#d8f5d8\", edgecolor=\"green\", lw=2.5))\n",
566+
"# Ligand bulk (will be SAS-rejected within the shell band).\n",
571567
"ax.add_patch(\n",
572568
" Ellipse(\n",
573569
" (0, 0),\n",
574570
" 2 * R_long,\n",
575571
" 2 * R_short,\n",
576-
" facecolor=\"dimgray\",\n",
577-
" edgecolor=\"black\",\n",
572+
" facecolor=\"#c98a8a\",\n",
573+
" edgecolor=\"darkred\",\n",
578574
" lw=1.5,\n",
579-
" alpha=0.85,\n",
580-
" zorder=3,\n",
575+
" alpha=0.9,\n",
581576
" )\n",
582577
")\n",
583-
"# COM\n",
584-
"ax.plot(0, 0, marker=\"*\", color=\"magenta\", markersize=18, zorder=4)\n",
585-
"\n",
586-
"# Direction arrows showing where the surface is\n",
587-
"# Short-axis surface point (top)\n",
588-
"ax.plot(0, R_short, marker=\"o\", color=\"red\", markersize=8, zorder=5)\n",
589-
"ax.annotate(\n",
590-
" \"surface point on short axis\\n(distance = R_min)\",\n",
591-
" xy=(0, R_short),\n",
592-
" xytext=(3, 4.5),\n",
593-
" arrowprops={\"arrowstyle\": \"->\", \"color\": \"red\", \"lw\": 1},\n",
594-
" fontsize=9,\n",
595-
" color=\"red\",\n",
596-
")\n",
597-
"# Long-axis surface point (right)\n",
598-
"ax.plot(R_long, 0, marker=\"o\", color=\"red\", markersize=8, zorder=5)\n",
599-
"ax.annotate(\n",
600-
" \"surface point on long axis\\n(distance = R_max)\",\n",
601-
" xy=(R_long, 0),\n",
602-
" xytext=(R_long + 1.5, -3),\n",
603-
" arrowprops={\"arrowstyle\": \"->\", \"color\": \"red\", \"lw\": 1},\n",
604-
" fontsize=9,\n",
605-
" color=\"red\",\n",
578+
"# Inner zone — preemptively skipped by the shell envelope.\n",
579+
"ax.add_patch(\n",
580+
" Circle((0, 0), inner, facecolor=\"#5a5a5a\", edgecolor=\"orange\", lw=2, ls=\"--\")\n",
606581
")\n",
582+
"# COM marker.\n",
583+
"ax.plot(0, 0, marker=\"*\", color=\"magenta\", markersize=18, zorder=10)\n",
584+
"\n",
585+
"\n",
586+
"# --- Surface points at different directions on the ligand boundary ---\n",
587+
"# Top: short axis. Right tip: long axis. Diagonal: in between.\n",
588+
"def ellipse_point(theta):\n",
589+
" return (R_long * _math.cos(theta), R_short * _math.sin(theta))\n",
607590
"\n",
608-
"# Annotations for the three regions\n",
591+
"\n",
592+
"surface_pts = [\n",
593+
" (ellipse_point(_math.pi / 2), \"short-axis surface\\n|r| = R_min\", (5, 9)),\n",
594+
" (ellipse_point(0), \"long-axis surface\\n|r| = R_max\", (R_long + 2, 4.5)),\n",
595+
" (ellipse_point(_math.pi / 4), \"diagonal surface\\n|r| ≈ 9.5\", (R_long + 2, -3)),\n",
596+
"]\n",
597+
"for (px, py), label, (lx, ly) in surface_pts:\n",
598+
" ax.plot(\n",
599+
" px,\n",
600+
" py,\n",
601+
" marker=\"o\",\n",
602+
" color=\"darkgreen\",\n",
603+
" markersize=10,\n",
604+
" zorder=11,\n",
605+
" markeredgecolor=\"white\",\n",
606+
" markeredgewidth=1.5,\n",
607+
" )\n",
608+
" ax.annotate(\n",
609+
" label,\n",
610+
" xy=(px, py),\n",
611+
" xytext=(lx, ly),\n",
612+
" fontsize=10,\n",
613+
" color=\"darkgreen\",\n",
614+
" arrowprops={\"arrowstyle\": \"->\", \"color\": \"darkgreen\", \"lw\": 1.2},\n",
615+
" )\n",
616+
"\n",
617+
"# --- Region legend boxes ---\n",
609618
"ax.text(\n",
610619
" 0,\n",
611-
" -1.2,\n",
612-
" \"guaranteed bulk\\n(< R_min − buffer)\\n← skipped →\",\n",
620+
" -10,\n",
621+
" \"shell band — sampled\\n(SAS rejects ligand bulk inside,\\n accepts surface layer)\",\n",
613622
" ha=\"center\",\n",
614-
" va=\"top\",\n",
615-
" fontsize=9,\n",
616-
" color=\"black\",\n",
617-
" bbox={\"facecolor\": \"white\", \"edgecolor\": \"orange\", \"boxstyle\": \"round\"},\n",
623+
" fontsize=10,\n",
624+
" color=\"darkgreen\",\n",
625+
" bbox={\"facecolor\": \"white\", \"edgecolor\": \"darkgreen\", \"boxstyle\": \"round,pad=0.4\"},\n",
618626
")\n",
619627
"ax.text(\n",
620628
" 0,\n",
621-
" outer + 0.3,\n",
622-
" \"shell band [inner, outer] — sampled; SAS rejects bulk-side, accepts surface-side\",\n",
629+
" 22,\n",
630+
" \"outside envelope (|r| > R_max + reach) — not sampled\",\n",
631+
" ha=\"center\",\n",
632+
" fontsize=10,\n",
633+
" color=\"steelblue\",\n",
634+
" bbox={\"facecolor\": \"white\", \"edgecolor\": \"steelblue\", \"boxstyle\": \"round,pad=0.4\"},\n",
635+
")\n",
636+
"ax.text(\n",
637+
" -12,\n",
638+
" 13,\n",
639+
" \"ligand bulk\\n(SAS-rejected\\nwithin shell band)\",\n",
623640
" ha=\"center\",\n",
624641
" fontsize=9,\n",
625-
" color=\"green\",\n",
626-
" bbox={\"facecolor\": \"white\", \"edgecolor\": \"green\", \"boxstyle\": \"round\"},\n",
642+
" color=\"darkred\",\n",
643+
" bbox={\"facecolor\": \"white\", \"edgecolor\": \"darkred\", \"boxstyle\": \"round,pad=0.3\"},\n",
644+
")\n",
645+
"ax.annotate(\n",
646+
" \"\",\n",
647+
" xy=(-6, 2.5),\n",
648+
" xytext=(-11, 11),\n",
649+
" arrowprops={\"arrowstyle\": \"->\", \"color\": \"darkred\", \"lw\": 1.2},\n",
627650
")\n",
628651
"ax.text(\n",
629-
" 0,\n",
630-
" 11.2,\n",
631-
" \"outside the envelope (> R_max + reach) — not sampled\",\n",
652+
" 8,\n",
653+
" 13,\n",
654+
" \"shell skips this tiny\\ndeep-interior zone\\n(|r| < R_min − buffer)\",\n",
632655
" ha=\"center\",\n",
633656
" fontsize=9,\n",
634-
" color=\"steelblue\",\n",
635-
" bbox={\"facecolor\": \"white\", \"edgecolor\": \"steelblue\", \"boxstyle\": \"round\"},\n",
657+
" color=\"darkorange\",\n",
658+
" bbox={\"facecolor\": \"white\", \"edgecolor\": \"darkorange\", \"boxstyle\": \"round,pad=0.3\"},\n",
659+
")\n",
660+
"ax.annotate(\n",
661+
" \"\",\n",
662+
" xy=(0.5, 0.5),\n",
663+
" xytext=(7, 11),\n",
664+
" arrowprops={\"arrowstyle\": \"->\", \"color\": \"darkorange\", \"lw\": 1.2},\n",
636665
")\n",
637666
"\n",
638-
"ax.set_xlim(-12, 12)\n",
639-
"ax.set_ylim(-8, 12)\n",
667+
"ax.set_xlim(-24, 24)\n",
668+
"ax.set_ylim(-13, 24)\n",
640669
"ax.set_aspect(\"equal\")\n",
641670
"ax.set_title(\n",
642-
" \"Why Shell with `inner = R_min − buffer` doesn't miss surface points\", fontsize=11\n",
671+
" \"Shell-band coverage on an elongated ligand\\n\"\n",
672+
" \"(green dots = surface points; all sit inside the shell band)\",\n",
673+
" fontsize=12,\n",
643674
")\n",
644675
"ax.grid(True, alpha=0.3)\n",
645676
"ax.axhline(0, color=\"lightgray\", lw=0.5)\n",

0 commit comments

Comments
 (0)