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.

1.1 Human data

1.1.1 Primary queries

There is a series of initial questions which make some intuitive sense to me, but these do not necessarily match the set of questions which are intuitive for Olga. 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).

extra <- "z23drugnodrug_vs_z22drugnodrug = (infsbz23 - infz23) - (infsbz22 - infz22)"
new_conditions <- paste0(pData(hs_macrophage)[["macrophagetreatment"]], "_",
                         pData(hs_macrophage)[["macrophagezymodeme"]])
hs_macrophage <- set_expt_conditions(hs_macrophage, fact = new_conditions)

hs_macrophage_de <- all_pairwise(hs_macrophage, model_batch="svaseq", filter=TRUE,
                                 extra_contrasts = extra)
## This DE analysis will perform all pairwise comparisons among:
## 
##   inf_sb_z2.2   inf_sb_z2.3      inf_z2.2      inf_z2.3    uninf_none 
##             6             6             6             6             2 
## uninf_sb_none 
##             2
## 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 (11460 remaining).
## Setting 757 low elements to zero.
## transform_counts: Found 757 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
## Used reverse contrast for deseq.
## Used reverse contrast for edger.
## Used reverse contrast for deseq.
## Used reverse contrast for basic.

1.1.1.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.

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"))

1.1.1.2 Write contrast results

Now let us write out the xlsx file containing the above contrasts.

hs_macrophage_table <- combine_de_tables(
    hs_macrophage_de,
    keepers = tmrc2_human_keepers,
    excel=glue::glue("excel/macrophage_human_table-v{ver}.xlsx"))
## Deleting the file excel/macrophage_human_table-v202209.xlsx before writing the tables.
## Warning in combine_single_de_table(li = limma, ed = edger, eb = ebseq, de =
## deseq, : The deseq table seems to be missing.
## Warning in combine_single_de_table(li = limma, ed = edger, eb = ebseq, de =
## deseq, : The basic table seems to be missing.
## Unable to find the table in the set of possible tables.
## The possible tables are: infsbz23_vs_infsbz22, infz22_vs_infsbz22, infz23_vs_infsbz22, uninfnone_vs_infsbz22, uninfsbnone_vs_infsbz22, infz22_vs_infsbz23, infz23_vs_infsbz23, uninfnone_vs_infsbz23, uninfsbnone_vs_infsbz23, infz23_vs_infz22, uninfnone_vs_infz22, uninfsbnone_vs_infz22, uninfnone_vs_infz23, uninfsbnone_vs_infz23, uninfsbnone_vs_uninfnone
hs_macrophage_sig <- extract_significant_genes(
    hs_macrophage_table,
    excel=glue::glue("excel/macrophage_human_sig-v{ver}.xlsx"))
## Deleting the file excel/macrophage_human_sig-v202209.xlsx before writing the tables.
## Unable to find the table in the set of possible tables.
## The possible tables are: infsbz23_vs_infsbz22, infz22_vs_infsbz22, infz23_vs_infsbz22, uninfnone_vs_infsbz22, uninfsbnone_vs_infsbz22, infz22_vs_infsbz23, infz23_vs_infsbz23, uninfnone_vs_infsbz23, uninfsbnone_vs_infsbz23, infz23_vs_infz22, uninfnone_vs_infz22, uninfsbnone_vs_infz22, uninfnone_vs_infz23, uninfsbnone_vs_infz23, uninfsbnone_vs_uninfnone
## Unable to find the table in the set of possible tables.
## The possible tables are: infsbz23_vs_infsbz22, infz22_vs_infsbz22, infz23_vs_infsbz22, uninfnone_vs_infsbz22, uninfsbnone_vs_infsbz22, infz22_vs_infsbz23, infz23_vs_infsbz23, uninfnone_vs_infsbz23, uninfsbnone_vs_infsbz23, infz23_vs_infz22, uninfnone_vs_infz22, uninfsbnone_vs_infz22, uninfnone_vs_infz23, uninfsbnone_vs_infz23, uninfsbnone_vs_uninfnone

