Adding GABAb

NMODL and the Channel Builder.
Post Reply
Cal

Adding GABAb

Post by Cal »

Okay, so I have a Neuron model that I've been working on, and have already added AMPA/NMDA/GABAa synapses via NetCons and such.

I wanted to use this .mod file of code:

"http://senselab.med.yale.edu/modeldb/Sh ... \gabab.mod"

to insert GABAb to my model. I also have written my files such that Neuron can read a list of input times to drive the attached synaptic currents.

I've attached my relevant code here:

Code: Select all

objref ni
strdef file3
ni = new File()
file3 = "numinputs.dat"
ni.ropen(file3)
numinputs = ni.scanvar()
ni.close()

objref nii
strdef file47
nii = new File()
file47 = "numinputsI.dat"
nii.ropen(file47)
numinputsI = nii.scanvar()
nii.close()

objref rf
objref atf
objref otf
objref rsp[numinputs]
objref rspI[numinputsI]

objref a[numinputs]
objref b[numinputs]

objref c[numinputsI]
objref d[numinputsI]

objref fih
objref nil
objref fihlist

objref nclist1, nctemp1
objref nclist2, nctemp2
objref nclist3, nctemp3
objref nclist4, nctemp4

double ampatau[1]
double gabaatau[1]

nclist1 = new List()
nclist2 = new List()
nclist3 = new List()
nclist4 = new List()

strdef filename
strdef filename2
strdef filename3

strdef filenameI
strdef dumbfile
strdef dumbfileI

atf = new File()
sprint(filename2,"ampatau.dat")
atf.ropen(filename2)
ampatau = atf.scanvar()
atf.close()

otf = new File()
sprint(filename3,"gabaatau.dat")
otf.ropen(filename3)
gabaatau = otf.scanvar()
otf.close()

rf = new File()

for iii = 0,numinputs-1 {
	sprint(filename,"dumbfile%d.dat",iii+1)
	dumbfile = filename
	rf.ropen(dumbfile)

	rsp[iii] = new Vector()
	n = rsp[iii].scanf(rf)
	numspiking = rsp[iii].size()
	rf.close

	a[iii] = new IC_AMPA_PPD(0.5)
	a[iii].tau = ampatau
	a[iii].presynG = 1
	nctemp1 = new NetCon(nil,a[iii],0,1,(ampaconduct))
	nclist1.append(nctemp1)

	b[iii] = new IC_NMDA_PPD(0.5)
	b[iii].presynG = 1
	nctemp2 = new NetCon(nil,b[iii],0,1,(nmdaconduct))
	nclist2.append(nctemp2)
}

for iiii = 0,numinputsI-1 {
	sprint(filenameI,"idumbfile%d.dat",iiii+1)
	dumbfileI = filenameI
	rf.ropen(dumbfileI)

	rspI[iiii] = new Vector()
	n = rspI[iiii].scanf(rf)
	numspikingI = rspI[iiii].size()
	rf.close

	c[iiii] = new ICGABAa2(0.5)
	c[iiii].tau = gabaatau
	nctemp3 = new NetCon(nil,c[iiii],0,1,(gabaaconduct))
	nclist3.append(nctemp3)
	
	d[iiii] = new GABABtry(0.5)
	nctemp4 = new NetCon(nil,d[iiii],0,1,(gababconduct))
	nclist4.append(nctemp4)

}

proc loadspikes() { local jj
for jj=0,numinputs-1 {
	numss = rsp[jj].size()
	for ii=0,numss-1 {
		nclist1.o(jj).event((rsp[jj].x[ii] + delay))
		nclist2.o(jj).event((rsp[jj].x[ii] + delay))
}}

for jj=0,numinputsI-1 {
	numsI = rspI[jj].size()
	for ii=0,numsI-1 {
		nclist3.o(jj).event((rspI[jj].x[ii] + delay))
		nclist4.o(jj).event((rspI[jj].x[ii] + delay))
		printf("dont worry\n")
}}}

fih = new FInitializeHandler("loadspikes()")

This works great if I only have a single input event. However, if I try to input a train of spikes (or anything more than 1 spike), the resulting GABAb current "breaks" (screenshot shown below)

Image
(this is a single neuron with GABAb receptors attached receiving two synaptic events at 200 and 300 ms)

Any suggestions as to why this occurs?
ted
Site Admin
Posts: 5810
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Adding GABAb

Post by ted »

