Two cells connected via a gap junction#
In this example, we will set up two cells connected via a gap junction. Each of the cells has a passive leak current as its only dynamics. This plus the gap junction will produce an equilibrium potential different from both the resting potentials. We will investigate how the equilibrium potentials of the two cells change due of the gap junction connection.
Note
Concepts covered in this example:
Creating a simulation recipe for two cells.
Placing probes.
Running the simulation and extracting the results.
Adding a gap junction connection.
We assume prior exposure to the concepts of cable cells, recipes, and simple networks.
Walk-through#
We set up a recipe for the simulation of two cells
def __init__(self, Vms, length, radius, cm, rL, g, gj_g, max_extent):
"""
Vms -- membrane leak potentials of the two cells
length -- length of cable in μm
radius -- radius of cable in μm
cm -- membrane capacitance in F/m²
rL -- axial resistivity in Ω·cm
g -- membrane conductivity in S/cm²
gj_g -- gap junction conductivity in μS
max_extent -- maximum extent of control volume in μm
"""
# Call base constructor first to ensure proper initialization
A.recipe.__init__(self)
self.Vms = [Vm * U.mV for Vm in Vms]
self.length = length * U.um
self.radius = radius * U.um
self.area = self.length * 2 * np.pi * self.radius
self.cm = cm * U.F / U.m2
self.rL = rL * U.Ohm * U.cm
self.g = g * U.S / U.cm2
self.gj_g = gj_g * U.uS
self.max_extent = max_extent
self.the_props = A.neuron_cable_properties()
in which we store the relevant parameters for the two cells, all of which are
shared except the equilibrium potentials in Vms
. These are used to build
the network.
Let’s quickly check some standard callbacks:
num_cells
returns the number of cells in the network, fixed as 2cell_kind
specifies that we handlecable_cell
exclusively.global_properties
returns a list of standard parameters based on the defaults of the NEURON simulator.probes
record the membrane potential at the cell mid.
The two remaining methods are:
cell_description
#
We construct a basic, single segment morphology from the length
and
radius
parameters. The decor sets the basic parameters and adds the passive
leak current pas
with the given resting value Vms[gid]
and conductivity
g
.
.place('"midpoint"', A.junction("gj", g=self.gj_g.value), "gj")
The only new item is the placement of the gap junction endpoint at midpoint
with the basic, builtin gj
dynamics type (other dynamics may be defined and
used).
gap_junctions_on
#
Similar to connections_on
, this method returns a list of gap junction
connections and these are defined in the same manner.
def gap_junctions_on(self, gid):
return [A.gap_junction_connection(((gid + 1) % 2, "gj"), "gj", 1)]
By (gid + 1) % 2
we define two connections, one per cell, between the cells.
This is due to the uni-directional definition of gap junctions in Arbor.
Running the simulation#
To allow runtime configuration, we define a parser for command line arguments which are used to set parameters in the recipe
# parse the command line arguments
parser = ArgumentParser(description="Two cells connected via a gap junction")
parser.add_argument(
"--Vms",
help="membrane leak potentials [mV]",
type=float,
default=[-100, -60],
nargs=2,
)
parser.add_argument("--length", help="cell length [μm]", type=float, default=100)
parser.add_argument("--radius", help="cell radius [μm]", type=float, default=3)
parser.add_argument(
"--cm", help="membrane capacitance [F/m²]", type=float, default=0.005
)
parser.add_argument("--rL", help="axial resistivity [Ω·cm]", type=float, default=90)
parser.add_argument("--g", help="leak conductivity [S/cm²]", type=float, default=0.001)
parser.add_argument(
"--gj_g", help="gap junction conductivity [μS]", type=float, default=0.01
)
parser.add_argument("--max-extent", help="discretization length [μm]", type=float)
args = parser.parse_args()
We then set up the simulation and configure sampling width equal to the timestep \(dt\). Now, we can run the network.
# set up membrane voltage probes at the position of the gap junction
rec = TwoCellsWithGapJunction(**vars(args))
# configure the simulation and handles for the probes
sim = A.simulation(rec)
T = 5 * U.ms
dt = 0.01 * U.ms
# generate handles for all probes and gids.
handles = [sim.sample((gid, "Um"), A.regular_schedule(dt)) for gid in [0, 1]]
All that is left to do is to put this into a plot. The output plot below shows how the potential of the two cells approaches their equilibrium potentials, which can be computed from the given parameters.
The full code#
You can find the full code of the example at python/examples/network_two_cells_gap_junctions.py
Executing the script will run the simulation with default parameters.