... | ... |
@@ -1561,8 +1561,10 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR |
1561 | 1561 |
# -extend The extension to both side of ``ylim``. The value is a percent value corresponding to ``ylim[2] - ylim[1]``. |
1562 | 1562 |
# -outline Whether draw outline of boxplots? |
1563 | 1563 |
# -box_width Relative width of boxes. The value should be smaller than one. |
1564 |
+# -add_points Whether add points on top of the boxes? |
|
1564 | 1565 |
# -pch Point style. |
1565 | 1566 |
# -size Point size. |
1567 |
+# -pt_gp Graphics parameters for points. |
|
1566 | 1568 |
# -axis Whether to add axis? |
1567 | 1569 |
# -axis_param parameters for controlling axis. See `default_axis_param` for all possible settings and default parameters. |
1568 | 1570 |
# -width Width of the annotation. The value should be an absolute unit. Width is not allowed to be set for column annotation. |
... | ... |
@@ -1584,8 +1586,8 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR |
1584 | 1586 |
# draw(anno, test = "anno_boxplot with gp") |
1585 | 1587 |
anno_boxplot = function(x, which = c("column", "row"), border = TRUE, |
1586 | 1588 |
gp = gpar(fill = "#CCCCCC"), ylim = NULL, extend = 0.05, outline = TRUE, box_width = 0.6, |
1587 |
- pch = 1, size = unit(2, "mm"), axis = TRUE, axis_param = default_axis_param(which), |
|
1588 |
- width = NULL, height = NULL, ...) { |
|
1589 |
+ add_points = FALSE, pch = 16, size = unit(4, "pt"), pt_gp = gpar(), axis = TRUE, |
|
1590 |
+ axis_param = default_axis_param(which), width = NULL, height = NULL, ...) { |
|
1589 | 1591 |
|
1590 | 1592 |
other_args = list(...) |
1591 | 1593 |
if(length(other_args)) { |
... | ... |
@@ -1639,6 +1641,7 @@ anno_boxplot = function(x, which = c("column", "row"), border = TRUE, |
1639 | 1641 |
|
1640 | 1642 |
n = length(value) |
1641 | 1643 |
gp = recycle_gp(gp, n) |
1644 |
+ pt_gp = recycle_gp(pt_gp, n) |
|
1642 | 1645 |
if(length(pch) == 1) pch = rep(pch, n) |
1643 | 1646 |
if(length(size) == 1) size = rep(size, n) |
1644 | 1647 |
|
... | ... |
@@ -1657,6 +1660,7 @@ anno_boxplot = function(x, which = c("column", "row"), border = TRUE, |
1657 | 1660 |
|
1658 | 1661 |
n = length(index) |
1659 | 1662 |
gp = subset_gp(gp, index) |
1663 |
+ pt_gp = subset_gp(pt_gp, index) |
|
1660 | 1664 |
pch = pch[index] |
1661 | 1665 |
size = size[index] |
1662 | 1666 |
pushViewport(viewport(xscale = data_scale, yscale = c(0.5, n+0.5))) |
... | ... |
@@ -1680,18 +1684,25 @@ anno_boxplot = function(x, which = c("column", "row"), border = TRUE, |
1680 | 1684 |
grid.segments(boxplot_stats[3, ], n - seq_along(index) + 1 - 0.5*box_width, |
1681 | 1685 |
boxplot_stats[3, ], n - seq_along(index) + 1 + 0.5*box_width, |
1682 | 1686 |
default.units = "native", gp = gp) |
1683 |
- if(outline) { |
|
1687 |
+ if(!add_points && outline) { |
|
1684 | 1688 |
for(i in seq_along(value)) { |
1685 | 1689 |
l1 = value[[i]] > boxplot_stats[5,i] |
1686 | 1690 |
l1[is.na(l1)] = FALSE |
1687 | 1691 |
if(sum(l1)) grid.points(y = rep(n - i + 1, sum(l1)), x = value[[i]][l1], |
1688 |
- default.units = "native", gp = subset_gp(gp, i), pch = pch[i], size = size[i]) |
|
1692 |
+ default.units = "native", gp = subset_gp(pt_gp, i), pch = pch[i], size = size[i]) |
|
1689 | 1693 |
l2 = value[[i]] < boxplot_stats[1,i] |
1690 | 1694 |
l2[is.na(l2)] = FALSE |
1691 | 1695 |
if(sum(l2)) grid.points(y = rep(n - i + 1, sum(l2)), x = value[[i]][l2], |
1692 |
- default.units = "native", gp = subset_gp(gp, i), pch = pch[i], size = size[i]) |
|
1696 |
+ default.units = "native", gp = subset_gp(pt_gp, i), pch = pch[i], size = size[i]) |
|
1697 |
+ } |
|
1698 |
+ } |
|
1699 |
+ if(add_points && outline) { |
|
1700 |
+ for(i in seq_along(value)) { |
|
1701 |
+ grid.points(y = n - runif(length(value[[i]]), min = i - 0.5*0.5*box_width, max = i + 0.5*0.5*box_width) + 1, |
|
1702 |
+ x = value[[i]], default.units = "native", gp = subset_gp(pt_gp, i), pch = pch[i], size = size[i]) |
|
1693 | 1703 |
} |
1694 | 1704 |
} |
1705 |
+ |
|
1695 | 1706 |
if(axis_param$side == "top") { |
1696 | 1707 |
if(k > 1) axis = FALSE |
1697 | 1708 |
} else if(axis_param$side == "bottom") { |
... | ... |
@@ -1712,6 +1723,7 @@ anno_boxplot = function(x, which = c("column", "row"), border = TRUE, |
1712 | 1723 |
|
1713 | 1724 |
n = length(index) |
1714 | 1725 |
gp = subset_gp(gp, index) |
1726 |
+ pt_gp = subset_gp(pt_gp, index) |
|
1715 | 1727 |
pch = pch[index] |
1716 | 1728 |
size = size[index] |
1717 | 1729 |
pushViewport(viewport(xscale = c(0.5, n+0.5), yscale = data_scale)) |
... | ... |
@@ -1734,16 +1746,24 @@ anno_boxplot = function(x, which = c("column", "row"), border = TRUE, |
1734 | 1746 |
grid.segments(seq_along(index) - 0.5*box_width, boxplot_stats[3, ], |
1735 | 1747 |
seq_along(index) + 0.5*box_width, boxplot_stats[3, ], |
1736 | 1748 |
default.units = "native", gp = gp) |
1737 |
- if(outline) { |
|
1749 |
+ |
|
1750 |
+ if(!add_points && outline) { |
|
1738 | 1751 |
for(i in seq_along(value)) { |
1739 | 1752 |
l1 = value[[i]] > boxplot_stats[5,i] |
1740 | 1753 |
l1[is.na(l1)] = FALSE |
1741 | 1754 |
if(sum(l1)) grid.points(x = rep(i, sum(l1)), y = value[[i]][l1], |
1742 |
- default.units = "native", gp = subset_gp(gp, i), pch = pch[i], size = size[i]) |
|
1755 |
+ default.units = "native", gp = subset_gp(pt_gp, i), pch = pch[i], size = size[i]) |
|
1743 | 1756 |
l2 = value[[i]] < boxplot_stats[1,i] |
1744 | 1757 |
l2[is.na(l2)] = FALSE |
1745 | 1758 |
if(sum(l2)) grid.points(x = rep(i, sum(l2)), y = value[[i]][l2], |
1746 |
- default.units = "native", gp = subset_gp(gp, i), pch = pch[i], size = size[i]) |
|
1759 |
+ default.units = "native", gp = subset_gp(pt_gp, i), pch = pch[i], size = size[i]) |
|
1760 |
+ } |
|
1761 |
+ } |
|
1762 |
+ |
|
1763 |
+ if(add_points && outline) { |
|
1764 |
+ for(i in seq_along(value)) { |
|
1765 |
+ grid.points(x = runif(length(value[[i]]), min = i - 0.5*0.5*box_width, max = i + 0.5*0.5*box_width), |
|
1766 |
+ y = value[[i]], default.units = "native", gp = subset_gp(pt_gp, i), pch = pch[i], size = size[i]) |
|
1747 | 1767 |
} |
1748 | 1768 |
} |
1749 | 1769 |
if(axis_param$side == "left") { |
... | ... |
@@ -1770,11 +1790,12 @@ anno_boxplot = function(x, which = c("column", "row"), border = TRUE, |
1770 | 1790 |
width = anno_size$width, |
1771 | 1791 |
height = anno_size$height, |
1772 | 1792 |
data_scale = data_scale, |
1773 |
- var_import = list(value, gp, border, box_width, axis, axis_param, axis_grob, data_scale, pch, size, outline) |
|
1793 |
+ var_import = list(value, gp, border, box_width, axis, axis_param, axis_grob, data_scale, add_points, pch, pt_gp, size, outline) |
|
1774 | 1794 |
) |
1775 | 1795 |
|
1776 | 1796 |
anno@subset_rule$value = subset_vector |
1777 | 1797 |
anno@subset_rule$gp = subset_gp |
1798 |
+ anno@subset_rule$pt_gp = subset_gp |
|
1778 | 1799 |
anno@subset_rule$pch = subset_vector |
1779 | 1800 |
anno@subset_rule$size = subset_vector |
1780 | 1801 |
|
... | ... |
@@ -1396,7 +1396,7 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR |
1396 | 1396 |
} else { |
1397 | 1397 |
if(beside) { |
1398 | 1398 |
nbar = ncol(value) |
1399 |
- nr = nrow(value) |
|
1399 |
+ nr = length(index) |
|
1400 | 1400 |
for(i in seq_along(index)) { |
1401 | 1401 |
for(j in 1:nbar) { |
1402 | 1402 |
if(attach) { |
... | ... |
@@ -1471,7 +1471,7 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR |
1471 | 1471 |
} else { |
1472 | 1472 |
if(beside) { |
1473 | 1473 |
nbar = ncol(value) |
1474 |
- nr = nrow(value) |
|
1474 |
+ nr = length(index) |
|
1475 | 1475 |
for(i in seq_along(index)) { |
1476 | 1476 |
for(j in 1:nbar) { |
1477 | 1477 |
if(attach) { |
... | ... |
@@ -2112,17 +2112,17 @@ anno_density = function(x, which = c("column", "row"), |
2112 | 2112 |
width = density_x[[i]][-1] - density_x[[i]][-n_breaks], height = 1, |
2113 | 2113 |
just = c("right", "bottom"), default.units = "native", |
2114 | 2114 |
gp = gpar(fill = col_fun((density_y[[i]][-1] + density_y[[i]][-n_breaks])/2), |
2115 |
- col = NA)) |
|
2115 |
+ col = col_fun((density_y[[i]][-1] + density_y[[i]][-n_breaks])/2))) |
|
2116 | 2116 |
if(density_x[[i]][1] - min_density_x > 0) { |
2117 | 2117 |
grid.rect(x = density_x[[i]][1], y = 0, width = density_x[[i]][1] - min_density_x, |
2118 | 2118 |
height = 1, just = c("right", "bottom"), default.units = "native", |
2119 |
- gp = gpar(fill = col_fun(0), col = NA)) |
|
2119 |
+ gp = gpar(fill = col_fun(0), col = col_fun(0))) |
|
2120 | 2120 |
} |
2121 | 2121 |
if(max_density_x - density_x[[i]][n_breaks] > 0) { |
2122 | 2122 |
grid.rect(x = density_x[[i]][n_breaks], y = 0, |
2123 | 2123 |
width = max_density_x - density_x[[i]][n_breaks], height = 1, |
2124 | 2124 |
just = c("left", "bottom"), default.units = "native", |
2125 |
- gp = gpar(fill = col_fun(0), col = NA)) |
|
2125 |
+ gp = gpar(fill = col_fun(0), col = col_fun(0))) |
|
2126 | 2126 |
} |
2127 | 2127 |
} |
2128 | 2128 |
popViewport() |
... | ... |
@@ -2149,8 +2149,6 @@ anno_density = function(x, which = c("column", "row"), |
2149 | 2149 |
density_x = density_x[index] |
2150 | 2150 |
density_y = density_y[index] |
2151 | 2151 |
|
2152 |
- yscale = range(unlist(density_x), na.rm = TRUE) |
|
2153 |
- yscale = yscale + c(0, 0.05)*(yscale[2] - yscale[1]) |
|
2154 | 2152 |
if(type == "lines") { |
2155 | 2153 |
xscale = c(0, max(unlist(density_y))) |
2156 | 2154 |
xscale[2] = xscale[2]*1.05 |
... | ... |
@@ -2158,7 +2156,6 @@ anno_density = function(x, which = c("column", "row"), |
2158 | 2156 |
xscale = max(unlist(density_y)) |
2159 | 2157 |
xscale = c(-xscale*1.05, xscale*1.05) |
2160 | 2158 |
} else if(type == "heatmap") { |
2161 |
- yscale = range(unlist(density_x), na.rm = TRUE) |
|
2162 | 2159 |
xscale = c(0, 1) |
2163 | 2160 |
min_y = min(unlist(density_y)) |
2164 | 2161 |
max_y = max(unlist(density_y)) |
... | ... |
@@ -2192,17 +2189,17 @@ anno_density = function(x, which = c("column", "row"), |
2192 | 2189 |
height = density_x[[i]][-1] - density_x[[i]][-n_breaks], width = 1, |
2193 | 2190 |
just = c("left", "top"), default.units = "native", |
2194 | 2191 |
gp = gpar(fill = col_fun((density_y[[i]][-1] + density_y[[i]][-n_breaks])/2), |
2195 |
- col = NA)) |
|
2192 |
+ col = col_fun((density_y[[i]][-1] + density_y[[i]][-n_breaks])/2))) |
|
2196 | 2193 |
if(density_x[[i]][1] - min_density_x > 0) { |
2197 | 2194 |
grid.rect(y = density_x[[i]][1], x = 0, height = density_x[[i]][1] - min_density_x, |
2198 | 2195 |
width = 1, just = c("left", "top"), default.units = "native", |
2199 |
- gp = gpar(fill = col_fun(0), col = NA)) |
|
2196 |
+ gp = gpar(fill = col_fun(0), col = col_fun(0))) |
|
2200 | 2197 |
} |
2201 | 2198 |
if(max_density_x - density_x[[i]][n_breaks] > 0) { |
2202 | 2199 |
grid.rect(y = density_x[[i]][n_breaks], x = 0, |
2203 | 2200 |
height = max_density_x - density_x[[i]][n_breaks], width = 1, |
2204 | 2201 |
just = c("left", "bottom"), default.units = "native", |
2205 |
- gp = gpar(fill = col_fun(0), col = NA)) |
|
2202 |
+ gp = gpar(fill = col_fun(0), col = col_fun(0))) |
|
2206 | 2203 |
} |
2207 | 2204 |
} |
2208 | 2205 |
popViewport() |
... | ... |
@@ -2042,6 +2042,8 @@ anno_density = function(x, which = c("column", "row"), |
2042 | 2042 |
density_x[[i]] = c(density_x[[i]][ 1 ], density_x[[i]], density_x[[i]][ length(density_x[[i]]) ]) |
2043 | 2043 |
density_y[[i]] = c(0, density_y[[i]], 0) |
2044 | 2044 |
} |
2045 |
+ min_density_x = xlim[1] |
|
2046 |
+ max_density_x = xlim[2] |
|
2045 | 2047 |
} |
2046 | 2048 |
|
2047 | 2049 |
if(type == "lines") { |
... | ... |
@@ -2111,13 +2113,17 @@ anno_density = function(x, which = c("column", "row"), |
2111 | 2113 |
just = c("right", "bottom"), default.units = "native", |
2112 | 2114 |
gp = gpar(fill = col_fun((density_y[[i]][-1] + density_y[[i]][-n_breaks])/2), |
2113 | 2115 |
col = NA)) |
2114 |
- grid.rect(x = density_x[[i]][1], y = 0, width = density_x[[i]][1] - min_density_x, |
|
2115 |
- height = 1, just = c("right", "bottom"), default.units = "native", |
|
2116 |
- gp = gpar(fill = col_fun(0), col = NA)) |
|
2117 |
- grid.rect(x = density_x[[i]][n_breaks], y = 0, |
|
2118 |
- width = max_density_x - density_x[[i]][n_breaks], height = 1, |
|
2119 |
- just = c("left", "bottom"), default.units = "native", |
|
2120 |
- gp = gpar(fill = col_fun(0), col = NA)) |
|
2116 |
+ if(density_x[[i]][1] - min_density_x > 0) { |
|
2117 |
+ grid.rect(x = density_x[[i]][1], y = 0, width = density_x[[i]][1] - min_density_x, |
|
2118 |
+ height = 1, just = c("right", "bottom"), default.units = "native", |
|
2119 |
+ gp = gpar(fill = col_fun(0), col = NA)) |
|
2120 |
+ } |
|
2121 |
+ if(max_density_x - density_x[[i]][n_breaks] > 0) { |
|
2122 |
+ grid.rect(x = density_x[[i]][n_breaks], y = 0, |
|
2123 |
+ width = max_density_x - density_x[[i]][n_breaks], height = 1, |
|
2124 |
+ just = c("left", "bottom"), default.units = "native", |
|
2125 |
+ gp = gpar(fill = col_fun(0), col = NA)) |
|
2126 |
+ } |
|
2121 | 2127 |
} |
2122 | 2128 |
popViewport() |
2123 | 2129 |
} |
... | ... |
@@ -2187,13 +2193,17 @@ anno_density = function(x, which = c("column", "row"), |
2187 | 2193 |
just = c("left", "top"), default.units = "native", |
2188 | 2194 |
gp = gpar(fill = col_fun((density_y[[i]][-1] + density_y[[i]][-n_breaks])/2), |
2189 | 2195 |
col = NA)) |
2190 |
- grid.rect(y = density_x[[i]][1], x = 0, height = density_x[[i]][1] - min_density_x, |
|
2191 |
- width = 1, just = c("left", "top"), default.units = "native", |
|
2192 |
- gp = gpar(fill = col_fun(0), col = NA)) |
|
2193 |
- grid.rect(y = density_x[[i]][n_breaks], x = 0, |
|
2194 |
- height = max_density_x - density_x[[i]][n_breaks], width = 1, |
|
2195 |
- just = c("left", "bottom"), default.units = "native", |
|
2196 |
- gp = gpar(fill = col_fun(0), col = NA)) |
|
2196 |
+ if(density_x[[i]][1] - min_density_x > 0) { |
|
2197 |
+ grid.rect(y = density_x[[i]][1], x = 0, height = density_x[[i]][1] - min_density_x, |
|
2198 |
+ width = 1, just = c("left", "top"), default.units = "native", |
|
2199 |
+ gp = gpar(fill = col_fun(0), col = NA)) |
|
2200 |
+ } |
|
2201 |
+ if(max_density_x - density_x[[i]][n_breaks] > 0) { |
|
2202 |
+ grid.rect(y = density_x[[i]][n_breaks], x = 0, |
|
2203 |
+ height = max_density_x - density_x[[i]][n_breaks], width = 1, |
|
2204 |
+ just = c("left", "bottom"), default.units = "native", |
|
2205 |
+ gp = gpar(fill = col_fun(0), col = NA)) |
|
2206 |
+ } |
|
2197 | 2207 |
} |
2198 | 2208 |
popViewport() |
2199 | 2209 |
} |
... | ... |
@@ -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 |
} |
... | ... |
@@ -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 |
|
... | ... |
@@ -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 |
+ |
... | ... |
@@ -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) |
... | ... |
@@ -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) |
... | ... |
@@ -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 |
|
... | ... |
@@ -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 |
... | ... |
@@ -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 |