Browse code

HeatmapAnnotation() can directly add annotation names

Zuguang Gu authored on 14/06/2016 14:00:31
Showing 16 changed files

... ...
@@ -2,14 +2,14 @@ Package: ComplexHeatmap
2 2
 Type: Package
3 3
 Title: Making Complex Heatmaps
4 4
 Version: 1.11.5
5
-Date: 2016-6-7
5
+Date: 2016-6-14
6 6
 Author: Zuguang Gu
7 7
 Maintainer: Zuguang Gu <z.gu@dkfz.de>
8 8
 Depends: R (>= 3.1.2), grid, graphics, stats, grDevices
9 9
 Imports: methods, circlize (>= 0.3.4), GetoptLong, colorspace,
10 10
     RColorBrewer, dendextend (>= 1.0.1), GlobalOptions (>= 0.0.10)
11 11
 Suggests: testthat (>= 0.3), knitr, markdown, cluster, MASS, pvclust, 
12
-    dendsort, HilbertCurve, Cairo, png, jpeg, tiff
12
+    dendsort, HilbertCurve, Cairo, png, jpeg, tiff, fastcluster
13 13
 VignetteBuilder: knitr
14 14
 Description: Complex heatmaps are efficient to visualize associations 
15 15
     between different sources of data sets and reveal potential structures. 
... ...
@@ -18,6 +18,6 @@ Description: Complex heatmaps are efficient to visualize associations
18 18
 biocViews: Software, Visualization, Sequencing
19 19
 URL: https://github.com/jokergoo/ComplexHeatmap
20 20
 License: GPL (>= 2)
21
-Packaged: 2016-6-7 00:00:00 UTC; Administrator
21
+Packaged: 2016-6-14 00:00:00 UTC; Administrator
22 22
 Repository: Bioconductor
23
-Date/Publication: 2016-6-7 00:00:00
23
+Date/Publication: 2016-6-14 00:00:00
... ...
@@ -648,6 +648,12 @@ setMethod(f = "make_column_cluster",
648 648
     signature = "Heatmap",
649 649
     definition = function(object) {
650 650
     
651
+    if(ht_global_opt("fast_hclust")) {
652
+        hclust = fastcluster::hclust
653
+    } else {
654
+        hclust = stats::hclust
655
+    }
656
+    
651 657
     mat = object@matrix
652 658
     distance = object@column_dend_param$distance
653 659
     method = object@column_dend_param$method
... ...
@@ -730,6 +736,12 @@ setMethod(f = "make_row_cluster",
730 736
     signature = "Heatmap",
731 737
     definition = function(object) {
732 738
 
739
+    if(ht_global_opt("fast_hclust")) {
740
+        hclust = fastcluster::hclust
741
+    } else {
742
+        hclust = stats::hclust
743
+    }
744
+
733 745
     mat = object@matrix
734 746
     distance = object@row_dend_param$distance
735 747
     method = object@row_dend_param$method
... ...
@@ -57,6 +57,7 @@ HeatmapAnnotation = setClass("HeatmapAnnotation",
57 57
 # -annotation_name_gp graphic parameters for anntation names. Graphic paramters can be vectors.
58 58
 # -annotation_name_offset offset to the annotations, `grid::unit` object. The value can be a vector.
59 59
 # -annotation_name_side side of the annotation names.
60
+# -annotation_name_rot rotation of the annotation names, can only take values in ``c(00, 90, 180, 270)``. The value can be a vector.
60 61
 #
61 62
 # == details
62 63
 # The simple annotations are defined by ``df`` and ``col`` arguments. Complex annotations are
... ...
@@ -85,7 +86,8 @@ HeatmapAnnotation = function(df, name, col, na_col = "grey",
85 86
 	show_annotation_name = FALSE,
86 87
 	annotation_name_gp = gpar(),
87 88
 	annotation_name_offset = unit(2, "mm"),
88
-	annotation_name_side = ifelse(which == "column", "right", "bottom")) {
89
+	annotation_name_side = ifelse(which == "column", "right", "bottom"),
90
+	annotation_name_rot = ifelse(which == "column", 0, 90)) {
89 91
 
90 92
 	.Object = new("HeatmapAnnotation")
91 93
 
... ...
@@ -104,7 +106,7 @@ HeatmapAnnotation = function(df, name, col, na_col = "grey",
104 106
     called_args = names(arg_list)
105 107
     anno_args = setdiff(called_args, c("name", "col", "na_col", "annotation_legend_param", "show_legend", "which", 
106 108
     	                             "annotation_height", "annotation_width", "height", "width", "gp", "gap",
107
-    	                             "show_annotation_name", "annotation_name_gp", "annotation_name_offset", "annotation_name_side"))
109
+    	                             "show_annotation_name", "annotation_name_gp", "annotation_name_offset", "annotation_name_side", "annotation_name_rot"))
108 110
     if(any(anno_args == "")) stop("annotations should have names.")
109 111
     if(any(duplicated(anno_args))) stop("names of annotations should be unique.")
110 112
     anno_arg_list = list(...)
... ...
@@ -170,6 +172,9 @@ HeatmapAnnotation = function(df, name, col, na_col = "grey",
170 172
     if(length(annotation_name_side) == 1) {
171 173
     	annotation_name_side = rep(annotation_name_side, n_total_anno)
172 174
     }
175
+    if(length(annotation_name_rot) == 1) {
176
+    	annotation_name_rot = rep(annotation_name_rot, n_total_anno)
177
+    }
173 178
     annotation_name_gp = recycle_gp(annotation_name_gp, n_total_anno)
174 179
 
175 180
 	i_simple = 0
... ...
@@ -195,7 +200,7 @@ HeatmapAnnotation = function(df, name, col, na_col = "grey",
195 200
 		        	anno_list = c(anno_list, list(SingleAnnotation(name = anno_name[i], value = df[, i], na_col = na_col, which = which, 
196 201
 		        		show_legend = show_legend[i_simple + i], gp = gp, legend_param = annotation_legend_param[[i_simple + i]],
197 202
 		        		show_name = show_annotation_name[i_anno], name_gp = subset_gp(annotation_name_gp, i_anno), 
198
-		        		name_offset = annotation_name_offset[i_anno], name_side = annotation_name_side[i_anno])))
203
+		        		name_offset = annotation_name_offset[i_anno], name_side = annotation_name_side[i_anno], name_rot = annotation_name_rot[i_anno])))
199 204
 		        }
200 205
 		    } else {
201 206
 		        for(i in seq_len(n_anno)) {
... ...
@@ -204,12 +209,12 @@ HeatmapAnnotation = function(df, name, col, na_col = "grey",
204 209
 		        		anno_list = c(anno_list, list(SingleAnnotation(name = anno_name[i], value = df[, i], na_col = na_col, which = which, 
205 210
 		        			show_legend = show_legend[i_simple + i], gp = gp, legend_param = annotation_legend_param[[i_simple + i]],
206 211
 		        			show_name = show_annotation_name[i_anno], name_gp = subset_gp(annotation_name_gp, i_anno), 
207
-		        			name_offset = annotation_name_offset[i_anno], name_side = annotation_name_side[i_anno])))
212
+		        			name_offset = annotation_name_offset[i_anno], name_side = annotation_name_side[i_anno], name_rot = annotation_name_rot[i_anno])))
208 213
 		        	} else {
209 214
 		        		anno_list = c(anno_list, list(SingleAnnotation(name = anno_name[i], value = df[, i], na_col = na_col, col = col[[ anno_name[i] ]], 
210 215
 		        			which = which, show_legend = show_legend[i_simple + i], gp = gp, legend_param = annotation_legend_param[[i_simple + i]],
211 216
 		        			show_name = show_annotation_name[i_anno], name_gp = subset_gp(annotation_name_gp, i_anno), 
212
-		        			name_offset = annotation_name_offset[i_anno], name_side = annotation_name_side[i_anno])))
217
+		        			name_offset = annotation_name_offset[i_anno], name_side = annotation_name_side[i_anno], name_rot = annotation_name_rot[i_anno])))
213 218
 		        	}
