1 Functions

source_from_github(repositoy = "HMSC_functions",version = "0.1.12",script_name = "functions.R")
ℹ SHA-1 hash of file is 2934dee5f6b9fee69635192f19b1bcc205e05b62

2 Data

acc1_cancer_cells = readRDS("./Data/acc1_cancer_cells_15KnCount_V3.RDS")
acc1_cancer_cells$plate = acc1_cancer_cells$orig.ident

3 Original UMAP

DimPlot(object = acc1_cancer_cells,pt.size = 2,group.by = "plate")

4 Seurat intergration

acc1_cancer_cells.list <- SplitObject(acc1_cancer_cells, split.by = "plate")

# normalize and identify variable features for each dataset independently
acc1_cancer_cells.list <- lapply(X = acc1_cancer_cells.list, FUN = function(x) {
    # x <- NormalizeData(x)
    x <- FindVariableFeatures(x, selection.method = "vst", nfeatures = 2000)
})

# select features that are repeatedly variable across datasets for integration
features <- SelectIntegrationFeatures(object.list = acc1_cancer_cells.list,nfeatures = 2000)
acc.anchors <- FindIntegrationAnchors(object.list = acc1_cancer_cells.list, anchor.features = features,k.filter = 50)
acc.combined <- IntegrateData(anchorset = acc.anchors,k.weight = 50)
Merging dataset 1 into 2
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
DefaultAssay(acc.combined) <- "integrated"
acc.combined <- ScaleData(acc.combined, verbose = FALSE)
acc.combined <- RunPCA(acc.combined, npcs = 30, verbose = FALSE)
ElbowPlot(acc.combined)

acc.combined <- RunUMAP(acc.combined, reduction = "pca", dims = 1:10)
acc.combined <- FindNeighbors(acc.combined, reduction = "pca", dims = 1:10)
acc.combined <- FindClusters(acc.combined, resolution = 0.5)

4.1 UMAPS

DimPlot(acc.combined, reduction = "umap", group.by = "plate")

DimPlot(acc.combined, reduction = "umap")

4.2 clusters DEG

acc_deg <- FindMarkers(acc.combined, ident.1 = "0",ident.2 = "1",features = VariableFeatures(acc.combined),densify = T)
enrichment_analysis(acc_deg,background = VariableFeatures(acc.combined),fdr_Cutoff = 0.01,ident.1 = "0",ident.2 = "1",show_by = 1)

4.3 myo-lum score

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" )
calculate_score = function(dataset,myo_genes,lum_genes,lum_threshold =1 , myo_threshold = -1) {
  myoscore=FetchData(object =dataset,vars =  myo_genes,slot = "data") %>% rowMeans()
  lescore=FetchData(object =dataset,vars =  lum_genes,slot = "data") %>% rowMeans()
  correlation = cor(lescore,myoscore) %>% round(digits = 2)
  message("correlation of lum score and myo score:" %>% paste(correlation))
  




  dataset=AddMetaData(dataset,lescore-myoscore,"luminal_over_myo")
  print(
    FeaturePlot(object = dataset,features = "luminal_over_myo")
  )
  data = FetchData(object = dataset,vars = "luminal_over_myo")
  print(
    data %>% 
    ggplot(aes( x=luminal_over_myo)) + 
    geom_density() 
    )
  
lum_cells_num = subset(x = dataset,luminal_over_myo >(lum_threshold)) %>% ncol() /ncol(dataset)
myo_cells_num = subset(x = dataset,luminal_over_myo <(myo_threshold)) %>% ncol()/ncol(dataset)
df = data.frame(cell_type = c("myo_cells","lum_cells"),percentage = c(myo_cells_num,lum_cells_num))
ggplot(data=df, aes(x=cell_type, y=percentage)) +
  geom_bar(stat="identity") + ggtitle("ACC cell types")
}
calculate_score(dataset = acc.combined,myo_genes = original_myo_genes,lum_genes = original_lum_genes)
Warning: Could not find TP63 in the default search locations, found in RNA assay instead
Warning: Could not find TP73 in the default search locations, found in RNA assay instead
Warning: Could not find CDH3 in the default search locations, found in RNA assay instead
Warning: Could not find MYLK in the default search locations, found in RNA assay instead
Warning: Could not find KIT in the default search locations, found in RNA assay instead
Warning: Could not find EHF in the default search locations, found in RNA assay instead
Warning: Could not find ELF5 in the default search locations, found in RNA assay instead
Warning: Could not find CLDN3 in the default search locations, found in RNA assay instead
Warning: Could not find CD24 in the default search locations, found in RNA assay instead
correlation of lum score and myo score: -0.04

