Contents

1 Foreword

Welcome to dandelionR!

dandelionR is an R package for performing single-cell immune repertoire trajectory analysis, based on the original python implementation in dandelion.

It provides all the necessary tools to interface with scRepertoire and a custom implementation of absorbing markov chain for pseudotime inference, inspired based on the palantir python package.

This is a work in progress, so please feel free to open an issue if you encounter any problems or have any suggestions for improvement.

2 Installation

You can install dandelionR with:

2.1 Bioconductor

if (!requireNamespace("BiocManager", quietly = TRUE)) {
    install.packages("BiocManager")
}
BiocManager::install("dandelionR")

2.2 Development version (GitHub)

if (!requireNamespace("devtools", quietly = TRUE)) {
    install.packages("devtools")
}
devtools::install_github("tuonglab/dandelionR", dependencies = TRUE)

In a standard analysis workflow in R, users probably choose to read in their VDJ data with scRepertoire.

In this vignette, we will demonstrate how to perform TCR trajectory analysis starting from ‘raw’ data i.e. just a standard single-cell gene expression data (stored in SingleCellExperiment) and VDJ data (in AIRR format).

Install scater and scRepertoire if you haven’t already.

# only for the tutorial
if (!requireNamespace("scater", quietly = TRUE)) {
    BiocManager::install("scater")
}
if (!requireNamespace("scRepertoire", quietly = TRUE)) {
    BiocManager::install("scRepertoire")
}
# or
devtools::install_github("ncborcherding/scRepertoire")

3 Usage

3.1 Load the required libraries

library(dandelionR)
library(scRepertoire)
library(scater)

3.2 Load the demo data

Due to size limitations of the package, we have provided a very trimmed down version of the demo data to ~2000 cells. The full dataset can be found here accordingly:

GEX (Lymphoid Cells) - https://developmental.cellatlas.io/fetal-immune

VDJ - https://github.com/zktuong/dandelion-demo-files/

The VDJ data is in the dandelion_manuscript/data/dandelion-remap folder.

data(demo_sce)
data(demo_airr)

Check out the other vignette for an example dataset that starts from the original dandelion output associated with the original manuscript.

vignette("vignette_reproduce_original")

We will also set the seed so that the plots and results are consistent.

set.seed(123)

4 Use scRepertoire to load the VDJ data

For the trajectory analysis work here, we are focusing on the main productive TCR chains. Therefore we will flag filterMulti = TRUE, which will keep the selection of the 2 corresponding chains with the highest expression for a single barcode. For more details, refer to scRepertoire’s docs.

contig.list <- loadContigs(input = demo_airr, format = "AIRR")

# Format to `scRepertoire`'s requirements and some light filtering
combined.TCR <- combineTCR(contig.list,
    removeNA = TRUE,
    removeMulti = FALSE,
    filterMulti = TRUE
)

4.1 Merging VDJ data with gene expression data

Next we will combine the gene expression data with the VDJ data to create a SingleCellExperiment object.

sce <- combineExpression(combined.TCR, demo_sce)

5 Initiate dandelionR workflow

Here, the data is ready to be used for the pseudobulk and trajectory analysis workflow in dandelionR.

Because this is a alpha-beta TCR data, we will set the mode_option to “abT”. This will append abT to the relevant columns holding the VDJ gene information. If you are going to try other types of VDJ data e.g. BCR, you should set mode_option to “B” instead. And this argument should be consistently set with the vdjPseudobulk function later.

Since the TCR data is already filtered for productive chains in combineTCR, we will set already.productive = TRUE and can keep allowed_chain_status as NULL.

We will also subset the data to only include the main T-cell types: CD8+T, CD4+T, ABT(ENTRY), DP(P)_T, DP(Q)_T.

sce <- setupVdjPseudobulk(sce,
    mode_option = "abT",
    already.productive = TRUE,
    subsetby = "anno_lvl_2_final_clean",
    groups = c("CD8+T", "CD4+T", "ABT(ENTRY)", "DP(P)_T", "DP(Q)_T")
)