1.1.1.3 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.

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 (function(x, i, exact) if (is.matrix(i)) as.matrix(x)[[i]] else .subset2(x, : object 'table_column' 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 (function(x, i, exact) if (is.matrix(i)) as.matrix(x)[[i]] else .subset2(x, : object 'table_column' 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
hs_macrophage_table[["plots"]][["z23nosb_vs_uninf"]][["deseq_vol_plots"]][["plot"]] +
  xlim(-10, 25) +
  ylim(0, 40)
## Warning: Removed 1 rows containing missing values (geom_point).

hs_macrophage_table[["plots"]][["z22nosb_vs_uninf"]][["deseq_vol_plots"]][["plot"]] +
  xlim(-10, 25) +
  ylim(0, 40)

hs_macrophage_table[["plots"]][["z23nosb_vs_z22nosb"]][["deseq_vol_plots"]][["plot"]] +
  xlim(-10, 10) +
  ylim(0, 60)

hs_macrophage_table[["plots"]][["z23sb_vs_z22sb"]][["deseq_vol_plots"]][["plot"]] +
  xlim(-10, 10) +
  ylim(0, 60)

shared <- Vennerable::Venn(list("drug" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z23sb_vs_z22sb"]]),
                                "nodrug" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z23nosb_vs_z22nosb"]])))
pp(file="images/drug_nodrug_venn_up.png")
Vennerable::plot(shared)
dev.off()
## png 
##   2
Vennerable::plot(shared)

shared <- Vennerable::Venn(list("drug" = rownames(hs_macrophage_sig[["deseq"]][["downs"]][["z23sb_vs_z22sb"]]),
                                "nodrug" = rownames(hs_macrophage_sig[["deseq"]][["downs"]][["z23nosb_vs_z22nosb"]])))
pp(file="images/drug_nodrug_venn_down.png")
Vennerable::plot(shared)
dev.off()
## png 
##   2
hs_macrophage_table[["plots"]][["z23sb_vs_z23nosb"]][["deseq_vol_plots"]][["plot"]] +
  xlim(-8, 8) +
  ylim(0, 210)

hs_macrophage_table[["plots"]][["z22sb_vs_z22nosb"]][["deseq_vol_plots"]][["plot"]] +
  xlim(-8, 8) +
  ylim(0, 210)

hs_macrophage_table[["plots"]][["z23sb_vs_sb"]][["deseq_vol_plots"]][["plot"]] +
  xlim(-10, 28) +
  ylim(0, 140)

hs_macrophage_table[["plots"]][["z22sb_vs_sb"]][["deseq_vol_plots"]][["plot"]] +
  xlim(-10, 28) +
  ylim(0, 140)

shared <- Vennerable::Venn(list("z23" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z23sb_vs_sb"]]),
                                "z22" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z22sb_vs_sb"]])))
pp(file="images/z23_z22_drug_venn_up.png")
Vennerable::plot(shared)
dev.off()
## png 
##   2
Vennerable::plot(shared)

shared <- Vennerable::Venn(list("z23" = rownames(hs_macrophage_sig[["deseq"]][["downs"]][["z23sb_vs_sb"]]),
                                "z22" = rownames(hs_macrophage_sig[["deseq"]][["downs"]][["z22sb_vs_sb"]])))
pp(file="images/z23_z22_drug_venn_down.png")
Vennerable::plot(shared)
dev.off()
## png 
##   2
Vennerable::plot(shared)

1.2 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 
##    5    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 (8522 remaining).
## Setting 45 low elements to zero.
## transform_counts: Found 45 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"))
## Deleting the file excel/macrophage_parasite_infection_de-v202209.xlsx before writing the tables.
lp_macrophage_sig <- extract_significant_genes(
    lp_macrophage_table,
    excel=glue::glue("excel/macrophage_parasite_sig-v{ver}.xlsx"))
## Deleting the file excel/macrophage_parasite_sig-v202209.xlsx before writing the tables.
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] 40 58
down_genes <- lp_macrophage_sig[["deseq"]][["downs"]][[1]]
dim(down_genes)
## [1] 75 58

2 Over representation searches

all_gp <- all_gprofiler(hs_macrophage_sig)
## Performing gProfiler GO search of 670 genes against hsapiens.
## Performing gProfiler KEGG search of 670 genes against hsapiens.
## Performing gProfiler REAC search of 670 genes against hsapiens.
## Performing gProfiler MI search of 670 genes against hsapiens.
## Performing gProfiler TF search of 670 genes against hsapiens.
## Performing gProfiler CORUM search of 670 genes against hsapiens.
## Performing gProfiler HP search of 670 genes against hsapiens.
## Performing gProfiler GO search of 386 genes against hsapiens.
## Performing gProfiler KEGG search of 386 genes against hsapiens.
## Performing gProfiler REAC search of 386 genes against hsapiens.
## Performing gProfiler MI search of 386 genes against hsapiens.
## Performing gProfiler TF search of 386 genes against hsapiens.
## Performing gProfiler CORUM search of 386 genes against hsapiens.
## Performing gProfiler HP search of 386 genes against hsapiens.
## Performing gProfiler GO search of 435 genes against hsapiens.
## Performing gProfiler KEGG search of 435 genes against hsapiens.
## Performing gProfiler REAC search of 435 genes against hsapiens.
## Performing gProfiler MI search of 435 genes against hsapiens.
## Performing gProfiler TF search of 435 genes against hsapiens.
## Performing gProfiler CORUM search of 435 genes against hsapiens.
## Performing gProfiler HP search of 435 genes against hsapiens.
## Performing gProfiler GO search of 7 genes against hsapiens.
## Performing gProfiler KEGG search of 7 genes against hsapiens.
## Performing gProfiler REAC search of 7 genes against hsapiens.
## Performing gProfiler MI search of 7 genes against hsapiens.
## Performing gProfiler TF search of 7 genes against hsapiens.
## Performing gProfiler CORUM search of 7 genes against hsapiens.
## Performing gProfiler HP search of 7 genes against hsapiens.
## Performing gProfiler GO search of 529 genes against hsapiens.
## Performing gProfiler KEGG search of 529 genes against hsapiens.
## Performing gProfiler REAC search of 529 genes against hsapiens.
## Performing gProfiler MI search of 529 genes against hsapiens.
## Performing gProfiler TF search of 529 genes against hsapiens.
## Performing gProfiler CORUM search of 529 genes against hsapiens.
## Performing gProfiler HP search of 529 genes against hsapiens.
## Performing gProfiler GO search of 730 genes against hsapiens.
## Performing gProfiler KEGG search of 730 genes against hsapiens.
## Performing gProfiler REAC search of 730 genes against hsapiens.
## Performing gProfiler MI search of 730 genes against hsapiens.
## Performing gProfiler TF search of 730 genes against hsapiens.
## Performing gProfiler CORUM search of 730 genes against hsapiens.
## Performing gProfiler HP search of 730 genes against hsapiens.
## Performing gProfiler GO search of 484 genes against hsapiens.
## Performing gProfiler KEGG search of 484 genes against hsapiens.
## Performing gProfiler REAC search of 484 genes against hsapiens.
## Performing gProfiler MI search of 484 genes against hsapiens.
## Performing gProfiler TF search of 484 genes against hsapiens.
## Performing gProfiler CORUM search of 484 genes against hsapiens.
## Performing gProfiler HP search of 484 genes against hsapiens.
## Performing gProfiler GO search of 422 genes against hsapiens.
## Performing gProfiler KEGG search of 422 genes against hsapiens.
## Performing gProfiler REAC search of 422 genes against hsapiens.
## Performing gProfiler MI search of 422 genes against hsapiens.
## Performing gProfiler TF search of 422 genes against hsapiens.
## Performing gProfiler CORUM search of 422 genes against hsapiens.
## Performing gProfiler HP search of 422 genes against hsapiens.
## Performing gProfiler GO search of 555 genes against hsapiens.
## Performing gProfiler KEGG search of 555 genes against hsapiens.
## Performing gProfiler REAC search of 555 genes against hsapiens.
## Performing gProfiler MI search of 555 genes against hsapiens.
## Performing gProfiler TF search of 555 genes against hsapiens.
## Performing gProfiler CORUM search of 555 genes against hsapiens.
## Performing gProfiler HP search of 555 genes against hsapiens.
## Performing gProfiler GO search of 780 genes against hsapiens.
## Performing gProfiler KEGG search of 780 genes against hsapiens.
## Performing gProfiler REAC search of 780 genes against hsapiens.
## Performing gProfiler MI search of 780 genes against hsapiens.
## Performing gProfiler TF search of 780 genes against hsapiens.
## Performing gProfiler CORUM search of 780 genes against hsapiens.
## Performing gProfiler HP search of 780 genes against hsapiens.
## Performing gProfiler GO search of 454 genes against hsapiens.
## Performing gProfiler KEGG search of 454 genes against hsapiens.
## Performing gProfiler REAC search of 454 genes against hsapiens.
## Performing gProfiler MI search of 454 genes against hsapiens.
## Performing gProfiler TF search of 454 genes against hsapiens.
## Performing gProfiler CORUM search of 454 genes against hsapiens.
## Performing gProfiler HP search of 454 genes against hsapiens.
## Performing gProfiler GO search of 986 genes against hsapiens.
## Performing gProfiler KEGG search of 986 genes against hsapiens.
## Performing gProfiler REAC search of 986 genes against hsapiens.
## Performing gProfiler MI search of 986 genes against hsapiens.
## Performing gProfiler TF search of 986 genes against hsapiens.
## Performing gProfiler CORUM search of 986 genes against hsapiens.
## Performing gProfiler HP search of 986 genes against hsapiens.
## Performing gProfiler GO search of 1081 genes against hsapiens.
## Performing gProfiler KEGG search of 1081 genes against hsapiens.
## Performing gProfiler REAC search of 1081 genes against hsapiens.
## Performing gProfiler MI search of 1081 genes against hsapiens.
## Performing gProfiler TF search of 1081 genes against hsapiens.
## Performing gProfiler CORUM search of 1081 genes against hsapiens.
## Performing gProfiler HP search of 1081 genes against hsapiens.
## Performing gProfiler GO search of 701 genes against hsapiens.
## Performing gProfiler KEGG search of 701 genes against hsapiens.
## Performing gProfiler REAC search of 701 genes against hsapiens.
## Performing gProfiler MI search of 701 genes against hsapiens.
## Performing gProfiler TF search of 701 genes against hsapiens.
## Performing gProfiler CORUM search of 701 genes against hsapiens.
## Performing gProfiler HP search of 701 genes against hsapiens.
## Performing gProfiler GO search of 1025 genes against hsapiens.
## Performing gProfiler KEGG search of 1025 genes against hsapiens.
## Performing gProfiler REAC search of 1025 genes against hsapiens.
## Performing gProfiler MI search of 1025 genes against hsapiens.
## Performing gProfiler TF search of 1025 genes against hsapiens.
## Performing gProfiler CORUM search of 1025 genes against hsapiens.
## Performing gProfiler HP search of 1025 genes against hsapiens.
## Performing gProfiler GO search of 427 genes against hsapiens.
## Performing gProfiler KEGG search of 427 genes against hsapiens.
## Performing gProfiler REAC search of 427 genes against hsapiens.
## Performing gProfiler MI search of 427 genes against hsapiens.
## Performing gProfiler TF search of 427 genes against hsapiens.
## Performing gProfiler CORUM search of 427 genes against hsapiens.
## Performing gProfiler HP search of 427 genes against hsapiens.
## Performing gProfiler GO search of 910 genes against hsapiens.
## Performing gProfiler KEGG search of 910 genes against hsapiens.
## Performing gProfiler REAC search of 910 genes against hsapiens.
## Performing gProfiler MI search of 910 genes against hsapiens.
## Performing gProfiler TF search of 910 genes against hsapiens.
## Performing gProfiler CORUM search of 910 genes against hsapiens.
## Performing gProfiler HP search of 910 genes against hsapiens.
## Performing gProfiler GO search of 983 genes against hsapiens.
## Performing gProfiler KEGG search of 983 genes against hsapiens.
## Performing gProfiler REAC search of 983 genes against hsapiens.
## Performing gProfiler MI search of 983 genes against hsapiens.
## Performing gProfiler TF search of 983 genes against hsapiens.
## Performing gProfiler CORUM search of 983 genes against hsapiens.
## Performing gProfiler HP search of 983 genes against hsapiens.
## Performing gProfiler GO search of 572 genes against hsapiens.
## Performing gProfiler KEGG search of 572 genes against hsapiens.
## Performing gProfiler REAC search of 572 genes against hsapiens.
## Performing gProfiler MI search of 572 genes against hsapiens.
## Performing gProfiler TF search of 572 genes against hsapiens.
## Performing gProfiler CORUM search of 572 genes against hsapiens.
## Performing gProfiler HP search of 572 genes against hsapiens.
## Performing gProfiler GO search of 644 genes against hsapiens.
## Performing gProfiler KEGG search of 644 genes against hsapiens.
## Performing gProfiler REAC search of 644 genes against hsapiens.
## Performing gProfiler MI search of 644 genes against hsapiens.
## Performing gProfiler TF search of 644 genes against hsapiens.
## Performing gProfiler CORUM search of 644 genes against hsapiens.
## Performing gProfiler HP search of 644 genes against hsapiens.
## Performing gProfiler GO search of 362 genes against hsapiens.
## Performing gProfiler KEGG search of 362 genes against hsapiens.
## Performing gProfiler REAC search of 362 genes against hsapiens.
## Performing gProfiler MI search of 362 genes against hsapiens.
## Performing gProfiler TF search of 362 genes against hsapiens.
## Performing gProfiler CORUM search of 362 genes against hsapiens.
## Performing gProfiler HP search of 362 genes against hsapiens.
## Performing gProfiler GO search of 503 genes against hsapiens.
## Performing gProfiler KEGG search of 503 genes against hsapiens.
## Performing gProfiler REAC search of 503 genes against hsapiens.
## Performing gProfiler MI search of 503 genes against hsapiens.
## Performing gProfiler TF search of 503 genes against hsapiens.
## Performing gProfiler CORUM search of 503 genes against hsapiens.
## Performing gProfiler HP search of 503 genes against hsapiens.
pp(file="images/z23_uninf_reactome_up.png", image=all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["reactome_plot_over"]], height=12, width=9)
## Error in all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["reactome_plot_over"]]: subscript out of bounds
all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["kegg_plot_over"]]
## Error in all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["kegg_plot_over"]]: subscript out of bounds
all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["mfp_plot_over"]]
## Error in all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["mfp_plot_over"]]: subscript out of bounds
all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["tf_plot_over"]]
## Error in all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["tf_plot_over"]]: subscript out of bounds
pp(file="images/z22_uninf_reactome_up.png", image=all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["reactome_plot_over"]], height=12, width=9)
## Error in all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["reactome_plot_over"]]: subscript out of bounds
all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["kegg_plot_over"]]
## Error in all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["kegg_plot_over"]]: subscript out of bounds
all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["mfp_plot_over"]]
## Error in all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["mfp_plot_over"]]: subscript out of bounds
all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["tf_plot_over"]]
## Error in all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["tf_plot_over"]]: subscript out of bounds
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["reactome_plot_over"]]
## Error in all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["reactome_plot_over"]]: subscript out of bounds
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["kegg_plot_over"]]
## Error in all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["kegg_plot_over"]]: subscript out of bounds
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["mfp_plot_over"]]
## Error in all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["mfp_plot_over"]]: subscript out of bounds
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["tf_plot_over"]]
## Error in all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["tf_plot_over"]]: subscript out of bounds
all_gp[["z23sb_vs_z22sb_down"]][["pvalue_plots"]][["reactome_plot_over"]]
## Error in all_gp[["z23sb_vs_z22sb_down"]][["pvalue_plots"]][["reactome_plot_over"]]: subscript out of bounds
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["reactome_plot_over"]]
## Error in all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["reactome_plot_over"]]: subscript out of bounds
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["kegg_plot_over"]]
## Error in all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["kegg_plot_over"]]: subscript out of bounds
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["mfp_plot_over"]]
## Error in all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["mfp_plot_over"]]: subscript out of bounds
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["tf_plot_over"]]
## Error in all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["tf_plot_over"]]: subscript out of bounds
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["reactome_plot_over"]]
## Error in all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["reactome_plot_over"]]: subscript out of bounds
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["kegg_plot_over"]]
## Error in all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["kegg_plot_over"]]: subscript out of bounds
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["mfp_plot_over"]]
## Error in all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["mfp_plot_over"]]: subscript out of bounds
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["tf_plot_over"]]
## Error in all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["tf_plot_over"]]: subscript out of bounds
up_goseq <- simple_goseq(up_genes, go_db=lp_go, length_db=lp_lengths)
## Found 11 go_db genes and 40 length_db genes out of 40.
## 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 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 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"
## 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 21 go_db genes and 75 length_db genes out of 75.
## 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 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 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"
## View categories over represented in the 2.2 samples
down_goseq$pvalue_plots$bpp_plot_over

