{"spec_id":"curve-oc","library":"makie","language":"julia","code":"# anyplot.ai\n# curve-oc: Operating Characteristic (OC) Curve\n# Library: makie 0.22.10 | Julia 1.11.9\n# Quality: 89/100 | Created: 2026-06-20\n\nusing CairoMakie\nusing Colors\nusing Random\n\nRandom.seed!(42)\n\n# Theme tokens (Imprint palette — theme-adaptive chrome)\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 (always first series)\n    colorant\"#C475FD\",  # 2 — lavender\n    colorant\"#4467A3\",  # 3 — blue\n]\n\n# Data — compute OC curves via binomial CDF: P(accept) = sum_{k=0}^{c} C(n,k) p^k (1-p)^(n-k)\noc_prob(n, c, p) = sum(binomial(n, k) * p^k * (1.0 - p)^(n - k) for k in 0:c)\noc_curve(n, c, ps) = [oc_prob(n, c, p) for p in ps]\n\np_range   = collect(range(0.0, 0.20; length = 200))\nplans     = [(50, 1), (100, 2), (200, 4)]\nplan_labs = [\"n=50, c=1\", \"n=100, c=2\", \"n=200, c=4\"]\npa_data   = [oc_curve(n, c, p_range) for (n, c) in plans]\n\naql  = 0.02   # Acceptable Quality Level\nltpd = 0.08   # Lot Tolerance Percent Defective\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             = \"curve-oc · julia · makie · anyplot.ai\",\n    titlesize         = 20,\n    titlecolor        = INK,\n    xlabel            = \"Fraction Defective (p)\",\n    ylabel            = \"Probability of Acceptance\",\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    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    ygridcolor        = RGBAf(INK.r, INK.g, INK.b, 0.15),\n    xminorgridvisible = false,\n    yminorgridvisible = false,\n    limits            = (0.0, 0.205, 0.0, 1.05),\n)\n\n# Risk zone shading — drawn first so OC curves render on top\nhspan!(ax, 0.95, 1.05; color = RGBAf(0.0, 0.62, 0.45, 0.07))   # producer risk (1−α region), brand green tint\nhspan!(ax, 0.0,  0.05; color = RGBAf(0.68, 0.19, 0.19, 0.07))  # consumer risk (β region), matte red tint\n\n# AQL and LTPD vertical reference lines\nref_color = RGBAf(INK.r, INK.g, INK.b, 0.45)\nvlines!(ax, [aql];  color = ref_color, linestyle = :dash, linewidth = 1.5)\nvlines!(ax, [ltpd]; color = ref_color, linestyle = :dash, linewidth = 1.5)\n\n# Producer risk (α) and consumer risk (β) horizontal reference lines\nhlines!(ax, [0.95]; color = RGBAf(INK.r, INK.g, INK.b, 0.30), linestyle = :dot, linewidth = 1.2)\nhlines!(ax, [0.05]; color = RGBAf(INK.r, INK.g, INK.b, 0.30), linestyle = :dot, linewidth = 1.2)\n\n# OC curves\nfor (i, (pa, lab)) in enumerate(zip(pa_data, plan_labs))\n    lines!(ax, p_range, pa;\n           color     = IMPRINT_PALETTE[i],\n           linewidth = 2.5,\n           label     = lab)\nend\n\n# AQL / LTPD labels — raised to y=0.87 to anchor near the high-probability zone\ntext!(ax, aql + 0.003, 0.87;  text = \"AQL = 2%\",  color = INK_SOFT, fontsize = 11, align = (:left, :center))\ntext!(ax, ltpd + 0.003, 0.87; text = \"LTPD = 8%\", color = INK_SOFT, fontsize = 11, align = (:left, :center))\n\n# Risk threshold labels — 1−α placed on left to avoid legend overlap; β given left padding\ntext!(ax, 0.005, 0.965; text = \"1−α\", color = INK_SOFT, fontsize = 11, align = (:left, :bottom))\ntext!(ax, 0.190, 0.065; text = \"β\",   color = INK_SOFT, fontsize = 11, align = (:right, :bottom))\n\naxislegend(ax;\n           position        = :rt,\n           backgroundcolor = ELEVATED_BG,\n           labelcolor      = INK_SOFT,\n           framecolor      = RGBAf(INK_SOFT.r, INK_SOFT.g, INK_SOFT.b, 0.3),\n           labelsize       = 12)\n\n# Save\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}