{"spec_id":"heatmap-polar","library":"makie","language":"julia","code":"# anyplot.ai\n# heatmap-polar: Polar Heatmap for Cyclic Two-Dimensional Data\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 88/100 | Created: 2026-09-05\n\nusing CairoMakie\nusing Colors\nusing Random\n\n# Theme tokens (see prompts/default-style-guide.md \"Background\" + \"Theme-adaptive Chrome\")\nTHEME    = get(ENV, \"ANYPLOT_THEME\", \"light\")\nPAGE_BG  = THEME == \"light\" ? colorant\"#FAF8F1\" : colorant\"#1A1A17\"\nINK      = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nINK_SOFT = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\n\n# The radial (day) tick labels sit on top of the heatmap cells rather than the page\n# background, and the heatmap colors are identical across themes — so this pairing is\n# fixed rather than theme-flipped, keeping the labels legible on both green and blue cells.\nLABEL_ON_DATA        = colorant\"#1A1A17\"\nLABEL_ON_DATA_HALO   = colorant\"#FFFDF6\"\n\n# Data — hourly web-app traffic by hour of day (angular) and day of week (radial)\nRandom.seed!(42)\n\nhours = 0:23\ndays = [\"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\", \"Sun\"]\n\n# Weekday: broad mid-morning/mid-afternoon work-hours bump + small evening check-in.\n# Weekend: single, later and lower midday-to-evening bump. Circular hour distance keeps\n# the pattern continuous across the 11pm/12am wrap.\nweekday_pattern = [\n    20 + 55 * exp(-(min(abs(h - 10), 24 - abs(h - 10)))^2 / 18) +\n         45 * exp(-(min(abs(h - 15), 24 - abs(h - 15)))^2 / 18) +\n         18 * exp(-(min(abs(h - 20), 24 - abs(h - 20)))^2 / 8)\n    for h in hours\n]\nweekend_pattern = [\n    15 + 60 * exp(-(min(abs(h - 13), 24 - abs(h - 13)))^2 / 32) +\n         35 * exp(-(min(abs(h - 20), 24 - abs(h - 20)))^2 / 18)\n    for h in hours\n]\nday_scale = [0.75, 0.90, 1.05, 1.20, 1.35, 0.55, 0.45]\n\nvisits = Array{Float64}(undef, length(hours), length(days))\nfor (d, scale) in enumerate(day_scale)\n    pattern = d <= 5 ? weekday_pattern : weekend_pattern\n    visits[:, d] = max.(0.0, scale .* pattern .+ 4 .* randn(length(hours)))\nend\n\ntheta_edges = range(0, 2π, length = length(hours) + 1)\nr_edges = 0:length(days)\n\n# Plot — see default-style-guide.md \"Visual Sizing Defaults\" for the canvas + sizing values\nfig = Figure(size = (1200, 1200), fontsize = 14, backgroundcolor = PAGE_BG)\n\nax = PolarAxis(\n    fig[1, 1];\n    title = \"heatmap-polar · julia · makie · anyplot.ai\",\n    titlesize = 22,\n    titlecolor = INK,\n    backgroundcolor = PAGE_BG,\n    direction = -1,\n    theta_0 = -pi / 2,\n    thetaticks = (range(0, 2π, length = 5)[1:4], [\"12am\", \"6am\", \"12pm\", \"6pm\"]),\n    rticks = (0.5:1:(length(days) - 0.5), days),\n    rtickangle = π / 8,\n    thetaticklabelsize = 15,\n    rticklabelsize = 15,\n    thetaticklabelcolor = INK_SOFT,\n    rticklabelcolor = LABEL_ON_DATA,\n    rticklabelstrokewidth = 1.5,\n    rticklabelstrokecolor = LABEL_ON_DATA_HALO,\n    rgridcolor = (INK, 0.15),\n    thetagridcolor = (INK, 0.15),\n    spinecolor = INK_SOFT,\n)\n\n# Sequential Imprint colormap (brand green -> blue) — visit counts are single-polarity\nhm = heatmap!(\n    ax, theta_edges, r_edges, visits,\n    colormap = [colorant\"#009E73\", colorant\"#4467A3\"],\n)\n\n# heatmap! has no strokewidth/strokecolor for this (irregular-grid) method, so cell\n# borders are drawn as thin overlay lines on top of the data instead: one spoke per\n# hour edge, one ring per day edge.\nspoke_pts = Point2f[]\nfor theta in theta_edges[1:end-1]\n    push!(spoke_pts, Point2f(theta, 0), Point2f(theta, length(days)), Point2f(NaN, NaN))\nend\nlines!(ax, spoke_pts, color = (PAGE_BG, 0.4), linewidth = 1)\n\nring_pts = Point2f[]\narc_theta = range(0, 2π, length = 145)\nfor r in r_edges\n    for theta in arc_theta\n        push!(ring_pts, Point2f(theta, r))\n    end\n    push!(ring_pts, Point2f(NaN, NaN))\nend\nlines!(ax, ring_pts, color = (PAGE_BG, 0.4), linewidth = 1)\n\nColorbar(\n    fig[1, 2], hm;\n    label = \"Avg. Hourly Visits\",\n    labelsize = 17,\n    ticklabelsize = 13,\n    labelcolor = INK,\n    ticklabelcolor = INK_SOFT,\n    width = 20,\n)\ncolgap!(fig.layout, 15)\n\n# Save\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}