Neocort. pyramidal cells subthreshold somatic voltage controls spike propagation (Munro Kopell 2012)

 Download zip file   Auto-launch 
Help downloading and running models
Accession:136309
There is suggestive evidence that pyramidal cell axons in neocortex may be coupled by gap junctions into an ``axonal plexus" capable of generating Very Fast Oscillations (VFOs) with frequencies exceeding 80 Hz. It is not obvious, however, how a pyramidal cell in such a network could control its output when action potentials are free to propagate from the axons of other pyramidal cells into its own axon. We address this problem by means of simulations based on 3D reconstructions of pyramidal cells from rat somatosensory cortex. We show that somatic depolarization enables propagation via gap junctions into the initial segment and main axon, while somatic hyperpolarization disables it. We show further that somatic voltage cannot effectively control action potential propagation through gap junctions on minor collaterals; action potentials may therefore propagate freely from such collaterals regardless of somatic voltage. In previous work, VFOs are all but abolished during the hyperpolarization phase of slow-oscillations induced by anesthesia in vivo. This finding constrains the density of gap junctions on collaterals in our model and suggests that axonal sprouting due to cortical lesions may result in abnormally high gap junction density on collaterals, leading in turn to excessive VFO activity and hence to epilepsy via kindling.
Reference:
1 . Munro E, Kopell N (2012) Subthreshold somatic voltage in neocortical pyramidal cells can control whether spikes propagate from the axonal plexus to axon terminals: a model study. J Neurophysiol 107:2833-52 [PubMed]
Model Information (Click on a link to find other models with that property)
Model Type: Realistic Network; Neuron or other electrically excitable cell; Axon;
Brain Region(s)/Organism: Neocortex;
Cell Type(s): Neocortex L5/6 pyramidal GLU cell; Neocortex U1 L2/6 pyramidal intratelencephalic GLU cell;
Channel(s): I Na,t; I K; I Sodium; I Potassium;
Gap Junctions: Gap junctions;
Receptor(s):
Gene(s):
Transmitter(s):
Simulation Environment: NEURON; MATLAB;
Model Concept(s): Oscillations; Detailed Neuronal Models; Axonal Action Potentials; Epilepsy;
Implementer(s): Munro, Erin [ecmun at math.bu.edu];
Search NeuronDB for information about:  Neocortex L5/6 pyramidal GLU cell; Neocortex U1 L2/6 pyramidal intratelencephalic GLU cell; I Na,t; I K; I Sodium; I Potassium;
/
Munro_Kopell_corticalcontrol
NEURON
cell_geoms
run_files
readme.txt
extrema.mod
gap.mod
k2_Traub.mod *
ka_Traub.mod *
kdr_Jonas.mod
kdr_Traub.mod
kdr_Yu.mod
naf_Jonas.mod
naf_Traub.mod
naf_Yu.mod
pas_basket.mod
pas_chand.mod
030625DS2.hoc
axon_templates.hoc
C040896A-P3.hoc
C040896A-P3axgeom.hoc
C230797B-P4.hoc
C270999B-P2axgeom.hoc
C280199C-P1.hoc
C290500C-P1axgeom.hoc
cell_templates.hoc
expcell_templates.hoc
gap_junction.hoc
gj_propagation_test.ses
junction_stats.hoc
kinetics.hoc
kinetics_wholecell.hoc
mosinit.hoc
propagation_test.ses
PropagationSearch.hoc
simulation_base.hoc
vs-arg_cutoff.hoc
vs-arg_cutoff_Jonas.hoc
vs-expcell_gj.hoc
vs-expcell_gj_gL.hoc
vs-expcell_gj_Jonas.hoc
vs-expcell_gjCC.hoc
vs-expcell_gjISgNa.hoc
vs-expcell_gjsISgNa.hoc
vs-generic_cutoff.hoc
vs-generic_cutoff_Jonas.hoc
                            
load_file("nrngui.hoc")

