Functions
Data
genesets <- msigdb_download("Homo sapiens",category="H") %>% append( msigdb_download("Homo sapiens",category="C2",subcategory = "CP:KEGG"))
a = msigdb_download("Homo sapiens",category="C2",subcategory = "CP")
H1975Oct23 = read.table(
file = "./Data/osiRoxa_bulk/Oct23/gene_fpkm.xls",
sep = "\t",
header = TRUE
)
rownames(H1975Oct23) = make.unique(H1975Oct23[,"gene_name",drop=T])
H1975Oct23 = H1975Oct23[,2:16]
names (H1975Oct23) = gsub(x = names(H1975Oct23),pattern = "_C",replacement = "_ctrl")%>% gsub(pattern = "p_OR",replacement = "_comboPersistors") %>% gsub(pattern = "p_O",replacement = "_osiPersistors") %>% gsub(pattern = "_R",replacement = "_roxa")%>% gsub(,pattern = "_O",replacement = "_osi")
cell.labels = names(H1975Oct23)
condition = str_extract(cell.labels, "osiPersistors|comboPersistors|osi|ctrl|roxa")
metadata = data.frame(condition = condition, row.names = colnames(H1975Oct23))
library(DESeq2)
dds <- DESeqDataSetFromMatrix(countData = round(H1975Oct23),
colData = metadata,
design = ~condition)
PCA
nrow(dds)
dds1 <- dds[ rowSums(counts(dds)) >= 3, ]
nrow(dds1)
vst = vst(dds1, blind=FALSE)
library("ggfortify")
PCAdata <- prcomp(t(assay(vst)))
autoplot(PCAdata, data = metadata,colour = "condition",label = FALSE, main="PCA") # Show dots

