• Overview
  • FASTQ+
  • PISA
  • Yano
  • My GitHub Page
  • Discussions

Alternative splicing analysis for single cell RNA sequencing

On this page

  • 0. Prerequisite
  • 1. Perform cell clustering with Seurat
  • 2. Perform alternative splicing with exon assay
  • 3. Load junction assay
  • 4. Heatmap analysis for highlight group specific alternative splicing
  • 5. Test between exon and exon skipped reads
  • Questions?

This vignette demonstrates alternative splicing analysis using gene, exon, and junction expression matrices generated by PISA. Although most scRNA-seq protocols are 3’ or 5’ biased, partial exon coverage can still be captured. The spatial dissimilarity test in Yano exploits the spatial distribution of features, so even lowly expressed features with strong spatial patterns can be detected. By comparing exon/junction expression against their host gene’s expression in spatial context, potential alternative splicing events are identified.

0. Prerequisite

  • Make sure you have installed the R environment and the latest version of the Yano package (>= 1.2) before proceeding.
  • The latest Yano uses grid-based highlight rendering for TrackPlot, enabling highlights that span continuously across multiple facet panels and tracks. If you have an older version installed, update with devtools::install_github("shiquan/Yano").

1. Perform cell clustering with Seurat

require(Yano)
Loading required package: Yano
require(Seurat)
Loading required package: Seurat
Loading required package: SeuratObject
Loading required package: sp

Attaching package: 'SeuratObject'
The following objects are masked from 'package:base':

    intersect, t
require(dplyr)
Loading required package: dplyr

Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
require(ggplot2)
Loading required package: ggplot2
require(Matrix)
Loading required package: Matrix
# Read raw gene expression matrix
exp <- ReadPISA("./exp/")

In this section, we will perform the standard Seurat analysis pipeline.

Note: The spatial dissimilarity test does not depend on clustering. Changing resolution or other parameters for FindClusters and RunUMAP has no impact on the results.

# Create Seurat object and filter droplets with fewer than 1000 genes
obj <- CreateSeuratObject(exp, min.features = 1000, min.cells = 10)

# Filter low quality droplets
obj[["percent.mt"]] <- PercentageFeatureSet(obj, pattern = "^MT-")
obj <- subset(obj, nFeature_RNA < 9000 & percent.mt < 20)

# Downsampling to 2000 cells for fast testing
obj <- obj[, sample(colnames(obj),2000)]

# We run the cell clustering analysis with Seurat pipeline
obj <- NormalizeData(obj) %>% FindVariableFeatures() %>% ScaleData() %>%  RunPCA(verbose=FALSE) %>% FindNeighbors(dims = 1:10, verbose=FALSE) %>% FindClusters(resolution = 0.5, verbose=FALSE) %>% RunUMAP(dims=1:10, verbose=FALSE)
Normalizing layer: counts
Finding variable features for layer counts
Centering and scaling data matrix
DimPlot(obj, label=TRUE, label.size = 5, label.box = TRUE)

2. Perform alternative splicing with exon assay

Here we compare exon expression with their host gene’s expression in a spatial context. “Spatial” refers to cell organization: in this vignette we use PCA space, but the method also supports spatial coordinates, lineage trajectories, or integration spaces such as harmony. The workflow has three steps. First, load exon data as a new assay. Second, run spatial autocorrelation to select informative exons. Third, define exon–gene binding relationships and run the spatial dissimilarity test to obtain p-values and adjusted p-values.

# Read exon count matrix file
exon <- ReadPISA("./exon/")

# Load the exon expression to Seurat object as a new assay, make sure the exon matrix has the same cells.
obj[['exon']] <- CreateAssayObject(exon[, colnames(obj)], min.cells=20)

# Switch work assay to exon
DefaultAssay(obj) <- "exon"
# Empty info for exon features
head(obj[['exon']][[]])
data frame with 0 columns and 6 rows
obj <- ParseExonName(obj)
Working on assay exon
# Gene name and location are parsed from exon name
head(obj[['exon']][[]]) %>% DT::datatable()
# Normalize the data for spatial autocorrelation test
obj <- NormalizeData(obj)
obj <- RunAutoCorr(obj)
Working on assay : exon
Run autocorrelation test for 117195 features.
Runtime : 12.55185 secs
71358 autocorrelated features.

