R/StateHeatmap.R
25d7d3d5
 #' @title Heatmap for featureModules
 #' @description Renders a heatmap for selected featureModules. Cells are
 #'  ordered from those with the lowest probability of the module on the left to
 #'  the highest probability on the right. If more than one module is used, then
 #'  cells will be ordered by the probabilities of the first module only.
 #'  Features are ordered from those with the highest probability in the module
 #'  on the top to the lowest probability on the bottom.
 #' @param counts Integer matrix. Rows represent features and columns represent
 #'  cells. This matrix should be the same as the one used to generate
 #'  `celdaMod`.
 #' @param celdaMod Celda object of class `celda_G` or `celda_CG`.
 #' @param featureModule Integer Vector. The featureModule(s) to display.
 #'  Multiple modules can be included in a vector.
 #' @param topCells Integer. Number of cells with the highest and lowest
 #'  probabilities for this module to include in the heatmap. For example, if
 #'  `topCells` = 50, the 50 cells with the lowest probability and the 50 cells
 #'  with the highest probability for that featureModule will be included. If
 #'  NULL, all cells will be plotted. Default 100.
 #' @param topFeatures Integer. Plot `topFeatures` with the highest probability
 #'  in the featureModule. If NULL, plot all features in the module. Default
 #'  NULL.
fa7bb072
 #' @param normalizedCounts Integer matrix. Rows represent features and columns
0327e448
 #'  represent cells. This matrix should correspond to the one provided for
 #'  `counts`, but should be passed through. If NA, normalize `counts`.
519b7390
 #'  Default NA.
fa7bb072
 #'  `normalizeCounts(counts, "proportion", transformationFun=sqrt)`. Use of this
 #'  parameter is particularly useful for plotting many moduleHeatmaps, where
 #'  normalizing the counts matrix repeatedly would be too time consuming.
25d7d3d5
 #' @param scaleRow Character. Which function to use to scale each individual
 #'  row. Set to NULL to disable. Occurs after normalization and log
 #'  transformation. For example, `scale` will Z-score transform each row.
 #'  Default `scale`.
 #' @param showFeaturenames Logical. Wheter feature names should be displayed.
 #'  Default TRUE.
 #' @return A list containing row and column dendrograms as well as a gtable for
 #'  grob plotting
1079f925
 #' @examples
a49fff03
 #' data(celdaCGSim, celdaCGMod)
a144fef9
 #' moduleHeatmap(celdaCGSim$counts, celdaCGMod)
d7196f24
 #' @importFrom methods .hasSlot
25d7d3d5
 #' @export
 moduleHeatmap <- function(counts,
     celdaMod,
     featureModule = 1,
     topCells = 100,
     topFeatures = NULL,
fa7bb072
     normalizedCounts = NA,
25d7d3d5
     scaleRow = scale,
     showFeaturenames = TRUE) {
ca5fb59d
 
25d7d3d5
     # Input checks
     if (is.null(counts) || !is.matrix(counts) & !is.data.frame(counts)) {
         stop("'counts' should be a numeric count matrix")
00248d05
     }
ca5fb59d
     if (is.null(celdaMod) || !methods::is(celdaMod, "celda_G") &
25d7d3d5
         !methods::is(celdaMod, "celda_CG")) {
         stop("'celdaMod' should be an object of class celda_G or celda_CG")
     }
     compareCountMatrix(counts, celdaMod)
ca5fb59d
 
25d7d3d5
     # factorize counts matrix
     factorizedMatrix <- factorizeMatrix(celdaMod = celdaMod, counts = counts)
ca5fb59d
 
25d7d3d5
     # take topRank
ca5fb59d
     if (!is.null(topFeatures) && (is.numeric(topFeatures)) |
25d7d3d5
         is.integer(topFeatures)) {
         topRanked <- topRank(matrix = factorizedMatrix$proportions$module,
             n = topFeatures)
     } else {
b6cf56ae
         topRanked <- topRank(matrix = factorizedMatrix$proportions$module,
25d7d3d5
             n = nrow(factorizedMatrix$proportions$module))
     }
ca5fb59d
 
25d7d3d5
     # filter topRank using featureModule into featureIndices
ca5fb59d
     featureIndices <- lapply(featureModule,
25d7d3d5
         function(module) {
             topRanked$index[[module]]
         })
     featureIndices <- unlist(featureIndices)
ca5fb59d
 
25d7d3d5
     # Determine cell order from factorizedMatrix$proportions$cell
     cellStates <- factorizedMatrix$proportions$cell
     cellStates <- cellStates[featureModule, , drop = FALSE]
ca5fb59d
 
     singleModule <- cellStates[1, ]
25d7d3d5
     singleModuleOrdered <- order(singleModule, decreasing = TRUE)
ca5fb59d
 
25d7d3d5
     if (!is.null(topCells)) {
         if (topCells * 2 < ncol(cellStates)) {
             cellIndices <- c(
                 utils::head(singleModuleOrdered, n = topCells),
                 utils::tail(singleModuleOrdered, n = topCells))
         } else {
             cellIndices <- singleModuleOrdered
         }
     } else {
         cellIndices <- singleModuleOrdered
     }
ca5fb59d
 
25d7d3d5
     cellIndices <- rev(cellIndices)
4b885087
     if (is.na(normalizedCounts)) {
ca5fb59d
       normCounts <- normalizeCounts(counts, normalize = "proportion",
2e877ffe
           transformationFun = sqrt)
25d7d3d5
     } else {
fa7bb072
         normCounts <- normalizedCounts
25d7d3d5
     }
ca5fb59d
 
25d7d3d5
     # filter counts based on featureIndices
     filteredNormCounts <-
         normCounts[featureIndices, cellIndices, drop = FALSE]
ca5fb59d
 
25d7d3d5
     filteredNormCounts <-
         filteredNormCounts[rowSums(filteredNormCounts > 0) > 0, , drop = FALSE]
ca5fb59d
 
06b0c870
     geneIx <- match(rownames(filteredNormCounts), matrixNames(celdaMod)$row)
     cellIx <- match(colnames(filteredNormCounts), matrixNames(celdaMod)$column)
ca5fb59d
     zToPlot <- c()
25d7d3d5
     anno_cell_colors <- NULL
     if (class(celdaMod)[1] == "celda_CG") {
         if (methods::.hasSlot(celdaMod, "clusters")) {
             cell <-
06b0c870
               distinctColors(length(unique(clusters(celdaMod)$z)))[
                   sort(unique(clusters(celdaMod)$z[cellIx]))]
             names(cell) <- sort(unique(clusters(celdaMod)$z[cellIx]))
25d7d3d5
             anno_cell_colors <- list(cell = cell)
06b0c870
             zToPlot <- clusters(celdaMod)$z[cellIndices]
25d7d3d5
         }
     }
ca5fb59d
 
25d7d3d5
     plotHeatmap(
         filteredNormCounts,
ca5fb59d
         z = zToPlot,
06b0c870
         y = clusters(celdaMod)$y[geneIx],
ca5fb59d
         scaleRow = scaleRow,
         colorScheme = "divergent",
         showNamesFeature = showFeaturenames,
         clusterFeature = FALSE,
         clusterCell = FALSE,
         annotationColor = anno_cell_colors)
9737c96f
 }