load libraries
Load and Subset Herrera
Data
Idents(ctrl) <- "seurat_clusters"
table(ctrl@active.ident)
2 3 0 12 6 17 5 4 1 15 14 18 9 13 7 8 11 16 10
3241 1006 185 124 404 44 223 2278 92 48 183 10 84 150 230 923 727 4 829
Reference data
reference <- scPred::pbmc_1
reference
An object of class Seurat
32838 features across 3500 samples within 1 assay
Active assay: RNA (32838 features, 0 variable features)
2 layers present: counts, data
Reference data
analysis
# Run SCTransform (normalization + variance stabilization)
reference <- SCTransform(reference, verbose = FALSE)
# Find variable features is done inside SCTransform, no need to run separately
# Run PCA on SCT assay
reference <- RunPCA(reference, assay = "SCT", verbose = FALSE, reduction.name = "pca")
Registered S3 method overwritten by 'rmarkdown':
method from
print.paged_df
# Run UMAP on PCA
reference <- RunUMAP(reference, dims = 1:30)
Using method 'umap'
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
DimPlot(reference, group.by = "cell_type", label = TRUE, repel = TRUE) + NoAxes()

Run all steps of the
analysis for the ctrl sample as well
DimPlot(ctrl, group.by = "seurat_clusters", label = TRUE, repel = TRUE) + NoAxes()

DimPlot(ctrl, group.by = "condition", label = TRUE, repel = TRUE) + NoAxes()

DimPlot(ctrl, group.by = "seurat_clusters", label = TRUE, repel = TRUE) + NoAxes()

Label transfer
# Set default assay to SCT
DefaultAssay(reference) <- "SCT"
# 1. Make sure SCT is the default assay in your query (ctrl)
DefaultAssay(ctrl) <- "RNA"
# 2. (Optional but recommended) Run SCTransform if not already done
# If you already normalized with SCTransform, you can skip this.
ctrl <- SCTransform(ctrl, verbose = FALSE)
# 3. Find anchors between reference and query
transfer.anchors <- FindTransferAnchors(
reference = reference,
query = ctrl,
normalization.method = "SCT", # MUST be SCT
reference.reduction = "pca", # Azimuth references use spca
dims = 1:30
)
# 4. Transfer annotations (cell types, etc.)
predictions <- TransferData(
anchorset = transfer.anchors,
refdata = reference$cell_type, # column from reference metadata
dims = 1:30
)
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
# 5. Add predictions back into your query object
ctrl <- AddMetaData(ctrl, metadata = predictions)
Dimplot-myumap
DimPlot(ctrl, group.by = "predicted.id", label = T, repel = T) + NoAxes()

barplot
Distributions
ggplot(ctrl@meta.data, aes(x = seurat_clusters, fill = predicted.id)) +
geom_bar() +
theme_classic()

