{"spec_id":"manhattan-gwas","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\nmanhattan-gwas: Manhattan Plot for GWAS\nLibrary: matplotlib 3.10.9 | Python 3.13.13\nQuality: 94/100 | Updated: 2026-05-15\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\n\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nBRAND = \"#009E73\"\n\n# Okabe-Ito palette for chromosome alternation\nCHROM_COLORS = [\"#009E73\", \"#C475FD\"]  # Brand green and vermillion, alternating\n\n# Data - Simulate GWAS results for 22 chromosomes\nnp.random.seed(42)\n\n# Define chromosome sizes (approximate in Mb, scaled down for simulation)\nchrom_sizes = {\n    1: 249,\n    2: 243,\n    3: 198,\n    4: 191,\n    5: 182,\n    6: 171,\n    7: 159,\n    8: 146,\n    9: 141,\n    10: 136,\n    11: 135,\n    12: 134,\n    13: 115,\n    14: 107,\n    15: 103,\n    16: 90,\n    17: 81,\n    18: 78,\n    19: 59,\n    20: 63,\n    21: 48,\n    22: 51,\n}\n\n# Generate SNPs for each chromosome\nchromosomes = []\npositions = []\np_values = []\n\nfor chrom, size in chrom_sizes.items():\n    n_snps = int(size * 40)\n    chrom_positions = np.sort(np.random.randint(1, size * 1_000_000, n_snps))\n\n    chrom_pvals = np.random.uniform(0, 1, n_snps)\n\n    # Add some significant SNPs in certain chromosomes\n    if chrom in [2, 6, 11, 16]:\n        peak_idx = np.random.choice(n_snps, size=np.random.randint(3, 8), replace=False)\n        chrom_pvals[peak_idx] = 10 ** (-np.random.uniform(8, 15, len(peak_idx)))\n\n    # Add suggestive hits in more chromosomes\n    if chrom in [1, 3, 8, 12, 19]:\n        suggestive_idx = np.random.choice(n_snps, size=np.random.randint(2, 5), replace=False)\n        chrom_pvals[suggestive_idx] = 10 ** (-np.random.uniform(5, 7.5, len(suggestive_idx)))\n\n    chromosomes.extend([chrom] * n_snps)\n    positions.extend(chrom_positions)\n    p_values.extend(chrom_pvals)\n\n# Create DataFrame\ndf = pd.DataFrame({\"chromosome\": chromosomes, \"position\": positions, \"p_value\": p_values})\n\n# Calculate -log10(p-value)\ndf[\"-log10p\"] = -np.log10(df[\"p_value\"])\n\n# Calculate cumulative position for x-axis\ndf[\"chrom_num\"] = df[\"chromosome\"]\ndf = df.sort_values([\"chrom_num\", \"position\"]).reset_index(drop=True)\n\n# Add cumulative position offset\nchrom_centers = {}\ncumulative_offset = 0\nfor chrom in sorted(df[\"chrom_num\"].unique()):\n    chrom_mask = df[\"chrom_num\"] == chrom\n    chrom_data = df.loc[chrom_mask].copy()\n    chrom_positions = chrom_data[\"position\"].values + cumulative_offset\n    df.loc[chrom_mask, \"cumulative_pos\"] = chrom_positions\n    chrom_centers[chrom] = cumulative_offset + chrom_data[\"position\"].median()\n    cumulative_offset += chrom_data[\"position\"].max() + 10_000_000\n\n# Define thresholds\ngenome_wide_threshold = -np.log10(5e-8)\nsuggestive_threshold = -np.log10(1e-5)\n\n# Plot\nfig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\n# Plot points by chromosome with alternating Okabe-Ito colors\nfor i, chrom in enumerate(sorted(df[\"chrom_num\"].unique())):\n    chrom_data = df[df[\"chrom_num\"] == chrom]\n    color = CHROM_COLORS[i % 2]\n\n    # Smaller markers for dense data\n    significant_mask = chrom_data[\"-log10p\"] >= genome_wide_threshold\n    regular_data = chrom_data[~significant_mask]\n    significant_data = chrom_data[significant_mask]\n\n    # Plot regular points\n    ax.scatter(\n        regular_data[\"cumulative_pos\"],\n        regular_data[\"-log10p\"],\n        c=color,\n        s=15,\n        alpha=0.6,\n        edgecolors=\"none\",\n        rasterized=True,\n    )\n\n    # Plot significant points with emphasis (using brand color)\n    if len(significant_data) > 0:\n        ax.scatter(\n            significant_data[\"cumulative_pos\"],\n            significant_data[\"-log10p\"],\n            c=BRAND,\n            s=50,\n            alpha=0.9,\n            edgecolors=INK_SOFT,\n            linewidths=0.5,\n            zorder=5,\n            rasterized=True,\n        )\n\n# Add threshold lines\nax.axhline(\n    y=genome_wide_threshold,\n    color=INK_SOFT,\n    linestyle=\"--\",\n    linewidth=2,\n    label=\"Genome-wide significance (p < 5×10⁻⁸)\",\n    alpha=0.6,\n)\nax.axhline(\n    y=suggestive_threshold,\n    color=INK_SOFT,\n    linestyle=\":\",\n    linewidth=2,\n    label=\"Suggestive threshold (p < 1×10⁻⁵)\",\n    alpha=0.4,\n)\n\n# Set x-axis with chromosome labels\nax.set_xticks([chrom_centers[c] for c in sorted(chrom_centers.keys())])\nax.set_xticklabels([str(c) for c in sorted(chrom_centers.keys())], fontsize=16)\nax.set_xlim(0, df[\"cumulative_pos\"].max() * 1.01)\n\n# Set y-axis\nax.set_ylim(0, df[\"-log10p\"].max() * 1.1)\n\n# Style\nax.set_xlabel(\"Chromosome\", fontsize=20, color=INK)\nax.set_ylabel(\"-log₁₀(p-value)\", fontsize=20, color=INK)\nax.set_title(\"manhattan-gwas · matplotlib · anyplot.ai\", fontsize=24, fontweight=\"medium\", color=INK)\nax.tick_params(axis=\"y\", labelsize=16, colors=INK_SOFT, labelcolor=INK_SOFT)\nax.tick_params(axis=\"x\", labelsize=16, colors=INK_SOFT, labelcolor=INK_SOFT)\n\n# Spine styling\nfor spine in (\"left\", \"bottom\"):\n    ax.spines[spine].set_color(INK_SOFT)\nax.spines[\"top\"].set_visible(False)\nax.spines[\"right\"].set_visible(False)\n\n# Legend\nleg = ax.legend(fontsize=16, loc=\"upper right\", frameon=True)\nif leg:\n    leg.get_frame().set_facecolor(ELEVATED_BG)\n    leg.get_frame().set_edgecolor(INK_SOFT)\n    for text in leg.get_texts():\n        text.set_color(INK_SOFT)\n\nplt.tight_layout()\nplt.savefig(f\"plot-{THEME}.png\", dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}