Source code for braincell.channel.hyperpolarization_activated

# -*- coding: utf-8 -*-
# Copyright 2026 BrainX Ecosystem Limited. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================


"""
This module implements hyperpolarization-activated cation channel.
"""

from typing import Callable, Optional, Union

import brainstate
import braintools
import brainunit as u

from braincell._base import HHTypedNeuron
from braincell.channel._base import Gate, HH, OhmicHH
from braincell.mech import register_channel

__all__ = [
    'HCN_HM1992',
    'HCN1_MA2025_BC',
    'HCN1_MA2024_PC',
    'HCN1_RI2021_SC',
    'HCN1_MA2020_GoC',
    'HCN2_MA2020_GoC',
    'HCN_SU2015_DCN',
    'HCN_ZH2019_IO',
]


@register_channel("HCN_HM1992")
class HCN_HM1992(OhmicHH):
    r"""Hyperpolarization-activated current of Huguenard & McCormick (1992).

    Reproduces the thalamic relay-neuron :math:`I_h` model of
    (Huguenard & McCormick, 1992) [1]_: a single Boltzmann-gated pore
    driven by an ohmic force against a fixed reversal potential.
    Dynamics:

    .. math::

        \begin{aligned}
        I_h &= g_{\mathrm{max}} \, p \, (E - V) \\
        \frac{dp}{dt} &= \phi \frac{p_{\infty} - p}{\tau_p} \\
        p_{\infty} &= \frac{1}{1 + \exp((V + 75) / 5.5)} \\
        \tau_p &= \frac{1}{\exp(-0.086 V - 14.59) +
                  \exp(0.0701 V - 1.87)}
        \end{aligned}

    where :math:`\phi = q_{10}^{(T - T_{\mathrm{ref}}) / 10}` and the
    default ``q10 = 1.0`` makes :math:`\phi \equiv 1` for any ``temp``.

    Parameters
    ----------
    size : brainstate.typing.Size
        Channel state shape.
    g_max : array-like or callable, optional
        Maximal conductance density, default ``10.0 mS/cm2``.
    E : array-like or callable, optional
        Reversal potential, default ``43.0 mV``.
    temp : array-like, optional
        Absolute temperature driving the Q10 factor, default 36
        degrees Celsius.
    q10 : array-like or callable, optional
        Q10 scaling factor for the ``p`` gate, default ``1.0``.
    temp_ref : array-like, optional
        Reference temperature for the Q10 formula, default 36
        degrees Celsius.
    name : str, optional
        Optional channel name.

    Notes
    -----
    This class overrides :meth:`reversal_potential` to return
    ``self.E`` instead of an ion's reversal potential, so the current
    is driven against the fixed ``E`` parameter, not an ion state --
    the correct closed form is ``g_max * p * (E - V)``, not
    ``g_max * p`` alone.

    References
    ----------
    .. [1] Huguenard, J. R., & McCormick, D. A. (1992). Simulation of
           the currents involved in rhythmic oscillations in thalamic
           relay neurons. Journal of Neurophysiology, 68(4), 1373-1383.
           doi:10.1152/jn.1992.68.4.1373
    """

    __module__ = 'braincell.channel'

    root_type = HHTypedNeuron
    gates = (Gate("p", q10="q10", temp_ref="temp_ref"),)

    def __init__(
        self,
        size: brainstate.typing.Size,
        g_max: Union[brainstate.typing.ArrayLike, Callable] = 10.0 * (u.mS / u.cm**2),
        E: Union[brainstate.typing.ArrayLike, Callable] = 43.0 * u.mV,
        temp: brainstate.typing.ArrayLike = u.celsius2kelvin(36.0),
        q10: Union[brainstate.typing.ArrayLike, Callable] = 1.0,
        temp_ref: brainstate.typing.ArrayLike = u.celsius2kelvin(36.0),
        name: Optional[str] = None,
    ):
        super().__init__(size=size, name=name)
        self.g_max = braintools.init.param(g_max, self.varshape, allow_none=False)
        self.E = braintools.init.param(E, self.varshape, allow_none=False)
        self.temp = braintools.init.param(temp, self.varshape, allow_none=False)
        self.q10 = braintools.init.param(q10, self.varshape, allow_none=False)
        self.temp_ref = braintools.init.param(temp_ref, self.varshape, allow_none=False)

