// $Id: spineloc.hoc,v 1.16 2015/09/30 05:14:15 ted Exp ted $
// buildpathfromrootnode() makes a SectionList
// whose elements constitute the path from the cell's root node
// to the currently accessed section
objref ptrn, pfrn, shplt
ptrn = new SectionList() // will contain the sections along the path
// that starts with the section that has the spine
// and ends with the root section
pfrn = new SectionList() // same as ptrn but the sequence is centrifugal
// i.e. starts with root section and ends will the section that has the spine
objref spinesubtree // the section that has the spine
// plus all of its descendants
spinesubtree = new SectionList()
objref pathplussubtree // path from soma to section that contains the spine
// plus that section's descendants
pathplussubtree = new SectionList()
// $o1 is a SectionList
// addsec() is a recursive procedure that appends to $o1
// a centripetal path that starts with an "initial section"
// i.e. the section that is CAS when addsec is first called
// and ends with the root of the tree that contains the initial section
proc addsec() { localobj sref
$o1.append() // append CAS
sref = new SectionRef()
if (ri(0) < 1e30) {
sref.parent addsec($o1)
}
}
// build paths to and from root node
// and paths distal to the section that has the spine
// also include all of these sections in the "pathplussubtree"
proc buildpaths() { local ii localobj tlist
// take care of the distal sections first
spinesubtree = new SectionList()
spinesubtree.subtree() // includes CAS
spinesubtree.remove() // omits CAS
head spinesubtree.remove() // also omit spine head and neck
neck spinesubtree.remove()
// spinesubtree now contains all sections that are children of the CAS
// but NOT the CAS
ptrn = new SectionList() // will be path from CAS to root node
addsec(ptrn)
/*
// ensure that ptrn includes the root section
tlist = new SectionList()
tlist.allroots()
forsec tlist ptrn.append()
ptrn.unique() // but make sure the root section appears only once
*/
// ptrn list is centripetal
// now reverse the sequence
pfrn = new SectionList() // will be path from root to CAS
// i.e. the path from root to the section that has the spine
tlist = new List()
forsec ptrn tlist.append(new SectionRef())
ii = tlist.count()-1
while (ii>=0) {
tlist.o(ii).sec pfrn.append()
ii-=1
}
shplt = new Shape()
// shplt.color_list(pfrn, 2) // red
shplt.color_list(ptrn, 2) // red
shplt.color_list(spinesubtree, 3) // blue
pathplussubtree = new SectionList()
forsec pfrn pathplussubtree.append()
forsec spinesubtree pathplussubtree.append()
}
///// control location of spine
load_file("loc.ses") // point process manager configured as a Loc attached to soma 0.5
objref locnc, nil, loc
loc = Loc[0]
locnc = new NetCon(nil, loc)
locnc.weight = 0
proc saywhere() { local x
x = locnc.postloc()
print secname(), " nseg = ", nseg, " mark at ", x
pop_section()
}
objref sref
sref = new SectionRef()
proc moveto() { local lastx
x = locnc.postloc()
/* to put spine in last segment
lastx = 1 - 0.5/nseg
print "moving spine to ", secname(), " ", lastx
neck disconnect() // disconnect neck from its existing parent
connect neck(0), lastx // connect neck(0) to x on currently accessed section
print secname(), " nseg = ", nseg, " spine at ", lastx
*/
// put spine at closest internal node
if (x==0) {
x = 0.5/nseg
} else {
if (x==1) x = 1 - 0.5/nseg
}
print "moving spine to ", secname(), " ", x
neck disconnect() // disconnect neck from its existing parent
connect neck(0), x // connect neck(0) to x on currently accessed section
Loc[0].loc(x) // make sure that Loc[0] is at the correct position
// NUTS! PPM's text "at secname(range)" doesn't always refresh properly!
print secname(), " nseg = ", nseg, " spine at ", x
buildpaths() // between root node and this section
sref = new SectionRef()
pop_section()
}
///// plot v vs. t at points along path from root node
/*
// not needed because we're using PSel
objref gvt
strdef tstr
// sets up a v vs. t plot
// for each internal node of currently accessed section
// do this in distal->proximal order
proc setsecplots() { local x
// don't bother with 0 or 1 ends
for (x,0) {
sprint(tstr,"%s.v(%g)", secname(), 1-x)
gvt.addvar(tstr)
}
}
*/
/* not any more--using NodeMarks class defined in nodemarks.hoc
// put a mark at each internal node of CAS
proc marknodes() { local x
// don't bother with 0 or 1 ends
for (x,0) {
// put a mark at node
// requires interpolation from pt3d data
// for now do nothing
}
}
*/
// v is to be recorded at each internal node along the path from root node
// (usually the soma's 0 end)
// to the distal end of the section that contains the spine
objref vveclist // will be a List that holds the Vectors to which v is recorded
vveclist = new List()
objref tvec
tvec = new Vector() // to record time
strdef tmplabel
// $o1 is a List to which recordings of v at all internal nodes of CAS
// are to be appended
proc setvecrec() { local x, i
i = 0
for (x,0) {
$o1.append(new Vector())
// proceed from distal to proximal
i+=1
sprint(tmplabel,"%s.v(%f)",secname(),1-x)
$o1.o($o1.count()-1).label(tmplabel)
$o1.o($o1.count()-1).record(&v(1-x))
}
}
load_file("nodemarks.hoc") // defines NodeMarks class
// used to mark locations of internal nodes along
// a set of sections contained in a SectionList
objref marks // will be a SectionList that contains the sections
// that are used to implement the node marks
strdef markstyle
markstyle = "+" // use plus sign for the marks
// any other character results in x shaped marks
marksize = 5 // um, defines length of each arm of a mark
proc setplotsalongpath() { local x, ii
/* don't bother with gvt--using PSel now
if (gvt!=nil) { // it points to something
ii = graphList[0].index(gvt) // remove it from graphList[0] if necessary
if (ii>=0) graphList[0].remove(ii)
objref gvt // and get rid of whatever it points to
}
gvt = new Graph(0)
gvt.size(0,tstop,0,30)
gvt.view(0, 0, tstop, 30, 962, 25, 300.48, 200.32)
addplot(gvt,0) // add to graphList 0
forsec ptrn { // stacks graph's variable labels from distal at top
// to proximal at bottom
setsecplots() // for each internal node in CAS add a v trace to gvt
marknodes() // put a mark at each internal node of CAS
}
gvt.addvar("soma.v(0.5)") // internal nodes only!
*/
// but we still want to see where the nodes are!
// forsec ptrn marknodes() // put a mark at each internal node of CAS
marks = new NodeMarks(ptrn, markstyle, marksize)
/*
// restore these colors!
shplt.color_list(ptrn, 2) // red
shplt.color_list(spinesubtree, 3) // blue
// nuts--doesn't work to restore them here--do it in proc pathcolors() instead
*/
// now set up vector recording at internal nodes along path
// start periperally and proceed toward center
vveclist = new List() // discard old data
forsec ptrn setvecrec(vveclist) // for ea intl node in CAS capture v(t)
vveclist.append(new Vector())
soma vveclist.o(vveclist.count()-1).record(&v(0.5))
vveclist.o(vveclist.count()-1).label("soma.v(0.5)")
tvec = new Vector() // really only have to do this once
tvec.record(&t)
}
proc pathcolors() {
// restore these colors, which may have been undone by adding NodeMarks
shplt.color_list(ptrn, 2) // red
shplt.color_list(spinesubtree, 3) // blue
}
objref gvp
proc plotvmaxonpath() { local ii, maxv, maxd
objref gvp
gvp = new Graph(0)
gvp.size(0,180,0,24)
gvp.view(0, 0, 180, 24, 962, 286, 301.44, 200.32)
// forsec pfrn for (x,0) gvp.mark(distance(x), vmax_extr(x), "+", 5)
maxv = 0
maxd = 0
gvp.beginline(1, 1)
forsec pfrn for (x,0) {
gvp.mark(distance(x), vmax_extr(x), "O", 6)
gvp.line(distance(x), vmax_extr(x))
if (maxv<vmax_extr(x)) maxv = vmax_extr(x)
if (maxd<distance(x)) maxd = distance(x)
}
gvp.exec_menu("View = plot")
gvp.flush()
gvp.size(0,maxd,0,maxv)
gvp.view(0, 0, maxd, maxv, 962, 286, 301.44, 200.32)
}
/*
proc plotdistalvmax() {
// forsec pfrn for (x,0) gvp.mark(distance(x), vmax_extr(x), "+", 5)
gvp.beginline(1, 1)
forsec pfrn for (x,0) {
gvp.mark(distance(x), vmax_extr(x), "O", 6)
gvp.line(distance(x), vmax_extr(x))
}
gvp.exec_menu("View = plot")
gvp.flush()
}
*/
/////
// should refactor this to eliminate overlap with previously developed stuff
objref spgmax, spveclist
spveclist = new List() // list of Vectors that contain values of vmax for plotting
BLACK = 1
RED = 2
strdef synlocstr
// sets synlocstr to a string of the form
// secname(rangeval)
// which describes the location to which the spine neck is attached
proc buildsynlocstr() { local x
x = $o1.get_loc()
sprint(synlocstr,"Spine is at %s(%f)",secname(),x)
pop_section()
}
/*
print "CAS starts as ", secname()
buildsynlocstr()
print "and ends as ", secname()
print synlocstr
*/
proc spshowpoints() {
objref spgmax
spgmax = new Graph(0)
spgmax.color(BLACK)
// plot vmax_extr(x) vs. distance(x) instead of vmax_util(x) vs. dist_util(x)
// forsec pathplussubtree for (x,0) spgmax.mark(dist_util(x), vmax_util(x), "+", 5)
forsec pathplussubtree for (x,0) spgmax.mark(distance(x), vmax_extr(x), "+", 5)
spgmax.size(-300,1300,0,MAX_VHEAD)
spgmax.view(-300, 0, 1600, MAX_VHEAD, 894, 286, 300.48, 200.32)
spgmax.exec_menu("View = plot")
// spgmax.label(0.65, 0.2, "Max depol (mV)", 2, 1, 0, 0, 1)
spgmax.label(0.15, 0.85, "Peak depol (mV)", 2, 1, 0, 0, 1)
buildsynlocstr(Loc[0])
spgmax.label(0.11, 0.75, synlocstr, 2, 1, 0, 0, 1)
}
// $o1 is veclist
// $2 is 0 for non-root section, 1 for root section
// proc spgetsecdata() { local ii localobj tdistvec, tvmaxvec, tvhmaxvec, tahdvec, srefthis
proc spgetsecdata() { local ii localobj tdistvec, tvmaxvec, srefthis
// get currently accessed section's distances and max vals into a set of vectors
// and append them to a List
tdistvec = new Vector(nseg)
tvmaxvec = new Vector(nseg)
// tvhmaxvec = new Vector(nseg)
// tahdvec = new Vector(nseg)
ii = 0
for (x,0) {
// tdistvec.x[ii] = dist_util(x)
// tvmaxvec.x[ii] = vmax_util(x)
tdistvec.x[ii] = distance(x)
tvmaxvec.x[ii] = vmax_extr(x)
// tvhmaxvec.x[ii] = vhmax_util(x)
// tahdvec.x[ii] = ahd_util(x)
ii+=1
}
if ($2==0) { // nonroot sections require special treatment
// the first elements of each nonroot section's vectors
// must be distance and max vals from a node in its parent
// but from which end of the parent?
srefthis = new SectionRef()
if (srefthis.has_trueparent() == 1) { // the most common case
// this section has a true parent
// so the vectors' first elements must be distance and max vals from just inside parent's 1 end
srefthis.parent() {
// tdistvec.append(dist_util(1))
// tvmaxvec.append(vmax_util(1))
tdistvec.append(distance(1 - 0.5/nseg))
tvmaxvec.append(vmax_extr(1))
// tvhmaxvec.append(vhmax_util(1))
// tahdvec.append(ahd_util(1))
}
} else { // less common
// this section is connected to the 0 end of the root section
// its vectors' first elements must be distance and max vals from just inside root section's 0 end
rootsecref.sec { // make rootsec the current section
srefthis.parent() {
// tdistvec.append(dist_util(0))
// tvmaxvec.append(vmax_util(0))
tdistvec.append(distance(0.5/nseg))
tvmaxvec.append(vmax_extr(0))
// tvhmaxvec.append(vhmax_util(0))
// tahdvec.append(ahd_util(0))
}
}
}
// now make parent node data become each vector's first element
tdistvec.rotate(1)
tvmaxvec.rotate(1)
// tvhmaxvec.rotate(1)
// tahdvec.rotate(1)
}
$o1.append(tdistvec) // .o(0) is distance vector
$o1.append(tvmaxvec) // .o(1) is vmax vector
// $o1.append(tvhmaxvec) // .o(2) is vhmax vector
// $o1.append(tahdvec) // .o(3) is ahd vector
}
proc spshowvplots() { local ii localobj tdistvec, tvmaxvec, tvhmaxvec, srefthis
// plots of vmax and vhmax vs. distance
spshowpoints() // first show the points
// next draw lines
// for each section get the distances and max values into vectors
// if the section has a parent, make sure the vectors' first elements are the
// distances and max values that belong to the parent's nearest internal node
// append these Vectors to veclist
spveclist = new List() // .o(0) will be the x value vector
// first deal with the root section
// get its distances and max vals into a set of vectors
rootsecref.sec spgetsecdata(spveclist, 1)
// now deal with non-root sections
forsec pathplussubtree spgetsecdata(spveclist, 0)
// finally plot the vmax and vhmax vectors against the distance vector in gmax
// and the gahd vectors against the distance vector in gahd
ii=0
/*
while (ii<veclist.count) {
veclist.o(ii+1).plot(gmax, veclist.o(ii), BLACK, 1)
veclist.o(ii+2).plot(gmax, veclist.o(ii), RED, 1)
veclist.o(ii+3).plot(gahd, veclist.o(ii), BLACK, 1)
ii+=4
}
*/
while (ii<spveclist.count) {
spveclist.o(ii+1).plot(spgmax, spveclist.o(ii), BLACK, 1)
// veclist.o(ii+2).plot(gmax, veclist.o(ii), RED, 1)
// veclist.o(ii+3).plot(gahd, veclist.o(ii), BLACK, 1)
// ii+=4
ii+=2
}
// mark the very first datum of the very first vector
// y value is spveclist.o(1).x[0]
// x value is spveclist.o(0).x[0]
spgmax.mark(spveclist.o(0).x[0], spveclist.o(1).x[0], "+", 5)
// revise this so it scales the Y axis nicely
spgmax.exec_menu("View = plot")
}
// $o1 is a List that contains Vectors
// $o2 is the tvec for those Vectors
objref ggg
proc listplot() { local i
ggg = new Graph()
for ii=0,$o1.count()-1 $o1.o(ii).plot(ggg,$o2)
ggg.exec_menu("View = plot")
}
/////
load_file("pselclass.hoc")
objref psel
print "defining proc genfig"
// xbutton("Generate figure", "setplotsalongpath() run() gvt.exec_menu(\"View = plot\")")
proc genfig() {
setplotsalongpath()
run()
// gvt.exec_menu("View = plot") // no longer needed--using PSel
// plotvmaxonpath() // from soma to 1 end of section that has the spine
// plotdistalvmax() // children of the section that has the spine
spshowvplots()
/*
listplot(vveclist,tvec) // instead make a new proc that spawns a bunch of graphs
// one per recorded v
*/
// listplot(vveclist,tvec) // instead make a new proc that spawns a bunch of
psel = new PSel(vveclist, tvec)
}