Chapter 5 MAG catalogue

load("data/data.Rdata")

5.1 Genome phylogeny

# Generate the phylum color heatmap
phylum_heatmap <- read_tsv("https://raw.githubusercontent.com/earthhologenome/EHI_taxonomy_colour/main/ehi_phylum_colors.tsv") %>%
    mutate(phylum=str_remove_all(phylum, "p__")) %>%
    right_join(genome_metadata, by=join_by(phylum == phylum)) %>%
    arrange(match(genome, genome_tree$tip.label)) %>%
    dplyr::select(genome,phylum) %>%
    mutate(phylum = factor(phylum, levels = unique(phylum))) %>%
    column_to_rownames(var = "genome")

# Generate Aisa heatmap
aisa_heatmap <- genome_counts_filt  %>%
  pivot_longer(!genome,names_to="sample",values_to="abundance") %>% 
  left_join(sample_metadata,by = join_by(sample == EHI_number)) %>% 
  filter(Transect=="Aisa") %>% 
  group_by(genome) %>% 
  summarise(presence=ifelse(sum(abundance)>0,"present","absent")) %>% 
  column_to_rownames(var="genome")

# Generate Aran heatmap
aran_heatmap <- genome_counts_filt  %>%
  pivot_longer(!genome,names_to="sample",values_to="abundance") %>% 
  left_join(sample_metadata,by = join_by(sample == EHI_number)) %>% 
  filter(Transect=="Aran") %>% 
  group_by(genome) %>% 
  summarise(presence=ifelse(sum(abundance)>0,"present","absent")) %>% 
  column_to_rownames(var="genome")

# Generate Sentein heatmap
sentein_heatmap <- genome_counts_filt  %>%
  pivot_longer(!genome,names_to="sample",values_to="abundance") %>% 
  left_join(sample_metadata,by = join_by(sample == EHI_number)) %>% 
  filter(Transect=="Sentein") %>% 
  group_by(genome) %>% 
  summarise(presence=ifelse(sum(abundance)>0,"present","absent")) %>% 
  column_to_rownames(var="genome")

# Generate Tourmalet heatmap
tourmalet_heatmap <- genome_counts_filt  %>%
  pivot_longer(!genome,names_to="sample",values_to="abundance") %>% 
  left_join(sample_metadata,by = join_by(sample == EHI_number)) %>% 
  filter(Transect=="Tourmalet") %>% 
  group_by(genome) %>% 
  summarise(presence=ifelse(sum(abundance)>0,"present","absent")) %>% 
  column_to_rownames(var="genome")

# Generate prevalence data
prevalence_data <- genome_counts_filt  %>%
  pivot_longer(!genome,names_to="sample",values_to="abundance") %>% 
  left_join(sample_metadata,by = join_by(sample == EHI_number)) %>% 
  group_by(genome,Transect) %>% 
  summarise(presence=ifelse(sum(abundance)>0,1,0)) %>% 
  group_by(genome) %>%
  summarise(prevalence=sum(presence))

# Generate  basal tree
circular_tree <- force.ultrametric(genome_tree, method="extend") %>% # extend to ultrametric for the sake of visualisation
    ggtree(., layout="fan", open.angle=10, size=0.5)
***************************************************************
*                          Note:                              *
*    force.ultrametric does not include a formal method to    *
*    ultrametricize a tree & should only be used to coerce    *
*   a phylogeny that fails is.ultrametric due to rounding --  *
*    not as a substitute for formal rate-smoothing methods.   *
***************************************************************
# Add phylum ring
circular_tree <- gheatmap(circular_tree, phylum_heatmap, offset=0, width=0.05, colnames=FALSE) +
        scale_fill_manual(values=phylum_colors) +
        theme(legend.position = "none", plot.margin = margin(0, 0, 0, 0), panel.margin = margin(0, 0, 0, 0)) +
        new_scale_fill()

# Add Aisa ring
circular_tree <- gheatmap(circular_tree, aisa_heatmap, offset=0.2, width=0.05, colnames=FALSE) +
        scale_fill_manual(values=c("#ffffff","#e5bd5b")) +
        theme(legend.position = "none", plot.margin = margin(0, 0, 0, 0), panel.margin = margin(0, 0, 0, 0)) +
        new_scale_fill()

# Add Aran ring
circular_tree <- gheatmap(circular_tree, aran_heatmap, offset=0.3, width=0.05, colnames=FALSE) +
        scale_fill_manual(values=c("#ffffff","#6b7398")) +
        theme(legend.position = "none", plot.margin = margin(0, 0, 0, 0), panel.margin = margin(0, 0, 0, 0)) +
        new_scale_fill()

# Add Sentein Verde ring
circular_tree <- gheatmap(circular_tree, sentein_heatmap, offset=0.4, width=0.05, colnames=FALSE) +
        scale_fill_manual(values=c("#ffffff","#e2815a")) +
        theme(legend.position = "none", plot.margin = margin(0, 0, 0, 0), panel.margin = margin(0, 0, 0, 0)) +
        new_scale_fill()

