R/grin.barplt.R

Defines functions grin.barplt

Documented in grin.barplt

#' GRIN Lesion Stacked Bar Plot
#'
#' @description
#' Generates a horizontal stacked bar plot showing the number of patients
#' affected by different genomic lesion types across a user-specified set of
#' genes, based on GRIN analysis results.
#'
#' @usage
#' grin.barplt(grin.res,
#'             count.genes,
#'             lsn.colors = NULL)
#'
#' @param grin.res GRIN results object, typically the output from the
#' `grin.stats` function.
#' @param count.genes A character vector of gene names to include in the plot.
#' Only genes present in the GRIN results are displayed.
#' @param lsn.colors A named vector of colors assigned to lesion types. If
#' `NULL`, colors are automatically assigned using `default.grin.colors`.
#'
#' @details
#' The function extracts the number of patients affected by each lesion type
#' from `grin.res$gene.hits` for the genes specified in `count.genes`.
#'
#' Each horizontal bar represents a gene and is divided into segments
#' corresponding to different lesion types. The length of each segment
#' represents the number of patients affected by that lesion type, and the
#' number of affected patients is displayed within each non-zero segment.
#'
#' Genes are ordered according to the total number of lesion-type-specific
#' affected-patient counts across the lesion categories displayed in the plot.
#' This visualization can be used to compare the relative burden and
#' distribution of different genomic lesion types across candidate driver
#' genes or other genes of interest.
#'
#' @return
#' A `ggplot` object containing a horizontal stacked bar plot. Each bar
#' represents a selected gene, bar segments represent lesion types, and segment
#' lengths represent the corresponding number of affected patients.
#'
#' @export
#'
#' @importFrom dplyr group_by summarize arrange
#' @importFrom ggplot2 ggplot aes geom_bar geom_text scale_fill_manual position_stack labs coord_flip theme_classic theme element_text
#' @importFrom utils stack
#' @importFrom stats reorder
#' @importFrom magrittr %>%
#'
#' @references
#' Cao, X., Elsayed, A. H., & Pounds, S. B. (2023). Statistical Methods
#' Inspired by Challenges in Pediatric Cancer Multi-omics.
#'
#' @author
#' Abdelrahman Elsayed \email{abdelrahman.elsayed@stjude.org}
#'
#' @seealso \code{\link{grin.stats}},
#' \code{\link{default.grin.colors}}
#'
#' @examples
#' data(lesion_data)
#' data(hg38_gene_annotation)
#' data(hg38_chrom_size)
#'
#' # Run GRIN analysis
#' grin.results <- grin.stats(lesion_data,
#'                            hg38_gene_annotation,
#'                            hg38_chrom_size)
#'
#' # Define genes of interest to include in the stacked bar plot
#' count.genes <- c("TAL1", "FBXW7", "PTEN", "IRF8", "NRAS",
#'                  "BCL11B", "MYB", "LEF1", "RB1", "MLLT3",
#'                  "EZH2", "ETV6", "CTCF", "JAK1", "KRAS",
#'                  "RUNX1", "IKZF1", "KMT2A", "RPL11", "TCF7",
#'                  "WT1", "JAK2", "JAK3", "FLT3")
#'
#' # Generate stacked bar plot showing the distribution of lesion types
#' # across the selected genes
#' grin.barplt(grin.results,
#'             count.genes)
#'
grin.barplt=function(grin.res,        # GRIN results (output of the grin.stats function)
                     count.genes,     # vector with gene names of a list of genes to be added to the bar plot
                     lsn.colors=NULL) # Lesion colors (If not provided by the user, colors will be automatically assigned using default.grin.colors function).
{

  if (!is.list(grin.res))
    stop("'grin.res' must be GRIN results returned by grin.stats().")

  if (!all(c("gene.hits","lsn.index") %in% names(grin.res)))
    stop("'grin.res' must contain 'gene.hits' and 'lsn.index'.")

  hits=grin.res$gene.hits

  if (!"gene.name" %in% colnames(hits))
    stop("'grin.res$gene.hits' must contain a 'gene.name' column.")

  if (missing(count.genes) ||
      is.null(count.genes) ||
      length(count.genes)==0 ||
      anyNA(count.genes) ||
      any(count.genes==""))
    stop("'count.genes' must contain at least one valid gene name.")

  count.genes=unique(as.character(count.genes))

  # identify lesion types and extract count data from GRIN results table

  lsn.types=sort(unique(as.character(grin.res$lsn.index$lsn.type)))
  count.names=paste0("nsubj.",lsn.types)

  if (!all(count.names %in% colnames(hits)))
    stop(
      "'grin.res$gene.hits' does not contain patient-count columns for all lesion types."
    )

  count.data=data.frame(
    gene.name=hits$gene.name,
    hits[,count.names,drop=FALSE],
    check.names=FALSE
  )

  # limit the bar plot to the list of genes of interest

  selected.count=count.data[count.data$gene.name %in% count.genes,,drop=FALSE]

  if (nrow(selected.count)==0)
    stop("None of the genes specified in 'count.genes' were found in the GRIN results.")

  names(selected.count) <- sub("^nsubj\\.", "", names(selected.count))

  count.clms=selected.count[,-1,drop=FALSE]
  count.clms=utils::stack(count.clms)

  nsubj.data=cbind.data.frame(
    gene.name=rep(selected.count$gene.name,times=length(lsn.types)),
    nsubj=count.clms$values,
    lsn.type=count.clms$ind
  )

  nsubj.data=nsubj.data[
    !is.na(nsubj.data$nsubj) &
      nsubj.data$nsubj>0,
  ]

  if (nrow(nsubj.data)==0)
    stop("No affected patients were found for the selected genes.")

  # assign colors for lesion groups automatically if not provided by the user

  if (is.null(lsn.colors))
  {
    lsn.colors=default.grin.colors(lsn.types)
  } else {

    if (is.null(names(lsn.colors)))
      stop("'lsn.colors' must be a named vector with names corresponding to lesion types.")

    missing.colors=setdiff(lsn.types,names(lsn.colors))

    if (length(missing.colors)>0)
      stop(
        "'lsn.colors' does not contain colors for the following lesion types: ",
        paste(missing.colors,collapse=", "),
        "."
      )

    lsn.colors=lsn.colors[lsn.types]
  }

  # summarize the df

  nsubj.data <- nsubj.data %>%
    dplyr::group_by(gene.name, lsn.type) %>%
    dplyr::summarize(nsubj = sum(nsubj), .groups = "drop") %>%
    dplyr::arrange(gene.name, lsn.type)

  # generate stacked bar plot for number of patients affected by each type of lesions in the list of genes of interest

  plot=ggplot2::ggplot(
    data=nsubj.data,
    ggplot2::aes(x=stats::reorder(gene.name,nsubj,sum))
  ) +
    ggplot2::geom_bar(
      ggplot2::aes(y=nsubj,fill=lsn.type),
      position=ggplot2::position_stack(reverse=TRUE),
      stat="identity",
      width=.5
    ) +
    ggplot2::scale_fill_manual(values=lsn.colors) +
    ggplot2::geom_text(
      ggplot2::aes(y=nsubj,label=nsubj,group=lsn.type),
      position=ggplot2::position_stack(vjust=0.5,reverse=TRUE),
      color="white",
      size=3.5
    ) +
    ggplot2::labs(
      x="Gene Name",
      y="Count",
      fill="Lesion Type"
    ) +
    ggplot2::coord_flip() +
    ggplot2::theme_classic()

  final.plt=plot+
    ggplot2::theme(text=ggplot2::element_text(size=15))

  return(final.plt)
}

Try the GRIN2 package in your browser

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

GRIN2 documentation built on Aug. 22, 2026, 5:09 p.m.