Data
lung = readRDS("./Data/lung_cancercells_withTP_onlyPatients.rds")
lung_patients = lung$patient.ident %>% unique() %>% as.character()
lung_patients_filtered = lung_patients[!(lung_patients %in% c("X1055new","X1099"))] # remove patients with less than 100 malignant cells
lung = subset(x = lung,subset = patient.ident %in% lung_patients_filtered)
suffix ="xeno_genes_normalized_0-5sigma_2-7theta"
from cnmf import cNMF
suffix = r.suffix
import pickle
f = open('./Data/cnmf/cnmf_objects/patients_' + suffix + '_cnmf_obj.pckl', 'rb')
cnmf_obj = pickle.load(f)
f.close()
Functions
library(stringi)
library(reticulate)
source_from_github(repositoy = "DEG_functions",version = "0.2.24")
source_from_github(repositoy = "cNMF_functions",version = "0.3.9",script_name = "cnmf_function_Harmony.R")
K selection plot
plot_path = paste0("/sci/labs/yotamd/lab_share/avishai.wizel/R_projects/EGFR/Data/cnmf/cNMF_patients_Varnorm_Harmony_",suffix,"/cNMF_patients_Varnorm_Harmony_",suffix,".k_selection.png")
knitr::include_graphics(plot_path)

gep scores for all NMF
k’s
density_threshold = 0.1
usage_norm, gep_scores3, gep_tpm, topgenes = cnmf_obj.load_results(K=3, density_threshold=density_threshold)
usage_norm, gep_scores4, gep_tpm, topgenes = cnmf_obj.load_results(K=4, density_threshold=density_threshold)
usage_norm, gep_scores5, gep_tpm, topgenes = cnmf_obj.load_results(K=5, density_threshold=density_threshold)
usage_norm, gep_scores6, gep_tpm, topgenes = cnmf_obj.load_results(K=6, density_threshold=density_threshold)
usage_norm, gep_scores7, gep_tpm, topgenes = cnmf_obj.load_results(K=7, density_threshold=density_threshold)
usage_norm, gep_scores8, gep_tpm, topgenes = cnmf_obj.load_results(K=8, density_threshold=density_threshold)
usage_norm, gep_scores9, gep_tpm, topgenes = cnmf_obj.load_results(K=9, density_threshold=density_threshold)
Enrichment analysis by top 200 genes of each program
gep_scores3 = py$gep_scores3
gep_scores4 = py$gep_scores4
gep_scores5 = py$gep_scores5
gep_scores6 = py$gep_scores6
gep_scores7 = py$gep_scores7
gep_scores8 = py$gep_scores8
gep_scores9 = py$gep_scores9
all_gep_scores = list(gep_scores3 = gep_scores3, gep_scores4 = gep_scores4, gep_scores5 = gep_scores5, gep_scores6 = gep_scores6, gep_scores7= gep_scores7, gep_scores8 = gep_scores8, gep_scores9 = gep_scores9)
# canonical_pathways = msigdbr(species = "Homo sapiens", category = "C2") %>% dplyr::filter(gs_subcat != "CGP") %>% dplyr::distinct(gs_name, gene_symbol)
for (gep_name in names(all_gep_scores)) {
gep_scores = all_gep_scores[[gep_name]]
top_genes_num = 200
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),top_genes_num) #take top top_genes_num
res = genes_vec_enrichment(genes = top,background = rownames(gep_scores),homer = T,title =
names(gep_scores)[i],silent = T,return_all = T,custom_pathways = NULL )
plt_list[[i]] = res$plt
}
print_tab(plt = ggarrange(plotlist = plt_list),
title = gep_name)
}
gep_scores3

gep_scores4

gep_scores5

gep_scores6

gep_scores7

gep_scores8

gep_scores9

NA
Chosen K
selected_k = 8
print("selected k = ",selected_k)
selected k = 8
density_threshold = 0.1
cnmf_obj.consensus(k=selected_k, density_threshold=density_threshold,show_clustering=True)
usage_norm, gep_scores, gep_tpm, topgenes = cnmf_obj.load_results(K=selected_k, density_threshold=density_threshold)
gep_scores = py$gep_scores
# canonical_pathways = msigdbr(species = "Homo sapiens", category = "C2") %>% dplyr::filter(gs_subcat != "CGP") %>% dplyr::distinct(gs_name, gene_symbol)
top_genes_num = 200
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),top_genes_num) #take top top_genes_num
res = genes_vec_enrichment(genes = top,background = rownames(gep_scores),homer = T,title =
names(gep_scores)[i],silent = T,return_all = T,custom_pathways = NULL )
plt_list[[i]] = res$plt
}
gridExtra::grid.arrange(grobs = plt_list)

Correlation of
programs
gep_scores = py$gep_scores
cor_res = cor(gep_scores)
breaks <- c(seq(-1,1,by=0.01))
colors_for_plot <- colorRampPalette(colors = c("blue", "white", "red"))(n = length(breaks))
pheatmap(cor_res,color = colors_for_plot,breaks = breaks)

correlation by top 150
combined
all_top= c()
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
all_top = c(all_top,top)
}
gep_scores_top = gep_scores[all_top,]
cor_res = cor(gep_scores_top)
breaks <- c(seq(-1,1,by=0.01))
colors_for_plot <- colorRampPalette(colors = c("blue", "white", "red"))(n = length(breaks))
pheatmap(cor_res,color = colors_for_plot,breaks = breaks)
Combine similar
programs
gep_scores = py$gep_scores
# groups_list = c(4,5,3)
# groups_list = c(4,5,6)
# groups_list = c(4,5,7)
groups_list = c(4,3,6)
gep_scores = union_programs(groups_list = groups_list,all_metagenes = gep_scores)
top_genes_num = 200
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),top_genes_num) #take top top_genes_num
res = genes_vec_enrichment(genes = top,background = rownames(gep_scores),homer = T,title =
names(gep_scores)[i],silent = T,return_all = T)
plt_list[[i]] = res$plt
}
gridExtra::grid.arrange(grobs = plt_list)

Calculate usage
# get expression with genes in cnmf input
lung = FindVariableFeatures(object = lung,nfeatures = 2000)
genes = rownames(lung)[rownames(lung) %in% VariableFeatures(object = xeno)[1:2000]]
lung_expression = t(as.matrix(GetAssayData(lung,slot='data')))
lung_expression = 2**lung_expression #convert from log2(tpm+1) to tpm
lung_expression = lung_expression-1
lung_expression = lung_expression[,genes] %>% as.data.frame()
all_0_genes = colnames(lung_expression)[colSums(lung_expression==0, na.rm=TRUE)==nrow(lung_expression)] #delete rows that have all 0
genes = genes[!genes %in% all_0_genes]
lung_expression = lung_expression[,!colnames(lung_expression) %in% all_0_genes]
gc(verbose = F)
lung_expression = r.lung_expression
genes = r.genes
gep_scores = r.gep_scores
usage_by_calc = get_usage_from_score(counts=lung_expression,tpm=lung_expression,genes=genes,cnmf_obj=cnmf_obj,k=selected_k,sumTo1=False)
usage_by_calc =usage_by_calc %>% rename(cell_cycle = gep4.3.6, hypoxia_like = gep2, interferon_like = gep1, TNFa = gep5, INF2 = gep7)
Error in `chr_as_locations()`:
! Can't rename columns that don't exist.
✖ Column `gep4.3.6` doesn't exist.
Backtrace:
1. usage_by_calc %>% ...
3. dplyr:::rename.data.frame(...)
4. tidyselect::eval_rename(expr(c(...)), .data)
5. tidyselect:::rename_impl(...)
6. tidyselect:::eval_select_impl(...)
...
18. tidyselect:::reduce_sels(node, data_mask, context_mask, init = init)
19. tidyselect:::walk_data_tree(new, data_mask, context_mask)
20. tidyselect:::as_indices_sel_impl(...)
21. tidyselect:::as_indices_impl(x, vars, call = call, strict = strict)
22. tidyselect:::chr_as_locations(x, vars, call = call)
Usgage UMAP
all_metagenes= usage_by_calc
#add each metagene to metadata
for (i in 1:ncol(all_metagenes)) {
metage_metadata = all_metagenes %>% dplyr::select(i)
lung = AddMetaData(object = lung,metadata = metage_metadata)
}
Note: Using an external vector in selections is ambiguous.
ℹ Use `all_of(i)` instead of `i` to silence this message.
ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
This message is displayed once per session.
FeaturePlot(object = lung,features = colnames(all_metagenes),ncol = 3)
Warning: The following variables were found in both object metadata and the default assay: INF2
Returning metadata; if you want the feature, please use the assay's key (eg. rna_INF2)

DimPlot(object = lung,group.by = "time.point",pt.size = 0.5)
pre_treatment_cells = FetchData(object = lung,vars = "time.point") %>% filter(time.point == "pre-treatment") %>% rownames()
on_treatment_cells = FetchData(object = lung,vars = "time.point") %>% filter(time.point == "on-treatment") %>% rownames()
cells_to_highlight = list(pre_treatment_cells = pre_treatment_cells)
DimPlot(object = lung, cells.highlight = cells_to_highlight, cols.highlight = c("red"), cols = "gray", order = TRUE, label = T, repel = T)
cells_to_highlight = list(on_treatment_cells = on_treatment_cells)
DimPlot(object = lung, cells.highlight = cells_to_highlight, cols.highlight = c("cyan3"), cols = "gray", order = TRUE, label = T, repel = T)
DotPlot(object = lung, features = c("hypoxia_like","interferon_like","cell_cycle","TNFa", "INF2"),scale = T,group.by = 'time.point')
Warning: The following variables were found in both object metadata and the default assay: INF2
Returning metadata; if you want the feature, please use the assay's key (eg. rna_INF2)

Assignment
larger_by = 1.25
lung = program_assignment(dataset = lung,larger_by = larger_by,program_names = colnames(all_metagenes))
p = cell_percentage(dataset = lung,time.point_var = "time.point",by_program = T)
print_tab(plt = p,title = "by program")
p = cell_percentage(dataset = lung,time.point_var = "time.point",by_tp = T,x_order = NULL)
print_tab(plt = p,title = "by timepoint")
program.assignment
# colors = rainbow(ncol(all_metagenes))
# fc <- colorRampPalette(c("lightgreen", "darkgreen"))
# greens = fc(4)
# colors[1] = "blue"
# colors[2:3] = greens[1:2]
# colors[4] = "red"
# colors[5:6] = greens[3:4]
# colors = c(colors,"grey")
# DimPlot(lung,group.by = "program.assignment",pt.size = 0.5,cols =colors)
# colors = rainbow(ncol(all_metagenes))
# colors = c(colors,"grey")
# DimPlot(lung,group.by = "program.assignment",pt.size = 0.5,cols =colors)
DimPlot(lung,group.by = "program.assignment",pt.size = 0.5)
DimPlot(lung,group.by = "patient.ident",pt.size = 0.5)
DimPlot(lung,group.by = "time.point",pt.size = 0.5)
Score
regulation
metagenes_mean_compare(dataset = lung, time.point_var = "time.point",prefix = "patient",patient.ident_var = "patient.ident",pre_on = c("pre-treatment","on-treatment"),axis.text.x = 8,programs = c("hypoxia_like","interferon_like","cell_cycle"))
hypoxia_like per patient

hypoxia_like

interferon_like per patient

interferon_like

cell_cycle per patient

cell_cycle

