1 Changelog

  • 202310: Cleaning up to make everything pass within a containerized environment.
  • 202310: Received a set of colors and contrasts of interest for a barplot of significance.
  • 20230410: Making some changes to improve the differential expression plots as well as prepare for some different pathway/GSEA/GSVA analyses on the data.

2 Notes

Showing plots of counts with respect to drug treatment: query to Najib to clarify normalization. I think I can make versions of these plots which use SL/normalized counts to alleviate Najib’s query.

mean ratio of SL/total by condition?

3 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).

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

3.2 Create sets focused on drug, celltype, strain, and combinations

Let us start by playing with the metadata a little and create sets with the condition set to:

  • Drug treatment
  • Cell type (macrophage or U937)
  • Donor
  • Infection Strain
  • Some useful combinations thereof

In addition, keep mental track of which datasets are comprised of all samples vs. those which are only macrophage vs. those which are only U937. (Thus, the usage of all_human vs. hs_macr vs. u937 as prefixes for the data structures.)

Ideally, these recreations of the data should perhaps be in the datastructures worksheet.

all_human <- sanitize_expt_pData(hs_macrophage, columns = "drug") %>%
  set_expt_conditions(fact = "drug") %>%
  set_expt_batches(fact = "typeofcells")
## The numbers of samples by condition are:
## 
## antimony     none 
##       34       34
## The number of samples by batch are:
## 
## Macrophages        U937 
##          54          14
## The following 3 lines were copy/pasted to datastructures and should be removed soon.
no_strain_idx <- pData(all_human)[["strainid"]] == "none"
##pData(all_human)[["strainid"]] <- paste0("s", pData(all_human)[["strainid"]],
##                                         "_", pData(all_human)[["macrophagezymodeme"]])
pData(all_human)[no_strain_idx, "strainid"] <- "none"
table(pData(all_human)[["strainid"]])
## 
## 10763 10772 10977 11026 11075 11126 12251 12309 12355 12367  2169  7158  none 
##     2     8     2     2     2     8     7     8     2     7     8     2    10
all_human_types <- set_expt_conditions(all_human, fact = "typeofcells") %>%
  set_expt_batches(fact = "drug")
## The numbers of samples by condition are:
## 
## Macrophages        U937 
##          54          14
## The number of samples by batch are:
## 
## antimony     none 
##       34       34
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)
## The numbers of samples by condition are:
## 
## Macrophages_none  Macrophages_z22  Macrophages_z23        U937_none 
##                8               23               23                2 
##         U937_z22         U937_z23 
##                6                6
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)
## The numbers of samples by condition are:
## 
## Macrophages_antimony     Macrophages_none        U937_antimony 
##                   27                   27                    7 
##            U937_none 
##                    7
strain_fact <- pData(all_human_types)[["strainid"]]
table(strain_fact)
## strain_fact
## 10763 10772 10977 11026 11075 11126 12251 12309 12355 12367  2169  7158  none 
##     2     8     2     2     2     8     7     8     2     7     8     2    10
new_conditions <- paste0(pData(hs_macrophage)[["macrophagetreatment"]], "_",
                         pData(hs_macrophage)[["macrophagezymodeme"]])
## Note the sanitize() call is redundant with the addition of sanitize() in the
## datastructures file, but I don't want to wait to rerun that.
hs_macr <- set_expt_conditions(hs_macrophage, fact = new_conditions) %>%
  sanitize_expt_pData(column = "drug") %>%
  subset_expt(subset = "typeofcells!='U937'")
## The numbers of samples by condition are:
## 
##      inf_z22      inf_z23    infsb_z22    infsb_z23   uninf_none uninfsb_none 
##           14           15           15           14            5            5
## The samples excluded are: TMRC30309, TMRC30293, TMRC30294, TMRC30291, TMRC30292, TMRC30307, TMRC30308, TMRC30310, TMRC30331, TMRC30311, TMRC30332, TMRC30305, TMRC30306, TMRC30330.
## subset_expt(): There were 68, now there are 54 samples.

3.2.1 Separate Macrophage samples

Once again, we should reconsider where the following block is placed, but these datastructures are likely to be used in many of the following analyses.

hs_macr_drug_expt <- set_expt_conditions(hs_macr, fact = "drug")
## The numbers of samples by condition are:
## 
## antimony     none 
##       27       27
hs_macr_strain_expt <- set_expt_conditions(hs_macr, fact = "macrophagezymodeme") %>%
  subset_expt(subset = "macrophagezymodeme != 'none'")
## The numbers of samples by condition are:
## 
## none  z22  z23 
##    8   23   23
## The samples excluded are: TMRC30059, TMRC30060, TMRC30266, TMRC30268, TMRC30326, TMRC30327, TMRC30312, TMRC30313.
## subset_expt(): There were 54, now there are 46 samples.
table(pData(hs_macr)[["strainid"]])
## 
## 10763 10772 10977 11026 11075 11126 12251 12309 12355 12367  2169  7158  none 
##     2     6     2     2     2     6     5     6     2     5     6     2     8

3.2.2 Refactor U937 samples

The U937 samples were separated in the datastructures file, but we want to use the combination of drug/zymodeme with them pretty much exclusively.

new_conditions <- paste0(pData(hs_u937)[["macrophagetreatment"]], "_",
                         pData(hs_u937)[["macrophagezymodeme"]])
u937_expt <- set_expt_conditions(hs_u937, fact = new_conditions)
## The numbers of samples by condition are:
## 
##      inf_z22      inf_z23    infsb_z22    infsb_z23   uninf_none uninfsb_none 
##            3            3            3            3            1            1

3.3 Contrasts used in this document

Given the various ways we have chopped up this dataset, there are a few general types of contrasts we will perform, which will then be combined into greater complexity:

  • drug treatment
  • strains used
  • cellltypes
  • donors

In the end, our actual goal is to consider the variable effects of drug+strain and see if we can discern patterns which lead to better or worse drug treatment outcome.

There is a set of contrasts in which we are primarily interested in this data, these follow. I created one ratio of ratios contrast which I think has the potential to ask our biggest question.

tmrc2_human_extra <- "z23drugnodrug_vs_z22drugnodrug = (infsbz23 - infz23) - (infsbz22 - infz22), z23z22drug_vs_z23z22nodrug = (infsbz23 - infsbz22) - (infz23 - infz22)"
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("infsbz23", "uninfsbnone"),
  "z22sb_vs_sb" = c("infsbz22", "uninfsbnone"),
  "z23sb_vs_uninf" = c("infsbz23", "uninfnone"),
  "z22sb_vs_uninf" = c("infsbz22", "uninfnone"),
  "sb_vs_uninf" = c("uninfsbnone", "uninfnone"),
  "extra_z2322" = c("z23drugnodrug", "z22drugnodrug"),
  "extra_drugnodrug" = c("z23z22drug", "z23z22nodrug"))
single_tmrc2_keeper <- list(
  "z22sb_vs_sb" = c("infsbz22", "uninfsbnone"))
tmrc2_drug_keepers <- list(
  "drug" = c("antimony", "none"))
tmrc2_type_keepers <- list(
  "type" = c("U937", "Macrophages"))
tmrc2_strain_keepers <- list(
  "strain" = c("z23", "z22"))
type_zymo_extra <- "zymos_vs_types = (U937z23 - U937z22) - (Macrophagesz23 - Macrophagesz22)"
tmrc2_typezymo_keepers <- list(
  "u937_macr" = c("Macrophagesnone", "U937none"),
  "zymo_macr" = c("Macrophagesz23", "Macrophagesz22"),
  "zymo_u937" = c("U937z23", "U937z22"),
  "z23_types" = c("U937z23", "Macrophagesz23"),
  "z22_types" = c("U937z22", "Macrophagesz22"),
  "zymos_types" = c("zymos_vs_types"))
tmrc2_typedrug_keepers <- list(
  "type_nodrug" = c("U937none", "Macrophagesnone"),
  "type_drug" = c("U937antimony", "Macrophagesantimony"),
  "macr_drugs" = c("Macrophagesantimony", "Macrophagesnone"),
  "u937_drugs" = c("U937antimony", "U937none"))
u937_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("infsbz23", "uninfsbnone"),
  "z22sb_vs_sb" = c("infsbz22", "uninfsbnone"),
  "z23sb_vs_uninf" = c("infsbz23", "uninfnone"),
  "z22sb_vs_uninf" = c("infsbz22", "uninfnone"),
  "sb_vs_uninf" = c("uninfsbnone", "uninfnone"))
high_expression <- 128
high_expression_column <- "deseq_basemean"

combined_to_tsv <- function(combined, celltype = "all") {
  keepers <- combined[["keepers"]]
  for (k in seq_len(length(keepers))) {
    kname <- names(keepers)[k]
    numerator <- keepers[[k]][1]
    denominator <- keepers[[k]][2]
    filename <- glue("excel/macrophage_de/{ver}/tsv_tables/tmrc2_{celltype}_{kname}_n{numerator}_d{denominator}-v{ver}.xlsx")
    kdata <- combined[["data"]][[kname]]
    if (is.null(kdata[["basic_num"]])) {
      next
    }
    wanted <- c("hgncsymbol", "deseq_logfc", "deseq_adjp", "deseq_basemean", "deseq_num", "deseq_den")
    wanted_data <- kdata[, wanted]
    colnames(wanted_data) <- c("hgncsymbol", "deseq_logfc", "deseq_adjp", "deseq_mean", "deseq_numerator", "deseq_denominator")
    write_xlsx(data = wanted_data, excel = filename)
  }
}

write_all_gp <- function(all_gp) {
  for (g in seq_len(length(all_gp))) {
    name <- names(all_gp)[g]
    datum <- all_gp[[name]]
    filename <- glue("excel/macrophage_de/{ver}/gprofiler/{name}_gprofiler-v{ver}.xlsx")
    written <- sm(write_gprofiler_data(datum, excel = filename))
  }
}

3.3.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).

3.3.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", do_noiseq = FALSE)
## 
## antimony     none 
##       34       34
## 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.
drug_de
## A pairwise differential expression with results from: basic, deseq, ebseq, edger, limma.
## This used a surrogate/batch estimate from: svaseq.
## The primary analysis performed 10 comparisons.
## The logFC agreement among the methods follows:
##                nn_vs_ntmn
## limma_vs_deseq     0.9665
## limma_vs_edger     0.9688
## limma_vs_ebseq     0.9728
## limma_vs_basic     0.9635
## deseq_vs_edger     0.9988
## deseq_vs_ebseq     0.9344
## deseq_vs_basic     0.9874
## edger_vs_ebseq     0.9383
## edger_vs_basic     0.9866
## ebseq_vs_basic     0.9143
drug_table <- combine_de_tables(
  drug_de, keepers = tmrc2_drug_keepers,
  excel = glue("excel/macrophage_de/{ver}/de_tables/macrophage_drug_comparison-v{ver}.xlsx"))
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: ebseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
drug_table
## A set of combined differential expression results.
##                       table deseq_sigup deseq_sigdown edger_sigup edger_sigdown
## 1 none_vs_antimony-inverted         480           764         480           759
##   limma_sigup limma_sigdown
## 1         471           700
## `geom_line()`: Each group consists of only one observation.
## i Do you need to adjust the group aesthetic?

combined_to_tsv(drug_table, celltype = "all")

drug_sig <- extract_significant_genes(
  drug_table,
  excel = glue("excel/macrophage_de/{ver}/sig_tables/macrophage_drug_sig-v{ver}.xlsx"))
drug_sig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##      limma_up limma_down edger_up edger_down deseq_up deseq_down ebseq_up
## drug      471        700      480        759      480        764      323
##      ebseq_down basic_up basic_down
## drug        577      444        590

drug_highsig <- extract_significant_genes(
  drug_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("excel/macrophage_de/{ver}/sig_tables/macrophage_drug_highsig-v{ver}.xlsx"))
drug_highsig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##      limma_up limma_down edger_up edger_down deseq_up deseq_down ebseq_up
## drug      222        388      233        427      231        429      162
##      ebseq_down basic_up basic_down
## drug        346      211        331

all_drug_gp <- all_gprofiler(drug_sig)
all_drug_gp
## Running gProfiler on every set of significant genes found:
##            GO KEGG REAC WP  TF MIRNA HPA CORUM HP
## drug_up   159    5   76  8  27     1   0     0  0
## drug_down 470    0    1  0 313     1   0     0  0
write_all_gp(all_drug_gp)

3.3.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", do_noiseq = FALSE)
## 
## Macrophages        U937 
##          54          14
## 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.
type_de
## A pairwise differential expression with results from: basic, deseq, ebseq, edger, limma.
## This used a surrogate/batch estimate from: svaseq.
## The primary analysis performed 10 comparisons.
## The logFC agreement among the methods follows:
##                U937_vs_Mc
## limma_vs_deseq     0.9851
## limma_vs_edger     0.9859
## limma_vs_ebseq     0.9490
## limma_vs_basic     0.9992
## deseq_vs_edger     0.9976
## deseq_vs_ebseq     0.9806
## deseq_vs_basic     0.9833
## edger_vs_ebseq     0.9836
## edger_vs_basic     0.9843
## ebseq_vs_basic     0.9461
type_table <- combine_de_tables(
  type_de, keepers = tmrc2_type_keepers,
  excel = glue("excel/macrophage_de/{ver}/de_tables/macrophage_type_comparison-v{ver}.xlsx"))
type_table
## A set of combined differential expression results.
##                 table deseq_sigup deseq_sigdown edger_sigup edger_sigdown
## 1 U937_vs_Macrophages        2105          2436        2077          2462
##   limma_sigup limma_sigdown
## 1        2247          2129
## `geom_line()`: Each group consists of only one observation.
## i Do you need to adjust the group aesthetic?

combined_to_tsv(type_table, celltype = "all")

type_sig <- extract_significant_genes(
  type_table,
  excel = glue("excel/macrophage_de/{ver}/sig_tables/macrophage_type_sig-v{ver}.xlsx"))
type_sig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##      limma_up limma_down edger_up edger_down deseq_up deseq_down ebseq_up
## type     2247       2129     2077       2462     2105       2436     1880
##      ebseq_down basic_up basic_down
## type       2485     2231       2097

type_highsig <- extract_significant_genes(
  type_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("excel/macrophage_de/{ver}/sig_tables/macrophage_type_highsig-v{ver}.xlsx"))
type_highsig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##      limma_up limma_down edger_up edger_down deseq_up deseq_down ebseq_up
## type     1365       1632     1298       1764     1322       1736     1181
##      ebseq_down basic_up basic_down
## type       1789     1354       1617

3.3.3.1 Combined factors of interest: celltype+zymodeme

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", do_noiseq = FALSE,
                             extra_contrasts = type_zymo_extra)
## 
## Macrophages_none  Macrophages_z22  Macrophages_z23        U937_none 
##                8               23               23                2 
##         U937_z22         U937_z23 
##                6                6
## 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.

type_zymo_de
## A pairwise differential expression with results from: basic, deseq, edger, limma.
## This used a surrogate/batch estimate from: svaseq.
## The primary analysis performed 6 comparisons.
type_zymo_table <- combine_de_tables(
  type_zymo_de, keepers = tmrc2_typezymo_keepers,
  excel = glue("excel/macrophage_de/de_tables/macrophage_type_zymo_comparison-v{ver}.xlsx"))
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Did not find NA or zymos_vs_types.
## Did not find NA or zymos_vs_types.
combined_to_tsv(type_zymo_table, celltype = "all")

type_zymo_sig <- extract_significant_genes(
  type_zymo_table,
  excel = glue("excel/macrophage_de/{ver}/sig_tables/macrophage_type_zymo_sig-v{ver}.xlsx"))
## There is no deseq_logfc column in the table.
## The columns are: ensemblgeneid, ensembltranscriptid, version, transcriptversion, description, genebiotype, cdslength, chromosomename, strand, startposition, endposition, hgncsymbol, uniprotgnsymbol, transcript, edger_logfc, edger_adjp, limma_logfc, limma_adjp, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_b, limma_p, limma_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no basic_logfc column in the table.
## The columns are: ensemblgeneid, ensembltranscriptid, version, transcriptversion, description, genebiotype, cdslength, chromosomename, strand, startposition, endposition, hgncsymbol, uniprotgnsymbol, transcript, edger_logfc, edger_adjp, limma_logfc, limma_adjp, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_b, limma_p, limma_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
type_zymo_sig
## A set of genes deemed significant according to limma, edger, deseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##             limma_up limma_down edger_up edger_down deseq_up deseq_down
## u937_macr       2019       2206     2363       2089     2351       2082
## zymo_macr        384        319      298        463      300        459
## zymo_u937          0          0        1          3        1          2
## z23_types       2295       2181     2123       2498     2152       2468
## z22_types       2271       2154     2004       2558     2024       2540
## zymos_types      187        223      337        220        0          0
##             basic_up basic_down
## u937_macr       1319       1697
## zymo_macr        362        288
## zymo_u937          0          0
## z23_types       2269       2098
## z22_types       2268       2132
## zymos_types        0          0

type_zymo_highsig <- extract_significant_genes(
  type_zymo_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("excel/macrophage_de/{ver}/sig_tables/macrophage_type_zymo_highsig-v{ver}.xlsx"))
## Warning in get_sig_genes(this_table, lfc = lfc, p = p, z = z, n = n, column =
## this_fc_column, : The column deseq_basemean does not appears to be in the
## table, cannot filter by expression.
## Warning in get_sig_genes(this_table, lfc = lfc, p = p, z = z, n = n, column =
## this_fc_column, : The column deseq_basemean does not appears to be in the
## table, cannot filter by expression.
## There is no deseq_logfc column in the table.
## The columns are: ensemblgeneid, ensembltranscriptid, version, transcriptversion, description, genebiotype, cdslength, chromosomename, strand, startposition, endposition, hgncsymbol, uniprotgnsymbol, transcript, edger_logfc, edger_adjp, limma_logfc, limma_adjp, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_b, limma_p, limma_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no basic_logfc column in the table.
## The columns are: ensemblgeneid, ensembltranscriptid, version, transcriptversion, description, genebiotype, cdslength, chromosomename, strand, startposition, endposition, hgncsymbol, uniprotgnsymbol, transcript, edger_logfc, edger_adjp, limma_logfc, limma_adjp, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_b, limma_p, limma_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var

3.3.3.2 Combined factors of inteest: celltype+drug

The ‘type_drug’ datastructure is the same as above, but the condition is created from the concatenation of the cell type and drug treatment.

type_drug_de <- all_pairwise(type_drug, filter = TRUE, model_batch = "svaseq")
## 
## Macrophages_antimony     Macrophages_none        U937_antimony 
##                   27                   27                    7 
##            U937_none 
##                    7
## 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.
type_drug_de
## A pairwise differential expression with results from: basic, deseq, ebseq, edger, limma, noiseq.
## This used a surrogate/batch estimate from: svaseq.
## The primary analysis performed 15 comparisons.
type_drug_table <- combine_de_tables(
  type_drug_de, keepers = tmrc2_typedrug_keepers,
  excel = glue("excel/macrophage_de/{ver}/de_tables/macrophage_type_drug_comparison-v{ver}.xlsx"))
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: ebseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: ebseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.
type_drug_table
## A set of combined differential expression results.

##                                             table deseq_sigup deseq_sigdown
## 1                     U937none_vs_Macrophagesnone        2099          2639
## 2             U937antimony_vs_Macrophagesantimony        2102          2375
## 3 Macrophagesnone_vs_Macrophagesantimony-inverted         599           963
## 4               U937none_vs_U937antimony-inverted         423           167
##   edger_sigup edger_sigdown limma_sigup limma_sigdown
## 1        2063          2665        2288          2197
## 2        2083          2387        2254          2130
## 3         605           963         669           914
## 4         439           176         209           162

combined_to_tsv(type_drug_table, celltype = "all")
type_drug_sig <- extract_significant_genes(
  type_drug_table,
  excel = glue("excel/macrophage_de/{ver}/sig_tables/macrophage_type_drug_sig-v{ver}.xlsx"))
type_drug_sig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##             limma_up limma_down edger_up edger_down deseq_up deseq_down
## type_nodrug     2288       2197     2063       2665     2099       2639
## type_drug       2254       2130     2083       2387     2102       2375
## macr_drugs       669        914      605        963      599        963
## u937_drugs       209        162      439        176      423        167
##             ebseq_up ebseq_down basic_up basic_down
## type_nodrug     1956       2465     2315       2164
## type_drug       2008       2312     2254       2151
## macr_drugs       482        881      669        858
## u937_drugs       359        157      233        179

type_drug_highsig <- extract_significant_genes(
  type_drug_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("excel/macrophage_de/{ver}/sig_tables/macrophage_type_drug_highsig-v{ver}.xlsx"))
type_drug_highsig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##             limma_up limma_down edger_up edger_down deseq_up deseq_down
## type_nodrug     1391       1694     1313       1892     1343       1866
## type_drug       1385       1651     1302       1736     1320       1721
## macr_drugs       328        523      301        563      301        564
## u937_drugs       101         84      209        105      203        101
##             ebseq_up ebseq_down basic_up basic_down
## type_nodrug     1275       1789     1414       1675
## type_drug       1266       1719     1392       1681
## macr_drugs       243        517      330        497
## u937_drugs       168        100      118         99

4 Individual cell types

At this point, I think it is fair to say that the two cell types are sufficiently different that they do not really belong together in a single analysis.

4.1 drug or strain effects, single cell type

One of the queries Najib asked which I think I misinterpreted was to look at drug and/or strain effects. My interpretation is somewhere below and was not what he was looking for. Instead, he was looking to see all(macrophage) drug/nodrug and all(macrophage) z23/z22 and compare them to each other. It may be that this is still a wrong interpretation, if so the most likely comparison is either:

  • (z23drug/z22drug) / (z23nodrug/z22nodrug), or perhaps
  • (z23drug/z23nodrug) / (z22drug/z22nodrug),

I am not sure those confuse me, and at least one of them is below

4.1.1 Macrophages

In these blocks we will explicitly query only one factor at a time, drug and strain. The eventual goal is to look for effects of drug treatment and/or strain treatment which are shared?

4.1.1.1 Macrophage Drug only

Thus we will start with the pure drug query. In this block we will look only at the drug/nodrug effect.

hs_macr_drug_de <- all_pairwise(hs_macr_drug_expt, filter = TRUE, model_batch = "svaseq")
## 
## antimony     none 
##       27       27
## Removing 0 low-count genes (11756 remaining).
## Setting 1309 low elements to zero.
## transform_counts: Found 1309 values equal to 0, adding 1 to the matrix.
hs_macr_drug_de
## A pairwise differential expression with results from: basic, deseq, ebseq, edger, limma, noiseq.
## This used a surrogate/batch estimate from: svaseq.
## The primary analysis performed 15 comparisons.
## The logFC agreement among the methods follows:
##                 nn_vs_ntmn
## limma_vs_deseq      0.9911
## limma_vs_edger      0.9911
## limma_vs_ebseq      0.9694
## limma_vs_basic      0.9922
## limma_vs_noiseq    -0.8786
## deseq_vs_edger      0.9997
## deseq_vs_ebseq      0.9647
## deseq_vs_basic      0.9916
## deseq_vs_noiseq    -0.8861
## edger_vs_ebseq      0.9643
## edger_vs_basic      0.9911
## edger_vs_noiseq    -0.8872
## ebseq_vs_basic      0.9618
## ebseq_vs_noiseq    -0.8578
## basic_vs_noiseq    -0.8903
hs_macr_drug_table <- combine_de_tables(
  hs_macr_drug_de, keepers = tmrc2_drug_keepers,
  excel = glue("excel/macrophage_de/macrophage_onlydrug_table-v{ver}.xlsx"))
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: ebseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.
hs_macr_drug_table
## A set of combined differential expression results.
##                       table deseq_sigup deseq_sigdown edger_sigup edger_sigdown
## 1 none_vs_antimony-inverted         519           862         525           852
##   limma_sigup limma_sigdown
## 1         556           808
## `geom_line()`: Each group consists of only one observation.
## i Do you need to adjust the group aesthetic?

combined_to_tsv(hs_macr_drug_table, celltype = "macrophage")

hs_macr_drug_sig <- extract_significant_genes(
  hs_macr_drug_table,
  excel = glue("excel/macrophage_de/macrophageonly_drug_sig-v{ver}.xlsx"))
hs_macr_drug_sig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##      limma_up limma_down edger_up edger_down deseq_up deseq_down ebseq_up
## drug      556        808      525        852      519        862      425
##      ebseq_down basic_up basic_down
## drug        821      573        766

hs_macr_drug_highsig <- extract_significant_genes(
  hs_macr_drug_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("excel/macrophage_de/macrophageonly_drug_highsig-v{ver}.xlsx"))
hs_macr_drug_highsig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##      limma_up limma_down edger_up edger_down deseq_up deseq_down ebseq_up
## drug      283        492      273        539      268        548      225
##      ebseq_down basic_up basic_down
## drug        511      292        482

4.1.1.2 Macrophage Strain only

In a similar fashion, let us look for effects which are observed when we consider only the strain used during infection.

hs_macr_strain_de <- all_pairwise(hs_macr_strain_expt, filter = TRUE, model_batch = "svaseq")
## 
## z22 z23 
##  23  23
## Removing 0 low-count genes (11720 remaining).
## Setting 1017 low elements to zero.
## transform_counts: Found 1017 values equal to 0, adding 1 to the matrix.
hs_macr_strain_de
## A pairwise differential expression with results from: basic, deseq, ebseq, edger, limma, noiseq.
## This used a surrogate/batch estimate from: svaseq.
## The primary analysis performed 15 comparisons.
## The logFC agreement among the methods follows:
##                 z23_vs_z22
## limma_vs_deseq      0.9637
## limma_vs_edger      0.9668
## limma_vs_ebseq      0.9614
## limma_vs_basic      0.9839
## limma_vs_noiseq    -0.8442
## deseq_vs_edger      0.9991
## deseq_vs_ebseq      0.9721
## deseq_vs_basic      0.9596
## deseq_vs_noiseq    -0.8301
## edger_vs_ebseq      0.9726
## edger_vs_basic      0.9623
## edger_vs_noiseq    -0.8338
## ebseq_vs_basic      0.9399
## ebseq_vs_noiseq    -0.8013
## basic_vs_noiseq    -0.8625
hs_macr_strain_table <- combine_de_tables(
  hs_macr_strain_de, keepers = tmrc2_strain_keepers,
  excel = glue("excel/macrophage_de/macrophage_onlystrain_table-v{ver}.xlsx"))
hs_macr_strain_table
## A set of combined differential expression results.
##        table deseq_sigup deseq_sigdown edger_sigup edger_sigdown limma_sigup
## 1 z23_vs_z22         291           371         290           366         337
##   limma_sigdown
## 1           275
## `geom_line()`: Each group consists of only one observation.
## i Do you need to adjust the group aesthetic?

combined_to_tsv(hs_macr_strain_table, celltype = "macrophage")

hs_macr_strain_sig <- extract_significant_genes(
  hs_macr_strain_table,
  excel = glue("excel/macrophage_de/macrophageonly_onlystrain_sig-v{ver}.xlsx"))
hs_macr_strain_sig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##        limma_up limma_down edger_up edger_down deseq_up deseq_down ebseq_up
## strain      337        275      290        366      291        371      199
##        ebseq_down basic_up basic_down
## strain        216      317        253

hs_macr_strain_highsig <- extract_significant_genes(
  hs_macr_strain_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("excel/macrophage_de/macrophageonly_onlystrain_highsig-v{ver}.xlsx"))
hs_macr_strain_highsig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##        limma_up limma_down edger_up edger_down deseq_up deseq_down ebseq_up
## strain      193        101      194        110      194        112      156
##        ebseq_down basic_up basic_down
## strain         51      187        101

4.1.1.3 Compare Drug and Strain Effects

Now let us consider the above two comparisons together. First, I will plot the logFC values of them against each other (drug on x-axis and strain on the y-axis). Then we can extract the significant genes in a few combined categories of interest. I assume these will focus exclusively on the categories which include the introduction of the drug.

drug_strain_comp_df <- merge(hs_macr_drug_table[["data"]][["drug"]],
                             hs_macr_strain_table[["data"]][["strain"]],
                             by = "row.names")
drug_strain_comp_plot <- plot_linear_scatter(
  drug_strain_comp_df[, c("deseq_logfc.x", "deseq_logfc.y")])
## Contrasts: antimony/none, z23/z22; x-axis: drug, y-axis: strain
## top left: higher no drug, z23; top right: higher drug z23
## bottom left: higher no drug, z22; bottom right: higher drug z22
drug_strain_comp_plot$scatter

As I noted in the comments above, some quadrants of the scatter plot are likely to be of greater interest to us than others (the right side). Because I get confused sometimes, the following block will explicitly name the categories of likely interest, then ask which genes are shared among them, and finally use UpSetR to extract the various gene intersection/union categories.

higher_drug <- hs_macr_drug_sig[["deseq"]][["downs"]][[1]]
higher_nodrug <- hs_macr_drug_sig[["deseq"]][["ups"]][[1]]
higher_z23 <- hs_macr_strain_sig[["deseq"]][["ups"]][[1]]
higher_z22 <- hs_macr_strain_sig[["deseq"]][["downs"]][[1]]
sum(rownames(higher_drug) %in% rownames(higher_z23))
## [1] 94
sum(rownames(higher_drug) %in% rownames(higher_z22))
## [1] 87
sum(rownames(higher_nodrug) %in% rownames(higher_z23))
## [1] 26
sum(rownames(higher_nodrug) %in% rownames(higher_z22))
## [1] 73
drug_z23_lst <- list("drug" = rownames(higher_drug),
                     "z23" = rownames(higher_z23))
