Parameters

suffix = ""
data_to_read = "./Data/acc_cancer_no146_primaryonly15k_cancercells.rds"

functions

Data

acc = read_rds(file = data_to_read)
DimPlot(acc,group.by = "patient.ident")

Immune checkpoints

FeaturePlot(object = acc,features = c("CD247","PDCD1LG2","CTLA4"))

cc_receptor = rownames(acc)[startsWith(x =rownames(acc), prefix = "CCR")]
cc_ligand = rownames(acc)[startsWith(x =rownames(acc), prefix = "CCL")]

CC receptors


i=1
exit = F
while (!exit) {
  
  cat("### ",cc_receptor[i:(i+3)]," \n")
    print(
    FeaturePlot(object = acc,features = cc_receptor[i:(i+3)])
  )
  i= i+4
  if (i > length(cc_receptor)) { exit = T}
   cat(' \n\n')

  plot.new()
  dev.off()

}

CCR4 CCR9 CCR3 CCR1

Warning in FeaturePlot(object = acc, features = cc_receptor[i:(i + 3)]) : All cells have the same value (0) of CCR4.

CCR2 CCR5 CCRL2 CCR6

Warning in FeaturePlot(object = acc, features = cc_receptor[i:(i + 3)]) : All cells have the same value (0) of CCR2. Warning in FeaturePlot(object = acc, features = cc_receptor[i:(i + 3)]) : All cells have the same value (0) of CCR5. Warning in FeaturePlot(object = acc, features = cc_receptor[i:(i + 3)]) : All cells have the same value (0) of CCR6.

CCR7 CCR10 NA NA

