1. load libraries

2. Read object with all samples


All_samples_Merged <- readRDS("../../0-Seurat_RDS_OBJECT_FINAL/All_samples_Merged_with_STCAT_and_renamed_FINAL.rds")

3. Read object with all Reference_CD4Tcells


 reference_integrated <- readRDS("Step1_sezary_cell_lines_mapped_to_cd4_reference_integrated_before_Query_Projection_03-09-2025.rds")

Trajectory and Pseudotime with Monocle3

reference_integrated$pseudotime[!is.finite(reference_integrated$pseudotime)] <- NA


max_finite <- max(reference_integrated$pseudotime, na.rm = TRUE)
reference_integrated$pseudotime[!is.finite(reference_integrated$pseudotime)] <- max_finite

summary(reference_integrated$pseudotime)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
0.00000 0.01969 0.19290 0.93865 0.90736 5.63665 
table(is.finite(reference_integrated$pseudotime))

TRUE 
8610 
FeaturePlot(
  reference_integrated,
  features = "pseudotime",
  reduction = "umap",
  cols = c("lightblue", "red"),
  label = TRUE
) + ggtitle("UMAP of Integrated CD4⁺ T Cells by Pseudotime") +
  theme(plot.title = element_text(hjust = 0.5))

NA
NA

Trajectory and Pseudotime with Monocle3



# Visualize UMAP colored by original donor (cell_line)
DimPlot(reference_integrated, group.by = "Prediction", reduction = "umap") +
  ggtitle("UMAP of Integrated CD4⁺ T Cells")


# Visualize UMAP colored by original donor (cell_line)
DimPlot(reference_integrated, group.by = "predicted.celltype.l2", reduction = "umap") +
  ggtitle("UMAP of Integrated CD4⁺ T Cells")

3. Subset L1 cells

# Convert numeric pseudotime vector into a 1-row matrix with rowname
pseudo_mat <- matrix(reference_integrated$pseudotime, nrow = 1)
colnames(pseudo_mat) <- colnames(reference_integrated)  # cells
rownames(pseudo_mat) <- "pseudotime"                     # feature name

# Transfer numeric pseudotime
pseudotime_transfer <- TransferData(
  anchorset = anchors,
  refdata = pseudo_mat,
  weight.reduction = L1[["pca"]],
  dims = 1:18
)
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
# Extract the data from the assay
pseudotime_vector <- GetAssayData(pseudotime_transfer, slot = "data")["pseudotime", ]

# Add to metadata
mapped_L1$pseudotime <- pseudotime_vector

#  Visualize pseudotime
FeaturePlot(mapped_L1,
            features = "pseudotime",
            reduction = "ref.umap",
            cols = c("lightblue","red"),
            label = TRUE) +
  ggtitle("Pseudotime Mapping of L1 onto Reference") +
  theme(plot.title = element_text(hjust = 0.5))


#  Visualize transferred cell type annotations
DimPlot(mapped_L1, group.by = "Prediction", reduction = "ref.umap") +
  ggtitle("Mapped L1: Prediction Annotations") +
  theme(plot.title = element_text(hjust = 0.5))


DimPlot(mapped_L1, group.by = "predicted.celltype.l2", reduction = "ref.umap") +
  ggtitle("Mapped L1: predicted.celltype.l2 Annotations") +
  theme(plot.title = element_text(hjust = 0.5))

Mapping of L1 on Reference



library(ggplot2)

# Prepare reference data
ref_df <- data.frame(Embeddings(reference_integrated, "umap"))
ref_df$dataset <- "Reference"

# Prepare L1 query data
query_df <- data.frame(Embeddings(mapped_L1, "ref.umap"))
query_df$dataset <- "L1"
query_df$pseudotime <- mapped_L1$pseudotime  # if pseudotime exists

