questions on event and NET_RECEIVE block

NMODL and the Channel Builder.
Post Reply
ttpuff

questions on event and NET_RECEIVE block

Post by ttpuff »

Hi, I'm studying the event method now. I'm confused by some questions on how the event works

1. Here is a model by Ted

http://senselab.med.yale.edu/modeldb/Sh ... sexpsn.mod

Code: Select all

INITIAL {
: these are in NET_RECEIVE to be per-stream
	F = 1
	D1 = 1
	D2 = 1
	tsyn = t
: this header will appear once per stream
: printf("t\t t-tsyn\t F\t D1\t D2\t amp\t newF\t newD1\t newD2\n")
}
So the INITIAL will only occurs once and at the beginning of the per-stream. By a stream, does that mean a single simulation cycle of NEURON? For instance, if we wanna run 10 trials, one trial is exactly one run. So in the above code, INITIAL only is applied at the beginning of 10 TRIALS rather than each RUN. But the INITIAL block in the MOD file is applied for each RUN, i.e., at the beginning of each run.

Thus, if I run the above code for 10 trials in one single simulation cycle. Results should be

F = 1 for the 1st trial, F = XXX in the following trials

If I put F=1 in the INITIAL block of MOD file rather than the INITIAL of the NET_RECEIVE block, results should be

F = 1 for every trials

So the stream is for each simulation cycle, not each run. I found that's true after I did a experiment. Is that right?


2. Whenever an event is triggered in NET_RECEIVE block, will this event only follow this stream by exact flags we set? Let's take an example,

