R/error_heatmap_plot.R

Defines functions error_heatmap_plot

Documented in error_heatmap_plot

#' Generate a Heatmap of PPM Errors per Ion Type per Residue
#'
#' @description Make a Heatmap where x is the peptide residue (in order from N to C-terminus), y is the ion type, and z is the ppm error
#'
#' @param MatchedPeaks A matched_peaks object generated by get_matched peaks. Required.
#' @param IncludeIsotopes A logical to indicate whether isotopes should be included. Default is FALSE
#'     for cleaner heatmaps.
#' @param Interactive A logical to determine whether the plot should be interactive or not. Default is TRUE.
#'
#' @examples
#' \dontrun{
#'
#' # Test bottom up data
#' BU_Peak <- get_peak_data(ScanMetadata = BU_ScanMetadata, ScanNumber = 31728)
#' BU_Match <- get_matched_peaks(ScanMetadata = BU_ScanMetadata, PeakData = BU_Peak)
#'
#' error_heatmap_plot(MatchedPeaks = BU_Match, IncludeIsotopes = FALSE)
#' error_heatmap_plot(MatchedPeaks = BU_Match, IncludeIsotopes = TRUE)
#' error_heatmap_plot(MatchedPeaks = BU_Match, IncludeIsotopes = TRUE, Interactive = FALSE)
#'
#' }
#'
#' @export
error_heatmap_plot <- function(MatchedPeaks,
                               IncludeIsotopes = FALSE,
                               Interactive = TRUE) {

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

  # Assert that Matched Peaks is an object of the matched_peaks
  if ("matched_peaks" %in% class(MatchedPeaks) == FALSE) {
    stop("MatchedPeaks is not an object of the matched_peaks class generated by get_matched_peaks.")
  }

  # Assert that Include Isotopes is a single logical
  if (is.na(IncludeIsotopes) || is.logical(IncludeIsotopes) == FALSE || length(IncludeIsotopes) > 1) {
    stop("IncludeIsotopes needs to be a single logical: a TRUE or FALSE.")
  }

  # Assert that Interactive is a single logical
  if (is.na(Interactive) || is.logical(Interactive) == FALSE || length(Interactive) > 1) {
    stop("Interactive needs to be a single logical: a TRUE or FALSE.")
  }

  #########################
  ## GENERATE DATA TABLE ##
  #########################

  # Subset out Fragemnt Dataframe
  FragmentTable <- MatchedPeaks

  # Remove isotopes if indicated
  if (IncludeIsotopes == FALSE) {
    FragmentTable <- FragmentTable[FragmentTable$Isotope == "M",]
  }

  # Subset Fragment Table Down to Heatmap-Specific Properties
  FragmentTable <- FragmentTable[,c("Type", "Z", "Isotope", "Residue", "PPM Error")]

  # Create Ion Type categories
  FragmentTable$`Ion Type` <- paste0(FragmentTable$Type, "(+", FragmentTable$Z, ") ", FragmentTable$Isotope)

  # Unique Ion Types
  UniqueIonTypes <- FragmentTable$`Ion Type` %>% unique()

  # Determine the names of the residues
  SplitSeq <- attr(MatchedPeaks, "pspecter")$Sequence %>% strsplit("") %>% unlist()
  Residues <- paste0(SplitSeq, 1:length(SplitSeq))

  # Build matrix
  Heatmap <- matrix(nrow = FragmentTable$`Ion Type` %>% unique() %>% length(),
                    ncol = nchar(attr(MatchedPeaks, "pspecter")$Sequence) + 1) %>% data.frame()

  # Fill out heatmap
  for (row in 1:nrow(FragmentTable)) {
    IonTypePosition <- which(UniqueIonTypes == FragmentTable[row, "Ion Type"] %>% unlist())
    ResPosition <- which(Residues == FragmentTable[row, "Residue"] %>% unlist()) + 1
    PPMError <- FragmentTable[row, "PPM Error"] %>% round(3)
    Heatmap[IonTypePosition, ResPosition] <- PPMError
  }

  # Convert to a data table
  Heatmap <- data.table::data.table(Heatmap)
  colnames(Heatmap) <- c("Ion Type", Residues)
  Heatmap$`Ion Type` <- UniqueIonTypes

  # Take the heatmap and pivot longer for ease of plotting
  Heatmap <- Heatmap %>% tidyr::pivot_longer(Residues)
  colnames(Heatmap)[2:3] <- c("Residues", "PPM Error")

  # Order heatmap residues
  Heatmap$Residues <- factor(Heatmap$Residues, levels = Residues)

  # Make heatmap
  HeatmapPlot <- ggplot2::ggplot(Heatmap, ggplot2::aes(x = Residues, y = `Ion Type`, fill = `PPM Error`)) +
    ggplot2::geom_tile() + ggplot2::theme_minimal() +
    ggplot2::theme(axis.text.x = ggplot2::element_text(angle = 90, hjust = 1)) +
    ggplot2::scale_fill_gradientn(colours = c("blue", "grey", "red"),
                                  values = c(0,0.5,1), na.value = "white")

  # Return interactive if directed
  if (Interactive) {
    return(HeatmapPlot %>% plotly::ggplotly())
  } else {
    return(HeatmapPlot)
  }

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