{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "193e27ec",
   "metadata": {},
   "source": [
    "# Mechanisms\n",
    "\n",
    "A *mechanism* is anything you install on a cell that affects its dynamics: an\n",
    "ion channel, an ion species, a passive cable property, a current clamp, a\n",
    "synapse, or a probe. In `braincell`, mechanisms are **purely declarative** —\n",
    "they live in {mod}`braincell.mech` and describe *what* to install without\n",
    "touching JAX, time, or runtime state."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cfad23e0",
   "metadata": {},
   "outputs": [],
   "source": [
    "import braincell.mech as mech"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9275d9af",
   "metadata": {},
   "source": [
    "## Two families: density and point\n",
    "\n",
    "Every declaration inherits from the {class}`~braincell.mech.Mechanism` marker\n",
    "base and falls into one of two families:\n",
    "\n",
    "```{list-table}\n",
    ":header-rows: 1\n",
    ":widths: 22 30 48\n",
    "\n",
    "* - Family\n",
    "  - Base class\n",
    "  - Distributed how?\n",
    "* - **Density**\n",
    "  - {class}`~braincell.mech.Density`\n",
    "  - spread over a **region** of cable (a quantity *per unit area*). Painted.\n",
    "* - **Point**\n",
    "  - {class}`~braincell.mech.Point`\n",
    "  - attached at a single **location**. Placed.\n",
    "```\n",
    "\n",
    "This distinction drives the two verbs you use to decorate a cell:\n",
    "\n",
    "```text\n",
    "   cell.paint(region,  density_mechanism)   # distribute over cable\n",
    "   cell.place(locset,  point_mechanism)      # attach at points\n",
    "```\n",
    "\n",
    "The `region` and `locset` arguments are selection expressions from\n",
    "{mod}`braincell.filter` — see {doc}`regions_locsets`.\n",
    "\n",
    "## Density mechanisms (paint these)\n",
    "\n",
    "```{list-table}\n",
    ":header-rows: 1\n",
    ":widths: 30 70\n",
    "\n",
    "* - Declaration\n",
    "  - Describes\n",
    "* - {class}`~braincell.mech.Channel`\n",
    "  - an ion channel, distributed with a maximal conductance density `g_max`.\n",
    "* - {class}`~braincell.mech.Ion`\n",
    "  - an ion species (its dynamics / reversal potential model).\n",
    "* - {class}`~braincell.CableProperty`\n",
    "  - passive cable: resting potential, membrane capacitance, axial resistivity,\n",
    "    temperature.\n",
    "```\n",
    "\n",
    "`Channel` and `Ion` name the concrete implementation either by class **or by\n",
    "string**, then take its parameters as keywords:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "21042683",
   "metadata": {},
   "outputs": [],
   "source": [
    "import brainunit as u\n",
    "import braincell.mech as mech\n",
    "\n",
    "# by string name\n",
    "mech.Channel(\"Na_Ba2002\", g_max=0.12 * u.S / u.cm**2)\n",
    "\n",
    "# passive cable\n",
    "mech.CableProperty(\n",
    "    resting_potential=-65. * u.mV,\n",
    "    membrane_capacitance=1.0 * u.uF / u.cm**2,\n",
    "    axial_resistivity=100. * u.ohm * u.cm,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2782e85a",
   "metadata": {},
   "source": [
    "The string names correspond to the concrete classes in\n",
    "{mod}`braincell.channel` and {mod}`braincell.ion`, which self-register at import\n",
    "time (see {doc}`ions_channels`).\n",
    "\n",
    "## Point mechanisms (place these)\n",
    "\n",
    "```{list-table}\n",
    ":header-rows: 1\n",
    ":widths: 30 70\n",
    "\n",
    "* - Declaration\n",
    "  - Describes\n",
    "* - {class}`~braincell.CurrentClamp`\n",
    "  - injected current; `CurrentClamp(delay=..., durations=duration, amplitudes=amp)` for a step.\n",
    "* - {class}`~braincell.SineClamp` / {class}`~braincell.FunctionClamp`\n",
    "  - sinusoidal or arbitrary-function current injection.\n",
    "* - {class}`~braincell.mech.Synapse`\n",
    "  - a synaptic point process.\n",
    "* - {class}`~braincell.mech.Junction`\n",
    "  - a gap junction.\n",
    "* - {class}`~braincell.mech.StateProbe` / {class}`~braincell.mech.MechanismProbe` / {class}`~braincell.mech.CurrentProbe`\n",
    "  - **recording** probes — what you `place` to read out a simulation.\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7b523b35",
   "metadata": {},
   "outputs": [],
   "source": [
    "from braincell.filter import RootLocation\n",
    "import braincell.mech as mech\n",
    "import brainunit as u\n",
    "\n",
    "# inject a step current at the soma\n",
    "cell.place(RootLocation(0.5),\n",
    "           mech.CurrentClamp(delay=10 * u.ms, durations=50 * u.ms, amplitudes=0.2 * u.nA))\n",
    "\n",
    "# record membrane voltage there\n",
    "cell.place(RootLocation(0.5), mech.StateProbe(\"V\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a38b317b",
   "metadata": {},
   "source": [
    "```{important}\n",
    "A multi-compartment run needs **at least one placed probe** — the probes define\n",
    "what `Cell.run(...)` returns. Without one you will get\n",
    "`ValueError: Cell.run(...) requires at least one placed probe.`\n",
    "```\n",
    "\n",
    "## Why declarations are separate from the runtime\n",
    "\n",
    "Because a mechanism is plain, hashable data, `braincell` can:\n",
    "\n",
    "- **deduplicate** identical paints across regions (via\n",
    "  {class}`~braincell.mech.Params`, an order-insensitive frozen mapping);\n",
    "- **inspect and diff** a model before it runs;\n",
    "- **compile** the whole decorated cell into a single differentiable kernel.\n",
    "\n",
    "This is the declaration layer of the {doc}`architecture`.\n",
    "\n",
    "## See also\n",
    "\n",
    "- {doc}`ions_channels` — the channels and ions you name in `Channel`/`Ion`.\n",
    "- {doc}`regions_locsets` — the `paint`/`place` targets.\n",
    "- {doc}`../apis/braincell.mech` — full mechanism API reference."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
