Browse code

add max_density argument

Zuguang Gu authored on 15/06/2022 10:42:56
Showing1 changed files
... ...
@@ -1958,6 +1958,8 @@ anno_histogram = function(x, which = c("column", "row"), n_breaks = 11,
1958 1958
 # -type Type of graphics to represent density distribution. "lines" for normal density plot; "violine" for violin plot
1959 1959
 #       and "heatmap" for heatmap visualization of density distribution.
1960 1960
 # -xlim Range on x-axis.
1961
+# -max_density Maximal density values in the plot. Normally you don't need to manually set it, but when you have multiple density annotations
1962
+#   and you want to compare between them, you should manually set this argument to make density distributions are in a same scale.
1961 1963
 # -heatmap_colors A vector of colors for interpolating density values.
1962 1964
 # -joyplot_scale Relative height of density distribution. A value higher than 1 increases the height of the density
1963 1965
 #               distribution and the plot will represented as so-called "joyplot".
... ...
@@ -1986,7 +1988,7 @@ anno_histogram = function(x, which = c("column", "row"), n_breaks = 11,
1986 1988
 #     heatmap_colors = c("white", "orange"))
1987 1989
 # draw(anno, test = "heatmap, colors")
1988 1990
 anno_density = function(x, which = c("column", "row"),
1989
-	type = c("lines", "violin", "heatmap"), xlim = NULL,
1991
+	type = c("lines", "violin", "heatmap"), xlim = NULL, max_density = NULL,
1990 1992
 	heatmap_colors = rev(brewer.pal(name = "RdYlBu", n = 11)), 
1991 1993
 	joyplot_scale = 1, border = TRUE, gp = gpar(fill = "#CCCCCC"),
1992 1994
 	axis = TRUE, axis_param = default_axis_param(which),
... ...
@@ -2044,16 +2046,29 @@ anno_density = function(x, which = c("column", "row"),
2044 2046
 	
2045 2047
 	if(type == "lines") {
2046 2048
 		xscale = xscale + c(-0.025, 0.025)*(xscale[2] - xscale[1])
2047
-		yscale = c(0, max(unlist(density_y)))
2049
+		if(is.null(max_density)) {
2050
+			yscale = c(0, max(unlist(density_y)))
2051
+		} else {
2052
+			yscale = c(0, max_density)
2053
+		}
2048 2054
 		yscale[2] = yscale[2]*1.05
2049 2055
 	} else if(type == "violin") {
2050 2056
 		xscale = xscale + c(-0.025, 0.025)*(xscale[2] - xscale[1])
2051
-		yscale = max(unlist(density_y))
2057
+		if(is.null(max_density)) {
2058
+			yscale = max(unlist(density_y))
2059
+		} else {
2060
+			yscale = max_density
2061
+		}
2052 2062
 		yscale = c(-yscale*1.05, yscale*1.05)
2053 2063
 	} else if(type == "heatmap") {
2054 2064
 		yscale = c(0, 1)
2055
-		min_y = min(unlist(density_y))
2056
-		max_y = max(unlist(density_y))
2065
+		if(is.null(max_density)) {
2066
+			min_y = min(unlist(density_y))
2067
+			max_y = max(unlist(density_y))
2068
+		} else {
2069
+			min_y = 0
2070
+			max_y = max_density
2071
+		}
2057 2072
 		col_fun = colorRamp2(seq(min_y, max_y, 
2058 2073
 			length.out = length(heatmap_colors)), heatmap_colors)
2059 2074
 	}
Browse code

add more annotation functions

Zuguang Gu authored on 18/02/2022 19:51:49
Showing1 changed files
... ...
@@ -1300,18 +1300,18 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1300 1300
 		data_scale = range(rowSums(x, na.rm = TRUE), na.rm = TRUE)
1301 1301
 	}
1302 1302
 
1303
-	if(data_scale[1] == data_scale[2]) data_scale[2] = data_scale[1] + 1
1303
+	if(data_scale[1] == data_scale[2]) data_scale[2] = data_scale[1] + .Machine$double.eps*1.1
1304 1304
 
1305 1305
 	if(!is.null(ylim)) data_scale = ylim
1306 1306
 	if(baseline == "min") {
1307 1307
 		data_scale = data_scale + c(0, extend)*(data_scale[2] - data_scale[1])
1308
-		baseline = min(x)
1308
+		baseline = min(x, na.rm = TRUE)
1309 1309
 	} else if(baseline == "max") {
1310 1310
 		data_scale = data_scale + c(-extend, 0)*(data_scale[2] - data_scale[1])
1311
-		baseline = max(x)
1311
+		baseline = max(x, na.rm = TRUE)
1312 1312
 	} else {
1313 1313
 		if(is.numeric(baseline)) {
1314
-			if(baseline == 0 && all(abs(rowSums(x) - 1) < 1e-6) && !beside) {
1314
+			if(baseline == 0 && all(abs(rowSums(x, na.rm = TRUE) - 1) < 1e-6) && !beside) {
1315 1315
 				data_scale = c(0, 1)
1316 1316
 			} else if(baseline <= data_scale[1]) {
1317 1317
 				data_scale = c(baseline, extend*(data_scale[2] - baseline) + data_scale[2])
... ...
@@ -4314,8 +4314,8 @@ anno_customize = function(x, graphics = list(), which = c("column", "row"),
4314 4314
 # == param
4315 4315
 # -x A vector of numeric values.
4316 4316
 # -rg Range. A numeric vector of length two.
4317
-# -labels_gp. Graphics parameters for labels.
4318
-# -x_convert. A function applied on ``x``. E.g. when ``x`` contains p-values, to map ``x`` to the heights of bars, a transformation of ``-log10(x)`` 
4317
+# -labels_gp Graphics parameters for labels.
4318
+# -x_convert A function applied on ``x``. E.g. when ``x`` contains p-values, to map ``x`` to the heights of bars, a transformation of ``-log10(x)`` 
4319 4319
 #      is normally applied.
4320 4320
 # -labels_format A function applied on ``x``. E.g., when ``x`` is a numeric, ``labels_format`` can be set to ``function(x) sprintf("\%.2f", x)``.
4321 4321
 # -labels_offset Offset of labels to the left or right of bars.
... ...
@@ -4330,7 +4330,7 @@ anno_customize = function(x, graphics = list(), which = c("column", "row"),
4330 4330
 #
4331 4331
 # == example
4332 4332
 # m = matrix(rnorm(100), 10)
4333
-# x = numeric(10)
4333
+# x = rnorm(10)
4334 4334
 # Heatmap(m, right_annotation = rowAnnotation(numeric = anno_numeric(x)))
4335 4335
 anno_numeric = function(x, rg = range(x), labels_gp = gpar(), x_convert = NULL, 
4336 4336
 	labels_format = NULL, labels_offset = unit(4, "pt"),
... ...
@@ -4359,6 +4359,10 @@ anno_numeric = function(x, rg = range(x), labels_gp = gpar(), x_convert = NULL,
4359 4359
 		rg = range(x_convert(rg))
4360 4360
 	}
4361 4361
 
4362
+	if(rg[1] == rg[2]) {
4363
+		rg[2] = rg[2] + .Machine$double.eps*1.1
4364
+	}
4365
+
4362 4366
     x[x < rg[1]] = rg[1]
4363 4367
     x[x > rg[2]] = rg[2]
4364 4368
 
Browse code

add show_name in anno_empty()

Zuguang Gu authored on 03/02/2022 09:53:48
Showing1 changed files
... ...
@@ -10,6 +10,7 @@
10 10
 #       and the original heatmap slices.
11 11
 # -width Width of the annotation. The value should be an absolute unit. Width is not allowed to be set for column annotation.
12 12
 # -height Height of the annotation. The value should be an absolute unit. Height is not allowed to be set for row annotation.
13
+# -show_name Whether to show annotation name.
13 14
 #
14 15
 # == details
15 16
 # It creates an empty annotation and holds space, later users can add graphics
... ...
@@ -46,7 +47,7 @@
46 47
 # anno = anno_empty(border = FALSE)
47 48
 # draw(anno, test = "anno_empty without border")
48 49
 anno_empty = function(which = c("column", "row"), border = TRUE, zoom = FALSE,
49
-	width = NULL, height = NULL) {
50
+	width = NULL, height = NULL, show_name = FALSE) {
50 51
 	
51 52
 	if(is.null(.ENV$current_annotation_which)) {
52 53
 		which = match.arg(which)[1]
... ...
@@ -68,10 +69,10 @@ anno_empty = function(which = c("column", "row"), border = TRUE, zoom = FALSE,
68 69
 		which = which,
69 70
 		var_import = list(border, zoom),
70 71
 		subset_rule = list(),
71
-		subsetable = TRUE,
72
+		subsettable = TRUE,
72 73
 		height = anno_size$height,
73 74
 		width = anno_size$width,
74
-		show_name = FALSE
75
+		show_name = show_name
75 76
 	)
76 77
 	
77 78
 	return(anno) 
... ...
@@ -242,10 +243,15 @@ anno_simple = function(x, col, na_col = "grey",
242 243
 			pch = pch[index, , drop = FALSE]
243 244
 
244 245
 			for(i in seq_len(nc)) {
245
-				if(color_mapping@type == "continuous") {
246
+				if(color_mapping@type == "continuous" || !is.null(gp$col)) {
246 247
 				    fill = map_to_colors(color_mapping, value[index, i])
247
-				    if(is.null(gp$col)) gp$col = fill
248
+				    flag = 0
249
+	                if(is.null(gp$col)) {
250
+	                	gp$col = fill
251
+	                	flag = 1
252
+	                }
248 253
 				    grid.rect(x = (i-0.5)/nc, y, height = 1/n, width = 1/nc, gp = do.call("gpar", c(list(fill = fill), gp)))
254
+				    if(flag) gp$col = NULL
249 255
 				} else {
250 256
 					r = rle(value[index, i])
251 257
 					fill = map_to_colors(color_mapping, r$values)
... ...
@@ -269,7 +275,7 @@ anno_simple = function(x, col, na_col = "grey",
269 275
 			    }
270 276
 			}
271 277
 	    } else {
272
-	    	if(color_mapping@type == "continuous") {
278
+	    	if(color_mapping@type == "continuous" || !is.null(gp$col)) {
273 279
 				fill = map_to_colors(color_mapping, value[index])
274 280
 				if(is.null(gp$col)) gp$col = fill
275 281
 				grid.rect(x = 0.5, y, height = 1/n, width = 1, gp = do.call("gpar", c(list(fill = fill), gp)))
... ...
@@ -308,12 +314,16 @@ anno_simple = function(x, col, na_col = "grey",
308 314
 
309 315
             nc = ncol(value)
310 316
 		    pch = pch[index, , drop = FALSE]
311
-				  
312 317
 	        for(i in seq_len(nc)) {
313
-	        	if(color_mapping@type == "continuous") {
318
+	        	if(color_mapping@type == "continuous" || !is.null(gp$col)) {
314 319
 	                fill = map_to_colors(color_mapping, value[index, i])
315
-	                if(is.null(gp$col)) gp$col = fill
320
+	                flag = 0
321
+	                if(is.null(gp$col)) {
322
+	                	gp$col = fill
323
+	                	flag = 1
324
+	                }
316 325
 	                grid.rect(x, y = (nc-i +0.5)/nc, width = 1/n, height = 1/nc, gp = do.call("gpar", c(list(fill = fill), gp)))
326
+	                if(flag) gp$col = NULL
317 327
 	            } else {
318 328
 	            	r = rle(value[index, i])
319 329
 					fill = map_to_colors(color_mapping, r$values)
... ...
@@ -337,7 +347,7 @@ anno_simple = function(x, col, na_col = "grey",
337 347
 				}
338 348
 		    }
339 349
         } else {
340
-        	if(color_mapping@type == "continuous") {
350
+        	if(color_mapping@type == "continuous" || !is.null(gp$col)) {
341 351
 				fill = map_to_colors(color_mapping, value[index])
342 352
 				if(is.null(gp$col)) gp$col = fill
343 353
 				grid.rect(x, y = 0.5, width = 1/n, height = 1, gp = do.call("gpar", c(list(fill = fill), gp)))
... ...
@@ -400,7 +410,7 @@ anno_simple = function(x, col, na_col = "grey",
400 410
 		}
401 411
 	}
402 412
 
403
-	anno@subsetable = TRUE
413
+	anno@subsettable = TRUE
404 414
 
405 415
 	return(anno)      
406 416
 }
... ...
@@ -563,7 +573,13 @@ anno_image = function(image, which = c("column", "row"), border = TRUE,
563 573
 				grid.picture(image_list[[ index[i] ]], x = (i-0.5)/n, width = width, height = height)
564 574
 			}
565 575
 		}
566
-		if(border) grid.rect(gp = gpar(fill = "transparent"))
576
+		if(is.logical(border)) {
577
+			if(border) {
578
+				grid.rect(gp = gpar(fill = "transparent"))
579
+			}
580
+		} else {
581
+			grid.rect(gp = gpar(fill = "transparent", col = border))
582
+		}
567 583
 		popViewport()
568 584
 	}
569 585
 
... ...
@@ -592,7 +608,13 @@ anno_image = function(image, which = c("column", "row"), border = TRUE,
592 608
 				grid.picture(image_list[[ index[i] ]], y = (n - i + 0.5)/n, width = width, height = height)
593 609
 			}
594 610
 		}
595
-		if(border) grid.rect(gp = gpar(fill = "transparent"))
611
+		if(is.logical(border)) {
612
+			if(border) {
613
+				grid.rect(gp = gpar(fill = "transparent"))
614
+			}
615
+		} else {
616
+			grid.rect(gp = gpar(fill = "transparent", col = border))
617
+		}
596 618
 		popViewport()
597 619
 	}
598 620
 	
... ...
@@ -617,7 +639,7 @@ anno_image = function(image, which = c("column", "row"), border = TRUE,
617 639
 	anno@subset_rule$image_list = subset_vector
618 640
 	anno@subset_rule$image_class = subset_vector
619 641
 
620
-	anno@subsetable = TRUE
642
+	anno@subsettable = TRUE
621 643
 
622 644
 	return(anno)   
623 645
 }
... ...
@@ -914,7 +936,7 @@ anno_points = function(x, which = c("column", "row"), border = TRUE, gp = gpar()
914 936
 		anno@subset_rule$pch = subset_vector
915 937
 	}
916 938
 
917
-	anno@subsetable = TRUE
939
+	anno@subsettable = TRUE
918 940
 
919 941
 	anno@extended = update_anno_extend(anno, axis_grob, axis_param)
920 942
 		
... ...
@@ -1185,7 +1207,7 @@ anno_lines = function(x, which = c("column", "row"), border = TRUE, gp = gpar(),
1185 1207
 		anno@subset_rule$pch = subset_vector
1186 1208
 	}
1187 1209
 
1188
-	anno@subsetable = TRUE
1210
+	anno@subsettable = TRUE
1189 1211
 
1190 1212
 	anno@extended = update_anno_extend(anno, axis_grob, axis_param)
1191 1213
 		
... ...
@@ -1205,6 +1227,7 @@ anno_lines = function(x, which = c("column", "row"), border = TRUE, gp = gpar(),
1205 1227
 # -border Wether draw borders of the annotation region?
1206 1228
 # -bar_width Relative width of the bars. The value should be smaller than one.
1207 1229
 # -beside When ``x`` is a matrix, will bars be positioned beside each other or as stacked bars?
1230
+# -attach When ``beside`` is ``TRUE``, it controls whether bars should be attached.
1208 1231
 # -gp Graphic parameters for bars. The length of each graphic parameter can be 1, length of ``x`` if ``x``
1209 1232
 #     is a vector, or number of columns of ``x`` is ``x`` is a matrix.
1210 1233
 # -ylim Data ranges. By default it is ``range(x)`` if ``x`` is a vector, or ``range(rowSums(x))`` if ``x`` is a matrix.
... ...
@@ -1233,7 +1256,8 @@ anno_lines = function(x, which = c("column", "row"), border = TRUE, gp = gpar(),
1233 1256
 # m = t(apply(m, 1, function(x) x/sum(x)))
1234 1257
 # anno = anno_barplot(m, gp = gpar(fill = 2:5), bar_width = 1, height = unit(6, "cm"))
1235 1258
 # draw(anno, test = "proportion matrix")
1236
-anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TRUE, bar_width = 0.6, beside = FALSE,
1259
+anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TRUE, bar_width = 0.6, 
1260
+	beside = FALSE, attach = FALSE,
1237 1261
 	gp = gpar(fill = "#CCCCCC"), ylim = NULL, extend = 0.05, axis = TRUE, 
1238 1262
 	axis_param = default_axis_param(which), 
1239 1263
 	add_numbers = FALSE, numbers_gp = gpar(fontsize = 8), 
... ...
@@ -1375,13 +1399,23 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1375 1399
 				nr = nrow(value)
1376 1400
 				for(i in seq_along(index)) {
1377 1401
 			        for(j in 1:nbar) {
1378
-			        	if(axis_param$direction == "normal") {
1379
-				        	grid.rect(x = baseline, y = nr-i+0.5 + (j-0.5)/nbar, width = value[index[i], j], height = 1/nbar*bar_width, just = c("left"),
1380
-				        		default.units = "native", gp = subset_gp(gp, j))
1381
-				        } else {
1382
-				        	grid.rect(x = baseline, y = nr-i+0.5 + (j-0.5)/nbar, width = value[index[i], j], height = 1/nbar*bar_width, just = c("right"),
1383
-				        		default.units = "native", gp = subset_gp(gp, j))
1384
-				        }
1402
+			        	if(attach) {
1403
+			        		if(axis_param$direction == "normal") {
1404
+					        	grid.rect(x = baseline, y = nr-i+0.5 + (1-bar_width)/2 + (nbar - j + 0.5)/nbar*bar_width, width = value[index[i], j], height = 1/nbar*bar_width, just = c("left"),
1405
+					        		default.units = "native", gp = subset_gp(gp, j))
1406
+					        } else {
1407
+					        	grid.rect(x = baseline, y = nr-i+0.5 + (1-bar_width)/2 + (nbar - j + 0.5)/nbar*bar_width, width = value[index[i], j], height = 1/nbar*bar_width, just = c("right"),
1408
+					        		default.units = "native", gp = subset_gp(gp, j))
1409
+					        }
1410
+			        	} else {
1411
+				        	if(axis_param$direction == "normal") {
1412
+					        	grid.rect(x = baseline, y = nr-i+0.5 + (nbar - j + 0.5)/nbar, width = value[index[i], j], height = 1/nbar*bar_width, just = c("left"),
1413
+					        		default.units = "native", gp = subset_gp(gp, j))
1414
+					        } else {
1415
+					        	grid.rect(x = baseline, y = nr-i+0.5 + (nbar - j + 0.5)/nbar, width = value[index[i], j], height = 1/nbar*bar_width, just = c("right"),
1416
+					        		default.units = "native", gp = subset_gp(gp, j))
1417
+					        }
1418
+					    }
1385 1419
 			        }
1386 1420
 			    }
1387 1421
 			} else {
... ...
@@ -1440,13 +1474,23 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1440 1474
 				nr = nrow(value)
1441 1475
 				for(i in seq_along(index)) {
1442 1476
 			        for(j in 1:nbar) {
1443
-			        	if(axis_param$direction == "normal") {
1444
-				        	grid.rect(y = baseline, x = nr-i+0.5 + (j-0.5)/nbar, height = value[index[i], j], width = 1/nbar*bar_width, just = c("bottom"),
1445
-				        		default.units = "native", gp = subset_gp(gp, j))
1446
-				        } else {
1447
-				        	grid.rect(y = baseline, x = nr-i+0.5 + (j-0.5)/nbar, height = value[index[i], j], width = 1/nbar*bar_width, just = c("top"),
1448
-				        		default.units = "native", gp = subset_gp(gp, j))
1449
-				        }
1477
+			        	if(attach) {
1478
+				        	if(axis_param$direction == "normal") {
1479
+					        	grid.rect(y = baseline, x = i-0.5 + (1-bar_width)/2 + (j-0.5)/nbar*bar_width, height = value[index[i], j], width = 1/nbar*bar_width, just = c("bottom"),
1480
+					        		default.units = "native", gp = subset_gp(gp, j))
1481
+					        } else {
1482
+					        	grid.rect(y = baseline, x = i-0.5 + (1-bar_width)/2 + (j-0.5)/nbar*bar_width, height = value[index[i], j], width = 1/nbar*bar_width, just = c("top"),
1483
+					        		default.units = "native", gp = subset_gp(gp, j))
1484
+					        }
1485
+					    } else {
1486
+					    	if(axis_param$direction == "normal") {
1487
+					        	grid.rect(y = baseline, x = i-0.5 + (j-0.5)/nbar, height = value[index[i], j], width = 1/nbar*bar_width, just = c("bottom"),
1488
+					        		default.units = "native", gp = subset_gp(gp, j))
1489
+					        } else {
1490
+					        	grid.rect(y = baseline, x = i-0.5 + (j-0.5)/nbar, height = value[index[i], j], width = 1/nbar*bar_width, just = c("top"),
1491
+					        		default.units = "native", gp = subset_gp(gp, j))
1492
+					        }
1493
+					    }
1450 1494
 			        }
1451 1495
 			    }
1452 1496
 			} else {
... ...
@@ -1489,7 +1533,7 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1489 1533
 		height = anno_size$height,
1490 1534
 		n = n,
1491 1535
 		data_scale = data_scale,
1492
-		var_import = list(value, gp, border, bar_width, baseline, beside, axis, axis_param, axis_grob, data_scale, add_numbers, numbers_gp, numbers_offset, numbers_rot)
1536
+		var_import = list(value, gp, border, bar_width, baseline, beside, attach, axis, axis_param, axis_grob, data_scale, add_numbers, numbers_gp, numbers_offset, numbers_rot)
1493 1537
 	)
1494 1538
 
1495 1539
 	anno@subset_rule$value = subset_matrix_by_row
... ...
@@ -1497,7 +1541,7 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1497 1541
 		anno@subset_rule$gp = subset_gp
1498 1542
 	}
1499 1543
 		
1500
-	anno@subsetable = TRUE
1544
+	anno@subsettable = TRUE
1501 1545
 
1502 1546
 	anno@extended = update_anno_extend(anno, axis_grob, axis_param)
1503 1547
 
... ...
@@ -1734,7 +1778,7 @@ anno_boxplot = function(x, which = c("column", "row"), border = TRUE,
1734 1778
 	anno@subset_rule$pch = subset_vector
1735 1779
 	anno@subset_rule$size = subset_vector
1736 1780
 	
1737
-	anno@subsetable = TRUE
1781
+	anno@subsettable = TRUE
1738 1782
 
1739 1783
 	anno@extended = update_anno_extend(anno, axis_grob, axis_param)
1740 1784
 
... ...
@@ -1897,7 +1941,7 @@ anno_histogram = function(x, which = c("column", "row"), n_breaks = 11,
1897 1941
 	anno@subset_rule$histogram_breaks = subset_vector
1898 1942
 	anno@subset_rule$histogram_counts = subset_vector
1899 1943
 	
1900
-	anno@subsetable = TRUE
1944
+	anno@subsettable = TRUE
1901 1945
 
1902 1946
 	anno@extended = update_anno_extend(anno, axis_grob, axis_param)
1903 1947
 
... ...
@@ -2176,7 +2220,7 @@ anno_density = function(x, which = c("column", "row"),
2176 2220
 	anno@subset_rule$density_x = subset_vector
2177 2221
 	anno@subset_rule$density_y = subset_vector
2178 2222
 	
2179
-	anno@subsetable = TRUE
2223
+	anno@subsettable = TRUE
2180 2224
 
2181 2225
 	anno@extended = update_anno_extend(anno, axis_grob, axis_param)
2182 2226
 
... ...
@@ -2360,7 +2404,7 @@ anno_text = function(x, which = c("column", "row"), gp = gpar(),
2360 2404
 	anno@subset_rule$value = subset_vector
2361 2405
 	anno@subset_rule$gp = subset_gp
2362 2406
 
2363
-	anno@subsetable = TRUE
2407
+	anno@subsettable = TRUE
2364 2408
 
2365 2409
 	return(anno)
2366 2410
 }
... ...
@@ -2549,7 +2593,7 @@ anno_joyplot = function(x, which = c("column", "row"), gp = gpar(fill = "#000000
2549 2593
 	anno@subset_rule$value = subset_vector
2550 2594
 	anno@subset_rule$gp = subset_gp
2551 2595
 
2552
-	anno@subsetable = TRUE
2596
+	anno@subsettable = TRUE
2553 2597
 
2554 2598
 	anno@extended = update_anno_extend(anno, axis_grob, axis_param)
2555 2599
 
... ...
@@ -2733,7 +2777,7 @@ anno_horizon = function(x, which = c("column", "row"),
2733 2777
 	anno@subset_rule$value = subset_vector
2734 2778
 	anno@subset_rule$gp = subset_gp
2735 2779
 
2736
-	anno@subsetable = TRUE
2780
+	anno@subsettable = TRUE
2737 2781
 
2738 2782
 	anno@extended = update_anno_extend(anno, axis_grob, axis_param)
2739 2783
 
... ...
@@ -3220,7 +3264,7 @@ anno_mark = function(at, labels, which = c("column", "row"),
3220 3264
 
3221 3265
 	anno@subset_rule$at = subset_by_intersect
3222 3266
 
3223
-	anno@subsetable = TRUE
3267
+	anno@subsettable = TRUE
3224 3268
 
3225 3269
 	attr(anno, "called_args") = list(
3226 3270
 		at = at, 
... ...
@@ -3427,7 +3471,7 @@ anno_summary = function(which = c("column", "row"), border = TRUE, bar_width = 0
3427 3471
 		show_name = FALSE
3428 3472
 	)
3429 3473
 
3430
-	anno@subsetable = FALSE
3474
+	anno@subsettable = FALSE
3431 3475
 	anno@extended = update_anno_extend(anno, axis_grob, axis_param)
3432 3476
 
3433 3477
 	return(anno)
... ...
@@ -3437,6 +3481,8 @@ anno_summary = function(which = c("column", "row"), border = TRUE, bar_width = 0
3437 3481
 # Block annotation
3438 3482
 #
3439 3483
 # == param
3484
+# -align_to If you don't want to create block annotation for all slices, you can specify a list of indices that cover continuously adjacent
3485
+#        rows or columns.
3440 3486
 # -gp Graphic parameters.
3441 3487
 # -labels Labels put on blocks.
3442 3488
 # -labels_gp Graphic parameters for labels.
... ...
@@ -3447,7 +3493,7 @@ anno_summary = function(which = c("column", "row"), border = TRUE, bar_width = 0
3447 3493
 # -width Width of the annotation. The value should be an absolute unit. Width is not allowed to be set for column annotation.
3448 3494
 # -height Height of the annotation. The value should be an absolute unit. Height is not allowed to be set for row annotation.
3449 3495
 # -show_name Whether show annotatio name.
3450
-# -graphics A self-defined function that draws graphics in each slice. It must have two arguments: 1. row/column indices for the 
3496
+# -panel_fun A self-defined function that draws graphics in each slice. It must have two arguments: 1. row/column indices for the 
3451 3497
 #      current slice and 2. a vector of levels from the split variable that correspond to current slice. When ``graphics`` is set,
3452 3498
 #      all other graphics parameters in `anno_block` are ignored.
3453 3499
 #
... ...
@@ -3470,11 +3516,11 @@ anno_summary = function(which = c("column", "row"), border = TRUE, bar_width = 0
3470 3516
 #     row_km = 3)
3471 3517
 #
3472 3518
 #
3473
-# # =============  set the graphics argument ==============
3519
+# # =============  set the panel_fun argument ==============
3474 3520
 # col = c("1" = "red", "2" = "blue", "A" = "green", "B" = "orange")
3475 3521
 # Heatmap(matrix(rnorm(100), 10), row_km = 2, row_split = sample(c("A", "B"), 10, replace = TRUE)) + 
3476 3522
 # rowAnnotation(foo = anno_block(
3477
-# 	graphics = function(index, levels) {
3523
+# 	panel_fun = function(index, levels) {
3478 3524
 # 		grid.rect(gp = gpar(fill = col[levels[2]], col = "black"))
3479 3525
 # 		grid.text(paste(levels, collapse = ","), 0.5, 0.5, rot = 90,
3480 3526
 # 			gp = gpar(col = col[levels[1]]))
... ...
@@ -3483,7 +3529,7 @@ anno_summary = function(which = c("column", "row"), border = TRUE, bar_width = 0
3483 3529
 #
3484 3530
 # labels = c("1" = "one", "2" = "two", "A" = "Group_A", "B" = "Group_B")
3485 3531
 # Heatmap(matrix(rnorm(100), 10), row_km = 2, row_split = sample(c("A", "B"), 10, replace = TRUE)) + 
3486
-# rowAnnotation(foo = anno_block(graphics = function(index, levels) {
3532
+# rowAnnotation(foo = anno_block(panel_fun = function(index, levels) {
3487 3533
 # 	grid.rect(gp = gpar(fill = col[levels[2]], col = "black"))
3488 3534
 # 	grid.text(paste(labels[levels], collapse = ","), 0.5, 0.5, rot = 90,
3489 3535
 # 		gp = gpar(col = col[levels[1]]))
... ...
@@ -3491,7 +3537,7 @@ anno_summary = function(which = c("column", "row"), border = TRUE, bar_width = 0
3491 3537
 #
3492 3538
 # Heatmap(matrix(rnorm(100), 10), row_km = 2, row_split = sample(c("A", "B"), 10, replace = TRUE)) + 
3493 3539
 # rowAnnotation(foo = anno_block(
3494
-# 	graphics = function(index, levels) {
3540
+# 	panel_fun = function(index, levels) {
3495 3541
 # 		grid.rect(gp = gpar(fill = col[levels[2]], col = "black"))
3496 3542
 # 		txt = paste(levels, collapse = ",")
3497 3543
 # 		txt = paste0(txt, "\n", length(index), " rows")
... ...
@@ -3501,17 +3547,40 @@ anno_summary = function(which = c("column", "row"), border = TRUE, bar_width = 0
3501 3547
 # 	width = unit(3, "cm")
3502 3548
 # ))
3503 3549
 #
3504
-anno_block = function(gp = gpar(), labels = NULL, labels_gp = gpar(), 
3550
+# # =========== set align_to ################
3551
+# col = c("foo" = "red", "bar" = "blue")
3552
+# Heatmap(matrix(rnorm(100), 10), cluster_rows = FALSE) +
3553
+# rowAnnotation(foo = anno_block(
3554
+# 	align_to = list(foo = 1:4, bar = 6:10),
3555
+# 	panel_fun = function(index, nm) {
3556
+# 		grid.rect(gp = gpar(fill = col[nm]))
3557
+# 		grid.text(nm, 0.5, 0.5)
3558
+# 	},
3559
+# 	width = unit(2, "cm"))
3560
+# )
3561
+anno_block = function(align_to = NULL, gp = gpar(), labels = NULL, labels_gp = gpar(), 
3505 3562
 	labels_rot = ifelse(which == "row", 90, 0),
3506 3563
 	labels_offset = unit(0.5, "npc"), labels_just = "center",
3507 3564
 	which = c("column", "row"), width = NULL, height = NULL, show_name = FALSE,
3508
-	graphics = NULL) {
3565
+	panel_fun = NULL) {
3509 3566
 
3510 3567
 	if(is.null(.ENV$current_annotation_which)) {
3511 3568
 		which = match.arg(which)[1]
3512 3569
 	} else {
3513 3570
 		which = .ENV$current_annotation_which
3514 3571
 	}
3572
+	if(!is.null(align_to)) {
3573
+		if(is.numeric(align_to)) {
3574
+			align_to = list(v = align_to)
3575
+		}
3576
+		if(!is.list(align_to)) {
3577
+			stop_wrap("`align_to` should be a list.")
3578
+		}
3579
+		if(is.null(names(align_to))) {
3580
+			stop_wrap("`align_to` should be a named list.")
3581
+		}
3582
+	}
3583
+
3515 3584
 	if(length(labels)) {
3516 3585
 		if(which == "column") {
3517 3586
 			if(missing(height)) {
... ...
@@ -3534,10 +3603,40 @@ anno_block = function(gp = gpar(), labels = NULL, labels_gp = gpar(),
3534 3603
 		}
3535 3604
 	}
3536 3605
 
3606
+	if(!is.null(panel_fun)) {
3607
+		if(length(as.list(formals(panel_fun))) == 1) {
3608
+	 		formals(panel_fun) = alist(index = , nm = NULL)
3609
+		}
3610
+	}
3611
+
3537 3612
 	anno_size = anno_width_and_height(which, width, height, unit(5, "mm"))
3538 3613
 	
3539 3614
 	fun = function(index, k, n) {
3540
-		if(is.null(graphics)) {
3615
+		if(!is.null(align_to)) {
3616
+			is_in = sapply(align_to, function(x) any(x %in% index))
3617
+			
3618
+			ind_aln = which(is_in)
3619
+
3620
+			for(ai in ind_aln) {
3621
+				ind = which(index %in% align_to[[ai]])
3622
+				if(any(diff(ind) > 1)) {
3623
+					stop_wrap("Indices in `align_to` should be continuously adjacent in the heatmap.")
3624
+				}
3625
+
3626
+				ni = length(index)
3627
+
3628
+				if(which == "row") {
3629
+					pushViewport(viewport(y = (ni - ind[length(ind)])/ni, height = length(ind)/ni, default.units = "npc", just = "bottom"))
3630
+					panel_fun(index[ind], names(align_to)[ai])
3631
+					popViewport()
3632
+				} else {
3633
+					pushViewport(viewport(x = (ind[length(ind)])/ni, width = length(ind)/ni, default.units = "npc", just = "right"))
3634
+					panel_fun(index[ind], names(align_to)[ai])
3635
+					popViewport()
3636
+				}
3637
+			}
3638
+
3639
+		} else if(is.null(panel_fun)) {
3541 3640
 			gp = subset_gp(recycle_gp(gp, n), k)
3542 3641
 			grid.rect(gp = gp)
3543 3642
 			if(length(labels)) {
... ...
@@ -3551,7 +3650,7 @@ anno_block = function(gp = gpar(), labels = NULL, labels_gp = gpar(),
3551 3650
 				if(which == "row") x = labels_offset
3552 3651
 				grid.text(label, x = x, y = y, gp = labels_gp, rot = labels_rot, just = labels_just)
3553 3652
 			}
3554
-		} else {
3653
+		} else  {
3555 3654
 
3556 3655
 			for(ifa in 1:30) {
3557 3656
 				if(exists("ht_main", envir = parent.frame(ifa))) {
... ...
@@ -3568,9 +3667,9 @@ anno_block = function(gp = gpar(), labels = NULL, labels_gp = gpar(),
3568 3667
 				order_list = ht@column_order_list
3569 3668
 			}
3570 3669
 			if(is.null(split)) {
3571
-				graphics(index, NULL)
3670
+				panel_fun(index, NULL)
3572 3671
 			} else {
3573
-				graphics(index, unlist(split[order_list[[k]][1], ]))
3672
+				panel_fun(index, unlist(split[order_list[[k]][1], ]))
3574 3673
 			}
3575 3674
 		}
3576 3675
 	}
... ...
@@ -3580,9 +3679,9 @@ anno_block = function(gp = gpar(), labels = NULL, labels_gp = gpar(),
3580 3679
 		n = NA,
3581 3680
 		fun_name = "anno_block",
3582 3681
 		which = which,
3583
-		var_import = list(gp, labels, labels_gp, labels_rot, labels_offset, labels_just, graphics, which),
3682
+		var_import = list(gp, labels, labels_gp, labels_rot, labels_offset, labels_just, panel_fun, which, align_to),
3584 3683
 		subset_rule = list(),
3585
-		subsetable = TRUE,
3684
+		subsettable = TRUE,
3586 3685
 		height = anno_size$height,
3587 3686
 		width = anno_size$width,
3588 3687
 		show_name = show_name
... ...
@@ -4087,7 +4186,7 @@ anno_zoom = function(align_to, panel_fun = function(index, nm = NULL) { grid.rec
4087 4186
 		}
4088 4187
 	}
4089 4188
 
4090
-	anno@subsetable = TRUE
4189
+	anno@subsettable = TRUE
4091 4190
 	return(anno)
4092 4191
 }
4093 4192
 
... ...
@@ -4202,8 +4301,147 @@ anno_customize = function(x, graphics = list(), which = c("column", "row"),
4202 4301
 
4203 4302
 	anno@subset_rule$value = subset_vector
4204 4303
 
4205
-	anno@subsetable = TRUE
4304
+	anno@subsettable = TRUE
4206 4305
 		
4207 4306
 	return(anno) 
4208 4307
 }
4209 4308
 
4309
+
4310
+
4311
+# == title
4312
+# Numeric labels annotation
4313
+#
4314
+# == param
4315
+# -x A vector of numeric values.
4316
+# -rg Range. A numeric vector of length two.
4317
+# -labels_gp. Graphics parameters for labels.
4318
+# -x_convert. A function applied on ``x``. E.g. when ``x`` contains p-values, to map ``x`` to the heights of bars, a transformation of ``-log10(x)`` 
4319
+#      is normally applied.
4320
+# -labels_format A function applied on ``x``. E.g., when ``x`` is a numeric, ``labels_format`` can be set to ``function(x) sprintf("\%.2f", x)``.
4321
+# -labels_offset Offset of labels to the left or right of bars.
4322
+# -bg_gp Graphics parameters for the background bars.
4323
+# -bar_width Width of bars. Note it corresponds to the vertical direction.
4324
+# -round_corners Whether to draw bars with round corners?
4325
+# -r Radius of the round corners.
4326
+# -which Row or column. Currently it only supports row annotation.
4327
+# -align_to Which side bars as well as the labels are aligned to. Values can be "left" or "right". If ``x`` contains both positive and negative values,
4328
+#       ``align_to`` can also be set to 0 so that bars are aligned to ``pos = 0``.
4329
+# -width Width of the annotation.
4330
+#
4331
+# == example
4332
+# m = matrix(rnorm(100), 10)
4333
+# x = numeric(10)
4334
+# Heatmap(m, right_annotation = rowAnnotation(numeric = anno_numeric(x)))
4335
+anno_numeric = function(x, rg = range(x), labels_gp = gpar(), x_convert = NULL, 
4336
+	labels_format = NULL, labels_offset = unit(4, "pt"),
4337
+	bg_gp = gpar(fill = "#8080FF", col = "#8080FF"), 
4338
+	bar_width = unit(1, "npc") - unit(4, "pt"),
4339
+	round_corners = TRUE, r = unit(0.05, "snpc"), 
4340
+    which = c("row", "column"), align_to = "left", width = NULL) {
4341
+
4342
+	which = match.arg(which)[1]
4343
+	if(which == "column") {
4344
+		stop_wrap("`anno_numeric()` can only be used as row annotation.")
4345
+	}
4346
+
4347
+	if(!is.numeric(x)) {
4348
+		stop_wrap("Input for `anno_numeric()` should be a numeric vector.")
4349
+	}
4350
+
4351
+    if(!is.null(labels_format)) {
4352
+    	labels = labels_format(x)
4353
+    } else {
4354
+    	labels = x
4355
+    }
4356
+
4357
+	if(!is.null(x_convert)) {
4358
+		x = x_convert(x)
4359
+		rg = range(x_convert(rg))
4360
+	}
4361
+
4362
+    x[x < rg[1]] = rg[1]
4363
+    x[x > rg[2]] = rg[2]
4364
+
4365
+    if(missing(align_to) && (any(x > 0) & any(x < 0))) {
4366
+    	align_to = 0
4367
+    }
4368
+
4369
+    cell_fun_pct = function(i) {
4370
+
4371
+    	min_x = rg[1]
4372
+    	max_x = rg[2]
4373
+        pushViewport(viewport(xscale = rg))
4374
+        if(align_to == "right") {
4375
+        	if(round_corners) {
4376
+	            grid.roundrect(x = unit(1, "npc"), 
4377
+	                width = unit(x[i] - min_x, "native"), height = bar_width, r = r,
4378
+	                just = "right", gp = subset_gp(bg_gp, i))
4379
+	        } else {
4380
+	        	grid.rect(x = unit(1, "npc"), 
4381
+	                width = unit(x[i] - min_x, "native"), height = bar_width,
4382
+	                just = "right", gp = subset_gp(bg_gp, i))
4383
+	        }
4384
+            grid.text(labels[i], x = unit(1, "npc") - labels_offset, just = "right", gp = subset_gp(labels_gp, i))
4385
+        } else if(align_to == "left") {
4386
+        	if(round_corners) {
4387
+	            grid.roundrect(x = unit(0, "npc"), 
4388
+	                width = unit(x[i] - min_x, "native"), height = bar_width,  r = r,
4389
+	                just = "left", gp = subset_gp(bg_gp, i))
4390
+	        } else {
4391
+	        	grid.rect(x = unit(0, "npc"), 
4392
+	                width = unit(x[i] - min_x, "native"), height = bar_width,
4393
+	                just = "left", gp = subset_gp(bg_gp, i))
4394
+	        }
4395
+            grid.text(labels[i], x = unit(0, "npc") + labels_offset, just = "left", gp = subset_gp(labels_gp, i))
4396
+        } else if(align_to == 0) {
4397
+        	if(x[i] <= 0) {
4398
+        		if(round_corners) {
4399
+		        	grid.roundrect(x = unit(0, "native"), 
4400
+		                width = unit(-x[i], "native"), height = bar_width,  r = r,
4401
+		                just = "right", gp = subset_gp(bg_gp, 1))
4402
+		        } else {
4403
+		        	grid.rect(x = unit(0, "native"), 
4404
+		                width = unit(-x[i], "native"), height = bar_width, 
4405
+		                just = "right", gp = subset_gp(bg_gp, 1))
4406
+		        }
4407
+	            grid.text(labels[i], x = unit(0, "native") - labels_offset, just = "right", gp = subset_gp(labels_gp, 1))
4408
+	        } else {
4409
+	        	if(round_corners) {
4410
+		        	grid.roundrect(x = unit(0, "native"), 
4411
+		                width = unit(x[i], "native"), height = bar_width,  r = r,
4412
+		                just = "left", gp = subset_gp(bg_gp, 2))
4413
+		        } else {
4414
+		        	grid.rect(x = unit(0, "native"), 
4415
+		                width = unit(x[i], "native"), height = bar_width,
4416
+		                just = "left", gp = subset_gp(bg_gp, 2))
4417
+		        }
4418
+	            grid.text(labels[i], x = unit(0, "native") + labels_offset, just = "left", gp = subset_gp(labels_gp, 2))
4419
+	        }
4420
+        }
4421
+        popViewport()
4422
+    }
4423
+
4424
+    if(is.null(width)) {
4425
+    	if(align_to == "left" || align_to == "right") {
4426
+        	width = convertWidth(max(unit.c(unit(2, "cm"), max_text_width(labels, gp = labels_gp) + labels_offset*2)), "mm")
4427
+        } else {
4428
+        	l1 = x >= 0
4429
+        	l2 = x < 0
4430
+        	if(any(l1) && any(l2)) {
4431
+        		w1 = max_text_width(labels[l1], gp = subset_gp(labels_gp, l1)) + labels_offset*2
4432
+        		w2 = max_text_width(labels[l2], gp = subset_gp(labels_gp, l2)) + labels_offset*2
4433
+				width = convertWidth(max(unit.c(unit(2, "cm"), w1 + w2)), "mm")
4434
+        		
4435
+        	} else {
4436
+        		width = convertWidth(max(unit.c(unit(2, "cm"), max_text_width(labels, gp = labels_gp) + labels_offset*2)), "mm")
4437
+        	}
4438
+        }
4439
+    }
4440
+    AnnotationFunction(
4441
+        cell_fun = cell_fun_pct,
4442
+        var_import = list(rg, labels, x, labels_gp, align_to, bg_gp, bar_width, labels_offset, round_corners, r), 
4443
+        which = "row",
4444
+        width = width
4445
+    )
4446
+}
4447
+
Browse code

reset the ylim when all values are the same

Zuguang Gu authored on 26/11/2021 14:28:45
Showing1 changed files
... ...
@@ -802,6 +802,7 @@ anno_points = function(x, which = c("column", "row"), border = TRUE, gp = gpar()
802 802
 	} else {
803 803
 		data_scale = ylim
804 804
 	}
805
+	if(data_scale[1] == data_scale[2]) data_scale[2] = data_scale[1] + 1
805 806
 	data_scale = data_scale + c(-extend, extend)*(data_scale[2] - data_scale[1])
806 807
 
807 808
 	value = x
... ...
@@ -1028,6 +1029,7 @@ anno_lines = function(x, which = c("column", "row"), border = TRUE, gp = gpar(),
1028 1029
 	} else {
1029 1030
 		data_scale = ylim
1030 1031
 	}
1032
+	if(data_scale[1] == data_scale[2]) data_scale[2] = data_scale[1] + 1
1031 1033
 	data_scale = data_scale + c(-extend, extend)*(data_scale[2] - data_scale[1])
1032 1034
 
1033 1035
 	value = x
... ...
@@ -1273,6 +1275,9 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1273 1275
 	} else {
1274 1276
 		data_scale = range(rowSums(x, na.rm = TRUE), na.rm = TRUE)
1275 1277
 	}
1278
+
1279
+	if(data_scale[1] == data_scale[2]) data_scale[2] = data_scale[1] + 1
1280
+
1276 1281
 	if(!is.null(ylim)) data_scale = ylim
1277 1282
 	if(baseline == "min") {
1278 1283
 		data_scale = data_scale + c(0, extend)*(data_scale[2] - data_scale[1])
... ...
@@ -1585,6 +1590,7 @@ anno_boxplot = function(x, which = c("column", "row"), border = TRUE,
1585 1590
 	} else {
1586 1591
 		data_scale = ylim
1587 1592
 	}
1593
+	if(data_scale[1] == data_scale[2]) data_scale[2] = data_scale[1] + 1
1588 1594
 	data_scale = data_scale + c(-extend, extend)*(data_scale[2] - data_scale[1])
1589 1595
 
1590 1596
 	n = length(value)
Browse code

change argument length to length.out in seq()

Zuguang Gu authored on 26/11/2021 14:06:31
Showing1 changed files
... ...
@@ -1049,7 +1049,7 @@ anno_lines = function(x, which = c("column", "row"), border = TRUE, gp = gpar(),
1049 1049
 				y = value[index, i]
1050 1050
 				if(smooth) {
1051 1051
 					fit = loess(y ~ x)
1052
-					x2 = seq(x[1], x[length(x)], length = 100)
1052
+					x2 = seq(x[1], x[length(x)], length.out = 100)
1053 1053
 					y2 = predict(fit, x2)
1054 1054
 					grid.lines(y2, x2, gp = subset_gp(gp, i), default.units = "native")
1055 1055
 				} else {
... ...
@@ -1072,7 +1072,7 @@ anno_lines = function(x, which = c("column", "row"), border = TRUE, gp = gpar(),
1072 1072
 			y = value[index]
1073 1073
 			if(smooth) {
1074 1074
 				fit = loess(y ~ x)
1075
-				x2 = seq(x[1], x[length(x)], length = 100)
1075
+				x2 = seq(x[1], x[length(x)], length.out = 100)
1076 1076
 				y2 = predict(fit, x2)
1077 1077
 				grid.lines(y2, x2, gp = gp, default.units = "native")
1078 1078
 			} else {
... ...
@@ -1107,7 +1107,7 @@ anno_lines = function(x, which = c("column", "row"), border = TRUE, gp = gpar(),
1107 1107
 				y = value[index, i]
1108 1108
 				if(smooth) {
1109 1109
 					fit = loess(y ~ x)
1110
-					x2 = seq(x[1], x[length(x)], length = 100)
1110
+					x2 = seq(x[1], x[length(x)], length.out = 100)
1111 1111
 					y2 = predict(fit, x2)
1112 1112
 					grid.lines(x2, y2, gp = subset_gp(gp, i), default.units = "native")
1113 1113
 				} else {
... ...
@@ -1130,7 +1130,7 @@ anno_lines = function(x, which = c("column", "row"), border = TRUE, gp = gpar(),
1130 1130
 			y = value[index]
1131 1131
 			if(smooth) {
1132 1132
 				fit = loess(y ~ x)
1133
-				x2 = seq(x[1], x[length(x)], length = 100)
1133
+				x2 = seq(x[1], x[length(x)], length.out = 100)
1134 1134
 				y2 = predict(fit, x2)
1135 1135
 				grid.lines(x2, y2, gp = gp, default.units = "native")
1136 1136
 			} else {
... ...
@@ -1265,7 +1265,7 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1265 1265
 	if(is.null(dim(x))) x = matrix(x, ncol = 1)
1266 1266
 	nc = ncol(x)
1267 1267
 	if(missing(gp)) {
1268
-		gp = gpar(fill = grey(seq(0, 1, length = nc+2))[-c(1, nc+2)])
1268
+		gp = gpar(fill = grey(seq(0, 1, length.out = nc+2))[-c(1, nc+2)])
1269 1269
 	}
1270 1270
 
1271 1271
 	if(beside) {
... ...
@@ -1795,7 +1795,7 @@ anno_histogram = function(x, which = c("column", "row"), n_breaks = 11,
1795 1795
 
1796 1796
 	n = length(value)
1797 1797
 	x_range =range(unlist(value), na.rm = TRUE)
1798
-	histogram_stats = lapply(value, hist, plot = FALSE, breaks = seq(x_range[1], x_range[2], length = n_breaks))
1798
+	histogram_stats = lapply(value, hist, plot = FALSE, breaks = seq(x_range[1], x_range[2], length.out = n_breaks))
1799 1799
 	histogram_breaks = lapply(histogram_stats, function(x) x$breaks)
1800 1800
 	histogram_counts = lapply(histogram_stats, function(x) x$counts)
1801 1801
 
... ...
@@ -2005,7 +2005,7 @@ anno_density = function(x, which = c("column", "row"),
2005 2005
 		min_y = min(unlist(density_y))
2006 2006
 		max_y = max(unlist(density_y))
2007 2007
 		col_fun = colorRamp2(seq(min_y, max_y, 
2008
-			length = length(heatmap_colors)), heatmap_colors)
2008
+			length.out = length(heatmap_colors)), heatmap_colors)
2009 2009
 	}
2010 2010
 
2011 2011
 	axis_param$direction = "normal"
... ...
@@ -2092,7 +2092,7 @@ anno_density = function(x, which = c("column", "row"),
2092 2092
 			min_y = min(unlist(density_y))
2093 2093
 			max_y = max(unlist(density_y))
2094 2094
 			col_fun = colorRamp2(seq(min_y, max_y, 
2095
-				length = length(heatmap_colors)), heatmap_colors)
2095
+				length.out = length(heatmap_colors)), heatmap_colors)
2096 2096
 		}
2097 2097
 
2098 2098
 		n = length(index)
Browse code

update

Zuguang Gu authored on 25/10/2021 10:18:45
Showing1 changed files
... ...
@@ -101,6 +101,18 @@ subset_matrix_by_row = function(x, i) x[i, , drop = FALSE]
101 101
 #
102 102
 subset_vector = function(x, i) x[i]
103 103
 
104
+# == title
105
+# Do not do subseting
106
+#
107
+# == param
108
+# -x A vector.
109
+# -i The indices.
110
+#
111
+# == details
112
+# Mainly used for constructing the `AnnotationFunction-class` object.
113
+#
114
+subset_no = function(x, i) x
115
+
104 116
 # == title
105 117
 # Simple Annotation
106 118
 #
... ...
@@ -4073,4 +4085,119 @@ anno_zoom = function(align_to, panel_fun = function(index, nm = NULL) { grid.rec
4073 4085
 	return(anno)
4074 4086
 }
4075 4087
 
4088
+# == title
4089
+# Customized annotation
4090
+#
4091
+# == param
4092
+# -x A categorical variable.
4093
+# -graphics A list of functions that define graphics for each level in ``x``.
4094
+# -which Is it a row annotation or a column annotation?
4095
+# -width Width of the annotation. The value should be an absolute unit. Width is not allowed to be set for column annotation.
4096
+# -height Height of the annotation. The value should be an absolute unit. Height is not allowed to be set for row annotation.
4097
+# -border Whether to draw border.
4098
+# -verbose Whether to print messages.
4099
+#
4100
+# == details
4101
+# Functions in ``graphics`` define simple graphics drawn in each annotation cell. The function takes four arguments:
4102
+#
4103
+# -x,y Center of the annotation cell.
4104
+# -w,h Width and height of the annotation cell.
4105
+#
4106
+# == value
4107
+# An annotation function which can be used in `HeatmapAnnotation`.
4108
+#
4109
+# == example
4110
+# x = sort(sample(letters[1:3], 10, replace = TRUE))
4111
+# graphics = list(
4112
+#     "a" = function(x, y, w, h) grid.points(x, y, pch = 16),
4113
+#     "b" = function(x, y, w, h) grid.rect(x, y, w*0.8, h*0.8, gp = gpar(fill = "red")),
4114
+#     "c" = function(x, y, w, h) grid.segments(x - 0.5*w, y - 0.5*h, x + 0.5*w, y + 0.5*h, gp = gpar(lty = 2))
4115
+# )
4116
+#
4117
+# anno = anno_customize(x, graphics = graphics)
4118
+#
4119
+# m = matrix(rnorm(100), 10)
4120
+# Heatmap(m, top_annotation = HeatmapAnnotation(bar = x, foo = anno))
4121
+#
4122
+# # Add legends for `foo`
4123
+# ht = Heatmap(m, top_annotation = HeatmapAnnotation(bar = x, foo = anno))
4124
+# lgd = Legend(title = "foo", at = names(graphics), graphics = graphics)
4125
+# draw(ht, annotation_legend_list = list(lgd))
4126
+anno_customize = function(x, graphics = list(), which = c("column", "row"),  
4127
+	border = TRUE, width = NULL, height = NULL, verbose = TRUE) {
4128
+
4129
+	if(is.null(.ENV$current_annotation_which)) {
4130
+		which = match.arg(which)[1]
4131
+	} else {
4132
+		which = .ENV$current_annotation_which
4133
+	}
4134
+
4135
+	anno_size = anno_width_and_height(which, width, height, unit(5, "mm"))
4136
+
4137
+	value = as.character(x)
4138
+	n = length(value)
4139
+
4140
+	if(verbose) {
4141
+		nm = setdiff(value, names(graphics))
4142
+		if(length(nm)) {
4143
+			message(qq("Note: following levels in `x` have no graphics defined:\n    @{paste(nm, collapse = ', ')}.\nSet `verbose = FALSE` in `anno_customize()` to turn off this message."))
4144
+		}
4145
+	}
4146
+
4147
+	row_fun = function(index, k = 1, N = 1) {
4148
+		
4149
+		n = length(index)
4150
+
4151
+		pushViewport(viewport(yscale = c(0.5, n+0.5)))
4152
+		for(i in seq_len(n)) {
4153
+			if(!is.null(graphics[[ value[index[i]] ]])) {
4154
+				fun = graphics[[ value[index[i]] ]]
4155
+				pushViewport(viewport(y = n-i+1, height = 1, default.units = "native"))
4156
+				fun(unit(0.5, "npc"), unit(0.5, "npc"), unit(1, "npc"), unit(1, "npc"))
4157
+				popViewport()
4158
+			}
4159
+		}
4160
+		if(border) grid.rect(gp = gpar(fill = "transparent"))
4161
+		popViewport()
4162
+	}
4163
+
4164
+	column_fun = function(index, k = 1, N = 1) {
4165
+		
4166
+		n = length(index)
4167
+
4168
+		pushViewport(viewport(xscale = c(0.5, n+0.5)))
4169
+		for(i in seq_len(n)) {
4170
+			if(!is.null(graphics[[ value[index[i]] ]])) {
4171
+				fun = graphics[[ value[index[i]] ]]
4172
+				pushViewport(viewport(x = i, width = 1, default.units = "native"))
4173
+				fun(unit(0.5, "npc"), unit(0.5, "npc"), unit(1, "npc"), unit(1, "npc"))
4174
+				popViewport()
4175
+			}
4176
+		}
4177
+		if(border) grid.rect(gp = gpar(fill = "transparent"))
4178
+		popViewport()
4179
+	}
4180
+
4181
+	if(which == "row") {
4182
+		fun = row_fun
4183
+	} else if(which == "column") {
4184
+		fun = column_fun
4185
+	}
4186
+
4187
+	anno = AnnotationFunction(
4188
+		fun = fun,
4189
+		fun_name = "anno_customize",
4190
+		which = which,
4191
+		width = anno_size$width,
4192
+		height = anno_size$height,
4193
+		n = n,
4194
+		var_import = list(value, border, graphics)
4195
+	)
4196
+
4197
+	anno@subset_rule$value = subset_vector
4198
+
4199
+	anno@subsetable = TRUE
4200
+		
4201
+	return(anno) 
4202
+}
4076 4203
 
Browse code

add new argument 'beside' in 'anno_barplot()'

Zuguang Gu authored on 28/09/2021 11:13:16
Showing1 changed files
... ...
@@ -1190,6 +1190,7 @@ anno_lines = function(x, which = c("column", "row"), border = TRUE, gp = gpar(),
1190 1190
 # -which Whether it is a column annotation or a row annotation?
1191 1191
 # -border Wether draw borders of the annotation region?
1192 1192
 # -bar_width Relative width of the bars. The value should be smaller than one.
1193
+# -beside When ``x`` is a matrix, will bars be positioned beside each other or as stacked bars?
1193 1194
 # -gp Graphic parameters for bars. The length of each graphic parameter can be 1, length of ``x`` if ``x``
1194 1195
 #     is a vector, or number of columns of ``x`` is ``x`` is a matrix.
1195 1196
 # -ylim Data ranges. By default it is ``range(x)`` if ``x`` is a vector, or ``range(rowSums(x))`` if ``x`` is a matrix.
... ...
@@ -1218,7 +1219,7 @@ anno_lines = function(x, which = c("column", "row"), border = TRUE, gp = gpar(),
1218 1219
 # m = t(apply(m, 1, function(x) x/sum(x)))
1219 1220
 # anno = anno_barplot(m, gp = gpar(fill = 2:5), bar_width = 1, height = unit(6, "cm"))
1220 1221
 # draw(anno, test = "proportion matrix")
1221
-anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TRUE, bar_width = 0.6,
1222
+anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TRUE, bar_width = 0.6, beside = FALSE,
1222 1223
 	gp = gpar(fill = "#CCCCCC"), ylim = NULL, extend = 0.05, axis = TRUE, 
1223 1224
 	axis_param = default_axis_param(which), 
1224 1225
 	add_numbers = FALSE, numbers_gp = gpar(fontsize = 8), 
... ...
@@ -1255,7 +1256,11 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1255 1256
 		gp = gpar(fill = grey(seq(0, 1, length = nc+2))[-c(1, nc+2)])
1256 1257
 	}
1257 1258
 
1258
-	data_scale = range(rowSums(x, na.rm = TRUE), na.rm = TRUE)
1259
+	if(beside) {
1260
+		data_scale = range(x, na.rm = TRUE)
1261
+	} else {
1262
+		data_scale = range(rowSums(x, na.rm = TRUE), na.rm = TRUE)
1263
+	}
1259 1264
 	if(!is.null(ylim)) data_scale = ylim
1260 1265
 	if(baseline == "min") {
1261 1266
 		data_scale = data_scale + c(0, extend)*(data_scale[2] - data_scale[1])
... ...
@@ -1265,7 +1270,7 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1265 1270
 		baseline = max(x)
1266 1271
 	} else {
1267 1272
 		if(is.numeric(baseline)) {
1268
-			if(baseline == 0 && all(abs(rowSums(x) - 1) < 1e-6)) {
1273
+			if(baseline == 0 && all(abs(rowSums(x) - 1) < 1e-6) && !beside) {
1269 1274
 				data_scale = c(0, 1)
1270 1275
 			} else if(baseline <= data_scale[1]) {
1271 1276
 				data_scale = c(baseline, extend*(data_scale[2] - baseline) + data_scale[2])
... ...
@@ -1348,16 +1353,32 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1348 1353
 				}
1349 1354
 			}
1350 1355
 		} else {
1351
-			for(i in seq_len(ncol(value))) {
1352
-				if(axis_param$direction == "normal") {
1353
-					width = abs(value[index, i])
1354
-					x_coor = rowSums(value[index, seq_len(i-1), drop = FALSE]) + width/2
1355
-					grid.rect(x = x_coor, y = n - seq_along(index) + 1, width = abs(width), height = 1*bar_width, default.units = "native", gp = subset_gp(gp, i))
1356
-				} else {
1357
-					width = value_origin[index, i] # the original width
1358
-					x_coor = rowSums(value_origin[index, seq_len(i-1), drop = FALSE]) + width/2 #distance to the right
1359
-					x_coor = data_scale[2] - x_coor + data_scale[1]
1360
-					grid.rect(x = x_coor, y = n - seq_along(index) + 1, width = abs(width), height = 1*bar_width, default.units = "native", gp = subset_gp(gp, i))
1356
+			if(beside) {
1357
+				nbar = ncol(value)
1358
+				nr = nrow(value)
1359
+				for(i in seq_along(index)) {
1360
+			        for(j in 1:nbar) {
1361
+			        	if(axis_param$direction == "normal") {
1362
+				        	grid.rect(x = baseline, y = nr-i+0.5 + (j-0.5)/nbar, width = value[index[i], j], height = 1/nbar*bar_width, just = c("left"),
1363
+				        		default.units = "native", gp = subset_gp(gp, j))
1364
+				        } else {
1365
+				        	grid.rect(x = baseline, y = nr-i+0.5 + (j-0.5)/nbar, width = value[index[i], j], height = 1/nbar*bar_width, just = c("right"),
1366
+				        		default.units = "native", gp = subset_gp(gp, j))
1367
+				        }
1368
+			        }
1369
+			    }
1370
+			} else {
1371
+				for(i in seq_len(ncol(value))) {
1372
+					if(axis_param$direction == "normal") {
1373
+						width = abs(value[index, i])
1374
+						x_coor = rowSums(value[index, seq_len(i-1), drop = FALSE]) + width/2
1375
+						grid.rect(x = x_coor, y = n - seq_along(index) + 1, width = abs(width), height = 1*bar_width, default.units = "native", gp = subset_gp(gp, i))
1376
+					} else {
1377
+						width = value_origin[index, i] # the original width
1378
+						x_coor = rowSums(value_origin[index, seq_len(i-1), drop = FALSE]) + width/2 #distance to the right
1379
+						x_coor = data_scale[2] - x_coor + data_scale[1]
1380
+						grid.rect(x = x_coor, y = n - seq_along(index) + 1, width = abs(width), height = 1*bar_width, default.units = "native", gp = subset_gp(gp, i))
1381
+					}
1361 1382
 				}
1362 1383
 			}
1363 1384
 		}
... ...
@@ -1397,16 +1418,32 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1397 1418
 				}
1398 1419
 			}
1399 1420
 		} else {
1400
-			for(i in seq_len(ncol(value))) {
1401
-				if(axis_param$direction == "normal") {
1402
-					height = value[index, i]
1403
-					y_coor = rowSums(value[index, seq_len(i-1), drop = FALSE]) + height/2
1404
-					grid.rect(y = y_coor, x = seq_along(index), height = abs(height), width = 1*bar_width, default.units = "native", gp = subset_gp(gp, i))
1405
-				} else {
1406
-					height = value_origin[index, i]
1407
-					y_coor = rowSums(value_origin[index, seq_len(i-1), drop = FALSE]) + height/2
1408
-					y_coor = data_scale[2] - y_coor + data_scale[1]
1409
-					grid.rect(y = y_coor, x = seq_along(index), height = abs(height), width = 1*bar_width, default.units = "native", gp = subset_gp(gp, i))
1421
+			if(beside) {
1422
+				nbar = ncol(value)
1423
+				nr = nrow(value)
1424
+				for(i in seq_along(index)) {
1425
+			        for(j in 1:nbar) {
1426
+			        	if(axis_param$direction == "normal") {
1427
+				        	grid.rect(y = baseline, x = nr-i+0.5 + (j-0.5)/nbar, height = value[index[i], j], width = 1/nbar*bar_width, just = c("bottom"),
1428
+				        		default.units = "native", gp = subset_gp(gp, j))
1429
+				        } else {
1430
+				        	grid.rect(y = baseline, x = nr-i+0.5 + (j-0.5)/nbar, height = value[index[i], j], width = 1/nbar*bar_width, just = c("top"),
1431
+				        		default.units = "native", gp = subset_gp(gp, j))
1432
+				        }
1433
+			        }
1434
+			    }
1435
+			} else {
1436
+				for(i in seq_len(ncol(value))) {
1437
+					if(axis_param$direction == "normal") {
1438
+						height = value[index, i]
1439
+						y_coor = rowSums(value[index, seq_len(i-1), drop = FALSE]) + height/2
1440
+						grid.rect(y = y_coor, x = seq_along(index), height = abs(height), width = 1*bar_width, default.units = "native", gp = subset_gp(gp, i))
1441
+					} else {
1442
+						height = value_origin[index, i]
1443
+						y_coor = rowSums(value_origin[index, seq_len(i-1), drop = FALSE]) + height/2
1444
+						y_coor = data_scale[2] - y_coor + data_scale[1]
1445
+						grid.rect(y = y_coor, x = seq_along(index), height = abs(height), width = 1*bar_width, default.units = "native", gp = subset_gp(gp, i))
1446
+					}
1410 1447
 				}
1411 1448
 			}
1412 1449
 		}
... ...
@@ -1435,7 +1472,7 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1435 1472
 		height = anno_size$height,
1436 1473
 		n = n,
1437 1474
 		data_scale = data_scale,
1438
-		var_import = list(value, gp, border, bar_width, baseline, axis, axis_param, axis_grob, data_scale, add_numbers, numbers_gp, numbers_offset, numbers_rot)
1475
+		var_import = list(value, gp, border, bar_width, baseline, beside, axis, axis_param, axis_grob, data_scale, add_numbers, numbers_gp, numbers_offset, numbers_rot)
1439 1476
 	)
1440 1477
 
1441 1478
 	anno@subset_rule$value = subset_matrix_by_row
Browse code

restrict the size of the temp raster image

Zuguang Gu authored on 28/09/2021 09:20:28
Showing1 changed files
... ...
@@ -1190,7 +1190,7 @@ anno_lines = function(x, which = c("column", "row"), border = TRUE, gp = gpar(),
1190 1190
 # -which Whether it is a column annotation or a row annotation?
1191 1191
 # -border Wether draw borders of the annotation region?
1192 1192
 # -bar_width Relative width of the bars. The value should be smaller than one.
1193
-# -gp Graphic parameters for points. The length of each graphic parameter can be 1, length of ``x`` if ``x``
1193
+# -gp Graphic parameters for bars. The length of each graphic parameter can be 1, length of ``x`` if ``x``
1194 1194
 #     is a vector, or number of columns of ``x`` is ``x`` is a matrix.
1195 1195
 # -ylim Data ranges. By default it is ``range(x)`` if ``x`` is a vector, or ``range(rowSums(x))`` if ``x`` is a matrix.
1196 1196
 # -extend The extension to both side of ``ylim``. The value is a percent value corresponding to ``ylim[2] - ylim[1]``.
Browse code

set max scale to 1 when dendrogram height is zero

Zuguang Gu authored on 08/09/2021 08:28:57
Showing1 changed files
... ...
@@ -1389,6 +1389,7 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1389 1389
 				if(!is.null(attr(value, "labels_format"))) {
1390 1390
 					txt = attr(value, "labels_format")(value[index])
1391 1391
 				}
1392
+				numbers_rot = numbers_rot %% 360
1392 1393
 				if(numbers_rot == 0) {
1393 1394
 					grid.text(txt, x = seq_along(index), y = unit(baseline + height, "native") + numbers_offset, default.units = "native", gp = subset_gp(numbers_gp, index), just = c("bottom"))
1394 1395
 				} else {
Browse code

adjust when numbers_rot = 0

Zuguang Gu authored on 04/08/2021 20:30:13
Showing1 changed files
... ...
@@ -1302,7 +1302,11 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1302 1302
 	if(ncol(value) == 1) {
1303 1303
 		if(add_numbers) {
1304 1304
 			if(which == "column") {
1305
-				extend = convertHeight(sin(numbers_rot/180*pi)*max_text_width(value, gp = numbers_gp) + numbers_offset + unit(4, "mm"), "mm", valueOnly = TRUE)/convertHeight(anno_size$height, "mm", valueOnly = TRUE)*(data_scale[2] - data_scale[1])
1305
+				if(numbers_rot == 0) {
1306
+					extend = convertHeight(max_text_height(value, gp = numbers_gp) + numbers_offset + unit(2, "mm"), "mm", valueOnly = TRUE)/convertHeight(anno_size$height, "mm", valueOnly = TRUE)*(data_scale[2] - data_scale[1])
1307
+				} else {
1308
+					extend = convertHeight(sin(numbers_rot/180*pi)*max_text_width(value, gp = numbers_gp) + numbers_offset + unit(4, "mm"), "mm", valueOnly = TRUE)/convertHeight(anno_size$height, "mm", valueOnly = TRUE)*(data_scale[2] - data_scale[1])
1309
+				}
1306 1310
 				data_scale[2] = data_scale[2] + extend
1307 1311
 			} else if(which == "row") {
1308 1312
 				extend = convertWidth(cos(numbers_rot/180*pi)*max_text_width(value, gp = numbers_gp) + numbers_offset + unit(4, "mm"), "mm", valueOnly = TRUE)/convertWidth(anno_size$width, "mm", valueOnly = TRUE)*(data_scale[2] - data_scale[1])
... ...
@@ -1385,7 +1389,11 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1385 1389
 				if(!is.null(attr(value, "labels_format"))) {
1386 1390
 					txt = attr(value, "labels_format")(value[index])
1387 1391
 				}
1388
-				grid.text(txt, x = seq_along(index), y = unit(baseline + height, "native") + numbers_offset, default.units = "native", gp = subset_gp(numbers_gp, index), just = c("left"), rot = numbers_rot)
1392
+				if(numbers_rot == 0) {
1393
+					grid.text(txt, x = seq_along(index), y = unit(baseline + height, "native") + numbers_offset, default.units = "native", gp = subset_gp(numbers_gp, index), just = c("bottom"))
1394
+				} else {
1395
+					grid.text(txt, x = seq_along(index), y = unit(baseline + height, "native") + numbers_offset, default.units = "native", gp = subset_gp(numbers_gp, index), just = c("left"), rot = numbers_rot)
1396
+				}
1389 1397
 			}
1390 1398
 		} else {
1391 1399
 			for(i in seq_len(ncol(value))) {
Browse code

correct variable name

Zuguang Gu authored on 03/08/2021 21:12:01
Showing1 changed files
... ...
@@ -1338,7 +1338,7 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1338 1338
 				} else {
1339 1339
 					txt = value_origin[index]
1340 1340
 					if(!is.null(attr(value, "labels_format"))) {
1341
-						txt = attr(value, "labels_format")(value[index])
1341
+						txt = attr(value, "labels_format")(value_origin[index])
1342 1342
 					}
1343 1343
 					grid.text(txt, x = unit(baseline + width, "native") - numbers_offset, y = n - seq_along(index) + 1, default.units = "native", gp = subset_gp(numbers_gp, index), just = c("right"), rot = numbers_rot)
1344 1344
 				}
Browse code

axis labels are automatical formatted for genomic coordinates

Zuguang Gu authored on 03/08/2021 21:05:45
Showing1 changed files
... ...
@@ -665,7 +665,7 @@ validate_axis_param = function(axis_param, which) {
665 665
 	return(dft)
666 666
 }
667 667
 
668
-construct_axis_grob = function(axis_param, which, data_scale) {
668
+construct_axis_grob = function(axis_param, which, data_scale, format = NULL) {
669 669
 	axis_param_default = default_axis_param(which)
670 670
 
671 671
 	for(nm in setdiff(names(axis_param_default), names(axis_param))) {
... ...
@@ -675,13 +675,20 @@ construct_axis_grob = function(axis_param, which, data_scale) {
675 675
 	if(is.null(axis_param$at)) {
676 676
 		at = pretty_breaks(data_scale)
677 677
 		axis_param$at = at
678
-		axis_param$labels = at
678
+		if(is.null(format)) {
679
+			axis_param$labels = at
680
+		} else {
681
+			axis_param$labels = format(at)
682
+		}
679 683
 	}
680 684
 
681 685
 	if(is.null(axis_param$labels)) {
682
-		axis_param$labels = axis_param$at
686
+		if(is.null(format)) {
687
+			axis_param$labels = axis_param$at
688
+		} else {
689
+			axis_param$labels = format(axis_param$at)
690
+		}
683 691
 	}
684
-
685 692
 	axis_param$scale = data_scale
686 693
 	axis_grob = do.call(annotation_axis_grob, axis_param)
687 694
 	return(axis_grob)
... ...
@@ -1239,6 +1246,8 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1239 1246
 			stop_wrap("Since `x` is a matrix, the sign of each row should be either all positive or all negative.")
1240 1247
 		}
1241 1248
 	}
1249
+
1250
+	labels_format = attr(x, "labels_format")
1242 1251
 	# convert everything to matrix
1243 1252
 	if(is.null(dim(x))) x = matrix(x, ncol = 1)
1244 1253
 	nc = ncol(x)
... ...
@@ -1288,6 +1297,7 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1288 1297
 	}
1289 1298
 
1290 1299
 	value = x
1300
+	attr(value, "labels_format") = labels_format
1291 1301
 
1292 1302
 	if(ncol(value) == 1) {
1293 1303
 		if(add_numbers) {
... ...
@@ -1302,7 +1312,7 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1302 1312
 	}
1303 1313
 
1304 1314
 	axis_param = validate_axis_param(axis_param, which)
1305
-	axis_grob = if(axis) construct_axis_grob(axis_param, which, data_scale) else NULL
1315
+	axis_grob = if(axis) construct_axis_grob(axis_param, which, data_scale, format = labels_format) else NULL
1306 1316
 
1307 1317
 	row_fun = function(index, k = 1, N = 1) {
1308 1318
 		n = length(index)
... ...
@@ -1320,9 +1330,17 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1320 1330
 			grid.rect(x = x_coor, y = n - seq_along(index) + 1, width = abs(width), height = 1*bar_width, default.units = "native", gp = subset_gp(gp, index))
1321 1331
 			if(add_numbers) {
1322 1332
 				if(axis_param$direction == "normal") {
1323
-					grid.text(value[index], x = unit(baseline + width, "native") + numbers_offset, y = n - seq_along(index) + 1, default.units = "native", gp = subset_gp(numbers_gp, index), just = c("left"), rot = numbers_rot)
1333
+					txt = value[index]
1334
+					if(!is.null(attr(value, "labels_format"))) {
1335
+						txt = attr(value, "labels_format")(value[index])
1336
+					}
1337
+					grid.text(txt, x = unit(baseline + width, "native") + numbers_offset, y = n - seq_along(index) + 1, default.units = "native", gp = subset_gp(numbers_gp, index), just = c("left"), rot = numbers_rot)
1324 1338
 				} else {
1325
-					grid.text(value_origin[index], x = unit(baseline + width, "native") - numbers_offset, y = n - seq_along(index) + 1, default.units = "native", gp = subset_gp(numbers_gp, index), just = c("right"), rot = numbers_rot)
1339
+					txt = value_origin[index]
1340
+					if(!is.null(attr(value, "labels_format"))) {
1341
+						txt = attr(value, "labels_format")(value[index])
1342
+					}
1343
+					grid.text(txt, x = unit(baseline + width, "native") - numbers_offset, y = n - seq_along(index) + 1, default.units = "native", gp = subset_gp(numbers_gp, index), just = c("right"), rot = numbers_rot)
1326 1344
 				}
1327 1345
 			}
1328 1346
 		} else {
... ...
@@ -1363,7 +1381,11 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1363 1381
 			y_coor = height/2+baseline
1364 1382
 			grid.rect(y = y_coor, x = seq_along(index), height = abs(height), width = 1*bar_width, default.units = "native", gp = subset_gp(gp, index))
1365 1383
 			if(add_numbers) {
1366
-				grid.text(value[index], x = seq_along(index), y = unit(baseline + height, "native") + numbers_offset, default.units = "native", gp = subset_gp(numbers_gp, index), just = c("left"), rot = numbers_rot)
1384
+				txt = value[index]
1385
+				if(!is.null(attr(value, "labels_format"))) {
1386
+					txt = attr(value, "labels_format")(value[index])
1387
+				}
1388
+				grid.text(txt, x = seq_along(index), y = unit(baseline + height, "native") + numbers_offset, default.units = "native", gp = subset_gp(numbers_gp, index), just = c("left"), rot = numbers_rot)
1367 1389
 			}
1368 1390
 		} else {
1369 1391
 			for(i in seq_len(ncol(value))) {
Browse code

add numbers to the barplot annotations

Zuguang Gu authored on 03/08/2021 12:22:45
Showing1 changed files
... ...
@@ -1189,6 +1189,10 @@ anno_lines = function(x, which = c("column", "row"), border = TRUE, gp = gpar(),
1189 1189
 # -extend The extension to both side of ``ylim``. The value is a percent value corresponding to ``ylim[2] - ylim[1]``.
1190 1190
 # -axis Whether to add axis?
1191 1191
 # -axis_param parameters for controlling axis. See `default_axis_param` for all possible settings and default parameters.
1192
+# -add_numbers Whether to add numbers to the bars. It only works when ``x`` is a simple vector.
1193
+# -numbers_gp Graphics parameters for the numbers.
1194
+# -numbers_rot Rotation of numbers.
1195
+# -numbers_offset Offset to the default positions (1mm away the top of the bars).
1192 1196
 # -width Width of the annotation. The value should be an absolute unit. Width is not allowed to be set for column annotation.
1193 1197
 # -height Height of the annotation. The value should be an absolute unit. Height is not allowed to be set for row annotation.
1194 1198
 # -... Other arguments.
... ...
@@ -1209,7 +1213,9 @@ anno_lines = function(x, which = c("column", "row"), border = TRUE, gp = gpar(),
1209 1213
 # draw(anno, test = "proportion matrix")
1210 1214
 anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TRUE, bar_width = 0.6,
1211 1215
 	gp = gpar(fill = "#CCCCCC"), ylim = NULL, extend = 0.05, axis = TRUE, 
1212
-	axis_param = default_axis_param(which),
1216
+	axis_param = default_axis_param(which), 
1217
+	add_numbers = FALSE, numbers_gp = gpar(fontsize = 8), 
1218
+	numbers_rot = ifelse(which == "column", 45, 0), numbers_offset = unit(2, "mm"),
1213 1219
 	width = NULL, height = NULL, ...) {
1214 1220
 
1215 1221
 	other_args = list(...)
... ...
@@ -1282,6 +1288,19 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1282 1288
 	}
1283 1289
 
1284 1290
 	value = x
1291
+
1292
+	if(ncol(value) == 1) {
1293
+		if(add_numbers) {
1294
+			if(which == "column") {
1295
+				extend = convertHeight(sin(numbers_rot/180*pi)*max_text_width(value, gp = numbers_gp) + numbers_offset + unit(4, "mm"), "mm", valueOnly = TRUE)/convertHeight(anno_size$height, "mm", valueOnly = TRUE)*(data_scale[2] - data_scale[1])
1296
+				data_scale[2] = data_scale[2] + extend
1297
+			} else if(which == "row") {
1298
+				extend = convertWidth(cos(numbers_rot/180*pi)*max_text_width(value, gp = numbers_gp) + numbers_offset + unit(4, "mm"), "mm", valueOnly = TRUE)/convertWidth(anno_size$width, "mm", valueOnly = TRUE)*(data_scale[2] - data_scale[1])
1299
+				data_scale[2] = data_scale[2] + extend
1300
+			}
1301
+		}
1302
+	}
1303
+
1285 1304
 	axis_param = validate_axis_param(axis_param, which)
1286 1305
 	axis_grob = if(axis) construct_axis_grob(axis_param, which, data_scale) else NULL
1287 1306
 
... ...
@@ -1299,6 +1318,13 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1299 1318
 			width = value[index] - baseline
1300 1319
 			x_coor = width/2+baseline
1301 1320
 			grid.rect(x = x_coor, y = n - seq_along(index) + 1, width = abs(width), height = 1*bar_width, default.units = "native", gp = subset_gp(gp, index))
1321
+			if(add_numbers) {
1322
+				if(axis_param$direction == "normal") {
1323
+					grid.text(value[index], x = unit(baseline + width, "native") + numbers_offset, y = n - seq_along(index) + 1, default.units = "native", gp = subset_gp(numbers_gp, index), just = c("left"), rot = numbers_rot)
1324
+				} else {
1325
+					grid.text(value_origin[index], x = unit(baseline + width, "native") - numbers_offset, y = n - seq_along(index) + 1, default.units = "native", gp = subset_gp(numbers_gp, index), just = c("right"), rot = numbers_rot)
1326
+				}
1327
+			}
1302 1328
 		} else {
1303 1329
 			for(i in seq_len(ncol(value))) {
1304 1330
 				if(axis_param$direction == "normal") {
... ...
@@ -1336,6 +1362,9 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1336 1362
 			height = value[index] - baseline
1337 1363
 			y_coor = height/2+baseline
1338 1364
 			grid.rect(y = y_coor, x = seq_along(index), height = abs(height), width = 1*bar_width, default.units = "native", gp = subset_gp(gp, index))
1365
+			if(add_numbers) {
1366
+				grid.text(value[index], x = seq_along(index), y = unit(baseline + height, "native") + numbers_offset, default.units = "native", gp = subset_gp(numbers_gp, index), just = c("left"), rot = numbers_rot)
1367
+			}
1339 1368
 		} else {
1340 1369
 			for(i in seq_len(ncol(value))) {
1341 1370
 				if(axis_param$direction == "normal") {
... ...
@@ -1375,7 +1404,7 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
1375 1404
 		height = anno_size$height,
1376 1405
 		n = n,
1377 1406
 		data_scale = data_scale,
1378
-		var_import = list(value, gp, border, bar_width, baseline, axis, axis_param, axis_grob, data_scale)
1407
+		var_import = list(value, gp, border, bar_width, baseline, axis, axis_param, axis_grob, data_scale, add_numbers, numbers_gp, numbers_offset, numbers_rot)
1379 1408
 	)
1380 1409
 
1381 1410
 	anno@subset_rule$value = subset_matrix_by_row
Browse code

neighbour annotation grids are merged if they have the same value

Zuguang Gu authored on 03/08/2021 08:49:11
Showing1 changed files
... ...
@@ -160,7 +160,7 @@ subset_vector = function(x, i) x[i]
160 160
 # anno = anno_simple(cbind(1:10, 10:1), pch = pch)
161 161
 # draw(anno, test = "matrix, pch is a matrix with NA values")
162 162
 anno_simple = function(x, col, na_col = "grey", 
163
-	which = c("column", "row"), border = FALSE, gp = gpar(col = NA),
163
+	which = c("column", "row"), border = FALSE, gp = gpar(),
164 164
 	pch = NULL, pt_size = unit(1, "snpc")*0.8, pt_gp = gpar(), 
165 165
 	simple_anno_size = ht_opt$simple_anno_size,
166 166
 	width = NULL, height = NULL) {
... ...
@@ -230,8 +230,16 @@ anno_simple = function(x, col, na_col = "grey",
230 230
 			pch = pch[index, , drop = FALSE]
231 231
 
232 232
 			for(i in seq_len(nc)) {
233
-			    fill = map_to_colors(color_mapping, value[index, i])
234
-			    grid.rect(x = (i-0.5)/nc, y, height = 1/n, width = 1/nc, gp = do.call("gpar", c(list(fill = fill), gp)))
233
+				if(color_mapping@type == "continuous") {
234
+				    fill = map_to_colors(color_mapping, value[index, i])
235
+				    if(is.null(gp$col)) gp$col = fill
236
+				    grid.rect(x = (i-0.5)/nc, y, height = 1/n, width = 1/nc, gp = do.call("gpar", c(list(fill = fill), gp)))
237
+				} else {
238
+					r = rle(value[index, i])
239
+					fill = map_to_colors(color_mapping, r$values)
240
+					if(is.null(gp$col)) gp$col = fill
241
+					grid.rect(x = (i-0.5)/nc, y = 1 - cumsum(r$lengths)/n, height = r$length/n, width = 1/nc, just = "bottom", gp = do.call("gpar", c(list(fill = fill), gp)))
242
+				}
235 243
 			    if(!is.null(pch)) {
236 244
 					l = !is.na(pch[, i])
237 245
 					if(any(l)) {
... ...
@@ -249,8 +257,16 @@ anno_simple = function(x, col, na_col = "grey",
249 257
 			    }
250 258
 			}
251 259
 	    } else {
252
-			fill = map_to_colors(color_mapping, value[index])
253
-			grid.rect(x = 0.5, y, height = 1/n, width = 1, gp = do.call("gpar", c(list(fill = fill), gp)))