{"spec_id":"ridgeline-basic","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nridgeline-basic: Basic Ridgeline Plot\nLibrary: seaborn 0.13.2 | Python 3.13.14\nQuality: 93/100 | Updated: 2026-07-25\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nfrom matplotlib.colors import LinearSegmentedColormap\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# Data - UI task reaction times, ordered by rising interaction complexity\nnp.random.seed(42)\n\ntasks = [\n    \"Single Tap\",\n    \"Double Tap\",\n    \"Swipe Gesture\",\n    \"Tap & Hold\",\n    \"Drag & Drop\",\n    \"Dropdown Select\",\n    \"Text Entry\",\n    \"Menu Navigation\",\n    \"Multi-Step Form\",\n]\n\nmean_ms = [280, 350, 420, 480, 560, 630, 720, 810, 950]\ngamma_shape = 6  # moderate right skew, characteristic of human reaction-time distributions\n\ndata = []\nfor task, mu in zip(tasks, mean_ms, strict=True):\n    reaction_times = np.random.gamma(shape=gamma_shape, scale=mu / gamma_shape, size=180)\n    for value in reaction_times:\n        data.append({\"task\": task, \"reaction_time\": value})\n\ndf = pd.DataFrame(data)\n\n# Imprint sequential colormap (brand green -> blue): single-polarity gradient tracks rising task complexity\nimprint_seq = LinearSegmentedColormap.from_list(\"imprint_seq\", [\"#009E73\", \"#4467A3\"])\npalette = [imprint_seq(t) for t in np.linspace(0, 1, len(tasks))]\n\n# Configure seaborn: transparent axes so figure background shows through\nsns.set_theme(\n    style=\"white\",\n    rc={\n        \"axes.facecolor\": (0, 0, 0, 0),\n        \"figure.facecolor\": PAGE_BG,\n        \"text.color\": INK,\n        \"axes.labelcolor\": INK,\n        \"xtick.color\": INK_SOFT,\n        \"ytick.color\": INK_SOFT,\n    },\n)\n\n# FacetGrid ridgeline layout (simplest task at top -> most complex task at bottom)\ng = sns.FacetGrid(df, row=\"task\", hue=\"task\", aspect=15, height=0.6, palette=palette, row_order=tasks, hue_order=tasks)\n\n# Filled density curves\ng.map(sns.kdeplot, \"reaction_time\", bw_adjust=0.8, clip_on=False, fill=True, alpha=0.85, linewidth=2.5)\n\n# Outline in ELEVATED_BG creates visible separation between overlapping ridges on both themes\ng.map(sns.kdeplot, \"reaction_time\", bw_adjust=0.8, clip_on=False, color=ELEVATED_BG, linewidth=3)\n\n# Baseline\ng.map(plt.axhline, y=0, linewidth=2, linestyle=\"-\", color=INK_SOFT, clip_on=False)\n\n\ndef label(x, color, label):\n    ax = plt.gca()\n    ax.text(\n        -0.02, 0.38, label, fontsize=12, fontweight=\"bold\", color=color, ha=\"right\", va=\"center\", transform=ax.transAxes\n    )\n    ax.text(\n        -0.02,\n        0.06,\n        f\"μ ≈ {x.mean():.0f} ms\",\n        fontsize=10,\n        color=INK_SOFT,\n        ha=\"right\",\n        va=\"center\",\n        transform=ax.transAxes,\n    )\n\n\ng.map(label, \"reaction_time\")\n\n# Overlap and cleanup\ng.figure.subplots_adjust(hspace=-0.5)\ng.set_titles(\"\")\ng.set(yticks=[], ylabel=\"\")\ng.despine(bottom=True, left=True)\n\ng.axes[-1, 0].set_xlabel(\"Reaction Time (ms)\", fontsize=11, color=INK)\ng.axes[-1, 0].tick_params(axis=\"x\", labelsize=9, colors=INK_SOFT)\n\ng.figure.set_size_inches(8, 4.5)\ng.figure.patch.set_facecolor(PAGE_BG)\ng.figure.suptitle(\"ridgeline-basic · python · seaborn · anyplot.ai\", fontsize=13, y=0.98, fontweight=\"bold\", color=INK)\n\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\n"}