The main output of this function is a SingleCellExperiment object with the relevant VDJ information appended to the colData, particularly the columns with the _main suffix e.g. v_call_abT_VJ_main, j_call_abT_VJ_main etc.

head(colData(sce))
## DataFrame with 6 rows and 35 columns
##                                  n_counts   n_genes           file      mito
##                                 <numeric> <integer>       <factor> <numeric>
## FCAImmP7851891-CCTACCATCGGACAAG      2947      1275 FCAImmP7851891 0.0105192
## FCAImmP7851892-ACGGGCTCAGCATGAG      4969      1971 FCAImmP7851892 0.0245522
## FCAImmP7803035-CCAGCGATCCGAAGAG      7230      1733 FCAImmP7803035 0.0302905
## FCAImmP7528296-ATAAGAGTCAAAGACA      2504       901 FCAImmP7528296 0.0207668
## FCAImmP7555860-AACTTTCTCAACGGGA      8689      2037 FCAImmP7555860 0.0357924
## FCAImmP7292034-CGTCACTGTGGTCTCG      3111      1254 FCAImmP7292034 0.0228222
##                                 doublet_scores predicted_doublets
##                                      <numeric>           <factor>
## FCAImmP7851891-CCTACCATCGGACAAG      0.0439224              False
## FCAImmP7851892-ACGGGCTCAGCATGAG      0.0610687              False
## FCAImmP7803035-CCAGCGATCCGAAGAG      0.0383747              False
## FCAImmP7528296-ATAAGAGTCAAAGACA      0.0236220              False
## FCAImmP7555860-AACTTTCTCAACGGGA      0.0738255              False
## FCAImmP7292034-CGTCACTGTGGTCTCG      0.0222841              False
##                                 old_annotation_uniform    organ  Sort_id
##                                               <factor> <factor> <factor>
## FCAImmP7851891-CCTACCATCGGACAAG              SP T CELL       TH    TOT  
## FCAImmP7851892-ACGGGCTCAGCATGAG              DP T CELL       TH    TOT  
## FCAImmP7803035-CCAGCGATCCGAAGAG              SP T CELL       SK    CD45P
## FCAImmP7528296-ATAAGAGTCAAAGACA              SP T CELL       SK    CD45P
## FCAImmP7555860-AACTTTCTCAACGGGA              SP T CELL       TH    CD45P
## FCAImmP7292034-CGTCACTGTGGTCTCG              SP T CELL       TH    TOT  
##                                       age   method    donor      sex
##                                 <integer> <factor> <factor> <factor>
## FCAImmP7851891-CCTACCATCGGACAAG        11     5GEX      F64   female
## FCAImmP7851892-ACGGGCTCAGCATGAG        12     5GEX      F67   female
## FCAImmP7803035-CCAGCGATCCGAAGAG        14     5GEX      F51   female
## FCAImmP7528296-ATAAGAGTCAAAGACA        12     5GEX      F38   male  
## FCAImmP7555860-AACTTTCTCAACGGGA        16     5GEX      F41   female
## FCAImmP7292034-CGTCACTGTGGTCTCG        14     5GEX      F30   male  
##                                                      Sample scvi_clusters
##                                                    <factor>      <factor>
## FCAImmP7851891-CCTACCATCGGACAAG F64_TH_TOT_FCAImmP7851891              14
## FCAImmP7851892-ACGGGCTCAGCATGAG F67_TH_TOT_FCAImmP7851892              4 
## FCAImmP7803035-CCAGCGATCCGAAGAG F51_SK_CD45P_FCAImmP7803035            2 
## FCAImmP7528296-ATAAGAGTCAAAGACA F38_SK_CD45P_FCAImmP7528296            2 
## FCAImmP7555860-AACTTTCTCAACGGGA F41_TH_CD45P_FCAImmP7555860            2 
## FCAImmP7292034-CGTCACTGTGGTCTCG F30_TH_TOT_FCAImmP7292034              14
##                                 is_maternal_contaminant anno_lvl_2_final_clean
##                                               <logical>               <factor>
## FCAImmP7851891-CCTACCATCGGACAAG                   FALSE             ABT(ENTRY)
## FCAImmP7851892-ACGGGCTCAGCATGAG                   FALSE             DP(Q)_T   
## FCAImmP7803035-CCAGCGATCCGAAGAG                   FALSE             CD4+T     
## FCAImmP7528296-ATAAGAGTCAAAGACA                   FALSE             CD4+T     
## FCAImmP7555860-AACTTTCTCAACGGGA                   FALSE             CD4+T     
## FCAImmP7292034-CGTCACTGTGGTCTCG                   FALSE             ABT(ENTRY)
##                                 celltype_annotation                 CTgene
##                                            <factor>            <character>
## FCAImmP7851891-CCTACCATCGGACAAG          ABT(ENTRY) TRAV13-1*02.TRAJ34*0..
## FCAImmP7851892-ACGGGCTCAGCATGAG          DP(Q)_T    TRAV12-2*01.TRAJ53*0..
## FCAImmP7803035-CCAGCGATCCGAAGAG          CD4+T      TRAV21*02.TRAJ33*01...
## FCAImmP7528296-ATAAGAGTCAAAGACA          CD4+T      TRAV38-2/DV8*01.TRAJ..
## FCAImmP7555860-AACTTTCTCAACGGGA          CD4+T      TRAV12-1*01.TRAJ6*01..
## FCAImmP7292034-CGTCACTGTGGTCTCG          ABT(ENTRY) TRAV1-1*01.TRAJ32*02..
##                                                   CTnt                   CTaa
##                                            <character>            <character>
## FCAImmP7851891-CCTACCATCGGACAAG TGTGCAGCAAGTATGAACAC.. CAASMNTDKLIF_CASSLTG..
## FCAImmP7851892-ACGGGCTCAGCATGAG TGTGCCGTGTGGAGGTAGCA.. CAVWR*QL*TDI_CASRTGN..
## FCAImmP7803035-CCAGCGATCCGAAGAG TGTGCTTCTATGGATAGCAA.. CASMDSNYQLIW_CASSLTS..
## FCAImmP7528296-ATAAGAGTCAAAGACA TGTGCTTATAGGAGCGTTCA.. CAYRSVQGAQKLVF_CASSW..
## FCAImmP7555860-AACTTTCTCAACGGGA TGTGTGGTGAACATAAGAGG.. CVVNIRGSYIPTF_CSARDL..
## FCAImmP7292034-CGTCACTGTGGTCTCG TGCGCTGTGAGAGATCAGTA.. CAVRDQYGGATNKLIF_CAS..
##                                               CTstrict clonalProportion
##                                            <character>        <numeric>
## FCAImmP7851891-CCTACCATCGGACAAG TRAV13-1*02.TRAJ34*0..        0.0416667
## FCAImmP7851892-ACGGGCTCAGCATGAG TRAV12-2*01.TRAJ53*0..        0.0277778
## FCAImmP7803035-CCAGCGATCCGAAGAG TRAV21*02.TRAJ33*01...        0.0370370
## FCAImmP7528296-ATAAGAGTCAAAGACA TRAV38-2/DV8*01.TRAJ..        0.0909091
## FCAImmP7555860-AACTTTCTCAACGGGA TRAV12-1*01.TRAJ6*01..        0.0476190
## FCAImmP7292034-CGTCACTGTGGTCTCG TRAV1-1*01.TRAJ32*02..        0.0204082
##                                 clonalFrequency               cloneSize
##                                       <integer>                <factor>
## FCAImmP7851891-CCTACCATCGGACAAG               1 Large (0.01 < X <= 0.1)
## FCAImmP7851892-ACGGGCTCAGCATGAG               1 Large (0.01 < X <= 0.1)
## FCAImmP7803035-CCAGCGATCCGAAGAG               1 Large (0.01 < X <= 0.1)
## FCAImmP7528296-ATAAGAGTCAAAGACA               1 Large (0.01 < X <= 0.1)
## FCAImmP7555860-AACTTTCTCAACGGGA               1 Large (0.01 < X <= 0.1)
## FCAImmP7292034-CGTCACTGTGGTCTCG               1 Large (0.01 < X <= 0.1)
##                                  v_call_abT_VDJ d_call_abT_VDJ j_call_abT_VDJ
##                                     <character>    <character>    <character>
## FCAImmP7851891-CCTACCATCGGACAAG     TRAV13-1*02      TRAJ34*01    TRBV11-3*04
## FCAImmP7851892-ACGGGCTCAGCATGAG     TRAV12-2*01      TRAJ53*01      TRBV19*01
## FCAImmP7803035-CCAGCGATCCGAAGAG       TRAV21*02      TRAJ33*01     TRBV5-4*01
## FCAImmP7528296-ATAAGAGTCAAAGACA TRAV38-2/DV8*01      TRAJ54*01     TRBV6-6*01
## FCAImmP7555860-AACTTTCTCAACGGGA     TRAV12-1*01       TRAJ6*01    TRBV20-1*01
## FCAImmP7292034-CGTCACTGTGGTCTCG      TRAV1-1*01      TRAJ32*02    TRBV12-4*01
##                                 v_call_abT_VJ j_call_abT_VJ v_call_abT_VDJ_main
##                                   <character>   <character>         <character>
## FCAImmP7851891-CCTACCATCGGACAAG      TRBD1*01    TRBJ1-2*01         TRAV13-1*02
## FCAImmP7851892-ACGGGCTCAGCATGAG            NA    TRBJ1-1*01         TRAV12-2*01
## FCAImmP7803035-CCAGCGATCCGAAGAG      TRBD2*02    TRBJ2-1*01           TRAV21*02
## FCAImmP7528296-ATAAGAGTCAAAGACA            NA    TRBJ1-3*01     TRAV38-2/DV8*01
## FCAImmP7555860-AACTTTCTCAACGGGA      TRBD2*02    TRBJ2-7*01         TRAV12-1*01
## FCAImmP7292034-CGTCACTGTGGTCTCG            NA    TRBJ1-2*01          TRAV1-1*01
##                                 d_call_abT_VDJ_main j_call_abT_VDJ_main
##                                         <character>         <character>
## FCAImmP7851891-CCTACCATCGGACAAG           TRAJ34*01         TRBV11-3*04
## FCAImmP7851892-ACGGGCTCAGCATGAG           TRAJ53*01           TRBV19*01
## FCAImmP7803035-CCAGCGATCCGAAGAG           TRAJ33*01          TRBV5-4*01
## FCAImmP7528296-ATAAGAGTCAAAGACA           TRAJ54*01          TRBV6-6*01
## FCAImmP7555860-AACTTTCTCAACGGGA            TRAJ6*01         TRBV20-1*01
## FCAImmP7292034-CGTCACTGTGGTCTCG           TRAJ32*02         TRBV12-4*01
##                                 v_call_abT_VJ_main j_call_abT_VJ_main
##                                        <character>        <character>
## FCAImmP7851891-CCTACCATCGGACAAG           TRBD1*01         TRBJ1-2*01
## FCAImmP7851892-ACGGGCTCAGCATGAG                 NA         TRBJ1-1*01
## FCAImmP7803035-CCAGCGATCCGAAGAG           TRBD2*02         TRBJ2-1*01
## FCAImmP7528296-ATAAGAGTCAAAGACA                 NA         TRBJ1-3*01
## FCAImmP7555860-AACTTTCTCAACGGGA           TRBD2*02         TRBJ2-7*01
## FCAImmP7292034-CGTCACTGTGGTCTCG                 NA         TRBJ1-2*01