acc1_cancer_cells.list <- SplitObject(acc1_cancer_cells, split.by = "plate")

# normalize and identify variable features for each dataset independently
acc1_cancer_cells.list <- lapply(X = acc1_cancer_cells.list, FUN = function(x) {
    # x <- NormalizeData(x)
    x <- FindVariableFeatures(x, selection.method = "vst", nfeatures = nrow(acc1_cancer_cells))
})

# select features that are repeatedly variable across datasets for integration
features <- SelectIntegrationFeatures(object.list = acc1_cancer_cells.list,nfeatures = nrow(acc1_cancer_cells))
acc.anchors <- FindIntegrationAnchors(object.list = acc1_cancer_cells.list, anchor.features = features,k.filter = 50)
acc.combined <- IntegrateData(anchorset = acc.anchors,k.weight = 50)
Merging dataset 1 into 2
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
DefaultAssay(acc.combined) <- "integrated"

4.4 HPV-MYB

HPV33_P3 = fread("./Data/HPV33_P3.txt",col.names = c("plate","reads")) %>% as.data.frame()
HPV33_P3.df = HPV33_P3 %>% mutate(
  plate = gsub(x =HPV33_P3$plate, replacement = "",pattern = "_.*$") 
  %>% gsub(pattern = "-P",replacement = ".P") 
  %>% gsub(pattern = "-",replacement = "_",)
  )
HPV33_P3.df = HPV33_P3.df %>% dplyr::filter(HPV33_P3.df$plate %in% colnames(acc1_cancer_cells))
rownames(HPV33_P3.df)  <- HPV33_P3.df$plate
HPV33_P3.df$plate = NULL


HPV33_P2 = fread("./Data/HPV33_P2.txt",col.names = c("plate","reads")) %>% as.data.frame()
HPV33_P2.df = HPV33_P2 %>% mutate(
  plate = gsub(x =HPV33_P2$plate, replacement = "",pattern = "_.*$") 
  %>% gsub(pattern = "plate2-",replacement = "plate2_",)
  %>% gsub(pattern = "-",replacement = "\\.",)
  )
HPV33_P2.df = HPV33_P2.df %>% dplyr::filter(HPV33_P2.df$plate %in% colnames(acc1_cancer_cells))
rownames(HPV33_P2.df)  <- HPV33_P2.df$plate
HPV33_P2.df$plate = NULL

HPV33 = rbind(HPV33_P3.df,HPV33_P2.df)
acc.combined = AddMetaData(object = acc.combined,metadata = HPV33,col.name = "HPV33.reads")
hpv33_positive = HPV33 %>% dplyr::mutate(hpv33_positive = case_when(reads >= 10 ~ "positive",
                                                                    reads < 10 ~ "negative")
)



hpv33_positive$reads = NULL
acc.combined = AddMetaData(object = acc.combined,metadata = hpv33_positive)
myb_vs_hpv = FetchData(object = acc.combined,vars = c("hpv33_positive","MYB"))
myb_vs_hpv $hpv33_positive = as.character(myb_vs_hpv $hpv33_positive )

ggboxplot(myb_vs_hpv, x = "hpv33_positive", y = "MYB",
          palette = "jco",
          add = "jitter")+ stat_compare_means(method = "wilcox.test",comparisons = list(c("positive","negative")))+ stat_summary(fun.data = function(x) data.frame(y=15, label = paste("Mean=",round(mean(x),digits = 2))), geom="text") +ylab("log2(MYB)")

