1 Introduction

Having established that the TMRC2 macrophage data looks robust and illustrative of a couple of interesting questions, let us perform a couple of differential analyses of it.

Also note that as of 202212, we received a new set of samples which now include some which are of a completely different cell type, U937. As their ATCC page states, they are malignant cells taken from the pleural effusion of a 37 year old white male with histiocytic lymphoma and which exhibit the morphology of monocytes. Thus, this document now includes some comparisons of the cell types as well as the various macrophage donors (given that there are now more donors too).

2 TODO

  • Query overlap of macrophage 2.3/2.2 Sb and noSb. (done?)
  • Repeat with U937

2.1 Human data

I am moving the dataset manipulations here so that I can look at them all together before running the various DE analyses.

all_human <- sanitize_expt_metadata(hs_macrophage, columns = "drug") %>%
  set_expt_conditions(fact = "drug") %>%
  set_expt_batches(fact = "typeofcells")

all_human_types <- set_expt_conditions(all_human, fact = "typeofcells") %>%
  set_expt_batches(fact = "drug")

type_zymo_fact <- paste0(pData(all_human_types)[["condition"]], "_",
                         pData(all_human_types)[["macrophagezymodeme"]])
type_zymo <- set_expt_conditions(all_human_types, fact = type_zymo_fact)

type_drug_fact <- paste0(pData(all_human_types)[["condition"]], "_",
                         pData(all_human_types)[["drug"]])
type_drug <- set_expt_conditions(all_human_types, fact=type_drug_fact)