func gr(){
  return ($2^1.5 + $3^1.5)/($1^1.5)
}

func elength(){
  // calculate the electrotonic length as given by Tuckwell p. 137
  // first input is diameter
  d = $1
  return 0.5*sqrt(d/(Ra*g_pas))*100 // 100 is for conversion to um
}

func timed_run(){local x,y
  x = startsw()
  run()
  y = startsw() - x
  return y
}

func round(){local x,up,down
    x = $1
    down = int(x)
    up = down + 1
    if(x-down <= up-x){
	return down
    }else{
	return up
    }
}

n_cells = 0

load_file("axon_templates.hoc")
load_file("cell_templates.hoc")
load_file("expcell_templates.hoc")
load_file("junction_stats.hoc")
load_file("gap_junction.hoc")

strdef cell_name // neuromorpho.org cell name
objectvar test_axon
objectvar stim1,stim2
objectvar v_extstim, v_stim, v_prop, st_extstim, st_stim, st_prop
objectvar t_f //firing times of extstim_site, stim_site, and prop_site
objref axon1,axon2,gj
objref v_soma1,v_soma2
objref nil // NULL reference for comparison
dx = 1
//secondorder = 1
dt = 0.001
Dt = dt//0.1
syn_g = 0.001
syn_del = 5

func courant_number(){
  // calculate the Courant number as defined by Iserles p. 271
  // Factor to get ratio unitless conferred by John Burke
  return (dt/dx^2)*(test_axon.axon[test_axon.junction_site].diam/2)/(2*Ra*cm)*10^7
}

proc load_axon(){local nv,i,j localobj sub_sections,sec_ref
    if($1==0){
        test_axon = new SimpleAxon($2,dx)
    }else if($1==1){
        test_axon = new TypicalAxon($2,dx)
    }else if($1==2){
        test_axon = new ComplexAxon($2,dx)
    }else if($1==3){
        test_axon = new TypicalCell($2,dx)
    }else if($1==4){
        test_axon = new ShortISCell($2,dx)
    }else if($1==5){
        test_axon = new MedISCell($2,dx)
    }else if($1==6){
        test_axon = new ComplexShortISCell($2,dx)
    }else if($1==7){ //generic cell
	      test_axon = new GenericCell($s3,$4,$5,$6,$7,$2,dx)
	      // $s3 = cell name
	      // $4 = IS
	      // $5 = prop_site
	      // $6 = extstim_site
	      // $7 = junction_site
	      // $2 = kinetics
    }else if($1==8){ // Branch-Distance cell for experiments
        if(numarg()==5){
            test_axon = new BranchDistCell($2,dx,$3,$4,$5)
        }else if(numarg()==6){
            test_axon = new BranchDistCell($2,dx,$3,$4,$5,$6)
        }else{// if(numarg()==7){
            test_axon = new BranchDistCell($2,dx,$3,$4,$5,$6,$7)
        }
        // kinetics = $1, dx=$2, 
        // branch ratio = $3
        // layer = $4
        // branch 1 distance = $5
        // branch 2 distance = $6
        // branch 3 distance = $7
    }else{ // Branch-Distance-Alt cell for experiments
        if(numarg()==7){
            test_axon = new BranchDistCellAlt($2,dx,$3,$4,$5,$6,$7)
        }else if(numarg()==8){
            test_axon = new BranchDistCellAlt($2,dx,$3,$4,$5,$6,$7,$8)
        }else{// if(numarg()==9){
            test_axon = new BranchDistCellAlt($2,dx,$3,$4,$5,$6,$7,$8,$9)
        }
        // kinetics = $1, dx=$2, 
        // branch ratio = $3
        // soma ratio = $4
        // ell_c = $5 : electronic length of cone
        // main diam = $6
        // branch 1 distance = $7
        // branch 2 distance = $8
        // branch 3 distance = $9
    }
    n_cells = 1
    access test_axon.axon[test_axon.extstim_site]
    kinetics = $2
    stim_loc = test_axon.stim_loc
    extstimrec_loc = test_axon.extstimrec_loc
    
    test_axon.axon[test_axon.extstim_site]{
        stim1 = new IClamp(0.5)
        stim2 = new IClamp(0.5)
    }
    
    stim1.del = 5
    stim1.dur = 0.3125
    stim1.amp = 0.2
    stim2.del = 10
    stim2.dur = 0.3125
    stim2.amp = 0.2
    
    // cutoff for spike to start is e_pas+(ena-e_pas)/3
    // cutoff for spike to end is e_pas + (ena-e_pas)/10
    test_axon.axon[test_axon.extstim_site]{
        spike_start = e_pas + (ena-e_pas)/3
        if(kinetics==1){
            spike_end = e_pas + (ena-e_pas)/6
        }else{
            spike_end = e_pas + (ena-e_pas)/4
        }
    }
    print "in load_axon test_axon.axon[test_axon.junction_site].diam=", test_axon.axon[test_axon.junction_site].diam
}

