{"spec_id":"line-reaction-coordinate","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\nline-reaction-coordinate: Reaction Coordinate Energy Diagram\nLibrary: plotnine 0.15.7 | Python 3.13.14\nQuality: 87/100 | Updated: 2026-06-24\n\"\"\"\n\n# ruff: noqa: E402\n\"\"\"anyplot.ai — line-reaction-coordinate: Reaction Coordinate Energy Diagram\nLibrary: plotnine | Python\n\"\"\"\n\nimport os\nimport sys\n\n\n_here = os.path.dirname(os.path.abspath(__file__))\nsys.path = [p for p in sys.path if os.path.abspath(p or \".\") != _here]\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    annotate,\n    arrow,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    geom_line,\n    geom_point,\n    geom_segment,\n    ggplot,\n    labs,\n    scale_x_continuous,\n    scale_y_continuous,\n    theme,\n    theme_minimal,\n)\nfrom scipy.interpolate import CubicSpline\n\n\n# Theme-adaptive chrome tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\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 (hybrid-v3, 8 hues)\nIMPRINT_PALETTE = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\", \"#99B314\"]\n\n# Data — single-step exothermic reaction\nreactant_energy = 50.0\ntransition_energy = 120.0\nproduct_energy = 20.0\n\ncontrol_x = np.array([0.0, 0.10, 0.20, 0.35, 0.50, 0.65, 0.80, 0.90, 1.0])\ncontrol_y = np.array([50.0, 50.0, 55.0, 90.0, 120.0, 85.0, 30.0, 20.0, 20.0])\n\ncs = CubicSpline(control_x, control_y)\nreaction_coord = np.linspace(0, 1, 300)\nenergy = cs(reaction_coord)\n\ncurve_df = pd.DataFrame({\"reaction_coord\": reaction_coord, \"energy\": energy})\nkey_points = pd.DataFrame(\n    {\"reaction_coord\": [0.0, 0.50, 1.0], \"energy\": [reactant_energy, transition_energy, product_energy]}\n)\n\n# Arrow positions — balanced within data range\nea_x = 0.08  # Ea arrow, left side\ndh_x = 0.82  # ΔH arrow, right side (room for label before edge)\n\n# Annotation colors from Imprint palette (semantic roles)\nea_color = IMPRINT_PALETTE[4]  # #AE3030 matte red — activation barrier (semantic: cost/warning)\ndh_color = IMPRINT_PALETTE[2]  # #4467A3 blue — enthalpy change\n\n# Horizontal dashed reference lines at reactant and product energy levels\nhline_df = pd.DataFrame(\n    {\n        \"x\": [0.0, 0.73],\n        \"xend\": [0.84, 0.84],\n        \"y\": [reactant_energy, product_energy],\n        \"yend\": [reactant_energy, product_energy],\n    }\n)\n\narrow_head = arrow(length=0.12, type=\"closed\")\n\nplot = (\n    ggplot(curve_df, aes(x=\"reaction_coord\", y=\"energy\"))\n    # Dashed reference lines at reactant and product energy levels\n    + geom_segment(\n        hline_df,\n        aes(x=\"x\", y=\"y\", xend=\"xend\", yend=\"yend\"),\n        linetype=\"dashed\",\n        color=INK_MUTED,\n        size=0.4,\n        inherit_aes=False,\n    )\n    # Main energy curve — Imprint brand green (#009E73), first categorical series\n    + geom_line(color=IMPRINT_PALETTE[0], size=1.5)\n    # Key-point markers at reactant, transition state, product\n    + geom_point(\n        key_points,\n        aes(x=\"reaction_coord\", y=\"energy\"),\n        color=IMPRINT_PALETTE[0],\n        fill=IMPRINT_PALETTE[0],\n        size=3,\n        inherit_aes=False,\n    )\n    # Ea double-headed arrow (reactant level ↔ transition state)\n    + annotate(\n        \"segment\",\n        x=ea_x,\n        xend=ea_x,\n        y=reactant_energy + 3,\n        yend=transition_energy - 3,\n        color=ea_color,\n        size=0.8,\n        arrow=arrow_head,\n    )\n    + annotate(\n        \"segment\",\n        x=ea_x,\n        xend=ea_x,\n        y=transition_energy - 3,\n        yend=reactant_energy + 3,\n        color=ea_color,\n        size=0.8,\n        arrow=arrow_head,\n    )\n    + annotate(\n        \"text\",\n        x=ea_x + 0.04,\n        y=(reactant_energy + transition_energy) / 2,\n        label=\"Eₐ = 70 kJ/mol\",\n        size=3.5,\n        color=ea_color,\n        ha=\"left\",\n        fontweight=\"bold\",\n    )\n    # ΔH double-headed arrow (reactant level ↔ product level)\n    + annotate(\n        \"segment\",\n        x=dh_x,\n        xend=dh_x,\n        y=reactant_energy - 2,\n        yend=product_energy + 2,\n        color=dh_color,\n        size=0.8,\n        arrow=arrow_head,\n    )\n    + annotate(\n        \"segment\",\n        x=dh_x,\n        xend=dh_x,\n        y=product_energy + 2,\n        yend=reactant_energy - 2,\n        color=dh_color,\n        size=0.8,\n        arrow=arrow_head,\n    )\n    + annotate(\n        \"text\",\n        x=dh_x + 0.03,\n        y=(reactant_energy + product_energy) / 2,\n        label=\"ΔH = −30\\nkJ/mol\",\n        size=3.5,\n        color=dh_color,\n        ha=\"left\",\n        fontweight=\"bold\",\n    )\n    # State labels\n    + annotate(\n        \"text\",\n        x=0.02,\n        y=reactant_energy + 7,\n        label=\"Reactants\\n50 kJ/mol\",\n        size=3.5,\n        color=INK,\n        ha=\"left\",\n        va=\"bottom\",\n        fontweight=\"bold\",\n    )\n    + annotate(\n        \"text\",\n        x=0.50,\n        y=transition_energy + 6,\n        label=\"Transition State\\n120 kJ/mol\",\n        size=3.5,\n        color=INK,\n        ha=\"center\",\n        va=\"bottom\",\n        fontweight=\"bold\",\n    )\n    + annotate(\n        \"text\",\n        x=0.93,\n        y=product_energy - 5,\n        label=\"Products\\n20 kJ/mol\",\n        size=3.5,\n        color=INK,\n        ha=\"right\",\n        va=\"top\",\n        fontweight=\"bold\",\n    )\n    + labs(\n        title=\"line-reaction-coordinate · python · plotnine · anyplot.ai\",\n        x=\"Reaction Coordinate\",\n        y=\"Potential Energy (kJ/mol)\",\n    )\n    + scale_x_continuous(breaks=[0, 0.25, 0.5, 0.75, 1.0], labels=[\"0\", \"\", \"0.5\", \"\", \"1.0\"], expand=(0.02, 0.08))\n    + scale_y_continuous(limits=[0, 145], expand=(0.02, 0.02))\n    + theme_minimal()\n    + theme(\n        figure_size=(8, 4.5),\n        plot_title=element_text(size=12, ha=\"center\", weight=\"bold\", color=INK, margin={\"b\": 10}),\n        axis_title_x=element_text(size=10, color=INK_SOFT, margin={\"t\": 8}),\n        axis_title_y=element_text(size=10, color=INK_SOFT, margin={\"r\": 8}),\n        axis_text=element_text(size=8, color=INK_SOFT),\n        axis_line=element_line(color=INK_SOFT, size=0.4),\n        panel_grid_major_x=element_blank(),\n        panel_grid_minor=element_blank(),\n        panel_grid_major_y=element_line(color=INK, size=0.3, alpha=0.15),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG),\n        axis_ticks=element_blank(),\n        plot_margin=0.04,\n    )\n)\n\nplot.save(f\"plot-{THEME}.png\", dpi=400, width=8, height=4.5, units=\"in\", verbose=False)\n"}