Recording *current through a channel (mechanism)

Anything that doesn't fit elsewhere.
Post Reply
bschneiders
Posts: 9
Joined: Thu Feb 02, 2017 11:30 am

Recording *current through a channel (mechanism)

Post by bschneiders » Thu Sep 14, 2017 11:41 am

Is there a way to record the charge* of an ion that flows through a channel defined as a mechanism? I am trying to record the calcium current that enters a spinehead through a calcium channel. I am doing the same for an NMDA channel, which is simple enough since it is a point process:

Code: Select all

ica_nmda = neuron.h.Vector()
ica_nmda.record(synnmda._ref_ica)
However, I haven't yet found the way to do that for this calcium channel (though the mod file for it obviously does write ica). Any suggestions?
Thanks!

*edited
Last edited by bschneiders on Mon Sep 25, 2017 12:09 pm, edited 4 times in total.

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

Re: Recording concentration through a channel (mechanism)

Post by ted » Thu Sep 14, 2017 1:22 pm

Concentration doesn't flow. Charge flows, mass flows, but not concentration.

If you're having difficulty recording a particular variable that an NMODL-specified mechanism "should" be calculating, it might be because the NMODL code doesn't expose that variable to hoc or Python. Your examples indicate that you want to record the calcium current produced by particular ion channels. This is possible as long as the NMODL code for your ion channels declares the current to be RANGE.

Here's an example of a mechanism that generates a particular ionic current in such a way that you can't get at it if there are any other mechanisms that produce a current carried by the same ionic species:

Code: Select all

NEURON {
  SUFFIX kleak
  USEION k READ ek WRITE ik
}
PARAMETER {
  g = 0.001 (siemens/cm2)
  ek = -65 (millivolt)
}
ASSIGNED {
  ik (milliamp/cm2)
  v (millivolt)
}
BREAKPOINT {
  ik = g*(v - ek)
}
The ik produced by this mechanism is added to the total transmembrane potassium current, but there will be no hoc or Python variable that tells you how much potassium current is attributable to this particular channel. That's a real problem if the segment contains other mechanisms that also WRITE ik.

The fix is to tell NMODL that there needs to be such a variable. The obscure way, sure to confuse yourself and others, is to simply declare ik as a RANGE variable in the NEURON block like this:

Code: Select all

NEURON {
  SUFFIX kleak
  USEION k READ ek WRITE ik
  RANGE ik
}
This takes advantage of a side-effect of the RANGE statement. Compile the mod file and presto! there is now an ik_kleak variable that tells how much current this particular mechanism generates. What makes this confusing is that a month from now, someone will ask "Why did you declare ik to be a RANGE variable? Isn't ik automatically a RANGE variable? [editor's note: it is] And doesn't USEION x WRITE ix tell NMODL that ix should be a RANGE variable? [editor's note: it does]" When that happens, you're probably not going to remember that you deliberately included the
RANGE ik
statement because of its side-effect. Just another example of why it's not a good idea to write code that relies on side-effects.

Instead, it's safer to use statements that are quite explicit about what's going on. The way to do this is declare a new variable i in the NEURON block

Code: Select all

NEURON {
  SUFFIX kleak
  USEION k READ ek WRITE ik
  RANGE i
}
specify its units in the ASSIGNED block

Code: Select all

ASSIGNED {
  ik (milliamp/cm2)
  i (milliamp/cm2)
  v (millivolt)
}
and calculate its value in the BREAKPOINT block

Code: Select all

BREAKPOINT {
  i = g*(v - ek)
  ik = i
}
Now there will be an i_kleak variable that hoc and Python can access.

These examples are density mechanisms, so the currents they report are in mA/cm2. To convert this to absolute current, you have to multiply by the surface area of the segment to which the current belongs. Note that NEURON has an area() function that returns the area of a segment in um2 (multiply by 1e-8 to convert to cm2 -- see https://www.neuron.yale.edu/neuron/stat ... .html#area

By the way, https://www.neuron.yale.edu/neuron/stat ... f-sections contains a lot of information that might be good to review from time to time.

bschneiders
Posts: 9
Joined: Thu Feb 02, 2017 11:30 am

Re: Recording *current through a channel (mechanism)

Post by bschneiders » Thu Sep 14, 2017 5:00 pm

Ted, thank you for your quick reply. I did mean current (from which I'm ultimately calculating concentration, hence my slip up).

This is very helpful - I will try the (safer) second method you mentioned. And thanks for the reference at the end as well.
Last edited by bschneiders on Tue Sep 19, 2017 4:43 pm, edited 3 times in total.

bschneiders
Posts: 9
Joined: Thu Feb 02, 2017 11:30 am

Re: Recording *current through a channel (mechanism)

Post by bschneiders » Sun Sep 17, 2017 6:23 pm

I have a follow up question. I can access the current at a given time now without a problem with:

Code: Select all

ica_car = spinehead.i_car
However, I am still having trouble with the recording part. I suspect this is because the variable I reference is already specific to a section? But I am not sure. I am trying to set up the recording similarly to the one I have in the original post for the NMDA channel so that I have access to the calcium current through the R-type calcium channel ("car") for every point in time of the simulation. I have been trying variations of the code below, which is clearly not right:

Code: Select all

var1 = spinehead.i_car
icacar = neuron.h.Vector()
icacar.record(spinehead._ref_var1)
Any suggestions? Thanks!

bschneiders
Posts: 9
Joined: Thu Feb 02, 2017 11:30 am

Re: Recording *current through a channel (mechanism)

Post by bschneiders » Mon Sep 25, 2017 1:53 pm

For anyone with similar questions - the issue was that I wasn't specifying the location along the section (as you would when referencing, say, the voltage). The following code does the job:

Code: Select all

icacar = neuron.h.Vector()
icacar.record(spinehead(.5)._ref_i_car)

Post Reply