Bulk RNA-seq Analysis Report

Grieco Mariachiara

30 September 2021

Introduction

In this report, a bulk-RNA seq analysis is performed comparing samples from colon, heart and liver Three samples from each tissue are retrieved from Recount2 and are analyzed for finding differentially expressed genes that characterize one tissue with respect to the other ones.

# Importing libraries --------------
library(limma)
library(edgeR)
library(DESeq2)
library(recount)
library(dplyr)
library(ggplot2)
library(reshape2)
library(RColorBrewer)
library(viridis)
library(gridExtra)
library(grid)
library(org.Hs.eg.db)
library(clusterProfiler)

Loading data

Data for each tissue are in the “Ranged Summarized Experiment” format of Recount2.

load(paste0(wd,"rse_gene_liver_9_scaled.Rdata"))
liver <- rse
liver_counts <- as.data.frame(assay(liver)[,2:4])
liver_sample_id <- colnames(liver_counts)
colnames(liver_counts) <- c('rep2','rep3','rep4')
liver_coldata <-as.data.frame(liver@colData)
liver_gtex_sampid <- liver_coldata$sampid[2:4]

load(paste0(wd,"rse_gene_heart_6_scaled.Rdata"))
heart <- rse
heart_counts <- as.data.frame(assay(heart)[,c(9,10,1)])
heart_sample_id <- colnames(heart_counts)
colnames(heart_counts) <- c('rep9','rep10','rep1')
heart_coldata <-as.data.frame(heart@colData)
heart_gtex_sampid <- heart_coldata$sampid[c(9,10,1)]

load(paste0(wd,"rse_gene_colon_7_scaled.Rdata"))
colon <- rse
colon_counts <- as.data.frame(assay(colon)[,2:4])
colon_sample_id <- colnames(colon_counts)
colnames(colon_counts) <- c('rep2','rep3','rep4')
colon_coldata <-as.data.frame(colon@colData)
colon_gtex_sampid <- colon_coldata$sampid[2:4]

Preprocessing

From the tables, we will:

  • select the columns we are interested in
  • remove all genes with length < 200
  • remove all mitochondrial genes
  • merge them into a single count table for subsequent analyses

Here we check that counts have already been normalized/scaled (to 40M reads per column) (e.g., check that the number of reads is less than or equal to 40 million)

colSums(liver_counts)/ 1e6
##     rep2     rep3     rep4 
## 36.16472 34.51705 39.72422
colSums(heart_counts) / 1e6
##     rep9    rep10     rep1 
## 39.51230 39.50502 38.78892
colSums(colon_counts)/ 1e6
##     rep2     rep3     rep4 
## 38.31695 36.18829 38.61814

Now we remove genes shorter than 200 bp. rowData is a dataframe object describing the rows. Row names, if present, become the row names of the SummarizedExperiment object. In the rowData are included: gene_id, bp_length and symbol (if present). Row names are the gene_id.

# The number of rows of the DataFrame must equal the number of rows of the matrices in assays.
# We can check this by doing:
dim(rowData(liver))
## [1] 58037     3
dim(assay(liver))
## [1] 58037    10

In this case, since all row data are identical – they represent the Gencode V25 comprehensive annotation - we can just use one of the tree to identify the short genes and the mt ones, to carry out then the filtering.

shortgenes <- as.data.frame(subset(rowData(liver), bp_length < 200))
dim(shortgenes)
## [1] 7341    3

Selecting mt genes: If a gene is both “short” and on the MT DNA, it has to be considered among the “short” genes and not a MT gene.

mt_genes <- as.data.frame(subset(rowRanges(liver), seqnames == 'chrM' & bp_length >= 200))
dim(mt_genes)
## [1] 15  8

Just for check, we can ensure that also in the heart and colon rowData the number of short genes is equal to the liver one.

dim(subset(rowData(heart), bp_length < 200))[1]
## [1] 7341
#colon
dim(subset(rowData(colon), bp_length < 200))[1]
## [1] 7341

