1 Functions

2 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)
converting counts to integer mode
Warning in DESeqDataSet(se, design = design, ignoreRank) :
  some variables in design formula are characters, converting to factors

3 PCA

nrow(dds)
[1] 32780
dds1 <- dds[ rowSums(counts(dds)) >= 3, ]
nrow(dds1)
[1] 9065
vst = vst(dds1, blind=FALSE)
library("ggfortify")
PCAdata <- prcomp(t(assay(vst)))
autoplot(PCAdata, data = metadata,colour = "condition",label = FALSE, main="PCA") # Show dots

4 DESeq

dds <- DESeq(dds)
dds_H1975_OCT23 = dds
dds = dds_H1975_OCT23

5 Top variable genes heatmap

genes <- head(order(rowVars(assay(dds)), decreasing = TRUE), 1000)

mat <- H1975Oct23[ genes, ]
mat <- t(scale(t(mat)))
anno <- as.data.frame(mat)

library(ComplexHeatmap) 
library(ggplot2) 
Heatmap(mat, cluster_rows = T, cluster_columns = F, column_labels = colnames(anno), name = "fpkm Z-score",row_names_gp = gpar(fontsize = 0)) 

6 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)
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")


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)
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")

7 CC upregulted in cp VS op

osiVSctrl_genes <- results(dds,contrast = c("condition","osi","ctrl"))  %>% as.data.frame() %>% filter(log2FoldChange>0 & padj < 0.05) %>% rownames()
cpVSctrl_genes <- results(dds,contrast = c("condition","comboPersistors","ctrl"))  %>% as.data.frame() %>% filter(log2FoldChange>0 & padj < 0.05) %>% rownames()
roxaVSctrl_genes = roxaVSctrl %>% filter(log2FoldChange>0 & padj < 0.05)%>% rownames()

8 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

9 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

print_tab(data.frame(up_genes[up_genes %in% genesets$HALLMARK_E2F_TARGETS]),title = "up genes in E2F")

up genes in E2F

print_tab(data.frame(up_genes[up_genes %in% genesets$HALLMARK_HYPOXIA]),title = "up genes in Hypoxia")

up genes in Hypoxia

NA

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")

10 Expression heatmap

# select the 50 most differentially expressed genes 
genes <- c("DUSP6","MKI67")
mat <- H1975Oct23[ genes, ]
mat <- t(scale(t(mat)))
anno <- as.data.frame(mat)

library(ComplexHeatmap) 
library(ggplot2) 
p = Heatmap(mat, cluster_rows = F, cluster_columns = F, column_labels = colnames(anno), name = "fpkm Z-score") 
print_tab(plt = p,title = "markers")

markers

genes <- hif_targets
mat <- H1975Oct23[genes, ] %>% filter(rowSums(across(where(is.numeric)))!=0)
mat <- t(scale(t(mat)))
anno <- as.data.frame(mat)

 
p = Heatmap(mat, cluster_rows = T, cluster_columns = F, column_labels = colnames(anno), name = "fpkm Z-score",column_title = "HIF targets",row_names_gp = gpar(fontsize = 8))

print_tab(plt = p,title = "HIF targets")

HIF targets

genes <- genesets$HALLMARK_G2M_CHECKPOINT
mat <- H1975Oct23[genes, ] %>% filter(rowSums(across(where(is.numeric)))!=0)
mat <- t(scale(t(mat)))
anno <- as.data.frame(mat)

 
p = Heatmap(mat, cluster_rows = T, cluster_columns = F, column_labels = colnames(anno), name = "fpkm Z-score",column_title = "HALLMARK_G2M_CHECKPOINT",row_names_gp =gpar(fontsize = 0)) 

print_tab(plt = p,title = "HALLMARK_G2M_CHECKPOINT")

HALLMARK_G2M_CHECKPOINT

NA

11 Distance plot

vsd <- vst(dds, blind=FALSE)
sampleDists <- dist(t(assay(vsd)))
library("RColorBrewer")
sampleDistMatrix <- as.matrix(sampleDists)
colnames(sampleDistMatrix) <- NULL
colors <- colorRampPalette( rev(brewer.pal(9, "Blues")) )(255)
pheatmap(sampleDistMatrix,
         clustering_distance_rows=sampleDists,
         clustering_distance_cols=sampleDists,
         col=colors)

LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19kZXB0aDogMQotLS0KCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+Ci5tYWluLWNvbnRhaW5lciB7CiAgbWF4LXdpZHRoOiA4NSUgIWltcG9ydGFudDsKICBtYXJnaW46IGF1dG87Cn0KPC9zdHlsZT4KCiMgRnVuY3Rpb25zCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpgYGAKCiMgRGF0YQoKYGBge3J9CmdlbmVzZXRzIDwtIG1zaWdkYl9kb3dubG9hZCgiSG9tbyBzYXBpZW5zIixjYXRlZ29yeT0iSCIpICU+JSBhcHBlbmQoIG1zaWdkYl9kb3dubG9hZCgiSG9tbyBzYXBpZW5zIixjYXRlZ29yeT0iQzIiLHN1YmNhdGVnb3J5ID0gIkNQOktFR0ciKSkKYSA9IG1zaWdkYl9kb3dubG9hZCgiSG9tbyBzYXBpZW5zIixjYXRlZ29yeT0iQzIiLHN1YmNhdGVnb3J5ID0gIkNQIikKSDE5NzVPY3QyMyA9IHJlYWQudGFibGUoCiAgZmlsZSA9ICIuL0RhdGEvb3NpUm94YV9idWxrL09jdDIzL2dlbmVfZnBrbS54bHMiLAogIHNlcCA9ICJcdCIsCiAgaGVhZGVyID0gVFJVRQopCnJvd25hbWVzKEgxOTc1T2N0MjMpID0gbWFrZS51bmlxdWUoSDE5NzVPY3QyM1ssImdlbmVfbmFtZSIsZHJvcD1UXSkKSDE5NzVPY3QyMyA9IEgxOTc1T2N0MjNbLDI6MTZdCm5hbWVzIChIMTk3NU9jdDIzKSA9IGdzdWIoeCA9IG5hbWVzKEgxOTc1T2N0MjMpLHBhdHRlcm4gPSAiX0MiLHJlcGxhY2VtZW50ID0gIl9jdHJsIiklPiUgZ3N1YihwYXR0ZXJuID0gInBfT1IiLHJlcGxhY2VtZW50ID0gIl9jb21ib1BlcnNpc3RvcnMiKSAlPiUgZ3N1YihwYXR0ZXJuID0gInBfTyIscmVwbGFjZW1lbnQgPSAiX29zaVBlcnNpc3RvcnMiKSAlPiUgZ3N1YihwYXR0ZXJuID0gIl9SIixyZXBsYWNlbWVudCA9ICJfcm94YSIpJT4lIGdzdWIoLHBhdHRlcm4gPSAiX08iLHJlcGxhY2VtZW50ID0gIl9vc2kiKQoKYGBgCgpgYGB7cn0KY2VsbC5sYWJlbHMgPSBuYW1lcyhIMTk3NU9jdDIzKQpjb25kaXRpb24gPSBzdHJfZXh0cmFjdChjZWxsLmxhYmVscywgIm9zaVBlcnNpc3RvcnN8Y29tYm9QZXJzaXN0b3JzfG9zaXxjdHJsfHJveGEiKQptZXRhZGF0YSA9IGRhdGEuZnJhbWUoY29uZGl0aW9uID0gY29uZGl0aW9uLCByb3cubmFtZXMgPSBjb2xuYW1lcyhIMTk3NU9jdDIzKSkKYGBgCgpgYGB7cn0KbGlicmFyeShERVNlcTIpCmRkcyA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IHJvdW5kKEgxOTc1T2N0MjMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xEYXRhID0gbWV0YWRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2lnbiA9IH5jb25kaXRpb24pCmBgYAoKCiMgUENBCmBgYHtyfQpucm93KGRkcykKZGRzMSA8LSBkZHNbIHJvd1N1bXMoY291bnRzKGRkcykpID49IDMsIF0KbnJvdyhkZHMxKQpgYGAKCmBgYHtyfQp2c3QgPSB2c3QoZGRzMSwgYmxpbmQ9RkFMU0UpCmBgYAoKYGBge3J9CmxpYnJhcnkoImdnZm9ydGlmeSIpClBDQWRhdGEgPC0gcHJjb21wKHQoYXNzYXkodnN0KSkpCmF1dG9wbG90KFBDQWRhdGEsIGRhdGEgPSBtZXRhZGF0YSxjb2xvdXIgPSAiY29uZGl0aW9uIixsYWJlbCA9IEZBTFNFLCBtYWluPSJQQ0EiKSAjIFNob3cgZG90cwoKYGBgCiMgREVTZXEKYGBge3J9CmRkcyA8LSBERVNlcShkZHMpCmRkc19IMTk3NV9PQ1QyMyA9IGRkcwpgYGAKCmBgYHtyfQpkZHMgPSBkZHNfSDE5NzVfT0NUMjMKYGBgCgoKIyBUb3AgdmFyaWFibGUgZ2VuZXMgaGVhdG1hcApgYGB7cn0KZ2VuZXMgPC0gaGVhZChvcmRlcihyb3dWYXJzKGFzc2F5KGRkcykpLCBkZWNyZWFzaW5nID0gVFJVRSksIDEwMDApCgptYXQgPC0gSDE5NzVPY3QyM1sgZ2VuZXMsIF0KbWF0IDwtIHQoc2NhbGUodChtYXQpKSkKYW5ubyA8LSBhcy5kYXRhLmZyYW1lKG1hdCkKCmxpYnJhcnkoQ29tcGxleEhlYXRtYXApIApsaWJyYXJ5KGdncGxvdDIpIApIZWF0bWFwKG1hdCwgY2x1c3Rlcl9yb3dzID0gVCwgY2x1c3Rlcl9jb2x1bW5zID0gRiwgY29sdW1uX2xhYmVscyA9IGNvbG5hbWVzKGFubm8pLCBuYW1lID0gImZwa20gWi1zY29yZSIscm93X25hbWVzX2dwID0gZ3Bhcihmb250c2l6ZSA9IDApKSAKYGBgCgojIERFRyBGQyB7LnRhYnNldH0KYGBge3J9CmNwVlNvcCA8LSByZXN1bHRzKGRkcyxjb250cmFzdCA9IGMoImNvbmRpdGlvbiIsImNvbWJvUGVyc2lzdG9ycyIsIm9zaVBlcnNpc3RvcnMiKSkgICU+JSBhcy5kYXRhLmZyYW1lKCkKcm94YVZTY3RybCA8LSByZXN1bHRzKGRkcyxjb250cmFzdCA9IGMoImNvbmRpdGlvbiIsInJveGEiLCJjdHJsIikpICAlPiUgYXMuZGF0YS5mcmFtZSgpCmRpZmZfZ2VuZXMgPSBkYXRhLmZyYW1lKHJvdy5uYW1lcyA9IHJvd25hbWVzKGNwVlNvcCksIGNwVlNvcF9GQyA9IGNwVlNvcCRsb2cyRm9sZENoYW5nZSxyb3hhVlNjdHJsX0ZDID0gcm94YVZTY3RybCRsb2cyRm9sZENoYW5nZSwgIGNwVlNvcF9wYWRqID0gY3BWU29wJHBhZGopCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEzLCByZXN1bHRzPSdhc2lzJ30KY3BWU29wID0gY3BWU29wW29yZGVyKGNwVlNvcCRsb2cyRm9sZENoYW5nZSwgY3BWU29wJHBhZGosZGVjcmVhc2luZyA9IFQpLF0gI29yZGVyIGJ5IEZDLCB0aWVzIGJ0IHBhZGoKcmFua2VkX3ZlYyA9IGNwVlNvcFssImxvZzJGb2xkQ2hhbmdlIl0lPiUgc2V0TmFtZXMocm93bmFtZXMoY3BWU29wKSkgJT4lIG5hLm9taXQoKSAjIG1ha2UgbmFtZWQgdmVjdG9yCgpoeXBfb2JqIDwtIGh5cGVSX2Znc2VhKHJhbmtlZF92ZWMsIGdlbmVzZXRzLCB1cF9vbmx5ID0gRikKcGx0ID0gaHlwX2RvdHMoaHlwX29iaixtZXJnZSA9IEYpCnBsdDEgPSBwbHQkdXArIGFlcyhzaXplPW5lcykrZ2d0aXRsZSgidXAgaW4gY29tYm9QZXJzaXN0b3IiKQpwbHQyID0gcGx0JGRuKyBhZXMoc2l6ZT1hYnMobmVzKSkrZ2d0aXRsZSgidXAgaW4gb3NpUGVyc2lzdG9ycyIpCnByaW50X3RhYihwbHQxK3BsdDIsdGl0bGUgPSAiY3BWU29wIikKCgpyb3hhVlNjdHJsID0gcm94YVZTY3RybFtvcmRlcihyb3hhVlNjdHJsJGxvZzJGb2xkQ2hhbmdlLCByb3hhVlNjdHJsJHBhZGosZGVjcmVhc2luZyA9IFQpLF0gI29yZGVyIGJ5IEZDLCB0aWVzIGJ0IHBhZGoKcmFua2VkX3ZlYyA9IHJveGFWU2N0cmxbLCJsb2cyRm9sZENoYW5nZSJdJT4lIHNldE5hbWVzKHJvd25hbWVzKHJveGFWU2N0cmwpKSAlPiUgbmEub21pdCgpICAjIG1ha2UgbmFtZWQgdmVjdG9yCgpoeXBfb2JqIDwtIGh5cGVSX2Znc2VhKHJhbmtlZF92ZWMsIGdlbmVzZXRzLCB1cF9vbmx5ID0gRikKcGx0ID0gaHlwX2RvdHMoaHlwX29iaixtZXJnZSA9IEYpCnBsdDEgPSBwbHQkdXArIGFlcyhzaXplPW5lcykrZ2d0aXRsZSgidXAgaW4gcm94YSIpCnBsdDIgPSBwbHQkZG4rIGFlcyhzaXplPWFicyhuZXMpKStnZ3RpdGxlKCJ1cCBpbiBjdHJsIikKcHJpbnRfdGFiKHBsdDErcGx0Mix0aXRsZSA9ICJjcFZTb3AiKQpgYGAKCgojIENDIHVwcmVndWx0ZWQgaW4gY3AgVlMgb3AKYGBge3J9Cm9zaVZTY3RybF9nZW5lcyA8LSByZXN1bHRzKGRkcyxjb250cmFzdCA9IGMoImNvbmRpdGlvbiIsIm9zaSIsImN0cmwiKSkgICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIGZpbHRlcihsb2cyRm9sZENoYW5nZT4wICYgcGFkaiA8IDAuMDUpICU+JSByb3duYW1lcygpCmNwVlNjdHJsX2dlbmVzIDwtIHJlc3VsdHMoZGRzLGNvbnRyYXN0ID0gYygiY29uZGl0aW9uIiwiY29tYm9QZXJzaXN0b3JzIiwiY3RybCIpKSAgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgZmlsdGVyKGxvZzJGb2xkQ2hhbmdlPjAgJiBwYWRqIDwgMC4wNSkgJT4lIHJvd25hbWVzKCkKcm94YVZTY3RybF9nZW5lcyA9IHJveGFWU2N0cmwgJT4lIGZpbHRlcihsb2cyRm9sZENoYW5nZT4wICYgcGFkaiA8IDAuMDUpJT4lIHJvd25hbWVzKCkKCmBgYAoKIyBERUcgc2hyaW5rZWQgRkMgey50YWJzZXR9CmBgYHtyfQpkZHMkY29uZGl0aW9uID0gcmVsZXZlbChkZHMkY29uZGl0aW9uLCByZWYgPSAib3NpUGVyc2lzdG9ycyIpCmRkcyA8LSBuYmlub21XYWxkVGVzdChkZHMpCmNwVlNvcCA8LSBsZmNTaHJpbmsoZGRzLGNvZWYgPSAiY29uZGl0aW9uX2NvbWJvUGVyc2lzdG9yc192c19vc2lQZXJzaXN0b3JzIikgICU+JSBhcy5kYXRhLmZyYW1lKCkKCmRkcyRjb25kaXRpb24gPSByZWxldmVsKGRkcyRjb25kaXRpb24sIHJlZiA9ICJjdHJsIikKZGRzIDwtIG5iaW5vbVdhbGRUZXN0KGRkcykKcm94YVZTY3RybCA8LSBsZmNTaHJpbmsoZGRzLGNvZWYgID0gImNvbmRpdGlvbl9yb3hhX3ZzX2N0cmwiKSAgJT4lIGFzLmRhdGEuZnJhbWUoKQoKCmRpZmZfZ2VuZXMgPSBkYXRhLmZyYW1lKHJvdy5uYW1lcyA9IHJvd25hbWVzKGNwVlNvcCksIGNwVlNvcF9GQyA9IGNwVlNvcCRsb2cyRm9sZENoYW5nZSxyb3hhVlNjdHJsX0ZDID0gcm94YVZTY3RybCRsb2cyRm9sZENoYW5nZSwgIGNwVlNvcF9wYWRqID0gY3BWU29wJHBhZGopCgpgYGAKCgpgYGB7ciBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMyxyZXN1bHRzPSdhc2lzJ30KcmFua2VkX3ZlYyA9IGRpZmZfZ2VuZXNbLCAxXSAlPiUgc2V0TmFtZXMocm93bmFtZXMoZGlmZl9nZW5lcykpICU+JSBzb3J0KGRlY3JlYXNpbmcgPSBUUlVFKQpoeXBfb2JqIDwtIGh5cGVSX2Znc2VhKHJhbmtlZF92ZWMsIGdlbmVzZXRzLCB1cF9vbmx5ID0gRikKcGx0ID0gaHlwX2RvdHMoaHlwX29iaixtZXJnZSA9IEYpCnBsdDEgPSBwbHQkdXArIGFlcyhzaXplPW5lcykrZ2d0aXRsZSgidXAgaW4gY29tYm9QZXJzaXN0b3IiKSArIHRoZW1lKCAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCkpCnBsdDIgPSBwbHQkZG4rIGFlcyhzaXplPWFicyhuZXMpKStnZ3RpdGxlKCJ1cCBpbiBvc2lQZXJzaXN0b3JzIikgKyB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSkKcHJpbnRfdGFiKHBsdDErcGx0Mix0aXRsZSA9ICJjcFZTb3AiKQoKcmFua2VkX3ZlYyA9IGRpZmZfZ2VuZXNbLCAyXSAlPiUgc2V0TmFtZXMocm93bmFtZXMoZGlmZl9nZW5lcykpICU+JSBzb3J0KGRlY3JlYXNpbmcgPSBUUlVFKQpoeXBfb2JqIDwtIGh5cGVSX2Znc2VhKHJhbmtlZF92ZWMsIGdlbmVzZXRzLCB1cF9vbmx5ID0gRikKcGx0ID0gaHlwX2RvdHMoaHlwX29iaixtZXJnZSA9IEYpCnBsdDEgPSBwbHQkdXArIGFlcyhzaXplPW5lcykrZ2d0aXRsZSgidXAgaW4gcm94YSIpCnBsdDIgPSBwbHQkZG4rIGFlcyhzaXplPWFicyhuZXMpKStnZ3RpdGxlKCJ1cCBpbiBjdHJsIikKcHJpbnRfdGFiKHBsdDErcGx0Mix0aXRsZSA9ICJjcFZTb3AiKQoKYGBgCiMgREVHIGluIGNvbWJvVlNvc2kgYnV0IG5vdCBpbiByb3hhVlNjdHJsIHsudGFic2V0fQoKYGBge3IgcmVzdWx0cz0nYXNpcyd9CmNwVlNvcCA8LSByZXN1bHRzKGRkcyxjb250cmFzdCA9IGMoImNvbmRpdGlvbiIsImNvbWJvUGVyc2lzdG9ycyIsIm9zaVBlcnNpc3RvcnMiKSkgICU+JSBhcy5kYXRhLmZyYW1lKCkKcm94YVZTY3RybCA8LSByZXN1bHRzKGRkcyxjb250cmFzdCA9IGMoImNvbmRpdGlvbiIsInJveGEiLCJjdHJsIikpICAlPiUgYXMuZGF0YS5mcmFtZSgpCmRpZmZfZ2VuZXMgPSBkYXRhLmZyYW1lKHJvdy5uYW1lcyA9IHJvd25hbWVzKGNwVlNvcCksIGNwVlNvcF9GQyA9IDIqKmNwVlNvcCRsb2cyRm9sZENoYW5nZSxyb3hhVlNjdHJsX0ZDID0gMioqcm94YVZTY3RybCRsb2cyRm9sZENoYW5nZSwgIGNwVlNvcF9wYWRqID0gY3BWU29wJHBhZGopCnVwX2dlbmVzX2RmID0gIGRpZmZfZ2VuZXMgJT4lIGZpbHRlcihjcFZTb3BfRkMgPiAyICYgcm94YVZTY3RybF9GQzwxLjIgJiBjcFZTb3BfcGFkajwwLjA1KSAKZG93bl9nZW5lc19kZiA9IGRpZmZfZ2VuZXMgJT4lIGZpbHRlcihjcFZTb3BfRkMgPCAwLjUgJiByb3hhVlNjdHJsX0ZDPjAuOCAmIGNwVlNvcF9wYWRqPDAuMDUpCnVwX2dlbmVzID0gZGlmZl9nZW5lcyAlPiUgZmlsdGVyKGNwVlNvcF9GQyA+IDIgJiByb3hhVlNjdHJsX0ZDPDEuMiAmIGNwVlNvcF9wYWRqPDAuMDUpICU+JSByb3duYW1lcygpCmRvd25fZ2VuZXMgPSBkaWZmX2dlbmVzICU+JSBmaWx0ZXIoY3BWU29wX0ZDIDwgMC41ICYgcm94YVZTY3RybF9GQz4wLjggJiBjcFZTb3BfcGFkajwwLjEpJT4lIHJvd25hbWVzKCkKCnByaW50X3RhYih1cF9nZW5lc19kZix0aXRsZSA9ICJ1cCIpCnByaW50X3RhYihkb3duX2dlbmVzX2RmLHRpdGxlID0gImRvd24iKQpgYGAKYGBge3J9CkgxOTc1X3VwX2dlbmVzID0gdXBfZ2VuZXMKSDE5NzVfZG93bl9nZW5lcyA9IGRvd25fZ2VuZXMKCmBgYAoKIyB7LX0KCmBgYHtyIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEzLHJlc3VsdHM9J2FzaXMnfQpoeXBfb2JqIDwtIGh5cGVSKHVwX2dlbmVzLCBnZW5lc2V0cywgdGVzdCA9ICJoeXBlcmdlb21ldHJpYyIsIGZkcj0xLCBwbG90dGluZz1GLGJhY2tncm91bmQgPSByb3duYW1lcyhIMTk3NU9jdDIzKSkKcGx0MSA9IGh5cF9kb3RzKGh5cF9vYmosdGl0bGUgPSAidXAgaW4gY29tYm9WU29zaSBidXQgbm90IGluIHJveGFWU2N0cmwiKQogCgpoeXBfb2JqIDwtIGh5cGVSKGRvd25fZ2VuZXMsIGdlbmVzZXRzLCB0ZXN0ID0gImh5cGVyZ2VvbWV0cmljIiwgZmRyPTEsIHBsb3R0aW5nPUYsYmFja2dyb3VuZCA9IHJvd25hbWVzKEgxOTc1T2N0MjMpKQpwbHQyID0gaHlwX2RvdHMoaHlwX29iaix0aXRsZSA9ICJkb3duIGluIGNvbWJvVlNvc2kgYnV0IG5vdCBpbiByb3hhVlNjdHJsIikKCnBsdDEgKyBwbHQyCmBgYApgYGB7ciByZXN1bHRzPSdhc2lzJ30KcHJpbnRfdGFiKGRhdGEuZnJhbWUodXBfZ2VuZXNbdXBfZ2VuZXMgJWluJSBnZW5lc2V0cyRIQUxMTUFSS19FMkZfVEFSR0VUU10pLHRpdGxlID0gInVwIGdlbmVzIGluIEUyRiIpCnByaW50X3RhYihkYXRhLmZyYW1lKHVwX2dlbmVzW3VwX2dlbmVzICVpbiUgZ2VuZXNldHMkSEFMTE1BUktfSFlQT1hJQV0pLHRpdGxlID0gInVwIGdlbmVzIGluIEh5cG94aWEiKQoKCmBgYAoKIyBFeHByZXNzaW9uIGhlYXRtYXAgey50YWJzZXR9CmBgYHtyIGZpZy5oZWlnaHQ9NiwgcmVzdWx0cz0nYXNpcyd9CiMgc2VsZWN0IHRoZSA1MCBtb3N0IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyAKZ2VuZXMgPC0gYygiRFVTUDYiLCJNS0k2NyIpCm1hdCA8LSBIMTk3NU9jdDIzWyBnZW5lcywgXQptYXQgPC0gdChzY2FsZSh0KG1hdCkpKQphbm5vIDwtIGFzLmRhdGEuZnJhbWUobWF0KQoKbGlicmFyeShDb21wbGV4SGVhdG1hcCkgCmxpYnJhcnkoZ2dwbG90MikgCnAgPSBIZWF0bWFwKG1hdCwgY2x1c3Rlcl9yb3dzID0gRiwgY2x1c3Rlcl9jb2x1bW5zID0gRiwgY29sdW1uX2xhYmVscyA9IGNvbG5hbWVzKGFubm8pLCBuYW1lID0gImZwa20gWi1zY29yZSIpIApwcmludF90YWIocGx0ID0gcCx0aXRsZSA9ICJtYXJrZXJzIikKCmdlbmVzIDwtIGhpZl90YXJnZXRzCm1hdCA8LSBIMTk3NU9jdDIzW2dlbmVzLCBdICU+JSBmaWx0ZXIocm93U3VtcyhhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYykpKSE9MCkKbWF0IDwtIHQoc2NhbGUodChtYXQpKSkKYW5ubyA8LSBhcy5kYXRhLmZyYW1lKG1hdCkKCiAKcCA9IEhlYXRtYXAobWF0LCBjbHVzdGVyX3Jvd3MgPSBULCBjbHVzdGVyX2NvbHVtbnMgPSBGLCBjb2x1bW5fbGFiZWxzID0gY29sbmFtZXMoYW5ubyksIG5hbWUgPSAiZnBrbSBaLXNjb3JlIixjb2x1bW5fdGl0bGUgPSAiSElGIHRhcmdldHMiLHJvd19uYW1lc19ncCA9IGdwYXIoZm9udHNpemUgPSA4KSkKCnByaW50X3RhYihwbHQgPSBwLHRpdGxlID0gIkhJRiB0YXJnZXRzIikKCmdlbmVzIDwtIGdlbmVzZXRzJEhBTExNQVJLX0cyTV9DSEVDS1BPSU5UCm1hdCA8LSBIMTk3NU9jdDIzW2dlbmVzLCBdICU+JSBmaWx0ZXIocm93U3VtcyhhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYykpKSE9MCkKbWF0IDwtIHQoc2NhbGUodChtYXQpKSkKYW5ubyA8LSBhcy5kYXRhLmZyYW1lKG1hdCkKCiAKcCA9IEhlYXRtYXAobWF0LCBjbHVzdGVyX3Jvd3MgPSBULCBjbHVzdGVyX2NvbHVtbnMgPSBGLCBjb2x1bW5fbGFiZWxzID0gY29sbmFtZXMoYW5ubyksIG5hbWUgPSAiZnBrbSBaLXNjb3JlIixjb2x1bW5fdGl0bGUgPSAiSEFMTE1BUktfRzJNX0NIRUNLUE9JTlQiLHJvd19uYW1lc19ncCA9Z3Bhcihmb250c2l6ZSA9IDApKSAKCnByaW50X3RhYihwbHQgPSBwLHRpdGxlID0gIkhBTExNQVJLX0cyTV9DSEVDS1BPSU5UIikKCmBgYApgYGB7cn0KCmBgYAoKIyBEaXN0YW5jZSBwbG90CmBgYHtyfQp2c2QgPC0gdnN0KGRkcywgYmxpbmQ9RkFMU0UpCnNhbXBsZURpc3RzIDwtIGRpc3QodChhc3NheSh2c2QpKSkKbGlicmFyeSgiUkNvbG9yQnJld2VyIikKc2FtcGxlRGlzdE1hdHJpeCA8LSBhcy5tYXRyaXgoc2FtcGxlRGlzdHMpCmNvbG5hbWVzKHNhbXBsZURpc3RNYXRyaXgpIDwtIE5VTEwKY29sb3JzIDwtIGNvbG9yUmFtcFBhbGV0dGUoIHJldihicmV3ZXIucGFsKDksICJCbHVlcyIpKSApKDI1NSkKcGhlYXRtYXAoc2FtcGxlRGlzdE1hdHJpeCwKICAgICAgICAgY2x1c3RlcmluZ19kaXN0YW5jZV9yb3dzPXNhbXBsZURpc3RzLAogICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX2NvbHM9c2FtcGxlRGlzdHMsCiAgICAgICAgIGNvbD1jb2xvcnMpCmBgYAo8c2NyaXB0IHNyYz0iaHR0cHM6Ly9oeXBvdGhlcy5pcy9lbWJlZC5qcyIgYXN5bmM+PC9zY3JpcHQ+Cgo=