Functions
Data
genesets <- msigdb_download("Homo sapiens",category="H") %>% append( msigdb_download("Homo sapiens",category="C2",subcategory = "CP:KEGG"))
xeno_bulk = read.table(
file = "/sci/labs/yotamd/lab_share/lung_sc/bulk/RoxaOsi/Oct23/star/mm39unmapped_noMTGLKI_tpm.txt",
sep = "\t",
header = TRUE
)
rownames(xeno_bulk) = make.unique(xeno_bulk[,"gene_name",drop=T])
xeno_bulk = xeno_bulk[,8:19]
names (xeno_bulk) = gsub(pattern = "_mm.*$",replacement = "",x = names (xeno_bulk))
xeno_bulk = xeno_bulk[,c("M2_ctrl", "M21_ctrl", "M36_ctrl", "M14_osi", "M33_osi", "M14_2_osi",
"M20_roxa", "M30_roxa", "M31_roxa", "M3_combo", "M26_combo",
"M32_combo")]
cell.labels = names(xeno_bulk)
condition = str_extract(cell.labels, "osi|combo|ctrl|roxa")
metadata = data.frame(condition = condition, row.names = colnames(xeno_bulk))
library(DESeq2)
dds <- DESeqDataSetFromMatrix(countData = round(xeno_bulk),
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
PCA
nrow(dds)
[1] 60580
dds1 <- dds[ rowSums(counts(dds)) >= 3, ]
nrow(dds1)
[1] 21163
vst = vst(dds, blind=FALSE)
library("ggfortify")
PCAdata <- prcomp(t(assay(vst)))
autoplot(PCAdata, data = metadata,colour = "condition",label = FALSE, main="PCA") # Show dots

DESeq
dds <- DESeq(dds)
estimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
dds_xeno = dds
dds = dds_xeno
Top variable genes
heatmap
genes <- head(order(rowVars(assay(dds)), decreasing = TRUE), 1000)
mat <- xeno_bulk[ 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 = "TPM Z-score",row_names_gp = gpar(fontsize = 0))

Expression heatmap
# select the 50 most differentially expressed genes
genes <- c("DUSP6")
mat <- xeno_bulk[ genes, ]
mat <- t(scale(t(mat)))
anno <- as.data.frame(mat)
library(ComplexHeatmap)
library(ggplot2)
Heatmap(mat, cluster_rows = F, cluster_columns = F, column_labels = colnames(anno), name = "TPM Z-score")

genes <- hif_targets
mat <- xeno_bulk[genes, ] %>% filter(rowSums(across(where(is.numeric)))!=0)
mat <- t(scale(t(mat)))
anno <- as.data.frame(mat)
Heatmap(mat, cluster_rows = T, cluster_columns = F, column_labels = colnames(anno), name = "TPM Z-score",column_title = "HIF targets",row_names_gp = gpar(fontsize = 8))

genes <- genesets$HALLMARK_G2M_CHECKPOINT
mat <- xeno_bulk[genes, ] %>% filter(rowSums(across(where(is.numeric)))!=0)
mat <- t(scale(t(mat)))
anno <- as.data.frame(mat)
Heatmap(mat, cluster_rows = T, cluster_columns = F, column_labels = colnames(anno), name = "TPM Z-score",column_title = "G2M targets",row_names_gp = gpar(fontsize = 0))

genes <- genesets$HALLMARK_HYPOXIA
mat <- xeno_bulk[genes, ] %>% filter(rowSums(across(where(is.numeric)))!=0)
mat <- t(scale(t(mat)))
anno <- as.data.frame(mat)
Heatmap(mat, cluster_rows = T, cluster_columns = F, column_labels = colnames(anno), name = "TPM Z-score",column_title = "Hallmark Hypoxia",row_names_gp = gpar(fontsize = 0))

NA
NA
DEG
cpVSop <- results(dds,contrast = c("condition","combo","osi")) %>% 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)
library(DT)
roxa_vs_ctrl = results(dds,contrast = c("condition","roxa","ctrl")) %>% as.data.frame()
combo_vs_ctrl = results(dds,contrast = c("condition","combo","ctrl")) %>% as.data.frame()
osi_vs_ctrl = results(dds,contrast = c("condition","osi","ctrl")) %>% as.data.frame()
combo_vs_roxa = results(dds,contrast = c("condition","combo","roxa")) %>% as.data.frame()
osi_vs_roxa = results(dds,contrast = c("condition","osi","roxa")) %>% as.data.frame()
combo_vs_osi <- results(dds,contrast = c("condition","combo","osi")) %>% as.data.frame()
dt1 = datatable(roxa_vs_ctrl%>% filter(padj <0.1) ,caption = "significant roxa VS ctrl")
dt2= datatable(combo_vs_ctrl %>% filter(padj <0.1),caption = "significant combo vs ctrl")
dt3 = datatable(osi_vs_ctrl %>% filter(padj <0.1),caption = "significant osi_vs_ctrl")
dt4 =datatable(combo_vs_roxa %>% filter(padj <0.1),caption = "significant combo_vs_roxa")
dt5 =datatable(osi_vs_roxa %>% filter(padj <0.1),caption = "significant osi_vs_roxa")
dt6 =datatable(combo_vs_osi %>% filter(padj <0.1),caption = "significant combo VS osi")
print_tab(plt = dt1,title = "significant roxa VS ctrl")
significant roxa VS ctrl
print_tab(plt = dt2,title = "significant combo vs ctrl")
significant combo vs ctrl
print_tab(plt = dt3,title = "significant osi VS ctrl")
significant osi VS ctrl
print_tab(plt = dt4,title = "significant combo VS roxa")
significant combo VS roxa
print_tab(plt = dt5,title = "significant osi VS roxa")
significant osi VS roxa
print_tab(plt = dt6,title = "significant combo VS osi")
significant combo VS osi
NA
all_comparision = list(combo_vs_ctrl = combo_vs_ctrl,osi_vs_ctrl = osi_vs_ctrl,combo_vs_roxa = combo_vs_roxa,osi_vs_roxa= osi_vs_roxa)
for (i in 1:length(all_comparision)) {
comparision = all_comparision[[i]]
comparision = comparision[order(comparision$log2FoldChange, comparision$padj,decreasing = T),] #order by FC, ties bt padj
ranked_vec = comparision[,"log2FoldChange"]%>% setNames(rownames(comparision)) %>% 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)
plt2 = plt$dn+ aes(size=abs(nes))
print_tab(plt1+plt2,title = names(all_comparision)[i])
}
Warning in preparePathwaysAndStats(pathways, stats, minSize, maxSize,
gseaParam, : There are ties in the preranked stats (15.08% of the list).
The order of those tied genes will be arbitrary, which may produce
unexpected results. ## combo_vs_ctrl {.unnumbered }

Warning in preparePathwaysAndStats(pathways, stats, minSize, maxSize,
gseaParam, : There are ties in the preranked stats (20.08% of the list).
The order of those tied genes will be arbitrary, which may produce
unexpected results. ## osi_vs_ctrl {.unnumbered }

Warning in preparePathwaysAndStats(pathways, stats, minSize, maxSize,
gseaParam, : There are ties in the preranked stats (12.39% of the list).
The order of those tied genes will be arbitrary, which may produce
unexpected results. ## combo_vs_roxa {.unnumbered }

Warning in preparePathwaysAndStats(pathways, stats, minSize, maxSize,
gseaParam, : There are ties in the preranked stats (18.54% of the list).
The order of those tied genes will be arbitrary, which may produce
unexpected results. ## osi_vs_roxa {.unnumbered }

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

xeno_bulk_no_mouse = read.table(
file = "/sci/labs/yotamd/lab_share/lung_sc/bulk/RoxaOsi/Oct23/star/mm39unmapped_noMTGLKI_tpm.txt",
sep = "\t",
header = TRUE
)
rownames(xeno_bulk_no_mouse) = make.unique(xeno_bulk_no_mouse[,"gene_name",drop=T])
xeno_bulk_no_mouse = xeno_bulk_no_mouse[,8:19]
names (xeno_bulk_no_mouse) = gsub(pattern = "_mm.*$",replacement = "",x = names (xeno_bulk_no_mouse))
xeno_bulk_no_mouse = xeno_bulk_no_mouse[,c("M2_ctrl", "M21_ctrl", "M36_ctrl", "M14_osi", "M33_osi", "M14_2_osi",
"M20_roxa", "M30_roxa", "M31_roxa", "M3_combo", "M26_combo",
"M32_combo")]
colnames(xeno_bulk_no_mouse) = paste0(colnames(xeno_bulk_no_mouse),"_noMouse")
xeno_bulk = read.table(
file = "/sci/labs/yotamd/lab_share/avishai.wizel/R_projects/EGFR/Data/osiRoxa_bulk/Oct23/03.Result_X202SC23082844-Z01-F001_Homo_sapiens/Result_X202SC23082844-Z01-F001_Homo_sapiens/3.Quant/1.Count/gene_fpkm.xls",
sep = "\t",
header = TRUE
)
rownames(xeno_bulk) = make.unique(xeno_bulk[,"gene_name",drop=T])
xeno_bulk = xeno_bulk[,26:37]
common_genes = intersect(rownames(xeno_bulk),rownames(xeno_bulk_no_mouse))
xeno_bulk_comp = cbind(xeno_bulk[common_genes,],xeno_bulk_no_mouse[common_genes,])
xeno_comp_cor = cor(xeno_bulk_comp)
ComplexHeatmap::Heatmap(xeno_comp_cor)

LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19kZXB0aDogMQotLS0KCgoKIyBGdW5jdGlvbnMKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CmBgYAoKIyBEYXRhCgpgYGB7cn0KZ2VuZXNldHMgPC0gbXNpZ2RiX2Rvd25sb2FkKCJIb21vIHNhcGllbnMiLGNhdGVnb3J5PSJIIikgJT4lIGFwcGVuZCggbXNpZ2RiX2Rvd25sb2FkKCJIb21vIHNhcGllbnMiLGNhdGVnb3J5PSJDMiIsc3ViY2F0ZWdvcnkgPSAiQ1A6S0VHRyIpKQp4ZW5vX2J1bGsgPSByZWFkLnRhYmxlKAogIGZpbGUgPSAiL3NjaS9sYWJzL3lvdGFtZC9sYWJfc2hhcmUvbHVuZ19zYy9idWxrL1JveGFPc2kvT2N0MjMvc3Rhci9tbTM5dW5tYXBwZWRfbm9NVEdMS0lfdHBtLnR4dCIsCiAgc2VwID0gIlx0IiwKICBoZWFkZXIgPSBUUlVFCikKcm93bmFtZXMoeGVub19idWxrKSA9IG1ha2UudW5pcXVlKHhlbm9fYnVsa1ssImdlbmVfbmFtZSIsZHJvcD1UXSkKeGVub19idWxrID0geGVub19idWxrWyw4OjE5XQpuYW1lcyAoeGVub19idWxrKSA9IGdzdWIocGF0dGVybiA9ICJfbW0uKiQiLHJlcGxhY2VtZW50ID0gIiIseCA9IG5hbWVzICh4ZW5vX2J1bGspKQp4ZW5vX2J1bGsgPSB4ZW5vX2J1bGtbLGMoIk0yX2N0cmwiLCAiTTIxX2N0cmwiLCAiTTM2X2N0cmwiLCAiTTE0X29zaSIsICJNMzNfb3NpIiwgIk0xNF8yX29zaSIsIAoiTTIwX3JveGEiLCAiTTMwX3JveGEiLCAiTTMxX3JveGEiLCAiTTNfY29tYm8iLCAiTTI2X2NvbWJvIiwgCiJNMzJfY29tYm8iKV0KYGBgCgpgYGB7cn0KY2VsbC5sYWJlbHMgPSBuYW1lcyh4ZW5vX2J1bGspCmNvbmRpdGlvbiA9IHN0cl9leHRyYWN0KGNlbGwubGFiZWxzLCAib3NpfGNvbWJvfGN0cmx8cm94YSIpCm1ldGFkYXRhID0gZGF0YS5mcmFtZShjb25kaXRpb24gPSBjb25kaXRpb24sIHJvdy5uYW1lcyA9IGNvbG5hbWVzKHhlbm9fYnVsaykpCmBgYAoKYGBge3J9CmxpYnJhcnkoREVTZXEyKQpkZHMgPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeChjb3VudERhdGEgPSByb3VuZCh4ZW5vX2J1bGspLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xEYXRhID0gbWV0YWRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2lnbiA9IH5jb25kaXRpb24pCmBgYAoKCiMgUENBCmBgYHtyfQpucm93KGRkcykKZGRzMSA8LSBkZHNbIHJvd1N1bXMoY291bnRzKGRkcykpID49IDMsIF0KbnJvdyhkZHMxKQpgYGAKCmBgYHtyfQp2c3QgPSB2c3QoZGRzLCBibGluZD1GQUxTRSkKYGBgCgpgYGB7cn0KbGlicmFyeSgiZ2dmb3J0aWZ5IikKUENBZGF0YSA8LSBwcmNvbXAodChhc3NheSh2c3QpKSkKYXV0b3Bsb3QoUENBZGF0YSwgZGF0YSA9IG1ldGFkYXRhLGNvbG91ciA9ICJjb25kaXRpb24iLGxhYmVsID0gRkFMU0UsIG1haW49IlBDQSIpICMgU2hvdyBkb3RzCgpgYGAKIyBERVNlcQpgYGB7cn0KZGRzIDwtIERFU2VxKGRkcykKZGRzX3hlbm8gPSBkZHMKCmBgYAoKYGBge3J9CmRkcyA9IGRkc194ZW5vCmBgYAoKCgojIFRvcCB2YXJpYWJsZSBnZW5lcyBoZWF0bWFwCmBgYHtyfQpnZW5lcyA8LSBoZWFkKG9yZGVyKHJvd1ZhcnMoYXNzYXkoZGRzKSksIGRlY3JlYXNpbmcgPSBUUlVFKSwgMTAwMCkKCm1hdCA8LSB4ZW5vX2J1bGtbIGdlbmVzLCBdCm1hdCA8LSB0KHNjYWxlKHQobWF0KSkpCmFubm8gPC0gYXMuZGF0YS5mcmFtZShtYXQpCgpsaWJyYXJ5KENvbXBsZXhIZWF0bWFwKSAKbGlicmFyeShnZ3Bsb3QyKSAKSGVhdG1hcChtYXQsIGNsdXN0ZXJfcm93cyA9IFQsIGNsdXN0ZXJfY29sdW1ucyA9IEYsIGNvbHVtbl9sYWJlbHMgPSBjb2xuYW1lcyhhbm5vKSwgbmFtZSA9ICJUUE0gWi1zY29yZSIscm93X25hbWVzX2dwID0gZ3Bhcihmb250c2l6ZSA9IDApKSAKYGBgCgojIEV4cHJlc3Npb24gaGVhdG1hcCB7LnRhYnNldH0KCmBgYHtyIGZpZy5oZWlnaHQ9Nn0KIyBzZWxlY3QgdGhlIDUwIG1vc3QgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIApnZW5lcyA8LSBjKCJEVVNQNiIpCm1hdCA8LSB4ZW5vX2J1bGtbIGdlbmVzLCBdCm1hdCA8LSB0KHNjYWxlKHQobWF0KSkpCmFubm8gPC0gYXMuZGF0YS5mcmFtZShtYXQpCgpsaWJyYXJ5KENvbXBsZXhIZWF0bWFwKSAKbGlicmFyeShnZ3Bsb3QyKSAKSGVhdG1hcChtYXQsIGNsdXN0ZXJfcm93cyA9IEYsIGNsdXN0ZXJfY29sdW1ucyA9IEYsIGNvbHVtbl9sYWJlbHMgPSBjb2xuYW1lcyhhbm5vKSwgbmFtZSA9ICJUUE0gWi1zY29yZSIpIAoKZ2VuZXMgPC0gaGlmX3RhcmdldHMKbWF0IDwtIHhlbm9fYnVsa1tnZW5lcywgXSAlPiUgZmlsdGVyKHJvd1N1bXMoYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpKSkhPTApCm1hdCA8LSB0KHNjYWxlKHQobWF0KSkpCmFubm8gPC0gYXMuZGF0YS5mcmFtZShtYXQpCgogCkhlYXRtYXAobWF0LCBjbHVzdGVyX3Jvd3MgPSBULCBjbHVzdGVyX2NvbHVtbnMgPSBGLCBjb2x1bW5fbGFiZWxzID0gY29sbmFtZXMoYW5ubyksIG5hbWUgPSAiVFBNIFotc2NvcmUiLGNvbHVtbl90aXRsZSA9ICJISUYgdGFyZ2V0cyIscm93X25hbWVzX2dwID0gZ3Bhcihmb250c2l6ZSA9IDgpKSAKCgpnZW5lcyA8LSBnZW5lc2V0cyRIQUxMTUFSS19HMk1fQ0hFQ0tQT0lOVAptYXQgPC0geGVub19idWxrW2dlbmVzLCBdICU+JSBmaWx0ZXIocm93U3VtcyhhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYykpKSE9MCkKbWF0IDwtIHQoc2NhbGUodChtYXQpKSkKYW5ubyA8LSBhcy5kYXRhLmZyYW1lKG1hdCkKCiAKSGVhdG1hcChtYXQsIGNsdXN0ZXJfcm93cyA9IFQsIGNsdXN0ZXJfY29sdW1ucyA9IEYsIGNvbHVtbl9sYWJlbHMgPSBjb2xuYW1lcyhhbm5vKSwgbmFtZSA9ICJUUE0gWi1zY29yZSIsY29sdW1uX3RpdGxlID0gIkcyTSB0YXJnZXRzIixyb3dfbmFtZXNfZ3AgPSBncGFyKGZvbnRzaXplID0gMCkpIAoKZ2VuZXMgPC0gZ2VuZXNldHMkSEFMTE1BUktfSFlQT1hJQQptYXQgPC0geGVub19idWxrW2dlbmVzLCBdICU+JSBmaWx0ZXIocm93U3VtcyhhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYykpKSE9MCkKbWF0IDwtIHQoc2NhbGUodChtYXQpKSkKYW5ubyA8LSBhcy5kYXRhLmZyYW1lKG1hdCkKCiAKSGVhdG1hcChtYXQsIGNsdXN0ZXJfcm93cyA9IFQsIGNsdXN0ZXJfY29sdW1ucyA9IEYsIGNvbHVtbl9sYWJlbHMgPSBjb2xuYW1lcyhhbm5vKSwgbmFtZSA9ICJUUE0gWi1zY29yZSIsY29sdW1uX3RpdGxlID0gIkhhbGxtYXJrIEh5cG94aWEiLHJvd19uYW1lc19ncCA9IGdwYXIoZm9udHNpemUgPSAwKSkgCgoKYGBgCgojIERFRyB7LnRhYnNldH0KYGBge3J9CmNwVlNvcCA8LSByZXN1bHRzKGRkcyxjb250cmFzdCA9IGMoImNvbmRpdGlvbiIsImNvbWJvIiwib3NpIikpICAlPiUgYXMuZGF0YS5mcmFtZSgpCnJveGFWU2N0cmwgPC0gcmVzdWx0cyhkZHMsY29udHJhc3QgPSBjKCJjb25kaXRpb24iLCJyb3hhIiwiY3RybCIpKSAgJT4lIGFzLmRhdGEuZnJhbWUoKQpkaWZmX2dlbmVzID0gZGF0YS5mcmFtZShyb3cubmFtZXMgPSByb3duYW1lcyhjcFZTb3ApLCBjcFZTb3BfRkMgPSBjcFZTb3AkbG9nMkZvbGRDaGFuZ2Uscm94YVZTY3RybF9GQyA9IHJveGFWU2N0cmwkbG9nMkZvbGRDaGFuZ2UsICBjcFZTb3BfcGFkaiA9IGNwVlNvcCRwYWRqKQpgYGAKCmBgYHtyIHJlc3VsdHM9J2FzaXMnfQpsaWJyYXJ5KERUKQpyb3hhX3ZzX2N0cmwgPSByZXN1bHRzKGRkcyxjb250cmFzdCA9IGMoImNvbmRpdGlvbiIsInJveGEiLCJjdHJsIikpICAlPiUgYXMuZGF0YS5mcmFtZSgpCmNvbWJvX3ZzX2N0cmwgPSByZXN1bHRzKGRkcyxjb250cmFzdCA9IGMoImNvbmRpdGlvbiIsImNvbWJvIiwiY3RybCIpKSAgJT4lIGFzLmRhdGEuZnJhbWUoKQpvc2lfdnNfY3RybCA9IHJlc3VsdHMoZGRzLGNvbnRyYXN0ID0gYygiY29uZGl0aW9uIiwib3NpIiwiY3RybCIpKSAgJT4lIGFzLmRhdGEuZnJhbWUoKQoKY29tYm9fdnNfcm94YSA9IHJlc3VsdHMoZGRzLGNvbnRyYXN0ID0gYygiY29uZGl0aW9uIiwiY29tYm8iLCJyb3hhIikpICAlPiUgYXMuZGF0YS5mcmFtZSgpCm9zaV92c19yb3hhID0gcmVzdWx0cyhkZHMsY29udHJhc3QgPSBjKCJjb25kaXRpb24iLCJvc2kiLCJyb3hhIikpICAlPiUgYXMuZGF0YS5mcmFtZSgpCmNvbWJvX3ZzX29zaSA8LSByZXN1bHRzKGRkcyxjb250cmFzdCA9IGMoImNvbmRpdGlvbiIsImNvbWJvIiwib3NpIikpICAlPiUgYXMuZGF0YS5mcmFtZSgpCgpkdDEgPSBkYXRhdGFibGUocm94YV92c19jdHJsJT4lIGZpbHRlcihwYWRqIDwwLjEpICAsY2FwdGlvbiA9ICJzaWduaWZpY2FudCByb3hhIFZTIGN0cmwiKQpkdDI9IGRhdGF0YWJsZShjb21ib192c19jdHJsICU+JSBmaWx0ZXIocGFkaiA8MC4xKSxjYXB0aW9uID0gInNpZ25pZmljYW50IGNvbWJvIHZzIGN0cmwiKQpkdDMgPSBkYXRhdGFibGUob3NpX3ZzX2N0cmwgJT4lIGZpbHRlcihwYWRqIDwwLjEpLGNhcHRpb24gPSAic2lnbmlmaWNhbnQgb3NpX3ZzX2N0cmwiKQpkdDQgPWRhdGF0YWJsZShjb21ib192c19yb3hhICU+JSBmaWx0ZXIocGFkaiA8MC4xKSxjYXB0aW9uID0gInNpZ25pZmljYW50IGNvbWJvX3ZzX3JveGEiKQpkdDUgPWRhdGF0YWJsZShvc2lfdnNfcm94YSAlPiUgZmlsdGVyKHBhZGogPDAuMSksY2FwdGlvbiA9ICJzaWduaWZpY2FudCBvc2lfdnNfcm94YSIpCmR0NiA9ZGF0YXRhYmxlKGNvbWJvX3ZzX29zaSAlPiUgZmlsdGVyKHBhZGogPDAuMSksY2FwdGlvbiA9ICJzaWduaWZpY2FudCBjb21ibyBWUyBvc2kiKQpwcmludF90YWIocGx0ID0gZHQxLHRpdGxlID0gInNpZ25pZmljYW50IHJveGEgVlMgY3RybCIpCnByaW50X3RhYihwbHQgPSBkdDIsdGl0bGUgPSAic2lnbmlmaWNhbnQgY29tYm8gdnMgY3RybCIpCnByaW50X3RhYihwbHQgPSBkdDMsdGl0bGUgPSAic2lnbmlmaWNhbnQgb3NpIFZTIGN0cmwiKQpwcmludF90YWIocGx0ID0gZHQ0LHRpdGxlID0gInNpZ25pZmljYW50IGNvbWJvIFZTIHJveGEiKQpwcmludF90YWIocGx0ID0gZHQ1LHRpdGxlID0gInNpZ25pZmljYW50IG9zaSBWUyByb3hhIikKcHJpbnRfdGFiKHBsdCA9IGR0Nix0aXRsZSA9ICJzaWduaWZpY2FudCBjb21ibyBWUyBvc2kiKQpgYGAKYGBge3IgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTMsIHJlc3VsdHM9J2FzaXMnfQphbGxfY29tcGFyaXNpb24gPSBsaXN0KGNvbWJvX3ZzX2N0cmwgPSBjb21ib192c19jdHJsLG9zaV92c19jdHJsID0gb3NpX3ZzX2N0cmwsY29tYm9fdnNfcm94YSA9IGNvbWJvX3ZzX3JveGEsb3NpX3ZzX3JveGE9IG9zaV92c19yb3hhKQpmb3IgKGkgaW4gMTpsZW5ndGgoYWxsX2NvbXBhcmlzaW9uKSkgewogIGNvbXBhcmlzaW9uID0gYWxsX2NvbXBhcmlzaW9uW1tpXV0KICBjb21wYXJpc2lvbiA9IGNvbXBhcmlzaW9uW29yZGVyKGNvbXBhcmlzaW9uJGxvZzJGb2xkQ2hhbmdlLCBjb21wYXJpc2lvbiRwYWRqLGRlY3JlYXNpbmcgPSBUKSxdICNvcmRlciBieSBGQywgdGllcyBidCBwYWRqCnJhbmtlZF92ZWMgPSBjb21wYXJpc2lvblssImxvZzJGb2xkQ2hhbmdlIl0lPiUgc2V0TmFtZXMocm93bmFtZXMoY29tcGFyaXNpb24pKSAlPiUgbmEub21pdCgpICMgbWFrZSBuYW1lZCB2ZWN0b3IKCmh5cF9vYmogPC0gaHlwZVJfZmdzZWEocmFua2VkX3ZlYywgZ2VuZXNldHMsIHVwX29ubHkgPSBGKQpwbHQgPSBoeXBfZG90cyhoeXBfb2JqLG1lcmdlID0gRikKcGx0MSA9IHBsdCR1cCsgYWVzKHNpemU9bmVzKQpwbHQyID0gcGx0JGRuKyBhZXMoc2l6ZT1hYnMobmVzKSkKcHJpbnRfdGFiKHBsdDErcGx0Mix0aXRsZSA9ICAgbmFtZXMoYWxsX2NvbXBhcmlzaW9uKVtpXSkKfQoKYGBgCgoKYGBge3J9CnZzZCA8LSB2c3QoZGRzLCBibGluZD1GQUxTRSkKc2FtcGxlRGlzdHMgPC0gZGlzdCh0KGFzc2F5KHZzZCkpKQpsaWJyYXJ5KCJSQ29sb3JCcmV3ZXIiKQpzYW1wbGVEaXN0TWF0cml4IDwtIGFzLm1hdHJpeChzYW1wbGVEaXN0cykKY29sbmFtZXMoc2FtcGxlRGlzdE1hdHJpeCkgPC0gTlVMTApjb2xvcnMgPC0gY29sb3JSYW1wUGFsZXR0ZSggcmV2KGJyZXdlci5wYWwoOSwgIkJsdWVzIikpICkoMjU1KQpwaGVhdG1hcChzYW1wbGVEaXN0TWF0cml4LAogICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX3Jvd3M9c2FtcGxlRGlzdHMsCiAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2VfY29scz1zYW1wbGVEaXN0cywKICAgICAgICAgY29sPWNvbG9ycykKYGBgCgpgYGB7cn0KeGVub19idWxrX25vX21vdXNlID0gcmVhZC50YWJsZSgKICBmaWxlID0gIi9zY2kvbGFicy95b3RhbWQvbGFiX3NoYXJlL2x1bmdfc2MvYnVsay9Sb3hhT3NpL09jdDIzL3N0YXIvbW0zOXVubWFwcGVkX25vTVRHTEtJX3RwbS50eHQiLAogIHNlcCA9ICJcdCIsCiAgaGVhZGVyID0gVFJVRQopCnJvd25hbWVzKHhlbm9fYnVsa19ub19tb3VzZSkgPSBtYWtlLnVuaXF1ZSh4ZW5vX2J1bGtfbm9fbW91c2VbLCJnZW5lX25hbWUiLGRyb3A9VF0pCnhlbm9fYnVsa19ub19tb3VzZSA9IHhlbm9fYnVsa19ub19tb3VzZVssODoxOV0KbmFtZXMgKHhlbm9fYnVsa19ub19tb3VzZSkgPSBnc3ViKHBhdHRlcm4gPSAiX21tLiokIixyZXBsYWNlbWVudCA9ICIiLHggPSBuYW1lcyAoeGVub19idWxrX25vX21vdXNlKSkKeGVub19idWxrX25vX21vdXNlID0geGVub19idWxrX25vX21vdXNlWyxjKCJNMl9jdHJsIiwgIk0yMV9jdHJsIiwgIk0zNl9jdHJsIiwgIk0xNF9vc2kiLCAiTTMzX29zaSIsICJNMTRfMl9vc2kiLCAKIk0yMF9yb3hhIiwgIk0zMF9yb3hhIiwgIk0zMV9yb3hhIiwgIk0zX2NvbWJvIiwgIk0yNl9jb21ibyIsIAoiTTMyX2NvbWJvIildCmNvbG5hbWVzKHhlbm9fYnVsa19ub19tb3VzZSkgPSBwYXN0ZTAoY29sbmFtZXMoeGVub19idWxrX25vX21vdXNlKSwiX25vTW91c2UiKQp4ZW5vX2J1bGsgPSByZWFkLnRhYmxlKAogIGZpbGUgPSAiL3NjaS9sYWJzL3lvdGFtZC9sYWJfc2hhcmUvYXZpc2hhaS53aXplbC9SX3Byb2plY3RzL0VHRlIvRGF0YS9vc2lSb3hhX2J1bGsvT2N0MjMvMDMuUmVzdWx0X1gyMDJTQzIzMDgyODQ0LVowMS1GMDAxX0hvbW9fc2FwaWVucy9SZXN1bHRfWDIwMlNDMjMwODI4NDQtWjAxLUYwMDFfSG9tb19zYXBpZW5zLzMuUXVhbnQvMS5Db3VudC9nZW5lX2Zwa20ueGxzIiwKICBzZXAgPSAiXHQiLAogIGhlYWRlciA9IFRSVUUKKQpyb3duYW1lcyh4ZW5vX2J1bGspID0gbWFrZS51bmlxdWUoeGVub19idWxrWywiZ2VuZV9uYW1lIixkcm9wPVRdKQp4ZW5vX2J1bGsgPSB4ZW5vX2J1bGtbLDI2OjM3XQoKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD04fQpjb21tb25fZ2VuZXMgPSBpbnRlcnNlY3Qocm93bmFtZXMoeGVub19idWxrKSxyb3duYW1lcyh4ZW5vX2J1bGtfbm9fbW91c2UpKQp4ZW5vX2J1bGtfY29tcCA9IGNiaW5kKHhlbm9fYnVsa1tjb21tb25fZ2VuZXMsXSx4ZW5vX2J1bGtfbm9fbW91c2VbY29tbW9uX2dlbmVzLF0pCnhlbm9fY29tcF9jb3IgPSBjb3IoeGVub19idWxrX2NvbXApCgpDb21wbGV4SGVhdG1hcDo6SGVhdG1hcCh4ZW5vX2NvbXBfY29yKQpgYGAKCgoKPHNjcmlwdCBzcmM9Imh0dHBzOi8vaHlwb3RoZXMuaXMvZW1iZWQuanMiIGFzeW5jPjwvc2NyaXB0PgoK