Record the sum of multiple sources with h.Vector()

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

Moderator: hines

Post Reply
Grado

Record the sum of multiple sources with h.Vector()

Post by Grado »

I am trying to create a parallel model that takes advantage of the extracellular recording mechanisms in viewtopic.php?f=28&t=168.

This model does the integration in the run control of each timestep. From what I understand, this won't work in parallel simulations.

I am trying to instead use vectors. I am currently using the following method:
I create a vector for each segment of each section of each cell that records er_xtra, and then sum them all together at the end of the simulation. This works, but is obviously memory inefficient.

Code: Select all

 114│     def _set_rec_vectors(self):
 115│         self.rec_vectors = []
 116│         for cell in self.cells:
 117│             for sec in cell.all:
 118│                 if h.ismembrane('xtra'):
 119│                     for i in np.arange(sec.nseg+2)[1:-1]/float(sec.nseg+1):
 120│                         vec = h.Vector()
 121│                         vec.record(sec(i)._ref_er_xtra)
 122│                         self.rec_vectors.append(vec)
What I'm wondering is if theres a way to set a single vector to record the sum of multiple sources. Something like this:

Code: Select all

 124│     def _set_v_rec(self):
 125│         self.v_rec = h.Vector()
 126│         for cell in self.cells:
 127│             for sec in cell.all:
 128│                 if h.ismembrane('xtra'):
 129│                     for i in np.arange(sec.nseg+2)[1:-1]/float(sec.nseg+1):
 130│                             temp = h.Vector()
 131│                             temp.record(sec(i)._ref_er_xtra)
 132│                             self.v_rec += temp
This doesn't work. Is there a way to make this work? I've tried replacing line 132 with

Code: Select all

self.v_rec = self.v_rec.add(temp)
but that also doesn't work because the arrays are empty when they are initialized.
ted
Site Admin
Posts: 6289
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Record the sum of multiple sources with h.Vector()

Post by ted »

I am trying to create a parallel model that takes advantage of the extracellular recording mechanisms in viewtopic.php?f=28&t=168. . . . What I'm wondering is if theres a way to set a single vector to record the sum of multiple sources.
Not like you're trying to do it. You'll have to add up the transfer-resistance-weighted currents after each fadvance().

But first, note that a recent addition to NEURON has made calculation of membrane current much faster, and independent of the extracellular mechanism. Read the Programmer's Reference entry about the CVode class's use_fast_imem.

