use self events in the NET_RECEIVE block

NMODL and the Channel Builder.
Post Reply
breakwave922

use self events in the NET_RECEIVE block

Post by breakwave922 »

Hi, Ted,
As you suggested, in our synaptic mechanism mod file, I'm going to replace the conditional statements at the start of the DERIVATIVE block(please see the codes below) by the use of self events in the NET_RECEIVE block.

Code: Select all

NEURON {
	POINT_PROCESS pyrD2pyrD_STFD
	USEION ca READ eca	
	NONSPECIFIC_CURRENT inmda, iampa
	RANGE initW
	RANGE Cdur_nmda, AlphaTmax_nmda, Beta_nmda, Erev_nmda, gbar_nmda, W_nmda, on_nmda, g_nmda
	RANGE Cdur_ampa, AlphaTmax_ampa, Beta_ampa, Erev_ampa, gbar_ampa, W, on_ampa, g_ampa
	RANGE eca, ICa, P0, fCa, tauCa, iCatotal
	RANGE Cainf, pooldiam, z
	RANGE lambda1, lambda2, threshold1, threshold2
	RANGE fmax, fmin, Wmax, Wmin, maxChange, normW, scaleW, srcid, destid, tempW  
	RANGE pregid,postgid, thr_rp
	RANGE F, f, tauF, D1, d1, tauD1, D2, d2, tauD2
	RANGE facfactor
}

UNITS {
	(mV) = (millivolt)
        (nA) = (nanoamp)
	(uS) = (microsiemens)
	FARADAY = 96485 (coul)
	pi = 3.141592 (1)
}

PARAMETER {

	srcid = -1 (1)
	destid = -1 (1)
	
	Cdur_nmda = 16.7650 (ms)
	AlphaTmax_nmda = .2659 (/ms)
	Beta_nmda = 0.008 (/ms)
	Erev_nmda = 0 (mV)
	gbar_nmda = .5e-3 (uS)

	Cdur_ampa = 1.4210 (ms)
	AlphaTmax_ampa = 3.8142 (/ms)
	Beta_ampa = 0.1429 (/ms)
	Erev_ampa = 0 (mV)
	gbar_ampa = 1e-3 (uS)

	eca = 120

	Cainf = 50e-6 (mM)
	pooldiam =  1.8172 (micrometer)
	z = 2

	tauCa = 50 (ms)
	P0 = .015
	fCa = .024
	
	lambda1 = 40  :80 : 60 : 12 :80: 20 : 15 :8 :5: 2.5
	lambda2 = .03
	threshold1 = 0.4 :  0.45 : 0.35 :0.35:0.2 :0.50 (uM)
	threshold2 = 0.55 : 0.50 : 0.40 :0.4 :0.3 :0.60 (uM)

	initW = 2 :  0.9 : 0.8 : 2 : 10 : 6 :1.5
	fmax = 3 : 2.5 : 4 : 2 : 3 : 1.5 : 3
	fmin = .8

	thr_rp = 1 : .7
	
	facfactor = 1
	: the (1) is needed for the range limits to be effective
        f = 0 (1) < 0, 1e9 >    : facilitation
        tauF = 20 (ms) < 1e-9, 1e9 >
        d1 = 0.95 (1) < 0, 1 >     : fast depression
        tauD1 = 40 (ms) < 1e-9, 1e9 >
        d2 = 0.9 (1) < 0, 1 >     : slow depression
        tauD2 = 70 (ms) < 1e-9, 1e9 >		
}

ASSIGNED {
	v (mV)

	inmda (nA)
	g_nmda (uS)
	on_nmda
	W_nmda

	iampa (nA)
	g_ampa (uS)
	on_ampa
	W

	t0 (ms)

	ICa (mA)
	Afactor	(mM/ms/nA)
	iCatotal (mA)

	dW_ampa
	Wmax
	Wmin
	maxChange
	normW
	scaleW
	tempW
	pregid
	postgid

	rp
	tsyn
	
	fa
	F
	D1
	D2
}

STATE { r_nmda r_ampa capoolcon }

INITIAL {
	on_nmda = 0
	r_nmda = 0
	W_nmda = initW

	on_ampa = 0
	r_ampa = 0
	W = initW
	tempW = initW
	t0 = -1
	
	Wmax = fmax*initW
	Wmin = fmin*initW
	maxChange = (Wmax-Wmin)/10
	dW_ampa = 0

	capoolcon = Cainf
	Afactor	= 1/(z*FARADAY*4/3*pi*(pooldiam/2)^3)*(1e6)

	fa =0
	F = 1
	D1 = 1
	D2 = 1
}

