Team:Groningen/Modelling/Arsenic.js

From 2009.igem.org

(Difference between revisions)
m
(Worked MBPArsR and fMT (and KostalArsR) into non-equilibrium model.)
Line 7: Line 7:
     ars1T: 1.6605e-9,
     ars1T: 1.6605e-9,
     ars2T: 16.605e-9,
     ars2T: 16.605e-9,
-
     pro: 16.605e-9,
+
     pro: 16.605e-9, // TODO: rename to proR
-
     proM: 0,
+
    proK: 0, // Promoters in front of ArsR fusion from Kostal2004 (handled completely analogously to MBPArsR)
 +
     proM: 0, // Promoters in front of our ArsR fusion (with MBP)
 +
    proF: 0, // Promoters in front of fMT
     // Reaction constants
     // Reaction constants
     k8: 0, // export (unknown)
     k8: 0, // export (unknown)
     K1d: 6e-6, // ArsR-As
     K1d: 6e-6, // ArsR-As
 +
    KKd: 6e-6, // ArsR-As (ArsR fusion from Kostal2004)
 +
    KMd: 6e-6, // MBPArsR-As
 +
    KFd: 6e-6, // fMT-As
 +
    nf: 3, // Hill coefficient for fMT + As
     K3d2: Math.pow(0.33e-6,2), // ArsR-ars
     K3d2: Math.pow(0.33e-6,2), // ArsR-ars
     v5: 3.1863e-6, // import
     v5: 3.1863e-6, // import
Line 19: Line 25:
     tauR: 60,  // half-life of ArsR
     tauR: 60,  // half-life of ArsR
     tauG: 60,  // half-life of GV
     tauG: 60,  // half-life of GV
 +
    tauK: 120, // half-life of ArsR fusion of Kostal2004
     tauM: 120, // half-life of MBP-ArsR
     tauM: 120, // half-life of MBP-ArsR
-
     beta1: 1000, // production rate of ArsR behind ars1
+
    tauF: 120, // half-life of fMT
 +
     beta1: 1000, // production rate of ArsR behind ars1 // TODO: Rename them all!
     beta3: 1000, // production rate of ArsR behind pro
     beta3: 1000, // production rate of ArsR behind pro
     beta4: 1000, // production rate of ArsB behind ars1
     beta4: 1000, // production rate of ArsB behind ars1
     beta5: 1000, // production rate of GV behind ars2
     beta5: 1000, // production rate of GV behind ars2
 +
    betaK: 500,  // production rate of ArsR fusion of Kostal2004 behind proK
     betaM: 500,  // production rate of MBP-ArsR behind proM
     betaM: 500,  // production rate of MBP-ArsR behind proM
 +
    betaF: 500,  // production rate of fMT behind proF
     // Volumes
     // Volumes
     Vs: 1.1e-3,
     Vs: 1.1e-3,