NA
CC
signature
hallmark_name = "HALLMARK_G2M_CHECKPOINT"
genesets =getGmt("./Data/h.all.v7.0.symbols.pluscc.gmt")
geneIds= genesets[[hallmark_name]]@geneIds
hallmars_exp = FetchData(object = xeno,vars = c(geneIds))
hallmars_exp = hallmars_exp[,colSums(hallmars_exp[])>0] #remove no expression genes
hallmark_cor = cor(hallmars_exp)
pht1 = pheatmap(mat = hallmark_cor,silent = T)
num_of_clusters = 4
clustering_distance = "euclidean"
myannotation = as.data.frame(cutree(pht1[["tree_row"]], k = num_of_clusters)) #split into k clusters
names(myannotation)[1] = "cluster"
myannotation$cluster = as.factor(myannotation$cluster)
palette1 <-brewer.pal(num_of_clusters, "Paired")
names(palette1) = unique(myannotation$cluster)
ann_colors = list (cluster = palette1)
annotation = list(ann_colors = ann_colors, myannotation = myannotation)
colors <- c(seq(-1,1,by=0.01))
my_palette <- c("blue",colorRampPalette(colors = c("blue", "white", "red"))
(n = length(colors)-3), "red")
print_tab(plt =
pheatmap(mat = hallmark_cor,annotation_col = annotation[["myannotation"]], annotation_colors = annotation[["ann_colors"]], clustering_distance_rows = clustering_distance,clustering_distance_cols = clustering_distance,color = my_palette,breaks = colors,show_rownames = F,show_colnames = F)
,title = "genes expression heatmap")
genes expression heatmap

NA
chosen_genes = annotation[["myannotation"]] %>% dplyr::filter(cluster == 1 | cluster == 2) %>% rownames() #take relevant genes
var_features=lung@assays$RNA@var.features
geneIds= genesets[[hallmark_name]]@geneIds
score <- apply(lung@assays$RNA@data[intersect(geneIds,var_features),],2,mean)
lung=AddMetaData(lung,score,hallmark_name)
print_tab(FeaturePlot(object = lung, features = hallmark_name),title = "Expression")
Expression

NA
cc_scores = FetchData(object = lung,vars = "HALLMARK_G2M_CHECKPOINT")
plt = ggplot(cc_scores, aes(x=HALLMARK_G2M_CHECKPOINT)) +
geom_density()+
geom_vline(
aes(xintercept=mean(cc_scores$HALLMARK_G2M_CHECKPOINT) + sd(cc_scores$HALLMARK_G2M_CHECKPOINT) ,color="1 SD"),
linetype="dashed", size=1)+
geom_vline(
aes(xintercept=mean(cc_scores$HALLMARK_G2M_CHECKPOINT) + 2*sd(cc_scores$HALLMARK_G2M_CHECKPOINT) ,color="2 SD"),
linetype="dashed", size=1)
print_tab(plt = plt,title = "dist")
dist
Warning: Use of cc_scores$HALLMARK_G2M_CHECKPOINT is
discouraged. Use HALLMARK_G2M_CHECKPOINT instead. Warning:
Use of cc_scores$HALLMARK_G2M_CHECKPOINT is discouraged.
Use HALLMARK_G2M_CHECKPOINT instead. Warning: Use of
cc_scores$HALLMARK_G2M_CHECKPOINT is discouraged. Use
HALLMARK_G2M_CHECKPOINT instead. Warning: Use of
cc_scores$HALLMARK_G2M_CHECKPOINT is discouraged. Use
HALLMARK_G2M_CHECKPOINT instead.

NA
cc_scores = cc_scores %>% mutate(is_cycling = if_else(condition =
HALLMARK_G2M_CHECKPOINT > mean(HALLMARK_G2M_CHECKPOINT) + sd(HALLMARK_G2M_CHECKPOINT),
true = "cycling",
false = "non_cycling"))
lung = AddMetaData(object = lung,metadata = cc_scores$is_cycling,col.name = "is_cycling")
print_tab(plt = DimPlot(object = lung,group.by = "is_cycling") , title = "assignment 1 sd")
assignment 1 sd

cc_scores = cc_scores %>% mutate(is_cycling = if_else(condition =
HALLMARK_G2M_CHECKPOINT > mean(HALLMARK_G2M_CHECKPOINT) + 2*sd(cc_scores$HALLMARK_G2M_CHECKPOINT),
true = "cycling",
false = "non_cycling"))
lung = AddMetaData(object = lung,metadata = cc_scores$is_cycling,col.name = "is_cycling")
print_tab(plt = DimPlot(object = lung,group.by = "is_cycling") , title = "assignment 2 sd")
assignment 2 sd

NA
df = FetchData(object = lung,vars = c("is_cycling","time.point")) %>%
filter (time.point %in% c("pre-treatment","on-treatment")) %>%
droplevels()
test = fisher.test(table(df))
library(ggstatsplot)
plt = ggbarstats(
df, is_cycling, time.point,
results.subtitle = FALSE,
subtitle = paste0(
"Fisher's exact test", ", p-value = ",
round(test$p.value,13))
)
print_tab(plt = plt,title = "fisher")
fisher

NA
Hypoxia
signature
hallmark_name = "HALLMARK_HYPOXIA"
genesets =getGmt("./Data/h.all.v7.0.symbols.pluscc.gmt")
geneIds= genesets[[hallmark_name]]@geneIds
hallmars_exp = FetchData(object = xeno,vars = c(geneIds))
Warning in FetchData.Seurat(object = xeno, vars = c(geneIds)) : The
following requested variables were not found: CCN5, CCN1, CCN2
hallmars_exp = hallmars_exp[,colSums(hallmars_exp[])>0] #remove no expression genes
hallmark_cor = cor(hallmars_exp)
pht1 = pheatmap(mat = hallmark_cor,silent = T)
num_of_clusters = 4
clustering_distance = "euclidean"
myannotation = as.data.frame(cutree(pht1[["tree_row"]], k = num_of_clusters)) #split into k clusters
names(myannotation)[1] = "cluster"
myannotation$cluster = as.factor(myannotation$cluster)
palette1 <-brewer.pal(num_of_clusters, "Paired")
names(palette1) = unique(myannotation$cluster)
ann_colors = list (cluster = palette1)
annotation = list(ann_colors = ann_colors, myannotation = myannotation)
colors <- c(seq(-1,1,by=0.01))
my_palette <- c("blue",colorRampPalette(colors = c("blue", "white", "red"))
(n = length(colors)-3), "red")
print_tab(plt =
pheatmap(mat = hallmark_cor,annotation_col = annotation[["myannotation"]], annotation_colors = annotation[["ann_colors"]], clustering_distance_rows = clustering_distance,clustering_distance_cols = clustering_distance,color = my_palette,breaks = colors,show_rownames = F,show_colnames = F)
,title = "genes expression heatmap")
genes expression heatmap

NA
chosen_genes = annotation[["myannotation"]] %>% dplyr::filter(cluster == 1 | cluster == 2) %>% rownames() #take relevant genes
var_features=lung@assays$RNA@var.features
geneIds= genesets[[hallmark_name]]@geneIds
score <- apply(lung@assays$RNA@data[intersect(geneIds,var_features),],2,mean)
lung=AddMetaData(lung,score,hallmark_name)
print_tab(FeaturePlot(object = lung, features = hallmark_name),title = "Expression")
Expression

NA
cc_scores = FetchData(object = lung,vars = hallmark_name)
plt = ggplot(cc_scores, aes(x=HALLMARK_HYPOXIA)) +
geom_density()+
geom_vline(
aes(xintercept=mean(cc_scores$HALLMARK_HYPOXIA) + sd(cc_scores$HALLMARK_HYPOXIA) ,color="1 SD"),
linetype="dashed", size=1)+
geom_vline(
aes(xintercept=mean(cc_scores$HALLMARK_HYPOXIA) + 2*sd(cc_scores$HALLMARK_HYPOXIA) ,color="2 SD"),
linetype="dashed", size=1)
print_tab(plt = plt,title = "dist")
dist
Warning: Use of cc_scores$HALLMARK_HYPOXIA is
discouraged. Use HALLMARK_HYPOXIA instead. Warning: Use of
cc_scores$HALLMARK_HYPOXIA is discouraged. Use
HALLMARK_HYPOXIA instead. Warning: Use of
cc_scores$HALLMARK_HYPOXIA is discouraged. Use
HALLMARK_HYPOXIA instead. Warning: Use of
cc_scores$HALLMARK_HYPOXIA is discouraged. Use
HALLMARK_HYPOXIA instead.

NA
glycolysis signature
hallmark_name = "HALLMARK_GLYCOLYSIS"
genesets =getGmt("./Data/h.all.v7.0.symbols.pluscc.gmt")
geneIds= genesets[[hallmark_name]]@geneIds
hallmars_exp = FetchData(object = xeno,vars = c(geneIds))
Warning in FetchData.Seurat(object = xeno, vars = c(geneIds)) : The
following requested variables were not found: AC010618.1
hallmars_exp = hallmars_exp[,colSums(hallmars_exp[])>0] #remove no expression genes
hallmark_cor = cor(hallmars_exp)
pht1 = pheatmap(mat = hallmark_cor,silent = T)
num_of_clusters = 5
clustering_distance = "euclidean"
myannotation = as.data.frame(cutree(pht1[["tree_row"]], k = num_of_clusters)) #split into k clusters
names(myannotation)[1] = "cluster"
myannotation$cluster = as.factor(myannotation$cluster)
palette1 <-brewer.pal(num_of_clusters, "Paired")
names(palette1) = unique(myannotation$cluster)
ann_colors = list (cluster = palette1)
annotation = list(ann_colors = ann_colors, myannotation = myannotation)
colors <- c(seq(-1,1,by=0.01))
my_palette <- c("blue",colorRampPalette(colors = c("blue", "white", "red"))
(n = length(colors)-3), "red")
print_tab(plt =
pheatmap(mat = hallmark_cor,annotation_col = annotation[["myannotation"]], annotation_colors = annotation[["ann_colors"]], clustering_distance_rows = clustering_distance,clustering_distance_cols = clustering_distance,color = my_palette,breaks = colors,show_rownames = F,show_colnames = F)
,title = "genes expression heatmap")
genes expression heatmap

NA
chosen_genes = annotation[["myannotation"]] %>% dplyr::filter(cluster == 1 | cluster == 2 | cluster == 5) %>% rownames() #take relevant genes
var_features=lung@assays$RNA@var.features
geneIds= genesets[[hallmark_name]]@geneIds
score <- apply(lung@assays$RNA@data[intersect(geneIds,var_features),],2,mean)
lung=AddMetaData(lung,score,hallmark_name)
print_tab(FeaturePlot(object = lung, features = hallmark_name),title = "Expression")
Expression

NA
cc_scores = FetchData(object = lung,vars = hallmark_name)
plt = ggplot(cc_scores, aes(x=HALLMARK_GLYCOLYSIS)) +
geom_density()+
geom_vline(
aes(xintercept=mean(HALLMARK_GLYCOLYSIS) + sd(HALLMARK_GLYCOLYSIS) ,color="1 SD"),
linetype="dashed", size=1)+
geom_vline(
aes(xintercept=mean(HALLMARK_GLYCOLYSIS) + 2*sd(HALLMARK_GLYCOLYSIS) ,color="2 SD"),
linetype="dashed", size=1)+
geom_vline(
aes(xintercept=mean(HALLMARK_GLYCOLYSIS) ,color="mean"),
linetype="dashed", size=1)
print_tab(plt = plt,title = "dist")
dist

NA
INF
signature
hallmark_name = "HALLMARK_INTERFERON_GAMMA_RESPONSE"
genesets =getGmt("./Data/h.all.v7.0.symbols.pluscc.gmt")
geneIds= genesets[[hallmark_name]]@geneIds
hallmars_exp = FetchData(object = xeno,vars = c(geneIds))
Warning in FetchData.Seurat(object = xeno, vars = c(geneIds)) : The
following requested variables were not found: AC124319.1
hallmars_exp = hallmars_exp[,colSums(hallmars_exp[])>0] #remove no expression genes
hallmark_cor = cor(hallmars_exp)
pht1 = pheatmap(mat = hallmark_cor,silent = T)
num_of_clusters = 7
clustering_distance = "euclidean"
myannotation = as.data.frame(cutree(pht1[["tree_row"]], k = num_of_clusters)) #split into k clusters
names(myannotation)[1] = "cluster"
myannotation$cluster = as.factor(myannotation$cluster)
palette1 <-brewer.pal(num_of_clusters, "Paired")
names(palette1) = unique(myannotation$cluster)
ann_colors = list (cluster = palette1)
annotation = list(ann_colors = ann_colors, myannotation = myannotation)
colors <- c(seq(-1,1,by=0.01))
my_palette <- c("blue",colorRampPalette(colors = c("blue", "white", "red"))
(n = length(colors)-3), "red")
print_tab(plt =
pheatmap(mat = hallmark_cor,annotation_col = annotation[["myannotation"]], annotation_colors = annotation[["ann_colors"]], clustering_distance_rows = clustering_distance,clustering_distance_cols = clustering_distance,color = my_palette,breaks = colors,show_rownames = F,show_colnames = F)
,title = "genes expression heatmap")
genes expression heatmap