3 GSVA

hs_infected <- subset_expt(hs_macrophage, subset="macrophagetreatment!='uninf'") %>%
  subset_expt(subset="macrophagetreatment!='uninf_sb'")
## subset_expt(): There were 28, now there are 26 samples.
## subset_expt(): There were 26, now there are 24 samples.
hs_gsva_c2 <- simple_gsva(hs_infected)
## Converting the rownames() of the expressionset to ENTREZID.
## 1622 ENSEMBL ID's didn't have a matching ENTEREZ ID. Dropping them now.
## Before conversion, the expressionset has 21481 entries.
## After conversion, the expressionset has 20013 entries.
hs_gsva_c7 <- simple_gsva(hs_infected, signature_category = "c7")
## Converting the rownames() of the expressionset to ENTREZID.
## 1622 ENSEMBL ID's didn't have a matching ENTEREZ ID. Dropping them now.
## Before conversion, the expressionset has 21481 entries.
## After conversion, the expressionset has 20013 entries.
hs_gsva_c2_sig <- get_sig_gsva_categories(hs_gsva_c2, excel = "excel/hs_macrophage_gsva_c2_sig.xlsx")
## Starting limma pairwise comparison.
## libsize was not specified, this parameter has profound effects on limma's result.
## Using the libsize from expt$libsize.
## Limma step 1/6: choosing model.
## Choosing the non-intercept containing model.
## Assuming this data is similar to a micro array and not performign voom.
## Limma step 3/6: running lmFit with method: ls.
## Limma step 4/6: making and fitting contrasts with no intercept. (~ 0 + factors)
## Limma step 5/6: Running eBayes with robust = FALSE and trend = FALSE.
## Limma step 6/6: Writing limma outputs.
## Limma step 6/6: 1/6: Creating table: infsbz23_vs_infsbz22.  Adjust = BH
## Limma step 6/6: 2/6: Creating table: infz22_vs_infsbz22.  Adjust = BH
## Limma step 6/6: 3/6: Creating table: infz23_vs_infsbz22.  Adjust = BH
## Limma step 6/6: 4/6: Creating table: infz22_vs_infsbz23.  Adjust = BH
## Limma step 6/6: 5/6: Creating table: infz23_vs_infsbz23.  Adjust = BH
## Limma step 6/6: 6/6: Creating table: infz23_vs_infz22.  Adjust = BH
## Limma step 6/6: 1/4: Creating table: infsbz22.  Adjust = BH
## Limma step 6/6: 2/4: Creating table: infsbz23.  Adjust = BH
## Limma step 6/6: 3/4: Creating table: infz22.  Adjust = BH
## Limma step 6/6: 4/4: Creating table: infz23.  Adjust = BH
## The factor inf_sb_z2.2 has 6 rows.
## The factor inf_sb_z2.3 has 6 rows.
## The factor inf_z2.2 has 6 rows.
## The factor inf_z2.3 has 6 rows.
## Testing each factor against the others.
## Scoring inf_sb_z2.2 against everything else.
## Scoring inf_sb_z2.3 against everything else.
## Scoring inf_z2.2 against everything else.
## Scoring inf_z2.3 against everything else.
## Deleting the file excel/hs_macrophage_gsva_c2_sig.xlsx before writing the tables.
hs_gsva_c2_sig$raw_plot

