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 L2 cells
# Subset L2 cells
L2 <- subset(All_samples_Merged, subset = cell_line == "L2")
# Use SCT assay for both
DefaultAssay(reference_integrated) <- "SCT"
DefaultAssay(L2) <- "SCT"
# Make sure both have variable features set
if (length(VariableFeatures(reference_integrated)) == 0) {
reference_integrated <- FindVariableFeatures(reference_integrated, assay = "SCT", selection.method = "vst", nfeatures = 3000)
}
if (length(VariableFeatures(L2)) == 0) {
L2 <- FindVariableFeatures(L2, assay = "SCT", selection.method = "vst", nfeatures = 3000)
}
# Find anchors
anchors <- FindTransferAnchors(
reference = reference_integrated,
query = L2,
normalization.method = "SCT",
reference.reduction = "pca",
dims = 1:18
)
[1] "Given reference assay has multiple sct models, selecting model with most cells for finding transfer anchors"
reference_integrated <- RunUMAP(
reference_integrated,
reduction = "pca",
dims = 1:18,
assay = "SCT",
return.model = TRUE, # For Seurat v5, save.model = TRUE deprecated; use return.model
)
Using method 'umap'
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
# Map query onto reference and transfer pseudotime
mapped_L2 <- MapQuery(
anchorset = anchors,
query = L2,
reference = reference_integrated,
refdata = list(
pseudotime = reference_integrated$pseudotime,
seurat_clusters = reference_integrated$seurat_clusters,
Prediction = reference_integrated$Prediction,
predicted.celltype.l2 = reference_integrated$predicted.celltype.l2
),
reference.reduction = "pca",
reduction.model = "umap"
)
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
| | 0 % ~calculating
|++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=01s
Using method 'umap'
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
# 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 = L2[["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_L2$pseudotime <- pseudotime_vector
# Visualize pseudotime
FeaturePlot(mapped_L2,
features = "pseudotime",
reduction = "ref.umap",
cols = c("lightblue","red"),
label = TRUE) +
ggtitle("Pseudotime Mapping of L2 onto Reference") +
theme(plot.title = element_text(hjust = 0.5))

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

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

Mapping of L2 on Reference
library(ggplot2)
# Prepare reference data
ref_df <- data.frame(Embeddings(reference_integrated, "umap"))
ref_df$dataset <- "Reference"
# Prepare L2 query data
query_df <- data.frame(Embeddings(mapped_L2, "ref.umap"))
query_df$dataset <- "L2"
query_df$pseudotime <- mapped_L2$pseudotime # if pseudotime exists
# Plot reference in grey, L2 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("L2 cells projected onto reference UMAP") +
theme(plot.title = element_text(hjust = 0.5))

NA
NA
Mapping of L2 on Reference (Azimuth)
library(ggplot2)
# Reference coordinates (grey background)
ref_df <- data.frame(Embeddings(reference_integrated, "umap"))
ref_df$dataset <- "Reference"
# Query (L2) coordinates
query_df <- data.frame(Embeddings(mapped_L2, "ref.umap"))
query_df$dataset <- "L2"
# Make sure annotations exist in mapped_L2
query_df$celltype <- mapped_L2$predicted.celltype.l2 # or "Prediction"
# Plot reference in grey and L2 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("L2 cells projected onto reference UMAP with annotations") +
theme(plot.title = element_text(hjust = 0.5))

Mapping of L2 on Reference (STCAT)
library(ggplot2)
# Reference coordinates (grey background)
ref_df <- data.frame(Embeddings(reference_integrated, "umap"))
ref_df$dataset <- "Reference"
# Query (L2) coordinates
query_df <- data.frame(Embeddings(mapped_L2, "ref.umap"))
query_df$dataset <- "L2"
# Make sure annotations exist in mapped_L2
query_df$celltype <- mapped_L2$Prediction # or "Prediction"
# Plot reference in grey and L2 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("L2 cells projected onto reference UMAP with annotations") +
theme(plot.title = element_text(hjust = 0.5))

