Browse code

Commit made by the Bioconductor Git-SVN bridge.

Commit id: 3981fe02c795578b6314576278486fa5f88be6b8

merge from bioconductor


Commit id: 6811bed29d478afac5e518d7ea40819f5c649212

change version number


Commit id: 4785016520655b11334a5ea701eeb0b93778f205

change default value when the matrix has zeor column


Commit id: cf793440d71a2170d50b00564b6464fa92fe650c

fixed documentations


Commit id: 2fd8ba9a0ebf38c86fbe4eed604d37851e9bd91f

fixed bug when the heatmap list only contains zero column matrix



git-svn-id: https://hedgehog.fhcrc.org/bioconductor/trunk/madman/Rpacks/ComplexHeatmap@102662 bc3139a8-67e5-0310-9ffc-ced21a209358

z.gu authored on 18/04/2015 05:39:01
Showing 13 changed files

... ...
@@ -1,7 +1,7 @@
1 1
 Package: ComplexHeatmap
2 2
 Type: Package
3 3
 Title: Making Complex Heatmaps
4
-Version: 1.1.0
4
+Version: 1.1.1
5 5
 Date: 2015-3-26
6 6
 Author: Zuguang Gu
7 7
 Maintainer: Zuguang Gu <z.gu@dkfz.de>
... ...
@@ -42,8 +42,10 @@ exportMethods(component_width)
42 42
 exportMethods(draw_heatmap_list)
43 43
 export(grid.dendrogram)
44 44
 export(dist2)
45
+export(rowAnnotation)
45 46
 exportMethods(draw_heatmap_legend)
46 47
 exportMethods(add_heatmap)
48
+export(columnAnnotation)
47 49
 export(anno_barplot)
48 50
 export(anno_density)
49 51
 
... ...
@@ -1,7 +1,12 @@
1
-CHANGES IN VERSION 0.99.4
1
+CHANGES IN VERSION 1.1.1
2 2
 
3 3
 * fixed a bug when setting `cluster_rows` to FALSE but still cluster
4 4
   on rows.
5
+* add `rowAnnotation` and `columnAnnotation` functions
6
+* add examples in the vignette
7
+* No error if the heatmap list only contains zero-column matrix
8
+
9
+=================================================
5 10
 
6 11
 CHANGES IN VERSION 0.99.2
7 12
 
