Interesting question. I'd approach it by stepping back from the details, and trying to cook up a "top level" solution that does just one thing--like implementing Vector recording from all the somas, all with code that is executed at the top level (outside of any procs or funcs). After I had something that works, then I'd figure out how to wrap it inside a proc or func. Then I'd try to generalize it to something that can also deal with attaching IClamps to the cells.
Here's an outline of a top level solution to implement Vector recording. It's in semi-pseudocode so I don't get lost in syntactical details:
Code: Select all
// assumes the list of cells is called cells
create a List called veclist that will hold all of the Vectors
for i=0,cells.count()-1 {
cells.o(i).soma { // makes soma be the currently accessed section
create a new Vector and append it to veclist
make this Vector record v at the middle of the currently accessed section
}
}
Translating to hoc this becomes
Code: Select all
// assumes the list of cells is called cells
objref veclist
veclist = new List()
objref tobj
for i=0,cells.count()-1 {
cells.o(i).soma { // currently accessed section
tobj = new Vector()
tobj.record(&v(0.5))
veclist.append(tobj)
}
}
objref tobj // destroy link between tobj and last item in veclist
// to prevent accidental mischief
I could wrap this inside of a procedure, but it might be nicer to wrap it inside an obfunc--
Code: Select all
// argument 1 is a List that contains cells
obfunc record_from_list_of_cells() { local i localobj tmplist
tmplist = new List()
for i=0,$1.count()-1 {
$1.o(i).soma {
tmplist.append(new Vector()) // creates Vector and appends to tmplist
tmpobj.record(&v(0.5))
}
}
return tmplist
}
// assumes the list of cells is called cells
objref veclist
veclist = record_from_cells(cells)
Now we're getting somewhere.
I could deal with the IClamps by writing a second obfunc that would differ only in its name and the fact that the stuff inside this block
$1.o(i).soma {
. . .
}
would be statements that create an IClamp attached to soma(0.5).
But there's a software pattern here that might be exploited. Each of these obfuncs would basically do the same thing: for each element in a list of cells, do something to the soma section of that particular cell. So why not separate the task of doing something to the soma section of a cell from the task of iterating over the list of cells?
There are two different "tasks of doing something to the cell." One is to set up Vector recording of soma.v(0.5), and the other is to attach an IClamp to soma(0.5). I could put each of these into its own procedure (actually an obfunc that returns a new IClamp or a new Vector):
Code: Select all
// returns a Vector that records v at middle of currently accessed section
obfunc record_soma_v() { localobj tobj
tobj = new Vector() //
tobj.record(&v(0.5))
return tobj
}
// returns an IClamp attached to middle of currently accessed section
obfunc stim_soma() {
return new IClamp(0.5)
}
Then I can call each of these with an obfunc that iterates over all cells in a list. I'm calling it instrument_somas() because stimulators and Vector recording fall into the category of "instrumentation."
Code: Select all
// argument 1 is a List that contains cells, each of which has a soma
// argument 2 is a string that calls an obfunc
// that attaches some "instrumentation" to the soma
strdef tstr // for constructing and executing a command string
objref tmpobj // must be top level because execute(tstr) executes the string at top level
obfunc instrument_somas() { local i localobj tlist
tlist = new List()
for i=0,$o1.count()-1 {
$o1.o(i).soma { // makes soma the currently accessed section
sprint(tstr,"tmpobj = %s", $s2)
execute(tstr)
tlist.append(tmpobj) // so we can reuse tmpobj for something else
}
}
objref tmpobj // break link between tmpobj and last item in tlist
return tlist
}
Given these three obfuncs, I can do this
Code: Select all
// assumes the list of cells is called cells
objref veclist, iclamplist
veclist = instrument_somas(cells, "record_soma_v()")
iclamplist = instrument_somas(cells, "stim_soma()")
and check the results by doing this
Code: Select all
// verify that it worked
// by demonstrating that each list contains the right number of things
// and that each element in each list is different from the others
print "Vectors created:"
for i=0,veclist.count()-1 print veclist.o(i)
print "IClamps created:"
for i=0,iclamplist.count()-1 print iclamplist.o(i)
For example, if cells contains 5 instances of a cell class that has a soma, this test should print out something like
Code: Select all
Vectors created:
Vector[3]
Vector[4]
Vector[5]
Vector[6]
Vector[7]
IClamps created:
IClamp[0]
IClamp[1]
IClamp[2]
IClamp[3]
IClamp[4]
What remains to be done? Iterate over iclamplist to set the parameters of the IClamps.