Adding white nose to current injection

NMODL and the Channel Builder.
Post Reply
Skyfire79

Adding white nose to current injection

Post by Skyfire79 »

Dear all,

I am trying to model an external current input with white Gaussian noise, i.e., I = f(t) + D*n(t), where f(t) is a given deterministic function and n(t) represents white Gaussian noise with standard deviation D. I did a search in the forum and found the function normrand(). Here is my code:

Code: Select all

NEURON {
        POINT_PROCESS IClampNoise
        RANGE i,del,dur,f0,f1,r,torn,std,bias
        ELECTRODE_CURRENT i
}

UNITS {
        (nA) = (nanoamp)
      }

PARAMETER {
        del=50    (ms)
        dur=200   (ms)
        torn=500  (ms)
        std=0.2   (nA)
        f0=0.2    (nA)
        f1=0.8    (nA)
        r =60
        bias = 0 (nA)
}

ASSIGNED {
        i (nA)
        amp (nA)
        noise (nA)
}

BREAKPOINT {
    at_time(del)
    at_time(del + dur)
   
    if (t < del) {
      i=0   
    } else{  
        if (t < del+dur) {
            noise = normrand(0,std) 	
            amp = f0 + 0.5*(f1-f0)*(tanh((t-torn)/(r/3)-3)+1) 
            i = amp + noise + bias
      }else{  
        i = 0
      }
	}
}


It seems the code can produce the noisy input. However, the neuron voltage became unstable with this input (goes to very large negative value) and the following warning message appears in the hoc screen: exp(826.416) out of range, returning exp(700). To see whether the white noise causes instability, I set the parameter std to 0 (no noise is produced by NMODL) and generated noise in the hoc file like this:

Code: Select all

objref r
r = new Random()
r.normal(0,d^2)

proc advance() {
fadvance()
var = r.repick()
Stim2.bias = var  
}
And the neuron now responds normally to the noisy input. So I reasoned the way I modeled the white noise with normrand() was not correct in the NMODL. I looked over some similar postings in the forum, but haven't found a good and direct answer to my problem, though I guess it should be pretty simple. Please advise and thank you very much in advance!

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

Re: Adding white nose to current injection

Post by ted »

You're probably just seeing the effect of normrand returning the occasional very large negative or positive result. That's the nature of the normal distribution. The error message suggests that your model contains a gating variable that is an exponential function of membrane potential, which is gagging on an unrealistically large value of membrane potential. To test these speculations, you could examine the time course of membrane potential and the current delivered by your IClampNoise object(s).
ted
Site Admin
Posts: 5793
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Adding white nose to current injection

Post by ted »

I take it back. Attaching an instance of IClampNoise to a single compartment model with passive membrane properties and running several simulations, I see several instances in which v jumps abruptly by tens or hundreds of mV, in the absence of anything in IClampNoise.i that could account for the jump. This is with
NEURON -- VERSION 7.2 (436:cbc0331180f8) 2010-04-05
Skyfire79

Re: Adding white noise to current injection

Post by Skyfire79 »

Hi, Ted,

Thank you very much for your help. I guess this is probably due to the incorrect use of the function normrand( ) in NMODL. If I don't use normrand(), are there any other functions to use to generate white noise in NMODL? How can I find out those functions and their usage? Do I need to write C code to implement this?

Thanks again!
GL
ted
Site Admin
Posts: 5793
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Adding white nose to current injection

Post by ted »

Michael Hines pointed out the source of the problem: calling a random number generator in a BREAKPOINT block. The BREAKPOINT block is executed twice on each time step, with slightly different values of v, in order to calculate the derivative di/dv (conductance of the point process). Calling normrand twice causes large random changes in the numerator of the di/dv calculation, which means the current source no longer has a conductance of 0 but instead has a (potentially very large) fluctuating conductance.

The solution is to use a BEFORE BREAKPOINT block to calcuate the value that is to be assigned to i. But the BREAKPOINT block must still exist, to make sure that the value of i will actually be updated on each call to fadvance().

So here's the revised mod file, which should work properly (at least it does in my tests):

Code: Select all

NEURON {
  POINT_PROCESS IClampNoise
  RANGE i,del,dur,f0,f1,r,torn,std,bias
  ELECTRODE_CURRENT i
}

UNITS {
  (nA) = (nanoamp)
}

PARAMETER {
  del=50    (ms)
  dur=200   (ms)
  torn=500  (ms)
  std=0.2   (nA)
  f0=0.2    (nA)
  f1=0.8    (nA)
  r =60
  bias = 0 (nA)
}

ASSIGNED {
  ival (nA)
  i (nA)
  amp (nA)
  noise (nA)
  on (1)
}

INITIAL {
  i = 0
  on = 0
  net_send(del, 1)
}

PROCEDURE seed(x) {
  set_seed(x)
}

BEFORE BREAKPOINT {
  if  (on) {
    noise = normrand(0,std*1(/nA))*1(nA)
    amp = f0 + 0.5*(f1-f0)*(tanh((t-torn)/(r/3)/(1(ms))-3)+1)
    ival = amp + noise + bias
  } else {
    ival = 0
  }
}

BREAKPOINT {
  i = ival
}

NET_RECEIVE (w) {
  if (flag == 1) {
    if (on == 0) {
      : turn it on
      on = 1
      : prepare to turn it off
      net_send(dur, 1)
    } else {
      : turn it off
      on = 0
    }
  }
}
Comments about the new implementation.