We can create a function to find the short and the mitochondrial genes previosly selected, that can be applied on the tree datasets we have.

find_short <- function(count_table, short) {
  counts_short <- count_table %>% filter(row.names(count_table) %in% short$gene_id)
  return(counts_short)
}

find_mt <- function(count_table, mt) {
  counts_mt <- count_table %>% filter(row.names(count_table) %in% mt$gene_id)
  return(counts_mt)
}

  
liver_shortgenes <- find_short(liver_counts,shortgenes)
liver_mtgenes <- find_mt(liver_counts, mt_genes)

heart_shortgenes <- find_short(heart_counts,shortgenes)
heart_mtgenes <- find_mt(heart_counts, mt_genes)

colon_shortgenes <- find_short(colon_counts,shortgenes)
colon_mtgenes <- find_mt(colon_counts, mt_genes)


liver_counts_table <- data.frame('tissue' = 'liver',
                           'column' = colnames(liver_counts),
                           'tot_short_genes' = rep(dim(shortgenes)[1],3),
                           'tot_mt_genes' = rep(dim(mt_genes)[1],3),
                           'tot_reads' = colSums(liver_counts),
                           'tot_reads_short_genes' = colSums(liver_shortgenes),
                           'perc_reads_short_genes' = round((colSums(liver_shortgenes)/colSums(liver_counts))*100,2),
                           'tot_reads_mt_genes' = colSums(liver_mtgenes),
                           'perc_reads_mt_genes' = round((colSums(liver_mtgenes)/colSums(liver_counts))*100,2)
)

#heart 
heart_counts_table <- data.frame('tissue' = 'heart',
                           'column' = colnames(heart_counts),
                           'tot_short_genes' = rep(dim(shortgenes)[1],3),
                           'tot_mt_genes' = rep(dim(mt_genes)[1],3),
                           'tot_reads' = colSums(heart_counts),
                           'tot_reads_short_genes' = colSums(heart_shortgenes),
                           'perc_reads_short_genes' = round((colSums(heart_shortgenes)/colSums(heart_counts))*100,2),
                           'tot_reads_mt_genes' = colSums(heart_mtgenes),
                           'perc_reads_mt_genes' = round((colSums(heart_mtgenes)/colSums(heart_counts))*100,2)
                           
)

#colon
colon_counts_table <- data.frame('tissue' = 'colon',
                           'column' = colnames(colon_counts),
                           'tot_short_genes' = rep(dim(shortgenes)[1],3),
                           'tot_mt_genes' = rep(dim(mt_genes)[1],3),
                           'tot_reads' = colSums(colon_counts),
                           'tot_reads_short_genes' = colSums(colon_shortgenes),
                           'perc_reads_short_genes' = round((colSums(colon_shortgenes)/colSums(colon_counts))*100,2),
                           'tot_reads_mt_genes' = colSums(colon_mtgenes),
                           'perc_reads_mt_genes' = round((colSums(colon_mtgenes)/colSums(colon_counts))*100,2)
                           
)


counts_table <- rbind(liver_counts_table,heart_counts_table,colon_counts_table)

Now we create a new counts table containing the counts of NO short and NO mt genes for each rep in each tissue for subsequential analysis. The resulting total number of gene to keep should be equal to 58037 (tot genes) -7341 (short) -15 (mt) = 50681

liver_count_filtered <- liver_counts %>% filter(!row.names(liver_counts) %in% shortgenes$gene_id) 
liver_count_filtered <- liver_count_filtered %>% filter(!row.names(liver_count_filtered) %in% mt_genes$gene_id) 

heart_count_filtered <- heart_counts %>% filter(!row.names(heart_counts) %in% shortgenes$gene_id) 
heart_count_filtered <- heart_count_filtered %>% filter(!row.names(heart_count_filtered) %in% mt_genes$gene_id) 

colon_count_filtered <- colon_counts %>% filter(!row.names(colon_counts) %in% shortgenes$gene_id) 
colon_count_filtered <- colon_count_filtered %>% filter(!row.names(colon_count_filtered) %in% mt_genes$gene_id) 