Visualise the UMAP of the filtered data.

plotUMAP(sce, color_by = "anno_lvl_2_final_clean")

5.1 Milo object and neighbourhood graph construction

We will use miloR to create the pseudobulks based on the gene expression data. The goal is to construct a neighbourhood graph with many neighbors with which we can sample the representative neighbours to form the objects.

library(miloR)
milo_object <- Milo(sce)
milo_object <- buildGraph(milo_object, k = 30, d = 20, reduced.dim = "X_scvi")
milo_object <- makeNhoods(milo_object,
    reduced_dims = "X_scvi", d = 20,
    prop = 0.3
)

5.2 Construct UMAP on milo neighbor graph

We can visualise this milo object using UMAP.

milo_object <- miloUmap(milo_object, n_neighbors = 30)
plotUMAP(milo_object,
    color_by = "anno_lvl_2_final_clean",
    dimred = "UMAP_knngraph"
)

6 Construct pseudobulked VDJ feature space

Next, we will construct the pseudobulked VDJ feature space using the neighbourhood graph constructed above. We will also run PCA on the pseudobulked VDJ feature space.

pb.milo <- vdjPseudobulk(milo_object,
    mode_option = "abT",
    col_to_take = "anno_lvl_2_final_clean"
)

Inspect the newly created pb.milo object.

