1. load libraries

2. Load Data into Seurat


ss_Bor_2023 <- readRDS("../Borch_Combined/data/ss_Borcherding_Malignant_6_Normal_1_Integrated_object.rds")

3. Export to .h5ad (AnnData format)

# Step 1: Rejoin Layers to Get Unified Raw Counts
ss_Bor_2023[["RNA"]] <- JoinLayers(ss_Bor_2023[["RNA"]])
raw_counts <- ss_Bor_2023[["RNA"]]$counts


# Step 2: Transpose to Cells × Genes
# Transpose: genes × cells → cells × genes
counts_transposed <- t(as.matrix(raw_counts))

# Step 3: Prepare Metadata (Optional, Recommended)
cell_metadata <- ss_Bor_2023[[]]  # All cell metadata

# Step 4: Convert to SingleCellExperiment
library(SingleCellExperiment)
sce <- SingleCellExperiment(
  assays = list(counts = raw_counts),       # Keep raw_counts (genes × cells!)
  colData = cell_metadata                   # Attach cell metadata
)

#Step 5: Export to .h5ad
library(zellkonverter)
writeH5AD(sce, file = "STCAT/ss_Bor_2023_raw_counts.h5ad")

4. Python Script to run (make sure you have right directory)

# import warnings
# warnings.filterwarnings("ignore")
# import STCAT
# import scanpy as sc
# 
# 
# # Load your .h5ad data
# adata = sc.read("/home/bioinfo/2025_NewHarmony_Integrated_Files/Year3_Analysis/Biomarkers_Validation_with_Public_Data/Borch_Combined/STCAT/STCAT_Annotation_Borcherding/ss_Bor_2023_raw_counts.h5ad")
# print(adata.var_names[:10])
# 
# 
# # Run STCAT
# results = STCAT.STCAT(adata)
# 
# # Save results
# results.write("/home/bioinfo/2025_NewHarmony_Integrated_Files/Year3_Analysis/Biomarkers_Validation_with_Public_Data/Borch_Combined/STCAT/STCAT_Annotation_Borcherding/STCAT_Annotation_ss_Bor_2023_raw_counts.h5ad")
# 
# 
# print(adata)
# 

5. Read and merge with Seurat (STCAT annotation)


# Load Seurat and read your annotated table
library(Seurat)
library(dplyr)

# Read your annotation table
annots <- read.csv("STCAT/STCAT_Annotation_Borcherding/STCAT_annotations.csv", row.names = 1)

# Confirm the rownames are cell barcodes
head(rownames(annots))  # e.g., AAACCTGGT...
[1] "SS_P1_AAATGCCTCAACGGCC-1" "SS_P1_AATCGGTGTTCCAACA-1" "SS_P1_ACACCCTTCGCGTTTC-1" "SS_P1_ACAGCCGAGCTCCTCT-1"
[5] "SS_P1_ACTTACTAGCTAAGAT-1" "SS_P1_AGGCCACGTACCGTAT-1"
# Match to your Seurat object (assuming your Seurat object is named `ss_Bor_2023`)
ss_Bor_2023$STCAT_Prediction <- annots[Cells(ss_Bor_2023), "Prediction"]
ss_Bor_2023$STCAT_Cluster <- annots[Cells(ss_Bor_2023), "Cluster"]
ss_Bor_2023$STCAT_Uncertainty <- annots[Cells(ss_Bor_2023), "Uncertainty.score"]

view(ss_Bor_2023@meta.data)

6. Read and merge with Seurat (STCAT annotation)


DimPlot(ss_Bor_2023_annotated, group.by = "Disease_state", label = TRUE, repel = T)

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

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

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

NA
NA
NA
NA

7. Read and merge with Seurat (STCAT annotation)


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_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_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")

