{"spec_id":"energy-level-atomic","library":"pygal","language":"python","code":"\"\"\" anyplot.ai\nenergy-level-atomic: Atomic Energy Level Diagram\nLibrary: pygal 3.1.0 | Python 3.13.13\nQuality: 87/100 | Updated: 2026-05-30\n\"\"\"\n\nimport os\n\nimport pygal\nfrom pygal.style import Style\n\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\n# Data — Hydrogen atom spectral series\n# Evenly-spaced visual y positions (nonlinear scale for converging upper levels)\nvisual_y = {1: 1.0, 2: 2.5, 3: 4.0, 4: 5.5, 5: 7.0, 6: 8.5}\nionization_y = 10.0\n\nlyman_transitions = [(2, 1, \"Ly-α 122 nm\"), (3, 1, \"Ly-β 103 nm\"), (4, 1, \"Ly-γ 97 nm\")]\nbalmer_transitions = [(3, 2, \"Hα 656 nm\"), (4, 2, \"Hβ 486 nm\"), (5, 2, \"Hγ 434 nm\"), (6, 2, \"Hδ 410 nm\")]\npaschen_transitions = [(4, 3, \"Pa-α 1875 nm\"), (5, 3, \"Pa-β 1282 nm\"), (6, 3, \"Pa-γ 1094 nm\")]\n\nlevel_x_start = 1.0\nlevel_x_end = 9.0\nlyman_x_positions = [2.0, 2.7, 3.4]\nbalmer_x_positions = [4.5, 5.2, 5.9, 6.6]\npaschen_x_positions = [7.5, 8.1, 8.7]\n\n# Colors: level lines → INK_MUTED (theme-adaptive), ionization → INK (theme-adaptive)\n# Transitions: Imprint palette with spectral semantic mapping\n#   Lyman UV (< 400 nm): lavender, rose, blue\n#   Balmer visible (400–700 nm): green (#009E73 brand anchor for focal H-alpha), cyan, blue, violet\n#   Paschen IR (> 800 nm): ochre, amber, lime\nall_colors = (\n    INK_MUTED,\n    INK_MUTED,\n    INK_MUTED,  # levels n=1–3\n    INK_MUTED,\n    INK_MUTED,\n    INK_MUTED,  # levels n=4–6\n    INK,  # ionization limit\n    \"#C475FD\",\n    \"#954477\",\n    \"#4467A3\",  # Lyman: lavender, rose, blue\n    \"#009E73\",\n    \"#2ABCCD\",\n    \"#4467A3\",\n    \"#C475FD\",  # Balmer: green (H-alpha focal), cyan, blue, violet\n    \"#BD8233\",\n    \"#DDCC77\",\n    \"#99B314\",  # Paschen: ochre, amber, lime\n)\n\ntitle_str = \"Hydrogen Atom · energy-level-atomic · python · pygal · anyplot.ai\"\ntitle_fontsize = round(66 * (67 / len(title_str) if len(title_str) > 67 else 1.0))\n\ncustom_style = Style(\n    background=PAGE_BG,\n    plot_background=PAGE_BG,\n    foreground=INK,\n    foreground_strong=INK,\n    foreground_subtle=INK_MUTED,\n    colors=all_colors,\n    title_font_size=title_fontsize,\n    label_font_size=48,\n    major_label_font_size=44,\n    legend_font_size=44,\n    value_font_size=36,\n    stroke_width=2.5,\n)\n\n# Plot\nchart = pygal.XY(\n    width=3200,\n    height=1800,\n    style=custom_style,\n    title=title_str,\n    y_title=\"Energy (eV)\",\n    show_legend=True,\n    legend_at_bottom=True,\n    legend_at_bottom_columns=4,\n    show_x_guides=False,\n    show_y_guides=False,\n    show_x_labels=False,\n    dots_size=10,\n    stroke=True,\n    margin=60,\n    margin_left=280,\n    margin_right=80,\n    margin_bottom=200,\n    margin_top=80,\n    range=(0, 11),\n    xrange=(0, 9.5),\n    truncate_legend=-1,\n    tooltip_border_radius=8,\n    print_values=False,\n    print_labels=False,\n    legend_box_size=20,\n)\n\n# Y-axis labels showing quantum numbers and actual energy values\nchart.y_labels = [\n    {\"label\": \"n=1:  −13.60 eV\", \"value\": visual_y[1]},\n    {\"label\": \"n=2:  −3.40 eV\", \"value\": visual_y[2]},\n    {\"label\": \"n=3:  −1.51 eV\", \"value\": visual_y[3]},\n    {\"label\": \"n=4:  −0.85 eV\", \"value\": visual_y[4]},\n    {\"label\": \"n=5:  −0.54 eV\", \"value\": visual_y[5]},\n    {\"label\": \"n=6:  −0.38 eV\", \"value\": visual_y[6]},\n    {\"label\": \"Ionization:  0.00 eV\", \"value\": ionization_y},\n]\n\n# Energy level horizontal lines (hidden from legend, no dots)\nfor n in range(1, 7):\n    chart.add(\n        None,\n        [\n            {\"value\": (level_x_start, visual_y[n]), \"node\": {\"r\": 0}},\n            {\"value\": (level_x_end, visual_y[n]), \"node\": {\"r\": 0}},\n        ],\n        stroke_style={\"width\": 2},\n    )\n\n# Ionization limit (dashed reference line)\nchart.add(\n    \"Ionization (0 eV)\",\n    [\n        {\"value\": (level_x_start - 0.3, ionization_y), \"node\": {\"r\": 0}},\n        {\"value\": (level_x_end + 0.3, ionization_y), \"node\": {\"r\": 0}},\n    ],\n    stroke_style={\"width\": 3, \"dasharray\": \"18, 10\"},\n)\n\n# Lyman series (UV transitions to n=1) — emission downward: large dot at destination (n=1), small at origin\nlyman_widths = [9, 8, 7]\nlyman_lower_nodes = [22, 20, 18]  # destination (n=1, lower energy) — large\nlyman_upper_nodes = [5, 5, 5]  # origin (upper level) — small\nfor i, (upper, lower, label) in enumerate(lyman_transitions):\n    x = lyman_x_positions[i]\n    chart.add(\n        label,\n        [\n            {\"value\": (x, visual_y[upper]), \"node\": {\"r\": lyman_upper_nodes[i]}},\n            {\"value\": (x, visual_y[lower]), \"node\": {\"r\": lyman_lower_nodes[i]}},\n        ],\n        stroke_style={\"width\": lyman_widths[i]},\n    )\n\n# Balmer series (visible transitions to n=2) — emission downward: large dot at destination (n=2), small at origin\n# Hα is focal point: brand green, widest stroke, largest destination dot\nbalmer_widths = [11, 9, 7, 6]\nbalmer_lower_nodes = [28, 22, 18, 15]  # destination (n=2) — large; Hα biggest\nbalmer_upper_nodes = [5, 5, 5, 5]  # origin (upper level) — small\nfor i, (upper, lower, label) in enumerate(balmer_transitions):\n    x = balmer_x_positions[i]\n    chart.add(\n        label,\n        [\n            {\"value\": (x, visual_y[upper]), \"node\": {\"r\": balmer_upper_nodes[i]}},\n            {\"value\": (x, visual_y[lower]), \"node\": {\"r\": balmer_lower_nodes[i]}},\n        ],\n        stroke_style={\"width\": balmer_widths[i]},\n    )\n\n# Paschen series (IR transitions to n=3) — emission downward: large dot at destination (n=3), small at origin\npaschen_widths = [9, 7, 6]\npaschen_lower_nodes = [22, 18, 15]  # destination (n=3) — large\npaschen_upper_nodes = [5, 5, 5]  # origin (upper level) — small\nfor i, (upper, lower, label) in enumerate(paschen_transitions):\n    x = paschen_x_positions[i]\n    chart.add(\n        label,\n        [\n            {\"value\": (x, visual_y[upper]), \"node\": {\"r\": paschen_upper_nodes[i]}},\n            {\"value\": (x, visual_y[lower]), \"node\": {\"r\": paschen_lower_nodes[i]}},\n        ],\n        stroke_style={\"width\": paschen_widths[i]},\n    )\n\n# Save\nchart.render_to_png(f\"plot-{THEME}.png\")\nwith open(f\"plot-{THEME}.html\", \"wb\") as f:\n    f.write(chart.render())\n"}