SinlgeR
# make sure you are on Seurat >= 5
DefaultAssay(ctrl) <- "RNA"
# merge all RNA layers into one
ctrl <- JoinLayers(ctrl, assay = "RNA")
# now convert to SCE
sce <- as.SingleCellExperiment(ctrl, assay = "RNA")
Immune cell
reference
immune = celldex::DatabaseImmuneCellExpressionData()
singler.immune <- SingleR(test = sce, ref = immune, assay.type.test=1,
labels = immune$label.fine)
head(singler.immune)
DataFrame with 6 rows and 4 columns
scores labels delta.next pruned.labels
<matrix> <character> <numeric> <character>
SS_SS1_Blood_H20_AAACGGGTCTGTACGA 0.126734:0.123792:0.127111:... T cells, CD4+, Th2 0.01020391 T cells, CD4+, Th2
SS_SS1_Blood_H20_AAAGCAAAGTCCCACG 0.146714:0.150715:0.153418:... T cells, CD4+, Th2 0.00787036 T cells, CD4+, Th2
SS_SS1_Blood_H20_AAAGTAGAGTTTCCTT 0.147983:0.135853:0.135882:... T cells, CD4+, Th2 0.06289714 T cells, CD4+, Th2
SS_SS1_Blood_H20_AAAGTAGTCCACGACG 0.127739:0.115666:0.116248:... T cells, CD4+, Th2 0.00174197 T cells, CD4+, Th2
SS_SS1_Blood_H20_AAATGCCCACCCATGG 0.140546:0.143729:0.155259:... T cells, CD4+, memor.. 0.00138212 T cells, CD4+, memor..
SS_SS1_Blood_H20_AACACGTAGCCCAATT 0.137978:0.121588:0.138889:... T cells, CD4+, Th2 0.00429020 T cells, CD4+, Th2
HPCA reference
hpca <- celldex::HumanPrimaryCellAtlasData()
singler.hpca <- SingleR(test = sce, ref = hpca, assay.type.test=1,
labels = hpca$label.fine)
head(singler.hpca)
DataFrame with 6 rows and 4 columns
scores labels delta.next pruned.labels
<matrix> <character> <numeric> <character>
SS_SS1_Blood_H20_AAACGGGTCTGTACGA 0.158345:0.252571:0.222786:... T_cell:CD4+_central_.. 0.1610613 T_cell:CD4+_central_..
SS_SS1_Blood_H20_AAAGCAAAGTCCCACG 0.167377:0.305519:0.274721:... T_cell:CD4+_central_.. 0.1069279 T_cell:CD4+_central_..
SS_SS1_Blood_H20_AAAGTAGAGTTTCCTT 0.182532:0.312291:0.278981:... T_cell:CD4+_central_.. 0.0303539 T_cell:CD4+_central_..
SS_SS1_Blood_H20_AAAGTAGTCCACGACG 0.168245:0.274507:0.247855:... T_cell:CD4+_effector.. 0.0999581 T_cell:CD4+_effector..
SS_SS1_Blood_H20_AAATGCCCACCCATGG 0.182977:0.305724:0.273373:... T_cell:CD4+_central_.. 0.0980566 T_cell:CD4+_central_..
SS_SS1_Blood_H20_AACACGTAGCCCAATT 0.175543:0.282729:0.252079:... T_cell:CD4+_effector.. 0.0399778 T_cell:CD4+_effector..
Compare results:
ctrl$singler.immune = singler.immune$pruned.labels
ctrl$singler.hpca = singler.hpca$pruned.labels
Compare results:
DimPlot(ctrl, group.by = "singler.hpca", label = T, repel = T) + NoAxes()

DimPlot(ctrl, group.by = "singler.immune", label = T, repel = T) + NoAxes()

NA
NA
Compare results:
DimPlot(ctrl, group.by = c("singler.hpca", "singler.immune"), ncol = 2, label = T, label.box = T, repel = T)

Compare results:
ctrl$singler.immune = singler.immune$pruned.labels
ctrl$singler.hpca = singler.hpca$pruned.labels
DimPlot(ctrl, group.by = c("singler.hpca", "singler.immune"), ncol = 2, label = F, label.box = F, repel = T)

Azimuth
options(future.globals.maxSize = 1e9)
library(SeuratData)
DefaultAssay(ctrl) <- "SCT"
ctrl <- RunAzimuth(ctrl, reference = "pbmcref")
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%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Azimuth Dimplot
DimPlot(ctrl, group.by = "predicted.celltype.l1", label = T, repel = T) + NoAxes()

DimPlot(ctrl, group.by = "predicted.celltype.l2", label = T, repel = T) + NoAxes()

DimPlot(ctrl, group.by = "predicted.celltype.l3", label = T, repel = T) + NoAxes()

ProjectTils
Annotation_CD4T_human_ref_v1


