{"spec_id":"stem-basic","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nstem-basic: Basic Stem Plot\nLibrary: seaborn 0.13.2 | Python 3.13.14\nQuality: 91/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\n\n\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\nBRAND = \"#009E73\"  # Imprint palette position 1\n\nsns.set_theme(\n    style=\"ticks\",\n    rc={\n        \"figure.facecolor\": PAGE_BG,\n        \"axes.facecolor\": PAGE_BG,\n        \"axes.edgecolor\": INK_SOFT,\n        \"axes.labelcolor\": INK,\n        \"text.color\": INK,\n        \"xtick.color\": INK_SOFT,\n        \"ytick.color\": INK_SOFT,\n        \"grid.color\": INK,\n        \"grid.alpha\": 0.10,\n        \"legend.facecolor\": ELEVATED_BG,\n        \"legend.edgecolor\": INK_SOFT,\n    },\n)\n\n# Data - Discrete signal samples (damped sinusoidal impulse response)\nnp.random.seed(42)\nn_samples = 30\nx = np.arange(n_samples)\ny = np.exp(-0.1 * x) * np.sin(0.5 * x) * 2.5\nenvelope = np.exp(-0.1 * x) * 2.5\n\ndf = pd.DataFrame({\"Sample Index\": x, \"Amplitude\": y, \"Magnitude\": np.abs(y)})\npeak_idx = df[\"Magnitude\"].idxmax()\n\nfig, ax = plt.subplots(figsize=(8, 4.5), dpi=400)\n\n# Decay envelope - traces the impulse-response narrative behind the samples\nsns.lineplot(x=x, y=envelope, ax=ax, color=INK_SOFT, linewidth=1.2, linestyle=\"--\", alpha=0.4, zorder=1)\nsns.lineplot(x=x, y=-envelope, ax=ax, color=INK_SOFT, linewidth=1.2, linestyle=\"--\", alpha=0.4, zorder=1)\n\n# Stems (thin vertical lines from baseline y=0 to data values)\nax.vlines(x=df[\"Sample Index\"], ymin=0, ymax=df[\"Amplitude\"], color=BRAND, linewidth=1.5, alpha=0.8, zorder=2)\n\n# Markers - uniform size per the spec's \"consistent marker size\" requirement;\n# plain dots with no background-colored edge.\nsns.scatterplot(\n    data=df, x=\"Sample Index\", y=\"Amplitude\", s=200, color=BRAND, edgecolor=\"none\", legend=False, ax=ax, zorder=3\n)\n\n# Baseline at y=0\nax.axhline(y=0, color=INK_SOFT, linewidth=0.75, alpha=0.5, zorder=1)\n\n# Annotate the peak sample to guide the viewer through the decay narrative\nax.annotate(\n    \"Peak amplitude\",\n    xy=(df[\"Sample Index\"][peak_idx], df[\"Amplitude\"][peak_idx]),\n    xytext=(df[\"Sample Index\"][peak_idx] + 3, df[\"Amplitude\"][peak_idx] + 0.3),\n    fontsize=8,\n    color=INK_SOFT,\n    arrowprops={\"arrowstyle\": \"-\", \"color\": INK_SOFT, \"alpha\": 0.6, \"linewidth\": 0.75},\n)\n\nax.set_xlabel(\"Sample Index (n)\", fontsize=10)\nax.set_ylabel(\"Amplitude\", fontsize=10)\nax.set_title(\"stem-basic · python · seaborn · anyplot.ai\", fontsize=12)\nax.tick_params(axis=\"both\", labelsize=8)\n\nax.yaxis.grid(True, linestyle=\"-\", linewidth=0.4, alpha=0.15)\nax.set_axisbelow(True)\n\nsns.despine(ax=ax)\n\nfig.tight_layout()\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\n"}