upset_input <- UpSetR::fromList(drug_z23_lst)
higher_drug_z23 <- upset(upset_input, text.scale = 2)
higher_drug_z23

drug_z23_shared_genes <- overlap_groups(drug_z23_lst)
shared_genes_drug_z23 <- overlap_geneids(drug_z23_shared_genes, "drug:z23")
shared_genes_drug_z23 <- attr(drug_z23_shared_genes, "elements")[drug_z23_shared_genes[["drug:z23"]]]

drug_z22_lst <- list("drug" = rownames(higher_drug),
                     "z22" = rownames(higher_z22))
higher_drug_z22 <- upset(UpSetR::fromList(drug_z22_lst), text.scale = 2)
higher_drug_z22

drug_z22_shared_genes <- overlap_groups(drug_z22_lst)
shared_genes_drug_z22 <- overlap_geneids(drug_z22_shared_genes, "drug:z22")
shared_genes_drug_z22 <- attr(drug_z22_shared_genes, "elements")[drug_z22_shared_genes[["drug:z22"]]]

4.1.1.4 Perform gProfiler on drug/strain effect shared genes

Now that we have some populations of genes which are shared across the drug/strain effects, let us pass them to some GSEA analyses and see what pops out.

wanted <- drug_z23_shared_genes[["drug:z23"]]
shared_genes_drug_z23 <- attr(drug_z23_shared_genes, "elements")[wanted]
shared_drug_z23_gp <- simple_gprofiler(shared_genes_drug_z23)
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## Add a little logic here to use enrichplot::dotplot().
shared_drug_z23_gp[["pvalue_plots"]][["MF"]]

shared_drug_z23_gp[["pvalue_plots"]][["BP"]]

shared_drug_z23_gp[["pvalue_plots"]][["REAC"]]

wanted <- drug_z22_shared_genes[["drug:z22"]]
shared_genes_drug_z22 <- attr(drug_z22_shared_genes, "elements")[wanted]
shared_drug_z22_gp <- simple_gprofiler(shared_genes_drug_z22)
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## Add a little logic here to use enrichplot::dotplot().
shared_drug_z22_gp[["pvalue_plots"]][["BP"]]

4.2 Our main question of interest

The data structure hs_macr contains our primary macrophages, which are, as shown above, the data we can really sink our teeth into.

Note, we expect some errors when running the combine_de_tables() because not all methods I use are comfortable using the ratio or ratios contrasts we added in the ‘extras’ argument. As a result, when we combine them into the larger output tables, those peculiar contrasts fail. This does not stop it from writing the rest of the results, however.

#test = deseq_pairwise(normalize_expt(hs_macr, filter=TRUE),
#                      model_batch = "svaseq", filter = TRUE,
#                      extra_contrasts = tmrc2_human_extra)

hs_macr_de <- all_pairwise(hs_macr, model_batch = "svaseq",
                           filter = TRUE, extra_contrasts = tmrc2_human_extra)
## 
##      inf_z22      inf_z23    infsb_z22    infsb_z23   uninf_none uninfsb_none 
##           11           12           12           11            4            4
## Removing 0 low-count genes (11756 remaining).
## Setting 2374 low elements to zero.
## transform_counts: Found 2374 values equal to 0, adding 1 to the matrix.
hs_macr_de
## A pairwise differential expression with results from: basic, deseq, edger, limma, noiseq.
## This used a surrogate/batch estimate from: svaseq.
## The primary analysis performed 10 comparisons.
hs_single_table <- combine_de_tables(
  hs_macr_de, keepers = single_tmrc2_keeper,
  excel = glue("excel/macrophage_de/hs_macr_drug_zymo_z22sb_sb-v{ver}.xlsx"))
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.
hs_single_table
## A set of combined differential expression results.
##                              table deseq_sigup deseq_sigdown edger_sigup
## 1 uninfsbnone_vs_infsbz22-inverted          33             0          31
##   edger_sigdown limma_sigup limma_sigdown
## 1             0           2             0
## Error in colSums(temp_data): 'x' must be an array of at least two dimensions
hs_macr_table <- combine_de_tables(
  hs_macr_de, keepers = tmrc2_human_keepers,
  excel = glue("excel/macrophage_de/hs_macr_drug_zymo_table_macr_only-v{ver}.xlsx"))
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_z2322 does not appear in the pairwise data.
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_z2322 does not appear in the pairwise data.
## Did not find z22drugnodrug or z23drugnodrug.
## Did not find z22drugnodrug or z23drugnodrug.
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_drugnodrug does not appear in the pairwise data.
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_drugnodrug does not appear in the pairwise data.
## Did not find z23z22nodrug or z23z22drug.
## Did not find z23z22nodrug or z23z22drug.
hs_macr_table
## A set of combined differential expression results.

##                               table deseq_sigup deseq_sigdown edger_sigup
## 1      uninfnone_vs_infz23-inverted         478           265         472
## 2      uninfnone_vs_infz22-inverted         359             6         340
## 3                  infz23_vs_infz22         349           539         360
## 4              infsbz23_vs_infsbz22         343           252         340
## 5       infz23_vs_infsbz23-inverted         619           828         625
## 6       infz22_vs_infsbz22-inverted         505          1040         520
## 7  uninfsbnone_vs_infsbz23-inverted         461           247         464
## 8  uninfsbnone_vs_infsbz22-inverted          33             0          31
## 9    uninfnone_vs_infsbz23-inverted         839           923         854
## 10   uninfnone_vs_infsbz22-inverted         660           746         672
## 11         uninfsbnone_vs_uninfnone         561           748         564
## 12   z23drugnodrug_vs_z22drugnodrug           0             0         330
## 13       z23z22drug_vs_z23z22nodrug           0             0         330
##    edger_sigdown limma_sigup limma_sigdown
## 1            270         392           251
## 2              6         264            72
## 3            528         451           390
## 4            253         378           216
## 5            821         571           746
## 6           1009         671           925
## 7            249         374           233
## 8              0           2             0
## 9            906         805           914
## 10           733         556           745
## 11           741         514           696
## 12            63         244           135
## 13            63         244           135

combined_to_tsv(hs_macr_table, "macrophage")

hs_macr_sig <- extract_significant_genes(
  hs_macr_table,
  excel = glue("excel/macrophage_de/hs_macr_drug_zymo_sig-v{ver}.xlsx"))
## There is no deseq_logfc column in the table.
## The columns are: ensemblgeneid, ensembltranscriptid, version, transcriptversion, description, genebiotype, cdslength, chromosomename, strand, startposition, endposition, hgncsymbol, uniprotgnsymbol, transcript, edger_logfc, edger_adjp, limma_logfc, limma_adjp, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_b, limma_p, limma_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no deseq_logfc column in the table.
## The columns are: ensemblgeneid, ensembltranscriptid, version, transcriptversion, description, genebiotype, cdslength, chromosomename, strand, startposition, endposition, hgncsymbol, uniprotgnsymbol, transcript, edger_logfc, edger_adjp, limma_logfc, limma_adjp, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_b, limma_p, limma_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no basic_logfc column in the table.
## The columns are: ensemblgeneid, ensembltranscriptid, version, transcriptversion, description, genebiotype, cdslength, chromosomename, strand, startposition, endposition, hgncsymbol, uniprotgnsymbol, transcript, edger_logfc, edger_adjp, limma_logfc, limma_adjp, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_b, limma_p, limma_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no basic_logfc column in the table.
## The columns are: ensemblgeneid, ensembltranscriptid, version, transcriptversion, description, genebiotype, cdslength, chromosomename, strand, startposition, endposition, hgncsymbol, uniprotgnsymbol, transcript, edger_logfc, edger_adjp, limma_logfc, limma_adjp, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_b, limma_p, limma_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
hs_macr_sig
## A set of genes deemed significant according to limma, edger, deseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##                    limma_up limma_down edger_up edger_down deseq_up deseq_down
## z23nosb_vs_uninf        392        251      472        270      478        265
## z22nosb_vs_uninf        264         72      340          6      359          6
## z23nosb_vs_z22nosb      451        390      360        528      349        539
## z23sb_vs_z22sb          378        216      340        253      343        252
## z23sb_vs_z23nosb        571        746      625        821      619        828
## z22sb_vs_z22nosb        671        925      520       1009      505       1040
## z23sb_vs_sb             374        233      464        249      461        247
## z22sb_vs_sb               2          0       31          0       33          0
## z23sb_vs_uninf          805        914      854        906      839        923
## z22sb_vs_uninf          556        745      672        733      660        746
## sb_vs_uninf             514        696      564        741      561        748
## extra_z2322             244        135      330         63        0          0
## extra_drugnodrug        244        135      330         63        0          0
##                    basic_up basic_down
## z23nosb_vs_uninf        203        117
## z22nosb_vs_uninf         78         10
## z23nosb_vs_z22nosb      425        407
## z23sb_vs_z22sb          195        116
## z23sb_vs_z23nosb        538        700
## z22sb_vs_z22nosb        668        892
## z23sb_vs_sb             130         58
## z22sb_vs_sb               5          0
## z23sb_vs_uninf          478        628
## z22sb_vs_uninf          277        414
## sb_vs_uninf             136        132
## extra_z2322               0          0
## extra_drugnodrug          0          0

hs_macr_highsig <- extract_significant_genes(
  hs_macr_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("excel/macrophage_de/hs_macr_drug_zymo_highsig-v{ver}.xlsx"))
## Warning in get_sig_genes(this_table, lfc = lfc, p = p, z = z, n = n, column =
## this_fc_column, : The column deseq_basemean does not appears to be in the
## table, cannot filter by expression.
## Warning in get_sig_genes(this_table, lfc = lfc, p = p, z = z, n = n, column =
## this_fc_column, : The column deseq_basemean does not appears to be in the
## table, cannot filter by expression.
## Warning in get_sig_genes(this_table, lfc = lfc, p = p, z = z, n = n, column =
## this_fc_column, : The column deseq_basemean does not appears to be in the
## table, cannot filter by expression.
## Warning in get_sig_genes(this_table, lfc = lfc, p = p, z = z, n = n, column =
## this_fc_column, : The column deseq_basemean does not appears to be in the
## table, cannot filter by expression.
## There is no deseq_logfc column in the table.
## The columns are: ensemblgeneid, ensembltranscriptid, version, transcriptversion, description, genebiotype, cdslength, chromosomename, strand, startposition, endposition, hgncsymbol, uniprotgnsymbol, transcript, edger_logfc, edger_adjp, limma_logfc, limma_adjp, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_b, limma_p, limma_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no deseq_logfc column in the table.
## The columns are: ensemblgeneid, ensembltranscriptid, version, transcriptversion, description, genebiotype, cdslength, chromosomename, strand, startposition, endposition, hgncsymbol, uniprotgnsymbol, transcript, edger_logfc, edger_adjp, limma_logfc, limma_adjp, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_b, limma_p, limma_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no basic_logfc column in the table.
## The columns are: ensemblgeneid, ensembltranscriptid, version, transcriptversion, description, genebiotype, cdslength, chromosomename, strand, startposition, endposition, hgncsymbol, uniprotgnsymbol, transcript, edger_logfc, edger_adjp, limma_logfc, limma_adjp, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_b, limma_p, limma_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no basic_logfc column in the table.
## The columns are: ensemblgeneid, ensembltranscriptid, version, transcriptversion, description, genebiotype, cdslength, chromosomename, strand, startposition, endposition, hgncsymbol, uniprotgnsymbol, transcript, edger_logfc, edger_adjp, limma_logfc, limma_adjp, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_b, limma_p, limma_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
hs_macr_highsig
## A set of genes deemed significant according to limma, edger, deseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##                    limma_up limma_down edger_up edger_down deseq_up deseq_down
## z23nosb_vs_uninf        269        139      317        139      314        138
## z22nosb_vs_uninf        103          4      110          0      115          0
## z23nosb_vs_z22nosb      221        154      247        174      238        178
## z23sb_vs_z22sb          211        105      210         86      211         84
## z23sb_vs_z23nosb        305        482      306        566      303        570
## z22sb_vs_z22nosb        330        545      301        572      288        598
## z23sb_vs_sb             250        130      279        140      274        140
## z22sb_vs_sb               2          0        9          0       13          0
## z23sb_vs_uninf          499        603      491        605      482        618
## z22sb_vs_uninf          310        479      318        501      303        513
## sb_vs_uninf             291        459      294        495      291        498
## extra_z2322             244        135      330         63        0          0
## extra_drugnodrug        244        135      330         63        0          0
##                    basic_up basic_down
## z23nosb_vs_uninf        163         79
## z22nosb_vs_uninf         33          0
## z23nosb_vs_z22nosb      225        188
## z23sb_vs_z22sb          127         52
## z23sb_vs_z23nosb        305        484
## z22sb_vs_z22nosb        334        551
## z23sb_vs_sb             108         28
## z22sb_vs_sb               0          0
## z23sb_vs_uninf          336        436
## z22sb_vs_uninf          175        281
## sb_vs_uninf             103        109
## extra_z2322               0          0
## extra_drugnodrug          0          0

4.3 gene group upset

nodrug_upset <- upsetr_combined_de(hs_macr_table,
                                   desired_contrasts = c("z22nosb_vs_uninf", "z23nosb_vs_uninf"))
## Error in upsetr_combined_de(hs_macr_table, desired_contrasts = c("z22nosb_vs_uninf", : could not find function "upsetr_combined_de"
pp(file = "images/nodrug_upset.png")
nodrug_upset
## Error in eval(expr, envir, enclos): object 'nodrug_upset' not found
dev.off()
## png 
##   2
drug_upset <- upsetr_combined_de(hs_macr_table,
                                 desired_contrasts = c("z22sb_vs_sb", "z23sb_vs_sb"))
## Error in upsetr_combined_de(hs_macr_table, desired_contrasts = c("z22sb_vs_sb", : could not find function "upsetr_combined_de"
pp(file = "images/drug_upset.png")
drug_upset
## Error in eval(expr, envir, enclos): object 'drug_upset' not found
dev.off()
## png 
##   2

5 Significance barplot of interest

Olga kindly sent a set of particularly interesting contrasts and colors for a significance barplot, they include the following:

  • z2.3 vs. uninfected.
  • z2.2 vs. uninfected.
  • z2.3 vs z2.2
  • z2.3Sbv vs z2.3
  • z2.2Sbv vs z2.2
  • z2.3Sbv vs z2.2Sbv
  • Sbv vs uninfected.

The existing set of ‘keepers’ exvised to these is taken from the extant set of ‘tmrc2_human_keepers’ and is as follows:

barplot_keepers <- list(
  ## z2.3 vs uninfected
  "z23nosb_vs_uninf" = c("infz23", "uninfnone"),
  ## z2.2 vs uninfected
  "z22nosb_vs_uninf" = c("infz22", "uninfnone"),
  ## z2.3 vs z2.2
  "z23nosb_vs_z22nosb" = c("infz23", "infz22"),
  ## z2.3Sbv vs z2.3
  "z23sb_vs_z23nosb" = c("infsbz23", "infz23"),
  ## z2.2Sbv vs z2.2
  "z22sb_vs_z22nosb" = c("infsbz22", "infz22"),
  ## z2.3Sbv vs z2.2Sbv
  "z23sb_vs_z22sb" = c("infsbz23", "infsbz22"),
  ## Sbv vs uninfected.
  "sb_vs_uninf" = c("uninfsbnone", "uninfnone"))
barplot_combined <- combine_de_tables(
  hs_macr_de, keepers = barplot_keepers,
  excel = glue("excel/macrophage_de/hs_macr_drug_zymo_7contrasts-v{ver}.xlsx"))
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: noiseq_logfc.

Now let us use the colors suggested by Olga to make a barplot of these…

color_list <-  c( "#de8bf9", "#ad07e3","#410257", "#ffa0a0", "#f94040", "#a00000")
barplot_sig <- extract_significant_genes(
  barplot_combined, color_list = color_list, according_to = "deseq",
  excel = glue("excel/macrophage_de/hs_macr_drug_zymo_7contrasts_sig-v{ver}.xlsx"))
barplot_sig
## A set of genes deemed significant according to deseq.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##                    deseq_up deseq_down
## z23nosb_vs_uninf        478        265
## z22nosb_vs_uninf        359          6
## z23nosb_vs_z22nosb      349        539
## z23sb_vs_z23nosb        619        828
## z22sb_vs_z22nosb        505       1040
## z23sb_vs_z22sb          343        252
## sb_vs_uninf             561        748

6 PROPER

In our last meeting there were some questions about the statistical power of different future experimental designs. One thing I can do is to use PROPER to estimate the power of an extant dataset and infer from that the likely power of other designs.

In order to use proper, one must feed it one or more DE tables.

power_estimate <- simple_proper(hs_single_table)
## Working on contrast 1: uninfsbnone_vs_infsbz22-inverted.
## Loading required package: edgeR
## Loading required package: limma
## 
## Attaching package: 'limma'
## The following object is masked from 'package:BiocGenerics':
## 
##     plotMA
##     SS=3,3 SS=5,5 SS=7,7 SS=10,10
## 0.2   0.70   0.72   0.73     0.75
## 0.5   0.78   0.79   0.79     0.79
## 1     0.96   0.98   0.98     0.99
## 2     0.84   0.84   0.84     0.84
## 5     0.88   0.88   0.88     0.88
## 10    0.89   0.88   0.88     0.88
power_estimate
## Assuming similar expression patterns and variance to the
## provided experiment, comparing uninfsbnone_vs_infsbz22, and a FDR
## cutoff of 0.05, simulations by PROPER (DOI:10.1093/bioinformatics/btu640)
## suggest that it should be possible to identify 80% of DE genes with a |log2FC| >= 1
## when the sequencing depth is in the range of (80,160] using 5
## replicates in each group.
## 
##   Assuming the 11756 genes used have a mean length of 2000 and the sequencing run
## produces 200nt per read, ~834,123,060 reads will be required per sample to
## approach 160 reads per gene.
## Error in xy.coords(x, y, xlabel, ylabel, log): 'x' is a list, but does not have components 'x' and 'y'
power_estimate[[1]][["power_plot"]]

power_estimate[[1]][["powertd_plot"]]

power_estimate[[1]][["powerfd_plot"]]

6.0.1 Our main questions in U937

Let us do the same comparisons in the U937 samples, though I will not do the extra contrasts, primarily because I think the dataset is less likely to support them.

u937_de <- all_pairwise(u937_expt, model_batch = "svaseq",
                        filter = TRUE, do_noiseq = FALSE)
## 
##      inf_z22      inf_z23    infsb_z22    infsb_z23   uninf_none uninfsb_none 
##            3            3            3            3            1            1
## Removing 0 low-count genes (10751 remaining).
## Setting 5 low elements to zero.
## transform_counts: Found 5 values equal to 0, adding 1 to the matrix.
u937_de
## A pairwise differential expression with results from: basic, deseq, edger, limma.
## This used a surrogate/batch estimate from: svaseq.
## The primary analysis performed 6 comparisons.
u937_table <- combine_de_tables(
  u937_de, keepers = u937_keepers,
  excel = glue("excel/macrophage_de/u937_drug_zymo_table-v{ver}.xlsx"))
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
## Inverting column: basic_logfc.
## Inverting column: deseq_logfc.
## Inverting column: edger_logfc.
## Inverting column: limma_logfc.
u937_table
## A set of combined differential expression results.

##                               table deseq_sigup deseq_sigdown edger_sigup
## 1      uninfnone_vs_infz23-inverted           0             5           2
## 2      uninfnone_vs_infz22-inverted           0             0           0
## 3                  infz23_vs_infz22           1             0          17
## 4              infsbz23_vs_infsbz22           0             0           0
## 5       infz23_vs_infsbz23-inverted         256           171         311
## 6       infz22_vs_infsbz22-inverted         298           154         305
## 7  uninfsbnone_vs_infsbz23-inverted           0             0           2
## 8  uninfsbnone_vs_infsbz22-inverted           0             0           2
## 9    uninfnone_vs_infsbz23-inverted         296           151         306
## 10   uninfnone_vs_infsbz22-inverted         294           169         300
## 11         uninfsbnone_vs_uninfnone         239           119         261
##    edger_sigdown limma_sigup limma_sigdown
## 1              5           0             3
## 2              5           0             2
## 3              6           3             4
## 4              1           0             2
## 5            176         226           196
## 6            149         220           190
## 7              0           0             0
## 8              5           1             4
## 9            155         235           183
## 10           175         230           211
## 11           127         196           155

combined_to_tsv(u937_table, celltype = "u937")

u937_sig <- extract_significant_genes(
  u937_table,
  excel = glue("excel/macrophage_de/u937_drug_zymo_sig-v{ver}.xlsx"))
u937_sig
## A set of genes deemed significant according to limma, edger, deseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##                    limma_up limma_down edger_up edger_down deseq_up deseq_down
## z23nosb_vs_uninf          0          3        2          5        0          5
## z22nosb_vs_uninf          0          2        0          5        0          0
## z23nosb_vs_z22nosb        3          4       17          6        1          0
## z23sb_vs_z22sb            0          2        0          1        0          0
## z23sb_vs_z23nosb        226        196      311        176      256        171
## z22sb_vs_z22nosb        220        190      305        149      298        154
## z23sb_vs_sb               0          0        2          0        0          0
## z22sb_vs_sb               1          4        2          5        0          0
## z23sb_vs_uninf          235        183      306        155      296        151
## z22sb_vs_uninf          230        211      300        175      294        169
## sb_vs_uninf             196        155      261        127      239        119
##                    basic_up basic_down
## z23nosb_vs_uninf          0          0
## z22nosb_vs_uninf          0          0
## z23nosb_vs_z22nosb        0          0
## z23sb_vs_z22sb            0          0
## z23sb_vs_z23nosb        111         97
## z22sb_vs_z22nosb         86         68
## z23sb_vs_sb               0          0
## z22sb_vs_sb               0          0
## z23sb_vs_uninf            0          0
## z22sb_vs_uninf            0          0
## sb_vs_uninf               0          0

u937_highsig <- extract_significant_genes(
  u937_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("excel/macrophage_de/u937_drug_zymo_highsig-v{ver}.xlsx"))
u937_highsig
## A set of genes deemed significant according to limma, edger, deseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##                    limma_up limma_down edger_up edger_down deseq_up deseq_down
## z23nosb_vs_uninf          0          3        0          4        0          4
## z22nosb_vs_uninf          0          1        0          4        0          0
## z23nosb_vs_z22nosb        2          3        6          4        1          0
## z23sb_vs_z22sb            0          0        0          0        0          0
## z23sb_vs_z23nosb        149        125      174        116      160        120
## z22sb_vs_z22nosb        130        111      152        104      149        107
## z23sb_vs_sb               0          0        0          0        0          0
## z22sb_vs_sb               0          1        0          1        0          0
## z23sb_vs_uninf          145         99      155         97      154         96
## z22sb_vs_uninf          143        119      155        115      155        116
## sb_vs_uninf             126         91      137         89      136         89
##                    basic_up basic_down
## z23nosb_vs_uninf          0          0
## z22nosb_vs_uninf          0          0
## z23nosb_vs_z22nosb        0          0
## z23sb_vs_z22sb            0          0
## z23sb_vs_z23nosb         91         83
## z22sb_vs_z22nosb         71         52
## z23sb_vs_sb               0          0
## z22sb_vs_sb               0          0
## z23sb_vs_uninf            0          0
## z22sb_vs_uninf            0          0
## sb_vs_uninf               0          0

6.0.1.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"))
upset_plots_hs_macr[["both"]]

groups <- upset_plots_hs_macr[["both_groups"]]
shared_genes <- attr(groups, "elements")[groups[[2]]] %>%
  gsub(pattern = "^gene:", replacement = "")
length(shared_genes)
## [1] 387
shared_gp <- simple_gprofiler(shared_genes)
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## Add a little logic here to use enrichplot::dotplot().
shared_gp[["pvalue_plots"]][["MF"]]

shared_gp[["pvalue_plots"]][["BP"]]

shared_gp[["pvalue_plots"]][["REAC"]]

drug_genes <- attr(groups, "elements")[groups[["z23sb_vs_z22sb"]]] %>%
  gsub(pattern = "^gene:", replacement = "")
drugonly_gp <- simple_gprofiler(drug_genes)
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## Add a little logic here to use enrichplot::dotplot().
drugonly_gp[["pvalue_plots"]][["BP"]]

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

both_sig <- hs_macr_sig
names(both_sig[["deseq"]][["ups"]]) <- paste0("macr_", names(both_sig[["deseq"]][["ups"]]))
names(both_sig[["deseq"]][["downs"]]) <- paste0("macr_", names(both_sig[["deseq"]][["downs"]]))
u937_deseq <- u937_sig[["deseq"]]
names(u937_deseq[["ups"]]) <- paste0("u937_", names(u937_deseq[["ups"]]))
names(u937_deseq[["downs"]]) <- paste0("u937_", names(u937_deseq[["downs"]]))
both_sig[["deseq"]][["ups"]] <- c(both_sig[["deseq"]][["ups"]], u937_deseq[["ups"]])
both_sig[["deseq"]][["downs"]] <- c(both_sig[["deseq"]][["ups"]], u937_deseq[["downs"]])
summary(both_sig[["deseq"]][["ups"]])
##                         Length Class      Mode
## macr_z23nosb_vs_uninf   58     data.frame list
## macr_z22nosb_vs_uninf   58     data.frame list
## macr_z23nosb_vs_z22nosb 58     data.frame list
## macr_z23sb_vs_z22sb     58     data.frame list
## macr_z23sb_vs_z23nosb   58     data.frame list
## macr_z22sb_vs_z22nosb   58     data.frame list
## macr_z23sb_vs_sb        58     data.frame list
## macr_z22sb_vs_sb        58     data.frame list
## macr_z23sb_vs_uninf     58     data.frame list
## macr_z22sb_vs_uninf     58     data.frame list
## macr_sb_vs_uninf        58     data.frame list
## macr_extra_z2322         0     data.frame list
## macr_extra_drugnodrug    0     data.frame list
## u937_z23nosb_vs_uninf   50     data.frame list
## u937_z22nosb_vs_uninf   50     data.frame list
## u937_z23nosb_vs_z22nosb 50     data.frame list
## u937_z23sb_vs_z22sb     50     data.frame list
## u937_z23sb_vs_z23nosb   50     data.frame list
## u937_z22sb_vs_z22nosb   50     data.frame list
## u937_z23sb_vs_sb        50     data.frame list
## u937_z22sb_vs_sb        50     data.frame list
## u937_z23sb_vs_uninf     50     data.frame list
## u937_z22sb_vs_uninf     50     data.frame list
## u937_sb_vs_uninf        50     data.frame list
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"))
upset_plots_both$both

6.0.1.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)

macr_u937_comparison$lfc_heat

macr_u937_venns <- compare_significant_contrasts(hs_macr_sig, second_sig_tables = u937_sig,
                                                 contrasts = "z23sb_vs_z23nosb")

macr_u937_venns$up_plot

macr_u937_venns$down_plot

macr_u937_venns_v2 <- compare_significant_contrasts(hs_macr_sig, second_sig_tables = u937_sig,
                                                    contrasts = "z22sb_vs_z22nosb")

macr_u937_venns_v2$up_plot

macr_u937_venns_v2$down_plot

macr_u937_venns_v3 <- compare_significant_contrasts(hs_macr_sig, second_sig_tables = u937_sig,
                                                    contrasts = "sb_vs_uninf")

macr_u937_venns_v3$up_plot

macr_u937_venns_v3$down_plot

6.0.2 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")
macru937_z23z22_plot <- plot_linear_scatter(comparison_df[, c("deseq_logfc.x", "deseq_logfc.y")])
macru937_z23z22_plot$scatter

comparison_df <- merge(hs_macr_table[["data"]][["z23nosb_vs_z22nosb"]],
                       u937_table[["data"]][["z23nosb_vs_z22nosb"]],
                       by = "row.names")
macru937_z23z22_plot <- plot_linear_scatter(comparison_df[, c("deseq_logfc.x", "deseq_logfc.y")])
macru937_z23z22_plot$scatter

6.0.2.1 Add donor to the contrasts, no sva

no_power_fact <- paste0(pData(hs_macr)[["donor"]], "_",
                        pData(hs_macr)[["condition"]])
