8 Annotating Tree with Silhouette Images and Sub-plots

8.1 Annotating Tree with Images

We usually use text to label taxa, i.e. displaying taxa names. If the text is image file name (either local or remote), ggtree can read the image and display the actual image as label of the taxa (Figure 8.1). The geom_tiplab and geom_nodelab are capable to render silhouette image by internally called ggimage package.

Online tools such as iTOL (Letunic and Bork 2007) and EvolView (He et al. 2016) support displaying subplots on phylogenetic tree. However only bar and pie charts are supported by these tools. Users may want to visualize node-associated data with other visualization methods, such as violin plot (Grubaugh et al. 2017), venn diagram (Lott et al. 2015), sequence logo etc, and display them on the tree. In ggtree, all kinds of subplots are supported as we can export all subplots to image files and use them to label corresponding nodes on the tree.


nwk <- "((((bufonidae, dendrobatidae), ceratophryidae), (centrolenidae, leptodactylidae)), hylidae);"

x = read.tree(text = nwk)
ggtree(x) + xlim(NA, 7) + ylim(NA, 6.2) +
    geom_tiplab(aes(image=paste0("img/frogs/", label, '.jpg')), 
                geom="image", offset=2, align=2, size=.2)  + 
    geom_tiplab(geom='label', offset=1, hjust=.5) + 
    geom_image(x=.8, y=5.5, image="img/frogs/frog.jpg", size=.2)
Labelling taxa with images.

Figure 8.1: Labelling taxa with images.

8.2 Annotating Tree with Phylopic

Phylopic contains more than 3200 silhouettes and covers almost all life forms. ggtree also supports using phylopic11 to annotate the tree. Most importantly, we can color the image using numerical/categorical variable.

ggimage package supports querying phylopic uid from scientific name, which is very handy for annotating tree with phylopic.

newick <- "((Pongo_abelii,(Gorilla_gorilla_gorilla,(Pan_paniscus,Pan_troglodytes)Pan,Homo_sapiens)Homininae)Hominidae,Nomascus_leucogenys)Hominoidea;"

tree <- read.tree(text=newick)

d <- ggimage::phylopic_uid(tree$tip.label)
d$body_mass = c(52, 114, 47, 45, 58, 6)

p <- ggtree(tree) %<+% d + 
  geom_tiplab(aes(image=uid, colour=body_mass), geom="phylopic", offset=2.5) +
  geom_tiplab(aes(label=label), offset = .2) + xlim(NA, 7) +
Labelling taxa with phylopic images. ggtree will automatically download phylopic figures by querying provided UID. The figures can be colored using numerical or categorical values.

Figure 8.2: Labelling taxa with phylopic images. ggtree will automatically download phylopic figures by querying provided UID. The figures can be colored using numerical or categorical values.

8.3 Annotating Tree with Sub-plots

ggtree provides a layer, geom_inset, for adding subplots to a phylogenetic tree. The input is a named list of ggplot graphic objects (can be any kind of charts). These objects should named by node numbers. Users can also use ggplotify to convert plots that generated by other functions (even implemented by base graphics) to ggplot objects, which can then be used in geom_inset. To facilitate adding bar and pie charts (e.g. summarized stats of results from ancestral reconstruction) to phylogenetic tree, ggtree provides nodepie and nodebar functions to create a list of pie or bar charts.

8.3.1 Annotate with bar charts

x <- getStates(anoletree,"tips")
tree <- anoletree

cols <- setNames(palette()[1:length(unique(x))],sort(unique(x)))
fitER <- ape::ace(x,tree,model="ER",type="discrete")
ancstats <- as.data.frame(fitER$lik.anc)
ancstats$node <- 1:tree$Nnode+Ntip(tree)

## cols parameter indicate which columns store stats
bars <- nodebar(ancstats, cols=1:6)
bars <- lapply(bars, function(g) g+scale_fill_manual(values = cols))

tree2 <- full_join(tree, data.frame(label = names(x), stat = x ), by = 'label')
p <- ggtree(tree2) + geom_tiplab() +
    geom_tippoint(aes(color = stat)) + 
    scale_color_manual(values = cols) +
    theme(legend.position = "right") + 
    xlim(NA, 8)
p + geom_inset(bars, width = .08, height = .05, x = "branch") 
Annotate internal nodes with barplots.

Figure 8.3: Annotate internal nodes with barplots.

