{"spec_id":"map-tile-background","library":"pygal","language":"python","code":"\"\"\" anyplot.ai\nmap-tile-background: Map with Tile Background\nLibrary: pygal 3.1.0 | Python 3.13.13\nQuality: 80/100 | Updated: 2026-05-27\n\"\"\"\n\nimport importlib\nimport os\nimport sys\n\n\n# Remove cwd from path to avoid importing this file instead of the pygal library\n_cwd = sys.path[0] if sys.path and sys.path[0] else None\nif _cwd:\n    sys.path.remove(_cwd)\n_pygal = importlib.import_module(\"pygal\")\n_style_mod = importlib.import_module(\"pygal.style\")\nif _cwd:\n    sys.path.insert(0, _cwd)\n\nStyle = _style_mod.Style\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\n\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\n# Map-inspired plot background simulates geographic tile context\n# Light: warm land beige; Dark: near-black land surface\nLAND_BG = \"#eae6df\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\n# Semantic color exception: temperature carries strong cold→blue / hot→red expectation\n# (Imprint palette positions 3, 1, 5 in semantic role order)\nCOLOR_COOL = \"#4467A3\"  # blue  — cool stations (annual mean < 12 °C)\nCOLOR_MILD = \"#009E73\"  # green — mild stations (12–22 °C)\nCOLOR_WARM = \"#AE3030\"  # red   — warm stations (> 22 °C)\n\n# Data: US weather monitoring network — mean annual surface temperatures\nstations = [\n    {\"label\": \"Seattle\", \"lat\": 47.6, \"lon\": -122.3, \"temp_c\": 11.0},\n    {\"label\": \"Portland\", \"lat\": 45.5, \"lon\": -122.7, \"temp_c\": 12.0},\n    {\"label\": \"San Francisco\", \"lat\": 37.8, \"lon\": -122.4, \"temp_c\": 13.5},\n    {\"label\": \"Los Angeles\", \"lat\": 34.1, \"lon\": -118.2, \"temp_c\": 19.0},\n    {\"label\": \"Phoenix\", \"lat\": 33.4, \"lon\": -112.1, \"temp_c\": 28.5},\n    {\"label\": \"Denver\", \"lat\": 39.7, \"lon\": -104.9, \"temp_c\": 10.5},\n    {\"label\": \"Dallas\", \"lat\": 32.8, \"lon\": -96.8, \"temp_c\": 19.5},\n    {\"label\": \"Houston\", \"lat\": 29.8, \"lon\": -95.4, \"temp_c\": 24.5},\n    {\"label\": \"Minneapolis\", \"lat\": 44.9, \"lon\": -93.2, \"temp_c\": 7.5},\n    {\"label\": \"Chicago\", \"lat\": 41.9, \"lon\": -87.6, \"temp_c\": 9.5},\n    {\"label\": \"Detroit\", \"lat\": 42.3, \"lon\": -83.0, \"temp_c\": 8.5},\n    {\"label\": \"Atlanta\", \"lat\": 33.7, \"lon\": -84.4, \"temp_c\": 17.5},\n    {\"label\": \"Miami\", \"lat\": 25.8, \"lon\": -80.2, \"temp_c\": 27.0},\n    {\"label\": \"Washington DC\", \"lat\": 38.9, \"lon\": -77.0, \"temp_c\": 13.5},\n    {\"label\": \"New York\", \"lat\": 40.7, \"lon\": -74.0, \"temp_c\": 12.5},\n    {\"label\": \"Boston\", \"lat\": 42.4, \"lon\": -71.1, \"temp_c\": 10.0},\n    {\"label\": \"Nashville\", \"lat\": 36.2, \"lon\": -86.8, \"temp_c\": 15.5},\n    {\"label\": \"New Orleans\", \"lat\": 30.0, \"lon\": -90.1, \"temp_c\": 23.0},\n    {\"label\": \"Kansas City\", \"lat\": 39.1, \"lon\": -94.6, \"temp_c\": 12.5},\n    {\"label\": \"Salt Lake City\", \"lat\": 40.8, \"lon\": -111.9, \"temp_c\": 11.5},\n    {\"label\": \"Las Vegas\", \"lat\": 36.2, \"lon\": -115.2, \"temp_c\": 20.0},\n    {\"label\": \"Albuquerque\", \"lat\": 35.1, \"lon\": -106.7, \"temp_c\": 14.5},\n    {\"label\": \"Memphis\", \"lat\": 35.1, \"lon\": -90.0, \"temp_c\": 18.0},\n    {\"label\": \"Charlotte\", \"lat\": 35.2, \"lon\": -80.8, \"temp_c\": 16.0},\n    {\"label\": \"Tampa\", \"lat\": 28.0, \"lon\": -82.5, \"temp_c\": 25.0},\n]\n\n# Continental US bounds; chart xrange padded to give tick labels breathing room\nlat_min, lat_max = 24, 51\nlon_min, lon_max = -128, -62\nchart_xrange = (-132, -58)\n\ntitle = \"map-tile-background · python · pygal · anyplot.ai\"\nn = len(title)\nratio = 67 / n if n > 67 else 1.0\ntitle_font_size = max(44, round(66 * ratio))\n\ncustom_style = Style(\n    background=PAGE_BG,\n    plot_background=LAND_BG,\n    foreground=INK,\n    foreground_strong=INK,\n    foreground_subtle=INK_MUTED,\n    colors=(COLOR_COOL, COLOR_MILD, COLOR_WARM),\n    title_font_size=title_font_size,\n    label_font_size=56,\n    major_label_font_size=44,\n    legend_font_size=44,\n    value_font_size=36,\n    stroke_width=2.5,\n    opacity=0.9,\n    opacity_hover=1.0,\n)\n\nchart = _pygal.XY(\n    width=3200,\n    height=1800,\n    style=custom_style,\n    title=title,\n    x_title=\"Longitude (°)\",\n    y_title=\"Latitude (°)\",\n    show_legend=True,\n    legend_at_bottom=True,\n    legend_box_size=36,\n    show_x_guides=True,\n    show_y_guides=True,\n    dots_size=18,\n    stroke=False,\n    margin=60,\n    margin_top=110,\n    margin_bottom=240,\n    margin_left=200,\n    margin_right=80,\n    range=(lat_min, lat_max),\n    xrange=chart_xrange,\n    print_values=False,\n    truncate_legend=-1,\n    truncate_label=-1,\n    explicit_size=True,\n)\n\n# Group stations by annual mean temperature\ncool_pts = []\nmild_pts = []\nwarm_pts = []\n\nfor s in stations:\n    pt = {\"value\": (s[\"lon\"], s[\"lat\"]), \"label\": f\"{s['label']}: {s['temp_c']} °C\"}\n    if s[\"temp_c\"] < 12:\n        cool_pts.append(pt)\n    elif s[\"temp_c\"] < 22:\n        mild_pts.append(pt)\n    else:\n        warm_pts.append(pt)\n\nchart.add(\"Cool (< 12 °C)\", cool_pts, dots_size=16)\nchart.add(\"Mild (12–22 °C)\", mild_pts, dots_size=20)\nchart.add(\"Warm (> 22 °C)\", warm_pts, dots_size=24)\n\nchart.x_labels = [f\"{lon}°\" for lon in range(lon_min, lon_max + 1, 10)]\nchart.y_labels = [f\"{lat}°\" for lat in range(lat_min, lat_max + 1, 5)]\n\n# Save PNG and interactive HTML\nchart.render_to_png(f\"plot-{THEME}.png\")\n\nwith open(f\"plot-{THEME}.html\", \"wb\") as f:\n    f.write(chart.render())\n"}