{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "# 离子\n",
    "\n",
    "在 `braincell` 中，离子被分为以下三种基类，\n",
    "- `Calcium` ：钙离子\n",
    "- `Potassium` ：钾离子\n",
    "- `Sodium` ：钠离子\n",
    "\n",
    "## 现有离子调用\n",
    "\n",
    "我们先来讲解如何使用现有离子。\n",
    "\n",
    "实际使用中，调用这些离子相关的模型非常简单。\n",
    "\n",
    "### Ion 调用\n",
    "\n",
    "同样，我们来看对 HH 神经元建模的例子："
   ],
   "id": "426539c77c6501e1"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-13T09:23:24.051706Z",
     "start_time": "2025-10-13T09:23:24.048159Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import braincell\n",
    "\n",
    "class HH(braincell.SingleCompartment):\n",
    "    def __init__(self, in_size):\n",
    "        super().__init__(in_size, C=Cm, solver='ind_exp_euler')\n",
    "        self.na = braincell.ion.SodiumFixed(in_size, E=50. * u.mV)\n",
    "        self.na.add_elem(\n",
    "            INa=braincell.channel.INa_TM1991(in_size, g_max=(100. * u.mS * u.cm ** -2) * area, V_sh=-63. * u.mV)\n",
    "        )\n",
    "\n",
    "        self.k = braincell.ion.PotassiumFixed(in_size, E=-90 * u.mV)\n",
    "        self.k.add_elem(\n",
    "            IK=braincell.channel.IK_TM1991(in_size, g_max=(30. * u.mS * u.cm ** -2) * area, V_sh=-63. * u.mV)\n",
    "        )\n",
    "\n",
    "        self.IL = braincell.channel.IL(in_size, E=-60. * u.mV, g_max=(5. * u.nS * u.cm ** -2) * area)"
   ],
   "id": "15ef61c888976132",
   "outputs": [],
   "execution_count": 41
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "首先，在导入相关模块之后，我们需要在 `__init__` 创建具体的模型对象。\n",
    "\n",
    "这里我们以钠离子 `na` 为例，使用 `SodiumDetailed` 创建钙离子模型。\n",
    "我们只需要根据文献中的定义或者实际情况对 `SodiumDetailed` 的参数进行设定即可。\n",
    "\n",
    "可以看到，使用已经完成建模的离子模型非常简单，只需简单调用即可。\n",
    "\n",
    "同样，我们也可以通过调用具体的 `Ion` 类型来进行简单仿真。\n",
    "如我们可以使用 `CalciumDetailed` ，模拟细胞内钙离子反转电位随时间的动态变化。"
   ],
   "id": "24c4ed05084516f2"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-13T09:23:24.066803Z",
     "start_time": "2025-10-13T09:23:24.059191Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import brainstate\n",
    "import braintools\n",
    "import braincell\n",
    "import brainunit as u"
   ],
   "id": "5332c6f6eadd307",
   "outputs": [],
   "execution_count": 42
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-13T09:23:24.565403Z",
     "start_time": "2025-10-13T09:23:24.561662Z"
    }
   },
   "cell_type": "code",
   "source": [
    "ca = braincell.ion.CalciumDetailed(size=1)\n",
    "V = -65 * u.mV\n",
    "ca.init_state(V)\n",
    "\n",
    "dt = 0.1 * u.ms\n",
    "steps = 1000"
   ],
   "id": "9a6e74284f220cdb",
   "outputs": [],
   "execution_count": 43
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-13T09:23:24.918058Z",
     "start_time": "2025-10-13T09:23:24.835890Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def run_calcium(i):\n",
    "    t = i * dt\n",
    "    with brainstate.environ.context(i=i, t=t, dt=dt):\n",
    "        # 流入电流\n",
    "        input_current = -0.1 * u.uA / u.cm**2\n",
    "        ca.C.derivative = input_current / (2 * u.faraday_constant * ca.d) + (ca.C_rest - ca.C.value) / ca.tau\n",
    "        ca.C.value = ca.C.value + ca.C.derivative * dt\n",
    "    return ca.E\n",
    "\n",
    "indices = u.math.arange(steps)\n",
    "E = brainstate.transform.for_loop(run_calcium, indices)\n",
    "\n",
    "plt.plot(indices * dt, E)\n",
    "plt.xlabel('Time (ms)')\n",
    "plt.ylabel('E (mV)')\n",
    "plt.title('Calcium Reversal Potential')\n",
    "plt.show()\n"
   ],
   "id": "d8a704cb31d184c9",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ],
      "image/png": "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k3b7P/PMM+ZcP/HEE+bcDh061HkuS/p3hPNcPuPGjZPMzEwT9oOCgsy/z88//7zpSlKca/cryznVR/0Doqjg4GDzh7G7zzshCijWSrJt2zbz1yTcKzk5WZ588klTo6AXRcBzfwjoX+AvvPCCmdeWKP2d1voRDVFwn3/84x/y/vvvy9y5c+W6666TTZs2mT/CtCCac1010J3nQ+Li4sxfO8WvVtL5xMRE247LX4waNcoUIK5YsUKSkpKcy/Xcaldqenq6y/qc9/LR7jq9AOKGG24wfxXqpMXjWiCqz/UvSc7z1dMrlq699lqXZa1atZJDhw6Z545zyb8jV++///u/TWvUvffea66A/NWvfmUujtArfhXn2v3Kck71sfjFVhcuXDBX7Ln7vBOifIg2x3fo0MH0wRf9q1Pnu3btauux+TKtXdQAtXDhQlm+fLm5XLkoPed6pVPR865DIOiXEue97Hr37i1bt241f607Jm0x0a4Px3PO89XTrujiQ3RozU7Dhg3Nc/391i+SoudZu6S0VoTzXD7Z2dmmzqYo/UNX/11WnGv3K8s51Uf9Y0z/cHPQf9v156K1U27l1jJ1eNy8efPMVQhvv/22uQLhkUcesWJjY63jx4/bfWg+6/HHH7diYmKslStXWseOHXNO2dnZznUee+wxq0GDBtby5cut77//3uratauZcHWKXp2nOM9Xb926dVZwcLD1/PPPW3v27LHef/99q1q1atZ7773nXGfKlCnm341FixZZW7Zsse68806rcePG1rlz52w9dl8zdOhQq169etbixYutAwcOWP/85z+tuLg46/e//71zHc51xa7g/c9//mMmjSmvvPKKef7jjz+W+Zz279/fat++vfXdd99Z33zzjbki+L777rPcjRDlg1577TXzRRMaGmqGPFi7dq3dh+TT9D/SkqY5c+Y419H/OH/zm99YNWrUMF9Id911lwlacG+I4jy7x6effmq1bt3a/MHVsmVLa/bs2S6v62Xizz77rJWQkGDW6d27t7V7927bjtdXZWZmmt9f/fc4PDzcatKkiTVhwgQrJyfHuQ7nuvxWrFhR4r/JGlrLek5PnjxpQlNkZKQVHR1tDR8+3IQzdwvQ/3Nv2xYAAID/oyYKAACgAghRAAAAFUCIAgAAqABCFAAAQAUQogAAACqAEAUAAFABhCgAAIAKIEQBAABUACEKgN8ZNmyYDBgwwLb9641oX3jhBY9tf8eOHeYm2VlZWR7bB4ArY8RyAD4lICDgsq9PmjRJnnrqKXNj6djYWPG2zZs3y89//nP58ccfJTIy0mP7ufvuu6Vt27by7LPPemwfAC6PEAXApxw/ftz5fP78+TJx4kTZvXu3c5kGF0+Glyv59a9/LcHBwfL66697dD+fffaZPPzww3Lo0CGzPwDeR3ceAJ+SmJjonGJiYkzLVNFlGqCKd+f17NlTRo8eLWPGjJEaNWpIQkKCvPnmm6Y7bPjw4RIVFSXNmjWTL774wmVf27Ztk1tvvdVsU9+j3XRpaWmlHlt+fr58+OGHcscdd7gsb9SokfzpT3+SIUOGmG01bNhQPvnkEzlx4oTceeedZlmbNm3k+++/d75HW7J0O3q81atXl+uuu04+//xz5+u33HKLnDp1SlatWuWmMwugvAhRAKqEd955R+Li4mTdunUmUD3++ONyzz33yE033SQbN26Uvn37mpCUnZ1t1k9PTzfdcu3btzfhZsmSJZKSkiK//OUvS93Hli1bJCMjQzp27HjJa1OnTpVu3brJf/7zH7ntttvMvjRUPfjgg2b/TZs2NfOOzoGRI0dKTk6OrF69WrZu3SovvviiSwtbaGiotGvXTr7++muPnC8AV0aIAlAlaP3QH/7wB2nevLmMHz9ewsPDTajSLjFdpt2CJ0+eNEFITZ8+3QQoLRBv2bKlef7WW2/JihUr5IcffihxH9p6FBQUJPHx8Ze89otf/EIeffRR574yMzOlU6dOJshdc8018vTTT8vOnTtNUFPaTaeh6/rrr5cmTZrI7bffLt27d3fZZt26dc0+AdiDEAWgStDuMgcNOrVq1TIBxUG761RqaqqzQFwDk6PGSicNU2rfvn0l7uPcuXMSFhZWYvF70f079nW5/T/xxBOmC1CDlBbLO8JdUREREc6WMwDeR4gCUCWEhIS4zGvQKbrMEXwKCgrM49mzZ01N0qZNm1ymPXv2XNIi5KAtWxpqcnNzL7t/x74ut38tUN+/f7/p9tPuPO0ifO2111y2qTVRtWvXrsDZAOAOhCgAKMENN9wg27dvN0XhWnRedNJC75JojZJjHCd3qF+/vjz22GPyz3/+U37729+aYvjihe/azQjAHoQoACiBFnZrS899990n69evN114//rXv8zVfHoVXkm0VUjD1zfffHPV+9crCXV/Bw4cMIXn2rXYqlUr5+sHDx6UI0eOSJ8+fa56XwAqhhAFACXQou1vv/3WBCa9ck/rlzTY6ACegYGl/9Op3XDvv//+Ve9f96tBToNT//79TfH5zJkzna9/8MEH5rh0uAQA9mCwTQBwIy0ub9GihRkItGvXrh7Zh9Zc6VV+c+fONYXnAOxBSxQAuJFeMffuu+9edlDOq6XDHzzzzDMEKMBmtEQBAABUAC1RAAAAFUCIAgAAqABCFAAAQAUQogAAACqAEAUAAFABhCgAAIAKIEQBAABUACEKAACgAghRAAAAUn7/Dwzz3HDNhng6AAAAAElFTkSuQmCC"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 44
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "\n",
    "### MixIons 调用\n",
    "\n",
    "在某些复杂模型中，一个通道可能涉及多个离子的协同作用。例如，某些钙激活钾通道同时依赖钙离子浓度和膜电位调控钾离子流出。这种多离子依赖的机制在生物系统中非常常见。\n",
    "\n",
    "为此，`braincell` 提供了一个专门的模块 `MixIons`，用于建模多种离子共同驱动的复合通道系统。\n",
    "\n",
    "`MixIons` 继承自 `IonChannel` 与 `Container` ，符合通道组件接口并且可以挂载多个子模块，在这里便于管理多个 `Channel`。同样， `MixIons` 也支持我们前面提及过的接口。\n",
    "\n",
    "总而言之， `MixIons` 提供了一种模块化方式来组合多个 `Ion` 与多个 `Channel`，非常适用于那些依赖多个离子状态的通道或者需要整合多种通道电流的建模。借助 `MixIons`，你可以构建更为灵活、精细的神经元动力学模型，并保持代码的清晰结构与良好可维护性。\n",
    "\n",
    "我们来看一个在实际建模中使用 `MixIons` 的例子："
   ],
   "id": "5784c15880f19f0a"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-13T09:23:25.168636Z",
     "start_time": "2025-10-13T09:23:25.163908Z"
    }
   },
   "cell_type": "code",
   "source": [
    "class HTC(braincell.SingleCompartment):\n",
    "    def __init__(\n",
    "        self,\n",
    "        size,\n",
    "        gKL=0.01 * (u.mS / u.cm ** 2),\n",
    "        V_initializer=braintools.init.Constant(-65. * u.mV),\n",
    "        solver: str = 'ind_exp_euler'\n",
    "    ):\n",
    "        super().__init__(size, V_initializer=V_initializer, V_th=20. * u.mV, solver=solver)\n",
    "\n",
    "        self.area = 1e-3 / (2.9e-4 * u.cm ** 2)\n",
    "\n",
    "        self.k = braincell.ion.PotassiumFixed(size, E=-90. * u.mV)\n",
    "        self.k.add(IKL=braincell.channel.IK_Leak(size, g_max=gKL))\n",
    "        self.k.add(IDR=braincell.channel.IKDR_Ba2002(size, V_sh=-30. * u.mV, phi=0.25))\n",
    "\n",
    "        self.ca = braincell.ion.CalciumDetailed(size, C_rest=5e-5 * u.mM, tau=10. * u.ms, d=0.5 * u.um)\n",
    "        self.ca.add(ICaL=braincell.channel.ICaL_IS2008(size, g_max=0.5 * (u.mS / u.cm ** 2)))\n",
    "        self.ca.add(ICaN=braincell.channel.ICaN_IS2008(size, g_max=0.5 * (u.mS / u.cm ** 2)))\n",
    "        self.ca.add(ICaT=braincell.channel.ICaT_HM1992(size, g_max=2.1 * (u.mS / u.cm ** 2)))\n",
    "        self.ca.add(ICaHT=braincell.channel.ICaHT_HM1992(size, g_max=3.0 * (u.mS / u.cm ** 2)))\n",
    "\n",
    "        self.kca = braincell.MixIons(self.k, self.ca)\n",
    "        self.kca.add(IAHP=braincell.channel.IAHP_De1994(size, g_max=0.3 * (u.mS / u.cm ** 2)))"
   ],
   "id": "8460786ae33fbac1",
   "outputs": [],
   "execution_count": 45
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "这个例子隐去了其他离子与相关通道，我们现在聚焦到混合离子的建模。\n",
    "\n",
    "如果需要与其他离子整合，如例子中的 `kca` 混合离子，只需要使用 `MixIons(self.k, self.ca)` 混合离子池即可。\n",
    "\n",
    "此处需要注意，传入离子的顺序非常重要。举个例子："
   ],
   "id": "ca67543596c5bc30"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-13T09:23:25.505017Z",
     "start_time": "2025-10-13T09:23:25.501358Z"
    }
   },
   "cell_type": "code",
   "source": "braincell.channel.IAHP_De1994.root_type",
   "id": "dc47e71c94f1ed4f",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "JointTypes[braincell.ion.Potassium, braincell.ion.Calcium]"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 46
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "可以看到，对于 `IAHP_De1994` 这种和多种离子相关的 `channel` ，其 `root_type` 中的两种 `Ion` 是有顺序的。\n",
    "因此，在我们对 `MixIons` 传入离子时，需要将两种离子的顺序一一匹配，如对于 `IAHP_De1994` ，就需要传入 `(self.k, self.ca)` ，而不能传入 `(self.ca, self.k)` ，从而规避因传如离子类型不匹配而导致的建模错误。\n",
    "\n",
    "总的来说，只要我们对需要整合的离子都拥有了相关的模型，如例子中的 `k` 和 `ca` ，我们就可以轻松的使用 `MixIons` 整合两者。\n",
    "\n",
    "## 自定义离子建模\n",
    "\n",
    "在实际建模中，可能目前内置的三种离子模型无法满足你的需要，你可能需要对其他种类的离子进行建模，比如 `Cl` 或更多离子，又或是对建模的离子的细节有更高的要求。\n",
    "鉴于此，我们来对如何自定义离子建模进行教学。\n",
    "\n",
    "### Ion 建模\n",
    "\n",
    "我们来讲解如何对 `Ion` 进行建模。\n",
    "\n",
    "从实际电生理结构来看，`Ion` 是依赖于 `Channel` 的选择性通过才能在膜内外转移的。\n",
    "而在实际编程中，我们也根据这种依赖关系设计了继承关系：`Ion` 继承自 `IonChannel` 和 `Container`，这意味着它既具备通道接口能力，又具有容纳多个子模块的容器功能。\n",
    "在模拟系统中，`Ion` 会被接入到 `HHTypedNeuron` 类型的细胞中，与膜电位共同驱动通道演化。\n",
    "\n",
    "在 `braincell` 中，`Ion` 是一个用于管理某一类离子的抽象实体。\n",
    "它本质上并不产生电流，而是通过组织和调度其所包含的多个 `Channel`对象来实现对离子电流的建模与仿真。\n",
    "每一种离子都会对应一个 `Ion` 实例，该实例作为多个相关通道的容器与控制中心，负责这些通道的统一管理。\n",
    "\n",
    "同样，`Ion` 提供了多个统一的仿真接口，以管理其状态演化过程。\n",
    "通过对 `Ion` 进行建模，可以使得代码结构更加模块化，集中管理每种离子的通道，避免混用。\n",
    "同时，通过 `Ion` 类，可以轻松实现组件的复用，提高了效率。\n",
    "\n",
    "在实际建模过程中，我们经常需要将离子的一些关键属性，如浓度和反转电位，传递给多个通道或者计算函数。为了简洁清晰的表达这些信息， `braincell` 引入了一个专用的数据结构 `IonInfo`。\n",
    "\n",
    "在 `IonInfo` 中，有两个关键属性：\n",
    "- `C` ：离子浓度\n",
    "- `E` ：反转电位\n",
    "\n",
    "在 `braincell` 中，可以将 `IonInfo` 理解为一个轻便的容器，用来统一管理和传递离子相关信息。\n",
    "它在 `Ion` 和 `Channel` 之间起到桥梁的作用，是一个简单但强大的信息传递结构。\n",
    "\n",
    "至此，我们已经了解了 `Ion` 的建模。接下来，我们来对具体的离子进行建模。\n",
    "\n",
    "我们以钙离子为例："
   ],
   "id": "535eea4f07803b16"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-13T09:23:25.526017Z",
     "start_time": "2025-10-13T09:23:25.523916Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from typing import Union, Callable, Optional\n",
    "from braincell.ion import Calcium"
   ],
   "id": "3a9ccbb3237a43e2",
   "outputs": [],
   "execution_count": 47
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-13T09:23:26.013209Z",
     "start_time": "2025-10-13T09:23:26.009222Z"
    }
   },
   "cell_type": "code",
   "source": [
    "class CalciumFixed(Calcium):\n",
    "\n",
    "    __module__ = 'braincell.ion'\n",
    "\n",
    "    def __init__(\n",
    "        self,\n",
    "        size: brainstate.typing.Size,\n",
    "        E: Union[brainstate.typing.ArrayLike, Callable] = 120. * u.mV,\n",
    "        C: Union[brainstate.typing.ArrayLike, Callable] = 2.4e-4 * u.mM,\n",
    "        name: Optional[str] = None,\n",
    "        **channels\n",
    "    ):\n",
    "        super().__init__(size, name=name, **channels)\n",
    "        self.E = braintools.init.param(E, self.varshape, allow_none=False)\n",
    "        self.C = braintools.init.param(C, self.varshape, allow_none=False)\n",
    "\n",
    "    def reset_state(self, V, batch_size=None):\n",
    "        ca_info = self.pack_info()\n",
    "        nodes = brainstate.graph.nodes(self, Channel, allowed_hierarchy=(1, 1)).values()\n",
    "        self.check_hierarchies(type(self), *tuple(nodes))\n",
    "        for node in nodes:\n",
    "            node.reset_state(V, ca_info, batch_size=batch_size)"
   ],
   "id": "942af492300bc6ba",
   "outputs": [],
   "execution_count": 48
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "我们非常轻松的就对 `CalciumFixed` 进行了建模，其继承自 `Calcium` ，实现了一个通用的钙离子模型。\n",
    "\n",
    "实际对具体的离子进行建模即可参考以上的形式。\n",
    "对新的离子进行自定义建模时最重要的就是设定好关键属性 `E` 和 `C` 。\n",
    "\n",
    "基于此，你可以对在实际建模中自己需要的离子进行自定义建模。"
   ],
   "id": "b6268edda3c28fbb"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "\n",
    "我们继续以钙离子为例，进一步讲解如何对更精细的动态模型，如 `CalciumDetailed` 进行建模。\n",
    "\n",
    "`CalciumDetailed` 的建模参考了 Bazhenov 在 1998 提出的模型。\n",
    "在这个模型中，钙离子动力学可以简化为一阶线性微分方程：\n",
    "$$\\frac{d[Ca^{2+}]_i}{dt} = -\\frac{I_{Ca}}{z F d} + \\frac{[Ca^{2+}]_{\\text{rest}} - [Ca^{2+}]_i}{\\tau_{Ca}}$$\n",
    "我们使用 `braincell` 对其微分方程进行建模：\n"
   ],
   "id": "e4bed0427547b648"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-13T09:23:26.272665Z",
     "start_time": "2025-10-13T09:23:26.270476Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from braincell.ion.calcium import _CalciumDynamics\n",
    "\n",
    "class CalciumDetailed(_CalciumDynamics):\n",
    "\n",
    "    __module__ = 'braincell.ion'"
   ],
   "id": "a09dbee2637e347e",
   "outputs": [],
   "execution_count": 49
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "在该模型中，参数如下：\n",
    "- \\$I\\_{Ca}\\$：所有钙通道产生的总电流\n",
    "- \\$d\\$：膜下薄壳的厚度（\\$1, \\mu\\mathrm{m}\\$）\n",
    "- \\$F\\$：法拉第常数\n",
    "- \\$\\tau\\_{Ca}\\$：钙的清除时间常数\n",
    "- $\\[Ca^{2+}]\\_{\\text{rest}} = 0.05\\mu\\mathrm{M}\\$\n",
    "\n",
    "我们据此来定义相关的参数："
   ],
   "id": "b6b6e3a20f4405bb"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-13T09:23:26.525324Z",
     "start_time": "2025-10-13T09:23:26.521936Z"
    }
   },
   "cell_type": "code",
   "source": [
    "    def __init__(\n",
    "        self,\n",
    "        size: brainstate.typing.Size,\n",
    "        T: Union[brainstate.typing.ArrayLike, Callable] = u.celsius2kelvin(36.),\n",
    "        d: Union[brainstate.typing.ArrayLike, Callable] = 1. * u.um,\n",
    "        tau: Union[brainstate.typing.ArrayLike, Callable] = 5. * u.ms,\n",
    "        C_rest: Union[brainstate.typing.ArrayLike, Callable] = 2.4e-4 * u.mM,\n",
    "        C0: Union[brainstate.typing.ArrayLike, Callable] = 2. * u.mM,\n",
    "        C_initializer: Union[brainstate.typing.ArrayLike, Callable] = braintools.init.Constant(2.4e-4 * u.mM),\n",
    "        name: Optional[str] = None,\n",
    "        **channels\n",
    "    ):\n",
    "        super().__init__(size, name=name, T=T, C0=C0, C_initializer=C_initializer, **channels)\n",
    "\n",
    "        # parameters\n",
    "        self.d = braintools.init.param(d, self.varshape, allow_none=False)\n",
    "        self.tau = braintools.init.param(tau, self.varshape, allow_none=False)\n",
    "        self.C_rest = braintools.init.param(C_rest, self.varshape, allow_none=False)"
   ],
   "id": "1ef0ef8166f876cf",
   "outputs": [],
   "execution_count": 50
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "然后再根据相关公式：\n",
    "$$\n",
    "\\frac{d[Ca^{2+}]_i}{dt} = -\\frac{I_{Ca}}{z F d} + \\frac{[Ca^{2+}]_{\\text{rest}} - [Ca^{2+}]_i}{\\tau_{Ca}}\n",
    "$$\n",
    "其中 \\$z = 2\\$，表示\\$\\mathrm{Ca^{2+}}\\$\n"
   ],
   "id": "40bb483b0a41b331"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-13T09:23:26.545389Z",
     "start_time": "2025-10-13T09:23:26.543182Z"
    }
   },
   "cell_type": "code",
   "source": [
    "    def derivative(self, C, V):\n",
    "        ICa = self.current(V, include_external=True)\n",
    "        drive = ICa / (2 * u.faraday_constant * self.d)\n",
    "        drive = u.math.maximum(drive, u.math.zeros_like(drive))\n",
    "        return drive + (self.C_rest - C) / self.tau"
   ],
   "id": "6f04ceb56b19a4bf",
   "outputs": [],
   "execution_count": 51
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "至此，我们就完成了对 `CalciumDetailed` 的建模，实现了经典的动态钙浓度模型。\n",
    "\n",
    "`CalciumDetailed` 继承自 `_CalciumDynamics` 基类，而 `_CalciumDynamics` 是 `Calcium` 的子类。\n",
    "我们可以通过这里的继承关系体会到对离子进行建模时应实现的继承规范。\n",
    "\n",
    "综上所述，对通用类的离子， 如 `CalciumFixed` 进行建模，需要我们定义好相关离子的 `E` 和 `C` 。\n",
    "而对更为具体的离子， 如 `CalciumDetailed` 进行建模，则需要我们根据实际的公式来进行定义。\n",
    "\n",
    "通过以上教程，你学会了如何对新的离子进行建模。\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ],
   "id": "ad3176122cf43b82"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "\n",
    "\n",
    "## 现有离子实例\n",
    "\n",
    "我们现有的离子模型也较为丰富，以下是对相关离子的介绍。\n",
    "\n",
    "### Calcium\n",
    "\n",
    "在 `braincell` 中，我们通过对 `Ion` 类的扩展，来建模各种具体类型的离子。我们现在聚焦于钙离子 `Calcium` 的建模方式。\n",
    "\n",
    "钙离子在神经元中起着至关重要的作用，参与动作电位的触发、神经递质的释放以及各种钙依赖的信号转导路径。因此，针对不同建模需求，我们提供了多个版本的钙离子模型：\n",
    "- `CalciumFixed`：固定浓度与反转电位的钙离子模型。\n",
    "- `CalciumDetailed`：基于生物物理机制的精细钙动力学模型。\n",
    "- `CalciumFirstOrder`：简化的一阶钙动力学模型。\n",
    "\n",
    "当然，在对这些不同模型进行了解之前，我们先要对基类 `Calcium` 进行说明。\n",
    "\n",
    "`Calcim` 是所有钙离子模型的基类。它本身不包含任何具体动力学，仅作为语义上的标识使用，即 `Ion` 的钙离子特化版本，方便对钙离子进行统一管理与约束。\n",
    "\n",
    "#### `CalciumFixed`\n",
    "\n",
    "`CalciumFixed` 提供最简单的钙建模形式，假设钙离子的反转电位 `E` 与浓度 `C` 是固定值，没有随时间变化的动力学。\n",
    "\n",
    "#### `CalciumDetailed`\n",
    "\n",
    "##### 细胞内钙离子的动力学\n",
    "\n",
    "细胞内钙离子的变化主要由两个机制决定：\n",
    "\n",
    "###### 由钙电流引起的内流\n",
    "\n",
    "钙离子通过钙通道进入细胞，并扩散到细胞内部。模型中只考虑膜下薄壳区域的钙离子浓度。内流的公式为：\n",
    "\n",
    "$$\n",
    "[Ca]_i = -\\frac{I_{Ca}}{2 F d}\n",
    "$$\n",
    "\n",
    "其中：\n",
    "- \\$F = 96489, \\mathrm{C/mol}\\$ 为法拉第常数\n",
    "- \\$d = 1, \\mu\\mathrm{m}\\$ 为膜下薄壳区域的厚度\n",
    "- \\$I\\_{Ca}\\$ 为所有钙通道产生的总电流\n",
    "- $\\[Ca]\\_i\\$ 为细胞内钙浓度\n",
    "\n",
    "###### 由钙泵引起的外流\n",
    "\n",
    "在膜下区域，钙的移除可通过结合缓冲物、钙泵活动、扩散等多种方式进行。此处模型只对泵进行建模，并采用如下动力学反应过程：\n",
    "\n",
    "$$\n",
    "\\mathrm{Ca^{2+}_i} + P \\underset{c_2}{\\overset{c_1}{\\rightleftharpoons}} \\mathrm{CaP} \\xrightarrow{c_3} P + \\mathrm{Ca^{2+}_0}\n",
    "$$\n",
    "\n",
    "其中：\n",
    "- \\$P\\$ 表示钙泵\n",
    "- \\$\\mathrm{CaP}\\$ 是钙泵中间复合态\n",
    "- \\$\\mathrm{Ca^{2+}\\_0}\\$ 是膜外钙浓度\n",
    "- \\$c\\_1\\$, \\$c\\_2\\$, \\$c\\_3\\$ 为反应速率常数\n",
    "\n",
    "考虑 \\$c\\_3\\$ 很小，可使用 Michaelis-Menten 近似公式表示钙泵的动力学行为：\n",
    "\n",
    "$$\n",
    "\\frac{d[Ca^{2+}]_i}{dt} = -\\frac{K_T [Ca]_i}{[Ca]_i + K_d}\n",
    "$$\n",
    "\n",
    "其中：\n",
    "- \\$K\\_T = 10^{-4}, \\mathrm{mM/ms}\\$\n",
    "- \\$K\\_d = \\frac{c\\_2}{c\\_1} = 10^{-4}, \\mathrm{mM}\\$\n",
    "- \\$K\\_d\\$ 表示钙泵激活一半所需的钙浓度\n",
    "\n",
    "##### 简化的一阶模型\n",
    "\n",
    "在 Bazhenov 在 1998 提出的模型中，钙离子动力学可以简化为一阶线性微分方程：\n",
    "\n",
    "$$\n",
    "\\frac{d[Ca^{2+}]_i}{dt} = -\\frac{I_{Ca}}{z F d} + \\frac{[Ca^{2+}]_{\\text{rest}} - [Ca^{2+}]_i}{\\tau_{Ca}}\n",
    "$$\n",
    "\n",
    "其中：\n",
    "- \\$I\\_{Ca}\\$：所有钙通道产生的总电流\n",
    "- \\$d\\$：膜下薄壳的厚度（\\$1, \\mu\\mathrm{m}\\$）\n",
    "- \\$z = 2\\$：\\$\\mathrm{Ca^{2+}}\\$ 的电荷价\n",
    "- \\$F\\$：法拉第常数\n",
    "- \\$\\tau\\_{Ca}\\$：钙的清除时间常数\n",
    "- $\\[Ca^{2+}]\\_{\\text{rest}} = 0.05\\mu\\mathrm{M}\\$\n",
    "\n",
    "##### 钙离子的反转电位\n",
    "\n",
    "钙离子的反转电位根据 Nernst 方程给出：\n",
    "\n",
    "$$\n",
    "E = \\frac{RT}{2F} \\log \\left( \\frac{[Ca^{2+}]_0}{[Ca^{2+}]_i} \\right)\n",
    "$$\n",
    "\n",
    "其中：\n",
    "- \\$R = 8.31441, \\mathrm{J/(mol\\cdot K)}\\$：气体常数\n",
    "- \\$T = 309.15, \\mathrm{K}\\$：绝对温度（约为 36℃）\n",
    "- \\$F = 96489, \\mathrm{C/mol}\\$：法拉第常数\n",
    "- $\\[Ca^{2+}]\\_0 = 2, \\mathrm{mM}\\$：膜外钙浓度\n",
    "\n",
    "#### `CalciumFirstOrder`\n",
    "\n",
    "该模型采用一个简洁的一阶微分方程模拟钙浓度的变化：\n",
    "\n",
    "$$\n",
    " Ca' = -\\alpha I_{Ca} + -\\beta Ca\n",
    "$$\n",
    "\n",
    "至此，我们完全了解了 `Calcium` 中内置的几种离子模型。\n",
    "\n",
    "### Potassium\n",
    "\n",
    "对于 `Potassium` ，我们依然通过对 `Ion` 类的扩展来建模。\n",
    "\n",
    "钾离子在神经元中广泛存在，其跨膜流动对静息膜电位的维持、动作电位的复极以及神经元兴奋性控制等具有关键影响。\n",
    "\n",
    "`Potassium` 是所有钾离子模型的基类，其继承自 `Ion`，用于钾离子的统一标识与组织。该类本身并不包含具体动力学，仅作为接口模板使用。\n",
    "\n",
    "如果需要实际建模，我们需要用到 `PotassiumFixed` 。\n",
    "\n",
    "#### `PotassiumFixed`\n",
    "\n",
    "`PotassiumFixed` 提供了最基础的钾离子建模方式，假设其浓度和反转电位固定，不随时间动态变化。这类模型适用于不关注离子浓度变化的情境，仅需要使用钾电流与恒定的反转电位。\n",
    "\n",
    "在 `reset_state` 中，它会将 `E` 与 `C` 打包为 `IonInfo` 并传递给其下挂的所有 `Channel` 子模块，用于后续电流计算。\n",
    "\n",
    "### Sodium\n",
    "\n",
    "和其他离子模型一样，`braincell` 中的钠离子也是通过扩展 `Ion` 类来建模。\n",
    "\n",
    "钠离子是动作电位产生的核心参与者。其跨膜内流导致去极化，是神经元兴奋与信号传导的关键机制。\n",
    "\n",
    "`Sodium` 是所有钠离子模型的抽象基类。它继承自 `Ion`，用于统一管理钠离子实例，并提供一致的结构接口。该类本身并不实现任何动力学，同样仅作为接口模板使用。\n",
    "\n",
    "#### `SodiumFixed`\n",
    "\n",
    "`SodiumFixed` 提供最简单的钠建模形式，假设其浓度 `C` 与反转电位 `E` 是固定的，不随时间变化。\n",
    "\n",
    "这类模型适用于仅考虑钠电流大小、无需关心钠离子浓度随时间变化的情境，常在传统的 Hodgkin-Huxley 型建模中使用。\n",
    "\n",
    "同样，在 `reset_state` 方法中，该模型会将自身的反转电位 `E` 与浓度 `C` 打包为 `IonInfo` 对象，并向所有绑定的 `Channel` 子模块传播，供后者在电流计算中使用。\n",
    "\n",
    "\n"
   ],
   "id": "b0fcd92870a36e07"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
