Overview of the workshop

Description

This package demo provides an overview of recent features added to the “iSEE universe”, the set of packages revolving around and extending the iSEE Bioconductor package.

Pre-requisites

  • Familiarity with the SummarizedExperiment class
  • Familiarity with the Differential Expression and Pathways Analysis workflows
  • (Optional, but helpful) Basic familiarity with the iSEE package

Participation

Participants will be able to follow along in the live coding parts of the demo.

Time outline

Activity Time
Overview of data set 10m
Overview of iSEE 10m
iSEEde + iSEEpathways 10m
iSEEhub + iSEEindex 15m

Workshop goals and objectives

Learning goals

  • Recap the general features of iSEE for exploring and visualizing potentially any dataset
  • Outline the new features introduced by a series of packages revolving around iSEE
  • Demonstrate how these packages can be applied and adopted to enhance existing workflows

Learning objectives

  • Analyze a bulk RNA-seq dataset and its DE results with the iSEE-universe set of packages (iSEEde and iSEEpathways)
  • Explore the ExperimentHub ecosystem within iSEE (iSEEhub)
  • Design and create iSEE instances for collections of datasets (iSEEindex)
  • Imagine use cases and future developments for interactive visualization as part of computational workflows

Loading required packages

We start by loading the packages that will be used during the demo.

library(macrophage)
library(DESeq2)
library(limma)
library(edgeR)
library(tximeta)
library(org.Hs.eg.db)
library(stringr)
library(SingleCellExperiment)
library(iSEE)
library(iSEEde)
library(iSEEpathways)
library(iSEEhub)
library(iSEEindex)
library(org.Hs.eg.db)
library(fgsea)
library(GO.db)
library(ExperimentHub)
library(DuoClustering2018)
library(BiocFileCache)
library(scater)
library(yaml)

Loading and processing the macrophage data set

The data set that will be used for this demo is a bulk RNA-seq data set containing 24 samples from Alasoo, et al: “Shared genetic effects on chromatin and gene expression indicate a role for enhancer priming in immune response”, published in Nature Genetics, January 2018. The 24 samples correspond to 6 different donors. For each of these we have four samples: one naive, one exposed to IFNgamma, one exposed to Salmonella, and one exposed to IFNgamma and Salmonella. The macrophage Bioconductor package provides the output files resulting from running Salmon on these 24 samples. Here, we load the quantifications into R using the tximeta package.

## Set the data directory
dir <- system.file("extdata", package = "macrophage")

## Read sample annotations
coldata <- read.csv(file.path(dir, "coldata.csv"))[, c(1, 2, 3, 5)]

## Create new columns indicating, respectively whether the sample was exposed
## to IFNgamma and Salmonella
coldata$IFNg <- as.character(grepl("IFNg", coldata$condition_name))
coldata$SL1344 <- as.character(grepl("SL1344", coldata$condition_name))

## Add paths to quantification files and import data
coldata$files <- file.path(dir, "quants", coldata$names, "quant.sf.gz")
se <- tximeta(coldata = coldata, type = "salmon", dropInfReps = TRUE)
#> importing quantifications
#> reading in files with read.delim (install 'readr' package for speed up)
#> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 
#> found matching transcriptome:
#> [ GENCODE - Homo sapiens - release 29 ]
#> useHub=TRUE: checking for TxDb via 'AnnotationHub'
#> found matching TxDb via 'AnnotationHub'
#> loading from cache
#> Loading required package: GenomicFeatures
#> generating transcript ranges

