{"spec_id":"cartogram-area-distortion","library":"makie","language":"julia","code":"# anyplot.ai\n# cartogram-area-distortion: Cartogram with Area Distortion by Data Value\n# Library: makie 0.22.10 | Julia 1.11.9\n# Quality: 86/100 | Created: 2026-06-08\n\nusing CairoMakie\nusing Colors\n\n# Theme tokens\nconst THEME       = get(ENV, \"ANYPLOT_THEME\", \"light\")\nconst PAGE_BG     = THEME == \"light\" ? colorant\"#FAF8F1\" : colorant\"#1A1A17\"\nconst ELEVATED_BG = THEME == \"light\" ? colorant\"#FFFDF6\" : colorant\"#242420\"\nconst INK         = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nconst INK_SOFT    = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\nconst INK_MUTED   = THEME == \"light\" ? colorant\"#6B6A63\" : colorant\"#A8A79F\"\n\n# Imprint palette — positions 1–4 for four US census regions\nconst REGION_COLORS = [\n    colorant\"#009E73\",  # Northeast — brand green\n    colorant\"#C475FD\",  # South     — lavender\n    colorant\"#4467A3\",  # Midwest   — blue\n    colorant\"#BD8233\",  # West      — ochre\n]\n\n# US states: (abbreviation, longitude, latitude, population_millions, region_index)\n# Alaska and Hawaii repositioned to lower-left corner for display\nconst STATE_DATA = [\n    (\"AL\", -86.7,  32.7, 5.03,  2),\n    (\"AK\", -127.0, 26.5, 0.73,  4),\n    (\"AZ\", -111.7, 34.3, 7.15,  4),\n    (\"AR\", -92.4,  34.9, 3.01,  2),\n    (\"CA\", -119.7, 37.2, 39.54, 4),\n    (\"CO\", -105.5, 39.0, 5.77,  4),\n    (\"CT\", -72.7,  41.6, 3.60,  1),\n    (\"DE\", -75.5,  39.0, 0.99,  2),\n    (\"FL\", -81.5,  28.1, 21.54, 2),\n    (\"GA\", -83.4,  32.7, 10.71, 2),\n    (\"HI\", -120.5, 24.0, 1.44,  4),\n    (\"ID\", -114.5, 44.4, 1.83,  4),\n    (\"IL\", -89.2,  40.1, 12.81, 3),\n    (\"IN\", -86.3,  40.3, 6.79,  3),\n    (\"IA\", -93.1,  42.1, 3.19,  3),\n    (\"KS\", -98.4,  38.5, 2.94,  3),\n    (\"KY\", -84.3,  37.5, 4.51,  2),\n    (\"LA\", -91.8,  31.2, 4.65,  2),\n    (\"ME\", -69.2,  45.4, 1.36,  1),\n    (\"MD\", -76.6,  39.0, 6.18,  2),\n    (\"MA\", -71.5,  42.2, 7.03,  1),\n    (\"MI\", -85.6,  44.3, 10.08, 3),\n    (\"MN\", -94.3,  46.4, 5.71,  3),\n    (\"MS\", -89.7,  32.7, 2.96,  2),\n    (\"MO\", -92.3,  38.5, 6.15,  3),\n    (\"MT\", -110.5, 46.9, 1.08,  4),\n    (\"NE\", -99.9,  41.5, 1.96,  3),\n    (\"NV\", -116.9, 39.5, 3.10,  4),\n    (\"NH\", -71.6,  43.7, 1.38,  1),\n    (\"NJ\", -74.4,  40.0, 9.29,  1),\n    (\"NM\", -106.1, 34.4, 2.12,  4),\n    (\"NY\", -75.4,  42.9, 20.20, 1),\n    (\"NC\", -79.4,  35.6, 10.44, 2),\n    (\"ND\", -100.5, 47.5, 0.78,  3),\n    (\"OH\", -82.8,  40.4, 11.80, 3),\n    (\"OK\", -97.5,  35.5, 3.96,  2),\n    (\"OR\", -120.5, 43.9, 4.24,  4),\n    (\"PA\", -77.2,  40.9, 13.00, 1),\n    (\"RI\", -71.4,  41.7, 1.10,  1),\n    (\"SC\", -80.9,  33.8, 5.12,  2),\n    (\"SD\", -100.2, 44.4, 0.89,  3),\n    (\"TN\", -86.7,  35.9, 6.91,  2),\n    (\"TX\", -99.3,  31.5, 29.15, 2),\n    (\"UT\", -111.1, 39.5, 3.27,  4),\n    (\"VT\", -72.7,  44.0, 0.64,  1),\n    (\"VA\", -78.5,  37.5, 8.63,  2),\n    (\"WA\", -120.7, 47.4, 7.71,  4),\n    (\"WV\", -80.7,  38.9, 1.79,  2),\n    (\"WI\", -89.8,  44.5, 5.89,  3),\n    (\"WY\", -107.6, 43.0, 0.58,  4),\n]\n\nabbrevs     = [s[1] for s in STATE_DATA]\nlons        = Float64[s[2] for s in STATE_DATA]\nlats        = Float64[s[3] for s in STATE_DATA]\npops        = Float64[s[4] for s in STATE_DATA]\nregion_idxs = Int[s[5] for s in STATE_DATA]\ncolors      = [REGION_COLORS[r] for r in region_idxs]\n\n# Leader-line offsets for the dense Northeast cluster — (dx, dy) from circle center to label.\n# Circles stay at geographic positions; only the text is displaced, with a thin connector line.\nconst NE_LEADERS = Dict(\n    \"VT\" => (-2.8,  2.2),   # circle -72.7,44.0 → label -75.5,46.2 (upper-left)\n    \"NH\" => ( 3.0,  0.0),   # circle -71.6,43.7 → label -68.6,43.7 (right)\n    \"RI\" => ( 2.0, -2.0),   # circle -71.4,41.7 → label -69.4,39.7 (lower-right)\n    \"CT\" => (-3.5, -2.0),   # circle -72.7,41.6 → label -76.2,39.6 (lower-left)\n    \"MA\" => ( 3.5,  0.5),   # circle -71.5,42.2 → label -68.0,42.7 (right)\n    \"NJ\" => ( 3.0, -2.0),   # circle -74.4,40.0 → label -71.4,38.0 (lower-right)\n    \"DE\" => (-1.0, -2.5),   # circle -75.5,39.0 → label -76.5,36.5 (lower-left)\n)\n\nconst LEADER_COLOR = RGBAf(INK_MUTED.r, INK_MUTED.g, INK_MUTED.b, 0.7f0)\n\n# Marker sizes: area ∝ population; minimum enforced so tiny states remain visible\nsize_scale   = 44.0 / sqrt(maximum(pops))\nmarker_sizes = [max(sqrt(p) * size_scale, 8.0) for p in pops]\n\n# Figure\nfig = Figure(\n    size            = (1600, 900),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\n# Main Dorling cartogram axis\nax = Axis(\n    fig[1, 1];\n    title              = \"cartogram-area-distortion · julia · makie · anyplot.ai\",\n    titlesize          = 20,\n    titlecolor         = INK,\n    xlabel             = \"Longitude\",\n    ylabel             = \"Latitude\",\n    xlabelsize         = 14,\n    ylabelsize         = 14,\n    xlabelcolor        = INK,\n    ylabelcolor        = INK,\n    xticklabelcolor    = INK_SOFT,\n    yticklabelcolor    = INK_SOFT,\n    xticklabelsize     = 12,\n    yticklabelsize     = 12,\n    backgroundcolor    = PAGE_BG,\n    topspinevisible    = false,\n    rightspinevisible  = false,\n    leftspinecolor     = INK_SOFT,\n    bottomspinecolor   = INK_SOFT,\n    xgridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.15),\n    ygridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.15),\n)\n\n# Draw leader lines first so circles render on top, covering the inner segment\nfor i in eachindex(abbrevs)\n    abbr = abbrevs[i]\n    if haskey(NE_LEADERS, abbr)\n        dx, dy = NE_LEADERS[abbr]\n        lines!(ax, [lons[i], lons[i] + dx], [lats[i], lats[i] + dy];\n            color = LEADER_COLOR, linewidth = 0.8)\n    end\nend\n\nscatter!(ax, lons, lats;\n    color       = colors,\n    markersize  = marker_sizes,\n    strokecolor = PAGE_BG,\n    strokewidth = 1.5,\n)\n\n# Labels: offset for NE cluster states (placed at leader endpoint), centered for all others\nfor i in eachindex(abbrevs)\n    abbr = abbrevs[i]\n    if haskey(NE_LEADERS, abbr)\n        dx, dy = NE_LEADERS[abbr]\n        text!(ax, lons[i] + dx, lats[i] + dy;\n            text     = abbr,\n            align    = (:center, :center),\n            fontsize = 10,\n            color    = INK,\n        )\n    else\n        text!(ax, lons[i], lats[i];\n            text     = abbr,\n            align    = (:center, :center),\n            fontsize = 10,\n            color    = INK,\n        )\n    end\nend\n\nxlims!(ax, -131.0, -64.0)\nylims!(ax, 22.5, 50.5)\n\n# Right panel — reference map and census region legend\nright_grid = fig[1, 2] = GridLayout()\n\n# Reference map: equal-size dots at geographic centers for comparison with cartogram\nref_ax = Axis(\n    right_grid[1, 1];\n    title              = \"Reference Map\",\n    titlesize          = 11,\n    titlecolor         = INK,\n    backgroundcolor    = PAGE_BG,\n    topspinevisible    = true,\n    rightspinevisible  = true,\n    leftspinevisible   = true,\n    bottomspinevisible = true,\n    topspinecolor      = INK_MUTED,\n    rightspinecolor    = INK_MUTED,\n    leftspinecolor     = INK_MUTED,\n    bottomspinecolor   = INK_MUTED,\n    xticksvisible      = false,\n    yticksvisible      = false,\n    xticklabelsvisible = false,\n    yticklabelsvisible = false,\n    xgridvisible       = false,\n    ygridvisible       = false,\n)\nscatter!(ref_ax, lons, lats;\n    color       = colors,\n    markersize  = 6.0,\n    strokecolor = PAGE_BG,\n    strokewidth = 0.8,\n)\nxlims!(ref_ax, -131.0, -64.0)\nylims!(ref_ax, 22.5, 50.5)\n\n# Census region legend\nLegend(\n    right_grid[2, 1],\n    [MarkerElement(color = REGION_COLORS[i], marker = :circle, markersize = 18) for i in 1:4],\n    [\"Northeast\", \"South\", \"Midwest\", \"West\"];\n    title           = \"Census Region\",\n    titlesize       = 13,\n    titlecolor      = INK,\n    labelsize       = 12,\n    labelcolor      = INK_SOFT,\n    framevisible    = true,\n    framecolor      = INK_SOFT,\n    backgroundcolor = ELEVATED_BG,\n    padding         = (12, 12, 12, 12),\n    rowgap          = 8,\n)\n\n# Caption\nLabel(\n    fig[2, 1:2];\n    text     = \"Dorling cartogram — circle area ∝ state population (2020 US Census). Reference map shows equal-size geographic layout. AK/HI repositioned.\",\n    fontsize = 10,\n    color    = INK_MUTED,\n    halign   = :left,\n)\n\n# Layout proportions\ncolsize!(fig.layout, 1, Relative(0.78))\nrowsize!(fig.layout, 1, Relative(0.92))\nrowsize!(right_grid, 1, Fixed(140))\n\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}