all_acc_cancer_cells = readRDS("./Data/acc_cancer_cells_V3.RDS")
  original_myo_genes = c("TP63", "TP73", "CAV1", "CDH3", "KRT5", "KRT14", "ACTA2", "TAGLN", "MYLK", "DKK3")
  original_lum_genes = c("KIT", "EHF", "ELF5", "KRT7", "CLDN3", "CLDN4", "CD24", "LGALS3", "LCN2", "SLPI")
  orig_myoscore=apply(all_acc_cancer_cells@assays[["RNA"]][original_myo_genes,],2,mean)
  orig_lescore=apply(all_acc_cancer_cells@assays[["RNA"]][original_lum_genes,],2,mean)
  all_acc_cancer_cells = AddMetaData(object = all_acc_cancer_cells,metadata = orig_lescore-orig_myoscore,col.name = "lum_over_myo")
    all_acc_cancer_cells = AddMetaData(object = all_acc_cancer_cells,metadata = orig_myoscore,col.name = "myo_score")
    all_acc_cancer_cells = AddMetaData(object = all_acc_cancer_cells,metadata = orig_lescore,col.name = "lum_score")

Load object

reticulate::repl_python()
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)
/sci/labs/yotamd/lab_share/avishai.wizel/python_envs/miniconda/envs/cnmf_env_6/lib/python3.7/site-packages/scanpy/preprocessing/_simple.py:843: UserWarning: Received a view of an AnnData. Making a copy.
  view_to_actual(adata)
usage_norm, gep_scores, gep_tpm, topgenes = cnmf_obj.load_results(K=selected_k, density_threshold=density_threshold)
quit
gep_scores = py$gep_scores
gep_tpm = py$gep_tpm
all_metagenes= py$usage_norm
no_neg <- function(x) {
  x = x + abs(min(x))
  x
}
gep_scores_norm = gep_scores

# gep_scores_norm = apply(gep_scores, MARGIN = 2, FUN = min_max_normalize)%>% as.data.frame()
#or:
gep_scores_norm = apply(gep_scores, MARGIN = 2, FUN = no_neg)%>% as.data.frame()

gep_scores_norm = sum2one(gep_scores_norm)
all_metagenes = expression_mult(gep_scores = gep_scores_norm,dataset = all_acc_cancer_cells,top_genes = T,z_score = F)

Programs enrichments

#Hallmarks:
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
}
p = ggarrange(plotlist  = plt_list)
print_tab(plt = p,title = "HALLMARK enrichment")

HALLMARK enrichment

#Canonical:
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
}
p = ggarrange(plotlist  = plt_list)
print_tab(plt = p,title = "canonical pathway enrichment")

canonical pathway enrichment

NA

luminal and myo genes in score

# lum genes in metagenes
message("lum genes in metagenes:")
lum genes in metagenes:
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
  cat(paste0("metagene ",i,": "))
  print(original_lum_genes[original_lum_genes %in% top])

}
metagene 1: [1] "KRT7" "SLPI"
metagene 2: [1] "CLDN4"
metagene 3: character(0)
metagene 4: [1] "KRT7"   "LGALS3" "LCN2"   "SLPI"  
cat("\n")
# myo genes in metagenes
message("myo genes in metagenes:")
myo genes in metagenes:
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
  cat(paste0("metagene ",i,": "))
  print(original_myo_genes[original_myo_genes %in% top])

}
metagene 1: [1] "KRT14" "ACTA2" "DKK3" 
metagene 2: character(0)
metagene 3: character(0)
metagene 4: character(0)
cat("\n")
notch_genes = c("JAG1","JAG2","NOTCH3","NOTCH2","NOTCH1","DLL1","MYB","HES4","HEY1","HEY2","NRARP")
# notch genes in metagenes
message("notch genes in metagenes:")
notch genes in metagenes:
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
  cat(paste0("metagene ",i,": "))
  print(notch_genes[notch_genes %in% top])

}
metagene 1: character(0)
metagene 2: character(0)
metagene 3: character(0)
metagene 4: character(0)
cat("\n")

Metagenes on ACC

# 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)
  all_acc_cancer_cells = AddMetaData(object = all_acc_cancer_cells,metadata = metage_metadata)
}

FeaturePlot(object = all_acc_cancer_cells,features = colnames(all_metagenes),max.cutoff = 100)

all_acc_cancer_cells = program_assignment(dataset = all_acc_cancer_cells,larger_by = 1.25,program_names = colnames(all_metagenes))

UMAPS

colors =  rainbow(all_acc_cancer_cells$program.assignment %>% unique() %>% length()-1)
colors = c(colors,"grey")
print_tab(plt = DimPlot(object = all_acc_cancer_cells,group.by = "program.assignment",cols =colors),title = "program.assignment")