LS0tCnRpdGxlOiAiSG93IHRvIGNyZWF0ZSAuaDVhZCBmb3IgU1RDQVQiCmF1dGhvcjogTmFzaXIgTWFobW9vZCBBYmJhc2kKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgI3JtZGZvcm1hdHM6OnJlYWR0aGVkb3duCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCi0tLQoKIyAxLiBsb2FkIGxpYnJhcmllcwpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KFNldXJhdE9iamVjdCkKbGlicmFyeShTZXVyYXREYXRhKQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShBemltdXRoKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHJtYXJrZG93bikKbGlicmFyeSh0aW55dGV4KQoKCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZGl0dG9TZXEpCmxpYnJhcnkoZ2dyZXBlbCkKI2xpYnJhcnkoZ2d0cmVlKQpsaWJyYXJ5KHBhcmFsbGVsKQpsaWJyYXJ5KHBsb3RseSkgICMgM0QgcGxvdApsaWJyYXJ5KFNldXJhdCkgICMgSWRlbnRzKCkKbGlicmFyeShTZXVyYXREaXNrKSAgIyBTYXZlSDVTZXVyYXQoKQpsaWJyYXJ5KHRpYmJsZSkgICMgcm93bm5hbWVzX3RvX2NvbHVtbgpsaWJyYXJ5KGhhcm1vbnkpICMgUnVuSGFybW9ueSgpCiNvcHRpb25zKG1jLmNvcmVzID0gZGV0ZWN0Q29yZXMoKSAtIDEpCgpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShkYnBseXIpCmxpYnJhcnkocm1hcmtkb3duKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KHRpbnl0ZXgpCiNBemltdXRoIEFubm90YXRpb24gbGlicmFyaWVzCmxpYnJhcnkoQXppbXV0aCkKI1Byb2plY1RpbHMgQW5ub3RhdGlvbiBsaWJyYXJpZXMKbGlicmFyeShTVEFDQVMpCmxpYnJhcnkoUHJvamVjVElMcykKI3NpbmdsZVIgQW5ub3RhdGlvbiBsaWJyYXJpZXMKCmxpYnJhcnkoU2luZ2xlQ2VsbEV4cGVyaW1lbnQpCgpgYGAKCgojIDIuIExvYWQgRGF0YSBpbnRvIFNldXJhdApgYGB7ciBsb2FkX3NldXJhdH0KCnNzX0Jvcl8yMDIzIDwtIHJlYWRSRFMoIi4uL0JvcmNoX0NvbWJpbmVkL2RhdGEvc3NfQm9yY2hlcmRpbmdfTWFsaWduYW50XzZfTm9ybWFsXzFfSW50ZWdyYXRlZF9vYmplY3QucmRzIikKCmBgYAoKIyAzLiBFeHBvcnQgdG8gLmg1YWQgKEFubkRhdGEgZm9ybWF0KQpgYGB7ciBBbm5EYXRhLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KIyBTdGVwIDE6IFJlam9pbiBMYXllcnMgdG8gR2V0IFVuaWZpZWQgUmF3IENvdW50cwpzc19Cb3JfMjAyM1tbIlJOQSJdXSA8LSBKb2luTGF5ZXJzKHNzX0Jvcl8yMDIzW1siUk5BIl1dKQpyYXdfY291bnRzIDwtIHNzX0Jvcl8yMDIzW1siUk5BIl1dJGNvdW50cwoKCiMgU3RlcCAyOiBUcmFuc3Bvc2UgdG8gQ2VsbHMgw5cgR2VuZXMKIyBUcmFuc3Bvc2U6IGdlbmVzIMOXIGNlbGxzIOKGkiBjZWxscyDDlyBnZW5lcwpjb3VudHNfdHJhbnNwb3NlZCA8LSB0KGFzLm1hdHJpeChyYXdfY291bnRzKSkKCiMgU3RlcCAzOiBQcmVwYXJlIE1ldGFkYXRhIChPcHRpb25hbCwgUmVjb21tZW5kZWQpCmNlbGxfbWV0YWRhdGEgPC0gc3NfQm9yXzIwMjNbW11dICAjIEFsbCBjZWxsIG1ldGFkYXRhCgojIFN0ZXAgNDogQ29udmVydCB0byBTaW5nbGVDZWxsRXhwZXJpbWVudApsaWJyYXJ5KFNpbmdsZUNlbGxFeHBlcmltZW50KQpzY2UgPC0gU2luZ2xlQ2VsbEV4cGVyaW1lbnQoCiAgYXNzYXlzID0gbGlzdChjb3VudHMgPSByYXdfY291bnRzKSwgICAgICAgIyBLZWVwIHJhd19jb3VudHMgKGdlbmVzIMOXIGNlbGxzISkKICBjb2xEYXRhID0gY2VsbF9tZXRhZGF0YSAgICAgICAgICAgICAgICAgICAjIEF0dGFjaCBjZWxsIG1ldGFkYXRhCikKCiNTdGVwIDU6IEV4cG9ydCB0byAuaDVhZApsaWJyYXJ5KHplbGxrb252ZXJ0ZXIpCndyaXRlSDVBRChzY2UsIGZpbGUgPSAiU1RDQVQvc3NfQm9yXzIwMjNfcmF3X2NvdW50cy5oNWFkIikKCmBgYAoKCiMgNC4gUHl0aG9uIFNjcmlwdCB0byBydW4gKG1ha2Ugc3VyZSB5b3UgaGF2ZSByaWdodCBkaXJlY3RvcnkpCmBgYHtyIFB5dGhvblNUQ0FULCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KIyBpbXBvcnQgd2FybmluZ3MKIyB3YXJuaW5ncy5maWx0ZXJ3YXJuaW5ncygiaWdub3JlIikKIyBpbXBvcnQgU1RDQVQKIyBpbXBvcnQgc2NhbnB5IGFzIHNjCiMgCiMgCiMgIyBMb2FkIHlvdXIgLmg1YWQgZGF0YQojIGFkYXRhID0gc2MucmVhZCgiL2hvbWUvYmlvaW5mby8yMDI1X05ld0hhcm1vbnlfSW50ZWdyYXRlZF9GaWxlcy9ZZWFyM19BbmFseXNpcy9CaW9tYXJrZXJzX1ZhbGlkYXRpb25fd2l0aF9QdWJsaWNfRGF0YS9Cb3JjaF9Db21iaW5lZC9TVENBVC9TVENBVF9Bbm5vdGF0aW9uX0JvcmNoZXJkaW5nL3NzX0Jvcl8yMDIzX3Jhd19jb3VudHMuaDVhZCIpCiMgcHJpbnQoYWRhdGEudmFyX25hbWVzWzoxMF0pCiMgCiMgCiMgIyBSdW4gU1RDQVQKIyByZXN1bHRzID0gU1RDQVQuU1RDQVQoYWRhdGEpCiMgCiMgIyBTYXZlIHJlc3VsdHMKIyByZXN1bHRzLndyaXRlKCIvaG9tZS9iaW9pbmZvLzIwMjVfTmV3SGFybW9ueV9JbnRlZ3JhdGVkX0ZpbGVzL1llYXIzX0FuYWx5c2lzL0Jpb21hcmtlcnNfVmFsaWRhdGlvbl93aXRoX1B1YmxpY19EYXRhL0JvcmNoX0NvbWJpbmVkL1NUQ0FUL1NUQ0FUX0Fubm90YXRpb25fQm9yY2hlcmRpbmcvU1RDQVRfQW5ub3RhdGlvbl9zc19Cb3JfMjAyM19yYXdfY291bnRzLmg1YWQiKQojIAojIAojIHByaW50KGFkYXRhKQojIAoKYGBgCgojIDUuIFJlYWQgYW5kIG1lcmdlIHdpdGggU2V1cmF0IChTVENBVCBhbm5vdGF0aW9uKQpgYGB7ciBTVENBVCwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CgojIExvYWQgU2V1cmF0IGFuZCByZWFkIHlvdXIgYW5ub3RhdGVkIHRhYmxlCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KGRwbHlyKQoKIyBSZWFkIHlvdXIgYW5ub3RhdGlvbiB0YWJsZQphbm5vdHMgPC0gcmVhZC5jc3YoIlNUQ0FUL1NUQ0FUX0Fubm90YXRpb25fQm9yY2hlcmRpbmcvU1RDQVRfYW5ub3RhdGlvbnMuY3N2Iiwgcm93Lm5hbWVzID0gMSkKCiMgQ29uZmlybSB0aGUgcm93bmFtZXMgYXJlIGNlbGwgYmFyY29kZXMKaGVhZChyb3duYW1lcyhhbm5vdHMpKSAgIyBlLmcuLCBBQUFDQ1RHR1QuLi4KCiMgTWF0Y2ggdG8geW91ciBTZXVyYXQgb2JqZWN0IChhc3N1bWluZyB5b3VyIFNldXJhdCBvYmplY3QgaXMgbmFtZWQgYHNzX0Jvcl8yMDIzYCkKc3NfQm9yXzIwMjMkU1RDQVRfUHJlZGljdGlvbiA8LSBhbm5vdHNbQ2VsbHMoc3NfQm9yXzIwMjMpLCAiUHJlZGljdGlvbiJdCnNzX0Jvcl8yMDIzJFNUQ0FUX0NsdXN0ZXIgPC0gYW5ub3RzW0NlbGxzKHNzX0Jvcl8yMDIzKSwgIkNsdXN0ZXIiXQpzc19Cb3JfMjAyMyRTVENBVF9VbmNlcnRhaW50eSA8LSBhbm5vdHNbQ2VsbHMoc3NfQm9yXzIwMjMpLCAiVW5jZXJ0YWludHkuc2NvcmUiXQoKdmlldyhzc19Cb3JfMjAyM0BtZXRhLmRhdGEpCgpgYGAKCgojIDYuIFJlYWQgYW5kIG1lcmdlIHdpdGggU2V1cmF0IChTVENBVCBhbm5vdGF0aW9uKQpgYGB7ciBTVENBVF92aXMsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xNH0KCkRpbVBsb3Qoc3NfQm9yXzIwMjNfYW5ub3RhdGVkLCBncm91cC5ieSA9ICJEaXNlYXNlX3N0YXRlIiwgbGFiZWwgPSBUUlVFLCByZXBlbCA9IFQpCkRpbVBsb3Qoc3NfQm9yXzIwMjNfYW5ub3RhdGVkLCBncm91cC5ieSA9ICJvcmlnLmlkZW50IiwgbGFiZWwgPSBUUlVFLCByZXBlbCA9IFQpCkRpbVBsb3Qoc3NfQm9yXzIwMjNfYW5ub3RhdGVkLCBncm91cC5ieSA9ICJpbnRlZ3JhdGVkX3Nubl9yZXMuMC41IiwgbGFiZWwgPSBUUlVFLCByZXBlbCA9IFQpCkRpbVBsb3Qoc3NfQm9yXzIwMjNfYW5ub3RhdGVkLCBncm91cC5ieSA9ICJTVENBVF9QcmVkaWN0aW9uIiwgbGFiZWwgPSBUUlVFLCByZXBlbCA9IFQpCgoKCgpgYGAKCiMgNy4gUmVhZCBhbmQgbWVyZ2Ugd2l0aCBTZXVyYXQgKFNUQ0FUIGFubm90YXRpb24pCmBgYHtyIFNUQ0FUX3ZpczIsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xNH0KCnRhYmxlKHNzX0Jvcl8yMDIzJFNUQ0FUX1ByZWRpY3Rpb24pICAjIHNob3VsZCBzaG93IGFsbCBwcmVkaWN0ZWQgbGFiZWxzCnRhYmxlKHNzX0Jvcl8yMDIzJG9yaWcuaWRlbnQpICAgICAgICAgIyBzaG91bGQgc2hvdyBMMeKAk0w3CgojIENvbnRpbmdlbmN5IHRhYmxlIG9mIFNUQ0FUIFByZWRpY3Rpb24gw5cgQ2VsbCBMaW5lCnRhYmxlX2Fubm90YXRpb25fb3JpZ19pZGVudCA8LSB0YWJsZShzc19Cb3JfMjAyMyRTVENBVF9QcmVkaWN0aW9uLCBzc19Cb3JfMjAyMyRvcmlnLmlkZW50KQp0YWJsZV9hbm5vdGF0aW9uX2NsdXN0ZXIgPC0gdGFibGUoc3NfQm9yXzIwMjMkU1RDQVRfUHJlZGljdGlvbiwgc3NfQm9yXzIwMjMkaW50ZWdyYXRlZF9zbm5fcmVzLjAuNSkKCmxpYnJhcnkocGhlYXRtYXApCgojIFByb3BvcnRpb24gdGFibGUgKGNvbG9yIHNjYWxlKQpwcm9wX3RhYmxlIDwtIHByb3AudGFibGUodGFibGVfYW5ub3RhdGlvbl9jbHVzdGVyLCBtYXJnaW4gPSAxKQoKIyBIZWF0bWFwIHdpdGggcmF3IGNvdW50cyBhcyBsYWJlbHMKcGhlYXRtYXAocHJvcF90YWJsZSwKICAgICAgICAgZGlzcGxheV9udW1iZXJzID0gdGFibGVfYW5ub3RhdGlvbl9jbHVzdGVyLAogICAgICAgICBjbHVzdGVyX3Jvd3MgPSBUUlVFLAogICAgICAgICBjbHVzdGVyX2NvbHMgPSBUUlVFLAogICAgICAgICBjb2xvciA9IGNvbG9yUmFtcFBhbGV0dGUoYygibGlnaHR5ZWxsb3ciLCAieWVsbG93IiwgImxpZ2h0Z3JlZW4iLCAid2hpdGUiKSkoMTAwKSwKICAgICAgICAgZm9udHNpemVfcm93ID0gMTAsCiAgICAgICAgIGZvbnRzaXplX2NvbCA9IDEwLAogICAgICAgICBtYWluID0gIlNUQ0FUIFByZWRpY3Rpb24gdnMgQ2x1c3RlcnMiKQoKCmxpYnJhcnkocGhlYXRtYXApCgojIFByb3BvcnRpb24gdGFibGUgKGNvbG9yIHNjYWxlKQpwcm9wX3RhYmxlIDwtIHByb3AudGFibGUodGFibGVfYW5ub3RhdGlvbl9vcmlnX2lkZW50LCBtYXJnaW4gPSAxKQoKIyBIZWF0bWFwIHdpdGggcmF3IGNvdW50cyBhcyBsYWJlbHMKcGhlYXRtYXAocHJvcF90YWJsZSwKICAgICAgICAgZGlzcGxheV9udW1iZXJzID0gdGFibGVfYW5ub3RhdGlvbl9vcmlnX2lkZW50LAogICAgICAgICBjbHVzdGVyX3Jvd3MgPSBUUlVFLAogICAgICAgICBjbHVzdGVyX2NvbHMgPSBUUlVFLAogICAgICAgICBjb2xvciA9IGNvbG9yUmFtcFBhbGV0dGUoYygibGlnaHR5ZWxsb3ciLCAieWVsbG93IiwgImxpZ2h0Z3JlZW4iLCAid2hpdGUiKSkoMTAwKSwKICAgICAgICAgZm9udHNpemVfcm93ID0gMTAsCiAgICAgICAgIGZvbnRzaXplX2NvbCA9IDEwLAogICAgICAgICBtYWluID0gIlNUQ0FUIFByZWRpY3Rpb24gdnMgUGF0aWVudHMiKQoKYGBg