R/REGS.R

Defines functions ResistanceClassifier ResistancePredictor CyclophosphamideClassifier CyclophosphamidePredictor DoxorubicinClassifier DoxorubicinPredictor VincristineClassifier VincristinePredictor ResistancePredFun ResistanceProbFun RituximabClassifier RituximabPredictor RituximabProbFun DexamethasoneClassifier DexamethasonePredictor MelphalanClassifier MelphalanPredictor

Documented in CyclophosphamideClassifier CyclophosphamidePredictor DexamethasoneClassifier DexamethasonePredictor DoxorubicinClassifier DoxorubicinPredictor MelphalanClassifier MelphalanPredictor ResistanceClassifier ResistancePredictor RituximabClassifier RituximabPredictor VincristineClassifier VincristinePredictor

#' REGS for prediction of chemoresistance
#' 
#' Resistance Gene Signatures (REGS) for prediction of resistance to various 
#' chemotherapeutic drugs.
#' 
#' @rdname REGS
#' @aliases 
#'   REGS
#'   ResistanceClassifier 
#'   ResistancePredictor
#'   CyclophosphamideClassifier
#'   CyclophosphamidePredictor
#'   DoxorubicinClassifier
#'   DoxorubicinPredictor
#'   VincristineClassifier
#'   VincristinePredictor
#'   RituximabClassifier
#'   RituximabPredictor
#'   DexamethasoneClassifier
#'   DexamethasonePredictor
#'   MelphalanClassifier
#'   MelphalanPredictor
#' @param new.data An expression matrix.
#' @param drugs An RMA reference object created by rmaPreprocessing.
#' @param cut Should the \code{.cel} files be tested. When set to \code{TRUE}  
#'   bad \code{.cel} files are automatically discarded.
#' @param type For Rituximab, What type of classifier or predictor should be
#'   used. Current choices are corrected, uncorrected, lysis, and lysis2.
#' @param calc.cut For Rituximab, calculate the cutpoints according to 
#'   proportions in the data. E.g. \code{calc.cut = c(0.33, 0.66)} means that a 
#'  third is deemed sensitive, intermediate, and resistant respectively.
#' @param cut.spec For the lysis type rituximab classifier specify the cut 
#'   point for unclassified.
#' @param percent.classified For the lysis type rituximab classifier specify 
#'   the percentage of unclassified.
#' @return
#' The \code{ResistanceClassifier} \code{ResistancePredictor},
#' \code{RituximabClassifier}, and \code{RituximabPredictor}
#' functions return 
#' a \code{list} of length 3 with the slots:
#' \item{class}{A \code{data.frame} giving predicted classes for each sample.}
#' \item{prob}{A \code{matrix} of proability or scores for each class and 
#'   sample.}
#' \item{cut}{A \code{numeric} or \code{list} of \code{numeric}s giving the 
#'   thresholds used to select the classes.}
#' 
#' The remaning \code{xxxClassifier}, \code{xxxPredictor}, and \code{xxxProbFun}
#' functions returns the components above.
#' @seealso \code{\link{rmaPreprocessing}}, \code{\link{rmaReference}},
#'   \code{\link{microarrayScale}}
#' @references
#'   \url{http://hemaClass.org}
#' @author 
#'   Steffen Falgreen <sfl (at) rn.dk> \cr 
#'   Anders Ellern Bilgrau <abilgrau (at) math.aau.dk>
#' @examples
#' \donttest{
#' # First, we read the .CEL files bundled together with hemaClass
#' files <- list.files(system.file("extdata/celfiles", package = "hemaClass"),
#'                     full.names = TRUE)
#' affyBatch <- readCelfiles(filenames = files)
#' 
#' # The .CEL files are then pre-processed
#' affyRMA <- rmaPreprocessing(affyBatch)
#' # The slot exprs.sc contains median centered and scaled expression values.
#' # The slot exprs.sc.mean contains mean centered and scaled expression values.
#' # This scaling can also be achieved using the function microarrayScale.
#' affyRMA.sc <- microarrayScale(affyRMA$exprs, center = "median")
#' 
#' # We can now use the predictors
#' 
#' # The classifier for Cyclophosphamide, Doxorubicin, and Vincristine:
#' ResistanceClassifier(affyRMA.sc)
#' 
#' # The predictor for Cyclophosphamide, Doxorubicin, and Vincristine:
#' ResistancePredictor(affyRMA.sc)
#' 
#' # The classifier for Rituximab into Lysis, Statisk, or Resistant:
#' RituximabClassifier(affyRMA.sc, type = "lysis2", percent.classified = 100) 
#' 
#' # The classifier for Rituximab into Sensitive, Intermediate, or Resistant 
#' # without  taking human serum into account:
#' RituximabClassifier(affyRMA.sc, type = "uncorrected", 
#'                     calc.cut = c(0.33, 0.66)) 
#' 
#' # The classifier for Rituximab into Sensitive, Intermediate, or Resistant 
#' # while taking human serum into account:
#' RituximabClassifier(affyRMA.sc, type = "corrected") 
#' 
#' # For the melphalan classifier we use mean centered and sd scaled expression 
#' # values:
#' affyRMA.sc.mean <- microarrayScale(affyRMA$exprs, center = "mean")
#' MelphalanClassifier(affyRMA.sc.mean) 
#' 
#' # For the melphalan predictor we use the original scale:
#' MelphalanPredictor(affyRMA$exprs)  
#' }
#' @export
ResistanceClassifier <- function(new.data, 
                                 drugs = c("Cyclophosphamide", "Doxorubicin", 
                                           "Vincristine", "Combined"),
                                 cut = list(Cyclophosphamide = c(0.33, 0.545),
                                            Doxorubicin      = c(0.14,   0.9),
                                            Vincristine      = c(0.46,  0.62),
                                            Combined         = c(0.093, 0.933))) {
  
  new.data[is.na(new.data)] <- 0
  train.mat <- ResistanceProbFun(new.data, setdiff(drugs, "Combined"))
  wh <- intersect(drugs, colnames(train.mat)) 
  train.mat <- train.mat[, wh, drop = FALSE]
  
  if ("Combined" %in% drugs & length(length(drugs) > 3)) {
    train.mat <- cbind(train.mat, apply(train.mat, 1, prod) / 
                         (apply(train.mat, 1, prod) +
                            apply(1 - train.mat, 1, prod)))
    colnames(train.mat) <- drugs
  }
  
  cut <- cut[drugs]
  
  class <- train.mat
  class[,] <- "Intermediate"
  
  class[train.mat < matrix(unlist(rep(data.frame(cut)[1,], each = nrow(train.mat))),
                           nrow = nrow(train.mat), byrow = FALSE)] <- "Sensitive"
  class[train.mat > matrix(unlist(rep(data.frame(cut)[2,], each = nrow(train.mat))),
                           nrow = nrow(train.mat), byrow = FALSE)] <- "Resistant"
  
  class <- as.data.frame(class)
  
  
  for (i in 1:ncol(train.mat)) {
    class[, i] <- factor(class[, i], 
                         levels = c("Sensitive", "Intermediate", "Resistant"))
  }
  
  return(list(class = class, prob  = train.mat, cut   = cut))
}


