2. Load Seurat Object


# Check original UMAP before integration
p1 <- DimPlot(All_samples_Merged,
reduction = "umap",
group.by = "cell_line",
label = TRUE,
label.box = TRUE) +
ggtitle("Before Harmony - By Cell Line")
p2 <- DimPlot(All_samples_Merged,
reduction = "umap",
group.by = "seurat_clusters",
label = TRUE,
label.box = TRUE) +
ggtitle("Before Harmony - By Clusters")
# Print original plots
p1 + p2
DimPlot(All_samples_Merged,
reduction = "umap",
group.by = "cell_line",
label = TRUE,
label.box = TRUE) +
ggtitle("Before Harmony - By Cell Line")
DimPlot(All_samples_Merged,
reduction = "umap",
group.by = "seurat_clusters",
label = TRUE,
label.box = TRUE) +
ggtitle("Before Harmony - By Clusters")

DimPlot(All_samples_Merged,
reduction = "umap",
group.by = "predicted.celltype.l1",
label = TRUE,
label.box = TRUE) +
ggtitle("Before Harmony - By Annotation.l1")

DimPlot(All_samples_Merged,
reduction = "umap",
group.by = "predicted.celltype.l2",
label = TRUE,
label.box = TRUE) +
ggtitle("Before Harmony - By Annotation.l2")

DimPlot(All_samples_Merged,
reduction = "umap",
group.by = "predicted.celltype.l3",
label = TRUE,
label.box = TRUE) +
ggtitle("Before Harmony - By Annotation.l3")

Harmony Visualization-1
library(harmony)
All_samples_Merged <- RunHarmony(
object = All_samples_Merged,
group.by.vars = "cell_line",
dims.use = 1:16,
theta = 0.5, # Lower theta to maintain biological differences
plot_convergence = TRUE
)
Transposing data matrix
Initializing state using k-means centroids initialization
Harmony 1/10
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Harmony 2/10
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Harmony converged after 2 iterations

# Run UMAP on the new Harmony reduction
All_samples_Merged <- RunUMAP(All_samples_Merged, reduction = "harmony", dims = 1:16, reduction.name = "umap.harmony")
20:49:52 UMAP embedding parameters a = 0.9922 b = 1.112
20:49:52 Read 49388 rows and found 16 numeric columns
20:49:52 Using Annoy for neighbor search, n_neighbors = 30
20:49:52 Building Annoy index with metric = cosine, n_trees = 50
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
20:49:58 Writing NN index file to temp file /tmp/Rtmpp3xsxj/file161ae333ffbabc
20:49:58 Searching Annoy index using 1 thread, search_k = 3000
20:50:19 Annoy recall = 100%
20:50:20 Commencing smooth kNN distance calibration using 1 thread with target n_neighbors = 30
20:50:24 Initializing from normalized Laplacian + noise (using RSpectra)
20:50:27 Commencing optimization for 200 epochs, with 2089626 positive edges
Using method 'umap'
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
20:50:56 Optimization finished
# Find neighbors and clusters using the Harmony reduction
All_samples_Merged <- FindNeighbors(All_samples_Merged, reduction = "harmony", dims = 1:16)
Computing nearest neighbor graph
Computing SNN
All_samples_Merged <- FindClusters(All_samples_Merged, resolution = 0.5)
Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck
Number of nodes: 49388
Number of edges: 1563357
Running Louvain algorithm...
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.9144
Number of communities: 15
Elapsed time: 15 seconds
# 7. Visualization after Harmony
# By cell line
p3 <- DimPlot(All_samples_Merged,
reduction = "umap.harmony",
group.by = "cell_line",
label = TRUE,
label.box = TRUE) +
ggtitle("After Harmony - By Cell Line")
# By clusters
p4 <- DimPlot(All_samples_Merged,
reduction = "umap.harmony",
group.by = "seurat_clusters",
label = TRUE,
label.box = TRUE) +
ggtitle("After Harmony - By Clusters")
# By cell type annotations
p5 <- DimPlot(All_samples_Merged,
reduction = "umap.harmony",
group.by = "predicted.celltype.l2",
label = TRUE,
label.box = TRUE) +
ggtitle("After Harmony - Cell Type Annotations")
# Print comparison plots
p3 + p4

