1. load libraries
2. Load Seurat Object
#Load Seurat Object merged from cell lines and a control(PBMC) after filtration
SS_All_samples_Merged <- load("SS_All_Sample_Merged_Azimuth_ProjectTils_singleR_ANNOTATION_on_My_UMAP0.7_HPC.Robj")
All_samples_Merged
An object of class Seurat
63193 features across 49193 samples within 6 assays
Active assay: SCT (26469 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: pca, umap, integrated_dr, ref.umap
3. QC
Idents(All_samples_Merged) <- "cell_line"
VlnPlot(All_samples_Merged, features = c("nFeature_RNA",
"nCount_RNA",
"percent.mito"),
ncol = 3)

FeatureScatter(All_samples_Merged,
feature1 = "nCount_RNA",
feature2 = "nFeature_RNA") +
geom_smooth(method = 'lm')

##FeatureScatter is typically used to visualize feature-feature
relationships ##for anything calculated by the object, ##i.e. columns in
object metadata, PC scores etc.
FeatureScatter(All_samples_Merged,
feature1 = "nCount_RNA",
feature2 = "percent.mito")+
geom_smooth(method = 'lm')

FeatureScatter(All_samples_Merged,
feature1 = "nCount_RNA",
feature2 = "nFeature_RNA")+
geom_smooth(method = 'lm')

4. Normalize data
# # Apply SCTransform
# All_samples_Merged <- SCTransform(All_samples_Merged, verbose = TRUE)
#
5. Perform PCA TEST
library(ggplot2)
library(RColorBrewer)
# Assuming you have 10 different cell lines, generating a color palette with 10 colors
cell_line_colors <- brewer.pal(10, "Set3")
# Assuming All_samples_Merged$cell_line is a factor or character vector containing cell line names
data <- as.data.frame(table(All_samples_Merged$cell_line))
colnames(data) <- c("cell_line", "nUMI") # Change column name to nUMI
ncells <- ggplot(data, aes(x = cell_line, y = nUMI, fill = cell_line)) +
geom_col() +
theme_classic() +
geom_text(aes(label = nUMI),
position = position_dodge(width = 0.9),
vjust = -0.25) +
scale_fill_manual(values = cell_line_colors) +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
plot.title = element_text(hjust = 0.5)) + # Adjust the title position
ggtitle("Filtered cells per sample") +
xlab("Cell lines") + # Adjust x-axis label
ylab("Frequency") # Adjust y-axis label
print(ncells)

cell_lines <- FindVariableFeatures(All_samples_Merged,
selection.method = "vst", # default vst
nfeatures = 2000, # default 2000
verbose = FALSE)
# view top variable genes
top40 <- head(VariableFeatures(cell_lines), 40)
top40
[1] "CCL17" "CXCL8" "CXCL5" "THBS1" "S100A8" "TYROBP" "S100A9" "CCL1" "CXCL1"
[10] "IL1B" "SERPINB2" "PID1" "CCL4" "FTH1" "CXCL3" "MMP9" "SOD2" "CD14"
[19] "C15orf48" "CCL3" "EREG" "IGKV3-20" "FCER1G" "LYZ" "CCL22" "GNLY" "PPBP"
[28] "OASL" "IGKV3-11" "IGLV2-14" "CXCL2" "DOCK4" "IFIT2" "CD79A" "VMO1" "IGKV1-5"
[37] "XCL1" "GZMB" "SPI1" "IGHV4-34"
# plot variable features with labels
VarFeatPlot <- VariableFeaturePlot(cell_lines, cols = c("gray47","red"))
VarFeatPlotLabel <- LabelPoints(plot = VarFeatPlot,
points = top40, repel = TRUE, fontface="italic",
xnudge = 0, ynudge = 0, max.overlaps = 12)
VarFeatPlotLabel

df <- data.frame(row.names = rownames(cell_lines))
df$rsum <- rowSums(x = cell_lines, slot = "counts")
df$gene_name <- rownames(df)
df <- df[order(df$rsum,decreasing = TRUE),]
head(df, 10)
# TEST-1
# given that the output of RunPCA is "pca"
# replace "so" by the name of your seurat object
pct <- All_samples_Merged[["pca"]]@stdev / sum(All_samples_Merged[["pca"]]@stdev) * 100
cumu <- cumsum(pct) # Calculate cumulative percents for each PC
# Determine the difference between variation of PC and subsequent PC
co2 <- sort(which((pct[-length(pct)] - pct[-1]) > 0.1), decreasing = T)[1] + 1
# last point where change of % of variation is more than 0.1%. -> co2
co2
[1] 20
# TEST-2
# get significant PCs
stdv <- All_samples_Merged[["pca"]]@stdev
sum.stdv <- sum(All_samples_Merged[["pca"]]@stdev)
percent.stdv <- (stdv / sum.stdv) * 100
cumulative <- cumsum(percent.stdv)
co1 <- which(cumulative > 90 & percent.stdv < 5)[1]
co2 <- sort(which((percent.stdv[1:length(percent.stdv) - 1] -
percent.stdv[2:length(percent.stdv)]) > 0.1),
decreasing = T)[1] + 1
min.pc <- min(co1, co2)
min.pc
[1] 20
# Create a dataframe with values
plot_df <- data.frame(pct = percent.stdv,
cumu = cumulative,
rank = 1:length(percent.stdv))
# Elbow plot to visualize
ggplot(plot_df, aes(cumulative, percent.stdv, label = rank, color = rank > min.pc)) +
geom_text() +
geom_vline(xintercept = 90, color = "grey") +
geom_hline(yintercept = min(percent.stdv[percent.stdv > 5]), color = "grey") +
theme_bw()