Line 44: Line 54:
// Computes gradient of the variables in the arsenic model
// Computes gradient of the variables in the arsenic model
function arsenicModelGradient(c,x) {
function arsenicModelGradient(c,x) {
-
   // Asin = x.AsinT*c.K1d/(c.K1d+ArsR)
+
   // Solve 0 = As(III)in (1 + ArsRT/(KRd + As(III)in) + MBPArsRT/(KMd + As(III)in)
-
  // Asin = x.AsinT/(1+ArsR/c.K1d)
+
   //           + fMTT As(III)in^(nf-1)/(KFdnf + As(III)in^nf)
-
   // Asin = x.AsinT/(1+x.ArsRT/(c.K1d+Asin))
+
   var fAsin = function(Asin) {
-
   // Asin = x.AsinT*(c.K1d+Asin)/(c.K1d+Asin+x.ArsRT)
+
                var Asinnf = Math.pow(Asin,c.nf);
-
  // (c.K1d+Asin+x.ArsRT)*Asin = x.AsinT*(c.K1d+Asin)
+
                return Asin*(1 + x.ArsRT/(c.KRd + Asin) + x.MBPArsRT/(c.KMd + Asin) + x.KostalArsRT/(c.KKd + Asin))
-
  // c.K1d*Asin+Asin*Asin+x.ArsRT*Asin = x.AsinT*(c.K1d+Asin)
+
                        + x.fMTT*Asinnf/(Math.pow(c.KFd,c.nf)+Asinnf) - x.AsinT;
-
  // Asin*Asin + (c.K1d + x.ArsRT - x.AsinT)*Asin - x.AsinT*c.K1d = 0;
+
              };
-
   var bAsin = c.K1d + x.ArsRT - x.AsinT;
+
  var Asinlow = 0, Asinhigh = x.AsinT;
-
   var cAsin = x.AsinT*c.K1d;
+
  var Asin = findSingleZero(fAsin,Asinlow,Asinhigh);
-
   var Asin = (-bAsin + Math.sqrt(Math.pow(bAsin,2)+4*cAsin))/2;
+
 
-
   var ArsR = Math.max(0,x.ArsRT+Asin-x.AsinT);
+
   var ArsR = x.ArsRT*c.K1d/(c.K1d+Asin);
 +
   var KostalArsR = x.KostalArsRT*c.KKd/(c.KKd+Asin);
 +
   var MBPArsR = x.MBPArsRT*c.KMd/(c.KMd+Asin);
 +
   var fMT = x.fMTT*c.KFd/(c.KFd+Asin);
   var ArsB = x.ArsBT*c.K7/(c.K7+Asin);
   var ArsB = x.ArsBT*c.K7/(c.K7+Asin);
   var ArsBAs = x.ArsBT*Asin/(c.K7+Asin);
   var ArsBAs = x.ArsBT*Asin/(c.K7+Asin);
Line 69: Line 82:
     AsinT: dAsinTdt,
     AsinT: dAsinTdt,
     ArsRT: dArsRT,
     ArsRT: dArsRT,
 +
    KostalArsRT: c.betaK*c.proK - (Math.LN2/c.tauK)*KostalArsR,
 +
    MBPArsRT: c.betaM*c.proM - (Math.LN2/c.tauM)*MBPArsR,
 +
    fMTT: c.betaF*c.proF - (Math.LN2/c.tauF)*fMT,
     GV: c.beta5*ars2 - (Math.LN2/c.tauG)*x.GV
     GV: c.beta5*ars2 - (Math.LN2/c.tauG)*x.GV
   };
   };
Line 76: Line 92:
function arsenicModelEquilibrium(c,AsT) {
function arsenicModelEquilibrium(c,AsT) {
   if (c.AsT!=undefined && AsT==undefined) AsT = c.AsT;
   if (c.AsT!=undefined && AsT==undefined) AsT = c.AsT;
 +
   // Solve 0 = (β1 ars1T + β3 pro) (τR/ln(2)) K3d² - K3d² ArsR + β3 (τR/ln(2)) pro ArsR² - ArsR³
   // Solve 0 = (β1 ars1T + β3 pro) (τR/ln(2)) K3d² - K3d² ArsR + β3 (τR/ln(2)) pro ArsR² - ArsR³
   var fArsR = function(ArsR) { return (c.beta1*c.ars1T + c.beta3*c.pro)*(c.tauR/Math.LN2)*c.K3d2 - c.K3d2*ArsR + c.beta3*(c.tauR/Math.LN2)*c.pro*Math.pow(ArsR,2) - Math.pow(ArsR,3); }
   var fArsR = function(ArsR) { return (c.beta1*c.ars1T + c.beta3*c.pro)*(c.tauR/Math.LN2)*c.K3d2 - c.K3d2*ArsR + c.beta3*(c.tauR/Math.LN2)*c.pro*Math.pow(ArsR,2) - Math.pow(ArsR,3); }
Line 101: Line 118:
     'AsinT': AsinT,
     'AsinT': AsinT,
     'ArsRT': ArsR*(1.0+Asin/c.K1d),
     'ArsRT': ArsR*(1.0+Asin/c.K1d),
 +
    'KostalArsRT': ArsR*(1.0+Asin/c.K1d),
 +
    'MBPArsRT': 0,
 +
    'fMTT': 0,
     'GV': GV
     'GV': GV
   };
   };

Revision as of 14:23, 6 October 2009