4.5 HPV-MYB per plate

plate_1 = subset(acc.combined,subset = plate == "ACC.plate2")
myb_vs_hpv = FetchData(object = plate_1,vars = c("hpv33_positive","MYB"))
myb_vs_hpv $hpv33_positive = as.character(myb_vs_hpv $hpv33_positive )

ggboxplot(myb_vs_hpv, x = "hpv33_positive", y = "MYB",
          palette = "jco",
          add = "jitter")+ stat_compare_means(method = "wilcox.test",comparisons = list(c("positive","negative")))+ stat_summary(fun.data = function(x) data.frame(y=15, label = paste("Mean=",round(mean(x),digits = 2))), geom="text") +ylab("log2(MYB)")+ggtitle("ACC.plate2")


plate_2 = subset(acc.combined,subset = plate == "ACC1.P3")
myb_vs_hpv = FetchData(object = plate_2,vars = c("hpv33_positive","MYB"))
myb_vs_hpv $hpv33_positive = as.character(myb_vs_hpv $hpv33_positive )

ggboxplot(myb_vs_hpv, x = "hpv33_positive", y = "MYB",
          palette = "jco",
          add = "jitter")+ stat_compare_means(method = "wilcox.test",comparisons = list(c("positive","negative")))+ stat_summary(fun.data = function(x) data.frame(y=15, label = paste("Mean=",round(mean(x),digits = 2))), geom="text") +ylab("log2(MYB)")+ggtitle("ACC1.P3")

LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19kZXB0aDogMQotLS0KCgoKIyBGdW5jdGlvbnMKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CnNvdXJjZV9mcm9tX2dpdGh1YihyZXBvc2l0b3kgPSAiY05NRl9mdW5jdGlvbnMiLHZlcnNpb24gPSAiMC4zLjg3IixzY3JpcHRfbmFtZSA9ICJjbm1mX2Z1bmN0aW9uX0hhcm1vbnkuUiIpCnNvdXJjZV9mcm9tX2dpdGh1YihyZXBvc2l0b3kgPSAiSE1TQ19mdW5jdGlvbnMiLHZlcnNpb24gPSAiMC4xLjEyIixzY3JpcHRfbmFtZSA9ICJmdW5jdGlvbnMuUiIpCgpgYGAKCiMgRGF0YQoKYGBge3J9CmFjYzFfY2FuY2VyX2NlbGxzID0gcmVhZFJEUygiLi9EYXRhL2FjYzFfY2FuY2VyX2NlbGxzXzE1S25Db3VudF9WMy5SRFMiKQphY2MxX2NhbmNlcl9jZWxscyRwbGF0ZSA9IGFjYzFfY2FuY2VyX2NlbGxzJG9yaWcuaWRlbnQKYGBgCgojIE9yaWdpbmFsIFVNQVAKYGBge3J9CkRpbVBsb3Qob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMscHQuc2l6ZSA9IDIsZ3JvdXAuYnkgPSAicGxhdGUiKQpgYGAKCgojIFNldXJhdCBpbnRlcmdyYXRpb24KYGBge3J9CmFjYzFfY2FuY2VyX2NlbGxzLmxpc3QgPC0gU3BsaXRPYmplY3QoYWNjMV9jYW5jZXJfY2VsbHMsIHNwbGl0LmJ5ID0gInBsYXRlIikKCiMgbm9ybWFsaXplIGFuZCBpZGVudGlmeSB2YXJpYWJsZSBmZWF0dXJlcyBmb3IgZWFjaCBkYXRhc2V0IGluZGVwZW5kZW50bHkKYWNjMV9jYW5jZXJfY2VsbHMubGlzdCA8LSBsYXBwbHkoWCA9IGFjYzFfY2FuY2VyX2NlbGxzLmxpc3QsIEZVTiA9IGZ1bmN0aW9uKHgpIHsKICAgICMgeCA8LSBOb3JtYWxpemVEYXRhKHgpCiAgICB4IDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKHgsIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMjAwMCkKfSkKCiMgc2VsZWN0IGZlYXR1cmVzIHRoYXQgYXJlIHJlcGVhdGVkbHkgdmFyaWFibGUgYWNyb3NzIGRhdGFzZXRzIGZvciBpbnRlZ3JhdGlvbgpmZWF0dXJlcyA8LSBTZWxlY3RJbnRlZ3JhdGlvbkZlYXR1cmVzKG9iamVjdC5saXN0ID0gYWNjMV9jYW5jZXJfY2VsbHMubGlzdCxuZmVhdHVyZXMgPSAyMDAwKQphY2MuYW5jaG9ycyA8LSBGaW5kSW50ZWdyYXRpb25BbmNob3JzKG9iamVjdC5saXN0ID0gYWNjMV9jYW5jZXJfY2VsbHMubGlzdCwgYW5jaG9yLmZlYXR1cmVzID0gZmVhdHVyZXMsay5maWx0ZXIgPSA1MCkKCmBgYAoKYGBge3J9CmFjYy5jb21iaW5lZCA8LSBJbnRlZ3JhdGVEYXRhKGFuY2hvcnNldCA9IGFjYy5hbmNob3JzLGsud2VpZ2h0ID0gNTApCkRlZmF1bHRBc3NheShhY2MuY29tYmluZWQpIDwtICJpbnRlZ3JhdGVkIgoKYGBgCgpgYGB7cn0KYWNjLmNvbWJpbmVkIDwtIFNjYWxlRGF0YShhY2MuY29tYmluZWQsIHZlcmJvc2UgPSBGQUxTRSkKYWNjLmNvbWJpbmVkIDwtIFJ1blBDQShhY2MuY29tYmluZWQsIG5wY3MgPSAzMCwgdmVyYm9zZSA9IEZBTFNFKQpFbGJvd1Bsb3QoYWNjLmNvbWJpbmVkKQoKYGBgCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmFjYy5jb21iaW5lZCA8LSBSdW5VTUFQKGFjYy5jb21iaW5lZCwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjEwKQphY2MuY29tYmluZWQgPC0gRmluZE5laWdoYm9ycyhhY2MuY29tYmluZWQsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gMToxMCkKYWNjLmNvbWJpbmVkIDwtIEZpbmRDbHVzdGVycyhhY2MuY29tYmluZWQsIHJlc29sdXRpb24gPSAwLjUpCmBgYAoKIyMgVU1BUFMKYGBge3J9CkRpbVBsb3QoYWNjLmNvbWJpbmVkLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInBsYXRlIikKRGltUGxvdChhY2MuY29tYmluZWQsIHJlZHVjdGlvbiA9ICJ1bWFwIikKYGBgCiMjIGNsdXN0ZXJzIERFRwpgYGB7cn0KYWNjX2RlZyA8LSBGaW5kTWFya2VycyhhY2MuY29tYmluZWQsIGlkZW50LjEgPSAiMCIsaWRlbnQuMiA9ICIxIixmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMoYWNjLmNvbWJpbmVkKSxkZW5zaWZ5ID0gVCkKYGBgCmBgYHtyfQplbnJpY2htZW50X2FuYWx5c2lzKGFjY19kZWcsYmFja2dyb3VuZCA9IFZhcmlhYmxlRmVhdHVyZXMoYWNjLmNvbWJpbmVkKSxmZHJfQ3V0b2ZmID0gMC4wMSxpZGVudC4xID0gIjAiLGlkZW50LjIgPSAiMSIsc2hvd19ieSA9IDEpCmBgYAoKIyMgbXlvLWx1bSBzY29yZQpgYGB7cn0Kb3JpZ2luYWxfbXlvX2dlbmVzID0gYyggIlRQNjMiLCAiVFA3MyIsICJDQVYxIiwgIkNESDMiLCAiS1JUNSIsICJLUlQxNCIsICJBQ1RBMiIsICJUQUdMTiIsICJNWUxLIiwgIkRLSzMiKQpvcmlnaW5hbF9sdW1fZ2VuZXMgPSBjKCJLSVQiLCAiRUhGIiwgIkVMRjUiLCAiS1JUNyIsICJDTEROMyIsICJDTERONCIsICJDRDI0IiwgIkxHQUxTMyIsICJMQ04yIiwgIlNMUEkiICkKYGBgCgoKYGBge3J9CmNhbGN1bGF0ZV9zY29yZSA9IGZ1bmN0aW9uKGRhdGFzZXQsbXlvX2dlbmVzLGx1bV9nZW5lcyxsdW1fdGhyZXNob2xkID0xICwgbXlvX3RocmVzaG9sZCA9IC0xKSB7CiAgbXlvc2NvcmU9RmV0Y2hEYXRhKG9iamVjdCA9ZGF0YXNldCx2YXJzID0gIG15b19nZW5lcyxzbG90ID0gImRhdGEiKSAlPiUgcm93TWVhbnMoKQogIGxlc2NvcmU9RmV0Y2hEYXRhKG9iamVjdCA9ZGF0YXNldCx2YXJzID0gIGx1bV9nZW5lcyxzbG90ID0gImRhdGEiKSAlPiUgcm93TWVhbnMoKQogIGNvcnJlbGF0aW9uID0gY29yKGxlc2NvcmUsbXlvc2NvcmUpICU+JSByb3VuZChkaWdpdHMgPSAyKQogIG1lc3NhZ2UoImNvcnJlbGF0aW9uIG9mIGx1bSBzY29yZSBhbmQgbXlvIHNjb3JlOiIgJT4lIHBhc3RlKGNvcnJlbGF0aW9uKSkKICAKCgoKCiAgZGF0YXNldD1BZGRNZXRhRGF0YShkYXRhc2V0LGxlc2NvcmUtbXlvc2NvcmUsImx1bWluYWxfb3Zlcl9teW8iKQogIHByaW50KAogICAgRmVhdHVyZVBsb3Qob2JqZWN0ID0gZGF0YXNldCxmZWF0dXJlcyA9ICJsdW1pbmFsX292ZXJfbXlvIikKICApCiAgZGF0YSA9IEZldGNoRGF0YShvYmplY3QgPSBkYXRhc2V0LHZhcnMgPSAibHVtaW5hbF9vdmVyX215byIpCiAgcHJpbnQoCiAgICBkYXRhICU+JSAKICAgIGdncGxvdChhZXMoIHg9bHVtaW5hbF9vdmVyX215bykpICsgCiAgICBnZW9tX2RlbnNpdHkoKSAKICAgICkKICAKbHVtX2NlbGxzX251bSA9IHN1YnNldCh4ID0gZGF0YXNldCxsdW1pbmFsX292ZXJfbXlvID4obHVtX3RocmVzaG9sZCkpICU+JSBuY29sKCkgL25jb2woZGF0YXNldCkKbXlvX2NlbGxzX251bSA9IHN1YnNldCh4ID0gZGF0YXNldCxsdW1pbmFsX292ZXJfbXlvIDwobXlvX3RocmVzaG9sZCkpICU+JSBuY29sKCkvbmNvbChkYXRhc2V0KQpkZiA9IGRhdGEuZnJhbWUoY2VsbF90eXBlID0gYygibXlvX2NlbGxzIiwibHVtX2NlbGxzIikscGVyY2VudGFnZSA9IGMobXlvX2NlbGxzX251bSxsdW1fY2VsbHNfbnVtKSkKZ2dwbG90KGRhdGE9ZGYsIGFlcyh4PWNlbGxfdHlwZSwgeT1wZXJjZW50YWdlKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKyBnZ3RpdGxlKCJBQ0MgY2VsbCB0eXBlcyIpCn0KYGBgCgpgYGB7cn0KY2FsY3VsYXRlX3Njb3JlKGRhdGFzZXQgPSBhY2MuY29tYmluZWQsbXlvX2dlbmVzID0gb3JpZ2luYWxfbXlvX2dlbmVzLGx1bV9nZW5lcyA9IG9yaWdpbmFsX2x1bV9nZW5lcykKYGBgCgpgYGB7cn0KYWNjMV9jYW5jZXJfY2VsbHMubGlzdCA8LSBTcGxpdE9iamVjdChhY2MxX2NhbmNlcl9jZWxscywgc3BsaXQuYnkgPSAicGxhdGUiKQoKIyBub3JtYWxpemUgYW5kIGlkZW50aWZ5IHZhcmlhYmxlIGZlYXR1cmVzIGZvciBlYWNoIGRhdGFzZXQgaW5kZXBlbmRlbnRseQphY2MxX2NhbmNlcl9jZWxscy5saXN0IDwtIGxhcHBseShYID0gYWNjMV9jYW5jZXJfY2VsbHMubGlzdCwgRlVOID0gZnVuY3Rpb24oeCkgewogICAgIyB4IDwtIE5vcm1hbGl6ZURhdGEoeCkKICAgIHggPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoeCwgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSBucm93KGFjYzFfY2FuY2VyX2NlbGxzKSkKfSkKCiMgc2VsZWN0IGZlYXR1cmVzIHRoYXQgYXJlIHJlcGVhdGVkbHkgdmFyaWFibGUgYWNyb3NzIGRhdGFzZXRzIGZvciBpbnRlZ3JhdGlvbgpmZWF0dXJlcyA8LSBTZWxlY3RJbnRlZ3JhdGlvbkZlYXR1cmVzKG9iamVjdC5saXN0ID0gYWNjMV9jYW5jZXJfY2VsbHMubGlzdCxuZmVhdHVyZXMgPSBucm93KGFjYzFfY2FuY2VyX2NlbGxzKSkKYWNjLmFuY2hvcnMgPC0gRmluZEludGVncmF0aW9uQW5jaG9ycyhvYmplY3QubGlzdCA9IGFjYzFfY2FuY2VyX2NlbGxzLmxpc3QsIGFuY2hvci5mZWF0dXJlcyA9IGZlYXR1cmVzLGsuZmlsdGVyID0gNTApCgpgYGAKCmBgYHtyfQphY2MuY29tYmluZWQgPC0gSW50ZWdyYXRlRGF0YShhbmNob3JzZXQgPSBhY2MuYW5jaG9ycyxrLndlaWdodCA9IDUwKQpEZWZhdWx0QXNzYXkoYWNjLmNvbWJpbmVkKSA8LSAiaW50ZWdyYXRlZCIKCmBgYAojIyBIUFYtTVlCCmBgYHtyfQpIUFYzM19QMyA9IGZyZWFkKCIuL0RhdGEvSFBWMzNfUDMudHh0Iixjb2wubmFtZXMgPSBjKCJwbGF0ZSIsInJlYWRzIikpICU+JSBhcy5kYXRhLmZyYW1lKCkKSFBWMzNfUDMuZGYgPSBIUFYzM19QMyAlPiUgbXV0YXRlKAogIHBsYXRlID0gZ3N1Yih4ID1IUFYzM19QMyRwbGF0ZSwgcmVwbGFjZW1lbnQgPSAiIixwYXR0ZXJuID0gIl8uKiQiKSAKICAlPiUgZ3N1YihwYXR0ZXJuID0gIi1QIixyZXBsYWNlbWVudCA9ICIuUCIpIAogICU+JSBnc3ViKHBhdHRlcm4gPSAiLSIscmVwbGFjZW1lbnQgPSAiXyIsKQogICkKSFBWMzNfUDMuZGYgPSBIUFYzM19QMy5kZiAlPiUgZHBseXI6OmZpbHRlcihIUFYzM19QMy5kZiRwbGF0ZSAlaW4lIGNvbG5hbWVzKGFjYzFfY2FuY2VyX2NlbGxzKSkKcm93bmFtZXMoSFBWMzNfUDMuZGYpICA8LSBIUFYzM19QMy5kZiRwbGF0ZQpIUFYzM19QMy5kZiRwbGF0ZSA9IE5VTEwKCgpIUFYzM19QMiA9IGZyZWFkKCIuL0RhdGEvSFBWMzNfUDIudHh0Iixjb2wubmFtZXMgPSBjKCJwbGF0ZSIsInJlYWRzIikpICU+JSBhcy5kYXRhLmZyYW1lKCkKSFBWMzNfUDIuZGYgPSBIUFYzM19QMiAlPiUgbXV0YXRlKAogIHBsYXRlID0gZ3N1Yih4ID1IUFYzM19QMiRwbGF0ZSwgcmVwbGFjZW1lbnQgPSAiIixwYXR0ZXJuID0gIl8uKiQiKSAKICAlPiUgZ3N1YihwYXR0ZXJuID0gInBsYXRlMi0iLHJlcGxhY2VtZW50ID0gInBsYXRlMl8iLCkKICAlPiUgZ3N1YihwYXR0ZXJuID0gIi0iLHJlcGxhY2VtZW50ID0gIlxcLiIsKQogICkKSFBWMzNfUDIuZGYgPSBIUFYzM19QMi5kZiAlPiUgZHBseXI6OmZpbHRlcihIUFYzM19QMi5kZiRwbGF0ZSAlaW4lIGNvbG5hbWVzKGFjYzFfY2FuY2VyX2NlbGxzKSkKcm93bmFtZXMoSFBWMzNfUDIuZGYpICA8LSBIUFYzM19QMi5kZiRwbGF0ZQpIUFYzM19QMi5kZiRwbGF0ZSA9IE5VTEwKCkhQVjMzID0gcmJpbmQoSFBWMzNfUDMuZGYsSFBWMzNfUDIuZGYpCmFjYy5jb21iaW5lZCA9IEFkZE1ldGFEYXRhKG9iamVjdCA9IGFjYy5jb21iaW5lZCxtZXRhZGF0YSA9IEhQVjMzLGNvbC5uYW1lID0gIkhQVjMzLnJlYWRzIikKYGBgCgpgYGB7cn0KaHB2MzNfcG9zaXRpdmUgPSBIUFYzMyAlPiUgZHBseXI6Om11dGF0ZShocHYzM19wb3NpdGl2ZSA9IGNhc2Vfd2hlbihyZWFkcyA+PSAxMCB+ICJwb3NpdGl2ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZHMgPCAxMCB+ICJuZWdhdGl2ZSIpCikKCgoKaHB2MzNfcG9zaXRpdmUkcmVhZHMgPSBOVUxMCmFjYy5jb21iaW5lZCA9IEFkZE1ldGFEYXRhKG9iamVjdCA9IGFjYy5jb21iaW5lZCxtZXRhZGF0YSA9IGhwdjMzX3Bvc2l0aXZlKQpgYGAKCgpgYGB7cn0KbXliX3ZzX2hwdiA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MuY29tYmluZWQsdmFycyA9IGMoImhwdjMzX3Bvc2l0aXZlIiwiTVlCIikpCm15Yl92c19ocHYgJGhwdjMzX3Bvc2l0aXZlID0gYXMuY2hhcmFjdGVyKG15Yl92c19ocHYgJGhwdjMzX3Bvc2l0aXZlICkKCmdnYm94cGxvdChteWJfdnNfaHB2LCB4ID0gImhwdjMzX3Bvc2l0aXZlIiwgeSA9ICJNWUIiLAogICAgICAgICAgcGFsZXR0ZSA9ICJqY28iLAogICAgICAgICAgYWRkID0gImppdHRlciIpKyBzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gIndpbGNveC50ZXN0Iixjb21wYXJpc29ucyA9IGxpc3QoYygicG9zaXRpdmUiLCJuZWdhdGl2ZSIpKSkrIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IGZ1bmN0aW9uKHgpIGRhdGEuZnJhbWUoeT0xNSwgbGFiZWwgPSBwYXN0ZSgiTWVhbj0iLHJvdW5kKG1lYW4oeCksZGlnaXRzID0gMikpKSwgZ2VvbT0idGV4dCIpICt5bGFiKCJsb2cyKE1ZQikiKQoKYGBgCiMjIEhQVi1NWUIgcGVyIHBsYXRlCmBgYHtyfQpwbGF0ZV8xID0gc3Vic2V0KGFjYy5jb21iaW5lZCxzdWJzZXQgPSBwbGF0ZSA9PSAiQUNDLnBsYXRlMiIpCm15Yl92c19ocHYgPSBGZXRjaERhdGEob2JqZWN0ID0gcGxhdGVfMSx2YXJzID0gYygiaHB2MzNfcG9zaXRpdmUiLCJNWUIiKSkKbXliX3ZzX2hwdiAkaHB2MzNfcG9zaXRpdmUgPSBhcy5jaGFyYWN0ZXIobXliX3ZzX2hwdiAkaHB2MzNfcG9zaXRpdmUgKQoKZ2dib3hwbG90KG15Yl92c19ocHYsIHggPSAiaHB2MzNfcG9zaXRpdmUiLCB5ID0gIk1ZQiIsCiAgICAgICAgICBwYWxldHRlID0gImpjbyIsCiAgICAgICAgICBhZGQgPSAiaml0dGVyIikrIHN0YXRfY29tcGFyZV9tZWFucyhtZXRob2QgPSAid2lsY294LnRlc3QiLGNvbXBhcmlzb25zID0gbGlzdChjKCJwb3NpdGl2ZSIsIm5lZ2F0aXZlIikpKSsgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gZnVuY3Rpb24oeCkgZGF0YS5mcmFtZSh5PTE1LCBsYWJlbCA9IHBhc3RlKCJNZWFuPSIscm91bmQobWVhbih4KSxkaWdpdHMgPSAyKSkpLCBnZW9tPSJ0ZXh0IikgK3lsYWIoImxvZzIoTVlCKSIpK2dndGl0bGUoIkFDQy5wbGF0ZTIiKQoKcGxhdGVfMiA9IHN1YnNldChhY2MuY29tYmluZWQsc3Vic2V0ID0gcGxhdGUgPT0gIkFDQzEuUDMiKQpteWJfdnNfaHB2ID0gRmV0Y2hEYXRhKG9iamVjdCA9IHBsYXRlXzIsdmFycyA9IGMoImhwdjMzX3Bvc2l0aXZlIiwiTVlCIikpCm15Yl92c19ocHYgJGhwdjMzX3Bvc2l0aXZlID0gYXMuY2hhcmFjdGVyKG15Yl92c19ocHYgJGhwdjMzX3Bvc2l0aXZlICkKCmdnYm94cGxvdChteWJfdnNfaHB2LCB4ID0gImhwdjMzX3Bvc2l0aXZlIiwgeSA9ICJNWUIiLAogICAgICAgICAgcGFsZXR0ZSA9ICJqY28iLAogICAgICAgICAgYWRkID0gImppdHRlciIpKyBzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gIndpbGNveC50ZXN0Iixjb21wYXJpc29ucyA9IGxpc3QoYygicG9zaXRpdmUiLCJuZWdhdGl2ZSIpKSkrIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IGZ1bmN0aW9uKHgpIGRhdGEuZnJhbWUoeT0xNSwgbGFiZWwgPSBwYXN0ZSgiTWVhbj0iLHJvdW5kKG1lYW4oeCksZGlnaXRzID0gMikpKSwgZ2VvbT0idGV4dCIpICt5bGFiKCJsb2cyKE1ZQikiKStnZ3RpdGxlKCJBQ0MxLlAzIikKYGBgCjxzY3JpcHQgc3JjPSJodHRwczovL2h5cG90aGVzLmlzL2VtYmVkLmpzIiBhc3luYz48L3NjcmlwdD4KCg==