{"spec_id":"pp-basic","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\npp-basic: Probability-Probability (P-P) Plot\nLibrary: plotnine 0.15.7 | Python 3.13.13\nQuality: 93/100 | Updated: 2026-06-16\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    annotate,\n    coord_fixed,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    geom_abline,\n    geom_point,\n    geom_ribbon,\n    ggplot,\n    labs,\n    scale_color_gradient,\n    scale_x_continuous,\n    scale_y_continuous,\n    theme,\n    theme_minimal,\n)\nfrom scipy import stats\n\n\n# Theme-adaptive chrome (Imprint palette + tokens)\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 (single-polarity): brand green -> blue.\n# Deviation magnitude is single-polarity, so imprint_seq is the correct ramp:\n# near-zero (good fit) reads brand green, large departures read blue. Every\n# point stays saturated and visible (the previous diverging midpoint sat too\n# close to the low end — fixed by using magnitude on a sequential ramp).\nSEQ_LOW = \"#009E73\"  # brand green — points on the diagonal (good fit)\nSEQ_HIGH = \"#4467A3\"  # blue — points departing from the diagonal\n\n# Data: Quality control — tensile strength of steel rods (MPa).\n# A mixture reflects a manufacturing process with occasional batch variation,\n# which produces a clear S-shaped departure from the normal reference.\nnp.random.seed(42)\nn = 200\nmain_batch = np.random.normal(loc=520, scale=35, size=160)\nvariant_batch = np.random.normal(loc=580, scale=20, size=40)\ntensile_strength = np.concatenate([main_batch, variant_batch])\n\nsorted_data = np.sort(tensile_strength)\nmu, sigma = np.mean(sorted_data), np.std(sorted_data)\nempirical_cdf = np.arange(1, n + 1) / (n + 1)\ntheoretical_cdf = stats.norm.cdf(sorted_data, loc=mu, scale=sigma)\n\n# Deviation from the diagonal drives the storytelling color ramp\ndeviation = empirical_cdf - theoretical_cdf\ndf = pd.DataFrame({\"theoretical\": theoretical_cdf, \"empirical\": empirical_cdf, \"abs_deviation\": np.abs(deviation)})\n\n# Confidence envelope: approximate 95% band under null (Kolmogorov-Smirnov)\nks_band = 1.36 / np.sqrt(n)\nenvelope_t = np.linspace(0, 1, 300)\nenvelope_df = pd.DataFrame(\n    {\n        \"theoretical\": envelope_t,\n        \"upper\": np.minimum(envelope_t + ks_band, 1.0),\n        \"lower\": np.maximum(envelope_t - ks_band, 0.0),\n    }\n)\n\n# Plot — plotnine grammar of graphics with layered composition\nplot = (\n    ggplot()\n    # Layer 1: KS confidence envelope (muted band fill, sits behind the data)\n    + geom_ribbon(aes(x=\"theoretical\", ymin=\"lower\", ymax=\"upper\"), data=envelope_df, fill=INK_MUTED, alpha=0.12)\n    # Layer 2: 45-degree reference line for perfect distributional fit\n    + geom_abline(intercept=0, slope=1, color=INK_MUTED, size=0.8, linetype=\"dashed\")\n    # Layer 3: Points colored by deviation magnitude — visual storytelling\n    + geom_point(aes(x=\"theoretical\", y=\"empirical\", color=\"abs_deviation\"), data=df, size=2.8, alpha=0.85, stroke=0)\n    # Imprint sequential ramp (single-polarity magnitude)\n    + scale_color_gradient(low=SEQ_LOW, high=SEQ_HIGH, name=\"Deviation\\n|emp − theo|\")\n    # Annotation: scenario context\n    + annotate(\n        \"text\",\n        x=0.04,\n        y=0.96,\n        label=\"Tensile strength of 200 steel rods\\nvs. fitted normal reference\",\n        ha=\"left\",\n        va=\"top\",\n        size=3.4,\n        color=INK_SOFT,\n        fontstyle=\"italic\",\n    )\n    # Annotation: highlight the S-curve departure\n    + annotate(\n        \"text\",\n        x=0.585,\n        y=0.66,\n        label=\"← S-curve reveals\\n     batch variation\",\n        ha=\"left\",\n        va=\"top\",\n        size=3.2,\n        color=INK,\n        fontweight=\"bold\",\n    )\n    # Annotation: label the confidence band\n    + annotate(\n        \"label\",\n        x=0.5,\n        y=0.06,\n        label=\"95% KS confidence band\",\n        ha=\"center\",\n        size=2.9,\n        color=INK_SOFT,\n        fill=ELEVATED_BG,\n        alpha=0.92,\n        label_size=0,\n    )\n    + labs(\n        x=\"Theoretical Cumulative Probability (Normal CDF)\",\n        y=\"Empirical Cumulative Probability\",\n        title=\"pp-basic · python · plotnine · anyplot.ai\",\n    )\n    + scale_x_continuous(limits=(0, 1), breaks=np.arange(0, 1.1, 0.2))\n    + scale_y_continuous(limits=(0, 1), breaks=np.arange(0, 1.1, 0.2))\n    + coord_fixed(ratio=1)\n    + theme_minimal()\n    + theme(\n        figure_size=(6, 6),\n        text=element_text(size=7),\n        plot_title=element_text(size=12, weight=\"bold\", color=INK),\n        axis_title=element_text(size=10, color=INK),\n        axis_text=element_text(size=8, color=INK_SOFT),\n        panel_grid_major=element_line(color=INK, size=0.3, alpha=0.15),\n        panel_grid_minor=element_blank(),\n        legend_title=element_text(size=8, color=INK),\n        legend_text=element_text(size=7, color=INK_SOFT),\n        legend_position=(0.86, 0.24),\n        legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG),\n    )\n)\n\n# Save (square 2400x2400 — preserves the diagonal's visual meaning)\nplot.save(f\"plot-{THEME}.png\", dpi=400, width=6, height=6, units=\"in\", verbose=False)\n"}