Cluster testing from Weinstock002 ALK+ALCL and ALK-ALCL data 14DEC21
Libraries
library(dendextend)
library(DESeq2)
library(colorspace)
library(RColorBrewer)
library(DESeq2)
library(ggplot2)
library(dplyr)
library(reshape2)
library(plotly)
library(gridExtra)
library(gplots)
library(pals)
library(pheatmap)
library(colorspace)
library(scico)
Full PROseq data set analysis for TCL cell lines
https://talgalili.github.io/dendextend/articles/Cluster_Analysis.html
dds_alcl <- dds_pro[,-c(1,2,3,7,8,13,15,16,17,18,19,20,21,22,23,24)] #Excluding sample numbers of entities that are not Alk+Alcl or Alk-Alcl
estimateSizeFactors(dds_alcl) #Must re-calculate size factors after removing samples
class: DESeqDataSet
dim: 120888 9
metadata(1): version
assays(1): counts
rownames(120888): dREGpeak000003 dREGpeak000004 ... dREGpeak312454 dREGpeak312455
rowData names(0):
colnames(9): KARPAS299 L82 ... DL40 SUDHL1
colData names(3): sample subtype sizeFactor
deseq_sizes_alcl <- as.data.frame(sizeFactors(dds_alcl))
deseq_sizes_alcl
rld_alcl <- rlog(dds_alcl, blind=TRUE)
#colnames(rld_alcl) <- paste0(sampleNames_alcl,"(",subTypes_alcl,")")
sampleDists_alcl <- dist(t(assay(rld_alcl)))
sampleDistMtx_alcl <- as.matrix(sampleDists_alcl)
rownames(sampleDistMtx_alcl) <- paste0(rld_alcl$sample,"_",rld_alcl$subtype)
colnames(sampleDistMtx_alcl) <- NULL
hclust_alcl <- hclust(sampleDists_alcl)
norm_alcl <- as.data.frame(counts(dds_alcl, normalized=TRUE)) #think this is redundant with normcounts_alcl but keeping it for now
colnames(norm_alcl) <- dds_alcl$sample
Do initial dendrograms and determine PCA contributors
plotPCA(rld_alcl, intgroup="subtype")

plotPCA(rld_alcl, intgroup="sample")

plot(hclust_alcl, labels=rownames(sampleDistMtx_alcl), main="PRO-seq Alcl Samples dREG Dendrogram")
pdf("dREG_hclust.sample.pdf")
plot(hclust_alcl, labels=rownames(sampleDistMtx_alcl), main="PRO-seq Alcl Samples dREG Dendrogram")
dev.off()
quartz_off_screen
2

Determine the number of PCA contributors necessary to cleanly separate subtypes
plotPCA(rld_alcl, intgroup="subtype", ntop=100) + ggtitle("Top 100")

plotPCA(rld_alcl, intgroup="subtype", ntop=200) + ggtitle("Top 200")

plotPCA(rld_alcl, intgroup="subtype", ntop=500) + ggtitle("Top 500")

plotPCA(rld_alcl, intgroup="subtype", ntop=1000) + ggtitle("Top 1000")

plotPCA(rld_alcl, intgroup="subtype", ntop=2000) + ggtitle("Top 2000")

plotPCA(rld_alcl, intgroup="subtype", ntop=5000) + ggtitle("Top 5000")

plotPCA(rld_alcl, intgroup="subtype", ntop=10000) + ggtitle("Top 10000")

plotPCA(rld_alcl, intgroup="subtype", ntop=20000) + ggtitle("Top 20000")

plotPCA(rld_alcl, intgroup="subtype", ntop=50000) + ggtitle("Top 50000")

plotPCA(rld_alcl, intgroup="subtype", ntop=120888) + ggtitle("All")
pdf("dREG_pca.all.pdf")
plotPCA(rld_alcl, intgroup="subtype", ntop=100) + ggtitle("Top 100")
plotPCA(rld_alcl, intgroup="subtype", ntop=200) + ggtitle("Top 200")
plotPCA(rld_alcl, intgroup="subtype", ntop=500) + ggtitle("Top 500")
plotPCA(rld_alcl, intgroup="subtype", ntop=1000) + ggtitle("Top 1000")
plotPCA(rld_alcl, intgroup="subtype", ntop=2000) + ggtitle("Top 2000")
plotPCA(rld_alcl, intgroup="subtype", ntop=5000) + ggtitle("Top 5000")
plotPCA(rld_alcl, intgroup="subtype", ntop=10000) + ggtitle("Top 10000")
plotPCA(rld_alcl, intgroup="subtype", ntop=20000) + ggtitle("Top 20000")
plotPCA(rld_alcl, intgroup="subtype", ntop=50000) + ggtitle("Top 50000")
plotPCA(rld_alcl, intgroup="subtype", ntop=77061) + ggtitle("All")
dev.off()
quartz_off_screen
2

#Note: can make this a nicer grid with shared axes?
Rank dREG peaks by PCA contribution and measure variance and cumulative variance
#Load dREG peak annotations
dREG_annot2 <- read.table("../002_TCLs_p1000_dREGpeak_annotation.txt", sep="\t", header=TRUE)
#Define and rank top 1k PCA contributors
rv <- rowVars(assay(rld_alcl))
select <- order(rv, decreasing=TRUE)#[seq_len(min(1000, length(rv)))]
pc <- prcomp(t(assay(rld_alcl)[select,]))
loadings <- as.data.frame(pc$rotation)
aload <- abs(loadings)
pcRank_alcl <- data.frame("peakID"=rownames(loadings), "PCA.rank"=seq.int(nrow(loadings)))
#sweep(aload, 2, colSums(aload), "/")
###clean up variables
rm(rv)
rm(select)
rm(pc)
rm(loadings)
#Generate list of dREG peak annotations
peakInfo_alcl <- merge(dREG_annot2, pcRank_alcl, by.x="peakID", by.y="peakID")
peakVar_alcl <- data.frame("peakID"=rownames(assay(rld_alcl)))
peakVar_alcl$rlog.variance <- rowVars(as.matrix(assay(rld_alcl)))
peakVar_alcl <- merge(peakInfo_alcl, peakVar_alcl, by.x="peakID", by.y="peakID")
pdf("variance.pdf")
ggplot(peakVar_alcl, aes(x=PCA.rank, y=rlog.variance)) + geom_line() + geom_vline(xintercept=5000, linetype="dotted")
dev.off()
null device
1
ggplot(peakVar_alcl, aes(x=PCA.rank, y=rlog.variance)) + geom_line() + geom_vline(xintercept=5000, linetype="dotted")
#add plot of fraction of explained variance.. running sum / total vs rank
peakVar_alcl <- peakVar_alcl[order(peakVar_alcl$PCA.rank),]
peakVar_alcl$cumulative.Variance <- cumsum(peakVar_alcl$rlog.variance)/sum(peakVar_alcl$rlog.variance)
pdf("cumulative_variance.pdf")
ggplot(peakVar_alcl, aes(x=PCA.rank, y=cumulative.Variance)) + geom_line() + geom_vline(xintercept=5000, linetype="dotted")
dev.off()
quartz_off_screen
2

ggplot(peakVar_alcl, aes(x=PCA.rank, y=cumulative.Variance)) + geom_line() + geom_vline(xintercept=5000, linetype="dotted")

Filter rld objects by samples… separate “positive” set from “negative” set
#Separate positiveing and negative set
filt <- which(!colnames(rld_alcl) %in% c("MAC2A", "FEPD", "DL40"))
rld_positive <- rld_alcl[,filt]
filt <- which(colnames(rld_alcl) %in% c("MAC2A", "FEPD", "DL40"))
rld_negative <- rld_alcl[,filt]
filt <- which(!colnames(norm_alcl) %in% c("MAC2A", "FEPD", "DL40"))
norm_positive <- norm_alcl[,filt]
filt <- which(colnames(norm_alcl) %in% c("MAC2A", "FEPD", "DL40"))
norm_negative <- norm_alcl[,filt]
Determine the number of PCA contributors necessary to cleanly separate subtypes
Sample grouping looks pretty good between 5k and 10k top contributors. Will look at these cutoffs in more detail.
Rank dREG peaks by PCA contribution and measure variance and cumulative variance
#Define and rank top 10k PCA contributors
rv <- rowVars(assay(rld_positive))
select <- order(rv, decreasing=TRUE)#[seq_len(min(10000, length(rv)))]
pc <- prcomp(t(assay(rld_positive)[select,]))
loadings <- as.data.frame(pc$rotation)
aload <- abs(loadings)
pcRank2 <- data.frame("peakID"=rownames(loadings), "PCA.rank"=seq.int(nrow(loadings)))
#sweep(aload, 2, colSums(aload), "/")
###clean up variables
rm(rv)
rm(select)
rm(pc)
rm(loadings)
#Generate list of dREG peak annotations
peakInfo2 <- merge(dREG_annot2, pcRank2, by.x="peakID", by.y="peakID")
peakVar2 <- data.frame("peakID"=rownames(assay(rld_positive)))
peakVar2$rlog.variance <- rowVars(as.matrix(assay(rld_positive)))
peakVar2 <- merge(peakInfo2, peakVar2, by.x="peakID", by.y="peakID")
ggplot(peakVar2, aes(x=PCA.rank, y=rlog.variance)) + geom_line() + geom_vline(xintercept=c(500,1000,2000,5000,10000), linetype="dotted")

#add plot of fraction of explained variance.. running sum / total vs rank
peakVar2 <- peakVar2[order(peakVar2$PCA.rank),]
peakVar2$cumulative.Variance <- cumsum(peakVar2$rlog.variance)/sum(peakVar2$rlog.variance)
ggplot(peakVar2, aes(x=PCA.rank, y=cumulative.Variance)) + geom_line() + geom_vline(xintercept=c(500,1000,2000,5000,10000), linetype="dotted")

1k seems reasonable
Filter for top 1k PCA contributors
#filter normalized counts for top 5k PCA contributors
top1k <- filter(peakVar2, PCA.rank<=1000)$peakID
norm_top1k <- norm_positive[which((rownames(norm_positive) %in% top1k)==TRUE),]
rld_top1k_positive <- subset(assay(rld_positive), rownames(assay(rld_positive)) %in% top1k)
rld_top1k_negative <- subset(assay(rld_negative), rownames(assay(rld_negative)) %in% top1k)
rld_top1k_alcl <- subset(assay(rld_alcl), rownames(assay(rld_alcl)) %in% top1k)
Calculate sample distances with new top1k training and matched test sets, then calculate the correlation between the branchpoints of the two
d_positive <- rld_top1k_positive %>% dist %>% hclust %>% as.dendrogram
d_negative <- rld_top1k_negative %>% dist %>% hclust %>% as.dendrogram
d_alcl <- rld_top1k_alcl %>% dist %>% hclust %>% as.dendrogram
#compare clusters excluding unclustered to unclustered alone
d_positive_negative <- dendlist(positive = d_positive, negative = d_negative)
d_positive_negative %>% cor.dendlist
positive negative
positive 1.0000000 0.3108639
negative 0.3108639 1.0000000
d_positive_negative %>% cor.dendlist(method_coef = "spearman")
positive negative
positive 1.0000000 0.3309033
negative 0.3309033 1.0000000
Bk_plot(d_positive, d_negative, k = 2:30, xlim = c(2,30), main = "ALK+ALCL Set vs ALK-ALCL Bk plot")

#compare clusters excluding unclustered to clusters using all samples
d_positive_alcl <- dendlist(positive = d_positive, all = d_alcl)
d_positive_alcl %>% cor.dendlist
positive all
positive 1.0000000 0.7879944
all 0.7879944 1.0000000
d_positive_alcl %>% cor.dendlist(method_coef = "spearman")
positive all
positive 1.000000 0.649814
all 0.649814 1.000000
Bk_plot(d_positive, d_alcl, k = 2:30, xlim = c(2,30), main = "ALK_ALCL Set vs All ALCL Samples Bk plot")

#compare clusters all sample clustering to unclustered alone
d_alcl_negative <- dendlist(all = d_alcl, negative = d_negative)
d_alcl_negative %>% cor.dendlist
all negative
all 1.0000000 0.4397905
negative 0.4397905 1.0000000
d_alcl_negative %>% cor.dendlist(method_coef = "spearman")
all negative
all 1.0000000 0.4374482
negative 0.4374482 1.0000000
Bk_plot(d_alcl, d_negative, k = 2:30, xlim = c(2,30), main = "All ALCL Samples vs. ALK-ALCL Bk plot")

3k clusters?
Now some fun with Tanglegrams…
pre_tang_d_positive_negative <- d_positive_negative %>% ladderize %>% untangle %>% set("branches_k_color", k = 3)
positive_branches_colors <- get_leaves_branches_col(pre_tang_d_positive_negative$positive)
pre_tang_d_positive_negative %>% tanglegram(fast = T, color_lines = positive_branches_colors)

pre_tang_d_positive_alcl <- d_positive_alcl %>% ladderize %>% untangle %>% set("branches_k_color", k = 3)
positive_branches_colors <- get_leaves_branches_col(pre_tang_d_positive_alcl$positive)
pre_tang_d_positive_alcl %>% tanglegram(fast = T, color_lines = positive_branches_colors)

pre_tang_d_alcl_negative <- d_alcl_negative %>% ladderize %>% untangle %>% set("branches_k_color", k = 3)
positive_branches_colors <- get_leaves_branches_col(pre_tang_d_alcl_negative$all)
pre_tang_d_alcl_negative %>% tanglegram(fast = T, color_lines = positive_branches_colors)

The three different sets lead to drastically different cluster designations. Will attempt to look at overlap between cluster sets though it is somewhat arbitrary which samples end up being the hold-outs.
Only highlight genes clustered in common
#d_positive_negative_common <- d_positive_negative %>% prune_common_subtrees.dendlist
#d_positive_negative_common %>% untangle %>% tanglegram(common_subtrees_color_branches = TRUE)
#d_positive_alcl_common <- d_positive_alcl %>% prune_common_subtrees.dendlist
#d_positive_alcl_common %>% untangle %>% tanglegram(common_subtrees_color_branches = TRUE)
#d_alcl_negative_common <- d_alcl_negative %>% prune_common_subtrees.dendlist
#d_alcl_negative_common %>% untangle %>% tanglegram(common_subtrees_color_branches = TRUE)
Quite a few shared leaves between the positiveing set and all. Let’s see what they are…
#d_positive_negative %>% nleaves
#d_positive_negative_common %>% nleaves
#d_positive_alcl %>% nleaves
#d_positive_alcl_common %>% nleaves
#d_alcl_negative %>% nleaves
#d_alcl_negative_common %>% nleaves
n leaves preserved between the subset and all samples.
Next is to figure a way to define expression/activity groups: - k-means as before - or - dynamic branch cutting -
using top 1k PCA contributors (as determined a reasonable cutoff in the variance plots)
#filter normalized counts for top 1k PCA contributors
top1k_alcl <- filter(peakVar_alcl, PCA.rank<=1000)$peakID
bot1k_alcl <- filter(peakVar_alcl, PCA.rank>119888)$peakID
norm_top1k_alcl <- norm_alcl[which((rownames(norm_alcl) %in% top1k_alcl)==TRUE),]
rld_top1k_alcl <- subset(assay(rld_alcl), rownames(assay(rld_alcl)) %in% top1k_alcl)
colnames(norm_top1k_alcl) <- colnames(rld_top1k_alcl)
rld_bot1k_alcl <- subset(assay(rld_alcl), rownames(assay(rld_alcl)) %in% bot1k_alcl)
(row.names(rld_top1k_alcl) %in% row.names(rld_bot1k_alcl))==FALSE #check dREGs pulled into top and bottom do not match- should run T for all
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[20] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[39] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[58] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[77] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[96] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[115] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[134] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[153] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[172] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[191] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[210] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[229] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[248] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[267] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[286] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[305] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[324] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[343] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[362] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[381] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[400] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[419] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[438] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[457] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[476] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[495] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[514] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[533] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[552] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[571] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[590] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[609] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[628] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[647] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[666] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[685] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[704] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[723] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[742] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[761] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[780] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[799] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[818] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[837] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[856] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[875] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[894] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[913] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[932] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[951] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[970] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[989] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
#scale() function centers values +/- the mean of each column for normalized counts or rlog normalized counts
scaledata_count_top <- t(scale(t(norm_top1k_alcl))) # Centers and scales data.
scaledata_count_top <- scaledata_count_top[complete.cases(scaledata_count_top),] # Removes rows with nulls
scaledata_rld_top <- t(scale(t(rld_top1k_alcl))) # Centers and scales data.
scaledata_rld_top <- scaledata_rld_top[complete.cases(scaledata_rld_top),] # Removes rows with nulls
scaledata_rld_alcl <- t(scale(t(assay(rld_alcl))))
scaledata_rld_alcl <- scaledata_rld_alcl[complete.cases(scaledata_rld_alcl),]
scaledata_rld_bot <- t(scale(t(rld_bot1k_alcl)))
scaledata_rld_bot <- scaledata_rld_bot[complete.cases(scaledata_rld_bot),]
#also try with relative activity scaling
scaledata_rel_top <- data.frame(row.names=rownames(norm_top1k_alcl))
scaledata_rel_top$max.dREG.counts <- apply(norm_top1k_alcl[1:ncol(norm_top1k_alcl)], 1, max, na.rm=TRUE)
i=1
while (i<=ncol(norm_top1k_alcl)){
scaledata_rel_top[paste0(names(norm_top1k_alcl[i]))] <- norm_top1k_alcl[,i]/scaledata_rel_top$max.dREG.counts
i=i+1
}
#Generate column and row hierarchical clustering for each normalization method (all spearman for now)
hr_count <- hclust(as.dist(1-cor(t(scaledata_count_top), method="spearman")), method="complete") # Cluster rows by Pearson correlation.
hc_count <- hclust(as.dist(1-cor(scaledata_count_top, method="spearman")), method="complete") # Clusters columns by Spearman correlation.
hr_rld <- hclust(as.dist(1-cor(t(scaledata_count_top), method="spearman")), method="complete") # Cluster rows by Pearson correlation.
hc_rld <- hclust(as.dist(1-cor(scaledata_rld_alcl, method="spearman")), method="complete") # Clusters columns by Spearman correlation.
#hr_bot <- hclust(as.dist(1-cor(t(scaledata_rld_bot), method="spearman")), method="complete")
hr_rel <- hclust(as.dist(1-cor(t(scaledata_rel_top[,c(2:10)]), method="spearman")), method="complete") # Cluster rows by Pearson correlation.
hc_rel <- hclust(as.dist(1-cor(scaledata_rel_top[,c(2:10)], method="spearman")), method="complete") # Clusters columns by Spearman correlation.
Dynamic Branch Cutting negative (3-5)
library(dendextend)
cnt_cutk3 <- cutree(hr_count,k=3) #cut at specific height h or cut for a specific number of clusters k
cnt_cutk4 <- cutree(hr_count,k=4)
cnt_cutk5 <- cutree(hr_count,k=5)
rld_cutk2 <- cutree(hr_rld,k=2)
rld_cutk3 <- cutree(hr_rld,k=3)
rld_cutk4 <- cutree(hr_rld,k=4)
rld_cutk5 <- cutree(hr_rld,k=5)
rld_cutk6 <- cutree(hr_rld,k=6)
rld_cutk7 <- cutree(hr_rld,k=7)
rld_cutk8 <- cutree(hr_rld,k=8)
rld_cutk9 <- cutree(hr_rld,k=9)
rld_bot1k_alcl <- as.integer(rep(0, 5000))
names(rld_bot1k_alcl) <- bot1k_alcl
rel_cutk3 <- cutree(hr_rel,k=3)
rel_cutk4 <- cutree(hr_rel,k=4)
rel_cutk5 <- cutree(hr_rel,k=5)
#plot the tree
TreeR_cnt = as.dendrogram(hr_count, method="average")
TreeR_rld = as.dendrogram(hr_rld, method="average")
TreeR_rel = as.dendrogram(hr_rel, method="average")
#define annotation bars
the_bars_k3 <- cbind(cnt_cutk3, rld_cutk3, rel_cutk3)
the_bars_k4 <- cbind(cnt_cutk4, rld_cutk4, rel_cutk4)
the_bars_k5 <- cbind(cnt_cutk5, rld_cutk5, rel_cutk5)
the_bars_cnt <- cbind(cnt_cutk3, cnt_cutk4, cnt_cutk5)
the_bars_rld <- cbind(rld_cutk3, rld_cutk4, rld_cutk5)
the_bars_rel <- cbind(rel_cutk3, rel_cutk4, rel_cutk5)
Compare clusters
plot(TreeR_rld,
leaflab = "none",
main = "dREG Peak Clustering (rlog) k=3",
ylab = "Height")
#this makes the bar
colored_bars(the_bars_k3, TreeR_rld, sort_by_labels_order = T, y_shift=-0.1, rowLabels = c("By Counts","By rLog","By Relative Activity"),cex.rowLabels=0.7)

