Browse code

backup

Zuguang Gu authored on 10/09/2018 10:14:12
Showing11 changed files

... ...
@@ -4,6 +4,7 @@ setGeneric('add_heatmap', function(object, ...) standardGeneric('add_heatmap'))
4 4
 setGeneric('map_to_colors', function(object, ...) standardGeneric('map_to_colors'))
5 5
 
6 6
 setGeneric('set_component_height', function(object, ...) standardGeneric('set_component_height'))
7
+setGeneric('set_component_width', function(object, ...) standardGeneric('set_component_width'))
7 8
 
8 9
 setGeneric('draw_heatmap_body', function(object, ...) standardGeneric('draw_heatmap_body'))
9 10
 
... ...
@@ -72,3 +72,27 @@ AdditiveUnit = function(...) {
72 72
         add_heatmap(x, y)
73 73
     }
74 74
 }
75
+
76
+
77
+"%v%" = function(x, y) {
78
+    if(inherits(x, "HeatmapAnnotation")) {
79
+        if(x@which != "column") {
80
+            stop("You should specify `which` to `column` or use `columnAnnotation()` directly if you want to add column annotations vertically.")
81
+        }
82
+    }
83
+    if(inherits(y, "HeatmapAnnotation")) {
84
+        if(y@which != "column") {
85
+            stop("You should specify `which` to `column` or use `columnAnnotation()` directly if you want to add column annotations vertically.")
86
+        }
87
+    }
88
+    if(is.null(x)) {
89
+        ht_list = new("HeatmapList")
90
+        add_heatmap(ht_list, y, direction = "vertical")
91
+    } else if(is.null(y)) {
92
+        ht_list = new("HeatmapList")
93
+        add_heatmap(ht_list, x, direction = "vertical")
94
+    } else {
95
+        add_heatmap(x, y, direction = "vertical")
96
+    }
97
+}
98
+
... ...
@@ -89,6 +89,9 @@ anno_width_and_height = function(which, width = NULL, height = NULL,
89 89
 #
90 90
 # == details
91 91
 # The AnnotationFunction class is a wrapper of the function which draws heatmap annotation.
92
+#
93
+# If the annotation function is subsetable, the annotation graphics can be split by rows or by columns
94
+# according to the split of the heatmap.
92 95
 AnnotationFunction = function(fun, fun_name = "", which = c("column", "row"), 
93 96
 	var_imported = list(), n = 0, data_scale = c(0, 1), subset_rule = list(), 
94 97
 	subsetable = FALSE, width = NULL, height = NULL) {
... ...
@@ -167,7 +170,7 @@ AnnotationFunction = function(fun, fun_name = "", which = c("column", "row"),
167 170
 #
168 171
 # == param
169 172
 # -x An `AnnotationFunction-class` object.
170
-# -i Index
173
+# -i A vector of indices.
171 174
 #
172 175
 # == details
173 176
 # One good thing for designing the `AnnotationFunction-class` can be subsetted.
... ...
@@ -238,6 +241,7 @@ setMethod(f = "draw",
238 241
 
239 242
     # names should be passed to the data viewport
240 243
 	pushViewport(viewport(width = anno_width, height = anno_height))
244
+	vp_name1 = current.viewport()$name
241 245
 	object@fun(index)
242 246
 	if(test2) {
243 247
 		grid.text(test, y = unit(1, "npc") + unit(2, "mm"), just = "bottom")
... ...
@@ -257,6 +261,10 @@ setMethod(f = "draw",
257 261
 		}
258 262
 		
259 263
 	}
264
+	vp_name2 = current.viewport()$name
265
+	if(vp_name1 != vp_name2) {
266
+		stop("Viewports are not the same before and after plotting the annotation graphics.")
267
+	}
260 268
 	popViewport()
261 269
 
262 270
 	if(test2) {
... ...
@@ -4,7 +4,7 @@
4 4
 #
5 5
 
6 6
 # == title
7
-# Class to map values to colors
7
+# Class for Mapping Values to Colors
8 8
 #
9 9
 # == details
10 10
 # The `ColorMapping-class` handles color mapping with both discrete values and continuous values.
... ...
@@ -33,17 +33,17 @@ ColorMapping = setClass("ColorMapping",
33 33
 )
34 34
 
35 35
 # == title
36
-# Constructor methods for ColorMapping class
36
+# Constructor Method for ColorMapping Class
37 37
 #
38 38
 # == param
39
-# -name name for this color mapping. The name is automatically generated if it is not specified.
40
-# -colors discrete colors.
41
-# -levels levels that correspond to ``colors``. If ``colors`` is name indexed,
39
+# -name Name for this color mapping. The name is automatically generated if it is not specified.
40
+# -colors Discrete colors.
41
+# -levels Levels that correspond to ``colors``. If ``colors`` is name indexed,
42 42
 #         ``levels`` can be ignored.
43
-# -col_fun color mapping function that maps continuous values to colors.
44
-# -breaks breaks for the continuous color mapping. If ``col_fun`` is
43
+# -col_fun Color mapping function that maps continuous values to colors.
44
+# -breaks Breaks for the continuous color mapping. If ``col_fun`` is
45 45
 #         generated by `circlize::colorRamp2`, ``breaks`` can be ignored.
46
-# -na_col colors for ``NA`` values.
46
+# -na_col Colors for ``NA`` values.
47 47
 #
48 48
 # == detail
49 49
 # ``colors`` and ``levels`` are used for discrete color mapping, ``col_fun`` and
... ...
@@ -118,10 +118,10 @@ ColorMapping = function(name, colors = NULL, levels = NULL,
118 118
 }
119 119
 
120 120
 # == title
121
-# Print ColorMapping object
121
+# Print ColorMapping Object
122 122
 #
123 123
 # == param
124
-# -object a `ColorMapping-class` object.
124
+# -object A `ColorMapping-class` object.
125 125
 #
126 126
 # == value
127 127
 # This function returns no value.
... ...
@@ -156,11 +156,11 @@ setMethod(f = "show",
156 156
 })
157 157
 
158 158
 # == title
159
-# Map values to colors
159
+# Map Values to Colors
160 160
 #
161 161
 # == param
162
-# -object a `ColorMapping-class` object.
163
-# -x input values.
162
+# -object A `ColorMapping-class` object.
163
+# -x Input values.
164 164
 #
165 165
 # == details
166 166
 # It maps a vector of values to a vector of colors.
... ...
@@ -204,27 +204,27 @@ setMethod(f = "map_to_colors",
204 204
 
205 205
 
206 206
 # == title
207
-# Draw legend based on color mapping
207
+# Draw Legend Based on Color Mapping
208 208
 #
209 209
 # == param
210
-# -object a `ColorMapping-class` object.
211
-# -plot whether to plot or just return the size of the legend viewport.
212
-# -title title of the legend, by default it is the name of the legend
213
-# -title_gp graphical parameters for legend title
214
-# -title_position position of the title
215
-# -color_bar a string of "continous" or "discrete". If the mapping is continuous, whether show the legend as discrete color bar or continuous color bar
216
-# -grid_height height of each legend grid.
217
-# -grid_width width of each legend grid.
218
-# -border color for legend grid borders.
219
-# -at break values of the legend
220
-# -labels labels corresponding to break values
221
-# -labels_gp graphcial parameters for legend labels
222
-# -nrow if there are too many legend grids, they can be put as an array, this controls number of rows
223
-# -ncol if there are too many legend grids, they can be put as an array, this controls number of columns
224
-# -by_row when there are multiple columns for legends, whether to arrange them by rows.
225
-# -legend_height height of the legend, only works when ``color_bar`` is ``continuous`` and ``direction`` is ``vertical``
226
-# -legend_width width of the legend, only works when ``color_bar`` is ``continuous`` and ``direction`` is ``horizontal``
227
-# -legend_direction when ``color_bar`` is ``continuous``, should the legend be vertical or horizontal? When ``color_bar`` is ``discrete``, should the items in the legend proceed vertically or horizontally?
210
+# -object A `ColorMapping-class` object.
211
+# -plot Whether to plot or just return legend object?
212
+# -title Title of the legend, by default it is the name of the legend
213
+# -title_gp Traphical parameters for legend title
214
+# -title_position Position of the title
215
+# -color_bar A string of "continous" or "discrete". If the mapping is continuous, whether show the legend as discrete color bar or continuous color bar
216
+# -grid_height Height of each legend grid.
217
+# -grid_width Width of each legend grid.
218
+# -border Color for legend grid borders.
219
+# -at Break values of the legend
220
+# -labels Labels corresponding to break values
221
+# -labels_gp Graphcial parameters for legend labels
222
+# -nrow If there are too many legend grids, they can be put as an array, this controls number of rows
223
+# -ncol If there are too many legend grids, they can be put as an array, this controls number of columns
224
+# -by_row When there are multiple columns for legends, whether to arrange them by rows.
225
+# -legend_height Height of the legend, only works when ``color_bar`` is ``continuous`` and ``direction`` is ``vertical``
226
+# -legend_width Width of the legend, only works when ``color_bar`` is ``continuous`` and ``direction`` is ``horizontal``
227
+# -legend_direction When ``color_bar`` is ``continuous``, should the legend be vertical or horizontal? When ``color_bar`` is ``discrete``, should the items in the legend proceed vertically or horizontally?
228 228
 # -param will be parsed if the parameters are specified as a list
229 229
 # -... pass to `grid::viewport`.
230 230
 #
... ...
@@ -97,6 +97,10 @@ Heatmap = setClass("Heatmap",
97 97
         top_annotation_param = "list",
98 98
         bottom_annotation = "ANY",
99 99
         bottom_annotation_param = "list",
100
+        left_annotation = "ANY", # NULL or a `HeatmapAnnotation` object
101
+        left_annotation_param = "list",
102
+        right_annotation = "ANY",
103
+        right_annotation_param = "list",
100 104
 
101 105
         heatmap_param = "list",
102 106
 
... ...
@@ -121,6 +125,7 @@ Heatmap = setClass("Heatmap",
121 125
 # -rect_gp graphic parameters for drawing rectangles (for heatmap body).
122 126
 # -color_space the color space in which colors are interpolated. Only used if ``matrix`` is numeric and 
123 127
 #            ``col`` is a vector of colors. Pass to `circlize::colorRamp2`.
128
+# -border
124 129
 # -cell_fun self-defined function to add graphics on each cell. Seven parameters will be passed into 
125 130
 #           this function: ``i``, ``j``, ``x``, ``y``, ``width``, ``height``, ``fill`` which are row index,
126 131
 #           column index in ``matrix``, coordinate of the middle points in the heatmap body viewport,
... ...
@@ -152,11 +157,7 @@ Heatmap = setClass("Heatmap",
152 157
 #                object with edges rendered, this argument will be ignored.
153 158
 # -row_dend_reorder apply reordering on rows. The value can be a logical value or a vector which contains weight 
154 159
 #               which is used to reorder rows
155
-# -row_hclust_side deprecated, use ``row_dend_side`` instead
156
-# -row_hclust_width deprecated, use ``row_dend_width`` instead
157
-# -show_row_hclust deprecated, use ``show_row_dend`` instead
158
-# -row_hclust_gp deprecated, use ``row_dend_gp`` instead
159
-# -row_hclust_reorder deprecated, use ``row_dend_reorder`` instead
160
+# -row_dend_gp
160 161
 # -cluster_columns whether make cluster on columns. Same settings as ``cluster_rows``.
161 162
 # -clustering_distance_columns same setting as ``clustering_distance_rows``.
162 163
 # -clustering_method_columns method to make cluster, pass to `stats::hclust`.
... ...
@@ -166,38 +167,43 @@ Heatmap = setClass("Heatmap",
166 167
 # -column_dend_gp graphic parameters for drawling lines. Same settings as ``row_dend_gp``.
167 168
 # -column_dend_reorder apply reordering on columns. The value can be a logical value or a vector which contains weight 
168 169
 #               which is used to reorder columns
169
-# -column_hclust_side deprecated, use ``column_dend_side`` instead
170
-# -column_hclust_height deprecated, use ``column_dend_height`` instead
171
-# -show_column_hclust deprecated, use ``show_column_dend`` instead
172
-# -column_hclust_gp deprecated, use ``column_dend_gp`` instead
173
-# -column_hclust_reorder deprecated, use ``column_dend_reorder`` instead
170
+# -column_dend_gp
174 171
 # -row_order order of rows. It makes it easy to adjust row order for a list of heatmaps if this heatmap 
175 172
 #      is selected as the main heatmap. Manually setting row order should turn off clustering
176 173
 # -column_order order of column. It makes it easy to adjust column order for both matrix and column annotations.
174
+# -row_labels
177 175
 # -row_names_side should the row names be put on the left or right of the heatmap?
178 176
 # -show_row_names whether show row names.
179 177
 # -row_names_max_width maximum width of row names viewport. Because some times row names can be very long, it is not reasonable
180 178
 #                      to show them all.
181 179
 # -row_names_gp graphic parameters for drawing text.
180
+# -row_names_rot
181
+# -column_labels
182 182
 # -column_names_side should the column names be put on the top or bottom of the heatmap?
183 183
 # -column_names_max_height maximum height of column names viewport.
184 184
 # -show_column_names whether show column names.
185 185
 # -column_names_gp graphic parameters for drawing text.
186
+# -column_names_rot
186 187
 # -top_annotation a `HeatmapAnnotation` object which contains a list of annotations.
187
-# -top_annotation_height total height of the column annotations on the top.
188 188
 # -bottom_annotation a `HeatmapAnnotation` object.
189
-# -bottom_annotation_height total height of the column annotations on the bottom.
189
+# -left_annotation
190
+# -right_annotation
190 191
 # -km do k-means clustering on rows. If the value is larger than 1, the heatmap will be split by rows according to the k-means clustering.
191 192
 #     For each row-clusters, hierarchical clustering is still applied with parameters above.
192
-# -km_title row title for each cluster when ``km`` is set. It must a text with format of ".*\%i.*" where "\%i" is replaced by the index of the cluster.
193 193
 # -split a vector or a data frame by which the rows are split. But if ``cluster_rows`` is a clustering object, ``split`` can be a single number
194 194
 #        indicating rows are to be split according to the split on the tree.
195
+# -row_km
196
+# -row_split
197
+# -column_km
198
+# -column_split
195 199
 # -gap gap between row-slices if the heatmap is split by rows, should be `grid::unit` object. If it is a vector, the order corresponds
196 200
 #   to top to bottom in the heatmap
197
-# -combined_name_fun if the heatmap is split by rows, how to make a combined row title for each slice?
198
-#                 The input parameter for this function is a vector which contains level names under each column in ``split``.
199
-# -width the width of the single heatmap, should be a fixed `grid::unit` object. It is used for the layout when the heatmap
200
-#        is appended to a list of heatmaps.
201
+# -row_gap
202
+# -column_gap
203
+# -width
204
+# -height
205
+# -heatmap_body_width
206
+# -heatmap_body_height
201 207
 # -show_heatmap_legend whether show heatmap legend?
202 208
 # -heatmap_legend_param a list contains parameters for the heatmap legend. See `color_mapping_legend,ColorMapping-method` for all available parameters.
203 209
 # -use_raster whether render the heatmap body as a raster image. It helps to reduce file size when the matrix is huge. Note if ``cell_fun``
... ...
@@ -276,6 +282,8 @@ Heatmap = function(matrix, col, name,
276 282
 
277 283
     top_annotation = NULL,
278 284
     bottom_annotation = NULL,
285
+    left_annotation = NULL,
286
+    right_annotation = NULL,
279 287
 
280 288
     km = 1, 
281 289
     split = NULL, 
... ...
@@ -699,6 +707,46 @@ Heatmap = function(matrix, col, name,
699 707
         }
700 708
     }
701 709
 
710
+    .Object@left_annotation = left_annotation # a `rowAnnotation` object
711
+    if(is.null(left_annotation)) {
712
+        .Object@left_annotation_param$width = unit(0, "mm")
713
+    } else {
714
+        .Object@left_annotation_param$width = width(left_annotation) + ROW_ANNO_PADDING*2  # append the gap
715
+    }
716
+    if(!is.null(left_annotation)) {
717
+        if(length(left_annotation) > 0) {
718
+            if(!.Object@left_annotation@which == "row") {
719
+                stop("`which` in `left_annotation` should only be `row`, or consider using `rowAnnotation()`.")
720
+            }
721
+        }
722
+        nb = nobs(left_annotation)
723
+        if(!is.na(nb)) {
724
+            if(nb != ncol(.Object@matrix)) {
725
+                stop("number of items in left anntotion should be same as number of columns of the matrix.")
726
+            }
727
+        }
728
+    }
729
+
730
+    .Object@right_annotation = right_annotation # a `rowAnnotation` object
731
+    if(is.null(right_annotation)) {
732
+        .Object@right_annotation_param$width = unit(0, "mm")
733
+    } else {
734
+        .Object@right_annotation_param$width = width(right_annotation) + ROW_ANNO_PADDING*2  # append the gap
735
+    }
736
+    if(!is.null(right_annotation)) {
737
+        if(length(right_annotation) > 0) {
738
+            if(!.Object@right_annotation@which == "row") {
739
+                stop("`which` in `right_annotation` should only be `row`, or consider using `rowAnnotation()`.")
740
+            }
741
+        }
742
+        nb = nobs(right_annotation)
743
+        if(!is.na(nb)) {
744
+            if(nb != ncol(.Object@matrix)) {
745
+                stop("number of items in left anntotion should be same as number of columns of the matrix.")
746
+            }
747
+        }
748
+    }
749
+
702 750
     .Object@layout = list(
703 751
         layout_size = list(
704 752
             column_title_top_height = unit(0, "mm"),
... ...
@@ -715,10 +763,12 @@ Heatmap = function(matrix, col, name,
715 763
             row_names_left_width = unit(0, "mm"),
716 764
             row_dend_right_width = unit(0, "mm"),
717 765
             row_names_right_width = unit(0, "mm"),
718
-            row_title_right_width = unit(0, "mm")
766
+            row_title_right_width = unit(0, "mm"),
767
+            row_anno_left_width = unit(0, "mm"),
768
+            row_anno_right_width = unit(0, "mm")
719 769
         ),
720 770
 
721
-        layout_index = data.frame(),
771
+        layout_index = NULL,
722 772
         graphic_fun_list = list()
723 773
     )
724 774
 
... ...
@@ -737,10 +787,10 @@ Heatmap = function(matrix, col, name,
737 787
 
738 788
 
739 789
 # == title
740
-# Make cluster on rows
790
+# Make Cluster on Rows
741 791
 #
742 792
 # == param
743
-# -object a `Heatmap-class` object.
793
+# -object A `Heatmap-class` object.
744 794
 #
745 795
 # == details
746 796
 # The function will fill or adjust ``row_dend_list``, ``row_order_list``, ``row_title`` and ``matrix_param`` slots.
... ...
@@ -1185,16 +1235,16 @@ make_cluster = function(object, which = c("row", "column")) {
1185 1235
 }
1186 1236
 
1187 1237
 # == title
1188
-# Make the layout of a single heatmap
1238
+# Make the Layout of a Single Heatmap
1189 1239
 #
1190 1240
 # == param
1191
-# -object a `Heatmap-class` object.
1241
+# -object A `Heatmap-class` object.
1192 1242
 # 
1193 1243
 # == detail
1194 1244
 # The layout of the single heatmap will be established by setting the size of each heatmap components.
1195
-# Also functions that make graphics for heatmap components will be recorded.
1245
+# Also functions that make graphics for heatmap components will be recorded by saving as functions.
1196 1246
 #
1197
-# Whether apply row clustering or column clustering affects the layout, so clustering should be applied 
1247
+# Whether to apply row clustering or column clustering affects the layout, so clustering should be applied 
1198 1248
 # first before making the layout.
1199 1249
 #
1200 1250
 # This function is only for internal use.
... ...
@@ -1254,7 +1304,7 @@ setMethod(f = "make_layout",
1254 1304
         
1255 1305
         ###########################################
1256 1306
         ## heatmap body
1257
-        object@layout$layout_index = rbind(c(5, 4))
1307
+        object@layout$layout_index = rbind(heatmapb_body = heatmap_layout_index("heatmap_body"))
1258 1308
         object@layout$graphic_fun_list = list(function(object) {
1259 1309
             for(i in seq_len(nr_slice)) {
1260 1310
                 for(j in seq_len(nc_slice)) {
... ...
@@ -1277,14 +1327,14 @@ setMethod(f = "make_layout",
1277 1327
             } else {
1278 1328
                 object@layout$layout_size$column_title_top_height = grobWidth(textGrob(column_title, gp = column_title_gp)) + TITLE_PADDING*2
1279 1329
             }
1280
-            object@layout$layout_index = rbind(object@layout$layout_index, c(1, 4))
1330
+            object@layout$layout_index = rbind(object@layout$layout_index, column_title_top = heatmap_layout_index("column_title_top"))
1281 1331
         } else {
1282 1332
             if(column_title_rot %in% c(0, 180)) {
1283 1333
                 object@layout$layout_size$column_title_bottom_height = grobHeight(textGrob(column_title, gp = column_title_gp)) + TITLE_PADDING*2
1284 1334
             } else {
1285 1335
                 object@layout$layout_size$column_title_bottom_height = grobWidth(textGrob(column_title, gp = column_title_gp)) + TITLE_PADDING*2
1286 1336
             }
1287
-            object@layout$layout_index = rbind(object@layout$layout_index, c(9, 4))
1337
+            object@layout$layout_index = rbind(object@layout$layout_index, column_title_bottom = heatmap_layout_index("column_title_bottom"))
1288 1338
         }
1289 1339
         object@layout$graphic_fun_list = c(object@layout$graphic_fun_list, function(object) {
1290 1340
             if(length(column_title) == 1 && nc_slice > 1) {
... ...
@@ -1310,14 +1360,14 @@ setMethod(f = "make_layout",
1310 1360
             } else {
1311 1361
                 object@layout$layout_size$row_title_left_width = max_text_height(row_title, gp = row_title_gp) + TITLE_PADDING*2
1312 1362
             }
1313
-            object@layout$layout_index = rbind(object@layout$layout_index, c(5, 1))
1363
+            object@layout$layout_index = rbind(object@layout$layout_index, row_title_left = heatmap_layout_index("row_title_left"))
1314 1364
         } else {
1315 1365
             if(row_title_rot %in% c(0, 180)) {
1316 1366
                 object@layout$layout_size$row_title_right_width = max_text_width(row_title, gp = row_title_gp) + TITLE_PADDING*2
1317 1367
             } else {
1318 1368
                 object@layout$layout_size$row_title_right_width = max_text_height(row_title, gp = row_title_gp) + TITLE_PADDING*2
1319 1369
             }
1320
-            object@layout$layout_index = rbind(object@layout$layout_index, c(5, 7))
1370
+            object@layout$layout_index = rbind(object@layout$layout_index, row_title_right = heatmap_layout_index("row_title_right"))
1321 1371
         }
1322 1372
         object@layout$graphic_fun_list = c(object@layout$graphic_fun_list, function(object) {
1323 1373
             if(length(row_title) == 1 && nr_slice > 1) {
... ...
@@ -1339,10 +1389,10 @@ setMethod(f = "make_layout",
1339 1389
     if(show_row_dend) {
1340 1390
         if(row_dend_side == "left") {
1341 1391
             object@layout$layout_size$row_dend_left_width = row_dend_width
1342
-            object@layout$layout_index = rbind(object@layout$layout_index, c(5, 2))
1392
+            object@layout$layout_index = rbind(object@layout$layout_index, row_dend_left = heatmap_layout_index("row_dend_left"))
1343 1393
         } else {
1344 1394
             object@layout$layout_size$row_dend_right_width = row_dend_width
1345
-            object@layout$layout_index = rbind(object@layout$layout_index, c(5, 6))
1395
+            object@layout$layout_index = rbind(object@layout$layout_index, row_dend_right = heatmap_layout_index("row_dend_right"))
1346 1396
         }
1347 1397
         row_dend_max_height = dend_heights(row_dend_slice) + max(dend_heights(object@row_dend_list))
1348 1398
         object@layout$graphic_fun_list = c(object@layout$graphic_fun_list, function(object) {
... ...
@@ -1380,10 +1430,10 @@ setMethod(f = "make_layout",
1380 1430
     if(show_column_dend) {
1381 1431
         if(column_dend_side == "top") {
1382 1432
             object@layout$layout_size$column_dend_top_height = column_dend_height
1383
-            object@layout$layout_index = rbind(object@layout$layout_index, c(2, 4))
1433
+            object@layout$layout_index = rbind(object@layout$layout_index, column_dend_top = heatmap_layout_index("column_dend_top"))
1384 1434
         } else {
1385 1435
             object@layout$layout_size$column_dend_bottom_height = column_dend_height
1386
-            object@layout$layout_index = rbind(object@layout$layout_index, c(8, 4))
1436
+            object@layout$layout_index = rbind(object@layout$layout_index, column_dend_bottom = heatmap_layout_index("column_dend_bottom"))
1387 1437
         }
1388 1438
         column_dend_max_height = dend_heights(column_dend_slice) + max(dend_heights(object@column_dend_list))
1389 1439
         object@layout$graphic_fun_list = c(object@layout$graphic_fun_list, function(object) {
... ...
@@ -1422,10 +1472,10 @@ setMethod(f = "make_layout",
1422 1472
         row_names_width = min(row_names_width, object@row_names_param$max_width)
1423 1473
         if(row_names_side == "left") {
1424 1474
             object@layout$layout_size$row_names_left_width = row_names_width
1425
-            object@layout$layout_index = rbind(object@layout$layout_index, c(5, 3))
1475
+            object@layout$layout_index = rbind(object@layout$layout_index, row_names_left = heatmap_layout_index("row_names_left"))
1426 1476
         } else {
1427 1477
             object@layout$layout_size$row_names_right_width = row_names_width
1428
-            object@layout$layout_index = rbind(object@layout$layout_index, c(5, 5))
1478
+            object@layout$layout_index = rbind(object@layout$layout_index, row_names_right = heatmap_layout_index("row_names_right"))
1429 1479
         }
1430 1480
         object@layout$graphic_fun_list = c(object@layout$graphic_fun_list, function(object) {
1431 1481
             for(i in seq_len(nr_slice)) {
... ...
@@ -1445,10 +1495,10 @@ setMethod(f = "make_layout",
1445 1495
         column_names_height = min(column_names_height, object@column_names_param$max_height)
1446 1496
         if(column_names_side == "top") {
1447 1497
             object@layout$layout_size$column_names_top_height = column_names_height
1448
-            object@layout$layout_index = rbind(object@layout$layout_index, c(3, 4))
1498
+            object@layout$layout_index = rbind(object@layout$layout_index, column_names_top = heatmap_layout_index("column_names_top"))
1449 1499
         } else {
1450 1500
             object@layout$layout_size$column_names_bottom_height = column_names_height
1451
-            object@layout$layout_index = rbind(object@layout$layout_index, c(7, 4))
1501
+            object@layout$layout_index = rbind(object@layout$layout_index, column_names_bottom = heatmap_layout_index("column_names_bottom"))
1452 1502
         }
1453 1503
         object@layout$graphic_fun_list = c(object@layout$graphic_fun_list, function(object) {
1454 1504
             for(i in seq_len(nc_slice)) {
... ...
@@ -1465,7 +1515,7 @@ setMethod(f = "make_layout",
1465 1515
     if(!is.null(annotation)) {
1466 1516
         if(length(annotation@anno_list) > 0) {
1467 1517
             object@layout$layout_size$column_anno_top_height = annotation_height
1468
-            object@layout$layout_index = rbind(object@layout$layout_index, c(4, 4))
1518
+            object@layout$layout_index = rbind(object@layout$layout_index, column_anno_top = heatmap_layout_index("column_anno_top"))
1469 1519
             
1470 1520
             object@layout$graphic_fun_list = c(object@layout$graphic_fun_list, function(object) {
1471 1521
                 for(i in seq_len(nc_slice)) {
... ...
@@ -1483,7 +1533,7 @@ setMethod(f = "make_layout",
1483 1533
     if(!is.null(annotation)) {
1484 1534
         if(length(annotation@anno_list) > 0) {
1485 1535
             object@layout$layout_size$column_anno_bottom_height = annotation_height
1486
-            object@layout$layout_index = rbind(object@layout$layout_index, c(6, 4))
1536
+            object@layout$layout_index = rbind(object@layout$layout_index, column_anno_bottom = heatmap_layout_index("column_anno_bottom"))
1487 1537
             object@layout$graphic_fun_list = c(object@layout$graphic_fun_list, function(object) {
1488 1538
                 for(i in seq_len(nc_slice)) {
1489 1539
                     draw_annotation(object, k = i, which = "bottom", x = slice_x[i], 
... ...
@@ -1493,14 +1543,51 @@ setMethod(f = "make_layout",
1493 1543
         }
1494 1544
     }
1495 1545
 
1546
+    ##########################################
1547
+    ## annotation on left
1548
+    annotation = object@left_annotation
1549
+    annotation_width = object@left_annotation_param$width
1550
+    if(!is.null(annotation)) {
1551
+        if(length(annotation@anno_list) > 0) {
1552
+            object@layout$layout_size$row_anno_left_width = annotation_width
1553
+            object@layout$layout_index = rbind(object@layout$layout_index, row_anno_left = heatmap_layout_index("row_anno_left"))
1554
+            object@layout$graphic_fun_list = c(object@layout$graphic_fun_list, function(object) {
1555
+                    for(i in seq_len(nr_slice)) {
1556
+                        draw_annotation(object, k = i, which = "left",  y = slice_y[i], 
1557
+                            height = slice_height[i], width = unit(1, "npc"), just = "top") 
1558
+                    }
1559
+                }
1560
+            )
1561
+        }
1562
+    }
1563
+
1564
+    ##########################################
1565
+    ## annotation on right
1566
+    annotation = object@right_annotation
1567
+    annotation_width = object@right_annotation_param$width
1568
+    if(!is.null(annotation)) {
1569
+        if(length(annotation@anno_list) > 0) {
1570
+            object@layout$layout_size$row_anno_right_width = annotation_width
1571
+            object@layout$layout_index = rbind(object@layout$layout_index, row_anno_right = heatmap_layout_index("row_anno_right"))
1572
+            object@layout$graphic_fun_list = c(object@layout$graphic_fun_list, function(object) {
1573
+                for(i in seq_len(nr_slice)) {
1574
+                    draw_annotation(object, k = i, which = "right", y = slice_y[i], 
1575
+                        height = slice_height[i], width = unit(1, "npc"), just = "top")
1576
+                }
1577
+            })
1578
+        }
1579
+    }
1580
+
1496 1581
     layout_size = object@layout$layout_size
1497 1582
     if(is_abs_unit(object@heatmap_param$width)) {
1498 1583
         # recalcualte the width of heatmap body
1499 1584
         object@matrix_param$width = object@heatmap_param$width -
1500 1585
             sum(layout_size$row_title_left_width,
1501 1586
                 layout_size$row_dend_left_width,
1587
+                layout_size$row_anno_left_width,
1502 1588
                 layout_size$row_names_left_width,
1503 1589
                 layout_size$row_dend_right_width,
1590
+                layout_size$row_anno_right_width,
1504 1591
                 layout_size$row_names_right_width,
1505 1592
                 layout_size$row_title_right_width)   
1506 1593
     } else if(is_abs_unit(object@matrix_param$width)) {  # e.g. unit(1, "npc")
... ...
@@ -1510,7 +1597,9 @@ setMethod(f = "make_layout",
1510 1597
             layout_size$row_names_left_width,
1511 1598
             layout_size$row_dend_right_width,
1512 1599
             layout_size$row_names_right_width,
1513
-            layout_size$row_title_right_width
1600
+            layout_size$row_title_right_width,
1601
+            layout_size$row_anno_left_width,
1602
+            layout_size$row_anno_right_width
1514 1603
         ) + object@matrix_param$width
1515 1604
         if(nr_slice > 1) {
1516 1605
             object@heatmap_param$width = object@heatmap_param$width + sum(row_gap[seq_len(nr_slice-1)])
... ...
@@ -1557,17 +1646,17 @@ setMethod(f = "make_layout",
1557 1646
 })
1558 1647
 
1559 1648
 # == title
1560
-# Draw the single heatmap with default parameters
1649
+# Draw the Single Heatmap with Defaults
1561 1650
 #
1562 1651
 # == param
1563
-# -object a `Heatmap-class` object.
1652
+# -object A `Heatmap-class` object.
1564 1653
 #
1565 1654
 # == details
1566
-# Actually it calls `draw,Heatmap-method`, but only with default parameters. If users want to customize the heatmap,
1655
+# It actually calls `draw,Heatmap-method`, but only with default parameters. If users want to customize the heatmap,
1567 1656
 # they can pass parameters directly to `draw,Heatmap-method`.
1568 1657
 #
1569 1658
 # == value
1570
-# This function returns no value.
1659
+# The `HeatmapList-class` object.
1571 1660
 #
1572 1661
 # == author
1573 1662
 # Zuguang Gu <z.gu@dkfz.de>
... ...
@@ -1576,18 +1665,16 @@ setMethod(f = "show",
1576 1665
     signature = "Heatmap",
1577 1666
     definition = function(object) {
1578 1667
 
1579
-    # cat("A Heatmap object:\n")
1580
-    # cat("name:", object@name, "\n")
1581
-    # cat("dim:", nrow(object@matrix), "x", ncol(object@matrix), "\n")
1582 1668
     draw(object)
1583 1669
 })
1584 1670
 
1585 1671
 # == title
1586
-# Add heatmaps or row annotations as a heatmap list
1672
+# Add Heatmap to the Heatmap List
1587 1673
 #
1588 1674
 # == param
1589
-# -object a `Heatmap-class` object.
1675
+# -object A `Heatmap-class` object.
1590 1676
 # -x a `Heatmap-class` object, a `HeatmapAnnotation-class` object or a `HeatmapList-class` object.
1677
+# -direction Whether the heatmap is added horizontal or vertically?
1591 1678
 #
1592 1679
 # == details
1593 1680
 # There is a shortcut function ``+.AdditiveUnit``.
... ...
@@ -1600,11 +1687,15 @@ setMethod(f = "show",
1600 1687
 #
1601 1688
 setMethod(f = "add_heatmap",
1602 1689
     signature = "Heatmap",
1603
-    definition = function(object, x) {
1690
+    definition = function(object, x, direction = c("horizontal", "vertical")) {
1691
+
1692
+    direction = match.arg(direction)[1]
1604 1693
 
1605 1694
     ht_list = new("HeatmapList")
1606
-    ht_list = add_heatmap(ht_list, object)
1607
-    ht_list = add_heatmap(ht_list, x)
1695
+    ht_list@direction = direction
1696
+    
1697
+    ht_list = add_heatmap(ht_list, object, direction = direction)
1698
+    ht_list = add_heatmap(ht_list, x, direction = direction)
1608 1699
     return(ht_list)
1609 1700
 
1610 1701
 })
... ...
@@ -1613,16 +1704,13 @@ setMethod(f = "add_heatmap",
1613 1704
 # Draw the heatmap body
1614 1705
 #
1615 1706
 # == param
1616
-# -object a `Heatmap-class` object.
1617
-# -k a matrix may be split by rows, the value identifies which row-slice.
1618
-# -... pass to `grid::viewport`, basically for defining the position of the viewport.
1707
+# -object A `Heatmap-class` object.
1708
+# -kr Row slice index.
1709
+# -kc Column slice index.
1710
+# -... Pass to `grid::viewport` which includes the subset of heatmap body.
1619 1711
 #
1620 1712
 # == details
1621
-# The matrix can be split into several parts by rows if ``km`` or ``split`` is 
1622
-# specified when initializing the `Heatmap` object. If the matrix is split, 
1623
-# there will be gaps between rows to identify different row-slice.
1624
-#
1625
-# A viewport is created which contains subset rows of the heatmap.
1713
+# A viewport is created which contains subset rows and columns of the heatmap.
1626 1714
 #
1627 1715
 # This function is only for internal use.
1628 1716
 #
... ...
@@ -1784,19 +1872,15 @@ R_binary = function() {
1784 1872
 }
1785 1873
 
1786 1874
 # == title
1787
-# Draw dendrogram on row or column
1875
+# Draw Heatmap Dendrograms
1788 1876
 #
1789 1877
 # == param
1790
-# -object a `Heatmap-class` object.
1791
-# -which is dendrogram put on the row or on the column of the heatmap?
1792
-# -k a matrix may be splitted by rows, the value identifies which row-slice.
1793
-# -max_height maximum height of the dendrograms.
1794
-# -... pass to `grid::viewport`, basically for defining the position of the viewport.
1878
+# -object A `Heatmap-class` object.
1879
+# -which Are the dendrograms put on the row or on the column of the heatmap?
1880
+# -k Slice index.
1881
+# -... Pass to `grid::viewport` which includes the complete heatmap dendrograms.
1795 1882
 #
1796 1883
 # == details
1797
-# If the matrix is split into several row slices, a list of dendrograms will be drawn by 
1798
-# the heatmap that each dendrogram corresponds to its row slices.
1799
-#
1800 1884
 # A viewport is created which contains dendrograms.
1801 1885
 #
1802 1886
 # This function is only for internal use.
... ...
@@ -1813,7 +1897,7 @@ R_binary = function() {
1813 1897
 setMethod(f = "draw_dend",
1814 1898
     signature = "Heatmap",
1815 1899
     definition = function(object,
1816
-    which = c("row", "column"), k = 1, max_height, ...) {
1900
+    which = c("row", "column"), k = 1, ...) {
1817 1901
 
1818 1902
     which = match.arg(which)[1]
1819 1903
     
... ...
@@ -1839,7 +1923,7 @@ setMethod(f = "draw_dend",
1839 1923
         return(invisible(NULL))
1840 1924
     }
1841 1925
 
1842
-    if(missing(max_height)) max_height = dend_heights(dend)
1926
+    max_height = dend_heights(dend)
1843 1927
 
1844 1928
     dend_padding = unit(1, "mm")
1845 1929
     if(side %in% c("left", "right")) {
... ...
@@ -1878,11 +1962,10 @@ setMethod(f = "draw_dend",
1878 1962
 # Draw row names or column names
1879 1963
 #
1880 1964
 # == param
1881
-# -object a `Heatmap-class` object.
1882
-# -which are names put on the row or on the column of the heatmap?
1883
-# -k a matrix may be split by rows, the value identifies which row-slice.
1884
-# -dimname_padding padding for the row/column names
1885
-# -... pass to `grid::viewport`, basically for defining the position of the viewport.
1965
+# -object A `Heatmap-class` object.
1966
+# -which Are the names put on the row or on the column of the heatmap?
1967
+# -k Slice index.
1968
+# -... Pass to `grid::viewport` which includes the complete heatmap row/column names.
1886 1969
 #
1887 1970
 # == details
1888 1971
 # A viewport is created which contains row names or column names.
... ...
@@ -1916,13 +1999,13 @@ setMethod(f = "draw_dimnames",
1916 1999
 })
1917 2000
 
1918 2001
 # == title
1919
-# Draw heatmap title
2002
+# Draw Heatmap Title
1920 2003
 #
1921 2004
 # == param
1922
-# -object a `Heatmap-class` object.
1923
-# -which is title put on the row or on the column of the heatmap?
1924
-# -k a matrix may be split by rows, the value identifies which row-slice.
1925
-# -... pass to `grid::viewport`, basically for defining the position of the viewport.
2005
+# -object A `Heatmap-class` object.
2006
+# -which Is title put on the row or on the column of the heatmap?
2007
+# -k Slice index.
2008
+# -... Pass to `grid::viewport` which includes the complete heatmap title
1926 2009
 #
1927 2010
 # == details
1928 2011
 # A viewport is created which contains heatmap title.
... ...
@@ -1991,17 +2074,18 @@ setMethod(f = "draw_title",
1991 2074
 })
1992 2075
 
1993 2076
 # == title
1994
-# Draw column annotations
2077
+# Draw Heatmap Annotations on the Heatmap
1995 2078
 #
1996 2079
 # == param
1997
-# -object a `Heatmap-class` object.
1998
-# -which are the annotations put on the top or bottom of the heatmap?
2080
+# -object A `Heatmap-class` object.
2081
+# -which The position of the heamtap annotation.
2082
+# -k Slice index.
2083
+# -... Pass to `grid::viewport` which includes the complete heatmap annotation.
1999 2084
 #
2000 2085
 # == details
2001
-# A viewport is created which contains column annotations.
2086
+# A viewport is created which contains column/top annotations.
2002 2087
 #
2003
-# Since the column annotations is a `HeatmapAnnotation-class` object, the function
2004
-# calls `draw,HeatmapAnnotation-method` to draw the annotations.
2088
+# The function calls `draw,HeatmapAnnotation-method` to draw the annotations.
2005 2089
 #
2006 2090
 # This function is only for internal use.
2007 2091
 #
... ...
@@ -2013,21 +2097,28 @@ setMethod(f = "draw_title",
2013 2097
 #
2014 2098
 setMethod(f = "draw_annotation",
2015 2099
     signature = "Heatmap",
2016
-    definition = function(object, which = c("top", "bottom"), k = 1, ...) {
2100
+    definition = function(object, which = c("top", "bottom", "left", "right"), k = 1, ...) {
2017 2101
     
2018 2102
     which = match.arg(which)[1]
2019 2103
 
2020 2104
     annotation = switch(which,
2021 2105
         top = object@top_annotation,
2022
-        bottom = object@bottom_annotation)
2106
+        bottom = object@bottom_annotation,
2107
+        left = object@left_annotation,
2108
+        right = object@right_annotation)
2023 2109
 
2024 2110
     # if there is no annotation, draw nothing
2025 2111
     if(is.null(annotation)) {
2026 2112
         return(invisible(NULL))
2027 2113
     }
2028 2114
 
2029
-    index = object@column_order_list[[k]]
2030
-    n = length(object@column_order_list)
2115
+    if(which %in% c("top", "bottom")) {
2116
+        index = object@column_order_list[[k]]
2117
+        n = length(object@column_order_list)
2118
+    } else {
2119
+        index = object@row_order_list[[k]]
2120
+        n = length(object@row_order_list)
2121
+    }
2031 2122
 
2032 2123
     pushViewport(viewport(...))
2033 2124
     draw(annotation, index = index, k = k, n = n)
... ...
@@ -2035,13 +2126,16 @@ setMethod(f = "draw_annotation",
2035 2126
 })
2036 2127
 
2037 2128
 # == title
2038
-# Width of each heatmap component
2129
+# Widths of Heatmap Components
2039 2130
 #
2040 2131
 # == param
2041
-# -object a `Heatmap-class` object.
2042
-# -k which component in the heatmap, see `Heatmap-class`.
2132
+# -object A `Heatmap-class` object.
2133
+# -k Which components in the heatmap. The value should numeric indices or the names
2134
+#    of the corresponding row component. See **Detials**.
2043 2135
 #
2044 2136
 # == details
2137
+# All row components are: ``row_title_left``, ``row_dend_left``, ``row_names_left``, ``row_anno_left``,
2138
+# ``heatmap_body``, ``row_anno_right``, ``row_names_right``, ``row_dend_right``, ``row_title_right``.
2045 2139
 #
2046 2140
 # This function is only for internal use.
2047 2141
 #
... ...
@@ -2053,40 +2147,37 @@ setMethod(f = "draw_annotation",
2053 2147
 #
2054 2148
 setMethod(f = "component_width",
2055 2149
     signature = "Heatmap",
2056
-    definition = function(object, k = 1:7) {
2150
+    definition = function(object, k = HEATMAP_LAYOUT_ROW_COMPONENT) {
2057 2151
 
2152
+    if(is.numeric(k)) {
2153
+        component_name = names(HEATMAP_LAYOUT_ROW_COMPONENT)[k]
2154
+    } else {
2155
+        component_name = k
2156
+    }
2058 2157
     # this function is used for grid.layout, so null unit is allowed
2059
-    .single_unit = function(k) {
2060
-        if(k == 1) {
2061
-            object@layout$layout_size$row_title_left_width
2062
-        } else if(k == 2) {
2063
-            object@layout$layout_size$row_dend_left_width
2064
-        } else if(k == 3) {
2065
-            object@layout$layout_size$row_names_left_width
2066
-        } else if(k == 4) {
2158
+    .single_unit = function(nm) {
2159
+        if(nm == "heatmap_body") {
2067 2160
             object@matrix_param$width
2068
-        } else if(k == 5) {
2069
-            object@layout$layout_size$row_names_right_width
2070
-        } else if(k == 6) {
2071
-            object@layout$layout_size$row_dend_right_width
2072
-        } else if(k == 7) {
2073
-            object@layout$layout_size$row_title_right_width
2074 2161
         } else {
2075
-            stop("wrong 'k'")
2162
+            object@layout$layout_size[[paste0(nm, "_width")]]
2076 2163
         }
2077 2164
     }
2078
-
2079
-    do.call("unit.c", lapply(k, function(i) .single_unit(i)))
2165
+    
2166
+    do.call("unit.c", lapply(component_name, .single_unit))
2080 2167
 })
2081 2168
 
2082 2169
 # == title
2083
-# Height of each heatmap component
2170
+# Heights of Heatmap Components
2084 2171
 #
2085 2172
 # == param
2086
-# -object a `Heatmap-class` object.
2087
-# -k which component in the heatmap, see `Heatmap-class`.
2173
+# -object A `Heatmap-class` object.
2174
+# -k Which components in the heatmap. The value should numeric indices or the names
2175
+#    of the corresponding column component. See **Detials**.
2088 2176
 #
2089 2177
 # == detail
2178
+# All column components are: ``column_title_top``, ``column_dend_top``, ``column_names_top``, 
2179
+# ``column_anno_top``, ``heatmap_body``, ``column_anno_bottom``, ``column_names_bottom``, 
2180
+# ``column_dend_bottom``, ``column_title_bottom``.
2090 2181
 #
2091 2182
 # This function is only for internal use.
2092 2183
 #
... ...
@@ -2098,62 +2189,109 @@ setMethod(f = "component_width",
2098 2189
 #
2099 2190
 setMethod(f = "component_height",
2100 2191
     signature = "Heatmap",
2101
-    definition = function(object, k = 1:9) {
2192
+    definition = function(object, k = HEATMAP_LAYOUT_COLUMN_COMPONENT) {
2102 2193
 
2194
+    if(is.numeric(k)) {
2195
+        component_name = names(HEATMAP_LAYOUT_COLUMN_COMPONENT)[k]
2196
+    } else {
2197
+        component_name = k
2198
+    }
2103 2199
     # this function is used for grid.layout, so null unit is allowed
2104
-    .single_unit = function(k) {
2105
-        if(k == 1) {
2106
-            object@layout$layout_size$column_title_top_height
2107
-        } else if(k == 2) {
2108
-            object@layout$layout_size$column_dend_top_height
2109
-        } else if(k == 4) {
2110
-            object@layout$layout_size$column_anno_top_height
2111
-        } else if(k == 3) {
2112
-            object@layout$layout_size$column_names_top_height
2113
-        } else if(k == 5) {
2200
+    .single_unit = function(nm) {
2201
+        if(nm == "heatmap_body") {
2114 2202
             object@matrix_param$height
2115
-        } else if(k == 7) {
2116
-            object@layout$layout_size$column_names_bottom_height
2117
-        } else if(k == 6) {
2118
-            object@layout$layout_size$column_anno_bottom_height
2119
-        } else if(k == 8) {
2120
-            object@layout$layout_size$column_dend_bottom_height
2121
-        } else if(k == 9) {
2122
-            object@layout$layout_size$column_title_bottom_height
2123 2203
         } else {
2124
-            stop("wrong 'k'")
2204
+            object@layout$layout_size[[paste0(nm, "_height")]]
2125 2205
         }
2126 2206
     }
2127 2207
 
2128
-    do.call("unit.c", lapply(k, function(i) .single_unit(i)))
2208
+    do.call("unit.c", lapply(component_name, .single_unit))
2129 2209
 })
2130 2210
 
2131
-has_component = function(object, which) {
2211
+has_component = function(object, component) {
2132 2212
     m = object@layout$layout_index
2133
-    switch(which,
2134
-        "top_column_dend" = any(m[, 1] == 2 & m[,2] == 4),
2135
-        "top_column_names" = any(m[, 1] == 3 & m[,2] == 4),
2136
-        "top_annotation" = any(m[, 1] == 4 & m[,2] == 4),
2137
-        "bottom_annotation" = any(m[, 1] == 6 & m[,2] == 4),
2138
-        "bottom_column_names" = any(m[, 1] == 7 & m[,2] == 4),
2139
-        "bottom_column_dend" = any(m[, 1] == 8 & m[,2] == 4)
2140
-    )
2213
+    ind = heatmap_layout_index(component)
2214
+    any(m[, 1] == ind[1] & m[, 2] == ind[2])
2215
+}
2216
+
2217
+
2218
+HEATMAP_LAYOUT_COLUMN_COMPONENT = 1:9
2219
+names(HEATMAP_LAYOUT_COLUMN_COMPONENT) = c("column_title_top", "column_dend_top", "column_names_top", "column_anno_top",
2220
+    "heatmap_body", "column_anno_bottom", "column_names_bottom", "column_dend_bottom", "column_title_bottom")
2221
+HEATMAP_LAYOUT_ROW_COMPONENT = 1:9
2222
+names(HEATMAP_LAYOUT_ROW_COMPONENT) = c("row_title_left", "row_dend_left", "row_names_left", "row_anno_left",
2223
+    "heatmap_body", "row_anno_right", "row_names_right", "row_dend_right", "row_title_right")
2224
+
2225
+heatmap_layout_index = function(nm) {
2226
+    if(grepl("column", nm)) {
2227
+        ind = c(HEATMAP_LAYOUT_COLUMN_COMPONENT[nm], HEATMAP_LAYOUT_ROW_COMPONENT["heatmap_body"])
2228
+    } else if(grepl("row", nm)) {
2229
+        ind = c(HEATMAP_LAYOUT_COLUMN_COMPONENT["heatmap_body"], HEATMAP_LAYOUT_ROW_COMPONENT[nm])
2230
+    } else if(nm == "heatmap_body") { # heatmap_body
2231
+        ind = c(HEATMAP_LAYOUT_COLUMN_COMPONENT["heatmap_body"], HEATMAP_LAYOUT_ROW_COMPONENT["heatmap_body"])
2232
+    }
2233
+    names(ind) = c("layout.pos.row", "layout.pos.col")
2234
+    return(ind)
2141 2235
 }
2142 2236
 
2143 2237
 # == title
2144
-# Set height of each heatmap component
2238
+# Set Width of Heatmap Component
2145 2239
 #
2146 2240
 # == param
2147
-# -object a `Heatmap-class` object.
2148
-# -k which components, see `Heatmap-class`.
2149
-# -v height of the component, a `grid::unit` object.
2241
+# -object A `Heatmap-class` object.
2242
+# -k Which row component? The value should a numeric index or the name
2243
+#    of the corresponding row component. See **Detials**.
2244
+# -v width of the component, a `grid::unit` object.
2150 2245
 #
2151 2246
 # == detail
2247
+# All row components are: ``row_title_left``, ``row_dend_left``, ``row_names_left``, ``row_anno_left``,
2248
+# ``heatmap_body``, ``row_anno_right``, ``row_names_right``, ``row_dend_right``, ``row_title_right``.
2152 2249
 #
2153 2250
 # This function is only for internal use.
2154 2251
 #
2155 2252
 # == value
2156
-# This function returns no value.
2253
+# The `Heatmap-class` object.
2254
+#
2255
+# == author
2256
+# Zuguang Gu <z.gu@dkfz.de>
2257
+#
2258
+setMethod(f = "set_component_width",
2259
+    signature = "Heatmap",
2260
+    definition = function(object, k, v) {
2261
+
2262
+    if(is.numeric(k)) {
2263
+        nm = names(HEATMAP_LAYOUT_ROW_COMPONENT)[k]
2264
+    } else {
2265
+        nm = k
2266
+    }
2267
+
2268
+    object@layout$layout_size[[ paste0(nm, "_width") ]] = v
2269
+    
2270
+    if(is_abs_unit(object@matrix_param$width)) {
2271
+        object@heatmap_param$width = sum(component_width(object))
2272
+    }
2273
+
2274
+    return(object)
2275
+})
2276
+
2277
+# == title
2278
+# Set Height of Heatmap Component
2279
+#
2280
+# == param
2281
+# -object A `Heatmap-class` object.
2282
+# -k Which column component? The value should a numeric index or the name
2283
+#    of the corresponding column component. See **Detials**.
2284
+# -v Height of the component, a `grid::unit` object.
2285
+#
2286
+# == detail
2287
+# All column components are: ``column_title_top``, ``column_dend_top``, ``column_names_top``, 
2288
+# ``column_anno_top``, ``heatmap_body``, ``column_anno_bottom``, ``column_names_bottom``, 
2289
+# ``column_dend_bottom``, ``column_title_bottom``.
2290
+#
2291
+# This function is only for internal use.
2292
+#
2293
+# == value
2294
+# The `Heatmap-class` object.
2157 2295
 #
2158 2296
 # == author
2159 2297
 # Zuguang Gu <z.gu@dkfz.de>
... ...
@@ -2162,48 +2300,40 @@ setMethod(f = "set_component_height",
2162 2300
     signature = "Heatmap",
2163 2301
     definition = function(object, k, v) {
2164 2302
 
2165
-    if(k == 1) {
2166
-        object@layout$layout_size$column_title_top_height = v
2167
-    } else if(k == 2) {
2168
-        object@layout$layout_size$column_dend_top_height = v
2169
-    } else if(k == 4) {
2170
-        object@layout$layout_size$column_anno_top_height = v
2171
-    } else if(k == 3) {
2172
-        object@layout$layout_size$column_names_top_height = v
2173
-    } else if(k == 7) {
2174
-        object@layout$layout_size$column_names_bottom_height = v
2175
-    } else if(k == 6) {
2176
-        object@layout$layout_size$column_anno_bottom_height = v
2177
-    } else if(k == 8) {
2178
-        object@layout$layout_size$column_dend_bottom_height = v
2179
-    } else if(k == 9) {
2180
-        object@layout$layout_size$column_title_bottom_height = v
2303
+    if(is.numeric(k)) {
2304
+        nm = names(HEATMAP_LAYOUT_COLUMN_COMPONENT)[k]
2181 2305
     } else {
2182
-        stop("wrong 'k'")
2306
+        nm = k
2183 2307
     }
2184 2308
 
2309
+    object@layout$layout_size[[ paste0(nm, "_height") ]] = v
2310
+    
2185 2311
     if(is_abs_unit(object@matrix_param$height)) {
2186
-        object@heatmap_param$height = sum(component_height(object, 1:9))
2312
+        object@heatmap_param$height = sum(component_height(object))
2187 2313
     }
2188 2314
 
2189 2315
     return(object)
2190 2316
 })
2191 2317
 
2192 2318
 # == title
2193
-# Draw a single heatmap
2319
+# Draw a Single Heatmap
2194 2320
 #
2195 2321
 # == param
2196
-# -object a `Heatmap-class` object.
2197
-# -internal only used inside the calling of `draw,HeatmapList-method`. Only heatmap without legends will be drawn.
2198
-# -test only for testing
2199
-# -... pass to `draw,HeatmapList-method`.
2322
+# -object A `Heatmap-class` object.
2323
+# -internal If ``TRUE``, it is only used inside the calling of `draw,HeatmapList-method`. 
2324
+#           It only draws the heatmap without legends where the legend will be drawn by `draw,HeatmapList-method`. 
2325
+# -test Only for testing. If it is ``TRUE``, the heatmap body is directly drawn.
2326
+# -... Pass to `draw,HeatmapList-method`.
2200 2327
 #
2201 2328
 # == detail
2202 2329
 # The function creates a `HeatmapList-class` object which only contains a single heatmap
2203 2330
 # and call `draw,HeatmapList-method` to make the final heatmap.
2204 2331
 #
2332
+# There are some arguments which control the global setting of the heatmap such as legends.
2333
+# Please go to `draw,HeatmapList-method` for these arguments.
2334
+#
2205 2335
 # == value
2206
-# This function returns no value.
2336
+# A `HeatmapList-class` object.
2207 2337
 #
2208 2338
 # == author
2209 2339
 # Zuguang Gu <z.gu@dkfz.de>
... ...
@@ -2230,13 +2360,15 @@ setMethod(f = "draw",
2230 2360
         upViewport()
2231 2361
     } else {
2232 2362
         if(internal) {  # a heatmap without legend
2233
-            layout = grid.layout(nrow = 9, ncol = 7, widths = component_width(object, 1:7), 
2234
-                heights = component_height(object, 1:9))
2363
+            layout = grid.layout(nrow = length(HEATMAP_LAYOUT_COLUMN_COMPONENT), 
2364
+                ncol = length(HEATMAP_LAYOUT_ROW_COMPONENT), widths = component_width(object), 
2365
+                heights = component_height(object))
2235 2366
             pushViewport(viewport(layout = layout))
2236 2367
             ht_layout_index = object@layout$layout_index
2237 2368
             ht_graphic_fun_list = object@layout$graphic_fun_list
2238 2369
             for(j in seq_len(nrow(ht_layout_index))) {
2239
-                if(5 %in% ht_layout_index[j, 1] == 5 && 4 %in% ht_layout_index[j, 2]) {
2370
+                if(HEATMAP_LAYOUT_COLUMN_COMPONENT["heatmap_body"] %in% ht_layout_index[j, 1] && 
2371
+                   HEATMAP_LAYOUT_ROW_COMPONENT["heatmap_body"] %in% ht_layout_index[j, 2]) {
2240 2372
                     pushViewport(viewport(layout.pos.row = ht_layout_index[j, 1], layout.pos.col = ht_layout_index[j, 2], name = paste(object@name, "heatmap_body_wrap", sep = "_")))
2241 2373
                 } else {
2242 2374
                     pushViewport(viewport(layout.pos.row = ht_layout_index[j, 1], layout.pos.col = ht_layout_index[j, 2]))
... ...
@@ -2257,23 +2389,23 @@ setMethod(f = "draw",
2257 2389
 })
2258 2390
 
2259 2391
 # == title
2260
-# Prepare the heatmap
2392
+# Prepare the Heatmap
2261 2393
 #
2262 2394
 # == param
2263
-# -object a `Heatmap-class` object.
2264
-# -process_rows whether process rows of the heatmap
2395
+# -object A `Heatmap-class` object.
2396
+# -process_rows Whether to process rows of the heatmap.
2265 2397
 #
2266 2398
 # == detail
2267 2399
 # The preparation of the heatmap includes following steps:
2268 2400
 #
2269
-# - making clustering on rows if specified (by calling `make_row_cluster,Heatmap-method`)
2270
-# - making clustering on columns if specified (by calling `make_column_cluster,Heatmap-method`)
2401
+# - making clustering on rows if it is specified (by calling `make_row_cluster,Heatmap-method`)
2402
+# - making clustering on columns (by calling `make_column_cluster,Heatmap-method`)
2271 2403
 # - making the layout of the heatmap (by calling `make_layout,Heatmap-method`)
2272 2404
 #
2273 2405
 # This function is only for internal use.
2274 2406
 #
2275 2407
 # == value
2276
-# A `Heatmap-class` object.
2408
+# The `Heatmap-class` object.
2277 2409
 #
2278 2410
 # == author
2279 2411
 # Zuguang Gu <z.gu@dkfz.de>
... ...
@@ -2292,10 +2424,23 @@ setMethod(f = "prepare",
2292 2424
 
2293 2425
 })
2294 2426
 
2295
-# ht[1:10, ]
2296
-# ht[1:10]
2297
-# ht[, 1:10]
2298
-# ht[1:10, 1:10]
2427
+# == title
2428
+# Subset a Heatmap
2429
+#
2430
+# == param
2431
+# -x A `Heatmap-class` object.
2432
+# -i Row indices
2433
+# -j Column indices
2434
+#
2435
+# == example
2436
+# m = matrix(rnorm(100), nrow = 10)
2437
+# rownames(m) = letters[1:10]
2438
+# colnames(m) = LETTERS[1:10]
2439
+# ht = Heatmap(m)
2440
+# ht[1:5, ]
2441
+# ht[1:5]
2442
+# ht[, 1:5]
2443
+# ht[1:5, 1:5]
2299 2444
 "[.Heatmap" = function(x, i, j) {
2300 2445
     if(nargs() == 2) {
2301 2446
         subset_heatmap_by_row(x, i)
... ...
@@ -2344,14 +2489,43 @@ subset_heatmap_by_column = function(ht, ind) {
2344 2489
     return(ht)
2345 2490
 }
2346 2491
 
2492
+# == title
2493
+# Dimension of the Heatmap
2494
+#
2495
+# == param
2496
+# -x A `Heatmap-class` object.
2497
+#
2347 2498
 dim.Heatmap = function(x) {
2348 2499
     dim(x@matrix)
2349 2500
 }
2350 2501
 
2351
-length.Heatmap = function(x) {
2502
+# == title
2503
+# Number of Rows in the Heatmap
2504
+#
2505
+# == param
2506
+# -x A `Heatmap-class` object.
2507
+#
2508
+nrow.Heatmap = function(x) {
2352 2509
     nrow(x@matrix)
2353 2510
 }
2354 2511
 
2512
+# == title
2513
+# Number of Columns in the Heatmap
2514
+#
2515
+# == param
2516
+# -x A `Heatmap-class` object.
2517
+#
2518
+ncol.Heatmap = function(x) {
2519
+    ncol(x@matrix)
2520
+}
2521
+
2522
+# == title
2523
+# Print the Summary of a Heatmap
2524
+#
2525
+# == param
2526
+# -object A `Heatmap-class` object.
2527
+# -... Other arguments.
2528
+#
2355 2529
 summary.Heatmap = function(object, ...) {
2356 2530
     qqcat("a matrix with @{nrow(object@matrix)} rows and @{ncol(object@matrix)} columns\n")
2357 2531
     qqcat("name: @{object@name}\n")
... ...
@@ -2438,5 +2612,21 @@ summary.Heatmap = function(object, ...) {
2438 2612
     } else {
2439 2613
         qqcat("has no bottom annotation\n")
2440 2614
     }
2615
+    if(length(object@left_annotation)) {
2616
+        qqcat("has @{length(object@left_annotation)} left annotationa:\n")
2617
+        qqcat("=======================================\n")
2618
+        show(object@left_annotation)
2619
+        qqcat("=======================================\n")
2620
+    } else {
2621
+        qqcat("has no left annotation\n")
2622
+    }
2623
+    if(length(object@right_annotation)) {
2624
+        qqcat("has @{length(object@right_annotation)} right annotationa:\n")
2625
+        qqcat("=======================================\n")
2626
+        show(object@right_annotation)
2627
+        qqcat("=======================================\n")
2628
+    } else {
2629
+        qqcat("has no right annotation\n")
2630
+    }
2441 2631
 }
2442 2632
 
... ...
@@ -1,6 +1,6 @@
1 1
 
2 2
 # == title
3
-# Class for heatmap annotations
3
+# Class for Heatmap Annotations
4 4
 #
5 5
 # == details
6 6
 # A complex heatmap contains a list of annotations which are represented as different graphics
... ...
@@ -42,31 +42,35 @@ HeatmapAnnotation = setClass("HeatmapAnnotation",
42 42
 # Constructor method for HeatmapAnnotation class
43 43
 #
44 44
 # == param
45
-# -df a data frame. Each column will be treated as a simple annotation. The data frame must have column names.
46
-# -name name of the heatmap annotation, optional.
47
-# -col a list of colors which contains color mapping to columns in ``df``. See `SingleAnnotation` for how to set colors.
48
-# -na_col color for ``NA`` values in simple annotations.
49
-# -annotation_legend_param a list which contains parameters for annotation legends
50
-# -show_legend whether show legend for each column in ``df``.
51
-# -... functions which define complex annotations or vectors of simple annotation. Values should be named arguments.
52
-# -which are the annotations row annotations or column annotations?
53
-# -annotation_height height of each annotation if annotations are column annotations.
54
-# -annotation_width width of each annotation if annotations are row annotations.
55
-# -height height of the column annotations, basically it is identical to ``bottom_annotation_height`` or ``top_annotation_height``
56
-#        in `Heatmap` function.
57
-# -width width of the whole heatmap annotations, only used for row annotation when appending to the list of heatmaps.
58
-# -gp graphic parameters for simple annotations.
59
-# -gap gap between each annotation
60
-# -show_annotation_name whether show annotation names. For column annotation, annotation names are drawn either on the left
45
+# -... Name-value pairs where the names correspond to annotation names and values can be a vector, a matrix and an
46
+#      annotation function. Each pair is sent to `SingleAnnotation` to contruct a single annotation.
47
+# -df A data frame. Each column will be treated as a simple annotation. The data frame must have column names.
48
+# -name Name of the heatmap annotation, optional.
49
+# -col A list of colors which contain color mapping to columns in ``df`` and simple annotations define din ``...```. 
50
+#      See `SingleAnnotation` for how to set colors.
51
+# -na_col Color for ``NA`` values in simple annotations.
52
+# -annotation_legend_param A list which contains parameters for annotation legends. See `color_mapping_legend,ColorMapping-method` for all possible options.
53
+# -show_legend Whether show annotation legend. The value can be one single value or a vector which corresponds to the simple annotations.
54
+# -which Are the annotations row annotations or column annotations?
55
+# -annotation_height Height of each annotation if annotations are column annotations.
56
+# -annotation_width Width of each annotation if annotations are row annotations.
57
+# -height Height of the complete column annotations.
58
+# -width Width of the complete heatmap annotations.
59
+# -gp Graphic parameters for simple annotations (with ``fill`` parameter ignored).
60
+# -gap Gap between each two annotation. It can be a single value or a vector of `grid.unit` objects.
61
+# -show_annotation_name Whether show annotation names? For column annotation, annotation names are drawn either on the left
61 62
 #   or the right, and for row annotations, names are draw either on top to at bottom. The value can be a vector.
62
-# -annotation_name_gp graphic parameters for anntation names. Graphic paramters can be vectors.
63
-# -annotation_name_offset offset to the annotations, `grid::unit` object. The value can be a vector.
64
-# -annotation_name_side side of the annotation names.
65
-# -annotation_name_rot rotation of the annotation names, can only take values in ``c(00, 90, 180, 270)``. The value can be a vector.
63
+# -annotation_name_gp Graphic parameters for anntation names. Graphic paramters can be vectors.
64
+# -annotation_name_offset Offset to the annotations, `grid::unit` object. The value can be a vector.
65
+# -annotation_name_side Side of the annotation names.
66
+# -annotation_name_rot Rotation of the annotation names, can only take values in ``c(00, 90, 180, 270)``. The value can be a vector.
66 67
 #
67 68
 # == details
68
-# The simple annotations are defined by ``df`` and ``col`` arguments. Complex annotations are
69
-# defined by the function list. So you need to at least to define ``df`` or a annotation function.
69
+# There are three ways to specify heatmap annotations:
70
+#
71
+# 1. If the annotation is simply a vector or a matrix, it can be specified as ``HeatmapAnnotation(foo = 1:10)``.
72
+# 2. If the annotations are already stored as a data frame, it can be specified as ``HeatmapAnnotation(df = df)``.
73
+# 3. For complex annotation, users can use the pre-defined annotation functions such as `anno_points`: ``HeatmapAnnotation(foo = anno_points(1:10))``.
70 74
 #
71 75
 # == value
72 76
 # A `HeatmapAnnotation-class` object.
... ...
@@ -350,7 +354,7 @@ HeatmapAnnotation = function(...,
350 354
     		if(!is.null(width)) {
351 355
     			global_width = width
352 356
     		}
353
-    		anno_size = lapply(anno_list, width)
357
+    		anno_size = do.call("unit.c", lapply(anno_list, width))
354 358
 			width = sum(anno_size) + sum(gap) - gap[n_total_anno]
355 359
     	} else {
356 360
     		if(length(annotation_width) != n_total_anno) {
... ...
@@ -410,10 +414,10 @@ HeatmapAnnotation = function(...,
410 414
 }
411 415
 
412 416
 # == title
413
-# Construct row annotations
417
+# Construct Row Annotations
414 418
 #
415 419
 # == param
416
-# -... pass to `HeatmapAnnotation`
420
+# -... Pass to `HeatmapAnnotation`
417 421
 #
418 422
 # == details
419 423
 # The function is identical to 
... ...
@@ -431,10 +435,10 @@ rowAnnotation = function(...) {
431 435
 }
432 436
 
433 437
 # == title
434
-# Construct column annotations
438
+# Construct Column Annotations
435 439
 #
436 440
 # == param
437
-# -... pass to `HeatmapAnnotation`
441
+# -... Pass to `HeatmapAnnotation`
438 442
 #
439 443
 # == details
440 444
 # The function is identical to
... ...
@@ -452,13 +456,13 @@ columnAnnotation = function(...) {
452 456
 }
453 457
 
454 458
 # == title
455
-# Get a list of color mapping objects
459
+# Get a List of ColorMapping objects
456 460
 #
457 461
 # == param
458
-# -object a `HeatmapAnnotation-class` object.
462
+# -object A `HeatmapAnnotation-class` object.
459 463
 #
460 464
 # == details
461
-# Color mapping for visible simple annotations are only returned.
465
+# Color mappings for visible simple annotations are only returned.
462 466
 #
463 467
 # This function is only for internal use.
464 468
 #
... ...
@@ -482,13 +486,13 @@ setMethod(f = "get_color_mapping_list",
482 486
 })
483 487
 
484 488
 # == title
485
-# Get a list of color mapping parameters
489
+# Get a List of Annotation Legend Parameters
486 490
 #
487 491
 # == param
488
-# -object a `HeatmapAnnotation-class` object.
492
+# -object A `HeatmapAnnotation-class` object.
489 493
 #
490 494
 # == details
491
-# Color mapping parameters for visible simple annotations are only returned.
495
+# The annotation legend parameters for visible simple annotations are only returned.
492 496
 #
493 497
 # This function is only for internal use.
494 498
 #
... ...
@@ -512,19 +516,16 @@ setMethod(f = "get_legend_param_list",
512 516
 })
513 517
 
514 518
 # == title
515
-# Draw the heatmap annotations
519
+# Draw the Heatmap Annotations
516 520
 #
517 521
 # == param
518
-# -object a `HeatmapAnnotation-class` object.
519
-# -index a vector of order.
520
-# -k if row annotation is splitted, the value identifies which row slice.
521
-# -n total number of row slices.
522
-# -align_to if the allocated space is more than than the column annotation itself, should
523
-#     the viewport be aligned to the top or bottom?
524
-# -... pass to `grid::viewport` which contains all annotations.
525
-#
526
-# == details
527
-# A viewport is created. Mostly, this method is used inside `draw,HeatmapList-method`.
522
+# -object A `HeatmapAnnotation-class` object.
523
+# -index A vector of indices.
524
+# -k The current slice index for the annotation if it is split.
525
+# -n Total number of slices.
526
+# -align_to This argument will be removed in the future.
527
+# -... Pass to `grid::viewport` which contains all the annotations.
528
+# -test Is it in test mode? The value can be logical or a text which is plotted as the title of plot.
528 529
 #
529 530
 # == value
530 531
 # No value is returned.
... ...
@@ -617,10 +618,10 @@ setMethod(f = "draw",
617 618
 })
618 619
 
619 620
 # == title
620
-# Print the Heatmap Annotation object
621
+# Print the HeatmapAnnotation object
621 622
 #
622 623
 # == param
623
-# -object a `HeatmapAnnotation-class` object.
624
+# -object A `HeatmapAnnotation-class` object.
624 625
 #
625 626
 # == value
626 627
 # No value is returned.
... ...
@@ -707,7 +708,13 @@ setMethod(f = "show",
707 708
 })
708 709
 
709 710
 
710
-nobs.HeatmapAnnotation = function(object, ...) {
711
+# == title
712
+# Number of Observations
713
+#
714
+# == param
715
+# -x The `HeatmapAnnotation-class` object.
716
+#
717
+nobs.HeatmapAnnotation = function(object) {
711 718
 	n_anno = length(object@anno_list)
712 719
 	len = sapply(seq_len(n_anno), function(i) {
713 720
 		if(inherits(object@anno_list[[i]]@fun, "AnnotationFunction")) {
... ...
@@ -742,15 +749,37 @@ nobs.HeatmapAnnotation = function(object, ...) {
742 749
 #
743 750
 setMethod(f = "add_heatmap",
744 751
     signature = "HeatmapAnnotation",
745
-    definition = function(object, x) {
752
+    definition = function(object, x, direction = c("horizontal", "vertical")) {
753
+
754
+    direction = match.arg(direction)[1]
746 755
 
747 756
     ht_list = new("HeatmapList")
748
-    ht_list = add_heatmap(ht_list, object)
749
-    ht_list = add_heatmap(ht_list, x)
757
+    ht_list@direction = direction
758
+    
759
+    ht_list = add_heatmap(ht_list, object, direction = direction)
760
+    ht_list = add_heatmap(ht_list, x, direction = direction)
750 761
     return(ht_list)
751 762
 
752 763
 })
753 764
 
765
+# == title
766
+# Concatenate Heatmap Annotations
767
+#
768
+# == param
769
+# -... `HeatmapAnnotation-class` objects.
770
+# -gap gap between the annotations.
771
+#
772
+# == details
773
+# The heatmap annotations should be same number of observations.
774
+# 
775
+# == example
776
+# ha1 = HeatmapAnnotation(foo = 1:10)
777
+# ha2 = HeatmapAnnotation(bar = anno_points(10:1))
778
+# ha = c(ha1, ha2)
779
+# ha
780
+# ha3 = HeatmapAnnotation(sth = cbind(1:10, 10:1))
781
+# ha = c(ha1, ha2, ha3, gap = unit(c(1, 4), "mm"))
782
+# ha
754 783
 c.HeatmapAnnotation = function(..., gap = unit(0, "mm")) {
755 784
 	anno_list = list(...)
756 785
 	n = length(anno_list)
... ...
@@ -758,6 +787,7 @@ c.HeatmapAnnotation = function(..., gap = unit(0, "mm")) {
758 787
 		stop("All annotations should be all row annotation or all column annotation.")
759 788
 	}
760 789
 	if(length(gap) == 1) gap = rep(gap, n)
790
+	if(length(gap) == n - 1) gap = unit.c(gap, unit(0, "mm"))
761 791
 	x = anno_list[[1]]
762 792
 	if(n > 1) {
763 793
 		x@gap[length(x@gap)] = gap[1]
... ...
@@ -800,10 +830,30 @@ c.HeatmapAnnotation = function(..., gap = unit(0, "mm")) {
800 830
 	return(x)
801 831
 }
802 832
 
833
+# == title
834
+# Annotation Names
835
+#
836
+# == param
837
+# -x A `HeatmapAnnotation-class` object.
838
+#
839
+# == example
840
+# ha = HeatmapAnnotation(foo = 1:10, bar = anno_points(10:1))
841
+# names(ha)
803 842
 names.HeatmapAnnotation = function(x) {
804 843
 	names(x@anno_list)
805 844
 }
806 845
 
846
+# == title
847
+# Assign Annotation Names
848
+#
849
+# == param
850
+# -x A `HeatmapAnnotation-class` object.
851
+# -value A vector of new names.
852
+#
853
+# == example
854
+# ha = HeatmapAnnotation(foo = 1:10, bar = anno_points(10:1))
855
+# names(ha) = c("A", "B")
856
+# names(ha)
807 857
 `names<-.HeatmapAnnotation` = function(x, value) {
808 858
 	if(length(value) != length(x@anno_list)) {
809 859
 		stop("Length of `value` should be same as number of annotations.")
... ...
@@ -819,7 +869,21 @@ names.HeatmapAnnotation = function(x) {
819 869
 }
820 870
 
821 871
 
822
-# ha[1:2, c("foo", "bar")]
872
+# == title
873
+# Subset the HeatmapAnnotation object
874
+#
875
+# == param
876
+# -x A `HeatmapAnnotation-class` object.
877
+# -i Index of observations.
878
+# -j Index of annotations.
879
+#
880
+# == example
881
+# ha = HeatmapAnnotation(foo = 1:10, bar = anno_points(10:1),
882
+# 	sth = cbind(1:10, 10:1))
883
+# ha[1:5, ]
884
+# ha[, c("foo", "bar")]
885
+# ha[, 1:2]
886
+# ha[1:5, c("foo", "sth")]
823 887
 "[.HeatmapAnnotation" = function(x, i, j) {
824 888
 	if(!missing(j)) {
825 889
 		if(is.character(j)) {
... ...
@@ -839,7 +903,7 @@ names.HeatmapAnnotation = function(x) {
839 903
         x2@gap = x@gap[j]
840 904
         x2@gap[length(x2@gap)] = unit(0, "mm")
841 905
 
842
-        x2@size = sum(x2@anno_size) + sum(x2@gap) - x2@gap[length(x2@gap)]
906
+        size(x2) = sum(x2@anno_size) + sum(x2@gap) - x2@gap[length(x2@gap)]
843 907
 
844 908
     } else if(nargs() == 3 && missing(j)) {  # ha[1:4, ]
845 909
         x2 = x
... ...
@@ -863,7 +927,7 @@ names.HeatmapAnnotation = function(x) {
863 927
         x2@gap = x@gap[j]
864 928
         x2@gap[length(x2@gap)] = unit(0, "mm")
865 929
 
866
-        x2@size = sum(x2@anno_size) + sum(x2@gap) - x2@gap[length(x2@gap)]
930
+        size(x2) = sum(x2@anno_size) + sum(x2@gap) - x2@gap[length(x2@gap)]
867 931
 
868 932
     }
869 933
     
... ...
@@ -878,18 +942,37 @@ names.HeatmapAnnotation = function(x) {
878 942
     return(x2)
879 943
 }
880 944
 
945
+# == title
946
+# Number of Annotations
947
+#
948
+# == param
949
+# -x A `HeatmapAnnotation-class` object.
950
+#
881 951
 length.HeatmapAnnotation = function(x) {
882 952
 	length(x@anno_list)
883 953
 }
884 954
 
885 955
 
886
-
956
+# == title
957
+# Width of the HeatmapAnnotation object
958
+#
959
+# == param
960
+# -object The `HeatmapAnnotation-class` object.
961
+#
887 962
 setMethod(f = "width",
888 963
     signature = "HeatmapAnnotation",
889 964
     definition = function(object) {
890 965
     object@width
891 966
 })
892 967
 
968
+# == title
969
+# Assign the Width of the HeatmapAnnotation object
970
+#
971
+# == param
972
+# -object The `HeatmapAnnotation-class` object.
973
+# -value A `grid::unit` object.
974
+# -... Other arguments
975
+#
893 976
 setReplaceMethod(f = "width",
894 977
     signature = "HeatmapAnnotation",
895 978
     definition = function(object, value, ...) {
... ...
@@ -906,13 +989,26 @@ setReplaceMethod(f = "width",
906 989
 })
907 990
 
908 991
 
909
-
992
+# == title
993
+# Height of the HeatmapAnnotation object
994
+#
995
+# == param
996
+# -object The `HeatmapAnnotation-class` object.
997
+#
910 998
 setMethod(f = "height",
911 999
     signature = "HeatmapAnnotation",
912 1000
     definition = function(object) {
913 1001
     object@height
914 1002
 })
915 1003
 
1004
+# == title
1005
+# Assign the Height of the HeatmapAnnotation object
1006
+#
1007
+# == param
1008
+# -object The `HeatmapAnnotation-class` object.
1009
+# -value A `grid::unit` object.
1010
+# -... Other arguments
1011
+#
916 1012
 setReplaceMethod(f = "height",
917 1013
     signature = "HeatmapAnnotation",
918 1014
     definition = function(object, value, ...) {
... ...
@@ -928,6 +1024,15 @@ setReplaceMethod(f = "height",
928 1024
     object
929 1025
 })
930 1026
 
1027
+# == title
1028
+# Size of the HeatmapAnnotation object
1029
+#
1030
+# == param
1031
+# -object The `HeatmapAnnotation-class` object.
1032
+#
1033
+# == detail
1034
+# It returns the width if it is a row annotation and the height if it is a column annotation.
1035
+#
931 1036
 setMethod(f = "size",
932 1037
     signature = "HeatmapAnnotation",
933 1038
     definition = function(object) {
... ...
@@ -938,6 +1043,17 @@ setMethod(f = "size",
938 1043
     }
939 1044
 })
940 1045
 
1046
+# == title
1047
+# Assign the Size of the HeatmapAnnotation object
1048
+#
1049
+# == param
1050
+# -object The `HeatmapAnnotation-class` object.
1051
+# -value A `grid::unit` object.
1052
+# -... Other arguments
1053
+#
1054
+# == detail
1055
+# It assigns the width if it is a row annotation and the height if it is a column annotation.
1056
+#
941 1057
 setReplaceMethod(f = "size",
942 1058
     signature = "HeatmapAnnotation",
943 1059
     definition = function(object, value, ...) {
... ...
@@ -949,7 +1065,31 @@ setReplaceMethod(f = "size",
949 1065
     object
950 1066
 })
951 1067
 
952
-## for some reasons, only set height for column annotation and width for row annotation
1068
+# == title
1069
+# Resize the Width or Height of Heatmap Annotations
1070
+#
1071
+# == param
1072
+# -annotation_height A vector of of annotation heights in `grid.unit` class.
1073
+# -annotation_width A vector of of annotation widths in `grid.unit` class.
1074
+# -height The height of the complete heatmap annotation.
1075
+# -width The width of the complete heatmap annotation.
1076
+# -anno_simple_row_size The size of one line of the simple annotation.
1077
+# -simple_anno_size_adjust Whether adjust the size of the simple annotation?
1078
+#
1079
+# == details
1080
+# The function only adjust height for column annotations and width for row annotations.
1081
+#
1082
+# the basic rule is:
1083
+# 1. if ``annotation_height`` is set, it needs to be a vector and ``height`` is disabled. If all
1084
+#    ``annotation_height`` are absolute units, ``height`` is ignored.
1085
+# 2. if ``annotation_height`` contains non-absolute units, ``height`` also need to be set and the
1086
+#    non-absolute unit should be set in a simple form such as 1:10 or ``unit(1, "null")``.
1087
+# 3. ``anno_simple_row_size`` is only used when ``annotation_height`` is NULL.
1088
+# 4. if only ``height`` is set, non-simple annotation is adjusted while keep simple anntation unchanged.
1089
+# 5. if only ``height`` is set and all annotations are simple annotations, all anntations are adjusted.
1090
+#      and ``anno_simple_row_size`` is disabled.
1091
+# 6. If ``simple_anno_size_adjust`` is ``FALSE``, the size of the simple annotations will not change.
1092
+#
953 1093
 setMethod(f = "resize",
954 1094
 	signature = "HeatmapAnnotation",
955 1095
 	definition = function(object, 
... ...
@@ -57,6 +57,7 @@ HeatmapList = setClass("HeatmapList",
57 57
     slots = list(
58 58
         ht_list = "list",
59 59
         ht_list_param = "list",
60
+        direction = "character",
60 61
 
61 62
         row_title = "ANY",
62 63
         row_title_param = "list",
... ...
@@ -69,6 +70,8 @@ HeatmapList = setClass("HeatmapList",
69 70
         layout = "list"
70 71
     ),
71 72
     prototype = list(
73
+        direction = "horizontal",
74
+
72 75
         layout = list(
73 76
             layout_annotation_legend_left_width = unit(0, "mm"),
74 77
             layout_heatmap_legend_left_width = unit(0, "mm"),
... ...
@@ -130,8 +133,13 @@ HeatmapList = function(...) {
130 133
 #
131 134
 setMethod(f = "add_heatmap",
132 135
     signature = "HeatmapList",
133
-    definition = function(object, x) {
136
+    definition = function(object, x, direction = c("horizontal", "vertical")) {
134 137
     
138
+    direction = match.arg(direction)[1]
139
+    if(object@direction != direction) {
140
+        stop("The heatmap list should only be all horizontal or vertical.")
141
+    }
142
+
135 143
     # check settings of this new heatmap
136 144
     if(inherits(x, "Heatmap")) {
137 145
         ht_name = x@name
... ...
@@ -139,14 +147,16 @@ setMethod(f = "add_heatmap",
139 147
         names(x) = ht_name
140 148
         object@ht_list = c(object@ht_list, x)
141 149
     } else if(inherits(x, "HeatmapAnnotation")) {
142
-        if(x@which == "row") {
143
-            ht_name = x@name
144
-            x = list(x)
145
-            names(x) = ht_name
146
-            object@ht_list = c(object@ht_list, x)
147
-        } else {
148
-            stop("You should specify `which` to `row` in you add a HeatmapAnnotation which shows row annotations.")    
150
+        if(x@which == "row" && direction == "vertical") {
151
+            stop("Row annotations should be added to the heatmap list in horizontal direction.")
152
+        } else if(x@which == "column" && direction == "horizontal") {
153
+            stop("Column annotations should be added to the heatmap list in vertical direction.")
149 154
         }
155
+        ht_name = x@name
156
+        x = list(x)
157
+        names(x) = ht_name
158
+        object@ht_list = c(object@ht_list, x)
159
+        
150 160
     } else if(inherits(x, "HeatmapList")) {
151 161
         ht_name = names(x@ht_list)
152 162
         object@ht_list = c(object@ht_list, x@ht_list)
... ...
@@ -155,20 +165,34 @@ setMethod(f = "add_heatmap",
155 165
     ht_name = names(object@ht_list)
156 166
     which_duplicated = duplicated(ht_name)
157 167
     if(any(which_duplicated)) {
158
-        warning(paste0("Heatmap/row annotation names are duplicated: ", paste(ht_name[which_duplicated], collapse = ", ")))
168
+        warning(paste0("Heatmap/annotation names are duplicated: ", paste(ht_name[which_duplicated], collapse = ", ")))
159 169
     }
160 170
 
161 171
     l = which(sapply(object@ht_list, inherits, "Heatmap"))
162
-    nr = sapply(object@ht_list[l], function(ht) nrow(ht@matrix))
163
-
164
-    if(length(unique(nr)) > 1) {
165
-        cat("`nrow` of all heatmaps:\n")
166
-        print(nr)
167
-        stop("`nrow` of all heatmaps should be the same.")
168
-        for(i in l) {
169
-            cat(object@ht_list[[i]]@name, ":", nrow(object@ht_list[[i]]@matrix), "\n")
172
+    if(direction == "horizontal") {
173
+        nr = sapply(object@ht_list[l], function(ht) nrow(ht@matrix))
174
+
175
+        if(length(unique(nr)) > 1) {
176
+            cat("`nrow` of all heatmaps:\n")
177
+            print(nr)
178
+            stop("`nrow` of all heatmaps should be the same for horizontal heatmap list.")
179
+            for(i in l) {
180
+                cat(object@ht_list[[i]]@name, ":", nrow(object@ht_list[[i]]@matrix), "\n")
181
+            }
182
+            cat("\n")
183
+        }
184
+    } else {
185
+        nc = sapply(object@ht_list[l], function(ht) ncol(ht@matrix))
186
+
187
+        if(length(unique(nc)) > 1) {
188
+            cat("`ncol` of all heatmaps:\n")
189
+            print(nr)
190
+            stop("`ncol` of all heatmaps should be the same for vertical heatmap list.")
191
+            for(i in l) {
192
+                cat(object@ht_list[[i]]@name, ":", ncol(object@ht_list[[i]]@matrix), "\n")
193
+            }
194
+            cat("\n")
170 195
         }
171
-        cat("\n")
172 196
     }
173 197
 
174 198
     return(object)
... ...
@@ -515,7 +539,7 @@ setMethod(f = "make_layout",
515 539
     }
516 540
 
517 541
     object = adjust_heatmap_list(object)
518
-    object@layout$layout_index = rbind(c(4, 4))
542
+    object@layout$layout_index = rbind(heatmaplist = heatmap_list_layout_index("heatmap_list"))
519 543
     object@layout$graphic_fun_list = list(function(object) draw_heatmap_list(object))
520 544
 
521 545
     ############################################
... ...
@@ -536,10 +560,10 @@ setMethod(f = "make_layout",
536 560
     if(length(column_title) > 0) {
537 561
         if(column_title_side == "top") {
538 562
             object@layout$layout_column_title_top_height = grobHeight(textGrob(column_title, gp = column_title_gp)) + TITLE_PADDING*2
539
-            object@layout$layout_index = rbind(object@layout$layout_index, c(3, 4))
563
+            object@layout$layout_index = rbind(object@layout$layout_index, column_title_top = heatmap_list_layout_index("column_title_top"))
540 564
         } else {
541 565
             object@layout$layout_column_title_bottom_height = grobHeight(textGrob(column_title, gp = column_title_gp)) + TITLE_PADDING*2
542
-            object@layout$layout_index = rbind(object@layout$layout_index, c(5, 4))
566
+            object@layout$layout_index = rbind(object@layout$layout_index, column_title_bottom = heatmap_list_layout_index("column_title_bottom"))
543 567
         }
544 568
         object@layout$graphic_fun_list = c(object@layout$graphic_fun_list, function(object) draw_title(object, which = "column"))
545 569
     }
... ...
@@ -562,10 +586,10 @@ setMethod(f = "make_layout",
562 586
     if(length(row_title) > 0) {
563 587
         if(row_title_side == "left") {
564 588
             object@layout$layout_row_title_left_width = grobHeight(textGrob(row_title, gp = row_title_gp)) + TITLE_PADDING*2
565
-            object@layout$layout_index = rbind(object@layout$layout_index, c(4, 3))
589
+            object@layout$layout_index = rbind(object@layout$layout_index, row_title_left = heatmap_list_layout_index("row_title_left"))
566 590
         } else {
567 591
             object@layout$layout_row_title_right_width = grobHeight(textGrob(row_title, gp = row_title_gp)) + TITLE_PADDING*2
568
-            object@layout$layout_index = rbind(object@layout$layout_index, c(4, 5))
592
+            object@layout$layout_index = rbind(object@layout$layout_index, row_title_right = heatmap_list_layout_index("row_title_right"))
569 593
         }
570 594
         object@layout$graphic_fun_list = c(object@layout$graphic_fun_list, function(object) draw_title(object, which = "row"))
571 595
     }
... ...
@@ -615,25 +639,25 @@ setMethod(f = "make_layout",
615 639
             size = heatmap_legend_size(object, legend_list = heatmap_legend_list)
616 640
             object@heatmap_legend_param$size = size
617 641
             object@layout$layout_heatmap_legend_top_height = size[2]
618
-            object@layout$layout_index = rbind(object@layout$layout_index, c(2, 4))
642
+            object@layout$layout_index = rbind(object@layout$layout_index, heatmap_legend_top = heatmap_list_layout_index("heatmap_legend_top"))
619 643
         } else if(heatmap_legend_side == "bottom") {
620 644
             object@heatmap_legend_param$padding = unit(c(0, 0, 2, 0), "mm")
621 645
             size = heatmap_legend_size(object, legend_list = heatmap_legend_list)
622 646
             object@heatmap_legend_param$size = size
623 647
             object@layout$layout_heatmap_legend_bottom_height = size[2]
624
-            object@layout$layout_index = rbind(object@layout$layout_index, c(6, 4))
648
+            object@layout$layout_index = rbind(object@layout$layout_index, heatmap_legend_bottom = heatmap_list_layout_index("heatmap_legend_bottom"))
625 649
         } else if(heatmap_legend_side == "left") {
626 650
             object@heatmap_legend_param$padding = unit(c(0, 0, 0, 2), "mm")
627 651
             size = heatmap_legend_size(object, legend_list = heatmap_legend_list)
628 652
             object@heatmap_legend_param$size = size
629 653
             object@layout$layout_heatmap_legend_left_width = size[1]
630
-            object@layout$layout_index = rbind(object@layout$layout_index, c(4, 2))
654
+            object@layout$layout_index = rbind(object@layout$layout_index, heatmap_legend_left = heatmap_list_layout_index("heatmap_legend_left"))
631 655
         } else if(heatmap_legend_side == "right") {
632 656
             object@heatmap_legend_param$padding = unit(c(0, 2, 0, 0), "mm")
633 657
             size = heatmap_legend_size(object, legend_list = heatmap_legend_list)
634 658
             object@heatmap_legend_param$size = size
635 659
             object@layout$layout_heatmap_legend_right_width = size[1]
636
-            object@layout$layout_index = rbind(object@layout$layout_index, c(4, 6))
660
+            object@layout$layout_index = rbind(object@layout$layout_index, heamap_legend_right = heatmap_list_layout_index("heamtap_legend_right"))
637 661
         }
638 662
         object@layout$graphic_fun_list = c(object@layout$graphic_fun_list, function(object) draw_heatmap_legend(object, legend_list = heatmap_legend_list))
639 663
     } else {
... ...
@@ -671,25 +695,25 @@ setMethod(f = "make_layout",
671 695
             size = annotation_legend_size(object, legend_list = annotation_legend_list)
672 696
             object@annotation_legend_param$size = size
673 697
             object@layout$layout_annotation_legend_top_height = size[2]
674
-            object@layout$layout_index = rbind(object@layout$layout_index, c(1, 4))
698
+            object@layout$layout_index = rbind(object@layout$layout_index, annotation_legend_top = heatmap_list_layout_index("annotation_legend_top"))
675 699
         } else if(annotation_legend_side == "bottom") {
676 700
             object@annotation_legend_param$padding = unit(c(0, 0, 2, 0), "mm")
677 701
             size = annotation_legend_size(object, legend_list = annotation_legend_list)
678 702
             object@annotation_legend_param$size = size
679 703
             object@layout$layout_annotation_legend_bottom_height = size[2]
680
-            object@layout$layout_index = rbind(object@layout$layout_index, c(7, 4))
704
+            object@layout$layout_index = rbind(object@layout$layout_index, annotation_legend_bottom = heatmap_list_layout_index("annotation_legend_bottom"))
681 705
         } else if(annotation_legend_side == "left") {
682 706
             object@annotation_legend_param$padding = unit(c(0, 0, 0, 2), "mm")
683 707
             size = annotation_legend_size(object, legend_list = annotation_legend_list)
684 708
             object@annotation_legend_param$size = size
685 709
             object@layout$layout_annotation_legend_left_width = size[1]
686
-            object@layout$layout_index = rbind(object@layout$layout_index, c(4, 1))
710
+            object@layout$layout_index = rbind(object@layout$layout_index, annotation_legend_left = heatmap_list_layout_index("annotation_legend_left"))
687 711
         } else if(annotation_legend_side == "right") {
688 712
             object@annotation_legend_param$padding = unit(c(0, 2, 0, 0), "mm")
689 713
             size = annotation_legend_size(object, legend_list = annotation_legend_list)
690 714
             object@annotation_legend_param$size = size
691 715
             object@layout$layout_annotation_legend_right_width = size[1]
692
-            object@layout$layout_index = rbind(object@layout$layout_index, c(4, 7))
716
+            object@layout$layout_index = rbind(object@layout$layout_index, annotation_legend_right = heatmap_list_layout_index("annotation_legend_right"))
693 717
         }
694 718
         object@layout$graphic_fun_list = c(object@layout$graphic_fun_list, function(object) draw_annotation_legend(object, legend_list = annotation_legend_list))
695 719
     } else {
... ...
@@ -868,6 +892,26 @@ setMethod(f = "draw",
868 892
 })
869 893
 
870 894
 
895
+HEATMAP_LIST_LAYOUT_COLUMN_COMPONENT = 1:7
896
+names(HEATMAP_LIST_LAYOUT_COLUMN_COMPONENT) = c("annotation_legend_top", "heatmap_legend_top", "row_title_top",
897
+    "heatmap_list", "row_title_bottom", "heatmap_legend_bottom", "annotation_legend_bottom")
898
+HEATMAP_LIST_LAYOUT_ROW_COMPONENT = 1:7
899
+names(HEATMAP_LIST_LAYOUT_ROW_COMPONENT) = c("annotation_legend_left", "heatmap_legend_left", "row_title_left", 
900
+    "heatmap_list", "row_title_right", "heatmap_legend_right", "annotation_legend_right")
901
+
902
+heatmap_list_layout_index = function(nm) {
903
+    if(grepl("column", nm)) {
904
+        ind = c(HEATMAP_LIST_LAYOUT_COLUMN_COMPONENT[nm], HEATMAP_LIST_LAYOUT_ROW_COMPONENT["heatmap_list"])
905
+    } else if(grepl("row", nm)) {
906
+        ind = c(HEATMAP_LIST_LAYOUT_COLUMN_COMPONENT["heatmap_list"], HEATMAP_LIST_LAYOUT_ROW_COMPONENT[nm])
907
+    } else if(nm == "heatmap_list") { # heatmap_body
908
+        ind = c(HEATMAP_LIST_LAYOUT_COLUMN_COMPONENT["heatmap_list"], HEATMAP_LIST_LAYOUT_ROW_COMPONENT["heatmap_list"])
909
+    }
910
+    names(ind) = c("layout.pos.row", "layout.pos.col")
911
+    return(ind)
912
+}
913
+
914
+
871 915
 # == title
872 916
 # Width of each heatmap list component
873 917
 #
... ...
@@ -886,17 +930,17 @@ setMethod(f = "draw",
886 930
 #
887 931
 setMethod(f = "component_width",
888 932
     signature = "HeatmapList",
889
-    definition = function(object, k = 1:7) {
890
-
891
-    .single_unit = function(k) {
892
-        if(k == 1) {
893
-            object@layout$layout_annotation_legend_left_width
894
-        } else if(k == 2) {
895
-            object@layout$layout_heatmap_legend_left_width
896
-        } else if(k == 3) {
897
-            object@layout$layout_row_title_left_width
898
-        } else if(k == 4) {
899
-            width = sum(do.call("unit.c", lapply(object@ht_list, function(ht) {
933
+    definition = function(object, k = HEATMAP_LIST_LAYOUT_ROW_COMPONENT) {
934
+
935
+    if(is.numeric(k)) {
936
+        component_name = names(HEATMAP_LIST_LAYOUT_ROW_COMPONENT)[k]
937
+    } else {
938
+        component_name = k
939
+    }
940
+    # this function is used for grid.layout, so null unit is allowed
941
+    .single_unit = function(nm) {
942
+        if(nm == "heatmap_list") {
943
+             width = sum(do.call("unit.c", lapply(object@ht_list, function(ht) {
900 944
                     if(inherits(ht, "Heatmap")) {
901 945
                         ht@heatmap_param$width
902 946
                     } else {
... ...
@@ -908,18 +952,12 @@ setMethod(f = "component_width",
908 952
             } else {
909 953
                 unit(1, "null") 
910 954
             }
911
-        } else if(k == 5) {
912
-            object@layout$layout_row_title_right_width
913
-        } else if(k == 6) {
914
-            object@layout$layout_heatmap_legend_right_width
915
-        } else if(k == 7) {
916
-            object@layout$layout_annotation_legend_right_width
917 955
         } else {
918
-            stop("wrong 'k'")
956
+            object@layout[[paste0("layout_", nm, "_width")]]
919 957
         }
920 958
     }
921
-
922
-    do.call("unit.c", lapply(k, function(i) .single_unit(i)))
959
+    
960
+    do.call("unit.c", lapply(component_name, .single_unit))
923 961
 })
924 962
 
925 963
 # == title
... ...
@@ -937,19 +975,16 @@ setMethod(f = "component_width",
937 975
 #
938 976
 setMethod(f = "component_height",
939 977
     signature = "HeatmapList",
940
-    definition = function(object, k = 1:7) {
941
-
942
-    ht_index = which(sapply(object@ht_list, inherits, "Heatmap"))
943
-    n = length(object@ht_list)
978
+    definition = function(object, k = HEATMAP_LIST_LAYOUT_COLUMN_COMPONENT) {
944 979
 
945
-    .single_unit = function(k) {
946
-        if(k == 1) {
947
-            object@layout$layout_annotation_legend_top_height
948
-        } else if(k == 2) {
949
-            object@layout$layout_heatmap_legend_top_height
950
-        } else if(k == 3) {
951
-            object@layout$layout_column_title_top_height
952
-        } else if(k == 4) {
980
+    if(is.numeric(k)) {
981
+        component_name = names(HEATMAP_LIST_LAYOUT_COLUMN_COMPONENT)[k]
982
+    } else {
983
+        component_name = k
984
+    }
985
+    # this function is used for grid.layout, so null unit is allowed
986
+    .single_unit = function(nm) {
987
+        if(nm == "heatmap_list") {
953 988
             height = max(do.call("unit.c", lapply(object@ht_list, function(ht) {
954 989
                     if(inherits(ht, "Heatmap")) {
955 990
                         ht@heatmap_param$height
... ...
@@ -962,18 +997,12 @@ setMethod(f = "component_height",
962 997
             } else {
963 998
                 unit(1, "null") 
964 999
             }
965
-        } else if(k == 5) {
966
-            object@layout$layout_column_title_bottom_height
967
-        } else if(k == 6) {
968
-            object@layout$layout_heatmap_legend_bottom_height
969
-        } else if(k == 7) {
970
-            object@layout$layout_annotation_legend_bottom_height
971 1000
         } else {
972
-            stop("wrong 'k'")
1001
+            object@layout[[paste0("layout_", nm, "_height")]]
973 1002
         }
974 1003
     }
975 1004
 
976
-    do.call("unit.c", lapply(k, function(i) .single_unit(i)))
1005
+    do.call("unit.c", lapply(component_name, .single_unit))
977 1006
 })