## Summarize to the gene level and add additional identifiers
seg <- summarizeToGene(se)
#> loading existing TxDb created: 2023-09-12 12:23:46
#> obtaining transcript-to-gene mapping from database
#> generating gene ranges
#> gene ranges assigned by total range of isoforms, see `assignRanges`
#> summarizing abundance
#> summarizing counts
#> summarizing length
rownames(seg) <- str_replace(rownames(seg), "\\.\\d+$", "")
seg <- addIds(seg, "SYMBOL")
#> it appears the rows are gene IDs, setting 'gene' to TRUE
#> mapping to new IDs using org.Hs.eg.db
#> if all matching IDs are desired, and '1:many mappings' are reported,
#> set multiVals='list' to obtain all the matching IDs
#> 'select()' returned 1:many mapping between keys and columns
seg <- addIds(seg, "GOALL", multiVals = "list")
#> it appears the rows are gene IDs, setting 'gene' to TRUE
#> mapping to new IDs using org.Hs.eg.db
#> if all matching IDs are desired, and '1:many mappings' are reported,
#> set multiVals='list' to obtain all the matching IDs
#> 'select()' returned 1:many mapping between keys and columns
rownames(seg) <- scater::uniquifyFeatureNames(
    ID = rownames(seg), names = rowData(seg)$SYMBOL
)

## Create a DESeqDataSet and filter lowly expressed genes
dds <- DESeqDataSet(seg, design = ~ IFNg * SL1344)
#> using counts and average transcript lengths from tximeta
#> Warning in DESeqDataSet(seg, design = ~IFNg * SL1344): some variables in design
#> formula are characters, converting to factors
keep <- rowSums(counts(dds)) >= 10
dds <- dds[keep,]

dds
#> class: DESeqDataSet 
#> dim: 29060 24 
#> metadata(8): tximetaInfo quantInfo ... assignRanges version
#> assays(3): counts abundance avgTxLength
#> rownames(29060): TSPAN6 DPM1 ... ENSG00000285992 ENSG00000285994
#> rowData names(4): gene_id tx_ids SYMBOL GOALL
#> colnames(24): SAMEA103885102 SAMEA103885347 ... SAMEA103885308
#>   SAMEA103884949
#> colData names(6): names sample_id ... IFNg SL1344

## Apply a variance stabilizing transform followed by PCA
vst <- DESeq2::varianceStabilizingTransformation(dds, blind = TRUE)
#> using 'avgTxLength' from assays(dds), correcting for library size
pca <- DESeq2::plotPCA(vst, intgroup = "condition_name", returnData = TRUE)

## Create a SingleCellExperiment object and include the PCA representation
sce <- as(dds, "SingleCellExperiment")
assay(sce, "vst") <- assay(vst)
SingleCellExperiment::reducedDim(sce, "PCA") <- pca[, c("PC1", "PC2")]

sce
#> class: SingleCellExperiment 
#> dim: 29060 24 
#> metadata(8): tximetaInfo quantInfo ... assignRanges version
#> assays(4): counts abundance avgTxLength vst
#> rownames(29060): TSPAN6 DPM1 ... ENSG00000285992 ENSG00000285994
#> rowData names(4): gene_id tx_ids SYMBOL GOALL
#> colnames(24): SAMEA103885102 SAMEA103885347 ... SAMEA103885308
#>   SAMEA103884949
#> colData names(6): names sample_id ... IFNg SL1344
#> reducedDimNames(1): PCA
#> mainExpName: NULL
#> altExpNames(0):

Performing differential expression analysis

Below, we will illustrate how to use the iSEEde and iSEEpathways packages to visualize results from differential expression analyses. Thus, we first apply the DESeq2 and limma packages to perform differential expression analysis. We test the interaction effect between IFNgamma and Salmonella exposure, to investigate whether the effect of Salmonella exposure is different depending on whether or not the sample was also exposed to IFNgamma.

## Run DESeq2
dds <- DESeq2::DESeq(dds)
#> estimating size factors
#> using 'avgTxLength' from assays(dds), correcting for library size
#> estimating dispersions
#> gene-wise dispersion estimates
#> mean-dispersion relationship
#> final dispersion estimates
#> fitting model and testing
DESeq2::resultsNames(dds)
#> [1] "Intercept"            "IFNg_TRUE_vs_FALSE"   "SL1344_TRUE_vs_FALSE"
#> [4] "IFNgTRUE.SL1344TRUE"
res <- DESeq2::results(dds, name = "IFNgTRUE.SL1344TRUE", 
                       lfcThreshold = 0)