# Add Tourmalet ring
circular_tree <- gheatmap(circular_tree, tourmalet_heatmap, offset=0.5, width=0.05, colnames=FALSE) +
        scale_fill_manual(values=c("#ffffff","#876b96")) +
        theme(legend.position = "none", plot.margin = margin(0, 0, 0, 0), panel.margin = margin(0, 0, 0, 0)) +
        new_scale_fill()

# Add prevalence ring
circular_tree <-  circular_tree +
        new_scale_fill() +
        scale_fill_manual(values = "#cccccc") +
        geom_fruit(
             data=prevalence_data,
             geom=geom_bar,
             mapping = aes(x=prevalence, y=genome),
                 offset = 0.4,
                 orientation="y",
         stat="identity")

# Flush color scale to enable a new color scheme in the next ring
circular_tree <- circular_tree + new_scale_fill()

# Add completeness ring
circular_tree <- circular_tree +
        new_scale_fill() +
        scale_fill_gradient(low = "#d1f4ba", high = "#f4baba") +
        geom_fruit(
                data=genome_metadata,
                geom=geom_bar,
                mapping = aes(x=completeness, y=genome, fill=contamination),
                offset = 0.55,
                orientation="y",
              stat="identity")

# Add genome-size ring
circular_tree <-  circular_tree +
        new_scale_fill() +
        scale_fill_manual(values = "#cccccc") +
        geom_fruit(
             data=genome_metadata,
             geom=geom_bar,
             mapping = aes(x=length, y=genome),
                 offset = 0.05,
                 orientation="y",
         stat="identity")

# Add text
circular_tree <-  circular_tree +
        annotate('text', x=2.8, y=0, label='             Phylum', family='arial', size=3.5) +
        annotate('text', x=3.1, y=0, label='                Location', family='arial', size=3.5) +
        annotate('text', x=3.8, y=0, label='                               Location prevalence', family='arial', size=3.5) +
        annotate('text', x=6.0, y=0, label='                         Genome quality', family='arial',size=3.5)+
        annotate('text', x=6.4, y=0, label='                     Genome size', family='arial', size=3.5)

#Plot circular tree
circular_tree %>% open_tree(30) %>% rotate_tree(90)

5.2 Genome quality

genome_metadata %>% 
    summarise(completeness_mean=mean(completeness) %>% round(2) %>% as.character(), 
              completeness_sd=sd(completeness) %>% round(2) %>% as.character(), 
              contamination_mean=mean(contamination) %>% round(2), 
              contamination_sd=sd(contamination) %>% round(2)) %>%
    unite("Completeness",completeness_mean, completeness_sd, sep = " ± ", remove = TRUE) %>%
    unite("Contamination",contamination_mean, contamination_sd, sep = " ± ", remove = TRUE) %>%
    tt()
Completeness Contamination
79.99 ± 15.48 2.19 ± 1.94
#Generate quality biplot
genome_biplot <- genome_metadata %>%
  select(c(genome,domain,phylum,completeness,contamination,length)) %>%
  arrange(match(genome, rev(genome_tree$tip.label))) %>% #sort MAGs according to phylogenetic tree
  ggplot(aes(x=completeness,y=contamination,size=length,color=phylum)) +
              geom_point(alpha=0.7) +
                    ylim(c(10,0)) +
                    scale_color_manual(values=phylum_colors) +
                    labs(y= "Contamination", x = "Completeness") +
                    theme_classic() +
                    theme(legend.position = "none")

#Generate contamination boxplot
genome_contamination <- genome_metadata %>%
            ggplot(aes(y=contamination)) +
                    ylim(c(10,0)) +
                    geom_boxplot(colour = "#999999", fill="#cccccc") +
                    theme_void() +
                    theme(legend.position = "none",
                        axis.title.x = element_blank(),
                        axis.title.y = element_blank(),
                        axis.text.y=element_blank(),
                        axis.ticks.y=element_blank(),
                        axis.text.x=element_blank(),
                        axis.ticks.x=element_blank(),
                        plot.margin = unit(c(0, 0, 0.40, 0),"inches")) #add bottom-margin (top, right, bottom, left)

#Generate completeness boxplot
genome_completeness <- genome_metadata %>%
        ggplot(aes(x=completeness)) +
                xlim(c(50,100)) +
                geom_boxplot(colour = "#999999", fill="#cccccc") +
                theme_void() +
                theme(legend.position = "none",
                    axis.title.x = element_blank(),
                    axis.title.y = element_blank(),
                    axis.text.y=element_blank(),
                    axis.ticks.y=element_blank(),
                    axis.text.x=element_blank(),
                    axis.ticks.x=element_blank(),
                    plot.margin = unit(c(0, 0, 0, 0.50),"inches")) #add left-margin (top, right, bottom, left)

