{"spec_id":"scatter-connected-temporal","library":"makie","language":"julia","code":"# anyplot.ai\n# scatter-connected-temporal: Connected Scatter Plot with Temporal Path\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 82/100 | Updated: 2026-10-08\n\nusing CairoMakie\nusing Colors\nusing Random\n\nRandom.seed!(42)\n\n# Theme tokens — Imprint palette\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 sequential colormap — early (green) → late (blue) encodes temporal direction\nconst ANYPLOT_SEQ = cgrad([colorant\"#009E73\", colorant\"#4467A3\"])\n\n# Data — synthetic daily closing price vs trading volume over 40 sessions\nn    = 40\ndays = collect(1:n)\n\nret    = 0.004 .+ randn(n) .* 0.012\nprice  = 82.0 .* cumprod(1 .+ ret)\nvolume = 11.0 .+ 90.0 .* abs.(ret) .+ randn(n) .* 0.8\n\n# Temporal position [0, 1] for colormap\nt_norm = (days .- days[1]) ./ (days[end] - days[1])\n\n# Key session annotations (first, every ~10th, last)\nkey_idx = [1, 10, 20, 30, 40]\n\ntitle_str = \"Price vs Volume · scatter-connected-temporal · julia · makie · anyplot.ai\"\ntitle_n   = length(title_str)\ntitle_sz  = max(14, round(Int, 20 * 67 / title_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              = title_str,\n    titlesize          = title_sz,\n    titlecolor         = INK,\n    xlabel             = \"Trading Volume (million shares)\",\n    ylabel             = \"Closing Price (USD)\",\n    xlabelsize         = 14,\n    ylabelsize         = 14,\n    xlabelcolor        = INK,\n    ylabelcolor        = INK,\n    xticklabelsize     = 12,\n    yticklabelsize     = 12,\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         = RGBAf(INK.r, INK.g, INK.b, 0.12),\n    ygridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.12),\n    xminorgridvisible  = false,\n    yminorgridvisible  = false,\n)\n\n# Temporal path — one segment per session pair, colored by midpoint time position\nfor i in 1:(n - 1)\n    mid_t = (t_norm[i] + t_norm[i + 1]) / 2\n    lines!(ax, [volume[i], volume[i + 1]], [price[i], price[i + 1]];\n        color     = ANYPLOT_SEQ[mid_t],\n        linewidth = 2.5,\n    )\nend\n\n# Scatter points — colored by temporal position via Imprint sequential colormap\nsc = scatter!(ax, volume, price;\n    color       = t_norm,\n    colormap    = ANYPLOT_SEQ,\n    markersize  = 14,\n    strokewidth = 1.0,\n    strokecolor = PAGE_BG,\n)\n\n# Directional arrow at temporal start — scaled to 6% of each axis span for visibility\nlet\n    volume_span  = maximum(volume) - minimum(volume)\n    price_span = maximum(price) - minimum(price)\n    dx = volume[2] - volume[1]\n    dy = price[2] - price[1]\n    nx = dx / volume_span\n    ny = dy / price_span\n    len = sqrt(nx^2 + ny^2)\n    scale = 0.06\n    arrows!(ax, [volume[1]], [price[1]], [nx / len * scale * volume_span], [ny / len * scale * price_span];\n        arrowsize = 16,\n        color     = ANYPLOT_SEQ[0.0],\n        linewidth = 2.0,\n    )\nend\n\n# Key session labels at notable positions\nfor ki in key_idx\n    text!(ax, volume[ki], price[ki];\n        text     = \"Day \" * string(days[ki]),\n        fontsize = 14,\n        color    = INK,\n        align    = (:center, :bottom),\n        offset   = (0, 8),\n    )\nend\n\n# Colorbar — shows trading-day range encoded by the temporal gradient\nColorbar(fig[1, 2];\n    colormap       = ANYPLOT_SEQ,\n    limits         = (Float64(days[1]), Float64(days[end])),\n    label          = \"Trading day\",\n    labelcolor     = INK,\n    ticklabelcolor = INK_SOFT,\n    tickcolor      = INK_SOFT,\n    ticklabelsize  = 11,\n    labelsize      = 13,\n    width          = 18,\n)\n\ncolgap!(fig.layout, 1, 20)\n\n# Save\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}