{"spec_id":"pp-basic","library":"altair","language":"python","code":"\"\"\" anyplot.ai\npp-basic: Probability-Probability (P-P) Plot\nLibrary: altair 6.2.1 | Python 3.13.13\nQuality: 93/100 | Updated: 2026-06-16\n\"\"\"\n\nimport os\nfrom statistics import NormalDist\n\nimport altair as alt\nimport numpy as np\nimport pandas as pd\nfrom PIL import Image\n\n\n# Theme tokens (see prompts/default-style-guide.md \"Theme-adaptive Chrome\")\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\n# Imprint sequential cmap for continuous deviation (brand green -> blue)\nIMPRINT_SEQ = [\"#009E73\", \"#4467A3\"]\nALERT = \"#AE3030\"  # matte red — semantic anchor for worst fit / max deviation\n\n# Data — clinical trial: blood pressure measurements vs normal reference\nnp.random.seed(42)\nobserved = np.concatenate([np.random.normal(50, 10, 160), np.random.exponential(5, 40) + 55])\nobserved_sorted = np.sort(observed)\nn = len(observed_sorted)\n\nmu = float(observed_sorted.mean())\nsigma = float(observed_sorted.std())\ndist = NormalDist(mu, sigma)\nempirical_cdf = np.arange(1, n + 1) / (n + 1)\ntheoretical_cdf = np.array([dist.cdf(x) for x in observed_sorted])\ndeviation = np.abs(empirical_cdf - theoretical_cdf)\n\n# Mark the point of maximum deviation for annotation\nmax_dev_idx = int(np.argmax(deviation))\n\ndf = pd.DataFrame({\"Theoretical CDF (Normal)\": theoretical_cdf, \"Empirical CDF\": empirical_cdf, \"Deviation\": deviation})\n\nref_df = pd.DataFrame({\"x\": [0, 1], \"y\": [0, 1]})\n\n# Confidence band around diagonal (± ~1.36/√n Kolmogorov-Smirnov bound)\nks_bound = 1.36 / np.sqrt(n)\nband_x = np.linspace(0, 1, 50)\nband_df = pd.DataFrame(\n    {\"x\": band_x, \"y_lo\": np.clip(band_x - ks_bound, 0, 1), \"y_hi\": np.clip(band_x + ks_bound, 0, 1)}\n)\n\n# Max deviation annotation label\nmax_dev_df = pd.DataFrame(\n    {\n        \"x\": [theoretical_cdf[max_dev_idx]],\n        \"y\": [empirical_cdf[max_dev_idx]],\n        \"label\": [f\"Max deviation: {deviation[max_dev_idx]:.3f}\"],\n    }\n)\n\n# Interactive selection — hovering highlights nearby points (Altair-distinctive)\nhover = alt.selection_point(on=\"pointerover\", nearest=True, empty=False)\n\n# Plot layers\nband = (\n    alt.Chart(band_df).mark_area(opacity=0.12, color=INK_MUTED).encode(x=alt.X(\"x:Q\"), y=alt.Y(\"y_lo:Q\"), y2=\"y_hi:Q\")\n)\n\nreference_line = (\n    alt.Chart(ref_df).mark_line(strokeDash=[8, 6], strokeWidth=2.5, color=INK_SOFT).encode(x=\"x:Q\", y=\"y:Q\")\n)\n\npoints = (\n    alt.Chart(df)\n    .mark_circle(stroke=PAGE_BG, strokeWidth=0.8)\n    .encode(\n        x=alt.X(\"Theoretical CDF (Normal):Q\", scale=alt.Scale(domain=[0, 1]), title=\"Theoretical CDF (Normal)\"),\n        y=alt.Y(\"Empirical CDF:Q\", scale=alt.Scale(domain=[0, 1]), title=\"Empirical CDF\"),\n        color=alt.Color(\n            \"Deviation:Q\",\n            scale=alt.Scale(range=IMPRINT_SEQ, domain=[0, float(deviation.max())]),\n            legend=alt.Legend(title=\"Deviation\", orient=\"bottom-right\", direction=\"vertical\", gradientLength=120),\n        ),\n        size=alt.condition(\n            hover, alt.value(260), alt.Size(\"Deviation:Q\", scale=alt.Scale(range=[55, 200]), legend=None)\n        ),\n        opacity=alt.condition(hover, alt.value(1.0), alt.value(0.7)),\n        strokeWidth=alt.condition(hover, alt.value(1.8), alt.value(0.8)),\n        tooltip=[\n            alt.Tooltip(\"Theoretical CDF (Normal):Q\", format=\".3f\"),\n            alt.Tooltip(\"Empirical CDF:Q\", format=\".3f\"),\n            alt.Tooltip(\"Deviation:Q\", format=\".4f\", title=\"Abs. Deviation\"),\n        ],\n    )\n    .add_params(hover)\n)\n\n# Highlight max-deviation point with contrasting ring\nmax_point = (\n    alt.Chart(max_dev_df).mark_point(size=380, stroke=ALERT, strokeWidth=2.5, filled=False).encode(x=\"x:Q\", y=\"y:Q\")\n)\n\nmax_label = (\n    alt.Chart(max_dev_df)\n    .mark_text(align=\"left\", dx=14, dy=-12, fontSize=13, fontWeight=\"bold\", color=ALERT)\n    .encode(x=\"x:Q\", y=\"y:Q\", text=\"label:N\")\n)\n\nchart = (\n    (band + reference_line + points + max_point + max_label)\n    .properties(\n        width=480,\n        height=480,\n        background=PAGE_BG,\n        padding={\"left\": 0, \"right\": 0, \"top\": 0, \"bottom\": 0},\n        title=alt.Title(\n            \"pp-basic · python · altair · anyplot.ai\",\n            fontSize=16,\n            fontWeight=\"bold\",\n            color=INK,\n            subtitle=\"Blood pressure normality check — points colored by deviation from perfect fit\",\n            subtitleFontSize=11,\n            subtitleColor=INK_SOFT,\n        ),\n    )\n    .configure_view(fill=PAGE_BG, strokeWidth=0)\n    .configure_axis(\n        labelFontSize=10,\n        titleFontSize=12,\n        titleColor=INK,\n        labelColor=INK_SOFT,\n        grid=True,\n        gridOpacity=0.15,\n        gridColor=INK,\n        domain=False,\n        ticks=False,\n    )\n    .configure_legend(\n        titleFontSize=10,\n        labelFontSize=10,\n        titleColor=INK,\n        labelColor=INK_SOFT,\n        fillColor=ELEVATED_BG,\n        strokeColor=INK_SOFT,\n        padding=10,\n        cornerRadius=4,\n    )\n)\n\n# Save — square target 2400×2400 (P-P plot keeps a square data region for the 45° diagonal)\nchart.save(f\"plot-{THEME}.png\", scale_factor=4.0)\nchart.save(f\"plot-{THEME}.html\")\n\n# Pad the saved PNG up to the exact 2400×2400 target (vl-convert pads outside width/height).\nTW, TH = 2400, 2400\n_img = Image.open(f\"plot-{THEME}.png\").convert(\"RGB\")\n_w, _h = _img.size\nif _w > TW or _h > TH:\n    raise SystemExit(\n        f\"altair vl-convert produced {_w}×{_h}, exceeds target {TW}×{TH}. \"\n        f\"Shrink chart .properties(width=, height=) values and re-render.\"\n    )\nif _w < TW or _h < TH:\n    _canvas = Image.new(\"RGB\", (TW, TH), PAGE_BG)\n    _canvas.paste(_img, ((TW - _w) // 2, (TH - _h) // 2))\n    _canvas.save(f\"plot-{THEME}.png\")\n"}