Conductance as a function of nseg distance from soma

NMODL and the Channel Builder.
Post Reply
Dathadorne

Conductance as a function of nseg distance from soma

Post by Dathadorne »

Hello,
I'm a somewhat new NEURON user, and I'm interested in building a channel that I can place in the dendrites, where the gbar would be dependent on the distance from the soma.

I've moved gbar into the states block of the .mod file, and created a procedure to calculate gbar, however i'm not sure what 'x' variable to give the equation to calculate the g for each segment, dependent on the distance the segment is from the soma.

If anyone could help point me in the right direction, it would be quite helpful. Thanks!
ted
Site Admin
Posts: 6300
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Conductance as a function of nseg distance from soma

Post by ted »

Dathadorne wrote:I'm interested in building a channel that I can place in the dendrites, where the gbar would be dependent on the distance from the soma.
. . .
I've moved gbar into the states block of the .mod file
Don't do that. It's not a state, it's a parameter. It should be declared in the PARAMETER block, and it should also appear in a RANGE statement in the NEURON block. That makes it a "range variable" i.e. something that can have different values at different locations in space. If you examine mod file definitions of voltage-gated currents, you will find that almost all of them specify that their conductance density parameters are range variables.
created a procedure to calculate gbar, however i'm not sure what 'x' variable to give the equation to calculate the g for each segment, dependent on the distance the segment is from the soma.
Stepping back from the problem for a moment to gain perspective, the task can be described in these terms:
There is a set s of sections in which parameter g is to be governed by function f of distance metric p.

s is a SectionList to which you append the sections of interest after the basic model has been set up, i.e. after all sections have been created, connected, and density mechanisms have been inserted.

Then define funcs p and f.

p returns the distance metric for the present node of the currently accessed section. Examples of distance metrics include:
--radial distance from a point
--(orthogonal) distance from a surface (e.g. height above or below a cell body layer, or depth from the cortical surface)
--path distance from a point (i.e. distance traversed from a point in the soma along intervening branches)

f expects an argument whose value is a distance, and returns the corresponding value of g. It can be anything that makes sense for your particular model.

The assignment of values to g is accomplished by creating a setparam() proc that does this (in pseudocode):

Code: Select all

for each member of s
  for each internal node of this section
    assign f(p) to g at this node
In hoc, this is just

Code: Select all