table(pData(hs_macr)[["donor"]])
## 
## d01 d02 d09 d81 
##  13  14  13  14
table(no_power_fact)
## no_power_fact
##      d01_inf_z22      d01_inf_z23    d01_infsb_z22    d01_infsb_z23 
##                2                3                3                3 
##   d01_uninf_none d01_uninfsb_none      d02_inf_z22      d02_inf_z23 
##                1                1                3                3 
##    d02_infsb_z22    d02_infsb_z23   d02_uninf_none d02_uninfsb_none 
##                3                3                1                1 
##      d09_inf_z22      d09_inf_z23    d09_infsb_z22    d09_infsb_z23 
##                3                3                3                2 
##   d09_uninf_none d09_uninfsb_none      d81_inf_z22      d81_inf_z23 
##                1                1                3                3 
##    d81_infsb_z22    d81_infsb_z23   d81_uninf_none d81_uninfsb_none 
##                3                3                1                1
hs_nopower <- set_expt_conditions(hs_macr, fact = no_power_fact)
## The numbers of samples by condition are:
## 
##      d01_inf_z22      d01_inf_z23    d01_infsb_z22    d01_infsb_z23 
##                2                3                3                3 
##   d01_uninf_none d01_uninfsb_none      d02_inf_z22      d02_inf_z23 
##                1                1                3                3 
##    d02_infsb_z22    d02_infsb_z23   d02_uninf_none d02_uninfsb_none 
##                3                3                1                1 
##      d09_inf_z22      d09_inf_z23    d09_infsb_z22    d09_infsb_z23 
##                3                3                3                2 
##   d09_uninf_none d09_uninfsb_none      d81_inf_z22      d81_inf_z23 
##                1                1                3                3 
##    d81_infsb_z22    d81_infsb_z23   d81_uninf_none d81_uninfsb_none 
##                3                3                1                1
hs_nopower <- subset_expt(hs_nopower, subset="macrophagezymodeme!='none'")
## The samples excluded are: TMRC30059, TMRC30060, TMRC30266, TMRC30268, TMRC30326, TMRC30327, TMRC30312, TMRC30313.
## subset_expt(): There were 54, now there are 46 samples.
hs_nopower_nosva_de <- all_pairwise(hs_nopower, model_batch = FALSE, filter = TRUE)
## 
##   d01_inf_z22   d01_inf_z23 d01_infsb_z22 d01_infsb_z23   d02_inf_z22 
##             2             3             3             3             3 
##   d02_inf_z23 d02_infsb_z22 d02_infsb_z23   d09_inf_z22   d09_inf_z23 
##             3             3             3             3             3 
## d09_infsb_z22 d09_infsb_z23   d81_inf_z22   d81_inf_z23 d81_infsb_z22 
##             3             2             3             3             3 
## d81_infsb_z23 
##             3

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("excel/macrophage_de/hs_nopower_table-v{ver}.xlsx"))
##                                  extra_contrasts = extra)
hs_nopower_nosva_sig <- extract_significant_genes(
  hs_nopower_nosva_table,
  excel = glue("excel/macrophage_de/hs_nopower_nosva_sig-v{ver}.xlsx"))

d01d02_zymo_nosva_comp <- merge(hs_nopower_nosva_table[["data"]][["d01_zymo"]],
                                hs_nopower_nosva_table[["data"]][["d02_zymo"]],
                                by="row.names")
d0102_zymo_nosva_plot <- plot_linear_scatter(d01d02_zymo_nosva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
d0102_zymo_nosva_plot$scatter

d0102_zymo_nosva_plot$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[[xcol]] and df[[ycol]]
## t = 199, df = 11718, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.8747 0.8829
## sample estimates:
##    cor 
## 0.8789
d0102_zymo_nosva_plot$lm_rsq
## [1] 0.8266
d09d81_zymo_nosva_comp <- merge(hs_nopower_nosva_table[["data"]][["d09_zymo"]],
                                hs_nopower_nosva_table[["data"]][["d81_zymo"]],
                                by="row.names")
d0981_zymo_nosva_plot <- plot_linear_scatter(d09d81_zymo_nosva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
d0981_zymo_nosva_plot$scatter

d0981_zymo_nosva_plot$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[[xcol]] and df[[ycol]]
## t = 103, df = 11718, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.6801 0.6991
## sample estimates:
##    cor 
## 0.6897
d0981_zymo_nosva_plot$lm_rsq
## [1] 0.4553
d01d81_zymo_nosva_comp <- merge(hs_nopower_nosva_table[["data"]][["d01_zymo"]],
                                hs_nopower_nosva_table[["data"]][["d81_zymo"]],
                                by="row.names")
d0181_zymo_nosva_plot <- plot_linear_scatter(d01d81_zymo_nosva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
d0181_zymo_nosva_plot$scatter

d0181_zymo_nosva_plot$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[[xcol]] and df[[ycol]]
## t = 84, df = 11718, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.6018 0.6244
## sample estimates:
##    cor 
## 0.6133
d0181_zymo_nosva_plot$lm_rsq
## [1] 0.2654
upset_plots_nosva <- upsetr_sig(hs_nopower_nosva_sig, both=TRUE,
                                contrasts=c("d01_zymo", "d02_zymo", "d09_zymo", "d81_zymo"))
upset_plots_nosva$up

upset_plots_nosva$down

upset_plots_nosva$both

## 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"]]
shared_genes <- attr(groups, "elements")[groups[[7]]] %>%
  gsub(pattern = "^gene:", replacement = "")
shared_gp <- simple_gprofiler(shared_genes)
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## Add a little logic here to use enrichplot::dotplot().
shared_gp$pvalue_plots$MF

shared_gp$pvalue_plots$BP

shared_gp$pvalue_plots$REAC

shared_gp$pvalue_plots$WP

6.0.2.2 Add donor to the contrasts, sva

hs_nopower_sva_de <- all_pairwise(hs_nopower, model_batch = "svaseq", filter = TRUE)
## 
##   d01_inf_z22   d01_inf_z23 d01_infsb_z22 d01_infsb_z23   d02_inf_z22 
##             2             3             3             3             3 
##   d02_inf_z23 d02_infsb_z22 d02_infsb_z23   d09_inf_z22   d09_inf_z23 
##             3             3             3             3             3 
## d09_infsb_z22 d09_infsb_z23   d81_inf_z22   d81_inf_z23 d81_infsb_z22 
##             3             2             3             3             3 
## d81_infsb_z23 
##             3
## Removing 0 low-count genes (11720 remaining).
## Setting 2174 low elements to zero.
## transform_counts: Found 2174 values equal to 0, adding 1 to the matrix.

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("excel/macrophage_de/hs_nopower_table-v{ver}.xlsx"))
## Deleting the file excel/macrophage_de/hs_nopower_table-v202404.xlsx before writing the tables.
##                                  extra_contrasts = extra)
hs_nopower_sva_sig <- extract_significant_genes(
  hs_nopower_sva_table,
  excel = glue("excel/macrophage_de/hs_nopower_sva_sig-v{ver}.xlsx"))

d01d02_zymo_sva_comp <- merge(hs_nopower_sva_table[["data"]][["d01_zymo"]],
                              hs_nopower_sva_table[["data"]][["d02_zymo"]],
                              by="row.names")
d0102_zymo_sva_plot <- plot_linear_scatter(d01d02_zymo_sva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
d0102_zymo_sva_plot$scatter

d0102_zymo_sva_plot$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[[xcol]] and df[[ycol]]
## t = 163, df = 11718, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.8277 0.8387
## sample estimates:
##    cor 
## 0.8333
d0102_zymo_sva_plot$lm_rsq
## [1] 0.72
d09d81_zymo_sva_comp <- merge(hs_nopower_sva_table[["data"]][["d09_zymo"]],
                              hs_nopower_sva_table[["data"]][["d81_zymo"]],
                              by="row.names")
d0981_zymo_sva_plot <- plot_linear_scatter(d09d81_zymo_sva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
d0981_zymo_sva_plot$scatter

d0981_zymo_sva_plot$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[[xcol]] and df[[ycol]]
## t = 103, df = 11718, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.680 0.699
## sample estimates:
##    cor 
## 0.6897
d0981_zymo_sva_plot$lm_rsq
## [1] 0.4552
d01d81_zymo_sva_comp <- merge(hs_nopower_sva_table[["data"]][["d01_zymo"]],
                              hs_nopower_sva_table[["data"]][["d81_zymo"]],
                              by="row.names")
d0181_zymo_sva_plot <- plot_linear_scatter(d01d81_zymo_sva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
d0181_zymo_sva_plot$scatter

d0181_zymo_sva_plot$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[[xcol]] and df[[ycol]]
## t = 77, df = 11718, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.5691 0.5931
## sample estimates:
##    cor 
## 0.5813
d0181_zymo_sva_plot$lm_rsq
## [1] 0.2183
upset_plots_sva <- upsetr_sig(hs_nopower_sva_sig, both=TRUE,
                              contrasts=c("d01_zymo", "d02_zymo", "d09_zymo", "d81_zymo"))
upset_plots_sva$up

upset_plots_sva$down

upset_plots_sva$both

## 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"]]
shared_genes <- attr(groups, "elements")[groups[[7]]] %>%
  gsub(pattern = "^gene:", replacement = "")
shared_gp <- simple_gprofiler(shared_genes)
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## Add a little logic here to use enrichplot::dotplot().
shared_gp$pvalue_plots$MF

shared_gp$pvalue_plots$BP

shared_gp$pvalue_plots$REAC

shared_gp$pvalue_plots$WP

6.0.3 Donor comparison

hs_donors <- set_expt_conditions(hs_macr, fact = "donor")
## The numbers of samples by condition are:
## 
## d01 d02 d09 d81 
##  13  14  13  14
donor_de <- all_pairwise(hs_donors, model_batch="svaseq", filter=TRUE)
## 
## d01 d02 d09 d81 
##  13  14  13  14
## Removing 0 low-count genes (11756 remaining).
## Setting 1225 low elements to zero.
## transform_counts: Found 1225 values equal to 0, adding 1 to the matrix.
donor_de
## A pairwise differential expression with results from: basic, deseq, ebseq, edger, limma, noiseq.
## This used a surrogate/batch estimate from: svaseq.
## The primary analysis performed 15 comparisons.
donor_table <- combine_de_tables(
  donor_de,
  excel=glue("excel/macrophage_de/donor_tables-v{ver}.xlsx"))
donor_table
## A set of combined differential expression results.

##        table deseq_sigup deseq_sigdown edger_sigup edger_sigdown limma_sigup
## 1 d02_vs_d01         299           386         310           375         356
## 2 d09_vs_d01         535           471         537           465         524
## 3 d81_vs_d01         677           762         680           757         664
## 4 d09_vs_d02         408           269         407           276         369
## 5 d81_vs_d02         574           652         568           655         529
## 6 d81_vs_d09         217           417         213           421         217
##   limma_sigdown
## 1           356
## 2           468
## 3           760
## 4           306
## 5           677
## 6           423

donor_sig <- extract_significant_genes(
  donor_table,
  excel = glue("excel/macrophage_de/donor_sig-v{ver}.xlsx"))
donor_sig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##            limma_up limma_down edger_up edger_down deseq_up deseq_down ebseq_up
## d02_vs_d01      356        356      310        375      299        386      242
## d09_vs_d01      524        468      537        465      535        471      485
## d81_vs_d01      664        760      680        757      677        762      576
## d09_vs_d02      369        306      407        276      408        269      211
## d81_vs_d02      529        677      568        655      574        652      299
## d81_vs_d09      217        423      213        421      217        417       86
##            ebseq_down basic_up basic_down
## d02_vs_d01        136      270        279
## d09_vs_d01        190      475        409
## d81_vs_d01        385      603        625
## d09_vs_d02        115      268        202
## d81_vs_d02        378      393        449
## d81_vs_d09        200      133        226

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

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

7 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)
for (g in seq_len(length(all_gp))) {
  name <- names(all_gp)[g]
  datum <- all_gp[[name]]
  filename <- glue("excel/macrophage_de/gprofiler/{name}_gprofiler-v{ver}.xlsx")
  written <- sm(write_gprofiler_data(datum, excel = filename))
}

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

8.1 Individual zymodemes vs. uninfected

8.1.1 Infected with z2.3 no Antimonial vs. Uninfected

plot_colors <- get_expt_colors(hs_macr_table[["input"]][["input"]])
x_limits <- c(-20, 10)

## The original plot from my xlsx file
hs_macr_table$plots$z23nosb_vs_uninf$deseq_vol_plots
## Warning: ggrepel: 1 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

z23nosb_vs_uninf_volcano <- plot_volcano_condition_de(
  input = hs_macr_table[["data"]][["z23nosb_vs_uninf"]],
  fc_col = "deseq_logfc", p_col = "deseq_adjp",
  label = 10, label_column = "hgncsymbol", invert = TRUE,
  color_high = plot_colors[["uninfnone"]], color_low = plot_colors[["infz23"]])
z23nosb_vs_uninf_volcano$plot +
  scale_x_continuous(limits = x_limits)
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_point()`).
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_text_repel()`).
## Warning: ggrepel: 1 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

plotly::ggplotly(z23nosb_vs_uninf_volcano$plot)
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
z23nosb_vs_uninf_volcano_nol <- plot_volcano_condition_de(
  input = hs_macr_table[["data"]][["z23nosb_vs_uninf"]],
  fc_col = "deseq_logfc", p_col = "deseq_adjp",
  label = NULL, label_column = "hgncsymbol", invert = TRUE,
  color_high = plot_colors[["uninfnone"]], color_low = plot_colors[["infz23"]])
z23nosb_vs_uninf_volcano_nol$plot +
  scale_x_continuous(limits = x_limits)
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_point()`).

all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["REAC"]]

## Reactome, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["KEGG"]]

## KEGG, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["MF"]]

## MF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["TF"]]

## TF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["WP"]]

## WikiPathways, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_uninf_up"]][["interactive_plots"]][["WP"]]
all_gp[["z23nosb_vs_uninf_down"]][["pvalue_plots"]][["REAC"]]
## NULL
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23nosb_vs_uninf_down"]][["pvalue_plots"]][["MF"]]

## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23nosb_vs_uninf_down"]][["pvalue_plots"]][["TF"]]

## TF, zymodeme2.3 without drug vs. uninfected without drug, down.

8.1.2 Infected with z2.2 no Antimonial vs. Uninfected

## The original plot
hs_macr_table$plots$z22nosb_vs_uninf$deseq_vol_plots
## Warning: ggrepel: 10 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

z22nosb_vs_uninf_volcano <- plot_volcano_condition_de(
  hs_macr_table[["data"]][["z22nosb_vs_uninf"]], "z22nosb_vs_uninf",
  fc_col = "deseq_logfc", p_col = "deseq_adjp",
  label = 10, label_column = "hgncsymbol", invert = TRUE,
  color_high = plot_colors[["uninfnone"]], color_low = plot_colors[["infz22"]])
z22nosb_vs_uninf_volcano$plot +
  scale_x_continuous(limits = x_limits)
## Warning: ggrepel: 10 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

plotly::ggplotly(z22nosb_vs_uninf_volcano$plot)
## Warning in geom2trace.default(dots[[1L]][[3L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
## Warning in geom2trace.default(dots[[1L]][[3L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
## Warning in geom2trace.default(dots[[1L]][[3L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
z22nosb_vs_uninf_volcano_nol <- plot_volcano_condition_de(
  hs_macr_table[["data"]][["z22nosb_vs_uninf"]], "z22nosb_vs_uninf",
  fc_col = "deseq_logfc", p_col = "deseq_adjp",
  label = NULL, label_column = "hgncsymbol", invert = TRUE,
  color_high = plot_colors[["uninfnone"]], color_low = plot_colors[["infz22"]])
z22nosb_vs_uninf_volcano_nol$plot +
  scale_x_continuous(limits = x_limits)

all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["REAC"]]

## Reactome, zymodeme2.2 without drug vs. uninfected without drug, up.
all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["MF"]]

## MF, zymodeme2.2 without drug vs. uninfected without drug, up.
all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["TF"]]

## TF, zymodeme2.2 without drug vs. uninfected without drug, up.
all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["WP"]]

## WikiPathways, zymodeme2.2 without drug vs. uninfected without drug, up.

all_gp[["z22nosb_vs_uninf_down"]][["pvalue_plots"]][["REAC"]]
## NULL
## Reactome, zymodeme2.2 without drug vs. uninfected without drug, down.
all_gp[["z22nosb_vs_uninf_down"]][["pvalue_plots"]][["MF"]]
## NULL
## MF, zymodeme2.2 without drug vs. uninfected without drug, down.
all_gp[["z22nosb_vs_uninf_down"]][["pvalue_plots"]][["TF"]]
## NULL
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.

8.1.3 Infected with z2.3 treated vs. Uninfected treated

## The original plot
hs_macr_table$plots$z23sb_vs_sb$deseq_vol_plots
## Warning: ggrepel: 5 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

z23sb_vs_uninfsb_volcano <- plot_volcano_condition_de(
  hs_macr_table[["data"]][["z23sb_vs_sb"]], "z23sb_vs_sb",
  fc_col = "deseq_logfc", p_col = "deseq_adjp",
  label = 10, label_column = "hgncsymbol", invert = TRUE,
  color_high = plot_colors[["infsbz23"]], color_low = plot_colors[["uninfsbnone"]])
z23sb_vs_uninfsb_volcano$plot +
  scale_x_continuous(limits = x_limits)
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_point()`).
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_text_repel()`).
## Warning: ggrepel: 5 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

plotly::ggplotly(z23sb_vs_uninfsb_volcano$plot)
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
z23sb_vs_uninfsb_volcano <- plot_volcano_condition_de(
  hs_macr_table[["data"]][["z23sb_vs_sb"]], "z23sb_vs_sb",
  fc_col = "deseq_logfc", p_col = "deseq_adjp",
  label = NULL, label_column = "hgncsymbol", invert = TRUE,
  color_high = plot_colors[["infsbz23"]], color_low = plot_colors[["uninfsbnone"]])
z23sb_vs_uninfsb_volcano$plot +
  scale_x_continuous(limits = x_limits)
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_point()`).

8.1.4 Infected with z2.3 untreated vs. z2.2 untreated

## The original plot
hs_macr_table$plots$z23nosb_vs_z22nosb$deseq_vol_plots

z23nosb_vs_z22nosb_volcano <- plot_volcano_condition_de(
  hs_macr_table[["data"]][["z23nosb_vs_z22nosb"]], "z23nosb_vs_z22nosb",
  fc_col = "deseq_logfc", p_col = "deseq_adjp",
  label = 10, label_column = "hgncsymbol", invert = TRUE,
  color_high = plot_colors[["infz23"]], color_low = plot_colors[["infz22"]])
z23nosb_vs_z22nosb_volcano$plot +
  scale_x_continuous(limits = x_limits)

8.1.5 Infected with z2.3 treated vs. z2.2 treated

## The original plot
hs_macr_table$plots$z23sb_vs_z22sb$deseq_vol_plots
## Warning: ggrepel: 3 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

z23sb_vs_z22sb_volcano <- plot_volcano_condition_de(
  hs_macr_table[["data"]][["z23sb_vs_z22sb"]], "z23sb_vs_z22sb",
  fc_col = "deseq_logfc", p_col = "deseq_adjp",
  label = 10, label_column = "hgncsymbol", invert = FALSE,
  color_high = plot_colors[["infsbz23"]], color_low = plot_colors[["infsbz22"]])
z23sb_vs_z22sb_volcano$plot +
  scale_x_continuous(limits = x_limits)
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_point()`).
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_text_repel()`).
## Warning: ggrepel: 3 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

8.1.6 Infected with z2.3 SB treated vs. z2.3 untreated

## The original plot
hs_macr_table$plots$z23sb_vs_z23nosb$deseq_vol_plots

z23sb_vs_z23nosb_volcano <- plot_volcano_condition_de(
  hs_macr_table[["data"]][["z23sb_vs_z23nosb"]], "z23sb_vs_z23nosb",
  fc_col = "deseq_logfc", p_col = "deseq_adjp",
  label = 10, label_column = "hgncsymbol", invert = TRUE,
  color_low = plot_colors[["infsbz23"]], color_high = plot_colors[["infz23"]])
z23sb_vs_z23nosb_volcano$plot +
  scale_x_continuous(limits = x_limits)
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_point()`).
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_text_repel()`).

8.1.7 Infected with z2.3 SB treated vs. z2.3 untreated

## The original plot
hs_macr_table$plots$z22sb_vs_z22nosb$deseq_vol_plots

z22sb_vs_z22nosb_volcano <- plot_volcano_condition_de(
  hs_macr_table[["data"]][["z22sb_vs_z22nosb"]], "z22sb_vs_z22nosb",
  fc_col = "deseq_logfc", p_col = "deseq_adjp",
  label = 10, label_column = "hgncsymbol", invert = TRUE,
  color_low = plot_colors[["infsbz22"]], color_high = plot_colors[["infz22"]])
z22sb_vs_z22nosb_volcano$plot +
  scale_x_continuous(limits = x_limits)

8.1.8 Infected with z2.3 SB treated vs. uninfected treated

## The original plot
hs_macr_table$plots$z23sb_vs_sb$deseq_vol_plots
## Warning: ggrepel: 5 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

z23sb_vs_sb_volcano <- plot_volcano_condition_de(
  hs_macr_table[["data"]][["z23sb_vs_sb"]], "z23sb_vs_sb",
  fc_col = "deseq_logfc", p_col = "deseq_adjp",
  label = 10, label_column = "hgncsymbol", invert = TRUE,
  color_low = plot_colors[["infsbz23"]], color_high = plot_colors[["uninfsbnone"]])
z23sb_vs_sb_volcano$plot +
  scale_x_continuous(limits = x_limits)
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_point()`).
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_text_repel()`).
## Warning: ggrepel: 5 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

8.1.9 Infected with z2.2 SB treated vs. uninfected treated

## The original plot
hs_macr_table$plots$z22sb_vs_sb$deseq_vol_plots
## Warning: ggrepel: 2 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

z22sb_vs_sb_volcano <- plot_volcano_condition_de(
  hs_macr_table[["data"]][["z22sb_vs_sb"]], "z22sb_vs_sb",
  fc_col = "deseq_logfc", p_col = "deseq_adjp",
  label = 10, label_column = "hgncsymbol", invert = TRUE,
  color_low = plot_colors[["infsbz22"]], color_high = plot_colors[["uninfsbnone"]])
z22sb_vs_sb_volcano$plot +
  scale_x_continuous(limits = x_limits)
## Warning: ggrepel: 13 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

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_macr_sig[["deseq"]][["ups"]][["z23sb_vs_uninf"]]),
                                "nodrug" = rownames(hs_macr_sig[["deseq"]][["ups"]][["z23nosb_vs_uninf"]])))
pp(file="images/z23_vs_uninf_venn_up.png")
Vennerable::plot(shared)
dev.off()
## png 
##   2
Vennerable::plot(shared)

## I see 910 z23sb/uninf and 670 no z23nosb/uninf genes in the venn diagram.
length(shared@IntersectionSets[["10"]]) + length(shared@IntersectionSets[["11"]])
## [1] 839
dim(hs_macr_sig[["deseq"]][["ups"]][["z23sb_vs_uninf"]])
## [1] 839  58
shared <- Vennerable::Venn(list("drug" = rownames(hs_macr_sig[["deseq"]][["ups"]][["z22sb_vs_uninf"]]),
                                "nodrug" = rownames(hs_macr_sig[["deseq"]][["ups"]][["z22nosb_vs_uninf"]])))
pp(file="images/z22_vs_uninf_venn_up.png")
Vennerable::plot(shared)
dev.off()
## png 
##   2
Vennerable::plot(shared)

length(shared@IntersectionSets[["10"]]) + length(shared@IntersectionSets[["11"]])
## [1] 660
dim(hs_macr_sig[["deseq"]][["ups"]][["z22sb_vs_uninf"]])
## [1] 660  58

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.

