Why am I getting a section stack overflow?

Managing anatomically complex model cells with the CellBuilder. Importing morphometric data with NEURON's Import3D tool or Robert Cannon's CVAPP. Where to find detailed morphometric data.
Post Reply
Bill Connelly
Posts: 85
Joined: Thu May 22, 2008 11:54 pm
Location: Australian National University

Why am I getting a section stack overflow?

Post by Bill Connelly » Thu Feb 21, 2013 2:34 pm

This function crashes out at the same point, everytime, halfway through the nested for functions. I'm sure I've run simulations that have called run() more times than this, so I'm not sure what the problem is. The function doesn't seem truly recursive (which I've read is a common cause for stack overflows). So any other ideas would be appreciated.

I start off by setting up a template for a unitary EPSP. Then I have a master function that prepares the simulation, and outputs the data, and a little one at the end that places the synapses.

Code: Select all

begintemplate uEPSP //first argument is position. Second argument is delay
  external dend
  public syn
  objref syn

  proc init() {
    objref syn
    dend[38] syn = new AlphaSynapse($1)
    syn.e = 0
    syn.tau = 3
    syn.gmax = 0.0003
    syn.onset = $2
    }

endtemplate uEPSP

objref esyn_list
esyn_list = new List()

proc TestDistrib() { local oldpos, start, end, oldtstop
  somastim.amp = 0
  dendstim.amp = 0

  oldtstop = tstop
  tstop = 3000

  f3 = new File()
  f3.aopen("distrib.txt")
  
  oldpos = 1.1
  for(p=20; p>=5; p-=1) {
  dendV.record(&dend[38].v(p/20))
  somaV.record(&soma.v(0.5))
  tvec.record(&t)
    dend[38] { dendstim.loc(p/20) }  //dummy to keep track of where we ACTUALLY are
    while(dendstim.get_loc()==oldpos) { //skip down till we get to a new section
      p-=0.5
      dend[38] { dendstim.loc(p/20) }
    }
    for(n=1; n<=16; n+=1) {
      DistributeInputs(n, p/20)
      init()
      run()
      start = tvec.indwhere(">=", 1999)
      end = tvec.indwhere(">=", 2500)
      f3.printf("%g\t", dendstim.get_loc()*dend[38].L + dend[37].L + dend[33].L) //distance of site
      f3.printf("%g\t", n)
      f3.printf("%g\t",somaV.max(start, end)-somaV.x[start])
      f3.printf("%g\t", dendV.max(start, end)-dendV.x[start])
      f3.printf("\n")     
      esyn_list.remove_all()
    }
  }
  f3.close()
  tstop=oldtstop
}



proc DistributeInputs() { localobj esyn //first argument is number of inputs. Second argument is location
  for (i=1; i<=$1; i+=1) {
    esyn = new uEPSP($2, 2000+((i-1)*0.6))
    esyn_list.append(esyn.syn)
  }
}

ted
Site Admin
Posts: 5301
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Why am I getting a section stack overflow?

Post by ted » Fri Feb 22, 2013 9:16 pm

The problem is the get_loc calls, which have a side effect that has caused headaches for more than one programmer.

The explanation is a tale of two stacks. One is the section stack, which keeps track of which section is the currently accessed section (answer: the section that is on the top of the section stack), and the other is the hoc interpreter's own stack. hoc is a stack machine. Statements that are executed outside of any object or pair of curly brackets are executed at the top level of the interpreter. Statements that are executed inside an object or pair of curly brackets (e.g. code inside a proc or func) are not executed at the top level of the interpreter.

"So what?"

Here's what: get_loc pushes the current section on the section stack, where it remains until the interpreter returns to its top level. And your code is doing a whole bunch of get_loc calls without returning to the interpreter's top level, which means it's stuffing the section stack. For a discussion and example of this, see
Missing documents for pointprocess.get_loc() and .has_loc()
viewtopic.php?f=20&t=1052

Why it's happening: proc TestDistrib() contains a for loop that in turn contains a while loop and another for loop, and this is causing lots of calls to get_loc. Here's TestDistrib, gutted of everything except the stuff that is biting you:

Code: Select all

proc TestDistrib() { . . .
  . . .
  oldpos = 1.1
  for(p=20; p>=5; p-=1) {
    . . .
    while(dendstim.get_loc()==oldpos) {
      . . .
    }
    for(n=1; n<=16; n+=1) {
      . . .
      f3.printf("%g\t", dendstim.get_loc()*dend[38].L + dend[37].L + dend[33].L) //distance of site
    }
  }
  . . .
}
The outer for loop is executed 16 times. So is the inner for loop. This forces 256 executions of the f3.printf statement, which calls get_loc each time. The while loop is never entered because get_loc() will never return a value > 1, but the expression in its parentheses is nevertheless executed once on each pass through the outer for loop. That makes a total of 16+256 = 272 executions of get_loc, all done inside a proc, hence 272 pushes onto the section stack.

The fix is to call pop_section after each call to get_loc--see the Programmer's Reference for information about pop_section().

That said, you may also want to rethink that while( ) statement, which isn't doing anything useful. Also, unless dend[38] has a very large value for nseg,

Code: Select all

  for(p=20; p>=5; p-=1) {
    dendV.record(&dend[38].v(p/20))
is going to record from locations that are quite irregularly spaced along dend[38]. It would be better to choose a "spatial resolution appropriate" value for dend[38].nseg, then

Code: Select all

  for (x) if (x>0.25) {
    dendV.record(&dend[38].v(x))
which would iterate over the distal 3/4 of dend[38]'s nodes and would also eliminate any need to call get_loc since x would only take on the values of valid node locations.

Bill Connelly
Posts: 85
Joined: Thu May 22, 2008 11:54 pm
Location: Australian National University

Re: Why am I getting a section stack overflow?

Post by Bill Connelly » Sat Feb 23, 2013 3:24 am

Hi Ted,

Just in case you haven't been told it recently, you are such a benefit to the neuroscience community. I can think of few others who do so much to help so many in science.

Secondly, yes, I know that while statement is super clumsy, but I couldn't for the life of me figure out a way to step down a dendrite otherwise, (I was deafeated because that gap between the end of the section (1) and next one (say 0.9) is not the same as the second one, and the third (0.9 to 0.7). If you can tell me a less stupid way of moving down a section so that I can know where I am, I am all ears!

ted
Site Admin
Posts: 5301
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Why am I getting a section stack overflow?

Post by ted » Sun Feb 24, 2013 11:38 am

Bill Connelly wrote:you are such a benefit to the neuroscience community. I can think of few others who do so much to help so many in science.
That must be the reason why, despite being so smart, I'm not rich.
I couldn't for the life of me figure out a way to step down a dendrite
for (x) statement
executes statement at each node of the currently accessed section, one node at a time, starting at the 0 end and going to the 1 end.
for (x) if (x>a) statement
and
for (x) if (x>=a) statement
limit the range over which statement is executed to (a,1] and [a,1], respectively.

If you absolutely must iterate from the 1 end toward the 0 end, one way would be
tmpvec.resize(0)
for (x) if (x>a) tmpvec.append(x)
for (i=tmpvec.size()-1; i>=0; i=i-1) statement
assuming that tmpvec is an objref that points to a Vector.

Bill Connelly
Posts: 85
Joined: Thu May 22, 2008 11:54 pm
Location: Australian National University

Re: Why am I getting a section stack overflow?

Post by Bill Connelly » Wed Feb 27, 2013 6:16 am

Oh, I always forget that in neuron the for() loop can do that. Quite a clever little trick. Thanks for your help!

Post Reply