Page 1 of 1

When using a model with a custom init procedure...

Posted: Tue Jun 24, 2014 4:37 pm
by neuromau
When using a model with a custom init procedure, check to make sure the initialization was done correctly. This means, compare the functions called by the custom init procedure with those called in the regular init procedure as shown in Chapter 8.3 of The NEURON Book, to make sure no necessary function calls are missing.

Below is a recap of a conversation I had with Ted, in which I came to realize that the custom init procedure traditionally used by our lab required a specific function call that it was missing. After poking through ModelDB, I believe this specific problem (and possibly general oversights with custom init functions) may occur in other models as well, so one should always check for it when trying out someone else's model.

In summary, if the custom init procedure calls fadvance() for running time steps prior to the start of the simulation (say, to let the model reach steady state before the start of the simulation), after the calls to fadvance() are completed, it needs to either call frecord_init() directly, or it should call another procedure that accomplishes the same task, such as finitialize().

Conversation with Ted:

My initialization procedure is affecting synapse timing in a way that I don't understand.

I made a minimal working example where, if I include the "while..." line of my custom init function, the effect of the synaptic current on postsynaptic membrane potential is delayed about 1.7 ms. In my actual model, this delay is several ms. In the working example, it seems that the more fadvance() calls that are made during the custom init, the larger the delay in the start of the synaptic current.

But when I print out the g and i of the Exp2Sid mechanism that I am using, the time course of it looks exactly the same (I checked 10 decimal places out) regardless of whether I use the custom init or not.

The presynaptic cell fires at 15 ms and there is 0 ms delay in the netcon. When looking at the voltage of the postsynaptic cell, it is the same whether the custom init is used, up until t=15.0750 ms, then it starts diverging. Given the similarities whether I use the custom init or not (1: that the postsynaptic cell always holds steady at -75.5 prior to the presynaptic cell firing at 15 ms, and 2: that the synapse mechanism's conductance and current seems to behave the same), I don't understand why there is a difference in the postsynaptic cell voltage after t=15.0750 ms?
ted wrote:the stimulus is really affecting v at the proper time--it's the
recorded vector that is incorrect.

The fix is for proc init() to call
just before it exits. You'll note such frecord_init() calls in
chapter 8 of the NEURON Book.

Easy to overlook the need to call frecord_init() because it seems
so arbitrary--everything else in the custom proc init() makes sense,
or, like the need to re-init cvode or call fcurrent(), is dictated
by some earlier action that made sense. But calling frecord_init()
actually makes sense too, because the working of Vector.record
involves an internal index that keeps track of the recording process
and increments on each fadvance. That's why the problem you saw was
worse if the init run involved more fadvances. frecord_init() resets
that internal index.


There are lots of models that have a custom proc init, but
frecord_init() is needed only when the init process involves
one or more fadvance() calls.
I randomly picked two ModelDB entries with custom inits that made calls to fadvance() to see if they addressed this issue or not.

Case Study #1: ... mofig2.hoc
Their custom init function includes the following:

Code: Select all

proc init() {
  t = -1e6               // back up in time
  finitialize(v_init)    // initialize
  temp_dt = dt           
  dt = 10                // take a few large steps
  for i=0,19 fadvance()  // to allow currents to reach steady state

  t = 0                  // restore t,dt
  dt = temp_dt

  finitialize(v)         // initialize again
So after the call to fadvance(), they have a call to finitialize(v), which will, as part of its duties, perform the same task that frecord_init() would, resetting the vector index. Therefore, this code would not exhibit the problem I mention above.

Case Study #2: ... ata_in.hoc
Their custom init function includes the following:

Code: Select all

proc init() {
        t = -200
        dtsav = dt
        dt = 10
        for i = 0, 19 {
        dt = dtsav
        t = 0
So, after they call fadvance(), they do not call frecord_init() or anything else that would call frecord_init(). Note that the call to fcurrent() does not call frecord_init() or perform the same task as it. Therefore, I would expect this code to exhibit the same problem as our lab's original code, where any recorded traces are shifted by 20 indices due to the 20 calls to fadvance(). However, this issue should not affect the spike times reported from the model (unless for some reason you were calculating them yourself based on the shifted traces).