Recording soma potential in multiple cells using Cvode.recor

Anything that doesn't fit elsewhere.
Post Reply
Sherif
Posts: 27
Joined: Thu Oct 13, 2005 4:32 pm

Recording soma potential in multiple cells using Cvode.recor

Post by Sherif »

Hi,

I have a list of cell objects and want to record the somatic potential of each cell in the list. I wrote the following code to insert an IClamp in each cell and record Vsoma and injected current for further processing. However, I get a syntax error that I couldn''t figure out. Your help will be highly appreciated.

Code: Select all

// Arg 1: a list of cells

proc Test(){local i  	localobj ss, Iinj, Tinj
  ss = new String()
  Iinj = new Vector()
  Tinj = new Vector()

  for i=0,$o1.count()-1 {									
        sprint(ss.s, "objref  SomaV%d", i)                // define a set of objects to store Vsoma
        execute(ss.s)
        sprint(ss.s, "SomaV%d = new Vector()", i)    // define a set of vectors to store Vsoma
        execute(ss.s)

        sprint(ss.s, "objref  SomaT%d", i)                // define a set of objects to store Tsoma
        execute(ss.s)
        sprint(ss.s, "SomaT%d = new Vector()", i)    // define a set of vectors to store Tsoma
        execute(ss.s)

        sprint(ss.s, "objref  ic%d", i)             	        // define a set of objects for Iclamp
        execute(ss.s)

        object_push($o1.o(i)) 		        // Access one cell from the list

        forsec "soma" {
	        sprint(ss.s, "ic%d = new IClamp(0.5)", i)    	// insert Iclamp
	        execute(ss.s)
	        sprint(ss.s, "cvode.record(&soma.v(0.5), SomaV%d, SomaT%d)", i, i) //Record Vsoma & Tsoma 
	        execute(ss.s)               
        }                                    

        object_pop()
  }

  sprint(ss.s, "cvode.record(&ic%d.i, Iinj, Tinj)", i)    	// Record Iinj and Tinj
  execute(ss.s)                                                   
	
  run()
}
When I run this code by calling Test(AllCells), I get the following error message:
Test(AllCells)
nrniv: syntax error
near line 29
{cvode.record(&soma.v(0.5), SomaV0, SomaT0)}
^
FR_Cell[0].execute("cvode.record(&soma.v(0.5), SomaV0, SomaT0)" )
Test(List[8] )
nrniv: execute error: cvode.record(&soma.v(0.5), SomaV0, SomaT0)
near line 29
I cannot figure out the problem. I think I am using cvode.record() in the correct form.

Also, please advise if you have a better way to define multiple vectors than the way I did.

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

Re: Recording soma potential in multiple cells using Cvode.r

Post by ted »

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.
Sherif
Posts: 27
Joined: Thu Oct 13, 2005 4:32 pm

Re: Recording soma potential in multiple cells using Cvode.r

Post by Sherif »

That's really a nice structure. The use of obfunc in conjunction with object lists handeled the vectors in a really easy way. Thanks, Ted!!!!
ted
Site Admin
Posts: 6289
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Recording soma potential in multiple cells using Cvode.r

Post by ted »

You're welcome, Sherif. Thanks for asking another interesting question.
Post Reply