0.1 Parameters

suffix = ""
data_to_read = ""

0.2 functions

source_from_github(repositoy = "DEG_functions",version = "0.2.24")
source_from_github(repositoy = "HMSC_functions",version = "0.1.12",script_name = "functions.R")
source_from_github(repositoy = "cNMF_functions",version = "0.3.72",script_name = "cnmf_function_Harmony.R")

no_neg <- function(x) {
  x = x + abs(min(x))
  x
}

sum_2_one <- function(x) {
  x =x/sum(x)
  x
}

0.3 Data

0.4 Load object

from cnmf import cNMF
import pickle
nfeatures = "2K"
f = open('./Data/cNMF/HMSC_cNMF_' + nfeatures+ 'vargenes/cnmf_obj.pckl', 'rb')
cnmf_obj = pickle.load(f)
f.close()
selected_k = 4
density_threshold = 0.1
cnmf_obj.consensus(k=selected_k, density_threshold=density_threshold,show_clustering=True)
usage_norm, gep_scores, gep_tpm, topgenes = cnmf_obj.load_results(K=selected_k, density_threshold=density_threshold)
gep_scores = py$gep_scores
gep_tpm = py$gep_tpm
all_metagenes= py$usage_norm

1 Hallmark Enrichment analysis by top 200 genes of each program

plt_list = list()
for (i in 1:ncol(gep_scores)) {
  top_genes = gep_scores  %>%  arrange(desc(gep_scores[i])) #sort by score a
  top = head(rownames(top_genes),200) #take top top_genes_num
  res = genes_vec_enrichment(genes = top,background = rownames(gep_scores),homer = T,title = 
                    i,silent = T,return_all = T)
   
  plt_list[[i]] = res$plt
}
gridExtra::grid.arrange(grobs = plt_list)

2 Hallmark + canonical Enrichment analysis by top 200 genes of each program


canonical_pathways = msigdbr(species = "Homo sapiens", category = "C2") %>% dplyr::filter(gs_subcat != "CGP") %>%  dplyr::distinct(gs_name, gene_symbol) 

plt_list = list()
for (i in 1:ncol(gep_scores)) {
  top_genes = gep_scores  %>%  arrange(desc(gep_scores[i])) #sort by score a
  top = head(rownames(top_genes),200) #take top top_genes_num
  res = genes_vec_enrichment(genes = top,background = rownames(gep_scores),homer = T,title = 
                    i,silent = T,return_all = T,custom_pathways = canonical_pathways)
   
  plt_list[[i]] = res$plt
}
gridExtra::grid.arrange(grobs = plt_list)

3 Expression by scores from cnmf

# Make metagene names
for (i in 1:ncol(all_metagenes)) {
  colnames(all_metagenes)[i] = "metagene." %>% paste0(i)
}

#add each metagene to metadata
for (i in 1:ncol(all_metagenes)) {
  metage_metadata = all_metagenes %>% select(i)
  acc1_cancer_cells = AddMetaData(object = acc1_cancer_cells,metadata = metage_metadata)
}

print_tab(plt = 
            FeaturePlot(object = acc1_cancer_cells,features = colnames(all_metagenes))
,title = "expression",subtitle_num = 2)

expression

print_tab(
  plt = FeaturePlot(object = acc1_cancer_cells,features = colnames(all_metagenes),max.cutoff = 0.05)
          ,title = "max.cutoff = 0.05",subtitle_num = 2)

max.cutoff = 0.05

NA

4 Expression by scores from cnmf + Z score



all_metagenes_norm= scale(all_metagenes) %>% as.data.frame()
# Make metagene names
for (i in 1:ncol(all_metagenes_norm)) {
  colnames(all_metagenes_norm)[i] = "metagene." %>% paste0(i)
}

#add each metagene to metadata
for (i in 1:ncol(all_metagenes_norm)) {
  metage_metadata = all_metagenes_norm %>% select(i)
  acc1_cancer_cells = AddMetaData(object = acc1_cancer_cells,metadata = metage_metadata)
}

print_tab(plt = 
            FeaturePlot(object = acc1_cancer_cells,features = colnames(all_metagenes))
,title = "expression",subtitle_num = 2)

expression

print_tab(
  plt = FeaturePlot(object = acc1_cancer_cells,features = colnames(all_metagenes),max.cutoff = 0.5)
          ,title = "max.cutoff = 0.5",subtitle_num = 2)

