Data included in this package was generated by harmonizing all
publicly available bulk RNA-seq samples from human primary colorectal
tissue available through NCBI’s Sequence Read Archive and database of Genotypes and
Phenotypes, NCI’s Genomic Data
Commons, and the NIH-funded BarcUVa-Seq project. FASTQ files were
downloaded directly or generated from BAM files using biobambam2.
Gene expression estimates were generated from FASTQ files using Salmon and aggregated
from quant.sf files using tximport.
The original processed data are stored as tab-delimited text on Synapse under Synapse ID syn22237139
and packaged as SummarizedExperiment objects on
ExperimentHub to facilitate reproduction and extension of
results published in Dampier et al. (PMCID: PMC7386360, PMID:
32764205).
The following example demonstrates how to download the dataset from
ExperimentHub.
First, make sure the Bioconductor packages BiocManager,
SummarizedExperiment, and ExperimentHub are
installed:
if (!requireNamespace("BiocManager", quietly=TRUE)) {
install.packages("BiocManager")
}
BiocManager::install(c("SummarizedExperiment", "ExperimentHub", "FieldEffectCrc"))Second, load the SummarizedExperiment and
ExperimentHub packages:
## Loading required package: MatrixGenerics
## Loading required package: matrixStats
##
## Attaching package: 'MatrixGenerics'
## The following objects are masked from 'package:matrixStats':
##
## colAlls, colAnyNAs, colAnys, colAvgsPerRowSet, colCollapse,
## colCounts, colCummaxs, colCummins, colCumprods, colCumsums,
## colDiffs, colIQRDiffs, colIQRs, colLogSumExps, colMadDiffs,
## colMads, colMaxs, colMeans2, colMedians, colMins, colOrderStats,
## colProds, colQuantiles, colRanges, colRanks, colSdDiffs, colSds,
## colSums2, colTabulates, colVarDiffs, colVars, colWeightedMads,
## colWeightedMeans, colWeightedMedians, colWeightedSds,
## colWeightedVars, rowAlls, rowAnyNAs, rowAnys, rowAvgsPerColSet,
## rowCollapse, rowCounts, rowCummaxs, rowCummins, rowCumprods,
## rowCumsums, rowDiffs, rowIQRDiffs, rowIQRs, rowLogSumExps,
## rowMadDiffs, rowMads, rowMaxs, rowMeans2, rowMedians, rowMins,
## rowOrderStats, rowProds, rowQuantiles, rowRanges, rowRanks,
## rowSdDiffs, rowSds, rowSums2, rowTabulates, rowVarDiffs, rowVars,
## rowWeightedMads, rowWeightedMeans, rowWeightedMedians,
## rowWeightedSds, rowWeightedVars
## Loading required package: GenomicRanges
## Loading required package: stats4
## Loading required package: BiocGenerics
## Loading required package: generics
##
## Attaching package: 'generics'
## The following objects are masked from 'package:base':
##
## as.difftime, as.factor, as.ordered, intersect, is.element, setdiff,
## setequal, union
##
## Attaching package: 'BiocGenerics'
## The following objects are masked from 'package:stats':
##
## IQR, mad, sd, var, xtabs
## The following objects are masked from 'package:base':
##
## anyDuplicated, aperm, append, as.data.frame, basename, cbind,
## colnames, dirname, do.call, duplicated, eval, evalq, Filter, Find,
## get, grep, grepl, is.unsorted, lapply, Map, mapply, match, mget,
## order, paste, pmax, pmax.int, pmin, pmin.int, Position, rank,
## rbind, Reduce, rownames, sapply, saveRDS, table, tapply, unique,
## unsplit, which.max, which.min
## Loading required package: S4Vectors
##
## Attaching package: 'S4Vectors'
## The following object is masked from 'package:utils':
##
## findMatches
## The following objects are masked from 'package:base':
##
## expand.grid, I, unname
## Loading required package: IRanges
## Loading required package: Seqinfo
## Loading required package: Biobase
## Welcome to Bioconductor
##
## Vignettes contain introductory material; view with
## 'browseVignettes()'. To cite Bioconductor, see
## 'citation("Biobase")', and for packages 'citation("pkgname")'.
##
## Attaching package: 'Biobase'
## The following object is masked from 'package:MatrixGenerics':
##
## rowMedians
## The following objects are masked from 'package:matrixStats':
##
## anyMissing, rowMedians
## Loading required package: AnnotationHub
## Loading required package: BiocFileCache
## Loading required package: dbplyr
##
## Attaching package: 'AnnotationHub'
## The following object is masked from 'package:Biobase':
##
## cache
Third, find the FieldEffectCrc data objects and look at
their descriptions:
## [1] "cohort A from Dampier et al." "cohort B from Dampier et al."
## [3] "cohort C from Dampier et al."
## ExperimentHub with 3 records
## # snapshotDate(): 2026-04-21
## # $dataprovider: Synapse
## # $species: Homo sapiens
## # $rdataclass: SummarizedExperiment
## # additional mcols(): taxonomyid, genome, description,
## # coordinate_1_based, maintainer, rdatadateadded, preparerclass, tags,
## # rdatapath, sourceurl, sourcetype
## # retrieve records with, e.g., 'object[["EH3524"]]'
##
## title
## EH3524 | cohort A from Dampier et al.
## EH3525 | cohort B from Dampier et al.
## EH3526 | cohort C from Dampier et al.
## DataFrame with 3 rows and 15 columns
## title dataprovider species taxonomyid genome
## <character> <character> <character> <integer> <character>
## EH3524 cohort A from Dampie.. Synapse Homo sapiens 9606 GRCh38
## EH3525 cohort B from Dampie.. Synapse Homo sapiens 9606 GRCh38
## EH3526 cohort C from Dampie.. Synapse Homo sapiens 9606 GRCh38
## description coordinate_1_based maintainer
## <character> <integer> <character>
## EH3524 Salmon-generated tra.. 1 Chris Dampier <chd5n..
## EH3525 Salmon-generated tra.. 1 Chris Dampier <chd5n..
## EH3526 Salmon-generated tra.. 1 Chris Dampier <chd5n..
## rdatadateadded preparerclass
## <character> <character>
## EH3524 2020-07-10 FieldEffectCrc
## EH3525 2020-07-10 FieldEffectCrc
## EH3526 2020-07-10 FieldEffectCrc
## tags rdataclass
## <AsIs> <character>
## EH3524 ExperimentData,ReproducibleResearch,Tissue,... SummarizedExperiment
## EH3525 ExperimentData,ReproducibleResearch,Tissue,... SummarizedExperiment
## EH3526 ExperimentData,ReproducibleResearch,Tissue,... SummarizedExperiment
## rdatapath sourceurl sourcetype
## <character> <character> <character>
## EH3524 FieldEffectCrc/Field.. https://www.synapse... tar.gz
## EH3525 FieldEffectCrc/Field.. https://www.synapse... tar.gz
## EH3526 FieldEffectCrc/Field.. https://www.synapse... tar.gz
## [1] "/github/home/.cache/R/ExperimentHub"
Fourth, explore the metadata of a particular file. Let’s look at the data for cohort A:
## ExperimentHub with 1 record
## # snapshotDate(): 2026-04-21
## # names(): EH3524
## # package(): FieldEffectCrc
## # $dataprovider: Synapse
## # $species: Homo sapiens
## # $rdataclass: SummarizedExperiment
## # $rdatadateadded: 2020-07-10
## # $title: cohort A from Dampier et al.
## # $description: Salmon-generated transcript-level abundance estimates summar...
## # $taxonomyid: 9606
## # $genome: GRCh38
## # $sourcetype: tar.gz
## # $sourceurl: https://www.synapse.org/#!Synapse:syn22237139/files/
## # $sourcesize: NA
## # $tags: c("ExperimentData", "ReproducibleResearch", "Tissue",
## # "Homo_sapiens_Data", "ColonCancerData", "RNASeqData",
## # "ExpressionData", "ExperimentHub")
## # retrieve record with 'object[["EH3524"]]'
Fifth, download the data object itself as a
SummarizedExperiment:
## see ?FieldEffectCrc and browseVignettes('FieldEffectCrc') for documentation
## downloading 1 resources
## retrieving 1 resource
## loading from cache
## class: SummarizedExperiment
## dim: 37361 834
## metadata(4): cohort build assay feature
## assays(3): abundance counts length
## rownames(37361): ENSG00000000003 ENSG00000000005 ... ENSG00000283698
## ENSG00000283700
## rowData names(0):
## colnames(834): AMC_10 AMC_12 ... VM1421 VM1422
## colData names(27): dirName projId ... percMap data
## see ?FieldEffectCrc and browseVignettes('FieldEffectCrc') for documentation
## loading from cache
## [[1]]
## class: SummarizedExperiment
## dim: 37361 834
## metadata(4): cohort build assay feature
## assays(3): abundance counts length
## rownames(37361): ENSG00000000003 ENSG00000000005 ... ENSG00000283698
## ENSG00000283700
## rowData names(0):
## colnames(834): AMC_10 AMC_12 ... VM1421 VM1422
## colData names(27): dirName projId ... percMap data
Since the data is a SummarizedExperiment, the different
phenotypes can be accessed using colData(). The phenotype
of interest in the field effect analysis is referred to as
sampType:
## CRC HLT NAT
## 311 462 61
To immediately access the count data for the 834 samples in cohort A,
load the SummarizedExperiment object for cohort A as
demonstrated in the Installation section
immediately above. Then use the assays() accessor function
to extract the counts assay, which is the second assay in
the SummarizedExperiment:
Note that assay(), the singular as opposed to plural,
will by default extract the first assay element from a
SummarizedExperiment but will extract the ’i’th assay
element with the assay(se, i) syntax:
The two alternatives are equivalent:
## [1] TRUE
We are interested in conducting a differential expression analysis
using DESeq2 to identify genes over- and under-expressed in
different colorectal tissue phenotypes. Due to substantial technical
artifacts between single-end and paired-end library formats observed in
the full FieldEffectCrc data set, samples are grouped
according to library format, with paired-end samples in cohorts A and B
and single-end samples in cohort C. Cohort A is the primary analysis
cohort and the one we want to use to discover differentially expressed
genes. To begin, load cohort A as demonstrated in the Installation section immediately above if not
already loaded.
In the following steps, we will use DESeq2 to perform
differential expression analysis on expression data stored in the
SummarizedExperiment object for cohort A. We will adjust
for latent batch effects with surrogate variable analysis as implemented
in the sva package. This analysis would typically consume
excess memory and time, so for the purpose of demonstration, we perform
the analysis on a small subset of the full data.
In order to take advantage of the feature lengths preserved by
tximport, we will recreate a tximport object
from the SummarizedExperiment object downloaded from
ExperimentHub and use the
DESeqDataSetFromTximport() function to create the
DESeqDataSet object. Alternatively, the
SummarizedExperiment object itself could be used to create
the DESeqDataSet object using the
DESeqDataSet() function, but the order of the assays would
need to be re-arranged and the counts would need to be rounded, as the
DESeqDataSet() function expects counts with
integer values to be the first assay in a
SummarizedExperiment object, and abundance
with floating-point values is the first assay in the
FieldEffectCrc objects to facilitate conversion to
tximport objects. Such a re-ordering is facilitated by the
FieldEffectCrc::reorder_assays() function. Yet another
option is to extract the counts assay as a matrix and use
the DESeqDataSetFromMatrix() function to create the
DESeqDataSet object. Since there are probably some benefits
to feature length normalization as implemented in DESeq2
when such information is available, we demonstrate creation of the
tximport object.
First, make the tximport object, which is just an object
of class list from base R:
## manual construction
txi <- as.list(assays(se))
txi$countsFromAbundance <- "no"
## convenience function construction
txi <- make_txi(se)Next, we could assign the clinical annotations from
colData(se) to an S4Vectors::DataFrame or a
base::data.frame object, since that is what
DESeqDataSetFromTximport() expects for the
colData argument. However, the colData slot of
a SummarizedExperiment object already stores the clinical
annotations as an S4Vectors::DataFrame, so we are ready to
create the DESeqDataSet object:
if (!requireNamespace("DESeq2", quietly=TRUE)) {
BiocManager::install("DESeq2")
}
library(DESeq2)
dds <- DESeqDataSetFromTximport(txi, colData(se), ~ sampType)## using counts and average transcript lengths from tximport
Note that we are interested in expression differences between
phenotypes, which are coded in the sampType field, so we
include sampType in our preliminary design.
Normally, we would pre-filter genes to select genes whose quantities are likely to be estimated accurately. We could use something like the following code, which selects for genes with a count greater than 10 RNA molecules in at least a third of all samples:
countLimit <- 10
sampleLimit <- (1/3) * ncol(dds)
keep <- rowSums( counts(dds) > countLimit ) >= sampleLimit
dds <- dds[keep, ]However, to expedite subsequent computational steps in this demonstration, we will select a random subset of genes and samples for analysis and then filter out any gene with a count less than 10 across all samples:
Amazingly, DESeq2 estimates size factors
(i.e. normalization factors based on library size and feature length)
and dispersions for every gene, fits negative binomial models for every
gene, and performs a Wald test for every gene in a single function:
## 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
## -- replacing outliers and refitting for 144 genes
## -- DESeq argument 'minReplicatesForReplace' = 7
## -- original counts are preserved in counts(dds)
## estimating dispersions
## fitting model and testing
Pretty incredible. Unfortunately, we have to do some more work before
we can fit useful models. The size factor estimates are the key result
of the DESeq() function at this stage.
If we trusted our high-throughput assays to be perfect
representations of the underlying biology they were designed to measure,
we would be ready to test for differential expression. However, our
dataset is composed of samples from several studies collected and
processed in various ways over several years, so we have reason to
suspect there are latent factors driving non-biological variation in the
expression data. Fortunately, we can use sva to estimate
the latent factors and include them in our DESeq2
design.
For a full tutorial on how to use the sva package, see
the package vignette.
For this demonstration, we will provide only cursory motivations for the
code.
The sva functions will take the normalized count data as
well as model matrices as inputs. The full model matrix should include
the variables of interest (e.g. sampType) as well as
adjustment variables (e.g. sex, age), which we
do not use here. The null model matrix should include adjustment
variables only (i.e. no variables of interest). Without any adjustment
variables, the null model includes an intercept term alone.
The sva package offers two approaches for estimating the
number of surrogate variables that should be included in a differential
expression model, the Buja Eyuboglu and Leek approaches. Buja Eyuboglu
is the default approach.
## Loading required package: mgcv
## Loading required package: nlme
##
## Attaching package: 'nlme'
## The following object is masked from 'package:IRanges':
##
## collapse
## This is mgcv 1.9-4. For overview type '?mgcv'.
## Loading required package: genefilter
##
## Attaching package: 'genefilter'
## The following objects are masked from 'package:MatrixGenerics':
##
## rowSds, rowVars
## The following objects are masked from 'package:matrixStats':
##
## rowSds, rowVars
## Loading required package: BiocParallel
The crucial function for estimating surrogate variables in RNA-seq
data is svaseq():
## Number of significant surrogate variables is: 1
## Iteration (out of 5 ):1 2 3 4 5
The output is a list of 4 elements, the first of which is the latent
factor estimate with a vector for each factor. The name of this element
is sv.
We want to include the latent factors as adjustment variables in our
statistical testing. Here, we add the surrogate variables to
colData and update the DESeqDataSet design
formula:
Now that we have the surrogate variables in the
DESeqDataSet, we can perform the differential expression
analysis we set out to do:
## using pre-existing normalization factors
## estimating dispersions
## found already estimated dispersions, replacing these
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## fitting model and testing
We want to extract results from each of the following 3 comparisons:
With three categories under consideration, the DESeq()
function call tests the first level against the other two, but the
second and third levels are not tested against each other. (Note that
the order of the levels is simply alphabetical if they are not
explicitly set.) Furthermore, the results reported with the
results() function are for the comparison of the first
level against the last by default. Therefore, in order to extract all
the results of interest, we set contrasts as follows:
cons <- list()
m <- combn(levels(colData(dds)$sampType), 2)
for (i in seq_len(ncol(m))) {
cons[[i]] <- c("sampType", rev(m[, i]))
names(cons) <- c(
names(cons)[seq_len(length(cons) - 1)], paste(rev(m[, i]), collapse="v")
)
}
res <- list()
for (i in seq_len(length(cons))) {
res[[i]] <- results(dds, contrast=cons[[i]], alpha=0.05) ## default alpha is 0.1
}
names(res) <- names(cons)Let’s take a look at the results:
## $HLTvCRC
## log2 fold change (MLE): sampType HLT vs CRC
## Wald test p-value: sampType HLT vs CRC
## DataFrame with 6 rows and 6 columns
## baseMean log2FoldChange lfcSE stat pvalue
## <numeric> <numeric> <numeric> <numeric> <numeric>
## ENSG00000234545 888.8866 0.1379632 0.0508032 2.71564 6.61479e-03
## ENSG00000166828 337.4201 1.0422025 0.2804839 3.71573 2.02617e-04
## ENSG00000136866 67.2355 0.2254938 0.1048593 2.15044 3.15203e-02
## ENSG00000060971 2442.4473 0.0975478 0.0709722 1.37445 1.69302e-01
## ENSG00000181195 48.5827 -1.4570428 0.3346561 -4.35385 1.33767e-05
## ENSG00000242612 947.3951 -0.1400999 0.0820405 -1.70769 8.76936e-02
## padj
## <numeric>
## ENSG00000234545 8.13627e-03
## ENSG00000166828 2.68131e-04
## ENSG00000136866 3.71410e-02
## ENSG00000060971 1.87974e-01
## ENSG00000181195 1.87611e-05
## ENSG00000242612 1.00088e-01
##
## $NATvCRC
## log2 fold change (MLE): sampType NAT vs CRC
## Wald test p-value: sampType NAT vs CRC
## DataFrame with 6 rows and 6 columns
## baseMean log2FoldChange lfcSE stat pvalue
## <numeric> <numeric> <numeric> <numeric> <numeric>
## ENSG00000234545 888.8866 -0.0168462 0.0873135 -0.192939 0.84700673
## ENSG00000166828 337.4201 -1.3793448 0.4835885 -2.852311 0.00434026
## ENSG00000136866 67.2355 0.1357423 0.1797289 0.755262 0.45009202
## ENSG00000060971 2442.4473 0.0503807 0.1221588 0.412420 0.68003144
## ENSG00000181195 48.5827 0.8143387 0.5460146 1.491423 0.13585049
## ENSG00000242612 947.3951 -0.1228458 0.1411148 -0.870539 0.38400619
## padj
## <numeric>
## ENSG00000234545 0.974947
## ENSG00000166828 0.147963
## ENSG00000136866 0.872271
## ENSG00000060971 0.951981
## ENSG00000181195 0.628659
## ENSG00000242612 0.846757
##
## $NATvHLT
## log2 fold change (MLE): sampType NAT vs HLT
## Wald test p-value: sampType NAT vs HLT
## DataFrame with 6 rows and 6 columns
## baseMean log2FoldChange lfcSE stat pvalue
## <numeric> <numeric> <numeric> <numeric> <numeric>
## ENSG00000234545 888.8866 -0.1548094 0.0842949 -1.836523 6.62804e-02
## ENSG00000166828 337.4201 -2.4215473 0.4665720 -5.190083 2.10201e-07
## ENSG00000136866 67.2355 -0.0897515 0.1736111 -0.516968 6.05178e-01
## ENSG00000060971 2442.4473 -0.0471670 0.1178302 -0.400296 6.88938e-01
## ENSG00000181195 48.5827 2.2713814 0.5359388 4.238136 2.25383e-05
## ENSG00000242612 947.3951 0.0172541 0.1361632 0.126716 8.99165e-01
## padj
## <numeric>
## ENSG00000234545 8.45593e-02
## ENSG00000166828 4.56297e-07
## ENSG00000136866 6.45753e-01
## ENSG00000060971 7.23042e-01
## ENSG00000181195 4.15325e-05
## ENSG00000242612 9.11316e-01
##
## out of 6000 with nonzero total read count
## adjusted p-value < 0.05
## LFC > 0 (up) : 2450, 41%
## LFC < 0 (down) : 2678, 45%
## outliers [1] : 0, 0%
## low counts [2] : 0, 0%
## (mean count < 6)
## [1] see 'cooksCutoff' argument of ?results
## [2] see 'independentFiltering' argument of ?results
##
##
## out of 6000 with nonzero total read count
## adjusted p-value < 0.05
## LFC > 0 (up) : 38, 0.63%
## LFC < 0 (down) : 65, 1.1%
## outliers [1] : 0, 0%
## low counts [2] : 0, 0%
## (mean count < 6)
## [1] see 'cooksCutoff' argument of ?results
## [2] see 'independentFiltering' argument of ?results
##
##
## out of 6000 with nonzero total read count
## adjusted p-value < 0.05
## LFC > 0 (up) : 2384, 40%
## LFC < 0 (down) : 2173, 36%
## outliers [1] : 0, 0%
## low counts [2] : 0, 0%
## (mean count < 6)
## [1] see 'cooksCutoff' argument of ?results
## [2] see 'independentFiltering' argument of ?results
## $HLTvCRC
## NULL
##
## $NATvCRC
## NULL
##
## $NATvHLT
## NULL
## R version 4.6.1 (2026-06-24)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 26.04.1 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.32.so; LAPACK version 3.12.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] sva_3.60.0 BiocParallel_1.46.0
## [3] genefilter_1.94.0 mgcv_1.9-4
## [5] nlme_3.1-171 DESeq2_1.52.0
## [7] FieldEffectCrc_1.22.0 ExperimentHub_3.2.2
## [9] AnnotationHub_4.2.2 BiocFileCache_3.2.0
## [11] dbplyr_2.6.0 SummarizedExperiment_1.42.0
## [13] Biobase_2.72.0 GenomicRanges_1.64.0
## [15] Seqinfo_1.2.0 IRanges_2.46.0
## [17] S4Vectors_0.50.3 BiocGenerics_0.58.1
## [19] generics_0.1.4 MatrixGenerics_1.24.0
## [21] matrixStats_1.5.0 BiocStyle_2.40.0
##
## loaded via a namespace (and not attached):
## [1] tidyselect_1.2.1 dplyr_1.2.1 farver_2.1.2
## [4] blob_1.3.0 filelock_1.0.3 Biostrings_2.80.2
## [7] S7_0.2.2 fastmap_1.2.0 XML_3.99-0.25
## [10] digest_0.6.39 lifecycle_1.0.5 statmod_1.5.2
## [13] survival_3.8-12 KEGGREST_1.52.2 RSQLite_3.53.3
## [16] magrittr_2.0.5 compiler_4.6.1 rlang_1.3.0
## [19] sass_0.4.10 tools_4.6.1 yaml_2.3.12
## [22] knitr_1.52 S4Arrays_1.12.1 bit_4.6.0
## [25] curl_8.0.0 DelayedArray_0.38.2 RColorBrewer_1.1-3
## [28] abind_1.4-8 withr_3.0.3 purrr_1.2.2
## [31] sys_3.4.3 grid_4.6.1 xtable_1.8-8
## [34] edgeR_4.10.5 ggplot2_4.0.3 scales_1.4.0
## [37] cli_3.6.6 rmarkdown_2.32 crayon_1.5.3
## [40] httr_1.4.9 RUnit_0.4.33.1 DBI_1.3.0
## [43] cachem_1.1.0 splines_4.6.1 parallel_4.6.1
## [46] AnnotationDbi_1.74.0 BiocManager_1.30.27 XVector_0.52.0
## [49] vctrs_0.7.3 Matrix_1.7-6 jsonlite_2.0.0
## [52] bit64_4.8.6 maketools_1.3.2 locfit_1.5-9.12
## [55] limma_3.68.5 jquerylib_0.1.4 annotate_1.90.0
## [58] glue_1.8.1 codetools_0.2-20 gtable_0.3.6
## [61] BiocVersion_3.23.1 tibble_3.3.1 pillar_1.11.1
## [64] rappdirs_0.3.4 htmltools_0.5.9 R6_2.6.1
## [67] httr2_1.3.0 evaluate_1.0.5 lattice_0.23-1
## [70] png_0.1-9 memoise_2.0.1 bslib_0.12.0
## [73] Rcpp_1.1.2 SparseArray_1.12.3 xfun_0.61
## [76] buildtools_1.0.0 pkgconfig_2.0.3