214 219
 		        }
215 220
 		    }
... ...
@@ -219,7 +224,7 @@ HeatmapAnnotation = function(df, name, col, na_col = "grey",
219 224
 			if(inherits(anno_arg_list[[ag]], "function")) {
220 225
 				anno_list = c(anno_list, list(SingleAnnotation(name = ag, fun = anno_arg_list[[ag]], which = which,
221 226
 					show_name = show_annotation_name[i_anno], name_gp = subset_gp(annotation_name_gp, i_anno), 
222
-		        	name_offset = annotation_name_offset[i_anno], name_side = annotation_name_side[i_anno])))
227
+		        	name_offset = annotation_name_offset[i_anno], name_side = annotation_name_side[i_anno], name_rot = annotation_name_rot[i_anno])))
223 228
 			} else if(is.atomic(anno_arg_list[[ag]])) {
224 229
 
225 230
 			    if(is.null(simple_length)) {
... ...
@@ -231,18 +236,18 @@ HeatmapAnnotation = function(df, name, col, na_col = "grey",
231 236
 			        anno_list = c(anno_list, list(SingleAnnotation(name = ag, value = anno_arg_list[[ag]], na_col = na_col, which = which, 
232 237
 			        	show_legend = show_legend[i_simple + 1], gp = gp, legend_param = annotation_legend_param[[i_simple + 1]],
233 238
 			        	show_name = show_annotation_name[i_anno], name_gp = subset_gp(annotation_name_gp, i_anno), 
234
-		        		name_offset = annotation_name_offset[i_anno], name_side = annotation_name_side[i_anno])))
239
+		        		name_offset = annotation_name_offset[i_anno], name_side = annotation_name_side[i_anno], name_rot = annotation_name_rot[i_anno])))
235 240
 			    } else {
236 241
 			        if(is.null(col[[ ag ]])) { # if the color is not provided
237 242
 			        	anno_list = c(anno_list, list(SingleAnnotation(name = ag, value = anno_arg_list[[ag]], na_col = na_col, which = which, 
238 243
 			        		show_legend = show_legend[i_simple + 1], gp = gp, legend_param = annotation_legend_param[[i_simple + 1]],
239 244
 			        		show_name = show_annotation_name[i_anno], name_gp = subset_gp(annotation_name_gp, i_anno), 
240
-		        		name_offset = annotation_name_offset[i_anno], name_side = annotation_name_side[i_anno])))
245
+		        		name_offset = annotation_name_offset[i_anno], name_side = annotation_name_side[i_anno], name_rot = annotation_name_rot[i_anno])))
241 246
 			        } else {
242 247
 			        	anno_list = c(anno_list, list(SingleAnnotation(name = ag, value = anno_arg_list[[ag]], na_col = na_col, col = col[[ ag ]], 
243 248
 			        		which = which, show_legend = show_legend[i_simple + 1], gp = gp, legend_param = annotation_legend_param[[i_simple + 1]],
244 249
 			        		show_name = show_annotation_name[i_anno], name_gp = subset_gp(annotation_name_gp, i_anno), 
245
-		        			name_offset = annotation_name_offset[i_anno], name_side = annotation_name_side[i_anno])))
250
+		        			name_offset = annotation_name_offset[i_anno], name_side = annotation_name_side[i_anno], name_rot = annotation_name_rot[i_anno])))
246 251
 			        }
247 252
 			    }
248 253
 			    i_simple = i_simple + 1