BREAKPOINT {
	SOLVE release METHOD cnexp
}

DERIVATIVE release {
	if (t0>0) {
		if (rp < thr_rp) {
			if (t-t0 < Cdur_nmda) {
				on_nmda = 1
			} else {
				on_nmda = 0
			}
			if (t-t0 < Cdur_ampa) {
				on_ampa = 1
			} else {
				on_ampa = 0
			}
		} else {
			on_nmda = 0
			on_ampa = 0
		}
	}
	r_nmda' = AlphaTmax_nmda*on_nmda*(1-r_nmda)-Beta_nmda*r_nmda
	r_ampa' = AlphaTmax_ampa*on_ampa*(1-r_ampa)-Beta_ampa*r_ampa

	dW_ampa = eta(capoolcon)*(lambda1*omega(capoolcon, threshold1, threshold2)-lambda2*W)*dt

	: Limit for extreme large weight changes
	if (fabs(dW_ampa) > maxChange) {
		if (dW_ampa < 0) {
			dW_ampa = -1*maxChange
		} else {
			dW_ampa = maxChange
		}
	}

	:Normalize the weight change
	normW = (W-Wmin)/(Wmax-Wmin)
	if (dW_ampa < 0) {
		scaleW = sqrt(fabs(normW))
	} else {
		scaleW = sqrt(fabs(1.0-normW))
	}

	W = W+ dW_ampa*scaleW
	
	if (fmod(t,100)< dt) {
		if (W > tempW + maxChange) {
		W = tempW + maxChange
		}
		tempW = W
	}
	
	:Weight value limits
	if (W > Wmax) { 
		W = Wmax
	} else if (W < Wmin) {
 		W = Wmin
	}

	g_nmda = gbar_nmda*r_nmda*facfactor
	inmda = W_nmda*g_nmda*(v - Erev_nmda)*sfunc(v)

	g_ampa = gbar_ampa*r_ampa*facfactor
	iampa = W*g_ampa*(v - Erev_ampa)

	ICa = P0*g_nmda*(v - eca)*sfunc(v)
	capoolcon'= -fCa*Afactor*ICa + (Cainf-capoolcon)/tauCa
}

NET_RECEIVE(dummy_weight) {
	t0 = t
	rp = unirand()	
	
	:F  = 1 + (F-1)* exp(-(t - tsyn)/tauF)
	D1 = 1 - (1-D1)*exp(-(t - tsyn)/tauD1)
	D2 = 1 - (1-D2)*exp(-(t - tsyn)/tauD2)
 :printf("%g\t%g\t%g\t%g\t%g\t%g\n", t, t-tsyn, F, D1, D2, facfactor)
	::printf("%g\t%g\t%g\t%g\n", F, D1, D2, facfactor)
	tsyn = t
	
	facfactor = F * D1 * D2

	:F = F+f  :F * f
	
	if (F > 3) { 
	F=3	}
	if (facfactor < 0.5) { 
	facfactor=0.5
	}	
	D1 = D1 * d1
	D2 = D2 * d2
:printf("\t%g\t%g\t%g\n", F, D1, D2)
}

:::::::::::: FUNCTIONs and PROCEDUREs ::::::::::::

FUNCTION sfunc (v (mV)) {
	UNITSOFF
	sfunc = 1/(1+0.33*exp(-0.06*v))
	UNITSON
}

FUNCTION eta(Cani (mM)) {
	LOCAL taulearn, P1, P2, P4, Cacon
	P1 = 0.1
	P2 = P1*1e-4
	P4 = 1
	Cacon = Cani*1e3
	taulearn = P1/(P2+Cacon*Cacon*Cacon)+P4
	eta = 1/taulearn*0.001
}

FUNCTION omega(Cani (mM), threshold1 (uM), threshold2 (uM)) {
	LOCAL r, mid, Cacon
	Cacon = Cani*1e3
	r = (threshold2-threshold1)/2
	mid = (threshold1+threshold2)/2
	if (Cacon <= threshold1) { omega = 0}
	else if (Cacon >= threshold2) {	omega = 1/(1+50*exp(-50*(Cacon-threshold2)))}
	else {omega = -sqrt(r*r-(Cacon-mid)*(Cacon-mid))}
}
FUNCTION unirand() {    : uniform random numbers between 0 and 1
        unirand = scop_random()
}
But we have two receptors in this mechanism, NMDA and AMPA; on_nmda and on_ampa are used to control them respectively and independently. Then if I want to use self events, I have to use two different flag, right?
The following code is what I've updated in the NET_RECEIVE block.

Code: Select all

