Two calcium buffers

NMODL and the Channel Builder.
Post Reply
tcp

Two calcium buffers

Post by tcp »

Dear Ted,

I am using the cdp.mod file for buffering, diffusion and pump of calcium. I want to include a more specific calcium buffer as the calbindin calcium buffer. Shall I implement a second buffer mechanism that will coexist with cdp.mod? Shall I modify cdp.mod in a way that will represent the calbindin buffer?

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

Re: Two calcium buffers

Post by ted »

Buffering is a process that is involved in ion accumulation, so if you are already using cdp and need to add another buffer, modify cdp so that it includes the new buffer's reactions. Use the existing code as a pattern for the additions that are necessary to represent the new buffer. If you are merely "switching from one buffer to another" and no new reactions are necessary, just change the total buffer parameter, its rate constants, and its diffusion constant--which you should be able to do from hoc via simple assignment statements.
tcp

Re: Two calcium buffers

Post by tcp »

Dear Ted,
Would you care if you could have a look in the modified cdp.mod file I made?

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

Re: Two calcium buffers

Post by ted »

It would be most compact if you posted just the changes right here on the Forum, along with a few clues to context for lines that have been revised and lines that have been inserted. A partial example:

Code: Select all

NEURON {
  GLOBAL TotalBuffer2
 . . .
KINETIC state {
:  COMPARTMENT i, diam*diam*vrat[i] {ca CaBuffer Buffer}
  COMPARTMENT i, diam*diam*vrat[i] {ca CaBuffer Buffer CaBuffer2 Buffer2}
 . . .
tcp

Re: Two calcium buffers

Post by tcp »

Dear Ted,
Below you may find my effort to make a cdp.mod file with two buffers. For many points I have uncertainties especially the point whether I should introduce a cd specific totalpump or not.

Any suggestion or help will be greatly appreciated.
Thanks a lot,
Eleftheria

Code: Select all

: Calcium ion accumulation with radial and longitudinal diffusion and pump

NEURON {
...
  GLOBAL vrat, TotalBuffer, TotalPump,TotalBuffer_cb, TotalPump_cb   : I added  TotalBuffer_cb and TotalPump_cb, however I am not sure if it is necessary to introduce a TotalPump_cb
}

UNITS {
  (mol)   = (1)
  (molar) = (1/liter)
  (mM)    = (millimolar)
  (um)    = (micron)
  (mA)    = (milliamp)
  FARADAY = (faraday)  (10000 coulomb)
  PI      = (pi)       (1)
}

DEFINE Nannuli 4


PARAMETER {
  DCa   = .6 (um2/ms)
  DCa_cb   = 0.05 (um2/ms)   :Different constant for Calbindin (cb) buffer
  k1buf = 110 (/mM-ms) : Yamada et al. 1989
  k1buf_cb = 20 (/mM-ms) : for Calbindin
  k2buf = 0.1 (/ms)
  k2buf_cb = 0.004 (/ms)  :for calbindin
  TotalBuffer = .003 (mM) :.09  (mM)
  TotalBuffer_cb= .001 (mM) : just a random value,

  k1    = 1   (/mM-ms)  : I keep these cinsatnts the same for cb buffer
  k2    = 0.005   (/ms)
  k3    = 1       (/ms)
  k4    = 0.005   (/mM-ms)
  : to eliminate pump, set TotalPump to 0 in hoc
  TotalPump = 0.95e-11  (mol/cm2)
:  TotalPump_cb= 0.95e-11  (mol/cm2)   :No cb Totalpump added (?)
}

ASSIGNED {
  diam      (um)
  ica       (mA/cm2)
  ica_pmp   (mA/cm2)
  ica_pmp_last   (mA/cm2)  : I haven't understood whether I should implicate or not a second  cb specific pump or not 
  parea     (um)     : pump area per unit length
  cai       (mM)
  cao       (mM)
  vrat[Nannuli]  (1) : dimensionless
                     : numeric value of vrat[i] equals the volume 
                     : of annulus i of a 1um diameter cylinder
                     : multiply by diam^2 to get volume per um length
  Kd        (/mM)
  B0        (mM)
  Kd_cb        (/mM)   :new Kd and B0 for cb buffer
  B0_cb        (mM)
}

CONSTANT { volo = 1e10 (um2) }

STATE {
  : ca[0] is equivalent to cai
  : ca[] are very small, so specify absolute tolerance
  : let it be ~1.5 - 2 orders of magnitude smaller than baseline level
  ca[Nannuli]       (mM) <1e-7>
  CaBuffer[Nannuli] (mM) <1e-5>
  Buffer[Nannuli]   (mM) <1e-5>
  CaBuffer_cb[Nannuli] (mM) <1e-7>   : different shells for the cb buffer, could I use the same? 
  Buffer_cb[Nannuli] (mM) <1e-7>
  pump              (mol/cm2) <1e-15>  : shall I introduce a new cb pump?
  pumpca            (mol/cm2) <1e-15>
}

BREAKPOINT {
  SOLVE state METHOD sparse
  ica_pmp_last = ica_pmp
  ica = ica_pmp
}

LOCAL factors_done

INITIAL {
   if (factors_done == 0) {  : flag becomes 1 in the first segment
      factors_done = 1       :   all subsequent segments will have
      factors()              :   vrat = 0 unless vrat is GLOBAL
   }

  Kd = k1buf/k2buf
  B0 = TotalBuffer/(1 + Kd*cai)

  Kd_cb = k1buf_cb/k2buf_cb
  B0_cb = TotalBuffer_cb/(1 + Kd_cb*cai)
  

  FROM i=0 TO Nannuli-1 {
    ca[i] = cai
    Buffer[i] = B0
    Buffer_cb[i]=B0_cb
    CaBuffer[i] = TotalBuffer - B0
    CaBuffer_cb[i]=TotalBuffer_cb-B0_cb
  }

  parea = PI*diam

: Manually computed initalization of pump
: assumes that cai has been equal to cai0_ca_ion for a long time
:  pump = TotalPump/(1 + (cai*k1/k2))
:  pumpca = TotalPump - pump
: If possible, instead of using formulas to calculate pump and pumpca,
: let NEURON figure them out--just uncomment the following four statements
  ica=0
  ica_pmp = 0
  ica_pmp_last = 0
  SOLVE state STEADYSTATE sparse
: This requires that pump and pumpca be constrained by the CONSERVE
: statement in the STATE block.
: If there is a voltage-gated calcium current, 
: this is almost certainly the wrong initialization. 
: In such a case, first do an initialization run, then use SaveState
: On subsequent runs, restore the initial condition from the saved states.
}

LOCAL frat[Nannuli]  : scales the rate constants for model geometry
PROCEDURE factors() {
  LOCAL r, dr2
  r = 1/2                : starts at edge (half diam)
  dr2 = r/(Nannuli-1)/2  : full thickness of outermost annulus,
                         : half thickness of all other annuli
  vrat[0] = 0
  frat[0] = 2*r
  FROM i=0 TO Nannuli-2 {
    vrat[i] = vrat[i] + PI*(r-dr2/2)*2*dr2  : interior half
    r = r - dr2
    frat[i+1] = 2*PI*r/(2*dr2)  : outer radius of annulus
                                : div by distance between centers
    r = r - dr2
    vrat[i+1] = PI*(r+dr2/2)*2*dr2  : outer half of annulus
  }
}

LOCAL dsq, dsqvol  : can't define local variable in KINETIC block
                   :   or use in COMPARTMENT statement

KINETIC state {
  COMPARTMENT i, diam*diam*vrat[i] {ca CaBuffer CaBuffer_cb Buffer Buffer_cb}
  COMPARTMENT (1e10)*parea {pump pumpca}   
  COMPARTMENT volo {cao}
  LONGITUDINAL_DIFFUSION i, DCa*diam*diam*vrat[i] {ca}
  LONGITUDINAL_DIFFUSION i, DCa_cb*diam*diam*vrat[i] {ca}   :on the top of the standard diffusion constant I add the diffusion constant for cb, is this right?

  :pump
  ~ ca[0] + pump <-> pumpca  (k1*parea*(1e10), k2*parea*(1e10))
  ~ pumpca <-> pump + cao    (k3*parea*(1e10), k4*parea*(1e10))
  CONSERVE pump + pumpca = TotalPump * parea * (1e10)
  ica_pmp = 2*FARADAY*(f_flux - b_flux)/parea

  : all currents except pump
  : ica is Ca efflux
  ~ ca[0] << (-(ica - ica_pmp_last)*PI*diam/(2*FARADAY))
  FROM i=0 TO Nannuli-2 {
    ~ ca[i] <-> ca[i+1]  (DCa*frat[i+1], DCa*frat[i+1])
    ~ ca[i] <-> ca[i+1]  (DCa_cb*frat[i+1], DCa*frat[i+1])  :plus dissociation constant for cb
  }
  dsq = diam*diam
  FROM i=0 TO Nannuli-1 {
    dsqvol = dsq*vrat[i]
    ~ ca[i] + Buffer[i] <-> CaBuffer[i]  (k1buf*dsqvol, k2buf*dsqvol)
    ~ ca[i] + Buffer_cb[i]<->CaBuffer_cb[i] (k1buf_cb*dsqvol, k2buf*dsqvol)  : buffering reaction for cb
  }
  cai = ca[0]
}

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

Re: Two calcium buffers

Post by ted »

Good questions. They raise many important points.
tcp wrote:For many points I have uncertainties especially the point whether I should introduce a cd specific totalpump or not.
Before one writes any code, it is essential to have a clear conceptual model. The conceptual model provides the rational basis for the code that is to be written.

The conceptual model of ca accumulation that served as the basis for the original cdp.mod includes a membrane-bound transport mechanism (a "pump"), and a single buffer. The geometry of diffusion exploits radial symmetry by representing the intracellular space as a set of concentric compartments; mobile species can move radially or longitudinally between adjacent compartments, but not circumferentially. The only mobile species is free ca. The equations that describe it are specified by reactions that are written in the KINETIC block. Omitting rate constants and scale factors related to surface/volume ratios for the sake of clarity, here are the reactions.

Code: Select all

  ~ ca[0] << (-(ica - ica_pmp_last)*PI*diam/(2*FARADAY))
specifies the contribution of calcium fluxes through the membrane (except for the flux generated by the pump itself) to the ca in the compartment just beneath the cell membrane.

Code: Select all

  FROM i=0 TO Nannuli-2 {
    ~ ca[i] <-> ca[i+1]
  }
specifies radial diffusion, and the LONGITUDINAL_DIFFUSION statement near the top of the KINETIC block instructs NMODL that ca may move between adjacent compartments along the length of a section, and may cross between adjacent segments of connected sections.

Code: Select all

  ~ ca[0] + pump <-> pumpca
  ~ pumpca <-> pump + cao
specifies the pump mechanism.

Code: Select all

  FROM i=0 TO Nannuli-1 {
    ~ ca[i] + Buffer[i] <-> CaBuffer[i]
  }
specifies buffering of ca by the single buffer.

To add a second _immobile_ buffer it is only necessary to add another reaction that specifies how this new buffer binds ca. And that gives you a new conceptual model.

If the new buffer is to be _mobile_, then you need to include a new set of reactions that specify the exchange of free and ca-bound buffer between adjacent compartments. So the equations for radial diffusion are now

Code: Select all

  FROM i=0 TO Nannuli-2 {
    ~ ca[i] <-> ca[i+1]
    ~ Buffer_cb[i] <-> Buffer_cb[i+1]
    ~ CaBuffer_cb[i] <-> CaBuffer_cb[i+1]
  }
and there will also have to be new LONGITUDINAL_DIFFUSION statements for Buffer_cb and CaBuffer_cb.

Implementation of the new conceptual model with NMODL is quite straightforward. It's just the old NMODL code plus a few additional statements. First among these new statements, of course, are the new buffering reactions, which introduce new STATEs that must be declared (the concentrations of free and bound buffer in each compartment). And, of course, the new diffusion reactions.

But there are also many other details. If there was a CONSERVE statement for the original buffer, it's probably a good idea to do the same thing for the new buffer. Also, the new buffer has its own rate constants, its own "total amount", its own diffusion constant(s) (at least 1 if it is mobile, and definitely 2 if there is a difference between the mobilities of free and bound buffer) etc.. All of these things must be specified by new parameters, assigned variables, etc..
I am not sure if it is necessary to introduce a TotalPump_cb
What do you think? Does the pump interact directly with the new buffer or not?

Code: Select all

  CaBuffer_cb[Nannuli] (mM) <1e-7>   : different shells for the cb buffer, could I use the same?
The new conceptual model is the same as the conceptual model for the original cdp.mod, with one exception: each compartment contains two buffering species. So if there are Nannuli compartments, there must be that same number of variables to hold the corresponding values of Buffer_cb, and another set of variables to hold the values of CaBuffer_cb.

"How many compartments should there be for the new buffer?" Don't even think of trying to use different numbers of compartments for the different mobile species. Choose a spatial grid that is fine enough to take care of the species with the highest mobility, and use that for all of them.

Code: Select all

  COMPARTMENT i, diam*diam*vrat[i] {ca CaBuffer CaBuffer_cb Buffer Buffer_cb}
Good.

Code: Select all

  LONGITUDINAL_DIFFUSION i, DCa_cb*diam*diam*vrat[i] {ca}
Not quite. You want to say

Code: Select all

  LONGITUDINAL_DIFFUSION i, DBuffer_cb*diam*diam*vrat[i] {Buffer_cb Ca_Buffer_cb}
assuming of course that Buffer_cb and CaBuffer_cb have the same mobility. If they have different mobilities, you'll need separate diffusion constants and LONGITUDINAL_DIFFUSION statements for the bound and free buffer.

Code: Select all

    ~ ca[i] <-> ca[i+1]  (DCa_cb*frat[i+1], DCa*frat[i+1])
This is incorrect. The mobility of free ca is DCa. It is not affected by the presence of buffer. There is only one equation that describes the movement of free ca and it has nothing to do with any buffers at all. If ca is going to hitch a ride on a mobile buffer in compartment 1, and diffuse into adjacent compartment 2 where it then dissocates from the mobile buffer, it is the CaBuffer_cb combination that moves, not ca. The whole process involves the following steps:
ca[1] + Buffer_cb[1] -> CaBuffer_cb[1]
CaBuffer_cb[1] -> CaBuffer_cb[2]
CaBuffer_cb[2] -> ca[2] + Buffer_cb[2]
These steps are embedded in the set of reactions I outlined above. They are _NOT_ equivalent to
ca[1] -> ca[2] (DCa_cb*frat[2])

Code: Select all

  FROM i=0 TO Nannuli-1 {
    dsqvol = dsq*vrat[i]
    ~ ca[i] + Buffer[i] <-> CaBuffer[i]  (k1buf*dsqvol, k2buf*dsqvol)
    ~ ca[i] + Buffer_cb[i]<->CaBuffer_cb[i] (k1buf_cb*dsqvol, k2buf*dsqvol)  : buffering reaction for cb
  }
Yes.


Be sure to check your new mod file with modlunit.
Post Reply