{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "b5f84ab1",
   "metadata": {},
   "source": [
    "# Extending braincell\n",
    "\n",
    "`braincell`'s registries are open: you can add your own ion channels, ion\n",
    "species, synapses, and numerical integrators, and they become usable by name\n",
    "just like the built-ins.\n",
    "\n",
    "## Adding an ion channel\n",
    "\n",
    "Concrete channels live in {mod}`braincell.channel` and **self-register** at\n",
    "import time with the `@register_channel` decorator from {mod}`braincell.mech`.\n",
    "A new channel subclasses the appropriate base ({class}`braincell.IonChannel` /\n",
    "{class}`braincell.Channel`), implements its current and gating dynamics, and\n",
    "registers a name:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13f0551b",
   "metadata": {},
   "outputs": [],
   "source": [
    "import braincell\n",
    "from braincell.mech import register_channel\n",
    "\n",
    "@register_channel(\"MyNa\")\n",
    "class MyNa(braincell.Channel):\n",
    "    # define states, derivatives, and current here\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c3a57f7f",
   "metadata": {},
   "source": [
    "Once imported, the registered name is what string-based declarations resolve to:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4baa263b",
   "metadata": {},
   "outputs": [],
   "source": [
    "import braincell.mech as mech\n",
    "mech.Channel(\"MyNa\", g_max=0.1 * u.S / u.cm**2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a418ef60",
   "metadata": {},
   "source": [
    "Use the existing channels in `braincell/channel/` (sodium, potassium, calcium,\n",
    "…) as templates — they show the expected state declaration, parameter\n",
    "normalization, and docstring style.\n",
    "\n",
    "## Adding an ion species\n",
    "\n",
    "Ion species register the same way with `@register_ion`, subclassing the\n",
    "relevant ion base ({class}`braincell.Ion`). Model the reversal potential and any\n",
    "concentration dynamics, following the patterns in `braincell/ion/`.\n",
    "\n",
    "## Adding a synapse\n",
    "\n",
    "Synaptic point processes register with `@register_synapse` and are declared via\n",
    "{class}`braincell.mech.Synapse`. See `braincell/synapse/` for the Markov-model\n",
    "examples (AMPA, GABAa, NMDA).\n",
    "\n",
    "## Adding an integrator\n",
    "\n",
    "Solvers live in {mod}`braincell.quad` and register with\n",
    "`@register_integrator`, after which they are selectable by name through the\n",
    "`solver=` argument of any cell:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "60728a7b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from braincell.quad import register_integrator\n",
    "\n",
    "@register_integrator(\"my_solver\")\n",
    "def my_solver_step(...):\n",
    "    # advance the state by one dt\n",
    "    ..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5d15b594",
   "metadata": {},
   "outputs": [],
   "source": [
    "cell = braincell.SingleCompartment(size, solver=\"my_solver\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f9d0152",
   "metadata": {},
   "source": [
    "The {doc}`../integration/advanced` guide covers the integrator protocol\n",
    "({class}`braincell.DiffEqState`, {class}`braincell.DiffEqModule`) in depth.\n",
    "\n",
    "## Testing your extension\n",
    "\n",
    "Add a co-located `*_test.py` next to your new module (see {doc}`testing`) that:\n",
    "\n",
    "- constructs the mechanism with united parameters,\n",
    "- checks the dynamics against a known reference (an analytic limit, a published\n",
    "  trace, or NEURON), and\n",
    "- exercises any edge cases.\n",
    "\n",
    "## See also\n",
    "\n",
    "- {doc}`../concepts/ions_channels` — how ions and channels relate.\n",
    "- {doc}`../concepts/integration` — the solver concept.\n",
    "- {doc}`project_layout` — where each kind of mechanism lives."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