program.assignment

print_tab(plt = DimPlot(object = all_acc_cancer_cells,group.by = "patient.ident"),title = "patient.ident")

patient.ident

print_tab(plt = FeaturePlot(object = all_acc_cancer_cells,features = "lum_score"),title = "lum_score")

lum_score

print_tab(plt = FeaturePlot(object = all_acc_cancer_cells,features = "myo_score"),title = "myo_score")

myo_score

NA

metagenes by lum_over_myo

acc_cancerCells_noACC1 = subset(all_acc_cancer_cells,subset = patient.ident!= "ACC1")

lumScore_vs_program = FetchData(object = acc_cancerCells_noACC1,vars = c("lum_over_myo","program.assignment"))
lumScore_vs_program$program.assignment <- factor(lumScore_vs_program$program.assignment, levels = c("metagene.1","metagene.2","metagene.4"))

lumScore_vs_program = lumScore_vs_program %>% dplyr::filter(program.assignment %in% c("metagene.1","metagene.2","metagene.4"))
ggboxplot(lumScore_vs_program, x = "program.assignment", y = "lum_over_myo",
          palette = "jco",
          add = "jitter")+ stat_compare_means(method = "wilcox.test",comparisons = list(c("metagene.1","metagene.2"),c("metagene.2","metagene.4")))

Metagenes correlation with myo score

for (metagene in c("metagene.1","metagene.2","metagene.4")) {
   lum_score_vs_programScore = FetchData(object = acc_cancerCells_noACC1,vars = c(metagene,"myo_score"))
  print_tab(plt = 
    ggscatter(lum_score_vs_programScore, x = metagene, y = "myo_score", 
            add = "reg.line", conf.int = TRUE, 
            cor.coef = TRUE, cor.method = "pearson")
  ,title = metagene)
}

metagene.1

geom_smooth() using formula ‘y ~ x’

metagene.2

geom_smooth() using formula ‘y ~ x’

metagene.4

geom_smooth() using formula ‘y ~ x’

NA

NA

Metagenes correlation with lum score

for (metagene in c("metagene.1","metagene.2","metagene.4")) {
   lum_score_vs_programScore = FetchData(object = acc_cancerCells_noACC1,vars = c(metagene,"lum_score"))
  print_tab(plt = 
    ggscatter(lum_score_vs_programScore, x = metagene, y = "lum_score", 
            add = "reg.line", conf.int = TRUE, 
            cor.coef = TRUE, cor.method = "pearson")
  ,title = metagene)
}

metagene.1

geom_smooth() using formula ‘y ~ x’

metagene.2

geom_smooth() using formula ‘y ~ x’

metagene.4

geom_smooth() using formula ‘y ~ x’

NA

NA

metagene 1 with myo genes


for (gene in original_myo_genes) {
  
  lum_score_vs_programScore = FetchData(object = acc_cancerCells_noACC1,vars = c("metagene.1",gene))
p = ggscatter(lum_score_vs_programScore, x = "metagene.1", y = gene, 
          add = "reg.line", conf.int = TRUE, 
          cor.coef = TRUE, cor.method = "pearson")
print_tab(plt = p,title = gene)
}

TP63

geom_smooth() using formula ‘y ~ x’

TP73

geom_smooth() using formula ‘y ~ x’

CAV1

geom_smooth() using formula ‘y ~ x’

CDH3

geom_smooth() using formula ‘y ~ x’

KRT5

geom_smooth() using formula ‘y ~ x’

KRT14

geom_smooth() using formula ‘y ~ x’

ACTA2

geom_smooth() using formula ‘y ~ x’

TAGLN

geom_smooth() using formula ‘y ~ x’

MYLK

geom_smooth() using formula ‘y ~ x’

DKK3

geom_smooth() using formula ‘y ~ x’

NA

metagene 2 with myo genes


for (gene in original_myo_genes) {
  
  lum_score_vs_programScore = FetchData(object = acc_cancerCells_noACC1,vars = c("metagene.2",gene))
p = ggscatter(lum_score_vs_programScore, x = "metagene.2", y = gene, 
          add = "reg.line", conf.int = TRUE, 
          cor.coef = TRUE, cor.method = "pearson")
print_tab(plt = p,title = gene)
}

TP63

geom_smooth() using formula ‘y ~ x’

TP73

geom_smooth() using formula ‘y ~ x’

CAV1

geom_smooth() using formula ‘y ~ x’

CDH3

geom_smooth() using formula ‘y ~ x’

KRT5