The permutation test is computationally expensive. Below we use perm=20 for quick results; the default is 100 permutations for better accuracy. If you are running Yano for the first time on a new dataset, perm=20 saves time and provides a useful overview.

obj <- RunSDT(obj, bind.name = "gene_name", bind.assay = "RNA", perm=20)
Working on assay exon.
Working on binding assay RNA.
Use predefined weight matrix "pca_wm".
Processing 71358 features.
Processing 14991 binding features.
Retrieve binding data from assay RNA.
Use "data" layer for test features and binding features.
Using 95 threads.
Runtime : 25.17418 secs.
# Now p values and adjusted p values have been generated
head(obj[['exon']][[]]) %>% DT::datatable()
# Plot feature binding test plot
FbtPlot(obj, val = "gene_name.padj")

The chromosome names are long and often overlap in the plot. You can resize labels or remove the “chr” prefix. The Y chromosome and mitochondrial genes can also be excluded.

sel.chrs <- c(1:21, "X")
FbtPlot(obj, val = "gene_name.padj", remove.chr = TRUE, sel.chrs = sel.chrs)

# Let's see how many exons are expressed in different spatial pattern with their genes
obj[['exon']][[]] %>% filter(gene_name.padj < 1e-5) %>% DT::datatable() 
# Random select a gene and its exons and visulize with FeaturePlot.
FeaturePlot(obj, features = c("chr19:16095264-16095357/+/TPM4", "TPM4"), ncol=2)

# The default color and parameters perhaps not easily to tell the difference between exon and its binding gene expression. Let's change the scaled colors and enlarge point size and order by expression.
require(RColorBrewer)
Loading required package: RColorBrewer
FeaturePlot(obj, features = c("chr19:16095264-16095357/+/TPM4", "TPM4"), ncol=2, order = TRUE, pt.size=1) & scale_colour_gradientn(colours = rev(brewer.pal(n = 11, name = "RdBu")))
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.

The RatioPlot function maps the ratio of exon expression to gene expression on the UMAP. TPM4 is lowly expressed in some cell groups, while the exon chr19:16095264-16095357/+/TPM4 shows a higher ratio in those same groups.

RatioPlot(obj, features = c("chr19:16095264-16095357/+/TPM4"), assay = 'exon', bind.assay = 'RNA', bind.name = "gene_name", order = TRUE, pt.size=1)

In the plots above, the inconsistency between exon and gene expression may indicate differential exon usage. Next we generate a track plot to inspect read coverage for the exon and gene body.

Yano loads gene locations from a GTF file rather than Bioconductor databases (e.g., org.Hs.eg.db). This avoids inconsistencies from differing annotation versions across sources. We recommend using the same GTF file throughout your project. The gtf2db function loads a GTF file into memory.

gtf <- gtf2db("./gencode.v44.annotation.gtf.gz")
[2026-06-15 14:45:20] GTF loading..
[2026-06-15 14:45:59] Load 62700 genes.
[2026-06-15 14:45:59] Load time : 38.895 sec

The track plot shows read coverage per cell group, specified by cell.group. Unlike IGV which uses read depth, this plot shows UMI depth. The cell barcode and UMI tags default to “CB” and “UB” (cell.tag and umi.tag). For each cell group, UMI depth is normalized by the number of cells, so the tracks are directly comparable across groups. If cell.group is not set, raw UMI depth per location is shown.

Highlighted regions are rendered with dark orange boundary lines and a semi-transparent grey fill. In the latest Yano, highlights use grid-based rendering that spans continuously across all facet panels and tracks (coverage, BED features, and gene annotations) with a small visual protrusion, making them clearly distinguishable from the panel data. Overlapping highlights produce additive darkening.

TrackPlot(bamfile = "Parent_SC3v3_Human_Glioblastoma_possorted_genome_bam.bam", gtf = gtf, gene = "TPM4", cell.group = Idents(obj), highlights = c(16095264,16095357) )