Compare results from
all Annotation methods
crossTab(ctrl, "predicted.id", "singler.hpca")
crossTab(ctrl, "predicted.id", "singler.immune")
crossTab(ctrl, "singler.hpca", "singler.immune")
crossTab(ctrl, "predicted.id", "predicted.celltype.l1")
crossTab(ctrl, "predicted.celltype.l2", "functional.cluster")
NA
Compare results
wrap_plots(
DimPlot(ctrl, label = T, group.by = "predicted.id") + NoAxes() + ggtitle("LabelTransfer"),
DimPlot(ctrl, label = F, group.by = "singler.hpca" ) + NoAxes() + ggtitle("SingleR HPCA"),
DimPlot(ctrl, label = F, group.by = "singler.immune") + NoAxes() + ggtitle("SingleR Ref"),
DimPlot(ctrl, label = T, group.by = "predicted.celltype.l1") + NoAxes() + ggtitle("Azimuth l1"),
ncol = 2
)

Compare results
wrap_plots(
DimPlot(ctrl, label = T, group.by = "predicted.id") + NoAxes() + ggtitle("LabelTransfer"),
DimPlot(ctrl, label = F, group.by = "singler.hpca") + NoAxes() + ggtitle("SingleR HPCA"),
DimPlot(ctrl, label = F, group.by = "singler.immune") + NoAxes() + ggtitle("SingleR Ref"),
DimPlot(ctrl, label = F, group.by = "predicted.celltype.l2") + NoAxes() + ggtitle("LabelTransfer"),
DimPlot(ctrl, label = T, group.by = "functional.cluster") + NoAxes() + ggtitle("ProjecTils CD4")
)

