|
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 |
|