{"spec_id":"pyramid-basic","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\npyramid-basic: Basic Pyramid Chart\nLibrary: plotly 6.7.0 | Python 3.13.13\nQuality: 91/100 | Updated: 2026-04-29\n\"\"\"\n\nimport os\n\nimport plotly.graph_objects as go\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\"\nGRID = \"rgba(26,26,23,0.10)\" if THEME == \"light\" else \"rgba(240,239,232,0.10)\"\n\n# Data — Germany-scale population pyramid (~83M total), values in thousands\nage_groups = [\"0–9\", \"10–19\", \"20–29\", \"30–39\", \"40–49\", \"50–59\", \"60–69\", \"70–79\", \"80+\"]\nmale_population = [3800, 4200, 4700, 6300, 6900, 6500, 5800, 3600, 1900]\nfemale_population = [3600, 3900, 4400, 6100, 6700, 6500, 6200, 4600, 3200]\n\n# Plot\nfig = go.Figure()\n\nfig.add_trace(\n    go.Bar(\n        y=age_groups,\n        x=[-v for v in male_population],\n        orientation=\"h\",\n        name=\"Male\",\n        marker_color=\"#009E73\",  # Okabe-Ito position 1\n        hovertemplate=\"Male<br>Age: %{y}<br>Population: %{customdata:,}k<extra></extra>\",\n        customdata=male_population,\n    )\n)\n\nfig.add_trace(\n    go.Bar(\n        y=age_groups,\n        x=female_population,\n        orientation=\"h\",\n        name=\"Female\",\n        marker_color=\"#C475FD\",  # Okabe-Ito position 2\n        hovertemplate=\"Female<br>Age: %{y}<br>Population: %{customdata:,}k<extra></extra>\",\n        customdata=female_population,\n    )\n)\n\nmax_val = max(max(male_population), max(female_population))\ntick_vals = list(range(-8000, 8001, 2000))\ntick_text = [f\"{abs(v):,}\" for v in tick_vals]\n\nfig.update_layout(\n    title={\n        \"text\": \"Population Distribution · pyramid-basic · plotly · anyplot.ai\",\n        \"font\": {\"size\": 28, \"color\": INK},\n        \"x\": 0.5,\n        \"xanchor\": \"center\",\n    },\n    xaxis={\n        \"title\": {\"text\": \"Population (thousands)\", \"font\": {\"size\": 22, \"color\": INK}},\n        \"tickfont\": {\"size\": 18, \"color\": INK_SOFT},\n        \"tickvals\": tick_vals,\n        \"ticktext\": tick_text,\n        \"range\": [-max_val * 1.15, max_val * 1.15],\n        \"gridcolor\": GRID,\n        \"gridwidth\": 1,\n        \"zeroline\": True,\n        \"zerolinecolor\": INK_SOFT,\n        \"zerolinewidth\": 2,\n        \"linecolor\": INK_SOFT,\n    },\n    yaxis={\n        \"title\": {\"text\": \"Age Group\", \"font\": {\"size\": 22, \"color\": INK}},\n        \"tickfont\": {\"size\": 18, \"color\": INK_SOFT},\n        \"categoryorder\": \"array\",\n        \"categoryarray\": age_groups,\n        \"linecolor\": INK_SOFT,\n    },\n    barmode=\"overlay\",\n    bargap=0.15,\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    font={\"color\": INK},\n    legend={\n        \"font\": {\"size\": 16, \"color\": INK_SOFT},\n        \"bgcolor\": ELEVATED_BG,\n        \"bordercolor\": INK_SOFT,\n        \"borderwidth\": 1,\n        \"orientation\": \"h\",\n        \"yanchor\": \"bottom\",\n        \"y\": 1.02,\n        \"xanchor\": \"center\",\n        \"x\": 0.5,\n    },\n    margin={\"l\": 120, \"r\": 80, \"t\": 150, \"b\": 100},\n)\n\n# Save\nfig.write_image(f\"plot-{THEME}.png\", width=1600, height=900, scale=3)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}