8.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_macr_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")
plotly::ggplotly(z23nosb_vs_z22nosb_volcano$plot)
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
z23sb_vs_z22sb_volcano <- plot_volcano_de(
  table = hs_macr_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")
plotly::ggplotly(z23sb_vs_z22sb_volcano$plot)
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
z23nosb_vs_z22nosb_volcano$plot +
  xlim(-10, 10) +
  ylim(0, 60)

pp(file="images/z23nosb_vs_z22nosb_reactome_up.png", image=all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Warning in pp(file = "images/z23nosb_vs_z22nosb_reactome_up.png", image =
## all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]], : There is no
## device to shut down.
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["KEGG"]]
## KEGG, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["MF"]]
## MF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["TF"]]
## TF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["WP"]]
## WikiPathways, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_z22nosb_up"]][["interactive_plots"]][["WP"]]
all_gp[["z23nosb_vs_z22nosb_down"]][["pvalue_plots"]][["REAC"]]
## NULL
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23nosb_vs_z22nosb_down"]][["pvalue_plots"]][["MF"]]
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23nosb_vs_z22nosb_down"]][["pvalue_plots"]][["TF"]]
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.
z23sb_vs_z22sb_volcano$plot +
  xlim(-10, 10) +
  ylim(0, 60)
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_point()`).
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_text_repel()`).
## Warning: ggrepel: 3 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

pp(file="images/z23sb_vs_z22sb_reactome_up.png", image=all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Warning in pp(file = "images/z23sb_vs_z22sb_reactome_up.png", image =
## all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["REAC"]], : There is no device
## to shut down.
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["KEGG"]]
## KEGG, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["MF"]]
## MF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["TF"]]
## TF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["WP"]]
## WikiPathways, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z22sb_up"]][["interactive_plots"]][["WP"]]
all_gp[["z23sb_vs_z22sb_down"]][["pvalue_plots"]][["REAC"]]
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23sb_vs_z22sb_down"]][["pvalue_plots"]][["MF"]]
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23sb_vs_z22sb_down"]][["pvalue_plots"]][["TF"]]
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.
shared <- Vennerable::Venn(list("drug" = rownames(hs_macr_sig[["deseq"]][["ups"]][["z23sb_vs_z22sb"]]),
                                "nodrug" = rownames(hs_macr_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_macr_sig[["deseq"]][["downs"]][["z23sb_vs_z22sb"]]),
                                "nodrug" = rownames(hs_macr_sig[["deseq"]][["downs"]][["z23nosb_vs_z22nosb"]])))
pp(file="images/drug_nodrug_venn_down.png")
Vennerable::plot(shared)
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.

8.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_macr_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")
plotly::ggplotly(z23sb_vs_z23nosb_volcano$plot)
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
z22sb_vs_z22nosb_volcano <- plot_volcano_de(
  table = hs_macr_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")
plotly::ggplotly(z22sb_vs_z22nosb_volcano$plot)
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
z23sb_vs_z23nosb_volcano$plot +
  xlim(-8, 8) +
  ylim(0, 210)
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_point()`).
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_text_repel()`).

pp(file="images/z23sb_vs_z23nosb_reactome_up.png",
   image=all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Warning in pp(file = "images/z23sb_vs_z23nosb_reactome_up.png", image =
## all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["REAC"]], : There is no
## device to shut down.
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["KEGG"]]
## KEGG, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["MF"]]
## MF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["TF"]]
## TF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["WP"]]
## WikiPathways, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z23nosb_up"]][["interactive_plots"]][["WP"]]
all_gp[["z23sb_vs_z23nosb_down"]][["pvalue_plots"]][["REAC"]]
## Warning: Removed 1 row containing missing values or values outside the scale
## range (`geom_col()`).
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23sb_vs_z23nosb_down"]][["pvalue_plots"]][["MF"]]
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23sb_vs_z23nosb_down"]][["pvalue_plots"]][["TF"]]
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.
z22sb_vs_z22nosb_volcano$plot +
  xlim(-8, 8) +
  ylim(0, 210)

pp(file="images/z22sb_vs_z22nosb_reactome_up.png",
   image=all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Warning in pp(file = "images/z22sb_vs_z22nosb_reactome_up.png", image =
## all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]], : There is no
## device to shut down.
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["KEGG"]]
## KEGG, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["MF"]]
## MF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["TF"]]
## TF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["WP"]]
## WikiPathways, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z22sb_vs_z22nosb_up"]][["interactive_plots"]][["WP"]]
all_gp[["z22sb_vs_z22nosb_down"]][["pvalue_plots"]][["REAC"]]
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z22sb_vs_z22nosb_down"]][["pvalue_plots"]][["MF"]]
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z22sb_vs_z22nosb_down"]][["pvalue_plots"]][["TF"]]
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.
shared <- Vennerable::Venn(list("z23" = rownames(hs_macr_sig[["deseq"]][["ups"]][["z23sb_vs_z23nosb"]]),
                                "z22" = rownames(hs_macr_sig[["deseq"]][["ups"]][["z22sb_vs_z22nosb"]])))
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_macr_sig[["deseq"]][["downs"]][["z23sb_vs_z23nosb"]]),
                                "z22" = rownames(hs_macr_sig[["deseq"]][["downs"]][["z22sb_vs_z22nosb"]])))
pp(file="images/z23_z22_drug_venn_down.png")
Vennerable::plot(shared)
dev.off()
## png 
##   2
Vennerable::plot(shared)

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.

8.4 LRT of the Human Macrophage

tmrc2_lrt_strain_drug <- deseq_lrt(hs_macr, interactor_column = "drug",
                                   interest_column = "macrophagezymodeme", factors = c("drug", "macrophagezymodeme"))
## converting counts to integer mode
## estimating size factors
## estimating dispersions
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## fitting model and testing
## -- replacing outliers and refitting for 38 genes
## -- DESeq argument 'minReplicatesForReplace' = 7 
## -- original counts are preserved in counts(dds)
## estimating dispersions
## fitting model and testing
## rlog() may take a long time with 50 or more samples,
## vst() is a much faster transformation
## Working with 858 genes.
## Working with 855 genes after filtering: minc > 3
## Joining with `by = join_by(merge)`
## Joining with `by = join_by(merge)`
## Warning in `labels<-.dendrogram`(dend, value = value, ...): The lengths of the
## new labels is shorter than the number of leaves in the dendrogram - labels are
## recycled.

tmrc2_lrt_strain_drug$cluster_data$plot

8.5 Parasite

lp_macrophage_de <- all_pairwise(lp_macrophage_nosb,
                                 model_batch="svaseq", filter=TRUE)
## 
## z2.2 z2.3 
##   14   15
## Removing 0 low-count genes (8591 remaining).
## Setting 889 low elements to zero.
## transform_counts: Found 889 values equal to 0, adding 1 to the matrix.
tmrc2_parasite_keepers <- list(
  "z23_vs_z22" = c("z23", "z22"))
lp_macrophage_table <- combine_de_tables(
  lp_macrophage_de, keepers = tmrc2_parasite_keepers,
  excel = glue("excel/macrophage_de/macrophage_parasite_infection_de-v{ver}.xlsx"))
lp_macrophage_sig <- extract_significant_genes(
  lp_macrophage_table,
  excel = glue("excel/macrophage_de/macrophage_parasite_sig-v{ver}.xlsx"))

lp_macrophage_table[["plots"]][["z23nosb_vs_z22nosb"]][["deseq_vol_plots"]][["plot"]]
## NULL
up_genes <- lp_macrophage_sig[["deseq"]][["ups"]][[1]]
dim(up_genes)
## [1] 48 67
down_genes <- lp_macrophage_sig[["deseq"]][["downs"]][[1]]
dim(down_genes)
## [1] 91 67
lp_z23sb_vs_z22sb_volcano <- plot_volcano_de(
  table = lp_macrophage_table[["data"]][["z23_vs_z22"]],
  fc_col = "deseq_logfc", p_col = "deseq_adjp",
  shapes_by_state = FALSE, color_by = "fc",  label = 10, label_column = "hgncsymbol")
plotly::ggplotly(lp_z23sb_vs_z22sb_volcano$plot)
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
##   If you'd like to see this geom implemented,
##   Please open an issue with your example code at
##   https://github.com/ropensci/plotly/issues
lp_z23sb_vs_z22sb_volcano$plot
## Warning: ggrepel: 7 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

lp_lengths <- all_lp_annot[, c("gid", "annot_cds_length")]
colnames(lp_lengths)  <- c("ID", "length")

up_goseq <- simple_goseq(up_genes, go_db = lp_go, length_db = lp_lengths)
## Found 18 go_db genes and 48 length_db genes out of 48.
## View categories over represented in the 2.3 samples
up_goseq$pvalue_plots$bpp_plot_over
## NULL
down_goseq <- simple_goseq(down_genes, go_db = lp_go, length_db = lp_lengths)
## Found 25 go_db genes and 91 length_db genes out of 91.
## View categories over represented in the 2.2 samples
down_goseq$pvalue_plots$bpp_plot_over
## NULL
written_goseq <- write_goseq_data(up_goseq,
                                  excel = glue("lp_macrophage_increased_z2.3_goseq-v{ver}.xlsx"))
## Writing a sheet containing the legend.
## Error in names(x) <- value: 'names' attribute [2] must be the same length as the vector [1]
written_goseq <- write_goseq_data(down_goseq,
                                  excel = glue("lp_macrophage_increased_z2.2_goseq-v{ver}.xlsx"))
## Writing a sheet containing the legend.
## Error in names(x) <- value: 'names' attribute [2] must be the same length as the vector [1]

9 GSVA

hs_infected <- subset_expt(hs_macrophage, subset="macrophagetreatment!='uninf'") %>%
  subset_expt(subset="macrophagetreatment!='uninf_sb'")
## The samples excluded are: TMRC30059, TMRC30266, TMRC30326, TMRC30312, TMRC30309.
## subset_expt(): There were 68, now there are 63 samples.
## The samples excluded are: .
## subset_expt(): There were 63, now there are 63 samples.
hs_gsva_c2 <- simple_gsva(hs_infected)
## Converting the rownames() of the expressionset to ENTREZID.
## 1655 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 19785 entries.
## Adding descriptions and IDs to the gene set annotations.
hs_gsva_c2_meta <- get_msigdb_metadata(hs_gsva_c2, msig_xml="reference/msigdb_v7.2.xml")
## Error in get_msigdb_metadata(hs_gsva_c2, msig_xml = "reference/msigdb_v7.2.xml"): unused argument (msig_xml = "reference/msigdb_v7.2.xml")
hs_gsva_c2_sig <- get_sig_gsva_categories(hs_gsva_c2_meta, excel = "excel/macrophage_de/hs_macrophage_gsva_c2_sig.xlsx")
## Error in eval(expr, envir, enclos): object 'hs_gsva_c2_meta' not found
hs_gsva_c2_sig$raw_plot
## Error in eval(expr, envir, enclos): object 'hs_gsva_c2_sig' not found
hs_gsva_c7 <- simple_gsva(hs_infected, signature_category = "c7")
## Converting the rownames() of the expressionset to ENTREZID.
## 1655 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 19785 entries.
## Adding descriptions and IDs to the gene set annotations.
hs_gsva_c7_meta <- get_msigdb_metadata(hs_gsva_c7, msig_xml="reference/msigdb_v7.2.xml")
## Error in get_msigdb_metadata(hs_gsva_c7, msig_xml = "reference/msigdb_v7.2.xml"): unused argument (msig_xml = "reference/msigdb_v7.2.xml")
hs_gsva_c7_sig <- get_sig_gsva_categories(hs_gsva_c7, excel = "excel/macrophage_de/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.
## 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/3: Creating table: infsb_vs_inf.  Adjust = BH
## Limma step 6/6: 2/3: Creating table: uninfsb_vs_inf.  Adjust = BH
## Limma step 6/6: 3/3: Creating table: uninfsb_vs_infsb.  Adjust = BH
## Limma step 6/6: 1/3: Creating table: inf.  Adjust = BH
## Limma step 6/6: 2/3: Creating table: infsb.  Adjust = BH
## Limma step 6/6: 3/3: Creating table: uninfsb.  Adjust = BH
## The factor inf has 29 rows.
## The factor inf_sb has 29 rows.
## The factor uninf_sb has 5 rows.
## Testing each factor against the others.
## Scoring inf against everything else.
## Scoring inf_sb against everything else.
## Scoring uninf_sb against everything else.
hs_gsva_c7_sig$raw_plot

10 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)
## Error in library(pathwayPCA): there is no package called 'pathwayPCA'
library(rWikiPathways)
## Error in library(rWikiPathways): there is no package called 'rWikiPathways'
downloaded <- downloadPathwayArchive(organism = "Homo sapiens", format = "gmt")
## Error in downloadPathwayArchive(organism = "Homo sapiens", format = "gmt"): could not find function "downloadPathwayArchive"
data_path <- system.file("extdata", package = "pathwayPCA")
wikipathways <- read_gmt(paste0(data_path, "/wikipathways_human_symbol.gmt"),
                         description = TRUE)
## Error in read_gmt(paste0(data_path, "/wikipathways_human_symbol.gmt"), : could not find function "read_gmt"
expt <- subset_expt(hs_macrophage, subset = "macrophagetreatment!='uninf'") %>%
  subset_expt(subset = "macrophagetreatment!='uninf_sb'")
## The samples excluded are: TMRC30059, TMRC30266, TMRC30326, TMRC30312, TMRC30309.
## subset_expt(): There were 68, now there are 63 samples.
## The samples excluded are: .
## subset_expt(): There were 63, now there are 63 samples.
expt <- set_expt_conditions(expt, fact = "macrophagezymodeme")
## The numbers of samples by condition are:
## 
## none  z22  z23 
##    5   29   29
symbol_vector <- fData(expt)[[symbol_column]]
## Error in eval(expr, envir, enclos): object 'symbol_column' not found
names(symbol_vector) <- rownames(fData(expt))
## Error: object 'symbol_vector' not found
symbol_df <- as.data.frame(symbol_vector)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'symbol_vector' not found
assay_df <- merge(symbol_df, as.data.frame(exprs(expt)), by = "row.names")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'merge': object 'symbol_df' not found
assay_df[["Row.names"]] <- NULL
## Error: object 'assay_df' not found
rownames(assay_df) <- make.names(assay_df[["symbol_vector"]], unique = TRUE)
## Error in eval(expr, envir, enclos): object 'assay_df' not found
assay_df[["symbol_vector"]] <- NULL
## Error: object 'assay_df' not found
assay_df <- as.data.frame(t(assay_df))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': error in evaluating the argument 'x' in selecting a method for function 't': object 'assay_df' not found
assay_df[["SampleID"]] <- rownames(assay_df)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'assay_df' not found
assay_df <- dplyr::select(assay_df, "SampleID", everything())
## Error in eval(expr, envir, enclos): object 'assay_df' not found
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)]
## Error in eval(expr, envir, enclos): object 'factors' not found
tt <- CreateOmics(
  assayData_df = assay_df,
  pathwayCollection_ls = wikipathways,
  response = factor_df,
  respType = "categorical",
  minPathSize=5)
## Error in CreateOmics(assayData_df = assay_df, pathwayCollection_ls = wikipathways, : could not find function "CreateOmics"
super <- AESPCA_pVals(
  object = tt,
  numPCs = 2,
  parallel = FALSE,
  numCores = 8,
  numReps = 2,
  adjustment = "BH")
