{"spec_id":"energy-level-atomic","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\nenergy-level-atomic: Atomic Energy Level Diagram\nLibrary: matplotlib 3.10.9 | Python 3.13.13\nQuality: 85/100 | Updated: 2026-05-30\n\"\"\"\n\nimport os\n\nimport matplotlib.patches as mpatches\nimport matplotlib.pyplot as plt\nimport numpy as np\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\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\n# Imprint palette — energy level lines use Imprint blue; transitions use spectral-matched Imprint hues\nLEVEL_COLOR = \"#4467A3\"  # Imprint blue\nLYMAN_COLOR = \"#BD8233\"  # Imprint ochre — warm, evokes UV glow\n\n# Data — Hydrogen atom energy levels: E_n = -13.6 / n^2 (eV)\nn_values = np.arange(1, 7)\nenergies = -13.6 / n_values**2\n\n# Sqrt-compressed display positions: y = -sqrt(|E|)\n# Preserves ordering (n=1 at bottom, ionization at top) while spreading upper levels\ny_pos = -np.sqrt(np.abs(energies))\nion_y = 0.0  # ionization at E=0 → y=0\n\n# Balmer series transitions with Imprint-matched spectral colors\n# Weakness fix: replaced similar blue-violet/purple pair with more distinct lavender/rose pair\nbalmer_data = [\n    (3, 2, \"#AE3030\"),  # H-alpha  656 nm (red → Imprint matte red)\n    (4, 2, \"#2ABCCD\"),  # H-beta   486 nm (cyan → Imprint cyan)\n    (5, 2, \"#C475FD\"),  # H-gamma  434 nm (violet → Imprint lavender)\n    (6, 2, \"#954477\"),  # H-delta  410 nm (deep violet → Imprint rose)\n]\n\n# Lyman series transitions (UV, uniform warm color)\nlyman_data = [(2, 1), (3, 1), (4, 1), (5, 1), (6, 1)]\n\n# Lookup: quantum number → compressed y position\ny_of = {n: -np.sqrt(13.6 / n**2) for n in range(1, 7)}\n\n# Plot\nfig, ax = plt.subplots(figsize=(8, 4.5), dpi=400, facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\nleft = 0.18\nright = 0.82\ngap = 0.06  # arrow gap from level lines\n\n# Energy level lines\nfor n, energy, y in zip(n_values, energies, y_pos, strict=True):\n    lw = 3.5 if n == 1 else 2.5  # bolder ground state anchors the diagram\n    ax.plot([left, right], [y, y], color=LEVEL_COLOR, linewidth=lw, solid_capstyle=\"round\", zorder=3)\n    ax.text(right + 0.02, y, f\"n = {n}\", fontsize=8, va=\"center\", ha=\"left\", color=LEVEL_COLOR, fontweight=\"medium\")\n    # Upper levels crowd together: smaller font + stagger n=5 left for visual separation\n    label_fs = 7 if n >= 4 else 8\n    label_x = (left - 0.05) if n == 5 else (left - 0.02)\n    ax.text(label_x, y, f\"{energy:.2f} eV\", fontsize=label_fs, va=\"center\", ha=\"right\", color=INK_MUTED)\n\n# Ionization limit (dashed, theme-adaptive)\nax.plot([left, right], [ion_y, ion_y], color=INK_SOFT, linewidth=1.5, linestyle=\"--\", zorder=2)\nax.text(right + 0.02, ion_y, \"Ionization (0 eV)\", fontsize=8, va=\"center\", ha=\"left\", color=INK_SOFT)\n\n# Lyman series arrows (left side)\nlyman_x = np.linspace(0.24, 0.40, len(lyman_data))\nfor (upper, lower), xp in zip(lyman_data, lyman_x, strict=True):\n    ax.annotate(\n        \"\",\n        xy=(xp, y_of[lower] + gap),\n        xytext=(xp, y_of[upper] - gap),\n        arrowprops={\"arrowstyle\": \"->,head_width=0.3,head_length=0.15\", \"color\": LYMAN_COLOR, \"lw\": 2.2},\n        zorder=4,\n    )\n\n# Balmer series arrows (right side, colored by wavelength)\nbalmer_x = np.linspace(0.55, 0.72, len(balmer_data))\nfor (upper, lower, color), xp in zip(balmer_data, balmer_x, strict=True):\n    ax.annotate(\n        \"\",\n        xy=(xp, y_of[lower] + gap),\n        xytext=(xp, y_of[upper] - gap),\n        arrowprops={\"arrowstyle\": \"->,head_width=0.3,head_length=0.15\", \"color\": color, \"lw\": 2.2},\n        zorder=4,\n    )\n\n# Series group labels\nax.text(\n    0.32,\n    (y_of[1] + y_of[2]) / 2,\n    \"Lyman series\\n(UV)\",\n    fontsize=8,\n    ha=\"center\",\n    va=\"center\",\n    color=LYMAN_COLOR,\n    fontstyle=\"italic\",\n)\nax.text(\n    0.77,\n    (y_of[2] + y_of[3]) / 2,\n    \"Balmer series\\n(Visible)\",\n    fontsize=8,\n    ha=\"left\",\n    va=\"center\",\n    color=\"#2ABCCD\",\n    fontstyle=\"italic\",\n)\n\n# Legend for Balmer transition colors + Lyman\nlegend_handles = [\n    mpatches.Patch(color=\"#AE3030\", label=\"H-α  656 nm\"),\n    mpatches.Patch(color=\"#2ABCCD\", label=\"H-β  486 nm\"),\n    mpatches.Patch(color=\"#C475FD\", label=\"H-γ  434 nm\"),\n    mpatches.Patch(color=\"#954477\", label=\"H-δ  410 nm\"),\n    mpatches.Patch(color=LYMAN_COLOR, label=\"Lyman (UV)\"),\n]\nleg = ax.legend(handles=legend_handles, fontsize=8, loc=\"lower right\", fancybox=False)\nleg.get_frame().set_facecolor(ELEVATED_BG)\nleg.get_frame().set_edgecolor(INK_SOFT)\nplt.setp(leg.get_texts(), color=INK_SOFT)\n\n# Style\ntitle = \"energy-level-atomic · python · matplotlib · anyplot.ai\"\ntitle_fontsize = max(8, round(12 * 67 / len(title))) if len(title) > 67 else 12\nax.set_ylabel(\"Energy (eV)\", fontsize=10, color=INK)\nax.set_title(title, fontsize=title_fontsize, fontweight=\"medium\", color=INK, pad=12)\nax.set_xlim(0.05, 1.08)\nax.set_ylim(y_of[1] - 0.3, ion_y + 0.4)\nax.set_xticks([])\n\n# Custom y-ticks: real energy values mapped onto compressed display axis\ntick_energies = np.array([0, -0.5, -1, -2, -4, -8, -14])\ntick_y = -np.sqrt(np.abs(tick_energies))\nax.set_yticks(tick_y)\nax.set_yticklabels([f\"{e:g}\" for e in tick_energies])\nax.tick_params(axis=\"y\", labelsize=8, colors=INK_SOFT)\n\nax.spines[\"top\"].set_visible(False)\nax.spines[\"right\"].set_visible(False)\nax.spines[\"bottom\"].set_visible(False)\nax.spines[\"left\"].set_color(INK_SOFT)\nax.yaxis.grid(True, alpha=0.15, linewidth=0.8, color=INK)\n\nplt.tight_layout()\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\n"}