Instead of using the long-deprecated at_time(), this implementation employs a simple state machine (which uses NEURON's event delivery system) to control turning the current on and off. The value of "on" denotes whether the current source is or isn't delivering a current. In a simulation, fadvance() is called once per time step. At each call to fadvance(), if "on" is 1, i is assigned a value that depends on a single new evaluation of normrand; otherwise, is assigned a value of 0. The actual calculation of the new value of i is done in the BEFORE BREAKPOINT block (which is called once per fadvance()), and the value is stored in the intermediate variable ival. The actual assignment of the new value to i is done in the BREAKPOINT block (which is called twice per fadvance()).

The INITIAL block sets i to 0, and also sets up the state machine by assgning 0 to "on" and launching a self-event that will return after a delay of "del" ms (i.e. at time t = current time + del = del). The self-event is associated with a "flag" value of 1, so that the NET_RECEIVE block can test any events it receives and verify that the event is a self-event.

When this self-event arrives, the first part of the conditional statement inside the NET_RECEIVE block sets "on" to 1 and launches a second self-event that will return after a delay of "dur" ms. Arrival of this second self-event causes execution of the second part of the conditional, which swithces "on" back to 0, terminating the injected current.

A final note: this implementation contains PROCEDURE seed(), which should be called from hoc during initialization (e.g. by an FInitializeHandler) to specify the seed used by the random number generator. Otherwise successive runs will produce different results even though no parameters have been changed.
Skyfire79

Re: Adding white noise to current injection

Post by Skyfire79 »

Hi, Ted,

The revised mod file works in my model! Thank you and Michael Hines for solving this problem! The use of the NEURON's event delivery system to control the on and off of the current injection is really ingenious!

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

Re: Adding white nose to current injection

Post by ted »

Good to hear it's working. The event delivery system offers many powerful and flexible ways to implement models and complex experimental/simulation protocols.

Thanks for using NEURON. If you publish anything that reports work done with NEURON, please be sure to cite it
How to cite NEURON
viewtopic.php?f=22&t=73
and also let me know so I can add your paper to NEURON's bibliography
http://www.neuron.yale.edu/neuron/stati ... ednrn.html
Skyfire79

Re: Adding white nose to current injection

Post by Skyfire79 »

Sure I will.
einsinghaf
Posts: 11
Joined: Tue Jun 17, 2014 2:23 pm

Re: Adding white nose to current injection

Post by einsinghaf »

Hi there
I have attempt to add a noisy conductance based synapse to my cell.
this the nmodl code

Code: Select all


NEURON {
	POINT_PROCESS Alpha2SynNoise
	RANGE tau1, tau2, e, i, mean, stddev, del, dur
	NONSPECIFIC_CURRENT i

	RANGE g
}

UNITS {
	(nA) = (nanoamp)
	(mV) = (millivolt)
	(uS) = (microsiemens)
}

PARAMETER {
	tau1=.1 (ms) <1e-9,1e9>
	tau2 = 10 (ms) <1e-9,1e9>
	e=0	(mV)
	del=0    (ms)
	dur=0    (ms)
	mean=1
	stddev=0.2
}

ASSIGNED {
	v (mV)
	i (nA)
	g (uS)
	factor
	gnoise
	on (1)
}

STATE {
	A (uS)
	B (uS)
}

INITIAL {
	LOCAL tp
	if (tau1/tau2 > .9999) {
		tau1 = .9999*tau2
	}
	A = 0
	B = 0
	tp = (tau1*tau2)/(tau2 - tau1) * log(tau2/tau1)
	factor = -exp(-tp/tau1) + exp(-tp/tau2)
	factor = 1/factor

	on = 0
	net_send(del, 1)
}


PROCEDURE seed(x) {
  set_seed(x)
}

BEFORE BREAKPOINT {
  if  (on) {
    gnoise = normrand(mean, stddev)
  } else {
    gnoise = 0
  }
}



BREAKPOINT {
	SOLVE state METHOD cnexp
	g = (B - A)*gnoise
	i = g*(v - e)
}

DERIVATIVE state {
	A' = -A/tau1
	B' = -B/tau2
}

NET_RECEIVE(weight (uS)) {
	A = A + weight*factor
	B = B + weight*factor

	if (flag == 1) {
		if (on == 0) {
			: turn it on
			on = 1
			: prepare to turn it off
			net_send(dur, 1)
		} else {
			: turn it off
			on = 0
		}
	}
}

but I can not figure out the errors:(
nrniv: Segmentation violation
Thank you so much inadvance!
einsinghaf
Posts: 11
Joined: Tue Jun 17, 2014 2:23 pm

Re: Adding white nose to current injection

Post by einsinghaf »

The problem was from

Code: Select all

on = 0
net_send(del, 1)
I just change it to

Code: Select all

on = 1
and every thing gets fine!
but I can not understand why?!
menica
Posts: 71
Joined: Wed Sep 02, 2015 11:02 am

Re: Adding white nose to current injection

Post by menica »

Hi,
I would like to modify the IClampnoise in order to tune the frequency of the input signal

I would like to have something similar to the current generated by a sinusoidal function as

i= constantAmp*cos(2*pi*(t-del)*freq*(0.001))

where I can tune freq.

How can I change the amp=f0+0.5(f1-f0)(tanh((t-torn)/(r/3)-3)+1) expression in order to change the frequency of the signal?

Can you please explain the meaning of the torn and r terms?
Maybe tuning f0 and f1 can be a way to explore a frequency range?

Best
Menica
Post Reply