arsenicModelMaxIter = 1000; function arsenicModelConstants() { // Prevents other scripts from overriding them.

 return {
   // Extra-cellular
   GlpFTfactor: 1, // relative amount of GlpF
   // Intra-cellular
   ars1T: 1.6605e-9,
   ars2T: 16.605e-9,
   pro: 16.605e-9, // TODO: rename to proR
   proK: 0, // Promoters in front of ArsR fusion from Kostal2004 (handled completely analogously to MBPArsR)
   proM: 0, // Promoters in front of our ArsR fusion (with MBP)
   proF: 0, // Promoters in front of fMT
   // Reaction constants
   k8: 0, // export (unknown)
   K1d: 6e-6, // ArsR-As
   KKd: 6e-6, // ArsR-As (ArsR fusion from Kostal2004)
   KMd: 6e-6, // MBPArsR-As
   KFd: 6e-6, // fMT-As
   nf: 3, // Hill coefficient for fMT + As
   K3d2: Math.pow(0.33e-6,2), // ArsR-ars
   v5: 3.1863e-6, // import
   K5: 27.718e-6, // import
   K7: 1, // export (unknown)
   tauB: 60,  // half-life of ArsB
   tauR: 60,  // half-life of ArsR
   tauG: 60,  // half-life of GV
   tauK: 120, // half-life of ArsR fusion of Kostal2004
   tauM: 120, // half-life of MBP-ArsR
   tauF: 120, // half-life of fMT
   beta1: 1000, // production rate of ArsR behind ars1 // TODO: Rename them all!
   beta3: 1000, // production rate of ArsR behind pro
   beta4: 1000, // production rate of ArsB behind ars1
   beta5: 1000, // production rate of GV behind ars2
   betaK: 500,  // production rate of ArsR fusion of Kostal2004 behind proK
   betaM: 500,  // production rate of MBP-ArsR behind proM
   betaF: 500,  // production rate of fMT behind proF
   // Volumes
   Vs: 1.1e-3,
   Vc: 0.0073e-3,
 };

}

// Returns an array with all the necessary variables initialized as if a solution with cells in equilibrium suddenly gets a shot of arsenic function arsenicModelInitialization(c,AsT) {

 if (c.AsT!=undefined && AsT==undefined) AsT = c.AsT;
 // First determine equilibrium without arsenic
 var x = arsenicModelEquilibrium(c,0);
 // Return equilibrium with added arsenic
 x.AsexT = AsT/c.Vs;
 return x;

}

// Computes gradient of the variables in the arsenic model function arsenicModelGradient(c,x) {

 // Solve 0 = As(III)in (1 + ArsRT/(KRd + As(III)in) + MBPArsRT/(KMd + As(III)in)
 //            + fMTT As(III)in^(nf-1)/(KFdnf + As(III)in^nf)
 var fAsin = function(Asin) {
               var Asinnf = Math.pow(Asin,c.nf);
               return Asin*(1 + x.ArsRT/(c.KRd + Asin) + x.MBPArsRT/(c.KMd + Asin) + x.KostalArsRT/(c.KKd + Asin))
                       + x.fMTT*Asinnf/(Math.pow(c.KFd,c.nf)+Asinnf) - x.AsinT;
             };
 var Asinlow = 0, Asinhigh = x.AsinT;
 var Asin = findSingleZero(fAsin,Asinlow,Asinhigh);
 var ArsR = x.ArsRT*c.K1d/(c.K1d+Asin);
 var KostalArsR = x.KostalArsRT*c.KKd/(c.KKd+Asin);
 var MBPArsR = x.MBPArsRT*c.KMd/(c.KMd+Asin);
 var fMT = x.fMTT*c.KFd/(c.KFd+Asin);
 var ArsB = x.ArsBT*c.K7/(c.K7+Asin);
 var ArsBAs = x.ArsBT*Asin/(c.K7+Asin);
 var arsFraction = c.K3d2/(c.K3d2+Math.pow(ArsR,2));
 var ars1 = c.ars1T*arsFraction;
 var ars2 = c.ars2T*arsFraction;
 var dAsinTdt = c.v5*x.AsexT / (c.K5+x.AsexT) - c.k8*ArsBAs;
 var dArsRT = c.beta1*ars1 + c.beta3*c.pro - (Math.LN2/c.tauR)*ArsR;
 return {
   // Extra-cellular
   AsexT: -(c.Vc/c.Vs)*dAsinTdt,
   // Intra-cellular
   ArsBT: c.beta4*ars1 - (Math.LN2/c.tauB)*ArsB,
   AsinT: dAsinTdt,
   ArsRT: dArsRT,
   KostalArsRT: c.betaK*c.proK - (Math.LN2/c.tauK)*KostalArsR,
   MBPArsRT: c.betaM*c.proM - (Math.LN2/c.tauM)*MBPArsR,
   fMTT: c.betaF*c.proF - (Math.LN2/c.tauF)*fMT,
   GV: c.beta5*ars2 - (Math.LN2/c.tauG)*x.GV
 };

}