pb.milo
## class: Milo 
## dim: 129 64 
## metadata(0):
## assays(1): Feature_space
## rownames(129): TRAV1-1*01 TRAV1-2*01 ... TRBJ2-7*01 TRBJ2-7*02
## rowData names(0):
## colnames(64): 179 93 ... 269 125
## colData names(3): anno_lvl_2_final_clean
##   anno_lvl_2_final_clean_fraction cell_count
## reducedDimNames(0):
## mainExpName: NULL
## altExpNames(0):
## nhoods dimensions(2): 64 382
## nhoodCounts dimensions(2): 1 1
## nhoodDistances dimension(1): 0
## graph names(0):
## nhoodIndex names(1): 0
## nhoodExpression dimension(2): 1 1
## nhoodReducedDim names(0):
## nhoodGraph names(0):
## nhoodAdjacency dimension(2): 1 1

We can compute and visualise the PCA of the pseudobulked VDJ feature space.

pb.milo <- runPCA(pb.milo, assay.type = "Feature_space", ncomponents = 20)
plotPCA(pb.milo, color_by = "anno_lvl_2_final_clean")

6.1 TCR trajectory inference using Absorbing Markov Chain

In the original dandelion python package, the trajectory inference is done using the palantir package. Here, we implement the absorbing markov chain approach in dandelionR to infer the trajectory, leveraging on destiny for diffusion map computation.