extra <- "z23drugnodrug_vs_z22drugnodrug = (infsbz23 - infz23) - (infsbz22 - infz22)"
new_conditions <- paste0(pData(hs_macr)[["macrophagetreatment"]], "_",
                         pData(hs_macr)[["macrophagezymodeme"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'hs_macr' not found
hs_macr <- set_expt_conditions(hs_macr, fact = new_conditions)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'hs_macr' not found
new_conditions <- paste0(pData(hs_u937)[["macrophagetreatment"]], "_",
                         pData(hs_u937)[["macrophagezymodeme"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'hs_u937' not found
u937_expt <- set_expt_conditions(hs_u937, fact=new_conditions)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'hs_u937' not found
tmrc2_human_keepers <- list(
    "z23nosb_vs_uninf" = c("infz23", "uninfnone"),
    "z22nosb_vs_uninf" = c("infz22", "uninfnone"),
    "z23nosb_vs_z22nosb" = c("infz23", "infz22"),
    "z23sb_vs_z22sb" = c("infsbz23", "infsbz22"),
    "z23sb_vs_z23nosb" = c("infsbz23", "infz23"),
    "z22sb_vs_z22nosb" = c("infsbz22", "infz22"),
    "z23sb_vs_sb" = c("infz23", "uninfsbnone"),
    "z22sb_vs_sb" = c("infz22", "uninfsbnone"),
    "z23sb_vs_uninf" = c("infsbz23", "uninfnone"),
    "z22sb_vs_uninf" = c("infsbz22", "uninfnone"),
    "sb_vs_uninf" = c("uninfsbnone", "uninfnone"))
##    "extra" = c("z23drugnodrug", "z22drugnodrug"))

2.1.1 Primary queries

There is a series of initial questions which make some sense to me, but these do not necessarily match the set of questions which are most pressing. I am hoping to pull both of these sets of queries in one.

Before extracting these groups of queries, let us invoke the all_pairwise() function and get all of the likely contrasts along with one or more extras that might prove useful (the ‘extra’ argument).

2.1.2 Combined U937 and Macrophages: Compare drug effects

When we have the u937 cells in the same dataset as the macrophages, that provides an interesting opportunity to see if we can observe drug-dependant effects which are shared across both cell types.

drug_de <- all_pairwise(all_human, filter = TRUE, model_batch = "svaseq")
## This DE analysis will perform all pairwise comparisons among:
## 
## antimony     none 
##       34       34
## This analysis will include surrogate estimates from: svaseq.
## This will pre-filter the input data using normalize_expt's: TRUE argument.
## Removing 0 low-count genes (12283 remaining).
## Setting 3092 low elements to zero.
## transform_counts: Found 3092 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
drug_table <- combine_de_tables(
    drug_de,
    excel = glue::glue("excel/tmrc2_macrophage_drug_comparison-v{ver}.xlsx"))
## Deleting the file excel/tmrc2_macrophage_drug_comparison-v202212.xlsx before writing the tables.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of none_vs_antimony according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of none_vs_antimony according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of none_vs_antimony according to the columns: logFC and adj.P.Val using the expressionset colors.

2.1.3 Combined U937 and Macrophages: compare cell types

There are a couple of ways one might want to directly compare the two cell types.

  • Given that the variance between the two celltypes is so huge, just compare all samples.
  • One might want to compare them with the interaction effects of drug/zymodeme.
type_de <- all_pairwise(all_human_types, filter = TRUE, model_batch = "svaseq")
## This DE analysis will perform all pairwise comparisons among:
## 
## Macrophages        U937 
##          54          14
## This analysis will include surrogate estimates from: svaseq.
## This will pre-filter the input data using normalize_expt's: TRUE argument.
## Removing 0 low-count genes (12283 remaining).
## Setting 8682 low elements to zero.
## transform_counts: Found 8682 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
type_table <- combine_de_tables(
    type_de,
    excel = glue::glue("excel/tmrc2_macrophage_type_comparison-v{ver}.xlsx"))
## Deleting the file excel/tmrc2_macrophage_type_comparison-v202212.xlsx before writing the tables.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937_vs_Macrophages according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937_vs_Macrophages according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937_vs_Macrophages according to the columns: logFC and adj.P.Val using the expressionset colors.

Given the above explicit comparison of all samples comprising the two cell types, now let us look at the drug treatment+zymodeme status with all samples, macrophages and U937.

type_zymo_de <- all_pairwise(type_zymo, filter = TRUE, model_batch = "svaseq")
## This DE analysis will perform all pairwise comparisons among:
## 
## Macrophages_none Macrophages_z2.2 Macrophages_z2.3        U937_none 
##                8               23               23                2 
##        U937_z2.2        U937_z2.3 
##                6                6
## This analysis will include surrogate estimates from: svaseq.
## This will pre-filter the input data using normalize_expt's: TRUE argument.
## Removing 0 low-count genes (12283 remaining).
## Setting 9655 low elements to zero.
## transform_counts: Found 9655 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

type_zymo_table <- combine_de_tables(
    type_zymo_de,
    excel = glue::glue("excel/tmrc2_macrophage_type_zymo_comparison-v{ver}.xlsx"))
## Deleting the file excel/tmrc2_macrophage_type_zymo_comparison-v202212.xlsx before writing the tables.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of Macrophagesz22_vs_Macrophagesnone according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of Macrophagesz22_vs_Macrophagesnone according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of Macrophagesz22_vs_Macrophagesnone according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of Macrophagesz23_vs_Macrophagesnone according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of Macrophagesz23_vs_Macrophagesnone according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of Macrophagesz23_vs_Macrophagesnone according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937none_vs_Macrophagesnone according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937none_vs_Macrophagesnone according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937none_vs_Macrophagesnone according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937z22_vs_Macrophagesnone according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937z22_vs_Macrophagesnone according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937z22_vs_Macrophagesnone according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937z23_vs_Macrophagesnone according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937z23_vs_Macrophagesnone according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937z23_vs_Macrophagesnone according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of Macrophagesz23_vs_Macrophagesz22 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of Macrophagesz23_vs_Macrophagesz22 according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of Macrophagesz23_vs_Macrophagesz22 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937none_vs_Macrophagesz22 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937none_vs_Macrophagesz22 according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937none_vs_Macrophagesz22 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937z22_vs_Macrophagesz22 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937z22_vs_Macrophagesz22 according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937z22_vs_Macrophagesz22 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937z23_vs_Macrophagesz22 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937z23_vs_Macrophagesz22 according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937z23_vs_Macrophagesz22 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937none_vs_Macrophagesz23 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937none_vs_Macrophagesz23 according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937none_vs_Macrophagesz23 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937z22_vs_Macrophagesz23 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937z22_vs_Macrophagesz23 according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937z22_vs_Macrophagesz23 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937z23_vs_Macrophagesz23 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937z23_vs_Macrophagesz23 according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937z23_vs_Macrophagesz23 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937z22_vs_U937none according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937z22_vs_U937none according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937z22_vs_U937none according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937z23_vs_U937none according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937z23_vs_U937none according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937z23_vs_U937none according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937z23_vs_U937z22 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937z23_vs_U937z22 according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937z23_vs_U937z22 according to the columns: logFC and adj.P.Val using the expressionset colors.
type_drug_de <- all_pairwise(type_drug, filter = TRUE, model_batch = "svaseq")
## This DE analysis will perform all pairwise comparisons among:
## 
## Macrophages_antimony     Macrophages_none        U937_antimony 
##                   27                   27                    7 
##            U937_none 
##                    7
## This analysis will include surrogate estimates from: svaseq.
## This will pre-filter the input data using normalize_expt's: TRUE argument.
## Removing 0 low-count genes (12283 remaining).
## Setting 9642 low elements to zero.
## transform_counts: Found 9642 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

type_drug_table <- combine_de_tables(
    type_drug_de,
    excel=glue::glue("excel/tmrc2_macrophage_type_drug_comparison-v{ver}.xlsx"))
## Deleting the file excel/tmrc2_macrophage_type_drug_comparison-v202212.xlsx before writing the tables.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of Macrophagesnone_vs_Macrophagesantimony according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of Macrophagesnone_vs_Macrophagesantimony according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of Macrophagesnone_vs_Macrophagesantimony according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937antimony_vs_Macrophagesantimony according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937antimony_vs_Macrophagesantimony according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937antimony_vs_Macrophagesantimony according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937none_vs_Macrophagesantimony according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937none_vs_Macrophagesantimony according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937none_vs_Macrophagesantimony according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937antimony_vs_Macrophagesnone according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937antimony_vs_Macrophagesnone according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937antimony_vs_Macrophagesnone according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937none_vs_Macrophagesnone according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937none_vs_Macrophagesnone according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937none_vs_Macrophagesnone according to the columns: logFC and adj.P.Val using the expressionset colors.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of U937none_vs_U937antimony according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of U937none_vs_U937antimony according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of U937none_vs_U937antimony according to the columns: logFC and adj.P.Val using the expressionset colors.
hs_macr_de <- all_pairwise(hs_macr, model_batch = "svaseq", filter = TRUE)
## This DE analysis will perform all pairwise comparisons among:
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'hs_macr' not found
hs_macr_table <- combine_de_tables(
    hs_macr_de,
    keepers = tmrc2_human_keepers,
    excel = glue::glue("excel/hs_macr_drug_zymo_table-v{ver}.xlsx"))
## Deleting the file excel/hs_macr_drug_zymo_table-v202212.xlsx before writing the tables.
## Error in combine_de_tables(hs_macr_de, keepers = tmrc2_human_keepers, : object 'hs_macr_de' not found
##                                  extra_contrasts = extra)
hs_macr_sig <- extract_significant_genes(
    hs_macr_table,
    excel = glue::glue("excel/hs_macr_drug_zymo_sig-v{ver}.xlsx"))
## Deleting the file excel/hs_macr_drug_zymo_sig-v202212.xlsx before writing the tables.
## Error in extract_significant_genes(hs_macr_table, excel = glue::glue("excel/hs_macr_drug_zymo_sig-v{ver}.xlsx")): object 'hs_macr_table' not found
u937_de <- all_pairwise(u937_expt, model_batch = "svaseq", filter = TRUE)
## This DE analysis will perform all pairwise comparisons among:
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'u937_expt' not found
## extra_contrasts=extra)
u937_table <- combine_de_tables(
    u937_de,
    keepers = tmrc2_human_keepers,
    excel = glue::glue("excel/u937_drug_zymo_table-v{ver}.xlsx"))
## Deleting the file excel/u937_drug_zymo_table-v202212.xlsx before writing the tables.
## Error in combine_de_tables(u937_de, keepers = tmrc2_human_keepers, excel = glue::glue("excel/u937_drug_zymo_table-v{ver}.xlsx")): object 'u937_de' not found
u937_sig <- extract_significant_genes(
    u937_table,
    excel = glue::glue("excel/u937_drug_zymo_sig-v{ver}.xlsx"))
## Deleting the file excel/u937_drug_zymo_sig-v202212.xlsx before writing the tables.
## Error in extract_significant_genes(u937_table, excel = glue::glue("excel/u937_drug_zymo_sig-v{ver}.xlsx")): object 'u937_table' not found

2.1.3.1 Compare (no)Sb z2.3/z2.2 treatments among macrophages

upset_plots_hs_macr <- upsetr_sig(
    hs_macr_sig, both = TRUE,
    contrasts = c("z23sb_vs_z22sb", "z23nosb_vs_z22nosb"))
## Error in upsetr_sig(hs_macr_sig, both = TRUE, contrasts = c("z23sb_vs_z22sb", : object 'hs_macr_sig' not found
upset_plots_hs_macr[["both"]]
## Error in eval(expr, envir, enclos): object 'upset_plots_hs_macr' not found
groups <- upset_plots_hs_macr[["both_groups"]]
## Error in eval(expr, envir, enclos): object 'upset_plots_hs_macr' not found
shared_genes <- attr(groups, "elements")[groups[[2]]] %>%
  gsub(pattern = "^gene:", replacement = "")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'gsub': object 'groups' not found
length(shared_genes)
## Error in eval(expr, envir, enclos): object 'shared_genes' not found
shared_gp <- simple_gprofiler(shared_genes)
## Error in "character" %in% class(sig_genes): object 'shared_genes' not found
shared_gp[["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'shared_gp' not found
pp(file="images/shared_genes_bp.png")
shared_gp[["pvalue_plots"]][["BP"]]
## Error in eval(expr, envir, enclos): object 'shared_gp' not found
dev.off()
## png 
##   2
shared_gp[["pvalue_plots"]][["REAC"]]
## Error in eval(expr, envir, enclos): object 'shared_gp' not found
drug_genes <- attr(groups, "elements")[groups[["z23sb_vs_z22sb"]]] %>%
    gsub(pattern = "^gene:", replacement = "")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'gsub': object 'groups' not found
drugonly_gp <- simple_gprofiler(drug_genes)
## Error in "character" %in% class(sig_genes): object 'drug_genes' not found
drugonly_gp[["pvalue_plots"]][["BP"]]
## Error in eval(expr, envir, enclos): object 'drugonly_gp' not found

I want to try something, directly include the u937 data in this…

both_sig <- hs_macr_sig
## Error in eval(expr, envir, enclos): object 'hs_macr_sig' not found
names(both_sig[["deseq"]][["ups"]]) <- paste0("macr_", names(both_sig[["deseq"]][["ups"]]))
## Error in paste0("macr_", names(both_sig[["deseq"]][["ups"]])): object 'both_sig' not found
names(both_sig[["deseq"]][["downs"]]) <- paste0("macr_", names(both_sig[["deseq"]][["downs"]]))
## Error in paste0("macr_", names(both_sig[["deseq"]][["downs"]])): object 'both_sig' not found
u937_deseq <- u937_sig[["deseq"]]
## Error in eval(expr, envir, enclos): object 'u937_sig' not found
names(u937_deseq[["ups"]]) <- paste0("u937_", names(u937_deseq[["ups"]]))
## Error in paste0("u937_", names(u937_deseq[["ups"]])): object 'u937_deseq' not found
names(u937_deseq[["downs"]]) <- paste0("u937_", names(u937_deseq[["downs"]]))
## Error in paste0("u937_", names(u937_deseq[["downs"]])): object 'u937_deseq' not found
both_sig[["deseq"]][["ups"]] <- c(both_sig[["deseq"]][["ups"]], u937_deseq[["ups"]])
## Error in eval(expr, envir, enclos): object 'both_sig' not found
both_sig[["deseq"]][["downs"]] <- c(both_sig[["deseq"]][["ups"]], u937_deseq[["downs"]])
## Error in eval(expr, envir, enclos): object 'both_sig' not found
summary(both_sig[["deseq"]][["ups"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'summary': object 'both_sig' not found
upset_plots_both <- upsetr_sig(
    both_sig, both=TRUE,
    contrasts=c("macr_z23sb_vs_z22sb", "macr_z23nosb_vs_z22nosb",
                "u937_z23sb_vs_z22sb", "u937_z23nosb_vs_z22nosb"))
## Error in upsetr_sig(both_sig, both = TRUE, contrasts = c("macr_z23sb_vs_z22sb", : object 'both_sig' not found
upset_plots_both$both
## Error in eval(expr, envir, enclos): object 'upset_plots_both' not found

2.1.3.2 Compare DE results from macrophages and U937 samples

Looking a bit more closely at these, I think the u937 data is too sparse to effectively compare.

macr_u937_comparison <- compare_de_results(hs_macr_table, u937_table)
## Testing method: limma.
## Error: object 'hs_macr_table' not found
macr_u937_comparison$lfc_heat
## Error in eval(expr, envir, enclos): object 'macr_u937_comparison' not found
macr_u937_venns <- compare_significant_contrasts(hs_macr_sig, second_sig_tables = u937_sig,
                                                 contrasts = "z23sb_vs_z23nosb")
## Error in compare_significant_contrasts(hs_macr_sig, second_sig_tables = u937_sig, : object 'hs_macr_sig' not found
macr_u937_venns$up_plot
## Error in eval(expr, envir, enclos): object 'macr_u937_venns' not found
macr_u937_venns$down_plot
## Error in eval(expr, envir, enclos): object 'macr_u937_venns' not found
macr_u937_venns_v2 <- compare_significant_contrasts(hs_macr_sig, second_sig_tables = u937_sig,
                                                    contrasts = "z22sb_vs_z22nosb")
## Error in compare_significant_contrasts(hs_macr_sig, second_sig_tables = u937_sig, : object 'hs_macr_sig' not found
macr_u937_venns_v2$up_plot
## Error in eval(expr, envir, enclos): object 'macr_u937_venns_v2' not found
macr_u937_venns_v2$down_plot
## Error in eval(expr, envir, enclos): object 'macr_u937_venns_v2' not found
macr_u937_venns_v3 <- compare_significant_contrasts(hs_macr_sig, second_sig_tables = u937_sig,
                                                    contrasts = "sb_vs_uninf")
## Error in compare_significant_contrasts(hs_macr_sig, second_sig_tables = u937_sig, : object 'hs_macr_sig' not found
macr_u937_venns_v3$up_plot
## Error in eval(expr, envir, enclos): object 'macr_u937_venns_v3' not found
macr_u937_venns_v3$down_plot
## Error in eval(expr, envir, enclos): object 'macr_u937_venns_v3' not found

2.1.4 Compare macrophage/u937 with respect to z2.3/z2.2

comparison_df <- merge(hs_macr_table[["data"]][["z23sb_vs_z22sb"]],
                       u937_table[["data"]][["z23sb_vs_z22sb"]],
                       by = "row.names")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'merge': object 'hs_macr_table' not found
macru937_z23z22_plot <- plot_linear_scatter(comparison_df[, c("deseq_logfc.x", "deseq_logfc.y")])
## Error in data.frame(df[, c(1, 2)]): object 'comparison_df' not found
macru937_z23z22_plot$scatter
## Error in eval(expr, envir, enclos): object 'macru937_z23z22_plot' not found
comparison_df <- merge(hs_macr_table[["data"]][["z23nosb_vs_z22nosb"]],
                       u937_table[["data"]][["z23nosb_vs_z22nosb"]],
                       by = "row.names")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'merge': object 'hs_macr_table' not found
macru937_z23z22_plot <- plot_linear_scatter(comparison_df[, c("deseq_logfc.x", "deseq_logfc.y")])
## Error in data.frame(df[, c(1, 2)]): object 'comparison_df' not found
macru937_z23z22_plot$scatter
## Error in eval(expr, envir, enclos): object 'macru937_z23z22_plot' not found

2.1.4.1 Add donor to the contrasts, no sva

no_power_fact <- paste0(pData(hs_macr)[["donor"]], "_",
                        pData(hs_macr)[["condition"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'hs_macr' not found
hs_nopower <- set_expt_conditions(hs_macr, fact = no_power_fact)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'hs_macr' not found
hs_nopower <- subset_expt(hs_nopower, subset="macrophagezymodeme!='none'")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'sampleNames': object 'hs_nopower' not found
hs_nopower_nosva_de <- all_pairwise(hs_nopower, model_batch = FALSE, filter = TRUE)
## This DE analysis will perform all pairwise comparisons among:
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'hs_nopower' not found
nopower_keepers <- list(
    "d01_zymo" = c("d01infz23", "d01infz22"),
    "d01_sbzymo" = c("d01infsbz23", "d01infsbz22"),
    "d02_zymo" = c("d02infz23", "d02infz22"),
    "d02_sbzymo" = c("d02infsbz23", "d02infsbz22"),
    "d09_zymo" = c("d09infz23", "d09infz22"),
    "d09_sbzymo" = c("d09infsbz23", "d09infsbz22"),
    "d81_zymo" = c("d81infz23", "d81infz22"),
    "d81_sbzymo" = c("d81infsbz23", "d81infsbz22"))
hs_nopower_nosva_table <- combine_de_tables(
    hs_nopower_nosva_de, keepers = nopower_keepers,
    excel = glue::glue("excel/hs_nopower_table-v{ver}.xlsx"))
## Deleting the file excel/hs_nopower_table-v202212.xlsx before writing the tables.
## Error in combine_de_tables(hs_nopower_nosva_de, keepers = nopower_keepers, : object 'hs_nopower_nosva_de' not found
##                                  extra_contrasts = extra)
hs_nopower_nosva_sig <- extract_significant_genes(
    hs_nopower_nosva_table,
    excel = glue::glue("excel/hs_nopower_nosva_sig-v{ver}.xlsx"))
## Deleting the file excel/hs_nopower_nosva_sig-v202212.xlsx before writing the tables.
## Error in extract_significant_genes(hs_nopower_nosva_table, excel = glue::glue("excel/hs_nopower_nosva_sig-v{ver}.xlsx")): object 'hs_nopower_nosva_table' not found
d01d02_zymo_nosva_comp <- merge(hs_nopower_nosva_table[["data"]][["d01_zymo"]],
                          hs_nopower_nosva_table[["data"]][["d02_zymo"]],
                          by="row.names")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'merge': object 'hs_nopower_nosva_table' not found
d0102_zymo_nosva_plot <- plot_linear_scatter(d01d02_zymo_nosva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
## Error in data.frame(df[, c(1, 2)]): object 'd01d02_zymo_nosva_comp' not found
d0102_zymo_nosva_plot$scatter
## Error in eval(expr, envir, enclos): object 'd0102_zymo_nosva_plot' not found
d0102_zymo_nosva_plot$correlation
## Error in eval(expr, envir, enclos): object 'd0102_zymo_nosva_plot' not found
d0102_zymo_nosva_plot$lm_rsq
## Error in eval(expr, envir, enclos): object 'd0102_zymo_nosva_plot' not found
d09d81_zymo_nosva_comp <- merge(hs_nopower_nosva_table[["data"]][["d09_zymo"]],
                          hs_nopower_nosva_table[["data"]][["d81_zymo"]],
                          by="row.names")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'merge': object 'hs_nopower_nosva_table' not found
d0981_zymo_nosva_plot <- plot_linear_scatter(d09d81_zymo_nosva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
## Error in data.frame(df[, c(1, 2)]): object 'd09d81_zymo_nosva_comp' not found
d0981_zymo_nosva_plot$scatter
## Error in eval(expr, envir, enclos): object 'd0981_zymo_nosva_plot' not found
d0981_zymo_nosva_plot$correlation
## Error in eval(expr, envir, enclos): object 'd0981_zymo_nosva_plot' not found
d0981_zymo_nosva_plot$lm_rsq
## Error in eval(expr, envir, enclos): object 'd0981_zymo_nosva_plot' not found
d01d81_zymo_nosva_comp <- merge(hs_nopower_nosva_table[["data"]][["d01_zymo"]],
                                hs_nopower_nosva_table[["data"]][["d81_zymo"]],
                                by="row.names")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'merge': object 'hs_nopower_nosva_table' not found
d0181_zymo_nosva_plot <- plot_linear_scatter(d01d81_zymo_nosva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
## Error in data.frame(df[, c(1, 2)]): object 'd01d81_zymo_nosva_comp' not found
d0181_zymo_nosva_plot$scatter
## Error in eval(expr, envir, enclos): object 'd0181_zymo_nosva_plot' not found
d0181_zymo_nosva_plot$correlation
## Error in eval(expr, envir, enclos): object 'd0181_zymo_nosva_plot' not found
d0181_zymo_nosva_plot$lm_rsq
## Error in eval(expr, envir, enclos): object 'd0181_zymo_nosva_plot' not found
upset_plots_nosva <- upsetr_sig(hs_nopower_nosva_sig, both=TRUE,
                          contrasts=c("d01_zymo", "d02_zymo", "d09_zymo", "d81_zymo"))
## Error in upsetr_sig(hs_nopower_nosva_sig, both = TRUE, contrasts = c("d01_zymo", : object 'hs_nopower_nosva_sig' not found
upset_plots_nosva$up
## Error in eval(expr, envir, enclos): object 'upset_plots_nosva' not found
upset_plots_nosva$down
## Error in eval(expr, envir, enclos): object 'upset_plots_nosva' not found
upset_plots_nosva$both
## Error in eval(expr, envir, enclos): object 'upset_plots_nosva' not found
## The 7th element in the both groups list is the set shared among all donors.
## I don't feel like writing out x:y:z:a
groups <- upset_plots_nosva[["both_groups"]]
## Error in eval(expr, envir, enclos): object 'upset_plots_nosva' not found
shared_genes <- attr(groups, "elements")[groups[[7]]] %>%
  gsub(pattern = "^gene:", replacement = "")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'gsub': object 'groups' not found
shared_gp <- simple_gprofiler(shared_genes)
## Error in "character" %in% class(sig_genes): object 'shared_genes' not found
shared_gp$pvalue_plots$MF
## Error in eval(expr, envir, enclos): object 'shared_gp' not found
shared_gp$pvalue_plots$BP
## Error in eval(expr, envir, enclos): object 'shared_gp' not found
shared_gp$pvalue_plots$REAC
## Error in eval(expr, envir, enclos): object 'shared_gp' not found
shared_gp$pvalue_plots$WP
## Error in eval(expr, envir, enclos): object 'shared_gp' not found

2.1.4.2 Add donor to the contrasts, sva

hs_nopower_sva_de <- all_pairwise(hs_nopower, model_batch = "svaseq", filter = TRUE)
## This DE analysis will perform all pairwise comparisons among:
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'hs_nopower' not found
nopower_keepers <- list(
    "d01_zymo" = c("d01infz23", "d01infz22"),
    "d01_sbzymo" = c("d01infsbz23", "d01infsbz22"),
    "d02_zymo" = c("d02infz23", "d02infz22"),
    "d02_sbzymo" = c("d02infsbz23", "d02infsbz22"),
    "d09_zymo" = c("d09infz23", "d09infz22"),
    "d09_sbzymo" = c("d09infsbz23", "d09infsbz22"),
    "d81_zymo" = c("d81infz23", "d81infz22"),
    "d81_sbzymo" = c("d81infsbz23", "d81infsbz22"))
hs_nopower_sva_table <- combine_de_tables(
    hs_nopower_sva_de, keepers = nopower_keepers,
    excel = glue::glue("excel/hs_nopower_table-v{ver}.xlsx"))
## Error in combine_de_tables(hs_nopower_sva_de, keepers = nopower_keepers, : object 'hs_nopower_sva_de' not found
##                                  extra_contrasts = extra)
hs_nopower_sva_sig <- extract_significant_genes(
    hs_nopower_sva_table,
    excel = glue::glue("excel/hs_nopower_sva_sig-v{ver}.xlsx"))
## Error in extract_significant_genes(hs_nopower_sva_table, excel = glue::glue("excel/hs_nopower_sva_sig-v{ver}.xlsx")): object 'hs_nopower_sva_table' not found
d01d02_zymo_sva_comp <- merge(hs_nopower_sva_table[["data"]][["d01_zymo"]],
                          hs_nopower_sva_table[["data"]][["d02_zymo"]],
                          by="row.names")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'merge': object 'hs_nopower_sva_table' not found
d0102_zymo_sva_plot <- plot_linear_scatter(d01d02_zymo_sva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
## Error in data.frame(df[, c(1, 2)]): object 'd01d02_zymo_sva_comp' not found
d0102_zymo_sva_plot$scatter
## Error in eval(expr, envir, enclos): object 'd0102_zymo_sva_plot' not found
d0102_zymo_sva_plot$correlation
## Error in eval(expr, envir, enclos): object 'd0102_zymo_sva_plot' not found
d0102_zymo_sva_plot$lm_rsq
## Error in eval(expr, envir, enclos): object 'd0102_zymo_sva_plot' not found
d09d81_zymo_sva_comp <- merge(hs_nopower_sva_table[["data"]][["d09_zymo"]],
                          hs_nopower_sva_table[["data"]][["d81_zymo"]],
                          by="row.names")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'merge': object 'hs_nopower_sva_table' not found
d0981_zymo_sva_plot <- plot_linear_scatter(d09d81_zymo_sva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
## Error in data.frame(df[, c(1, 2)]): object 'd09d81_zymo_sva_comp' not found
d0981_zymo_sva_plot$scatter
## Error in eval(expr, envir, enclos): object 'd0981_zymo_sva_plot' not found
d0981_zymo_sva_plot$correlation
## Error in eval(expr, envir, enclos): object 'd0981_zymo_sva_plot' not found
d0981_zymo_sva_plot$lm_rsq
## Error in eval(expr, envir, enclos): object 'd0981_zymo_sva_plot' not found
d01d81_zymo_sva_comp <- merge(hs_nopower_sva_table[["data"]][["d01_zymo"]],
                              hs_nopower_sva_table[["data"]][["d81_zymo"]],
                              by="row.names")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'merge': object 'hs_nopower_sva_table' not found
d0181_zymo_sva_plot <- plot_linear_scatter(d01d81_zymo_sva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
## Error in data.frame(df[, c(1, 2)]): object 'd01d81_zymo_sva_comp' not found
d0181_zymo_sva_plot$scatter
## Error in eval(expr, envir, enclos): object 'd0181_zymo_sva_plot' not found
d0181_zymo_sva_plot$correlation
## Error in eval(expr, envir, enclos): object 'd0181_zymo_sva_plot' not found
d0181_zymo_sva_plot$lm_rsq
## Error in eval(expr, envir, enclos): object 'd0181_zymo_sva_plot' not found
upset_plots_sva <- upsetr_sig(hs_nopower_sva_sig, both=TRUE,
                          contrasts=c("d01_zymo", "d02_zymo", "d09_zymo", "d81_zymo"))
## Error in upsetr_sig(hs_nopower_sva_sig, both = TRUE, contrasts = c("d01_zymo", : object 'hs_nopower_sva_sig' not found
upset_plots_sva$up
## Error in eval(expr, envir, enclos): object 'upset_plots_sva' not found
upset_plots_sva$down
## Error in eval(expr, envir, enclos): object 'upset_plots_sva' not found
upset_plots_sva$both
## Error in eval(expr, envir, enclos): object 'upset_plots_sva' not found
## The 7th element in the both groups list is the set shared among all donors.
## I don't feel like writing out x:y:z:a
groups <- upset_plots_sva[["both_groups"]]
## Error in eval(expr, envir, enclos): object 'upset_plots_sva' not found
shared_genes <- attr(groups, "elements")[groups[[7]]] %>%
  gsub(pattern = "^gene:", replacement = "")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'gsub': object 'groups' not found
shared_gp <- simple_gprofiler(shared_genes)
## Error in "character" %in% class(sig_genes): object 'shared_genes' not found
shared_gp$pvalue_plots$MF
## Error in eval(expr, envir, enclos): object 'shared_gp' not found
shared_gp$pvalue_plots$BP
## Error in eval(expr, envir, enclos): object 'shared_gp' not found
shared_gp$pvalue_plots$REAC
## Error in eval(expr, envir, enclos): object 'shared_gp' not found
shared_gp$pvalue_plots$WP
## Error in eval(expr, envir, enclos): object 'shared_gp' not found

2.1.5 Donor comparison

donor_de <- all_pairwise(hs_donors, model_batch="svaseq", filter=TRUE)
## This DE analysis will perform all pairwise comparisons among:
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'hs_donors' not found
donor_table <- combine_de_tables(
    donor_de,
    excel=glue::glue("excel/donor_tables-v{ver}.xlsx"))
## Deleting the file excel/donor_tables-v202212.xlsx before writing the tables.
## Error in combine_de_tables(donor_de, excel = glue::glue("excel/donor_tables-v{ver}.xlsx")): object 'donor_de' not found

2.1.5.1 Primary query contrasts

The final contrast in this list is interesting because it depends on the extra contrasts applied to the all_pairwise() above. In my way of thinking, the primary comparisons to consider are either cross-drug or cross-strain, but not both. However I think in at least a few instances Olga is interested in strain+drug / uninfected+nodrug.

2.1.5.2 Write contrast results

Now let us write out the xlsx file containing the above contrasts. The file with the suffix _table-version will therefore contain all genes and the file with the suffix _sig-version will contain only those deemed significant via our default criteria of DESeq2 |logFC| >= 1.0 and adjusted p-value <= 0.05.

hs_macr_table <- combine_de_tables(
    hs_macr_de,
    keepers = tmrc2_human_keepers,
    excel=glue::glue("excel/macrophage_human_table-v{ver}.xlsx"))
## Error in combine_de_tables(hs_macr_de, keepers = tmrc2_human_keepers, : object 'hs_macr_de' not found
hs_macr_sig <- extract_significant_genes(
    hs_macr_table,
    excel=glue::glue("excel/macrophage_human_sig-v{ver}.xlsx"))
## Error in extract_significant_genes(hs_macr_table, excel = glue::glue("excel/macrophage_human_sig-v{ver}.xlsx")): object 'hs_macr_table' not found
u937_table <- combine_de_tables(
    u937_de,
    keepers = tmrc2_human_keepers,
    excel=glue::glue("excel/u937_human_table-v{ver}.xlsx"))
## Error in combine_de_tables(u937_de, keepers = tmrc2_human_keepers, excel = glue::glue("excel/u937_human_table-v{ver}.xlsx")): object 'u937_de' not found
u937_sig <- extract_significant_genes(
    u937_table,
    excel=glue::glue("excel/u937_human_sig-v{ver}.xlsx"))
## Error in extract_significant_genes(u937_table, excel = glue::glue("excel/u937_human_sig-v{ver}.xlsx")): object 'u937_table' not found

3 Over representation searches

I decided to make one initially small, but I think quickly big change to the organization of this document: I am moving the GSEA searches up to immediately after the DE. I will then move the plots of the gprofiler results to immediately after the various volcano plots so that it is easier to interpret them.

all_gp <- all_gprofiler(hs_macr_sig)
## Error in all_gprofiler(hs_macr_sig): object 'hs_macr_sig' not found

4 Plot contrasts of interest

One suggestion I received recently was to set the axes for these volcano plots to be static rather than let ggplot choose its own. I am assuming this is only relevant for pairs of contrasts, but that might not be true.

4.1 Individual zymodemes vs. uninfected

z23nosb_vs_uninf_volcano <- plot_volcano_de(
    table = hs_macrophage_table[["data"]][["z23nosb_vs_uninf"]],
    fc_col = "deseq_logfc", p_col = "deseq_adjp",
    shapes_by_state = FALSE, color_by = "fc",  label = 10, label_column = "hgncsymbol")
## Error in is.data.frame(x): object 'hs_macrophage_table' not found
plotly::ggplotly(z23nosb_vs_uninf_volcano$plot)
## Error in plotly::ggplotly(z23nosb_vs_uninf_volcano$plot): object 'z23nosb_vs_uninf_volcano' not found
z22nosb_vs_uninf_volcano <- plot_volcano_de(
    table = hs_macrophage_table[["data"]][["z22nosb_vs_uninf"]],
    fc_col = "deseq_logfc", p_col = "deseq_adjp",
    shapes_by_state = FALSE, color_by = "fc",  label = 10, label_column = "hgncsymbol")
## Error in is.data.frame(x): object 'hs_macrophage_table' not found
plotly::ggplotly(z22nosb_vs_uninf_volcano$plot)
## Error in plotly::ggplotly(z22nosb_vs_uninf_volcano$plot): object 'z22nosb_vs_uninf_volcano' not found

4.1.1 Zymodeme 2.3 without drug vs. uninfected

z23nosb_vs_uninf_volcano$plot +
  xlim(-10, 25) +
  ylim(0, 40)
## Error in eval(expr, envir, enclos): object 'z23nosb_vs_uninf_volcano' not found
pp(file="images/z23_uninf_reactome_up.png", image=all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Error in pp(file = "images/z23_uninf_reactome_up.png", image = all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["REAC"]], : object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["KEGG"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## KEGG, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## WikiPathways, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_uninf_up"]][["interactive_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
all_gp[["z23nosb_vs_uninf_down"]][["pvalue_plots"]][["REAC"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23nosb_vs_uninf_down"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23nosb_vs_uninf_down"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.
z22nosb_vs_uninf_volcano$plot +
  xlim(-10, 25) +
  ylim(0, 40)
## Error in eval(expr, envir, enclos): object 'z22nosb_vs_uninf_volcano' not found
pp(file="images/z22_uninf_reactome_up.png", image=all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Error in pp(file = "images/z22_uninf_reactome_up.png", image = all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["REAC"]], : object 'all_gp' not found
## Reactome, zymodeme2.2 without drug vs. uninfected without drug, up.
all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.2 without drug vs. uninfected without drug, up.
all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.2 without drug vs. uninfected without drug, up.
all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## WikiPathways, zymodeme2.2 without drug vs. uninfected without drug, up.

all_gp[["z22nosb_vs_uninf_down"]][["pvalue_plots"]][["REAC"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## Reactome, zymodeme2.2 without drug vs. uninfected without drug, down.
all_gp[["z22nosb_vs_uninf_down"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.2 without drug vs. uninfected without drug, down.
all_gp[["z22nosb_vs_uninf_down"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.

Check that my perception of the number of significant up/down genes matches what the table/venn says.

shared <- Vennerable::Venn(list("drug" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z23sb_vs_uninf"]]),
                                "nodrug" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z23nosb_vs_uninf"]])))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'hs_macrophage_sig' not found
pp(file="images/z23_vs_uninf_venn_up.png")
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
dev.off()
## png 
##   2
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
## I see 910 z23sb/uninf and 670 no z23nosb/uninf genes in the venn diagram.
length(shared@IntersectionSets[["10"]]) + length(shared@IntersectionSets[["11"]])
## Error in eval(expr, envir, enclos): object 'shared' not found
dim(hs_macrophage_sig[["deseq"]][["ups"]][["z23sb_vs_uninf"]])
## Error in eval(expr, envir, enclos): object 'hs_macrophage_sig' not found
shared <- Vennerable::Venn(list("drug" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z22sb_vs_uninf"]]),
                                "nodrug" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z22nosb_vs_uninf"]])))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'hs_macrophage_sig' not found
pp(file="images/z22_vs_uninf_venn_up.png")
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
dev.off()
## png 
##   2
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
length(shared@IntersectionSets[["10"]]) + length(shared@IntersectionSets[["11"]])
## Error in eval(expr, envir, enclos): object 'shared' not found
dim(hs_macrophage_sig[["deseq"]][["ups"]][["z22sb_vs_uninf"]])
## Error in eval(expr, envir, enclos): object 'hs_macrophage_sig' not found

Note to self: There is an error in my volcano plot code which takes effect when the numerator and denominator of the all_pairwise contrasts are different than those in combine_de_tables. It is putting the ups/downs on the correct sides of the plot, but calling the down genes ‘up’ and vice-versa. The reason for this is that I did a check for this happening, but used the wrong argument to handle it.

A likely bit of text for these volcano plots:

The set of genes differentially expressed between the zymodeme 2.3 and uninfected samples without druge treatment was quantified with DESeq2 and included surrogate estimates from SVA. Given the criteria of significance of a abs(logFC) >= 1.0 and false discovery rate adjusted p-value <= 0.05, 670 genes were observed as significantly increased between the infected and uninfected samples and 386 were observed as decreased. The most increased genes from the uninfected samples include some which are potentially indicative of a strong innate immune response and the inflammatory response.

In contrast, when the set of genes differentially expressed between the zymodeme 2.2 and uninfected samples was visualized, only 7 genes were observed as decreased and 435 increased. The inflammatory response was significantly less apparent in this set, but instead included genes related to transporter activity and oxidoreductases.

4.2 Direct zymodeme comparisons

An orthogonal comparison to that performed above is to directly compare the zymodeme 2.3 and 2.2 samples with and without antimonial treatment.

z23nosb_vs_z22nosb_volcano <- plot_volcano_de(
    table = hs_macrophage_table[["data"]][["z23nosb_vs_z22nosb"]],
    fc_col = "deseq_logfc", p_col = "deseq_adjp",
    shapes_by_state = FALSE, color_by = "fc",  label = 10, label_column = "hgncsymbol")
## Error in is.data.frame(x): object 'hs_macrophage_table' not found
plotly::ggplotly(z23nosb_vs_z22nosb_volcano$plot)
## Error in plotly::ggplotly(z23nosb_vs_z22nosb_volcano$plot): object 'z23nosb_vs_z22nosb_volcano' not found
z23sb_vs_z22sb_volcano <- plot_volcano_de(
    table = hs_macrophage_table[["data"]][["z23sb_vs_z22sb"]],
    fc_col = "deseq_logfc", p_col = "deseq_adjp",
    shapes_by_state = FALSE, color_by = "fc",  label = 10, label_column = "hgncsymbol")
## Error in is.data.frame(x): object 'hs_macrophage_table' not found
plotly::ggplotly(z23sb_vs_z22sb_volcano$plot)
## Error in plotly::ggplotly(z23sb_vs_z22sb_volcano$plot): object 'z23sb_vs_z22sb_volcano' not found
z23nosb_vs_z22nosb_volcano$plot +
  xlim(-10, 10) +
  ylim(0, 60)
## Error in eval(expr, envir, enclos): object 'z23nosb_vs_z22nosb_volcano' not found
pp(file="images/z23nosb_vs_z22nosb_reactome_up.png", image=all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Error in pp(file = "images/z23nosb_vs_z22nosb_reactome_up.png", image = all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]], : object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["KEGG"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## KEGG, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## WikiPathways, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_z22nosb_up"]][["interactive_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
all_gp[["z23nosb_vs_z22nosb_down"]][["pvalue_plots"]][["REAC"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23nosb_vs_z22nosb_down"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23nosb_vs_z22nosb_down"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.
z23sb_vs_z22sb_volcano$plot +
  xlim(-10, 10) +
  ylim(0, 60)
## Error in eval(expr, envir, enclos): object 'z23sb_vs_z22sb_volcano' not found
pp(file="images/z23sb_vs_z22sb_reactome_up.png", image=all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Error in pp(file = "images/z23sb_vs_z22sb_reactome_up.png", image = all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["REAC"]], : object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["KEGG"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## KEGG, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## WikiPathways, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z22sb_up"]][["interactive_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
all_gp[["z23sb_vs_z22sb_down"]][["pvalue_plots"]][["REAC"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23sb_vs_z22sb_down"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23sb_vs_z22sb_down"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.
shared <- Vennerable::Venn(list("drug" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z23sb_vs_z22sb"]]),
                                "nodrug" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z23nosb_vs_z22nosb"]])))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'hs_macrophage_sig' not found
pp(file="images/drug_nodrug_venn_up.png")
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
dev.off()
## png 
##   2
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
shared <- Vennerable::Venn(list("drug" = rownames(hs_macrophage_sig[["deseq"]][["downs"]][["z23sb_vs_z22sb"]]),
                                "nodrug" = rownames(hs_macrophage_sig[["deseq"]][["downs"]][["z23nosb_vs_z22nosb"]])))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'hs_macrophage_sig' not found
pp(file="images/drug_nodrug_venn_down.png")
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
dev.off()
## png 
##   2

A slightly different way of looking at the differences between the two zymodeme infections is to directly compare the infected samples with and without drug. Thus, when a volcano plot showing the comparison of the zymodeme 2.3 vs. 2.2 samples was plotted, 484 genes were observed as increased and 422 decreased; these groups include many of the same inflammatory (up) and membrane (down) genes.

Similar patterns were observed when the antimonial was included. Thus, when a Venn diagram of the two sets of increased genes was plotted, a significant number of the genes was observed as increased (313) and decreased (244) in both the untreated and antimonial treated samples.

4.3 Drug effects on each zymodeme infection

Another likely question is to directly compare the treated vs untreated samples for each zymodeme infection in order to visualize the effects of antimonial.

z23sb_vs_z23nosb_volcano <- plot_volcano_de(
    table = hs_macrophage_table[["data"]][["z23sb_vs_z23nosb"]],
    fc_col = "deseq_logfc", p_col = "deseq_adjp",
    shapes_by_state = FALSE, color_by = "fc",  label = 10, label_column = "hgncsymbol")
## Error in is.data.frame(x): object 'hs_macrophage_table' not found
plotly::ggplotly(z23sb_vs_z23nosb_volcano$plot)
## Error in plotly::ggplotly(z23sb_vs_z23nosb_volcano$plot): object 'z23sb_vs_z23nosb_volcano' not found
z22sb_vs_z22nosb_volcano <- plot_volcano_de(
    table = hs_macrophage_table[["data"]][["z22sb_vs_z22nosb"]],
    fc_col = "deseq_logfc", p_col = "deseq_adjp",
    shapes_by_state = FALSE, color_by = "fc",  label = 10, label_column = "hgncsymbol")
## Error in is.data.frame(x): object 'hs_macrophage_table' not found
plotly::ggplotly(z22sb_vs_z22nosb_volcano$plot)
## Error in plotly::ggplotly(z22sb_vs_z22nosb_volcano$plot): object 'z22sb_vs_z22nosb_volcano' not found
z23sb_vs_z23nosb_volcano$plot +
  xlim(-8, 8) +
  ylim(0, 210)
## Error in eval(expr, envir, enclos): object 'z23sb_vs_z23nosb_volcano' not found
pp(file="images/z23sb_vs_z23nosb_reactome_up.png",
   image=all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Error in pp(file = "images/z23sb_vs_z23nosb_reactome_up.png", image = all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["REAC"]], : object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["KEGG"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## KEGG, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## WikiPathways, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z23nosb_up"]][["interactive_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
all_gp[["z23sb_vs_z23nosb_down"]][["pvalue_plots"]][["REAC"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23sb_vs_z23nosb_down"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23sb_vs_z23nosb_down"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.
z22sb_vs_z22nosb_volcano$plot +
  xlim(-8, 8) +
  ylim(0, 210)
## Error in eval(expr, envir, enclos): object 'z22sb_vs_z22nosb_volcano' not found
pp(file="images/z22sb_vs_z22nosb_reactome_up.png",
   image=all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Error in pp(file = "images/z22sb_vs_z22nosb_reactome_up.png", image = all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]], : object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["KEGG"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## KEGG, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## WikiPathways, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z22sb_vs_z22nosb_up"]][["interactive_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
all_gp[["z22sb_vs_z22nosb_down"]][["pvalue_plots"]][["REAC"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z22sb_vs_z22nosb_down"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z22sb_vs_z22nosb_down"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.
shared <- Vennerable::Venn(list("z23" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z23sb_vs_z23nosb"]]),
                                "z22" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z22sb_vs_z22nosb"]])))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'hs_macrophage_sig' not found
pp(file="images/z23_z22_drug_venn_up.png")
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
dev.off()
## png 
##   2
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
shared <- Vennerable::Venn(list("z23" = rownames(hs_macrophage_sig[["deseq"]][["downs"]][["z23sb_vs_z23nosb"]]),
                                "z22" = rownames(hs_macrophage_sig[["deseq"]][["downs"]][["z22sb_vs_z22nosb"]])))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'hs_macrophage_sig' not found
pp(file="images/z23_z22_drug_venn_down.png")
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
dev.off()
## png 
##   2
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found

Note: I am settig the x and y-axis boundaries by allowing the plotter to pick its own axis the first time, writing down the ranges I observe, and then setting them to the largest of the pair. It is therefore possible that I missed one or more genes which lies outside that range.

The previous plotted contrasts sought to show changes between the two strains z2.3 and z2.2. Conversely, the previous volcano plots seek to directly compare each strain before/after drug treatment.

4.4 Parasite

lp_macrophage_de <- all_pairwise(lp_macrophage,
                                 model_batch="svaseq", filter=TRUE)
## This DE analysis will perform all pairwise comparisons among:
## 
## z2.2 z2.3 
##   11    9
## This analysis will include surrogate estimates from: svaseq.
## This will pre-filter the input data using normalize_expt's: TRUE argument.
## Removing 0 low-count genes (8541 remaining).
## Setting 134 low elements to zero.
## transform_counts: Found 134 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
tmrc2_parasite_keepers <- list(
    "z23nosb_vs_z22nosb" = c("z23", "z22"))
lp_macrophage_table <- combine_de_tables(
  lp_macrophage_de, keepers = tmrc2_parasite_keepers,
  excel=glue::glue("excel/macrophage_parasite_infection_de-v{ver}.xlsx"))
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of z23_vs_z22 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of z23_vs_z22 according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of z23_vs_z22 according to the columns: logFC and adj.P.Val using the expressionset colors.
lp_macrophage_sig <- extract_significant_genes(
    lp_macrophage_table,
    excel=glue::glue("excel/macrophage_parasite_sig-v{ver}.xlsx"))
## Plotting volcano plot of the DE results of z23_vs_z22 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of z23_vs_z22 according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of z23_vs_z22 according to the columns: logFC and adj.P.Val using the expressionset colors.
pp(file="images/lp_macrophage_z23_z22.png",
   image=lp_macrophage_table[["plots"]][["z23nosb_vs_z22nosb"]][["deseq_vol_plots"]][["plot"]])
## Warning in pp(file = "images/lp_macrophage_z23_z22.png", image =
## lp_macrophage_table[["plots"]][["z23nosb_vs_z22nosb"]][["deseq_vol_plots"]][["plot"]]):
## There is no device to shut down.
up_genes <- lp_macrophage_sig[["deseq"]][["ups"]][[1]]
dim(up_genes)
## [1] 47 58
down_genes <- lp_macrophage_sig[["deseq"]][["downs"]][[1]]
dim(down_genes)
## [1] 88 58
lp_z23sb_vs_z22sb_volcano <- plot_volcano_de(
    table = lp_macrophage_table[["data"]][["z23nosb_vs_z22nosb"]],
    fc_col = "deseq_logfc", p_col = "deseq_adjp",
    shapes_by_state = FALSE, color_by = "fc",  label = 10, label_column = "hgncsymbol")
## Error in plot_volcano_de(table = lp_macrophage_table[["data"]][["z23nosb_vs_z22nosb"]], : object 'color_list' not found
plotly::ggplotly(lp_z23sb_vs_z22sb_volcano$plot)
## Error in plotly::ggplotly(lp_z23sb_vs_z22sb_volcano$plot): object 'lp_z23sb_vs_z22sb_volcano' not found
lp_z23nosb_vs_z22nosb_volcano$plot
## Error in eval(expr, envir, enclos): object 'lp_z23nosb_vs_z22nosb_volcano' not found
up_goseq <- simple_goseq(up_genes, go_db=lp_go, length_db=lp_lengths)
## Found 16 go_db genes and 47 length_db genes out of 47.
## Testing that go categories are defined.
## Removing undefined categories.
## Gathering synonyms.
## Gathering category definitions.
## The score column is null, defaulting to score.
## Possible columns are:
## [1] "category"                 "over_represented_pvalue" 
## [3] "under_represented_pvalue" "numDEInCat"              
## [5] "numInCat"                 "term"                    
## [7] "ontology"                 "qvalue"
## The over_represented_pvalue column is null, defaulting to score.
## Possible columns are:
## [1] "term"    "pvalue"  "score"   "num_de"  "num_cat"
## The score column is null, defaulting to score.
## Possible columns are:
## [1] "category"                 "over_represented_pvalue" 
## [3] "under_represented_pvalue" "numDEInCat"              
## [5] "numInCat"                 "term"                    
## [7] "ontology"                 "qvalue"
## The over_represented_pvalue column is null, defaulting to score.
## Possible columns are:
## [1] "term"    "pvalue"  "score"   "num_de"  "num_cat"
## The score column is null, defaulting to score.
## Possible columns are:
## [1] "category"                 "over_represented_pvalue" 
## [3] "under_represented_pvalue" "numDEInCat"              
## [5] "numInCat"                 "term"                    
## [7] "ontology"                 "qvalue"
## The over_represented_pvalue column is null, defaulting to score.
## Possible columns are:
## [1] "term"    "pvalue"  "score"   "num_de"  "num_cat"
## View categories over represented in the 2.3 samples
up_goseq$pvalue_plots$bpp_plot_over

down_goseq <- simple_goseq(down_genes, go_db=lp_go, length_db=lp_lengths)
## Found 28 go_db genes and 88 length_db genes out of 88.
## Testing that go categories are defined.
## Removing undefined categories.
## Gathering synonyms.
## Gathering category definitions.
## The score column is null, defaulting to score.
## Possible columns are:
## [1] "category"                 "over_represented_pvalue" 
## [3] "under_represented_pvalue" "numDEInCat"              
## [5] "numInCat"                 "term"                    
## [7] "ontology"                 "qvalue"
## The over_represented_pvalue column is null, defaulting to score.
## Possible columns are:
## [1] "term"    "pvalue"  "score"   "num_de"  "num_cat"
## The score column is null, defaulting to score.
## Possible columns are:
## [1] "category"                 "over_represented_pvalue" 
## [3] "under_represented_pvalue" "numDEInCat"              
## [5] "numInCat"                 "term"                    
## [7] "ontology"                 "qvalue"
## The over_represented_pvalue column is null, defaulting to score.
## Possible columns are:
## [1] "term"    "pvalue"  "score"   "num_de"  "num_cat"
## The score column is null, defaulting to score.
## Possible columns are:
## [1] "category"                 "over_represented_pvalue" 
## [3] "under_represented_pvalue" "numDEInCat"              
## [5] "numInCat"                 "term"                    
## [7] "ontology"                 "qvalue"
## The over_represented_pvalue column is null, defaulting to score.
## Possible columns are:
## [1] "term"    "pvalue"  "score"   "num_de"  "num_cat"
## View categories over represented in the 2.2 samples
down_goseq$pvalue_plots$bpp_plot_over

5 GSVA

hs_infected <- subset_expt(hs_macrophage, subset="macrophagetreatment!='uninf'") %>%
  subset_expt(subset="macrophagetreatment!='uninf_sb'")
hs_gsva_c2 <- simple_gsva(hs_infected)
hs_gsva_c2_meta <- get_msigdb_metadata(hs_gsva_c2, msig_xml="reference/msigdb_v7.2.xml")
hs_gsva_c2_sig <- get_sig_gsva_categories(hs_gsva_c2_meta, excel = "excel/hs_macrophage_gsva_c2_sig.xlsx")
hs_gsva_c2_sig$raw_plot

hs_gsva_c7 <- simple_gsva(hs_infected, signature_category = "c7")
hs_gsva_c7_meta <- get_msigdb_metadata(hs_gsva_c7, msig_xml="reference/msigdb_v7.2.xml")4
hs_gsva_c7_sig <- get_sig_gsva_categories(hs_gsva_c7, excel = "excel/hs_macrophage_gsva_c7_sig.xlsx")
hs_gsva_c7_sig$raw_plot
## Error: <text>:9:89: unexpected numeric constant
## 8: hs_gsva_c7 <- simple_gsva(hs_infected, signature_category = "c7")
## 9: hs_gsva_c7_meta <- get_msigdb_metadata(hs_gsva_c7, msig_xml="reference/msigdb_v7.2.xml")4
##                                                                                            ^

6 Try out a new tool

Two reasons: Najib loves him some PCA, this uses wikipathways, which is something I think is neat.

Ok, I spent some time looking through the code and I have some problems with some of the design decisions.

Most importantly, it requires a data.frame() which has the following format:

  1. No rownames, instead column #1 is the sample ID.
  2. Columns 2-m are the categorical/survival/etc metrics.
  3. Columns m-n are 1 gene-per-column with log2 values.

But when I think about it I think I get the idea, they want to be able to do modelling stuff more easily with response factors.

library(pathwayPCA)
library(rWikiPathways)

downloaded <- downloadPathwayArchive(organism = "Homo sapiens", format = "gmt")
data_path <- system.file("extdata", package="pathwayPCA")
wikipathways <- read_gmt(paste0(data_path, "/wikipathways_human_symbol.gmt"), description=TRUE)

expt <- subset_expt(hs_macrophage, subset="macrophagetreatment!='uninf'") %>%
  subset_expt(subset="macrophagetreatment!='uninf_sb'")
expt <- set_expt_conditions(expt, fact="macrophagezymodeme")

symbol_vector <- fData(expt)[[symbol_column]]
names(symbol_vector) <- rownames(fData(expt))
symbol_df <- as.data.frame(symbol_vector)

assay_df <- merge(symbol_df, as.data.frame(exprs(expt)), by = "row.names")
assay_df[["Row.names"]] <- NULL
rownames(assay_df) <- make.names(assay_df[["symbol_vector"]], unique = TRUE)
assay_df[["symbol_vector"]] <- NULL
assay_df <- as.data.frame(t(assay_df))
assay_df[["SampleID"]] <- rownames(assay_df)
assay_df <- dplyr::select(assay_df, "SampleID", everything())

factor_df <- as.data.frame(pData(expt))
factor_df[["SampleID"]] <- rownames(factor_df)
factor_df <- dplyr::select(factor_df, "SampleID", everything())
factor_df <- factor_df[, c("SampleID", factors)]

tt <- CreateOmics(
    assayData_df = assay_df,
    pathwayCollection_ls = wikipathways,
    response = factor_df,
    respType = "categorical",
    minPathSize=5)

super <- AESPCA_pVals(
    object = tt,
    numPCs = 2,
    parallel = FALSE,
    numCores = 8,
    numReps = 2,
    adjustment = "BH")
if (!isTRUE(get0("skip_load"))) {
  pander::pander(sessionInfo())
  message(paste0("This is hpgltools commit: ", get_git_commit()))
  message(paste0("Saving to ", savefile))
  tmp <- sm(saveme(filename = savefile))
}
## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset 911e7d4beebdc73267ec4be631a305574289efd3
## This is hpgltools commit: Tue Jan 17 10:36:44 2023 -0500: 911e7d4beebdc73267ec4be631a305574289efd3
## Saving to tmrc2_macrophage_visualization_202212.rda.xz
tmp <- loadme(filename = savefile)
LS0tCnRpdGxlOiAiVE1SQzIgMjAyMjEyOiBNYWNyb3BoYWdlIERpZmZlcmVudGlhbCBFeHByZXNzaW9uLiIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogaHRtbF9kb2N1bWVudDoKICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgY29kZV9mb2xkaW5nOiBzaG93CiAgZmlnX2NhcHRpb246IHRydWUKICBmaWdfaGVpZ2h0OiA3CiAgZmlnX3dpZHRoOiA3CiAgaGlnaGxpZ2h0OiBkZWZhdWx0CiAga2VlcF9tZDogZmFsc2UKICBtb2RlOiBzZWxmY29udGFpbmVkCiAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgc2VsZl9jb250YWluZWQ6IHRydWUKICB0aGVtZTogcmVhZGFibGUKICB0b2M6IHRydWUKICB0b2NfZmxvYXQ6CiAgIGNvbGxhcHNlZDogZmFsc2UKICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgo8c3R5bGU+CiAgYm9keSAubWFpbi1jb250YWluZXIgewogICAgbWF4LXdpZHRoOiAxNjAwcHg7CiAgfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZSA9IEZBTFNFfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoSGVhdHBsdXMpCmxpYnJhcnkoaHBnbHRvb2xzKQp0dCA8LSBkZXZ0b29sczo6bG9hZF9hbGwoIn4vaHBnbHRvb2xzIikKa25pdHI6Om9wdHNfa25pdCRzZXQocHJvZ3Jlc3MgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICB2ZXJib3NlID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSA5MCwKICAgICAgICAgICAgICAgICAgICAgZWNobyA9IFRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBmaWcud2lkdGggPSA4LAogICAgICAgICAgICAgICAgICAgICAgZmlnLmhlaWdodCA9IDgsCiAgICAgICAgICAgICAgICAgICAgICBkcGkgPSA5NikKb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHMgPSA0LAogICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBrbml0ci5kdXBsaWNhdGUubGFiZWwgPSAiYWxsb3ciKQpnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTIpKQp2ZXIgPC0gIjIwMjIxMiIKcHJldmlvdXNfZmlsZSA8LSAiIgpydW5kYXRlIDwtIGZvcm1hdChTeXMuRGF0ZSgpLCBmb3JtYXQgPSAiJVklbSVkIikKCiMjIHRtcCA8LSB0cnkoc20obG9hZG1lKGZpbGVuYW1lID0gZ3N1YihwYXR0ZXJuID0gIlxcLlJtZCIsIHJlcGxhY2UgPSAiXFwucmRhXFwueHoiLCB4ID0gcHJldmlvdXNfZmlsZSkpKSkKcm1kX2ZpbGUgPC0gZ2x1ZTo6Z2x1ZSgidG1yYzJfbWFjcm9waGFnZV92aXN1YWxpemF0aW9uX3t2ZXJ9LlJtZCIpCmxvYWRlZCA8LSBsb2FkKGZpbGU9Z2x1ZTo6Z2x1ZSgicmRhL3RtcmMyX2RhdGFfc3RydWN0dXJlcy12e3Zlcn0ucmRhIikpCnNhdmVmaWxlIDwtIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLCByZXBsYWNlID0gIlxcLnJkYVxcLnh6IiwgeCA9IHJtZF9maWxlKQpgYGAKCiMgSW50cm9kdWN0aW9uCgpIYXZpbmcgZXN0YWJsaXNoZWQgdGhhdCB0aGUgVE1SQzIgbWFjcm9waGFnZSBkYXRhIGxvb2tzIHJvYnVzdCBhbmQKaWxsdXN0cmF0aXZlIG9mIGEgY291cGxlIG9mIGludGVyZXN0aW5nIHF1ZXN0aW9ucywgbGV0IHVzIHBlcmZvcm0gYQpjb3VwbGUgb2YgZGlmZmVyZW50aWFsIGFuYWx5c2VzIG9mIGl0LgoKQWxzbyBub3RlIHRoYXQgYXMgb2YgMjAyMjEyLCB3ZSByZWNlaXZlZCBhIG5ldyBzZXQgb2Ygc2FtcGxlcyB3aGljaApub3cgaW5jbHVkZSBzb21lIHdoaWNoIGFyZSBvZiBhIGNvbXBsZXRlbHkgZGlmZmVyZW50IGNlbGwgdHlwZSwKVTkzNy4gQXMgdGhlaXIgQVRDQyBwYWdlIHN0YXRlcywgdGhleSBhcmUgbWFsaWduYW50IGNlbGxzIHRha2VuIGZyb20KdGhlIHBsZXVyYWwgZWZmdXNpb24gb2YgYSAzNyB5ZWFyIG9sZCB3aGl0ZSBtYWxlIHdpdGggaGlzdGlvY3l0aWMKbHltcGhvbWEgYW5kIHdoaWNoIGV4aGliaXQgdGhlIG1vcnBob2xvZ3kgb2YgbW9ub2N5dGVzLiAgVGh1cywgdGhpcwpkb2N1bWVudCBub3cgaW5jbHVkZXMgc29tZSBjb21wYXJpc29ucyBvZiB0aGUgY2VsbCB0eXBlcyBhcyB3ZWxsIGFzCnRoZSB2YXJpb3VzIG1hY3JvcGhhZ2UgZG9ub3JzIChnaXZlbiB0aGF0IHRoZXJlIGFyZSBub3cgbW9yZSBkb25vcnMKdG9vKS4KCiMgVE9ETwoKKiBRdWVyeSBvdmVybGFwIG9mIG1hY3JvcGhhZ2UgMi4zLzIuMiBTYiBhbmQgbm9TYi4gKGRvbmU/KQoqIFJlcGVhdCB3aXRoIFU5MzcKCiMjIEh1bWFuIGRhdGEKCkkgYW0gbW92aW5nIHRoZSBkYXRhc2V0IG1hbmlwdWxhdGlvbnMgaGVyZSBzbyB0aGF0IEkgY2FuIGxvb2sgYXQgdGhlbQphbGwgdG9nZXRoZXIgYmVmb3JlIHJ1bm5pbmcgdGhlIHZhcmlvdXMgREUgYW5hbHlzZXMuCgpgYGB7ciBkZV9kYXRhc2V0c30KYWxsX2h1bWFuIDwtIHNhbml0aXplX2V4cHRfbWV0YWRhdGEoaHNfbWFjcm9waGFnZSwgY29sdW1ucyA9ICJkcnVnIikgJT4lCiAgc2V0X2V4cHRfY29uZGl0aW9ucyhmYWN0ID0gImRydWciKSAlPiUKICBzZXRfZXhwdF9iYXRjaGVzKGZhY3QgPSAidHlwZW9mY2VsbHMiKQoKYWxsX2h1bWFuX3R5cGVzIDwtIHNldF9leHB0X2NvbmRpdGlvbnMoYWxsX2h1bWFuLCBmYWN0ID0gInR5cGVvZmNlbGxzIikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0ID0gImRydWciKQoKdHlwZV96eW1vX2ZhY3QgPC0gcGFzdGUwKHBEYXRhKGFsbF9odW1hbl90eXBlcylbWyJjb25kaXRpb24iXV0sICJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgIHBEYXRhKGFsbF9odW1hbl90eXBlcylbWyJtYWNyb3BoYWdlenltb2RlbWUiXV0pCnR5cGVfenltbyA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGFsbF9odW1hbl90eXBlcywgZmFjdCA9IHR5cGVfenltb19mYWN0KQoKdHlwZV9kcnVnX2ZhY3QgPC0gcGFzdGUwKHBEYXRhKGFsbF9odW1hbl90eXBlcylbWyJjb25kaXRpb24iXV0sICJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgIHBEYXRhKGFsbF9odW1hbl90eXBlcylbWyJkcnVnIl1dKQp0eXBlX2RydWcgPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhhbGxfaHVtYW5fdHlwZXMsIGZhY3Q9dHlwZV9kcnVnX2ZhY3QpCgpleHRyYSA8LSAiejIzZHJ1Z25vZHJ1Z192c196MjJkcnVnbm9kcnVnID0gKGluZnNiejIzIC0gaW5mejIzKSAtIChpbmZzYnoyMiAtIGluZnoyMikiCm5ld19jb25kaXRpb25zIDwtIHBhc3RlMChwRGF0YShoc19tYWNyKVtbIm1hY3JvcGhhZ2V0cmVhdG1lbnQiXV0sICJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgIHBEYXRhKGhzX21hY3IpW1sibWFjcm9waGFnZXp5bW9kZW1lIl1dKQpoc19tYWNyIDwtIHNldF9leHB0X2NvbmRpdGlvbnMoaHNfbWFjciwgZmFjdCA9IG5ld19jb25kaXRpb25zKQoKbmV3X2NvbmRpdGlvbnMgPC0gcGFzdGUwKHBEYXRhKGhzX3U5MzcpW1sibWFjcm9waGFnZXRyZWF0bWVudCJdXSwgIl8iLAogICAgICAgICAgICAgICAgICAgICAgICAgcERhdGEoaHNfdTkzNylbWyJtYWNyb3BoYWdlenltb2RlbWUiXV0pCnU5MzdfZXhwdCA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGhzX3U5MzcsIGZhY3Q9bmV3X2NvbmRpdGlvbnMpCmBgYAoKYGBge3IgdHVtcmMyX2h1bWFuX2tlZXBlcnN9CnRtcmMyX2h1bWFuX2tlZXBlcnMgPC0gbGlzdCgKICAgICJ6MjNub3NiX3ZzX3VuaW5mIiA9IGMoImluZnoyMyIsICJ1bmluZm5vbmUiKSwKICAgICJ6MjJub3NiX3ZzX3VuaW5mIiA9IGMoImluZnoyMiIsICJ1bmluZm5vbmUiKSwKICAgICJ6MjNub3NiX3ZzX3oyMm5vc2IiID0gYygiaW5mejIzIiwgImluZnoyMiIpLAogICAgInoyM3NiX3ZzX3oyMnNiIiA9IGMoImluZnNiejIzIiwgImluZnNiejIyIiksCiAgICAiejIzc2JfdnNfejIzbm9zYiIgPSBjKCJpbmZzYnoyMyIsICJpbmZ6MjMiKSwKICAgICJ6MjJzYl92c196MjJub3NiIiA9IGMoImluZnNiejIyIiwgImluZnoyMiIpLAogICAgInoyM3NiX3ZzX3NiIiA9IGMoImluZnoyMyIsICJ1bmluZnNibm9uZSIpLAogICAgInoyMnNiX3ZzX3NiIiA9IGMoImluZnoyMiIsICJ1bmluZnNibm9uZSIpLAogICAgInoyM3NiX3ZzX3VuaW5mIiA9IGMoImluZnNiejIzIiwgInVuaW5mbm9uZSIpLAogICAgInoyMnNiX3ZzX3VuaW5mIiA9IGMoImluZnNiejIyIiwgInVuaW5mbm9uZSIpLAogICAgInNiX3ZzX3VuaW5mIiA9IGMoInVuaW5mc2Jub25lIiwgInVuaW5mbm9uZSIpKQojIyAgICAiZXh0cmEiID0gYygiejIzZHJ1Z25vZHJ1ZyIsICJ6MjJkcnVnbm9kcnVnIikpCmBgYAoKIyMjIFByaW1hcnkgcXVlcmllcwoKVGhlcmUgaXMgYSBzZXJpZXMgb2YgaW5pdGlhbCBxdWVzdGlvbnMgd2hpY2ggbWFrZSBzb21lIHNlbnNlCnRvIG1lLCBidXQgdGhlc2UgZG8gbm90IG5lY2Vzc2FyaWx5IG1hdGNoIHRoZSBzZXQgb2YgcXVlc3Rpb25zIHdoaWNoCmFyZSBtb3N0IHByZXNzaW5nLiAgSSBhbSBob3BpbmcgdG8gcHVsbCBib3RoIG9mIHRoZXNlIHNldHMgb2YKcXVlcmllcyBpbiBvbmUuCgpCZWZvcmUgZXh0cmFjdGluZyB0aGVzZSBncm91cHMgb2YgcXVlcmllcywgbGV0IHVzIGludm9rZSB0aGUKYWxsX3BhaXJ3aXNlKCkgZnVuY3Rpb24gYW5kIGdldCBhbGwgb2YgdGhlIGxpa2VseSBjb250cmFzdHMgYWxvbmcgd2l0aApvbmUgb3IgbW9yZSBleHRyYXMgdGhhdCBtaWdodCBwcm92ZSB1c2VmdWwgKHRoZSAnZXh0cmEnIGFyZ3VtZW50KS4KCiMjIyBDb21iaW5lZCBVOTM3IGFuZCBNYWNyb3BoYWdlczogQ29tcGFyZSBkcnVnIGVmZmVjdHMKCldoZW4gd2UgaGF2ZSB0aGUgdTkzNyBjZWxscyBpbiB0aGUgc2FtZSBkYXRhc2V0IGFzIHRoZSBtYWNyb3BoYWdlcywKdGhhdCBwcm92aWRlcyBhbiBpbnRlcmVzdGluZyBvcHBvcnR1bml0eSB0byBzZWUgaWYgd2UgY2FuIG9ic2VydmUKZHJ1Zy1kZXBlbmRhbnQgZWZmZWN0cyB3aGljaCBhcmUgc2hhcmVkIGFjcm9zcyBib3RoIGNlbGwgdHlwZXMuCgpgYGB7ciBib3RoX3R5cGVzX2RydWd9CmRydWdfZGUgPC0gYWxsX3BhaXJ3aXNlKGFsbF9odW1hbiwgZmlsdGVyID0gVFJVRSwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIikKZHJ1Z190YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIGRydWdfZGUsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3RtcmMyX21hY3JvcGhhZ2VfZHJ1Z19jb21wYXJpc29uLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMjIENvbWJpbmVkIFU5MzcgYW5kIE1hY3JvcGhhZ2VzOiBjb21wYXJlIGNlbGwgdHlwZXMKClRoZXJlIGFyZSBhIGNvdXBsZSBvZiB3YXlzIG9uZSBtaWdodCB3YW50IHRvIGRpcmVjdGx5IGNvbXBhcmUgdGhlIHR3bwpjZWxsIHR5cGVzLgoKKiBHaXZlbiB0aGF0IHRoZSB2YXJpYW5jZSBiZXR3ZWVuIHRoZSB0d28gY2VsbHR5cGVzIGlzIHNvIGh1Z2UsIGp1c3QKICBjb21wYXJlIGFsbCBzYW1wbGVzLgoqIE9uZSBtaWdodCB3YW50IHRvIGNvbXBhcmUgdGhlbSB3aXRoIHRoZSBpbnRlcmFjdGlvbiBlZmZlY3RzIG9mIGRydWcvenltb2RlbWUuCgpgYGB7ciBib3RoX3R5cGVzX2NvbXBhcmV9CnR5cGVfZGUgPC0gYWxsX3BhaXJ3aXNlKGFsbF9odW1hbl90eXBlcywgZmlsdGVyID0gVFJVRSwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIikKdHlwZV90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIHR5cGVfZGUsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3RtcmMyX21hY3JvcGhhZ2VfdHlwZV9jb21wYXJpc29uLXZ7dmVyfS54bHN4IikpCmBgYAoKR2l2ZW4gdGhlIGFib3ZlIGV4cGxpY2l0IGNvbXBhcmlzb24gb2YgYWxsIHNhbXBsZXMgY29tcHJpc2luZyB0aGUgdHdvCmNlbGwgdHlwZXMsIG5vdyBsZXQgdXMgbG9vayBhdCB0aGUgZHJ1ZyB0cmVhdG1lbnQrenltb2RlbWUgc3RhdHVzIHdpdGgKYWxsIHNhbXBsZXMsIG1hY3JvcGhhZ2VzIGFuZCBVOTM3LgoKYGBge3IgYWxsX3NhbXBsZXNfenltb190eXBlfQp0eXBlX3p5bW9fZGUgPC0gYWxsX3BhaXJ3aXNlKHR5cGVfenltbywgZmlsdGVyID0gVFJVRSwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIikKdHlwZV96eW1vX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgdHlwZV96eW1vX2RlLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC90bXJjMl9tYWNyb3BoYWdlX3R5cGVfenltb19jb21wYXJpc29uLXZ7dmVyfS54bHN4IikpCgp0eXBlX2RydWdfZGUgPC0gYWxsX3BhaXJ3aXNlKHR5cGVfZHJ1ZywgZmlsdGVyID0gVFJVRSwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIikKdHlwZV9kcnVnX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgdHlwZV9kcnVnX2RlLAogICAgZXhjZWw9Z2x1ZTo6Z2x1ZSgiZXhjZWwvdG1yYzJfbWFjcm9waGFnZV90eXBlX2RydWdfY29tcGFyaXNvbi12e3Zlcn0ueGxzeCIpKQpgYGAKCmBgYHtyIGhzX2RlfQpoc19tYWNyX2RlIDwtIGFsbF9wYWlyd2lzZShoc19tYWNyLCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiLCBmaWx0ZXIgPSBUUlVFKQpoc19tYWNyX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgaHNfbWFjcl9kZSwKICAgIGtlZXBlcnMgPSB0bXJjMl9odW1hbl9rZWVwZXJzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9oc19tYWNyX2RydWdfenltb190YWJsZS12e3Zlcn0ueGxzeCIpKQojIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHRyYV9jb250cmFzdHMgPSBleHRyYSkKaHNfbWFjcl9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGhzX21hY3JfdGFibGUsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2hzX21hY3JfZHJ1Z196eW1vX3NpZy12e3Zlcn0ueGxzeCIpKQoKdTkzN19kZSA8LSBhbGxfcGFpcndpc2UodTkzN19leHB0LCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiLCBmaWx0ZXIgPSBUUlVFKQojIyBleHRyYV9jb250cmFzdHM9ZXh0cmEpCnU5MzdfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICB1OTM3X2RlLAogICAga2VlcGVycyA9IHRtcmMyX2h1bWFuX2tlZXBlcnMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3U5MzdfZHJ1Z196eW1vX3RhYmxlLXZ7dmVyfS54bHN4IikpCnU5Mzdfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICB1OTM3X3RhYmxlLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC91OTM3X2RydWdfenltb19zaWctdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIyMjIENvbXBhcmUgKG5vKVNiIHoyLjMvejIuMiB0cmVhdG1lbnRzIGFtb25nIG1hY3JvcGhhZ2VzCgpgYGB7ciBjb21wYXJlX2RydWdfejIzMjJ9CnVwc2V0X3Bsb3RzX2hzX21hY3IgPC0gdXBzZXRyX3NpZygKICAgIGhzX21hY3Jfc2lnLCBib3RoID0gVFJVRSwKICAgIGNvbnRyYXN0cyA9IGMoInoyM3NiX3ZzX3oyMnNiIiwgInoyM25vc2JfdnNfejIybm9zYiIpKQp1cHNldF9wbG90c19oc19tYWNyW1siYm90aCJdXQpncm91cHMgPC0gdXBzZXRfcGxvdHNfaHNfbWFjcltbImJvdGhfZ3JvdXBzIl1dCnNoYXJlZF9nZW5lcyA8LSBhdHRyKGdyb3VwcywgImVsZW1lbnRzIilbZ3JvdXBzW1syXV1dICU+JQogIGdzdWIocGF0dGVybiA9ICJeZ2VuZToiLCByZXBsYWNlbWVudCA9ICIiKQpsZW5ndGgoc2hhcmVkX2dlbmVzKQoKc2hhcmVkX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoc2hhcmVkX2dlbmVzKQpzaGFyZWRfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQpwcChmaWxlPSJpbWFnZXMvc2hhcmVkX2dlbmVzX2JwLnBuZyIpCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCmRldi5vZmYoKQpzaGFyZWRfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCgpkcnVnX2dlbmVzIDwtIGF0dHIoZ3JvdXBzLCAiZWxlbWVudHMiKVtncm91cHNbWyJ6MjNzYl92c196MjJzYiJdXV0gJT4lCiAgICBnc3ViKHBhdHRlcm4gPSAiXmdlbmU6IiwgcmVwbGFjZW1lbnQgPSAiIikKZHJ1Z29ubHlfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihkcnVnX2dlbmVzKQpkcnVnb25seV9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCmBgYAoKSSB3YW50IHRvIHRyeSBzb21ldGhpbmcsIGRpcmVjdGx5IGluY2x1ZGUgdGhlIHU5MzcgZGF0YSBpbiB0aGlzLi4uCgpgYGB7ciBhZGRfdTkzN30KYm90aF9zaWcgPC0gaHNfbWFjcl9zaWcKbmFtZXMoYm90aF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXSkgPC0gcGFzdGUwKCJtYWNyXyIsIG5hbWVzKGJvdGhfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV0pKQpuYW1lcyhib3RoX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV0pIDwtIHBhc3RlMCgibWFjcl8iLCBuYW1lcyhib3RoX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV0pKQp1OTM3X2Rlc2VxIDwtIHU5Mzdfc2lnW1siZGVzZXEiXV0KbmFtZXModTkzN19kZXNlcVtbInVwcyJdXSkgPC0gcGFzdGUwKCJ1OTM3XyIsIG5hbWVzKHU5MzdfZGVzZXFbWyJ1cHMiXV0pKQpuYW1lcyh1OTM3X2Rlc2VxW1siZG93bnMiXV0pIDwtIHBhc3RlMCgidTkzN18iLCBuYW1lcyh1OTM3X2Rlc2VxW1siZG93bnMiXV0pKQpib3RoX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dIDwtIGMoYm90aF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXSwgdTkzN19kZXNlcVtbInVwcyJdXSkKYm90aF9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dIDwtIGMoYm90aF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXSwgdTkzN19kZXNlcVtbImRvd25zIl1dKQpzdW1tYXJ5KGJvdGhfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV0pCgp1cHNldF9wbG90c19ib3RoIDwtIHVwc2V0cl9zaWcoCiAgICBib3RoX3NpZywgYm90aD1UUlVFLAogICAgY29udHJhc3RzPWMoIm1hY3JfejIzc2JfdnNfejIyc2IiLCAibWFjcl96MjNub3NiX3ZzX3oyMm5vc2IiLAogICAgICAgICAgICAgICAgInU5MzdfejIzc2JfdnNfejIyc2IiLCAidTkzN196MjNub3NiX3ZzX3oyMm5vc2IiKSkKdXBzZXRfcGxvdHNfYm90aCRib3RoCmBgYAoKCiMjIyMgQ29tcGFyZSBERSByZXN1bHRzIGZyb20gbWFjcm9waGFnZXMgYW5kIFU5Mzcgc2FtcGxlcwoKTG9va2luZyBhIGJpdCBtb3JlIGNsb3NlbHkgYXQgdGhlc2UsIEkgdGhpbmsgdGhlIHU5MzcgZGF0YSBpcyB0b28Kc3BhcnNlIHRvIGVmZmVjdGl2ZWx5IGNvbXBhcmUuCgpgYGB7ciBjb21wYXJlX2RlX3U5MzdfbWFjcm99Cm1hY3JfdTkzN19jb21wYXJpc29uIDwtIGNvbXBhcmVfZGVfcmVzdWx0cyhoc19tYWNyX3RhYmxlLCB1OTM3X3RhYmxlKQptYWNyX3U5MzdfY29tcGFyaXNvbiRsZmNfaGVhdAoKbWFjcl91OTM3X3Zlbm5zIDwtIGNvbXBhcmVfc2lnbmlmaWNhbnRfY29udHJhc3RzKGhzX21hY3Jfc2lnLCBzZWNvbmRfc2lnX3RhYmxlcyA9IHU5Mzdfc2lnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJhc3RzID0gInoyM3NiX3ZzX3oyM25vc2IiKQptYWNyX3U5MzdfdmVubnMkdXBfcGxvdAptYWNyX3U5MzdfdmVubnMkZG93bl9wbG90CgptYWNyX3U5MzdfdmVubnNfdjIgPC0gY29tcGFyZV9zaWduaWZpY2FudF9jb250cmFzdHMoaHNfbWFjcl9zaWcsIHNlY29uZF9zaWdfdGFibGVzID0gdTkzN19zaWcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cmFzdHMgPSAiejIyc2JfdnNfejIybm9zYiIpCm1hY3JfdTkzN192ZW5uc192MiR1cF9wbG90Cm1hY3JfdTkzN192ZW5uc192MiRkb3duX3Bsb3QKCm1hY3JfdTkzN192ZW5uc192MyA8LSBjb21wYXJlX3NpZ25pZmljYW50X2NvbnRyYXN0cyhoc19tYWNyX3NpZywgc2Vjb25kX3NpZ190YWJsZXMgPSB1OTM3X3NpZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyYXN0cyA9ICJzYl92c191bmluZiIpCm1hY3JfdTkzN192ZW5uc192MyR1cF9wbG90Cm1hY3JfdTkzN192ZW5uc192MyRkb3duX3Bsb3QKYGBgCgojIyMgQ29tcGFyZSBtYWNyb3BoYWdlL3U5Mzcgd2l0aCByZXNwZWN0IHRvIHoyLjMvejIuMgoKYGBge3IgbWFjcl91OTM3X3oyM3oyMn0KY29tcGFyaXNvbl9kZiA8LSBtZXJnZShoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyM3NiX3ZzX3oyMnNiIl1dLAogICAgICAgICAgICAgICAgICAgICAgIHU5MzdfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfejIyc2IiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAicm93Lm5hbWVzIikKbWFjcnU5MzdfejIzejIyX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihjb21wYXJpc29uX2RmWywgYygiZGVzZXFfbG9nZmMueCIsICJkZXNlcV9sb2dmYy55IildKQptYWNydTkzN196MjN6MjJfcGxvdCRzY2F0dGVyCgpjb21wYXJpc29uX2RmIDwtIG1lcmdlKGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dLAogICAgICAgICAgICAgICAgICAgICAgIHU5MzdfdGFibGVbWyJkYXRhIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dLAogICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInJvdy5uYW1lcyIpCm1hY3J1OTM3X3oyM3oyMl9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoY29tcGFyaXNvbl9kZlssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKbWFjcnU5MzdfejIzejIyX3Bsb3Qkc2NhdHRlcgpgYGAKCiMjIyMgQWRkIGRvbm9yIHRvIHRoZSBjb250cmFzdHMsIG5vIHN2YQoKYGBge3Igbm9wb3dlcl9ub3N2YX0Kbm9fcG93ZXJfZmFjdCA8LSBwYXN0ZTAocERhdGEoaHNfbWFjcilbWyJkb25vciJdXSwgIl8iLAogICAgICAgICAgICAgICAgICAgICAgICBwRGF0YShoc19tYWNyKVtbImNvbmRpdGlvbiJdXSkKaHNfbm9wb3dlciA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGhzX21hY3IsIGZhY3QgPSBub19wb3dlcl9mYWN0KQpoc19ub3Bvd2VyIDwtIHN1YnNldF9leHB0KGhzX25vcG93ZXIsIHN1YnNldD0ibWFjcm9waGFnZXp5bW9kZW1lIT0nbm9uZSciKQpoc19ub3Bvd2VyX25vc3ZhX2RlIDwtIGFsbF9wYWlyd2lzZShoc19ub3Bvd2VyLCBtb2RlbF9iYXRjaCA9IEZBTFNFLCBmaWx0ZXIgPSBUUlVFKQpub3Bvd2VyX2tlZXBlcnMgPC0gbGlzdCgKICAgICJkMDFfenltbyIgPSBjKCJkMDFpbmZ6MjMiLCAiZDAxaW5mejIyIiksCiAgICAiZDAxX3NienltbyIgPSBjKCJkMDFpbmZzYnoyMyIsICJkMDFpbmZzYnoyMiIpLAogICAgImQwMl96eW1vIiA9IGMoImQwMmluZnoyMyIsICJkMDJpbmZ6MjIiKSwKICAgICJkMDJfc2J6eW1vIiA9IGMoImQwMmluZnNiejIzIiwgImQwMmluZnNiejIyIiksCiAgICAiZDA5X3p5bW8iID0gYygiZDA5aW5mejIzIiwgImQwOWluZnoyMiIpLAogICAgImQwOV9zYnp5bW8iID0gYygiZDA5aW5mc2J6MjMiLCAiZDA5aW5mc2J6MjIiKSwKICAgICJkODFfenltbyIgPSBjKCJkODFpbmZ6MjMiLCAiZDgxaW5mejIyIiksCiAgICAiZDgxX3NienltbyIgPSBjKCJkODFpbmZzYnoyMyIsICJkODFpbmZzYnoyMiIpKQpoc19ub3Bvd2VyX25vc3ZhX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgaHNfbm9wb3dlcl9ub3N2YV9kZSwga2VlcGVycyA9IG5vcG93ZXJfa2VlcGVycywKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvaHNfbm9wb3dlcl90YWJsZS12e3Zlcn0ueGxzeCIpKQojIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHRyYV9jb250cmFzdHMgPSBleHRyYSkKaHNfbm9wb3dlcl9ub3N2YV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGhzX25vcG93ZXJfbm9zdmFfdGFibGUsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2hzX25vcG93ZXJfbm9zdmFfc2lnLXZ7dmVyfS54bHN4IikpCgpkMDFkMDJfenltb19ub3N2YV9jb21wIDwtIG1lcmdlKGhzX25vcG93ZXJfbm9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDAxX3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgaHNfbm9wb3dlcl9ub3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDJfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICBieT0icm93Lm5hbWVzIikKZDAxMDJfenltb19ub3N2YV9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoZDAxZDAyX3p5bW9fbm9zdmFfY29tcFssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKZDAxMDJfenltb19ub3N2YV9wbG90JHNjYXR0ZXIKZDAxMDJfenltb19ub3N2YV9wbG90JGNvcnJlbGF0aW9uCmQwMTAyX3p5bW9fbm9zdmFfcGxvdCRsbV9yc3EKCmQwOWQ4MV96eW1vX25vc3ZhX2NvbXAgPC0gbWVyZ2UoaHNfbm9wb3dlcl9ub3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDlfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICBoc19ub3Bvd2VyX25vc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQ4MV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgIGJ5PSJyb3cubmFtZXMiKQpkMDk4MV96eW1vX25vc3ZhX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihkMDlkODFfenltb19ub3N2YV9jb21wWywgYygiZGVzZXFfbG9nZmMueCIsICJkZXNlcV9sb2dmYy55IildKQpkMDk4MV96eW1vX25vc3ZhX3Bsb3Qkc2NhdHRlcgpkMDk4MV96eW1vX25vc3ZhX3Bsb3QkY29ycmVsYXRpb24KZDA5ODFfenltb19ub3N2YV9wbG90JGxtX3JzcQoKZDAxZDgxX3p5bW9fbm9zdmFfY29tcCA8LSBtZXJnZShoc19ub3Bvd2VyX25vc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwMV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhzX25vcG93ZXJfbm9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDgxX3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnk9InJvdy5uYW1lcyIpCmQwMTgxX3p5bW9fbm9zdmFfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGQwMWQ4MV96eW1vX25vc3ZhX2NvbXBbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCmQwMTgxX3p5bW9fbm9zdmFfcGxvdCRzY2F0dGVyCmQwMTgxX3p5bW9fbm9zdmFfcGxvdCRjb3JyZWxhdGlvbgpkMDE4MV96eW1vX25vc3ZhX3Bsb3QkbG1fcnNxCgp1cHNldF9wbG90c19ub3N2YSA8LSB1cHNldHJfc2lnKGhzX25vcG93ZXJfbm9zdmFfc2lnLCBib3RoPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJhc3RzPWMoImQwMV96eW1vIiwgImQwMl96eW1vIiwgImQwOV96eW1vIiwgImQ4MV96eW1vIikpCnVwc2V0X3Bsb3RzX25vc3ZhJHVwCnVwc2V0X3Bsb3RzX25vc3ZhJGRvd24KdXBzZXRfcGxvdHNfbm9zdmEkYm90aAojIyBUaGUgN3RoIGVsZW1lbnQgaW4gdGhlIGJvdGggZ3JvdXBzIGxpc3QgaXMgdGhlIHNldCBzaGFyZWQgYW1vbmcgYWxsIGRvbm9ycy4KIyMgSSBkb24ndCBmZWVsIGxpa2Ugd3JpdGluZyBvdXQgeDp5Ono6YQpncm91cHMgPC0gdXBzZXRfcGxvdHNfbm9zdmFbWyJib3RoX2dyb3VwcyJdXQpzaGFyZWRfZ2VuZXMgPC0gYXR0cihncm91cHMsICJlbGVtZW50cyIpW2dyb3Vwc1tbN11dXSAlPiUKICBnc3ViKHBhdHRlcm4gPSAiXmdlbmU6IiwgcmVwbGFjZW1lbnQgPSAiIikKc2hhcmVkX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoc2hhcmVkX2dlbmVzKQpzaGFyZWRfZ3AkcHZhbHVlX3Bsb3RzJE1GCnNoYXJlZF9ncCRwdmFsdWVfcGxvdHMkQlAKc2hhcmVkX2dwJHB2YWx1ZV9wbG90cyRSRUFDCnNoYXJlZF9ncCRwdmFsdWVfcGxvdHMkV1AKYGBgCgojIyMjIEFkZCBkb25vciB0byB0aGUgY29udHJhc3RzLCBzdmEKCmBgYHtyIGRvbm9yX2RydWdfenltb19ldGN9CmhzX25vcG93ZXJfc3ZhX2RlIDwtIGFsbF9wYWlyd2lzZShoc19ub3Bvd2VyLCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiLCBmaWx0ZXIgPSBUUlVFKQpub3Bvd2VyX2tlZXBlcnMgPC0gbGlzdCgKICAgICJkMDFfenltbyIgPSBjKCJkMDFpbmZ6MjMiLCAiZDAxaW5mejIyIiksCiAgICAiZDAxX3NienltbyIgPSBjKCJkMDFpbmZzYnoyMyIsICJkMDFpbmZzYnoyMiIpLAogICAgImQwMl96eW1vIiA9IGMoImQwMmluZnoyMyIsICJkMDJpbmZ6MjIiKSwKICAgICJkMDJfc2J6eW1vIiA9IGMoImQwMmluZnNiejIzIiwgImQwMmluZnNiejIyIiksCiAgICAiZDA5X3p5bW8iID0gYygiZDA5aW5mejIzIiwgImQwOWluZnoyMiIpLAogICAgImQwOV9zYnp5bW8iID0gYygiZDA5aW5mc2J6MjMiLCAiZDA5aW5mc2J6MjIiKSwKICAgICJkODFfenltbyIgPSBjKCJkODFpbmZ6MjMiLCAiZDgxaW5mejIyIiksCiAgICAiZDgxX3NienltbyIgPSBjKCJkODFpbmZzYnoyMyIsICJkODFpbmZzYnoyMiIpKQpoc19ub3Bvd2VyX3N2YV90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIGhzX25vcG93ZXJfc3ZhX2RlLCBrZWVwZXJzID0gbm9wb3dlcl9rZWVwZXJzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9oc19ub3Bvd2VyX3RhYmxlLXZ7dmVyfS54bHN4IikpCiMjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4dHJhX2NvbnRyYXN0cyA9IGV4dHJhKQpoc19ub3Bvd2VyX3N2YV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGhzX25vcG93ZXJfc3ZhX3RhYmxlLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9oc19ub3Bvd2VyX3N2YV9zaWctdnt2ZXJ9Lnhsc3giKSkKCmQwMWQwMl96eW1vX3N2YV9jb21wIDwtIG1lcmdlKGhzX25vcG93ZXJfc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwMV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgIGhzX25vcG93ZXJfc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwMl96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgIGJ5PSJyb3cubmFtZXMiKQpkMDEwMl96eW1vX3N2YV9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoZDAxZDAyX3p5bW9fc3ZhX2NvbXBbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCmQwMTAyX3p5bW9fc3ZhX3Bsb3Qkc2NhdHRlcgpkMDEwMl96eW1vX3N2YV9wbG90JGNvcnJlbGF0aW9uCmQwMTAyX3p5bW9fc3ZhX3Bsb3QkbG1fcnNxCgpkMDlkODFfenltb19zdmFfY29tcCA8LSBtZXJnZShoc19ub3Bvd2VyX3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDlfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICBoc19ub3Bvd2VyX3N2YV90YWJsZVtbImRhdGEiXV1bWyJkODFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICBieT0icm93Lm5hbWVzIikKZDA5ODFfenltb19zdmFfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGQwOWQ4MV96eW1vX3N2YV9jb21wWywgYygiZGVzZXFfbG9nZmMueCIsICJkZXNlcV9sb2dmYy55IildKQpkMDk4MV96eW1vX3N2YV9wbG90JHNjYXR0ZXIKZDA5ODFfenltb19zdmFfcGxvdCRjb3JyZWxhdGlvbgpkMDk4MV96eW1vX3N2YV9wbG90JGxtX3JzcQoKZDAxZDgxX3p5bW9fc3ZhX2NvbXAgPC0gbWVyZ2UoaHNfbm9wb3dlcl9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDAxX3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhzX25vcG93ZXJfc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQ4MV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieT0icm93Lm5hbWVzIikKZDAxODFfenltb19zdmFfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGQwMWQ4MV96eW1vX3N2YV9jb21wWywgYygiZGVzZXFfbG9nZmMueCIsICJkZXNlcV9sb2dmYy55IildKQpkMDE4MV96eW1vX3N2YV9wbG90JHNjYXR0ZXIKZDAxODFfenltb19zdmFfcGxvdCRjb3JyZWxhdGlvbgpkMDE4MV96eW1vX3N2YV9wbG90JGxtX3JzcQoKdXBzZXRfcGxvdHNfc3ZhIDwtIHVwc2V0cl9zaWcoaHNfbm9wb3dlcl9zdmFfc2lnLCBib3RoPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJhc3RzPWMoImQwMV96eW1vIiwgImQwMl96eW1vIiwgImQwOV96eW1vIiwgImQ4MV96eW1vIikpCnVwc2V0X3Bsb3RzX3N2YSR1cAp1cHNldF9wbG90c19zdmEkZG93bgp1cHNldF9wbG90c19zdmEkYm90aAojIyBUaGUgN3RoIGVsZW1lbnQgaW4gdGhlIGJvdGggZ3JvdXBzIGxpc3QgaXMgdGhlIHNldCBzaGFyZWQgYW1vbmcgYWxsIGRvbm9ycy4KIyMgSSBkb24ndCBmZWVsIGxpa2Ugd3JpdGluZyBvdXQgeDp5Ono6YQpncm91cHMgPC0gdXBzZXRfcGxvdHNfc3ZhW1siYm90aF9ncm91cHMiXV0Kc2hhcmVkX2dlbmVzIDwtIGF0dHIoZ3JvdXBzLCAiZWxlbWVudHMiKVtncm91cHNbWzddXV0gJT4lCiAgZ3N1YihwYXR0ZXJuID0gIl5nZW5lOiIsIHJlcGxhY2VtZW50ID0gIiIpCnNoYXJlZF9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNoYXJlZF9nZW5lcykKc2hhcmVkX2dwJHB2YWx1ZV9wbG90cyRNRgpzaGFyZWRfZ3AkcHZhbHVlX3Bsb3RzJEJQCnNoYXJlZF9ncCRwdmFsdWVfcGxvdHMkUkVBQwpzaGFyZWRfZ3AkcHZhbHVlX3Bsb3RzJFdQCmBgYAoKIyMjIERvbm9yIGNvbXBhcmlzb24KCmBgYHtyIGRvbm9yX2RlfQpkb25vcl9kZSA8LSBhbGxfcGFpcndpc2UoaHNfZG9ub3JzLCBtb2RlbF9iYXRjaD0ic3Zhc2VxIiwgZmlsdGVyPVRSVUUpCmRvbm9yX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgZG9ub3JfZGUsCiAgICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC9kb25vcl90YWJsZXMtdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIyMjIFByaW1hcnkgcXVlcnkgY29udHJhc3RzCgpUaGUgZmluYWwgY29udHJhc3QgaW4gdGhpcyBsaXN0IGlzIGludGVyZXN0aW5nIGJlY2F1c2UgaXQgZGVwZW5kcyBvbgp0aGUgZXh0cmEgY29udHJhc3RzIGFwcGxpZWQgdG8gdGhlIGFsbF9wYWlyd2lzZSgpIGFib3ZlLiAgSW4gbXkgd2F5IG9mCnRoaW5raW5nLCB0aGUgcHJpbWFyeSBjb21wYXJpc29ucyB0byBjb25zaWRlciBhcmUgZWl0aGVyIGNyb3NzLWRydWcgb3IKY3Jvc3Mtc3RyYWluLCBidXQgbm90IGJvdGguICBIb3dldmVyIEkgdGhpbmsgaW4gYXQgbGVhc3QgYSBmZXcKaW5zdGFuY2VzIE9sZ2EgaXMgaW50ZXJlc3RlZCBpbiBzdHJhaW4rZHJ1ZyAvIHVuaW5mZWN0ZWQrbm9kcnVnLgoKIyMjIyBXcml0ZSBjb250cmFzdCByZXN1bHRzCgpOb3cgbGV0IHVzIHdyaXRlIG91dCB0aGUgeGxzeCBmaWxlIGNvbnRhaW5pbmcgdGhlIGFib3ZlIGNvbnRyYXN0cy4KVGhlIGZpbGUgd2l0aCB0aGUgc3VmZml4IF90YWJsZS12ZXJzaW9uIHdpbGwgdGhlcmVmb3JlIGNvbnRhaW4gYWxsCmdlbmVzIGFuZCB0aGUgZmlsZSB3aXRoIHRoZSBzdWZmaXggX3NpZy12ZXJzaW9uIHdpbGwgY29udGFpbiBvbmx5CnRob3NlIGRlZW1lZCBzaWduaWZpY2FudCB2aWEgb3VyIGRlZmF1bHQgY3JpdGVyaWEgb2YgREVTZXEyIHxsb2dGQ3wgPj0gMS4wCmFuZCBhZGp1c3RlZCBwLXZhbHVlIDw9IDAuMDUuCgpgYGB7ciBtYWtlX3RhYmxlc190bXJjMn0KaHNfbWFjcl90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIGhzX21hY3JfZGUsCiAgICBrZWVwZXJzID0gdG1yYzJfaHVtYW5fa2VlcGVycywKICAgIGV4Y2VsPWdsdWU6OmdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfaHVtYW5fdGFibGUtdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGhzX21hY3JfdGFibGUsCiAgICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC9tYWNyb3BoYWdlX2h1bWFuX3NpZy12e3Zlcn0ueGxzeCIpKQoKdTkzN190YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIHU5MzdfZGUsCiAgICBrZWVwZXJzID0gdG1yYzJfaHVtYW5fa2VlcGVycywKICAgIGV4Y2VsPWdsdWU6OmdsdWUoImV4Y2VsL3U5MzdfaHVtYW5fdGFibGUtdnt2ZXJ9Lnhsc3giKSkKdTkzN19zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIHU5MzdfdGFibGUsCiAgICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC91OTM3X2h1bWFuX3NpZy12e3Zlcn0ueGxzeCIpKQpgYGAKCiMgT3ZlciByZXByZXNlbnRhdGlvbiBzZWFyY2hlcwoKSSBkZWNpZGVkIHRvIG1ha2Ugb25lIGluaXRpYWxseSBzbWFsbCwgYnV0IEkgdGhpbmsgcXVpY2tseSBiaWcgY2hhbmdlCnRvIHRoZSBvcmdhbml6YXRpb24gb2YgdGhpcyBkb2N1bWVudDogIEkgYW0gbW92aW5nIHRoZSBHU0VBIHNlYXJjaGVzCnVwIHRvIGltbWVkaWF0ZWx5IGFmdGVyIHRoZSBERS4gIEkgd2lsbCB0aGVuIG1vdmUgdGhlIHBsb3RzIG9mIHRoZQpncHJvZmlsZXIgcmVzdWx0cyB0byBpbW1lZGlhdGVseSBhZnRlciB0aGUgdmFyaW91cyB2b2xjYW5vIHBsb3RzIHNvCnRoYXQgaXQgaXMgZWFzaWVyIHRvIGludGVycHJldCB0aGVtLgoKYGBge3Igb3Zlcl9yZXByZXNlbnRfZGF0YX0KYWxsX2dwIDwtIGFsbF9ncHJvZmlsZXIoaHNfbWFjcl9zaWcpCmBgYAoKIyBQbG90IGNvbnRyYXN0cyBvZiBpbnRlcmVzdAoKT25lIHN1Z2dlc3Rpb24gSSByZWNlaXZlZCByZWNlbnRseSB3YXMgdG8gc2V0IHRoZSBheGVzIGZvciB0aGVzZQp2b2xjYW5vIHBsb3RzIHRvIGJlIHN0YXRpYyByYXRoZXIgdGhhbiBsZXQgZ2dwbG90IGNob29zZSBpdHMgb3duLiAgSQphbSBhc3N1bWluZyB0aGlzIGlzIG9ubHkgcmVsZXZhbnQgZm9yIHBhaXJzIG9mIGNvbnRyYXN0cywgYnV0IHRoYXQKbWlnaHQgbm90IGJlIHRydWUuCgojIyBJbmRpdmlkdWFsIHp5bW9kZW1lcyB2cy4gdW5pbmZlY3RlZAoKYGBge3IgaHNfbWFjcm9waGFnZV9zaWdfZ2VuZXNfMjMyMnZzdW5pbmZ9CnoyM25vc2JfdnNfdW5pbmZfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fZGUoCiAgICB0YWJsZSA9IGhzX21hY3JvcGhhZ2VfdGFibGVbWyJkYXRhIl1dW1siejIzbm9zYl92c191bmluZiJdXSwKICAgIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogICAgc2hhcGVzX2J5X3N0YXRlID0gRkFMU0UsIGNvbG9yX2J5ID0gImZjIiwgIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jc3ltYm9sIikKCnBsb3RseTo6Z2dwbG90bHkoejIzbm9zYl92c191bmluZl92b2xjYW5vJHBsb3QpCnoyMm5vc2JfdnNfdW5pbmZfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fZGUoCiAgICB0YWJsZSA9IGhzX21hY3JvcGhhZ2VfdGFibGVbWyJkYXRhIl1dW1siejIybm9zYl92c191bmluZiJdXSwKICAgIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogICAgc2hhcGVzX2J5X3N0YXRlID0gRkFMU0UsIGNvbG9yX2J5ID0gImZjIiwgIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jc3ltYm9sIikKcGxvdGx5OjpnZ3Bsb3RseSh6MjJub3NiX3ZzX3VuaW5mX3ZvbGNhbm8kcGxvdCkKYGBgCgojIyMgWnltb2RlbWUgMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZAoKYGBge3IgenltbzIzX3ZzX3VuaW5mfQp6MjNub3NiX3ZzX3VuaW5mX3ZvbGNhbm8kcGxvdCArCiAgeGxpbSgtMTAsIDI1KSArCiAgeWxpbSgwLCA0MCkKCnBwKGZpbGU9ImltYWdlcy96MjNfdW5pbmZfcmVhY3RvbWVfdXAucG5nIiwgaW1hZ2U9YWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0sIGhlaWdodD0xMiwgd2lkdGg9OSkKIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siS0VHRyJdXQojIyBLRUdHLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIldQIl1dCiMjIFdpa2lQYXRod2F5cywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfdXAiXV1bWyJpbnRlcmFjdGl2ZV9wbG90cyJdXVtbIldQIl1dCgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmBgYAoKYGBge3IgejIybm9zYl92c191bmluZl9wbG90c30KejIybm9zYl92c191bmluZl92b2xjYW5vJHBsb3QgKwogIHhsaW0oLTEwLCAyNSkgKwogIHlsaW0oMCwgNDApCgpwcChmaWxlPSJpbWFnZXMvejIyX3VuaW5mX3JlYWN0b21lX3VwLnBuZyIsIGltYWdlPWFsbF9ncFtbInoyMm5vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dLCBoZWlnaHQ9MTIsIHdpZHRoPTkpCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMiB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIybm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMiB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIybm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMiB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIybm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIldQIl1dCiMjIFdpa2lQYXRod2F5cywgenltb2RlbWUyLjIgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCgphbGxfZ3BbWyJ6MjJub3NiX3ZzX3VuaW5mX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMiB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjJub3NiX3ZzX3VuaW5mX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjIgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIybm9zYl92c191bmluZl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmBgYAoKQ2hlY2sgdGhhdCBteSBwZXJjZXB0aW9uIG9mIHRoZSBudW1iZXIgb2Ygc2lnbmlmaWNhbnQgdXAvZG93biBnZW5lcwptYXRjaGVzIHdoYXQgdGhlIHRhYmxlL3Zlbm4gc2F5cy4KCmBgYHtyIGNoZWNrX3NpZ192ZW5uMDF9CnNoYXJlZCA8LSBWZW5uZXJhYmxlOjpWZW5uKGxpc3QoImRydWciID0gcm93bmFtZXMoaHNfbWFjcm9waGFnZV9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM3NiX3ZzX3VuaW5mIl1dKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibm9kcnVnIiA9IHJvd25hbWVzKGhzX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjNub3NiX3ZzX3VuaW5mIl1dKSkpCnBwKGZpbGU9ImltYWdlcy96MjNfdnNfdW5pbmZfdmVubl91cC5wbmciKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKZGV2Lm9mZigpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQojIyBJIHNlZSA5MTAgejIzc2IvdW5pbmYgYW5kIDY3MCBubyB6MjNub3NiL3VuaW5mIGdlbmVzIGluIHRoZSB2ZW5uIGRpYWdyYW0uCmxlbmd0aChzaGFyZWRASW50ZXJzZWN0aW9uU2V0c1tbIjEwIl1dKSArIGxlbmd0aChzaGFyZWRASW50ZXJzZWN0aW9uU2V0c1tbIjExIl1dKQpkaW0oaHNfbWFjcm9waGFnZV9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM3NiX3ZzX3VuaW5mIl1dKQoKc2hhcmVkIDwtIFZlbm5lcmFibGU6OlZlbm4obGlzdCgiZHJ1ZyIgPSByb3duYW1lcyhoc19tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIyc2JfdnNfdW5pbmYiXV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJub2RydWciID0gcm93bmFtZXMoaHNfbWFjcm9waGFnZV9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyMm5vc2JfdnNfdW5pbmYiXV0pKSkKcHAoZmlsZT0iaW1hZ2VzL3oyMl92c191bmluZl92ZW5uX3VwLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCgpsZW5ndGgoc2hhcmVkQEludGVyc2VjdGlvblNldHNbWyIxMCJdXSkgKyBsZW5ndGgoc2hhcmVkQEludGVyc2VjdGlvblNldHNbWyIxMSJdXSkKZGltKGhzX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjJzYl92c191bmluZiJdXSkKYGBgCgoqTm90ZSB0byBzZWxmKjogVGhlcmUgaXMgYW4gZXJyb3IgaW4gbXkgdm9sY2FubyBwbG90IGNvZGUgd2hpY2ggdGFrZXMKZWZmZWN0IHdoZW4gdGhlIG51bWVyYXRvciBhbmQgZGVub21pbmF0b3Igb2YgdGhlIGFsbF9wYWlyd2lzZQpjb250cmFzdHMgYXJlIGRpZmZlcmVudCB0aGFuIHRob3NlIGluIGNvbWJpbmVfZGVfdGFibGVzLiAgSXQgaXMKcHV0dGluZyB0aGUgdXBzL2Rvd25zIG9uIHRoZSBjb3JyZWN0IHNpZGVzIG9mIHRoZSBwbG90LCBidXQgY2FsbGluZwp0aGUgZG93biBnZW5lcyAndXAnIGFuZCB2aWNlLXZlcnNhLiAgVGhlIHJlYXNvbiBmb3IgdGhpcyBpcyB0aGF0IEkgZGlkCmEgY2hlY2sgZm9yIHRoaXMgaGFwcGVuaW5nLCBidXQgdXNlZCB0aGUgd3JvbmcgYXJndW1lbnQgdG8gaGFuZGxlIGl0LgoKQSBsaWtlbHkgYml0IG9mIHRleHQgZm9yIHRoZXNlIHZvbGNhbm8gcGxvdHM6CgpUaGUgc2V0IG9mIGdlbmVzIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBiZXR3ZWVuIHRoZSB6eW1vZGVtZSAyLjMKYW5kIHVuaW5mZWN0ZWQgc2FtcGxlcyB3aXRob3V0IGRydWdlIHRyZWF0bWVudCB3YXMgcXVhbnRpZmllZCB3aXRoCkRFU2VxMiBhbmQgaW5jbHVkZWQgc3Vycm9nYXRlIGVzdGltYXRlcyBmcm9tIFNWQS4gIEdpdmVuIHRoZSBjcml0ZXJpYQpvZiBzaWduaWZpY2FuY2Ugb2YgYSBhYnMobG9nRkMpID49IDEuMCBhbmQgZmFsc2UgZGlzY292ZXJ5IHJhdGUKYWRqdXN0ZWQgcC12YWx1ZSA8PSAwLjA1LCA2NzAgZ2VuZXMgd2VyZSBvYnNlcnZlZCBhcyBzaWduaWZpY2FudGx5CmluY3JlYXNlZCBiZXR3ZWVuIHRoZSBpbmZlY3RlZCBhbmQgdW5pbmZlY3RlZCBzYW1wbGVzIGFuZCAzODYgd2VyZQpvYnNlcnZlZCBhcyBkZWNyZWFzZWQuIFRoZSBtb3N0IGluY3JlYXNlZCBnZW5lcyBmcm9tIHRoZSB1bmluZmVjdGVkCnNhbXBsZXMgaW5jbHVkZSBzb21lIHdoaWNoIGFyZSBwb3RlbnRpYWxseSBpbmRpY2F0aXZlIG9mIGEgc3Ryb25nCmlubmF0ZSBpbW11bmUgcmVzcG9uc2UgYW5kIHRoZSBpbmZsYW1tYXRvcnkgcmVzcG9uc2UuCgpJbiBjb250cmFzdCwgd2hlbiB0aGUgc2V0IG9mIGdlbmVzIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBiZXR3ZWVuCnRoZSB6eW1vZGVtZSAyLjIgYW5kIHVuaW5mZWN0ZWQgc2FtcGxlcyB3YXMgdmlzdWFsaXplZCwgb25seSA3IGdlbmVzCndlcmUgb2JzZXJ2ZWQgYXMgZGVjcmVhc2VkIGFuZCA0MzUgaW5jcmVhc2VkLiAgVGhlIGluZmxhbW1hdG9yeQpyZXNwb25zZSB3YXMgc2lnbmlmaWNhbnRseSBsZXNzIGFwcGFyZW50IGluIHRoaXMgc2V0LCBidXQgaW5zdGVhZAppbmNsdWRlZCBnZW5lcyByZWxhdGVkIHRvIHRyYW5zcG9ydGVyIGFjdGl2aXR5IGFuZCBveGlkb3JlZHVjdGFzZXMuCgojIyBEaXJlY3Qgenltb2RlbWUgY29tcGFyaXNvbnMKCkFuIG9ydGhvZ29uYWwgY29tcGFyaXNvbiB0byB0aGF0IHBlcmZvcm1lZCBhYm92ZSBpcyB0byBkaXJlY3RseQpjb21wYXJlIHRoZSB6eW1vZGVtZSAyLjMgYW5kIDIuMiBzYW1wbGVzIHdpdGggYW5kIHdpdGhvdXQgYW50aW1vbmlhbAp0cmVhdG1lbnQuCgpgYGB7ciB6MjJ6MjNfY29tcGFyaXNvbl9wbG90c30KejIzbm9zYl92c196MjJub3NiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2RlKAogICAgdGFibGUgPSBoc19tYWNyb3BoYWdlX3RhYmxlW1siZGF0YSJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXSwKICAgIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogICAgc2hhcGVzX2J5X3N0YXRlID0gRkFMU0UsIGNvbG9yX2J5ID0gImZjIiwgIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jc3ltYm9sIikKcGxvdGx5OjpnZ3Bsb3RseSh6MjNub3NiX3ZzX3oyMm5vc2Jfdm9sY2FubyRwbG90KQoKejIzc2JfdnNfejIyc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fZGUoCiAgICB0YWJsZSA9IGhzX21hY3JvcGhhZ2VfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfejIyc2IiXV0sCiAgICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICAgIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIpCnBsb3RseTo6Z2dwbG90bHkoejIzc2JfdnNfejIyc2Jfdm9sY2FubyRwbG90KQpgYGAKCmBgYHtyIHoyM25vc2JfdnNfejIybm9zYl9wbG90c30KejIzbm9zYl92c196MjJub3NiX3ZvbGNhbm8kcGxvdCArCiAgeGxpbSgtMTAsIDEwKSArCiAgeWxpbSgwLCA2MCkKCnBwKGZpbGU9ImltYWdlcy96MjNub3NiX3ZzX3oyMm5vc2JfcmVhY3RvbWVfdXAucG5nIiwgaW1hZ2U9YWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXSwgaGVpZ2h0PTEyLCB3aWR0aD05KQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIktFR0ciXV0KIyMgS0VHRywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJXUCJdXQojIyBXaWtpUGF0aHdheXMsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfdXAiXV1bWyJpbnRlcmFjdGl2ZV9wbG90cyJdXVtbIldQIl1dCgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmBgYAoKYGBge3IgejIzX3ZzX3oyMnNiX3Bsb3RzfQp6MjNzYl92c196MjJzYl92b2xjYW5vJHBsb3QgKwogIHhsaW0oLTEwLCAxMCkgKwogIHlsaW0oMCwgNjApCgpwcChmaWxlPSJpbWFnZXMvejIzc2JfdnNfejIyc2JfcmVhY3RvbWVfdXAucG5nIiwgaW1hZ2U9YWxsX2dwW1siejIzc2JfdnNfejIyc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dLCBoZWlnaHQ9MTIsIHdpZHRoPTkpCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIyc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJLRUdHIl1dCiMjIEtFR0csIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIyc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KIyMgV2lraVBhdGh3YXlzLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIyc2JfdXAiXV1bWyJpbnRlcmFjdGl2ZV9wbG90cyJdXVtbIldQIl1dCgphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzc2JfdnNfejIyc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmBgYAoKCmBgYHtyIHoyM3NiX3ZzX3oyMnNiX3Zlbm59CnNoYXJlZCA8LSBWZW5uZXJhYmxlOjpWZW5uKGxpc3QoImRydWciID0gcm93bmFtZXMoaHNfbWFjcm9waGFnZV9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM3NiX3ZzX3oyMnNiIl1dKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibm9kcnVnIiA9IHJvd25hbWVzKGhzX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjNub3NiX3ZzX3oyMm5vc2IiXV0pKSkKcHAoZmlsZT0iaW1hZ2VzL2RydWdfbm9kcnVnX3Zlbm5fdXAucG5nIikKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmRldi5vZmYoKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKCnNoYXJlZCA8LSBWZW5uZXJhYmxlOjpWZW5uKGxpc3QoImRydWciID0gcm93bmFtZXMoaHNfbWFjcm9waGFnZV9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1siejIzc2JfdnNfejIyc2IiXV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJub2RydWciID0gcm93bmFtZXMoaHNfbWFjcm9waGFnZV9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dKSkpCnBwKGZpbGU9ImltYWdlcy9kcnVnX25vZHJ1Z192ZW5uX2Rvd24ucG5nIikKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmRldi5vZmYoKQpgYGAKCkEgc2xpZ2h0bHkgZGlmZmVyZW50IHdheSBvZiBsb29raW5nIGF0IHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSB0d28Kenltb2RlbWUgaW5mZWN0aW9ucyBpcyB0byBkaXJlY3RseSBjb21wYXJlIHRoZSBpbmZlY3RlZCBzYW1wbGVzIHdpdGgKYW5kIHdpdGhvdXQgZHJ1Zy4gIFRodXMsIHdoZW4gYSB2b2xjYW5vIHBsb3Qgc2hvd2luZyB0aGUgY29tcGFyaXNvbiBvZgp0aGUgenltb2RlbWUgMi4zIHZzLiAyLjIgc2FtcGxlcyB3YXMgcGxvdHRlZCwgNDg0IGdlbmVzIHdlcmUgb2JzZXJ2ZWQKYXMgaW5jcmVhc2VkIGFuZCA0MjIgZGVjcmVhc2VkOyB0aGVzZSBncm91cHMgaW5jbHVkZSBtYW55IG9mIHRoZSBzYW1lCmluZmxhbW1hdG9yeSAodXApIGFuZCBtZW1icmFuZSAoZG93bikgZ2VuZXMuCgpTaW1pbGFyIHBhdHRlcm5zIHdlcmUgb2JzZXJ2ZWQgd2hlbiB0aGUgYW50aW1vbmlhbCB3YXMgaW5jbHVkZWQuClRodXMsIHdoZW4gYSBWZW5uIGRpYWdyYW0gb2YgdGhlIHR3byBzZXRzIG9mIGluY3JlYXNlZCBnZW5lcyB3YXMKcGxvdHRlZCwgYSBzaWduaWZpY2FudCBudW1iZXIgb2YgdGhlIGdlbmVzIHdhcyBvYnNlcnZlZCBhcyBpbmNyZWFzZWQKKDMxMykgYW5kIGRlY3JlYXNlZCAoMjQ0KSBpbiBib3RoIHRoZSB1bnRyZWF0ZWQgYW5kIGFudGltb25pYWwgdHJlYXRlZApzYW1wbGVzLgoKIyMgRHJ1ZyBlZmZlY3RzIG9uIGVhY2ggenltb2RlbWUgaW5mZWN0aW9uCgpBbm90aGVyIGxpa2VseSBxdWVzdGlvbiBpcyB0byBkaXJlY3RseSBjb21wYXJlIHRoZSB0cmVhdGVkIHZzCnVudHJlYXRlZCBzYW1wbGVzIGZvciBlYWNoIHp5bW9kZW1lIGluZmVjdGlvbiBpbiBvcmRlciB0byB2aXN1YWxpemUKdGhlIGVmZmVjdHMgb2YgYW50aW1vbmlhbC4KCmBgYHtyIHoyM2RydWdfejIzbm9kcnVnX3oyMmRydWdfejIybm9kcnVnX3Bsb3RzfQp6MjNzYl92c196MjNub3NiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2RlKAogICAgdGFibGUgPSBoc19tYWNyb3BoYWdlX3RhYmxlW1siZGF0YSJdXVtbInoyM3NiX3ZzX3oyM25vc2IiXV0sCiAgICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICAgIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIpCnBsb3RseTo6Z2dwbG90bHkoejIzc2JfdnNfejIzbm9zYl92b2xjYW5vJHBsb3QpCnoyMnNiX3ZzX3oyMm5vc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fZGUoCiAgICB0YWJsZSA9IGhzX21hY3JvcGhhZ2VfdGFibGVbWyJkYXRhIl1dW1siejIyc2JfdnNfejIybm9zYiJdXSwKICAgIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogICAgc2hhcGVzX2J5X3N0YXRlID0gRkFMU0UsIGNvbG9yX2J5ID0gImZjIiwgIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jc3ltYm9sIikKcGxvdGx5OjpnZ3Bsb3RseSh6MjJzYl92c196MjJub3NiX3ZvbGNhbm8kcGxvdCkKYGBgCgpgYGB7ciB6MjNzYl92c196MjNub3NiX3Bsb3RzfQp6MjNzYl92c196MjNub3NiX3ZvbGNhbm8kcGxvdCArCiAgeGxpbSgtOCwgOCkgKwogIHlsaW0oMCwgMjEwKQoKcHAoZmlsZT0iaW1hZ2VzL3oyM3NiX3ZzX3oyM25vc2JfcmVhY3RvbWVfdXAucG5nIiwKICAgaW1hZ2U9YWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0sIGhlaWdodD0xMiwgd2lkdGg9OSkKIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siS0VHRyJdXQojIyBLRUdHLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIldQIl1dCiMjIFdpa2lQYXRod2F5cywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyM25vc2JfdXAiXV1bWyJpbnRlcmFjdGl2ZV9wbG90cyJdXVtbIldQIl1dCgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmBgYAoKYGBge3IgejIyc2JfdnNfejIybm9zYl9wbG90c30KejIyc2JfdnNfejIybm9zYl92b2xjYW5vJHBsb3QgKwogIHhsaW0oLTgsIDgpICsKICB5bGltKDAsIDIxMCkKCnBwKGZpbGU9ImltYWdlcy96MjJzYl92c196MjJub3NiX3JlYWN0b21lX3VwLnBuZyIsCiAgIGltYWdlPWFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dLCBoZWlnaHQ9MTIsIHdpZHRoPTkpCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIktFR0ciXV0KIyMgS0VHRywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJXUCJdXQojIyBXaWtpUGF0aHdheXMsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1siaW50ZXJhY3RpdmVfcGxvdHMiXV1bWyJXUCJdXQoKYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgpgYGAKCmBgYHtyIHoyMnNiX3ZzX3oyMm5vc2JfdmVubnN9CnNoYXJlZCA8LSBWZW5uZXJhYmxlOjpWZW5uKGxpc3QoInoyMyIgPSByb3duYW1lcyhoc19tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIzc2JfdnNfejIzbm9zYiJdXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInoyMiIgPSByb3duYW1lcyhoc19tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIyc2JfdnNfejIybm9zYiJdXSkpKQpwcChmaWxlPSJpbWFnZXMvejIzX3oyMl9kcnVnX3Zlbm5fdXAucG5nIikKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmRldi5vZmYoKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKCnNoYXJlZCA8LSBWZW5uZXJhYmxlOjpWZW5uKGxpc3QoInoyMyIgPSByb3duYW1lcyhoc19tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJ6MjNzYl92c196MjNub3NiIl1dKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiejIyIiA9IHJvd25hbWVzKGhzX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyMnNiX3ZzX3oyMm5vc2IiXV0pKSkKcHAoZmlsZT0iaW1hZ2VzL3oyM196MjJfZHJ1Z192ZW5uX2Rvd24ucG5nIikKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmRldi5vZmYoKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKYGBgCgpOb3RlOiBJIGFtIHNldHRpZyB0aGUgeCBhbmQgeS1heGlzIGJvdW5kYXJpZXMgYnkgYWxsb3dpbmcgdGhlIHBsb3R0ZXIKdG8gcGljayBpdHMgb3duIGF4aXMgdGhlIGZpcnN0IHRpbWUsIHdyaXRpbmcgZG93biB0aGUgcmFuZ2VzIEkKb2JzZXJ2ZSwgYW5kIHRoZW4gc2V0dGluZyB0aGVtIHRvIHRoZSBsYXJnZXN0IG9mIHRoZSBwYWlyLiAgSXQgaXMKdGhlcmVmb3JlIHBvc3NpYmxlIHRoYXQgSSBtaXNzZWQgb25lIG9yIG1vcmUgZ2VuZXMgd2hpY2ggbGllcyBvdXRzaWRlCnRoYXQgcmFuZ2UuCgpUaGUgcHJldmlvdXMgcGxvdHRlZCBjb250cmFzdHMgc291Z2h0IHRvIHNob3cgY2hhbmdlcyBiZXR3ZWVuIHRoZSB0d28Kc3RyYWlucyB6Mi4zIGFuZCB6Mi4yLiAgQ29udmVyc2VseSwgdGhlIHByZXZpb3VzIHZvbGNhbm8gcGxvdHMgc2VlayB0bwpkaXJlY3RseSBjb21wYXJlIGVhY2ggc3RyYWluIGJlZm9yZS9hZnRlciBkcnVnIHRyZWF0bWVudC4KCiMjIFBhcmFzaXRlCgpgYGB7ciBscF9kZX0KbHBfbWFjcm9waGFnZV9kZSA8LSBhbGxfcGFpcndpc2UobHBfbWFjcm9waGFnZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfYmF0Y2g9InN2YXNlcSIsIGZpbHRlcj1UUlVFKQp0bXJjMl9wYXJhc2l0ZV9rZWVwZXJzIDwtIGxpc3QoCiAgICAiejIzbm9zYl92c196MjJub3NiIiA9IGMoInoyMyIsICJ6MjIiKSkKbHBfbWFjcm9waGFnZV90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBscF9tYWNyb3BoYWdlX2RlLCBrZWVwZXJzID0gdG1yYzJfcGFyYXNpdGVfa2VlcGVycywKICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC9tYWNyb3BoYWdlX3BhcmFzaXRlX2luZmVjdGlvbl9kZS12e3Zlcn0ueGxzeCIpKQpscF9tYWNyb3BoYWdlX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgbHBfbWFjcm9waGFnZV90YWJsZSwKICAgIGV4Y2VsPWdsdWU6OmdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfcGFyYXNpdGVfc2lnLXZ7dmVyfS54bHN4IikpCgpwcChmaWxlPSJpbWFnZXMvbHBfbWFjcm9waGFnZV96MjNfejIyLnBuZyIsCiAgIGltYWdlPWxwX21hY3JvcGhhZ2VfdGFibGVbWyJwbG90cyJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXVtbInBsb3QiXV0pCgp1cF9nZW5lcyA8LSBscF9tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1sxXV0KZGltKHVwX2dlbmVzKQpkb3duX2dlbmVzIDwtIGxwX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbMV1dCmRpbShkb3duX2dlbmVzKQpgYGAKCmBgYHtyIHBhcmFzaXRlX3ZvbGNhbm99CmxwX3oyM3NiX3ZzX3oyMnNiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2RlKAogICAgdGFibGUgPSBscF9tYWNyb3BoYWdlX3RhYmxlW1siZGF0YSJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXSwKICAgIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogICAgc2hhcGVzX2J5X3N0YXRlID0gRkFMU0UsIGNvbG9yX2J5ID0gImZjIiwgIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jc3ltYm9sIikKcGxvdGx5OjpnZ3Bsb3RseShscF96MjNzYl92c196MjJzYl92b2xjYW5vJHBsb3QpCgpscF96MjNub3NiX3ZzX3oyMm5vc2Jfdm9sY2FubyRwbG90CmBgYAoKYGBge3IgZ29zZXFfbHB9CnVwX2dvc2VxIDwtIHNpbXBsZV9nb3NlcSh1cF9nZW5lcywgZ29fZGI9bHBfZ28sIGxlbmd0aF9kYj1scF9sZW5ndGhzKQojIyBWaWV3IGNhdGVnb3JpZXMgb3ZlciByZXByZXNlbnRlZCBpbiB0aGUgMi4zIHNhbXBsZXMKdXBfZ29zZXEkcHZhbHVlX3Bsb3RzJGJwcF9wbG90X292ZXIKZG93bl9nb3NlcSA8LSBzaW1wbGVfZ29zZXEoZG93bl9nZW5lcywgZ29fZGI9bHBfZ28sIGxlbmd0aF9kYj1scF9sZW5ndGhzKQojIyBWaWV3IGNhdGVnb3JpZXMgb3ZlciByZXByZXNlbnRlZCBpbiB0aGUgMi4yIHNhbXBsZXMKZG93bl9nb3NlcSRwdmFsdWVfcGxvdHMkYnBwX3Bsb3Rfb3ZlcgpgYGAKCiMgR1NWQQoKYGBge3IgZ3N2YX0KaHNfaW5mZWN0ZWQgPC0gc3Vic2V0X2V4cHQoaHNfbWFjcm9waGFnZSwgc3Vic2V0PSJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmYnIikgJT4lCiAgc3Vic2V0X2V4cHQoc3Vic2V0PSJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmZfc2InIikKaHNfZ3N2YV9jMiA8LSBzaW1wbGVfZ3N2YShoc19pbmZlY3RlZCkKaHNfZ3N2YV9jMl9tZXRhIDwtIGdldF9tc2lnZGJfbWV0YWRhdGEoaHNfZ3N2YV9jMiwgbXNpZ194bWw9InJlZmVyZW5jZS9tc2lnZGJfdjcuMi54bWwiKQpoc19nc3ZhX2MyX3NpZyA8LSBnZXRfc2lnX2dzdmFfY2F0ZWdvcmllcyhoc19nc3ZhX2MyX21ldGEsIGV4Y2VsID0gImV4Y2VsL2hzX21hY3JvcGhhZ2VfZ3N2YV9jMl9zaWcueGxzeCIpCmhzX2dzdmFfYzJfc2lnJHJhd19wbG90Cgpoc19nc3ZhX2M3IDwtIHNpbXBsZV9nc3ZhKGhzX2luZmVjdGVkLCBzaWduYXR1cmVfY2F0ZWdvcnkgPSAiYzciKQpoc19nc3ZhX2M3X21ldGEgPC0gZ2V0X21zaWdkYl9tZXRhZGF0YShoc19nc3ZhX2M3LCBtc2lnX3htbD0icmVmZXJlbmNlL21zaWdkYl92Ny4yLnhtbCIpNApoc19nc3ZhX2M3X3NpZyA8LSBnZXRfc2lnX2dzdmFfY2F0ZWdvcmllcyhoc19nc3ZhX2M3LCBleGNlbCA9ICJleGNlbC9oc19tYWNyb3BoYWdlX2dzdmFfYzdfc2lnLnhsc3giKQpoc19nc3ZhX2M3X3NpZyRyYXdfcGxvdApgYGAKCiMgVHJ5IG91dCBhIG5ldyB0b29sCgpUd28gcmVhc29uczogTmFqaWIgbG92ZXMgaGltIHNvbWUgUENBLCB0aGlzIHVzZXMgd2lraXBhdGh3YXlzLCB3aGljaCBpcyBzb21ldGhpbmcgSSB0aGluayBpcyBuZWF0LgoKT2ssIEkgc3BlbnQgc29tZSB0aW1lIGxvb2tpbmcgdGhyb3VnaCB0aGUgY29kZSBhbmQgSSBoYXZlIHNvbWUKcHJvYmxlbXMgd2l0aCBzb21lIG9mIHRoZSBkZXNpZ24gZGVjaXNpb25zLgoKTW9zdCBpbXBvcnRhbnRseSwgaXQgcmVxdWlyZXMgYSBkYXRhLmZyYW1lKCkgd2hpY2ggaGFzIHRoZSBmb2xsb3dpbmcgZm9ybWF0OgoKMS4gIE5vIHJvd25hbWVzLCBpbnN0ZWFkIGNvbHVtbiAjMSBpcyB0aGUgc2FtcGxlIElELgoyLiAgQ29sdW1ucyAyLW0gYXJlIHRoZSBjYXRlZ29yaWNhbC9zdXJ2aXZhbC9ldGMgbWV0cmljcy4KMy4gIENvbHVtbnMgbS1uIGFyZSAxIGdlbmUtcGVyLWNvbHVtbiB3aXRoIGxvZzIgdmFsdWVzLgoKQnV0IHdoZW4gSSB0aGluayBhYm91dCBpdCBJIHRoaW5rIEkgZ2V0IHRoZSBpZGVhLCB0aGV5IHdhbnQgdG8gYmUgYWJsZSB0byBkbyBtb2RlbGxpbmcgc3R1ZmYKbW9yZSBlYXNpbHkgd2l0aCByZXNwb25zZSBmYWN0b3JzLgoKYGBge3IgcGF0aHdheVBDQSwgZXZhbD1GQUxTRX0KbGlicmFyeShwYXRod2F5UENBKQpsaWJyYXJ5KHJXaWtpUGF0aHdheXMpCgpkb3dubG9hZGVkIDwtIGRvd25sb2FkUGF0aHdheUFyY2hpdmUob3JnYW5pc20gPSAiSG9tbyBzYXBpZW5zIiwgZm9ybWF0ID0gImdtdCIpCmRhdGFfcGF0aCA8LSBzeXN0ZW0uZmlsZSgiZXh0ZGF0YSIsIHBhY2thZ2U9InBhdGh3YXlQQ0EiKQp3aWtpcGF0aHdheXMgPC0gcmVhZF9nbXQocGFzdGUwKGRhdGFfcGF0aCwgIi93aWtpcGF0aHdheXNfaHVtYW5fc3ltYm9sLmdtdCIpLCBkZXNjcmlwdGlvbj1UUlVFKQoKZXhwdCA8LSBzdWJzZXRfZXhwdChoc19tYWNyb3BoYWdlLCBzdWJzZXQ9Im1hY3JvcGhhZ2V0cmVhdG1lbnQhPSd1bmluZiciKSAlPiUKICBzdWJzZXRfZXhwdChzdWJzZXQ9Im1hY3JvcGhhZ2V0cmVhdG1lbnQhPSd1bmluZl9zYiciKQpleHB0IDwtIHNldF9leHB0X2NvbmRpdGlvbnMoZXhwdCwgZmFjdD0ibWFjcm9waGFnZXp5bW9kZW1lIikKCnN5bWJvbF92ZWN0b3IgPC0gZkRhdGEoZXhwdClbW3N5bWJvbF9jb2x1bW5dXQpuYW1lcyhzeW1ib2xfdmVjdG9yKSA8LSByb3duYW1lcyhmRGF0YShleHB0KSkKc3ltYm9sX2RmIDwtIGFzLmRhdGEuZnJhbWUoc3ltYm9sX3ZlY3RvcikKCmFzc2F5X2RmIDwtIG1lcmdlKHN5bWJvbF9kZiwgYXMuZGF0YS5mcmFtZShleHBycyhleHB0KSksIGJ5ID0gInJvdy5uYW1lcyIpCmFzc2F5X2RmW1siUm93Lm5hbWVzIl1dIDwtIE5VTEwKcm93bmFtZXMoYXNzYXlfZGYpIDwtIG1ha2UubmFtZXMoYXNzYXlfZGZbWyJzeW1ib2xfdmVjdG9yIl1dLCB1bmlxdWUgPSBUUlVFKQphc3NheV9kZltbInN5bWJvbF92ZWN0b3IiXV0gPC0gTlVMTAphc3NheV9kZiA8LSBhcy5kYXRhLmZyYW1lKHQoYXNzYXlfZGYpKQphc3NheV9kZltbIlNhbXBsZUlEIl1dIDwtIHJvd25hbWVzKGFzc2F5X2RmKQphc3NheV9kZiA8LSBkcGx5cjo6c2VsZWN0KGFzc2F5X2RmLCAiU2FtcGxlSUQiLCBldmVyeXRoaW5nKCkpCgpmYWN0b3JfZGYgPC0gYXMuZGF0YS5mcmFtZShwRGF0YShleHB0KSkKZmFjdG9yX2RmW1siU2FtcGxlSUQiXV0gPC0gcm93bmFtZXMoZmFjdG9yX2RmKQpmYWN0b3JfZGYgPC0gZHBseXI6OnNlbGVjdChmYWN0b3JfZGYsICJTYW1wbGVJRCIsIGV2ZXJ5dGhpbmcoKSkKZmFjdG9yX2RmIDwtIGZhY3Rvcl9kZlssIGMoIlNhbXBsZUlEIiwgZmFjdG9ycyldCgp0dCA8LSBDcmVhdGVPbWljcygKICAgIGFzc2F5RGF0YV9kZiA9IGFzc2F5X2RmLAogICAgcGF0aHdheUNvbGxlY3Rpb25fbHMgPSB3aWtpcGF0aHdheXMsCiAgICByZXNwb25zZSA9IGZhY3Rvcl9kZiwKICAgIHJlc3BUeXBlID0gImNhdGVnb3JpY2FsIiwKICAgIG1pblBhdGhTaXplPTUpCgpzdXBlciA8LSBBRVNQQ0FfcFZhbHMoCiAgICBvYmplY3QgPSB0dCwKICAgIG51bVBDcyA9IDIsCiAgICBwYXJhbGxlbCA9IEZBTFNFLAogICAgbnVtQ29yZXMgPSA4LAogICAgbnVtUmVwcyA9IDIsCiAgICBhZGp1c3RtZW50ID0gIkJIIikKYGBgCgpgYGB7ciBzYXZlbWV9CmlmICghaXNUUlVFKGdldDAoInNraXBfbG9hZCIpKSkgewogIHBhbmRlcjo6cGFuZGVyKHNlc3Npb25JbmZvKCkpCiAgbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCiAgbWVzc2FnZShwYXN0ZTAoIlNhdmluZyB0byAiLCBzYXZlZmlsZSkpCiAgdG1wIDwtIHNtKHNhdmVtZShmaWxlbmFtZSA9IHNhdmVmaWxlKSkKfQpgYGAKCmBgYHtyIGxvYWRtZV9hZnRlciwgZXZhbCA9IEZBTFNFfQp0bXAgPC0gbG9hZG1lKGZpbGVuYW1lID0gc2F2ZWZpbGUpCmBgYAo=