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)