NA
NA
6. Clustering
# run umap
#celllines.nointergration <- RunUMAP(All_samples_Merged, dims = 1:min.pc, reduction = "pca")
# cluster
#celllines.nointergration <- FindNeighbors(object = celllines.nointergration, dims = 1:min.pc)
# Determine the clusters for various resolutions
#celllines.nointergration <- FindClusters(object = celllines.nointergration, resolution = seq(0.1,1.2,by=0.1))
Idents(celllines.nointergration) <- "SCT_snn_res.0.7"
celllines.nointergration$seurat_clusters <- celllines.nointergration$SCT_snn_res.0.7
u1 <- DimPlot(object = celllines.nointergration, group.by = "seurat_clusters", label = TRUE, label.box = TRUE)
u1

u2 <- DimPlot(object = celllines.nointergration,
group.by = "seurat_clusters",
reduction = "umap",
label = TRUE,
label.box = TRUE,
split.by = "cell_line")
u2

u3 <- DimPlot(object = celllines.nointergration,
group.by = "seurat_clusters",
reduction = "umap",
label = TRUE,
label.box = TRUE,
split.by = "Patient_origin")
u3

u4 <- DimPlot(object = celllines.nointergration,
group.by = "seurat_clusters",
reduction = "umap",
label = TRUE,
label.box = TRUE,
split.by = "Treatments_analysis")
u4

u5 <- dittoDimPlot(object = celllines.nointergration,
var = "seurat_clusters",
reduction.use = "umap",
do.label = TRUE,
labels.highlight = FALSE)
u5

u6 <- dittoDimPlot(object = celllines.nointergration,
var = "seurat_clusters",
reduction.use = "umap",
do.label = TRUE,
split.by = "Treatments_analysis",
labels.highlight = FALSE)
u6

#Integrate with harmony
# Run harmony to harmonize over samples
# celllines.intergration <- RunHarmony(
# celllines.nointergration,
# group.by.vars = "orig.ident",
# assay.use = "SCT",
# reduction.use = "pca",
# plot_convergence = TRUE)
#Find significant PCs
#First metric
# Determine percent of variation associated with each PC
stdv <- celllines.intergration[["pca"]]@stdev
sum.stdv <- sum(celllines.intergration[["pca"]]@stdev)
percent.stdv <- (stdv / sum.stdv) * 100
# Calculate cumulative percents for each PC
cumulative <- cumsum(percent.stdv)
# Determine which PC exhibits cumulative percent greater than 90% and
# and % variation associated with the PC as less than 5
co1 <- which(cumulative > 90 & percent.stdv < 5)[1]
co1
[1] 41
# Determine the difference between variation of PC and subsequent PC
co2 <- sort(which(
(percent.stdv[1:length(percent.stdv) - 1] -
percent.stdv[2:length(percent.stdv)]) > 0.1),
decreasing = T)[1] + 1
# last point where change of % of variation is more than 0.1%.
co2
[1] 20
# Minimum of the two calculation
min.pc <- min(co1, co2)
min.pc
[1] 20
plot_df <- data.frame(pct = percent.stdv,
cumu = cumulative,
rank = 1:length(percent.stdv))
# Elbow plot to visualize
ggplot(plot_df, aes(cumulative, percent.stdv, label = rank, color = rank > min.pc)) +
geom_text() +
geom_vline(xintercept = 90, color = "grey") +
geom_hline(yintercept = min(percent.stdv[percent.stdv > 5]), color = "grey") +
theme_bw()

# Run UMAP
# celllines.intergration <- RunUMAP(celllines.intergration,
# dims = 1:min.pc,
# reduction.use = "pca",
# n.components = 3) # set to 3 to use with VR
# Determine the K-nearest neighbor graph
#celllines.intergration <- FindNeighbors(object = celllines.intergration,dims = 1:min.pc)
# Determine the clusters for various resolutions
#cell_line.unannotated <- FindClusters(object = celllines.intergration,resolution = seq(0.1,1.2,by=0.1))
# Neurons after re-cluster
# UMAP
DefaultAssay(cell_line.unannotated) <- "SCT"
#neuron.unannotated <- NormalizeData(neuron.unannotated, verbose = FALSE)
cell_line.unannotated$seurat_clusters <- cell_line.unannotated$SCT_snn_res.0.7
u1 <- dittoDimPlot(object = cell_line.unannotated,
var = "seurat_clusters",
reduction.use = "umap",
do.label = TRUE,
labels.highlight = FALSE)
u1

u2 <- dittoDimPlot(object = cell_line.unannotated,
var = "seurat_clusters",
reduction.use = "umap",
do.label = TRUE,
split.by = "Treatments_analysis",
labels.highlight = FALSE)
u2

