create variable number of multiple sections

The basics of how to develop, test, and use models.
Post Reply
mctavish
Posts: 74
Joined: Tue Mar 14, 2006 6:10 pm
Location: New Haven, CT

create variable number of multiple sections

Post by mctavish »

I would like to create a variable number of sections, but it seems that it has to be hard-coded.

For example, I would like to have the following:

Code: Select all

numdends=4

begintemplate MyNeuron
external numdends
public dend

create dend[numdends]  // This is the problem
    .
    .
endtemplate MyNeuron
If I hard-code the line

Code: Select all

create dend[4]
Then there is no problem, but again, I need the size to be variable.

This problem also exists for double arrays:

Code: Select all

double d[arraySize]     // Will also be a problem.
I've tried "execute", but that does not seem to take, either. Perhaps because it is after I've called begintemplate, but before or in init()? Any other ideas?
ted
Site Admin
Posts: 5810
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: create variable number of multiple sections

Post by ted »

Doesn't have to be hard coded. The following shows how (and also tries to encourage stealing and modifying reusable code from the GUI).

Use a CellBuilder to make a toy cell that consists entirely of a soma plus two dend sections attached to its 1 end. Do only the topology; don't bother with subsets, geometry or biophysics for now. From this export a cell type (click on Management, select Cell Type, then click on "Save hoc code in file" (may have to drag bottom edge of CellBuilder down to show this button)). I called my file celldef.hoc

Now you have a file that contains a template for a cell class called Cell, which allows you to do
nrngui celldef.hoc
and then at the oc prompt
objref foo
foo = new Cell()
gives you a soma with two child dends. The challenge is to modify the Cell template so that
foo = new Cell(n)
generates a soma with n children.

I found 5 locations inside the Cell template that needed to be modified.
Modification 1
// create soma, dend[2]
create soma, dend[1]
This statement is outside of the template's procs. It's there because hoc must be told that a symbol is the name of a section, before that symbol can be used as such inside a proc or func. I changed dend[2] to dend[1] so that I could create an instance with just one dend. I wonder if
create soma, dend
(without the bracketed 1) would work as well . . .

Modification 2

Code: Select all

proc topol() { local i
//  for i = 0, 1 connect dend[i](0), soma(1)
  create dend[$1] // create the actual number of sections here!
  for i = 0, $1-1 connect dend[i](0), soma(1)
  basic_shape()
}
Given any argument >= 1, this modified proc topol() will create as many dends as we like, and connect them to the 1 end of soma.

Modification 3

Code: Select all

proc basic_shape() {
  soma {pt3dclear() pt3dadd(0, 0, 0, 1) pt3dadd(15, 0, 0, 1)}
/* this part clearly needs to be revised before it can be used with an argument
  dend {pt3dclear() pt3dadd(15, 0, 0, 1) pt3dadd(75, 0, 0, 1)}
  dend[1] {pt3dclear() pt3dadd(15, 0, 0, 1) pt3dadd(60, 45, 0, 1)}
*/
}
This particular modification is completely for the sake of the Shape plot's appearance
Actually, I could just as well have commented out proc basic_shape() entirely, as well as every call to proc basic_shape().

Modification 4

Code: Select all

proc subsets() { local i
 . . .
//    for i=0, 1 dend[i] all.append()
    for i=0, $1-1 dend[i] all.append()
 . . .
}
This ensures that every dend will be part of the all subset.

Last but not least, the changes that make everything else happen:
Modification 5

Code: Select all

proc init() {
//  topol()
//  subsets()
  topol($1) // because procs topol and subsets now expect an argument
    // and that argument is the value passed to the class's template on creation
  subsets($1)
  . . .
}
Note that there is no error trapping--this code will fail if called with an argument of 0, i.e.
foo = new Cell(0)


Finally--the test.

Code: Select all

load_file("nrngui.hoc")
load_file("celldef.hoc")

objref cells
cells = new List()

proc makecell() { localobj foo
  if ($1 < 1) {
    print "arg must be > 1"
  } else {
    foo = new Cell($1)
    cells.append(foo)
  }
}

for i = 0, 2 makecell(i+1)
objref gs
gs = new Shape()
for i = 0, 2 cells.o(i).position(100*i-100, 100*i-100, 0)
mctavish
Posts: 74
Joined: Tue Mar 14, 2006 6:10 pm
Location: New Haven, CT

Re: create variable number of multiple sections

Post by mctavish »

Thanks for the detailed reply on a weekend, Ted!

From your response, I also found that to have a member variable that is a pointer to an array of doubles, I did the following:

Code: Select all

begintemplate MyObject
public myDoubleArray
double myDoubleArray[1]  // Need to init with at least one val

// $1 is the size of myDoubleArray
proc init() {
    double myDoubleArray[$1]
        .
        .
}
endtemplate MyObject
ted
Site Admin
Posts: 5810
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: create variable number of multiple sections

Post by ted »

So the [1] was necessary in the declaration to ensure that the name would be treated as an array of doubles. Was it also necessary to ensure that a section name could be used to refer to an array of sections?
mctavish
Posts: 74
Joined: Tue Mar 14, 2006 6:10 pm
Location: New Haven, CT

Re: create variable number of multiple sections

Post by mctavish »

Yes. I could do something similar with an array of sections:

Code: Select all

begintemplate MyNeuron
public dend
public numDendSections

create dend[1]

// $1 is the number of sections
proc init() {
  numDendSections=$1
  create dend[numDendSections]
      .
      .
}
      .
      .
endtemplate MyNeuron
Post Reply