Recording into a matrix

When Python is the interpreter, what is a good
design for the interface to the basic NEURON
concepts.

Moderator: hines

Post Reply
gartland

Recording into a matrix

Post by gartland » Mon Nov 10, 2008 5:53 pm

Does anyone have a good idea about how to record into a matrix?
I have a variable number of vectors that I'd like to record into and then reference simply by a second dimension rather than naming them V1, V2, V3 etc.

My idea was to use a single vector and record into different parts of it simultaneously by passing the record function pointers to different parts of the vector (essentially pointers to each row of the matrix that is being represented by the vector) For example if I had N vectors of length L, I could just resize a single vector to the size = N*L and then record into it at N different locations (0, L, 2*L,...(N-1)*L). This is better than having to figure out what N is and then on the fly resize N temp vectors to size L and record into each of them (i'm not even sure how i'd do this...).

It seems like I need to write my own record function essentially, but I'm not sure I could figure that out on my own. Any tips or workarounds from you guys would be great! Thanks, -Andrew

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

Re: Recording into a matrix

Post by ted » Mon Nov 10, 2008 8:22 pm

Lists are the best way to manage collections of objects.

Example 1: calcium accumulation in a model with several sections, each of which has nseg = 1.
Step 1 (left as an exercise to the reader): Create a SectionList, and to it append all sections whose cai you want to record. For the sake of this example, suppose the SectionList is called casecs.
Step 2: Set up Vector recording of cai in each section in casecs by doing the following:

Code: Select all

objref tmpvec, veclist
veclist = new List()
forsec casecs {
  tmpvec = new Vector()
  tmpvec.record(&cai)
  veclist.append(tmpvec)
}
objref tmpvec // to prevent careless use of tmpvec from damaging the last Vector
Example 2: calcium accumulation in a model with several sections, each of which may have any number of segments.
Step 1 (left as an exercise to the reader): Create a SectionList, and to it append all sections whose cai you want to record. For the sake of this example, suppose the SectionList is called casecs.
Step 2: Set up Vector recording of cai in each segment of each section in casecs by doing the following:

Code: Select all

objref tmpvec, tmpveclist, listofveclists
listofveclists = new List()
forsec casecs {
  tmpveclist = new List()
  for i=0,nseg-1 {
    x = (0.5+i)/nseg
    tmpvec = new Vector()
    tmpvec.record(&cai(x))
    tmpveclist.append(tmpvec)
  }
  listofveclists.append(tmpveclist)
}
objref tmpvec, tmpveclist // prevent careless damage to the last Vector and List of Vectors
For each section in SectionList casecs, there is a corresponding List in listofveclists; each such List is a set of Vectors--one Vector for each internal node of that section--which will contain the time course of cai at the middle of each internal node of that section.

Example 3: radial diffusion in a model with several sections, each of which has nseg = 1. Radial diffusion is implemented with mechanism cadifus, which uses Nannuli compartments. The concentration of ca in the jth compartment at range x is known to hoc as ca_cadifus[j](x).
Step 1 (left as an exercise to the reader): Create a SectionList, and to it append all sections whose ca you want to record. For the sake of this example, suppose the SectionList is called casecs.
Step 2: Set up Vector recording of ca in each annulus of each section in casecs by doing the following:

Code: Select all

objref tmpvec, tmpveclist, listofveclists
listofveclists = new List()
forsec casecs {
  tmpveclist = new List()
  for j=0,Nannuli-1 {
    tmpvec = new Vector()
    tmpvec.record(&ca_cadifus[j](0.5))
    tmpveclist.append(tmpvec)
  }
  listofveclists.append(tmpveclist)
}
objref tmpvec, tmpveclist
Example 4: radial diffusion in a model with several sections, each of which may have any number of segments. Radial diffusion is implemented with mechanism cadifus, which uses Nannuli compartments. The concentration of ca in the jth compartment at range x is known to hoc as ca_cadifus[j](x).
Step 1 (left as an exercise to the reader): Create a SectionList, and to it append all sections whose cai you want to record. For the sake of this example, suppose the SectionList is called casecs.
Step 2: Set up Vector recording of ca in each annulus of each segment of each section in casecs by doing the following:

Code: Select all

objref tmpvec, tmpveclist, tmplistofveclists, listoflistsofveclists
listoflistsofveclists = new List() // for all recordings from all segments of all sections
forsec casecs {
  tmplistofveclists = new List() // for all recordings from one section
  for i=0,nseg-1 {
    x = (0.5+i)/nseg
    tmpveclist = new List() // for all recordings from one segment
    for j=0,Nannuli-1 {
      tmpvec = new Vector()
      tmpvec.record(&ca_cadifus[j](x))
      tmpveclist.append(tmpvec)
    }
    tmplistofveclists.append(tmpveclist)
  }
  listofveclists.append(tmpveclist)
}
objref tmpvec, tmpveclist
Assuming that I have made no errors in algorithm or syntax.

It would be advisable to implement incrementally, testing on small models and proceeding from simple to more complex (a few sections without annuli and containing one segment each, next a few sections without annuli but having different values of nseg, then a few sections with several annuli and nseg = 1, and finally a few sections with several annuli and several different values of nseg).

