standard run system hooks from Python

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

Moderator: hines

Post Reply
sec6
Posts: 39
Joined: Sat Mar 15, 2008 10:32 am

standard run system hooks from Python

Post by sec6 »

My questions, from specific to general, are:
  • Is there a way to call a Python method from inside a Hoc proc?
    If I modify advance() as described below, will I slow down execution horribly?
    Is there some other better, or more conventional way than the one described below to accumulate output on disk, rather than in memory?
I want to override the "advance()" proc of the standard run system, inserting a call to a Python method.

The reason I want to do this is:
I'm recording spike times into hoc.Vectors using the Netcon.record() method
The simulation is very long (millions of milliseconds), and the Vectors are occupying more memory than I've got (4 gig, of which about 0.5 gig is used by the OS, and the rest is available to NEURON).
So, instead of keeping it all in physical RAM, I want to write it to disk, and use the Vectors like file buffers.
I figure I can accomplish this by overwriting advance() with something like:

Code: Select all

proc advance() {
	if (my_nrnSsn_instance.largestVecLen() > blockLen) {
		my_nrnSsn_instance.appendVectorsToFile()
		my_nrnSsn_instance.initVectors()
	}
	fadvance()
}
where largestVecLen(), appendVectorsToFile(), and initVectors() are Python methods of class nrnSsn

Code: Select all

Class nrnSsn:
	...
	def largestVecLen():
		return(max([v.size() for v in self.vecList]))
		
	def initVectors():
		for (nc,vec) in zip(self.netconList,self.vecList):
			nc.record(vec)
		
	def appendVectorToFile():
		pass #Left as an exercise to the reader ;}

Why, you may ask, do I not write largestVecLen(), initVectors(), and appendVectorToFile in Hoc?
Well, apart from the fact that I find Hoc a lot harder to use than Python, my_nrnSsn_instance.vecList and my_nrnSsn_instance.netconList are *Python* lists of *Hoc* objects. I don't see how I'd get a largestVecLen or initVectors proc written in Hoc to iterate over a Python list.
ted
Site Admin
Posts: 6299
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: standard run system hooks from Python

Post by ted »

These broad suggestions omit many implementational details.

If you assign each cell its own "global identifier" at the time it is created, you can capture network activity with a single pair of Vectors tvec (for spike times) and idvec (for the corresponding cell ids). For a couple of examples, see Hines, M.L. and Carnevale, N.T. Translating network models to parallel hardware in NEURON, which appeared in J. Neurosci. Methods, is available in preprint form here http://www.neuron.yale.edu/neuron/bib/nrnpubs.html, and has source code you can grab from ModelDB. This will save space (only one pair of Vectors needed to capture spike times from the entire net), and time (only have to check the length of one Vector in proc fadvance() in order to know when to write these to output).

When it is time to write to output, I'd do the following:
--save the model's states to a SaveState object
--write the two vectors to output
--do a custom initialization that restores the states from the SaveStates object
(this will also clear tvec and idvec so they're ready to capture new events)
--resume the simulation from this point

If your model cells happen to have maximal firing rates, there is no need to check at every fadvance(). Given NCELL cells, each of which can fire at most FMAX spikes per ms, and storage sufficient to hold NUMPTS elements in tvec and idvec, you only have to dump to output once every tpoll = NUMPTS/NCELL/FMAX ms. This can be orchestrated by using an FInitializeHandler and the CVode class's event() method to call a procedure at intervals of tpoll throughout the simulation.
hines
Site Admin
Posts: 1687
Joined: Wed May 18, 2005 3:32 pm

Re: standard run system hooks from Python

Post by hines »

Is there a way to call a Python method from inside a Hoc proc?
objref p
p = new PythonObject()
p.method(...)
If I modify advance() as described below, will I slow down execution horribly?
No. But modifying the advance() loop is considered a last resort since it generally only
is valid for the fixed step method..
Is there some other better, or more conventional way than the one described below to accumulate output on disk, rather than in memory?
I think that the use of tvec and idvec to record all the spiketimes (associated with some id) is best.
Every 1 to 10 seconds (when the vectors get long), a cvode.event(t+1e4, "spkout()") could be triggered (start it from
an FInitializeHandler) to write the vectors to a file and resize them to 0.

If you want to do this in Python,
both FInitializeHandler and CVode.event have been extended to accept Python callbacks (as have most other methods that classically
executed a hoc statement as a callback).
Consider
neurondemo -python test.py
where test.py is

Code: Select all

from neuron import h
h.demo(1)

class Event(object):
  def __init__(self):
    self.fih = h.FInitializeHandler(1, self.callback)

  def callback(self) :
    print self, "t=", h.t 
    h.cvode.event(h.t + 1, self.callback)

e = Event()

h.run()
The output would be something like:

Code: Select all

NEURON -- VERSION 7.1 (297:6042034f57a2) 2009-03-02
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
<__main__.Event object at 0x2aaaad36b3d0> t= 0.0
<__main__.Event object at 0x2aaaad36b3d0> t= 1.0
<__main__.Event object at 0x2aaaad36b3d0> t= 2.0
<__main__.Event object at 0x2aaaad36b3d0> t= 3.0
<__main__.Event object at 0x2aaaad36b3d0> t= 4.0
<__main__.Event object at 0x2aaaad36b3d0> t= 5.0
>>> 
Post Reply