[docs] def reversal_potential(self, V, *ions): return self.E
def f_p_inf(self, V): V = V.to_decimal(u.mV) return 1.0 / (1.0 + u.math.exp((V + 75.0) / 5.5)) def f_p_tau(self, V): V = V.to_decimal(u.mV) return 1.0 / (u.math.exp(-0.086 * V - 14.59) + u.math.exp(0.0701 * V - 1.87)) # class Ih_De1996(Channel): # r""" # The hyperpolarization-activated cation current model propsoed by (Destexhe, et al., 1996) [1]_. # # The full kinetic schema was # # .. math:: # # \begin{gathered} # C \underset{\beta(V)}{\stackrel{\alpha(V)}{\rightleftarrows}} O \\ # P_{0}+2 \mathrm{Ca}^{2+} \underset{k_{2}}{\stackrel{k_{1}}{\rightleftarrows}} P_{1} \\ # O+P_{1} \underset{k_{4}}{\rightleftarrows} O_{\mathrm{L}} # \end{gathered} # # where the first reaction represents the voltage-dependent transitions of :math:`I_h` channel # between closed (C) and open (O) forms, with :math:`\alpha` and :math:`\beta` as transition rates. # The second reaction represents the biding of intracellular :math:`\mathrm{Ca^{2+}}` ion to a # regulating factor (:math:`P_0` for unbound and :math:`P_1` for bound) with four binding sites for # calcium and rates of :math:`k_1 = 2.5e^7\, mM^{-4} \, ms^{-1}` and :math:`k_2=4e-4 \, ms^{-1}` # (half-activation of 0.002 mM :math:`Ca^{2+}`). The calcium-bound form :math:`P_1` associates # with the open form of the channel, leading to a locked open form :math:`O_L`, with rates of # :math:`k_3=0.1 \, ms^{-1}` and :math:`k_4 = 0.001 \, ms^{-1}`. # # The current is the proportional to the relative concentration of open channel # # .. math:: # # I_h = g_h (O+g_{inc}O_L) (V - E_h) # # with a maximal conductance of :math:`\bar{g}_{\mathrm{h}}=0.02 \mathrm{mS} / \mathrm{cm}^{2}` # and a reversal potential of :math:`E_{\mathrm{h}}=-40 \mathrm{mV}`. Because of the factor # :math:`g_{\text {inc }}=2`, the conductance of the calcium-bound open state of # :math:`I_{\mathrm{h}}` channel is twice that of the unbound open state. This produces an # augmentation of conductance after the binding of :math:`\mathrm{Ca}^{2+}`, as observed in # sino-atrial cells (Hagiwara and Irisawa 1989). # # The rates of :math:`\alpha` and :math:`\beta` are: # # .. math:: # # & \alpha = m_{\infty} / \tau_m \\ # & \beta = (1-m_{\infty}) / \tau_m \\ # & m_{\infty} = 1/(1+\exp((V+75-V_{sh})/5.5)) \\ # & \tau_m = (5.3 + 267/(\exp((V+71.5-V_{sh})/14.2) + \exp(-(V+89-V_{sh})/11.6))) # # and the temperature regulating factor :math:`\phi=2^{(temp-24)/10}`. # # References # ---------- # .. [1] Destexhe, Alain, et al. "Ionic mechanisms underlying synchronized # oscillations and propagating waves in a model of ferret thalamic # slices." Journal of neurophysiology 76.3 (1996): 2049-2070. # """ # # root_type = Calcium # # def __init__( # self, # size: brainstate.typing.Size, # E: Union[brainstate.typing.ArrayLike, Callable] = -40. * u.mV, # k2: Union[brainstate.typing.ArrayLike, Callable] = 4e-4, # k4: Union[brainstate.typing.ArrayLike, Callable] = 1e-3, # V_sh: Union[brainstate.typing.ArrayLike, Callable] = 0. * u.mV, # g_max: Union[brainstate.typing.ArrayLike, Callable] = 0.02 * (u.mS / u.cm ** 2), # g_inc: Union[brainstate.typing.ArrayLike, Callable] = 2., # Ca_half: Union[brainstate.typing.ArrayLike, Callable] = 2e-3, # temp: brainstate.typing.ArrayLike = 36., # q10_base: brainstate.typing.ArrayLike = 3., # phi: Union[brainstate.typing.ArrayLike, Callable] = None, # name: Optional[str] = None, # mode: Optional[brainstate.mixin.Mode] = None, # ): # super().__init__( # size, # name=name, # mode=mode # ) # # # parameters # self.temp = braintools.init.param(temp, self.varshape, allow_none=False) # self.q10_base = braintools.init.param(q10_base, self.varshape, allow_none=False) # if phi is None: # self.phi = self.q10_base ** ((self.temp - 24.) / 10) # else: # self.phi = braintools.init.param(phi, self.varshape, allow_none=False) # self.E = braintools.init.param(E, self.varshape, allow_none=False) # self.k2 = braintools.init.param(k2, self.varshape, allow_none=False) # self.Ca_half = braintools.init.param(Ca_half, self.varshape, allow_none=False) # self.k1 = self.k2 / self.Ca_half ** 4 # self.k4 = braintools.init.param(k4, self.varshape, allow_none=False) # self.k3 = self.k4 / 0.01 # self.V_sh = braintools.init.param(V_sh, self.varshape, allow_none=False) # self.g_max = braintools.init.param(g_max, self.varshape, allow_none=False) # self.g_inc = braintools.init.param(g_inc, self.varshape, allow_none=False) # # def dO(self, O, t, OL, V): # inf = self.f_inf(V) # tau = self.f_tau(V) # alpha = inf / tau # beta = (1 - inf) / tau # return alpha * (1 - O - OL) - beta * O # # def dOL(self, OL, t, O, P1): # return self.k3 * P1 * O - self.k4 * OL # # def dP1(self, P1, t, C_Ca): # return self.k1 * C_Ca ** 4 * (1 - P1) - self.k2 * P1 # # def update_state(self, V, Ca: IonInfo): # self.O.value, self.OL.value, self.P1.value = self.integral( # self.O.value, self.OL.value, self.P1.value, brainstate.environ.get('t'), V=V, # ) # # def current(self, V, Ca: IonInfo): # return self.g_max * (self.O.value + self.g_inc * self.OL.value) * (self.E - V) # # def init_state(self, V, Ca, batch_size=None): # self.O = state(braintools.init.param(u.math.zeros, self.varshape, batch_size)) # self.OL = state(braintools.init.param(u.math.zeros, self.varshape, batch_size)) # self.P1 = state(braintools.init.param(u.math.zeros, self.varshape, batch_size)) # # def reset_state(self, V, Ca: IonInfo, batch_size=None): # varshape = self.varshape if (batch_size is None) else ((batch_size,) + self.varshape) # k1 = self.k1 * Ca.C ** 4 # self.P1.value = u.math.broadcast_arrays(k1 / (k1 + self.k2), varshape) # inf = self.f_inf(V) # tau = self.f_tau(V) # alpha = inf / tau # beta = (1 - inf) / tau # self.O.value = alpha / (alpha + alpha * self.k3 * self.P1 / self.k4 + beta) # self.OL.value = self.k3 * self.P1.value * self.O.value / self.k4 # # def f_inf(self, V): # V = V.to_decimal(u.mV) # return 1 / (1 + u.math.exp((V + 75 - self.V_sh) / 5.5)) # # def f_tau(self, V): # V = V.to_decimal(u.mV) # return (20. + 1000 / (u.math.exp((V + 71.5 - self.V_sh) / 14.2) + # u.math.exp(-(V + 89 - self.V_sh) / 11.6))) / self.phi @register_channel("HCN1_MA2025_BC") class HCN1_MA2025_BC(OhmicHH): r"""HCN1 h-current imported for the cerebellar basket cell model. Ports the single ``h`` gate NEURON mechanism ``HCN1_MA25_BC.mod`` used in the basket-cell deposit of (Masoli et al., 2025) [3]_. The Boltzmann activation curve and biexponential time constant are the same functional forms used across the ``HCN1_MA2024_PC`` / ``HCN1_RI2021_SC`` siblings; only the model citation differs. .. math:: \begin{aligned} h_\infty &= \frac{1}{1 + \exp\left(\dfrac{V - V_{1/2}} {k}\right)} \\ \tau_h &= \frac{\mathrm{ratetau}}{c \left[ \exp\left(\dfrac{V - V_{\tau 1}}{k_1}\right) + \exp\left(\dfrac{V - V_{\tau 2}}{k_2}\right) \right]} \end{aligned} where :math:`V_{1/2} = V_{\infty,\mathrm{noljp}} - V_{\mathrm{ljp}} = -99.6\ \mathrm{mV}`, :math:`k = 9.67\ \mathrm{mV}`, :math:`V_{\tau 1} = V_{\tau 2} = V_{\tau,\mathrm{noljp}} - V_{\mathrm{ljp}} = -77.3\ \mathrm{mV}`, :math:`k_1 = -22.0\ \mathrm{mV}`, :math:`k_2 = 7.14\ \mathrm{mV}`, :math:`c = 0.0018\ \mathrm{ms^{-1}}`, and :math:`\mathrm{ratetau} = 1.0`. These six constants and ``ratetau`` are fixed internal values set in ``__init__``; they are not exposed as parameters. Parameters ---------- size : brainstate.typing.Size Channel state shape. g_max : array-like or callable, optional Maximal conductance density, default ``0.1 mS/cm2``. E : array-like or callable, optional Reversal potential, default ``-34.4 mV``. temp : array-like, optional Absolute temperature driving the ``h`` gate's Q10 factor (``q10=3.0``, ``temp_ref=37`` degrees Celsius), default 23 degrees Celsius. name : str, optional Optional channel name. See Also -------- HCN1_MA2024_PC : Same kinetics ported for a Purkinje-cell model. HCN1_RI2021_SC : Same kinetics ported for a stellate-cell model. Notes ----- Ported from ``HCN1_MA25_BC.mod``. This class overrides :meth:`reversal_potential` to return ``self.E`` instead of an ion's reversal potential. ``HCN1_MA25_BC.mod`` inherits its comment verbatim from the ``HCN1_MA24_PC.mod`` Purkinje-cell port, including the note "We call it HCN1 as PC express only HCN1 Santoro et al. 2000", whose origin is the subunit-identity paper [2]_ -- a claim about Purkinje cells, not this basket-cell channel, and not repeated here as though it were. The default ``temp = 23`` degrees Celsius is likewise carried over unchanged: Angelo et al. (2007) [1]_ did not report a recording temperature, so 23 degrees Celsius is the porter's assumption, not a value from that paper. References ---------- .. [1] Angelo, K., London, M., Christensen, S. R., & Hausser, M. (2007). Local and global effects of Ih distribution in dendrites of mammalian neurons. The Journal of Neuroscience, 27(32), 8643-8653. doi:10.1523/JNEUROSCI.5284-06.2007 .. [2] Santoro, B., Chen, S., Luthi, A., Pavlidis, P., Shumyatsky, G. P., Tibbs, G. R., & Siegelbaum, S. A. (2000). Molecular and functional heterogeneity of hyperpolarization-activated pacemaker channels in the mouse CNS. The Journal of Neuroscience, 20(14), 5264-5275. doi:10.1523/JNEUROSCI.20-14-05264.2000 .. [3] Masoli, S., Rizza, M. F., Soda, T., Sanchez-Ponce, D., Munoz, A., Prestori, F., & D'Angelo, E. (2025). Cerebellar basket cell filtering of Purkinje cell responses elicited by low frequency parallel fibre transmission. Scientific Reports, 15(1), 25192. doi:10.1038/s41598-025-09964-2 """ __module__ = "braincell.channel" root_type = HHTypedNeuron gates = (Gate("h", q10=3.0, temp_ref=u.celsius2kelvin(37.0)),) def __init__( self, size: brainstate.typing.Size, g_max: Union[brainstate.typing.ArrayLike, Callable] = 0.1 * (u.mS / u.cm**2), E: Union[brainstate.typing.ArrayLike, Callable] = -34.4 * u.mV, temp: brainstate.typing.ArrayLike = u.celsius2kelvin(23.0), name: Optional[str] = None, ): super().__init__(size=size, name=name) self.g_max = braintools.init.param(g_max, self.varshape, allow_none=False) self.E = braintools.init.param(E, self.varshape, allow_none=False) self.temp = braintools.init.param(temp, self.varshape, allow_none=False) self.ratetau = 1.0 self.ljp = 9.3 * u.mV self.v_inf_half_noljp = -90.3 * u.mV self.v_inf_k = 9.67 * u.mV self.v_tau_const = 0.0018 self.v_tau_half1_noljp = -68.0 * u.mV self.v_tau_half2_noljp = -68.0 * u.mV self.v_tau_k1 = -22.0 * u.mV self.v_tau_k2 = 7.14 * u.mV
[docs] def reversal_potential(self, V, *ions): return self.E
def f_h_inf(self, V): V = V.to_decimal(u.mV) v_half = (self.v_inf_half_noljp - self.ljp).to_decimal(u.mV) v_k = self.v_inf_k.to_decimal(u.mV) return 1.0 / (1.0 + u.math.exp((V - v_half) / v_k)) def f_h_tau(self, V): V = V.to_decimal(u.mV) v_half1 = (self.v_tau_half1_noljp - self.ljp).to_decimal(u.mV) v_half2 = (self.v_tau_half2_noljp - self.ljp).to_decimal(u.mV) v_k1 = self.v_tau_k1.to_decimal(u.mV) v_k2 = self.v_tau_k2.to_decimal(u.mV) return self.ratetau / (self.v_tau_const * (u.math.exp((V - v_half1) / v_k1) + u.math.exp((V - v_half2) / v_k2))) @register_channel("HCN1_MA2024_PC") class HCN1_MA2024_PC(OhmicHH): r"""HCN1 h-current imported for the human Purkinje cell model. Ports the single ``h`` gate NEURON mechanism ``HCN1_MA24_PC.mod`` used in the Purkinje-cell deposit of (Masoli et al., 2024) [3]_. The Boltzmann activation curve and biexponential time constant are the same functional forms used across the ``HCN1_MA2025_BC`` / ``HCN1_RI2021_SC`` siblings; only the model citation differs. .. math:: \begin{aligned} h_\infty &= \frac{1}{1 + \exp\left(\dfrac{V - V_{1/2}} {k}\right)} \\ \tau_h &= \frac{\mathrm{ratetau}}{c \left[ \exp\left(\dfrac{V - V_{\tau 1}}{k_1}\right) + \exp\left(\dfrac{V - V_{\tau 2}}{k_2}\right) \right]} \end{aligned} where :math:`V_{1/2} = V_{\infty,\mathrm{noljp}} - V_{\mathrm{ljp}} = -99.6\ \mathrm{mV}`, :math:`k = 9.67\ \mathrm{mV}`, :math:`V_{\tau 1} = V_{\tau 2} = V_{\tau,\mathrm{noljp}} - V_{\mathrm{ljp}} = -77.3\ \mathrm{mV}`, :math:`k_1 = -22.0\ \mathrm{mV}`, :math:`k_2 = 7.14\ \mathrm{mV}`, :math:`c = 0.0018\ \mathrm{ms^{-1}}`, and :math:`\mathrm{ratetau} = 1.0`. These six constants and ``ratetau`` are fixed internal values set in ``__init__``; they are not exposed as parameters. Parameters ---------- size : brainstate.typing.Size Channel state shape. g_max : array-like or callable, optional Maximal conductance density, default ``0.1 mS/cm2``. E : array-like or callable, optional Reversal potential, default ``-34.4 mV``. temp : array-like, optional Absolute temperature driving the ``h`` gate's Q10 factor (``q10=3.0``, ``temp_ref=37`` degrees Celsius), default 23 degrees Celsius. name : str, optional Optional channel name. See Also -------- HCN1_MA2025_BC : Same kinetics ported for a basket-cell model. HCN1_RI2021_SC : Same kinetics ported for a stellate-cell model. Notes ----- Ported from ``HCN1_MA24_PC.mod``. This class overrides :meth:`reversal_potential` to return ``self.E`` instead of an ion's reversal potential. ``HCN1_MA24_PC.mod`` carries the comment "We call it HCN1 as PC express only HCN1 Santoro et al. 2000" -- correctly describing this Purkinje-cell channel, and the origin of that "PC" claim is the subunit-identity paper [2]_, not the kinetics paper [1]_. The default ``temp = 23`` degrees Celsius is carried over unchanged from the ``.mod`` file: Angelo et al. (2007) [1]_ did not report a recording temperature, so 23 degrees Celsius is the porter's assumption, not a value from that paper. References ---------- .. [1] Angelo, K., London, M., Christensen, S. R., & Hausser, M. (2007). Local and global effects of Ih distribution in dendrites of mammalian neurons. The Journal of Neuroscience, 27(32), 8643-8653. doi:10.1523/JNEUROSCI.5284-06.2007 .. [2] Santoro, B., Chen, S., Luthi, A., Pavlidis, P., Shumyatsky, G. P., Tibbs, G. R., & Siegelbaum, S. A. (2000). Molecular and functional heterogeneity of hyperpolarization-activated pacemaker channels in the mouse CNS. The Journal of Neuroscience, 20(14), 5264-5275. doi:10.1523/JNEUROSCI.20-14-05264.2000 .. [3] Masoli, S., Sanchez-Ponce, D., Vrieler, N., Abu-Haya, K., Lerner, V., Shahar, T., Nedelescu, H., Rizza, M. F., Benavides-Piccione, R., DeFelipe, J., Yarom, Y., Munoz, A., & D'Angelo, E. (2024). Human Purkinje cells outperform mouse Purkinje cells in dendritic complexity and computational capacity. Communications Biology, 7(1), 5. doi:10.1038/s42003-023-05689-y """ __module__ = "braincell.channel" root_type = HHTypedNeuron gates = (Gate("h", q10=3.0, temp_ref=u.celsius2kelvin(37.0)),) def __init__( self, size: brainstate.typing.Size, g_max: Union[brainstate.typing.ArrayLike, Callable] = 0.1 * (u.mS / u.cm**2), E: Union[brainstate.typing.ArrayLike, Callable] = -34.4 * u.mV, temp: brainstate.typing.ArrayLike = u.celsius2kelvin(23.0), name: Optional[str] = None, ): super().__init__(size=size, name=name) self.g_max = braintools.init.param(g_max, self.varshape, allow_none=False) self.E = braintools.init.param(E, self.varshape, allow_none=False) self.temp = braintools.init.param(temp, self.varshape, allow_none=False) self.ratetau = 1.0 self.ljp = 9.3 * u.mV self.v_inf_half_noljp = -90.3 * u.mV self.v_inf_k = 9.67 * u.mV self.v_tau_const = 0.0018 self.v_tau_half1_noljp = -68.0 * u.mV self.v_tau_half2_noljp = -68.0 * u.mV self.v_tau_k1 = -22.0 * u.mV self.v_tau_k2 = 7.14 * u.mV
[docs] def reversal_potential(self, V, *ions): return self.E
def f_h_inf(self, V): V = V.to_decimal(u.mV) v_half = (self.v_inf_half_noljp - self.ljp).to_decimal(u.mV) v_k = self.v_inf_k.to_decimal(u.mV) return 1.0 / (1.0 + u.math.exp((V - v_half) / v_k)) def f_h_tau(self, V): V = V.to_decimal(u.mV) v_half1 = (self.v_tau_half1_noljp - self.ljp).to_decimal(u.mV) v_half2 = (self.v_tau_half2_noljp - self.ljp).to_decimal(u.mV) v_k1 = self.v_tau_k1.to_decimal(u.mV) v_k2 = self.v_tau_k2.to_decimal(u.mV) return self.ratetau / (self.v_tau_const * (u.math.exp((V - v_half1) / v_k1) + u.math.exp((V - v_half2) / v_k2))) @register_channel("HCN1_RI2021_SC") class HCN1_RI2021_SC(OhmicHH): r"""HCN1 h-current imported for the cerebellar stellate cell model. Ports the single ``h`` gate NEURON mechanism ``HCN1_RI21_SC.mod`` used in the stellate-cell deposit of (Rizza et al., 2021) [3]_. The Boltzmann activation curve and biexponential time constant are the same functional forms used across the ``HCN1_MA2025_BC`` / ``HCN1_MA2024_PC`` siblings; only the model citation differs. .. math:: \begin{aligned} h_\infty &= \frac{1}{1 + \exp\left(\dfrac{V - V_{1/2}} {k}\right)} \\ \tau_h &= \frac{\mathrm{ratetau}}{c \left[ \exp\left(\dfrac{V - V_{\tau 1}}{k_1}\right) + \exp\left(\dfrac{V - V_{\tau 2}}{k_2}\right) \right]} \end{aligned} where :math:`V_{1/2} = V_{\infty,\mathrm{noljp}} - V_{\mathrm{ljp}} = -99.6\ \mathrm{mV}`, :math:`k = 9.67\ \mathrm{mV}`, :math:`V_{\tau 1} = V_{\tau 2} = V_{\tau,\mathrm{noljp}} - V_{\mathrm{ljp}} = -77.3\ \mathrm{mV}`, :math:`k_1 = -22.0\ \mathrm{mV}`, :math:`k_2 = 7.14\ \mathrm{mV}`, :math:`c = 0.0018\ \mathrm{ms^{-1}}`, and :math:`\mathrm{ratetau} = 1.0`. These six constants and ``ratetau`` are fixed internal values set in ``__init__``; they are not exposed as parameters. Parameters ---------- size : brainstate.typing.Size Channel state shape. g_max : array-like or callable, optional Maximal conductance density, default ``0.1 mS/cm2``. E : array-like or callable, optional Reversal potential, default ``-34.4 mV``. temp : array-like, optional Absolute temperature driving the ``h`` gate's Q10 factor (``q10=3.0``, ``temp_ref=37`` degrees Celsius), default 23 degrees Celsius. name : str, optional Optional channel name. See Also -------- HCN1_MA2025_BC : Same kinetics ported for a basket-cell model. HCN1_MA2024_PC : Same kinetics ported for a Purkinje-cell model. Notes ----- Ported from ``HCN1_RI21_SC.mod``. This class overrides :meth:`reversal_potential` to return ``self.E`` instead of an ion's reversal potential. ``HCN1_RI21_SC.mod`` carries the same inherited comment as the basket-cell port, "We call it HCN1 as PC express only HCN1 Santoro et al. 2000" [2]_ -- a claim about Purkinje cells, not this stellate-cell channel, and not repeated here as though it were. The default ``temp = 23`` degrees Celsius is carried over unchanged from the ``.mod`` file: Angelo et al. (2007) [1]_ did not report a recording temperature, so 23 degrees Celsius is the porter's assumption, not a value from that paper. References ---------- .. [1] Angelo, K., London, M., Christensen, S. R., & Hausser, M. (2007). Local and global effects of Ih distribution in dendrites of mammalian neurons. The Journal of Neuroscience, 27(32), 8643-8653. doi:10.1523/JNEUROSCI.5284-06.2007 .. [2] Santoro, B., Chen, S., Luthi, A., Pavlidis, P., Shumyatsky, G. P., Tibbs, G. R., & Siegelbaum, S. A. (2000). Molecular and functional heterogeneity of hyperpolarization-activated pacemaker channels in the mouse CNS. The Journal of Neuroscience, 20(14), 5264-5275. doi:10.1523/JNEUROSCI.20-14-05264.2000 .. [3] Rizza, M. F., Locatelli, F., Masoli, S., Sanchez-Ponce, D., Munoz, A., Prestori, F., & D'Angelo, E. (2021). Stellate cell computational modeling predicts signal filtering in the molecular layer circuit of cerebellum. Scientific Reports, 11(1), 3873. doi:10.1038/s41598-021-83209-w """ __module__ = "braincell.channel" root_type = HHTypedNeuron gates = (Gate("h", q10=3.0, temp_ref=u.celsius2kelvin(37.0)),) def __init__( self, size: brainstate.typing.Size, g_max: Union[brainstate.typing.ArrayLike, Callable] = 0.1 * (u.mS / u.cm**2), E: Union[brainstate.typing.ArrayLike, Callable] = -34.4 * u.mV, temp: brainstate.typing.ArrayLike = u.celsius2kelvin(23.0), name: Optional[str] = None, ): super().__init__(size=size, name=name) self.g_max = braintools.init.param(g_max, self.varshape, allow_none=False) self.E = braintools.init.param(E, self.varshape, allow_none=False) self.temp = braintools.init.param(temp, self.varshape, allow_none=False) self.ratetau = 1.0 self.ljp = 9.3 * u.mV self.v_inf_half_noljp = -90.3 * u.mV self.v_inf_k = 9.67 * u.mV self.v_tau_const = 0.0018 self.v_tau_half1_noljp = -68.0 * u.mV self.v_tau_half2_noljp = -68.0 * u.mV self.v_tau_k1 = -22.0 * u.mV self.v_tau_k2 = 7.14 * u.mV
[docs] def reversal_potential(self, V, *ions): return self.E
def f_h_inf(self, V): V = V.to_decimal(u.mV) v_half = (self.v_inf_half_noljp - self.ljp).to_decimal(u.mV) v_k = self.v_inf_k.to_decimal(u.mV) return 1.0 / (1.0 + u.math.exp((V - v_half) / v_k)) def f_h_tau(self, V): V = V.to_decimal(u.mV) v_half1 = (self.v_tau_half1_noljp - self.ljp).to_decimal(u.mV) v_half2 = (self.v_tau_half2_noljp - self.ljp).to_decimal(u.mV) v_k1 = self.v_tau_k1.to_decimal(u.mV) v_k2 = self.v_tau_k2.to_decimal(u.mV) return self.ratetau / (self.v_tau_const * (u.math.exp((V - v_half1) / v_k1) + u.math.exp((V - v_half2) / v_k2))) @register_channel("HCN1_MA2020_GoC") class HCN1_MA2020_GoC(HH): r"""HCN1 fast/slow h-current imported for the Golgi cell model. Ports the two-gate NEURON mechanism ``HCN1_MA20_GoC.mod`` used in the Golgi-cell deposit of (Masoli et al., 2020) [3]_. Two independent open-state gates, ``o_fast`` and ``o_slow``, share one Boltzmann steady state split by a linear mixing fraction ``r(V)``: .. math:: \begin{aligned} I_h &= \phi_Q \, g_{\mathrm{max}} \, (o_{\mathrm{fast}} + o_{\mathrm{slow}}) \, (E - V) \\ o_\infty(V) &= \frac{1}{1 + \exp((V - E_{1/2}) \, c)} \\ r(V) &= r_A V + r_B \\ o_{\mathrm{fast},\infty} &= r(V) \, o_\infty(V) \\ o_{\mathrm{slow},\infty} &= (1 - r(V)) \, o_\infty(V) \\ \tau_{\mathrm{fast}} &= \exp((t_{Cf} V - t_{Df}) \, t_{Ef}) \\ \tau_{\mathrm{slow}} &= \exp((t_{Cs} V - t_{Ds}) \, t_{Es}) \end{aligned} with :math:`\phi_Q = Q_{10}^{(T - 23^{\circ}\mathrm{C}) / 10}`, :math:`E_{1/2} = -72.49\ \mathrm{mV}`, :math:`c = 0.11305\ \mathrm{mV^{-1}}`, :math:`r_A = 0.002096\ \mathrm{mV^{-1}}`, :math:`r_B = 0.97596`, :math:`t_{Cf} = 0.01371\ \mathrm{mV^{-1}}`, :math:`t_{Df} = -3.368`, :math:`t_{Ef} = 2.30259`, :math:`t_{Cs} = 0.01451\ \mathrm{mV^{-1}}`, :math:`t_{Ds} = -4.056`, :math:`t_{Es} = 2.30259`, and :math:`Q_{10} = 1.5`. ``r(V)`` is not clamped for this isoform, unlike ``HCN2_MA2020_GoC``. Both gates additionally carry ``q10=3.0``, ``temp_ref=23`` degrees Celsius on their own state relaxation, independent of the :math:`\phi_Q` conductance prefactor above. All eleven constants are fixed internal values set in ``__init__``; they are not exposed as parameters. This class subclasses :class:`HH` directly, not :class:`OhmicHH`, because :meth:`current` sums two gate values before applying the driving force rather than taking a single ``power``-weighted product. Parameters ---------- size : brainstate.typing.Size Channel state shape. g_max : array-like or callable, optional Maximal conductance density, default ``0.05 mS/cm2``. E : array-like or callable, optional Reversal potential, default ``-20.0 mV``. temp : array-like, optional Absolute temperature driving both the gate Q10 factors and :math:`\phi_Q`, default 22 degrees Celsius. name : str, optional Optional channel name. See Also -------- HCN2_MA2020_GoC : Companion isoform with a clamped ``r(V)``. Notes ----- Ported from ``HCN1_MA20_GoC.mod``. The former NEURON ``TABLE`` tabulated ``o_fast_inf``, ``o_slow_inf``, ``tau_f`` and ``tau_s`` over ``[-100, 30] mV`` and clamped outside that range; BrainCell evaluates the continuous formulas above at every call instead, so values outside ``[-100, 30] mV`` are expected to diverge from the original NEURON boundary-clamped output. ``.mod`` writes the time-constant exponent constants ``tEf`` and ``tEs`` as ``2.302585092``; NEURON's compiled default rounds this to ``2.30259``, and BrainCell follows the compiled value rather than the ``.mod`` source text. ``HCN1_MA20_GoC.mod`` credits its kinetics data to "Santoro et al. J Neurosci. 2000" [2]_; the Boltzmann/exponential functional forms trace to the cerebellar Golgi cell model of Solinas et al. (2007) [1]_. References ---------- .. [1] Solinas, S., Forti, L., Cesana, E., Mapelli, J., De Schutter, E., & D'Angelo, E. (2007). Computational reconstruction of pacemaking and intrinsic electroresponsiveness in cerebellar Golgi cells. Frontiers in Cellular Neuroscience, 1, 2. doi:10.3389/neuro.03.002.2007 .. [2] Santoro, B., Chen, S., Luthi, A., Pavlidis, P., Shumyatsky, G. P., Tibbs, G. R., & Siegelbaum, S. A. (2000). Molecular and functional heterogeneity of hyperpolarization-activated pacemaker channels in the mouse CNS. The Journal of Neuroscience, 20(14), 5264-5275. doi:10.1523/JNEUROSCI.20-14-05264.2000 .. [3] Masoli, S., Ottaviani, A., Casali, S., & D'Angelo, E. (2020). Cerebellar Golgi cell models predict dendritic processing and mechanisms of synaptic plasticity. PLOS Computational Biology, 16(12), e1007937. doi:10.1371/journal.pcbi.1007937 """ __module__ = "braincell.channel" root_type = HHTypedNeuron gates = ( Gate("o_fast", q10=3.0, temp_ref=u.celsius2kelvin(23.0)), Gate("o_slow", q10=3.0, temp_ref=u.celsius2kelvin(23.0)), ) def __init__( self, size: brainstate.typing.Size, g_max: Union[brainstate.typing.ArrayLike, Callable] = 0.05 * (u.mS / u.cm**2), E: Union[brainstate.typing.ArrayLike, Callable] = -20.0 * u.mV, temp: brainstate.typing.ArrayLike = u.celsius2kelvin(22.0), name: Optional[str] = None, ): super().__init__(size=size, name=name) self.g_max = braintools.init.param(g_max, self.varshape, allow_none=False) self.E = braintools.init.param(E, self.varshape, allow_none=False) self.temp = braintools.init.param(temp, self.varshape, allow_none=False) self.Q10_diff = 1.5 self.Ehalf = -72.49 self.c = 0.11305 self.rA = 0.002096 self.rB = 0.97596 self.tCf = 0.01371 self.tDf = -3.368 self.tEf = 2.30259 self.tCs = 0.01451 self.tDs = -4.056 self.tEs = 2.30259
[docs] def current(self, V): o = self.o_fast.value + self.o_slow.value return self._gbar_phi() * self.g_max * o * (self.E - V)
def _gbar_phi(self): temp_ref = u.celsius2kelvin(23.0) return self.Q10_diff ** (((self.temp - temp_ref) / u.kelvin) / 10.0) def o_inf(self, V): V = V.to_decimal(u.mV) return 1.0 / (1.0 + u.math.exp((V - self.Ehalf) * self.c)) def r(self, V): V = V.to_decimal(u.mV) return self.rA * V + self.rB def f_o_fast_inf(self, V): return self.r(V) * self.o_inf(V) def f_o_slow_inf(self, V): return (1.0 - self.r(V)) * self.o_inf(V) def f_o_fast_tau(self, V): V = V.to_decimal(u.mV) return u.math.exp(((self.tCf * V) - self.tDf) * self.tEf) def f_o_slow_tau(self, V): V = V.to_decimal(u.mV) return u.math.exp(((self.tCs * V) - self.tDs) * self.tEs) @register_channel("HCN2_MA2020_GoC") class HCN2_MA2020_GoC(HH): r"""HCN2 fast/slow h-current imported for the Golgi cell model. Ports the two-gate NEURON mechanism ``HCN2_MA20_GoC.mod`` used in the Golgi-cell deposit of (Masoli et al., 2020) [3]_. Two independent open-state gates, ``o_fast`` and ``o_slow``, share one Boltzmann steady state split by a mixing fraction ``r(V)`` that is linear only inside a clamped voltage window: .. math:: \begin{aligned} I_h &= \phi_Q \, g_{\mathrm{max}} \, (o_{\mathrm{fast}} + o_{\mathrm{slow}}) \, (E - V) \\ o_\infty(V) &= \frac{1}{1 + \exp((V - E_{1/2}) \, c)} \\ r(V) &= \begin{cases} 0 & V \geq -64.70\ \mathrm{mV} \\ 1 & V \leq -108.70\ \mathrm{mV} \\ r_A V + r_B & \text{otherwise} \end{cases} \\ o_{\mathrm{fast},\infty} &= r(V) \, o_\infty(V) \\ o_{\mathrm{slow},\infty} &= (1 - r(V)) \, o_\infty(V) \\ \tau_{\mathrm{fast}} &= \exp((t_{Cf} V - t_{Df}) \, t_{Ef}) \\ \tau_{\mathrm{slow}} &= \exp((t_{Cs} V - t_{Ds}) \, t_{Es}) \end{aligned} with :math:`\phi_Q = Q_{10}^{(T - 23^{\circ}\mathrm{C}) / 10}`, :math:`E_{1/2} = -81.95\ \mathrm{mV}`, :math:`c = 0.1661\ \mathrm{mV^{-1}}`, :math:`r_A = -0.0227\ \mathrm{mV^{-1}}`, :math:`r_B = -1.4694`, :math:`t_{Cf} = 0.0269\ \mathrm{mV^{-1}}`, :math:`t_{Df} = -5.6111`, :math:`t_{Ef} = 2.3026`, :math:`t_{Cs} = 0.0152\ \mathrm{mV^{-1}}`, :math:`t_{Ds} = -5.2944`, :math:`t_{Es} = 2.3026`, and :math:`Q_{10} = 1.5`. Both gates additionally carry ``q10=3.0``, ``temp_ref=23`` degrees Celsius on their own state relaxation, independent of the :math:`\phi_Q` conductance prefactor above. All eleven constants are fixed internal values set in ``__init__``; they are not exposed as parameters. This class subclasses :class:`HH` directly, not :class:`OhmicHH`, because :meth:`current` sums two gate values before applying the driving force rather than taking a single ``power``-weighted product. Parameters ---------- size : brainstate.typing.Size Channel state shape. g_max : array-like or callable, optional Maximal conductance density, default ``0.08 mS/cm2``. E : array-like or callable, optional Reversal potential, default ``-20.0 mV``. temp : array-like, optional Absolute temperature driving both the gate Q10 factors and :math:`\phi_Q`, default 22 degrees Celsius. name : str, optional Optional channel name. See Also -------- HCN1_MA2020_GoC : Companion isoform with an unclamped ``r(V)``. Notes ----- Ported from ``HCN2_MA20_GoC.mod``. The former NEURON ``TABLE`` tabulated ``o_fast_inf``, ``o_slow_inf``, ``tau_f`` and ``tau_s`` over ``[-100, 30] mV`` and clamped outside that range; BrainCell evaluates the continuous formulas above at every call instead, so values outside ``[-100, 30] mV`` are expected to diverge from the original NEURON boundary-clamped output. The explicit ``r(V)`` clamp to ``{0, 1}`` above ``-64.70 mV`` / below ``-108.70 mV`` is reproduced directly in :meth:`r`, independent of the removed ``TABLE`` boundary clamp. ``HCN2_MA20_GoC.mod`` credits its kinetics data to "Santoro et al. J Neurosci. 2000" [2]_; the Boltzmann/exponential functional forms trace to the cerebellar Golgi cell model of Solinas et al. (2007) [1]_. References ---------- .. [1] Solinas, S., Forti, L., Cesana, E., Mapelli, J., De Schutter, E., & D'Angelo, E. (2007). Computational reconstruction of pacemaking and intrinsic electroresponsiveness in cerebellar Golgi cells. Frontiers in Cellular Neuroscience, 1, 2. doi:10.3389/neuro.03.002.2007 .. [2] Santoro, B., Chen, S., Luthi, A., Pavlidis, P., Shumyatsky, G. P., Tibbs, G. R., & Siegelbaum, S. A. (2000). Molecular and functional heterogeneity of hyperpolarization-activated pacemaker channels in the mouse CNS. The Journal of Neuroscience, 20(14), 5264-5275. doi:10.1523/JNEUROSCI.20-14-05264.2000 .. [3] Masoli, S., Ottaviani, A., Casali, S., & D'Angelo, E. (2020). Cerebellar Golgi cell models predict dendritic processing and mechanisms of synaptic plasticity. PLOS Computational Biology, 16(12), e1007937. doi:10.1371/journal.pcbi.1007937 """ __module__ = "braincell.channel" root_type = HHTypedNeuron gates = ( Gate("o_fast", q10=3.0, temp_ref=u.celsius2kelvin(23.0)), Gate("o_slow", q10=3.0, temp_ref=u.celsius2kelvin(23.0)), ) def __init__( self, size: brainstate.typing.Size, g_max: Union[brainstate.typing.ArrayLike, Callable] = 0.08 * (u.mS / u.cm**2), E: Union[brainstate.typing.ArrayLike, Callable] = -20.0 * u.mV, temp: brainstate.typing.ArrayLike = u.celsius2kelvin(22.0), name: Optional[str] = None, ): super().__init__(size=size, name=name) self.g_max = braintools.init.param(g_max, self.varshape, allow_none=False) self.E = braintools.init.param(E, self.varshape, allow_none=False) self.temp = braintools.init.param(temp, self.varshape, allow_none=False) self.Q10_diff = 1.5 self.Ehalf = -81.95 self.c = 0.1661 self.rA = -0.0227 self.rB = -1.4694 self.tCf = 0.0269 self.tDf = -5.6111 self.tEf = 2.3026 self.tCs = 0.0152 self.tDs = -5.2944 self.tEs = 2.3026
[docs] def current(self, V): o = self.o_fast.value + self.o_slow.value return self._gbar_phi() * self.g_max * o * (self.E - V)
def _gbar_phi(self): temp_ref = u.celsius2kelvin(23.0) return self.Q10_diff ** (((self.temp - temp_ref) / u.kelvin) / 10.0) def o_inf(self, V): V = V.to_decimal(u.mV) return 1.0 / (1.0 + u.math.exp((V - self.Ehalf) * self.c)) def r(self, V): V = V.to_decimal(u.mV) return u.math.where( V >= -64.70, 0.0, u.math.where( V <= -108.70, 1.0, self.rA * V + self.rB, ), ) def f_o_fast_inf(self, V): return self.r(V) * self.o_inf(V) def f_o_slow_inf(self, V): return (1.0 - self.r(V)) * self.o_inf(V) def f_o_fast_tau(self, V): V = V.to_decimal(u.mV) return u.math.exp(((self.tCf * V) - self.tDf) * self.tEf) def f_o_slow_tau(self, V): V = V.to_decimal(u.mV) return u.math.exp(((self.tCs * V) - self.tDs) * self.tEs) @register_channel("HCN_SU2015_DCN") class HCN_SU2015_DCN(OhmicHH): r"""H-current imported for the deep cerebellar nucleus (DCN) model. Ports the single ``m`` gate (power 2) NEURON mechanism ``HCN_SU15_DCN.mod`` used in the deep-cerebellar-nucleus deposit of (Sudhakar et al., 2015) [2]_. .. math:: \begin{aligned} I_h &= g_{\mathrm{max}} \, m^2 \, (E - V) \\ m_\infty &= \frac{1}{1 + \exp((V + 80) / 5)} \\ \tau_m &= \frac{400}{\mathrm{qdeltat}} \end{aligned} :math:`\tau_m` is a voltage-independent constant, not a function of :math:`V`; ``qdeltat`` is a fixed internal value (default ``1.0``) set in ``__init__`` and is not exposed as a parameter. Parameters ---------- size : brainstate.typing.Size Channel state shape. g_max : array-like or callable, optional Maximal conductance density, default ``0.01 mS/cm2``. E : array-like or callable, optional Reversal potential, default ``-45.0 mV``. name : str, optional Optional channel name. Notes ----- This class overrides :meth:`reversal_potential` to return ``self.E`` instead of an ion's reversal potential. The ``m`` gate carries no ``q10``/``phi``, so :meth:`HH.gate_phi` resolves to the default ``1.0``. Ported from ``HCN_SU15_DCN.mod``. Its kinetics belong to the deep cerebellar nucleus model of Steuber et al. (2011) [1]_, translated from GENESIS to NEURON by Luthman et al. (2011), and used in Sudhakar et al. (2015) [2]_. ``HCN`` is one of only four mechanism names (with ``CaLVA``, ``NaP`` and ``SK``) that occur as strings in the text of [2]_; the paper does not, however, print the Boltzmann or time constants above for any mechanism -- those are established only by direct comparison against the ``.mod`` source, not by a per-mechanism statement in either paper. :meth:`f_m_tau` returns the constant ``400.0 / qdeltat`` (400 ms by default), a genuine, finite, voltage-independent time constant -- the gate is **not** instantaneous. The former NEURON ``TABLE`` directive tabulated only ``minf`` over ``[-150, 100] mV``; ``taum`` was never tabulated because it does not depend on voltage, not because it is zero or absent. References ---------- .. [1] Steuber, V., Schultheiss, N. W., Silver, R. A., De Schutter, E., & Jaeger, D. (2011). Determinants of synaptic integration and heterogeneity in rebound firing explored with data-driven models of deep cerebellar nucleus cells. Journal of Computational Neuroscience, 30(3), 633-658. doi:10.1007/s10827-010-0282-z .. [2] Sudhakar, S. K., Torben-Nielsen, B., & De Schutter, E. (2015). Cerebellar nuclear neurons use time and rate coding to transmit Purkinje neuron pauses. PLOS Computational Biology, 11(12), e1004641. doi:10.1371/journal.pcbi.1004641 """ __module__ = "braincell.channel" root_type = HHTypedNeuron gates = (Gate("m", power=2),) def __init__( self, size: brainstate.typing.Size, g_max: Union[brainstate.typing.ArrayLike, Callable] = 0.01 * (u.mS / u.cm**2), E: Union[brainstate.typing.ArrayLike, Callable] = -45.0 * u.mV, name: Optional[str] = None, ): super().__init__(size=size, name=name) self.g_max = braintools.init.param(g_max, self.varshape, allow_none=False) self.E = braintools.init.param(E, self.varshape, allow_none=False) self.qdeltat = 1.0
[docs] def reversal_potential(self, V, *ions): return self.E
def f_m_inf(self, V): V = V.to_decimal(u.mV) return 1.0 / (1.0 + u.math.exp((V + 80.0) / 5.0)) def f_m_tau(self, V): return 400.0 / self.qdeltat @register_channel("HCN_ZH2019_IO") class HCN_ZH2019_IO(OhmicHH): r"""Inferior olive somatic h-current, imported from ``HCN_ZH19_IO.mod``. A single-gate hyperpolarization-activated current for the single-compartment inferior olive somatic model of Zhang & Santaniello (2019) [2]_. The gating kinetics originate in the inferior olive compartmental model of Schweighofer, Doya, & Kawato (1999) [1]_ and reached this class through the NEURON port of Torben-Nielsen, Segev, & Yarom (2012) (see Notes). Parameters ---------- size : brainstate.typing.Size Channel state shape. g_max : array-like or callable, optional Maximum conductance, default ``0.15 mS/cm2``. E : array-like or callable, optional Fixed reversal potential used in place of an ion-derived driving force, default ``-43.0 mV``. name : str, optional Optional channel name. Notes ----- The current is .. math:: I_h = g_{max} \, q \, (E - V) with the single gate ``q`` following .. math:: q_\infty(V) = \frac{1}{1 + \exp\left(\dfrac{V + 75\ \text{mV}}{5.5\ \text{mV}}\right)} .. math:: \tau_q(V) = \frac{1}{\exp(-0.086\,V/\text{mV} - 14.6) + \exp(0.07\,V/\text{mV} - 1.87)}\ \text{ms} ``q`` carries no ``phi``/``q10`` in its :class:`~braincell.channel._base.Gate` declaration, so :meth:`~braincell.channel._base.HH.gate_phi` resolves to the default ``1.0`` and neither rate method is temperature-scaled. This mechanism is ported from ``IO/channel/HCN_ZH19_IO.mod``, whose header credits "Somatic h channel from Schweighofer et al., 1999" and porter "Xu Zhang @ UConn, 6-22-2018". The inferior olive neurons modelled by Zhang & Santaniello (2019) [2]_ are **single-compartment** (``nseg = 1``); this class must not be described as part of a multi-compartment inferior olive mechanism. In the source `.mod` file the kinetics originate with Schweighofer, Doya, & Kawato (1999) [1]_ and reached ``HCN_ZH19_IO.mod`` through the intermediate NEURON port of Torben-Nielsen, Segev, & Yarom (2012), credited in the header as "B. Torben-Nielsen @ HUJI" on the sibling `Na`/`Kdr`/`Ca` files of the same deposit. **Import deviation.** In the upstream `.mod` file the ``rates(v)`` call that refreshes ``q_inf``/``tau_q`` lives inside ``BREAKPOINT``; in this deposit's ``HCN_ZH19_IO.mod`` it was relocated into ``DERIVATIVE states``, so the rates are refreshed *before* the ``cnexp`` state update rather than after it. This is a semantic change, not a cosmetic one -- the only other difference from the upstream file is the ``SUFFIX`` rename, and the ``COMMENT`` header is otherwise untouched. References ---------- .. [1] Schweighofer, N., Doya, K., & Kawato, M. (1999). Electrophysiological properties of inferior olive neurons: A compartmental model. Journal of Neurophysiology, 82(2), 804-817. doi:10.1152/jn.1999.82.2.804 .. [2] Zhang, X., & Santaniello, S. (2019). Role of cerebellar GABAergic dysfunctions in the origins of essential tremor. Proceedings of the National Academy of Sciences of the United States of America, 116(27), 13592-13601. doi:10.1073/pnas.1817689116 """ __module__ = "braincell.channel" root_type = HHTypedNeuron gates = (Gate("q"),) def __init__( self, size: brainstate.typing.Size, g_max: Union[brainstate.typing.ArrayLike, Callable] = 0.15 * (u.mS / u.cm**2), E: Union[brainstate.typing.ArrayLike, Callable] = -43.0 * u.mV, name: Optional[str] = None, ): super().__init__(size=size, name=name) self.g_max = braintools.init.param(g_max, self.varshape, allow_none=False) self.E = braintools.init.param(E, self.varshape, allow_none=False)
[docs] def reversal_potential(self, V, *ions): return self.E
def f_q_inf(self, V): V = V.to_decimal(u.mV) return 1.0 / (1.0 + u.math.exp((V + 75.0) / 5.5)) def f_q_tau(self, V): V = V.to_decimal(u.mV) return 1.0 / (u.math.exp(-0.086 * V - 14.6) + u.math.exp(0.07 * V - 1.87))