R/fitEdgeEffect.R

Defines functions fitEdgeEffect

Documented in fitEdgeEffect

#' Fit a 2D surface to capture the incubation/edge effect on each plate
#'
#' This function fits a 2D surface using either loess (local regression) model or a 2D sigmod model
#' based on the measurements on each plate to estimate the shape and strength of per-plate incubation effect.
#' This function is normally called by the correctEdgeEffect() function instead of used as a standalone function.
#'
#' @param screenData the data frame containing screen results generated by \code{readScreen()} function.
#' For this function to work, the \code{normVal} (normalized viability values) generated by \code{readScreen()}
#' function with \code{normalization = TRUE} must be present.
#' @param method a character string specifying the method used for estimating the shape and strength of edge effect.
#' Currently two methods are supported:
#' 'loess', which uses local regression to estimate edge effect;
#' 'sigmoid', a experimental feature, using 2D-sigmoid model to estimate edge effect.
#' @param useNeg a logical value. If TRUE, only negative controls are used to estimate edge effect. Otherwise, all the wells are used for edge effect estimation.
#' @param useLowConcentrations an integer value. In addition to negative controls,
#' sample wells with low concentrations of drugs or other perturbators can be considered as 'de facto' negative controls and included in edge effect estimation.
#' The default value is 0, means no sample wells are used. If the value n >= 1, the n lowest concentrations will be used.
#' @param span a numeric value. The span parameter for loess, which controls the degree of smoothing.
#' @param exclude a list of samples that should be excluded when performing edge effect correction. Both plate file names or sampleIDs can be used as identifiers.
#' @export
#' @import dplyr
#' @return This function will add one column, \code{edgeFactor}, which is the estimated incubation or edge effect, to the input data frame.
#' @examples
#' # load drug screen dataset
#' data('screenData_normalized')
#' screenData_fitted <- fitEdgeEffect(screenData_normalized, method = 'loess', useNeg = TRUE)

fitEdgeEffect <- function(screenData, method = "loess", useNeg = TRUE, useLowConcentrations = 0, span = 1, exclude = c()) {
  # a function to calculate position correction factor for each plate

  # check if normalized values is present
  if (!"normVal" %in% colnames(screenData)) {
    error("Normalized values are not present. Please perform plate normalization first.")
  }

  # remove precalculated edge factor if present
  if ("edgeFactor" %in% colnames(screenData))
    screenData[["edgeFactor"]] <- NULL

  # check if data has been normalized find n lowest concentrations
  if (useLowConcentrations > 0) {
    # identify the lowest concentrations for each drug
    if (!all(c("name", "concentration", "wellType") %in% colnames(screenData))) {
      stop("No information of name, concentration and well type found")
    } else {
      nLowest <- function(x, n) {
        sort(unique(x))[seq(1, n)]
      }
      lowConcTab <- dplyr::filter(screenData, wellType == "sample") %>%
        group_by(name) %>%
        do(tibble(concentration = nLowest(.$concentration, useLowConcentrations))) %>%
        ungroup()
    }
  }

  # change rowID and colID to numeric values for fitting
  nRow <- length(unique(screenData$rowID))
  row2num <- structure(seq(nRow), names = genRowIDs(nRow))
  screenSub <- dplyr::mutate(screenData, numRowID = row2num[rowID], numColID = as.integer(colID)) %>%
    dplyr::filter(!fileName %in% exclude)

  if (method == "loess") {
    screenSub <- group_by(screenSub, fileName) %>%
      do(fitOneLoess(., useNeg, useLowConcentrations, lowConcTab, span)) %>%
      ungroup() %>%
      dplyr::select(fileName, rowID, colID, edgeFactor)

  } else if (method == "sigmoid") {
    screenSub <- group_by(screenSub, fileName) %>%
      do(fitOneSigmoid(., useNeg, useLowConcentrations, lowConcTab)) %>%
      ungroup() %>%
      dplyr::select(fileName, rowID, colID, edgeFactor)
  }

  screenData <- left_join(screenData, screenSub, by = c("fileName", "rowID", "colID")) %>%
    dplyr::mutate(edgeFactor = ifelse(is.na(edgeFactor), 1, edgeFactor))

  return(screenData)

}
lujunyan1118/DrugScreenExplorer_dev documentation built on Dec. 21, 2021, 12:42 p.m.