Setting max.depth = 2 caps the depth and setting display.genes = "TPM4" filters to the gene of interest, making the highlighted exon visible. It now shows a distinct expression pattern from the gene TPM4.

TrackPlot(bamfile = "Parent_SC3v3_Human_Glioblastoma_possorted_genome_bam.bam", gtf = gtf, gene = "TPM4", cell.group = Idents(obj), highlights = c(16095264,16095357), max.depth = 2, display.genes = "TPM4")

3. Load junction assay

Junction expression provides a complementary view of alternative splicing. Junctions capture reads spanning adjacent exons. They are named similarly to exons but with different coordinates: the junction start is the end of the upstream exon, and the junction end is the start of the downstream exon.

junction <- ReadPISA("./junction/")
obj[['junction']] <- CreateAssayObject(junction[, colnames(obj)], min.cells=20)

DefaultAssay(obj) <- "junction"
obj <- NormalizeData(obj)

# select spatial autocorrelated junctions
obj <- RunAutoCorr(obj)
Working on assay : junction
Run autocorrelation test for 14754 features.
Runtime : 1.195152 secs
7505 autocorrelated features.
# Parse the gene name and coordinates from junction names
obj <- ParseExonName(obj)
Working on assay junction
# perform dissimilarity test between junctions and their binding genes
obj <- RunSDT(obj, bind.name = "gene_name", bind.assay = "RNA", perm=20)
Working on assay junction.
Working on binding assay RNA.
Use predefined weight matrix "pca_wm".
Processing 7505 features.
Processing 3753 binding features.
Retrieve binding data from assay RNA.
Use "data" layer for test features and binding features.
Using 95 threads.
Runtime : 2.214221 secs.
FbtPlot(obj, val="gene_name.padj", remove.chr=TRUE, sel.chrs = sel.chrs)

obj[['junction']][[]] %>% filter(gene_name.padj<1e-5) %>% DT::datatable()
# Because both exon and junction are compared with gene, so it's reasonable to combine these two assays in one plot
FbtPlot(obj, val="gene_name.padj", assay = c("exon", "junction"), col.by = "assay", shape.by = "assay", pt.size = 2, remove.chr = TRUE, sel.chrs = sel.chrs, cols = c("red", "blue"))

# We can find there is an exon and a junction at chromosome 12 with very low p value (<1e-5), let's see which gene they are located
obj[['exon']][[]] %>% filter(chr == "chr12" & gene_name.padj < 1e-5) %>% DT::datatable()
obj[['junction']][[]] %>% filter(chr == "chr12" & gene_name.padj < 1e-5) %>% DT::datatable()
FeaturePlot(obj, features = c("chr12:56161387-56161465/+/MYL6","chr12:56160320-56161387/+/MYL6", "MYL6"), order = TRUE, pt.size = 2, ncol=3) & scale_colour_gradientn(colours = rev(brewer.pal(n = 11, name = "RdBu")))
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.

# We could also plot the expression ratio of these exons or junctions on umap
p1 <- RatioPlot(obj, assay = "exon", bind.assay = "RNA", bind.name = "gene_name", features = "chr12:56161387-56161465/+/MYL6")
p2 <- RatioPlot(obj, assay = "exon", bind.assay = "RNA", bind.name = "gene_name", features = "chr12:56160626-56160670/+/MYL6")
p3 <- RatioPlot(obj, assay = "junction", bind.assay = "RNA", bind.name = "gene_name", features = "chr12:56160320-56161387/+/MYL6")
cowplot::plot_grid(p1,p2,p3, ncol=3)

We then visualize the track plot for this gene, including junction reads by setting junc=TRUE. Two adjacent highlight regions are specified as a list, producing overlapping highlights — the overlapping portion appears darker due to additive alpha blending, and each highlight is marked with a dark orange boundary line at its start position.

TrackPlot(bamfile = "Parent_SC3v3_Human_Glioblastoma_possorted_genome_bam.bam", gtf = gtf, gene = "MYL6", cell.group = Idents(obj), junc = TRUE, highlights = list(c(56160320,56161387),c(56161387,56161465)))