## Embed the contrast results obtained from DESeq2 into the SCE
stopifnot(rownames(res) == rownames(sce))
sce <- embedContrastResults(res, 
                            sce, 
                            name = "IFNgTRUE.SL1344TRUE.DESeq2")

sce
#> class: SingleCellExperiment 
#> dim: 29060 24 
#> metadata(8): tximetaInfo quantInfo ... assignRanges version
#> assays(4): counts abundance avgTxLength vst
#> rownames(29060): TSPAN6 DPM1 ... ENSG00000285992 ENSG00000285994
#> rowData names(5): gene_id tx_ids SYMBOL GOALL iSEEde
#> colnames(24): SAMEA103885102 SAMEA103885347 ... SAMEA103885308
#>   SAMEA103884949
#> colData names(6): names sample_id ... IFNg SL1344
#> reducedDimNames(1): PCA
#> mainExpName: NULL
#> altExpNames(0):

## Run limma-trend
dge <- tximeta::makeDGEList(seg)
dge <- dge[rownames(dds), ]
logCPM <- edgeR::cpm(dge, log = TRUE, prior.count = 3)
design <- model.matrix(~ IFNg * SL1344, data = dge$samples)
fit <- limma::lmFit(logCPM, design = design)
fit <- eBayes(fit, trend = TRUE)
tt <- topTable(fit, coef = ncol(design), number = Inf, sort.by = "none")

## Embed the results obtained from limma into the SCE
stopifnot(rownames(tt) == rownames(sce))
sce <- embedContrastResults(tt, 
                            sce, 
                            name = "IFNgTRUE.SL1344TRUE.limma", 
                            class = "limma")

sce
#> class: SingleCellExperiment 
#> dim: 29060 24 
#> metadata(8): tximetaInfo quantInfo ... assignRanges version
#> assays(4): counts abundance avgTxLength vst
#> rownames(29060): TSPAN6 DPM1 ... ENSG00000285992 ENSG00000285994
#> rowData names(5): gene_id tx_ids SYMBOL GOALL iSEEde
#> colnames(24): SAMEA103885102 SAMEA103885347 ... SAMEA103885308
#>   SAMEA103884949
#> colData names(6): names sample_id ... IFNg SL1344
#> reducedDimNames(1): PCA
#> mainExpName: NULL
#> altExpNames(0):

## Where's the information stored?
rowData(sce)$iSEEde
#> DataFrame with 29060 rows and 2 columns
#>       IFNgTRUE.SL1344TRUE.DESeq2 IFNgTRUE.SL1344TRUE.limma
#>              <iSEEDESeq2Results>        <iSEELimmaResults>
#> 1            <iSEEDESeq2Results>        <iSEELimmaResults>
#> 2            <iSEEDESeq2Results>        <iSEELimmaResults>
#> 3            <iSEEDESeq2Results>        <iSEELimmaResults>
#> 4            <iSEEDESeq2Results>        <iSEELimmaResults>
#> 5            <iSEEDESeq2Results>        <iSEELimmaResults>
#> ...                          ...                       ...
#> 29056        <iSEEDESeq2Results>        <iSEELimmaResults>
#> 29057        <iSEEDESeq2Results>        <iSEELimmaResults>
#> 29058        <iSEEDESeq2Results>        <iSEELimmaResults>
#> 29059        <iSEEDESeq2Results>        <iSEELimmaResults>
#> 29060        <iSEEDESeq2Results>        <iSEELimmaResults>

Perform pathway analysis

We also run fgsea to perform a gene set enrichment analysis of GO terms, based on the DESeq2 results obtained above.