NA
NA
# #Cluster tree
# cluster_colors <- c("gold","firebrick1","dodgerblue","green",
# "cyan","chocolate4","gray40","purple", "blue")
#
# celllines.nointergration <- BuildClusterTree(object = celllines.nointergration,
# dims = 1:min.pc,
# reorder = FALSE,
# reorder.numeric = FALSE)
#
# tree <- celllines.nointergration@tools$BuildClusterTree
# tree$tip.label <- paste0("Cluster ", tree$tip.label)
#
# p <- ggtree::ggtree(tree, aes(x, y)) +
# scale_y_reverse() +
# ggtree::geom_tree() +
# ggtree::theme_tree() +
# ggtree::geom_tiplab(offset = 1) +
# ggtree::geom_tippoint(color = cluster_colors[1:length(tree$tip.label)], shape = 16, size = 5) +
# coord_cartesian(clip = 'off') +
# theme(plot.margin = unit(c(0,2.5,0,0), 'cm'))
Save the Seurat object as an Robj file———————————————————————-
```
LS0tCnRpdGxlOiAiUEMgdGVzdCBxbmQgaGFybW9ueSBpbnRlZ3JhdGlvbiBvbiBTQ1QiCmF1dGhvcjogTmFzaXIgTWFobW9vZCBBYmJhc2kKZGF0ZTogIjIwMjQtMDUtMTIiCm91dHB1dDoKICBodG1sX25vdGVib29rOiAKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCiAgICB0aGVtZTogZGFya2x5Ci0tLQoKIyAxLiBsb2FkIGxpYnJhcmllcwpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KFNldXJhdE9iamVjdCkKbGlicmFyeShTZXVyYXREYXRhKQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShBemltdXRoKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHJtYXJrZG93bikKbGlicmFyeSh0aW55dGV4KQoKCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZGl0dG9TZXEpCmxpYnJhcnkoZ2dyZXBlbCkKI2xpYnJhcnkoZ2d0cmVlKQpsaWJyYXJ5KHBhcmFsbGVsKQpsaWJyYXJ5KHBsb3RseSkgICMgM0QgcGxvdApsaWJyYXJ5KFNldXJhdCkgICMgSWRlbnRzKCkKbGlicmFyeShTZXVyYXREaXNrKSAgIyBTYXZlSDVTZXVyYXQoKQpsaWJyYXJ5KHRpYmJsZSkgICMgcm93bm5hbWVzX3RvX2NvbHVtbgpsaWJyYXJ5KGhhcm1vbnkpICMgUnVuSGFybW9ueSgpCiNvcHRpb25zKG1jLmNvcmVzID0gZGV0ZWN0Q29yZXMoKSAtIDEpCgoKCmBgYAoKCiMgMi4gTG9hZCBTZXVyYXQgT2JqZWN0IApgYGB7ciBsb2FkX3NldXJhdH0KCiNMb2FkIFNldXJhdCBPYmplY3QgbWVyZ2VkIGZyb20gY2VsbCBsaW5lcyBhbmQgYSBjb250cm9sKFBCTUMpIGFmdGVyIGZpbHRyYXRpb24KU1NfQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIGxvYWQoIlNTX0FsbF9TYW1wbGVfTWVyZ2VkX0F6aW11dGhfUHJvamVjdFRpbHNfc2luZ2xlUl9BTk5PVEFUSU9OX29uX015X1VNQVAwLjdfSFBDLlJvYmoiKQoKQWxsX3NhbXBsZXNfTWVyZ2VkCmBgYAoKCiMgMy4gUUMKYGBge3IgUUMsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKSWRlbnRzKEFsbF9zYW1wbGVzX01lcmdlZCkgPC0gImNlbGxfbGluZSIKVmxuUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIGZlYXR1cmVzID0gYygibkZlYXR1cmVfUk5BIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJuQ291bnRfUk5BIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwZXJjZW50Lm1pdG8iKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDMpCgpGZWF0dXJlU2NhdHRlcihBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgICBmZWF0dXJlMSA9ICJuQ291bnRfUk5BIiwgCiAgICAgICAgICAgICAgIGZlYXR1cmUyID0gIm5GZWF0dXJlX1JOQSIpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nKQoKYGBgCgojI0ZlYXR1cmVTY2F0dGVyIGlzIHR5cGljYWxseSB1c2VkIHRvIHZpc3VhbGl6ZSBmZWF0dXJlLWZlYXR1cmUgcmVsYXRpb25zaGlwcwojI2ZvciBhbnl0aGluZyBjYWxjdWxhdGVkIGJ5IHRoZSBvYmplY3QsIAojI2kuZS4gY29sdW1ucyBpbiBvYmplY3QgbWV0YWRhdGEsIFBDIHNjb3JlcyBldGMuCgpgYGB7ciBGQywgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CgpGZWF0dXJlU2NhdHRlcihBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgICBmZWF0dXJlMSA9ICJuQ291bnRfUk5BIiwgCiAgICAgICAgICAgICAgIGZlYXR1cmUyID0gInBlcmNlbnQubWl0byIpKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdsbScpCgpGZWF0dXJlU2NhdHRlcihBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgICBmZWF0dXJlMSA9ICJuQ291bnRfUk5BIiwgCiAgICAgICAgICAgICAgIGZlYXR1cmUyID0gIm5GZWF0dXJlX1JOQSIpKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdsbScpCgpgYGAKCgoKIyA0LiBOb3JtYWxpemUgZGF0YQpgYGB7ciBOb3JtYWxpemUsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CgoKIyAjIEFwcGx5IFNDVHJhbnNmb3JtCiMgQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIFNDVHJhbnNmb3JtKEFsbF9zYW1wbGVzX01lcmdlZCwgdmVyYm9zZSA9IFRSVUUpCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKYGBgCgoKIyA1LiBQZXJmb3JtIFBDQQpgYGB7ciBQQ0EsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKIyBWYXJpYWJsZXNfZ2VuZXMgPC0gQWxsX3NhbXBsZXNfTWVyZ2VkQGFzc2F5cyRTQ1RAdmFyLmZlYXR1cmVzCiMgCiMgIyBFeGNsdWRlIGdlbmVzIHN0YXJ0aW5nIHdpdGggIkhMQS0iIG9yICJYaXN0IgojIFZhcmlhYmxlc19nZW5lc19hZnRlcl9leGNsdXNpb24gPC0gVmFyaWFibGVzX2dlbmVzWyFncmVwbCgiXkhMQS18Xlhpc3QiLCBWYXJpYWJsZXNfZ2VuZXMpXQojIAojIAojICMgVGhlc2UgYXJlIG5vdyBzdGFuZGFyZCBzdGVwcyBpbiB0aGUgU2V1cmF0IHdvcmtmbG93IGZvciB2aXN1YWxpemF0aW9uIGFuZCBjbHVzdGVyaW5nCiMgQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIFJ1blBDQShBbGxfc2FtcGxlc19NZXJnZWQsCiMgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSBWYXJpYWJsZXNfZ2VuZXNfYWZ0ZXJfZXhjbHVzaW9uLAojICAgICAgICAgICAgICAgICAgICAgICAgIGRvLnByaW50ID0gVFJVRSwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgcGNzLnByaW50ID0gMTo1LCAKIyAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lcy5wcmludCA9IDE1KQoKIyBkZXRlcm1pbmUgZGltZW5zaW9uYWxpdHkgb2YgdGhlIGRhdGEKRWxib3dQbG90KEFsbF9zYW1wbGVzX01lcmdlZCkKCgpgYGAKCgojIDUuIFBlcmZvcm0gUENBIFRFU1QKYGBge3IgUENBLVRFU1QsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShSQ29sb3JCcmV3ZXIpICAKCiMgQXNzdW1pbmcgeW91IGhhdmUgMTAgZGlmZmVyZW50IGNlbGwgbGluZXMsIGdlbmVyYXRpbmcgYSBjb2xvciBwYWxldHRlIHdpdGggMTAgY29sb3JzCmNlbGxfbGluZV9jb2xvcnMgPC0gYnJld2VyLnBhbCgxMCwgIlNldDMiKQoKIyBBc3N1bWluZyBBbGxfc2FtcGxlc19NZXJnZWQkY2VsbF9saW5lIGlzIGEgZmFjdG9yIG9yIGNoYXJhY3RlciB2ZWN0b3IgY29udGFpbmluZyBjZWxsIGxpbmUgbmFtZXMKZGF0YSA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKEFsbF9zYW1wbGVzX01lcmdlZCRjZWxsX2xpbmUpKQpjb2xuYW1lcyhkYXRhKSA8LSBjKCJjZWxsX2xpbmUiLCAiblVNSSIpICAjIENoYW5nZSBjb2x1bW4gbmFtZSB0byBuVU1JCgpuY2VsbHMgPC0gZ2dwbG90KGRhdGEsIGFlcyh4ID0gY2VsbF9saW5lLCB5ID0gblVNSSwgZmlsbCA9IGNlbGxfbGluZSkpICsgCiAgZ2VvbV9jb2woKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gblVNSSksIAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC45KSwgCiAgICAgICAgICAgIHZqdXN0ID0gLTAuMjUpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjZWxsX2xpbmVfY29sb3JzKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsgICMgQWRqdXN0IHRoZSB0aXRsZSBwb3NpdGlvbgogIGdndGl0bGUoIkZpbHRlcmVkIGNlbGxzIHBlciBzYW1wbGUiKSArCiAgeGxhYigiQ2VsbCBsaW5lcyIpICsgICMgQWRqdXN0IHgtYXhpcyBsYWJlbAogIHlsYWIoIkZyZXF1ZW5jeSIpICAgICMgQWRqdXN0IHktYXhpcyBsYWJlbAoKcHJpbnQobmNlbGxzKQoKCmNlbGxfbGluZXMgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoQWxsX3NhbXBsZXNfTWVyZ2VkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgICMgZGVmYXVsdCB2c3QKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZmVhdHVyZXMgPSAyMDAwLCAgIyBkZWZhdWx0IDIwMDAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJib3NlID0gRkFMU0UpCgojIHZpZXcgdG9wIHZhcmlhYmxlIGdlbmVzCnRvcDQwIDwtIGhlYWQoVmFyaWFibGVGZWF0dXJlcyhjZWxsX2xpbmVzKSwgNDApCnRvcDQwCgoKCiMgcGxvdCB2YXJpYWJsZSBmZWF0dXJlcyB3aXRoIGxhYmVscwpWYXJGZWF0UGxvdCA8LSBWYXJpYWJsZUZlYXR1cmVQbG90KGNlbGxfbGluZXMsIGNvbHMgPSBjKCJncmF5NDciLCJyZWQiKSkKVmFyRmVhdFBsb3RMYWJlbCA8LSBMYWJlbFBvaW50cyhwbG90ID0gVmFyRmVhdFBsb3QsIAogICAgICAgICAgICAgICAgICAgIHBvaW50cyA9IHRvcDQwLCByZXBlbCA9IFRSVUUsIGZvbnRmYWNlPSJpdGFsaWMiLCAKICAgICAgICAgICAgICAgICAgICB4bnVkZ2UgPSAwLCB5bnVkZ2UgPSAwLCBtYXgub3ZlcmxhcHMgPSAxMikKVmFyRmVhdFBsb3RMYWJlbAoKCmRmIDwtIGRhdGEuZnJhbWUocm93Lm5hbWVzID0gcm93bmFtZXMoY2VsbF9saW5lcykpCmRmJHJzdW0gPC0gcm93U3Vtcyh4ID0gY2VsbF9saW5lcywgc2xvdCA9ICJjb3VudHMiKQpkZiRnZW5lX25hbWUgPC0gcm93bmFtZXMoZGYpCmRmIDwtIGRmW29yZGVyKGRmJHJzdW0sZGVjcmVhc2luZyA9IFRSVUUpLF0KaGVhZChkZiwgMTApCgojIFRFU1QtMQojIGdpdmVuIHRoYXQgdGhlIG91dHB1dCBvZiBSdW5QQ0EgaXMgInBjYSIKIyByZXBsYWNlICJzbyIgYnkgdGhlIG5hbWUgb2YgeW91ciBzZXVyYXQgb2JqZWN0CgpwY3QgPC0gQWxsX3NhbXBsZXNfTWVyZ2VkW1sicGNhIl1dQHN0ZGV2IC8gc3VtKEFsbF9zYW1wbGVzX01lcmdlZFtbInBjYSJdXUBzdGRldikgKiAxMDAKY3VtdSA8LSBjdW1zdW0ocGN0KSAjIENhbGN1bGF0ZSBjdW11bGF0aXZlIHBlcmNlbnRzIGZvciBlYWNoIFBDCiMgRGV0ZXJtaW5lIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdmFyaWF0aW9uIG9mIFBDIGFuZCBzdWJzZXF1ZW50IFBDCmNvMiA8LSBzb3J0KHdoaWNoKChwY3RbLWxlbmd0aChwY3QpXSAtIHBjdFstMV0pID4gMC4xKSwgZGVjcmVhc2luZyA9IFQpWzFdICsgMQojIGxhc3QgcG9pbnQgd2hlcmUgY2hhbmdlIG9mICUgb2YgdmFyaWF0aW9uIGlzIG1vcmUgdGhhbiAwLjElLiAtPiBjbzIKY28yCgojIFRFU1QtMgojIGdldCBzaWduaWZpY2FudCBQQ3MKc3RkdiA8LSBBbGxfc2FtcGxlc19NZXJnZWRbWyJwY2EiXV1Ac3RkZXYKc3VtLnN0ZHYgPC0gc3VtKEFsbF9zYW1wbGVzX01lcmdlZFtbInBjYSJdXUBzdGRldikKcGVyY2VudC5zdGR2IDwtIChzdGR2IC8gc3VtLnN0ZHYpICogMTAwCmN1bXVsYXRpdmUgPC0gY3Vtc3VtKHBlcmNlbnQuc3RkdikKY28xIDwtIHdoaWNoKGN1bXVsYXRpdmUgPiA5MCAmIHBlcmNlbnQuc3RkdiA8IDUpWzFdCmNvMiA8LSBzb3J0KHdoaWNoKChwZXJjZW50LnN0ZHZbMTpsZW5ndGgocGVyY2VudC5zdGR2KSAtIDFdIC0gCiAgICAgICAgICAgICAgICAgICAgICAgcGVyY2VudC5zdGR2WzI6bGVuZ3RoKHBlcmNlbnQuc3RkdildKSA+IDAuMSksIAogICAgICAgICAgICAgIGRlY3JlYXNpbmcgPSBUKVsxXSArIDEKbWluLnBjIDwtIG1pbihjbzEsIGNvMikKbWluLnBjCgojIENyZWF0ZSBhIGRhdGFmcmFtZSB3aXRoIHZhbHVlcwpwbG90X2RmIDwtIGRhdGEuZnJhbWUocGN0ID0gcGVyY2VudC5zdGR2LCAKICAgICAgICAgICBjdW11ID0gY3VtdWxhdGl2ZSwgCiAgICAgICAgICAgcmFuayA9IDE6bGVuZ3RoKHBlcmNlbnQuc3RkdikpCgojIEVsYm93IHBsb3QgdG8gdmlzdWFsaXplIAogIGdncGxvdChwbG90X2RmLCBhZXMoY3VtdWxhdGl2ZSwgcGVyY2VudC5zdGR2LCBsYWJlbCA9IHJhbmssIGNvbG9yID0gcmFuayA+IG1pbi5wYykpICsgCiAgZ2VvbV90ZXh0KCkgKyAKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSA5MCwgY29sb3IgPSAiZ3JleSIpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbWluKHBlcmNlbnQuc3RkdltwZXJjZW50LnN0ZHYgPiA1XSksIGNvbG9yID0gImdyZXkiKSArCiAgdGhlbWVfYncoKQoKCmBgYAoKCiMgNi4gQ2x1c3RlcmluZwpgYGB7ciBDMSwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CgojIHJ1biB1bWFwCiNjZWxsbGluZXMubm9pbnRlcmdyYXRpb24gPC0gUnVuVU1BUChBbGxfc2FtcGxlc19NZXJnZWQsIGRpbXMgPSAxOm1pbi5wYywgcmVkdWN0aW9uID0gInBjYSIpCgoKIyBjbHVzdGVyCiNjZWxsbGluZXMubm9pbnRlcmdyYXRpb24gPC0gRmluZE5laWdoYm9ycyhvYmplY3QgPSBjZWxsbGluZXMubm9pbnRlcmdyYXRpb24sIGRpbXMgPSAxOm1pbi5wYykgICAKCgoKIyBEZXRlcm1pbmUgdGhlIGNsdXN0ZXJzIGZvciB2YXJpb3VzIHJlc29sdXRpb25zICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKI2NlbGxsaW5lcy5ub2ludGVyZ3JhdGlvbiA8LSBGaW5kQ2x1c3RlcnMob2JqZWN0ID0gY2VsbGxpbmVzLm5vaW50ZXJncmF0aW9uLCByZXNvbHV0aW9uID0gc2VxKDAuMSwxLjIsYnk9MC4xKSkKCgoKSWRlbnRzKGNlbGxsaW5lcy5ub2ludGVyZ3JhdGlvbikgPC0gIlNDVF9zbm5fcmVzLjAuNyIKY2VsbGxpbmVzLm5vaW50ZXJncmF0aW9uJHNldXJhdF9jbHVzdGVycyA8LSBjZWxsbGluZXMubm9pbnRlcmdyYXRpb24kU0NUX3Nubl9yZXMuMC43CgoKCnUxIDwtIERpbVBsb3Qob2JqZWN0ID0gY2VsbGxpbmVzLm5vaW50ZXJncmF0aW9uLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLCBsYWJlbCA9IFRSVUUsIGxhYmVsLmJveCA9IFRSVUUpCgp1MQoKCnUyIDwtIERpbVBsb3Qob2JqZWN0ID0gY2VsbGxpbmVzLm5vaW50ZXJncmF0aW9uLCAKICAgICAgICAgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwgCiAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgIGxhYmVsID0gVFJVRSwgCiAgICAgICAgIGxhYmVsLmJveCA9IFRSVUUsIAogICAgICAgICBzcGxpdC5ieSA9ICJjZWxsX2xpbmUiKQoKdTIKCgp1MyA8LSBEaW1QbG90KG9iamVjdCA9IGNlbGxsaW5lcy5ub2ludGVyZ3JhdGlvbiwgCiAgICAgICAgIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsIAogICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICBsYWJlbCA9IFRSVUUsIAogICAgICAgICBsYWJlbC5ib3ggPSBUUlVFLCAKICAgICAgICAgc3BsaXQuYnkgPSAiUGF0aWVudF9vcmlnaW4iKQoKdTMKCgp1NCA8LSBEaW1QbG90KG9iamVjdCA9IGNlbGxsaW5lcy5ub2ludGVyZ3JhdGlvbiwgCiAgICAgICAgIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsIAogICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICBsYWJlbCA9IFRSVUUsIAogICAgICAgICBsYWJlbC5ib3ggPSBUUlVFLCAKICAgICAgICAgc3BsaXQuYnkgPSAiVHJlYXRtZW50c19hbmFseXNpcyIpCgp1NAoKCnU1IDwtIGRpdHRvRGltUGxvdChvYmplY3QgPSBjZWxsbGluZXMubm9pbnRlcmdyYXRpb24sCiAgICAgICAgICAgICB2YXIgPSAic2V1cmF0X2NsdXN0ZXJzIiwKICAgICAgICAgICAgIHJlZHVjdGlvbi51c2UgPSAidW1hcCIsCiAgICAgICAgICAgICBkby5sYWJlbCA9IFRSVUUsCiAgICAgICAgICAgICBsYWJlbHMuaGlnaGxpZ2h0ID0gRkFMU0UpCnU1CgoKCnU2IDwtIGRpdHRvRGltUGxvdChvYmplY3QgPSBjZWxsbGluZXMubm9pbnRlcmdyYXRpb24sCiAgICAgICAgICAgICB2YXIgPSAic2V1cmF0X2NsdXN0ZXJzIiwKICAgICAgICAgICAgIHJlZHVjdGlvbi51c2UgPSAidW1hcCIsCiAgICAgICAgICAgICBkby5sYWJlbCA9IFRSVUUsCiAgICAgICAgICAgICBzcGxpdC5ieSA9ICJUcmVhdG1lbnRzX2FuYWx5c2lzIiwKICAgICAgICAgICAgIGxhYmVscy5oaWdobGlnaHQgPSBGQUxTRSkKdTYKCgoKCgojSW50ZWdyYXRlIHdpdGggaGFybW9ueQojIFJ1biBoYXJtb255IHRvIGhhcm1vbml6ZSBvdmVyIHNhbXBsZXMgCiMgY2VsbGxpbmVzLmludGVyZ3JhdGlvbiA8LSBSdW5IYXJtb255KAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGxsaW5lcy5ub2ludGVyZ3JhdGlvbiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAuYnkudmFycyA9ICJvcmlnLmlkZW50IiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXkudXNlID0gIlNDVCIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJwY2EiLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90X2NvbnZlcmdlbmNlID0gVFJVRSkKCgoKCgoKI0ZpbmQgc2lnbmlmaWNhbnQgUENzCiNGaXJzdCBtZXRyaWMKCiMgRGV0ZXJtaW5lIHBlcmNlbnQgb2YgdmFyaWF0aW9uIGFzc29jaWF0ZWQgd2l0aCBlYWNoIFBDCnN0ZHYgPC0gY2VsbGxpbmVzLmludGVyZ3JhdGlvbltbInBjYSJdXUBzdGRldgpzdW0uc3RkdiA8LSBzdW0oY2VsbGxpbmVzLmludGVyZ3JhdGlvbltbInBjYSJdXUBzdGRldikKcGVyY2VudC5zdGR2IDwtIChzdGR2IC8gc3VtLnN0ZHYpICogMTAwCgojIENhbGN1bGF0ZSBjdW11bGF0aXZlIHBlcmNlbnRzIGZvciBlYWNoIFBDCmN1bXVsYXRpdmUgPC0gY3Vtc3VtKHBlcmNlbnQuc3RkdikKCiMgRGV0ZXJtaW5lIHdoaWNoIFBDIGV4aGliaXRzIGN1bXVsYXRpdmUgcGVyY2VudCBncmVhdGVyIHRoYW4gOTAlIGFuZAojIGFuZCAlIHZhcmlhdGlvbiBhc3NvY2lhdGVkIHdpdGggdGhlIFBDIGFzIGxlc3MgdGhhbiA1CmNvMSA8LSB3aGljaChjdW11bGF0aXZlID4gOTAgJiBwZXJjZW50LnN0ZHYgPCA1KVsxXQpjbzEKCgojIERldGVybWluZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHZhcmlhdGlvbiBvZiBQQyBhbmQgc3Vic2VxdWVudCBQQwpjbzIgPC0gc29ydCh3aGljaCgKICAocGVyY2VudC5zdGR2WzE6bGVuZ3RoKHBlcmNlbnQuc3RkdikgLSAxXSAtIAogICAgIHBlcmNlbnQuc3RkdlsyOmxlbmd0aChwZXJjZW50LnN0ZHYpXSkgPiAwLjEpLCAKICBkZWNyZWFzaW5nID0gVClbMV0gKyAxCgojIGxhc3QgcG9pbnQgd2hlcmUgY2hhbmdlIG9mICUgb2YgdmFyaWF0aW9uIGlzIG1vcmUgdGhhbiAwLjElLgpjbzIKCiMgTWluaW11bSBvZiB0aGUgdHdvIGNhbGN1bGF0aW9uCm1pbi5wYyA8LSBtaW4oY28xLCBjbzIpCm1pbi5wYwoKCiAKcGxvdF9kZiA8LSBkYXRhLmZyYW1lKHBjdCA9IHBlcmNlbnQuc3RkdiwgCiAgICAgICAgICAgY3VtdSA9IGN1bXVsYXRpdmUsIAogICAgICAgICAgIHJhbmsgPSAxOmxlbmd0aChwZXJjZW50LnN0ZHYpKQoKIyBFbGJvdyBwbG90IHRvIHZpc3VhbGl6ZSAKICBnZ3Bsb3QocGxvdF9kZiwgYWVzKGN1bXVsYXRpdmUsIHBlcmNlbnQuc3RkdiwgbGFiZWwgPSByYW5rLCBjb2xvciA9IHJhbmsgPiBtaW4ucGMpKSArIAogIGdlb21fdGV4dCgpICsgCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gOTAsIGNvbG9yID0gImdyZXkiKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IG1pbihwZXJjZW50LnN0ZHZbcGVyY2VudC5zdGR2ID4gNV0pLCBjb2xvciA9ICJncmV5IikgKwogIHRoZW1lX2J3KCkKCiMgUnVuIFVNQVAKIyBjZWxsbGluZXMuaW50ZXJncmF0aW9uIDwtIFJ1blVNQVAoY2VsbGxpbmVzLmludGVyZ3JhdGlvbiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gMTptaW4ucGMsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJwY2EiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4uY29tcG9uZW50cyA9IDMpICMgc2V0IHRvIDMgdG8gdXNlIHdpdGggVlIKCgojIERldGVybWluZSB0aGUgSy1uZWFyZXN0IG5laWdoYm9yIGdyYXBoCiNjZWxsbGluZXMuaW50ZXJncmF0aW9uIDwtIEZpbmROZWlnaGJvcnMob2JqZWN0ID0gY2VsbGxpbmVzLmludGVyZ3JhdGlvbixkaW1zID0gMTptaW4ucGMpCgoKIyBEZXRlcm1pbmUgdGhlIGNsdXN0ZXJzIGZvciB2YXJpb3VzIHJlc29sdXRpb25zICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKI2NlbGxfbGluZS51bmFubm90YXRlZCA8LSBGaW5kQ2x1c3RlcnMob2JqZWN0ID0gY2VsbGxpbmVzLmludGVyZ3JhdGlvbixyZXNvbHV0aW9uID0gc2VxKDAuMSwxLjIsYnk9MC4xKSkKCgoKIyBOZXVyb25zIGFmdGVyIHJlLWNsdXN0ZXIKIyBVTUFQCkRlZmF1bHRBc3NheShjZWxsX2xpbmUudW5hbm5vdGF0ZWQpIDwtICJTQ1QiCiNuZXVyb24udW5hbm5vdGF0ZWQgPC0gTm9ybWFsaXplRGF0YShuZXVyb24udW5hbm5vdGF0ZWQsIHZlcmJvc2UgPSBGQUxTRSkKY2VsbF9saW5lLnVuYW5ub3RhdGVkJHNldXJhdF9jbHVzdGVycyA8LSBjZWxsX2xpbmUudW5hbm5vdGF0ZWQkU0NUX3Nubl9yZXMuMC43Cgp1MSA8LSBkaXR0b0RpbVBsb3Qob2JqZWN0ID0gY2VsbF9saW5lLnVuYW5ub3RhdGVkLAogICAgICAgICAgICAgdmFyID0gInNldXJhdF9jbHVzdGVycyIsCiAgICAgICAgICAgICByZWR1Y3Rpb24udXNlID0gInVtYXAiLAogICAgICAgICAgICAgZG8ubGFiZWwgPSBUUlVFLAogICAgICAgICAgICAgbGFiZWxzLmhpZ2hsaWdodCA9IEZBTFNFKQp1MQoKdTIgPC0gZGl0dG9EaW1QbG90KG9iamVjdCA9IGNlbGxfbGluZS51bmFubm90YXRlZCwKICAgICAgICAgICAgIHZhciA9ICJzZXVyYXRfY2x1c3RlcnMiLAogICAgICAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJ1bWFwIiwKICAgICAgICAgICAgIGRvLmxhYmVsID0gVFJVRSwKICAgICAgICAgICAgIHNwbGl0LmJ5ID0gIlRyZWF0bWVudHNfYW5hbHlzaXMiLAogICAgICAgICAgICAgbGFiZWxzLmhpZ2hsaWdodCA9IEZBTFNFKQp1MgoKCmBgYAoKCmBgYHtyIEMyLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQoKIyAjQ2x1c3RlciB0cmVlCiMgY2x1c3Rlcl9jb2xvcnMgPC0gYygiZ29sZCIsImZpcmVicmljazEiLCJkb2RnZXJibHVlIiwiZ3JlZW4iLAojICAgICAgICAgICAgICAgICAgICAgImN5YW4iLCJjaG9jb2xhdGU0IiwiZ3JheTQwIiwicHVycGxlIiwgImJsdWUiKQojIAojIGNlbGxsaW5lcy5ub2ludGVyZ3JhdGlvbiA8LSBCdWlsZENsdXN0ZXJUcmVlKG9iamVjdCA9IGNlbGxsaW5lcy5ub2ludGVyZ3JhdGlvbiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IDE6bWluLnBjLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW9yZGVyID0gRkFMU0UsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlb3JkZXIubnVtZXJpYyA9IEZBTFNFKQojIAojIHRyZWUgPC0gY2VsbGxpbmVzLm5vaW50ZXJncmF0aW9uQHRvb2xzJEJ1aWxkQ2x1c3RlclRyZWUKIyB0cmVlJHRpcC5sYWJlbCA8LSBwYXN0ZTAoIkNsdXN0ZXIgIiwgdHJlZSR0aXAubGFiZWwpCiMgCiMgcCA8LSBnZ3RyZWU6OmdndHJlZSh0cmVlLCBhZXMoeCwgeSkpICsKIyAgIHNjYWxlX3lfcmV2ZXJzZSgpICsKIyAgIGdndHJlZTo6Z2VvbV90cmVlKCkgKwojICAgZ2d0cmVlOjp0aGVtZV90cmVlKCkgKwojICAgZ2d0cmVlOjpnZW9tX3RpcGxhYihvZmZzZXQgPSAxKSArCiMgICBnZ3RyZWU6Omdlb21fdGlwcG9pbnQoY29sb3IgPSBjbHVzdGVyX2NvbG9yc1sxOmxlbmd0aCh0cmVlJHRpcC5sYWJlbCldLCBzaGFwZSA9IDE2LCBzaXplID0gNSkgKwojICAgY29vcmRfY2FydGVzaWFuKGNsaXAgPSAnb2ZmJykgKwojICAgdGhlbWUocGxvdC5tYXJnaW4gPSB1bml0KGMoMCwyLjUsMCwwKSwgJ2NtJykpCgpgYGAKCgojIFNhdmUgdGhlIFNldXJhdCBvYmplY3QgYXMgYW4gUm9iaiBmaWxlLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpgYGB7ciBzYXZlUkRTfQoKCiMgc2F2ZQojc2F2ZShjZWxsX2xpbmUudW5hbm5vdGF0ZWQsZmlsZSA9ICIxNS1jZWxsX2xpbmUudW5hbm5vdGF0ZWRfMS5Sb2JqIikKCmBgYAoKYGBgCgoKCg==