{"spec_id":"spectrum-nmr","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\nspectrum-nmr: NMR Spectrum (Nuclear Magnetic Resonance)\nLibrary: matplotlib 3.10.9 | Python 3.13.13\nQuality: 91/100 | Updated: 2026-06-03\n\"\"\"\n\nimport os\n\nimport matplotlib.patheffects as pe\nimport matplotlib.pyplot as plt\nimport matplotlib.ticker as mticker\nimport numpy as np\n\n\n# Theme-adaptive chrome (Imprint palette)\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 — first categorical series always brand green\nBRAND = \"#009E73\"\n\n# Data: synthetic 1H NMR spectrum of ethanol (CH3CH2OH)\nnp.random.seed(42)\nppm = np.linspace(-0.5, 5.0, 6000)\nspectrum = np.zeros_like(ppm)\n\nw = 0.025  # Lorentzian half-width\nj = 0.078  # J-coupling constant — wider than minimal so multiplet splitting is visually striking\n\n# Lorentzian peaks: A / (1 + ((x - x0) / w)^2)\n# TMS reference singlet at 0.00 ppm\nspectrum += 0.30 / (1 + ((ppm - 0.00) / 0.015) ** 2)\n\n# CH3 triplet ~1.18 ppm  (1 : 2 : 1 ratio)\nspectrum += 0.50 / (1 + ((ppm - (1.18 - j)) / w) ** 2)\nspectrum += 1.00 / (1 + ((ppm - 1.18) / w) ** 2)\nspectrum += 0.50 / (1 + ((ppm - (1.18 + j)) / w) ** 2)\n\n# CH2 quartet ~3.69 ppm  (1 : 3 : 3 : 1 ratio)\nspectrum += 0.25 / (1 + ((ppm - (3.69 - 1.5 * j)) / w) ** 2)\nspectrum += 0.75 / (1 + ((ppm - (3.69 - 0.5 * j)) / w) ** 2)\nspectrum += 0.75 / (1 + ((ppm - (3.69 + 0.5 * j)) / w) ** 2)\nspectrum += 0.25 / (1 + ((ppm - (3.69 + 1.5 * j)) / w) ** 2)\n\n# OH singlet ~2.61 ppm\nspectrum += 0.40 / (1 + ((ppm - 2.61) / w) ** 2)\n\n# Subtle baseline noise\nspectrum += np.random.normal(0, 0.003, len(ppm))\nspectrum = np.clip(spectrum, 0, None)\n\n# Canvas — landscape 3200 × 1800 px (16:9)\nfig, ax = plt.subplots(figsize=(8, 4.5), dpi=400, facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\n# Spectrum trace + area fill\nax.plot(ppm, spectrum, linewidth=2.5, color=BRAND, zorder=3)\nax.fill_between(ppm, spectrum, alpha=0.12, color=BRAND, zorder=2)\n\n# Subtle peak-region highlight bands\nfor lo, hi in [(-0.15, 0.15), (1.00, 1.42), (2.45, 2.75), (3.50, 3.92)]:\n    ax.axvspan(lo, hi, alpha=0.06, color=BRAND, zorder=1)\n\n# Peak annotations with theme-matched path-effect outline\ntext_outline = [pe.withStroke(linewidth=3, foreground=ELEVATED_BG)]\nannotations = [\n    (0.00, \"TMS\\n0.00 ppm\", (42, 28)),\n    (1.18, \"CH₃ (triplet)\\n1.18 ppm\", (82, -48)),\n    (2.61, \"OH (singlet)\\n2.61 ppm\", (-55, 34)),\n    (3.69, \"CH₂ (quartet)\\n3.69 ppm\", (-60, 38)),\n]\nfor peak_ppm, label, offset in annotations:\n    peak_idx = np.argmin(np.abs(ppm - peak_ppm))\n    ax.annotate(\n        label,\n        xy=(peak_ppm, spectrum[peak_idx]),\n        xytext=offset,\n        textcoords=\"offset points\",\n        fontsize=9,\n        fontweight=\"semibold\",\n        ha=\"center\",\n        va=\"bottom\",\n        arrowprops={\"arrowstyle\": \"-|>\", \"color\": INK_MUTED, \"lw\": 1.5, \"mutation_scale\": 12},\n        color=INK,\n        path_effects=text_outline,\n        zorder=5,\n    )\n\n# Integration bars — prominent thick lines below baseline\nbar_y = -0.07\nfor center, ratio, rlabel in [(1.18, 3, \"3H\"), (2.61, 1, \"1H\"), (3.69, 2, \"2H\")]:\n    hw = 0.28 * ratio / 3\n    ax.plot(\n        [center - hw, center + hw],\n        [bar_y, bar_y],\n        linewidth=7,\n        color=BRAND,\n        alpha=0.75,\n        solid_capstyle=\"round\",\n        zorder=4,\n    )\n    ax.text(\n        center,\n        bar_y - 0.028,\n        rlabel,\n        ha=\"center\",\n        va=\"top\",\n        fontsize=8,\n        color=BRAND,\n        fontweight=\"bold\",\n        path_effects=text_outline,\n    )\n\n# Minor x-axis ticks at 0.2 ppm intervals (standard NMR scale)\nax.xaxis.set_major_locator(mticker.MultipleLocator(1.0))\nax.xaxis.set_minor_locator(mticker.MultipleLocator(0.2))\nax.tick_params(axis=\"x\", which=\"minor\", length=3, width=0.8, color=INK_SOFT)\nax.tick_params(axis=\"x\", which=\"major\", length=6, width=1.2)\nax.tick_params(axis=\"both\", labelsize=8, colors=INK_SOFT, labelcolor=INK_SOFT)\n\n# Title — length-aware fontsize scaling\ntitle = \"Ethanol ¹H NMR · spectrum-nmr · matplotlib · anyplot.ai\"\ntitle_fs = max(8, round(12 * 67 / len(title))) if len(title) > 67 else 12\n\nax.set_title(title, fontsize=title_fs, fontweight=\"medium\", pad=14, color=INK)\nax.set_xlabel(\"Chemical Shift (ppm)\", fontsize=10, labelpad=10, color=INK)\nax.set_ylabel(\"Intensity\", fontsize=10, color=INK)\n\n# NMR conventions: reversed x-axis, no y-ticks\nax.set_xlim(5.0, -0.5)\nax.set_ylim(-0.12, 1.30)\nax.set_yticks([])\n\n# Spine styling — remove top, right, left (NMR convention); keep bottom\nax.spines[\"top\"].set_visible(False)\nax.spines[\"right\"].set_visible(False)\nax.spines[\"left\"].set_visible(False)\nax.spines[\"bottom\"].set_color(INK_SOFT)\n\n# Molecule formula watermark\nax.text(\n    0.98,\n    0.95,\n    \"CH₃CH₂OH\",\n    transform=ax.transAxes,\n    fontsize=11,\n    fontweight=\"bold\",\n    ha=\"right\",\n    va=\"top\",\n    color=BRAND,\n    alpha=0.30,\n    fontstyle=\"italic\",\n)\n\nfig.subplots_adjust(left=0.06, right=0.97, top=0.91, bottom=0.15)\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\n"}