#' @rdname REGS
#' @export
ResistancePredictor <- function(new.data, 
                                drugs = c("Cyclophosphamide", "Doxorubicin", 
                                          "Vincristine", "Combined"),
                                cut = list(Cyclophosphamide = c(280, 340),
                                           Doxorubicin      = c(280, 320),
                                           Vincristine      = c(115,  127),
                                           Combined         = c(200, 295))) {
  new.data[is.na(new.data)] <- 0
  train.mat <- ResistancePredFun(new.data, setdiff(drugs, "Combined"))
  wh <- intersect(drugs, colnames(train.mat)) 
  train.mat <- train.mat[, wh, drop = FALSE]
  
  if ("Combined" %in% drugs & length(length(drugs) > 3)) {
    train.mat <- cbind(train.mat, apply(train.mat, 1, prod) / 
                         (apply(train.mat, 1, prod) +
                            apply(1 - train.mat, 1, prod)))
    colnames(train.mat) <- drugs
  }
  
  cut <- cut[drugs]
  
  class <- train.mat
  class[,] <- "Intermediate"
  
  # Check that these are the correct way
  class[train.mat < matrix(unlist(rep(data.frame(cut)[1,], each = nrow(train.mat))),
                           nrow = nrow(train.mat), byrow = FALSE)] <- "Sensitive"
  class[train.mat > matrix(unlist(rep(data.frame(cut)[2,], each = nrow(train.mat))),
                           nrow = nrow(train.mat), byrow = FALSE)] <- "Resistant"
  
  class <- as.data.frame(class)
  
  
  for (i in 1:ncol(train.mat)) {
    class[, i] <- factor(class[, i], 
                         levels = c("Sensitive", "Intermediate", "Resistant"))
  }
  return(list(class = class, pred  = train.mat, cut   = cut))
}