Code: Select all

   
NET_RECEIVE(weight, nspike, on) { 
if (flag == 1) {
	WATCH (v > Thr ) 2	: threshod reached?
    } else if (flag == 2) {
	net_event(t)                 : deliver a message
	on = 1
	lastspike = t
	nspike = nspike +1      :spike counted
	v = vON                     : 40 mv
	net_send(spikedur, 3)
    } else if (flag == 3) {   : spike off, refactory period on
	v = vOFF                : -60 mv
	on = 0
    }  
in the above code, my LIF cell has a spike duration as 1ms, i.e., if v>thr, I set v=40 mv for 1 ms. My question is that during this spike duration time, obviously v>Thr, so do this deliver another event? Or the next event only happens after the first event go over all these three flags?

suppose the fixed dt=0.1, v>thr at t=0, then t=0.1, we'll has v>thr. Do we have another event at t=0.1? If not, when we will have second event?


Hope I said these clearly, thanks.

[/code]
ted
Site Admin
Posts: 6398
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: questions on event and NET_RECEIVE block

Post by ted »

Time to clear up many misconceptions. I hope that the following does not merely
foster new ones.
ttpuff wrote:By a stream, does that mean a single simulation cycle of NEURON?
"stream" = "afferent stream" = "stream of events delivered by a single NetCon"
Analogous to a spike train carried by a single axon.

If a NET_RECEIVE block starts with the declaration
NET_RECEIVE (w) {
then the weight is a scalar whose value is set by the weight of the NetCon that delivers
an event. If a NET_RECEIVE block starts with a declaration that includes more than one
variable name, e.g.
NET_RECEIVE (w, a1, a2, . . . an) {
then the weight is a vector with n+1 elements. Each NetCon that has this mechanism as its
target will automatically have a weight vector with n+1 elements. The first element of the
weight vector is just the "synaptic weight" in the usual sense of that term. The other
elements can be used to store information about the "state" of the synaptic mechanism.
In many models of stream-specific use-dependent synaptic plasticity, each stream needs
to keep track of the time of the previous event that it delivered, as well as the values of
variables that describe the degree of synaptic potentiation and/or depression immediately
after the delivery of that event. For such models to work properly, the "initial state" of
each afferent stream cannot be left to chance. The purpose of the INITIAL block
embedded inside a NET_RECEIVE block is to properly initialize the state of each afferent
stream (each NetCon that targets this synaptic mechanism).

So suppose a mechanism description contains two INITIAL blocks: one that lies outside a
NET_RECEIVE block (let's call this one "A"), and another that lies inside a NET_RECEIVE
block (let's call this one "B"). When the model is initialized, the following will occur:

Code: Select all

for each instance of this mechanism {
  execute the contents of INITIAL block "A"
  for each NetCon that targets this mechanism instance {
    execute the contents of INITIAL block "B"
  }
}

The difference between an initialization and a "run":
Initialization and running a simulation are not the same thing. Initialization means assigning
initial values to all state variables, and using these to calculate the corresponding values
of assigned variables. This constitutes the starting point of a simulation. A "run" consists
of starting from this point and advancing the solution from time t0 to tstop.
NEURON's standard run system contains a procedure called run() which does two
things: initializes the model, then advances the solution from t = 0 to tstop.
if I run the above code for 10 trials in one single simulation cycle. Results should be

F = 1 for the 1st trial, F = XXX in the following trials
No. After each initialization, F would be 1 for every NetCon that targets this mechanism.
Each run() would reset F to 1, for each NetCon that targets this mechanism, before
advancing the solution from t = 0 to tstop.
If I put F=1 in the INITIAL block of MOD file rather than the INITIAL of the NET_RECEIVE block, results should be

F = 1 for every trials
No. It would have no affect on the weight vectors of the NetCons that target the synapse.
Instead, each NetCon's weight vector would have F == 0.
2. Whenever an event is triggered in NET_RECEIVE block, will this event only follow this stream by exact flags we set?
This question is an abuse of terms. Flags do not control where events are delivered.

This example

Code: Select all

   
NET_RECEIVE(weight, nspike, on) { 
if (flag == 1) {
	WATCH (v > Thr ) 2	: threshod reached?
    } else if (flag == 2) {
	net_event(t)                 : deliver a message
	on = 1
	lastspike = t
	nspike = nspike +1      :spike counted
	v = vON                     : 40 mv
	net_send(spikedur, 3)
    } else if (flag == 3) {   : spike off, refactory period on
	v = vOFF                : -60 mv
	on = 0
    }  
contains a big mistake: v is a reserved name in NMODL. It means membrane potential.
You are asking for a conflict in variable name space, which will generate garbage
results. If you are lucky, the results will be extremely bad so you will recognize the fact
before wasting too much time. Better to use vm or Vm instead.
in the above code, my LIF cell has a spike duration as 1ms, i.e., if v>thr, I set v=40 mv for 1 ms. My question is that during this spike duration time, obviously v>Thr, so do this deliver another event?
No. Threshold crossings are detected when the monitored variable moves in a
positive-going direction.
Or the next event only happens after the first event go over all these three flags?

This question is an abuse of terms. Events do not go over flags.
suppose the fixed dt=0.1, v>thr at t=0, then t=0.1, we'll has v>thr. Do we have another event at t=0.1? If not, when we will have second event?
What do you think? Pretend you're the computer and try to figure it out. Then implement
your mechanism and see if it does what you predicted.
If the outcome disagrees with your prediction, try to figure out which is wrong.
But if the outcome agrees with your prediction, can you be sure that both are right? Or is
there a chance that both are wrong?
ttpuff

Re: questions on event and NET_RECEIVE block

Post by ttpuff »

Thanks, more clearly than before.


ted wrote:Time to clear up many misconceptions. I hope that the following does not merely
foster new ones.
ttpuff wrote:By a stream, does that mean a single simulation cycle of NEURON?
"stream" = "afferent stream" = "stream of events delivered by a single NetCon"
Analogous to a spike train carried by a single axon.

If a NET_RECEIVE block starts with the declaration
NET_RECEIVE (w) {
then the weight is a scalar whose value is set by the weight of the NetCon that delivers
an event. If a NET_RECEIVE block starts with a declaration that includes more than one
variable name, e.g.
NET_RECEIVE (w, a1, a2, . . . an) {
then the weight is a vector with n+1 elements. Each NetCon that has this mechanism as its
target will automatically have a weight vector with n+1 elements. The first element of the
weight vector is just the "synaptic weight" in the usual sense of that term. The other
elements can be used to store information about the "state" of the synaptic mechanism.
In many models of stream-specific use-dependent synaptic plasticity, each stream needs
to keep track of the time of the previous event that it delivered, as well as the values of
variables that describe the degree of synaptic potentiation and/or depression immediately
after the delivery of that event. For such models to work properly, the "initial state" of
each afferent stream cannot be left to chance. The purpose of the INITIAL block
embedded inside a NET_RECEIVE block is to properly initialize the state of each afferent
stream (each NetCon that targets this synaptic mechanism).
It's exactly my understanding too, thanks.
So suppose a mechanism description contains two INITIAL blocks: one that lies outside a
NET_RECEIVE block (let's call this one "A"), and another that lies inside a NET_RECEIVE
block (let's call this one "B"). When the model is initialized, the following will occur:

Code: Select all

for each instance of this mechanism {
  execute the contents of INITIAL block "A"
  for each NetCon that targets this mechanism instance {
    execute the contents of INITIAL block "B"
  }
}
The difference between an initialization and a "run":
Initialization and running a simulation are not the same thing. Initialization means assigning
initial values to all state variables, and using these to calculate the corresponding values
of assigned variables. This constitutes the starting point of a simulation. A "run" consists
of starting from this point and advancing the solution from time t0 to tstop.
NEURON's standard run system contains a procedure called run() which does two
things: initializes the model, then advances the solution from t = 0 to tstop.
if I run the above code for 10 trials in one single simulation cycle. Results should be

F = 1 for the 1st trial, F = XXX in the following trials
No. After each initialization, F would be 1 for every NetCon that targets this mechanism.
Each run() would reset F to 1, for each NetCon that targets this mechanism, before
advancing the solution from t = 0 to tstop.
If I put F=1 in the INITIAL block of MOD file rather than the INITIAL of the NET_RECEIVE block, results should be

F = 1 for every trials
No. It would have no affect on the weight vectors of the NetCons that target the synapse.
Instead, each NetCon's weight vector would have F == 0.

right, I made a mistake here. Actually, here is my question. See the code :

Code: Select all

: NetCon's weight vector has these elements: 
NET_RECEIVE(weight, R, u, nspike, on) { 
INITIAL {
: these are in NET_RECEIVE to be per-stream
    R = 1 
    u = U  
: this header will appear once per stream
: printf("t\t t-tsyn\t F\t D1\t D2\t amp\t newF\t newD1\t newD2\n")
}


    : on == 1 if transmitter is present ("onset" state), otherwise 0
    : flag is an implicit argument of NET_RECEIVE, normally 0
    if (flag == 0) {
                lastspike = t		
		nspike = nspike+1
		printf("spike at t=%g, nspike is %g, u=%g \n", lastspike,nspike, u)
     } 

Code: Select all

 5 trials ... 
 
 >>>>>>>>>>>>>>>Trial=1 
 spike at t=10.8, nspike is 1, u=0.5 

 >>>>>>>>>>>>>>>Trial=2 
 spike at t=10.8, nspike is 2, u=0.5 

 >>>>>>>>>>>>>>>Trial=3 
 spike at t=10.8, nspike is 3, u=0.5 

 >>>>>>>>>>>>>>>Trial=4 
 spike at t=10.8, nspike is 4, u=0.5 

 >>>>>>>>>>>>>>>Trial=5 
 spike at t=10.8, nspike is 5, u=0.5 

If move u and R out of NET_RECEIVE block, like this:

Code: Select all

INITIAL {
    R = 1 
    u = U     
}

: NetCon's weight vector has these elements: 
NET_RECEIVE(weight, nspike, on) { 
    : on == 1 if transmitter is present ("onset" state), otherwise 0
    : flag is an implicit argument of NET_RECEIVE, normally 0
    if (flag == 0) {
                lastspike = t		
		nspike = nspike+1
		printf("spike at t=%g, nspike is %g, u=%g \n", lastspike,nspike, u)
     } 

Results are below:

Code: Select all

 5 trials ... 
 
 >>>>>>>>>>>>>>>Trial=1 
 spike at t=10.8, nspike is 1, u=0.5 

 >>>>>>>>>>>>>>>Trial=2 
 spike at t=10.8, nspike is 1, u=0.5 

 >>>>>>>>>>>>>>>Trial=3 
 spike at t=10.8, nspike is 1, u=0.5 

 >>>>>>>>>>>>>>>Trial=4 
 spike at t=10.8, nspike is 1, u=0.5 

 >>>>>>>>>>>>>>>Trial=5 
 spike at t=10.8, nspike is 1, u=0.5 
In both cases, I didn't initialize nspike. If I put nspike=0 into INITIAL of NET_RECEIVE block together with u and R, then I'll get the second result. I can't figure out what happened here.

Each run() reset u=0.5, but not for nspike=0 automatically.
ttpuff

Re: questions on event and NET_RECEIVE block

Post by ttpuff »

ted wrote:
This example

Code: Select all

   
NET_RECEIVE(weight, nspike, on) { 
if (flag == 1) {
	WATCH (v > Thr ) 2	: threshod reached?
    } else if (flag == 2) {
	net_event(t)                 : deliver a message
	on = 1
	lastspike = t
	nspike = nspike +1      :spike counted
	v = vON                     : 40 mv
	net_send(spikedur, 3)
    } else if (flag == 3) {   : spike off, refactory period on
	v = vOFF                : -60 mv
	on = 0
    }  
contains a big mistake: v is a reserved name in NMODL. It means membrane potential.
You are asking for a conflict in variable name space, which will generate garbage
results. If you are lucky, the results will be extremely bad so you will recognize the fact
before wasting too much time. Better to use vm or Vm instead.
But I check this model:

http://senselab.med.yale.edu/modeldb/Sh ... ikeout.mod

So you mean we can't assign v directly?

Code: Select all

NET_RECEIVE(w) {
	if (flag == 1) {
		net_event(t)
		net_send(refrac, 2)
		v = vrefrac
		g = grefrac
	}else if (flag == 2) {
		g = 0
	}else if (flag == 3) {
		WATCH (v > thresh) 1
	}	
}


No. Threshold crossings are detected when the monitored variable moves in a
positive-going direction.
I see, we only need detect the threshold crossings v>thr as a event, rather than how much time is when v>thr.
ted
Site Admin
Posts: 6398
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: questions on event and NET_RECEIVE block

Post by ted »

ttpuff wrote:But I check this model:

http://senselab.med.yale.edu/modeldb/Sh ... ikeout.mod
Let me correct myself. It is possible for a POINT_PROCESS to assign a value to membrane
potential. We did it in spikeout.mod, a mod file that is just one part of a "conductance-
based integrate and fire" model cell. You might call that an example of "the Sopranos
style of programming" --otherwise known as "write it and fugeddaboudit."

However, the code excerpt that you provide differs from the NET_RECEIVE block in
spikeout.mod; presumably your own mod file has an INITIAL block that contains the
statement net_send(0, 1).
ted
Site Admin
Posts: 6398
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: questions on event and NET_RECEIVE block

Post by ted »

ttpuff wrote:

Code: Select all

 5 trials ... 
 
 >>>>>>>>>>>>>>>Trial=1 
 spike at t=10.8, nspike is 1, u=0.5 

 >>>>>>>>>>>>>>>Trial=2 
 spike at t=10.8, nspike is 2, u=0.5 

 >>>>>>>>>>>>>>>Trial=3 
 spike at t=10.8, nspike is 3, u=0.5 

 >>>>>>>>>>>>>>>Trial=4 
 spike at t=10.8, nspike is 4, u=0.5 

 >>>>>>>>>>>>>>>Trial=5 
 spike at t=10.8, nspike is 5, u=0.5 
It is time to emphasize the importance of conceptual clarity and reproducibility.

Both are absolutely essential to scientific research, whether one is working on physical
systems or computer models. A computer model should be capable of generating
completely reproducible results, every time a simulation is run, unless one deliberately
takes some action between runs that changes
--a model parameter or the initial value of a state variable (e.g. sodium chanel density,
an ionic concentration, the seed for a pseudorandom sequence generator)
--the structure of the model equations (e.g. adding a new dendrite to a cell, inserting a
new voltage-gated channel)
--or a simulation parameter (e.g. time step, numerical integration method)

It is a very bad idea to construct a model in such a way as to interfere with
reproducibility, because that eliminates the ability to verify correctness of the model
implementation. And without verification, how can one tell if there is a close match
between the concept (hypothesis) in one's mind, and the model that is implemented in
the computer?

Proper initialization is an absolute prerequisite for reproducibility. If a parameter or state
variable changes in the course of a simulation, it must be reset to the desired initial value
before the next simulation is run. Leftover results from the end of one run should not
be the accidental starting point of the next run.

"Oh, but we want to model use-dependent synaptic plasticity. Our idea is to run a series
of simulations, and automatically change model parameters at the end of each simulation."

Fine. So here's how to do it, in pseudocode:

Code: Select all

set up the equations that describe the model system
REPEAT
  1. Run a simulation. That is, initialize the model (set parameters 
      and states to the desired values), 
      then advance the solution from 0 to tstop
  2. Analyze the results to decide the new desired values of parameters 
      and state variable initial conditions
UNTIL DONE
One must be able to repeat step 1 as many times as one likes, and get exactly the same
results each time.

Properly written mod files, used properly, generate reproducible results.
ttpuff

Re: questions on event and NET_RECEIVE block

Post by ttpuff »

Right, I do have net_send(0, 1). I want to set up a integrate-and-fire model by modifying this spikeout.mod by adding a spike duration as 1ms. Maybe I also need a ON current by turning on gON.

My idea is that turning on gON and off gOFF when a spike is on, after 1 ms, turn off gON and on gOFF, after the refractory period, say 2ms, turn off both. I'm testing this idea. If you can give me some suggestions, that will be great. Thank you very much.

ted wrote: However, the code excerpt that you provide differs from the NET_RECEIVE block in
spikeout.mod; presumably your own mod file has an INITIAL block that contains the
statement net_send(0, 1).
ttpuff

Re: questions on event and NET_RECEIVE block

Post by ttpuff »

Exactly, we have to know exactly which variables are need to be initialized in a simulation, and which are need to updated after a simulation. It's better to always initialize variables.

Also , in my case, I want to input two stimuli (POINT PROCESS) for each trial, i.e., each stimuli is presented in alternative trial. To do this, the way I figured out is that making a redeclaration of stimulus object in each simulation. Since redeclaration of objects by redefining objref STIM will erase the former STIM defined. Is that O.K. in NEURON? Thanks.

ted wrote: Fine. So here's how to do it, in pseudocode:

Code: Select all

set up the equations that describe the model system
REPEAT
  1. Run a simulation. That is, initialize the model (set parameters 
      and states to the desired values), 
      then advance the solution from 0 to tstop
  2. Analyze the results to decide the new desired values of parameters 
      and state variable initial conditions
UNTIL DONE
One must be able to repeat step 1 as many times as one likes, and get exactly the same
results each time.

Properly written mod files, used properly, generate reproducible results.
ted
Site Admin
Posts: 6398
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: questions on event and NET_RECEIVE block

Post by ted »

ttpuff wrote:I want to input two stimuli (POINT PROCESS) for each trial, i.e., each stimuli is presented in alternative trial. To do this, the way I figured out is that making a redeclaration of stimulus object in each simulation.
I don't understand why such a thing would be necessary. What are you trying to do?
ttpuff

Re: questions on event and NET_RECEIVE block

Post by ttpuff »

Oh, sorry, forget it. I'm the wrong idea.
Post Reply