## Extract GO term composition 
pathways <- select(org.Hs.eg.db, keys(org.Hs.eg.db, "SYMBOL"), c("GOALL"), 
                   keytype = "SYMBOL")
#> 'select()' returned 1:many mapping between keys and columns
pathways <- subset(pathways, ONTOLOGYALL == "BP")
pathways <- unique(pathways[, c("SYMBOL", "GOALL")])
pathways <- split(pathways$SYMBOL, pathways$GOALL)
len_pathways <- lengths(pathways)
pathways <- pathways[len_pathways > 15 & len_pathways < 200]
length(pathways)
#> [1] 4454

## Get test statistics and apply fgsea
feature_stats <- res$stat
names(feature_stats) <- rownames(res)
set.seed(42)
fgseaRes <- fgsea(pathways = pathways, 
                  stats = feature_stats,
                  minSize = 15,
                  maxSize = 200)
fgseaRes <- fgseaRes[order(pval), ]

head(fgseaRes)
#>       pathway         pval         padj  log2err         ES       NES size
#> 1: GO:0006399 3.543000e-32 7.976586e-29 1.474563 -0.7006414 -2.967155  192
#> 2: GO:0140053 3.694574e-32 7.976586e-29 1.474563 -0.7275861 -2.997353  163
#> 3: GO:0009451 1.363682e-30 1.962792e-27 1.439026 -0.7118139 -2.960285  172
#> 4: GO:0032543 1.442761e-26 1.557460e-23 1.334497 -0.7341839 -2.933556  132
#> 5: GO:0042274 3.590575e-25 3.100821e-22 1.303093 -0.8221723 -3.002545   77
#> 6: GO:0008033 1.062547e-23 7.646799e-21 1.262740 -0.7094165 -2.843095  134
#>                                       leadingEdge
#> 1:        QTRT2,MARS2,RARS1,YRDC,ELAC2,GTF3C2,...
#> 2:    TBRG4,FASTKD2,MRPL38,TWNK,SUPV3L1,ELAC2,...
#> 3:        QTRT2,NSUN4,NOP2,YRDC,METTL16,DUS3L,...
#> 4: FASTKD2,MRPL38,EARS2,MRPS30,MRPS12,TRMT10C,...
#> 5:     KRI1,MPHOSPH10,NOB1,UTP23,DHX37,HEATR1,...
#> 6:           QTRT2,YRDC,ELAC2,DUS3L,PUS1,POP1,...

## Embed pathway analysis results in the SCE object
sce <- embedPathwaysResults(fgseaRes, 
                            sce, 
                            name = "IFNgTRUE.SL1344TRUE.DESeq2.fgsea", 
                            class = "fgsea", 
                            pathwayType = "GO", 
                            pathwaysList = pathways, 
                            featuresStats = feature_stats)

