3. Visualizations
counts <- c(
"CD4 Tcm" = 21126,
"None T" = 5678,
"CD4 Tn" = 4420,
"CD4 Trm cell-death" = 3252,
"CD4 Tn adhesion" = 3109,
"CD4 Tc" = 2353,
"CD4 Trm" = 1874,
"CD4 Tex" = 1832,
"CD4 Treg" = 1729,
"CD4 Tem" = 1320,
"CD4 Tisg" = 1236,
"CD4 Th17" = 725,
"CD4 Trm naive-like" = 621,
"CD4 Tstr" = 434,
"CD4 proliferation" = 376,
"Tgd" = 360,
"CD4 Tfh" = 224,
"CD4 Treg activated" = 132,
"Heterogeneous" = 128,
"CD4 Temra" = 103,
"CD4 Th1" = 63
)
barplot(sort(counts, decreasing = TRUE), las = 2,
col = "steelblue",
main = "STCAT Prediction Counts",
ylab = "Number of Cells",
cex.names = 0.8)

library(ggplot2)
# Assuming 'counts' is your named vector from before
df_counts <- data.frame(
Prediction = names(counts),
Count = as.numeric(counts)
)
# Order the factor so bars are sorted top to bottom by count
df_counts$Prediction <- factor(df_counts$Prediction, levels = df_counts$Prediction[order(df_counts$Count)])
ggplot(df_counts, aes(x = Prediction, y = Count)) +
geom_bar(stat = "identity", fill = "steelblue") +
coord_flip() + # Flip to make prediction labels on Y axis
theme_minimal() +
labs(title = "STCAT Prediction Counts",
x = "Cell Type Prediction",
y = "Number of Cells")

Dimplot
DimPlot(ss_Bor_2023, group.by = "Disease_state", label = TRUE, repel = T,label.box = T)

DimPlot(ss_Bor_2023, group.by = "orig.ident", label = TRUE, repel = T,label.box = T)

DimPlot(ss_Bor_2023, group.by = "integrated_snn_res.0.5", label = TRUE, repel = T, label.box = T)

DimPlot(ss_Bor_2023, group.by = "STCAT_Prediction", label = TRUE, repel = T, label.box = T)

Distributions
table(ss_Bor_2023$STCAT_Prediction) # should show all predicted labels
CD4 proliferation CD4 Tc CD4 Tcm CD4 Tem CD4 Temra CD4 Tex
376 2353 21126 1320 103 1832
CD4 Tfh CD4 Th1 CD4 Th17 CD4 Tisg CD4 Tn CD4 Tn adhesion
224 63 725 1236 4420 3109
CD4 Treg CD4 Treg activated CD4 Trm CD4 Trm cell-death CD4 Trm naive-like CD4 Tstr
1729 132 1874 3252 621 434
Heterogeneous None T Tgd
128 5678 360
table(ss_Bor_2023$orig.ident) # should show L1–L7
Control SS_P1 SS_P2 SS_P3 SS_P4 SS_P5 SS_P6
4437 3443 34179 3084 849 1582 3521
# Contingency table of STCAT Prediction × Cell Line
table_annotation_Disease <- table(ss_Bor_2023$STCAT_Prediction, ss_Bor_2023$Disease_state)
table_annotation_orig_ident <- table(ss_Bor_2023$STCAT_Prediction, ss_Bor_2023$orig.ident)
table_annotation_cluster <- table(ss_Bor_2023$STCAT_Prediction, ss_Bor_2023$integrated_snn_res.0.5)
library(pheatmap)
# Proportion table (color scale)
prop_table <- prop.table(table_annotation_Disease, margin = 1)
# Heatmap with raw counts as labels
pheatmap(prop_table,
display_numbers = table_annotation_Disease,
cluster_rows = TRUE,
cluster_cols = TRUE,
color = colorRampPalette(c("lightyellow", "yellow", "lightgreen", "white"))(100),
fontsize_row = 10,
fontsize_col = 10,
main = "STCAT Prediction vs Disease_state")

