{"spec_id":"waffle-basic","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nwaffle-basic: Basic Waffle Chart\nLibrary: plotly 6.9.0 | Python 3.13.14\nQuality: 91/100 | Updated: 2026-07-26\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport plotly.graph_objects as go\n\n\n# Theme tokens (see prompts/default-style-guide.md \"Background\" + \"Theme-adaptive Chrome\")\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 series ALWAYS #009E73\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\"]\n\n# Data - budget allocation across spending categories\ncategories = [\"Operations\", \"Marketing\", \"R&D\", \"HR\", \"Other\"]\nvalues = [35, 25, 22, 12, 6]  # Percentages (sum to 100)\nn_categories = len(categories)\n\n# Build a 10x10 waffle grid (100 squares, each = 1%), filled bottom-up, left-to-right\ngrid_size = 10\ntotal_squares = grid_size * grid_size\ncategory_idx = np.repeat(np.arange(n_categories), values)\nwaffle_matrix = category_idx.reshape(grid_size, grid_size)[::-1]\n\n# Hover metadata mirrors the grid so each square reports its own category and share\ncategory_names = np.array(categories)[waffle_matrix]\ncategory_values = np.array(values)[waffle_matrix]\n\n# Single Heatmap trace (not 100+ scatter traces) with a hand-built discrete\n# colorscale - each category occupies an equal band so cell colors stay flat,\n# and the vertical colorbar doubles as a labeled legend (unrotated tick text,\n# one row per category, so nothing crowds or clips at the canvas edge).\ndiscrete_colorscale = []\nfor idx, color in enumerate(IMPRINT[:n_categories]):\n    discrete_colorscale.append([idx / n_categories, color])\n    discrete_colorscale.append([(idx + 1) / n_categories, color])\n\nfig = go.Figure(\n    go.Heatmap(\n        z=waffle_matrix,\n        zmin=-0.5,\n        zmax=n_categories - 0.5,\n        colorscale=discrete_colorscale,\n        xgap=6,\n        ygap=6,\n        text=category_names,\n        customdata=category_values,\n        hovertemplate=\"<b>%{text}</b><br>%{customdata}% of total<extra></extra>\",\n        showscale=True,\n        colorbar={\n            \"thickness\": 26,\n            \"len\": 0.7,\n            \"x\": 1.06,\n            \"xanchor\": \"left\",\n            \"y\": 0.5,\n            \"yanchor\": \"middle\",\n            \"tickmode\": \"array\",\n            \"tickvals\": list(range(n_categories)),\n            \"ticktext\": [f\"{cat} — {val}%\" for cat, val in zip(categories, values, strict=True)],\n            \"ticks\": \"\",\n            \"outlinewidth\": 1,\n            \"outlinecolor\": INK_SOFT,\n            \"tickfont\": {\"size\": 13, \"color\": INK_SOFT},\n            \"bgcolor\": ELEVATED_BG,\n        },\n    )\n)\n\n# Layout\nfig.update_layout(\n    autosize=False,\n    title={\n        \"text\": \"waffle-basic · python · plotly · anyplot.ai\",\n        \"font\": {\"size\": 16, \"color\": INK},\n        \"x\": 0.5,\n        \"xanchor\": \"center\",\n    },\n    xaxis={\"visible\": False, \"range\": [-0.5, grid_size - 0.5], \"scaleanchor\": \"y\", \"scaleratio\": 1},\n    yaxis={\"visible\": False, \"range\": [-0.5, grid_size - 0.5]},\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    margin={\"l\": 60, \"r\": 220, \"t\": 90, \"b\": 60},\n)\n\n# Save outputs\nfig.write_image(f\"plot-{THEME}.png\", width=600, height=600, scale=4)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}