NA
chosen_genes = annotation[["myannotation"]] %>% dplyr::filter(cluster == 4 | cluster == 1 | cluster == 3) %>% rownames() #take relevant genes
var_features=lung@assays$RNA@var.features
geneIds= genesets[[hallmark_name]]@geneIds
score <- apply(lung@assays$RNA@data[intersect(geneIds,var_features),],2,mean)
lung=AddMetaData(lung,score,hallmark_name)
print_tab(FeaturePlot(object = lung, features = hallmark_name),title = "Expression")
Expression

NA
cc_scores = FetchData(object = lung,vars = hallmark_name)
plt = ggplot(cc_scores, aes(x=HALLMARK_INTERFERON_GAMMA_RESPONSE)) +
geom_density()+
geom_vline(
aes(xintercept=mean(HALLMARK_INTERFERON_GAMMA_RESPONSE) + sd(HALLMARK_INTERFERON_GAMMA_RESPONSE) ,color="1 SD"),
linetype="dashed", size=1)+
geom_vline(
aes(xintercept=mean(HALLMARK_INTERFERON_GAMMA_RESPONSE) + 2*sd(HALLMARK_INTERFERON_GAMMA_RESPONSE) ,color="2 SD"),
linetype="dashed", size=1)+
geom_vline(
aes(xintercept=mean(HALLMARK_INTERFERON_GAMMA_RESPONSE) ,color="mean"),
linetype="dashed", size=1)
print_tab(plt = plt,title = "dist")
dist

NA
Signature regulation
metagenes_mean_compare(dataset = lung, time.point_var = "time.point",prefix = "patient",patient.ident_var = "patient.ident",pre_on = c("pre-treatment","on-treatment"),axis.text.x = 8,programs = c("HALLMARK_HYPOXIA","HALLMARK_INTERFERON_GAMMA_RESPONSE","GO_MITOTIC_CC"))
HALLMARK_HYPOXIA per patient

HALLMARK_HYPOXIA

HALLMARK_INTERFERON_GAMMA_RESPONSE per
patient

HALLMARK_INTERFERON_GAMMA_RESPONSE

GO_MITOTIC_CC per patient

GO_MITOTIC_CC

