{"spec_id":"hexbin-map-geographic","library":"makie","language":"julia","code":"# anyplot.ai\n# hexbin-map-geographic: Hexagonal Binning Map\n# Library: makie 0.22.10 | Julia 1.11.9\n# Quality: 85/100 | Created: 2026-05-27\n\nusing CairoMakie\nusing Colors\nusing Random\n\nRandom.seed!(42)\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\"\nconst GRID_COLOR  = THEME == \"light\" ?\n    RGBAf(26/255f0, 26/255f0, 23/255f0, 0.12f0) :\n    RGBAf(240/255f0, 239/255f0, 232/255f0, 0.12f0)\n\n# Water fill and coastline colors for the geographic base map\nconst WATER_FILL  = THEME == \"light\" ?\n    RGBAf(0.58f0, 0.75f0, 0.88f0, 0.32f0) :\n    RGBAf(0.18f0, 0.35f0, 0.56f0, 0.45f0)\nconst COAST_LINE  = THEME == \"light\" ?\n    RGBAf(0.27f0, 0.46f0, 0.63f0, 0.65f0) :\n    RGBAf(0.42f0, 0.62f0, 0.80f0, 0.52f0)\n\n# Anyplot sequential colormap for density (single-polarity)\nconst ANYPLOT_SEQ = cgrad([colorant\"#009E73\", colorant\"#4467A3\"])\n\n# Data: synthetic bike-share ride starts in San Francisco\ncluster_centers = [\n    (-122.4057, 37.7871),  # Union Square / Downtown\n    (-122.4194, 37.7599),  # Mission District\n    (-122.3971, 37.7749),  # SoMa\n    (-122.4352, 37.8012),  # Marina\n    (-122.4447, 37.7698),  # Haight-Ashbury\n]\ncluster_weights = [0.33, 0.22, 0.20, 0.13, 0.12]\ncluster_stds    = [0.013, 0.012, 0.011, 0.010, 0.013]\n\nn_total = 14000\nlons = Float64[]\nlats = Float64[]\n\nfor ((cx, cy), w, σ) in zip(cluster_centers, cluster_weights, cluster_stds)\n    n_i = round(Int, n_total * w)\n    append!(lons, cx .+ σ .* randn(n_i))\n    append!(lats, cy .+ σ .* randn(n_i))\nend\n\n# Map extent — tightened from original to reduce empty ocean space upper-left\nlon_lo, lon_hi = -122.515, -122.360\nlat_lo, lat_hi =   37.700,   37.835\n\n# Clip to bounds\nmask = (lons .>= lon_lo) .& (lons .<= lon_hi) .& (lats .>= lat_lo) .& (lats .<= lat_hi)\nlons = lons[mask]\nlats = lats[mask]\n\n# --- Simplified geographic base map -----------------------------------------\n# Polygon vertices tracing simplified SF coastlines; Makie auto-closes last→first.\n\n# SF Bay water polygon: follows the eastern SF waterfront (south→north),\n# then closes via the box top-right corner and right edge.\nbay_pts = Point2f[\n    (-122.374, 37.700), (-122.376, 37.748), (-122.381, 37.762),\n    (-122.386, 37.776), (-122.393, 37.790), (-122.400, 37.800),\n    (-122.407, 37.805), (-122.414, 37.808), (-122.432, 37.804),\n    (-122.443, 37.803), (-122.455, 37.803), (-122.464, 37.804),\n    (-122.479, 37.808),                       # Golden Gate Bridge — SF side\n    (-122.479, 37.835), (-122.360, 37.835), (-122.360, 37.700),\n]\n\n# Pacific Ocean polygon: follows the western SF coast (north→south),\n# then closes via the box bottom-left and left edge back to the top.\npac_pts = Point2f[\n    (-122.479, 37.808),                       # Golden Gate Bridge — SF side\n    (-122.484, 37.800), (-122.493, 37.798),\n    (-122.499, 37.794), (-122.505, 37.789),\n    (-122.509, 37.782), (-122.511, 37.770),\n    (-122.512, 37.748), (-122.511, 37.710),\n    (-122.515, 37.700), (-122.515, 37.835),\n    (-122.479, 37.835),\n]\n\n# --- Figure -----------------------------------------------------------------\nfig = Figure(\n    size            = (1600, 900),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis(\n    fig[1, 1];\n    title              = \"SF Bike-Share · hexbin-map-geographic · julia · makie · anyplot.ai\",\n    titlesize          = 20,\n    titlecolor         = INK,\n    xlabel             = \"Longitude\",\n    ylabel             = \"Latitude\",\n    xlabelsize         = 14,\n    ylabelsize         = 14,\n    xticklabelsize     = 12,\n    yticklabelsize     = 12,\n    xlabelcolor        = INK,\n    ylabelcolor        = INK,\n    xticklabelcolor    = INK_SOFT,\n    yticklabelcolor    = INK_SOFT,\n    xtickcolor         = INK_SOFT,\n    ytickcolor         = INK_SOFT,\n    backgroundcolor    = PAGE_BG,\n    topspinevisible    = false,\n    rightspinevisible  = false,\n    leftspinecolor     = INK_SOFT,\n    bottomspinecolor   = INK_SOFT,\n    xgridcolor         = GRID_COLOR,\n    ygridcolor         = GRID_COLOR,\n    xminorgridvisible  = false,\n    yminorgridvisible  = false,\n)\n\n# Base map: water bodies rendered before hexbins so land clusters stay visible\npoly!(ax, bay_pts; color = WATER_FILL, strokecolor = COAST_LINE, strokewidth = 1.2)\npoly!(ax, pac_pts; color = WATER_FILL, strokecolor = COAST_LINE, strokewidth = 1.2)\n\n# Hexagonal density map overlaid on base map\nhb = hexbin!(ax, lons, lats;\n    cellsize    = 0.009,\n    colormap    = ANYPLOT_SEQ,\n    threshold   = 1,\n    strokecolor = PAGE_BG,\n    strokewidth = 0.5,\n)\n\n# Colorbar\nColorbar(fig[1, 2], hb;\n    label           = \"Ride Count\",\n    labelsize       = 13,\n    labelcolor      = INK,\n    ticklabelsize   = 11,\n    ticklabelcolor  = INK_SOFT,\n    tickcolor       = INK_SOFT,\n    width           = 18,\n)\n\nlimits!(ax, lon_lo, lon_hi, lat_lo, lat_hi)\ncolgap!(fig.layout, 12)\n\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}