plot(TreeR_rld,
leaflab = "none",
main = "dREG Peak Clustering (rlog) k=4",
ylab = "Height")
#this makes the bar
colored_bars(the_bars_k4, TreeR_rld, sort_by_labels_order = T, y_shift=-0.1, rowLabels = c("By Counts","By rLog","By Relative Activity"),cex.rowLabels=0.7)

plot(TreeR_rld,
leaflab = "none",
main = "dREG Peak Clustering (rlog) k=5",
ylab = "Height")
#this makes the bar
colored_bars(the_bars_k5, TreeR_rld, sort_by_labels_order = T, y_shift=-0.1, rowLabels = c("By Counts","By rLog","By Relative Activity"),cex.rowLabels=0.7)

Clustering is exactly the same regardless of method now!! This is great!
Compare clusters
plot(TreeR_cnt,
leaflab = "none",
main = "dREG Peak Clustering (counts)",
ylab = "Height")
#this makes the bar
colored_bars(the_bars_cnt, TreeR_cnt, sort_by_labels_order = T, y_shift=-0.1, rowLabels = c("k=3","k=4","k=5"),cex.rowLabels=0.7)

plot(TreeR_rld,
leaflab = "none",
main = "dREG Peak Clustering (rlog)",
ylab = "Height")
#this makes the bar
colored_bars(the_bars_rld, TreeR_rld, sort_by_labels_order = T, y_shift=-0.1, rowLabels = c("k=3","k=4","k=5"),cex.rowLabels=0.7)

plot(TreeR_rel,
leaflab = "none",
main = "dREG Peak Clustering (relative activity)",
ylab = "Height")
#this makes the bar
colored_bars(the_bars_rel, TreeR_rel, sort_by_labels_order = T, y_shift=-0.1, rowLabels = c("k=3","k=4","k=5"),cex.rowLabels=0.7)

Let’s see how well these clusters separate expression groups associated with different cell line subtypes…
data_alcl <- c( "KARPAS299_ALK+ALCL",
"L82_ALK+ALCL",
"SUPM2_ALK+ALCL",
"MAC2A_ALK-ALCL",
"KIJK_ALK+ALCL",
"SR786_ALK+ALCL",
"FEPD_ALK-ALCL",
"DL40_ALK-ALCL",
"SUDHL1_ALK+ALCL")
#Defining box plot functions
clust.core = function(i, dat, clusters) {
ind = (clusters == i)
colMeans(dat[ind,])
}
box <- function(clusters, scaledata_count_top, title){
cores <- sapply(unique(clusters), clust.core, scaledata_count_top, clusters)
#make a dataframe of cores by subtype
d <- data.frame(cbind(data_alcl, cores)) #subType list from beginning!
colnames(d) <-c("sample", paste0("clust_",1:ncol(cores)))
#get the data frame into long format for plotting
dmolten <- melt(d, id.vars = "sample")
#order by subtype
dmolten <- dmolten[order(dmolten$sample),]
dmolten$sample <- ordered(dmolten$sample, levels=unique(dmolten$sample))
# make the plot
p1 <- ggplot(dmolten, aes(x=sample, y=as.numeric(value), col=variable)) +
geom_boxplot() +
# geom_point() +
# geom_line() +
# scale_x_continuous(minor_breaks = NULL, breaks=c(as.numeric(levels(factor(dmolten$subtype))))) +
# scale_y_continuous() +
xlab("Sample") +
ylab("Activity") +
labs(title= paste0("Cluster Core Expression by Sample (",title,")"),color = "Cluster")
return(p1)
}
Make boxplots
box(rld_cutk2, scaledata_rld_alcl, "cutk2 rlog")

box(rld_cutk3, scaledata_rld_alcl, "cutk3 rlog")

box(rld_cutk4, scaledata_rld_alcl, "cutk4 rlog")

box(rld_cutk5, scaledata_rld_alcl, "cutk5 rlog")

box(rld_cutk6, scaledata_rld_alcl, "cutk6 rlog")

box(rld_cutk7, scaledata_rld_alcl, "cutk7 rlog")

box(rld_cutk8, scaledata_rld_alcl, "cutk8 rlog")

box(rld_cutk9, scaledata_rld_alcl, "cutk9 rlog")

box(c(rld_cutk3,rld_bot1k_alcl), rbind(scaledata_rld_alcl,scaledata_rld_bot), "cutk3 + static [\"clust_5\"] rlog")

box(rel_cutk3, scaledata_rel_top[,2:10], "cutk3 rel")

box(rel_cutk4, scaledata_rel_top[,2:10], "cutk4 rel")

box(rel_cutk5, scaledata_rel_top[,2:10], "cutk5 rel")

box(rel_cutk3, scaledata_count_top, "cutk3 count")

box(rel_cutk4, scaledata_count_top, "cutk4 count")

box(rel_cutk5, scaledata_count_top, "cutk5 count")

Properly by subtype instead of individual samples
data_alcl <- c( "ALK+ALCL",
"ALK+ALCL",
"ALK+ALCL",
"ALK-ALCL",
"ALK+ALCL",
"ALK+ALCL",
"ALK-ALCL",
"ALK-ALCL",
"ALK+ALCL")
#Defining box plot functions
clust.core = function(i, dat, clusters) {
ind = (clusters == i)
colMeans(dat[ind,])
}
box <- function(clusters, scaledata_count_top, title){
cores <- sapply(unique(clusters), clust.core, scaledata_count_top, clusters)
#make a dataframe of cores by subtype
d <- data.frame(cbind(data_alcl, cores)) #subType list from beginning!
colnames(d) <-c("subtype", paste0("clust_",1:ncol(cores)))
#get the data frame into long format for plotting
dmolten <- melt(d, id.vars = "subtype")
#order by subtype
dmolten <- dmolten[order(dmolten$subtype),]
dmolten$subtype <- ordered(dmolten$subtype, levels=unique(dmolten$subtype))
# make the plot
p1 <- ggplot(dmolten, aes(x=subtype, y=as.numeric(value), col=variable)) +
geom_boxplot() +
# geom_point() +
# geom_line() +
# scale_x_continuous(minor_breaks = NULL, breaks=c(as.numeric(levels(factor(dmolten$subtype))))) +
# scale_y_continuous() +
xlab("Subtype") +
ylab("Activity") +
labs(title= paste0("Cluster Core Expression by Subtype (",title,")"),color = "Cluster")
return(p1)
}
Make boxplots
box(rld_cutk2, scaledata_rld_alcl, "cutk2 rlog")

box(rld_cutk3, scaledata_rld_alcl, "cutk3 rlog")

box(rld_cutk4, scaledata_rld_alcl, "cutk4 rlog")

box(rld_cutk5, scaledata_rld_alcl, "cutk5 rlog")

box(rld_cutk6, scaledata_rld_alcl, "cutk6 rlog")

box(rld_cutk7, scaledata_rld_alcl, "cutk7 rlog")

box(rld_cutk8, scaledata_rld_alcl, "cutk8 rlog")

box(rld_cutk9, scaledata_rld_alcl, "cutk9 rlog")

box(c(rld_cutk3,rld_bot1k_alcl), rbind(scaledata_rld_alcl,scaledata_rld_bot), "cutk3 + static [\"clust_5\"] rlog")

box(rel_cutk3, scaledata_rel_top[,2:10], "cutk3 rel")

box(rel_cutk4, scaledata_rel_top[,2:10], "cutk4 rel")

box(rel_cutk5, scaledata_rel_top[,2:10], "cutk5 rel")

box(rel_cutk3, scaledata_count_top, "cutk3 count")

box(rel_cutk4, scaledata_count_top, "cutk4 count")

box(rel_cutk5, scaledata_count_top, "cutk5 count")

Can’t make much sense of unique clustering between the samples or their subtypes. Considering subsetting out original data into clustering and nonclustering samples and moving on with individual cluster treatments for each from there.
Want to make a heatmap with the above clusters and a cluster-trait correlation heatmap…
Trait correlation (edit for this dataset)
traits <- data.frame(row.names=colnames(scaledata_rld_alcl))
#here I'm adding vectors of subtype traits to the dataframe
traits$'ALK+ALCL' <- c(1,1,1,0,1,1,0,0,1) #corrected
traits$'ALK-ALCL' <- c(0,0,0,1,0,0,1,1,0) #corrected
#Extract the gene/sample numbers
nPeaks = nrow(scaledata_rld_alcl)
nSamples = ncol(scaledata_rld_alcl)
#p value calculation from WGCNA
corPvalueStudent = function(cor, nSamples) {
T=sqrt(nSamples-2) * cor/sqrt(1-cor^2)
2*pt(abs(T),nSamples-2, lower.tail = FALSE)
}
Make correlation heatmaps
nSamples=9
#Finalize clustering and branch cuts
clusters <- rld_cutk2
cores <- sapply(unique(clusters), clust.core, scaledata_rld_alcl, clusters)
#correlate the cores to traits:
moduleTraitCor = cor(cores, traits, use= "p")
moduleTraitPvalue = corPvalueStudent(moduleTraitCor, nSamples)
#generate a text matrix of the correlation and pvalue
textMatrix= paste(signif(moduleTraitCor, 2), "\n(",
signif(moduleTraitPvalue, 1), ")", sep= "")
dim(textMatrix)= dim(moduleTraitCor)
#plot a heatmap of the clusters by trait overlaying the corr/pvalue
#par(oma=c(1,0,1,1))
heatmap.2(moduleTraitCor,
dendrogram = "none",
Colv =FALSE,
scale = c("none"),
col="heat.colors",
na.rm=TRUE,
cellnote = textMatrix,
notecol="grey30",
notecex=1,
trace=c("none"),
cexRow = 0.8,
cexCol = 0.8,
main = "Cluster-Trait Correlation (k=2)",
xlab = "Traits",
ylab = "Clusters")

clusters <- rld_cutk3
cores <- sapply(unique(clusters), clust.core, scaledata_rld_alcl, clusters)
#correlate the cores to traits:
moduleTraitCor = cor(cores, traits, use= "p")
moduleTraitPvalue = corPvalueStudent(moduleTraitCor, nSamples)
#generate a text matrix of the correlation and pvalue
textMatrix= paste(signif(moduleTraitCor, 2), "\n(",
signif(moduleTraitPvalue, 1), ")", sep= "")
dim(textMatrix)= dim(moduleTraitCor)
#plot a heatmap of the clusters by trait overlaying the corr/pvalue
#par(oma=c(1,0,1,1))
heatmap.2(moduleTraitCor,
dendrogram = "none",
Colv =FALSE,
scale = c("none"),
col="heat.colors",
na.rm=TRUE,
cellnote = textMatrix,
notecol="grey30",
notecex=1,
trace=c("none"),
cexRow = 0.8,
cexCol = 0.8,
main = "Cluster-Trait Correlation (k=3)",
xlab = "Traits",
ylab = "Clusters")

clusters <- rld_cutk4
cores <- sapply(unique(clusters), clust.core, scaledata_rld_alcl, clusters)
#correlate the cores to traits:
moduleTraitCor = cor(cores, traits, use= "p")
moduleTraitPvalue = corPvalueStudent(moduleTraitCor, nSamples)
#generate a text matrix of the correlation and pvalue
textMatrix= paste(signif(moduleTraitCor, 2), "\n(",
signif(moduleTraitPvalue, 1), ")", sep= "")
dim(textMatrix)= dim(moduleTraitCor)
#plot a heatmap of the clusters by trait overlaying the corr/pvalue
#par(oma=c(1,0,1,1))
heatmap.2(moduleTraitCor,
dendrogram = "none",
Colv =FALSE,
scale = c("none"),
col="heat.colors",
na.rm=TRUE,
cellnote = textMatrix,
notecol="grey30",
notecex=1,
trace=c("none"),
cexRow = 0.8,
cexCol = 0.8,
main = "Cluster-Trait Correlation (k=4)",
xlab = "Traits",
ylab = "Clusters")

clusters <- rld_cutk5
cores <- sapply(unique(clusters), clust.core, scaledata_rld_alcl, clusters)
#correlate the cores to traits:
moduleTraitCor = cor(cores, traits, use= "p")
moduleTraitPvalue = corPvalueStudent(moduleTraitCor, nSamples)
#generate a text matrix of the correlation and pvalue
textMatrix= paste(signif(moduleTraitCor, 2), "\n(",
signif(moduleTraitPvalue, 1), ")", sep= "")
dim(textMatrix)= dim(moduleTraitCor)
#plot a heatmap of the clusters by trait overlaying the corr/pvalue
#par(oma=c(1,0,1,1))
heatmap.2(moduleTraitCor,
dendrogram = "none",
Colv =FALSE,
scale = c("none"),
col="heat.colors",
na.rm=TRUE,
cellnote = textMatrix,
notecol="grey30",
notecex=1,
trace=c("none"),
cexRow = 0.8,
cexCol = 0.8,
main = "Cluster-Trait Correlation (k=5)",
xlab = "Traits",
ylab = "Clusters")

clusters <- rld_cutk6
cores <- sapply(unique(clusters), clust.core, scaledata_rld_alcl, clusters)
#correlate the cores to traits:
moduleTraitCor = cor(cores, traits, use= "p")
moduleTraitPvalue = corPvalueStudent(moduleTraitCor, nSamples)
#generate a text matrix of the correlation and pvalue
textMatrix= paste(signif(moduleTraitCor, 2), "\n(",
signif(moduleTraitPvalue, 1), ")", sep= "")
dim(textMatrix)= dim(moduleTraitCor)
#plot a heatmap of the clusters by trait overlaying the corr/pvalue
#par(oma=c(1,0,1,1))
heatmap.2(moduleTraitCor,
dendrogram = "none",
Colv =FALSE,
scale = c("none"),
col="heat.colors",
na.rm=TRUE,
cellnote = textMatrix,
notecol="grey30",
notecex=1,
trace=c("none"),
cexRow = 0.8,
cexCol = 0.8,
main = "Cluster-Trait Correlation (k=6)",
xlab = "Traits",
ylab = "Clusters")

