{"spec_id":"line-reaction-coordinate","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nline-reaction-coordinate: Reaction Coordinate Energy Diagram\nLibrary: plotly 6.8.0 | Python 3.13.14\nQuality: 93/100 | Updated: 2026-06-24\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport plotly.graph_objects as go\n\n\n# Theme tokens — Imprint palette (see prompts/default-style-guide.md)\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\"\nGRID = \"rgba(26,26,23,0.15)\" if THEME == \"light\" else \"rgba(240,239,232,0.15)\"\n\n# Imprint palette — curve + scientific annotation colors\nBRAND = \"#009E73\"  # brand green — main reaction curve (Imprint position 1)\nEA_COLOR = \"#4467A3\"  # blue — activation energy (Imprint position 3, kinetic)\nDH_COLOR = \"#BD8233\"  # ochre — enthalpy change (Imprint position 4, thermodynamic)\nFILL_COLOR = \"rgba(0,158,115,0.10)\" if THEME == \"light\" else \"rgba(0,158,115,0.15)\"\n\n# Data — single-step exothermic reaction\nreactant_energy = 50.0\ntransition_energy = 120.0\nproduct_energy = 20.0\npeak_pos = 0.4\n\nreaction_coord = np.linspace(0, 1, 500)\n\nbaseline = reactant_energy + (product_energy - reactant_energy) * (3 * reaction_coord**2 - 2 * reaction_coord**3)\n\nbarrier_height = transition_energy - (\n    reactant_energy + (product_energy - reactant_energy) * (3 * peak_pos**2 - 2 * peak_pos**3)\n)\ngaussian_bump = barrier_height * np.exp(-((reaction_coord - peak_pos) ** 2) / (2 * 0.018))\n\nenergy = baseline + gaussian_bump\npeak_idx = int(np.argmax(energy))\n\n# Plot\nfig = go.Figure()\n\n# Filled area under curve with brand green tint\nfig.add_trace(\n    go.Scatter(\n        x=reaction_coord,\n        y=energy,\n        mode=\"lines\",\n        line={\"color\": \"rgba(0,0,0,0)\", \"width\": 0},\n        fill=\"tozeroy\",\n        fillcolor=FILL_COLOR,\n        showlegend=False,\n        hoverinfo=\"skip\",\n    )\n)\n\n# Main reaction energy curve\nfig.add_trace(\n    go.Scatter(\n        x=reaction_coord,\n        y=energy,\n        mode=\"lines\",\n        line={\"color\": BRAND, \"width\": 4, \"shape\": \"spline\"},\n        showlegend=False,\n        hovertemplate=\"Reaction Coordinate: %{x:.2f}<br>Energy: %{y:.1f} kJ/mol<extra></extra>\",\n    )\n)\n\n# Transition state peak marker dot\nfig.add_trace(\n    go.Scatter(\n        x=[reaction_coord[peak_idx]],\n        y=[energy[peak_idx]],\n        mode=\"markers\",\n        marker={\"color\": BRAND, \"size\": 12, \"symbol\": \"circle\", \"line\": {\"color\": PAGE_BG, \"width\": 2}},\n        showlegend=False,\n        hoverinfo=\"skip\",\n    )\n)\n\n# Horizontal dashed lines at reactant and product energy levels\nfor x0, x1, y_level in [(-0.05, 0.28, reactant_energy), (0.72, 1.05, product_energy)]:\n    fig.add_shape(\n        type=\"line\", x0=x0, x1=x1, y0=y_level, y1=y_level, line={\"color\": INK_SOFT, \"width\": 1.5, \"dash\": \"dash\"}\n    )\n\n# Reference dashed line at reactant level on ΔH side\nfig.add_shape(\n    type=\"line\",\n    x0=0.82,\n    x1=0.94,\n    y0=reactant_energy,\n    y1=reactant_energy,\n    line={\"color\": INK_SOFT, \"width\": 1, \"dash\": \"dot\"},\n)\n\n# Reference dashed line at transition state level for Ea\nea_x = 0.14\nfig.add_shape(\n    type=\"line\",\n    x0=ea_x - 0.02,\n    x1=peak_pos + 0.08,\n    y0=transition_energy,\n    y1=transition_energy,\n    line={\"color\": INK_SOFT, \"width\": 1, \"dash\": \"dot\"},\n)\n\n# Activation energy (Ea) double-headed arrow\nfig.add_shape(\n    type=\"line\", x0=ea_x, y0=reactant_energy, x1=ea_x, y1=transition_energy, line={\"color\": EA_COLOR, \"width\": 2.5}\n)\nfig.add_annotation(\n    x=ea_x,\n    y=transition_energy,\n    ax=0,\n    ay=-14,\n    text=\"\",\n    showarrow=True,\n    arrowhead=2,\n    arrowsize=1.5,\n    arrowwidth=2.5,\n    arrowcolor=EA_COLOR,\n)\nfig.add_annotation(\n    x=ea_x,\n    y=reactant_energy,\n    ax=0,\n    ay=14,\n    text=\"\",\n    showarrow=True,\n    arrowhead=2,\n    arrowsize=1.5,\n    arrowwidth=2.5,\n    arrowcolor=EA_COLOR,\n)\nfig.add_annotation(\n    x=ea_x,\n    y=(reactant_energy + transition_energy) / 2,\n    text=\"<b>E<sub>a</sub> = 70 kJ/mol</b>\",\n    showarrow=False,\n    xanchor=\"right\",\n    xshift=-14,\n    font={\"size\": 12, \"color\": EA_COLOR, \"family\": \"Arial, sans-serif\"},\n)\n\n# Enthalpy change (ΔH) double-headed arrow\ndh_x = 0.88\nfig.add_shape(\n    type=\"line\", x0=dh_x, y0=product_energy, x1=dh_x, y1=reactant_energy, line={\"color\": DH_COLOR, \"width\": 2.5}\n)\nfig.add_annotation(\n    x=dh_x,\n    y=reactant_energy,\n    ax=0,\n    ay=-14,\n    text=\"\",\n    showarrow=True,\n    arrowhead=2,\n    arrowsize=1.5,\n    arrowwidth=2.5,\n    arrowcolor=DH_COLOR,\n)\nfig.add_annotation(\n    x=dh_x,\n    y=product_energy,\n    ax=0,\n    ay=14,\n    text=\"\",\n    showarrow=True,\n    arrowhead=2,\n    arrowsize=1.5,\n    arrowwidth=2.5,\n    arrowcolor=DH_COLOR,\n)\nfig.add_annotation(\n    x=dh_x,\n    y=(reactant_energy + product_energy) / 2,\n    text=\"<b>ΔH = −30 kJ/mol</b>\",\n    showarrow=False,\n    xanchor=\"left\",\n    xshift=14,\n    font={\"size\": 12, \"color\": DH_COLOR, \"family\": \"Arial, sans-serif\"},\n)\n\n# Labels — Reactants, Transition State, Products\nfig.add_annotation(\n    x=0.02,\n    y=reactant_energy,\n    text=\"<b>Reactants</b><br>50 kJ/mol\",\n    showarrow=False,\n    yshift=34,\n    xanchor=\"left\",\n    font={\"size\": 12, \"color\": INK, \"family\": \"Arial, sans-serif\"},\n)\n\nfig.add_annotation(\n    x=reaction_coord[peak_idx],\n    y=energy[peak_idx],\n    text=\"<b>Transition State</b><br>120 kJ/mol\",\n    showarrow=True,\n    ay=-55,\n    ax=45,\n    arrowhead=2,\n    arrowsize=1,\n    arrowwidth=1.5,\n    arrowcolor=INK_SOFT,\n    font={\"size\": 12, \"color\": INK, \"family\": \"Arial, sans-serif\"},\n)\n\nfig.add_annotation(\n    x=0.98,\n    y=product_energy,\n    text=\"<b>Products</b><br>20 kJ/mol\",\n    showarrow=False,\n    yshift=-32,\n    xanchor=\"right\",\n    font={\"size\": 12, \"color\": INK, \"family\": \"Arial, sans-serif\"},\n)\n\n# Title — length 55 chars < 67 baseline, no scaling needed\ntitle = \"line-reaction-coordinate · python · plotly · anyplot.ai\"\ntitle_len = len(title)\ntitle_fontsize = round(16 * (67 / title_len)) if title_len > 67 else 16\n\n# Style\nfig.update_layout(\n    autosize=False,\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    font={\"family\": \"Arial, sans-serif\", \"color\": INK},\n    title={\n        \"text\": title,\n        \"font\": {\"size\": title_fontsize, \"family\": \"Arial, sans-serif\", \"color\": INK},\n        \"x\": 0.5,\n        \"xanchor\": \"center\",\n    },\n    xaxis={\n        \"title\": {\n            \"text\": \"Reaction Coordinate\",\n            \"font\": {\"size\": 12, \"family\": \"Arial, sans-serif\", \"color\": INK},\n            \"standoff\": 15,\n        },\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"showgrid\": False,\n        \"showticklabels\": False,\n        \"zeroline\": False,\n        \"range\": [-0.08, 1.08],\n        \"showline\": True,\n        \"linecolor\": INK_SOFT,\n        \"linewidth\": 1,\n    },\n    yaxis={\n        \"title\": {\n            \"text\": \"Potential Energy (kJ/mol)\",\n            \"font\": {\"size\": 12, \"family\": \"Arial, sans-serif\", \"color\": INK},\n            \"standoff\": 10,\n        },\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"gridcolor\": GRID,\n        \"gridwidth\": 1,\n        \"zeroline\": False,\n        \"range\": [0, 140],\n        \"showline\": True,\n        \"linecolor\": INK_SOFT,\n        \"linewidth\": 1,\n        \"dtick\": 20,\n    },\n    margin={\"l\": 85, \"r\": 40, \"t\": 80, \"b\": 65},\n)\n\n# Save\nfig.write_image(f\"plot-{THEME}.png\", width=800, height=450, scale=4)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}