Skip to content

Commit

Permalink
add numbers to the barplot annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
jokergoo committed Aug 3, 2021
1 parent 7e46f0a commit 00490f9
Show file tree
Hide file tree
Showing 19 changed files with 238 additions and 43 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ export("subset_matrix_by_row")
export("subset_vector")
export("test_alter_fun")
export("unify_mat_list")
export("upset_left_annotation")
export("upset_right_annotation")
export("upset_top_annotation")
exportClasses("AdditiveUnit")
Expand Down
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ CHANGES in VERSION 2.9.3
* legends: fixed a bug of the grid heights were not correctedly calculated.
* discrete annotations: neighbour grids are merged into one single grid if they have the
same values.
* `anno_barplot()`: allows to add numbers on top of bars.

=========================

Expand Down
46 changes: 23 additions & 23 deletions R/00_S4_generic_methods.R
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
setGeneric('draw_title', function(object, ...) standardGeneric('draw_title'))
setGeneric('annotation_legend_size', function(object, ...) standardGeneric('annotation_legend_size'))
setGeneric('attach_annotation', function(object, ...) standardGeneric('attach_annotation'))
setGeneric('draw_heatmap_legend', function(object, ...) standardGeneric('draw_heatmap_legend'))
setGeneric('draw_dend', function(object, ...) standardGeneric('draw_dend'))
setGeneric('add_heatmap', function(object, ...) standardGeneric('add_heatmap'))
setGeneric('draw_dimnames', function(object, ...) standardGeneric('draw_dimnames'))
setGeneric('component_height', function(object, ...) standardGeneric('component_height'))
setGeneric('draw_annotation_legend', function(object, ...) standardGeneric('draw_annotation_legend'))
setGeneric('make_layout', function(object, ...) standardGeneric('make_layout'))
setGeneric('row_order', function(object, ...) standardGeneric('row_order'))
setGeneric('re_size', function(object, ...) standardGeneric('re_size'))
setGeneric('get_legend_param_list', function(object, ...) standardGeneric('get_legend_param_list'))
setGeneric('column_dend', function(object, ...) standardGeneric('column_dend'))
setGeneric('draw_title', function(object, ...) standardGeneric('draw_title'))
setGeneric('set_component_width', function(object, ...) standardGeneric('set_component_width'))
setGeneric('map_to_colors', function(object, ...) standardGeneric('map_to_colors'))
setGeneric('make_layout', function(object, ...) standardGeneric('make_layout'))
setGeneric('row_dend', function(object, ...) standardGeneric('row_dend'))
setGeneric('add_heatmap', function(object, ...) standardGeneric('add_heatmap'))
setGeneric('component_height', function(object, ...) standardGeneric('component_height'))
setGeneric('heatmap_legend_size', function(object, ...) standardGeneric('heatmap_legend_size'))
setGeneric('make_row_cluster', function(object, ...) standardGeneric('make_row_cluster'))
setGeneric('draw_heatmap_body', function(object, ...) standardGeneric('draw_heatmap_body'))
setGeneric('copy_all', function(object, ...) standardGeneric('copy_all'))
setGeneric('draw_annotation', function(object, ...) standardGeneric('draw_annotation'))
setGeneric('draw', function(object, ...) standardGeneric('draw'))
setGeneric('prepare', function(object, ...) standardGeneric('prepare'))
setGeneric('make_column_cluster', function(object, ...) standardGeneric('make_column_cluster'))
setGeneric('adjust_heatmap_list', function(object, ...) standardGeneric('adjust_heatmap_list'))
setGeneric('set_component_width', function(object, ...) standardGeneric('set_component_width'))
setGeneric('draw_heatmap_list', function(object, ...) standardGeneric('draw_heatmap_list'))
setGeneric('draw_dend', function(object, ...) standardGeneric('draw_dend'))
setGeneric('heatmap_legend_size', function(object, ...) standardGeneric('heatmap_legend_size'))
setGeneric('color_mapping_legend', function(object, ...) standardGeneric('color_mapping_legend'))
setGeneric('component_width', function(object, ...) standardGeneric('component_width'))
setGeneric('set_component_height', function(object, ...) standardGeneric('set_component_height'))
setGeneric('re_size', function(object, ...) standardGeneric('re_size'))
setGeneric('draw_annotation_legend', function(object, ...) standardGeneric('draw_annotation_legend'))
setGeneric('copy_all', function(object, ...) standardGeneric('copy_all'))
setGeneric('get_legend_param_list', function(object, ...) standardGeneric('get_legend_param_list'))
setGeneric('draw_annotation', function(object, ...) standardGeneric('draw_annotation'))
setGeneric('make_row_cluster', function(object, ...) standardGeneric('make_row_cluster'))
setGeneric('draw_heatmap_legend', function(object, ...) standardGeneric('draw_heatmap_legend'))
setGeneric('column_order', function(object, ...) standardGeneric('column_order'))
setGeneric('row_order', function(object, ...) standardGeneric('row_order'))
setGeneric('draw_heatmap_list', function(object, ...) standardGeneric('draw_heatmap_list'))
setGeneric('draw_heatmap_body', function(object, ...) standardGeneric('draw_heatmap_body'))
setGeneric('set_component_height', function(object, ...) standardGeneric('set_component_height'))
setGeneric('prepare', function(object, ...) standardGeneric('prepare'))
setGeneric('attach_annotation', function(object, ...) standardGeneric('attach_annotation'))
setGeneric('annotation_legend_size', function(object, ...) standardGeneric('annotation_legend_size'))
setGeneric('make_column_cluster', function(object, ...) standardGeneric('make_column_cluster'))
setGeneric('get_color_mapping_list', function(object, ...) standardGeneric('get_color_mapping_list'))
setGeneric('draw_dimnames', function(object, ...) standardGeneric('draw_dimnames'))
33 changes: 31 additions & 2 deletions R/AnnotationFunction-function.R
Original file line number Diff line number Diff line change
Expand Up @@ -1189,6 +1189,10 @@ anno_lines = function(x, which = c("column", "row"), border = TRUE, gp = gpar(),
# -extend The extension to both side of ``ylim``. The value is a percent value corresponding to ``ylim[2] - ylim[1]``.
# -axis Whether to add axis?
# -axis_param parameters for controlling axis. See `default_axis_param` for all possible settings and default parameters.
# -add_numbers Whether to add numbers to the bars. It only works when ``x`` is a simple vector.
# -numbers_gp Graphics parameters for the numbers.
# -numbers_rot Rotation of numbers.
# -numbers_offset Offset to the default positions (1mm away the top of the bars).
# -width Width of the annotation. The value should be an absolute unit. Width is not allowed to be set for column annotation.
# -height Height of the annotation. The value should be an absolute unit. Height is not allowed to be set for row annotation.
# -... Other arguments.
Expand All @@ -1209,7 +1213,9 @@ anno_lines = function(x, which = c("column", "row"), border = TRUE, gp = gpar(),
# draw(anno, test = "proportion matrix")
anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TRUE, bar_width = 0.6,
gp = gpar(fill = "#CCCCCC"), ylim = NULL, extend = 0.05, axis = TRUE,
axis_param = default_axis_param(which),
axis_param = default_axis_param(which),
add_numbers = FALSE, numbers_gp = gpar(fontsize = 8),
numbers_rot = ifelse(which == "column", 45, 0), numbers_offset = unit(2, "mm"),
width = NULL, height = NULL, ...) {

other_args = list(...)
Expand Down Expand Up @@ -1282,6 +1288,19 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
}

value = x

if(ncol(value) == 1) {
if(add_numbers) {
if(which == "column") {
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])
data_scale[2] = data_scale[2] + extend
} else if(which == "row") {
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])
data_scale[2] = data_scale[2] + extend
}
}
}

