{"spec_id":"histogram-basic","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\nhistogram-basic: Basic Histogram\nLibrary: matplotlib 3.10.9 | Python 3.13.13\nQuality: 93/100 | Updated: 2026-05-28\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom matplotlib.colors import to_rgba\n\n\n# Theme 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\"\nBRAND = \"#009E73\"  # Imprint palette position 1 — ALWAYS first series\nMEAN_COLOR = \"#AE3030\"  # matte red — semantic anchor for reference/alert\n\n# Data - exam scores with slight left skew and high-performer cluster\nnp.random.seed(42)\nbase = np.random.normal(loc=72, scale=12, size=450)\nhigh_cluster = np.random.normal(loc=88, scale=4, size=50)\nscores = np.clip(np.concatenate([base, high_cluster]), 0, 100)\n\n# Title\ntitle = \"histogram-basic · python · matplotlib · anyplot.ai\"\ntitle_fontsize = max(8, round(12 * 67 / len(title))) if len(title) > 67 else 12\n\n# Plot\nfig, ax = plt.subplots(figsize=(8, 4.5), dpi=400, facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\nn, bins, patches = ax.hist(scores, bins=25, color=BRAND, linewidth=0.8)\n\n# Intensity-graded bar coloring via patch manipulation (matplotlib-distinctive)\nmax_count = max(n)\nbase_rgba = to_rgba(BRAND)\nfor count, patch in zip(n, patches, strict=True):\n    intensity = 0.65 + 0.35 * (count / max_count)\n    patch.set_facecolor((*base_rgba[:3], intensity * 0.85))\n    patch.set_edgecolor(to_rgba(INK_SOFT, alpha=0.35))\n\n# Key statistics\nmean_score = np.mean(scores)\ny_max = max(n)\npct_above_80 = 100 * np.sum(scores >= 80) / len(scores)\n\n# Combined mean/median line — values nearly equal, indicating symmetric distribution\nax.axvline(mean_score, color=MEAN_COLOR, linewidth=2.5, linestyle=\"--\", zorder=5)\nax.annotate(\n    f\"Mean ≈ Median: {mean_score:.0f}\",\n    xy=(mean_score, y_max * 0.90),\n    xytext=(mean_score - 20, y_max * 0.97),\n    fontsize=8,\n    fontweight=\"bold\",\n    color=MEAN_COLOR,\n    arrowprops={\"arrowstyle\": \"->\", \"color\": MEAN_COLOR, \"lw\": 1.8},\n    bbox={\"boxstyle\": \"round,pad=0.3\", \"facecolor\": ELEVATED_BG, \"edgecolor\": MEAN_COLOR, \"alpha\": 0.9},\n    zorder=6,\n)\n\n# High-performer cluster annotation with percentage insight\nax.annotate(\n    f\"High-performer cluster\\n{pct_above_80:.0f}% scored above 80\",\n    xy=(88, y_max * 0.35),\n    xytext=(96, y_max * 0.58),\n    fontsize=8,\n    fontstyle=\"italic\",\n    color=INK_SOFT,\n    ha=\"center\",\n    arrowprops={\"arrowstyle\": \"->\", \"color\": INK_SOFT, \"lw\": 1.5, \"connectionstyle\": \"arc3,rad=-0.2\"},\n    bbox={\"boxstyle\": \"round,pad=0.3\", \"facecolor\": ELEVATED_BG, \"edgecolor\": INK_SOFT, \"alpha\": 0.9},\n    zorder=6,\n)\n\n# Labels and styling\nax.set_xlabel(\"Exam Score (points)\", fontsize=10, color=INK)\nax.set_ylabel(\"Frequency (count)\", fontsize=10, color=INK)\nax.set_title(title, fontsize=title_fontsize, fontweight=\"medium\", color=INK, pad=12)\nax.tick_params(axis=\"both\", labelsize=8, colors=INK_SOFT)\n\n# Spine removal\nax.spines[\"top\"].set_visible(False)\nax.spines[\"right\"].set_visible(False)\nfor s in (\"left\", \"bottom\"):\n    ax.spines[s].set_color(INK_SOFT)\n\n# Subtle y-axis grid\nax.yaxis.grid(True, alpha=0.15, linewidth=0.8, color=INK)\nax.set_axisbelow(True)\n\n# Y-axis starts at zero\nax.set_ylim(bottom=0)\n\nfig.subplots_adjust(left=0.09, right=0.97, top=0.91, bottom=0.12)\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\n"}