load libraries————————————

1. Load and Subset Normal CD4 T Cells


All_samples_Merged <- readRDS("../0-Seurat_RDS_OBJECT_FINAL/Seurat_object_Final_changes/All_samples_Merged_with_STCAT_Annotation_final-5-09-2025.rds")

2. Run FindAllMarkers on RNA Assay

# Set assay to RNA
DefaultAssay(All_samples_Merged) <- "RNA"

# Check if RNA assay has normalized data
if (!"data" %in% slotNames(All_samples_Merged[["RNA"]]) || 
    ncol(GetAssayData(All_samples_Merged[["RNA"]], slot = "data")) == 0) {
  
  message("RNA assay does not contain normalized data. Running NormalizeData...")
  All_samples_Merged <- NormalizeData(
    All_samples_Merged,
    assay = "RNA",
    normalization.method = "LogNormalize",
    scale.factor = 10000
  )
  
} else {
  message("RNA assay already contains normalized data. Skipping normalization.")
}
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Idents(All_samples_Merged) <- "seurat_clusters"

# Find markers for all clusters
all_markers <- FindAllMarkers(
  All_samples_Merged,
  only.pos = TRUE,
  min.pct = 0.25,
  logfc.threshold = 0.25
)

# Save markers
write.csv(all_markers, "AllMarkers_clusters-17-09-2025.csv", row.names = FALSE)

3. Top 25 and Top 5 markers per cluster

cat("Top 5 marker list saved to Top5Markers_clusters.csv\n")
Top 5 marker list saved to Top5Markers_clusters.csv

3. Visualize Markers


DefaultAssay(All_samples_Merged) <- "RNA"

# Unique genes from top5
all_genes <- top5$gene

# 1️⃣ Check overlap with RNA assay
valid_genes <- intersect(unique(all_genes), rownames(All_samples_Merged[["RNA"]]))
invalid_genes <- setdiff(unique(all_genes), rownames(All_samples_Merged[["RNA"]]))

cat("Valid genes:", length(valid_genes), "\n")
Valid genes: 69 
cat("Missing genes:", invalid_genes, "\n\n")
Missing genes:  
# 2️⃣ Check duplicates in top5 list
gene_counts <- table(all_genes)
duplicate_genes <- names(gene_counts[gene_counts > 1])

if(length(duplicate_genes) > 0){
  cat("Genes appearing more than once in top5 list:\n")
  print(duplicate_genes)
} else {
  cat("No duplicates found in top5 list.\n")
}
Genes appearing more than once in top5 list:
[1] "TRAV17"
# Scale only the top5 marker genes
All_samples_Merged <- ScaleData(All_samples_Merged, features = unique(top5$gene))

  |                                                                                                            
  |                                                                                                      |   0%
  |                                                                                                            
  |======================================================================================================| 100%
 # DotPlot for top 5 markers
DotPlot(All_samples_Merged, features = unique(top5$gene), cols =
c("grey", "firebrick"), dot.scale = 8, assay = "RNA") + RotatedAxis()

3. Rename clusters (manual placeholder)