Warning in FetchData.Seurat(object = object, vars = c(dims, “ident”, features), : The following requested variables were not found: NA

CC ligands


i=1
exit = F
while (!exit) {
  
  cat("### ",cc_ligand[i:(i+3)]," \n")
    print(
    FeaturePlot(object = acc,features = cc_ligand[i:(i+3)])
  )
  i= i+4
  if (i > length(cc_ligand)) { exit = T}
   cat(' \n\n')

  plot.new()
  dev.off()

}

CCL20 CCL28 CCL26 CCL19

Warning in FeaturePlot(object = acc, features = cc_ligand[i:(i + 3)]) : All cells have the same value (0) of CCL26.

CCL21 CCL22 CCL17 CCL2

CCL7 CCL11 CCL8 CCL13

Warning in FeaturePlot(object = acc, features = cc_ligand[i:(i + 3)]) : All cells have the same value (0) of CCL11. Warning in FeaturePlot(object = acc, features = cc_ligand[i:(i + 3)]) : All cells have the same value (0) of CCL13.

CCL5 CCL16 CCL14 CCL15

Warning in FeaturePlot(object = acc, features = cc_ligand[i:(i + 3)]) : All cells have the same value (0) of CCL16. Warning in FeaturePlot(object = acc, features = cc_ligand[i:(i + 3)]) : All cells have the same value (0) of CCL15.

CCL23 CCL18 CCL3 CCL4

Warning in FeaturePlot(object = acc, features = cc_ligand[i:(i + 3)]) : All cells have the same value (0) of CCL23.

CCL3L3 CCL4L2 CCL25 NA

Warning in FetchData.Seurat(object = object, vars = c(dims, “ident”, features), : The following requested variables were not found: NA Warning in FeaturePlot(object = acc, features = cc_ligand[i:(i + 3)]) : All cells have the same value (0) of CCL3L3.

lumScore = FetchData(object = acc,vars = c("luminal_over_myo"))
lumScore = lumScore %>% mutate(lum_or_myo = case_when( 
  luminal_over_myo > 1  ~ "luminal",
  luminal_over_myo < (-1)  ~ "myo",
  TRUE ~ "NA"))

acc = AddMetaData(object = acc,metadata = lumScore)
DimPlot(acc,group.by = "lum_or_myo")
lumScore_vs_program = FetchData(object = acc,vars = c("CCL28","lum_or_myo"))
lumScore_vs_program = lumScore_vs_program %>% dplyr::filter(lum_or_myo != "NA")
ggboxplot(lumScore_vs_program, x = "lum_or_myo", y = "CCL28",
          palette = "jco",
          add = "jitter")+ stat_compare_means(method = "wilcox.test",comparisons = list(c("luminal","myo")))+
  stat_summary(fun.data = function(x) data.frame(y=11, label = paste("Mean=",mean(x))), geom="text") +
     theme(legend.position="none")


lumScore_vs_program = FetchData(object = acc,vars = c("CCL22","lum_or_myo"))
lumScore_vs_program = lumScore_vs_program %>% dplyr::filter(lum_or_myo != "NA")
ggboxplot(lumScore_vs_program, x = "lum_or_myo", y = "CCL22",
          palette = "jco",
          add = "jitter")+ stat_compare_means(method = "wilcox.test",comparisons = list(c("luminal","myo")))+ 
     stat_summary(fun.data = function(x) data.frame(y=11, label = paste("Mean=",mean(x))), geom="text") +
     theme(legend.position="none")

cxc_receptor = rownames(acc)[startsWith(x =rownames(acc), prefix = "CXCR")]
cxc_ligand = rownames(acc)[startsWith(x =rownames(acc), prefix = "CXCL")]

CXC receptors


i=1
exit = F
while (!exit) {
  
  cat("### ",cxc_receptor[i:(i+3)]," \n")
    print(
    FeaturePlot(object = acc,features = cxc_receptor[i:(i+3)])
  )
  i= i+4
  if (i > length(cxc_receptor)) { exit = T}
   cat(' \n\n')

  plot.new()
  dev.off()

}

CXCR4 CXCR2 CXCR6 CXCR5

CXCR3 NA NA NA

Warning in FetchData.Seurat(object = object, vars = c(dims, “ident”, features), : The following requested variables were not found: NA

CXC ligands


i=1
exit = F
while (!exit) {
  
  cat("### ",cxc_ligand[i:(i+3)]," \n")
    print(
    FeaturePlot(object = acc,features = cxc_ligand[i:(i+3)])
  )
  i= i+4
  if (i > length(cxc_ligand)) { exit = T}
   cat(' \n\n')

  plot.new()
  dev.off()

}

CXCL8 CXCL6 CXCL1 CXCL5

CXCL3 CXCL2 CXCL9 CXCL10

CXCL11 CXCL13 CXCL14 CXCL12

Warning in FeaturePlot(object = acc, features = cxc_ligand[i:(i + 3)]) : All cells have the same value (0) of CXCL13.

CXCL16 CXCL17 NA NA

Warning in FetchData.Seurat(object = object, vars = c(dims, “ident”, features), : The following requested variables were not found: NA

lumScore_vs_program = FetchData(object = acc,vars = c("CXCL14","lum_or_myo"))
lumScore_vs_program = lumScore_vs_program %>% dplyr::filter(lum_or_myo != "NA")
ggboxplot(lumScore_vs_program, x = "lum_or_myo", y = "CXCL14",
          palette = "jco",
          add = "jitter")+ stat_compare_means(method = "wilcox.test",comparisons = list(c("luminal","myo")))+
  stat_summary(fun.data = function(x) data.frame(y=16, label = paste("Mean=",mean(x))), geom="text") +
     theme(legend.position="none")

NA
NA
NA

IL receptors genes

il_receptors_genes = rownames(acc)[grepl("^IL\\d*R.*", rownames(acc))]

i=1
exit = F
while (!exit) {
  
  cat("### ",il_receptors_genes[i:(i+3)]," \n")
    print(
    FeaturePlot(object = acc,features = il_receptors_genes[i:(i+3)])
  )
  i= i+4
  if (i > length(il_receptors_genes)) { exit = T}
   cat(' \n\n')

  plot.new()
  dev.off()

}

IL22RA1 IL23R IL12RB2 IL6R

IL1R2 IL1R1 IL1RL2 IL1RL1

IL18R1 IL18RAP IL36RN IL1RN

IL8RBP IL5RA IL17RE IL17RC

IL17RB IL17RD IL20RB IL1RAP

IL7R IL31RA IL20RA IL22RA2

Warning in FeaturePlot(object = acc, features = il_receptors_genes[i:(i + : All cells have the same value (0) of IL22RA2.

IL11RA IL9RP2 IL15RA IL2RA

IL10RA IL4R IL21R IL9RP4

Warning in FeaturePlot(object = acc, features = il_receptors_genes[i:(i + : All cells have the same value (0) of IL21R.

IL27RA IL12RB1 IL10RB IL17RA

IL2RB IL17REL IL3RA IL1RAPL1

IL2RG IL1RAPL2 IL13RA2 IL13RA1

Warning in FeaturePlot(object = acc, features = il_receptors_genes[i:(i + : All cells have the same value (0) of IL13RA2.

IL9R NA NA NA

Warning in FetchData.Seurat(object = object, vars = c(dims, “ident”, features), : The following requested variables were not found: NA

Classical HLA 1 genes

hla_genes = rownames(acc)[startsWith(x =rownames(acc), prefix = "HLA")]
hla_class_2 = hla_genes[startsWith(x =hla_genes, prefix = "HLA-D")]
hla_class_1 = hla_genes[!startsWith(x =hla_genes, prefix = "HLA-D")]
FeaturePlot(object = acc,features = c("HLA-A","HLA-B","HLA-C"))

Non-classical HLA 1 genes


i=1
exit = F
non_classical  = hla_class_1 [!hla_class_1 %in% c("HLA-A","HLA-B","HLA-C")] %>% sort()
while (!exit) {
  
  cat("### ",non_classical[i:(i+3)]," \n")
    print(
    FeaturePlot(object = acc,features = non_classical[i:(i+3)])
  )
  i= i+4
  if (i > length(non_classical)) { exit = T}
   cat(' \n\n')

  plot.new()
  dev.off()

}

HLA-E HLA-F HLA-G HLA-H

HLA-J HLA-K HLA-L HLA-N

HLA-P HLA-S HLA-T HLA-U

HLA-V HLA-W HLA-Z NA

Warning in FetchData.Seurat(object = object, vars = c(dims, “ident”, features), : The following requested variables were not found: NA

acc= AddModuleScore(object = acc,features = list(c("HLA-T","HLA-G","HLA-H","HLA-K","HLA-W","HLA-L","HLA-F","HLA-J")),name = "hla_score")
FeaturePlot(object = acc,features = "hla_score1")

HLA 2 genes

i=1

exit = F
while (!exit) {
    cat("### ",hla_class_2[i:(i+3)]," \n")

    print(
    FeaturePlot(object = acc,features = hla_class_2[i:(i+3)])
  )
 i= i+4
  if (i > length(hla_class_2)) { exit = T}
   cat(' \n\n')

  plot.new()
  dev.off()
}

IL17RD

    FeaturePlot(object = acc,features = "IL17RD")

acc = SetIdent(object = acc,value = "lum_or_myo")
deg = FindMarkers(object = acc,ident.1 = "luminal",ident.2 = "myo",densify = T,logfc.threshold = 0)
deg  =deg %>% mutate(fdr = p.adjust(p_val,method = "fdr"))%>% #add fdr
    filter((avg_log2FC>1 & fdr<0.1) | (avg_log2FC< (-1) & fdr<0.1))  #filter significant
deg
str_detect(rownames(deg), "HLA") %>% table()
.
FALSE  TRUE 
 2681     7 
 rownames(deg)[which(str_detect(rownames(deg), "HLA"))]
[1] "HLA-B"    "HLA-L"    "HLA-DRB5" "HLA-DRB1" "HLA-W"    "HLA-DRB6" "HLA-F"   
deg_hla = rownames(deg)[which(str_detect(rownames(deg), "HLA"))]
deg %>% dplyr::filter(row.names(deg) %in% deg_hla)
lumScore_vs_program = FetchData(object = acc,vars = c("HLA-B","lum_or_myo"))
lumScore_vs_program = lumScore_vs_program %>% dplyr::filter(lum_or_myo != "NA")
ggboxplot(lumScore_vs_program, x = "lum_or_myo", y = "HLA-B",
          palette = "jco",
          add = "jitter")+ stat_compare_means(method = "wilcox.test",comparisons = list(c("luminal","myo")))+
  stat_summary(fun.data = function(x) data.frame(y=16, label = paste("Mean=",mean(x))), geom="text") +
     theme(legend.position="none")

NA
NA
NA

intersect with GO “immune response GO:0006955

# ensembl = useMart("ensembl",dataset="hsapiens_gene_ensembl") #uses human ensembl annotations
# 
#  immune_genes <- getBM(attributes=c('hgnc_symbol'),
#        filters = 'go', values = 'GO:0002376', mart = ensembl)

immune_genes = fread(input = "./Data/GO_term_summary_20230218_165937.txt",sep = "\t", select = 2) %>% pull(1)
Warning in fread(input = "./Data/GO_term_summary_20230218_165937.txt", sep = "\t",  :
  Detected 11 column names but the data has 12 columns (i.e. invalid file). Added 1 extra default column name for the first column which is guessed to be row names or an index. Use setnames() afterwards if this guess is not correct, or fix the file write command that created the file to create a valid file.
intersect(rownames(deg),immune_genes)
[1] "C3"
FeaturePlot(object = acc_cancer,features = "C3")

FeaturePlot(object = acc_cancer,features = "RARA")

library(msigdbr)

genes = msigdbr(species = "Homo sapiens", category = "C2") %>% filter(gs_subcat != "CGP" & grepl('RETINOIC', gs_name))

retinoic_acid_pathways = unique(genes$gs_name)
retinoic_acid_pathways = retinoic_acid_pathways[c(1,2)] #take relevant pathways


for (pathway in retinoic_acid_pathways) {
  pathway_genes = genes %>% filter(gs_name == pathway) %>% pull("gene_symbol")
  print(
    deg %>% dplyr::filter(row.names(deg) %in% intersect(rownames(deg),pathway_genes))
  )
  sig_genes = deg %>% dplyr::filter(row.names(deg) %in% intersect(rownames(deg),pathway_genes)) %>% rownames()

#   for (gene  in sig_genes) {
#     lumScore_vs_gene = FetchData(object = acc,vars = c(gene,"lum_or_myo"))
# lumScore_vs_gene = lumScore_vs_gene %>% dplyr::filter(lum_or_myo != "NA")
# p = ggboxplot(lumScore_vs_gene, x = "lum_or_myo", y = gene,
#           palette = "jco",
#           add = "jitter")+ stat_compare_means(method = "wilcox.test",comparisons = list(c("luminal","myo")))+
#   stat_summary(fun.data = function(x) data.frame(y=16, label = paste("Mean=",mean(x))), geom="text") +
#      theme(legend.position="none")
# 
# print(p)
#   }
}
NA
NA
NA
NA

https://reactome.org/PathwayBrowser/#/R-HSA-5362517

for (pathway in retinoic_acid_pathways) {
  pathway_genes = genes %>% filter(gs_name == pathway) %>% pull("gene_symbol")
  geneIds = intersect(pathway_genes, VariableFeatures(acc)[1:10000])
  score <- apply(acc@assays$RNA@data[geneIds,],2,mean)
  acc=AddMetaData(acc,score,col.name = pathway)
}
LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMuRGF0ZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCi0tLQoKIyMgUGFyYW1ldGVycwoKYGBge3Igd2FybmluZz1GQUxTRX0Kc3VmZml4ID0gIiIKZGF0YV90b19yZWFkID0gIi4vRGF0YS9hY2NfY2FuY2VyX25vMTQ2X3ByaW1hcnlvbmx5MTVrX2NhbmNlcmNlbGxzLnJkcyIKYGBgCgoKIyMgZnVuY3Rpb25zCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpgYGAKCiMjIERhdGEKCmBgYHtyfQphY2MgPSByZWFkX3JkcyhmaWxlID0gZGF0YV90b19yZWFkKQpgYGAKCmBgYHtyfQpEaW1QbG90KGFjYyxncm91cC5ieSA9ICJwYXRpZW50LmlkZW50IikKYGBgCiMjIEltbXVuZSBjaGVja3BvaW50cwpgYGB7cn0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gYygiQ0QyNDciLCJQRENEMUxHMiIsIkNUTEE0IikpCmBgYAoKCmBgYHtyfQpjY19yZWNlcHRvciA9IHJvd25hbWVzKGFjYylbc3RhcnRzV2l0aCh4ID1yb3duYW1lcyhhY2MpLCBwcmVmaXggPSAiQ0NSIildCmNjX2xpZ2FuZCA9IHJvd25hbWVzKGFjYylbc3RhcnRzV2l0aCh4ID1yb3duYW1lcyhhY2MpLCBwcmVmaXggPSAiQ0NMIildCgpgYGAKCiMjIENDIHJlY2VwdG9ycyB7LnRhYnNldH0KCmBgYHtyIGVjaG89VFJVRSwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE0LCByZXN1bHRzPSdhc2lzJ30KCmk9MQpleGl0ID0gRgp3aGlsZSAoIWV4aXQpIHsKICAKICBjYXQoIiMjIyAiLGNjX3JlY2VwdG9yW2k6KGkrMyldLCIgXG4iKQogICAgcHJpbnQoCiAgICBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MsZmVhdHVyZXMgPSBjY19yZWNlcHRvcltpOihpKzMpXSkKICApCiAgaT0gaSs0CiAgaWYgKGkgPiBsZW5ndGgoY2NfcmVjZXB0b3IpKSB7IGV4aXQgPSBUfQogICBjYXQoJyBcblxuJykKCiAgcGxvdC5uZXcoKQogIGRldi5vZmYoKQoKfQoKYGBgCgojIyBDQyBsaWdhbmRzIHsudGFic2V0fQoKYGBge3IgZWNobz1UUlVFLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTQsIHJlc3VsdHM9J2FzaXMnfQoKaT0xCmV4aXQgPSBGCndoaWxlICghZXhpdCkgewogIAogIGNhdCgiIyMjICIsY2NfbGlnYW5kW2k6KGkrMyldLCIgXG4iKQogICAgcHJpbnQoCiAgICBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MsZmVhdHVyZXMgPSBjY19saWdhbmRbaTooaSszKV0pCiAgKQogIGk9IGkrNAogIGlmIChpID4gbGVuZ3RoKGNjX2xpZ2FuZCkpIHsgZXhpdCA9IFR9CiAgIGNhdCgnIFxuXG4nKQoKICBwbG90Lm5ldygpCiAgZGV2Lm9mZigpCgp9CgpgYGAKYGBge3J9Cmx1bVNjb3JlID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYyx2YXJzID0gYygibHVtaW5hbF9vdmVyX215byIpKQpsdW1TY29yZSA9IGx1bVNjb3JlICU+JSBtdXRhdGUobHVtX29yX215byA9IGNhc2Vfd2hlbiggCiAgbHVtaW5hbF9vdmVyX215byA+IDEgIH4gImx1bWluYWwiLAogIGx1bWluYWxfb3Zlcl9teW8gPCAoLTEpICB+ICJteW8iLAogIFRSVUUgfiAiTkEiKSkKCmFjYyA9IEFkZE1ldGFEYXRhKG9iamVjdCA9IGFjYyxtZXRhZGF0YSA9IGx1bVNjb3JlKQpEaW1QbG90KGFjYyxncm91cC5ieSA9ICJsdW1fb3JfbXlvIikKYGBgCgpgYGB7cn0KbHVtU2NvcmVfdnNfcHJvZ3JhbSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MsdmFycyA9IGMoIkNDTDI4IiwibHVtX29yX215byIpKQpsdW1TY29yZV92c19wcm9ncmFtID0gbHVtU2NvcmVfdnNfcHJvZ3JhbSAlPiUgZHBseXI6OmZpbHRlcihsdW1fb3JfbXlvICE9ICJOQSIpCmdnYm94cGxvdChsdW1TY29yZV92c19wcm9ncmFtLCB4ID0gImx1bV9vcl9teW8iLCB5ID0gIkNDTDI4IiwKICAgICAgICAgIHBhbGV0dGUgPSAiamNvIiwKICAgICAgICAgIGFkZCA9ICJqaXR0ZXIiKSsgc3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ3aWxjb3gudGVzdCIsY29tcGFyaXNvbnMgPSBsaXN0KGMoImx1bWluYWwiLCJteW8iKSkpKwogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IGZ1bmN0aW9uKHgpIGRhdGEuZnJhbWUoeT0xMSwgbGFiZWwgPSBwYXN0ZSgiTWVhbj0iLG1lYW4oeCkpKSwgZ2VvbT0idGV4dCIpICsKICAgICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQoKbHVtU2NvcmVfdnNfcHJvZ3JhbSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MsdmFycyA9IGMoIkNDTDIyIiwibHVtX29yX215byIpKQpsdW1TY29yZV92c19wcm9ncmFtID0gbHVtU2NvcmVfdnNfcHJvZ3JhbSAlPiUgZHBseXI6OmZpbHRlcihsdW1fb3JfbXlvICE9ICJOQSIpCmdnYm94cGxvdChsdW1TY29yZV92c19wcm9ncmFtLCB4ID0gImx1bV9vcl9teW8iLCB5ID0gIkNDTDIyIiwKICAgICAgICAgIHBhbGV0dGUgPSAiamNvIiwKICAgICAgICAgIGFkZCA9ICJqaXR0ZXIiKSsgc3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ3aWxjb3gudGVzdCIsY29tcGFyaXNvbnMgPSBsaXN0KGMoImx1bWluYWwiLCJteW8iKSkpKyAKICAgICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBmdW5jdGlvbih4KSBkYXRhLmZyYW1lKHk9MTEsIGxhYmVsID0gcGFzdGUoIk1lYW49IixtZWFuKHgpKSksIGdlb209InRleHQiKSArCiAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKCmBgYAoKCgpgYGB7cn0KY3hjX3JlY2VwdG9yID0gcm93bmFtZXMoYWNjKVtzdGFydHNXaXRoKHggPXJvd25hbWVzKGFjYyksIHByZWZpeCA9ICJDWENSIildCmN4Y19saWdhbmQgPSByb3duYW1lcyhhY2MpW3N0YXJ0c1dpdGgoeCA9cm93bmFtZXMoYWNjKSwgcHJlZml4ID0gIkNYQ0wiKV0KYGBgCgoKIyMgQ1hDIHJlY2VwdG9ycyB7LnRhYnNldH0KCmBgYHtyIGVjaG89VFJVRSwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE0LCByZXN1bHRzPSdhc2lzJ30KCmk9MQpleGl0ID0gRgp3aGlsZSAoIWV4aXQpIHsKICAKICBjYXQoIiMjIyAiLGN4Y19yZWNlcHRvcltpOihpKzMpXSwiIFxuIikKICAgIHByaW50KAogICAgRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gY3hjX3JlY2VwdG9yW2k6KGkrMyldKQogICkKICBpPSBpKzQKICBpZiAoaSA+IGxlbmd0aChjeGNfcmVjZXB0b3IpKSB7IGV4aXQgPSBUfQogICBjYXQoJyBcblxuJykKCiAgcGxvdC5uZXcoKQogIGRldi5vZmYoKQoKfQoKYGBgCgojIyBDWEMgbGlnYW5kcyB7LnRhYnNldH0KCmBgYHtyIGVjaG89VFJVRSwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE0LCByZXN1bHRzPSdhc2lzJ30KCmk9MQpleGl0ID0gRgp3aGlsZSAoIWV4aXQpIHsKICAKICBjYXQoIiMjIyAiLGN4Y19saWdhbmRbaTooaSszKV0sIiBcbiIpCiAgICBwcmludCgKICAgIEZlYXR1cmVQbG90KG9iamVjdCA9IGFjYyxmZWF0dXJlcyA9IGN4Y19saWdhbmRbaTooaSszKV0pCiAgKQogIGk9IGkrNAogIGlmIChpID4gbGVuZ3RoKGN4Y19saWdhbmQpKSB7IGV4aXQgPSBUfQogICBjYXQoJyBcblxuJykKCiAgcGxvdC5uZXcoKQogIGRldi5vZmYoKQoKfQoKYGBgCgpgYGB7cn0KbHVtU2NvcmVfdnNfcHJvZ3JhbSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MsdmFycyA9IGMoIkNYQ0wxNCIsImx1bV9vcl9teW8iKSkKbHVtU2NvcmVfdnNfcHJvZ3JhbSA9IGx1bVNjb3JlX3ZzX3Byb2dyYW0gJT4lIGRwbHlyOjpmaWx0ZXIobHVtX29yX215byAhPSAiTkEiKQpnZ2JveHBsb3QobHVtU2NvcmVfdnNfcHJvZ3JhbSwgeCA9ICJsdW1fb3JfbXlvIiwgeSA9ICJDWENMMTQiLAogICAgICAgICAgcGFsZXR0ZSA9ICJqY28iLAogICAgICAgICAgYWRkID0gImppdHRlciIpKyBzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gIndpbGNveC50ZXN0Iixjb21wYXJpc29ucyA9IGxpc3QoYygibHVtaW5hbCIsIm15byIpKSkrCiAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gZnVuY3Rpb24oeCkgZGF0YS5mcmFtZSh5PTE2LCBsYWJlbCA9IHBhc3RlKCJNZWFuPSIsbWVhbih4KSkpLCBnZW9tPSJ0ZXh0IikgKwogICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpCgoKCmBgYAoKIyMgSUwgcmVjZXB0b3JzIGdlbmVzIHsudGFic2V0fQpgYGB7cn0KaWxfcmVjZXB0b3JzX2dlbmVzID0gcm93bmFtZXMoYWNjKVtncmVwbCgiXklMXFxkKlIuKiIsIHJvd25hbWVzKGFjYykpXQpgYGAKCmBgYHtyIGVjaG89VFJVRSwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE0LCByZXN1bHRzPSdhc2lzJ30KCmk9MQpleGl0ID0gRgp3aGlsZSAoIWV4aXQpIHsKICAKICBjYXQoIiMjIyAiLGlsX3JlY2VwdG9yc19nZW5lc1tpOihpKzMpXSwiIFxuIikKICAgIHByaW50KAogICAgRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gaWxfcmVjZXB0b3JzX2dlbmVzW2k6KGkrMyldKQogICkKICBpPSBpKzQKICBpZiAoaSA+IGxlbmd0aChpbF9yZWNlcHRvcnNfZ2VuZXMpKSB7IGV4aXQgPSBUfQogICBjYXQoJyBcblxuJykKCiAgcGxvdC5uZXcoKQogIGRldi5vZmYoKQoKfQoKYGBgCiMjIENsYXNzaWNhbCAgSExBIDEgZ2VuZXMgey50YWJzZXR9CgpgYGB7cn0KaGxhX2dlbmVzID0gcm93bmFtZXMoYWNjKVtzdGFydHNXaXRoKHggPXJvd25hbWVzKGFjYyksIHByZWZpeCA9ICJITEEiKV0KaGxhX2NsYXNzXzIgPSBobGFfZ2VuZXNbc3RhcnRzV2l0aCh4ID1obGFfZ2VuZXMsIHByZWZpeCA9ICJITEEtRCIpXQpobGFfY2xhc3NfMSA9IGhsYV9nZW5lc1shc3RhcnRzV2l0aCh4ID1obGFfZ2VuZXMsIHByZWZpeCA9ICJITEEtRCIpXQoKYGBgCgpgYGB7ciBlY2hvPVRSVUUsIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNCwgcmVzdWx0cz0nYXNpcyd9CkZlYXR1cmVQbG90KG9iamVjdCA9IGFjYyxmZWF0dXJlcyA9IGMoIkhMQS1BIiwiSExBLUIiLCJITEEtQyIpKQpgYGAKCgoKIyMgTm9uLWNsYXNzaWNhbCAgSExBIDEgZ2VuZXMgey50YWJzZXR9CgpgYGB7ciBlY2hvPVRSVUUsIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNCwgcmVzdWx0cz0nYXNpcyd9CgppPTEKZXhpdCA9IEYKbm9uX2NsYXNzaWNhbCAgPSBobGFfY2xhc3NfMSBbIWhsYV9jbGFzc18xICVpbiUgYygiSExBLUEiLCJITEEtQiIsIkhMQS1DIildICU+JSBzb3J0KCkKd2hpbGUgKCFleGl0KSB7CiAgCiAgY2F0KCIjIyMgIixub25fY2xhc3NpY2FsW2k6KGkrMyldLCIgXG4iKQogICAgcHJpbnQoCiAgICBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MsZmVhdHVyZXMgPSBub25fY2xhc3NpY2FsW2k6KGkrMyldKQogICkKICBpPSBpKzQKICBpZiAoaSA+IGxlbmd0aChub25fY2xhc3NpY2FsKSkgeyBleGl0ID0gVH0KICAgY2F0KCcgXG5cbicpCgogIHBsb3QubmV3KCkKICBkZXYub2ZmKCkKCn0KCmBgYApgYGB7cn0KaGxhID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYyx2YXJzID0gbm9uX2NsYXNzaWNhbCkKCmNvcl9yZXMgPSBjb3IoaGxhKQpwaGVhdG1hcChjb3JfcmVzKQpgYGAKYGBge3J9CmFjYz0gQWRkTW9kdWxlU2NvcmUob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gbGlzdChjKCJITEEtVCIsIkhMQS1HIiwiSExBLUgiLCJITEEtSyIsIkhMQS1XIiwiSExBLUwiLCJITEEtRiIsIkhMQS1KIikpLG5hbWUgPSAiaGxhX3Njb3JlIikKYGBgCgpgYGB7cn0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gImhsYV9zY29yZTEiKQpgYGAKCiMjIEhMQSAyIGdlbmVzIHsudGFic2V0fQpgYGB7ciBlY2hvPVRSVUUsIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNCwgcmVzdWx0cz0nYXNpcyd9Cmk9MQoKZXhpdCA9IEYKd2hpbGUgKCFleGl0KSB7CiAgICBjYXQoIiMjIyAiLGhsYV9jbGFzc18yW2k6KGkrMyldLCIgXG4iKQoKICAgIHByaW50KAogICAgRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjLGZlYXR1cmVzID0gaGxhX2NsYXNzXzJbaTooaSszKV0pCiAgKQogaT0gaSs0CiAgaWYgKGkgPiBsZW5ndGgoaGxhX2NsYXNzXzIpKSB7IGV4aXQgPSBUfQogICBjYXQoJyBcblxuJykKCiAgcGxvdC5uZXcoKQogIGRldi5vZmYoKQp9CgpgYGAKIyMgSUwxN1JEIApgYGB7ciBmaWcud2lkdGg9MTB9CiAgICBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2MsZmVhdHVyZXMgPSAiSUwxN1JEIikKYGBgCgoKYGBge3J9CmFjYyA9IFNldElkZW50KG9iamVjdCA9IGFjYyx2YWx1ZSA9ICJsdW1fb3JfbXlvIikKZGVnID0gRmluZE1hcmtlcnMob2JqZWN0ID0gYWNjLGlkZW50LjEgPSAibHVtaW5hbCIsaWRlbnQuMiA9ICJteW8iLGRlbnNpZnkgPSBULGxvZ2ZjLnRocmVzaG9sZCA9IDApCmBgYAoKYGBge3J9CmRlZyAgPWRlZyAlPiUgbXV0YXRlKGZkciA9IHAuYWRqdXN0KHBfdmFsLG1ldGhvZCA9ICJmZHIiKSklPiUgI2FkZCBmZHIKICAgIGZpbHRlcigoYXZnX2xvZzJGQz4xICYgZmRyPDAuMSkgfCAoYXZnX2xvZzJGQzwgKC0xKSAmIGZkcjwwLjEpKSAgI2ZpbHRlciBzaWduaWZpY2FudApgYGAKCmBgYHtyfQpkZWcKYGBgCmBgYHtyfQpzdHJfZGV0ZWN0KHJvd25hbWVzKGRlZyksICJITEEiKSAlPiUgdGFibGUoKQogcm93bmFtZXMoZGVnKVt3aGljaChzdHJfZGV0ZWN0KHJvd25hbWVzKGRlZyksICJITEEiKSldCmRlZ19obGEgPSByb3duYW1lcyhkZWcpW3doaWNoKHN0cl9kZXRlY3Qocm93bmFtZXMoZGVnKSwgIkhMQSIpKV0KYGBgCmBgYHtyfQpkZWcgJT4lIGRwbHlyOjpmaWx0ZXIocm93Lm5hbWVzKGRlZykgJWluJSBkZWdfaGxhKQpgYGAKCmBgYHtyfQpsdW1TY29yZV92c19wcm9ncmFtID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYyx2YXJzID0gYygiSExBLUIiLCJsdW1fb3JfbXlvIikpCmx1bVNjb3JlX3ZzX3Byb2dyYW0gPSBsdW1TY29yZV92c19wcm9ncmFtICU+JSBkcGx5cjo6ZmlsdGVyKGx1bV9vcl9teW8gIT0gIk5BIikKZ2dib3hwbG90KGx1bVNjb3JlX3ZzX3Byb2dyYW0sIHggPSAibHVtX29yX215byIsIHkgPSAiSExBLUIiLAogICAgICAgICAgcGFsZXR0ZSA9ICJqY28iLAogICAgICAgICAgYWRkID0gImppdHRlciIpKyBzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gIndpbGNveC50ZXN0Iixjb21wYXJpc29ucyA9IGxpc3QoYygibHVtaW5hbCIsIm15byIpKSkrCiAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gZnVuY3Rpb24oeCkgZGF0YS5mcmFtZSh5PTE2LCBsYWJlbCA9IHBhc3RlKCJNZWFuPSIsbWVhbih4KSkpLCBnZW9tPSJ0ZXh0IikgKwogICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpCgoKCmBgYAppbnRlcnNlY3Qgd2l0aCBHTyAiaW1tdW5lIHJlc3BvbnNlIEdPOjAwMDY5NTUiCmBgYHtyfQojIGVuc2VtYmwgPSB1c2VNYXJ0KCJlbnNlbWJsIixkYXRhc2V0PSJoc2FwaWVuc19nZW5lX2Vuc2VtYmwiKSAjdXNlcyBodW1hbiBlbnNlbWJsIGFubm90YXRpb25zCiMgCiMgIGltbXVuZV9nZW5lcyA8LSBnZXRCTShhdHRyaWJ1dGVzPWMoJ2hnbmNfc3ltYm9sJyksCiMgICAgICAgIGZpbHRlcnMgPSAnZ28nLCB2YWx1ZXMgPSAnR086MDAwMjM3NicsIG1hcnQgPSBlbnNlbWJsKQoKaW1tdW5lX2dlbmVzID0gZnJlYWQoaW5wdXQgPSAiLi9EYXRhL0dPX3Rlcm1fc3VtbWFyeV8yMDIzMDIxOF8xNjU5MzcudHh0IixzZXAgPSAiXHQiLCBzZWxlY3QgPSAyKSAlPiUgcHVsbCgxKQppbnRlcnNlY3Qocm93bmFtZXMoZGVnKSxpbW11bmVfZ2VuZXMpCmBgYApgYGB7cn0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjX2NhbmNlcixmZWF0dXJlcyA9ICJDMyIpCmBgYApgYGB7cn0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjX2NhbmNlcixmZWF0dXJlcyA9ICJSQVJBIikKYGBgCgpgYGB7cn0KbGlicmFyeShtc2lnZGJyKQoKZ2VuZXMgPSBtc2lnZGJyKHNwZWNpZXMgPSAiSG9tbyBzYXBpZW5zIiwgY2F0ZWdvcnkgPSAiQzIiKSAlPiUgZmlsdGVyKGdzX3N1YmNhdCAhPSAiQ0dQIiAmIGdyZXBsKCdSRVRJTk9JQycsIGdzX25hbWUpKQoKcmV0aW5vaWNfYWNpZF9wYXRod2F5cyA9IHVuaXF1ZShnZW5lcyRnc19uYW1lKQpyZXRpbm9pY19hY2lkX3BhdGh3YXlzID0gcmV0aW5vaWNfYWNpZF9wYXRod2F5c1tjKDEsMildICN0YWtlIHJlbGV2YW50IHBhdGh3YXlzCgoKZm9yIChwYXRod2F5IGluIHJldGlub2ljX2FjaWRfcGF0aHdheXMpIHsKICBwYXRod2F5X2dlbmVzID0gZ2VuZXMgJT4lIGZpbHRlcihnc19uYW1lID09IHBhdGh3YXkpICU+JSBwdWxsKCJnZW5lX3N5bWJvbCIpCiAgcHJpbnQoCiAgICBkZWcgJT4lIGRwbHlyOjpmaWx0ZXIocm93Lm5hbWVzKGRlZykgJWluJSBpbnRlcnNlY3Qocm93bmFtZXMoZGVnKSxwYXRod2F5X2dlbmVzKSkKICApCiAgc2lnX2dlbmVzID0gZGVnICU+JSBkcGx5cjo6ZmlsdGVyKHJvdy5uYW1lcyhkZWcpICVpbiUgaW50ZXJzZWN0KHJvd25hbWVzKGRlZykscGF0aHdheV9nZW5lcykpICU+JSByb3duYW1lcygpCgojICAgZm9yIChnZW5lICBpbiBzaWdfZ2VuZXMpIHsKIyAgICAgbHVtU2NvcmVfdnNfZ2VuZSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MsdmFycyA9IGMoZ2VuZSwibHVtX29yX215byIpKQojIGx1bVNjb3JlX3ZzX2dlbmUgPSBsdW1TY29yZV92c19nZW5lICU+JSBkcGx5cjo6ZmlsdGVyKGx1bV9vcl9teW8gIT0gIk5BIikKIyBwID0gZ2dib3hwbG90KGx1bVNjb3JlX3ZzX2dlbmUsIHggPSAibHVtX29yX215byIsIHkgPSBnZW5lLAojICAgICAgICAgICBwYWxldHRlID0gImpjbyIsCiMgICAgICAgICAgIGFkZCA9ICJqaXR0ZXIiKSsgc3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ3aWxjb3gudGVzdCIsY29tcGFyaXNvbnMgPSBsaXN0KGMoImx1bWluYWwiLCJteW8iKSkpKwojICAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gZnVuY3Rpb24oeCkgZGF0YS5mcmFtZSh5PTE2LCBsYWJlbCA9IHBhc3RlKCJNZWFuPSIsbWVhbih4KSkpLCBnZW9tPSJ0ZXh0IikgKwojICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKIyAKIyBwcmludChwKQojICAgfQp9CgoKCgpgYGAKCmh0dHBzOi8vcmVhY3RvbWUub3JnL1BhdGh3YXlCcm93c2VyLyMvUi1IU0EtNTM2MjUxNwoKYGBge3J9CmZvciAocGF0aHdheSBpbiByZXRpbm9pY19hY2lkX3BhdGh3YXlzKSB7CiAgcGF0aHdheV9nZW5lcyA9IGdlbmVzICU+JSBmaWx0ZXIoZ3NfbmFtZSA9PSBwYXRod2F5KSAlPiUgcHVsbCgiZ2VuZV9zeW1ib2wiKQogIGdlbmVJZHMgPSBpbnRlcnNlY3QocGF0aHdheV9nZW5lcywgVmFyaWFibGVGZWF0dXJlcyhhY2MpWzE6MTAwMDBdKQogIHNjb3JlIDwtIGFwcGx5KGFjY0Bhc3NheXMkUk5BQGRhdGFbZ2VuZUlkcyxdLDIsbWVhbikKICBhY2M9QWRkTWV0YURhdGEoYWNjLHNjb3JlLGNvbC5uYW1lID0gcGF0aHdheSkKfQpgYGAKCgo=