proc setup_session(){
  load_file("propagation_test.ses")
}

proc load_gj_axons(){local sec localobj sec1,sec2
    // load two BranchDistCells and attach them via gap junction
    rat = $1
    layer = $2
    sec = $3
    loc = $4
    g_gj = $5
    if(numarg()>5){
	      kinetics = $6
    }else{
	      kinetics = 4
    }
    
    //load axon1 and axon2
    print "setting up axon2"
    axon2 = new BranchDistCell(kinetics,dx,rat,layer)
    print "n_cells = ", n_cells
    if(kinetics==4){
	      print "axon2.axon[IS].gbar_nafTraub = ", axon2.axon[axon2.IS].gbar_nafTraub
    }
    print "setting up axon1"
    axon1 = new BranchDistCell(kinetics,dx,rat,layer)
    test_axon = axon1
    print "n_cells = ", n_cells
    if(kinetics==4){
	      print "axon1.axon[IS].gbar_nafTraub = ", axon1.axon[axon1.IS].gbar_nafTraub
	      print "axon2.axon[IS].gbar_nafTraub = ", axon2.axon[axon2.IS].gbar_nafTraub
    }
    access test_axon.axon[test_axon.extstim_site]
    stim_loc = test_axon.stim_loc
    extstimrec_loc = test_axon.extstimrec_loc
    
    // set up external stimulus
    setup_axon_stim()
    
    // set spike_start and spike_end
    test_axon.axon[test_axon.extstim_site]{
        spike_start = e_pas + (ena-e_pas)/3
        if(kinetics==1){
            spike_end = e_pas + (ena-e_pas)/6
        }else{
            spike_end = e_pas + (ena-e_pas)/4
        }
    }
    
    // put gap junction between cells
    axon1.axon[sec]{
        sec1 = new SectionRef()
    }
    axon2.axon[sec]{
        sec2 = new SectionRef()
    }
    gj = new GapJunction(sec1,sec2,loc,g_gj)    
    
    print "tstop = ", tstop
}

proc setup_soma_stim(){local A,curr,curr_min
    // put stimulus in soma instead of extstim site
    // for two gap junction coupled axons
    axon1.soma{
        stim1 = new IClamp(0.5)
        A = PI*diam*L + 2*(diam/2)^2
        curr = 0.1*g_pas*A
    }
    
    if(axon1.layer==5){ // minimum current checked manually for layers 2 and 5
        curr_min = 0.05
    }else{
        curr_min = 0.03
    }
    if(curr>curr_min){
        stim1.amp = curr
    }else{
        stim1.amp = curr_min
    }
    
    stim1.del = 5
    stim1.dur = 40
    stim2.del = 40
    stim2.dur = 0
    stim2.amp = 0
}    