## Error in AESPCA_pVals(object = tt, numPCs = 2, parallel = FALSE, numCores = 8, : could not find function "AESPCA_pVals"
## Stopping this because it takes forever
##if (!isTRUE(get0("skip_load"))) {
##  pander::pander(sessionInfo())
##  message("This is hpgltools commit: ", get_git_commit())
##  message("Saving to ", savefile)
##  tmp <- sm(saveme(filename = savefile))
##}
tmp <- loadme(filename = savefile)
LS0tCnRpdGxlOiAiVE1SQzIgYHIgU3lzLmdldGVudignVkVSU0lPTicpYDogTWFjcm9waGFnZSBEaWZmZXJlbnRpYWwgRXhwcmVzc2lvbi4iCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICB0aGVtZTogcmVhZGFibGUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlPgpib2R5IC5tYWluLWNvbnRhaW5lciB7Cm1heC13aWR0aDogMTYwMHB4Owp9Cjwvc3R5bGU+CgpgYGB7ciBvcHRpb25zLCBpbmNsdWRlID0gRkFMU0V9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnbHVlKQpsaWJyYXJ5KEhlYXRwbHVzKQpsaWJyYXJ5KGhwZ2x0b29scykKbGlicmFyeShVcFNldFIpCmxpYnJhcnkodGliYmxlKQoKa25pdHI6Om9wdHNfa25pdCRzZXQocHJvZ3Jlc3MgPSBUUlVFLCB2ZXJib3NlID0gVFJVRSwgd2lkdGggPSA5MCwgZWNobyA9IFRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvciA9IFRSVUUsIGZpZy53aWR0aCA9IDgsIGZpZy5oZWlnaHQgPSA4LCBkcGkgPSA5NikKb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHMgPSA0LCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbCA9ICJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMikpCnZlciA8LSBTeXMuZ2V0ZW52KCJWRVJTSU9OIikKcHJldmlvdXNfZmlsZSA8LSAiIgpydW5kYXRlIDwtIGZvcm1hdChTeXMuRGF0ZSgpLCBmb3JtYXQgPSAiJVklbSVkIikKCiMjIHRtcCA8LSB0cnkoc20obG9hZG1lKGZpbGVuYW1lID0gZ3N1YihwYXR0ZXJuID0gIlxcLlJtZCIsIHJlcGxhY2UgPSAiXFwucmRhXFwueHoiLCB4ID0gcHJldmlvdXNfZmlsZSkpKSkKcm1kX2ZpbGUgPC0gIjAzZGlmZmVyZW50aWFsX2V4cHJlc3Npb24uUm1kIgpsb2FkZWQgPC0gbG9hZChmaWxlID0gZ2x1ZSgicmRhL3RtcmMyX2RhdGFfc3RydWN0dXJlcy12e3Zlcn0ucmRhIikpCnNhdmVmaWxlIDwtIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLCByZXBsYWNlID0gIlxcLnJkYVxcLnh6IiwgeCA9IHJtZF9maWxlKQpgYGAKCiMgQ2hhbmdlbG9nCgoqIDIwMjMxMDogQ2xlYW5pbmcgdXAgdG8gbWFrZSBldmVyeXRoaW5nIHBhc3Mgd2l0aGluIGEgY29udGFpbmVyaXplZCBlbnZpcm9ubWVudC4KKiAyMDIzMTA6IFJlY2VpdmVkIGEgc2V0IG9mIGNvbG9ycyBhbmQgY29udHJhc3RzIG9mIGludGVyZXN0IGZvciBhIGJhcnBsb3Qgb2Ygc2lnbmlmaWNhbmNlLgoqIDIwMjMwNDEwOiBNYWtpbmcgc29tZSBjaGFuZ2VzIHRvIGltcHJvdmUgdGhlIGRpZmZlcmVudGlhbCBleHByZXNzaW9uCnBsb3RzIGFzIHdlbGwgYXMgcHJlcGFyZSBmb3Igc29tZSBkaWZmZXJlbnQgcGF0aHdheS9HU0VBL0dTVkEKYW5hbHlzZXMgb24gdGhlIGRhdGEuCgojIE5vdGVzCgpTaG93aW5nIHBsb3RzIG9mIGNvdW50cyB3aXRoIHJlc3BlY3QgdG8gZHJ1ZyB0cmVhdG1lbnQ6IHF1ZXJ5IHRvIE5hamliCnRvIGNsYXJpZnkgbm9ybWFsaXphdGlvbi4gSSB0aGluayBJIGNhbiBtYWtlIHZlcnNpb25zIG9mIHRoZXNlIHBsb3RzCndoaWNoIHVzZSBTTC9ub3JtYWxpemVkIGNvdW50cyB0byBhbGxldmlhdGUgTmFqaWIncyBxdWVyeS4KCm1lYW4gcmF0aW8gb2YgU0wvdG90YWwgYnkgY29uZGl0aW9uPwoKIyBJbnRyb2R1Y3Rpb24KCkhhdmluZyBlc3RhYmxpc2hlZCB0aGF0IHRoZSBUTVJDMiBtYWNyb3BoYWdlIGRhdGEgbG9va3Mgcm9idXN0IGFuZAppbGx1c3RyYXRpdmUgb2YgYSBjb3VwbGUgb2YgaW50ZXJlc3RpbmcgcXVlc3Rpb25zLCBsZXQgdXMgcGVyZm9ybSBhCmNvdXBsZSBvZiBkaWZmZXJlbnRpYWwgYW5hbHlzZXMgb2YgaXQuCgpBbHNvIG5vdGUgdGhhdCBhcyBvZiAyMDIyMTIsIHdlIHJlY2VpdmVkIGEgbmV3IHNldCBvZiBzYW1wbGVzIHdoaWNoCm5vdyBpbmNsdWRlIHNvbWUgd2hpY2ggYXJlIG9mIGEgY29tcGxldGVseSBkaWZmZXJlbnQgY2VsbCB0eXBlLApVOTM3LiBBcyB0aGVpciBBVENDIHBhZ2Ugc3RhdGVzLCB0aGV5IGFyZSBtYWxpZ25hbnQgY2VsbHMgdGFrZW4gZnJvbQp0aGUgcGxldXJhbCBlZmZ1c2lvbiBvZiBhIDM3IHllYXIgb2xkIHdoaXRlIG1hbGUgd2l0aCBoaXN0aW9jeXRpYwpseW1waG9tYSBhbmQgd2hpY2ggZXhoaWJpdCB0aGUgbW9ycGhvbG9neSBvZiBtb25vY3l0ZXMuICBUaHVzLCB0aGlzCmRvY3VtZW50IG5vdyBpbmNsdWRlcyBzb21lIGNvbXBhcmlzb25zIG9mIHRoZSBjZWxsIHR5cGVzIGFzIHdlbGwgYXMKdGhlIHZhcmlvdXMgbWFjcm9waGFnZSBkb25vcnMgKGdpdmVuIHRoYXQgdGhlcmUgYXJlIG5vdyBtb3JlIGRvbm9ycwp0b28pLgoKIyMgSHVtYW4gZGF0YQoKSSBhbSBtb3ZpbmcgdGhlIGRhdGFzZXQgbWFuaXB1bGF0aW9ucyBoZXJlIHNvIHRoYXQgSSBjYW4gbG9vayBhdCB0aGVtCmFsbCB0b2dldGhlciBiZWZvcmUgcnVubmluZyB0aGUgdmFyaW91cyBERSBhbmFseXNlcy4KCiMjIENyZWF0ZSBzZXRzIGZvY3VzZWQgb24gZHJ1ZywgY2VsbHR5cGUsIHN0cmFpbiwgYW5kIGNvbWJpbmF0aW9ucwoKTGV0IHVzIHN0YXJ0IGJ5IHBsYXlpbmcgd2l0aCB0aGUgbWV0YWRhdGEgYSBsaXR0bGUgYW5kIGNyZWF0ZSBzZXRzCndpdGggdGhlIGNvbmRpdGlvbiBzZXQgdG86CgoqIERydWcgdHJlYXRtZW50CiogQ2VsbCB0eXBlIChtYWNyb3BoYWdlIG9yIFU5MzcpCiogRG9ub3IKKiBJbmZlY3Rpb24gU3RyYWluCiogU29tZSB1c2VmdWwgY29tYmluYXRpb25zIHRoZXJlb2YKCkluIGFkZGl0aW9uLCBrZWVwIG1lbnRhbCB0cmFjayBvZiB3aGljaCBkYXRhc2V0cyBhcmUgY29tcHJpc2VkIG9mIGFsbApzYW1wbGVzIHZzLiB0aG9zZSB3aGljaCBhcmUgb25seSBtYWNyb3BoYWdlIHZzLiB0aG9zZSB3aGljaCBhcmUgb25seQpVOTM3LiAgKFRodXMsIHRoZSB1c2FnZSBvZiBhbGxfaHVtYW4gdnMuIGhzX21hY3IgdnMuIHU5MzcgYXMgcHJlZml4ZXMKZm9yIHRoZSBkYXRhIHN0cnVjdHVyZXMuKQoKSWRlYWxseSwgdGhlc2UgcmVjcmVhdGlvbnMgb2YgdGhlIGRhdGEgc2hvdWxkIHBlcmhhcHMgYmUgaW4gdGhlCmRhdGFzdHJ1Y3R1cmVzIHdvcmtzaGVldC4KCmBgYHtyfQphbGxfaHVtYW4gPC0gc2FuaXRpemVfZXhwdF9wRGF0YShoc19tYWNyb3BoYWdlLCBjb2x1bW5zID0gImRydWciKSAlPiUKICBzZXRfZXhwdF9jb25kaXRpb25zKGZhY3QgPSAiZHJ1ZyIpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdCA9ICJ0eXBlb2ZjZWxscyIpCgojIyBUaGUgZm9sbG93aW5nIDMgbGluZXMgd2VyZSBjb3B5L3Bhc3RlZCB0byBkYXRhc3RydWN0dXJlcyBhbmQgc2hvdWxkIGJlIHJlbW92ZWQgc29vbi4Kbm9fc3RyYWluX2lkeCA8LSBwRGF0YShhbGxfaHVtYW4pW1sic3RyYWluaWQiXV0gPT0gIm5vbmUiCiMjcERhdGEoYWxsX2h1bWFuKVtbInN0cmFpbmlkIl1dIDwtIHBhc3RlMCgicyIsIHBEYXRhKGFsbF9odW1hbilbWyJzdHJhaW5pZCJdXSwKIyMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJfIiwgcERhdGEoYWxsX2h1bWFuKVtbIm1hY3JvcGhhZ2V6eW1vZGVtZSJdXSkKcERhdGEoYWxsX2h1bWFuKVtub19zdHJhaW5faWR4LCAic3RyYWluaWQiXSA8LSAibm9uZSIKdGFibGUocERhdGEoYWxsX2h1bWFuKVtbInN0cmFpbmlkIl1dKQoKYWxsX2h1bWFuX3R5cGVzIDwtIHNldF9leHB0X2NvbmRpdGlvbnMoYWxsX2h1bWFuLCBmYWN0ID0gInR5cGVvZmNlbGxzIikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0ID0gImRydWciKQoKdHlwZV96eW1vX2ZhY3QgPC0gcGFzdGUwKHBEYXRhKGFsbF9odW1hbl90eXBlcylbWyJjb25kaXRpb24iXV0sICJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgIHBEYXRhKGFsbF9odW1hbl90eXBlcylbWyJtYWNyb3BoYWdlenltb2RlbWUiXV0pCnR5cGVfenltbyA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGFsbF9odW1hbl90eXBlcywgZmFjdCA9IHR5cGVfenltb19mYWN0KQoKdHlwZV9kcnVnX2ZhY3QgPC0gcGFzdGUwKHBEYXRhKGFsbF9odW1hbl90eXBlcylbWyJjb25kaXRpb24iXV0sICJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgIHBEYXRhKGFsbF9odW1hbl90eXBlcylbWyJkcnVnIl1dKQp0eXBlX2RydWcgPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhhbGxfaHVtYW5fdHlwZXMsIGZhY3QgPSB0eXBlX2RydWdfZmFjdCkKCnN0cmFpbl9mYWN0IDwtIHBEYXRhKGFsbF9odW1hbl90eXBlcylbWyJzdHJhaW5pZCJdXQp0YWJsZShzdHJhaW5fZmFjdCkKCm5ld19jb25kaXRpb25zIDwtIHBhc3RlMChwRGF0YShoc19tYWNyb3BoYWdlKVtbIm1hY3JvcGhhZ2V0cmVhdG1lbnQiXV0sICJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgIHBEYXRhKGhzX21hY3JvcGhhZ2UpW1sibWFjcm9waGFnZXp5bW9kZW1lIl1dKQojIyBOb3RlIHRoZSBzYW5pdGl6ZSgpIGNhbGwgaXMgcmVkdW5kYW50IHdpdGggdGhlIGFkZGl0aW9uIG9mIHNhbml0aXplKCkgaW4gdGhlCiMjIGRhdGFzdHJ1Y3R1cmVzIGZpbGUsIGJ1dCBJIGRvbid0IHdhbnQgdG8gd2FpdCB0byByZXJ1biB0aGF0Lgpoc19tYWNyIDwtIHNldF9leHB0X2NvbmRpdGlvbnMoaHNfbWFjcm9waGFnZSwgZmFjdCA9IG5ld19jb25kaXRpb25zKSAlPiUKICBzYW5pdGl6ZV9leHB0X3BEYXRhKGNvbHVtbiA9ICJkcnVnIikgJT4lCiAgc3Vic2V0X2V4cHQoc3Vic2V0ID0gInR5cGVvZmNlbGxzIT0nVTkzNyciKQpgYGAKCiMjIyBTZXBhcmF0ZSBNYWNyb3BoYWdlIHNhbXBsZXMKCk9uY2UgYWdhaW4sIHdlIHNob3VsZCByZWNvbnNpZGVyIHdoZXJlIHRoZSBmb2xsb3dpbmcgYmxvY2sgaXMgcGxhY2VkLApidXQgdGhlc2UgZGF0YXN0cnVjdHVyZXMgYXJlIGxpa2VseSB0byBiZSB1c2VkIGluIG1hbnkgb2YgdGhlCmZvbGxvd2luZyBhbmFseXNlcy4KCmBgYHtyfQpoc19tYWNyX2RydWdfZXhwdCA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGhzX21hY3IsIGZhY3QgPSAiZHJ1ZyIpCgpoc19tYWNyX3N0cmFpbl9leHB0IDwtIHNldF9leHB0X2NvbmRpdGlvbnMoaHNfbWFjciwgZmFjdCA9ICJtYWNyb3BoYWdlenltb2RlbWUiKSAlPiUKICBzdWJzZXRfZXhwdChzdWJzZXQgPSAibWFjcm9waGFnZXp5bW9kZW1lICE9ICdub25lJyIpCgp0YWJsZShwRGF0YShoc19tYWNyKVtbInN0cmFpbmlkIl1dKQpgYGAKCiMjIyBSZWZhY3RvciBVOTM3IHNhbXBsZXMKClRoZSBVOTM3IHNhbXBsZXMgd2VyZSBzZXBhcmF0ZWQgaW4gdGhlIGRhdGFzdHJ1Y3R1cmVzIGZpbGUsIGJ1dCB3ZQp3YW50IHRvIHVzZSB0aGUgY29tYmluYXRpb24gb2YgZHJ1Zy96eW1vZGVtZSB3aXRoIHRoZW0gcHJldHR5IG11Y2gKZXhjbHVzaXZlbHkuCgpgYGB7cn0KbmV3X2NvbmRpdGlvbnMgPC0gcGFzdGUwKHBEYXRhKGhzX3U5MzcpW1sibWFjcm9waGFnZXRyZWF0bWVudCJdXSwgIl8iLAogICAgICAgICAgICAgICAgICAgICAgICAgcERhdGEoaHNfdTkzNylbWyJtYWNyb3BoYWdlenltb2RlbWUiXV0pCnU5MzdfZXhwdCA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGhzX3U5MzcsIGZhY3QgPSBuZXdfY29uZGl0aW9ucykKYGBgCgojIyBDb250cmFzdHMgdXNlZCBpbiB0aGlzIGRvY3VtZW50CgpHaXZlbiB0aGUgdmFyaW91cyB3YXlzIHdlIGhhdmUgY2hvcHBlZCB1cCB0aGlzIGRhdGFzZXQsIHRoZXJlIGFyZSBhCmZldyBnZW5lcmFsIHR5cGVzIG9mIGNvbnRyYXN0cyB3ZSB3aWxsIHBlcmZvcm0sIHdoaWNoIHdpbGwgdGhlbiBiZQpjb21iaW5lZCBpbnRvIGdyZWF0ZXIgY29tcGxleGl0eToKCiogZHJ1ZyB0cmVhdG1lbnQKKiBzdHJhaW5zIHVzZWQKKiBjZWxsbHR5cGVzCiogZG9ub3JzCgpJbiB0aGUgZW5kLCBvdXIgYWN0dWFsIGdvYWwgaXMgdG8gY29uc2lkZXIgdGhlIHZhcmlhYmxlIGVmZmVjdHMgb2YKZHJ1ZytzdHJhaW4gYW5kIHNlZSBpZiB3ZSBjYW4gZGlzY2VybiBwYXR0ZXJucyB3aGljaCBsZWFkIHRvIGJldHRlciBvcgp3b3JzZSBkcnVnIHRyZWF0bWVudCBvdXRjb21lLgoKVGhlcmUgaXMgYSBzZXQgb2YgY29udHJhc3RzIGluIHdoaWNoIHdlIGFyZSBwcmltYXJpbHkgaW50ZXJlc3RlZCBpbgp0aGlzIGRhdGEsIHRoZXNlIGZvbGxvdy4gIEkgY3JlYXRlZCBvbmUgcmF0aW8gb2YgcmF0aW9zIGNvbnRyYXN0IHdoaWNoCkkgdGhpbmsgaGFzIHRoZSBwb3RlbnRpYWwgdG8gYXNrIG91ciBiaWdnZXN0IHF1ZXN0aW9uLgoKYGBge3J9CnRtcmMyX2h1bWFuX2V4dHJhIDwtICJ6MjNkcnVnbm9kcnVnX3ZzX3oyMmRydWdub2RydWcgPSAoaW5mc2J6MjMgLSBpbmZ6MjMpIC0gKGluZnNiejIyIC0gaW5mejIyKSwgejIzejIyZHJ1Z192c196MjN6MjJub2RydWcgPSAoaW5mc2J6MjMgLSBpbmZzYnoyMikgLSAoaW5mejIzIC0gaW5mejIyKSIKdG1yYzJfaHVtYW5fa2VlcGVycyA8LSBsaXN0KAogICJ6MjNub3NiX3ZzX3VuaW5mIiA9IGMoImluZnoyMyIsICJ1bmluZm5vbmUiKSwKICAiejIybm9zYl92c191bmluZiIgPSBjKCJpbmZ6MjIiLCAidW5pbmZub25lIiksCiAgInoyM25vc2JfdnNfejIybm9zYiIgPSBjKCJpbmZ6MjMiLCAiaW5mejIyIiksCiAgInoyM3NiX3ZzX3oyMnNiIiA9IGMoImluZnNiejIzIiwgImluZnNiejIyIiksCiAgInoyM3NiX3ZzX3oyM25vc2IiID0gYygiaW5mc2J6MjMiLCAiaW5mejIzIiksCiAgInoyMnNiX3ZzX3oyMm5vc2IiID0gYygiaW5mc2J6MjIiLCAiaW5mejIyIiksCiAgInoyM3NiX3ZzX3NiIiA9IGMoImluZnNiejIzIiwgInVuaW5mc2Jub25lIiksCiAgInoyMnNiX3ZzX3NiIiA9IGMoImluZnNiejIyIiwgInVuaW5mc2Jub25lIiksCiAgInoyM3NiX3ZzX3VuaW5mIiA9IGMoImluZnNiejIzIiwgInVuaW5mbm9uZSIpLAogICJ6MjJzYl92c191bmluZiIgPSBjKCJpbmZzYnoyMiIsICJ1bmluZm5vbmUiKSwKICAic2JfdnNfdW5pbmYiID0gYygidW5pbmZzYm5vbmUiLCAidW5pbmZub25lIiksCiAgImV4dHJhX3oyMzIyIiA9IGMoInoyM2RydWdub2RydWciLCAiejIyZHJ1Z25vZHJ1ZyIpLAogICJleHRyYV9kcnVnbm9kcnVnIiA9IGMoInoyM3oyMmRydWciLCAiejIzejIybm9kcnVnIikpCnNpbmdsZV90bXJjMl9rZWVwZXIgPC0gbGlzdCgKICAiejIyc2JfdnNfc2IiID0gYygiaW5mc2J6MjIiLCAidW5pbmZzYm5vbmUiKSkKdG1yYzJfZHJ1Z19rZWVwZXJzIDwtIGxpc3QoCiAgImRydWciID0gYygiYW50aW1vbnkiLCAibm9uZSIpKQp0bXJjMl90eXBlX2tlZXBlcnMgPC0gbGlzdCgKICAidHlwZSIgPSBjKCJVOTM3IiwgIk1hY3JvcGhhZ2VzIikpCnRtcmMyX3N0cmFpbl9rZWVwZXJzIDwtIGxpc3QoCiAgInN0cmFpbiIgPSBjKCJ6MjMiLCAiejIyIikpCnR5cGVfenltb19leHRyYSA8LSAienltb3NfdnNfdHlwZXMgPSAoVTkzN3oyMyAtIFU5Mzd6MjIpIC0gKE1hY3JvcGhhZ2VzejIzIC0gTWFjcm9waGFnZXN6MjIpIgp0bXJjMl90eXBlenltb19rZWVwZXJzIDwtIGxpc3QoCiAgInU5MzdfbWFjciIgPSBjKCJNYWNyb3BoYWdlc25vbmUiLCAiVTkzN25vbmUiKSwKICAienltb19tYWNyIiA9IGMoIk1hY3JvcGhhZ2VzejIzIiwgIk1hY3JvcGhhZ2VzejIyIiksCiAgInp5bW9fdTkzNyIgPSBjKCJVOTM3ejIzIiwgIlU5Mzd6MjIiKSwKICAiejIzX3R5cGVzIiA9IGMoIlU5Mzd6MjMiLCAiTWFjcm9waGFnZXN6MjMiKSwKICAiejIyX3R5cGVzIiA9IGMoIlU5Mzd6MjIiLCAiTWFjcm9waGFnZXN6MjIiKSwKICAienltb3NfdHlwZXMiID0gYygienltb3NfdnNfdHlwZXMiKSkKdG1yYzJfdHlwZWRydWdfa2VlcGVycyA8LSBsaXN0KAogICJ0eXBlX25vZHJ1ZyIgPSBjKCJVOTM3bm9uZSIsICJNYWNyb3BoYWdlc25vbmUiKSwKICAidHlwZV9kcnVnIiA9IGMoIlU5MzdhbnRpbW9ueSIsICJNYWNyb3BoYWdlc2FudGltb255IiksCiAgIm1hY3JfZHJ1Z3MiID0gYygiTWFjcm9waGFnZXNhbnRpbW9ueSIsICJNYWNyb3BoYWdlc25vbmUiKSwKICAidTkzN19kcnVncyIgPSBjKCJVOTM3YW50aW1vbnkiLCAiVTkzN25vbmUiKSkKdTkzN19rZWVwZXJzIDwtIGxpc3QoCiAgInoyM25vc2JfdnNfdW5pbmYiID0gYygiaW5mejIzIiwgInVuaW5mbm9uZSIpLAogICJ6MjJub3NiX3ZzX3VuaW5mIiA9IGMoImluZnoyMiIsICJ1bmluZm5vbmUiKSwKICAiejIzbm9zYl92c196MjJub3NiIiA9IGMoImluZnoyMyIsICJpbmZ6MjIiKSwKICAiejIzc2JfdnNfejIyc2IiID0gYygiaW5mc2J6MjMiLCAiaW5mc2J6MjIiKSwKICAiejIzc2JfdnNfejIzbm9zYiIgPSBjKCJpbmZzYnoyMyIsICJpbmZ6MjMiKSwKICAiejIyc2JfdnNfejIybm9zYiIgPSBjKCJpbmZzYnoyMiIsICJpbmZ6MjIiKSwKICAiejIzc2JfdnNfc2IiID0gYygiaW5mc2J6MjMiLCAidW5pbmZzYm5vbmUiKSwKICAiejIyc2JfdnNfc2IiID0gYygiaW5mc2J6MjIiLCAidW5pbmZzYm5vbmUiKSwKICAiejIzc2JfdnNfdW5pbmYiID0gYygiaW5mc2J6MjMiLCAidW5pbmZub25lIiksCiAgInoyMnNiX3ZzX3VuaW5mIiA9IGMoImluZnNiejIyIiwgInVuaW5mbm9uZSIpLAogICJzYl92c191bmluZiIgPSBjKCJ1bmluZnNibm9uZSIsICJ1bmluZm5vbmUiKSkKaGlnaF9leHByZXNzaW9uIDwtIDEyOApoaWdoX2V4cHJlc3Npb25fY29sdW1uIDwtICJkZXNlcV9iYXNlbWVhbiIKCmNvbWJpbmVkX3RvX3RzdiA8LSBmdW5jdGlvbihjb21iaW5lZCwgY2VsbHR5cGUgPSAiYWxsIikgewogIGtlZXBlcnMgPC0gY29tYmluZWRbWyJrZWVwZXJzIl1dCiAgZm9yIChrIGluIHNlcV9sZW4obGVuZ3RoKGtlZXBlcnMpKSkgewogICAga25hbWUgPC0gbmFtZXMoa2VlcGVycylba10KICAgIG51bWVyYXRvciA8LSBrZWVwZXJzW1trXV1bMV0KICAgIGRlbm9taW5hdG9yIDwtIGtlZXBlcnNbW2tdXVsyXQogICAgZmlsZW5hbWUgPC0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS97dmVyfS90c3ZfdGFibGVzL3RtcmMyX3tjZWxsdHlwZX1fe2tuYW1lfV9ue251bWVyYXRvcn1fZHtkZW5vbWluYXRvcn0tdnt2ZXJ9Lnhsc3giKQogICAga2RhdGEgPC0gY29tYmluZWRbWyJkYXRhIl1dW1trbmFtZV1dCiAgICBpZiAoaXMubnVsbChrZGF0YVtbImJhc2ljX251bSJdXSkpIHsKICAgICAgbmV4dAogICAgfQogICAgd2FudGVkIDwtIGMoImhnbmNzeW1ib2wiLCAiZGVzZXFfbG9nZmMiLCAiZGVzZXFfYWRqcCIsICJkZXNlcV9iYXNlbWVhbiIsICJkZXNlcV9udW0iLCAiZGVzZXFfZGVuIikKICAgIHdhbnRlZF9kYXRhIDwtIGtkYXRhWywgd2FudGVkXQogICAgY29sbmFtZXMod2FudGVkX2RhdGEpIDwtIGMoImhnbmNzeW1ib2wiLCAiZGVzZXFfbG9nZmMiLCAiZGVzZXFfYWRqcCIsICJkZXNlcV9tZWFuIiwgImRlc2VxX251bWVyYXRvciIsICJkZXNlcV9kZW5vbWluYXRvciIpCiAgICB3cml0ZV94bHN4KGRhdGEgPSB3YW50ZWRfZGF0YSwgZXhjZWwgPSBmaWxlbmFtZSkKICB9Cn0KCndyaXRlX2FsbF9ncCA8LSBmdW5jdGlvbihhbGxfZ3ApIHsKICBmb3IgKGcgaW4gc2VxX2xlbihsZW5ndGgoYWxsX2dwKSkpIHsKICAgIG5hbWUgPC0gbmFtZXMoYWxsX2dwKVtnXQogICAgZGF0dW0gPC0gYWxsX2dwW1tuYW1lXV0KICAgIGZpbGVuYW1lIDwtIGdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfZGUve3Zlcn0vZ3Byb2ZpbGVyL3tuYW1lfV9ncHJvZmlsZXItdnt2ZXJ9Lnhsc3giKQogICAgd3JpdHRlbiA8LSBzbSh3cml0ZV9ncHJvZmlsZXJfZGF0YShkYXR1bSwgZXhjZWwgPSBmaWxlbmFtZSkpCiAgfQp9CmBgYAoKIyMjIFByaW1hcnkgcXVlcmllcwoKVGhlcmUgaXMgYSBzZXJpZXMgb2YgaW5pdGlhbCBxdWVzdGlvbnMgd2hpY2ggbWFrZSBzb21lIHNlbnNlCnRvIG1lLCBidXQgdGhlc2UgZG8gbm90IG5lY2Vzc2FyaWx5IG1hdGNoIHRoZSBzZXQgb2YgcXVlc3Rpb25zIHdoaWNoCmFyZSBtb3N0IHByZXNzaW5nLiAgSSBhbSBob3BpbmcgdG8gcHVsbCBib3RoIG9mIHRoZXNlIHNldHMgb2YKcXVlcmllcyBpbiBvbmUuCgpCZWZvcmUgZXh0cmFjdGluZyB0aGVzZSBncm91cHMgb2YgcXVlcmllcywgbGV0IHVzIGludm9rZSB0aGUKYWxsX3BhaXJ3aXNlKCkgZnVuY3Rpb24gYW5kIGdldCBhbGwgb2YgdGhlIGxpa2VseSBjb250cmFzdHMgYWxvbmcgd2l0aApvbmUgb3IgbW9yZSBleHRyYXMgdGhhdCBtaWdodCBwcm92ZSB1c2VmdWwgKHRoZSAnZXh0cmEnIGFyZ3VtZW50KS4KCiMjIyBDb21iaW5lZCBVOTM3IGFuZCBNYWNyb3BoYWdlczogQ29tcGFyZSBkcnVnIGVmZmVjdHMKCldoZW4gd2UgaGF2ZSB0aGUgdTkzNyBjZWxscyBpbiB0aGUgc2FtZSBkYXRhc2V0IGFzIHRoZSBtYWNyb3BoYWdlcywKdGhhdCBwcm92aWRlcyBhbiBpbnRlcmVzdGluZyBvcHBvcnR1bml0eSB0byBzZWUgaWYgd2UgY2FuIG9ic2VydmUKZHJ1Zy1kZXBlbmRhbnQgZWZmZWN0cyB3aGljaCBhcmUgc2hhcmVkIGFjcm9zcyBib3RoIGNlbGwgdHlwZXMuCgpgYGB7cn0KZHJ1Z19kZSA8LSBhbGxfcGFpcndpc2UoYWxsX2h1bWFuLCBmaWx0ZXIgPSBUUlVFLCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiLCBkb19ub2lzZXEgPSBGQUxTRSkKZHJ1Z19kZQoKZHJ1Z190YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBkcnVnX2RlLCBrZWVwZXJzID0gdG1yYzJfZHJ1Z19rZWVwZXJzLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS97dmVyfS9kZV90YWJsZXMvbWFjcm9waGFnZV9kcnVnX2NvbXBhcmlzb24tdnt2ZXJ9Lnhsc3giKSkKZHJ1Z190YWJsZQpjb21iaW5lZF90b190c3YoZHJ1Z190YWJsZSwgY2VsbHR5cGUgPSAiYWxsIikKCmRydWdfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgZHJ1Z190YWJsZSwKICBleGNlbCA9IGdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfZGUve3Zlcn0vc2lnX3RhYmxlcy9tYWNyb3BoYWdlX2RydWdfc2lnLXZ7dmVyfS54bHN4IikpCmRydWdfc2lnCmRydWdfaGlnaHNpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGRydWdfdGFibGUsIG1pbl9tZWFuX2V4cHJzID0gaGlnaF9leHByZXNzaW9uLCBleHByc19jb2x1bW4gPSBoaWdoX2V4cHJlc3Npb25fY29sdW1uLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS97dmVyfS9zaWdfdGFibGVzL21hY3JvcGhhZ2VfZHJ1Z19oaWdoc2lnLXZ7dmVyfS54bHN4IikpCmRydWdfaGlnaHNpZwpgYGAKCmBgYHtyfQphbGxfZHJ1Z19ncCA8LSBhbGxfZ3Byb2ZpbGVyKGRydWdfc2lnKQphbGxfZHJ1Z19ncAp3cml0ZV9hbGxfZ3AoYWxsX2RydWdfZ3ApCmBgYAoKIyMjIENvbWJpbmVkIFU5MzcgYW5kIE1hY3JvcGhhZ2VzOiBjb21wYXJlIGNlbGwgdHlwZXMKClRoZXJlIGFyZSBhIGNvdXBsZSBvZiB3YXlzIG9uZSBtaWdodCB3YW50IHRvIGRpcmVjdGx5IGNvbXBhcmUgdGhlIHR3bwpjZWxsIHR5cGVzLgoKKiBHaXZlbiB0aGF0IHRoZSB2YXJpYW5jZSBiZXR3ZWVuIHRoZSB0d28gY2VsbHR5cGVzIGlzIHNvIGh1Z2UsIGp1c3QKY29tcGFyZSBhbGwgc2FtcGxlcy4KKiBPbmUgbWlnaHQgd2FudCB0byBjb21wYXJlIHRoZW0gd2l0aCB0aGUgaW50ZXJhY3Rpb24gZWZmZWN0cyBvZiBkcnVnL3p5bW9kZW1lLgoKYGBge3J9CnR5cGVfZGUgPC0gYWxsX3BhaXJ3aXNlKGFsbF9odW1hbl90eXBlcywgZmlsdGVyID0gVFJVRSwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIiwgZG9fbm9pc2VxID0gRkFMU0UpCnR5cGVfZGUKCnR5cGVfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgdHlwZV9kZSwga2VlcGVycyA9IHRtcmMyX3R5cGVfa2VlcGVycywKICBleGNlbCA9IGdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfZGUve3Zlcn0vZGVfdGFibGVzL21hY3JvcGhhZ2VfdHlwZV9jb21wYXJpc29uLXZ7dmVyfS54bHN4IikpCnR5cGVfdGFibGUKY29tYmluZWRfdG9fdHN2KHR5cGVfdGFibGUsIGNlbGx0eXBlID0gImFsbCIpCgp0eXBlX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHR5cGVfdGFibGUsCiAgZXhjZWwgPSBnbHVlKCJleGNlbC9tYWNyb3BoYWdlX2RlL3t2ZXJ9L3NpZ190YWJsZXMvbWFjcm9waGFnZV90eXBlX3NpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX3NpZwp0eXBlX2hpZ2hzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB0eXBlX3RhYmxlLCBtaW5fbWVhbl9leHBycyA9IGhpZ2hfZXhwcmVzc2lvbiwgZXhwcnNfY29sdW1uID0gaGlnaF9leHByZXNzaW9uX2NvbHVtbiwKICBleGNlbCA9IGdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfZGUve3Zlcn0vc2lnX3RhYmxlcy9tYWNyb3BoYWdlX3R5cGVfaGlnaHNpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX2hpZ2hzaWcKYGBgCgojIyMjIENvbWJpbmVkIGZhY3RvcnMgb2YgaW50ZXJlc3Q6IGNlbGx0eXBlK3p5bW9kZW1lCgpHaXZlbiB0aGUgYWJvdmUgZXhwbGljaXQgY29tcGFyaXNvbiBvZiBhbGwgc2FtcGxlcyBjb21wcmlzaW5nIHRoZSB0d28KY2VsbCB0eXBlcywgbm93IGxldCB1cyBsb29rIGF0IHRoZSBkcnVnIHRyZWF0bWVudCt6eW1vZGVtZSBzdGF0dXMgd2l0aAphbGwgc2FtcGxlcywgbWFjcm9waGFnZXMgYW5kIFU5MzcuCgpgYGB7cn0KdHlwZV96eW1vX2RlIDwtIGFsbF9wYWlyd2lzZSh0eXBlX3p5bW8sIGZpbHRlciA9IFRSVUUsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIsIGRvX25vaXNlcSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4dHJhX2NvbnRyYXN0cyA9IHR5cGVfenltb19leHRyYSkKdHlwZV96eW1vX2RlCgp0eXBlX3p5bW9fdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgdHlwZV96eW1vX2RlLCBrZWVwZXJzID0gdG1yYzJfdHlwZXp5bW9fa2VlcGVycywKICBleGNlbCA9IGdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL21hY3JvcGhhZ2VfdHlwZV96eW1vX2NvbXBhcmlzb24tdnt2ZXJ9Lnhsc3giKSkKY29tYmluZWRfdG9fdHN2KHR5cGVfenltb190YWJsZSwgY2VsbHR5cGUgPSAiYWxsIikKCnR5cGVfenltb19zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB0eXBlX3p5bW9fdGFibGUsCiAgZXhjZWwgPSBnbHVlKCJleGNlbC9tYWNyb3BoYWdlX2RlL3t2ZXJ9L3NpZ190YWJsZXMvbWFjcm9waGFnZV90eXBlX3p5bW9fc2lnLXZ7dmVyfS54bHN4IikpCnR5cGVfenltb19zaWcKdHlwZV96eW1vX2hpZ2hzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB0eXBlX3p5bW9fdGFibGUsIG1pbl9tZWFuX2V4cHJzID0gaGlnaF9leHByZXNzaW9uLCBleHByc19jb2x1bW4gPSBoaWdoX2V4cHJlc3Npb25fY29sdW1uLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS97dmVyfS9zaWdfdGFibGVzL21hY3JvcGhhZ2VfdHlwZV96eW1vX2hpZ2hzaWctdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIyMjIENvbWJpbmVkIGZhY3RvcnMgb2YgaW50ZWVzdDogY2VsbHR5cGUrZHJ1ZwoKVGhlICd0eXBlX2RydWcnIGRhdGFzdHJ1Y3R1cmUgaXMgdGhlIHNhbWUgYXMgYWJvdmUsIGJ1dCB0aGUgY29uZGl0aW9uCmlzIGNyZWF0ZWQgZnJvbSB0aGUgY29uY2F0ZW5hdGlvbiBvZiB0aGUgY2VsbCB0eXBlIGFuZCBkcnVnIHRyZWF0bWVudC4KCmBgYHtyfQp0eXBlX2RydWdfZGUgPC0gYWxsX3BhaXJ3aXNlKHR5cGVfZHJ1ZywgZmlsdGVyID0gVFJVRSwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIikKdHlwZV9kcnVnX2RlCnR5cGVfZHJ1Z190YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICB0eXBlX2RydWdfZGUsIGtlZXBlcnMgPSB0bXJjMl90eXBlZHJ1Z19rZWVwZXJzLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS97dmVyfS9kZV90YWJsZXMvbWFjcm9waGFnZV90eXBlX2RydWdfY29tcGFyaXNvbi12e3Zlcn0ueGxzeCIpKQp0eXBlX2RydWdfdGFibGUKY29tYmluZWRfdG9fdHN2KHR5cGVfZHJ1Z190YWJsZSwgY2VsbHR5cGUgPSAiYWxsIikKdHlwZV9kcnVnX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHR5cGVfZHJ1Z190YWJsZSwKICBleGNlbCA9IGdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfZGUve3Zlcn0vc2lnX3RhYmxlcy9tYWNyb3BoYWdlX3R5cGVfZHJ1Z19zaWctdnt2ZXJ9Lnhsc3giKSkKdHlwZV9kcnVnX3NpZwp0eXBlX2RydWdfaGlnaHNpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHR5cGVfZHJ1Z190YWJsZSwgbWluX21lYW5fZXhwcnMgPSBoaWdoX2V4cHJlc3Npb24sIGV4cHJzX2NvbHVtbiA9IGhpZ2hfZXhwcmVzc2lvbl9jb2x1bW4sCiAgZXhjZWwgPSBnbHVlKCJleGNlbC9tYWNyb3BoYWdlX2RlL3t2ZXJ9L3NpZ190YWJsZXMvbWFjcm9waGFnZV90eXBlX2RydWdfaGlnaHNpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX2RydWdfaGlnaHNpZwpgYGAKCiMgSW5kaXZpZHVhbCBjZWxsIHR5cGVzCgpBdCB0aGlzIHBvaW50LCBJIHRoaW5rIGl0IGlzIGZhaXIgdG8gc2F5IHRoYXQgdGhlIHR3byBjZWxsIHR5cGVzIGFyZQpzdWZmaWNpZW50bHkgZGlmZmVyZW50IHRoYXQgdGhleSBkbyBub3QgcmVhbGx5IGJlbG9uZyB0b2dldGhlciBpbiBhCnNpbmdsZSBhbmFseXNpcy4KCiMjIGRydWcgb3Igc3RyYWluIGVmZmVjdHMsIHNpbmdsZSBjZWxsIHR5cGUKCk9uZSBvZiB0aGUgcXVlcmllcyBOYWppYiBhc2tlZCB3aGljaCBJIHRoaW5rIEkgbWlzaW50ZXJwcmV0ZWQgd2FzIHRvCmxvb2sgYXQgZHJ1ZyBhbmQvb3Igc3RyYWluIGVmZmVjdHMuICBNeSBpbnRlcnByZXRhdGlvbiBpcyBzb21ld2hlcmUKYmVsb3cgYW5kIHdhcyBub3Qgd2hhdCBoZSB3YXMgbG9va2luZyBmb3IuICBJbnN0ZWFkLCBoZSB3YXMgbG9va2luZyB0bwpzZWUgYWxsKG1hY3JvcGhhZ2UpIGRydWcvbm9kcnVnIGFuZCBhbGwobWFjcm9waGFnZSkgejIzL3oyMiBhbmQKY29tcGFyZSB0aGVtIHRvIGVhY2ggb3RoZXIuICBJdCBtYXkgYmUgdGhhdCB0aGlzIGlzIHN0aWxsIGEgd3JvbmcKaW50ZXJwcmV0YXRpb24sIGlmIHNvIHRoZSBtb3N0IGxpa2VseSBjb21wYXJpc29uIGlzIGVpdGhlcjoKCiogICh6MjNkcnVnL3oyMmRydWcpIC8gKHoyM25vZHJ1Zy96MjJub2RydWcpLCBvciBwZXJoYXBzCiogICh6MjNkcnVnL3oyM25vZHJ1ZykgLyAoejIyZHJ1Zy96MjJub2RydWcpLAoKSSBhbSBub3Qgc3VyZSB0aG9zZSBjb25mdXNlIG1lLCBhbmQgYXQgbGVhc3Qgb25lIG9mIHRoZW0gaXMgYmVsb3cKCiMjIyBNYWNyb3BoYWdlcwoKSW4gdGhlc2UgYmxvY2tzIHdlIHdpbGwgZXhwbGljaXRseSBxdWVyeSBvbmx5IG9uZSBmYWN0b3IgYXQgYSB0aW1lLApkcnVnIGFuZCBzdHJhaW4uICBUaGUgZXZlbnR1YWwgZ29hbCBpcyB0byBsb29rIGZvciBlZmZlY3RzIG9mCmRydWcgdHJlYXRtZW50IGFuZC9vciBzdHJhaW4gdHJlYXRtZW50IHdoaWNoIGFyZSBzaGFyZWQ/CgojIyMjIE1hY3JvcGhhZ2UgRHJ1ZyBvbmx5CgpUaHVzIHdlIHdpbGwgc3RhcnQgd2l0aCB0aGUgcHVyZSBkcnVnIHF1ZXJ5LiAgSW4gdGhpcyBibG9jayB3ZSB3aWxsCmxvb2sgb25seSBhdCB0aGUgZHJ1Zy9ub2RydWcgZWZmZWN0LgoKYGBge3J9CmhzX21hY3JfZHJ1Z19kZSA8LSBhbGxfcGFpcndpc2UoaHNfbWFjcl9kcnVnX2V4cHQsIGZpbHRlciA9IFRSVUUsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIpCmhzX21hY3JfZHJ1Z19kZQpoc19tYWNyX2RydWdfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgaHNfbWFjcl9kcnVnX2RlLCBrZWVwZXJzID0gdG1yYzJfZHJ1Z19rZWVwZXJzLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS9tYWNyb3BoYWdlX29ubHlkcnVnX3RhYmxlLXZ7dmVyfS54bHN4IikpCmhzX21hY3JfZHJ1Z190YWJsZQpjb21iaW5lZF90b190c3YoaHNfbWFjcl9kcnVnX3RhYmxlLCBjZWxsdHlwZSA9ICJtYWNyb3BoYWdlIikKCmhzX21hY3JfZHJ1Z19zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBoc19tYWNyX2RydWdfdGFibGUsCiAgZXhjZWwgPSBnbHVlKCJleGNlbC9tYWNyb3BoYWdlX2RlL21hY3JvcGhhZ2Vvbmx5X2RydWdfc2lnLXZ7dmVyfS54bHN4IikpCmhzX21hY3JfZHJ1Z19zaWcKaHNfbWFjcl9kcnVnX2hpZ2hzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBoc19tYWNyX2RydWdfdGFibGUsIG1pbl9tZWFuX2V4cHJzID0gaGlnaF9leHByZXNzaW9uLCBleHByc19jb2x1bW4gPSBoaWdoX2V4cHJlc3Npb25fY29sdW1uLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS9tYWNyb3BoYWdlb25seV9kcnVnX2hpZ2hzaWctdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9kcnVnX2hpZ2hzaWcKYGBgCgojIyMjIE1hY3JvcGhhZ2UgU3RyYWluIG9ubHkKCkluIGEgc2ltaWxhciBmYXNoaW9uLCBsZXQgdXMgbG9vayBmb3IgZWZmZWN0cyB3aGljaCBhcmUgb2JzZXJ2ZWQgd2hlbgp3ZSBjb25zaWRlciBvbmx5IHRoZSBzdHJhaW4gdXNlZCBkdXJpbmcgaW5mZWN0aW9uLgoKYGBge3J9CmhzX21hY3Jfc3RyYWluX2RlIDwtIGFsbF9wYWlyd2lzZShoc19tYWNyX3N0cmFpbl9leHB0LCBmaWx0ZXIgPSBUUlVFLCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiKQpoc19tYWNyX3N0cmFpbl9kZQpoc19tYWNyX3N0cmFpbl90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBoc19tYWNyX3N0cmFpbl9kZSwga2VlcGVycyA9IHRtcmMyX3N0cmFpbl9rZWVwZXJzLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS9tYWNyb3BoYWdlX29ubHlzdHJhaW5fdGFibGUtdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9zdHJhaW5fdGFibGUKY29tYmluZWRfdG9fdHN2KGhzX21hY3Jfc3RyYWluX3RhYmxlLCBjZWxsdHlwZSA9ICJtYWNyb3BoYWdlIikKCmhzX21hY3Jfc3RyYWluX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX21hY3Jfc3RyYWluX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS9tYWNyb3BoYWdlb25seV9vbmx5c3RyYWluX3NpZy12e3Zlcn0ueGxzeCIpKQpoc19tYWNyX3N0cmFpbl9zaWcKaHNfbWFjcl9zdHJhaW5faGlnaHNpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX21hY3Jfc3RyYWluX3RhYmxlLCBtaW5fbWVhbl9leHBycyA9IGhpZ2hfZXhwcmVzc2lvbiwgZXhwcnNfY29sdW1uID0gaGlnaF9leHByZXNzaW9uX2NvbHVtbiwKICBleGNlbCA9IGdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfZGUvbWFjcm9waGFnZW9ubHlfb25seXN0cmFpbl9oaWdoc2lnLXZ7dmVyfS54bHN4IikpCmhzX21hY3Jfc3RyYWluX2hpZ2hzaWcKYGBgCgojIyMjIENvbXBhcmUgRHJ1ZyBhbmQgU3RyYWluIEVmZmVjdHMKCk5vdyBsZXQgdXMgY29uc2lkZXIgdGhlIGFib3ZlIHR3byBjb21wYXJpc29ucyB0b2dldGhlci4gIEZpcnN0LCBJIHdpbGwKcGxvdCB0aGUgbG9nRkMgdmFsdWVzIG9mIHRoZW0gYWdhaW5zdCBlYWNoIG90aGVyIChkcnVnIG9uIHgtYXhpcyBhbmQKc3RyYWluIG9uIHRoZSB5LWF4aXMpLiAgVGhlbiB3ZSBjYW4gZXh0cmFjdCB0aGUgc2lnbmlmaWNhbnQgZ2VuZXMgaW4gYQpmZXcgY29tYmluZWQgY2F0ZWdvcmllcyBvZiBpbnRlcmVzdC4gIEkgYXNzdW1lIHRoZXNlIHdpbGwgZm9jdXMKZXhjbHVzaXZlbHkgb24gdGhlIGNhdGVnb3JpZXMgd2hpY2ggaW5jbHVkZSB0aGUgaW50cm9kdWN0aW9uIG9mIHRoZQpkcnVnLgoKYGBge3J9CmRydWdfc3RyYWluX2NvbXBfZGYgPC0gbWVyZ2UoaHNfbWFjcl9kcnVnX3RhYmxlW1siZGF0YSJdXVtbImRydWciXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHNfbWFjcl9zdHJhaW5fdGFibGVbWyJkYXRhIl1dW1sic3RyYWluIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInJvdy5uYW1lcyIpCmRydWdfc3RyYWluX2NvbXBfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKAogIGRydWdfc3RyYWluX2NvbXBfZGZbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCiMjIENvbnRyYXN0czogYW50aW1vbnkvbm9uZSwgejIzL3oyMjsgeC1heGlzOiBkcnVnLCB5LWF4aXM6IHN0cmFpbgojIyB0b3AgbGVmdDogaGlnaGVyIG5vIGRydWcsIHoyMzsgdG9wIHJpZ2h0OiBoaWdoZXIgZHJ1ZyB6MjMKIyMgYm90dG9tIGxlZnQ6IGhpZ2hlciBubyBkcnVnLCB6MjI7IGJvdHRvbSByaWdodDogaGlnaGVyIGRydWcgejIyCmRydWdfc3RyYWluX2NvbXBfcGxvdCRzY2F0dGVyCmBgYAoKQXMgSSBub3RlZCBpbiB0aGUgY29tbWVudHMgYWJvdmUsIHNvbWUgcXVhZHJhbnRzIG9mIHRoZSBzY2F0dGVyIHBsb3QKYXJlIGxpa2VseSB0byBiZSBvZiBncmVhdGVyIGludGVyZXN0IHRvIHVzIHRoYW4gb3RoZXJzICh0aGUgcmlnaHQKc2lkZSkuICBCZWNhdXNlIEkgZ2V0IGNvbmZ1c2VkIHNvbWV0aW1lcywgdGhlIGZvbGxvd2luZyBibG9jayB3aWxsCmV4cGxpY2l0bHkgbmFtZSB0aGUgY2F0ZWdvcmllcyBvZiBsaWtlbHkgaW50ZXJlc3QsIHRoZW4gYXNrIHdoaWNoCmdlbmVzIGFyZSBzaGFyZWQgYW1vbmcgdGhlbSwgYW5kIGZpbmFsbHkgdXNlIFVwU2V0UiB0byBleHRyYWN0IHRoZQp2YXJpb3VzIGdlbmUgaW50ZXJzZWN0aW9uL3VuaW9uIGNhdGVnb3JpZXMuCgpgYGB7cn0KaGlnaGVyX2RydWcgPC0gaHNfbWFjcl9kcnVnX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWzFdXQpoaWdoZXJfbm9kcnVnIDwtIGhzX21hY3JfZHJ1Z19zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbMV1dCmhpZ2hlcl96MjMgPC0gaHNfbWFjcl9zdHJhaW5fc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWzFdXQpoaWdoZXJfejIyIDwtIGhzX21hY3Jfc3RyYWluX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWzFdXQpzdW0ocm93bmFtZXMoaGlnaGVyX2RydWcpICVpbiUgcm93bmFtZXMoaGlnaGVyX3oyMykpCnN1bShyb3duYW1lcyhoaWdoZXJfZHJ1ZykgJWluJSByb3duYW1lcyhoaWdoZXJfejIyKSkKc3VtKHJvd25hbWVzKGhpZ2hlcl9ub2RydWcpICVpbiUgcm93bmFtZXMoaGlnaGVyX3oyMykpCnN1bShyb3duYW1lcyhoaWdoZXJfbm9kcnVnKSAlaW4lIHJvd25hbWVzKGhpZ2hlcl96MjIpKQoKZHJ1Z196MjNfbHN0IDwtIGxpc3QoImRydWciID0gcm93bmFtZXMoaGlnaGVyX2RydWcpLAogICAgICAgICAgICAgICAgICAgICAiejIzIiA9IHJvd25hbWVzKGhpZ2hlcl96MjMpKQp1cHNldF9pbnB1dCA8LSBVcFNldFI6OmZyb21MaXN0KGRydWdfejIzX2xzdCkKaGlnaGVyX2RydWdfejIzIDwtIHVwc2V0KHVwc2V0X2lucHV0LCB0ZXh0LnNjYWxlID0gMikKaGlnaGVyX2RydWdfejIzCgpkcnVnX3oyM19zaGFyZWRfZ2VuZXMgPC0gb3ZlcmxhcF9ncm91cHMoZHJ1Z196MjNfbHN0KQpzaGFyZWRfZ2VuZXNfZHJ1Z196MjMgPC0gb3ZlcmxhcF9nZW5laWRzKGRydWdfejIzX3NoYXJlZF9nZW5lcywgImRydWc6ejIzIikKc2hhcmVkX2dlbmVzX2RydWdfejIzIDwtIGF0dHIoZHJ1Z196MjNfc2hhcmVkX2dlbmVzLCAiZWxlbWVudHMiKVtkcnVnX3oyM19zaGFyZWRfZ2VuZXNbWyJkcnVnOnoyMyJdXV0KCmRydWdfejIyX2xzdCA8LSBsaXN0KCJkcnVnIiA9IHJvd25hbWVzKGhpZ2hlcl9kcnVnKSwKICAgICAgICAgICAgICAgICAgICAgInoyMiIgPSByb3duYW1lcyhoaWdoZXJfejIyKSkKaGlnaGVyX2RydWdfejIyIDwtIHVwc2V0KFVwU2V0Ujo6ZnJvbUxpc3QoZHJ1Z196MjJfbHN0KSwgdGV4dC5zY2FsZSA9IDIpCmhpZ2hlcl9kcnVnX3oyMgoKZHJ1Z196MjJfc2hhcmVkX2dlbmVzIDwtIG92ZXJsYXBfZ3JvdXBzKGRydWdfejIyX2xzdCkKc2hhcmVkX2dlbmVzX2RydWdfejIyIDwtIG92ZXJsYXBfZ2VuZWlkcyhkcnVnX3oyMl9zaGFyZWRfZ2VuZXMsICJkcnVnOnoyMiIpCnNoYXJlZF9nZW5lc19kcnVnX3oyMiA8LSBhdHRyKGRydWdfejIyX3NoYXJlZF9nZW5lcywgImVsZW1lbnRzIilbZHJ1Z196MjJfc2hhcmVkX2dlbmVzW1siZHJ1Zzp6MjIiXV1dCmBgYAoKIyMjIyBQZXJmb3JtIGdQcm9maWxlciBvbiBkcnVnL3N0cmFpbiBlZmZlY3Qgc2hhcmVkIGdlbmVzCgpOb3cgdGhhdCB3ZSBoYXZlIHNvbWUgcG9wdWxhdGlvbnMgb2YgZ2VuZXMgd2hpY2ggYXJlIHNoYXJlZCBhY3Jvc3MgdGhlCmRydWcvc3RyYWluIGVmZmVjdHMsIGxldCB1cyBwYXNzIHRoZW0gdG8gc29tZSBHU0VBIGFuYWx5c2VzIGFuZCBzZWUKd2hhdCBwb3BzIG91dC4KCmBgYHtyfQp3YW50ZWQgPC0gZHJ1Z196MjNfc2hhcmVkX2dlbmVzW1siZHJ1Zzp6MjMiXV0Kc2hhcmVkX2dlbmVzX2RydWdfejIzIDwtIGF0dHIoZHJ1Z196MjNfc2hhcmVkX2dlbmVzLCAiZWxlbWVudHMiKVt3YW50ZWRdCnNoYXJlZF9kcnVnX3oyM19ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNoYXJlZF9nZW5lc19kcnVnX3oyMykKc2hhcmVkX2RydWdfejIzX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0Kc2hhcmVkX2RydWdfejIzX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siQlAiXV0Kc2hhcmVkX2RydWdfejIzX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQoKd2FudGVkIDwtIGRydWdfejIyX3NoYXJlZF9nZW5lc1tbImRydWc6ejIyIl1dCnNoYXJlZF9nZW5lc19kcnVnX3oyMiA8LSBhdHRyKGRydWdfejIyX3NoYXJlZF9nZW5lcywgImVsZW1lbnRzIilbd2FudGVkXQpzaGFyZWRfZHJ1Z196MjJfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihzaGFyZWRfZ2VuZXNfZHJ1Z196MjIpCnNoYXJlZF9kcnVnX3oyMl9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCmBgYAoKIyMgT3VyIG1haW4gcXVlc3Rpb24gb2YgaW50ZXJlc3QKClRoZSBkYXRhIHN0cnVjdHVyZSBoc19tYWNyIGNvbnRhaW5zIG91ciBwcmltYXJ5IG1hY3JvcGhhZ2VzLCB3aGljaAphcmUsIGFzIHNob3duIGFib3ZlLCB0aGUgZGF0YSB3ZSBjYW4gcmVhbGx5IHNpbmsgb3VyIHRlZXRoIGludG8uCgpOb3RlLCB3ZSBleHBlY3Qgc29tZSBlcnJvcnMgd2hlbiBydW5uaW5nIHRoZSBjb21iaW5lX2RlX3RhYmxlcygpCmJlY2F1c2Ugbm90IGFsbCBtZXRob2RzIEkgdXNlIGFyZSBjb21mb3J0YWJsZSB1c2luZyB0aGUgcmF0aW8gb3IKcmF0aW9zIGNvbnRyYXN0cyB3ZSBhZGRlZCBpbiB0aGUgJ2V4dHJhcycgYXJndW1lbnQuICBBcyBhIHJlc3VsdCwgd2hlbgp3ZSBjb21iaW5lIHRoZW0gaW50byB0aGUgbGFyZ2VyIG91dHB1dCB0YWJsZXMsIHRob3NlIHBlY3VsaWFyCmNvbnRyYXN0cyBmYWlsLiAgVGhpcyBkb2VzIG5vdCBzdG9wIGl0IGZyb20gd3JpdGluZyB0aGUgcmVzdCBvZiB0aGUKcmVzdWx0cywgaG93ZXZlci4KCmBgYHtyfQojdGVzdCA9IGRlc2VxX3BhaXJ3aXNlKG5vcm1hbGl6ZV9leHB0KGhzX21hY3IsIGZpbHRlcj1UUlVFKSwKIyAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiLCBmaWx0ZXIgPSBUUlVFLAojICAgICAgICAgICAgICAgICAgICAgIGV4dHJhX2NvbnRyYXN0cyA9IHRtcmMyX2h1bWFuX2V4dHJhKQoKaHNfbWFjcl9kZSA8LSBhbGxfcGFpcndpc2UoaHNfbWFjciwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyID0gVFJVRSwgZXh0cmFfY29udHJhc3RzID0gdG1yYzJfaHVtYW5fZXh0cmEpCmhzX21hY3JfZGUKaHNfc2luZ2xlX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGhzX21hY3JfZGUsIGtlZXBlcnMgPSBzaW5nbGVfdG1yYzJfa2VlcGVyLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS9oc19tYWNyX2RydWdfenltb196MjJzYl9zYi12e3Zlcn0ueGxzeCIpKQpoc19zaW5nbGVfdGFibGUKaHNfbWFjcl90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBoc19tYWNyX2RlLCBrZWVwZXJzID0gdG1yYzJfaHVtYW5fa2VlcGVycywKICBleGNlbCA9IGdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfZGUvaHNfbWFjcl9kcnVnX3p5bW9fdGFibGVfbWFjcl9vbmx5LXZ7dmVyfS54bHN4IikpCmhzX21hY3JfdGFibGUKY29tYmluZWRfdG9fdHN2KGhzX21hY3JfdGFibGUsICJtYWNyb3BoYWdlIikKCmhzX21hY3Jfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgaHNfbWFjcl90YWJsZSwKICBleGNlbCA9IGdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfZGUvaHNfbWFjcl9kcnVnX3p5bW9fc2lnLXZ7dmVyfS54bHN4IikpCmhzX21hY3Jfc2lnCmhzX21hY3JfaGlnaHNpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX21hY3JfdGFibGUsIG1pbl9tZWFuX2V4cHJzID0gaGlnaF9leHByZXNzaW9uLCBleHByc19jb2x1bW4gPSBoaWdoX2V4cHJlc3Npb25fY29sdW1uLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS9oc19tYWNyX2RydWdfenltb19oaWdoc2lnLXZ7dmVyfS54bHN4IikpCmhzX21hY3JfaGlnaHNpZwpgYGAKCiMjIGdlbmUgZ3JvdXAgdXBzZXQKCmBgYHtyfQpub2RydWdfdXBzZXQgPC0gdXBzZXRyX2NvbWJpbmVkX2RlKGhzX21hY3JfdGFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaXJlZF9jb250cmFzdHMgPSBjKCJ6MjJub3NiX3ZzX3VuaW5mIiwgInoyM25vc2JfdnNfdW5pbmYiKSkKcHAoZmlsZSA9ICJpbWFnZXMvbm9kcnVnX3Vwc2V0LnBuZyIpCm5vZHJ1Z191cHNldApkZXYub2ZmKCkKZHJ1Z191cHNldCA8LSB1cHNldHJfY29tYmluZWRfZGUoaHNfbWFjcl90YWJsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaXJlZF9jb250cmFzdHMgPSBjKCJ6MjJzYl92c19zYiIsICJ6MjNzYl92c19zYiIpKQpwcChmaWxlID0gImltYWdlcy9kcnVnX3Vwc2V0LnBuZyIpCmRydWdfdXBzZXQKZGV2Lm9mZigpCmBgYAoKIyBTaWduaWZpY2FuY2UgYmFycGxvdCBvZiBpbnRlcmVzdAoKT2xnYSBraW5kbHkgc2VudCBhIHNldCBvZiBwYXJ0aWN1bGFybHkgaW50ZXJlc3RpbmcgY29udHJhc3RzIGFuZApjb2xvcnMgZm9yIGEgc2lnbmlmaWNhbmNlIGJhcnBsb3QsIHRoZXkgaW5jbHVkZSB0aGUgZm9sbG93aW5nOgoKKiB6Mi4zIHZzLiB1bmluZmVjdGVkLgoqIHoyLjIgdnMuIHVuaW5mZWN0ZWQuCiogejIuMyB2cyB6Mi4yCiogejIuM1NidiB2cyB6Mi4zCiogejIuMlNidiB2cyB6Mi4yCiogejIuM1NidiB2cyB6Mi4yU2J2CiogU2J2IHZzIHVuaW5mZWN0ZWQuCgpUaGUgZXhpc3Rpbmcgc2V0IG9mICdrZWVwZXJzJyBleHZpc2VkIHRvIHRoZXNlIGlzIHRha2VuIGZyb20gdGhlCmV4dGFudCBzZXQgb2YgJ3RtcmMyX2h1bWFuX2tlZXBlcnMnIGFuZCBpcyBhcyBmb2xsb3dzOgoKCmBgYHtyfQpiYXJwbG90X2tlZXBlcnMgPC0gbGlzdCgKICAjIyB6Mi4zIHZzIHVuaW5mZWN0ZWQKICAiejIzbm9zYl92c191bmluZiIgPSBjKCJpbmZ6MjMiLCAidW5pbmZub25lIiksCiAgIyMgejIuMiB2cyB1bmluZmVjdGVkCiAgInoyMm5vc2JfdnNfdW5pbmYiID0gYygiaW5mejIyIiwgInVuaW5mbm9uZSIpLAogICMjIHoyLjMgdnMgejIuMgogICJ6MjNub3NiX3ZzX3oyMm5vc2IiID0gYygiaW5mejIzIiwgImluZnoyMiIpLAogICMjIHoyLjNTYnYgdnMgejIuMwogICJ6MjNzYl92c196MjNub3NiIiA9IGMoImluZnNiejIzIiwgImluZnoyMyIpLAogICMjIHoyLjJTYnYgdnMgejIuMgogICJ6MjJzYl92c196MjJub3NiIiA9IGMoImluZnNiejIyIiwgImluZnoyMiIpLAogICMjIHoyLjNTYnYgdnMgejIuMlNidgogICJ6MjNzYl92c196MjJzYiIgPSBjKCJpbmZzYnoyMyIsICJpbmZzYnoyMiIpLAogICMjIFNidiB2cyB1bmluZmVjdGVkLgogICJzYl92c191bmluZiIgPSBjKCJ1bmluZnNibm9uZSIsICJ1bmluZm5vbmUiKSkKYmFycGxvdF9jb21iaW5lZCA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBoc19tYWNyX2RlLCBrZWVwZXJzID0gYmFycGxvdF9rZWVwZXJzLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS9oc19tYWNyX2RydWdfenltb183Y29udHJhc3RzLXZ7dmVyfS54bHN4IikpCmBgYAoKTm93IGxldCB1cyB1c2UgdGhlIGNvbG9ycyBzdWdnZXN0ZWQgYnkgT2xnYSB0byBtYWtlIGEgYmFycGxvdCBvZgp0aGVzZS4uLgoKYGBge3J9CmNvbG9yX2xpc3QgPC0gIGMoICIjZGU4YmY5IiwgIiNhZDA3ZTMiLCIjNDEwMjU3IiwgIiNmZmEwYTAiLCAiI2Y5NDA0MCIsICIjYTAwMDAwIikKYmFycGxvdF9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBiYXJwbG90X2NvbWJpbmVkLCBjb2xvcl9saXN0ID0gY29sb3JfbGlzdCwgYWNjb3JkaW5nX3RvID0gImRlc2VxIiwKICBleGNlbCA9IGdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfZGUvaHNfbWFjcl9kcnVnX3p5bW9fN2NvbnRyYXN0c19zaWctdnt2ZXJ9Lnhsc3giKSkKYmFycGxvdF9zaWcKYGBgCgojIFBST1BFUgoKSW4gb3VyIGxhc3QgbWVldGluZyB0aGVyZSB3ZXJlIHNvbWUgcXVlc3Rpb25zIGFib3V0IHRoZSBzdGF0aXN0aWNhbApwb3dlciBvZiBkaWZmZXJlbnQgZnV0dXJlIGV4cGVyaW1lbnRhbCBkZXNpZ25zLiAgT25lIHRoaW5nIEkgY2FuIGRvIGlzCnRvIHVzZSBQUk9QRVIgdG8gZXN0aW1hdGUgdGhlIHBvd2VyIG9mIGFuIGV4dGFudCBkYXRhc2V0IGFuZCBpbmZlcgpmcm9tIHRoYXQgdGhlIGxpa2VseSBwb3dlciBvZiBvdGhlciBkZXNpZ25zLgoKSW4gb3JkZXIgdG8gdXNlIHByb3Blciwgb25lIG11c3QgZmVlZCBpdCBvbmUgb3IgbW9yZSBERSB0YWJsZXMuCgpgYGB7cn0KcG93ZXJfZXN0aW1hdGUgPC0gc2ltcGxlX3Byb3Blcihoc19zaW5nbGVfdGFibGUpCnBvd2VyX2VzdGltYXRlCgpwb3dlcl9lc3RpbWF0ZVtbMV1dW1sicG93ZXJfcGxvdCJdXQpwb3dlcl9lc3RpbWF0ZVtbMV1dW1sicG93ZXJ0ZF9wbG90Il1dCnBvd2VyX2VzdGltYXRlW1sxXV1bWyJwb3dlcmZkX3Bsb3QiXV0KCmBgYAoKIyMjIE91ciBtYWluIHF1ZXN0aW9ucyBpbiBVOTM3CgpMZXQgdXMgZG8gdGhlIHNhbWUgY29tcGFyaXNvbnMgaW4gdGhlIFU5Mzcgc2FtcGxlcywgdGhvdWdoIEkgd2lsbCBub3QKZG8gdGhlIGV4dHJhIGNvbnRyYXN0cywgcHJpbWFyaWx5IGJlY2F1c2UgSSB0aGluayB0aGUgZGF0YXNldCBpcyBsZXNzCmxpa2VseSB0byBzdXBwb3J0IHRoZW0uCgpgYGB7cn0KdTkzN19kZSA8LSBhbGxfcGFpcndpc2UodTkzN19leHB0LCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiLAogICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIgPSBUUlVFLCBkb19ub2lzZXEgPSBGQUxTRSkKdTkzN19kZQp1OTM3X3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIHU5MzdfZGUsIGtlZXBlcnMgPSB1OTM3X2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJleGNlbC9tYWNyb3BoYWdlX2RlL3U5MzdfZHJ1Z196eW1vX3RhYmxlLXZ7dmVyfS54bHN4IikpCnU5MzdfdGFibGUKY29tYmluZWRfdG9fdHN2KHU5MzdfdGFibGUsIGNlbGx0eXBlID0gInU5MzciKQoKdTkzN19zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB1OTM3X3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS91OTM3X2RydWdfenltb19zaWctdnt2ZXJ9Lnhsc3giKSkKdTkzN19zaWcKdTkzN19oaWdoc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgdTkzN190YWJsZSwgbWluX21lYW5fZXhwcnMgPSBoaWdoX2V4cHJlc3Npb24sIGV4cHJzX2NvbHVtbiA9IGhpZ2hfZXhwcmVzc2lvbl9jb2x1bW4sCiAgZXhjZWwgPSBnbHVlKCJleGNlbC9tYWNyb3BoYWdlX2RlL3U5MzdfZHJ1Z196eW1vX2hpZ2hzaWctdnt2ZXJ9Lnhsc3giKSkKdTkzN19oaWdoc2lnCmBgYAoKIyMjIyBDb21wYXJlIChubylTYiB6Mi4zL3oyLjIgdHJlYXRtZW50cyBhbW9uZyBtYWNyb3BoYWdlcwoKYGBge3J9CnVwc2V0X3Bsb3RzX2hzX21hY3IgPC0gdXBzZXRyX3NpZygKICBoc19tYWNyX3NpZywgYm90aCA9IFRSVUUsCiAgY29udHJhc3RzID0gYygiejIzc2JfdnNfejIyc2IiLCAiejIzbm9zYl92c196MjJub3NiIikpCnVwc2V0X3Bsb3RzX2hzX21hY3JbWyJib3RoIl1dCmdyb3VwcyA8LSB1cHNldF9wbG90c19oc19tYWNyW1siYm90aF9ncm91cHMiXV0Kc2hhcmVkX2dlbmVzIDwtIGF0dHIoZ3JvdXBzLCAiZWxlbWVudHMiKVtncm91cHNbWzJdXV0gJT4lCiAgZ3N1YihwYXR0ZXJuID0gIl5nZW5lOiIsIHJlcGxhY2VtZW50ID0gIiIpCmxlbmd0aChzaGFyZWRfZ2VuZXMpCgpzaGFyZWRfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihzaGFyZWRfZ2VuZXMpCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KCmRydWdfZ2VuZXMgPC0gYXR0cihncm91cHMsICJlbGVtZW50cyIpW2dyb3Vwc1tbInoyM3NiX3ZzX3oyMnNiIl1dXSAlPiUKICBnc3ViKHBhdHRlcm4gPSAiXmdlbmU6IiwgcmVwbGFjZW1lbnQgPSAiIikKZHJ1Z29ubHlfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihkcnVnX2dlbmVzKQpkcnVnb25seV9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCmBgYAoKSSB3YW50IHRvIHRyeSBzb21ldGhpbmcsIGRpcmVjdGx5IGluY2x1ZGUgdGhlIHU5MzcgZGF0YSBpbiB0aGlzLi4uCgpgYGB7cn0KYm90aF9zaWcgPC0gaHNfbWFjcl9zaWcKbmFtZXMoYm90aF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXSkgPC0gcGFzdGUwKCJtYWNyXyIsIG5hbWVzKGJvdGhfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV0pKQpuYW1lcyhib3RoX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV0pIDwtIHBhc3RlMCgibWFjcl8iLCBuYW1lcyhib3RoX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV0pKQp1OTM3X2Rlc2VxIDwtIHU5Mzdfc2lnW1siZGVzZXEiXV0KbmFtZXModTkzN19kZXNlcVtbInVwcyJdXSkgPC0gcGFzdGUwKCJ1OTM3XyIsIG5hbWVzKHU5MzdfZGVzZXFbWyJ1cHMiXV0pKQpuYW1lcyh1OTM3X2Rlc2VxW1siZG93bnMiXV0pIDwtIHBhc3RlMCgidTkzN18iLCBuYW1lcyh1OTM3X2Rlc2VxW1siZG93bnMiXV0pKQpib3RoX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dIDwtIGMoYm90aF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXSwgdTkzN19kZXNlcVtbInVwcyJdXSkKYm90aF9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dIDwtIGMoYm90aF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXSwgdTkzN19kZXNlcVtbImRvd25zIl1dKQpzdW1tYXJ5KGJvdGhfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV0pCgp1cHNldF9wbG90c19ib3RoIDwtIHVwc2V0cl9zaWcoCiAgYm90aF9zaWcsIGJvdGggPSBUUlVFLAogIGNvbnRyYXN0cyA9IGMoIm1hY3JfejIzc2JfdnNfejIyc2IiLCAibWFjcl96MjNub3NiX3ZzX3oyMm5vc2IiLAogICAgICAgICAgICAgICAgInU5MzdfejIzc2JfdnNfejIyc2IiLCAidTkzN196MjNub3NiX3ZzX3oyMm5vc2IiKSkKdXBzZXRfcGxvdHNfYm90aCRib3RoCmBgYAoKIyMjIyBDb21wYXJlIERFIHJlc3VsdHMgZnJvbSBtYWNyb3BoYWdlcyBhbmQgVTkzNyBzYW1wbGVzCgpMb29raW5nIGEgYml0IG1vcmUgY2xvc2VseSBhdCB0aGVzZSwgSSB0aGluayB0aGUgdTkzNyBkYXRhIGlzIHRvbwpzcGFyc2UgdG8gZWZmZWN0aXZlbHkgY29tcGFyZS4KCmBgYHtyfQptYWNyX3U5MzdfY29tcGFyaXNvbiA8LSBjb21wYXJlX2RlX3Jlc3VsdHMoaHNfbWFjcl90YWJsZSwgdTkzN190YWJsZSkKbWFjcl91OTM3X2NvbXBhcmlzb24kbGZjX2hlYXQKCm1hY3JfdTkzN192ZW5ucyA8LSBjb21wYXJlX3NpZ25pZmljYW50X2NvbnRyYXN0cyhoc19tYWNyX3NpZywgc2Vjb25kX3NpZ190YWJsZXMgPSB1OTM3X3NpZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyYXN0cyA9ICJ6MjNzYl92c196MjNub3NiIikKbWFjcl91OTM3X3Zlbm5zJHVwX3Bsb3QKbWFjcl91OTM3X3Zlbm5zJGRvd25fcGxvdAoKbWFjcl91OTM3X3Zlbm5zX3YyIDwtIGNvbXBhcmVfc2lnbmlmaWNhbnRfY29udHJhc3RzKGhzX21hY3Jfc2lnLCBzZWNvbmRfc2lnX3RhYmxlcyA9IHU5Mzdfc2lnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJhc3RzID0gInoyMnNiX3ZzX3oyMm5vc2IiKQptYWNyX3U5MzdfdmVubnNfdjIkdXBfcGxvdAptYWNyX3U5MzdfdmVubnNfdjIkZG93bl9wbG90CgptYWNyX3U5MzdfdmVubnNfdjMgPC0gY29tcGFyZV9zaWduaWZpY2FudF9jb250cmFzdHMoaHNfbWFjcl9zaWcsIHNlY29uZF9zaWdfdGFibGVzID0gdTkzN19zaWcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cmFzdHMgPSAic2JfdnNfdW5pbmYiKQptYWNyX3U5MzdfdmVubnNfdjMkdXBfcGxvdAptYWNyX3U5MzdfdmVubnNfdjMkZG93bl9wbG90CmBgYAoKIyMjIENvbXBhcmUgbWFjcm9waGFnZS91OTM3IHdpdGggcmVzcGVjdCB0byB6Mi4zL3oyLjIKCmBgYHtyfQpjb21wYXJpc29uX2RmIDwtIG1lcmdlKGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfejIyc2IiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgdTkzN190YWJsZVtbImRhdGEiXV1bWyJ6MjNzYl92c196MjJzYiJdXSwKICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJyb3cubmFtZXMiKQptYWNydTkzN196MjN6MjJfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGNvbXBhcmlzb25fZGZbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCm1hY3J1OTM3X3oyM3oyMl9wbG90JHNjYXR0ZXIKCmNvbXBhcmlzb25fZGYgPC0gbWVyZ2UoaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNub3NiX3ZzX3oyMm5vc2IiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgdTkzN190YWJsZVtbImRhdGEiXV1bWyJ6MjNub3NiX3ZzX3oyMm5vc2IiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAicm93Lm5hbWVzIikKbWFjcnU5MzdfejIzejIyX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihjb21wYXJpc29uX2RmWywgYygiZGVzZXFfbG9nZmMueCIsICJkZXNlcV9sb2dmYy55IildKQptYWNydTkzN196MjN6MjJfcGxvdCRzY2F0dGVyCmBgYAoKIyMjIyBBZGQgZG9ub3IgdG8gdGhlIGNvbnRyYXN0cywgbm8gc3ZhCgpgYGB7cn0Kbm9fcG93ZXJfZmFjdCA8LSBwYXN0ZTAocERhdGEoaHNfbWFjcilbWyJkb25vciJdXSwgIl8iLAogICAgICAgICAgICAgICAgICAgICAgICBwRGF0YShoc19tYWNyKVtbImNvbmRpdGlvbiJdXSkKdGFibGUocERhdGEoaHNfbWFjcilbWyJkb25vciJdXSkKdGFibGUobm9fcG93ZXJfZmFjdCkKaHNfbm9wb3dlciA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGhzX21hY3IsIGZhY3QgPSBub19wb3dlcl9mYWN0KQpoc19ub3Bvd2VyIDwtIHN1YnNldF9leHB0KGhzX25vcG93ZXIsIHN1YnNldD0ibWFjcm9waGFnZXp5bW9kZW1lIT0nbm9uZSciKQpoc19ub3Bvd2VyX25vc3ZhX2RlIDwtIGFsbF9wYWlyd2lzZShoc19ub3Bvd2VyLCBtb2RlbF9iYXRjaCA9IEZBTFNFLCBmaWx0ZXIgPSBUUlVFKQpub3Bvd2VyX2tlZXBlcnMgPC0gbGlzdCgKICAiZDAxX3p5bW8iID0gYygiZDAxaW5mejIzIiwgImQwMWluZnoyMiIpLAogICJkMDFfc2J6eW1vIiA9IGMoImQwMWluZnNiejIzIiwgImQwMWluZnNiejIyIiksCiAgImQwMl96eW1vIiA9IGMoImQwMmluZnoyMyIsICJkMDJpbmZ6MjIiKSwKICAiZDAyX3NienltbyIgPSBjKCJkMDJpbmZzYnoyMyIsICJkMDJpbmZzYnoyMiIpLAogICJkMDlfenltbyIgPSBjKCJkMDlpbmZ6MjMiLCAiZDA5aW5mejIyIiksCiAgImQwOV9zYnp5bW8iID0gYygiZDA5aW5mc2J6MjMiLCAiZDA5aW5mc2J6MjIiKSwKICAiZDgxX3p5bW8iID0gYygiZDgxaW5mejIzIiwgImQ4MWluZnoyMiIpLAogICJkODFfc2J6eW1vIiA9IGMoImQ4MWluZnNiejIzIiwgImQ4MWluZnNiejIyIikpCmhzX25vcG93ZXJfbm9zdmFfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgaHNfbm9wb3dlcl9ub3N2YV9kZSwga2VlcGVycyA9IG5vcG93ZXJfa2VlcGVycywKICBleGNlbCA9IGdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfZGUvaHNfbm9wb3dlcl90YWJsZS12e3Zlcn0ueGxzeCIpKQojIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHRyYV9jb250cmFzdHMgPSBleHRyYSkKaHNfbm9wb3dlcl9ub3N2YV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBoc19ub3Bvd2VyX25vc3ZhX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS9oc19ub3Bvd2VyX25vc3ZhX3NpZy12e3Zlcn0ueGxzeCIpKQoKZDAxZDAyX3p5bW9fbm9zdmFfY29tcCA8LSBtZXJnZShoc19ub3Bvd2VyX25vc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwMV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhzX25vcG93ZXJfbm9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDAyX3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnk9InJvdy5uYW1lcyIpCmQwMTAyX3p5bW9fbm9zdmFfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGQwMWQwMl96eW1vX25vc3ZhX2NvbXBbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCmQwMTAyX3p5bW9fbm9zdmFfcGxvdCRzY2F0dGVyCmQwMTAyX3p5bW9fbm9zdmFfcGxvdCRjb3JyZWxhdGlvbgpkMDEwMl96eW1vX25vc3ZhX3Bsb3QkbG1fcnNxCgpkMDlkODFfenltb19ub3N2YV9jb21wIDwtIG1lcmdlKGhzX25vcG93ZXJfbm9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDA5X3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHNfbm9wb3dlcl9ub3N2YV90YWJsZVtbImRhdGEiXV1bWyJkODFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieT0icm93Lm5hbWVzIikKZDA5ODFfenltb19ub3N2YV9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoZDA5ZDgxX3p5bW9fbm9zdmFfY29tcFssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKZDA5ODFfenltb19ub3N2YV9wbG90JHNjYXR0ZXIKZDA5ODFfenltb19ub3N2YV9wbG90JGNvcnJlbGF0aW9uCmQwOTgxX3p5bW9fbm9zdmFfcGxvdCRsbV9yc3EKCmQwMWQ4MV96eW1vX25vc3ZhX2NvbXAgPC0gbWVyZ2UoaHNfbm9wb3dlcl9ub3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoc19ub3Bvd2VyX25vc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQ4MV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5PSJyb3cubmFtZXMiKQpkMDE4MV96eW1vX25vc3ZhX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihkMDFkODFfenltb19ub3N2YV9jb21wWywgYygiZGVzZXFfbG9nZmMueCIsICJkZXNlcV9sb2dmYy55IildKQpkMDE4MV96eW1vX25vc3ZhX3Bsb3Qkc2NhdHRlcgpkMDE4MV96eW1vX25vc3ZhX3Bsb3QkY29ycmVsYXRpb24KZDAxODFfenltb19ub3N2YV9wbG90JGxtX3JzcQoKdXBzZXRfcGxvdHNfbm9zdmEgPC0gdXBzZXRyX3NpZyhoc19ub3Bvd2VyX25vc3ZhX3NpZywgYm90aD1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyYXN0cz1jKCJkMDFfenltbyIsICJkMDJfenltbyIsICJkMDlfenltbyIsICJkODFfenltbyIpKQp1cHNldF9wbG90c19ub3N2YSR1cAp1cHNldF9wbG90c19ub3N2YSRkb3duCnVwc2V0X3Bsb3RzX25vc3ZhJGJvdGgKIyMgVGhlIDd0aCBlbGVtZW50IGluIHRoZSBib3RoIGdyb3VwcyBsaXN0IGlzIHRoZSBzZXQgc2hhcmVkIGFtb25nIGFsbCBkb25vcnMuCiMjIEkgZG9uJ3QgZmVlbCBsaWtlIHdyaXRpbmcgb3V0IHg6eTp6OmEKZ3JvdXBzIDwtIHVwc2V0X3Bsb3RzX25vc3ZhW1siYm90aF9ncm91cHMiXV0Kc2hhcmVkX2dlbmVzIDwtIGF0dHIoZ3JvdXBzLCAiZWxlbWVudHMiKVtncm91cHNbWzddXV0gJT4lCiAgZ3N1YihwYXR0ZXJuID0gIl5nZW5lOiIsIHJlcGxhY2VtZW50ID0gIiIpCnNoYXJlZF9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNoYXJlZF9nZW5lcykKc2hhcmVkX2dwJHB2YWx1ZV9wbG90cyRNRgpzaGFyZWRfZ3AkcHZhbHVlX3Bsb3RzJEJQCnNoYXJlZF9ncCRwdmFsdWVfcGxvdHMkUkVBQwpzaGFyZWRfZ3AkcHZhbHVlX3Bsb3RzJFdQCmBgYAoKIyMjIyBBZGQgZG9ub3IgdG8gdGhlIGNvbnRyYXN0cywgc3ZhCgpgYGB7cn0KaHNfbm9wb3dlcl9zdmFfZGUgPC0gYWxsX3BhaXJ3aXNlKGhzX25vcG93ZXIsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpCm5vcG93ZXJfa2VlcGVycyA8LSBsaXN0KAogICJkMDFfenltbyIgPSBjKCJkMDFpbmZ6MjMiLCAiZDAxaW5mejIyIiksCiAgImQwMV9zYnp5bW8iID0gYygiZDAxaW5mc2J6MjMiLCAiZDAxaW5mc2J6MjIiKSwKICAiZDAyX3p5bW8iID0gYygiZDAyaW5mejIzIiwgImQwMmluZnoyMiIpLAogICJkMDJfc2J6eW1vIiA9IGMoImQwMmluZnNiejIzIiwgImQwMmluZnNiejIyIiksCiAgImQwOV96eW1vIiA9IGMoImQwOWluZnoyMyIsICJkMDlpbmZ6MjIiKSwKICAiZDA5X3NienltbyIgPSBjKCJkMDlpbmZzYnoyMyIsICJkMDlpbmZzYnoyMiIpLAogICJkODFfenltbyIgPSBjKCJkODFpbmZ6MjMiLCAiZDgxaW5mejIyIiksCiAgImQ4MV9zYnp5bW8iID0gYygiZDgxaW5mc2J6MjMiLCAiZDgxaW5mc2J6MjIiKSkKaHNfbm9wb3dlcl9zdmFfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgaHNfbm9wb3dlcl9zdmFfZGUsIGtlZXBlcnMgPSBub3Bvd2VyX2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJleGNlbC9tYWNyb3BoYWdlX2RlL2hzX25vcG93ZXJfdGFibGUtdnt2ZXJ9Lnhsc3giKSkKIyMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXh0cmFfY29udHJhc3RzID0gZXh0cmEpCmhzX25vcG93ZXJfc3ZhX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX25vcG93ZXJfc3ZhX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS9oc19ub3Bvd2VyX3N2YV9zaWctdnt2ZXJ9Lnhsc3giKSkKCmQwMWQwMl96eW1vX3N2YV9jb21wIDwtIG1lcmdlKGhzX25vcG93ZXJfc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwMV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoc19ub3Bvd2VyX3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDJfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnk9InJvdy5uYW1lcyIpCmQwMTAyX3p5bW9fc3ZhX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihkMDFkMDJfenltb19zdmFfY29tcFssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKZDAxMDJfenltb19zdmFfcGxvdCRzY2F0dGVyCmQwMTAyX3p5bW9fc3ZhX3Bsb3QkY29ycmVsYXRpb24KZDAxMDJfenltb19zdmFfcGxvdCRsbV9yc3EKCmQwOWQ4MV96eW1vX3N2YV9jb21wIDwtIG1lcmdlKGhzX25vcG93ZXJfc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwOV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoc19ub3Bvd2VyX3N2YV90YWJsZVtbImRhdGEiXV1bWyJkODFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnk9InJvdy5uYW1lcyIpCmQwOTgxX3p5bW9fc3ZhX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihkMDlkODFfenltb19zdmFfY29tcFssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKZDA5ODFfenltb19zdmFfcGxvdCRzY2F0dGVyCmQwOTgxX3p5bW9fc3ZhX3Bsb3QkY29ycmVsYXRpb24KZDA5ODFfenltb19zdmFfcGxvdCRsbV9yc3EKCmQwMWQ4MV96eW1vX3N2YV9jb21wIDwtIG1lcmdlKGhzX25vcG93ZXJfc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwMV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoc19ub3Bvd2VyX3N2YV90YWJsZVtbImRhdGEiXV1bWyJkODFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnk9InJvdy5uYW1lcyIpCmQwMTgxX3p5bW9fc3ZhX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihkMDFkODFfenltb19zdmFfY29tcFssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKZDAxODFfenltb19zdmFfcGxvdCRzY2F0dGVyCmQwMTgxX3p5bW9fc3ZhX3Bsb3QkY29ycmVsYXRpb24KZDAxODFfenltb19zdmFfcGxvdCRsbV9yc3EKCnVwc2V0X3Bsb3RzX3N2YSA8LSB1cHNldHJfc2lnKGhzX25vcG93ZXJfc3ZhX3NpZywgYm90aD1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cmFzdHM9YygiZDAxX3p5bW8iLCAiZDAyX3p5bW8iLCAiZDA5X3p5bW8iLCAiZDgxX3p5bW8iKSkKdXBzZXRfcGxvdHNfc3ZhJHVwCnVwc2V0X3Bsb3RzX3N2YSRkb3duCnVwc2V0X3Bsb3RzX3N2YSRib3RoCiMjIFRoZSA3dGggZWxlbWVudCBpbiB0aGUgYm90aCBncm91cHMgbGlzdCBpcyB0aGUgc2V0IHNoYXJlZCBhbW9uZyBhbGwgZG9ub3JzLgojIyBJIGRvbid0IGZlZWwgbGlrZSB3cml0aW5nIG91dCB4Onk6ejphCmdyb3VwcyA8LSB1cHNldF9wbG90c19zdmFbWyJib3RoX2dyb3VwcyJdXQpzaGFyZWRfZ2VuZXMgPC0gYXR0cihncm91cHMsICJlbGVtZW50cyIpW2dyb3Vwc1tbN11dXSAlPiUKICBnc3ViKHBhdHRlcm4gPSAiXmdlbmU6IiwgcmVwbGFjZW1lbnQgPSAiIikKc2hhcmVkX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoc2hhcmVkX2dlbmVzKQpzaGFyZWRfZ3AkcHZhbHVlX3Bsb3RzJE1GCnNoYXJlZF9ncCRwdmFsdWVfcGxvdHMkQlAKc2hhcmVkX2dwJHB2YWx1ZV9wbG90cyRSRUFDCnNoYXJlZF9ncCRwdmFsdWVfcGxvdHMkV1AKYGBgCgojIyMgRG9ub3IgY29tcGFyaXNvbgoKYGBge3J9CmhzX2Rvbm9ycyA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGhzX21hY3IsIGZhY3QgPSAiZG9ub3IiKQpkb25vcl9kZSA8LSBhbGxfcGFpcndpc2UoaHNfZG9ub3JzLCBtb2RlbF9iYXRjaD0ic3Zhc2VxIiwgZmlsdGVyPVRSVUUpCmRvbm9yX2RlCmRvbm9yX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGRvbm9yX2RlLAogIGV4Y2VsPWdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfZGUvZG9ub3JfdGFibGVzLXZ7dmVyfS54bHN4IikpCmRvbm9yX3RhYmxlCmRvbm9yX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGRvbm9yX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS9kb25vcl9zaWctdnt2ZXJ9Lnhsc3giKSkKZG9ub3Jfc2lnCmBgYAoKIyMjIyBQcmltYXJ5IHF1ZXJ5IGNvbnRyYXN0cwoKVGhlIGZpbmFsIGNvbnRyYXN0IGluIHRoaXMgbGlzdCBpcyBpbnRlcmVzdGluZyBiZWNhdXNlIGl0IGRlcGVuZHMgb24KdGhlIGV4dHJhIGNvbnRyYXN0cyBhcHBsaWVkIHRvIHRoZSBhbGxfcGFpcndpc2UoKSBhYm92ZS4gIEluIG15IHdheSBvZgp0aGlua2luZywgdGhlIHByaW1hcnkgY29tcGFyaXNvbnMgdG8gY29uc2lkZXIgYXJlIGVpdGhlciBjcm9zcy1kcnVnIG9yCmNyb3NzLXN0cmFpbiwgYnV0IG5vdCBib3RoLiAgSG93ZXZlciBJIHRoaW5rIGluIGF0IGxlYXN0IGEgZmV3Cmluc3RhbmNlcyBPbGdhIGlzIGludGVyZXN0ZWQgaW4gc3RyYWluK2RydWcgLyB1bmluZmVjdGVkK25vZHJ1Zy4KCiMjIyMgV3JpdGUgY29udHJhc3QgcmVzdWx0cwoKTm93IGxldCB1cyB3cml0ZSBvdXQgdGhlIHhsc3ggZmlsZSBjb250YWluaW5nIHRoZSBhYm92ZSBjb250cmFzdHMuClRoZSBmaWxlIHdpdGggdGhlIHN1ZmZpeCBfdGFibGUtdmVyc2lvbiB3aWxsIHRoZXJlZm9yZSBjb250YWluIGFsbApnZW5lcyBhbmQgdGhlIGZpbGUgd2l0aCB0aGUgc3VmZml4IF9zaWctdmVyc2lvbiB3aWxsIGNvbnRhaW4gb25seQp0aG9zZSBkZWVtZWQgc2lnbmlmaWNhbnQgdmlhIG91ciBkZWZhdWx0IGNyaXRlcmlhIG9mIERFU2VxMiB8bG9nRkN8ID49IDEuMAphbmQgYWRqdXN0ZWQgcC12YWx1ZSA8PSAwLjA1LgoKIyBPdmVyIHJlcHJlc2VudGF0aW9uIHNlYXJjaGVzCgpJIGRlY2lkZWQgdG8gbWFrZSBvbmUgaW5pdGlhbGx5IHNtYWxsLCBidXQgSSB0aGluayBxdWlja2x5IGJpZyBjaGFuZ2UKdG8gdGhlIG9yZ2FuaXphdGlvbiBvZiB0aGlzIGRvY3VtZW50OiAgSSBhbSBtb3ZpbmcgdGhlIEdTRUEgc2VhcmNoZXMKdXAgdG8gaW1tZWRpYXRlbHkgYWZ0ZXIgdGhlIERFLiAgSSB3aWxsIHRoZW4gbW92ZSB0aGUgcGxvdHMgb2YgdGhlCmdwcm9maWxlciByZXN1bHRzIHRvIGltbWVkaWF0ZWx5IGFmdGVyIHRoZSB2YXJpb3VzIHZvbGNhbm8gcGxvdHMgc28KdGhhdCBpdCBpcyBlYXNpZXIgdG8gaW50ZXJwcmV0IHRoZW0uCgpgYGB7cn0KYWxsX2dwIDwtIGFsbF9ncHJvZmlsZXIoaHNfbWFjcl9zaWcpCmZvciAoZyBpbiBzZXFfbGVuKGxlbmd0aChhbGxfZ3ApKSkgewogIG5hbWUgPC0gbmFtZXMoYWxsX2dwKVtnXQogIGRhdHVtIDwtIGFsbF9ncFtbbmFtZV1dCiAgZmlsZW5hbWUgPC0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS9ncHJvZmlsZXIve25hbWV9X2dwcm9maWxlci12e3Zlcn0ueGxzeCIpCiAgd3JpdHRlbiA8LSBzbSh3cml0ZV9ncHJvZmlsZXJfZGF0YShkYXR1bSwgZXhjZWwgPSBmaWxlbmFtZSkpCn0KYGBgCgojIFBsb3QgY29udHJhc3RzIG9mIGludGVyZXN0CgpPbmUgc3VnZ2VzdGlvbiBJIHJlY2VpdmVkIHJlY2VudGx5IHdhcyB0byBzZXQgdGhlIGF4ZXMgZm9yIHRoZXNlCnZvbGNhbm8gcGxvdHMgdG8gYmUgc3RhdGljIHJhdGhlciB0aGFuIGxldCBnZ3Bsb3QgY2hvb3NlIGl0cyBvd24uICBJCmFtIGFzc3VtaW5nIHRoaXMgaXMgb25seSByZWxldmFudCBmb3IgcGFpcnMgb2YgY29udHJhc3RzLCBidXQgdGhhdAptaWdodCBub3QgYmUgdHJ1ZS4KCiMjIEluZGl2aWR1YWwgenltb2RlbWVzIHZzLiB1bmluZmVjdGVkCgojIyMgSW5mZWN0ZWQgd2l0aCB6Mi4zIG5vIEFudGltb25pYWwgdnMuIFVuaW5mZWN0ZWQKCmBgYHtyfQpwbG90X2NvbG9ycyA8LSBnZXRfZXhwdF9jb2xvcnMoaHNfbWFjcl90YWJsZVtbImlucHV0Il1dW1siaW5wdXQiXV0pCnhfbGltaXRzIDwtIGMoLTIwLCAxMCkKCiMjIFRoZSBvcmlnaW5hbCBwbG90IGZyb20gbXkgeGxzeCBmaWxlCmhzX21hY3JfdGFibGUkcGxvdHMkejIzbm9zYl92c191bmluZiRkZXNlcV92b2xfcGxvdHMKCnoyM25vc2JfdnNfdW5pbmZfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGlucHV0ID0gaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNub3NiX3ZzX3VuaW5mIl1dLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jc3ltYm9sIiwgaW52ZXJ0ID0gVFJVRSwKICBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJ1bmluZm5vbmUiXV0sIGNvbG9yX2xvdyA9IHBsb3RfY29sb3JzW1siaW5mejIzIl1dKQp6MjNub3NiX3ZzX3VuaW5mX3ZvbGNhbm8kcGxvdCArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IHhfbGltaXRzKQpwbG90bHk6OmdncGxvdGx5KHoyM25vc2JfdnNfdW5pbmZfdm9sY2FubyRwbG90KQoKejIzbm9zYl92c191bmluZl92b2xjYW5vX25vbCA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGlucHV0ID0gaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNub3NiX3ZzX3VuaW5mIl1dLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIGxhYmVsID0gTlVMTCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiLCBpbnZlcnQgPSBUUlVFLAogIGNvbG9yX2hpZ2ggPSBwbG90X2NvbG9yc1tbInVuaW5mbm9uZSJdXSwgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJpbmZ6MjMiXV0pCnoyM25vc2JfdnNfdW5pbmZfdm9sY2Fub19ub2wkcGxvdCArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IHhfbGltaXRzKQoKYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siS0VHRyJdXQojIyBLRUdHLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIldQIl1dCiMjIFdpa2lQYXRod2F5cywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfdXAiXV1bWyJpbnRlcmFjdGl2ZV9wbG90cyJdXVtbIldQIl1dCgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmBgYAoKIyMjIEluZmVjdGVkIHdpdGggejIuMiBubyBBbnRpbW9uaWFsIHZzLiBVbmluZmVjdGVkCgpgYGB7cn0KIyMgVGhlIG9yaWdpbmFsIHBsb3QKaHNfbWFjcl90YWJsZSRwbG90cyR6MjJub3NiX3ZzX3VuaW5mJGRlc2VxX3ZvbF9wbG90cwoKejIybm9zYl92c191bmluZl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjJub3NiX3ZzX3VuaW5mIl1dLCAiejIybm9zYl92c191bmluZiIsCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiLCBpbnZlcnQgPSBUUlVFLAogIGNvbG9yX2hpZ2ggPSBwbG90X2NvbG9yc1tbInVuaW5mbm9uZSJdXSwgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJpbmZ6MjIiXV0pCnoyMm5vc2JfdnNfdW5pbmZfdm9sY2FubyRwbG90ICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0geF9saW1pdHMpCnBsb3RseTo6Z2dwbG90bHkoejIybm9zYl92c191bmluZl92b2xjYW5vJHBsb3QpCgp6MjJub3NiX3ZzX3VuaW5mX3ZvbGNhbm9fbm9sIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjJub3NiX3ZzX3VuaW5mIl1dLCAiejIybm9zYl92c191bmluZiIsCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSBOVUxMLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIsIGludmVydCA9IFRSVUUsCiAgY29sb3JfaGlnaCA9IHBsb3RfY29sb3JzW1sidW5pbmZub25lIl1dLCBjb2xvcl9sb3cgPSBwbG90X2NvbG9yc1tbImluZnoyMiJdXSkKejIybm9zYl92c191bmluZl92b2xjYW5vX25vbCRwbG90ICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0geF9saW1pdHMpCgphbGxfZ3BbWyJ6MjJub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjIgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMm5vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjIgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMm5vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjIgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMm5vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJXUCJdXQojIyBXaWtpUGF0aHdheXMsIHp5bW9kZW1lMi4yIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgoKYWxsX2dwW1siejIybm9zYl92c191bmluZl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjIgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIybm9zYl92c191bmluZl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4yIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyMm5vc2JfdnNfdW5pbmZfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgpgYGAKCiMjIyBJbmZlY3RlZCB3aXRoIHoyLjMgdHJlYXRlZCB2cy4gVW5pbmZlY3RlZCB0cmVhdGVkCgpgYGB7cn0KIyMgVGhlIG9yaWdpbmFsIHBsb3QKaHNfbWFjcl90YWJsZSRwbG90cyR6MjNzYl92c19zYiRkZXNlcV92b2xfcGxvdHMKCnoyM3NiX3ZzX3VuaW5mc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfc2IiXV0sICJ6MjNzYl92c19zYiIsCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiLCBpbnZlcnQgPSBUUlVFLAogIGNvbG9yX2hpZ2ggPSBwbG90X2NvbG9yc1tbImluZnNiejIzIl1dLCBjb2xvcl9sb3cgPSBwbG90X2NvbG9yc1tbInVuaW5mc2Jub25lIl1dKQp6MjNzYl92c191bmluZnNiX3ZvbGNhbm8kcGxvdCArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IHhfbGltaXRzKQpwbG90bHk6OmdncGxvdGx5KHoyM3NiX3ZzX3VuaW5mc2Jfdm9sY2FubyRwbG90KQoKejIzc2JfdnNfdW5pbmZzYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNzYl92c19zYiJdXSwgInoyM3NiX3ZzX3NiIiwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBsYWJlbCA9IE5VTEwsIGxhYmVsX2NvbHVtbiA9ICJoZ25jc3ltYm9sIiwgaW52ZXJ0ID0gVFJVRSwKICBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJpbmZzYnoyMyJdXSwgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJ1bmluZnNibm9uZSJdXSkKejIzc2JfdnNfdW5pbmZzYl92b2xjYW5vJHBsb3QgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSB4X2xpbWl0cykKYGBgCgojIyMgSW5mZWN0ZWQgd2l0aCB6Mi4zIHVudHJlYXRlZCB2cy4gejIuMiB1bnRyZWF0ZWQKCmBgYHtyfQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlJHBsb3RzJHoyM25vc2JfdnNfejIybm9zYiRkZXNlcV92b2xfcGxvdHMKCnoyM25vc2JfdnNfejIybm9zYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNub3NiX3ZzX3oyMm5vc2IiXV0sICJ6MjNub3NiX3ZzX3oyMm5vc2IiLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jc3ltYm9sIiwgaW52ZXJ0ID0gVFJVRSwKICBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJpbmZ6MjMiXV0sIGNvbG9yX2xvdyA9IHBsb3RfY29sb3JzW1siaW5mejIyIl1dKQp6MjNub3NiX3ZzX3oyMm5vc2Jfdm9sY2FubyRwbG90ICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0geF9saW1pdHMpCmBgYAoKIyMjIEluZmVjdGVkIHdpdGggejIuMyB0cmVhdGVkIHZzLiB6Mi4yIHRyZWF0ZWQKCmBgYHtyfQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlJHBsb3RzJHoyM3NiX3ZzX3oyMnNiJGRlc2VxX3ZvbF9wbG90cwoKejIzc2JfdnNfejIyc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfejIyc2IiXV0sICJ6MjNzYl92c196MjJzYiIsCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiLCBpbnZlcnQgPSBGQUxTRSwKICBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJpbmZzYnoyMyJdXSwgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJpbmZzYnoyMiJdXSkKejIzc2JfdnNfejIyc2Jfdm9sY2FubyRwbG90ICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0geF9saW1pdHMpCmBgYAoKIyMjIEluZmVjdGVkIHdpdGggejIuMyBTQiB0cmVhdGVkIHZzLiB6Mi4zIHVudHJlYXRlZAoKYGBge3J9CiMjIFRoZSBvcmlnaW5hbCBwbG90CmhzX21hY3JfdGFibGUkcGxvdHMkejIzc2JfdnNfejIzbm9zYiRkZXNlcV92b2xfcGxvdHMKCnoyM3NiX3ZzX3oyM25vc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfejIzbm9zYiJdXSwgInoyM3NiX3ZzX3oyM25vc2IiLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jc3ltYm9sIiwgaW52ZXJ0ID0gVFJVRSwKICBjb2xvcl9sb3cgPSBwbG90X2NvbG9yc1tbImluZnNiejIzIl1dLCBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJpbmZ6MjMiXV0pCnoyM3NiX3ZzX3oyM25vc2Jfdm9sY2FubyRwbG90ICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0geF9saW1pdHMpCmBgYAoKIyMjIEluZmVjdGVkIHdpdGggejIuMyBTQiB0cmVhdGVkIHZzLiB6Mi4zIHVudHJlYXRlZAoKYGBge3J9CiMjIFRoZSBvcmlnaW5hbCBwbG90CmhzX21hY3JfdGFibGUkcGxvdHMkejIyc2JfdnNfejIybm9zYiRkZXNlcV92b2xfcGxvdHMKCnoyMnNiX3ZzX3oyMm5vc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIyc2JfdnNfejIybm9zYiJdXSwgInoyMnNiX3ZzX3oyMm5vc2IiLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jc3ltYm9sIiwgaW52ZXJ0ID0gVFJVRSwKICBjb2xvcl9sb3cgPSBwbG90X2NvbG9yc1tbImluZnNiejIyIl1dLCBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJpbmZ6MjIiXV0pCnoyMnNiX3ZzX3oyMm5vc2Jfdm9sY2FubyRwbG90ICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0geF9saW1pdHMpCmBgYAoKIyMjIEluZmVjdGVkIHdpdGggejIuMyBTQiB0cmVhdGVkIHZzLiB1bmluZmVjdGVkIHRyZWF0ZWQKCmBgYHtyfQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlJHBsb3RzJHoyM3NiX3ZzX3NiJGRlc2VxX3ZvbF9wbG90cwoKejIzc2JfdnNfc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfc2IiXV0sICJ6MjNzYl92c19zYiIsCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiLCBpbnZlcnQgPSBUUlVFLAogIGNvbG9yX2xvdyA9IHBsb3RfY29sb3JzW1siaW5mc2J6MjMiXV0sIGNvbG9yX2hpZ2ggPSBwbG90X2NvbG9yc1tbInVuaW5mc2Jub25lIl1dKQp6MjNzYl92c19zYl92b2xjYW5vJHBsb3QgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSB4X2xpbWl0cykKYGBgCgojIyMgSW5mZWN0ZWQgd2l0aCB6Mi4yIFNCIHRyZWF0ZWQgdnMuIHVuaW5mZWN0ZWQgdHJlYXRlZAoKYGBge3J9CiMjIFRoZSBvcmlnaW5hbCBwbG90CmhzX21hY3JfdGFibGUkcGxvdHMkejIyc2JfdnNfc2IkZGVzZXFfdm9sX3Bsb3RzCgp6MjJzYl92c19zYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjJzYl92c19zYiJdXSwgInoyMnNiX3ZzX3NiIiwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIsIGludmVydCA9IFRSVUUsCiAgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJpbmZzYnoyMiJdXSwgY29sb3JfaGlnaCA9IHBsb3RfY29sb3JzW1sidW5pbmZzYm5vbmUiXV0pCnoyMnNiX3ZzX3NiX3ZvbGNhbm8kcGxvdCArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IHhfbGltaXRzKQpgYGAKCkNoZWNrIHRoYXQgbXkgcGVyY2VwdGlvbiBvZiB0aGUgbnVtYmVyIG9mIHNpZ25pZmljYW50IHVwL2Rvd24gZ2VuZXMKbWF0Y2hlcyB3aGF0IHRoZSB0YWJsZS92ZW5uIHNheXMuCgpgYGB7cn0Kc2hhcmVkIDwtIFZlbm5lcmFibGU6OlZlbm4obGlzdCgiZHJ1ZyIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIzc2JfdnNfdW5pbmYiXV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJub2RydWciID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM25vc2JfdnNfdW5pbmYiXV0pKSkKcHAoZmlsZT0iaW1hZ2VzL3oyM192c191bmluZl92ZW5uX3VwLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCiMjIEkgc2VlIDkxMCB6MjNzYi91bmluZiBhbmQgNjcwIG5vIHoyM25vc2IvdW5pbmYgZ2VuZXMgaW4gdGhlIHZlbm4gZGlhZ3JhbS4KbGVuZ3RoKHNoYXJlZEBJbnRlcnNlY3Rpb25TZXRzW1siMTAiXV0pICsgbGVuZ3RoKHNoYXJlZEBJbnRlcnNlY3Rpb25TZXRzW1siMTEiXV0pCmRpbShoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIzc2JfdnNfdW5pbmYiXV0pCgpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KCJkcnVnIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjJzYl92c191bmluZiJdXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5vZHJ1ZyIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIybm9zYl92c191bmluZiJdXSkpKQpwcChmaWxlPSJpbWFnZXMvejIyX3ZzX3VuaW5mX3Zlbm5fdXAucG5nIikKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmRldi5vZmYoKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKCmxlbmd0aChzaGFyZWRASW50ZXJzZWN0aW9uU2V0c1tbIjEwIl1dKSArIGxlbmd0aChzaGFyZWRASW50ZXJzZWN0aW9uU2V0c1tbIjExIl1dKQpkaW0oaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyMnNiX3ZzX3VuaW5mIl1dKQpgYGAKCipOb3RlIHRvIHNlbGYqOiBUaGVyZSBpcyBhbiBlcnJvciBpbiBteSB2b2xjYW5vIHBsb3QgY29kZSB3aGljaCB0YWtlcwplZmZlY3Qgd2hlbiB0aGUgbnVtZXJhdG9yIGFuZCBkZW5vbWluYXRvciBvZiB0aGUgYWxsX3BhaXJ3aXNlCmNvbnRyYXN0cyBhcmUgZGlmZmVyZW50IHRoYW4gdGhvc2UgaW4gY29tYmluZV9kZV90YWJsZXMuICBJdCBpcwpwdXR0aW5nIHRoZSB1cHMvZG93bnMgb24gdGhlIGNvcnJlY3Qgc2lkZXMgb2YgdGhlIHBsb3QsIGJ1dCBjYWxsaW5nCnRoZSBkb3duIGdlbmVzICd1cCcgYW5kIHZpY2UtdmVyc2EuICBUaGUgcmVhc29uIGZvciB0aGlzIGlzIHRoYXQgSSBkaWQKYSBjaGVjayBmb3IgdGhpcyBoYXBwZW5pbmcsIGJ1dCB1c2VkIHRoZSB3cm9uZyBhcmd1bWVudCB0byBoYW5kbGUgaXQuCgpBIGxpa2VseSBiaXQgb2YgdGV4dCBmb3IgdGhlc2Ugdm9sY2FubyBwbG90czoKClRoZSBzZXQgb2YgZ2VuZXMgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGJldHdlZW4gdGhlIHp5bW9kZW1lIDIuMwphbmQgdW5pbmZlY3RlZCBzYW1wbGVzIHdpdGhvdXQgZHJ1Z2UgdHJlYXRtZW50IHdhcyBxdWFudGlmaWVkIHdpdGgKREVTZXEyIGFuZCBpbmNsdWRlZCBzdXJyb2dhdGUgZXN0aW1hdGVzIGZyb20gU1ZBLiAgR2l2ZW4gdGhlIGNyaXRlcmlhCm9mIHNpZ25pZmljYW5jZSBvZiBhIGFicyhsb2dGQykgPj0gMS4wIGFuZCBmYWxzZSBkaXNjb3ZlcnkgcmF0ZQphZGp1c3RlZCBwLXZhbHVlIDw9IDAuMDUsIDY3MCBnZW5lcyB3ZXJlIG9ic2VydmVkIGFzIHNpZ25pZmljYW50bHkKaW5jcmVhc2VkIGJldHdlZW4gdGhlIGluZmVjdGVkIGFuZCB1bmluZmVjdGVkIHNhbXBsZXMgYW5kIDM4NiB3ZXJlCm9ic2VydmVkIGFzIGRlY3JlYXNlZC4gVGhlIG1vc3QgaW5jcmVhc2VkIGdlbmVzIGZyb20gdGhlIHVuaW5mZWN0ZWQKc2FtcGxlcyBpbmNsdWRlIHNvbWUgd2hpY2ggYXJlIHBvdGVudGlhbGx5IGluZGljYXRpdmUgb2YgYSBzdHJvbmcKaW5uYXRlIGltbXVuZSByZXNwb25zZSBhbmQgdGhlIGluZmxhbW1hdG9yeSByZXNwb25zZS4KCkluIGNvbnRyYXN0LCB3aGVuIHRoZSBzZXQgb2YgZ2VuZXMgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGJldHdlZW4KdGhlIHp5bW9kZW1lIDIuMiBhbmQgdW5pbmZlY3RlZCBzYW1wbGVzIHdhcyB2aXN1YWxpemVkLCBvbmx5IDcgZ2VuZXMKd2VyZSBvYnNlcnZlZCBhcyBkZWNyZWFzZWQgYW5kIDQzNSBpbmNyZWFzZWQuICBUaGUgaW5mbGFtbWF0b3J5CnJlc3BvbnNlIHdhcyBzaWduaWZpY2FudGx5IGxlc3MgYXBwYXJlbnQgaW4gdGhpcyBzZXQsIGJ1dCBpbnN0ZWFkCmluY2x1ZGVkIGdlbmVzIHJlbGF0ZWQgdG8gdHJhbnNwb3J0ZXIgYWN0aXZpdHkgYW5kIG94aWRvcmVkdWN0YXNlcy4KCiMjIERpcmVjdCB6eW1vZGVtZSBjb21wYXJpc29ucwoKQW4gb3J0aG9nb25hbCBjb21wYXJpc29uIHRvIHRoYXQgcGVyZm9ybWVkIGFib3ZlIGlzIHRvIGRpcmVjdGx5CmNvbXBhcmUgdGhlIHp5bW9kZW1lIDIuMyBhbmQgMi4yIHNhbXBsZXMgd2l0aCBhbmQgd2l0aG91dCBhbnRpbW9uaWFsCnRyZWF0bWVudC4KCmBgYHtyfQp6MjNub3NiX3ZzX3oyMm5vc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fZGUoCiAgdGFibGUgPSBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXSwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBzaGFwZXNfYnlfc3RhdGUgPSBGQUxTRSwgY29sb3JfYnkgPSAiZmMiLCAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiKQpwbG90bHk6OmdncGxvdGx5KHoyM25vc2JfdnNfejIybm9zYl92b2xjYW5vJHBsb3QpCgp6MjNzYl92c196MjJzYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19kZSgKICB0YWJsZSA9IGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfejIyc2IiXV0sCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgc2hhcGVzX2J5X3N0YXRlID0gRkFMU0UsIGNvbG9yX2J5ID0gImZjIiwgIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jc3ltYm9sIikKcGxvdGx5OjpnZ3Bsb3RseSh6MjNzYl92c196MjJzYl92b2xjYW5vJHBsb3QpCmBgYAoKYGBge3J9CnoyM25vc2JfdnNfejIybm9zYl92b2xjYW5vJHBsb3QgKwogIHhsaW0oLTEwLCAxMCkgKwogIHlsaW0oMCwgNjApCgpwcChmaWxlPSJpbWFnZXMvejIzbm9zYl92c196MjJub3NiX3JlYWN0b21lX3VwLnBuZyIsIGltYWdlPWFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0sIGhlaWdodD0xMiwgd2lkdGg9OSkKIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJLRUdHIl1dCiMjIEtFR0csIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KIyMgV2lraVBhdGh3YXlzLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX3VwIl1dW1siaW50ZXJhY3RpdmVfcGxvdHMiXV1bWyJXUCJdXQoKYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgpgYGAKCmBgYHtyfQp6MjNzYl92c196MjJzYl92b2xjYW5vJHBsb3QgKwogIHhsaW0oLTEwLCAxMCkgKwogIHlsaW0oMCwgNjApCgpwcChmaWxlPSJpbWFnZXMvejIzc2JfdnNfejIyc2JfcmVhY3RvbWVfdXAucG5nIiwgaW1hZ2U9YWxsX2dwW1siejIzc2JfdnNfejIyc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dLCBoZWlnaHQ9MTIsIHdpZHRoPTkpCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIyc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJLRUdHIl1dCiMjIEtFR0csIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIyc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KIyMgV2lraVBhdGh3YXlzLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIyc2JfdXAiXV1bWyJpbnRlcmFjdGl2ZV9wbG90cyJdXVtbIldQIl1dCgphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzc2JfdnNfejIyc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmBgYAoKCmBgYHtyfQpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KCJkcnVnIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjNzYl92c196MjJzYiJdXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5vZHJ1ZyIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dKSkpCnBwKGZpbGU9ImltYWdlcy9kcnVnX25vZHJ1Z192ZW5uX3VwLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCgpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KCJkcnVnIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyM3NiX3ZzX3oyMnNiIl1dKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibm9kcnVnIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXSkpKQpwcChmaWxlPSJpbWFnZXMvZHJ1Z19ub2RydWdfdmVubl9kb3duLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKYGBgCgpBIHNsaWdodGx5IGRpZmZlcmVudCB3YXkgb2YgbG9va2luZyBhdCB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgdHdvCnp5bW9kZW1lIGluZmVjdGlvbnMgaXMgdG8gZGlyZWN0bHkgY29tcGFyZSB0aGUgaW5mZWN0ZWQgc2FtcGxlcyB3aXRoCmFuZCB3aXRob3V0IGRydWcuICBUaHVzLCB3aGVuIGEgdm9sY2FubyBwbG90IHNob3dpbmcgdGhlIGNvbXBhcmlzb24gb2YKdGhlIHp5bW9kZW1lIDIuMyB2cy4gMi4yIHNhbXBsZXMgd2FzIHBsb3R0ZWQsIDQ4NCBnZW5lcyB3ZXJlIG9ic2VydmVkCmFzIGluY3JlYXNlZCBhbmQgNDIyIGRlY3JlYXNlZDsgdGhlc2UgZ3JvdXBzIGluY2x1ZGUgbWFueSBvZiB0aGUgc2FtZQppbmZsYW1tYXRvcnkgKHVwKSBhbmQgbWVtYnJhbmUgKGRvd24pIGdlbmVzLgoKU2ltaWxhciBwYXR0ZXJucyB3ZXJlIG9ic2VydmVkIHdoZW4gdGhlIGFudGltb25pYWwgd2FzIGluY2x1ZGVkLgpUaHVzLCB3aGVuIGEgVmVubiBkaWFncmFtIG9mIHRoZSB0d28gc2V0cyBvZiBpbmNyZWFzZWQgZ2VuZXMgd2FzCnBsb3R0ZWQsIGEgc2lnbmlmaWNhbnQgbnVtYmVyIG9mIHRoZSBnZW5lcyB3YXMgb2JzZXJ2ZWQgYXMgaW5jcmVhc2VkCigzMTMpIGFuZCBkZWNyZWFzZWQgKDI0NCkgaW4gYm90aCB0aGUgdW50cmVhdGVkIGFuZCBhbnRpbW9uaWFsIHRyZWF0ZWQKc2FtcGxlcy4KCiMjIERydWcgZWZmZWN0cyBvbiBlYWNoIHp5bW9kZW1lIGluZmVjdGlvbgoKQW5vdGhlciBsaWtlbHkgcXVlc3Rpb24gaXMgdG8gZGlyZWN0bHkgY29tcGFyZSB0aGUgdHJlYXRlZCB2cwp1bnRyZWF0ZWQgc2FtcGxlcyBmb3IgZWFjaCB6eW1vZGVtZSBpbmZlY3Rpb24gaW4gb3JkZXIgdG8gdmlzdWFsaXplCnRoZSBlZmZlY3RzIG9mIGFudGltb25pYWwuCgpgYGB7cn0KejIzc2JfdnNfejIzbm9zYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19kZSgKICB0YWJsZSA9IGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfejIzbm9zYiJdXSwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBzaGFwZXNfYnlfc3RhdGUgPSBGQUxTRSwgY29sb3JfYnkgPSAiZmMiLCAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiKQpwbG90bHk6OmdncGxvdGx5KHoyM3NiX3ZzX3oyM25vc2Jfdm9sY2FubyRwbG90KQp6MjJzYl92c196MjJub3NiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2RlKAogIHRhYmxlID0gaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjJzYl92c196MjJub3NiIl1dLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIpCnBsb3RseTo6Z2dwbG90bHkoejIyc2JfdnNfejIybm9zYl92b2xjYW5vJHBsb3QpCmBgYAoKYGBge3J9CnoyM3NiX3ZzX3oyM25vc2Jfdm9sY2FubyRwbG90ICsKICB4bGltKC04LCA4KSArCiAgeWxpbSgwLCAyMTApCgpwcChmaWxlPSJpbWFnZXMvejIzc2JfdnNfejIzbm9zYl9yZWFjdG9tZV91cC5wbmciLAogICBpbWFnZT1hbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXSwgaGVpZ2h0PTEyLCB3aWR0aD05KQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyM25vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJLRUdHIl1dCiMjIEtFR0csIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KIyMgV2lraVBhdGh3YXlzLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbImludGVyYWN0aXZlX3Bsb3RzIl1dW1siV1AiXV0KCmFsbF9ncFtbInoyM3NiX3ZzX3oyM25vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyM3NiX3ZzX3oyM25vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYGBgCgpgYGB7cn0KejIyc2JfdnNfejIybm9zYl92b2xjYW5vJHBsb3QgKwogIHhsaW0oLTgsIDgpICsKICB5bGltKDAsIDIxMCkKCnBwKGZpbGU9ImltYWdlcy96MjJzYl92c196MjJub3NiX3JlYWN0b21lX3VwLnBuZyIsCiAgIGltYWdlPWFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dLCBoZWlnaHQ9MTIsIHdpZHRoPTkpCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIktFR0ciXV0KIyMgS0VHRywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJXUCJdXQojIyBXaWtpUGF0aHdheXMsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1siaW50ZXJhY3RpdmVfcGxvdHMiXV1bWyJXUCJdXQoKYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgpgYGAKCmBgYHtyfQpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KCJ6MjMiID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM3NiX3ZzX3oyM25vc2IiXV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ6MjIiID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyMnNiX3ZzX3oyMm5vc2IiXV0pKSkKcHAoZmlsZT0iaW1hZ2VzL3oyM196MjJfZHJ1Z192ZW5uX3VwLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCgpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KCJ6MjMiID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1siejIzc2JfdnNfejIzbm9zYiJdXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInoyMiIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJ6MjJzYl92c196MjJub3NiIl1dKSkpCnBwKGZpbGU9ImltYWdlcy96MjNfejIyX2RydWdfdmVubl9kb3duLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmBgYAoKTm90ZTogSSBhbSBzZXR0aWcgdGhlIHggYW5kIHktYXhpcyBib3VuZGFyaWVzIGJ5IGFsbG93aW5nIHRoZSBwbG90dGVyCnRvIHBpY2sgaXRzIG93biBheGlzIHRoZSBmaXJzdCB0aW1lLCB3cml0aW5nIGRvd24gdGhlIHJhbmdlcyBJCm9ic2VydmUsIGFuZCB0aGVuIHNldHRpbmcgdGhlbSB0byB0aGUgbGFyZ2VzdCBvZiB0aGUgcGFpci4gIEl0IGlzCnRoZXJlZm9yZSBwb3NzaWJsZSB0aGF0IEkgbWlzc2VkIG9uZSBvciBtb3JlIGdlbmVzIHdoaWNoIGxpZXMgb3V0c2lkZQp0aGF0IHJhbmdlLgoKVGhlIHByZXZpb3VzIHBsb3R0ZWQgY29udHJhc3RzIHNvdWdodCB0byBzaG93IGNoYW5nZXMgYmV0d2VlbiB0aGUgdHdvCnN0cmFpbnMgejIuMyBhbmQgejIuMi4gIENvbnZlcnNlbHksIHRoZSBwcmV2aW91cyB2b2xjYW5vIHBsb3RzIHNlZWsgdG8KZGlyZWN0bHkgY29tcGFyZSBlYWNoIHN0cmFpbiBiZWZvcmUvYWZ0ZXIgZHJ1ZyB0cmVhdG1lbnQuCgojIyBMUlQgb2YgdGhlIEh1bWFuIE1hY3JvcGhhZ2UKCmBgYHtyfQp0bXJjMl9scnRfc3RyYWluX2RydWcgPC0gZGVzZXFfbHJ0KGhzX21hY3IsIGludGVyYWN0b3JfY29sdW1uID0gImRydWciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyZXN0X2NvbHVtbiA9ICJtYWNyb3BoYWdlenltb2RlbWUiLCBmYWN0b3JzID0gYygiZHJ1ZyIsICJtYWNyb3BoYWdlenltb2RlbWUiKSkKdG1yYzJfbHJ0X3N0cmFpbl9kcnVnJGNsdXN0ZXJfZGF0YSRwbG90CmBgYAoKIyMgUGFyYXNpdGUKCmBgYHtyfQpscF9tYWNyb3BoYWdlX2RlIDwtIGFsbF9wYWlyd2lzZShscF9tYWNyb3BoYWdlX25vc2IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsX2JhdGNoPSJzdmFzZXEiLCBmaWx0ZXI9VFJVRSkKdG1yYzJfcGFyYXNpdGVfa2VlcGVycyA8LSBsaXN0KAogICJ6MjNfdnNfejIyIiA9IGMoInoyMyIsICJ6MjIiKSkKbHBfbWFjcm9waGFnZV90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBscF9tYWNyb3BoYWdlX2RlLCBrZWVwZXJzID0gdG1yYzJfcGFyYXNpdGVfa2VlcGVycywKICBleGNlbCA9IGdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfZGUvbWFjcm9waGFnZV9wYXJhc2l0ZV9pbmZlY3Rpb25fZGUtdnt2ZXJ9Lnhsc3giKSkKbHBfbWFjcm9waGFnZV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBscF9tYWNyb3BoYWdlX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS9tYWNyb3BoYWdlX3BhcmFzaXRlX3NpZy12e3Zlcn0ueGxzeCIpKQoKbHBfbWFjcm9waGFnZV90YWJsZVtbInBsb3RzIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dW1sicGxvdCJdXQoKdXBfZ2VuZXMgPC0gbHBfbWFjcm9waGFnZV9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbMV1dCmRpbSh1cF9nZW5lcykKZG93bl9nZW5lcyA8LSBscF9tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWzFdXQpkaW0oZG93bl9nZW5lcykKYGBgCgpgYGB7ciBwYXJhc2l0ZV92b2xjYW5vfQpscF96MjNzYl92c196MjJzYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19kZSgKICB0YWJsZSA9IGxwX21hY3JvcGhhZ2VfdGFibGVbWyJkYXRhIl1dW1siejIzX3ZzX3oyMiJdXSwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBzaGFwZXNfYnlfc3RhdGUgPSBGQUxTRSwgY29sb3JfYnkgPSAiZmMiLCAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiKQpwbG90bHk6OmdncGxvdGx5KGxwX3oyM3NiX3ZzX3oyMnNiX3ZvbGNhbm8kcGxvdCkKbHBfejIzc2JfdnNfejIyc2Jfdm9sY2FubyRwbG90CmBgYAoKYGBge3J9CmxwX2xlbmd0aHMgPC0gYWxsX2xwX2Fubm90WywgYygiZ2lkIiwgImFubm90X2Nkc19sZW5ndGgiKV0KY29sbmFtZXMobHBfbGVuZ3RocykgIDwtIGMoIklEIiwgImxlbmd0aCIpCgp1cF9nb3NlcSA8LSBzaW1wbGVfZ29zZXEodXBfZ2VuZXMsIGdvX2RiID0gbHBfZ28sIGxlbmd0aF9kYiA9IGxwX2xlbmd0aHMpCiMjIFZpZXcgY2F0ZWdvcmllcyBvdmVyIHJlcHJlc2VudGVkIGluIHRoZSAyLjMgc2FtcGxlcwp1cF9nb3NlcSRwdmFsdWVfcGxvdHMkYnBwX3Bsb3Rfb3Zlcgpkb3duX2dvc2VxIDwtIHNpbXBsZV9nb3NlcShkb3duX2dlbmVzLCBnb19kYiA9IGxwX2dvLCBsZW5ndGhfZGIgPSBscF9sZW5ndGhzKQojIyBWaWV3IGNhdGVnb3JpZXMgb3ZlciByZXByZXNlbnRlZCBpbiB0aGUgMi4yIHNhbXBsZXMKZG93bl9nb3NlcSRwdmFsdWVfcGxvdHMkYnBwX3Bsb3Rfb3ZlcgoKd3JpdHRlbl9nb3NlcSA8LSB3cml0ZV9nb3NlcV9kYXRhKHVwX2dvc2VxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWwgPSBnbHVlKCJscF9tYWNyb3BoYWdlX2luY3JlYXNlZF96Mi4zX2dvc2VxLXZ7dmVyfS54bHN4IikpCndyaXR0ZW5fZ29zZXEgPC0gd3JpdGVfZ29zZXFfZGF0YShkb3duX2dvc2VxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWwgPSBnbHVlKCJscF9tYWNyb3BoYWdlX2luY3JlYXNlZF96Mi4yX2dvc2VxLXZ7dmVyfS54bHN4IikpCmBgYAoKIyBHU1ZBCgpgYGB7cn0KaHNfaW5mZWN0ZWQgPC0gc3Vic2V0X2V4cHQoaHNfbWFjcm9waGFnZSwgc3Vic2V0PSJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmYnIikgJT4lCiAgc3Vic2V0X2V4cHQoc3Vic2V0PSJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmZfc2InIikKaHNfZ3N2YV9jMiA8LSBzaW1wbGVfZ3N2YShoc19pbmZlY3RlZCkKaHNfZ3N2YV9jMl9tZXRhIDwtIGdldF9tc2lnZGJfbWV0YWRhdGEoaHNfZ3N2YV9jMiwgbXNpZ194bWw9InJlZmVyZW5jZS9tc2lnZGJfdjcuMi54bWwiKQpoc19nc3ZhX2MyX3NpZyA8LSBnZXRfc2lnX2dzdmFfY2F0ZWdvcmllcyhoc19nc3ZhX2MyX21ldGEsIGV4Y2VsID0gImV4Y2VsL21hY3JvcGhhZ2VfZGUvaHNfbWFjcm9waGFnZV9nc3ZhX2MyX3NpZy54bHN4IikKaHNfZ3N2YV9jMl9zaWckcmF3X3Bsb3QKCmhzX2dzdmFfYzcgPC0gc2ltcGxlX2dzdmEoaHNfaW5mZWN0ZWQsIHNpZ25hdHVyZV9jYXRlZ29yeSA9ICJjNyIpCmhzX2dzdmFfYzdfbWV0YSA8LSBnZXRfbXNpZ2RiX21ldGFkYXRhKGhzX2dzdmFfYzcsIG1zaWdfeG1sPSJyZWZlcmVuY2UvbXNpZ2RiX3Y3LjIueG1sIikKaHNfZ3N2YV9jN19zaWcgPC0gZ2V0X3NpZ19nc3ZhX2NhdGVnb3JpZXMoaHNfZ3N2YV9jNywgZXhjZWwgPSAiZXhjZWwvbWFjcm9waGFnZV9kZS9oc19tYWNyb3BoYWdlX2dzdmFfYzdfc2lnLnhsc3giKQpoc19nc3ZhX2M3X3NpZyRyYXdfcGxvdApgYGAKCiMgVHJ5IG91dCBhIG5ldyB0b29sCgpUd28gcmVhc29uczogTmFqaWIgbG92ZXMgaGltIHNvbWUgUENBLCB0aGlzIHVzZXMgd2lraXBhdGh3YXlzLCB3aGljaCBpcyBzb21ldGhpbmcgSSB0aGluayBpcyBuZWF0LgoKT2ssIEkgc3BlbnQgc29tZSB0aW1lIGxvb2tpbmcgdGhyb3VnaCB0aGUgY29kZSBhbmQgSSBoYXZlIHNvbWUKcHJvYmxlbXMgd2l0aCBzb21lIG9mIHRoZSBkZXNpZ24gZGVjaXNpb25zLgoKTW9zdCBpbXBvcnRhbnRseSwgaXQgcmVxdWlyZXMgYSBkYXRhLmZyYW1lKCkgd2hpY2ggaGFzIHRoZSBmb2xsb3dpbmcgZm9ybWF0OgoKMS4gIE5vIHJvd25hbWVzLCBpbnN0ZWFkIGNvbHVtbiAjMSBpcyB0aGUgc2FtcGxlIElELgoyLiAgQ29sdW1ucyAyLW0gYXJlIHRoZSBjYXRlZ29yaWNhbC9zdXJ2aXZhbC9ldGMgbWV0cmljcy4KMy4gIENvbHVtbnMgbS1uIGFyZSAxIGdlbmUtcGVyLWNvbHVtbiB3aXRoIGxvZzIgdmFsdWVzLgoKQnV0IHdoZW4gSSB0aGluayBhYm91dCBpdCBJIHRoaW5rIEkgZ2V0IHRoZSBpZGVhLCB0aGV5IHdhbnQgdG8gYmUgYWJsZSB0byBkbyBtb2RlbGxpbmcgc3R1ZmYKbW9yZSBlYXNpbHkgd2l0aCByZXNwb25zZSBmYWN0b3JzLgoKYGBge3J9CmxpYnJhcnkocGF0aHdheVBDQSkKbGlicmFyeShyV2lraVBhdGh3YXlzKQoKZG93bmxvYWRlZCA8LSBkb3dubG9hZFBhdGh3YXlBcmNoaXZlKG9yZ2FuaXNtID0gIkhvbW8gc2FwaWVucyIsIGZvcm1hdCA9ICJnbXQiKQpkYXRhX3BhdGggPC0gc3lzdGVtLmZpbGUoImV4dGRhdGEiLCBwYWNrYWdlID0gInBhdGh3YXlQQ0EiKQp3aWtpcGF0aHdheXMgPC0gcmVhZF9nbXQocGFzdGUwKGRhdGFfcGF0aCwgIi93aWtpcGF0aHdheXNfaHVtYW5fc3ltYm9sLmdtdCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gPSBUUlVFKQoKZXhwdCA8LSBzdWJzZXRfZXhwdChoc19tYWNyb3BoYWdlLCBzdWJzZXQgPSAibWFjcm9waGFnZXRyZWF0bWVudCE9J3VuaW5mJyIpICU+JQogIHN1YnNldF9leHB0KHN1YnNldCA9ICJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmZfc2InIikKZXhwdCA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGV4cHQsIGZhY3QgPSAibWFjcm9waGFnZXp5bW9kZW1lIikKCnN5bWJvbF92ZWN0b3IgPC0gZkRhdGEoZXhwdClbW3N5bWJvbF9jb2x1bW5dXQpuYW1lcyhzeW1ib2xfdmVjdG9yKSA8LSByb3duYW1lcyhmRGF0YShleHB0KSkKc3ltYm9sX2RmIDwtIGFzLmRhdGEuZnJhbWUoc3ltYm9sX3ZlY3RvcikKCmFzc2F5X2RmIDwtIG1lcmdlKHN5bWJvbF9kZiwgYXMuZGF0YS5mcmFtZShleHBycyhleHB0KSksIGJ5ID0gInJvdy5uYW1lcyIpCmFzc2F5X2RmW1siUm93Lm5hbWVzIl1dIDwtIE5VTEwKcm93bmFtZXMoYXNzYXlfZGYpIDwtIG1ha2UubmFtZXMoYXNzYXlfZGZbWyJzeW1ib2xfdmVjdG9yIl1dLCB1bmlxdWUgPSBUUlVFKQphc3NheV9kZltbInN5bWJvbF92ZWN0b3IiXV0gPC0gTlVMTAphc3NheV9kZiA8LSBhcy5kYXRhLmZyYW1lKHQoYXNzYXlfZGYpKQphc3NheV9kZltbIlNhbXBsZUlEIl1dIDwtIHJvd25hbWVzKGFzc2F5X2RmKQphc3NheV9kZiA8LSBkcGx5cjo6c2VsZWN0KGFzc2F5X2RmLCAiU2FtcGxlSUQiLCBldmVyeXRoaW5nKCkpCgpmYWN0b3JfZGYgPC0gYXMuZGF0YS5mcmFtZShwRGF0YShleHB0KSkKZmFjdG9yX2RmW1siU2FtcGxlSUQiXV0gPC0gcm93bmFtZXMoZmFjdG9yX2RmKQpmYWN0b3JfZGYgPC0gZHBseXI6OnNlbGVjdChmYWN0b3JfZGYsICJTYW1wbGVJRCIsIGV2ZXJ5dGhpbmcoKSkKZmFjdG9yX2RmIDwtIGZhY3Rvcl9kZlssIGMoIlNhbXBsZUlEIiwgZmFjdG9ycyldCgp0dCA8LSBDcmVhdGVPbWljcygKICBhc3NheURhdGFfZGYgPSBhc3NheV9kZiwKICBwYXRod2F5Q29sbGVjdGlvbl9scyA9IHdpa2lwYXRod2F5cywKICByZXNwb25zZSA9IGZhY3Rvcl9kZiwKICByZXNwVHlwZSA9ICJjYXRlZ29yaWNhbCIsCiAgbWluUGF0aFNpemU9NSkKCnN1cGVyIDwtIEFFU1BDQV9wVmFscygKICBvYmplY3QgPSB0dCwKICBudW1QQ3MgPSAyLAogIHBhcmFsbGVsID0gRkFMU0UsCiAgbnVtQ29yZXMgPSA4LAogIG51bVJlcHMgPSAyLAogIGFkanVzdG1lbnQgPSAiQkgiKQpgYGAKCmBgYHtyfQojIyBTdG9wcGluZyB0aGlzIGJlY2F1c2UgaXQgdGFrZXMgZm9yZXZlcgojI2lmICghaXNUUlVFKGdldDAoInNraXBfbG9hZCIpKSkgewojIyAgcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSkKIyMgIG1lc3NhZ2UoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkKIyMgIG1lc3NhZ2UoIlNhdmluZyB0byAiLCBzYXZlZmlsZSkKIyMgIHRtcCA8LSBzbShzYXZlbWUoZmlsZW5hbWUgPSBzYXZlZmlsZSkpCiMjfQpgYGAKCmBgYHtyIGxvYWRtZV9hZnRlciwgZXZhbCA9IEZBTFNFfQp0bXAgPC0gbG9hZG1lKGZpbGVuYW1lID0gc2F2ZWZpbGUpCmBgYAo=