You might try simply attaching one instance of the GABAB mechanism to a single compartment passive model, and driving it with one or more events. Or better yet, start with by doing this with an ExpSyn, then trying it with a GABAB mechanism. That will tell you whether the problem lies in the GABAB mechanism or elsewhere. This is the first diagnostic step.

Rather than stuffing multiple event times into the queue with NetCon's event() method, it would be a better idea to use the VecStim class--see the example in
nrn/share/nrn/examples/nrniv/netcon/vecevent.mod
(c:/nrnxx/examples/nrniv/netcon/vecevent.mod if you're using MSWin).

A few comments about programming style:

1. Organizing code into short procedures makes code easier to develop/debug/maintain/understand by eliminating needless repetition. Example--

Code: Select all

objref ni
strdef file3
ni = new File()
file3 = "numinputs.dat"
ni.ropen(file3)
numinputs = ni.scanvar()
ni.close()
etc.
could be replaced by

Code: Select all

// reads and returns a single numerical value from a file
// $s1 filename
func getval() { local tmp  localobj tfil
  tfil = new File()
  tfil.ropen($s1)
  tmp = tfil.scanvar()
  tfil.close()
  return tmp
}

numinputs = getval("numinputs.dat")
numinputsI = getval("numinputsI.dat")
 . . .
ampatau = getval("ampatau.dat")
gabatau = getval("gabatau.dat")
Likewise it would be easy to write an objfunc that reads a vector from a file.

2. There's no need to use unique names for every last throwaway variable in a program, e.g. the index variables iii and iiii. Pick one name and use it again and again.
Cal

Re: Adding GABAb

Post by Cal »

ted wrote:You might try simply attaching one instance of the GABAB mechanism to a single compartment passive model, and driving it with one or more events. Or better yet, start with by doing this with an ExpSyn, then trying it with a GABAB mechanism. That will tell you whether the problem lies in the GABAB mechanism or elsewhere. This is the first diagnostic step.
I've used AMPA and NMDA mechanisms with my existing model, so I'm fairly confident that the problem lies within my use of NetCon with the GABAb .mod file.
ted wrote: Rather than stuffing multiple event times into the queue with NetCon's event() method, it would be a better idea to use the VecStim class--see the example in
nrn/share/nrn/examples/nrniv/netcon/vecevent.mod
(c:/nrnxx/examples/nrniv/netcon/vecevent.mod if you're using MSWin).
Had I but only known about this a couple years ago... Is there any documentation on the usage of VecStim? I suppose I'd do something similar to the following

Code: Select all

objref test, nettest
test = new VecStim
nettest = new NetCon(test, "target", ... )
Is it as simple as passing a vector of event times as an input arg to VecStim?

ted wrote: A few comments about programming style:

1. Organizing code into short procedures makes code easier to develop/debug/maintain/understand by eliminating needless repetition. Example--

Code: Select all

objref ni
strdef file3
ni = new File()
file3 = "numinputs.dat"
ni.ropen(file3)
numinputs = ni.scanvar()
ni.close()
etc.
could be replaced by

Code: Select all

// reads and returns a single numerical value from a file
// $s1 filename
func getval() { local tmp  localobj tfil
  tfil = new File()
  tfil.ropen($s1)
  tmp = tfil.scanvar()
  tfil.close()
  return tmp
}

numinputs = getval("numinputs.dat")
numinputsI = getval("numinputsI.dat")
 . . .
ampatau = getval("ampatau.dat")
gabatau = getval("gabatau.dat")
Likewise it would be easy to write an objfunc that reads a vector from a file.

2. There's no need to use unique names for every last throwaway variable in a program, e.g. the index variables iii and iiii. Pick one name and use it again and again.
I've been putting off cleaning up my code for some time now; I suppose now is a good time to start. Thanks for the suggestions.
Cal

Re: Adding GABAb

Post by Cal »

For additional reference, this is the GABAb mechanism I'm attempting to use:

Code: Select all

INDEPENDENT {t FROM 0 TO 1 WITH 1 (ms)}

NEURON {
	POINT_PROCESS GABABtry
	RANGE R, G, g
	NONSPECIFIC_CURRENT i
	GLOBAL Cmax, Cdur
	GLOBAL K1, K2, K3, K4, KD, Erev
}
UNITS {
	(nA) = (nanoamp)
	(mV) = (millivolt)
	(umho) = (micromho)
	(mM) = (milli/liter)
}

PARAMETER {

	Cmax	= 0.5	(mM)		: max transmitter concentration
	Cdur	= 0.3	(ms)		: transmitter duration (rising phase)
:
:	From Kfit with long pulse (5ms 0.5mM)
:
	K1	= 0.52	(/ms mM)	: forward binding rate to receptor
	K2	= 0.0013 (/ms)		: backward (unbinding) rate of receptor
	K3	= 0.098 (/ms)		: rate of G-protein production
	K4	= 0.033 (/ms)		: rate of G-protein decay
	KD	= 100			: dissociation constant of K+ channel
	n	= 4			: nb of binding sites of G-protein on K+
	Erev	= -85	(mV)		: reversal potential (E_K)
}


ASSIGNED {
	v		(mV)		: postsynaptic voltage
	i 		(nA)		: current = g*(v - Erev)
	g 		(umho)		: conductance
	Gn
	R				: fraction of activated receptor
	edc
	synon
	Rinf
	Rtau (ms)
	Beta (/ms)
}


STATE {
	Ron Roff
	G				: fraction of activated G-protein
}


INITIAL {
	R = 0
	G = 0
	synon = 0
	Rinf = K1*Cmax/(K1*Cmax + K2)
	Rtau = 1/(K1*Cmax + K2)
	Beta = K2
}

BREAKPOINT {
	SOLVE bindkin METHOD cnexp
	Gn = G*G*G*G : ^n = 4
	g = Gn / (Gn+KD)
	i = g*(v - Erev)
}


DERIVATIVE bindkin {
	Ron' = synon*K1*Cmax - (K1*Cmax + K2)*Ron
	Roff' = -K2*Roff
	R = Ron + Roff
	G' = K3 * R - K4 * G
}

: following supports both saturation from single input and
: summation from multiple inputs
: Note: automatic initialization of all reference args to 0 except first

NET_RECEIVE(weight,  r0, t0 (ms)) {
	if (flag == 1) { : at end of Cdur pulse so turn off
		r0 = weight*(Rinf + (r0 - Rinf)*exp(-(t - t0)/Rtau))
		t0 = t
		synon = synon - weight
		state_discontinuity(Ron, Ron - r0)
		state_discontinuity(Roff, Roff + r0)
       }else{ : at beginning of Cdur pulse so turn on
		r0 = weight*r0*exp(-Beta*(t - t0))
		t0 = t
		synon = synon + weight
		state_discontinuity(Ron, Ron + r0)
		state_discontinuity(Roff, Roff - r0)
		:come again in Cdur
		net_send(Cdur, 1)
        }
}
My guess is that there's conflicts in my use of NetCon (code in 1st post) and the Net_Receive here.
ted
Site Admin
Posts: 5810
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Adding GABAb

Post by ted »

Cal wrote:I've used AMPA and NMDA mechanisms with my existing model, so I'm fairly confident that the problem lies within my use of NetCon with the GABAb .mod file.
Which is why I suggested stepping back from the complex to the more simple. The recipe that causes problems is "multiple events" plus "complex model cell" plus "gabab synaptic mechanism. The task is first to localize the cause of the problem. Start with something simple and add one complexity at a time. ExpSyn on a passive single compartment is about as simple as it gets. If you can drive one of those with multiple events, then try driving {your gabaergic synaptic mechanism attached to a single passive compartment} with multiple events--won't take long. If that works, then try driving {your gabaergic synaptic mechanism attached to your complex model} with multiple events.
Is there any documentation on the usage of VecStim?
The documentation is the sample code that accompanies it in
nrn/share/nrn/examples/nrniv/netcon/vecevent*
(c:/nrnxx/examples/nrniv/netcon/vecevent* if you're using MSWin).
Cal

Re: Adding GABAb

Post by Cal »

So after simplification and debugging, I decided to redownload the GABAb .mod file. Everything now works as it should. From what I can tell, I couldn't find any differences in code between the first .mod file and the second .mod file. (Huh? What?) Oh well. Thanks for the coding suggestions and the VecStim class!

EDIT: Ok, so scratch that, I figured out what I what I was doing wrong.

Code: Select all

	c[i] = new GABABDiagnostic(0.5)
	c[i]_Erev = -85
        nctemp1 = new NetCon(vs[i],c[i],0,1,1.5)
Basically, making the last argument value of

Code: Select all

"NetCon(vs[i],c[i],0,1,1.5)"
large (the weight value, if I'm correct) really drives everything down to Erev really, really quick. This is probably amplified by the multiple input events as well.
Post Reply