NA
per patient fisher
test
patients_vector = lung$patient.ident %>% unique()
for (patient_name in patients_vector) {
df = FetchData(object = lung,vars = c("program.assignment","patient.ident","time.point")) %>%
filter (patient.ident == patient_name) %>%
filter (program.assignment %in% c("metagene.1","metagene.2")) %>%
filter (time.point %in% c("pre-treatment","on-treatment")) %>%
select(-patient.ident) %>%
droplevels()
test = fisher.test(table(df))
library(ggstatsplot)
print(
ggbarstats(
df, program.assignment, time.point,
results.subtitle = FALSE,
subtitle = paste0(
"Fisher's exact test", ", p-value = ",
ifelse(test$p.value < 0.001, "< 0.001", round(test$p.value, 3))
),title = patient_name
)
)
}
LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19kZXB0aDogMQotLS0KCgojIERhdGEKCmBgYHtyfQpsdW5nID0gcmVhZFJEUygiLi9EYXRhL2x1bmdfY2FuY2VyY2VsbHNfd2l0aFRQX29ubHlQYXRpZW50cy5yZHMiKQpsdW5nX3BhdGllbnRzID0gbHVuZyRwYXRpZW50LmlkZW50ICU+JSB1bmlxdWUoKSAlPiUgYXMuY2hhcmFjdGVyKCkKbHVuZ19wYXRpZW50c19maWx0ZXJlZCA9IGx1bmdfcGF0aWVudHNbIShsdW5nX3BhdGllbnRzICVpbiUgYygiWDEwNTVuZXciLCJYMTA5OSIpKV0gIyByZW1vdmUgcGF0aWVudHMgd2l0aCBsZXNzIHRoYW4gMTAwIG1hbGlnbmFudCBjZWxscwpsdW5nID0gc3Vic2V0KHggPSBsdW5nLHN1YnNldCA9IHBhdGllbnQuaWRlbnQgJWluJSBsdW5nX3BhdGllbnRzX2ZpbHRlcmVkKQpgYGAKCgpgYGB7cn0Kc3VmZml4ID0ieGVub19nZW5lc19ub3JtYWxpemVkXzAtNXNpZ21hXzItN3RoZXRhIgpgYGAKCgpgYGB7cHl0aG9ufQpmcm9tIGNubWYgaW1wb3J0IGNOTUYKc3VmZml4ID0gci5zdWZmaXgKaW1wb3J0IHBpY2tsZQpmID0gb3BlbignLi9EYXRhL2NubWYvY25tZl9vYmplY3RzL3BhdGllbnRzXycgKyBzdWZmaXggKyAnX2NubWZfb2JqLnBja2wnLCAncmInKQpjbm1mX29iaiA9IHBpY2tsZS5sb2FkKGYpCmYuY2xvc2UoKQpgYGAKCgojIEZ1bmN0aW9ucwoKYGBge3J9CmxpYnJhcnkoc3RyaW5naSkKbGlicmFyeShyZXRpY3VsYXRlKQpzb3VyY2VfZnJvbV9naXRodWIocmVwb3NpdG95ID0gIkRFR19mdW5jdGlvbnMiLHZlcnNpb24gPSAiMC4yLjI0IikKc291cmNlX2Zyb21fZ2l0aHViKHJlcG9zaXRveSA9ICJjTk1GX2Z1bmN0aW9ucyIsdmVyc2lvbiA9ICIwLjMuOSIsc2NyaXB0X25hbWUgPSAiY25tZl9mdW5jdGlvbl9IYXJtb255LlIiKSAKYGBgCgojIEsgc2VsZWN0aW9uIHBsb3QKYGBge3J9CnBsb3RfcGF0aCA9IHBhc3RlMCgiL3NjaS9sYWJzL3lvdGFtZC9sYWJfc2hhcmUvYXZpc2hhaS53aXplbC9SX3Byb2plY3RzL0VHRlIvRGF0YS9jbm1mL2NOTUZfcGF0aWVudHNfVmFybm9ybV9IYXJtb255XyIsc3VmZml4LCIvY05NRl9wYXRpZW50c19WYXJub3JtX0hhcm1vbnlfIixzdWZmaXgsIi5rX3NlbGVjdGlvbi5wbmciKQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhwbG90X3BhdGgpCmBgYAoKCgoKCgojIGdlcCBzY29yZXMgZm9yIGFsbCBOTUYgaydzCmBgYHtweXRob259CmRlbnNpdHlfdGhyZXNob2xkID0gMC4xCnVzYWdlX25vcm0sIGdlcF9zY29yZXMzLCBnZXBfdHBtLCB0b3BnZW5lcyA9IGNubWZfb2JqLmxvYWRfcmVzdWx0cyhLPTMsIGRlbnNpdHlfdGhyZXNob2xkPWRlbnNpdHlfdGhyZXNob2xkKQp1c2FnZV9ub3JtLCBnZXBfc2NvcmVzNCwgZ2VwX3RwbSwgdG9wZ2VuZXMgPSBjbm1mX29iai5sb2FkX3Jlc3VsdHMoSz00LCBkZW5zaXR5X3RocmVzaG9sZD1kZW5zaXR5X3RocmVzaG9sZCkKdXNhZ2Vfbm9ybSwgZ2VwX3Njb3JlczUsIGdlcF90cG0sIHRvcGdlbmVzID0gY25tZl9vYmoubG9hZF9yZXN1bHRzKEs9NSwgZGVuc2l0eV90aHJlc2hvbGQ9ZGVuc2l0eV90aHJlc2hvbGQpCnVzYWdlX25vcm0sIGdlcF9zY29yZXM2LCBnZXBfdHBtLCB0b3BnZW5lcyA9IGNubWZfb2JqLmxvYWRfcmVzdWx0cyhLPTYsIGRlbnNpdHlfdGhyZXNob2xkPWRlbnNpdHlfdGhyZXNob2xkKQp1c2FnZV9ub3JtLCBnZXBfc2NvcmVzNywgZ2VwX3RwbSwgdG9wZ2VuZXMgPSBjbm1mX29iai5sb2FkX3Jlc3VsdHMoSz03LCBkZW5zaXR5X3RocmVzaG9sZD1kZW5zaXR5X3RocmVzaG9sZCkKdXNhZ2Vfbm9ybSwgZ2VwX3Njb3JlczgsIGdlcF90cG0sIHRvcGdlbmVzID0gY25tZl9vYmoubG9hZF9yZXN1bHRzKEs9OCwgZGVuc2l0eV90aHJlc2hvbGQ9ZGVuc2l0eV90aHJlc2hvbGQpCnVzYWdlX25vcm0sIGdlcF9zY29yZXM5LCBnZXBfdHBtLCB0b3BnZW5lcyA9IGNubWZfb2JqLmxvYWRfcmVzdWx0cyhLPTksIGRlbnNpdHlfdGhyZXNob2xkPWRlbnNpdHlfdGhyZXNob2xkKQoKYGBgCgoKIyBFbnJpY2htZW50IGFuYWx5c2lzIGJ5IHRvcCAyMDAgZ2VuZXMgb2YgZWFjaCBwcm9ncmFtIHsudGFic2V0fQpgYGB7ciBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD04LCByZXN1bHRzPSdhc2lzJ30KZ2VwX3Njb3JlczMgPSBweSRnZXBfc2NvcmVzMwpnZXBfc2NvcmVzNCA9IHB5JGdlcF9zY29yZXM0CmdlcF9zY29yZXM1ID0gcHkkZ2VwX3Njb3JlczUKZ2VwX3Njb3JlczYgPSBweSRnZXBfc2NvcmVzNgpnZXBfc2NvcmVzNyA9IHB5JGdlcF9zY29yZXM3CmdlcF9zY29yZXM4ID0gcHkkZ2VwX3Njb3JlczgKZ2VwX3Njb3JlczkgPSBweSRnZXBfc2NvcmVzOQoKYWxsX2dlcF9zY29yZXMgPSAgbGlzdChnZXBfc2NvcmVzMyA9IGdlcF9zY29yZXMzLCBnZXBfc2NvcmVzNCA9IGdlcF9zY29yZXM0LCBnZXBfc2NvcmVzNSA9IGdlcF9zY29yZXM1LCBnZXBfc2NvcmVzNiA9IGdlcF9zY29yZXM2LCBnZXBfc2NvcmVzNz0gZ2VwX3Njb3JlczcsIGdlcF9zY29yZXM4ID0gZ2VwX3Njb3JlczgsIGdlcF9zY29yZXM5ID0gZ2VwX3Njb3JlczkpCiMgY2Fub25pY2FsX3BhdGh3YXlzID0gbXNpZ2RicihzcGVjaWVzID0gIkhvbW8gc2FwaWVucyIsIGNhdGVnb3J5ID0gIkMyIikgJT4lIGRwbHlyOjpmaWx0ZXIoZ3Nfc3ViY2F0ICE9ICJDR1AiKSAlPiUgIGRwbHlyOjpkaXN0aW5jdChnc19uYW1lLCBnZW5lX3N5bWJvbCkgCmZvciAoZ2VwX25hbWUgaW4gbmFtZXMoYWxsX2dlcF9zY29yZXMpKSB7CiAgZ2VwX3Njb3JlcyA9IGFsbF9nZXBfc2NvcmVzW1tnZXBfbmFtZV1dCiAgdG9wX2dlbmVzX251bSA9IDIwMAogIHBsdF9saXN0ID0gbGlzdCgpCiAgZm9yIChpIGluIDE6bmNvbChnZXBfc2NvcmVzKSkgewogICAgdG9wX2dlbmVzID0gZ2VwX3Njb3JlcyAgJT4lICBhcnJhbmdlKGRlc2MoZ2VwX3Njb3Jlc1tpXSkpICNzb3J0IGJ5IHNjb3JlIGEKICAgIHRvcCA9IGhlYWQocm93bmFtZXModG9wX2dlbmVzKSx0b3BfZ2VuZXNfbnVtKSAjdGFrZSB0b3AgdG9wX2dlbmVzX251bQogICAgcmVzID0gZ2VuZXNfdmVjX2VucmljaG1lbnQoZ2VuZXMgPSB0b3AsYmFja2dyb3VuZCA9IHJvd25hbWVzKGdlcF9zY29yZXMpLGhvbWVyID0gVCx0aXRsZSA9IAogICAgICAgICAgICAgICAgICAgICAgbmFtZXMoZ2VwX3Njb3JlcylbaV0sc2lsZW50ID0gVCxyZXR1cm5fYWxsID0gVCxjdXN0b21fcGF0aHdheXMgPSBOVUxMICkKICAgICAKICAgIHBsdF9saXN0W1tpXV0gPSByZXMkcGx0CiAgfQogIHByaW50X3RhYihwbHQgPSAgIGdnYXJyYW5nZShwbG90bGlzdCA9IHBsdF9saXN0KSwKICAgICAgICAgICAgdGl0bGUgPSBnZXBfbmFtZSkKfQpgYGAKCiMgQ2hvc2VuIEsKYGBge3B5dGhvbn0Kc2VsZWN0ZWRfayA9IDgKcHJpbnQoInNlbGVjdGVkIGsgPSAiLHNlbGVjdGVkX2spCmRlbnNpdHlfdGhyZXNob2xkID0gMC4xCmNubWZfb2JqLmNvbnNlbnN1cyhrPXNlbGVjdGVkX2ssIGRlbnNpdHlfdGhyZXNob2xkPWRlbnNpdHlfdGhyZXNob2xkLHNob3dfY2x1c3RlcmluZz1UcnVlKQp1c2FnZV9ub3JtLCBnZXBfc2NvcmVzLCBnZXBfdHBtLCB0b3BnZW5lcyA9IGNubWZfb2JqLmxvYWRfcmVzdWx0cyhLPXNlbGVjdGVkX2ssIGRlbnNpdHlfdGhyZXNob2xkPWRlbnNpdHlfdGhyZXNob2xkKQpgYGAKCgpgYGB7ciBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD04LCByZXN1bHRzPSdoaWRlJ30KZ2VwX3Njb3JlcyA9IHB5JGdlcF9zY29yZXMKCiMgY2Fub25pY2FsX3BhdGh3YXlzID0gbXNpZ2RicihzcGVjaWVzID0gIkhvbW8gc2FwaWVucyIsIGNhdGVnb3J5ID0gIkMyIikgJT4lIGRwbHlyOjpmaWx0ZXIoZ3Nfc3ViY2F0ICE9ICJDR1AiKSAlPiUgIGRwbHlyOjpkaXN0aW5jdChnc19uYW1lLCBnZW5lX3N5bWJvbCkgCgp0b3BfZ2VuZXNfbnVtID0gMjAwCnBsdF9saXN0ID0gbGlzdCgpCmZvciAoaSBpbiAxOm5jb2woZ2VwX3Njb3JlcykpIHsKICB0b3BfZ2VuZXMgPSBnZXBfc2NvcmVzICAlPiUgIGFycmFuZ2UoZGVzYyhnZXBfc2NvcmVzW2ldKSkgI3NvcnQgYnkgc2NvcmUgYQogIHRvcCA9IGhlYWQocm93bmFtZXModG9wX2dlbmVzKSx0b3BfZ2VuZXNfbnVtKSAjdGFrZSB0b3AgdG9wX2dlbmVzX251bQogIHJlcyA9IGdlbmVzX3ZlY19lbnJpY2htZW50KGdlbmVzID0gdG9wLGJhY2tncm91bmQgPSByb3duYW1lcyhnZXBfc2NvcmVzKSxob21lciA9IFQsdGl0bGUgPSAKICAgICAgICAgICAgICAgICAgICBuYW1lcyhnZXBfc2NvcmVzKVtpXSxzaWxlbnQgPSBULHJldHVybl9hbGwgPSBULGN1c3RvbV9wYXRod2F5cyA9IE5VTEwgKQogICAKICBwbHRfbGlzdFtbaV1dID0gcmVzJHBsdAp9CmdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKGdyb2JzID0gcGx0X2xpc3QpCmBgYAoKIyBDb3JyZWxhdGlvbiBvZiBwcm9ncmFtcwoKYGBge3J9CmdlcF9zY29yZXMgPSBweSRnZXBfc2NvcmVzCmNvcl9yZXMgPSBjb3IoZ2VwX3Njb3JlcykKYnJlYWtzIDwtIGMoc2VxKC0xLDEsYnk9MC4wMSkpCmNvbG9yc19mb3JfcGxvdCA8LSBjb2xvclJhbXBQYWxldHRlKGNvbG9ycyA9IGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpKG4gPSBsZW5ndGgoYnJlYWtzKSkKCnBoZWF0bWFwKGNvcl9yZXMsY29sb3IgPSBjb2xvcnNfZm9yX3Bsb3QsYnJlYWtzID0gYnJlYWtzKQpgYGAKIyBjb3JyZWxhdGlvbiBieSB0b3AgMTUwIGNvbWJpbmVkCmBgYHtyfQphbGxfdG9wPSBjKCkKZm9yIChpIGluIDE6bmNvbChnZXBfc2NvcmVzKSkgewogIHRvcF9nZW5lcyA9IGdlcF9zY29yZXMgICU+JSAgYXJyYW5nZShkZXNjKGdlcF9zY29yZXNbaV0pKSAjc29ydCBieSBzY29yZSBhCiAgdG9wID0gaGVhZChyb3duYW1lcyh0b3BfZ2VuZXMpLDIwMCkgI3Rha2UgdG9wIHRvcF9nZW5lc19udW0KYWxsX3RvcCA9IGMoYWxsX3RvcCx0b3ApCn0KZ2VwX3Njb3Jlc190b3AgPSBnZXBfc2NvcmVzW2FsbF90b3AsXQpjb3JfcmVzID0gY29yKGdlcF9zY29yZXNfdG9wKQoKYnJlYWtzIDwtIGMoc2VxKC0xLDEsYnk9MC4wMSkpCmNvbG9yc19mb3JfcGxvdCA8LSBjb2xvclJhbXBQYWxldHRlKGNvbG9ycyA9IGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpKG4gPSBsZW5ndGgoYnJlYWtzKSkKCnBoZWF0bWFwKGNvcl9yZXMsY29sb3IgPSBjb2xvcnNfZm9yX3Bsb3QsYnJlYWtzID0gYnJlYWtzKQpgYGAKCiMgQ29tYmluZSBzaW1pbGFyIHByb2dyYW1zCmBgYHtyfQpnZXBfc2NvcmVzID0gcHkkZ2VwX3Njb3JlcwojIGdyb3Vwc19saXN0ID0gYyg0LDUsMykKIyBncm91cHNfbGlzdCA9IGMoNCw1LDYpCiMgZ3JvdXBzX2xpc3QgPSBjKDQsNSw3KQpncm91cHNfbGlzdCA9IGMoNCwzLDYpCgpnZXBfc2NvcmVzID0gdW5pb25fcHJvZ3JhbXMoZ3JvdXBzX2xpc3QgPSBncm91cHNfbGlzdCxhbGxfbWV0YWdlbmVzID0gZ2VwX3Njb3JlcykKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD04LCByZXN1bHRzPSdoaWRlJ30KdG9wX2dlbmVzX251bSA9IDIwMApwbHRfbGlzdCA9IGxpc3QoKQpmb3IgKGkgaW4gMTpuY29sKGdlcF9zY29yZXMpKSB7CiAgdG9wX2dlbmVzID0gZ2VwX3Njb3JlcyAgJT4lICBhcnJhbmdlKGRlc2MoZ2VwX3Njb3Jlc1tpXSkpICNzb3J0IGJ5IHNjb3JlIGEKICB0b3AgPSBoZWFkKHJvd25hbWVzKHRvcF9nZW5lcyksdG9wX2dlbmVzX251bSkgI3Rha2UgdG9wIHRvcF9nZW5lc19udW0KICByZXMgPSBnZW5lc192ZWNfZW5yaWNobWVudChnZW5lcyA9IHRvcCxiYWNrZ3JvdW5kID0gcm93bmFtZXMoZ2VwX3Njb3JlcyksaG9tZXIgPSBULHRpdGxlID0gCiAgICAgICAgICAgICAgICAgICAgIG5hbWVzKGdlcF9zY29yZXMpW2ldLHNpbGVudCA9IFQscmV0dXJuX2FsbCA9IFQpCiAgIAogIHBsdF9saXN0W1tpXV0gPSByZXMkcGx0Cn0KZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UoZ3JvYnMgPSBwbHRfbGlzdCkKYGBgCgojIENhbGN1bGF0ZSB1c2FnZQpgYGB7ciBlY2hvPVRSVUUsIHJlc3VsdHM9J2FzaXMnfQojIGdldCBleHByZXNzaW9uIHdpdGggZ2VuZXMgaW4gY25tZiBpbnB1dApsdW5nID0gRmluZFZhcmlhYmxlRmVhdHVyZXMob2JqZWN0ID0gbHVuZyxuZmVhdHVyZXMgPSAyMDAwKQpnZW5lcyA9IHJvd25hbWVzKGx1bmcpW3Jvd25hbWVzKGx1bmcpICVpbiUgVmFyaWFibGVGZWF0dXJlcyhvYmplY3QgPSB4ZW5vKVsxOjIwMDBdXQoKbHVuZ19leHByZXNzaW9uID0gdChhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKGx1bmcsc2xvdD0nZGF0YScpKSkgCmx1bmdfZXhwcmVzc2lvbiA9IDIqKmx1bmdfZXhwcmVzc2lvbiAjY29udmVydCBmcm9tIGxvZzIodHBtKzEpIHRvIHRwbQpsdW5nX2V4cHJlc3Npb24gPSBsdW5nX2V4cHJlc3Npb24tMQpsdW5nX2V4cHJlc3Npb24gPSBsdW5nX2V4cHJlc3Npb25bLGdlbmVzXSAlPiUgYXMuZGF0YS5mcmFtZSgpCgphbGxfMF9nZW5lcyA9IGNvbG5hbWVzKGx1bmdfZXhwcmVzc2lvbilbY29sU3VtcyhsdW5nX2V4cHJlc3Npb249PTAsIG5hLnJtPVRSVUUpPT1ucm93KGx1bmdfZXhwcmVzc2lvbildICNkZWxldGUgcm93cyB0aGF0IGhhdmUgYWxsIDAKZ2VuZXMgPSBnZW5lc1shZ2VuZXMgJWluJSBhbGxfMF9nZW5lc10KbHVuZ19leHByZXNzaW9uID0gbHVuZ19leHByZXNzaW9uWywhY29sbmFtZXMobHVuZ19leHByZXNzaW9uKSAlaW4lIGFsbF8wX2dlbmVzXQpnYyh2ZXJib3NlID0gRikKYGBgCgoKCgpgYGB7cHl0aG9ufQoKbHVuZ19leHByZXNzaW9uID0gci5sdW5nX2V4cHJlc3Npb24KZ2VuZXMgPSByLmdlbmVzCmdlcF9zY29yZXMgPSByLmdlcF9zY29yZXMKdXNhZ2VfYnlfY2FsYyA9IGdldF91c2FnZV9mcm9tX3Njb3JlKGNvdW50cz1sdW5nX2V4cHJlc3Npb24sdHBtPWx1bmdfZXhwcmVzc2lvbixnZW5lcz1nZW5lcyxjbm1mX29iaj1jbm1mX29iaixrPXNlbGVjdGVkX2ssc3VtVG8xPUZhbHNlKQpgYGAKCgpgYGB7cn0KdXNhZ2VfYnlfY2FsYyA9IHB5JHVzYWdlX2J5X2NhbGMKZ3JvdXBzX2xpc3QgPSBjKDQsMyw2KQp1c2FnZV9ieV9jYWxjID0gdW5pb25fcHJvZ3JhbXMoZ3JvdXBzX2xpc3QgPSBncm91cHNfbGlzdCxhbGxfbWV0YWdlbmVzID0gdXNhZ2VfYnlfY2FsYykKdXNhZ2VfYnlfY2FsYyA9IGFwcGx5KHVzYWdlX2J5X2NhbGMsIE1BUkdJTiA9IDEsIHN1bV8yX29uZSkgJT4lIHQoKSAlPiUgYXMuZGF0YS5mcmFtZSgpCnVzYWdlX2J5X2NhbGMgPXVzYWdlX2J5X2NhbGMgJT4lIHJlbmFtZShjZWxsX2N5Y2xlID0gZ2VwNC4zLjYsIGh5cG94aWFfbGlrZSA9IGdlcDIsIGludGVyZmVyb25fbGlrZSA9IGdlcDEsIFRORmEgPSAgZ2VwNSwgSU5GMiA9IGdlcDcpCmBgYAoKCgojIFVzZ2FnZSBVTUFQCmBgYHtyIGZpZy5oZWlnaHQ9OSwgZmlnLndpZHRoPTEzfQphbGxfbWV0YWdlbmVzPSB1c2FnZV9ieV9jYWxjCgojYWRkIGVhY2ggbWV0YWdlbmUgdG8gbWV0YWRhdGEKZm9yIChpIGluIDE6bmNvbChhbGxfbWV0YWdlbmVzKSkgewogIG1ldGFnZV9tZXRhZGF0YSA9IGFsbF9tZXRhZ2VuZXMgJT4lIGRwbHlyOjpzZWxlY3QoaSkKICBsdW5nID0gQWRkTWV0YURhdGEob2JqZWN0ID0gbHVuZyxtZXRhZGF0YSA9IG1ldGFnZV9tZXRhZGF0YSkKfQpGZWF0dXJlUGxvdChvYmplY3QgPSBsdW5nLGZlYXR1cmVzID0gY29sbmFtZXMoYWxsX21ldGFnZW5lcyksbmNvbCA9IDMpCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTEwfQpEaW1QbG90KG9iamVjdCA9IGx1bmcsZ3JvdXAuYnkgPSAidGltZS5wb2ludCIscHQuc2l6ZSA9IDAuNSkKcHJlX3RyZWF0bWVudF9jZWxscyA9IEZldGNoRGF0YShvYmplY3QgPSBsdW5nLHZhcnMgPSAidGltZS5wb2ludCIpICU+JSBmaWx0ZXIodGltZS5wb2ludCA9PSAicHJlLXRyZWF0bWVudCIpICU+JSByb3duYW1lcygpCm9uX3RyZWF0bWVudF9jZWxscyA9IEZldGNoRGF0YShvYmplY3QgPSBsdW5nLHZhcnMgPSAidGltZS5wb2ludCIpICU+JSBmaWx0ZXIodGltZS5wb2ludCA9PSAib24tdHJlYXRtZW50IikgJT4lIHJvd25hbWVzKCkKCmNlbGxzX3RvX2hpZ2hsaWdodCA9ICBsaXN0KHByZV90cmVhdG1lbnRfY2VsbHMgPSBwcmVfdHJlYXRtZW50X2NlbGxzKQpEaW1QbG90KG9iamVjdCA9IGx1bmcsIGNlbGxzLmhpZ2hsaWdodCA9IGNlbGxzX3RvX2hpZ2hsaWdodCwgY29scy5oaWdobGlnaHQgPSBjKCJyZWQiKSwgY29scyA9ICJncmF5Iiwgb3JkZXIgPSBUUlVFLCBsYWJlbCA9IFQsIHJlcGVsID0gVCkKCmNlbGxzX3RvX2hpZ2hsaWdodCA9ICBsaXN0KG9uX3RyZWF0bWVudF9jZWxscyA9IG9uX3RyZWF0bWVudF9jZWxscykKRGltUGxvdChvYmplY3QgPSBsdW5nLCBjZWxscy5oaWdobGlnaHQgPSBjZWxsc190b19oaWdobGlnaHQsIGNvbHMuaGlnaGxpZ2h0ID0gYygiY3lhbjMiKSwgY29scyA9ICJncmF5Iiwgb3JkZXIgPSBUUlVFLCAgbGFiZWwgPSBULCByZXBlbCA9IFQpCgpgYGAKCgoKYGBge3IgZmlnLndpZHRoPTl9CkRvdFBsb3Qob2JqZWN0ID0gbHVuZywgZmVhdHVyZXMgPSBjKCJoeXBveGlhX2xpa2UiLCJpbnRlcmZlcm9uX2xpa2UiLCJjZWxsX2N5Y2xlIiwiVE5GYSIsICJJTkYyIiksc2NhbGUgPSBULGdyb3VwLmJ5ICA9ICd0aW1lLnBvaW50JykKYGBgCgojIEFzc2lnbm1lbnQgCmBgYHtyfQpsYXJnZXJfYnkgPSAxLjI1Cmx1bmcgPSBwcm9ncmFtX2Fzc2lnbm1lbnQoZGF0YXNldCA9IGx1bmcsbGFyZ2VyX2J5ID0gbGFyZ2VyX2J5LHByb2dyYW1fbmFtZXMgPSBjb2xuYW1lcyhhbGxfbWV0YWdlbmVzKSkKYGBgCgoKCgpgYGB7ciBlY2hvPVRSVUUsIGZpZy53aWR0aD0xMCwgcmVzdWx0cz0nYXNpcyd9CnAgPSBjZWxsX3BlcmNlbnRhZ2UoZGF0YXNldCA9IGx1bmcsdGltZS5wb2ludF92YXIgPSAidGltZS5wb2ludCIsYnlfcHJvZ3JhbSA9IFQpCnByaW50X3RhYihwbHQgPSBwLHRpdGxlID0gImJ5IHByb2dyYW0iKQpwID0gY2VsbF9wZXJjZW50YWdlKGRhdGFzZXQgPSBsdW5nLHRpbWUucG9pbnRfdmFyID0gInRpbWUucG9pbnQiLGJ5X3RwID0gVCx4X29yZGVyID0gTlVMTCkKcHJpbnRfdGFiKHBsdCA9IHAsdGl0bGUgPSAiYnkgdGltZXBvaW50IikKCmBgYAoKIyMgcHJvZ3JhbS5hc3NpZ25tZW50CmBgYHtyIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEwfQojIGNvbG9ycyA9ICByYWluYm93KG5jb2woYWxsX21ldGFnZW5lcykpCiMgZmMgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJsaWdodGdyZWVuIiwgImRhcmtncmVlbiIpKQojIGdyZWVucyA9IGZjKDQpCiMgY29sb3JzWzFdID0gImJsdWUiCiMgY29sb3JzWzI6M10gPSBncmVlbnNbMToyXQojIGNvbG9yc1s0XSA9ICJyZWQiCiMgY29sb3JzWzU6Nl0gPSBncmVlbnNbMzo0XQojIGNvbG9ycyA9IGMoY29sb3JzLCJncmV5IikKIyBEaW1QbG90KGx1bmcsZ3JvdXAuYnkgPSAicHJvZ3JhbS5hc3NpZ25tZW50IixwdC5zaXplID0gMC41LGNvbHMgPWNvbG9ycykKCgojIGNvbG9ycyA9ICByYWluYm93KG5jb2woYWxsX21ldGFnZW5lcykpCiMgY29sb3JzID0gYyhjb2xvcnMsImdyZXkiKQojIERpbVBsb3QobHVuZyxncm91cC5ieSA9ICJwcm9ncmFtLmFzc2lnbm1lbnQiLHB0LnNpemUgPSAwLjUsY29scyA9Y29sb3JzKQoKRGltUGxvdChsdW5nLGdyb3VwLmJ5ID0gInByb2dyYW0uYXNzaWdubWVudCIscHQuc2l6ZSA9IDAuNSkKRGltUGxvdChsdW5nLGdyb3VwLmJ5ID0gInBhdGllbnQuaWRlbnQiLHB0LnNpemUgPSAwLjUpCkRpbVBsb3QobHVuZyxncm91cC5ieSA9ICJ0aW1lLnBvaW50IixwdC5zaXplID0gMC41KQpgYGAKCgojIFNjb3JlIHJlZ3VsYXRpb24gey50YWJzZXR9CgpgYGB7ciBlY2hvPVRSVUUsIHJlc3VsdHM9J2FzaXMnfQptZXRhZ2VuZXNfbWVhbl9jb21wYXJlKGRhdGFzZXQgPSBsdW5nLCB0aW1lLnBvaW50X3ZhciA9ICJ0aW1lLnBvaW50IixwcmVmaXggPSAicGF0aWVudCIscGF0aWVudC5pZGVudF92YXIgPSAicGF0aWVudC5pZGVudCIscHJlX29uID0gYygicHJlLXRyZWF0bWVudCIsIm9uLXRyZWF0bWVudCIpLGF4aXMudGV4dC54ID0gOCxwcm9ncmFtcyA9IGMoImh5cG94aWFfbGlrZSIsImludGVyZmVyb25fbGlrZSIsImNlbGxfY3ljbGUiKSkKYGBgCgoKCiMgQ0Mgc2lnbmF0dXJlICB7LnRhYnNldH0KCgoKYGBge3IgcmVzdWx0cz0nYXNpcyd9CmhhbGxtYXJrX25hbWUgPSAiSEFMTE1BUktfRzJNX0NIRUNLUE9JTlQiCmdlbmVzZXRzICA9Z2V0R210KCIuL0RhdGEvaC5hbGwudjcuMC5zeW1ib2xzLnBsdXNjYy5nbXQiKQpnZW5lSWRzPSBnZW5lc2V0c1tbaGFsbG1hcmtfbmFtZV1dQGdlbmVJZHMKaGFsbG1hcnNfZXhwID0gRmV0Y2hEYXRhKG9iamVjdCA9IHhlbm8sdmFycyA9IGMoZ2VuZUlkcykpCmhhbGxtYXJzX2V4cCA9IGhhbGxtYXJzX2V4cFssY29sU3VtcyhoYWxsbWFyc19leHBbXSk+MF0gI3JlbW92ZSBubyBleHByZXNzaW9uIGdlbmVzCmhhbGxtYXJrX2NvciA9IGNvcihoYWxsbWFyc19leHApCnBodDEgPSBwaGVhdG1hcChtYXQgPSBoYWxsbWFya19jb3Isc2lsZW50ID0gVCkKYGBgCgpgYGB7ciBlY2hvPVRSVUUsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTEwLCByZXN1bHRzPSdhc2lzJ30KbnVtX29mX2NsdXN0ZXJzID0gNApjbHVzdGVyaW5nX2Rpc3RhbmNlID0gImV1Y2xpZGVhbiIKbXlhbm5vdGF0aW9uID0gYXMuZGF0YS5mcmFtZShjdXRyZWUocGh0MVtbInRyZWVfcm93Il1dLCBrID0gbnVtX29mX2NsdXN0ZXJzKSkgI3NwbGl0IGludG8gayBjbHVzdGVycwogCm5hbWVzKG15YW5ub3RhdGlvbilbMV0gPSAiY2x1c3RlciIKICBteWFubm90YXRpb24kY2x1c3RlciA9IGFzLmZhY3RvcihteWFubm90YXRpb24kY2x1c3RlcikKICAKICBwYWxldHRlMSA8LWJyZXdlci5wYWwobnVtX29mX2NsdXN0ZXJzLCAiUGFpcmVkIikKCiAgbmFtZXMocGFsZXR0ZTEpID0gdW5pcXVlKG15YW5ub3RhdGlvbiRjbHVzdGVyKQogIGFubl9jb2xvcnMgPSBsaXN0IChjbHVzdGVyID0gcGFsZXR0ZTEpCiAgYW5ub3RhdGlvbiA9IGxpc3QoYW5uX2NvbG9ycyA9IGFubl9jb2xvcnMsIG15YW5ub3RhdGlvbiA9IG15YW5ub3RhdGlvbikKICAKICBjb2xvcnMgPC0gYyhzZXEoLTEsMSxieT0wLjAxKSkKICBteV9wYWxldHRlIDwtIGMoImJsdWUiLGNvbG9yUmFtcFBhbGV0dGUoY29sb3JzID0gYygiYmx1ZSIsICJ3aGl0ZSIsICJyZWQiKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKG4gPSBsZW5ndGgoY29sb3JzKS0zKSwgInJlZCIpCgoKICBwcmludF90YWIocGx0ID0gCiAgICAgICAgICAgICAgICBwaGVhdG1hcChtYXQgPSBoYWxsbWFya19jb3IsYW5ub3RhdGlvbl9jb2wgPSAgYW5ub3RhdGlvbltbIm15YW5ub3RhdGlvbiJdXSwgYW5ub3RhdGlvbl9jb2xvcnMgPSBhbm5vdGF0aW9uW1siYW5uX2NvbG9ycyJdXSwgY2x1c3RlcmluZ19kaXN0YW5jZV9yb3dzID0gY2x1c3RlcmluZ19kaXN0YW5jZSxjbHVzdGVyaW5nX2Rpc3RhbmNlX2NvbHMgPSBjbHVzdGVyaW5nX2Rpc3RhbmNlLGNvbG9yID0gbXlfcGFsZXR0ZSxicmVha3MgPSBjb2xvcnMsc2hvd19yb3duYW1lcyA9IEYsc2hvd19jb2xuYW1lcyA9IEYpCiAgICAgICAgICAgICx0aXRsZSA9ICJnZW5lcyBleHByZXNzaW9uIGhlYXRtYXAiKQpgYGAKCmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcyd9CmNob3Nlbl9nZW5lcyA9IGFubm90YXRpb25bWyJteWFubm90YXRpb24iXV0gJT4lIGRwbHlyOjpmaWx0ZXIoY2x1c3RlciA9PSAxIHwgY2x1c3RlciA9PSAyKSAlPiUgcm93bmFtZXMoKSAjdGFrZSByZWxldmFudCBnZW5lcwp2YXJfZmVhdHVyZXM9bHVuZ0Bhc3NheXMkUk5BQHZhci5mZWF0dXJlcwpnZW5lSWRzPSBnZW5lc2V0c1tbaGFsbG1hcmtfbmFtZV1dQGdlbmVJZHMKc2NvcmUgPC0gYXBwbHkobHVuZ0Bhc3NheXMkUk5BQGRhdGFbaW50ZXJzZWN0KGdlbmVJZHMsdmFyX2ZlYXR1cmVzKSxdLDIsbWVhbikKbHVuZz1BZGRNZXRhRGF0YShsdW5nLHNjb3JlLGhhbGxtYXJrX25hbWUpCgpwcmludF90YWIoRmVhdHVyZVBsb3Qob2JqZWN0ID0gbHVuZywgZmVhdHVyZXMgPSBoYWxsbWFya19uYW1lKSx0aXRsZSA9ICJFeHByZXNzaW9uIikKYGBgCgoKYGBge3IgZWNobz1UUlVFLCByZXN1bHRzPSdhc2lzJ30KY2Nfc2NvcmVzID0gRmV0Y2hEYXRhKG9iamVjdCA9IGx1bmcsdmFycyA9ICJIQUxMTUFSS19HMk1fQ0hFQ0tQT0lOVCIpCgpwbHQgID0gIGdncGxvdChjY19zY29yZXMsIGFlcyh4PUhBTExNQVJLX0cyTV9DSEVDS1BPSU5UKSkgKwogIGdlb21fZGVuc2l0eSgpKwogICBnZW9tX3ZsaW5lKAogICAgYWVzKHhpbnRlcmNlcHQ9bWVhbihjY19zY29yZXMkSEFMTE1BUktfRzJNX0NIRUNLUE9JTlQpICsgc2QoY2Nfc2NvcmVzJEhBTExNQVJLX0cyTV9DSEVDS1BPSU5UKSAsY29sb3I9IjEgU0QiKSwKICAgICAgICAgIGxpbmV0eXBlPSJkYXNoZWQiLCBzaXplPTEpKwogICAgZ2VvbV92bGluZSgKICAgIGFlcyh4aW50ZXJjZXB0PW1lYW4oY2Nfc2NvcmVzJEhBTExNQVJLX0cyTV9DSEVDS1BPSU5UKSArIDIqc2QoY2Nfc2NvcmVzJEhBTExNQVJLX0cyTV9DSEVDS1BPSU5UKSAsY29sb3I9IjIgU0QiKSwKICAgICAgICAgIGxpbmV0eXBlPSJkYXNoZWQiLCBzaXplPTEpCgpwcmludF90YWIocGx0ID0gcGx0LHRpdGxlID0gImRpc3QiKQpgYGAKCgpgYGB7ciBlY2hvPVRSVUUsIHJlc3VsdHM9J2FzaXMnfQpjY19zY29yZXMgPSBjY19zY29yZXMgJT4lIG11dGF0ZShpc19jeWNsaW5nID0gaWZfZWxzZShjb25kaXRpb24gPSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSEFMTE1BUktfRzJNX0NIRUNLUE9JTlQgPiBtZWFuKEhBTExNQVJLX0cyTV9DSEVDS1BPSU5UKSArIHNkKEhBTExNQVJLX0cyTV9DSEVDS1BPSU5UKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUgPSAiY3ljbGluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWxzZSA9ICJub25fY3ljbGluZyIpKQpsdW5nID0gQWRkTWV0YURhdGEob2JqZWN0ID0gbHVuZyxtZXRhZGF0YSA9IGNjX3Njb3JlcyRpc19jeWNsaW5nLGNvbC5uYW1lID0gImlzX2N5Y2xpbmciKQpwcmludF90YWIocGx0ID0gRGltUGxvdChvYmplY3QgPSBsdW5nLGdyb3VwLmJ5ID0gImlzX2N5Y2xpbmciKSAsIHRpdGxlID0gImFzc2lnbm1lbnQgMSBzZCIpCgoKY2Nfc2NvcmVzID0gY2Nfc2NvcmVzICU+JSBtdXRhdGUoaXNfY3ljbGluZyA9IGlmX2Vsc2UoY29uZGl0aW9uID0gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEhBTExNQVJLX0cyTV9DSEVDS1BPSU5UID4gbWVhbihIQUxMTUFSS19HMk1fQ0hFQ0tQT0lOVCkgKyAyKnNkKGNjX3Njb3JlcyRIQUxMTUFSS19HMk1fQ0hFQ0tQT0lOVCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnVlID0gImN5Y2xpbmciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFsc2UgPSAibm9uX2N5Y2xpbmciKSkKbHVuZyA9IEFkZE1ldGFEYXRhKG9iamVjdCA9IGx1bmcsbWV0YWRhdGEgPSBjY19zY29yZXMkaXNfY3ljbGluZyxjb2wubmFtZSA9ICJpc19jeWNsaW5nIikKcHJpbnRfdGFiKHBsdCA9IERpbVBsb3Qob2JqZWN0ID0gbHVuZyxncm91cC5ieSA9ICJpc19jeWNsaW5nIikgLCB0aXRsZSA9ICJhc3NpZ25tZW50IDIgc2QiKQoKCmBgYAoKCgpgYGB7ciBlY2hvPVRSVUUsIHJlc3VsdHM9J2FzaXMnfQogZGYgID0gRmV0Y2hEYXRhKG9iamVjdCA9IGx1bmcsdmFycyA9IGMoImlzX2N5Y2xpbmciLCJ0aW1lLnBvaW50IikpICU+JSAKICAgIGZpbHRlciAodGltZS5wb2ludCAlaW4lIGMoInByZS10cmVhdG1lbnQiLCJvbi10cmVhdG1lbnQiKSkgJT4lIAogICAgZHJvcGxldmVscygpIAogIHRlc3QgPSBmaXNoZXIudGVzdCh0YWJsZShkZikpCiAgICAKICBsaWJyYXJ5KGdnc3RhdHNwbG90KQoKICAgIHBsdCA9IGdnYmFyc3RhdHMoCiAgICBkZiwgaXNfY3ljbGluZywgdGltZS5wb2ludCwKICAgIHJlc3VsdHMuc3VidGl0bGUgPSBGQUxTRSwKICAgIHN1YnRpdGxlID0gcGFzdGUwKAogICAgICAiRmlzaGVyJ3MgZXhhY3QgdGVzdCIsICIsIHAtdmFsdWUgPSAiLAogICAgICAgcm91bmQodGVzdCRwLnZhbHVlLDEzKSkKICAgICkKICAKcHJpbnRfdGFiKHBsdCA9IHBsdCx0aXRsZSA9ICJmaXNoZXIiKQpgYGAKCgoKIyBIeXBveGlhIHNpZ25hdHVyZSAgey50YWJzZXR9CgpgYGB7ciByZXN1bHRzPSdhc2lzJ30KaGFsbG1hcmtfbmFtZSA9ICJIQUxMTUFSS19IWVBPWElBIgpnZW5lc2V0cyAgPWdldEdtdCgiLi9EYXRhL2guYWxsLnY3LjAuc3ltYm9scy5wbHVzY2MuZ210IikKZ2VuZUlkcz0gZ2VuZXNldHNbW2hhbGxtYXJrX25hbWVdXUBnZW5lSWRzCmhhbGxtYXJzX2V4cCA9IEZldGNoRGF0YShvYmplY3QgPSB4ZW5vLHZhcnMgPSBjKGdlbmVJZHMpKQpoYWxsbWFyc19leHAgPSBoYWxsbWFyc19leHBbLGNvbFN1bXMoaGFsbG1hcnNfZXhwW10pPjBdICNyZW1vdmUgbm8gZXhwcmVzc2lvbiBnZW5lcwpoYWxsbWFya19jb3IgPSBjb3IoaGFsbG1hcnNfZXhwKQpwaHQxID0gcGhlYXRtYXAobWF0ID0gaGFsbG1hcmtfY29yLHNpbGVudCA9IFQpCmBgYAoKYGBge3IgZWNobz1UUlVFLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD0xMCwgcmVzdWx0cz0nYXNpcyd9Cm51bV9vZl9jbHVzdGVycyA9IDQKY2x1c3RlcmluZ19kaXN0YW5jZSA9ICJldWNsaWRlYW4iCm15YW5ub3RhdGlvbiA9IGFzLmRhdGEuZnJhbWUoY3V0cmVlKHBodDFbWyJ0cmVlX3JvdyJdXSwgayA9IG51bV9vZl9jbHVzdGVycykpICNzcGxpdCBpbnRvIGsgY2x1c3RlcnMKIApuYW1lcyhteWFubm90YXRpb24pWzFdID0gImNsdXN0ZXIiCiAgbXlhbm5vdGF0aW9uJGNsdXN0ZXIgPSBhcy5mYWN0b3IobXlhbm5vdGF0aW9uJGNsdXN0ZXIpCiAgCiAgcGFsZXR0ZTEgPC1icmV3ZXIucGFsKG51bV9vZl9jbHVzdGVycywgIlBhaXJlZCIpCgogIG5hbWVzKHBhbGV0dGUxKSA9IHVuaXF1ZShteWFubm90YXRpb24kY2x1c3RlcikKICBhbm5fY29sb3JzID0gbGlzdCAoY2x1c3RlciA9IHBhbGV0dGUxKQogIGFubm90YXRpb24gPSBsaXN0KGFubl9jb2xvcnMgPSBhbm5fY29sb3JzLCBteWFubm90YXRpb24gPSBteWFubm90YXRpb24pCiAgCiAgY29sb3JzIDwtIGMoc2VxKC0xLDEsYnk9MC4wMSkpCiAgbXlfcGFsZXR0ZSA8LSBjKCJibHVlIixjb2xvclJhbXBQYWxldHRlKGNvbG9ycyA9IGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuID0gbGVuZ3RoKGNvbG9ycyktMyksICJyZWQiKQoKCiAgcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICAgICAgcGhlYXRtYXAobWF0ID0gaGFsbG1hcmtfY29yLGFubm90YXRpb25fY29sID0gIGFubm90YXRpb25bWyJteWFubm90YXRpb24iXV0sIGFubm90YXRpb25fY29sb3JzID0gYW5ub3RhdGlvbltbImFubl9jb2xvcnMiXV0sIGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9IGNsdXN0ZXJpbmdfZGlzdGFuY2UsY2x1c3RlcmluZ19kaXN0YW5jZV9jb2xzID0gY2x1c3RlcmluZ19kaXN0YW5jZSxjb2xvciA9IG15X3BhbGV0dGUsYnJlYWtzID0gY29sb3JzLHNob3dfcm93bmFtZXMgPSBGLHNob3dfY29sbmFtZXMgPSBGKQogICAgICAgICAgICAsdGl0bGUgPSAiZ2VuZXMgZXhwcmVzc2lvbiBoZWF0bWFwIikKYGBgCgpgYGB7ciBlY2hvPVRSVUUsIHJlc3VsdHM9J2FzaXMnfQpjaG9zZW5fZ2VuZXMgPSBhbm5vdGF0aW9uW1sibXlhbm5vdGF0aW9uIl1dICU+JSBkcGx5cjo6ZmlsdGVyKGNsdXN0ZXIgPT0gMSB8IGNsdXN0ZXIgPT0gMikgJT4lIHJvd25hbWVzKCkgI3Rha2UgcmVsZXZhbnQgZ2VuZXMKdmFyX2ZlYXR1cmVzPWx1bmdAYXNzYXlzJFJOQUB2YXIuZmVhdHVyZXMKZ2VuZUlkcz0gZ2VuZXNldHNbW2hhbGxtYXJrX25hbWVdXUBnZW5lSWRzCnNjb3JlIDwtIGFwcGx5KGx1bmdAYXNzYXlzJFJOQUBkYXRhW2ludGVyc2VjdChnZW5lSWRzLHZhcl9mZWF0dXJlcyksXSwyLG1lYW4pCmx1bmc9QWRkTWV0YURhdGEobHVuZyxzY29yZSxoYWxsbWFya19uYW1lKQoKcHJpbnRfdGFiKEZlYXR1cmVQbG90KG9iamVjdCA9IGx1bmcsIGZlYXR1cmVzID0gaGFsbG1hcmtfbmFtZSksdGl0bGUgPSAiRXhwcmVzc2lvbiIpCmBgYAoKCmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcyd9CmNjX3Njb3JlcyA9IEZldGNoRGF0YShvYmplY3QgPSBsdW5nLHZhcnMgPSBoYWxsbWFya19uYW1lKQoKcGx0ICA9ICBnZ3Bsb3QoY2Nfc2NvcmVzLCBhZXMoeD1IQUxMTUFSS19IWVBPWElBKSkgKwogIGdlb21fZGVuc2l0eSgpKwogICBnZW9tX3ZsaW5lKAogICAgYWVzKHhpbnRlcmNlcHQ9bWVhbihjY19zY29yZXMkSEFMTE1BUktfSFlQT1hJQSkgKyBzZChjY19zY29yZXMkSEFMTE1BUktfSFlQT1hJQSkgLGNvbG9yPSIxIFNEIiksCiAgICAgICAgICBsaW5ldHlwZT0iZGFzaGVkIiwgc2l6ZT0xKSsKICAgIGdlb21fdmxpbmUoCiAgICBhZXMoeGludGVyY2VwdD1tZWFuKGNjX3Njb3JlcyRIQUxMTUFSS19IWVBPWElBKSArIDIqc2QoY2Nfc2NvcmVzJEhBTExNQVJLX0hZUE9YSUEpICxjb2xvcj0iMiBTRCIpLAogICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIsIHNpemU9MSkKCnByaW50X3RhYihwbHQgPSBwbHQsdGl0bGUgPSAiZGlzdCIpCmBgYAoKCiMgZ2x5Y29seXNpcyBzaWduYXR1cmUgIHsudGFic2V0fQoKYGBge3IgcmVzdWx0cz0nYXNpcyd9CmhhbGxtYXJrX25hbWUgPSAiSEFMTE1BUktfR0xZQ09MWVNJUyIKZ2VuZXNldHMgID1nZXRHbXQoIi4vRGF0YS9oLmFsbC52Ny4wLnN5bWJvbHMucGx1c2NjLmdtdCIpCmdlbmVJZHM9IGdlbmVzZXRzW1toYWxsbWFya19uYW1lXV1AZ2VuZUlkcwpoYWxsbWFyc19leHAgPSBGZXRjaERhdGEob2JqZWN0ID0geGVubyx2YXJzID0gYyhnZW5lSWRzKSkKaGFsbG1hcnNfZXhwID0gaGFsbG1hcnNfZXhwWyxjb2xTdW1zKGhhbGxtYXJzX2V4cFtdKT4wXSAjcmVtb3ZlIG5vIGV4cHJlc3Npb24gZ2VuZXMKaGFsbG1hcmtfY29yID0gY29yKGhhbGxtYXJzX2V4cCkKcGh0MSA9IHBoZWF0bWFwKG1hdCA9IGhhbGxtYXJrX2NvcixzaWxlbnQgPSBUKQpgYGAKCmBgYHtyIGVjaG89VFJVRSwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9MTAsIHJlc3VsdHM9J2FzaXMnfQpudW1fb2ZfY2x1c3RlcnMgPSA1CmNsdXN0ZXJpbmdfZGlzdGFuY2UgPSAiZXVjbGlkZWFuIgpteWFubm90YXRpb24gPSBhcy5kYXRhLmZyYW1lKGN1dHJlZShwaHQxW1sidHJlZV9yb3ciXV0sIGsgPSBudW1fb2ZfY2x1c3RlcnMpKSAjc3BsaXQgaW50byBrIGNsdXN0ZXJzCiAKbmFtZXMobXlhbm5vdGF0aW9uKVsxXSA9ICJjbHVzdGVyIgogIG15YW5ub3RhdGlvbiRjbHVzdGVyID0gYXMuZmFjdG9yKG15YW5ub3RhdGlvbiRjbHVzdGVyKQogIAogIHBhbGV0dGUxIDwtYnJld2VyLnBhbChudW1fb2ZfY2x1c3RlcnMsICJQYWlyZWQiKQoKICBuYW1lcyhwYWxldHRlMSkgPSB1bmlxdWUobXlhbm5vdGF0aW9uJGNsdXN0ZXIpCiAgYW5uX2NvbG9ycyA9IGxpc3QgKGNsdXN0ZXIgPSBwYWxldHRlMSkKICBhbm5vdGF0aW9uID0gbGlzdChhbm5fY29sb3JzID0gYW5uX2NvbG9ycywgbXlhbm5vdGF0aW9uID0gbXlhbm5vdGF0aW9uKQogIAogIGNvbG9ycyA8LSBjKHNlcSgtMSwxLGJ5PTAuMDEpKQogIG15X3BhbGV0dGUgPC0gYygiYmx1ZSIsY29sb3JSYW1wUGFsZXR0ZShjb2xvcnMgPSBjKCJibHVlIiwgIndoaXRlIiwgInJlZCIpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAobiA9IGxlbmd0aChjb2xvcnMpLTMpLCAicmVkIikKCgogIHByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgICAgIHBoZWF0bWFwKG1hdCA9IGhhbGxtYXJrX2Nvcixhbm5vdGF0aW9uX2NvbCA9ICBhbm5vdGF0aW9uW1sibXlhbm5vdGF0aW9uIl1dLCBhbm5vdGF0aW9uX2NvbG9ycyA9IGFubm90YXRpb25bWyJhbm5fY29sb3JzIl1dLCBjbHVzdGVyaW5nX2Rpc3RhbmNlX3Jvd3MgPSBjbHVzdGVyaW5nX2Rpc3RhbmNlLGNsdXN0ZXJpbmdfZGlzdGFuY2VfY29scyA9IGNsdXN0ZXJpbmdfZGlzdGFuY2UsY29sb3IgPSBteV9wYWxldHRlLGJyZWFrcyA9IGNvbG9ycyxzaG93X3Jvd25hbWVzID0gRixzaG93X2NvbG5hbWVzID0gRikKICAgICAgICAgICAgLHRpdGxlID0gImdlbmVzIGV4cHJlc3Npb24gaGVhdG1hcCIpCmBgYAoKYGBge3IgZWNobz1UUlVFLCByZXN1bHRzPSdhc2lzJ30KY2hvc2VuX2dlbmVzID0gYW5ub3RhdGlvbltbIm15YW5ub3RhdGlvbiJdXSAlPiUgZHBseXI6OmZpbHRlcihjbHVzdGVyID09IDEgfCBjbHVzdGVyID09IDIgfCBjbHVzdGVyID09IDUpICU+JSByb3duYW1lcygpICN0YWtlIHJlbGV2YW50IGdlbmVzCnZhcl9mZWF0dXJlcz1sdW5nQGFzc2F5cyRSTkFAdmFyLmZlYXR1cmVzCmdlbmVJZHM9IGdlbmVzZXRzW1toYWxsbWFya19uYW1lXV1AZ2VuZUlkcwpzY29yZSA8LSBhcHBseShsdW5nQGFzc2F5cyRSTkFAZGF0YVtpbnRlcnNlY3QoZ2VuZUlkcyx2YXJfZmVhdHVyZXMpLF0sMixtZWFuKQpsdW5nPUFkZE1ldGFEYXRhKGx1bmcsc2NvcmUsaGFsbG1hcmtfbmFtZSkKCnByaW50X3RhYihGZWF0dXJlUGxvdChvYmplY3QgPSBsdW5nLCBmZWF0dXJlcyA9IGhhbGxtYXJrX25hbWUpLHRpdGxlID0gIkV4cHJlc3Npb24iKQpgYGAKCmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcyd9CmNjX3Njb3JlcyA9IEZldGNoRGF0YShvYmplY3QgPSBsdW5nLHZhcnMgPSBoYWxsbWFya19uYW1lKQoKcGx0ICA9ICBnZ3Bsb3QoY2Nfc2NvcmVzLCBhZXMoeD1IQUxMTUFSS19HTFlDT0xZU0lTKSkgKwogIGdlb21fZGVuc2l0eSgpKwogICBnZW9tX3ZsaW5lKAogICAgYWVzKHhpbnRlcmNlcHQ9bWVhbihIQUxMTUFSS19HTFlDT0xZU0lTKSArIHNkKEhBTExNQVJLX0dMWUNPTFlTSVMpICxjb2xvcj0iMSBTRCIpLAogICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIsIHNpemU9MSkrCiAgICBnZW9tX3ZsaW5lKAogICAgYWVzKHhpbnRlcmNlcHQ9bWVhbihIQUxMTUFSS19HTFlDT0xZU0lTKSArIDIqc2QoSEFMTE1BUktfR0xZQ09MWVNJUykgLGNvbG9yPSIyIFNEIiksCiAgICAgICAgICBsaW5ldHlwZT0iZGFzaGVkIiwgc2l6ZT0xKSsKICAgIGdlb21fdmxpbmUoCiAgICBhZXMoeGludGVyY2VwdD1tZWFuKEhBTExNQVJLX0dMWUNPTFlTSVMpICxjb2xvcj0ibWVhbiIpLAogICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIsIHNpemU9MSkKCnByaW50X3RhYihwbHQgPSBwbHQsdGl0bGUgPSAiZGlzdCIpCmBgYAoKCiMgSU5GIHNpZ25hdHVyZSAgey50YWJzZXR9CgpgYGB7ciByZXN1bHRzPSdhc2lzJ30KaGFsbG1hcmtfbmFtZSA9ICJIQUxMTUFSS19JTlRFUkZFUk9OX0dBTU1BX1JFU1BPTlNFIgpnZW5lc2V0cyAgPWdldEdtdCgiLi9EYXRhL2guYWxsLnY3LjAuc3ltYm9scy5wbHVzY2MuZ210IikKZ2VuZUlkcz0gZ2VuZXNldHNbW2hhbGxtYXJrX25hbWVdXUBnZW5lSWRzCmhhbGxtYXJzX2V4cCA9IEZldGNoRGF0YShvYmplY3QgPSB4ZW5vLHZhcnMgPSBjKGdlbmVJZHMpKQpoYWxsbWFyc19leHAgPSBoYWxsbWFyc19leHBbLGNvbFN1bXMoaGFsbG1hcnNfZXhwW10pPjBdICNyZW1vdmUgbm8gZXhwcmVzc2lvbiBnZW5lcwpoYWxsbWFya19jb3IgPSBjb3IoaGFsbG1hcnNfZXhwKQpwaHQxID0gcGhlYXRtYXAobWF0ID0gaGFsbG1hcmtfY29yLHNpbGVudCA9IFQpCmBgYAoKYGBge3IgZWNobz1UUlVFLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD0xMCwgcmVzdWx0cz0nYXNpcyd9Cm51bV9vZl9jbHVzdGVycyA9IDcKY2x1c3RlcmluZ19kaXN0YW5jZSA9ICJldWNsaWRlYW4iCm15YW5ub3RhdGlvbiA9IGFzLmRhdGEuZnJhbWUoY3V0cmVlKHBodDFbWyJ0cmVlX3JvdyJdXSwgayA9IG51bV9vZl9jbHVzdGVycykpICNzcGxpdCBpbnRvIGsgY2x1c3RlcnMKIApuYW1lcyhteWFubm90YXRpb24pWzFdID0gImNsdXN0ZXIiCiAgbXlhbm5vdGF0aW9uJGNsdXN0ZXIgPSBhcy5mYWN0b3IobXlhbm5vdGF0aW9uJGNsdXN0ZXIpCiAgCiAgcGFsZXR0ZTEgPC1icmV3ZXIucGFsKG51bV9vZl9jbHVzdGVycywgIlBhaXJlZCIpCgogIG5hbWVzKHBhbGV0dGUxKSA9IHVuaXF1ZShteWFubm90YXRpb24kY2x1c3RlcikKICBhbm5fY29sb3JzID0gbGlzdCAoY2x1c3RlciA9IHBhbGV0dGUxKQogIGFubm90YXRpb24gPSBsaXN0KGFubl9jb2xvcnMgPSBhbm5fY29sb3JzLCBteWFubm90YXRpb24gPSBteWFubm90YXRpb24pCiAgCiAgY29sb3JzIDwtIGMoc2VxKC0xLDEsYnk9MC4wMSkpCiAgbXlfcGFsZXR0ZSA8LSBjKCJibHVlIixjb2xvclJhbXBQYWxldHRlKGNvbG9ycyA9IGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuID0gbGVuZ3RoKGNvbG9ycyktMyksICJyZWQiKQoKCiAgcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICAgICAgcGhlYXRtYXAobWF0ID0gaGFsbG1hcmtfY29yLGFubm90YXRpb25fY29sID0gIGFubm90YXRpb25bWyJteWFubm90YXRpb24iXV0sIGFubm90YXRpb25fY29sb3JzID0gYW5ub3RhdGlvbltbImFubl9jb2xvcnMiXV0sIGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9IGNsdXN0ZXJpbmdfZGlzdGFuY2UsY2x1c3RlcmluZ19kaXN0YW5jZV9jb2xzID0gY2x1c3RlcmluZ19kaXN0YW5jZSxjb2xvciA9IG15X3BhbGV0dGUsYnJlYWtzID0gY29sb3JzLHNob3dfcm93bmFtZXMgPSBGLHNob3dfY29sbmFtZXMgPSBGKQogICAgICAgICAgICAsdGl0bGUgPSAiZ2VuZXMgZXhwcmVzc2lvbiBoZWF0bWFwIikKYGBgCmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcyd9CmNob3Nlbl9nZW5lcyA9IGFubm90YXRpb25bWyJteWFubm90YXRpb24iXV0gJT4lIGRwbHlyOjpmaWx0ZXIoY2x1c3RlciA9PSA0IHwgY2x1c3RlciA9PSAxIHwgY2x1c3RlciA9PSAzKSAlPiUgcm93bmFtZXMoKSAjdGFrZSByZWxldmFudCBnZW5lcwp2YXJfZmVhdHVyZXM9bHVuZ0Bhc3NheXMkUk5BQHZhci5mZWF0dXJlcwpnZW5lSWRzPSBnZW5lc2V0c1tbaGFsbG1hcmtfbmFtZV1dQGdlbmVJZHMKc2NvcmUgPC0gYXBwbHkobHVuZ0Bhc3NheXMkUk5BQGRhdGFbaW50ZXJzZWN0KGdlbmVJZHMsdmFyX2ZlYXR1cmVzKSxdLDIsbWVhbikKbHVuZz1BZGRNZXRhRGF0YShsdW5nLHNjb3JlLGhhbGxtYXJrX25hbWUpCgpwcmludF90YWIoRmVhdHVyZVBsb3Qob2JqZWN0ID0gbHVuZywgZmVhdHVyZXMgPSBoYWxsbWFya19uYW1lKSx0aXRsZSA9ICJFeHByZXNzaW9uIikKYGBgCgpgYGB7ciBlY2hvPVRSVUUsIHJlc3VsdHM9J2FzaXMnfQpjY19zY29yZXMgPSBGZXRjaERhdGEob2JqZWN0ID0gbHVuZyx2YXJzID0gaGFsbG1hcmtfbmFtZSkKCnBsdCAgPSAgZ2dwbG90KGNjX3Njb3JlcywgYWVzKHg9SEFMTE1BUktfSU5URVJGRVJPTl9HQU1NQV9SRVNQT05TRSkpICsKICBnZW9tX2RlbnNpdHkoKSsKICAgZ2VvbV92bGluZSgKICAgIGFlcyh4aW50ZXJjZXB0PW1lYW4oSEFMTE1BUktfSU5URVJGRVJPTl9HQU1NQV9SRVNQT05TRSkgKyBzZChIQUxMTUFSS19JTlRFUkZFUk9OX0dBTU1BX1JFU1BPTlNFKSAsY29sb3I9IjEgU0QiKSwKICAgICAgICAgIGxpbmV0eXBlPSJkYXNoZWQiLCBzaXplPTEpKwogICAgZ2VvbV92bGluZSgKICAgIGFlcyh4aW50ZXJjZXB0PW1lYW4oSEFMTE1BUktfSU5URVJGRVJPTl9HQU1NQV9SRVNQT05TRSkgKyAyKnNkKEhBTExNQVJLX0lOVEVSRkVST05fR0FNTUFfUkVTUE9OU0UpICxjb2xvcj0iMiBTRCIpLAogICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIsIHNpemU9MSkrCiAgICBnZW9tX3ZsaW5lKAogICAgYWVzKHhpbnRlcmNlcHQ9bWVhbihIQUxMTUFSS19JTlRFUkZFUk9OX0dBTU1BX1JFU1BPTlNFKSAsY29sb3I9Im1lYW4iKSwKICAgICAgICAgIGxpbmV0eXBlPSJkYXNoZWQiLCBzaXplPTEpCgpwcmludF90YWIocGx0ID0gcGx0LHRpdGxlID0gImRpc3QiKQpgYGAKIyAgU2lnbmF0dXJlIHJlZ3VsYXRpb24gIHsudGFic2V0fQoKYGBge3IgZWNobz1UUlVFLCByZXN1bHRzPSdhc2lzJ30KbWV0YWdlbmVzX21lYW5fY29tcGFyZShkYXRhc2V0ID0gbHVuZywgdGltZS5wb2ludF92YXIgPSAidGltZS5wb2ludCIscHJlZml4ID0gInBhdGllbnQiLHBhdGllbnQuaWRlbnRfdmFyID0gInBhdGllbnQuaWRlbnQiLHByZV9vbiA9IGMoInByZS10cmVhdG1lbnQiLCJvbi10cmVhdG1lbnQiKSxheGlzLnRleHQueCA9IDgscHJvZ3JhbXMgPSBjKCJIQUxMTUFSS19IWVBPWElBIiwiSEFMTE1BUktfSU5URVJGRVJPTl9HQU1NQV9SRVNQT05TRSIsIkdPX01JVE9USUNfQ0MiKSkKYGBgCgojIHBlciBwYXRpZW50IGZpc2hlciB0ZXN0CgpgYGB7cn0KcGF0aWVudHNfdmVjdG9yID0gbHVuZyRwYXRpZW50LmlkZW50ICU+JSB1bmlxdWUoKQpmb3IgKHBhdGllbnRfbmFtZSBpbiBwYXRpZW50c192ZWN0b3IpIHsKICBkZiAgPSBGZXRjaERhdGEob2JqZWN0ID0gbHVuZyx2YXJzID0gYygicHJvZ3JhbS5hc3NpZ25tZW50IiwicGF0aWVudC5pZGVudCIsInRpbWUucG9pbnQiKSkgJT4lIAogICAgZmlsdGVyIChwYXRpZW50LmlkZW50ID09IHBhdGllbnRfbmFtZSkgJT4lIAogICAgZmlsdGVyIChwcm9ncmFtLmFzc2lnbm1lbnQgJWluJSBjKCJtZXRhZ2VuZS4xIiwibWV0YWdlbmUuMiIpKSAlPiUgCiAgICBmaWx0ZXIgKHRpbWUucG9pbnQgJWluJSBjKCJwcmUtdHJlYXRtZW50Iiwib24tdHJlYXRtZW50IikpICU+JSAKICAgIHNlbGVjdCgtcGF0aWVudC5pZGVudCkgJT4lIAogICAgZHJvcGxldmVscygpIAogIHRlc3QgPSBmaXNoZXIudGVzdCh0YWJsZShkZikpCiAgICAKICBsaWJyYXJ5KGdnc3RhdHNwbG90KQpwcmludCgKICAgIGdnYmFyc3RhdHMoCiAgICBkZiwgcHJvZ3JhbS5hc3NpZ25tZW50LCB0aW1lLnBvaW50LAogICAgcmVzdWx0cy5zdWJ0aXRsZSA9IEZBTFNFLAogICAgc3VidGl0bGUgPSBwYXN0ZTAoCiAgICAgICJGaXNoZXIncyBleGFjdCB0ZXN0IiwgIiwgcC12YWx1ZSA9ICIsCiAgICAgIGlmZWxzZSh0ZXN0JHAudmFsdWUgPCAwLjAwMSwgIjwgMC4wMDEiLCByb3VuZCh0ZXN0JHAudmFsdWUsIDMpKQogICAgKSx0aXRsZSA9IHBhdGllbnRfbmFtZQogICkKKQp9CmBgYAoKCgo=