1 Package Introduction

GSEAlens derives its name from Lens, symbolizing how this package acts as a magnifying glass to help researchers deeply explore key pathways in GSEA enrichment analysis.

GSEAlens provides a web-based interactive platform for displaying pathway introductions and descriptions, integrating AI-assisted pathway enrichment result export functionality. By encapsulating workflows and standardizing input formats, this R package simplifies the process of viewing and exploring GSEA enrichment analysis results.

1.1 Integration with Bioconductor Workflows

GSEAlens is designed to plug into standard Bioconductor RNA-seq and functional enrichment workflows as a post-DEG exploration layer:

  • Upstream (input preparation): GSEAlens accepts fitted model objects from limma (the MArrayLM object returned by limma::eBayes(), based on the edgeR + limma-voom pipeline) or DESeqDataSet objects from DESeq2. The expression matrix and sample metadata can be passed as SummarizedExperiment objects, ensuring interoperability with the core Bioconductor data containers.

  • Enrichment computation: Under the hood, GSEAlens wraps clusterProfiler (GSEA() function) and uses gene set collections from msigdbr. The statistical framework therefore inherits the methodology of fgsea via clusterProfiler.

  • Parallelization: GSEAlens uses future (future::multisession) for multi-contrast parallel computation. The user’s original future::plan() and future.globals.maxSize option are saved before the parallel run and restored on exit via on.exit(), so the global state is never polluted. We anecdotally observed future::multisession to be noticeably faster than BiocParallel (SnowParam / PSOCK serialization) on Windows for this package’s typical workload, which serializes large globals (the full DE table plus the gene set dictionary and metadata dictionary). This is an informal observation from development, not a formal benchmark; users are free to re-run the analysis with BiocParallel if it better suits their environment.

  • Visualization: Plotting builds on enrichplot, ComplexHeatmap, ggplot2, patchwork, and visNetwork, producing figures compatible with downstream publication pipelines.

  • Downstream: The “Generate R Code” feature in the Shiny application emits self-contained scripts that can be embedded in rmarkdown / Quarto reports or integrated into multi-step pipelines.

A typical end-to-end Bioconductor workflow is therefore:


RNA-seq counts

   |
   +--[edgeR + limma-voom]--> MArrayLM fit --+
   |                                         |
   +--[DESeq2]--------------> DESeqDataSet --+
                                             |
                                             v
                                   [setup_gsea_env]
                                             |
                                             v
                                  [batch_calc_gsea]
                                             |
                                             v
                                    Shiny app exploration
                                             |
                                             v
                                  Reproducible R code export

This makes GSEAlens a natural complement to existing Bioconductor enrichment packages: where clusterProfiler, GSVA, gprofiler2, or ReactomePA focus on computing enrichment, GSEAlens focuses on interactive interpretation of the resulting pathway lists.

1.2 Installation

GSEAlens is available on Bioconductor. Install the stable release with:

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

The development version can be installed from GitHub:

if (!requireNamespace("pak", quietly = TRUE))
    install.packages("pak")
pak::pkg_install("DDL095/GSEAlens")

2 Quick Start

This section demonstrates a complete GSEAlens workflow using the airway dataset. Because GSEAlens does not perform DEG analysis itself, we assume the input objects (fit, dds_se, dds) have been prepared according to standard limma / DESeq2 workflows.

For detailed input preparation steps (limma-voom fitting, DESeq2 object construction, gene filtering), please see the supplementary vignette vignette("GSEAlens-preprocessing").

library(GSEAlens)
library(airway)

For reproducibility in this main vignette, the three input objects (fit, dds_se, dds) are prepared following the preprocessing vignette. Because re-running DESeq2::DESeq() and the limma-voom pipeline on every build would make the vignette slow, we ship pre-computed versions of those objects in inst/extdata/; the script that regenerates them lives in inst/scripts/make_preprocessed_inputs.R and follows the preprocessing vignette exactly.