NET_RECEIVE(dummy_weight) {

     if (flag==0) {           :a spike arrived, start onset state if not already on
         if (!on_nmda){       :this synpase joins the set of synapses in onset state
          t0=t
	      on_nmda=1
		  flag_nmda=1
	      net_send(Cdur_nmda,1)
         } else {             :already in onset state, so move offset time
          net_move(t+Cdur_nmda)
	      }	  
	    }
	if (flag == 1) { : turn off transmitter, i.e. this synapse enters the offset state
	
	t0=t
	on_nmda=0
    }
} 
Is there any method that I can use to implement the second receptor mechanism, i.e. ampa, separately and independently of NMDA mechanism, by using self events?

Thanks in advance.
ted
Site Admin
Posts: 6289
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: use self events in the NET_RECEIVE block

Post by ted »

I realize that much effort has already gone into your NMODL code, but before proceeding further let me suggest that you take a look at ampanmda.mod in ModelDB entry 144570 and see if it is close enough to what you want to serve as is, or after minor modification.
breakwave922

Re: use self events in the NET_RECEIVE block

Post by breakwave922 »

ted wrote:I realize that much effort has already gone into your NMODL code, but before proceeding further let me suggest that you take a look at ampanmda.mod in ModelDB entry 144570 and see if it is close enough to what you want to serve as is, or after minor modification.
Hi, Ted,

Thanks. I read at the ampanmda.mod that you recommended. But the case I have now is different than in entry 144570. In there, Cdur is the same for both ampa and nmda. But in my case, Cdur is different for them. Can I turn the transmitter on/off separately, for ampa and nmda , which means I may need two flags for ampa and nmda.
ted
Site Admin
Posts: 6289
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: use self events in the NET_RECEIVE block

Post by ted »

the case I have now is different than in entry 144570. In there, Cdur is the same for both ampa and nmda. But in my case, Cdur is different for them.
Why bother with Cdur for AMPAergic synaptic transmission? Those channels open so fast that current rise times are a small fraction of a millisecond; time course of the resulting conductance change is closely approximated by an abrupt jump followed by a monoexponential decay. That said, your NMODL code indicates that your conceptual model of synaptic transmission is quite complex, so maybe something as simple as the AmpaNmda mechanism used by Yu et al. 2013 would not do the job.

One thing I would suggest that would make development and debugging much less difficult for you: use separate NMODL files to implement AMPA- and NMDA-gated synaptic transmission. The present implementation's NEURON block and lists of parameters and assigned variables are much too large. Modular code is easier to work with.

Conditional statements are OK in FUNCTIONs and the NET_RECEIVE block, but try to avoid using them elsewhere--especially don't put them in DERIVATIVE blocks, unless you like setting traps for yourself and others. Put only ODEs in DERIVATIVE blocks, if at all possible.

A strong suggestion: don't include randomness or stochasticity until after you're sure everything else works properly. Otherwise you're complicating your development and debugging process.
Can I turn the transmitter on/off separately, for ampa and nmda , which means I may need two flags for ampa and nmda.
Eliminate the problem by breaking your implementation into two separate synaptic mechanisms, one for AMPA-gated and the other for NMDA-gated synaptic transmission.
breakwave922

Re: use self events in the NET_RECEIVE block

Post by breakwave922 »

Hi, Ted,

Really appreciate your reply and time.
ted wrote:One thing I would suggest that would make development and debugging much less difficult for you: use separate NMODL files to implement AMPA- and NMDA-gated synaptic transmission. The present implementation's NEURON block and lists of parameters and assigned variables are much too large. Modular code is easier to work with.
Eliminate the problem by breaking your implementation into two separate synaptic mechanisms, one for AMPA-gated and the other for NMDA-gated synaptic transmission.
I understand that by separating synaptic mechanism into two would solve our problem, but that will double the synapses we need to track now in 1000-cell model. Since our goal is to build a 25,000-cell network, data size would be a problem for us then.
Do you think it is fine that we just keep the two mechanisms into one mod file, by not using self events and keep as it is now?
ted wrote: Conditional statements are OK in FUNCTIONs and the NET_RECEIVE block, but try to avoid using them elsewhere--especially don't put them in DERIVATIVE blocks, unless you like setting traps for yourself and others. Put only ODEs in DERIVATIVE blocks, if at all possible.
How about is I move all the conditional statements into BREAKPOINT block, and leave only ODEs in DERIVATIVE blocks?
ted wrote: A strong suggestion: don't include randomness or stochasticity until after you're sure everything else works properly. Otherwise you're complicating your development and debugging process.
Yes, we are going to remove the randomness part in this mod file.
ted
Site Admin
Posts: 6289
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: use self events in the NET_RECEIVE block

Post by ted »