// Computes the equilibrium from constants function arsenicModelEquilibrium(c,AsT) {

 if (c.AsT!=undefined && AsT==undefined) AsT = c.AsT;
 // Solve 0 = (β1 ars1T + β3 pro) (τR/ln(2)) K3d² - K3d² ArsR + β3 (τR/ln(2)) pro ArsR² - ArsR³
 var fArsR = function(ArsR) { return (c.beta1*c.ars1T + c.beta3*c.pro)*(c.tauR/Math.LN2)*c.K3d2 - c.K3d2*ArsR + c.beta3*(c.tauR/Math.LN2)*c.pro*Math.pow(ArsR,2) - Math.pow(ArsR,3); }
 var ArsRlow = 0, ArsRhigh = (c.beta1*c.ars1T + c.beta3*c.pro)*(c.tauR/Math.LN2);
 var ArsR = findSingleZero(fArsR,ArsRlow,ArsRhigh);
 // Compute ArsB and GV
 var arsFraction = c.K3d2/(c.K3d2+Math.pow(ArsR,2));
 var ArsB = c.beta4*(c.tauB/Math.LN2)*c.ars1T*arsFraction;
 var GV = c.beta5*(c.tauB/Math.LN2)*c.ars2T*arsFraction;
 // Determine intra-cellular concentration of As(III)
 var aAs = c.k8*ArsB*c.Vc;
 var bAs = c.v5*c.Vc*c.K7*(1+ArsR/c.K1d) + c.k8*ArsB*(c.Vs*c.K5 + AsT);
 var cAs = c.v5*c.K7*(1+ArsR/c.K1d)*AsT;
 var AsinT = 2*cAs/(bAs + Math.sqrt(Math.pow(bAs,2) - 4*aAs*cAs));
 if (isNaN(AsinT)) AsinT = 0;
 var Asin = AsinT*c.K1d/(c.K1d+ArsR);
 return {
   // Extra-cellular
   'AsexT': (AsT-c.Vc*AsinT)/c.Vs,
   // Intra-cellular
   'ArsBT': ArsB*(1.0+Asin/c.K7),
   'AsinT': AsinT,
   'ArsRT': ArsR*(1.0+Asin/c.K1d),
   'KostalArsRT': ArsR*(1.0+Asin/c.K1d),
   'MBPArsRT': 0,
   'fMTT': 0,
   'GV': GV
 };

}

// Assuming there is exactly one zero of f(x) for x in [low,high] this function will find it function findSingleZero(f,low,high,tol) {

 if (tol===undefined) tol = 1e-6;
 var ylow = f(low);
 var yhigh = f(high);
 var x = (low+high)/2.0, y;
 for(var iter=1;
     iter<=arsenicModelMaxIter && (high-low)/x>tol;
     iter++)
 {
   y = f(x);
   if (y*ylow>0) { // Checking if y and ylow have the same sign
     low = x;
     ylow = y;
   } else {
     high = x;
     yhigh = y;
   }
   x = high - yhigh*(high-low)/(yhigh-ylow); // Secant method (roughly)
   x = Math.min(Math.max(x,low+0.1*(high-low)),low+0.9*(high-low)); // Ensures convergence
 }
 return x;

}