library(pheatmap)
# Proportion table (color scale)
prop_table <- prop.table(table_annotation_cluster, margin = 1)
# Heatmap with raw counts as labels
pheatmap(prop_table,
display_numbers = table_annotation_cluster,
cluster_rows = TRUE,
cluster_cols = TRUE,
color = colorRampPalette(c("lightyellow", "yellow", "lightgreen", "white"))(100),
fontsize_row = 10,
fontsize_col = 10,
main = "STCAT Prediction vs Clusters")

library(pheatmap)
# Proportion table (color scale)
prop_table <- prop.table(table_annotation_orig_ident, margin = 1)
# Heatmap with raw counts as labels
pheatmap(prop_table,
display_numbers = table_annotation_orig_ident,
cluster_rows = TRUE,
cluster_cols = TRUE,
color = colorRampPalette(c("lightyellow", "yellow", "lightgreen", "white"))(100),
fontsize_row = 10,
fontsize_col = 10,
main = "STCAT Prediction vs Patients")

library(ggplot2)
library(ggridges)
ggplot(ss_Bor_2023@meta.data, aes(x = STCAT_Uncertainty, y = STCAT_Prediction, fill = STCAT_Prediction)) +
geom_density_ridges(alpha = 0.7, scale = 2, rel_min_height = 0.01) +
theme_minimal() +
labs(
x = "Cluster Entropy Score",
y = "Predicted T Cell Type (STCAT)",
title = "Density Ridgeline of Cluster Entropy by T Cell Type"
) +
theme(
legend.position = "none",
axis.text.y = element_text(size = 9)
)

