{"spec_id":"line-arrhenius","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nline-arrhenius: Arrhenius Plot for Reaction Kinetics\nLibrary: seaborn 0.13.2 | Python 3.13.14\nQuality: 92/100 | Updated: 2026-06-24\n\"\"\"\n\nimport os\nimport sys\n\n\n# Remove the script's own directory from sys.path so sibling files (e.g. matplotlib.py)\n# do not shadow installed packages when running from the implementations directory.\n_here = os.path.dirname(os.path.abspath(__file__))\nsys.path = [p for p in sys.path if os.path.abspath(p) != _here]\ndel _here\n\nimport matplotlib.pyplot as plt\nimport matplotlib.ticker as ticker\nimport numpy as np\nimport seaborn as sns\nfrom scipy import stats\n\n\n# Theme-adaptive chrome tokens (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 series always #009E73 (brand green)\nBRAND = \"#009E73\"\n\n# Data — enzyme-catalyzed hydrolysis (alkaline phosphatase) across physiological temperatures\n# Domain: enzyme kinetics, Ea ~58 kJ/mol (lower than thermal decomposition, typical for enzymes)\ntemperature_K = np.array([278, 283, 288, 293, 298, 303, 308, 313, 320, 330])\nR = 8.314  # gas constant (J/mol·K)\nEa_true = 58000  # activation energy (J/mol)\nA = 1.2e9  # pre-exponential factor (s⁻¹)\n\nnp.random.seed(7)\nnoise = np.random.normal(0, 0.28, len(temperature_K))\nrate_constant_k = A * np.exp(-Ea_true / (R * temperature_K)) * np.exp(noise)\nrate_constant_k[7] *= 2.0  # one elevated outlier at 313 K — demonstrates regression robustness\n\ninv_T = 1.0 / temperature_K\nln_k = np.log(rate_constant_k)\n\n# Linear regression for annotation\nslope, intercept, r_value, p_value, std_err = stats.linregress(inv_T, ln_k)\nr_squared = r_value**2\nEa_extracted = -slope * R\n\n# Seaborn theme setup with full theme-adaptive chrome\nsns.set_theme(\n    style=\"ticks\",\n    rc={\n        \"figure.facecolor\": PAGE_BG,\n        \"axes.facecolor\": PAGE_BG,\n        \"axes.edgecolor\": INK_SOFT,\n        \"axes.labelcolor\": INK,\n        \"text.color\": INK,\n        \"xtick.color\": INK_SOFT,\n        \"ytick.color\": INK_SOFT,\n        \"grid.color\": INK,\n        \"grid.alpha\": 0.15,\n        \"legend.facecolor\": ELEVATED_BG,\n        \"legend.edgecolor\": INK_SOFT,\n        \"font.family\": \"sans-serif\",\n        \"axes.spines.top\": False,\n        \"axes.spines.right\": False,\n    },\n)\n\n# Canvas: landscape 3200×1800 — figsize=(8, 4.5) × dpi=400\nfig, ax = plt.subplots(figsize=(8, 4.5), dpi=400)\nfig.patch.set_facecolor(PAGE_BG)\n\n# Main plot — sns.regplot with 95% CI band is idiomatic seaborn for regression + scatter\nsns.regplot(\n    x=inv_T,\n    y=ln_k,\n    ci=95,\n    scatter_kws={\"s\": 170, \"color\": BRAND, \"edgecolor\": \"white\", \"linewidths\": 1.5, \"zorder\": 5},\n    line_kws={\"color\": BRAND, \"linewidth\": 2.5, \"alpha\": 0.9},\n    ax=ax,\n)\n\n# Fix CI band visibility in dark theme — regplot draws the band as a PolyCollection\n# with low default alpha; raise it in dark mode so it reads against #1A1A17\nfor coll in ax.collections:\n    coll.set_facecolor(BRAND)\n    coll.set_alpha(0.38 if THEME == \"dark\" else 0.18)\n\n# Outlier annotation — raised to 8pt (above mobile-readable minimum)\nax.annotate(\n    \"outlier\",\n    xy=(inv_T[7], ln_k[7]),\n    xytext=(6, 10),\n    textcoords=\"offset points\",\n    fontsize=8,\n    color=INK_MUTED,\n    arrowprops={\"arrowstyle\": \"-\", \"color\": INK_MUTED, \"lw\": 0.8},\n)\n\n# Annotation box with extracted kinetic parameters\nannotation_text = f\"$R^2$ = {r_squared:.4f}\\nSlope = {slope:.0f} K\\n$E_a$ = {Ea_extracted / 1000:.1f} kJ/mol\"\nax.text(\n    0.03,\n    0.38,\n    annotation_text,\n    transform=ax.transAxes,\n    fontsize=8,\n    verticalalignment=\"top\",\n    horizontalalignment=\"left\",\n    color=INK,\n    bbox={\"boxstyle\": \"round,pad=0.6\", \"facecolor\": ELEVATED_BG, \"edgecolor\": BRAND, \"alpha\": 0.95, \"linewidth\": 1.5},\n)\n\n# Secondary x-axis — temperature in Kelvin for chemical context\nax_top = ax.twiny()\nax_top.set_xlim(ax.get_xlim())\ntemp_ticks_K = np.array([278, 293, 303, 313, 330])\nax_top.set_xticks(1.0 / temp_ticks_K)\nax_top.set_xticklabels([f\"{t} K\" for t in temp_ticks_K], fontsize=8)\nax_top.set_xlabel(\"Temperature (K)\", fontsize=9, labelpad=8, color=INK)\n# Tick-less secondary axis: labels only, no tick marks — cleaner composition\nax_top.tick_params(axis=\"x\", labelsize=8, colors=INK_SOFT, length=0)\nax_top.spines[\"top\"].set_color(INK_SOFT)\nax_top.spines[\"right\"].set_visible(False)\n\n# Bottom axis styling\nax.set_xlabel(\"1/T (K⁻¹)\", fontsize=10, color=INK)\nax.set_ylabel(\"ln(k)\", fontsize=10, color=INK)\nax.set_title(\"line-arrhenius · python · seaborn · anyplot.ai\", fontsize=12, fontweight=\"medium\", color=INK)\nax.tick_params(axis=\"both\", labelsize=8, colors=INK_SOFT)\nax.yaxis.grid(True, alpha=0.15, linewidth=0.8, color=INK)\nax.xaxis.grid(True, alpha=0.08, linewidth=0.6, color=INK)\nax.xaxis.set_major_formatter(ticker.FormatStrFormatter(\"%.4f\"))\n\n# Explicit spine cleanup (belt-and-suspenders alongside rc — seaborn despine idiom)\nsns.despine(ax=ax, top=True, right=True)\n\nfig.subplots_adjust(top=0.78, bottom=0.15, left=0.10, right=0.97)\n_out = os.path.join(os.path.dirname(os.path.abspath(__file__)), f\"plot-{THEME}.png\")\nplt.savefig(_out, dpi=400, facecolor=PAGE_BG)\nplt.close(fig)\n"}