{"spec_id":"bland-altman-basic","library":"makie","language":"julia","code":"# anyplot.ai\n# bland-altman-basic: Bland-Altman Agreement Plot\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 91/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 INK      = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nconst INK_SOFT = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\nconst IMPRINT_PALETTE = [\n    colorant\"#009E73\", colorant\"#C475FD\", colorant\"#4467A3\", colorant\"#BD8233\",\n    colorant\"#AE3030\", colorant\"#2ABCCD\", colorant\"#954477\", colorant\"#99B314\",\n]\nconst BRAND = IMPRINT_PALETTE[1]\nconst BIAS_COLOR = INK  # neutral anchor — reference/baseline lines read as part of the chart's structural layer\n\n# --- Data ---------------------------------------------------------------\n# Paired systolic blood pressure readings (mmHg) from two sphygmomanometers\n# on the same 90 subjects: a new automated cuff vs. a mercury reference device.\nn_subjects = 90\ntrue_pressure = rand(105:180, n_subjects)\nreference_device = true_pressure .+ randn(n_subjects) .* 3.0\nnew_device = true_pressure .+ 4.0 .+ randn(n_subjects) .* 4.5\n\nmean_pressure = (reference_device .+ new_device) ./ 2\npressure_diff = new_device .- reference_device\n\nbias = mean(pressure_diff)\nsd_diff = std(pressure_diff)\nupper_loa = bias + 1.96 * sd_diff\nlower_loa = bias - 1.96 * sd_diff\n\n# --- Plot -----------------------------------------------------------------\nfig = Figure(\n    size            = (1600, 900),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis(\n    fig[1, 1];\n    title              = \"bland-altman-basic · julia · makie · anyplot.ai\",\n    titlesize          = 20,\n    titlecolor         = INK,\n    xlabel             = \"Mean of Two Devices (mmHg)\",\n    ylabel             = \"Difference: New − Reference (mmHg)\",\n    xlabelsize         = 14,\n    ylabelsize         = 14,\n    xlabelcolor        = INK,\n    ylabelcolor        = INK,\n    xticks             = LinearTicks(7),\n    yticks             = LinearTicks(7),\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.15),\n    ygridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.15),\n    xminorgridvisible  = false,\n    yminorgridvisible  = false,\n)\n\nx_min = minimum(mean_pressure)\nx_max = maximum(mean_pressure)\n\n# Shaded limits-of-agreement band gives the acceptable-range region its own\n# visual weight instead of relying on the two dashed lines alone.\nband!(ax, [x_min, x_max], [lower_loa, lower_loa], [upper_loa, upper_loa];\n    color = (BIAS_COLOR, 0.08))\n\nscatter!(ax, mean_pressure, pressure_diff;\n    color = BRAND, markersize = 14, strokewidth = 1, strokecolor = PAGE_BG,\n    alpha = 0.65)\n\nhlines!(ax, [bias]; color = BIAS_COLOR, linewidth = 2.5)\nhlines!(ax, [upper_loa, lower_loa]; color = BIAS_COLOR, linewidth = 2, linestyle = :dash)\n\ntext!(ax, x_max, bias;\n    text = \"Bias = $(round(bias, digits = 1))\",\n    align = (:right, :bottom), fontsize = 13, color = BIAS_COLOR, offset = (0, 4))\ntext!(ax, x_max, upper_loa;\n    text = \"+1.96 SD = $(round(upper_loa, digits = 1))\",\n    align = (:right, :bottom), fontsize = 13, color = BIAS_COLOR, offset = (0, 4))\ntext!(ax, x_max, lower_loa;\n    text = \"−1.96 SD = $(round(lower_loa, digits = 1))\",\n    align = (:right, :top), fontsize = 13, color = BIAS_COLOR, offset = (0, -4))\n\n# --- Save -------------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}