The exon chr12:56161387-56161465/+/MYL6 appears highly expressed in group 3 in the track plot, yet its expression in the feature plot is lower than expected. This is because the exon overlaps with other exons from different transcripts. Only reads fully contained within the exon are counted toward its expression; partially overlapping reads are excluded.

The overlapping exon chr12:56161387-56161575/+/MYL6, by contrast, shows strong expression in group 3. Note that when a read is fully contained within multiple overlapping exons, PISA counts it for all of them. See PISA’s manual for details.

p1 <- DimPlot(obj, label=TRUE, label.size = 5, label.box = TRUE)
p2 <- FeaturePlot(obj, features = c("chr12:56161387-56161575/+/MYL6"), order = TRUE, pt.size = 1) & scale_colour_gradientn(colours = rev(brewer.pal(n = 11, name = "RdBu")))
Warning: Could not find chr12:56161387-56161575/+/MYL6 in the default search
locations, found in 'exon' assay instead
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.
p1 + p2

4. Heatmap analysis for highlight group specific alternative splicing

The spatial dissimilarity test identifies alternatively spliced exons and junctions across all cells, but does not pinpoint which cell groups drive the signal. To address this, we extract scaled expression for the selected exons and their host genes, then perform co-clustering. The heatmap below uses ComplexHeatmap to visualize the distribution across cell groups.

obj[['exon']][[]] %>% filter(gene_name.padj<1e-5) %>% rownames -> exons
obj[['exon']][[]] %>% filter(gene_name.padj<1e-5) %>% pull(gene_name) -> bind.genes
DefaultAssay(obj) <- "RNA"
obj <- ScaleData(obj, features = unique(bind.genes))
DefaultAssay(obj) <- "exon"
obj <- ScaleData(obj, features = exons)

dat1 <- GetAssayData(obj, assay = 'exon', layer = 'scale.data')
dat2 <- GetAssayData(obj, assay = 'RNA', layer = 'scale.data')
idents <- sort(Idents(obj))
order.cells <- names(idents)

dat2 <- dat2[bind.genes,]
rownames(dat2) <- exons

dat <- cbind(dat1, dat2)

require(ComplexHeatmap)
d <- dist(dat)
hc <- hclust(d)
idx <- hc$labels[hc$order]

ha <- HeatmapAnnotation(group=idents, border = TRUE)
ht1 <- Heatmap(dat1[idx, order.cells], cluster_rows = FALSE, cluster_columns = FALSE, show_column_names = FALSE, border = TRUE,  top_annotation = ha, name = "exon", column_title = "exon")
ht2 <- Heatmap(dat2[idx, order.cells], cluster_rows = FALSE, cluster_columns = FALSE, show_column_names = FALSE, border = TRUE,  top_annotation = ha, name = "gene", column_title = "gene", row_names_max_width = max_text_width(rownames(dat2), gp = gpar(fontsize = 12)))

ht <- ht1 + ht2
draw(ht, heatmap_legend_side = "left",  annotation_legend_side = "left")

5. Test between exon and exon skipped reads

The spatial dissimilarity test is not limited to gene-level binding features. Here we test exon expression against reads that skip the exon (exclude assay). This is analogous to the Percent Spliced In (PSI) method widely used in bulk and single-cell RNA-seq: PSI = exon reads / (exon reads + reads skipping this exon).

# The reads that skip exons are annotated using the `-psi` option in PISA anno, and these counts are stored in the `exclude` directory. We then load these excluded counts into a new assay.
exclude <- ReadPISA("exclude/")
obj[['exclude']] <- CreateAssayObject(exclude[,colnames(obj)], min.cells = 10)
DefaultAssay(obj) <- "exclude"
# Normalize counts for exon-excluded reads
obj <- NormalizeData(obj)
# Then we switch to exon assay
DefaultAssay(obj) <- "exon"

# Because the feature names in the exclude assay are exactly the same as those in the exon assay, they represent the reads that skip each corresponding exon. Therefore, we set up the binding feature using the exon name itself.
obj[['exon']][['exon_name']] <- rownames(obj)
obj[['exon']][['exon_name']] %>% head
                                                                exon_name