... ...
@@ -311,12 +316,11 @@ HeatmapAnnotation = function(df, name, col, na_col = "grey",
311 316
 #
312 317
 # == param
313 318
 # -... pass to `HeatmapAnnotation`
314
-# -width default width of the row annotations
315 319
 #
316 320
 # == details
317 321
 # The function is identical to 
318 322
 #
319
-#     HeatmapAnnotation(..., which = "row", width = width)
323
+#     HeatmapAnnotation(..., which = "row")
320 324
 #
321 325
 # == value
322 326
 # A `HeatmapAnnotation-class` object.
... ...
@@ -324,8 +328,8 @@ HeatmapAnnotation = function(df, name, col, na_col = "grey",
324 328
 # == author
325 329
 # Zuguang Gu <z.gu@dkfz.de>
326 330
 #
327
-rowAnnotation = function(..., width = unit(1, "cm")) {
328
-	HeatmapAnnotation(..., which = "row", width = width)
331
+rowAnnotation = function(...) {
332
+	HeatmapAnnotation(..., which = "row")
329 333
 }
330 334
 
331 335
 # == title
... ...
@@ -65,6 +65,7 @@ SingleAnnotation = setClass("SingleAnnotation",
65 65
 # -name_gp graphic parameters for annotation name
66 66
 # -name_offset offset to the annotation, a `grid::unit` object
67 67
 # -name_side 'right' and 'left' for column annotations and 'top' and 'bottom' for row annotations
68
+# -name_rot rotation of the annotation name, can only take values in ``c(00, 90, 180, 270)``.
68 69
 #
69 70
 # == details
70 71
 # The most simple annotation is one row or one column grids in which different colors
... ...
@@ -99,10 +100,11 @@ SingleAnnotation = function(name, value, col, fun,
99 100
 	show_legend = TRUE, 
100 101
 	gp = gpar(col = NA), 
101 102
 	legend_param = list(),
102
-	show_name = TRUE, 
103
+	show_name = FALSE, 
103 104
 	name_gp = gpar(fontsize = 12),
104 105
 	name_offset = unit(2, "mm"),
105
-	name_side = ifelse(which == "column", "right", "bottom")) {
106
+	name_side = ifelse(which == "column", "right", "bottom"),
107
+    name_rot = ifelse(which == "column", 0, 90)) {
106 108
 
107 109
 	# re-define some of the argument values according to global settings
108 110
     called_args = names(as.list(match.call())[-1])
... ...
@@ -131,7 +133,11 @@ SingleAnnotation = function(name, value, col, fun,
131 133
     }
132 134
     .Object@name = name
133 135
 
134
-    name_rot = ifelse(which == "column", 0, 90)
136
+    if(!name_rot %in% c(0, 90, 180, 270)) {
137
+        stop("`name_rot` can only take values in c(0, 90, 180, 270)")
138
+    }
139
+
140
+    
135 141
     if(which == "column") {
136 142
     	if(!name_side %in% c("left", "right")) {
137 143
     		stop("`name_side` should be 'left' or 'right' when it is a column annotation.")
... ...
@@ -139,11 +145,27 @@ SingleAnnotation = function(name, value, col, fun,
139 145
     	if(name_side == "left") {
140 146
     		name_x = unit(0, "npc") - name_offset
141 147
     		name_y = unit(0.5, "npc")
142
-    		name_just = "right"
148
+            if(name_rot == 0) {
149
+                name_just = "right"
150
+            } else if(name_rot == 90) {
151
+                name_just = "bottom"
152
+            } else if(name_rot == 180) {
153
+                name_just = "left"
154
+            } else {
155
+                name_just = "top"
156
+            }
143 157
     	} else {
144 158
     		name_x = unit(1, "npc") + name_offset
145 159
     		name_y = unit(0.5, "npc")
146
-    		name_just = "left"
160
+            if(name_rot == 0) {
161
+                name_just = "left"
162
+            } else if(name_rot == 90) {
163
+                name_just = "top"
164
+            } else if(name_rot == 180) {
165
+                name_just = "right"
166
+            } else {
167
+                name_just = "bottom"
168
+            }
147 169
     	}
148 170
     } else if(which == "row") {
149 171
     	if(!name_side %in% c("top", "bottom")) {
... ...
@@ -152,11 +174,27 @@ SingleAnnotation = function(name, value, col, fun,
152 174
     	if(name_side == "top") {
153 175
     		name_x = unit(0.5, "npc")
154 176
     		name_y = unit(1, "npc") + name_offset
155
-    		name_just = "left"
177
+            if(name_rot == 0) {
178
+                name_just = "bottom"
179
+            } else if(name_rot == 90) {
180
+                name_just = "left"
181
+            } else if(name_rot == 180) {
182
+                name_just = "top"
183
+            } else {
184
+                name_just = "right"
185
+            }
156 186
     	} else {
157 187
     		name_x = unit(0.5, "npc")
158 188
     		name_y = unit(0, "npc") - name_offset
159
-    		name_just = "right"
189
+            if(name_rot == 0) {
190
+                name_just = "top"
191
+            } else if(name_rot == 90) {
192
+                name_just = "right"
193
+            } else if(name_rot == 180) {
194
+                name_just = "bottom"
195
+            } else {
196
+                name_just = "left"
197
+            }
160 198
     	}
161 199
     }
162 200
     .Object@name_param = list(show = show_name,
... ...
@@ -107,20 +107,7 @@ ht_global_opt = setGlobalOptions(
107 107
 		.value = NULL),
108 108
 	fast_hclust = list(
109 109
 		.value = FALSE,
110
-		.filter = function(x) {
111
-				if(x) {
112
-					if(require(fastcluster)) {
113
-						assign("hclust", envir = topenv()) = getFromNamespace("hclust", "fastcluster")
114
-					} else {
115
-						stop("Cannot find fastcluster package.")
116
-					}
117
-				} else {
118
-					assign("hclust", envir = topenv()) = getFromNamespace("hclust", "stats")
119
-				}
120
-				x
121
-			}
122
-		)
110
+		.class = "logical",
111
+		.length = 1
112
+	)
123 113
 )
124
-
125
-hclust = getFromNamespace("hclust", "stats")
126
-
... ...
@@ -21,7 +21,8 @@ HeatmapAnnotation(df, name, col, na_col = "grey",
21 21
     show_annotation_name = FALSE,
22 22
     annotation_name_gp = gpar(),
23 23
     annotation_name_offset = unit(2, "mm"),
24
-    annotation_name_side = ifelse(which == "column", "right", "bottom"))
24
+    annotation_name_side = ifelse(which == "column", "right", "bottom"),
25
+    annotation_name_rot = ifelse(which == "column", 0, 90))
25 26
 }
26 27
 \arguments{
27 28
 
... ...
@@ -43,6 +44,7 @@ HeatmapAnnotation(df, name, col, na_col = "grey",
43 44
   \item{annotation_name_gp}{graphic parameters for anntation names. Graphic paramters can be vectors.}
44 45
   \item{annotation_name_offset}{offset to the annotations, \code{\link[grid]{unit}} object. The value can be a vector.}
45 46
   \item{annotation_name_side}{side of the annotation names.}
47
+  \item{annotation_name_rot}{rotation of the annotation names, can only take values in \code{c(00, 90, 180, 270)}. The value can be a vector.}
46 48
 
47 49
 }
48 50
 \details{
... ...
@@ -13,10 +13,11 @@ SingleAnnotation(name, value, col, fun,
13 13
     show_legend = TRUE,
14 14
     gp = gpar(col = NA),
15 15
     legend_param = list(),
16
-    show_name = TRUE,
16
+    show_name = FALSE,
17 17
     name_gp = gpar(fontsize = 12),
18 18
     name_offset = unit(2, "mm"),
19
-    name_side = ifelse(which == "column", "right", "bottom"))
19
+    name_side = ifelse(which == "column", "right", "bottom"),
20
+    name_rot = ifelse(which == "column", 0, 90))
20 21
 }
21 22
 \arguments{
22 23
 
... ...
@@ -33,6 +34,7 @@ SingleAnnotation(name, value, col, fun,
33 34
   \item{name_gp}{graphic parameters for annotation name}
34 35
   \item{name_offset}{offset to the annotation, a \code{\link[grid]{unit}} object}
35 36
   \item{name_side}{'right' and 'left' for column annotations and 'top' and 'bottom' for row annotations}
37
+  \item{name_rot}{rotation of the annotation name, can only take values in \code{c(00, 90, 180, 270)}.}
36 38
 
37 39
 }
38 40
 \details{
... ...
@@ -7,19 +7,18 @@ Construct row annotations
7 7
 Construct row annotations
8 8
 }
9 9
 \usage{
10
-rowAnnotation(..., width = unit(1, "cm"))
10
+rowAnnotation(...)
11 11
 }
12 12
 \arguments{
13 13
 
14 14
   \item{...}{pass to \code{\link{HeatmapAnnotation}}}
15
-  \item{width}{default width of the row annotations}
16 15
 
17 16
 }
18 17
 \details{
19 18
 The function is identical to
20 19
 
21 20
   \preformatted{
22
-    HeatmapAnnotation(..., which = "row", width = width)  }
21
+    HeatmapAnnotation(..., which = "row")  }
23 22
 }
24 23
 \value{
25 24
 A \code{\link{HeatmapAnnotation-class}} object.
... ...
@@ -64,7 +64,7 @@ to get full use of the package.
64 64
 
65 65
 ## Vignettes
66 66
 
67
-There are several vignettes in the package. Each vignette focuses on a specific topic. Following
67
+There are several vignettes in the package. Each vignette focuses on one specific topic. Following
68 68
 lists the general topics discussed in these vignettes:
69 69
 
70 70
   1. [**Making a Single Heatmap**](s2.single_heatmap.html)
... ...
@@ -72,13 +72,13 @@ lists the general topics discussed in these vignettes:
72 72
     This vignette introduces the basic configuration for making a single heatmap. Similar as other
73 73
     R functions/packages, the basic usage is quite similar, but there are several unique features
74 74
     for **ComplexHeamtap** package.
75
-    - Works both for numeric matrix and character matrix
75
+    - Works both for numeric matrix and character matrix.
76 76
     - For numeric matrix which contains continuous values, the package allows a color mapping function
77 77
       which can give more accurate colors and be robust to outliers.
78 78
     - Highly flexible for clustering. You can define the distance method for clustering by:
79
-          * a pre-defined distance such as "euclidean" or "pearson"
80
-          * a self-defined function which calculates distance from a matrix.
81
-          * a self-defined function which calculates distance from two vectors
79
+          * a pre-defined distance such as "euclidean" or "pearson",
80
+          * a self-defined function which calculates distance from a matrix,
81
+          * a self-defined function which calculates distance from two vectors.
82 82
         
83 83
         You can define the clustering method by:
84 84
           * a clustering function such as `diana()` from **cluster** package
... ...
@@ -96,7 +96,7 @@ lists the general topics discussed in these vignettes:
96 96
 
97 97
   3. [**Heatmap Annotations**](s4.heatmap_annotation.html)
98 98
 
99
-    This vignette introduces the concept of the heatmap annotation and demonstrate how to make simple annotations
99
+    This vignette introduces the concept of the heatmap annotation and demonstrates how to make simple annotations
100 100
     as well as complex annotations. Also, the vignette explains the difference between column annotations
101 101
     and row annotations.
102 102
 
... ...
@@ -121,4 +121,11 @@ lists the general topics discussed in these vignettes:
121 121
   8. [**Examples**](s9.examples.html)
122 122
 
123 123
     More simulated and real-world examples are shown in this vignette.
124
+
125
+In the supplementaries of [the ComplexHeatmap paper](http://bioinformatics.oxfordjournals.org/content/early/2016/05/20/bioinformatics.btw313.abstract), there are four comprehensive examples which are applied
126
+on real-world high-throughput datasets. [The examples can be found here.](http://jokergoo.github.io/supplementary/ComplexHeatmap-supplementary1-4/index.html)
127
+
128
+Also [my blog](http://jokergoo.github.io/blog.html) has some examples and tips for making better complex heatmaps.
129
+
130
+
124 131
     
... ...
@@ -196,7 +196,7 @@ Heatmap(mat, name = "foo", column_title = "I am a big column title",
196 196
     column_title_gp = gpar(fontsize = 20, fontface = "bold"))
197 197
 ```
198 198
 
199
-Roatations for titles can be set by `row_title_rot` and `column_title_rot`, but only horizontal and vertical 
199
+Rotations for titles can be set by `row_title_rot` and `column_title_rot`, but only horizontal and vertical 
200 200
 rotations are allowed.
201 201
 
202 202
 ```{r title_rotation}
... ...
@@ -212,7 +212,7 @@ contains clustering, or directly by a clustering function. It is also possible t
212 212
 your dendrograms with different colors and styles for different branches for better revealing
213 213
 structures of your data.
214 214
 
215
-First there are general settings for the clustering, e.g. whether show dendrograms, side
215
+First there are general settings for the clustering, e.g. whether do or show dendrograms, side
216 216
 of the dendrograms and size of the dendrograms.
217 217
 
218 218
 ```{r cluster_basic}
... ...
@@ -263,6 +263,7 @@ If possible distance method provided, you can also cluster a character matrix.
263 263
 
264 264
 ```{r cluster_character_matrix}
265 265
 mat_letters = matrix(sample(letters[1:4], 100, replace = TRUE), 10)
266
+# distance in th ASCII table
266 267
 dist_letters = function(x, y) {
267 268
     x = strtoi(charToRaw(paste(x, collapse = "")), base = 16)
268 269
     y = strtoi(charToRaw(paste(y, collapse = "")), base = 16)
... ...
@@ -294,8 +295,7 @@ Heatmap(mat, name = "foo", cluster_rows = as.dendrogram(diana(mat)),
294 295
 ```
295 296
 
296 297
 In the native `heatmap()` function, dendrograms on row and on column are reordered to let features with larger different
297
-separated more from each other, but according to my experience, the default reordering can not always give nice visualization.
298
-So by default the reordering for the dendrograms are turned off for `Heatmap()` function. 
298
+separated more from each other, By default the reordering for the dendrograms are turned on by `Heatmap()` as well. 
299 299
 
300 300
 Besides the default reordering method, you can first generate a dendrogram and apply other reordering
301 301
 method and then send the reordered dendrogram to `cluster_rows` argument. 
... ...
@@ -340,6 +340,26 @@ Heatmap(mat, name = "foo", cluster_rows = function(m) as.dendrogram(diana(m)),
340 340
     cluster_columns = function(m) as.dendrogram(agnes(m)))
341 341
 ```
342 342
 
343
+`fastcluster::hclust` implements a faster version of `hclust`. We can re-define `cluster_rows` and `cluster_columns`
344
+to use the faster version of `hclust`. But note `fastcluster::hclust` only speed up the calculation of the cluster while not the
345
+calculation of distance matrix.
346
+
347
+```{r}
348
+# code not run when building the vignette
349
+Heatmap(mat, name = "foo", cluster_rows = function(m) fastcluster::hclust(dist(m)),
350
+    cluster_columns = function(m) fastcluster::hclust(dist(m))) # for column cluster, m will be automatically transposed
351
+```
352
+
353
+To make it more convinient to use the faster version of `hclust` (assuming you have many heatmaps to be concatenated), it can
354
+be set as a global option:
355
+
356
+```{r}
357
+# code not run when building the vignette
358
+ht_global_opt(fast_hclust = TRUE)
359
+# now hclust from fastcluster package is used in all heatmaps
360
+Heatmap(mat, name = "foo")
361
+```
362
+
343 363
 Clustering can help to adjust order in rows and in columns. But you can still set the order manually by `row_order`
344 364
 and `column_order`. Note you need to turn off clustering
345 365
 if you want to set order manually. `row_order` and `column_order` can also be set according to matrix row names and column names if they exist.
... ...
@@ -438,6 +458,8 @@ and they want to split rows by splitting the dendrogram into k sub trees. In thi
438 458
 `split` can be specified as a single number:
439 459
 
440 460
 ```{r split_dendrogram}
461
+dend = hclust(dist(mat))
462
+dend = color_branches(dend, k = 2)
441 463
 Heatmap(mat, name = "foo", cluster_rows = dend, split = 2)
442 464
 ```
443 465
 
... ...
@@ -600,7 +622,7 @@ the file size. In `Heatmap()` function, there are four options which control how
600 622
 the raster image: `use_raster`, `raster_device`, `raster_quality`, `raster_device_param`. 
601 623
 
602 624
 You can choose graphic device (`png`, `jpeg` and `tiff`) by `raster_device`, control the quality of the raster image by `raster_quality`,
603
-and pass further parameters for a specific device by `raster_device_param`.
625
+and pass further parameters for a specific device by `raster_device_param`. [Check this web page for better demonstrations.](http://zuguang.de/blog/html/d3aa6e2b289514ecddded64a467d1961.html)
604 626
 
605 627
 ## Session info
606 628
 
... ...
@@ -31,7 +31,8 @@ options(width = 100)
31 31
 
32 32
 A list of heatmaps can improve visualization of the correspondence between multiple data sources.
33 33
 In this vignette, we will discuss configurations for making a list of heatmaps and you can
34
-see more real-world examples in the [**Examples**](s9.examples.html) vignette.
34
+see more real-world examples in the [**Examples**](s9.examples.html) vignette as well as [in the 
35
+supplementaries](http://jokergoo.github.io/supplementary/ComplexHeatmap-supplementary1-4/index.html) of [the ComplexHeatmap paper](http://bioinformatics.oxfordjournals.org/content/early/2016/05/20/bioinformatics.btw313.abstract).
35 36
 
36 37
 ## Heatmap concatenation
37 38
 
... ...
@@ -44,13 +45,18 @@ are to be combined, users can append one heatmap to the other by `+` operator.
44 45
 ```{r heatmap_list_default, fig.width = 10}
45 46
 library(ComplexHeatmap)
46 47
 
47
-mat = matrix(rnorm(80, 2), 8, 10)
48
-mat = rbind(mat, matrix(rnorm(40, -2), 4, 10))
49
-rownames(mat) = paste0("R", 1:12)
50
-colnames(mat) = paste0("C", 1:10)
48
+mat1 = matrix(rnorm(80, 2), 8, 10)
49
+mat1 = rbind(mat1, matrix(rnorm(40, -2), 4, 10))
50
+rownames(mat1) = paste0("R", 1:12)
51
+colnames(mat1) = paste0("C", 1:10)
52
+
53
+mat2 = matrix(rnorm(60, 2), 6, 10)
54
+mat2 = rbind(mat2, matrix(rnorm(60, -2), 6, 10))
55
+rownames(mat2) = paste0("R", 1:12)
56
+colnames(mat2) = paste0("C", 1:10)
51 57
 
52
-ht1 = Heatmap(mat, name = "ht1")
53
-ht2 = Heatmap(mat, name = "ht2")
58
+ht1 = Heatmap(mat1, name = "ht1")
59
+ht2 = Heatmap(mat2, name = "ht2")
54 60
 class(ht1)
55 61
 class(ht2)
56 62
 
... ...
@@ -61,7 +67,7 @@ Under default mode, dendrograms from the second heatmap will be removed and row
61 67
 
62 68
 The returned value of addition of two heatmaps is a `HeatmapList` object. Directly calling `ht_list` object
63 69
 will call `draw()` method with default settings. With explicitly calling `draw()` method, you can have more controls
64
-on the legend and titles.
70
+e.g. on the legend and titles.
65 71
 
66 72
 ```{r}
67 73
 ht_list = ht1 + ht2
... ...
@@ -91,8 +97,8 @@ for(s in sth) {
91 97
 A heatmap list also has titles which are independent to the heatmap titles.
92 98
 
93 99
 ```{r heatmap_list_title, fig.width = 10}
94
-ht1 = Heatmap(mat, name = "ht1", row_title = "Heatmap 1", column_title = "Heatmap 1")
95
-ht2 = Heatmap(mat, name = "ht2", row_title = "Heatmap 2", column_title = "Heatmap 2")
100
+ht1 = Heatmap(mat1, name = "ht1", row_title = "Heatmap 1", column_title = "Heatmap 1")
101
+ht2 = Heatmap(mat2, name = "ht2", row_title = "Heatmap 2", column_title = "Heatmap 2")
96 102
 ht_list = ht1 + ht2
97 103
 
98 104
 draw(ht_list, row_title = "Two heatmaps, row title", row_title_gp = gpar(col = "red"),
... ...
@@ -113,8 +119,8 @@ draw(ht_list + ht_list, gap = unit(c(3, 6, 9, 0), "mm"))
113 119
 The width for some (not all) heatmaps can be set to a fixed width.
114 120
 
115 121
 ```{r heatmap_list_size, fig.width = 10, fig.keep = "all"}
116
-ht1 = Heatmap(mat, name = "ht1", column_title = "Heatmap 1")
117
-ht2 = Heatmap(mat, name = "ht2", column_title = "Heatmap 2", width = unit(5, "cm"))
122
+ht1 = Heatmap(mat1, name = "ht1", column_title = "Heatmap 1")
123
+ht2 = Heatmap(mat2, name = "ht2", column_title = "Heatmap 2", width = unit(5, "cm"))
118 124
 ht1 + ht2
119 125
 ```
120 126
 
... ...
@@ -122,8 +128,8 @@ or the width can be set as relative values. Please not in this case, `width` for
122 128
 should be set (relative width and fixed width can be mixed).
123 129
 
124 130
 ```{r heatmap_list_relative_size, fig.width = 10, fig.keep = "all"}
125
-ht1 = Heatmap(mat, name = "ht1", column_title = "Heatmap 1", width = 2)
126
-ht2 = Heatmap(mat, name = "ht2", column_title = "Heatmap 2", width = 1)
131
+ht1 = Heatmap(mat1, name = "ht1", column_title = "Heatmap 1", width = 2)
132
+ht2 = Heatmap(mat2, name = "ht2", column_title = "Heatmap 2", width = 1)
127 133
 ht1 + ht2
128 134
 ```
129 135
 
... ...
@@ -141,8 +147,8 @@ The main heatmap can be specified by `main_heatmap` argument. The value can be a
141 147
 (of course, you need to set the heatmap name when you create the `Heatmap` object).
142 148
 
143 149
 ```{r heatmap_list_auto_adjust, fig.width = 10, fig.keep = "all"}
144
-ht1 = Heatmap(mat, name = "ht1", column_title = "Heatmap 1", km = 2)
145
-ht2 = Heatmap(mat, name = "ht2", column_title = "Heatmap 2")
150
+ht1 = Heatmap(mat1, name = "ht1", column_title = "Heatmap 1", km = 2)
151
+ht2 = Heatmap(mat2, name = "ht2", column_title = "Heatmap 2")
146 152
 ht1 + ht2
147 153
 
148 154
 # note we changed the order of `ht1` and `ht2`
... ...
@@ -156,8 +162,8 @@ draw(ht2 + ht1, main_heatmap = "ht1")
156 162
 If there is no row clustering in the main heatmap, all other heatmaps have no row clustering neither.
157 163
 
158 164
 ```{r heatmap_list_auto_adjust_no_row_cluster, fig.width = 10}
159
-ht1 = Heatmap(mat, name = "ht1", column_title = "Heatmap 1", cluster_rows = FALSE)
160
-ht2 = Heatmap(mat, name = "ht2", column_title = "Heatmap 2")
165
+ht1 = Heatmap(mat1, name = "ht1", column_title = "Heatmap 1", cluster_rows = FALSE)
166
+ht2 = Heatmap(mat2, name = "ht2", column_title = "Heatmap 2")
161 167
 ht1 + ht2
162 168
 ```
163 169
 
... ...
@@ -168,8 +174,8 @@ ht1 + ht2
168 174
 ```{r, fig.width = 10}
169 175
 ht_global_opt(heatmap_row_names_gp = gpar(fontface = "italic"), 
170 176
 	          heatmap_column_names_gp = gpar(fontsize = 14))
171
-ht1 = Heatmap(mat, name = "ht1", column_title = "Heatmap 1")
172
-ht2 = Heatmap(mat, name = "ht2", column_title = "Heatmap 2")
177
+ht1 = Heatmap(mat1, name = "ht1", column_title = "Heatmap 1")
178
+ht2 = Heatmap(mat2, name = "ht2", column_title = "Heatmap 2")
173 179
 ht1 + ht2
174 180
 ht_global_opt(RESET = TRUE)
175 181
 ```
... ...
@@ -208,7 +214,7 @@ column_dend(ht_list)
208 214
 
209 215
 ## Heatmap list with row annotations
210 216
 
211
-Row annotations can also be reordered and split according to the main heatmap, 
217
+Row annotations can be added to the heatmap list, 
212 218
 please see [**Heatmap Annotation**](s4.heatmap_annotation.html) for more explanations.
213 219
 
214 220
 ## Modify row orders/clustering in main heatmap
... ...
@@ -218,11 +224,7 @@ in `draw()` method. This makes it convinient to switch main heatmaps without mod
218 224
 heatmaps. Actually settings specified in `draw()` will overwrite corresponding settings in the main heatmap.
219 225
 
220 226
 ```{r, fig.width = 8}
221
-mat1 = matrix(rnorm(80, 2), 8, 10)
222
-mat1 = rbind(mat1, matrix(rnorm(40, -2), 4, 10))
223
-mat2 = mat1[sample(1:nrow(mat1)), ]
224
-
225
-split = sample(c("a", "b"), nrow(mat1), replace = TRUE)
227
+split = rep(c("a", "b"), each = 6)
226 228
 ht_list = Heatmap(mat1, name = "mat1", cluster_rows = FALSE, column_title = "mat1") + 
227 229
           Heatmap(mat2, name = "mat2", cluster_rows = FALSE, column_title = "mat2")
228 230
 draw(ht_list, main_heatmap = "mat1", split = split)
... ...
@@ -45,7 +45,7 @@ color mapping functions, depending on whether the simple annotations are discret
45 45
 In the heatmap, simple annotations will be represented as rows of grids.
46 46
 
47 47
 There is a `draw()` method for the `HeatmapAnnotation` class. `draw()` is used internally and here
48
-we just use it for illustration.
48
+we just use it for demonstration.
49 49
 
50 50
 ```{r heatmap_annotation, fig.width = 7, fig.height = 0.5}
51 51
 library(ComplexHeatmap)
... ...
@@ -103,7 +103,7 @@ ha
103 103
 draw(ha, 1:10)
104 104
 ```
105 105
 
106
-Also individual annotations can be specified as vectors:
106
+Also individual annotations can be directly specified as vectors:
107 107
 
108 108
 ```{r heatmap_annotation_vector, fig.width = 7, fig.height = 1}
109 109
 ha = HeatmapAnnotation(type = c(rep("a", 5), rep("b", 5)),
... ...
@@ -367,7 +367,7 @@ The order of elements in row annotations will be adjusted by the clustering of h
367 367
 ha = rowAnnotation(df = df, col = list(type = c("a" = "red", "b" = "blue")),
368 368
     width = unit(1, "cm"))
369 369
 ht1 = Heatmap(mat, name = "ht1")
370
-ht1 = Heatmap(mat, name = "ht2")
370
+ht2 = Heatmap(mat, name = "ht2")
371 371
 ht1 + ha + ht2
372 372
 ```
373 373
 
... ...
@@ -378,7 +378,7 @@ splitted as well.
378 378
 ht1 = Heatmap(mat, name = "ht1", km = 2)
379 379
 ha = rowAnnotation(df = df, col = list(type = c("a" = "red", "b" = "blue")),
380 380
     boxplot = row_anno_boxplot(mat, axis = TRUE), 
381
-    width = unit(6, "cm"))
381
+    annotation_width = unit(c(1, 5), "cm"))
382 382
 ha + ht1
383 383
 ```
384 384
 
... ...
@@ -544,6 +544,43 @@ draw(ht_list, column_title = "reverse axis direction", newpage = FALSE)
544 544
 upViewport(2)
545 545
 ```
546 546
 
547
+## Add annotation names
548
+
549
+From version 1.11.5, `HeatmapAnnotation()` supports adding annotation names directly to the annotations.
550
+However, due to the design of the package, sometimes the names will be positioned outside of the plot
551
+or overlap to other heatmap compoments, thus, by default it is turned off.
552
+
553
+```{r}
554
+df = data.frame(type = c(rep("a", 5), rep("b", 5)),
555
+                age = sample(1:20, 10))
556
+value = rnorm(10)
557
+ha = HeatmapAnnotation(df = df, points = anno_points(value, axis = TRUE),
558
+    col = list(type = c("a" = "red", "b" = "blue"),
559
+               age = colorRamp2(c(0, 20), c("white", "red"))),
560
+    annotation_height = unit(c(0.5, 0.5, 2), "cm"),
561
+    show_annotation_name = TRUE,
562
+    annotation_name_offset = unit(2, "mm"),
563
+    annotation_name_rot = c(0, 0, 90))
564
+Heatmap(mat, name = "foo", top_annotation = ha)
565
+```
566
+
567
+Or the row annotation names: Note we manually adjust `padding` to fully show the text of "points".
568
+
569
+```{r}
570
+df = data.frame(type = c(rep("a", 6), rep("b", 6)),
571
+                age = sample(1:20, 12))
572
+value = rnorm(12)
573
+ha = rowAnnotation(df = df, points = row_anno_points(value, axis = TRUE),
574
+    col = list(type = c("a" = "red", "b" = "blue"),
575
+               age = colorRamp2(c(0, 20), c("white", "red"))),
576
+    annotation_width = unit(c(0.5, 0.5, 2), "cm"),
577
+    show_annotation_name = c(TRUE, FALSE, TRUE),
578
+    annotation_name_offset = unit(c(2, 2, 8), "mm"),
579
+    annotation_name_rot = c(90, 90, 0))
580
+ht = Heatmap(mat, name = "foo") + ha
581
+draw(ht, padding = unit(c(4, 2, 2, 2), "mm"))
582
+```
583
+
547 584
 ## Adjust positions of column names
548 585
 
549 586
 In the layout of the heatmap components, column names are put directly below the heatmap body. This will cause
... ...
@@ -119,7 +119,8 @@ ha = HeatmapAnnotation(df = df, col = list(type = c("a" =  "red", "b" = "blue"))
119 119
                                                labels_gp = gpar(fontsize = 8))))
120 120
 ht1 = Heatmap(mat, name = "ht1", column_title = "Heatmap 1", top_annotation = ha)
121 121
 ht2 = Heatmap(mat, name = "ht2", column_title = "Heatmap 2", 
122
-    heatmap_legend_param = list(title = "Heatmap2", title_gp = gpar(fontsize = 8), labels_gp = gpar(fontsize = 14)))
122
+    heatmap_legend_param = list(title = "Heatmap2", title_gp = gpar(fontsize = 8), 
123
+        labels_gp = gpar(fontsize = 14)))
123 124
 ht1 + ht2
124 125
 ```
125 126
 
... ...
@@ -146,6 +147,16 @@ ht1 = Heatmap(mat, name = "ht1")
146 147
 ht1 + ha_chr
147 148
 ```
148 149
 
150
+Or put at bottom of the heatmap:
151
+
152
+```{r, fig.width = 6}
153
+ha_chr = rowAnnotation(chr = sample(paste0("chr", 1:20), nrow(mat), replace = TRUE),
154
+    annotation_legend_param = list(chr = list(nrow = 2, title = "chr", title_position = "leftcenter")),
155
+    width = unit(5, "mm"))
156
+ht1 = Heatmap(mat, name = "ht1", show_heatmap_legend = FALSE)
157
+draw(ht1 + ha_chr, heatmap_legend_side = "bottom")
158
+```
159
+
149 160
 If you don't like the default discrete color bar for continuous values, you can specify `color_bar` to `continuous`.
150 161
 For the simple annotation which contains continuous values, `color_bar` can also be set to `continuous`.
151 162
 
... ...
@@ -206,6 +217,8 @@ lgd = Legend(at = c("class1", "class2"), title = "points", type = "points", lege
206 217
 draw(ht, annotation_legend_list = list(lgd))
207 218
 ```
208 219
 
220
+Also check [this blog link](http://zuguang.de/blog/html/dde69a9cf5a606a9486b19eb91ba6f4e.html) for more demonstrations.
221
+
209 222
 ## Session info
210 223
 
211 224
 ```{r}
... ...
@@ -165,7 +165,8 @@ can be used in the decoration code.
165 165
 
166 166
 By default, annotation names are not plotted along with the heatmap annotations. The reason is
167 167
 if annotation names is plotted, they will located in the area of other heatmap components which
168
-would makes the adjustment of the heatmap layout difficult. But since you can go to any component 
168
+would makes the adjustment of the heatmap layout difficult. `HeatmapAnnotation()` provides a 
169
+not-so-perfect [solution](s4.heatmap_annotation.html#toc_11) for adding annotation names, however, since you can go to any component 
169 170
 in the heatmap list by its name, actually it is not difficult to add annotation names manually.
170 171
 
171 172
 Following code add annotation names on the both sides of the column annotations. The drawback is
... ...
@@ -37,6 +37,8 @@ additional barplots at both sides of the heatmap which show numbers of different
37 37
 each sample and for each gene. Also with the functionality of **ComplexHeatmap**, you can control oncoPrint with
38 38
 more flexibilities.
39 39
 
40
+## General settings
41
+
40 42
 There are two different forms of input data. The first is represented as a matrix in which 
41 43
 element would include multiple alterations in a form of a complex string. In follow example,
42 44
 'g1' in 's1' has two types of alterations which are 'snv' and 'indel'.
... ...
@@ -78,7 +80,10 @@ oncoPrint(mat, get_type = function(x) strsplit(x, ";")[[1]],
78 80
 	), col = col)
79 81
 ```
80 82
 
81
-The second type of input data is a list of matrix for which each matrix contains binary value representing
83
+In above example, form of the string (e.g. `snv;indel`) correlates to how you define `get_type`. If the string
84
+has the form of `snv|indel|amp`, `get_type` should be defined as `function(x) strsplit(x, "|")[[1]]`.
85
+
86
+If you are pulzzed by how to generated the matrix, there is a second way. The second type of input data is a list of matrix for which each matrix contains binary value representing
82 87
 whether the alteration is absent or present. The list should have names which correspond to the alteration
83 88
 types.
84 89
 
... ...
@@ -100,30 +105,27 @@ mat_list = unify_mat_list(mat_list)
100 105
 mat_list
101 106
 ```
102 107
 
103
-Same as the first example, but here we also define `background` in `alter_fun` argument. This function defines
104
-how to add graphics when there is no alteration and it is always put as the first in the list.
108
+Pass `mat_list` to `oncoPrint()`:
105 109
 
106 110
 ```{r}
107 111
 oncoPrint(mat_list,
108 112
 	alter_fun = list(
109
-		background = function(x, y, w, h) NULL,
110 113
 		snv = function(x, y, w, h) grid.rect(x, y, w*0.9, h*0.9, gp = gpar(fill = col["snv"], col = NA)),
111 114
 		indel = function(x, y, w, h) grid.rect(x, y, w*0.9, h*0.4, gp = gpar(fill = col["indel"], col = NA))
112 115
 	), col = col)
113 116
 ```
114 117
 
115
-If types of alterations is less than two and the purpose is only to have a quick look at the data, there are default
116
-graphics added:
117
-
118
-```{r}
119
-oncoPrint(mat_list)
120
-```
121
-
122 118
 In above examples, `alter_fun` is a list of functons which add graphics layer by layer. Graphics
123 119
 can also be added in a grid-by-grid style by specifying `alter_fun` as a single function. The difference
124 120
 from the function list is now `alter_fun` should accept a fifth argument which is a logical vector. 
125 121
 This logical vector shows whether different alterations exist for current gene in current sample.
126 122
 
123
+Let's assume in a grid there is only snv event, `v` for this grid is:
124
+
125
+```{r, echo = FALSE}
126
+print(c("snv" = TRUE, "indel" = FALSE))
127
+```
128
+
127 129
 ```{r}
128 130
 oncoPrint(mat_list,
129 131
 	alter_fun = function(x, y, w, h, v) {
... ...
@@ -146,6 +148,32 @@ oncoPrint(mat_list,
146 148
     }, col = col)
147 149
 ```
148 150
 
151
+If `alter_fun` is specified as a list, the order of the elements controls the order of adding graphics. 
152
+There is a special element named `background` which defines how to draw background and it should be always put
153
+as the first element in the `alter_fun` list. In following example, backgrond color is changed to light green with borders.
154
+
155
+```{r}
156
+oncoPrint(mat_list,
157
+	alter_fun = list(
158
+		background = function(x, y, w, h) grid.rect(x, y, w, h, gp = gpar(fill = "#00FF0020")),
159
+		snv = function(x, y, w, h) grid.rect(x, y, w*0.9, h*0.9, gp = gpar(fill = col["snv"], col = NA)),
160
+		indel = function(x, y, w, h) grid.rect(x, y, w*0.9, h*0.4, gp = gpar(fill = col["indel"], col = NA))
161
+	), col = col)
162
+```
163
+
164
+Or just remove the background:
165
+
166
+```{r}
167
+oncoPrint(mat_list,
168
+	alter_fun = list(
169
+		background = NULL,
170
+		snv = function(x, y, w, h) grid.rect(x, y, w*0.9, h*0.9, gp = gpar(fill = col["snv"], col = NA)),
171
+		indel = function(x, y, w, h) grid.rect(x, y, w*0.9, h*0.4, gp = gpar(fill = col["indel"], col = NA))
172
+	), col = col)
173
+```
174
+
175
+## Apply to cBioPortal dataset
176
+
149 177
 Now we make an oncoPrint with a real-world data. The data is retrieved from [cBioPortal](http://www.cbioportal.org/). 
150 178
 Steps for getting the data are as follows:
151 179
 
... ...
@@ -264,7 +292,7 @@ ht_list = oncoPrint(mat, get_type = function(x) strsplit(x, ";")[[1]],
264 292
 	heatmap_legend_param = list(title = "Alternations", at = c("AMP", "HOMDEL", "MUT"), 
265 293
 		labels = c("Amplification", "Deep deletion", "Mutation")),
266 294
 	split = sample(letters[1:2], nrow(mat), replace = TRUE)) +
267
-Heatmap(matrix(rnorm(nrow(mat)*10), ncol = 10), name = "expr", width = unit(4, "cm"))
295
+Heatmap(matrix(rnorm(nrow(mat)*10), ncol = 10), name = "expr", show_column_dend = FALSE, width = unit(4, "cm"))
268 296
 draw(ht_list, row_sub_title_side = "left")
269 297
 ```
270 298
 
... ...
@@ -28,6 +28,11 @@ options(markdown.HTML.stylesheet = "custom.css")
28 28
 options(width = 100)
29 29
 ```
30 30
 
31
+In the supplementaries of [the ComplexHeatmap paper](http://bioinformatics.oxfordjournals.org/content/early/2016/05/20/bioinformatics.btw313.abstract), there are four comprehensive examples which are applied
32
+on real-world high-throughput datasets. [The examples can be found here.](http://jokergoo.github.io/supplementary/ComplexHeatmap-supplementary1-4/index.html)
33
+
34
+Also [my blog](http://jokergoo.github.io/blog.html) has some examples and tips for making better complex heatmaps.
35
+
31 36
 
32 37
 ### Add more information for gene expression matrix
33 38