Page 1 of 1

Using Pointers with Distributed Mechanisms

Posted: Tue Jul 11, 2006 1:57 pm
by Amelia
Hi There,

I am trying to use the setpointer (hoc syntax) with the POINTER (mod syntax) to set a variable used in a distributed Mechanism (Schannel) from value of v elsewhere in the model.

The mod file is:

Code: Select all

TITLE stretch gated Na+ membrane channel

UNITS {
	(mV) = (millivolt)
	(mA) = (milliamp)
	(S) = (siemens)
}

NEURON {
	SUFFIX Schannel
	USEION na READ ena WRITE ina
	POINTER mus
	RANGE g, e, stretch
}

PARAMETER {
	g = .00002	(S/cm2)	<0,1e19>
	e = 50	(mV)
}

ASSIGNED {
	v (mV)  
	i (mA/cm2)
	gna (S/cm2)
	ina (mA/cm2)
	ena (mV)
	stretch
	mus (mV)
}

BREAKPOINT {
	if (mus>0){
		stretch = (mus+35)*10
	}
	gna = g*(1/(1+exp((50-stretch)/10)))
	ina = gna*(v - ena)
}
The relevant (I think) hoc statments are:

Code: Select all

DB10posterior2{
diam = 0.3
	L = 90
	insert pas1
	insert Schannel
	nseg = 51
	DB10.append()
	setpointer mus.Schannel, VB11posterior1.v(0.5) 
}
VB11posterior1{
	diam = 0.3
	L = 90
	insert pas1
	nseg = 101
	VB11.append()
}
When I run the hoc, I get a syntax error on the line "setpointer mus.Schannel, VB11posterior1.v(0.5) "

I think that the problem is caused because the syntax is for use with a point process not a distributed mechanism. However, I am not sure what I need to change to get it to work.

Any help greatly appreciated

Amelia

Posted: Tue Jul 11, 2006 6:24 pm
by Raj
In topic
http://www.neuron.yale.edu/phpBB2/viewtopic.php?p=952&
your problem is addressed.

It gives a reference to a MOdelDB entry:
http://senselab.med.yale.edu/senselab/m ... odel=39949
where you can find what I think solves your problem in the file C_Cell.hoc.

Translated to your situation:

Code: Select all

if (issection("Schannel")) {
      for (x,0) { // skip the nodes at 0 and 1
	     setpointer mus_Schannel(x), VB11posterior1.v(0.5) 
      }
}
seems to be what is needed.

Where the if part is only necessary if you don't know whether your section contains Schannel.

Posted: Tue Jul 11, 2006 7:00 pm
by ted
I think that the problem is caused because the syntax is for use with a point process not a distributed mechanism.
If Schannel were a class of point process, the proper syntax would not involve
mus.Schannel at all--you would use an objref (say, schan) to refer to an instance of
the Schannel class, and the syntax would be of the form

Code: Select all

setpointer schan.mus, pre.v(0.5)
But Schannel is a distributed mechanism, so the syntax is of the form

Code: Select all

setpointer post.mus_Schannel(0.5), pre.v(0.5)
One might well ask why Schannel is NOT a point process, and why, with such modest
dimensions, nseg for your two sections is so large. Ra and/or cm would have to be
enormous to require such a fine spatial grid (with Ra = 500 ohm cm and cm = 10 uf/cm2,
nseg == 43 should be sufficient). Or maybe you're concerned with extremely short times,
or the complete model specification includes longitudinal diffusion, e.g. of calcium?

Since you are using such a large value for nseg in the section with Schannel--and also
because nseg is different in the "pre" and "post" sections--have you verified that a
single setpointer statement guarantees the proper value of mus over the entire "post"
section?

Not knowing anything particular about your ultimate purposes, here are some further
observations and suggestions:

1. e is declared but not used.

2. The conditional in the BREAKPOINT block

Code: Select all

   if (mus>0){
      stretch = (mus+35)*10
   }
doesn't assign any value to stretch if mus<=0. This is asking for trouble.

3. Debugging and testing will be easier if your NMODL code is easily testable from hoc.
Instead of burying all complexities in the BREAKPOINT block, split them out into
FUNCTIONs which can be called from hoc. That is, instead of making stretch an
ASSIGNED, make it a FUNCTION. Likewise, rather than compute compute gna
directly from stretch with a bunch of code inside the BREAKPOINT block, split that
out into another FUNCTION.

Code: Select all

BREAKPOINT {
   gna = g*fstretch(stretch(mus))
   ina = gna*(v - ena)
}

FUNCTION stretch(m (mV)) (1) {
  if (m>0) {
    stretch = (m+35)*10/(1(mV))
  } else {
    stretch = 0
  }
}

