-
Notifications
You must be signed in to change notification settings - Fork 24
/
15-other-tricks.Rmd
109 lines (90 loc) · 4.4 KB
/
15-other-tricks.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# Other Tricks {#other-tricks}
## Set the same cell size for different heatmaps with different dimensions
Assume you have a list of heatmaps/oncoPrints that you want to save as different e.g. png or pdf files, one
thing you might want to do is to make the size of each grid/cell in the heatmap identical across
heatmaps, thus, you need to calculate the size of png/pdf file according to the number of rows or
columns in the heatmap. In the heatmap generated by **ComplexHeatmap**, all the heatmap components
have absolute size and only the size of the heatmap body (or the size of the cells) is changable (or
in other words, if you change the size of the final graphic device, e.g. by draging the graphics
window if you plot in, only the size of the heatmap body is adjusted), which means, the size of the
whole plot is linearly related to the number of rows or columns in the heatmap. This implies we can
actually fit a linear model `y = a*x + b` where e.g. `y` is the height of the whole plot and `x` is
the number of rows.
In following example, we simply demonstrate how to establish the relation between the plot height
and the number of rows in the heatmap. We first define a function which generates a
10-column matrix with specific number of rows. Note the values in the matrix is of no importance
in this demonstration.
```{r}
random_mat = function(nr) {
m = matrix(rnorm(10*nr), nc = 10)
colnames(m) = letters[1:10]
return(m)
}
```
Since the relation is absolutely linear, we only need to test two heatmaps with different number of
rows where the height of a single row is `unit(5, "mm")`. In the heatmap, there are also column title,
column dendrogram, column annotation and the column names.
There are several things that needs to be noted in following code:
1. The heatmap object should be returned by `draw()` because the layout of the heatmap is calculated only
after the execution of `draw()`.
2. `component_height()` returns a vector of units which correspond to the height of all heatmap components
from top to bottom in the heatmap. (`component_width()` returns the width of heatmap components).
3. When calculating `ht_height`, we add `unit(4, "mm")` because on top and bottom of the final plot,
there are `2mm` white borders.
4. `ht_height` needs to be converted to a simple unit in `cm` or `inch`.
In following, `y` contains values which are measured in `inch` unit.
```{r, eval = FALSE}
y = NULL
for(nr in c(10, 20)) {
ht = draw(Heatmap(random_mat(nr), height = unit(5, "mm")*nr,
column_title = "foo", # one line text
top_annotation = HeatmapAnnotation(bar = 1:10)))
ht_height = sum(component_height(ht)) + unit(4, "mm")
ht_height = convertHeight(ht_height, "inch", valueOnly = TRUE)
y = c(y, ht_height)
}
```
```{r, echo = FALSE}
pdf(NULL)
y = NULL
for(nr in c(10, 20)) {
ht = draw(Heatmap(random_mat(nr), height = unit(5, "mm")*nr,
column_title = "foo",
top_annotation = HeatmapAnnotation(bar = 1:10)))
ht_height = sum(component_height(ht)) + unit(4, "mm")
ht_height = convertHeight(ht_height, "inch", valueOnly = TRUE)
y = c(y, ht_height)
}
invisible(dev.off())
```
Then we can fit a linear relation between `y` and the number of rows:
```{r}
x = c(10, 20)
lm(y ~ x)
```
This means the relation between the number of rows `x` and the height of the plot `y` is: `y = 0.1969*x + 1.3150`.
You can test whether the height of single rows are the same for heatmaps with different rows by following code.
Note all the heatmap configuations should be the same as the ones you prepare `y`.
```{r, eval = FALSE}
for(nr in c(10, 20)) {
png(paste0("test_heatmap_nr_", nr, ".png"), width = 5, height = 0.1969*nr + 1.3150,
units = "in", res = 100)
draw(Heatmap(random_mat(nr), height = unit(5, "mm")*nr,
column_title = "foo", # column title can be any one-line string
top_annotation = HeatmapAnnotation(bar = 1:10)))
dev.off()
}
```
```{r, echo = FALSE}
fit = lm(y ~ x)
a = coefficients(fit)[2]
b = coefficients(fit)[1]
```
```{r, fig.height = a*10+b, fig.width = 5, echo = FALSE}
draw(Heatmap(random_mat(10), height = unit(5, "mm")*10, column_title = "10 rows, each row is 5mm",
top_annotation = HeatmapAnnotation(bar = 1:10)))
```
```{r, fig.height = a*20+b, fig.width = 5, echo = FALSE}
draw(Heatmap(random_mat(20), height = unit(5, "mm")*20, column_title = "20 rows, each row is 5mm",
top_annotation = HeatmapAnnotation(bar = 1:10)))
```