a b/R/scAI_plotting.R
1
2
#' ggplot theme in scAI
3
#'
4
#' @return
5
#' @export
6
#'
7
#' @examples
8
#' @importFrom ggplot2 theme_classic element_rect theme element_blank element_line element_text
9
scAI_theme_opts <- function() {
10
  theme(strip.background = element_rect(colour = "white", fill = "white")) +
11
    theme_classic() +
12
    theme(panel.border = element_blank()) +
13
    theme(axis.line.x = element_line(color = "black")) +
14
    theme(axis.line.y = element_line(color = "black")) +
15
    theme(panel.grid.minor.x = element_blank(), panel.grid.minor.y = element_blank()) +
16
    theme(panel.grid.major.x = element_blank(), panel.grid.major.y = element_blank()) +
17
    theme(panel.background = element_rect(fill = "white")) +
18
    theme(legend.key = element_blank()) + theme(plot.title = element_text(size = 10, face = "bold", hjust = 0.5))
19
}
20
21
22
23
#' Visualize the inferred biologically relevant factors
24
#' We plot the heatmap of the three learned low-rank matrices using hierarchical clustering.
25
#' @param object scAI object
26
#' @param color.by the name of the variable in object.pData; defining cell groups (not necessary)
27
#' @param colors.use defined colors of the cell groups
28
#' @param do.sampling whether perform sampling of loci when generating heatmap of the loci-factor matrix
29
#'
30
#' @return
31
#' @export
32
#'
33
#' @examples
34
#' @importFrom ComplexHeatmap Heatmap HeatmapAnnotation draw
35
#' @importFrom stats setNames
36
#' @importFrom grid grid.grabExpr grid.newpage pushViewport grid.draw unit gpar viewport popViewport
37
lmHeatmap <- function(object, color.by, colors.use = NULL,do.sampling = T ){
38
39
  H <- as.matrix(object@fit$H)
40
  H <- sweep(H,2,colSums(H),FUN = `/`)
41
42
  label <- object@pData[[color.by]]
43
  df<- data.frame(group = label); rownames(df) <- colnames(H)
44
45
  if (is.null(colors.use)) {
46
    colors.use <- scPalette(length(unique(label)))
47
  }
48
  cell.cols.assigned <- setNames(colors.use, unique(as.character(df$group)))
49
  col_annotation <- HeatmapAnnotation(df = df, col = list(group = cell.cols.assigned),annotation_name_side = "left",simple_anno_size = grid::unit(0.2, "cm"))
50
  colormap = structure(rev(brewer.pal(9,"RdBu")))
51
  H = H + runif(length(H), min = -0.5, max = 0.5)*1e-5
52
  ht1 = Heatmap(H,name = "H",
53
                clustering_method_columns = "average",
54
                clustering_distance_columns = "euclidean",
55
                col = colormap,
56
                cluster_rows = FALSE, show_column_names = FALSE, show_row_names = TRUE, row_names_side = "left", row_names_rot = 0,row_names_gp = gpar(fontsize = 10),
57
                width = unit(6, "cm"), height = unit(4, "cm"),
58
                top_annotation = col_annotation,
59
                column_title = "Cell loading matrix",
60
                column_title_gp = gpar(fontsize = 10, fontface = "bold"),
61
                heatmap_legend_param = list(title = "H", at = c(0, 0.5, 1),legend_width = unit(0.0001, "cm"),legend_height = unit(2, "cm"),labels_gp = gpar(font = 6))
62
  )
63
64
65
  # heatmap for W1
66
  W1 <- as.matrix(object@fit$W[[1]])
67
  W1 <- sweep(W1,1,rowSums(W1),FUN = `/`)
68
  W1[is.na(W1)] <- 0
69
  colormap = structure(rev(brewer.pal(11,"RdBu")))
70
  W1 = W1 + runif(length(W1), min = -0.5, max = 0.5)*1e-5
71
  ht2 = Heatmap(W1,name = "W1",
72
                clustering_method_rows = "average",
73
                col = colormap,
74
                cluster_columns = FALSE, show_column_names = T, show_row_names = F, column_names_gp = gpar(fontsize = 10),
75
                width = unit(4, "cm"), height = unit(8, "cm"),
76
                column_title = "Gene loading matrix (scRNA-seq)",
77
                column_title_gp = gpar(fontsize = 10, fontface = "bold"),
78
                row_title = "Genes", row_title_rot = 90,row_names_gp = gpar(fontsize = 10),
79
                heatmap_legend_param = list(title = "W1", at = c(0, 0.5, 1),legend_width = unit(0.0001, "cm"),legend_height = unit(2, "cm"),labels_gp = gpar(font = 6))
80
  )
81
82
  # heatmap for W1
83
  W2 <- as.matrix(object@fit$W[[2]])
84
  W2 <- sweep(W2,1,rowSums(W2),FUN = `/`)
85
  W2[is.na(W2)] <- 0
86
  if (nrow(W2) > 5000 & do.sampling) {
87
    loci.use <- sample(1:nrow(W2), 5000, replace=F)
88
    W2 <- W2[sort(loci.use),]
89
  }
90
91
  colormap = structure(rev(brewer.pal(9,"Spectral")))
92
  W2 = W2 + runif(length(W2), min = -0.5, max = 0.5)*1e-5
93
  ht3 = Heatmap(W2,name = "W2",
94
                clustering_method_rows = "average",
95
                col = colormap,
96
                cluster_columns = FALSE, show_column_names = T, show_row_names = F, column_names_gp = gpar(fontsize = 10),
97
                width = unit(4, "cm"), height = unit(8, "cm"),
98
                column_title = "Locus loading matrix (scATAC-seq)",
99
                column_title_gp = gpar(fontsize = 10, fontface = "bold"),
100
                row_title = "Loci", row_title_rot = 90,row_names_gp = gpar(fontsize = 10),
101
                heatmap_legend_param = list(title = "W2", at = c(0, 0.5, 1),legend_width = unit(0.0001, "cm"),legend_height = unit(2, "cm"),labels_gp = gpar(font = 6))
102
  )
103
  gb_ht1 = grid::grid.grabExpr(draw(ht1))
104
  gb_ht2 = grid::grid.grabExpr(draw(ht2))
105
  gb_ht3 = grid::grid.grabExpr(draw(ht3))
106
  grid::grid.newpage()
107
  grid::pushViewport(viewport(x = 0.2,y = 1, width = 0.5, height = 0.3, just = c("left", "top")))
108
  grid::grid.draw(gb_ht1)
109
  grid::popViewport()
110
111
  grid::pushViewport(viewport(x = 0.1, y = 0.1, width = 0.2, height = 0.5, just = c("left", "bottom")))
112
  grid::grid.draw(gb_ht2)
113
  grid::popViewport()
114
115
  grid::pushViewport(viewport(x = 0.5, y = 0.1, width = 0.2, height = 0.5, just = c("left", "bottom")))
116
  grid::grid.draw(gb_ht3)
117
  grid::popViewport()
118
}
119
120
121
122
#' visualize cells in 2D-dimensional space
123
#'
124
#' @param object scAI object
125
#' @param cell_coords 2D embedding coordinates of cells
126
#' @param color.by the name of the variable in pData, defining cell groups, cells are colored based on the labels
127
#' @param labels.order defining the factor level of cell groups
128
#' @param colors.use defining the color for each cell group
129
#' @param brewer.use use RColorBrewer palette instead of default ggplot2 color
130
#' @param xlabel label of x-axis
131
#' @param ylabel label of y-axis
132
#' @param title main title of the plot
133
#' @param label.size font size of the legend
134
#' @param cell.size size of the dots
135
#' @param font.size font size
136
#' @param do.label label the cluster in 2D space
137
#' @param show.legend whether show the legend
138
#' @param show.axes whether show the axes
139
#'
140
#' @return ggplot2 object with 2D plot
141
#' @export
142
#'
143
#' @examples
144
#' @importFrom ggplot2 ggplot geom_point aes scale_color_manual facet_wrap element_text theme guides element_blank element_rect geom_line
145
#' @importFrom ggrepel geom_text_repel
146
#' @importFrom dplyr %>% summarize
147
#' @importFrom RColorBrewer brewer.pal
148
#' @importFrom grDevices colorRampPalette
149
#' @importFrom stats median
150
cellVisualization <- function(object, cell_coords, color.by, labels.order = NULL, colors.use = NULL, brewer.use = FALSE,
151
                              xlabel = "UMAP1", ylabel = "UMAP2", title = NULL,
152
                              label.size = 4, cell.size = 0.3, font.size = 10, do.label = F, show.legend = T, show.axes = T) {
153
154
155
    labels <- object@pData[[color.by]]
156
157
    if (is.null(labels.order) == FALSE) {
158
        labels <- factor(labels, levels = labels.order)
159
    } else if (class(labels) != "factor") {
160
        labels <- as.factor(labels)
161
    }
162
163
    df <- data.frame(x = cell_coords[, 1], y = cell_coords[, 2], group = labels)
164
165
    gg <- ggplot(data = df, aes(x, y)) +
166
    geom_point(aes(colour = labels), size = cell.size) + scAI_theme_opts() +
167
    theme(text = element_text(size = 10)) + labs(title = title, x = xlabel, y = ylabel) +
168
    guides(colour = guide_legend(override.aes = list(size = label.size))) +
169
    theme(legend.title = element_blank())
170
    numCluster = length(unique((labels)))
171
    if (is.null(colors.use)) {
172
        colors <- scPalette(numCluster)
173
        names(colors) <- levels(labels)
174
        gg <- gg + scale_color_manual(values = colors)
175
        if (brewer.use) {
176
            if (numCluster < 9) {
177
                colors <- RColorBrewer::brewer.pal(numCluster, "Set1")
178
            } else {
179
                colors <- grDevices::colorRampPalette(RColorBrewer::brewer.pal(9, "Set1"))(numCluster)
180
            }
181
            names(colors) <- levels(labels)
182
            gg <- gg + scale_color_manual(values = colors)
183
        }
184
    } else {
185
        gg <- gg + scale_color_manual(values = colors.use)
186
    }
187
188
    if (do.label) {
189
        centers <- df %>% dplyr::group_by(group) %>% dplyr::summarize(x = median(x = x), y = median(x = y))
190
        gg <- gg + ggrepel::geom_text_repel(data = centers, mapping = aes(x, y, label = group), size = label.size)
191
    }
192
193
    if (!show.legend) {
194
        gg <- gg + theme(legend.position = "none")
195
    }
196
197
    if (!show.axes) {
198
        gg <- gg + theme_void()
199
    }
200
    gg
201
}
202
203
#' Generate colors from a customed color palette
204
#'
205
#' @param n number of colors
206
#'
207
#' @return A color palette for plotting
208
#' @importFrom grDevices colorRampPalette
209
#'
210
#' @export
211
#'
212
scPalette <- function(n) {
213
    colorSpace <- c(
214
    '#E41A1C',
215
    '#377EB8',
216
    '#4DAF4A',
217
    '#984EA3',
218
    '#F29403',
219
    '#F781BF',
220
    '#BC9DCC',
221
    '#A65628',
222
    '#54B0E4',
223
    '#222F75',
224
    '#1B9E77',
225
    '#B2DF8A',
226
    '#E3BE00',
227
    '#FB9A99',
228
    '#E7298A',
229
    '#910241',
230
    '#00CDD1',
231
    '#A6CEE3',
232
    '#CE1261',
233
    '#5E4FA2',
234
    '#8CA77B',
235
    '#00441B',
236
    '#DEDC00',
237
    '#B3DE69',
238
    '#8DD3C7',
239
    '#999999'
240
    )
241
    if (n <= length(colorSpace)) {
242
        colors <- colorSpace[1:n]
243
    } else {
244
        colors <- grDevices::colorRampPalette(colorSpace)(n)
245
    }
246
    return(colors)
247
}
248
249
250
#' Ranking the features (genes/loci) and show the top markers in each factor
251
#'
252
#' @param object scAI object
253
#' @param assay define an assay to show, e.g., assay = "RNA"
254
#' @param factor.show a set of factors to show
255
#' @param feature.show a vector of the features that are labeled on the plot
256
#' @param ncol number of columns in plot
257
#' @param feature.show.names instead of the default name in feature.show, one can show the manual feature name such as the enriched motif
258
#' @param top.p showing the features in top ranking
259
#' @param features.diff a table includes the differential features, returned from identifyfactorMakrers.R
260
#' @param ylabel ylabel shown on the y-axis
261
#'
262
#' @return
263
#' @export
264
#'
265
#' @examples
266
featureRankingPlot <- function(object, assay, factor.show = NULL, ncol = NULL, feature.show = NULL, feature.show.names = NULL, top.p = 0.5, features.diff = NULL, ylabel = "Weight") {
267
    W <- object@fit$W[[assay]]
268
    features <- rownames(W)
269
    if (!is.null(factor.show)) {
270
        W <- W[, factor.show]
271
    }
272
    K = ncol(W)
273
    W <- sweep(W,1,rowSums(W),FUN = `/`)
274
    W[is.na(W)] <- 0
275
276
    Wg <- vector("list", K)
277
    for (i in 1:K) {
278
        W_order <- sort(W[,i],decreasing=F, index.return = T)
279
        features_ordered <- features[W_order$ix]
280
        if (!is.null(features.diff)) {
281
            features.diffi <- as.character(features.diff$features[features.diff$factors == i])
282
        }else {
283
            features.diffi <- as.character(features)
284
        }
285
286
        if (!is.null(feature.show)) {
287
            features.diffi <- intersect(features.diffi, feature.show)
288
        }
289
        idx <- match(features.diffi, features_ordered)
290
        data_show <- matrix(0, nrow(W), 1); data_show[idx] <- 1
291
        if (!is.null(top.p) & top.p < 1) {
292
            idx_bottom <- seq_len(floor((1-top.p)*nrow(W))); data_show[idx_bottom] <- 0
293
        }
294
295
        Wg[[i]] <- cbind(Weight =  as.numeric(W_order$x), factor = colnames(W)[i], Ranking = seq_len(nrow(W)), Show = as.numeric(data_show), Genes = features_ordered)
296
    }
297
    data <- Wg[[1]]
298
    for (i in 2:K) {
299
        data <- rbind(data, Wg[[i]])
300
    }
301
302
    df <- as.data.frame(data, stringsAsFactors=FALSE)
303
    colnames(df) <- c("Weight", "factor", "Ranking", "Show","Genes")
304
    df$factor <- paste('Factor',df$factor, sep = " ")
305
    df$Weight <- as.numeric(as.character(df$Weight))
306
    df$Ranking <- as.numeric(as.character(df$Ranking))
307
    df$Show <- as.numeric(as.character(df$Show))
308
309
    if (!is.null(feature.show.names)) {
310
        idx <- which(df$Genes %in% feature.show)
311
        df$Genes[idx] <- feature.show.names
312
    }
313
314
    data_topFeature = df[df$Show == 1,]
315
316
    gg <- ggplot(df, aes(Ranking, Weight)) +
317
    geom_line(colour = "grey80",size = 1) + facet_wrap(~ factor, ncol = ncol, scales = "free")+
318
    scAI_theme_opts()+
319
    theme(text = element_text(size = 10), axis.text.x = element_blank(),axis.ticks.x = element_blank()) +
320
    theme(strip.background = element_rect(fill="grey80")) +
321
    ylab(ylabel) +
322
    geom_point(size = 3, shape = 1, data = data_topFeature) +
323
    ggrepel::geom_text_repel(aes(label = Genes), data = data_topFeature, segment.color = "grey50", segment.alpha = 1,
324
    direction = "y",nudge_x = -150, hjust = 1,size = 3,segment.size = 0.3) # hjust = 1 for right-align
325
    gg
326
}
327
328
329
330
331
332
#' VscAI visualize the genes, loci and factors that separate cell states on two dimensions alongside the cells
333
#'
334
#' @param object scAI object
335
#' @param gene.use embedded genes
336
#' @param loci.use embedded loci
337
#' @param loci.use.names alternative names of embedded loci, e.g, the corresponding motif
338
#' @param color.by the name of the variable in pData, defining cell groups, cells are colored based on the labels
339
#' @param labels.order defining the factor level
340
#' @param colors.use defining the color for each cell group
341
#' @param brewer.use use RColorBrewer palette instead of default ggplot2 color
342
#' @param xlabel label of x-axis
343
#' @param ylabel label of y-axis
344
#' @param title main title of the plot
345
#' @param label.size font size of the legend
346
#' @param cell.size size of the dots
347
#' @param font.size size of font
348
#' @param do.label label the cluster in 2D space
349
#' @param show.legend whether show the legend
350
#' @param show.axes whether show the axes
351
#'
352
#' @return ggplot2 object with 2D plot
353
#' @export
354
#'
355
#' @examples
356
#' @importFrom ggplot2 guide_legend guides labs element_text theme xlab ylab scale_fill_manual scale_color_manual scale_shape_manual scale_size_manual
357
358
VscAIplot <- function(object, gene.use, loci.use, loci.use.names, color.by,
359
                      labels.order = NULL, colors.use = NULL, brewer.use = FALSE, xlabel = "VscAI1",
360
                      ylabel = "VscAI2", title = NULL, label.size = 3, cell.size = 0.3, font.size = 10,
361
                      do.label = T, show.legend = T, show.axes = T) {
362
363
  cell_coords <- object@embed$VscAI$cells
364
  factor_coords <- object@embed$VscAI$factors
365
  gene_coords <- object@embed$VscAI$genes
366
  loci_coords <- object@embed$VscAI$loci
367
368
  labels <- object@pData[[color.by]]
369
370
  if (is.null(labels.order) == FALSE) {
371
    labels <- factor(labels, levels = labels.order)
372
  } else if (class(labels) != "factor") {
373
    labels <- as.factor(labels)
374
  }
375
376
  df.cell <- data.frame(x = cell_coords[, 1], y = cell_coords[, 2], group = labels)
377
378
  gg <- ggplot(data = df.cell, aes(x, y)) +
379
    geom_point(aes(colour = labels), size = cell.size) +
380
    scAI_theme_opts() + theme(text = element_text(size = 10)) +
381
    labs(title = title) + xlab(xlabel) + ylab(ylabel) +
382
    guides(colour = guide_legend(override.aes = list(size = 3))) +
383
    guides(fill = guide_legend(title = "Cell groups")) + scale_fill_manual("Cell groups")
384
385
  numCluster = length(unique((labels)))
386
  if (is.null(colors.use)) {
387
    colors <- scPalette(numCluster)
388
    names(colors) <- levels(labels)
389
    gg <- gg + scale_color_manual(values = colors)
390
    if (brewer.use) {
391
      if (numCluster < 9) {
392
        colors <- RColorBrewer::brewer.pal(numCluster, "Set1")
393
      } else {
394
        colors <- grDevices::colorRampPalette(RColorBrewer::brewer.pal(9, "Set1"))(numCluster)
395
      }
396
      names(colors) <- levels(labels)
397
      gg <- gg + scale_color_manual(values = colors)
398
    }
399
  } else {
400
    gg <- gg + scale_color_manual(values = colors.use)
401
  }
402
403
404
  # embedding factors
405
  if (do.label) {
406
    df.factor <- data.frame(factor_coords, label.name = paste0("F", seq_len(length(factor_coords[, 1]))), Embedding = "Factors")
407
    df.features <- df.factor
408
  }
409
410
  # embedding genes
411
  if (!is.null(gene.use)) {
412
    df.genes <- data.frame(gene_coords[gene.use, ], label.name = gene.use,
413
                           Embedding = "Genes")
414
    df.features <- rbind(df.features, df.genes)
415
  }
416
417
  # embedding loci
418
  if (!is.null(loci.use)) {
419
    df.loci <- data.frame(loci_coords[loci.use, ], label.name = loci.use.names,
420
                          Embedding = "Loci")
421
    df.features <- rbind(df.features, df.loci)
422
  }
423
424
425
  gg <- gg + geom_point(data = df.features, aes(x, y, shape = Embedding, size = Embedding)) +
426
    scale_shape_manual(values = c(1, 16, 5)) +
427
    scale_size_manual(values = c(3, 2, 2)) +
428
    ggrepel::geom_text_repel(data = df.features, aes(label = label.name), size = label.size,
429
                             segment.color = "grey50", segment.size = 0.3, box.padding = grid::unit(0.35, "lines"), point.padding = grid::unit(0.2, "lines"))
430
431
432
  if (!show.legend) {
433
    gg <- gg + theme(legend.position = "none")
434
  }
435
436
  if (!show.axes) {
437
    gg <- gg + theme_void()
438
  }
439
  gg
440
}
441
442
443
444
#' visualize cells on the 2D space with gene expression or chromatian accessibility overlayed
445
#'
446
#' @param object scAI object
447
#' @param assay define an assay to show, e.g., assay = "RNA"
448
#' @param feature.use a vector of features
449
#' @param method dimensional reduction method, e.g., VscAI, tsne, umap
450
#' @param nCol number of columns of the plot
451
#' @param xlabel label shown on x-axis
452
#' @param ylabel label shown on y-axis
453
#' @param cell.size the size of points (cells)
454
#' @param show.legend whether show individual legend
455
#' @param show.legend.combined  whether just show one legend
456
#' @param show.axes whether show the axes
457
#'
458
#' @return
459
#' @export
460
#'
461
#' @examples
462
#' @importFrom ggplot2 guide_colorbar scale_colour_gradientn
463
featureVisualization <- function(object, assay, feature.use, method = "VscAI", nCol = NULL,
464
                                 xlabel = "VscAI1", ylabel = "VscAI2", cell.size = 0.3,
465
                                 show.legend = T, show.legend.combined = F, show.axes = T) {
466
467
  data <- object@norm.data[[assay]]
468
469
  feature.use <- intersect(feature.use, rownames(data))
470
  data.use <- data[feature.use, ]
471
472
  if (is.null(nCol)) {
473
    if (length(feature.use) > 9) {
474
      nCol <- 4
475
    } else {
476
      nCol <- min(length(feature.use), 3)
477
    }
478
  }
479
  if (method == "VscAI") {
480
    cell_coords <- object@embed$VscAI$cells
481
  } else if (method == "tsne") {
482
    cell_coords <- object@embed$tsne
483
    xlabel = "tSNE1"
484
    ylabel = "tSNE2"
485
  } else if (method == "umap") {
486
    cell_coords <- object@embed$umap
487
    xlabel = "UMAP1"
488
    ylabel = "UMAP2"
489
  }
490
491
  colormap <- colorRampPalette(c("#FFFFEF", "#FFFF00", "#FF0000", "#0A0000"))(64)
492
  colormap[1] <- "#E5E5E5"
493
494
  df <- data.frame(x = cell_coords[, 1], y = cell_coords[, 2])
495
  numFeature = length(feature.use)
496
  gg <- vector("list", numFeature)
497
  for (i in seq_len(numFeature)) {
498
    feature.name <- feature.use[i]
499
    df$feature.data <- data.use[i, ]
500
    g <- ggplot(data = df, aes(x, y)) +
501
      geom_point(aes(colour = feature.data), size = cell.size) +
502
      scale_colour_gradientn(colours = colormap, guide = guide_colorbar(title = NULL, ticks = T, label = T, barwidth = 0.5), na.value = "lightgrey") +
503
      labs(title = feature.name) + scAI_theme_opts() +
504
      theme(text = element_text(size = 10), legend.key.height = grid::unit(0.15, "in")) + labs(x = xlabel, y = ylabel)
505
506
    if (!show.legend) {
507
      g <- g + theme(legend.position = "none")
508
    }
509
510
    if (show.legend.combined & i == numFeature) {
511
      g <- g + theme(legend.position = "right", legend.key.height = grid::unit(0.15, "in"), legend.key.width = grid::unit(0.5, "in"), legend.title = NULL)
512
    }
513
514
    if (!show.axes) {
515
      g <- g + theme_void()
516
    }
517
    gg[[i]] <- g
518
  }
519
  gg.combined <- cowplot::plot_grid(plotlist = gg, ncol = nCol)
520
521
  gg.combined
522
}
523
524
525
#' visualize cells on the 2D space with features overlayed
526
#'
527
#' @param object scAI object
528
#' @param feature.use a vector of features
529
#' @param feature.scores a matrix containing the feature scores
530
#' @param method dimensional reduction method, e.g., VscAI, tsne, umap
531
#' @param colormap RColorbrewer palette to use
532
#' @param color.direction Sets the order of colours in the scale. If 1, the default, colours are as output by RColorBrewer::brewer.pal(). If -1, the order of colours is reversed.
533
#' @param nCol number of columns of the plot
534
#' @param xlabel label shown on x-axis
535
#' @param ylabel label shown on y-axis
536
#' @param cell.size the size of points (cells)
537
#' @param show.legend whether show individual legend
538
#' @param show.legend.combined  whether just show one legend
539
#' @param show.axes whether show the axes
540
#'
541
#' @return
542
#' @export
543
#'
544
#' @examples
545
#' @importFrom ggplot2 guide_colorbar scale_color_distiller
546
featureScoreVisualization <- function(object, feature.use = NULL, feature.scores, method = "VscAI",
547
                                      colormap = "RdPu", color.direction = 1,
548
                                      nCol = NULL, xlabel = "VscAI1", ylabel = "VscAI2",
549
                                      show.axes = T,  cell.size = 0.3,
550
                                      show.legend = T, show.legend.combined = F) {
551
552
  data.use <- as.matrix(feature.scores[ ,feature.use])
553
554
  if (is.null(nCol)) {
555
    if (length(feature.use) > 9) {
556
      nCol <- 4
557
    } else {
558
      nCol <- min(length(feature.use), 3)
559
    }
560
  }
561
562
  if (method == "VscAI") {
563
    cell_coords <- object@embed$VscAI$cells
564
  } else if (method == "tsne") {
565
    cell_coords <- object@embed$tsne
566
    xlabel = "tSNE1"
567
    ylabel = "tSNE2"
568
  } else if (method == "umap") {
569
    cell_coords <- object@embed$umap
570
    xlabel = "UMAP1"
571
    ylabel = "UMAP2"
572
  }
573
574
  df <- data.frame(x = cell_coords[, 1], y = cell_coords[, 2])
575
  numFeature = length(feature.use)
576
  gg <- vector("list", numFeature)
577
  for (i in seq_len(numFeature)) {
578
    feature.name <- feature.use[i]
579
    df$feature.data <- data.use[ ,i]
580
581
    g <- ggplot(data = df, aes(x, y)) +
582
      geom_point(aes(colour = feature.data), size = cell.size) +
583
      scale_color_distiller(palette = colormap, direction = color.direction, guide = guide_colorbar(title = NULL, ticks = T, label = T, barwidth = 0.5), na.value = "lightgrey") +
584
      labs(title = feature.name) + scAI_theme_opts() +
585
      theme(text = element_text(size = 10), legend.key.height = grid::unit(0.15, "in")) + labs(x = xlabel, y = ylabel)
586
587
    if (!show.legend) {
588
      g <- g + theme(legend.position = "none")
589
    }
590
591
    if (show.legend.combined & i == numFeature) {
592
      g <- g + theme(legend.position = "right", legend.key.height = grid::unit(0.15, "in"), legend.key.width = grid::unit(0.5, "in"), legend.title = NULL)
593
    }
594
595
    if (!show.axes) {
596
      g <- g + theme_void()
597
    }
598
    gg[[i]] <- g
599
  }
600
  gg.combined <- cowplot::plot_grid(plotlist = gg, ncol = nCol)
601
602
  gg.combined
603
}
604
605
606
607
#' generate a heatmap for the expression of differential features across different cell groups
608
#'
609
#' @param object scAI object
610
#' @param assay define an assay to show, e.g., assay = "RNA"
611
#' @param feature.use a vector of features to show
612
#' @param group.by the name of the variable in pData, defining cell groups. cells are grouped together
613
#' @param color.use colors for the cell clusters
614
#' @param names.show whether show the feature names
615
#' @param size.names the font size of the feature names
616
#' @param use.agg whether use aggregated data
617
#' @param rescaling whether rescale each feature across all the cells
618
#'
619
#' @return
620
#' @export
621
#'
622
#' @examples
623
#' @importFrom circlize colorRamp2
624
#' @importFrom ComplexHeatmap Heatmap HeatmapAnnotation
625
featureHeatmap <- function(object, assay, feature.use,  group.by, color.use = NULL, use.agg = TRUE, rescaling = TRUE, names.show = TRUE, size.names = 8) {
626
    if (assay == "RNA") {
627
      data <- object@norm.data[[assay]]
628
    } else {
629
        if (use.agg) {
630
          data <- object@agg.data
631
        } else {
632
          data <- object@norm.data[[assay]]
633
        }
634
    }
635
636
    groups = object@pData[[group.by]]
637
    feature.use <- feature.use[feature.use %in% rownames(data)]
638
    data.use <- data[feature.use,]
639
640
    if(rescaling) {
641
        data.use = Matrix::t(scale(Matrix::t(data.use), center = T))
642
    }
643
    data.use <- as.matrix(data.use)
644
645
    cell.order <- order(groups)
646
    data.use <- data.use[,cell.order]
647
    numCluster <- length(unique(groups))
648
649
    if (is.null(color.use)) {
650
        color.use <- scPalette(numCluster)
651
    }
652
653
    colorGate = structure(color.use, names = as.character(levels(groups)))
654
655
    col_annotation = HeatmapAnnotation(group = sort(groups),col = list(group = colorGate),
656
    annotation_name_side = "left",simple_anno_size = unit(0.2, "cm"))
657
    Heatmap(data.use,name = "zscore",
658
    col = colorRamp2(c(-2, 0, 2), c("#2166ac", "#f7f7f7", "#b2182b"),space = "LAB"),
659
    cluster_rows = FALSE, cluster_columns = FALSE, show_column_names = FALSE,
660
    show_row_names = names.show, row_names_side = "left", row_names_rot = 0,row_names_gp = gpar(fontsize = size.names),
661
    width = unit(6, "cm"),
662
    bottom_annotation = col_annotation,
663
    heatmap_legend_param = list(title = NULL, legend_width = unit(0.0001, "cm"),labels_gp = gpar(font = 6))
664
    )
665
}
666