geom_smooth() using formula ‘y ~ x’

KRT14

geom_smooth() using formula ‘y ~ x’

ACTA2

geom_smooth() using formula ‘y ~ x’

TAGLN

geom_smooth() using formula ‘y ~ x’

MYLK

geom_smooth() using formula ‘y ~ x’

DKK3

geom_smooth() using formula ‘y ~ x’

NA

metagene 2 with acc genes

notch_genes = c("JAG1","JAG2","NOTCH3","NOTCH2","NOTCH1","DLL1","MYB","HES4","HEY1","HEY2","NRARP")

acc_cancerCells_noACC1 = subset(all_acc_cancer_cells,subset = patient.ident!= "ACC1")
for (gene in notch_genes) {
  
  lum_score_vs_programScore = FetchData(object = acc_cancerCells_noACC1,vars = c("metagene.2",gene))
p = ggscatter(lum_score_vs_programScore, x = "metagene.2", y = gene, 
          add = "reg.line", conf.int = TRUE, 
          cor.coef = TRUE, cor.method = "pearson")
print_tab(plt = p,title = gene)
}

JAG1

geom_smooth() using formula ‘y ~ x’

JAG2

geom_smooth() using formula ‘y ~ x’

NOTCH3

geom_smooth() using formula ‘y ~ x’

NOTCH2

geom_smooth() using formula ‘y ~ x’

NOTCH1

geom_smooth() using formula ‘y ~ x’

DLL1

geom_smooth() using formula ‘y ~ x’

MYB

geom_smooth() using formula ‘y ~ x’

HES4

geom_smooth() using formula ‘y ~ x’

HEY1

geom_smooth() using formula ‘y ~ x’

HEY2

geom_smooth() using formula ‘y ~ x’

NRARP

geom_smooth() using formula ‘y ~ x’

NA

LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMuRGF0ZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCi0tLQoKCmBgYHtyfQphbGxfYWNjX2NhbmNlcl9jZWxscyA9IHJlYWRSRFMoIi4vRGF0YS9hY2NfY2FuY2VyX2NlbGxzX1YzLlJEUyIpCmBgYAoKYGBge3J9CiAgb3JpZ2luYWxfbXlvX2dlbmVzID0gYygiVFA2MyIsICJUUDczIiwgIkNBVjEiLCAiQ0RIMyIsICJLUlQ1IiwgIktSVDE0IiwgIkFDVEEyIiwgIlRBR0xOIiwgIk1ZTEsiLCAiREtLMyIpCiAgb3JpZ2luYWxfbHVtX2dlbmVzID0gYygiS0lUIiwgIkVIRiIsICJFTEY1IiwgIktSVDciLCAiQ0xETjMiLCAiQ0xETjQiLCAiQ0QyNCIsICJMR0FMUzMiLCAiTENOMiIsICJTTFBJIikKICBvcmlnX215b3Njb3JlPWFwcGx5KGFsbF9hY2NfY2FuY2VyX2NlbGxzQGFzc2F5c1tbIlJOQSJdXVtvcmlnaW5hbF9teW9fZ2VuZXMsXSwyLG1lYW4pCiAgb3JpZ19sZXNjb3JlPWFwcGx5KGFsbF9hY2NfY2FuY2VyX2NlbGxzQGFzc2F5c1tbIlJOQSJdXVtvcmlnaW5hbF9sdW1fZ2VuZXMsXSwyLG1lYW4pCiAgYWxsX2FjY19jYW5jZXJfY2VsbHMgPSBBZGRNZXRhRGF0YShvYmplY3QgPSBhbGxfYWNjX2NhbmNlcl9jZWxscyxtZXRhZGF0YSA9IG9yaWdfbGVzY29yZS1vcmlnX215b3Njb3JlLGNvbC5uYW1lID0gImx1bV9vdmVyX215byIpCiAgICBhbGxfYWNjX2NhbmNlcl9jZWxscyA9IEFkZE1ldGFEYXRhKG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLG1ldGFkYXRhID0gb3JpZ19teW9zY29yZSxjb2wubmFtZSA9ICJteW9fc2NvcmUiKQogICAgYWxsX2FjY19jYW5jZXJfY2VsbHMgPSBBZGRNZXRhRGF0YShvYmplY3QgPSBhbGxfYWNjX2NhbmNlcl9jZWxscyxtZXRhZGF0YSA9IG9yaWdfbGVzY29yZSxjb2wubmFtZSA9ICJsdW1fc2NvcmUiKQpgYGAKIyMgTG9hZCBvYmplY3QKYGBge3B5dGhvbn0KZnJvbSBjbm1mIGltcG9ydCBjTk1GCmltcG9ydCBwaWNrbGUKbmZlYXR1cmVzID0gIjJLIgpmID0gb3BlbignLi9EYXRhL2NOTUYvSE1TQ19jTk1GXycgKyBuZmVhdHVyZXMrICd2YXJnZW5lcy9jbm1mX29iai5wY2tsJywgJ3JiJykKY25tZl9vYmogPSBwaWNrbGUubG9hZChmKQpmLmNsb3NlKCkKYGBgCgpgYGB7cHl0aG9ufQpzZWxlY3RlZF9rID0gNApkZW5zaXR5X3RocmVzaG9sZCA9IDAuMQpjbm1mX29iai5jb25zZW5zdXMoaz1zZWxlY3RlZF9rLCBkZW5zaXR5X3RocmVzaG9sZD1kZW5zaXR5X3RocmVzaG9sZCxzaG93X2NsdXN0ZXJpbmc9VHJ1ZSkKdXNhZ2Vfbm9ybSwgZ2VwX3Njb3JlcywgZ2VwX3RwbSwgdG9wZ2VuZXMgPSBjbm1mX29iai5sb2FkX3Jlc3VsdHMoSz1zZWxlY3RlZF9rLCBkZW5zaXR5X3RocmVzaG9sZD1kZW5zaXR5X3RocmVzaG9sZCkKYGBgCgpgYGB7cn0KZ2VwX3Njb3JlcyA9IHB5JGdlcF9zY29yZXMKZ2VwX3RwbSA9IHB5JGdlcF90cG0KYWxsX21ldGFnZW5lcz0gcHkkdXNhZ2Vfbm9ybQpgYGAKCgpgYGB7cn0Kbm9fbmVnIDwtIGZ1bmN0aW9uKHgpIHsKICB4ID0geCArIGFicyhtaW4oeCkpCiAgeAp9CmdlcF9zY29yZXNfbm9ybSA9IGdlcF9zY29yZXMKCiMgZ2VwX3Njb3Jlc19ub3JtID0gYXBwbHkoZ2VwX3Njb3JlcywgTUFSR0lOID0gMiwgRlVOID0gbWluX21heF9ub3JtYWxpemUpJT4lIGFzLmRhdGEuZnJhbWUoKQojb3I6CmdlcF9zY29yZXNfbm9ybSA9IGFwcGx5KGdlcF9zY29yZXMsIE1BUkdJTiA9IDIsIEZVTiA9IG5vX25lZyklPiUgYXMuZGF0YS5mcmFtZSgpCgpnZXBfc2NvcmVzX25vcm0gPSBzdW0yb25lKGdlcF9zY29yZXNfbm9ybSkKYWxsX21ldGFnZW5lcyA9IGV4cHJlc3Npb25fbXVsdChnZXBfc2NvcmVzID0gZ2VwX3Njb3Jlc19ub3JtLGRhdGFzZXQgPSBhbGxfYWNjX2NhbmNlcl9jZWxscyx0b3BfZ2VuZXMgPSBULHpfc2NvcmUgPSBGKQpgYGAKIyBQcm9ncmFtcyBlbnJpY2htZW50cyB7LnRhYnNldH0KCmBgYHtyIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTgsIHJlc3VsdHM9J2FzaXMnfQojSGFsbG1hcmtzOgpwbHRfbGlzdCA9IGxpc3QoKQpmb3IgKGkgaW4gMTpuY29sKGdlcF9zY29yZXMpKSB7CiAgdG9wX2dlbmVzID0gZ2VwX3Njb3JlcyAgJT4lICBhcnJhbmdlKGRlc2MoZ2VwX3Njb3Jlc1tpXSkpICNzb3J0IGJ5IHNjb3JlIGEKICB0b3AgPSBoZWFkKHJvd25hbWVzKHRvcF9nZW5lcyksMjAwKSAjdGFrZSB0b3AgdG9wX2dlbmVzX251bQogIHJlcyA9IGdlbmVzX3ZlY19lbnJpY2htZW50KGdlbmVzID0gdG9wLGJhY2tncm91bmQgPSByb3duYW1lcyhnZXBfc2NvcmVzKSxob21lciA9IFQsdGl0bGUgPSAKICAgICAgICAgICAgICAgICAgICBpLHNpbGVudCA9IFQscmV0dXJuX2FsbCA9IFQpCiAgIAogIHBsdF9saXN0W1tpXV0gPSByZXMkcGx0Cn0KcCA9IGdnYXJyYW5nZShwbG90bGlzdCAgPSBwbHRfbGlzdCkKcHJpbnRfdGFiKHBsdCA9IHAsdGl0bGUgPSAiSEFMTE1BUksgZW5yaWNobWVudCIpCgojQ2Fub25pY2FsOgpjYW5vbmljYWxfcGF0aHdheXMgPSBtc2lnZGJyKHNwZWNpZXMgPSAiSG9tbyBzYXBpZW5zIiwgY2F0ZWdvcnkgPSAiQzIiKSAlPiUgZHBseXI6OmZpbHRlcihnc19zdWJjYXQgIT0gIkNHUCIpICU+JSAgZHBseXI6OmRpc3RpbmN0KGdzX25hbWUsIGdlbmVfc3ltYm9sKSAKCnBsdF9saXN0ID0gbGlzdCgpCmZvciAoaSBpbiAxOm5jb2woZ2VwX3Njb3JlcykpIHsKICB0b3BfZ2VuZXMgPSBnZXBfc2NvcmVzICAlPiUgIGFycmFuZ2UoZGVzYyhnZXBfc2NvcmVzW2ldKSkgI3NvcnQgYnkgc2NvcmUgYQogIHRvcCA9IGhlYWQocm93bmFtZXModG9wX2dlbmVzKSwyMDApICN0YWtlIHRvcCB0b3BfZ2VuZXNfbnVtCiAgcmVzID0gZ2VuZXNfdmVjX2VucmljaG1lbnQoZ2VuZXMgPSB0b3AsYmFja2dyb3VuZCA9IHJvd25hbWVzKGdlcF9zY29yZXMpLGhvbWVyID0gVCx0aXRsZSA9IAogICAgICAgICAgICAgICAgICAgIGksc2lsZW50ID0gVCxyZXR1cm5fYWxsID0gVCxjdXN0b21fcGF0aHdheXMgPSBjYW5vbmljYWxfcGF0aHdheXMpCiAgIAogIHBsdF9saXN0W1tpXV0gPSByZXMkcGx0Cn0KcCA9IGdnYXJyYW5nZShwbG90bGlzdCAgPSBwbHRfbGlzdCkKcHJpbnRfdGFiKHBsdCA9IHAsdGl0bGUgPSAiY2Fub25pY2FsIHBhdGh3YXkgZW5yaWNobWVudCIpCgoKCmBgYAojIyBsdW1pbmFsIGFuZCBteW8gZ2VuZXMgaW4gc2NvcmUKYGBge3IgcmVzdWx0cz0naG9sZCcsY29sbGFwc2U9VFJVRX0KIyBsdW0gZ2VuZXMgaW4gbWV0YWdlbmVzCm1lc3NhZ2UoImx1bSBnZW5lcyBpbiBtZXRhZ2VuZXM6IikKZm9yIChpIGluIDE6bmNvbChnZXBfc2NvcmVzKSkgewogIHRvcF9nZW5lcyA9IGdlcF9zY29yZXMgICU+JSAgYXJyYW5nZShkZXNjKGdlcF9zY29yZXNbaV0pKSAjc29ydCBieSBzY29yZSBhCiAgdG9wID0gaGVhZChyb3duYW1lcyh0b3BfZ2VuZXMpLDIwMCkgI3Rha2UgdG9wIHRvcF9nZW5lc19udW0KICBjYXQocGFzdGUwKCJtZXRhZ2VuZSAiLGksIjogIikpCiAgcHJpbnQob3JpZ2luYWxfbHVtX2dlbmVzW29yaWdpbmFsX2x1bV9nZW5lcyAlaW4lIHRvcF0pCgp9CmNhdCgiXG4iKQoKCiMgbXlvIGdlbmVzIGluIG1ldGFnZW5lcwptZXNzYWdlKCJteW8gZ2VuZXMgaW4gbWV0YWdlbmVzOiIpCmZvciAoaSBpbiAxOm5jb2woZ2VwX3Njb3JlcykpIHsKICB0b3BfZ2VuZXMgPSBnZXBfc2NvcmVzICAlPiUgIGFycmFuZ2UoZGVzYyhnZXBfc2NvcmVzW2ldKSkgI3NvcnQgYnkgc2NvcmUgYQogIHRvcCA9IGhlYWQocm93bmFtZXModG9wX2dlbmVzKSwyMDApICN0YWtlIHRvcCB0b3BfZ2VuZXNfbnVtCiAgY2F0KHBhc3RlMCgibWV0YWdlbmUgIixpLCI6ICIpKQogIHByaW50KG9yaWdpbmFsX215b19nZW5lc1tvcmlnaW5hbF9teW9fZ2VuZXMgJWluJSB0b3BdKQoKfQpjYXQoIlxuIikKCm5vdGNoX2dlbmVzID0gYygiSkFHMSIsIkpBRzIiLCJOT1RDSDMiLCJOT1RDSDIiLCJOT1RDSDEiLCJETEwxIiwiTVlCIiwiSEVTNCIsIkhFWTEiLCJIRVkyIiwiTlJBUlAiKQojIG5vdGNoIGdlbmVzIGluIG1ldGFnZW5lcwptZXNzYWdlKCJub3RjaCBnZW5lcyBpbiBtZXRhZ2VuZXM6IikKZm9yIChpIGluIDE6bmNvbChnZXBfc2NvcmVzKSkgewogIHRvcF9nZW5lcyA9IGdlcF9zY29yZXMgICU+JSAgYXJyYW5nZShkZXNjKGdlcF9zY29yZXNbaV0pKSAjc29ydCBieSBzY29yZSBhCiAgdG9wID0gaGVhZChyb3duYW1lcyh0b3BfZ2VuZXMpLDIwMCkgI3Rha2UgdG9wIHRvcF9nZW5lc19udW0KICBjYXQocGFzdGUwKCJtZXRhZ2VuZSAiLGksIjogIikpCiAgcHJpbnQobm90Y2hfZ2VuZXNbbm90Y2hfZ2VuZXMgJWluJSB0b3BdKQoKfQpjYXQoIlxuIikKYGBgCgoKCiMgTWV0YWdlbmVzIG9uIEFDQwoKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTEwfQojIE1ha2UgbWV0YWdlbmUgbmFtZXMKZm9yIChpIGluIDE6bmNvbChhbGxfbWV0YWdlbmVzKSkgewogIGNvbG5hbWVzKGFsbF9tZXRhZ2VuZXMpW2ldID0gIm1ldGFnZW5lLiIgJT4lIHBhc3RlMChpKQp9CgoKI2FkZCBlYWNoIG1ldGFnZW5lIHRvIG1ldGFkYXRhCmZvciAoaSBpbiAxOm5jb2woYWxsX21ldGFnZW5lcykpIHsKICBtZXRhZ2VfbWV0YWRhdGEgPSBhbGxfbWV0YWdlbmVzICU+JSBzZWxlY3QoaSkKICBhbGxfYWNjX2NhbmNlcl9jZWxscyA9IEFkZE1ldGFEYXRhKG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLG1ldGFkYXRhID0gbWV0YWdlX21ldGFkYXRhKQp9CgpGZWF0dXJlUGxvdChvYmplY3QgPSBhbGxfYWNjX2NhbmNlcl9jZWxscyxmZWF0dXJlcyA9IGNvbG5hbWVzKGFsbF9tZXRhZ2VuZXMpLG1heC5jdXRvZmYgPSAxMDApCgpgYGAKCmBgYHtyfQphbGxfYWNjX2NhbmNlcl9jZWxscyA9IHByb2dyYW1fYXNzaWdubWVudChkYXRhc2V0ID0gYWxsX2FjY19jYW5jZXJfY2VsbHMsbGFyZ2VyX2J5ID0gMS4yNSxwcm9ncmFtX25hbWVzID0gY29sbmFtZXMoYWxsX21ldGFnZW5lcykpCmBgYAoKCgoKCgoKIyBVTUFQUyB7LnRhYnNldH0KCmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcyd9CmNvbG9ycyA9ICByYWluYm93KGFsbF9hY2NfY2FuY2VyX2NlbGxzJHByb2dyYW0uYXNzaWdubWVudCAlPiUgdW5pcXVlKCkgJT4lIGxlbmd0aCgpLTEpCmNvbG9ycyA9IGMoY29sb3JzLCJncmV5IikKcHJpbnRfdGFiKHBsdCA9IERpbVBsb3Qob2JqZWN0ID0gYWxsX2FjY19jYW5jZXJfY2VsbHMsZ3JvdXAuYnkgPSAicHJvZ3JhbS5hc3NpZ25tZW50Iixjb2xzID1jb2xvcnMpLHRpdGxlID0gInByb2dyYW0uYXNzaWdubWVudCIpCnByaW50X3RhYihwbHQgPSBEaW1QbG90KG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLGdyb3VwLmJ5ID0gInBhdGllbnQuaWRlbnQiKSx0aXRsZSA9ICJwYXRpZW50LmlkZW50IikKCnByaW50X3RhYihwbHQgPSBGZWF0dXJlUGxvdChvYmplY3QgPSBhbGxfYWNjX2NhbmNlcl9jZWxscyxmZWF0dXJlcyA9ICJsdW1fc2NvcmUiKSx0aXRsZSA9ICJsdW1fc2NvcmUiKQoKcHJpbnRfdGFiKHBsdCA9IEZlYXR1cmVQbG90KG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gIm15b19zY29yZSIpLHRpdGxlID0gIm15b19zY29yZSIpCgoKCmBgYAojIG1ldGFnZW5lcyBieSBsdW1fb3Zlcl9teW8KYGBge3J9CmFjY19jYW5jZXJDZWxsc19ub0FDQzEgPSBzdWJzZXQoYWxsX2FjY19jYW5jZXJfY2VsbHMsc3Vic2V0ID0gcGF0aWVudC5pZGVudCE9ICJBQ0MxIikKCmx1bVNjb3JlX3ZzX3Byb2dyYW0gPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjX2NhbmNlckNlbGxzX25vQUNDMSx2YXJzID0gYygibHVtX292ZXJfbXlvIiwicHJvZ3JhbS5hc3NpZ25tZW50IikpCmx1bVNjb3JlX3ZzX3Byb2dyYW0kcHJvZ3JhbS5hc3NpZ25tZW50IDwtIGZhY3RvcihsdW1TY29yZV92c19wcm9ncmFtJHByb2dyYW0uYXNzaWdubWVudCwgbGV2ZWxzID0gYygibWV0YWdlbmUuMSIsIm1ldGFnZW5lLjIiLCJtZXRhZ2VuZS40IikpCgpsdW1TY29yZV92c19wcm9ncmFtID0gbHVtU2NvcmVfdnNfcHJvZ3JhbSAlPiUgZHBseXI6OmZpbHRlcihwcm9ncmFtLmFzc2lnbm1lbnQgJWluJSBjKCJtZXRhZ2VuZS4xIiwibWV0YWdlbmUuMiIsIm1ldGFnZW5lLjQiKSkKZ2dib3hwbG90KGx1bVNjb3JlX3ZzX3Byb2dyYW0sIHggPSAicHJvZ3JhbS5hc3NpZ25tZW50IiwgeSA9ICJsdW1fb3Zlcl9teW8iLAogICAgICAgICAgcGFsZXR0ZSA9ICJqY28iLAogICAgICAgICAgYWRkID0gImppdHRlciIpKyBzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gIndpbGNveC50ZXN0Iixjb21wYXJpc29ucyA9IGxpc3QoYygibWV0YWdlbmUuMSIsIm1ldGFnZW5lLjIiKSxjKCJtZXRhZ2VuZS4yIiwibWV0YWdlbmUuNCIpKSkKYGBgCiMgTWV0YWdlbmVzIGNvcnJlbGF0aW9uIHdpdGggbXlvIHNjb3JlIHsudGFic2V0fQoKCmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcyd9CmZvciAobWV0YWdlbmUgaW4gYygibWV0YWdlbmUuMSIsIm1ldGFnZW5lLjIiLCJtZXRhZ2VuZS40IikpIHsKICAgbHVtX3Njb3JlX3ZzX3Byb2dyYW1TY29yZSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxLHZhcnMgPSBjKG1ldGFnZW5lLCJteW9fc2NvcmUiKSkKICBwcmludF90YWIocGx0ID0gCiAgICBnZ3NjYXR0ZXIobHVtX3Njb3JlX3ZzX3Byb2dyYW1TY29yZSwgeCA9IG1ldGFnZW5lLCB5ID0gIm15b19zY29yZSIsIAogICAgICAgICAgICBhZGQgPSAicmVnLmxpbmUiLCBjb25mLmludCA9IFRSVUUsIAogICAgICAgICAgICBjb3IuY29lZiA9IFRSVUUsIGNvci5tZXRob2QgPSAicGVhcnNvbiIpCiAgLHRpdGxlID0gbWV0YWdlbmUpCn0KIApgYGAKIyBNZXRhZ2VuZXMgY29ycmVsYXRpb24gd2l0aCBsdW0gc2NvcmUgey50YWJzZXR9CgoKYGBge3IgZWNobz1UUlVFLCByZXN1bHRzPSdhc2lzJ30KZm9yIChtZXRhZ2VuZSBpbiBjKCJtZXRhZ2VuZS4xIiwibWV0YWdlbmUuMiIsIm1ldGFnZW5lLjQiKSkgewogICBsdW1fc2NvcmVfdnNfcHJvZ3JhbVNjb3JlID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjY19jYW5jZXJDZWxsc19ub0FDQzEsdmFycyA9IGMobWV0YWdlbmUsImx1bV9zY29yZSIpKQogIHByaW50X3RhYihwbHQgPSAKICAgIGdnc2NhdHRlcihsdW1fc2NvcmVfdnNfcHJvZ3JhbVNjb3JlLCB4ID0gbWV0YWdlbmUsIHkgPSAibHVtX3Njb3JlIiwgCiAgICAgICAgICAgIGFkZCA9ICJyZWcubGluZSIsIGNvbmYuaW50ID0gVFJVRSwgCiAgICAgICAgICAgIGNvci5jb2VmID0gVFJVRSwgY29yLm1ldGhvZCA9ICJwZWFyc29uIikKICAsdGl0bGUgPSBtZXRhZ2VuZSkKfQogCmBgYAoKIyBtZXRhZ2VuZSAxIHdpdGggbXlvIGdlbmVzIHsudGFic2V0fQoKCmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcyd9Cgpmb3IgKGdlbmUgaW4gb3JpZ2luYWxfbXlvX2dlbmVzKSB7CiAgCiAgbHVtX3Njb3JlX3ZzX3Byb2dyYW1TY29yZSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxLHZhcnMgPSBjKCJtZXRhZ2VuZS4xIixnZW5lKSkKcCA9IGdnc2NhdHRlcihsdW1fc2NvcmVfdnNfcHJvZ3JhbVNjb3JlLCB4ID0gIm1ldGFnZW5lLjEiLCB5ID0gZ2VuZSwgCiAgICAgICAgICBhZGQgPSAicmVnLmxpbmUiLCBjb25mLmludCA9IFRSVUUsIAogICAgICAgICAgY29yLmNvZWYgPSBUUlVFLCBjb3IubWV0aG9kID0gInBlYXJzb24iKQpwcmludF90YWIocGx0ID0gcCx0aXRsZSA9IGdlbmUpCn0KCmBgYAojIG1ldGFnZW5lIDIgd2l0aCBteW8gZ2VuZXMgey50YWJzZXR9CgpgYGB7ciBlY2hvPVRSVUUsIHJlc3VsdHM9J2FzaXMnfQoKZm9yIChnZW5lIGluIG9yaWdpbmFsX215b19nZW5lcykgewogIAogIGx1bV9zY29yZV92c19wcm9ncmFtU2NvcmUgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjX2NhbmNlckNlbGxzX25vQUNDMSx2YXJzID0gYygibWV0YWdlbmUuMiIsZ2VuZSkpCnAgPSBnZ3NjYXR0ZXIobHVtX3Njb3JlX3ZzX3Byb2dyYW1TY29yZSwgeCA9ICJtZXRhZ2VuZS4yIiwgeSA9IGdlbmUsIAogICAgICAgICAgYWRkID0gInJlZy5saW5lIiwgY29uZi5pbnQgPSBUUlVFLCAKICAgICAgICAgIGNvci5jb2VmID0gVFJVRSwgY29yLm1ldGhvZCA9ICJwZWFyc29uIikKcHJpbnRfdGFiKHBsdCA9IHAsdGl0bGUgPSBnZW5lKQp9CgpgYGAKCiMgbWV0YWdlbmUgMiB3aXRoIGFjYyBnZW5lcyB7LnRhYnNldH0KCmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcyd9Cm5vdGNoX2dlbmVzID0gYygiSkFHMSIsIkpBRzIiLCJOT1RDSDMiLCJOT1RDSDIiLCJOT1RDSDEiLCJETEwxIiwiTVlCIiwiSEVTNCIsIkhFWTEiLCJIRVkyIiwiTlJBUlAiKQoKYWNjX2NhbmNlckNlbGxzX25vQUNDMSA9IHN1YnNldChhbGxfYWNjX2NhbmNlcl9jZWxscyxzdWJzZXQgPSBwYXRpZW50LmlkZW50IT0gIkFDQzEiKQpmb3IgKGdlbmUgaW4gbm90Y2hfZ2VuZXMpIHsKICAKICBsdW1fc2NvcmVfdnNfcHJvZ3JhbVNjb3JlID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjY19jYW5jZXJDZWxsc19ub0FDQzEsdmFycyA9IGMoIm1ldGFnZW5lLjIiLGdlbmUpKQpwID0gZ2dzY2F0dGVyKGx1bV9zY29yZV92c19wcm9ncmFtU2NvcmUsIHggPSAibWV0YWdlbmUuMiIsIHkgPSBnZW5lLCAKICAgICAgICAgIGFkZCA9ICJyZWcubGluZSIsIGNvbmYuaW50ID0gVFJVRSwgCiAgICAgICAgICBjb3IuY29lZiA9IFRSVUUsIGNvci5tZXRob2QgPSAicGVhcnNvbiIpCnByaW50X3RhYihwbHQgPSBwLHRpdGxlID0gZ2VuZSkKfQoKYGBgCg==