Browse code

add functions to deal with genome-scale heatmaps

Zuguang Gu authored on 22/11/2020 20:40:20
Showing16 changed files

... ...
@@ -1,8 +1,8 @@
1 1
 Package: ComplexHeatmap
2 2
 Type: Package
3 3
 Title: Make Complex Heatmaps
4
-Version: 2.7.1
5
-Date: 2020-10-13
4
+Version: 2.7.1.1001
5
+Date: 2020-10-22
6 6
 Author: Zuguang Gu
7 7
 Maintainer: Zuguang Gu <z.gu@dkfz.de>
8 8
 Depends: R (>= 3.1.2), methods, grid, graphics, stats, grDevices
... ...
@@ -21,4 +21,4 @@ Description: Complex heatmaps are efficient to visualize associations
21 21
     multiple heatmaps and supports various annotation graphics.
22 22
 biocViews: Software, Visualization, Sequencing
23 23
 URL: https://github.com/jokergoo/ComplexHeatmap, https://jokergoo.github.io/ComplexHeatmap-reference/book/
24
-License: MIT + file LICENSE
24
+License: MIT + file LICENSE
25 25
\ No newline at end of file
... ...
@@ -148,6 +148,7 @@ export("anno_summary")
148 148
 export("anno_text")
149 149
 export("anno_zoom")
150 150
 export("annotation_axis_grob")
151
+export("bin_genome")
151 152
 export("cluster_within_group")
152 153
 export("columnAnnotation")
153 154
 export("comb_degree")
... ...
@@ -193,6 +194,7 @@ export("max_text_height")
193 194
 export("max_text_width")
194 195
 export("merge_dendrogram")
195 196
 export("normalize_comb_mat")
197
+export("normalize_genomic_signals_to_bins")
196 198
 export("oncoPrint")
197 199
 export("order.comb_mat")
198 200
 export("packLegend")
... ...
@@ -9,6 +9,7 @@ CHANGES in VERSION 2.7.1
9 9
 * Fixed a bug that it crashes Rstudio
10 10
 * `make_comb_mat()`: print warning messages when there are NA values in the matrix.
11 11
 * temporary solution for woking under retina display with Rstudio
12
+* add `bin_genome()` and `normalize_genomic_signals_to_bins()`
12 13
 
13 14
 ========================
14 15
 
... ...
@@ -1,32 +1,32 @@
1
-setGeneric('draw_title', function(object, ...) standardGeneric('draw_title'))
1
+setGeneric('map_to_colors', function(object, ...) standardGeneric('map_to_colors'))
2
+setGeneric('set_component_height', function(object, ...) standardGeneric('set_component_height'))
2 3
 setGeneric('draw_heatmap_body', function(object, ...) standardGeneric('draw_heatmap_body'))
3
-setGeneric('annotation_legend_size', function(object, ...) standardGeneric('annotation_legend_size'))
4
-setGeneric('draw_annotation_legend', function(object, ...) standardGeneric('draw_annotation_legend'))
5
-setGeneric('attach_annotation', function(object, ...) standardGeneric('attach_annotation'))
4
+setGeneric('component_height', function(object, ...) standardGeneric('component_height'))
5
+setGeneric('re_size', function(object, ...) standardGeneric('re_size'))
6
+setGeneric('make_layout', function(object, ...) standardGeneric('make_layout'))
7
+setGeneric('heatmap_legend_size', function(object, ...) standardGeneric('heatmap_legend_size'))
6 8
 setGeneric('get_legend_param_list', function(object, ...) standardGeneric('get_legend_param_list'))
7
-setGeneric('row_dend', function(object, ...) standardGeneric('row_dend'))
9
+setGeneric('attach_annotation', function(object, ...) standardGeneric('attach_annotation'))
10
+setGeneric('color_mapping_legend', function(object, ...) standardGeneric('color_mapping_legend'))
11
+setGeneric('make_column_cluster', function(object, ...) standardGeneric('make_column_cluster'))
12
+setGeneric('column_dend', function(object, ...) standardGeneric('column_dend'))
8 13
 setGeneric('row_order', function(object, ...) standardGeneric('row_order'))
9 14
 setGeneric('draw_heatmap_list', function(object, ...) standardGeneric('draw_heatmap_list'))
10
-setGeneric('set_component_height', function(object, ...) standardGeneric('set_component_height'))
11
-setGeneric('draw', function(object, ...) standardGeneric('draw'))
12
-setGeneric('draw_annotation', function(object, ...) standardGeneric('draw_annotation'))
15
+setGeneric('row_dend', function(object, ...) standardGeneric('row_dend'))
13 16
 setGeneric('add_heatmap', function(object, ...) standardGeneric('add_heatmap'))
