"""E8 figure — the vertical claim: n-parent recombination exceeds any parent (Fisher–Muller). The society headline. Decorrelated *parents* are specialists (expert on some loci, agnostic on the rest); an *offspring* recombined from all of them can be fitter than any parent — capability that *exceeds* every component, not just recovers a ceiling. Unlike biological sex there is no two-parent limit, so capability climbs toward the optimum as the parent pool grows and decorrelates. Two panels: (A) deployed capability (mode-genotype fitness) vs parent count at ρ=0 — sexual recombination reaches the optimum (a genotype no parent had) while the best single parent and the mean-mixture "model soup" plateau below; (B) the decorrelation control — sexual capability vs parent count for ρ ∈ {0, 0.5, 1}: decorrelated parents (ρ=0) climb to the optimum, identical parents (ρ=1) buy nothing. Reads only the committed bundle. Usage: python figures/plot_figS9_specialist_superparent.py [results/figS9_specialist_superparent] """ from __future__ import annotations import sys from pathlib import Path import matplotlib.pyplot as plt import numpy as np sys.path.insert(0, str(Path(__file__).parent)) from _figlib import load_bundle, mean_ci, savefig, letter_axes # noqa: E402 def main(results_dir: str = "results/figS9_specialist_superparent") -> None: df, cfg = load_bundle(results_dir) L = cfg["society"]["L"] rhos = sorted(df["rho"].unique()) fig, axes = plt.subplots(1, 2, figsize=(13, 5)) # Panel A: best-parent vs average vs sexual, at rho=0. ax = axes[0] d0 = df[df["rho"] == 0.0] for col, c, lab in [("best_parent", "#7f7f7f", "best single parent"), ("average", "#1f77b4", "average (model soup)"), ("sexual", "#d62728", "sexual recombination")]: k, m, ci = mean_ci(d0, "K_T", col) ax.errorbar(k, m, yerr=ci, fmt="-o", color=c, capsize=3, label=lab) ax.axhline(L, ls=":", color="green", lw=1, label=f"optimum ($L$={L})") ax.set(xlabel="number of parents $K_T$", ylabel="deployed capability (mode fitness)", title="Recombination exceeds any parent (ρ=0):\nsexual reaches the optimum; soup & best-parent plateau") ax.legend(frameon=False, fontsize=9) # Panel B: sexual capability vs K_T for each rho (decorrelation control). ax = axes[1] colors = plt.cm.viridis(np.linspace(0, 0.8, len(rhos))) for rho, c in zip(rhos, colors): sub = df[df["rho"] == rho] k, m, ci = mean_ci(sub, "K_T", "sexual") ax.errorbar(k, m, yerr=ci, fmt="-o", color=c, capsize=3, label=fr"ρ={rho:g}") ax.axhline(L, ls=":", color="green", lw=1, label=f"optimum ($L$={L})") ax.set(xlabel="number of parents $K_T$", ylabel="sexual-recombination capability", title="Decorrelation is the fuel:\nρ=0 climbs to the optimum; ρ=1 (clones) buy nothing") ax.legend(frameon=False, fontsize=9) fig.tight_layout() letter_axes(fig) savefig(fig, results_dir, "figS9_specialist_superparent") if __name__ == "__main__": main(*sys.argv[1:])