NA
NA
LS0tCnRpdGxlOiAiU1RDQVRfQm9yY2hlcmRpbmdfMjAyM19WaXN1YWxpemF0aW9uIgphdXRob3I6IE5hc2lyIE1haG1vb2QgQWJiYXNpCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogICNybWRmb3JtYXRzOjpyZWFkdGhlZG93bgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQotLS0KCiMgMS4gbG9hZCBsaWJyYXJpZXMKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CgpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShTZXVyYXRPYmplY3QpCmxpYnJhcnkoU2V1cmF0RGF0YSkKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoQXppbXV0aCkKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShybWFya2Rvd24pCmxpYnJhcnkodGlueXRleCkKCgpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGRpdHRvU2VxKQpsaWJyYXJ5KGdncmVwZWwpCiNsaWJyYXJ5KGdndHJlZSkKbGlicmFyeShwYXJhbGxlbCkKbGlicmFyeShwbG90bHkpICAjIDNEIHBsb3QKbGlicmFyeShTZXVyYXQpICAjIElkZW50cygpCmxpYnJhcnkoU2V1cmF0RGlzaykgICMgU2F2ZUg1U2V1cmF0KCkKbGlicmFyeSh0aWJibGUpICAjIHJvd25uYW1lc190b19jb2x1bW4KbGlicmFyeShoYXJtb255KSAjIFJ1bkhhcm1vbnkoKQojb3B0aW9ucyhtYy5jb3JlcyA9IGRldGVjdENvcmVzKCkgLSAxKQoKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoZGJwbHlyKQpsaWJyYXJ5KHJtYXJrZG93bikKbGlicmFyeShrbml0cikKbGlicmFyeSh0aW55dGV4KQojQXppbXV0aCBBbm5vdGF0aW9uIGxpYnJhcmllcwpsaWJyYXJ5KEF6aW11dGgpCiNQcm9qZWNUaWxzIEFubm90YXRpb24gbGlicmFyaWVzCmxpYnJhcnkoU1RBQ0FTKQpsaWJyYXJ5KFByb2plY1RJTHMpCiNzaW5nbGVSIEFubm90YXRpb24gbGlicmFyaWVzCgpsaWJyYXJ5KFNpbmdsZUNlbGxFeHBlcmltZW50KQoKYGBgCgoKIyAyLiBMb2FkIERhdGEgaW50byBTZXVyYXQKYGBge3IgbG9hZF9zZXVyYXR9Cgpzc19Cb3JfMjAyMyA8LSByZWFkUkRTKCJTVENBVC9BbGxfUGF0aWVudHNfSW50ZWdyYXRlZF9zc19Cb3JfMjAyM19hbm5vdGF0ZWQuUkRTIikKCmBgYAoKIyAzLiBWaXN1YWxpemF0aW9ucyAKYGBge3IgU1RDQVRfdmlzLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTR9Cgpjb3VudHMgPC0gYygKICAiQ0Q0IFRjbSIgPSAyMTEyNiwKICAiTm9uZSBUIiA9IDU2NzgsCiAgIkNENCBUbiIgPSA0NDIwLAogICJDRDQgVHJtIGNlbGwtZGVhdGgiID0gMzI1MiwKICAiQ0Q0IFRuIGFkaGVzaW9uIiA9IDMxMDksCiAgIkNENCBUYyIgPSAyMzUzLAogICJDRDQgVHJtIiA9IDE4NzQsCiAgIkNENCBUZXgiID0gMTgzMiwKICAiQ0Q0IFRyZWciID0gMTcyOSwKICAiQ0Q0IFRlbSIgPSAxMzIwLAogICJDRDQgVGlzZyIgPSAxMjM2LAogICJDRDQgVGgxNyIgPSA3MjUsCiAgIkNENCBUcm0gbmFpdmUtbGlrZSIgPSA2MjEsCiAgIkNENCBUc3RyIiA9IDQzNCwKICAiQ0Q0IHByb2xpZmVyYXRpb24iID0gMzc2LAogICJUZ2QiID0gMzYwLAogICJDRDQgVGZoIiA9IDIyNCwKICAiQ0Q0IFRyZWcgYWN0aXZhdGVkIiA9IDEzMiwKICAiSGV0ZXJvZ2VuZW91cyIgPSAxMjgsCiAgIkNENCBUZW1yYSIgPSAxMDMsCiAgIkNENCBUaDEiID0gNjMKKQoKYmFycGxvdChzb3J0KGNvdW50cywgZGVjcmVhc2luZyA9IFRSVUUpLCBsYXMgPSAyLAogICAgICAgIGNvbCA9ICJzdGVlbGJsdWUiLCAKICAgICAgICBtYWluID0gIlNUQ0FUIFByZWRpY3Rpb24gQ291bnRzIiwKICAgICAgICB5bGFiID0gIk51bWJlciBvZiBDZWxscyIsCiAgICAgICAgY2V4Lm5hbWVzID0gMC44KQoKCgpsaWJyYXJ5KGdncGxvdDIpCgojIEFzc3VtaW5nICdjb3VudHMnIGlzIHlvdXIgbmFtZWQgdmVjdG9yIGZyb20gYmVmb3JlCmRmX2NvdW50cyA8LSBkYXRhLmZyYW1lKAogIFByZWRpY3Rpb24gPSBuYW1lcyhjb3VudHMpLAogIENvdW50ID0gYXMubnVtZXJpYyhjb3VudHMpCikKCiMgT3JkZXIgdGhlIGZhY3RvciBzbyBiYXJzIGFyZSBzb3J0ZWQgdG9wIHRvIGJvdHRvbSBieSBjb3VudApkZl9jb3VudHMkUHJlZGljdGlvbiA8LSBmYWN0b3IoZGZfY291bnRzJFByZWRpY3Rpb24sIGxldmVscyA9IGRmX2NvdW50cyRQcmVkaWN0aW9uW29yZGVyKGRmX2NvdW50cyRDb3VudCldKQoKZ2dwbG90KGRmX2NvdW50cywgYWVzKHggPSBQcmVkaWN0aW9uLCB5ID0gQ291bnQpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAic3RlZWxibHVlIikgKwogIGNvb3JkX2ZsaXAoKSArICAgIyBGbGlwIHRvIG1ha2UgcHJlZGljdGlvbiBsYWJlbHMgb24gWSBheGlzCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlID0gIlNUQ0FUIFByZWRpY3Rpb24gQ291bnRzIiwKICAgICAgIHggPSAiQ2VsbCBUeXBlIFByZWRpY3Rpb24iLAogICAgICAgeSA9ICJOdW1iZXIgb2YgQ2VsbHMiKQoKYGBgCgoKIyMgRGltcGxvdApgYGB7ciBTVENBVF92aXMyLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTR9CgpEaW1QbG90KHNzX0Jvcl8yMDIzLCBncm91cC5ieSA9ICJEaXNlYXNlX3N0YXRlIiwgbGFiZWwgPSBUUlVFLCByZXBlbCA9IFQsbGFiZWwuYm94ID0gVCkKRGltUGxvdChzc19Cb3JfMjAyMywgZ3JvdXAuYnkgPSAib3JpZy5pZGVudCIsIGxhYmVsID0gVFJVRSwgcmVwZWwgPSBULGxhYmVsLmJveCA9IFQpCkRpbVBsb3Qoc3NfQm9yXzIwMjMsIGdyb3VwLmJ5ID0gImludGVncmF0ZWRfc25uX3Jlcy4wLjUiLCBsYWJlbCA9IFRSVUUsIHJlcGVsID0gVCwgbGFiZWwuYm94ID0gVCkKRGltUGxvdChzc19Cb3JfMjAyMywgZ3JvdXAuYnkgPSAiU1RDQVRfUHJlZGljdGlvbiIsIGxhYmVsID0gVFJVRSwgcmVwZWwgPSBULCBsYWJlbC5ib3ggPSBUKQoKYGBgCgojIyBEaXN0cmlidXRpb25zCmBgYHtyIFNUQ0FUX3ZpczMsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xNH0KCnRhYmxlKHNzX0Jvcl8yMDIzJFNUQ0FUX1ByZWRpY3Rpb24pICAjIHNob3VsZCBzaG93IGFsbCBwcmVkaWN0ZWQgbGFiZWxzCnRhYmxlKHNzX0Jvcl8yMDIzJG9yaWcuaWRlbnQpICAgICAgICAgIyBzaG91bGQgc2hvdyBMMeKAk0w3CgojIENvbnRpbmdlbmN5IHRhYmxlIG9mIFNUQ0FUIFByZWRpY3Rpb24gw5cgQ2VsbCBMaW5lCnRhYmxlX2Fubm90YXRpb25fRGlzZWFzZSA8LSB0YWJsZShzc19Cb3JfMjAyMyRTVENBVF9QcmVkaWN0aW9uLCBzc19Cb3JfMjAyMyREaXNlYXNlX3N0YXRlKQp0YWJsZV9hbm5vdGF0aW9uX29yaWdfaWRlbnQgPC0gdGFibGUoc3NfQm9yXzIwMjMkU1RDQVRfUHJlZGljdGlvbiwgc3NfQm9yXzIwMjMkb3JpZy5pZGVudCkKdGFibGVfYW5ub3RhdGlvbl9jbHVzdGVyIDwtIHRhYmxlKHNzX0Jvcl8yMDIzJFNUQ0FUX1ByZWRpY3Rpb24sIHNzX0Jvcl8yMDIzJGludGVncmF0ZWRfc25uX3Jlcy4wLjUpCgoKbGlicmFyeShwaGVhdG1hcCkKCiMgUHJvcG9ydGlvbiB0YWJsZSAoY29sb3Igc2NhbGUpCnByb3BfdGFibGUgPC0gcHJvcC50YWJsZSh0YWJsZV9hbm5vdGF0aW9uX0Rpc2Vhc2UsIG1hcmdpbiA9IDEpCgojIEhlYXRtYXAgd2l0aCByYXcgY291bnRzIGFzIGxhYmVscwpwaGVhdG1hcChwcm9wX3RhYmxlLAogICAgICAgICBkaXNwbGF5X251bWJlcnMgPSB0YWJsZV9hbm5vdGF0aW9uX0Rpc2Vhc2UsCiAgICAgICAgIGNsdXN0ZXJfcm93cyA9IFRSVUUsCiAgICAgICAgIGNsdXN0ZXJfY29scyA9IFRSVUUsCiAgICAgICAgIGNvbG9yID0gY29sb3JSYW1wUGFsZXR0ZShjKCJsaWdodHllbGxvdyIsICJ5ZWxsb3ciLCAibGlnaHRncmVlbiIsICJ3aGl0ZSIpKSgxMDApLAogICAgICAgICBmb250c2l6ZV9yb3cgPSAxMCwKICAgICAgICAgZm9udHNpemVfY29sID0gMTAsCiAgICAgICAgIG1haW4gPSAiU1RDQVQgUHJlZGljdGlvbiB2cyBEaXNlYXNlX3N0YXRlIikKCgpsaWJyYXJ5KHBoZWF0bWFwKQoKIyBQcm9wb3J0aW9uIHRhYmxlIChjb2xvciBzY2FsZSkKcHJvcF90YWJsZSA8LSBwcm9wLnRhYmxlKHRhYmxlX2Fubm90YXRpb25fY2x1c3RlciwgbWFyZ2luID0gMSkKCiMgSGVhdG1hcCB3aXRoIHJhdyBjb3VudHMgYXMgbGFiZWxzCnBoZWF0bWFwKHByb3BfdGFibGUsCiAgICAgICAgIGRpc3BsYXlfbnVtYmVycyA9IHRhYmxlX2Fubm90YXRpb25fY2x1c3RlciwKICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwKICAgICAgICAgY2x1c3Rlcl9jb2xzID0gVFJVRSwKICAgICAgICAgY29sb3IgPSBjb2xvclJhbXBQYWxldHRlKGMoImxpZ2h0eWVsbG93IiwgInllbGxvdyIsICJsaWdodGdyZWVuIiwgIndoaXRlIikpKDEwMCksCiAgICAgICAgIGZvbnRzaXplX3JvdyA9IDEwLAogICAgICAgICBmb250c2l6ZV9jb2wgPSAxMCwKICAgICAgICAgbWFpbiA9ICJTVENBVCBQcmVkaWN0aW9uIHZzIENsdXN0ZXJzIikKCgpsaWJyYXJ5KHBoZWF0bWFwKQoKIyBQcm9wb3J0aW9uIHRhYmxlIChjb2xvciBzY2FsZSkKcHJvcF90YWJsZSA8LSBwcm9wLnRhYmxlKHRhYmxlX2Fubm90YXRpb25fb3JpZ19pZGVudCwgbWFyZ2luID0gMSkKCiMgSGVhdG1hcCB3aXRoIHJhdyBjb3VudHMgYXMgbGFiZWxzCnBoZWF0bWFwKHByb3BfdGFibGUsCiAgICAgICAgIGRpc3BsYXlfbnVtYmVycyA9IHRhYmxlX2Fubm90YXRpb25fb3JpZ19pZGVudCwKICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwKICAgICAgICAgY2x1c3Rlcl9jb2xzID0gVFJVRSwKICAgICAgICAgY29sb3IgPSBjb2xvclJhbXBQYWxldHRlKGMoImxpZ2h0eWVsbG93IiwgInllbGxvdyIsICJsaWdodGdyZWVuIiwgIndoaXRlIikpKDEwMCksCiAgICAgICAgIGZvbnRzaXplX3JvdyA9IDEwLAogICAgICAgICBmb250c2l6ZV9jb2wgPSAxMCwKICAgICAgICAgbWFpbiA9ICJTVENBVCBQcmVkaWN0aW9uIHZzIFBhdGllbnRzIikKCmBgYAoKCgojIyAKYGBge3IgLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTR9CgpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dyaWRnZXMpCgpnZ3Bsb3Qoc3NfQm9yXzIwMjNAbWV0YS5kYXRhLCBhZXMoeCA9IFNUQ0FUX1VuY2VydGFpbnR5LCB5ID0gU1RDQVRfUHJlZGljdGlvbiwgZmlsbCA9IFNUQ0FUX1ByZWRpY3Rpb24pKSArCiAgZ2VvbV9kZW5zaXR5X3JpZGdlcyhhbHBoYSA9IDAuNywgc2NhbGUgPSAyLCByZWxfbWluX2hlaWdodCA9IDAuMDEpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnMoCiAgICB4ID0gIkNsdXN0ZXIgRW50cm9weSBTY29yZSIsCiAgICB5ID0gIlByZWRpY3RlZCBUIENlbGwgVHlwZSAoU1RDQVQpIiwKICAgIHRpdGxlID0gIkRlbnNpdHkgUmlkZ2VsaW5lIG9mIENsdXN0ZXIgRW50cm9weSBieSBUIENlbGwgVHlwZSIKICApICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KQogICkKCgpgYGAKCgoKCgo=