proc setup_axon_stim(){
    test_axon.axon[test_axon.extstim_site]{
        stim1 = new IClamp(0.5)
        stim2 = new IClamp(0.5)
    }
    stim1.del = 5
    stim1.dur = 0.3125
    stim1.amp = 0.2
    stim2.del = 10
    stim2.dur = 0.3125
    stim2.amp = 0.2
}

proc setup_gj_session(){
  load_file("gj_propagation_test.ses")
}

proc init(){
  n_extstim = 0
  n_stim = 0
  n_prop = 0
  t_f = new Vector(6,-1)
  v_extstim = new Vector(int(tstop/Dt)+1)
  v_extstim.record(&test_axon.extstim_sr.sec.v(extstimrec_loc),Dt)
  v_stim = new Vector(int(tstop/Dt)+1)
  v_stim.record(&test_axon.stim_sr.sec.v(stim_loc),Dt)
  v_prop = new Vector(int(tstop/Dt)+1)
  if(axon2==nil){
    v_prop.record(&test_axon.axon[test_axon.prop_site].v(0.5),Dt)
  }else{
    v_prop.record(&axon2.axon[axon2.prop_site].v(0.5),Dt)
  } 
  if(axon1 != nil){
      v_soma1 = new Vector(int(tstop/Dt)+1)
      v_soma1.record(&axon1.soma.v(0.5))
      v_soma2 = new Vector(int(tstop/Dt)+1)
      v_soma2.record(&axon2.soma.v(0.5))
  }
  st_extstim = new Vector()
  st_stim = new Vector()
  st_prop = new Vector()
  test_axon.axon[test_axon.IS].g_pas = test_axon.axon[test_axon.prop_site].g_pas
  forall{
    for(x){
      v(x) = e_pas(x)
    }
  }

  finitialize()//test_axon.axon[test_axon.extstim_site].e_pas)
}

obfunc spike_times(){local ind,n_spikes localobj v_vec,v_sub,t_sub,spikes
    // take in a vector with voltage data, and count the number of spikes
    spikes = new Vector(10)
    n_spikes = 0
    
    v_vec = $o1
    v_sub = new Vector()
    v_sub.copy(v_vec)
    t_sub = new Vector(v_sub.size())
    t_sub.indgen(Dt)
    while(1){
        ind = v_sub.indwhere(">=",spike_start)
        if(ind != -1){
            if(spikes.size() == n_spikes){
                spikes.resize(spikes.size()+10)
            }
            spikes.x[n_spikes] = t_sub.x[ind]
            n_spikes = n_spikes + 1
            v_sub.remove(0,ind)
            t_sub.remove(0,ind)
            ind = v_sub.indwhere("<=",spike_end)
            if(ind != -1){
                v_sub.remove(0,ind)
                t_sub.remove(0,ind)
            }else{
                break
            }
        }else{
            break
        }
    }
    spikes.resize(n_spikes)
    return spikes
}

proc calc_spikes(){local i,n
    // calculate spike times based on the last simulation
    st_extstim = spike_times(v_extstim)
    n_extstim = st_extstim.size()
    st_stim = spike_times(v_stim)
    n_stim = st_stim.size()
    st_prop = spike_times(v_prop)
    n_prop = st_prop.size()
    n = 0
    for(i=0;i<2 && i<st_extstim.size();i=i+1){
        t_f.x[n] = st_extstim.x[i]
        n = n + 1
    }
    n = 2
    for(i=0;i<2 && i<st_stim.size();i=i+1){
        t_f.x[n] = st_stim.x[i]
        n = n + 1
    }
    n = 4
    for(i=0;i<2 && i<st_prop.size();i=i+1){
        t_f.x[n] = st_prop.x[i]
        n = n + 1
    }
}

func calc_CC(){local v1max,v2max
    // compute coupling coefficient based on change in somatic voltage
    v1max = v_soma1.max()
    v2max = v_soma2.max()
    return (v2max-v2_1)/(v1max-v1_1)
}