print(p5)

DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line", label = T, label.box = T) +
ggtitle("Harmony Integration - By Cell Line")

DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "seurat_clusters",label = T, label.box = T) +
ggtitle("Harmony Integration - By Clusters")

DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "predicted.celltype.l2",label = T, label.box = T) +
ggtitle("Harmony Integration - Annotations")

Marker Gene Visualization
# Set marker genes specific to requested immune cell types
myfeatures1 <- c("CD19", "CD79A", "MS4A1", # B cells
"CD14", "LYZ", "FCGR3A", # Monocytes
"CSF1R", "CD68", # Macrophages
"NKG7", "GNLY", "KIR3DL1", # NK cells
"MKI67", # Proliferating NK cells
"CD34", "KIT", # HSPCs
"CD3E", "CCR7", # T cells
"SELL", "CD45RO", # Tnaive, Tcm
"CD44", "CD45RA") # Tem, Temra
# Define markers specific to CD4 T cells and their subsets
cd4_markers <- c(
"CD4", # General CD4 T cells
"IL7R", # Naive T cells
"CCR7", # T central memory (Tcm) cells
"SELL", # T naive cells
"FOXP3", # Regulatory T cells (Tregs)
"IL2RA", # Activated T cells
"PDCD1", # Exhausted T cells
"LAG3", # Exhausted T cells
"TIGIT", # Exhausted T cells
"GATA3", # Th2 cells
"TBX21", # Th1 cells
"RORC", # Th17 cells
"BCL6" # T follicular helper (Tfh) cells
)
# Visualize marker genes for CD4 T cells
cd4_feature_plot <- FeaturePlot(
All_samples_Merged,
features = cd4_markers,
reduction = "umap.harmony",
ncol = 4
) +
ggtitle("CD4 T Cell Marker Expression - Harmony Integration") +
NoLegend()
# Display the plot
print(cd4_feature_plot)

CD4 T Cell Marker Visualization
# Set marker genes specific to CD4 T cell biology and states
cd4_markers <- c(
# Core T cell markers
"CD3E", # T cell marker
"CD4", # CD4 T cell marker
# Naive/Memory markers
"CCR7", # Naive/Central memory
"SELL", # L-selectin, naive marker
"CD27", # Memory marker
"IL7R", # Naive/Memory marker
# Activation/State markers
"IL2RA", # CD25, activation marker
"CD69", # Early activation
"HLA-DRA", # Activation marker
# Exhaustion markers
"PDCD1", # PD-1
"LAG3", # Exhaustion marker
"TIGIT", # Exhaustion marker
# Regulatory T cell markers
"FOXP3", # Treg marker
"IL2RA", # CD25, Treg marker
"CTLA4", # Treg/exhaustion marker
# Effector/Function markers
"IL2", # T cell function
"IFNG", # Th1
"IL4", # Th2
"IL13", # Th2
"IL17A" # Th17
)
# Create feature plots with better visualization
FeaturePlot(All_samples_Merged,
features = cd4_markers,
reduction = "umap.harmony",
ncol = 4,
pt.size = 0.1, # Smaller point size for better resolution
min.cutoff = "q1", # Remove bottom 1% of expression
max.cutoff = "q99", # Remove top 1% of expression
order = TRUE) + # Plot highest expressing cells on top
ggtitle("CD4 T Cell Marker Expression - Harmony Integration") +
theme(plot.title = element_text(size = 16, face = "bold")) +
NoLegend()

# Optional: Add violin plots to see expression distribution across clusters
VlnPlot(All_samples_Merged,
features = cd4_markers[1:8], # First 8 markers
stack = TRUE,
flip = TRUE) +
ggtitle("CD4 T Cell Marker Distribution Across Clusters")

