CA1 pyramidal neuron: nonlinear a5-GABAAR controls synaptic NMDAR activation (Schulz et al 2018)

 Download zip file   Auto-launch 
Help downloading and running models
Accession:258867
The study shows that IPSCs mediated by a5-subunit containing GABAA receptors are strongly outward-rectifying generating 4-fold larger conductances above -50?mV than at rest. Experiments and modeling show that synaptic activation of these receptors can very effectively control voltage-dependent NMDA-receptor activation in a spatiotemporally controlled manner in fine dendrites of CA1 pyramidal cells. The files contain the NEURON code for Fig.8, Fig.S8 and Fig.S9 of the paper. The model is based on the model published by Bloss et al., 2017. Physiological properties of GABA synapses were modified as determined by optogenetic activation of inputs during voltage-clamp recordings in Schulz et al. 2018. Other changes include stochastic synaptic release and short-term synaptic plasticity. All changes of mechanisms and parameters are detailed in the Methods of the paper. Simulation can be run by starting start_simulation.hoc after running mknrndll. The files that model the individual figures have to be uncommented in start_simulation.hoc beforehand.
Reference:
1 . Schulz JM, Knoflach F, Hernandez MC, Bischofberger J (2018) Dendrite-targeting interneurons control synaptic NMDA-receptor activation via nonlinear a5-GABAA receptors. Nat Commun 9:3576 [PubMed]
Citations  Citation Browser
Model Information (Click on a link to find other models with that property)
Model Type: Neuron or other electrically excitable cell; Dendrite; Synapse;
Brain Region(s)/Organism: Hippocampus; Mouse;
Cell Type(s): Hippocampus CA1 pyramidal GLU cell;
Channel(s): I h; I A;
Gap Junctions:
Receptor(s): GabaA; GabaB; AMPA; NMDA;
Gene(s):
Transmitter(s): Gaba; Glutamate;
Simulation Environment: NEURON;
Model Concept(s):
Implementer(s): Schulz, Jan M [j.schulz at unibas.ch];
Search NeuronDB for information about:  Hippocampus CA1 pyramidal GLU cell; GabaA; GabaB; AMPA; NMDA; I A; I h; Gaba; Glutamate;
/
Alpha5_NMDA_CA1_pyr
README.html
dists.mod *
eff.mod *
exc.mod *
gabab.mod
h.mod
id.mod *
inh.mod
kad.mod *
kap.mod *
kdr.mod *
na3.mod *
nmdaSyn.mod
syns.mod *
tonic.mod
activateExcitation.hoc
activateInhibition_JMS.hoc
addChannels_JMS.hoc
addExcitation_JMS.hoc
addVgatInhibition_JMS.hoc
channelParameters.hoc
Connect_Stimulator2ExcSyn.hoc
Connect_Stimulator2InhSyn.hoc
Fig8_tuft_NMDA_spike.hoc
FigS8_SR_SLM_burst_stim.hoc
FigS9_test_TI.hoc
flagVgatInhibition_JMS.hoc
Generate_Stimulator.hoc
getBranchOrder.hoc *
idMorph.hoc
inhibitionBiophysics_JMS.hoc
initializationAndRun.hoc *
loadMorph.hoc *
mosinit.hoc
naceaxon.nrn *
Print-to-File.hoc
processMorph.hoc *
proofreadMorph.hoc *
resetNSeg.hoc *
screenshot.png
start_simulation.hoc
synHelperScripts.hoc
SynStim_SR_SLM_control.hoc
SynStim_SR_SLM_noInh.hoc
SynStim_SR_SLM_redInh.hoc
SynStim_SR_SLM_TI.hoc
tuft_NMDA_spike_fast.hoc
tuft_NMDA_spike_noRect.hoc
twinApical.swc *
update_Synapses.hoc
                            
// THIS SCRIPT FACILITATES INTERPLAY BETWEEN ANATOMICAL DATA AND COMPUTATIONAL
// HANDLING OF ANATOMICAL DATA.

// Some of the importing procedure can be complicated by the fact that individual
// cables (as defined within NEURON) do not give a perfect one-to-one
// correspondence with branches; for example, a given branch (as viewed 
// strictly by morphology) may be composed of several branches (ie, sections in 
// NEURON) each only having a single daughter.  Need a way to construct an "effective"
// morphology so that the statistics used for synapse placement truly reflects
// the morphology, rather than the NEURON partitioning of the morphology.

// First, for all neurites, construct an array of SectionLists that correspond
// to effectively one branch.
// 
// The implementation is the following:
// 1.  Start a given section.  Extract a subtree, and identify whether the
// 	longest arc along the subtree is sufficiently close to the whole
//	length of the subtree.  If this is the case, keep it.
objref brEff[1000] // preallocate a large number

maxDistDiff = 20 // distance, in microns, to allow the max path length dist
		// to vary from the total length and still create an "effective"
		// branch.
numEffBr = 0 // number of effective branches.

// 050815: write a script that organises all sections into a hierarchy.  This
// is relevant for constructing the effective branches below; when interating
// over the morphology, need to do so in a somato-centric way (ie proceeding
// from parents to children) because the algorithm iterates down family trees,
// and will not properly work if daughter branches are visited before parent
// branches.
objref orgSecList
orgSecList = new SectionList()
soma.sec { orgSecList.subtree() }


