{"spec_id":"histogram-capability","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nhistogram-capability: Process Capability Plot with Specification Limits\nLibrary: plotly 6.8.0 | Python 3.13.14\nQuality: 90/100 | Updated: 2026-06-20\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport plotly.graph_objects as go\nfrom scipy import stats\n\n\n# Theme tokens — Imprint palette (see prompts/default-style-guide.md)\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\"\nGRID = \"rgba(26,26,23,0.15)\" if THEME == \"light\" else \"rgba(240,239,232,0.15)\"\n\nBRAND = \"#009E73\"  # Imprint position 1 — histogram bars (first series)\nLIMIT_COLOR = \"#AE3030\"  # matte red — spec limit boundaries (semantic: bad/rejection)\nTARGET_COLOR = \"#DDCC77\"  # amber — target nominal reference line\n\n# Data — shaft diameter measurements (mm), slightly off-center to contrast Cp vs Cpk\nnp.random.seed(42)\nmeasurements = np.random.normal(loc=10.010, scale=0.012, size=200)\n\nlsl = 9.95\nusl = 10.05\ntarget = 10.00\n\nmean_val = np.mean(measurements)\nsigma = np.std(measurements, ddof=1)\n\n# Capability indices\ncp = (usl - lsl) / (6 * sigma)\ncpk = min((usl - mean_val) / (3 * sigma), (mean_val - lsl) / (3 * sigma))\n\n# Normal distribution curve (fitted to sample mean and sigma)\nx_min, x_max = 9.925, 10.075\nx_curve = np.linspace(mean_val - 4 * sigma, mean_val + 4 * sigma, 300)\ny_curve = stats.norm.pdf(x_curve, mean_val, sigma)\n\n# Scale curve to match histogram area (count scale)\nbin_width = (measurements.max() - measurements.min()) / 25\ny_scaled = y_curve * len(measurements) * bin_width\n\n# Plot\nfig = go.Figure()\n\n# Rejection zone shading via vrect — clearly visible background, below all traces\nfig.add_vrect(x0=x_min, x1=lsl, fillcolor=\"rgba(174,48,48,0.10)\", line_width=0, layer=\"below\")\nfig.add_vrect(x0=usl, x1=x_max, fillcolor=\"rgba(174,48,48,0.10)\", line_width=0, layer=\"below\")\n\n# Histogram bars (Imprint brand green — first categorical series)\nfig.add_trace(\n    go.Histogram(\n        x=measurements,\n        nbinsx=25,\n        marker={\"color\": \"rgba(0,158,115,0.75)\", \"line\": {\"color\": PAGE_BG, \"width\": 1.2}},\n        name=\"Measurements\",\n        hovertemplate=\"Diameter: %{x:.4f} mm<br>Count: %{y}<extra></extra>\",\n    )\n)\n\n# Normal distribution curve (INK — analytical/structural layer)\nfig.add_trace(\n    go.Scatter(\n        x=x_curve,\n        y=y_scaled,\n        mode=\"lines\",\n        line={\"color\": INK, \"width\": 3.0, \"shape\": \"spline\"},\n        name=\"Normal Fit\",\n        hoverinfo=\"skip\",\n    )\n)\n\n# LSL vertical line (matte red — rejection boundary)\nfig.add_shape(\n    type=\"line\", x0=lsl, x1=lsl, y0=0, y1=0.90, yref=\"paper\", line={\"color\": LIMIT_COLOR, \"width\": 2.5, \"dash\": \"dash\"}\n)\nfig.add_annotation(\n    x=lsl,\n    y=0.93,\n    yref=\"paper\",\n    text=f\"<b>LSL</b><br>{lsl}\",\n    showarrow=False,\n    font={\"size\": 11, \"color\": LIMIT_COLOR},\n    align=\"center\",\n)\n\n# USL vertical line (matte red — rejection boundary)\nfig.add_shape(\n    type=\"line\", x0=usl, x1=usl, y0=0, y1=0.90, yref=\"paper\", line={\"color\": LIMIT_COLOR, \"width\": 2.5, \"dash\": \"dash\"}\n)\nfig.add_annotation(\n    x=usl,\n    y=0.93,\n    yref=\"paper\",\n    text=f\"<b>USL</b><br>{usl}\",\n    showarrow=False,\n    font={\"size\": 11, \"color\": LIMIT_COLOR},\n    align=\"center\",\n)\n\n# Target line (amber — nominal reference point)\nfig.add_shape(\n    type=\"line\",\n    x0=target,\n    x1=target,\n    y0=0,\n    y1=0.90,\n    yref=\"paper\",\n    line={\"color\": TARGET_COLOR, \"width\": 2.5, \"dash\": \"dashdot\"},\n)\nfig.add_annotation(\n    x=target,\n    y=0.93,\n    yref=\"paper\",\n    text=f\"<b>Target</b><br>{target:.2f}\",\n    showarrow=False,\n    font={\"size\": 11, \"color\": TARGET_COLOR},\n    align=\"center\",\n)\n\n# Capability status\ncpk_status = \"Capable\" if cpk >= 1.33 else \"Marginal\" if cpk >= 1.0 else \"Not Capable\"\ncpk_flag = \"PASS\" if cpk >= 1.33 else \"WARN\" if cpk >= 1.0 else \"FAIL\"\n\n# Process capability annotation card\nfig.add_annotation(\n    x=0.98,\n    y=0.86,\n    xref=\"paper\",\n    yref=\"paper\",\n    text=(\n        f\"<b>Process Capability</b><br>\"\n        f\"Cp = {cp:.2f}    Cpk = {cpk:.2f}<br>\"\n        f\"<br>\"\n        f\"μ = {mean_val:.4f} mm<br>\"\n        f\"σ = {sigma:.4f} mm<br>\"\n        f\"<br>\"\n        f\"<b>{cpk_status}</b> [{cpk_flag}]\"\n    ),\n    showarrow=False,\n    font={\"size\": 11, \"color\": INK},\n    align=\"left\",\n    xanchor=\"right\",\n    yanchor=\"top\",\n    bgcolor=ELEVATED_BG,\n    bordercolor=INK_SOFT,\n    borderwidth=1.5,\n    borderpad=10,\n)\n\n# Layout\nfig.update_layout(\n    autosize=False,\n    title={\n        \"text\": (\n            \"<b>Shaft Diameter Process Capability</b>\"\n            f\"<br><span style='font-size:12px;color:{INK_MUTED}'>\"\n            \"histogram-capability · python · plotly · anyplot.ai</span>\"\n        ),\n        \"font\": {\"size\": 16, \"color\": INK},\n        \"x\": 0.5,\n        \"xanchor\": \"center\",\n        \"y\": 0.97,\n        \"yanchor\": \"top\",\n    },\n    xaxis={\n        \"title\": {\"text\": \"Shaft Diameter (mm)\", \"font\": {\"size\": 12, \"color\": INK}},\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"showgrid\": False,\n        \"zeroline\": False,\n        \"showline\": True,\n        \"linecolor\": INK_SOFT,\n        \"linewidth\": 1,\n        \"range\": [x_min, x_max],\n        \"dtick\": 0.01,\n        \"tickformat\": \".2f\",\n        \"gridcolor\": GRID,\n        \"zerolinecolor\": INK_SOFT,\n    },\n    yaxis={\n        \"title\": {\"text\": \"Frequency\", \"font\": {\"size\": 12, \"color\": INK}},\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"showgrid\": True,\n        \"gridcolor\": GRID,\n        \"gridwidth\": 0.5,\n        \"zeroline\": False,\n        \"showline\": False,\n        \"rangemode\": \"tozero\",\n        \"linecolor\": INK_SOFT,\n        \"zerolinecolor\": INK_SOFT,\n    },\n    template=\"plotly_white\",\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    font={\"color\": INK},\n    bargap=0,\n    margin={\"l\": 80, \"r\": 50, \"t\": 80, \"b\": 60},\n    showlegend=True,\n    legend={\n        \"font\": {\"size\": 10, \"color\": INK_SOFT},\n        \"x\": 0.02,\n        \"y\": 0.78,\n        \"bgcolor\": ELEVATED_BG,\n        \"bordercolor\": INK_SOFT,\n        \"borderwidth\": 1,\n    },\n)\n\n# Save\nfig.write_image(f\"plot-{THEME}.png\", width=800, height=450, scale=4)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}