counts <- cbind(liver_count_filtered, heart_count_filtered, colon_count_filtered)
colnames(counts) <- c('liver2','liver3','liver4',
                      'heart9','heart10','heart1',
                      'colon2','colon3','colon4')

DEG analysis using EdgeR

The DEG analysis will be performed using EdgeR. Firstly, the count table needs to be converted into a DGEList object, which contains all the data stored in a better way for usage with edgeR and allows to subsequently add further data derived from the following steps of the analysis itself. Then, we will set the design matrix.

de_object <- DGEList(counts = counts)

Now, we have to label the samples:

tissue <- factor(c(rep('liver',3),rep('heart',3),rep('colon',3)),levels = c('liver','heart','colon'))
de_object$samples$group <- tissue
table(rowSums(de_object$counts==0)==9)
## 
## FALSE  TRUE 
## 41248  9433

Remove altogether all genes with low or zero counts.

exprs2keep <- filterByExpr(de_object, group=tissue)
de_object_filtered <- de_object[exprs2keep,, keep.lib.sizes=FALSE]
dim(de_object)
## [1] 50681     9
dim(de_object_filtered)
## [1] 23454     9

Store in a vector the log of the counts per million before normalization with the “cpm” function:

logcpm_no_norm <- as.data.frame(cpm(de_object_filtered, log=TRUE))
melt_logcpm_no_norm <- melt(logcpm_no_norm)
colnames(melt_logcpm_no_norm) <- c('sample','log2_no_norm_count')

melt_logcpm_no_norm_liver <- melt(logcpm_no_norm[,1:3])
colnames(melt_logcpm_no_norm_liver) <- c('sample','log2_no_norm_count')
melt_logcpm_no_norm_liver$tissue <- 'liver'

melt_logcpm_no_norm_heart <- melt(logcpm_no_norm[,4:6])
colnames(melt_logcpm_no_norm_heart) <- c('sample','log2_no_norm_count')
melt_logcpm_no_norm_heart$tissue <- 'heart'

melt_logcpm_no_norm_colon <- melt(logcpm_no_norm[,7:9])
colnames(melt_logcpm_no_norm_colon) <- c('sample','log2_no_norm_count')
melt_logcpm_no_norm_colon$tissue <- 'colon'

melt_logcpm_no_norm_tissue <- rbind(melt_logcpm_no_norm_liver,
                                 melt_logcpm_no_norm_heart,
                                 melt_logcpm_no_norm_colon)
melt_logcpm_no_norm_tissue$tissue <- factor(melt_logcpm_no_norm_tissue$tissue,
                                         levels = c('liver','heart','colon'))
#This is the palette used to plot the three tissue in all downstream analysis
mypalette <- brewer.pal(8,'Set3')[c(3,4,7)]
ggplot(melt_logcpm_no_norm_tissue, aes(x=sample, y = log2_no_norm_count, fill = tissue)) + 
  geom_boxplot(outlier.shape = NA, notch = TRUE) +
  scale_fill_manual(values = mypalette,
                    name = 'Tissue',
                    labels = c('Liver','Heart','Colon')) +
  scale_x_discrete(labels = c(liver_sample_id,heart_sample_id,colon_sample_id)) +
  xlab('samples') + ylab('log2(counts)') +
  ggtitle('Not normalized counts') +
  theme_bw()

TMM normalization

TMM normalization is the default method used by edgeR to normalize data, based on a trimmed scaling factor for each column (sample).

de_object_normalized <- calcNormFactors(de_object_filtered, method = "TMM")

log2CPM

The read counts are again stored as the log(CPM).

logcpm_norm <- as.data.frame(cpm(de_object_normalized, log=TRUE))

melt_logcpm_norm <- melt(logcpm_norm)
colnames(melt_logcpm_norm) <- c('sample','log2_norm_count')

melt_logcpm_norm_liver <- melt(logcpm_norm[,1:3])
colnames(melt_logcpm_norm_liver) <- c('sample','log2_norm_count')
melt_logcpm_norm_liver$tissue <- 'liver'