gartland

Re: Recording into a matrix

Post by gartland » Wed Nov 12, 2008 3:03 am

Thanks for the tips and the walkthrough. It all makes good sense to me now. I believe I'm having trouble with some of the syntax that you've demonstrated because I'm trying to implement it in python. Feel free to move this into the NEURON + Python folder if you'd like. Let me know if its something I'm doing wrong. Thanks!

So heres the code that generates an error:

Code: Select all

for i in range(self.nshells):
			self.h.caVList.o(i).record(self.soma(0.5)._ref_caShells_cad[i],sec=self.soma)
			self.h.caB1VList.o(i).record(self.soma(0.5)._ref_caB1_cad[i],sec=self.soma)
and heres the error. Notice the error is encountered at the record statement and not during the simulation:

Code: Select all

bad stack access: expecting (double *); really (double)
NEURON: interpreter stack type error
 near line 0
 comV.play(&clamp.amp,dt)
                         ^
        Vector[7].record(0.5)
oc_restore_code tobj_count=1 should be 0
Exception in Tkinter callback
Traceback (most recent call last):
  File "lib-tk/Tkinter.py", line 1406, in __call__
    return self.func(*args)
  File "inits.py", line 120, in protLBCB
    self.curProt.run()
  File "/home/gartland/rgc/testProtocol.py", line 19, in run
    self.n.go()
  File "/home/gartland/rgc/rgcFunctions.py", line 195, in go
    self.h.caVList.o(i).record(self.soma(0.5)._ref_caShells_cad[i],sec=self.soma)
RuntimeError: hoc error
Just for reference, this statement works as you'd expect:

Code: Select all

self.h.inaV.record(self.soma(0.5)._ref_ina,sec=self.soma)
I've also tried this:

Code: Select all

for i in range(self.nshells):
			self.h('caVList.o(%d).record(&soma.caShells_cad[%d](0.5))' % (i,i))
			self.h('caB1VList.o(%d).record(&soma.caB1_cad[%d](0.5))' % (i,i))
But this results in an error that states that the cad mechanism doesn't exist in the soma. I seem to remember that this has something to do with the fact that I inserted the mechanism like this:

Code: Select all

self.soma.insert('cad')
Instead of like this:

Code: Select all

self.h('insert cad')
I'm using what I think is a pretty recent build of NEURON:

Code: Select all

NEURON -- VERSION 7.0 (198+:e5fbbdc44436+) 2008-10-08
Thanks for all your efforts. I've built a pretty cool GUI and analysis python program around the NEURON python module!

hines
Site Admin
Posts: 1517
Joined: Wed May 18, 2005 3:32 pm

Re: Recording into a matrix

Post by hines » Wed Nov 12, 2008 11:19 am

Code: Select all

self.h.caVList.o(i).record(self.soma(0.5)._ref_caShells_cad[i],sec=self.soma)
Unfortunately, a reference to an element of a RangeVariable array has not been
implemented. I need to do that but it is not clear yet what a consistent python
syntax would be.

Code: Select all

self.h('caVList.o(%d).record(&soma.caShells_cad[%d](0.5))' % (i,i))
You are on the right track here (til the proper _ref_ extension is implemented)
since hoc knows how to interpret &caShells_cad[2](0.5). Just
make soma the currently accessed section with
soma.push()
...
h.pop_section()
and leave it out of the statement you are constructing.
I'm assuming that the soma was created as an anonymous Python Section instead of with
h(' create soma'). Otherwise, putting in the 'soma' literal should work. The method you use to 'insert'
does not matter to the issue.
I've built a pretty cool GUI and analysis python program around the NEURON python module!
Sounds interesting. I'm making the InterViews gui items which are used by hoc programs also conveniently
available from Python. But maybe it is time to think about settling on a standard python gui toolkit.
The only problem is to have it with no extra installation difficulty on mac, mswin, or linux.

gartland

Re: Recording into a matrix

Post by gartland » Wed Nov 12, 2008 1:10 pm

Thanks. I'll check on how I am 'creating' the soma and get something to work!

My two cents on a python GUI toolkit is that Tkinter is the way to go:

1) Its built into the standard python distribution
2) It works well on ubuntu, WinXP and Mac OSX (yes i have the distinct displeasure of working with all three operating systems on a daily basis...)
3) I have found it very easy to learn and use to implement simple GUIs with buttons, entry boxes, labels, lists etc.
4) It is easy to stick matplotlib figures and axes into Canvas widgets in Tkinter windows

Apparently this is a very open debate though because you will find dozens of people out there describing pros and cons of many GUI implementations. The other one I was considering learning was wxWidgets. It also has good support for all three operating systems. The main advantage is that, from what people say, it looks like a professionally developed program because in each operating system it makes use of the operating system's calls to create windows, buttons etc. I think this fact gives you greater control over the look of the GUI in general. Personally this didn't matter to me, and I didn't want to go through the hassle of installing wxWidgets (not trivial...)