sce
#> class: SingleCellExperiment 
#> dim: 29060 24 
#> metadata(9): tximetaInfo quantInfo ... version iSEEpathways
#> assays(4): counts abundance avgTxLength vst
#> rownames(29060): TSPAN6 DPM1 ... ENSG00000285992 ENSG00000285994
#> rowData names(5): gene_id tx_ids SYMBOL GOALL iSEEde
#> colnames(24): SAMEA103885102 SAMEA103885347 ... SAMEA103885308
#>   SAMEA103884949
#> colData names(6): names sample_id ... IFNg SL1344
#> reducedDimNames(1): PCA
#> mainExpName: NULL
#> altExpNames(0):
## Again: where's the data stored?
metadata(sce)$iSEEpathways
#> $IFNgTRUE.SL1344TRUE.DESeq2.fgsea
#> iSEEfgseaResults with 4318 rows and 7 columns
#>                   pval        padj   log2err        ES       NES      size
#>              <numeric>   <numeric> <numeric> <numeric> <numeric> <integer>
#> GO:0006399 3.54300e-32 7.97659e-29   1.47456 -0.700641  -2.96715       192
#> GO:0140053 3.69457e-32 7.97659e-29   1.47456 -0.727586  -2.99735       163
#> GO:0009451 1.36368e-30 1.96279e-27   1.43903 -0.711814  -2.96028       172
#> GO:0032543 1.44276e-26 1.55746e-23   1.33450 -0.734184  -2.93356       132
#> GO:0042274 3.59057e-25 3.10082e-22   1.30309 -0.822172  -3.00255        77
#> ...                ...         ...       ...       ...       ...       ...
#> GO:0003382           1           1 0.0426734 -0.147476 -0.443623        30
#> GO:0006636           1           1 0.0426734 -0.140740 -0.468816        46
#> GO:0007156           1           1 0.0496901  0.142194  0.597536       162
#> GO:0044062           1           1 0.0438002 -0.159312 -0.425874        18
#> GO:1900273           1           1 0.0438002 -0.142301 -0.403754        23
#>                         leadingEdge
#>                              <list>
#> GO:0006399    QTRT2,MARS2,RARS1,...
#> GO:0140053 TBRG4,FASTKD2,MRPL38,...
#> GO:0009451     QTRT2,NSUN4,NOP2,...
#> GO:0032543 FASTKD2,MRPL38,EARS2,...
#> GO:0042274  KRI1,MPHOSPH10,NOB1,...
#> ...                             ...
#> GO:0003382  CCDC88C,PKHD1,VSIG1,...
#> GO:0006636 PLA2G4A,DECR2,ELOVL1,...
#> GO:0007156     PCDH12,FAT2,CD84,...
#> GO:0044062        SNX5,NPR1,SPX,...
#> GO:1900273      CRTC1,NPTN,RELN,...

## Add details about the GO terms
## These will be displayed in the application
go_details <- function(x) {
    info <- select(GO.db, x, c("TERM", "ONTOLOGY", "DEFINITION"), "GOID")
    html <- list(p(strong(info$GOID), ":", info$TERM, paste0("(", info$ONTOLOGY, ")")))
    if (!is.na(info$DEFINITION)) {
        html <- append(html, list(p(info$DEFINITION)))
    }
    tagList(html)
}

## Define the mapping from GO terms to gene IDs
map_GO <- function(pathway_id, se) {
    pathway_symbol <- mapIds(org.Hs.eg.db, pathway_id, "SYMBOL", 
                             keytype = "GOALL", multiVals = "CharacterList")[[pathway_id]]
    pathway_rownames <- rownames(se)[rowData(se)$SYMBOL %in% pathway_symbol]
    pathway_rownames
}

## Register the pathway mapping information into the SCE object
sce <- registerAppOptions(sce, Pathways.map.functions = list(GO = map_GO))
sce <- registerAppOptions(sce, PathwaysTable.select.details = go_details)

metadata(sce)$iSEE
#> $options
#> $options$Pathways.map.functions
#> $options$Pathways.map.functions$GO
#> function(pathway_id, se) {
#>     pathway_symbol <- mapIds(org.Hs.eg.db, pathway_id, "SYMBOL", 
#>                              keytype = "GOALL", multiVals = "CharacterList")[[pathway_id]]
#>     pathway_rownames <- rownames(se)[rowData(se)$SYMBOL %in% pathway_symbol]
#>     pathway_rownames
#> }
#> 
#> 
#> $options$PathwaysTable.select.details
#> function(x) {
#>     info <- select(GO.db, x, c("TERM", "ONTOLOGY", "DEFINITION"), "GOID")
#>     html <- list(p(strong(info$GOID), ":", info$TERM, paste0("(", info$ONTOLOGY, ")")))
#>     if (!is.na(info$DEFINITION)) {
#>         html <- append(html, list(p(info$DEFINITION)))
#>     }
#>     tagList(html)
#> }

This concludes the preparation of the dataset for this workshop.
We can conveniently store that as a binary RDS file which we can load afterwards, anytime.

saveRDS(sce, "sce_macrophage_readytouse.RDS")

