Table
objects, I see this error “ValueError: x and y must have same first dimension, but have shapes ...
”. What is the problem?length
and diameter
of a Compartment
update its membrane resistance Rm
and capacitance Cm
fields?Ra
in a Compartment
?HH
in HHChannel
, HHGate
, etc. stand for?HHChannel
?HHGate.setupAlpha()
or HHGate.setupTau()
for setting up the lookup tables of an HHGate
object?HHGate
?HHGates
when using an HHChannel
?moose.le('/classes')
help(moose.{classname})
and moose.doc('{classname}')
in Python.Here {classname}
should be replaced by the name of the class you want to know about.
For example, to learn more about the Compartment
class you can run either of the following code snippets:
import moose
moose.doc('Compartment')
or
import moose
help(moose.Compartment)
moose.doc('{classname}.{fieldname}')
Experimentalists use different units for different quantities for convenience. These often get mixed up in computational models and can produce unexpected results due to inconsistent units. The physiological unit system uses for membrane potential, for time. Now, if you express membrane capacitance in , your membrane resistance must be in in to get consistent time course in your simulation. This is because only then your membrane time constant () will be in . But then your currents would be in ().
Another source of frustration is that dimensions of neurons are usually expressed in . But conveniently, the specific capacitance of cell membrane is close to . So if you are trying to set the absolute capacitance of a compartment based on this, you must convert its length and diameter to first and compute the surface area in .
wildcardFind
in the form moose.wildcardFind('{root}/#[TYPE={typename}]')
where root
is the element under which to search.Example: You loaded the Kholodenko 2000 model as '/Kholodenko'
, then the container for the chemicals and reactions is '/Kholodenko/kinetics/MAPK'
. You want to search for elements of type Pool
(which represents a pool of molecules or ions) directly under MAPK
.
In [19]: moose.wildcardFind('/Kholodenko/kinetics[0]/MAPK[0]/#[TYPE==Pool]')
Out[19]: [<moose.Reac id=521 dataIndex=0 path=/Kholodenko[0]/kinetics[0]/MAPK[0]/Neg_feedback[0]>]
This returns a list of elements of type Pool
that are children of /Kholodenko/kinetics/MAPK
. But not its grand children or beyond.
wildcardFind
in the form moose.wildcardFind('{root}/##[TYPE={typename}]')
Example: In the Kholodenko 2000 model you want to search for elements of type Pool
(which represents a pool of molecules or ions) you loaded the model as "/Kholodenko\"
, then
In [19]: moose.wildcardFind('/Kholodenko/##[TYPE==Pool]')
Out[19]: [<moose.Reac id=521 dataIndex=0 path=/Kholodenko[0]/kinetics[0]/MAPK[0]/Neg_feedback[0]>]
The ##
here tells wildcardFind
to do a recursive seach, i.e., starting at {root}
, look through its children, grand children, all the way down to the leaves of the element tree.
wildcardFind
in the form moose.wildcardFind('{root}/##[FIELD(name)={name}]')
This always returns a list of elements. If the name is unique under root, it will be a list with a single element. If there are multiple elements with the same name, this will return a list containing all those elements.
Example: In the Kholodenko 2000 model you want to search for the element "Neg_feedback"
, and you loaded the model as "/Kholodenko\"
, then
In [19]: moose.wildcardFind('/Kholodenko/##[FIELD(name)==Neg_feedback]')
Out[19]: [<moose.Reac id=521 dataIndex=0 path=/Kholodenko[0]/kinetics[0]/MAPK[0]/Neg_feedback[0]>]
If you search for "MAPK"
:
In [21]: moose.wildcardFind('/Kholodenko/##/MAPK')
Out[21]:
[<moose.Neutral id=489 dataIndex=0 path=/Kholodenko[0]/kinetics[0]/MAPK[0]>,
<moose.Pool id=491 dataIndex=0 path=/Kholodenko[0]/kinetics[0]/MAPK[0]/MAPK[0]>,
<moose.Table2 id=552 dataIndex=0 path=/Kholodenko[0]/data[0]/MAPK[0]>]
Note that the recursive search wildcard (##
) must be separated by /
(slash). moose.wildcardFind('/Kholodenko/##MAPK')
returns an empty list.
Table
objects, I see this error “ValueError: x and y must have same first dimension, but have shapes ...
”. What is the problem? File "C:\moose-core\tests\core\debug_hhchanf2d.py", line 86, in test_vclamp
axes[1].plot(t, gktab.vector, label=f'({vstep * 1e3} mV)')
File "C:\miniforge3\envs\track\Lib\site-packages\matplotlib\axes\_axes.py", line 1721, in plot
lines = [*self._get_lines(self, *args, data=data, **kwargs)]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\miniforge3\envs\track\Lib\site-packages\matplotlib\axes\_base.py", line 303, in __call__
yield from self._plot_args(
^^^^^^^^^^^^^^^^
File "C:\miniforge3\envs\track\Lib\site-packages\matplotlib\axes\_base.py", line 499, in _plot_args
raise ValueError(f"x and y must have same first dimension, but "
ValueError: x and y must have same first dimension, but have shapes (1050001,) and (2100002,)
In this instance, you are creating the time vector based on the length of one Table
, and plotting another. One of the tables (here the second one) was doubly connected, i.e., its requestOut
message was passed in two connect calls, like this:
moose.connect(gktab, 'requestOut', channel1, 'Gk')
moose.connect(gktab, 'requestOut', channel2, 'Gk')
You should check the length of the vector
attribute of a table against the number of time points expected from total simulation time (simtime in moose.start(simtime)
) and the dt
of the table. If the length of vector
is a multiple of the expected number, then you have multiple connection issue with that table.
length
and diameter
of a Compartment
update its membrane resistance Rm
and capacitance Cm
fields?length
and diameter
are utility fields that can be used for visualization and format conversion. They are not used by MOOSE for computing Rm
and Cm
. In some other tools the user specifies the specific resistance and specific capacitance of the membrane along with length
and diameter
of a compartment. And the software computes the total mebrane resistance and capacitance based on the surface area. However, in MOOSE Rm
and Cm
represent total membrane resistance and capacitance respectively, and are set directly.
If you have a cylindrical compartment with given length and diameter, and the specific resistance and capacitance are RM
and CM
respectively, then you should set:
surface_area = pi * compartment.length * compartment.diameter
compartment.Rm = RM / surface_area
compartment.Cm = CM * surface_area
where pi
is imported from any of the modules like math
or numpy
, or set directly to 3.14159… You must ensure unit consistency between length and specific resistance/capacitance here.
Ra
in a Compartment
?Ra
represents total axial resistance (also called cytoplasmic resistance) of the compartment.It is relevant only for multicompartmental models, and represents the resistance faced by current flowing from one compartment to the next.
HH
in HHChannel
, HHGate
, etc. stand for?HH
stands for Hodgkin and Huxley.They figured out the dynamics of ion channels that generate action potentials in nerve fibres, and these models use their formulation to implement channel dynamics. See here, here and here to learn more about this.
HHChannel
class for fast computations, or HHChannelF
class for more flexible computations.The HHChannel
class is designed for faster simulations, and avoids explicitly evaluating Hodgkin-Huxley-type expressions at each simulation step. Instead, it finds the alpha(V)
and beta(V)
for membrane voltage V
using lookup/interpolation tables.
The HHChannelF
class is for convenience and accuracy, and allows you to explicitly set the gate expressions as strings. However, it evaluates the formula at each time step, which is slower than table lookup in HHChannel
.
HHChannel
?HHChannel
are computed via HHGate
objects. They use tables mapping voltage values to gating parameter values to find the gating parameters for a given voltage.HHChannel.Xpower
, HHChannel.Ypower
corresponding to the number of gating particles in the channel model.
channel.Xpower= 3 and ~channel.Ypower=1
.HHGate
objects are created.HHGate.setupAlpha()
(for alpha-beta form of the HH equations) or HHGate.setupTau()
(for the tau-inf form of the HH equations) function.HHGate.alphaExpr
and HHGate.betaExpr
for alpha-beta form, or HHGate.tauExpr
and HHGate.infExpr
for tau-inf formHHGate.tableA
and HHGate.tableB
fields with arrays computed in Python.HHGate.setupAlpha()
or HHGate.setupTau()
for setting up the lookup tables of an HHGate
object?HHGate.setupAlpha(...)
for alpha-beta form of the HH equations or HHGate.setupTau(...)
for the tau-inf form of the HH equations.These functions compute the HH-gate expressions in the generic form:
Thus for each of alpha
and beta
(or tau
and inf
depeding on the formulation) there are 5 constant coefficients: A…F, some of which may be 0
. The setupAlpha()
function (or setupTau()
) takes a list of 13 parameters: 5 each for the constants in the expressions for alpha
and beta
(or tau
and inf
), number of divisions in the interpolation table (divs
), the lower bound of the interpolation table (min
), and the upper bound of the interpolation table (max
).
Below is an example of setting up Hodgkin-Huxley’s Na channel using setupAlpha
. In their formulation
Thus , , , and . Similarly,
so, , , , and .
We expect the membrane voltage to stay within -110 mV to 50 mV under physiological conditions, and divide this range into in 3000 points for lookup. We also want the lookup to use linear interpolation for voltage values falling between two entries in the table.
import moose
chan = moose.HHChannel('channel')
chan.Xpower = 3 # this will also initialize the HHGate element channel/gateX
chan.Ypower = 1 # this will also initialize the HHGate element channel/gateY
m_gate = moose.element(f'{chan.path}/gateX')
h_gate = moose.element(f'{chan.path}/gateY')
vmin = -110
vmax = 50
vdivs = 3000
m_gate.setupAlpha([
0.1 * 25.0, # A_A
-0.1, # A_B
-1.0, # A_C
-25.0, # A_D
-10.0, # A_F
4.0, # B_A
0.0, # B_B
0.0, # B_C
0.0, # B_D
18.0, # B_F
vdivs,
vmin,
vmax])
m_gate.useInterpolation = True # use linear interpolation instead of direct lookup
# Similarly for h_gate ...
HHGate
?HHGate.alphaExpr
and HHGate.betaExpr
for alpha-beta form, or HHGate.tauExpr
and HHGate.infExpr
for tau-inf form.In this case you must explicitly set the min
, max
, and divs
fields of each gate. The expressions should use exprtk syntax. Do not forget to convert the expressions to reflect the unit system of your entire model. We recommend adhering to SI units, but the code sample below shows original Hodgkin-Huxley formulation in physiological units. Note that the min
and max
voltages are in mV
.
import moose
chan = moose.HHChannel('channel')
chan.Xpower = 3 # this will also initialize the HHGate element channel/gateX
chan.Ypower = 1 # this will also initialize the HHGate element channel/gateY
m_gate = moose.element(f'{chan.path}/gateX')
h_gate = moose.element(f'{chan.path}/gateY')
m_gate.alphaExpr = '0.1 * (25 - v)/(exp((25 - v)/10) - 1)'
m_gate.betaExpr = '4 * exp(-v/18)'
h_gate.alphaExpr = '0.07 * exp(-v/20)'
h_gate.betaExpr = '1/(exp((30-v)/10) + 1)'
for gate in (m_gate, h_gate):
gate.useInterpolation = True
gate.divs = 1000
gate.min = -30.0
gate.max = 120.0
HHGates
when using an HHChannel
?alpha(V)
and beta(V)
values for the desired range of voltages.Then for the target gate, assign alpha(V)
series to the tableA
field, and alpha(V) + beta(V)
to the tableB
field. If you have few voltage values, or if you want higher accuracy, set useInterpolation
to True
. You must explicitly set the min
, max
, and divs
fields of each gate. Note that we are using SI units here and the HH equations have been modified accordingly.
import numpy as np
import moose
chan = moose.HHChannel('channel')
chan.Xpower = 3
chan.Ypower = 1
m_gate = moose.element(f'{chan.path}/gateX')
h_gate = moose.element(f'{chan.path}/gateY')
vmin = -110e-3
vmax = 50e-3
vdivs = 1000
v = np.linspace(vmin, vmax, vdivs + 1) - (-70e-3)
m_alpha = (
1e3 * (25 - v * 1e3) / (10 * (np.exp((25 - v * 1e3) / 10) - 1))
)
m_beta = 1e3 * 4 * np.exp(-v * 1e3 / 18)
m_gate.min = vmin
m_gate.max = vmax
m_gate.divs = vdivs
m_gate.tableA = m_alpha
m_gate.tableB = m_alpha + m_beta
h_alpha = 1e3 * 0.07 * np.exp(-v / 20e-3)
h_beta = 1e3 * 1 / (np.exp((30e-3 - v) / 10e-3) + 1)
h_gate.min = vmin
h_gate.max = vmax
h_gate.divs = vdivs
h_gate.tableA = h_alpha
h_gate.tableB = h_alpha + h_beta
HHChannelF
class for formula based evaluation of gating variables.HHChannelF
is similar to HHChannel
but allows you to specify expression strings for gate dynamics. It allows both alpha-beta form and the tau-inf forms. To use alpha-beta form assign the formula for alpha and beta to the fields alpha
and beta
of the gate in the channel.
HHChannel2D
or HHChannelF2D
.