{"spec_id":"map-tilegrid","library":"pygal","language":"python","code":"\"\"\" anyplot.ai\nmap-tilegrid: Tile Grid Map for Equal-Area Geographic Comparison\nLibrary: pygal 3.1.0 | Python 3.13.13\nQuality: 74/100 | Created: 2026-05-14\n\"\"\"\n\nimport os\nimport sys\n\n\nsys.path.pop(0)  # remove script dir so \"import pygal\" finds the installed package, not this file\n\nimport matplotlib.colors as mcolors\nimport numpy as np\nimport pygal\nfrom pygal.style import Style\n\n\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\n# US state tile grid positions (row, col) — geographic approximation\nSTATE_GRID = {\n    \"AK\": (0, 0),\n    \"ME\": (0, 10),\n    \"WA\": (1, 1),\n    \"MT\": (1, 2),\n    \"ND\": (1, 3),\n    \"MN\": (1, 4),\n    \"WI\": (1, 5),\n    \"VT\": (1, 9),\n    \"NH\": (1, 10),\n    \"OR\": (2, 1),\n    \"ID\": (2, 2),\n    \"WY\": (2, 3),\n    \"SD\": (2, 4),\n    \"IA\": (2, 5),\n    \"MI\": (2, 6),\n    \"NY\": (2, 7),\n    \"MA\": (2, 9),\n    \"RI\": (2, 10),\n    \"CA\": (3, 1),\n    \"NV\": (3, 2),\n    \"CO\": (3, 3),\n    \"NE\": (3, 4),\n    \"IL\": (3, 5),\n    \"IN\": (3, 6),\n    \"OH\": (3, 7),\n    \"PA\": (3, 8),\n    \"NJ\": (3, 9),\n    \"CT\": (3, 10),\n    \"AZ\": (4, 2),\n    \"UT\": (4, 3),\n    \"KS\": (4, 4),\n    \"MO\": (4, 5),\n    \"KY\": (4, 6),\n    \"WV\": (4, 7),\n    \"VA\": (4, 8),\n    \"MD\": (4, 9),\n    \"DE\": (4, 10),\n    \"NM\": (5, 3),\n    \"OK\": (5, 4),\n    \"AR\": (5, 5),\n    \"TN\": (5, 6),\n    \"NC\": (5, 7),\n    \"SC\": (5, 8),\n    \"TX\": (6, 4),\n    \"LA\": (6, 5),\n    \"MS\": (6, 6),\n    \"AL\": (6, 7),\n    \"GA\": (6, 8),\n    \"HI\": (7, 1),\n    \"FL\": (7, 9),\n}\n\n# Synthetic renewable energy % of total electricity generation\nnp.random.seed(42)\nstate_values = {s: round(float(np.random.uniform(18, 78)), 1) for s in STATE_GRID}\nstate_values.update(\n    {\n        \"WA\": 88.2,  # Pacific Northwest hydropower\n        \"OR\": 72.1,\n        \"ID\": 81.5,\n        \"MT\": 65.3,\n        \"WY\": 18.5,  # Coal-heavy states\n        \"WV\": 12.3,\n        \"KY\": 15.7,\n        \"TX\": 24.8,\n        \"LA\": 20.4,\n        \"MS\": 18.9,\n        \"CA\": 52.3,\n        \"ND\": 41.8,\n        \"SD\": 76.4,  # High hydro + wind\n    }\n)\n\n# Quintile assignment using numpy digitize\nvalues_array = np.array(list(state_values.values()))\nquintile_bins = np.percentile(values_array, [20, 40, 60, 80])\nquintile_assignments = {state: int(np.digitize(val, quintile_bins)) for state, val in state_values.items()}\n\n# Viridis colors for 5 quintiles (dark purple = low, bright yellow = high)\nviridis = mcolors.LinearSegmentedColormap.from_list(\n    \"viridis_approx\", [\"#440154\", \"#482475\", \"#355f8d\", \"#21918c\", \"#44bf70\", \"#bddf26\", \"#fde725\"]\n)\nquintile_hex = tuple(mcolors.to_hex(viridis(t)) for t in (0.1, 0.3, 0.5, 0.7, 0.9))\n\n# Quintile legend labels\nb = quintile_bins\nquintile_labels = [\n    f\"< {b[0]:.0f}%  (lowest fifth)\",\n    f\"{b[0]:.0f}–{b[1]:.0f}%\",\n    f\"{b[1]:.0f}–{b[2]:.0f}%\",\n    f\"{b[2]:.0f}–{b[3]:.0f}%\",\n    f\"> {b[3]:.0f}%  (highest fifth)\",\n]\n\n# Organise data by quintile — offset grid by 1 to prevent edge clipping\nquintile_data = [[] for _ in range(5)]\nfor state, (row, col) in STATE_GRID.items():\n    q = quintile_assignments[state]\n    quintile_data[q].append({\"value\": (col + 1, -(row + 1)), \"label\": f\"{state}: {state_values[state]:.1f}%\"})\n\n# Pygal style\ncustom_style = Style(\n    background=PAGE_BG,\n    plot_background=PAGE_BG,\n    foreground=INK,\n    foreground_strong=INK,\n    foreground_subtle=INK_MUTED,\n    colors=quintile_hex,\n    title_font_size=32,\n    label_font_size=22,\n    major_label_font_size=22,\n    legend_font_size=24,\n    value_font_size=50,\n)\n\n# Chart\nchart = pygal.XY(\n    width=4800,\n    height=2700,\n    title=\"map-tilegrid · pygal · anyplot.ai\",\n    stroke=False,\n    dots_size=50,\n    print_labels=True,\n    show_x_labels=False,\n    show_y_labels=False,\n    show_x_guides=False,\n    show_y_guides=False,\n    legend_at_bottom=True,\n    style=custom_style,\n)\n\nfor q_data, q_label in zip(quintile_data, quintile_labels, strict=False):\n    chart.add(q_label, q_data)\n\n# Save\nchart.render_to_png(f\"plot-{THEME}.png\")\nwith open(f\"plot-{THEME}.html\", \"wb\") as f:\n    f.write(chart.render())\n"}