proc setparam() {
  forsec s {
    for (x,0) { // skip the zero area nodes at 0 and 1--see footnote below
      g_foo(x) = f(p())
  }
}
If it is ever necessary to change nseg of any section, or to make any change to the topology or geometry of the model, setparam() should be called again.

The CellBuilder does all this very nicely, and allows a lot of customization of the distance metric and the function f--see
Specifying parameterized variation of biophysical properties.
in the CellBuilder tutorial
http://www.neuron.yale.edu/neuron/stati ... /main.html

Footnote--
Note that the iterator for (x,0) omits the zero area nodes, i.e. the nodes at 0 and 1. This saves a (very) little bit of time during model setup. More important, however, is the fact that it avoids assigning an incorrect value to the range parameter in the segment that contains the 1 end. Why? Recall that rangevar(x) accesses the value of rangevar at the nearest internal node. for (x) starts at the 0 end and iterates over all nodes, right up to the 1 end. When it gets to the last internal node, the x value is < 1, and g_foo for the last segment will get the corresponding value. But the iterator makes one more pass with x = 1, and this time g_foo in the last segment will be overwritten with a value that may be too large or too small (depending on whether f is increasing or decreasing along the length of the segment). This is a very common error--it crops up in many published models, including quite a few that have been heavily reused.
Dathadorne

Re: Conductance as a function of nseg distance from soma

Post by Dathadorne »

Wow, what a thorough response, thank you! I'll be sure to give this a shot, and get back to you on my implementation.
Dathadorne

Re: Conductance as a function of nseg distance from soma

Post by Dathadorne »

Hi, Ted, I first want to thank you for your response, especially since explaining code to beginners can be a task.

There are a few things I'm not sure about. Having only coded in scheme, things aren't intuitive for me yet. I've placed the section list in the .hoc after the connect statements:

objectref s

s = new SectionList()
dend[0] s.append()
dend[1] s.append()

Am I right that 'defining a function' means to create a procedure? If so, should p and f be defined in the .hoc, or the .mod of the channel? I'm working with someone else's code, so unfortunately I don't have the option to start fresh with the CellBuilder.

My largest issue is that I'm not sure how to go about defining "p," the distance of a dendritic segment from the soma. This is something that needs to change with the segment that conductance is being calculated for. Of the options you offered, I think that "path distance from a point" would be from the center of the segment to the beginning of the dendrite (position 0), which would have a maximum of (L.dend-(half of segment length)).

I don't know how what types of inputs I have available to do this calculation; is there a way that the nth segment could know which number it is (20 segments per dendrite), and then just use algebra to figure out "p" each iteration?

Thank you so much for your time!
ted
Site Admin
Posts: 6300
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Conductance as a function of nseg distance from soma

Post by ted »

Dathadorne wrote:Having only coded in scheme, things aren't intuitive for me yet.
I had to quit scheme--all those parentheses ran together and made me dizzy. Eventually an ophthalmologist told me it was just astigmatism.

Code: Select all

objectref s

s = new SectionList()
	dend[0] s.append()
	dend[1] s.append()
Yep. You can then verify the contents of s by
forsec s print secname()
Am I right that 'defining a function' means to create a procedure?
Just another way of saying the same thing.
If so, should p and f be defined in the .hoc, or the .mod of the channel?
hoc. Think of NMODL as a tool for adding new keywords to NEURON, and hoc as the language that is used to create model cells and nets.
I'm working with someone else's code, so unfortunately I don't have the option to start fresh with the CellBuilder.
Right. I often build extra info into my replies, in anticipation that someone else will read it in the future.
My largest issue is that I'm not sure how to go about defining "p," the distance of a dendritic segment from the soma.
hoc has a built in function called distance that returns path distance from a reference point. Read about it in the Programmer's Reference.
http://www.neuron.yale.edu/neuron/stati ... l#distance

Suppose the root section of a cell is called soma.

Code: Select all

proc alldist() {
  soma distance() // make soma(0) be the reference point for distance measurements
  forall {
    print secname()
    for (x,0) print x, " ", distance(x)
  }
}
will iterate over all sections, reporting the name of the section and the distances of all internal nodes from soma(0) in microns.
Dathadorne

Re: Conductance as a function of nseg distance from soma

Post by Dathadorne »

Hello, Ted. Within the .hoc, after sections are created, my code stands as:

Code: Select all

     	connect dend[0](0), soma(0) 
     	connect dend[1](0), soma(1) 
	connect axon(0), soma(.5)  //  4.5/20 nseg(45um)      
}  
 //Create section for channel reference
objectref s
s = new SectionList()
	dend[0] s.append()
	dend[1] s.append()
forsec s print secname()

 //define distance from somatic membrane
proc alldist() {
  soma distance() // make soma(0) be the reference point for distance measurements
  forall {
    print secname()
    for (x,0) print x, " ", distance(x)
  }
}  
 //calculate gkbar
proc setparam() {
  forsec s{
    for (x, 0) {
      gkbar(x) = 17*(0.6*exp(-x/74))+0.05
  }
}
   endtemplate Cell
Here are my thoughts:
1) dend[0] is connected to soma[1], so the distance calculation from somatic edge will be off by 1, correct? In the model I'm using, gkbar drops off from distance to the somatic edge. My soma.L = 40, so I suppose I should set "proc alldist { soma distance()" to "soma distance(0.5)," and then alter the equation to subtract 40/2 from x: gkbar(x) = 17*(0.6*exp(-(x-20)/74))+0.05

I'm used to having lots of defined terms in my equations. May I replace (x-20) with (x-0.5*soma.L) so that any changes in the soma length are automatically reflected?

