1. load libraries
2. Load Seurat Object
#Load Seurat Object merged from cell lines and a control(PBMC) after filtration
load("../../../0-IMP-OBJECTS/All_Samples_Merged_with_10x_Azitmuth_Annotated_SCT_HPC_without_harmony_integration.robj")
All_samples_Merged
An object of class Seurat
64169 features across 59355 samples within 6 assays
Active assay: SCT (27417 features, 3000 variable features)
3 layers present: counts, data, scale.data
5 other assays present: RNA, ADT, prediction.score.celltype.l1, prediction.score.celltype.l2, prediction.score.celltype.l3
4 dimensional reductions calculated: integrated_dr, ref.umap, pca, umap
3. Data PREPARATION and Harmony Integration-1
library(harmony)
All_samples_Merged <- RunHarmony(
object = All_samples_Merged,
group.by.vars = "cell_line", # Replace with the metadata column specifying batch or cell line
dims.use = 1:22, # Use the same dimensions as PCA
assay.use = "SCT",
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 3/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 3 iterations

# Run UMAP on the new Harmony reduction
All_samples_Merged <- RunUMAP(All_samples_Merged, reduction = "harmony", dims = 1:22, reduction.name = "umap.harmony")
Avis : The default method for RunUMAP has changed from calling Python UMAP via reticulate to the R-native UWOT using the cosine metric
To use Python UMAP via reticulate, set umap.method to 'umap-learn' and metric to 'correlation'
This message will be shown once per session20:52:39 UMAP embedding parameters a = 0.9922 b = 1.112
20:52:39 Read 59355 rows and found 22 numeric columns
20:52:39 Using Annoy for neighbor search, n_neighbors = 30
20:52:39 Building Annoy index with metric = cosine, n_trees = 50
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
20:52:47 Writing NN index file to temp file /tmp/RtmpXZmaNf/file3adae7a1148d
20:52:47 Searching Annoy index using 1 thread, search_k = 3000
20:53:16 Annoy recall = 100%
20:53:17 Commencing smooth kNN distance calibration using 1 thread with target n_neighbors = 30
20:53:21 Initializing from normalized Laplacian + noise (using RSpectra)
20:53:24 Commencing optimization for 200 epochs, with 2569038 positive edges
Using method 'umap'
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
20:54:02 Optimization finished
# Find neighbors and clusters using the Harmony reduction
All_samples_Merged <- FindNeighbors(All_samples_Merged, reduction = "harmony", dims = 1:22)
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: 59355
Number of edges: 1769146
Running Louvain algorithm...
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.8990
Number of communities: 18
Elapsed time: 20 seconds
# Visualize results
p1 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line") +
ggtitle("Harmony Integration - By Cell Line")
p2 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "seurat_clusters") +
ggtitle("Harmony Integration - By Clusters")
# Compare with original UMAP
p3 <- DimPlot(All_samples_Merged, reduction = "umap", group.by = "cell_line") +
ggtitle("Original Integration - By Cell Line")
p4 <- DimPlot(All_samples_Merged, reduction = "umap", group.by = "seurat_clusters") +
ggtitle("Original Integration - By Clusters")
# Print the plots
print(p1 + p2)

print(p3 + p4)

NA
NA
Harmony Visualization-1
# Visualize results
p1 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line", label = T, label.box = T) +
ggtitle("Harmony Integration - By Cell Line")
p2 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "seurat_clusters",label = T, label.box = T) +
ggtitle("Harmony Integration - By Clusters")
# Compare with original UMAP
p3 <- DimPlot(All_samples_Merged, reduction = "umap", group.by = "cell_line",label = T, label.box = T) +
ggtitle("Original Integration - By Cell Line")
p4 <- DimPlot(All_samples_Merged, reduction = "umap", group.by = "seurat_clusters",label = T, label.box = T) +
ggtitle("Original Integration - By Clusters")
# Print the plots
print(p1 + p2)

print(p3 + p4)

4. Data PREPARATION and Harmony Integration-2
library(harmony)
All_samples_Merged <- RunHarmony(
object = All_samples_Merged,
group.by.vars = "cell_line", # Replace with the metadata column specifying batch or cell line
dims.use = 1:22, # Use the same dimensions as PCA
assay.use = "SCT",
Theta = 0.5,
lambda =0.5,
plot_convergence = TRUE
)
Transposing data matrix
Initializing state using k-means centroids initialization
Avis : Les étapes de transfer (quick-TRANSfer stage) ont dépassé le maximum (= 2967750)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 3/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 3 iterations

# Run UMAP on the new Harmony reduction
All_samples_Merged <- RunUMAP(All_samples_Merged, reduction = "harmony", dims = 1:22, reduction.name = "umap.harmony")
21:23:30 UMAP embedding parameters a = 0.9922 b = 1.112
21:23:30 Read 59355 rows and found 22 numeric columns
21:23:30 Using Annoy for neighbor search, n_neighbors = 30
21:23:30 Building Annoy index with metric = cosine, n_trees = 50
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
21:23:37 Writing NN index file to temp file /tmp/RtmpXZmaNf/file3adae591aca7d
21:23:37 Searching Annoy index using 1 thread, search_k = 3000
21:24:06 Annoy recall = 100%
21:24:07 Commencing smooth kNN distance calibration using 1 thread with target n_neighbors = 30
21:24:11 Initializing from normalized Laplacian + noise (using RSpectra)
21:24:14 Commencing optimization for 200 epochs, with 2575888 positive edges
Using method 'umap'
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
21:24:52 Optimization finished
# Find neighbors and clusters using the Harmony reduction
All_samples_Merged <- FindNeighbors(All_samples_Merged, reduction = "harmony", dims = 1:22)
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: 59355
Number of edges: 1756087
Running Louvain algorithm...
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.8918
Number of communities: 17
Elapsed time: 26 seconds
Harmony Visualization-2
# Visualize results
p1 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line", label = T, label.box = T) +
ggtitle("Harmony Integration - By Cell Line")
p2 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "seurat_clusters",label = T, label.box = T) +
ggtitle("Harmony Integration - By Clusters")
# Compare with original UMAP
p3 <- DimPlot(All_samples_Merged, reduction = "umap", group.by = "cell_line",label = T, label.box = T) +
ggtitle("Original Integration - By Cell Line")
p4 <- DimPlot(All_samples_Merged, reduction = "umap", group.by = "seurat_clusters",label = T, label.box = T) +
ggtitle("Original Integration - By Clusters")
# Print the plots
print(p1 + p2)