FUNCTION fstretch(stx (1)) (1) {
   fstretch = 1/(1+exp((50-stx)/10))
}
Then you can plot stretch_Schannel(v) vs. v, fstretch_Schannel(x) vs. x (here x is
used as a generic independent variable, not range),
and fstretch_Schannel(stretch_Schannel(v)) vs. v. The results may be informative.

Posted: Tue Jul 11, 2006 7:12 pm
by ted
I almost forgot--
you might also want to make gna a RANGE variable so you can observe its time course
during a simulation.

Posted: Wed Jul 12, 2006 6:00 am
by Amelia
Hi thanks for the quick reply.

Unfortunately, I am now getting a Segmentation violation when I run the simulation.

I am wondering if perhaps I am approaching the problem completely incorrectly.

This line:

setpointer DB10posterior2.mus_Schannel(0.5), VB11posterior1.v(0.5)

Specifically the (0.5) in the post variable, suggests that this is not what I should be using. I would like the variable “musâ€

Posted: Wed Jul 12, 2006 6:39 am
by Raj
The for (x) {} construction is exactly ment to set the variable for every segment in your section. Although starting to set it for one point is a good way to do incremental programming.

Segmentation faults can have many causes, and sometimes require a bit of debugging skill to find. Commenting in and out chunks off code can reveal where the problem is hiding, and the best advice I can give on debugging: never trust yourself.

As far as I can see your approach should be able to work out just fine, so at first sight no need to change strategy. I don't know how large your model is, but you might want to develop and test your new mechanism in a very limited setting with just two sections. One containing your new mechanism and one just for generating a membrane potential that you can pass to your mechanism using a pointer. That way you do away with the possibly complicated surrounding code and you can focus on your mechanism first.

Posted: Wed Jul 12, 2006 7:55 am
by Amelia
Thank you both for your help

It is working now

Thanks again,
Amelia

Posted: Wed Jul 12, 2006 12:02 pm
by ted
Raj wrote:you might want to develop and test your new mechanism in a very limited setting with just two sections. One containing your new mechanism and one just for generating a membrane potential that you can pass to your mechanism using a pointer. That way you do away with the possibly complicated surrounding code and you can focus on your mechanism first.
Raj is absolutely right. Always test unfamiliar syntax in the context of small "toy"
programs. Trying to debug big, complex programs is one of the most common
"beginner's mistakes" (another is failing to read the documentation).
Amelia wrote:I am wondering if perhaps I am approaching the problem completely incorrectly.

This line:

setpointer DB10posterior2.mus_Schannel(0.5), VB11posterior1.v(0.5)

Specifically the (0.5) in the post variable, suggests that this is not what I should be using. I would like the variable “musâ€

Setting up distributed mechanism pointers in a forsec loop

Posted: Tue Oct 24, 2006 2:42 pm
by carl
I am trying to setup pointers for a distributed mechanism in a loop, rather than by name as in the previous examples. Let me briefly explain the motivation, as otherwise you may think me crazy: Naundorf et al. (Nature, 2006) show that features of AP initiation in cortical neurons are best matched by a "cooperative" model of Na+ activation, where the opening of Na+ channels reduces the V_1/2 for the activation curve. In their model they only use a single compartment. It is not too hard to implement their model in NEURON if you assume that the range of cooperativity is only the present compartment. In NMODL you get something like this:

Code: Select all

STATE {
   o
}
PROCEDURE rates(v) {
        alpha_a = alpha(v+K*o, vhalf_a, k_a, tau_a)
        beta_a  =  beta(v+K*o, vhalf_a, k_a, tau_a)
        ....
}
So as you can see, the voltage passed into the alpha function is shifted by the opening of the channels. Thats nice, but it is logical that cooperativity of the Na+ channel may extend to neighboring compartments in average sense. Then the mechanism starts to look like so:

Code: Select all

NEURON {
   ...
   POINTER oparent
   POINTER ochild1
   ...
}

PROCEDURE rates(v) {
        alpha_a = alpha(v+K*J*(o + oparent + ochild1)*0.333, vhalf_a, k_a, tau_a)
        beta_a  =  beta(v+K*J*(o + oparent + ochild1)*0.333, vhalf_a, k_a, tau_a)
        ....
}
So to calculate the cooperative shift in the activation curve we would like to include the open state for the parent and child compartments. Thats the background for why I want to do what I want to do.

---------------------------------------------------------------------------------------------

Unfortunately, setting all those pointers may be a pain The code examples I have seen for setting pointers in distributed mechanisms all refer to sections by name and I want this code to run on a variety of morphologies where the naming of sections will vary.

I think I would like to do something like loop over a list of sections and use section refs in my set pointer statements

Code: Select all

