CA1 pyramidal neuron synaptic integration (Bloss et al. 2016)

 Download zip file   Auto-launch 
Help downloading and running models
Accession:187610
"... We examined synaptic connectivity between molecularly defined inhibitory interneurons and CA1 pyramidal cell dendrites using correlative light-electron microscopy and large-volume array tomography. We show that interneurons can be highly selective in their connectivity to specific dendritic branch types and, furthermore, exhibit precisely targeted connectivity to the origin or end of individual branches. Computational simulations indicate that the observed subcellular targeting enables control over the nonlinear integration of synaptic input or the initiation and backpropagation of action potentials in a branchselective manner. Our results demonstrate that connectivity between interneurons and pyramidal cell dendrites is more precise and spatially segregated than previously appreciated, which may be a critical determinant of how inhibition shapes dendritic computation."
Reference:
1 . Bloss EB, Cembrowski MS, Karsh B, Colonell J, Fetter RD, Spruston N (2016) Structured Dendritic Inhibition Supports Branch-Selective Integration in CA1 Pyramidal Cells. Neuron 89:1016-30 [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;
Brain Region(s)/Organism:
Cell Type(s): Hippocampus CA1 pyramidal GLU cell;
Channel(s): I Na,t; I K;
Gap Junctions:
Receptor(s): AMPA; NMDA; Gaba;
Gene(s):
Transmitter(s):
Simulation Environment: NEURON;
Model Concept(s): Synaptic Integration;
Implementer(s): Cembrowski, Mark S [cembrowskim at janelia.hhmi.org];
Search NeuronDB for information about:  Hippocampus CA1 pyramidal GLU cell; AMPA; NMDA; Gaba; I Na,t; I K;
/
arrayTomography
README.txt
dists.mod *
eff.mod *
exc.mod
id.mod *
inh.mod
kad.mod *
kap.mod *
kdr.mod *
na3.mod *
nmdaSyn.mod
syns.mod *
activateExcitation.hoc
activateInhibition.hoc
addChannels.hoc *
addExcitation.hoc
addVgatInhibition.hoc
channelParameters.hoc *
flagVgatInhibition.hoc
getBranchOrder.hoc *
idMorph.hoc
inhibitionBiophysics.hoc
initializationAndRun.hoc *
loadMorph.hoc *
mosinit.hoc *
naceaxon.nrn *
processMorph.hoc *
proofreadMorph.hoc *
resetNSeg.hoc *
start.hoc
synHelperScripts.hoc
twinApical.swc *
                            
// 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)