# Analysing Long Read RNA-Seq data with bambu

#### Ying Chen, Yuk Kei Wan, Jonathan Göke

# Introduction

Bambu is a method for transcript discovery and quantification from long read RNA-Seq data. Bambu uses aligned reads and genome reference annotations as input, and will return abundance estimates for all known transcripts and for newly discovered transcripts. Bambu uses the information from the reference annotations to correct misalignment at splice junctions, then reduces the aligned reads to read equivalent classes, and uses this information to identify novel transcripts across all samples of interest. Reads are then assigned to transcripts, and expression estimates are obtained using an expectation maximisation algorithm. Here, we present an example workflow for analysing Nanopore long read RNA-Sequencing data from two human cancer cell lines from the Singapore Nanopore Expression Project (SG-NEx).

# Quick start: Transcript discovery and quantification with bambu

## Installation

You can install bambu from github:

    if (!requireNamespace("BiocManager", quietly = TRUE)) install.packages("BiocManager")
    BiocManager::install("bambu")
    BiocManager::install("NanoporeRNASeq")

## General Usage

The default mode to run bambu is using a set of aligned reads (bam files), reference genome annotations (gtf file, TxDb object, or bambuAnnotation object), and reference genome sequence (fasta file or BSgenome). bambu will return a summarizedExperiment object with the genomic coordinates for annotated and new transcripts and transcript expression estimates. We highly recommend to use the same annotations that were used for genome alignment. If you have a gtf file and fasta file you can run bambu with the following options:

    library(bambu)
    test.bam <- system.file("extdata", "SGNex_A549_directRNA_replicate5_run1_chr9_1_1000000.bam",
        package = "bambu")

    fa.file <- system.file("extdata", "Homo_sapiens.GRCh38.dna_sm.primary_assembly_chr9_1_1000000.fa",
        package = "bambu")

    gtf.file <- system.file("extdata", "Homo_sapiens.GRCh38.91_chr9_1_1000000.gtf", package = "bambu")

    bambuAnnotations <- prepareAnnotations(gtf.file)

    se <- bambu(reads = test.bam, annotations = bambuAnnotations, genome = fa.file)
    ##>
      |
      |                                                                      |   0%
      |
      |======================================================================| 100%
    ##>
    ##>
      |
      |                                                                      |   0%
      |
      |======================================================================| 100%

bambu returns a SummarizedExperiment object which can be accessed as follows:

- assays(se) returns the transcript abundance estimates as counts or CPM
- rowRanges(se) returns a GRangesList with all annotated and newly discovered transcripts
- rowData(se) returns additional information about each transcript such as the gene name and the class of newly discovered transcript

# A complete workflow to identify and quantify transcript expression from