hs_gsva_c7_sig <- get_sig_gsva_categories(hs_gsva_c7, excel = "excel/hs_macrophage_gsva_c7_sig.xlsx")
## Starting limma pairwise comparison.
## libsize was not specified, this parameter has profound effects on limma's result.
## Using the libsize from expt$libsize.
## Limma step 1/6: choosing model.
## Choosing the non-intercept containing model.
## Assuming this data is similar to a micro array and not performign voom.
## Limma step 3/6: running lmFit with method: ls.
## Limma step 4/6: making and fitting contrasts with no intercept. (~ 0 + factors)
## Limma step 5/6: Running eBayes with robust = FALSE and trend = FALSE.
## Limma step 6/6: Writing limma outputs.
## Limma step 6/6: 1/6: Creating table: infsbz23_vs_infsbz22.  Adjust = BH
## Limma step 6/6: 2/6: Creating table: infz22_vs_infsbz22.  Adjust = BH
## Limma step 6/6: 3/6: Creating table: infz23_vs_infsbz22.  Adjust = BH
## Limma step 6/6: 4/6: Creating table: infz22_vs_infsbz23.  Adjust = BH
## Limma step 6/6: 5/6: Creating table: infz23_vs_infsbz23.  Adjust = BH
## Limma step 6/6: 6/6: Creating table: infz23_vs_infz22.  Adjust = BH
## Limma step 6/6: 1/4: Creating table: infsbz22.  Adjust = BH
## Limma step 6/6: 2/4: Creating table: infsbz23.  Adjust = BH
## Limma step 6/6: 3/4: Creating table: infz22.  Adjust = BH
## Limma step 6/6: 4/4: Creating table: infz23.  Adjust = BH
## The factor inf_sb_z2.2 has 6 rows.
## The factor inf_sb_z2.3 has 6 rows.
## The factor inf_z2.2 has 6 rows.
## The factor inf_z2.3 has 6 rows.
## Testing each factor against the others.
## Scoring inf_sb_z2.2 against everything else.
## Scoring inf_sb_z2.3 against everything else.
## Scoring inf_z2.2 against everything else.
## Scoring inf_z2.3 against everything else.
## Deleting the file excel/hs_macrophage_gsva_c7_sig.xlsx before writing the tables.
hs_gsva_c7_sig$raw_plot