clusters <- rld_cutk7
cores <- sapply(unique(clusters), clust.core, scaledata_rld_alcl, clusters)
#correlate the cores to traits:
moduleTraitCor = cor(cores, traits, use= "p")
moduleTraitPvalue = corPvalueStudent(moduleTraitCor, nSamples)
#generate a text matrix of the correlation and pvalue
textMatrix= paste(signif(moduleTraitCor, 2), "\n(",
signif(moduleTraitPvalue, 1), ")", sep= "")
dim(textMatrix)= dim(moduleTraitCor)
#plot a heatmap of the clusters by trait overlaying the corr/pvalue
#par(oma=c(1,0,1,1))
heatmap.2(moduleTraitCor,
dendrogram = "none",
Colv =FALSE,
scale = c("none"),
col="heat.colors",
na.rm=TRUE,
cellnote = textMatrix,
notecol="grey30",
notecex=1,
trace=c("none"),
cexRow = 0.8,
cexCol = 0.8,
main = "Cluster-Trait Correlation (k=7)",
xlab = "Traits",
ylab = "Clusters")

clusters <- rld_cutk8
cores <- sapply(unique(clusters), clust.core, scaledata_rld_alcl, clusters)
#correlate the cores to traits:
moduleTraitCor = cor(cores, traits, use= "p")
moduleTraitPvalue = corPvalueStudent(moduleTraitCor, nSamples)
#generate a text matrix of the correlation and pvalue
textMatrix= paste(signif(moduleTraitCor, 2), "\n(",
signif(moduleTraitPvalue, 1), ")", sep= "")
dim(textMatrix)= dim(moduleTraitCor)
#plot a heatmap of the clusters by trait overlaying the corr/pvalue
#par(oma=c(1,0,1,1))
heatmap.2(moduleTraitCor,
dendrogram = "none",
Colv =FALSE,
scale = c("none"),
col="heat.colors",
na.rm=TRUE,
cellnote = textMatrix,
notecol="grey30",
notecex=1,
trace=c("none"),
cexRow = 0.8,
cexCol = 0.8,
main = "Cluster-Trait Correlation (k=8)",
xlab = "Traits",
ylab = "Clusters")

clusters <- rld_cutk9
cores <- sapply(unique(clusters), clust.core, scaledata_rld_alcl, clusters)
#correlate the cores to traits:
moduleTraitCor = cor(cores, traits, use= "p")
moduleTraitPvalue = corPvalueStudent(moduleTraitCor, nSamples)
#generate a text matrix of the correlation and pvalue
textMatrix= paste(signif(moduleTraitCor, 2), "\n(",
signif(moduleTraitPvalue, 1), ")", sep= "")
dim(textMatrix)= dim(moduleTraitCor)
#plot a heatmap of the clusters by trait overlaying the corr/pvalue
#par(oma=c(1,0,1,1))
heatmap.2(moduleTraitCor,
dendrogram = "none",
Colv =FALSE,
scale = c("none"),
col="heat.colors",
na.rm=TRUE,
cellnote = textMatrix,
notecol="grey30",
notecex=1,
trace=c("none"),
cexRow = 0.8,
cexCol = 0.8,
main = "Cluster-Trait Correlation (k=9)",
xlab = "Traits",
ylab = "Clusters")

#clusters <- c(rld_cutk4,rld_bop5k_alcl)
#cores <- sapply(unique(clusters), clust.core, rbind(scaledata_rld_top, scaledata_bot), clusters)
#correlate the cores to traits:
#moduleTraitCor = cor(cores, traits, use= "p")
#moduleTraitPvalue = corPvalueStudent(moduleTraitCor, nSamples)
#generate a text matrix of the correlation and pvalue
#textMatrix= paste(signif(moduleTraitCor, 2), "\n(",
#signif(moduleTraitPvalue, 1), ")", sep= "")
#dim(textMatrix)= dim(moduleTraitCor)
#plot a heatmap of the clusters by trait overlaying the corr/pvalue
#par(oma=c(1,0,1,1))
#heatmap.2(moduleTraitCor,
#dendrogram = "none",
#Colv =FALSE,
#scale = c("none"),
#col="heat.colors",
#na.rm=TRUE,
#cellnote = textMatrix,
#notecol="grey30",
#notecex=1,
#trace=c("none"),
#cexRow = 0.8,
#cexCol = 0.8,
#main = "Cluster-Trait Correlation (k=4 + Static [5k])",
#xlab = "Traits",
#ylab = "Clusters")
Make annotated scaled rlog heatmap
rld_df <- as.data.frame(scaledata_rld_top)
rld_df$k3 <- as.data.frame(rld_cutk3)$rld_cutk3
rld_df$k4 <- as.data.frame(rld_cutk4)$rld_cutk4
colors <- c('#e6194B','#3cb44b','#ffe119','#4363d8','#f58231','#911eb4','#42d4f4','#f032e6','#bfef45','#fabed4','#469990','#dcbeff','#9A6324','#fffac8','#800000','#aaffc3','#808000','#ffd8b1','#000075','#a9a9a9','#ffffff','#000000')
#High contrast colors for figures was pulled from https://sashamaps.net/docs/resources/20-colors/
pheatmap(rld_top1k_alcl,
#rld_df[order(rld_df[,12]),][,1:11],
#gaps_row = c(879,2298,4213),
cluster_cols=T,
cluster_rows=hr_rld,
#clustering_distance_rows = "euclidean",
#clustering_method = "complete",
scale="row",
cutree_rows=4,
cutree_cols=3,
border_color=NA,
show_rownames=F,
main="Top 1k dREG Peak PCA Contributors Hierarchical",
breaks=seq(-2,2,by=0.01),
color=ocean.balance(401),
#color=scico(401, palette = 'berlin'),
#color=colorRampPalette(c("blue", "white", "red"))(41),
annotation_row=rld_df[10:11],
annotation_col=data.frame(row.names=colnames(rld_df[,1:9]), Subtype = data_alcl),
annotation_colors=list(k3=c("blue", "green", "red"),
k4=c("purple", "blue", "green", "goldenrod1"),
Subtype=c("ALK+ALCL"= 'chocolate4', "ALK-ALCL"= 'cadetblue'))
)