Note on the shipped dds_se: to stay below the Bioconductor 5 MB extdata limit, the preprocessed_dds_se.rds shipped here is a slimmed DESeqDataSet produced by slim_dds_se() inside make_preprocessed_inputs.R. The slimmed copy drops the mu / H / cooks assay layers (DESeq() fitting intermediates) and flattens rowRanges from GRangesList to GRanges (one representative range per gene). DESeq2::results() and every GSEAlens entry point return bit-identical output on the slimmed vs. the full object. To rebuild the full, untrimmed DESeqDataSet for teaching DESeq2 itself, see the preprocessing vignette.

data(preprocessed_limma, package = "GSEAlens")
preproc_limma         <- preprocessed_limma
fit                   <- preproc_limma$fit
gsea_limma_voom_data  <- preproc_limma$gsea_limma_voom_data
data(preprocessed_dds_se, package = "GSEAlens")
dds_se <- preprocessed_dds_se
data(preprocessed_dds, package = "GSEAlens")
dds <- preprocessed_dds

To prepare these objects from your own data, follow the supplementary preprocessing vignette:


vignette("GSEAlens-preprocessing")

2.1 GSEAlens Processing

2.1.1 Creating GSEA Pathway Object

Use the build_gsea_pathways function to construct a pathway object for GSEA enrichment analysis. The real call downloads multiple MSigDB collections and is slow on the Bioconductor build machine, so it is shown commented out; instead we load a pre-computed lightweight pathway object (Hallmark + KEGG_LEGACY, 236 pathways, see inst/scripts/make_gsea_pathwaysets_toy.R for regeneration instructions).

# Real call (slow on the Bioconductor build machine):
# gsea_pathwaysets <- build_gsea_pathways(
#   species = "HS", auto_select = c("H", "C2:CP:REACTOME", "C5:GO:BP")
# )
# For the vignette we load a pre-computed lightweight pathway object instead:
data(gsea_pathwaysets_toy, package = "GSEAlens")
gsea_pathwaysets <- gsea_pathwaysets_toy

2.1.2 Assembling Computation Object

Through the setup_gsea_env function, assemble a GSEAEnv object for computational analysis. Different workflows use the same function with different data inputs. For the limma-voom workflow, since the fit object does not contain the original gene read counts, the filtered DGEList used to generate the fit object must be additionally provided (here gsea_limma_voom_data). The three supported backends are assembled below.

# limma-voom workflow (needs the DGEList because fit alone lacks raw counts)
gseadata_limmavoom <- setup_gsea_env(fit = fit, pathway_obj = gsea_pathwaysets, expr_data = gsea_limma_voom_data)
# DESeq2 SummarizedExperiment workflow
gseadata_se <- setup_gsea_env(fit = dds_se, pathway_obj = gsea_pathwaysets)
# DESeq2 Count matrix workflow
gseadata_dds <- setup_gsea_env(fit = dds, pathway_obj = gsea_pathwaysets)

2.1.3 Running Processing

All objects are processed using the batch_calc_gsea function with no differences.

Parallel computing note: Adjust the workers option based on your computer’s performance to set the number of cores for computation. More contrasts recommend higher core settings for better computational efficiency.

# Write vignette outputs to a temporary directory to avoid polluting the
# Bioconductor build machine's working directory.
out_dir <- tempdir()
# limma-voom workflow
gsea_res_limmavoom <- batch_calc_gsea(gseadata_limmavoom,
                                                 custom_series_name = "limmavoom_data",
                                                 output_dir = out_dir,
                                                 workers = 2,
                                                 force = TRUE)
# DESeq2 SummarizedExperiment workflow
gsea_res_se <- batch_calc_gsea(gseadata_se,
                                          custom_series_name = "dds_se_data",
                                          output_dir = out_dir,
                                          workers = 2,
                                          force = TRUE)