The x position can be one of ‘node’ or ‘branch’ and can be adjusted by the parameter hjust and vjust for horizontal and vertical adjustment respectively.

8.3.2 Annotate with pie charts

Similarly, users can use nodepie function to generate a list of pie charts and place these charts to annotate corresponding nodes. Both nodebar and nodepie accepts parameter alpha to allow transparency.

pies <- nodepie(ancstats, cols = 1:6)
pies <- lapply(pies, function(g) g+scale_fill_manual(values = cols))
p + geom_inset(pies, width = .1, height = .1) 
Annotate internal nodes with pie plots.

Figure 8.4: Annotate internal nodes with pie plots.

8.3.3 Annotate with other types of charts

The inset function accepts a list of ggplot graphic objects and these input objects are not restricted to pie or bar charts. They can be any kinds of charts and hybrid of these charts.

pies_and_bars <- pies
i <- sample(length(pies), 20)
pies_and_bars[i] <- bars[i]
p + geom_inset(pies_and_bars, width=.08, height=.05)
Annotate internal nodes with different types of subplots (bar and pie).

Figure 8.5: Annotate internal nodes with different types of subplots (bar and pie).

8.4 Have Fun with Phylomoji

#phylomoji is fun and it is internally supported by ggtree since 201512.

Here, we will use ggtree to recreate the figure:


tt = '((snail,mushroom),(((sunflower,evergreen_tree),leaves),green_salad));'
tree = read.tree(text = tt)
d <- data.frame(label = c('snail','mushroom', 'sunflower',
                          'evergreen_tree','leaves', 'green_salad'),
                group = c('animal', 'fungi', 'flowering plant',
                          'conifers', 'ferns', 'mosses'))

ggtree(tree, linetype = "dashed", size=1, color='firebrick') %<+% d + 
  xlim(0, 4.5) + ylim(0.5, 6.5) +
  geom_tiplab(parse="emoji", size=15, vjust=.25) +
  geom_tiplab(aes(label = group), geom="label", x=3.5, hjust=.5)
Parsing label as emoji. Text (e.g. node or tip labels) can be parsed as emoji.

Figure 8.6: Parsing label as emoji. Text (e.g. node or tip labels) can be parsed as emoji.

Note that the output may depends on what emoji fonts installed in your system13.

With ggtree, it is easy to generate phylomoji. The emoji is treated as text, like abc. We can use emojis to label taxa, clade, color and rotate emoji with any given color and angle. This functionality is internally supported by the emojifont package.

8.4.1 Emoji in circular/fan layout tree

p <- ggtree(tree, layout = "circular", size=1) +  
  geom_tiplab(parse="emoji", size=10, vjust=.25)

## fan layout  
p2 <- open_tree(p, angle=200) 

p2 %>% rotate_tree(-90)
Phylomoji in cirular and fan layouts.

Figure 8.7: Phylomoji in cirular and fan layouts.

Another example using ggtree and emojifont to produce phylogeny of plant emojis can be found on https://github.com/ghuertaramos/PlantPhylomoji.

8.4.2 Emoji to label clades

tr <- rtree(30)

ggtree(tr) + xlim(NA, 5.2) +
    geom_cladelabel(node=41, label="chicken", parse="emoji",
                    fontsize=12, align=TRUE, colour="firebrick") +
    geom_cladelabel(node=53, label="duck", parse="emoji",
                    fontsize=12, align=TRUE, colour="steelblue") +
    geom_cladelabel(node=48, label="family", parse="emoji",
                    fontsize=12, align=TRUE, colour="darkkhaki")
Emoji to label clades.

Figure 8.8: Emoji to label clades.

8.4.3 Apple Color Emoji

Although R’s graphical devices don’t support AppleColorEmoji font, it’s still possible to use it. We can export the plot to svg file and render it in Safari.

tree_text <- "(((((cow, (whale, dolphin)), (pig2, boar)), camel), fish), seedling);"
x <- read.tree(text=tree_text)
p <-  ggtree(x, size=2) + geom_tiplab(size=20, parse='emoji') +
    xlim(NA, 7) + ylim(NA, 8.5) +
                  color="firebrick", alpha = .3, size=Inf)

ps = grid.export("emoji.svg", addClass=T)
Use Apple Color Emoji in ggtree.

Figure 8.9: Use Apple Color Emoji in ggtree.

8.4.4 Phylomoji in ASCII art

This is also possible, please refer to Appendix D for details.