2) In the channel .mod, gkbar is defined as a constant in the PARAMETERs. It is also mentioned in the RANGE. Will this override the .hoc calculation of gkbar and if so, I assume gkbar should be deleted from PARAMETERs and moved to ASSIGNED?

3) To check that the dendritic conductance falls off as segment number increases, is there a print command that would allow me to check each segment individually, maybe something like "print dend[0] seg3 gkbar" ?

Once again, thank you so much!
ted
Site Admin
Posts: 6300
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Conductance as a function of nseg distance from soma

Post by ted »

My answers are often guided by the principle "better to teach how to fish than to give a fish." That was the point of including proc alldist() in my previous message. Don't just stick it, verbatim, into your own code. It's not a mystical incantation that must be recited word for word. It's an illustration of how to use distance().

Second, I see that your cell definition appears to use a template. Are you going to be working with model networks or models of individual cells? Templates are useful for network models, but that utility comes at the cost of introducing a host of programming complications that are best avoided during initial development and debugging of the individual cell classes. It is generally advisable to defer wrapping any particular cell model inside a template until the last instant, after it has been debugged and is ready to be incorporated into a network model.

Case in point:

Code: Select all

//Create section for channel reference
objectref s
s = new SectionList()
	dend[0] s.append()
	dend[1] s.append()
forsec s print secname()
This bit of code, stuck inside a template but not contained in a proc or func, will do nothing useful because it will be executed only when the template is parsed by hoc. It will never be executed again. It must be inside a proc or func, and that proc or func must be called each time a new instance of the class defined by the template is created. See what I mean about "complications that are best avoided"?

Code: Select all

dend[0] is connected to soma[1], so the distance calculation from somatic edge will be off by 1, correct?
Off by 1 what? Don't confuse soma[1] with location 1 on the soma. soma[1] is the name of a section; square brackets are used for indices, as when one declares multiple sections
create soma[2]
or multiple objrefs
objref foo[2]
Location 1 on the soma, on the other hand, is the "distal" end of the soma.

What is the "somatic edge", from the perspective of dend[0]? "The point at which dend[0] is attached to soma"?
In the model I'm using, gkbar drops off from distance to the somatic edge.
If that is the case for all sections other than soma, and if no sections are attached to the 0 or 0.5 location on the soma, you could just define the 1 end of soma as the origin for distance measurements
soma distance(0,1)
Then there is no need to subtract anything from any value returned by distance()

In proc setparam() don't forget that gkbar belongs to a density mechanism so you need to include that mechanism's suffix, e.g. for the hh mechanism the complete hoc name would be gkbar_hh.
In the channel .mod, gkbar is defined as a constant in the PARAMETERs. It is also mentioned in the RANGE. Will this override the .hoc calculation of gkbar
No, but you should check for yourself.
I assume gkbar should be deleted from PARAMETERs and moved to ASSIGNED?
Declaring a variable name in the PARAMETER block will make it appear in GUI tools such as the CellBuilder alongside widgets that make it easy for users to change its value. It will not appear in these tools if it is declared in the ASSIGNED block. By default, PARAMETERs are "global" i.e. have the same value in all segments of all sections in which the mechanism has been inserted. Declaring it as RANGE in the NEURON block means that it is allowed to have different values at all internal nodes of all sections, i.e. it is a "range variable". ASSIGNED variables are range variables by default.
To check that the dendritic conductance falls off as segment number increases, is there a print command that would allow me to check each segment individually, maybe something like "print dend[0] seg3 gkbar" ?
Starting from the example of proc alldist(), you could create a new proc that iterates over all internal nodes of all sections, printing each section name, the distance of the node from the reference point, and the value of your potassium conductance density. I'd suggest calling the new proc something like report(). The print statement would look something like this
for (x,0) print x, " ", distance(x), " ", gkbar_suffix(x)
where suffix should be replaced by your mechanism's SUFFIX.

Another suggestion: use the ModelView tool (see link to tutorial at http://www.neuron.yale.edu/neuron/docs).
Post Reply