chr1:135141-135895/-/ENSG00000268903 chr1:135141-135895/-/ENSG00000268903
chr1:629640-630683/+/MTND2P28               chr1:629640-630683/+/MTND2P28
chr1:631074-632616/+/MTCO1P12               chr1:631074-632616/+/MTCO1P12
chr1:632757-633438/+/MTCO2P12               chr1:632757-633438/+/MTCO2P12
chr1:633696-634376/+/MTATP6P1               chr1:633696-634376/+/MTATP6P1
chr1:634376-634922/+/MTCO3P12               chr1:634376-634922/+/MTCO3P12
# Then we perform spatial dissimilarity test between exon and exclude, mode 1
obj <- RunSDT(obj, bind.name = "exon_name", bind.assay = "exclude")

# Swith to exon exluded assay
DefaultAssay(obj) <- "exclude"
obj <- RunAutoCorr(obj)
obj <- ParseExonName(obj)
obj[['exclude']][['exon_name']] <- rownames(obj)

obj <- RunSDT(obj, bind.name = "exon_name", bind.assay = "exon")

FbtPlot(obj, val = "exon_name.padj", remove.chr = TRUE, assay = c("exclude", "exon"), shape.by = "assay", col.by = "assay", cols = c("yellow", "green"), pt.size = 2)

# Let's how many exons can be prioritized by both exon assay and exclude assay
obj[['exclude']][[]] %>% filter(exon_name.padj<1e-5) %>% rownames -> sel1
obj[['exon']][[]] %>% filter(exon_name.padj<1e-5) %>% rownames -> sel2
intersect(sel1,sel2)
 [1] "chr1:19342752-19342864/-/CAPZB"    "chr1:153990914-153991034/+/RPS27" 
 [3] "chr10:128047570-128047683/+/PTPRE" "chr12:56160626-56160670/+/MYL6"   
 [5] "chr12:56160626-56160945/+/MYL6"    "chr14:75279237-75279531/+/FOS"    
 [7] "chr15:29822002-29822468/-/TJP1"    "chr15:29822002-29822503/-/TJP1"   
 [9] "chr15:29822002-29822502/-/TJP1"    "chr19:16095264-16095357/+/TPM4"   
[11] "chr19:16095264-16095454/+/TPM4"    "chr19:16095264-16095496/+/TPM4"   
[13] "chr19:16095264-16095893/+/TPM4"    "chr19:16095264-16096744/+/TPM4"   
[15] "chr19:16095264-16095591/+/TPM4"    "chr2:197490527-197490664/-/HSPD1" 
[17] "chr20:37238402-37238449/+/RPN2"    "chr3:197953488-197953660/+/RPL35A"
[19] "chr4:82425563-82425667/-/HNRNPDL"  "chr4:118278944-118279137/+/SNHG8" 
[21] "chr4:118278934-118279137/+/SNHG8"  "chr4:118279107-118279137/+/SNHG8" 
[23] "chr4:118278966-118279137/+/SNHG8"  "chr5:83519349-83522309/+/VCAN"    
[25] "chr6:85677795-85677875/-/SNHG5"    "chr6:85677795-85677868/-/SNHG5"   
[27] "chr6:85677791-85677875/-/SNHG5"    "chr6:85677795-85677899/-/SNHG5"   
[29] "chr9:35684732-35684807/-/TPM2"     "chr9:35684732-35684802/-/TPM2"    
[31] "chrX:154400464-154400626/+/RPL10" 
DefaultAssay(obj) <- "exclude"
p1 <- FeaturePlot(obj, features = c("chr19:16095264-16095357/+/TPM4"),order = TRUE)
DefaultAssay(obj) <- "exon"
p2 <- FeaturePlot(obj, features = c("chr19:16095264-16095357/+/TPM4"),order = TRUE)
p3 <- PSIPlot(obj, exon.assay = "exon", exclude.assay = "exclude", features = c("chr19:16095264-16095357/+/TPM4"),order = TRUE)
cowplot::plot_grid(p1,p2,p3, ncol=3)

