diff options
Diffstat (limited to 'CakeModel.R')
| -rw-r--r-- | CakeModel.R | 287 | 
1 files changed, 101 insertions, 186 deletions
diff --git a/CakeModel.R b/CakeModel.R index ce6bc01..3a32779 100644 --- a/CakeModel.R +++ b/CakeModel.R @@ -1,15 +1,13 @@  # Was Id: mkinmod.R 71 2010-09-12 01:13:36Z jranke  -# $Id$ -# The CAKE R modules are based on mkin +# Some of the CAKE R modules are based on mkin  # Portions Johannes Ranke, 2010  # Contact: mkin-devel@lists.berlios.de -# This version has been modified to parameterise SFO as k and flow fractions -# Modifications developed by Tessella Plc for Syngenta: Copyright (C) 2011  Syngenta -# Tessella Project Reference: 6245 +# Modifications developed by Tessella for Syngenta: Copyright (C) 2011-2016 Syngenta +# Tessella Project Reference: 6245, 7247, 8361, 7414 -#    This program is free software: you can redistribute it and/or modify +#    The CAKE R modules are free software: you can redistribute it and/or modify  #    it under the terms of the GNU General Public License as published by  #    the Free Software Foundation, either version 3 of the License, or  #    (at your option) any later version. @@ -20,98 +18,80 @@  #    GNU General Public License for more details.  #   #    You should have received a copy of the GNU General Public License -#    along with this program.  If not, see <http://www.gnu.org/licenses/>.” +#    along with this program.  If not, see <http://www.gnu.org/licenses/>.  CakeModel <- function(..., use_of_ff = "max")  {    spec <- list(...)    obs_vars <- names(spec) -  if (!use_of_ff %in% c("min", "max")) -    stop("The use of formation fractions 'use_of_ff' can only be 'min' or 'max'") +  if (!use_of_ff %in% c("min", "max")) stop("The use of formation fractions 'use_of_ff' can only be 'min' or 'max'") +      # differential equations, parameter names and a mapping from model variables    # to observed variables. If possible, a matrix representation of the     # differential equations is included    parms <- vector()    diffs <- vector()    map <- list() -  if(spec[[1]]$type %in% c("FOMC", "DFOP", "HS")) { -    mat = FALSE  -    if(!is.null(spec[[1]]$to)) { -      message <- paste("Only constant formation fractions over time are implemented.", -        "Depending on the reason for the time dependence of degradation, this may be unrealistic", -        sep="\n") -      warning(message) -    } else message <- "ok" -  } else mat = TRUE -   -  mat = FALSE # XYZZY Not implemented yet assuming it should be    nlt = list()    # Establish list of differential equations    for (varname in obs_vars)    { -    if(is.null(spec[[varname]]$type)) stop( -      "Every argument to mkinmod must be a list containing a type component") -    if(!spec[[varname]]$type %in% c("SFO", "FOMC", "DFOP", "HS", "SFORB")) stop( -      "Available types are SFO, FOMC, DFOP, HS and SFORB only") +    if(is.null(spec[[varname]]$type)) stop("Every argument to CakeModel must be a list containing a type component") +    if(!spec[[varname]]$type %in% c("SFO", "FOMC", "DFOP", "HS", "IORE")) stop("Available types are SFO, FOMC, DFOP, HS and IORE only") +          new_parms <- vector()      # New (sub)compartments (boxes) needed for the model type -    new_boxes <- switch(spec[[varname]]$type, -      SFO = varname, -      FOMC = varname, -      DFOP = varname, -      HS = varname, -      SFORB = paste(varname, c("free", "bound"), sep="_") -    ) +    if (spec[[varname]]$type == "DFOP" && varname != "Parent"){ +      # If this is a DFOP metabolite, we need to form a system of two differential equations +      # (see FOCUS page 137) +      new_boxes <- paste(varname, c("1", "2"), sep="_") +    } else{ +      new_boxes <- varname +    } +          map[[varname]] <- new_boxes      names(map[[varname]]) <- rep(spec[[varname]]$type, length(new_boxes))      # Start a new differential equation for each new box      new_diffs <- paste("d_", new_boxes, " =", sep="") -    # Get the name of the box(es) we are working on for the decline term(s) -    box_1 = map[[varname]][[1]] # This is the only box unless type is SFORB -          # Turn on sink if not specified otherwise      if(is.null(spec[[varname]]$sink)) spec[[varname]]$sink <- TRUE -    #@@@ADD SFO k HERE !!!!!!!!!!!!!      # Construct and add SFO term and add SFO parameters if needed      if(spec[[varname]]$type == "SFO") {        if (use_of_ff == "min") { # Minimum use of formation fractions          if(spec[[varname]]$sink) { -      # From p. 53 of the FOCUS kinetics report -      k_term <- paste("k", new_boxes[[1]], "sink", sep="_") -      nonlinear_term <- paste(k_term, new_boxes[[1]], sep=" * ") -      spec[[varname]]$nlt<-nonlinear_term -      new_diffs[[1]] <- paste(new_diffs[[1]], "-", nonlinear_term) -      new_parms <- k_term -      ff <- vector() -      decline_term <- paste(nonlinear_term, "*", new_boxes[[1]]) -    } else { # otherwise no decline term needed here -      decline_term = "0"  -    } -  } else { -      k_term <- paste("k", new_boxes[[1]], sep="_") -      nonlinear_term <- paste(k_term, new_boxes[[1]], sep=" * ") -      spec[[varname]]$nlt<-nonlinear_term -      new_diffs[[1]] <- paste(new_diffs[[1]], "-", nonlinear_term) -      new_parms <- k_term -      ff <- vector() -    decline_term <- paste(nonlinear_term, "*", new_boxes[[1]]) -  } - }  +          # From p. 53 of the FOCUS kinetics report +          k_term <- paste("k", new_boxes[[1]], "sink", sep="_") +          nonlinear_term <- paste(k_term, new_boxes[[1]], sep=" * ") +          spec[[varname]]$nlt<-nonlinear_term +          new_diffs[[1]] <- paste(new_diffs[[1]], "-", nonlinear_term) +          new_parms <- k_term +          ff <- vector() +          decline_term <- paste(nonlinear_term, "*", new_boxes[[1]]) +        } else { # otherwise no decline term needed here +          decline_term = "0"  +        } +      } else { +        k_term <- paste("k", new_boxes[[1]], sep="_") +        nonlinear_term <- paste(k_term, new_boxes[[1]], sep=" * ") +        spec[[varname]]$nlt<-nonlinear_term +        new_diffs[[1]] <- paste(new_diffs[[1]], "-", nonlinear_term) +        new_parms <- k_term +        ff <- vector() +        decline_term <- paste(nonlinear_term, "*", new_boxes[[1]]) +      } +    }       # Construct and add FOMC term and add FOMC parameters if needed      if(spec[[varname]]$type == "FOMC") {        if(match(varname, obs_vars) != 1) {          stop("Type FOMC is only possible for the first compartment, which is assumed to be the source compartment")        } -#      if(spec[[varname]]$sink == FALSE) { -#        stop("Turning off the sink for the FOMC model is not implemented") -#      }        # From p. 53 of the FOCUS kinetics report        nonlinear_term <- paste("(alpha/beta) * ((time/beta) + 1)^-1 *", new_boxes[[1]])        spec[[varname]]$nlt<-nonlinear_term @@ -122,18 +102,31 @@ CakeModel <- function(..., use_of_ff = "max")      # Construct and add DFOP term and add DFOP parameters if needed      if(spec[[varname]]$type == "DFOP") { -      if(match(varname, obs_vars) != 1) { -        stop("Type DFOP is only possible for the first compartment, which is assumed to be the source compartment") -      } -#      if(spec[[varname]]$sink == FALSE) { -#        stop("Turning off the sink for the DFOP model is not implemented") -#      } -      # From p. 57 of the FOCUS kinetics report -      nonlinear_term <- paste("((k1 * g * exp(-k1 * time) + k2 * (1 - g) * exp(-k2 * time)) / (g * exp(-k1 * time) + (1 - g) * exp(-k2 * time))) *", new_boxes[[1]]) -      spec[[varname]]$nlt<-nonlinear_term -      new_diffs[[1]] <- paste(new_diffs[[1]], "-", nonlinear_term) -      new_parms <- c("k1", "k2", "g") +      k1_term = paste("k1", varname, sep="_") +      k2_term = paste("k2", varname, sep="_") +      g_term = paste("g", varname, sep="_") +       +      new_parms <- c(k1_term, k2_term, g_term)        ff <- vector() +       +      if (varname == "Parent"){ +        # From p. 57 of the FOCUS kinetics report +        # Looks like this: paste("((k1 * g * exp(-k1 * time) + k2 * (1 - g) * exp(-k2 * time)) / (g * exp(-k1 * time) + (1 - g) * exp(-k2 * time))) *", new_boxes[[1]]) +        nonlinear_term <- paste("((", k1_term, " * ", g_term, " * exp(-", k1_term, " * time) + ", k2_term, " * (1 - ", g_term, ") * exp(-", k2_term, " * time)) / (", g_term, " * exp(-", k1_term, " * time) + (1 - ", g_term, ") * exp(-", k2_term, " * time))) *", new_boxes[[1]]) +         +        spec[[varname]]$nlt<-nonlinear_term +        new_diffs[[1]] <- paste(new_diffs[[1]], "-", nonlinear_term) +      } else { +        # From p. 137 of the FOCUS kinetics report - two sub-compartments with g applied to initial conditions (in ODE pre-processing) and in formation terms. +        first_nonlinear_term <- paste(k1_term, new_boxes[[1]], sep=" * ") +        second_nonlinear_term <- paste(k2_term, new_boxes[[2]], sep=" * ") +         +        overall_term_for_formation <- paste("(", g_term, " * ", first_nonlinear_term, " + (1 - ", g_term, ") *", second_nonlinear_term, ")") +        spec[[varname]]$nlt <- overall_term_for_formation +         +        new_diffs[[1]] <- paste(new_diffs[[1]], "-", first_nonlinear_term) +        new_diffs[[2]] <- paste(new_diffs[[2]], "-", second_nonlinear_term) +      }      }       # Construct and add HS term and add HS parameters if needed @@ -141,82 +134,52 @@ CakeModel <- function(..., use_of_ff = "max")        if(match(varname, obs_vars) != 1) {          stop("Type HS is only possible for the first compartment, which is assumed to be the source compartment")        } -#      if(spec[[varname]]$sink == FALSE) { -#        stop("Turning off the sink for the HS model is not implemented") -#      } -      # From p. 55 of the FOCUS kinetics report -#      nonlinear_term <- paste("ifelse(time <= tb, k1, k2)", "*", new_boxes[[1]]) -      nonlinear_term <- paste("((k1 - k2) / ( 1 + exp( 10*(time - tb) ) ) + k2)", "*", new_boxes[[1]]) +      # From p. 55 of the FOCUS kinetics report: nonlinear_term <- paste("ifelse(time <= tb, k1, k2)", "*", new_boxes[[1]])  +      # Replaced this with the smoothed version on the next line to ease convergence. +      nonlinear_term <- paste("((k1 - k2) / ( 1 + exp( 300*(time - tb)/(tb + 0.00001) ) ) + k2)", "*", new_boxes[[1]])        spec[[varname]]$nlt<-nonlinear_term        new_diffs[[1]] <- paste(new_diffs[[1]], "-", nonlinear_term)        new_parms <- c("k1", "k2", "tb")        ff <- vector()      }  -    # Construct terms for transfer to sink and add if appropriate - -    #@@@@ REMOVE THIS ????? -    if(spec[[varname]]$sink) { -      # Add first-order sink term to first (or only) box for SFO and SFORB -#      if(spec[[varname]]$type %in% c("SFO", "SFORB")) { -      if(spec[[varname]]$type == "SFORB") { -        k_compound_sink <- paste("k", new_boxes[[1]], "sink", sep="_") -        sink_term <- paste("-", k_compound_sink, "*", new_boxes[[1]]) -        new_diffs[[1]] <- paste(new_diffs[[1]], sink_term) -        new_parms <- k_compound_sink -      } +    # Construct and add IORE term and add IORE parameters if needed +    if(spec[[varname]]$type == "IORE") { +      k_term <- paste("k", new_boxes[[1]], sep="_") +      nonlinear_term <- paste(k_term, new_boxes[[1]], sep=" * ") +      nonlinear_term <- paste(nonlinear_term, "^N") +      spec[[varname]]$nlt<-nonlinear_term +      new_diffs[[1]] <- paste(new_diffs[[1]], "-", nonlinear_term) +      new_parms <- c(k_term, "N") +      ff <- vector()      } -    -    # Add reversible binding if appropriate -    if(spec[[varname]]$type == "SFORB") { -      k_free_bound <- paste("k", varname, "free", "bound", sep="_")       -      k_bound_free <- paste("k", varname, "bound", "free", sep="_")       -      reversible_binding_terms <- c( -        paste("-", k_free_bound, "*", new_boxes[[1]], "+", k_bound_free, "*", new_boxes[[2]]), -        paste("+", k_free_bound, "*", new_boxes[[1]], "-", k_bound_free, "*", new_boxes[[2]])) -      new_diffs <- paste(new_diffs, reversible_binding_terms) -      new_parms <- c(new_parms, k_free_bound, k_bound_free) -    }       # Add observed variable to model      parms <- c(parms, new_parms)      names(new_diffs) <- new_boxes      diffs <- c(diffs, new_diffs)    } +      # Transfer between compartments    for (varname in obs_vars) {      to <- spec[[varname]]$to +          if(!is.null(to)) { -      origin_box <- switch(spec[[varname]]$type, -        SFO = varname, -        FOMC = varname, -        DFOP = varname, -        HS = varname, -        SFORB = paste(varname, "free", sep="_"))        fraction_left <- NULL +              for (target in to) { -        target_box <- switch(spec[[target]]$type, +        target_boxes <- switch(spec[[target]]$type,            SFO = target, -          SFORB = paste(target, "free", sep="_")) -        # SFO is no longer special -        #if(spec[[varname]]$type %in% c("SFO", "SFORB")) { -        if(spec[[varname]]$type == "SFORB") { -          k_from_to <- paste("k", origin_box, target_box, sep="_") -          diffs[[origin_box]] <- paste(diffs[[origin_box]], "-",  -            k_from_to, "*", origin_box) -          diffs[[target_box]] <- paste(diffs[[target_box]], "+",  -            k_from_to, "*", origin_box) -          parms <- c(parms, k_from_to) -        } -        # Handle SFO like the others -#        if(spec[[varname]]$type %in% c("FOMC", "DFOP", "HS")) { -        if(spec[[varname]]$type %in% c("FOMC", "DFOP", "HS", "SFO")) { +          DFOP = paste(target, c("1", "2"), sep="_")) +         +        if(spec[[varname]]$type %in% c("FOMC", "DFOP", "HS", "SFO", "IORE")) {            if ( length(to)==1 && !spec[[varname]]$sink ) {              # There is only one output, so no need for any flow fractions. Just add the whole flow from the parent -            diffs[[target_box]] <- paste(diffs[[target_box]], "+", spec[[varname]]$nlt) +            formation_term <- spec[[varname]]$nlt            } else {              fraction_to_target = paste("f", varname, "to", target, sep="_")              fraction_not_to_target = paste("(1 - ", fraction_to_target, ")", sep="") +                          if(is.null(fraction_left)) {                fraction_really_to_target = fraction_to_target                fraction_left = fraction_not_to_target @@ -225,86 +188,38 @@ CakeModel <- function(..., use_of_ff = "max")                if ( target==tail(to,1) && !spec[[varname]]$sink ) {                   fraction_really_to_target = fraction_left                } else { -# (1-fa)fb version -#                 fraction_really_to_target = paste(fraction_left, " * ", fraction_to_target, sep="") -#                 fraction_left = paste(fraction_left, " * ", fraction_not_to_target, sep="") -# fb version                   fraction_really_to_target = fraction_to_target                   fraction_left = paste(fraction_left, " - ", fraction_to_target, sep="")                }              } -            ff[target_box] = fraction_really_to_target -            diffs[[target_box]] <- paste(diffs[[target_box]], "+", ff[target_box], "*", spec[[varname]]$nlt) +             +            ff[target] = fraction_really_to_target +            formation_term <- paste(ff[target], "*", spec[[varname]]$nlt) +                          # Add the flow fraction parameter (if it exists)              if ( target!=tail(to,1) || spec[[varname]]$sink ) {                parms <- c(parms, fraction_to_target)              }            } +           +          if (spec[[target]]$type == "DFOP") { +            g_term <- paste("g", target, sep="_") +             +            first_formation_term <- paste(g_term, "*", formation_term) +            second_formation_term <- paste("(1 -", g_term, ") *", formation_term) +             +            diffs[[target_boxes[[1]]]] <- paste(diffs[[target_boxes[[1]]]], "+", first_formation_term) +            diffs[[target_boxes[[2]]]] <- paste(diffs[[target_boxes[[2]]]], "+", second_formation_term) +          } else{ +            diffs[[target_boxes[[1]]]] <- paste(diffs[[target_boxes[[1]]]], "+", formation_term) +          }          }        }      }    } +      model <- list(diffs = diffs, parms = parms, map = map, use_of_ff = use_of_ff) -  # Create coefficient matrix if appropriate#{{{ -  if (mat) { -    boxes <- names(diffs) -    n <- length(boxes) -    m <- matrix(nrow=n, ncol=n, dimnames=list(boxes, boxes)) - -    if (use_of_ff == "min") { # Minimum use of formation fractions -      for (from in boxes) { -        for (to in boxes) { -          if (from == to) { # diagonal elements -            k.candidate = paste("k", from, c(boxes, "sink"), sep="_") -            k.candidate = sub("free.*bound", "free_bound", k.candidate) -            k.candidate = sub("bound.*free", "bound_free", k.candidate) -            k.effective = intersect(model$parms, k.candidate) -            m[from,to] = ifelse(length(k.effective) > 0, -                paste("-", k.effective, collapse = " "), "0") - -          } else {          # off-diagonal elements -            k.candidate = paste("k", from, to, sep="_") -	    if (sub("_free$", "", from) == sub("_bound$", "", to)) { -              k.candidate = paste("k", sub("_free$", "_free_bound", from), sep="_") -	    } -	    if (sub("_bound$", "", from) == sub("_free$", "", to)) { -              k.candidate = paste("k", sub("_bound$", "_bound_free", from), sep="_") -	    } -            k.effective = intersect(model$parms, k.candidate) -            m[to, from] = ifelse(length(k.effective) > 0, -                k.effective, "0") -          } -        } -      }  -    } else {  # Use formation fractions where possible -      for (from in boxes) { -        for (to in boxes) { -          if (from == to) { # diagonal elements -            k.candidate = paste("k", from, sep="_") -            m[from,to] = ifelse(k.candidate %in% model$parms, -                paste("-", k.candidate), "0") -            if(grepl("_free", from)) { # add transfer to bound compartment for SFORB -              m[from,to] = paste(m[from,to], "-", paste("k", from, "bound", sep="_")) -            } -            if(grepl("_bound", from)) { # add backtransfer to free compartment for SFORB -              m[from,to] = paste("- k", from, "free", sep="_") -            } -            m[from,to] = m[from,to] -          } else {          # off-diagonal elements -            f.candidate = paste("f", from, "to", to, sep="_") -            k.candidate = paste("k", from, to, sep="_") -	    # SFORB with maximum use of formation fractions not implemented, see above -            m[to, from] = ifelse(f.candidate %in% model$parms, -              paste(f.candidate, " * k_", from, sep=""),  -              ifelse(k.candidate %in% model$parms, k.candidate, "0")) -          } -        } -      } -    }  -    model$coefmat <- m -  } -    if (exists("ff")) model$ff = ff    class(model) <- "mkinmod"    invisible(model)  | 