melt_logcpm_norm_heart <- melt(logcpm_norm[,4:6])
colnames(melt_logcpm_norm_heart) <- c('sample','log2_norm_count')
melt_logcpm_norm_heart$tissue <- 'heart'

melt_logcpm_norm_colon <- melt(logcpm_norm[,7:9])
colnames(melt_logcpm_norm_colon) <- c('sample','log2_norm_count')
melt_logcpm_norm_colon$tissue <- 'colon'

melt_logcpm_norm_tissue <- rbind(melt_logcpm_norm_liver,
                                 melt_logcpm_norm_heart,
                                 melt_logcpm_norm_colon)
melt_logcpm_norm_tissue$tissue <- factor(melt_logcpm_norm_tissue$tissue,
                                         levels = c('liver','heart','colon'))
ggplot(melt_logcpm_norm_tissue, aes(x=sample, y = log2_norm_count, fill = tissue)) + 
  geom_boxplot(outlier.shape = NA, notch = TRUE) +
  scale_fill_manual(values = mypalette,
                    name = 'Tissue',
                    labels = c('Liver','Heart','Colon')) +
  scale_x_discrete(labels = c(liver_sample_id,heart_sample_id,colon_sample_id)) +
  xlab('samples') + ylab('log2(normalized_counts)') +
  theme_bw()

Experimental design

When we set the experimental design we can use the intercept in the linear model to specify a reference condition. In this case, the tissue compared are different and there is no a reference condition of one with respect to the others, so no intercept is used in the linear model. The features in the model are the tissue to which the replicates belong and are selected as retrieved in building the dataset for this analysis: liver, heart and colon.

design <- model.matrix(~0 + group, data=de_object_normalized$samples)
colnames(design) <- levels(de_object_normalized$samples$group)
design
##         liver heart colon
## liver2      1     0     0
## liver3      1     0     0
## liver4      1     0     0
## heart9      0     1     0
## heart10     0     1     0
## heart1      0     1     0
## colon2      0     0     1
## colon3      0     0     1
## colon4      0     0     1
## attr(,"assign")
## [1] 1 1 1
## attr(,"contrasts")
## attr(,"contrasts")$group
## [1] "contr.treatment"

Exploratory Analysis

edgeR contains a function plotMDS, which operates on a DGEList object and generates a two-dimensional MDS representation of the samples. The default distance between two samples can be interpreted as the “typical” log fold change between the two samples, for the genes that are most different between them (by default, the top 500 genes, but this can be modified as shown below).

MDS

plotMDS(logcpm_norm, 
        labels = c(liver_sample_id,heart_sample_id,colon_sample_id), 
        col = rep(mypalette, each = 3),
        cex = 0.85,
        xlim = c(-8,5),
        main = 'MDS of log2(CPM) using log fold change as distance')
legend(-8, 3.5, legend = c("Liver", "Heart", "Colon"), fill = mypalette)

PCA plot

plotMDS(logcpm_norm, 
        labels = c(liver_sample_id,heart_sample_id,colon_sample_id), 
        col = rep(mypalette, each = 3),
        cex = 0.85,
        xlim = c(-8,5),
        main = 'PCA of log2(CPM) using log fold change as distance',
        gene.selection = 'common')
legend(-8, 2.5, legend = c("Liver", "Heart", "Colon"), fill = mypalette)

We can also perform MDS on manually calculated distances, using the R function cmdscale and the Euclidean distance as distance.

sample_dist <- as.matrix(dist(t(logcpm_norm)))
mds <- data.frame(cmdscale(sample_dist))
mds$tissue <- tissue

p <- ggplot(mds, aes(X1,X2,color=tissue,shape=tissue)) + 
  geom_point(size=4) +
  scale_color_manual(values = mypalette,
                    name = 'Tissue',
                    labels = c('Liver','Heart','Colon'))+
  scale_shape_manual(values = c(17,18,19),
                     name = 'Tissue',
                    labels = c('Liver','Heart','Colon')) +
  theme_bw()