A quick overview of iSEE

iSEE is a Bioconductor package, based on shiny, that allows the user to create an interactive interface for exploring their data. The input should be an object of the class SummarizedExperiment, or any class extending SummarizedExperiment (e.g., SingleCellExperiment, DESeqDataSet). Launching an application is as simple as:

iSEE(sce)

For a more extensive description of the different parts of the interface, we refer to the overview vignette in a previous, extended workshop on iSEE.

iSEEde and iSEEpathways: ideal companions for exploring DE results

iSEEde and iSEEpathways are two new Bioconductor packages that provide iSEE panels specifically aimed towards exploration of differential expression and pathway analysis results. More precisely, iSEEde provides the VolcanoPlot, MAPlot, LogFCLogFCPlot and DETable panels. These panels can be configured to extract data that was added via the embedContrastResults() function above. Let’s look at an example:

app <- iSEE(sce, initial = list(
    DETable(ContrastName = "IFNgTRUE.SL1344TRUE.DESeq2", 
            HiddenColumns = c("baseMean", "lfcSE", "stat")),
    VolcanoPlot(ContrastName = "IFNgTRUE.SL1344TRUE.DESeq2"),
    MAPlot(ContrastName = "IFNgTRUE.SL1344TRUE.DESeq2")
))
app

Note how it is easy to switch to a different contrast in any of the panels.

app <- iSEE(sce, initial = list(
    DETable(ContrastName = "IFNgTRUE.SL1344TRUE.DESeq2", 
            HiddenColumns = c("baseMean", "lfcSE", "stat")),
    VolcanoPlot(ContrastName = "IFNgTRUE.SL1344TRUE.DESeq2"),
    MAPlot(ContrastName = "IFNgTRUE.SL1344TRUE.DESeq2"),
    PathwaysTable(ResultName = "IFNgTRUE.SL1344TRUE.limma.fgsea", 
                  Selected = "GO:0046324"),
    ComplexHeatmapPlot(RowSelectionSource = "PathwaysTable1", 
                       CustomRows = FALSE, ColumnData = "condition_name",
                       ClusterRows = TRUE, Assay = "vst"),
    FgseaEnrichmentPlot(ResultName = "IFNgTRUE.SL1344TRUE.limma.fgsea",
                        PathwayId = "GO:0046324")
))
app

iSEEhub: iSEEing the ExperimentHub datasets

The iSEEhub package provides a custom landing page for an iSEE application interfacing with the Bioconductor ExperimentHub. The landing page allows users to browse the ExperimentHub, select a data set, download and cache it, and import it directly into an iSEE app.

ehub <- ExperimentHub()
app <- iSEEhub(ehub)
app

iSEEindex: one instance of iSEE to explore them all

iSEEindex provides an interface to any collection of data sets within a single iSEE web-application.
The main functionality of this package is to define a custom landing page allowing app maintainers to list a custom collection of data sets that users can select from and directly load objects into an iSEE web application. To see how to configure such an app, we will create a small example:

bfc <- BiocFileCache(cache = tempdir())

dataset_fun <- function() {
    x <- yaml::read_yaml(system.file(package = "iSEEindex", "example.yaml"))
    x$datasets
}
initial_fun <- function() {
    x <- yaml::read_yaml(system.file(package = "iSEEindex", "example.yaml"))
    x$initial
}
app <- iSEEindex(bfc, dataset_fun, initial_fun)
app

A more elaborate example is available at https://rehwinkellab.shinyapps.io/ifnresource/. The source can be found at https://github.com/kevinrue/IFNresource.

Potential use cases can include:

  • An app to present and explore the different datasets in your next publication
  • An app to explore collection of datasets collaboratively, in consortium-like initiatives
  • An app to mirror and enhance the content of e.g. the cellxgene data portal
  • Got any ideas on how to use iSEE for such deployments?

Session info