#' @rdname REGS
#' @export
CyclophosphamideClassifier <- function(new.data) {
  coef <- readCyclophosphamideClasCoef()
  
  x <- rbind(1, new.data[names(coef)[-1], , drop = FALSE])
  
  prob <- t(x) %*% as.matrix((coef))
  
  prob <- exp(prob) / (exp(prob) + exp(-prob))
  colnames(prob) <- "Resistant"
  return(prob)
}

#' @rdname REGS
#' @export
CyclophosphamidePredictor <- function(new.data) {
  coef <- readCyclophosphamidePredCoef()
  
  x <- rbind(1, new.data[names(coef)[-1], , drop = FALSE])
  
  return(t(x) %*% as.matrix(coef))
}


#' @rdname REGS
#' @export
DoxorubicinClassifier <- function(new.data) {
  coef <- readDoxorubicinClasCoef()
  
  x <- rbind(1, new.data[names(coef)[-1], , drop = FALSE])
  
  prob <- t(x) %*% as.matrix((coef))
  
  prob <-  exp(prob) / (exp(prob) + exp(-prob))
  colnames(prob) <- "Resistant"
  return(prob)
}

#' @rdname REGS
#' @export
DoxorubicinPredictor <- function(new.data) {
  coef <- readDoxorubicinPredCoef()
  
  x <- rbind(1, new.data[names(coef)[-1], , drop = FALSE])
  
  return(t(x) %*% as.matrix(coef))
}


#' @rdname REGS
#' @export
VincristineClassifier <- function(new.data) {
  coef <- readVincristineClasCoef()
  
  x <- rbind(1, new.data[names(coef)[-1], , drop = FALSE])
  
  prob <- t(x) %*% as.matrix((coef)  )
  
  prob <- exp(prob) / (exp(prob) + exp(-prob))
  colnames(prob) <- "Resistant"
  return(prob)
}

#' @rdname REGS
#' @export
VincristinePredictor <- function(new.data) {
  coef <- readVincristinePredCoef()
  
  x <- rbind(1, new.data[names(coef)[-1], , drop = FALSE])
  
  return(t(x) %*% as.matrix((coef)))
}

ResistancePredFun <- function(newx, 
                              drugs = c("Cyclophosphamide", "Doxorubicin", 
                                        "Vincristine")) {
  
  coef <- readPredCoef()
  
  diff <- setdiff(row.names(coef)[-1], rownames(newx))
  
  if (length(diff)) {
    missing <-  matrix(0, ncol = ncol(newx), nrow = length(diff), 
                       dimnames = list(diff, colnames(newx) ))
    
    newx <- rbind(newx, missing)
    
    warning("the following probesets are missing:\n", 
            paste(diff, collapse = ", "))
  }
  
  x <- rbind(1, newx[row.names(coef)[-1], , drop = FALSE])
  
  return(t(x) %*% coef[, drugs, drop = FALSE])
}