Let me know if you'd like to see any demo code of NEURON in Tkinter.

hines
Site Admin
Posts: 1517
Joined: Wed May 18, 2005 3:32 pm

Re: Recording into a matrix

Post by hines » Sat Nov 15, 2008 7:36 am

Yes, I would like to see an example. Please send, as a zip file, to michael.hines@yale.edu.
What I want to determine is how easy it would be to develop a tool with the complexity of the
Cellbuilder or LinearCircuitBuilder.

hines
Site Admin
Posts: 1517
Joined: Wed May 18, 2005 3:32 pm

Re: Recording into a matrix

Post by hines » Tue Nov 18, 2008 11:27 am

Code: Select all

self.h.caVList.o(i).record(self.soma(0.5)._ref_caShells_cad[i],sec=self.soma)
should work now.
http://www.neuron.yale.edu/hg/neuron/nr ... 80d5739788

gartland

Re: Recording into a matrix

Post by gartland » Thu Dec 04, 2008 6:46 pm

cool. i'm trying out the new syntax now. i receive an error now but i'm not sure why. how should i confirm that i am using the version of neuron that you've updated? i deleted the neuron/nrn directory, cloned a new nrn directory using mercurial and then rebuilt the whole thing...i think. would love to know how to check this though and make sure i'm importing the new neuron module when i'm in python.

heres the error though in case i am using the new version you posted:

Code: Select all

bad stack access: expecting (double *); really (double)
NEURON: interpreter stack type error
 near line 0
 caB2VList.o(0).record(&caB2_cad[0](0.5))
                                         ^
        Vector[7].record(0)
oc_restore_code tobj_count=1 should be 0
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python2.5/lib-tk/Tkinter.py", line 1406, in __call__
    return self.func(*args)
  File "inits.py", line 120, in protLBCB
    self.curProt.run()
  File "/home/gartland/rgc/testProtocol.py", line 19, in run
    self.n.go()
  File "/home/gartland/rgc/rgcFunctions.py", line 199, in go
    self.h.caVList.o(i).record(self.soma(0.5)._ref_caShells_cad[i],sec=self.soma)
RuntimeError: hoc error
On a similar note, what is the syntax for playing into an IClamp?

I think i should be something like:

Code: Select all

self.iclamp = self.h.IClamp(self.soma(pos))
self.h.comV.play(self.iclamp._ref_amp)
where h.comV is a hoc vector.

hines
Site Admin
Posts: 1517
Joined: Wed May 18, 2005 3:32 pm

Re: Recording into a matrix

Post by hines » Thu Dec 04, 2008 8:39 pm

I thought you were using linux and installing from the hg repository. For mswin use

http://www.neuron.yale.edu/ftp/neuron/v ... -setup.exe

gartland

Re: Recording into a matrix

Post by gartland » Thu Dec 04, 2008 8:44 pm

actually i am using linux. what made you think mswin...just curious i probably said something wrong...

hines
Site Admin
Posts: 1517
Joined: Wed May 18, 2005 3:32 pm

Re: Recording into a matrix

Post by hines » Thu Dec 04, 2008 9:12 pm

You can compare the number on the banner when launching neuron (or importing from python) with the changesets in the repository.
I observe the following:

Code: Select all

]$ neurondemo -python
NEURON -- VERSION 7.0 (264+:5f335f53c245+) 2008-12-03
Duke, Yale, and the BlueBrain Project -- Copyright 1984-2008
See http://www.neuron.yale.edu/credits.html

loading membrane mechanisms from /home/hines/neuron/nrnmpi/share/nrn/demo/release/x86_64/.libs/libnrnmech.so
Additional mechanisms from files
 cabpump.mod cachan1.mod camchan.mod capump.mod invlfire.mod khhchan.mod mcna.mod nacaex.mod nachan.mod release.mod
>>> #select Release
>>> from neuron import h
>>> sec = h.cas()
>>> print sec.name()
terminal
>>> v = h.Vector()
>>> v.record(sec(.5)._ref_ca_cadifpmp[2], sec=sec)
1.0
>>> #hit Init&Run
>>> v.printf()
3e-06   2.99993e-06     3.00012e-06     3.00108e-06     3.00345e-06
3.00795e-06     3.01495e-06     3.02466e-06  

gartland

Re: Recording into a matrix

Post by gartland » Thu Dec 04, 2008 10:43 pm

As I had suspected I had not properly rebuilt neuron, but I wrote down the steps this time so I won't ever have to wrestle with it again! The new syntax does work now. I am still not sure how to get a reference to the IClamp.amp variable so that I can "play" a hoc vector into it, but I've managed to use the push, pop strategy as you suggested last time and it does the trick. Thanks.

hines
Site Admin
Posts: 1517
Joined: Wed May 18, 2005 3:32 pm

Re: Recording into a matrix

Post by hines » Fri Dec 05, 2008 7:41 am

Code: Select all

>>> from neuron import h
>>> s = h.cas()
>>> ic = h.IClamp(.5, sec=s)
>>> v = h.Vector()
>>> v.record(ic._ref_amp, sec=s)

Post Reply