14
-setGeneric('adjust_heatmap_list', function(object, ...) standardGeneric('adjust_heatmap_list'))
15
-setGeneric('draw_heatmap_legend', function(object, ...) standardGeneric('draw_heatmap_legend'))
16
-setGeneric('make_row_cluster', function(object, ...) standardGeneric('make_row_cluster'))
17
-setGeneric('color_mapping_legend', function(object, ...) standardGeneric('color_mapping_legend'))
18
-setGeneric('component_width', function(object, ...) standardGeneric('component_width'))
19
-setGeneric('map_to_colors', function(object, ...) standardGeneric('map_to_colors'))
20 17
 setGeneric('set_component_width', function(object, ...) standardGeneric('set_component_width'))
21
-setGeneric('re_size', function(object, ...) standardGeneric('re_size'))
22
-setGeneric('copy_all', function(object, ...) standardGeneric('copy_all'))
23
-setGeneric('draw_dend', function(object, ...) standardGeneric('draw_dend'))
24
-setGeneric('draw_dimnames', function(object, ...) standardGeneric('draw_dimnames'))
25 18
 setGeneric('column_order', function(object, ...) standardGeneric('column_order'))
19
+setGeneric('draw_annotation_legend', function(object, ...) standardGeneric('draw_annotation_legend'))
20
+setGeneric('draw_heatmap_legend', function(object, ...) standardGeneric('draw_heatmap_legend'))
21
+setGeneric('annotation_legend_size', function(object, ...) standardGeneric('annotation_legend_size'))
22
+setGeneric('draw_annotation', function(object, ...) standardGeneric('draw_annotation'))
26 23
 setGeneric('prepare', function(object, ...) standardGeneric('prepare'))
27
-setGeneric('make_layout', function(object, ...) standardGeneric('make_layout'))
28
-setGeneric('column_dend', function(object, ...) standardGeneric('column_dend'))
29
-setGeneric('make_column_cluster', function(object, ...) standardGeneric('make_column_cluster'))
24
+setGeneric('draw_dimnames', function(object, ...) standardGeneric('draw_dimnames'))
25
+setGeneric('draw', function(object, ...) standardGeneric('draw'))
26
+setGeneric('draw_title', function(object, ...) standardGeneric('draw_title'))
27
+setGeneric('make_row_cluster', function(object, ...) standardGeneric('make_row_cluster'))
28
+setGeneric('component_width', function(object, ...) standardGeneric('component_width'))
30 29
 setGeneric('get_color_mapping_list', function(object, ...) standardGeneric('get_color_mapping_list'))
31
-setGeneric('component_height', function(object, ...) standardGeneric('component_height'))
32
-setGeneric('heatmap_legend_size', function(object, ...) standardGeneric('heatmap_legend_size'))
30
+setGeneric('draw_dend', function(object, ...) standardGeneric('draw_dend'))
31
+setGeneric('adjust_heatmap_list', function(object, ...) standardGeneric('adjust_heatmap_list'))
32
+setGeneric('copy_all', function(object, ...) standardGeneric('copy_all'))
... ...
@@ -2804,6 +2804,8 @@ anno_mark = function(at, labels, which = c("column", "row"),
2804 2804
 		stop_wrap(paste0("`at` should be numeric ", which, " index corresponding to the matrix."))
2805 2805
 	}
2806 2806
 	
2807
+	if(is.logical(at)) at = which(at)
2808
+
2807 2809
 	n = length(at)