# Plot reference in grey, L1 cells colored by pseudotime
ggplot() +
  geom_point(data = ref_df, aes(x = umap_1, y = umap_2),
             color = "grey80", size = 0.5) +
  geom_point(data = query_df, aes(x = refUMAP_1, y = refUMAP_2, color = pseudotime),
             size = 1) +
  scale_color_gradient(low = "lightblue", high = "red") +
  theme_classic() +
  ggtitle("L1 cells projected onto reference UMAP") +
  theme(plot.title = element_text(hjust = 0.5))

NA
NA

Mapping of L1 on Reference (Azimuth)


library(ggplot2)

# Reference coordinates (grey background)
ref_df <- data.frame(Embeddings(reference_integrated, "umap"))
ref_df$dataset <- "Reference"

# Query (L1) coordinates
query_df <- data.frame(Embeddings(mapped_L1, "ref.umap"))
query_df$dataset <- "L1"

# Make sure annotations exist in mapped_L1
query_df$celltype <- mapped_L1$predicted.celltype.l2  # or "Prediction"

# Plot reference in grey and L1 cells colored by annotation
ggplot() +
  geom_point(data = ref_df, aes(x = umap_1, y = umap_2),
             color = "grey80", size = 0.5) +
  geom_point(data = query_df, aes(x = refUMAP_1, y = refUMAP_2, color = celltype),
             size = 1) +
  scale_color_brewer(palette = "Set1") +
  theme_classic() +
  ggtitle("L1 cells projected onto reference UMAP with annotations") +
  theme(plot.title = element_text(hjust = 0.5))

Mapping of L1 on Reference (STCAT)


library(ggplot2)

# Reference coordinates (grey background)
ref_df <- data.frame(Embeddings(reference_integrated, "umap"))
ref_df$dataset <- "Reference"

# Query (L1) coordinates
query_df <- data.frame(Embeddings(mapped_L1, "ref.umap"))
query_df$dataset <- "L1"

# Make sure annotations exist in mapped_L1
query_df$celltype <- mapped_L1$Prediction  # or "Prediction"

# Plot reference in grey and L1 cells colored by annotation
ggplot() +
  geom_point(data = ref_df, aes(x = umap_1, y = umap_2),
             color = "grey80", size = 0.5) +
  geom_point(data = query_df, aes(x = refUMAP_1, y = refUMAP_2, color = celltype),
             size = 1) +
  scale_color_brewer(palette = "Set1") +
  theme_classic() +
  ggtitle("L1 cells projected onto reference UMAP with annotations") +
  theme(plot.title = element_text(hjust = 0.5))

4. Subset L1 Projection