# DESeq2 Count matrix workflow
gsea_res_dds <- batch_calc_gsea(gseadata_dds,
                                           custom_series_name = "dds_data",
                                           output_dir = out_dir,
                                           workers = 2,
                                           force = TRUE)

2.1.4 Interactive Analysis and Viewing

After running batch_calc_gsea, an RDS file (the “GSEA Capsule”) is generated in the output directory. You can either read it directly with readRDS or use import_gsea_capsule, which automatically organizes related files into the working directory of your .Rmd / .R script and performs data inspection.

gsea_res <- import_gsea_capsule("/path/to/your/files/")
# Or read the RDS directly:
# gsea_res <- readRDS("/path/of/your/file/")

2.2 Interactive Exploration with the Shiny Application

GSEAlens provides an interactive Shiny application for visual exploration of GSEA results. The app is launched by passing a GseaRes object (returned by batch_calc_gsea or loaded via import_gsea_capsule) to launch_gsea_app.

2.2.1 Launching the App

Launch the Shiny app by passing a GseaRes object (returned by batch_calc_gsea or loaded via import_gsea_capsule) to launch_gsea_app. Optionally pass an addition_data data frame (or path to .csv / .rds file) to merge pathway annotations into the main table; if NULL, the app auto-detects addition_data_gsealens.rds or addition_data_gsealens.csv in the working directory.

# Basic launch
launch_gsea_app(gsea_res)
# With explicit pathway annotations:
# launch_gsea_app(gsea_res, addition_data = "pathway_annotations.csv")

2.2.2 Application Layout

The app uses a sidebar + main panel layout with 6 tabs. The sidebar (Data Preprocessing module) provides global controls; the main panel hosts the six feature tabs.

2.2.2.2 Tab 1 – Main Workspace

The default landing tab, combining two sub-modules:

  • Master Table (DT::datatable): interactive table of all enriched pathways with sortable columns (NES, pvalue, p.adjust, setSize) and checkbox selection. Selected rows are pushed to other tabs.

  • Combined Pathway Plotting: aggregates multiple selected pathways into a single composite figure (uses patchwork under the hood). The export modal includes a WYSIWYG Live Preview, PDF/PNG/SVG/TIFF output, and a “Copy R Code” button via generate_combined_plot_code().

Click any pathway row to open the Pathway Detail Modal, which shows the full description, leading-edge genes, and an option to add the pathway to the plot queue.

Source: R/09_shiny_mod_table.R, R/11_shiny_mod_modal.R, R/12_shiny_mod_multi_plot.R.

2.2.2.3 Tab 2 – Holographic Quadruple Linkage

Four synchronized panels:

  1. Top-left: pathway selector (linked to Main Workspace selection)

  2. Top-right: gene ranking table (ranked by |stat|)

  3. Bottom-left: volcano plot for the selected contrast

  4. Bottom-right: expression boxplot for the selected gene

Selections are bidirectionally synchronized – clicking a gene in the table highlights it in the volcano; clicking a point in the volcano scrolls the table.

Source: R/10_shiny_mod_quadrant.R.

2.2.2.4 Tab 3 – Pathway Relationship Exploration