#Render composite figure
grid.arrange(grobs = list(genome_completeness,genome_biplot,genome_contamination),
        layout_matrix = rbind(c(1,1,1,1,1,1,1,1,1,1,1,4),
                              c(2,2,2,2,2,2,2,2,2,2,2,3),
                              c(2,2,2,2,2,2,2,2,2,2,2,3),
                              c(2,2,2,2,2,2,2,2,2,2,2,3),
                              c(2,2,2,2,2,2,2,2,2,2,2,3),
                              c(2,2,2,2,2,2,2,2,2,2,2,3),
                              c(2,2,2,2,2,2,2,2,2,2,2,3),
                              c(2,2,2,2,2,2,2,2,2,2,2,3),
                              c(2,2,2,2,2,2,2,2,2,2,2,3),
                              c(2,2,2,2,2,2,2,2,2,2,2,3),
                              c(2,2,2,2,2,2,2,2,2,2,2,3),
                              c(2,2,2,2,2,2,2,2,2,2,2,3)))

5.3 Functional overview

# Aggregate basal GIFT into elements
function_table <- genome_gifts %>%
    to.elements(., GIFT_db)

# Generate  basal tree
function_tree <- force.ultrametric(genome_tree, method="extend") %>%
                ggtree(., size = 0.3) 
***************************************************************
*                          Note:                              *
*    force.ultrametric does not include a formal method to    *
*    ultrametricize a tree & should only be used to coerce    *
*   a phylogeny that fails is.ultrametric due to rounding --  *
*    not as a substitute for formal rate-smoothing methods.   *
***************************************************************
#Add phylum colors next to the tree tips
function_tree <- gheatmap(function_tree, phylum_heatmap, offset=0, width=0.1, colnames=FALSE) +
            scale_fill_manual(values=phylum_colors) +
            labs(fill="Phylum")

#Reset fill scale to use a different colour profile in the heatmap
function_tree <- function_tree + new_scale_fill()

#Add functions heatmap
function_tree <- gheatmap(function_tree, function_table, offset=0.5, width=3.5, colnames=FALSE) +
            vexpand(.08) +
            coord_cartesian(clip = "off") +
            scale_fill_gradient(low = "#f4f4f4", high = "steelblue", na.value="white") +
            labs(fill="GIFT")

#Reset fill scale to use a different colour profile in the heatmap
function_tree <- function_tree + new_scale_fill()

# Add completeness barplots
function_tree <- function_tree +
            geom_fruit(data=genome_metadata,
            geom=geom_bar,
            grid.params=list(axis="x", text.size=2, nbreak = 1),
            axis.params=list(vline=TRUE),
            mapping = aes(x=length, y=genome, fill=completeness),
                 offset = 3.8,
                 orientation="y",
                 stat="identity") +
            scale_fill_gradient(low = "#cf8888", high = "#a2cc87") +
            labs(fill="Genome\ncompleteness")

function_tree

5.4 Functional ordination

# Generate the tSNE ordination
tSNE_function <- Rtsne(X=function_table, dims = 2, check_duplicates = FALSE)

# Plot the ordination
function_ordination <- tSNE_function$Y %>%
                as.data.frame() %>%
                mutate(genome=rownames(function_table)) %>%
                inner_join(genome_metadata, by="genome") %>%
                rename(tSNE1="V1", tSNE2="V2") %>%
                select(genome,phylum,tSNE1,tSNE2, length) %>%
                ggplot(aes(x = tSNE1, y = tSNE2, color = phylum, size=length))+
                            geom_point(shape=16, alpha=0.7) +
                            scale_color_manual(values=phylum_colors) +
                            theme_minimal() +
                labs(color="Phylum", size="Genome size") +
                guides(color = guide_legend(override.aes = list(size = 5))) # enlarge Phylum dots in legend

function_ordination

5.5 MAGs shared across transects

genome_counts_rel <- genome_counts_filt %>%
  mutate_at(vars(-genome),~./sum(.)) %>%
  column_to_rownames(., "genome")
genome_counts_rel_pa=1*(genome_counts_rel>0)

table_upset_analysis_cont=t(aggregate(t(genome_counts_rel_pa),by=list(sample_metadata$Transect),FUN=sum)[,-1])
colnames(table_upset_analysis_cont)=levels(as.factor(sample_metadata$Transect))
table_upset_analysis=(table_upset_analysis_cont>0)*1
table_upset_analysis=data.frame(table_upset_analysis)
table_upset_analysis=apply(table_upset_analysis,2,as.integer)
rownames(table_upset_analysis) <- rownames(genome_counts_rel_pa)

locationcolors=c("#e5bd5b", "#6b7398","#e2815a", "#876b96")
upset(as.data.frame(table_upset_analysis),
      keep.order = T,
      sets = rev(c("Aisa","Aran","Sentein","Tourmalet")),
      sets.bar.color= rev(locationcolors),
      mb.ratio = c(0.55, 0.45), order.by = "freq")