{"spec_id":"ridgeline-basic","library":"altair","language":"python","code":"\"\"\" anyplot.ai\nridgeline-basic: Basic Ridgeline Plot\nLibrary: altair 6.2.2 | Python 3.13.14\nQuality: 93/100 | Updated: 2026-07-25\n\"\"\"\n\nimport os\n\nimport altair as alt\nimport numpy as np\nimport pandas as pd\nfrom PIL import Image\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\"\n\n# Imprint sequential colormap (brand green -> blue) for the 12 ordered ridges\nIMPRINT_SEQ = [\"#009E73\", \"#4467A3\"]\n_c0 = tuple(int(IMPRINT_SEQ[0][i : i + 2], 16) for i in (1, 3, 5))\n_c1 = tuple(int(IMPRINT_SEQ[1][i : i + 2], 16) for i in (1, 3, 5))\nmonth_colors = [\n    \"#{:02x}{:02x}{:02x}\".format(*(round(_c0[j] + (_c1[j] - _c0[j]) * i / 11) for j in range(3))) for i in range(12)\n]\n\n# Data\nnp.random.seed(42)\nmonths = [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"]\n\ndata = []\nbase_temps = [2, 4, 8, 14, 18, 22, 25, 24, 20, 14, 8, 4]\ntemp_stds = [4, 5, 5, 4, 4, 3, 3, 3, 4, 5, 5, 4]\n\nfor i, month in enumerate(months):\n    temps = np.random.normal(base_temps[i], temp_stds[i], 200)\n    for t in temps:\n        data.append({\"month\": month, \"temperature\": t, \"month_order\": i})\n\ndf = pd.DataFrame(data)\n\n# Plot - ridgeline via row faceting with negative spacing for overlap\nchart = (\n    alt.Chart(df)\n    .transform_density(\n        density=\"temperature\",\n        as_=[\"temperature\", \"density\"],\n        groupby=[\"month\", \"month_order\"],\n        extent=[-15, 40],\n        bandwidth=2,\n    )\n    .mark_area(fillOpacity=0.85, stroke=INK_SOFT, strokeWidth=1, interpolate=\"monotone\")\n    .encode(\n        x=alt.X(\n            \"temperature:Q\",\n            title=\"Temperature (°C)\",\n            axis=alt.Axis(labelFontSize=10, titleFontSize=12, grid=False),\n            scale=alt.Scale(domain=[-15, 40]),\n        ),\n        y=alt.Y(\"density:Q\", title=None, axis=None, scale=alt.Scale(domain=[0, 0.15])),\n        fill=alt.Fill(\"month_order:O\", scale=alt.Scale(domain=list(range(12)), range=month_colors), legend=None),\n        row=alt.Row(\n            \"month:N\",\n            sort=months,\n            header=alt.Header(\n                labelFontSize=12, labelAngle=0, labelAlign=\"right\", labelPadding=8, title=None, labelColor=INK_SOFT\n            ),\n        ),\n    )\n    .properties(\n        width=650,\n        height=28,\n        background=PAGE_BG,\n        title=alt.Title(\n            text=\"Monthly Temperature Distribution · ridgeline-basic · altair · anyplot.ai\",\n            fontSize=16,\n            anchor=\"middle\",\n        ),\n    )\n    .configure_facet(spacing=-13)\n    .configure_view(fill=PAGE_BG, stroke=None)\n    .configure_axis(\n        labelFontSize=10,\n        titleFontSize=12,\n        labelColor=INK_SOFT,\n        titleColor=INK,\n        domainColor=INK_SOFT,\n        tickColor=INK_SOFT,\n    )\n    .configure_title(color=INK)\n    .configure_header(labelColor=INK_SOFT)\n)\n\n# Save\nchart.save(f\"plot-{THEME}.png\", scale_factor=4.0)\n\n# PAD-only to exact target canvas — see prompts/library/altair.md \"Canvas\"\nTW, TH = 3200, 1800\n_img = Image.open(f\"plot-{THEME}.png\").convert(\"RGB\")\n_w, _h = _img.size\nif _w > TW or _h > TH:\n    raise SystemExit(\n        f\"altair vl-convert produced {_w}×{_h}, exceeds target {TW}×{TH}. \"\n        f\"Shrink chart .properties(width=, height=) values and re-render.\"\n    )\nif _w < TW or _h < TH:\n    _canvas = Image.new(\"RGB\", (TW, TH), PAGE_BG)\n    _canvas.paste(_img, ((TW - _w) // 2, (TH - _h) // 2))\n    _canvas.save(f\"plot-{THEME}.png\")\n\nchart.save(f\"plot-{THEME}.html\")\n"}