R/plot_wrapper.R

Defines functions PlotSynergy PlotDoseResponse

Documented in PlotDoseResponse PlotSynergy

# Copyright Shuyu Zheng and Jing Tang - All Rights Reserved
# Unauthorized copying of this file, via any medium is strictly prohibited
# Proprietary and confidential
# Written by Shuyu Zheng <shuyu.zheng@helsinki.fi>, March 2021
#
# SynergyFinder
#
# Functions on this page:
#
# PlotDoseResponse: Visualize the Drug Combination Dose-response Data

#' Visualize the Drug Combination Dose-response Data
#'
#' A function to visualize the drug combination dose-response data
#'
#' @param data A list object generated by function \code{\link{ReshapeData}}.
#' @param block_ids A vector of characters/integers or NULL. It contains the
#'   block IDs for the blocks to visualize. By default, it is NULL so that the
#'   visualization of all the drug combinations in input \code{data}.
#' @param drugs A vector of characters or integers with length of 2. It contains
#'   the index for two drugs to plot. For example, \code{c(1, 2)} indicates to
#'   plot "drug1" and "drug2" in the input \code{data}.
#' @param adjusted A logical value. If it is \code{FALSE}, original response
#'   matrix will be plotted. If it is \code{TRUE}, adjusted response matrix will
#'   be plotted.
#' @param statistic A character or NULL. It indicates the statistics printed
#'   in the plot while there are replicates in input data. Available values are:
#'   \itemize{
#'     \item \strong{sem} Standard error of mean;
#'     \item \strong{ci} 95% confidence interval.
#'   }
#'   If it is \code{NULL}, no statistics will be printed.
#' @param summary_statistic A vector of characters or NULL. It indicates the
#'   summary statistics printed in heatmap for all the \code{plot_value} in
#'   whole combination matrix. Available values are:
#'   \itemize{
#'     \item \strong{mean} Median value for all the responses or synergy
#'     scores in the matrix;
#'     \item \strong{median} Median value for all the responses or synergy
#'     scores in the matrix;
#'     \item \strong{quantile_90} 90% quantile. User could change the number to
#'     print different sample quantile. For example quantile_50 equal to median. 
#'   }
#'   If it is \code{NULL}, no statistics will be printed.
#' @param high_value_color An R color value. It indicates the color for the
#'   high values.
#' @param low_value_color An R color value. It indicates the color for low
#'   values.
#' @param point_color An R color value. It indicates the color for points in
#'   dose response curve plots.
#' @param curve_color An R color value. It indicates the color for curves in 
#'   dose response curve plots.
#' @param text_size_scale A numeric value. It is used to control the size
#'   of text in the plot. All the text size will multiply by this scale factor.
#' @param heatmap_text_label_size_scale A numeric value. It is used to control
#'   the size of text labels in the heatmap plot. It only works while 
#'   \code{plot_type = "heatmap"}.
#' @param heatmap_text_label_color NULL or an R color value. It is used to
#'   control the color of text labels in the heatmap plot. If it is \code{NULL},
#'   text label will not be shown.It only works while
#'   \code{plot_type = "heatmap"}. 
#' @param heatmap_plot_title A character value to indicate the plot title for
#'   the heatmap.
#' @param curve_plot_title A character value to indicate the plot title for
#'   the dose-response curve.
#' @param Emin A numeric or \code{NA}. the minimal effect of the drug used in
#'   the 4-parameter log-logistic function to fit the dose-response curve. If
#'   it is not NA, it is fixed the value assigned by the user. Default setting
#'   is \code{NA}.
#' @param Emax A numeric or \code{NA}. the maximal effect of the drug used in
#'   the 4-parameter log-logistic function to fit the dose-response curve. If
#'   it is not NA, it is fixed the value assigned by the user. Default setting
#'   is \code{NA}.
#' @param save_file A parameter to specify if the visualization results are
#'   saved as pdf files in current working directory or not. If it is FALSE,
#'   the results are returned as a list of the plots. It is FALSE by default.
#' @param file_type A character. It indicates the format of files you want to
#'   save as. Default is "pdf". Available values are "jpeg", "bmp", "png",
#'   "tiff", "pdf", "svg".
#' @param file_name A character vector. It indicates the file names, if
#'   user chose to save the plot to local directory.If it is not defined by
#'   user, a default name will be assigned.
#' @param width a numeric value. It indicates the width of saved file.
#' @param height a numeric value. It indicates the height of saved file.
#'
#' @return A list of plot objects recorded by \link[grDevices]{recordPlot}. The 
#'   plot will be saved into a local file if \code{save_file = TRUE}. If 
#'   \code{save_file = FALSE}, the plot will be printed in default graphic
#'   device.
#'
#' @author
#' \itemize{
#'   \item Shuyu Zheng \email{shuyu.zheng@helsinki.fi}
#'   \item Jing Tang \email{jing.tang@helsinki.fi}
#' }
#' 
#' @import ggplot2
#' @export
#'
#' @examples
#' \dontrun{
#' data("mathews_screening_data")
#' data <- ReshapeData(mathews_screening_data)
#' plots <- PlotDoseResponse(data)
#' }
PlotDoseResponse <- function(data,
                             block_ids = c(1),
                             drugs = c(1, 2),
                             adjusted = TRUE,
                             statistic = NULL,
                             summary_statistic = "mean",
                             high_value_color = "#A90217",
                             low_value_color = "#2166AC",
                             point_color = "#C24B40",
                             curve_color = "black",
                             text_size_scale = 1,
                             heatmap_text_label_size_scale = 1,
                             heatmap_text_label_color = "#000000",
                             curve_plot_title = NULL,
                             heatmap_plot_title = NULL,
                             Emin = NA,
                             Emax = NA,
                             save_file = FALSE,
                             file_type = "pdf",
                             file_name = NULL,
                             width = 12,
                             height = 6) {
  # 1. Check the input data
  if (!is.list(data)) {
    stop("Input data is not in list format!")
  }
  if (!all(c("drug_pairs", "response") %in% names(data))) {
    stop("Input data should contain at least tow elements: 'drug_pairs' and 
         'response'. Please prepare your data with 'ReshapeData' function.")
  }
  
  # 2. Select the dose response table for plotting.
  if (adjusted) {
    plot_value = "response"
  } else {
    plot_value = "response_origin"
  }

  # 3. Select block
  if (!is.null(block_ids)) {
    no_block_id <- setdiff(block_ids, data$drug_pairs$block_id)
    if (length(no_block_id) > 0) {
      stop(
        "Selected block_ids ",
        paste(unique(no_block_id), sep = ", "),
        " are not found in the input data. Please check the input data."
      )
    }
  } else {
    block_ids <- data$drug_pairs$block_id
  }
  
  plots <- vector(mode = "list", length = length(block_ids))
  names(plots) <- block_ids

  i <- 1
  for (b in block_ids) {

    # ggplot object for heatmap
    dose_response_plot <- Plot2DrugHeatmap(
      data,
      plot_block = b,
      drugs = drugs,
      plot_value = plot_value,
      statistic = statistic,
      title_text_size_scale = text_size_scale,
      summary_statistic = summary_statistic,
      high_value_color = high_value_color,
      low_value_color = low_value_color,
      plot_title = heatmap_plot_title,
      text_label_size_scale = heatmap_text_label_size_scale,
      text_label_color = heatmap_text_label_color
    )
    # plot dose response curve
    
    graphics::plot.new()
    graphics::layout(matrix(c(1, 3, 2, 3), 2, 2, byrow = TRUE))
    
    for (i in drugs){
      PlotDoseResponseCurve(
        data,
        plot_block = b,
        drug_index = i,
        plot_setting = list(
          mgp = c(2, 0.5, 0),
          font.main = 2,
          cex.main = 1 / 12 * 13.5,
          cex.sub = 1
        ),
        plot_subtitle = "",
        grid = grid,
        point_color = point_color,
        curve_color = curve_color,
        Emin = Emin,
        Emax = Emax,
        plot_new = FALSE,
        text_size_scale = text_size_scale,
        plot_title = curve_plot_title
      )
    }
    # vps <- baseViewports()
    # pushViewport()

    print(dose_response_plot, vp = grid::viewport(
      height = grid::unit(1, "npc"),
      width = grid::unit(0.5, "npc"),
      just = c("left", "top"),
      y = 1, x = 0.5
    ))
    # popViewport()
    merge_plot <- grDevices::recordPlot()

    plots[[b]] <- merge_plot
    if (save_file) {
      if (is.null(file_name)) {
        if (adjusted) {
          file <- paste(
            data$drug_pairs[which(data$drug_pairs$block_id == b), 
                            paste0("drug", drugs)],
            "adjusted_dose_response_block",
            b,
            sep = "_"
          )
        } else {
          file <- paste(
            data$drug_pairs[which(data$drug_pairs$block_id == b), 
                            paste0("drug", drugs)],
            "original_dose_response_block",
            b,
            sep = "_"
          )
        }
      } else {
        file <- file_name[i]
        i <- i + 1
      }

      if (!file_type %in% c("jpeg", "bmp", "png", "tiff", "pdf", "svg")) {
        warning(
          "Can not save plot in ", file_type, " format. Avaliable formats are ",
          "'svg', 'jpeg', 'bmp', 'png', 'tiff', and 'pdf'.")
      } else if (file_type == "pdf") {
        grDevices::pdf(paste(file, file_type, sep = "."),
          width = width, height = height
        )
      } else if (file_type == "svg") {
        grDevices::svg(paste(file, file_type, sep = "."),
          width = width, height = height
        )
      } else {
        do.call(file_type, args = list(
          filename = paste(file, file_type, sep = "."),
          width = width, height = height,
          units = "in", res = 600
        ))
      }
      #
      # grDevices::jpeg(file_name, width = 800, height = 600)
      grDevices::replayPlot(merge_plot)
      grDevices::dev.off()
    }
  }
  return(plots)
}


#' Plot Interaction Landscape for Synergy Scores
#'
#' A function to visualize the synergy scores for drug combinations as 2D or 3D
#' interaction landscape over the dose-response matrix.
#'
#' @param data A list object generated by function
#'   \code{\link{CalculateSynergy}}
#' @param type A character value. It specifies the type of the plot. Available
#'   values are:
#'   \itemize{
#'     \item \strong{2D} Visualize 2D interactive landscape with contour plot.
#'     \item \strong{heatmap} Heatmap for synergy scores.
#'     \item \strong{3D} Visualize 3D surface for interactive landscape.
#'   }
#' @param method A character value. It indicates which synergy score to be 
#'   visualized. Available values are "ZIP", "HSA", "Bliss", or "Loewe".
#' @param block_ids A parameter to specify which drug combination if there are 
#'    many drug combinations in the data. By default, it is NULL so that the 
#'    synergy score visualization of all the drug combinations in the data is 
#'    returned.
#' @param drugs A vector of characters or integers with length of 2. It contains
#'   the index for two drugs to plot. For example, \code{c(1, 2)} indicates to
#'   plot "drug1" and "drug2" in the input \code{data}.
#' @param col_range A vector of two integers. They specify the starting and 
#'   ending concentration of the drug on x-axis. Use e.g., c(1, 3) to specify
#'   that only from 1st to 3rd concentrations of the drug on x-axis are used. By
#'   default, it is NULl so all the concentrations are used.
#' @param row_range A vector of two integers. They specify the starting and
#'   ending concentration of the drug on y-axis. Use e.g., c(1, 3) to specify
#'   that only from 1st to 3rd concentrations of the drug on y-axis are used. By
#'   default, it is NULl so all the concentrations are used.
#' @param statistic A character or NULL. It indicates the statistics printed
#'   in the plot while there are replicates in input data. Available values are:
#'   \itemize{
#'     \item \strong{sem} Standard error of mean;
#'     \item \strong{ci} 95\% confidence interval.
#'   }
#'   If it is \code{NULL}, no statistics will be printed. \strong{Note}: It only
#'   works in Heatmap plot.
#' @param summary_statistic A vector of characters or NULL. It indicates the
#'   summary statistics for all the \code{plot_value} in whole combination
#'   matrix. Available values are:
#'   \itemize{
#'     \item \strong{mean} Median value for all the responses or synergy
#'     scores in the matrix;
#'     \item \strong{median} Median value for all the responses or synergy
#'     scores in the matrix;
#'     \item \strong{quantile_90} 90\% quantile. User could change the number to
#'     print different sample quantile. For example quantile_50 equal to median. 
#'   }
#'   If it is \code{NULL}, no statistics will be printed.
#' @param plot_title A character value. It specifies the plot title. If it is
#'   \code{NULL}, the function will automatically generate a title.
#' @param interpolate_len An integer. It specifies how many values need to be
#'   interpolated between two concentrations. It is used to control the 
#'   smoothness of the synergy surface in the contour plot and surface plot.
#'   \strong{Note}: It only works in 2D and 3D plots.
#' @param high_value_color An R color value. It indicates the color for the
#'   high values.
#' @param low_value_color An R color value. It indicates the color for low
#'   values.
#' @param text_size_scale A numeric value. It is used to control the size
#'   of text in the plot. All the text size will multiply by this scale factor.
#' @param heatmap_text_label_size_scale A numeric value. It is used to control
#'   the size of text labels in the heatmap plot. It only works while 
#'   \code{plot_type = "heatmap"}.
#' @param heatmap_text_label_color NULL or an R color value. It is used to
#'   control the color of text labels in the heatmap plot. If it is \code{NULL},
#'   text label will not be shown. It only works while
#'   \code{plot_type = "heatmap"}.
#' @param surface_grid A logical value. It indicates whether to add grids on the 
#'   surface. It only works while \code{plot_type = "3D"}.
#' @param dynamic A logic value. It indicates whether to generate interactive
#'   plot wit package "plotly" or static plot with package "ggplot2"/"lattice".
#' @param display A logic value. It specifies whether to automatically display
#'   plots while calling the function.
#' @param save_file A logic value. It specifies if the interaction landscapes
#'   is saved by calling \link[ggplot2]{ggsave} function ("2D" or "heatmap"
#'   plots) or plot saving function defined by \code{device} ("3D" plots). By
#'   default, it is FALSE. \strong{Note}: It doesn't work while
#'   \code{dynamic = TRUE}, because installation of "Orca" is required for
#'   exporting plotly plots. Please check 
#'   https://plotly.com/r/static-image-export/ for more details.
#' @param file_name A character vector. It indicates the file names. If it is 
#'   not defined by user, a default name will be assigned. \strong{Note}: It
#'   only works while \code{save_file = TRUE}.
#' @param file_path A character vector. It indicates the path to save file.
#'   If it is not defined by user, a default name will be assigned. 
#'   \strong{Note}: It only works while \code{save_file = TRUE}.
#' @param width A numeric value. It indicates the width of the output plot.
#'   \strong{Note}: It only works while \code{save_file = TRUE}.
#' @param height A numeric value. It indicates the height of the output plot.
#'   \strong{Note}: It only works while \code{save_file = TRUE}.
#' @param units A character value. It indicates the units for \code{width} and
#'   \code{height} for saved plots. It is used to set the \code{units}
#'   parameter in function \link[ggplot2]{ggsave} or the function selected by
#'   \code{device} (It will not work on "pdf" and "svg" devices. There units
#'   are always in inch.). \strong{Note}: It only works while 
#'   \code{save_file = TRUE}.
#' @param device A character value. It indicates the device to use for saving 
#'   plots. If \code{type = "3D"}, the corresponding device function in package
#'   "grDevices" will be called to save the plots. If
#'   \code{type = "2D"/"heatmap"}, it will be used to set the parameter
#'   \code{device} in function \link[ggplot2]{ggsave}.
#'   \strong{Note}: It only works while \code{save_file = TRUE}.
#'   
#' @return A list of ggplot objects.
#'    
#' @author
#'   \itemize{
#'     \item Liye He \email{liye.he@helsinki.fi},
#'     \item Shuyu Zheng \email{shuyu.zheng@helsinki.fi}
#'   }
#'
#' @export
#' 
#' @examples
#' data("mathews_screening_data")
#' data <- ReshapeData(mathews_screening_data)
#' data <- CalculateSynergy(data)
#' plots <- PlotSynergy(data, "2D", block_ids = NULL)
PlotSynergy <- function(data,
                        type = "2D",
                        method = "ZIP",
                        block_ids = c(1), 
                        drugs = c(1, 2),
                        row_range = NULL,
                        col_range = NULL,
                        statistic = NULL,
                        summary_statistic = "mean",
                        plot_title = NULL,
                        interpolate_len = 3,
                        high_value_color = "#A90217",
                        low_value_color = "#2166AC",
                        text_size_scale = 1,
                        heatmap_text_label_size_scale = 1,
                        heatmap_text_label_color = "#000000",
                        surface_grid = TRUE,
                        dynamic = FALSE,
                        display = TRUE, 
                        save_file = FALSE,
                        file_name = NULL,
                        file_path = NULL,
                        height = 6,
                        width = 6,
                        units = "in",
                        device = "pdf") {
  # Check input data
  if (!is.list(data)) {
    stop("Input data is not a list format!")
  }
  
  if(is.null(block_ids)) {
    block_ids <- unique(data$drug_pairs$block_id)
  }
  
  # Container for plots
  plots <- vector(mode = "list", length = length(block_ids))
  names(plots) <- block_ids
  
  i <- 1
  for (block in block_ids) {
    drug_pair <- data$drug_pairs[data$drug_pairs$block_id == block, ]
    if (type == "2D") {
      fig <- Plot2DrugContour(
        data = data,
        plot_block = block,
        drugs = drugs,
        dynamic = dynamic,
        plot_value = paste0(method, "_synergy"),
        summary_statistic = summary_statistic,
        plot_title = plot_title,
        interpolate_len = interpolate_len,
        high_value_color = high_value_color,
        low_value_color = low_value_color,
        row_range = row_range,
        col_range = col_range,
        text_size_scale = text_size_scale)
      if (display) {
        fig
      }
    } else if (type == "heatmap") {
      fig <- Plot2DrugHeatmap(
        data = data,
        plot_block = block,
        drugs = drugs,
        statistic = statistic,
        dynamic = dynamic,
        plot_value = paste0(method, "_synergy"),
        summary_statistic = summary_statistic,
        plot_title = plot_title,
        high_value_color = high_value_color,
        low_value_color = low_value_color,
        row_range = row_range,
        col_range = col_range,
        title_text_size_scale = text_size_scale,
        text_label_size_scale = heatmap_text_label_size_scale,
        text_label_color = heatmap_text_label_color)
      if (display) {
        fig
      }
    } else if (type == "3D") {
      fig <- Plot2DrugSurface(
        data = data,
        plot_block = block,
        drugs = drugs,
        interpolate_len = interpolate_len,
        dynamic = dynamic,
        plot_value = paste0(method, "_synergy"),
        summary_statistic = summary_statistic,
        plot_title = plot_title,
        high_value_color = high_value_color,
        low_value_color = low_value_color,
        row_range = row_range,
        col_range = col_range,
        grid = surface_grid,
        text_size_scale = text_size_scale)
      if (display) {
        if (dynamic) {
          fig
        } else {
          print(fig)
        }
      }
    } else {
      stop("The type of plot '", type, "' is not available. Available values
           for parameter 'type' are: 2D, 3D, or heatmap.")
    }
    plots[[block]] <- fig
    
    # Save plots
    if(save_file) {
      if (dynamic) {
        warning("Saving dynamic surface plot from plotly requires installation",
                " of Orca. This function can not save such plot as static ",
                "images, but return the plotly object.",
                "Please check https://plotly.com/r/static-image-export/ to see",
                "how to export plotly plot objects to local directory.")
      } else {
        if (is.null(file_name)) {
          file <-paste(
            c(drug_pair[, paste0("drug", drugs)],
              "synergy",
              block,
              method,
              type),
            collapse = "_"
          )
        } else {
          file <- file_name[i]
          i <- i + 1
        }
        # Set width and height according to plot types
        if (type == "3D") {
          if (!device %in% c("jpeg", "bmp", "png", "tiff", "pdf", "svg")){
            warning("Can not save plot in ", device, " format. Avaliable formats
                are 'svg', 'jpeg', 'bmp', 'png', 'tiff',and 'pdf'.")
          } else if (device  == "pdf") {
            grDevices::pdf(paste(file, device, sep = "."), 
                           width = width, height = height)
          } else if (device == "svg") {
            grDevices::svg(
              paste(file, device, sep = "."), 
              width = width, 
              height = height)
          } else {
            do.call(
              device,
              args = list(
                filename = paste(file, device, sep="."),
                width = width,
                height = height, 
                units = units,
                res = 600)
            )
          }
          grDevices::replayPlot(fig)
          grDevices::dev.off()
        } else {
          ggplot2::ggsave(
            filename = paste(file, device, sep="."),
            plot = plots[[block]],
            path = file_path,
            width = width,
            height = height,
            device = device,
            units = units
          )
        }
      }
    }
  }
  return(plots)
}

Try the synergyfinder package in your browser

Any scripts or data that you put into this service are public.

synergyfinder documentation built on April 4, 2021, 6 p.m.