grid.arrange(textGrob('MDS of log2(CPM) using Euclidean distance as distance',
                      gp = gpar(fontsize = 1.5*10, fontface = "bold")),
             p, 
             heights = c(0.1, 1))

plotMDS(logcpm_norm, 
        labels = c(rep("male",3),c("male","female","female"),c("female","male","female")), 
        col = rep(mypalette, each = 3),
        cex = 0.85,
        xlim = c(-8,5),
        main = 'PCA of log2(CPM) using log fold change as distance',
        gene.selection = 'common')
legend(-8, 2.5, legend = c("Liver", "Heart", "Colon"), fill = mypalette)

BCV

In order to fit the model used by edgeR it’s necessary to evaluate if the normalized counts can be modeled with a Negative Binomial distribution, which is used by edgeR itself to model the variability of counts. In order to do that, in the plot below we can observe as estimate for the dispersion of the NB the Biological Coefficient of Variation (BCV):

de_object_normalized <- estimateDisp(de_object_normalized,design)
plotBCV(de_object_normalized)

The datasets have the following common dispersion estimate

de_object_normalized$common.dispersion
## [1] 0.2480655

Model fitting

Fit the data to the “generalized linear” model we designed

fit <- glmQLFit(de_object_normalized, design)

Finding DE

In this case, genes will be considered “DE” if:

  • their FDR < 0.01
  • their log-fold change is greater than 0 or lower than 0 (the lfc value is a threshold for the absolute value).

The comparisons between tissues are:

  • Liver versus heart
  • Liver versus colon
  • Heart versus colon

Liver versus heart

qlf.1vs2 <- glmQLFTest(fit, contrast=c(1,-1,0))

# select the significant ones with corrected pvalue < 0.01:
summary(decideTests(qlf.1vs2, p.value = 0.01, lfc = 0))
##        1*liver -1*heart
## Down               1779
## NotSig            19306
## Up                 2369
# Filtering and storing up and down regulated genes
deg.1vs2 <- topTags(qlf.1vs2, n=20000, adjust.method = "BH", sort.by = "PValue", p.value = 0.01)$table
up.genes.1vs2 <- row.names(deg.1vs2[deg.1vs2$logFC > 0,])
down.genes.1vs2 <- row.names(deg.1vs2[deg.1vs2$logFC < 0,])
deg.1vs2

Liver versus colon

qlf.1vs3 <- glmQLFTest(fit, contrast=c(1,0,-1))

# select the significant ones with corrected pvalue < 0.01:
summary(decideTests(qlf.1vs3, p.value = 0.01, lfc = 0))
##        1*liver -1*colon
## Down               1966
## NotSig            18950
## Up                 2538
deg.1vs3 <- topTags(qlf.1vs3, n=20000, adjust.method = "BH", sort.by = "PValue", p.value = 0.01)$table
up.genes.1vs3 <- row.names(deg.1vs3[deg.1vs3$logFC > 0,])
down.genes.1vs3 <- row.names(deg.1vs3[deg.1vs3$logFC < 0,])
deg.1vs3

Heart versus colon

qlf.2vs3 <- glmQLFTest(fit, contrast=c(0,1,-1))

# select the significant ones with corrected pvalue < 0.01:
summary(decideTests(qlf.2vs3, p.value = 0.01, lfc = 0))
##        1*heart -1*colon
## Down                439
## NotSig            22371
## Up                  644
deg.2vs3 <- topTags(qlf.2vs3, n=20000, adjust.method = "BH", sort.by = "PValue", p.value = 0.01)$table
up.genes.2vs3 <- row.names(deg.2vs3[deg.2vs3$logFC > 0,])
down.genes.2vs3 <- row.names(deg.2vs3[deg.2vs3$logFC < 0,])
deg.2vs3

Extracting list of genes up and down in each tissue:

# Liver
up_genes_liver <- intersect(up.genes.1vs2, up.genes.1vs3)
down_genes_liver <- intersect(down.genes.1vs2, down.genes.1vs3)

