Functions
Data
names (osiRoxaJun23)
[1] "H1975ctrl1" "H1975ctrl2" "H1975ctrl3" "H1975roxa1" "H1975roxa2"
[6] "H1975roxa3" "H1975osi1" "H1975osi2" "H1975osi3" "H1975osiPersistors1"
[11] "H1975osiPersistors2" "H1975osiPersistors3" "H1975comboPersistors1" "H1975comboPersistors2" "H1975comboPersistors3"
[16] "HCC827ctrl1" "HCC827ctrl2" "HCC827ctrl3" "HCC827roxa1" "HCC827roxa2"
[21] "HCC827roxa3" "HCC827osi1" "HCC827osi2" "HCC827osi3" "HCC827osiPersistors1"
[26] "HCC827osiPersistors2" "HCC827osiPersistors3" "HCC827comboPersistors1" "HCC827comboPersistors2" "HCC827comboPersistors3"
cell.labels = names(osiRoxaJun23)
condition = str_extract(cell.labels, "osiPersistors|comboPersistors|osi|ctrl|roxa")
metadata = data.frame(condition = condition, row.names = colnames(osiRoxaJun23))
library(DESeq2)
dds <- DESeqDataSetFromMatrix(countData = round(osiRoxaJun23),
colData = metadata,
design = ~condition)
PCA
nrow(dds)
[1] 27827
dds1 <- dds[ rowSums(counts(dds)) >= 3, ]
nrow(dds1)
[1] 8340
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 (4.95% 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 (14.34% 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 (22.72% 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 (22.72% 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")
hyp_obj <- hypeR(up_genes, genesets, test = "hypergeometric", fdr=1, plotting=F,background = rownames(osiRoxaJun23))
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(osiRoxaJun23))
plt2 = hyp_dots(hyp_obj,title = "down in comboVSosi but not in roxaVSctrl")
plt1 + plt2

LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19kZXB0aDogMQotLS0KCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+Ci5tYWluLWNvbnRhaW5lciB7CiAgbWF4LXdpZHRoOiA4NSUgIWltcG9ydGFudDsKICBtYXJnaW46IGF1dG87Cn0KPC9zdHlsZT4KCiMgRnVuY3Rpb25zCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpgYGAKCiMgRGF0YQoKYGBge3J9CmdlbmVzZXRzIDwtIG1zaWdkYl9kb3dubG9hZCgiSG9tbyBzYXBpZW5zIixjYXRlZ29yeT0iSCIpICU+JSBhcHBlbmQoIG1zaWdkYl9kb3dubG9hZCgiSG9tbyBzYXBpZW5zIixjYXRlZ29yeT0iQzIiLHN1YmNhdGVnb3J5ID0gIkNQOktFR0ciKSkKb3NpUm94YUp1bjIzID0gcmVhZC50YWJsZSgKICBmaWxlID0gIi4vRGF0YS9vc2lSb3hhX2J1bGsvSnVuMjMvZ2VuZV9mcGttLnhscyIsCiAgc2VwID0gIlx0IiwKICBoZWFkZXIgPSBUUlVFCikKcm93bmFtZXMob3NpUm94YUp1bjIzKSA9IG1ha2UudW5pcXVlKG9zaVJveGFKdW4yM1ssImdlbmVfbmFtZSIsZHJvcD1UXSkKb3NpUm94YUp1bjIzID0gb3NpUm94YUp1bjIzWywyOjMxXQpuYW1lcyAob3NpUm94YUp1bjIzKSA9IGdzdWIoeCA9IG5hbWVzKG9zaVJveGFKdW4yMykscGF0dGVybiA9ICJvcCIscmVwbGFjZW1lbnQgPSAib3NpUGVyc2lzdG9ycyIpJT4lIGdzdWIocGF0dGVybiA9ICJjcCIscmVwbGFjZW1lbnQgPSAiY29tYm9QZXJzaXN0b3JzIikgCm9zaVJveGFKdW4yMyA9IG9zaVJveGFKdW4yM1ssMToxNV0KCgpgYGAKCmBgYHtyfQpjZWxsLmxhYmVscyA9IG5hbWVzKG9zaVJveGFKdW4yMykKY29uZGl0aW9uID0gc3RyX2V4dHJhY3QoY2VsbC5sYWJlbHMsICJvc2lQZXJzaXN0b3JzfGNvbWJvUGVyc2lzdG9yc3xvc2l8Y3RybHxyb3hhIikKbWV0YWRhdGEgPSBkYXRhLmZyYW1lKGNvbmRpdGlvbiA9IGNvbmRpdGlvbiwgcm93Lm5hbWVzID0gY29sbmFtZXMob3NpUm94YUp1bjIzKSkKYGBgCgpgYGB7cn0KbGlicmFyeShERVNlcTIpCmRkcyA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IHJvdW5kKG9zaVJveGFKdW4yMyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbERhdGEgPSBtZXRhZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduID0gfmNvbmRpdGlvbikKYGBgCgoKIyBQQ0EKYGBge3J9Cm5yb3coZGRzKQpkZHMxIDwtIGRkc1sgcm93U3Vtcyhjb3VudHMoZGRzKSkgPj0gMywgXQpucm93KGRkczEpCmBgYAoKYGBge3J9CnZzdCA9IHZzdChkZHMxLCBibGluZD1GQUxTRSkKYGBgCgpgYGB7cn0KbGlicmFyeSgiZ2dmb3J0aWZ5IikKUENBZGF0YSA8LSBwcmNvbXAodChhc3NheSh2c3QpKSkKYXV0b3Bsb3QoUENBZGF0YSwgZGF0YSA9IG1ldGFkYXRhLGNvbG91ciA9ICJjb25kaXRpb24iLGxhYmVsID0gRkFMU0UsIG1haW49IlBDQSIpICMgU2hvdyBkb3RzCgpgYGAKIyBERVNlcQpgYGB7cn0KZGRzIDwtIERFU2VxKGRkcykKYGBgCgojIERFRyBGQyB7LnRhYnNldH0KYGBge3J9CmNwVlNvcCA8LSByZXN1bHRzKGRkcyxjb250cmFzdCA9IGMoImNvbmRpdGlvbiIsImNvbWJvUGVyc2lzdG9ycyIsIm9zaVBlcnNpc3RvcnMiKSkgICU+JSBhcy5kYXRhLmZyYW1lKCkKcm94YVZTY3RybCA8LSByZXN1bHRzKGRkcyxjb250cmFzdCA9IGMoImNvbmRpdGlvbiIsInJveGEiLCJjdHJsIikpICAlPiUgYXMuZGF0YS5mcmFtZSgpCmRpZmZfZ2VuZXMgPSBkYXRhLmZyYW1lKHJvdy5uYW1lcyA9IHJvd25hbWVzKGNwVlNvcCksIGNwVlNvcF9GQyA9IGNwVlNvcCRsb2cyRm9sZENoYW5nZSxyb3hhVlNjdHJsX0ZDID0gcm94YVZTY3RybCRsb2cyRm9sZENoYW5nZSwgIGNwVlNvcF9wYWRqID0gY3BWU29wJHBhZGopCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEzLCByZXN1bHRzPSdhc2lzJ30KY3BWU29wID0gY3BWU29wW29yZGVyKGNwVlNvcCRsb2cyRm9sZENoYW5nZSwgY3BWU29wJHBhZGosZGVjcmVhc2luZyA9IFQpLF0gI29yZGVyIGJ5IEZDLCB0aWVzIGJ0IHBhZGoKcmFua2VkX3ZlYyA9IGNwVlNvcFssImxvZzJGb2xkQ2hhbmdlIl0lPiUgc2V0TmFtZXMocm93bmFtZXMoY3BWU29wKSkgJT4lIG5hLm9taXQoKSAjIG1ha2UgbmFtZWQgdmVjdG9yCgpoeXBfb2JqIDwtIGh5cGVSX2Znc2VhKHJhbmtlZF92ZWMsIGdlbmVzZXRzLCB1cF9vbmx5ID0gRikKcGx0ID0gaHlwX2RvdHMoaHlwX29iaixtZXJnZSA9IEYpCnBsdDEgPSBwbHQkdXArIGFlcyhzaXplPW5lcykrZ2d0aXRsZSgidXAgaW4gY29tYm9QZXJzaXN0b3IiKQpwbHQyID0gcGx0JGRuKyBhZXMoc2l6ZT1hYnMobmVzKSkrZ2d0aXRsZSgidXAgaW4gb3NpUGVyc2lzdG9ycyIpCnByaW50X3RhYihwbHQxK3BsdDIsdGl0bGUgPSAiY3BWU29wIikKCgpyb3hhVlNjdHJsID0gcm94YVZTY3RybFtvcmRlcihyb3hhVlNjdHJsJGxvZzJGb2xkQ2hhbmdlLCByb3hhVlNjdHJsJHBhZGosZGVjcmVhc2luZyA9IFQpLF0gI29yZGVyIGJ5IEZDLCB0aWVzIGJ0IHBhZGoKcmFua2VkX3ZlYyA9IHJveGFWU2N0cmxbLCJsb2cyRm9sZENoYW5nZSJdJT4lIHNldE5hbWVzKHJvd25hbWVzKHJveGFWU2N0cmwpKSAlPiUgbmEub21pdCgpICAjIG1ha2UgbmFtZWQgdmVjdG9yCgpoeXBfb2JqIDwtIGh5cGVSX2Znc2VhKHJhbmtlZF92ZWMsIGdlbmVzZXRzLCB1cF9vbmx5ID0gRikKcGx0ID0gaHlwX2RvdHMoaHlwX29iaixtZXJnZSA9IEYpCnBsdDEgPSBwbHQkdXArIGFlcyhzaXplPW5lcykrZ2d0aXRsZSgidXAgaW4gcm94YSIpCnBsdDIgPSBwbHQkZG4rIGFlcyhzaXplPWFicyhuZXMpKStnZ3RpdGxlKCJ1cCBpbiBjdHJsIikKcHJpbnRfdGFiKHBsdDErcGx0Mix0aXRsZSA9ICJjcFZTb3AiKQpgYGAKCiMgREVHIHNocmlua2VkIEZDIHsudGFic2V0fQpgYGB7cn0KZGRzJGNvbmRpdGlvbiA9IHJlbGV2ZWwoZGRzJGNvbmRpdGlvbiwgcmVmID0gIm9zaVBlcnNpc3RvcnMiKQpkZHMgPC0gbmJpbm9tV2FsZFRlc3QoZGRzKQpjcFZTb3AgPC0gbGZjU2hyaW5rKGRkcyxjb2VmID0gImNvbmRpdGlvbl9jb21ib1BlcnNpc3RvcnNfdnNfb3NpUGVyc2lzdG9ycyIpICAlPiUgYXMuZGF0YS5mcmFtZSgpCgpkZHMkY29uZGl0aW9uID0gcmVsZXZlbChkZHMkY29uZGl0aW9uLCByZWYgPSAiY3RybCIpCmRkcyA8LSBuYmlub21XYWxkVGVzdChkZHMpCnJveGFWU2N0cmwgPC0gbGZjU2hyaW5rKGRkcyxjb2VmICA9ICJjb25kaXRpb25fcm94YV92c19jdHJsIikgICU+JSBhcy5kYXRhLmZyYW1lKCkKCgpkaWZmX2dlbmVzID0gZGF0YS5mcmFtZShyb3cubmFtZXMgPSByb3duYW1lcyhjcFZTb3ApLCBjcFZTb3BfRkMgPSBjcFZTb3AkbG9nMkZvbGRDaGFuZ2Uscm94YVZTY3RybF9GQyA9IHJveGFWU2N0cmwkbG9nMkZvbGRDaGFuZ2UsICBjcFZTb3BfcGFkaiA9IGNwVlNvcCRwYWRqKQoKYGBgCgoKYGBge3IgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTMscmVzdWx0cz0nYXNpcyd9CnJhbmtlZF92ZWMgPSBkaWZmX2dlbmVzWywgMV0gJT4lIHNldE5hbWVzKHJvd25hbWVzKGRpZmZfZ2VuZXMpKSAlPiUgc29ydChkZWNyZWFzaW5nID0gVFJVRSkKaHlwX29iaiA8LSBoeXBlUl9mZ3NlYShyYW5rZWRfdmVjLCBnZW5lc2V0cywgdXBfb25seSA9IEYpCnBsdCA9IGh5cF9kb3RzKGh5cF9vYmosbWVyZ2UgPSBGKQpwbHQxID0gcGx0JHVwKyBhZXMoc2l6ZT1uZXMpK2dndGl0bGUoInVwIGluIGNvbWJvUGVyc2lzdG9yIikgKyB0aGVtZSggIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApKQpwbHQyID0gcGx0JGRuKyBhZXMoc2l6ZT1hYnMobmVzKSkrZ2d0aXRsZSgidXAgaW4gb3NpUGVyc2lzdG9ycyIpICsgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCkpCnByaW50X3RhYihwbHQxK3BsdDIsdGl0bGUgPSAiY3BWU29wIikKCnJhbmtlZF92ZWMgPSBkaWZmX2dlbmVzWywgMl0gJT4lIHNldE5hbWVzKHJvd25hbWVzKGRpZmZfZ2VuZXMpKSAlPiUgc29ydChkZWNyZWFzaW5nID0gVFJVRSkKaHlwX29iaiA8LSBoeXBlUl9mZ3NlYShyYW5rZWRfdmVjLCBnZW5lc2V0cywgdXBfb25seSA9IEYpCnBsdCA9IGh5cF9kb3RzKGh5cF9vYmosbWVyZ2UgPSBGKQpwbHQxID0gcGx0JHVwKyBhZXMoc2l6ZT1uZXMpK2dndGl0bGUoInVwIGluIHJveGEiKQpwbHQyID0gcGx0JGRuKyBhZXMoc2l6ZT1hYnMobmVzKSkrZ2d0aXRsZSgidXAgaW4gY3RybCIpCnByaW50X3RhYihwbHQxK3BsdDIsdGl0bGUgPSAiY3BWU29wIikKCmBgYAojIERFRyBpbiBjb21ib1ZTb3NpIGJ1dCBub3QgaW4gcm94YVZTY3RybCB7LnRhYnNldH0KCmBgYHtyIHJlc3VsdHM9J2FzaXMnfQpjcFZTb3AgPC0gcmVzdWx0cyhkZHMsY29udHJhc3QgPSBjKCJjb25kaXRpb24iLCJjb21ib1BlcnNpc3RvcnMiLCJvc2lQZXJzaXN0b3JzIikpICAlPiUgYXMuZGF0YS5mcmFtZSgpCnJveGFWU2N0cmwgPC0gcmVzdWx0cyhkZHMsY29udHJhc3QgPSBjKCJjb25kaXRpb24iLCJyb3hhIiwiY3RybCIpKSAgJT4lIGFzLmRhdGEuZnJhbWUoKQpkaWZmX2dlbmVzID0gZGF0YS5mcmFtZShyb3cubmFtZXMgPSByb3duYW1lcyhjcFZTb3ApLCBjcFZTb3BfRkMgPSAyKipjcFZTb3AkbG9nMkZvbGRDaGFuZ2Uscm94YVZTY3RybF9GQyA9IDIqKnJveGFWU2N0cmwkbG9nMkZvbGRDaGFuZ2UsICBjcFZTb3BfcGFkaiA9IGNwVlNvcCRwYWRqKQp1cF9nZW5lc19kZiA9ICBkaWZmX2dlbmVzICU+JSBmaWx0ZXIoY3BWU29wX0ZDID4gMiAmIHJveGFWU2N0cmxfRkM8MS4yICYgY3BWU29wX3BhZGo8MC4wNSkgCmRvd25fZ2VuZXNfZGYgPSBkaWZmX2dlbmVzICU+JSBmaWx0ZXIoY3BWU29wX0ZDIDwgMC41ICYgcm94YVZTY3RybF9GQz4wLjggJiBjcFZTb3BfcGFkajwwLjA1KQp1cF9nZW5lcyA9IGRpZmZfZ2VuZXMgJT4lIGZpbHRlcihjcFZTb3BfRkMgPiAyICYgcm94YVZTY3RybF9GQzwxLjIgJiBjcFZTb3BfcGFkajwwLjA1KSAlPiUgcm93bmFtZXMoKQpkb3duX2dlbmVzID0gZGlmZl9nZW5lcyAlPiUgZmlsdGVyKGNwVlNvcF9GQyA8IDAuNSAmIHJveGFWU2N0cmxfRkM+MC44ICYgY3BWU29wX3BhZGo8MC4xKSU+JSByb3duYW1lcygpCgpwcmludF90YWIodXBfZ2VuZXNfZGYsdGl0bGUgPSAidXAiKQpwcmludF90YWIoZG93bl9nZW5lc19kZix0aXRsZSA9ICJkb3duIikKYGBgCgoKIyB7LX0KCmBgYHtyIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEzLHJlc3VsdHM9J2FzaXMnfQpoeXBfb2JqIDwtIGh5cGVSKHVwX2dlbmVzLCBnZW5lc2V0cywgdGVzdCA9ICJoeXBlcmdlb21ldHJpYyIsIGZkcj0xLCBwbG90dGluZz1GLGJhY2tncm91bmQgPSByb3duYW1lcyhvc2lSb3hhSnVuMjMpKQpwbHQxID0gaHlwX2RvdHMoaHlwX29iaix0aXRsZSA9ICJ1cCBpbiBjb21ib1ZTb3NpIGJ1dCBub3QgaW4gcm94YVZTY3RybCIpCiAKCmh5cF9vYmogPC0gaHlwZVIoZG93bl9nZW5lcywgZ2VuZXNldHMsIHRlc3QgPSAiaHlwZXJnZW9tZXRyaWMiLCBmZHI9MSwgcGxvdHRpbmc9RixiYWNrZ3JvdW5kID0gcm93bmFtZXMob3NpUm94YUp1bjIzKSkKcGx0MiA9IGh5cF9kb3RzKGh5cF9vYmosdGl0bGUgPSAiZG93biBpbiBjb21ib1ZTb3NpIGJ1dCBub3QgaW4gcm94YVZTY3RybCIpCgpwbHQxICsgcGx0MgpgYGAKCgo8c2NyaXB0IHNyYz0iaHR0cHM6Ly9oeXBvdGhlcy5pcy9lbWJlZC5qcyIgYXN5bmM+PC9zY3JpcHQ+Cgo=