Network visualization of pathway-to-pathway relationships, where nodes are pathways and edges represent shared genes (Jaccard similarity). Two selection modes:

  • Single mode: explore one pathway and its neighbors

  • Batch mode: select multiple pathways from Main Workspace and visualize their interconnections Two sub-panels are provided under this tab:

  • DotPlot panel: horizontal dot plot where the X axis is NES, dot color encodes significance (-log10(FDR) / -log10(P-value) / |NES|, dot size encodes gene-set magnitude. A data-driven size scale (no fixed limits, no transform) is used so that dot sizes faithfully reflect the underlying gene-set magnitude range. This mirrors the ggplot2::scale_size_continuous(range=c(3,8)) convention used by enrichplot::dotplot, where size limits are derived from the data rather than imposed as a fixed domain.

  • Network panel: graph layout (Fruchterman-Reingold / Kamada-Kawai / Circle) with two user-selectable edge-width encodings:

    • Weight-based (default, emapplot convention): edge width is linearly proportional to the Jaccard value, faithfully reflecting the underlying similarity magnitude. Recommended for publication.

    • Rank-based: edge width is assigned by Jaccard rank, guaranteeing uniform visual spacing between edges regardless of absolute weight. Useful for dense networks with low weight variance. Node size reflects |NES|; node color reflects enrichment direction (red = up in left group, blue = up in right group).

Export Center (both panels): clicking “Export Publication Plot” opens a

modal with width / height / DPI / format (PDF, PNG, SVG, TIFF) controls and two actions: download a static ggplot2-rendered image via ggsave (no external dependencies such as kaleido/orca), or copy a fully reproducible R script (generate_dotplot_code() / generate_network_code()) to the clipboard. The static figures are byte-for-byte identical to what the copied code would produce.

Source: R/13_shiny_mod_pathway_relation.R, helper R/utils_hubgene.R, code generators in R/15_code_generator.R.

2.2.2.5 Tab 4 – HubGene Network

Identifies and visualizes hub genes (highly connected genes across multiple enriched pathways) using a visNetwork interactive plot. Adjustable parameters:

  • Physics simulation: toggle on/off, adjust force-directed parameters

  • Pathway node size encoding: three user-selectable modes

    • By gene-set size (setSize, default): matches the enrichplot::cnetplot convention; pathway node size is proportional to the number of genes in the set (sqrt-scaled). Recommended for biological interpretation.

    • By significance (-log10(FDR)): emphasizes the most statistically trustworthy pathways.

    • Fixed size: constant node size controlled by the slider (legacy behavior). The slider value always acts as the base size; the chosen encoding scales around it within [0.6x, 1.4x] to keep visNetwork’s force-directed layout stable (size variance beyond ~2.3x causes visible layout jitter). Gene-node size is unaffected (always base + degree * 3).

  • Network statistics: summary panel showing node count, edge count, density

Export Center: same modal pattern as Tab 3. The static reproduction uses

generate_hubgene_code() and renders pathway nodes as diamonds and gene nodes as circles in a bipartite layout via igraph + ggplot2 (no ggraph dependency). The current size-encoding mode is preserved in the generated script.

Source: R/16_shiny_mod_hubgene_vis.R, code generator in R/15_code_generator.R.

2.2.2.6 Tab 5 – AI Interpretation

Generates a structured prompt for an external LLM (e.g. GPT-4, Claude) to interpret the selected pathways. Supports custom templates so users can enforce a particular output format (e.g. “produce a 3-paragraph biological interpretation citing leading-edge genes”). The generated prompt can be copied to clipboard.

Source: R/17_shiny_mod_AI.R.

Note: This tab only generates prompts; it does not call external APIs directly. The author explicitly designed this to keep API keys and network calls under user control.

2.2.2.7 Tab 6 – Joint GSEA Canvas

Aggregates enrichment running-score curves for multiple selected pathways into a single composite canvas. The image export modal includes a WYSIWYG Live Preview, PDF/PNG/SVG/TIFF output, adjustable canvas margins, and a “Copy R Code” button that generates a self-contained R script via generate_joint_canvas_code() for reproduction outside the Shiny environment.

Source: R/14_shiny_mod_joint_canvas.R, code generator R/15_code_generator.R.

2.2.3 Interpreting Outputs

A practical interpretation guide:

Visualization What to look for Biological meaning
NES (Normalized Enrichment Score) Sign and magnitude Positive NES -> pathway up-regulated in the right-hand group of the contrast
p.adjust < 0.05 threshold Statistical significance after BH correction
Volcano (Tab 2) Symmetry / asymmetry Balanced volcano suggests global shift; skewed suggests targeted regulation
Pathway network (Tab 3) Cluster structure Tightly connected clusters indicate co-regulated biological modules
HubGene (Tab 4) High-degree genes Hub genes are candidate biomarkers or regulatory nodes
Joint Canvas (Tab 6) Curve overlap Overlapping running-score curves suggest coordinated regulation

2.2.4 Reproducible Code Export

Tabs 1 (Combined Pathway Plotting), 2, 3, 4, and 6 include a “Copy R Code” button integrated directly into each module’s image export modal, producing a self-contained R script reproducing the current visualization. This is the recommended way to generate publication-quality figures: iteratively refine the plot in the Shiny app, then export the code for final customization.

3 Package Intermediate Object Descriptions

3.1 GseaEnv Object

The GseaEnv object returned by the setup_gsea_env function contains the following components:

Component Description
backend_info Backend type information (limma-voom or DESeq2)
contrast_registry Contrast registry containing all pairwise comparison information
de_store Differential expression analysis results storage
expr_bundle Expression data bundle (raw counts, normalized matrix, sample metadata)
geneset Geneset information (TERM2GENE, metadata dictionary, species)

3.2 GseaRes Object

The GseaRes object returned by the batch_calc_gsea function contains the following components:

Component Description
metadata Computation metadata (runtime, cores used, parameter settings)
backend_info Backend type information
contrast_registry Contrast registry
de_store Differential expression analysis results storage
expr_bundle Expression data bundle
geneset_info Geneset information
results GSEA results list, one entry per contrast

3.3 GseaTask Object

The GseaTask object returned by the extract_gsea_task function is used for single-contrast analysis:

Component Description
gsea_res GSEA result object
meta Metadata (contrast information, geneset name, expression data)

4 Session Info

sessionInfo()
## R version 4.6.1 (2026-06-24)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.4 LTS
## 
## Matrix products: default
## BLAS:   /home/biocbuild/bbs-3.24-bioc/R/lib/libRblas.so 
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.0  LAPACK version 3.12.0
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_GB              LC_COLLATE=C              
##  [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: America/New_York
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats4    stats     graphics  grDevices utils     datasets  methods  
## [8] base     
## 
## other attached packages:
##  [1] GSEAlens_0.99.33            DESeq2_1.53.2              
##  [3] edgeR_4.11.6                limma_3.69.2               
##  [5] airway_1.33.2               SummarizedExperiment_1.43.0
##  [7] Biobase_2.73.2              GenomicRanges_1.65.1       
##  [9] Seqinfo_1.3.0               IRanges_2.47.2             
## [11] S4Vectors_0.51.6            BiocGenerics_0.59.11       
## [13] generics_0.1.4              MatrixGenerics_1.25.0      
## [15] matrixStats_1.5.0           BiocStyle_2.41.0           
## 
## loaded via a namespace (and not attached):
##   [1] splines_4.6.1           later_1.4.8             ggplotify_0.1.3        
##   [4] tibble_3.3.1            polyclip_1.10-7         enrichit_0.2.1         
##   [7] lifecycle_1.0.5         httr2_1.3.0             doParallel_1.0.17      
##  [10] globals_0.19.1          processx_3.9.0          lattice_0.22-9         
##  [13] MASS_7.3-66             magrittr_2.0.5          plotly_4.12.1          
##  [16] sass_0.4.10             rmarkdown_2.31          jquerylib_0.1.4        
##  [19] yaml_2.3.12             httpuv_1.6.17           otel_0.2.0             
##  [22] ggtangle_0.1.2          DBI_1.3.0               RColorBrewer_1.1-3     
##  [25] abind_1.4-8             purrr_1.2.2             msigdbr_26.1.0         
##  [28] yulab.utils_0.2.4       tweenr_2.0.3            rappdirs_0.3.4         
##  [31] aisdk_1.4.12            gdtools_0.5.1           circlize_0.4.18        
##  [34] enrichplot_1.33.0       ggrepel_0.9.8           listenv_1.0.0          
##  [37] tidytree_0.4.8          parallelly_1.48.0       codetools_0.2-20       
##  [40] DelayedArray_0.39.4     DOSE_4.7.2              DT_0.34.0              
##  [43] ggforce_0.5.0           tidyselect_1.2.1        shape_1.4.6.1          
##  [46] aplot_0.3.1             farver_2.1.2            jsonlite_2.0.0         
##  [49] GetoptLong_1.1.1        progressr_1.0.0         iterators_1.0.14       
##  [52] systemfonts_1.3.2       foreach_1.5.2           tools_4.6.1            
##  [55] ggnewscale_0.5.2        treeio_1.37.0           Rcpp_1.1.2             
##  [58] glue_1.8.1              SparseArray_1.13.2      BiocBaseUtils_1.15.1   
##  [61] xfun_0.60               qvalue_2.45.0           dplyr_1.2.1            
##  [64] withr_3.0.3             BiocManager_1.30.27     fastmap_1.2.0          
##  [67] shinyjs_2.1.1           callr_3.8.0             digest_0.6.39          
##  [70] mime_0.13               R6_2.6.1                gridGraphics_0.5-1     
##  [73] colorspace_2.1-3        GO.db_3.23.1            dichromat_2.0-1        
##  [76] RSQLite_3.53.3          tidyr_1.3.2             fontLiberation_0.1.0   
##  [79] data.table_1.18.4       httr_1.4.8              htmlwidgets_1.6.4      
##  [82] S4Arrays_1.13.0         scatterpie_0.2.6        pkgconfig_2.0.3        
##  [85] gtable_0.3.6            blob_1.3.0              ComplexHeatmap_2.29.0  
##  [88] S7_0.2.2                XVector_0.53.0          clusterProfiler_4.21.1 
##  [91] htmltools_0.5.9         fontBitstreamVera_0.1.1 bookdown_0.47          
##  [94] clue_0.3-68             scales_1.4.0            png_0.1-9              
##  [97] ggfun_0.2.1             knitr_1.51              reshape2_1.4.5         
## [100] rjson_0.2.23            visNetwork_2.1.4        nlme_3.1-170           
## [103] curl_7.1.0              cachem_1.1.0            GlobalOptions_0.1.4    
## [106] stringr_1.6.0           shinycssloaders_1.1.0   parallel_4.6.1         
## [109] AnnotationDbi_1.75.2    pillar_1.11.1           grid_4.6.1             
## [112] vctrs_0.7.3             promises_1.5.0          tidydr_0.0.6           
## [115] xtable_1.8-8            cluster_2.1.8.3         evaluate_1.0.5         
## [118] cli_3.6.6               locfit_1.5-9.12         compiler_4.6.1         
## [121] rlang_1.3.0             crayon_1.5.3            future.apply_1.20.2    
## [124] ps_1.9.3                plyr_1.8.9              fs_2.1.0               
## [127] ggiraph_0.9.6           stringi_1.8.9           viridisLite_0.4.3      
## [130] BiocParallel_1.47.0     assertthat_0.2.1        babelgene_22.9         
## [133] Biostrings_2.81.6       lazyeval_0.2.3          GOSemSim_2.39.2        
## [136] fontquiver_0.2.1        Matrix_1.7-6            patchwork_1.3.2        
## [139] bit64_4.8.2             future_1.75.0           ggplot2_4.0.3          
## [142] KEGGREST_1.53.6         statmod_1.5.2           shiny_1.14.0           
## [145] clipr_0.8.1             igraph_2.3.3            memoise_2.0.1          
## [148] bslib_0.12.0            ggtree_4.3.0            bit_4.6.0              
## [151] ape_5.8-1               gson_0.2.1

5 References