TrackPlot(bamfile = "Parent_SC3v3_Human_Glioblastoma_possorted_genome_bam.bam", gtf = gtf, gene = "TPM4", cell.group = Idents(obj), highlights = c(16095264,16095357), junc = TRUE, max.depth = 1)

Exon or junction expression is part of gene expression, so inverse expression patterns can indicate alternative splicing. By contrast, exon-skipped reads are largely independent of exon expression, offering higher sensitivity for detecting splicing events.

The spatial dissimilarity test does not model the spatial dependency of the binding feature, so many events may be prioritized when the binding feature is sparse. Intersecting results from both directions (exon vs. exclude and exclude vs. exon) helps reduce false positives from low coverage.

Mode 3 specifically detects strong inverse expression patterns by summing exon reads and exon-excluded reads as the binding assay. Events found by mode 3 are a subset of those found by mode 1, making it a stricter filter.

DefaultAssay(obj) <- "exclude"
obj <- RunSDT(obj, bind.name = "exon_name", bind.assay = "exon", mode = 3, prefix = "mode3")
DefaultAssay(obj) <- "exon"
obj <- RunSDT(obj, bind.name = "exon_name", bind.assay = "exclude", mode = 3, prefix = "mode3")
FbtPlot(obj, val = "mode3.padj", remove.chr = TRUE, assay = c("exclude", "exon"), shape.by = "assay", col.by = "assay", pt.size = 2, cols=c("yellow", "green"))

In this case study, we applied the spatial dissimilarity test to multiple feature pairs. The method works on the entire cell population without requiring prior clustering or annotation, making it suitable for exploratory analysis. We recommend testing both exons and junctions against their host genes, particularly in 3’ or 5’ biased scRNA-seq data. The exon vs. exon-skipped comparison provides additional power to detect exon exclusion events. For cell-cluster-specific patterns, follow up with heatmaps and co-clustering.

Questions?

If you have any questions regarding this vignette and the usage of Yano, please feel free to report them through the discussion forum. When submitting your query, please ensure you attach the commands you used for better clarity and support.

Command(obj)
 [1] "NormalizeData.RNA"            "FindVariableFeatures.RNA"    
 [3] "RunPCA.RNA"                   "FindNeighbors.RNA.pca"       
 [5] "FindClusters"                 "RunUMAP.RNA.pca"             
 [7] "ParseExonName.exon"           "NormalizeData.exon"          
 [9] "RunAutoCorr.exon.pca"         "SetAutoCorrFeatures.exon"    
[11] "NormalizeData.junction"       "RunAutoCorr.junction.pca"    
[13] "SetAutoCorrFeatures.junction" "ParseExonName.junction"      
[15] "RunSDT.junction"              "ScaleData.RNA"               
[17] "ScaleData.exon"               "NormalizeData.exclude"       
[19] "RunAutoCorr.exclude.pca"      "SetAutoCorrFeatures.exclude" 
[21] "ParseExonName.exclude"        "RunSDT.exclude"              
[23] "RunSDT.exon"                 
sessionInfo()
R version 4.5.3 (2026-03-11)
Platform: x86_64-pc-linux-gnu
Running under: Ubuntu 24.04.4 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.26.so;  LAPACK version 3.12.0

locale:
 [1] LC_CTYPE=C.UTF-8       LC_NUMERIC=C           LC_TIME=C.UTF-8       
 [4] LC_COLLATE=C.UTF-8     LC_MONETARY=C.UTF-8    LC_MESSAGES=C.UTF-8   
 [7] LC_PAPER=C.UTF-8       LC_NAME=C              LC_ADDRESS=C          
[10] LC_TELEPHONE=C         LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C   

time zone: Etc/UTC
tzcode source: system (glibc)

attached base packages:
[1] grid      stats     graphics  grDevices utils     datasets  methods  
[8] base     

other attached packages:
 [1] ComplexHeatmap_2.24.1 RColorBrewer_1.1-3    future_1.70.0        
 [4] Matrix_1.7-5          ggplot2_4.0.2         dplyr_1.2.0          
 [7] Seurat_5.4.0          SeuratObject_5.3.0    sp_2.2-1             