# 🔹 Cluster Annotation Table (0–13)
# Cluster   Top 5 Markers   Suggested Name  Reasoning
# 0 CTAG2, MACROD2, IMPG1, TUBA3C, AGMO Cancer/testis antigen–expressing malignant T cells  CTAG2 is a cancer/testis antigen; other markers (MACROD2, IMPG1) are associated with tumor-specific expression. Likely represents a malignant cluster with immunogenic features.
# 1 XCL1, XCL2, KIR2DL4, KRT81, IGFBP2  Cytotoxic/NK-like T cells   XCL1/2 are chemokines expressed by cytotoxic T cells; KIR2DL4 is an NK receptor; suggests cytotoxic, immune-interacting malignant subset.
# 2 CA2, IL13, HS3ST1, AC100801.1, C9orf135 Type 2 cytokine–expressing T cells / Th2-like malignant cells   IL13 indicates Th2-like phenotype; CA2 may mark metabolic adaptation; cluster likely represents Th2-skewed malignant cells.
# 3 RPS4Y1, LINC00861, LINC01550, TMIGD2, ARMH1 Ribosomal/translationally active T cells    RPS4Y1 is ribosomal; TMIGD2 is involved in T-cell costimulation; suggests highly active, proliferative subset.
# 4 AC096577.1, AC004160.1, PTPRD, MGST1, CLIC2 Malignant T cells with signaling/metabolic adaptation   PTPRD is a tumor suppressor often mutated in cancers; MGST1 and CLIC2 suggest oxidative stress or metabolic adaptation; likely malignant subset.
# 5 TTC29, VIPR2, HMGA2, ZNF521, ARHGEF28   Stem-like / progenitor-like malignant T cells   HMGA2 and ZNF521 are stemness-associated genes; TTC29 may indicate proliferative potential; cluster likely retains progenitor-like features.
# 6 THY1, CFI, RANBP17, AL023574.1, ALKAL2  Memory-like T cells / survival-oriented cluster THY1 is CD90 (memory marker); CFI involved in complement regulation; suggests memory-like or long-lived malignant T cells.
# 7 TRAV17, MXD3, KLHL4, SLC2A2, PSRC1  TCR-enriched / variable T-cell subset   TRAV17 is a TCR alpha variable gene; cluster likely reflects clonally expanded T cells; possibly malignant TCR-dominant population.
# 8 GPAT2, PTCHD1-AS, CTDSPL, LHX9, PRSS57  Developmental / early progenitor-like cluster   GPAT2 and PTCHD1-AS are testis or early developmental genes; may represent early differentiation or stem-like malignant cells.
# 9 TBX4, AC069410.1, PODXL2, NPTX1, LINC00469  Migratory / adhesion-oriented T cells   PODXL2 and TBX4 suggest migratory potential; possibly tissue-homing or trafficking T-cell subset.
# 10    IL7R, SESN3, PASK, AC006369.1, DUSP16   Naïve / central memory T cells  IL7R is canonical naïve/central memory marker; SESN3 and DUSP16 indicate survival and stress response; likely normal-like or less malignant T cells.
# 11    TRAV17, FUCA1, PTGDR2, TNFRSF18, S100P  Activated / regulatory-like T cells TNFRSF18 (GITR) indicates activation; S100P linked to stress response; TRAV17 suggests clonal expansion; cluster may have regulatory/activated features.
# 12    CCL3, CSF2, CCL1, SERPINE1, GZMB    Pro-inflammatory / cytotoxic T cells    CCL3/CCL1/CSF2 are cytokines; GZMB is cytotoxic; cluster likely represents inflammatory and cytotoxic subset.
# 13    OASL, IFIT3, IFIT2, CXCL10, CSAG3   Interferon-response / antiviral-like T cells    IFIT and OASL genes indicate strong interferon signaling; CXCL10 recruits T cells; suggests antiviral or inflammatory response in malignant T cells.
LS0tCnRpdGxlOiAiU8OpemFyeSBTeW5kcm9tZSBTaW5nbGUtQ2VsbCBSTkEtU2VxIE1hcmtlciBBbmFseXNpcy0xNS0wOS0yMDI1IgphdXRob3I6IE5hc2lyIE1haG1vb2QgQWJiYXNpCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogICNybWRmb3JtYXRzOjpyZWFkdGhlZG93bgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQotLS0KCgoKIyMgbG9hZCBsaWJyYXJpZXMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CgpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShtb25vY2xlMykKbGlicmFyeShTZXVyYXRXcmFwcGVycykKbGlicmFyeShNYXRyaXgpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkocGhlYXRtYXApCmxpYnJhcnkoU0NwdWJyKQoKc2V0LnNlZWQoMTIzNCkKYGBgCgoKIyAxLiBMb2FkIGFuZCBTdWJzZXQgTm9ybWFsIENENCBUIENlbGxzCmBgYHtyIGxvYWRTZXVyYXR9CgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gcmVhZFJEUygiLi4vMC1TZXVyYXRfUkRTX09CSkVDVF9GSU5BTC9TZXVyYXRfb2JqZWN0X0ZpbmFsX2NoYW5nZXMvQWxsX3NhbXBsZXNfTWVyZ2VkX3dpdGhfU1RDQVRfQW5ub3RhdGlvbl9maW5hbC01LTA5LTIwMjUucmRzIikKCgoKCmBgYAoKIyAyLiBSdW4gRmluZEFsbE1hcmtlcnMgb24gUk5BIEFzc2F5CmBgYHtyfQojIFNldCBhc3NheSB0byBSTkEKRGVmYXVsdEFzc2F5KEFsbF9zYW1wbGVzX01lcmdlZCkgPC0gIlJOQSIKCiMgQ2hlY2sgaWYgUk5BIGFzc2F5IGhhcyBub3JtYWxpemVkIGRhdGEKaWYgKCEiZGF0YSIgJWluJSBzbG90TmFtZXMoQWxsX3NhbXBsZXNfTWVyZ2VkW1siUk5BIl1dKSB8fCAKICAgIG5jb2woR2V0QXNzYXlEYXRhKEFsbF9zYW1wbGVzX01lcmdlZFtbIlJOQSJdXSwgc2xvdCA9ICJkYXRhIikpID09IDApIHsKICAKICBtZXNzYWdlKCJSTkEgYXNzYXkgZG9lcyBub3QgY29udGFpbiBub3JtYWxpemVkIGRhdGEuIFJ1bm5pbmcgTm9ybWFsaXplRGF0YS4uLiIpCiAgQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIE5vcm1hbGl6ZURhdGEoCiAgICBBbGxfc2FtcGxlc19NZXJnZWQsCiAgICBhc3NheSA9ICJSTkEiLAogICAgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiTG9nTm9ybWFsaXplIiwKICAgIHNjYWxlLmZhY3RvciA9IDEwMDAwCiAgKQogIAp9IGVsc2UgewogIG1lc3NhZ2UoIlJOQSBhc3NheSBhbHJlYWR5IGNvbnRhaW5zIG5vcm1hbGl6ZWQgZGF0YS4gU2tpcHBpbmcgbm9ybWFsaXphdGlvbi4iKQp9CgoKCklkZW50cyhBbGxfc2FtcGxlc19NZXJnZWQpIDwtICJzZXVyYXRfY2x1c3RlcnMiCgojIEZpbmQgbWFya2VycyBmb3IgYWxsIGNsdXN0ZXJzCmFsbF9tYXJrZXJzIDwtIEZpbmRBbGxNYXJrZXJzKAogIEFsbF9zYW1wbGVzX01lcmdlZCwKICBvbmx5LnBvcyA9IFRSVUUsCiAgbWluLnBjdCA9IDAuMjUsCiAgbG9nZmMudGhyZXNob2xkID0gMC4yNQopCgojIFNhdmUgbWFya2Vycwp3cml0ZS5jc3YoYWxsX21hcmtlcnMsICJBbGxNYXJrZXJzX2NsdXN0ZXJzLTE3LTA5LTIwMjUuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgpjYXQoIkZ1bGwgbWFya2VyIGxpc3Qgc2F2ZWQgdG8gQWxsTWFya2Vyc19jbHVzdGVycy0xNy0wOS0yMDI1LmNzdlxuIikKCmBgYAoKIyAzLiBUb3AgMjUgYW5kIFRvcCA1IG1hcmtlcnMgcGVyIGNsdXN0ZXIKYGBge3J9CgojIFRvcCAyNSBtYXJrZXJzIHBlciBjbHVzdGVyCnRvcDI1IDwtIGFsbF9tYXJrZXJzICU+JSBncm91cF9ieShjbHVzdGVyKSAlPiUgdG9wX24obiA9IDI1LCB3dCA9IGF2Z19sb2cyRkMpCndyaXRlLmNzdih0b3AyNSwgIlRvcDI1TWFya2Vyc19jbHVzdGVycy5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKCmNhdCgiVG9wIDI1IG1hcmtlciBsaXN0IHNhdmVkIHRvIFRvcDI1TWFya2Vyc19jbHVzdGVycy5jc3ZcbiIpCgojIFRvcCA1IG1hcmtlcnMgcGVyIGNsdXN0ZXIKdG9wNSA8LSBhbGxfbWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKG4gPSA1LCB3dCA9IGF2Z19sb2cyRkMpCndyaXRlLmNzdih0b3A1LCAiVG9wNU1hcmtlcnNfY2x1c3RlcnMuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgpjYXQoIlRvcCA1IG1hcmtlciBsaXN0IHNhdmVkIHRvIFRvcDVNYXJrZXJzX2NsdXN0ZXJzLmNzdlxuIikKCgoKYGBgCgojIDMuIFZpc3VhbGl6ZSBNYXJrZXJzCmBgYHtyLCBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0gMTh9CgpEZWZhdWx0QXNzYXkoQWxsX3NhbXBsZXNfTWVyZ2VkKSA8LSAiUk5BIgoKIyBVbmlxdWUgZ2VuZXMgZnJvbSB0b3A1CmFsbF9nZW5lcyA8LSB0b3A1JGdlbmUKCiMgMe+4j+KDoyBDaGVjayBvdmVybGFwIHdpdGggUk5BIGFzc2F5CnZhbGlkX2dlbmVzIDwtIGludGVyc2VjdCh1bmlxdWUoYWxsX2dlbmVzKSwgcm93bmFtZXMoQWxsX3NhbXBsZXNfTWVyZ2VkW1siUk5BIl1dKSkKaW52YWxpZF9nZW5lcyA8LSBzZXRkaWZmKHVuaXF1ZShhbGxfZ2VuZXMpLCByb3duYW1lcyhBbGxfc2FtcGxlc19NZXJnZWRbWyJSTkEiXV0pKQoKY2F0KCJWYWxpZCBnZW5lczoiLCBsZW5ndGgodmFsaWRfZ2VuZXMpLCAiXG4iKQpjYXQoIk1pc3NpbmcgZ2VuZXM6IiwgaW52YWxpZF9nZW5lcywgIlxuXG4iKQoKIyAy77iP4oOjIENoZWNrIGR1cGxpY2F0ZXMgaW4gdG9wNSBsaXN0CmdlbmVfY291bnRzIDwtIHRhYmxlKGFsbF9nZW5lcykKZHVwbGljYXRlX2dlbmVzIDwtIG5hbWVzKGdlbmVfY291bnRzW2dlbmVfY291bnRzID4gMV0pCgppZihsZW5ndGgoZHVwbGljYXRlX2dlbmVzKSA+IDApewogIGNhdCgiR2VuZXMgYXBwZWFyaW5nIG1vcmUgdGhhbiBvbmNlIGluIHRvcDUgbGlzdDpcbiIpCiAgcHJpbnQoZHVwbGljYXRlX2dlbmVzKQp9IGVsc2UgewogIGNhdCgiTm8gZHVwbGljYXRlcyBmb3VuZCBpbiB0b3A1IGxpc3QuXG4iKQp9CiMgU2NhbGUgb25seSB0aGUgdG9wNSBtYXJrZXIgZ2VuZXMKQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIFNjYWxlRGF0YShBbGxfc2FtcGxlc19NZXJnZWQsIGZlYXR1cmVzID0gdW5pcXVlKHRvcDUkZ2VuZSkpCgoKCiAjIERvdFBsb3QgZm9yIHRvcCA1IG1hcmtlcnMKRG90UGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIGZlYXR1cmVzID0gdW5pcXVlKHRvcDUkZ2VuZSksIGNvbHMgPQpjKCJncmV5IiwgImZpcmVicmljayIpLCBkb3Quc2NhbGUgPSA4LCBhc3NheSA9ICJSTkEiKSArIFJvdGF0ZWRBeGlzKCkKCmBgYAoKCiMgMy4gUmVuYW1lIGNsdXN0ZXJzIChtYW51YWwgcGxhY2Vob2xkZXIpCmBgYHtyfQoKIyDwn5S5IENsdXN0ZXIgQW5ub3RhdGlvbiBUYWJsZSAoMOKAkzEzKQojIENsdXN0ZXIJVG9wIDUgTWFya2VycwlTdWdnZXN0ZWQgTmFtZQlSZWFzb25pbmcKIyAwCUNUQUcyLCBNQUNST0QyLCBJTVBHMSwgVFVCQTNDLCBBR01PCUNhbmNlci90ZXN0aXMgYW50aWdlbuKAk2V4cHJlc3NpbmcgbWFsaWduYW50IFQgY2VsbHMJQ1RBRzIgaXMgYSBjYW5jZXIvdGVzdGlzIGFudGlnZW47IG90aGVyIG1hcmtlcnMgKE1BQ1JPRDIsIElNUEcxKSBhcmUgYXNzb2NpYXRlZCB3aXRoIHR1bW9yLXNwZWNpZmljIGV4cHJlc3Npb24uIExpa2VseSByZXByZXNlbnRzIGEgbWFsaWduYW50IGNsdXN0ZXIgd2l0aCBpbW11bm9nZW5pYyBmZWF0dXJlcy4KIyAxCVhDTDEsIFhDTDIsIEtJUjJETDQsIEtSVDgxLCBJR0ZCUDIJQ3l0b3RveGljL05LLWxpa2UgVCBjZWxscwlYQ0wxLzIgYXJlIGNoZW1va2luZXMgZXhwcmVzc2VkIGJ5IGN5dG90b3hpYyBUIGNlbGxzOyBLSVIyREw0IGlzIGFuIE5LIHJlY2VwdG9yOyBzdWdnZXN0cyBjeXRvdG94aWMsIGltbXVuZS1pbnRlcmFjdGluZyBtYWxpZ25hbnQgc3Vic2V0LgojIDIJQ0EyLCBJTDEzLCBIUzNTVDEsIEFDMTAwODAxLjEsIEM5b3JmMTM1CVR5cGUgMiBjeXRva2luZeKAk2V4cHJlc3NpbmcgVCBjZWxscyAvIFRoMi1saWtlIG1hbGlnbmFudCBjZWxscwlJTDEzIGluZGljYXRlcyBUaDItbGlrZSBwaGVub3R5cGU7IENBMiBtYXkgbWFyayBtZXRhYm9saWMgYWRhcHRhdGlvbjsgY2x1c3RlciBsaWtlbHkgcmVwcmVzZW50cyBUaDItc2tld2VkIG1hbGlnbmFudCBjZWxscy4KIyAzCVJQUzRZMSwgTElOQzAwODYxLCBMSU5DMDE1NTAsIFRNSUdEMiwgQVJNSDEJUmlib3NvbWFsL3RyYW5zbGF0aW9uYWxseSBhY3RpdmUgVCBjZWxscwlSUFM0WTEgaXMgcmlib3NvbWFsOyBUTUlHRDIgaXMgaW52b2x2ZWQgaW4gVC1jZWxsIGNvc3RpbXVsYXRpb247IHN1Z2dlc3RzIGhpZ2hseSBhY3RpdmUsIHByb2xpZmVyYXRpdmUgc3Vic2V0LgojIDQJQUMwOTY1NzcuMSwgQUMwMDQxNjAuMSwgUFRQUkQsIE1HU1QxLCBDTElDMglNYWxpZ25hbnQgVCBjZWxscyB3aXRoIHNpZ25hbGluZy9tZXRhYm9saWMgYWRhcHRhdGlvbglQVFBSRCBpcyBhIHR1bW9yIHN1cHByZXNzb3Igb2Z0ZW4gbXV0YXRlZCBpbiBjYW5jZXJzOyBNR1NUMSBhbmQgQ0xJQzIgc3VnZ2VzdCBveGlkYXRpdmUgc3RyZXNzIG9yIG1ldGFib2xpYyBhZGFwdGF0aW9uOyBsaWtlbHkgbWFsaWduYW50IHN1YnNldC4KIyA1CVRUQzI5LCBWSVBSMiwgSE1HQTIsIFpORjUyMSwgQVJIR0VGMjgJU3RlbS1saWtlIC8gcHJvZ2VuaXRvci1saWtlIG1hbGlnbmFudCBUIGNlbGxzCUhNR0EyIGFuZCBaTkY1MjEgYXJlIHN0ZW1uZXNzLWFzc29jaWF0ZWQgZ2VuZXM7IFRUQzI5IG1heSBpbmRpY2F0ZSBwcm9saWZlcmF0aXZlIHBvdGVudGlhbDsgY2x1c3RlciBsaWtlbHkgcmV0YWlucyBwcm9nZW5pdG9yLWxpa2UgZmVhdHVyZXMuCiMgNglUSFkxLCBDRkksIFJBTkJQMTcsIEFMMDIzNTc0LjEsIEFMS0FMMglNZW1vcnktbGlrZSBUIGNlbGxzIC8gc3Vydml2YWwtb3JpZW50ZWQgY2x1c3RlcglUSFkxIGlzIENEOTAgKG1lbW9yeSBtYXJrZXIpOyBDRkkgaW52b2x2ZWQgaW4gY29tcGxlbWVudCByZWd1bGF0aW9uOyBzdWdnZXN0cyBtZW1vcnktbGlrZSBvciBsb25nLWxpdmVkIG1hbGlnbmFudCBUIGNlbGxzLgojIDcJVFJBVjE3LCBNWEQzLCBLTEhMNCwgU0xDMkEyLCBQU1JDMQlUQ1ItZW5yaWNoZWQgLyB2YXJpYWJsZSBULWNlbGwgc3Vic2V0CVRSQVYxNyBpcyBhIFRDUiBhbHBoYSB2YXJpYWJsZSBnZW5lOyBjbHVzdGVyIGxpa2VseSByZWZsZWN0cyBjbG9uYWxseSBleHBhbmRlZCBUIGNlbGxzOyBwb3NzaWJseSBtYWxpZ25hbnQgVENSLWRvbWluYW50IHBvcHVsYXRpb24uCiMgOAlHUEFUMiwgUFRDSEQxLUFTLCBDVERTUEwsIExIWDksIFBSU1M1NwlEZXZlbG9wbWVudGFsIC8gZWFybHkgcHJvZ2VuaXRvci1saWtlIGNsdXN0ZXIJR1BBVDIgYW5kIFBUQ0hEMS1BUyBhcmUgdGVzdGlzIG9yIGVhcmx5IGRldmVsb3BtZW50YWwgZ2VuZXM7IG1heSByZXByZXNlbnQgZWFybHkgZGlmZmVyZW50aWF0aW9uIG9yIHN0ZW0tbGlrZSBtYWxpZ25hbnQgY2VsbHMuCiMgOQlUQlg0LCBBQzA2OTQxMC4xLCBQT0RYTDIsIE5QVFgxLCBMSU5DMDA0NjkJTWlncmF0b3J5IC8gYWRoZXNpb24tb3JpZW50ZWQgVCBjZWxscwlQT0RYTDIgYW5kIFRCWDQgc3VnZ2VzdCBtaWdyYXRvcnkgcG90ZW50aWFsOyBwb3NzaWJseSB0aXNzdWUtaG9taW5nIG9yIHRyYWZmaWNraW5nIFQtY2VsbCBzdWJzZXQuCiMgMTAJSUw3UiwgU0VTTjMsIFBBU0ssIEFDMDA2MzY5LjEsIERVU1AxNglOYcOvdmUgLyBjZW50cmFsIG1lbW9yeSBUIGNlbGxzCUlMN1IgaXMgY2Fub25pY2FsIG5hw692ZS9jZW50cmFsIG1lbW9yeSBtYXJrZXI7IFNFU04zIGFuZCBEVVNQMTYgaW5kaWNhdGUgc3Vydml2YWwgYW5kIHN0cmVzcyByZXNwb25zZTsgbGlrZWx5IG5vcm1hbC1saWtlIG9yIGxlc3MgbWFsaWduYW50IFQgY2VsbHMuCiMgMTEJVFJBVjE3LCBGVUNBMSwgUFRHRFIyLCBUTkZSU0YxOCwgUzEwMFAJQWN0aXZhdGVkIC8gcmVndWxhdG9yeS1saWtlIFQgY2VsbHMJVE5GUlNGMTggKEdJVFIpIGluZGljYXRlcyBhY3RpdmF0aW9uOyBTMTAwUCBsaW5rZWQgdG8gc3RyZXNzIHJlc3BvbnNlOyBUUkFWMTcgc3VnZ2VzdHMgY2xvbmFsIGV4cGFuc2lvbjsgY2x1c3RlciBtYXkgaGF2ZSByZWd1bGF0b3J5L2FjdGl2YXRlZCBmZWF0dXJlcy4KIyAxMglDQ0wzLCBDU0YyLCBDQ0wxLCBTRVJQSU5FMSwgR1pNQglQcm8taW5mbGFtbWF0b3J5IC8gY3l0b3RveGljIFQgY2VsbHMJQ0NMMy9DQ0wxL0NTRjIgYXJlIGN5dG9raW5lczsgR1pNQiBpcyBjeXRvdG94aWM7IGNsdXN0ZXIgbGlrZWx5IHJlcHJlc2VudHMgaW5mbGFtbWF0b3J5IGFuZCBjeXRvdG94aWMgc3Vic2V0LgojIDEzCU9BU0wsIElGSVQzLCBJRklUMiwgQ1hDTDEwLCBDU0FHMwlJbnRlcmZlcm9uLXJlc3BvbnNlIC8gYW50aXZpcmFsLWxpa2UgVCBjZWxscwlJRklUIGFuZCBPQVNMIGdlbmVzIGluZGljYXRlIHN0cm9uZyBpbnRlcmZlcm9uIHNpZ25hbGluZzsgQ1hDTDEwIHJlY3J1aXRzIFQgY2VsbHM7IHN1Z2dlc3RzIGFudGl2aXJhbCBvciBpbmZsYW1tYXRvcnkgcmVzcG9uc2UgaW4gbWFsaWduYW50IFQgY2VsbHMuCgpgYGAKCgoK