"""
Build the converged-structural-picture schematic figure for the manuscript.

Three panels:
  a — Nucleus + chromosome cartoon with 3 nested radial pleats
  b — 1D unwound view showing T_1, T_1/3, T_1/5 superposition along chromosome
  c — Three-level mapping table (scale, cycles, mechanism, biology refined,
      breakpoint vulnerability)

Output: supplementary_figure_44_structural_picture.{png,svg}
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from matplotlib.patches import Circle, Wedge, FancyBboxPatch, Rectangle
from matplotlib.lines import Line2D
from pathlib import Path

OUT = Path("/sessions/kind-brave-babbage/mnt/Wavelet/harmonic_synthesis_2026-05-01")

WONG = {'blue':'#0072B2','vermil':'#D55E00','green':'#009E73',
        'gold':'#E69F00','sky':'#56B4E9','pink':'#CC79A7','grey':'#999999',
        'lightgold':'#F4D03F','darkgold':'#B7950B'}

# Level colors (hierarchical)
L1_C = WONG['gold']     # Level 1: supra-compartment wave
L2_C = WONG['green']    # Level 2: sub-radial substops
L3_C = WONG['sky']      # Level 3: fine TAD-scale modulation

fig = plt.figure(figsize=(15, 10.5))
gs = gridspec.GridSpec(2, 2, height_ratios=[1.2, 1.0], width_ratios=[1, 1.4],
                       hspace=0.32, wspace=0.20)

# =============================================================================
# Panel a — Nucleus + chromosome with 3 nested radial pleats
# =============================================================================
ax_a = fig.add_subplot(gs[0, 0])
ax_a.set_aspect('equal'); ax_a.axis('off')
ax_a.set_xlim(-1.4, 1.4); ax_a.set_ylim(-1.4, 1.4)

# Nuclear envelope (outer circle)
ne = Circle((0, 0), 1.2, fill=False, edgecolor='black', lw=1.6, zorder=1)
ax_a.add_patch(ne)
ax_a.text(0, 1.30, 'Nuclear envelope', ha='center', fontsize=8.5, color='black',
          style='italic')

# Lamina layer
lamina = plt.matplotlib.patches.Annulus((0, 0), 1.2, 0.10, fc=WONG['blue'],
                                         ec='none', alpha=0.18, zorder=1.5)
ax_a.add_patch(lamina)
ax_a.text(0, -1.32, 'Lamina (B-side)', ha='center', fontsize=8.5,
          color=WONG['blue'], style='italic')

# Speckles (cluster of vermil dots near center)
np.random.seed(7)
for r_off, t_off in [(0.08, 0.3), (0.12, 1.2), (0.06, 2.4),
                       (0.10, 3.4), (0.14, 4.8), (0.05, 5.7)]:
    x = r_off*np.cos(t_off); y = r_off*np.sin(t_off)
    ax_a.add_patch(Circle((x, y), 0.06, fc=WONG['vermil'], ec='black',
                          linewidth=0.4, zorder=3))
ax_a.text(0, -0.30, 'Speckles\n(A-side)', ha='center', fontsize=8.5,
          color=WONG['vermil'], style='italic')

# Chromosome path: parametric radial accordion with 3 nested levels
# r(t) = R_mean + A1*cos(2πt·5)         level 1: 5 cycles
#               + A2*cos(2πt·15)        level 2: 3 sub-cycles per level-1 cycle
#               + A3*cos(2πt·75)        level 3: 5 sub-sub per level-2 cycle
t = np.linspace(0, 1, 1500)
R_mean = 0.65
A1 = 0.45
A2 = 0.13
A3 = 0.04
r_l1   = R_mean + A1*np.cos(2*np.pi*t*5)
r_l12  = r_l1   + A2*np.cos(2*np.pi*t*15)
r_l123 = r_l12  + A3*np.cos(2*np.pi*t*75)

# Map t → angular position around the nucleus (chromosome is wound)
theta = 2*np.pi*t
xs = r_l123 * np.cos(theta)
ys = r_l123 * np.sin(theta)

# Plot in 3 layers: level-1 envelope, level-2 substops, level-3 fine
# To show the layering, plot all three radial profiles on a "polar" mini-strip
# at distinct angular extents.

# Show level 1 (full chromosome) in gold + level 2 overlay in green + level 3 overlay in sky
xs1 = r_l1 * np.cos(theta);   ys1 = r_l1 * np.sin(theta)
xs12 = r_l12 * np.cos(theta); ys12 = r_l12 * np.sin(theta)
ax_a.plot(xs, ys, color=L3_C, lw=0.8, alpha=0.9, zorder=4, label='Level 3 ($T_1/5$, ~5–10 Mbp)')
ax_a.plot(xs12, ys12, color=L2_C, lw=1.2, alpha=0.85, zorder=5, label='Level 2 ($T_1/3$, ~8–15 Mbp)')
ax_a.plot(xs1, ys1, color=L1_C, lw=1.7, alpha=0.85, zorder=6, label='Level 1 ($T_1$, ~25–50 Mbp)')

# Mark the 5 level-1 A-crests (closest to speckles) and B-troughs (closest to lamina)
for k in range(5):
    t_crest = k/5.0
    x_cr = (R_mean - A1) * np.cos(2*np.pi*t_crest)   # crest (closest to centre = A-side)
    y_cr = (R_mean - A1) * np.sin(2*np.pi*t_crest)
    ax_a.add_patch(Circle((x_cr, y_cr), 0.04, fc=WONG['vermil'], ec='black',
                          linewidth=0.4, zorder=7))
    t_trough = (k + 0.5)/5.0
    x_tr = (R_mean + A1) * np.cos(2*np.pi*t_trough)
    y_tr = (R_mean + A1) * np.sin(2*np.pi*t_trough)
    ax_a.add_patch(Circle((x_tr, y_tr), 0.04, fc=WONG['blue'], ec='black',
                          linewidth=0.4, zorder=7))
ax_a.text(-1.4, 1.32, 'a', fontsize=15, fontweight='bold', va='top')
ax_a.text(0, -1.55, 'Top view of nucleus: chromosome traces 3 nested radial pleats\n'
                    '(level 1 gold, level 2 green, level 3 sky)',
          ha='center', fontsize=9.5, va='top', style='italic')

# Legend for panel a
legend_elements = [
    Line2D([0],[0], color=L1_C, lw=2.2, label=r'Level 1 ($T_1$, $\sim$25–50 Mbp; $\sim$5 radial cycles)'),
    Line2D([0],[0], color=L2_C, lw=1.5, label=r'Level 2 ($T_1/3$, $\sim$8–15 Mbp; 3 sub-stops/cycle)'),
    Line2D([0],[0], color=L3_C, lw=1.0, label=r'Level 3 ($T_1/5$, $\sim$5–10 Mbp; fine TAD-scale)'),
]
ax_a.legend(handles=legend_elements, fontsize=7.5, loc='upper right',
            framealpha=0.85, frameon=True)

# =============================================================================
# Panel b — Unwound view: T1, T1+T1/3, T1+T1/3+T1/5 superposition
# =============================================================================
ax_b = fig.add_subplot(gs[0, 1])
t = np.linspace(0, 1, 2000)
y1 = A1 * np.cos(2*np.pi*t*5)
y2 = A2 * np.cos(2*np.pi*t*15)
y3 = A3 * np.cos(2*np.pi*t*75)

# Three stacked plots in the same axis with vertical offsets
offset_full = 0.0
offset_l12  = -1.3
offset_l1   = -2.6

ax_b.plot(t, y1 + y2 + y3 + offset_full, color='black', lw=0.9,
          label='Sum: level 1 + 2 + 3')
ax_b.fill_between(t, y1 + offset_full, y1+y2+y3+offset_full,
                  where=(y1+y2+y3 >= y1), color=L3_C, alpha=0.30, lw=0)
ax_b.fill_between(t, y1 + offset_full, y1+y2+y3+offset_full,
                  where=(y1+y2+y3 < y1), color=L3_C, alpha=0.15, lw=0)

ax_b.plot(t, y1 + y2 + offset_l12, color=L2_C, lw=1.0)
ax_b.plot(t, y1 + offset_l1, color=L1_C, lw=1.6)

# Annotations on each trace
ax_b.text(1.02, offset_full + 0.4, 'Sum (all 3 levels)', fontsize=9, va='center',
          color='black', fontweight='bold')
ax_b.text(1.02, offset_l12 + 0.4, 'Level 1 + Level 2\n(15 sub-stops)', fontsize=8.5,
          va='center', color=L2_C, fontweight='bold')
ax_b.text(1.02, offset_l1 + 0.4, 'Level 1 only\n(5 radial cycles)', fontsize=8.5,
          va='center', color=L1_C, fontweight='bold')

# Mark cycle counts
for i in range(5):
    t_pos = (i + 0.5)/5.0
    ax_b.axvline(t_pos, ymin=0.05, ymax=0.95, color=L1_C, lw=0.3, alpha=0.3, zorder=0)

ax_b.axhline(offset_full, color='black', lw=0.4, alpha=0.4)
ax_b.axhline(offset_l12,  color='black', lw=0.4, alpha=0.4)
ax_b.axhline(offset_l1,   color='black', lw=0.4, alpha=0.4)
ax_b.set_xlim(0, 1.35)
ax_b.set_ylim(-3.2, 1.1)
ax_b.set_xticks([0, 0.5, 1.0]); ax_b.set_xticklabels(['0','L/2','L'], fontsize=9.5)
ax_b.set_yticks([])
ax_b.set_xlabel('Position along chromosome', fontsize=10.5)
ax_b.spines['left'].set_visible(False); ax_b.spines['top'].set_visible(False)
ax_b.spines['right'].set_visible(False)
ax_b.text(-0.05, 1.05, 'b', transform=ax_b.transAxes, fontsize=15, fontweight='bold')

# Add labels on the "speckle" / "lamina" extremes
ax_b.text(-0.02, 0.45, 'speckle\n(A)', ha='right', va='center', fontsize=8,
          color=WONG['vermil'], fontweight='bold', rotation=90)
ax_b.text(-0.02, -0.45, 'lamina\n(B)', ha='right', va='center', fontsize=8,
          color=WONG['blue'], fontweight='bold', rotation=90)

# Title with annotation
ax_b.set_title('Unwound view: same scaling rule $T \\propto L^{0.83}$ at all three nested scales',
               fontsize=10.5, loc='left', pad=8)

# =============================================================================
# Panel c — Three-level mapping table
# =============================================================================
ax_c = fig.add_subplot(gs[1, :])
ax_c.set_xlim(0, 12); ax_c.set_ylim(0, 7)
ax_c.axis('off')
ax_c.text(0, 6.7, 'c', fontsize=15, fontweight='bold')
ax_c.text(0.6, 6.5, 'Three nested levels of supra-compartment geometry',
          fontsize=11.5, fontweight='bold')

# Column headers
levels = ['Level 1', 'Level 2', 'Level 3']
colors = [L1_C, L2_C, L3_C]
xstart = [3.0, 6.1, 9.2]
xwidth = 3.0

for i, (lv, c, xs_) in enumerate(zip(levels, colors, xstart)):
    # Header box
    head = FancyBboxPatch((xs_, 5.5), xwidth, 0.8,
                           boxstyle='round,pad=0.05', fc=c, ec='black',
                           linewidth=0.6, alpha=0.85)
    ax_c.add_patch(head)
    ax_c.text(xs_ + xwidth/2, 5.9, lv, fontsize=11, fontweight='bold',
              ha='center', va='center', color='white')

# Row headers
rows = [
    'Wavelength',
    'Cycles per chromosome',
    'Mechanism',
    'Biology refined',
    'Breakpoint vulnerability',
]
yrows = [4.7, 3.9, 3.1, 2.3, 1.5]
for r_, y_ in zip(rows, yrows):
    ax_c.text(0.4, y_, r_, fontsize=9.5, fontweight='bold', va='center', ha='left')

# Cell content
content = [
    # Level 1
    [r'$T_1 \sim 25$–$50$ Mbp',
     r'$\sim 5$ radial excursions',
     'RIF1 / replication-timing\ncoupled coherence',
     'A/B compartment identity;\nradial position $R^2 = 0.93$',
     'Sets the supra-compartment\nframe (no breakpoint signal\nbeyond mean)'],
    # Level 2
    [r'$T_1/3 \sim 8$–$15$ Mbp',
     r'3 sub-stops per cycle ($\sim 15$ total)',
     'Block-copolymer\nphase separation',
     'Radial $\\Delta R^2 = +0.19$\n(F = 759, $p<10^{-16}$);\nReplisome, transcription,\nmutation density',
     '$F_{\\rm CNV} = 27.4$, $F_{\\rm SV} = 16.5$,\n$F_{\\rm TRA} = 13.0$ — $T_1/3$\n\\textbf{captures} all SV breakpoint signal'],
    # Level 3
    [r'$T_1/5 \sim 5$–$10$ Mbp',
     r'$\sim 5$ sub-sub-stops per substop ($\sim 75$ total)',
     'CTCF + cohesin\nloop extrusion',
     r'Continuous TAD-scale '
     '\nrefinement of TSA-seq, RT,\ngene/mut. density',
     '\\textbf{Saturates} for sparse SVs\n(CNV $p=0.10$, TRA $p=0.99$)\nbut continuous biology refines'],
]
for col, (xs_, c, items) in enumerate(zip(xstart, colors, content)):
    for row, (y_, txt) in enumerate(zip(yrows, items)):
        # Render with simple text (avoid LaTeX bolds since matplotlib won't compile them)
        clean = txt.replace('\\textbf{', '').replace('}', '').replace('\\sim', '~').replace('$', '')
        ax_c.text(xs_ + xwidth/2, y_, clean,
                  ha='center', va='center', fontsize=8.5, color='black',
                  linespacing=1.25)
    # Column separator (light)
    if col < 2:
        ax_c.plot([xs_+xwidth+0.1, xs_+xwidth+0.1], [1.0, 5.4],
                  color='grey', lw=0.4, alpha=0.5)

# Bottom caption
ax_c.text(6, 0.5,
          'All three scales obey the same scaling rule $T \\propto L^{0.83}$ within $\\pm 1$ SE.\n'
          'Phenomenologically self-similar (Kleiber-style); mechanism-distinct in execution.',
          fontsize=10, ha='center', va='center', style='italic',
          bbox=dict(boxstyle='round,pad=0.4', fc='#fafafa', ec='black', lw=0.6))

plt.suptitle('A converged structural picture of the chromosome:\n'
             'a self-similar radial pleat at three nested scales, mechanism-distinct in execution',
             fontsize=12.5, fontweight='bold', y=0.995)

plt.savefig(OUT / "supplementary_figure_44_structural_picture.png",
            dpi=200, bbox_inches='tight')
plt.savefig(OUT / "supplementary_figure_44_structural_picture.svg",
            bbox_inches='tight')
plt.close(fig)
print("Saved: supplementary_figure_44_structural_picture.png/svg")
