{"spec_id":"volcano-basic","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nvolcano-basic: Volcano Plot for Statistical Significance\nLibrary: seaborn 0.13.2 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-05-14\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\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\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\n# Okabe-Ito palette for volcano plot\n# Non-significant: adaptive neutral\n# Down-regulated: #4467A3 (Okabe-Ito blue)\n# Up-regulated: #AE3030 (Okabe-Ito orange)\nNOT_SIG_COLOR = INK_MUTED\nDOWN_COLOR = \"#4467A3\"\nUP_COLOR = \"#AE3030\"\n\n# Data generation\nnp.random.seed(42)\nn_genes = 500\n\n# Single normal distribution for log2 fold changes\nlog2_fold_change = np.random.normal(0, 0.8, n_genes)\n\n# Generate p-values: correlation with fold change magnitude for realistic volcano shape\n# Genes with larger fold changes tend to have lower p-values\nbase_pvalues = 10 ** (-(np.abs(log2_fold_change) ** 1.5) * np.random.uniform(0.8, 1.5, n_genes))\nbase_pvalues = np.clip(base_pvalues, 1e-10, 1.0)\nneg_log10_pvalue = -np.log10(base_pvalues)\n\n# Define significance thresholds\npval_threshold = 1.3  # -log10(0.05)\nfc_threshold = 1.0  # log2(2) = 1\n\n# Categorize genes\ncategories = np.where(\n    neg_log10_pvalue < pval_threshold,\n    \"Not Significant\",\n    np.where(\n        log2_fold_change > fc_threshold,\n        \"Up-regulated\",\n        np.where(log2_fold_change < -fc_threshold, \"Down-regulated\", \"Not Significant\"),\n    ),\n)\n\n# Create DataFrame\ndf = pd.DataFrame({\"log2_fold_change\": log2_fold_change, \"neg_log10_pvalue\": neg_log10_pvalue, \"category\": categories})\n\n# Sort by category to plot significant genes on top\ncategory_order = {\"Not Significant\": 0, \"Down-regulated\": 1, \"Up-regulated\": 2}\ndf[\"order\"] = df[\"category\"].map(category_order)\ndf = df.sort_values(\"order\")\n\n# Color palette with Okabe-Ito colors\npalette = {\"Not Significant\": NOT_SIG_COLOR, \"Down-regulated\": DOWN_COLOR, \"Up-regulated\": UP_COLOR}\n\n# Set seaborn theme with adaptive colors\nsns.set_theme(\n    style=\"ticks\",\n    rc={\n        \"figure.facecolor\": PAGE_BG,\n        \"axes.facecolor\": PAGE_BG,\n        \"axes.edgecolor\": INK_SOFT,\n        \"axes.labelcolor\": INK,\n        \"text.color\": INK,\n        \"xtick.color\": INK_SOFT,\n        \"ytick.color\": INK_SOFT,\n        \"grid.color\": INK,\n        \"grid.alpha\": 0.10,\n        \"legend.facecolor\": ELEVATED_BG,\n        \"legend.edgecolor\": INK_SOFT,\n    },\n)\n\n# Create figure\nfig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\n# Scatter plot\nsns.scatterplot(\n    data=df,\n    x=\"log2_fold_change\",\n    y=\"neg_log10_pvalue\",\n    hue=\"category\",\n    hue_order=[\"Not Significant\", \"Down-regulated\", \"Up-regulated\"],\n    palette=palette,\n    s=120,\n    alpha=0.6,\n    edgecolor=\"none\",\n    ax=ax,\n)\n\n# Threshold lines with adaptive colors\nax.axhline(y=pval_threshold, color=INK_SOFT, linestyle=\"--\", linewidth=2, alpha=0.5)\nax.axvline(x=fc_threshold, color=INK_SOFT, linestyle=\"--\", linewidth=2, alpha=0.5)\nax.axvline(x=-fc_threshold, color=INK_SOFT, linestyle=\"--\", linewidth=2, alpha=0.5)\n\n# Labels and styling\nax.set_xlabel(\"Log2 Fold Change\", fontsize=20, color=INK, fontweight=\"medium\")\nax.set_ylabel(\"-Log10(p-value)\", fontsize=20, color=INK, fontweight=\"medium\")\nax.set_title(\"volcano-basic · seaborn · anyplot.ai\", fontsize=24, color=INK, fontweight=\"medium\")\nax.tick_params(axis=\"both\", labelsize=16, colors=INK_SOFT)\n\n# Remove top and right spines\nax.spines[\"top\"].set_visible(False)\nax.spines[\"right\"].set_visible(False)\nax.spines[\"left\"].set_color(INK_SOFT)\nax.spines[\"bottom\"].set_color(INK_SOFT)\n\n# Legend styling\nlegend = ax.legend(\n    title=\"Significance Status\", fontsize=14, title_fontsize=16, loc=\"upper right\", framealpha=0.95, edgecolor=INK_SOFT\n)\nlegend.get_frame().set_facecolor(ELEVATED_BG)\nfor text in legend.get_texts():\n    text.set_color(INK)\nlegend.get_title().set_color(INK)\n\nplt.tight_layout()\nplt.savefig(f\"plot-{THEME}.png\", dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}