print(p3 + p4)

5. Data PREPARATION and Harmony Integration-3
# Create a new metadata column for grouping
All_samples_Merged$sample_group <- case_when(
grepl("^L", All_samples_Merged$cell_line) ~ "Cell_Line",
All_samples_Merged$cell_line == "PBMC" ~ "PBMC",
All_samples_Merged$cell_line == "PBMC_10x" ~ "PBMC_10x",
TRUE ~ "Other"
)
# Create the cell line grouping correctly
All_samples_Merged$cell_line_group <- case_when(
grepl("^L[1-2]", All_samples_Merged$cell_line) ~ "P1",
grepl("^L[3-4]", All_samples_Merged$cell_line) ~ "P2",
grepl("^L[5-7]", All_samples_Merged$cell_line) ~ "P3",
All_samples_Merged$cell_line == "PBMC" ~ "PBMC",
All_samples_Merged$cell_line == "PBMC_10x" ~ "PBMC_10x",
TRUE ~ "Other" # This catches any unexpected values
)
library(harmony)
All_samples_Merged <- RunHarmony(
object = All_samples_Merged,
group.by.vars = "sample_group",
dims.use = 1:22, # Increased to capture more variation
theta = c(0.5), # Adjust these values as needed
plot_convergence = TRUE
)
Transposing data matrix
Initializing state using k-means centroids initialization
Avis : Les étapes de transfer (quick-TRANSfer stage) ont dépassé le maximum (= 2967750)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:22, reduction.name = "umap.harmony")
22:10:52 UMAP embedding parameters a = 0.9922 b = 1.112
22:10:52 Read 59355 rows and found 22 numeric columns
22:10:52 Using Annoy for neighbor search, n_neighbors = 30
22:10:52 Building Annoy index with metric = cosine, n_trees = 50
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
22:11:00 Writing NN index file to temp file /tmp/RtmpXZmaNf/file3adae5b8271ac
22:11:22 Searching Annoy index using 1 thread, search_k = 3000
22:11:47 Annoy recall = 100%
22:11:49 Commencing smooth kNN distance calibration using 1 thread with target n_neighbors = 30
22:12:36 Initializing from normalized Laplacian + noise (using RSpectra)
22:12:46 Commencing optimization for 200 epochs, with 2535858 positive edges
Using method 'umap'
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
22:13:22 Optimization finished
# Find neighbors and clusters using the Harmony reduction
All_samples_Merged <- FindNeighbors(All_samples_Merged, reduction = "harmony", dims = 1:22)
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: 59355
Number of edges: 1956184
Running Louvain algorithm...
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.9485
Number of communities: 21
Elapsed time: 46 seconds
Harmony Visualization-3
p1 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "sample_group", label = T, label.box = T)
p2 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line_group",label = T, label.box = T)
p3 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line",label = T, label.box = T)
p1 + p2 + p3

DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "sample_group",label = T, label.box = T)

DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line_group",label = T, label.box = T)

DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line",label = T, label.box = T)

# Compare with original UMAP
p4 <- DimPlot(All_samples_Merged, reduction = "umap", group.by = "cell_line",label = T, label.box = T) +
ggtitle("Original Integration - By Cell Line")
p5 <- DimPlot(All_samples_Merged, reduction = "umap", group.by = "seurat_clusters",label = T, label.box = T) +
ggtitle("Original Integration - By Clusters")
# Print the plots
print(p4 + p5)

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

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

# Visualize results
p6 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line", label = T, label.box = T) +
ggtitle("Harmony Integration - By Cell Line")
p7 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "seurat_clusters",label = T, label.box = T) +
ggtitle("Harmony Integration - By Clusters")
# Print the plots
print(p6 + p7)

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

p7 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "seurat_clusters",label = T, label.box = T) +
ggtitle("Harmony Integration - By Clusters")
6. Data PREPARATION and Harmony Integration-4
# Create a new metadata column for grouping
All_samples_Merged$sample_group <- case_when(
grepl("^L", All_samples_Merged$cell_line) ~ "Cell_Line",
All_samples_Merged$cell_line == "PBMC" ~ "PBMC",
All_samples_Merged$cell_line == "PBMC_10x" ~ "PBMC_10x",
TRUE ~ "Other"
)
# Create the cell line grouping correctly
All_samples_Merged$cell_line_group <- case_when(
grepl("^L[1-2]", All_samples_Merged$cell_line) ~ "P1",
grepl("^L[3-4]", All_samples_Merged$cell_line) ~ "P2",
grepl("^L[5-7]", All_samples_Merged$cell_line) ~ "P3",
All_samples_Merged$cell_line == "PBMC" ~ "PBMC",
All_samples_Merged$cell_line == "PBMC_10x" ~ "PBMC_10x",
TRUE ~ "Other" # This catches any unexpected values
)
library(harmony)
All_samples_Merged <- RunHarmony(
object = All_samples_Merged,
group.by.vars = "cell_line_group",
dims.use = 1:22, # Increased to capture more variation
theta = c(0.5), # Adjust these values as needed
plot_convergence = TRUE
)
Transposing data matrix
Initializing state using k-means centroids initialization
Avis : Les étapes de transfer (quick-TRANSfer stage) ont dépassé le maximum (= 2967750)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:22, reduction.name = "umap.harmony")
22:21:18 UMAP embedding parameters a = 0.9922 b = 1.112
22:21:18 Read 59355 rows and found 22 numeric columns
22:21:18 Using Annoy for neighbor search, n_neighbors = 30
22:21:18 Building Annoy index with metric = cosine, n_trees = 50
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
22:21:26 Writing NN index file to temp file /tmp/RtmpXZmaNf/file3adae14396554
22:21:26 Searching Annoy index using 1 thread, search_k = 3000
22:21:51 Annoy recall = 100%
22:21:52 Commencing smooth kNN distance calibration using 1 thread with target n_neighbors = 30
22:21:57 Initializing from normalized Laplacian + noise (using RSpectra)
22:22:03 Commencing optimization for 200 epochs, with 2541136 positive edges
Using method 'umap'
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
22:22:41 Optimization finished
# Find neighbors and clusters using the Harmony reduction
All_samples_Merged <- FindNeighbors(All_samples_Merged, reduction = "harmony", dims = 1:22)
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: 59355
Number of edges: 1951462
Running Louvain algorithm...
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.9474
Number of communities: 21
Elapsed time: 24 seconds
Harmony Visualization-4
p1 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "sample_group", label = T, label.box = T)
p2 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line_group",label = T, label.box = T)
p3 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line",label = T, label.box = T)
p1 + p2 + p3

DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "sample_group",label = T, label.box = T)

DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line_group",label = T, label.box = T)

DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line",label = T, label.box = T)

# Compare with original UMAP
p4 <- DimPlot(All_samples_Merged, reduction = "umap", group.by = "cell_line",label = T, label.box = T) +
ggtitle("Original Integration - By Cell Line")
p5 <- DimPlot(All_samples_Merged, reduction = "umap", group.by = "seurat_clusters",label = T, label.box = T) +
ggtitle("Original Integration - By Clusters")
# Print the plots
print(p4 + p5)

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

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

# Visualize results
p6 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line", label = T, label.box = T) +
ggtitle("Harmony Integration - By Cell Line")
p7 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "seurat_clusters",label = T, label.box = T) +
ggtitle("Harmony Integration - By Clusters")
# Print the plots
print(p6 + p7)

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

p7 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "seurat_clusters",label = T, label.box = T) +
ggtitle("Harmony Integration - By Clusters")
7. Data PREPARATION and Harmony Integration-5
# Create a new metadata column for grouping
All_samples_Merged$sample_group <- case_when(
grepl("^L", All_samples_Merged$cell_line) ~ "Cell_Line",
All_samples_Merged$cell_line == "PBMC" ~ "PBMC",
All_samples_Merged$cell_line == "PBMC_10x" ~ "PBMC_10x",
TRUE ~ "Other"
)
# Create the cell line grouping correctly
All_samples_Merged$cell_line_group <- case_when(
grepl("^L[1-2]", All_samples_Merged$cell_line) ~ "P1",
grepl("^L[3-4]", All_samples_Merged$cell_line) ~ "P2",
grepl("^L[5-7]", All_samples_Merged$cell_line) ~ "P3",
All_samples_Merged$cell_line == "PBMC" ~ "PBMC",
All_samples_Merged$cell_line == "PBMC_10x" ~ "PBMC_10x",
TRUE ~ "Other" # This catches any unexpected values
)
library(harmony)
All_samples_Merged <- RunHarmony(
object = All_samples_Merged,
group.by.vars = "cell_line",
dims.use = 1:22, # Increased to capture more variation
theta = c(0.5), # Adjust these values as needed
plot_convergence = TRUE
)
Transposing data matrix
Initializing state using k-means centroids initialization
Avis : Les étapes de transfer (quick-TRANSfer stage) ont dépassé le maximum (= 2967750)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:22, reduction.name = "umap.harmony")
22:27:30 UMAP embedding parameters a = 0.9922 b = 1.112
22:27:30 Read 59355 rows and found 22 numeric columns
22:27:30 Using Annoy for neighbor search, n_neighbors = 30
22:27:30 Building Annoy index with metric = cosine, n_trees = 50
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
22:27:38 Writing NN index file to temp file /tmp/RtmpXZmaNf/file3adae432647b0
22:27:38 Searching Annoy index using 1 thread, search_k = 3000
22:28:03 Annoy recall = 100%
22:28:04 Commencing smooth kNN distance calibration using 1 thread with target n_neighbors = 30
22:28:08 Initializing from normalized Laplacian + noise (using RSpectra)
22:28:14 Commencing optimization for 200 epochs, with 2543152 positive edges
Using method 'umap'
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
22:28:51 Optimization finished
# Find neighbors and clusters using the Harmony reduction
All_samples_Merged <- FindNeighbors(All_samples_Merged, reduction = "harmony", dims = 1:22)
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: 59355
Number of edges: 1882456
Running Louvain algorithm...
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.9226
Number of communities: 18
Elapsed time: 24 seconds
Harmony Visualization-5
p1 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "sample_group", label = T, label.box = T)
p2 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line_group",label = T, label.box = T)
p3 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line",label = T, label.box = T)
p1 + p2 + p3

DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "sample_group",label = T, label.box = T)

DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line_group",label = T, label.box = T)

DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line",label = T, label.box = T)

# Compare with original UMAP
p4 <- DimPlot(All_samples_Merged, reduction = "umap", group.by = "cell_line",label = T, label.box = T) +
ggtitle("Original Integration - By Cell Line")
p5 <- DimPlot(All_samples_Merged, reduction = "umap", group.by = "seurat_clusters",label = T, label.box = T) +
ggtitle("Original Integration - By Clusters")
# Print the plots
print(p4 + p5)

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

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

# Visualize results
p6 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "cell_line", label = T, label.box = T) +
ggtitle("Harmony Integration - By Cell Line")
p7 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "seurat_clusters",label = T, label.box = T) +
ggtitle("Harmony Integration - By Clusters")
# Print the plots
print(p6 + p7)

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

p7 <- DimPlot(All_samples_Merged, reduction = "umap.harmony", group.by = "seurat_clusters",label = T, label.box = T) +
ggtitle("Harmony Integration - By Clusters")
Marker Gene Visualization
# Set marker genes specific to requested immune cell types
myfeatures <- 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
# Visualize marker genes for Harmony
FeaturePlot(All_samples_Merged, features = myfeatures, reduction = "umap.harmony", ncol = 4) +
ggtitle("Marker Gene Expression - Harmony Integration") +
NoLegend()
Avis : Could not find CD45RO in the default search locations, found in 'ADT' assay insteadAvis : Could not find CD45RA in the default search locations, found in 'ADT' assay instead