ResistanceProbFun <- function(newx, 
                              drugs = c("Cyclophosphamide", "Doxorubicin", 
                                        "Vincristine")) {
  
  coef <- readClasCoef()
  
  diff <- setdiff(row.names(coef)[-1], rownames(newx))
  
  if (length(diff)) {
    missing <-  matrix(0, ncol = ncol(newx), nrow = length(diff), 
                       dimnames = list(diff, colnames(newx) ))
    
    newx <- rbind(newx, missing)
    
    warning("the following probesets are missing:\n", 
            paste(diff, collapse = ", "))
  }
  x <- rbind(1, newx[row.names(coef)[-1], , drop = FALSE])
  
  prob.mat <- t(x) %*% coef[, drugs, drop = FALSE]
  
  prob.mat2 <- exp(prob.mat) / (exp(prob.mat) + exp(-prob.mat))
  
  return(prob.mat2)
}



#' @rdname REGS
#' @export
RituximabClassifier <- function(new.data,
                                type = "corrected",
                                cut = c(0.33, 0.66), 
                                calc.cut = NULL,
                                cut.spec = NULL, 
                                percent.classified = 85){
  
  if (grepl("lysis", type)) {
    
    new.data[is.na(new.data)] <- 0
    
    train.mat <- RituximabProbFun(new.data, type = type)
    
    if (nrow(new.data) > 1) {
      class <- colnames(train.mat)[apply(train.mat, 1, which.max)]
    } else {
      class <- names(which.max(train.mat))
    }
    
    if (nrow(new.data) > 1) {
      prob = apply(train.mat, 1, max)
      if (is.null(cut.spec)) {
        cut <- quantile(prob, 1 - percent.classified / 100)    
      }
    } else {
      cut <- 0
      prob = max(train.mat)
    }
    
    if (!is.null(cut.spec)) {
      cut <- cut.spec
    }
    
    class <- 
      factor(ifelse(prob < cut, "Unclassified", class),
             levels = c("Lytic", "Static", "Resistant", "Unclassified"))
    class <- as.matrix(class)
    colnames(class) <- "Sensitivity"
    
    return(list(class = class, prob = train.mat, cut = cut))
    
  } else {
    
    if (type == "uncorrected") {
      coef <- readRituximabClasCoef()
    }
    if (type == "corrected") {
      coef <- readRituximabClasCorCoef()
    }
    
    x <- rbind(1, new.data[names(coef)[-1], , drop = FALSE])
    
    prob <- t(x) %*% as.matrix(coef)
    
    prob <- exp(prob) / (exp(prob) + exp(-prob))
    colnames(prob) <- "Resistant"
    
   # prob <- 1 - prob # to obtain probability of being sensitive
  #  colnames(prob) <- "Sensitivity"
    
    if (!is.null(calc.cut)) {
      cut <- quantile(prob, calc.cut)
    }
    class <- prob
    class[] <- "Intermediate"
    class[prob < min(cut)] <- "Sensitive"
    class[prob > max(cut)] <- "Resistant"
    
    class <- as.data.frame(class)
    
    class[,1] <- factor(class[,1], 
                        levels = c("Sensitive", "Intermediate", "Resistant"))
    
    return(list(class = class, prob = prob, cut = cut))
  }
}