6.1.1 Define root and branch tips

# extract the PCA matrix
pca <- t(as.matrix(reducedDim(pb.milo, type = "PCA")))
# define the CD8 terminal cell as the top-most cell and CD4 terminal cell as
# the bottom-most cell
branch.tips <- c(which.max(pca[2, ]), which.min(pca[2, ]))
names(branch.tips) <- c("CD8+T", "CD4+T")
# define the start of our trajectory as the right-most cell
root <- which.max(pca[1, ])

6.1.2 Construct diffusion map

library(destiny)
# Run diffusion map on the PCA
dm <- DiffusionMap(t(pca), n_pcs = 10, n_eigs = 10)

6.1.3 Compute diffusion pseudotime on diffusion map

dif.pse <- DPT(dm, tips = c(root, branch.tips), w_width = 0.1)
# the root is automatically called DPT + index of the root cell
DPTroot <- paste0("DPT", root)
# store pseudotime in milo object
pb.milo$pseudotime <- dif.pse[[DPTroot]]
# set the colours for pseudotime
pal <- colorRampPalette(rev((RColorBrewer::brewer.pal(9, "RdYlBu"))))(255)
plotPCA(pb.milo, color_by = "pseudotime") +
    scale_colour_gradientn(colours = pal)

7 Markov chain construction on the pseudobulk VDJ feature space

This step will compute the Markov chain probabilities on the pseudobulk VDJ feature space. It will return the branch probabilities in the colData and the column name corresponds to the branch tips defined earlier.

pb.milo <- markovProbability(
    milo = pb.milo,
    diffusionmap = dm,
    terminal_state = branch.tips,
    root_cell = root,
    pseudotime_key = "pseudotime",
    knn = 30
)

Inspect the pb.milo object to see the newly added columns.

