1 Functions

library(GSEABase)
filter_pathways <- function(pathway,dataset) {
  genes_in_data = pathway@geneIds %in% rownames(dataset) %>% sum()
  pathway@setName = paste( pathway@setName,genes_in_data,sep = "_genes:") #if genes in data are less than threshold, mark them
  pathway
}

calculatePathwayScores <- function(pathwayToScore, countsMatrix)
{
  pathwayName <- pathwayToScore@setName
  print(pathwayName)
  pathwayGenes <- pathwayToScore@geneIds
  pathwayScoresObject <- getPathwayScores(countsMatrix, pathwayGenes) 
  suppressWarnings(
    if(is.na(pathwayScoresObject)){return (NA)}
  )
  return(pathwayScoresObject$pathwayScores)
}

sipsic_pipeline <- function(geneset, dataset,thresholds) {

  pathwayScoreLists <- lapply(X = geneset@.Data, calculatePathwayScores, dataset %>% as.matrix() %>% Matrix(sparse = T))
  pathwayScoreLists <- pathwayScoreLists[!is.na(pathwayScoreLists)] #remove NA pathways
  pathwayScoresMatrix <- as.data.frame(do.call("rbind", pathwayScoreLists))
  for(currPathwayIndex in 1:length(pathwayScoreLists)){
    rownames(pathwayScoresMatrix)[currPathwayIndex] <- geneset@.Data[[currPathwayIndex]]@setName
  }
  
  seurat_assay <- CreateAssayObject(counts = pathwayScoresMatrix)
  return(seurat_assay)
}

2 Data

GBMSeurat_cancer = readRDS("./Data/GSM3828673_10X_GBM_seurat_cancer.RDS")
genesets_h <- getGmt("./Data/msigdb_pathways/h.all.v7.0.symbols.pluscc.gmt")
genesets_cp <- getGmt("./Data/msigdb_pathways/c2.cp.v2023.2.Hs.symbols.gmt")
genesets_kegg <- getGmt("./Data/msigdb_pathways/c2.cp.kegg_medicus.v2023.2.Hs.symbols.gmt")
genesets_pid<- getGmt("./Data/msigdb_pathways/c2.cp.pid.v2023.2.Hs.symbols.gmt")

genesets_test = GeneSetCollection(genesets_h[10:13])
genesets_h_cp = GeneSetCollection(c(genesets_h,genesets_cp))
genesets_h_kegg = GeneSetCollection(c(genesets_h,genesets_kegg))
genesets_h_pid = GeneSetCollection(c(genesets_h,genesets_pid))
GBMSeurat_cancer@assays$RNA <- data.frame()
saveRDS(GBMSeurat_cancer,file = "./Data/GSM3828673_10X_GBM_seurat_cancer_msigdb_pathwyas.RDS")

3 original Louvain algorithm

print_tab(all_p_patient,title = "patients barplot")

patients barplot

print_tab(all_p_cellType,title = "cancer type barplot")

cancer type barplot

print_tab(all_p_umap,title = "UMAPs")

UMAPs

NA

4 Louvain algorithm with multilevel refinement

all_p

5 SLM algorithm

all_p

6 Leiden algorithm

all_p

LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19kZXB0aDogMQotLS0KCgoKIyBGdW5jdGlvbnMKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoR1NFQUJhc2UpCmZpbHRlcl9wYXRod2F5cyA8LSBmdW5jdGlvbihwYXRod2F5LGRhdGFzZXQpIHsKICBnZW5lc19pbl9kYXRhID0gcGF0aHdheUBnZW5lSWRzICVpbiUgcm93bmFtZXMoZGF0YXNldCkgJT4lIHN1bSgpCiAgcGF0aHdheUBzZXROYW1lID0gcGFzdGUoIHBhdGh3YXlAc2V0TmFtZSxnZW5lc19pbl9kYXRhLHNlcCA9ICJfZ2VuZXM6IikgI2lmIGdlbmVzIGluIGRhdGEgYXJlIGxlc3MgdGhhbiB0aHJlc2hvbGQsIG1hcmsgdGhlbQogIHBhdGh3YXkKfQoKY2FsY3VsYXRlUGF0aHdheVNjb3JlcyA8LSBmdW5jdGlvbihwYXRod2F5VG9TY29yZSwgY291bnRzTWF0cml4KQp7CiAgcGF0aHdheU5hbWUgPC0gcGF0aHdheVRvU2NvcmVAc2V0TmFtZQogIHByaW50KHBhdGh3YXlOYW1lKQogIHBhdGh3YXlHZW5lcyA8LSBwYXRod2F5VG9TY29yZUBnZW5lSWRzCiAgcGF0aHdheVNjb3Jlc09iamVjdCA8LSBnZXRQYXRod2F5U2NvcmVzKGNvdW50c01hdHJpeCwgcGF0aHdheUdlbmVzKSAKICBzdXBwcmVzc1dhcm5pbmdzKAogICAgaWYoaXMubmEocGF0aHdheVNjb3Jlc09iamVjdCkpe3JldHVybiAoTkEpfQogICkKICByZXR1cm4ocGF0aHdheVNjb3Jlc09iamVjdCRwYXRod2F5U2NvcmVzKQp9CgpzaXBzaWNfcGlwZWxpbmUgPC0gZnVuY3Rpb24oZ2VuZXNldCwgZGF0YXNldCx0aHJlc2hvbGRzKSB7CgogIHBhdGh3YXlTY29yZUxpc3RzIDwtIGxhcHBseShYID0gZ2VuZXNldEAuRGF0YSwgY2FsY3VsYXRlUGF0aHdheVNjb3JlcywgZGF0YXNldCAlPiUgYXMubWF0cml4KCkgJT4lIE1hdHJpeChzcGFyc2UgPSBUKSkKICBwYXRod2F5U2NvcmVMaXN0cyA8LSBwYXRod2F5U2NvcmVMaXN0c1shaXMubmEocGF0aHdheVNjb3JlTGlzdHMpXSAjcmVtb3ZlIE5BIHBhdGh3YXlzCiAgcGF0aHdheVNjb3Jlc01hdHJpeCA8LSBhcy5kYXRhLmZyYW1lKGRvLmNhbGwoInJiaW5kIiwgcGF0aHdheVNjb3JlTGlzdHMpKQogIGZvcihjdXJyUGF0aHdheUluZGV4IGluIDE6bGVuZ3RoKHBhdGh3YXlTY29yZUxpc3RzKSl7CiAgICByb3duYW1lcyhwYXRod2F5U2NvcmVzTWF0cml4KVtjdXJyUGF0aHdheUluZGV4XSA8LSBnZW5lc2V0QC5EYXRhW1tjdXJyUGF0aHdheUluZGV4XV1Ac2V0TmFtZQogIH0KICAKICBzZXVyYXRfYXNzYXkgPC0gQ3JlYXRlQXNzYXlPYmplY3QoY291bnRzID0gcGF0aHdheVNjb3Jlc01hdHJpeCkKICByZXR1cm4oc2V1cmF0X2Fzc2F5KQp9CgpgYGAKCiMgRGF0YQpgYGB7cn0KR0JNU2V1cmF0X2NhbmNlciA9IHJlYWRSRFMoIi4vRGF0YS9HU00zODI4NjczXzEwWF9HQk1fc2V1cmF0X2NhbmNlci5SRFMiKQpnZW5lc2V0c19oIDwtIGdldEdtdCgiLi9EYXRhL21zaWdkYl9wYXRod2F5cy9oLmFsbC52Ny4wLnN5bWJvbHMucGx1c2NjLmdtdCIpCmdlbmVzZXRzX2NwIDwtIGdldEdtdCgiLi9EYXRhL21zaWdkYl9wYXRod2F5cy9jMi5jcC52MjAyMy4yLkhzLnN5bWJvbHMuZ210IikKZ2VuZXNldHNfa2VnZyA8LSBnZXRHbXQoIi4vRGF0YS9tc2lnZGJfcGF0aHdheXMvYzIuY3Aua2VnZ19tZWRpY3VzLnYyMDIzLjIuSHMuc3ltYm9scy5nbXQiKQpnZW5lc2V0c19waWQ8LSBnZXRHbXQoIi4vRGF0YS9tc2lnZGJfcGF0aHdheXMvYzIuY3AucGlkLnYyMDIzLjIuSHMuc3ltYm9scy5nbXQiKQoKZ2VuZXNldHNfdGVzdCA9IEdlbmVTZXRDb2xsZWN0aW9uKGdlbmVzZXRzX2hbMTA6MTNdKQpnZW5lc2V0c19oX2NwID0gR2VuZVNldENvbGxlY3Rpb24oYyhnZW5lc2V0c19oLGdlbmVzZXRzX2NwKSkKZ2VuZXNldHNfaF9rZWdnID0gR2VuZVNldENvbGxlY3Rpb24oYyhnZW5lc2V0c19oLGdlbmVzZXRzX2tlZ2cpKQpnZW5lc2V0c19oX3BpZCA9IEdlbmVTZXRDb2xsZWN0aW9uKGMoZ2VuZXNldHNfaCxnZW5lc2V0c19waWQpKQpgYGAKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CmdlbmVzZXRzX29wdGlvbnMgPSBsaXN0KGdlbmVzZXRzX2NwPWdlbmVzZXRzX2NwLGdlbmVzZXRzX2ggPSBnZW5lc2V0c19oLCBnZW5lc2V0c19rZWdnID0gZ2VuZXNldHNfa2VnZywgZ2VuZXNldHNfcGlkID0gZ2VuZXNldHNfcGlkKQpmaWx0ZXJfZ2VuZXNfb3B0aW9ucyA9IGMoNSwxMCkKCiNzaXBzaWMgZm9yIGVhY2ggZ2VuZXNldApmb3IgKGkgaW4gc2VxX2Fsb25nKGdlbmVzZXRzX29wdGlvbnMpKSB7IAogIGdlbmVzZXQgPSBnZW5lc2V0c19vcHRpb25zW1tpXV0KICBnZW5lc2V0X25hbWUgPSBuYW1lcyhnZW5lc2V0c19vcHRpb25zKVtpXQogIHByaW50KGdlbmVzZXRfbmFtZSkKICBuZXdfYXNzYXkgPSBzaXBzaWNfcGlwZWxpbmUoZ2VuZXNldCA9IGdlbmVzZXQsZGF0YXNldCA9IEdCTVNldXJhdF9jYW5jZXJAYXNzYXlzJFJOQUBjb3VudHMsdGhyZXNob2xkID0gZ2VuZXNfdGhyZXNob2xkKQogIEdCTVNldXJhdF9jYW5jZXJbW2dlbmVzZXRfbmFtZV1dID0gbmV3X2Fzc2F5Cn0KCiMgQWRkIGhhbGxtYXJrIHRvIHRoZSBvdGhlciBnZW5lc2V0cwpuZXdfYXNzYXkgPSByYmluZChHQk1TZXVyYXRfY2FuY2VyQGFzc2F5cyRnZW5lc2V0c19jcEBjb3VudHMsR0JNU2V1cmF0X2NhbmNlckBhc3NheXMkZ2VuZXNldHNfaEBjb3VudHMpICU+JSBDcmVhdGVBc3NheU9iamVjdApHQk1TZXVyYXRfY2FuY2VyW1siZ2VuZXNldHNfaF9jcCJdXSA9IG5ld19hc3NheQoKbmV3X2Fzc2F5ID0gcmJpbmQoR0JNU2V1cmF0X2NhbmNlckBhc3NheXMkZ2VuZXNldHNfa2VnZ0Bjb3VudHMsR0JNU2V1cmF0X2NhbmNlckBhc3NheXMkZ2VuZXNldHNfaEBjb3VudHMpICU+JSBDcmVhdGVBc3NheU9iamVjdApHQk1TZXVyYXRfY2FuY2VyW1siZ2VuZXNldHNfaF9rZWdnIl1dID0gbmV3X2Fzc2F5CgpuZXdfYXNzYXkgPSByYmluZChHQk1TZXVyYXRfY2FuY2VyQGFzc2F5cyRnZW5lc2V0c19waWRAY291bnRzLEdCTVNldXJhdF9jYW5jZXJAYXNzYXlzJGdlbmVzZXRzX2hAY291bnRzKSAlPiUgQ3JlYXRlQXNzYXlPYmplY3QKR0JNU2V1cmF0X2NhbmNlcltbImdlbmVzZXRzX2hfcGlkIl1dID0gbmV3X2Fzc2F5CgoKZ2VuZXNldHNfb3B0aW9uc193aXRoX2ggPSBsaXN0KGdlbmVzZXRzX2hfY3A9Z2VuZXNldHNfaF9jcCxnZW5lc2V0c19oID0gZ2VuZXNldHNfaCwgZ2VuZXNldHNfaF9rZWdnID0gZ2VuZXNldHNfaF9rZWdnLCBnZW5lc2V0c19oX3BpZCA9IGdlbmVzZXRzX2hfcGlkKQoKIyBmb3IgZWFjaCBnZW5lc2V0LCBmaWx0ZXIgcGF0aHdheSB0aGF0IGFyZSBiZWxvdyB0aHJlc2hvbGQKZm9yIChpIGluIHNlcV9hbG9uZyhnZW5lc2V0c19vcHRpb25zX3dpdGhfaCkpIHsKICBnZW5lc2V0ID0gZ2VuZXNldHNfb3B0aW9uc193aXRoX2hbW2ldXQogIGdlbmVzZXRfbmFtZSA9IG5hbWVzKGdlbmVzZXRzX29wdGlvbnNfd2l0aF9oKVtpXQogIGdlbmVzZXQgPSBnZW5lc2V0W3Jvd25hbWVzKEdCTVNldXJhdF9jYW5jZXJbW2dlbmVzZXRfbmFtZV1dKSAlPiUgZ3N1YihwYXR0ZXJuID0gIi0iLHJlcGxhY2VtZW50ID0gIl8iKV0gI3VwZGF0ZSBnZW5lc2V0IHBhdGh3YXkgdG8gYmUgbGlrZSBhZnRlciBzaXBzaWMgZmlsdGVyaW5nCiAgZm9yIChnZW5lc190aHJlc2hvbGQgaW4gZmlsdGVyX2dlbmVzX29wdGlvbnMpIHsKICAgIGdlbmVzZXRfd2l0aF9udW1HZW5lcyA8LSBsYXBwbHkoWCA9IGdlbmVzZXRALkRhdGEsIGZpbHRlcl9wYXRod2F5cywgZGF0YXNldCkgJT4lIEdlbmVTZXRDb2xsZWN0aW9uKCkgIyBhZGQgbnVtIG9mIGV4aXN0aW5nIGdlbmVzCiAgICBudW1fb2ZfZ2VuZXMgPSBuYW1lcyhnZW5lc2V0X3dpdGhfbnVtR2VuZXMpICU+JSBnc3ViKHBhdHRlcm4gPSAiLipfZ2VuZXM6IixyZXBsYWNlbWVudCA9ICIiKSAlPiUgYXMubnVtZXJpYygpICMgZ2V0IHZlY3RvciBvZiBudW0gb2YgZXhpc3QgZ2VuZXMKICAgIHNldXJhdF9hc3NheSA9IEdCTVNldXJhdF9jYW5jZXJbW2dlbmVzZXRfbmFtZV1dQGNvdW50c1tudW1fb2ZfZ2VuZXM+Z2VuZXNfdGhyZXNob2xkLCBdICU+JSBDcmVhdGVBc3NheU9iamVjdCgpICNmaWx0ZXIgcm93cyBiYXNlZCBvbiBudW1fb2ZfZ2VuZXMKICAgIEdCTVNldXJhdF9jYW5jZXJbW3Bhc3RlKGdlbmVzZXRfbmFtZSxnZW5lc190aHJlc2hvbGQsc2VwID0gIl8iKV1dID0gc2V1cmF0X2Fzc2F5ICNhZGQgbmV3IGFzc2F5CiAgfQp9ICAKCmBgYAoKYGBge3J9CkdCTVNldXJhdF9jYW5jZXJAYXNzYXlzJFJOQSA8LSBkYXRhLmZyYW1lKCkKc2F2ZVJEUyhHQk1TZXVyYXRfY2FuY2VyLGZpbGUgPSAiLi9EYXRhL0dTTTM4Mjg2NzNfMTBYX0dCTV9zZXVyYXRfY2FuY2VyX21zaWdkYl9wYXRod3lhcy5SRFMiKQpgYGAKCiMgb3JpZ2luYWwgTG91dmFpbiBhbGdvcml0aG0gey50YWJzZXR9CmBgYHtyIGluY2x1ZGU9RkFMU0V9CmFsbF9ydW5zID0gbmFtZXMoZ2VuZXNldHNfb3B0aW9uc193aXRoX2gpICU+JSBjKGFzLnZlY3RvcihvdXRlcihuYW1lcyhnZW5lc2V0c19vcHRpb25zX3dpdGhfaCksIGZpbHRlcl9nZW5lc19vcHRpb25zLCBwYXN0ZSwgc2VwPSJfIikpICApICMgdmVjdG9yIG9mIGFsbCBjb21iaW5hdGlvbnMKcGF0aWVudF9wbHRfbGlzdCA8LSBsaXN0KCkgCmNlbGxUeXBlX3BsdF9saXN0IDwtIGxpc3QoKSAKdW1hcF9wbHRfbGlzdCA8LSBsaXN0KCkgCgpydW5zX3JlcyA9IGMoMC42MSwwLjksMC42MSwwLjcyLDAuNjEsMC45LDAuNjU5OCwwLjcsMC42MjIyLDAuOSwwLjcsMC43MikKbmFtZXMocnVuc19yZXMpID0gYWxsX3J1bnMKZm9yIChydW4gaW4gYWxsX3J1bnMpIHsKICBEZWZhdWx0QXNzYXkoR0JNU2V1cmF0X2NhbmNlcikgPSBydW4KICBHQk1TZXVyYXRfY2FuY2VyICAlPD4lICAgIFJ1blBDQShmZWF0dXJlcyA9IHJvd25hbWVzKEdCTVNldXJhdF9jYW5jZXIpKSAlPiUgRmluZE5laWdoYm9ycyhkaW1zID0gMToxNSkgJT4lIEZpbmRDbHVzdGVycyhyZXNvbHV0aW9uID0gcnVuc19yZXNbW3J1bl1dKQoKICBjbHVzdGVyc19hbmRfc2NvcmVzID0gRmV0Y2hEYXRhKG9iamVjdCA9IEdCTVNldXJhdF9jYW5jZXIsdmFycz0gYygib3JpZy5pZGVudCIsInNldXJhdF9jbHVzdGVycyIpKSAlPiUgIGdyb3VwX2J5KHNldXJhdF9jbHVzdGVycyxvcmlnLmlkZW50KSAlPiUgIAogICAgc3VtbWFyaXNlKG5fY2VsbHMgPSBuKCksIC5ncm91cHMgPSAiZHJvcF9sYXN0IiklPiUgbXV0YXRlKHBlciA9ICAxMDAgKm5fY2VsbHMvc3VtKG5fY2VsbHMpKQogIAogIGNvbG9ycyA9IFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCg5LCAiUGFpcmVkIikKICBwID0gIGdncGxvdChkYXRhPWNsdXN0ZXJzX2FuZF9zY29yZXMsIGFlcyh4PXNldXJhdF9jbHVzdGVycywgeT1wZXIsIGZpbGw9ZmFjdG9yKG9yaWcuaWRlbnQpKSkgKwogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSt0aGVtZV9taW5pbWFsKCkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnMsbmFtZSAgPSAiUGF0aWVudCIpKyAKICAgIGxhYnModGl0bGUgPSBydW4pKwogICAgeWxhYigiJSBmcm9tIGNsdXN0ZXIiKQogIAogIHBhdGllbnRfcGx0X2xpc3RbW3J1bl1dIDwtIHAgICMgYWRkIGVhY2ggcGxvdCBpbnRvIHBsb3QgbGlzdAogIAogIAogICMgY2FuY2VyIHR5cGVzIHN0YWNrZWQgYmFycGxvdAogIAogICBjbHVzdGVyc19hbmRfc2NvcmVzID0gRmV0Y2hEYXRhKG9iamVjdCA9IEdCTVNldXJhdF9jYW5jZXIsdmFycz0gYygiY2FuY2VyX3R5cGUiLCJzZXVyYXRfY2x1c3RlcnMiKSkgJT4lICBncm91cF9ieShzZXVyYXRfY2x1c3RlcnMsY2FuY2VyX3R5cGUpICU+JQogICAgc3VtbWFyaXNlKG5fY2VsbHMgPSBuKCksIC5ncm91cHMgPSAiZHJvcF9sYXN0IiklPiUgbXV0YXRlKHBlciA9ICAxMDAgKm5fY2VsbHMvc3VtKG5fY2VsbHMpKQogIAogIGludGVncmF0aW9uX3Njb3JlID0gRmV0Y2hEYXRhKG9iamVjdCA9IEdCTVNldXJhdF9jYW5jZXIsdmFycz0gYygiY2FuY2VyX3R5cGUiLCJzZXVyYXRfY2x1c3RlcnMiKSklPiUKICAgIG11dGF0ZShjYW5jZXJfdHlwZSA9IGNhbmNlcl90eXBlICU+JSBnc3ViKHBhdHRlcm4gPSJNZXNMaWtlMXxNZXNMaWtlMiIscmVwbGFjZW1lbnQgPSAiTWVzTGlrZSIpKSU+JSAgI3VuaW9uIHN1YnR5cGVzCiAgICBtdXRhdGUoY2FuY2VyX3R5cGUgPSBjYW5jZXJfdHlwZSAlPiUgZ3N1YihwYXR0ZXJuID0gIk5QQ0xpa2UxfE5QQ0xpa2UyIixyZXBsYWNlbWVudCA9ICJOUENMaWtlIikpICU+JSAjdW5pb24gc3VidHlwZXMKICAgIGdyb3VwX2J5KHNldXJhdF9jbHVzdGVycyxjYW5jZXJfdHlwZSkgJT4lIAogICAgc3VtbWFyaXNlKG5fY2VsbHMgPSBuKCksIC5ncm91cHMgPSAiZHJvcF9sYXN0IiklPiUgI2NvdW50IGJ5IGNsdXN0ZXIKICAgIG11dGF0ZShwZXIgPSAgMTAwICpuX2NlbGxzL3N1bShuX2NlbGxzKSkgJT4lICAgI2NhbGMgcGVyY2VudGFnZXMKICAgIGdyb3VwX2J5KHNldXJhdF9jbHVzdGVycykgJT4lICNmb3IgZWFjaCBjbHVzdGVyCiAgICBmaWx0ZXIobl9jZWxscyA9PSBtYXgobl9jZWxscykpICU+JSAjZ2V0IG1heCBjZWxsIHR5cGUKICAgIHB1bGwocGVyKSAlPiUgbWVhbigpICU+JSByb3VuZChkaWdpdHMgPSAyKQogIAogIAogIGNlbGxfdHlwZXNfbGV2ZWxzIDwtYyggIk1lc0xpa2UxIiwgIk1lc0xpa2UyIiwgIk5QQ0xpa2UxIiwgIk5QQ0xpa2UyIiwgIk9QQ0xpa2UiLCJBQ0xpa2UiKQogIGNvbG9ycyA9IFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCg2LCAiUGFpcmVkIik7IGNvbG9yc1s1XSA9ICJvcmFuZ2UiCiAgcDIgPSBnZ3Bsb3QoZGF0YT1jbHVzdGVyc19hbmRfc2NvcmVzLCBhZXMoeD1zZXVyYXRfY2x1c3RlcnMsIHk9cGVyLCBmaWxsPWZhY3RvcihjYW5jZXJfdHlwZSwgbGV2ZWxzID0gY2VsbF90eXBlc19sZXZlbHMpKSkgKwogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSt0aGVtZV9taW5pbWFsKCkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnMsbmFtZSAgPSAiQ2FuY2VyIHR5cGUiKSsgCiAgICBsYWJzKHRpdGxlID0gcnVuLHN1YnRpdGxlID0gImludGVncmF0aW9uIHNjb3JlPSIgJXMrJSBpbnRlZ3JhdGlvbl9zY29yZSkrCiAgICB5bGFiKCIlIGZyb20gY2x1c3RlciIpCiAgY2VsbFR5cGVfcGx0X2xpc3RbW3J1bl1dIDwtIHAyICAjIGFkZCBlYWNoIHBsb3QgaW50byBwbG90IGxpc3QKICBHQk1TZXVyYXRfY2FuY2VyIDwtIFJ1blVNQVAoR0JNU2V1cmF0X2NhbmNlciwgZGltcyA9IDE6MTUpCiAgcDMgPSBEaW1QbG90KEdCTVNldXJhdF9jYW5jZXIsIHJlZHVjdGlvbiA9ICJ1bWFwIixncm91cC5ieSA9IGMoIm9yaWcuaWRlbnQiKSkKICAgIHVtYXBfcGx0X2xpc3RbW3J1bl1dIDwtIHAzICAjIGFkZCBlYWNoIHBsb3QgaW50byBwbG90IGxpc3QKCn0KCmFsbF9wX3BhdGllbnQgPSBnZ2FycmFuZ2UocGxvdGxpc3QgPSBwYXRpZW50X3BsdF9saXN0LGNvbW1vbi5sZWdlbmQgPSBUKQphbGxfcF9jZWxsVHlwZSA9IGdnYXJyYW5nZShwbG90bGlzdCA9IGNlbGxUeXBlX3BsdF9saXN0LGNvbW1vbi5sZWdlbmQgPSBUKQphbGxfcF91bWFwID0gZ2dhcnJhbmdlKHBsb3RsaXN0ID0gdW1hcF9wbHRfbGlzdCxjb21tb24ubGVnZW5kID0gVCkKCgpgYGAKCgpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTQscmVzdWx0cz0nYXNpcyd9CnByaW50X3RhYihhbGxfcF9wYXRpZW50LHRpdGxlID0gInBhdGllbnRzIGJhcnBsb3QiKQpwcmludF90YWIoYWxsX3BfY2VsbFR5cGUsdGl0bGUgPSAiY2FuY2VyIHR5cGUgYmFycGxvdCIpCgpwcmludF90YWIoYWxsX3BfdW1hcCx0aXRsZSA9ICJVTUFQcyIpCgpgYGAKCiMgIExvdXZhaW4gYWxnb3JpdGhtIHdpdGggbXVsdGlsZXZlbCByZWZpbmVtZW50CmBgYHtyIGluY2x1ZGU9RkFMU0V9CmFsbF9ydW5zID0gbmFtZXMoZ2VuZXNldHNfb3B0aW9uc193aXRoX2gpICU+JSBjKGFzLnZlY3RvcihvdXRlcihuYW1lcyhnZW5lc2V0c19vcHRpb25zX3dpdGhfaCksIGZpbHRlcl9nZW5lc19vcHRpb25zLCBwYXN0ZSwgc2VwPSJfIikpICApCm15cGxvdHMgPC0gbGlzdCgpIApmb3IgKHJ1biBpbiBhbGxfcnVucykgewogIERlZmF1bHRBc3NheShHQk1TZXVyYXRfY2FuY2VyKSA9IHJ1bgogIEdCTVNldXJhdF9jYW5jZXIgICU8PiUgIEZpbmRDbHVzdGVycyhyZXNvbHV0aW9uID0gcnVuc19yZXNbW3J1bl1dLGFsZ29yaXRobSA9MikKICAKICBjbHVzdGVyc19hbmRfc2NvcmVzID0gRmV0Y2hEYXRhKG9iamVjdCA9IEdCTVNldXJhdF9jYW5jZXIsdmFycz0gYygib3JpZy5pZGVudCIsInNldXJhdF9jbHVzdGVycyIpKSAlPiUgIGdyb3VwX2J5KHNldXJhdF9jbHVzdGVycyxvcmlnLmlkZW50KSAlPiUgIAogICAgc3VtbWFyaXNlKG5fY2VsbHMgPSBuKCksIC5ncm91cHMgPSAiZHJvcF9sYXN0IiklPiUgbXV0YXRlKHBlciA9ICAxMDAgKm5fY2VsbHMvc3VtKG5fY2VsbHMpKQogIAogIGNvbG9ycyA9IFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCg5LCAiUGFpcmVkIikKICBwID0gZ2dwbG90KGRhdGE9Y2x1c3RlcnNfYW5kX3Njb3JlcywgYWVzKHg9c2V1cmF0X2NsdXN0ZXJzLCB5PXBlciwgZmlsbD1mYWN0b3Iob3JpZy5pZGVudCkpKSArCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpK3RoZW1lX21pbmltYWwoKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9ycyxuYW1lICA9ICJQYXRpZW50IikrIAogICAgbGFicyh0aXRsZSA9IHJ1bikrCiAgICB5bGFiKCIlIGZyb20gY2x1c3RlciIpCiAgbXlwbG90c1tbcnVuXV0gPC0gcCAgIyBhZGQgZWFjaCBwbG90IGludG8gcGxvdCBsaXN0Cgp9CgphbGxfcCA9IGdnYXJyYW5nZShwbG90bGlzdCA9IG15cGxvdHMsY29tbW9uLmxlZ2VuZCA9IFQpCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNH0KYWxsX3AKYGBgCgojIFNMTSBhbGdvcml0aG0KYGBge3IgaW5jbHVkZT1GQUxTRX0KYWxsX3J1bnMgPSBuYW1lcyhnZW5lc2V0c19vcHRpb25zX3dpdGhfaCkgJT4lIGMoYXMudmVjdG9yKG91dGVyKG5hbWVzKGdlbmVzZXRzX29wdGlvbnNfd2l0aF9oKSwgZmlsdGVyX2dlbmVzX29wdGlvbnMsIHBhc3RlLCBzZXA9Il8iKSkgICkKbXlwbG90cyA8LSBsaXN0KCkgCmZvciAocnVuIGluIGFsbF9ydW5zKSB7CiAgRGVmYXVsdEFzc2F5KEdCTVNldXJhdF9jYW5jZXIpID0gcnVuCiAgR0JNU2V1cmF0X2NhbmNlciAgJTw+JSAgRmluZENsdXN0ZXJzKHJlc29sdXRpb24gPSBydW5zX3Jlc1tbcnVuXV0sYWxnb3JpdGhtID0gMykKICAKICBjbHVzdGVyc19hbmRfc2NvcmVzID0gRmV0Y2hEYXRhKG9iamVjdCA9IEdCTVNldXJhdF9jYW5jZXIsdmFycz0gYygib3JpZy5pZGVudCIsInNldXJhdF9jbHVzdGVycyIpKSAlPiUgIGdyb3VwX2J5KHNldXJhdF9jbHVzdGVycyxvcmlnLmlkZW50KSAlPiUgIAogICAgc3VtbWFyaXNlKG5fY2VsbHMgPSBuKCksIC5ncm91cHMgPSAiZHJvcF9sYXN0IiklPiUgbXV0YXRlKHBlciA9ICAxMDAgKm5fY2VsbHMvc3VtKG5fY2VsbHMpKQogIAogIGNvbG9ycyA9IFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCg5LCAiUGFpcmVkIikKICBwID0gZ2dwbG90KGRhdGE9Y2x1c3RlcnNfYW5kX3Njb3JlcywgYWVzKHg9c2V1cmF0X2NsdXN0ZXJzLCB5PXBlciwgZmlsbD1mYWN0b3Iob3JpZy5pZGVudCkpKSArCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpK3RoZW1lX21pbmltYWwoKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9ycyxuYW1lICA9ICJQYXRpZW50IikrIAogICAgbGFicyh0aXRsZSA9IHJ1bikrCiAgICB5bGFiKCIlIGZyb20gY2x1c3RlciIpCiAgbXlwbG90c1tbcnVuXV0gPC0gcCAgIyBhZGQgZWFjaCBwbG90IGludG8gcGxvdCBsaXN0Cgp9CgphbGxfcCA9IGdnYXJyYW5nZShwbG90bGlzdCA9IG15cGxvdHMsY29tbW9uLmxlZ2VuZCA9IFQpCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNH0KYWxsX3AKYGBgCgojIExlaWRlbiBhbGdvcml0aG0KCmBgYHtyIGluY2x1ZGU9RkFMU0V9CnJ1bnNfcmVzID0gcnVuc19yZXMtMC4wNwphbGxfcnVucyA9IG5hbWVzKGdlbmVzZXRzX29wdGlvbnNfd2l0aF9oKSAlPiUgYyhhcy52ZWN0b3Iob3V0ZXIobmFtZXMoZ2VuZXNldHNfb3B0aW9uc193aXRoX2gpLCBmaWx0ZXJfZ2VuZXNfb3B0aW9ucywgcGFzdGUsIHNlcD0iXyIpKSAgKQpteXBsb3RzIDwtIGxpc3QoKSAKZm9yIChydW4gaW4gYWxsX3J1bnMpIHsKICBEZWZhdWx0QXNzYXkoR0JNU2V1cmF0X2NhbmNlcikgPSBydW4KICBHQk1TZXVyYXRfY2FuY2VyICU8PiUgRmluZENsdXN0ZXJzKHJlc29sdXRpb24gPSBydW5zX3Jlc1tbcnVuXV0sYWxnb3JpdGhtID0gNCkKICAKICBjbHVzdGVyc19hbmRfc2NvcmVzID0gRmV0Y2hEYXRhKG9iamVjdCA9IEdCTVNldXJhdF9jYW5jZXIsdmFycz0gYygib3JpZy5pZGVudCIsInNldXJhdF9jbHVzdGVycyIpKSAlPiUgIGdyb3VwX2J5KHNldXJhdF9jbHVzdGVycyxvcmlnLmlkZW50KSAlPiUgIAogICAgc3VtbWFyaXNlKG5fY2VsbHMgPSBuKCksIC5ncm91cHMgPSAiZHJvcF9sYXN0IiklPiUgbXV0YXRlKHBlciA9ICAxMDAgKm5fY2VsbHMvc3VtKG5fY2VsbHMpKQogIAogIGNvbG9ycyA9IFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCg5LCAiUGFpcmVkIikKICBwID0gZ2dwbG90KGRhdGE9Y2x1c3RlcnNfYW5kX3Njb3JlcywgYWVzKHg9c2V1cmF0X2NsdXN0ZXJzLCB5PXBlciwgZmlsbD1mYWN0b3Iob3JpZy5pZGVudCkpKSArCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpK3RoZW1lX21pbmltYWwoKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9ycyxuYW1lICA9ICJQYXRpZW50IikrIAogICAgbGFicyh0aXRsZSA9IHJ1bikrCiAgICB5bGFiKCIlIGZyb20gY2x1c3RlciIpCiAgbXlwbG90c1tbcnVuXV0gPC0gcCAgIyBhZGQgZWFjaCBwbG90IGludG8gcGxvdCBsaXN0Cgp9CgphbGxfcCA9IGdnYXJyYW5nZShwbG90bGlzdCA9IG15cGxvdHMsY29tbW9uLmxlZ2VuZCA9IFQpCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNH0KYWxsX3AKYGBgCgo8c2NyaXB0IHNyYz0iaHR0cHM6Ly9oeXBvdGhlcy5pcy9lbWJlZC5qcyIgYXN5bmM+PC9zY3JpcHQ+Cgo=