Fast sodium channel gating in mossy fiber axons (Schmidt-Hieber et al. 2010)

 Download zip file   Auto-launch 
Help downloading and running models
Accession:128079
"... To study the mechanisms underlying AP initiation in unmyelinated hippocampal mossy fibers of adult mice, we recorded sodium currents in axonal and somatic membrane patches. We demonstrate that sodium channel density in the proximal axon is ~5 times higher than in the soma. Furthermore, sodium channel activation and inactivation are ~2 times faster. Modeling revealed that the fast activation localized the initiation site to the proximal axon even upon strong synaptic stimulation, while fast inactivation contributed to energy-efficient membrane charging during APs. ..."
Reference:
1 . Schmidt-Hieber C, Bischofberger J (2010) Fast sodium channel gating supports localized and efficient axonal action potential initiation. J Neurosci 30:10233-42 [PubMed]
Model Information (Click on a link to find other models with that property)
Model Type: Neuron or other electrically excitable cell;
Brain Region(s)/Organism:
Cell Type(s): Dentate gyrus granule GLU cell;
Channel(s):
Gap Junctions:
Receptor(s):
Gene(s):
Transmitter(s):
Simulation Environment: NEURON;
Model Concept(s): Action Potential Initiation;
Implementer(s):
Search NeuronDB for information about:  Dentate gyrus granule GLU cell;
/
na8st
dat
hoc
mod
README.txt
ap.py
ap_utils.py
mech.py
qmatrix.py
stfio_plot.py
                            
"""
Computes sodium currents using pyqmatrix or NEURON.
"""
# C. Schmidt-Hieber, University College London
# 2010-07-01
#
# accompanies the publication:
# Schmidt-Hieber C, Bischofberger J. (2010)
# Fast sodium channel gating supports localized and efficient 
# axonal action potential initiation.
# J Neurosci 30:10233-42

import numpy as np
import time
import sys

import qmatpy as qmat
from neuron import h
import mech
import stfio_plot
import fft_filter

v_rev_na = 55.6
gna_soma = 188

class gating_model:
    def __init__(self, func, act_func, inact_func, title, pars=None,
                 filename = None, 
                 linestyle="-k",
                 plot=False, 
                 nrn_mech="", nrn_vshift=0, nrn_hScale=1.0,
                 h_vshift=0, plot_vshift=0):
        self.func = func
        self.act_func = act_func
        self.inact_func = inact_func
        self.title = title
        self.linestyle = linestyle
        if pars==None and filename==None:
            print "Error initializing model", title, "aborting now"
            sys.exit(1)
        if pars == None:
            self.pars = np.loadtxt(file(filename))
        else:
            self.pars = pars
        self.filename = filename    
        self.plot = plot
        self.nrn_mech = nrn_mech
        self.nrn_vshift = nrn_vshift
        self.nrn_hScale = nrn_hScale
        self.h_vshift = h_vshift
        self.plot_vshift = plot_vshift

def init_st8_model():
    file_st8_soma = "dat/soma_st8.txt"
    file_st8_axon = "dat/axon_st8.txt"
    st8_model = \
        gating_model(init_matrix, init_act, init_inact, 
                     "soma_st8_nrn", filename=file_st8_soma,
                     nrn_mech="na8st")

    return st8_model

def init_act(V, p, max_rate = 8e+03):
    ret = np.array([ \
            p[0]*np.exp(p[1]*V),
            p[2]*np.exp(-p[3]*V),

            p[4]*np.exp(p[5]*V),
            p[6]*np.exp(-p[7]*V),

             p[8]*np.exp( p[9]*V),
            p[10]*np.exp(-p[11]*V)
            ])
    if max_rate > 0:
        ret = ret * max_rate / (ret + max_rate)
    return ret

def init_inact(V, p, max_rate = 8e+03, h_vshift=0):
    ret = np.array([ \
            p[15]/(1+p[16]*np.exp(p[17]*(V-h_vshift))),
            p[12]/(1+p[13]*np.exp(-p[14]*(V-h_vshift)))
            ])
    if max_rate > 0:
        ret = ret * max_rate / (ret + max_rate)
    return ret