proc advance(){local vmax
    fadvance()
    //if(t>syn_del){
    //    test_axon.axon[test_axon.IS].g_pas=syn_g
    //}
    if(axon1 != nil){
        if(t<=5 && t-int(t)<dt){
            v1_1 = axon1.soma.v(0.5)
            v2_1 = axon2.soma.v(0.5)
        }else if(t<=10 && t-int(t)<dt){
            v1_2 = axon1.soma.v(0.5)
            v2_2 = axon2.soma.v(0.5)
        }
    }
    if(t>stim2.del+1 && t-int(t)<dt){
        vmax = test_axon.axon[test_axon.extstim_site].e_pas
        forall{
            for(x){
                if(v(x)>vmax){
                    vmax = v(x)
                }
            }
        }
        if(vmax<spike_end){
            print "t=", t, ", vmax = ", vmax
            stoprun = 1
        }else{
            print "t=", t, ", vmax = ", vmax, " > ", spike_end
        }
    }
}

load_file("PropagationSearch.hoc")

proc run_search(){localobj cutoffs,vcutoffs,cutoff_file,run_file,ps
    // run a propagation search, printing cutoff information to cutoff_file 
    // ($o1) and saving the simulation database in the file run_file_name ($s2)
    // find cutoffs up to resolution e(-$3)
  cutoff_file = $o1
  run_file = new File()
  run_file.wopen($s2)
  ps = new PropagationSearch()
  ps.kinetics = kinetics
  
  if(numarg()>3){ // do ISgNa cutoff
      print "finding ISgNa cutoff"
      cutoffs = ps.find_cutoffs(ps.pc_ISgNa,$3)
  }else{
      print "finding regular gNa cutoff"
      cutoffs = ps.find_cutoffs(ps.pc_gNa,$3)
  }
  
  if(ps.n_simulations>0){
      ps.simulation_database.resize(ps.n_simulations,ps.simulation_database.ncol)
      ps.simulation_database.fprint(run_file,"%g\t")
  }
  run_file.close()

  vcutoffs = cutoffs.transpose().to_vector()
  vcutoffs.printf(cutoff_file,"%g\t")
  cutoff_file.flush()
}

proc refine_search(){local ncol,nrow,exists,parameter_choice localobj cutoffs,vcutoffs,cutoff_file,run_file,ps,run_data
    // run a propagation search, printing cutoff information to cutoff_file 
    // ($o1) and saving the simulation database in the file run_file_name ($s2)
    // find cutoffs up to resolution e(-$3)
    cutoff_file = $o1
    ps = new PropagationSearch()
    ps.kinetics = kinetics
    if(numarg()>3){
        parameter_choice = ps.pc_ISgNa
    }else{
        parameter_choice = ps.pc_gNa
    }
    
    run_file = new File()
    exists = run_file.ropen($s2)
    if(exists){
	      run_data = new Matrix(10,10)
	      run_data.scanf(run_file)
	      run_file.close()
	      cutoffs = ps.find_cutoffs(parameter_choice,$3,run_data)
    }else{
	      cutoffs = ps.find_cutoffs(parameter_choice,$3)
    }
	
    run_file.wopen($s2)
    ps.simulation_database.resize(ps.n_simulations,ps.simulation_database.ncol)
    ps.simulation_database.fprint(run_file,"%g\t")
    run_file.close()

    vcutoffs = cutoffs.transpose().to_vector()
    vcutoffs.printf(cutoff_file,"%g\t")
    cutoff_file.flush()
}

proc set_arg(){
    // set arguments for running vs-arg_exp
    geom = $1
    extstim_site = $2
    junction_site = $3
}

proc set_generic_arg(){
    // set arguments for *-generic_exp.hoc
    cell_name = $s1 // cell geometry
    print "in set_generic_arg: cell_name is ", cell_name
    IS = $2 // initial segment
    prop_site = $3
    extstim_site = $4
    junction_site = $5
}