save all the annotation
in object into RDS
# Save the Seurat object with all annotations
saveRDS(ctrl, file = "All_samples_Merged_with_all_annotations_ATLAS-Herrera-03-02-2026.rds")
LS0tCnRpdGxlOiAiQ2VsbHR5cGUgUHJlZGljdGlvbiB1c2luZyBIZXJyZXJhIGRhdGEiCmF1dGhvcjogTmFzaXIgTWFobW9vZCBBYmJhc2kKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogdHJ1ZQogICAgdGhlbWU6IGpvdXJuYWwKLS0tCgoKIyBsb2FkIGxpYnJhcmllcwpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KCiAgICBsaWJyYXJ5KFNldXJhdCkKICAgIGxpYnJhcnkoZHBseXIpCiAgICBsaWJyYXJ5KHBhdGNod29yaykKICAgIGxpYnJhcnkoZ2dwbG90MikKICAgIGxpYnJhcnkocGhlYXRtYXApCiAgICBsaWJyYXJ5KHNjUHJlZCkKICAgIGxpYnJhcnkoY2VsbGRleCkKICAgIGxpYnJhcnkoU2luZ2xlUikKICAgIGxpYnJhcnkocmVtb3RlcykKICAgIGxpYnJhcnkocHJlc3RvKQogICAgbGlicmFyeShTZXVyYXREaXNrKQogICAgbGlicmFyeShTZXVyYXREYXRhKQogICAgbGlicmFyeShBemltdXRoKQoKYGBgCgoKIyBMb2FkIGFuZCBTdWJzZXQgSGVycmVyYSBEYXRhCmBgYHtyIGxvYWRTZXVyYXR9CgpjdHJsIDwtIHJlYWRSRFMoIi9ob21lL2Jpb2luZm8vMS1UaGVzaXNfRmluYWxfWWVhcl8yMDI1LzIwMjUtWWVhcjNfQW5hbHlzaXMvMS1zY1JOQV9SRVNVTFRTLTE5LTExLTIwMjUvMS1CaW9tYXJrZXJzX1ZhbGlkYXRpb25fd2l0aF9QdWJsaWNfRGF0YS1BdWd1c3QyMDI1L0hlcnJlcmFfRGF0YS9IZXJyYXJhX1RDUl9BQi9BbmFseXNpcy9TZXphcnlfQmxvb2RfU2tpbl92c19IQ19UQ1JfZmlsdGVyZWQucmRzIikKCklkZW50cyhjdHJsKSA8LSAic2V1cmF0X2NsdXN0ZXJzIgp0YWJsZShjdHJsQGFjdGl2ZS5pZGVudCkKCgpgYGAKCgojIyBSZWZlcmVuY2UgZGF0YQpgYGB7cn0KCnJlZmVyZW5jZSA8LSBzY1ByZWQ6OnBibWNfMQpyZWZlcmVuY2UKCmBgYAoKCiMjIFJlZmVyZW5jZSBkYXRhIGFuYWx5c2lzCmBgYHtyfQoKCgojIFJ1biBTQ1RyYW5zZm9ybSAobm9ybWFsaXphdGlvbiArIHZhcmlhbmNlIHN0YWJpbGl6YXRpb24pCnJlZmVyZW5jZSA8LSBTQ1RyYW5zZm9ybShyZWZlcmVuY2UsIHZlcmJvc2UgPSBGQUxTRSkKCiMgRmluZCB2YXJpYWJsZSBmZWF0dXJlcyBpcyBkb25lIGluc2lkZSBTQ1RyYW5zZm9ybSwgbm8gbmVlZCB0byBydW4gc2VwYXJhdGVseQoKIyBSdW4gUENBIG9uIFNDVCBhc3NheQpyZWZlcmVuY2UgPC0gUnVuUENBKHJlZmVyZW5jZSwgYXNzYXkgPSAiU0NUIiwgdmVyYm9zZSA9IEZBTFNFLCByZWR1Y3Rpb24ubmFtZSA9ICJwY2EiKQoKCiMgUnVuIFVNQVAgb24gUENBCnJlZmVyZW5jZSA8LSBSdW5VTUFQKHJlZmVyZW5jZSwgZGltcyA9IDE6MzApCgoKRGltUGxvdChyZWZlcmVuY2UsIGdyb3VwLmJ5ID0gImNlbGxfdHlwZSIsIGxhYmVsID0gVFJVRSwgcmVwZWwgPSBUUlVFKSArIE5vQXhlcygpCgpgYGAKCiMjIFJ1biBhbGwgc3RlcHMgb2YgdGhlIGFuYWx5c2lzIGZvciB0aGUgY3RybCBzYW1wbGUgYXMgd2VsbApgYGB7cn0KRGltUGxvdChjdHJsLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLCBsYWJlbCA9IFRSVUUsIHJlcGVsID0gVFJVRSkgKyBOb0F4ZXMoKQpEaW1QbG90KGN0cmwsIGdyb3VwLmJ5ID0gImNvbmRpdGlvbiIsIGxhYmVsID0gVFJVRSwgcmVwZWwgPSBUUlVFKSArIE5vQXhlcygpCkRpbVBsb3QoY3RybCwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwgbGFiZWwgPSBUUlVFLCByZXBlbCA9IFRSVUUpICsgTm9BeGVzKCkKCmBgYAoKIyMgTGFiZWwgdHJhbnNmZXIKYGBge3J9CiMgU2V0IGRlZmF1bHQgYXNzYXkgdG8gU0NUCkRlZmF1bHRBc3NheShyZWZlcmVuY2UpIDwtICJTQ1QiCgojIDEuIE1ha2Ugc3VyZSBTQ1QgaXMgdGhlIGRlZmF1bHQgYXNzYXkgaW4geW91ciBxdWVyeSAoY3RybCkKRGVmYXVsdEFzc2F5KGN0cmwpIDwtICJSTkEiCgojIDIuIChPcHRpb25hbCBidXQgcmVjb21tZW5kZWQpIFJ1biBTQ1RyYW5zZm9ybSBpZiBub3QgYWxyZWFkeSBkb25lCiMgSWYgeW91IGFscmVhZHkgbm9ybWFsaXplZCB3aXRoIFNDVHJhbnNmb3JtLCB5b3UgY2FuIHNraXAgdGhpcy4KIGN0cmwgPC0gU0NUcmFuc2Zvcm0oY3RybCwgdmVyYm9zZSA9IEZBTFNFKQoKIyAzLiBGaW5kIGFuY2hvcnMgYmV0d2VlbiByZWZlcmVuY2UgYW5kIHF1ZXJ5CnRyYW5zZmVyLmFuY2hvcnMgPC0gRmluZFRyYW5zZmVyQW5jaG9ycygKICAgIHJlZmVyZW5jZSA9IHJlZmVyZW5jZSwKICAgIHF1ZXJ5ID0gY3RybCwKICAgIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIlNDVCIsICAgIyBNVVNUIGJlIFNDVAogICAgcmVmZXJlbmNlLnJlZHVjdGlvbiA9ICJwY2EiLCAgICMgQXppbXV0aCByZWZlcmVuY2VzIHVzZSBzcGNhCiAgICBkaW1zID0gMTozMAopCgojIDQuIFRyYW5zZmVyIGFubm90YXRpb25zIChjZWxsIHR5cGVzLCBldGMuKQpwcmVkaWN0aW9ucyA8LSBUcmFuc2ZlckRhdGEoCiAgICBhbmNob3JzZXQgPSB0cmFuc2Zlci5hbmNob3JzLAogICAgcmVmZGF0YSA9IHJlZmVyZW5jZSRjZWxsX3R5cGUsICAjIGNvbHVtbiBmcm9tIHJlZmVyZW5jZSBtZXRhZGF0YQogICAgZGltcyA9IDE6MzAKKQoKIyA1LiBBZGQgcHJlZGljdGlvbnMgYmFjayBpbnRvIHlvdXIgcXVlcnkgb2JqZWN0CmN0cmwgPC0gQWRkTWV0YURhdGEoY3RybCwgbWV0YWRhdGEgPSBwcmVkaWN0aW9ucykKCgpgYGAKCgojIyBEaW1wbG90LW15dW1hcApgYGB7cn0KCkRpbVBsb3QoY3RybCwgZ3JvdXAuYnkgPSAicHJlZGljdGVkLmlkIiwgbGFiZWwgPSBULCByZXBlbCA9IFQpICsgTm9BeGVzKCkKCmBgYAojIyBiYXJwbG90IERpc3RyaWJ1dGlvbnMKYGBge3J9CgpnZ3Bsb3QoY3RybEBtZXRhLmRhdGEsIGFlcyh4ID0gc2V1cmF0X2NsdXN0ZXJzLCBmaWxsID0gcHJlZGljdGVkLmlkKSkgKwogICAgZ2VvbV9iYXIoKSArCiAgICB0aGVtZV9jbGFzc2ljKCkKCmBgYAoKCiMgU2lubGdlUgpgYGB7cn0KCiAjIG1ha2Ugc3VyZSB5b3UgYXJlIG9uIFNldXJhdCA+PSA1CkRlZmF1bHRBc3NheShjdHJsKSA8LSAiUk5BIgoKIyBtZXJnZSBhbGwgUk5BIGxheWVycyBpbnRvIG9uZQpjdHJsIDwtIEpvaW5MYXllcnMoY3RybCwgYXNzYXkgPSAiUk5BIikKCiMgbm93IGNvbnZlcnQgdG8gU0NFCnNjZSA8LSBhcy5TaW5nbGVDZWxsRXhwZXJpbWVudChjdHJsLCBhc3NheSA9ICJSTkEiKQoKCmBgYAoKCgoKCiMjIEltbXVuZSBjZWxsIHJlZmVyZW5jZQpgYGB7cn0KCiBpbW11bmUgPSBjZWxsZGV4OjpEYXRhYmFzZUltbXVuZUNlbGxFeHByZXNzaW9uRGF0YSgpCnNpbmdsZXIuaW1tdW5lIDwtIFNpbmdsZVIodGVzdCA9IHNjZSwgcmVmID0gaW1tdW5lLCBhc3NheS50eXBlLnRlc3Q9MSwKICAgIGxhYmVscyA9IGltbXVuZSRsYWJlbC5maW5lKQoKaGVhZChzaW5nbGVyLmltbXVuZSkKCmBgYAoKCgoKCgojIyBIUENBIHJlZmVyZW5jZQpgYGB7cn0KCmhwY2EgPC0gY2VsbGRleDo6SHVtYW5QcmltYXJ5Q2VsbEF0bGFzRGF0YSgpCnNpbmdsZXIuaHBjYSA8LSBTaW5nbGVSKHRlc3QgPSBzY2UsIHJlZiA9IGhwY2EsIGFzc2F5LnR5cGUudGVzdD0xLAogICAgbGFiZWxzID0gaHBjYSRsYWJlbC5maW5lKQoKaGVhZChzaW5nbGVyLmhwY2EpCgpgYGAKCgojIyBDb21wYXJlIHJlc3VsdHM6CmBgYHtyLCAgZmlnLmhlaWdodD0gMTIsIGZpZy53aWR0aD0gMTR9CgpjdHJsJHNpbmdsZXIuaW1tdW5lID0gc2luZ2xlci5pbW11bmUkcHJ1bmVkLmxhYmVscwpjdHJsJHNpbmdsZXIuaHBjYSA9IHNpbmdsZXIuaHBjYSRwcnVuZWQubGFiZWxzCgpgYGAKCiMjIENvbXBhcmUgcmVzdWx0czoKYGBge3IsICBmaWcuaGVpZ2h0PSAxMiwgZmlnLndpZHRoPSAxNH0KCgpEaW1QbG90KGN0cmwsIGdyb3VwLmJ5ID0gInNpbmdsZXIuaHBjYSIsIGxhYmVsID0gVCwgcmVwZWwgPSBUKSArIE5vQXhlcygpCkRpbVBsb3QoY3RybCwgZ3JvdXAuYnkgPSAic2luZ2xlci5pbW11bmUiLCBsYWJlbCA9IFQsIHJlcGVsID0gVCkgKyBOb0F4ZXMoKQoKCmBgYAoKIyMgQ29tcGFyZSByZXN1bHRzOgpgYGB7ciwgIGZpZy5oZWlnaHQ9IDEyLCBmaWcud2lkdGg9IDMwfQoKCkRpbVBsb3QoY3RybCwgZ3JvdXAuYnkgPSBjKCJzaW5nbGVyLmhwY2EiLCAic2luZ2xlci5pbW11bmUiKSwgbmNvbCA9IDIsIGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCwgcmVwZWwgPSBUKQoKYGBgCiMjIENvbXBhcmUgcmVzdWx0czoKYGBge3IsIGZpZy5oZWlnaHQ9IDYsIGZpZy53aWR0aD0gMjB9CgpjdHJsJHNpbmdsZXIuaW1tdW5lID0gc2luZ2xlci5pbW11bmUkcHJ1bmVkLmxhYmVscwpjdHJsJHNpbmdsZXIuaHBjYSA9IHNpbmdsZXIuaHBjYSRwcnVuZWQubGFiZWxzCgoKRGltUGxvdChjdHJsLCBncm91cC5ieSA9IGMoInNpbmdsZXIuaHBjYSIsICJzaW5nbGVyLmltbXVuZSIpLCBuY29sID0gMiwgbGFiZWwgPSBGLCBsYWJlbC5ib3ggPSBGLCByZXBlbCA9IFQpCgpgYGAKCgojIEF6aW11dGgKYGBge3J9Cm9wdGlvbnMoZnV0dXJlLmdsb2JhbHMubWF4U2l6ZSA9IDFlOSkKCmxpYnJhcnkoU2V1cmF0RGF0YSkKCkRlZmF1bHRBc3NheShjdHJsKSA8LSAiU0NUIgoKY3RybCA8LSBSdW5BemltdXRoKGN0cmwsIHJlZmVyZW5jZSA9ICJwYm1jcmVmIikKCmBgYAoKIyMgQXppbXV0aCBEaW1wbG90CmBgYHtyLCBmaWcuaGVpZ2h0PSA2LCBmaWcud2lkdGg9IDEwfQpEaW1QbG90KGN0cmwsIGdyb3VwLmJ5ID0gInByZWRpY3RlZC5jZWxsdHlwZS5sMSIsIGxhYmVsID0gVCwgcmVwZWwgPSBUKSArIE5vQXhlcygpCgpEaW1QbG90KGN0cmwsIGdyb3VwLmJ5ID0gInByZWRpY3RlZC5jZWxsdHlwZS5sMiIsIGxhYmVsID0gVCwgcmVwZWwgPSBUKSArIE5vQXhlcygpCgpEaW1QbG90KGN0cmwsIGdyb3VwLmJ5ID0gInByZWRpY3RlZC5jZWxsdHlwZS5sMyIsIGxhYmVsID0gVCwgcmVwZWwgPSBUKSArIE5vQXhlcygpCgpgYGAKCgoKIyBQcm9qZWN0VGlscyBBbm5vdGF0aW9uX0NENFRfaHVtYW5fcmVmX3YxCmBgYHtyfQpsaWJyYXJ5KFNUQUNBUykKbGlicmFyeShQcm9qZWNUSUxzKQoKCiNMb2FkIHJlZmVyZW5jZSBhdGxhcyBhbmQgcXVlcnkgZGF0YQogcmVmIDwtIHJlYWRSRFMoZmlsZSA9ICJDRDRUX2h1bWFuX3JlZl92MS5yZHMiKQoKcXVlcnkucHJvamVjdGVkIDwtIFByb2plY1RJTHMuY2xhc3NpZmllcihxdWVyeSA9IGN0cmwsIHJlZiA9IHJlZikKCgojcmVmZXJlbmNlIGF0bGFzCiBEaW1QbG90KHJlZiwgbGFiZWwgPSBUKQogCiAKCgogI1Bsb3QgdGhlIHByZWRpY3RlZCBjb21wb3NpdGlvbiBvZiB0aGUgcXVlcnkgaW4gdGVybXMgb2YgcmVmZXJlbmNlIFQgY2VsbCBzdWJ0eXBlcwogcGxvdC5zdGF0ZXByZWQuY29tcG9zaXRpb24ocmVmLCBxdWVyeS5wcm9qZWN0ZWQsIG1ldHJpYyA9ICJQZXJjZW50IikKCgoKIyBOb3cgeW91IGNhbiBwbG90CkRpbVBsb3QoY3RybCwgZ3JvdXAuYnkgPSAiZnVuY3Rpb25hbC5jbHVzdGVyIiwgCiAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLAogICAgICAgIGxhYmVsLnNpemUgPSAzLAogICAgICAgIHJlcGVsID0gVFJVRSwKICAgICAgICBsYWJlbCA9IEZBTFNFKQogCiAKCmBgYAoKIyAgQ29tcGFyZSByZXN1bHRzIGZyb20gYWxsIEFubm90YXRpb24gbWV0aG9kcwpgYGB7cn0KCmNyb3NzVGFiKGN0cmwsICJwcmVkaWN0ZWQuaWQiLCAic2luZ2xlci5ocGNhIikKCmNyb3NzVGFiKGN0cmwsICJwcmVkaWN0ZWQuaWQiLCAic2luZ2xlci5pbW11bmUiKQoKY3Jvc3NUYWIoY3RybCwgInNpbmdsZXIuaHBjYSIsICJzaW5nbGVyLmltbXVuZSIpCgpjcm9zc1RhYihjdHJsLCAicHJlZGljdGVkLmlkIiwgInByZWRpY3RlZC5jZWxsdHlwZS5sMSIpCgpjcm9zc1RhYihjdHJsLCAicHJlZGljdGVkLmNlbGx0eXBlLmwyIiwgImZ1bmN0aW9uYWwuY2x1c3RlciIpCgpgYGAKCiMjICBDb21wYXJlIHJlc3VsdHMKYGBge3IsIGZpZy5oZWlnaHQ9IDgsIGZpZy53aWR0aD0gMjB9Cgp3cmFwX3Bsb3RzKAogICAgRGltUGxvdChjdHJsLCBsYWJlbCA9IFQsIGdyb3VwLmJ5ID0gInByZWRpY3RlZC5pZCIpICsgTm9BeGVzKCkgKyBnZ3RpdGxlKCJMYWJlbFRyYW5zZmVyIiksCiAgICBEaW1QbG90KGN0cmwsIGxhYmVsID0gRiwgZ3JvdXAuYnkgPSAic2luZ2xlci5ocGNhIiApICsgTm9BeGVzKCkgKyBnZ3RpdGxlKCJTaW5nbGVSIEhQQ0EiKSwKICAgIERpbVBsb3QoY3RybCwgbGFiZWwgPSBGLCBncm91cC5ieSA9ICJzaW5nbGVyLmltbXVuZSIpICsgTm9BeGVzKCkgKyBnZ3RpdGxlKCJTaW5nbGVSIFJlZiIpLAogICAgRGltUGxvdChjdHJsLCBsYWJlbCA9IFQsIGdyb3VwLmJ5ID0gInByZWRpY3RlZC5jZWxsdHlwZS5sMSIpICsgTm9BeGVzKCkgKyBnZ3RpdGxlKCJBemltdXRoIGwxIiksCiAgICBuY29sID0gMgopCgpgYGAKCgojIyAgQ29tcGFyZSByZXN1bHRzCmBgYHtyLCBmaWcuaGVpZ2h0PSAxMiwgZmlnLndpZHRoPSAyMH0KCndyYXBfcGxvdHMoCiAgICBEaW1QbG90KGN0cmwsIGxhYmVsID0gVCwgZ3JvdXAuYnkgPSAicHJlZGljdGVkLmlkIikgKyBOb0F4ZXMoKSArIGdndGl0bGUoIkxhYmVsVHJhbnNmZXIiKSwKICAgIERpbVBsb3QoY3RybCwgbGFiZWwgPSBGLCBncm91cC5ieSA9ICJzaW5nbGVyLmhwY2EiKSArIE5vQXhlcygpICsgZ2d0aXRsZSgiU2luZ2xlUiBIUENBIiksCiAgICBEaW1QbG90KGN0cmwsIGxhYmVsID0gRiwgZ3JvdXAuYnkgPSAic2luZ2xlci5pbW11bmUiKSArIE5vQXhlcygpICsgZ2d0aXRsZSgiU2luZ2xlUiBSZWYiKSwKICAgIERpbVBsb3QoY3RybCwgbGFiZWwgPSBGLCBncm91cC5ieSA9ICJwcmVkaWN0ZWQuY2VsbHR5cGUubDIiKSArIE5vQXhlcygpICsgZ2d0aXRsZSgiTGFiZWxUcmFuc2ZlciIpLAogICAgRGltUGxvdChjdHJsLCBsYWJlbCA9IFQsIGdyb3VwLmJ5ID0gImZ1bmN0aW9uYWwuY2x1c3RlciIpICsgTm9BeGVzKCkgKyBnZ3RpdGxlKCJQcm9qZWNUaWxzIENENCIpCiAgCikKCmBgYAoKIyBzYXZlIGFsbCB0aGUgYW5ub3RhdGlvbiBpbiBvYmplY3QgaW50byBSRFMKYGBge3J9CgojIFNhdmUgdGhlIFNldXJhdCBvYmplY3Qgd2l0aCBhbGwgYW5ub3RhdGlvbnMKc2F2ZVJEUyhjdHJsLCBmaWxlID0gIkFsbF9zYW1wbGVzX01lcmdlZF93aXRoX2FsbF9hbm5vdGF0aW9uc19BVExBUy1IZXJyZXJhLTAzLTAyLTIwMjYucmRzIikKCmBgYAo=