2808 2810
 	if(n < 1) {
2809 2811
 		stop_wrap("Length of `at` should be positive.")
2810 2812
new file mode 100644
... ...
@@ -0,0 +1,266 @@
1
+GHEATMAP_ENV = new.env()
2
+
3
+# == title
4
+# Bin the genome
5
+#
6
+# == param
7
+# -species Abbreviation of the genome, pass to `circlize::read.chromInfo`.
8
+# -bins Number of bins. The final number of bins is approximately equal to it.
9
+# -bin_size Size of the bins. If ``bin_size`` is set, ``bins`` is ignored.
10
+# -... All pass to `circlize::read.chromInfo`. E.g. you can set a subset of chromosomes there.
11
+#
12
+# == value
13
+# A `GenomicRanges::GRanges` object of the genomic bins.
14
+#
15
+bin_genome = function(species = "hg19", bins = 2000, bin_size = NULL, ...) {
16
+
17
+    lt = circlize::read.chromInfo(species = species, ...)
18
+
19
+    chr_df = lt$df
20
+    chr_gr = GenomicRanges::GRanges(seqnames = chr_df[, 1], ranges = IRanges::IRanges(chr_df[, 2] + 1, chr_df[, 3]))
21
+
22
+    if(is.null(bin_size)) {
23
+        bin_size = round(sum(lt$chr.len)/bins)
24
+        bin_size = max(bin_size, 1)
25
+    }
26
+    chr_window = EnrichedHeatmap::makeWindows(chr_gr, w = bin_size)
27
+    GenomicRanges::mcols(chr_window) = NULL
28
+
29
+    GHEATMAP_ENV$chr_window = chr_window
30
+    invisible(chr_window)
31
+}
32
+
33
+# == title
34
+# Overlap genomic signals to the genomic bins
35
+#
36
+# == param
37
+# -gr A `GenomicRanges::GRanges` object.
38
+# -value The corresponding signals corresponding to ``gr``.
39
+# -value_column If ``value`` is not set and the values are in the meta-columns in ``gr``, you can specify the column
40
+#     indices for these value columns, better to use name indices.
41
+# -method One of "weighted", "w0" and "absolute". For the three different methods, please refer to https://bioconductor.org/packages/release/bioc/vignettes/EnrichedHeatmap/inst/doc/EnrichedHeatmap.html#toc_7 .
42
+# -empty_value The value for the bins where no signal is overlapped.
43
+#
44
+# == details
45
+# The genomic bins should be generated by `bin_genome` in advance. The genomic bins are saved internally, so that multiple
46
+# uses of `bin_genomic_signals` ensure they all return the matrices with the same rows.
47
+#
48
+# It supports following values.
49
+#
50
+# - When neither ``value`` nor ``value_column`` is set, it simply overlap ``gr`` to the genomic bins and returns a one-column logical
51
+#   matrix which represents whether the current genomic bin overlaps to any signal.
52
+# - When the signals are numeric, ``value`` can be a numeric vector or a matrix, or ``value_column`` can contain multiple columns.
53
+#   The function returns a numeric matrix where the values are properly averaged depending on what ``method`` was used.
54
+# - When the signals are character, ``value`` can only be a vector or `value_column` can only contain one single column.
55
+#   The function returns a one-column character matrix.
56
+#
57
+# == value
58
+# A matrix with the same row as the genomic bins.
59
+#
60
+# == examples
61
+# library(ComplexHeatmap)
62
+# require(circlize)
63
+# require(GenomicRanges)
64
+#
65
+# chr_window = bin_genome("hg19")
66
+#
67
+# #### the first is a numeric matrix #######
68
+# bed1 = generateRandomBed(nr = 1000, nc = 10)
69
+# gr1 = GRanges(seqnames = bed1[, 1], ranges = IRanges(bed1[, 2], bed1[, 3]))
70
+#
71
+# num_mat = normalize_genomic_signals_to_bins(gr1, bed1[, -(1:3)])
72
+#
73
+# #### the second is a character matrix ######
74
+# bed_list = lapply(1:10, function(i) {
75
+#     generateRandomBed(nr = 1000, nc = 1, 
76
+#         fun = function(n) sample(c("gain", "loss"), n, replace = TRUE))
77
+# })
78
+# char_mat = NULL
79
+# for(i in 1:10) {
80
+#     bed = bed_list[[i]]
81
+#     bed = bed[sample(nrow(bed), 20), , drop = FALSE]
82
+#     gr_cnv = GRanges(seqnames = bed[, 1], ranges = IRanges(bed[, 2], bed[, 3]))
83
+#
84
+#     char_mat = cbind(char_mat, normalize_genomic_signals_to_bins(gr_cnv, bed[, 4]))
85
+# }
86
+#
87
+# #### two numeric columns ##########
88
+# bed2 = generateRandomBed(nr = 100, nc = 2)
89
+# gr2 = GRanges(seqnames = bed2[, 1], ranges = IRanges(bed2[, 2], bed2[, 3]))
90
+#
91
+# v = normalize_genomic_signals_to_bins(gr2, bed2[, 4:5])
92
+#
93
+# ##### a list of genes need to be highlighted
94
+# bed3 = generateRandomBed(nr = 40, nc = 0)
95
+# gr3 = GRanges(seqnames = bed3[, 1], ranges = IRanges(bed3[, 2], bed3[, 2]))
96
+# gr3$gene = paste0("gene_", 1:length(gr3))
97
+#
98
+# mtch = as.matrix(findOverlaps(chr_window, gr3))
99
+# at = mtch[, 1]
100
+# labels = mcols(gr3)[mtch[, 2], 1]
101
+#
102
+# ##### order of the chromosomes ########
103
+# chr = as.vector(seqnames(chr_window))
104
+# chr_level = paste0("chr", c(1:22, "X", "Y"))
105
+# chr = factor(chr, levels = chr_level)
106
+#
107
+# #### make the heatmap #######
108
+# subgroup = rep(c("A", "B"), each = 5)
109
+#
110
+# ht_opt$TITLE_PADDING = unit(c(4, 4), "points")
111
+# ht_list = Heatmap(num_mat, name = "mat", col = colorRamp2(c(-1, 0, 1), c("green", "white", "red")),
112
+#     row_split = chr, cluster_rows = FALSE, show_column_dend = FALSE,
113
+#     column_split = subgroup, cluster_column_slices = FALSE,
114
+#     column_title = "numeric matrix",
115
+#     top_annotation = HeatmapAnnotation(subgroup = subgroup, annotation_name_side = "left"),
116
+#     row_title_rot = 0, row_title_gp = gpar(fontsize = 10), border = TRUE,
117
+#     row_gap = unit(0, "points")) +
118
+# Heatmap(char_mat, name = "CNV", col = c("gain" = "red", "loss" = "blue"),
119
+#     border = TRUE, column_title = "character matrix") +
120
+# rowAnnotation(label = anno_mark(at = at, labels = labels)) +
121
+# rowAnnotation(pt = anno_points(v, gp = gpar(col = 4:5), pch = c(1, 16)), 
122
+#     width = unit(2, "cm")) +
123
+# rowAnnotation(bar = anno_barplot(v[, 1], gp = gpar(col = ifelse(v[ ,1] > 0, 2, 3))), 
124
+#     width = unit(2, "cm"))
125
+# draw(ht_list, merge_legend = TRUE)
126
+#
127
+# ##### or horizontally ###
128
+# ht_list = Heatmap(t(num_mat), name = "mat", col = colorRamp2(c(-1, 0, 1), c("green", "white", "red")),
129
+#     column_split = chr, cluster_columns = FALSE, show_row_dend = FALSE,
130
+#     row_split = subgroup, cluster_row_slices = FALSE,
131
+#     row_title = "numeric matrix",
132
+#     left_annotation = rowAnnotation(subgroup = subgroup, show_annotation_name = FALSE,
133
+#         annotation_legend_param = list(
134
+#             subgroup = list(direction = "horizontal", title_position = "lefttop", nrow = 1))),
135
+#     column_title_gp = gpar(fontsize = 10), border = TRUE,
136
+#     column_gap = unit(0, "points"),
137
+#     column_title = ifelse(seq_along(chr_level) %% 2 == 0, paste0("\n", chr_level), paste0(chr_level, "\n")),
138
+#     heatmap_legend_param = list(direction = "horizontal", title_position = "lefttop")) %v%
139
+# Heatmap(t(char_mat), name = "CNV", col = c("gain" = "red", "loss" = "blue"),
140
+#     border = TRUE, row_title = "character matrix",
141
+#     heatmap_legend_param = list(direction = "horizontal", title_position = "lefttop", nrow = 1)) %v%
142
+# HeatmapAnnotation(label = anno_mark(at = at, labels = labels, side = "bottom")) %v%
143
+# HeatmapAnnotation(pt = anno_points(v, gp = gpar(col = 4:5), pch = c(1, 16)),
144
+#     annotation_name_side = "left", height = unit(2, "cm")) %v%
145
+# HeatmapAnnotation(bar = anno_barplot(v[, 1], gp = gpar(col = ifelse(v[ ,1] > 0, 2, 3))), 
146
+#     annotation_name_side = "left", height = unit(2, "cm"))
147
+# draw(ht_list, heatmap_legend_side = "bottom", merge_legend = TRUE)
148
+#
149
+normalize_genomic_signals_to_bins = function(gr, value, value_column = NULL, method = "weighted", 
150
+    empty_value = NA, window = GHEATMAP_ENV$chr_window) {
151
+    
152
+    if(is.null(window)) {
153
+        stop_wrap("`bin_genome()` should be executed first.")
154
+    }
155
+
156
+    if(!inherits(gr, "GRanges")) {
157
+        if(is.data.frame(gr)) {
158
+            oe = try({
159
+                gr <- GenomicRanges::GenomicRanges(seqnames(gr[, 1]), ranges = IRanges::IRanges(gr[, 2], gr[, 3]))
160
+                if(ncol(gr) > 3) {
161
+                    GenomicRanges::mcols(gr) = gr[, -(1:3), drop = FALSE]
162
+                }
163
+            })
164
+            if(inherits(oe, "try-error")) {
165
+                stop_wrap("Failed to convert `gr` to a `GRanges` object. Please provide `gr` as a `GRanges` object.")
166
+            }
167
+        } else {
168
+            stop_wrap("`gr` must be a `GRanges` object.")
169
+        }
170
+    }
171
+
172
+    if(missing(value) && is.null(value_column)) {
173
+        mtch = as.matrix(GenomicRanges::findOverlaps(window, gr))
174
+        u = matrix(FALSE, nrow = length(window), ncol = 1)
175
+        u[mtch[, 1], 1] = TRUE
176
+        return(u)
177
+    }
178
+
179
+    if(is.null(value) && is.null(value_column)) {
180
+        mtch = as.matrix(GenomicRanges::findOverlaps(window, gr))
181
+        u = matrix(FALSE, nrow = length(window), ncol = 1)
182
+        u[mtch[, 1], 1] = TRUE
183
+        return(u)
184
+    }
185
+
186
+    if(!is.null(value_column)) {
187
+        value = GenomicRanges::mcols(gr)[, value_column]
188
+        value = as.matrix(as.data.frame(value))
189
+    }
190
+
191
+    if(is.atomic(value) && is.vector(value)) value = cbind(value)
192
+
193
+    value = as.matrix(value)
194
+    if(is.character(value) && ncol(value) > 1) {
195
+        stop("For character signals, `value` can only be a single character vector or `value_column` can only contain one column.")
196
+    }
197
+
198
+    if(length(empty_value) == 1) {
199
+        empty_value = rep(empty_value, ncol(value))
200
+    }
201
+
202
+    u = matrix(rep(empty_value, each = length(window)), nrow = length(window), ncol = ncol(value))
203
+
204
+    mtch = as.matrix(GenomicRanges::findOverlaps(window, gr))
205
+    intersect = GenomicRanges::pintersect(window[mtch[,1]], gr[mtch[,2]])
206
+    w = GenomicRanges::width(intersect)
207
+    value = value[mtch[,2], , drop = FALSE]
208
+    n = nrow(value)
209
+
210
+    ind_list = split(seq_len(n), mtch[, 1])
211
+    window_index = as.numeric(names(ind_list))
212
+    window_w = GenomicRanges::width(window)
213
+
214
+    if(is.character(value)) {
215
+        for(i in seq_along(ind_list)) {
216
+            ind = ind_list[[i]]
217
+            if(is.function(method)) {
218
+                u[window_index[i], ] = method(value[ind], w[ind], window_w[i])
219
+            } else {
220
+                tb = tapply(w[ind], value[ind], sum)
221
+                u[window_index[i], ] = names(tb[which.max(tb)])
222
+            }
223
+        }
224
+    } else {
225
+        if(method == "w0") {
226
+            gr2 = GenomicRanges::reduce(gr, min.gapwidth = 0)
227
+            mtch2 = as.matrix(GenomicRanges::findOverlaps(window, gr2))
228
+            intersect2 = GenomicRanges::pintersect(window[mtch2[, 1]], gr2[mtch2[, 2]])
229
+
230
+            width_intersect = tapply(GenomicRanges::width(intersect2), mtch2[, 1], sum)
231
+            ind = unique(mtch2[, 1])
232
+            width_setdiff = GenomicRanges::width(window[ind]) - width_intersect
233
+
234
+            w2 = GenomicRanges::width(window[ind])
235
+
236
+            for(i in seq_along(ind_list)) {
237
+                ind = ind_list[[i]]
238
+                x = colSums(value[ind, , drop = FALSE]*w[ind])/sum(w[ind])
239
+                u[window_index[i], ] = (x*width_intersect[i] + empty_v*width_setdiff[i])/w2[i]
240
+            }
241
+
242
+        } else if(method == "absolute") {
243
+            for(i in seq_along(ind_list)) {
244
+                u[window_index[i], ] = colMeans(value[ind_list[[i]], , drop = FALSE])
245
+            }
246
+            
247
+        } else if(method == "weighted") {
248
+            for(i in seq_along(ind_list)) {
249
+                ind = ind_list[[i]]
250
+                u[window_index[i], ] = colSums(value[ind, , drop = FALSE]*w[ind])/sum(w[ind])
251
+            }
252
+        } else {
253
+            if(is.function(method)) {
254
+                for(i in seq_along(ind_list)) {
255
+                    ind = ind_list[[i]]
256
+                    u[window_index[i], ] = method(value[ind], w[ind], window_w[i])
257
+                }
258
+            } else {
259
+                stop_wrap("Wrong method.")
260
+            }
261
+        }
262
+    }
263
+
264
+    return(u)
265
+}
266
+
... ...
@@ -833,6 +833,7 @@ horizontal_continuous_legend_body = function(at, labels = at, col_fun,
833 833
 		}
834 834
 	}