LS0tCnRpdGxlOiAiQUxDTCBDTHVzdGVyaW5nIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpDbHVzdGVyIHRlc3RpbmcgZnJvbSBXZWluc3RvY2swMDIgQUxLK0FMQ0wgYW5kIEFMSy1BTENMIGRhdGEgMTRERUMyMQoKTGlicmFyaWVzCmBgYHtyfQpsaWJyYXJ5KGRlbmRleHRlbmQpCmxpYnJhcnkoREVTZXEyKQpsaWJyYXJ5KGNvbG9yc3BhY2UpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KERFU2VxMikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJlc2hhcGUyKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoZ3Bsb3RzKQpsaWJyYXJ5KHBhbHMpCmxpYnJhcnkocGhlYXRtYXApCmxpYnJhcnkoY29sb3JzcGFjZSkKbGlicmFyeShzY2ljbykKYGBgCgpGdWxsIFBST3NlcSBkYXRhIHNldCBhbmFseXNpcyBmb3IgVENMIGNlbGwgbGluZXMKCmh0dHBzOi8vdGFsZ2FsaWxpLmdpdGh1Yi5pby9kZW5kZXh0ZW5kL2FydGljbGVzL0NsdXN0ZXJfQW5hbHlzaXMuaHRtbApgYGB7cn0KZGRzX2FsY2wgPC0gZGRzX3Byb1ssLWMoMSwyLDMsNyw4LDEzLDE1LDE2LDE3LDE4LDE5LDIwLDIxLDIyLDIzLDI0KV0gI0V4Y2x1ZGluZyBzYW1wbGUgbnVtYmVycyBvZiBlbnRpdGllcyB0aGF0IGFyZSBub3QgQWxrK0FsY2wgb3IgQWxrLUFsY2wKZXN0aW1hdGVTaXplRmFjdG9ycyhkZHNfYWxjbCkgI011c3QgcmUtY2FsY3VsYXRlIHNpemUgZmFjdG9ycyBhZnRlciByZW1vdmluZyBzYW1wbGVzCmRlc2VxX3NpemVzX2FsY2wgPC0gYXMuZGF0YS5mcmFtZShzaXplRmFjdG9ycyhkZHNfYWxjbCkpCmRlc2VxX3NpemVzX2FsY2wgCnJsZF9hbGNsIDwtIHJsb2coZGRzX2FsY2wsIGJsaW5kPVRSVUUpCiNjb2xuYW1lcyhybGRfYWxjbCkgPC0gcGFzdGUwKHNhbXBsZU5hbWVzX2FsY2wsIigiLHN1YlR5cGVzX2FsY2wsIikiKQpzYW1wbGVEaXN0c19hbGNsIDwtIGRpc3QodChhc3NheShybGRfYWxjbCkpKQpzYW1wbGVEaXN0TXR4X2FsY2wgPC0gYXMubWF0cml4KHNhbXBsZURpc3RzX2FsY2wpCnJvd25hbWVzKHNhbXBsZURpc3RNdHhfYWxjbCkgPC0gcGFzdGUwKHJsZF9hbGNsJHNhbXBsZSwiXyIscmxkX2FsY2wkc3VidHlwZSkKY29sbmFtZXMoc2FtcGxlRGlzdE10eF9hbGNsKSA8LSBOVUxMCmhjbHVzdF9hbGNsIDwtIGhjbHVzdChzYW1wbGVEaXN0c19hbGNsKQoKbm9ybV9hbGNsIDwtIGFzLmRhdGEuZnJhbWUoY291bnRzKGRkc19hbGNsLCBub3JtYWxpemVkPVRSVUUpKSAjdGhpbmsgdGhpcyBpcyByZWR1bmRhbnQgd2l0aCBub3JtY291bnRzX2FsY2wgYnV0IGtlZXBpbmcgaXQgZm9yIG5vdwpjb2xuYW1lcyhub3JtX2FsY2wpIDwtIGRkc19hbGNsJHNhbXBsZQpgYGAKCkRvIGluaXRpYWwgZGVuZHJvZ3JhbXMgYW5kIGRldGVybWluZSBQQ0EgY29udHJpYnV0b3JzCmBgYHtyfQpwbG90UENBKHJsZF9hbGNsLCBpbnRncm91cD0ic3VidHlwZSIpIApwbG90UENBKHJsZF9hbGNsLCBpbnRncm91cD0ic2FtcGxlIikgCnBsb3QoaGNsdXN0X2FsY2wsIGxhYmVscz1yb3duYW1lcyhzYW1wbGVEaXN0TXR4X2FsY2wpLCBtYWluPSJQUk8tc2VxIEFsY2wgU2FtcGxlcyBkUkVHIERlbmRyb2dyYW0iKQpwZGYoImRSRUdfaGNsdXN0LnNhbXBsZS5wZGYiKQpwbG90KGhjbHVzdF9hbGNsLCBsYWJlbHM9cm93bmFtZXMoc2FtcGxlRGlzdE10eF9hbGNsKSwgbWFpbj0iUFJPLXNlcSBBbGNsIFNhbXBsZXMgZFJFRyBEZW5kcm9ncmFtIikKZGV2Lm9mZigpCmBgYAoKCkRldGVybWluZSB0aGUgbnVtYmVyIG9mIFBDQSBjb250cmlidXRvcnMgbmVjZXNzYXJ5IHRvIGNsZWFubHkgc2VwYXJhdGUgc3VidHlwZXMKYGBge3J9CiAgcGxvdFBDQShybGRfYWxjbCwgaW50Z3JvdXA9InN1YnR5cGUiLCBudG9wPTEwMCkgKyBnZ3RpdGxlKCJUb3AgMTAwIikKICBwbG90UENBKHJsZF9hbGNsLCBpbnRncm91cD0ic3VidHlwZSIsIG50b3A9MjAwKSArIGdndGl0bGUoIlRvcCAyMDAiKQogIHBsb3RQQ0EocmxkX2FsY2wsIGludGdyb3VwPSJzdWJ0eXBlIiwgbnRvcD01MDApICsgZ2d0aXRsZSgiVG9wIDUwMCIpCiAgcGxvdFBDQShybGRfYWxjbCwgaW50Z3JvdXA9InN1YnR5cGUiLCBudG9wPTEwMDApICsgZ2d0aXRsZSgiVG9wIDEwMDAiKQogIHBsb3RQQ0EocmxkX2FsY2wsIGludGdyb3VwPSJzdWJ0eXBlIiwgbnRvcD0yMDAwKSArIGdndGl0bGUoIlRvcCAyMDAwIikKICBwbG90UENBKHJsZF9hbGNsLCBpbnRncm91cD0ic3VidHlwZSIsIG50b3A9NTAwMCkgKyBnZ3RpdGxlKCJUb3AgNTAwMCIpCiAgcGxvdFBDQShybGRfYWxjbCwgaW50Z3JvdXA9InN1YnR5cGUiLCBudG9wPTEwMDAwKSArIGdndGl0bGUoIlRvcCAxMDAwMCIpCiAgcGxvdFBDQShybGRfYWxjbCwgaW50Z3JvdXA9InN1YnR5cGUiLCBudG9wPTIwMDAwKSArIGdndGl0bGUoIlRvcCAyMDAwMCIpCiAgcGxvdFBDQShybGRfYWxjbCwgaW50Z3JvdXA9InN1YnR5cGUiLCBudG9wPTUwMDAwKSArIGdndGl0bGUoIlRvcCA1MDAwMCIpCiAgcGxvdFBDQShybGRfYWxjbCwgaW50Z3JvdXA9InN1YnR5cGUiLCBudG9wPTEyMDg4OCkgKyBnZ3RpdGxlKCJBbGwiKQogIApwZGYoImRSRUdfcGNhLmFsbC5wZGYiKQogIHBsb3RQQ0EocmxkX2FsY2wsIGludGdyb3VwPSJzdWJ0eXBlIiwgbnRvcD0xMDApICsgZ2d0aXRsZSgiVG9wIDEwMCIpCiAgcGxvdFBDQShybGRfYWxjbCwgaW50Z3JvdXA9InN1YnR5cGUiLCBudG9wPTIwMCkgKyBnZ3RpdGxlKCJUb3AgMjAwIikKICBwbG90UENBKHJsZF9hbGNsLCBpbnRncm91cD0ic3VidHlwZSIsIG50b3A9NTAwKSArIGdndGl0bGUoIlRvcCA1MDAiKQogIHBsb3RQQ0EocmxkX2FsY2wsIGludGdyb3VwPSJzdWJ0eXBlIiwgbnRvcD0xMDAwKSArIGdndGl0bGUoIlRvcCAxMDAwIikKICBwbG90UENBKHJsZF9hbGNsLCBpbnRncm91cD0ic3VidHlwZSIsIG50b3A9MjAwMCkgKyBnZ3RpdGxlKCJUb3AgMjAwMCIpCiAgcGxvdFBDQShybGRfYWxjbCwgaW50Z3JvdXA9InN1YnR5cGUiLCBudG9wPTUwMDApICsgZ2d0aXRsZSgiVG9wIDUwMDAiKQogIHBsb3RQQ0EocmxkX2FsY2wsIGludGdyb3VwPSJzdWJ0eXBlIiwgbnRvcD0xMDAwMCkgKyBnZ3RpdGxlKCJUb3AgMTAwMDAiKQogIHBsb3RQQ0EocmxkX2FsY2wsIGludGdyb3VwPSJzdWJ0eXBlIiwgbnRvcD0yMDAwMCkgKyBnZ3RpdGxlKCJUb3AgMjAwMDAiKQogIHBsb3RQQ0EocmxkX2FsY2wsIGludGdyb3VwPSJzdWJ0eXBlIiwgbnRvcD01MDAwMCkgKyBnZ3RpdGxlKCJUb3AgNTAwMDAiKQogIHBsb3RQQ0EocmxkX2FsY2wsIGludGdyb3VwPSJzdWJ0eXBlIiwgbnRvcD03NzA2MSkgKyBnZ3RpdGxlKCJBbGwiKQpkZXYub2ZmKCkKI05vdGU6IGNhbiBtYWtlIHRoaXMgYSBuaWNlciBncmlkIHdpdGggc2hhcmVkIGF4ZXM/CmBgYAoKUmFuayBkUkVHIHBlYWtzIGJ5IFBDQSBjb250cmlidXRpb24gYW5kIG1lYXN1cmUgdmFyaWFuY2UgYW5kIGN1bXVsYXRpdmUgdmFyaWFuY2UKYGBge3J9CiNMb2FkIGRSRUcgcGVhayBhbm5vdGF0aW9ucwpkUkVHX2Fubm90MiA8LSByZWFkLnRhYmxlKCIuLi8wMDJfVENMc19wMTAwMF9kUkVHcGVha19hbm5vdGF0aW9uLnR4dCIsIHNlcD0iXHQiLCBoZWFkZXI9VFJVRSkKI0RlZmluZSBhbmQgcmFuayB0b3AgMWsgUENBIGNvbnRyaWJ1dG9ycwpydiA8LSByb3dWYXJzKGFzc2F5KHJsZF9hbGNsKSkgCnNlbGVjdCA8LSBvcmRlcihydiwgZGVjcmVhc2luZz1UUlVFKSNbc2VxX2xlbihtaW4oMTAwMCwgbGVuZ3RoKHJ2KSkpXQpwYyA8LSBwcmNvbXAodChhc3NheShybGRfYWxjbClbc2VsZWN0LF0pKQpsb2FkaW5ncyA8LSBhcy5kYXRhLmZyYW1lKHBjJHJvdGF0aW9uKQphbG9hZCA8LSBhYnMobG9hZGluZ3MpCnBjUmFua19hbGNsIDwtIGRhdGEuZnJhbWUoInBlYWtJRCI9cm93bmFtZXMobG9hZGluZ3MpLCAiUENBLnJhbmsiPXNlcS5pbnQobnJvdyhsb2FkaW5ncykpKQojc3dlZXAoYWxvYWQsIDIsIGNvbFN1bXMoYWxvYWQpLCAiLyIpCiMjI2NsZWFuIHVwIHZhcmlhYmxlcwpybShydikKcm0oc2VsZWN0KQpybShwYykKcm0obG9hZGluZ3MpCgojR2VuZXJhdGUgbGlzdCBvZiBkUkVHIHBlYWsgYW5ub3RhdGlvbnMKcGVha0luZm9fYWxjbCA8LSBtZXJnZShkUkVHX2Fubm90MiwgcGNSYW5rX2FsY2wsIGJ5Lng9InBlYWtJRCIsIGJ5Lnk9InBlYWtJRCIpCnBlYWtWYXJfYWxjbCA8LSBkYXRhLmZyYW1lKCJwZWFrSUQiPXJvd25hbWVzKGFzc2F5KHJsZF9hbGNsKSkpCnBlYWtWYXJfYWxjbCRybG9nLnZhcmlhbmNlIDwtIHJvd1ZhcnMoYXMubWF0cml4KGFzc2F5KHJsZF9hbGNsKSkpCnBlYWtWYXJfYWxjbCA8LSBtZXJnZShwZWFrSW5mb19hbGNsLCBwZWFrVmFyX2FsY2wsIGJ5Lng9InBlYWtJRCIsIGJ5Lnk9InBlYWtJRCIpCnBkZigidmFyaWFuY2UucGRmIikKZ2dwbG90KHBlYWtWYXJfYWxjbCwgYWVzKHg9UENBLnJhbmssIHk9cmxvZy52YXJpYW5jZSkpICsgZ2VvbV9saW5lKCkgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9NTAwMCwgbGluZXR5cGU9ImRvdHRlZCIpCmRldi5vZmYoKQpnZ3Bsb3QocGVha1Zhcl9hbGNsLCBhZXMoeD1QQ0EucmFuaywgeT1ybG9nLnZhcmlhbmNlKSkgKyBnZW9tX2xpbmUoKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD01MDAwLCBsaW5ldHlwZT0iZG90dGVkIikKCiNhZGQgcGxvdCBvZiBmcmFjdGlvbiBvZiBleHBsYWluZWQgdmFyaWFuY2UuLiBydW5uaW5nIHN1bSAvIHRvdGFsIHZzIHJhbmsKcGVha1Zhcl9hbGNsIDwtIHBlYWtWYXJfYWxjbFtvcmRlcihwZWFrVmFyX2FsY2wkUENBLnJhbmspLF0KcGVha1Zhcl9hbGNsJGN1bXVsYXRpdmUuVmFyaWFuY2UgPC0gY3Vtc3VtKHBlYWtWYXJfYWxjbCRybG9nLnZhcmlhbmNlKS9zdW0ocGVha1Zhcl9hbGNsJHJsb2cudmFyaWFuY2UpCnBkZigiY3VtdWxhdGl2ZV92YXJpYW5jZS5wZGYiKQpnZ3Bsb3QocGVha1Zhcl9hbGNsLCBhZXMoeD1QQ0EucmFuaywgeT1jdW11bGF0aXZlLlZhcmlhbmNlKSkgKyBnZW9tX2xpbmUoKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD01MDAwLCBsaW5ldHlwZT0iZG90dGVkIikKZGV2Lm9mZigpCmdncGxvdChwZWFrVmFyX2FsY2wsIGFlcyh4PVBDQS5yYW5rLCB5PWN1bXVsYXRpdmUuVmFyaWFuY2UpKSArIGdlb21fbGluZSgpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0PTUwMDAsIGxpbmV0eXBlPSJkb3R0ZWQiKQpgYGAKCgpGaWx0ZXIgcmxkIG9iamVjdHMgYnkgc2FtcGxlcy4uLiBzZXBhcmF0ZSAicG9zaXRpdmUiIHNldCBmcm9tICJuZWdhdGl2ZSIgc2V0IApgYGB7cn0KI1NlcGFyYXRlIHBvc2l0aXZlaW5nIGFuZCBuZWdhdGl2ZSBzZXQKZmlsdCA8LSB3aGljaCghY29sbmFtZXMocmxkX2FsY2wpICVpbiUgYygiTUFDMkEiLCAiRkVQRCIsICJETDQwIikpCnJsZF9wb3NpdGl2ZSA8LSBybGRfYWxjbFssZmlsdF0KCmZpbHQgPC0gd2hpY2goY29sbmFtZXMocmxkX2FsY2wpICVpbiUgYygiTUFDMkEiLCAiRkVQRCIsICJETDQwIikpCnJsZF9uZWdhdGl2ZSA8LSBybGRfYWxjbFssZmlsdF0KCmZpbHQgPC0gd2hpY2goIWNvbG5hbWVzKG5vcm1fYWxjbCkgJWluJSBjKCJNQUMyQSIsICJGRVBEIiwgIkRMNDAiKSkKbm9ybV9wb3NpdGl2ZSA8LSBub3JtX2FsY2xbLGZpbHRdCgpmaWx0IDwtIHdoaWNoKGNvbG5hbWVzKG5vcm1fYWxjbCkgJWluJSBjKCJNQUMyQSIsICJGRVBEIiwgIkRMNDAiKSkKbm9ybV9uZWdhdGl2ZSA8LSBub3JtX2FsY2xbLGZpbHRdCmBgYAoKRGV0ZXJtaW5lIHRoZSBudW1iZXIgb2YgUENBIGNvbnRyaWJ1dG9ycyBuZWNlc3NhcnkgdG8gY2xlYW5seSBzZXBhcmF0ZSBzdWJ0eXBlcwoKU2FtcGxlIGdyb3VwaW5nIGxvb2tzIHByZXR0eSBnb29kIGJldHdlZW4gNWsgYW5kIDEwayB0b3AgY29udHJpYnV0b3JzLiBXaWxsIGxvb2sgYXQgdGhlc2UgY3V0b2ZmcyBpbiBtb3JlIGRldGFpbC4KClJhbmsgZFJFRyBwZWFrcyBieSBQQ0EgY29udHJpYnV0aW9uIGFuZCBtZWFzdXJlIHZhcmlhbmNlIGFuZCBjdW11bGF0aXZlIHZhcmlhbmNlCmBgYHtyfQojRGVmaW5lIGFuZCByYW5rIHRvcCAxMGsgUENBIGNvbnRyaWJ1dG9ycwpydiA8LSByb3dWYXJzKGFzc2F5KHJsZF9wb3NpdGl2ZSkpIApzZWxlY3QgPC0gb3JkZXIocnYsIGRlY3JlYXNpbmc9VFJVRSkjW3NlcV9sZW4obWluKDEwMDAwLCBsZW5ndGgocnYpKSldCnBjIDwtIHByY29tcCh0KGFzc2F5KHJsZF9wb3NpdGl2ZSlbc2VsZWN0LF0pKQpsb2FkaW5ncyA8LSBhcy5kYXRhLmZyYW1lKHBjJHJvdGF0aW9uKQphbG9hZCA8LSBhYnMobG9hZGluZ3MpCnBjUmFuazIgPC0gZGF0YS5mcmFtZSgicGVha0lEIj1yb3duYW1lcyhsb2FkaW5ncyksICJQQ0EucmFuayI9c2VxLmludChucm93KGxvYWRpbmdzKSkpCiNzd2VlcChhbG9hZCwgMiwgY29sU3VtcyhhbG9hZCksICIvIikKIyMjY2xlYW4gdXAgdmFyaWFibGVzCnJtKHJ2KQpybShzZWxlY3QpCnJtKHBjKQpybShsb2FkaW5ncykKCiNHZW5lcmF0ZSBsaXN0IG9mIGRSRUcgcGVhayBhbm5vdGF0aW9ucwpwZWFrSW5mbzIgPC0gbWVyZ2UoZFJFR19hbm5vdDIsIHBjUmFuazIsIGJ5Lng9InBlYWtJRCIsIGJ5Lnk9InBlYWtJRCIpCnBlYWtWYXIyIDwtIGRhdGEuZnJhbWUoInBlYWtJRCI9cm93bmFtZXMoYXNzYXkocmxkX3Bvc2l0aXZlKSkpCnBlYWtWYXIyJHJsb2cudmFyaWFuY2UgPC0gcm93VmFycyhhcy5tYXRyaXgoYXNzYXkocmxkX3Bvc2l0aXZlKSkpCnBlYWtWYXIyIDwtIG1lcmdlKHBlYWtJbmZvMiwgcGVha1ZhcjIsIGJ5Lng9InBlYWtJRCIsIGJ5Lnk9InBlYWtJRCIpCmdncGxvdChwZWFrVmFyMiwgYWVzKHg9UENBLnJhbmssIHk9cmxvZy52YXJpYW5jZSkpICsgZ2VvbV9saW5lKCkgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9Yyg1MDAsMTAwMCwyMDAwLDUwMDAsMTAwMDApLCBsaW5ldHlwZT0iZG90dGVkIikKCiNhZGQgcGxvdCBvZiBmcmFjdGlvbiBvZiBleHBsYWluZWQgdmFyaWFuY2UuLiBydW5uaW5nIHN1bSAvIHRvdGFsIHZzIHJhbmsKcGVha1ZhcjIgPC0gcGVha1ZhcjJbb3JkZXIocGVha1ZhcjIkUENBLnJhbmspLF0KcGVha1ZhcjIkY3VtdWxhdGl2ZS5WYXJpYW5jZSA8LSBjdW1zdW0ocGVha1ZhcjIkcmxvZy52YXJpYW5jZSkvc3VtKHBlYWtWYXIyJHJsb2cudmFyaWFuY2UpCmdncGxvdChwZWFrVmFyMiwgYWVzKHg9UENBLnJhbmssIHk9Y3VtdWxhdGl2ZS5WYXJpYW5jZSkpICsgZ2VvbV9saW5lKCkgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9Yyg1MDAsMTAwMCwyMDAwLDUwMDAsMTAwMDApLCBsaW5ldHlwZT0iZG90dGVkIikKYGBgCgoxayBzZWVtcyByZWFzb25hYmxlCgpGaWx0ZXIgZm9yIHRvcCAxayBQQ0EgY29udHJpYnV0b3JzCmBgYHtyfQojZmlsdGVyIG5vcm1hbGl6ZWQgY291bnRzIGZvciB0b3AgNWsgUENBIGNvbnRyaWJ1dG9ycwp0b3AxayA8LSBmaWx0ZXIocGVha1ZhcjIsIFBDQS5yYW5rPD0xMDAwKSRwZWFrSUQKbm9ybV90b3AxayA8LSBub3JtX3Bvc2l0aXZlW3doaWNoKChyb3duYW1lcyhub3JtX3Bvc2l0aXZlKSAlaW4lIHRvcDFrKT09VFJVRSksXQpybGRfdG9wMWtfcG9zaXRpdmUgPC0gc3Vic2V0KGFzc2F5KHJsZF9wb3NpdGl2ZSksIHJvd25hbWVzKGFzc2F5KHJsZF9wb3NpdGl2ZSkpICVpbiUgdG9wMWspCnJsZF90b3Axa19uZWdhdGl2ZSA8LSBzdWJzZXQoYXNzYXkocmxkX25lZ2F0aXZlKSwgcm93bmFtZXMoYXNzYXkocmxkX25lZ2F0aXZlKSkgJWluJSB0b3AxaykKcmxkX3RvcDFrX2FsY2wgPC0gc3Vic2V0KGFzc2F5KHJsZF9hbGNsKSwgcm93bmFtZXMoYXNzYXkocmxkX2FsY2wpKSAlaW4lIHRvcDFrKQpgYGAKCkNhbGN1bGF0ZSBzYW1wbGUgZGlzdGFuY2VzIHdpdGggbmV3IHRvcDFrIHRyYWluaW5nIGFuZCBtYXRjaGVkIHRlc3Qgc2V0cywgdGhlbiBjYWxjdWxhdGUgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIGJyYW5jaHBvaW50cyBvZiB0aGUgdHdvCmBgYHtyfQpkX3Bvc2l0aXZlIDwtIHJsZF90b3Axa19wb3NpdGl2ZSAlPiUgZGlzdCAlPiUgaGNsdXN0ICU+JSBhcy5kZW5kcm9ncmFtCmRfbmVnYXRpdmUgPC0gcmxkX3RvcDFrX25lZ2F0aXZlICU+JSBkaXN0ICU+JSBoY2x1c3QgJT4lIGFzLmRlbmRyb2dyYW0KZF9hbGNsIDwtIHJsZF90b3Axa19hbGNsICU+JSBkaXN0ICU+JSBoY2x1c3QgJT4lIGFzLmRlbmRyb2dyYW0KCiNjb21wYXJlIGNsdXN0ZXJzIGV4Y2x1ZGluZyB1bmNsdXN0ZXJlZCB0byB1bmNsdXN0ZXJlZCBhbG9uZQpkX3Bvc2l0aXZlX25lZ2F0aXZlIDwtIGRlbmRsaXN0KHBvc2l0aXZlID0gZF9wb3NpdGl2ZSwgbmVnYXRpdmUgPSBkX25lZ2F0aXZlKQpkX3Bvc2l0aXZlX25lZ2F0aXZlICU+JSBjb3IuZGVuZGxpc3QKZF9wb3NpdGl2ZV9uZWdhdGl2ZSAlPiUgY29yLmRlbmRsaXN0KG1ldGhvZF9jb2VmID0gInNwZWFybWFuIikKQmtfcGxvdChkX3Bvc2l0aXZlLCBkX25lZ2F0aXZlLCBrID0gMjozMCwgeGxpbSA9IGMoMiwzMCksIG1haW4gPSAiQUxLK0FMQ0wgU2V0IHZzIEFMSy1BTENMIEJrIHBsb3QiKQoKI2NvbXBhcmUgY2x1c3RlcnMgZXhjbHVkaW5nIHVuY2x1c3RlcmVkIHRvIGNsdXN0ZXJzIHVzaW5nIGFsbCBzYW1wbGVzCmRfcG9zaXRpdmVfYWxjbCA8LSBkZW5kbGlzdChwb3NpdGl2ZSA9IGRfcG9zaXRpdmUsIGFsbCA9IGRfYWxjbCkKZF9wb3NpdGl2ZV9hbGNsICU+JSBjb3IuZGVuZGxpc3QKZF9wb3NpdGl2ZV9hbGNsICU+JSBjb3IuZGVuZGxpc3QobWV0aG9kX2NvZWYgPSAic3BlYXJtYW4iKQpCa19wbG90KGRfcG9zaXRpdmUsIGRfYWxjbCwgayA9IDI6MzAsIHhsaW0gPSBjKDIsMzApLCBtYWluID0gIkFMS19BTENMIFNldCB2cyBBbGwgQUxDTCBTYW1wbGVzIEJrIHBsb3QiKQoKI2NvbXBhcmUgY2x1c3RlcnMgYWxsIHNhbXBsZSBjbHVzdGVyaW5nIHRvIHVuY2x1c3RlcmVkIGFsb25lCmRfYWxjbF9uZWdhdGl2ZSA8LSBkZW5kbGlzdChhbGwgPSBkX2FsY2wsIG5lZ2F0aXZlID0gZF9uZWdhdGl2ZSkKZF9hbGNsX25lZ2F0aXZlICU+JSBjb3IuZGVuZGxpc3QKZF9hbGNsX25lZ2F0aXZlICU+JSBjb3IuZGVuZGxpc3QobWV0aG9kX2NvZWYgPSAic3BlYXJtYW4iKQpCa19wbG90KGRfYWxjbCwgZF9uZWdhdGl2ZSwgayA9IDI6MzAsIHhsaW0gPSBjKDIsMzApLCBtYWluID0gIkFsbCBBTENMIFNhbXBsZXMgdnMuIEFMSy1BTENMIEJrIHBsb3QiKQpgYGAKCjNrIGNsdXN0ZXJzPwoKTm93IHNvbWUgZnVuIHdpdGggVGFuZ2xlZ3JhbXMuLi4KYGBge3J9CnByZV90YW5nX2RfcG9zaXRpdmVfbmVnYXRpdmUgPC0gZF9wb3NpdGl2ZV9uZWdhdGl2ZSAlPiUgbGFkZGVyaXplICU+JSB1bnRhbmdsZSAlPiUgc2V0KCJicmFuY2hlc19rX2NvbG9yIiwgayA9IDMpCnBvc2l0aXZlX2JyYW5jaGVzX2NvbG9ycyA8LSBnZXRfbGVhdmVzX2JyYW5jaGVzX2NvbChwcmVfdGFuZ19kX3Bvc2l0aXZlX25lZ2F0aXZlJHBvc2l0aXZlKQpwcmVfdGFuZ19kX3Bvc2l0aXZlX25lZ2F0aXZlICU+JSB0YW5nbGVncmFtKGZhc3QgPSBULCBjb2xvcl9saW5lcyA9IHBvc2l0aXZlX2JyYW5jaGVzX2NvbG9ycykKCnByZV90YW5nX2RfcG9zaXRpdmVfYWxjbCA8LSBkX3Bvc2l0aXZlX2FsY2wgJT4lIGxhZGRlcml6ZSAlPiUgIHVudGFuZ2xlICU+JSBzZXQoImJyYW5jaGVzX2tfY29sb3IiLCBrID0gMykKcG9zaXRpdmVfYnJhbmNoZXNfY29sb3JzIDwtIGdldF9sZWF2ZXNfYnJhbmNoZXNfY29sKHByZV90YW5nX2RfcG9zaXRpdmVfYWxjbCRwb3NpdGl2ZSkKcHJlX3RhbmdfZF9wb3NpdGl2ZV9hbGNsICU+JSB0YW5nbGVncmFtKGZhc3QgPSBULCBjb2xvcl9saW5lcyA9IHBvc2l0aXZlX2JyYW5jaGVzX2NvbG9ycykKCnByZV90YW5nX2RfYWxjbF9uZWdhdGl2ZSA8LSBkX2FsY2xfbmVnYXRpdmUgJT4lIGxhZGRlcml6ZSAlPiUgIHVudGFuZ2xlICU+JSBzZXQoImJyYW5jaGVzX2tfY29sb3IiLCBrID0gMykKcG9zaXRpdmVfYnJhbmNoZXNfY29sb3JzIDwtIGdldF9sZWF2ZXNfYnJhbmNoZXNfY29sKHByZV90YW5nX2RfYWxjbF9uZWdhdGl2ZSRhbGwpCnByZV90YW5nX2RfYWxjbF9uZWdhdGl2ZSAlPiUgdGFuZ2xlZ3JhbShmYXN0ID0gVCwgY29sb3JfbGluZXMgPSBwb3NpdGl2ZV9icmFuY2hlc19jb2xvcnMpCmBgYAoKVGhlIHRocmVlIGRpZmZlcmVudCBzZXRzIGxlYWQgdG8gZHJhc3RpY2FsbHkgZGlmZmVyZW50IGNsdXN0ZXIgZGVzaWduYXRpb25zLiBXaWxsIGF0dGVtcHQgdG8gbG9vayBhdCBvdmVybGFwIGJldHdlZW4gY2x1c3RlciBzZXRzIHRob3VnaCBpdCBpcyBzb21ld2hhdCBhcmJpdHJhcnkgd2hpY2ggc2FtcGxlcyBlbmQgdXAgYmVpbmcgdGhlIGhvbGQtb3V0cy4KCk9ubHkgaGlnaGxpZ2h0IGdlbmVzIGNsdXN0ZXJlZCBpbiBjb21tb24gCmBgYHtyfQojZF9wb3NpdGl2ZV9uZWdhdGl2ZV9jb21tb24gPC0gZF9wb3NpdGl2ZV9uZWdhdGl2ZSAlPiUgcHJ1bmVfY29tbW9uX3N1YnRyZWVzLmRlbmRsaXN0CiNkX3Bvc2l0aXZlX25lZ2F0aXZlX2NvbW1vbiAlPiUgdW50YW5nbGUgJT4lICB0YW5nbGVncmFtKGNvbW1vbl9zdWJ0cmVlc19jb2xvcl9icmFuY2hlcyA9IFRSVUUpCgojZF9wb3NpdGl2ZV9hbGNsX2NvbW1vbiA8LSBkX3Bvc2l0aXZlX2FsY2wgJT4lIHBydW5lX2NvbW1vbl9zdWJ0cmVlcy5kZW5kbGlzdAojZF9wb3NpdGl2ZV9hbGNsX2NvbW1vbiAlPiUgdW50YW5nbGUgJT4lICB0YW5nbGVncmFtKGNvbW1vbl9zdWJ0cmVlc19jb2xvcl9icmFuY2hlcyA9IFRSVUUpCgojZF9hbGNsX25lZ2F0aXZlX2NvbW1vbiA8LSBkX2FsY2xfbmVnYXRpdmUgJT4lIHBydW5lX2NvbW1vbl9zdWJ0cmVlcy5kZW5kbGlzdAojZF9hbGNsX25lZ2F0aXZlX2NvbW1vbiAlPiUgdW50YW5nbGUgJT4lICB0YW5nbGVncmFtKGNvbW1vbl9zdWJ0cmVlc19jb2xvcl9icmFuY2hlcyA9IFRSVUUpCmBgYAoKUXVpdGUgYSBmZXcgc2hhcmVkIGxlYXZlcyBiZXR3ZWVuIHRoZSBwb3NpdGl2ZWluZyBzZXQgYW5kIGFsbC4gTGV0J3Mgc2VlIHdoYXQgdGhleSBhcmUuLi4gCmBgYHtyfQojZF9wb3NpdGl2ZV9uZWdhdGl2ZSAlPiUgbmxlYXZlcwojZF9wb3NpdGl2ZV9uZWdhdGl2ZV9jb21tb24gJT4lIG5sZWF2ZXMKCiNkX3Bvc2l0aXZlX2FsY2wgJT4lIG5sZWF2ZXMKI2RfcG9zaXRpdmVfYWxjbF9jb21tb24gJT4lIG5sZWF2ZXMKCiNkX2FsY2xfbmVnYXRpdmUgJT4lIG5sZWF2ZXMKI2RfYWxjbF9uZWdhdGl2ZV9jb21tb24gJT4lIG5sZWF2ZXMKYGBgCm4gbGVhdmVzIHByZXNlcnZlZCBiZXR3ZWVuIHRoZSBzdWJzZXQgYW5kIGFsbCBzYW1wbGVzLgoKTmV4dCBpcyB0byBmaWd1cmUgYSB3YXkgdG8gZGVmaW5lIGV4cHJlc3Npb24vYWN0aXZpdHkgZ3JvdXBzOgotIGstbWVhbnMgYXMgYmVmb3JlIC0Kb3IKLSBkeW5hbWljIGJyYW5jaCBjdXR0aW5nIC0KCnVzaW5nIHRvcCAxayBQQ0EgY29udHJpYnV0b3JzIChhcyBkZXRlcm1pbmVkIGEgcmVhc29uYWJsZSBjdXRvZmYgaW4gdGhlIHZhcmlhbmNlIHBsb3RzKQpgYGB7cn0KI2ZpbHRlciBub3JtYWxpemVkIGNvdW50cyBmb3IgdG9wIDFrIFBDQSBjb250cmlidXRvcnMKdG9wMWtfYWxjbCA8LSBmaWx0ZXIocGVha1Zhcl9hbGNsLCBQQ0EucmFuazw9MTAwMCkkcGVha0lECmJvdDFrX2FsY2wgPC0gZmlsdGVyKHBlYWtWYXJfYWxjbCwgUENBLnJhbms+MTE5ODg4KSRwZWFrSUQKbm9ybV90b3Axa19hbGNsIDwtIG5vcm1fYWxjbFt3aGljaCgocm93bmFtZXMobm9ybV9hbGNsKSAlaW4lIHRvcDFrX2FsY2wpPT1UUlVFKSxdCgpybGRfdG9wMWtfYWxjbCA8LSBzdWJzZXQoYXNzYXkocmxkX2FsY2wpLCByb3duYW1lcyhhc3NheShybGRfYWxjbCkpICVpbiUgdG9wMWtfYWxjbCkKY29sbmFtZXMobm9ybV90b3Axa19hbGNsKSA8LSBjb2xuYW1lcyhybGRfdG9wMWtfYWxjbCkKcmxkX2JvdDFrX2FsY2wgPC0gc3Vic2V0KGFzc2F5KHJsZF9hbGNsKSwgcm93bmFtZXMoYXNzYXkocmxkX2FsY2wpKSAlaW4lIGJvdDFrX2FsY2wpCihyb3cubmFtZXMocmxkX3RvcDFrX2FsY2wpICVpbiUgcm93Lm5hbWVzKHJsZF9ib3Qxa19hbGNsKSk9PUZBTFNFICNjaGVjayBkUkVHcyBwdWxsZWQgaW50byB0b3AgYW5kIGJvdHRvbSBkbyBub3QgbWF0Y2gtIHNob3VsZCBydW4gVCBmb3IgYWxsCgojc2NhbGUoKSBmdW5jdGlvbiBjZW50ZXJzIHZhbHVlcyArLy0gdGhlIG1lYW4gb2YgZWFjaCBjb2x1bW4gZm9yIG5vcm1hbGl6ZWQgY291bnRzIG9yIHJsb2cgbm9ybWFsaXplZCBjb3VudHMKc2NhbGVkYXRhX2NvdW50X3RvcCA8LSB0KHNjYWxlKHQobm9ybV90b3Axa19hbGNsKSkpICMgQ2VudGVycyBhbmQgc2NhbGVzIGRhdGEuCnNjYWxlZGF0YV9jb3VudF90b3AgPC0gc2NhbGVkYXRhX2NvdW50X3RvcFtjb21wbGV0ZS5jYXNlcyhzY2FsZWRhdGFfY291bnRfdG9wKSxdICMgUmVtb3ZlcyByb3dzIHdpdGggbnVsbHMKc2NhbGVkYXRhX3JsZF90b3AgPC0gdChzY2FsZSh0KHJsZF90b3Axa19hbGNsKSkpICMgQ2VudGVycyBhbmQgc2NhbGVzIGRhdGEuCnNjYWxlZGF0YV9ybGRfdG9wIDwtIHNjYWxlZGF0YV9ybGRfdG9wW2NvbXBsZXRlLmNhc2VzKHNjYWxlZGF0YV9ybGRfdG9wKSxdICMgUmVtb3ZlcyByb3dzIHdpdGggbnVsbHMKCnNjYWxlZGF0YV9ybGRfYWxjbCA8LSB0KHNjYWxlKHQoYXNzYXkocmxkX2FsY2wpKSkpCnNjYWxlZGF0YV9ybGRfYWxjbCA8LSBzY2FsZWRhdGFfcmxkX2FsY2xbY29tcGxldGUuY2FzZXMoc2NhbGVkYXRhX3JsZF9hbGNsKSxdCgpzY2FsZWRhdGFfcmxkX2JvdCA8LSB0KHNjYWxlKHQocmxkX2JvdDFrX2FsY2wpKSkKc2NhbGVkYXRhX3JsZF9ib3QgPC0gc2NhbGVkYXRhX3JsZF9ib3RbY29tcGxldGUuY2FzZXMoc2NhbGVkYXRhX3JsZF9ib3QpLF0gCgojYWxzbyB0cnkgd2l0aCByZWxhdGl2ZSBhY3Rpdml0eSBzY2FsaW5nCnNjYWxlZGF0YV9yZWxfdG9wIDwtIGRhdGEuZnJhbWUocm93Lm5hbWVzPXJvd25hbWVzKG5vcm1fdG9wMWtfYWxjbCkpCnNjYWxlZGF0YV9yZWxfdG9wJG1heC5kUkVHLmNvdW50cyA8LSBhcHBseShub3JtX3RvcDFrX2FsY2xbMTpuY29sKG5vcm1fdG9wMWtfYWxjbCldLCAxLCBtYXgsIG5hLnJtPVRSVUUpCmk9MQp3aGlsZSAoaTw9bmNvbChub3JtX3RvcDFrX2FsY2wpKXsKICBzY2FsZWRhdGFfcmVsX3RvcFtwYXN0ZTAobmFtZXMobm9ybV90b3Axa19hbGNsW2ldKSldIDwtIG5vcm1fdG9wMWtfYWxjbFssaV0vc2NhbGVkYXRhX3JlbF90b3AkbWF4LmRSRUcuY291bnRzCiAgaT1pKzEKfQoKI0dlbmVyYXRlIGNvbHVtbiBhbmQgcm93IGhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nIGZvciBlYWNoIG5vcm1hbGl6YXRpb24gbWV0aG9kIChhbGwgc3BlYXJtYW4gZm9yIG5vdykKaHJfY291bnQgPC0gaGNsdXN0KGFzLmRpc3QoMS1jb3IodChzY2FsZWRhdGFfY291bnRfdG9wKSwgbWV0aG9kPSJzcGVhcm1hbiIpKSwgbWV0aG9kPSJjb21wbGV0ZSIpICMgQ2x1c3RlciByb3dzIGJ5IFBlYXJzb24gY29ycmVsYXRpb24uCmhjX2NvdW50IDwtIGhjbHVzdChhcy5kaXN0KDEtY29yKHNjYWxlZGF0YV9jb3VudF90b3AsIG1ldGhvZD0ic3BlYXJtYW4iKSksIG1ldGhvZD0iY29tcGxldGUiKSAjIENsdXN0ZXJzIGNvbHVtbnMgYnkgU3BlYXJtYW4gY29ycmVsYXRpb24uCgpocl9ybGQgPC0gaGNsdXN0KGFzLmRpc3QoMS1jb3IodChzY2FsZWRhdGFfY291bnRfdG9wKSwgbWV0aG9kPSJzcGVhcm1hbiIpKSwgbWV0aG9kPSJjb21wbGV0ZSIpICMgQ2x1c3RlciByb3dzIGJ5IFBlYXJzb24gY29ycmVsYXRpb24uCmhjX3JsZCA8LSBoY2x1c3QoYXMuZGlzdCgxLWNvcihzY2FsZWRhdGFfcmxkX2FsY2wsIG1ldGhvZD0ic3BlYXJtYW4iKSksIG1ldGhvZD0iY29tcGxldGUiKSAjIENsdXN0ZXJzIGNvbHVtbnMgYnkgU3BlYXJtYW4gY29ycmVsYXRpb24uCgojaHJfYm90IDwtIGhjbHVzdChhcy5kaXN0KDEtY29yKHQoc2NhbGVkYXRhX3JsZF9ib3QpLCBtZXRob2Q9InNwZWFybWFuIikpLCBtZXRob2Q9ImNvbXBsZXRlIikKCmhyX3JlbCA8LSBoY2x1c3QoYXMuZGlzdCgxLWNvcih0KHNjYWxlZGF0YV9yZWxfdG9wWyxjKDI6MTApXSksIG1ldGhvZD0ic3BlYXJtYW4iKSksIG1ldGhvZD0iY29tcGxldGUiKSAjIENsdXN0ZXIgcm93cyBieSBQZWFyc29uIGNvcnJlbGF0aW9uLgpoY19yZWwgPC0gaGNsdXN0KGFzLmRpc3QoMS1jb3Ioc2NhbGVkYXRhX3JlbF90b3BbLGMoMjoxMCldLCBtZXRob2Q9InNwZWFybWFuIikpLCBtZXRob2Q9ImNvbXBsZXRlIikgIyBDbHVzdGVycyBjb2x1bW5zIGJ5IFNwZWFybWFuIGNvcnJlbGF0aW9uLgpgYGAKCkR5bmFtaWMgQnJhbmNoIEN1dHRpbmcgbmVnYXRpdmUgKDMtNSkKYGBge3J9CmxpYnJhcnkoZGVuZGV4dGVuZCkKCmNudF9jdXRrMyA8LSBjdXRyZWUoaHJfY291bnQsaz0zKSAjY3V0IGF0IHNwZWNpZmljIGhlaWdodCBoIG9yIGN1dCBmb3IgYSBzcGVjaWZpYyBudW1iZXIgb2YgY2x1c3RlcnMgawpjbnRfY3V0azQgPC0gY3V0cmVlKGhyX2NvdW50LGs9NCkKY250X2N1dGs1IDwtIGN1dHJlZShocl9jb3VudCxrPTUpCgpybGRfY3V0azIgPC0gY3V0cmVlKGhyX3JsZCxrPTIpCnJsZF9jdXRrMyA8LSBjdXRyZWUoaHJfcmxkLGs9MykKcmxkX2N1dGs0IDwtIGN1dHJlZShocl9ybGQsaz00KQpybGRfY3V0azUgPC0gY3V0cmVlKGhyX3JsZCxrPTUpCnJsZF9jdXRrNiA8LSBjdXRyZWUoaHJfcmxkLGs9NikKcmxkX2N1dGs3IDwtIGN1dHJlZShocl9ybGQsaz03KQpybGRfY3V0azggPC0gY3V0cmVlKGhyX3JsZCxrPTgpCnJsZF9jdXRrOSA8LSBjdXRyZWUoaHJfcmxkLGs9OSkKCnJsZF9ib3Qxa19hbGNsIDwtIGFzLmludGVnZXIocmVwKDAsIDUwMDApKQpuYW1lcyhybGRfYm90MWtfYWxjbCkgPC0gYm90MWtfYWxjbAoKcmVsX2N1dGszIDwtIGN1dHJlZShocl9yZWwsaz0zKQpyZWxfY3V0azQgPC0gY3V0cmVlKGhyX3JlbCxrPTQpCnJlbF9jdXRrNSA8LSBjdXRyZWUoaHJfcmVsLGs9NSkKCiNwbG90IHRoZSB0cmVlClRyZWVSX2NudCA9IGFzLmRlbmRyb2dyYW0oaHJfY291bnQsIG1ldGhvZD0iYXZlcmFnZSIpClRyZWVSX3JsZCA9IGFzLmRlbmRyb2dyYW0oaHJfcmxkLCBtZXRob2Q9ImF2ZXJhZ2UiKQpUcmVlUl9yZWwgPSBhcy5kZW5kcm9ncmFtKGhyX3JlbCwgbWV0aG9kPSJhdmVyYWdlIikKCiNkZWZpbmUgYW5ub3RhdGlvbiBiYXJzCnRoZV9iYXJzX2szIDwtIGNiaW5kKGNudF9jdXRrMywgcmxkX2N1dGszLCByZWxfY3V0azMpCnRoZV9iYXJzX2s0IDwtIGNiaW5kKGNudF9jdXRrNCwgcmxkX2N1dGs0LCByZWxfY3V0azQpCnRoZV9iYXJzX2s1IDwtIGNiaW5kKGNudF9jdXRrNSwgcmxkX2N1dGs1LCByZWxfY3V0azUpCgp0aGVfYmFyc19jbnQgPC0gY2JpbmQoY250X2N1dGszLCBjbnRfY3V0azQsIGNudF9jdXRrNSkKdGhlX2JhcnNfcmxkIDwtIGNiaW5kKHJsZF9jdXRrMywgcmxkX2N1dGs0LCBybGRfY3V0azUpCnRoZV9iYXJzX3JlbCA8LSBjYmluZChyZWxfY3V0azMsIHJlbF9jdXRrNCwgcmVsX2N1dGs1KQpgYGAKCkNvbXBhcmUgY2x1c3RlcnMKYGBge3J9CnBsb3QoVHJlZVJfcmxkLAogICAgIGxlYWZsYWIgPSAibm9uZSIsCiAgICAgbWFpbiA9ICJkUkVHIFBlYWsgQ2x1c3RlcmluZyAocmxvZykgaz0zIiwKICAgICB5bGFiID0gIkhlaWdodCIpCgojdGhpcyBtYWtlcyB0aGUgYmFyCmNvbG9yZWRfYmFycyh0aGVfYmFyc19rMywgVHJlZVJfcmxkLCBzb3J0X2J5X2xhYmVsc19vcmRlciA9IFQsIHlfc2hpZnQ9LTAuMSwgcm93TGFiZWxzID0gYygiQnkgQ291bnRzIiwiQnkgckxvZyIsIkJ5IFJlbGF0aXZlIEFjdGl2aXR5IiksY2V4LnJvd0xhYmVscz0wLjcpCgpwbG90KFRyZWVSX3JsZCwKICAgICBsZWFmbGFiID0gIm5vbmUiLAogICAgIG1haW4gPSAiZFJFRyBQZWFrIENsdXN0ZXJpbmcgKHJsb2cpIGs9NCIsCiAgICAgeWxhYiA9ICJIZWlnaHQiKQoKI3RoaXMgbWFrZXMgdGhlIGJhcgpjb2xvcmVkX2JhcnModGhlX2JhcnNfazQsIFRyZWVSX3JsZCwgc29ydF9ieV9sYWJlbHNfb3JkZXIgPSBULCB5X3NoaWZ0PS0wLjEsIHJvd0xhYmVscyA9IGMoIkJ5IENvdW50cyIsIkJ5IHJMb2ciLCJCeSBSZWxhdGl2ZSBBY3Rpdml0eSIpLGNleC5yb3dMYWJlbHM9MC43KQoKcGxvdChUcmVlUl9ybGQsCiAgICAgbGVhZmxhYiA9ICJub25lIiwKICAgICBtYWluID0gImRSRUcgUGVhayBDbHVzdGVyaW5nIChybG9nKSBrPTUiLAogICAgIHlsYWIgPSAiSGVpZ2h0IikKCiN0aGlzIG1ha2VzIHRoZSBiYXIKY29sb3JlZF9iYXJzKHRoZV9iYXJzX2s1LCBUcmVlUl9ybGQsIHNvcnRfYnlfbGFiZWxzX29yZGVyID0gVCwgeV9zaGlmdD0tMC4xLCByb3dMYWJlbHMgPSBjKCJCeSBDb3VudHMiLCJCeSByTG9nIiwiQnkgUmVsYXRpdmUgQWN0aXZpdHkiKSxjZXgucm93TGFiZWxzPTAuNykKYGBgCgpDbHVzdGVyaW5nIGlzIGV4YWN0bHkgdGhlIHNhbWUgcmVnYXJkbGVzcyBvZiBtZXRob2Qgbm93ISEgVGhpcyBpcyBncmVhdCEKCkNvbXBhcmUgY2x1c3RlcnMKYGBge3J9CnBsb3QoVHJlZVJfY250LAogICAgIGxlYWZsYWIgPSAibm9uZSIsCiAgICAgbWFpbiA9ICJkUkVHIFBlYWsgQ2x1c3RlcmluZyAoY291bnRzKSIsCiAgICAgeWxhYiA9ICJIZWlnaHQiKQoKI3RoaXMgbWFrZXMgdGhlIGJhcgpjb2xvcmVkX2JhcnModGhlX2JhcnNfY250LCBUcmVlUl9jbnQsIHNvcnRfYnlfbGFiZWxzX29yZGVyID0gVCwgeV9zaGlmdD0tMC4xLCByb3dMYWJlbHMgPSBjKCJrPTMiLCJrPTQiLCJrPTUiKSxjZXgucm93TGFiZWxzPTAuNykKCnBsb3QoVHJlZVJfcmxkLAogICAgIGxlYWZsYWIgPSAibm9uZSIsCiAgICAgbWFpbiA9ICJkUkVHIFBlYWsgQ2x1c3RlcmluZyAocmxvZykiLAogICAgIHlsYWIgPSAiSGVpZ2h0IikKCiN0aGlzIG1ha2VzIHRoZSBiYXIKY29sb3JlZF9iYXJzKHRoZV9iYXJzX3JsZCwgVHJlZVJfcmxkLCBzb3J0X2J5X2xhYmVsc19vcmRlciA9IFQsIHlfc2hpZnQ9LTAuMSwgcm93TGFiZWxzID0gYygiaz0zIiwiaz00Iiwiaz01IiksY2V4LnJvd0xhYmVscz0wLjcpCgpwbG90KFRyZWVSX3JlbCwKICAgICBsZWFmbGFiID0gIm5vbmUiLAogICAgIG1haW4gPSAiZFJFRyBQZWFrIENsdXN0ZXJpbmcgKHJlbGF0aXZlIGFjdGl2aXR5KSIsCiAgICAgeWxhYiA9ICJIZWlnaHQiKQoKI3RoaXMgbWFrZXMgdGhlIGJhcgpjb2xvcmVkX2JhcnModGhlX2JhcnNfcmVsLCBUcmVlUl9yZWwsIHNvcnRfYnlfbGFiZWxzX29yZGVyID0gVCwgeV9zaGlmdD0tMC4xLCByb3dMYWJlbHMgPSBjKCJrPTMiLCJrPTQiLCJrPTUiKSxjZXgucm93TGFiZWxzPTAuNykKYGBgCgpMZXQncyBzZWUgaG93IHdlbGwgdGhlc2UgY2x1c3RlcnMgc2VwYXJhdGUgZXhwcmVzc2lvbiBncm91cHMgYXNzb2NpYXRlZCB3aXRoIGRpZmZlcmVudCBjZWxsIGxpbmUgc3VidHlwZXMuLi4KYGBge3J9CmRhdGFfYWxjbCA8LSBjKCAiS0FSUEFTMjk5X0FMSytBTENMIiwgCiAgICAgICAgICAgICAgICAgIkw4Ml9BTEsrQUxDTCIsCiAgICAgICAgICAgICAgICAgIlNVUE0yX0FMSytBTENMIiwKICAgICAgICAgICAgICAgICAiTUFDMkFfQUxLLUFMQ0wiLAogICAgICAgICAgICAgICAgICJLSUpLX0FMSytBTENMIiwKICAgICAgICAgICAgICAgICAiU1I3ODZfQUxLK0FMQ0wiLAogICAgICAgICAgICAgICJGRVBEX0FMSy1BTENMIiwKICAgICAgICAgICAgICAgICAiREw0MF9BTEstQUxDTCIsIAogICAgICAgICAgICAgICJTVURITDFfQUxLK0FMQ0wiKQoKI0RlZmluaW5nIGJveCBwbG90IGZ1bmN0aW9ucwpjbHVzdC5jb3JlID0gZnVuY3Rpb24oaSwgZGF0LCBjbHVzdGVycykgewogIGluZCA9IChjbHVzdGVycyA9PSBpKQogIGNvbE1lYW5zKGRhdFtpbmQsXSkKfQoKYm94IDwtIGZ1bmN0aW9uKGNsdXN0ZXJzLCBzY2FsZWRhdGFfY291bnRfdG9wLCB0aXRsZSl7CmNvcmVzIDwtIHNhcHBseSh1bmlxdWUoY2x1c3RlcnMpLCBjbHVzdC5jb3JlLCBzY2FsZWRhdGFfY291bnRfdG9wLCBjbHVzdGVycykKCiNtYWtlIGEgZGF0YWZyYW1lIG9mIGNvcmVzIGJ5IHN1YnR5cGUKZCA8LSBkYXRhLmZyYW1lKGNiaW5kKGRhdGFfYWxjbCwgY29yZXMpKSAjc3ViVHlwZSBsaXN0IGZyb20gYmVnaW5uaW5nIQpjb2xuYW1lcyhkKSA8LWMoInNhbXBsZSIsIHBhc3RlMCgiY2x1c3RfIiwxOm5jb2woY29yZXMpKSkKCiNnZXQgdGhlIGRhdGEgZnJhbWUgaW50byBsb25nIGZvcm1hdCBmb3IgcGxvdHRpbmcKZG1vbHRlbiA8LSBtZWx0KGQsIGlkLnZhcnMgPSAic2FtcGxlIikKI29yZGVyIGJ5IHN1YnR5cGUKZG1vbHRlbiA8LSBkbW9sdGVuW29yZGVyKGRtb2x0ZW4kc2FtcGxlKSxdCmRtb2x0ZW4kc2FtcGxlIDwtIG9yZGVyZWQoZG1vbHRlbiRzYW1wbGUsIGxldmVscz11bmlxdWUoZG1vbHRlbiRzYW1wbGUpKQoKIyBtYWtlIHRoZSBwbG90CnAxIDwtIGdncGxvdChkbW9sdGVuLCBhZXMoeD1zYW1wbGUsIHk9YXMubnVtZXJpYyh2YWx1ZSksIGNvbD12YXJpYWJsZSkpICsgCiAgZ2VvbV9ib3hwbG90KCkgKwojICBnZW9tX3BvaW50KCkgKyAKIyAgZ2VvbV9saW5lKCkgKwojICBzY2FsZV94X2NvbnRpbnVvdXMobWlub3JfYnJlYWtzID0gTlVMTCwgYnJlYWtzPWMoYXMubnVtZXJpYyhsZXZlbHMoZmFjdG9yKGRtb2x0ZW4kc3VidHlwZSkpKSkpICsKIyAgc2NhbGVfeV9jb250aW51b3VzKCkgKwogIHhsYWIoIlNhbXBsZSIpICsKICB5bGFiKCJBY3Rpdml0eSIpICsKICBsYWJzKHRpdGxlPSBwYXN0ZTAoIkNsdXN0ZXIgQ29yZSBFeHByZXNzaW9uIGJ5IFNhbXBsZSAoIix0aXRsZSwiKSIpLGNvbG9yID0gIkNsdXN0ZXIiKQpyZXR1cm4ocDEpCn0KYGBgCgpNYWtlIGJveHBsb3RzCmBgYHtyfQpib3gocmxkX2N1dGsyLCBzY2FsZWRhdGFfcmxkX2FsY2wsICJjdXRrMiBybG9nIikKYm94KHJsZF9jdXRrMywgc2NhbGVkYXRhX3JsZF9hbGNsLCAiY3V0azMgcmxvZyIpCmJveChybGRfY3V0azQsIHNjYWxlZGF0YV9ybGRfYWxjbCwgImN1dGs0IHJsb2ciKQpib3gocmxkX2N1dGs1LCBzY2FsZWRhdGFfcmxkX2FsY2wsICJjdXRrNSBybG9nIikKYm94KHJsZF9jdXRrNiwgc2NhbGVkYXRhX3JsZF9hbGNsLCAiY3V0azYgcmxvZyIpCmJveChybGRfY3V0azcsIHNjYWxlZGF0YV9ybGRfYWxjbCwgImN1dGs3IHJsb2ciKQpib3gocmxkX2N1dGs4LCBzY2FsZWRhdGFfcmxkX2FsY2wsICJjdXRrOCBybG9nIikKYm94KHJsZF9jdXRrOSwgc2NhbGVkYXRhX3JsZF9hbGNsLCAiY3V0azkgcmxvZyIpCgpib3goYyhybGRfY3V0azMscmxkX2JvdDFrX2FsY2wpLCByYmluZChzY2FsZWRhdGFfcmxkX2FsY2wsc2NhbGVkYXRhX3JsZF9ib3QpLCAiY3V0azMgKyBzdGF0aWMgW1wiY2x1c3RfNVwiXSBybG9nIikKCmJveChyZWxfY3V0azMsIHNjYWxlZGF0YV9yZWxfdG9wWywyOjEwXSwgImN1dGszIHJlbCIpCmJveChyZWxfY3V0azQsIHNjYWxlZGF0YV9yZWxfdG9wWywyOjEwXSwgImN1dGs0IHJlbCIpCmJveChyZWxfY3V0azUsIHNjYWxlZGF0YV9yZWxfdG9wWywyOjEwXSwgImN1dGs1IHJlbCIpCgpib3gocmVsX2N1dGszLCBzY2FsZWRhdGFfY291bnRfdG9wLCAiY3V0azMgY291bnQiKQpib3gocmVsX2N1dGs0LCBzY2FsZWRhdGFfY291bnRfdG9wLCAiY3V0azQgY291bnQiKQpib3gocmVsX2N1dGs1LCBzY2FsZWRhdGFfY291bnRfdG9wLCAiY3V0azUgY291bnQiKQpgYGAKClByb3Blcmx5IGJ5IHN1YnR5cGUgaW5zdGVhZCBvZiBpbmRpdmlkdWFsIHNhbXBsZXMKYGBge3J9CmRhdGFfYWxjbCA8LSBjKCAgIkFMSytBTENMIiwgCiAgICAgICAgICAgICAgICAgIkFMSytBTENMIiwKICAgICAgICAgICAgICAgICAiQUxLK0FMQ0wiLAogICAgICAgICAgICAgICAgICJBTEstQUxDTCIsCiAgICAgICAgICAgICAgICAgIkFMSytBTENMIiwKICAgICAgICAgICAgICAgICAiQUxLK0FMQ0wiLAogICAgICAgICAgICAgICJBTEstQUxDTCIsCiAgICAgICAgICAgICAgICAgIkFMSy1BTENMIiwKICAgICAgICAgICAgICAiQUxLK0FMQ0wiKQoKI0RlZmluaW5nIGJveCBwbG90IGZ1bmN0aW9ucwpjbHVzdC5jb3JlID0gZnVuY3Rpb24oaSwgZGF0LCBjbHVzdGVycykgewogIGluZCA9IChjbHVzdGVycyA9PSBpKQogIGNvbE1lYW5zKGRhdFtpbmQsXSkKfQoKYm94IDwtIGZ1bmN0aW9uKGNsdXN0ZXJzLCBzY2FsZWRhdGFfY291bnRfdG9wLCB0aXRsZSl7CmNvcmVzIDwtIHNhcHBseSh1bmlxdWUoY2x1c3RlcnMpLCBjbHVzdC5jb3JlLCBzY2FsZWRhdGFfY291bnRfdG9wLCBjbHVzdGVycykKCiNtYWtlIGEgZGF0YWZyYW1lIG9mIGNvcmVzIGJ5IHN1YnR5cGUKZCA8LSBkYXRhLmZyYW1lKGNiaW5kKGRhdGFfYWxjbCwgY29yZXMpKSAjc3ViVHlwZSBsaXN0IGZyb20gYmVnaW5uaW5nIQpjb2xuYW1lcyhkKSA8LWMoInN1YnR5cGUiLCBwYXN0ZTAoImNsdXN0XyIsMTpuY29sKGNvcmVzKSkpCgojZ2V0IHRoZSBkYXRhIGZyYW1lIGludG8gbG9uZyBmb3JtYXQgZm9yIHBsb3R0aW5nCmRtb2x0ZW4gPC0gbWVsdChkLCBpZC52YXJzID0gInN1YnR5cGUiKQojb3JkZXIgYnkgc3VidHlwZQpkbW9sdGVuIDwtIGRtb2x0ZW5bb3JkZXIoZG1vbHRlbiRzdWJ0eXBlKSxdCmRtb2x0ZW4kc3VidHlwZSA8LSBvcmRlcmVkKGRtb2x0ZW4kc3VidHlwZSwgbGV2ZWxzPXVuaXF1ZShkbW9sdGVuJHN1YnR5cGUpKQoKIyBtYWtlIHRoZSBwbG90CnAxIDwtIGdncGxvdChkbW9sdGVuLCBhZXMoeD1zdWJ0eXBlLCB5PWFzLm51bWVyaWModmFsdWUpLCBjb2w9dmFyaWFibGUpKSArIAogIGdlb21fYm94cGxvdCgpICsKIyAgZ2VvbV9wb2ludCgpICsgCiMgIGdlb21fbGluZSgpICsKIyAgc2NhbGVfeF9jb250aW51b3VzKG1pbm9yX2JyZWFrcyA9IE5VTEwsIGJyZWFrcz1jKGFzLm51bWVyaWMobGV2ZWxzKGZhY3RvcihkbW9sdGVuJHN1YnR5cGUpKSkpKSArCiMgIHNjYWxlX3lfY29udGludW91cygpICsKICB4bGFiKCJTdWJ0eXBlIikgKwogIHlsYWIoIkFjdGl2aXR5IikgKwogIGxhYnModGl0bGU9IHBhc3RlMCgiQ2x1c3RlciBDb3JlIEV4cHJlc3Npb24gYnkgU3VidHlwZSAoIix0aXRsZSwiKSIpLGNvbG9yID0gIkNsdXN0ZXIiKQpyZXR1cm4ocDEpCn0KYGBgCgpNYWtlIGJveHBsb3RzCmBgYHtyfQpib3gocmxkX2N1dGsyLCBzY2FsZWRhdGFfcmxkX2FsY2wsICJjdXRrMiBybG9nIikKYm94KHJsZF9jdXRrMywgc2NhbGVkYXRhX3JsZF9hbGNsLCAiY3V0azMgcmxvZyIpCmJveChybGRfY3V0azQsIHNjYWxlZGF0YV9ybGRfYWxjbCwgImN1dGs0IHJsb2ciKQpib3gocmxkX2N1dGs1LCBzY2FsZWRhdGFfcmxkX2FsY2wsICJjdXRrNSBybG9nIikKYm94KHJsZF9jdXRrNiwgc2NhbGVkYXRhX3JsZF9hbGNsLCAiY3V0azYgcmxvZyIpCmJveChybGRfY3V0azcsIHNjYWxlZGF0YV9ybGRfYWxjbCwgImN1dGs3IHJsb2ciKQpib3gocmxkX2N1dGs4LCBzY2FsZWRhdGFfcmxkX2FsY2wsICJjdXRrOCBybG9nIikKYm94KHJsZF9jdXRrOSwgc2NhbGVkYXRhX3JsZF9hbGNsLCAiY3V0azkgcmxvZyIpCgpib3goYyhybGRfY3V0azMscmxkX2JvdDFrX2FsY2wpLCByYmluZChzY2FsZWRhdGFfcmxkX2FsY2wsc2NhbGVkYXRhX3JsZF9ib3QpLCAiY3V0azMgKyBzdGF0aWMgW1wiY2x1c3RfNVwiXSBybG9nIikKCmJveChyZWxfY3V0azMsIHNjYWxlZGF0YV9yZWxfdG9wWywyOjEwXSwgImN1dGszIHJlbCIpCmJveChyZWxfY3V0azQsIHNjYWxlZGF0YV9yZWxfdG9wWywyOjEwXSwgImN1dGs0IHJlbCIpCmJveChyZWxfY3V0azUsIHNjYWxlZGF0YV9yZWxfdG9wWywyOjEwXSwgImN1dGs1IHJlbCIpCgpib3gocmVsX2N1dGszLCBzY2FsZWRhdGFfY291bnRfdG9wLCAiY3V0azMgY291bnQiKQpib3gocmVsX2N1dGs0LCBzY2FsZWRhdGFfY291bnRfdG9wLCAiY3V0azQgY291bnQiKQpib3gocmVsX2N1dGs1LCBzY2FsZWRhdGFfY291bnRfdG9wLCAiY3V0azUgY291bnQiKQpgYGAKCkNhbid0IG1ha2UgbXVjaCBzZW5zZSBvZiB1bmlxdWUgY2x1c3RlcmluZyBiZXR3ZWVuIHRoZSBzYW1wbGVzIG9yIHRoZWlyIHN1YnR5cGVzLiBDb25zaWRlcmluZyBzdWJzZXR0aW5nIG91dCBvcmlnaW5hbCBkYXRhIGludG8gY2x1c3RlcmluZyBhbmQgbm9uY2x1c3RlcmluZyBzYW1wbGVzIGFuZCBtb3Zpbmcgb24gd2l0aCBpbmRpdmlkdWFsIGNsdXN0ZXIgdHJlYXRtZW50cyBmb3IgZWFjaCBmcm9tIHRoZXJlLgoKV2FudCB0byBtYWtlIGEgaGVhdG1hcCB3aXRoIHRoZSBhYm92ZSBjbHVzdGVycyBhbmQgYSBjbHVzdGVyLXRyYWl0IGNvcnJlbGF0aW9uIGhlYXRtYXAuLi4KClRyYWl0IGNvcnJlbGF0aW9uIChlZGl0IGZvciB0aGlzIGRhdGFzZXQpCmBgYHtyfQp0cmFpdHMgPC0gZGF0YS5mcmFtZShyb3cubmFtZXM9Y29sbmFtZXMoc2NhbGVkYXRhX3JsZF9hbGNsKSkgCiNoZXJlIEknbSBhZGRpbmcgdmVjdG9ycyBvZiBzdWJ0eXBlIHRyYWl0cyB0byB0aGUgZGF0YWZyYW1lCnRyYWl0cyQnQUxLK0FMQ0wnIDwtICAgICAgIGMoMSwxLDEsMCwxLDEsMCwwLDEpICNjb3JyZWN0ZWQKdHJhaXRzJCdBTEstQUxDTCcgPC0gYygwLDAsMCwxLDAsMCwxLDEsMCkgI2NvcnJlY3RlZAoKI0V4dHJhY3QgdGhlIGdlbmUvc2FtcGxlIG51bWJlcnMKblBlYWtzID0gbnJvdyhzY2FsZWRhdGFfcmxkX2FsY2wpIApuU2FtcGxlcyA9IG5jb2woc2NhbGVkYXRhX3JsZF9hbGNsKQoKI3AgdmFsdWUgY2FsY3VsYXRpb24gZnJvbSBXR0NOQQpjb3JQdmFsdWVTdHVkZW50ID0gZnVuY3Rpb24oY29yLCBuU2FtcGxlcykgewogIFQ9c3FydChuU2FtcGxlcy0yKSAqIGNvci9zcXJ0KDEtY29yXjIpCiAgMipwdChhYnMoVCksblNhbXBsZXMtMiwgbG93ZXIudGFpbCA9IEZBTFNFKQp9CmBgYAoKTWFrZSBjb3JyZWxhdGlvbiBoZWF0bWFwcwpgYGB7cn0KblNhbXBsZXM9OQoKI0ZpbmFsaXplIGNsdXN0ZXJpbmcgYW5kIGJyYW5jaCBjdXRzCmNsdXN0ZXJzIDwtIHJsZF9jdXRrMgoKY29yZXMgPC0gc2FwcGx5KHVuaXF1ZShjbHVzdGVycyksIGNsdXN0LmNvcmUsIHNjYWxlZGF0YV9ybGRfYWxjbCwgY2x1c3RlcnMpCiNjb3JyZWxhdGUgdGhlIGNvcmVzIHRvIHRyYWl0czoKbW9kdWxlVHJhaXRDb3IgPSBjb3IoY29yZXMsIHRyYWl0cywgdXNlPSAicCIpCm1vZHVsZVRyYWl0UHZhbHVlID0gY29yUHZhbHVlU3R1ZGVudChtb2R1bGVUcmFpdENvciwgblNhbXBsZXMpCiNnZW5lcmF0ZSBhIHRleHQgbWF0cml4IG9mIHRoZSBjb3JyZWxhdGlvbiBhbmQgcHZhbHVlCnRleHRNYXRyaXg9IHBhc3RlKHNpZ25pZihtb2R1bGVUcmFpdENvciwgMiksICJcbigiLAogICAgICAgICAgICAgICAgICBzaWduaWYobW9kdWxlVHJhaXRQdmFsdWUsIDEpLCAiKSIsIHNlcD0gIiIpCmRpbSh0ZXh0TWF0cml4KT0gZGltKG1vZHVsZVRyYWl0Q29yKQojcGxvdCBhIGhlYXRtYXAgb2YgdGhlIGNsdXN0ZXJzIGJ5IHRyYWl0IG92ZXJsYXlpbmcgdGhlIGNvcnIvcHZhbHVlCiNwYXIob21hPWMoMSwwLDEsMSkpCmhlYXRtYXAuMihtb2R1bGVUcmFpdENvciwKICAgICAgICAgIGRlbmRyb2dyYW0gPSAibm9uZSIsCiAgICAgICAgICBDb2x2ID1GQUxTRSwKICAgICAgICAgIHNjYWxlID0gYygibm9uZSIpLAogICAgICAgICAgY29sPSJoZWF0LmNvbG9ycyIsCiAgICAgICAgICBuYS5ybT1UUlVFLAogICAgICAgICAgY2VsbG5vdGUgPSB0ZXh0TWF0cml4LAogICAgICAgICAgbm90ZWNvbD0iZ3JleTMwIiwKICAgICAgICAgIG5vdGVjZXg9MSwKICAgICAgICAgIHRyYWNlPWMoIm5vbmUiKSwKICAgICAgICAgIGNleFJvdyA9IDAuOCwKICAgICAgICAgIGNleENvbCA9IDAuOCwKICAgICAgICAgIG1haW4gPSAiQ2x1c3Rlci1UcmFpdCBDb3JyZWxhdGlvbiAoaz0yKSIsCiAgICAgICAgICB4bGFiID0gIlRyYWl0cyIsCiAgICAgICAgICB5bGFiID0gIkNsdXN0ZXJzIikKCmNsdXN0ZXJzIDwtIHJsZF9jdXRrMwoKY29yZXMgPC0gc2FwcGx5KHVuaXF1ZShjbHVzdGVycyksIGNsdXN0LmNvcmUsIHNjYWxlZGF0YV9ybGRfYWxjbCwgY2x1c3RlcnMpCiNjb3JyZWxhdGUgdGhlIGNvcmVzIHRvIHRyYWl0czoKbW9kdWxlVHJhaXRDb3IgPSBjb3IoY29yZXMsIHRyYWl0cywgdXNlPSAicCIpCm1vZHVsZVRyYWl0UHZhbHVlID0gY29yUHZhbHVlU3R1ZGVudChtb2R1bGVUcmFpdENvciwgblNhbXBsZXMpCiNnZW5lcmF0ZSBhIHRleHQgbWF0cml4IG9mIHRoZSBjb3JyZWxhdGlvbiBhbmQgcHZhbHVlCnRleHRNYXRyaXg9IHBhc3RlKHNpZ25pZihtb2R1bGVUcmFpdENvciwgMiksICJcbigiLAogICAgICAgICAgICAgICAgICBzaWduaWYobW9kdWxlVHJhaXRQdmFsdWUsIDEpLCAiKSIsIHNlcD0gIiIpCmRpbSh0ZXh0TWF0cml4KT0gZGltKG1vZHVsZVRyYWl0Q29yKQojcGxvdCBhIGhlYXRtYXAgb2YgdGhlIGNsdXN0ZXJzIGJ5IHRyYWl0IG92ZXJsYXlpbmcgdGhlIGNvcnIvcHZhbHVlCiNwYXIob21hPWMoMSwwLDEsMSkpCmhlYXRtYXAuMihtb2R1bGVUcmFpdENvciwKICAgICAgICAgIGRlbmRyb2dyYW0gPSAibm9uZSIsCiAgICAgICAgICBDb2x2ID1GQUxTRSwKICAgICAgICAgIHNjYWxlID0gYygibm9uZSIpLAogICAgICAgICAgY29sPSJoZWF0LmNvbG9ycyIsCiAgICAgICAgICBuYS5ybT1UUlVFLAogICAgICAgICAgY2VsbG5vdGUgPSB0ZXh0TWF0cml4LAogICAgICAgICAgbm90ZWNvbD0iZ3JleTMwIiwKICAgICAgICAgIG5vdGVjZXg9MSwKICAgICAgICAgIHRyYWNlPWMoIm5vbmUiKSwKICAgICAgICAgIGNleFJvdyA9IDAuOCwKICAgICAgICAgIGNleENvbCA9IDAuOCwKICAgICAgICAgIG1haW4gPSAiQ2x1c3Rlci1UcmFpdCBDb3JyZWxhdGlvbiAoaz0zKSIsCiAgICAgICAgICB4bGFiID0gIlRyYWl0cyIsCiAgICAgICAgICB5bGFiID0gIkNsdXN0ZXJzIikKCmNsdXN0ZXJzIDwtIHJsZF9jdXRrNAoKY29yZXMgPC0gc2FwcGx5KHVuaXF1ZShjbHVzdGVycyksIGNsdXN0LmNvcmUsIHNjYWxlZGF0YV9ybGRfYWxjbCwgY2x1c3RlcnMpCiNjb3JyZWxhdGUgdGhlIGNvcmVzIHRvIHRyYWl0czoKbW9kdWxlVHJhaXRDb3IgPSBjb3IoY29yZXMsIHRyYWl0cywgdXNlPSAicCIpCm1vZHVsZVRyYWl0UHZhbHVlID0gY29yUHZhbHVlU3R1ZGVudChtb2R1bGVUcmFpdENvciwgblNhbXBsZXMpCiNnZW5lcmF0ZSBhIHRleHQgbWF0cml4IG9mIHRoZSBjb3JyZWxhdGlvbiBhbmQgcHZhbHVlCnRleHRNYXRyaXg9IHBhc3RlKHNpZ25pZihtb2R1bGVUcmFpdENvciwgMiksICJcbigiLAogICAgICAgICAgICAgICAgICBzaWduaWYobW9kdWxlVHJhaXRQdmFsdWUsIDEpLCAiKSIsIHNlcD0gIiIpCmRpbSh0ZXh0TWF0cml4KT0gZGltKG1vZHVsZVRyYWl0Q29yKQojcGxvdCBhIGhlYXRtYXAgb2YgdGhlIGNsdXN0ZXJzIGJ5IHRyYWl0IG92ZXJsYXlpbmcgdGhlIGNvcnIvcHZhbHVlCiNwYXIob21hPWMoMSwwLDEsMSkpCmhlYXRtYXAuMihtb2R1bGVUcmFpdENvciwKICAgICAgICAgIGRlbmRyb2dyYW0gPSAibm9uZSIsCiAgICAgICAgICBDb2x2ID1GQUxTRSwKICAgICAgICAgIHNjYWxlID0gYygibm9uZSIpLAogICAgICAgICAgY29sPSJoZWF0LmNvbG9ycyIsCiAgICAgICAgICBuYS5ybT1UUlVFLAogICAgICAgICAgY2VsbG5vdGUgPSB0ZXh0TWF0cml4LAogICAgICAgICAgbm90ZWNvbD0iZ3JleTMwIiwKICAgICAgICAgIG5vdGVjZXg9MSwKICAgICAgICAgIHRyYWNlPWMoIm5vbmUiKSwKICAgICAgICAgIGNleFJvdyA9IDAuOCwKICAgICAgICAgIGNleENvbCA9IDAuOCwKICAgICAgICAgIG1haW4gPSAiQ2x1c3Rlci1UcmFpdCBDb3JyZWxhdGlvbiAoaz00KSIsCiAgICAgICAgICB4bGFiID0gIlRyYWl0cyIsCiAgICAgICAgICB5bGFiID0gIkNsdXN0ZXJzIikKCmNsdXN0ZXJzIDwtIHJsZF9jdXRrNQoKY29yZXMgPC0gc2FwcGx5KHVuaXF1ZShjbHVzdGVycyksIGNsdXN0LmNvcmUsIHNjYWxlZGF0YV9ybGRfYWxjbCwgY2x1c3RlcnMpCiNjb3JyZWxhdGUgdGhlIGNvcmVzIHRvIHRyYWl0czoKbW9kdWxlVHJhaXRDb3IgPSBjb3IoY29yZXMsIHRyYWl0cywgdXNlPSAicCIpCm1vZHVsZVRyYWl0UHZhbHVlID0gY29yUHZhbHVlU3R1ZGVudChtb2R1bGVUcmFpdENvciwgblNhbXBsZXMpCiNnZW5lcmF0ZSBhIHRleHQgbWF0cml4IG9mIHRoZSBjb3JyZWxhdGlvbiBhbmQgcHZhbHVlCnRleHRNYXRyaXg9IHBhc3RlKHNpZ25pZihtb2R1bGVUcmFpdENvciwgMiksICJcbigiLAogICAgICAgICAgICAgICAgICBzaWduaWYobW9kdWxlVHJhaXRQdmFsdWUsIDEpLCAiKSIsIHNlcD0gIiIpCmRpbSh0ZXh0TWF0cml4KT0gZGltKG1vZHVsZVRyYWl0Q29yKQojcGxvdCBhIGhlYXRtYXAgb2YgdGhlIGNsdXN0ZXJzIGJ5IHRyYWl0IG92ZXJsYXlpbmcgdGhlIGNvcnIvcHZhbHVlCiNwYXIob21hPWMoMSwwLDEsMSkpCmhlYXRtYXAuMihtb2R1bGVUcmFpdENvciwKICAgICAgICAgIGRlbmRyb2dyYW0gPSAibm9uZSIsCiAgICAgICAgICBDb2x2ID1GQUxTRSwKICAgICAgICAgIHNjYWxlID0gYygibm9uZSIpLAogICAgICAgICAgY29sPSJoZWF0LmNvbG9ycyIsCiAgICAgICAgICBuYS5ybT1UUlVFLAogICAgICAgICAgY2VsbG5vdGUgPSB0ZXh0TWF0cml4LAogICAgICAgICAgbm90ZWNvbD0iZ3JleTMwIiwKICAgICAgICAgIG5vdGVjZXg9MSwKICAgICAgICAgIHRyYWNlPWMoIm5vbmUiKSwKICAgICAgICAgIGNleFJvdyA9IDAuOCwKICAgICAgICAgIGNleENvbCA9IDAuOCwKICAgICAgICAgIG1haW4gPSAiQ2x1c3Rlci1UcmFpdCBDb3JyZWxhdGlvbiAoaz01KSIsCiAgICAgICAgICB4bGFiID0gIlRyYWl0cyIsCiAgICAgICAgICB5bGFiID0gIkNsdXN0ZXJzIikKCmNsdXN0ZXJzIDwtIHJsZF9jdXRrNgoKY29yZXMgPC0gc2FwcGx5KHVuaXF1ZShjbHVzdGVycyksIGNsdXN0LmNvcmUsIHNjYWxlZGF0YV9ybGRfYWxjbCwgY2x1c3RlcnMpCiNjb3JyZWxhdGUgdGhlIGNvcmVzIHRvIHRyYWl0czoKbW9kdWxlVHJhaXRDb3IgPSBjb3IoY29yZXMsIHRyYWl0cywgdXNlPSAicCIpCm1vZHVsZVRyYWl0UHZhbHVlID0gY29yUHZhbHVlU3R1ZGVudChtb2R1bGVUcmFpdENvciwgblNhbXBsZXMpCiNnZW5lcmF0ZSBhIHRleHQgbWF0cml4IG9mIHRoZSBjb3JyZWxhdGlvbiBhbmQgcHZhbHVlCnRleHRNYXRyaXg9IHBhc3RlKHNpZ25pZihtb2R1bGVUcmFpdENvciwgMiksICJcbigiLAogICAgICAgICAgICAgICAgICBzaWduaWYobW9kdWxlVHJhaXRQdmFsdWUsIDEpLCAiKSIsIHNlcD0gIiIpCmRpbSh0ZXh0TWF0cml4KT0gZGltKG1vZHVsZVRyYWl0Q29yKQojcGxvdCBhIGhlYXRtYXAgb2YgdGhlIGNsdXN0ZXJzIGJ5IHRyYWl0IG92ZXJsYXlpbmcgdGhlIGNvcnIvcHZhbHVlCiNwYXIob21hPWMoMSwwLDEsMSkpCmhlYXRtYXAuMihtb2R1bGVUcmFpdENvciwKICAgICAgICAgIGRlbmRyb2dyYW0gPSAibm9uZSIsCiAgICAgICAgICBDb2x2ID1GQUxTRSwKICAgICAgICAgIHNjYWxlID0gYygibm9uZSIpLAogICAgICAgICAgY29sPSJoZWF0LmNvbG9ycyIsCiAgICAgICAgICBuYS5ybT1UUlVFLAogICAgICAgICAgY2VsbG5vdGUgPSB0ZXh0TWF0cml4LAogICAgICAgICAgbm90ZWNvbD0iZ3JleTMwIiwKICAgICAgICAgIG5vdGVjZXg9MSwKICAgICAgICAgIHRyYWNlPWMoIm5vbmUiKSwKICAgICAgICAgIGNleFJvdyA9IDAuOCwKICAgICAgICAgIGNleENvbCA9IDAuOCwKICAgICAgICAgIG1haW4gPSAiQ2x1c3Rlci1UcmFpdCBDb3JyZWxhdGlvbiAoaz02KSIsCiAgICAgICAgICB4bGFiID0gIlRyYWl0cyIsCiAgICAgICAgICB5bGFiID0gIkNsdXN0ZXJzIikKCmNsdXN0ZXJzIDwtIHJsZF9jdXRrNwoKY29yZXMgPC0gc2FwcGx5KHVuaXF1ZShjbHVzdGVycyksIGNsdXN0LmNvcmUsIHNjYWxlZGF0YV9ybGRfYWxjbCwgY2x1c3RlcnMpCiNjb3JyZWxhdGUgdGhlIGNvcmVzIHRvIHRyYWl0czoKbW9kdWxlVHJhaXRDb3IgPSBjb3IoY29yZXMsIHRyYWl0cywgdXNlPSAicCIpCm1vZHVsZVRyYWl0UHZhbHVlID0gY29yUHZhbHVlU3R1ZGVudChtb2R1bGVUcmFpdENvciwgblNhbXBsZXMpCiNnZW5lcmF0ZSBhIHRleHQgbWF0cml4IG9mIHRoZSBjb3JyZWxhdGlvbiBhbmQgcHZhbHVlCnRleHRNYXRyaXg9IHBhc3RlKHNpZ25pZihtb2R1bGVUcmFpdENvciwgMiksICJcbigiLAogICAgICAgICAgICAgICAgICBzaWduaWYobW9kdWxlVHJhaXRQdmFsdWUsIDEpLCAiKSIsIHNlcD0gIiIpCmRpbSh0ZXh0TWF0cml4KT0gZGltKG1vZHVsZVRyYWl0Q29yKQojcGxvdCBhIGhlYXRtYXAgb2YgdGhlIGNsdXN0ZXJzIGJ5IHRyYWl0IG92ZXJsYXlpbmcgdGhlIGNvcnIvcHZhbHVlCiNwYXIob21hPWMoMSwwLDEsMSkpCmhlYXRtYXAuMihtb2R1bGVUcmFpdENvciwKICAgICAgICAgIGRlbmRyb2dyYW0gPSAibm9uZSIsCiAgICAgICAgICBDb2x2ID1GQUxTRSwKICAgICAgICAgIHNjYWxlID0gYygibm9uZSIpLAogICAgICAgICAgY29sPSJoZWF0LmNvbG9ycyIsCiAgICAgICAgICBuYS5ybT1UUlVFLAogICAgICAgICAgY2VsbG5vdGUgPSB0ZXh0TWF0cml4LAogICAgICAgICAgbm90ZWNvbD0iZ3JleTMwIiwKICAgICAgICAgIG5vdGVjZXg9MSwKICAgICAgICAgIHRyYWNlPWMoIm5vbmUiKSwKICAgICAgICAgIGNleFJvdyA9IDAuOCwKICAgICAgICAgIGNleENvbCA9IDAuOCwKICAgICAgICAgIG1haW4gPSAiQ2x1c3Rlci1UcmFpdCBDb3JyZWxhdGlvbiAoaz03KSIsCiAgICAgICAgICB4bGFiID0gIlRyYWl0cyIsCiAgICAgICAgICB5bGFiID0gIkNsdXN0ZXJzIikKCmNsdXN0ZXJzIDwtIHJsZF9jdXRrOAoKY29yZXMgPC0gc2FwcGx5KHVuaXF1ZShjbHVzdGVycyksIGNsdXN0LmNvcmUsIHNjYWxlZGF0YV9ybGRfYWxjbCwgY2x1c3RlcnMpCiNjb3JyZWxhdGUgdGhlIGNvcmVzIHRvIHRyYWl0czoKbW9kdWxlVHJhaXRDb3IgPSBjb3IoY29yZXMsIHRyYWl0cywgdXNlPSAicCIpCm1vZHVsZVRyYWl0UHZhbHVlID0gY29yUHZhbHVlU3R1ZGVudChtb2R1bGVUcmFpdENvciwgblNhbXBsZXMpCiNnZW5lcmF0ZSBhIHRleHQgbWF0cml4IG9mIHRoZSBjb3JyZWxhdGlvbiBhbmQgcHZhbHVlCnRleHRNYXRyaXg9IHBhc3RlKHNpZ25pZihtb2R1bGVUcmFpdENvciwgMiksICJcbigiLAogICAgICAgICAgICAgICAgICBzaWduaWYobW9kdWxlVHJhaXRQdmFsdWUsIDEpLCAiKSIsIHNlcD0gIiIpCmRpbSh0ZXh0TWF0cml4KT0gZGltKG1vZHVsZVRyYWl0Q29yKQojcGxvdCBhIGhlYXRtYXAgb2YgdGhlIGNsdXN0ZXJzIGJ5IHRyYWl0IG92ZXJsYXlpbmcgdGhlIGNvcnIvcHZhbHVlCiNwYXIob21hPWMoMSwwLDEsMSkpCmhlYXRtYXAuMihtb2R1bGVUcmFpdENvciwKICAgICAgICAgIGRlbmRyb2dyYW0gPSAibm9uZSIsCiAgICAgICAgICBDb2x2ID1GQUxTRSwKICAgICAgICAgIHNjYWxlID0gYygibm9uZSIpLAogICAgICAgICAgY29sPSJoZWF0LmNvbG9ycyIsCiAgICAgICAgICBuYS5ybT1UUlVFLAogICAgICAgICAgY2VsbG5vdGUgPSB0ZXh0TWF0cml4LAogICAgICAgICAgbm90ZWNvbD0iZ3JleTMwIiwKICAgICAgICAgIG5vdGVjZXg9MSwKICAgICAgICAgIHRyYWNlPWMoIm5vbmUiKSwKICAgICAgICAgIGNleFJvdyA9IDAuOCwKICAgICAgICAgIGNleENvbCA9IDAuOCwKICAgICAgICAgIG1haW4gPSAiQ2x1c3Rlci1UcmFpdCBDb3JyZWxhdGlvbiAoaz04KSIsCiAgICAgICAgICB4bGFiID0gIlRyYWl0cyIsCiAgICAgICAgICB5bGFiID0gIkNsdXN0ZXJzIikKCmNsdXN0ZXJzIDwtIHJsZF9jdXRrOQoKY29yZXMgPC0gc2FwcGx5KHVuaXF1ZShjbHVzdGVycyksIGNsdXN0LmNvcmUsIHNjYWxlZGF0YV9ybGRfYWxjbCwgY2x1c3RlcnMpCiNjb3JyZWxhdGUgdGhlIGNvcmVzIHRvIHRyYWl0czoKbW9kdWxlVHJhaXRDb3IgPSBjb3IoY29yZXMsIHRyYWl0cywgdXNlPSAicCIpCm1vZHVsZVRyYWl0UHZhbHVlID0gY29yUHZhbHVlU3R1ZGVudChtb2R1bGVUcmFpdENvciwgblNhbXBsZXMpCiNnZW5lcmF0ZSBhIHRleHQgbWF0cml4IG9mIHRoZSBjb3JyZWxhdGlvbiBhbmQgcHZhbHVlCnRleHRNYXRyaXg9IHBhc3RlKHNpZ25pZihtb2R1bGVUcmFpdENvciwgMiksICJcbigiLAogICAgICAgICAgICAgICAgICBzaWduaWYobW9kdWxlVHJhaXRQdmFsdWUsIDEpLCAiKSIsIHNlcD0gIiIpCmRpbSh0ZXh0TWF0cml4KT0gZGltKG1vZHVsZVRyYWl0Q29yKQojcGxvdCBhIGhlYXRtYXAgb2YgdGhlIGNsdXN0ZXJzIGJ5IHRyYWl0IG92ZXJsYXlpbmcgdGhlIGNvcnIvcHZhbHVlCiNwYXIob21hPWMoMSwwLDEsMSkpCmhlYXRtYXAuMihtb2R1bGVUcmFpdENvciwKICAgICAgICAgIGRlbmRyb2dyYW0gPSAibm9uZSIsCiAgICAgICAgICBDb2x2ID1GQUxTRSwKICAgICAgICAgIHNjYWxlID0gYygibm9uZSIpLAogICAgICAgICAgY29sPSJoZWF0LmNvbG9ycyIsCiAgICAgICAgICBuYS5ybT1UUlVFLAogICAgICAgICAgY2VsbG5vdGUgPSB0ZXh0TWF0cml4LAogICAgICAgICAgbm90ZWNvbD0iZ3JleTMwIiwKICAgICAgICAgIG5vdGVjZXg9MSwKICAgICAgICAgIHRyYWNlPWMoIm5vbmUiKSwKICAgICAgICAgIGNleFJvdyA9IDAuOCwKICAgICAgICAgIGNleENvbCA9IDAuOCwKICAgICAgICAgIG1haW4gPSAiQ2x1c3Rlci1UcmFpdCBDb3JyZWxhdGlvbiAoaz05KSIsCiAgICAgICAgICB4bGFiID0gIlRyYWl0cyIsCiAgICAgICAgICB5bGFiID0gIkNsdXN0ZXJzIikKCiNjbHVzdGVycyA8LSBjKHJsZF9jdXRrNCxybGRfYm9wNWtfYWxjbCkKCiNjb3JlcyA8LSBzYXBwbHkodW5pcXVlKGNsdXN0ZXJzKSwgY2x1c3QuY29yZSwgcmJpbmQoc2NhbGVkYXRhX3JsZF90b3AsIHNjYWxlZGF0YV9ib3QpLCBjbHVzdGVycykKI2NvcnJlbGF0ZSB0aGUgY29yZXMgdG8gdHJhaXRzOgojbW9kdWxlVHJhaXRDb3IgPSBjb3IoY29yZXMsIHRyYWl0cywgdXNlPSAicCIpCiNtb2R1bGVUcmFpdFB2YWx1ZSA9IGNvclB2YWx1ZVN0dWRlbnQobW9kdWxlVHJhaXRDb3IsIG5TYW1wbGVzKQojZ2VuZXJhdGUgYSB0ZXh0IG1hdHJpeCBvZiB0aGUgY29ycmVsYXRpb24gYW5kIHB2YWx1ZQojdGV4dE1hdHJpeD0gcGFzdGUoc2lnbmlmKG1vZHVsZVRyYWl0Q29yLCAyKSwgIlxuKCIsCiAgICAgICAgICAgICAgICAgICNzaWduaWYobW9kdWxlVHJhaXRQdmFsdWUsIDEpLCAiKSIsIHNlcD0gIiIpCiNkaW0odGV4dE1hdHJpeCk9IGRpbShtb2R1bGVUcmFpdENvcikKI3Bsb3QgYSBoZWF0bWFwIG9mIHRoZSBjbHVzdGVycyBieSB0cmFpdCBvdmVybGF5aW5nIHRoZSBjb3JyL3B2YWx1ZQojcGFyKG9tYT1jKDEsMCwxLDEpKQojaGVhdG1hcC4yKG1vZHVsZVRyYWl0Q29yLAogICAgICAgICAgI2RlbmRyb2dyYW0gPSAibm9uZSIsCiAgICAgICAgICAjQ29sdiA9RkFMU0UsCiAgICAgICAgICAjc2NhbGUgPSBjKCJub25lIiksCiAgICAgICAgICAjY29sPSJoZWF0LmNvbG9ycyIsCiAgICAgICAgICAjbmEucm09VFJVRSwKICAgICAgICAgICNjZWxsbm90ZSA9IHRleHRNYXRyaXgsCiAgICAgICAgICAjbm90ZWNvbD0iZ3JleTMwIiwKICAgICAgICAgICNub3RlY2V4PTEsCiAgICAgICAgICAjdHJhY2U9Yygibm9uZSIpLAogICAgICAgICAgI2NleFJvdyA9IDAuOCwKICAgICAgICAgICNjZXhDb2wgPSAwLjgsCiAgICAgICAgICAjbWFpbiA9ICJDbHVzdGVyLVRyYWl0IENvcnJlbGF0aW9uIChrPTQgKyBTdGF0aWMgWzVrXSkiLAogICAgICAgICAgI3hsYWIgPSAiVHJhaXRzIiwKICAgICAgICAgICN5bGFiID0gIkNsdXN0ZXJzIikKYGBgCgpNYWtlIGFubm90YXRlZCBzY2FsZWQgcmxvZyBoZWF0bWFwCmBgYHtyfQpybGRfZGYgPC0gYXMuZGF0YS5mcmFtZShzY2FsZWRhdGFfcmxkX3RvcCkKcmxkX2RmJGszIDwtIGFzLmRhdGEuZnJhbWUocmxkX2N1dGszKSRybGRfY3V0azMKcmxkX2RmJGs0IDwtIGFzLmRhdGEuZnJhbWUocmxkX2N1dGs0KSRybGRfY3V0azQKCmNvbG9ycyA8LSBjKCcjZTYxOTRCJywnIzNjYjQ0YicsJyNmZmUxMTknLCcjNDM2M2Q4JywnI2Y1ODIzMScsJyM5MTFlYjQnLCcjNDJkNGY0JywnI2YwMzJlNicsJyNiZmVmNDUnLCcjZmFiZWQ0JywnIzQ2OTk5MCcsJyNkY2JlZmYnLCcjOUE2MzI0JywnI2ZmZmFjOCcsJyM4MDAwMDAnLCcjYWFmZmMzJywnIzgwODAwMCcsJyNmZmQ4YjEnLCcjMDAwMDc1JywnI2E5YTlhOScsJyNmZmZmZmYnLCcjMDAwMDAwJykKI0hpZ2ggY29udHJhc3QgY29sb3JzIGZvciBmaWd1cmVzIHdhcyBwdWxsZWQgZnJvbSBodHRwczovL3Nhc2hhbWFwcy5uZXQvZG9jcy9yZXNvdXJjZXMvMjAtY29sb3JzLwoKcGhlYXRtYXAocmxkX3RvcDFrX2FsY2wsCiAgICAgICAgICNybGRfZGZbb3JkZXIocmxkX2RmWywxMl0pLF1bLDE6MTFdLCAKICAgICAgICAgI2dhcHNfcm93ID0gYyg4NzksMjI5OCw0MjEzKSwgCiAgICAgICAgIGNsdXN0ZXJfY29scz1ULCAKICAgICAgICAgY2x1c3Rlcl9yb3dzPWhyX3JsZCwKICAgICAgICAgI2NsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9ICJldWNsaWRlYW4iLAogICAgICAgICAjY2x1c3RlcmluZ19tZXRob2QgPSAiY29tcGxldGUiLAogICAgICAgICBzY2FsZT0icm93IiwKICAgICAgICAgY3V0cmVlX3Jvd3M9NCwKICAgICAgICAgY3V0cmVlX2NvbHM9MywgCiAgICAgICAgIGJvcmRlcl9jb2xvcj1OQSwgCiAgICAgICAgIHNob3dfcm93bmFtZXM9RiwgCiAgICAgICAgIG1haW49IlRvcCAxayBkUkVHIFBlYWsgUENBIENvbnRyaWJ1dG9ycyBIaWVyYXJjaGljYWwiLAogICAgICAgICBicmVha3M9c2VxKC0yLDIsYnk9MC4wMSksCiAgICAgICAgIGNvbG9yPW9jZWFuLmJhbGFuY2UoNDAxKSwKICAgICAgICAgI2NvbG9yPXNjaWNvKDQwMSwgcGFsZXR0ZSA9ICdiZXJsaW4nKSwKICAgICAgICAgI2NvbG9yPWNvbG9yUmFtcFBhbGV0dGUoYygiYmx1ZSIsICJ3aGl0ZSIsICJyZWQiKSkoNDEpLAogICAgICAgICBhbm5vdGF0aW9uX3Jvdz1ybGRfZGZbMTA6MTFdLCAKICAgICAgICAgYW5ub3RhdGlvbl9jb2w9ZGF0YS5mcmFtZShyb3cubmFtZXM9Y29sbmFtZXMocmxkX2RmWywxOjldKSwgU3VidHlwZSA9IGRhdGFfYWxjbCksIAogICAgICAgICBhbm5vdGF0aW9uX2NvbG9ycz1saXN0KGszPWMoImJsdWUiLCAiZ3JlZW4iLCAicmVkIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgazQ9YygicHVycGxlIiwgImJsdWUiLCAiZ3JlZW4iLCAiZ29sZGVucm9kMSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdWJ0eXBlPWMoIkFMSytBTENMIj0gJ2Nob2NvbGF0ZTQnLCAiQUxLLUFMQ0wiPSAnY2FkZXRibHVlJykpCiAgICAgICAgICkKYGBgCgoKCg==