// ----------------------------------------------------------------------------
// genutils.hoc
// general routines
//
// 2007-03-01, Christoph Schmidt-Hieber, University of Freiburg
//
// accompanies the publication:
// Schmidt-Hieber C, Jonas P, Bischofberger J (2007)
// Subthreshold Dendritic Signal Processing and Coincidence Detection
// in Dentate Gyrus Granule Cells. J Neurosci 27:8430-8441
//
// ----------------------------------------------------------------------------
// constants
PROXDIST=150
// returns the interpolated index of a vector ($o1) where
func whereis() {local n,retIndex,fromtop,frombottom,m,c,x0,x1,y0,y1
retIndex=0
fromtop=0
frombottom=0
// coming from top or bottom?
if ($o1.x[0]>$2) {
fromtop=1
} else {
frombottom=1
}
for n=0,$o1.size()-1 {
if (fromtop==1) {
if ($o1.x[n]<$2) {
retIndex=n
break
}
} else {
if ($o1.x[n]>$2) {
retIndex=n
break
}
}
}
if (retIndex==0) {
print "Value not found in whereis()"
return 0
}
// linear interpolation:
x0=retIndex-1
x1=retIndex
y0=$o1.x(x0)
y1=$o1.x(x1)
m=(y1-y0)/(x1-x0)
c=y0-m*x0
return ($2-c)/m
}
// Returns the full width at half-maximal amplitude (FWHM) of an event in vector $o1.
// The index of the (estimated) peak of the event should be given as $2, baseline as $3, peak as $4
func t50() {local t50LeftId,t50RightId,t50LeftReal,t50RightReal,center,base,ampl,yLong2,yLong1
center=$2
base=$3
ampl=$4-$3
// walk left from center until HMA is reached:
t50LeftId=center
while (1) {
t50LeftId-=1
if (abs($o1.x[t50LeftId]-base)<abs(0.5 * ampl) || t50LeftId <=0) break
}
// walk right:
t50RightId=center
while (1) {
t50RightId+=1
if (abs($o1.x[t50RightId]-base)<abs(0.5 * ampl) || t50RightId >= $o1.size()) break
}
//calculation of real values by linear interpolation:
yLong2=$o1.x[t50LeftId+1]
yLong1=$o1.x[t50LeftId]
t50LeftReal=0.0
if (yLong2-yLong1 !=0) {
t50LeftReal=(t50LeftId+abs((0.5*ampl-(yLong1-base))/(yLong2-yLong1)))
} else {
t50LeftReal=t50LeftId
}
//Right side
yLong2=$o1.x[t50RightId]
yLong1=$o1.x[t50RightId-1]
t50RightReal=0.0
if (yLong2-yLong1 !=0) {
t50RightReal=t50RightId-abs((0.5*ampl-(yLong2-base))/abs(yLong2-yLong1))
} else {
t50RightReal=t50RightId
}
return t50RightReal-t50LeftReal
}
// returns the maximal slope of rise within the vector $o1 between indices $2 and $3
func maxRise() {local left,right,maxRise,i,diff
left=$2
right=$3
// Maximal rise
maxRise=abs($o1.x[right]-$o1.x[right-1])
i=right-1
while(1) {
diff=abs($o1.x[i]-$o1.x[i-1])
if (maxRise<diff) {
maxRise=diff
}
i-=1
if (i<left) break
}
return maxRise
}
// returns the maximal slope of decay within the vector $o1 between indices $2 and $3
func maxDecay() {local left,right,maxDecay,i,diff
left=$2
right=$3
// Maximal decay
maxDecay=abs($o1.x[left+1]-$o1.x[left])
i=left+2
while(1) {
diff=abs($o1.x[i]-$o1.x[i-1])
if (maxDecay<diff) {
maxDecay=diff
}
i+=1
if (i>=right) break
}
return maxDecay
}
begintemplate Location
public secRef, loc, distToRootCenter
objref secRef
proc init() {
secRef = new SectionRef()
loc = $1
secRef.root distance(0,0.5)
secRef.sec distToRootCenter = distance(loc)
}
endtemplate Location
// returns a list of locations from the 1-end of the
// currently accessed section to the center (0.5) of root
obfunc pathToRootCenter() {local x,i localobj retList,secRef,tempLoc
retList = new List()
secRef = new SectionRef()
while (secRef.has_parent()) {
// We don't want the 0-end to be added,
// because it's the same as the parent's 1-end.
secRef.sec for (x) if (x < 1) {
tempLoc = new Location(1-x)
retList.append(tempLoc)
}
secRef.parent secRef = new SectionRef()
}
// add root:
secRef.sec for (x) if (x <= 0.5) {
tempLoc = new Location(1-x)
retList.append(tempLoc)
}
if (debug_mode) {
for i=0,retList.count()-1 {
retList.o(i).secRef.sec if (debug_mode) print "Added ",secname(),"(",retList.o(i).loc,")"
}
}
return retList
}
obfunc termList() {local i localobj retList,secRef,rootRef
retList=new List()
// check whether a section has a child...
forsec "section" {
secRef = new SectionRef()
$o2.sec distance(0,0.5)
if (secRef.nchild==0 && scale_spines != 1.0 && distance(1.0) > $1) {
// ... and if it doesn't, add it to the list
retList.append(secRef)
secRef.sec if (debug_mode) print secname()," is terminal"
}
}
return retList
}
// returns temperature-dependent scaling factor
func tempScale() {local scale
// $1: Q10
return $1^((celsius-24)/10)
}
func secArea() {local totalArea
totalArea = 0
for (x) totalArea += area(x)
return totalArea
}