835 835
 
836
+	labels = as.character(labels)
836 837
 	labels_rot = labels_rot %% 360
837 838
 
838 839
 	n_labels = length(labels)
... ...
@@ -876,12 +877,12 @@ horizontal_continuous_legend_body = function(at, labels = at, col_fun,
876 877
 	}
877 878
 	# adjust the text position
878 879
 	labels_width = do.call("unit.c", lapply(labels, 
879
-		function(x) grobWidth(textGrob(x, gp = labels_gp, rot = labels_rot)) + unit(2, "mm")))
880
+		function(x) grobWidth(textGrob(x, gp = labels_gp, rot = labels_rot)) + unit(1, "mm")))
880 881
 	x_right = labels_x + labels_width*0.5
881 882
 	x_left = labels_x - labels_width*0.5
882 883
 	x_right = convertX(x_right, "mm", valueOnly = TRUE)
883 884
 	x_left = convertX(x_left, "mm", valueOnly = TRUE)
884
-	
885
+
885 886
 	# adjust to the left extension, caused by e.g. title
886 887
 	ext = max(legend_extension, labels_width[1]*0.5 - offset)
887 888
 	xrange = convertX(unit.c(-ext,
888 889
new file mode 100644
... ...
@@ -0,0 +1,26 @@
1
+\name{bin_genome}
2
+\alias{bin_genome}
3
+\title{
4
+Bin the genome
5
+}
6
+\description{
7
+Bin the genome
8
+}
9
+\usage{
10
+bin_genome(species = "hg19", bins = 2000, bin_size = NULL, ...)
11
+}
12
+\arguments{
13
+
14
+  \item{species}{Abbreviation of the genome, pass to \code{\link[circlize]{read.chromInfo}}.}
15
+  \item{bins}{Number of bins. The final number of bins is approximately equal to it.}
16
+  \item{bin_size}{Size of the bins. If \code{bin_size} is set, \code{bins} is ignored.}
17
+  \item{...}{All pass to \code{\link[circlize]{read.chromInfo}}. E.g. you can set a subset of chromosomes there.}
18
+
19
+}
20
+\value{
21
+A \code{\link[GenomicRanges:GRanges-class]{GRanges}} object of the genomic bins.
22
+}
23
+\examples{
24
+# There is no example
25
+NULL
26
+}
... ...
@@ -10,8 +10,8 @@ Method dispatch page for \code{column_dend}.
10 10
 \code{column_dend} can be dispatched on following classes:
11 11
 
12 12
 \itemize{
13
-\item \code{\link{column_dend,Heatmap-method}}, \code{\link{Heatmap-class}} class method
14 13
 \item \code{\link{column_dend,HeatmapList-method}}, \code{\link{HeatmapList-class}} class method
14
+\item \code{\link{column_dend,Heatmap-method}}, \code{\link{Heatmap-class}} class method
15 15
 }
16 16
 }
17 17
 \examples{
... ...
@@ -10,8 +10,8 @@ Method dispatch page for \code{column_order}.
10 10
 \code{column_order} can be dispatched on following classes:
11 11
 
12 12
 \itemize{
13
-\item \code{\link{column_order,Heatmap-method}}, \code{\link{Heatmap-class}} class method
14 13
 \item \code{\link{column_order,HeatmapList-method}}, \code{\link{HeatmapList-class}} class method
14
+\item \code{\link{column_order,Heatmap-method}}, \code{\link{Heatmap-class}} class method
15 15
 }
16 16
 }
17 17
 \examples{
... ...
@@ -10,8 +10,8 @@ Method dispatch page for \code{component_height}.
10 10
 \code{component_height} can be dispatched on following classes:
11 11
 
12 12
 \itemize{
13
-\item \code{\link{component_height,Heatmap-method}}, \code{\link{Heatmap-class}} class method
14 13
 \item \code{\link{component_height,HeatmapList-method}}, \code{\link{HeatmapList-class}} class method
14
+\item \code{\link{component_height,Heatmap-method}}, \code{\link{Heatmap-class}} class method
15 15
 }
16 16
 }
17 17
 \examples{
... ...
@@ -10,8 +10,8 @@ Method dispatch page for \code{copy_all}.
10 10
 \code{copy_all} can be dispatched on following classes:
11 11
 
12 12
 \itemize{
13
-\item \code{\link{copy_all,SingleAnnotation-method}}, \code{\link{SingleAnnotation-class}} class method
14 13
 \item \code{\link{copy_all,AnnotationFunction-method}}, \code{\link{AnnotationFunction-class}} class method
14
+\item \code{\link{copy_all,SingleAnnotation-method}}, \code{\link{SingleAnnotation-class}} class method
15 15
 }
16 16
 }
17 17
 \examples{
... ...
@@ -10,12 +10,12 @@ Method dispatch page for \code{draw}.
10 10
 \code{draw} can be dispatched on following classes:
11 11
 
12 12
 \itemize{
13
+\item \code{\link{draw,AnnotationFunction-method}}, \code{\link{AnnotationFunction-class}} class method
13 14
 \item \code{\link{draw,Legends-method}}, \code{\link{Legends-class}} class method
15
+\item \code{\link{draw,HeatmapAnnotation-method}}, \code{\link{HeatmapAnnotation-class}} class method
16
+\item \code{\link{draw,SingleAnnotation-method}}, \code{\link{SingleAnnotation-class}} class method
14 17
 \item \code{\link{draw,HeatmapList-method}}, \code{\link{HeatmapList-class}} class method
15 18
 \item \code{\link{draw,Heatmap-method}}, \code{\link{Heatmap-class}} class method
16
-\item \code{\link{draw,SingleAnnotation-method}}, \code{\link{SingleAnnotation-class}} class method
17
-\item \code{\link{draw,AnnotationFunction-method}}, \code{\link{AnnotationFunction-class}} class method
18
-\item \code{\link{draw,HeatmapAnnotation-method}}, \code{\link{HeatmapAnnotation-class}} class method
19 19
 }
20 20
 }
21 21
 \examples{
... ...
@@ -10,8 +10,8 @@ Method dispatch page for \code{draw_title}.
10 10
 \code{draw_title} can be dispatched on following classes:
11 11
 
12 12
 \itemize{
13
-\item \code{\link{draw_title,Heatmap-method}}, \code{\link{Heatmap-class}} class method
14 13
 \item \code{\link{draw_title,HeatmapList-method}}, \code{\link{HeatmapList-class}} class method
14
+\item \code{\link{draw_title,Heatmap-method}}, \code{\link{Heatmap-class}} class method
15 15
 }
16 16
 }
17 17
 \examples{
18 18
new file mode 100644
... ...
@@ -0,0 +1,125 @@
1
+\name{normalize_genomic_signals_to_bins}
2
+\alias{normalize_genomic_signals_to_bins}
3
+\title{
4
+Overlap genomic signals to the genomic bins
5
+}
6
+\description{
7
+Overlap genomic signals to the genomic bins
8
+}
9
+\usage{
10
+normalize_genomic_signals_to_bins(gr, value, value_column = NULL, method = "weighted",
11
+    empty_value = NA, window = GHEATMAP_ENV$chr_window)
12
+}
13
+\arguments{
14
+
15
+  \item{gr}{A \code{\link[GenomicRanges:GRanges-class]{GRanges}} object.}
16
+  \item{value}{The corresponding signals corresponding to \code{gr}.}
17
+  \item{value_column}{If \code{value} is not set and the values are in the meta-columns in \code{gr}, you can specify the column indices for these value columns, better to use name indices.}
18
+  \item{method}{One of "weighted", "w0" and "absolute". For the three different methods, please refer to \url{https://bioconductor.org/packages/release/bioc/vignettes/EnrichedHeatmap/inst/doc/EnrichedHeatmap.html#toc_7} .}
19
+  \item{empty_value}{The value for the bins where no signal is overlapped.}
20
+
21
+}
22
+\details{
23
+The genomic bins should be generated by \code{\link{bin_genome}} in advance. The genomic bins are saved internally, so that multiple
24
+uses of \code{\link{bin_genomic_signals}} ensure they all return the matrices with the same rows.
25
+
26
+It supports following values.
27
+
28
+\itemize{
29
+  \item When neither \code{value} nor \code{value_column} is set, it simply overlap \code{gr} to the genomic bins and returns a one-column logical matrix which represents whether the current genomic bin overlaps to any signal.
30
+  \item When the signals are numeric, \code{value} can be a numeric vector or a matrix, or \code{value_column} can contain multiple columns. The function returns a numeric matrix where the values are properly averaged depending on what \code{method} was used.
31
+  \item When the signals are character, \code{value} can only be a vector or \code{\link{value_column}} can only contain one single column. The function returns a one-column character matrix.
32
+}
33
+}
34
+\value{
35
+A matrix with the same row as the genomic bins.
36
+}
37
+\examples{
38
+library(ComplexHeatmap)
39
+require(circlize)
40
+require(GenomicRanges)
41
+
42
+chr_window = bin_genome("hg19")
43
+
44
+#### the first is a numeric matrix #######
45
+bed1 = generateRandomBed(nr = 1000, nc = 10)
46
+gr1 = GRanges(seqnames = bed1[, 1], ranges = IRanges(bed1[, 2], bed1[, 3]))
47
+
48
+num_mat = normalize_genomic_signals_to_bins(gr1, bed1[, -(1:3)])
49
+
50
+#### the second is a character matrix ######
51
+bed_list = lapply(1:10, function(i) {
52
+    generateRandomBed(nr = 1000, nc = 1, 
53
+        fun = function(n) sample(c("gain", "loss"), n, replace = TRUE))
54
+})
55
+char_mat = NULL
56
+for(i in 1:10) {
57
+    bed = bed_list[[i]]
58
+    bed = bed[sample(nrow(bed), 20), , drop = FALSE]
59
+    gr_cnv = GRanges(seqnames = bed[, 1], ranges = IRanges(bed[, 2], bed[, 3]))
60
+
61
+char_mat = cbind(char_mat, normalize_genomic_signals_to_bins(gr_cnv, bed[, 4]))
62
+}
63
+
64
+#### two numeric columns ##########
65
+bed2 = generateRandomBed(nr = 100, nc = 2)
66
+gr2 = GRanges(seqnames = bed2[, 1], ranges = IRanges(bed2[, 2], bed2[, 3]))
67
+
68
+v = normalize_genomic_signals_to_bins(gr2, bed2[, 4:5])
69
+
70
+##### a list of genes need to be highlighted
71
+bed3 = generateRandomBed(nr = 40, nc = 0)
72
+gr3 = GRanges(seqnames = bed3[, 1], ranges = IRanges(bed3[, 2], bed3[, 2]))
73
+gr3$gene = paste0("gene_", 1:length(gr3))
74
+
75
+mtch = as.matrix(findOverlaps(chr_window, gr3))
76
+at = mtch[, 1]
77
+labels = mcols(gr3)[mtch[, 2], 1]
78
+
79
+##### order of the chromosomes ########
80
+chr = as.vector(seqnames(chr_window))
81
+chr_level = paste0("chr", c(1:22, "X", "Y"))
82
+chr = factor(chr, levels = chr_level)
83
+
84
+#### make the heatmap #######
85
+subgroup = rep(c("A", "B"), each = 5)
86
+
87
+ht_opt$TITLE_PADDING = unit(c(4, 4), "points")
88
+ht_list = Heatmap(num_mat, name = "mat", col = colorRamp2(c(-1, 0, 1), c("green", "white", "red")),
89
+    row_split = chr, cluster_rows = FALSE, show_column_dend = FALSE,
90
+    column_split = subgroup, cluster_column_slices = FALSE,
91
+    column_title = "numeric matrix",
92
+    top_annotation = HeatmapAnnotation(subgroup = subgroup, annotation_name_side = "left"),
93
+    row_title_rot = 0, row_title_gp = gpar(fontsize = 10), border = TRUE,
94
+    row_gap = unit(0, "points")) +
95
+Heatmap(char_mat, name = "CNV", col = c("gain" = "red", "loss" = "blue"),
96
+    border = TRUE, column_title = "character matrix") +
97
+rowAnnotation(label = anno_mark(at = at, labels = labels)) +
98
+rowAnnotation(pt = anno_points(v, gp = gpar(col = 4:5), pch = c(1, 16)), 
99
+    width = unit(2, "cm")) +
100
+rowAnnotation(bar = anno_barplot(v[, 1], gp = gpar(col = ifelse(v[ ,1] > 0, 2, 3))), 
101
+    width = unit(2, "cm"))
102
+draw(ht_list, merge_legend = TRUE)
103
+
104
+##### or horizontally ###
105
+ht_list = Heatmap(t(num_mat), name = "mat", col = colorRamp2(c(-1, 0, 1), c("green", "white", "red")),
106
+    column_split = chr, cluster_columns = FALSE, show_row_dend = FALSE,
107
+    row_split = subgroup, cluster_row_slices = FALSE,
108
+    row_title = "numeric matrix",
109
+    left_annotation = rowAnnotation(subgroup = subgroup, show_annotation_name = FALSE,
110
+        annotation_legend_param = list(
111
+            subgroup = list(direction = "horizontal", title_position = "lefttop", nrow = 1))),
112
+    column_title_gp = gpar(fontsize = 10), border = TRUE,
113
+    column_gap = unit(0, "points"),
114
+    column_title = ifelse(seq_along(chr_level) %% 2 == 0, paste0("\n", chr_level), paste0(chr_level, "\n")),
115
+    heatmap_legend_param = list(direction = "horizontal", title_position = "lefttop")) %v%
116
+Heatmap(t(char_mat), name = "CNV", col = c("gain" = "red", "loss" = "blue"),
117
+    border = TRUE, row_title = "character matrix",
118
+    heatmap_legend_param = list(direction = "horizontal", title_position = "lefttop", nrow = 1)) %v%
119
+HeatmapAnnotation(label = anno_mark(at = at, labels = labels, side = "bottom")) %v%
120
+HeatmapAnnotation(pt = anno_points(v, gp = gpar(col = 4:5), pch = c(1, 16)),
121
+    annotation_name_side = "left", height = unit(2, "cm")) %v%
122
+HeatmapAnnotation(bar = anno_barplot(v[, 1], gp = gpar(col = ifelse(v[ ,1] > 0, 2, 3))), 
123
+    annotation_name_side = "left", height = unit(2, "cm"))
124
+draw(ht_list, heatmap_legend_side = "bottom", merge_legend = TRUE)
125
+}
... ...
@@ -10,10 +10,10 @@ Method dispatch page for \code{show}.
10 10
 \code{show} can be dispatched on following classes:
11 11
 
12 12
 \itemize{
13
-\item \code{\link{show,SingleAnnotation-method}}, \code{\link{SingleAnnotation-class}} class method
14 13
 \item \code{\link{show,ColorMapping-method}}, \code{\link{ColorMapping-class}} class method
15
-\item \code{\link{show,HeatmapAnnotation-method}}, \code{\link{HeatmapAnnotation-class}} class method
16 14
 \item \code{\link{show,AnnotationFunction-method}}, \code{\link{AnnotationFunction-class}} class method
15
+\item \code{\link{show,HeatmapAnnotation-method}}, \code{\link{HeatmapAnnotation-class}} class method
16
+\item \code{\link{show,SingleAnnotation-method}}, \code{\link{SingleAnnotation-class}} class method
17 17
 \item \code{\link{show,HeatmapList-method}}, \code{\link{HeatmapList-class}} class method
18 18
 \item \code{\link{show,Heatmap-method}}, \code{\link{Heatmap-class}} class method
19 19
 }