// ORGANISE TUFT INTO EFFECTIVE SECTIONS.
objref curTree,tempSecList,curSec
bifThres = 5
tempSecList = new SectionList() // will contain all the sections to iterate over
tempLen = 0
forsec orgSecList {
	curSec = new SectionRef()
	// Check if current section is previously added to an effective branch;
	// if so, break.  
	isUsed=0



	for ii=1,numEffBr{
		if(sectionRefInList(curSec,brEff[ii-1])){
			isUsed=1
		}
	}
	
	
	if(isUsed<0.1){
		// proceed down parent dendrite, appending all sections until
		// encounter a bifurcation with both branches > threshold.
		
		brEff[numEffBr] = new SectionList()
		tempSecList.append()
		numSecList = 1

		
		while(numSecList>0.1){
			forsec tempSecList {
				
				// remove from section list, add to branch tree
				curSec = new SectionRef()
				tempSecList.remove()
				brEff[numEffBr].append()
				// check out outstanding tree.
				
				if(curSec.nchild<0.1){
					// childless, do nothing
				}else{
					if(curSec.nchild<1.1){
						// one daugheter.  add.
						curSec.child[0] { tempSecList.append() }
					}else{
						// two+ children.  dont take if each have length > bifThres;
						// otherwise, add to tree and keep going...
						minLen = 100000
						for nn=1,curSec.nchild(){
							curSec.child[nn-1] {
								tempLen = L
							//	if(tempLen<bifThres){ tempSecList.append() }
								if(tempLen<minLen){minLen=tempLen}
							}
						}
						if(tempLen>bifThres){
							// all daughters created longer than bifThres distance.
							// do nothing.
						}else{
							minLen = 100000
							for nn=1,curSec.nchild(){
								curSec.child[nn-1] {
									tempLen = L
									tempSecList.append()
								}
							}
						}
					}
						
				}
			}
			numSecList = 0
			forsec tempSecList { numSecList += 1 }
		}		
		numEffBr+=1
	}
}
			

//print "The number of effective branches is ",numEffBr

// Implement a check to see the number of sections assigned to clusters, and
// make sure it covers all sections.
numInClust = 0
numInClustExpect = 0
for ii=1,numEffBr{
	forsec brEff[ii-1] {
		numInClust = numInClust + 1
	}
}
forall {
	numInClustExpect = numInClustExpect + 1
}

if(abs(numInClust-numInClustExpect)>0.1){
	print "The number of sections in effective branches does not equal the total number of sections.  Halting."
	stop
}	

// Implement a check to make sure that there is no overlap in the elements of clusters.
overlapFlag=0
for ii=1,numEffBr-1{
	forsec brEff[ii-1] {
		curSec = new SectionRef()
		for jj=ii+1,numEffBr{
			if(sectionRefInList(curSec,brEff[jj-1])){
				overlapFlag=1
			}
		}
	}
}
if(overlapFlag){
	print "There is overlap in sections found across different effective branches. Halting."
	stop
}

// Create features associated with effective branches.
forall {
	insert eff
	L_eff = -1 // effective length
	d_eff = -1 // effective distance along length
	x_eff = -1 // effective x value
}


// create features associated with effective branches.  do just lengths at this
// point, as this is how things are typically processed.
for nn=1,numEffBr{
	lEffKeeper = 0 // effective length
	visitedFirst = 0 // have visited first section?
	forsec brEff[nn-1] {
		if(visitedFirst<0.1){
			visitedFirst = 1
			distance()
			for(x,0){
				d_eff(x) = x*L
			}
			lEffKeeper = L // effective branch length
			maxDist = L
		}else{
			for(x,0){
				d_eff(x) = distance(x)
			}
			lEffKeeper += L
			if(distance(1)>maxDist){
				maxDist = distance(1)
			}
		}
	}
	
	forsec brEff[nn-1] {
		L_eff = maxDist
		for(x,0){
			x_eff(x) = distance(x)/maxDist
		}
	}
}

//// 091715: added in printing of parameters of morphologies.
//print "Delete this in processMorph.hoc later"
//for nn=1,numEffBr{
//	print 
//	forsec brEff[nn-1] {
//		print "\t",secname()," ",L_eff
//	}
//}

	
	
// function that determines whether a given sectionlist is terminal.  By the
// way the effective branches were created, this evaluates to whether all of
// the daughter branches of the given sectionlist are also contained within
// the sectionlist.
// $o1: SectionList instance to examine.
// OUTPUT: logical representing whether the sectionlist is termina..
func isTermEff() {local withinList localobj tempSecKeeper,theTempSec
	
	// First, iterate over all sections and extract daughters.
	tempSecKeeper = new SectionList()
	forsec $o1 {
		tempSecKeeper.children()
	}
	
	allWithinList = 1
	// Next, check if every child was part of the original list.
	forsec tempSecKeeper {
		theTempSec = new SectionRef()
		withinList = sectionRefInList(theTempSec,$o1)
		if(withinList<0.1){
			allWithinList=0
		}
	}
	return allWithinList
}

// assign terminal identify
for nn=1,numEffBr {
	forsec brEff[nn-1] {
		isTerm_id = isTermEff(brEff[nn-1])
	}
}

// proofread some terminal IDs that get screened:
load_file("getBranchOrder.hoc")
Cell[0].dend[36] {isTerm_id=1}
Cell[0].dend[37] {isTerm_id=1}

assignBranchOrder(soma,0)