LS0tCnRpdGxlOiAiU3RlcDI6TDIgcHJvamVjdGlvbiBvZiBSZWZlcmVuY2VDRDRUY2VsbHMiCmF1dGhvcjogIk5hc2lyIE1haG1vb2QgQWJiYXNpIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMKICB3b3JkX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIGRmX3ByaW50OiBwYWdlZAogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKLS0tCgojIDEuIGxvYWQgbGlicmFyaWVzCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQoKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkobW9ub2NsZTMpCmxpYnJhcnkoU2V1cmF0V3JhcHBlcnMpCmxpYnJhcnkoaGFybW9ueSkKCgojIEV4dHJhIGxpYnJhcmllcwpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHBoZWF0bWFwKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoTWF0cml4KQpsaWJyYXJ5KHBhdGNod29yaykKCgpzZXQuc2VlZCgxMjM0KQoKYGBgCgoKIyAyLiBSZWFkIG9iamVjdCB3aXRoIGFsbCBzYW1wbGVzCmBgYHtyIH0KCkFsbF9zYW1wbGVzX01lcmdlZCA8LSByZWFkUkRTKCIuLi8uLi8wLVNldXJhdF9SRFNfT0JKRUNUX0ZJTkFML0FsbF9zYW1wbGVzX01lcmdlZF93aXRoX1NUQ0FUX2FuZF9yZW5hbWVkX0ZJTkFMLnJkcyIpCgoKYGBgCgojIDMuIFJlYWQgb2JqZWN0IHdpdGggYWxsIFJlZmVyZW5jZV9DRDRUY2VsbHMKYGBge3IgfQoKIHJlZmVyZW5jZV9pbnRlZ3JhdGVkIDwtIHJlYWRSRFMoIlN0ZXAxX3NlemFyeV9jZWxsX2xpbmVzX21hcHBlZF90b19jZDRfcmVmZXJlbmNlX2ludGVncmF0ZWRfYmVmb3JlX1F1ZXJ5X1Byb2plY3Rpb25fMDMtMDktMjAyNS5yZHMiKQoKCmBgYAoKCiMjIFRyYWplY3RvcnkgYW5kIFBzZXVkb3RpbWUgd2l0aCBNb25vY2xlMwpgYGB7cn0KcmVmZXJlbmNlX2ludGVncmF0ZWQkcHNldWRvdGltZVshaXMuZmluaXRlKHJlZmVyZW5jZV9pbnRlZ3JhdGVkJHBzZXVkb3RpbWUpXSA8LSBOQQoKCm1heF9maW5pdGUgPC0gbWF4KHJlZmVyZW5jZV9pbnRlZ3JhdGVkJHBzZXVkb3RpbWUsIG5hLnJtID0gVFJVRSkKcmVmZXJlbmNlX2ludGVncmF0ZWQkcHNldWRvdGltZVshaXMuZmluaXRlKHJlZmVyZW5jZV9pbnRlZ3JhdGVkJHBzZXVkb3RpbWUpXSA8LSBtYXhfZmluaXRlCgpzdW1tYXJ5KHJlZmVyZW5jZV9pbnRlZ3JhdGVkJHBzZXVkb3RpbWUpCnRhYmxlKGlzLmZpbml0ZShyZWZlcmVuY2VfaW50ZWdyYXRlZCRwc2V1ZG90aW1lKSkKCkZlYXR1cmVQbG90KAogIHJlZmVyZW5jZV9pbnRlZ3JhdGVkLAogIGZlYXR1cmVzID0gInBzZXVkb3RpbWUiLAogIHJlZHVjdGlvbiA9ICJ1bWFwIiwKICBjb2xzID0gYygibGlnaHRibHVlIiwgInJlZCIpLAogIGxhYmVsID0gVFJVRQopICsgZ2d0aXRsZSgiVU1BUCBvZiBJbnRlZ3JhdGVkIENENOKBuiBUIENlbGxzIGJ5IFBzZXVkb3RpbWUiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCgoKYGBgCiMjIFRyYWplY3RvcnkgYW5kIFBzZXVkb3RpbWUgd2l0aCBNb25vY2xlMwpgYGB7cn0KCgojIFZpc3VhbGl6ZSBVTUFQIGNvbG9yZWQgYnkgb3JpZ2luYWwgZG9ub3IgKGNlbGxfbGluZSkKRGltUGxvdChyZWZlcmVuY2VfaW50ZWdyYXRlZCwgZ3JvdXAuYnkgPSAiUHJlZGljdGlvbiIsIHJlZHVjdGlvbiA9ICJ1bWFwIikgKwogIGdndGl0bGUoIlVNQVAgb2YgSW50ZWdyYXRlZCBDRDTigbogVCBDZWxscyIpCgojIFZpc3VhbGl6ZSBVTUFQIGNvbG9yZWQgYnkgb3JpZ2luYWwgZG9ub3IgKGNlbGxfbGluZSkKRGltUGxvdChyZWZlcmVuY2VfaW50ZWdyYXRlZCwgZ3JvdXAuYnkgPSAicHJlZGljdGVkLmNlbGx0eXBlLmwyIiwgcmVkdWN0aW9uID0gInVtYXAiKSArCiAgZ2d0aXRsZSgiVU1BUCBvZiBJbnRlZ3JhdGVkIENENOKBuiBUIENlbGxzIikKCmBgYAoKIyAzLiBTdWJzZXQgTDIgY2VsbHMKYGBge3IgfQoKIyBTdWJzZXQgTDIgY2VsbHMKTDIgPC0gc3Vic2V0KEFsbF9zYW1wbGVzX01lcmdlZCwgc3Vic2V0ID0gY2VsbF9saW5lID09ICJMMiIpCgoKIyBVc2UgU0NUIGFzc2F5IGZvciBib3RoCkRlZmF1bHRBc3NheShyZWZlcmVuY2VfaW50ZWdyYXRlZCkgPC0gIlNDVCIKRGVmYXVsdEFzc2F5KEwyKSA8LSAiU0NUIgoKCiMgTWFrZSBzdXJlIGJvdGggaGF2ZSB2YXJpYWJsZSBmZWF0dXJlcyBzZXQKaWYgKGxlbmd0aChWYXJpYWJsZUZlYXR1cmVzKHJlZmVyZW5jZV9pbnRlZ3JhdGVkKSkgPT0gMCkgewogIHJlZmVyZW5jZV9pbnRlZ3JhdGVkIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKHJlZmVyZW5jZV9pbnRlZ3JhdGVkLCBhc3NheSA9ICJTQ1QiLCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDMwMDApCn0KaWYgKGxlbmd0aChWYXJpYWJsZUZlYXR1cmVzKEwyKSkgPT0gMCkgewogIEwyIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKEwyLCBhc3NheSA9ICJTQ1QiLCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDMwMDApCn0KCiMgRmluZCBhbmNob3JzCmFuY2hvcnMgPC0gRmluZFRyYW5zZmVyQW5jaG9ycygKICByZWZlcmVuY2UgPSByZWZlcmVuY2VfaW50ZWdyYXRlZCwKICBxdWVyeSA9IEwyLAogIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIlNDVCIsCiAgcmVmZXJlbmNlLnJlZHVjdGlvbiA9ICJwY2EiLAogIGRpbXMgPSAxOjE4CikKCnJlZmVyZW5jZV9pbnRlZ3JhdGVkIDwtIFJ1blVNQVAoCiAgcmVmZXJlbmNlX2ludGVncmF0ZWQsCiAgcmVkdWN0aW9uID0gInBjYSIsCiAgZGltcyA9IDE6MTgsCiAgYXNzYXkgPSAiU0NUIiwKICByZXR1cm4ubW9kZWwgPSBUUlVFLCAgICMgRm9yIFNldXJhdCB2NSwgc2F2ZS5tb2RlbCA9IFRSVUUgZGVwcmVjYXRlZDsgdXNlIHJldHVybi5tb2RlbAopCgoKIyBNYXAgcXVlcnkgb250byByZWZlcmVuY2UgYW5kIHRyYW5zZmVyIHBzZXVkb3RpbWUKbWFwcGVkX0wyIDwtIE1hcFF1ZXJ5KAogIGFuY2hvcnNldCA9IGFuY2hvcnMsCiAgcXVlcnkgPSBMMiwKICByZWZlcmVuY2UgPSByZWZlcmVuY2VfaW50ZWdyYXRlZCwKICByZWZkYXRhID0gbGlzdCgKICAgIHBzZXVkb3RpbWUgPSByZWZlcmVuY2VfaW50ZWdyYXRlZCRwc2V1ZG90aW1lLAogICAgc2V1cmF0X2NsdXN0ZXJzID0gcmVmZXJlbmNlX2ludGVncmF0ZWQkc2V1cmF0X2NsdXN0ZXJzLAogICAgUHJlZGljdGlvbiA9IHJlZmVyZW5jZV9pbnRlZ3JhdGVkJFByZWRpY3Rpb24sCiAgICBwcmVkaWN0ZWQuY2VsbHR5cGUubDIgPSByZWZlcmVuY2VfaW50ZWdyYXRlZCRwcmVkaWN0ZWQuY2VsbHR5cGUubDIKICApLAogIHJlZmVyZW5jZS5yZWR1Y3Rpb24gPSAicGNhIiwKICByZWR1Y3Rpb24ubW9kZWwgPSAidW1hcCIKKQoKIyBDb252ZXJ0IG51bWVyaWMgcHNldWRvdGltZSB2ZWN0b3IgaW50byBhIDEtcm93IG1hdHJpeCB3aXRoIHJvd25hbWUKcHNldWRvX21hdCA8LSBtYXRyaXgocmVmZXJlbmNlX2ludGVncmF0ZWQkcHNldWRvdGltZSwgbnJvdyA9IDEpCmNvbG5hbWVzKHBzZXVkb19tYXQpIDwtIGNvbG5hbWVzKHJlZmVyZW5jZV9pbnRlZ3JhdGVkKSAgIyBjZWxscwpyb3duYW1lcyhwc2V1ZG9fbWF0KSA8LSAicHNldWRvdGltZSIgICAgICAgICAgICAgICAgICAgICAjIGZlYXR1cmUgbmFtZQoKIyBUcmFuc2ZlciBudW1lcmljIHBzZXVkb3RpbWUKcHNldWRvdGltZV90cmFuc2ZlciA8LSBUcmFuc2ZlckRhdGEoCiAgYW5jaG9yc2V0ID0gYW5jaG9ycywKICByZWZkYXRhID0gcHNldWRvX21hdCwKICB3ZWlnaHQucmVkdWN0aW9uID0gTDJbWyJwY2EiXV0sCiAgZGltcyA9IDE6MTgKKQoKIyBFeHRyYWN0IHRoZSBkYXRhIGZyb20gdGhlIGFzc2F5CnBzZXVkb3RpbWVfdmVjdG9yIDwtIEdldEFzc2F5RGF0YShwc2V1ZG90aW1lX3RyYW5zZmVyLCBzbG90ID0gImRhdGEiKVsicHNldWRvdGltZSIsIF0KCiMgQWRkIHRvIG1ldGFkYXRhCm1hcHBlZF9MMiRwc2V1ZG90aW1lIDwtIHBzZXVkb3RpbWVfdmVjdG9yCgojICBWaXN1YWxpemUgcHNldWRvdGltZQpGZWF0dXJlUGxvdChtYXBwZWRfTDIsCiAgICAgICAgICAgIGZlYXR1cmVzID0gInBzZXVkb3RpbWUiLAogICAgICAgICAgICByZWR1Y3Rpb24gPSAicmVmLnVtYXAiLAogICAgICAgICAgICBjb2xzID0gYygibGlnaHRibHVlIiwicmVkIiksCiAgICAgICAgICAgIGxhYmVsID0gVFJVRSkgKwogIGdndGl0bGUoIlBzZXVkb3RpbWUgTWFwcGluZyBvZiBMMiBvbnRvIFJlZmVyZW5jZSIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCiMgIFZpc3VhbGl6ZSB0cmFuc2ZlcnJlZCBjZWxsIHR5cGUgYW5ub3RhdGlvbnMKRGltUGxvdChtYXBwZWRfTDIsIGdyb3VwLmJ5ID0gIlByZWRpY3Rpb24iLCByZWR1Y3Rpb24gPSAicmVmLnVtYXAiKSArCiAgZ2d0aXRsZSgiTWFwcGVkIEwyOiBQcmVkaWN0aW9uIEFubm90YXRpb25zIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQoKRGltUGxvdChtYXBwZWRfTDIsIGdyb3VwLmJ5ID0gInByZWRpY3RlZC5jZWxsdHlwZS5sMiIsIHJlZHVjdGlvbiA9ICJyZWYudW1hcCIpICsKICBnZ3RpdGxlKCJNYXBwZWQgTDI6IHByZWRpY3RlZC5jZWxsdHlwZS5sMiBBbm5vdGF0aW9ucyIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCmBgYAojIyBNYXBwaW5nIG9mIEwyIG9uIFJlZmVyZW5jZQpgYGB7cn0KCgpsaWJyYXJ5KGdncGxvdDIpCgojIFByZXBhcmUgcmVmZXJlbmNlIGRhdGEKcmVmX2RmIDwtIGRhdGEuZnJhbWUoRW1iZWRkaW5ncyhyZWZlcmVuY2VfaW50ZWdyYXRlZCwgInVtYXAiKSkKcmVmX2RmJGRhdGFzZXQgPC0gIlJlZmVyZW5jZSIKCiMgUHJlcGFyZSBMMiBxdWVyeSBkYXRhCnF1ZXJ5X2RmIDwtIGRhdGEuZnJhbWUoRW1iZWRkaW5ncyhtYXBwZWRfTDIsICJyZWYudW1hcCIpKQpxdWVyeV9kZiRkYXRhc2V0IDwtICJMMiIKcXVlcnlfZGYkcHNldWRvdGltZSA8LSBtYXBwZWRfTDIkcHNldWRvdGltZSAgIyBpZiBwc2V1ZG90aW1lIGV4aXN0cwoKIyBQbG90IHJlZmVyZW5jZSBpbiBncmV5LCBMMiBjZWxscyBjb2xvcmVkIGJ5IHBzZXVkb3RpbWUKZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHJlZl9kZiwgYWVzKHggPSB1bWFwXzEsIHkgPSB1bWFwXzIpLAogICAgICAgICAgICAgY29sb3IgPSAiZ3JleTgwIiwgc2l6ZSA9IDAuNSkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHF1ZXJ5X2RmLCBhZXMoeCA9IHJlZlVNQVBfMSwgeSA9IHJlZlVNQVBfMiwgY29sb3IgPSBwc2V1ZG90aW1lKSwKICAgICAgICAgICAgIHNpemUgPSAxKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gImxpZ2h0Ymx1ZSIsIGhpZ2ggPSAicmVkIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgZ2d0aXRsZSgiTDIgY2VsbHMgcHJvamVjdGVkIG9udG8gcmVmZXJlbmNlIFVNQVAiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCgoKYGBgCiMjIE1hcHBpbmcgb2YgTDIgb24gUmVmZXJlbmNlIChBemltdXRoKQpgYGB7cn0KCmxpYnJhcnkoZ2dwbG90MikKCiMgUmVmZXJlbmNlIGNvb3JkaW5hdGVzIChncmV5IGJhY2tncm91bmQpCnJlZl9kZiA8LSBkYXRhLmZyYW1lKEVtYmVkZGluZ3MocmVmZXJlbmNlX2ludGVncmF0ZWQsICJ1bWFwIikpCnJlZl9kZiRkYXRhc2V0IDwtICJSZWZlcmVuY2UiCgojIFF1ZXJ5IChMMikgY29vcmRpbmF0ZXMKcXVlcnlfZGYgPC0gZGF0YS5mcmFtZShFbWJlZGRpbmdzKG1hcHBlZF9MMiwgInJlZi51bWFwIikpCnF1ZXJ5X2RmJGRhdGFzZXQgPC0gIkwyIgoKIyBNYWtlIHN1cmUgYW5ub3RhdGlvbnMgZXhpc3QgaW4gbWFwcGVkX0wyCnF1ZXJ5X2RmJGNlbGx0eXBlIDwtIG1hcHBlZF9MMiRwcmVkaWN0ZWQuY2VsbHR5cGUubDIgICMgb3IgIlByZWRpY3Rpb24iCgojIFBsb3QgcmVmZXJlbmNlIGluIGdyZXkgYW5kIEwyIGNlbGxzIGNvbG9yZWQgYnkgYW5ub3RhdGlvbgpnZ3Bsb3QoKSArCiAgZ2VvbV9wb2ludChkYXRhID0gcmVmX2RmLCBhZXMoeCA9IHVtYXBfMSwgeSA9IHVtYXBfMiksCiAgICAgICAgICAgICBjb2xvciA9ICJncmV5ODAiLCBzaXplID0gMC41KSArCiAgZ2VvbV9wb2ludChkYXRhID0gcXVlcnlfZGYsIGFlcyh4ID0gcmVmVU1BUF8xLCB5ID0gcmVmVU1BUF8yLCBjb2xvciA9IGNlbGx0eXBlKSwKICAgICAgICAgICAgIHNpemUgPSAxKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGdndGl0bGUoIkwyIGNlbGxzIHByb2plY3RlZCBvbnRvIHJlZmVyZW5jZSBVTUFQIHdpdGggYW5ub3RhdGlvbnMiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCgpgYGAKCiMjIE1hcHBpbmcgb2YgTDIgb24gUmVmZXJlbmNlIChTVENBVCkKYGBge3J9CgpsaWJyYXJ5KGdncGxvdDIpCgojIFJlZmVyZW5jZSBjb29yZGluYXRlcyAoZ3JleSBiYWNrZ3JvdW5kKQpyZWZfZGYgPC0gZGF0YS5mcmFtZShFbWJlZGRpbmdzKHJlZmVyZW5jZV9pbnRlZ3JhdGVkLCAidW1hcCIpKQpyZWZfZGYkZGF0YXNldCA8LSAiUmVmZXJlbmNlIgoKIyBRdWVyeSAoTDIpIGNvb3JkaW5hdGVzCnF1ZXJ5X2RmIDwtIGRhdGEuZnJhbWUoRW1iZWRkaW5ncyhtYXBwZWRfTDIsICJyZWYudW1hcCIpKQpxdWVyeV9kZiRkYXRhc2V0IDwtICJMMiIKCiMgTWFrZSBzdXJlIGFubm90YXRpb25zIGV4aXN0IGluIG1hcHBlZF9MMgpxdWVyeV9kZiRjZWxsdHlwZSA8LSBtYXBwZWRfTDIkUHJlZGljdGlvbiAgIyBvciAiUHJlZGljdGlvbiIKCiMgUGxvdCByZWZlcmVuY2UgaW4gZ3JleSBhbmQgTDIgY2VsbHMgY29sb3JlZCBieSBhbm5vdGF0aW9uCmdncGxvdCgpICsKICBnZW9tX3BvaW50KGRhdGEgPSByZWZfZGYsIGFlcyh4ID0gdW1hcF8xLCB5ID0gdW1hcF8yKSwKICAgICAgICAgICAgIGNvbG9yID0gImdyZXk4MCIsIHNpemUgPSAwLjUpICsKICBnZW9tX3BvaW50KGRhdGEgPSBxdWVyeV9kZiwgYWVzKHggPSByZWZVTUFQXzEsIHkgPSByZWZVTUFQXzIsIGNvbG9yID0gY2VsbHR5cGUpLAogICAgICAgICAgICAgc2l6ZSA9IDEpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJTZXQxIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgZ2d0aXRsZSgiTDIgY2VsbHMgcHJvamVjdGVkIG9udG8gcmVmZXJlbmNlIFVNQVAgd2l0aCBhbm5vdGF0aW9ucyIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCmBgYAoKIyA0LiBTdWJzZXQgTDIgUHJvamVjdGlvbgpgYGB7ciBzYXZlZmluYWx9CgojIDEuIERlZmluZSBvdXRwdXQgZGlyZWN0b3J5Cm91dF9kaXIgPC0gInJlc3VsdHMvTDJfcHJvamVjdGlvbiIKaWYoIWRpci5leGlzdHMob3V0X2RpcikpIGRpci5jcmVhdGUob3V0X2RpciwgcmVjdXJzaXZlID0gVFJVRSkKCnNhdmUobWFwcGVkX0wyLCBmaWxlID0gZmlsZS5wYXRoKG91dF9kaXIsICJMMl9tYXBwZWRfb25fcmVmZXJlbmNlX3dpdGhfcHNldWRvdGltZS0zLTgtMjAyNS5Sb2JqIikpCgoKYGBgCgoK