{"spec_id":"pyramid-basic","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\npyramid-basic: Basic Pyramid Chart\nLibrary: matplotlib 3.11.0 | Python 3.13.13\nQuality: 92/100 | Updated: 2026-06-16\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n\n# Theme-adaptive chrome 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\"\n\n# Imprint palette — first two categorical positions (gender is abstract here,\n# so canonical order 1→2 applies: brand green, lavender)\nMALE = \"#009E73\"  # Imprint position 1 (brand green) — always first series\nFEMALE = \"#C475FD\"  # Imprint position 2 (lavender)\n\n# Data — population pyramid showing age distribution by gender (millions).\n# Deterministic, no randomness; females outlive males at the oldest groups.\nage_groups = [\"0-9\", \"10-19\", \"20-29\", \"30-39\", \"40-49\", \"50-59\", \"60-69\", \"70-79\", \"80+\"]\nmale = np.array([4.8, 5.2, 6.1, 7.3, 8.5, 7.8, 5.9, 3.2, 1.2])\nfemale = np.array([4.5, 5.0, 6.3, 7.5, 8.7, 8.2, 6.4, 4.1, 2.1])\n\n# Figure — landscape 3200×1800 px (8 × 4.5 in @ 400 dpi)\nfig, ax = plt.subplots(figsize=(8, 4.5), dpi=400, facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\ny_pos = np.arange(len(age_groups))\nbar_height = 0.78\n\n# Focal zone — shade the oldest age bands where the female surplus appears,\n# drawing the eye to the chart's real insight (women outlive men).\nfocus = {7, 8}  # 70-79 and 80+\nax.axhspan(min(focus) - 0.5, max(focus) + 0.5, color=INK, alpha=0.06, zorder=0)\n\n# Male extends left (negative), female extends right (positive)\nmale_bars = ax.barh(y_pos, -male, height=bar_height, color=MALE, label=\"Male\", edgecolor=PAGE_BG, linewidth=0.6)\nfemale_bars = ax.barh(y_pos, female, height=bar_height, color=FEMALE, label=\"Female\", edgecolor=PAGE_BG, linewidth=0.6)\n\n# Symmetric axis for fair comparison — tightened so the data fills the canvas\nmax_val = max(male.max(), female.max())\nax.set_xlim(-max_val * 1.08, max_val * 1.08)\nax.set_ylim(-0.7, len(age_groups) - 0.3)\n\n# Tick labels — absolute values on x so both sides read positive\nax.set_yticks(y_pos)\nax.set_yticklabels(age_groups)\nax.set_xticks([-8, -6, -4, -2, 0, 2, 4, 6, 8])\nax.set_xticklabels([\"8\", \"6\", \"4\", \"2\", \"0\", \"2\", \"4\", \"6\", \"8\"])\n\ntitle = \"pyramid-basic · python · matplotlib · anyplot.ai\"\nax.set_title(title, fontsize=12, fontweight=\"medium\", color=INK, pad=12)\nax.set_xlabel(\"Population (millions)\", fontsize=10, color=INK)\nax.set_ylabel(\"Age group\", fontsize=10, color=INK)\nax.tick_params(axis=\"both\", colors=INK_SOFT, labelsize=9, length=0)\n\n# Value tags on the focal bands only — bar_label makes the asymmetry concrete\n# without cluttering the symmetric core.\nmale_tags = [f\"{v:.1f}\" if i in focus else \"\" for i, v in enumerate(male)]\nfemale_tags = [f\"{v:.1f}\" if i in focus else \"\" for i, v in enumerate(female)]\nax.bar_label(male_bars, labels=male_tags, padding=3, fontsize=8, color=INK, fontweight=\"medium\")\nax.bar_label(female_bars, labels=female_tags, padding=3, fontsize=8, color=INK, fontweight=\"medium\")\n\n# Caption — name the story the shaded focal zone tells\nax.text(\n    -max_val * 1.04, 7.5, \"Women outlive men\", fontsize=9, fontstyle=\"italic\", color=INK_SOFT, ha=\"left\", va=\"center\"\n)\n\n# Central divider — structural reference line in neutral ink\nax.axvline(x=0, color=INK_SOFT, linewidth=1.0)\n\n# Subtle x-grid only, behind the bars\nax.set_axisbelow(True)\nax.xaxis.grid(True, alpha=0.15, color=INK, linewidth=0.8)\n\n# Spines — keep only the bottom (L-shaped frame; left replaced by center line)\nfor s in (\"top\", \"right\", \"left\"):\n    ax.spines[s].set_visible(False)\nax.spines[\"bottom\"].set_color(INK_SOFT)\n\n# Legend — theme-adaptive elevated frame\nleg = ax.legend(fontsize=8, loc=\"upper right\", frameon=True)\nleg.get_frame().set_facecolor(ELEVATED_BG)\nleg.get_frame().set_edgecolor(INK_SOFT)\nplt.setp(leg.get_texts(), color=INK_SOFT)\n\nfig.subplots_adjust(left=0.07, right=0.97, top=0.9, bottom=0.11)\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\n"}