R/scan_metadata_plot.R

Defines functions scan_metadata_plot

Documented in scan_metadata_plot

#' Make a Scatter Plot of Scan Metadata
#'
#' @description Generate an interactive or static plot of a scan metadata variable
#'     versus a second metadata variable, with possible coloring of points by a third.
#'
#' @param ScanMetadata Object of the scan_metadata class from get_scan_metadata
#' @param XVar X variable of the plot. Accepted values are: Scan Number, Retention Time,
#'     Precursor M/Z, Precursor Scan, Calculated Mass, and Experimental Mass. The mass variables
#'     can only be used if ID data is provided. Default is Precursor M/Z.
#' @param YVar Y variable of the plot. Accepted values are the same as XVar. Default is Retention Time.
#' @param LabVar Variable to label the points. More options available if ID data is provided. Accepted values are:
#'     MS Level, Precursor Charge, Score, and Q Value. Default is MS Level.
#' @param Interactive If True, an interactive plotly graphic will be returned. If
#'     False, a static ggplot graphic will be returned. Default is TRUE.
#' @param MSFilter A vector containing the MS Levels to filter by. Acceptable options are NULL, 1, 2, or c(1,2). Default is NULL.
#' @param ScanNumFilter A vector of length 2 containing the minimum and maximum Scan Numbers to filter by. Default is NULL.
#'
#' @examples
#' \dontrun{
#'
#' # Build scan_metadata object with bottom_up example
#' scan_metadata_plot(BU_ScanMetadata, XVar = "Calculated Mass", YVar = "Retention Time",
#'                    LabVar = "Precursor Charge", Interactive = FALSE)
#' scan_metadata_plot(BU_ScanMetadata, XVar = "Precursor M/Z", YVar = "Retention Time",
#'                    LabVar = "Score", Interactive = TRUE, MSFilter = 2, ScanNumFilter = c(32000, 34500))
#'
#' }
#' @export
scan_metadata_plot <- function(ScanMetadata,
                               XVar = "Precursor M/Z",
                               YVar = "Retention Time",
                               LabVar = "MS Level",
                               Interactive = TRUE,
                               MSFilter = NULL,
                               ScanNumFilter = NULL) {

  ##################
  ## CHECK INPUTS ##
  ##################

  # Assert that ScanMetadata is a ScanMetadata object.
  if ("scan_metadata" %in% class(ScanMetadata) == FALSE) {
    stop("ScanMetadata must be a scan_metadata object generated by get_scan_metadata.")
  }

  # Assert that XVar and YVar are acceptable choice
  XYVarOptions <- c("Scan Number", "MS Level", "Retention Time", "Precursor M/Z", "Precursor Scan",
                    "Calculated Mass", "Experimental Mass")
  if (XVar %in% XYVarOptions == F) {
    stop(paste("X Variable must be one of the following options:", paste0(XYVarOptions, collapse =", ")))
  }
  if (YVar %in% XYVarOptions == F) {
    stop(paste("Y Variable must be one of the following options:", paste0(XYVarOptions, collapse =", ")))
  }

  # Check that Interactive is logical
  if (Interactive %in% c(TRUE, FALSE) == FALSE) {stop("Interactive must be True or False.")}

  # Mass can't be used as XVar or YVar if no ID data is provided. LabVar also can't be used if no ID data is provided.
  if (is.null(attr(ScanMetadata, "pspecter")$IDPath)) {
    if (XVar %in% c("Calculated Mass", "Experimental Mass") | YVar %in% c("Calculated Mass", "Experimental Mass")) {
      stop("XVar and YVar cannot be Calculated or Experimental Mass if no ID data is provided.")
    }
    if (LabVar != "MS Level") {
      stop("If no ID data is provided, LabVar must be MS Level.")
    }
  }

  # Assert that LabVar is an acceptable choice
  LabVarOptions <- c("MS Level", "Precursor Charge", "Score", "Q Value")
  if (is.null(LabVar) == FALSE && LabVar %in% LabVarOptions == F) {
    stop(paste("Label Variable must be one of the following options:", paste0(LabVarOptions, collapse =", ")))
  }

  # Ensure MSFilter contains a 1 or 2 or both
  if (is.null(MSFilter) == F && any(MSFilter %in% c(1,2)) == FALSE) {
    stop("MS Filter must contain 1, 2, or both in a vector.")
  }

  # Ensure ScanNumFilter includes two values within the min and max scan number
  if (is.null(ScanNumFilter) == F) {
      if (length(ScanNumFilter) != 2 || ScanNumFilter[1] > ScanNumFilter[2]) {
        stop("Scan Number Filter must contain 2 values: a min and a max scan number in order from smallest to largest.")}
  }

  ###################
  ## DATA CLEANING ##
  ###################

  # Pull out scan metadata
  scan <- ScanMetadata

  # Apply MS and Scan Number Filters
  if (is.null(MSFilter) == F) {scan <- subset(scan, `MS Level` %in% MSFilter)}
  if (is.null(ScanNumFilter) == F) {scan <- subset(scan, `Scan Number` >= min(ScanNumFilter) &
                                                     `Scan Number` <= max(ScanNumFilter))}

  # Generate appropriate labels for hover-over
  X <- scan[[XVar]]
  Y <- scan[[YVar]]

  # Label will be a factor variable if it's not score or q-value
  if (LabVar %in% c("Score", "Q Value")) {
    Label <- as.numeric(scan[[LabVar]])
  } else{
    Label <- as.factor(scan[[LabVar]])
  }

  # Generate plotting data frame
  DF <- data.frame(X, Y, Label)

  ###############
  ## MAKE PLOT ##
  ###############

  ScanMetadataPlot <- ggplot2::ggplot(DF, ggplot2::aes(x = X, y = Y, color = Label)) +
    ggplot2::geom_point() + ggplot2::theme_bw() + ggplot2::labs(color = LabVar) +
    ggplot2::xlab(XVar) + ggplot2::ylab(YVar)

  # If interactive is True
  if (Interactive) {
    ScanMetadataPlot <- ScanMetadataPlot %>% plotly::ggplotly()
  }

  # Return Plot
  return(ScanMetadataPlot)

}
EMSL-Computing/pspecterlib documentation built on Jan. 28, 2024, 8:13 p.m.