If you want to do that, first make these changes to xtra.mod:
1. In the COMMENT block at the top of the file, insert the statement
Now uses i_membrane_ (see CVode class's use_fast_imem documentation).
2. In the ASSIGNED block change
im (milliamp/cm2)
to
: im (milliamp/cm2)
im (nA)
and also change
area (micron2)
to
: area (micron2)
3. In the INITIAL and AFTER_SOLVE blocks change
er = (10)*rx*im*area
to
: er = (10)*rx*im*area
er = rx*im

Then be sure to delete any .dll, .o, or .c files in the directory that contains xtra.mod, and recompile the mod files.

You'll need to link each segment's i_membrane_ to xtra's im.

Finally, you need to calculate the extracellular potential at the point of interest after each fadvance(). If I were doing this entirely with hoc, I'd create a file called
customadvance.hoc
that contains these statements

Code: Select all

// presumes that all sections of interest have been appended
// to a SectionList called rec_from_these
vx = 0
proc advance() {
  fadvance()
  vx = 0
  forsec rec_from_these {
    for (x,0) vx += er_xtra(x)
  }
}
and I'd execute
load_file("customadvance.hoc")
right after all model specification code and the statements that insert xtra and link xtra's im to i_membrane_ have been executed, but before the statements that set up Vector recording of the value of vx.

However, your list of sections of interest is a Python list and I'll have to think about how to have hoc iterate over those sections--or whether a different tactic is better.
hines
Site Admin
Posts: 1682
Joined: Wed May 18, 2005 3:32 pm

Re: Record the sum of multiple sources with h.Vector()

Post by hines »

A helpful element when a python def needs to be called every time step (and works with variable step methods as well as fixed step) is

Code: Select all

$ cat beforestep_py.mod
: Python callback from BEFORE STEP

NEURON {
  POINT_PROCESS beforestep_callback
  POINTER ptr     
}

ASSIGNED {
  ptr     
}

INITIAL {
}

VERBATIM
extern int (*nrnpy_hoccommand_exec)(Object*);
extern Object** hoc_objgetarg(int);
extern int ifarg(int);
extern void hoc_obj_ref(Object*);
extern void hoc_obj_unref(Object*);
ENDVERBATIM

BEFORE STEP {
  :printf("beforestep_callback t=%g\n", t)
VERBATIM
{
  Object* cb = (Object*)(_p_ptr);
  if (cb) {
    (*nrnpy_hoccommand_exec)(cb);
  }
}
ENDVERBATIM
}

PROCEDURE set_callback() {
VERBATIM
  Object** pcb = (Object**)(&(_p_ptr));
  if (*pcb) {
    hoc_obj_unref(*pcb);
    *pcb = (Object*)0;
  }
  if (ifarg(1)) {
    *pcb = *(hoc_objgetarg(1));
    hoc_obj_ref(*pcb);
  }
ENDVERBATIM
}
A test is

Code: Select all

$ cat test_beforestep_py.py
from neuron import h

# Need a home for bscallback. Location is important for threads
# and local variable step method. Not important otherwise
s = h.Section()

bscallback = h.beforestep_callback(s(.5))

def callback():
  print h.t

bscallback.set_callback(callback)

h.load_file("stdrun.hoc")
h.cvode_active(1)
h.run()
and

Code: Select all

$ nrniv -python test_beforestep_py.py
NEURON -- VERSION 7.4 (1362:1e1480f0a0e3) 2015-10-02
Duke, Yale, and the BlueBrain Project -- Copyright 1984-2015
See http://www.neuron.yale.edu/neuron/credits

loading membrane mechanisms from x86_64/.libs/libnrnmech.so
Additional mechanisms from files
 beforestep_py.mod cadynam.mod halfgapm1.mod ik1.mod ina.mod is.mod ix1.mod kcum.mod nacum.mod nipace.mod
0.0
3.43225906488
5.0
>>> 
if 'print h.t' does not work correctly in the above test, then your earlier version of NEURON may not have the fix which updates the intertpreter time from the thread 0 time during a simulation and you
should use
pc = h.ParallelContext()
...
print pc.t(0)

Another element that is very useful when the interpreter is called on to do a lot of work each time step is to use the PtrVector for gathering values into a Vector which (with numpy) you can
multiply by a weight matrix and then add to your extracellular recording trajectories. See
http://www.neuron.yale.edu/neuron/stati ... ector.html
Grado

Re: Record the sum of multiple sources with h.Vector()

Post by Grado »

Thanks Michael. I was able to use beforestep_py.mod to record the extracellular potential. Just wondering, but are there any plans to implement some sort of custom advance definition in Python, analogous to defining "proc advance() { }"? Maybe just making beforestep_py native to nrnpython?

Ted, thanks for the heads up about the use_fast_imem, I am currently working on implementing it in my model.
hines
Site Admin
Posts: 1682
Joined: Wed May 18, 2005 3:32 pm

Re: Record the sum of multiple sources with h.Vector()

Post by hines »

are there any plans ...
My old, probably obsolete, rule of thumb, has been not to encourage a lot of interpreter activity during an fadvance due to performance reasons (interpreter is order(s) of magnitude slower than c/c++).
But user convenience often trumps that, and, in many situations (e.g. LFP calcualtions) the interpreter executes lengthy vector/matrix calculations that are done in c anyway so the interpreter overhead
is amortized to insignificance. There is now a gaggle of methods that callback into hoc/python during an fadvance. eg, cvode.event, netcon.event, nonvint_supervisor_block, cvode.extra_scatter_gather,
is a partial list. From a opportunistic point of view, it is reasonable to repurpose a POINT_PROCESS mod file to obtain callback functionality for all the BEFORE/AFTER keywords. If a model make use
of too many of these repurposed POINT_PROCESS instances, there is a considerable danger of losing clarity about their interactions.
Post Reply