exploreSE is package that provides an interactive Shiny-based user interface for exploring transcriptional data and analysis results stored in summarizedExperiment or DeeDeeExperiment format. The aim is to facilitate easy comparison between different model approaches on a single data set.
The package can be installed via the BiocManager by
starting R and running:
if (!requireNamespace("BiocManager", quietly = TRUE)) {
install.packages("BiocManager")
}
BiocManager::install("exploreSE")Once installed, the packages can be accessed through the following bit of code:
To explore the results of differential expression analysis, we need to organise them in the structure and you will learn how to do that in this vignette. If you want to explore on your own, you can run the following code and start exploring the example data.
For the purposes of this example, we’ll be using the
airway data. It is part of the airway
package, containing RNA-Seq data from different airway smooth muscle
cell lines either untreated or treated with dexamethasone.
library(airway)
#> Loading required package: SummarizedExperiment
#> 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 object is masked from 'package:utils':
#>
#> data
#> 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, scale, sequence, table,
#> tapply, transform, 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
data(airway)
airway
#> class: RangedSummarizedExperiment
#> dim: 63677 8
#> metadata(1): ''
#> assays(1): counts
#> rownames(63677): ENSG00000000003 ENSG00000000005 ... ENSG00000273492
#> ENSG00000273493
#> rowData names(10): gene_id gene_name ... seq_coord_system symbol
#> colnames(8): SRR1039508 SRR1039509 ... SRR1039520 SRR1039521
#> colData names(9): SampleName cell ... Sample BioSampleOut of the box, the airway object is
summarizedExperiment object, containing eight samples from
four cell lines. This information is available in
coldata(airway).
colData(airway)
#> DataFrame with 8 rows and 9 columns
#> SampleName cell dex albut Run avgLength
#> <factor> <factor> <factor> <factor> <factor> <integer>
#> SRR1039508 GSM1275862 N61311 untrt untrt SRR1039508 126
#> SRR1039509 GSM1275863 N61311 trt untrt SRR1039509 126
#> SRR1039512 GSM1275866 N052611 untrt untrt SRR1039512 126
#> SRR1039513 GSM1275867 N052611 trt untrt SRR1039513 87
#> SRR1039516 GSM1275870 N080611 untrt untrt SRR1039516 120
#> SRR1039517 GSM1275871 N080611 trt untrt SRR1039517 126
#> SRR1039520 GSM1275874 N061011 untrt untrt SRR1039520 101
#> SRR1039521 GSM1275875 N061011 trt untrt SRR1039521 98
#> Experiment Sample BioSample
#> <factor> <factor> <factor>
#> SRR1039508 SRX384345 SRS508568 SAMN02422669
#> SRR1039509 SRX384346 SRS508567 SAMN02422675
#> SRR1039512 SRX384349 SRS508571 SAMN02422678
#> SRR1039513 SRX384350 SRS508572 SAMN02422670
#> SRR1039516 SRX384353 SRS508575 SAMN02422682
#> SRR1039517 SRX384354 SRS508576 SAMN02422673
#> SRR1039520 SRX384357 SRS508579 SAMN02422683
#> SRR1039521 SRX384358 SRS508580 SAMN02422677In this vignette, we will subset airway to only contain
protein-coding genes. The required information is stored in its
rowData, accessible through
rowData(airway).
rowData(airway)
#> DataFrame with 63677 rows and 10 columns
#> gene_id gene_name entrezid gene_biotype
#> <character> <character> <integer> <character>
#> ENSG00000000003 ENSG00000000003 TSPAN6 NA protein_coding
#> ENSG00000000005 ENSG00000000005 TNMD NA protein_coding
#> ENSG00000000419 ENSG00000000419 DPM1 NA protein_coding
#> ENSG00000000457 ENSG00000000457 SCYL3 NA protein_coding
#> ENSG00000000460 ENSG00000000460 C1orf112 NA protein_coding
#> ... ... ... ... ...
#> ENSG00000273489 ENSG00000273489 RP11-180C16.1 NA antisense
#> ENSG00000273490 ENSG00000273490 TSEN34 NA protein_coding
#> ENSG00000273491 ENSG00000273491 RP11-138A9.2 NA lincRNA
#> ENSG00000273492 ENSG00000273492 AP000230.1 NA lincRNA
#> ENSG00000273493 ENSG00000273493 RP11-80H18.4 NA lincRNA
#> gene_seq_start gene_seq_end seq_name seq_strand
#> <integer> <integer> <character> <integer>
#> ENSG00000000003 99883667 99894988 X -1
#> ENSG00000000005 99839799 99854882 X 1
#> ENSG00000000419 49551404 49575092 20 -1
#> ENSG00000000457 169818772 169863408 1 -1
#> ENSG00000000460 169631245 169823221 1 1
#> ... ... ... ... ...
#> ENSG00000273489 131178723 131182453 7 -1
#> ENSG00000273490 54693789 54697585 HSCHR19LRC_LRC_J_CTG1 1
#> ENSG00000273491 130600118 130603315 HG1308_PATCH 1
#> ENSG00000273492 27543189 27589700 21 1
#> ENSG00000273493 58315692 58315845 3 1
#> seq_coord_system symbol
#> <integer> <character>
#> ENSG00000000003 NA TSPAN6
#> ENSG00000000005 NA TNMD
#> ENSG00000000419 NA DPM1
#> ENSG00000000457 NA SCYL3
#> ENSG00000000460 NA C1orf112
#> ... ... ...
#> ENSG00000273489 NA RP11-180C16.1
#> ENSG00000273490 NA TSEN34
#> ENSG00000273491 NA RP11-138A9.2
#> ENSG00000273492 NA AP000230.1
#> ENSG00000273493 NA RP11-80H18.4dim(airway)
#> [1] 63677 8
airway <- airway[rowData(airway)$gene_biotype == "protein_coding", ]
dim(airway)
#> [1] 22810 8Let’s start our anaylsis. Using the DESeq2
package, we will convert airway into an DESeqDataSet and
build a simple model based the dexamethasone stimulation stored in the
dex variable.
library(DESeq2)
airway <- DESeqDataSet(airway, design = ~dex)
airway <- DESeq(airway)
#> estimating size factors
#> estimating dispersions
#> gene-wise dispersion estimates
#> mean-dispersion relationship
#> final dispersion estimates
#> fitting model and testing
baseline <- results(airway)In addition, we’ll build a second model, where we control for the
effect of the cell line, stored in the cell variable:
design(airway) <- ~ cell + dex
airway <- DESeq(airway)
#> using pre-existing size factors
#> estimating dispersions
#> found already estimated dispersions, replacing these
#> gene-wise dispersion estimates
#> mean-dispersion relationship
#> final dispersion estimates
#> fitting model and testing
cell_controlled <- results(airway)Using the DeeDeeExperiment package, we will store these results in the their respective slots.
library(DeeDeeExperiment)
#> Loading required package: SingleCellExperiment
airway <- DeeDeeExperiment(airway)
airway <- addDEA(airway, baseline)
airway <- addDEA(airway, cell_controlled)Let’s take a look:
airway
#> class: DeeDeeExperiment
#> dim: 22810 8
#> metadata(3): '' version singlecontrast
#> assays(4): counts mu H cooks
#> rownames(22810): ENSG00000000003 ENSG00000000005 ... ENSG00000273482
#> ENSG00000273490
#> rowData names(50): gene_id gene_name ... cell_controlled_pvalue
#> cell_controlled_padj
#> colnames(8): SRR1039508 SRR1039509 ... SRR1039520 SRR1039521
#> colData names(10): SampleName cell ... BioSample sizeFactor
#> reducedDimNames(0):
#> mainExpName: NULL
#> altExpNames(0):
#> dea(2): baseline, cell_controlled
#> fea(0):In addition to differential expression anaylsis, we can also explore
some biological data mining, in this case GO ORA. Here we use the
get.gos() function from the exploreSE package,
but it just populates the FEA slot of the DeeDeeExperiment.
airway <- get.gos(obj = airway, NAME = "baseline", gene_type = "ENSEMBL")
#>
#>
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 0.85% of input gene IDs are fail to map...
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 2.72% of input gene IDs are fail to map...
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 1.02% of input gene IDs are fail to map...
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 2.72% of input gene IDs are fail to map...
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 0.85% of input gene IDs are fail to map...
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 2.72% of input gene IDs are fail to map...
#> Found 3104 gene sets in `enrichResult` object, of which 79 are significant.
#> Converting for usage within the DeeDeeExperiment framework...
#> ✔ Renamed FEA entries: "up_go" to "baseline_up_go"
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 1.02% of input gene IDs are fail to map...
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 2.72% of input gene IDs are fail to map...
#> Found 3248 gene sets in `enrichResult` object, of which 109 are significant.
#> Converting for usage within the DeeDeeExperiment framework...
#> ✔ Renamed FEA entries: "dn_go" to "baseline_down_go"
airway <- get.gos(obj = airway, NAME = "cell_controlled", gene_type = "ENSEMBL")
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 0.66% of input gene IDs are fail to map...
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 2.48% of input gene IDs are fail to map...
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 0.88% of input gene IDs are fail to map...
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 2.48% of input gene IDs are fail to map...
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 0.66% of input gene IDs are fail to map...
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 2.48% of input gene IDs are fail to map...
#> Found 3370 gene sets in `enrichResult` object, of which 191 are significant.
#> Converting for usage within the DeeDeeExperiment framework...
#> ✔ Renamed FEA entries: "up_go" to "cell_controlled_up_go"
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 0.88% of input gene IDs are fail to map...
#> 'select()' returned 1:many mapping between keys and columns
#> Warning in bitr(gene, fromType = fromType, toType = "ENTREZID", OrgDb = OrgDb):
#> 2.48% of input gene IDs are fail to map...
#> Found 3352 gene sets in `enrichResult` object, of which 48 are significant.
#> Converting for usage within the DeeDeeExperiment framework...
#> ✔ Renamed FEA entries: "dn_go" to "cell_controlled_down_go"airway
#> class: DeeDeeExperiment
#> dim: 22810 8
#> metadata(3): '' version singlecontrast
#> assays(4): counts mu H cooks
#> rownames(22810): ENSG00000000003 ENSG00000000005 ... ENSG00000273482
#> ENSG00000273490
#> rowData names(50): gene_id gene_name ... cell_controlled_pvalue
#> cell_controlled_padj
#> colnames(8): SRR1039508 SRR1039509 ... SRR1039520 SRR1039521
#> colData names(10): SampleName cell ... BioSample sizeFactor
#> reducedDimNames(0):
#> mainExpName: NULL
#> altExpNames(0):
#> dea(2): baseline, cell_controlled
#> fea(4): baseline_up_go, baseline_down_go, cell_controlled_up_go, cell_controlled_down_goNow that our data is ready, we can explore the data.
The simplest way to launch the app is through a call to the
exploreSE() function. Without any arguments, the app opens
and you can load in any .RDS file. Alternatively, you can supply the
file argument, defining the path to the file, or the
object argument when you have the object already
loaded.
After starting the app, you are created with an overview of the
metadata in the colData of the relevant
summarizedExperiment, as well as a search- and scrollable
view of the same table. On the left hand side, you can load in a
different object from the local environment if desired under the “Data
Input header” - should you start up the app without any data, the “Use
Demo Data” checkbox will be checked and some demo data will be generated
for you. Below that, you will find some options for the your data
exploration throughout the app. Options that are specific to the one
panel only are integrated into that panel, but globally relevant options
appear in the sidebar as needed. You will have your choice of the
relevant gene identifier; by default it picks the first column from your
rowData, but with the drop-down menu that behavior can be
changed. Secondly, you can pick your differential expression analysis;
these come from the relevant slots from the underlying
DeeDeeExperiment or m̀etdata()`.
On the top side, you have 6 riders to choose from: 1. Overview, currently selected 2. PCA; an overview of the principle component visualisation 3. Gene Expression, where the expression of a selected gene is visualised 4. DE Results; the currently selected DE comparison is summarised and visualised 5. Volcano Plot: a volcano plot of the selected DE comparison 6. Enrichment Results: present enrichment results are plotted
Progressing through the app, you can navigate to the PCA rider.
You can select the coloring scheme of the the points in the drop down
menu, as well as how many genes are used to calculate the PCA. In the
airway dataset, the dexamethasone treatment, saved in the
dex variable, is the primary variable of interest, but you
can also select other from the dropdown menu.
Navigating to the Gene Expression tab, you can check the expression of selected genes. By selecting a value in the Color/Group by drop-down menu, you can select the value on the x-axis. You can also include/exclude certain levels of that variable through the tick boxes on the left. The gene being plotted is selected by the “Select Gene” dropdown, which is searchable. Any values visible in the plot can be exported from the table below.
The heart of this application is the comparison of different possible models and within this tab, we are starting that process.
On the top of the page, a little overview indicates all the comparisons found in the respective slots. Below, a barchart indicates the number of differentially expressed genes. The specifics of the results can looked up in a table below and exported.
This view also exists for each comparison; selecting a different comparison from the drop-down menu on the left hand side refreshes the view:
A graphical overview over the differential expression can be found in the Volcano Plot tab.
On the top of this tab, a variety of graphical settings can be determined: the cutoffs for the different colors, a number of genes to label and the colorcode are all freely changeable. Again, this view depends on the selected comparison.
For interpretation of these results, you often rely on the different enrichment methods that to determine which biological themes or pathways are altered in a given comparison. These results are visualised in the Enrichment Results tab.
In this case, we are looking at the GO term enrichments for the baseline model. Like before, some graphical adjustments can be set at the top. Below, we have two bar charts, one for each direction of the comparison. The genes driving the enrichment are written inside the bars.
Direct comparison of fold changes across models can generate insights into the differences. For this, two models can be selected and their respective fold changes plotted against each other.
]
Q: How do I add results into the
summarizedExperiment? A: The easiest way is to use the
DeeDeeExperiment extension of the
summarizedExperiment class. You can use the dedicated DEA
and FEA slots. There is a detailed explanation here.
If you do not want that, you can add it to the
summarizedExperiment metadata, using
de-resultsand fe_resultsas names. Q:
can I use the explorer to perform analysis? A: No, this app is
only design to visualise already performed analyses. All decisions on
what to test, what enrichments to run should happen before you start the
app and make use of the package.
sessionInfo()
#> R version 4.6.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 26.04 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] DeeDeeExperiment_1.3.0 SingleCellExperiment_1.35.2
#> [3] DESeq2_1.53.2 airway_1.33.2
#> [5] SummarizedExperiment_1.43.0 Biobase_2.73.2
#> [7] GenomicRanges_1.65.1 Seqinfo_1.3.0
#> [9] IRanges_2.47.2 S4Vectors_0.51.7
#> [11] BiocGenerics_0.59.12 generics_0.1.4
#> [13] MatrixGenerics_1.25.0 matrixStats_1.5.0
#> [15] exploreSE_0.99.5 BiocStyle_2.41.0
#>
#> loaded via a namespace (and not attached):
#> [1] RColorBrewer_1.1-3 sys_3.4.3 jsonlite_2.0.0
#> [4] tidydr_0.0.6 magrittr_2.0.5 ggtangle_0.1.2
#> [7] farver_2.1.2 rmarkdown_2.31 fs_2.1.0
#> [10] vctrs_0.7.3 memoise_2.0.1 ggtree_4.3.0
#> [13] htmltools_0.5.9 S4Arrays_1.13.0 BiocBaseUtils_1.15.1
#> [16] SparseArray_1.13.2 gridGraphics_0.5-1 sass_0.4.10
#> [19] bslib_0.12.0 htmlwidgets_1.6.4 plyr_1.8.9
#> [22] httr2_1.3.0 cachem_1.1.0 buildtools_1.0.0
#> [25] igraph_2.3.3 lifecycle_1.0.5 pkgconfig_2.0.3
#> [28] gson_0.2.1 Matrix_1.7-6 R6_2.6.1
#> [31] fastmap_1.2.0 digest_0.6.39 aplot_0.3.1
#> [34] enrichplot_1.33.0 ggnewscale_0.5.2 patchwork_1.3.2
#> [37] AnnotationDbi_1.75.2 aisdk_1.4.12 ps_1.9.3
#> [40] RSQLite_3.53.3 org.Hs.eg.db_3.23.1 polyclip_1.10-7
#> [43] httr_1.4.8 abind_1.4-8 compiler_4.6.1
#> [46] bit64_4.8.4 fontquiver_0.2.1 withr_3.0.3
#> [49] S7_0.2.2 BiocParallel_1.47.0 DBI_1.3.0
#> [52] ggforce_0.5.0 MASS_7.3-66 rappdirs_0.3.4
#> [55] DelayedArray_0.39.6 tools_4.6.1 otel_0.2.0
#> [58] scatterpie_0.2.6 ape_5.8-1 glue_1.8.1
#> [61] callr_3.8.0 nlme_3.1-170 GOSemSim_2.39.2
#> [64] grid_4.6.1 cluster_2.1.8.3 reshape2_1.4.5
#> [67] gtable_0.3.6 tidyr_1.3.2 XVector_0.53.0
#> [70] ggrepel_0.9.8 pillar_1.11.1 stringr_1.6.0
#> [73] yulab.utils_0.2.4 limma_3.69.4 splines_4.6.1
#> [76] tweenr_2.0.3 dplyr_1.2.1 treeio_1.37.0
#> [79] lattice_0.23-1 bit_4.6.0 tidyselect_1.2.1
#> [82] fontLiberation_0.1.0 GO.db_3.23.1 locfit_1.5-9.12
#> [85] maketools_1.3.2 Biostrings_2.81.6 knitr_1.51
#> [88] fontBitstreamVera_0.1.1 edgeR_4.11.6 xfun_0.60
#> [91] statmod_1.5.2 stringi_1.8.9 lazyeval_0.2.3
#> [94] ggfun_0.2.1 yaml_2.3.12 evaluate_1.0.5
#> [97] codetools_0.2-20 qvalue_2.45.0 gdtools_0.5.1
#> [100] tibble_3.3.1 BiocManager_1.30.27 ggplotify_0.1.3
#> [103] cli_3.6.6 systemfonts_1.3.2 processx_3.9.0
#> [106] jquerylib_0.1.4 Rcpp_1.1.2 png_0.1-9
#> [109] parallel_4.6.1 ggplot2_4.0.3 blob_1.3.0
#> [112] clusterProfiler_4.21.1 DOSE_4.7.2 tidytree_0.4.8
#> [115] ggiraph_0.9.6 enrichit_0.2.1 scales_1.4.0
#> [118] purrr_1.2.2 crayon_1.5.3 writexl_2.0.0
#> [121] rlang_1.3.0 KEGGREST_1.53.6