{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "70669caa",
   "metadata": {},
   "source": [
    "**WARNING: this was LLM-generated and has not been fully reviewed yet.**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a1",
   "metadata": {},
   "source": [
    "# Quickstart\n",
    "\n",
    "This notebook walks through the basics of computing equilibrium\n",
    "concentrations with **equiconc**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a2",
   "metadata": {},
   "outputs": [],
   "source": [
    "import equiconc\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a3",
   "metadata": {},
   "source": [
    "## Simple dimerization\n",
    "\n",
    "Consider two strands **A** and **B** at 100 nM each that can form a\n",
    "heterodimer **AB** with $\\Delta G^\\circ = -10$ kcal/mol at 25 &deg;C."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a4",
   "metadata": {},
   "outputs": [],
   "source": "eq = (\n    equiconc.System()\n    .monomer(\"A\", 100e-9)\n    .monomer(\"B\", 100e-9)\n    .complex(\"AB\", [(\"A\", 1), (\"B\", 1)], dg_st=-10.0)\n    .equilibrium()\n)\n\nfor name, conc in eq.items():\n    print(f\"{name:>3s}: {conc:.3e} M\")"
  },
  {
   "cell_type": "markdown",
   "id": "a5",
   "metadata": {},
   "source": [
    "## Exploring the result\n",
    "\n",
    "The `Equilibrium` object supports dict-like access, iteration, and\n",
    "several convenience properties."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "a6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[AB] = 5.111e-08 M\n",
      "'AB' in eq: True\n",
      "'XY' in eq: False\n",
      "eq.concentration('AB') = 5.111e-08\n"
     ]
    }
   ],
   "source": [
    "# Bracket access\n",
    "print(f\"[AB] = {eq['AB']:.3e} M\")\n",
    "\n",
    "# Membership test\n",
    "print(f\"'AB' in eq: {'AB' in eq}\")\n",
    "print(f\"'XY' in eq: {'XY' in eq}\")\n",
    "\n",
    "# Named lookup\n",
    "print(f\"eq.concentration('AB') = {eq.concentration('AB'):.3e}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "a7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Monomer names: ['A', 'B']\n",
      "Complex names: ['AB']\n",
      "Converged fully: True\n"
     ]
    }
   ],
   "source": [
    "# Properties\n",
    "print(\"Monomer names:\", eq.monomer_names)\n",
    "print(\"Complex names:\", eq.complex_names)\n",
    "print(\"Converged fully:\", eq.converged_fully)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a8",
   "metadata": {},
   "source": [
    "## Mass conservation check\n",
    "\n",
    "The total concentration of each monomer is conserved:\n",
    "$[\\text{A}]_\\text{free} + [\\text{AB}] = [\\text{A}]_\\text{total}$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "a9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total [A] = 1.000e-07 M  (expected 1.000e-07 M)\n",
      "Total [B] = 1.000e-07 M  (expected 1.000e-07 M)\n"
     ]
    }
   ],
   "source": [
    "total_A = eq[\"A\"] + eq[\"AB\"]\n",
    "print(f\"Total [A] = {total_A:.3e} M  (expected 1.000e-07 M)\")\n",
    "\n",
    "total_B = eq[\"B\"] + eq[\"AB\"]\n",
    "print(f\"Total [B] = {total_B:.3e} M  (expected 1.000e-07 M)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a10",
   "metadata": {},
   "source": [
    "## Multi-complex system\n",
    "\n",
    "Now consider a system where strand **A** can bind **B** or **C**,\n",
    "forming heterodimers **AB** and **AC** with different affinities."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a11",
   "metadata": {},
   "outputs": [],
   "source": "eq2 = (\n    equiconc.System()\n    .monomer(\"A\", 1e-6)\n    .monomer(\"B\", 1e-6)\n    .monomer(\"C\", 1e-6)\n    .complex(\"AB\", [(\"A\", 1), (\"B\", 1)], dg_st=-12.0)\n    .complex(\"AC\", [(\"A\", 1), (\"C\", 1)], dg_st=-8.0)\n    .equilibrium()\n)\n\nfor name, conc in eq2.items():\n    print(f\"{name:>3s}: {conc:.3e} M\")"
  },
  {
   "cell_type": "markdown",
   "id": "a12",
   "metadata": {},
   "source": [
    "## Visualizing concentrations\n",
    "\n",
    "A simple bar chart of the equilibrium concentrations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a13",
   "metadata": {},
   "outputs": [],
   "source": [
    "d = eq2.to_dict()\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(5, 3))\n",
    "ax.bar(d.keys(), [v * 1e6 for v in d.values()], color=\"teal\")\n",
    "ax.set_ylabel(\"Concentration (uM)\")\n",
    "ax.set_title(\"Equilibrium concentrations\")\n",
    "fig.tight_layout()\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.14.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}