head(colData(pb.milo))
## DataFrame with 6 rows and 6 columns
##     anno_lvl_2_final_clean anno_lvl_2_final_clean_fraction cell_count
##                <character>                       <numeric>  <numeric>
## 179              faDP(P)_T                        0.605263         38
## 93                 faCD8+T                        0.750000         48
## 75               faDP(Q)_T                        0.907407         54
## 279              faDP(Q)_T                        0.913793         58
## 277                faCD4+T                        0.936170         47
## 375              faDP(P)_T                        0.632653         49
##     pseudotime     CD8+T     CD4+T
##      <numeric> <numeric> <numeric>
## 179   0.449589  0.578761  0.421239
## 93    5.584408  0.729279  0.270721
## 75    2.642788  0.559456  0.440544
## 279   2.595964  0.559617  0.440383
## 277   4.314940  0.565749  0.434251
## 375   0.134566  0.578744  0.421256

8 Visualising branch probabilities

With the Markov chain probabilities computed, we can visualise the branch probabilities towards CD4+ or CD8+ T-cell fate on the PCA plot.

plotPCA(pb.milo, color_by = "CD8+T") + scale_color_gradientn(colors = pal)

plotPCA(pb.milo, color_by = "CD4+T") + scale_color_gradientn(colors = pal)

9 Transfer

The next step is to project the pseudotime and the branch probability information from the pseudobulks back to each cell in the dataset. If the cell do not belong to any of the pseudobulk, it will be removed. If a cell belongs to multiple pseudobulk samples, its value should be calculated as a weighted average of the corresponding values from each pseudobulk, where each weight is inverse of the size of the pseudobulk.

9.1 Project pseudobulk data to each cell

cdata <- projectPseudotimeToCell(milo_object, pb.milo, branch.tips)

9.2 Visualise the trajectory data on a per cell basis

plotUMAP(cdata, color_by = "anno_lvl_2_final_clean", dimred = "UMAP_knngraph")

plotUMAP(cdata, color_by = "pseudotime", dimred = "UMAP_knngraph") +
    scale_color_gradientn(colors = pal)

plotUMAP(cdata, color_by = "CD4+T", dimred = "UMAP_knngraph") +
    scale_color_gradientn(colors = pal)

plotUMAP(cdata, color_by = "CD8+T", dimred = "UMAP_knngraph") +
    scale_color_gradientn(colors = pal)

And that’s it! We have successfully inferred the trajectory of the T-cells in this dataset!

10 Session info

