4. Subset MalignantCD4T cells
# Subset MalignantCD4T cells
MalignantCD4T <- subset(All_samples_Merged, subset = Group == "MalignantCD4T")
# Use SCT assay for both
DefaultAssay(reference_integrated) <- "SCT"
DefaultAssay(MalignantCD4T) <- "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(MalignantCD4T)) == 0) {
MalignantCD4T <- FindVariableFeatures(MalignantCD4T, assay = "SCT", selection.method = "vst", nfeatures = 3000)
}
# Find anchors
anchors <- FindTransferAnchors(
reference = reference_integrated,
query = MalignantCD4T,
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"
gc()
used (Mb) gc trigger (Mb) max used (Mb)
Ncells 8828727 471.6 15971052 853.0 15971052 853.0
Vcells 2508768160 19140.4 4750680560 36244.9 3958833800 30203.6
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_MalignantCD4T <- MapQuery(
anchorset = anchors,
query = MalignantCD4T,
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=03s
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 = MalignantCD4T[["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_MalignantCD4T$pseudotime <- pseudotime_vector
# Visualize pseudotime
FeaturePlot(mapped_MalignantCD4T,
features = "pseudotime",
reduction = "ref.umap",
cols = c("lightblue","red"),
label = TRUE) +
ggtitle("Pseudotime Mapping of MalignantCD4T onto Reference") +
theme(plot.title = element_text(hjust = 0.5))

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

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

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

NA
NA
Mapping of MalignantCD4T on Reference (Azimuth)
library(ggplot2)
# Reference coordinates (grey background)
ref_df <- data.frame(Embeddings(reference_integrated, "umap"))
ref_df$dataset <- "Reference"
# Query (MalignantCD4T) coordinates
query_df <- data.frame(Embeddings(mapped_MalignantCD4T, "ref.umap"))
query_df$dataset <- "MalignantCD4T"
# Make sure annotations exist in mapped_MalignantCD4T
query_df$celltype <- mapped_MalignantCD4T$predicted.celltype.l2 # or "Prediction"
library(RColorBrewer)
big_palette <- colorRampPalette(brewer.pal(12, "Paired"))(20)
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_manual(values = big_palette) +
theme_classic() +
ggtitle("MalignantCD4T cells projected onto reference UMAP with annotations") +
theme(plot.title = element_text(hjust = 0.5))

NA
NA
Mapping of MalignantCD4T on Reference (STCAT)
library(ggplot2)
# Reference coordinates (grey background)
ref_df <- data.frame(Embeddings(reference_integrated, "umap"))
ref_df$dataset <- "Reference"
# Query (MalignantCD4T) coordinates
query_df <- data.frame(Embeddings(mapped_MalignantCD4T, "ref.umap"))
query_df$dataset <- "MalignantCD4T"
# Make sure annotations exist in mapped_MalignantCD4T
query_df$celltype <- mapped_MalignantCD4T$Prediction # or "Prediction"
library(RColorBrewer)
# Get a palette with up to 20 colors
big_palette <- colorRampPalette(brewer.pal(12, "Paired"))(20)
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_manual(values = big_palette) +
theme_classic() +
ggtitle("MalignantCD4T cells projected onto reference UMAP with annotations") +
theme(plot.title = element_text(hjust = 0.5))

NA
NA
LS0tCnRpdGxlOiAiU3RlcDI6TWFsaWduYW50Q0Q0VCBwcm9qZWN0aW9uIG9mIFJlZmVyZW5jZUNENFRjZWxscyIKYXV0aG9yOiAiTmFzaXIgTWFobW9vZCBBYmJhc2kiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIHRvY19jb2xsYXBzZWQ6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwotLS0KCiMgMS4gbG9hZCBsaWJyYXJpZXMKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CgpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShtb25vY2xlMykKbGlicmFyeShTZXVyYXRXcmFwcGVycykKbGlicmFyeShoYXJtb255KQoKCiMgRXh0cmEgbGlicmFyaWVzCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocGhlYXRtYXApCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShNYXRyaXgpCmxpYnJhcnkocGF0Y2h3b3JrKQoKCnNldC5zZWVkKDEyMzQpCgpgYGAKCgojIDIuIFJlYWQgb2JqZWN0IHdpdGggYWxsIHNhbXBsZXMKYGBge3IgfQoKQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIHJlYWRSRFMoIi4uLy4uLzAtU2V1cmF0X1JEU19PQkpFQ1RfRklOQUwvQWxsX3NhbXBsZXNfTWVyZ2VkX3dpdGhfU1RDQVRfYW5kX3JlbmFtZWRfRklOQUwucmRzIikKCiMgQWRkICJncm91cCIgY29sdW1uIHRvIG1ldGFkYXRhCkFsbF9zYW1wbGVzX01lcmdlZCRHcm91cCA8LSBpZmVsc2UoQWxsX3NhbXBsZXNfTWVyZ2VkJGNlbGxfbGluZSAlaW4lIHBhc3RlMCgiTCIsIDE6NyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1hbGlnbmFudENENFQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKEFsbF9zYW1wbGVzX01lcmdlZCRjZWxsX2xpbmUgJWluJSBjKCJDRDRUY2VsbHNfbGFiIiwgIkNENFRjZWxsc18xMHgiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9ybWFsQ0Q0VCIsICJPdGhlciIpKQoKdGFibGUoQWxsX3NhbXBsZXNfTWVyZ2VkJEdyb3VwKQoKCgpgYGAKCiMgMy4gUmVhZCBvYmplY3Qgd2l0aCBhbGwgUmVmZXJlbmNlX0NENFRjZWxscwpgYGB7ciB9CgogcmVmZXJlbmNlX2ludGVncmF0ZWQgPC0gcmVhZFJEUygiU3RlcDFfc2V6YXJ5X2NlbGxfbGluZXNfbWFwcGVkX3RvX2NkNF9yZWZlcmVuY2VfaW50ZWdyYXRlZF9iZWZvcmVfUXVlcnlfUHJvamVjdGlvbl8wMy0wOS0yMDI1LnJkcyIpCgoKYGBgCgoKIyMgVHJhamVjdG9yeSBhbmQgUHNldWRvdGltZSB3aXRoIE1vbm9jbGUzCmBgYHtyfQpyZWZlcmVuY2VfaW50ZWdyYXRlZCRwc2V1ZG90aW1lWyFpcy5maW5pdGUocmVmZXJlbmNlX2ludGVncmF0ZWQkcHNldWRvdGltZSldIDwtIE5BCgoKbWF4X2Zpbml0ZSA8LSBtYXgocmVmZXJlbmNlX2ludGVncmF0ZWQkcHNldWRvdGltZSwgbmEucm0gPSBUUlVFKQpyZWZlcmVuY2VfaW50ZWdyYXRlZCRwc2V1ZG90aW1lWyFpcy5maW5pdGUocmVmZXJlbmNlX2ludGVncmF0ZWQkcHNldWRvdGltZSldIDwtIG1heF9maW5pdGUKCnN1bW1hcnkocmVmZXJlbmNlX2ludGVncmF0ZWQkcHNldWRvdGltZSkKdGFibGUoaXMuZmluaXRlKHJlZmVyZW5jZV9pbnRlZ3JhdGVkJHBzZXVkb3RpbWUpKQoKRmVhdHVyZVBsb3QoCiAgcmVmZXJlbmNlX2ludGVncmF0ZWQsCiAgZmVhdHVyZXMgPSAicHNldWRvdGltZSIsCiAgcmVkdWN0aW9uID0gInVtYXAiLAogIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksCiAgbGFiZWwgPSBUUlVFCikgKyBnZ3RpdGxlKCJVTUFQIG9mIEludGVncmF0ZWQgQ0Q04oG6IFQgQ2VsbHMgYnkgUHNldWRvdGltZSIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCgpgYGAKIyMgVHJhamVjdG9yeSBhbmQgUHNldWRvdGltZSB3aXRoIE1vbm9jbGUzCmBgYHtyfQoKCiMgVmlzdWFsaXplIFVNQVAgY29sb3JlZCBieSBvcmlnaW5hbCBkb25vciAoY2VsbF9saW5lKQpEaW1QbG90KHJlZmVyZW5jZV9pbnRlZ3JhdGVkLCBncm91cC5ieSA9ICJQcmVkaWN0aW9uIiwgcmVkdWN0aW9uID0gInVtYXAiKSArCiAgZ2d0aXRsZSgiVU1BUCBvZiBJbnRlZ3JhdGVkIENENOKBuiBUIENlbGxzIikKCiMgVmlzdWFsaXplIFVNQVAgY29sb3JlZCBieSBvcmlnaW5hbCBkb25vciAoY2VsbF9saW5lKQpEaW1QbG90KHJlZmVyZW5jZV9pbnRlZ3JhdGVkLCBncm91cC5ieSA9ICJwcmVkaWN0ZWQuY2VsbHR5cGUubDIiLCByZWR1Y3Rpb24gPSAidW1hcCIpICsKICBnZ3RpdGxlKCJVTUFQIG9mIEludGVncmF0ZWQgQ0Q04oG6IFQgQ2VsbHMiKQoKYGBgCgojIDQuIFN1YnNldCBNYWxpZ25hbnRDRDRUIGNlbGxzCmBgYHtyIH0KCiMgU3Vic2V0IE1hbGlnbmFudENENFQgY2VsbHMKTWFsaWduYW50Q0Q0VCA8LSBzdWJzZXQoQWxsX3NhbXBsZXNfTWVyZ2VkLCBzdWJzZXQgPSBHcm91cCA9PSAiTWFsaWduYW50Q0Q0VCIpCgoKIyBVc2UgU0NUIGFzc2F5IGZvciBib3RoCkRlZmF1bHRBc3NheShyZWZlcmVuY2VfaW50ZWdyYXRlZCkgPC0gIlNDVCIKRGVmYXVsdEFzc2F5KE1hbGlnbmFudENENFQpIDwtICJTQ1QiCgoKIyBNYWtlIHN1cmUgYm90aCBoYXZlIHZhcmlhYmxlIGZlYXR1cmVzIHNldAppZiAobGVuZ3RoKFZhcmlhYmxlRmVhdHVyZXMocmVmZXJlbmNlX2ludGVncmF0ZWQpKSA9PSAwKSB7CiAgcmVmZXJlbmNlX2ludGVncmF0ZWQgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMocmVmZXJlbmNlX2ludGVncmF0ZWQsIGFzc2F5ID0gIlNDVCIsIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMzAwMCkKfQppZiAobGVuZ3RoKFZhcmlhYmxlRmVhdHVyZXMoTWFsaWduYW50Q0Q0VCkpID09IDApIHsKICBNYWxpZ25hbnRDRDRUIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKE1hbGlnbmFudENENFQsIGFzc2F5ID0gIlNDVCIsIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMzAwMCkKfQoKIyBGaW5kIGFuY2hvcnMKYW5jaG9ycyA8LSBGaW5kVHJhbnNmZXJBbmNob3JzKAogIHJlZmVyZW5jZSA9IHJlZmVyZW5jZV9pbnRlZ3JhdGVkLAogIHF1ZXJ5ID0gTWFsaWduYW50Q0Q0VCwKICBub3JtYWxpemF0aW9uLm1ldGhvZCA9ICJTQ1QiLAogIHJlZmVyZW5jZS5yZWR1Y3Rpb24gPSAicGNhIiwKICBkaW1zID0gMToxOAopCgpyZWZlcmVuY2VfaW50ZWdyYXRlZCA8LSBSdW5VTUFQKAogIHJlZmVyZW5jZV9pbnRlZ3JhdGVkLAogIHJlZHVjdGlvbiA9ICJwY2EiLAogIGRpbXMgPSAxOjE4LAogIGFzc2F5ID0gIlNDVCIsCiAgcmV0dXJuLm1vZGVsID0gVFJVRSwgICAjIEZvciBTZXVyYXQgdjUsIHNhdmUubW9kZWwgPSBUUlVFIGRlcHJlY2F0ZWQ7IHVzZSByZXR1cm4ubW9kZWwKKQoKCiMgTWFwIHF1ZXJ5IG9udG8gcmVmZXJlbmNlIGFuZCB0cmFuc2ZlciBwc2V1ZG90aW1lCm1hcHBlZF9NYWxpZ25hbnRDRDRUIDwtIE1hcFF1ZXJ5KAogIGFuY2hvcnNldCA9IGFuY2hvcnMsCiAgcXVlcnkgPSBNYWxpZ25hbnRDRDRULAogIHJlZmVyZW5jZSA9IHJlZmVyZW5jZV9pbnRlZ3JhdGVkLAogIHJlZmRhdGEgPSBsaXN0KAogICAgcHNldWRvdGltZSA9IHJlZmVyZW5jZV9pbnRlZ3JhdGVkJHBzZXVkb3RpbWUsCiAgICBzZXVyYXRfY2x1c3RlcnMgPSByZWZlcmVuY2VfaW50ZWdyYXRlZCRzZXVyYXRfY2x1c3RlcnMsCiAgICBQcmVkaWN0aW9uID0gcmVmZXJlbmNlX2ludGVncmF0ZWQkUHJlZGljdGlvbiwKICAgIHByZWRpY3RlZC5jZWxsdHlwZS5sMiA9IHJlZmVyZW5jZV9pbnRlZ3JhdGVkJHByZWRpY3RlZC5jZWxsdHlwZS5sMgogICksCiAgcmVmZXJlbmNlLnJlZHVjdGlvbiA9ICJwY2EiLAogIHJlZHVjdGlvbi5tb2RlbCA9ICJ1bWFwIgopCgojIENvbnZlcnQgbnVtZXJpYyBwc2V1ZG90aW1lIHZlY3RvciBpbnRvIGEgMS1yb3cgbWF0cml4IHdpdGggcm93bmFtZQpwc2V1ZG9fbWF0IDwtIG1hdHJpeChyZWZlcmVuY2VfaW50ZWdyYXRlZCRwc2V1ZG90aW1lLCBucm93ID0gMSkKY29sbmFtZXMocHNldWRvX21hdCkgPC0gY29sbmFtZXMocmVmZXJlbmNlX2ludGVncmF0ZWQpICAjIGNlbGxzCnJvd25hbWVzKHBzZXVkb19tYXQpIDwtICJwc2V1ZG90aW1lIiAgICAgICAgICAgICAgICAgICAgICMgZmVhdHVyZSBuYW1lCgojIFRyYW5zZmVyIG51bWVyaWMgcHNldWRvdGltZQpwc2V1ZG90aW1lX3RyYW5zZmVyIDwtIFRyYW5zZmVyRGF0YSgKICBhbmNob3JzZXQgPSBhbmNob3JzLAogIHJlZmRhdGEgPSBwc2V1ZG9fbWF0LAogIHdlaWdodC5yZWR1Y3Rpb24gPSBNYWxpZ25hbnRDRDRUW1sicGNhIl1dLAogIGRpbXMgPSAxOjE4CikKCiMgRXh0cmFjdCB0aGUgZGF0YSBmcm9tIHRoZSBhc3NheQpwc2V1ZG90aW1lX3ZlY3RvciA8LSBHZXRBc3NheURhdGEocHNldWRvdGltZV90cmFuc2Zlciwgc2xvdCA9ICJkYXRhIilbInBzZXVkb3RpbWUiLCBdCgojIEFkZCB0byBtZXRhZGF0YQptYXBwZWRfTWFsaWduYW50Q0Q0VCRwc2V1ZG90aW1lIDwtIHBzZXVkb3RpbWVfdmVjdG9yCgojICBWaXN1YWxpemUgcHNldWRvdGltZQpGZWF0dXJlUGxvdChtYXBwZWRfTWFsaWduYW50Q0Q0VCwKICAgICAgICAgICAgZmVhdHVyZXMgPSAicHNldWRvdGltZSIsCiAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJyZWYudW1hcCIsCiAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCJyZWQiKSwKICAgICAgICAgICAgbGFiZWwgPSBUUlVFKSArCiAgZ2d0aXRsZSgiUHNldWRvdGltZSBNYXBwaW5nIG9mIE1hbGlnbmFudENENFQgb250byBSZWZlcmVuY2UiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCgojICBWaXN1YWxpemUgdHJhbnNmZXJyZWQgY2VsbCB0eXBlIGFubm90YXRpb25zCkRpbVBsb3QobWFwcGVkX01hbGlnbmFudENENFQsIGdyb3VwLmJ5ID0gIlByZWRpY3Rpb24iLCByZWR1Y3Rpb24gPSAicmVmLnVtYXAiKSArCiAgZ2d0aXRsZSgiTWFwcGVkIE1hbGlnbmFudENENFQ6IFByZWRpY3Rpb24gQW5ub3RhdGlvbnMiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCgpEaW1QbG90KG1hcHBlZF9NYWxpZ25hbnRDRDRULCBncm91cC5ieSA9ICJwcmVkaWN0ZWQuY2VsbHR5cGUubDIiLCByZWR1Y3Rpb24gPSAicmVmLnVtYXAiKSArCiAgZ2d0aXRsZSgiTWFwcGVkIE1hbGlnbmFudENENFQ6IHByZWRpY3RlZC5jZWxsdHlwZS5sMiBBbm5vdGF0aW9ucyIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCmBgYAojIyBNYXBwaW5nIG9mIE1hbGlnbmFudENENFQgb24gUmVmZXJlbmNlCmBgYHtyfQoKCmxpYnJhcnkoZ2dwbG90MikKCiMgUHJlcGFyZSByZWZlcmVuY2UgZGF0YQpyZWZfZGYgPC0gZGF0YS5mcmFtZShFbWJlZGRpbmdzKHJlZmVyZW5jZV9pbnRlZ3JhdGVkLCAidW1hcCIpKQpyZWZfZGYkZGF0YXNldCA8LSAiUmVmZXJlbmNlIgoKIyBQcmVwYXJlIE1hbGlnbmFudENENFQgcXVlcnkgZGF0YQpxdWVyeV9kZiA8LSBkYXRhLmZyYW1lKEVtYmVkZGluZ3MobWFwcGVkX01hbGlnbmFudENENFQsICJyZWYudW1hcCIpKQpxdWVyeV9kZiRkYXRhc2V0IDwtICJNYWxpZ25hbnRDRDRUIgpxdWVyeV9kZiRwc2V1ZG90aW1lIDwtIG1hcHBlZF9NYWxpZ25hbnRDRDRUJHBzZXVkb3RpbWUgICMgaWYgcHNldWRvdGltZSBleGlzdHMKCiMgUGxvdCByZWZlcmVuY2UgaW4gZ3JleSwgTWFsaWduYW50Q0Q0VCBjZWxscyBjb2xvcmVkIGJ5IHBzZXVkb3RpbWUKZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHJlZl9kZiwgYWVzKHggPSB1bWFwXzEsIHkgPSB1bWFwXzIpLAogICAgICAgICAgICAgY29sb3IgPSAiZ3JleTgwIiwgc2l6ZSA9IDAuNSkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHF1ZXJ5X2RmLCBhZXMoeCA9IHJlZlVNQVBfMSwgeSA9IHJlZlVNQVBfMiwgY29sb3IgPSBwc2V1ZG90aW1lKSwKICAgICAgICAgICAgIHNpemUgPSAxKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gImxpZ2h0Ymx1ZSIsIGhpZ2ggPSAicmVkIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgZ2d0aXRsZSgiTWFsaWduYW50Q0Q0VCBjZWxscyBwcm9qZWN0ZWQgb250byByZWZlcmVuY2UgVU1BUCIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCgpgYGAKIyMgTWFwcGluZyBvZiBNYWxpZ25hbnRDRDRUIG9uIFJlZmVyZW5jZSAoQXppbXV0aCkKYGBge3J9CgpsaWJyYXJ5KGdncGxvdDIpCgojIFJlZmVyZW5jZSBjb29yZGluYXRlcyAoZ3JleSBiYWNrZ3JvdW5kKQpyZWZfZGYgPC0gZGF0YS5mcmFtZShFbWJlZGRpbmdzKHJlZmVyZW5jZV9pbnRlZ3JhdGVkLCAidW1hcCIpKQpyZWZfZGYkZGF0YXNldCA8LSAiUmVmZXJlbmNlIgoKIyBRdWVyeSAoTWFsaWduYW50Q0Q0VCkgY29vcmRpbmF0ZXMKcXVlcnlfZGYgPC0gZGF0YS5mcmFtZShFbWJlZGRpbmdzKG1hcHBlZF9NYWxpZ25hbnRDRDRULCAicmVmLnVtYXAiKSkKcXVlcnlfZGYkZGF0YXNldCA8LSAiTWFsaWduYW50Q0Q0VCIKCiMgTWFrZSBzdXJlIGFubm90YXRpb25zIGV4aXN0IGluIG1hcHBlZF9NYWxpZ25hbnRDRDRUCnF1ZXJ5X2RmJGNlbGx0eXBlIDwtIG1hcHBlZF9NYWxpZ25hbnRDRDRUJHByZWRpY3RlZC5jZWxsdHlwZS5sMiAgIyBvciAiUHJlZGljdGlvbiIKCmxpYnJhcnkoUkNvbG9yQnJld2VyKQoKYmlnX3BhbGV0dGUgPC0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDEyLCAiUGFpcmVkIikpKDIwKQoKZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHJlZl9kZiwgYWVzKHggPSB1bWFwXzEsIHkgPSB1bWFwXzIpLAogICAgICAgICAgICAgY29sb3IgPSAiZ3JleTgwIiwgc2l6ZSA9IDAuNSkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHF1ZXJ5X2RmLCBhZXMoeCA9IHJlZlVNQVBfMSwgeSA9IHJlZlVNQVBfMiwgY29sb3IgPSBjZWxsdHlwZSksCiAgICAgICAgICAgICBzaXplID0gMSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBiaWdfcGFsZXR0ZSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgZ2d0aXRsZSgiTWFsaWduYW50Q0Q0VCBjZWxscyBwcm9qZWN0ZWQgb250byByZWZlcmVuY2UgVU1BUCB3aXRoIGFubm90YXRpb25zIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQoKCmBgYAoKIyMgTWFwcGluZyBvZiBNYWxpZ25hbnRDRDRUIG9uIFJlZmVyZW5jZSAoU1RDQVQpCmBgYHtyLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMH0KCmxpYnJhcnkoZ2dwbG90MikKCiMgUmVmZXJlbmNlIGNvb3JkaW5hdGVzIChncmV5IGJhY2tncm91bmQpCnJlZl9kZiA8LSBkYXRhLmZyYW1lKEVtYmVkZGluZ3MocmVmZXJlbmNlX2ludGVncmF0ZWQsICJ1bWFwIikpCnJlZl9kZiRkYXRhc2V0IDwtICJSZWZlcmVuY2UiCgojIFF1ZXJ5IChNYWxpZ25hbnRDRDRUKSBjb29yZGluYXRlcwpxdWVyeV9kZiA8LSBkYXRhLmZyYW1lKEVtYmVkZGluZ3MobWFwcGVkX01hbGlnbmFudENENFQsICJyZWYudW1hcCIpKQpxdWVyeV9kZiRkYXRhc2V0IDwtICJNYWxpZ25hbnRDRDRUIgoKIyBNYWtlIHN1cmUgYW5ub3RhdGlvbnMgZXhpc3QgaW4gbWFwcGVkX01hbGlnbmFudENENFQKcXVlcnlfZGYkY2VsbHR5cGUgPC0gbWFwcGVkX01hbGlnbmFudENENFQkUHJlZGljdGlvbiAgIyBvciAiUHJlZGljdGlvbiIKCmxpYnJhcnkoUkNvbG9yQnJld2VyKQoKIyBHZXQgYSBwYWxldHRlIHdpdGggdXAgdG8gMjAgY29sb3JzCmJpZ19wYWxldHRlIDwtIGNvbG9yUmFtcFBhbGV0dGUoYnJld2VyLnBhbCgxMiwgIlBhaXJlZCIpKSgyMCkKCmdncGxvdCgpICsKICBnZW9tX3BvaW50KGRhdGEgPSByZWZfZGYsIGFlcyh4ID0gdW1hcF8xLCB5ID0gdW1hcF8yKSwKICAgICAgICAgICAgIGNvbG9yID0gImdyZXk4MCIsIHNpemUgPSAwLjUpICsKICBnZW9tX3BvaW50KGRhdGEgPSBxdWVyeV9kZiwgYWVzKHggPSByZWZVTUFQXzEsIHkgPSByZWZVTUFQXzIsIGNvbG9yID0gY2VsbHR5cGUpLAogICAgICAgICAgICAgc2l6ZSA9IDEpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYmlnX3BhbGV0dGUpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGdndGl0bGUoIk1hbGlnbmFudENENFQgY2VsbHMgcHJvamVjdGVkIG9udG8gcmVmZXJlbmNlIFVNQVAgd2l0aCBhbm5vdGF0aW9ucyIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCgpgYGAKCiMgNS4gU3Vic2V0IE1hbGlnbmFudENENFQgUHJvamVjdGlvbgpgYGB7ciBzYXZlZmluYWx9CgojIDEuIERlZmluZSBvdXRwdXQgZGlyZWN0b3J5Cm91dF9kaXIgPC0gInJlc3VsdHMvTWFsaWduYW50Q0Q0VF9wcm9qZWN0aW9uIgppZighZGlyLmV4aXN0cyhvdXRfZGlyKSkgZGlyLmNyZWF0ZShvdXRfZGlyLCByZWN1cnNpdmUgPSBUUlVFKQoKc2F2ZShtYXBwZWRfTWFsaWduYW50Q0Q0VCwgZmlsZSA9IGZpbGUucGF0aChvdXRfZGlyLCAiTWFsaWduYW50Q0Q0VF9tYXBwZWRfb25fcmVmZXJlbmNlX3dpdGhfcHNldWRvdGltZS0zLTgtMjAyNS5Sb2JqIikpCgoKYGBgCgoK