[10] Yano_1.5             

loaded via a namespace (and not attached):
  [1] shape_1.4.6.1          jsonlite_2.0.0         magrittr_2.0.4        
  [4] magick_2.9.1           spatstat.utils_3.2-2   farver_2.1.2          
  [7] rmarkdown_2.30         GlobalOptions_0.1.3    vctrs_0.7.2           
 [10] ROCR_1.0-12            Cairo_1.7-0            spatstat.explore_3.8-0
 [13] htmltools_0.5.9        sass_0.4.10            sctransform_0.4.3     
 [16] parallelly_1.46.1      KernSmooth_2.23-26     bslib_0.10.0          
 [19] htmlwidgets_1.6.4      ica_1.0-3              plyr_1.8.9            
 [22] plotly_4.12.0          zoo_1.8-15             cachem_1.1.0          
 [25] igraph_2.2.2           mime_0.13              lifecycle_1.0.5       
 [28] iterators_1.0.14       pkgconfig_2.0.3        R6_2.6.1              
 [31] fastmap_1.2.0          clue_0.3-67            fitdistrplus_1.2-6    
 [34] shiny_1.13.0           digest_0.6.39          colorspace_2.1-2      
 [37] S4Vectors_0.48.1       patchwork_1.3.2        tensor_1.5.1          
 [40] RSpectra_0.16-2        irlba_2.3.7            crosstalk_1.2.2       
 [43] labeling_0.4.3         progressr_0.18.0       spatstat.sparse_3.1-0 
 [46] httr_1.4.8             polyclip_1.10-7        abind_1.4-8           
 [49] compiler_4.5.3         withr_3.0.2            doParallel_1.0.17     
 [52] S7_0.2.1               viridis_0.6.5          fastDummies_1.7.5     
 [55] MASS_7.3-65            rjson_0.2.23           gtools_3.9.5          
 [58] tools_4.5.3            lmtest_0.9-40          otel_0.2.0            
 [61] httpuv_1.6.17          future.apply_1.20.2    goftest_1.2-3         
 [64] glue_1.8.0             nlme_3.1-168           promises_1.5.0        
 [67] Rtsne_0.17             cluster_2.1.8.2        reshape2_1.4.5        
 [70] generics_0.1.4         gtable_0.3.6           spatstat.data_3.1-9   
 [73] tidyr_1.3.2            data.table_1.18.2.1    BiocGenerics_0.54.1   
 [76] spatstat.geom_3.7-3    RcppAnnoy_0.0.23       ggrepel_0.9.8         
 [79] RANN_2.6.2             foreach_1.5.2          pillar_1.11.1         
 [82] stringr_1.6.0          spam_2.11-3            RcppHNSW_0.6.0        
 [85] later_1.4.8            circlize_0.4.17        splines_4.5.3         
 [88] lattice_0.22-9         survival_3.8-6         deldir_2.0-4          
 [91] tidyselect_1.2.1       miniUI_0.1.2           pbapply_1.7-4         
 [94] knitr_1.51             gridExtra_2.3          IRanges_2.42.0        
 [97] scattermore_1.2        stats4_4.5.3           xfun_0.57             
[100] matrixStats_1.5.0      DT_0.34.0              stringi_1.8.7         
[103] lazyeval_0.2.2         yaml_2.3.12            evaluate_1.0.5        
[106] codetools_0.2-20       tibble_3.3.1           cli_3.6.5             
[109] uwot_0.2.4             xtable_1.8-8           reticulate_1.45.0     
[112] systemfonts_1.3.2      jquerylib_0.1.4        Rcpp_1.1.1            
[115] globals_0.19.1         spatstat.random_3.4-5  png_0.1-9             
[118] spatstat.univar_3.1-7  parallel_4.5.3         dotCall64_1.2         
[121] listenv_0.10.1         viridisLite_0.4.3      scales_1.4.0          
[124] ggridges_0.5.7         crayon_1.5.3           purrr_1.2.1           
[127] GetoptLong_1.1.0       rlang_1.1.7            cowplot_1.2.0         
Back to top