Last updated: 2026-07-16
Checks: 7 0
Knit directory: flex-fusion-probes/
This reproducible R Markdown analysis was created with workflowr (version 1.7.1). The Checks tab describes the reproducibility checks that were applied when the results were created. The Past versions tab lists the development history.
Great! Since the R Markdown file has been committed to the Git repository, you know the exact version of the code that produced these results.
Great job! The global environment was empty. Objects defined in the global environment can affect the analysis in your R Markdown file in unknown ways. For reproduciblity it’s best to always run the code in an empty environment.
The command set.seed(20240925) was run prior to running
the code in the R Markdown file. Setting a seed ensures that any results
that rely on randomness, e.g. subsampling or permutations, are
reproducible.
Great job! Recording the operating system, R version, and package versions is critical for reproducibility.
Nice! There were no cached chunks for this analysis, so you can be confident that you successfully produced the results during this run.
Great job! Using relative paths to the files within your workflowr project makes it easier to run your code on other machines.
Great! You are using Git for version control. Tracking code development and connecting the code version to the results is critical for reproducibility.
The results in this page were generated with repository version 510ab74. See the Past versions tab to see a history of the changes made to the R Markdown and HTML files.
Note that you need to be careful to ensure that all relevant files for
the analysis have been committed to Git prior to generating the results
(you can use wflow_publish or
wflow_git_commit). workflowr only checks the R Markdown
file, but you know if there are other scripts or data files that it
depends on. Below is the status of the Git repository when the results
were generated:
Ignored files:
Ignored: .DS_Store
Ignored: .Rhistory
Ignored: .Rproj.user/
Ignored: analysis/.gitignore
Ignored: analysis/figure/
Ignored: analysis/obsolete/B-ALL_nonblast_fusion_analysis_cache/
Ignored: analysis/projectionFigures/
Ignored: code/files/
Ignored: data/.DS_Store
Ignored: data/BoneMarrowMap/
Ignored: data/BoneMarrowMapBoneMarrowMap_SymphonyReference.rds
Ignored: data/BoneMarrowMapBoneMarrowMap_uwot_model.uwot
Ignored: data/CAPTURE-1-POOL-FLEX/
Ignored: data/CAPTURE-2-POOL-FLEX/
Ignored: data/Pool-240917-FLEX/
Ignored: data/RDS/
Ignored: data/Run_1_and_Run_2/
Ignored: data/Run_2/
Ignored: logs/
Ignored: output/
Ignored: projectionFigures/
Ignored: renv/library/
Ignored: renv/staging/
Untracked files:
Untracked: CLAUDE.md
Untracked: analysis/B-ALL_exp2_c1437_clone_analysis.Rmd
Untracked: analysis/B-ALL_exp2_c369_mrd_analysis.Rmd
Untracked: analysis/B-ALL_exp2_fig4_assembly.Rmd
Untracked: analysis/B-ALL_exp2_joint_clustering.Rmd
Untracked: analysis/B-ALL_exp2_nonblast_fusion_analysis.Rmd
Untracked: data/sample_information_flex_experiment_2_table.csv
Untracked: poster.pptx
Unstaged changes:
Deleted: analysis/B-ALL_exp2_background.Rmd
Deleted: analysis/B-ALL_exp2_c1437_li2025_clone_analysis.Rmd
Deleted: analysis/B-ALL_nonblast_fusion_analysis.Rmd
Modified: analysis/index.Rmd
Modified: render_all.sh
Note that any generated files, e.g. HTML, png, CSS, etc., are not included in this status report because it is ok for generated content to have uncommitted changes.
These are the previous versions of the repository in which changes were
made to the R Markdown (analysis/B-ALL_exp2_clustering.Rmd)
and HTML (docs/B-ALL_exp2_clustering.html) files. If you’ve
configured a remote Git repository (see ?wflow_git_remote),
click on the hyperlinks in the table below to view the files as they
were in that past version.
| File | Version | Author | Date | Message |
|---|---|---|---|---|
| Rmd | 510ab74 | Jovana Maksimovic | 2026-07-16 | wflow_publish("analysis/B-ALL_exp2_clustering.Rmd") |
| html | abab370 | Jovana Maksimovic | 2026-05-19 | Build site. |
| Rmd | 5481825 | Jovana Maksimovic | 2026-05-19 | Update figure labels, add C369 heading, comment out exp1 DE section, minor point size |
| html | 74aa8d8 | Jovana Maksimovic | 2026-05-19 | Build site. |
| Rmd | 700df84 | Jovana Maksimovic | 2026-05-19 | MRD dot plot: n labels, fusion -ve label, remove reclassify-ambient chunk and Poisson |
| html | a8def9a | Jovana Maksimovic | 2026-05-18 | Build site. |
| Rmd | 08f1e2b | Jovana Maksimovic | 2026-05-18 | Update index and exp1/exp2 notebooks |
| html | 1b5bb97 | Jovana Maksimovic | 2026-05-11 | Build site. |
| Rmd | af3bc31 | Jovana Maksimovic | 2026-05-11 | Re-run all notebooks with updated RDS naming scheme |
| Rmd | 1f3159b | Jovana Maksimovic | 2026-05-08 | Rename RDS checkpoints to systematic naming scheme |
| Rmd | 71c5f99 | Jovana Maksimovic | 2026-05-08 | docs: add getting_started page; fix myeloid_types error; move exploratory notebooks to obsolete |
| Rmd | 1578018 | Jovana Maksimovic | 2026-05-08 | docs: add prose, standardise headings and figure labels across all 10 B-ALL notebooks |
| Rmd | 1a33400 | Jovana Maksimovic | 2026-05-08 | B-ALL cleanup: fix index links, stray library() calls, add chunk labels |
| Rmd | 1724beb | Jovana Maksimovic | 2026-05-08 | Standardise YAML headers and chunk names across all notebooks; merge utility_functions into utilities.R |
| Rmd | 10d2f5e | Jovana Maksimovic | 2026-05-08 | Rename analysis notebooks to new naming scheme |
This notebook performs per-sample clustering of all eight Experiment
2 B-ALL samples, examines fusion transcript detection in the context of
cell type and cell cycle, and produces the following publication
figures: a lineage marker dot plot across blast populations
(Figure 4D), a bar chart of the percentage of
ETV6::RUNX1 fusion-positive cells per sample (Figure
4E), the C369 BoneMarrowMap UMAP across timepoints
(Figure 4I), and a B-precursor marker dot plot for C369
MRD cell groups (Figure 4J). An exploratory C1437 clone
overview is also included here; the canonical publication C1437 figures
(4F–4H) are produced in
B-ALL_exp2_c1437_clone_analysis.Rmd.
file <- here("data", "RDS", "ball_exp2_annotated.seu.rds")
seu <- readRDS(file)
All cells from the eight patient samples are normalised together and projected into a shared UMAP embedding for an initial overview of sample composition and cell type distribution.
seu <- NormalizeData(seu)
seu <- FindVariableFeatures(seu, selection.method = "vst",
nfeatures = 3000, verbose = FALSE)
seu <- ScaleData(seu)
seu <- RunPCA(seu, verbose = FALSE, npcs = 30)
seu <- RunUMAP(seu, dims = 1:30, reduction = "pca")
Plot UMAP labelled by sample and reference annotations.
DimPlot(seu, reduction = "umap", group.by = "patient_timepoint",
label = FALSE, repel = TRUE, label.size = 2.5, ) +
scale_color_manual(values = RColorBrewer::brewer.pal(n = 8, "Dark2")) +
guides(colour = guide_legend(ncol = 3,
override.aes = list(size = 3))) +
theme(legend.position = "bottom")

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
DimPlot(seu, reduction = "umap", group.by = "PPID",
label = FALSE, repel = TRUE, label.size = 2.5, ) +
scale_color_manual(values = RColorBrewer::brewer.pal(n = 8, "Set2")) +
guides(colour = guide_legend(ncol = 3,
override.aes = list(size = 3))) +
theme(legend.position = "bottom")

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
DimPlot(seu, reduction = "umap", group.by = "predicted_CellType_Broad") +
paletteer::scale_color_paletteer_d("pals::glasbey") +
guides(colour = guide_legend(ncol = 3,
override.aes = list(size = 3))) +
theme(legend.position = "bottom")

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
DimPlot(seu, reduction = "umap", label = FALSE, repel = TRUE,
label.size = 2.5, group.by = "patient_timepoint",
cells.highlight = which(seu$patient_fusion != "not-detected"),
sizes.highlight = 0.1) +
NoLegend()

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
DimPlot(seu, reduction = "umap", label = TRUE, repel = TRUE,
label.size = 2.5, group.by = "batch")

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
DimPlot(seu, reduction = "umap", label = TRUE, repel = TRUE,
label.size = 2.5, group.by = "status")

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
# Calculate median proportion of fusion-positive cells per sample
median_prop <- seu@meta.data %>%
group_by(patient_timepoint) %>%
summarise(prop_fusion = sum(fusion_detected)/n()) %>%
summarise(median_prop = median(prop_fusion, na.rm = TRUE)) %>%
pull(median_prop)
seu@meta.data %>%
ggplot() +
geom_bar(mapping = aes(x = patient_timepoint,
fill = fusion_detected),
position = 'fill') +
geom_hline(yintercept = median_prop, linetype = "dashed") +
theme_bw() +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5)) +
labs(x = "Sample",
y = "Proportion",
fill = "Fusion detected")

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
seu@meta.data %>%
dplyr::filter(fusion_detected) %>%
ggplot(aes(x = patient_timepoint, fill = PPID)) +
geom_bar() +
theme_bw() +
theme(axis.text.x = element_blank(),
axis.title.x = element_blank(),
axis.ticks.x = element_blank(),
legend.justification = "left") +
labs(x = "Sample", y = "No. cells",
fill = "Patient") +
geom_text(
stat = "count",
aes(label = after_stat(count)),
vjust = -0.3,
size = 3
) -> p1
seu@meta.data %>%
dplyr::filter(fusion_detected) %>%
ggplot() +
geom_bar(mapping = aes(x = patient_timepoint,
fill = predicted_CellType_Broad),
position = 'fill') +
theme_bw() +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5)) +
labs(x = "Sample",
y = "Proportion",
fill = "Bone marrow reference cell type") +
paletteer::scale_fill_paletteer_d("pals::polychrome") -> p2
p1 / p2

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
Fusion-positive cells annotated as non-B-precursor cell types are likely ambient contamination. Library size and fusion UMI comparisons help distinguish true blast cells from ambient fusion signal.
seu$suspected_ambient <- seu$patient_fusion != "not-detected" &
!seu$predicted_CellType_Broad %in% c("Pro-B", "Pre-B", "Early Lymphoid")
VlnPlot(seu, features = "nCount_RNA",
group.by = "suspected_ambient",
pt.size = 0)

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
# Add a flag for suspected ambient fusion-positive cells
b_precursor_types <- c("Pro-B", "Pre-B", "Early Lymphoid")
seu$fusion_classification <- case_when(
seu$patient_fusion == "not-detected" ~ "not-detected",
seu$predicted_CellType_Broad %in% b_precursor_types ~ "fusion-positive blast",
TRUE ~ "fusion-positive non-blast"
)
# UMI comparison
VlnPlot(seu,
features = "nCount_RNA",
group.by = "fusion_classification",
pt.size = 0.1) +
scale_y_log10()

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
# Extract fusion UMI counts per cell
seu$fusion_v1_UMI <- GetAssayData(seu, layer = "counts")["ETV6-RUNX1-v1-fusion", ]
seu$fusion_v2_UMI <- GetAssayData(seu, layer = "counts")["ETV6-RUNX1-v2-fusion", ]
seu$fusion_total_UMI <- seu$fusion_v1_UMI + seu$fusion_v2_UMI
# Compare fusion UMI counts between blast and non-blast fusion-positive cells
VlnPlot(seu %>% subset(patient_fusion != "not-detected"),
features = "fusion_total_UMI",
group.by = "fusion_classification",
pt.size = 0.5) +
scale_y_log10()

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
seu@meta.data %>%
filter(patient_fusion != "not-detected") %>%
group_by(fusion_classification) %>%
summarise(
n = n(),
median_fusion_UMI = median(fusion_total_UMI),
mean_fusion_UMI = mean(fusion_total_UMI),
pct_1UMI = mean(fusion_total_UMI == 1) * 100
)
# A tibble: 2 × 5
fusion_classification n median_fusion_UMI mean_fusion_UMI pct_1UMI
<chr> <int> <dbl> <dbl> <dbl>
1 fusion-positive blast 25963 1 1.40 70.7
2 fusion-positive non-blast 752 1 1.34 77.8
seu@meta.data %>%
filter(patient_fusion != "not-detected") %>%
group_by(predicted_CellType_Broad, fusion_classification) %>%
summarise(
n = n(),
median_fusion_UMI = median(fusion_total_UMI),
pct_1UMI = mean(fusion_total_UMI == 1) * 100
) %>%
arrange(fusion_classification, desc(n))
# A tibble: 23 × 5
# Groups: predicted_CellType_Broad [23]
predicted_CellType_B…¹ fusion_classification n median_fusion_UMI pct_1UMI
<chr> <chr> <int> <dbl> <dbl>
1 Pro-B fusion-positive blast 19791 1 70.9
2 Pre-B fusion-positive blast 5584 1 70.0
3 Early Lymphoid fusion-positive blast 588 1 71.6
4 <NA> fusion-positive non-… 394 1 72.1
5 B fusion-positive non-… 244 1 84.8
6 Cycling Progenitor fusion-positive non-… 18 1 66.7
7 pDC fusion-positive non-… 15 2 46.7
8 Late Erythroid fusion-positive non-… 11 1 90.9
9 Naive T fusion-positive non-… 10 1 100
10 Early Erythroid fusion-positive non-… 9 1 100
# ℹ 13 more rows
# ℹ abbreviated name: ¹predicted_CellType_Broad
VlnPlot(seu[, seu$fusion_detected],
features = "CD19",
group.by = "predicted_CellType_Broad",
split.by = "patient_timepoint") +
theme(legend.position = "bottom")

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
Cell cycle phase is scored before clustering. Each sample is then clustered independently using SCTransform normalisation and Leiden algorithm across a range of resolutions.
s.genes <- cc.genes$s.genes
g2m.genes <- cc.genes$g2m.genes
seu <- CellCycleScoring(seu,
s.features = s.genes,
g2m.features = g2m.genes)
seu@meta.data %>%
ggplot(aes(x = Phase,
fill = fusion_detected)) +
geom_bar(position = position_dodge(width = 0.9)) +
theme_bw() +
labs(x = "Sample",
y = "No. cells",
fill = "Fusion detected") +
geom_text(
stat = "count",
aes(label = after_stat(count)),
vjust = -0.5,
size = 3,
position = position_dodge(width = 0.9))

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
seu@meta.data %>%
filter(!is.na(Phase)) %>%
group_by(Phase) %>%
summarise(
total = n(),
fusion_positive = sum(patient_fusion != "not-detected"),
pct_fusion = round(fusion_positive / total * 100, 1),
.groups = "drop"
) %>%
mutate(
label = paste0(pct_fusion, "%"),
Phase = factor(Phase, levels = c("G1", "S", "G2M"))
) %>%
ggplot(aes(x = Phase, y = pct_fusion, fill = Phase)) +
geom_col(width = 0.5) +
geom_text(aes(label = label), vjust = -0.5, size = 3.5) +
scale_fill_manual(values = c(
"G1" = "#E69F00",
"S" = "#009E73",
"G2M" = "#56B4E9"
)) +
scale_y_continuous(limits = c(0, 45), expand = c(0, 0)) +
labs(x = "Cell cycle phase", y = "% fusion-positive cells") +
theme_classic() +
theme(legend.position = "none")

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
Cluster each sample individually at multiple resolutions, to identify the leukaemic cell population.
out <- here("data", "RDS", "ball_exp2_clustered.seu.rds")
if(!file.exists(out)) {
seu[["RNA"]] <- split(seu[["RNA"]], f = factor(seu$batch))
seu <- SCTransform(seu, verbose = FALSE,
return.only.var.genes = TRUE)#,
#vars.to.regress = c("S.Score", "G2M.Score", "nCount_RNA"))
seu_lst <- SplitObject(seu, split.by = "patient_timepoint")
lapply(seu_lst, function(seu){
# seu <- SCTransform(seu, verbose = FALSE,
# return.only.var.genes = FALSE,
# vars.to.regress = c("S.Score", "G2M.Score", "nCount_RNA"))
DefaultAssay(seu) <- "SCT"
seu <- FindVariableFeatures(seu)
#VariableFeatures(seu) <- setdiff(VariableFeatures(seu), c(s.genes, g2m.genes))
seu <- RunPCA(seu, verbose = FALSE, npcs = 30, assay = "SCT")
seu <- RunUMAP(seu, dims = 1:30, reduction = "pca")
seu <- FindNeighbors(seu, reduction = "pca", dims = 1:30)
seu <- FindClusters(seu, resolution = seq(0.1, 1, by = 0.1),
algorithm = "Leiden")
seu
}) -> seu_lst
saveRDS(seu_lst, file = out)
fs::file_chmod(out, "664")
try(fs::file_chown(out, group_id = "oshlack_lab"),
silent = TRUE)
} else {
seu_lst <- readRDS(out)
}
The lowest resolution (0.3) is probably sufficient for separating likely leukaemic clusters from clusters of other cells.
lapply(seu_lst, function(seu){
clustree(seu, prefix = "SCT_snn_res.")
})
$C659_Diagnosis

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
$C1437_Relapse

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
$C369_Diagnosis

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
$C1437_Diagnosis

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
$C369_Relapse

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
$C658_Diagnosis

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
$C601_Diagnosis

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
$C369_MRD

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
Visualise the clusters for each sample, along with cell cycle, labelled fusions and broad reference annotations.
grp <- "SCT_snn_res.0.3"
lapply(seq_along(seu_lst), function(i){
DimPlot(seu_lst[[i]], reduction = "umap", label = TRUE, repel = TRUE,
label.size = 2.5, group.by = grp) +
theme(legend.text = element_text(size = 8),
legend.position = "bottom") -> p1
DimPlot(seu_lst[[i]], reduction = "umap", label = TRUE, repel = TRUE,
label.size = 2.5, group.by = grp,
cells.highlight = which(seu_lst[[i]]$patient_fusion != "not-detected"),
sizes.highlight = 0.1) +
NoLegend() -> p2
DimPlot(seu_lst[[i]], reduction = "umap", label = TRUE, repel = TRUE,
label.size = 2.5, group.by = "predicted_CellType_Broad") +
NoLegend() -> p3
DimPlot(seu_lst[[i]], reduction = "umap", label = TRUE, repel = TRUE,
label.size = 2.5, group.by = "Phase") +
theme(legend.text = element_text(size = 8),
legend.position = "bottom") -> p4
((p1 | p4) / (p2 | p3)) +
plot_annotation(title = names(seu_lst)[i]) +
theme(title = element_text(size = 10))
}) -> p
p
[[1]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[2]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[3]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[4]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[5]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[6]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[7]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[8]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
Per-sample four-panel UMAPs (clusters, cell cycle, fusion highlight, BoneMarrowMap annotation) for all eight samples. This figure was previously Supplementary Figure 6 but has been retired from the active figure set; it is retained here as a diagnostic overview.
# Exploratory per-sample clustering: clusters, cell cycle, fusion, and BoneMarrowMap annotation for all eight Exp2 samples
grp <- "SCT_snn_res.0.3"
lapply(seq_along(seu_lst), function(i) {
# Cluster UMAP
DimPlot(seu_lst[[i]], reduction = "umap", label = TRUE, repel = TRUE,
label.size = 2.5, group.by = grp) +
theme(legend.text = element_text(size = 8),
legend.position = "bottom") +
NoAxes() -> p1
# Cell cycle phase
DimPlot(seu_lst[[i]], reduction = "umap", label = TRUE, repel = TRUE,
label.size = 2.5, group.by = "Phase") +
scale_color_manual(values = c("G1" = "#E69F00",
"G2M" = "#56B4E9",
"S" = "#009E73")) +
theme(legend.text = element_text(size = 8),
legend.position = "bottom") +
NoAxes() -> p2
# Fusion highlight
DimPlot(seu_lst[[i]], reduction = "umap", label = TRUE, repel = TRUE,
label.size = 2.5, group.by = grp,
cells.highlight = which(seu_lst[[i]]$patient_fusion != "not-detected"),
sizes.highlight = 0.1) +
NoLegend() +
NoAxes() +
ggtitle("Fusion highlight") -> p3
# BoneMarrowMap annotation
DimPlot(seu_lst[[i]], reduction = "umap", label = TRUE, repel = TRUE,
label.size = 2.5, group.by = "predicted_CellType_Broad") +
NoLegend() +
NoAxes() +
ggtitle("BoneMarrowMap annotation") -> p4
((p1 | p2) / (p3 | p4)) +
plot_annotation(title = names(seu_lst)[i],
theme = theme(plot.title = element_text(size = 10,
face = "bold")))
}) -> supp_plots
# Print all panels
supp_plots
[[1]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[2]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[3]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[4]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[5]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[6]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[7]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[8]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
Publication-quality per-sample figure. For each sample (rows): unsupervised cluster labels, majority-vote cell type annotation, ETV6::RUNX1 fusion isoform highlight, and canonical lineage marker dot plot. Generated separately for Capture 1 (C1437_Dx, C1437_Rel, C369_Dx, C659_Dx) and Capture 2 (C369_Rel, C369_MRD, C601_Dx, C658_Dx) to account for the difference in sequencing depth. This corresponds to Figure 4A.
# Figure 4A: Per-sample four-panel figure (Capture 1 and Capture 2 separately)
# ── Shared themes ─────────────────────────────────────────────────────────────
umap_theme_supp <- function() {
theme_classic(base_size = 11) +
theme(
plot.title = element_text(size = 11, face = "bold", color = "grey15",
hjust = 0.5, margin = margin(b = 4)),
axis.title = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
axis.line = element_blank(),
panel.grid = element_blank(),
panel.border = element_blank(),
legend.text = element_text(size = 9, color = "grey20"),
legend.key.size = unit(0.5, "lines"),
legend.title = element_blank(),
plot.margin = margin(8, 2, 8, 2)
)
}
dot_theme_supp <- function() {
theme_classic(base_size = 9) +
theme(
plot.title = element_text(size = 11, face = "bold", color = "grey15",
hjust = 0.5, margin = margin(b = 4)),
axis.text.x = element_text(size = 6, color = "grey20",
angle = 90, hjust = 1, vjust = 0.5),
axis.text.y = element_text(size = 7, color = "grey15"),
axis.title = element_blank(),
panel.grid.major = element_line(color = "grey92", linewidth = 0.3),
legend.text = element_text(size = 7, color = "grey20"),
legend.key.size = unit(0.4, "lines"),
legend.title = element_text(size = 7, color = "grey20"),
plot.margin = margin(8, 2, 8, 2)
)
}
col_title_theme <- theme(
plot.title = element_text(size = 11, face = "bold", color = "grey15",
hjust = 0.5, margin = margin(b = 20))
)
# ── Fusion colours ────────────────────────────────────────────────────────────
fusion_colours <- c(
"ETV6::RUNX1-v1" = "#E69F00",
"ETV6::RUNX1-v2" = "#0072B2"
)
# ── Canonical markers ─────────────────────────────────────────────────────────
canonical_markers <- c("CD19", "CD3E", "CD14", "HBB", "CD34", "CXCL12")
# ── Sample orders per capture ─────────────────────────────────────────────────
capture1_samples <- c("C1437_Diagnosis", "C1437_Relapse", "C369_Diagnosis", "C659_Diagnosis")
capture2_samples <- c("C369_Relapse", "C369_MRD", "C601_Diagnosis", "C658_Diagnosis")
# ── Core function to build figure for one capture ─────────────────────────────
make_supp_figure <- function(seu_lst_subset) {
# Global max expression for consistent dot plot scale across capture
global_max_expr <- max(sapply(seu_lst_subset, function(s) {
avail <- canonical_markers[canonical_markers %in% rownames(s)]
norm <- GetAssayData(s, layer = "data")[avail, ]
max(as.matrix(norm), na.rm = TRUE)
}))
all_rows <- lapply(seq_along(seu_lst_subset), function(i) {
s <- seu_lst_subset[[i]]
s_name <- names(seu_lst_subset)[i]
is_last <- i == length(seu_lst_subset)
# ── Majority vote annotation ──────────────────────────────────────────────
cluster_annotation <- s@meta.data %>%
tibble::rownames_to_column("cell") %>%
mutate(
cluster = as.character(.data[["SCT_snn_res.0.3"]]),
cell_type = as.character(predicted_CellType_Broad)
) %>%
group_by(cluster, cell_type) %>%
summarise(n = n(), .groups = "drop") %>%
group_by(cluster) %>%
slice_max(n, n = 1, with_ties = FALSE) %>%
ungroup() %>%
select(cluster, majority_type = cell_type)
s$majority_type <- cluster_annotation$majority_type[
match(as.character(s$SCT_snn_res.0.3),
cluster_annotation$cluster)
]
# ── UMAP coordinate range ─────────────────────────────────────────────────
umap_emb <- Embeddings(s, reduction = "umap")
xlim_vals <- range(umap_emb[, 1]) + c(-1, 1)
ylim_vals <- range(umap_emb[, 2]) + c(-1, 1)
ar <- diff(ylim_vals) / diff(xlim_vals)
umap_df <- as.data.frame(umap_emb)
umap_col1 <- colnames(umap_df)[1]
umap_col2 <- colnames(umap_df)[2]
# ── Median UMAP per majority type ─────────────────────────────────────────
label_df <- umap_df %>%
rownames_to_column("cell") %>%
mutate(label = s$majority_type[cell]) %>%
filter(!is.na(label)) %>%
group_by(label) %>%
summarise(
x = median(.data[[umap_col1]]),
y = median(.data[[umap_col2]]),
.groups = "drop"
)
# ── Panel 1: Unsupervised clusters ────────────────────────────────────────
p1 <- DimPlot(
s, reduction = "umap",
group.by = "SCT_snn_res.0.3",
label = TRUE, repel = TRUE,
label.size = 2.5, pt.size = 0.4
) +
labs(title = if (i == 1) "Unsupervised clusters" else NULL) +
umap_theme_supp() +
{ if (i == 1) col_title_theme else theme() } +
coord_cartesian(xlim = xlim_vals, ylim = ylim_vals, clip = "off") +
theme(legend.position = "none", aspect.ratio = ar)
# ── Panel 2: Majority vote annotation ─────────────────────────────────────
p2 <- DimPlot(
s, reduction = "umap",
group.by = "majority_type",
label = FALSE,
pt.size = 0.4
) +
geom_text_repel(
data = label_df,
aes(x = x, y = y, label = label),
size = 2.5,
color = "grey15",
fontface = "plain",
box.padding = 0.3,
point.padding = 0.1,
segment.size = 0.3,
segment.color = "grey50",
max.overlaps = 20,
inherit.aes = FALSE
) +
labs(title = if (i == 1) "Cluster annotation\n(majority vote)" else NULL) +
umap_theme_supp() +
{ if (i == 1) col_title_theme else theme() } +
coord_cartesian(xlim = xlim_vals, ylim = ylim_vals, clip = "off") +
theme(legend.position = "none", aspect.ratio = ar)
# ── Panel 3: Fusion highlight (manual ggplot) ─────────────────────────────
umap_coords <- as.data.frame(Embeddings(s, reduction = "umap"))
colnames(umap_coords) <- c("UMAP_1", "UMAP_2")
umap_coords$cell <- rownames(umap_coords)
umap_coords$fusion_label <- dplyr::case_when(
s$patient_fusion == "ETV6-RUNX1-v1-fusion" ~ "ETV6::RUNX1-v1",
s$patient_fusion == "ETV6-RUNX1-v2-fusion" ~ "ETV6::RUNX1-v2",
TRUE ~ "Unselected"
)
# Plot unselected first, fusion-positive on top
# Fix 1: correct sort order - unselected plotted first (underneath)
umap_coords <- umap_coords %>%
arrange(desc(fusion_label == "Unselected"))
# Fix 2: convert to factor with all levels to force legend entries
umap_coords$fusion_label <- factor(
umap_coords$fusion_label,
levels = c("ETV6::RUNX1-v1", "ETV6::RUNX1-v2", "Unselected")
)
p3 <- ggplot(umap_coords, aes(x = UMAP_1, y = UMAP_2, colour = fusion_label)) +
geom_point(size = 0.4, alpha = 0.8) +
# Invisible points just to force legend entries
geom_point(
data = data.frame(
UMAP_1 = rep(NA_real_, 3),
UMAP_2 = rep(NA_real_, 3),
fusion_label = factor(
c("ETV6::RUNX1-v1", "ETV6::RUNX1-v2", "Unselected"),
levels = c("ETV6::RUNX1-v1", "ETV6::RUNX1-v2", "Unselected")
)
),
aes(colour = fusion_label),
size = 3
) +
scale_colour_manual(
values = c(
"Unselected" = "grey88",
"ETV6::RUNX1-v1" = "#E69F00",
"ETV6::RUNX1-v2" = "#0072B2"
),
breaks = c("ETV6::RUNX1-v1", "ETV6::RUNX1-v2", "Unselected"),
drop = FALSE
) +
labs(title = if (i == 1) "Fusion expression" else NULL,
colour = NULL) +
umap_theme_supp() +
{ if (i == 1) col_title_theme else theme() } +
coord_cartesian(xlim = xlim_vals, ylim = ylim_vals, clip = "off") +
theme(
aspect.ratio = ar,
legend.position = if (is_last) "bottom" else "none"
)
# ── Panel 4: Dot plot ──────────────────────────────────────────────────────
meta <- s@meta.data %>%
tibble::rownames_to_column("cell") %>%
mutate(majority_type = s$majority_type[cell])
avail_markers <- canonical_markers[canonical_markers %in% rownames(s)]
marker_counts <- GetAssayData(s, layer = "counts")[avail_markers, ]
marker_norm <- GetAssayData(s, layer = "data")[avail_markers, ]
dot_df <- lapply(avail_markers, function(gn) {
counts_vec <- as.numeric(marker_counts[gn, meta$cell])
norm_vec <- as.numeric(marker_norm[gn, meta$cell])
meta %>%
mutate(expressed = counts_vec > 0, norm_expr = norm_vec) %>%
group_by(majority_type) %>%
summarise(
pct_expressing = mean(expressed) * 100,
mean_expr = ifelse(any(expressed),
mean(norm_expr[expressed]), NA_real_),
.groups = "drop"
) %>%
mutate(marker = gn)
}) %>%
bind_rows() %>%
mutate(
marker = factor(marker, levels = rev(avail_markers)),
majority_type = factor(majority_type)
)
p4 <- ggplot(
dot_df %>% filter(!is.na(pct_expressing) & pct_expressing > 0),
aes(x = majority_type, y = marker,
size = pct_expressing, color = mean_expr)
) +
geom_point(alpha = 0.9) +
scale_color_gradient(
low = "#E8D5F0",
high = "#4A0080",
name = "Mean\nexpr.",
limits = c(0, global_max_expr),
na.value = "grey80",
guide = guide_colourbar(direction = "horizontal",
title.position = "left",
barwidth = 4,
barheight = 0.5)
) +
scale_size_continuous(
name = "% expr.",
range = c(0.5, 6),
breaks = c(1, 25, 50, 75),
limits = c(0, 100),
guide = guide_legend(direction = "horizontal",
title.position = "left",
nrow = 1)
) +
scale_y_discrete(drop = TRUE) +
labs(title = if (i == 1) "Marker expression\nper cell type" else NULL) +
dot_theme_supp() +
{ if (i == 1) col_title_theme else theme() } +
theme(
axis.text.x = element_text(size = 6, angle = 90,
hjust = 1, vjust = 0.5),
legend.position = "bottom",
legend.box = "horizontal",
legend.direction = "horizontal"
)
# ── Vertical sample label ──────────────────────────────────────────────────
label_panel <- ggplot() +
annotate(
"text",
x = 0.5, y = 0.5,
label = s_name,
angle = 90,
size = 4,
fontface = "bold",
color = "grey15"
) +
theme_void() +
theme(plot.margin = margin(0, 6, 0, 6),
legend.position = "none")
# ── Assemble row ───────────────────────────────────────────────────────────
(label_panel | p1 | p2 | p3 | p4) +
plot_layout(widths = c(0.06, 1, 1, 1, 0.5))
})
# ── Stack rows ────────────────────────────────────────────────────────────────
n_samples <- length(seu_lst_subset)
wrap_plots(all_rows, ncol = 1) /
guide_area() +
plot_layout(
heights = c(rep(1, n_samples), 0.4),
guides = "collect"
)
}
# ── Generate figures ──────────────────────────────────────────────────────────
supp_capture1 <- make_supp_figure(seu_lst[capture1_samples])
supp_capture2 <- make_supp_figure(seu_lst[capture2_samples])
supp_capture1

supp_capture2

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
Expression of B-ALL marker DNTT is highly correlated with detected fusions.
lapply(seq_along(seu_lst), function(i){
FeaturePlot(seu_lst[[i]], features = "DNTT") -> p1
DimPlot(seu_lst[[i]], reduction = "umap", label = TRUE, repel = TRUE,
label.size = 2.5, group.by = "SCT_snn_res.0.1",
cells.highlight = which(seu_lst[[i]]$patient_fusion != "not-detected"),
sizes.highlight = 0.1) +
NoLegend() -> p2
(p1 / p2) +
plot_annotation(title = names(seu_lst)[i]) +
theme(title = element_text(size = 10))
})
[[1]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[2]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[3]]

[[4]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[5]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[6]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[7]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
[[8]]

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
Patient C1437 has samples from both diagnosis and relapse. Here the two timepoints are jointly clustered to identify diagnosis-specific and relapse-specific blast clones.
out <- here("data", "RDS", "ball_exp2_clustered_c1437.seu.rds")
if(!file.exists(out)) {
seu_c1437 <- subset(seu, patient_timepoint %in% c("C1437_Diagnosis", "C1437_Relapse"))
seu_c1437 <- SCTransform(seu_c1437, verbose = FALSE,
return.only.var.genes = TRUE)
seu_c1437 <- RunPCA(seu_c1437, verbose = FALSE, npcs = 30, assay = "SCT")
seu_c1437 <- RunUMAP(seu_c1437, dims = 1:30, reduction = "pca")
seu_c1437 <- FindNeighbors(seu_c1437, reduction = "pca", dims = 1:30)
seu_c1437 <- FindClusters(seu_c1437, resolution = seq(0.1, 1, by = 0.1),
algorithm = "Leiden")
saveRDS(seu_c1437, file = out)
fs::file_chmod(out, "664")
try(fs::file_chown(out, group_id = "oshlack_lab"), silent = TRUE)
} else {
seu_c1437 <- readRDS(out)
}
The lowest resolution (0.1) is probably sufficient for separating likely leukaemic clusters from clusters of other cells.
clustree(seu_c1437, prefix = "SCT_snn_res.")

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
p1 <- DimPlot(seu_c1437, group.by = "SCT_snn_res.0.3",
label = TRUE, repel = TRUE,
label.size = 3) +
ggtitle("Clusters (res 0.3)") +
NoLegend()
p2 <- DimPlot(seu_c1437, group.by = "patient_timepoint",
cols = c("C1437_Diagnosis" = "#56B4E9",
"C1437_Relapse" = "#E69F00")) +
ggtitle("Timepoint")
p3 <- DimPlot(seu_c1437, group.by = "predicted_CellType_Broad",
label = TRUE, repel = TRUE,
label.size = 3) +
ggtitle("BoneMarrowMap annotation") +
NoLegend()
p4 <- DimPlot(seu_c1437, group.by = "Phase",
cols = c("G1" = "#E69F00",
"G2M" = "#56B4E9",
"S" = "#009E73")) +
ggtitle("Cell cycle phase")
(p1 | p2) / (p3 | p4)

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
Clusters are annotated as “Diagnosis clone”, “Relapse clone”, or
“Normal BM” based on majority-vote cell type and the proportion of cells
from each timepoint. This is an exploratory overview; the canonical
publication C1437 figures (4F–4H) are assembled in
B-ALL_exp2_c1437_clone_analysis.Rmd.
# Exploratory C1437 clone annotation — timepoint, clone identity, and fusion detection overview
# Step 1: majority vote cell type per cluster
blast_types <- c("Pro-B", "Pre-B", "Early Lymphoid")
cluster_meta <- seu_c1437@meta.data %>%
group_by(SCT_snn_res.0.3) %>%
summarise(
majority_type = names(which.max(table(predicted_CellType_Broad))),
pct_diagnosis = mean(patient_timepoint == "C1437_Diagnosis"),
pct_relapse = mean(patient_timepoint == "C1437_Relapse"),
is_blast = majority_type %in% blast_types,
.groups = "drop"
) %>%
mutate(
clone = dplyr::case_when(
is_blast & pct_diagnosis >= 0.9 ~ "Diagnosis clone",
is_blast & pct_relapse >= 0.9 ~ "Relapse clone",
!is_blast ~ "Normal BM",
TRUE ~ "Mixed blast" # safety catch
)
)
# Step 2: map back to cells
seu_c1437$clone <- cluster_meta$clone[
match(seu_c1437$SCT_snn_res.0.3, cluster_meta$SCT_snn_res.0.3)
]
table(seu_c1437$clone)
Diagnosis clone Normal BM Relapse clone
9159 1482 13374
clone_colours <- c(
"Diagnosis clone" = "#0072B2",
"Relapse clone" = "#D55E00",
"Normal BM" = "#999999"
)
umap_arrow <- annotation_custom(
grob = grid::grobTree(
grid::segmentsGrob(
x0 = 0.05, y0 = 0.05, x1 = 0.12, y1 = 0.05,
arrow = grid::arrow(length = grid::unit(0.1, "cm"), type = "closed"),
gp = grid::gpar(fill = "grey30", col = "grey30", lwd = 2)
),
grid::segmentsGrob(
x0 = 0.05, y0 = 0.05, x1 = 0.05, y1 = 0.12,
arrow = grid::arrow(length = grid::unit(0.1, "cm"), type = "closed"),
gp = grid::gpar(fill = "grey30", col = "grey30", lwd = 2)
),
grid::textGrob(
"UMAP", x = 0.085, y = 0.01,
gp = grid::gpar(fontsize = 6, col = "grey30")
)
)
)
# Fusion highlight data
umap_coords_c1437 <- as.data.frame(Embeddings(seu_c1437, reduction = "umap"))
colnames(umap_coords_c1437) <- c("UMAP_1", "UMAP_2")
umap_coords_c1437$fusion_label <- dplyr::case_when(
seu_c1437$patient_fusion == "ETV6-RUNX1-v1-fusion" ~ "ETV6::RUNX1-v1",
TRUE ~ "Unselected"
) %>% factor(levels = c("ETV6::RUNX1-v1", "Unselected"))
# Plot unselected first
umap_coords_c1437 <- umap_coords_c1437 %>%
arrange(desc(fusion_label == "Unselected"))
seu_c1437$clone <- factor(seu_c1437$clone,
levels = c("Diagnosis clone",
"Relapse clone",
"Normal BM"))
p1 <- DimPlot(seu_c1437, group.by = "patient_timepoint",
cols = c("C1437_Diagnosis" = "#56B4E9",
"C1437_Relapse" = "#E69F00"),
pt.size = 0.3) +
ggtitle("Timepoint") +
theme_void() +
theme(legend.position = "bottom") +
umap_arrow
p2 <- DimPlot(seu_c1437, group.by = "clone",
cols = clone_colours,
pt.size = 0.3) +
ggtitle("Clone") +
theme_void() +
theme(legend.position = "bottom") +
scale_color_manual(values = clone_colours, drop = FALSE)
p3 <- ggplot(umap_coords_c1437,
aes(x = UMAP_1, y = UMAP_2, colour = fusion_label)) +
geom_point(size = 0.3, alpha = 0.8) +
scale_colour_manual(
values = c(
"ETV6::RUNX1-v1" = "#009E73",
"Unselected" = "grey88"
),
drop = FALSE,
guide = guide_legend(override.aes = list(size = 3))
) +
ggtitle("Fusion detection") +
labs(colour = NULL) +
theme_void() +
theme(legend.position = "bottom")
# Cleaner x labels and add percentage labels
seu_c1437@meta.data %>%
group_by(patient_timepoint) %>%
summarise(
pct_fusion = mean(patient_fusion == "ETV6-RUNX1-v1-fusion") * 100,
.groups = "drop"
) %>%
mutate(label = paste0(round(pct_fusion, 1), "%"),
patient_timepoint = gsub("C1437_", "", patient_timepoint)) %>%
ggplot(aes(x = patient_timepoint, y = pct_fusion,
fill = patient_timepoint)) +
geom_col(width = 0.5) +
geom_text(aes(label = label), vjust = -0.5, size = 2.5) +
scale_fill_manual(values = c("Diagnosis" = "#0072B2",
"Relapse" = "#D55E00")) +
labs(x = NULL, y = "% fusion-positive cells") +
theme_classic() +
theme(legend.position = "none") -> p4
layout <- "
AAABBBCCC
AAABBBCCC
AAABBBCCC
##DDDDD##
##DDDDD##
"
(p1 + p2 + p3 + p4) +
plot_layout(design = layout)

| Version | Author | Date |
|---|---|---|
| 1b5bb97 | Jovana Maksimovic | 2026-05-11 |
# C1437 ETV6::RUNX1-v1 % fusion-positive cells at Diagnosis and Relapse
seu_c1437@meta.data %>%
group_by(patient_timepoint) %>%
summarise(
total = n(),
fusion_positive = sum(patient_fusion == "ETV6-RUNX1-v1-fusion"),
pct_fusion = round(fusion_positive / total * 100, 1)
)
# A tibble: 2 × 4
patient_timepoint total fusion_positive pct_fusion
<fct> <int> <int> <dbl>
1 C1437_Diagnosis 10143 2182 21.5
2 C1437_Relapse 13872 4858 35
seu_c1437@meta.data %>%
group_by(patient_timepoint) %>%
summarise(
pct_fusion = mean(patient_fusion == "ETV6-RUNX1-v1-fusion") * 100,
.groups = "drop"
) %>%
ggplot(aes(x = patient_timepoint, y = pct_fusion,
fill = patient_timepoint)) +
geom_col(width = 0.6) +
scale_fill_manual(values = c("C1437_Diagnosis" = "#56B4E9",
"C1437_Relapse" = "#E69F00")) +
labs(x = NULL, y = "% fusion-positive cells") +
theme_classic() +
theme(legend.position = "none")

| Version | Author | Date |
|---|---|---|
| abab370 | Jovana Maksimovic | 2026-05-19 |
sessioninfo::session_info()
─ Session info ───────────────────────────────────────────────────────────────
setting value
version R version 4.4.1 (2024-06-14)
os macOS 15.5
system aarch64, darwin20
ui X11
language (EN)
collate en_US.UTF-8
ctype en_US.UTF-8
tz Australia/Melbourne
date 2026-07-16
pandoc 3.8.3 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/aarch64/ (via rmarkdown)
quarto 1.9.38 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/quarto
─ Packages ───────────────────────────────────────────────────────────────────
! package * version date (UTC) lib source
P abind 1.4-8 2024-09-12 [?] CRAN (R 4.4.1)
P backports 1.5.0 2024-05-23 [?] CRAN (R 4.4.1)
P beeswarm 0.4.0 2021-06-01 [?] CRAN (R 4.4.1)
P Biobase 2.66.0 2024-11-08 [?] Bioconduc~
P BiocGenerics 0.52.0 2024-11-08 [?] Bioconduc~
P BiocManager 1.30.27 2025-11-14 [?] CRAN (R 4.4.3)
P bslib 0.9.0 2025-01-30 [?] CRAN (R 4.4.1)
P cachem 1.1.0 2024-05-16 [?] CRAN (R 4.4.1)
P callr 3.7.6 2024-03-25 [?] CRAN (R 4.4.0)
P checkmate 2.3.2 2024-07-29 [?] CRAN (R 4.4.0)
P cli 3.6.5 2025-04-23 [?] CRAN (R 4.4.1)
P cluster 2.1.6 2023-12-01 [?] CRAN (R 4.4.1)
P clustree * 0.5.1 2023-11-05 [?] CRAN (R 4.4.0)
P codetools 0.2-20 2024-03-31 [?] CRAN (R 4.4.1)
P colorspace 2.1-1 2024-07-26 [?] CRAN (R 4.4.1)
P cowplot 1.1.3 2024-01-22 [?] CRAN (R 4.4.0)
P crayon 1.5.3 2024-06-20 [?] CRAN (R 4.4.1)
P data.table 1.18.2.1 2026-01-27 [?] CRAN (R 4.4.3)
P DelayedArray 0.32.0 2024-11-08 [?] Bioconduc~
P deldir 2.0-4 2024-02-28 [?] CRAN (R 4.4.1)
P digest 0.6.37 2024-08-19 [?] CRAN (R 4.4.1)
P dotCall64 1.2 2024-10-04 [?] CRAN (R 4.4.1)
P dplyr * 1.1.4 2023-11-17 [?] CRAN (R 4.4.0)
P evaluate 1.0.3 2025-01-10 [?] CRAN (R 4.4.1)
P farver 2.1.2 2024-05-13 [?] CRAN (R 4.4.1)
P fastDummies 1.7.5 2025-01-20 [?] CRAN (R 4.4.1)
P fastmap 1.2.0 2024-05-15 [?] CRAN (R 4.4.1)
P fitdistrplus 1.2-2 2025-01-07 [?] CRAN (R 4.4.1)
P forcats * 1.0.0 2023-01-29 [?] CRAN (R 4.4.0)
P fs 1.6.6 2025-04-12 [?] CRAN (R 4.4.1)
P future 1.49.0 2025-05-09 [?] CRAN (R 4.4.1)
P future.apply 1.11.3 2024-10-27 [?] CRAN (R 4.4.1)
P generics 0.1.4 2025-05-09 [?] CRAN (R 4.4.1)
P GenomeInfoDb 1.42.3 2025-01-27 [?] Bioconduc~
P GenomeInfoDbData 1.2.13 2025-05-28 [?] Bioconductor
P GenomicRanges 1.58.0 2024-11-08 [?] Bioconduc~
P getPass 0.2-4 2023-12-10 [?] CRAN (R 4.4.1)
P ggbeeswarm 0.7.2 2023-04-29 [?] CRAN (R 4.4.0)
P ggforce 0.4.2 2024-02-19 [?] CRAN (R 4.4.0)
P ggplot2 * 4.0.2 2026-02-03 [?] CRAN (R 4.4.3)
P ggraph * 2.2.1 2024-03-07 [?] CRAN (R 4.4.0)
P ggrastr 1.0.2 2023-06-01 [?] CRAN (R 4.4.0)
P ggrepel * 0.9.6 2024-09-07 [?] CRAN (R 4.4.1)
P ggridges 0.5.6 2024-01-23 [?] CRAN (R 4.4.0)
P git2r 0.36.2 2025-03-29 [?] CRAN (R 4.4.1)
P glmGamPoi * 1.18.0 2024-11-08 [?] Bioconduc~
P globals 0.18.0 2025-05-08 [?] CRAN (R 4.4.1)
P glue * 1.8.0 2024-09-30 [?] CRAN (R 4.4.1)
P goftest 1.2-3 2021-10-07 [?] CRAN (R 4.4.1)
P graphlayouts 1.2.2 2025-01-23 [?] CRAN (R 4.4.1)
P gridExtra 2.3 2017-09-09 [?] CRAN (R 4.4.1)
P gtable 0.3.6 2024-10-25 [?] CRAN (R 4.4.1)
P here * 1.0.1 2020-12-13 [?] CRAN (R 4.4.1)
P hms 1.1.3 2023-03-21 [?] CRAN (R 4.4.0)
P htmltools 0.5.8.1 2024-04-04 [?] CRAN (R 4.4.1)
P htmlwidgets 1.6.4 2023-12-06 [?] CRAN (R 4.4.0)
P httpuv 1.6.16 2025-04-16 [?] CRAN (R 4.4.1)
P httr 1.4.7 2023-08-15 [?] CRAN (R 4.4.0)
P ica 1.0-3 2022-07-08 [?] CRAN (R 4.4.1)
P igraph 2.1.4 2025-01-23 [?] CRAN (R 4.4.1)
P IRanges 2.40.1 2024-12-05 [?] Bioconduc~
P irlba 2.3.5.1 2022-10-03 [?] CRAN (R 4.4.0)
P jquerylib 0.1.4 2021-04-26 [?] CRAN (R 4.4.0)
P jsonlite 2.0.0 2025-03-27 [?] CRAN (R 4.4.1)
P KernSmooth 2.23-24 2024-05-17 [?] CRAN (R 4.4.1)
P knitr 1.50 2025-03-16 [?] CRAN (R 4.4.1)
P labeling 0.4.3 2023-08-29 [?] CRAN (R 4.4.1)
P later 1.4.2 2025-04-08 [?] CRAN (R 4.4.1)
P lattice 0.22-6 2024-03-20 [?] CRAN (R 4.4.1)
P lazyeval 0.2.2 2019-03-15 [?] CRAN (R 4.4.1)
P lifecycle 1.0.4 2023-11-07 [?] CRAN (R 4.4.1)
P listenv 0.9.1 2024-01-29 [?] CRAN (R 4.4.1)
P lmtest 0.9-40 2022-03-21 [?] CRAN (R 4.4.1)
P lubridate * 1.9.4 2024-12-08 [?] CRAN (R 4.4.1)
P magrittr 2.0.3 2022-03-30 [?] CRAN (R 4.4.1)
P MASS 7.3-60.2 2024-04-26 [?] CRAN (R 4.4.1)
P Matrix 1.7-0 2024-04-26 [?] CRAN (R 4.4.1)
P MatrixGenerics 1.18.1 2025-01-09 [?] Bioconduc~
P matrixStats 1.5.0 2025-01-07 [?] CRAN (R 4.4.1)
P memoise 2.0.1 2021-11-26 [?] CRAN (R 4.4.0)
P mime 0.13 2025-03-17 [?] CRAN (R 4.4.1)
P miniUI 0.1.2 2025-04-17 [?] CRAN (R 4.4.1)
P nlme 3.1-164 2023-11-27 [?] CRAN (R 4.4.1)
P paletteer 1.6.0 2024-01-21 [?] CRAN (R 4.4.0)
P parallelly 1.45.0 2025-06-02 [?] CRAN (R 4.4.1)
P patchwork * 1.3.0 2024-09-16 [?] CRAN (R 4.4.1)
P pbapply 1.7-4 2025-07-20 [?] CRAN (R 4.4.1)
P pillar 1.10.2 2025-04-05 [?] CRAN (R 4.4.1)
P pkgconfig 2.0.3 2019-09-22 [?] CRAN (R 4.4.1)
P plotly 4.10.4 2024-01-13 [?] CRAN (R 4.4.0)
P plyr 1.8.9 2023-10-02 [?] CRAN (R 4.4.1)
P png 0.1-8 2022-11-29 [?] CRAN (R 4.4.1)
P polyclip 1.10-7 2024-07-23 [?] CRAN (R 4.4.1)
P prismatic 1.1.2 2024-04-10 [?] CRAN (R 4.4.1)
P processx 3.8.6 2025-02-21 [?] CRAN (R 4.4.1)
P progressr 0.15.1 2024-11-22 [?] CRAN (R 4.4.1)
P promises 1.3.3 2025-05-29 [?] CRAN (R 4.4.1)
P ps 1.9.1 2025-04-12 [?] CRAN (R 4.4.1)
P purrr * 1.0.4 2025-02-05 [?] CRAN (R 4.4.1)
P R6 2.6.1 2025-02-15 [?] CRAN (R 4.4.1)
P RANN 2.6.2 2024-08-25 [?] CRAN (R 4.4.1)
P RColorBrewer 1.1-3 2022-04-03 [?] CRAN (R 4.4.1)
P Rcpp 1.1.1-1.1 2026-04-24 [?] CRAN (R 4.4.1)
P RcppAnnoy 0.0.22 2024-01-23 [?] CRAN (R 4.4.1)
P RcppHNSW 0.6.0 2024-02-04 [?] CRAN (R 4.4.1)
P readr * 2.1.5 2024-01-10 [?] CRAN (R 4.4.0)
P rematch2 2.1.2 2020-05-01 [?] CRAN (R 4.4.0)
renv 1.1.4 2025-03-20 [1] CRAN (R 4.4.1)
P reshape2 1.4.4 2020-04-09 [?] CRAN (R 4.4.0)
P reticulate 1.42.0 2025-03-25 [?] CRAN (R 4.4.1)
P rlang 1.1.6 2025-04-11 [?] CRAN (R 4.4.1)
P rmarkdown 2.29 2024-11-04 [?] CRAN (R 4.4.1)
P ROCR 1.0-11 2020-05-02 [?] CRAN (R 4.4.0)
P rprojroot 2.0.4 2023-11-05 [?] CRAN (R 4.4.1)
P RSpectra 0.16-2 2024-07-18 [?] CRAN (R 4.4.0)
P rstudioapi 0.17.1 2024-10-22 [?] CRAN (R 4.4.1)
P Rtsne 0.17 2023-12-07 [?] CRAN (R 4.4.1)
P S4Arrays 1.6.0 2024-11-08 [?] Bioconduc~
P S4Vectors 0.44.0 2024-11-08 [?] Bioconduc~
P S7 0.2.0 2024-11-07 [?] CRAN (R 4.4.1)
P sass 0.4.10 2025-04-11 [?] CRAN (R 4.4.1)
P scales * 1.4.0 2025-04-24 [?] CRAN (R 4.4.1)
P scattermore 1.2 2023-06-12 [?] CRAN (R 4.4.0)
P sctransform 0.4.2 2025-04-30 [?] CRAN (R 4.4.1)
P sessioninfo 1.2.3 2025-02-05 [?] CRAN (R 4.4.1)
P Seurat * 5.3.0 2025-04-23 [?] CRAN (R 4.4.1)
P SeuratObject * 5.1.0 2025-04-22 [?] CRAN (R 4.4.1)
P shiny 1.10.0 2024-12-14 [?] CRAN (R 4.4.1)
P sp * 2.2-0 2025-02-01 [?] CRAN (R 4.4.1)
P spam 2.11-1 2025-01-20 [?] CRAN (R 4.4.1)
P SparseArray 1.6.2 2025-02-20 [?] Bioconduc~
P spatstat.data 3.1-6 2025-03-17 [?] CRAN (R 4.4.1)
P spatstat.explore 3.4-3 2025-05-21 [?] CRAN (R 4.4.1)
P spatstat.geom 3.4-1 2025-05-20 [?] CRAN (R 4.4.1)
P spatstat.random 3.4-1 2025-05-20 [?] CRAN (R 4.4.1)
P spatstat.sparse 3.1-0 2024-06-21 [?] CRAN (R 4.4.0)
P spatstat.univar 3.1-3 2025-05-08 [?] CRAN (R 4.4.1)
P spatstat.utils 3.1-4 2025-05-15 [?] CRAN (R 4.4.1)
P stringi 1.8.7 2025-03-27 [?] CRAN (R 4.4.1)
P stringr * 1.6.0 2025-11-04 [?] CRAN (R 4.4.1)
P SummarizedExperiment 1.36.0 2024-11-08 [?] Bioconduc~
P survival 3.6-4 2024-04-24 [?] CRAN (R 4.4.1)
P tensor 1.5 2012-05-05 [?] CRAN (R 4.4.1)
P tibble * 3.2.1 2023-03-20 [?] CRAN (R 4.4.0)
P tidygraph 1.3.1 2024-01-30 [?] CRAN (R 4.4.0)
P tidyr * 1.3.1 2024-01-24 [?] CRAN (R 4.4.1)
P tidyselect 1.2.1 2024-03-11 [?] CRAN (R 4.4.0)
P tidyverse * 2.0.0 2023-02-22 [?] CRAN (R 4.4.0)
P timechange 0.3.0 2024-01-18 [?] CRAN (R 4.4.1)
P tweenr 2.0.3 2024-02-26 [?] CRAN (R 4.4.0)
P tzdb 0.5.0 2025-03-15 [?] CRAN (R 4.4.1)
P UCSC.utils 1.2.0 2024-11-08 [?] Bioconduc~
P utf8 1.2.5 2025-05-01 [?] CRAN (R 4.4.1)
P uwot 0.2.3 2025-02-24 [?] CRAN (R 4.4.1)
P vctrs 0.6.5 2023-12-01 [?] CRAN (R 4.4.0)
P vipor 0.4.7 2023-12-18 [?] CRAN (R 4.4.1)
P viridis 0.6.5 2024-01-29 [?] CRAN (R 4.4.0)
P viridisLite 0.4.2 2023-05-02 [?] CRAN (R 4.4.1)
P whisker 0.4.1 2022-12-05 [?] CRAN (R 4.4.1)
P withr 3.0.2 2024-10-28 [?] CRAN (R 4.4.1)
P workflowr * 1.7.1 2023-08-23 [?] CRAN (R 4.4.0)
P xfun 0.56 2026-01-18 [?] CRAN (R 4.4.3)
P xtable 1.8-4 2019-04-21 [?] CRAN (R 4.4.1)
P XVector 0.46.0 2024-11-08 [?] Bioconduc~
P yaml 2.3.10 2024-07-26 [?] CRAN (R 4.4.1)
P zlibbioc 1.52.0 2024-11-08 [?] Bioconduc~
P zoo 1.8-14 2025-04-10 [?] CRAN (R 4.4.1)
[1] /Users/maksimovicjovana/projects/active/flex-fusion-probes/renv/library/macos/R-4.4/aarch64-apple-darwin20
[2] /Users/maksimovicjovana/Library/Caches/org.R-project.R/R/renv/sandbox/macos/R-4.4/aarch64-apple-darwin20/f7156815
* ── Packages attached to the search path.
P ── Loaded and on-disk path mismatch.
──────────────────────────────────────────────────────────────────────────────
sessionInfo()
R version 4.4.1 (2024-06-14)
Platform: aarch64-apple-darwin20
Running under: macOS 15.5
Matrix products: default
BLAS: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.0
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
time zone: Australia/Melbourne
tzcode source: internal
attached base packages:
[1] stats graphics grDevices datasets utils methods base
other attached packages:
[1] ggrepel_0.9.6 glmGamPoi_1.18.0 clustree_0.5.1 ggraph_2.2.1
[5] patchwork_1.3.0 scales_1.4.0 Seurat_5.3.0 SeuratObject_5.1.0
[9] sp_2.2-0 glue_1.8.0 here_1.0.1 lubridate_1.9.4
[13] forcats_1.0.0 stringr_1.6.0 dplyr_1.1.4 purrr_1.0.4
[17] readr_2.1.5 tidyr_1.3.1 tibble_3.2.1 ggplot2_4.0.2
[21] tidyverse_2.0.0 workflowr_1.7.1
loaded via a namespace (and not attached):
[1] RcppAnnoy_0.0.22 splines_4.4.1
[3] later_1.4.2 prismatic_1.1.2
[5] polyclip_1.10-7 fastDummies_1.7.5
[7] lifecycle_1.0.4 rprojroot_2.0.4
[9] globals_0.18.0 processx_3.8.6
[11] lattice_0.22-6 MASS_7.3-60.2
[13] backports_1.5.0 magrittr_2.0.3
[15] plotly_4.10.4 sass_0.4.10
[17] rmarkdown_2.29 jquerylib_0.1.4
[19] yaml_2.3.10 httpuv_1.6.16
[21] sctransform_0.4.2 spam_2.11-1
[23] sessioninfo_1.2.3 spatstat.sparse_3.1-0
[25] reticulate_1.42.0 cowplot_1.1.3
[27] pbapply_1.7-4 RColorBrewer_1.1-3
[29] abind_1.4-8 zlibbioc_1.52.0
[31] Rtsne_0.17 GenomicRanges_1.58.0
[33] BiocGenerics_0.52.0 tweenr_2.0.3
[35] git2r_0.36.2 GenomeInfoDbData_1.2.13
[37] IRanges_2.40.1 S4Vectors_0.44.0
[39] irlba_2.3.5.1 listenv_0.9.1
[41] spatstat.utils_3.1-4 goftest_1.2-3
[43] RSpectra_0.16-2 spatstat.random_3.4-1
[45] fitdistrplus_1.2-2 parallelly_1.45.0
[47] codetools_0.2-20 DelayedArray_0.32.0
[49] ggforce_0.4.2 tidyselect_1.2.1
[51] UCSC.utils_1.2.0 farver_2.1.2
[53] viridis_0.6.5 matrixStats_1.5.0
[55] stats4_4.4.1 spatstat.explore_3.4-3
[57] jsonlite_2.0.0 tidygraph_1.3.1
[59] progressr_0.15.1 ggridges_0.5.6
[61] survival_3.6-4 tools_4.4.1
[63] ica_1.0-3 Rcpp_1.1.1-1.1
[65] SparseArray_1.6.2 gridExtra_2.3
[67] xfun_0.56 MatrixGenerics_1.18.1
[69] GenomeInfoDb_1.42.3 withr_3.0.2
[71] BiocManager_1.30.27 fastmap_1.2.0
[73] callr_3.7.6 digest_0.6.37
[75] timechange_0.3.0 R6_2.6.1
[77] mime_0.13 colorspace_2.1-1
[79] scattermore_1.2 tensor_1.5
[81] spatstat.data_3.1-6 utf8_1.2.5
[83] generics_0.1.4 renv_1.1.4
[85] data.table_1.18.2.1 graphlayouts_1.2.2
[87] httr_1.4.7 htmlwidgets_1.6.4
[89] S4Arrays_1.6.0 whisker_0.4.1
[91] uwot_0.2.3 pkgconfig_2.0.3
[93] gtable_0.3.6 lmtest_0.9-40
[95] S7_0.2.0 XVector_0.46.0
[97] htmltools_0.5.8.1 dotCall64_1.2
[99] Biobase_2.66.0 png_0.1-8
[101] spatstat.univar_3.1-3 knitr_1.50
[103] rstudioapi_0.17.1 tzdb_0.5.0
[105] reshape2_1.4.4 checkmate_2.3.2
[107] nlme_3.1-164 cachem_1.1.0
[109] zoo_1.8-14 KernSmooth_2.23-24
[111] vipor_0.4.7 parallel_4.4.1
[113] miniUI_0.1.2 ggrastr_1.0.2
[115] pillar_1.10.2 grid_4.4.1
[117] vctrs_0.6.5 RANN_2.6.2
[119] promises_1.3.3 xtable_1.8-4
[121] cluster_2.1.6 beeswarm_0.4.0
[123] paletteer_1.6.0 evaluate_1.0.3
[125] cli_3.6.5 compiler_4.4.1
[127] rlang_1.1.6 crayon_1.5.3
[129] future.apply_1.11.3 labeling_0.4.3
[131] rematch2_2.1.2 ps_1.9.1
[133] ggbeeswarm_0.7.2 getPass_0.2-4
[135] plyr_1.8.9 fs_1.6.6
[137] stringi_1.8.7 viridisLite_0.4.2
[139] deldir_2.0-4 lazyeval_0.2.2
[141] spatstat.geom_3.4-1 Matrix_1.7-0
[143] RcppHNSW_0.6.0 hms_1.1.3
[145] future_1.49.0 shiny_1.10.0
[147] SummarizedExperiment_1.36.0 ROCR_1.0-11
[149] igraph_2.1.4 memoise_2.0.1
[151] bslib_0.9.0