{"spec_id":"histogram-capability","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nhistogram-capability: Process Capability Plot with Specification Limits\nLibrary: letsplot 4.10.1 | Python 3.13.14\nQuality: 89/100 | Updated: 2026-06-20\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom lets_plot import (\n    LetsPlot,\n    aes,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    geom_area,\n    geom_histogram,\n    geom_rect,\n    geom_text,\n    geom_vline,\n    ggplot,\n    ggsize,\n    labs,\n    layer_tooltips,\n    scale_x_continuous,\n    scale_y_continuous,\n    theme,\n    theme_minimal,\n)\nfrom lets_plot.export import ggsave\nfrom scipy import stats\n\n\nLetsPlot.setup_html()\n\n# Theme tokens — Imprint palette, theme-adaptive chrome\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\n# Pre-blended grid color: 15% INK over PAGE_BG (rgba() avoids dependency on CSS parser)\nGRID_COLOR = \"#D8D7D0\" if THEME == \"light\" else \"#3A3A37\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\n\nIMPRINT_PALETTE = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\", \"#99B314\"]\nBRAND = IMPRINT_PALETTE[0]  # #009E73 — always first series (histogram bars + curve)\nLIMIT_COLOR = IMPRINT_PALETTE[4]  # #AE3030 — matte red, semantic: out-of-spec danger\n\n# Data — shaft diameter measurements (mm), Six Sigma precision machining\nnp.random.seed(42)\nlsl = 9.95\nusl = 10.05\ntarget = 10.00\nmargin = 0.015\n\nmeasurements = np.random.normal(loc=10.002, scale=0.012, size=200)\nsample_mean = float(np.mean(measurements))\nsample_std = float(np.std(measurements, ddof=1))\n\n# Capability indices per Six Sigma formulas\ncp = (usl - lsl) / (6 * sample_std)\ncpk = min((usl - sample_mean) / (3 * sample_std), (sample_mean - lsl) / (3 * sample_std))\n\ndf = pd.DataFrame({\"measurement\": measurements})\n\n# Compute bins matching lets-plot's geom_histogram(bins=30) behavior:\n# lets-plot bins the data over the visible x range (limits from scale_x_continuous)\nlp_bins = np.linspace(lsl - margin, usl + margin, 31)\nhist_counts, _ = np.histogram(measurements, bins=lp_bins)\ny_max = float(hist_counts.max())\nlp_bin_width = float(lp_bins[1] - lp_bins[0])\n\n# Normal distribution curve fitted to sample mean and std\nx_curve = np.linspace(sample_mean - 4 * sample_std, sample_mean + 4 * sample_std, 300)\ny_curve = stats.norm.pdf(x_curve, sample_mean, sample_std)\ny_curve_scaled = y_curve * lp_bin_width * len(measurements)\ndf_curve = pd.DataFrame({\"x\": x_curve, \"y\": y_curve_scaled})\n\ncap_text = f\"Cp = {cp:.2f}  |  Cpk = {cpk:.2f}\"\nstats_text = f\"Mean = {sample_mean:.4f} mm  |  Std = {sample_std:.4f} mm\"\n\n# Place capability text in upper-left tail region (above low-count bars)\nann_x = lsl + 0.004\nann_df = pd.DataFrame({\"x\": [ann_x], \"y\": [y_max * 0.92], \"label\": [cap_text]})\nstats_ann_df = pd.DataFrame({\"x\": [ann_x], \"y\": [y_max * 0.78], \"label\": [stats_text]})\n\n# Spec limit labels — symmetric margins, labels outside bars\nlsl_label_df = pd.DataFrame({\"x\": [lsl - 0.004], \"y\": [y_max * 0.70], \"label\": [\"LSL\\n9.950\"]})\nusl_label_df = pd.DataFrame({\"x\": [usl + 0.004], \"y\": [y_max * 0.70], \"label\": [\"USL\\n10.050\"]})\n# Target label above histogram top (clear of bars and curve)\ntarget_label_df = pd.DataFrame({\"x\": [target], \"y\": [y_max * 1.05], \"label\": [\"Target\\n10.000\"]})\n\n# Title (53 chars < 67 baseline, no scaling needed)\ntitle = \"histogram-capability · python · letsplot · anyplot.ai\"\n\n# Plot\nplot = (\n    ggplot(df, aes(x=\"measurement\"))\n    + geom_histogram(\n        bins=30,\n        fill=BRAND,\n        color=PAGE_BG,\n        alpha=0.75,\n        size=0.3,\n        tooltips=layer_tooltips().format(\"..count..\", \"d\").line(\"Count|@..count..\"),\n    )\n    + geom_area(\n        data=df_curve, mapping=aes(x=\"x\", y=\"y\"), fill=BRAND, alpha=0.15, color=BRAND, size=1.5, inherit_aes=False\n    )\n    # Specification limits: matte red = out-of-spec semantic anchor\n    + geom_vline(xintercept=lsl, color=LIMIT_COLOR, size=1.5, linetype=\"dashed\")\n    + geom_vline(xintercept=usl, color=LIMIT_COLOR, size=1.5, linetype=\"dashed\")\n    # Target: INK neutral = reference/baseline semantic anchor (theme-adaptive)\n    + geom_vline(xintercept=target, color=INK, size=1.5, linetype=\"dashed\")\n    + geom_text(\n        data=lsl_label_df,\n        mapping=aes(x=\"x\", y=\"y\", label=\"label\"),\n        size=4,\n        color=LIMIT_COLOR,\n        fontface=\"bold\",\n        hjust=1,\n        inherit_aes=False,\n    )\n    + geom_text(\n        data=usl_label_df,\n        mapping=aes(x=\"x\", y=\"y\", label=\"label\"),\n        size=4,\n        color=LIMIT_COLOR,\n        fontface=\"bold\",\n        hjust=0,\n        inherit_aes=False,\n    )\n    + geom_text(\n        data=target_label_df,\n        mapping=aes(x=\"x\", y=\"y\", label=\"label\"),\n        size=4,\n        color=INK_SOFT,\n        fontface=\"bold\",\n        hjust=0.5,\n        inherit_aes=False,\n    )\n    # Subtle callout box behind capability indices for visual anchoring\n    + geom_rect(\n        xmin=ann_x - 0.003,\n        xmax=ann_x + 0.030,\n        ymin=y_max * 0.72,\n        ymax=y_max * 0.98,\n        fill=ELEVATED_BG,\n        color=INK_SOFT,\n        alpha=0.90,\n        size=0.3,\n        inherit_aes=False,\n    )\n    # Capability indices — most prominent annotation\n    + geom_text(\n        data=ann_df,\n        mapping=aes(x=\"x\", y=\"y\", label=\"label\"),\n        size=5,\n        color=INK,\n        fontface=\"bold\",\n        hjust=0,\n        inherit_aes=False,\n    )\n    + geom_text(\n        data=stats_ann_df,\n        mapping=aes(x=\"x\", y=\"y\", label=\"label\"),\n        size=4.5,\n        color=INK_SOFT,\n        hjust=0,\n        inherit_aes=False,\n    )\n    + scale_x_continuous(name=\"Shaft Diameter (mm)\", format=\".3f\", limits=[lsl - margin, usl + margin])\n    + scale_y_continuous(name=\"Frequency\", format=\"d\", expand=[0, 0, 0.15, 0])\n    + labs(title=title)\n    + theme_minimal()\n    + theme(\n        plot_title=element_text(size=16, face=\"bold\", color=INK),\n        axis_title=element_text(size=12, color=INK),\n        axis_text=element_text(size=10, color=INK_SOFT),\n        legend_position=\"none\",\n        panel_grid_major_x=element_blank(),\n        panel_grid_minor=element_blank(),\n        panel_grid_major_y=element_line(color=GRID_COLOR, size=0.5),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG),\n        axis_line=element_line(color=INK_SOFT),\n    )\n    + ggsize(800, 450)\n)\n\n# Save\nggsave(plot, f\"plot-{THEME}.png\", path=\".\", scale=4)\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n"}