breakwave922 wrote:I understand that by separating synaptic mechanism into two would solve our problem, but that will double the synapses we need to track now in 1000-cell model. Since our goal is to build a 25,000-cell network, data size would be a problem for us then.
Seems unlikely. How many synapses do you expect to need?
How about is I move all the conditional statements into BREAKPOINT block, and leave only ODEs in DERIVATIVE blocks?
Not sure that is much better. I don't really want to have to wade through all the hideous details, but maybe I need to look more closely at the code in order to make a more targeted suggestion.
breakwave922

Re: use self events in the NET_RECEIVE block

Post by breakwave922 »

Seems unlikely. How many synapses do you expect to need?
For the current 1000-cell network, we already have around 40,000 synapses.
Ted, "seems unlikely" means, we have some potential problems now? Or it's OK, we can go with the current mechanism, i.e. without using self events?
but maybe I need to look more closely at the code in order to make a more targeted suggestion.
Yes. Please take a closer look give your suggestion. Thank you so much.
ted
Site Admin
Posts: 6289
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: use self events in the NET_RECEIVE block

Post by ted »

40,000 is no big deal. NEURON can handle as many instances of an individual class as your computer's memory can allow, or the largest integer that hoc can represent, whichever is smaller. On my 8 GB PC running a 32 bit Linux I just now created 1e8 objrefs, then turned them all into ExpSyns attached to a soma. Took a few seconds. Wasn't able to make 1e9 objrefs, however. Probably can do better with a 64 bit OS.

The question is how the number of synapses in your model scales with the number of neurons.
breakwave922

Re: use self events in the NET_RECEIVE block

Post by breakwave922 »

We are running on paralleled codes, and on workstation. So memory shouldn't be a problem. But our usable hard drive space is a big problem. Sometimes we may even want to save the synaptic info at 1 dt step with a long protocol, which would make the situation even worse. The number of synapses in our model scales nearly exponentially with the number of neurons.
Ted, do you think not using self event would be/cause a big issue? But I didn't see anything wrong with the current coding scheme at this part (on_nmda, on_ampa). Maybe we can postpone this and proceed with other potential problems in this synaptic mechanism. I believe there are some.
ted
Site Admin
Posts: 6289
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: use self events in the NET_RECEIVE block

Post by ted »

breakwave922 wrote:We are running on paralleled codes, and on workstation. So memory shouldn't be a problem. But our usable hard drive space is a big problem. Sometimes we may even want to save the synaptic info at 1 dt step with a long protocol, which would make the situation even worse.
How does that have anything to do with whether you have bundled multiple synaptic mechanisms into a single NMODL file, or whether the code has been factored into separate files, i.e. one NMODL file per mechanism? Debugging and development, however, depend critically on having understandable code. Making sure that there is a close match between your conceptual model and your computational model should be a high priority.
The number of synapses in our model scales nearly exponentially with the number of neurons.
Do you mean the number of NetCons, or the number of synaptic mechanisms? If your synaptic mechanisms are linear, then multiple instances that are electrically close to each other can be represented by a single instance that is the target of multiple NetCons, and the number of synaptic mechanisms should be proportional to the number of cells.
Ted, do you think not using self event would be/cause a big issue? But I didn't see anything wrong with the current coding scheme at this part (on_nmda, on_ampa). Maybe we can postpone this and proceed with other potential problems in this synaptic mechanism. I believe there are some.
Let's take the discussion to a private exchange of email.
breakwave922

Re: use self events in the NET_RECEIVE block

Post by breakwave922 »

How does that have anything to do with whether you have bundled multiple synaptic mechanisms into a single NMODL file, or whether the code has been factored into separate files, i.e. one NMODL file per mechanism?
Hi, Ted, sorry to confuse. I meant, if we separate the mod file, we have to record like weight info, synaptic currents info, etc, for NMDA and AMPA separately, which would double the number of the files. I'm afraid we don't have that much of space to save the files, especially when network size increases.
Do you mean the number of NetCons, or the number of synaptic mechanisms? If your synaptic mechanisms are linear, then multiple instances that are electrically close to each other can be represented by a single instance that is the target of multiple NetCons, and the number of synaptic mechanisms should be proportional to the number of cells.
Sorry, I made a mistake here. It should be linear to the number of cells. But another scenario I didn't consider yesterday is about neuromodulators. We have at least 3 different kinds of neuromodulators for each synapse, then we have at least 4 types of candidate synapse for each connections. This applies to all the of connections, including pyramidal to pyramidal, pyramidal to interneuron, interneuron(1or2) to pyramidal, and interneuron1 to interneuron2 connections. If we split the mod file, I'm afraid it would complicate the system.
Post Reply