{"spec_id":"scatter-embedding","library":"makie","language":"julia","code":"# anyplot.ai\n# scatter-embedding: t-SNE and UMAP Embedding Visualization\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 94/100 | Created: 2026-08-11\n\nusing CairoMakie\nusing Colors\nusing Random\nusing Statistics\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\"\n\nconst IMPRINT_PALETTE = [\n    colorant\"#009E73\",  # 1 — brand green (first series)\n    colorant\"#C475FD\",  # 2 — lavender\n    colorant\"#4467A3\",  # 3 — blue\n    colorant\"#BD8233\",  # 4 — ochre\n    colorant\"#AE3030\",  # 5 — matte red\n    colorant\"#2ABCCD\",  # 6 — cyan\n    colorant\"#954477\",  # 7 — rose\n    colorant\"#99B314\",  # 8 — lime\n]\n\n# Data — synthetic UMAP projection of a single-cell RNA-seq immune atlas,\n# 8 organic (anisotropic, unequal-density) clusters mimicking real embeddings\ncell_types = [\"T cells\", \"B cells\", \"NK cells\", \"Monocytes\",\n              \"Dendritic cells\", \"Erythrocytes\", \"Platelets\", \"Neutrophils\"]\nn_clusters = length(cell_types)\n\ncenters = [(-6.5, 3.8), (-1.8, 5.6), (3.2, 6.0), (6.6, 1.8),\n           (4.8, -3.4), (0.2, -5.6), (-4.2, -4.4), (-7.2, -0.6)]\nspreads  = [1.3, 1.1, 0.9, 1.4, 1.0, 1.2, 0.75, 1.5]\nrotation = [0.3, -0.4, 0.6, -0.2, 0.5, -0.6, 0.2, -0.3]\nsizes    = [165, 140, 90, 130, 100, 110, 70, 120]  # 500-5000 pt range, high density\n\nxs = Float64[]\nys = Float64[]\ngroup_idx = Int[]\nfor i in 1:n_clusters\n    cx, cy = centers[i]\n    s = spreads[i]\n    θ = rotation[i]\n    dx = s .* randn(sizes[i])\n    dy = 0.6s .* randn(sizes[i])\n    append!(xs, cx .+ dx .* cos(θ) .- dy .* sin(θ))\n    append!(ys, cy .+ dx .* sin(θ) .+ dy .* cos(θ))\n    append!(group_idx, fill(i, sizes[i]))\nend\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              = \"Immune Cell Atlas · scatter-embedding · julia · makie · anyplot.ai\",\n    titlesize          = 20,\n    titlecolor         = INK,\n    subtitle           = \"UMAP (n_neighbors = 15, min_dist = 0.1)\",\n    subtitlesize       = 14,\n    subtitlecolor      = INK_SOFT,\n    xlabel             = \"UMAP 1\",\n    ylabel             = \"UMAP 2\",\n    xlabelsize         = 14,\n    ylabelsize         = 14,\n    xlabelcolor        = INK,\n    ylabelcolor        = INK,\n    xticklabelsvisible = false,\n    yticklabelsvisible = false,\n    xticksvisible      = false,\n    yticksvisible      = false,\n    backgroundcolor    = PAGE_BG,\n    xgridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.15f0),\n    ygridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.15f0),\n    xminorgridvisible  = false,\n    yminorgridvisible  = false,\n)\n\n# Embedding coordinates carry no meaningful axis position, so drop the frame\n# entirely (style guide's \"minimal scatter\" spine alternative) rather than\n# keeping the default L-shape around hidden ticks.\nhidespines!(ax)\n\n# --- Points, one scatter! call per cluster for a clean discrete legend -------\n# T cells is the largest population (165 of 925 cells, ~18%); a modest bump\n# in marker size/opacity gives it visual priority over the other 7 clusters.\nlargest = argmax(sizes)\nfor i in 1:n_clusters\n    mask = group_idx .== i\n    emphasized = i == largest\n    scatter!(ax, xs[mask], ys[mask];\n        color       = (IMPRINT_PALETTE[i], emphasized ? 0.8 : 0.65),\n        markersize  = emphasized ? 11 : 9,\n        strokewidth = 0,\n        label       = cell_types[i],\n    )\nend\n\n# --- Centroid labels — direct per-cluster labeling. 8 series exceeds safe\n# --- color-only discrimination, so labels add a redundant, non-color cue. ---\nfor i in 1:n_clusters\n    cx, cy = mean(xs[group_idx .== i]), mean(ys[group_idx .== i])\n    text!(ax, cx, cy;\n        text     = cell_types[i],\n        color    = INK,\n        fontsize = i == largest ? 17 : 15,\n        font     = :bold,\n        align    = (:center, :center),\n    )\nend\n\n# --- Legend ------------------------------------------------------------------\nLegend(\n    fig[1, 2],\n    ax,\n    framecolor      = INK_SOFT,\n    backgroundcolor = ELEVATED_BG,\n    labelcolor      = INK,\n    labelsize       = 13,\n    patchsize       = (16, 16),\n    margin          = (8, 8, 8, 8),\n)\n\n# --- Footnote — layout-level polish + the storytelling cue behind the -------\n# --- T-cell emphasis above (Makie's grid layout takes a footnote row as ----\n# --- naturally as a plot column). --------------------------------------------\nLabel(\n    fig[2, 1:2],\n    \"T cells form the largest population in this atlas — 165 of 925 profiled cells (~18%).\",\n    fontsize  = 12,\n    color     = INK_SOFT,\n    halign    = :left,\n    padding   = (4, 0, 0, 0),\n)\n\n# --- Save --------------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}