{"spec_id":"scatter-constellation-diagram","library":"makie","language":"julia","code":"# anyplot.ai\n# scatter-constellation-diagram: Digital Modulation Constellation Diagram\n# Library: makie 0.22.10 | Julia 1.11.9\n# Quality: 88/100 | Created: 2026-06-18\n\nusing CairoMakie\nusing Colors\nusing Printf\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\"\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 (semantic: reference target)\n    colorant\"#2ABCCD\",  # 6 — cyan\n    colorant\"#954477\",  # 7 — rose\n    colorant\"#99B314\",  # 8 — lime\n]\n\n# 16-QAM ideal constellation: ±1, ±3 grid (4×4 = 16 symbols)\nlevels = [-3.0, -1.0, 1.0, 3.0]\nideal_i = [ii for qi in levels for ii in levels]\nideal_q = [qi for qi in levels for ii in levels]\n\n# Received symbols with additive Gaussian noise (~20 dB SNR)\nn_symbols = 1200\nnoise_std = 0.18\nsymbol_idx = rand(1:16, n_symbols)\nrecv_i = ideal_i[symbol_idx] .+ noise_std .* randn(n_symbols)\nrecv_q = ideal_q[symbol_idx] .+ noise_std .* randn(n_symbols)\n\n# EVM: sqrt(mean squared error) / RMS ideal amplitude × 100%\nerr_sq = (recv_i .- ideal_i[symbol_idx]).^2 .+ (recv_q .- ideal_q[symbol_idx]).^2\nrms_signal = sqrt(mean(ideal_i.^2 .+ ideal_q.^2))\nevm_pct = sqrt(mean(err_sq)) / rms_signal * 100.0\n\n# Figure — square canvas (equal aspect ratio required for constellation geometry)\nfig = Figure(\n    size            = (1200, 1200),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\ntitle_str = \"scatter-constellation-diagram · julia · makie · anyplot.ai\"\nax = Axis(\n    fig[1, 1];\n    title              = title_str,\n    titlesize          = 28,\n    titlecolor         = INK,\n    xlabel             = \"In-Phase (I)\",\n    ylabel             = \"Quadrature (Q)\",\n    xlabelsize         = 16,\n    ylabelsize         = 16,\n    xlabelcolor        = INK,\n    ylabelcolor        = INK,\n    xticklabelcolor    = INK_SOFT,\n    yticklabelcolor    = INK_SOFT,\n    xticklabelsize     = 13,\n    yticklabelsize     = 13,\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    xgridvisible       = false,\n    ygridvisible       = false,\n    xminorgridvisible  = false,\n    yminorgridvisible  = false,\n    aspect             = DataAspect(),\n    limits             = (-4.5, 4.5, -4.5, 4.5),\n)\n\n# Dashed decision boundary lines separating the 16 symbol regions\nboundary_color = RGBAf(INK.r, INK.g, INK.b, 0.2f0)\nfor boundary in [-2.0, 0.0, 2.0]\n    hlines!(ax, boundary; color = boundary_color, linewidth = 1.2, linestyle = :dash)\n    vlines!(ax, boundary; color = boundary_color, linewidth = 1.2, linestyle = :dash)\nend\n\n# Received symbols — Imprint brand green (first series), semi-transparent\nrecv_plt = scatter!(ax, recv_i, recv_q;\n    color       = RGBAf(IMPRINT_PALETTE[1].r, IMPRINT_PALETTE[1].g, IMPRINT_PALETTE[1].b, 0.35f0),\n    markersize  = 6,\n    strokewidth = 0,\n)\n\n# Ideal 16-QAM reference points — matte red cross markers\nideal_plt = scatter!(ax, ideal_i, ideal_q;\n    color       = IMPRINT_PALETTE[5],\n    marker      = :xcross,\n    markersize  = 20,\n    strokewidth = 2.5,\n)\n\n# EVM annotation (top-left, clear of constellation data)\ntext!(ax, -4.2, 4.1;\n    text     = @sprintf(\"EVM = %.1f%%\", evm_pct),\n    fontsize = 15,\n    color    = INK_SOFT,\n)\n\n# Legend\nLegend(\n    fig[2, 1],\n    [recv_plt, ideal_plt],\n    [\"Received symbols (n = $n_symbols)\", \"Ideal 16-QAM points\"],\n    orientation     = :horizontal,\n    framecolor      = INK_SOFT,\n    framewidth      = 0.5,\n    labelcolor      = INK_SOFT,\n    fontsize        = 14,\n    backgroundcolor = ELEVATED_BG,\n    tellheight      = true,\n)\n\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}