6. Save the Seurat object as an Robj file
#save(All_samples_Merged, file = "integrated_All_samples_Merged_with_PBMC10x.Robj")
LS0tCnRpdGxlOiAiTXVsdGlwbGUgSGFybW9ueSBpbnRlZ3JhdGlvbnMgb2YgUEJNQzEweCIKYXV0aG9yOiBOYXNpciBNYWhtb29kIEFiYmFzaQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICAjcm1kZm9ybWF0czo6cmVhZHRoZWRvd24KICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19jb2xsYXBzZWQ6IHRydWUKLS0tCgojIDEuIGxvYWQgbGlicmFyaWVzCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShTZXVyYXRXcmFwcGVycykKbGlicmFyeShTZXVyYXRPYmplY3QpCmxpYnJhcnkoU2V1cmF0RGF0YSkKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoaGFybW9ueSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHJldGljdWxhdGUpCmxpYnJhcnkoQXppbXV0aCkKbGlicmFyeShkcGx5cikKbGlicmFyeShSdHNuZSkKbGlicmFyeShoYXJtb255KQoKb3B0aW9ucyhmdXR1cmUuZ2xvYmFscy5tYXhTaXplID0gMWU5KQoKYGBgCgoKCgojIDIuIExvYWQgU2V1cmF0IE9iamVjdCAKYGBge3IgbG9hZF9zZXVyYXR9CgojTG9hZCBTZXVyYXQgT2JqZWN0IG1lcmdlZCBmcm9tIGNlbGwgbGluZXMgYW5kIGEgY29udHJvbChQQk1DKSBhZnRlciBmaWx0cmF0aW9uCmxvYWQoIi4uLy4uLy4uLzAtSU1QLU9CSkVDVFMvQWxsX1NhbXBsZXNfTWVyZ2VkX3dpdGhfMTB4X0F6aXRtdXRoX0Fubm90YXRlZF9TQ1RfSFBDX3dpdGhvdXRfaGFybW9ueV9pbnRlZ3JhdGlvbi5yb2JqIikKCkFsbF9zYW1wbGVzX01lcmdlZAoKYGBgCgojIDMuIERhdGEgUFJFUEFSQVRJT04gYW5kIEhhcm1vbnkgSW50ZWdyYXRpb24tMQpgYGB7ciBkYXRhLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCmxpYnJhcnkoaGFybW9ueSkKCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBSdW5IYXJtb255KAogIG9iamVjdCA9IEFsbF9zYW1wbGVzX01lcmdlZCwKICBncm91cC5ieS52YXJzID0gImNlbGxfbGluZSIsICAjIFJlcGxhY2Ugd2l0aCB0aGUgbWV0YWRhdGEgY29sdW1uIHNwZWNpZnlpbmcgYmF0Y2ggb3IgY2VsbCBsaW5lCiAgZGltcy51c2UgPSAxOjIyLCAgIyBVc2UgdGhlIHNhbWUgZGltZW5zaW9ucyBhcyBQQ0EKICBhc3NheS51c2UgPSAiU0NUIiwKcGxvdF9jb252ZXJnZW5jZSA9IFRSVUUKICApCgojIFJ1biBVTUFQIG9uIHRoZSBuZXcgSGFybW9ueSByZWR1Y3Rpb24KQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIFJ1blVNQVAoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAiaGFybW9ueSIsIGRpbXMgPSAxOjIyLCByZWR1Y3Rpb24ubmFtZSA9ICJ1bWFwLmhhcm1vbnkiKQoKIyBGaW5kIG5laWdoYm9ycyBhbmQgY2x1c3RlcnMgdXNpbmcgdGhlIEhhcm1vbnkgcmVkdWN0aW9uCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBGaW5kTmVpZ2hib3JzKEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gImhhcm1vbnkiLCBkaW1zID0gMToyMikKQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIEZpbmRDbHVzdGVycyhBbGxfc2FtcGxlc19NZXJnZWQsIHJlc29sdXRpb24gPSAwLjUpCgojIFZpc3VhbGl6ZSByZXN1bHRzCnAxIDwtIERpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAiY2VsbF9saW5lIikgKyAKICBnZ3RpdGxlKCJIYXJtb255IEludGVncmF0aW9uIC0gQnkgQ2VsbCBMaW5lIikKcDIgPC0gRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiKSArIAogIGdndGl0bGUoIkhhcm1vbnkgSW50ZWdyYXRpb24gLSBCeSBDbHVzdGVycyIpCgojIENvbXBhcmUgd2l0aCBvcmlnaW5hbCBVTUFQCnAzIDwtIERpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZSIpICsgCiAgZ2d0aXRsZSgiT3JpZ2luYWwgSW50ZWdyYXRpb24gLSBCeSBDZWxsIExpbmUiKQpwNCA8LSBEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiKSArIAogIGdndGl0bGUoIk9yaWdpbmFsIEludGVncmF0aW9uIC0gQnkgQ2x1c3RlcnMiKQoKIyBQcmludCB0aGUgcGxvdHMKcHJpbnQocDEgKyBwMikKcHJpbnQocDMgKyBwNCkKCgpgYGAKCiMjICBIYXJtb255IFZpc3VhbGl6YXRpb24tMQpgYGB7ciBoYXJtb255LXZpc3VhbGl6YXRpb24xLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCiMgVmlzdWFsaXplIHJlc3VsdHMKcDEgPC0gRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLCBncm91cC5ieSA9ICJjZWxsX2xpbmUiLCBsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpICsgCiAgZ2d0aXRsZSgiSGFybW9ueSBJbnRlZ3JhdGlvbiAtIEJ5IENlbGwgTGluZSIpCnAyIDwtIERpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpICsgCiAgZ2d0aXRsZSgiSGFybW9ueSBJbnRlZ3JhdGlvbiAtIEJ5IENsdXN0ZXJzIikKCiMgQ29tcGFyZSB3aXRoIG9yaWdpbmFsIFVNQVAKcDMgPC0gRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAiY2VsbF9saW5lIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpICsgCiAgZ2d0aXRsZSgiT3JpZ2luYWwgSW50ZWdyYXRpb24gLSBCeSBDZWxsIExpbmUiKQpwNCA8LSBEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkgKyAKICBnZ3RpdGxlKCJPcmlnaW5hbCBJbnRlZ3JhdGlvbiAtIEJ5IENsdXN0ZXJzIikKCiMgUHJpbnQgdGhlIHBsb3RzCnByaW50KHAxICsgcDIpCnByaW50KHAzICsgcDQpCgpgYGAKCgojIDQuIERhdGEgUFJFUEFSQVRJT04gYW5kIEhhcm1vbnkgSW50ZWdyYXRpb24tMgpgYGB7ciBkYXRhMiwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgpsaWJyYXJ5KGhhcm1vbnkpCgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gUnVuSGFybW9ueSgKICBvYmplY3QgPSBBbGxfc2FtcGxlc19NZXJnZWQsCiAgZ3JvdXAuYnkudmFycyA9ICJjZWxsX2xpbmUiLCAgIyBSZXBsYWNlIHdpdGggdGhlIG1ldGFkYXRhIGNvbHVtbiBzcGVjaWZ5aW5nIGJhdGNoIG9yIGNlbGwgbGluZQogIGRpbXMudXNlID0gMToyMiwgICMgVXNlIHRoZSBzYW1lIGRpbWVuc2lvbnMgYXMgUENBCiAgYXNzYXkudXNlID0gIlNDVCIsCiAgVGhldGEgPSAwLjUsCiAgbGFtYmRhID0wLjUsCiAgcGxvdF9jb252ZXJnZW5jZSA9IFRSVUUKICApCgojIFJ1biBVTUFQIG9uIHRoZSBuZXcgSGFybW9ueSByZWR1Y3Rpb24KQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIFJ1blVNQVAoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAiaGFybW9ueSIsIGRpbXMgPSAxOjIyLCByZWR1Y3Rpb24ubmFtZSA9ICJ1bWFwLmhhcm1vbnkiKQoKIyBGaW5kIG5laWdoYm9ycyBhbmQgY2x1c3RlcnMgdXNpbmcgdGhlIEhhcm1vbnkgcmVkdWN0aW9uCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBGaW5kTmVpZ2hib3JzKEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gImhhcm1vbnkiLCBkaW1zID0gMToyMikKQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIEZpbmRDbHVzdGVycyhBbGxfc2FtcGxlc19NZXJnZWQsIHJlc29sdXRpb24gPSAwLjUpCmBgYAoKIyMgIEhhcm1vbnkgVmlzdWFsaXphdGlvbi0yCmBgYHtyIGhhcm1vbnktdmlzdWFsaXphdGlvbjIsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQoKIyBWaXN1YWxpemUgcmVzdWx0cwpwMSA8LSBEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZSIsIGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkgKyAKICBnZ3RpdGxlKCJIYXJtb255IEludGVncmF0aW9uIC0gQnkgQ2VsbCBMaW5lIikKcDIgPC0gRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkgKyAKICBnZ3RpdGxlKCJIYXJtb255IEludGVncmF0aW9uIC0gQnkgQ2x1c3RlcnMiKQoKIyBDb21wYXJlIHdpdGggb3JpZ2luYWwgVU1BUApwMyA8LSBEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJjZWxsX2xpbmUiLGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkgKyAKICBnZ3RpdGxlKCJPcmlnaW5hbCBJbnRlZ3JhdGlvbiAtIEJ5IENlbGwgTGluZSIpCnA0IDwtIERpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKSArIAogIGdndGl0bGUoIk9yaWdpbmFsIEludGVncmF0aW9uIC0gQnkgQ2x1c3RlcnMiKQoKIyBQcmludCB0aGUgcGxvdHMKcHJpbnQocDEgKyBwMikKcHJpbnQocDMgKyBwNCkKCmBgYAoKIyA1LiBEYXRhIFBSRVBBUkFUSU9OIGFuZCBIYXJtb255IEludGVncmF0aW9uLTMKYGBge3IgZGF0YTMsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQoKIyBDcmVhdGUgYSBuZXcgbWV0YWRhdGEgY29sdW1uIGZvciBncm91cGluZwpBbGxfc2FtcGxlc19NZXJnZWQkc2FtcGxlX2dyb3VwIDwtIGNhc2Vfd2hlbigKICBncmVwbCgiXkwiLCBBbGxfc2FtcGxlc19NZXJnZWQkY2VsbF9saW5lKSB+ICJDZWxsX0xpbmUiLAogIEFsbF9zYW1wbGVzX01lcmdlZCRjZWxsX2xpbmUgPT0gIlBCTUMiIH4gIlBCTUMiLAogIEFsbF9zYW1wbGVzX01lcmdlZCRjZWxsX2xpbmUgPT0gIlBCTUNfMTB4IiB+ICJQQk1DXzEweCIsCiAgVFJVRSB+ICJPdGhlciIKKQoKIyBDcmVhdGUgdGhlIGNlbGwgbGluZSBncm91cGluZyBjb3JyZWN0bHkKQWxsX3NhbXBsZXNfTWVyZ2VkJGNlbGxfbGluZV9ncm91cCA8LSBjYXNlX3doZW4oCiAgZ3JlcGwoIl5MWzEtMl0iLCBBbGxfc2FtcGxlc19NZXJnZWQkY2VsbF9saW5lKSB+ICJQMSIsCiAgZ3JlcGwoIl5MWzMtNF0iLCBBbGxfc2FtcGxlc19NZXJnZWQkY2VsbF9saW5lKSB+ICJQMiIsCiAgZ3JlcGwoIl5MWzUtN10iLCBBbGxfc2FtcGxlc19NZXJnZWQkY2VsbF9saW5lKSB+ICJQMyIsCiAgQWxsX3NhbXBsZXNfTWVyZ2VkJGNlbGxfbGluZSA9PSAiUEJNQyIgfiAiUEJNQyIsCiAgQWxsX3NhbXBsZXNfTWVyZ2VkJGNlbGxfbGluZSA9PSAiUEJNQ18xMHgiIH4gIlBCTUNfMTB4IiwKICBUUlVFIH4gIk90aGVyIiAgIyBUaGlzIGNhdGNoZXMgYW55IHVuZXhwZWN0ZWQgdmFsdWVzCikKCmxpYnJhcnkoaGFybW9ueSkKCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBSdW5IYXJtb255KAogIG9iamVjdCA9IEFsbF9zYW1wbGVzX01lcmdlZCwKICBncm91cC5ieS52YXJzID0gInNhbXBsZV9ncm91cCIsCiAgZGltcy51c2UgPSAxOjIyLCAgIyBJbmNyZWFzZWQgdG8gY2FwdHVyZSBtb3JlIHZhcmlhdGlvbgogIHRoZXRhID0gYygwLjUpLCAgIyBBZGp1c3QgdGhlc2UgdmFsdWVzIGFzIG5lZWRlZAogIHBsb3RfY29udmVyZ2VuY2UgPSBUUlVFCikKCiMgUnVuIFVNQVAgb24gdGhlIG5ldyBIYXJtb255IHJlZHVjdGlvbgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gUnVuVU1BUChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJoYXJtb255IiwgZGltcyA9IDE6MjIsIHJlZHVjdGlvbi5uYW1lID0gInVtYXAuaGFybW9ueSIpCgojIEZpbmQgbmVpZ2hib3JzIGFuZCBjbHVzdGVycyB1c2luZyB0aGUgSGFybW9ueSByZWR1Y3Rpb24KQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIEZpbmROZWlnaGJvcnMoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAiaGFybW9ueSIsIGRpbXMgPSAxOjIyKQpBbGxfc2FtcGxlc19NZXJnZWQgPC0gRmluZENsdXN0ZXJzKEFsbF9zYW1wbGVzX01lcmdlZCwgcmVzb2x1dGlvbiA9IDAuNSkKCmBgYAoKIyMgIEhhcm1vbnkgVmlzdWFsaXphdGlvbi0zCmBgYHtyIGhhcm1vbnktdmlzdWFsaXphdGlvbjMsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQoKCnAxIDwtIERpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAic2FtcGxlX2dyb3VwIiwgbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQpwMiA8LSBEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZV9ncm91cCIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQpwMyA8LSBEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZSIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQoKcDEgKyBwMiArIHAzCgpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIGdyb3VwLmJ5ID0gInNhbXBsZV9ncm91cCIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZV9ncm91cCIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZSIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQoKCgojIENvbXBhcmUgd2l0aCBvcmlnaW5hbCBVTUFQCnA0IDwtIERpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZSIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKSArIAogIGdndGl0bGUoIk9yaWdpbmFsIEludGVncmF0aW9uIC0gQnkgQ2VsbCBMaW5lIikKcDUgPC0gRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpICsgCiAgZ2d0aXRsZSgiT3JpZ2luYWwgSW50ZWdyYXRpb24gLSBCeSBDbHVzdGVycyIpCgojIFByaW50IHRoZSBwbG90cwpwcmludChwNCArIHA1KQoKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAiY2VsbF9saW5lIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpICsgCiAgZ2d0aXRsZSgiT3JpZ2luYWwgSW50ZWdyYXRpb24gLSBCeSBDZWxsIExpbmUiKQpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkgKyAKICBnZ3RpdGxlKCJPcmlnaW5hbCBJbnRlZ3JhdGlvbiAtIEJ5IENsdXN0ZXJzIikKCiMgVmlzdWFsaXplIHJlc3VsdHMKcDYgPC0gRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLCBncm91cC5ieSA9ICJjZWxsX2xpbmUiLCBsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpICsgCiAgZ2d0aXRsZSgiSGFybW9ueSBJbnRlZ3JhdGlvbiAtIEJ5IENlbGwgTGluZSIpCnA3IDwtIERpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpICsgCiAgZ2d0aXRsZSgiSGFybW9ueSBJbnRlZ3JhdGlvbiAtIEJ5IENsdXN0ZXJzIikKIyBQcmludCB0aGUgcGxvdHMKcHJpbnQocDYgKyBwNykKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAiY2VsbF9saW5lIiwgbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKSArIAogIGdndGl0bGUoIkhhcm1vbnkgSW50ZWdyYXRpb24gLSBCeSBDZWxsIExpbmUiKQpwNyA8LSBEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKSArIAogIGdndGl0bGUoIkhhcm1vbnkgSW50ZWdyYXRpb24gLSBCeSBDbHVzdGVycyIpCgpgYGAKIyA2LiBEYXRhIFBSRVBBUkFUSU9OIGFuZCBIYXJtb255IEludGVncmF0aW9uLTQKYGBge3IgZGF0YTQsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQoKIyBDcmVhdGUgYSBuZXcgbWV0YWRhdGEgY29sdW1uIGZvciBncm91cGluZwpBbGxfc2FtcGxlc19NZXJnZWQkc2FtcGxlX2dyb3VwIDwtIGNhc2Vfd2hlbigKICBncmVwbCgiXkwiLCBBbGxfc2FtcGxlc19NZXJnZWQkY2VsbF9saW5lKSB+ICJDZWxsX0xpbmUiLAogIEFsbF9zYW1wbGVzX01lcmdlZCRjZWxsX2xpbmUgPT0gIlBCTUMiIH4gIlBCTUMiLAogIEFsbF9zYW1wbGVzX01lcmdlZCRjZWxsX2xpbmUgPT0gIlBCTUNfMTB4IiB+ICJQQk1DXzEweCIsCiAgVFJVRSB+ICJPdGhlciIKKQoKIyBDcmVhdGUgdGhlIGNlbGwgbGluZSBncm91cGluZyBjb3JyZWN0bHkKQWxsX3NhbXBsZXNfTWVyZ2VkJGNlbGxfbGluZV9ncm91cCA8LSBjYXNlX3doZW4oCiAgZ3JlcGwoIl5MWzEtMl0iLCBBbGxfc2FtcGxlc19NZXJnZWQkY2VsbF9saW5lKSB+ICJQMSIsCiAgZ3JlcGwoIl5MWzMtNF0iLCBBbGxfc2FtcGxlc19NZXJnZWQkY2VsbF9saW5lKSB+ICJQMiIsCiAgZ3JlcGwoIl5MWzUtN10iLCBBbGxfc2FtcGxlc19NZXJnZWQkY2VsbF9saW5lKSB+ICJQMyIsCiAgQWxsX3NhbXBsZXNfTWVyZ2VkJGNlbGxfbGluZSA9PSAiUEJNQyIgfiAiUEJNQyIsCiAgQWxsX3NhbXBsZXNfTWVyZ2VkJGNlbGxfbGluZSA9PSAiUEJNQ18xMHgiIH4gIlBCTUNfMTB4IiwKICBUUlVFIH4gIk90aGVyIiAgIyBUaGlzIGNhdGNoZXMgYW55IHVuZXhwZWN0ZWQgdmFsdWVzCikKCmxpYnJhcnkoaGFybW9ueSkKCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBSdW5IYXJtb255KAogIG9iamVjdCA9IEFsbF9zYW1wbGVzX01lcmdlZCwKICBncm91cC5ieS52YXJzID0gImNlbGxfbGluZV9ncm91cCIsCiAgZGltcy51c2UgPSAxOjIyLCAgIyBJbmNyZWFzZWQgdG8gY2FwdHVyZSBtb3JlIHZhcmlhdGlvbgogIHRoZXRhID0gYygwLjUpLCAgIyBBZGp1c3QgdGhlc2UgdmFsdWVzIGFzIG5lZWRlZAogIHBsb3RfY29udmVyZ2VuY2UgPSBUUlVFCikKCiMgUnVuIFVNQVAgb24gdGhlIG5ldyBIYXJtb255IHJlZHVjdGlvbgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gUnVuVU1BUChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJoYXJtb255IiwgZGltcyA9IDE6MjIsIHJlZHVjdGlvbi5uYW1lID0gInVtYXAuaGFybW9ueSIpCgojIEZpbmQgbmVpZ2hib3JzIGFuZCBjbHVzdGVycyB1c2luZyB0aGUgSGFybW9ueSByZWR1Y3Rpb24KQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIEZpbmROZWlnaGJvcnMoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAiaGFybW9ueSIsIGRpbXMgPSAxOjIyKQpBbGxfc2FtcGxlc19NZXJnZWQgPC0gRmluZENsdXN0ZXJzKEFsbF9zYW1wbGVzX01lcmdlZCwgcmVzb2x1dGlvbiA9IDAuNSkKCmBgYAoKIyMgIEhhcm1vbnkgVmlzdWFsaXphdGlvbi00CmBgYHtyIGhhcm1vbnktdmlzdWFsaXphdGlvbjQsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQoKCnAxIDwtIERpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAic2FtcGxlX2dyb3VwIiwgbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQpwMiA8LSBEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZV9ncm91cCIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQpwMyA8LSBEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZSIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQoKcDEgKyBwMiArIHAzCgpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIGdyb3VwLmJ5ID0gInNhbXBsZV9ncm91cCIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZV9ncm91cCIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZSIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQoKCgojIENvbXBhcmUgd2l0aCBvcmlnaW5hbCBVTUFQCnA0IDwtIERpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZSIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKSArIAogIGdndGl0bGUoIk9yaWdpbmFsIEludGVncmF0aW9uIC0gQnkgQ2VsbCBMaW5lIikKcDUgPC0gRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpICsgCiAgZ2d0aXRsZSgiT3JpZ2luYWwgSW50ZWdyYXRpb24gLSBCeSBDbHVzdGVycyIpCgojIFByaW50IHRoZSBwbG90cwpwcmludChwNCArIHA1KQoKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAiY2VsbF9saW5lIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpICsgCiAgZ2d0aXRsZSgiT3JpZ2luYWwgSW50ZWdyYXRpb24gLSBCeSBDZWxsIExpbmUiKQpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkgKyAKICBnZ3RpdGxlKCJPcmlnaW5hbCBJbnRlZ3JhdGlvbiAtIEJ5IENsdXN0ZXJzIikKCiMgVmlzdWFsaXplIHJlc3VsdHMKcDYgPC0gRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLCBncm91cC5ieSA9ICJjZWxsX2xpbmUiLCBsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpICsgCiAgZ2d0aXRsZSgiSGFybW9ueSBJbnRlZ3JhdGlvbiAtIEJ5IENlbGwgTGluZSIpCnA3IDwtIERpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpICsgCiAgZ2d0aXRsZSgiSGFybW9ueSBJbnRlZ3JhdGlvbiAtIEJ5IENsdXN0ZXJzIikKIyBQcmludCB0aGUgcGxvdHMKcHJpbnQocDYgKyBwNykKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAiY2VsbF9saW5lIiwgbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKSArIAogIGdndGl0bGUoIkhhcm1vbnkgSW50ZWdyYXRpb24gLSBCeSBDZWxsIExpbmUiKQpwNyA8LSBEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKSArIAogIGdndGl0bGUoIkhhcm1vbnkgSW50ZWdyYXRpb24gLSBCeSBDbHVzdGVycyIpCgpgYGAKCgojIDcuIERhdGEgUFJFUEFSQVRJT04gYW5kIEhhcm1vbnkgSW50ZWdyYXRpb24tNQpgYGB7ciBkYXRhNSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgojIENyZWF0ZSBhIG5ldyBtZXRhZGF0YSBjb2x1bW4gZm9yIGdyb3VwaW5nCkFsbF9zYW1wbGVzX01lcmdlZCRzYW1wbGVfZ3JvdXAgPC0gY2FzZV93aGVuKAogIGdyZXBsKCJeTCIsIEFsbF9zYW1wbGVzX01lcmdlZCRjZWxsX2xpbmUpIH4gIkNlbGxfTGluZSIsCiAgQWxsX3NhbXBsZXNfTWVyZ2VkJGNlbGxfbGluZSA9PSAiUEJNQyIgfiAiUEJNQyIsCiAgQWxsX3NhbXBsZXNfTWVyZ2VkJGNlbGxfbGluZSA9PSAiUEJNQ18xMHgiIH4gIlBCTUNfMTB4IiwKICBUUlVFIH4gIk90aGVyIgopCgojIENyZWF0ZSB0aGUgY2VsbCBsaW5lIGdyb3VwaW5nIGNvcnJlY3RseQpBbGxfc2FtcGxlc19NZXJnZWQkY2VsbF9saW5lX2dyb3VwIDwtIGNhc2Vfd2hlbigKICBncmVwbCgiXkxbMS0yXSIsIEFsbF9zYW1wbGVzX01lcmdlZCRjZWxsX2xpbmUpIH4gIlAxIiwKICBncmVwbCgiXkxbMy00XSIsIEFsbF9zYW1wbGVzX01lcmdlZCRjZWxsX2xpbmUpIH4gIlAyIiwKICBncmVwbCgiXkxbNS03XSIsIEFsbF9zYW1wbGVzX01lcmdlZCRjZWxsX2xpbmUpIH4gIlAzIiwKICBBbGxfc2FtcGxlc19NZXJnZWQkY2VsbF9saW5lID09ICJQQk1DIiB+ICJQQk1DIiwKICBBbGxfc2FtcGxlc19NZXJnZWQkY2VsbF9saW5lID09ICJQQk1DXzEweCIgfiAiUEJNQ18xMHgiLAogIFRSVUUgfiAiT3RoZXIiICAjIFRoaXMgY2F0Y2hlcyBhbnkgdW5leHBlY3RlZCB2YWx1ZXMKKQoKbGlicmFyeShoYXJtb255KQoKQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIFJ1bkhhcm1vbnkoCiAgb2JqZWN0ID0gQWxsX3NhbXBsZXNfTWVyZ2VkLAogIGdyb3VwLmJ5LnZhcnMgPSAiY2VsbF9saW5lIiwKICBkaW1zLnVzZSA9IDE6MjIsICAjIEluY3JlYXNlZCB0byBjYXB0dXJlIG1vcmUgdmFyaWF0aW9uCiAgdGhldGEgPSBjKDAuNSksICAjIEFkanVzdCB0aGVzZSB2YWx1ZXMgYXMgbmVlZGVkCiAgcGxvdF9jb252ZXJnZW5jZSA9IFRSVUUKKQoKIyBSdW4gVU1BUCBvbiB0aGUgbmV3IEhhcm1vbnkgcmVkdWN0aW9uCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBSdW5VTUFQKEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gImhhcm1vbnkiLCBkaW1zID0gMToyMiwgcmVkdWN0aW9uLm5hbWUgPSAidW1hcC5oYXJtb255IikKCiMgRmluZCBuZWlnaGJvcnMgYW5kIGNsdXN0ZXJzIHVzaW5nIHRoZSBIYXJtb255IHJlZHVjdGlvbgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gRmluZE5laWdoYm9ycyhBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJoYXJtb255IiwgZGltcyA9IDE6MjIpCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBGaW5kQ2x1c3RlcnMoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZXNvbHV0aW9uID0gMC41KQoKYGBgCgojIyAgSGFybW9ueSBWaXN1YWxpemF0aW9uLTUKYGBge3IgaGFybW9ueS12aXN1YWxpemF0aW9uNSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgoKcDEgPC0gRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLCBncm91cC5ieSA9ICJzYW1wbGVfZ3JvdXAiLCBsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpCnAyIDwtIERpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAiY2VsbF9saW5lX2dyb3VwIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpCnAzIDwtIERpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAiY2VsbF9saW5lIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpCgpwMSArIHAyICsgcDMKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAic2FtcGxlX2dyb3VwIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAiY2VsbF9saW5lX2dyb3VwIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAiY2VsbF9saW5lIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpCgoKCiMgQ29tcGFyZSB3aXRoIG9yaWdpbmFsIFVNQVAKcDQgPC0gRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAiY2VsbF9saW5lIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpICsgCiAgZ2d0aXRsZSgiT3JpZ2luYWwgSW50ZWdyYXRpb24gLSBCeSBDZWxsIExpbmUiKQpwNSA8LSBEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkgKyAKICBnZ3RpdGxlKCJPcmlnaW5hbCBJbnRlZ3JhdGlvbiAtIEJ5IENsdXN0ZXJzIikKCiMgUHJpbnQgdGhlIHBsb3RzCnByaW50KHA0ICsgcDUpCgpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJjZWxsX2xpbmUiLGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkgKyAKICBnZ3RpdGxlKCJPcmlnaW5hbCBJbnRlZ3JhdGlvbiAtIEJ5IENlbGwgTGluZSIpCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKSArIAogIGdndGl0bGUoIk9yaWdpbmFsIEludGVncmF0aW9uIC0gQnkgQ2x1c3RlcnMiKQoKIyBWaXN1YWxpemUgcmVzdWx0cwpwNiA8LSBEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZSIsIGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkgKyAKICBnZ3RpdGxlKCJIYXJtb255IEludGVncmF0aW9uIC0gQnkgQ2VsbCBMaW5lIikKcDcgPC0gRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkgKyAKICBnZ3RpdGxlKCJIYXJtb255IEludGVncmF0aW9uIC0gQnkgQ2x1c3RlcnMiKQojIFByaW50IHRoZSBwbG90cwpwcmludChwNiArIHA3KQoKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLCBncm91cC5ieSA9ICJjZWxsX2xpbmUiLCBsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpICsgCiAgZ2d0aXRsZSgiSGFybW9ueSBJbnRlZ3JhdGlvbiAtIEJ5IENlbGwgTGluZSIpCnA3IDwtIERpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpICsgCiAgZ2d0aXRsZSgiSGFybW9ueSBJbnRlZ3JhdGlvbiAtIEJ5IENsdXN0ZXJzIikKCmBgYAoKIyMgIE1hcmtlciBHZW5lIFZpc3VhbGl6YXRpb24KYGBge3IgZmVhdHVyZXBsb3QtaGFybW9ueSwgZmlnLmhlaWdodD0xNCwgZmlnLndpZHRoPTE4fQoKCiMgU2V0IG1hcmtlciBnZW5lcyBzcGVjaWZpYyB0byByZXF1ZXN0ZWQgaW1tdW5lIGNlbGwgdHlwZXMKbXlmZWF0dXJlcyA8LSBjKCJDRDE5IiwgIkNENzlBIiwgIk1TNEExIiwgIyBCIGNlbGxzCiAgICAgICAgICAgICAgICAiQ0QxNCIsICJMWVoiLCAiRkNHUjNBIiwgIyBNb25vY3l0ZXMKICAgICAgICAgICAgICAgICJDU0YxUiIsICJDRDY4IiwgIyBNYWNyb3BoYWdlcwogICAgICAgICAgICAgICAgIk5LRzciLCAiR05MWSIsICJLSVIzREwxIiwgIyBOSyBjZWxscwogICAgICAgICAgICAgICAgIk1LSTY3IiwgIyBQcm9saWZlcmF0aW5nIE5LIGNlbGxzCiAgICAgICAgICAgICAgICAiQ0QzNCIsICJLSVQiLCAjIEhTUENzCiAgICAgICAgICAgICAgICAiQ0QzRSIsICJDQ1I3IiwgIyBUIGNlbGxzCiAgICAgICAgICAgICAgICAiU0VMTCIsICJDRDQ1Uk8iLCAjIFRuYWl2ZSwgVGNtCiAgICAgICAgICAgICAgICAiQ0Q0NCIsICJDRDQ1UkEiKSAjIFRlbSwgVGVtcmEKIyBWaXN1YWxpemUgbWFya2VyIGdlbmVzIGZvciBIYXJtb255CkZlYXR1cmVQbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgZmVhdHVyZXMgPSBteWZlYXR1cmVzLCByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwgbmNvbCA9IDQpICsgCiAgZ2d0aXRsZSgiTWFya2VyIEdlbmUgRXhwcmVzc2lvbiAtIEhhcm1vbnkgSW50ZWdyYXRpb24iKSArCiAgTm9MZWdlbmQoKQpgYGAKCiMgNi4gU2F2ZSB0aGUgU2V1cmF0IG9iamVjdCBhcyBhbiBSb2JqIGZpbGUKYGBge3Igc2F2ZVJPQkp9Cgojc2F2ZShBbGxfc2FtcGxlc19NZXJnZWQsIGZpbGUgPSAiaW50ZWdyYXRlZF9BbGxfc2FtcGxlc19NZXJnZWRfd2l0aF9QQk1DMTB4LlJvYmoiKQoKYGBgCgoKCgo=