# Heart 
up_genes_heart <- intersect(down.genes.1vs2, up.genes.2vs3)
down_genes_heart <- intersect(up.genes.1vs2, down.genes.2vs3)

# Colon
up_genes_colon <- intersect(down.genes.1vs3, down.genes.2vs3)
down_genes_colon <- intersect(up.genes.1vs3, up.genes.2vs3)

Export results to .xlsx file

create_de_df <- function(v1, v2, cols_name){
  sq <- seq(max(length(v1), length(v2)))
  df <- data.frame(v1[sq],
                   v2[sq])
  colnames(df) <- cols_name
  return(df)
}


a_1vs2 <- create_de_df(up.genes.1vs2, down.genes.1vs2, c('up_liver_vs_heart','down_liver_vs_heart'))
b_1vs3 <- create_de_df(up.genes.1vs3, down.genes.1vs3, c('up_liver_vs_colon', 'down_liver_vs_colon'))
c_2vs3 <- create_de_df(up.genes.2vs3, down.genes.2vs3, c('up_heart_vs_colon', 'down_heart_vs_colon'))

d_de_liver <- create_de_df(up_genes_liver, down_genes_liver, c('up_liver','down_liver'))
e_de_heart <- create_de_df(up_genes_heart, down_genes_heart, c('up_heart','down_heart'))
f_de_colon <- create_de_df(up_genes_colon, down_genes_colon, c('up_colon','down_colon'))
xlsx::write.xlsx(a_1vs2, paste(wd,"966292_DE_genes.xlsx"), 
                 sheetName = "Liver vs heart",
                 col.names = TRUE, 
                 row.names = FALSE, 
                 append = FALSE, 
                 showNA=FALSE)

xlsx::write.xlsx(b_1vs3, paste(wd,"966292_DE_genes.xlsx"), 
                 sheetName = "Liver vs colon",
                 col.names = TRUE, 
                 row.names = FALSE, 
                 append = TRUE, 
                 showNA=FALSE)

xlsx::write.xlsx(c_2vs3, paste(wd,"966292_DE_genes.xlsx"), 
                 sheetName = "Heart vs colon",
                 col.names = TRUE, 
                 row.names = FALSE, 
                 append = TRUE, 
                 showNA=FALSE)

xlsx::write.xlsx(d_de_liver, paste(wd,"966292_DE_genes.xlsx"), 
                 sheetName = "DEG Liver",
                 col.names = TRUE, 
                 row.names = FALSE, 
                 append = TRUE, 
                 showNA=FALSE)

xlsx::write.xlsx(e_de_heart, paste(wd,"966292_DE_genes.xlsx"), 
                 sheetName = "DEG Heart",
                 col.names = TRUE, 
                 row.names = FALSE, 
                 append = TRUE, 
                 showNA=FALSE)

xlsx::write.xlsx(f_de_colon, paste(wd,"966292_DE_genes.xlsx"), 
                 sheetName = "DEG Colon",
                 col.names = TRUE, 
                 row.names = FALSE, 
                 append = TRUE, 
                 showNA=FALSE)

GO analysis on DE genes

In order to perform functional enrichment for this analysis, function enrichGO() contained in the package clusterProfiler is used.

Firstly, we have to remove the version from the ENSG ID.

up_genes_liver_noversion <- sapply(strsplit(up_genes_liver, "\\."), "[[", 1)
up_genes_heart_noversion <- sapply(strsplit(up_genes_heart, "\\."), "[[", 1)
up_genes_colon_noversion <- sapply(strsplit(up_genes_colon, "\\."), "[[", 1)
go_liver <- enrichGO(up_genes_liver_noversion, keyType = "ENSEMBL", 
                                      OrgDb = org.Hs.eg.db,
                                      ont = 'BP')
dotplot(go_liver)

go_heart <- enrichGO(up_genes_heart_noversion, keyType = "ENSEMBL", 
                                      OrgDb = org.Hs.eg.db,
                                      ont = 'BP')
dotplot(go_heart)