objref curr_o, parent_o, child_o
forsec o_sections {
	
	curr_o = new SectionRef()		
	curr_o.parent {parent_o = new SectionRef()}

	x = 1/(nseg+1)
	y = parent_o.sec.nseg/(parent_o.sec.nseg+1)
        setpointer curr_o.sec.oparent_nacx(x), parent_o.sec.o_nacx(y)

	for (i=2; i <n; i=i+1) {
	    x = i/(nseg+1)
	    y = (i-1)/(nseg+1)
	    setpointer curr_o.sec.oparent_nacx(x), curr_o.sec.o_nacx(y)
	    y = (i+1)/(nseg+1)
	    setpointer cur_o.sec.ochild1_nacx(x), curr_o.sec.o_nacx(y)
      }
      .... (something similar for the child)
}
But when I execute this I get

/usr/local/bin/nrniv: not a point process pointer in src/main.hoc near line 57

So it looks like setpointer is not happy with SectionRef's - what is the proper way to setup this kind of distributed mechanism?

I have already envisioned a hacky way to do it as follows: I can construct strings using secname() to determine the name of my section, and then execute() to run it. Something like:

Code: Select all

strdef astring
sprint(astring,"setpointer %s.oparent_nacx(%f), %s.o_nacx(%f)", curr_secname, x, parent_secname,y)
execute(astring)
But that sure is pretty hacky - whats the right way to do it?

POINTER arrays - problems

Posted: Thu Oct 26, 2006 11:53 am
by carl
Okay, so I initialized my pointers using the hacky sprint/execute method that I mentioned and it works great. Now would I would like to do is extend the code to a case where my compartment has more than just a parent and a child but some arbitrary number of neighbors. For example, 2 children as at a branch point, or conceivably up to a dozen or so children for the soma of a large pyramidal cell.

Naturally I want to use an array of POINTER's in my mod file, but I can't seem to get the NMODL code right, and there is no example of this kind of use. Here is what I am trying:

Code: Select all

NEURON {
   SUFFIX nacx
   USEION na READ ena WRITE ina

   POINTER oneighbors
   RANGE   nneighbors
   
   RANGE gbar
   RANGE alpha_a, beta_a, alpha_ci, beta_ci
   ...
}

DEFINE MAX_NEIGHBORS 32

ASSIGNED {
   ...
   oneighbors[MAX_NEIGHBORS]
   nneighbors
   ...
}


PROCEDURE rates(v) {
   LOCAL o_avg
   o_avg = o

   FROM i=0 TO nneighbors-1 {
       o_avg = o_avg +  oneighbors[i]
   }
   o_avg = o_avg / (nneighbors+1)

   alpha_a = alpha(v+K*J*o_avg, vhalf_a, k_a, tau_a)
   beta_a  =  beta(v+K*J*o_avg, vhalf_a, k_a, tau_a)
   ...
}
And when I do nrnivmodl I get this error:


nacx.c: In function `rates':
nacx.c:248: error: invalid type argument of `unary *'
make: *** [nacx.lo] Error 1


Telling me the line number for the c file nacx.c is not very helpfule, but I have determined that if I comment out the line:

Code: Select all

       o_avg = o_avg +  oneighbors[i]
then the error goes away so that is the source of the error - it seems to be confused by the use of my pointer array.

What is the correct way to do this?

Posted: Thu Oct 26, 2006 4:20 pm
by hines

Code: Select all

setpointer curr_o.sec.oparent_nacx(x), parent_o.sec.o_nacx(y)
That's my mistake. I have to update the parser to handle object references for setpointer arguments.
............

Code: Select all

alpha_a = alpha(v+K*J*(o...
I worry when states appear in the rate functions for those states since that can be a source of numerical instability. The requirements for METHOD cnexp do not hold and you are likely to have better luck with
METHOD derivimplicit for the fixed step method.
...............
Given the lack of POINTER arrays in NMODL the best way to proceed is with
VERBATIM and making a list of pointers along with a function that adds up the values in them. At the hoc level, the elementary
operation would be

Code: Select all

section { setdata_nacx(x) // so that procedures you call know the correct range variables at x.
     add_pointer_nacx(&some_variable) // this one needs to be implemented
}
nrn/src/nrnoc/pattern.mod can be mined for some idioms that are useful in safely maintaining arbitrary c structure data when there are many mechanism instances. If you need help with this I can prepare a mod file that has allthe scaffolding you would need.

Posted: Thu Oct 26, 2006 8:16 pm
by carl
I worry when states appear in the rate functions for those states since that can be a source of numerical instability. The requirements for METHOD cnexp do not hold and you are likely to have better luck with
METHOD derivimplicit for the fixed step method.
What about using CVode, which I normally do? I found the reference for this on pages 225-226 of the book, but it doesn't say anything about if the state appears on the right side under CVode. Thanks for your help!

Posted: Thu Oct 26, 2006 8:22 pm
by carl
ah, I think I got it it says on page 226 that under CVode it adaptively chooses the numerical integration formula, so it doesn't matter what I say in the mod file. Right?

Posted: Fri Oct 27, 2006 10:28 am
by hines
Correct.