sessionInfo()
#> R version 4.3.1 (2023-06-16)
#> Platform: x86_64-pc-linux-gnu (64-bit)
#> Running under: Ubuntu 22.04.3 LTS
#> 
#> Matrix products: default
#> BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.20.so;  LAPACK version 3.10.0
#> 
#> locale:
#>  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
#>  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
#>  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
#>  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
#>  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
#> 
#> time zone: Etc/UTC
#> tzcode source: system (glibc)
#> 
#> attached base packages:
#> [1] stats4    stats     graphics  grDevices utils     datasets  methods  
#> [8] base     
#> 
#> other attached packages:
#>  [1] GenomicFeatures_1.53.2      yaml_2.3.7                 
#>  [3] scater_1.29.4               ggplot2_3.4.3              
#>  [5] scuttle_1.11.2              DuoClustering2018_1.19.0   
#>  [7] GO.db_3.17.0                fgsea_1.27.1               
#>  [9] iSEEindex_0.99.13           iSEEhub_1.3.2              
#> [11] ExperimentHub_2.9.1         AnnotationHub_3.9.2        
#> [13] BiocFileCache_2.9.1         dbplyr_2.3.3               
#> [15] iSEEpathways_0.99.0         iSEEde_0.99.0              
#> [17] iSEE_2.13.5                 SingleCellExperiment_1.23.0
#> [19] stringr_1.5.0               org.Hs.eg.db_3.17.0        
#> [21] AnnotationDbi_1.63.2        tximeta_1.19.5             
#> [23] edgeR_3.43.8                limma_3.57.7               
#> [25] DESeq2_1.41.10              SummarizedExperiment_1.31.1
#> [27] Biobase_2.61.0              MatrixGenerics_1.13.1      
#> [29] matrixStats_1.0.0           GenomicRanges_1.53.1       
#> [31] GenomeInfoDb_1.37.4         IRanges_2.35.2             
#> [33] S4Vectors_0.39.1            BiocGenerics_0.47.0        
#> [35] macrophage_1.17.0           BiocStyle_2.29.1           
#> 
#> loaded via a namespace (and not attached):
#>   [1] fs_1.6.3                      ProtGenerics_1.33.1          
#>   [3] bitops_1.0-7                  httr_1.4.7                   
#>   [5] RColorBrewer_1.1-3            doParallel_1.0.17            
#>   [7] tools_4.3.1                   utf8_1.2.3                   
#>   [9] R6_2.5.1                      DT_0.29                      
#>  [11] lazyeval_0.2.2                mgcv_1.9-0                   
#>  [13] GetoptLong_1.0.5              withr_2.5.0                  
#>  [15] prettyunits_1.1.1             gridExtra_2.3                
#>  [17] cli_3.6.1                     textshaping_0.3.6            
#>  [19] shinyjs_2.1.0                 sass_0.4.7                   
#>  [21] pkgdown_2.0.7                 Rsamtools_2.17.0             
#>  [23] systemfonts_1.0.4             RSQLite_2.3.1                
#>  [25] generics_0.1.3                shape_1.4.6                  
#>  [27] BiocIO_1.11.0                 dplyr_1.1.3                  
#>  [29] Matrix_1.6-1                  ggbeeswarm_0.7.2             
#>  [31] fansi_1.0.4                   abind_1.4-5                  
#>  [33] lifecycle_1.0.3               SparseArray_1.1.12           
#>  [35] grid_4.3.1                    blob_1.2.4                   
#>  [37] promises_1.2.1                crayon_1.5.2                 
#>  [39] shinydashboard_0.7.2          miniUI_0.1.1.1               
#>  [41] lattice_0.21-8                beachmat_2.17.16             
#>  [43] cowplot_1.1.1                 KEGGREST_1.41.0              
#>  [45] pillar_1.9.0                  knitr_1.44                   
#>  [47] ComplexHeatmap_2.17.0         rjson_0.2.21                 
#>  [49] codetools_0.2-19              fastmatch_1.1-4              
#>  [51] glue_1.6.2                    data.table_1.14.8            
#>  [53] vctrs_0.6.3                   png_0.1-8                    
#>  [55] urltools_1.7.3                gtable_0.3.4                 
#>  [57] cachem_1.0.8                  xfun_0.40                    
#>  [59] S4Arrays_1.1.6                mime_0.12                    
#>  [61] iterators_1.0.14              statmod_1.5.0                
#>  [63] interactiveDisplayBase_1.39.0 ellipsis_0.3.2               
#>  [65] nlme_3.1-163                  bit64_4.0.5                  
#>  [67] progress_1.2.2                filelock_1.0.2               
#>  [69] rprojroot_2.0.3               bslib_0.5.1                  
#>  [71] irlba_2.3.5.1                 vipor_0.4.5                  
#>  [73] colorspace_2.1-0              DBI_1.1.3                    
#>  [75] tidyselect_1.2.0              bit_4.0.5                    
#>  [77] compiler_4.3.1                curl_5.0.2                   
#>  [79] BiocNeighbors_1.19.0          xml2_1.3.5                   
#>  [81] desc_1.4.2                    DelayedArray_0.27.10         
#>  [83] colourpicker_1.3.0            bookdown_0.35                
#>  [85] rtracklayer_1.61.1            triebeard_0.4.1              
#>  [87] scales_1.2.1                  rappdirs_0.3.3               
#>  [89] digest_0.6.33                 rmarkdown_2.24               
#>  [91] XVector_0.41.1                htmltools_0.5.6              
#>  [93] pkgconfig_2.0.3               sparseMatrixStats_1.13.4     
#>  [95] fastmap_1.1.1                 ensembldb_2.25.0             
#>  [97] rlang_1.1.1                   GlobalOptions_0.1.2          
#>  [99] htmlwidgets_1.6.2             ggthemes_4.2.4               
#> [101] shiny_1.7.5                   DelayedMatrixStats_1.23.4    
#> [103] jquerylib_0.1.4               jsonlite_1.8.7               
#> [105] BiocParallel_1.35.4           mclust_6.0.0                 
#> [107] BiocSingular_1.17.1           RCurl_1.98-1.12              
#> [109] magrittr_2.0.3                GenomeInfoDbData_1.2.10      
#> [111] munsell_0.5.0                 Rcpp_1.0.11                  
#> [113] viridis_0.6.4                 stringi_1.7.12               
#> [115] rintrojs_0.3.2                zlibbioc_1.47.0              
#> [117] plyr_1.8.8                    parallel_4.3.1               
#> [119] ggrepel_0.9.3                 Biostrings_2.69.2            
#> [121] splines_4.3.1                 hms_1.1.3                    
#> [123] circlize_0.4.15               locfit_1.5-9.8               
#> [125] igraph_1.5.1                  paws.common_0.6.0            
#> [127] reshape2_1.4.4                biomaRt_2.57.1               
#> [129] ScaledMatrix_1.9.1            BiocVersion_3.18.0           
#> [131] XML_3.99-0.14                 evaluate_0.21                
#> [133] BiocManager_1.30.22           foreach_1.5.2                
#> [135] httpuv_1.6.11                 tidyr_1.3.0                  
#> [137] purrr_1.0.2                   clue_0.3-64                  
#> [139] paws.storage_0.4.0            rsvd_1.0.5                   
#> [141] xtable_1.8-4                  restfulr_0.0.15              
#> [143] AnnotationFilter_1.25.0       later_1.3.1                  
#> [145] viridisLite_0.4.2             ragg_1.2.5                   
#> [147] tibble_3.2.1                  beeswarm_0.4.0               
#> [149] memoise_2.0.1                 GenomicAlignments_1.37.0     
#> [151] tximport_1.29.1               cluster_2.1.4                
#> [153] shinyWidgets_0.8.0            shinyAce_0.4.2