axis_param = validate_axis_param(axis_param, which)
axis_grob = if(axis) construct_axis_grob(axis_param, which, data_scale) else NULL

Expand All @@ -1299,6 +1318,13 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
width = value[index] - baseline
x_coor = width/2+baseline
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))
if(add_numbers) {
if(axis_param$direction == "normal") {
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)
} else {
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)
}
}
} else {
for(i in seq_len(ncol(value))) {
if(axis_param$direction == "normal") {
Expand Down Expand Up @@ -1336,6 +1362,9 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
height = value[index] - baseline
y_coor = height/2+baseline
grid.rect(y = y_coor, x = seq_along(index), height = abs(height), width = 1*bar_width, default.units = "native", gp = subset_gp(gp, index))
if(add_numbers) {
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)
}
} else {
for(i in seq_len(ncol(value))) {
if(axis_param$direction == "normal") {
Expand Down Expand Up @@ -1375,7 +1404,7 @@ anno_barplot = function(x, baseline = 0, which = c("column", "row"), border = TR
height = anno_size$height,
n = n,
data_scale = data_scale,
var_import = list(value, gp, border, bar_width, baseline, axis, axis_param, axis_grob, data_scale)
var_import = list(value, gp, border, bar_width, baseline, axis, axis_param, axis_grob, data_scale, add_numbers, numbers_gp, numbers_offset, numbers_rot)
)

anno@subset_rule$value = subset_matrix_by_row
Expand Down
31 changes: 31 additions & 0 deletions R/HeatmapList-draw_component.R
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ setMethod(f = "adjust_heatmap_list",
padding = unit(c(0, 0, 0, 0), "mm")
if(is.null(adjust_annotation_extension)) {
if(direction == "horizontal") {
# right side
if(inherits(object@ht_list[[n]], "Heatmap")) {
# if the last heatmap has nothing on the right while something on the right of heatmap list
if(!(has_component(object@ht_list[[n]], "row_anno_right") ||
Expand All @@ -459,6 +460,7 @@ setMethod(f = "adjust_heatmap_list",
}
}
}
# left side
if(inherits(object@ht_list[[1]], "Heatmap")) {
if(!(has_component(object@ht_list[[1]], "row_anno_left") ||
has_component(object@ht_list[[1]], "row_names_left") ||
Expand All @@ -472,6 +474,21 @@ setMethod(f = "adjust_heatmap_list",
}
}
}
# bottom side
if(has_heatmap_list_component(object, "column_title_bottom") ||
has_heatmap_list_component(object, "heatmap_legend_bottom") ||
has_heatmap_list_component(object, "annotation_legend_bottom")) {
object@layout$row_anno_max_bottom_extended = unit(0, "mm")
adjust_annotation_extension = TRUE
}

if(has_heatmap_list_component(object, "column_title_top") ||
has_heatmap_list_component(object, "heatmap_legend_top") ||
has_heatmap_list_component(object, "annotation_legend_top")) {
object@layout$row_anno_max_top_extended = unit(0, "mm")
adjust_annotation_extension = TRUE
}

} else {
if(inherits(object@ht_list[[n]], "Heatmap")) {
# if the last heatmap has nothing on the right while something on the right of heatmap list
Expand Down Expand Up @@ -500,6 +517,20 @@ setMethod(f = "adjust_heatmap_list",
}
}
}

if(has_heatmap_list_component(object, "column_title_bottom") ||
has_heatmap_list_component(object, "heatmap_legend_bottom") ||
has_heatmap_list_component(object, "annotation_legend_bottom")) {
object@layout$row_anno_max_bottom_extended = unit(0, "mm")
adjust_annotation_extension = TRUE
}

if(has_heatmap_list_component(object, "column_title_top") ||
has_heatmap_list_component(object, "heatmap_legend_top") ||
has_heatmap_list_component(object, "annotation_legend_top")) {
object@layout$row_anno_max_top_extended = unit(0, "mm")
adjust_annotation_extension = TRUE
}
}
}

Expand Down
1 change: 0 additions & 1 deletion R/HeatmapList-layout.R
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,6 @@ setMethod(f = "make_layout",
object@ht_list[[i_main]]@row_order = row_order
if(verbose) qqcat("set row_order to main heatmap\n")
}


if(!is.null(height) && !is.null(heatmap_height)) {
stop_wrap("You can only specify one of `height` and `heatmap_height` in draw().")
Expand Down
2 changes: 1 addition & 1 deletion R/HeatmapList-legends.R
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ setMethod(f = "draw_heatmap_legend",
y = max(y1, y2)
pushViewport(viewport(name = "heatmap_legend", x = unit(0.5, "npc"), y = y, width = size[1], height = size[2], just = c("center", "top")))
} else {
x1 = unit(0.5, "npc") - size[1]*0.5 # top of heatmap legend
x1 = unit(0.5, "npc") - size[1]*0.5 # left of heatmap legend
x2 = unit(0.5, "npc") - annotation_legend_size[1]*0.5
x = min(x1, x2)
pushViewport(viewport(name = "heatmap_legend", x = x, y = unit(0.5, "npc"), width = size[1], height = size[2], just = c("left", "center")))
Expand Down
94 changes: 91 additions & 3 deletions R/Upset.R
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,7 @@ print.comb_mat = function(x, ...) {
# -set_order The order of sets.
# -comb_order The order of combination sets.
# -top_annotation A `HeatmapAnnotation` object on top of the combination matrix.
# -left_annotation A `HeatmapAnnotation` object on top of the combination matrix.
# -right_annotation A `HeatmapAnnotation` object on the right of the combination matrix.
# -row_names_side The side of row names.
# -... Other arguments passed to `Heatmap`.
Expand Down Expand Up @@ -1350,6 +1351,7 @@ UpSet = function(m,
},
top_annotation = upset_top_annotation(m),
right_annotation = upset_right_annotation(m),
left_annotation = NULL,
row_names_side = "left",
...) {

Expand All @@ -1364,6 +1366,15 @@ UpSet = function(m,
pt_size = pt_size
lwd = lwd

if(!is.null(left_annotation)) {
if(missing(right_annotation)) {
right_annotation = NULL
}
if(missing(row_names_side)) {
row_names_side = "right"
}
}

if(set_on_rows) {
n_comb = ncol(m)
if(length(comb_col == 1)) comb_col = rep(comb_col, n_comb)
Expand Down Expand Up @@ -1409,7 +1420,7 @@ UpSet = function(m,
ht = Heatmap(m2, cluster_rows = FALSE, cluster_columns = FALSE, rect_gp = gpar(type = "none"),
layer_fun = layer_fun, show_heatmap_legend = FALSE,
top_annotation = ra,
right_annotation = right_annotation,
right_annotation = right_annotation, left_annotation = left_annotation,
row_names_side = row_names_side, col = c("0" = bg_pt_col, "1" = comb_col[1]),
row_order = set_order, column_order = comb_order, ...)
} else {
Expand Down Expand Up @@ -1451,10 +1462,21 @@ UpSet = function(m,
}
}
}
la = left_annotation
if(length(la) == 1) {
ta_call = substitute(top_annotation)
ta_call = as.list(ta_call)
if(as.character(ta_call[[1]]) == "upset_left_annotation") {
if(!"gp" %in% names(as.list(ta_call))) {
la@anno_list[[1]]@fun@var_env$gp$fill = comb_col
la@anno_list[[1]]@fun@var_env$gp$col = comb_col
}
}
}
ht = Heatmap(m2, cluster_rows = FALSE, cluster_columns = FALSE, rect_gp = gpar(type = "none"),
layer_fun = layer_fun, show_heatmap_legend = FALSE,
top_annotation = top_annotation,
right_annotation = ra, col = c("0" = bg_pt_col, "1" = comb_col[1]),
right_annotation = ra, left_annotation = la, col = c("0" = bg_pt_col, "1" = comb_col[1]),
row_order = comb_order, column_order = set_order, ...)
}
ht@heatmap_param$type = "UpSet"
Expand Down Expand Up @@ -1495,6 +1517,8 @@ order.comb_mat = function(m, decreasing = TRUE, on = "comb_set") {
}
}



# == title
# Default UpSet Top Annotation
#
Expand Down Expand Up @@ -1573,7 +1597,7 @@ upset_top_annotation = function(m,
# -annotation_name_offset Offset to the annotation name, a `grid::unit` object.
# -annotation_name_side Side of the annotation name.
# -annotation_name_rot Rotation of the annotation name, it can only take values in ``c(00, 90, 180, 270)``.
# -... Passed to `anno_barplot`.
# -... Passed to `anno_barplot`, e.g. to set ``add_numbers``.
#
# == details
# The default right annotation is actually barplot implemented by `anno_barplot`. For
Expand Down Expand Up @@ -1627,6 +1651,70 @@ upset_right_annotation = function(m,
return(ha)
}

# == title
# UpSet Left Annotation
#
# == param
# -m A combination matrix which is as same as the one for `UpSet`.
# -gp Graphic parameters for bars.
# -axis_param Parameters for axis.
# -width Width of the left annotation.
# -show_annotation_name Whether show annotation names?
# -annotation_name_gp Graphic parameters for anntation names.
# -annotation_name_offset Offset to the annotation name, a `grid::unit` object.
# -annotation_name_side Side of the annotation name.
# -annotation_name_rot Rotation of the annotation name, it can only take values in ``c(00, 90, 180, 270)``.
# -... Passed to `anno_barplot`, e.g. to set ``add_numbers``.
#
upset_left_annotation = function(m,
gp = gpar(fill = "black"),
axis_param = list(direction = "reverse"),
width = unit(ifelse(set_on_rows, 2, 3), "cm"),
show_annotation_name = TRUE,
annotation_name_gp = gpar(),
annotation_name_offset = NULL,
annotation_name_side = "bottom",
annotation_name_rot = NULL,
...) {

set_on_rows = attr(m, "param")$set_on_rows

if(!"direction" %in% names(axis_param)) {
axis_param$direction = "reverse"
}

if(set_on_rows) {
ha = rowAnnotation("set_size" = anno_barplot(set_size(m), border = FALSE,
gp = gp, width = width, axis_param = axis_param, ...),
show_annotation_name = show_annotation_name,
annotation_name_gp = annotation_name_gp,
annotation_name_offset = annotation_name_offset,
annotation_name_side = annotation_name_side,
annotation_name_rot = annotation_name_rot,
annotation_label = "Set size")
} else {
ha = rowAnnotation("intersection_size" = anno_barplot(comb_size(m),
border = FALSE, gp = gp, width = width, axis_param = axis_param, ...),
show_annotation_name = show_annotation_name,
annotation_name_gp = annotation_name_gp,
annotation_name_offset = annotation_name_offset,
annotation_name_side = annotation_name_side,
annotation_name_rot = annotation_name_rot,
annotation_label = "Intersection\nsize")
}

mode = attr(m, "param")$mode
if(!set_on_rows) {
if(mode %in% c("distinct", "intersect")) {
# names(ha) = "intersection_size"
} else {
names(ha) = "union_size"
ha@anno_list[[1]]@label = "Union size"
}
}
return(ha)
}

# == title
# Normalize a list of combination matrice
#
Expand Down
2 changes: 2 additions & 0 deletions man/UpSet.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ UpSet(m,
},
top_annotation = upset_top_annotation(m),
right_annotation = upset_right_annotation(m),
left_annotation = NULL,
row_names_side = "left",
...)
}
Expand All @@ -33,6 +34,7 @@ UpSet(m,
\item{set_order}{The order of sets.}
\item{comb_order}{The order of combination sets.}
\item{top_annotation}{A \code{\link{HeatmapAnnotation}} object on top of the combination matrix.}
\item{left_annotation}{A \code{\link{HeatmapAnnotation}} object on top of the combination matrix.}
\item{right_annotation}{A \code{\link{HeatmapAnnotation}} object on the right of the combination matrix.}
\item{row_names_side}{The side of row names.}
\item{...}{Other arguments passed to \code{\link{Heatmap}}.}
Expand Down
Loading

0 comments on commit 00490f9

Please sign in to comment.