{"spec_id":"scatter-3d","library":"makie","language":"julia","code":"# anyplot.ai\n# scatter-3d: 3D Scatter Plot\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 87/100 | Created: 2026-09-10\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 GRID        = RGBAf(INK.r, INK.g, INK.b, 0.15)\n\nconst IMPRINT_PALETTE = [\n    colorant\"#009E73\", colorant\"#C475FD\", colorant\"#4467A3\", colorant\"#BD8233\",\n    colorant\"#AE3030\", colorant\"#2ABCCD\", colorant\"#954477\", colorant\"#99B314\",\n]\n\n# --- Data ----------------------------------------------------------------------\n# Sensor readings from a machine feature space (vibration, temperature,\n# pressure), forming three clusters by operating mode. Idle and Normal\n# deliberately overlap in vibration/temperature (the third axis, pressure,\n# is what actually separates them) so the 3D view carries information a\n# single 2D projection would not.\nn_per_mode = 60\nmodes = [\"Idle\", \"Normal\", \"Stress\"]\ncenters = [(1.0, 55.0, 1.2), (1.5, 58.0, 3.0), (6.5, 92.0, 4.6)]\nspreads = [(0.4, 3.5, 0.2), (0.45, 3.5, 0.3), (0.7, 5.0, 0.4)]\n\nvibration = Float64[]\ntemperature = Float64[]\npressure = Float64[]\nmode_idx = Int[]\n\nfor (i, (cx, cy, cz)) in enumerate(centers)\n    sx, sy, sz = spreads[i]\n    append!(vibration, cx .+ sx .* randn(n_per_mode))\n    append!(temperature, cy .+ sy .* randn(n_per_mode))\n    append!(pressure, cz .+ sz .* randn(n_per_mode))\n    append!(mode_idx, fill(i, n_per_mode))\nend\n\n# --- Plot ------------------------------------------------------------------\nfig = Figure(\n    resolution      = (1600, 900),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis3(\n    fig[1, 1];\n    title             = \"scatter-3d · julia · makie · anyplot.ai\",\n    titlesize         = 20,\n    titlecolor        = INK,\n    xlabel            = \"Vibration (mm/s)\",\n    ylabel            = \"Temperature (°C)\",\n    zlabel            = \"Pressure (bar)\",\n    xlabelsize        = 14,\n    ylabelsize        = 14,\n    zlabelsize        = 14,\n    xlabelcolor       = INK,\n    ylabelcolor       = INK,\n    zlabelcolor       = INK,\n    xticklabelsize    = 12,\n    yticklabelsize    = 12,\n    zticklabelsize    = 12,\n    xticklabelcolor   = INK_SOFT,\n    yticklabelcolor   = INK_SOFT,\n    zticklabelcolor   = INK_SOFT,\n    xtickcolor        = INK_SOFT,\n    ytickcolor        = INK_SOFT,\n    ztickcolor        = INK_SOFT,\n    xspinecolor_1     = INK_SOFT, xspinecolor_2 = INK_SOFT, xspinecolor_3 = INK_SOFT,\n    yspinecolor_1     = INK_SOFT, yspinecolor_2 = INK_SOFT, yspinecolor_3 = INK_SOFT,\n    zspinecolor_1     = INK_SOFT, zspinecolor_2 = INK_SOFT, zspinecolor_3 = INK_SOFT,\n    xgridcolor        = GRID,\n    ygridcolor        = GRID,\n    zgridcolor        = GRID,\n    xypanelcolor      = ELEVATED_BG,\n    xzpanelcolor      = ELEVATED_BG,\n    yzpanelcolor      = ELEVATED_BG,\n    backgroundcolor   = PAGE_BG,\n    azimuth           = 1.275 * pi,\n    elevation         = 0.15 * pi,\n    aspect            = (1, 1, 1),\n)\n\nfor (i, name) in enumerate(modes)\n    sel = mode_idx .== i\n    scatter!(\n        ax, vibration[sel], temperature[sel], pressure[sel];\n        color = (IMPRINT_PALETTE[i], 0.85), markersize = 14,\n        strokewidth = 0.5, strokecolor = PAGE_BG, label = name,\n    )\nend\n\naxislegend(\n    ax; position = :lt, framevisible = false, labelcolor = INK,\n    labelsize = 12, backgroundcolor = :transparent,\n)\n\n# --- Save --------------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}