{"spec_id":"dot-matrix-proportional","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\ndot-matrix-proportional: Dot Matrix Chart for Proportional Counts\nLibrary: plotly 6.7.0 | Python 3.13.13\nQuality: 93/100 | Created: 2026-05-08\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\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\n# Data: city commute survey, 100 respondents\ncategories = [\"Public Transit\", \"Car\", \"Cycling\", \"Work from Home\"]\ncounts = [42, 31, 15, 12]\ncolors = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\"]\ntotal = sum(counts)  # 100\ngrid_cols = 10\ngrid_rows = total // grid_cols  # 10\n\n# Build dot grid positions: fill left-to-right, top-to-bottom\ndot_positions = {}\nidx = 0\nfor cat, count in zip(categories, counts, strict=False):\n    positions = []\n    for _ in range(count):\n        col = idx % grid_cols\n        row = idx // grid_cols\n        positions.append((col, grid_rows - 1 - row))  # flip y so row 0 is at top\n        idx += 1\n    dot_positions[cat] = positions\n\n# Plot\nfig = go.Figure()\n\nfor cat, color, count in zip(categories, colors, counts, strict=False):\n    xs = [p[0] for p in dot_positions[cat]]\n    ys = [p[1] for p in dot_positions[cat]]\n    pct = count / total * 100\n    fig.add_trace(\n        go.Scatter(\n            x=xs,\n            y=ys,\n            mode=\"markers\",\n            name=f\"{cat}  ·  {count} ({pct:.0f}%)\",\n            marker={\"color\": color, \"size\": 44, \"symbol\": \"circle\"},\n            hovertemplate=f\"<b>{cat}</b><br>Count: {count}<br>Share: {pct:.0f}%<extra></extra>\",\n        )\n    )\n\n# Layout\nfig.update_layout(\n    title={\n        \"text\": \"City Commute Survey · dot-matrix-proportional · plotly · anyplot.ai\",\n        \"font\": {\"size\": 28, \"color\": INK},\n        \"x\": 0.5,\n        \"xanchor\": \"center\",\n        \"y\": 0.975,\n        \"yanchor\": \"top\",\n    },\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    xaxis={\"visible\": False, \"range\": [-0.7, grid_cols - 0.3], \"fixedrange\": True},\n    yaxis={\"visible\": False, \"range\": [-0.7, grid_rows - 0.3], \"scaleanchor\": \"x\", \"scaleratio\": 1, \"fixedrange\": True},\n    legend={\n        \"orientation\": \"h\",\n        \"x\": 0.5,\n        \"y\": -0.05,\n        \"xanchor\": \"center\",\n        \"yanchor\": \"top\",\n        \"bgcolor\": ELEVATED_BG,\n        \"bordercolor\": INK_SOFT,\n        \"borderwidth\": 1,\n        \"font\": {\"color\": INK_SOFT, \"size\": 18},\n        \"tracegroupgap\": 0,\n    },\n    annotations=[\n        # Insight subtitle: draw attention to the dominant transit mode\n        {\n            \"text\": \"<b>42%</b> rely on public transit — the city's dominant commute mode\",\n            \"x\": 0.5,\n            \"y\": 1.03,\n            \"xref\": \"paper\",\n            \"yref\": \"paper\",\n            \"showarrow\": False,\n            \"font\": {\"size\": 18, \"color\": \"#009E73\"},\n            \"xanchor\": \"center\",\n            \"yanchor\": \"bottom\",\n        },\n        # Scale context\n        {\n            \"text\": \"Each ● represents 1 commuter  ·  n = 100\",\n            \"x\": 0.5,\n            \"y\": -0.01,\n            \"xref\": \"paper\",\n            \"yref\": \"paper\",\n            \"showarrow\": False,\n            \"font\": {\"size\": 16, \"color\": INK_MUTED},\n            \"xanchor\": \"center\",\n            \"yanchor\": \"bottom\",\n        },\n    ],\n    width=1200,\n    height=1200,\n    margin={\"l\": 80, \"r\": 80, \"t\": 145, \"b\": 110},\n)\n\n# Save\nfig.write_image(f\"plot-{THEME}.png\", width=1200, height=1200, scale=3)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}