def init_matrix(V, model, debug=False):
    """Initialises a Q matrix for the 8-state gating scheme
    """
    (a_1, b_1, a_2, b_2, a_3, b_3) = init_act(V, model.pars)
    (a_h, b_h) = init_inact(V, model.pars, h_vshift=model.h_vshift)

    # calculate rates from current parameter estimates:
    #                 1    2    3    4    5    6    7    8
    Q = np.array([[   0, b_3,   0,   0,   0,   0,   0, b_h], \
                  [ a_3,   0, b_2,   0,   0,   0, b_h,   0], \
                  [   0, a_2,   0, b_1,   0, b_h,   0,   0], \
                  [   0,   0, a_1,   0, b_h,   0,   0,   0], \
                  [   0,   0,   0, a_h,   0, a_1,   0,   0], \
                  [   0,   0, a_h,   0, b_1,   0, a_2,   0], \
                  [   0, a_h,   0,   0,   0, b_2,   0, a_3], \
                  [ a_h,   0,   0,   0,   0,   0, b_3,   0]])

    # Update diagonal elements:
    qmat.init_matrix(Q)

    if debug: 
        sys.stdout.write("Initialised 8-state Q matrix: %s\n" % Q)

    return Q

def init_nrn_patch(model, dt):
    h("load_file(\"stdrun.hoc\")")
    h("load_file(\"./hoc/config.hoc\")")
    h.celsius = 24.0
    h.dt = dt
    h.steps_per_ms = 1.0/h.dt

    # create a patch:
    patch = h.Section()
    patch.L = 1
    patch.diam = 1
    patch.Ra = 1e-9
    
    # insert mechanism:
    patch.insert(model.nrn_mech)
    patch.ena = v_rev_na

    if model.nrn_mech == "na8st":
        # read somatic best-fit rates from file:
        rates = np.loadtxt(model.filename)
        for seg in patch:
            mech.set_rates_na8st(seg, rates, vshift_inact=0)
        # vShift is global, so we don't set it for a segment
        h("vShift_na8st = %f" % model.nrn_vshift) 
        h("vShift_inact_na8st = %f" % model.h_vshift)

    # insert a v clamp:
    vc = h.SEClamp(patch(0.5))
    vc.rs = 1e-9

    # record current:
    irec = h.Vector()
    irec.record(patch(0.5)._ref_ina, sec=patch)

    return patch, vc, irec

def activation(model, v_range, dt=0.001, filter=-1, plot_fit=True):
    traces, pulses = [], []
    times_qm, times_nrn = [], []
    trange = np.arange(0, 8.0, dt)

    # initialise Q-matrix
    Q_m120 = model.func(-120.0, model)
    p_m120 = qmat.p_inf(Q_m120)

    # initialise NEURON
    patch, vc, irec = init_nrn_patch(model, dt)
    vc.dur1 = trange[-1]
    h.tstop = vc.dur1

    for (n_v, v) in enumerate(v_range):
        # Q-Matrix
        time0 = time.time()
        Qv = model.func(v, model)
        pv = qmat.p_inf(Qv)
        lv, Av = qmat.mat_solve(Qv)
        trace = \
            qmat.p(trange, p_m120, pv, lv, Av)[0]# * \
            # (v-v_rev_na) * 1e-3 * gna_soma
        trace /= np.max(trace)

        times_qm.append(time.time()-time0)
        if filter > 0:
            trace = fft_filter.gaussian_filter(trace, filter, dt)
        traces.append(
            stfio_plot.timeseries(trace, dt, 
                                  xunits="ms", 
                                  yunits="",
                                  linestyle=model.linestyle, linewidth=2.0))

        # NEURON
        time0 = time.time()
        vc.amp1 = v

        h.v_init = -120.0
        h.init()
        h.run()
        times_nrn.append(time.time()-time0)
        trace_nrn = np.array(irec)
        trace_nrn /= np.min(trace_nrn)
        # trace_nrn *= norm

        if filter > 0:
            trace = fft_filter.gaussian_filter(trace, filter, dt)
        traces.append(
            stfio_plot.timeseries(trace_nrn, h.dt, 
                                  xunits="ms",
                                  yunits="",
                                  linestyle="--r", linewidth=2.0))

        pulse = np.array([v for i in range(len(trace))])
        pulse[0] = -120.0
        pulses.append(
            stfio_plot.timeseries(pulse, dt, 
                                  xunits="ms",
                                  yunits="mV",
                                  linestyle="-k", linewidth=2.0))

    stfio_plot.plot_traces(traces, pulses)

    stfio_plot.plt.show()

    sys.stdout.write("NEURON: %f\n" % np.array(times_nrn).mean())
    sys.stdout.write("Q-Matrix: %f\n" % np.array(times_qm).mean())

if __name__=="__main__":
    model = init_st8_model()
    vrange = np.arange(-70.0, 40.0, 10.0)
    activation(model, vrange)

Loading data, please wait...