save(mapped_L1, file = file.path(out_dir, "L1_mapped_on_reference_with_pseudotime-3-8-2025.Robj"))
LS0tCnRpdGxlOiAiU3RlcDI6TDEgcHJvamVjdGlvbiBvZiBSZWZlcmVuY2VDRDRUY2VsbHMiCmF1dGhvcjogIk5hc2lyIE1haG1vb2QgQWJiYXNpIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMKICB3b3JkX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIGRmX3ByaW50OiBwYWdlZAogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKLS0tCgojIDEuIGxvYWQgbGlicmFyaWVzCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQoKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkobW9ub2NsZTMpCmxpYnJhcnkoU2V1cmF0V3JhcHBlcnMpCmxpYnJhcnkoaGFybW9ueSkKCgojIEV4dHJhIGxpYnJhcmllcwpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHBoZWF0bWFwKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoTWF0cml4KQpsaWJyYXJ5KHBhdGNod29yaykKCgpzZXQuc2VlZCgxMjM0KQoKYGBgCgoKIyAyLiBSZWFkIG9iamVjdCB3aXRoIGFsbCBzYW1wbGVzCmBgYHtyIH0KCkFsbF9zYW1wbGVzX01lcmdlZCA8LSByZWFkUkRTKCIuLi8uLi8wLVNldXJhdF9SRFNfT0JKRUNUX0ZJTkFML0FsbF9zYW1wbGVzX01lcmdlZF93aXRoX1NUQ0FUX2FuZF9yZW5hbWVkX0ZJTkFMLnJkcyIpCgoKYGBgCgojIDMuIFJlYWQgb2JqZWN0IHdpdGggYWxsIFJlZmVyZW5jZV9DRDRUY2VsbHMKYGBge3IgfQoKIHJlZmVyZW5jZV9pbnRlZ3JhdGVkIDwtIHJlYWRSRFMoIlN0ZXAxX3NlemFyeV9jZWxsX2xpbmVzX21hcHBlZF90b19jZDRfcmVmZXJlbmNlX2ludGVncmF0ZWRfYmVmb3JlX1F1ZXJ5X1Byb2plY3Rpb25fMDMtMDktMjAyNS5yZHMiKQoKCmBgYAoKCiMjIFRyYWplY3RvcnkgYW5kIFBzZXVkb3RpbWUgd2l0aCBNb25vY2xlMwpgYGB7cn0KcmVmZXJlbmNlX2ludGVncmF0ZWQkcHNldWRvdGltZVshaXMuZmluaXRlKHJlZmVyZW5jZV9pbnRlZ3JhdGVkJHBzZXVkb3RpbWUpXSA8LSBOQQoKCm1heF9maW5pdGUgPC0gbWF4KHJlZmVyZW5jZV9pbnRlZ3JhdGVkJHBzZXVkb3RpbWUsIG5hLnJtID0gVFJVRSkKcmVmZXJlbmNlX2ludGVncmF0ZWQkcHNldWRvdGltZVshaXMuZmluaXRlKHJlZmVyZW5jZV9pbnRlZ3JhdGVkJHBzZXVkb3RpbWUpXSA8LSBtYXhfZmluaXRlCgpzdW1tYXJ5KHJlZmVyZW5jZV9pbnRlZ3JhdGVkJHBzZXVkb3RpbWUpCnRhYmxlKGlzLmZpbml0ZShyZWZlcmVuY2VfaW50ZWdyYXRlZCRwc2V1ZG90aW1lKSkKCkZlYXR1cmVQbG90KAogIHJlZmVyZW5jZV9pbnRlZ3JhdGVkLAogIGZlYXR1cmVzID0gInBzZXVkb3RpbWUiLAogIHJlZHVjdGlvbiA9ICJ1bWFwIiwKICBjb2xzID0gYygibGlnaHRibHVlIiwgInJlZCIpLAogIGxhYmVsID0gVFJVRQopICsgZ2d0aXRsZSgiVU1BUCBvZiBJbnRlZ3JhdGVkIENENOKBuiBUIENlbGxzIGJ5IFBzZXVkb3RpbWUiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCgoKYGBgCiMjIFRyYWplY3RvcnkgYW5kIFBzZXVkb3RpbWUgd2l0aCBNb25vY2xlMwpgYGB7cn0KCgojIFZpc3VhbGl6ZSBVTUFQIGNvbG9yZWQgYnkgb3JpZ2luYWwgZG9ub3IgKGNlbGxfbGluZSkKRGltUGxvdChyZWZlcmVuY2VfaW50ZWdyYXRlZCwgZ3JvdXAuYnkgPSAiUHJlZGljdGlvbiIsIHJlZHVjdGlvbiA9ICJ1bWFwIikgKwogIGdndGl0bGUoIlVNQVAgb2YgSW50ZWdyYXRlZCBDRDTigbogVCBDZWxscyIpCgojIFZpc3VhbGl6ZSBVTUFQIGNvbG9yZWQgYnkgb3JpZ2luYWwgZG9ub3IgKGNlbGxfbGluZSkKRGltUGxvdChyZWZlcmVuY2VfaW50ZWdyYXRlZCwgZ3JvdXAuYnkgPSAicHJlZGljdGVkLmNlbGx0eXBlLmwyIiwgcmVkdWN0aW9uID0gInVtYXAiKSArCiAgZ2d0aXRsZSgiVU1BUCBvZiBJbnRlZ3JhdGVkIENENOKBuiBUIENlbGxzIikKCmBgYAoKIyAzLiBTdWJzZXQgTDEgY2VsbHMKYGBge3IgfQoKIyBTdWJzZXQgTDEgY2VsbHMKTDEgPC0gc3Vic2V0KEFsbF9zYW1wbGVzX01lcmdlZCwgc3Vic2V0ID0gY2VsbF9saW5lID09ICJMMSIpCgoKIyBVc2UgU0NUIGFzc2F5IGZvciBib3RoCkRlZmF1bHRBc3NheShyZWZlcmVuY2VfaW50ZWdyYXRlZCkgPC0gIlNDVCIKRGVmYXVsdEFzc2F5KEwxKSA8LSAiU0NUIgoKCiMgTWFrZSBzdXJlIGJvdGggaGF2ZSB2YXJpYWJsZSBmZWF0dXJlcyBzZXQKaWYgKGxlbmd0aChWYXJpYWJsZUZlYXR1cmVzKHJlZmVyZW5jZV9pbnRlZ3JhdGVkKSkgPT0gMCkgewogIHJlZmVyZW5jZV9pbnRlZ3JhdGVkIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKHJlZmVyZW5jZV9pbnRlZ3JhdGVkLCBhc3NheSA9ICJTQ1QiLCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDMwMDApCn0KaWYgKGxlbmd0aChWYXJpYWJsZUZlYXR1cmVzKEwxKSkgPT0gMCkgewogIEwxIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKEwxLCBhc3NheSA9ICJTQ1QiLCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDMwMDApCn0KCiMgRmluZCBhbmNob3JzCmFuY2hvcnMgPC0gRmluZFRyYW5zZmVyQW5jaG9ycygKICByZWZlcmVuY2UgPSByZWZlcmVuY2VfaW50ZWdyYXRlZCwKICBxdWVyeSA9IEwxLAogIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIlNDVCIsCiAgcmVmZXJlbmNlLnJlZHVjdGlvbiA9ICJwY2EiLAogIGRpbXMgPSAxOjE4CikKCnJlZmVyZW5jZV9pbnRlZ3JhdGVkIDwtIFJ1blVNQVAoCiAgcmVmZXJlbmNlX2ludGVncmF0ZWQsCiAgcmVkdWN0aW9uID0gInBjYSIsCiAgZGltcyA9IDE6MTgsCiAgYXNzYXkgPSAiU0NUIiwKICByZXR1cm4ubW9kZWwgPSBUUlVFLCAgICMgRm9yIFNldXJhdCB2NSwgc2F2ZS5tb2RlbCA9IFRSVUUgZGVwcmVjYXRlZDsgdXNlIHJldHVybi5tb2RlbAopCgoKIyBNYXAgcXVlcnkgb250byByZWZlcmVuY2UgYW5kIHRyYW5zZmVyIHBzZXVkb3RpbWUKbWFwcGVkX0wxIDwtIE1hcFF1ZXJ5KAogIGFuY2hvcnNldCA9IGFuY2hvcnMsCiAgcXVlcnkgPSBMMSwKICByZWZlcmVuY2UgPSByZWZlcmVuY2VfaW50ZWdyYXRlZCwKICByZWZkYXRhID0gbGlzdCgKICAgIHBzZXVkb3RpbWUgPSByZWZlcmVuY2VfaW50ZWdyYXRlZCRwc2V1ZG90aW1lLAogICAgc2V1cmF0X2NsdXN0ZXJzID0gcmVmZXJlbmNlX2ludGVncmF0ZWQkc2V1cmF0X2NsdXN0ZXJzLAogICAgUHJlZGljdGlvbiA9IHJlZmVyZW5jZV9pbnRlZ3JhdGVkJFByZWRpY3Rpb24sCiAgICBwcmVkaWN0ZWQuY2VsbHR5cGUubDIgPSByZWZlcmVuY2VfaW50ZWdyYXRlZCRwcmVkaWN0ZWQuY2VsbHR5cGUubDIKICApLAogIHJlZmVyZW5jZS5yZWR1Y3Rpb24gPSAicGNhIiwKICByZWR1Y3Rpb24ubW9kZWwgPSAidW1hcCIKKQoKIyBDb252ZXJ0IG51bWVyaWMgcHNldWRvdGltZSB2ZWN0b3IgaW50byBhIDEtcm93IG1hdHJpeCB3aXRoIHJvd25hbWUKcHNldWRvX21hdCA8LSBtYXRyaXgocmVmZXJlbmNlX2ludGVncmF0ZWQkcHNldWRvdGltZSwgbnJvdyA9IDEpCmNvbG5hbWVzKHBzZXVkb19tYXQpIDwtIGNvbG5hbWVzKHJlZmVyZW5jZV9pbnRlZ3JhdGVkKSAgIyBjZWxscwpyb3duYW1lcyhwc2V1ZG9fbWF0KSA8LSAicHNldWRvdGltZSIgICAgICAgICAgICAgICAgICAgICAjIGZlYXR1cmUgbmFtZQoKIyBUcmFuc2ZlciBudW1lcmljIHBzZXVkb3RpbWUKcHNldWRvdGltZV90cmFuc2ZlciA8LSBUcmFuc2ZlckRhdGEoCiAgYW5jaG9yc2V0ID0gYW5jaG9ycywKICByZWZkYXRhID0gcHNldWRvX21hdCwKICB3ZWlnaHQucmVkdWN0aW9uID0gTDFbWyJwY2EiXV0sCiAgZGltcyA9IDE6MTgKKQoKIyBFeHRyYWN0IHRoZSBkYXRhIGZyb20gdGhlIGFzc2F5CnBzZXVkb3RpbWVfdmVjdG9yIDwtIEdldEFzc2F5RGF0YShwc2V1ZG90aW1lX3RyYW5zZmVyLCBzbG90ID0gImRhdGEiKVsicHNldWRvdGltZSIsIF0KCiMgQWRkIHRvIG1ldGFkYXRhCm1hcHBlZF9MMSRwc2V1ZG90aW1lIDwtIHBzZXVkb3RpbWVfdmVjdG9yCgojICBWaXN1YWxpemUgcHNldWRvdGltZQpGZWF0dXJlUGxvdChtYXBwZWRfTDEsCiAgICAgICAgICAgIGZlYXR1cmVzID0gInBzZXVkb3RpbWUiLAogICAgICAgICAgICByZWR1Y3Rpb24gPSAicmVmLnVtYXAiLAogICAgICAgICAgICBjb2xzID0gYygibGlnaHRibHVlIiwicmVkIiksCiAgICAgICAgICAgIGxhYmVsID0gVFJVRSkgKwogIGdndGl0bGUoIlBzZXVkb3RpbWUgTWFwcGluZyBvZiBMMSBvbnRvIFJlZmVyZW5jZSIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCiMgIFZpc3VhbGl6ZSB0cmFuc2ZlcnJlZCBjZWxsIHR5cGUgYW5ub3RhdGlvbnMKRGltUGxvdChtYXBwZWRfTDEsIGdyb3VwLmJ5ID0gIlByZWRpY3Rpb24iLCByZWR1Y3Rpb24gPSAicmVmLnVtYXAiKSArCiAgZ2d0aXRsZSgiTWFwcGVkIEwxOiBQcmVkaWN0aW9uIEFubm90YXRpb25zIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQoKRGltUGxvdChtYXBwZWRfTDEsIGdyb3VwLmJ5ID0gInByZWRpY3RlZC5jZWxsdHlwZS5sMiIsIHJlZHVjdGlvbiA9ICJyZWYudW1hcCIpICsKICBnZ3RpdGxlKCJNYXBwZWQgTDE6IHByZWRpY3RlZC5jZWxsdHlwZS5sMiBBbm5vdGF0aW9ucyIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCmBgYAojIyBNYXBwaW5nIG9mIEwxIG9uIFJlZmVyZW5jZQpgYGB7cn0KCgpsaWJyYXJ5KGdncGxvdDIpCgojIFByZXBhcmUgcmVmZXJlbmNlIGRhdGEKcmVmX2RmIDwtIGRhdGEuZnJhbWUoRW1iZWRkaW5ncyhyZWZlcmVuY2VfaW50ZWdyYXRlZCwgInVtYXAiKSkKcmVmX2RmJGRhdGFzZXQgPC0gIlJlZmVyZW5jZSIKCiMgUHJlcGFyZSBMMSBxdWVyeSBkYXRhCnF1ZXJ5X2RmIDwtIGRhdGEuZnJhbWUoRW1iZWRkaW5ncyhtYXBwZWRfTDEsICJyZWYudW1hcCIpKQpxdWVyeV9kZiRkYXRhc2V0IDwtICJMMSIKcXVlcnlfZGYkcHNldWRvdGltZSA8LSBtYXBwZWRfTDEkcHNldWRvdGltZSAgIyBpZiBwc2V1ZG90aW1lIGV4aXN0cwoKIyBQbG90IHJlZmVyZW5jZSBpbiBncmV5LCBMMSBjZWxscyBjb2xvcmVkIGJ5IHBzZXVkb3RpbWUKZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHJlZl9kZiwgYWVzKHggPSB1bWFwXzEsIHkgPSB1bWFwXzIpLAogICAgICAgICAgICAgY29sb3IgPSAiZ3JleTgwIiwgc2l6ZSA9IDAuNSkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHF1ZXJ5X2RmLCBhZXMoeCA9IHJlZlVNQVBfMSwgeSA9IHJlZlVNQVBfMiwgY29sb3IgPSBwc2V1ZG90aW1lKSwKICAgICAgICAgICAgIHNpemUgPSAxKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gImxpZ2h0Ymx1ZSIsIGhpZ2ggPSAicmVkIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgZ2d0aXRsZSgiTDEgY2VsbHMgcHJvamVjdGVkIG9udG8gcmVmZXJlbmNlIFVNQVAiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCgoKYGBgCiMjIE1hcHBpbmcgb2YgTDEgb24gUmVmZXJlbmNlIChBemltdXRoKQpgYGB7cn0KCmxpYnJhcnkoZ2dwbG90MikKCiMgUmVmZXJlbmNlIGNvb3JkaW5hdGVzIChncmV5IGJhY2tncm91bmQpCnJlZl9kZiA8LSBkYXRhLmZyYW1lKEVtYmVkZGluZ3MocmVmZXJlbmNlX2ludGVncmF0ZWQsICJ1bWFwIikpCnJlZl9kZiRkYXRhc2V0IDwtICJSZWZlcmVuY2UiCgojIFF1ZXJ5IChMMSkgY29vcmRpbmF0ZXMKcXVlcnlfZGYgPC0gZGF0YS5mcmFtZShFbWJlZGRpbmdzKG1hcHBlZF9MMSwgInJlZi51bWFwIikpCnF1ZXJ5X2RmJGRhdGFzZXQgPC0gIkwxIgoKIyBNYWtlIHN1cmUgYW5ub3RhdGlvbnMgZXhpc3QgaW4gbWFwcGVkX0wxCnF1ZXJ5X2RmJGNlbGx0eXBlIDwtIG1hcHBlZF9MMSRwcmVkaWN0ZWQuY2VsbHR5cGUubDIgICMgb3IgIlByZWRpY3Rpb24iCgojIFBsb3QgcmVmZXJlbmNlIGluIGdyZXkgYW5kIEwxIGNlbGxzIGNvbG9yZWQgYnkgYW5ub3RhdGlvbgpnZ3Bsb3QoKSArCiAgZ2VvbV9wb2ludChkYXRhID0gcmVmX2RmLCBhZXMoeCA9IHVtYXBfMSwgeSA9IHVtYXBfMiksCiAgICAgICAgICAgICBjb2xvciA9ICJncmV5ODAiLCBzaXplID0gMC41KSArCiAgZ2VvbV9wb2ludChkYXRhID0gcXVlcnlfZGYsIGFlcyh4ID0gcmVmVU1BUF8xLCB5ID0gcmVmVU1BUF8yLCBjb2xvciA9IGNlbGx0eXBlKSwKICAgICAgICAgICAgIHNpemUgPSAxKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGdndGl0bGUoIkwxIGNlbGxzIHByb2plY3RlZCBvbnRvIHJlZmVyZW5jZSBVTUFQIHdpdGggYW5ub3RhdGlvbnMiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCgpgYGAKCiMjIE1hcHBpbmcgb2YgTDEgb24gUmVmZXJlbmNlIChTVENBVCkKYGBge3J9CgpsaWJyYXJ5KGdncGxvdDIpCgojIFJlZmVyZW5jZSBjb29yZGluYXRlcyAoZ3JleSBiYWNrZ3JvdW5kKQpyZWZfZGYgPC0gZGF0YS5mcmFtZShFbWJlZGRpbmdzKHJlZmVyZW5jZV9pbnRlZ3JhdGVkLCAidW1hcCIpKQpyZWZfZGYkZGF0YXNldCA8LSAiUmVmZXJlbmNlIgoKIyBRdWVyeSAoTDEpIGNvb3JkaW5hdGVzCnF1ZXJ5X2RmIDwtIGRhdGEuZnJhbWUoRW1iZWRkaW5ncyhtYXBwZWRfTDEsICJyZWYudW1hcCIpKQpxdWVyeV9kZiRkYXRhc2V0IDwtICJMMSIKCiMgTWFrZSBzdXJlIGFubm90YXRpb25zIGV4aXN0IGluIG1hcHBlZF9MMQpxdWVyeV9kZiRjZWxsdHlwZSA8LSBtYXBwZWRfTDEkUHJlZGljdGlvbiAgIyBvciAiUHJlZGljdGlvbiIKCiMgUGxvdCByZWZlcmVuY2UgaW4gZ3JleSBhbmQgTDEgY2VsbHMgY29sb3JlZCBieSBhbm5vdGF0aW9uCmdncGxvdCgpICsKICBnZW9tX3BvaW50KGRhdGEgPSByZWZfZGYsIGFlcyh4ID0gdW1hcF8xLCB5ID0gdW1hcF8yKSwKICAgICAgICAgICAgIGNvbG9yID0gImdyZXk4MCIsIHNpemUgPSAwLjUpICsKICBnZW9tX3BvaW50KGRhdGEgPSBxdWVyeV9kZiwgYWVzKHggPSByZWZVTUFQXzEsIHkgPSByZWZVTUFQXzIsIGNvbG9yID0gY2VsbHR5cGUpLAogICAgICAgICAgICAgc2l6ZSA9IDEpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJTZXQxIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgZ2d0aXRsZSgiTDEgY2VsbHMgcHJvamVjdGVkIG9udG8gcmVmZXJlbmNlIFVNQVAgd2l0aCBhbm5vdGF0aW9ucyIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCmBgYAoKIyA0LiBTdWJzZXQgTDEgUHJvamVjdGlvbgpgYGB7ciBzYXZlZmluYWx9CgojIDEuIERlZmluZSBvdXRwdXQgZGlyZWN0b3J5Cm91dF9kaXIgPC0gInJlc3VsdHMvTDFfcHJvamVjdGlvbiIKaWYoIWRpci5leGlzdHMob3V0X2RpcikpIGRpci5jcmVhdGUob3V0X2RpciwgcmVjdXJzaXZlID0gVFJVRSkKCnNhdmUobWFwcGVkX0wxLCBmaWxlID0gZmlsZS5wYXRoKG91dF9kaXIsICJMMV9tYXBwZWRfb25fcmVmZXJlbmNlX3dpdGhfcHNldWRvdGltZS0zLTgtMjAyNS5Sb2JqIikpCgoKYGBgCgoK