{"spec_id":"scatter-regression-linear","library":"makie","language":"julia","code":"# anyplot.ai\n# scatter-regression-linear: Scatter Plot with Linear Regression\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 88/100 | Created: 2026-08-05\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]\n\n# --- Data ---------------------------------------------------------------------\nn = 150\ntemperature = rand(15.0:0.1:35.0, n)\nenergy_consumption = 12.0 .+ 3.4 .* temperature .+ randn(n) .* 15.0\n\n# --- Regression -----------------------------------------------------------\nx_mean = mean(temperature)\ny_mean = mean(energy_consumption)\nsum_xx = sum((temperature .- x_mean) .^ 2)\nsum_xy = sum((temperature .- x_mean) .* (energy_consumption .- y_mean))\nslope = sum_xy / sum_xx\nintercept = y_mean - slope * x_mean\n\nfitted = intercept .+ slope .* temperature\nresiduals = energy_consumption .- fitted\nss_res = sum(residuals .^ 2)\nss_tot = sum((energy_consumption .- y_mean) .^ 2)\nr_squared = 1 - ss_res / ss_tot\n\ndof = n - 2\nresidual_se = sqrt(ss_res / dof)\nt_critical = 1.96  # normal approximation for 95% CI, valid at dof=148\n\nx_line = range(minimum(temperature), maximum(temperature), length = 200)\ny_line = intercept .+ slope .* x_line\nse_fit = residual_se .* sqrt.(1 / n .+ (x_line .- x_mean) .^ 2 ./ sum_xx)\ny_lower = y_line .- t_critical .* se_fit\ny_upper = y_line .+ t_critical .* se_fit\n\n# --- Plot -----------------------------------------------------------------\nfig = Figure(\n    resolution      = (1600, 900),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis(\n    fig[1, 1];\n    title              = \"scatter-regression-linear · julia · makie · anyplot.ai\",\n    titlesize          = 20,\n    titlecolor         = INK,\n    xlabel             = \"Average Temperature (°C)\",\n    ylabel             = \"Daily Energy Consumption (kWh)\",\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    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)\n\nband_plot = band!(ax, x_line, y_lower, y_upper; color = (IMPRINT_PALETTE[3], 0.16))\nscatter_plot = scatter!(ax, temperature, energy_consumption;\n    color = (IMPRINT_PALETTE[1], 0.55), markersize = 10, strokewidth = 0)\nline_plot = lines!(ax, x_line, y_line; color = IMPRINT_PALETTE[3], linewidth = 3)\n\n# --- Equation callout card ---------------------------------------------------\n# A layered card (drop-shadow rect + bordered panel) instead of bare text-on-plot,\n# giving the annotation a distinct focal point rather than a floating label.\ncard_bg = THEME == \"light\" ? colorant\"#FFFDF6\" : colorant\"#242420\"\npoly!(ax, Point2f[(0.022, 0.975), (0.335, 0.975), (0.335, 0.815), (0.022, 0.815)];\n    space = :relative, color = (INK, 0.06), strokewidth = 0)\npoly!(ax, Point2f[(0.015, 0.985), (0.328, 0.985), (0.328, 0.825), (0.015, 0.825)];\n    space = :relative, color = (card_bg, 0.92), strokecolor = INK_SOFT, strokewidth = 1)\n\nequation_sign = intercept >= 0 ? \"+\" : \"-\"\nequation = \"y = $(round(slope, digits = 2))x $equation_sign $(round(abs(intercept), digits = 1))\"\nstats_label = \"$equation\\nR² = $(round(r_squared, digits = 3))\"\n\ntext!(ax, 0.035, 0.955; text = stats_label, space = :relative,\n    align = (:left, :top), fontsize = 16, color = INK)\n\n# --- Legend (Makie layout composition, identifies the 95% CI band) ----------\nlegend_elements = [\n    MarkerElement(color = (IMPRINT_PALETTE[1], 0.55), marker = :circle, markersize = 10),\n    LineElement(color = IMPRINT_PALETTE[3], linewidth = 3),\n    PolyElement(color = (IMPRINT_PALETTE[3], 0.16)),\n]\nLegend(fig[1, 2], legend_elements, [\"Observed data\", \"Linear fit\", \"95% CI band\"];\n    framevisible   = false,\n    labelcolor     = INK,\n    labelsize      = 13,\n    backgroundcolor = PAGE_BG,\n    tellheight     = false,\n    valign         = :top,\n)\ncolsize!(fig.layout, 2, Relative(0.13))\ncolgap!(fig.layout, 1, 18)\n\n# --- Save -------------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}