{"spec_id":"histogram-density","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nhistogram-density: Density Histogram\nLibrary: plotly 6.7.0 | Python 3.13.13\nQuality: 92/100 | Updated: 2026-05-11\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport plotly.graph_objects as go\nfrom scipy import stats\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\"\nGRID = \"rgba(26,26,23,0.10)\" if THEME == \"light\" else \"rgba(240,239,232,0.10)\"\n\nBRAND = \"#009E73\"  # Okabe-Ito position 1\nOKABE_ITO_2 = \"#C475FD\"  # Okabe-Ito position 2 for KDE curve\n\n# Data - simulated test scores with a more pronounced bimodal distribution\nnp.random.seed(42)\ntest_scores = np.concatenate(\n    [\n        np.random.normal(loc=65, scale=8, size=350),  # Main group (lower peak)\n        np.random.normal(loc=90, scale=6, size=200),  # High performers (upper peak)\n    ]\n)\n\n# Create histogram with density normalization\nfig = go.Figure()\n\n# Histogram trace (normalized to density)\nfig.add_trace(\n    go.Histogram(\n        x=test_scores,\n        histnorm=\"probability density\",\n        nbinsx=30,\n        marker={\"color\": BRAND, \"line\": {\"color\": PAGE_BG, \"width\": 1}},\n        opacity=0.75,\n        name=\"Test Scores\",\n        hovertemplate=\"<b>Score Range</b>: %{x:.1f}<br><b>Density</b>: %{y:.4f}<extra></extra>\",\n    )\n)\n\n# Overlay KDE (kernel density estimate) for smooth reference curve\nx_range = np.linspace(test_scores.min() - 5, test_scores.max() + 5, 200)\nkde = stats.gaussian_kde(test_scores)\nfig.add_trace(\n    go.Scatter(\n        x=x_range,\n        y=kde(x_range),\n        mode=\"lines\",\n        line={\"color\": OKABE_ITO_2, \"width\": 4},\n        name=\"Density Curve (KDE)\",\n        hovertemplate=\"<b>Score</b>: %{x:.1f}<br><b>Density</b>: %{y:.4f}<extra></extra>\",\n    )\n)\n\n# Layout\nfig.update_layout(\n    title={\"text\": \"histogram-density · plotly · anyplot.ai\", \"font\": {\"size\": 28, \"color\": INK}, \"x\": 0.5, \"xanchor\": \"center\"},\n    xaxis={\n        \"title\": {\"text\": \"Test Score (points)\", \"font\": {\"size\": 22, \"color\": INK}},\n        \"tickfont\": {\"size\": 18, \"color\": INK_SOFT},\n        \"showgrid\": True,\n        \"gridcolor\": GRID,\n        \"gridwidth\": 1,\n        \"linecolor\": INK_SOFT,\n        \"zerolinecolor\": INK_SOFT,\n    },\n    yaxis={\n        \"title\": {\"text\": \"Density (probability per unit)\", \"font\": {\"size\": 22, \"color\": INK}},\n        \"tickfont\": {\"size\": 18, \"color\": INK_SOFT},\n        \"showgrid\": True,\n        \"gridcolor\": GRID,\n        \"gridwidth\": 1,\n        \"linecolor\": INK_SOFT,\n        \"zerolinecolor\": INK_SOFT,\n    },\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    font={\"color\": INK},\n    legend={\n        \"font\": {\"size\": 18, \"color\": INK_SOFT},\n        \"x\": 0.98,\n        \"y\": 0.98,\n        \"xanchor\": \"right\",\n        \"yanchor\": \"top\",\n        \"bgcolor\": ELEVATED_BG,\n        \"bordercolor\": INK_SOFT,\n        \"borderwidth\": 1,\n    },\n    margin={\"l\": 80, \"r\": 40, \"t\": 80, \"b\": 80},\n    bargap=0.02,\n    hovermode=\"closest\",\n)\n\n# Save as PNG (4800 x 2700 via scale=3)\nfig.write_image(f\"plot-{THEME}.png\", width=1600, height=900, scale=3)\n\n# Save as HTML for interactivity\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}