Single excitatory axons form clustered synapses onto CA1 pyramidal cell dendrites (Bloss et al 2018)

 Download zip file   Auto-launch 
Help downloading and running models
Accession:237728
" ... Here we show that single presynaptic axons form multiple, spatially clustered inputs onto the distal, but not proximal, dendrites of CA1 pyramidal neurons. These compound connections exhibit ultrastructural features indicative of strong synapses and occur much more commonly in entorhinal than in thalamic afferents. Computational simulations revealed that compound connections depolarize dendrites in a biophysically efficient manner, owing to their inherent spatiotemporal clustering. ..."
Reference:
1 . Bloss EB, Cembrowski MS, Karsh B, Colonell J, Fetter RD, Spruston N (2018) Single excitatory axons form clustered synapses onto CA1 pyramidal cell dendrites. Nat Neurosci 21:353-363 [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):
Gap Junctions:
Receptor(s):
Gene(s):
Transmitter(s):
Simulation Environment: NEURON;
Model Concept(s):
Implementer(s):
Search NeuronDB for information about:  Hippocampus CA1 pyramidal GLU cell;
/
BlossEtAl2018
readme.html
dists.mod *
eff.mod *
gScale.mod
id.mod *
kad.mod *
kap.mod *
kdr.mod *
na3.mod *
nmdaSyn.mod
syns.mod *
addChannels.hoc *
addSpines.hoc
addSynapses.hoc
buildCell.hoc
channelParameters.hoc *
createBiophysics.hoc
createMorphology.hoc
createPlots.hoc
createPointers.hoc
doAnalysis.hoc
getBranchOrder.hoc *
idMorph.hoc
initializationAndRun.hoc
loadMorph.hoc
mosinit.hoc *
processMorph.hoc
proofreadMorph.hoc
resetNSeg.hoc *
screenshot.png
simParameters.hoc
singleSim.hoc
singleSimDist.hoc
spineGeom.hoc
spineShaftConc.hoc
start.hoc
trackVoltages.hoc
twinApical.swc *
varyDistribution.hoc
varySpaceTime.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)