Page 1 of 1

Sectionlist as a vector of strings

Posted: Wed Mar 12, 2008 1:06 am
by Sherif

I have a sectionlist that has the names of more than 50 sections of my model. I want to iterate over the first 10 sections and run Statement 1, and the second 10 sections and run Statement 2, and so on. In other words, I want to know a way of using the sectionlist as a vector of strings that can be accessed at any index. Any ideas?



using the String class to emulate indexed strings

Posted: Wed Mar 12, 2008 9:25 am
by ted
There are lots of ways to accomplish the same end result. Any solution must address
two problems:
1. it must overcome the fact (limitation) that a SectionList does not have an "index" that
would allow retrieval of a particular item
2. it also has to manage the selection and execution of the appropriate statement, in a
way that remains easy for the programmer to manage

First think about problem 1. One approach to dealing with this is to use an auxiliary
variable that keeps track of where you are in the SectionList. A crude example:

Code: Select all

ii = 0
forsec seclist {
  if (ii < 10) {
  if ((ii >= 10) && (ii < 20) {
So the auxiliary variable ii solves the problem of how to select sections in groups of 10,
but all those "if" statements make this code hard to manage. So now the focus shifts to
problem 2.

What is needed is a better way to select and execute the desired statement. It would be
much nicer if the statements were numbered 0, 1, . . . Then you could write

Code: Select all

ii = 0
forsec seclist {
  dostmt( int(ii/10) ) // argument will be 0, 1, 2 . . .
  ii += 1
where dostmt() is a procedure that uses its numeric argument to specify which
statement is executed

Code: Select all

proc dostmt() { // expects the argument to be 0, 1, 2 . . .
  execute( a string specified by the argument )
Since NEURON's strdefs don't have indexes, this doesn't look like much help. But the
standard run library defines a String class that is just a strdef inside of a template, so
as long as you are using the standard run library (which you are, if your hoc code begins
or if you are starting NEURON from the command line by typing
nrngui yourprogramname.hoc
), you can define a collection of String objects, initialize their strdefs to contain the
command strings you want, and then access the strings via the indexed String objects.
A toy example of the basic idea:

Code: Select all

objref command[NUMCMDS]
for ii = 0,NUMCMDS-1 command[ii] = new String()

command[0].s = "x = PI"
command[1].s = "x = sqrt(2)"
command[2].s = "x = exp(-1)"

proc docmd() {

for ii=0,NUMCMDS-1 {
  print "command ", ii, " makes x equal to ", x
So now you have all the pieces of the complete solution.

Posted: Thu Mar 13, 2008 11:39 am
by Sherif
Many thanks Ted.

One thing to confirm. When I say

Code: Select all

forsec "den" { .... }
the loop will iterate over sections whose names start with "den" according to their creation order not alphabetical order?

Posted: Fri Mar 14, 2008 12:10 pm
by ted
I don't know; this is something you can discover for yourself by making a toy model and
then executing
forsec "den" print secname()

But if the sequence of section access is important to your program, you probably shouldn't
leave it up to chance. Instead of
forsec "den"
it would be safer to explicitly create a new SectionList and append the sections of interest
to this list, in the order that you want. Otherwise the program will not be robust and could
cause future problems that are hard to debug and/or fix, e.g.
--might not work properly when you or your future students or collaborators try it on a
different model cell
--might not work properly if the default behavior of forsec "den" changes in some future
implementation of NEURON
--won't be readily portable to other simulators because it relies on an undocumented
and non-guaranteed behavior of forsec "string"

So it may be better to prevent these problems now, while everything is fresh in your mind.