#' @rdname REGS
#' @export
RituximabPredictor <- function(new.data, type = "corrected", 
                               cut = c(0.33, 0.66), calc.cut = NULL) {
  
  if (type == "uncorrected") {
    coef <- readRituximabPredCoef()
  } else if (type == "corrected") {
    coef <- readRituximabPredCorCoef()
  }
  x <- rbind(1, new.data[names(coef)[-1], , drop = FALSE])
  
  prob <- t(x) %*% as.matrix((coef))
  
  # calculate classes
  class <- prob
  
  if (!is.null(calc.cut)) {
    cut <- quantile(prob, calc.cut)
  }
  class[] <- "Intermediate"
  
  if (type == "uncorrected") {
    class[prob < min(cut)] <- "Sensitive"
    class[prob > max(cut)] <- "Resistant"
  }
  
  if (type == "corrected") {
    class[prob < min(cut)] <- "Resistant"
    class[prob > max(cut)] <- "Sensitive"
  }
  
  class <- as.data.frame(class)
  class[,1] <- factor(class[,1], 
                      levels = c("Sensitive", "Intermediate", "Resistant"))
  
  return(list(class = class, pred  = prob, cut   = cut))
}


RituximabProbFun <- function(newx, type = c("lysis", "lysis2")) {
  type <- match.arg(type)
  if (type == "lysis") {
    coef <- readRituximabClasLytiskCoef()
  } else if (type == "lysis2") {
    coef <- readRituximabClasLytisk2Coef()
  }
  
  x <- rbind(1, newx[row.names(coef)[-1], , drop = FALSE])
  prob.mat <- matrix(ncol = 3, nrow = ncol(x))
  
  colnames(prob.mat) <- c("Lytic", "Static", "Resistant")
  rownames(prob.mat) <- colnames(x)
  prob.mat[, "Lytic"]     <- t(x) %*% as.matrix(coef)[, "Lytisk"] 
  prob.mat[, "Static"]    <- t(x) %*% as.matrix(coef)[, "Statisk"]
  prob.mat[, "Resistant"] <- t(x) %*% as.matrix(coef)[, "Resistant"]
  
  prob.mat <- exp(prob.mat)
  return(prob.mat/rowSums(prob.mat))
}



#' @rdname REGS
#' @export
DexamethasoneClassifier <- function(new.data){
  warning("The Dexamethasone classifier is still experimental! ",
          "Use with caution.")
  coef <- readDexamethasoneClasCoef()
  
  x <- rbind(1, new.data[names(coef)[-1], , drop = FALSE])
  
  prob <- t(x) %*% as.matrix(coef)
  prob <- exp(prob)/(exp(prob) + exp(-prob))
  colnames(prob) <- "Resistant"
  return(prob)
}

#' @rdname REGS
#' @export
DexamethasonePredictor <- function(new.data) {
  warning("The Dexamethasone classifier is still experimental! ",
          "Use with caution.")
  coef <- readDexamethasonePredCoef()
  
  x <- rbind(1, new.data[names(coef)[-1], , drop = FALSE])
  
  return(t(x) %*% as.matrix((coef)))
}

#' @rdname REGS
#' @export
MelphalanClassifier <- function(new.data) {
  coef <- readMelphalanClasCoef()
  
  x <- rbind(1, as.matrix(new.data)[colnames(coef)[-1], , drop = FALSE])
  
  probs <- t(tcrossprod(coef, t(x)))
  probs <- exp(probs - probs[cbind(1:nrow(probs), 
                                   max.col(probs, ties.method = "first"))])
  probs <- zapsmall(probs/rowSums(probs))
  class <- factor(rownames(coef)[max.col(probs)], 
                  levels = c("Sensitive", "Intermediate", "Resistant"))
  
  return(list(probs = probs, class = class))
}

#' @rdname REGS
#' @export
MelphalanPredictor <- function(new.data) {
  fit <- readMelphalanPredCoef()
  
  newx <- t(as.matrix(new.data)[rownames(fit$beta)[-1], , drop = FALSE])
  newx <- scale(newx, fit$center, fit$scale)
  
  return(cbind(1, newx) %*% fit$beta)
}
HaemAalborg/hemaClass documentation built on Oct. 22, 2019, 7:01 p.m.