proc set_expcell_arg(){
    // set arguments for *-expcell*.hoc
    layer=$1
    ratio = $2
    vs = $3
    g_basket = $4
    g_chand = $5
}

proc set_expcell_dist(){
    // set distance arguments for expcell experiments
    dist1_beg = $1
    dist1_end = $2
    if(numarg()>2){
	dist2_beg = $3
	dist2_end = $4
	if(numarg()>4){
	    dist3_beg = $5
	    dist3_end = $6
	}
    }
}

proc set_g_chand(){local needISchild
    // set the passive current that mimics chandelier cells on first
    // 40 um of IS
    test_axon.axon[test_axon.IS]{
	needISchild = 1
        for(x,0){
            if(x*L<40){
                g_pasChand(x) = $1
            }else{
		needISchild = 0
		break
	    }
        }
    }
    if(needISchild){
	test_axon.axon[$2]{
	    for(x){
		if(test_axon.axon[test_axon.IS].L + x*L < 40){
		    g_pasChand(x) = $1
		}
	    }
	}
    }
}

proc set_IS_myelin(){
    // with argument "1", put myelin between 40 um from soma 
    // to first branch point
    test_axon.axon[test_axon.IS]{
        if($1){ // put myelin on
            for(x,0){
                if(x*L>40){
                    g_pas(x) = g_pas(0)/5000
                    cm(x) = cm(0)/50
                    if(kinetics==0 || kinetics==4){
                        gbar_nafTraub(x) = 0
                        gbar_kdrTraub(x) = 0
                    }
                }
            }
        }else{ // take myelin off
            for(x,0){
                if(x*L>40){
                    g_pas(x) = test_axon.axon[test_axon.prop_site].g_pas
                    cm(x) = test_axon.axon[test_axon.prop_site].cm
                    if(kinetics==0 || kinetics==4){
                        gbar_nafTraub(x) = test_axon.axon[test_axon.prop_site].gbar_nafTraub
                        gbar_kdrTraub(x) = test_axon.axon[test_axon.prop_site].gbar_kdrTraub
                    }
                }
            }
        }
    }
}

proc set_soma_stim(){
    // mimic soma being stimulated, either by far away PSPs or directly
    // arguments: amp, del, duration
    test_axon.se.amp2 = $1
    test_axon.se.amp3 = test_axon.se.amp1
    test_axon.se.dur1 = $2
    test_axon.se.dur2 = $3
    test_axon.se.dur3 = tstop
}

proc set_soma_leak(){local e,g localobj cell,sref
    cell = $o1
    e = $2
    g = $3
    cell.soma{
        e_pas = e
        g_pas = g
        sref = new SectionRef()
    }
    for(i=0;i<=sref.nchild-1;i=i+1){
        sref.child[i]{
	    ifsec "dendrite"{
		for(x){
                    if(diam(x)>5){
			e_pas(x) = e
			g_pas(x) = g
                    }
		}
	    }
        }
    }
}

proc set_basket(){local e,g localobj cell,sref
    cell = $o1
    e = $2
    g = $3
    cell.soma{
        e_pasBasket = e
        g_pasBasket = g
        sref = new SectionRef()
    }
    for(i=0;i<=sref.nchild-1;i=i+1){
        sref.child[i]{
            e_pasBasket = e
            for(x){
                if(diam(x)>5){
                    g_pasBasket(x) = g
                }
            }
        }
    }
}

proc set_extstim_site(){
    test_axon.extstim_site = $1
    test_axon.junction_site = $2
    
    test_axon.stim_loc = 0
    test_axon.extstimrec_loc = 0
    choose_stim_site(test_axon,kinetics)
    
    test_axon.axon[$1]{
        stim1 = new IClamp(0.5)
        stim2 = new IClamp(0.5)
    }
    
    stim1.del = 5
    stim1.dur = 0.3125
    stim1.amp = 0.2
    stim2.del = 10
    stim2.dur = 0.3125
    stim2.amp = 0.2
}


Loading data, please wait...