NA
NA
LS0tCnRpdGxlOiAiSGFybW9ueSBpbnRlZ3JhdGlvbnMgb2YgUEJNQzEweCBieSBjZWxsX2xpbmUtdGhldGEtMC41X3JlbW92aW5nIG5vbiBDRDRUY2VsbHMgYW5kIEIgY2VsbHMgZnJvbSBMNCIKYXV0aG9yOiBOYXNpciBNYWhtb29kIEFiYmFzaQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICAjcm1kZm9ybWF0czo6cmVhZHRoZWRvd24KICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19jb2xsYXBzZWQ6IHRydWUKLS0tCgoKIyAxLiBsb2FkIGxpYnJhcmllcwpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoU2V1cmF0V3JhcHBlcnMpCmxpYnJhcnkoU2V1cmF0T2JqZWN0KQpsaWJyYXJ5KFNldXJhdERhdGEpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KGhhcm1vbnkpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShyZXRpY3VsYXRlKQpsaWJyYXJ5KEF6aW11dGgpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoUnRzbmUpCmxpYnJhcnkoaGFybW9ueSkKCm9wdGlvbnMoZnV0dXJlLmdsb2JhbHMubWF4U2l6ZSA9IDFlOSkKCmBgYAoKCgoKIyAyLiBMb2FkIFNldXJhdCBPYmplY3QgCmBgYHtyIGxvYWRfc2V1cmF0LCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCiNMb2FkIFNldXJhdCBPYmplY3QgbWVyZ2VkIGZyb20gY2VsbCBsaW5lcyBhbmQgYSBjb250cm9sKFBCTUMpIGFmdGVyIGZpbHRyYXRpb24KbG9hZCgiMC1pbXBfUm9iai9BbGxfU2FtcGxlc19NZXJnZWRfd2l0aF8xMHhfQXppdG11dGhfQW5ub3RhdGVkX1NDVF9IUENfd2l0aG91dF9oYXJtb255X2ludGVncmF0aW9uX3JlbW92ZWRfbm9uQ0Q0Y2VsbHNfZnJvbV9jb250cm9sX2FuZF9CY2VsbHNfZnJvbV9MNC5yb2JqIikKCkFsbF9zYW1wbGVzX01lcmdlZAoKIyBJZGVudGlmeSBhbmQgcmVtb3ZlIElMQyBhbmQgTksgY2VsbHMKaWxjX25rX2NlbGxzIDwtIFdoaWNoQ2VsbHMoQWxsX3NhbXBsZXNfTWVyZ2VkLCBleHByZXNzaW9uID0gCiAgZ3JlcGwoIl5OSyIsIHByZWRpY3RlZC5jZWxsdHlwZS5sMikgfCAKICBncmVwbCgiXklMQyIsIHByZWRpY3RlZC5jZWxsdHlwZS5sMikKKQoKIyBTdWJzZXQgdG8gZXhjbHVkZSBJTEMgYW5kIE5LIGNlbGxzCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBzdWJzZXQoQWxsX3NhbXBsZXNfTWVyZ2VkLCBjZWxscyA9IHNldGRpZmYoQ2VsbHMoQWxsX3NhbXBsZXNfTWVyZ2VkKSwgaWxjX25rX2NlbGxzKSkKCgojIFJlY2FsY3VsYXRlIFBDQQpBbGxfc2FtcGxlc19NZXJnZWQgPC0gUnVuUENBKEFsbF9zYW1wbGVzX01lcmdlZCwgbnBjcyA9IDUwLCB2ZXJib3NlID0gRkFMU0UpCgpFbGJvd1Bsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkKQoKIyBDaGVjayBvcmlnaW5hbCBVTUFQIGJlZm9yZSBpbnRlZ3JhdGlvbgpwMSA8LSBEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgCiAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICBncm91cC5ieSA9ICJjZWxsX2xpbmUiLAogICAgICAgICAgICAgIGxhYmVsID0gVFJVRSwgCiAgICAgICAgICAgICAgbGFiZWwuYm94ID0gVFJVRSkgKyAKICAgICAgZ2d0aXRsZSgiQmVmb3JlIEhhcm1vbnkgLSBCeSBDZWxsIExpbmUiKQoKcDIgPC0gRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwKICAgICAgICAgICAgICBsYWJlbCA9IFRSVUUsIAogICAgICAgICAgICAgIGxhYmVsLmJveCA9IFRSVUUpICsgCiAgICAgIGdndGl0bGUoIkJlZm9yZSBIYXJtb255IC0gQnkgQ2x1c3RlcnMiKQoKIyBQcmludCBvcmlnaW5hbCBwbG90cwpwMSArIHAyCgpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgCiAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICBncm91cC5ieSA9ICJjZWxsX2xpbmUiLAogICAgICAgICAgICAgIGxhYmVsID0gVFJVRSwgCiAgICAgICAgICAgICAgbGFiZWwuYm94ID0gVFJVRSkgKyAKICAgICAgZ2d0aXRsZSgiQmVmb3JlIEhhcm1vbnkgLSBCeSBDZWxsIExpbmUiKQoKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwKICAgICAgICAgICAgICBsYWJlbCA9IFRSVUUsIAogICAgICAgICAgICAgIGxhYmVsLmJveCA9IFRSVUUpICsgCiAgICAgIGdndGl0bGUoIkJlZm9yZSBIYXJtb255IC0gQnkgQ2x1c3RlcnMiKQpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgCiAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICBncm91cC5ieSA9ICJwcmVkaWN0ZWQuY2VsbHR5cGUubDEiLAogICAgICAgICAgICAgIGxhYmVsID0gVFJVRSwgCiAgICAgICAgICAgICAgbGFiZWwuYm94ID0gVFJVRSkgKyAKICAgICAgZ2d0aXRsZSgiQmVmb3JlIEhhcm1vbnkgLSBCeSBBbm5vdGF0aW9uLmwxIikKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCAKICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgIGdyb3VwLmJ5ID0gInByZWRpY3RlZC5jZWxsdHlwZS5sMiIsCiAgICAgICAgICAgICAgbGFiZWwgPSBUUlVFLCAKICAgICAgICAgICAgICBsYWJlbC5ib3ggPSBUUlVFKSArIAogICAgICBnZ3RpdGxlKCJCZWZvcmUgSGFybW9ueSAtIEJ5IEFubm90YXRpb24ubDIiKQoKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAicHJlZGljdGVkLmNlbGx0eXBlLmwzIiwKICAgICAgICAgICAgICBsYWJlbCA9IFRSVUUsIAogICAgICAgICAgICAgIGxhYmVsLmJveCA9IFRSVUUpICsgCiAgICAgIGdndGl0bGUoIkJlZm9yZSBIYXJtb255IC0gQnkgQW5ub3RhdGlvbi5sMyIpCgpgYGAKCgojIyAgSGFybW9ueSBWaXN1YWxpemF0aW9uLTEKYGBge3IgaGFybW9ueS12aXN1YWxpemF0aW9uMSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CmxpYnJhcnkoaGFybW9ueSkKCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBSdW5IYXJtb255KAogIG9iamVjdCA9IEFsbF9zYW1wbGVzX01lcmdlZCwKICBncm91cC5ieS52YXJzID0gImNlbGxfbGluZSIsCiAgZGltcy51c2UgPSAxOjE2LAogIHRoZXRhID0gMC41LCAgIyBMb3dlciB0aGV0YSB0byBtYWludGFpbiBiaW9sb2dpY2FsIGRpZmZlcmVuY2VzCiAgcGxvdF9jb252ZXJnZW5jZSA9IFRSVUUKKQoKIyBSdW4gVU1BUCBvbiB0aGUgbmV3IEhhcm1vbnkgcmVkdWN0aW9uCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBSdW5VTUFQKEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gImhhcm1vbnkiLCBkaW1zID0gMToxNiwgcmVkdWN0aW9uLm5hbWUgPSAidW1hcC5oYXJtb255IikKCiMgRmluZCBuZWlnaGJvcnMgYW5kIGNsdXN0ZXJzIHVzaW5nIHRoZSBIYXJtb255IHJlZHVjdGlvbgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gRmluZE5laWdoYm9ycyhBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJoYXJtb255IiwgZGltcyA9IDE6MTYpCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBGaW5kQ2x1c3RlcnMoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZXNvbHV0aW9uID0gMC41KQoKCiMgNy4gVmlzdWFsaXphdGlvbiBhZnRlciBIYXJtb255CiMgQnkgY2VsbCBsaW5lCnAzIDwtIERpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCAKICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgCiAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAiY2VsbF9saW5lIiwKICAgICAgICAgICAgICBsYWJlbCA9IFRSVUUsIAogICAgICAgICAgICAgIGxhYmVsLmJveCA9IFRSVUUpICsgCiAgICAgIGdndGl0bGUoIkFmdGVyIEhhcm1vbnkgLSBCeSBDZWxsIExpbmUiKQoKIyBCeSBjbHVzdGVycwpwNCA8LSBEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgCiAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIAogICAgICAgICAgICAgIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsCiAgICAgICAgICAgICAgbGFiZWwgPSBUUlVFLCAKICAgICAgICAgICAgICBsYWJlbC5ib3ggPSBUUlVFKSArIAogICAgICBnZ3RpdGxlKCJBZnRlciBIYXJtb255IC0gQnkgQ2x1c3RlcnMiKQoKIyBCeSBjZWxsIHR5cGUgYW5ub3RhdGlvbnMKcDUgPC0gRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLCAKICAgICAgICAgICAgICBncm91cC5ieSA9ICJwcmVkaWN0ZWQuY2VsbHR5cGUubDIiLAogICAgICAgICAgICAgIGxhYmVsID0gVFJVRSwgCiAgICAgICAgICAgICAgbGFiZWwuYm94ID0gVFJVRSkgKyAKICAgICAgZ2d0aXRsZSgiQWZ0ZXIgSGFybW9ueSAtIENlbGwgVHlwZSBBbm5vdGF0aW9ucyIpCgojIFByaW50IGNvbXBhcmlzb24gcGxvdHMKcDMgKyBwNApwcmludChwNSkKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAiY2VsbF9saW5lIiwgbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKSArIAogIGdndGl0bGUoIkhhcm1vbnkgSW50ZWdyYXRpb24gLSBCeSBDZWxsIExpbmUiKQpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKSArIAogIGdndGl0bGUoIkhhcm1vbnkgSW50ZWdyYXRpb24gLSBCeSBDbHVzdGVycyIpCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAicHJlZGljdGVkLmNlbGx0eXBlLmwyIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpICsgCiAgZ2d0aXRsZSgiSGFybW9ueSBJbnRlZ3JhdGlvbiAtIEFubm90YXRpb25zIikKCmBgYAoKIyMgIE1hcmtlciBHZW5lIFZpc3VhbGl6YXRpb24KYGBge3IgZmVhdHVyZXBsb3QtaGFybW9ueTEsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD0xOH0KCgojIFNldCBtYXJrZXIgZ2VuZXMgc3BlY2lmaWMgdG8gcmVxdWVzdGVkIGltbXVuZSBjZWxsIHR5cGVzCm15ZmVhdHVyZXMxIDwtIGMoIkNEMTkiLCAiQ0Q3OUEiLCAiTVM0QTEiLCAjIEIgY2VsbHMKICAgICAgICAgICAgICAgICJDRDE0IiwgIkxZWiIsICJGQ0dSM0EiLCAjIE1vbm9jeXRlcwogICAgICAgICAgICAgICAgIkNTRjFSIiwgIkNENjgiLCAjIE1hY3JvcGhhZ2VzCiAgICAgICAgICAgICAgICAiTktHNyIsICJHTkxZIiwgIktJUjNETDEiLCAjIE5LIGNlbGxzCiAgICAgICAgICAgICAgICAiTUtJNjciLCAjIFByb2xpZmVyYXRpbmcgTksgY2VsbHMKICAgICAgICAgICAgICAgICJDRDM0IiwgIktJVCIsICMgSFNQQ3MKICAgICAgICAgICAgICAgICJDRDNFIiwgIkNDUjciLCAjIFQgY2VsbHMKICAgICAgICAgICAgICAgICJTRUxMIiwgIkNENDVSTyIsICMgVG5haXZlLCBUY20KICAgICAgICAgICAgICAgICJDRDQ0IiwgIkNENDVSQSIpICMgVGVtLCBUZW1yYQoKCgojIERlZmluZSBtYXJrZXJzIHNwZWNpZmljIHRvIENENCBUIGNlbGxzIGFuZCB0aGVpciBzdWJzZXRzCmNkNF9tYXJrZXJzIDwtIGMoCiAgIkNENCIsICAgICAgICAgICMgR2VuZXJhbCBDRDQgVCBjZWxscwogICJJTDdSIiwgICAgICAgICAjIE5haXZlIFQgY2VsbHMKICAiQ0NSNyIsICAgICAgICAgIyBUIGNlbnRyYWwgbWVtb3J5IChUY20pIGNlbGxzCiAgIlNFTEwiLCAgICAgICAgICMgVCBuYWl2ZSBjZWxscwogICJGT1hQMyIsICAgICAgICAjIFJlZ3VsYXRvcnkgVCBjZWxscyAoVHJlZ3MpCiAgIklMMlJBIiwgICAgICAgICMgQWN0aXZhdGVkIFQgY2VsbHMKICAiUERDRDEiLCAgICAgICAgIyBFeGhhdXN0ZWQgVCBjZWxscwogICJMQUczIiwgICAgICAgICAjIEV4aGF1c3RlZCBUIGNlbGxzCiAgIlRJR0lUIiwgICAgICAgICMgRXhoYXVzdGVkIFQgY2VsbHMKICAiR0FUQTMiLCAgICAgICAgIyBUaDIgY2VsbHMKICAiVEJYMjEiLCAgICAgICAgIyBUaDEgY2VsbHMKICAiUk9SQyIsICAgICAgICAgIyBUaDE3IGNlbGxzCiAgIkJDTDYiICAgICAgICAgICMgVCBmb2xsaWN1bGFyIGhlbHBlciAoVGZoKSBjZWxscwopCgojIFZpc3VhbGl6ZSBtYXJrZXIgZ2VuZXMgZm9yIENENCBUIGNlbGxzCmNkNF9mZWF0dXJlX3Bsb3QgPC0gRmVhdHVyZVBsb3QoCiAgQWxsX3NhbXBsZXNfTWVyZ2VkLCAKICBmZWF0dXJlcyA9IGNkNF9tYXJrZXJzLCAKICByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgCiAgbmNvbCA9IDQKKSArIAogIGdndGl0bGUoIkNENCBUIENlbGwgTWFya2VyIEV4cHJlc3Npb24gLSBIYXJtb255IEludGVncmF0aW9uIikgKwogIE5vTGVnZW5kKCkKCiMgRGlzcGxheSB0aGUgcGxvdApwcmludChjZDRfZmVhdHVyZV9wbG90KQpgYGAKCiMjICBDRDQgVCBDZWxsIE1hcmtlciBWaXN1YWxpemF0aW9uCmBgYHtyIGZlYXR1cmVwbG90LWhhcm1vbnkyLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTZ9CiMgU2V0IG1hcmtlciBnZW5lcyBzcGVjaWZpYyB0byBDRDQgVCBjZWxsIGJpb2xvZ3kgYW5kIHN0YXRlcwpjZDRfbWFya2VycyA8LSBjKAogICAgIyBDb3JlIFQgY2VsbCBtYXJrZXJzCiAgICAiQ0QzRSIsICAgICAjIFQgY2VsbCBtYXJrZXIKICAgICJDRDQiLCAgICAgICMgQ0Q0IFQgY2VsbCBtYXJrZXIKICAgIAogICAgIyBOYWl2ZS9NZW1vcnkgbWFya2VycwogICAgIkNDUjciLCAgICAgIyBOYWl2ZS9DZW50cmFsIG1lbW9yeQogICAgIlNFTEwiLCAgICAgIyBMLXNlbGVjdGluLCBuYWl2ZSBtYXJrZXIKICAgICJDRDI3IiwgICAgICMgTWVtb3J5IG1hcmtlcgogICAgIklMN1IiLCAgICAgIyBOYWl2ZS9NZW1vcnkgbWFya2VyCiAgICAKICAgICMgQWN0aXZhdGlvbi9TdGF0ZSBtYXJrZXJzCiAgICAiSUwyUkEiLCAgICAjIENEMjUsIGFjdGl2YXRpb24gbWFya2VyCiAgICAiQ0Q2OSIsICAgICAjIEVhcmx5IGFjdGl2YXRpb24KICAgICJITEEtRFJBIiwgICMgQWN0aXZhdGlvbiBtYXJrZXIKICAgIAogICAgIyBFeGhhdXN0aW9uIG1hcmtlcnMKICAgICJQRENEMSIsICAgICMgUEQtMQogICAgIkxBRzMiLCAgICAgIyBFeGhhdXN0aW9uIG1hcmtlcgogICAgIlRJR0lUIiwgICAgIyBFeGhhdXN0aW9uIG1hcmtlcgogICAgCiAgICAjIFJlZ3VsYXRvcnkgVCBjZWxsIG1hcmtlcnMKICAgICJGT1hQMyIsICAgICMgVHJlZyBtYXJrZXIKICAgICJJTDJSQSIsICAgICMgQ0QyNSwgVHJlZyBtYXJrZXIKICAgICJDVExBNCIsICAgICMgVHJlZy9leGhhdXN0aW9uIG1hcmtlcgogICAgCiAgICAjIEVmZmVjdG9yL0Z1bmN0aW9uIG1hcmtlcnMKICAgICJJTDIiLCAgICAgICMgVCBjZWxsIGZ1bmN0aW9uCiAgICAiSUZORyIsICAgICAjIFRoMQogICAgIklMNCIsICAgICAgIyBUaDIKICAgICJJTDEzIiwgICAgICMgVGgyCiAgICAiSUwxN0EiICAgICAjIFRoMTcKKQoKIyBDcmVhdGUgZmVhdHVyZSBwbG90cyB3aXRoIGJldHRlciB2aXN1YWxpemF0aW9uCkZlYXR1cmVQbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgCiAgICAgICAgICAgIGZlYXR1cmVzID0gY2Q0X21hcmtlcnMsIAogICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgCiAgICAgICAgICAgIG5jb2wgPSA0LAogICAgICAgICAgICBwdC5zaXplID0gMC4xLCAgICAgICAgICAgIyBTbWFsbGVyIHBvaW50IHNpemUgZm9yIGJldHRlciByZXNvbHV0aW9uCiAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTEiLCAgICAgICAjIFJlbW92ZSBib3R0b20gMSUgb2YgZXhwcmVzc2lvbgogICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5OSIsICAgICAgIyBSZW1vdmUgdG9wIDElIG9mIGV4cHJlc3Npb24KICAgICAgICAgICAgb3JkZXIgPSBUUlVFKSArICAgICAgICAgICMgUGxvdCBoaWdoZXN0IGV4cHJlc3NpbmcgY2VsbHMgb24gdG9wCiAgICBnZ3RpdGxlKCJDRDQgVCBDZWxsIE1hcmtlciBFeHByZXNzaW9uIC0gSGFybW9ueSBJbnRlZ3JhdGlvbiIpICsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSkgKwogICAgTm9MZWdlbmQoKQoKIyBPcHRpb25hbDogQWRkIHZpb2xpbiBwbG90cyB0byBzZWUgZXhwcmVzc2lvbiBkaXN0cmlidXRpb24gYWNyb3NzIGNsdXN0ZXJzClZsblBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCAKICAgICAgICBmZWF0dXJlcyA9IGNkNF9tYXJrZXJzWzE6OF0sICMgRmlyc3QgOCBtYXJrZXJzCiAgICAgICAgc3RhY2sgPSBUUlVFLAogICAgICAgIGZsaXAgPSBUUlVFKSArCiAgICAgICAgZ2d0aXRsZSgiQ0Q0IFQgQ2VsbCBNYXJrZXIgRGlzdHJpYnV0aW9uIEFjcm9zcyBDbHVzdGVycyIpCgoKYGBgCgojIDQuIFNhdmUgdGhlIFNldXJhdCBvYmplY3QgYXMgYW4gUm9iaiBmaWxlCmBgYHtyIHNhdmVST0JKfQoKI3NhdmUoQWxsX3NhbXBsZXNfTWVyZ2VkLCBmaWxlID0gIi4uLy4uLy4uLzAtSU1QLU9CSkVDVFMvSGFybW9ueV9pbnRlZ3JhdGVkX0FsbF9zYW1wbGVzX01lcmdlZF93aXRoX1BCTUMxMHguUm9iaiIpCgpgYGAKCgoKCg==