Dendrify basics#
In this tutorial, we are going to cover the following topics:
Getting to know Dendrify’s basic object types and their functions
How to generate model equations
How to set model parameters
Imports#
import brian2 as b
import dendrify as d
from brian2.units import *
from dendrify import Soma, Dendrite, PointNeuronModel
b.prefs.codegen.target = 'numpy' # faster for simple models and short simulations
Generating model equations#
In this first part of the tutorial we are going to focus on how to create single compartments and how to equip them with desired mechanisms.
Creating compartments#
# Setting a compartment's name is the barely minimum you need to create it
soma = Soma('soma')
dend = Dendrite('dend')
# Soma and Dendrite objects share many functions since they both inherit from
# the same class
print(isinstance(soma, d.Compartment))
print(isinstance(dend, d.Compartment))
True
True
Accessing equations#
print(soma.equations)
dV_soma/dt = (gL_soma * (EL_soma-V_soma) + I_soma) / C_soma :volt
I_soma = I_ext_soma :amp
I_ext_soma :amp
print(dend.equations)
dV_dend/dt = (gL_dend * (EL_dend-V_dend) + I_dend) / C_dend :volt
I_dend = I_ext_dend :amp
I_ext_dend :amp
Synaptic currents#
# The usage of tags helps differentiate between same type of synapses that reach
# a single compartment.
dend.synapse('AMPA', tag='A')
print(dend.equations)
dV_dend/dt = (gL_dend * (EL_dend-V_dend) + I_dend) / C_dend :volt
I_dend = I_ext_dend + I_AMPA_A_dend :amp
I_ext_dend :amp
I_AMPA_A_dend = g_AMPA_A_dend * (E_AMPA-V_dend) * s_AMPA_A_dend * w_AMPA_A_dend :amp
ds_AMPA_A_dend/dt = -s_AMPA_A_dend / t_AMPA_decay_A_dend :1
s_AMPA_x_dend -> the state variable for this channel (0 -> closed).
w_AMPA_x_dend -> the weight variable. Useful for plasticity (1 by default).
dend.synapse('AMPA', tag='B')
print(dend.equations)
dV_dend/dt = (gL_dend * (EL_dend-V_dend) + I_dend) / C_dend :volt
I_dend = I_ext_dend + I_AMPA_B_dend + I_AMPA_A_dend :amp
I_ext_dend :amp
I_AMPA_A_dend = g_AMPA_A_dend * (E_AMPA-V_dend) * s_AMPA_A_dend * w_AMPA_A_dend :amp
ds_AMPA_A_dend/dt = -s_AMPA_A_dend / t_AMPA_decay_A_dend :1
I_AMPA_B_dend = g_AMPA_B_dend * (E_AMPA-V_dend) * s_AMPA_B_dend * w_AMPA_B_dend :amp
ds_AMPA_B_dend/dt = -s_AMPA_B_dend / t_AMPA_decay_B_dend :1
dend.synapse('NMDA', tag='A')
print(dend.equations)
dV_dend/dt = (gL_dend * (EL_dend-V_dend) + I_dend) / C_dend :volt
I_dend = I_ext_dend + I_NMDA_A_dend + I_AMPA_B_dend + I_AMPA_A_dend :amp
I_ext_dend :amp
I_AMPA_A_dend = g_AMPA_A_dend * (E_AMPA-V_dend) * s_AMPA_A_dend * w_AMPA_A_dend :amp
ds_AMPA_A_dend/dt = -s_AMPA_A_dend / t_AMPA_decay_A_dend :1
I_AMPA_B_dend = g_AMPA_B_dend * (E_AMPA-V_dend) * s_AMPA_B_dend * w_AMPA_B_dend :amp
ds_AMPA_B_dend/dt = -s_AMPA_B_dend / t_AMPA_decay_B_dend :1
I_NMDA_A_dend = g_NMDA_A_dend * (E_NMDA-V_dend) * s_NMDA_A_dend / (1 + Mg_con * exp(-Alpha_NMDA*(V_dend/mV+Gamma_NMDA)) / Beta_NMDA) * w_NMDA_A_dend :amp
ds_NMDA_A_dend/dt = -s_NMDA_A_dend/t_NMDA_decay_A_dend :1
Random noise#
dend.noise()
print(dend.equations)
dV_dend/dt = (gL_dend * (EL_dend-V_dend) + I_dend) / C_dend :volt
I_dend = I_ext_dend + I_noise_dend + I_NMDA_A_dend + I_AMPA_B_dend + I_AMPA_A_dend :amp
I_ext_dend :amp
I_AMPA_A_dend = g_AMPA_A_dend * (E_AMPA-V_dend) * s_AMPA_A_dend * w_AMPA_A_dend :amp
ds_AMPA_A_dend/dt = -s_AMPA_A_dend / t_AMPA_decay_A_dend :1
I_AMPA_B_dend = g_AMPA_B_dend * (E_AMPA-V_dend) * s_AMPA_B_dend * w_AMPA_B_dend :amp
ds_AMPA_B_dend/dt = -s_AMPA_B_dend / t_AMPA_decay_B_dend :1
I_NMDA_A_dend = g_NMDA_A_dend * (E_NMDA-V_dend) * s_NMDA_A_dend / (1 + Mg_con * exp(-Alpha_NMDA*(V_dend/mV+Gamma_NMDA)) / Beta_NMDA) * w_NMDA_A_dend :amp
ds_NMDA_A_dend/dt = -s_NMDA_A_dend/t_NMDA_decay_A_dend :1
dI_noise_dend/dt = (mean_noise_dend-I_noise_dend) / tau_noise_dend + sigma_noise_dend * (sqrt(2/(tau_noise_dend*dt)) * randn()) :amp
NOTE: You can find more info about how random noise is impemented inBrian’s documentation.
Dendritic spikes#
dend.dspikes('Na')
print(dend.equations)
dV_dend/dt = (gL_dend * (EL_dend-V_dend) + I_dend) / C_dend :volt
I_dend = I_ext_dend + I_rise_Na_dend + I_fall_Na_dend + I_noise_dend + I_NMDA_A_dend + I_AMPA_B_dend + I_AMPA_A_dend :amp
I_ext_dend :amp
I_AMPA_A_dend = g_AMPA_A_dend * (E_AMPA-V_dend) * s_AMPA_A_dend * w_AMPA_A_dend :amp
ds_AMPA_A_dend/dt = -s_AMPA_A_dend / t_AMPA_decay_A_dend :1
I_AMPA_B_dend = g_AMPA_B_dend * (E_AMPA-V_dend) * s_AMPA_B_dend * w_AMPA_B_dend :amp
ds_AMPA_B_dend/dt = -s_AMPA_B_dend / t_AMPA_decay_B_dend :1
I_NMDA_A_dend = g_NMDA_A_dend * (E_NMDA-V_dend) * s_NMDA_A_dend / (1 + Mg_con * exp(-Alpha_NMDA*(V_dend/mV+Gamma_NMDA)) / Beta_NMDA) * w_NMDA_A_dend :amp
ds_NMDA_A_dend/dt = -s_NMDA_A_dend/t_NMDA_decay_A_dend :1
dI_noise_dend/dt = (mean_noise_dend-I_noise_dend) / tau_noise_dend + sigma_noise_dend * (sqrt(2/(tau_noise_dend*dt)) * randn()) :amp
I_rise_Na_dend = g_rise_Na_dend * (E_rise_Na-V_dend) :amp
I_fall_Na_dend = g_fall_Na_dend * (E_fall_Na-V_dend) :amp
g_rise_Na_dend = g_rise_max_Na_dend * int(t_in_timesteps <= spiketime_Na_dend + duration_rise_Na_dend) * gate_Na_dend :siemens
g_fall_Na_dend = g_fall_max_Na_dend * int(t_in_timesteps <= spiketime_Na_dend + offset_fall_Na_dend + duration_fall_Na_dend) * int(t_in_timesteps >= spiketime_Na_dend + offset_fall_Na_dend) * gate_Na_dend :siemens
spiketime_Na_dend :1
gate_Na_dend :1
Connecting compartments#
dend.connect(soma)
NOTE: Ιgnore the above errors for now. They will make sense in a while.
print(dend.equations)
dV_dend/dt = (gL_dend * (EL_dend-V_dend) + I_dend) / C_dend :volt
I_dend = I_ext_dend + I_soma_dend + I_rise_Na_dend + I_fall_Na_dend + I_noise_dend + I_NMDA_A_dend + I_AMPA_B_dend + I_AMPA_A_dend :amp
I_ext_dend :amp
I_AMPA_A_dend = g_AMPA_A_dend * (E_AMPA-V_dend) * s_AMPA_A_dend * w_AMPA_A_dend :amp
ds_AMPA_A_dend/dt = -s_AMPA_A_dend / t_AMPA_decay_A_dend :1
I_AMPA_B_dend = g_AMPA_B_dend * (E_AMPA-V_dend) * s_AMPA_B_dend * w_AMPA_B_dend :amp
ds_AMPA_B_dend/dt = -s_AMPA_B_dend / t_AMPA_decay_B_dend :1
I_NMDA_A_dend = g_NMDA_A_dend * (E_NMDA-V_dend) * s_NMDA_A_dend / (1 + Mg_con * exp(-Alpha_NMDA*(V_dend/mV+Gamma_NMDA)) / Beta_NMDA) * w_NMDA_A_dend :amp
ds_NMDA_A_dend/dt = -s_NMDA_A_dend/t_NMDA_decay_A_dend :1
dI_noise_dend/dt = (mean_noise_dend-I_noise_dend) / tau_noise_dend + sigma_noise_dend * (sqrt(2/(tau_noise_dend*dt)) * randn()) :amp
I_rise_Na_dend = g_rise_Na_dend * (E_rise_Na-V_dend) :amp
I_fall_Na_dend = g_fall_Na_dend * (E_fall_Na-V_dend) :amp
g_rise_Na_dend = g_rise_max_Na_dend * int(t_in_timesteps <= spiketime_Na_dend + duration_rise_Na_dend) * gate_Na_dend :siemens
g_fall_Na_dend = g_fall_max_Na_dend * int(t_in_timesteps <= spiketime_Na_dend + offset_fall_Na_dend + duration_fall_Na_dend) * int(t_in_timesteps >= spiketime_Na_dend + offset_fall_Na_dend) * gate_Na_dend :siemens
spiketime_Na_dend :1
gate_Na_dend :1
I_soma_dend = (V_soma-V_dend) * g_soma_dend :amp
print(soma.equations)
dV_soma/dt = (gL_soma * (EL_soma-V_soma) + I_soma) / C_soma :volt
I_soma = I_ext_soma + I_dend_soma :amp
I_ext_soma :amp
I_dend_soma = (V_dend-V_soma) * g_dend_soma :amp
User-defined equations#
Equations are Python strings, thus you can adapt them with standard string formatting practices.
type(dend.equations)
str
custom_model = "dcns/dt = -cns/tau_cns :1"
eqs = f"{dend.equations}\n{custom_model}"
print(eqs)
dV_dend/dt = (gL_dend * (EL_dend-V_dend) + I_dend) / C_dend :volt
I_dend = I_ext_dend + I_soma_dend + I_rise_Na_dend + I_fall_Na_dend + I_noise_dend + I_NMDA_A_dend + I_AMPA_B_dend + I_AMPA_A_dend :amp
I_ext_dend :amp
I_AMPA_A_dend = g_AMPA_A_dend * (E_AMPA-V_dend) * s_AMPA_A_dend * w_AMPA_A_dend :amp
ds_AMPA_A_dend/dt = -s_AMPA_A_dend / t_AMPA_decay_A_dend :1
I_AMPA_B_dend = g_AMPA_B_dend * (E_AMPA-V_dend) * s_AMPA_B_dend * w_AMPA_B_dend :amp
ds_AMPA_B_dend/dt = -s_AMPA_B_dend / t_AMPA_decay_B_dend :1
I_NMDA_A_dend = g_NMDA_A_dend * (E_NMDA-V_dend) * s_NMDA_A_dend / (1 + Mg_con * exp(-Alpha_NMDA*(V_dend/mV+Gamma_NMDA)) / Beta_NMDA) * w_NMDA_A_dend :amp
ds_NMDA_A_dend/dt = -s_NMDA_A_dend/t_NMDA_decay_A_dend :1
dI_noise_dend/dt = (mean_noise_dend-I_noise_dend) / tau_noise_dend + sigma_noise_dend * (sqrt(2/(tau_noise_dend*dt)) * randn()) :amp
I_rise_Na_dend = g_rise_Na_dend * (E_rise_Na-V_dend) :amp
I_fall_Na_dend = g_fall_Na_dend * (E_fall_Na-V_dend) :amp
g_rise_Na_dend = g_rise_max_Na_dend * int(t_in_timesteps <= spiketime_Na_dend + duration_rise_Na_dend) * gate_Na_dend :siemens
g_fall_Na_dend = g_fall_max_Na_dend * int(t_in_timesteps <= spiketime_Na_dend + offset_fall_Na_dend + duration_fall_Na_dend) * int(t_in_timesteps >= spiketime_Na_dend + offset_fall_Na_dend) * gate_Na_dend :siemens
spiketime_Na_dend :1
gate_Na_dend :1
I_soma_dend = (V_soma-V_dend) * g_soma_dend :amp
dcns/dt = -cns/tau_cns :1
Setting model parameters#
In this second part of the tutorial we are going to explore how to access, generate or update all model parameters.
Accessing model properties#
dend.parameters
ERROR [dendrify.ephysproperties:336]
Could not calculate the g_couple for 'dend' and 'soma'.
Please make sure that [length, diameter, r_axial] are
available for both compartments.
WARNING [dendrify.ephysproperties:180]
Missing parameters [length | diameter] for 'dend'.
Could not calculate the area of 'dend', returned None.
WARNING [dendrify.ephysproperties:210]
Could not calculate the [capacitance] of 'dend', returned None.
WARNING [dendrify.ephysproperties:180]
Missing parameters [length | diameter] for 'dend'.
Could not calculate the area of 'dend', returned None.
WARNING [dendrify.ephysproperties:240]
Could not calculate the [g_leakage] of 'dend', returned None.
ERROR [dendrify.ephysproperties:266]
Could not resolve [EL_dend] for 'dend'.
ERROR [dendrify.ephysproperties:266]
Could not resolve [C_dend] for 'dend'.
ERROR [dendrify.ephysproperties:266]
Could not resolve [gL_dend] for 'dend'.
{'w_AMPA_A_dend': 1.0,
'w_AMPA_B_dend': 1.0,
'w_NMDA_A_dend': 1.0,
'tau_noise_dend': 20. * msecond,
'sigma_noise_dend': 1. * pamp,
'mean_noise_dend': 0. * amp,
'g_soma_dend': None,
'Vth_Na_dend': None,
'g_rise_max_Na_dend': None,
'g_fall_max_Na_dend': None,
'E_rise_Na': None,
'E_fall_Na': None,
'duration_rise_Na_dend': None,
'duration_fall_Na_dend': None,
'offset_fall_Na_dend': None,
'refractory_Na_dend': None,
'E_AMPA': 0. * volt,
'E_NMDA': 0. * volt,
'E_GABA': -80. * mvolt,
'E_Na': 70. * mvolt,
'E_K': -89. * mvolt,
'E_Ca': 136. * mvolt,
'Mg_con': 1.0,
'Alpha_NMDA': 0.062,
'Beta_NMDA': 3.57,
'Gamma_NMDA': 0}
Dendrify is designed to fail loudly!!! Errors and warnings are raised if you try to access parameters that do not exist, or if something important is missing.
Default parameters#
NOTE: Dendrify has a built-in library of default simulation parameters that can be views or adjusted using default_params() and update_default_params() respectively.
d.default_params()
{'E_AMPA': 0. * volt,
'E_NMDA': 0. * volt,
'E_GABA': -80. * mvolt,
'E_Na': 70. * mvolt,
'E_K': -89. * mvolt,
'E_Ca': 136. * mvolt,
'Mg_con': 1.0,
'Alpha_NMDA': 0.062,
'Beta_NMDA': 3.57,
'Gamma_NMDA': 0}
d.update_default_params({"E_Ca":2023})
d.default_params()
{'E_AMPA': 0. * volt,
'E_NMDA': 0. * volt,
'E_GABA': -80. * mvolt,
'E_Na': 70. * mvolt,
'E_K': -89. * mvolt,
'E_Ca': 2023,
'Mg_con': 1.0,
'Alpha_NMDA': 0.062,
'Beta_NMDA': 3.57,
'Gamma_NMDA': 0}
Ephys parameters#
In Dendrify, each compartment is treated as an open cylinder. Although an RC circuit does not have physical dimensions, length and diameter are needed to estimate a compartment’s theoretical surface area.
soma = Soma('soma', length=20*um, diameter=20*um,
cm=1*uF/(cm**2), gl=40*uS/(cm**2),
r_axial=150*ohm*cm, v_rest=-70*mV)
dend = Dendrite('dend', length=20*um, diameter=20*um,
cm=1*uF/(cm**2), gl=40*uS/(cm**2),
r_axial=150*ohm*cm, v_rest=-70*mV)
print(soma) # no more errors :)
OBJECT
------
<class 'dendrify.compartment.Soma'>
EQUATIONS
---------
dV_soma/dt = (gL_soma * (EL_soma-V_soma) + I_soma) / C_soma :volt
I_soma = I_ext_soma :amp
I_ext_soma :amp
PARAMETERS
----------
{'Alpha_NMDA': 0.062,
'Beta_NMDA': 3.57,
'C_soma': 12.56637061 * pfarad,
'EL_soma': -70. * mvolt,
'E_AMPA': 0. * volt,
'E_Ca': 2023,
'E_GABA': -80. * mvolt,
'E_K': -89. * mvolt,
'E_NMDA': 0. * volt,
'E_Na': 70. * mvolt,
'Gamma_NMDA': 0,
'Mg_con': 1.0,
'gL_soma': 0.50265482 * nsiemens}
USER PARAMETERS
---------------
{'_dimensionless': False,
'cm': 0.01 * metre ** -4 * kilogram ** -1 * second ** 4 * amp ** 2,
'cm_abs': None,
'diameter': 20. * umetre,
'gl': 0.4 * metre ** -4 * kilogram ** -1 * second ** 3 * amp ** 2,
'gl_abs': None,
'length': 20. * umetre,
'name': 'soma',
'r_axial': 1.5 * metre ** 3 * kilogram * second ** -3 * amp ** -2,
'scale_factor': 1.0,
'spine_factor': 1.0,
'v_rest': -70. * mvolt}
# The surface area of an equivalent open cylinder
soma.area
# Absolute capacitance (specific capacitance [cm] multiplied by area)
soma.capacitance
# Absolute leakage conductance (specific leakage conductance [gl] multiplied by area)
soma.g_leakage
Synaptic parameters#
dend.synapse('AMPA', 'A', g=1*nS, t_decay=5*ms)
print(dend)
OBJECT
------
<class 'dendrify.compartment.Dendrite'>
EQUATIONS
---------
dV_dend/dt = (gL_dend * (EL_dend-V_dend) + I_dend) / C_dend :volt
I_dend = I_ext_dend + I_AMPA_A_dend :amp
I_ext_dend :amp
I_AMPA_A_dend = g_AMPA_A_dend * (E_AMPA-V_dend) * s_AMPA_A_dend * w_AMPA_A_dend :amp
ds_AMPA_A_dend/dt = -s_AMPA_A_dend / t_AMPA_decay_A_dend :1
PARAMETERS
----------
{'Alpha_NMDA': 0.062,
'Beta_NMDA': 3.57,
'C_dend': 12.56637061 * pfarad,
'EL_dend': -70. * mvolt,
'E_AMPA': 0. * volt,
'E_Ca': 2023,
'E_GABA': -80. * mvolt,
'E_K': -89. * mvolt,
'E_NMDA': 0. * volt,
'E_Na': 70. * mvolt,
'Gamma_NMDA': 0,
'Mg_con': 1.0,
'gL_dend': 0.50265482 * nsiemens,
'g_AMPA_A_dend': 1. * nsiemens,
't_AMPA_decay_A_dend': 5. * msecond,
'w_AMPA_A_dend': 1.0}
EVENTS
------
[]
EVENT CONDITIONS
----------------
{}
USER PARAMETERS
---------------
{'cm': 0.01 * metre ** -4 * kilogram ** -1 * second ** 4 * amp ** 2,
'diameter': 20. * umetre,
'gl': 0.4 * metre ** -4 * kilogram ** -1 * second ** 3 * amp ** 2,
'length': 20. * umetre,
'name': 'dend',
'r_axial': 1.5 * metre ** 3 * kilogram * second ** -3 * amp ** -2,
'scale_factor': 1.0,
'spine_factor': 1.0,
'v_rest': -70. * mvolt}
# NMDA synapse with instant activation and exponential decay:
dend.synapse('NMDA', 'A', g=1*nS, t_decay=60*ms)
# NMDA synapse as a sum of two exponentials with rise and decay kinetics:
dend.synapse('NMDA', 'B', g=1*nS, t_decay=60*ms, t_rise=5*ms)
print(dend)
OBJECT
------
<class 'dendrify.compartment.Dendrite'>
EQUATIONS
---------
dV_dend/dt = (gL_dend * (EL_dend-V_dend) + I_dend) / C_dend :volt
I_dend = I_ext_dend + I_NMDA_B_dend + I_NMDA_A_dend + I_AMPA_A_dend :amp
I_ext_dend :amp
I_AMPA_A_dend = g_AMPA_A_dend * (E_AMPA-V_dend) * s_AMPA_A_dend * w_AMPA_A_dend :amp
ds_AMPA_A_dend/dt = -s_AMPA_A_dend / t_AMPA_decay_A_dend :1
I_NMDA_A_dend = g_NMDA_A_dend * (E_NMDA-V_dend) * s_NMDA_A_dend / (1 + Mg_con * exp(-Alpha_NMDA*(V_dend/mV+Gamma_NMDA)) / Beta_NMDA) * w_NMDA_A_dend :amp
ds_NMDA_A_dend/dt = -s_NMDA_A_dend/t_NMDA_decay_A_dend :1
I_NMDA_B_dend = g_NMDA_B_dend * (E_NMDA-V_dend) * x_NMDA_B_dend / (1 + Mg_con * exp(-Alpha_NMDA*(V_dend/mV+Gamma_NMDA)) / Beta_NMDA) * w_NMDA_B_dend :amp
dx_NMDA_B_dend/dt = (-x_NMDA_B_dend/t_NMDA_decay_B_dend) + s_NMDA_B_dend/ms :1
ds_NMDA_B_dend/dt = -s_NMDA_B_dend / t_NMDA_rise_B_dend :1
PARAMETERS
----------
{'Alpha_NMDA': 0.062,
'Beta_NMDA': 3.57,
'C_dend': 12.56637061 * pfarad,
'EL_dend': -70. * mvolt,
'E_AMPA': 0. * volt,
'E_Ca': 2023,
'E_GABA': -80. * mvolt,
'E_K': -89. * mvolt,
'E_NMDA': 0. * volt,
'E_Na': 70. * mvolt,
'Gamma_NMDA': 0,
'Mg_con': 1.0,
'gL_dend': 0.50265482 * nsiemens,
'g_AMPA_A_dend': 1. * nsiemens,
'g_NMDA_A_dend': 1. * nsiemens,
'g_NMDA_B_dend': 1. * nsiemens,
't_AMPA_decay_A_dend': 5. * msecond,
't_NMDA_decay_A_dend': 60. * msecond,
't_NMDA_decay_B_dend': 60. * msecond,
't_NMDA_rise_B_dend': 5. * msecond,
'w_AMPA_A_dend': 1.0,
'w_NMDA_A_dend': 1.0,
'w_NMDA_B_dend': 1.0}
EVENTS
------
[]
EVENT CONDITIONS
----------------
{}
USER PARAMETERS
---------------
{'cm': 0.01 * metre ** -4 * kilogram ** -1 * second ** 4 * amp ** 2,
'diameter': 20. * umetre,
'gl': 0.4 * metre ** -4 * kilogram ** -1 * second ** 3 * amp ** 2,
'length': 20. * umetre,
'name': 'dend',
'r_axial': 1.5 * metre ** 3 * kilogram * second ** -3 * amp ** -2,
'scale_factor': 1.0,
'spine_factor': 1.0,
'v_rest': -70. * mvolt}
Random noise parameters#
dend.noise(mean=0*pA, sigma=10*pA, tau=1*ms)
dSpike parameters#
We will explore this topic in another tutorial…
Coupling parameters#
# Automatic approach
soma.connect(dend, g=10*nS)
print(soma)
OBJECT
------
<class 'dendrify.compartment.Soma'>
EQUATIONS
---------
dV_soma/dt = (gL_soma * (EL_soma-V_soma) + I_soma) / C_soma :volt
I_soma = I_ext_soma + I_dend_soma :amp
I_ext_soma :amp
I_dend_soma = (V_dend-V_soma) * g_dend_soma :amp
PARAMETERS
----------
{'Alpha_NMDA': 0.062,
'Beta_NMDA': 3.57,
'C_soma': 12.56637061 * pfarad,
'EL_soma': -70. * mvolt,
'E_AMPA': 0. * volt,
'E_Ca': 2023,
'E_GABA': -80. * mvolt,
'E_K': -89. * mvolt,
'E_NMDA': 0. * volt,
'E_Na': 70. * mvolt,
'Gamma_NMDA': 0,
'Mg_con': 1.0,
'gL_soma': 0.50265482 * nsiemens,
'g_dend_soma': 10. * nsiemens}
USER PARAMETERS
---------------
{'_dimensionless': False,
'cm': 0.01 * metre ** -4 * kilogram ** -1 * second ** 4 * amp ** 2,
'cm_abs': None,
'diameter': 20. * umetre,
'gl': 0.4 * metre ** -4 * kilogram ** -1 * second ** 3 * amp ** 2,
'gl_abs': None,
'length': 20. * umetre,
'name': 'soma',
'r_axial': 1.5 * metre ** 3 * kilogram * second ** -3 * amp ** -2,
'scale_factor': 1.0,
'spine_factor': 1.0,
'v_rest': -70. * mvolt}
Dimensionless compartments#
If you know the model’s desired capacitance and leakage conductance you can pass them dirrectly as a parameters when creating a compartment.
soma = Soma('soma', cm_abs=200*pF, gl_abs=20*nS, v_rest=-70*mV)
dend = Dendrite('dend', cm_abs=200*pF, gl_abs=20*nS, v_rest=-70*mV)
Since these compartments have no dimensions, the automatic connection approach will not work, since it calculates the resistance between two adjucent half-cylinders.
soma.connect(dend)
---------------------------------------------------------------------------
DimensionlessCompartmentError Traceback (most recent call last)
Cell In[31], line 1
----> 1 soma.connect(dend)
File ~/anaconda3/envs/dendrify/lib/python3.11/site-packages/dendrify/compartment.py:169, in Compartment.connect(self, other, g)
166 raise ValueError(
167 "Cannot connect compartments with the same name.\n")
168 if (self.dimensionless or other.dimensionless) and type(g) == str:
--> 169 raise DimensionlessCompartmentError(
170 ("Cannot automatically calculate the coupling \nconductance of "
171 "dimensionless compartments. To resolve this error, perform\n"
172 "one of the following:\n\n"
173 f"1. Provide [length, diameter, r_axial] for both '{self.name}'"
174 f" and '{other.name}'.\n\n"
175 f"2. Turn both compartment into dimensionless by providing only"
176 " values for \n [cm_abs, gl_abs] and then connect them using "
177 "an exact coupling conductance."
178 )
179 )
181 # Current from Comp2 -> Comp1
182 I_forward = 'I_{1}_{0} = (V_{1}-V_{0}) * g_{1}_{0} :amp'.format(
183 self.name, other.name)
DimensionlessCompartmentError: Cannot automatically calculate the coupling
conductance of dimensionless compartments. To resolve this error, perform
one of the following:
1. Provide [length, diameter, r_axial] for both 'soma' and 'dend'.
2. Turn both compartment into dimensionless by providing only values for
[cm_abs, gl_abs] and then connect them using an exact coupling conductance.
However, you can still connect them by explicitly specifying the coupling conductance as shown bellow.IMPORTANT: This trick also works for compartments that have dimensions as well.
soma.connect(dend, g=10*nS)
print(soma)
OBJECT
------
<class 'dendrify.compartment.Soma'>
EQUATIONS
---------
dV_soma/dt = (gL_soma * (EL_soma-V_soma) + I_soma) / C_soma :volt
I_soma = I_ext_soma + I_dend_soma :amp
I_ext_soma :amp
I_dend_soma = (V_dend-V_soma) * g_dend_soma :amp
PARAMETERS
----------
{'Alpha_NMDA': 0.062,
'Beta_NMDA': 3.57,
'C_soma': 200. * pfarad,
'EL_soma': -70. * mvolt,
'E_AMPA': 0. * volt,
'E_Ca': 2023,
'E_GABA': -80. * mvolt,
'E_K': -89. * mvolt,
'E_NMDA': 0. * volt,
'E_Na': 70. * mvolt,
'Gamma_NMDA': 0,
'Mg_con': 1.0,
'gL_soma': 20. * nsiemens,
'g_dend_soma': 10. * nsiemens}
USER PARAMETERS
---------------
{'_dimensionless': True,
'cm': None,
'cm_abs': 200. * pfarad,
'diameter': None,
'gl': None,
'gl_abs': 20. * nsiemens,
'length': None,
'name': 'soma',
'r_axial': None,
'scale_factor': None,
'spine_factor': None,
'v_rest': -70. * mvolt}
Creating point neurons#
Dendrify also supports point (single-compartment) neuron models that share most of the functionalities of compartment objects (Soma/Dendrite). Notice that here, there is no need to specify a compartment’s name.
model = PointNeuronModel(model='leakyIF', v_rest=-60*mV,
cm_abs=200*pF, gl_abs=10*nS)
model.noise(mean=10*pA, sigma=100*pA, tau=20*ms)
model.synapse('AMPA', tag='x', g=2*nS, t_decay=2*ms)
print(model)
OBJECT
------
<class 'dendrify.neuronmodel.PointNeuronModel'>
EQUATIONS
---------
dV/dt = (gL * (EL-V) + I) / C :volt
I = I_ext + I_AMPA_x + I_noise :amp
I_ext :amp
dI_noise/dt = (mean_noise-I_noise) / tau_noise + sigma_noise * (sqrt(2/(tau_noise*dt)) * randn()) :amp
I_AMPA_x = g_AMPA_x * (E_AMPA-V) * s_AMPA_x * w_AMPA_x :amp
ds_AMPA_x/dt = -s_AMPA_x / t_AMPA_decay_x :1
PARAMETERS
----------
{'Alpha_NMDA': 0.062,
'Beta_NMDA': 3.57,
'C': 200. * pfarad,
'EL': -60. * mvolt,
'E_AMPA': 0. * volt,
'E_Ca': 2023,
'E_GABA': -80. * mvolt,
'E_K': -89. * mvolt,
'E_NMDA': 0. * volt,
'E_Na': 70. * mvolt,
'Gamma_NMDA': 0,
'Mg_con': 1.0,
'gL': 10. * nsiemens,
'g_AMPA_x': 2. * nsiemens,
'mean_noise': 10. * pamp,
'sigma_noise': 100. * pamp,
't_AMPA_decay_x': 2. * msecond,
'tau_noise': 20. * msecond,
'w_AMPA_x': 1.0}
USER PARAMETERS
---------------
{'_dimensionless': True,
'cm': None,
'cm_abs': 200. * pfarad,
'diameter': None,
'gl': None,
'gl_abs': 10. * nsiemens,
'length': None,
'name': None,
'r_axial': None,
'scale_factor': None,
'spine_factor': None,
'v_rest': -60. * mvolt}