4 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
## This is hpgltools commit:
## Saving to tmrc2_macrophage_visualization_202209.rda.xz
tmp <- loadme(filename = savefile)
LS0tCnRpdGxlOiAiTC4gcGFuYW1lbnNpcyAyMDIyMDk6IFRNUkMyIE1hY3JvcGhhZ2UgRGlmZmVyZW50aWFsIEV4cHJlc3Npb24uIgphdXRob3I6ICJhdGIgYWJlbGV3QGdtYWlsLmNvbSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiBodG1sX2RvY3VtZW50OgogIGNvZGVfZG93bmxvYWQ6IHRydWUKICBjb2RlX2ZvbGRpbmc6IHNob3cKICBmaWdfY2FwdGlvbjogdHJ1ZQogIGZpZ19oZWlnaHQ6IDcKICBmaWdfd2lkdGg6IDcKICBoaWdobGlnaHQ6IGRlZmF1bHQKICBrZWVwX21kOiBmYWxzZQogIG1vZGU6IHNlbGZjb250YWluZWQKICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogIHRoZW1lOiByZWFkYWJsZQogIHRvYzogdHJ1ZQogIHRvY19mbG9hdDoKICAgY29sbGFwc2VkOiBmYWxzZQogICBzbW9vdGhfc2Nyb2xsOiBmYWxzZQotLS0KCjxzdHlsZT4KICBib2R5IC5tYWluLWNvbnRhaW5lciB7CiAgICBtYXgtd2lkdGg6IDE2MDBweDsKICB9Cjwvc3R5bGU+CgpgYGB7ciBvcHRpb25zLCBpbmNsdWRlID0gRkFMU0V9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShIZWF0cGx1cykKbGlicmFyeShocGdsdG9vbHMpCnR0IDwtIGRldnRvb2xzOjpsb2FkX2FsbCgifi9ocGdsdG9vbHMiKQprbml0cjo6b3B0c19rbml0JHNldChwcm9ncmVzcyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IDkwLAogICAgICAgICAgICAgICAgICAgICBlY2hvID0gVFJVRSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVycm9yID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy53aWR0aCA9IDgsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuaGVpZ2h0ID0gOCwKICAgICAgICAgICAgICAgICAgICAgIGRwaSA9IDk2KQpvbGRfb3B0aW9ucyA8LSBvcHRpb25zKGRpZ2l0cyA9IDQsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbCA9ICJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMikpCnZlciA8LSAiMjAyMjA5IgpwcmV2aW91c19maWxlIDwtICIiCnJ1bmRhdGUgPC0gZm9ybWF0KFN5cy5EYXRlKCksIGZvcm1hdCA9ICIlWSVtJWQiKQoKIyMgdG1wIDwtIHRyeShzbShsb2FkbWUoZmlsZW5hbWUgPSBnc3ViKHBhdHRlcm4gPSAiXFwuUm1kIiwgcmVwbGFjZSA9ICJcXC5yZGFcXC54eiIsIHggPSBwcmV2aW91c19maWxlKSkpKQpybWRfZmlsZSA8LSBnbHVlOjpnbHVlKCJ0bXJjMl9tYWNyb3BoYWdlX3Zpc3VhbGl6YXRpb25fe3Zlcn0uUm1kIikKbG9hZGVkIDwtIGxvYWQoZmlsZT1nbHVlOjpnbHVlKCJyZGEvdG1yYzJfZGF0YV9zdHJ1Y3R1cmVzLXZ7dmVyfS5yZGEiKSkKc2F2ZWZpbGUgPC0gZ3N1YihwYXR0ZXJuID0gIlxcLlJtZCIsIHJlcGxhY2UgPSAiXFwucmRhXFwueHoiLCB4ID0gcm1kX2ZpbGUpCmBgYAoKIyBJbnRyb2R1Y3Rpb24KCkhhdmluZyBlc3RhYmxpc2hlZCB0aGF0IHRoZSBUTVJDMiBtYWNyb3BoYWdlIGRhdGEgbG9va3Mgcm9idXN0IGFuZAppbGx1c3RyYXRpdmUgb2YgYSBjb3VwbGUgb2YgaW50ZXJlc3RpbmcgcXVlc3Rpb25zLCBsZXQgdXMgcGVyZm9ybSBhCmNvdXBsZSBvZiBkaWZmZXJlbnRpYWwgYW5hbHlzZXMgb2YgaXQuCgojIyBIdW1hbiBkYXRhCgojIyMgUHJpbWFyeSBxdWVyaWVzCgpUaGVyZSBpcyBhIHNlcmllcyBvZiBpbml0aWFsIHF1ZXN0aW9ucyB3aGljaCBtYWtlIHNvbWUgaW50dWl0aXZlIHNlbnNlCnRvIG1lLCBidXQgdGhlc2UgZG8gbm90IG5lY2Vzc2FyaWx5IG1hdGNoIHRoZSBzZXQgb2YgcXVlc3Rpb25zIHdoaWNoCmFyZSBpbnR1aXRpdmUgZm9yIE9sZ2EuICBJIGFtIGhvcGluZyB0byBwdWxsIGJvdGggb2YgdGhlc2Ugc2V0cyBvZgpxdWVyaWVzIGluIG9uZS4KCkJlZm9yZSBleHRyYWN0aW5nIHRoZXNlIGdyb3VwcyBvZiBxdWVyaWVzLCBsZXQgdXMgaW52b2tlIHRoZQphbGxfcGFpcndpc2UoKSBmdW5jdGlvbiBhbmQgZ2V0IGFsbCBvZiB0aGUgbGlrZWx5IGNvbnRyYXN0cyBhbG9uZyB3aXRoCm9uZSBvciBtb3JlIGV4dHJhcyB0aGF0IG1pZ2h0IHByb3ZlIHVzZWZ1bCAodGhlICdleHRyYScgYXJndW1lbnQpLgoKYGBge3IgaHNfZGV9CmV4dHJhIDwtICJ6MjNkcnVnbm9kcnVnX3ZzX3oyMmRydWdub2RydWcgPSAoaW5mc2J6MjMgLSBpbmZ6MjMpIC0gKGluZnNiejIyIC0gaW5mejIyKSIKbmV3X2NvbmRpdGlvbnMgPC0gcGFzdGUwKHBEYXRhKGhzX21hY3JvcGhhZ2UpW1sibWFjcm9waGFnZXRyZWF0bWVudCJdXSwgIl8iLAogICAgICAgICAgICAgICAgICAgICAgICAgcERhdGEoaHNfbWFjcm9waGFnZSlbWyJtYWNyb3BoYWdlenltb2RlbWUiXV0pCmhzX21hY3JvcGhhZ2UgPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhoc19tYWNyb3BoYWdlLCBmYWN0ID0gbmV3X2NvbmRpdGlvbnMpCgpoc19tYWNyb3BoYWdlX2RlIDwtIGFsbF9wYWlyd2lzZShoc19tYWNyb3BoYWdlLCBtb2RlbF9iYXRjaD0ic3Zhc2VxIiwgZmlsdGVyPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4dHJhX2NvbnRyYXN0cyA9IGV4dHJhKQpgYGAKCiMjIyMgUHJpbWFyeSBxdWVyeSBjb250cmFzdHMKClRoZSBmaW5hbCBjb250cmFzdCBpbiB0aGlzIGxpc3QgaXMgaW50ZXJlc3RpbmcgYmVjYXVzZSBpdCBkZXBlbmRzIG9uCnRoZSBleHRyYSBjb250cmFzdHMgYXBwbGllZCB0byB0aGUgYWxsX3BhaXJ3aXNlKCkgYWJvdmUuICBJbiBteSB3YXkgb2YKdGhpbmtpbmcsIHRoZSBwcmltYXJ5IGNvbXBhcmlzb25zIHRvIGNvbnNpZGVyIGFyZSBlaXRoZXIgY3Jvc3MtZHJ1ZyBvcgpjcm9zcy1zdHJhaW4sIGJ1dCBub3QgYm90aC4gIEhvd2V2ZXIgSSB0aGluayBpbiBhdCBsZWFzdCBhIGZldwppbnN0YW5jZXMgT2xnYSBpcyBpbnRlcmVzdGVkIGluIHN0cmFpbitkcnVnIC8gdW5pbmZlY3RlZCtub2RydWcuCgpgYGB7ciB0dW1yYzJfaHVtYW5fa2VlcGVyc30KdG1yYzJfaHVtYW5fa2VlcGVycyA8LSBsaXN0KAogICAgInoyM25vc2JfdnNfdW5pbmYiID0gYygiaW5mejIzIiwgInVuaW5mbm9uZSIpLAogICAgInoyMm5vc2JfdnNfdW5pbmYiID0gYygiaW5mejIyIiwgInVuaW5mbm9uZSIpLAogICAgInoyM25vc2JfdnNfejIybm9zYiIgPSBjKCJpbmZ6MjMiLCAiaW5mejIyIiksCiAgICAiejIzc2JfdnNfejIyc2IiID0gYygiaW5mc2J6MjMiLCAiaW5mc2J6MjIiKSwKICAgICJ6MjNzYl92c196MjNub3NiIiA9IGMoImluZnNiejIzIiwgImluZnoyMyIpLAogICAgInoyMnNiX3ZzX3oyMm5vc2IiID0gYygiaW5mc2J6MjIiLCAiaW5mejIyIiksCiAgICAiejIzc2JfdnNfc2IiID0gYygiaW5mejIzIiwgInVuaW5mc2Jub25lIiksCiAgICAiejIyc2JfdnNfc2IiID0gYygiaW5mejIyIiwgInVuaW5mc2Jub25lIiksCiAgICAiejIzc2JfdnNfdW5pbmYiID0gYygiaW5mc2J6MjMiLCAidW5pbmZub25lIiksCiAgICAiejIyc2JfdnNfdW5pbmYiID0gYygiaW5mc2J6MjIiLCAidW5pbmZub25lIiksCiAgICAic2JfdnNfdW5pbmYiID0gYygidW5pbmZzYm5vbmUiLCAidW5pbmZub25lIiksCiAgICAiZXh0cmEiID0gYygiejIzZHJ1Z25vZHJ1ZyIsICJ6MjJkcnVnbm9kcnVnIikpCmBgYAoKIyMjIyBXcml0ZSBjb250cmFzdCByZXN1bHRzCgpOb3cgbGV0IHVzIHdyaXRlIG91dCB0aGUgeGxzeCBmaWxlIGNvbnRhaW5pbmcgdGhlIGFib3ZlIGNvbnRyYXN0cy4KCmBgYHtyIG1ha2VfdGFibGVzX3RtcmMyfQpoc19tYWNyb3BoYWdlX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgaHNfbWFjcm9waGFnZV9kZSwKICAgIGtlZXBlcnMgPSB0bXJjMl9odW1hbl9rZWVwZXJzLAogICAgZXhjZWw9Z2x1ZTo6Z2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9odW1hbl90YWJsZS12e3Zlcn0ueGxzeCIpKQpoc19tYWNyb3BoYWdlX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgaHNfbWFjcm9waGFnZV90YWJsZSwKICAgIGV4Y2VsPWdsdWU6OmdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfaHVtYW5fc2lnLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMjIyBQbG90IGNvbnRyYXN0cyBvZiBpbnRlcmVzdAoKT25lIHN1Z2dlc3Rpb24gSSByZWNlaXZlZCByZWNlbnRseSB3YXMgdG8gc2V0IHRoZSBheGVzIGZvciB0aGVzZQp2b2xjYW5vIHBsb3RzIHRvIGJlIHN0YXRpYyByYXRoZXIgdGhhbiBsZXQgZ2dwbG90IGNob29zZSBpdHMgb3duLiAgSQphbSBhc3N1bWluZyB0aGlzIGlzIG9ubHkgcmVsZXZhbnQgZm9yIHBhaXJzIG9mIGNvbnRyYXN0cywgYnV0IHRoYXQKbWlnaHQgbm90IGJlIHRydWUuCgpgYGB7ciBoc19tYWNyb3BoYWdlX3NpZ19nZW5lc18yMzIydnN1bmluZn0KejIzbm9zYl92c191bmluZl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19kZSgKICAgIHRhYmxlID0gaHNfbWFjcm9waGFnZV90YWJsZVtbImRhdGEiXV1bWyJ6MjNub3NiX3ZzX3VuaW5mIl1dLAogICAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgICBzaGFwZXNfYnlfc3RhdGUgPSBGQUxTRSwgY29sb3JfYnkgPSAiZmMiLCAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiKQpwbG90bHk6OmdncGxvdGx5KHoyM25vc2JfdnNfdW5pbmZfdm9sY2FubyRwbG90KQp6MjJub3NiX3ZzX3VuaW5mX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2RlKAogICAgdGFibGUgPSBoc19tYWNyb3BoYWdlX3RhYmxlW1siZGF0YSJdXVtbInoyMm5vc2JfdnNfdW5pbmYiXV0sCiAgICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICAgIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIpCnBsb3RseTo6Z2dwbG90bHkoejIybm9zYl92c191bmluZl92b2xjYW5vJHBsb3QpCgpoc19tYWNyb3BoYWdlX3RhYmxlW1sicGxvdHMiXV1bWyJ6MjNub3NiX3ZzX3VuaW5mIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dW1sicGxvdCJdXSArCiAgeGxpbSgtMTAsIDI1KSArCiAgeWxpbSgwLCA0MCkKaHNfbWFjcm9waGFnZV90YWJsZVtbInBsb3RzIl1dW1siejIybm9zYl92c191bmluZiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXVtbInBsb3QiXV0gKwogIHhsaW0oLTEwLCAyNSkgKwogIHlsaW0oMCwgNDApCgpoc19tYWNyb3BoYWdlX3RhYmxlW1sicGxvdHMiXV1bWyJ6MjNub3NiX3ZzX3oyMm5vc2IiXV1bWyJkZXNlcV92b2xfcGxvdHMiXV1bWyJwbG90Il1dICsKICB4bGltKC0xMCwgMTApICsKICB5bGltKDAsIDYwKQpoc19tYWNyb3BoYWdlX3RhYmxlW1sicGxvdHMiXV1bWyJ6MjNzYl92c196MjJzYiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXVtbInBsb3QiXV0gKwogIHhsaW0oLTEwLCAxMCkgKwogIHlsaW0oMCwgNjApCgpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KCJkcnVnIiA9IHJvd25hbWVzKGhzX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjNzYl92c196MjJzYiJdXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5vZHJ1ZyIgPSByb3duYW1lcyhoc19tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dKSkpCnBwKGZpbGU9ImltYWdlcy9kcnVnX25vZHJ1Z192ZW5uX3VwLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCgpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KCJkcnVnIiA9IHJvd25hbWVzKGhzX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyM3NiX3ZzX3oyMnNiIl1dKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibm9kcnVnIiA9IHJvd25hbWVzKGhzX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXSkpKQpwcChmaWxlPSJpbWFnZXMvZHJ1Z19ub2RydWdfdmVubl9kb3duLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKYGBgCgpgYGB7ciB6MjNkcnVnX3oyM25vZHJ1Z196MjJkcnVnX3oyMm5vZHJ1Z19wbG90c30KaHNfbWFjcm9waGFnZV90YWJsZVtbInBsb3RzIl1dW1siejIzc2JfdnNfejIzbm9zYiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXVtbInBsb3QiXV0gKwogIHhsaW0oLTgsIDgpICsKICB5bGltKDAsIDIxMCkKaHNfbWFjcm9waGFnZV90YWJsZVtbInBsb3RzIl1dW1siejIyc2JfdnNfejIybm9zYiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXVtbInBsb3QiXV0gKwogIHhsaW0oLTgsIDgpICsKICB5bGltKDAsIDIxMCkKCmhzX21hY3JvcGhhZ2VfdGFibGVbWyJwbG90cyJdXVtbInoyM3NiX3ZzX3NiIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dW1sicGxvdCJdXSArCiAgeGxpbSgtMTAsIDI4KSArCiAgeWxpbSgwLCAxNDApCmhzX21hY3JvcGhhZ2VfdGFibGVbWyJwbG90cyJdXVtbInoyMnNiX3ZzX3NiIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dW1sicGxvdCJdXSArCiAgeGxpbSgtMTAsIDI4KSArCiAgeWxpbSgwLCAxNDApCgpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KCJ6MjMiID0gcm93bmFtZXMoaHNfbWFjcm9waGFnZV9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM3NiX3ZzX3NiIl1dKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiejIyIiA9IHJvd25hbWVzKGhzX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjJzYl92c19zYiJdXSkpKQpwcChmaWxlPSJpbWFnZXMvejIzX3oyMl9kcnVnX3Zlbm5fdXAucG5nIikKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmRldi5vZmYoKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKCnNoYXJlZCA8LSBWZW5uZXJhYmxlOjpWZW5uKGxpc3QoInoyMyIgPSByb3duYW1lcyhoc19tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJ6MjNzYl92c19zYiJdXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInoyMiIgPSByb3duYW1lcyhoc19tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJ6MjJzYl92c19zYiJdXSkpKQpwcChmaWxlPSJpbWFnZXMvejIzX3oyMl9kcnVnX3Zlbm5fZG93bi5wbmciKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKZGV2Lm9mZigpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpgYGAKCiMjIFBhcmFzaXRlCgpgYGB7ciBscF9kZX0KbHBfbWFjcm9waGFnZV9kZSA8LSBhbGxfcGFpcndpc2UobHBfbWFjcm9waGFnZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfYmF0Y2g9InN2YXNlcSIsIGZpbHRlcj1UUlVFKQp0bXJjMl9wYXJhc2l0ZV9rZWVwZXJzIDwtIGxpc3QoCiAgICAiejIzbm9zYl92c196MjJub3NiIiA9IGMoInoyMyIsICJ6MjIiKSkKbHBfbWFjcm9waGFnZV90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBscF9tYWNyb3BoYWdlX2RlLCBrZWVwZXJzID0gdG1yYzJfcGFyYXNpdGVfa2VlcGVycywKICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC9tYWNyb3BoYWdlX3BhcmFzaXRlX2luZmVjdGlvbl9kZS12e3Zlcn0ueGxzeCIpKQpscF9tYWNyb3BoYWdlX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgbHBfbWFjcm9waGFnZV90YWJsZSwKICAgIGV4Y2VsPWdsdWU6OmdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfcGFyYXNpdGVfc2lnLXZ7dmVyfS54bHN4IikpCgpwcChmaWxlPSJpbWFnZXMvbHBfbWFjcm9waGFnZV96MjNfejIyLnBuZyIsIGltYWdlPWxwX21hY3JvcGhhZ2VfdGFibGVbWyJwbG90cyJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXVtbInBsb3QiXV0pCgp1cF9nZW5lcyA8LSBscF9tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1sxXV0KZGltKHVwX2dlbmVzKQpkb3duX2dlbmVzIDwtIGxwX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbMV1dCmRpbShkb3duX2dlbmVzKQpgYGAKCiMgT3ZlciByZXByZXNlbnRhdGlvbiBzZWFyY2hlcwoKCgpgYGB7ciBvdmVyX3JlcHJlc2VudF9kYXRhfQphbGxfZ3AgPC0gYWxsX2dwcm9maWxlcihoc19tYWNyb3BoYWdlX3NpZykKCnBwKGZpbGU9ImltYWdlcy96MjNfdW5pbmZfcmVhY3RvbWVfdXAucG5nIiwgaW1hZ2U9YWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXSwgaGVpZ2h0PTEyLCB3aWR0aD05KQphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1sia2VnZ19wbG90X292ZXIiXV0KYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIm1mcF9wbG90X292ZXIiXV0KYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbInRmX3Bsb3Rfb3ZlciJdXQoKcHAoZmlsZT0iaW1hZ2VzL3oyMl91bmluZl9yZWFjdG9tZV91cC5wbmciLCBpbWFnZT1hbGxfZ3BbWyJ6MjJub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1sicmVhY3RvbWVfcGxvdF9vdmVyIl1dLCBoZWlnaHQ9MTIsIHdpZHRoPTkpCmFsbF9ncFtbInoyMm5vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJrZWdnX3Bsb3Rfb3ZlciJdXQphbGxfZ3BbWyJ6MjJub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1sibWZwX3Bsb3Rfb3ZlciJdXQphbGxfZ3BbWyJ6MjJub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1sidGZfcGxvdF9vdmVyIl1dCgphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbImtlZ2dfcGxvdF9vdmVyIl1dCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1sibWZwX3Bsb3Rfb3ZlciJdXQphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbInRmX3Bsb3Rfb3ZlciJdXQoKYWxsX2dwW1siejIzc2JfdnNfejIyc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQoKYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1sia2VnZ19wbG90X292ZXIiXV0KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIm1mcF9wbG90X292ZXIiXV0KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbInRmX3Bsb3Rfb3ZlciJdXQoKYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1sia2VnZ19wbG90X292ZXIiXV0KYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIm1mcF9wbG90X292ZXIiXV0KYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbInRmX3Bsb3Rfb3ZlciJdXQpgYGAKCmBgYHtyIGdvc2VxX2xwfQp1cF9nb3NlcSA8LSBzaW1wbGVfZ29zZXEodXBfZ2VuZXMsIGdvX2RiPWxwX2dvLCBsZW5ndGhfZGI9bHBfbGVuZ3RocykKIyMgVmlldyBjYXRlZ29yaWVzIG92ZXIgcmVwcmVzZW50ZWQgaW4gdGhlIDIuMyBzYW1wbGVzCnVwX2dvc2VxJHB2YWx1ZV9wbG90cyRicHBfcGxvdF9vdmVyCmRvd25fZ29zZXEgPC0gc2ltcGxlX2dvc2VxKGRvd25fZ2VuZXMsIGdvX2RiPWxwX2dvLCBsZW5ndGhfZGI9bHBfbGVuZ3RocykKIyMgVmlldyBjYXRlZ29yaWVzIG92ZXIgcmVwcmVzZW50ZWQgaW4gdGhlIDIuMiBzYW1wbGVzCmRvd25fZ29zZXEkcHZhbHVlX3Bsb3RzJGJwcF9wbG90X292ZXIKYGBgCgojIEdTVkEKCmBgYHtyIGdzdmF9CmhzX2luZmVjdGVkIDwtIHN1YnNldF9leHB0KGhzX21hY3JvcGhhZ2UsIHN1YnNldD0ibWFjcm9waGFnZXRyZWF0bWVudCE9J3VuaW5mJyIpICU+JQogIHN1YnNldF9leHB0KHN1YnNldD0ibWFjcm9waGFnZXRyZWF0bWVudCE9J3VuaW5mX3NiJyIpCmhzX2dzdmFfYzIgPC0gc2ltcGxlX2dzdmEoaHNfaW5mZWN0ZWQpCmhzX2dzdmFfYzcgPC0gc2ltcGxlX2dzdmEoaHNfaW5mZWN0ZWQsIHNpZ25hdHVyZV9jYXRlZ29yeSA9ICJjNyIpCgpoc19nc3ZhX2MyX3NpZyA8LSBnZXRfc2lnX2dzdmFfY2F0ZWdvcmllcyhoc19nc3ZhX2MyLCBleGNlbCA9ICJleGNlbC9oc19tYWNyb3BoYWdlX2dzdmFfYzJfc2lnLnhsc3giKQpoc19nc3ZhX2MyX3NpZyRyYXdfcGxvdAoKaHNfZ3N2YV9jN19zaWcgPC0gZ2V0X3NpZ19nc3ZhX2NhdGVnb3JpZXMoaHNfZ3N2YV9jNywgZXhjZWwgPSAiZXhjZWwvaHNfbWFjcm9waGFnZV9nc3ZhX2M3X3NpZy54bHN4IikKaHNfZ3N2YV9jN19zaWckcmF3X3Bsb3QKYGBgCgojIFRyeSBvdXQgYSBuZXcgdG9vbAoKVHdvIHJlYXNvbnM6IE5hamliIGxvdmVzIGhpbSBzb21lIFBDQSwgdGhpcyB1c2VzIHdpa2lwYXRod2F5cywgd2hpY2ggaXMgc29tZXRoaW5nIEkgdGhpbmsgaXMgbmVhdC4KCk9rLCBJIHNwZW50IHNvbWUgdGltZSBsb29raW5nIHRocm91Z2ggdGhlIGNvZGUgYW5kIEkgaGF2ZSBzb21lCnByb2JsZW1zIHdpdGggc29tZSBvZiB0aGUgZGVzaWduIGRlY2lzaW9ucy4KCk1vc3QgaW1wb3J0YW50bHksIGl0IHJlcXVpcmVzIGEgZGF0YS5mcmFtZSgpIHdoaWNoIGhhcyB0aGUgZm9sbG93aW5nIGZvcm1hdDoKCjEuICBObyByb3duYW1lcywgaW5zdGVhZCBjb2x1bW4gIzEgaXMgdGhlIHNhbXBsZSBJRC4KMi4gIENvbHVtbnMgMi1tIGFyZSB0aGUgY2F0ZWdvcmljYWwvc3Vydml2YWwvZXRjIG1ldHJpY3MuCjMuICBDb2x1bW5zIG0tbiBhcmUgMSBnZW5lLXBlci1jb2x1bW4gd2l0aCBsb2cyIHZhbHVlcy4KCkJ1dCB3aGVuIEkgdGhpbmsgYWJvdXQgaXQgSSB0aGluayBJIGdldCB0aGUgaWRlYSwgdGhleSB3YW50IHRvIGJlIGFibGUgdG8gZG8gbW9kZWxsaW5nIHN0dWZmCm1vcmUgZWFzaWx5IHdpdGggcmVzcG9uc2UgZmFjdG9ycy4KCmBgYHtyIHBhdGh3YXlQQ0EsIGV2YWw9RkFMU0V9CmxpYnJhcnkocGF0aHdheVBDQSkKbGlicmFyeShyV2lraVBhdGh3YXlzKQoKZG93bmxvYWRlZCA8LSBkb3dubG9hZFBhdGh3YXlBcmNoaXZlKG9yZ2FuaXNtID0gIkhvbW8gc2FwaWVucyIsIGZvcm1hdCA9ICJnbXQiKQpkYXRhX3BhdGggPC0gc3lzdGVtLmZpbGUoImV4dGRhdGEiLCBwYWNrYWdlPSJwYXRod2F5UENBIikKd2lraXBhdGh3YXlzIDwtIHJlYWRfZ210KHBhc3RlMChkYXRhX3BhdGgsICIvd2lraXBhdGh3YXlzX2h1bWFuX3N5bWJvbC5nbXQiKSwgZGVzY3JpcHRpb249VFJVRSkKCmV4cHQgPC0gc3Vic2V0X2V4cHQoaHNfbWFjcm9waGFnZSwgc3Vic2V0PSJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmYnIikgJT4lCiAgc3Vic2V0X2V4cHQoc3Vic2V0PSJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmZfc2InIikKZXhwdCA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGV4cHQsIGZhY3Q9Im1hY3JvcGhhZ2V6eW1vZGVtZSIpCgpzeW1ib2xfdmVjdG9yIDwtIGZEYXRhKGV4cHQpW1tzeW1ib2xfY29sdW1uXV0KbmFtZXMoc3ltYm9sX3ZlY3RvcikgPC0gcm93bmFtZXMoZkRhdGEoZXhwdCkpCnN5bWJvbF9kZiA8LSBhcy5kYXRhLmZyYW1lKHN5bWJvbF92ZWN0b3IpCgphc3NheV9kZiA8LSBtZXJnZShzeW1ib2xfZGYsIGFzLmRhdGEuZnJhbWUoZXhwcnMoZXhwdCkpLCBieSA9ICJyb3cubmFtZXMiKQphc3NheV9kZltbIlJvdy5uYW1lcyJdXSA8LSBOVUxMCnJvd25hbWVzKGFzc2F5X2RmKSA8LSBtYWtlLm5hbWVzKGFzc2F5X2RmW1sic3ltYm9sX3ZlY3RvciJdXSwgdW5pcXVlID0gVFJVRSkKYXNzYXlfZGZbWyJzeW1ib2xfdmVjdG9yIl1dIDwtIE5VTEwKYXNzYXlfZGYgPC0gYXMuZGF0YS5mcmFtZSh0KGFzc2F5X2RmKSkKYXNzYXlfZGZbWyJTYW1wbGVJRCJdXSA8LSByb3duYW1lcyhhc3NheV9kZikKYXNzYXlfZGYgPC0gZHBseXI6OnNlbGVjdChhc3NheV9kZiwgIlNhbXBsZUlEIiwgZXZlcnl0aGluZygpKQoKZmFjdG9yX2RmIDwtIGFzLmRhdGEuZnJhbWUocERhdGEoZXhwdCkpCmZhY3Rvcl9kZltbIlNhbXBsZUlEIl1dIDwtIHJvd25hbWVzKGZhY3Rvcl9kZikKZmFjdG9yX2RmIDwtIGRwbHlyOjpzZWxlY3QoZmFjdG9yX2RmLCAiU2FtcGxlSUQiLCBldmVyeXRoaW5nKCkpCmZhY3Rvcl9kZiA8LSBmYWN0b3JfZGZbLCBjKCJTYW1wbGVJRCIsIGZhY3RvcnMpXQoKdHQgPC0gQ3JlYXRlT21pY3MoCiAgICBhc3NheURhdGFfZGYgPSBhc3NheV9kZiwKICAgIHBhdGh3YXlDb2xsZWN0aW9uX2xzID0gd2lraXBhdGh3YXlzLAogICAgcmVzcG9uc2UgPSBmYWN0b3JfZGYsCiAgICByZXNwVHlwZSA9ICJjYXRlZ29yaWNhbCIsCiAgICBtaW5QYXRoU2l6ZT01KQoKc3VwZXIgPC0gQUVTUENBX3BWYWxzKAogICAgb2JqZWN0ID0gdHQsCiAgICBudW1QQ3MgPSAyLAogICAgcGFyYWxsZWwgPSBGQUxTRSwKICAgIG51bUNvcmVzID0gOCwKICAgIG51bVJlcHMgPSAyLAogICAgYWRqdXN0bWVudCA9ICJCSCIpCmBgYAoKYGBge3Igc2F2ZW1lfQppZiAoIWlzVFJVRShnZXQwKCJza2lwX2xvYWQiKSkpIHsKICBwYW5kZXI6OnBhbmRlcihzZXNzaW9uSW5mbygpKQogIG1lc3NhZ2UocGFzdGUwKCJUaGlzIGlzIGhwZ2x0b29scyBjb21taXQ6ICIsIGdldF9naXRfY29tbWl0KCkpKQogIG1lc3NhZ2UocGFzdGUwKCJTYXZpbmcgdG8gIiwgc2F2ZWZpbGUpKQogIHRtcCA8LSBzbShzYXZlbWUoZmlsZW5hbWUgPSBzYXZlZmlsZSkpCn0KYGBgCgpgYGB7ciBsb2FkbWVfYWZ0ZXIsIGV2YWwgPSBGQUxTRX0KdG1wIDwtIGxvYWRtZShmaWxlbmFtZSA9IHNhdmVmaWxlKQpgYGAK