go_colon <- enrichGO(up_genes_colon_noversion, keyType = "ENSEMBL", 
                                      OrgDb = org.Hs.eg.db,
                                      ont = 'BP')
dotplot(go_colon)

Now we select the genes up-regulated in tissue 1 (liver) in both comparison and sort them by the FDR:

up_1vs2_FDR <- data.frame(deg.1vs2[deg.1vs2$logFC > 0,]$FDR)
up_1vs2_FDR$ENSG <- row.names(deg.1vs2[deg.1vs2$logFC > 0,])
row.names(up_1vs2_FDR) <- up_1vs2_FDR$ENSG

up_1vs3_FDR <- data.frame(deg.1vs3[deg.1vs3$logFC > 0,]$FDR)
up_1vs3_FDR$ENSG <- row.names(deg.1vs3[deg.1vs3$logFC > 0,])
row.names(up_1vs3_FDR) <- up_1vs3_FDR$ENSG

up_both <- merge(up_1vs2_FDR,up_1vs3_FDR)
sort_up_both <- up_both[order(up_both$deg.1vs2.deg.1vs2.logFC...0....FDR,up_both$deg.1vs3.deg.1vs3.logFC...0....FDR),]

Session info

sessionInfo()
## R version 4.1.2 (2021-11-01)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 20.04.2 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8          LC_NUMERIC=C                 
##  [3] LC_TIME=en_GB.UTF-8           LC_COLLATE=en_US.UTF-8       
##  [5] LC_MONETARY=en_GB.UTF-8       LC_MESSAGES=en_US.UTF-8      
##  [7] LC_PAPER=en_GB.UTF-8          LC_NAME=en_GB.UTF-8          
##  [9] LC_ADDRESS=en_GB.UTF-8        LC_TELEPHONE=en_GB.UTF-8     
## [11] LC_MEASUREMENT=en_GB.UTF-8    LC_IDENTIFICATION=en_GB.UTF-8
## 
## attached base packages:
## [1] grid      stats4    stats     graphics  grDevices utils     datasets 
## [8] methods   base     
## 
## other attached packages:
##  [1] clusterProfiler_4.2.2       org.Hs.eg.db_3.14.0        
##  [3] AnnotationDbi_1.56.2        gridExtra_2.3              
##  [5] viridis_0.6.2               viridisLite_0.4.0          
##  [7] RColorBrewer_1.1-2          reshape2_1.4.4             
##  [9] ggplot2_3.3.5               dplyr_1.0.7                
## [11] recount_1.20.0              DESeq2_1.34.0              
## [13] SummarizedExperiment_1.24.0 Biobase_2.54.0             
## [15] MatrixGenerics_1.6.0        matrixStats_0.61.0         
## [17] GenomicRanges_1.46.1        GenomeInfoDb_1.30.1        
## [19] IRanges_2.28.0              S4Vectors_0.32.3           
## [21] BiocGenerics_0.40.0         edgeR_3.36.0               
## [23] limma_3.50.1                rmdformats_1.0.3           
## [25] knitr_1.37                 
## 
## loaded via a namespace (and not attached):
##   [1] utf8_1.2.2               tidyselect_1.1.1         RSQLite_2.2.9           
##   [4] htmlwidgets_1.5.4        BiocParallel_1.28.3      scatterpie_0.1.7        
##   [7] munsell_0.5.0            codetools_0.2-18         rentrez_1.2.3           
##  [10] withr_2.4.3              colorspace_2.0-2         GOSemSim_2.20.0         
##  [13] filelock_1.0.2           highr_0.9                rstudioapi_0.13         
##  [16] rJava_1.0-6              DOSE_3.20.1              labeling_0.4.2          
##  [19] GenomeInfoDbData_1.2.7   polyclip_1.10-0          bit64_4.0.5             
##  [22] farver_2.1.0             downloader_0.4           treeio_1.18.1           
##  [25] vctrs_0.3.8              generics_0.1.2           xfun_0.30               
##  [28] BiocFileCache_2.2.1      R6_2.5.1                 graphlayouts_0.8.0      
##  [31] locfit_1.5-9.5           bitops_1.0-7             cachem_1.0.6            
##  [34] fgsea_1.20.0             gridGraphics_0.5-1       DelayedArray_0.20.0     
##  [37] assertthat_0.2.1         BiocIO_1.4.0             scales_1.1.1            
##  [40] ggraph_2.0.5             nnet_7.3-15              derfinder_1.28.0        
##  [43] enrichplot_1.14.2        gtable_0.3.0             xlsx_0.6.5              
##  [46] tidygraph_1.2.0          rlang_1.0.1              genefilter_1.76.0       
##  [49] splines_4.1.2            lazyeval_0.2.2           rtracklayer_1.54.0      
##  [52] GEOquery_2.62.2          checkmate_2.0.0          yaml_2.2.2              
##  [55] GenomicFeatures_1.46.4   backports_1.4.1          qvalue_2.26.0           
##  [58] Hmisc_4.6-0              tools_4.1.2              bookdown_0.25           
##  [61] ggplotify_0.1.0          ellipsis_0.3.2           jquerylib_0.1.4         
##  [64] Rcpp_1.0.8               plyr_1.8.6               base64enc_0.1-3         
##  [67] progress_1.2.2           zlibbioc_1.40.0          purrr_0.3.4             
##  [70] RCurl_1.98-1.5           prettyunits_1.1.1        rpart_4.1-15            
##  [73] bumphunter_1.36.0        GenomicFiles_1.30.0      ggrepel_0.9.1           
##  [76] cluster_2.1.0            magrittr_2.0.2           data.table_1.14.2       
##  [79] DO.db_2.9                xlsxjars_0.6.1           patchwork_1.1.1         
##  [82] hms_1.1.1                evaluate_0.14            xtable_1.8-4            
##  [85] XML_3.99-0.8             jpeg_0.1-9               compiler_4.1.2          
##  [88] biomaRt_2.50.3           tibble_3.1.6             shadowtext_0.1.1        
##  [91] crayon_1.4.2             htmltools_0.5.2          ggfun_0.0.6             
##  [94] tzdb_0.2.0               Formula_1.2-4            tidyr_1.2.0             
##  [97] geneplotter_1.72.0       aplot_0.1.3              DBI_1.1.2               
## [100] tweenr_1.0.2             dbplyr_2.1.1             MASS_7.3-53.1           
## [103] rappdirs_0.3.3           Matrix_1.4-0             readr_2.1.2             
## [106] cli_3.1.1                parallel_4.1.2           derfinderHelper_1.28.0  
## [109] igraph_1.2.11            pkgconfig_2.0.3          GenomicAlignments_1.30.0
## [112] foreign_0.8-80           xml2_1.3.3               foreach_1.5.2           
## [115] ggtree_3.2.1             annotate_1.72.0          bslib_0.3.1             
## [118] rngtools_1.5.2           XVector_0.34.0           yulab.utils_0.0.4       
## [121] doRNG_1.8.2              stringr_1.4.0            VariantAnnotation_1.40.0
## [124] digest_0.6.29            Biostrings_2.62.0        rmarkdown_2.13          
## [127] fastmatch_1.1-3          tidytree_0.3.9           htmlTable_2.4.0         
## [130] restfulr_0.0.13          curl_4.3.2               Rsamtools_2.10.0        
## [133] rjson_0.2.21             nlme_3.1-152             lifecycle_1.0.1         
## [136] jsonlite_1.7.3           BSgenome_1.62.0          fansi_1.0.2             
## [139] pillar_1.7.0             lattice_0.20-41          KEGGREST_1.34.0         
## [142] fastmap_1.1.0            httr_1.4.2               survival_3.2-7          
## [145] GO.db_3.14.0             glue_1.6.1               png_0.1-7               
## [148] iterators_1.0.14         bit_4.0.4                ggforce_0.3.3           
## [151] stringi_1.7.6            sass_0.4.0               blob_1.2.2              
## [154] latticeExtra_0.6-29      memoise_2.0.1            ape_5.6-2