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")
  notch_targets_genes = c("NRARP", "NOTCH3", "HES4", "HEY1", "HEY2")
  notch_ligands = c("DLL1", "JAG1", "JAG2", "HEY1")

  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)
  notch_score=apply(all_acc_cancer_cells@assays[["RNA"]][notch_targets_genes,],2,mean)
  notch_ligands_score=apply(all_acc_cancer_cells@assays[["RNA"]][notch_ligands,],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")
    all_acc_cancer_cells = AddMetaData(object = all_acc_cancer_cells,metadata = notch_score,col.name = "notch_score")
    
  all_acc_cancer_cells = AddMetaData(object = all_acc_cancer_cells,metadata = notch_ligands_score,col.name = "notch_ligands_score_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
}

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

gep_scores_norm = gep_scores
# gep_scores_norm = scale(gep_scores_norm) %>% 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)
# normalize metagenes:
all_metagenes = apply(all_metagenes, MARGIN = 2, FUN = no_neg)  %>% as.data.frame()
all_metagenes = apply(all_metagenes, 1, sum_2_one) %>% t() %>% as.data.frame()

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

Notch score

for (metagene in c("metagene.1","metagene.2","metagene.4")) {
   lum_score_vs_programScore = FetchData(object = acc_cancerCells_noACC1,vars = c(metagene,"notch_score"))
  print_tab(plt = 
    ggscatter(lum_score_vs_programScore, x = metagene, y = "notch_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

Notch ligands score

for (metagene in c("metagene.1","metagene.2","metagene.4")) {
   lum_score_vs_programScore = FetchData(object = acc_cancerCells_noACC1,vars = c(metagene,"notch_ligands_score_score"))
  print_tab(plt = 
    ggscatter(lum_score_vs_programScore, x = metagene, y = "notch_ligands_score_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

LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMuRGF0ZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCi0tLQoKCmBgYHtyfQphbGxfYWNjX2NhbmNlcl9jZWxscyA9IHJlYWRSRFMoIi4vRGF0YS9hY2NfY2FuY2VyX2NlbGxzX1YzLlJEUyIpCmBgYAoKYGBge3J9CiAgb3JpZ2luYWxfbXlvX2dlbmVzID0gYygiVFA2MyIsICJUUDczIiwgIkNBVjEiLCAiQ0RIMyIsICJLUlQ1IiwgIktSVDE0IiwgIkFDVEEyIiwgIlRBR0xOIiwgIk1ZTEsiLCAiREtLMyIpCiAgb3JpZ2luYWxfbHVtX2dlbmVzID0gYygiS0lUIiwgIkVIRiIsICJFTEY1IiwgIktSVDciLCAiQ0xETjMiLCAiQ0xETjQiLCAiQ0QyNCIsICJMR0FMUzMiLCAiTENOMiIsICJTTFBJIikKICBub3RjaF90YXJnZXRzX2dlbmVzID0gYygiTlJBUlAiLCAiTk9UQ0gzIiwgIkhFUzQiLCAiSEVZMSIsICJIRVkyIikKICBub3RjaF9saWdhbmRzID0gYygiRExMMSIsICJKQUcxIiwgIkpBRzIiLCAiSEVZMSIpCgogIG9yaWdfbXlvc2NvcmU9YXBwbHkoYWxsX2FjY19jYW5jZXJfY2VsbHNAYXNzYXlzW1siUk5BIl1dW29yaWdpbmFsX215b19nZW5lcyxdLDIsbWVhbikKICBvcmlnX2xlc2NvcmU9YXBwbHkoYWxsX2FjY19jYW5jZXJfY2VsbHNAYXNzYXlzW1siUk5BIl1dW29yaWdpbmFsX2x1bV9nZW5lcyxdLDIsbWVhbikKICBub3RjaF9zY29yZT1hcHBseShhbGxfYWNjX2NhbmNlcl9jZWxsc0Bhc3NheXNbWyJSTkEiXV1bbm90Y2hfdGFyZ2V0c19nZW5lcyxdLDIsbWVhbikKICBub3RjaF9saWdhbmRzX3Njb3JlPWFwcGx5KGFsbF9hY2NfY2FuY2VyX2NlbGxzQGFzc2F5c1tbIlJOQSJdXVtub3RjaF9saWdhbmRzLF0sMixtZWFuKQoKICBhbGxfYWNjX2NhbmNlcl9jZWxscyA9IEFkZE1ldGFEYXRhKG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLG1ldGFkYXRhID0gb3JpZ19sZXNjb3JlLW9yaWdfbXlvc2NvcmUsY29sLm5hbWUgPSAibHVtX292ZXJfbXlvIikKICAgIGFsbF9hY2NfY2FuY2VyX2NlbGxzID0gQWRkTWV0YURhdGEob2JqZWN0ID0gYWxsX2FjY19jYW5jZXJfY2VsbHMsbWV0YWRhdGEgPSBvcmlnX215b3Njb3JlLGNvbC5uYW1lID0gIm15b19zY29yZSIpCiAgICBhbGxfYWNjX2NhbmNlcl9jZWxscyA9IEFkZE1ldGFEYXRhKG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLG1ldGFkYXRhID0gb3JpZ19sZXNjb3JlLGNvbC5uYW1lID0gImx1bV9zY29yZSIpCiAgICBhbGxfYWNjX2NhbmNlcl9jZWxscyA9IEFkZE1ldGFEYXRhKG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLG1ldGFkYXRhID0gbm90Y2hfc2NvcmUsY29sLm5hbWUgPSAibm90Y2hfc2NvcmUiKQogICAgCiAgYWxsX2FjY19jYW5jZXJfY2VsbHMgPSBBZGRNZXRhRGF0YShvYmplY3QgPSBhbGxfYWNjX2NhbmNlcl9jZWxscyxtZXRhZGF0YSA9IG5vdGNoX2xpZ2FuZHNfc2NvcmUsY29sLm5hbWUgPSAibm90Y2hfbGlnYW5kc19zY29yZV9zY29yZSIpCgoKYGBgCiMjIExvYWQgb2JqZWN0CmBgYHtweXRob259CmZyb20gY25tZiBpbXBvcnQgY05NRgppbXBvcnQgcGlja2xlCm5mZWF0dXJlcyA9ICIySyIKZiA9IG9wZW4oJy4vRGF0YS9jTk1GL0hNU0NfY05NRl8nICsgbmZlYXR1cmVzKyAndmFyZ2VuZXMvY25tZl9vYmoucGNrbCcsICdyYicpCmNubWZfb2JqID0gcGlja2xlLmxvYWQoZikKZi5jbG9zZSgpCmBgYAoKYGBge3B5dGhvbn0Kc2VsZWN0ZWRfayA9IDQKZGVuc2l0eV90aHJlc2hvbGQgPSAwLjEKY25tZl9vYmouY29uc2Vuc3VzKGs9c2VsZWN0ZWRfaywgZGVuc2l0eV90aHJlc2hvbGQ9ZGVuc2l0eV90aHJlc2hvbGQsc2hvd19jbHVzdGVyaW5nPVRydWUpCnVzYWdlX25vcm0sIGdlcF9zY29yZXMsIGdlcF90cG0sIHRvcGdlbmVzID0gY25tZl9vYmoubG9hZF9yZXN1bHRzKEs9c2VsZWN0ZWRfaywgZGVuc2l0eV90aHJlc2hvbGQ9ZGVuc2l0eV90aHJlc2hvbGQpCmBgYAoKYGBge3J9CmdlcF9zY29yZXMgPSBweSRnZXBfc2NvcmVzCmdlcF90cG0gPSBweSRnZXBfdHBtCmFsbF9tZXRhZ2VuZXM9IHB5JHVzYWdlX25vcm0KYGBgCgoKCgpgYGB7cn0Kbm9fbmVnIDwtIGZ1bmN0aW9uKHgpIHsKICB4ID0geCArIGFicyhtaW4oeCkpCiAgeAp9CgpzdW1fMl9vbmUgPC0gZnVuY3Rpb24oeCkgewogIHggPXgvc3VtKHgpCiAgeAp9CgpnZXBfc2NvcmVzX25vcm0gPSBnZXBfc2NvcmVzCiMgZ2VwX3Njb3Jlc19ub3JtID0gc2NhbGUoZ2VwX3Njb3Jlc19ub3JtKSAlPiUgYXMuZGF0YS5mcmFtZSgpCgojb3I6CmdlcF9zY29yZXNfbm9ybSA9IGFwcGx5KGdlcF9zY29yZXMsIE1BUkdJTiA9IDIsIEZVTiA9IG5vX25lZyklPiUgYXMuZGF0YS5mcmFtZSgpCiMgCmdlcF9zY29yZXNfbm9ybSA9IHN1bTJvbmUoZ2VwX3Njb3Jlc19ub3JtKQphbGxfbWV0YWdlbmVzID0gZXhwcmVzc2lvbl9tdWx0KGdlcF9zY29yZXMgPSBnZXBfc2NvcmVzX25vcm0sZGF0YXNldCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLHRvcF9nZW5lcyA9IFQsel9zY29yZSA9IEYpCiMgbm9ybWFsaXplIG1ldGFnZW5lczoKYWxsX21ldGFnZW5lcyA9IGFwcGx5KGFsbF9tZXRhZ2VuZXMsIE1BUkdJTiA9IDIsIEZVTiA9IG5vX25lZykgICU+JSBhcy5kYXRhLmZyYW1lKCkKYWxsX21ldGFnZW5lcyA9IGFwcGx5KGFsbF9tZXRhZ2VuZXMsIDEsIHN1bV8yX29uZSkgJT4lIHQoKSAlPiUgYXMuZGF0YS5mcmFtZSgpCmBgYAoKCiMgUHJvZ3JhbXMgZW5yaWNobWVudHMgey50YWJzZXR9CgpgYGB7ciBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD04LCByZXN1bHRzPSdhc2lzJ30KI0hhbGxtYXJrczoKcGx0X2xpc3QgPSBsaXN0KCkKZm9yIChpIGluIDE6bmNvbChnZXBfc2NvcmVzKSkgewogIHRvcF9nZW5lcyA9IGdlcF9zY29yZXMgICU+JSAgYXJyYW5nZShkZXNjKGdlcF9zY29yZXNbaV0pKSAjc29ydCBieSBzY29yZSBhCiAgdG9wID0gaGVhZChyb3duYW1lcyh0b3BfZ2VuZXMpLDIwMCkgI3Rha2UgdG9wIHRvcF9nZW5lc19udW0KICByZXMgPSBnZW5lc192ZWNfZW5yaWNobWVudChnZW5lcyA9IHRvcCxiYWNrZ3JvdW5kID0gcm93bmFtZXMoZ2VwX3Njb3JlcyksaG9tZXIgPSBULHRpdGxlID0gCiAgICAgICAgICAgICAgICAgICAgaSxzaWxlbnQgPSBULHJldHVybl9hbGwgPSBUKQogICAKICBwbHRfbGlzdFtbaV1dID0gcmVzJHBsdAp9CnAgPSBnZ2FycmFuZ2UocGxvdGxpc3QgID0gcGx0X2xpc3QpCnByaW50X3RhYihwbHQgPSBwLHRpdGxlID0gIkhBTExNQVJLIGVucmljaG1lbnQiKQoKI0Nhbm9uaWNhbDoKY2Fub25pY2FsX3BhdGh3YXlzID0gbXNpZ2RicihzcGVjaWVzID0gIkhvbW8gc2FwaWVucyIsIGNhdGVnb3J5ID0gIkMyIikgJT4lIGRwbHlyOjpmaWx0ZXIoZ3Nfc3ViY2F0ICE9ICJDR1AiKSAlPiUgIGRwbHlyOjpkaXN0aW5jdChnc19uYW1lLCBnZW5lX3N5bWJvbCkgCgpwbHRfbGlzdCA9IGxpc3QoKQpmb3IgKGkgaW4gMTpuY29sKGdlcF9zY29yZXMpKSB7CiAgdG9wX2dlbmVzID0gZ2VwX3Njb3JlcyAgJT4lICBhcnJhbmdlKGRlc2MoZ2VwX3Njb3Jlc1tpXSkpICNzb3J0IGJ5IHNjb3JlIGEKICB0b3AgPSBoZWFkKHJvd25hbWVzKHRvcF9nZW5lcyksMjAwKSAjdGFrZSB0b3AgdG9wX2dlbmVzX251bQogIHJlcyA9IGdlbmVzX3ZlY19lbnJpY2htZW50KGdlbmVzID0gdG9wLGJhY2tncm91bmQgPSByb3duYW1lcyhnZXBfc2NvcmVzKSxob21lciA9IFQsdGl0bGUgPSAKICAgICAgICAgICAgICAgICAgICBpLHNpbGVudCA9IFQscmV0dXJuX2FsbCA9IFQsY3VzdG9tX3BhdGh3YXlzID0gY2Fub25pY2FsX3BhdGh3YXlzKQogICAKICBwbHRfbGlzdFtbaV1dID0gcmVzJHBsdAp9CnAgPSBnZ2FycmFuZ2UocGxvdGxpc3QgID0gcGx0X2xpc3QpCnByaW50X3RhYihwbHQgPSBwLHRpdGxlID0gImNhbm9uaWNhbCBwYXRod2F5IGVucmljaG1lbnQiKQoKCgpgYGAKIyMgbHVtaW5hbCBhbmQgbXlvIGdlbmVzIGluIHNjb3JlCmBgYHtyIHJlc3VsdHM9J2hvbGQnLGNvbGxhcHNlPVRSVUV9CiMgbHVtIGdlbmVzIGluIG1ldGFnZW5lcwptZXNzYWdlKCJsdW0gZ2VuZXMgaW4gbWV0YWdlbmVzOiIpCmZvciAoaSBpbiAxOm5jb2woZ2VwX3Njb3JlcykpIHsKICB0b3BfZ2VuZXMgPSBnZXBfc2NvcmVzICAlPiUgIGFycmFuZ2UoZGVzYyhnZXBfc2NvcmVzW2ldKSkgI3NvcnQgYnkgc2NvcmUgYQogIHRvcCA9IGhlYWQocm93bmFtZXModG9wX2dlbmVzKSwyMDApICN0YWtlIHRvcCB0b3BfZ2VuZXNfbnVtCiAgY2F0KHBhc3RlMCgibWV0YWdlbmUgIixpLCI6ICIpKQogIHByaW50KG9yaWdpbmFsX2x1bV9nZW5lc1tvcmlnaW5hbF9sdW1fZ2VuZXMgJWluJSB0b3BdKQoKfQpjYXQoIlxuIikKCgojIG15byBnZW5lcyBpbiBtZXRhZ2VuZXMKbWVzc2FnZSgibXlvIGdlbmVzIGluIG1ldGFnZW5lczoiKQpmb3IgKGkgaW4gMTpuY29sKGdlcF9zY29yZXMpKSB7CiAgdG9wX2dlbmVzID0gZ2VwX3Njb3JlcyAgJT4lICBhcnJhbmdlKGRlc2MoZ2VwX3Njb3Jlc1tpXSkpICNzb3J0IGJ5IHNjb3JlIGEKICB0b3AgPSBoZWFkKHJvd25hbWVzKHRvcF9nZW5lcyksMjAwKSAjdGFrZSB0b3AgdG9wX2dlbmVzX251bQogIGNhdChwYXN0ZTAoIm1ldGFnZW5lICIsaSwiOiAiKSkKICBwcmludChvcmlnaW5hbF9teW9fZ2VuZXNbb3JpZ2luYWxfbXlvX2dlbmVzICVpbiUgdG9wXSkKCn0KY2F0KCJcbiIpCgpub3RjaF9nZW5lcyA9IGMoIkpBRzEiLCJKQUcyIiwiTk9UQ0gzIiwiTk9UQ0gyIiwiTk9UQ0gxIiwiRExMMSIsIk1ZQiIsIkhFUzQiLCJIRVkxIiwiSEVZMiIsIk5SQVJQIikKIyBub3RjaCBnZW5lcyBpbiBtZXRhZ2VuZXMKbWVzc2FnZSgibm90Y2ggZ2VuZXMgaW4gbWV0YWdlbmVzOiIpCmZvciAoaSBpbiAxOm5jb2woZ2VwX3Njb3JlcykpIHsKICB0b3BfZ2VuZXMgPSBnZXBfc2NvcmVzICAlPiUgIGFycmFuZ2UoZGVzYyhnZXBfc2NvcmVzW2ldKSkgI3NvcnQgYnkgc2NvcmUgYQogIHRvcCA9IGhlYWQocm93bmFtZXModG9wX2dlbmVzKSwyMDApICN0YWtlIHRvcCB0b3BfZ2VuZXNfbnVtCiAgY2F0KHBhc3RlMCgibWV0YWdlbmUgIixpLCI6ICIpKQogIHByaW50KG5vdGNoX2dlbmVzW25vdGNoX2dlbmVzICVpbiUgdG9wXSkKCn0KY2F0KCJcbiIpCmBgYAoKCgojIE1ldGFnZW5lcyBvbiBBQ0MKCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xMH0KIyBNYWtlIG1ldGFnZW5lIG5hbWVzCmZvciAoaSBpbiAxOm5jb2woYWxsX21ldGFnZW5lcykpIHsKICBjb2xuYW1lcyhhbGxfbWV0YWdlbmVzKVtpXSA9ICJtZXRhZ2VuZS4iICU+JSBwYXN0ZTAoaSkKfQoKCiNhZGQgZWFjaCBtZXRhZ2VuZSB0byBtZXRhZGF0YQpmb3IgKGkgaW4gMTpuY29sKGFsbF9tZXRhZ2VuZXMpKSB7CiAgbWV0YWdlX21ldGFkYXRhID0gYWxsX21ldGFnZW5lcyAlPiUgc2VsZWN0KGkpCiAgYWxsX2FjY19jYW5jZXJfY2VsbHMgPSBBZGRNZXRhRGF0YShvYmplY3QgPSBhbGxfYWNjX2NhbmNlcl9jZWxscyxtZXRhZGF0YSA9IG1ldGFnZV9tZXRhZGF0YSkKfQoKRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWxsX2FjY19jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSBjb2xuYW1lcyhhbGxfbWV0YWdlbmVzKSxtYXguY3V0b2ZmID0gMTAwKQoKYGBgCgpgYGB7cn0KYWxsX2FjY19jYW5jZXJfY2VsbHMgPSBwcm9ncmFtX2Fzc2lnbm1lbnQoZGF0YXNldCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLGxhcmdlcl9ieSA9IDEuMjUscHJvZ3JhbV9uYW1lcyA9IGNvbG5hbWVzKGFsbF9tZXRhZ2VuZXMpKQpgYGAKCgoKCgoKCiMgVU1BUFMgey50YWJzZXR9CgpgYGB7ciBlY2hvPVRSVUUsIHJlc3VsdHM9J2FzaXMnfQpjb2xvcnMgPSAgcmFpbmJvdyhhbGxfYWNjX2NhbmNlcl9jZWxscyRwcm9ncmFtLmFzc2lnbm1lbnQgJT4lIHVuaXF1ZSgpICU+JSBsZW5ndGgoKS0xKQpjb2xvcnMgPSBjKGNvbG9ycywiZ3JleSIpCnByaW50X3RhYihwbHQgPSBEaW1QbG90KG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLGdyb3VwLmJ5ID0gInByb2dyYW0uYXNzaWdubWVudCIsY29scyA9Y29sb3JzKSx0aXRsZSA9ICJwcm9ncmFtLmFzc2lnbm1lbnQiKQpwcmludF90YWIocGx0ID0gRGltUGxvdChvYmplY3QgPSBhbGxfYWNjX2NhbmNlcl9jZWxscyxncm91cC5ieSA9ICJwYXRpZW50LmlkZW50IiksdGl0bGUgPSAicGF0aWVudC5pZGVudCIpCgpwcmludF90YWIocGx0ID0gRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWxsX2FjY19jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSAibHVtX3Njb3JlIiksdGl0bGUgPSAibHVtX3Njb3JlIikKCnByaW50X3RhYihwbHQgPSBGZWF0dXJlUGxvdChvYmplY3QgPSBhbGxfYWNjX2NhbmNlcl9jZWxscyxmZWF0dXJlcyA9ICJteW9fc2NvcmUiKSx0aXRsZSA9ICJteW9fc2NvcmUiKQoKCgpgYGAKIyBtZXRhZ2VuZXMgYnkgbHVtX292ZXJfbXlvCmBgYHtyfQphY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxID0gc3Vic2V0KGFsbF9hY2NfY2FuY2VyX2NlbGxzLHN1YnNldCA9IHBhdGllbnQuaWRlbnQhPSAiQUNDMSIpCgpsdW1TY29yZV92c19wcm9ncmFtID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjY19jYW5jZXJDZWxsc19ub0FDQzEsdmFycyA9IGMoImx1bV9vdmVyX215byIsInByb2dyYW0uYXNzaWdubWVudCIpKQpsdW1TY29yZV92c19wcm9ncmFtJHByb2dyYW0uYXNzaWdubWVudCA8LSBmYWN0b3IobHVtU2NvcmVfdnNfcHJvZ3JhbSRwcm9ncmFtLmFzc2lnbm1lbnQsIGxldmVscyA9IGMoIm1ldGFnZW5lLjEiLCJtZXRhZ2VuZS4yIiwibWV0YWdlbmUuNCIpKQoKbHVtU2NvcmVfdnNfcHJvZ3JhbSA9IGx1bVNjb3JlX3ZzX3Byb2dyYW0gJT4lIGRwbHlyOjpmaWx0ZXIocHJvZ3JhbS5hc3NpZ25tZW50ICVpbiUgYygibWV0YWdlbmUuMSIsIm1ldGFnZW5lLjIiLCJtZXRhZ2VuZS40IikpCmdnYm94cGxvdChsdW1TY29yZV92c19wcm9ncmFtLCB4ID0gInByb2dyYW0uYXNzaWdubWVudCIsIHkgPSAibHVtX292ZXJfbXlvIiwKICAgICAgICAgIHBhbGV0dGUgPSAiamNvIiwKICAgICAgICAgIGFkZCA9ICJqaXR0ZXIiKSsgc3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ3aWxjb3gudGVzdCIsY29tcGFyaXNvbnMgPSBsaXN0KGMoIm1ldGFnZW5lLjEiLCJtZXRhZ2VuZS4yIiksYygibWV0YWdlbmUuMiIsIm1ldGFnZW5lLjQiKSkpCmBgYAojIE1ldGFnZW5lcyBjb3JyZWxhdGlvbiB3aXRoIG15byBzY29yZSB7LnRhYnNldH0KCgoKYGBge3IgZWNobz1UUlVFLCByZXN1bHRzPSdhc2lzJ30KZm9yIChtZXRhZ2VuZSBpbiBjKCJtZXRhZ2VuZS4xIiwibWV0YWdlbmUuMiIsIm1ldGFnZW5lLjQiKSkgewogICBsdW1fc2NvcmVfdnNfcHJvZ3JhbVNjb3JlID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjY19jYW5jZXJDZWxsc19ub0FDQzEsdmFycyA9IGMobWV0YWdlbmUsIm15b19zY29yZSIpKQogIHByaW50X3RhYihwbHQgPSAKICAgIGdnc2NhdHRlcihsdW1fc2NvcmVfdnNfcHJvZ3JhbVNjb3JlLCB4ID0gbWV0YWdlbmUsIHkgPSAibXlvX3Njb3JlIiwgCiAgICAgICAgICAgIGFkZCA9ICJyZWcubGluZSIsIGNvbmYuaW50ID0gVFJVRSwgCiAgICAgICAgICAgIGNvci5jb2VmID0gVFJVRSwgY29yLm1ldGhvZCA9ICJwZWFyc29uIikKICAsdGl0bGUgPSBtZXRhZ2VuZSkKfQogCmBgYAoKCiMgTWV0YWdlbmVzIGNvcnJlbGF0aW9uIHdpdGggbHVtIHNjb3JlIHsudGFic2V0fQpgYGB7ciBlY2hvPVRSVUUsIHJlc3VsdHM9J2FzaXMnfQpmb3IgKG1ldGFnZW5lIGluIGMoIm1ldGFnZW5lLjEiLCJtZXRhZ2VuZS4yIiwibWV0YWdlbmUuNCIpKSB7CiAgIGx1bV9zY29yZV92c19wcm9ncmFtU2NvcmUgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjX2NhbmNlckNlbGxzX25vQUNDMSx2YXJzID0gYyhtZXRhZ2VuZSwibHVtX3Njb3JlIikpCiAgcHJpbnRfdGFiKHBsdCA9IAogICAgZ2dzY2F0dGVyKGx1bV9zY29yZV92c19wcm9ncmFtU2NvcmUsIHggPSBtZXRhZ2VuZSwgeSA9ICJsdW1fc2NvcmUiLCAKICAgICAgICAgICAgYWRkID0gInJlZy5saW5lIiwgY29uZi5pbnQgPSBUUlVFLCAKICAgICAgICAgICAgY29yLmNvZWYgPSBUUlVFLCBjb3IubWV0aG9kID0gInBlYXJzb24iKQogICx0aXRsZSA9IG1ldGFnZW5lKQp9CiAKYGBgCgoKCiMgTm90Y2ggc2NvcmUgey50YWJzZXR9CmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcyd9CmZvciAobWV0YWdlbmUgaW4gYygibWV0YWdlbmUuMSIsIm1ldGFnZW5lLjIiLCJtZXRhZ2VuZS40IikpIHsKICAgbHVtX3Njb3JlX3ZzX3Byb2dyYW1TY29yZSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxLHZhcnMgPSBjKG1ldGFnZW5lLCJub3RjaF9zY29yZSIpKQogIHByaW50X3RhYihwbHQgPSAKICAgIGdnc2NhdHRlcihsdW1fc2NvcmVfdnNfcHJvZ3JhbVNjb3JlLCB4ID0gbWV0YWdlbmUsIHkgPSAibm90Y2hfc2NvcmUiLCAKICAgICAgICAgICAgYWRkID0gInJlZy5saW5lIiwgY29uZi5pbnQgPSBUUlVFLCAKICAgICAgICAgICAgY29yLmNvZWYgPSBUUlVFLCBjb3IubWV0aG9kID0gInBlYXJzb24iKQogICx0aXRsZSA9IG1ldGFnZW5lKQp9CiAKYGBgCgoKCiMgTm90Y2ggIGxpZ2FuZHMgc2NvcmUgey50YWJzZXR9CmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcyd9CmZvciAobWV0YWdlbmUgaW4gYygibWV0YWdlbmUuMSIsIm1ldGFnZW5lLjIiLCJtZXRhZ2VuZS40IikpIHsKICAgbHVtX3Njb3JlX3ZzX3Byb2dyYW1TY29yZSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxLHZhcnMgPSBjKG1ldGFnZW5lLCJub3RjaF9saWdhbmRzX3Njb3JlX3Njb3JlIikpCiAgcHJpbnRfdGFiKHBsdCA9IAogICAgZ2dzY2F0dGVyKGx1bV9zY29yZV92c19wcm9ncmFtU2NvcmUsIHggPSBtZXRhZ2VuZSwgeSA9ICJub3RjaF9saWdhbmRzX3Njb3JlX3Njb3JlIiwgCiAgICAgICAgICAgIGFkZCA9ICJyZWcubGluZSIsIGNvbmYuaW50ID0gVFJVRSwgCiAgICAgICAgICAgIGNvci5jb2VmID0gVFJVRSwgY29yLm1ldGhvZCA9ICJwZWFyc29uIikKICAsdGl0bGUgPSBtZXRhZ2VuZSkKfQogCmBgYAoKIyBtZXRhZ2VuZSAxIHdpdGggbXlvIGdlbmVzIHsudGFic2V0fQoKCmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcyd9Cgpmb3IgKGdlbmUgaW4gb3JpZ2luYWxfbXlvX2dlbmVzKSB7CiAgCiAgbHVtX3Njb3JlX3ZzX3Byb2dyYW1TY29yZSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxLHZhcnMgPSBjKCJtZXRhZ2VuZS4xIixnZW5lKSkKcCA9IGdnc2NhdHRlcihsdW1fc2NvcmVfdnNfcHJvZ3JhbVNjb3JlLCB4ID0gIm1ldGFnZW5lLjEiLCB5ID0gZ2VuZSwgCiAgICAgICAgICBhZGQgPSAicmVnLmxpbmUiLCBjb25mLmludCA9IFRSVUUsIAogICAgICAgICAgY29yLmNvZWYgPSBUUlVFLCBjb3IubWV0aG9kID0gInBlYXJzb24iKQpwcmludF90YWIocGx0ID0gcCx0aXRsZSA9IGdlbmUpCn0KCmBgYAojIG1ldGFnZW5lIDIgd2l0aCBteW8gZ2VuZXMgey50YWJzZXR9CgoKCmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcyd9Cgpmb3IgKGdlbmUgaW4gb3JpZ2luYWxfbXlvX2dlbmVzKSB7CiAgCiAgbHVtX3Njb3JlX3ZzX3Byb2dyYW1TY29yZSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxLHZhcnMgPSBjKCJtZXRhZ2VuZS4yIixnZW5lKSkKcCA9IGdnc2NhdHRlcihsdW1fc2NvcmVfdnNfcHJvZ3JhbVNjb3JlLCB4ID0gIm1ldGFnZW5lLjIiLCB5ID0gZ2VuZSwgCiAgICAgICAgICBhZGQgPSAicmVnLmxpbmUiLCBjb25mLmludCA9IFRSVUUsIAogICAgICAgICAgY29yLmNvZWYgPSBUUlVFLCBjb3IubWV0aG9kID0gInBlYXJzb24iKQpwcmludF90YWIocGx0ID0gcCx0aXRsZSA9IGdlbmUpCn0KCmBgYAoKIyBtZXRhZ2VuZSAyIHdpdGggYWNjIGdlbmVzIHsudGFic2V0fQoKCgpgYGB7ciBlY2hvPVRSVUUsIHJlc3VsdHM9J2FzaXMnfQpub3RjaF9nZW5lcyA9IGMoIkpBRzEiLCJKQUcyIiwiTk9UQ0gzIiwiTk9UQ0gyIiwiTk9UQ0gxIiwiRExMMSIsIk1ZQiIsIkhFUzQiLCJIRVkxIiwiSEVZMiIsIk5SQVJQIikKCmFjY19jYW5jZXJDZWxsc19ub0FDQzEgPSBzdWJzZXQoYWxsX2FjY19jYW5jZXJfY2VsbHMsc3Vic2V0ID0gcGF0aWVudC5pZGVudCE9ICJBQ0MxIikKZm9yIChnZW5lIGluIG5vdGNoX2dlbmVzKSB7CiAgCiAgbHVtX3Njb3JlX3ZzX3Byb2dyYW1TY29yZSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2NfY2FuY2VyQ2VsbHNfbm9BQ0MxLHZhcnMgPSBjKCJtZXRhZ2VuZS4yIixnZW5lKSkKcCA9IGdnc2NhdHRlcihsdW1fc2NvcmVfdnNfcHJvZ3JhbVNjb3JlLCB4ID0gIm1ldGFnZW5lLjIiLCB5ID0gZ2VuZSwgCiAgICAgICAgICBhZGQgPSAicmVnLmxpbmUiLCBjb25mLmludCA9IFRSVUUsIAogICAgICAgICAgY29yLmNvZWYgPSBUUlVFLCBjb3IubWV0aG9kID0gInBlYXJzb24iKQpwcmludF90YWIocGx0ID0gcCx0aXRsZSA9IGdlbmUpCn0KCmBgYAoKCg==