DEG
FC
cpVSop <- results(dds,contrast = c("condition","comboPersistors","osiPersistors")) %>% as.data.frame()
roxaVSctrl <- results(dds,contrast = c("condition","roxa","ctrl")) %>% as.data.frame()
diff_genes = data.frame(row.names = rownames(cpVSop), cpVSop_FC = cpVSop$log2FoldChange,roxaVSctrl_FC = roxaVSctrl$log2FoldChange, cpVSop_padj = cpVSop$padj)
cpVSop = cpVSop[order(cpVSop$log2FoldChange, cpVSop$padj,decreasing = T),] #order by FC, ties bt padj
ranked_vec = cpVSop[,"log2FoldChange"]%>% setNames(rownames(cpVSop)) %>% na.omit() # make named vector
hyp_obj <- hypeR_fgsea(ranked_vec, genesets, up_only = F)
Warning in preparePathwaysAndStats(pathways, stats, minSize, maxSize,
gseaParam, : There are ties in the preranked stats (10.89% of the list).
The order of those tied genes will be arbitrary, which may produce
unexpected results.
plt = hyp_dots(hyp_obj,merge = F)
plt1 = plt$up+ aes(size=nes)+ggtitle("up in comboPersistor")
plt2 = plt$dn+ aes(size=abs(nes))+ggtitle("up in osiPersistors")
print_tab(plt1+plt2,title = "cpVSop")
cpVSop

roxaVSctrl = roxaVSctrl[order(roxaVSctrl$log2FoldChange, roxaVSctrl$padj,decreasing = T),] #order by FC, ties bt padj
ranked_vec = roxaVSctrl[,"log2FoldChange"]%>% setNames(rownames(roxaVSctrl)) %>% na.omit() # make named vector
hyp_obj <- hypeR_fgsea(ranked_vec, genesets, up_only = F)
Warning in preparePathwaysAndStats(pathways, stats, minSize, maxSize,
gseaParam, : There are ties in the preranked stats (19.69% of the list).
The order of those tied genes will be arbitrary, which may produce
unexpected results.
plt = hyp_dots(hyp_obj,merge = F)
plt1 = plt$up+ aes(size=nes)+ggtitle("up in roxa")
plt2 = plt$dn+ aes(size=abs(nes))+ggtitle("up in ctrl")
print_tab(plt1+plt2,title = "cpVSop")
cpVSop

NA
DEG
shrinked FC
dds$condition = relevel(dds$condition, ref = "osiPersistors")
dds <- nbinomWaldTest(dds)
cpVSop <- lfcShrink(dds,coef = "condition_comboPersistors_vs_osiPersistors") %>% as.data.frame()
dds$condition = relevel(dds$condition, ref = "ctrl")
dds <- nbinomWaldTest(dds)
roxaVSctrl <- lfcShrink(dds,coef = "condition_roxa_vs_ctrl") %>% as.data.frame()
diff_genes = data.frame(row.names = rownames(cpVSop), cpVSop_FC = cpVSop$log2FoldChange,roxaVSctrl_FC = roxaVSctrl$log2FoldChange, cpVSop_padj = cpVSop$padj)
ranked_vec = diff_genes[, 1] %>% setNames(rownames(diff_genes)) %>% sort(decreasing = TRUE)
hyp_obj <- hypeR_fgsea(ranked_vec, genesets, up_only = F)
Warning in preparePathwaysAndStats(pathways, stats, minSize, maxSize,
gseaParam, : There are ties in the preranked stats (16.5% of the list).
The order of those tied genes will be arbitrary, which may produce
unexpected results.
plt = hyp_dots(hyp_obj,merge = F)
plt1 = plt$up+ aes(size=nes)+ggtitle("up in comboPersistor") + theme( axis.text.y = element_text(size=10))
plt2 = plt$dn+ aes(size=abs(nes))+ggtitle("up in osiPersistors") + theme(axis.text.y = element_text(size=10))
print_tab(plt1+plt2,title = "cpVSop")
cpVSop

ranked_vec = diff_genes[, 2] %>% setNames(rownames(diff_genes)) %>% sort(decreasing = TRUE)
hyp_obj <- hypeR_fgsea(ranked_vec, genesets, up_only = F)
Warning in preparePathwaysAndStats(pathways, stats, minSize, maxSize,
gseaParam, : There are ties in the preranked stats (16.41% of the list).
The order of those tied genes will be arbitrary, which may produce
unexpected results.
plt = hyp_dots(hyp_obj,merge = F)
plt1 = plt$up+ aes(size=nes)+ggtitle("up in roxa")
plt2 = plt$dn+ aes(size=abs(nes))+ggtitle("up in ctrl")
print_tab(plt1+plt2,title = "cpVSop")
cpVSop

NA
DEG in
comboVSosi but not in roxaVSctrl
cpVSop <- results(dds,contrast = c("condition","comboPersistors","osiPersistors")) %>% as.data.frame()
roxaVSctrl <- results(dds,contrast = c("condition","roxa","ctrl")) %>% as.data.frame()
diff_genes = data.frame(row.names = rownames(cpVSop), cpVSop_FC = 2**cpVSop$log2FoldChange,roxaVSctrl_FC = 2**roxaVSctrl$log2FoldChange, cpVSop_padj = cpVSop$padj)
up_genes_df = diff_genes %>% filter(cpVSop_FC > 2 & roxaVSctrl_FC<1.2 & cpVSop_padj<0.05)
down_genes_df = diff_genes %>% filter(cpVSop_FC < 0.5 & roxaVSctrl_FC>0.8 & cpVSop_padj<0.05)
up_genes = diff_genes %>% filter(cpVSop_FC > 2 & roxaVSctrl_FC<1.2 & cpVSop_padj<0.05) %>% rownames()
down_genes = diff_genes %>% filter(cpVSop_FC < 0.5 & roxaVSctrl_FC>0.8 & cpVSop_padj<0.1)%>% rownames()
print_tab(up_genes_df,title = "up")
up
print_tab(down_genes_df,title = "down")
down
NA
H1975_up_genes = up_genes
H1975_down_genes = down_genes
hyp_obj <- hypeR(up_genes, genesets, test = "hypergeometric", fdr=1, plotting=F,background = rownames(H1975Oct23))
plt1 = hyp_dots(hyp_obj,title = "up in comboVSosi but not in roxaVSctrl")
hyp_obj <- hypeR(down_genes, genesets, test = "hypergeometric", fdr=1, plotting=F,background = rownames(H1975Oct23))
plt2 = hyp_dots(hyp_obj,title = "down in comboVSosi but not in roxaVSctrl")
plt1 + plt2

print_tab(data.frame(up_genes[up_genes %in% genesets$HALLMARK_E2F_TARGETS]),title = "up genes in E2F")
print_tab(data.frame(up_genes[up_genes %in% genesets$HALLMARK_HYPOXIA]),title = "up genes in Hypoxia")
LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19kZXB0aDogMQotLS0KCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+Ci5tYWluLWNvbnRhaW5lciB7CiAgbWF4LXdpZHRoOiA4NSUgIWltcG9ydGFudDsKICBtYXJnaW46IGF1dG87Cn0KPC9zdHlsZT4KCiMgRnVuY3Rpb25zCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpgYGAKCiMgRGF0YQoKYGBge3J9CmdlbmVzZXRzIDwtIG1zaWdkYl9kb3dubG9hZCgiSG9tbyBzYXBpZW5zIixjYXRlZ29yeT0iSCIpICU+JSBhcHBlbmQoIG1zaWdkYl9kb3dubG9hZCgiSG9tbyBzYXBpZW5zIixjYXRlZ29yeT0iQzIiLHN1YmNhdGVnb3J5ID0gIkNQOktFR0ciKSkKYSA9IG1zaWdkYl9kb3dubG9hZCgiSG9tbyBzYXBpZW5zIixjYXRlZ29yeT0iQzIiLHN1YmNhdGVnb3J5ID0gIkNQIikKSDE5NzVPY3QyMyA9IHJlYWQudGFibGUoCiAgZmlsZSA9ICIuL0RhdGEvb3NpUm94YV9idWxrL09jdDIzL2dlbmVfZnBrbS54bHMiLAogIHNlcCA9ICJcdCIsCiAgaGVhZGVyID0gVFJVRQopCnJvd25hbWVzKEgxOTc1T2N0MjMpID0gbWFrZS51bmlxdWUoSDE5NzVPY3QyM1ssImdlbmVfbmFtZSIsZHJvcD1UXSkKSDE5NzVPY3QyMyA9IEgxOTc1T2N0MjNbLDI6MTZdCm5hbWVzIChIMTk3NU9jdDIzKSA9IGdzdWIoeCA9IG5hbWVzKEgxOTc1T2N0MjMpLHBhdHRlcm4gPSAiX0MiLHJlcGxhY2VtZW50ID0gIl9jdHJsIiklPiUgZ3N1YihwYXR0ZXJuID0gInBfT1IiLHJlcGxhY2VtZW50ID0gIl9jb21ib1BlcnNpc3RvcnMiKSAlPiUgZ3N1YihwYXR0ZXJuID0gInBfTyIscmVwbGFjZW1lbnQgPSAiX29zaVBlcnNpc3RvcnMiKSAlPiUgZ3N1YihwYXR0ZXJuID0gIl9SIixyZXBsYWNlbWVudCA9ICJfcm94YSIpJT4lIGdzdWIoLHBhdHRlcm4gPSAiX08iLHJlcGxhY2VtZW50ID0gIl9vc2kiKQoKYGBgCgpgYGB7cn0KY2VsbC5sYWJlbHMgPSBuYW1lcyhIMTk3NU9jdDIzKQpjb25kaXRpb24gPSBzdHJfZXh0cmFjdChjZWxsLmxhYmVscywgIm9zaVBlcnNpc3RvcnN8Y29tYm9QZXJzaXN0b3JzfG9zaXxjdHJsfHJveGEiKQptZXRhZGF0YSA9IGRhdGEuZnJhbWUoY29uZGl0aW9uID0gY29uZGl0aW9uLCByb3cubmFtZXMgPSBjb2xuYW1lcyhIMTk3NU9jdDIzKSkKYGBgCgpgYGB7cn0KbGlicmFyeShERVNlcTIpCmRkcyA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IHJvdW5kKEgxOTc1T2N0MjMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xEYXRhID0gbWV0YWRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2lnbiA9IH5jb25kaXRpb24pCmBgYAoKCiMgUENBCmBgYHtyfQpucm93KGRkcykKZGRzMSA8LSBkZHNbIHJvd1N1bXMoY291bnRzKGRkcykpID49IDMsIF0KbnJvdyhkZHMxKQpgYGAKCmBgYHtyfQp2c3QgPSB2c3QoZGRzMSwgYmxpbmQ9RkFMU0UpCmBgYAoKYGBge3J9CmxpYnJhcnkoImdnZm9ydGlmeSIpClBDQWRhdGEgPC0gcHJjb21wKHQoYXNzYXkodnN0KSkpCmF1dG9wbG90KFBDQWRhdGEsIGRhdGEgPSBtZXRhZGF0YSxjb2xvdXIgPSAiY29uZGl0aW9uIixsYWJlbCA9IEZBTFNFLCBtYWluPSJQQ0EiKSAjIFNob3cgZG90cwoKYGBgCiMgREVTZXEKYGBge3J9CmRkcyA8LSBERVNlcShkZHMpCmBgYAoKIyBERUcgRkMgey50YWJzZXR9CmBgYHtyfQpjcFZTb3AgPC0gcmVzdWx0cyhkZHMsY29udHJhc3QgPSBjKCJjb25kaXRpb24iLCJjb21ib1BlcnNpc3RvcnMiLCJvc2lQZXJzaXN0b3JzIikpICAlPiUgYXMuZGF0YS5mcmFtZSgpCnJveGFWU2N0cmwgPC0gcmVzdWx0cyhkZHMsY29udHJhc3QgPSBjKCJjb25kaXRpb24iLCJyb3hhIiwiY3RybCIpKSAgJT4lIGFzLmRhdGEuZnJhbWUoKQpkaWZmX2dlbmVzID0gZGF0YS5mcmFtZShyb3cubmFtZXMgPSByb3duYW1lcyhjcFZTb3ApLCBjcFZTb3BfRkMgPSBjcFZTb3AkbG9nMkZvbGRDaGFuZ2Uscm94YVZTY3RybF9GQyA9IHJveGFWU2N0cmwkbG9nMkZvbGRDaGFuZ2UsICBjcFZTb3BfcGFkaiA9IGNwVlNvcCRwYWRqKQpgYGAKCgpgYGB7ciBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMywgcmVzdWx0cz0nYXNpcyd9CmNwVlNvcCA9IGNwVlNvcFtvcmRlcihjcFZTb3AkbG9nMkZvbGRDaGFuZ2UsIGNwVlNvcCRwYWRqLGRlY3JlYXNpbmcgPSBUKSxdICNvcmRlciBieSBGQywgdGllcyBidCBwYWRqCnJhbmtlZF92ZWMgPSBjcFZTb3BbLCJsb2cyRm9sZENoYW5nZSJdJT4lIHNldE5hbWVzKHJvd25hbWVzKGNwVlNvcCkpICU+JSBuYS5vbWl0KCkgIyBtYWtlIG5hbWVkIHZlY3RvcgoKaHlwX29iaiA8LSBoeXBlUl9mZ3NlYShyYW5rZWRfdmVjLCBnZW5lc2V0cywgdXBfb25seSA9IEYpCnBsdCA9IGh5cF9kb3RzKGh5cF9vYmosbWVyZ2UgPSBGKQpwbHQxID0gcGx0JHVwKyBhZXMoc2l6ZT1uZXMpK2dndGl0bGUoInVwIGluIGNvbWJvUGVyc2lzdG9yIikKcGx0MiA9IHBsdCRkbisgYWVzKHNpemU9YWJzKG5lcykpK2dndGl0bGUoInVwIGluIG9zaVBlcnNpc3RvcnMiKQpwcmludF90YWIocGx0MStwbHQyLHRpdGxlID0gImNwVlNvcCIpCgoKcm94YVZTY3RybCA9IHJveGFWU2N0cmxbb3JkZXIocm94YVZTY3RybCRsb2cyRm9sZENoYW5nZSwgcm94YVZTY3RybCRwYWRqLGRlY3JlYXNpbmcgPSBUKSxdICNvcmRlciBieSBGQywgdGllcyBidCBwYWRqCnJhbmtlZF92ZWMgPSByb3hhVlNjdHJsWywibG9nMkZvbGRDaGFuZ2UiXSU+JSBzZXROYW1lcyhyb3duYW1lcyhyb3hhVlNjdHJsKSkgJT4lIG5hLm9taXQoKSAgIyBtYWtlIG5hbWVkIHZlY3RvcgoKaHlwX29iaiA8LSBoeXBlUl9mZ3NlYShyYW5rZWRfdmVjLCBnZW5lc2V0cywgdXBfb25seSA9IEYpCnBsdCA9IGh5cF9kb3RzKGh5cF9vYmosbWVyZ2UgPSBGKQpwbHQxID0gcGx0JHVwKyBhZXMoc2l6ZT1uZXMpK2dndGl0bGUoInVwIGluIHJveGEiKQpwbHQyID0gcGx0JGRuKyBhZXMoc2l6ZT1hYnMobmVzKSkrZ2d0aXRsZSgidXAgaW4gY3RybCIpCnByaW50X3RhYihwbHQxK3BsdDIsdGl0bGUgPSAiY3BWU29wIikKYGBgCgojIERFRyBzaHJpbmtlZCBGQyB7LnRhYnNldH0KYGBge3J9CmRkcyRjb25kaXRpb24gPSByZWxldmVsKGRkcyRjb25kaXRpb24sIHJlZiA9ICJvc2lQZXJzaXN0b3JzIikKZGRzIDwtIG5iaW5vbVdhbGRUZXN0KGRkcykKY3BWU29wIDwtIGxmY1NocmluayhkZHMsY29lZiA9ICJjb25kaXRpb25fY29tYm9QZXJzaXN0b3JzX3ZzX29zaVBlcnNpc3RvcnMiKSAgJT4lIGFzLmRhdGEuZnJhbWUoKQoKZGRzJGNvbmRpdGlvbiA9IHJlbGV2ZWwoZGRzJGNvbmRpdGlvbiwgcmVmID0gImN0cmwiKQpkZHMgPC0gbmJpbm9tV2FsZFRlc3QoZGRzKQpyb3hhVlNjdHJsIDwtIGxmY1NocmluayhkZHMsY29lZiAgPSAiY29uZGl0aW9uX3JveGFfdnNfY3RybCIpICAlPiUgYXMuZGF0YS5mcmFtZSgpCgoKZGlmZl9nZW5lcyA9IGRhdGEuZnJhbWUocm93Lm5hbWVzID0gcm93bmFtZXMoY3BWU29wKSwgY3BWU29wX0ZDID0gY3BWU29wJGxvZzJGb2xkQ2hhbmdlLHJveGFWU2N0cmxfRkMgPSByb3hhVlNjdHJsJGxvZzJGb2xkQ2hhbmdlLCAgY3BWU29wX3BhZGogPSBjcFZTb3AkcGFkaikKCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEzLHJlc3VsdHM9J2FzaXMnfQpyYW5rZWRfdmVjID0gZGlmZl9nZW5lc1ssIDFdICU+JSBzZXROYW1lcyhyb3duYW1lcyhkaWZmX2dlbmVzKSkgJT4lIHNvcnQoZGVjcmVhc2luZyA9IFRSVUUpCmh5cF9vYmogPC0gaHlwZVJfZmdzZWEocmFua2VkX3ZlYywgZ2VuZXNldHMsIHVwX29ubHkgPSBGKQpwbHQgPSBoeXBfZG90cyhoeXBfb2JqLG1lcmdlID0gRikKcGx0MSA9IHBsdCR1cCsgYWVzKHNpemU9bmVzKStnZ3RpdGxlKCJ1cCBpbiBjb21ib1BlcnNpc3RvciIpICsgdGhlbWUoICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSkKcGx0MiA9IHBsdCRkbisgYWVzKHNpemU9YWJzKG5lcykpK2dndGl0bGUoInVwIGluIG9zaVBlcnNpc3RvcnMiKSArIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApKQpwcmludF90YWIocGx0MStwbHQyLHRpdGxlID0gImNwVlNvcCIpCgpyYW5rZWRfdmVjID0gZGlmZl9nZW5lc1ssIDJdICU+JSBzZXROYW1lcyhyb3duYW1lcyhkaWZmX2dlbmVzKSkgJT4lIHNvcnQoZGVjcmVhc2luZyA9IFRSVUUpCmh5cF9vYmogPC0gaHlwZVJfZmdzZWEocmFua2VkX3ZlYywgZ2VuZXNldHMsIHVwX29ubHkgPSBGKQpwbHQgPSBoeXBfZG90cyhoeXBfb2JqLG1lcmdlID0gRikKcGx0MSA9IHBsdCR1cCsgYWVzKHNpemU9bmVzKStnZ3RpdGxlKCJ1cCBpbiByb3hhIikKcGx0MiA9IHBsdCRkbisgYWVzKHNpemU9YWJzKG5lcykpK2dndGl0bGUoInVwIGluIGN0cmwiKQpwcmludF90YWIocGx0MStwbHQyLHRpdGxlID0gImNwVlNvcCIpCgpgYGAKIyBERUcgaW4gY29tYm9WU29zaSBidXQgbm90IGluIHJveGFWU2N0cmwgey50YWJzZXR9CgpgYGB7ciByZXN1bHRzPSdhc2lzJ30KY3BWU29wIDwtIHJlc3VsdHMoZGRzLGNvbnRyYXN0ID0gYygiY29uZGl0aW9uIiwiY29tYm9QZXJzaXN0b3JzIiwib3NpUGVyc2lzdG9ycyIpKSAgJT4lIGFzLmRhdGEuZnJhbWUoKQpyb3hhVlNjdHJsIDwtIHJlc3VsdHMoZGRzLGNvbnRyYXN0ID0gYygiY29uZGl0aW9uIiwicm94YSIsImN0cmwiKSkgICU+JSBhcy5kYXRhLmZyYW1lKCkKZGlmZl9nZW5lcyA9IGRhdGEuZnJhbWUocm93Lm5hbWVzID0gcm93bmFtZXMoY3BWU29wKSwgY3BWU29wX0ZDID0gMioqY3BWU29wJGxvZzJGb2xkQ2hhbmdlLHJveGFWU2N0cmxfRkMgPSAyKipyb3hhVlNjdHJsJGxvZzJGb2xkQ2hhbmdlLCAgY3BWU29wX3BhZGogPSBjcFZTb3AkcGFkaikKdXBfZ2VuZXNfZGYgPSAgZGlmZl9nZW5lcyAlPiUgZmlsdGVyKGNwVlNvcF9GQyA+IDIgJiByb3hhVlNjdHJsX0ZDPDEuMiAmIGNwVlNvcF9wYWRqPDAuMDUpIApkb3duX2dlbmVzX2RmID0gZGlmZl9nZW5lcyAlPiUgZmlsdGVyKGNwVlNvcF9GQyA8IDAuNSAmIHJveGFWU2N0cmxfRkM+MC44ICYgY3BWU29wX3BhZGo8MC4wNSkKdXBfZ2VuZXMgPSBkaWZmX2dlbmVzICU+JSBmaWx0ZXIoY3BWU29wX0ZDID4gMiAmIHJveGFWU2N0cmxfRkM8MS4yICYgY3BWU29wX3BhZGo8MC4wNSkgJT4lIHJvd25hbWVzKCkKZG93bl9nZW5lcyA9IGRpZmZfZ2VuZXMgJT4lIGZpbHRlcihjcFZTb3BfRkMgPCAwLjUgJiByb3hhVlNjdHJsX0ZDPjAuOCAmIGNwVlNvcF9wYWRqPDAuMSklPiUgcm93bmFtZXMoKQoKcHJpbnRfdGFiKHVwX2dlbmVzX2RmLHRpdGxlID0gInVwIikKcHJpbnRfdGFiKGRvd25fZ2VuZXNfZGYsdGl0bGUgPSAiZG93biIpCmBgYApgYGB7cn0KSDE5NzVfdXBfZ2VuZXMgPSB1cF9nZW5lcwpIMTk3NV9kb3duX2dlbmVzID0gZG93bl9nZW5lcwoKYGBgCgojIHstfQoKYGBge3IgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTMscmVzdWx0cz0nYXNpcyd9Cmh5cF9vYmogPC0gaHlwZVIodXBfZ2VuZXMsIGdlbmVzZXRzLCB0ZXN0ID0gImh5cGVyZ2VvbWV0cmljIiwgZmRyPTEsIHBsb3R0aW5nPUYsYmFja2dyb3VuZCA9IHJvd25hbWVzKEgxOTc1T2N0MjMpKQpwbHQxID0gaHlwX2RvdHMoaHlwX29iaix0aXRsZSA9ICJ1cCBpbiBjb21ib1ZTb3NpIGJ1dCBub3QgaW4gcm94YVZTY3RybCIpCiAKCmh5cF9vYmogPC0gaHlwZVIoZG93bl9nZW5lcywgZ2VuZXNldHMsIHRlc3QgPSAiaHlwZXJnZW9tZXRyaWMiLCBmZHI9MSwgcGxvdHRpbmc9RixiYWNrZ3JvdW5kID0gcm93bmFtZXMoSDE5NzVPY3QyMykpCnBsdDIgPSBoeXBfZG90cyhoeXBfb2JqLHRpdGxlID0gImRvd24gaW4gY29tYm9WU29zaSBidXQgbm90IGluIHJveGFWU2N0cmwiKQoKcGx0MSArIHBsdDIKYGBgCmBgYHtyIHJlc3VsdHM9J2FzaXMnfQpwcmludF90YWIoZGF0YS5mcmFtZSh1cF9nZW5lc1t1cF9nZW5lcyAlaW4lIGdlbmVzZXRzJEhBTExNQVJLX0UyRl9UQVJHRVRTXSksdGl0bGUgPSAidXAgZ2VuZXMgaW4gRTJGIikKcHJpbnRfdGFiKGRhdGEuZnJhbWUodXBfZ2VuZXNbdXBfZ2VuZXMgJWluJSBnZW5lc2V0cyRIQUxMTUFSS19IWVBPWElBXSksdGl0bGUgPSAidXAgZ2VuZXMgaW4gSHlwb3hpYSIpCgoKYGBgCgo8c2NyaXB0IHNyYz0iaHR0cHM6Ly9oeXBvdGhlcy5pcy9lbWJlZC5qcyIgYXN5bmM+PC9zY3JpcHQ+Cgo=