pacman::p_load(
Seurat, tidyverse, qs2, harmony, tictoc, cowplot, ggh4x,
CytoTRACE2, slingshot
)
knitr::opts_knit$set(root.dir = "/home/han/Desktop/guoqiang/stroke_bm/stroke_bm_Rproj")
setwd("/home/han/Desktop/guoqiang/stroke_bm/stroke_bm_Rproj")
source("codes/plot_colors.R")
source("codes/activity_helpers.R")
summarise <- dplyr::summarise
mutate <- dplyr::mutate
filter <- dplyr::filter
rename <- dplyr::rename
arrange <- dplyr::arrange
group_by <- dplyr::group_by
ungroup <- dplyr::ungroupHSPC trajectory (HSC → MEP / GMP / MDP)
HSC 向红系(MEP)、粒系(GMP)、单核(MDP)三条命运。拟时间在 Harmony 空间计算;UMAP 上的线连接各亚型中心,箭头贴在线的末端。
res_path <- "results/hspc_trajectory"
obj_path <- "data/rdata/hspc_trajectory"
if (dir.exists(res_path)) {
old_res <- list.files(res_path, full.names = TRUE)
if (length(old_res) > 0) unlink(old_res, recursive = TRUE)
} else {
dir.create(res_path, recursive = TRUE)
}
if (!dir.exists(obj_path)) dir.create(obj_path, recursive = TRUE)alpha <- 0.45
pt_size <- 0.4
raster <- FALSE
raster_dpi <- c(3000, 3000)
n_hvg <- 3000
n_dims <- 20
traj_levels <- c("HSC", "MEP", "GMP", "MDP")
traj_col <- annot_sub_col[traj_levels]1. Subset HSPC
只保留 HSC、MEP、GMP、MDP。GMP 在 08 还会作为粒系轴的起点;这里问的是 HSC 先分到哪一支。
test_genes <- qs_read("data/rdata/test_genes.qs2", nthreads = 10)
seurat_object <- qs_read("data/rdata/seurat_object_final.qs2", nthreads = 10)
stopifnot(all(c("sample", "group", "annot_sub") %in% colnames(seurat_object[[]])))
seurat_object$group <- factor(seurat_object$group, levels = c("CTRL", "ACI"))
keep <- as.character(seurat_object$annot_sub) %in% traj_levels
print(table(seurat_object$annot_sub[keep], seurat_object$group[keep]))
CTRL ACI
HSC 298 106
MEP 155 24
GMP 204 1320
MDP 733 526
Pro-B 0 0
Large Pre-B 0 0
Small Pre-B 0 0
Trans B 0 0
Naive B 0 0
Memory B 0 0
Plasma 0 0
CD4 Tnaive 0 0
CD4 Tcm 0 0
CD4 Treg 0 0
CD8 Tnaive 0 0
CD8 Tem 0 0
CD8 CTL 0 0
CD8 NKT 0 0
MAIT 0 0
gdT 0 0
CD56bright NK 0 0
CD56dim NK 0 0
CD14 Mono 0 0
CD16 Mono 0 0
cDC2 0 0
pDC 0 0
Promyelocyte 0 0
MMP8 Pre-Neut 0 0
MMP9 Pre-Neut 0 0
S100A12 Neut 0 0
SLC8A1 Neut 0 0
ISG15 Neut 0 0
Early Ery 0 0
Late Ery 0 0
seurat_object <- seurat_object[, keep]
seurat_object$annot_sub <- factor(
as.character(seurat_object$annot_sub),
levels = traj_levels
)
dim(seurat_object)[1] 38606 3366
if (length(Layers(seurat_object, search = "counts")) > 1) {
seurat_object <- JoinLayers(seurat_object)
}
seurat_object[["RNA"]]$data <- NULL
seurat_object[["RNA"]]$scale.data <- NULL2. Normalize, HVG, PCA, Harmony, UMAP
子集上重新高变基因、PCA、Harmony 和 UMAP。亚型名字沿用 06,不再聚类。
seurat_object <- NormalizeData(seurat_object, verbose = TRUE)
seurat_object <- FindVariableFeatures(
seurat_object, nfeatures = n_hvg, verbose = TRUE
)
pca_features <- setdiff(
VariableFeatures(seurat_object),
test_genes$gene[test_genes$unwant | test_genes$ig | test_genes$tr]
)
seurat_object <- ScaleData(
seurat_object, features = pca_features, assay = "RNA"
)
seurat_object <- RunPCA(
seurat_object, npcs = 50, features = pca_features,
verbose = TRUE, reduction.name = "pca"
)
ElbowPlot(seurat_object, reduction = "pca", ndims = 50)tic("Harmony")
seurat_object <- RunHarmony(
seurat_object, c("sample"), ncores = 15, plot_convergence = TRUE
)toc()Harmony: 1.362 sec elapsed
seurat_object <- RunUMAP(
seurat_object, dims = 1:n_dims, reduction = "harmony",
reduction.name = "umap"
)3. Annotation UMAP
核对 HSC 与三个下游亚型是否分开。分叉要画得住,三类终点不能完全叠在一起。
plot_umap_short(
seurat_object, group.by = "annot_sub", cols = traj_col,
pt.size = pt_size, alpha = alpha, raster = raster, raster.dpi = raster_dpi,
label = TRUE, label.size = 4, legend = TRUE
)ggsave(file.path(res_path, "01_umap_annot.pdf"), width = 8, height = 7, dpi = 600)plot_grid(
ncol = 2,
plot_umap_short(
subset(seurat_object, group == "CTRL"),
group.by = "annot_sub", cols = traj_col,
pt.size = pt_size, alpha = alpha, raster = raster, raster.dpi = raster_dpi,
label = FALSE, title = "CTRL"
),
plot_umap_short(
subset(seurat_object, group == "ACI"),
group.by = "annot_sub", cols = traj_col,
pt.size = pt_size, alpha = alpha, raster = raster, raster.dpi = raster_dpi,
label = FALSE, title = "ACI"
)
)ggsave(file.path(res_path, "01_umap_by_group.pdf"), width = 14, height = 7, dpi = 600)plot_grid(
ncol = 2,
DimPlot(
seurat_object, reduction = "umap", group.by = "sample",
pt.size = pt_size, alpha = alpha, raster = raster, raster.dpi = raster_dpi
) + theme(aspect.ratio = 1),
DimPlot(
seurat_object, reduction = "umap", group.by = "group", cols = group_col,
pt.size = pt_size, alpha = alpha, raster = raster, raster.dpi = raster_dpi
) + theme(aspect.ratio = 1)
)ggsave(file.path(res_path, "01_umap_sample_group.pdf"), width = 14, height = 7, dpi = 600)4. CytoTRACE2
高分更接近未成熟。HSC 应偏高,MEP / GMP / MDP 应偏低。组间密度差也可能只是组成不同。
cyto_qs2 <- file.path(obj_path, "cytotrace_hspc.qs2")
cyto_cache <- NULL
if (file.exists(cyto_qs2)) {
cyto_cache <- qs_read(cyto_qs2, nthreads = 10)
}
same_n <- !is.null(cyto_cache) && nrow(cyto_cache) == ncol(seurat_object)
same_cells <- same_n &&
identical(sort(rownames(cyto_cache)), sort(colnames(seurat_object)))
if (same_cells) {
message("Reuse CytoTRACE2 qs2. Skip cytotrace2().")
cyto_cache <- cyto_cache[colnames(seurat_object), , drop = FALSE]
seurat_object <- AddMetaData(seurat_object, cyto_cache)
} else {
counts_mat <- LayerData(seurat_object, assay = "RNA", layer = "counts")
seurat_object[["RNA"]]$counts <- as(counts_mat, "dgCMatrix")
seurat_object <- cytotrace2(
seurat_object, species = "human", is_seurat = TRUE, ncores = 10
)
cyto_cols <- grep("^CytoTRACE2", colnames(seurat_object[[]]), value = TRUE)
cyto_out <- FetchData(seurat_object, vars = cyto_cols)
qs_save(cyto_out, cyto_qs2, nthreads = 10)
}
table(seurat_object$CytoTRACE2_Potency)
Differentiated Unipotent Oligopotent Multipotent Pluripotent
437 464 2212 253 0
Totipotent
0
summary(seurat_object$CytoTRACE2_Score) Min. 1st Qu. Median Mean 3rd Qu. Max.
0.01267 0.30852 0.40161 0.36279 0.44279 0.64856
FeaturePlot(
seurat_object, reduction = "umap", features = "CytoTRACE2_Score",
pt.size = pt_size, raster = raster, raster.dpi = raster_dpi
) + theme(aspect.ratio = 1)ggsave(file.path(res_path, "02_cytotrace_umap.pdf"), width = 8, height = 7, dpi = 600)cyto_meta <- FetchData(
seurat_object, vars = c("sample", "group", "annot_sub", "CytoTRACE2_Score")
)
p_cyto_box <- ggplot(cyto_meta, aes(x = annot_sub, y = CytoTRACE2_Score, fill = annot_sub)) +
geom_boxplot(outlier.size = 0.2, width = 0.7) +
scale_fill_manual(values = traj_col) +
theme_classic() +
theme(legend.position = "none", axis.text.x = element_text(angle = 45, hjust = 1)) +
xlab(NULL) +
ylab("CytoTRACE2")
ggsave(file.path(res_path, "02_cytotrace_by_subtype.pdf"), p_cyto_box, width = 6, height = 5, dpi = 600)
p_cyto_boxsample_cyto <- cyto_meta |>
dplyr::group_by(sample, group) |>
dplyr::summarise(
n_cell = dplyr::n(),
cyto_median = median(CytoTRACE2_Score, na.rm = TRUE),
.groups = "drop"
) |>
dplyr::filter(n_cell >= min_cells_sample)
cyto_test <- wilcox_ctrl_aci(sample_cyto$cyto_median, sample_cyto$group) |>
dplyr::mutate(feature = "cyto_median") |>
add_stars()
write_csv(sample_cyto, file.path(res_path, "02_sample_cytotrace.csv"))
write_csv(cyto_test, file.path(res_path, "02_sample_cytotrace_wilcox.csv"))
print(cyto_test)# A tibble: 1 × 8
n_ctrl n_aci median_ctrl median_aci delta_aci_minus_ctrl p feature star
<int> <int> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
1 6 5 0.408 0.400 -0.00830 0.315 cyto_med… ns
5. Slingshot
起点固定为 HSC,三条终点为 MEP、GMP、MDP。拟时间在 Harmony 上算;图上的线走亚型中心,箭头是曲线最后一段的切向。组间看每例细胞落在哪一支的比例。
sling <- list()
sling$dimred_fit <- Embeddings(seurat_object, "harmony")[, 1:n_dims]
sling$dimred <- Embeddings(seurat_object, "umap")[, 1:2]
sling$clustering <- seurat_object$annot_sub
sling$slingshot_fit <- slingshot(
sling$dimred_fit,
sling$clustering,
start.clus = "HSC",
end.clus = c("MEP", "GMP", "MDP"),
stretch = 0
)
print(slingLineages(sling$slingshot_fit))$Lineage1
[1] "HSC" "MDP"
$Lineage2
[1] "HSC" "MEP"
$Lineage3
[1] "HSC" "GMP"
lin_ok <- vapply(
slingLineages(sling$slingshot_fit),
function(x) identical(x[[1]], "HSC"),
logical(1)
)
if (!all(lin_ok)) {
lin_txt <- vapply(
slingLineages(sling$slingshot_fit),
function(x) paste(x, collapse = ">"),
character(1)
)
stop("Slingshot lineages do not all start at HSC: ", paste(lin_txt, collapse = "; "))
}
sling$pseudotime <- as.data.frame(slingPseudotime(sling$slingshot_fit))
sling$slingshot <- sling$slingshot_fit
stopifnot(identical(rownames(sling$dimred_fit), colnames(seurat_object)))pt_cols <- grep("^Lineage", colnames(sling$pseudotime), value = TRUE)
for (ln in pt_cols) {
seurat_object[[paste0("sling_", ln)]] <- sling$pseudotime[[ln]]
}
path_from_centroids <- function(xy, n = 120) {
xy <- as.matrix(xy)
stopifnot(nrow(xy) >= 2, ncol(xy) == 2)
if (nrow(xy) == 2) {
t <- seq(0, 1, length.out = n)
return(data.frame(
x = (1 - t) * xy[1, 1] + t * xy[2, 1],
y = (1 - t) * xy[1, 2] + t * xy[2, 2]
))
}
grDevices::pdf(NULL)
sp <- graphics::xspline(
xy[, 1], xy[, 2],
shape = -0.5,
open = TRUE,
draw = FALSE,
repEnds = TRUE
)
grDevices::dev.off()
dx <- diff(sp$x)
dy <- diff(sp$y)
s <- c(0, cumsum(sqrt(dx * dx + dy * dy)))
s <- s / max(s)
t <- seq(0, 1, length.out = n)
data.frame(
x = stats::approx(s, sp$x, xout = t)$y,
y = stats::approx(s, sp$y, xout = t)$y
)
}
umap_cent <- as.data.frame(sling$dimred)
colnames(umap_cent) <- c("x", "y")
umap_cent$clus <- as.character(sling$clustering)
cent_df <- umap_cent |>
dplyr::group_by(clus) |>
dplyr::summarise(x = mean(.data$x), y = mean(.data$y), .groups = "drop")
lin_map <- slingLineages(sling$slingshot_fit)
curve_sm <- purrr::imap_dfr(lin_map, function(clus, nm) {
cc <- cent_df[match(clus, cent_df$clus), c("x", "y")]
d <- path_from_centroids(cc)
d$Lineage <- nm
d$Order <- seq_len(nrow(d))
d$end_lab <- tail(clus, 1)
d
})
lab_df <- curve_sm |>
dplyr::group_by(Lineage) |>
dplyr::slice_max(order_by = .data$Order, n = 2, with_ties = FALSE) |>
dplyr::arrange(.data$Order) |>
dplyr::summarise(
x0 = dplyr::first(.data$x),
y0 = dplyr::first(.data$y),
x = dplyr::last(.data$x),
y = dplyr::last(.data$y),
lab = dplyr::last(.data$end_lab),
.groups = "drop"
) |>
dplyr::mutate(
dx = .data$x - .data$x0,
dy = .data$y - .data$y0,
x = .data$x + 8 * .data$dx,
y = .data$y + 8 * .data$dy
)
start_df <- cent_df |>
dplyr::filter(.data$clus == "HSC") |>
dplyr::select(x, y)
plot_df <- as.data.frame(sling$dimred) |>
mutate(annot_sub = sling$clustering)
x_umap <- colnames(plot_df)[1]
y_umap <- colnames(plot_df)[2]
p_sling <- ggplot(plot_df, aes(.data[[x_umap]], .data[[y_umap]])) +
geom_point(aes(color = annot_sub), shape = 19, size = 0.35, alpha = 0.45) +
geom_path(
data = curve_sm,
aes(x = x, y = y, group = Lineage),
linewidth = 1.15,
lineend = "butt",
linejoin = "round",
arrow = arrow(type = "closed", length = unit(0.28, "cm"), angle = 20)
) +
geom_point(
data = start_df, aes(x = x, y = y),
inherit.aes = FALSE,
size = 4, shape = 21, fill = "white", color = "black", stroke = 1.1
) +
geom_text(
data = start_df, aes(x = x, y = y),
inherit.aes = FALSE,
label = "HSC", fontface = "bold", size = 3.5, vjust = -1.2
) +
geom_text(
data = lab_df, aes(x = x, y = y, label = lab),
size = 4.5, fontface = "bold"
) +
scale_color_manual(values = traj_col) +
theme_classic() +
theme_umap_short() +
theme(legend.position = "right") +
xlab("UMAP-1") +
ylab("UMAP-2") +
scale_x_continuous(breaks = NULL) +
scale_y_continuous(breaks = NULL) +
guides(x = umap_trunc_axis(), y = umap_trunc_axis())
ggsave(file.path(res_path, "03_slingshot_umap.pdf"), p_sling, width = 8, height = 7, dpi = 600)
p_slingif (length(pt_cols) > 0) {
for (ln in pt_cols) {
FeaturePlot(
seurat_object, reduction = "umap", features = paste0("sling_", ln),
pt.size = pt_size, raster = raster, raster.dpi = raster_dpi
) + theme(aspect.ratio = 1)
ggsave(
file.path(res_path, paste0("03_slingshot_pt_", ln, ".pdf")),
width = 8, height = 7, dpi = 600
)
}
}
pt_long <- FetchData(
seurat_object,
vars = c("annot_sub", paste0("sling_", pt_cols))
) |>
tidyr::pivot_longer(
dplyr::all_of(paste0("sling_", pt_cols)),
names_to = "lineage", values_to = "pt"
)
p_pt_box <- ggplot(pt_long, aes(x = annot_sub, y = pt, fill = annot_sub)) +
geom_boxplot(outlier.size = 0.15, width = 0.7, na.rm = TRUE) +
facet_wrap(~lineage) +
scale_fill_manual(values = traj_col) +
theme_classic() +
theme(
legend.position = "none",
axis.text.x = element_text(angle = 45, hjust = 1)
) +
xlab(NULL) +
ylab("Pseudotime")
ggsave(file.path(res_path, "03_pt_by_subtype.pdf"), p_pt_box, width = 10, height = 4.2, dpi = 600)
p_pt_boxhspc_meta <- FetchData(
seurat_object,
vars = c("sample", "group", "annot_sub", paste0("sling_", pt_cols))
) |>
rownames_to_column("barcode")
write_csv(hspc_meta, file.path(res_path, "03_hspc_pseudotime_cells.csv"))
# Fate: among cells assigned to a lineage, fraction ending toward GMP vs MEP vs MDP.
lin_map <- slingLineages(sling$slingshot)
end_clus <- vapply(lin_map, function(x) tail(x, 1), character(1))
print(end_clus)Lineage1 Lineage2 Lineage3
"MDP" "MEP" "GMP"
pt_mat <- as.matrix(sling$pseudotime)
idx <- max.col(replace(pt_mat, is.na(pt_mat), -Inf), ties.method = "first")
assigned <- colnames(pt_mat)[idx]
ok_pt <- is.finite(pt_mat[cbind(seq_len(nrow(pt_mat)), idx)])
assigned[!ok_pt] <- NA
hspc_meta$lineage_end <- unname(end_clus[assigned])
fate <- hspc_meta |>
dplyr::filter(!is.na(.data$lineage_end)) |>
dplyr::count(sample, group, lineage_end, name = "n") |>
dplyr::group_by(sample, group) |>
dplyr::mutate(frac = n / sum(n)) |>
dplyr::ungroup()
write_csv(fate, file.path(res_path, "03_sample_fate_frac.csv"))
print(fate)# A tibble: 33 × 5
sample group lineage_end n frac
<chr> <fct> <chr> <int> <dbl>
1 ACI-1 ACI GMP 286 0.719
2 ACI-1 ACI MDP 74 0.186
3 ACI-1 ACI MEP 38 0.0955
4 ACI-2 ACI GMP 427 0.690
5 ACI-2 ACI MDP 158 0.255
6 ACI-2 ACI MEP 34 0.0549
7 ACI-3 ACI GMP 188 0.655
8 ACI-3 ACI MDP 83 0.289
9 ACI-3 ACI MEP 16 0.0557
10 ACI-4 ACI GMP 311 0.681
# ℹ 23 more rows
p_fate <- ggplot(fate, aes(x = group, y = frac, fill = group)) +
geom_boxplot(width = 0.55, outlier.shape = NA) +
geom_jitter(width = 0.12, size = 2) +
facet_wrap(~lineage_end) +
scale_fill_manual(values = group_col) +
theme_classic() +
theme(legend.position = "none") +
xlab(NULL) +
ylab("Fraction of HSPC on this lineage")
ggsave(file.path(res_path, "03_fate_frac.pdf"), p_fate, width = 9, height = 4.5, dpi = 600)
p_fatesample_group <- dplyr::distinct(hspc_meta, sample, group)
fate_test <- fate |>
dplyr::select(-group) |>
tidyr::complete(sample, lineage_end, fill = list(frac = 0, n = 0)) |>
dplyr::left_join(sample_group, by = "sample") |>
dplyr::group_by(lineage_end) |>
dplyr::group_modify(function(d, k) {
wilcox_ctrl_aci(d$frac, d$group)
}) |>
dplyr::ungroup() |>
add_stars()
write_csv(fate_test, file.path(res_path, "03_fate_frac_wilcox.csv"))
print(fate_test)# A tibble: 3 × 8
lineage_end n_ctrl n_aci median_ctrl median_aci delta_aci_minus_ctrl p
<chr> <int> <int> <dbl> <dbl> <dbl> <dbl>
1 GMP 6 5 0.287 0.690 0.403 0.00811
2 MDP 6 5 0.437 0.255 -0.182 0.00811
3 MEP 6 5 0.241 0.0549 -0.186 0.00811
# ℹ 1 more variable: star <chr>
qs_save(sling, file.path(obj_path, "slingshot_hspc.qs2"), nthreads = 10)
qs_save(
seurat_object,
file.path(obj_path, "seurat_object_hspc_traj.qs2"),
nthreads = 10
)sessionInfo()R version 4.4.3 (2025-02-28)
Platform: x86_64-pc-linux-gnu
Running under: Ubuntu 24.04.3 LTS
Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.12.0
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.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: Asia/Shanghai
tzcode source: system (glibc)
attached base packages:
[1] stats4 parallel stats graphics grDevices utils datasets
[8] methods base
other attached packages:
[1] slingshot_2.14.0 TrajectoryUtils_1.14.0
[3] SingleCellExperiment_1.28.1 SummarizedExperiment_1.36.0
[5] Biobase_2.66.0 GenomicRanges_1.58.0
[7] GenomeInfoDb_1.42.0 IRanges_2.40.0
[9] S4Vectors_0.44.0 BiocGenerics_0.52.0
[11] MatrixGenerics_1.18.0 matrixStats_1.4.1
[13] princurve_2.1.6 CytoTRACE2_1.1.0
[15] RSpectra_0.16-2 Rfast_2.1.0
[17] RcppParallel_5.1.9 RcppZiggurat_0.1.6
[19] plyr_1.8.9 Matrix_1.7-3
[21] magrittr_2.0.3 HiClimR_2.2.1
[23] doParallel_1.0.17 iterators_1.0.14
[25] foreach_1.5.2 data.table_1.16.2
[27] ggh4x_0.2.8 cowplot_1.1.3
[29] tictoc_1.2.1 harmony_1.2.3
[31] Rcpp_1.0.13-1 qs2_0.1.7
[33] lubridate_1.9.3 forcats_1.0.0
[35] stringr_1.5.1 dplyr_1.1.4
[37] purrr_1.0.2 readr_2.1.5
[39] tidyr_1.3.1 tibble_3.2.1
[41] ggplot2_3.5.1 tidyverse_2.0.0
[43] Seurat_5.2.1 SeuratObject_5.0.2
[45] sp_2.1-4
loaded via a namespace (and not attached):
[1] RcppAnnoy_0.0.22 splines_4.4.3
[3] later_1.4.1 polyclip_1.10-7
[5] fastDummies_1.7.4 lifecycle_1.0.4
[7] vroom_1.6.5 globals_0.16.3
[9] lattice_0.22-6 MASS_7.3-65
[11] plotly_4.10.4 rmarkdown_2.29
[13] yaml_2.3.10 httpuv_1.6.15
[15] sctransform_0.4.1 spam_2.11-0
[17] spatstat.sparse_3.1-0 reticulate_1.42.0
[19] pbapply_1.7-2 RColorBrewer_1.1-3
[21] abind_1.4-8 zlibbioc_1.52.0
[23] Rtsne_0.17 GenomeInfoDbData_1.2.13
[25] ggrepel_0.9.6 irlba_2.3.5.1
[27] listenv_0.9.1 spatstat.utils_3.1-1
[29] goftest_1.2-3 spatstat.random_3.3-2
[31] fitdistrplus_1.2-1 parallelly_1.39.0
[33] DelayedMatrixStats_1.28.0 ncdf4_1.23
[35] codetools_0.2-20 DelayedArray_0.32.0
[37] tidyselect_1.2.1 UCSC.utils_1.2.0
[39] farver_2.1.2 spatstat.explore_3.3-3
[41] jsonlite_1.8.9 progressr_0.15.1
[43] ggridges_0.5.6 survival_3.8-3
[45] systemfonts_1.1.0 tools_4.4.3
[47] ragg_1.3.3 ica_1.0-3
[49] glue_1.8.0 gridExtra_2.3
[51] SparseArray_1.6.0 xfun_0.49
[53] withr_3.0.2 fastmap_1.2.0
[55] fansi_1.0.6 digest_0.6.37
[57] timechange_0.3.0 R6_2.5.1
[59] mime_0.12 textshaping_0.4.0
[61] colorspace_2.1-1 scattermore_1.2
[63] tensor_1.5 spatstat.data_3.1-4
[65] RhpcBLASctl_0.23-42 utf8_1.2.4
[67] generics_0.1.3 httr_1.4.7
[69] htmlwidgets_1.6.4 S4Arrays_1.6.0
[71] uwot_0.2.2 pkgconfig_2.0.3
[73] gtable_0.3.6 lmtest_0.9-40
[75] XVector_0.46.0 htmltools_0.5.8.1
[77] dotCall64_1.2 scales_1.3.0
[79] png_0.1-8 spatstat.univar_3.1-1
[81] knitr_1.49 tzdb_0.4.0
[83] reshape2_1.4.4 nlme_3.1-166
[85] zoo_1.8-12 KernSmooth_2.23-26
[87] miniUI_0.1.1.1 pillar_1.9.0
[89] grid_4.4.3 vctrs_0.6.5
[91] RANN_2.6.2 promises_1.3.2
[93] stringfish_0.18.0 xtable_1.8-4
[95] cluster_2.1.8.1 evaluate_1.0.1
[97] cli_3.6.3 compiler_4.4.3
[99] rlang_1.1.4 crayon_1.5.3
[101] future.apply_1.11.3 labeling_0.4.3
[103] stringi_1.8.4 viridisLite_0.4.2
[105] deldir_2.0-4 munsell_0.5.1
[107] lazyeval_0.2.2 spatstat.geom_3.3-4
[109] pacman_0.5.1 RcppHNSW_0.6.0
[111] hms_1.1.3 patchwork_1.3.0
[113] sparseMatrixStats_1.18.0 bit64_4.5.2
[115] future_1.34.0 shiny_1.9.1
[117] ROCR_1.0-11 igraph_2.1.2
[119] bit_4.5.0