sessionInfo()
## R Under development (unstable) (2025-01-20 r87609)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.2 LTS
## 
## Matrix products: default
## BLAS:   /home/biocbuild/bbs-3.21-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] destiny_3.21.0              miloR_2.3.0                
##  [3] edgeR_4.5.2                 limma_3.63.3               
##  [5] scater_1.35.1               scuttle_1.17.0             
##  [7] SingleCellExperiment_1.29.1 SummarizedExperiment_1.37.0
##  [9] Biobase_2.67.0              GenomicRanges_1.59.1       
## [11] GenomeInfoDb_1.43.4         IRanges_2.41.3             
## [13] S4Vectors_0.45.4            BiocGenerics_0.53.6        
## [15] generics_0.1.3              MatrixGenerics_1.19.1      
## [17] matrixStats_1.5.0           scRepertoire_2.3.2         
## [19] ggplot2_3.5.1               dandelionR_0.99.10         
## [21] BiocStyle_2.35.0           
## 
## loaded via a namespace (and not attached):
##   [1] cubature_2.1.1          splines_4.5.0           tibble_3.2.1           
##   [4] polyclip_1.10-7         xts_0.14.1              lifecycle_1.0.4        
##   [7] globals_0.16.3          lattice_0.22-6          MASS_7.3-64            
##  [10] magrittr_2.0.3          vcd_1.4-13              sass_0.4.9             
##  [13] rmarkdown_2.29          jquerylib_0.1.4         yaml_2.3.10            
##  [16] spam_2.11-1             sp_2.2-0                cowplot_1.1.3          
##  [19] RColorBrewer_1.1-3      abind_1.4-8             purrr_1.0.4            
##  [22] ggraph_2.2.1            nnet_7.3-20             pracma_2.4.4           
##  [25] tweenr_2.0.3            evmix_2.12              GenomeInfoDbData_1.2.13
##  [28] ggrepel_0.9.6           irlba_2.3.5.1           listenv_0.9.1          
##  [31] iNEXT_3.0.1             MatrixModels_0.5-3      RSpectra_0.16-2        
##  [34] parallelly_1.42.0       codetools_0.2-20        smoother_1.3           
##  [37] DelayedArray_0.33.6     ggforce_0.4.2           tidyselect_1.2.1       
##  [40] UCSC.utils_1.3.1        farver_2.1.2            ScaledMatrix_1.15.0    
##  [43] viridis_0.6.5           jsonlite_1.9.0          BiocNeighbors_2.1.2    
##  [46] e1071_1.7-16            tidygraph_1.3.1         progressr_0.15.1       
##  [49] Formula_1.2-5           survival_3.8-3          ggalluvial_0.12.5      
##  [52] tools_4.5.0             stringdist_0.9.15       Rcpp_1.0.14            
##  [55] glue_1.8.0              gridExtra_2.3           SparseArray_1.7.6      
##  [58] laeken_0.5.3            xfun_0.51               ranger_0.17.0          
##  [61] TTR_0.24.4              ggthemes_5.1.0          dplyr_1.1.4            
##  [64] withr_3.0.2             numDeriv_2016.8-1.1     BiocManager_1.30.25    
##  [67] fastmap_1.2.0           boot_1.3-31             bluster_1.17.0         
##  [70] SparseM_1.84-2          VIM_6.2.2               digest_0.6.37          
##  [73] rsvd_1.0.5              R6_2.6.1                colorspace_2.1-1       
##  [76] gtools_3.9.5            tidyr_1.3.1             hexbin_1.28.5          
##  [79] data.table_1.16.4       robustbase_0.99-4-1     class_7.3-23           
##  [82] graphlayouts_1.2.2      httr_1.4.7              S4Arrays_1.7.3         
##  [85] scatterplot3d_0.3-44    uwot_0.2.2              pkgconfig_2.0.3        
##  [88] gtable_0.3.6            lmtest_0.9-40           XVector_0.47.2         
##  [91] htmltools_0.5.8.1       carData_3.0-5           dotCall64_1.2          
##  [94] bookdown_0.42           SeuratObject_5.0.2      scales_1.3.0           
##  [97] knn.covertree_1.0       ggdendro_0.2.0          knitr_1.49             
## [100] rjson_0.2.23            reshape2_1.4.4          curl_6.2.1             
## [103] proxy_0.4-27            cachem_1.1.0            zoo_1.8-12             
## [106] stringr_1.5.1           parallel_4.5.0          vipor_0.4.7            
## [109] pillar_1.10.1           grid_4.5.0              vctrs_0.6.5            
## [112] pcaMethods_1.99.0       VGAM_1.1-13             car_3.1-3              
## [115] BiocSingular_1.23.0     beachmat_2.23.6         cluster_2.1.8          
## [118] beeswarm_0.4.0          evaluate_1.0.3          magick_2.8.5           
## [121] tinytex_0.55            truncdist_1.0-2         cli_3.6.4              
## [124] locfit_1.5-9.11         compiler_4.5.0          rlang_1.1.5            
## [127] crayon_1.5.3            future.apply_1.11.3     labeling_0.4.3         
## [130] plyr_1.8.9              ggbeeswarm_0.7.2        stringi_1.8.4          
## [133] viridisLite_0.4.2       BiocParallel_1.41.2     assertthat_0.2.1       
## [136] munsell_0.5.1           gsl_2.1-8               quantreg_6.00          
## [139] Matrix_1.7-2            RcppHNSW_0.6.0          RcppEigen_0.3.4.0.2    
## [142] patchwork_1.3.0         future_1.34.0           statmod_1.5.0          
## [145] evd_2.3-7.1             igraph_2.1.4            memoise_2.0.1          
## [148] bslib_0.9.0             DEoptimR_1.1-3-1        ggplot.multistats_1.0.1