Nanopore RNA-Seq data {#complete-workflow} To demonstrate the usage of Bambu, we used long-read RNA-Seq data generated using Oxford Nanopore Sequencing from the NanoporeRNASeq package, which consists of 6 samples from two human cell lines (K562 and MCF7) that were generated by the SG-NEx project. Each of these cell lines has three replicates, with 1 direct RNA sequencing run and 2 cDNA sequencing runs. Reads are aligned to chromosome 22 (Grch38) and stored as bam files. In this workflow, we will demonstrate how to apply bambu to these bam files to identify novel transcripts and estimates transcript expression, visualize the results, and identify differentially expressed genes and transcripts.

## Input data

### Aligned reads (bam files)

bambu takes genomic alignments saved in bam files. Here we use bam-files from the NanoporeRNASeq package, which contains reads aligned to the first half of the human chromosome 22 using minimap2.

    library(bambu)

    library(NanoporeRNASeq)
    data("SGNexSamples")
    SGNexSamples
    ##> DataFrame with 6 rows and 6 columns
    ##>                sample_id    Platform    cellLine    protocol cancer_type
    ##>              <character> <character> <character> <character> <character>
    ##> 1 K562_directcDNA_repl..      MinION        K562  directcDNA   Leukocyte
    ##> 2 K562_directcDNA_repl..     GridION        K562  directcDNA   Leukocyte
    ##> 3 K562_directRNA_repli..     GridION        K562   directRNA   Leukocyte
    ##> 4 MCF7_directcDNA_repl..      MinION        MCF7  directcDNA      Breast
    ##> 5 MCF7_directcDNA_repl..     GridION        MCF7  directcDNA      Breast
    ##> 6 MCF7_directRNA_repli..     GridION        MCF7   directRNA      Breast
    ##>                fileNames
    ##>              <character>
    ##> 1 NanoporeRNASeq/versi..
    ##> 2 NanoporeRNASeq/versi..
    ##> 3 NanoporeRNASeq/versi..
    ##> 4 NanoporeRNASeq/versi..
    ##> 5 NanoporeRNASeq/versi..
    ##> 6 NanoporeRNASeq/versi..

    library(ExperimentHub)
    NanoporeData <- query(ExperimentHub(), c("NanoporeRNA", "GRCh38", "BAM"))
    bamFiles <- Rsamtools::BamFileList(NanoporeData[["EH3808"]], NanoporeData[["EH3809"]],
        NanoporeData[["EH3810"]], NanoporeData[["EH3811"]], NanoporeData[["EH3812"]],
        NanoporeData[["EH3813"]])

### Genome sequence (fasta file/ BSGenome object)

bambu additionally requires a genome sequence, which is used to correct splicing junctions in read alignments. Ideally, we recommend to use the same genome seqeunce file that was used for alignment to be used for bambu.

    # get path to fasta file
    genomeSequence <- query(ExperimentHub(), c("NanoporeRNA", "GRCh38", "FASTA"))

As an option, users can also choose to use a BSgenome object:

    library(BSgenome.Hsapiens.NCBI.GRCh38)
    genomeSequence <- BSgenome.Hsapiens.NCBI.GRCh38

### Genome annotations (bambu annotations object/ gtf file / TxDb object)

{#annotations}
bambu also requires a reference transcript annotations object, which is used to correct read alignments, to identify for transcripts and genes (and the type for novel transcripts), and for quantification. The annotation object can be created from a gtf file:

    gtf.file <- system.file("extdata", "Homo_sapiens.GRCh38.91_chr9_1_1000000.gtf", package = "bambu")

    annotation <- prepareAnnotations(gtf.file)

The annotation object can also be created from a TxDb object:

    txdb <- system.file("extdata", "Homo_sapiens.GRCh38.91_chr9_1_1000000.gtf", package = "bambu")

    annotation <- prepareAnnotations(txdb)

The annotation object can be stored and used again for re-running bambu. Here we will used the annotation object from the NanoporeRNASeq package that wasis prepared from a gtf file using the function in by function in bambu.

    data("HsChr22BambuAnnotation")
    HsChr22BambuAnnotation
    ##> GRangesList object of length 1500:
    ##> $ENST00000043402
    ##> GRanges object with 2 ranges and 2 metadata columns:
    ##>       seqnames            ranges strand | exon_rank exon_endRank
    ##>          <Rle>         <IRanges>  <Rle> | <integer>    <integer>
    ##>   [1]       22 20241415-20243110      - |         2            1
    ##>   [2]       22 20268071-20268531      - |         1            2
    ##>   -------
    ##>   seqinfo: 1 sequence from an unspecified genome; no seqlengths
    ##>
    ##> $ENST00000086933
    ##> GRanges object with 3 ranges and 2 metadata columns:
    ##>       seqnames            ranges strand | exon_rank exon_endRank
    ##>          <Rle>         <IRanges>  <Rle> | <integer>    <integer>
    ##>   [1]       22 19148576-19149095      - |         3            1
    ##>   [2]       22 19149663-19149916      - |         2            2
    ##>   [3]       22 19150025-19150283      - |         1            3
    ##>   -------
    ##>   seqinfo: 1 sequence from an unspecified genome; no seqlengths
    ##>
    ##> $ENST00000155674
    ##> GRanges object with 8 ranges and 2 metadata columns:
    ##>       seqnames            ranges strand | exon_rank exon_endRank
    ##>          <Rle>         <IRanges>  <Rle> | <integer>    <integer>
    ##>   [1]       22 17137511-17138357      - |         8            1
    ##>   [2]       22 17138550-17138738      - |         7            2
    ##>   [3]       22 17141059-17141233      - |         6            3
    ##>   [4]       22 17143098-17143131      - |         5            4
    ##>   [5]       22 17145024-17145117      - |         4            5
    ##>   [6]       22 17148448-17148560      - |         3            6
    ##>   [7]       22 17149542-17149745      - |         2            7
    ##>   [8]       22 17165209-17165287      - |         1            8
    ##>   -------
    ##>   seqinfo: 1 sequence from an unspecified genome; no seqlengths
    ##>
    ##> ...
    ##> <1497 more elements>

## Transcript discovery and quantification

### Running bambu

Next we apply bambu on the input data (bam files, annotations, genomeSequence). Bambu will perform isoform discovery to extend the provided annotation, and then quantify the transcript expression from these extended annotation using an Expectation-Maximisation algorithm. Here we will use 1 core, which can be changed to process multiple files in parallel.

    se <- bambu(reads = bamFiles, annotations = HsChr22BambuAnnotation, genome = genomeSequence,
        ncore = 1)

    se
    ##> class: RangedSummarizedExperiment
    ##> dim: 1930 6
    ##> metadata(0):
    ##> assays(2): counts CPM
    ##> rownames(1930): tx.1 tx.2 ... ENST00000641933 ENST00000641967
    ##> rowData names(4): TXNAME GENEID eqClass newTxClass
    ##> colnames(6): 2a477826358_3844 2a472b72020_3846 ... 2a41ef06a9c_3852
    ##>   2a439b06ebb_3854
    ##> colData names(1): name

For the downstream analysis, we will add the condition of interest to the object that describes the samples. Here we are interested in a comparison of the 2 cell lines:

    colData(se)$condition <- as.factor(SGNexSamples$cellLine)

Optionally, users can choose to apply bambu to do quantification only (without isoform discovery)

    seUnextended <- bambu(reads = bamFiles, annotations = HsChr22BambuAnnotation, genome = genomeSequence,
        discovery = FALSE)

    seUnextended
    ##> class: RangedSummarizedExperiment
    ##> dim: 1500 6
    ##> metadata(0):
    ##> assays(2): counts CPM
    ##> rownames(1500): ENST00000043402 ENST00000086933 ... ENST00000641933
    ##>   ENST00000641967
    ##> rowData names(3): TXNAME GENEID eqClass
    ##> colnames(6): 2a477826358_3844 2a472b72020_3846 ... 2a41ef06a9c_3852
    ##>   2a439b06ebb_3854
    ##> colData names(1): name

### Visualise results

bambu provides functions to visualise and explore the results. When multiple samples are used, we can visualise the correlation and clustering of all samples with a heatmap:

    library(ggplot2)
    plotBambu(se, type = "heatmap")

Additionally, we can also visualise the correlation with a 2-dimmensional PCA plot.

    plotBambu(se, type = "pca")

In addition to visualising the correlation between samples, bambu also provide a function to visualise the extended annotation and expression estimation for individual genes. Here we look at gene ENSG00000099968 and visualise the transcript coordinates for annotated and novel isoforms and expression levels for these isoforms across all samples.

    plotBambu(se, type = "annotation", gene_id = "ENSG00000099968")

    ##> [[1]]
    ##> TableGrob (3 x 1) "arrange": 3 grobs
    ##>   z     cells    name                grob
    ##> 1 1 (2-2,1-1) arrange      gtable[layout]
    ##> 2 2 (3-3,1-1) arrange      gtable[layout]
    ##> 3 3 (1-1,1-1) arrange text[GRID.text.256]

### Obtain gene expression estimates from transcript expression

{#gene-expression} Gene expression can be calculated from the transcript expression estimates returned by bambu using the function. Looking at the output, we can see there are novel genes identified as well

    seGene <- transcriptToGeneExpression(se)
    seGene
    ##> class: RangedSummarizedExperiment
    ##> dim: 887 6
    ##> metadata(0):
    ##> assays(2): counts CPM
    ##> rownames(887): ENSG00000015475 ENSG00000040608 ... gene.98 gene.99
    ##> rowData names(2): GENEID newGeneClass
    ##> colnames(6): 2a477826358_3844 2a472b72020_3846 ... 2a41ef06a9c_3852
    ##>   2a439b06ebb_3854
    ##> colData names(2): name condition

We can again use the function to visualise the gene expression data across the 6 samples with a heatmap or PCA plot. As expected, samples from the same cell line showed higher correlation than across the cell lines.

    colData(seGene)$groupVar <- SGNexSamples$cellLine
    plotBambu(seGene, type = "heatmap")

### Save data (gtf/text)

bambu includes a function to write the extended annotations, the transcript and the gene expression estimates that include any newly discovered genes and transcripts to text files.

    save.dir <- tempdir()
    writeBambuOutput(se, path = save.dir, prefix = "NanoporeRNASeq_")

bambu also includes a function that only exports the extended annotations to gtf file:

    save.file <- tempfile(fileext = ".gtf")
    writeToGTF(rowRanges(se), file = save.file)

## Identifying differentially expressed genes

One of the most common tasks when analysing RNA-Seq data is the analysis of differential gene expression across a condition of intertest. Here we use DESeq2 to find the differentially expressed genes between MCF7 and K562 cell lines. Similar to using results from Salmon, estimates from bambu will first be rounded.

    library(DESeq2)
    dds <- DESeqDataSetFromMatrix(round(assays(seGene)$counts), colData = colData(se),
        design = ~condition)
    dds.deseq <- DESeq(dds)
    deGeneRes <- DESeq2::results(dds.deseq, independentFiltering = FALSE)
    head(deGeneRes[order(deGeneRes$padj), ])
    ##> log2 fold change (MLE): condition MCF7 vs K562
    ##> Wald test p-value: condition MCF7 vs K562
    ##> DataFrame with 6 rows and 6 columns
    ##>                  baseMean log2FoldChange     lfcSE      stat      pvalue
    ##>                 <numeric>      <numeric> <numeric> <numeric>   <numeric>
    ##> ENSG00000185686  513.5480       -7.22600  0.493772 -14.63430 1.69717e-48
    ##> ENSG00000283633   93.5023       -9.10927  1.246739  -7.30647 2.74242e-13
    ##> ENSG00000197077   26.1272        9.09281  1.324172   6.86679 6.56628e-12
    ##> ENSG00000099977  231.6737        1.84393  0.300300   6.14029 8.23710e-10
    ##> ENSG00000169635   44.4125       -3.44575  0.575597  -5.98639 2.14552e-09
    ##> ENSG00000099917  178.4921       -1.93268  0.337731  -5.72254 1.04946e-08
    ##>                        padj
    ##>                   <numeric>
    ##> ENSG00000185686 1.00642e-45
    ##> ENSG00000283633 8.13127e-11
    ##> ENSG00000197077 1.29793e-09
    ##> ENSG00000099977 1.22115e-07
    ##> ENSG00000169635 2.54459e-07
    ##> ENSG00000099917 1.03721e-06

A quick summary of differentially expressed genes

    summary(deGeneRes)
    ##>
    ##> out of 593 with nonzero total read count
    ##> adjusted p-value < 0.1
    ##> LFC > 0 (up)       : 16, 2.7%
    ##> LFC < 0 (down)     : 22, 3.7%
    ##> outliers [1]       : 0, 0%
    ##> low counts [2]     : 0, 0%
    ##> (mean count < 0)
    ##> [1] see 'cooksCutoff' argument of ?results
    ##> [2] see 'independentFiltering' argument of ?results

We can also visualise the MA-plot for differentially used isoforms using . However, visualizing the MA-plots using the original log-fold change results will be affected by the noise associated with log2 fold changes from low count genes without requiring arbitrary filtering thresholds. As recommended in the [DESeq2tutorial] (http://bioconductor.org/packages/devel/bioc/vignettes/DESeq2/inst/doc/ DESeq2.html#alternative-shrinkage-estimators). we applied the same shrinkage to effect sizes to improve the visualization.

    library(apeglm)
    resLFC <- lfcShrink(dds.deseq, coef = "condition_MCF7_vs_K562", type = "apeglm")
    plotMA(resLFC, ylim = c(-3, 3))

## Identifying differential transcript usage

We used DEXSeq to detect alternative used isoforms.

    library(DEXSeq)
    dxd <- DEXSeqDataSet(countData = round(assays(se)$counts), sampleData = as.data.frame(colData(se)),
        design = ~sample + exon + condition:exon, featureID = rowData(se)$TXNAME, groupID = rowData(se)$GENEID)

    dxr <- DEXSeq(dxd)

    head(dxr)
    ##>
    ##> LRT p-value: full vs reduced
    ##>
    ##> DataFrame with 6 rows and 12 columns
    ##>                 groupID   featureID exonBaseMean dispersion      stat    pvalue
    ##>             <character> <character>    <numeric>  <numeric> <numeric> <numeric>
    ##> gene.1:tx.1      gene.1        tx.1     2.792492  0.1127788 4.7341547 0.0295694
    ##> gene.1:tx.2      gene.1        tx.2     0.727101  0.1325100 0.3163976 0.5737806
    ##> gene.1:tx.3      gene.1        tx.3     2.631925  0.0746159 1.3909273 0.2382486
    ##> gene.4:tx.4      gene.4        tx.4     0.969831  0.4064437 0.0121821 0.9121140
    ##> gene.5:tx.5      gene.5        tx.5     0.367620 12.0000000 0.0573918 0.8106668
    ##> gene.6:tx.6      gene.6        tx.6     7.397162 12.0000000 0.4054379 0.5242942
    ##>                  padj        K562        MCF7 log2fold_MCF7_K562   genomicData
    ##>             <numeric>   <numeric>   <numeric>          <numeric> <GRangesList>
    ##> gene.1:tx.1  0.347046 0.685893146 0.000505759         -11.690661
    ##> gene.1:tx.2  0.902995 0.290118170 0.000505512          -9.672442
    ##> gene.1:tx.3  0.751522 0.631451848 0.271843454          -1.914630
    ##> gene.4:tx.4  1.000000 0.012219824 0.009929559          -0.303242
    ##> gene.5:tx.5        NA 0.009346073 0.005536434          -0.761749
    ##> gene.6:tx.6  0.898745 0.000290816 0.000116959          -1.314388
    ##>                countData
    ##>                 <matrix>
    ##> gene.1:tx.1  18:13:3:...
    ##> gene.1:tx.2    3:3:2:...
    ##> gene.1:tx.3  10:15:3:...
    ##> gene.4:tx.4    6:2:3:...
    ##> gene.5:tx.5    4:1:0:...
    ##> gene.6:tx.6 34:38:13:...

We can visualize the MA-plot

    plotMA(dxr, cex = 0.8)

# Running bambu with large number of samples

For larger sample numbers we recommend to write the processed data to a file. This can be done by providing the readClass.outputDir:

    se <- bambu(reads = bamFiles, rcOutDir = "./bambu/", annotations = annotaiton, genome = genomeSequence)

# Bambu parameters

## Advanced Options

For transcript discovery we recommend to adjust the parameters according to the number of replicates and the sequencing throughput. The most relevant parameters are explained here. You can use any combination of these parameters. ### More stringent filtering thresholds imposed on potential novel transcripts

- Keep novel transcripts with min 5 read count in at least 1 sample:

    bambu(reads, annotations, genome, opt.discovery = list(min.readCount = 5))

- Keep novel transcripts with min 5 samples having at least 2 counts:

    bambu(reads, annotations, genome, opt.discovery = list(min.sampleNumber = 5))

- Filter out transcripts with relative abundance within gene lower than 10%:

    bambu(reads, annotations, genome, opt.discovery = list(min.readFractionByGene = 0.1))

### Quantification without bias correction

The default estimation automatically does bias correction for expression estimates. However, you can choose to perform the quantification without bias correction.

    bambu(reads, annotations, genome, opt.em = list(bias = FALSE))

### Parallel computation

bambu allows parallel computation.

    bambu(reads, annotations, genome, ncore = 8)

See manual for details to customize other conditions.

# Getting help

Questions and issues can be raised at the Bioconductor support site (once bambu is available through bioconductor): https://support.bioconductor.org. Please tag your your posts with bambu.

Alternatively, issues can be raised at the bambu Github repository:https://github.com/GoekeLab/bambu.

# Citing bambu

A manuscript describing bambu is currently in preparation. If you use bambu for your research, please cite using the following doi: 10.5281/zenodo.3900025.

# Session Information

    sessionInfo()
    ##> R version 4.1.1 (2021-08-10)
    ##> Platform: x86_64-w64-mingw32/x64 (64-bit)
    ##> Running under: Windows Server 2012 R2 x64 (build 9600)
    ##>
    ##> Matrix products: default
    ##>
    ##> locale:
    ##> [1] LC_COLLATE=C
    ##> [2] LC_CTYPE=English_United States.1252
    ##> [3] LC_MONETARY=English_United States.1252
    ##> [4] LC_NUMERIC=C
    ##> [5] LC_TIME=English_United States.1252
    ##>
    ##> attached base packages:
    ##> [1] parallel  stats4    stats     graphics  grDevices utils     datasets
    ##> [8] methods   base
    ##>
    ##> other attached packages:
    ##>  [1] DEXSeq_1.38.0
    ##>  [2] RColorBrewer_1.1-2
    ##>  [3] AnnotationDbi_1.54.1
    ##>  [4] BiocParallel_1.26.2
    ##>  [5] apeglm_1.14.0
    ##>  [6] DESeq2_1.32.0
    ##>  [7] ggplot2_3.3.5
    ##>  [8] BSgenome.Hsapiens.NCBI.GRCh38_1.3.1000
    ##>  [9] BSgenome_1.60.0
    ##> [10] rtracklayer_1.52.1
    ##> [11] Rsamtools_2.8.0
    ##> [12] Biostrings_2.60.2
    ##> [13] XVector_0.32.0
    ##> [14] NanoporeRNASeq_1.2.1
    ##> [15] ExperimentHub_2.0.0
    ##> [16] AnnotationHub_3.0.1
    ##> [17] BiocFileCache_2.0.0
    ##> [18] dbplyr_2.1.1
    ##> [19] bambu_1.2.1
    ##> [20] SummarizedExperiment_1.22.0
    ##> [21] Biobase_2.52.0
    ##> [22] GenomicRanges_1.44.0
    ##> [23] GenomeInfoDb_1.28.3
    ##> [24] IRanges_2.26.0
    ##> [25] S4Vectors_0.30.0
    ##> [26] BiocGenerics_0.38.0
    ##> [27] MatrixGenerics_1.4.3
    ##> [28] matrixStats_0.60.1
    ##>
    ##> loaded via a namespace (and not attached):
    ##>   [1] utf8_1.2.2                    tidyselect_1.1.1
    ##>   [3] RSQLite_2.2.8                 htmlwidgets_1.5.3
    ##>   [5] grid_4.1.1                    munsell_0.5.0
    ##>   [7] codetools_0.2-18              statmod_1.4.36
    ##>   [9] withr_2.4.2                   colorspace_2.0-2
    ##>  [11] filelock_1.0.2                OrganismDbi_1.34.0
    ##>  [13] highr_0.9                     knitr_1.33
    ##>  [15] rstudioapi_0.13               labeling_0.4.2
    ##>  [17] bbmle_1.0.24                  GenomeInfoDbData_1.2.6
    ##>  [19] hwriter_1.3.2                 bit64_4.0.5
    ##>  [21] farver_2.1.0                  coda_0.19-4
    ##>  [23] vctrs_0.3.8                   generics_0.1.0
    ##>  [25] xfun_0.25                     biovizBase_1.40.0
    ##>  [27] R6_2.5.1                      doParallel_1.0.16
    ##>  [29] clue_0.3-59                   locfit_1.5-9.4
    ##>  [31] AnnotationFilter_1.16.0       bitops_1.0-7
    ##>  [33] cachem_1.0.6                  reshape_0.8.8
    ##>  [35] DelayedArray_0.18.0           assertthat_0.2.1
    ##>  [37] promises_1.2.0.1              BiocIO_1.2.0
    ##>  [39] scales_1.1.1                  nnet_7.3-16
    ##>  [41] gtable_0.3.0                  Cairo_1.5-12.2
    ##>  [43] ggbio_1.40.0                  ensembldb_2.16.4
    ##>  [45] rlang_0.4.11                  genefilter_1.74.0
    ##>  [47] GlobalOptions_0.1.2           splines_4.1.1
    ##>  [49] lazyeval_0.2.2                dichromat_2.0-0
    ##>  [51] checkmate_2.0.0               BiocManager_1.30.16
    ##>  [53] yaml_2.2.1                    reshape2_1.4.4
    ##>  [55] GenomicFeatures_1.44.2        backports_1.2.1
    ##>  [57] httpuv_1.6.2                  Hmisc_4.5-0
    ##>  [59] RBGL_1.68.0                   tools_4.1.1
    ##>  [61] ellipsis_0.3.2                jquerylib_0.1.4
    ##>  [63] Rcpp_1.0.7                    plyr_1.8.6
    ##>  [65] base64enc_0.1-3               progress_1.2.2
    ##>  [67] zlibbioc_1.38.0               purrr_0.3.4
    ##>  [69] RCurl_1.98-1.4                prettyunits_1.1.1
    ##>  [71] rpart_4.1-15                  GetoptLong_1.0.5
    ##>  [73] cluster_2.1.2                 magrittr_2.0.1
    ##>  [75] data.table_1.14.0             magick_2.7.3
    ##>  [77] circlize_0.4.13               mvtnorm_1.1-2
    ##>  [79] ProtGenerics_1.24.0           hms_1.1.0
    ##>  [81] mime_0.11                     evaluate_0.14
    ##>  [83] xtable_1.8-4                  XML_3.99-0.7
    ##>  [85] emdbook_1.3.12                jpeg_0.1-9
    ##>  [87] gridExtra_2.3                 shape_1.4.6
    ##>  [89] bdsmatrix_1.3-4               compiler_4.1.1
    ##>  [91] biomaRt_2.48.3                tibble_3.1.4
    ##>  [93] crayon_1.4.1                  htmltools_0.5.2
    ##>  [95] later_1.3.0                   Formula_1.2-4
    ##>  [97] geneplotter_1.70.0            DBI_1.1.1
    ##>  [99] formatR_1.11                  ComplexHeatmap_2.8.0
    ##> [101] MASS_7.3-54                   rappdirs_0.3.3
    ##> [103] Matrix_1.3-4                  pkgconfig_2.0.3
    ##> [105] GenomicAlignments_1.28.0      numDeriv_2016.8-1.1
    ##> [107] foreign_0.8-81                xml2_1.3.2
    ##> [109] foreach_1.5.1                 annotate_1.70.0
    ##> [111] bslib_0.2.5.1                 stringr_1.4.0
    ##> [113] VariantAnnotation_1.38.0      digest_0.6.27
    ##> [115] graph_1.70.0                  rmarkdown_2.10
    ##> [117] htmlTable_2.2.1               restfulr_0.0.13
    ##> [119] curl_4.3.2                    shiny_1.6.0
    ##> [121] rjson_0.2.20                  lifecycle_1.0.0
    ##> [123] jsonlite_1.7.2                fansi_0.5.0
    ##> [125] pillar_1.6.2                  lattice_0.20-44
    ##> [127] GGally_2.1.2                  KEGGREST_1.32.0
    ##> [129] fastmap_1.1.0                 httr_1.4.2
    ##> [131] survival_3.2-13               interactiveDisplayBase_1.30.0
    ##> [133] glue_1.4.2                    png_0.1-7
    ##> [135] iterators_1.0.13              BiocVersion_3.13.1
    ##> [137] glmnet_4.1-2                  bit_4.0.4
    ##> [139] stringi_1.7.4                 sass_0.4.0
    ##> [141] blob_1.2.2                    latticeExtra_0.6-29
    ##> [143] memoise_2.0.0                 dplyr_1.0.7