... ...
@@ -228,6 +228,7 @@ Heatmap = function(matrix, col, name, rect_gp = gpar(col = NA),
228 228
 
229 229
     if(ncol(matrix) == 0) {
230 230
         .Object@heatmap_param$show_heatmap_legend = FALSE
231
+        .Object@heatmap_param$width = unit(0, "null")
231 232
     }
232 233
 
233 234
     if(is.character(matrix) || ncol(matrix) <= 1) {
... ...
@@ -24,7 +24,8 @@ HeatmapAnnotation = setClass("HeatmapAnnotation",
24 24
 		anno_list = "list",  # a list of `SingleAnnotation` objects
25 25
 		anno_size = "ANY",
26 26
 		which = "character",
27
-		size = "ANY"  # only for  consistent of Heatmap
27
+		size = "ANY",  # only for  consistent of Heatmap
28
+		gap = "ANY"
28 29
 	),
29 30
 	prototype = list(
30 31
 		anno_list = list(),
... ...
@@ -47,8 +48,9 @@ HeatmapAnnotation = setClass("HeatmapAnnotation",
47 48
 # -annotation_height height of each annotation if annotations are column annotations.
48 49
 # -annotation_width width of each annotation if annotations are row annotations.
49 50
 # -height not using currently.
50
-# -width width of the whole heatmap annotations, only used for column annotation when appending to the list of heatmaps.
51
+# -width width of the whole heatmap annotations, only used for row annotation when appending to the list of heatmaps.
51 52
 # -gp graphic parameters for simple annotations.
53
+# -gap gap between each annotation
52 54
 #
53 55
 # == details
54 56
 # The simple annotations are defined by ``df`` and ``col`` arguments. Complex annotations are
... ...
@@ -57,12 +59,16 @@ HeatmapAnnotation = setClass("HeatmapAnnotation",
57 59
 # == value
58 60
 # A `HeatmapAnnotation-class` object.
59 61
 #
62
+# == seealso
63
+# There are two shortcut functions: `rowAnnotation` and `columnAnnotation`.
64
+#
60 65
 # == author
61 66
 # Zuguang Gu <z.gu@dkfz.de>
62 67
 #
63 68
 HeatmapAnnotation = function(df, name, col, show_legend, ..., 
64 69
 	which = c("column", "row"), annotation_height = 1, annotation_width = 1, 
65
-	height = unit(1, "cm"), width = unit(1, "cm"), gp = gpar(col = NA)) {
70
+	height = unit(1, "cm"), width = unit(1, "cm"), gp = gpar(col = NA),
71
+	gap = unit(0, "null")) {
66 72
 
67 73
 	.Object = new("HeatmapAnnotation")
68 74
 
... ...
@@ -139,7 +145,7 @@ HeatmapAnnotation = function(df, name, col, show_legend, ...,
139 145
 	}
140 146
 
141 147
 	if(!is.unit(anno_size)) {
142
-		anno_size = unit(anno_size/sum(anno_size), "npc")
148
+		anno_size = unit(anno_size/sum(anno_size), "null")
143 149
 	}
144 150
 
145 151
 
... ...
@@ -153,9 +159,63 @@ HeatmapAnnotation = function(df, name, col, show_legend, ...,
153 159
 
154 160
     .Object@size = size
155 161
 
162
+    if(is.null(gap)) gap = unit(0, "null")
163
+
164
+    if(length(gap) == 1) {
165
+    	.Object@gap = rep(gap, n_anno)
166
+    } else if(length(gap) == n_anno - 1) {
167
+    	.Object@gap = unit.c(gap, unit(0, "null"))
168
+    } else if(length(gap) < n_anno - 1) {
169
+    	stop("Length of `gap` is wrong.")
170
+    } else {
171
+    	.Object@gap = gap
172
+    }
173
+
156 174
     return(.Object)
157 175
 }
158 176
 
177
+# == title
178
+# Construct row annotations
179
+#
180
+# == param
181
+# -... pass to `HeatmapAnnotation`
182
+#
183
+# == details
184
+# The function is identical to 
185
+#
186
+#     HeatmapAnnotation(..., which = "row")
187
+#
188
+# == value
189
+# A `HeatmapAnnotation-class` object.
190
+#
191
+# == author
192
+# Zuguang Gu <z.gu@dkfz.de>
193
+#
194
+rowAnnotation = function(...) {
195
+	HeatmapAnnotation(..., which = "row")
196
+}
197
+
198
+# == title
199
+# Construct column annotations
200
+#
201
+# == param
202
+# -... pass to `HeatmapAnnotation`
203
+#
204
+# == details
205
+# The function is identical to
206
+#
207
+#     HeatmapAnnotation(..., which = "column")
208
+#
209
+# == value
210
+# A `HeatmapAnnotation-class` object.
211
+#
212
+# == author
213
+# Zuguang Gu <z.gu@dkfz.de>
214
+#
215
+columnAnnotation = function(...) {
216
+	HeatmapAnnotation(..., which = "column")
217
+}
218
+
159 219
 # == title
160 220
 # Get a list of color mapping objects
161 221
 #
... ...
@@ -210,13 +270,14 @@ setMethod(f = "draw",
210 270
 	which = object@which
211 271
 	n_anno = length(object@anno_list)
212 272
 	anno_size = object@anno_size
273
+	gap = object@gap
213 274
 
214 275
 	pushViewport(viewport(...))
215 276
 	for(i in seq_len(n_anno)) {
216 277
 		if(which == "column") {
217
-			pushViewport(viewport(y = sum(anno_size[seq_len(i)]), height = anno_size[i], just = c("center", "top")))
278
+			pushViewport(viewport(y = sum(anno_size[seq_len(i)]) + sum(gap[seq_len(i)]) - gap[i], height = anno_size[i], just = c("center", "top")))
218 279
 		} else {
219
-			pushViewport(viewport(x = sum(anno_size[seq_len(i)]), width = anno_size[i], just = c("right", "center")))
280
+			pushViewport(viewport(x = sum(anno_size[seq_len(i)]) + sum(gap[seq_len(i)]) - gap[i], width = anno_size[i], just = c("right", "center")))
220 281
 		}
221 282
 		draw(object@anno_list[[i]], index)
222 283
 		upViewport()
... ...
@@ -668,8 +668,30 @@ setMethod(f = "draw_heatmap_list",
668 668
 
669 669
     gap = object@ht_list_param$gap
670 670
     ht_index = which(sapply(object@ht_list, inherits, "Heatmap"))
671
-
672 671
     n = length(object@ht_list)
672
+
673
+    # if there is only one heatmap but with zero column, width for one
674
+    # row annotations is allowed to have no width set
675
+    if(length(ht_index) == 1) {
676
+        ht = object@ht_list[[ht_index]]
677
+        i_row_anno_nofix_width = which(sapply(object@ht_list, function(ht) {
678
+            if(inherits(ht, "Heatmap")) {
679
+                return(FALSE)
680
+            } else {
681
+                return(is.null(ht@size))
682
+            }
683
+        }))
684
+        i_row_anno_fix_width = setdiff(seq_len(n), c(i_row_anno_nofix_width, ht_index))
685
+        if(!is.null(ht@heatmap_param$width) && length(i_row_anno_nofix_width) == 1) {
686
+            if(length(i_row_anno_fix_width)) {
687
+                row_anno_fix_width = sum(do.call("unit.c", lapply(object@ht_list[i_row_anno_fix_width], function(x) x@size)))
688
+            } else {
689
+                row_anno_fix_width = unit(0, "null")
690
+            }
691
+            object@ht_list[[i_row_anno_nofix_width]]@size = unit(1, "npc") - ht@heatmap_param$width - row_anno_fix_width - sum(gap) + gap[length(gap)]
692
+        }
693
+    }
694
+
673 695
     # since each heatmap actually has nine rows, calculate the maximum height of corresponding rows in all heatmap 
674 696
     max_component_height = unit.c(
675 697
         max(do.call("unit.c", lapply(object@ht_list[ht_index], function(ht) component_height(ht, k = 1)))),
... ...
@@ -730,13 +752,17 @@ setMethod(f = "draw_heatmap_list",
730 752
     })
731 753
     heatmap_fixed_width = do.call("unit.c", heatmap_fixed_width)
732 754
     # width for body for each heatmap
733
-    heatmap_body_width = (unit(1, "npc") - sum(width_without_heatmap_body) - sum(heatmap_fixed_width) - sum(gap) + gap[length(gap)]) * (1/sum(heatmap_ncol)) * heatmap_ncol
755
+    if(sum(heatmap_ncol) == 0) {
756
+        heatmap_nofixed_width = unit(rep(0, n), "null")
757
+    } else {
758
+        heatmap_nofixed_width = (unit(1, "npc") - sum(width_without_heatmap_body) - sum(heatmap_fixed_width) - sum(gap) + gap[length(gap)]) * (1/sum(heatmap_ncol)) * heatmap_ncol
759
+    }
734 760
 
735 761
     # width of heatmap including body, and other components
736 762
     # width without fixed width
737
-    heatmap_width = sum(width_without_heatmap_body[1:3]) + heatmap_body_width[1] + sum(width_without_heatmap_body[5:7-1])
763
+    heatmap_width = sum(width_without_heatmap_body[1:3]) + heatmap_nofixed_width[1] + sum(width_without_heatmap_body[5:7-1])
738 764
     for(i in seq_len(n - 1) + 1) {
739
-        heatmap_width = unit.c(heatmap_width, sum(width_without_heatmap_body[6*(i-1) + 1:3]) + heatmap_body_width[i] + sum(width_without_heatmap_body[6*(i-1) + 5:7-1]))
765
+        heatmap_width = unit.c(heatmap_width, sum(width_without_heatmap_body[6*(i-1) + 1:3]) + heatmap_nofixed_width[i] + sum(width_without_heatmap_body[6*(i-1) + 5:7-1]))
740 766
     }
741 767
     # width with fixed width
742 768
     heatmap_width = heatmap_width + heatmap_fixed_width
... ...
@@ -13,7 +13,8 @@ Constructor method for HeatmapAnnotation class
13 13
 \usage{
14 14
 HeatmapAnnotation(df, name, col, show_legend, ...,
15 15
     which = c("column", "row"), annotation_height = 1, annotation_width = 1,
16
-    height = unit(1, "cm"), width = unit(1, "cm"), gp = gpar(col = NA))
16
+    height = unit(1, "cm"), width = unit(1, "cm"), gp = gpar(col = NA),
17
+    gap = NULL)
17 18
 }
18 19
 \arguments{
19 20
 
... ...
@@ -26,8 +27,9 @@ HeatmapAnnotation(df, name, col, show_legend, ...,
26 27
   \item{annotation_height}{height of each annotation if annotations are column annotations.}
27 28
   \item{annotation_width}{width of each annotation if annotations are row annotations.}
28 29
   \item{height}{not using currently.}
29
-  \item{width}{width of the whole heatmap annotations, only used for column annotation when appending to the list of heatmaps.}
30
+  \item{width}{width of the whole heatmap annotations, only used for row annotation when appending to the list of heatmaps.}
30 31
   \item{gp}{graphic parameters for simple annotations.}
32
+  \item{gap}{gap between each annotation}
31 33
 
32 34
 }
33 35
 \details{
... ...
@@ -39,6 +41,11 @@ The simple annotations are defined by \code{df} and \code{col} arguments. Comple
39 41
 A \code{\link{HeatmapAnnotation-class}} object.  
40 42
 
41 43
 
44
+}
45
+\seealso{
46
+There are two shortcut functions: \code{\link{rowAnnotation}} and \code{\link{columnAnnotation}}.  
47
+
48
+
42 49
 }
43 50
 \author{
44 51
 Zuguang Gu <z.gu@dkfz.de>  
... ...
@@ -20,7 +20,7 @@ Add heatmaps or row annotations as a heatmap list
20 20
 
21 21
 }
22 22
 \details{
23
-There is a shortcut function \code{+.Heatmap}.  
23
+There is a shortcut function \code{+.AdditiveUnit}.  
24 24
 
25 25
 
26 26
 }
... ...
@@ -20,7 +20,7 @@ Add row annotations or heatmaps as a heatmap list
20 20
 
21 21
 }
22 22
 \details{
23
-There is a shortcut function \code{+.HeatmapAnnotation}.  
23
+There is a shortcut function \code{+.AdditiveUnit}.  
24 24
 
25 25
 
26 26
 }
... ...
@@ -20,7 +20,7 @@ Add heatmaps and row annotations to the heatmap list
20 20
 
21 21
 }
22 22
 \details{
23
-There is a shortcut function \code{+.HeatmapList}.  
23
+There is a shortcut function \code{+.AdditiveUnit}.  
24 24
 
25 25
 
26 26
 }
27 27
new file mode 100644
... ...
@@ -0,0 +1,39 @@
1
+\name{columnAnnotation}
2
+\alias{columnAnnotation}
3
+\title{
4
+Construct column annotations  
5
+
6
+
7
+}
8
+\description{
9
+Construct column annotations  
10
+
11
+
12
+}
13
+\usage{
14
+columnAnnotation(...)
15
+}
16
+\arguments{
17
+
18
+  \item{...}{pass to \code{\link{HeatmapAnnotation}}}
19
+
20
+}
21
+\details{
22
+The function is identical to  
23
+
24
+  \preformatted{
25
+    HeatmapAnnotation(..., which = "column")
26
+  }
27
+
28
+
29
+}
30
+\value{
31
+A \code{\link{HeatmapAnnotation-class}} object.  
32
+
33
+
34
+}
35
+\author{
36
+Zuguang Gu <z.gu@dkfz.de>  
37
+
38
+
39
+}
0 40
new file mode 100644
... ...
@@ -0,0 +1,39 @@
1
+\name{rowAnnotation}
2
+\alias{rowAnnotation}
3
+\title{
4
+Construct row annotations  
5
+
6
+
7
+}
8
+\description{
9
+Construct row annotations  
10
+
11
+
12
+}
13
+\usage{
14
+rowAnnotation(...)
15
+}
16
+\arguments{
17
+
18
+  \item{...}{pass to \code{\link{HeatmapAnnotation}}}
19
+
20
+}
21
+\details{
22
+The function is identical to   
23
+
24
+  \preformatted{
25
+    HeatmapAnnotation(..., which = "row")
26
+  }
27
+
28
+
29
+}
30
+\value{
31
+A \code{\link{HeatmapAnnotation-class}} object.  
32
+
33
+
34
+}
35
+\author{
36
+Zuguang Gu <z.gu@dkfz.de>  
37
+
38
+
39
+}
... ...
@@ -649,6 +649,14 @@ ha = HeatmapAnnotation(df = df, which = "row", width = unit(1, "cm"))
649 649
 draw(ha, 1:12)
650 650
 ```
651 651
 
652
+Similar, there can be more than one row annotation:
653
+
654
+```{r, fig.width = 3, fig.height = 7}
655
+ha_combined = HeatmapAnnotation(df = df, boxplot = anno_boxplot(mat, which = "row"), 
656
+    which = "row", annotation_width = c(1, 3))
657
+draw(ha_combined, 1:12)
658
+```
659
+
652 660
 ### Mix heatmaps and row annotations
653 661
 
654 662
 Essentially, row annotations and column annotations are identical graphics, but in applications,
... ...
@@ -677,7 +685,7 @@ For row annotations, more complex annotation graphics can help to visualize the
677 685
 ht1 = Heatmap(mat, name = "ht1", km = 2)
678 686
 random_data = lapply(1:12, function(x) runif(20))
679 687
 random_data[1:6] = lapply(random_data[1:6], function(x) x*0.5)
680
-ha = HeatmapAnnotation(distribution = function(index) {
688
+ha2 = HeatmapAnnotation(distribution = function(index) {
681 689
         random_data = random_data[index]
682 690
         n = length(index)
683 691
         
... ...
@@ -692,7 +700,17 @@ ha = HeatmapAnnotation(distribution = function(index) {
692 700
             upViewport()
693 701
         }
694 702
     }, which = "row", width = unit(10, "cm"))
695
-draw(ht1 + ha, row_hclust_side = "left", row_sub_title_side = "right")
703
+draw(ht1 + ha2, row_hclust_side = "left", row_sub_title_side = "right")
704
+```
705
+
706
+If no heatmap is needed to draw and users only want to arrange a list of row annotations, an empty
707
+matrix with no column can be added to the heatmap list. (This functionality will be improved in the future)
708
+
709
+```{r all_row_annotations, fig.width = 4}
710
+nr = nrow(mat)
711
+ha = HeatmapAnnotation(df = df, which = "row", width = NULL)
712
+Heatmap(matrix(nrow = nr, ncol = 0), split = sample(c("A", "B"), nr, replace = TRUE)) + 
713
+    ha + ha_boxplot
696 714
 ```
697 715
 
698 716
 ## Access components