max.cutoff = 0.5

NA

5 Expression by coefficients inversion * expression


all_metagenes_inversed  = expression_inversion(gep_scores = gep_scores %>% as.matrix() ,dataset = acc1_cancer_cells) %>% t() %>% as.data.frame()

# Make metagene names
for (i in 1:ncol(all_metagenes_inversed)) {
  colnames(all_metagenes_inversed)[i] = "metagene." %>% paste0(i)
}

#add each metagene to metadata
for (i in 1:ncol(all_metagenes_inversed)) {
  metage_metadata = all_metagenes_inversed %>% select(i)
  acc1_cancer_cells = AddMetaData(object = acc1_cancer_cells,metadata = metage_metadata)
}

FeaturePlot(object = acc1_cancer_cells,features = colnames(all_metagenes_inversed))

6 Expression by (coefficients inversion sum to 1) * expression

gep_scores_norm = apply(gep_scores, 2, no_neg)
gep_scores_norm = apply(gep_scores_norm, 2, sum_2_one)


all_metagenes_inversed  = expression_inversion(gep_scores = gep_scores_norm ,dataset = acc1_cancer_cells) %>% t() %>% as.data.frame()

# Make metagene names
for (i in 1:ncol(all_metagenes_inversed)) {
  colnames(all_metagenes_inversed)[i] = "metagene." %>% paste0(i)
}

#add each metagene to metadata
for (i in 1:ncol(all_metagenes_inversed)) {
  metage_metadata = all_metagenes_inversed %>% select(i)
  acc1_cancer_cells = AddMetaData(object = acc1_cancer_cells,metadata = metage_metadata)
}

print_tab(plt = 
            FeaturePlot(object = acc1_cancer_cells,features = colnames(all_metagenes))
,title = "expression",subtitle_num = 2)

expression

print_tab(
  plt = FeaturePlot(object = acc1_cancer_cells,features = colnames(all_metagenes),max.cutoff = 750)
          ,title = "max.cutoff = 750",subtitle_num = 2)

max.cutoff = 750

NA

7 Expression by coefficients sum to 1 * expression

gep_scores_norm = apply(gep_scores, 2, no_neg)
gep_scores_norm = apply(gep_scores_norm, 2, sum_2_one) %>% as.data.frame()


all_metagenes_mult  = expression_mult(gep_scores = gep_scores_norm ,dataset = acc1_cancer_cells,top_genes = T)

# Make metagene names
for (i in 1:ncol(all_metagenes_mult)) {
  colnames(all_metagenes_mult)[i] = "metagene." %>% paste0(i)
}

#add each metagene to metadata
for (i in 1:ncol(all_metagenes_mult)) {
  metage_metadata = all_metagenes_mult %>% select(i)
  acc1_cancer_cells = AddMetaData(object = acc1_cancer_cells,metadata = metage_metadata)
}

print_tab(plt = 
            FeaturePlot(object = acc1_cancer_cells,features = colnames(all_metagenes))
,title = "expression",subtitle_num = 2)

expression

print_tab(
  plt = FeaturePlot(object = acc1_cancer_cells,features = colnames(all_metagenes),max.cutoff = 50)
          ,title = "max.cutoff = 50",subtitle_num = 2)

max.cutoff = 50

NA

LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19kZXB0aDogMQotLS0KCiMjIFBhcmFtZXRlcnMKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CnN1ZmZpeCA9ICIiCmRhdGFfdG9fcmVhZCA9ICIiCmBgYAoKCiMjIGZ1bmN0aW9ucwoKYGBge3Igd2FybmluZz1GQUxTRX0Kc291cmNlX2Zyb21fZ2l0aHViKHJlcG9zaXRveSA9ICJERUdfZnVuY3Rpb25zIix2ZXJzaW9uID0gIjAuMi4yNCIpCnNvdXJjZV9mcm9tX2dpdGh1YihyZXBvc2l0b3kgPSAiSE1TQ19mdW5jdGlvbnMiLHZlcnNpb24gPSAiMC4xLjEyIixzY3JpcHRfbmFtZSA9ICJmdW5jdGlvbnMuUiIpCnNvdXJjZV9mcm9tX2dpdGh1YihyZXBvc2l0b3kgPSAiY05NRl9mdW5jdGlvbnMiLHZlcnNpb24gPSAiMC4zLjcyIixzY3JpcHRfbmFtZSA9ICJjbm1mX2Z1bmN0aW9uX0hhcm1vbnkuUiIpCgpub19uZWcgPC0gZnVuY3Rpb24oeCkgewogIHggPSB4ICsgYWJzKG1pbih4KSkKICB4Cn0KCnN1bV8yX29uZSA8LSBmdW5jdGlvbih4KSB7CiAgeCA9eC9zdW0oeCkKICB4Cn0KCmBgYAoKIyMgRGF0YQoKYGBge3J9CgpgYGAKCgoKIyMgTG9hZCBvYmplY3QKYGBge3B5dGhvbn0KZnJvbSBjbm1mIGltcG9ydCBjTk1GCmltcG9ydCBwaWNrbGUKbmZlYXR1cmVzID0gIjJLIgpmID0gb3BlbignLi9EYXRhL2NOTUYvSE1TQ19jTk1GXycgKyBuZmVhdHVyZXMrICd2YXJnZW5lcy9jbm1mX29iai5wY2tsJywgJ3JiJykKY25tZl9vYmogPSBwaWNrbGUubG9hZChmKQpmLmNsb3NlKCkKYGBgCgoKYGBge3B5dGhvbn0Kc2VsZWN0ZWRfayA9IDQKZGVuc2l0eV90aHJlc2hvbGQgPSAwLjEKY25tZl9vYmouY29uc2Vuc3VzKGs9c2VsZWN0ZWRfaywgZGVuc2l0eV90aHJlc2hvbGQ9ZGVuc2l0eV90aHJlc2hvbGQsc2hvd19jbHVzdGVyaW5nPVRydWUpCnVzYWdlX25vcm0sIGdlcF9zY29yZXMsIGdlcF90cG0sIHRvcGdlbmVzID0gY25tZl9vYmoubG9hZF9yZXN1bHRzKEs9c2VsZWN0ZWRfaywgZGVuc2l0eV90aHJlc2hvbGQ9ZGVuc2l0eV90aHJlc2hvbGQpCmBgYAoKYGBge3J9CmdlcF9zY29yZXMgPSBweSRnZXBfc2NvcmVzCmdlcF90cG0gPSBweSRnZXBfdHBtCmFsbF9tZXRhZ2VuZXM9IHB5JHVzYWdlX25vcm0KYGBgCgojIEhhbGxtYXJrIEVucmljaG1lbnQgYW5hbHlzaXMgYnkgdG9wIDIwMCBnZW5lcyBvZiBlYWNoIHByb2dyYW0KYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9OCwgcmVzdWx0cz0naGlkZSd9CnBsdF9saXN0ID0gbGlzdCgpCmZvciAoaSBpbiAxOm5jb2woZ2VwX3Njb3JlcykpIHsKICB0b3BfZ2VuZXMgPSBnZXBfc2NvcmVzICAlPiUgIGFycmFuZ2UoZGVzYyhnZXBfc2NvcmVzW2ldKSkgI3NvcnQgYnkgc2NvcmUgYQogIHRvcCA9IGhlYWQocm93bmFtZXModG9wX2dlbmVzKSwyMDApICN0YWtlIHRvcCB0b3BfZ2VuZXNfbnVtCiAgcmVzID0gZ2VuZXNfdmVjX2VucmljaG1lbnQoZ2VuZXMgPSB0b3AsYmFja2dyb3VuZCA9IHJvd25hbWVzKGdlcF9zY29yZXMpLGhvbWVyID0gVCx0aXRsZSA9IAogICAgICAgICAgICAgICAgICAgIGksc2lsZW50ID0gVCxyZXR1cm5fYWxsID0gVCkKICAgCiAgcGx0X2xpc3RbW2ldXSA9IHJlcyRwbHQKfQpncmlkRXh0cmE6OmdyaWQuYXJyYW5nZShncm9icyA9IHBsdF9saXN0KQpgYGAKCiMgSGFsbG1hcmsgKyBjYW5vbmljYWwgRW5yaWNobWVudCBhbmFseXNpcyBieSB0b3AgMjAwIGdlbmVzIG9mIGVhY2ggcHJvZ3JhbQoKYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9OCwgcmVzdWx0cz0naGlkZSd9CgpjYW5vbmljYWxfcGF0aHdheXMgPSBtc2lnZGJyKHNwZWNpZXMgPSAiSG9tbyBzYXBpZW5zIiwgY2F0ZWdvcnkgPSAiQzIiKSAlPiUgZHBseXI6OmZpbHRlcihnc19zdWJjYXQgIT0gIkNHUCIpICU+JSAgZHBseXI6OmRpc3RpbmN0KGdzX25hbWUsIGdlbmVfc3ltYm9sKSAKCnBsdF9saXN0ID0gbGlzdCgpCmZvciAoaSBpbiAxOm5jb2woZ2VwX3Njb3JlcykpIHsKICB0b3BfZ2VuZXMgPSBnZXBfc2NvcmVzICAlPiUgIGFycmFuZ2UoZGVzYyhnZXBfc2NvcmVzW2ldKSkgI3NvcnQgYnkgc2NvcmUgYQogIHRvcCA9IGhlYWQocm93bmFtZXModG9wX2dlbmVzKSwyMDApICN0YWtlIHRvcCB0b3BfZ2VuZXNfbnVtCiAgcmVzID0gZ2VuZXNfdmVjX2VucmljaG1lbnQoZ2VuZXMgPSB0b3AsYmFja2dyb3VuZCA9IHJvd25hbWVzKGdlcF9zY29yZXMpLGhvbWVyID0gVCx0aXRsZSA9IAogICAgICAgICAgICAgICAgICAgIGksc2lsZW50ID0gVCxyZXR1cm5fYWxsID0gVCxjdXN0b21fcGF0aHdheXMgPSBjYW5vbmljYWxfcGF0aHdheXMpCiAgIAogIHBsdF9saXN0W1tpXV0gPSByZXMkcGx0Cn0KZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UoZ3JvYnMgPSBwbHRfbGlzdCkKYGBgCgojIEV4cHJlc3Npb24gYnkgc2NvcmVzIGZyb20gY25tZiB7LnRhYnNldH0KYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTEwLCByZXN1bHRzPSdhc2lzJ30gCiMgTWFrZSBtZXRhZ2VuZSBuYW1lcwpmb3IgKGkgaW4gMTpuY29sKGFsbF9tZXRhZ2VuZXMpKSB7CiAgY29sbmFtZXMoYWxsX21ldGFnZW5lcylbaV0gPSAibWV0YWdlbmUuIiAlPiUgcGFzdGUwKGkpCn0KCiNhZGQgZWFjaCBtZXRhZ2VuZSB0byBtZXRhZGF0YQpmb3IgKGkgaW4gMTpuY29sKGFsbF9tZXRhZ2VuZXMpKSB7CiAgbWV0YWdlX21ldGFkYXRhID0gYWxsX21ldGFnZW5lcyAlPiUgc2VsZWN0KGkpCiAgYWNjMV9jYW5jZXJfY2VsbHMgPSBBZGRNZXRhRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyxtZXRhZGF0YSA9IG1ldGFnZV9tZXRhZGF0YSkKfQoKcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyxmZWF0dXJlcyA9IGNvbG5hbWVzKGFsbF9tZXRhZ2VuZXMpKQosdGl0bGUgPSAiZXhwcmVzc2lvbiIsc3VidGl0bGVfbnVtID0gMikKCgpwcmludF90YWIoCiAgcGx0ID0gRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSBjb2xuYW1lcyhhbGxfbWV0YWdlbmVzKSxtYXguY3V0b2ZmID0gMC4wNSkKICAgICAgICAgICx0aXRsZSA9ICJtYXguY3V0b2ZmID0gMC4wNSIsc3VidGl0bGVfbnVtID0gMikKCmBgYAojIEV4cHJlc3Npb24gYnkgc2NvcmVzIGZyb20gY25tZiArIFogc2NvcmUgey50YWJzZXR9CmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xMCwgcmVzdWx0cz0nYXNpcyd9IAoKCmFsbF9tZXRhZ2VuZXNfbm9ybT0gc2NhbGUoYWxsX21ldGFnZW5lcykgJT4lIGFzLmRhdGEuZnJhbWUoKQojIE1ha2UgbWV0YWdlbmUgbmFtZXMKZm9yIChpIGluIDE6bmNvbChhbGxfbWV0YWdlbmVzX25vcm0pKSB7CiAgY29sbmFtZXMoYWxsX21ldGFnZW5lc19ub3JtKVtpXSA9ICJtZXRhZ2VuZS4iICU+JSBwYXN0ZTAoaSkKfQoKI2FkZCBlYWNoIG1ldGFnZW5lIHRvIG1ldGFkYXRhCmZvciAoaSBpbiAxOm5jb2woYWxsX21ldGFnZW5lc19ub3JtKSkgewogIG1ldGFnZV9tZXRhZGF0YSA9IGFsbF9tZXRhZ2VuZXNfbm9ybSAlPiUgc2VsZWN0KGkpCiAgYWNjMV9jYW5jZXJfY2VsbHMgPSBBZGRNZXRhRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyxtZXRhZGF0YSA9IG1ldGFnZV9tZXRhZGF0YSkKfQoKcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyxmZWF0dXJlcyA9IGNvbG5hbWVzKGFsbF9tZXRhZ2VuZXMpKQosdGl0bGUgPSAiZXhwcmVzc2lvbiIsc3VidGl0bGVfbnVtID0gMikKCgpwcmludF90YWIoCiAgcGx0ID0gRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSBjb2xuYW1lcyhhbGxfbWV0YWdlbmVzKSxtYXguY3V0b2ZmID0gMC41KQogICAgICAgICAgLHRpdGxlID0gIm1heC5jdXRvZmYgPSAwLjUiLHN1YnRpdGxlX251bSA9IDIpCgpgYGAKIyBFeHByZXNzaW9uIGJ5IGNvZWZmaWNpZW50cyBpbnZlcnNpb24gKiBleHByZXNzaW9uICB7LnRhYnNldH0KYGBge3J9CgphbGxfbWV0YWdlbmVzX2ludmVyc2VkICA9IGV4cHJlc3Npb25faW52ZXJzaW9uKGdlcF9zY29yZXMgPSBnZXBfc2NvcmVzICU+JSBhcy5tYXRyaXgoKSAsZGF0YXNldCA9IGFjYzFfY2FuY2VyX2NlbGxzKSAlPiUgdCgpICU+JSBhcy5kYXRhLmZyYW1lKCkKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTAsIHJlc3VsdHM9J2FzaXMnfSAKCiMgTWFrZSBtZXRhZ2VuZSBuYW1lcwpmb3IgKGkgaW4gMTpuY29sKGFsbF9tZXRhZ2VuZXNfaW52ZXJzZWQpKSB7CiAgY29sbmFtZXMoYWxsX21ldGFnZW5lc19pbnZlcnNlZClbaV0gPSAibWV0YWdlbmUuIiAlPiUgcGFzdGUwKGkpCn0KCiNhZGQgZWFjaCBtZXRhZ2VuZSB0byBtZXRhZGF0YQpmb3IgKGkgaW4gMTpuY29sKGFsbF9tZXRhZ2VuZXNfaW52ZXJzZWQpKSB7CiAgbWV0YWdlX21ldGFkYXRhID0gYWxsX21ldGFnZW5lc19pbnZlcnNlZCAlPiUgc2VsZWN0KGkpCiAgYWNjMV9jYW5jZXJfY2VsbHMgPSBBZGRNZXRhRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyxtZXRhZGF0YSA9IG1ldGFnZV9tZXRhZGF0YSkKfQoKRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSBjb2xuYW1lcyhhbGxfbWV0YWdlbmVzX2ludmVyc2VkKSkKCmBgYAoKIyBFeHByZXNzaW9uIGJ5IChjb2VmZmljaWVudHMgaW52ZXJzaW9uIHN1bSB0byAxKSAqIGV4cHJlc3Npb24gey50YWJzZXR9CmBgYHtyfQpnZXBfc2NvcmVzX25vcm0gPSBhcHBseShnZXBfc2NvcmVzLCAyLCBub19uZWcpCmdlcF9zY29yZXNfbm9ybSA9IGFwcGx5KGdlcF9zY29yZXNfbm9ybSwgMiwgc3VtXzJfb25lKQoKCmFsbF9tZXRhZ2VuZXNfaW52ZXJzZWQgID0gZXhwcmVzc2lvbl9pbnZlcnNpb24oZ2VwX3Njb3JlcyA9IGdlcF9zY29yZXNfbm9ybSAsZGF0YXNldCA9IGFjYzFfY2FuY2VyX2NlbGxzKSAlPiUgdCgpICU+JSBhcy5kYXRhLmZyYW1lKCkKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTAsIHJlc3VsdHM9J2FzaXMnfSAKCiMgTWFrZSBtZXRhZ2VuZSBuYW1lcwpmb3IgKGkgaW4gMTpuY29sKGFsbF9tZXRhZ2VuZXNfaW52ZXJzZWQpKSB7CiAgY29sbmFtZXMoYWxsX21ldGFnZW5lc19pbnZlcnNlZClbaV0gPSAibWV0YWdlbmUuIiAlPiUgcGFzdGUwKGkpCn0KCiNhZGQgZWFjaCBtZXRhZ2VuZSB0byBtZXRhZGF0YQpmb3IgKGkgaW4gMTpuY29sKGFsbF9tZXRhZ2VuZXNfaW52ZXJzZWQpKSB7CiAgbWV0YWdlX21ldGFkYXRhID0gYWxsX21ldGFnZW5lc19pbnZlcnNlZCAlPiUgc2VsZWN0KGkpCiAgYWNjMV9jYW5jZXJfY2VsbHMgPSBBZGRNZXRhRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyxtZXRhZGF0YSA9IG1ldGFnZV9tZXRhZGF0YSkKfQoKcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyxmZWF0dXJlcyA9IGNvbG5hbWVzKGFsbF9tZXRhZ2VuZXMpKQosdGl0bGUgPSAiZXhwcmVzc2lvbiIsc3VidGl0bGVfbnVtID0gMikKCgpwcmludF90YWIoCiAgcGx0ID0gRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSBjb2xuYW1lcyhhbGxfbWV0YWdlbmVzKSxtYXguY3V0b2ZmID0gNzUwKQogICAgICAgICAgLHRpdGxlID0gIm1heC5jdXRvZmYgPSA3NTAiLHN1YnRpdGxlX251bSA9IDIpCmBgYAoKIyBFeHByZXNzaW9uIGJ5IGNvZWZmaWNpZW50cyBzdW0gdG8gMSAqIGV4cHJlc3Npb24gey50YWJzZXR9CmBgYHtyfQpnZXBfc2NvcmVzX25vcm0gPSBhcHBseShnZXBfc2NvcmVzLCAyLCBub19uZWcpCmdlcF9zY29yZXNfbm9ybSA9IGFwcGx5KGdlcF9zY29yZXNfbm9ybSwgMiwgc3VtXzJfb25lKSAlPiUgYXMuZGF0YS5mcmFtZSgpCgoKYWxsX21ldGFnZW5lc19tdWx0ICA9IGV4cHJlc3Npb25fbXVsdChnZXBfc2NvcmVzID0gZ2VwX3Njb3Jlc19ub3JtICxkYXRhc2V0ID0gYWNjMV9jYW5jZXJfY2VsbHMsdG9wX2dlbmVzID0gVCkKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTAsIHJlc3VsdHM9J2FzaXMnfSAKCiMgTWFrZSBtZXRhZ2VuZSBuYW1lcwpmb3IgKGkgaW4gMTpuY29sKGFsbF9tZXRhZ2VuZXNfbXVsdCkpIHsKICBjb2xuYW1lcyhhbGxfbWV0YWdlbmVzX211bHQpW2ldID0gIm1ldGFnZW5lLiIgJT4lIHBhc3RlMChpKQp9CgojYWRkIGVhY2ggbWV0YWdlbmUgdG8gbWV0YWRhdGEKZm9yIChpIGluIDE6bmNvbChhbGxfbWV0YWdlbmVzX211bHQpKSB7CiAgbWV0YWdlX21ldGFkYXRhID0gYWxsX21ldGFnZW5lc19tdWx0ICU+JSBzZWxlY3QoaSkKICBhY2MxX2NhbmNlcl9jZWxscyA9IEFkZE1ldGFEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLG1ldGFkYXRhID0gbWV0YWdlX21ldGFkYXRhKQp9CgpwcmludF90YWIocGx0ID0gCiAgICAgICAgICAgIEZlYXR1cmVQbG90KG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gY29sbmFtZXMoYWxsX21ldGFnZW5lcykpCix0aXRsZSA9ICJleHByZXNzaW9uIixzdWJ0aXRsZV9udW0gPSAyKQoKCnByaW50X3RhYigKICBwbHQgPSBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyxmZWF0dXJlcyA9IGNvbG5hbWVzKGFsbF9tZXRhZ2VuZXMpLG1heC5jdXRvZmYgPSA1MCkKICAgICAgICAgICx0aXRsZSA9ICJtYXguY3V0b2ZmID0gNTAiLHN1YnRpdGxlX251bSA9IDIpCmBgYAo=