1 Changelog

  • 202401-202405: Cleanups, formatting, ensuring that everything works in the container.
  • 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 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 a completely different cell type, U937. As their ATCC page states, they are malignant cells taken from the pleural effusion of a 37 year old white male with histiocytic lymphoma and which exhibit the morphology of monocytes. Thus, this document now includes some comparisons of the cell types as well as the various macrophage donors (given that there are now more donors too).

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

2.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_metadata(hs_macrophage, columns = "drug") %>%
  set_conditions(fact = "drug", colors = color_choices[["drug"]]) %>%
  set_batches(fact = "typeofcells")
## Recasting the data.frame to DataFrame.
## 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 <- colData(all_human)[["strainid"]] == "none"
##colData(all_human)[["strainid"]] <- paste0("s", colData(all_human)[["strainid"]],
##                                         "_", colData(all_human)[["macrophagezymodeme"]])
colData(all_human)[no_strain_idx, "strainid"] <- "none"
table(colData(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_conditions(all_human, fact = "typeofcells") %>%
  set_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(colData(all_human_types)[["condition"]], "_",
                         colData(all_human_types)[["macrophagezymodeme"]])
type_zymo <- set_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(colData(all_human_types)[["condition"]], "_",
                         colData(all_human_types)[["drug"]])
type_drug <- set_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 <- colData(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(colData(hs_macrophage)[["macrophagetreatment"]], "_",
                         colData(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_conditions(hs_macrophage, fact = new_conditions) %>%
  sanitize_metadata(column = "drug") %>%
  subset_se(subset = "typeofcells!='U937'") %>%
  set_se_colors(color_choices[["treatment_zymo"]])
## The numbers of samples by condition are:
## 
##    inf_sb_z22    inf_sb_z23       inf_z22       inf_z23    uninf_none 
##            15            14            14            15             5 
## uninf_sb_none 
##             5
## Recasting the data.frame to DataFrame.

2.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_se <- set_conditions(hs_macr, fact = "drug", colors = color_choices[["drug"]])
## The numbers of samples by condition are:
## 
## antimony     none 
##       27       27
hs_macr_strain_se <- set_conditions(hs_macr, fact = "macrophagezymodeme",
                                      colors = color_choices[["zymo"]]) %>%
  subset_se(subset = "macrophagezymodeme != 'none'")
## The numbers of samples by condition are:
## 
## none  z22  z23 
##    8   23   23
table(colData(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

2.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(colData(hs_u937)[["macrophagetreatment"]], "_",
                         colData(hs_u937)[["macrophagezymodeme"]])
u937_se <- set_conditions(hs_u937, fact = new_conditions,
                            colors = color_choices[["treatment_zymo"]])
## The numbers of samples by condition are:
## 
##    inf_sb_z22    inf_sb_z23       inf_z22       inf_z23    uninf_none 
##             3             3             3             3             1 
## uninf_sb_none 
##             1

2.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: Antimonal treated or not.
  • strains used: Uninfected, z2.3, and z2.2.
  • cellltypes: U937 or macrophage.
  • donors: The person from whom the macrophages were taken.

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.

## Each of the following lists has the name of the contrast as the key
## followed by a two element vector comprised of the numerator and
## denominator as the value.  In the case of this first contrast, that
## is comprised of a string which manually defines a series of more
## complex contrasts than the usual/simple pairwise.
tmrc2_human_extra <- "z23drugnodrug_vs_z22drugnodrug = (conditioninf_sb_z23 - conditioninf_z23) - (conditioninf_sb_z22 - conditioninf_z22), z23z22drug_vs_z23z22nodrug = (conditioninf_sb_z23 - conditioninf_sb_z22) - (conditioninf_z23 - conditioninf_z22)"
tmrc2_human_keepers <- list(
  "z23nosb_vs_uninf" = c("inf_z23", "uninf_none"),
  "z22nosb_vs_uninf" = c("inf_z22", "uninf_none"),
  "z23nosb_vs_z22nosb" = c("inf_z23", "inf_z22"),
  "z23sb_vs_z22sb" = c("inf_sb_z23", "inf_sb_z22"),
  "z23sb_vs_z23nosb" = c("inf_sb_z23", "inf_z23"),
  "z22sb_vs_z22nosb" = c("inf_sb_z22", "inf_z22"),
  "z23sb_vs_sb" = c("inf_sb_z23", "uninf_sb_none"),
  "z22sb_vs_sb" = c("inf_sb_z22", "uninf_sb_none"),
  "z23sb_vs_uninf" = c("inf_sb_z23", "uninf_none"),
  "z22sb_vs_uninf" = c("inf_sb_z22", "uninf_none"),
  "sb_vs_uninf" = c("uninf_sb_none", "uninf_none"),
  "extra_z2322" = c("z23drugnodrug", "z22drugnodrug"),
  "extra_drugnodrug" = c("z23z22drug", "z23z22nodrug"))
single_tmrc2_keeper <- list(
  "z22sb_vs_sb" = c("inf_sb_z22", "uninf_sb_none"))
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 = (conditionU937_z23 - conditionU937_z22) - (conditionMacrophages_z23 - conditionMacrophages_z22)"
tmrc2_typezymo_keepers <- list(
  "u937_macr" = c("Macrophages_none", "U937_none"),
  "zymo_macr" = c("Macrophages_z23", "Macrophages_z22"),
  "zymo_u937" = c("U937_z23", "U937_z22"),
  "z23_types" = c("U937_z23", "Macrophages_z23"),
  "z22_types" = c("U937_z22", "Macrophages_z22"),
  "zymos_types" = c("zymos_vs_types"))
tmrc2_typedrug_keepers <- list(
  "type_nodrug" = c("U937_none", "Macrophages_none"),
  "type_drug" = c("U937_antimony", "Macrophages_antimony"),
  "macr_drugs" = c("Macrophages_antimony", "Macrophages_none"),
  "u937_drugs" = c("U937_antimony", "U937_none"))
u937_keepers <- list(
  "z23nosb_vs_uninf" = c("inf_z23", "uninf_none"),
  "z22nosb_vs_uninf" = c("inf_z22", "uninf_none"),
  "z23nosb_vs_z22nosb" = c("inf_z23", "inf_z22"),
  "z23sb_vs_z22sb" = c("inf_sb_z23", "inf_sb_z22"),
  "z23sb_vs_z23nosb" = c("inf_sb_z23", "inf_z23"),
  "z22sb_vs_z22nosb" = c("inf_sb_z22", "inf_z22"),
  "z23sb_vs_sb" = c("inf_sb_z23", "uninf_sb_none"),
  "z22sb_vs_sb" = c("inf_sb_z22", "uninf_sb_none"),
  "z23sb_vs_uninf" = c("inf_sb_z23", "uninf_none"),
  "z22sb_vs_uninf" = c("inf_sb_z22", "uninf_none"),
  "sb_vs_uninf" = c("uninf_sb_none", "uninf_none"))
## If some cases, when the set of significant genes was chosen, an
## additional filter was added to exclude genes with expression values
## less than 'high_expression' according to the
## 'high_expression_column' in the table.
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("analyses/macrophage_de/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("hgnc_symbol", "deseq_logfc", "deseq_adjp",
                "deseq_basemean", "deseq_num", "deseq_den")
    wanted_data <- kdata[, wanted]
    colnames(wanted_data) <- c("hgnc_symbol", "deseq_logfc", "deseq_adjp",
                               "deseq_mean", "deseq_numerator", "deseq_denominator")
    write_xlsx(data = wanted_data, excel = filename)
  }
}

write_all_gp <- function(all_gp, suffix = NULL) {
  all_written <- list()
  for (g in seq_len(length(all_gp))) {
    name <- names(all_gp)[g]
    datum <- all_gp[[name]]
    filename <- glue("analyses/macrophage_de/gprofiler/{name}_gprofiler-v{ver}.xlsx")
    if (!is.null(suffix)) {
      filename <- glue("analyses/macrophage_de/gprofiler/{name}_gprofiler{suffix}-v{ver}.xlsx")
    }
    written <- sm(write_gprofiler_data(datum, excel = filename))
    all_written[[g]] <- written
  }
  return(all_written)
}

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

The structure of these blocks will all basically be identical:

  • Perform a set of pairwise contrasts of all the conditions against each other. Optionally use sva.
  • Given that result, dump it in its entirety to an xlsx file in the analyses/ directory.
  • Given those combined tables, extract from them the set deemed ‘significant’ by whatever criteria we want to try. (Usually |lfc| >= 1.0, adjusted p <= 0.05; but potentially also expression >= x and sometimes a set of less stringent values (|lfc| >= 0.6))
  • Given one or more gene sets deemed ‘significant’ pass them to gProfiler2 and see what pops out.

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

Note to self: given the changes to hpgltools I may need to specify the statistical model string when I am using svaseq for some/many/all of these comparisons.

drug_de <- all_pairwise(all_human, filter = TRUE, model_svs = "svaseq",
                        model_fstring = "~ 0 + condition")
## antimony     none 
##       34       34
## Running normalize_se.
## Removing 9198 low-count genes (12283 remaining).
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## I think this is failing? SummarizedExperiment
## Basic step 0/3: Transforming data.
## Running normalize_se.
## Setting 85798 entries to zero.
## This received a matrix of SVs.
## converting counts to integer mode
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## Warning in createContrastL(objFlt$formula, objFlt$data, L): Contrasts with only
## a single non-zero term are already evaluated by default.
## conditions
## antimony     none 
##       34       34
## conditions
## antimony     none 
##       34       34
## conditions
## antimony     none 
##       34       34
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 1 comparisons.
## The logFC agreement among the methods follows:
##                 nn_vs_ntmn
## basic_vs_deseq      0.8651
## basic_vs_dream      0.8738
## basic_vs_ebseq      0.8367
## basic_vs_edger      0.8671
## basic_vs_limma      0.8771
## basic_vs_noiseq     0.8726
## deseq_vs_dream      0.9719
## deseq_vs_ebseq      0.9344
## deseq_vs_edger      0.9988
## deseq_vs_limma      0.9665
## deseq_vs_noiseq     0.9738
## dream_vs_ebseq      0.9770
## dream_vs_edger      0.9741
## dream_vs_limma      0.9953
## dream_vs_noiseq     0.9616
## ebseq_vs_edger      0.9383
## ebseq_vs_limma      0.9728
## ebseq_vs_noiseq     0.9486
## edger_vs_limma      0.9688
## edger_vs_noiseq     0.9745
## limma_vs_noiseq     0.9584
drug_table <- combine_de_tables(
  drug_de, keepers = tmrc2_drug_keepers,
  excel = glue("analyses/macrophage_de/de_tables/macrophage_drug_comparison-v{ver}.xlsx"))
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?
## Plot describing unique/shared genes in a differential expression table.

combined_to_tsv(drug_table, celltype = "all")

drug_sig <- extract_significant_genes(
  drug_table,
  excel = glue("analyses/macrophage_de/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      256        393

drug_highsig <- extract_significant_genes(
  drug_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("analyses/macrophage_de/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      208        343

drug_lesssig <- extract_significant_genes(
  drug_table, lfc = 0.6,
  excel = glue("analyses/macrophage_de/sig_tables/macrophage_drug_lesssig-v{ver}.xlsx"))
drug_lesssig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 0.6 adj P cutoff: 0.05
##      limma_up limma_down edger_up edger_down deseq_up deseq_down ebseq_up
## drug     1120       1326     1098       1451     1082       1461      647
##      ebseq_down basic_up basic_down
## drug        983      772        945

2.4.1.1 gProfiler2 results of the significant drug genes

all_drug_gp <- all_gprofiler(drug_sig, enrich_id_column = "hgnc_symbol")
all_drug_gp
##            BP CC CORUM HP HPA KEGG MIRNA MF REAC  TF WP
## drug_up    88 32     0  0   0    5     0 38   78  26  9
## drug_down 320 61     0  0   0    1     1 32    2 297  2
written <- write_all_gp(all_drug_gp)

all_drug_lesssig <- all_gprofiler(drug_lesssig, enrich_id_column = "hgnc_symbol")
written <- write_all_gp(all_drug_lesssig, suffix = "_lfc0.6_")

2.4.2 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_fstring = "~ 0 + condition",
                        model_svs = "svaseq")
## Macrophages        U937 
##          54          14
## Running normalize_se.
## Removing 9198 low-count genes (12283 remaining).
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## I think this is failing? SummarizedExperiment
## Basic step 0/3: Transforming data.
## Running normalize_se.
## Setting 85798 entries to zero.
## This received a matrix of SVs.
## converting counts to integer mode
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## Warning in createContrastL(objFlt$formula, objFlt$data, L): Contrasts with only
## a single non-zero term are already evaluated by default.
## conditions
## Macrophages        U937 
##          54          14
## conditions
## Macrophages        U937 
##          54          14
## conditions
## Macrophages        U937 
##          54          14
type_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 1 comparisons.
## The logFC agreement among the methods follows:
##                 U937_vs_Mc
## basic_vs_deseq      0.8587
## basic_vs_dream      0.8853
## basic_vs_ebseq      0.8125
## basic_vs_edger      0.8576
## basic_vs_limma      0.8982
## basic_vs_noiseq     0.9114
## deseq_vs_dream      0.9938
## deseq_vs_ebseq      0.9805
## deseq_vs_edger      0.9974
## deseq_vs_limma      0.9849
## deseq_vs_noiseq     0.9835
## dream_vs_ebseq      0.9682
## dream_vs_edger      0.9947
## dream_vs_limma      0.9932
## dream_vs_noiseq     0.9910
## ebseq_vs_edger      0.9836
## ebseq_vs_limma      0.9490
## ebseq_vs_noiseq     0.9652
## edger_vs_limma      0.9859
## edger_vs_noiseq     0.9829
## limma_vs_noiseq     0.9817
type_table <- combine_de_tables(
  type_de, keepers = tmrc2_type_keepers,
  excel = glue("analyses/macrophage_de/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        2076          2460
##   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?
## Plot describing unique/shared genes in a differential expression table.

combined_to_tsv(type_table, celltype = "all")

type_sig <- extract_significant_genes(
  type_table,
  excel = glue("analyses/macrophage_de/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     2076       2460     2105       2436     1880
##      ebseq_down basic_up basic_down
## type       2485     1972       1784

type_highsig <- extract_significant_genes(
  type_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("analyses/macrophage_de/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     1297       1762     1322       1736     1181
##      ebseq_down basic_up basic_down
## type       1789     1345       1613

type_lesssig <- extract_significant_genes(
  type_table, lfc = 0.6,
  excel = glue("analyses/macrophage_de/sig_tables/macrophage_type_lesssig-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     2076       2460     2105       2436     1880
##      ebseq_down basic_up basic_down
## type       2485     1972       1784

2.4.2.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_svs = "svaseq",
                             model_fstring = "~ 0 + condition",
                             extra_contrasts = type_zymo_extra)
## Macrophages_none  Macrophages_z22  Macrophages_z23        U937_none 
##                8               23               23                2 
##         U937_z22         U937_z23 
##                6                6
## Running normalize_se.
## Removing 9198 low-count genes (12283 remaining).
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## I think this is failing? SummarizedExperiment
## Basic step 0/3: Transforming data.
## Running normalize_se.
## Setting 85798 entries to zero.
## This received a matrix of SVs.
## converting counts to integer mode
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## The contrast zymos is not in the results.
## If this is not an extra contrast, then this is an error.
## Warning in createContrastL(objFlt$formula, objFlt$data, L): Contrasts with only
## a single non-zero term are already evaluated by default.
## conditions
## Macrophages_none  Macrophages_z22  Macrophages_z23        U937_none 
##                8               23               23                2 
##         U937_z22         U937_z23 
##                6                6
## conditions
## Macrophages_none  Macrophages_z22  Macrophages_z23        U937_none 
##                8               23               23                2 
##         U937_z22         U937_z23 
##                6                6
## conditions
## Macrophages_none  Macrophages_z22  Macrophages_z23        U937_none 
##                8               23               23                2 
##         U937_z22         U937_z23 
##                6                6

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

Strangely, as of 20250903, the following line throws an error in the container: “Error: subscript contains invalid names.”

But when I run it manually I get no error. I assume this means that I fell behind while maintaining hpgltools HEAD with the container?

In addition, the functions actually did return successfully.

type_zymo_table <- combine_de_tables(
  type_zymo_de, keepers = tmrc2_typezymo_keepers,
  excel = glue("analyses/macrophage_de/de_tables/macrophage_type_zymo_comparison-v{ver}.xlsx"))
## Error : subscript contains invalid names
## coefficient limma did not find NA or zymos_vs_types.
## coefficient edger did not find conditionNA or conditionzymos_vs_types.
## coefficient limma did not find NA or zymos_vs_types.
type_zymo_table
## A set of combined differential expression results.
##                                    table deseq_sigup deseq_sigdown edger_sigup
## 1 U937_none_vs_Macrophages_none-inverted        2353          2081        2360
## 2     Macrophages_z23_vs_Macrophages_z22         300           459         297
## 3                   U937_z23_vs_U937_z22           1             2           1
## 4            U937_z23_vs_Macrophages_z23        2153          2468        2122
## 5            U937_z22_vs_Macrophages_z22        2024          2539        2005
## 6                         zymos_vs_types           0             0         334
##   edger_sigdown limma_sigup limma_sigdown
## 1          2088        2017          2206
## 2           460         382           318
## 3             3           0             0
## 4          2498        2294          2182
## 5          2558        2272          2154
## 6           219         185           222
## Plot describing unique/shared genes in a differential expression table.

combined_to_tsv(type_zymo_table, celltype = "all")

type_zymo_sig <- extract_significant_genes(
  type_zymo_table,
  excel = glue("analyses/macrophage_de/sig_tables/macrophage_type_zymo_sig-v{ver}.xlsx"))
## There is no deseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no ebseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_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: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_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, 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
## u937_macr       2017       2206     2360       2088     2353       2081
## zymo_macr        382        318      297        460      300        459
## zymo_u937          0          0        1          3        1          2
## z23_types       2294       2182     2122       2498     2153       2468
## z22_types       2272       2154     2005       2558     2024       2539
## zymos_types      185        222      334        219        0          0
##             ebseq_up ebseq_down basic_up basic_down
## u937_macr       1720       1867        0          0
## zymo_macr        211        255      213        113
## zymo_u937          0          1        0          0
## z23_types       1971       2021     1997       1808
## z22_types       1899       2423     2001       1804
## zymos_types        0          0        0          0

type_zymo_highsig <- extract_significant_genes(
  type_zymo_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("analyses/macrophage_de/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: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no ebseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_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: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
type_zymo_lesssig <- extract_significant_genes(
  type_zymo_table, lfc = 0.6,
  excel = glue("analyses/macrophage_de/sig_tables/macrophage_type_zymo_lesssig-v{ver}.xlsx"))
## There is no deseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no ebseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_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: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
type_zymo_lesssig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 0.6 adj P cutoff: 0.05
##             limma_up limma_down edger_up edger_down deseq_up deseq_down
## u937_macr       2865       3266     3296       3115     3292       3121
## zymo_macr        737        704      624        946      622        936
## zymo_u937          1          1        1          3        1          2
## z23_types       3432       3109     3197       3550     3242       3501
## z22_types       3465       3072     3141       3536     3181       3509
## zymos_types      338        331      527        374        0          0
##             ebseq_up ebseq_down basic_up basic_down
## u937_macr       2157       2696        0          0
## zymo_macr        343        418      442        389
## zymo_u937          2          1        0          0
## z23_types       2933       2687     3151       2748
## z22_types       2949       3250     3231       2760
## zymos_types        0          0        0          0

2.4.2.2 Combined factors of interest: 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_svs = "svaseq",
                             model_fstring = "~ 0 + condition")
## Macrophages_antimony     Macrophages_none        U937_antimony 
##                   27                   27                    7 
##            U937_none 
##                    7
## Running normalize_se.
## Removing 9198 low-count genes (12283 remaining).
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## I think this is failing? SummarizedExperiment
## Basic step 0/3: Transforming data.
## Running normalize_se.
## Setting 85798 entries to zero.
## This received a matrix of SVs.
## converting counts to integer mode
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## Warning in createContrastL(objFlt$formula, objFlt$data, L): Contrasts with only
## a single non-zero term are already evaluated by default.
## conditions
## Macrophages_antimony     Macrophages_none        U937_antimony 
##                   27                   27                    7 
##            U937_none 
##                    7
## conditions
## Macrophages_antimony     Macrophages_none        U937_antimony 
##                   27                   27                    7 
##            U937_none 
##                    7
## conditions
## Macrophages_antimony     Macrophages_none        U937_antimony 
##                   27                   27                    7 
##            U937_none 
##                    7

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 6 comparisons.
type_drug_table <- combine_de_tables(
  type_drug_de, keepers = tmrc2_typedrug_keepers,
  excel = glue("analyses/macrophage_de/de_tables/macrophage_type_drug_comparison-v{ver}.xlsx"))
type_drug_table
## A set of combined differential expression results.
##                                               table deseq_sigup deseq_sigdown
## 1                     U937_none_vs_Macrophages_none        2094          2644
## 2             U937_antimony_vs_Macrophages_antimony        2102          2375
## 3 Macrophages_none_vs_Macrophages_antimony-inverted         606           966
## 4               U937_none_vs_U937_antimony-inverted         421           167
##   edger_sigup edger_sigdown limma_sigup limma_sigdown
## 1        2059          2668        2295          2194
## 2        2083          2385        2254          2133
## 3         605           960         672           910
## 4         442           176         211           162
## Plot describing unique/shared genes in a differential expression table.

#combined_to_tsv(type_drug_table, celltype = "all")

type_drug_sig <- extract_significant_genes(
  type_drug_table,
  excel = glue("analyses/macrophage_de/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     2295       2194     2059       2668     2094       2644
## type_drug       2254       2133     2083       2385     2102       2375
## macr_drugs       672        910      605        960      606        966
## u937_drugs       211        162      442        176      421        167
##             ebseq_up ebseq_down basic_up basic_down
## type_nodrug     1956       2465     2041       1852
## type_drug       2008       2312     1989       1856
## macr_drugs       482        881      369        569
## u937_drugs       359        157      168        146

type_drug_highsig <- extract_significant_genes(
  type_drug_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("analyses/macrophage_de/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     1394       1690     1312       1895     1343       1869
## type_drug       1386       1649     1302       1734     1321       1721
## macr_drugs       330        520      300        564      303        565
## u937_drugs       102         84      210        105      202        101
##             ebseq_up ebseq_down basic_up basic_down
## type_nodrug     1275       1789     1402       1659
## type_drug       1266       1719     1379       1657
## macr_drugs       243        517      294        471
## u937_drugs       168        100       99         85

type_drug_lesssig <- extract_significant_genes(
  type_drug_table, lfc = 0.6,
  excel = glue("analyses/macrophage_de/sig_tables/macrophage_type_drug_lesssig-v{ver}.xlsx"))
type_drug_lesssig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 0.6 adj P cutoff: 0.05
##             limma_up limma_down edger_up edger_down deseq_up deseq_down
## type_nodrug     3497       3150     3169       3694     3220       3659
## type_drug       3387       3114     3181       3438     3210       3414
## macr_drugs      1422       1592     1311       1747     1303       1743
## u937_drugs       459        429      800        417      770        414
##             ebseq_up ebseq_down basic_up basic_down
## type_nodrug     3010       3258     3246       2824
## type_drug       3048       3198     3187       2886
## macr_drugs       999       1467     1071       1179
## u937_drugs       720        454      470        449

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

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

3.2 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?

3.2.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_se, filter = TRUE, model_svs = "svaseq",
                                model_fstring = "~ 0 + condition")
## antimony     none 
##       27       27
## Running normalize_se.
## Removing 9725 low-count genes (11756 remaining).
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## I think this is failing? SummarizedExperiment
## Basic step 0/3: Transforming data.
## Running normalize_se.
## Setting 40036 entries to zero.
## This received a matrix of SVs.
## converting counts to integer mode
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## Warning in createContrastL(objFlt$formula, objFlt$data, L): Contrasts with only
## a single non-zero term are already evaluated by default.
## conditions
## antimony     none 
##       27       27
## conditions
## antimony     none 
##       27       27
## conditions
## antimony     none 
##       27       27
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 1 comparisons.
## The logFC agreement among the methods follows:
##                 nn_vs_ntmn
## basic_vs_deseq      0.8930
## basic_vs_dream      0.8901
## basic_vs_ebseq      0.8651
## basic_vs_edger      0.8942
## basic_vs_limma      0.8948
## basic_vs_noiseq     0.9048
## deseq_vs_dream      0.9951
## deseq_vs_ebseq      0.9647
## deseq_vs_edger      0.9997
## deseq_vs_limma      0.9911
## deseq_vs_noiseq     0.9837
## dream_vs_ebseq      0.9725
## dream_vs_edger      0.9952
## dream_vs_limma      0.9961
## dream_vs_noiseq     0.9880
## ebseq_vs_edger      0.9643
## ebseq_vs_limma      0.9694
## ebseq_vs_noiseq     0.9891
## edger_vs_limma      0.9911
## edger_vs_noiseq     0.9837
## limma_vs_noiseq     0.9852
hs_macr_drug_table <- combine_de_tables(
  hs_macr_drug_de, keepers = tmrc2_drug_keepers,
  excel = glue("analyses/macrophage_de/de_tables/macrophage_onlydrug_table-v{ver}.xlsx"))
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?
## Plot describing unique/shared genes in a differential expression table.

#combined_to_tsv(hs_macr_drug_table, celltype = "macrophage")

hs_macr_drug_sig <- extract_significant_genes(
  hs_macr_drug_table,
  excel = glue("analyses/macrophage_de/sig_tables/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      366        562

hs_macr_drug_highsig <- extract_significant_genes(
  hs_macr_drug_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("analyses/macrophage_de/sig_tables/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      285        479

## Creating the following to see how it affects gProfiler.
hs_macr_drug_lesssig <- extract_significant_genes(
  hs_macr_drug_table, lfc = 0.6,
  excel = glue("analyses/macrophage_de/sig_tables/macrophageonly_drug_sig_lfc0.6-v{ver}.xlsx"))

3.2.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_se, filter = TRUE, model_svs = "svaseq",
                                  model_fstring = "~ 0 + condition")
## z22 z23 
##  23  23
## Running normalize_se.
## Removing 9761 low-count genes (11720 remaining).
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## I think this is failing? SummarizedExperiment
## Basic step 0/3: Transforming data.
## Running normalize_se.
## Setting 32467 entries to zero.
## This received a matrix of SVs.
## converting counts to integer mode
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## Warning in createContrastL(objFlt$formula, objFlt$data, L): Contrasts with only
## a single non-zero term are already evaluated by default.
## conditions
## z22 z23 
##  23  23
## conditions
## z22 z23 
##  23  23
## conditions
## z22 z23 
##  23  23
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 1 comparisons.
## The logFC agreement among the methods follows:
##                 z23_vs_z22
## basic_vs_deseq      0.8273
## basic_vs_dream      0.8408
## basic_vs_ebseq      0.8021
## basic_vs_edger      0.8313
## basic_vs_limma      0.8629
## basic_vs_noiseq     0.1082
## deseq_vs_dream      0.9850
## deseq_vs_ebseq      0.9721
## deseq_vs_edger      0.9991
## deseq_vs_limma      0.9637
## deseq_vs_noiseq     0.2183
## dream_vs_ebseq      0.9734
## dream_vs_edger      0.9876
## dream_vs_limma      0.9782
## dream_vs_noiseq     0.2520
## ebseq_vs_edger      0.9726
## ebseq_vs_limma      0.9614
## ebseq_vs_noiseq     0.4180
## edger_vs_limma      0.9668
## edger_vs_noiseq     0.2127
## limma_vs_noiseq     0.2754
hs_macr_strain_table <- combine_de_tables(
  hs_macr_strain_de, keepers = tmrc2_strain_keepers,
  excel = glue("analyses/macrophage_de/de_tables/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         288           363         337
##   limma_sigdown
## 1           275
## `geom_line()`: Each group consists of only one observation.
## i Do you need to adjust the group aesthetic?
## Plot describing unique/shared genes in a differential expression table.

combined_to_tsv(hs_macr_strain_table, celltype = "macrophage")

hs_macr_strain_sig <- extract_significant_genes(
  hs_macr_strain_table,
  excel = glue("analyses/macrophage_de/sig_tables/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      288        363      291        371      199
##        ebseq_down basic_up basic_down
## strain        216      210        112

hs_macr_strain_highsig <- extract_significant_genes(
  hs_macr_strain_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("analyses/macrophage_de/sig_tables/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      184         93

hs_macr_strain_lesssig <- extract_significant_genes(
  hs_macr_strain_table, lfc = 0.6,
  excel = glue("analyses/macrophage_de/sig_tables/macrophageonly_onlystrain_lesssig-v{ver}.xlsx"))
hs_macr_strain_lesssig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 0.6 adj P cutoff: 0.05
##        limma_up limma_down edger_up edger_down deseq_up deseq_down ebseq_up
## strain      667        662      608        822      607        830      331
##        ebseq_down basic_up basic_down
## strain        370      446        387

3.2.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"]]]

3.2.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)
shared_drug_z23_gp[["pvalue_plots"]][["MF"]]
## NULL
shared_drug_z23_gp[["pvalue_plots"]][["BP"]]
## NULL
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)
shared_drug_z22_gp[["pvalue_plots"]][["BP"]]
## NULL

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

hs_macr_de_noextra <- all_pairwise(hs_macr, model_svs = "svaseq",
                                   model_fstring = "~ 0 + condition", filter = TRUE)
##    inf_sb_z22    inf_sb_z23       inf_z22       inf_z23    uninf_none 
##            12            11            11            12             4 
## uninf_sb_none 
##             4
## Running normalize_se.
## Removing 9725 low-count genes (11756 remaining).
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## I think this is failing? SummarizedExperiment
## Basic step 0/3: Transforming data.
## Running normalize_se.
## Setting 40036 entries to zero.
## This received a matrix of SVs.
## converting counts to integer mode
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## Warning in createContrastL(objFlt$formula, objFlt$data, L): Contrasts with only
## a single non-zero term are already evaluated by default.
## conditions
##    inf_sb_z22    inf_sb_z23       inf_z22       inf_z23    uninf_none 
##            12            11            11            12             4 
## uninf_sb_none 
##             4
## conditions
##    inf_sb_z22    inf_sb_z23       inf_z22       inf_z23    uninf_none 
##            12            11            11            12             4 
## uninf_sb_none 
##             4
## conditions
##    inf_sb_z22    inf_sb_z23       inf_z22       inf_z23    uninf_none 
##            12            11            11            12             4 
## uninf_sb_none 
##             4

hs_macr_de <- all_pairwise(hs_macr, model_svs = "svaseq", model_fstring = "~ 0 + condition",
                           filter = TRUE, extra_contrasts = tmrc2_human_extra)
##    inf_sb_z22    inf_sb_z23       inf_z22       inf_z23    uninf_none 
##            12            11            11            12             4 
## uninf_sb_none 
##             4
## Running normalize_se.
## Removing 9725 low-count genes (11756 remaining).
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## I think this is failing? SummarizedExperiment
## Basic step 0/3: Transforming data.
## Running normalize_se.
## Setting 40036 entries to zero.
## This received a matrix of SVs.
## converting counts to integer mode
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## The contrast z23drugnodrug is not in the results.
## If this is not an extra contrast, then this is an error.
## The contrast z23z22drug is not in the results.
## If this is not an extra contrast, then this is an error.
## Warning in createContrastL(objFlt$formula, objFlt$data, L): Contrasts with only
## a single non-zero term are already evaluated by default.
## conditions
##    inf_sb_z22    inf_sb_z23       inf_z22       inf_z23    uninf_none 
##            12            11            11            12             4 
## uninf_sb_none 
##             4
## conditions
##    inf_sb_z22    inf_sb_z23       inf_z22       inf_z23    uninf_none 
##            12            11            11            12             4 
## uninf_sb_none 
##             4
## conditions
##    inf_sb_z22    inf_sb_z23       inf_z22       inf_z23    uninf_none 
##            12            11            11            12             4 
## uninf_sb_none 
##             4
hs_macr_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.

Write out the results.

hs_single_table <- combine_de_tables(
  hs_macr_de_noextra, keepers = single_tmrc2_keeper,
  excel = glue("analyses/macrophage_de/de_tables/hs_macr_drug_zymo_z22sb_sb-v{ver}.xlsx"))
hs_single_table
## A set of combined differential expression results.
##                                  table deseq_sigup deseq_sigdown edger_sigup
## 1 uninf_sb_none_vs_inf_sb_z22-inverted          33             0          32
##   edger_sigdown limma_sigup limma_sigdown
## 1             0           2             0
## Only z22sb_vs_sb_up has information, cannot create an UpSet.
## Plot describing unique/shared genes in a differential expression table.
## NULL
hs_macr_table <- combine_de_tables(
  hs_macr_de, keepers = tmrc2_human_keepers,
  excel = glue("analyses/macrophage_de/de_tables/hs_macr_drug_zymo_table_macr_only-v{ver}.xlsx"))
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_z2322 using basic does not appear in the pairwise data.
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_z2322 using ebseq does not appear in the pairwise data.
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_z2322 using noiseq does not appear in the pairwise data.
## Error : subscript contains invalid names
## coefficient limma did not find z22drugnodrug or z23drugnodrug.
## coefficient edger did not find conditionz22drugnodrug or conditionz23drugnodrug.
## coefficient limma did not find z22drugnodrug or z23drugnodrug.
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_drugnodrug using basic does not appear in the pairwise
## data.
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_drugnodrug using ebseq does not appear in the pairwise
## data.
## Warning in extract_keepers(extracted, keepers, table_names, all_coefficients, :
## The table for extra_drugnodrug using noiseq does not appear in the pairwise
## data.
## Error : subscript contains invalid names
## coefficient limma did not find z23z22nodrug or z23z22drug.
## coefficient edger did not find conditionz23z22nodrug or conditionz23z22drug.
## coefficient limma did not find z23z22nodrug or z23z22drug.
hs_macr_table
## A set of combined differential expression results.
##                                   table deseq_sigup deseq_sigdown edger_sigup
## 1        uninf_none_vs_inf_z23-inverted         478           265         470
## 2        uninf_none_vs_inf_z22-inverted         359             6         340
## 3                    inf_z23_vs_inf_z22         349           539         359
## 4              inf_sb_z23_vs_inf_sb_z22         343           252         339
## 5        inf_z23_vs_inf_sb_z23-inverted         619           828         625
## 6        inf_z22_vs_inf_sb_z22-inverted         505          1040         520
## 7  uninf_sb_none_vs_inf_sb_z23-inverted         461           247         461
## 8  uninf_sb_none_vs_inf_sb_z22-inverted          33             0          32
## 9     uninf_none_vs_inf_sb_z23-inverted         839           923         854
## 10    uninf_none_vs_inf_sb_z22-inverted         660           746         672
## 11          uninf_sb_none_vs_uninf_none         561           748         563
## 12                                FALSE           0             0         329
## 13                                FALSE           0             0         329
##    edger_sigdown limma_sigup limma_sigdown
## 1            270         392           251
## 2              6         264            71
## 3            528         450           390
## 4            253         377           215
## 5            821         571           746
## 6           1009         671           925
## 7            249         374           232
## 8              0           2             0
## 9            906         805           914
## 10           733         555           744
## 11           742         513           696
## 12            63         243           135
## 13            63         243           135
## Plot describing unique/shared genes in a differential expression table.

combined_to_tsv(hs_macr_table, "macrophage")

hs_macr_sig <- extract_significant_genes(
  hs_macr_table,
  excel = glue("analyses/macrophage_de/sig_tables/hs_macr_drug_zymo_sig-v{ver}.xlsx"))
## There is no deseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_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: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no ebseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no ebseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_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: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_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: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_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, 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
## z23nosb_vs_uninf        392        251      470        270      478        265
## z22nosb_vs_uninf        264         71      340          6      359          6
## z23nosb_vs_z22nosb      450        390      359        528      349        539
## z23sb_vs_z22sb          377        215      339        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        232      461        249      461        247
## z22sb_vs_sb               2          0       32          0       33          0
## z23sb_vs_uninf          805        914      854        906      839        923
## z22sb_vs_uninf          555        744      672        733      660        746
## sb_vs_uninf             513        696      563        742      561        748
## extra_z2322             243        135      329         63        0          0
## extra_drugnodrug        243        135      329         63        0          0
##                    ebseq_up ebseq_down basic_up basic_down
## z23nosb_vs_uninf        111        112        0          0
## z22nosb_vs_uninf        160          2        0          0
## z23nosb_vs_z22nosb      257        408      281        259
## z23sb_vs_z22sb          106        108      117         44
## z23sb_vs_z23nosb        412        699      371        540
## z22sb_vs_z22nosb        458        886      437        680
## z23sb_vs_sb              33         58        0          0
## z22sb_vs_sb              25          0        0          0
## z23sb_vs_uninf          280        767      350        489
## z22sb_vs_uninf          444        551      276        396
## sb_vs_uninf             316        495        0          0
## extra_z2322               0          0        0          0
## extra_drugnodrug          0          0        0          0

hs_macr_highsig <- extract_significant_genes(
  hs_macr_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("analyses/macrophage_de/sig_tables/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: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_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: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no ebseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no ebseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_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: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_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: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_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, 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
## 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      278        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             243        135      329         63        0          0
## extra_drugnodrug        243        135      329         63        0          0
##                    ebseq_up ebseq_down basic_up basic_down
## z23nosb_vs_uninf         87         64        0          0
## z22nosb_vs_uninf         41          0        0          0
## z23nosb_vs_z22nosb      207        140      214        169
## z23sb_vs_z22sb           80         37       99         35
## z23sb_vs_z23nosb        212        529      293        465
## z22sb_vs_z22nosb        276        519      326        540
## z23sb_vs_sb              21         28        0          0
## z22sb_vs_sb               5          0        0          0
## z23sb_vs_uninf          177        550      295        401
## z22sb_vs_uninf          235        393      216        321
## sb_vs_uninf             191        352        0          0
## extra_z2322               0          0        0          0
## extra_drugnodrug          0          0        0          0

hs_macr_lesssig <- extract_significant_genes(
  hs_macr_table, lfc = 0.6,
  excel = glue("analyses/macrophage_de/sig_tables/hs_macr_drug_zymo_sig_lfc0.6-v{ver}.xlsx"))
## There is no deseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_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: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no ebseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
## There is no ebseq_logfc column in the table.
## The columns are: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_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: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_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: ensembl_gene_id, ensembl_transcript_id, version, transcript_version, description, gene_biotype, cds_length, chromosome_name, strand, start_position, end_position, hgnc_symbol, transcript, dream_logfc, dream_adjp, edger_logfc, edger_adjp, limma_logfc, limma_adjp, dream_ave, dream_t, dream_p, dream_b, edger_logcpm, edger_lr, edger_p, limma_ave, limma_t, limma_p, limma_b, limma_adjp_fdr, dream_adjp_fdr, edger_adjp_fdr, lfc_meta, lfc_var, lfc_varbymed, p_meta, p_var
hs_macr_lesssig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 0.6 adj P cutoff: 0.05
##                    limma_up limma_down edger_up edger_down deseq_up deseq_down
## z23nosb_vs_uninf        701        587      856        594      865        587
## z22nosb_vs_uninf        378        128      464         21      505         22
## z23nosb_vs_z22nosb      867        786      746        964      728        981
## z23sb_vs_z22sb          670        587      649        645      655        641
## z23sb_vs_z23nosb       1237       1395     1297       1536     1279       1545
## z22sb_vs_z22nosb       1492       1542     1287       1692     1211       1747
## z23sb_vs_sb             622        643      761        610      772        614
## z22sb_vs_sb               2          0       33          0       34          0
## z23sb_vs_uninf         1516       1656     1595       1671     1557       1700
## z22sb_vs_uninf         1127       1297     1246       1293     1222       1340
## sb_vs_uninf            1037       1148     1055       1262     1042       1291
## extra_z2322             381        288      482        210        0          0
## extra_drugnodrug        381        288      482        210        0          0
##                    ebseq_up ebseq_down basic_up basic_down
## z23nosb_vs_uninf        141        196        0          0
## z22nosb_vs_uninf        186          4        0          0
## z23nosb_vs_z22nosb      463        602      593        580
## z23sb_vs_z22sb          144        237      193        144
## z23sb_vs_z23nosb        774       1166     1016       1047
## z22sb_vs_z22nosb       1044       1349     1228       1264
## z23sb_vs_sb              39        115        0          0
## z22sb_vs_sb              30          0        0          0
## z23sb_vs_uninf          458       1259      665        812
## z22sb_vs_uninf          746        907      535        686
## sb_vs_uninf             495        788        0          0
## extra_z2322               0          0        0          0
## extra_drugnodrug          0          0        0          0

4.1 gene group upset

4.1.1 2.3 vs 2.2 up and down vs. uninfected

This is my version of the Venn diagram which includes the text:

“Differentially expressed genes in macrophages infected with subpopulations 2.2 or 2.3. Volcano plots contrast of: A. Venn diagram for upregulated and downregulated genes by infection with 2.3 and 2.2 strains. B. infected cells with 2.3 strains and uninfected cells; C. infected cells with 2.2 strains and uninfected cells; D. infected cells with 2.3 strains and infected cells with 2.2 strains”

The following upset plot is currently Figure 2E.

nodrug_upset <- upsetr_combined_de(hs_macr_table,
                                   desired_contrasts = c("z22nosb_vs_uninf", "z23nosb_vs_uninf"))
pp(file = "images/nodrug_upset.svg")
nodrug_upset[["plot"]]
dev.off()
## png 
##   2
nodrug_upset
## Plot describing unique/shared genes in a differential expression table.

4.1.1.1 A point of interest while Olga visits Umd

Najib and Olga asked about pulling the 9 gene IDs which are in the peculiar situation of increased expression in z2.2/uninf and decreased in z2.3/uninf. In the previous upset plot, these are visible in the 6th bar. I can access these via the attr() function, which I should admit I can never remember how to use, so I am going to use the code under the ‘Compare(no)Sb z2.3/z2.2 treatment’ heading to remember how to extract these genes.

all_groups <- nodrug_upset[["groups"]]
wanted_group <- "z23nosb_vs_uninf_down:z22nosb_vs_uninf_up"
gene_idx <- all_groups[[wanted_group]]
wanted_genes <- attr(all_groups, "elements")[gene_idx]
wanted_genes
## [1] "ENSG00000004846" "ENSG00000111783" "ENSG00000118298" "ENSG00000120738"
## [5] "ENSG00000126217" "ENSG00000163687" "ENSG00000170345" "ENSG00000244242"
## [9] "ENSG00000277481"
gene_symbol_idx <- rownames(rowData(hs_macr)) %in% as.character(wanted_genes)
rowData(hs_macr)[gene_symbol_idx, "hgnc_symbol"]
## [1] "ABCB5"    "RFX4"     "CA14"     "EGR1"     "MCF2L"    "DNASE1L3" "FOS"     
## [8] "IFITM10"  "PKD1L3"
  • ABCB5: ATB Binding Cassette Subfamily B Member #5, wide range of functions in this diverse paralogous family. Associated with skin diseases (melanoma and Epidermolysis Bullosa; participate in ATP-dependent transmembrane transport).
  • RFX4: Regulatory Factor X #4: transcription factor.
  • CA14: Carbonic anhydrase #14: Zync metalloenzyme catalyzes reversible hydration of CO2. This gene looks pretty neat, but not really relevant to anything we are likely to care about.
  • EGR1: Early Growth Response Protein #1: Another Tx factor (zinc-finger) – important for cell survival/proliferation/cell death. Presumably important for healing?
  • MCF2L: MCF.2 Cell Line Derived Transforming Sequence Like? guanine nucleotide exchange factor interacting with GTP-bound Rac1. Apparently associated with ostroarthritis; potentially relevant to regulation of RHOA and CDC42 signalling.
  • DNASE1L3: Deoxyribonuclease I family member: not inhibited by actin, breaks down DNA during apoptosis. Important during necrosis.
  • FOS: Proto-Oncogene, AP-1 Transcription Factor: leucine zipper dimerizes with JUN family proteins, forming tx factor complex AP-1. Important for cell proliferation, differentiation, and transformation.
  • IFITM10: Interferon-Induced Transmembrane Protein #10
  • PKD1L3: Polycystin 1 Like #3, Transient Receptor Potential Channel Interacting: 11 transmembrane domain protein which might help create cation channels.

As some comparison points, the Venn in the current figure has:

  • 387 up z2.3
  • 259 up z2.2
  • 83 shared up z2.3 and z2.2
  • 247 down z2.3
  • 3 down z2.2
  • 3 shared down z2.3 and z2.2

4.1.2 2.2 and 2.3 with SbV vs 2.2 and 2.3 without SbV

This is my version of the Venn with the text:

“Differentially expressed genes in macrophages infected with subpopulations 2.2 or 2.3, in presence of SbV. Volcano plots contrast of: A. infected cells with 2.3 strains + SbV and infected cells with 2.3 strains; B. infected cells with 2.2 strains + SbV and infected cells with 2.2 strains; C. infected cells with 2.3 strains + SbV and infected cells with 2.2 strains + SbV. D. Venn diagram for upregulated and downregulated genes by infection with 2.3+SbV and 2.2+SbV strains.”

A query from Olga (20240801): Please include in the upset in figure 3 the contrast of uninfected cells + SbV vs uninfected without SbV.

## I keep mis-interpreting this text, it is z2.3/z2.3SbV and z2.2/z2.2SbV
drugnodrug_upset <- upsetr_combined_de(hs_macr_table,
                                       desired_contrasts = c("z23sb_vs_z23nosb", "z22sb_vs_z22nosb"))
pp(file = "images/drugnodrug_upset.pdf")
drugnodrug_upset[["plot"]]
dev.off()
## png 
##   2
drugnodrug_upset
## Plot describing unique/shared genes in a differential expression table.

drugnodrug_uninf_contrasts <- c("z23sb_vs_z23nosb", "z22sb_vs_z22nosb", "sb_vs_uninf")
drugnodrug_upset_with_uninf <- upsetr_combined_de(hs_macr_table,
                                       desired_contrasts = drugnodrug_uninf_contrasts)
pp(file = "figures/drugnodrug_with_uninf_upset.svg")
drugnodrug_upset_with_uninf[["plot"]]
dev.off()
## png 
##   2
drugnodrug_upset_with_uninf
## Plot describing unique/shared genes in a differential expression table.

For some comparison points, the venn image has:

  • 222 up z2.3 SbV
  • 134 up z2.2 SbV
  • 182 down z2.3 SbV
  • 396 down z2.2 SbV
  • 605 shared down z2.2 and z2.3 SbV
  • 34 shared down z2.2 SbV and up z2.3 SbV
  • 363 shared up z2.2 SbV and z2.3 SbV

4.1.3 Compare z2.2SbV vs SbV and z2.3SbV and SbV

drug_upset <- upsetr_combined_de(hs_macr_table,
                                 desired_contrasts = c("z22sb_vs_sb", "z23sb_vs_sb"))
pp(file = "images/drug_upset.pdf")
drug_upset[["plot"]]
dev.off()
## png 
##   2
drug_upset
## Plot describing unique/shared genes in a differential expression table.

4.2 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("inf_z23", "uninf_none"),
  ## z2.2 vs uninfected
  "z22nosb_vs_uninf" = c("inf_z22", "uninf_none"),
  ## z2.3 vs z2.2
  "z23nosb_vs_z22nosb" = c("inf_z23", "inf_z22"),
  ## z2.3Sbv vs z2.3
  "z23sb_vs_z23nosb" = c("inf_sb_z23", "inf_z23"),
  ## z2.2Sbv vs z2.2
  "z22sb_vs_z22nosb" = c("inf_sb_z22", "inf_z22"),
  ## z2.3Sbv vs z2.2Sbv
  "z23sb_vs_z22sb" = c("inf_sb_z23", "inf_sb_z22"),
  ## Sbv vs uninfected.
  "sb_vs_uninf" = c("uninf_sb_none", "uninf_none"))
barplot_combined <- combine_de_tables(
  hs_macr_de, keepers = barplot_keepers,
  excel = glue("analyses/macrophage_de/de_tables/hs_macr_drug_zymo_7contrasts-v{ver}.xlsx"))

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("analyses/macrophage_de/sig_tables/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

5 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)
## Error in if (all_coverage < cutoff) {: missing value where TRUE/FALSE needed
power_estimate[[1]][["power_plot"]]
## Error: object 'power_estimate' not found
power_estimate[[1]][["powertd_plot"]]
## Error: object 'power_estimate' not found
power_estimate[[1]][["powerfd_plot"]]
## Error: object 'power_estimate' not found

6 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_se, model_svs = "svaseq",
                        filter = TRUE, model_fstring = "~ 0 + condition")
##    inf_sb_z22    inf_sb_z23       inf_z22       inf_z23    uninf_none 
##             3             3             3             3             1 
## uninf_sb_none 
##             1
## Running normalize_se.
## Removing 10730 low-count genes (10751 remaining).
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## I think this is failing? SummarizedExperiment
## Basic step 0/3: Transforming data.
## Running normalize_se.
## Setting 938 entries to zero.
## This received a matrix of SVs.
## converting counts to integer mode
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## Warning in createContrastL(objFlt$formula, objFlt$data, L): Contrasts with only
## a single non-zero term are already evaluated by default.
## conditions
##    inf_sb_z22    inf_sb_z23       inf_z22       inf_z23    uninf_none 
##             3             3             3             3             1 
## uninf_sb_none 
##             1
## conditions
##    inf_sb_z22    inf_sb_z23       inf_z22       inf_z23    uninf_none 
##             3             3             3             3             1 
## uninf_sb_none 
##             1
## conditions
##    inf_sb_z22    inf_sb_z23       inf_z22       inf_z23    uninf_none 
##             3             3             3             3             1 
## uninf_sb_none 
##             1 
## Error in NOISeq::noiseqbio(norm_input, k = k, norm = norm, factor = condition_column,  : 
##   ERROR: To run NOISeqBIO at least two replicates per condition are needed.
##          Please, run NOISeq if there are not enough replicates in your experiment.
u937_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.
u937_table <- combine_de_tables(
  u937_de, keepers = u937_keepers,
  excel = glue("analyses/macrophage_de/de_tables/u937_drug_zymo_table-v{ver}.xlsx"))
u937_table
## A set of combined differential expression results.
##                                   table deseq_sigup deseq_sigdown edger_sigup
## 1        uninf_none_vs_inf_z23-inverted           0             5           2
## 2        uninf_none_vs_inf_z22-inverted           0             0           0
## 3                    inf_z23_vs_inf_z22           1             0          17
## 4              inf_sb_z23_vs_inf_sb_z22           0             0           0
## 5        inf_z23_vs_inf_sb_z23-inverted         256           171         311
## 6        inf_z22_vs_inf_sb_z22-inverted         298           154         305
## 7  uninf_sb_none_vs_inf_sb_z23-inverted           0             0           2
## 8  uninf_sb_none_vs_inf_sb_z22-inverted           0             0           2
## 9     uninf_none_vs_inf_sb_z23-inverted         296           151         306
## 10    uninf_none_vs_inf_sb_z22-inverted         294           169         300
## 11          uninf_sb_none_vs_uninf_none         239           119         261
##    edger_sigdown limma_sigup limma_sigdown
## 1              5           0             3
## 2              5           0             3
## 3              6           3             3
## 4              1           0             2
## 5            176         221           192
## 6            149         220           190
## 7              0           0             0
## 8              5           1             3
## 9            155         233           181
## 10           175         227           210
## 11           127         192           154
## Plot describing unique/shared genes in a differential expression table.

combined_to_tsv(u937_table, celltype = "u937")

u937_sig <- extract_significant_genes(
  u937_table,
  excel = glue("analyses/macrophage_de/sig_tables/u937_drug_zymo_sig-v{ver}.xlsx"))
u937_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
## z23nosb_vs_uninf          0          3        2          5        0          5
## z22nosb_vs_uninf          0          3        0          5        0          0
## z23nosb_vs_z22nosb        3          3       17          6        1          0
## z23sb_vs_z22sb            0          2        0          1        0          0
## z23sb_vs_z23nosb        221        192      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          3        2          5        0          0
## z23sb_vs_uninf          233        181      306        155      296        151
## z22sb_vs_uninf          227        210      300        175      294        169
## sb_vs_uninf             192        154      261        127      239        119
##                    ebseq_up ebseq_down basic_up basic_down
## z23nosb_vs_uninf          5         14        0          0
## z22nosb_vs_uninf          0          7        0          0
## z23nosb_vs_z22nosb        8         42        0          0
## z23sb_vs_z22sb            0          0        0          0
## z23sb_vs_z23nosb        328        179        0          0
## z22sb_vs_z22nosb        279        150        0          0
## z23sb_vs_sb               5          4        0          0
## z22sb_vs_sb               7          6        0          0
## z23sb_vs_uninf          267        122        0          0
## z22sb_vs_uninf          226        163        0          0
## sb_vs_uninf             152        175        0          0

u937_highsig <- extract_significant_genes(
  u937_table, min_mean_exprs = high_expression, exprs_column = high_expression_column,
  excel = glue("analyses/macrophage_de/sig_tables/u937_drug_zymo_highsig-v{ver}.xlsx"))
u937_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
## z23nosb_vs_uninf          0          3        0          4        0          4
## z22nosb_vs_uninf          0          2        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
##                    ebseq_up ebseq_down basic_up basic_down
## z23nosb_vs_uninf          2          4        0          0
## z22nosb_vs_uninf          0          2        0          0
## z23nosb_vs_z22nosb        0         25        0          0
## z23sb_vs_z22sb            0          0        0          0
## z23sb_vs_z23nosb        182        119        0          0
## z22sb_vs_z22nosb        139        103        0          0
## z23sb_vs_sb               0          0        0          0
## z22sb_vs_sb               0          0        0          0
## z23sb_vs_uninf          161         83        0          0
## z22sb_vs_uninf          136        112        0          0
## sb_vs_uninf              89        139        0          0

u937_lesssig <- extract_significant_genes(
  u937_table, lfc = 0.6,
  excel = glue("analyses/macrophage_de/sig_tables/u937_drug_zymo_lesssig-v{ver}.xlsx"))
u937_lesssig
## A set of genes deemed significant according to limma, edger, deseq, ebseq, basic.
## The parameters defining significant were:
## LFC cutoff: 0.6 adj P cutoff: 0.05
##                    limma_up limma_down edger_up edger_down deseq_up deseq_down
## z23nosb_vs_uninf          1          5        6         13        2          8
## z22nosb_vs_uninf          0          7        0         15        0          2
## z23nosb_vs_z22nosb       17         10       40         23        2          2
## z23sb_vs_z22sb            1          3        7          3        1          0
## z23sb_vs_z23nosb        478        433      627        416      499        421
## z22sb_vs_z22nosb        568        506      739        451      678        467
## z23sb_vs_sb               0          1        4          3        0          2
## z22sb_vs_sb               1         16        7         26        2         11
## z23sb_vs_uninf          487        472      600        439      566        409
## z22sb_vs_uninf          517        568      641        522      596        500
## sb_vs_uninf             430        400      535        373      466        345
##                    ebseq_up ebseq_down basic_up basic_down
## z23nosb_vs_uninf         14        113        0          0
## z22nosb_vs_uninf          0         27        0          0
## z23nosb_vs_z22nosb       78        427        0          0
## z23sb_vs_z22sb            5          1        0          0
## z23sb_vs_z23nosb        765        656        0          0
## z22sb_vs_z22nosb        582        442        0          0
## z23sb_vs_sb              20         10        0          0
## z22sb_vs_sb              26         18        0          0
## z23sb_vs_uninf          488        332        0          0
## z22sb_vs_uninf          406        488        0          0
## sb_vs_uninf             160        209        0          0

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

In the following block, I will jump back to the macrophage samples and look for genes which are shared/unique when comparing z2.3/z2.2 for the drug treated samples and the untreated samples.

upset_plots_hs_macr <- upsetr_sig(
  hs_macr_sig, both = TRUE,
  contrasts = c("z23sb_vs_z22sb", "z23nosb_vs_z22nosb"))
upset_plots_hs_macr[["both"]]
## [1] TRUE
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)
shared_gp[["pvalue_plots"]][["MF"]]
## NULL
shared_gp[["pvalue_plots"]][["BP"]]
## NULL
shared_gp[["pvalue_plots"]][["REAC"]]

drug_genes <- attr(groups, "elements")[groups[["z23sb_vs_z22sb"]]] %>%
  gsub(pattern = "^gene:", replacement = "")
drugonly_gp <- simple_gprofiler(drug_genes)
drugonly_gp[["pvalue_plots"]][["BP"]]
## NULL

I want to try something, directly include the u937 data in this. Thus, in the following block I will repeat but compare all samples and the U937 using the same logic.

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   73     DFrame     S4  
## macr_z22nosb_vs_uninf   73     DFrame     S4  
## macr_z23nosb_vs_z22nosb 73     DFrame     S4  
## macr_z23sb_vs_z22sb     73     DFrame     S4  
## macr_z23sb_vs_z23nosb   73     DFrame     S4  
## macr_z22sb_vs_z22nosb   73     DFrame     S4  
## macr_z23sb_vs_sb        73     DFrame     S4  
## macr_z22sb_vs_sb        73     DFrame     S4  
## macr_z23sb_vs_uninf     73     DFrame     S4  
## macr_z22sb_vs_uninf     73     DFrame     S4  
## macr_sb_vs_uninf        73     DFrame     S4  
## macr_extra_z2322         0     data.frame list
## macr_extra_drugnodrug    0     data.frame list
## u937_z23nosb_vs_uninf   64     DFrame     S4  
## u937_z22nosb_vs_uninf   64     DFrame     S4  
## u937_z23nosb_vs_z22nosb 64     DFrame     S4  
## u937_z23sb_vs_z22sb     64     DFrame     S4  
## u937_z23sb_vs_z23nosb   64     DFrame     S4  
## u937_z22sb_vs_z22nosb   64     DFrame     S4  
## u937_z23sb_vs_sb        64     DFrame     S4  
## u937_z22sb_vs_sb        64     DFrame     S4  
## u937_z23sb_vs_uninf     64     DFrame     S4  
## u937_z22sb_vs_uninf     64     DFrame     S4  
## u937_sb_vs_uninf        64     DFrame     S4
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"]]
## [1] TRUE

7.1 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"]]

7.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"]]

8 Add donor to the contrasts, no sva

In the following block, I will change the sample condition to include the donor.

no_power_fact <- paste0(colData(hs_macr)[["donor"]], "_",
                        colData(hs_macr)[["condition"]])
table(colData(hs_macr)[["donor"]])
## 
## d01 d02 d09 d81 
##  13  14  13  14
table(no_power_fact)
## no_power_fact
##    d01_inf_sb_z22    d01_inf_sb_z23       d01_inf_z22       d01_inf_z23 
##                 3                 3                 2                 3 
##    d01_uninf_none d01_uninf_sb_none    d02_inf_sb_z22    d02_inf_sb_z23 
##                 1                 1                 3                 3 
##       d02_inf_z22       d02_inf_z23    d02_uninf_none d02_uninf_sb_none 
##                 3                 3                 1                 1 
##    d09_inf_sb_z22    d09_inf_sb_z23       d09_inf_z22       d09_inf_z23 
##                 3                 2                 3                 3 
##    d09_uninf_none d09_uninf_sb_none    d81_inf_sb_z22    d81_inf_sb_z23 
##                 1                 1                 3                 3 
##       d81_inf_z22       d81_inf_z23    d81_uninf_none d81_uninf_sb_none 
##                 3                 3                 1                 1
hs_nopower <- set_conditions(hs_macr, fact = no_power_fact)
## The numbers of samples by condition are:
## 
##    d01_inf_sb_z22    d01_inf_sb_z23       d01_inf_z22       d01_inf_z23 
##                 3                 3                 2                 3 
##    d01_uninf_none d01_uninf_sb_none    d02_inf_sb_z22    d02_inf_sb_z23 
##                 1                 1                 3                 3 
##       d02_inf_z22       d02_inf_z23    d02_uninf_none d02_uninf_sb_none 
##                 3                 3                 1                 1 
##    d09_inf_sb_z22    d09_inf_sb_z23       d09_inf_z22       d09_inf_z23 
##                 3                 2                 3                 3 
##    d09_uninf_none d09_uninf_sb_none    d81_inf_sb_z22    d81_inf_sb_z23 
##                 1                 1                 3                 3 
##       d81_inf_z22       d81_inf_z23    d81_uninf_none d81_uninf_sb_none 
##                 3                 3                 1                 1
hs_nopower <- subset_se(hs_nopower, subset = "macrophagezymodeme!='none'")
hs_nopower_nosva_de <- all_pairwise(hs_nopower, model_svs = FALSE, filter = TRUE)
## d01_inf_sb_z22 d01_inf_sb_z23    d01_inf_z22    d01_inf_z23 d02_inf_sb_z22 
##              3              3              2              3              3 
## d02_inf_sb_z23    d02_inf_z22    d02_inf_z23 d09_inf_sb_z22 d09_inf_sb_z23 
##              3              3              3              3              2 
##    d09_inf_z22    d09_inf_z23 d81_inf_sb_z22 d81_inf_sb_z23    d81_inf_z22 
##              3              3              3              3              3 
##    d81_inf_z23 
##              3 
## z2.2 z2.3 
##   23   23
## Warning: attributes are not identical across measure variables; they will be
## dropped
## Running normalize_se.
## Removing 9761 low-count genes (11720 remaining).
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## I think this is failing? SummarizedExperiment
## Basic step 0/3: Transforming data.
## Running normalize_se.
## Setting 32467 entries to zero.
## converting counts to integer mode
## Error in checkFullRank(modelMatrix) : 
##   the model matrix is not full rank, so the model cannot be fit as specified.
##   One or more variables or interaction terms in the design formula are linear
##   combinations of the others and must be removed.
## 
##   Please read the vignette section 'Model matrix not full rank':
## 
##   vignette('DESeq2')
## Coefficients not estimable: batchz23
## Warning: Partial NA coefficients for 11720 probe(s)
## Error in variancePartition::dream(exprObj = voom_result, formula = model_fstring,  : 
##   Design matrix is singular, covariates are very correlated
## conditions
## d01_inf_sb_z22 d01_inf_sb_z23    d01_inf_z22    d01_inf_z23 d02_inf_sb_z22 
##              3              3              2              3              3 
## d02_inf_sb_z23    d02_inf_z22    d02_inf_z23 d09_inf_sb_z22 d09_inf_sb_z23 
##              3              3              3              3              2 
##    d09_inf_z22    d09_inf_z23 d81_inf_sb_z22 d81_inf_sb_z23    d81_inf_z22 
##              3              3              3              3              3 
##    d81_inf_z23 
##              3 
## Error in glmFit.default(y, design = design, dispersion = dispersion, offset = offset,  : 
##   Design matrix not of full rank.  The following coefficients not estimable:
##  batchz23
## Warning in edger_pairwise(...): estimateGLMCommonDisp() failed.  Trying again
## with estimateDisp().
## Warning in edger_pairwise(...): There was a failure when doing the estimations.
## There was a failure when doing the estimations, using estimateDisp().
## Error in glmFit.default(sely, design, offset = seloffset, dispersion = 0.05,  : 
##   Design matrix not of full rank.  The following coefficients not estimable:
##  batchz23
## conditions
## d01_inf_sb_z22 d01_inf_sb_z23    d01_inf_z22    d01_inf_z23 d02_inf_sb_z22 
##              3              3              2              3              3 
## d02_inf_sb_z23    d02_inf_z22    d02_inf_z23 d09_inf_sb_z22 d09_inf_sb_z23 
##              3              3              3              3              2 
##    d09_inf_z22    d09_inf_z23 d81_inf_sb_z22 d81_inf_sb_z23    d81_inf_z22 
##              3              3              3              3              3 
##    d81_inf_z23 
##              3 
## Coefficients not estimable: batchz23
## Warning: Partial NA coefficients for 11720 probe(s)
## Coefficients not estimable: batchz23
## Warning: Partial NA coefficients for 11720 probe(s)
## conditions
## d01_inf_sb_z22 d01_inf_sb_z23    d01_inf_z22    d01_inf_z23 d02_inf_sb_z22 
##              3              3              2              3              3 
## d02_inf_sb_z23    d02_inf_z22    d02_inf_z23 d09_inf_sb_z22 d09_inf_sb_z23 
##              3              3              3              3              2 
##    d09_inf_z22    d09_inf_z23 d81_inf_sb_z22 d81_inf_sb_z23    d81_inf_z22 
##              3              3              3              3              3 
##    d81_inf_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("analyses/macrophage_de/de_tables/hs_nopower_table-v{ver}.xlsx"))
## The keepers has no elements in the coefficients.
## Here are the keepers: d01infz23, d01infz22, d01infsbz23, d01infsbz22, d02infz23, d02infz22, d02infsbz23, d02infsbz22, d09infz23, d09infz22, d09infsbz23, d09infsbz22, d81infz23, d81infz22, d81infsbz23, d81infsbz22
## Here are the coefficients: d81_inf_z23, d81_inf_z22, d81_inf_z23, d81_inf_sb_z23, d81_inf_z22, d81_inf_sb_z23, d81_inf_z23, d81_inf_sb_z22, d81_inf_z22, d81_inf_sb_z22, d81_inf_sb_z23, d81_inf_sb_z22, d81_inf_z23, d09_inf_z23, d81_inf_z22, d09_inf_z23, d81_inf_sb_z23, d09_inf_z23, d81_inf_sb_z22, d09_inf_z23, d81_inf_z23, d09_inf_z22, d81_inf_z22, d09_inf_z22, d81_inf_sb_z23, d09_inf_z22, d81_inf_sb_z22, d09_inf_z22, d09_inf_z23, d09_inf_z22, d81_inf_z23, d09_inf_sb_z23, d81_inf_z22, d09_inf_sb_z23, d81_inf_sb_z23, d09_inf_sb_z23, d81_inf_sb_z22, d09_inf_sb_z23, d09_inf_z23, d09_inf_sb_z23, d09_inf_z22, d09_inf_sb_z23, d81_inf_z23, d09_inf_sb_z22, d81_inf_z22, d09_inf_sb_z22, d81_inf_sb_z23, d09_inf_sb_z22, d81_inf_sb_z22, d09_inf_sb_z22, d09_inf_z23, d09_inf_sb_z22, d09_inf_z22, d09_inf_sb_z22, d09_inf_sb_z23, d09_inf_sb_z22, d81_inf_z23, d02_inf_z23, d81_inf_z22, d02_inf_z23, d81_inf_sb_z23, d02_inf_z23, d81_inf_sb_z22, d02_inf_z23, d09_inf_z23, d02_inf_z23, d09_inf_z22, d02_inf_z23, d09_inf_sb_z23, d02_inf_z23, d09_inf_sb_z22, d02_inf_z23, d81_inf_z23, d02_inf_z22, d81_inf_z22, d02_inf_z22, d81_inf_sb_z23, d02_inf_z22, d81_inf_sb_z22, d02_inf_z22, d09_inf_z23, d02_inf_z22, d09_inf_z22, d02_inf_z22, d09_inf_sb_z23, d02_inf_z22, d09_inf_sb_z22, d02_inf_z22, d02_inf_z23, d02_inf_z22, d81_inf_z23, d02_inf_sb_z23, d81_inf_z22, d02_inf_sb_z23, d81_inf_sb_z23, d02_inf_sb_z23, d81_inf_sb_z22, d02_inf_sb_z23, d09_inf_z23, d02_inf_sb_z23, d09_inf_z22, d02_inf_sb_z23, d09_inf_sb_z23, d02_inf_sb_z23, d09_inf_sb_z22, d02_inf_sb_z23, d02_inf_z23, d02_inf_sb_z23, d02_inf_z22, d02_inf_sb_z23, d81_inf_z23, d02_inf_sb_z22, d81_inf_z22, d02_inf_sb_z22, d81_inf_sb_z23, d02_inf_sb_z22, d81_inf_sb_z22, d02_inf_sb_z22, d09_inf_z23, d02_inf_sb_z22, d09_inf_z22, d02_inf_sb_z22, d09_inf_sb_z23, d02_inf_sb_z22, d09_inf_sb_z22, d02_inf_sb_z22, d02_inf_z23, d02_inf_sb_z22, d02_inf_z22, d02_inf_sb_z22, d02_inf_sb_z23, d02_inf_sb_z22, d81_inf_z23, d01_inf_z23, d81_inf_z22, d01_inf_z23, d81_inf_sb_z23, d01_inf_z23, d81_inf_sb_z22, d01_inf_z23, d09_inf_z23, d01_inf_z23, d09_inf_z22, d01_inf_z23, d09_inf_sb_z23, d01_inf_z23, d09_inf_sb_z22, d01_inf_z23, d02_inf_z23, d01_inf_z23, d02_inf_z22, d01_inf_z23, d02_inf_sb_z23, d01_inf_z23, d02_inf_sb_z22, d01_inf_z23, d81_inf_z23, d01_inf_z22, d81_inf_z22, d01_inf_z22, d81_inf_sb_z23, d01_inf_z22, d81_inf_sb_z22, d01_inf_z22, d09_inf_z23, d01_inf_z22, d09_inf_z22, d01_inf_z22, d09_inf_sb_z23, d01_inf_z22, d09_inf_sb_z22, d01_inf_z22, d02_inf_z23, d01_inf_z22, d02_inf_z22, d01_inf_z22, d02_inf_sb_z23, d01_inf_z22, d02_inf_sb_z22, d01_inf_z22, d01_inf_z23, d01_inf_z22, d81_inf_z23, d01_inf_sb_z23, d81_inf_z22, d01_inf_sb_z23, d81_inf_sb_z23, d01_inf_sb_z23, d81_inf_sb_z22, d01_inf_sb_z23, d09_inf_z23, d01_inf_sb_z23, d09_inf_z22, d01_inf_sb_z23, d09_inf_sb_z23, d01_inf_sb_z23, d09_inf_sb_z22, d01_inf_sb_z23, d02_inf_z23, d01_inf_sb_z23, d02_inf_z22, d01_inf_sb_z23, d02_inf_sb_z23, d01_inf_sb_z23, d02_inf_sb_z22, d01_inf_sb_z23, d01_inf_z23, d01_inf_sb_z23, d01_inf_z22, d01_inf_sb_z23, d81_inf_z23, d01_inf_sb_z22, d81_inf_z22, d01_inf_sb_z22, d81_inf_sb_z23, d01_inf_sb_z22, d81_inf_sb_z22, d01_inf_sb_z22, d09_inf_z23, d01_inf_sb_z22, d09_inf_z22, d01_inf_sb_z22, d09_inf_sb_z23, d01_inf_sb_z22, d09_inf_sb_z22, d01_inf_sb_z22, d02_inf_z23, d01_inf_sb_z22, d02_inf_z22, d01_inf_sb_z22, d02_inf_sb_z23, d01_inf_sb_z22, d02_inf_sb_z22, d01_inf_sb_z22, d01_inf_z23, d01_inf_sb_z22, d01_inf_z22, d01_inf_sb_z22, d01_inf_sb_z23, d01_inf_sb_z22
## Error in extract_keepers(extracted, keepers, table_names, all_coefficients, : Unable to find the set of contrasts to keep, fix this and try again.
## extra_contrasts = extra)
hs_nopower_nosva_sig <- extract_significant_genes(
  hs_nopower_nosva_table,
  excel = glue("analyses/macrophage_de/sig_tables/hs_nopower_nosva_sig-v{ver}.xlsx"))
## Error: object 'hs_nopower_nosva_table' not found
d01d02_zymo_nosva_comp <- merge(hs_nopower_nosva_table[["data"]][["d01_zymo"]],
                                hs_nopower_nosva_table[["data"]][["d02_zymo"]],
                                by = "row.names")
## Error: object 'hs_nopower_nosva_table' not found
d0102_zymo_nosva_plot <- plot_linear_scatter(d01d02_zymo_nosva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'd01d02_zymo_nosva_comp' not found
d0102_zymo_nosva_plot[["scatter"]]
## Error: object 'd0102_zymo_nosva_plot' not found
d0102_zymo_nosva_plot[["correlation"]]
## Error: object 'd0102_zymo_nosva_plot' not found
d0102_zymo_nosva_plot[["lm_rsq"]]
## Error: object 'd0102_zymo_nosva_plot' not found
d09d81_zymo_nosva_comp <- merge(hs_nopower_nosva_table[["data"]][["d09_zymo"]],
                                hs_nopower_nosva_table[["data"]][["d81_zymo"]],
                                by = "row.names")
## Error: object 'hs_nopower_nosva_table' not found
d0981_zymo_nosva_plot <- plot_linear_scatter(d09d81_zymo_nosva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'd09d81_zymo_nosva_comp' not found
d0981_zymo_nosva_plot[["scatter"]]
## Error: object 'd0981_zymo_nosva_plot' not found
d0981_zymo_nosva_plot[["correlation"]]
## Error: object 'd0981_zymo_nosva_plot' not found
d0981_zymo_nosva_plot[["lm_rsq"]]
## Error: object 'd0981_zymo_nosva_plot' not found
d01d81_zymo_nosva_comp <- merge(hs_nopower_nosva_table[["data"]][["d01_zymo"]],
                                hs_nopower_nosva_table[["data"]][["d81_zymo"]],
                                by = "row.names")
## Error: object 'hs_nopower_nosva_table' not found
d0181_zymo_nosva_plot <- plot_linear_scatter(d01d81_zymo_nosva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'd01d81_zymo_nosva_comp' not found
d0181_zymo_nosva_plot[["scatter"]]
## Error: object 'd0181_zymo_nosva_plot' not found
d0181_zymo_nosva_plot[["correlation"]]
## Error: object 'd0181_zymo_nosva_plot' not found
d0181_zymo_nosva_plot[["lm_rsq"]]
## Error: object 'd0181_zymo_nosva_plot' not found
upset_plots_nosva <- upsetr_sig(hs_nopower_nosva_sig, both = TRUE,
                                contrasts = c("d01_zymo", "d02_zymo", "d09_zymo", "d81_zymo"))
## Error: object 'hs_nopower_nosva_sig' not found
upset_plots_nosva[["up"]]
## Error: object 'upset_plots_nosva' not found
upset_plots_nosva[["down"]]
## Error: object 'upset_plots_nosva' not found
upset_plots_nosva[["both"]]
## Error: object 'upset_plots_nosva' not found
## The 7th element in the both groups list is the set shared among all donors.
## I don't feel like writing out x:y:z:a
groups <- upset_plots_nosva[["both_groups"]]
## Error: object 'upset_plots_nosva' not found
shared_genes <- attr(groups, "elements")[groups[[7]]] %>%
  gsub(pattern = "^gene:", replacement = "")
## Error in groups[[7]]: subscript out of bounds
shared_gp <- simple_gprofiler(shared_genes)
shared_gp[["pvalue_plots"]][["MF"]]
## NULL
shared_gp[["pvalue_plots"]][["BP"]]
## NULL
shared_gp[["pvalue_plots"]][["REAC"]]

shared_gp[["pvalue_plots"]][["WP"]]

9 Add donor to the contrasts, sva

Same deal as the last block, but this time add SVA into the mix!

hs_nopower_sva_de <- all_pairwise(hs_nopower, model_svs = "svaseq",
                                  model_fstring = "~ 0 + condition", filter = TRUE)
## d01_inf_sb_z22 d01_inf_sb_z23    d01_inf_z22    d01_inf_z23 d02_inf_sb_z22 
##              3              3              2              3              3 
## d02_inf_sb_z23    d02_inf_z22    d02_inf_z23 d09_inf_sb_z22 d09_inf_sb_z23 
##              3              3              3              3              2 
##    d09_inf_z22    d09_inf_z23 d81_inf_sb_z22 d81_inf_sb_z23    d81_inf_z22 
##              3              3              3              3              3 
##    d81_inf_z23 
##              3
## Running normalize_se.
## Removing 9761 low-count genes (11720 remaining).
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## I think this is failing? SummarizedExperiment
## Basic step 0/3: Transforming data.
## Running normalize_se.
## Setting 32467 entries to zero.
## This received a matrix of SVs.
## converting counts to integer mode
##   the design formula contains one or more numeric variables with integer values,
##   specifying a model with increasing fold change for higher values.
##   did you mean for this to be a factor? if so, first convert
##   this variable to a factor using the factor() function
##   the design formula contains one or more numeric variables with integer values,
##   specifying a model with increasing fold change for higher values.
##   did you mean for this to be a factor? if so, first convert
##   this variable to a factor using the factor() function
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## Warning in createContrastL(objFlt$formula, objFlt$data, L): Contrasts with only
## a single non-zero term are already evaluated by default.
## conditions
## d01_inf_sb_z22 d01_inf_sb_z23    d01_inf_z22    d01_inf_z23 d02_inf_sb_z22 
##              3              3              2              3              3 
## d02_inf_sb_z23    d02_inf_z22    d02_inf_z23 d09_inf_sb_z22 d09_inf_sb_z23 
##              3              3              3              3              2 
##    d09_inf_z22    d09_inf_z23 d81_inf_sb_z22 d81_inf_sb_z23    d81_inf_z22 
##              3              3              3              3              3 
##    d81_inf_z23 
##              3
## conditions
## d01_inf_sb_z22 d01_inf_sb_z23    d01_inf_z22    d01_inf_z23 d02_inf_sb_z22 
##              3              3              2              3              3 
## d02_inf_sb_z23    d02_inf_z22    d02_inf_z23 d09_inf_sb_z22 d09_inf_sb_z23 
##              3              3              3              3              2 
##    d09_inf_z22    d09_inf_z23 d81_inf_sb_z22 d81_inf_sb_z23    d81_inf_z22 
##              3              3              3              3              3 
##    d81_inf_z23 
##              3
## conditions
## d01_inf_sb_z22 d01_inf_sb_z23    d01_inf_z22    d01_inf_z23 d02_inf_sb_z22 
##              3              3              2              3              3 
## d02_inf_sb_z23    d02_inf_z22    d02_inf_z23 d09_inf_sb_z22 d09_inf_sb_z23 
##              3              3              3              3              2 
##    d09_inf_z22    d09_inf_z23 d81_inf_sb_z22 d81_inf_sb_z23    d81_inf_z22 
##              3              3              3              3              3 
##    d81_inf_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_sva_table <- combine_de_tables(
  hs_nopower_sva_de, keepers = nopower_keepers,
  excel = glue("analyses/macrophage_de/de_tables/hs_nopower_table-v{ver}.xlsx"))
## The keepers has no elements in the coefficients.
## Here are the keepers: d01infz23, d01infz22, d01infsbz23, d01infsbz22, d02infz23, d02infz22, d02infsbz23, d02infsbz22, d09infz23, d09infz22, d09infsbz23, d09infsbz22, d81infz23, d81infz22, d81infsbz23, d81infsbz22
## Here are the coefficients: d81_inf_z23, d81_inf_z22, d81_inf_z23, d81_inf_sb_z23, d81_inf_z22, d81_inf_sb_z23, d81_inf_z23, d81_inf_sb_z22, d81_inf_z22, d81_inf_sb_z22, d81_inf_sb_z23, d81_inf_sb_z22, d81_inf_z23, d09_inf_z23, d81_inf_z22, d09_inf_z23, d81_inf_sb_z23, d09_inf_z23, d81_inf_sb_z22, d09_inf_z23, d81_inf_z23, d09_inf_z22, d81_inf_z22, d09_inf_z22, d81_inf_sb_z23, d09_inf_z22, d81_inf_sb_z22, d09_inf_z22, d09_inf_z23, d09_inf_z22, d81_inf_z23, d09_inf_sb_z23, d81_inf_z22, d09_inf_sb_z23, d81_inf_sb_z23, d09_inf_sb_z23, d81_inf_sb_z22, d09_inf_sb_z23, d09_inf_z23, d09_inf_sb_z23, d09_inf_z22, d09_inf_sb_z23, d81_inf_z23, d09_inf_sb_z22, d81_inf_z22, d09_inf_sb_z22, d81_inf_sb_z23, d09_inf_sb_z22, d81_inf_sb_z22, d09_inf_sb_z22, d09_inf_z23, d09_inf_sb_z22, d09_inf_z22, d09_inf_sb_z22, d09_inf_sb_z23, d09_inf_sb_z22, d81_inf_z23, d02_inf_z23, d81_inf_z22, d02_inf_z23, d81_inf_sb_z23, d02_inf_z23, d81_inf_sb_z22, d02_inf_z23, d09_inf_z23, d02_inf_z23, d09_inf_z22, d02_inf_z23, d09_inf_sb_z23, d02_inf_z23, d09_inf_sb_z22, d02_inf_z23, d81_inf_z23, d02_inf_z22, d81_inf_z22, d02_inf_z22, d81_inf_sb_z23, d02_inf_z22, d81_inf_sb_z22, d02_inf_z22, d09_inf_z23, d02_inf_z22, d09_inf_z22, d02_inf_z22, d09_inf_sb_z23, d02_inf_z22, d09_inf_sb_z22, d02_inf_z22, d02_inf_z23, d02_inf_z22, d81_inf_z23, d02_inf_sb_z23, d81_inf_z22, d02_inf_sb_z23, d81_inf_sb_z23, d02_inf_sb_z23, d81_inf_sb_z22, d02_inf_sb_z23, d09_inf_z23, d02_inf_sb_z23, d09_inf_z22, d02_inf_sb_z23, d09_inf_sb_z23, d02_inf_sb_z23, d09_inf_sb_z22, d02_inf_sb_z23, d02_inf_z23, d02_inf_sb_z23, d02_inf_z22, d02_inf_sb_z23, d81_inf_z23, d02_inf_sb_z22, d81_inf_z22, d02_inf_sb_z22, d81_inf_sb_z23, d02_inf_sb_z22, d81_inf_sb_z22, d02_inf_sb_z22, d09_inf_z23, d02_inf_sb_z22, d09_inf_z22, d02_inf_sb_z22, d09_inf_sb_z23, d02_inf_sb_z22, d09_inf_sb_z22, d02_inf_sb_z22, d02_inf_z23, d02_inf_sb_z22, d02_inf_z22, d02_inf_sb_z22, d02_inf_sb_z23, d02_inf_sb_z22, d81_inf_z23, d01_inf_z23, d81_inf_z22, d01_inf_z23, d81_inf_sb_z23, d01_inf_z23, d81_inf_sb_z22, d01_inf_z23, d09_inf_z23, d01_inf_z23, d09_inf_z22, d01_inf_z23, d09_inf_sb_z23, d01_inf_z23, d09_inf_sb_z22, d01_inf_z23, d02_inf_z23, d01_inf_z23, d02_inf_z22, d01_inf_z23, d02_inf_sb_z23, d01_inf_z23, d02_inf_sb_z22, d01_inf_z23, d81_inf_z23, d01_inf_z22, d81_inf_z22, d01_inf_z22, d81_inf_sb_z23, d01_inf_z22, d81_inf_sb_z22, d01_inf_z22, d09_inf_z23, d01_inf_z22, d09_inf_z22, d01_inf_z22, d09_inf_sb_z23, d01_inf_z22, d09_inf_sb_z22, d01_inf_z22, d02_inf_z23, d01_inf_z22, d02_inf_z22, d01_inf_z22, d02_inf_sb_z23, d01_inf_z22, d02_inf_sb_z22, d01_inf_z22, d01_inf_z23, d01_inf_z22, d81_inf_z23, d01_inf_sb_z23, d81_inf_z22, d01_inf_sb_z23, d81_inf_sb_z23, d01_inf_sb_z23, d81_inf_sb_z22, d01_inf_sb_z23, d09_inf_z23, d01_inf_sb_z23, d09_inf_z22, d01_inf_sb_z23, d09_inf_sb_z23, d01_inf_sb_z23, d09_inf_sb_z22, d01_inf_sb_z23, d02_inf_z23, d01_inf_sb_z23, d02_inf_z22, d01_inf_sb_z23, d02_inf_sb_z23, d01_inf_sb_z23, d02_inf_sb_z22, d01_inf_sb_z23, d01_inf_z23, d01_inf_sb_z23, d01_inf_z22, d01_inf_sb_z23, d81_inf_z23, d01_inf_sb_z22, d81_inf_z22, d01_inf_sb_z22, d81_inf_sb_z23, d01_inf_sb_z22, d81_inf_sb_z22, d01_inf_sb_z22, d09_inf_z23, d01_inf_sb_z22, d09_inf_z22, d01_inf_sb_z22, d09_inf_sb_z23, d01_inf_sb_z22, d09_inf_sb_z22, d01_inf_sb_z22, d02_inf_z23, d01_inf_sb_z22, d02_inf_z22, d01_inf_sb_z22, d02_inf_sb_z23, d01_inf_sb_z22, d02_inf_sb_z22, d01_inf_sb_z22, d01_inf_z23, d01_inf_sb_z22, d01_inf_z22, d01_inf_sb_z22, d01_inf_sb_z23, d01_inf_sb_z22
## Error in extract_keepers(extracted, keepers, table_names, all_coefficients, : Unable to find the set of contrasts to keep, fix this and try again.
## extra_contrasts = extra)
hs_nopower_sva_sig <- extract_significant_genes(
  hs_nopower_sva_table,
  excel = glue("analyses/macrophage_de/sig_tables/hs_nopower_sva_sig-v{ver}.xlsx"))
## Error: object 'hs_nopower_sva_table' not found
d01d02_zymo_sva_comp <- merge(hs_nopower_sva_table[["data"]][["d01_zymo"]],
                              hs_nopower_sva_table[["data"]][["d02_zymo"]],
                              by = "row.names")
## Error: object 'hs_nopower_sva_table' not found
d0102_zymo_sva_plot <- plot_linear_scatter(d01d02_zymo_sva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'd01d02_zymo_sva_comp' not found
d0102_zymo_sva_plot[["scatter"]]
## Error: object 'd0102_zymo_sva_plot' not found
d0102_zymo_sva_plot[["correlation"]]
## Error: object 'd0102_zymo_sva_plot' not found
d0102_zymo_sva_plot[["lm_rsq"]]
## Error: object 'd0102_zymo_sva_plot' not found
d09d81_zymo_sva_comp <- merge(hs_nopower_sva_table[["data"]][["d09_zymo"]],
                              hs_nopower_sva_table[["data"]][["d81_zymo"]],
                              by = "row.names")
## Error: object 'hs_nopower_sva_table' not found
d0981_zymo_sva_plot <- plot_linear_scatter(d09d81_zymo_sva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'd09d81_zymo_sva_comp' not found
d0981_zymo_sva_plot[["scatter"]]
## Error: object 'd0981_zymo_sva_plot' not found
d0981_zymo_sva_plot[["correlation"]]
## Error: object 'd0981_zymo_sva_plot' not found
d0981_zymo_sva_plot[["lm_rsq"]]
## Error: object 'd0981_zymo_sva_plot' not found
d01d81_zymo_sva_comp <- merge(hs_nopower_sva_table[["data"]][["d01_zymo"]],
                              hs_nopower_sva_table[["data"]][["d81_zymo"]],
                              by = "row.names")
## Error: object 'hs_nopower_sva_table' not found
d0181_zymo_sva_plot <- plot_linear_scatter(d01d81_zymo_sva_comp[, c("deseq_logfc.x", "deseq_logfc.y")])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'd01d81_zymo_sva_comp' not found
d0181_zymo_sva_plot[["scatter"]]
## Error: object 'd0181_zymo_sva_plot' not found
d0181_zymo_sva_plot[["correlation"]]
## Error: object 'd0181_zymo_sva_plot' not found
d0181_zymo_sva_plot[["lm_rsq"]]
## Error: object 'd0181_zymo_sva_plot' not found
upset_plots_sva <- upsetr_sig(hs_nopower_sva_sig, both = TRUE,
                              contrasts = c("d01_zymo", "d02_zymo", "d09_zymo", "d81_zymo"))
## Error: object 'hs_nopower_sva_sig' not found
upset_plots_sva[["up"]]
## Error: object 'upset_plots_sva' not found
upset_plots_sva[["down"]]
## Error: object 'upset_plots_sva' not found
upset_plots_sva[["both"]]
## Error: object 'upset_plots_sva' not found
## The 7th element in the both groups list is the set shared among all donors.
## I don't feel like writing out x:y:z:a
groups <- upset_plots_sva[["both_groups"]]
## Error: object 'upset_plots_sva' not found
shared_genes <- attr(groups, "elements")[groups[[7]]] %>%
  gsub(pattern = "^gene:", replacement = "")
## Error in groups[[7]]: subscript out of bounds
shared_gp <- simple_gprofiler(shared_genes)
shared_gp[["pvalue_plots"]][["MF"]]
## NULL
shared_gp[["pvalue_plots"]][["BP"]]
## NULL
shared_gp[["pvalue_plots"]][["REAC"]]

shared_gp[["pvalue_plots"]][["WP"]]

10 Donor comparison

Now compare the donors to each other directly.

hs_donors <- set_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_svs = "svaseq",
                         model_fstring = "~ 0 + condition", filter = TRUE)
## d01 d02 d09 d81 
##  13  14  13  14
## Running normalize_se.
## Removing 9725 low-count genes (11756 remaining).
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## I think this is failing? SummarizedExperiment
## Basic step 0/3: Transforming data.
## Running normalize_se.
## Setting 40036 entries to zero.
## This received a matrix of SVs.
## converting counts to integer mode
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## Warning in createContrastL(objFlt$formula, objFlt$data, L): Contrasts with only
## a single non-zero term are already evaluated by default.
## conditions
## d01 d02 d09 d81 
##  13  14  13  14
## conditions
## d01 d02 d09 d81 
##  13  14  13  14
## conditions
## d01 d02 d09 d81 
##  13  14  13  14

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 6 comparisons.
donor_table <- combine_de_tables(
  donor_de,
  excel = glue("analyses/macrophage_de/de_tables/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         310           389         318           381         350
## 2 d09_vs_d01         532           457         533           451         513
## 3 d81_vs_d01         668           753         669           744         663
## 4 d09_vs_d02         414           267         412           272         373
## 5 d81_vs_d02         572           650         561           658         532
## 6 d81_vs_d09         221           421         212           423         218
##   limma_sigdown
## 1           359
## 2           467
## 3           753
## 4           309
## 5           672
## 6           416
## Plot describing unique/shared genes in a differential expression table.

donor_sig <- extract_significant_genes(
  donor_table,
  excel = glue("analyses/macrophage_de/sig_tables/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      350        359      318        381      310        389      242
## d09_vs_d01      513        467      533        451      532        457      485
## d81_vs_d01      663        753      669        744      668        753      576
## d09_vs_d02      373        309      412        272      414        267      211
## d81_vs_d02      532        672      561        658      572        650      299
## d81_vs_d09      218        416      212        423      221        421       86
##            ebseq_down basic_up basic_down
## d02_vs_d01        136      169        185
## d09_vs_d01        190      334        257
## d81_vs_d01        385      435        446
## d09_vs_d02        115      165        105
## d81_vs_d02        378      235        291
## d81_vs_d09        200       73        150

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

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

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

I am reasonably certain this is the place to check that z23no drug / uninfected has the expected set of genes and that there is or is not a reactome result.

Reproducibility note: Given that this is entirely dependent on an online service, I must assume that the results will change over time; in addition their web servers undergo maintenance regularly, which may result in systematic failure of these analyses. I like gProfiler quite a lot for this type of stuff, but this is an important caveat.

Conversely, the clusterProfiler results later depend on a consistent orgdb annotation set (or reactome or whatever); those versions are fixed by the container installation.

all_gp <- all_gprofiler(hs_macr_sig, enrich_id_column = "hgnc_symbol")
for (g in seq_len(length(all_gp))) {
  name <- names(all_gp)[g]
  datum <- all_gp[[name]]
  filename <- glue("analyses/macrophage_de/gprofiler/{name}_gprofiler-v{ver}.xlsx")
  written <- sm(write_gprofiler_data(datum, excel = filename))
}
lesssig_all_gp <- all_gprofiler(hs_macr_lesssig, enrich_id_column = "hgnc_symbol")
for (g in seq_len(length(lesssig_all_gp))) {
  name <- names(lesssig_all_gp)[g]
  datum <- lesssig_all_gp[[name]]
  filename <- glue("analyses/macrophage_de/gprofiler/{name}_gprofiler_lesssig-v{ver}.xlsx")
  written <- sm(write_gprofiler_data(datum, excel = filename))
}

11.3 Explicit GSEA search vis clusterProfiler

all_cp <- all_cprofiler(hs_macr_sig, hs_macr_table)
## Reading KEGG annotation online: "https://rest.kegg.jp/link/hsa/pathway"...
## Reading KEGG annotation online: "https://rest.kegg.jp/list/pathway/hsa"...
## ReactomePA v1.52.0 Learn more at https://yulab-smu.top/contribution-knowledge-mining/
## 
## Please cite:
## 
## Guangchuang Yu, Qing-Yu He. ReactomePA: an R/Bioconductor package for
## reactome pathway analysis and visualization. Molecular BioSystems.
## 2016, 12(2):477-479
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(up, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this DOSE organism, leaving it as human.
## Warning in simple_clusterprofiler(down, table, orgdb = orgdb, orgdb_from =
## orgdb_from, : I do not know this mesh organism, leaving it as human.

11.4 Specific desires in Reactome results

In previous analyses (I think by Dr. Colmenares), a specific Tryptophan biosynthesis pathway was observed. Partciularly in the 2.3/uninfected comparison. I think my gprofiler analysis is too stringent and therefore not observing this. Olga asked if I could look at that and see if there are trivial settings I can change to highlight this pathway. The two most likely things I can change are the stringencies of the DE analysis and/or gProfiler.

test_z23_uninf_up <- hs_macr_sig[["deseq"]][["ups"]][["z23nosb_vs_uninf"]]
nrow(test_z23_uninf_up)
## [1] 478
test_z23_uninf_down <- hs_macr_sig[["deseq"]][["downs"]][["z23nosb_vs_uninf"]]
nrow(test_z23_uninf_down)
## [1] 265
test_gp_up <- simple_gprofiler(test_z23_uninf_up, enrich_id_column = "hgnc_symbol",
                               threshold = 1.0)
test_gp_up
written_up <- write_gprofiler_data(test_gp_up, excel = "excel/z23_uninf_gp_up_all.xlsx")

test_gp_down <- simple_gprofiler(test_z23_uninf_down, enrich_id_column = "hgnc_symbol",
                                 threshold = 1.0)
test_gp_down
written_down <- write_gprofiler_data(test_gp_down, excel = "excel/z23_uninf_gp_down_all.xlsx")

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

11.6 Individual zymodemes vs. uninfected

The following blocks will be a lot of repetition. In each case I am yanking out the volcano plot for a specific contrast and showing the original followed by a version with different colors/labelling.

11.6.1 Infected with z2.3 no Antimonial vs. Uninfected

plot_colors <- get_se_colors(hs_macr_table[["input"]][["input"]])
## Error in get_se_colors(hs_macr_table[["input"]][["input"]]): could not find function "get_se_colors"
## The original plot from my xlsx file
hs_macr_table[["plots"]][["z23nosb_vs_uninf"]][["deseq_vol_plots"]]

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 = "hgnc_symbol",
  color_low = plot_colors[["uninfnone"]], color_high = plot_colors[["infz23"]])
## Error: object 'plot_colors' not found
labeled <- z23nosb_vs_uninf_volcano[["plot"]] +
  scale_x_continuous(limits = c(-6, 21), breaks = c(-6, -4, -2, 0, 2, 4, 6, 8, 10, 20)) +
  ggbreak::scale_x_break(c(10, 19), scales = 0.2, space = 0.02)
## Error: object 'z23nosb_vs_uninf_volcano' not found
pp(file = "figures/fig2a_labeled_with_break.svg")
labeled
## Error: object 'labeled' not found
dev.off()
## png 
##   2
labeled
## Error: object 'labeled' not found
plotly::ggplotly(z23nosb_vs_uninf_volcano[["plot"]])
## Error: object 'z23nosb_vs_uninf_volcano' not found

The following provides some of the over-representation plots from gProfiler2.

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"]]
message("Olga received a query about the following result, I think it is null.")
## Olga received a query about the following result, I think it is null.
all_gp[["z23nosb_vs_uninf_down"]][["pvalue_plots"]][["REAC"]]
## NULL
message("Is the previous plot null?")
## Is the previous plot null?
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23nosb_vs_uninf_down"]][["pvalue_plots"]][["MF"]]
## NULL
## 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.

We have some other categorical enrichment plots available via enrichplot, let us try a few out for contrasts of interest and see if any of them prove helpful.

First, as a reminder, here are the contrasts which are available to examine, in each case there is an _up and _down enrichment object in the data. Thus in the following list I am going to arbitrarily print out some invocations which extract putatively interesting bits of data.

  • z23nosb_vs_uninf: all_gp[[“z23nosb_vs_uninf_up”]][[“BP_enrich”]]
  • z22nosb_vs_uninf.
  • z23nosb_vs_z22nosb.
  • z23sb_vs_z22sb.
  • z23sb_vs_z23nosb.
  • z22sb_vs_z22nosb.
  • z23sb_vs_sb.
  • z22sb_vs_sb.
  • z23sb_vs_uninf.
  • z22sb_vs_uninf.
  • sb_vs_uninf.
  • extra_z2322.
  • extra_drugnodrug.
z23nosb_uninf_up_go <- all_gp[["z23nosb_vs_uninf_up"]][["BP_enrich"]]
z23nosb_uninf_up_go_pair <- pairwise_termsim(z23nosb_uninf_up_go)
dotplot(z23nosb_uninf_up_go)

emapplot(z23nosb_uninf_up_go_pair)

##ssplot(z23nosb_uninf_up_go_pair)
treeplot(z23nosb_uninf_up_go_pair)

upsetplot(z23nosb_uninf_up_go)

cnetplot(z23nosb_uninf_up_go)
## Warning: ggrepel: 5 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

11.6.2 Repeat, but using a less strict set of ‘significant genes’

I am not entirely certain if the Reactome results Olga showed me included both up and down genes? I am going to assume for the moment that it was just up/down, but if that proves intractable I will go back to the manuscript and read more carefully (e.g. I just remembered where the picture came from!)

11.6.2.1 Add a little topgo

In the process of exploring the various parameters used with gProfiler2, I found myself thinking that it would be nice to have some topgo results to compare against. The following block is the result of that thought.

test_genes_up <- hs_macr_lesssig[["deseq"]][["ups"]][["z23nosb_vs_uninf"]]
test_query_up <- simple_gprofiler(test_genes_up, threshold = 0.1)
test_query_up[["pvalue_plots"]][["REAC"]]

pdf(file = "images/test_query_biological_process_z23_vs_uninf_up.pdf", height = 12, width = 9)
test_query_up[["pvalue_plots"]][["BP"]]
## NULL
dev.off()
## png 
##   2
enrichplot::dotplot(test_query_up[["BP_enrich"]])

test_genes_down <- hs_macr_lesssig[["deseq"]][["downs"]][["z23nosb_vs_uninf"]]
test_query_down <- simple_gprofiler(test_genes_down)
test_query_down[["pvalue_plots"]][["REAC"]]
## NULL
## I keep getting all sorts of annoying biomart errors.
hs_go <- try(load_biomart_go(archive = FALSE, overwrite = TRUE))
## Using mart: ENSEMBL_MART_ENSEMBL from host: useast.ensembl.org.
## Successfully connected to the hsapiens_gene_ensembl database.
## Error in httr2::req_perform(req) : Failed to perform HTTP request.
## Caused by error in `curl::curl_fetch_memory()` at httr2/R/req-perform.R:201:5:
## ! Timeout was reached [useast.ensembl.org]:
## Operation timed out after 300002 milliseconds with 10486132 bytes received
## Unable to download annotation data.
if ("try-error" %in% class(hs_go)) {
  hs_go <- load_biomart_go(archive = TRUE, month = "04", year = "2020", overwrite = TRUE)
}
test_topgo_up <- simple_topgo(test_genes_up, go_db = hs_go[["go"]], parallel = FALSE)
## Error in go_db[, c("L1", "value")]: incorrect number of dimensions
written_topgo <- write_topgo_data(
  test_topgo_up,
  excel = glue("analyses/macrophage_de/ontology_topgo/topgo_z23_uninf_less_strict.xlsx"))
## Error: object 'test_topgo_up' not found

11.6.3 Infected with z2.2 no Antimonial vs. Uninfected

Here is where things will get most repetitive. In each instance I am creating a couple of volcano plots followed by printing some of the gProfiler2 results (when I get the itch).

The following should be a slightly improved version of our extant figure 2B.

## The original plot
hs_macr_table[["plots"]][["z22nosb_vs_uninf"]][["deseq_vol_plots"]]

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 = "hgnc_symbol",
  color_low = plot_colors[["uninfnone"]], color_high = plot_colors[["infz22"]])
## Error: object 'plot_colors' not found
labeled <- z22nosb_vs_uninf_volcano[["plot"]] +
  scale_x_continuous(limits = c(-2, 21), breaks = c(-2, 0, 2, 4, 6, 8, 10, 21, 22)) +
  ggbreak::scale_x_break(c(11, 20), scales = 0.2, space = 0.02)
## Error: object 'z22nosb_vs_uninf_volcano' not found
pp(file = "figures/fig2b_labeled_with_break.svg")
labeled
## Error: object 'labeled' not found
dev.off()
## png 
##   2
labeled
## Error: object 'labeled' not found
plotly::ggplotly(z22nosb_vs_uninf_volcano[["plot"]])
## Error: object 'z22nosb_vs_uninf_volcano' not found

Add some pvalue barplots from gProfiler for this contrast.

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"]]
## NULL
## 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.

11.6.4 Infected with z2.3 treated vs. Uninfected treated

I do not think this plot is used at this time.

## The original plot
hs_macr_table[["plots"]][["z23sb_vs_sb"]][["deseq_vol_plots"]]

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 = "hgnc_symbol",
  color_low = plot_colors[["infsbz23"]], color_high = plot_colors[["uninfsbnone"]])
## Error: object 'plot_colors' not found
z23sb_vs_uninfsb_volcano[["plot"]]
## Error: object 'z23sb_vs_uninfsb_volcano' not found
plotly::ggplotly(z23sb_vs_uninfsb_volcano[["plot"]])
## Error: object 'z23sb_vs_uninfsb_volcano' not found

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

This is figure 2C at this time.

## 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 = "hgnc_symbol",
  color_low = plot_colors[["infz23"]], color_high = plot_colors[["infz22"]])
## Error: object 'plot_colors' not found
labeled <- z23nosb_vs_z22nosb_volcano[["plot"]] +
  scale_x_continuous(breaks = c(-10, -8, -6, -4, -2, 0, 2, 4, 6))
## Error: object 'z23nosb_vs_z22nosb_volcano' not found
pp(file = "figures/fig2c_labeled.svg")
labeled
## Error: object 'labeled' not found
dev.off()
## png 
##   2
labeled
## Error: object 'labeled' not found

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

This is currently figure 3C.

FIXME: The axis label isn’t quite right for the ggbreak.

## The original plot
hs_macr_table[["plots"]][["z23sb_vs_z22sb"]][["deseq_vol_plots"]]

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 = "hgnc_symbol",
  color_high = plot_colors[["infsbz23"]], color_low = plot_colors[["infsbz22"]])
## Error: object 'plot_colors' not found
labeled <- z23sb_vs_z22sb_volcano[["plot"]] +
  scale_x_continuous(breaks = c(-23, -6, -4, -2, 0, 2, 4, 6)) +
  ggbreak::scale_x_break(c(-5, -22.5), scales = 10, space = 0.02)
## Error: object 'z23sb_vs_z22sb_volcano' not found
pp(file = "figures/fig3c_labeled_breaks.svg")
labeled
## Error: object 'labeled' not found
dev.off()
## png 
##   2
labeled
## Error: object 'labeled' not found

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

I think this is currently figure 3A.

FIXME: The axis label for the ggbreak isn’t quite right.

## 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 = "hgnc_symbol",
  color_high = plot_colors[["infsbz23"]], color_low = plot_colors[["infz23"]])
## Error: object 'plot_colors' not found
labeled <- z23sb_vs_z23nosb_volcano[["plot"]] +
  scale_x_continuous(limits = c(-19, 6),
                     breaks = c(-20, -18, -16, -14, -12, -10, -6, -4, -2, 0, 2, 4, 6)) +
  ggbreak::scale_x_break(c(-17, -8), scales = 17, space = 0.02)
## Error: object 'z23sb_vs_z23nosb_volcano' not found
pp(file = "figures/fig3a_labeled_with_break.svg")
labeled
## Error: object 'labeled' not found
dev.off()
## png 
##   2
labeled
## Error: object 'labeled' not found

11.6.8 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 = "hgnc_symbol",
  color_high = plot_colors[["infsbz22"]], color_low = plot_colors[["infz22"]])
## Error: object 'plot_colors' not found
labeled <- z22sb_vs_z22nosb_volcano[["plot"]] +
  scale_x_continuous(breaks = c(-6, -4, -2, 0, 2, 4, 6))
## Error: object 'z22sb_vs_z22nosb_volcano' not found
pp(file = "figures/fig3b_labeled.svg")
labeled
## Error: object 'labeled' not found
dev.off()
## png 
##   2
labeled
## Error: object 'labeled' not found

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

x_limits <- c(-6, 6)
## The original plot
hs_macr_table[["plots"]][["z23sb_vs_sb"]][["deseq_vol_plots"]]

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 = "hgnc_symbol", invert = TRUE,
  color_low = plot_colors[["infsbz23"]], color_high = plot_colors[["uninfsbnone"]])
## Error: object 'plot_colors' not found
z23sb_vs_sb_volcano[["plot"]]
## Error: object 'z23sb_vs_sb_volcano' not found

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

## The original plot
hs_macr_table[["plots"]][["z22sb_vs_sb"]][["deseq_vol_plots"]]

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 = "hgnc_symbol", invert = TRUE,
  color_low = plot_colors[["infsbz22"]], color_high = plot_colors[["uninfsbnone"]])
## Error: object 'plot_colors' not found
z22sb_vs_sb_volcano[["plot"]]
## Error: object 'z22sb_vs_sb_volcano' not found

11.6.11 Uninfected+SbV vs. Uninfected-SbV

This is currently figure 3D.

FIXME: This needs the BOLA2B ggbreak.

## The original plot
hs_macr_table[["plots"]][["sb_vs_uninf"]][["deseq_vol_plots"]]

sb_vs_uninf_volcano <- plot_volcano_condition_de(
  hs_macr_table[["data"]][["sb_vs_uninf"]], "sb_vs_uninf",
  fc_col = "deseq_logfc", p_col = "deseq_adjp",
  label = 10, label_column = "hgnc_symbol",
  color_high = plot_colors[["uninfsbnone"]], color_low = plot_colors[["uninfnone"]])
## Error: object 'plot_colors' not found
labeled <- sb_vs_uninf_volcano[["plot"]] +
  scale_x_continuous(breaks = c(-23, -6, -4, -2, 0, 2, 4, 6)) +
  ggbreak::scale_x_break(c(-5, -22.5), scales = 10, space = 0.02)
## Error: object 'sb_vs_uninf_volcano' not found
pp(file = "figures/fig3d_labeled_breaks.svg")
labeled
## Error: object 'labeled' not found
dev.off()
## png 
##   2
labeled
## Error: object 'labeled' not found

11.7 Double-check that gene counts match my perceptions

Check that my perception of the number of significant up/down genes matches what the table/venn says. In the following block I am performing some venn/upset analyses to see if the numbers of genes match what we have in the current version of the manuscript (plus or minus a gene) and thus if my interpretation of the figure/legend text matches what I think it means.

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  73
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  73

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.

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

11.8.1 Z2.3 / z2.2 without drug

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 = "hgnc_symbol")
## Error in plot_volcano_de(table = hs_macr_table[["data"]][["z23nosb_vs_z22nosb"]], : could not find function "plot_volcano_de"
plotly::ggplotly(z23nosb_vs_z22nosb_volcano[["plot"]])
## Error: object 'z23nosb_vs_z22nosb_volcano' not found
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 = "hgnc_symbol")
## Error in plot_volcano_de(table = hs_macr_table[["data"]][["z23sb_vs_z22sb"]], : could not find function "plot_volcano_de"
plotly::ggplotly(z23sb_vs_z22sb_volcano[["plot"]])
## Error: object 'z23sb_vs_z22sb_volcano' not found
z23nosb_vs_z22nosb_volcano[["plot"]] +
  xlim(-10, 10) +
  ylim(0, 60)
## Error: object 'z23nosb_vs_z22nosb_volcano' not found
pp(file = "images/z23nosb_vs_z22nosb_reactome_up.svg",
   image = all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]],
   height = 12, width = 9)
## Warning: ImageMagick was built without librsvg which causes poor quality of SVG rendering.
## For better results use image_read_svg() which uses the rsvg package.
## Error in eval(expr, envir): R: geometry does not contain image `/lab/singularity/tmrc2_macrophage_deb/202509081525_outputs/images/z23nosb_vs_z22nosb_reactome_up.svg' @ warning/attribute.c/GetImageBoundingBox/554
all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]]

## 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"]]
## NULL
## 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"]]
pp(file = "images/z23nosb_vs_z22nosb_reactome_down.svg",
   image = all_gp[["z23nosb_vs_z22nosb_down"]][["pvalue_plots"]][["REAC"]],
   height = 12, width = 9)
## Warning: ImageMagick was built without librsvg which causes poor quality of SVG rendering.
## For better results use image_read_svg() which uses the rsvg package.
## Error in eval(expr, envir): R: geometry does not contain image `/lab/singularity/tmrc2_macrophage_deb/202509081525_outputs/images/z23nosb_vs_z22nosb_reactome_down.svg' @ warning/attribute.c/GetImageBoundingBox/554
all_gp[["z23nosb_vs_z22nosb_down"]][["pvalue_plots"]][["REAC"]]

## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23nosb_vs_z22nosb_down"]][["pvalue_plots"]][["MF"]]
## NULL
## 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.

11.8.2 z2.3 / z2.2 with drug

z23sb_vs_z22sb_volcano[["plot"]] +
  xlim(-10, 10) +
  ylim(0, 60)
## Error: object 'z23sb_vs_z22sb_volcano' not found
pp(
  file = "images/z23sb_vs_z22sb_reactome_up.png",
  image = all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["REAC"]],
  height = 12, width = 9)
## 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.
## Error in eval(expr, envir): R: improper image header `/lab/singularity/tmrc2_macrophage_deb/202509081525_outputs/images/z23sb_vs_z22sb_reactome_up.png' @ error/png.c/ReadPNGImage/3941
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["REAC"]]
## 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"]]
## NULL
## 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"]]
## NULL
## 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.

11.8.3 Venn to see shared/unique genes

Once again I wish to pull out the significant genes and see how my numbers match against the text.

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
Vennerable::plot(shared)

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.

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

11.9.1 z2.3 with and without drug

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 = "hgnc_symbol")
## Error in plot_volcano_de(table = hs_macr_table[["data"]][["z23sb_vs_z23nosb"]], : could not find function "plot_volcano_de"
plotly::ggplotly(z23sb_vs_z23nosb_volcano[["plot"]])
## Error: object 'z23sb_vs_z23nosb_volcano' not found
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 = "hgnc_symbol")
## Error in plot_volcano_de(table = hs_macr_table[["data"]][["z22sb_vs_z22nosb"]], : could not find function "plot_volcano_de"
plotly::ggplotly(z22sb_vs_z22nosb_volcano[["plot"]])
## Error: object 'z22sb_vs_z22nosb_volcano' not found
z23sb_vs_z23nosb_volcano[["plot"]] +
  xlim(-8, 8) +
  ylim(0, 210)
## Error: object 'z23sb_vs_z23nosb_volcano' not found
pp(file = "images/z23sb_vs_z23nosb_reactome_up.png",
   image = all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["REAC"]],
   height = 12, width = 9)
## 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.
## Error in eval(expr, envir): R: improper image header `/lab/singularity/tmrc2_macrophage_deb/202509081525_outputs/images/z23sb_vs_z23nosb_reactome_up.png' @ error/png.c/ReadPNGImage/3941
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["REAC"]]
## 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"]]
## NULL
## 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"]]
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23sb_vs_z23nosb_down"]][["pvalue_plots"]][["MF"]]
## NULL
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23sb_vs_z23nosb_down"]][["pvalue_plots"]][["TF"]]
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_col()`).
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.

11.9.2 z2.2 with and without drug

z22sb_vs_z22nosb_volcano[["plot"]] +
  xlim(-8, 8) +
  ylim(0, 210)
## Error: object 'z22sb_vs_z22nosb_volcano' not found
pp(file = "images/z22sb_vs_z22nosb_reactome_up.png",
   image = all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]],
   height = 12, width = 9)
## 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.
## Error in eval(expr, envir): R: improper image header `/lab/singularity/tmrc2_macrophage_deb/202509081525_outputs/images/z22sb_vs_z22nosb_reactome_up.png' @ error/png.c/ReadPNGImage/3941
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]]
## 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"]]
## NULL
## 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"]]
## NULL
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z22sb_vs_z22nosb_down"]][["pvalue_plots"]][["TF"]]
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_col()`).
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.

11.9.3 Shared and unique genes after/before drug

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.

12 LRT of the Human Macrophage

A slightly different tack to examine the data is to perform a likelihood ratio test in order to look for trends which are shared among genes when examining different conditions in the data.

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

tmrc2_lrt_strain_drug[["cluster_data"]][["plot"]]

13 Parasite

Let us consider for a moment differences among the parasite transcriptomes for the samples which were not drug treated.

One thing I did in the initial implementation of this document was to repeat the variable ‘up_genes’ for each comparison; I think this time I will make a different variable for each comparison so I can play with them a little further.

comparison <- "z23_vs_z22"
lp_macrophage_de <- all_pairwise(lp_macrophage_nosb, model_svs = "svaseq",
                                 model_fstring = "~ 0 + condition", filter = TRUE)
## z2.2 z2.3 
##   14   15
## Running normalize_se.
## Removing 119 low-count genes (8591 remaining).
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## I think this is failing? SummarizedExperiment
## Basic step 0/3: Transforming data.
## Running normalize_se.
## Setting 2387 entries to zero.
## This received a matrix of SVs.
## converting counts to integer mode
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## Warning in createContrastL(objFlt$formula, objFlt$data, L): Contrasts with only
## a single non-zero term are already evaluated by default.
## conditions
## z22 z23 
##  14  15
## conditions
## z22 z23 
##  14  15
## conditions
## z22 z23 
##  14  15
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("analyses/macrophage_de/de_tables/parasite_infection_de-v{ver}.xlsx"))
lp_macrophage_sig <- extract_significant_genes(
  lp_macrophage_table,
  excel = glue("analyses/macrophage_de/sig_tables/parasite_sig-v{ver}.xlsx"))

lp_macrophage_table[["plots"]][[comparison]][["deseq_vol_plots"]]

lp_macrophage_table[["plots"]][[comparison]][["deseq_ma_plots"]]

up_genes_z23z22 <- lp_macrophage_sig[["deseq"]][["ups"]][[comparison]]
dim(up_genes_z23z22)
## [1] 48 69
down_genes_z23z22 <- lp_macrophage_sig[["deseq"]][["downs"]][[comparison]]
dim(down_genes_z23z22)
## [1] 91 69
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 = "hgnc_symbol")
## Error in plot_volcano_de(table = lp_macrophage_table[["data"]][["z23_vs_z22"]], : could not find function "plot_volcano_de"
plotly::ggplotly(lp_z23sb_vs_z22sb_volcano[["plot"]])
## Error: object 'lp_z23sb_vs_z22sb_volcano' not found
lp_z23sb_vs_z22sb_volcano[["plot"]]
## Error: object 'lp_z23sb_vs_z22sb_volcano' not found

14 GSVA

Note: The following block assumes one is able to download a fresh copy of msigDB, which I am not sure is possible within the constraints of a container (I mean it is trivial to do, but I am not sure if it is ok due to licensing). However, Broad provides a data package of a msigdb release. As a result, the following block will be repeated using that.

hs_infected <- subset_se(hs_macrophage, subset = "macrophagetreatment!='uninf'") %>%
  subset_se(subset = "macrophagetreatment!='uninf_sb'")
hs_gsva_c2 <- simple_gsva(hs_infected)
hs_gsva_c2_meta <- get_msigdb_metadata(hs_gsva_c2, msig_xml = "reference/msigdb_v7.2.xml")
hs_gsva_c2_sig <- get_sig_gsva_categories(
  hs_gsva_c2_meta,
  excel = glue("analyses/macrophage_de/gsva/hs_macrophage_gsva_c2_sig.xlsx"))
hs_gsva_c2_sig[["raw_plot"]]

hs_gsva_c7 <- simple_gsva(hs_infected, signature_category = "c7")
hs_gsva_c7_meta <- get_msigdb_metadata(hs_gsva_c7, msig_xml = "reference/msigdb_v7.2.xml")
hs_gsva_c7_sig <- get_sig_gsva_categories(
  hs_gsva_c7,
  excel = glue("analyses/macrophage_de/gsva/hs_macrophage_gsva_c7_sig.xlsx"))
hs_gsva_c7_sig[["raw_plot"]]

14.1 Repeat using the GSVAdata package.

hs_infected <- subset_se(hs_macrophage, subset = "macrophagetreatment!='uninf'") %>%
  subset_se(subset = "macrophagetreatment!='uninf_sb'")
hs_gsva_c2 <- simple_gsva(hs_infected)
## Error: unable to find an inherited method for function 'annotation' for signature 'object = "SummarizedExperiment"'
##hs_gsva_c2_meta <- get_msigdb_metadata(hs_gsva_c2, msig_xml="reference/msigdb_v7.2.xml")
hs_gsva_c2_sig <- get_sig_gsva_categories(
  hs_gsva_c2,
  excel = glue("analyses/macrophage_de/gsva/hs_macrophage_gsva_c2_sig.xlsx"))
## Error: object 'hs_gsva_c2' not found
hs_gsva_c2_sig[["raw_plot"]]
## Error: object 'hs_gsva_c2_sig' not found
hs_gsva_c7 <- simple_gsva(hs_infected, signature_category = "c7")
## Error: unable to find an inherited method for function 'annotation' for signature 'object = "SummarizedExperiment"'
##hs_gsva_c7_meta <- get_msigdb_metadata(hs_gsva_c7, msig_xml="reference/msigdb_v7.2.xml")
hs_gsva_c7_sig <- get_sig_gsva_categories(
  hs_gsva_c7,
  excel = glue("analyses/macrophage_de/gsva/hs_macrophage_gsva_c7_sig.xlsx"))
## Error: object 'hs_gsva_c7' not found
hs_gsva_c7_sig[["raw_plot"]]
## Error: object 'hs_gsva_c7_sig' not found

15 Try out a new tool

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

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

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

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

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

library(pathwayPCA)
library(rWikiPathways)
## 
## Attaching package: 'rWikiPathways'
## The following object is masked from 'package:edgeR':
## 
##     getCounts
downloaded <- downloadPathwayArchive(organism = "Homo sapiens", format = "gmt")
data_path <- system.file("extdata", package = "pathwayPCA")
wikipathways <- read_gmt(paste0(data_path, "/wikipathways_human_symbol.gmt"),
                         description = TRUE)

se <- subset_se(hs_macrophage, subset = "macrophagetreatment!='uninf'") %>%
  subset_se(subset = "macrophagetreatment!='uninf_sb'")
se <- set_conditions(se, fact = "macrophagezymodeme")
## The numbers of samples by condition are:
## 
## none  z22  z23 
##    0   29   29
symbol_column <- "hgnc_symbol"
symbol_vector <- rowData(se)[[symbol_column]]
names(symbol_vector) <- rownames(rowData(se))
symbol_df <- as.data.frame(symbol_vector)

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

factor_df <- as.data.frame(colData(se))
factor_df[["SampleID"]] <- rownames(factor_df)
factor_df <- dplyr::select(factor_df, "SampleID", everything())
factor_df <- factor_df[, c("SampleID", factors)]
## Error: object 'factors' not found
tt <- CreateOmics(
  assayData_df = assay_df,
  pathwayCollection_ls = wikipathways,
  response = factor_df,
  respType = "categorical",
  minPathSize = 5)
## 3190 genes have variance < epsilon and will be removed. These gene(s) include:
##   [1] "TNMD"         "CYP51A1"      "KRIT1"        "MAD1L1"       "ARF5"        
##   [6] "REXO5"        "FBXL3"        "REX1BD"       "KRT33A"       "TAC1"        
##  [11] "LGALS14"      "SLC13A2"      "TRAPPC6A"     "SELE"         "TFAP2B"      
##  [16] "SS18L2"       "IDS"          "SLC7A14"      "CLDN11"       "MDH1"        
##  [21] "COX15"        "MATR3"        "ISL1"         "INSRR"        "EFCAB1"      
##  [26] "TMSB10"       "OTC"          "HOXC8"        "XK"           "NOP16"       
##  [31] "TNFRSF17"     "GUCA1A"       "NNAT"         "NRIP2"        "MCOLN3"      
##  [36] "SERPINB3"     "MRPS24"       "SEZ6"         "AHRR"         "BORCS8.MEF2B"
##  [41] "KDM4A"        "THUMPD1"      "IFT80"        "ERLEC1"       "PAGE1"       
##  [46] "FRMPD1"       "LNX1"         "IPCEF1"       "ZNF37A"       "TUBA3D"      
##  [51] "SPAG5"        "EXOSC5"       "TIGAR"        "TP53INP2"     "LXN"         
##  [56] "AFM"          "CFHR2"        "UBA5"         "JMJD4"        "PCDHA6"      
##  [61] "PCDHGA2"      "C1QTNF3"      "RNF13"        "ZNF671"       "RRN3"        
##  [66] "CHERP"        "DIMT1"        "NME8"         "PIGS"         "DEFB127"     
##  [71] "FXYD3"        "CMTM1"        "FLT3LG"       "RBM27"        "ANGPT2"      
##  [76] "RNF31"        "SEMA4G"       "NUBP2"        "KCNK16"       "MAGEB2"      
##  [81] "MTAP"         "SERPIND1"     "DDT"          "SEC14L2"      "GGT1"        
##  [86] "PRODH"        "SOX10"        "TIMP3"        "PSMA3"        "SNW1"        
##  [91] "SERPINA4"     "PCK2"         "PRORP"        "TM9SF1"       "RAB5IF"      
##  [96] "CST9L"        "CST4"         "SPINT3"       "EPPIN"        "RBFA"        
## [101] "CEP76"        "H2BW2"        "MCTS2P"       "SRPX"         "F9"          
## [106] "PPP1R2C"      "BRS3"         "TIMP1"        "GLA"          "ACP5"        
## [111] "DHRS12"       "ZNF821"       "CMC2"         "ZNF174"       "CORO7.PAM16" 
## [116] "SALL1"        "AQP9"         "OIP5"         "ARHGEF10"     "CGB2"        
## [121] "CGB3"         "PPP1R37"      "RNASEH2A"     "OAZ1"         "C19orf44"    
## [126] "MED26"        "ZNF419"       "LGALS13"      "CEACAM5"      "BABAM1"      
## [131] "ATP1A3"       "ZNRF4"        "TMEM205"      "WDR83OS"      "PIK3R2"      
## [136] "PDE4C"        "DDX49"        "ERF"          "RASA4"        "TFPI2"       
## [141] "DUS4L"        "NPVF"         "WNT2"         "HOXA5"        "HOXA6"       
## [146] "CHN2"         "MINDY4"       "PSMA2"        "OGN"          "ASPN"        
## [151] "ECM2"         "EXOSC3"       "VSIR"         "RNF43"        "ASPA"        
## [156] "HOXB6"        "SLC16A6"      "RANGRF"       "VTN"          "FOXN1"       
## [161] "UNC119"       "ALDOC"        "ODAM"         "SMR3A"        "CHIC2"       
## [166] "IL2"          "CPZ"          "DBX1"         "SNX15"        "APOC3"       
## [171] "SCGB2A2"      "PTPMT1"       "CALCA"        "MYF6"         "MYF5"        
## [176] "PRR4"         "AKAP3"        "GSG1"         "OGFOD2"       "ART4"        
## [181] "MGP"          "FZD10"        "LPCAT3"       "GYS2"         "MAK"         
## [186] "ASF1A"        "IL17A"        "TSPO2"        "CCNC"         "HDGFL1"      
## [191] "OR12D3"       "MRPL2"        "TMCO6"        "PDE8B"        "IL5"         
## [196] "SMC4"         "NPHP3"        "BCHE"         "ABHD14B"      "ABHD14A.ACY1"
## [201] "TP53I3"       "INO80B"       "REG1A"        "KCNJ13"       "NEU2"        
## [206] "HSPE1"        "ABCB6"        "PNO1"         "ATP6V1B1"     "ANGPTL1"     
## [211] "NCF2"         "PRAMEF1"      "AGMAT"        "TNNI3K"       "TSNAX"       
## [216] "CRYGD"        "ZC2HC1B"      "CCND2"        "FGF23"        "TRIM32"      
## [221] "TGFB3"        "ZNF410"       "GPR75"        "IFIT3"        "NKX2.3"      
## [226] "IFIT2"        "HOXB8"        "HOXB5"        "CRHR1"        "HOXB1"       
## [231] "MLANA"        "IFNA6"        "GRIA2"        "LRP11"        "MAGEB4"      
## [236] "SLC25A2"      "GPR31"        "TNFSF11"      "TRIM6"        "TAS2R10"     
## [241] "IAPP"         "SLITRK3"      "CLCC1"        "GPSM2"        "OBP2A"       
## [246] "TBX22"        "PRM2"         "RWDD3"        "MRM2"         "SLC25A51"    
## [251] "DCAF10"       "WDR83"        "ACTRT1"       "TSFM"         "ORMDL2"      
## [256] "CDK2"         "KBTBD4"       "COL10A1"      "SERPINA7"     "H2BW1"       
## [261] "ESX1"         "B9D2"         "MC3R"         "GCNT7"        "ANKRD60"     
## [266] "C20orf85"     "TP53TG5"      "MAGEA10"      "FASTKD3"      "CRISP2"      
## [271] "AARS2"        "RPS10"        "APOBEC2"      "GCM2"         "TRIM51"      
## [276] "SCGB2A1"      "GPR18"        "IRF1"         "AMELX"        "NPBWR2"      
## [281] "BHLHE23"      "FOSB"         "DEFB126"      "FOXA2"        "NKX2.4"      
## [286] "NKX2.2"       "CSTL1"        "FLRT3"        "MGME1"        "TMEM74B"     
## [291] "CITED1"       "MMP24"        "TMEM115"      "KIRREL2"      "X.5"         
## [296] "STATH"        "HTN1"         "TIMM17B"      "EVI2A"        "OMG"         
## [301] "AVPR2"        "OMD"          "TAS2R3"       "TAS2R4"       "OR7A10"      
## [306] "SLC35E1"      "OR7C2"        "GNG13"        "EMC6"         "OR1E2"       
## [311] "FGL2"         "GNAZ"         "ADORA2A"      "TAS2R16"      "ATP6V1F"     
## [316] "LRRC4"        "LRRC17"       "FEZF1"        "MRPS12"       "HOXD1"       
## [321] "HAT1"         "HOXD9"        "HOXD13"       "ELL3"         "CALML4"      
## [326] "THAP10"       "ACKR4"        "SOX15"        "KLK8"         "NEDD8"       
## [331] "VCY1B"        "VCY"          "CDY2B"        "INS.IGF2"     "KCNA5"       
## [336] "ANGPTL8"      "ACE2"         "GDF1"         "MRPL34"       "LSM7"        
## [341] "ACSBG2"       "BMP15"        "ARPC1B"       "OR11H1"       "CALY"        
## [346] "PPAN"         "HSD17B3"      "PRRG1"        "BPIFA3"       "DEFB118"     
## [351] "GJA9"         "CDX4"         "NAPSA"        "PDLIM4"       "TMEM204"     
## [356] "KRT33B"       "FSHB"         "USP29"        "NR0B2"        "ACTR10"      
## [361] "ABHD12B"      "RTBDN"        "TRIM22"       "TIMM10B"      "SCLY"        
## [366] "FTHL17"       "NIP7"         "VPS4A"        "SCP2D1"       "SSTR4"       
## [371] "APCS"         "TOE1"         "PPP1R3D"      "BHMT2"        "ZBED3"       
## [376] "ANGPTL3"      "STOML3"       "IRS4"         "ERG28"        "GSC"         
## [381] "CAMK1"        "GSTM1"        "TSHB"         "GSTM3"        "FKBP11"      
## [386] "GRP"          "PRH2"         "SOX3"         "BIVM"         "ERCC5"       
## [391] "UGT2A3"       "CSN2"         "LACRT"        "GLS2"         "FAM186B"     
## [396] "BLOC1S1"      "ZC3H10"       "SLC26A10"     "MIP"          "CHST5"       
## [401] "HTR2B"        "TMBIM1"       "RCBTB2"       "KDELR2"       "CIDEB"       
## [406] "NKX2.8"       "NKX2.1"       "SRSF1"        "CHAD"         "GH2"         
## [411] "LIMD2"        "CFC1"         "OR13C9"       "ANGPTL2"      "TLR4"        
## [416] "HINT2"        "YIPF3"        "CLPS"         "FXYD6"        "SLTM"        
## [421] "LHCGR"        "SLC3A1"       "LBX1"         "CUZD1"        "RBP4"        
## [426] "GPR87"        "MSTN"         "CARF"         "IL21"         "GSTCD"       
## [431] "ZCRB1"        "NDUFA9"       "KERA"         "SYCP3"        "CCDC65"      
## [436] "NPFF"         "LPAR6"        "RNF113B"      "SSTR1"        "TSSK4"       
## [441] "RAB15"        "SERF2"        "FGF7"         "CELF6"        "IGSF6"       
## [446] "CHST4"        "ZSCAN32"      "CTRL"         "KIF2B"        "ADCYAP1"     
## [451] "MEP1B"        "SAT2"         "ZNF750"       "ELAC1"        "SLC39A3"     
## [456] "CCDC97"       "TMEM91"       "ZNF593"       "EVA1B"        "DMRTB1"      
## [461] "BARHL2"       "PIGM"         "CRNN"         "JTB"          "CREB3L4"     
## [466] "PYCR2"        "CHAC2"        "ANKRD53"      "TEX261"       "LIPT1"       
## [471] "LYG1"         "GPR17"        "PHOSPHO2"     "RPL32"        "LRTM1"       
## [476] "ZNF660"       "EIF2A"        "AMT"          "ECE2"         "SLC26A1"     
## [481] "CABS1"        "BHMT"         "KCNMB1"       "LRRTM2"       "SLC17A4"     
## [486] "H2BC1"        "HIGD2A"       "TCTE1"        "CLVS2"        "TAAR2"       
## [491] "TAAR6"        "TAAR8"        "WTAP"         "RBAK"         "FERD3L"      
## [496] "TMEM140"      "CLTRN"        "LANCL3"       "SYTL5"        "AKAP4"
## 1103 gene name(s) are invalid. Invalid name(s) include:
##   [1] "NME1.NME2"       "RTEL1.TNFRSF6B"  "STON1.GTF2A1L"   "X.1"            
##   [5] "PTGES3L.AARSD1"  "NKX3.2"          "X.2"             "TMEM189.UBE2V1" 
##   [9] "H1.3"            "X.3"             "H1.1"            "X.4"            
##  [13] "CHURC1.FNTB"     "X.6"             "H3.3B"           "ZNF670.ZNF695"  
##  [17] "X.7"             "ERVK3.1"         "X.8"             "X.9"            
##  [21] "NKX6.2"          "X.10"            "H3.3A"           "NKX6.1"         
##  [25] "NKX6.3"          "NKX3.1"          "X.11"            "X.12"           
##  [29] "H3.4"            "H1.4"            "JMJD7.PLA2G4B"   "X.14"           
##  [33] "KRTAP4.4"        "RAB4B.EGLN2"     "X.15"            "X.16"           
##  [37] "H1.8"            "HLA.DQB1"        "X.17"            "NKX2.6"         
##  [41] "KRTAP9.7"        "KRTAP11.1"       "NKX2.5"          "KRTAP8.1"       
##  [45] "X.19"            "KRTAP19.1"       "H1.5"            "KRTAP6.1"       
##  [49] "H1.10"           "KRTAP5.5"        "KRTAP17.1"       "KRTAP21.2"      
##  [53] "H1.7"            "X.20"            "H1.6"            "H1.2"           
##  [57] "X.21"            "H3.5"            "X.22"            "H1.0"           
##  [61] "HLA.DRB1"        "KRTAP5.3"        "HLA.DQA1"        "X.23"           
##  [65] "H4.16"           "X.25"            "KRTAP4.1"        "HLA.DRB5"       
##  [69] "MT.ND6"          "MT.CO2"          "MT.CYB"          "MT.ND2"         
##  [73] "MT.ND5"          "MT.CO1"          "MT.ND3"          "MT.ND4"         
##  [77] "MT.ND1"          "MT.ATP6"         "MT.CO3"          "X.26"           
##  [81] "HLA.DOA"         "HLA.DMA"         "HLA.DRA"         "X.28"           
##  [85] "HLA.C"           "KRTAP5.11"       "KRTAP5.10"       "HLA.E"          
##  [89] "HLA.G"           "HLA.F"           "X.29"            "CLLU1.AS1"      
##  [93] "X.30"            "TRBV20OR9.2"     "KRTAP5.6"        "KRTAP5.2"       
##  [97] "KRTAP5.1"        "KRTAP19.8"       "HLA.A"           "X.31"           
## [101] "IGKV4.1"         "IGKV6.21"        "IGKV3D.20"       "IGLV10.54"      
## [105] "IGLV5.52"        "IGLV1.51"        "IGLV1.50"        "IGLV1.47"       
## [109] "IGLV7.46"        "IGLV1.44"        "IGLV7.43"        "IGLV1.40"       
## [113] "IGLV3.25"        "IGLV2.23"        "IGLV3.21"        "IGLV3.19"       
## [117] "IGLV3.16"        "IGLV2.14"        "IGLV2.11"        "IGLV3.9"        
## [121] "IGLV3.1"         "TRBV7.3"         "TRBV5.3"         "TRBV10.1"       
## [125] "TRBV6.5"         "TRBV6.6"         "TRBV7.6"         "TRBV5.1"        
## [129] "TRBV20.1"        "TRBV24.1"        "TRBJ2.1"         "TRBJ2.2P"       
## [133] "TRBJ2.3"         "TRBJ2.6"         "TRBJ2.7"         "TRAV12.3"       
## [137] "TRAV8.7"         "IGHD3.10"        "IGHV6.1"         "IGHV1.2"        
## [141] "IGHV1.3"         "IGHV2.5"         "IGHV3.7"         "IGHV3.11"       
## [145] "IGHV3.13"        "IGHV3.15"        "IGHV1.18"        "IGHV3.20"       
## [149] "IGHV3.21"        "IGHV3.23"        "IGHV1.24"        "IGHV2.26"       
## [153] "IGHV4.28"        "IGHV3.33"        "IGHV4.34"        "IGHV4.39"       
## [157] "IGHV3.49"        "IGHV5.51"        "IGHV3.66"        "IGHV3.73"       
## [161] "KRTAP16.1"       "KRTAP3.3"        "KRTAP3.2"        "MT.ND4L"        
## [165] "X.32"            "ZNF625.ZNF20"    "ERV3.1"          "X.33"           
## [169] "RPL17.C18orf32"  "KRTAP1.5"        "ZNF816.ZNF321P"  "IGHV3.64"       
## [173] "HLA.DPB1"        "IGHV4.59"        "IGHV3.74"        "APOC4.APOC2"    
## [177] "X.36"            "X.38"            "ERVMER34.1"      "X.39"           
## [181] "MT.ATP8"         "IGKV3D.7"        "TRBV5.4"         "X.40"           
## [185] "IGKV1OR2.108"    "HLA.DPA1"        "IGHV3.43"        "HLA.DQB2"       
## [189] "TRBV29.1"        "X.41"            "IGKV3OR2.268"    "HLA.B"          
## [193] "HNRNPUL2.BSCL2"  "NKX1.1"          "X.44"            "HLA.DQA2"       
## [197] "IGKV2D.30"       "IGKV1D.8"        "IGKV1.6"         "X.47"           
## [201] "IGKV3.20"        "IGKV1D.33"       "IGKV1.17"        "IGKV1.8"        
## [205] "IGKV1.16"        "HLA.DOB"         "KRTAP5.8"        "IGKV2.24"       
## [209] "IGKV3.11"        "X.48"            "KRTAP5.4"        "IGKV1.9"        
## [213] "X.50"            "IGKV1.33"        "IGKV1.39"        "IGKV2D.28"      
## [217] "HLA.DMB"         "IGKV1D.17"       "ERVW.1"          "PPAN.P2RY11"    
## [221] "IGKV2.30"        "IGKV2D.29"       "IGKV1.12"        "IGKV1.5"        
## [225] "X.51"            "X.52"            "DNAJC25.GNG10"   "KRTAP5.7"       
## [229] "IGKV3.15"        "KRTAP4.2"        "IGKV1.27"        "TRIM39.RPP21"   
## [233] "X.54"            "PRR5.ARHGAP8"    "STIMATE.MUSTN1"  "RBM14.RBM4"     
## [237] "LY75.CD302"      "X.55"            "X.56"            "TNFSF12.TNFSF13"
## [241] "ATP5MF.PTCD1"    "X.57"            "EPPIN.WFDC6"     "X.58"           
## [245] "X.59"            "X.60"            "X.61"            "X.62"           
## [249] "X.63"            "X.64"            "RNF103.CHMP3"    "X.66"           
## [253] "ARPIN.AP3S2"     "ARPC4.TTLL3"     "X.67"            "X.68"           
## [257] "X.69"            "LY6G6F.LY6G6D"   "X.70"            "CCDC169.SOHLH2" 
## [261] "NT5C1B.RDH14"    "X.71"            "X.72"            "X.73"           
## [265] "TMED7.TICAM2"    "X.74"            "MSANTD3.TMEFF1"  "X.75"           
## [269] "CENPS.CORT"      "X.76"            "X.77"            "TRBV7.4"        
## [273] "CHKB.CPT1B"      "X.78"            "X.79"            "X.80"           
## [277] "X.81"            "X.82"            "X.83"            "CKLF.CMTM1"     
## [281] "ATP6V1G2.DDX39B" "INMT.MINDY4"     "X.85"            "STX16.NPEPL1"   
## [285] "KRTAP5.9"        "X.86"            "SAA2.SAA4"       "ZFP91.CNTF"     
## [289] "X.87"            "MSH5.SAPCD1"     "FXYD6.FXYD2"     "X.88"           
## [293] "X.89"            "X.90"            "X.91"            "X.92"           
## [297] "X.93"            "NEDD8.MDP1"      "TRAV1.1"         "X.94"           
## [301] "X.96"            "X.97"            "KLRC4.KLRK1"     "X.98"           
## [305] "X.99"            "X.100"           "X.101"           "X.102"          
## [309] "X.103"           "X.104"           "TRAV1.2"         "X.107"          
## [313] "X.108"           "X.109"           "X.110"           "X.111"          
## [317] "X.112"           "X.113"           "SLCO1B3.SLCO1B7" "X.114"          
## [321] "X.115"           "X.117"           "X.118"           "X.120"          
## [325] "X.121"           "X.122"           "RPL36A.HNRNPH2"  "X.123"          
## [329] "X.124"           "P2RX5.TAX1BP3"   "X.125"           "X.126"          
## [333] "X.127"           "PPT2.EGFL8"      "X.129"           "X.130"          
## [337] "X.131"           "X.132"           "X.133"           "X.134"          
## [341] "SPECC1L.ADORA2A" "BCL2L2.PABPN1"   "X.137"           "X.138"          
## [345] "PINX1.1"         "X.140"           "X.141"           "X.142"          
## [349] "X.143"           "UBE2F.SCLY"      "X.144"           "FPGT.TNNI3K"    
## [353] "BLOC1S5.TXNDC5"  "X.146"           "POC1B.GALNT4"    "NDUFC2.KCTD14"  
## [357] "X.147"           "ZHX1.C8orf76"    "X.150"           "ST20.MTHFS"     
## [361] "X.151"           "TGIF2.RAB5IF"    "X.152"           "X.153"          
## [365] "X.155"           "X.156"           "X.158"           "X.159"          
## [369] "X.160"           "X.161"           "X.162"           "PMF1.BGLAP"     
## [373] "X.163"           "X.164"           "X.165"           "X.166"          
## [377] "X.169"           "X.170"           "X.171"           "X.172"          
## [381] "X.173"           "X.174"           "X.175"           "X.176"          
## [385] "TEN1.CDK3"       "X.177"           "X.178"           "X.179"          
## [389] "X.180"           "X.181"           "X.182"           "ISY1.RAB43"     
## [393] "X.183"           "X.184"           "X.185"           "X.186"          
## [397] "TMEM256.PLSCR3"  "X.191"           "X.192"           "X.193"          
## [401] "X.195"           "X.196"           "LINC02210.CRHR1" "X.197"          
## [405] "X.198"           "X.200"           "X.201"           "X.202"          
## [409] "X.203"           "X.205"           "CFAP298.TCP10L"  "X.206"          
## [413] "EEF1E1.BLOC1S5"  "X.207"           "X.208"           "X.209"          
## [417] "X.210"           "X.211"           "X.213"           "X.214"          
## [421] "X.215"           "X.216"           "X.217"           "X.218"          
## [425] "X.221"           "X.222"           "X.223"           "X.224"          
## [429] "X.225"           "X.226"           "X.227"           "X.228"          
## [433] "X.229"           "X.230"           "X.231"           "X.232"          
## [437] "X.233"           "X.234"           "X.235"           "X.236"          
## [441] "X.237"           "X.238"           "X.239"           "X.240"          
## [445] "X.241"           "X.242"           "X.244"           "X.245"          
## [449] "X.246"           "X.247"           "X.248"           "X.249"          
## [453] "X.250"           "X.251"           "X.252"           "X.253"          
## [457] "X.254"           "X.255"           "X.256"           "X.257"          
## [461] "X.258"           "X.259"           "X.260"           "X.261"          
## [465] "X.263"           "X.264"           "X.266"           "X.267"          
## [469] "X.268"           "X.269"           "X.270"           "MIA.RAB4B"      
## [473] "X.271"           "X.272"           "X.273"           "X.274"          
## [477] "X.275"           "X.276"           "X.277"           "X.279"          
## [481] "X.280"           "X.281"           "X.283"           "X.285"          
## [485] "X.286"           "X.288"           "ARHGAP19.SLIT1"  "COMMD3.BMI1"    
## [489] "ZNF559.ZNF177"   "X.289"           "TSNAX.DISC1"     "X.290"          
## [493] "X.291"           "X.292"           "BORCS7.ASMT"     "IGHV3.30"       
## [497] "URGCP.MRPS24"    "RPS10.NUDT3"     "TLCD4.RWDD3"     "X.293"
## These genes may be excluded from analysis. Proper gene names
## contain alphanumeric characters only, and start with a letter.
## Warning in CheckSampleIDs(assayData_df): Row names will be ignored. Sample IDs must be in the first column of the data
##   frame.
## Error in .convertPhenoDF(response, type = respType): Regression and categorical data must be a data frame with two columns, sample ID
##   and response, in exactly that order.
super <- AESPCA_pVals(
  object = tt,
  numPCs = 2,
  parallel = FALSE,
  numCores = 8,
  numReps = 2,
  adjustment = "BH")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'AESPCA_pVals': object 'tt' not found

16 Evaluating a log2FC barplot

Figure 2E is now comprised of a plot which shows log2FC values with error bars for selected genes and seeks to show differences between 2.3/uninfected and 2.2/uninfected.

Here is the table Olga used to generate it:

I went looking in the xlsx files produced in 202405 and found that these are the log2FC values and standard errors produced by DESeq2.

It should be noted that in my most recent version of these analyses, these numbers did shift slightly. I am looking into that now.

  • Data witout drug

** 2.3 vs Uninfected MØ 2.2 vs Uninfected MØ

16.1 | Gene | Mean | SEM | n | Mean | SEM |n |

|IFI27 | 7.224 | 0.5662 |6 | 2.702 | 0.5669 | 6| |RSAD2 | 6.29 | 0.7312 |6 | 1.623 | 0.7303 | 6| |CCL8 | 6.225 | 0.928 |6 | -0.314| 0.941 | 6| |IFI44L| 5.895 | 0.612 |6 | 2.06 | 0.611 | 6| |OASL | 4.726 | 0.4974 |6 | 1.392 | 0.4973 | 6| |USP18 | 3.644 | 0.483 |6 | 0.999 | 0.4826 | 6| |IDO1 | 7.145 | 1.107 |6 | 1.257 | 1.141 | 6| |IDO2 | 3.935 | 1.3 |6 | 2.557 | 1.341 | 6| |KYNU | 1.07 | 0.2186 |6 | 0.0207| 0.2184 | 6| |AHR | 0.9382 | 0.2236 |6 | 0.5032| 0.2239 | 6| |IL4I1 | 2.593 | 0.4623 |6 | 0.039 | 0.4618 | 6| |SOD2 | 2.76 | 0.349 |6 | 0.4241| 0.3528 | 6| |NOTCH1| 0.7572| 0.275 |6 | 1.495 | 0.2744 | 6| |DLL1 | 0.8268| 0.5285 |6 | 3.455 | 0.5228 | 6| |DLL4 | 1.116 | 0.737 |6 | 4.243 | 0.71 | 6| |HES1 | -0.0183| 0.8599 |6 | 6.536 | 0.7973 | 6| |HEY1 | 0.5533| 0.5789 |6 | 4.181 | 0.6273 | 6|

Ok, I think I found a problem: The NOTCH1 value is actually the adjusted p-value.

  • Transporters without drug

** 2.3 vs Uninfected MØ 2.2 vs Uninfected MØ

16.2 | Gene | Mean | SEM | n| Mean | SEM | n|

|ABCB1 | -2.354 | 0.442 | 6| -0.406| 0.431| 6| |ABCG4 | -3.715 | 0.648 | 6| -0.653| 0.630| 6| |ABCB5 | -1.192 | 0.380 | 6| 1.351 | 0.363| 6| |ABCA9 | 1.880 | 0.648 | 6| 3.444 | 0.637| 6| |ABCC2 | 0.454 | 0.321 | 6| 1.818 | 0.314| 6| |AQP2 | -1.191 | 0.529 | 6| 0.745 | 0.514| 6| |AQP3 | -0.940 | 0.402 | 6| 0.431 | 0.395| 6|

  • Transporters with drug

** 2.3 vs Uninfected MØ 2.2 vs Uninfected MØ

16.3 |Gene | Mean | SEM | n| Mean | SEM | n |

|ABCB1 | -0.697| 0.349 | 6| -1.255| 0.337 | 6| |ABCG4 | 1.231 | 0.503 | 6| 0.547 | 0.484 | 6| |AQP2 | 0.816 | 0.399 | 6| 0.043 | 0.387 | 6| |AQP3 | -1.286| 0.320 | 6| -1.613| 0.309 | 6| |AQP8 | 0.634 | 0.370 | 6| 0.943 | 0.365 | 6|

Let us now see if I can recapitulate the plot…

nodrug_contrasts <- c("z23nosb_vs_uninf", "z22nosb_vs_uninf")
genes_no_drug <- c("IFI27", "RSAD2", "CCL8", "IFI44L", "OASL", "USP18", "IDO1", "IDO2", "KYNU", "AHR", "IL4I1", "SOD2", "NOTCH1", "DLL1", "DLL4", "HES1", "HEY1")
transporters_no_drug <- c("ABCB1", "ABCG4", "ABCB5", "ABCA9", "ABCC2", "AQP2", "AQP3")
drug_contrasts <- c("z23sb_vs_sb", "z22sb_vs_sb")
transporters_drug <- c("ABCB1", "ABCG4", "AQP2", "AQP3", "AQP8")

These values came out of the data structure called ‘hs_macr_table’

z23nosb_uninf_values <- hs_macr_table[["data"]][["z23nosb_vs_uninf"]]
gene_idx <- z23nosb_uninf_values[["hgnc_symbol"]] %in% genes_no_drug
nodrug_rows <-  z23nosb_uninf_values[gene_idx, ]
rownames(nodrug_rows) <- nodrug_rows[["hgnc_symbol"]]
z23_nodrug_values <- nodrug_rows[, c("deseq_logfc", "deseq_lfcse")]
z23_nodrug_values
## DataFrame with 17 rows and 2 columns
##       deseq_logfc deseq_lfcse
##         <numeric>   <numeric>
## IL4I1     2.59300      0.4623
## AHR       0.93810      0.2236
## CCL8      6.22500      0.9280
## SOD2      2.76000      0.3490
## HES1     -0.01786      0.8599
## ...           ...         ...
## HEY1       0.5531      0.6520
## IFI27      7.2240      0.5662
## USP18      3.6440      0.4830
## IDO2       3.9340      1.2990
## DLL1       0.8268      0.5284
z22nosb_uninf_values <- hs_macr_table[["data"]][["z22nosb_vs_uninf"]]
gene_idx <- z22nosb_uninf_values[["hgnc_symbol"]] %in% genes_no_drug
nodrug_rows <-  z22nosb_uninf_values[gene_idx, ]
rownames(nodrug_rows) <- nodrug_rows[["hgnc_symbol"]]
z22_nodrug_values <- nodrug_rows[, c("deseq_logfc", "deseq_lfcse")]
z22_nodrug_values
## DataFrame with 17 rows and 2 columns
##       deseq_logfc deseq_lfcse
##         <numeric>   <numeric>
## IL4I1     0.03995      0.4618
## AHR       0.50310      0.2239
## CCL8     -0.31360      0.9406
## SOD2      0.42410      0.3528
## HES1      6.53600      0.7973
## ...           ...         ...
## HEY1        4.181      0.6273
## IFI27       2.702      0.5669
## USP18       0.999      0.4826
## IDO2        2.557      1.3410
## DLL1        3.455      0.5228
z23_nodrug_values[["state"]] <- "z23_vs_uninfected"
z22_nodrug_values[["state"]] <- "z22_vs_uninfected"
plot_df <- rbind.data.frame(as.data.frame(z23_nodrug_values), as.data.frame(z22_nodrug_values))
plot_df[["gene"]] <- rownames(plot_df)

## I just realized that this is actually just a comparison of z23/z22
## we should just take the adjusted p-values from that contrast for this.
z23_z22_comparison <- hs_macr_table[["data"]][["z23nosb_vs_z22nosb"]]
nodrug_rows <- z23_z22_comparison[gene_idx, ]
nodrug_pvalues <- nodrug_rows[, c("deseq_p", "deseq_adjp")]
rownames(nodrug_pvalues) <- nodrug_rows[["hgnc_symbol"]]
nodrug_pvalues
## DataFrame with 17 rows and 2 columns
##         deseq_p deseq_adjp
##       <numeric>  <numeric>
## IL4I1 1.250e-13  3.949e-12
## AHR   8.308e-03  2.421e-02
## CCL8  3.677e-21  4.197e-19
## SOD2  6.181e-20  5.813e-18
## HES1  9.422e-38  2.215e-34
## ...         ...        ...
## HEY1  9.854e-17  5.410e-15
## IFI27 6.486e-28  2.310e-25
## USP18 1.772e-13  5.467e-12
## IDO2  1.047e-01  1.895e-01
## DLL1  4.352e-12  1.103e-10
ggplot(plot_df, aes(x = gene, y = deseq_logfc, fill = state)) +
  geom_bar(position = position_dodge(), stat = "identity") +
  geom_errorbar(aes(ymin = deseq_logfc - deseq_lfcse,
                    ymax = deseq_logfc + deseq_lfcse),
                width = 0.2, position = position_dodge(0.9)) +
  scale_fill_manual(values = c("#1B9E77", "#7570B3")) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

comparison <- c("z23_vs_uninfected", "z22_vs_uninfected")
comparisons <- rep(list(comparison), nrow(plot_df) / 2)
ggplot(plot_df, aes(x = gene, y = deseq_logfc, fill = state, add = deseq_lfcse, facet.by = "state")) +
  geom_bar(position = position_dodge(), stat = "identity") +
  geom_errorbar(aes(ymin = deseq_logfc - deseq_lfcse,
                    ymax = deseq_logfc + deseq_lfcse),
                width = 0.2, position = position_dodge(0.9)) +
  stat_compare_means() +
  stat_compare_means(comparisons = comparisons, label.y = rownames(z23_nodrug_values)) +
  scale_fill_manual(values = c("#1B9E77", "#7570B3")) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5))
## Error in stat_compare_means(): could not find function "stat_compare_means"

Excellent, the values now match up. Now I ust need to figure out why the stupid hgnc IDs got lost… I can see them in the hs_annot data structure, so I must have messed up when I regenered the input to the de. Ok, I got to the same starting point now with identical values. As soon as I did that, I looked at the resulting plot and realized that we are actually just comparing z23 / z22.

Here is why: the plot as it stands is a comparison of the log2FC values of the following two contrasts: z23/uninfected and z22/uninfected; stated differently, this is (z23/uninf)/(z22/uninf) which of course cancels out to just z23/z22.

Therefore it is much more parsimonious to just use the values from z23/z22. I swear I have gone through this exact exercise on so so many occasions in the past it is terrible.

16.4 ggsignificance of the immune modulators

wanted_genes <- c("IFI27", "RSAD2", "CCL8", "IFI44L", "OASL",
                  "USP18", "IDO1", "IDO2", "KYNU", "AHR", "IL4I1",
                  "SOD2", "NOTCH1", "DLL1", "DLL4", "HES1", "HEY1")
modulator_plot <- ggsignif_paired_genes(
  hs_macr, conditions = c("inf_z23", "inf_z22"), genes = wanted_genes)
## Running normalize_se.
## Warning in normalize_se(exp, ...): Quantile normalization and sva do not always
## play well together.
## Removing 9725 low-count genes (11756 remaining).
## transform_counts: Found 2226 values less than 0.
## Warning in transform_counts(count_table, method = transform, ...): NaNs
## produced
## Setting 34233 entries to zero.
## Using Row.names, ensembl_gene_id, ensembl_transcript_id, description, gene_biotype, cds_length, chromosome_name, strand, hgnc_symbol, transcript as id variables
## Error in ggsignif_paired_genes(hs_macr, conditions = c("inf_z23", "inf_z22"), : object 'merged' not found
modulator_plot
## Error: object 'modulator_plot' not found

16.5 ggsignificance of the transporters

## First line is without drug
wanted_genes <- c("ABCB1", "ABCG4", "ABCB5", "AQP2", "AQP3",
                  ## with drug
                  "ABCB1", "ABCG4", "AQP2", "AQP3", "AQP8")
transporter_plot <- ggsignif_paired_genes(
  hs_macr, conditions = c("inf_z23", "inf_z22"), genes = wanted_genes)
## Running normalize_se.
## Warning in normalize_se(exp, ...): Quantile normalization and sva do not always
## play well together.
## Removing 9725 low-count genes (11756 remaining).
## transform_counts: Found 2226 values less than 0.
## Warning in transform_counts(count_table, method = transform, ...): NaNs
## produced
## Setting 34233 entries to zero.
## Error in `dplyr::arrange()` at magrittr/R/pipe.R:136:3:
## i In argument: `..1 = factor(hgnc_symbol, levels = genes)`.
## Caused by error in `levels<-`:
## ! factor level [6] is duplicated
transporter_plot
## Error: object 'transporter_plot' not found
pander::pander(sessionInfo())
## Warning: Your system is mis-configured: '/etc/localtime' is not a symlink
## Warning: It is strongly recommended to set envionment variable TZ to
## 'America/New_York' (or equivalent)

R version 4.5.0 (2025-04-11)

Platform: x86_64-pc-linux-gnu

locale: C

attached base packages: grid, stats4, stats, graphics, grDevices, utils, datasets, methods and base

other attached packages: rWikiPathways(v.1.28.0), pathwayPCA(v.1.24.0), Rgraphviz(v.2.52.0), graph(v.1.86.0), SparseM(v.1.84-2), topGO(v.2.60.1), GSVAdata(v.1.44.0), org.Hs.eg.db(v.3.21.0), AnnotationDbi(v.1.70.0), IRanges(v.2.42.0), S4Vectors(v.0.46.0), Biobase(v.2.68.0), BiocGenerics(v.0.54.0), generics(v.0.1.4), ReactomePA(v.1.52.0), edgeR(v.4.6.3), ruv(v.0.9.7.1), ggstatsplot(v.0.13.1), enrichplot(v.1.28.4), tidyr(v.1.3.1), tibble(v.3.3.0), UpSetR(v.1.4.0), hpgltools(v.1.2), Heatplus(v.3.16.0), glue(v.1.8.0), ggplot2(v.3.5.2) and ggbreak(v.0.1.6)

loaded via a namespace (and not attached): R.methodsS3(v.1.8.2), dichromat(v.2.0-0.1), GSEABase(v.1.70.0), progress(v.1.2.3), Biostrings(v.2.76.0), vctrs(v.0.6.5), ggtangle(v.0.0.7), shape(v.1.4.6.1), effectsize(v.1.0.1), digest(v.0.6.37), png(v.0.1-8), corpcor(v.1.6.10), DEGreport(v.1.44.0), ggrepel(v.0.9.6), bayestestR(v.0.17.0), correlation(v.0.8.8), magick(v.2.9.0), MASS(v.7.3-65), reshape(v.0.8.10), reshape2(v.1.4.4), httpuv(v.1.6.16), foreach(v.1.5.2), qvalue(v.2.40.0), withr(v.3.0.2), psych(v.2.5.6), xfun(v.0.53), ggfun(v.0.2.0), survival(v.3.8-3), memoise(v.2.0.1), clusterProfiler(v.4.16.0), gson(v.0.1.0), BiasedUrn(v.2.0.12), parameters(v.0.28.1), GlobalOptions(v.0.1.2), tidytree(v.0.4.6), gtools(v.3.9.5), logging(v.0.10-108), R.oo(v.1.27.1), DEoptimR(v.1.1-4), prettyunits(v.1.2.0), datawizard(v.1.2.0), rematch2(v.2.1.2), KEGGREST(v.1.48.1), promises(v.1.3.3), httr(v.1.4.7), restfulr(v.0.0.16), meshes(v.1.34.0), UCSC.utils(v.1.4.0), DOSE(v.4.2.0), reactome.db(v.1.92.0), curl(v.7.0.0), ggraph(v.2.2.2), polyclip(v.1.10-7), GenomeInfoDbData(v.1.2.14), SparseArray(v.1.8.1), RBGL(v.1.84.0), RcppEigen(v.0.3.4.0.2), doParallel(v.1.0.17), xtable(v.1.8-4), stringr(v.1.5.1), desc(v.1.4.3), evaluate(v.1.0.4), S4Arrays(v.1.8.1), BiocFileCache(v.2.16.1), preprocessCore(v.1.70.0), hms(v.1.1.3), GenomicRanges(v.1.60.0), colorspace(v.2.1-1), filelock(v.1.0.3), magrittr(v.2.0.3), later(v.1.4.3), viridis(v.0.6.5), ggtree(v.3.17.1.001), lattice(v.0.22-7), genefilter(v.1.90.0), robustbase(v.0.99-6), XML(v.3.99-0.19), cowplot(v.1.2.0), matrixStats(v.1.5.0), ggupset(v.0.4.1), pillar(v.1.11.0), nlme(v.3.1-168), iterators(v.1.0.14), caTools(v.1.18.3), compiler(v.4.5.0), stringi(v.1.8.7), minqa(v.1.2.8), SummarizedExperiment(v.1.38.1), GenomicAlignments(v.1.44.0), plyr(v.1.8.9), BiocIO(v.1.18.0), crayon(v.1.5.3), abind(v.1.4-8), ggdendro(v.0.2.0), gridGraphics(v.0.5-1), locfit(v.1.5-9.12), graphlayouts(v.1.2.2), bit(v.4.6.0), dplyr(v.1.1.4), fastmatch(v.1.1-6), codetools(v.0.2-20), crosstalk(v.1.2.1), bslib(v.0.9.0), paletteer(v.1.6.0), GetoptLong(v.1.0.5), plotly(v.4.11.0), remaCor(v.0.0.20), mime(v.0.13), splines(v.4.5.0), circlize(v.0.4.16), Rcpp(v.1.1.0), dbplyr(v.2.5.0), lars(v.1.3), knitr(v.1.50), blob(v.1.2.4), clue(v.0.3-66), BiocVersion(v.3.21.1), lme4(v.1.1-37), fs(v.1.6.6), Rdpack(v.2.6.4), EBSeq(v.2.6.0), openxlsx(v.4.2.8), ggplotify(v.0.1.2), Matrix(v.1.7-3), statmod(v.1.5.0), fANCOVA(v.0.6-1), tweenr(v.2.0.3), pkgconfig(v.2.0.3), tools(v.4.5.0), cachem(v.1.1.0), RhpcBLASctl(v.0.23-42), rbibutils(v.2.3), RSQLite(v.2.4.3), viridisLite(v.0.4.2), DBI(v.1.2.3), numDeriv(v.2016.8-1.1), graphite(v.1.54.0), fastmap(v.1.2.0), rmarkdown(v.2.29), scales(v.1.4.0), gprofiler2(v.0.2.3), Rsamtools(v.2.24.0), broom(v.1.0.9), AnnotationHub(v.3.16.1), sass(v.0.4.10), patchwork(v.1.3.2), BiocManager(v.1.30.26), insight(v.1.4.2), varhandle(v.2.0.6), farver(v.2.1.2), reformulas(v.0.4.1), aod(v.1.3.3), tidygraph(v.1.3.1), mgcv(v.1.9-3), yaml(v.2.3.10), MatrixGenerics(v.1.20.0), rtracklayer(v.1.68.0), cli(v.3.6.5), purrr(v.1.1.0), txdbmaker(v.1.4.2), lifecycle(v.1.0.4), mvtnorm(v.1.3-3), backports(v.1.5.0), Vennerable(v.3.1.0.9000), BiocParallel(v.1.42.1), annotate(v.1.86.1), MeSHDbi(v.1.44.0), rjson(v.0.2.23), gtable(v.0.3.6), parallel(v.4.5.0), ape(v.5.8-1), testthat(v.3.2.3), limma(v.3.64.3), jsonlite(v.2.0.0), bitops(v.1.0-9), NOISeq(v.2.52.0), bit64(v.4.6.0-1), brio(v.1.1.5), yulab.utils(v.0.2.1), zip(v.2.3.3), geneLenDataBase(v.1.44.0), RcppParallel(v.5.1.11-1), jquerylib(v.0.1.4), GOSemSim(v.2.34.0), zeallot(v.0.2.0), R.utils(v.2.13.0), pbkrtest(v.0.5.5), lazyeval(v.0.2.2), pander(v.0.6.6), ConsensusClusterPlus(v.1.72.0), shiny(v.1.11.1), htmltools(v.0.5.8.1), GO.db(v.3.21.0), rappdirs(v.0.3.3), blockmodeling(v.1.1.8), tinytex(v.0.57), httr2(v.1.2.1), XVector(v.0.48.0), RCurl(v.1.98-1.17), rprojroot(v.2.1.0), treeio(v.1.32.0), mnormt(v.2.1.1), gridExtra(v.2.3), ggsankey(v.0.0.99999), EnvStats(v.3.1.0), boot(v.1.3-31), igraph(v.2.1.4), variancePartition(v.1.38.1), R6(v.2.6.1), sva(v.3.56.0), DESeq2(v.1.48.1), gplots(v.3.2.0), labeling(v.0.4.3), GenomicFeatures(v.1.60.0), cluster(v.2.1.8.1), pkgload(v.1.4.0), aplot(v.0.2.8), GenomeInfoDb(v.1.44.2), nloptr(v.2.2.1), rstantools(v.2.5.0), DelayedArray(v.0.34.1), tidyselect(v.1.2.1), xml2(v.1.4.0), ggforce(v.0.5.0), statsExpressions(v.1.7.1), goseq(v.1.60.0), KernSmooth(v.2.23-26), data.table(v.1.17.8), ComplexHeatmap(v.2.24.1), htmlwidgets(v.1.6.4), fgsea(v.1.34.2), RColorBrewer(v.1.1-3), biomaRt(v.2.64.0), rlang(v.1.1.6), lmerTest(v.3.1-3) and ggnewscale(v.0.5.2)

message("This is hpgltools commit: ", get_git_commit())
## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset 2315e0db2bd684765eb5d29c71cfe08dc63b4322
## This is hpgltools commit: Mon Sep 8 13:30:32 2025 -0400: 2315e0db2bd684765eb5d29c71cfe08dc63b4322
tmp <- saveme(filename = savefile)
## The savefile is: /lab/singularity/tmrc2_macrophage_deb/202509081525_outputs/savefiles/03differential_expression.rda.xz
## The file does not yet exist.
## The save string is: con <- pipe(paste0('pxz > /lab/singularity/tmrc2_macrophage_deb/202509081525_outputs/savefiles/03differential_expression.rda.xz'), 'wb'); save(list = ls(all.names = TRUE, envir = globalenv()),
##      envir = globalenv(), file = con, compress = FALSE); close(con)
## Error in save(list = ls(all.names = TRUE, envir = globalenv()), envir = globalenv(), : ignoring SIGPIPE signal
tmp <- loadme(filename = savefile)

devtools::load_all(‘~/hpgltools’)

LS0tCnRpdGxlOiAiVE1SQzIgYHIgU3lzLmdldGVudignVkVSU0lPTicpYDogTWFjcm9waGFnZSBEaWZmZXJlbnRpYWwgRXhwcmVzc2lvbi4iCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICB0aGVtZTogcmVhZGFibGUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KYm9keSAubWFpbi1jb250YWluZXIgewogIG1heC13aWR0aDogMTYwMHB4Owp9CmJvZHksIHRkIHsKICBmb250LXNpemU6IDE2cHg7Cn0KY29kZS5yewogIGZvbnQtc2l6ZTogMTZweDsKfQpwcmUgewogIGZvbnQtc2l6ZTogMTZweAp9Cjwvc3R5bGU+CgpgYGB7ciBvcHRpb25zLCBpbmNsdWRlID0gRkFMU0V9CmxpYnJhcnkoZ2dicmVhaykKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdsdWUpCmxpYnJhcnkoSGVhdHBsdXMpCmxpYnJhcnkoaHBnbHRvb2xzKQpsaWJyYXJ5KFVwU2V0UikKbGlicmFyeSh0aWJibGUpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZW5yaWNocGxvdCkKbGlicmFyeShnZ3N0YXRzcGxvdCkKCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHByb2dyZXNzID0gVFJVRSwgdmVyYm9zZSA9IFRSVUUsIHdpZHRoID0gOTAsIGVjaG8gPSBUUlVFKQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZXJyb3IgPSBUUlVFLCBmaWcud2lkdGggPSA4LCBmaWcuaGVpZ2h0ID0gOCwgZmlnLnJldGluYSA9IDIsCiAgb3V0LndpZHRoID0gIjEwMCUiLCBkZXYgPSAicG5nIiwKICBkZXYuYXJncyA9IGxpc3QocG5nID0gbGlzdCh0eXBlID0gImNhaXJvLXBuZyIpKSkKb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHMgPSA0LCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbCA9ICJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMikpCnZlciA8LSBTeXMuZ2V0ZW52KCJWRVJTSU9OIikKcHJldmlvdXNfZmlsZSA8LSAiIgpydW5kYXRlIDwtIGZvcm1hdChTeXMuRGF0ZSgpLCBmb3JtYXQgPSAiJVklbSVkIikKCiMjIHRtcCA8LSB0cnkoc20obG9hZG1lKGZpbGVuYW1lID0gZ3N1YihwYXR0ZXJuID0gIlxcLlJtZCIsIHJlcGxhY2UgPSAiXFwucmRhXFwueHoiLCB4ID0gcHJldmlvdXNfZmlsZSkpKSkKcm1kX2ZpbGUgPC0gIjAzZGlmZmVyZW50aWFsX2V4cHJlc3Npb24uUm1kIgpsb2FkZWQgPC0gbG9hZChmaWxlID0gZ2x1ZSgicmRhL3RtcmMyX2RhdGFfc3RydWN0dXJlcy12e3Zlcn0ucmRhIikpCnNhdmVmaWxlIDwtIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLCByZXBsYWNlID0gIlxcLnJkYVxcLnh6IiwgeCA9IHJtZF9maWxlKQpjcmVhdGVkIDwtIGRpci5jcmVhdGUoImFuYWx5c2VzIikKYGBgCgojIENoYW5nZWxvZwoKKiAyMDI0MDEtMjAyNDA1OiBDbGVhbnVwcywgZm9ybWF0dGluZywgZW5zdXJpbmcgdGhhdCBldmVyeXRoaW5nIHdvcmtzIGluIHRoZSBjb250YWluZXIuCiogMjAyMzEwOiBDbGVhbmluZyB1cCB0byBtYWtlIGV2ZXJ5dGhpbmcgcGFzcyB3aXRoaW4gYSBjb250YWluZXJpemVkIGVudmlyb25tZW50LgoqIDIwMjMxMDogUmVjZWl2ZWQgYSBzZXQgb2YgY29sb3JzIGFuZCBjb250cmFzdHMgb2YgaW50ZXJlc3QgZm9yIGEgYmFycGxvdCBvZiBzaWduaWZpY2FuY2UuCiogMjAyMzA0MTA6IE1ha2luZyBzb21lIGNoYW5nZXMgdG8gaW1wcm92ZSB0aGUgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24KICBwbG90cyBhcyB3ZWxsIGFzIHByZXBhcmUgZm9yIHNvbWUgZGlmZmVyZW50IHBhdGh3YXkvR1NFQS9HU1ZBCiAgYW5hbHlzZXMgb24gdGhlIGRhdGEuCgojIEludHJvZHVjdGlvbgoKSGF2aW5nIGVzdGFibGlzaGVkIHRoYXQgdGhlIFRNUkMyIG1hY3JvcGhhZ2UgZGF0YSBsb29rcyByb2J1c3QgYW5kCmlsbHVzdHJhdGl2ZSBvZiBhIGNvdXBsZSBvZiBpbnRlcmVzdGluZyBxdWVzdGlvbnMsIGxldCB1cyBwZXJmb3JtIGEKY291cGxlIG9mIGRpZmZlcmVudGlhbCBhbmFseXNlcyBvZiBpdC4KCkFsc28gbm90ZSB0aGF0IGFzIG9mIDIwMjIxMiwgd2UgcmVjZWl2ZWQgYSBuZXcgc2V0IG9mIHNhbXBsZXMgd2hpY2gKbm93IGluY2x1ZGUgc29tZSB3aGljaCBhcmUgYSBjb21wbGV0ZWx5IGRpZmZlcmVudCBjZWxsIHR5cGUsClU5MzcuICBBcyB0aGVpciBBVENDIHBhZ2Ugc3RhdGVzLCB0aGV5IGFyZSBtYWxpZ25hbnQgY2VsbHMgdGFrZW4gZnJvbQp0aGUgcGxldXJhbCBlZmZ1c2lvbiBvZiBhIDM3IHllYXIgb2xkIHdoaXRlIG1hbGUgd2l0aCBoaXN0aW9jeXRpYwpseW1waG9tYSBhbmQgd2hpY2ggZXhoaWJpdCB0aGUgbW9ycGhvbG9neSBvZiBtb25vY3l0ZXMuICBUaHVzLCB0aGlzCmRvY3VtZW50IG5vdyBpbmNsdWRlcyBzb21lIGNvbXBhcmlzb25zIG9mIHRoZSBjZWxsIHR5cGVzIGFzIHdlbGwgYXMKdGhlIHZhcmlvdXMgbWFjcm9waGFnZSBkb25vcnMgKGdpdmVuIHRoYXQgdGhlcmUgYXJlIG5vdyBtb3JlIGRvbm9ycwp0b28pLgoKIyMgSHVtYW4gZGF0YQoKSSBhbSBtb3ZpbmcgdGhlIGRhdGFzZXQgbWFuaXB1bGF0aW9ucyBoZXJlIHNvIHRoYXQgSSBjYW4gbG9vayBhdCB0aGVtCmFsbCB0b2dldGhlciBiZWZvcmUgcnVubmluZyB0aGUgdmFyaW91cyBERSBhbmFseXNlcy4KCiMjIENyZWF0ZSBzZXRzIGZvY3VzZWQgb24gZHJ1ZywgY2VsbHR5cGUsIHN0cmFpbiwgYW5kIGNvbWJpbmF0aW9ucwoKTGV0IHVzIHN0YXJ0IGJ5IHBsYXlpbmcgd2l0aCB0aGUgbWV0YWRhdGEgYSBsaXR0bGUgYW5kIGNyZWF0ZSBzZXRzCndpdGggdGhlIGNvbmRpdGlvbiBzZXQgdG86CgoqIERydWcgdHJlYXRtZW50CiogQ2VsbCB0eXBlIChtYWNyb3BoYWdlIG9yIFU5MzcpCiogRG9ub3IKKiBJbmZlY3Rpb24gU3RyYWluCiogU29tZSB1c2VmdWwgY29tYmluYXRpb25zIHRoZXJlb2YKCkluIGFkZGl0aW9uLCBrZWVwIG1lbnRhbCB0cmFjayBvZiB3aGljaCBkYXRhc2V0cyBhcmUgY29tcHJpc2VkIG9mIGFsbApzYW1wbGVzIHZzLiB0aG9zZSB3aGljaCBhcmUgb25seSBtYWNyb3BoYWdlIHZzLiB0aG9zZSB3aGljaCBhcmUgb25seQpVOTM3LiAgKFRodXMsIHRoZSB1c2FnZSBvZiBhbGxfaHVtYW4gdnMuIGhzX21hY3IgdnMuIHU5MzcgYXMgcHJlZml4ZXMKZm9yIHRoZSBkYXRhIHN0cnVjdHVyZXMuKQoKSWRlYWxseSwgdGhlc2UgcmVjcmVhdGlvbnMgb2YgdGhlIGRhdGEgc2hvdWxkIHBlcmhhcHMgYmUgaW4gdGhlCmRhdGFzdHJ1Y3R1cmVzIHdvcmtzaGVldC4KCmBgYHtyfQphbGxfaHVtYW4gPC0gc2FuaXRpemVfbWV0YWRhdGEoaHNfbWFjcm9waGFnZSwgY29sdW1ucyA9ICJkcnVnIikgJT4lCiAgc2V0X2NvbmRpdGlvbnMoZmFjdCA9ICJkcnVnIiwgY29sb3JzID0gY29sb3JfY2hvaWNlc1tbImRydWciXV0pICU+JQogIHNldF9iYXRjaGVzKGZhY3QgPSAidHlwZW9mY2VsbHMiKQoKIyMgVGhlIGZvbGxvd2luZyAzIGxpbmVzIHdlcmUgY29weS9wYXN0ZWQgdG8gZGF0YXN0cnVjdHVyZXMgYW5kIHNob3VsZCBiZSByZW1vdmVkIHNvb24uCm5vX3N0cmFpbl9pZHggPC0gY29sRGF0YShhbGxfaHVtYW4pW1sic3RyYWluaWQiXV0gPT0gIm5vbmUiCiMjY29sRGF0YShhbGxfaHVtYW4pW1sic3RyYWluaWQiXV0gPC0gcGFzdGUwKCJzIiwgY29sRGF0YShhbGxfaHVtYW4pW1sic3RyYWluaWQiXV0sCiMjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXyIsIGNvbERhdGEoYWxsX2h1bWFuKVtbIm1hY3JvcGhhZ2V6eW1vZGVtZSJdXSkKY29sRGF0YShhbGxfaHVtYW4pW25vX3N0cmFpbl9pZHgsICJzdHJhaW5pZCJdIDwtICJub25lIgp0YWJsZShjb2xEYXRhKGFsbF9odW1hbilbWyJzdHJhaW5pZCJdXSkKCmFsbF9odW1hbl90eXBlcyA8LSBzZXRfY29uZGl0aW9ucyhhbGxfaHVtYW4sIGZhY3QgPSAidHlwZW9mY2VsbHMiKSAlPiUKICBzZXRfYmF0Y2hlcyhmYWN0ID0gImRydWciKQoKdHlwZV96eW1vX2ZhY3QgPC0gcGFzdGUwKGNvbERhdGEoYWxsX2h1bWFuX3R5cGVzKVtbImNvbmRpdGlvbiJdXSwgIl8iLAogICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YShhbGxfaHVtYW5fdHlwZXMpW1sibWFjcm9waGFnZXp5bW9kZW1lIl1dKQp0eXBlX3p5bW8gPC0gc2V0X2NvbmRpdGlvbnMoYWxsX2h1bWFuX3R5cGVzLCBmYWN0ID0gdHlwZV96eW1vX2ZhY3QpCgp0eXBlX2RydWdfZmFjdCA8LSBwYXN0ZTAoY29sRGF0YShhbGxfaHVtYW5fdHlwZXMpW1siY29uZGl0aW9uIl1dLCAiXyIsCiAgICAgICAgICAgICAgICAgICAgICAgICBjb2xEYXRhKGFsbF9odW1hbl90eXBlcylbWyJkcnVnIl1dKQp0eXBlX2RydWcgPC0gc2V0X2NvbmRpdGlvbnMoYWxsX2h1bWFuX3R5cGVzLCBmYWN0ID0gdHlwZV9kcnVnX2ZhY3QpCgpzdHJhaW5fZmFjdCA8LSBjb2xEYXRhKGFsbF9odW1hbl90eXBlcylbWyJzdHJhaW5pZCJdXQp0YWJsZShzdHJhaW5fZmFjdCkKCm5ld19jb25kaXRpb25zIDwtIHBhc3RlMChjb2xEYXRhKGhzX21hY3JvcGhhZ2UpW1sibWFjcm9waGFnZXRyZWF0bWVudCJdXSwgIl8iLAogICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YShoc19tYWNyb3BoYWdlKVtbIm1hY3JvcGhhZ2V6eW1vZGVtZSJdXSkKIyMgTm90ZSB0aGUgc2FuaXRpemUoKSBjYWxsIGlzIHJlZHVuZGFudCB3aXRoIHRoZSBhZGRpdGlvbiBvZiBzYW5pdGl6ZSgpIGluIHRoZQojIyBkYXRhc3RydWN0dXJlcyBmaWxlLCBidXQgSSBkb24ndCB3YW50IHRvIHdhaXQgdG8gcmVydW4gdGhhdC4KaHNfbWFjciA8LSBzZXRfY29uZGl0aW9ucyhoc19tYWNyb3BoYWdlLCBmYWN0ID0gbmV3X2NvbmRpdGlvbnMpICU+JQogIHNhbml0aXplX21ldGFkYXRhKGNvbHVtbiA9ICJkcnVnIikgJT4lCiAgc3Vic2V0X3NlKHN1YnNldCA9ICJ0eXBlb2ZjZWxscyE9J1U5MzcnIikgJT4lCiAgc2V0X3NlX2NvbG9ycyhjb2xvcl9jaG9pY2VzW1sidHJlYXRtZW50X3p5bW8iXV0pCmBgYAoKIyMjIFNlcGFyYXRlIE1hY3JvcGhhZ2Ugc2FtcGxlcwoKT25jZSBhZ2Fpbiwgd2Ugc2hvdWxkIHJlY29uc2lkZXIgd2hlcmUgdGhlIGZvbGxvd2luZyBibG9jayBpcyBwbGFjZWQsCmJ1dCB0aGVzZSBkYXRhc3RydWN0dXJlcyBhcmUgbGlrZWx5IHRvIGJlIHVzZWQgaW4gbWFueSBvZiB0aGUKZm9sbG93aW5nIGFuYWx5c2VzLgoKYGBge3J9CmhzX21hY3JfZHJ1Z19zZSA8LSBzZXRfY29uZGl0aW9ucyhoc19tYWNyLCBmYWN0ID0gImRydWciLCBjb2xvcnMgPSBjb2xvcl9jaG9pY2VzW1siZHJ1ZyJdXSkKCmhzX21hY3Jfc3RyYWluX3NlIDwtIHNldF9jb25kaXRpb25zKGhzX21hY3IsIGZhY3QgPSAibWFjcm9waGFnZXp5bW9kZW1lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcnMgPSBjb2xvcl9jaG9pY2VzW1sienltbyJdXSkgJT4lCiAgc3Vic2V0X3NlKHN1YnNldCA9ICJtYWNyb3BoYWdlenltb2RlbWUgIT0gJ25vbmUnIikKCnRhYmxlKGNvbERhdGEoaHNfbWFjcilbWyJzdHJhaW5pZCJdXSkKYGBgCgojIyMgUmVmYWN0b3IgVTkzNyBzYW1wbGVzCgpUaGUgVTkzNyBzYW1wbGVzIHdlcmUgc2VwYXJhdGVkIGluIHRoZSBkYXRhc3RydWN0dXJlcyBmaWxlLCBidXQgd2UKd2FudCB0byB1c2UgdGhlIGNvbWJpbmF0aW9uIG9mIGRydWcvenltb2RlbWUgd2l0aCB0aGVtIHByZXR0eSBtdWNoCmV4Y2x1c2l2ZWx5LgoKYGBge3J9Cm5ld19jb25kaXRpb25zIDwtIHBhc3RlMChjb2xEYXRhKGhzX3U5MzcpW1sibWFjcm9waGFnZXRyZWF0bWVudCJdXSwgIl8iLAogICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YShoc191OTM3KVtbIm1hY3JvcGhhZ2V6eW1vZGVtZSJdXSkKdTkzN19zZSA8LSBzZXRfY29uZGl0aW9ucyhoc191OTM3LCBmYWN0ID0gbmV3X2NvbmRpdGlvbnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcnMgPSBjb2xvcl9jaG9pY2VzW1sidHJlYXRtZW50X3p5bW8iXV0pCmBgYAoKIyMgQ29udHJhc3RzIHVzZWQgaW4gdGhpcyBkb2N1bWVudAoKR2l2ZW4gdGhlIHZhcmlvdXMgd2F5cyB3ZSBoYXZlIGNob3BwZWQgdXAgdGhpcyBkYXRhc2V0LCB0aGVyZSBhcmUgYQpmZXcgZ2VuZXJhbCB0eXBlcyBvZiBjb250cmFzdHMgd2Ugd2lsbCBwZXJmb3JtLCB3aGljaCB3aWxsIHRoZW4gYmUKY29tYmluZWQgaW50byBncmVhdGVyIGNvbXBsZXhpdHk6CgoqIGRydWcgdHJlYXRtZW50OiBBbnRpbW9uYWwgdHJlYXRlZCBvciBub3QuCiogc3RyYWlucyB1c2VkOiBVbmluZmVjdGVkLCB6Mi4zLCBhbmQgejIuMi4KKiBjZWxsbHR5cGVzOiBVOTM3IG9yIG1hY3JvcGhhZ2UuCiogZG9ub3JzOiBUaGUgcGVyc29uIGZyb20gd2hvbSB0aGUgbWFjcm9waGFnZXMgd2VyZSB0YWtlbi4KCkluIHRoZSBlbmQsIG91ciBhY3R1YWwgZ29hbCBpcyB0byBjb25zaWRlciB0aGUgdmFyaWFibGUgZWZmZWN0cyBvZgpkcnVnK3N0cmFpbiBhbmQgc2VlIGlmIHdlIGNhbiBkaXNjZXJuIHBhdHRlcm5zIHdoaWNoIGxlYWQgdG8gYmV0dGVyIG9yCndvcnNlIGRydWcgdHJlYXRtZW50IG91dGNvbWUuCgpUaGVyZSBpcyBhIHNldCBvZiBjb250cmFzdHMgaW4gd2hpY2ggd2UgYXJlIHByaW1hcmlseSBpbnRlcmVzdGVkIGluCnRoaXMgZGF0YSwgdGhlc2UgZm9sbG93LiAgSSBjcmVhdGVkIG9uZSByYXRpbyBvZiByYXRpb3MgY29udHJhc3Qgd2hpY2gKSSB0aGluayBoYXMgdGhlIHBvdGVudGlhbCB0byBhc2sgb3VyIGJpZ2dlc3QgcXVlc3Rpb24uCgpgYGB7cn0KIyMgRWFjaCBvZiB0aGUgZm9sbG93aW5nIGxpc3RzIGhhcyB0aGUgbmFtZSBvZiB0aGUgY29udHJhc3QgYXMgdGhlIGtleQojIyBmb2xsb3dlZCBieSBhIHR3byBlbGVtZW50IHZlY3RvciBjb21wcmlzZWQgb2YgdGhlIG51bWVyYXRvciBhbmQKIyMgZGVub21pbmF0b3IgYXMgdGhlIHZhbHVlLiAgSW4gdGhlIGNhc2Ugb2YgdGhpcyBmaXJzdCBjb250cmFzdCwgdGhhdAojIyBpcyBjb21wcmlzZWQgb2YgYSBzdHJpbmcgd2hpY2ggbWFudWFsbHkgZGVmaW5lcyBhIHNlcmllcyBvZiBtb3JlCiMjIGNvbXBsZXggY29udHJhc3RzIHRoYW4gdGhlIHVzdWFsL3NpbXBsZSBwYWlyd2lzZS4KdG1yYzJfaHVtYW5fZXh0cmEgPC0gInoyM2RydWdub2RydWdfdnNfejIyZHJ1Z25vZHJ1ZyA9IChjb25kaXRpb25pbmZfc2JfejIzIC0gY29uZGl0aW9uaW5mX3oyMykgLSAoY29uZGl0aW9uaW5mX3NiX3oyMiAtIGNvbmRpdGlvbmluZl96MjIpLCB6MjN6MjJkcnVnX3ZzX3oyM3oyMm5vZHJ1ZyA9IChjb25kaXRpb25pbmZfc2JfejIzIC0gY29uZGl0aW9uaW5mX3NiX3oyMikgLSAoY29uZGl0aW9uaW5mX3oyMyAtIGNvbmRpdGlvbmluZl96MjIpIgp0bXJjMl9odW1hbl9rZWVwZXJzIDwtIGxpc3QoCiAgInoyM25vc2JfdnNfdW5pbmYiID0gYygiaW5mX3oyMyIsICJ1bmluZl9ub25lIiksCiAgInoyMm5vc2JfdnNfdW5pbmYiID0gYygiaW5mX3oyMiIsICJ1bmluZl9ub25lIiksCiAgInoyM25vc2JfdnNfejIybm9zYiIgPSBjKCJpbmZfejIzIiwgImluZl96MjIiKSwKICAiejIzc2JfdnNfejIyc2IiID0gYygiaW5mX3NiX3oyMyIsICJpbmZfc2JfejIyIiksCiAgInoyM3NiX3ZzX3oyM25vc2IiID0gYygiaW5mX3NiX3oyMyIsICJpbmZfejIzIiksCiAgInoyMnNiX3ZzX3oyMm5vc2IiID0gYygiaW5mX3NiX3oyMiIsICJpbmZfejIyIiksCiAgInoyM3NiX3ZzX3NiIiA9IGMoImluZl9zYl96MjMiLCAidW5pbmZfc2Jfbm9uZSIpLAogICJ6MjJzYl92c19zYiIgPSBjKCJpbmZfc2JfejIyIiwgInVuaW5mX3NiX25vbmUiKSwKICAiejIzc2JfdnNfdW5pbmYiID0gYygiaW5mX3NiX3oyMyIsICJ1bmluZl9ub25lIiksCiAgInoyMnNiX3ZzX3VuaW5mIiA9IGMoImluZl9zYl96MjIiLCAidW5pbmZfbm9uZSIpLAogICJzYl92c191bmluZiIgPSBjKCJ1bmluZl9zYl9ub25lIiwgInVuaW5mX25vbmUiKSwKICAiZXh0cmFfejIzMjIiID0gYygiejIzZHJ1Z25vZHJ1ZyIsICJ6MjJkcnVnbm9kcnVnIiksCiAgImV4dHJhX2RydWdub2RydWciID0gYygiejIzejIyZHJ1ZyIsICJ6MjN6MjJub2RydWciKSkKc2luZ2xlX3RtcmMyX2tlZXBlciA8LSBsaXN0KAogICJ6MjJzYl92c19zYiIgPSBjKCJpbmZfc2JfejIyIiwgInVuaW5mX3NiX25vbmUiKSkKdG1yYzJfZHJ1Z19rZWVwZXJzIDwtIGxpc3QoCiAgImRydWciID0gYygiYW50aW1vbnkiLCAibm9uZSIpKQp0bXJjMl90eXBlX2tlZXBlcnMgPC0gbGlzdCgKICAidHlwZSIgPSBjKCJVOTM3IiwgIk1hY3JvcGhhZ2VzIikpCnRtcmMyX3N0cmFpbl9rZWVwZXJzIDwtIGxpc3QoCiAgInN0cmFpbiIgPSBjKCJ6MjMiLCAiejIyIikpCnR5cGVfenltb19leHRyYSA8LSAienltb3NfdnNfdHlwZXMgPSAoY29uZGl0aW9uVTkzN196MjMgLSBjb25kaXRpb25VOTM3X3oyMikgLSAoY29uZGl0aW9uTWFjcm9waGFnZXNfejIzIC0gY29uZGl0aW9uTWFjcm9waGFnZXNfejIyKSIKdG1yYzJfdHlwZXp5bW9fa2VlcGVycyA8LSBsaXN0KAogICJ1OTM3X21hY3IiID0gYygiTWFjcm9waGFnZXNfbm9uZSIsICJVOTM3X25vbmUiKSwKICAienltb19tYWNyIiA9IGMoIk1hY3JvcGhhZ2VzX3oyMyIsICJNYWNyb3BoYWdlc196MjIiKSwKICAienltb191OTM3IiA9IGMoIlU5MzdfejIzIiwgIlU5MzdfejIyIiksCiAgInoyM190eXBlcyIgPSBjKCJVOTM3X3oyMyIsICJNYWNyb3BoYWdlc196MjMiKSwKICAiejIyX3R5cGVzIiA9IGMoIlU5MzdfejIyIiwgIk1hY3JvcGhhZ2VzX3oyMiIpLAogICJ6eW1vc190eXBlcyIgPSBjKCJ6eW1vc192c190eXBlcyIpKQp0bXJjMl90eXBlZHJ1Z19rZWVwZXJzIDwtIGxpc3QoCiAgInR5cGVfbm9kcnVnIiA9IGMoIlU5Mzdfbm9uZSIsICJNYWNyb3BoYWdlc19ub25lIiksCiAgInR5cGVfZHJ1ZyIgPSBjKCJVOTM3X2FudGltb255IiwgIk1hY3JvcGhhZ2VzX2FudGltb255IiksCiAgIm1hY3JfZHJ1Z3MiID0gYygiTWFjcm9waGFnZXNfYW50aW1vbnkiLCAiTWFjcm9waGFnZXNfbm9uZSIpLAogICJ1OTM3X2RydWdzIiA9IGMoIlU5MzdfYW50aW1vbnkiLCAiVTkzN19ub25lIikpCnU5Mzdfa2VlcGVycyA8LSBsaXN0KAogICJ6MjNub3NiX3ZzX3VuaW5mIiA9IGMoImluZl96MjMiLCAidW5pbmZfbm9uZSIpLAogICJ6MjJub3NiX3ZzX3VuaW5mIiA9IGMoImluZl96MjIiLCAidW5pbmZfbm9uZSIpLAogICJ6MjNub3NiX3ZzX3oyMm5vc2IiID0gYygiaW5mX3oyMyIsICJpbmZfejIyIiksCiAgInoyM3NiX3ZzX3oyMnNiIiA9IGMoImluZl9zYl96MjMiLCAiaW5mX3NiX3oyMiIpLAogICJ6MjNzYl92c196MjNub3NiIiA9IGMoImluZl9zYl96MjMiLCAiaW5mX3oyMyIpLAogICJ6MjJzYl92c196MjJub3NiIiA9IGMoImluZl9zYl96MjIiLCAiaW5mX3oyMiIpLAogICJ6MjNzYl92c19zYiIgPSBjKCJpbmZfc2JfejIzIiwgInVuaW5mX3NiX25vbmUiKSwKICAiejIyc2JfdnNfc2IiID0gYygiaW5mX3NiX3oyMiIsICJ1bmluZl9zYl9ub25lIiksCiAgInoyM3NiX3ZzX3VuaW5mIiA9IGMoImluZl9zYl96MjMiLCAidW5pbmZfbm9uZSIpLAogICJ6MjJzYl92c191bmluZiIgPSBjKCJpbmZfc2JfejIyIiwgInVuaW5mX25vbmUiKSwKICAic2JfdnNfdW5pbmYiID0gYygidW5pbmZfc2Jfbm9uZSIsICJ1bmluZl9ub25lIikpCiMjIElmIHNvbWUgY2FzZXMsIHdoZW4gdGhlIHNldCBvZiBzaWduaWZpY2FudCBnZW5lcyB3YXMgY2hvc2VuLCBhbgojIyBhZGRpdGlvbmFsIGZpbHRlciB3YXMgYWRkZWQgdG8gZXhjbHVkZSBnZW5lcyB3aXRoIGV4cHJlc3Npb24gdmFsdWVzCiMjIGxlc3MgdGhhbiAnaGlnaF9leHByZXNzaW9uJyBhY2NvcmRpbmcgdG8gdGhlCiMjICdoaWdoX2V4cHJlc3Npb25fY29sdW1uJyBpbiB0aGUgdGFibGUuCmhpZ2hfZXhwcmVzc2lvbiA8LSAxMjgKaGlnaF9leHByZXNzaW9uX2NvbHVtbiA8LSAiZGVzZXFfYmFzZW1lYW4iCgpjb21iaW5lZF90b190c3YgPC0gZnVuY3Rpb24oY29tYmluZWQsIGNlbGx0eXBlID0gImFsbCIpIHsKICBrZWVwZXJzIDwtIGNvbWJpbmVkW1sia2VlcGVycyJdXQogIGZvciAoayBpbiBzZXFfbGVuKGxlbmd0aChrZWVwZXJzKSkpIHsKICAgIGtuYW1lIDwtIG5hbWVzKGtlZXBlcnMpW2tdCiAgICBudW1lcmF0b3IgPC0ga2VlcGVyc1tba11dWzFdCiAgICBkZW5vbWluYXRvciA8LSBrZWVwZXJzW1trXV1bMl0KICAgIGZpbGVuYW1lIDwtIGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvdHN2X3RhYmxlcy90bXJjMl97Y2VsbHR5cGV9X3trbmFtZX1fbntudW1lcmF0b3J9X2R7ZGVub21pbmF0b3J9LXZ7dmVyfS54bHN4IikKICAgIGtkYXRhIDwtIGNvbWJpbmVkW1siZGF0YSJdXVtba25hbWVdXQogICAgaWYgKGlzLm51bGwoa2RhdGFbWyJiYXNpY19udW0iXV0pKSB7CiAgICAgIG5leHQKICAgIH0KICAgIHdhbnRlZCA8LSBjKCJoZ25jX3N5bWJvbCIsICJkZXNlcV9sb2dmYyIsICJkZXNlcV9hZGpwIiwKICAgICAgICAgICAgICAgICJkZXNlcV9iYXNlbWVhbiIsICJkZXNlcV9udW0iLCAiZGVzZXFfZGVuIikKICAgIHdhbnRlZF9kYXRhIDwtIGtkYXRhWywgd2FudGVkXQogICAgY29sbmFtZXMod2FudGVkX2RhdGEpIDwtIGMoImhnbmNfc3ltYm9sIiwgImRlc2VxX2xvZ2ZjIiwgImRlc2VxX2FkanAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImRlc2VxX21lYW4iLCAiZGVzZXFfbnVtZXJhdG9yIiwgImRlc2VxX2Rlbm9taW5hdG9yIikKICAgIHdyaXRlX3hsc3goZGF0YSA9IHdhbnRlZF9kYXRhLCBleGNlbCA9IGZpbGVuYW1lKQogIH0KfQoKd3JpdGVfYWxsX2dwIDwtIGZ1bmN0aW9uKGFsbF9ncCwgc3VmZml4ID0gTlVMTCkgewogIGFsbF93cml0dGVuIDwtIGxpc3QoKQogIGZvciAoZyBpbiBzZXFfbGVuKGxlbmd0aChhbGxfZ3ApKSkgewogICAgbmFtZSA8LSBuYW1lcyhhbGxfZ3ApW2ddCiAgICBkYXR1bSA8LSBhbGxfZ3BbW25hbWVdXQogICAgZmlsZW5hbWUgPC0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9ncHJvZmlsZXIve25hbWV9X2dwcm9maWxlci12e3Zlcn0ueGxzeCIpCiAgICBpZiAoIWlzLm51bGwoc3VmZml4KSkgewogICAgICBmaWxlbmFtZSA8LSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2dwcm9maWxlci97bmFtZX1fZ3Byb2ZpbGVye3N1ZmZpeH0tdnt2ZXJ9Lnhsc3giKQogICAgfQogICAgd3JpdHRlbiA8LSBzbSh3cml0ZV9ncHJvZmlsZXJfZGF0YShkYXR1bSwgZXhjZWwgPSBmaWxlbmFtZSkpCiAgICBhbGxfd3JpdHRlbltbZ11dIDwtIHdyaXR0ZW4KICB9CiAgcmV0dXJuKGFsbF93cml0dGVuKQp9CmBgYAoKIyMgUHJpbWFyeSBxdWVyaWVzCgpUaGVyZSBpcyBhIHNlcmllcyBvZiBpbml0aWFsIHF1ZXN0aW9ucyB3aGljaCBtYWtlIHNvbWUgc2Vuc2UKdG8gbWUsIGJ1dCB0aGVzZSBkbyBub3QgbmVjZXNzYXJpbHkgbWF0Y2ggdGhlIHNldCBvZiBxdWVzdGlvbnMgd2hpY2gKYXJlIG1vc3QgcHJlc3NpbmcuICBJIGFtIGhvcGluZyB0byBwdWxsIGJvdGggb2YgdGhlc2Ugc2V0cyBvZgpxdWVyaWVzIGluIG9uZS4KCkJlZm9yZSBleHRyYWN0aW5nIHRoZXNlIGdyb3VwcyBvZiBxdWVyaWVzLCBsZXQgdXMgaW52b2tlIHRoZQphbGxfcGFpcndpc2UoKSBmdW5jdGlvbiBhbmQgZ2V0IGFsbCBvZiB0aGUgbGlrZWx5IGNvbnRyYXN0cyBhbG9uZyB3aXRoCm9uZSBvciBtb3JlIGV4dHJhcyB0aGF0IG1pZ2h0IHByb3ZlIHVzZWZ1bCAodGhlICdleHRyYScgYXJndW1lbnQpLgoKVGhlIHN0cnVjdHVyZSBvZiB0aGVzZSBibG9ja3Mgd2lsbCBhbGwgYmFzaWNhbGx5IGJlIGlkZW50aWNhbDoKCiogUGVyZm9ybSBhIHNldCBvZiBwYWlyd2lzZSBjb250cmFzdHMgb2YgYWxsIHRoZSBjb25kaXRpb25zIGFnYWluc3QKICBlYWNoIG90aGVyLiAgT3B0aW9uYWxseSB1c2Ugc3ZhLgoqIEdpdmVuIHRoYXQgcmVzdWx0LCBkdW1wIGl0IGluIGl0cyBlbnRpcmV0eSB0byBhbiB4bHN4IGZpbGUgaW4gdGhlCiAgYW5hbHlzZXMvIGRpcmVjdG9yeS4KKiBHaXZlbiB0aG9zZSBjb21iaW5lZCB0YWJsZXMsIGV4dHJhY3QgZnJvbSB0aGVtIHRoZSBzZXQgZGVlbWVkCiAgJ3NpZ25pZmljYW50JyBieSB3aGF0ZXZlciBjcml0ZXJpYSB3ZSB3YW50IHRvIHRyeS4gKFVzdWFsbHkgfGxmY3wgPj0KICAxLjAsIGFkanVzdGVkIHAgPD0gMC4wNTsgYnV0IHBvdGVudGlhbGx5IGFsc28gZXhwcmVzc2lvbiA+PSB4IGFuZAogIHNvbWV0aW1lcyBhIHNldCBvZiBsZXNzIHN0cmluZ2VudCB2YWx1ZXMgKHxsZmN8ID49IDAuNikpCiogR2l2ZW4gb25lIG9yIG1vcmUgZ2VuZSBzZXRzIGRlZW1lZCAnc2lnbmlmaWNhbnQnIHBhc3MgdGhlbSB0bwogIGdQcm9maWxlcjIgYW5kIHNlZSB3aGF0IHBvcHMgb3V0LgoKIyMjIENvbWJpbmVkIFU5MzcgYW5kIE1hY3JvcGhhZ2VzOiBDb21wYXJlIGRydWcgZWZmZWN0cwoKV2hlbiB3ZSBoYXZlIHRoZSB1OTM3IGNlbGxzIGluIHRoZSBzYW1lIGRhdGFzZXQgYXMgdGhlIG1hY3JvcGhhZ2VzLAp0aGF0IHByb3ZpZGVzIGFuIGludGVyZXN0aW5nIG9wcG9ydHVuaXR5IHRvIHNlZSBpZiB3ZSBjYW4gb2JzZXJ2ZQpkcnVnLWRlcGVuZGFudCBlZmZlY3RzIHdoaWNoIGFyZSBzaGFyZWQgYWNyb3NzIGJvdGggY2VsbCB0eXBlcy4KCk5vdGUgdG8gc2VsZjogZ2l2ZW4gdGhlIGNoYW5nZXMgdG8gaHBnbHRvb2xzIEkgbWF5IG5lZWQgdG8gc3BlY2lmeSB0aGUKc3RhdGlzdGljYWwgbW9kZWwgc3RyaW5nIHdoZW4gSSBhbSB1c2luZyBzdmFzZXEgZm9yIHNvbWUvbWFueS9hbGwgb2YKdGhlc2UgY29tcGFyaXNvbnMuCgpgYGB7cn0KZHJ1Z19kZSA8LSBhbGxfcGFpcndpc2UoYWxsX2h1bWFuLCBmaWx0ZXIgPSBUUlVFLCBtb2RlbF9zdnMgPSAic3Zhc2VxIiwKICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfZnN0cmluZyA9ICJ+IDAgKyBjb25kaXRpb24iKQpkcnVnX2RlCgpkcnVnX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGRydWdfZGUsIGtlZXBlcnMgPSB0bXJjMl9kcnVnX2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9tYWNyb3BoYWdlX2RydWdfY29tcGFyaXNvbi12e3Zlcn0ueGxzeCIpKQpkcnVnX3RhYmxlCmNvbWJpbmVkX3RvX3RzdihkcnVnX3RhYmxlLCBjZWxsdHlwZSA9ICJhbGwiKQoKZHJ1Z19zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBkcnVnX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL21hY3JvcGhhZ2VfZHJ1Z19zaWctdnt2ZXJ9Lnhsc3giKSkKZHJ1Z19zaWcKZHJ1Z19oaWdoc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgZHJ1Z190YWJsZSwgbWluX21lYW5fZXhwcnMgPSBoaWdoX2V4cHJlc3Npb24sIGV4cHJzX2NvbHVtbiA9IGhpZ2hfZXhwcmVzc2lvbl9jb2x1bW4sCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZV9kcnVnX2hpZ2hzaWctdnt2ZXJ9Lnhsc3giKSkKZHJ1Z19oaWdoc2lnCmRydWdfbGVzc3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGRydWdfdGFibGUsIGxmYyA9IDAuNiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlX2RydWdfbGVzc3NpZy12e3Zlcn0ueGxzeCIpKQpkcnVnX2xlc3NzaWcKYGBgCgojIyMjIGdQcm9maWxlcjIgcmVzdWx0cyBvZiB0aGUgc2lnbmlmaWNhbnQgZHJ1ZyBnZW5lcwoKYGBge3J9CmFsbF9kcnVnX2dwIDwtIGFsbF9ncHJvZmlsZXIoZHJ1Z19zaWcsIGVucmljaF9pZF9jb2x1bW4gPSAiaGduY19zeW1ib2wiKQphbGxfZHJ1Z19ncAp3cml0dGVuIDwtIHdyaXRlX2FsbF9ncChhbGxfZHJ1Z19ncCkKCmFsbF9kcnVnX2xlc3NzaWcgPC0gYWxsX2dwcm9maWxlcihkcnVnX2xlc3NzaWcsIGVucmljaF9pZF9jb2x1bW4gPSAiaGduY19zeW1ib2wiKQp3cml0dGVuIDwtIHdyaXRlX2FsbF9ncChhbGxfZHJ1Z19sZXNzc2lnLCBzdWZmaXggPSAiX2xmYzAuNl8iKQpgYGAKCiMjIyBDb21iaW5lZCBVOTM3IGFuZCBNYWNyb3BoYWdlczogY29tcGFyZSBjZWxsIHR5cGVzCgpUaGVyZSBhcmUgYSBjb3VwbGUgb2Ygd2F5cyBvbmUgbWlnaHQgd2FudCB0byBkaXJlY3RseSBjb21wYXJlIHRoZSB0d28KY2VsbCB0eXBlcy4KCiogR2l2ZW4gdGhhdCB0aGUgdmFyaWFuY2UgYmV0d2VlbiB0aGUgdHdvIGNlbGx0eXBlcyBpcyBzbyBodWdlLCBqdXN0CmNvbXBhcmUgYWxsIHNhbXBsZXMuCiogT25lIG1pZ2h0IHdhbnQgdG8gY29tcGFyZSB0aGVtIHdpdGggdGhlIGludGVyYWN0aW9uIGVmZmVjdHMgb2YgZHJ1Zy96eW1vZGVtZS4KCmBgYHtyfQp0eXBlX2RlIDwtIGFsbF9wYWlyd2lzZShhbGxfaHVtYW5fdHlwZXMsIGZpbHRlciA9IFRSVUUsIG1vZGVsX2ZzdHJpbmcgPSAifiAwICsgY29uZGl0aW9uIiwKICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfc3ZzID0gInN2YXNlcSIpCnR5cGVfZGUKCnR5cGVfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgdHlwZV9kZSwga2VlcGVycyA9IHRtcmMyX3R5cGVfa2VlcGVycywKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL21hY3JvcGhhZ2VfdHlwZV9jb21wYXJpc29uLXZ7dmVyfS54bHN4IikpCnR5cGVfdGFibGUKY29tYmluZWRfdG9fdHN2KHR5cGVfdGFibGUsIGNlbGx0eXBlID0gImFsbCIpCgp0eXBlX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHR5cGVfdGFibGUsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZV90eXBlX3NpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX3NpZwp0eXBlX2hpZ2hzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB0eXBlX3RhYmxlLCBtaW5fbWVhbl9leHBycyA9IGhpZ2hfZXhwcmVzc2lvbiwgZXhwcnNfY29sdW1uID0gaGlnaF9leHByZXNzaW9uX2NvbHVtbiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlX3R5cGVfaGlnaHNpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX2hpZ2hzaWcKCnR5cGVfbGVzc3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHR5cGVfdGFibGUsIGxmYyA9IDAuNiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlX3R5cGVfbGVzc3NpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX3NpZwpgYGAKCiMjIyMgQ29tYmluZWQgZmFjdG9ycyBvZiBpbnRlcmVzdDogY2VsbHR5cGUrenltb2RlbWUKCkdpdmVuIHRoZSBhYm92ZSBleHBsaWNpdCBjb21wYXJpc29uIG9mIGFsbCBzYW1wbGVzIGNvbXByaXNpbmcgdGhlIHR3bwpjZWxsIHR5cGVzLCBub3cgbGV0IHVzIGxvb2sgYXQgdGhlIGRydWcgdHJlYXRtZW50K3p5bW9kZW1lIHN0YXR1cyB3aXRoCmFsbCBzYW1wbGVzLCBtYWNyb3BoYWdlcyBhbmQgVTkzNy4KCmBgYHtyfQp0eXBlX3p5bW9fZGUgPC0gYWxsX3BhaXJ3aXNlKHR5cGVfenltbywgZmlsdGVyID0gVFJVRSwgbW9kZWxfc3ZzID0gInN2YXNlcSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfZnN0cmluZyA9ICJ+IDAgKyBjb25kaXRpb24iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4dHJhX2NvbnRyYXN0cyA9IHR5cGVfenltb19leHRyYSkKdHlwZV96eW1vX2RlCmBgYAoKU3RyYW5nZWx5LCBhcyBvZiAyMDI1MDkwMywgdGhlIGZvbGxvd2luZyBsaW5lIHRocm93cyBhbiBlcnJvciBpbiB0aGUgY29udGFpbmVyOgoiRXJyb3I6IHN1YnNjcmlwdCBjb250YWlucyBpbnZhbGlkIG5hbWVzLiIKCkJ1dCB3aGVuIEkgcnVuIGl0IG1hbnVhbGx5IEkgZ2V0IG5vIGVycm9yLiAgSSBhc3N1bWUgdGhpcyBtZWFucyB0aGF0IEkgZmVsbCBiZWhpbmQgd2hpbGUgbWFpbnRhaW5pbmcKaHBnbHRvb2xzIEhFQUQgd2l0aCB0aGUgY29udGFpbmVyPwoKSW4gYWRkaXRpb24sIHRoZSBmdW5jdGlvbnMgYWN0dWFsbHkgZGlkIHJldHVybiBzdWNjZXNzZnVsbHkuCgpgYGB7cn0KdHlwZV96eW1vX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIHR5cGVfenltb19kZSwga2VlcGVycyA9IHRtcmMyX3R5cGV6eW1vX2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9tYWNyb3BoYWdlX3R5cGVfenltb19jb21wYXJpc29uLXZ7dmVyfS54bHN4IikpCnR5cGVfenltb190YWJsZQpjb21iaW5lZF90b190c3YodHlwZV96eW1vX3RhYmxlLCBjZWxsdHlwZSA9ICJhbGwiKQoKdHlwZV96eW1vX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHR5cGVfenltb190YWJsZSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlX3R5cGVfenltb19zaWctdnt2ZXJ9Lnhsc3giKSkKdHlwZV96eW1vX3NpZwp0eXBlX3p5bW9faGlnaHNpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHR5cGVfenltb190YWJsZSwgbWluX21lYW5fZXhwcnMgPSBoaWdoX2V4cHJlc3Npb24sIGV4cHJzX2NvbHVtbiA9IGhpZ2hfZXhwcmVzc2lvbl9jb2x1bW4sCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZV90eXBlX3p5bW9faGlnaHNpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX3p5bW9fbGVzc3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHR5cGVfenltb190YWJsZSwgbGZjID0gMC42LAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL21hY3JvcGhhZ2VfdHlwZV96eW1vX2xlc3NzaWctdnt2ZXJ9Lnhsc3giKSkKdHlwZV96eW1vX2xlc3NzaWcKYGBgCgojIyMjIENvbWJpbmVkIGZhY3RvcnMgb2YgaW50ZXJlc3Q6IGNlbGx0eXBlK2RydWcKClRoZSAndHlwZV9kcnVnJyBkYXRhc3RydWN0dXJlIGlzIHRoZSBzYW1lIGFzIGFib3ZlLCBidXQgdGhlIGNvbmRpdGlvbgppcyBjcmVhdGVkIGZyb20gdGhlIGNvbmNhdGVuYXRpb24gb2YgdGhlIGNlbGwgdHlwZSBhbmQgZHJ1ZyB0cmVhdG1lbnQuCgpgYGB7cn0KdHlwZV9kcnVnX2RlIDwtIGFsbF9wYWlyd2lzZSh0eXBlX2RydWcsIGZpbHRlciA9IFRSVUUsIG1vZGVsX3N2cyA9ICJzdmFzZXEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsX2ZzdHJpbmcgPSAifiAwICsgY29uZGl0aW9uIikKdHlwZV9kcnVnX2RlCnR5cGVfZHJ1Z190YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICB0eXBlX2RydWdfZGUsIGtlZXBlcnMgPSB0bXJjMl90eXBlZHJ1Z19rZWVwZXJzLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9kZV90YWJsZXMvbWFjcm9waGFnZV90eXBlX2RydWdfY29tcGFyaXNvbi12e3Zlcn0ueGxzeCIpKQp0eXBlX2RydWdfdGFibGUKCiNjb21iaW5lZF90b190c3YodHlwZV9kcnVnX3RhYmxlLCBjZWxsdHlwZSA9ICJhbGwiKQoKdHlwZV9kcnVnX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHR5cGVfZHJ1Z190YWJsZSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlX3R5cGVfZHJ1Z19zaWctdnt2ZXJ9Lnhsc3giKSkKdHlwZV9kcnVnX3NpZwoKdHlwZV9kcnVnX2hpZ2hzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICB0eXBlX2RydWdfdGFibGUsIG1pbl9tZWFuX2V4cHJzID0gaGlnaF9leHByZXNzaW9uLCBleHByc19jb2x1bW4gPSBoaWdoX2V4cHJlc3Npb25fY29sdW1uLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL21hY3JvcGhhZ2VfdHlwZV9kcnVnX2hpZ2hzaWctdnt2ZXJ9Lnhsc3giKSkKdHlwZV9kcnVnX2hpZ2hzaWcKCnR5cGVfZHJ1Z19sZXNzc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgdHlwZV9kcnVnX3RhYmxlLCBsZmMgPSAwLjYsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZV90eXBlX2RydWdfbGVzc3NpZy12e3Zlcn0ueGxzeCIpKQp0eXBlX2RydWdfbGVzc3NpZwpgYGAKCiMgSW5kaXZpZHVhbCBjZWxsIHR5cGVzCgpBdCB0aGlzIHBvaW50LCBJIHRoaW5rIGl0IGlzIGZhaXIgdG8gc2F5IHRoYXQgdGhlIHR3byBjZWxsIHR5cGVzIGFyZQpzdWZmaWNpZW50bHkgZGlmZmVyZW50IHRoYXQgdGhleSBkbyBub3QgcmVhbGx5IGJlbG9uZyB0b2dldGhlciBpbiBhCnNpbmdsZSBhbmFseXNpcy4KCiMjIGRydWcgb3Igc3RyYWluIGVmZmVjdHMsIHNpbmdsZSBjZWxsIHR5cGUKCk9uZSBvZiB0aGUgcXVlcmllcyBOYWppYiBhc2tlZCB3aGljaCBJIHRoaW5rIEkgbWlzaW50ZXJwcmV0ZWQgd2FzIHRvCmxvb2sgYXQgZHJ1ZyBhbmQvb3Igc3RyYWluIGVmZmVjdHMuICBNeSBpbnRlcnByZXRhdGlvbiBpcyBzb21ld2hlcmUKYmVsb3cgYW5kIHdhcyBub3Qgd2hhdCBoZSB3YXMgbG9va2luZyBmb3IuICBJbnN0ZWFkLCBoZSB3YXMgbG9va2luZyB0bwpzZWUgYWxsKG1hY3JvcGhhZ2UpIGRydWcvbm9kcnVnIGFuZCBhbGwobWFjcm9waGFnZSkgejIzL3oyMiBhbmQKY29tcGFyZSB0aGVtIHRvIGVhY2ggb3RoZXIuICBJdCBtYXkgYmUgdGhhdCB0aGlzIGlzIHN0aWxsIGEgd3JvbmcKaW50ZXJwcmV0YXRpb24sIGlmIHNvIHRoZSBtb3N0IGxpa2VseSBjb21wYXJpc29uIGlzIGVpdGhlcjoKCiogICh6MjNkcnVnL3oyMmRydWcpIC8gKHoyM25vZHJ1Zy96MjJub2RydWcpLCBvciBwZXJoYXBzCiogICh6MjNkcnVnL3oyM25vZHJ1ZykgLyAoejIyZHJ1Zy96MjJub2RydWcpLAoKSSBhbSBub3Qgc3VyZSB0aG9zZSBjb25mdXNlIG1lLCBhbmQgYXQgbGVhc3Qgb25lIG9mIHRoZW0gaXMgYmVsb3cKCiMjIE1hY3JvcGhhZ2VzCgpJbiB0aGVzZSBibG9ja3Mgd2Ugd2lsbCBleHBsaWNpdGx5IHF1ZXJ5IG9ubHkgb25lIGZhY3RvciBhdCBhIHRpbWUsCmRydWcgYW5kIHN0cmFpbi4gIFRoZSBldmVudHVhbCBnb2FsIGlzIHRvIGxvb2sgZm9yIGVmZmVjdHMgb2YKZHJ1ZyB0cmVhdG1lbnQgYW5kL29yIHN0cmFpbiB0cmVhdG1lbnQgd2hpY2ggYXJlIHNoYXJlZD8KCiMjIyBNYWNyb3BoYWdlIERydWcgb25seQoKVGh1cyB3ZSB3aWxsIHN0YXJ0IHdpdGggdGhlIHB1cmUgZHJ1ZyBxdWVyeS4gIEluIHRoaXMgYmxvY2sgd2Ugd2lsbApsb29rIG9ubHkgYXQgdGhlIGRydWcvbm9kcnVnIGVmZmVjdC4KCmBgYHtyfQpoc19tYWNyX2RydWdfZGUgPC0gYWxsX3BhaXJ3aXNlKGhzX21hY3JfZHJ1Z19zZSwgZmlsdGVyID0gVFJVRSwgbW9kZWxfc3ZzID0gInN2YXNlcSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfZnN0cmluZyA9ICJ+IDAgKyBjb25kaXRpb24iKQpoc19tYWNyX2RydWdfZGUKCmhzX21hY3JfZHJ1Z190YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBoc19tYWNyX2RydWdfZGUsIGtlZXBlcnMgPSB0bXJjMl9kcnVnX2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9tYWNyb3BoYWdlX29ubHlkcnVnX3RhYmxlLXZ7dmVyfS54bHN4IikpCmhzX21hY3JfZHJ1Z190YWJsZQoKI2NvbWJpbmVkX3RvX3Rzdihoc19tYWNyX2RydWdfdGFibGUsIGNlbGx0eXBlID0gIm1hY3JvcGhhZ2UiKQoKaHNfbWFjcl9kcnVnX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX21hY3JfZHJ1Z190YWJsZSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlb25seV9kcnVnX3NpZy12e3Zlcn0ueGxzeCIpKQpoc19tYWNyX2RydWdfc2lnCgpoc19tYWNyX2RydWdfaGlnaHNpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX21hY3JfZHJ1Z190YWJsZSwgbWluX21lYW5fZXhwcnMgPSBoaWdoX2V4cHJlc3Npb24sIGV4cHJzX2NvbHVtbiA9IGhpZ2hfZXhwcmVzc2lvbl9jb2x1bW4sCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZW9ubHlfZHJ1Z19oaWdoc2lnLXZ7dmVyfS54bHN4IikpCmhzX21hY3JfZHJ1Z19oaWdoc2lnCgojIyBDcmVhdGluZyB0aGUgZm9sbG93aW5nIHRvIHNlZSBob3cgaXQgYWZmZWN0cyBnUHJvZmlsZXIuCmhzX21hY3JfZHJ1Z19sZXNzc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgaHNfbWFjcl9kcnVnX3RhYmxlLCBsZmMgPSAwLjYsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZW9ubHlfZHJ1Z19zaWdfbGZjMC42LXZ7dmVyfS54bHN4IikpCmBgYAoKIyMjIE1hY3JvcGhhZ2UgU3RyYWluIG9ubHkKCkluIGEgc2ltaWxhciBmYXNoaW9uLCBsZXQgdXMgbG9vayBmb3IgZWZmZWN0cyB3aGljaCBhcmUgb2JzZXJ2ZWQgd2hlbgp3ZSBjb25zaWRlciBvbmx5IHRoZSBzdHJhaW4gdXNlZCBkdXJpbmcgaW5mZWN0aW9uLgoKYGBge3J9CmhzX21hY3Jfc3RyYWluX2RlIDwtIGFsbF9wYWlyd2lzZShoc19tYWNyX3N0cmFpbl9zZSwgZmlsdGVyID0gVFJVRSwgbW9kZWxfc3ZzID0gInN2YXNlcSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9mc3RyaW5nID0gIn4gMCArIGNvbmRpdGlvbiIpCmhzX21hY3Jfc3RyYWluX2RlCgpoc19tYWNyX3N0cmFpbl90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBoc19tYWNyX3N0cmFpbl9kZSwga2VlcGVycyA9IHRtcmMyX3N0cmFpbl9rZWVwZXJzLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9kZV90YWJsZXMvbWFjcm9waGFnZV9vbmx5c3RyYWluX3RhYmxlLXZ7dmVyfS54bHN4IikpCmhzX21hY3Jfc3RyYWluX3RhYmxlCmNvbWJpbmVkX3RvX3Rzdihoc19tYWNyX3N0cmFpbl90YWJsZSwgY2VsbHR5cGUgPSAibWFjcm9waGFnZSIpCgpoc19tYWNyX3N0cmFpbl9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBoc19tYWNyX3N0cmFpbl90YWJsZSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9tYWNyb3BoYWdlb25seV9vbmx5c3RyYWluX3NpZy12e3Zlcn0ueGxzeCIpKQpoc19tYWNyX3N0cmFpbl9zaWcKCmhzX21hY3Jfc3RyYWluX2hpZ2hzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBoc19tYWNyX3N0cmFpbl90YWJsZSwgbWluX21lYW5fZXhwcnMgPSBoaWdoX2V4cHJlc3Npb24sIGV4cHJzX2NvbHVtbiA9IGhpZ2hfZXhwcmVzc2lvbl9jb2x1bW4sCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvbWFjcm9waGFnZW9ubHlfb25seXN0cmFpbl9oaWdoc2lnLXZ7dmVyfS54bHN4IikpCmhzX21hY3Jfc3RyYWluX2hpZ2hzaWcKCmhzX21hY3Jfc3RyYWluX2xlc3NzaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBoc19tYWNyX3N0cmFpbl90YWJsZSwgbGZjID0gMC42LAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL21hY3JvcGhhZ2Vvbmx5X29ubHlzdHJhaW5fbGVzc3NpZy12e3Zlcn0ueGxzeCIpKQpoc19tYWNyX3N0cmFpbl9sZXNzc2lnCmBgYAoKIyMjIENvbXBhcmUgRHJ1ZyBhbmQgU3RyYWluIEVmZmVjdHMKCk5vdyBsZXQgdXMgY29uc2lkZXIgdGhlIGFib3ZlIHR3byBjb21wYXJpc29ucyB0b2dldGhlci4gIEZpcnN0LCBJIHdpbGwKcGxvdCB0aGUgbG9nRkMgdmFsdWVzIG9mIHRoZW0gYWdhaW5zdCBlYWNoIG90aGVyIChkcnVnIG9uIHgtYXhpcyBhbmQKc3RyYWluIG9uIHRoZSB5LWF4aXMpLiAgVGhlbiB3ZSBjYW4gZXh0cmFjdCB0aGUgc2lnbmlmaWNhbnQgZ2VuZXMgaW4gYQpmZXcgY29tYmluZWQgY2F0ZWdvcmllcyBvZiBpbnRlcmVzdC4gIEkgYXNzdW1lIHRoZXNlIHdpbGwgZm9jdXMKZXhjbHVzaXZlbHkgb24gdGhlIGNhdGVnb3JpZXMgd2hpY2ggaW5jbHVkZSB0aGUgaW50cm9kdWN0aW9uIG9mIHRoZQpkcnVnLgoKYGBge3J9CmRydWdfc3RyYWluX2NvbXBfZGYgPC0gbWVyZ2UoaHNfbWFjcl9kcnVnX3RhYmxlW1siZGF0YSJdXVtbImRydWciXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHNfbWFjcl9zdHJhaW5fdGFibGVbWyJkYXRhIl1dW1sic3RyYWluIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInJvdy5uYW1lcyIpCmRydWdfc3RyYWluX2NvbXBfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKAogIGRydWdfc3RyYWluX2NvbXBfZGZbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCiMjIENvbnRyYXN0czogYW50aW1vbnkvbm9uZSwgejIzL3oyMjsgeC1heGlzOiBkcnVnLCB5LWF4aXM6IHN0cmFpbgojIyB0b3AgbGVmdDogaGlnaGVyIG5vIGRydWcsIHoyMzsgdG9wIHJpZ2h0OiBoaWdoZXIgZHJ1ZyB6MjMKIyMgYm90dG9tIGxlZnQ6IGhpZ2hlciBubyBkcnVnLCB6MjI7IGJvdHRvbSByaWdodDogaGlnaGVyIGRydWcgejIyCmRydWdfc3RyYWluX2NvbXBfcGxvdFtbInNjYXR0ZXIiXV0KYGBgCgpBcyBJIG5vdGVkIGluIHRoZSBjb21tZW50cyBhYm92ZSwgc29tZSBxdWFkcmFudHMgb2YgdGhlIHNjYXR0ZXIgcGxvdAphcmUgbGlrZWx5IHRvIGJlIG9mIGdyZWF0ZXIgaW50ZXJlc3QgdG8gdXMgdGhhbiBvdGhlcnMgKHRoZSByaWdodApzaWRlKS4gIEJlY2F1c2UgSSBnZXQgY29uZnVzZWQgc29tZXRpbWVzLCB0aGUgZm9sbG93aW5nIGJsb2NrIHdpbGwKZXhwbGljaXRseSBuYW1lIHRoZSBjYXRlZ29yaWVzIG9mIGxpa2VseSBpbnRlcmVzdCwgdGhlbiBhc2sgd2hpY2gKZ2VuZXMgYXJlIHNoYXJlZCBhbW9uZyB0aGVtLCBhbmQgZmluYWxseSB1c2UgVXBTZXRSIHRvIGV4dHJhY3QgdGhlCnZhcmlvdXMgZ2VuZSBpbnRlcnNlY3Rpb24vdW5pb24gY2F0ZWdvcmllcy4KCmBgYHtyfQpoaWdoZXJfZHJ1ZyA8LSBoc19tYWNyX2RydWdfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbMV1dCmhpZ2hlcl9ub2RydWcgPC0gaHNfbWFjcl9kcnVnX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1sxXV0KaGlnaGVyX3oyMyA8LSBoc19tYWNyX3N0cmFpbl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbMV1dCmhpZ2hlcl96MjIgPC0gaHNfbWFjcl9zdHJhaW5fc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbMV1dCnN1bShyb3duYW1lcyhoaWdoZXJfZHJ1ZykgJWluJSByb3duYW1lcyhoaWdoZXJfejIzKSkKc3VtKHJvd25hbWVzKGhpZ2hlcl9kcnVnKSAlaW4lIHJvd25hbWVzKGhpZ2hlcl96MjIpKQpzdW0ocm93bmFtZXMoaGlnaGVyX25vZHJ1ZykgJWluJSByb3duYW1lcyhoaWdoZXJfejIzKSkKc3VtKHJvd25hbWVzKGhpZ2hlcl9ub2RydWcpICVpbiUgcm93bmFtZXMoaGlnaGVyX3oyMikpCgpkcnVnX3oyM19sc3QgPC0gbGlzdCgiZHJ1ZyIgPSByb3duYW1lcyhoaWdoZXJfZHJ1ZyksCiAgICAgICAgICAgICAgICAgICAgICJ6MjMiID0gcm93bmFtZXMoaGlnaGVyX3oyMykpCnVwc2V0X2lucHV0IDwtIFVwU2V0Ujo6ZnJvbUxpc3QoZHJ1Z196MjNfbHN0KQpoaWdoZXJfZHJ1Z196MjMgPC0gdXBzZXQodXBzZXRfaW5wdXQsIHRleHQuc2NhbGUgPSAyKQpoaWdoZXJfZHJ1Z196MjMKCmRydWdfejIzX3NoYXJlZF9nZW5lcyA8LSBvdmVybGFwX2dyb3VwcyhkcnVnX3oyM19sc3QpCnNoYXJlZF9nZW5lc19kcnVnX3oyMyA8LSBvdmVybGFwX2dlbmVpZHMoZHJ1Z196MjNfc2hhcmVkX2dlbmVzLCAiZHJ1Zzp6MjMiKQpzaGFyZWRfZ2VuZXNfZHJ1Z196MjMgPC0gYXR0cihkcnVnX3oyM19zaGFyZWRfZ2VuZXMsICJlbGVtZW50cyIpW2RydWdfejIzX3NoYXJlZF9nZW5lc1tbImRydWc6ejIzIl1dXQoKZHJ1Z196MjJfbHN0IDwtIGxpc3QoImRydWciID0gcm93bmFtZXMoaGlnaGVyX2RydWcpLAogICAgICAgICAgICAgICAgICAgICAiejIyIiA9IHJvd25hbWVzKGhpZ2hlcl96MjIpKQpoaWdoZXJfZHJ1Z196MjIgPC0gdXBzZXQoVXBTZXRSOjpmcm9tTGlzdChkcnVnX3oyMl9sc3QpLCB0ZXh0LnNjYWxlID0gMikKaGlnaGVyX2RydWdfejIyCgpkcnVnX3oyMl9zaGFyZWRfZ2VuZXMgPC0gb3ZlcmxhcF9ncm91cHMoZHJ1Z196MjJfbHN0KQpzaGFyZWRfZ2VuZXNfZHJ1Z196MjIgPC0gb3ZlcmxhcF9nZW5laWRzKGRydWdfejIyX3NoYXJlZF9nZW5lcywgImRydWc6ejIyIikKc2hhcmVkX2dlbmVzX2RydWdfejIyIDwtIGF0dHIoZHJ1Z196MjJfc2hhcmVkX2dlbmVzLCAiZWxlbWVudHMiKVtkcnVnX3oyMl9zaGFyZWRfZ2VuZXNbWyJkcnVnOnoyMiJdXV0KYGBgCgojIyMgUGVyZm9ybSBnUHJvZmlsZXIgb24gZHJ1Zy9zdHJhaW4gZWZmZWN0IHNoYXJlZCBnZW5lcwoKTm93IHRoYXQgd2UgaGF2ZSBzb21lIHBvcHVsYXRpb25zIG9mIGdlbmVzIHdoaWNoIGFyZSBzaGFyZWQgYWNyb3NzIHRoZQpkcnVnL3N0cmFpbiBlZmZlY3RzLCBsZXQgdXMgcGFzcyB0aGVtIHRvIHNvbWUgR1NFQSBhbmFseXNlcyBhbmQgc2VlCndoYXQgcG9wcyBvdXQuCgpgYGB7cn0Kd2FudGVkIDwtIGRydWdfejIzX3NoYXJlZF9nZW5lc1tbImRydWc6ejIzIl1dCnNoYXJlZF9nZW5lc19kcnVnX3oyMyA8LSBhdHRyKGRydWdfejIzX3NoYXJlZF9nZW5lcywgImVsZW1lbnRzIilbd2FudGVkXQpzaGFyZWRfZHJ1Z196MjNfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihzaGFyZWRfZ2VuZXNfZHJ1Z196MjMpCnNoYXJlZF9kcnVnX3oyM19ncFtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCnNoYXJlZF9kcnVnX3oyM19ncFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCnNoYXJlZF9kcnVnX3oyM19ncFtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KCndhbnRlZCA8LSBkcnVnX3oyMl9zaGFyZWRfZ2VuZXNbWyJkcnVnOnoyMiJdXQpzaGFyZWRfZ2VuZXNfZHJ1Z196MjIgPC0gYXR0cihkcnVnX3oyMl9zaGFyZWRfZ2VuZXMsICJlbGVtZW50cyIpW3dhbnRlZF0Kc2hhcmVkX2RydWdfejIyX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoc2hhcmVkX2dlbmVzX2RydWdfejIyKQpzaGFyZWRfZHJ1Z196MjJfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJCUCJdXQpgYGAKCiMgT3VyIG1haW4gcXVlc3Rpb24gb2YgaW50ZXJlc3QKClRoZSBkYXRhIHN0cnVjdHVyZSBoc19tYWNyIGNvbnRhaW5zIG91ciBwcmltYXJ5IG1hY3JvcGhhZ2VzLCB3aGljaAphcmUsIGFzIHNob3duIGFib3ZlLCB0aGUgZGF0YSB3ZSBjYW4gcmVhbGx5IHNpbmsgb3VyIHRlZXRoIGludG8uCgpOb3RlLCB3ZSBleHBlY3Qgc29tZSBlcnJvcnMgd2hlbiBydW5uaW5nIHRoZSBjb21iaW5lX2RlX3RhYmxlcygpCmJlY2F1c2Ugbm90IGFsbCBtZXRob2RzIEkgdXNlIGFyZSBjb21mb3J0YWJsZSB1c2luZyB0aGUgcmF0aW8gb3IKcmF0aW9zIGNvbnRyYXN0cyB3ZSBhZGRlZCBpbiB0aGUgJ2V4dHJhcycgYXJndW1lbnQuICBBcyBhIHJlc3VsdCwgd2hlbgp3ZSBjb21iaW5lIHRoZW0gaW50byB0aGUgbGFyZ2VyIG91dHB1dCB0YWJsZXMsIHRob3NlIHBlY3VsaWFyCmNvbnRyYXN0cyBmYWlsLiAgVGhpcyBkb2VzIG5vdCBzdG9wIGl0IGZyb20gd3JpdGluZyB0aGUgcmVzdCBvZiB0aGUKcmVzdWx0cywgaG93ZXZlci4KCmBgYHtyfQpoc19tYWNyX2RlX25vZXh0cmEgPC0gYWxsX3BhaXJ3aXNlKGhzX21hY3IsIG1vZGVsX3N2cyA9ICJzdmFzZXEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsX2ZzdHJpbmcgPSAifiAwICsgY29uZGl0aW9uIiwgZmlsdGVyID0gVFJVRSkKCmhzX21hY3JfZGUgPC0gYWxsX3BhaXJ3aXNlKGhzX21hY3IsIG1vZGVsX3N2cyA9ICJzdmFzZXEiLCBtb2RlbF9mc3RyaW5nID0gIn4gMCArIGNvbmRpdGlvbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlciA9IFRSVUUsIGV4dHJhX2NvbnRyYXN0cyA9IHRtcmMyX2h1bWFuX2V4dHJhKQpoc19tYWNyX2RlCmBgYAoKV3JpdGUgb3V0IHRoZSByZXN1bHRzLgoKYGBge3J9CmhzX3NpbmdsZV90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBoc19tYWNyX2RlX25vZXh0cmEsIGtlZXBlcnMgPSBzaW5nbGVfdG1yYzJfa2VlcGVyLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9kZV90YWJsZXMvaHNfbWFjcl9kcnVnX3p5bW9fejIyc2Jfc2Itdnt2ZXJ9Lnhsc3giKSkKaHNfc2luZ2xlX3RhYmxlCmhzX21hY3JfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgaHNfbWFjcl9kZSwga2VlcGVycyA9IHRtcmMyX2h1bWFuX2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9oc19tYWNyX2RydWdfenltb190YWJsZV9tYWNyX29ubHktdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl90YWJsZQoKY29tYmluZWRfdG9fdHN2KGhzX21hY3JfdGFibGUsICJtYWNyb3BoYWdlIikKCmhzX21hY3Jfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgaHNfbWFjcl90YWJsZSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9oc19tYWNyX2RydWdfenltb19zaWctdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9zaWcKaHNfbWFjcl9oaWdoc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgaHNfbWFjcl90YWJsZSwgbWluX21lYW5fZXhwcnMgPSBoaWdoX2V4cHJlc3Npb24sIGV4cHJzX2NvbHVtbiA9IGhpZ2hfZXhwcmVzc2lvbl9jb2x1bW4sCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvaHNfbWFjcl9kcnVnX3p5bW9faGlnaHNpZy12e3Zlcn0ueGxzeCIpKQpoc19tYWNyX2hpZ2hzaWcKaHNfbWFjcl9sZXNzc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgaHNfbWFjcl90YWJsZSwgbGZjID0gMC42LAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL2hzX21hY3JfZHJ1Z196eW1vX3NpZ19sZmMwLjYtdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9sZXNzc2lnCmBgYAoKIyMgZ2VuZSBncm91cCB1cHNldAoKIyMjIDIuMyB2cyAyLjIgdXAgYW5kIGRvd24gdnMuIHVuaW5mZWN0ZWQKClRoaXMgaXMgbXkgdmVyc2lvbiBvZiB0aGUgVmVubiBkaWFncmFtIHdoaWNoIGluY2x1ZGVzIHRoZSB0ZXh0OgoKIkRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBpbiBtYWNyb3BoYWdlcyBpbmZlY3RlZCB3aXRoCnN1YnBvcHVsYXRpb25zIDIuMiBvciAyLjMuICBWb2xjYW5vIHBsb3RzIGNvbnRyYXN0IG9mOiBBLiBWZW5uIGRpYWdyYW0KZm9yIHVwcmVndWxhdGVkIGFuZCBkb3ducmVndWxhdGVkIGdlbmVzIGJ5IGluZmVjdGlvbiB3aXRoIDIuMyBhbmQgMi4yCnN0cmFpbnMuIEIuIGluZmVjdGVkIGNlbGxzIHdpdGggMi4zIHN0cmFpbnMgYW5kIHVuaW5mZWN0ZWQgY2VsbHM7CkMuIGluZmVjdGVkIGNlbGxzIHdpdGggMi4yIHN0cmFpbnMgYW5kIHVuaW5mZWN0ZWQgY2VsbHM7IEQuIGluZmVjdGVkCmNlbGxzIHdpdGggMi4zIHN0cmFpbnMgYW5kIGluZmVjdGVkIGNlbGxzIHdpdGggMi4yIHN0cmFpbnMiCgpUaGUgZm9sbG93aW5nIHVwc2V0IHBsb3QgaXMgY3VycmVudGx5IEZpZ3VyZSAyRS4KCmBgYHtyfQpub2RydWdfdXBzZXQgPC0gdXBzZXRyX2NvbWJpbmVkX2RlKGhzX21hY3JfdGFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaXJlZF9jb250cmFzdHMgPSBjKCJ6MjJub3NiX3ZzX3VuaW5mIiwgInoyM25vc2JfdnNfdW5pbmYiKSkKcHAoZmlsZSA9ICJpbWFnZXMvbm9kcnVnX3Vwc2V0LnN2ZyIpCm5vZHJ1Z191cHNldFtbInBsb3QiXV0KZGV2Lm9mZigpCm5vZHJ1Z191cHNldApgYGAKCiMjIyMgQSBwb2ludCBvZiBpbnRlcmVzdCB3aGlsZSBPbGdhIHZpc2l0cyBVbWQKCk5hamliIGFuZCBPbGdhIGFza2VkIGFib3V0IHB1bGxpbmcgdGhlIDkgZ2VuZSBJRHMgd2hpY2ggYXJlIGluIHRoZQpwZWN1bGlhciBzaXR1YXRpb24gb2YgaW5jcmVhc2VkIGV4cHJlc3Npb24gaW4gejIuMi91bmluZiBhbmQgZGVjcmVhc2VkCmluIHoyLjMvdW5pbmYuICBJbiB0aGUgcHJldmlvdXMgdXBzZXQgcGxvdCwgdGhlc2UgYXJlIHZpc2libGUgaW4gdGhlCjZ0aCBiYXIuICBJIGNhbiBhY2Nlc3MgdGhlc2UgdmlhIHRoZSBhdHRyKCkgZnVuY3Rpb24sIHdoaWNoIEkgc2hvdWxkCmFkbWl0IEkgY2FuIG5ldmVyIHJlbWVtYmVyIGhvdyB0byB1c2UsIHNvIEkgYW0gZ29pbmcgdG8gdXNlIHRoZSBjb2RlCnVuZGVyIHRoZSAnQ29tcGFyZShubylTYiB6Mi4zL3oyLjIgdHJlYXRtZW50JyBoZWFkaW5nIHRvIHJlbWVtYmVyIGhvdwp0byBleHRyYWN0IHRoZXNlIGdlbmVzLgoKYGBge3J9CmFsbF9ncm91cHMgPC0gbm9kcnVnX3Vwc2V0W1siZ3JvdXBzIl1dCndhbnRlZF9ncm91cCA8LSAiejIzbm9zYl92c191bmluZl9kb3duOnoyMm5vc2JfdnNfdW5pbmZfdXAiCmdlbmVfaWR4IDwtIGFsbF9ncm91cHNbW3dhbnRlZF9ncm91cF1dCndhbnRlZF9nZW5lcyA8LSBhdHRyKGFsbF9ncm91cHMsICJlbGVtZW50cyIpW2dlbmVfaWR4XQp3YW50ZWRfZ2VuZXMKZ2VuZV9zeW1ib2xfaWR4IDwtIHJvd25hbWVzKHJvd0RhdGEoaHNfbWFjcikpICVpbiUgYXMuY2hhcmFjdGVyKHdhbnRlZF9nZW5lcykKcm93RGF0YShoc19tYWNyKVtnZW5lX3N5bWJvbF9pZHgsICJoZ25jX3N5bWJvbCJdCmBgYAoKKiBBQkNCNTogQVRCIEJpbmRpbmcgQ2Fzc2V0dGUgU3ViZmFtaWx5IEIgTWVtYmVyICM1LCB3aWRlIHJhbmdlIG9mCiAgZnVuY3Rpb25zIGluIHRoaXMgZGl2ZXJzZSBwYXJhbG9nb3VzIGZhbWlseS4gIEFzc29jaWF0ZWQgd2l0aCBza2luCiAgZGlzZWFzZXMgKG1lbGFub21hIGFuZCBFcGlkZXJtb2x5c2lzIEJ1bGxvc2E7IHBhcnRpY2lwYXRlIGluCiAgQVRQLWRlcGVuZGVudCB0cmFuc21lbWJyYW5lIHRyYW5zcG9ydCkuCiogUkZYNDogUmVndWxhdG9yeSBGYWN0b3IgWCAjNDogdHJhbnNjcmlwdGlvbiBmYWN0b3IuCiogQ0ExNDogQ2FyYm9uaWMgYW5oeWRyYXNlICMxNDogWnluYyBtZXRhbGxvZW56eW1lIGNhdGFseXplcwogIHJldmVyc2libGUgaHlkcmF0aW9uIG9mIENPMi4gIFRoaXMgZ2VuZSBsb29rcyBwcmV0dHkgbmVhdCwgYnV0IG5vdAogIHJlYWxseSByZWxldmFudCB0byBhbnl0aGluZyB3ZSBhcmUgbGlrZWx5IHRvIGNhcmUgYWJvdXQuCiogRUdSMTogRWFybHkgR3Jvd3RoIFJlc3BvbnNlIFByb3RlaW4gIzE6IEFub3RoZXIgVHggZmFjdG9yCiAgKHppbmMtZmluZ2VyKSAtLSBpbXBvcnRhbnQgZm9yIGNlbGwgc3Vydml2YWwvcHJvbGlmZXJhdGlvbi9jZWxsCiAgZGVhdGguICBQcmVzdW1hYmx5IGltcG9ydGFudCBmb3IgaGVhbGluZz8KKiBNQ0YyTDogTUNGLjIgQ2VsbCBMaW5lIERlcml2ZWQgVHJhbnNmb3JtaW5nIFNlcXVlbmNlIExpa2U/ICBndWFuaW5lCiAgbnVjbGVvdGlkZSBleGNoYW5nZSBmYWN0b3IgaW50ZXJhY3Rpbmcgd2l0aCBHVFAtYm91bmQgUmFjMS4KICBBcHBhcmVudGx5IGFzc29jaWF0ZWQgd2l0aCBvc3Ryb2FydGhyaXRpczsgcG90ZW50aWFsbHkgcmVsZXZhbnQgdG8KICByZWd1bGF0aW9uIG9mIFJIT0EgYW5kIENEQzQyIHNpZ25hbGxpbmcuCiogRE5BU0UxTDM6IERlb3h5cmlib251Y2xlYXNlIEkgZmFtaWx5IG1lbWJlcjogbm90IGluaGliaXRlZCBieSBhY3RpbiwKICBicmVha3MgZG93biBETkEgZHVyaW5nIGFwb3B0b3Npcy4gIEltcG9ydGFudCBkdXJpbmcgbmVjcm9zaXMuCiogRk9TOiBQcm90by1PbmNvZ2VuZSwgQVAtMSBUcmFuc2NyaXB0aW9uIEZhY3RvcjogbGV1Y2luZSB6aXBwZXIKICBkaW1lcml6ZXMgd2l0aCBKVU4gZmFtaWx5IHByb3RlaW5zLCBmb3JtaW5nIHR4IGZhY3RvciBjb21wbGV4IEFQLTEuCiAgSW1wb3J0YW50IGZvciBjZWxsIHByb2xpZmVyYXRpb24sIGRpZmZlcmVudGlhdGlvbiwgYW5kCiAgdHJhbnNmb3JtYXRpb24uCiogSUZJVE0xMDogSW50ZXJmZXJvbi1JbmR1Y2VkIFRyYW5zbWVtYnJhbmUgUHJvdGVpbiAjMTAKKiBQS0QxTDM6IFBvbHljeXN0aW4gMSBMaWtlICMzLCBUcmFuc2llbnQgUmVjZXB0b3IgUG90ZW50aWFsIENoYW5uZWwKICBJbnRlcmFjdGluZzogMTEgdHJhbnNtZW1icmFuZSBkb21haW4gcHJvdGVpbiB3aGljaCBtaWdodCBoZWxwIGNyZWF0ZQogIGNhdGlvbiBjaGFubmVscy4KCkFzIHNvbWUgY29tcGFyaXNvbiBwb2ludHMsIHRoZSBWZW5uIGluIHRoZSBjdXJyZW50IGZpZ3VyZSBoYXM6CgoqIDM4NyB1cCB6Mi4zCiogMjU5IHVwIHoyLjIKKiA4MyBzaGFyZWQgdXAgejIuMyBhbmQgejIuMgoqIDI0NyBkb3duIHoyLjMKKiAzIGRvd24gejIuMgoqIDMgc2hhcmVkIGRvd24gejIuMyBhbmQgejIuMgoKIyMjIDIuMiBhbmQgMi4zIHdpdGggU2JWIHZzIDIuMiBhbmQgMi4zIHdpdGhvdXQgU2JWCgpUaGlzIGlzIG15IHZlcnNpb24gb2YgdGhlIFZlbm4gd2l0aCB0aGUgdGV4dDoKCiJEaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgaW4gbWFjcm9waGFnZXMgaW5mZWN0ZWQgd2l0aApzdWJwb3B1bGF0aW9ucyAyLjIgb3IgMi4zLCBpbiBwcmVzZW5jZSBvZiBTYlYuIFZvbGNhbm8gcGxvdHMgY29udHJhc3QKb2Y6IEEuIGluZmVjdGVkIGNlbGxzIHdpdGggMi4zIHN0cmFpbnMgKyBTYlYgYW5kIGluZmVjdGVkIGNlbGxzIHdpdGgKMi4zIHN0cmFpbnM7IEIuIGluZmVjdGVkIGNlbGxzIHdpdGggMi4yIHN0cmFpbnMgKyBTYlYgYW5kIGluZmVjdGVkCmNlbGxzIHdpdGggMi4yIHN0cmFpbnM7IEMuIGluZmVjdGVkIGNlbGxzIHdpdGggMi4zIHN0cmFpbnMgKyBTYlYgYW5kCmluZmVjdGVkIGNlbGxzIHdpdGggMi4yIHN0cmFpbnMgKyBTYlYuIEQuIFZlbm4gZGlhZ3JhbSBmb3IgdXByZWd1bGF0ZWQKYW5kIGRvd25yZWd1bGF0ZWQgZ2VuZXMgYnkgaW5mZWN0aW9uIHdpdGggMi4zK1NiViBhbmQgMi4yK1NiVgpzdHJhaW5zLiIKCkEgcXVlcnkgZnJvbSBPbGdhICgyMDI0MDgwMSk6IFBsZWFzZSBpbmNsdWRlIGluIHRoZSB1cHNldCBpbiBmaWd1cmUgMwp0aGUgY29udHJhc3Qgb2YgdW5pbmZlY3RlZCBjZWxscyArIFNiViB2cyB1bmluZmVjdGVkIHdpdGhvdXQgU2JWLgoKYGBge3J9CiMjIEkga2VlcCBtaXMtaW50ZXJwcmV0aW5nIHRoaXMgdGV4dCwgaXQgaXMgejIuMy96Mi4zU2JWIGFuZCB6Mi4yL3oyLjJTYlYKZHJ1Z25vZHJ1Z191cHNldCA8LSB1cHNldHJfY29tYmluZWRfZGUoaHNfbWFjcl90YWJsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaXJlZF9jb250cmFzdHMgPSBjKCJ6MjNzYl92c196MjNub3NiIiwgInoyMnNiX3ZzX3oyMm5vc2IiKSkKcHAoZmlsZSA9ICJpbWFnZXMvZHJ1Z25vZHJ1Z191cHNldC5wZGYiKQpkcnVnbm9kcnVnX3Vwc2V0W1sicGxvdCJdXQpkZXYub2ZmKCkKZHJ1Z25vZHJ1Z191cHNldAoKZHJ1Z25vZHJ1Z191bmluZl9jb250cmFzdHMgPC0gYygiejIzc2JfdnNfejIzbm9zYiIsICJ6MjJzYl92c196MjJub3NiIiwgInNiX3ZzX3VuaW5mIikKZHJ1Z25vZHJ1Z191cHNldF93aXRoX3VuaW5mIDwtIHVwc2V0cl9jb21iaW5lZF9kZShoc19tYWNyX3RhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpcmVkX2NvbnRyYXN0cyA9IGRydWdub2RydWdfdW5pbmZfY29udHJhc3RzKQpwcChmaWxlID0gImZpZ3VyZXMvZHJ1Z25vZHJ1Z193aXRoX3VuaW5mX3Vwc2V0LnN2ZyIpCmRydWdub2RydWdfdXBzZXRfd2l0aF91bmluZltbInBsb3QiXV0KZGV2Lm9mZigpCmRydWdub2RydWdfdXBzZXRfd2l0aF91bmluZgpgYGAKCkZvciBzb21lIGNvbXBhcmlzb24gcG9pbnRzLCB0aGUgdmVubiBpbWFnZSBoYXM6CgoqIDIyMiB1cCB6Mi4zIFNiVgoqIDEzNCB1cCB6Mi4yIFNiVgoqIDE4MiBkb3duIHoyLjMgU2JWCiogMzk2IGRvd24gejIuMiBTYlYKKiA2MDUgc2hhcmVkIGRvd24gejIuMiBhbmQgejIuMyBTYlYKKiAzNCBzaGFyZWQgZG93biB6Mi4yIFNiViBhbmQgdXAgejIuMyBTYlYKKiAzNjMgc2hhcmVkIHVwIHoyLjIgU2JWIGFuZCB6Mi4zIFNiVgoKIyMjIENvbXBhcmUgejIuMlNiViB2cyBTYlYgYW5kIHoyLjNTYlYgYW5kIFNiVgoKYGBge3J9CmRydWdfdXBzZXQgPC0gdXBzZXRyX2NvbWJpbmVkX2RlKGhzX21hY3JfdGFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2lyZWRfY29udHJhc3RzID0gYygiejIyc2JfdnNfc2IiLCAiejIzc2JfdnNfc2IiKSkKcHAoZmlsZSA9ICJpbWFnZXMvZHJ1Z191cHNldC5wZGYiKQpkcnVnX3Vwc2V0W1sicGxvdCJdXQpkZXYub2ZmKCkKZHJ1Z191cHNldApgYGAKCiMjIFNpZ25pZmljYW5jZSBiYXJwbG90IG9mIGludGVyZXN0CgpPbGdhIGtpbmRseSBzZW50IGEgc2V0IG9mIHBhcnRpY3VsYXJseSBpbnRlcmVzdGluZyBjb250cmFzdHMgYW5kCmNvbG9ycyBmb3IgYSBzaWduaWZpY2FuY2UgYmFycGxvdCwgdGhleSBpbmNsdWRlIHRoZSBmb2xsb3dpbmc6CgoqIHoyLjMgdnMuIHVuaW5mZWN0ZWQuCiogejIuMiB2cy4gdW5pbmZlY3RlZC4KKiB6Mi4zIHZzIHoyLjIKKiB6Mi4zU2J2IHZzIHoyLjMKKiB6Mi4yU2J2IHZzIHoyLjIKKiB6Mi4zU2J2IHZzIHoyLjJTYnYKKiBTYnYgdnMgdW5pbmZlY3RlZC4KClRoZSBleGlzdGluZyBzZXQgb2YgJ2tlZXBlcnMnIGV4dmlzZWQgdG8gdGhlc2UgaXMgdGFrZW4gZnJvbSB0aGUKZXh0YW50IHNldCBvZiAndG1yYzJfaHVtYW5fa2VlcGVycycgYW5kIGlzIGFzIGZvbGxvd3M6CgoKYGBge3J9CmJhcnBsb3Rfa2VlcGVycyA8LSBsaXN0KAogICMjIHoyLjMgdnMgdW5pbmZlY3RlZAogICJ6MjNub3NiX3ZzX3VuaW5mIiA9IGMoImluZl96MjMiLCAidW5pbmZfbm9uZSIpLAogICMjIHoyLjIgdnMgdW5pbmZlY3RlZAogICJ6MjJub3NiX3ZzX3VuaW5mIiA9IGMoImluZl96MjIiLCAidW5pbmZfbm9uZSIpLAogICMjIHoyLjMgdnMgejIuMgogICJ6MjNub3NiX3ZzX3oyMm5vc2IiID0gYygiaW5mX3oyMyIsICJpbmZfejIyIiksCiAgIyMgejIuM1NidiB2cyB6Mi4zCiAgInoyM3NiX3ZzX3oyM25vc2IiID0gYygiaW5mX3NiX3oyMyIsICJpbmZfejIzIiksCiAgIyMgejIuMlNidiB2cyB6Mi4yCiAgInoyMnNiX3ZzX3oyMm5vc2IiID0gYygiaW5mX3NiX3oyMiIsICJpbmZfejIyIiksCiAgIyMgejIuM1NidiB2cyB6Mi4yU2J2CiAgInoyM3NiX3ZzX3oyMnNiIiA9IGMoImluZl9zYl96MjMiLCAiaW5mX3NiX3oyMiIpLAogICMjIFNidiB2cyB1bmluZmVjdGVkLgogICJzYl92c191bmluZiIgPSBjKCJ1bmluZl9zYl9ub25lIiwgInVuaW5mX25vbmUiKSkKYmFycGxvdF9jb21iaW5lZCA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBoc19tYWNyX2RlLCBrZWVwZXJzID0gYmFycGxvdF9rZWVwZXJzLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9kZV90YWJsZXMvaHNfbWFjcl9kcnVnX3p5bW9fN2NvbnRyYXN0cy12e3Zlcn0ueGxzeCIpKQpgYGAKCk5vdyBsZXQgdXMgdXNlIHRoZSBjb2xvcnMgc3VnZ2VzdGVkIGJ5IE9sZ2EgdG8gbWFrZSBhIGJhcnBsb3Qgb2YKdGhlc2UuLi4KCmBgYHtyfQpjb2xvcl9saXN0IDwtICBjKCAiI2RlOGJmOSIsICIjYWQwN2UzIiwiIzQxMDI1NyIsICIjZmZhMGEwIiwgIiNmOTQwNDAiLCAiI2EwMDAwMCIpCmJhcnBsb3Rfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgYmFycGxvdF9jb21iaW5lZCwgY29sb3JfbGlzdCA9IGNvbG9yX2xpc3QsIGFjY29yZGluZ190byA9ICJkZXNlcSIsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvaHNfbWFjcl9kcnVnX3p5bW9fN2NvbnRyYXN0c19zaWctdnt2ZXJ9Lnhsc3giKSkKYmFycGxvdF9zaWcKYGBgCgojIFBST1BFUgoKSW4gb3VyIGxhc3QgbWVldGluZyB0aGVyZSB3ZXJlIHNvbWUgcXVlc3Rpb25zIGFib3V0IHRoZSBzdGF0aXN0aWNhbApwb3dlciBvZiBkaWZmZXJlbnQgZnV0dXJlIGV4cGVyaW1lbnRhbCBkZXNpZ25zLiAgT25lIHRoaW5nIEkgY2FuIGRvIGlzCnRvIHVzZSBQUk9QRVIgdG8gZXN0aW1hdGUgdGhlIHBvd2VyIG9mIGFuIGV4dGFudCBkYXRhc2V0IGFuZCBpbmZlcgpmcm9tIHRoYXQgdGhlIGxpa2VseSBwb3dlciBvZiBvdGhlciBkZXNpZ25zLgoKSW4gb3JkZXIgdG8gdXNlIHByb3Blciwgb25lIG11c3QgZmVlZCBpdCBvbmUgb3IgbW9yZSBERSB0YWJsZXMuCgpgYGB7cn0KcG93ZXJfZXN0aW1hdGUgPC0gc2ltcGxlX3Byb3Blcihoc19zaW5nbGVfdGFibGUpCgpwb3dlcl9lc3RpbWF0ZVtbMV1dW1sicG93ZXJfcGxvdCJdXQpwb3dlcl9lc3RpbWF0ZVtbMV1dW1sicG93ZXJ0ZF9wbG90Il1dCnBvd2VyX2VzdGltYXRlW1sxXV1bWyJwb3dlcmZkX3Bsb3QiXV0KYGBgCgojIE91ciBtYWluIHF1ZXN0aW9ucyBpbiBVOTM3CgpMZXQgdXMgZG8gdGhlIHNhbWUgY29tcGFyaXNvbnMgaW4gdGhlIFU5Mzcgc2FtcGxlcywgdGhvdWdoIEkgd2lsbCBub3QKZG8gdGhlIGV4dHJhIGNvbnRyYXN0cywgcHJpbWFyaWx5IGJlY2F1c2UgSSB0aGluayB0aGUgZGF0YXNldCBpcyBsZXNzCmxpa2VseSB0byBzdXBwb3J0IHRoZW0uCgpgYGB7cn0KdTkzN19kZSA8LSBhbGxfcGFpcndpc2UodTkzN19zZSwgbW9kZWxfc3ZzID0gInN2YXNlcSIsCiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlciA9IFRSVUUsIG1vZGVsX2ZzdHJpbmcgPSAifiAwICsgY29uZGl0aW9uIikKdTkzN19kZQp1OTM3X3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIHU5MzdfZGUsIGtlZXBlcnMgPSB1OTM3X2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy91OTM3X2RydWdfenltb190YWJsZS12e3Zlcn0ueGxzeCIpKQp1OTM3X3RhYmxlCmNvbWJpbmVkX3RvX3Rzdih1OTM3X3RhYmxlLCBjZWxsdHlwZSA9ICJ1OTM3IikKCnU5Mzdfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgdTkzN190YWJsZSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy91OTM3X2RydWdfenltb19zaWctdnt2ZXJ9Lnhsc3giKSkKdTkzN19zaWcKdTkzN19oaWdoc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgdTkzN190YWJsZSwgbWluX21lYW5fZXhwcnMgPSBoaWdoX2V4cHJlc3Npb24sIGV4cHJzX2NvbHVtbiA9IGhpZ2hfZXhwcmVzc2lvbl9jb2x1bW4sCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvdTkzN19kcnVnX3p5bW9faGlnaHNpZy12e3Zlcn0ueGxzeCIpKQp1OTM3X2hpZ2hzaWcKdTkzN19sZXNzc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgdTkzN190YWJsZSwgbGZjID0gMC42LAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9zaWdfdGFibGVzL3U5MzdfZHJ1Z196eW1vX2xlc3NzaWctdnt2ZXJ9Lnhsc3giKSkKdTkzN19sZXNzc2lnCmBgYAoKIyBDb21wYXJlIChubylTYiB6Mi4zL3oyLjIgdHJlYXRtZW50cyBhbW9uZyBtYWNyb3BoYWdlcwoKSW4gdGhlIGZvbGxvd2luZyBibG9jaywgSSB3aWxsIGp1bXAgYmFjayB0byB0aGUgbWFjcm9waGFnZSBzYW1wbGVzIGFuZApsb29rIGZvciBnZW5lcyB3aGljaCBhcmUgc2hhcmVkL3VuaXF1ZSB3aGVuIGNvbXBhcmluZyB6Mi4zL3oyLjIKZm9yIHRoZSBkcnVnIHRyZWF0ZWQgc2FtcGxlcyBhbmQgdGhlIHVudHJlYXRlZCBzYW1wbGVzLgoKYGBge3J9CnVwc2V0X3Bsb3RzX2hzX21hY3IgPC0gdXBzZXRyX3NpZygKICBoc19tYWNyX3NpZywgYm90aCA9IFRSVUUsCiAgY29udHJhc3RzID0gYygiejIzc2JfdnNfejIyc2IiLCAiejIzbm9zYl92c196MjJub3NiIikpCnVwc2V0X3Bsb3RzX2hzX21hY3JbWyJib3RoIl1dCmdyb3VwcyA8LSB1cHNldF9wbG90c19oc19tYWNyW1siYm90aF9ncm91cHMiXV0Kc2hhcmVkX2dlbmVzIDwtIGF0dHIoZ3JvdXBzLCAiZWxlbWVudHMiKVtncm91cHNbWzJdXV0gJT4lCiAgZ3N1YihwYXR0ZXJuID0gIl5nZW5lOiIsIHJlcGxhY2VtZW50ID0gIiIpCmxlbmd0aChzaGFyZWRfZ2VuZXMpCgpzaGFyZWRfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihzaGFyZWRfZ2VuZXMpCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KCmRydWdfZ2VuZXMgPC0gYXR0cihncm91cHMsICJlbGVtZW50cyIpW2dyb3Vwc1tbInoyM3NiX3ZzX3oyMnNiIl1dXSAlPiUKICBnc3ViKHBhdHRlcm4gPSAiXmdlbmU6IiwgcmVwbGFjZW1lbnQgPSAiIikKZHJ1Z29ubHlfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihkcnVnX2dlbmVzKQpkcnVnb25seV9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCmBgYAoKSSB3YW50IHRvIHRyeSBzb21ldGhpbmcsIGRpcmVjdGx5IGluY2x1ZGUgdGhlIHU5MzcgZGF0YSBpbiB0aGlzLgpUaHVzLCBpbiB0aGUgZm9sbG93aW5nIGJsb2NrIEkgd2lsbCByZXBlYXQgYnV0IGNvbXBhcmUgYWxsIHNhbXBsZXMgYW5kCnRoZSBVOTM3IHVzaW5nIHRoZSBzYW1lIGxvZ2ljLgoKYGBge3J9CmJvdGhfc2lnIDwtIGhzX21hY3Jfc2lnCm5hbWVzKGJvdGhfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV0pIDwtIHBhc3RlMCgibWFjcl8iLCBuYW1lcyhib3RoX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dKSkKbmFtZXMoYm90aF9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dKSA8LSBwYXN0ZTAoIm1hY3JfIiwgbmFtZXMoYm90aF9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dKSkKdTkzN19kZXNlcSA8LSB1OTM3X3NpZ1tbImRlc2VxIl1dCm5hbWVzKHU5MzdfZGVzZXFbWyJ1cHMiXV0pIDwtIHBhc3RlMCgidTkzN18iLCBuYW1lcyh1OTM3X2Rlc2VxW1sidXBzIl1dKSkKbmFtZXModTkzN19kZXNlcVtbImRvd25zIl1dKSA8LSBwYXN0ZTAoInU5MzdfIiwgbmFtZXModTkzN19kZXNlcVtbImRvd25zIl1dKSkKYm90aF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXSA8LSBjKGJvdGhfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV0sIHU5MzdfZGVzZXFbWyJ1cHMiXV0pCmJvdGhfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXSA8LSBjKGJvdGhfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV0sIHU5MzdfZGVzZXFbWyJkb3ducyJdXSkKc3VtbWFyeShib3RoX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dKQoKdXBzZXRfcGxvdHNfYm90aCA8LSB1cHNldHJfc2lnKAogIGJvdGhfc2lnLCBib3RoID0gVFJVRSwKICBjb250cmFzdHMgPSBjKCJtYWNyX3oyM3NiX3ZzX3oyMnNiIiwgIm1hY3JfejIzbm9zYl92c196MjJub3NiIiwKICAgICAgICAgICAgICAgICJ1OTM3X3oyM3NiX3ZzX3oyMnNiIiwgInU5MzdfejIzbm9zYl92c196MjJub3NiIikpCnVwc2V0X3Bsb3RzX2JvdGhbWyJib3RoIl1dCmBgYAoKIyMgQ29tcGFyZSBERSByZXN1bHRzIGZyb20gbWFjcm9waGFnZXMgYW5kIFU5Mzcgc2FtcGxlcwoKTG9va2luZyBhIGJpdCBtb3JlIGNsb3NlbHkgYXQgdGhlc2UsIEkgdGhpbmsgdGhlIHU5MzcgZGF0YSBpcyB0b28Kc3BhcnNlIHRvIGVmZmVjdGl2ZWx5IGNvbXBhcmUuCgpgYGB7cn0KbWFjcl91OTM3X2NvbXBhcmlzb24gPC0gY29tcGFyZV9kZV9yZXN1bHRzKGhzX21hY3JfdGFibGUsIHU5MzdfdGFibGUpCm1hY3JfdTkzN19jb21wYXJpc29uW1sibGZjX2hlYXQiXV0KCm1hY3JfdTkzN192ZW5ucyA8LSBjb21wYXJlX3NpZ25pZmljYW50X2NvbnRyYXN0cyhoc19tYWNyX3NpZywgc2Vjb25kX3NpZ190YWJsZXMgPSB1OTM3X3NpZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyYXN0cyA9ICJ6MjNzYl92c196MjNub3NiIikKbWFjcl91OTM3X3Zlbm5zW1sidXBfcGxvdCJdXQptYWNyX3U5MzdfdmVubnNbWyJkb3duX3Bsb3QiXV0KCm1hY3JfdTkzN192ZW5uc192MiA8LSBjb21wYXJlX3NpZ25pZmljYW50X2NvbnRyYXN0cygKICBoc19tYWNyX3NpZywgc2Vjb25kX3NpZ190YWJsZXMgPSB1OTM3X3NpZywgY29udHJhc3RzID0gInoyMnNiX3ZzX3oyMm5vc2IiKQptYWNyX3U5MzdfdmVubnNfdjJbWyJ1cF9wbG90Il1dCm1hY3JfdTkzN192ZW5uc192MltbImRvd25fcGxvdCJdXQoKbWFjcl91OTM3X3Zlbm5zX3YzIDwtIGNvbXBhcmVfc2lnbmlmaWNhbnRfY29udHJhc3RzKAogIGhzX21hY3Jfc2lnLCBzZWNvbmRfc2lnX3RhYmxlcyA9IHU5Mzdfc2lnLCBjb250cmFzdHMgPSAic2JfdnNfdW5pbmYiKQptYWNyX3U5MzdfdmVubnNfdjNbWyJ1cF9wbG90Il1dCm1hY3JfdTkzN192ZW5uc192M1tbImRvd25fcGxvdCJdXQpgYGAKCiMjIENvbXBhcmUgbWFjcm9waGFnZS91OTM3IHdpdGggcmVzcGVjdCB0byB6Mi4zL3oyLjIKCmBgYHtyfQpjb21wYXJpc29uX2RmIDwtIG1lcmdlKGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfejIyc2IiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgdTkzN190YWJsZVtbImRhdGEiXV1bWyJ6MjNzYl92c196MjJzYiJdXSwKICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJyb3cubmFtZXMiKQptYWNydTkzN196MjN6MjJfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGNvbXBhcmlzb25fZGZbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCm1hY3J1OTM3X3oyM3oyMl9wbG90W1sic2NhdHRlciJdXQoKY29tcGFyaXNvbl9kZiA8LSBtZXJnZShoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXSwKICAgICAgICAgICAgICAgICAgICAgICB1OTM3X3RhYmxlW1siZGF0YSJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXSwKICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJyb3cubmFtZXMiKQptYWNydTkzN196MjN6MjJfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGNvbXBhcmlzb25fZGZbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCm1hY3J1OTM3X3oyM3oyMl9wbG90W1sic2NhdHRlciJdXQpgYGAKCiMgQWRkIGRvbm9yIHRvIHRoZSBjb250cmFzdHMsIG5vIHN2YQoKSW4gdGhlIGZvbGxvd2luZyBibG9jaywgSSB3aWxsIGNoYW5nZSB0aGUgc2FtcGxlIGNvbmRpdGlvbiB0byBpbmNsdWRlCnRoZSBkb25vci4KCmBgYHtyfQpub19wb3dlcl9mYWN0IDwtIHBhc3RlMChjb2xEYXRhKGhzX21hY3IpW1siZG9ub3IiXV0sICJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YShoc19tYWNyKVtbImNvbmRpdGlvbiJdXSkKdGFibGUoY29sRGF0YShoc19tYWNyKVtbImRvbm9yIl1dKQp0YWJsZShub19wb3dlcl9mYWN0KQpoc19ub3Bvd2VyIDwtIHNldF9jb25kaXRpb25zKGhzX21hY3IsIGZhY3QgPSBub19wb3dlcl9mYWN0KQpoc19ub3Bvd2VyIDwtIHN1YnNldF9zZShoc19ub3Bvd2VyLCBzdWJzZXQgPSAibWFjcm9waGFnZXp5bW9kZW1lIT0nbm9uZSciKQpoc19ub3Bvd2VyX25vc3ZhX2RlIDwtIGFsbF9wYWlyd2lzZShoc19ub3Bvd2VyLCBtb2RlbF9zdnMgPSBGQUxTRSwgZmlsdGVyID0gVFJVRSkKbm9wb3dlcl9rZWVwZXJzIDwtIGxpc3QoCiAgImQwMV96eW1vIiA9IGMoImQwMWluZnoyMyIsICJkMDFpbmZ6MjIiKSwKICAiZDAxX3NienltbyIgPSBjKCJkMDFpbmZzYnoyMyIsICJkMDFpbmZzYnoyMiIpLAogICJkMDJfenltbyIgPSBjKCJkMDJpbmZ6MjMiLCAiZDAyaW5mejIyIiksCiAgImQwMl9zYnp5bW8iID0gYygiZDAyaW5mc2J6MjMiLCAiZDAyaW5mc2J6MjIiKSwKICAiZDA5X3p5bW8iID0gYygiZDA5aW5mejIzIiwgImQwOWluZnoyMiIpLAogICJkMDlfc2J6eW1vIiA9IGMoImQwOWluZnNiejIzIiwgImQwOWluZnNiejIyIiksCiAgImQ4MV96eW1vIiA9IGMoImQ4MWluZnoyMyIsICJkODFpbmZ6MjIiKSwKICAiZDgxX3NienltbyIgPSBjKCJkODFpbmZzYnoyMyIsICJkODFpbmZzYnoyMiIpKQpoc19ub3Bvd2VyX25vc3ZhX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGhzX25vcG93ZXJfbm9zdmFfZGUsIGtlZXBlcnMgPSBub3Bvd2VyX2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2RlX3RhYmxlcy9oc19ub3Bvd2VyX3RhYmxlLXZ7dmVyfS54bHN4IikpCiMjIGV4dHJhX2NvbnRyYXN0cyA9IGV4dHJhKQpoc19ub3Bvd2VyX25vc3ZhX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGhzX25vcG93ZXJfbm9zdmFfdGFibGUsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvaHNfbm9wb3dlcl9ub3N2YV9zaWctdnt2ZXJ9Lnhsc3giKSkKCmQwMWQwMl96eW1vX25vc3ZhX2NvbXAgPC0gbWVyZ2UoaHNfbm9wb3dlcl9ub3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoc19ub3Bvd2VyX25vc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwMl96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInJvdy5uYW1lcyIpCmQwMTAyX3p5bW9fbm9zdmFfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGQwMWQwMl96eW1vX25vc3ZhX2NvbXBbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCmQwMTAyX3p5bW9fbm9zdmFfcGxvdFtbInNjYXR0ZXIiXV0KZDAxMDJfenltb19ub3N2YV9wbG90W1siY29ycmVsYXRpb24iXV0KZDAxMDJfenltb19ub3N2YV9wbG90W1sibG1fcnNxIl1dCgpkMDlkODFfenltb19ub3N2YV9jb21wIDwtIG1lcmdlKGhzX25vcG93ZXJfbm9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDA5X3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHNfbm9wb3dlcl9ub3N2YV90YWJsZVtbImRhdGEiXV1bWyJkODFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJyb3cubmFtZXMiKQpkMDk4MV96eW1vX25vc3ZhX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihkMDlkODFfenltb19ub3N2YV9jb21wWywgYygiZGVzZXFfbG9nZmMueCIsICJkZXNlcV9sb2dmYy55IildKQpkMDk4MV96eW1vX25vc3ZhX3Bsb3RbWyJzY2F0dGVyIl1dCmQwOTgxX3p5bW9fbm9zdmFfcGxvdFtbImNvcnJlbGF0aW9uIl1dCmQwOTgxX3p5bW9fbm9zdmFfcGxvdFtbImxtX3JzcSJdXQoKZDAxZDgxX3p5bW9fbm9zdmFfY29tcCA8LSBtZXJnZShoc19ub3Bvd2VyX25vc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwMV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhzX25vcG93ZXJfbm9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDgxX3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAicm93Lm5hbWVzIikKZDAxODFfenltb19ub3N2YV9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoZDAxZDgxX3p5bW9fbm9zdmFfY29tcFssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKZDAxODFfenltb19ub3N2YV9wbG90W1sic2NhdHRlciJdXQpkMDE4MV96eW1vX25vc3ZhX3Bsb3RbWyJjb3JyZWxhdGlvbiJdXQpkMDE4MV96eW1vX25vc3ZhX3Bsb3RbWyJsbV9yc3EiXV0KCnVwc2V0X3Bsb3RzX25vc3ZhIDwtIHVwc2V0cl9zaWcoaHNfbm9wb3dlcl9ub3N2YV9zaWcsIGJvdGggPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyYXN0cyA9IGMoImQwMV96eW1vIiwgImQwMl96eW1vIiwgImQwOV96eW1vIiwgImQ4MV96eW1vIikpCnVwc2V0X3Bsb3RzX25vc3ZhW1sidXAiXV0KdXBzZXRfcGxvdHNfbm9zdmFbWyJkb3duIl1dCnVwc2V0X3Bsb3RzX25vc3ZhW1siYm90aCJdXQojIyBUaGUgN3RoIGVsZW1lbnQgaW4gdGhlIGJvdGggZ3JvdXBzIGxpc3QgaXMgdGhlIHNldCBzaGFyZWQgYW1vbmcgYWxsIGRvbm9ycy4KIyMgSSBkb24ndCBmZWVsIGxpa2Ugd3JpdGluZyBvdXQgeDp5Ono6YQpncm91cHMgPC0gdXBzZXRfcGxvdHNfbm9zdmFbWyJib3RoX2dyb3VwcyJdXQpzaGFyZWRfZ2VuZXMgPC0gYXR0cihncm91cHMsICJlbGVtZW50cyIpW2dyb3Vwc1tbN11dXSAlPiUKICBnc3ViKHBhdHRlcm4gPSAiXmdlbmU6IiwgcmVwbGFjZW1lbnQgPSAiIikKc2hhcmVkX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoc2hhcmVkX2dlbmVzKQpzaGFyZWRfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQpzaGFyZWRfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJCUCJdXQpzaGFyZWRfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIldQIl1dCmBgYAoKIyBBZGQgZG9ub3IgdG8gdGhlIGNvbnRyYXN0cywgc3ZhCgpTYW1lIGRlYWwgYXMgdGhlIGxhc3QgYmxvY2ssIGJ1dCB0aGlzIHRpbWUgYWRkIFNWQSBpbnRvIHRoZSBtaXghCgpgYGB7cn0KaHNfbm9wb3dlcl9zdmFfZGUgPC0gYWxsX3BhaXJ3aXNlKGhzX25vcG93ZXIsIG1vZGVsX3N2cyA9ICJzdmFzZXEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfZnN0cmluZyA9ICJ+IDAgKyBjb25kaXRpb24iLCBmaWx0ZXIgPSBUUlVFKQpub3Bvd2VyX2tlZXBlcnMgPC0gbGlzdCgKICAiZDAxX3p5bW8iID0gYygiZDAxaW5mejIzIiwgImQwMWluZnoyMiIpLAogICJkMDFfc2J6eW1vIiA9IGMoImQwMWluZnNiejIzIiwgImQwMWluZnNiejIyIiksCiAgImQwMl96eW1vIiA9IGMoImQwMmluZnoyMyIsICJkMDJpbmZ6MjIiKSwKICAiZDAyX3NienltbyIgPSBjKCJkMDJpbmZzYnoyMyIsICJkMDJpbmZzYnoyMiIpLAogICJkMDlfenltbyIgPSBjKCJkMDlpbmZ6MjMiLCAiZDA5aW5mejIyIiksCiAgImQwOV9zYnp5bW8iID0gYygiZDA5aW5mc2J6MjMiLCAiZDA5aW5mc2J6MjIiKSwKICAiZDgxX3p5bW8iID0gYygiZDgxaW5mejIzIiwgImQ4MWluZnoyMiIpLAogICJkODFfc2J6eW1vIiA9IGMoImQ4MWluZnNiejIzIiwgImQ4MWluZnNiejIyIikpCmhzX25vcG93ZXJfc3ZhX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGhzX25vcG93ZXJfc3ZhX2RlLCBrZWVwZXJzID0gbm9wb3dlcl9rZWVwZXJzLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9kZV90YWJsZXMvaHNfbm9wb3dlcl90YWJsZS12e3Zlcn0ueGxzeCIpKQojIyBleHRyYV9jb250cmFzdHMgPSBleHRyYSkKaHNfbm9wb3dlcl9zdmFfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgaHNfbm9wb3dlcl9zdmFfdGFibGUsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL3NpZ190YWJsZXMvaHNfbm9wb3dlcl9zdmFfc2lnLXZ7dmVyfS54bHN4IikpCgpkMDFkMDJfenltb19zdmFfY29tcCA8LSBtZXJnZShoc19ub3Bvd2VyX3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHNfbm9wb3dlcl9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDAyX3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInJvdy5uYW1lcyIpCmQwMTAyX3p5bW9fc3ZhX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihkMDFkMDJfenltb19zdmFfY29tcFssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKZDAxMDJfenltb19zdmFfcGxvdFtbInNjYXR0ZXIiXV0KZDAxMDJfenltb19zdmFfcGxvdFtbImNvcnJlbGF0aW9uIl1dCmQwMTAyX3p5bW9fc3ZhX3Bsb3RbWyJsbV9yc3EiXV0KCmQwOWQ4MV96eW1vX3N2YV9jb21wIDwtIG1lcmdlKGhzX25vcG93ZXJfc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwOV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoc19ub3Bvd2VyX3N2YV90YWJsZVtbImRhdGEiXV1bWyJkODFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAicm93Lm5hbWVzIikKZDA5ODFfenltb19zdmFfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGQwOWQ4MV96eW1vX3N2YV9jb21wWywgYygiZGVzZXFfbG9nZmMueCIsICJkZXNlcV9sb2dmYy55IildKQpkMDk4MV96eW1vX3N2YV9wbG90W1sic2NhdHRlciJdXQpkMDk4MV96eW1vX3N2YV9wbG90W1siY29ycmVsYXRpb24iXV0KZDA5ODFfenltb19zdmFfcGxvdFtbImxtX3JzcSJdXQoKZDAxZDgxX3p5bW9fc3ZhX2NvbXAgPC0gbWVyZ2UoaHNfbm9wb3dlcl9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDAxX3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhzX25vcG93ZXJfc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQ4MV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJyb3cubmFtZXMiKQpkMDE4MV96eW1vX3N2YV9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoZDAxZDgxX3p5bW9fc3ZhX2NvbXBbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCmQwMTgxX3p5bW9fc3ZhX3Bsb3RbWyJzY2F0dGVyIl1dCmQwMTgxX3p5bW9fc3ZhX3Bsb3RbWyJjb3JyZWxhdGlvbiJdXQpkMDE4MV96eW1vX3N2YV9wbG90W1sibG1fcnNxIl1dCgp1cHNldF9wbG90c19zdmEgPC0gdXBzZXRyX3NpZyhoc19ub3Bvd2VyX3N2YV9zaWcsIGJvdGggPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cmFzdHMgPSBjKCJkMDFfenltbyIsICJkMDJfenltbyIsICJkMDlfenltbyIsICJkODFfenltbyIpKQp1cHNldF9wbG90c19zdmFbWyJ1cCJdXQp1cHNldF9wbG90c19zdmFbWyJkb3duIl1dCnVwc2V0X3Bsb3RzX3N2YVtbImJvdGgiXV0KIyMgVGhlIDd0aCBlbGVtZW50IGluIHRoZSBib3RoIGdyb3VwcyBsaXN0IGlzIHRoZSBzZXQgc2hhcmVkIGFtb25nIGFsbCBkb25vcnMuCiMjIEkgZG9uJ3QgZmVlbCBsaWtlIHdyaXRpbmcgb3V0IHg6eTp6OmEKZ3JvdXBzIDwtIHVwc2V0X3Bsb3RzX3N2YVtbImJvdGhfZ3JvdXBzIl1dCnNoYXJlZF9nZW5lcyA8LSBhdHRyKGdyb3VwcywgImVsZW1lbnRzIilbZ3JvdXBzW1s3XV1dICU+JQogIGdzdWIocGF0dGVybiA9ICJeZ2VuZToiLCByZXBsYWNlbWVudCA9ICIiKQpzaGFyZWRfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihzaGFyZWRfZ2VuZXMpCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0Kc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KYGBgCgojIERvbm9yIGNvbXBhcmlzb24KCk5vdyBjb21wYXJlIHRoZSBkb25vcnMgdG8gZWFjaCBvdGhlciBkaXJlY3RseS4KCmBgYHtyfQpoc19kb25vcnMgPC0gc2V0X2NvbmRpdGlvbnMoaHNfbWFjciwgZmFjdCA9ICJkb25vciIpCmRvbm9yX2RlIDwtIGFsbF9wYWlyd2lzZShoc19kb25vcnMsIG1vZGVsX3N2cyA9ICJzdmFzZXEiLAogICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfZnN0cmluZyA9ICJ+IDAgKyBjb25kaXRpb24iLCBmaWx0ZXIgPSBUUlVFKQpkb25vcl9kZQpkb25vcl90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBkb25vcl9kZSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZGVfdGFibGVzL2Rvbm9yX3RhYmxlcy12e3Zlcn0ueGxzeCIpKQpkb25vcl90YWJsZQpkb25vcl9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBkb25vcl90YWJsZSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9kb25vcl9zaWctdnt2ZXJ9Lnhsc3giKSkKZG9ub3Jfc2lnCmBgYAoKIyBQcmltYXJ5IHF1ZXJ5IGNvbnRyYXN0cwoKVGhlIGZpbmFsIGNvbnRyYXN0IGluIHRoaXMgbGlzdCBpcyBpbnRlcmVzdGluZyBiZWNhdXNlIGl0IGRlcGVuZHMgb24KdGhlIGV4dHJhIGNvbnRyYXN0cyBhcHBsaWVkIHRvIHRoZSBhbGxfcGFpcndpc2UoKSBhYm92ZS4gIEluIG15IHdheSBvZgp0aGlua2luZywgdGhlIHByaW1hcnkgY29tcGFyaXNvbnMgdG8gY29uc2lkZXIgYXJlIGVpdGhlciBjcm9zcy1kcnVnIG9yCmNyb3NzLXN0cmFpbiwgYnV0IG5vdCBib3RoLiAgSG93ZXZlciBJIHRoaW5rIGluIGF0IGxlYXN0IGEgZmV3Cmluc3RhbmNlcyBPbGdhIGlzIGludGVyZXN0ZWQgaW4gc3RyYWluK2RydWcgLyB1bmluZmVjdGVkK25vZHJ1Zy4KCiMjIFdyaXRlIGNvbnRyYXN0IHJlc3VsdHMKCk5vdyBsZXQgdXMgd3JpdGUgb3V0IHRoZSB4bHN4IGZpbGUgY29udGFpbmluZyB0aGUgYWJvdmUgY29udHJhc3RzLgpUaGUgZmlsZSB3aXRoIHRoZSBzdWZmaXggX3RhYmxlLXZlcnNpb24gd2lsbCB0aGVyZWZvcmUgY29udGFpbiBhbGwKZ2VuZXMgYW5kIHRoZSBmaWxlIHdpdGggdGhlIHN1ZmZpeCBfc2lnLXZlcnNpb24gd2lsbCBjb250YWluIG9ubHkKdGhvc2UgZGVlbWVkIHNpZ25pZmljYW50IHZpYSBvdXIgZGVmYXVsdCBjcml0ZXJpYSBvZiBERVNlcTIgfGxvZ0ZDfCA+PSAxLjAKYW5kIGFkanVzdGVkIHAtdmFsdWUgPD0gMC4wNS4KCiMjIE92ZXIgcmVwcmVzZW50YXRpb24gc2VhcmNoZXMKCkkgZGVjaWRlZCB0byBtYWtlIG9uZSBpbml0aWFsbHkgc21hbGwsIGJ1dCBJIHRoaW5rIHF1aWNrbHkgYmlnIGNoYW5nZQp0byB0aGUgb3JnYW5pemF0aW9uIG9mIHRoaXMgZG9jdW1lbnQ6ICBJIGFtIG1vdmluZyB0aGUgR1NFQSBzZWFyY2hlcwp1cCB0byBpbW1lZGlhdGVseSBhZnRlciB0aGUgREUuICBJIHdpbGwgdGhlbiBtb3ZlIHRoZSBwbG90cyBvZiB0aGUKZ3Byb2ZpbGVyIHJlc3VsdHMgdG8gaW1tZWRpYXRlbHkgYWZ0ZXIgdGhlIHZhcmlvdXMgdm9sY2FubyBwbG90cyBzbwp0aGF0IGl0IGlzIGVhc2llciB0byBpbnRlcnByZXQgdGhlbS4KCkkgYW0gcmVhc29uYWJseSBjZXJ0YWluIHRoaXMgaXMgdGhlIHBsYWNlIHRvIGNoZWNrIHRoYXQgejIzbm8gZHJ1ZyAvCnVuaW5mZWN0ZWQgaGFzIHRoZSBleHBlY3RlZCBzZXQgb2YgZ2VuZXMgYW5kIHRoYXQgdGhlcmUgaXMgb3IgaXMgbm90IGEKcmVhY3RvbWUgcmVzdWx0LgoKUmVwcm9kdWNpYmlsaXR5IG5vdGU6IEdpdmVuIHRoYXQgdGhpcyBpcyBlbnRpcmVseSBkZXBlbmRlbnQgb24gYW4Kb25saW5lIHNlcnZpY2UsIEkgbXVzdCBhc3N1bWUgdGhhdCB0aGUgcmVzdWx0cyB3aWxsIGNoYW5nZSBvdmVyIHRpbWU7CmluIGFkZGl0aW9uIHRoZWlyIHdlYiBzZXJ2ZXJzIHVuZGVyZ28gbWFpbnRlbmFuY2UgcmVndWxhcmx5LCB3aGljaCBtYXkKcmVzdWx0IGluIHN5c3RlbWF0aWMgZmFpbHVyZSBvZiB0aGVzZSBhbmFseXNlcy4gIEkgbGlrZSBnUHJvZmlsZXIKcXVpdGUgYSBsb3QgZm9yIHRoaXMgdHlwZSBvZiBzdHVmZiwgYnV0IHRoaXMgaXMgYW4gaW1wb3J0YW50IGNhdmVhdC4KCkNvbnZlcnNlbHksIHRoZSBjbHVzdGVyUHJvZmlsZXIgcmVzdWx0cyBsYXRlciBkZXBlbmQgb24gYSBjb25zaXN0ZW50Cm9yZ2RiIGFubm90YXRpb24gc2V0IChvciByZWFjdG9tZSBvciB3aGF0ZXZlcik7IHRob3NlIHZlcnNpb25zIGFyZQpmaXhlZCBieSB0aGUgY29udGFpbmVyIGluc3RhbGxhdGlvbi4KCmBgYHtyfQphbGxfZ3AgPC0gYWxsX2dwcm9maWxlcihoc19tYWNyX3NpZywgZW5yaWNoX2lkX2NvbHVtbiA9ICJoZ25jX3N5bWJvbCIpCmZvciAoZyBpbiBzZXFfbGVuKGxlbmd0aChhbGxfZ3ApKSkgewogIG5hbWUgPC0gbmFtZXMoYWxsX2dwKVtnXQogIGRhdHVtIDwtIGFsbF9ncFtbbmFtZV1dCiAgZmlsZW5hbWUgPC0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9ncHJvZmlsZXIve25hbWV9X2dwcm9maWxlci12e3Zlcn0ueGxzeCIpCiAgd3JpdHRlbiA8LSBzbSh3cml0ZV9ncHJvZmlsZXJfZGF0YShkYXR1bSwgZXhjZWwgPSBmaWxlbmFtZSkpCn0KbGVzc3NpZ19hbGxfZ3AgPC0gYWxsX2dwcm9maWxlcihoc19tYWNyX2xlc3NzaWcsIGVucmljaF9pZF9jb2x1bW4gPSAiaGduY19zeW1ib2wiKQpmb3IgKGcgaW4gc2VxX2xlbihsZW5ndGgobGVzc3NpZ19hbGxfZ3ApKSkgewogIG5hbWUgPC0gbmFtZXMobGVzc3NpZ19hbGxfZ3ApW2ddCiAgZGF0dW0gPC0gbGVzc3NpZ19hbGxfZ3BbW25hbWVdXQogIGZpbGVuYW1lIDwtIGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZ3Byb2ZpbGVyL3tuYW1lfV9ncHJvZmlsZXJfbGVzc3NpZy12e3Zlcn0ueGxzeCIpCiAgd3JpdHRlbiA8LSBzbSh3cml0ZV9ncHJvZmlsZXJfZGF0YShkYXR1bSwgZXhjZWwgPSBmaWxlbmFtZSkpCn0KYGBgCgojIyBFeHBsaWNpdCBHU0VBIHNlYXJjaCB2aXMgY2x1c3RlclByb2ZpbGVyCgpgYGB7cn0KYWxsX2NwIDwtIGFsbF9jcHJvZmlsZXIoaHNfbWFjcl9zaWcsIGhzX21hY3JfdGFibGUpCmBgYAoKIyMgU3BlY2lmaWMgZGVzaXJlcyBpbiBSZWFjdG9tZSByZXN1bHRzCgpJbiBwcmV2aW91cyBhbmFseXNlcyAoSSB0aGluayBieSBEci4gQ29sbWVuYXJlcyksIGEgc3BlY2lmaWMKVHJ5cHRvcGhhbiBiaW9zeW50aGVzaXMgcGF0aHdheSB3YXMgb2JzZXJ2ZWQuICBQYXJ0Y2l1bGFybHkgaW4gdGhlCjIuMy91bmluZmVjdGVkIGNvbXBhcmlzb24uICBJIHRoaW5rIG15IGdwcm9maWxlciBhbmFseXNpcyBpcyB0b28Kc3RyaW5nZW50IGFuZCB0aGVyZWZvcmUgbm90IG9ic2VydmluZyB0aGlzLiAgT2xnYSBhc2tlZCBpZiBJIGNvdWxkCmxvb2sgYXQgdGhhdCBhbmQgc2VlIGlmIHRoZXJlIGFyZSB0cml2aWFsIHNldHRpbmdzIEkgY2FuIGNoYW5nZSB0bwpoaWdobGlnaHQgdGhpcyBwYXRod2F5LiAgVGhlIHR3byBtb3N0IGxpa2VseSB0aGluZ3MgSSBjYW4gY2hhbmdlIGFyZQp0aGUgc3RyaW5nZW5jaWVzIG9mIHRoZSBERSBhbmFseXNpcyBhbmQvb3IgZ1Byb2ZpbGVyLgoKYGBge3J9CnRlc3RfejIzX3VuaW5mX3VwIDwtIGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjNub3NiX3ZzX3VuaW5mIl1dCm5yb3codGVzdF96MjNfdW5pbmZfdXApCnRlc3RfejIzX3VuaW5mX2Rvd24gPC0gaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1siejIzbm9zYl92c191bmluZiJdXQpucm93KHRlc3RfejIzX3VuaW5mX2Rvd24pCgp0ZXN0X2dwX3VwIDwtIHNpbXBsZV9ncHJvZmlsZXIodGVzdF96MjNfdW5pbmZfdXAsIGVucmljaF9pZF9jb2x1bW4gPSAiaGduY19zeW1ib2wiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyZXNob2xkID0gMS4wKQp0ZXN0X2dwX3VwCndyaXR0ZW5fdXAgPC0gd3JpdGVfZ3Byb2ZpbGVyX2RhdGEodGVzdF9ncF91cCwgZXhjZWwgPSAiZXhjZWwvejIzX3VuaW5mX2dwX3VwX2FsbC54bHN4IikKCnRlc3RfZ3BfZG93biA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHRlc3RfejIzX3VuaW5mX2Rvd24sIGVucmljaF9pZF9jb2x1bW4gPSAiaGduY19zeW1ib2wiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJlc2hvbGQgPSAxLjApCnRlc3RfZ3BfZG93bgp3cml0dGVuX2Rvd24gPC0gd3JpdGVfZ3Byb2ZpbGVyX2RhdGEodGVzdF9ncF9kb3duLCBleGNlbCA9ICJleGNlbC96MjNfdW5pbmZfZ3BfZG93bl9hbGwueGxzeCIpCmBgYAoKIyMgUGxvdCBjb250cmFzdHMgb2YgaW50ZXJlc3QKCk9uZSBzdWdnZXN0aW9uIEkgcmVjZWl2ZWQgcmVjZW50bHkgd2FzIHRvIHNldCB0aGUgYXhlcyBmb3IgdGhlc2UKdm9sY2FubyBwbG90cyB0byBiZSBzdGF0aWMgcmF0aGVyIHRoYW4gbGV0IGdncGxvdCBjaG9vc2UgaXRzIG93bi4gIEkKYW0gYXNzdW1pbmcgdGhpcyBpcyBvbmx5IHJlbGV2YW50IGZvciBwYWlycyBvZiBjb250cmFzdHMsIGJ1dCB0aGF0Cm1pZ2h0IG5vdCBiZSB0cnVlLgoKIyMgSW5kaXZpZHVhbCB6eW1vZGVtZXMgdnMuIHVuaW5mZWN0ZWQKClRoZSBmb2xsb3dpbmcgYmxvY2tzIHdpbGwgYmUgYSBsb3Qgb2YgcmVwZXRpdGlvbi4gIEluIGVhY2ggY2FzZSBJIGFtCnlhbmtpbmcgb3V0IHRoZSB2b2xjYW5vIHBsb3QgZm9yIGEgc3BlY2lmaWMgY29udHJhc3QgYW5kIHNob3dpbmcgdGhlCm9yaWdpbmFsIGZvbGxvd2VkIGJ5IGEgdmVyc2lvbiB3aXRoIGRpZmZlcmVudCBjb2xvcnMvbGFiZWxsaW5nLgoKIyMjIEluZmVjdGVkIHdpdGggejIuMyBubyBBbnRpbW9uaWFsIHZzLiBVbmluZmVjdGVkCgpgYGB7cn0KcGxvdF9jb2xvcnMgPC0gZ2V0X3NlX2NvbG9ycyhoc19tYWNyX3RhYmxlW1siaW5wdXQiXV1bWyJpbnB1dCJdXSkKCiMjIFRoZSBvcmlnaW5hbCBwbG90IGZyb20gbXkgeGxzeCBmaWxlCmhzX21hY3JfdGFibGVbWyJwbG90cyJdXVtbInoyM25vc2JfdnNfdW5pbmYiXV1bWyJkZXNlcV92b2xfcGxvdHMiXV0KCnoyM25vc2JfdnNfdW5pbmZfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGlucHV0ID0gaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNub3NiX3ZzX3VuaW5mIl1dLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jX3N5bWJvbCIsCiAgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJ1bmluZm5vbmUiXV0sIGNvbG9yX2hpZ2ggPSBwbG90X2NvbG9yc1tbImluZnoyMyJdXSkKCmxhYmVsZWQgPC0gejIzbm9zYl92c191bmluZl92b2xjYW5vW1sicGxvdCJdXSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTYsIDIxKSwgYnJlYWtzID0gYygtNiwgLTQsIC0yLCAwLCAyLCA0LCA2LCA4LCAxMCwgMjApKSArCiAgZ2dicmVhazo6c2NhbGVfeF9icmVhayhjKDEwLCAxOSksIHNjYWxlcyA9IDAuMiwgc3BhY2UgPSAwLjAyKQpwcChmaWxlID0gImZpZ3VyZXMvZmlnMmFfbGFiZWxlZF93aXRoX2JyZWFrLnN2ZyIpCmxhYmVsZWQKZGV2Lm9mZigpCmxhYmVsZWQKCnBsb3RseTo6Z2dwbG90bHkoejIzbm9zYl92c191bmluZl92b2xjYW5vW1sicGxvdCJdXSkKYGBgCgpUaGUgZm9sbG93aW5nIHByb3ZpZGVzIHNvbWUgb2YgdGhlIG92ZXItcmVwcmVzZW50YXRpb24gcGxvdHMgZnJvbSBnUHJvZmlsZXIyLgoKYGBge3J9CmFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIktFR0ciXV0KIyMgS0VHRywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCiMjYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIldQIl1dCiMjIFdpa2lQYXRod2F5cywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfdXAiXV1bWyJpbnRlcmFjdGl2ZV9wbG90cyJdXVtbIldQIl1dCgptZXNzYWdlKCJPbGdhIHJlY2VpdmVkIGEgcXVlcnkgYWJvdXQgdGhlIGZvbGxvd2luZyByZXN1bHQsIEkgdGhpbmsgaXQgaXMgbnVsbC4iKQphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCm1lc3NhZ2UoIklzIHRoZSBwcmV2aW91cyBwbG90IG51bGw/IikKIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYGBgCgpXZSBoYXZlIHNvbWUgb3RoZXIgY2F0ZWdvcmljYWwgZW5yaWNobWVudCBwbG90cyBhdmFpbGFibGUgdmlhCmVucmljaHBsb3QsIGxldCB1cyB0cnkgYSBmZXcgb3V0IGZvciBjb250cmFzdHMgb2YgaW50ZXJlc3QgYW5kIHNlZSBpZgphbnkgb2YgdGhlbSBwcm92ZSBoZWxwZnVsLgoKRmlyc3QsIGFzIGEgcmVtaW5kZXIsIGhlcmUgYXJlIHRoZSBjb250cmFzdHMgd2hpY2ggYXJlIGF2YWlsYWJsZSB0bwpleGFtaW5lLCBpbiBlYWNoIGNhc2UgdGhlcmUgaXMgYW4gX3VwIGFuZCBfZG93biBlbnJpY2htZW50IG9iamVjdCBpbgp0aGUgZGF0YS4gIFRodXMgaW4gdGhlIGZvbGxvd2luZyBsaXN0IEkgYW0gZ29pbmcgdG8gYXJiaXRyYXJpbHkgcHJpbnQKb3V0IHNvbWUgaW52b2NhdGlvbnMgd2hpY2ggZXh0cmFjdCBwdXRhdGl2ZWx5IGludGVyZXN0aW5nIGJpdHMgb2YgZGF0YS4KCiogejIzbm9zYl92c191bmluZjogYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbIkJQX2VucmljaCJdXQoqIHoyMm5vc2JfdnNfdW5pbmYuCiogejIzbm9zYl92c196MjJub3NiLgoqIHoyM3NiX3ZzX3oyMnNiLgoqIHoyM3NiX3ZzX3oyM25vc2IuCiogejIyc2JfdnNfejIybm9zYi4KKiB6MjNzYl92c19zYi4KKiB6MjJzYl92c19zYi4KKiB6MjNzYl92c191bmluZi4KKiB6MjJzYl92c191bmluZi4KKiBzYl92c191bmluZi4KKiBleHRyYV96MjMyMi4KKiBleHRyYV9kcnVnbm9kcnVnLgoKYGBge3J9CnoyM25vc2JfdW5pbmZfdXBfZ28gPC0gYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbIkJQX2VucmljaCJdXQp6MjNub3NiX3VuaW5mX3VwX2dvX3BhaXIgPC0gcGFpcndpc2VfdGVybXNpbSh6MjNub3NiX3VuaW5mX3VwX2dvKQpkb3RwbG90KHoyM25vc2JfdW5pbmZfdXBfZ28pCmVtYXBwbG90KHoyM25vc2JfdW5pbmZfdXBfZ29fcGFpcikKIyNzc3Bsb3QoejIzbm9zYl91bmluZl91cF9nb19wYWlyKQp0cmVlcGxvdCh6MjNub3NiX3VuaW5mX3VwX2dvX3BhaXIpCnVwc2V0cGxvdCh6MjNub3NiX3VuaW5mX3VwX2dvKQpjbmV0cGxvdCh6MjNub3NiX3VuaW5mX3VwX2dvKQpgYGAKCiMjIyBSZXBlYXQsIGJ1dCB1c2luZyBhIGxlc3Mgc3RyaWN0IHNldCBvZiAnc2lnbmlmaWNhbnQgZ2VuZXMnCgpJIGFtIG5vdCBlbnRpcmVseSBjZXJ0YWluIGlmIHRoZSBSZWFjdG9tZSByZXN1bHRzIE9sZ2Egc2hvd2VkIG1lCmluY2x1ZGVkIGJvdGggdXAgYW5kIGRvd24gZ2VuZXM/ICBJIGFtIGdvaW5nIHRvIGFzc3VtZSBmb3IgdGhlIG1vbWVudAp0aGF0IGl0IHdhcyBqdXN0IHVwL2Rvd24sIGJ1dCBpZiB0aGF0IHByb3ZlcyBpbnRyYWN0YWJsZSBJIHdpbGwgZ28KYmFjayB0byB0aGUgbWFudXNjcmlwdCBhbmQgcmVhZCBtb3JlIGNhcmVmdWxseSAoZS5nLiBJIGp1c3QgcmVtZW1iZXJlZAp3aGVyZSB0aGUgcGljdHVyZSBjYW1lIGZyb20hKQoKIyMjIyBBZGQgYSBsaXR0bGUgdG9wZ28KCkluIHRoZSBwcm9jZXNzIG9mIGV4cGxvcmluZyB0aGUgdmFyaW91cyBwYXJhbWV0ZXJzIHVzZWQgd2l0aApnUHJvZmlsZXIyLCBJIGZvdW5kIG15c2VsZiB0aGlua2luZyB0aGF0IGl0IHdvdWxkIGJlIG5pY2UgdG8gaGF2ZSBzb21lCnRvcGdvIHJlc3VsdHMgdG8gY29tcGFyZSBhZ2FpbnN0LiAgVGhlIGZvbGxvd2luZyBibG9jayBpcyB0aGUgcmVzdWx0Cm9mIHRoYXQgdGhvdWdodC4KCmBgYHtyfQp0ZXN0X2dlbmVzX3VwIDwtIGhzX21hY3JfbGVzc3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIzbm9zYl92c191bmluZiJdXQp0ZXN0X3F1ZXJ5X3VwIDwtIHNpbXBsZV9ncHJvZmlsZXIodGVzdF9nZW5lc191cCwgdGhyZXNob2xkID0gMC4xKQp0ZXN0X3F1ZXJ5X3VwW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQpwZGYoZmlsZSA9ICJpbWFnZXMvdGVzdF9xdWVyeV9iaW9sb2dpY2FsX3Byb2Nlc3NfejIzX3ZzX3VuaW5mX3VwLnBkZiIsIGhlaWdodCA9IDEyLCB3aWR0aCA9IDkpCnRlc3RfcXVlcnlfdXBbWyJwdmFsdWVfcGxvdHMiXV1bWyJCUCJdXQpkZXYub2ZmKCkKZW5yaWNocGxvdDo6ZG90cGxvdCh0ZXN0X3F1ZXJ5X3VwW1siQlBfZW5yaWNoIl1dKQp0ZXN0X2dlbmVzX2Rvd24gPC0gaHNfbWFjcl9sZXNzc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyM25vc2JfdnNfdW5pbmYiXV0KdGVzdF9xdWVyeV9kb3duIDwtIHNpbXBsZV9ncHJvZmlsZXIodGVzdF9nZW5lc19kb3duKQp0ZXN0X3F1ZXJ5X2Rvd25bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCgojIyBJIGtlZXAgZ2V0dGluZyBhbGwgc29ydHMgb2YgYW5ub3lpbmcgYmlvbWFydCBlcnJvcnMuCmhzX2dvIDwtIHRyeShsb2FkX2Jpb21hcnRfZ28oYXJjaGl2ZSA9IEZBTFNFLCBvdmVyd3JpdGUgPSBUUlVFKSkKaWYgKCJ0cnktZXJyb3IiICVpbiUgY2xhc3MoaHNfZ28pKSB7CiAgaHNfZ28gPC0gbG9hZF9iaW9tYXJ0X2dvKGFyY2hpdmUgPSBUUlVFLCBtb250aCA9ICIwNCIsIHllYXIgPSAiMjAyMCIsIG92ZXJ3cml0ZSA9IFRSVUUpCn0KdGVzdF90b3Bnb191cCA8LSBzaW1wbGVfdG9wZ28odGVzdF9nZW5lc191cCwgZ29fZGIgPSBoc19nb1tbImdvIl1dLCBwYXJhbGxlbCA9IEZBTFNFKQp3cml0dGVuX3RvcGdvIDwtIHdyaXRlX3RvcGdvX2RhdGEoCiAgdGVzdF90b3Bnb191cCwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvb250b2xvZ3lfdG9wZ28vdG9wZ29fejIzX3VuaW5mX2xlc3Nfc3RyaWN0Lnhsc3giKSkKYGBgCgojIyMgSW5mZWN0ZWQgd2l0aCB6Mi4yIG5vIEFudGltb25pYWwgdnMuIFVuaW5mZWN0ZWQKCkhlcmUgaXMgd2hlcmUgdGhpbmdzIHdpbGwgZ2V0IG1vc3QgcmVwZXRpdGl2ZS4gIEluIGVhY2ggaW5zdGFuY2UgSSBhbQpjcmVhdGluZyBhIGNvdXBsZSBvZiB2b2xjYW5vIHBsb3RzIGZvbGxvd2VkIGJ5IHByaW50aW5nIHNvbWUgb2YgdGhlCmdQcm9maWxlcjIgcmVzdWx0cyAod2hlbiBJIGdldCB0aGUgaXRjaCkuCgpUaGUgZm9sbG93aW5nIHNob3VsZCBiZSBhIHNsaWdodGx5IGltcHJvdmVkIHZlcnNpb24gb2Ygb3VyIGV4dGFudApmaWd1cmUgMkIuCgpgYGB7cn0KIyMgVGhlIG9yaWdpbmFsIHBsb3QKaHNfbWFjcl90YWJsZVtbInBsb3RzIl1dW1siejIybm9zYl92c191bmluZiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQoKejIybm9zYl92c191bmluZl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjJub3NiX3ZzX3VuaW5mIl1dLCAiejIybm9zYl92c191bmluZiIsCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNfc3ltYm9sIiwKICBjb2xvcl9sb3cgPSBwbG90X2NvbG9yc1tbInVuaW5mbm9uZSJdXSwgY29sb3JfaGlnaCA9IHBsb3RfY29sb3JzW1siaW5mejIyIl1dKQoKbGFiZWxlZCA8LSB6MjJub3NiX3ZzX3VuaW5mX3ZvbGNhbm9bWyJwbG90Il1dICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMiwgMjEpLCBicmVha3MgPSBjKC0yLCAwLCAyLCA0LCA2LCA4LCAxMCwgMjEsIDIyKSkgKwogIGdnYnJlYWs6OnNjYWxlX3hfYnJlYWsoYygxMSwgMjApLCBzY2FsZXMgPSAwLjIsIHNwYWNlID0gMC4wMikKcHAoZmlsZSA9ICJmaWd1cmVzL2ZpZzJiX2xhYmVsZWRfd2l0aF9icmVhay5zdmciKQpsYWJlbGVkCmRldi5vZmYoKQpsYWJlbGVkCgpwbG90bHk6OmdncGxvdGx5KHoyMm5vc2JfdnNfdW5pbmZfdm9sY2Fub1tbInBsb3QiXV0pCmBgYAoKQWRkIHNvbWUgcHZhbHVlIGJhcnBsb3RzIGZyb20gZ1Byb2ZpbGVyIGZvciB0aGlzIGNvbnRyYXN0LgoKYGBge3J9CmFsbF9ncFtbInoyMm5vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMiB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIybm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMiB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIybm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMiB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIybm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIldQIl1dCiMjIFdpa2lQYXRod2F5cywgenltb2RlbWUyLjIgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCgphbGxfZ3BbWyJ6MjJub3NiX3ZzX3VuaW5mX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMiB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjJub3NiX3ZzX3VuaW5mX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjIgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIybm9zYl92c191bmluZl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmBgYAoKIyMjIEluZmVjdGVkIHdpdGggejIuMyB0cmVhdGVkIHZzLiBVbmluZmVjdGVkIHRyZWF0ZWQKCkkgZG8gbm90IHRoaW5rIHRoaXMgcGxvdCBpcyB1c2VkIGF0IHRoaXMgdGltZS4KCmBgYHtyfQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlW1sicGxvdHMiXV1bWyJ6MjNzYl92c19zYiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQoKejIzc2JfdnNfdW5pbmZzYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNzYl92c19zYiJdXSwgInoyM3NiX3ZzX3NiIiwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY19zeW1ib2wiLAogIGNvbG9yX2xvdyA9IHBsb3RfY29sb3JzW1siaW5mc2J6MjMiXV0sIGNvbG9yX2hpZ2ggPSBwbG90X2NvbG9yc1tbInVuaW5mc2Jub25lIl1dKQp6MjNzYl92c191bmluZnNiX3ZvbGNhbm9bWyJwbG90Il1dCgpwbG90bHk6OmdncGxvdGx5KHoyM3NiX3ZzX3VuaW5mc2Jfdm9sY2Fub1tbInBsb3QiXV0pCmBgYAoKIyMjIEluZmVjdGVkIHdpdGggejIuMyB1bnRyZWF0ZWQgdnMuIHoyLjIgdW50cmVhdGVkCgpUaGlzIGlzIGZpZ3VyZSAyQyBhdCB0aGlzIHRpbWUuCgpgYGB7cn0KIyMgVGhlIG9yaWdpbmFsIHBsb3QKaHNfbWFjcl90YWJsZVtbInBsb3RzIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dCgp6MjNub3NiX3ZzX3oyMm5vc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dLCAiejIzbm9zYl92c196MjJub3NiIiwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY19zeW1ib2wiLAogIGNvbG9yX2xvdyA9IHBsb3RfY29sb3JzW1siaW5mejIzIl1dLCBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJpbmZ6MjIiXV0pCgpsYWJlbGVkIDwtIHoyM25vc2JfdnNfejIybm9zYl92b2xjYW5vW1sicGxvdCJdXSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoLTEwLCAtOCwgLTYsIC00LCAtMiwgMCwgMiwgNCwgNikpCgpwcChmaWxlID0gImZpZ3VyZXMvZmlnMmNfbGFiZWxlZC5zdmciKQpsYWJlbGVkCmRldi5vZmYoKQpsYWJlbGVkCmBgYAoKIyMjIEluZmVjdGVkIHdpdGggejIuMyB0cmVhdGVkIHZzLiB6Mi4yIHRyZWF0ZWQKClRoaXMgaXMgY3VycmVudGx5IGZpZ3VyZSAzQy4KCkZJWE1FOiBUaGUgYXhpcyBsYWJlbCBpc24ndCBxdWl0ZSByaWdodCBmb3IgdGhlIGdnYnJlYWsuCgpgYGB7cn0KIyMgVGhlIG9yaWdpbmFsIHBsb3QKaHNfbWFjcl90YWJsZVtbInBsb3RzIl1dW1siejIzc2JfdnNfejIyc2IiXV1bWyJkZXNlcV92b2xfcGxvdHMiXV0KCnoyM3NiX3ZzX3oyMnNiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2NvbmRpdGlvbl9kZSgKICBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyM3NiX3ZzX3oyMnNiIl1dLCAiejIzc2JfdnNfejIyc2IiLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jX3N5bWJvbCIsCiAgY29sb3JfaGlnaCA9IHBsb3RfY29sb3JzW1siaW5mc2J6MjMiXV0sIGNvbG9yX2xvdyA9IHBsb3RfY29sb3JzW1siaW5mc2J6MjIiXV0pCgpsYWJlbGVkIDwtIHoyM3NiX3ZzX3oyMnNiX3ZvbGNhbm9bWyJwbG90Il1dICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygtMjMsIC02LCAtNCwgLTIsIDAsIDIsIDQsIDYpKSArCiAgZ2dicmVhazo6c2NhbGVfeF9icmVhayhjKC01LCAtMjIuNSksIHNjYWxlcyA9IDEwLCBzcGFjZSA9IDAuMDIpCnBwKGZpbGUgPSAiZmlndXJlcy9maWczY19sYWJlbGVkX2JyZWFrcy5zdmciKQpsYWJlbGVkCmRldi5vZmYoKQpsYWJlbGVkCmBgYAoKIyMjIEluZmVjdGVkIHdpdGggejIuMyBTQiB0cmVhdGVkIHZzLiB6Mi4zIHVudHJlYXRlZAoKSSB0aGluayB0aGlzIGlzIGN1cnJlbnRseSBmaWd1cmUgM0EuCgpGSVhNRTogVGhlIGF4aXMgbGFiZWwgZm9yIHRoZSBnZ2JyZWFrIGlzbid0IHF1aXRlIHJpZ2h0LgoKYGBge3J9CiMjIFRoZSBvcmlnaW5hbCBwbG90CmhzX21hY3JfdGFibGVbWyJwbG90cyJdXVtbInoyM3NiX3ZzX3oyM25vc2IiXV1bWyJkZXNlcV92b2xfcGxvdHMiXV0KCnoyM3NiX3ZzX3oyM25vc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfejIzbm9zYiJdXSwgInoyM3NiX3ZzX3oyM25vc2IiLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jX3N5bWJvbCIsCiAgY29sb3JfaGlnaCA9IHBsb3RfY29sb3JzW1siaW5mc2J6MjMiXV0sIGNvbG9yX2xvdyA9IHBsb3RfY29sb3JzW1siaW5mejIzIl1dKQoKbGFiZWxlZCA8LSB6MjNzYl92c196MjNub3NiX3ZvbGNhbm9bWyJwbG90Il1dICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMTksIDYpLAogICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBjKC0yMCwgLTE4LCAtMTYsIC0xNCwgLTEyLCAtMTAsIC02LCAtNCwgLTIsIDAsIDIsIDQsIDYpKSArCiAgZ2dicmVhazo6c2NhbGVfeF9icmVhayhjKC0xNywgLTgpLCBzY2FsZXMgPSAxNywgc3BhY2UgPSAwLjAyKQpwcChmaWxlID0gImZpZ3VyZXMvZmlnM2FfbGFiZWxlZF93aXRoX2JyZWFrLnN2ZyIpCmxhYmVsZWQKZGV2Lm9mZigpCmxhYmVsZWQKYGBgCgojIyMgSW5mZWN0ZWQgd2l0aCB6Mi4zIFNCIHRyZWF0ZWQgdnMuIHoyLjMgdW50cmVhdGVkCgpgYGB7cn0KIyMgVGhlIG9yaWdpbmFsIHBsb3QKaHNfbWFjcl90YWJsZVtbInBsb3RzIl1dW1siejIyc2JfdnNfejIybm9zYiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQoKejIyc2JfdnNfejIybm9zYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19jb25kaXRpb25fZGUoCiAgaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjJzYl92c196MjJub3NiIl1dLCAiejIyc2JfdnNfejIybm9zYiIsCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNfc3ltYm9sIiwKICBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJpbmZzYnoyMiJdXSwgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJpbmZ6MjIiXV0pCgpsYWJlbGVkIDwtIHoyMnNiX3ZzX3oyMm5vc2Jfdm9sY2Fub1tbInBsb3QiXV0gKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKC02LCAtNCwgLTIsIDAsIDIsIDQsIDYpKQoKcHAoZmlsZSA9ICJmaWd1cmVzL2ZpZzNiX2xhYmVsZWQuc3ZnIikKbGFiZWxlZApkZXYub2ZmKCkKbGFiZWxlZApgYGAKCiMjIyBJbmZlY3RlZCB3aXRoIHoyLjMgU0IgdHJlYXRlZCB2cy4gdW5pbmZlY3RlZCB0cmVhdGVkCgpgYGB7cn0KeF9saW1pdHMgPC0gYygtNiwgNikKIyMgVGhlIG9yaWdpbmFsIHBsb3QKaHNfbWFjcl90YWJsZVtbInBsb3RzIl1dW1siejIzc2JfdnNfc2IiXV1bWyJkZXNlcV92b2xfcGxvdHMiXV0KCnoyM3NiX3ZzX3NiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2NvbmRpdGlvbl9kZSgKICBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyM3NiX3ZzX3NiIl1dLCAiejIzc2JfdnNfc2IiLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jX3N5bWJvbCIsIGludmVydCA9IFRSVUUsCiAgY29sb3JfbG93ID0gcGxvdF9jb2xvcnNbWyJpbmZzYnoyMyJdXSwgY29sb3JfaGlnaCA9IHBsb3RfY29sb3JzW1sidW5pbmZzYm5vbmUiXV0pCnoyM3NiX3ZzX3NiX3ZvbGNhbm9bWyJwbG90Il1dCmBgYAoKIyMjIEluZmVjdGVkIHdpdGggejIuMiBTQiB0cmVhdGVkIHZzLiB1bmluZmVjdGVkIHRyZWF0ZWQKCmBgYHtyfQojIyBUaGUgb3JpZ2luYWwgcGxvdApoc19tYWNyX3RhYmxlW1sicGxvdHMiXV1bWyJ6MjJzYl92c19zYiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQoKejIyc2JfdnNfc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIyc2JfdnNfc2IiXV0sICJ6MjJzYl92c19zYiIsCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNfc3ltYm9sIiwgaW52ZXJ0ID0gVFJVRSwKICBjb2xvcl9sb3cgPSBwbG90X2NvbG9yc1tbImluZnNiejIyIl1dLCBjb2xvcl9oaWdoID0gcGxvdF9jb2xvcnNbWyJ1bmluZnNibm9uZSJdXSkKejIyc2JfdnNfc2Jfdm9sY2Fub1tbInBsb3QiXV0KYGBgCgojIyMgVW5pbmZlY3RlZCtTYlYgdnMuIFVuaW5mZWN0ZWQtU2JWCgpUaGlzIGlzIGN1cnJlbnRseSBmaWd1cmUgM0QuCgpGSVhNRTogVGhpcyBuZWVkcyB0aGUgQk9MQTJCIGdnYnJlYWsuCgpgYGB7cn0KIyMgVGhlIG9yaWdpbmFsIHBsb3QKaHNfbWFjcl90YWJsZVtbInBsb3RzIl1dW1sic2JfdnNfdW5pbmYiXV1bWyJkZXNlcV92b2xfcGxvdHMiXV0KCnNiX3ZzX3VuaW5mX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2NvbmRpdGlvbl9kZSgKICBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInNiX3ZzX3VuaW5mIl1dLCAic2JfdnNfdW5pbmYiLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jX3N5bWJvbCIsCiAgY29sb3JfaGlnaCA9IHBsb3RfY29sb3JzW1sidW5pbmZzYm5vbmUiXV0sIGNvbG9yX2xvdyA9IHBsb3RfY29sb3JzW1sidW5pbmZub25lIl1dKQoKbGFiZWxlZCA8LSBzYl92c191bmluZl92b2xjYW5vW1sicGxvdCJdXSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoLTIzLCAtNiwgLTQsIC0yLCAwLCAyLCA0LCA2KSkgKwogIGdnYnJlYWs6OnNjYWxlX3hfYnJlYWsoYygtNSwgLTIyLjUpLCBzY2FsZXMgPSAxMCwgc3BhY2UgPSAwLjAyKQpwcChmaWxlID0gImZpZ3VyZXMvZmlnM2RfbGFiZWxlZF9icmVha3Muc3ZnIikKbGFiZWxlZApkZXYub2ZmKCkKbGFiZWxlZApgYGAKCiMjIERvdWJsZS1jaGVjayB0aGF0IGdlbmUgY291bnRzIG1hdGNoIG15IHBlcmNlcHRpb25zCgpDaGVjayB0aGF0IG15IHBlcmNlcHRpb24gb2YgdGhlIG51bWJlciBvZiBzaWduaWZpY2FudCB1cC9kb3duIGdlbmVzCm1hdGNoZXMgd2hhdCB0aGUgdGFibGUvdmVubiBzYXlzLiAgSW4gdGhlIGZvbGxvd2luZyBibG9jayBJIGFtCnBlcmZvcm1pbmcgc29tZSB2ZW5uL3Vwc2V0IGFuYWx5c2VzIHRvIHNlZSBpZiB0aGUgbnVtYmVycyBvZiBnZW5lcwptYXRjaCB3aGF0IHdlIGhhdmUgaW4gdGhlIGN1cnJlbnQgdmVyc2lvbiBvZiB0aGUgbWFudXNjcmlwdCAocGx1cyBvcgptaW51cyBhIGdlbmUpIGFuZCB0aHVzIGlmIG15IGludGVycHJldGF0aW9uIG9mIHRoZSBmaWd1cmUvbGVnZW5kIHRleHQKbWF0Y2hlcyB3aGF0IEkgdGhpbmsgaXQgbWVhbnMuCgpgYGB7cn0Kc2hhcmVkIDwtIFZlbm5lcmFibGU6OlZlbm4obGlzdCgKICAiZHJ1ZyIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIzc2JfdnNfdW5pbmYiXV0pLAogICJub2RydWciID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM25vc2JfdnNfdW5pbmYiXV0pKSkKcHAoZmlsZSA9ICJpbWFnZXMvejIzX3ZzX3VuaW5mX3Zlbm5fdXAucG5nIikKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmRldi5vZmYoKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKIyMgSSBzZWUgOTEwIHoyM3NiL3VuaW5mIGFuZCA2NzAgbm8gejIzbm9zYi91bmluZiBnZW5lcyBpbiB0aGUgdmVubiBkaWFncmFtLgpsZW5ndGgoc2hhcmVkQEludGVyc2VjdGlvblNldHNbWyIxMCJdXSkgKyBsZW5ndGgoc2hhcmVkQEludGVyc2VjdGlvblNldHNbWyIxMSJdXSkKZGltKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjNzYl92c191bmluZiJdXSkKCnNoYXJlZCA8LSBWZW5uZXJhYmxlOjpWZW5uKGxpc3QoCiAgImRydWciID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyMnNiX3ZzX3VuaW5mIl1dKSwKICAibm9kcnVnIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjJub3NiX3ZzX3VuaW5mIl1dKSkpCnBwKGZpbGUgPSAiaW1hZ2VzL3oyMl92c191bmluZl92ZW5uX3VwLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCgpsZW5ndGgoc2hhcmVkQEludGVyc2VjdGlvblNldHNbWyIxMCJdXSkgKyBsZW5ndGgoc2hhcmVkQEludGVyc2VjdGlvblNldHNbWyIxMSJdXSkKZGltKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjJzYl92c191bmluZiJdXSkKYGBgCgoqTm90ZSB0byBzZWxmKjogVGhlcmUgaXMgYW4gZXJyb3IgaW4gbXkgdm9sY2FubyBwbG90IGNvZGUgd2hpY2ggdGFrZXMKZWZmZWN0IHdoZW4gdGhlIG51bWVyYXRvciBhbmQgZGVub21pbmF0b3Igb2YgdGhlIGFsbF9wYWlyd2lzZQpjb250cmFzdHMgYXJlIGRpZmZlcmVudCB0aGFuIHRob3NlIGluIGNvbWJpbmVfZGVfdGFibGVzLiAgSXQgaXMKcHV0dGluZyB0aGUgdXBzL2Rvd25zIG9uIHRoZSBjb3JyZWN0IHNpZGVzIG9mIHRoZSBwbG90LCBidXQgY2FsbGluZwp0aGUgZG93biBnZW5lcyAndXAnIGFuZCB2aWNlLXZlcnNhLiAgVGhlIHJlYXNvbiBmb3IgdGhpcyBpcyB0aGF0IEkgZGlkCmEgY2hlY2sgZm9yIHRoaXMgaGFwcGVuaW5nLCBidXQgdXNlZCB0aGUgd3JvbmcgYXJndW1lbnQgdG8gaGFuZGxlIGl0LgoKQSBsaWtlbHkgYml0IG9mIHRleHQgZm9yIHRoZXNlIHZvbGNhbm8gcGxvdHM6CgpUaGUgc2V0IG9mIGdlbmVzIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBiZXR3ZWVuIHRoZSB6eW1vZGVtZSAyLjMKYW5kIHVuaW5mZWN0ZWQgc2FtcGxlcyB3aXRob3V0IGRydWdlIHRyZWF0bWVudCB3YXMgcXVhbnRpZmllZCB3aXRoCkRFU2VxMiBhbmQgaW5jbHVkZWQgc3Vycm9nYXRlIGVzdGltYXRlcyBmcm9tIFNWQS4gIEdpdmVuIHRoZSBjcml0ZXJpYQpvZiBzaWduaWZpY2FuY2Ugb2YgYSBhYnMobG9nRkMpID49IDEuMCBhbmQgZmFsc2UgZGlzY292ZXJ5IHJhdGUKYWRqdXN0ZWQgcC12YWx1ZSA8PSAwLjA1LCA2NzAgZ2VuZXMgd2VyZSBvYnNlcnZlZCBhcyBzaWduaWZpY2FudGx5CmluY3JlYXNlZCBiZXR3ZWVuIHRoZSBpbmZlY3RlZCBhbmQgdW5pbmZlY3RlZCBzYW1wbGVzIGFuZCAzODYgd2VyZQpvYnNlcnZlZCBhcyBkZWNyZWFzZWQuIFRoZSBtb3N0IGluY3JlYXNlZCBnZW5lcyBmcm9tIHRoZSB1bmluZmVjdGVkCnNhbXBsZXMgaW5jbHVkZSBzb21lIHdoaWNoIGFyZSBwb3RlbnRpYWxseSBpbmRpY2F0aXZlIG9mIGEgc3Ryb25nCmlubmF0ZSBpbW11bmUgcmVzcG9uc2UgYW5kIHRoZSBpbmZsYW1tYXRvcnkgcmVzcG9uc2UuCgpJbiBjb250cmFzdCwgd2hlbiB0aGUgc2V0IG9mIGdlbmVzIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBiZXR3ZWVuCnRoZSB6eW1vZGVtZSAyLjIgYW5kIHVuaW5mZWN0ZWQgc2FtcGxlcyB3YXMgdmlzdWFsaXplZCwgb25seSA3IGdlbmVzCndlcmUgb2JzZXJ2ZWQgYXMgZGVjcmVhc2VkIGFuZCA0MzUgaW5jcmVhc2VkLiAgVGhlIGluZmxhbW1hdG9yeQpyZXNwb25zZSB3YXMgc2lnbmlmaWNhbnRseSBsZXNzIGFwcGFyZW50IGluIHRoaXMgc2V0LCBidXQgaW5zdGVhZAppbmNsdWRlZCBnZW5lcyByZWxhdGVkIHRvIHRyYW5zcG9ydGVyIGFjdGl2aXR5IGFuZCBveGlkb3JlZHVjdGFzZXMuCgojIyBEaXJlY3Qgenltb2RlbWUgY29tcGFyaXNvbnMKCkFuIG9ydGhvZ29uYWwgY29tcGFyaXNvbiB0byB0aGF0IHBlcmZvcm1lZCBhYm92ZSBpcyB0byBkaXJlY3RseQpjb21wYXJlIHRoZSB6eW1vZGVtZSAyLjMgYW5kIDIuMiBzYW1wbGVzIHdpdGggYW5kIHdpdGhvdXQgYW50aW1vbmlhbAp0cmVhdG1lbnQuCgojIyMgWjIuMyAvIHoyLjIgd2l0aG91dCBkcnVnCgpgYGB7cn0KejIzbm9zYl92c196MjJub3NiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2RlKAogIHRhYmxlID0gaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNub3NiX3ZzX3oyMm5vc2IiXV0sCiAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgc2hhcGVzX2J5X3N0YXRlID0gRkFMU0UsIGNvbG9yX2J5ID0gImZjIiwgIGxhYmVsID0gMTAsIGxhYmVsX2NvbHVtbiA9ICJoZ25jX3N5bWJvbCIpCnBsb3RseTo6Z2dwbG90bHkoejIzbm9zYl92c196MjJub3NiX3ZvbGNhbm9bWyJwbG90Il1dKQoKejIzc2JfdnNfejIyc2Jfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fZGUoCiAgdGFibGUgPSBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyM3NiX3ZzX3oyMnNiIl1dLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY19zeW1ib2wiKQpwbG90bHk6OmdncGxvdGx5KHoyM3NiX3ZzX3oyMnNiX3ZvbGNhbm9bWyJwbG90Il1dKQpgYGAKCmBgYHtyfQp6MjNub3NiX3ZzX3oyMm5vc2Jfdm9sY2Fub1tbInBsb3QiXV0gKwogIHhsaW0oLTEwLCAxMCkgKwogIHlsaW0oMCwgNjApCgpwcChmaWxlID0gImltYWdlcy96MjNub3NiX3ZzX3oyMm5vc2JfcmVhY3RvbWVfdXAuc3ZnIiwKICAgaW1hZ2UgPSBhbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dLAogICBoZWlnaHQgPSAxMiwgd2lkdGggPSA5KQphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siS0VHRyJdXQojIyBLRUdHLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIldQIl1dCiMjIFdpa2lQYXRod2F5cywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl91cCJdXVtbImludGVyYWN0aXZlX3Bsb3RzIl1dW1siV1AiXV0KCnBwKGZpbGUgPSAiaW1hZ2VzL3oyM25vc2JfdnNfejIybm9zYl9yZWFjdG9tZV9kb3duLnN2ZyIsCiAgIGltYWdlID0gYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dLAogICBoZWlnaHQgPSAxMiwgd2lkdGggPSA5KQphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmBgYAoKIyMjIHoyLjMgLyB6Mi4yIHdpdGggZHJ1ZwoKYGBge3J9CnoyM3NiX3ZzX3oyMnNiX3ZvbGNhbm9bWyJwbG90Il1dICsKICB4bGltKC0xMCwgMTApICsKICB5bGltKDAsIDYwKQoKcHAoCiAgZmlsZSA9ICJpbWFnZXMvejIzc2JfdnNfejIyc2JfcmVhY3RvbWVfdXAucG5nIiwKICBpbWFnZSA9IGFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXSwKICBoZWlnaHQgPSAxMiwgd2lkdGggPSA5KQphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIktFR0ciXV0KIyMgS0VHRywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIyc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJXUCJdXQojIyBXaWtpUGF0aHdheXMsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl91cCJdXVtbImludGVyYWN0aXZlX3Bsb3RzIl1dW1siV1AiXV0KCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYGBgCgojIyMgVmVubiB0byBzZWUgc2hhcmVkL3VuaXF1ZSBnZW5lcwoKT25jZSBhZ2FpbiBJIHdpc2ggdG8gcHVsbCBvdXQgdGhlIHNpZ25pZmljYW50IGdlbmVzIGFuZCBzZWUgaG93IG15Cm51bWJlcnMgbWF0Y2ggYWdhaW5zdCB0aGUgdGV4dC4KCmBgYHtyfQpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KAogICJkcnVnIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjNzYl92c196MjJzYiJdXSksCiAgIm5vZHJ1ZyIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dKSkpCnBwKGZpbGUgPSAiaW1hZ2VzL2RydWdfbm9kcnVnX3Zlbm5fdXAucG5nIikKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmRldi5vZmYoKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKCnNoYXJlZCA8LSBWZW5uZXJhYmxlOjpWZW5uKAogIGxpc3QoImRydWciID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1siejIzc2JfdnNfejIyc2IiXV0pLAogICAgICAgIm5vZHJ1ZyIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJ6MjNub3NiX3ZzX3oyMm5vc2IiXV0pKSkKcHAoZmlsZSA9ICJpbWFnZXMvZHJ1Z19ub2RydWdfdmVubl9kb3duLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmBgYAoKQSBzbGlnaHRseSBkaWZmZXJlbnQgd2F5IG9mIGxvb2tpbmcgYXQgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIHR3bwp6eW1vZGVtZSBpbmZlY3Rpb25zIGlzIHRvIGRpcmVjdGx5IGNvbXBhcmUgdGhlIGluZmVjdGVkIHNhbXBsZXMgd2l0aAphbmQgd2l0aG91dCBkcnVnLiAgVGh1cywgd2hlbiBhIHZvbGNhbm8gcGxvdCBzaG93aW5nIHRoZSBjb21wYXJpc29uIG9mCnRoZSB6eW1vZGVtZSAyLjMgdnMuIDIuMiBzYW1wbGVzIHdhcyBwbG90dGVkLCA0ODQgZ2VuZXMgd2VyZSBvYnNlcnZlZAphcyBpbmNyZWFzZWQgYW5kIDQyMiBkZWNyZWFzZWQ7IHRoZXNlIGdyb3VwcyBpbmNsdWRlIG1hbnkgb2YgdGhlIHNhbWUKaW5mbGFtbWF0b3J5ICh1cCkgYW5kIG1lbWJyYW5lIChkb3duKSBnZW5lcy4KClNpbWlsYXIgcGF0dGVybnMgd2VyZSBvYnNlcnZlZCB3aGVuIHRoZSBhbnRpbW9uaWFsIHdhcyBpbmNsdWRlZC4KVGh1cywgd2hlbiBhIFZlbm4gZGlhZ3JhbSBvZiB0aGUgdHdvIHNldHMgb2YgaW5jcmVhc2VkIGdlbmVzIHdhcwpwbG90dGVkLCBhIHNpZ25pZmljYW50IG51bWJlciBvZiB0aGUgZ2VuZXMgd2FzIG9ic2VydmVkIGFzIGluY3JlYXNlZAooMzEzKSBhbmQgZGVjcmVhc2VkICgyNDQpIGluIGJvdGggdGhlIHVudHJlYXRlZCBhbmQgYW50aW1vbmlhbCB0cmVhdGVkCnNhbXBsZXMuCgojIyBEcnVnIGVmZmVjdHMgb24gZWFjaCB6eW1vZGVtZSBpbmZlY3Rpb24KCkFub3RoZXIgbGlrZWx5IHF1ZXN0aW9uIGlzIHRvIGRpcmVjdGx5IGNvbXBhcmUgdGhlIHRyZWF0ZWQgdnMKdW50cmVhdGVkIHNhbXBsZXMgZm9yIGVhY2ggenltb2RlbWUgaW5mZWN0aW9uIGluIG9yZGVyIHRvIHZpc3VhbGl6ZQp0aGUgZWZmZWN0cyBvZiBhbnRpbW9uaWFsLgoKIyMjIHoyLjMgd2l0aCBhbmQgd2l0aG91dCBkcnVnCgpgYGB7cn0KejIzc2JfdnNfejIzbm9zYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19kZSgKICB0YWJsZSA9IGhzX21hY3JfdGFibGVbWyJkYXRhIl1dW1siejIzc2JfdnNfejIzbm9zYiJdXSwKICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICBzaGFwZXNfYnlfc3RhdGUgPSBGQUxTRSwgY29sb3JfYnkgPSAiZmMiLCAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNfc3ltYm9sIikKcGxvdGx5OjpnZ3Bsb3RseSh6MjNzYl92c196MjNub3NiX3ZvbGNhbm9bWyJwbG90Il1dKQp6MjJzYl92c196MjJub3NiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2RlKAogIHRhYmxlID0gaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjJzYl92c196MjJub3NiIl1dLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY19zeW1ib2wiKQpwbG90bHk6OmdncGxvdGx5KHoyMnNiX3ZzX3oyMm5vc2Jfdm9sY2Fub1tbInBsb3QiXV0pCmBgYAoKYGBge3J9CnoyM3NiX3ZzX3oyM25vc2Jfdm9sY2Fub1tbInBsb3QiXV0gKwogIHhsaW0oLTgsIDgpICsKICB5bGltKDAsIDIxMCkKCnBwKGZpbGUgPSAiaW1hZ2VzL3oyM3NiX3ZzX3oyM25vc2JfcmVhY3RvbWVfdXAucG5nIiwKICAgaW1hZ2UgPSBhbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXSwKICAgaGVpZ2h0ID0gMTIsIHdpZHRoID0gOSkKYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siS0VHRyJdXQojIyBLRUdHLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIldQIl1dCiMjIFdpa2lQYXRod2F5cywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyM25vc2JfdXAiXV1bWyJpbnRlcmFjdGl2ZV9wbG90cyJdXVtbIldQIl1dCgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmBgYAoKIyMjIHoyLjIgd2l0aCBhbmQgd2l0aG91dCBkcnVnCgpgYGB7cn0KejIyc2JfdnNfejIybm9zYl92b2xjYW5vW1sicGxvdCJdXSArCiAgeGxpbSgtOCwgOCkgKwogIHlsaW0oMCwgMjEwKQoKcHAoZmlsZSA9ICJpbWFnZXMvejIyc2JfdnNfejIybm9zYl9yZWFjdG9tZV91cC5wbmciLAogICBpbWFnZSA9IGFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dLAogICBoZWlnaHQgPSAxMiwgd2lkdGggPSA5KQphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJLRUdHIl1dCiMjIEtFR0csIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KIyMgV2lraVBhdGh3YXlzLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl91cCJdXVtbImludGVyYWN0aXZlX3Bsb3RzIl1dW1siV1AiXV0KCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYGBgCgojIyMgU2hhcmVkIGFuZCB1bmlxdWUgZ2VuZXMgYWZ0ZXIvYmVmb3JlIGRydWcKCmBgYHtyfQpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KAogICJ6MjMiID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM3NiX3ZzX3oyM25vc2IiXV0pLAogICJ6MjIiID0gcm93bmFtZXMoaHNfbWFjcl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyMnNiX3ZzX3oyMm5vc2IiXV0pKSkKcHAoZmlsZSA9ICJpbWFnZXMvejIzX3oyMl9kcnVnX3Zlbm5fdXAucG5nIikKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmRldi5vZmYoKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKCnNoYXJlZCA8LSBWZW5uZXJhYmxlOjpWZW5uKGxpc3QoCiAgInoyMyIgPSByb3duYW1lcyhoc19tYWNyX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJ6MjNzYl92c196MjNub3NiIl1dKSwKICAiejIyIiA9IHJvd25hbWVzKGhzX21hY3Jfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyMnNiX3ZzX3oyMm5vc2IiXV0pKSkKcHAoZmlsZSA9ICJpbWFnZXMvejIzX3oyMl9kcnVnX3Zlbm5fZG93bi5wbmciKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKZGV2Lm9mZigpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpgYGAKCk5vdGU6IEkgYW0gc2V0dGlnIHRoZSB4IGFuZCB5LWF4aXMgYm91bmRhcmllcyBieSBhbGxvd2luZyB0aGUgcGxvdHRlcgp0byBwaWNrIGl0cyBvd24gYXhpcyB0aGUgZmlyc3QgdGltZSwgd3JpdGluZyBkb3duIHRoZSByYW5nZXMgSQpvYnNlcnZlLCBhbmQgdGhlbiBzZXR0aW5nIHRoZW0gdG8gdGhlIGxhcmdlc3Qgb2YgdGhlIHBhaXIuICBJdCBpcwp0aGVyZWZvcmUgcG9zc2libGUgdGhhdCBJIG1pc3NlZCBvbmUgb3IgbW9yZSBnZW5lcyB3aGljaCBsaWVzIG91dHNpZGUKdGhhdCByYW5nZS4KClRoZSBwcmV2aW91cyBwbG90dGVkIGNvbnRyYXN0cyBzb3VnaHQgdG8gc2hvdyBjaGFuZ2VzIGJldHdlZW4gdGhlIHR3bwpzdHJhaW5zIHoyLjMgYW5kIHoyLjIuICBDb252ZXJzZWx5LCB0aGUgcHJldmlvdXMgdm9sY2FubyBwbG90cyBzZWVrIHRvCmRpcmVjdGx5IGNvbXBhcmUgZWFjaCBzdHJhaW4gYmVmb3JlL2FmdGVyIGRydWcgdHJlYXRtZW50LgoKIyBMUlQgb2YgdGhlIEh1bWFuIE1hY3JvcGhhZ2UKCkEgc2xpZ2h0bHkgZGlmZmVyZW50IHRhY2sgdG8gZXhhbWluZSB0aGUgZGF0YSBpcyB0byBwZXJmb3JtIGEKbGlrZWxpaG9vZCByYXRpbyB0ZXN0IGluIG9yZGVyIHRvIGxvb2sgZm9yIHRyZW5kcyB3aGljaCBhcmUgc2hhcmVkCmFtb25nIGdlbmVzIHdoZW4gZXhhbWluaW5nIGRpZmZlcmVudCBjb25kaXRpb25zIGluIHRoZSBkYXRhLgoKYGBge3J9CnRtcmMyX2xydF9zdHJhaW5fZHJ1ZyA8LSBkZXNlcV9scnQoaHNfbWFjciwgaW50ZXJhY3Rvcl9jb2x1bW4gPSAiZHJ1ZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJlc3RfY29sdW1uID0gIm1hY3JvcGhhZ2V6eW1vZGVtZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjdG9ycyA9IGMoImRydWciLCAibWFjcm9waGFnZXp5bW9kZW1lIikpCnRtcmMyX2xydF9zdHJhaW5fZHJ1Z1tbImNsdXN0ZXJfZGF0YSJdXVtbInBsb3QiXV0KYGBgCgojIFBhcmFzaXRlCgpMZXQgdXMgY29uc2lkZXIgZm9yIGEgbW9tZW50IGRpZmZlcmVuY2VzIGFtb25nIHRoZSBwYXJhc2l0ZQp0cmFuc2NyaXB0b21lcyBmb3IgdGhlIHNhbXBsZXMgd2hpY2ggd2VyZSBub3QgZHJ1ZyB0cmVhdGVkLgoKT25lIHRoaW5nIEkgZGlkIGluIHRoZSBpbml0aWFsIGltcGxlbWVudGF0aW9uIG9mIHRoaXMgZG9jdW1lbnQgd2FzIHRvCnJlcGVhdCB0aGUgdmFyaWFibGUgJ3VwX2dlbmVzJyBmb3IgZWFjaCBjb21wYXJpc29uOyBJIHRoaW5rIHRoaXMgdGltZQpJIHdpbGwgbWFrZSBhIGRpZmZlcmVudCB2YXJpYWJsZSBmb3IgZWFjaCBjb21wYXJpc29uIHNvIEkgY2FuIHBsYXkKd2l0aCB0aGVtIGEgbGl0dGxlIGZ1cnRoZXIuCgpgYGB7cn0KY29tcGFyaXNvbiA8LSAiejIzX3ZzX3oyMiIKbHBfbWFjcm9waGFnZV9kZSA8LSBhbGxfcGFpcndpc2UobHBfbWFjcm9waGFnZV9ub3NiLCBtb2RlbF9zdnMgPSAic3Zhc2VxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfZnN0cmluZyA9ICJ+IDAgKyBjb25kaXRpb24iLCBmaWx0ZXIgPSBUUlVFKQp0bXJjMl9wYXJhc2l0ZV9rZWVwZXJzIDwtIGxpc3QoCiAgInoyM192c196MjIiID0gYygiejIzIiwgInoyMiIpKQpscF9tYWNyb3BoYWdlX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGxwX21hY3JvcGhhZ2VfZGUsIGtlZXBlcnMgPSB0bXJjMl9wYXJhc2l0ZV9rZWVwZXJzLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9kZV90YWJsZXMvcGFyYXNpdGVfaW5mZWN0aW9uX2RlLXZ7dmVyfS54bHN4IikpCmxwX21hY3JvcGhhZ2Vfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgbHBfbWFjcm9waGFnZV90YWJsZSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvc2lnX3RhYmxlcy9wYXJhc2l0ZV9zaWctdnt2ZXJ9Lnhsc3giKSkKCmxwX21hY3JvcGhhZ2VfdGFibGVbWyJwbG90cyJdXVtbY29tcGFyaXNvbl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dCmxwX21hY3JvcGhhZ2VfdGFibGVbWyJwbG90cyJdXVtbY29tcGFyaXNvbl1dW1siZGVzZXFfbWFfcGxvdHMiXV0KCnVwX2dlbmVzX3oyM3oyMiA8LSBscF9tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1tjb21wYXJpc29uXV0KZGltKHVwX2dlbmVzX3oyM3oyMikKZG93bl9nZW5lc196MjN6MjIgPC0gbHBfbWFjcm9waGFnZV9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1tjb21wYXJpc29uXV0KZGltKGRvd25fZ2VuZXNfejIzejIyKQpgYGAKCmBgYHtyIHBhcmFzaXRlX3ZvbGNhbm99CmxwX3oyM3NiX3ZzX3oyMnNiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2RlKAogIHRhYmxlID0gbHBfbWFjcm9waGFnZV90YWJsZVtbImRhdGEiXV1bWyJ6MjNfdnNfejIyIl1dLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLAogIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY19zeW1ib2wiKQpwbG90bHk6OmdncGxvdGx5KGxwX3oyM3NiX3ZzX3oyMnNiX3ZvbGNhbm9bWyJwbG90Il1dKQpscF96MjNzYl92c196MjJzYl92b2xjYW5vW1sicGxvdCJdXQpgYGAKCiMjIE9udG9sb2d5IHNlYXJjaAoKQW4gaW1wb3J0YW50IG5vdGUsIEkgcmVjZW50bHkgYWRkZWQgYSBtaW5pbXVtIGNyb3NzcmVmZXJlbmNlIGFyZ3VtZW50CihkZWZhdWx0aW5nIHRvIDQwIGdlbmVzKSwgd2hpY2ggY2F1c2VzIGxvdHMgb2YgY29tcGFyaXNvbnMgdG8gZmFpbCBmb3IKcG9vcmx5IGFubm90YXRlZCBnZW5vbWVzIChsaWtlIHBhbmFtZW5zaXMuKSAgVGh1cywgSSBhbSByZWxheGluZyB0aGF0CmNvbnN0cmFpbnQgZm9yIHRoZXNlIHNlYXJjaGVzLgoKYGBge3J9CmxwX2xlbmd0aHMgPC0gYWxsX2xwX2Fubm90WywgYygiZ2lkIiwgImFubm90X2Nkc19sZW5ndGgiKV0KY29sbmFtZXMobHBfbGVuZ3RocykgIDwtIGMoIklEIiwgImxlbmd0aCIpCgp1cF9nb3NlcSA8LSBzaW1wbGVfZ29zZXEodXBfZ2VuZXNfejIzejIyLCBnb19kYiA9IGxwX2dvLAogICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoX2RiID0gbHBfbGVuZ3RocywgbWluX3hyZWYgPSAxNSkKIyMgVmlldyBjYXRlZ29yaWVzIG92ZXIgcmVwcmVzZW50ZWQgaW4gdGhlIDIuMyBzYW1wbGVzCnVwX2dvc2VxW1sicHZhbHVlX3Bsb3RzIl1dW1siYnBwX3Bsb3Rfb3ZlciJdXQpkb3duX2dvc2VxIDwtIHNpbXBsZV9nb3NlcShkb3duX2dlbmVzX3oyM3oyMiwgZ29fZGIgPSBscF9nbywKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoX2RiID0gbHBfbGVuZ3RocywgbWluX3hyZWYgPSAxNSkKIyMgVmlldyBjYXRlZ29yaWVzIG92ZXIgcmVwcmVzZW50ZWQgaW4gdGhlIDIuMiBzYW1wbGVzCmRvd25fZ29zZXFbWyJwdmFsdWVfcGxvdHMiXV1bWyJicHBfcGxvdF9vdmVyIl1dCgpjcmVhdGVkIDwtIGRpci5jcmVhdGUoZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9nb3NlcV9wYXJhc2l0ZSIpKQp3cml0dGVuX2dvc2VxIDwtIHdyaXRlX2dvc2VxX2RhdGEoCiAgdXBfZ29zZXEsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2dvc2VxX3BhcmFzaXRlL2xwX21hY3JvcGhhZ2VfaW5jcmVhc2VkX3oyLjNfZ29zZXEtdnt2ZXJ9Lnhsc3giKSkKd3JpdHRlbl9nb3NlcSA8LSB3cml0ZV9nb3NlcV9kYXRhKAogIGRvd25fZ29zZXEsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2dvc2VxX3BhcmFzaXRlL2xwX21hY3JvcGhhZ2VfaW5jcmVhc2VkX3oyLjJfZ29zZXEtdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIEdTVkEKCk5vdGU6IFRoZSBmb2xsb3dpbmcgYmxvY2sgYXNzdW1lcyBvbmUgaXMgYWJsZSB0byBkb3dubG9hZCBhIGZyZXNoIGNvcHkKb2YgbXNpZ0RCLCB3aGljaCBJIGFtIG5vdCBzdXJlIGlzIHBvc3NpYmxlIHdpdGhpbiB0aGUgY29uc3RyYWludHMgb2YgYQpjb250YWluZXIgKEkgbWVhbiBpdCBpcyB0cml2aWFsIHRvIGRvLCBidXQgSSBhbSBub3Qgc3VyZSBpZiBpdCBpcyBvawpkdWUgdG8gbGljZW5zaW5nKS4gIEhvd2V2ZXIsIEJyb2FkIHByb3ZpZGVzIGEgZGF0YSBwYWNrYWdlIG9mIGEgbXNpZ2RiCnJlbGVhc2UuICBBcyBhIHJlc3VsdCwgdGhlIGZvbGxvd2luZyBibG9jayB3aWxsIGJlIHJlcGVhdGVkIHVzaW5nIHRoYXQuCgpgYGB7ciwgZXZhbD1GQUxTRX0KaHNfaW5mZWN0ZWQgPC0gc3Vic2V0X3NlKGhzX21hY3JvcGhhZ2UsIHN1YnNldCA9ICJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmYnIikgJT4lCiAgc3Vic2V0X3NlKHN1YnNldCA9ICJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmZfc2InIikKaHNfZ3N2YV9jMiA8LSBzaW1wbGVfZ3N2YShoc19pbmZlY3RlZCkKaHNfZ3N2YV9jMl9tZXRhIDwtIGdldF9tc2lnZGJfbWV0YWRhdGEoaHNfZ3N2YV9jMiwgbXNpZ194bWwgPSAicmVmZXJlbmNlL21zaWdkYl92Ny4yLnhtbCIpCmhzX2dzdmFfYzJfc2lnIDwtIGdldF9zaWdfZ3N2YV9jYXRlZ29yaWVzKAogIGhzX2dzdmFfYzJfbWV0YSwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUvZ3N2YS9oc19tYWNyb3BoYWdlX2dzdmFfYzJfc2lnLnhsc3giKSkKaHNfZ3N2YV9jMl9zaWdbWyJyYXdfcGxvdCJdXQoKaHNfZ3N2YV9jNyA8LSBzaW1wbGVfZ3N2YShoc19pbmZlY3RlZCwgc2lnbmF0dXJlX2NhdGVnb3J5ID0gImM3IikKaHNfZ3N2YV9jN19tZXRhIDwtIGdldF9tc2lnZGJfbWV0YWRhdGEoaHNfZ3N2YV9jNywgbXNpZ194bWwgPSAicmVmZXJlbmNlL21zaWdkYl92Ny4yLnhtbCIpCmhzX2dzdmFfYzdfc2lnIDwtIGdldF9zaWdfZ3N2YV9jYXRlZ29yaWVzKAogIGhzX2dzdmFfYzcsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2dzdmEvaHNfbWFjcm9waGFnZV9nc3ZhX2M3X3NpZy54bHN4IikpCmhzX2dzdmFfYzdfc2lnW1sicmF3X3Bsb3QiXV0KYGBgCgojIyBSZXBlYXQgdXNpbmcgdGhlIEdTVkFkYXRhIHBhY2thZ2UuCgpgYGB7cn0KaHNfaW5mZWN0ZWQgPC0gc3Vic2V0X3NlKGhzX21hY3JvcGhhZ2UsIHN1YnNldCA9ICJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmYnIikgJT4lCiAgc3Vic2V0X3NlKHN1YnNldCA9ICJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmZfc2InIikKaHNfZ3N2YV9jMiA8LSBzaW1wbGVfZ3N2YShoc19pbmZlY3RlZCkKIyNoc19nc3ZhX2MyX21ldGEgPC0gZ2V0X21zaWdkYl9tZXRhZGF0YShoc19nc3ZhX2MyLCBtc2lnX3htbD0icmVmZXJlbmNlL21zaWdkYl92Ny4yLnhtbCIpCmhzX2dzdmFfYzJfc2lnIDwtIGdldF9zaWdfZ3N2YV9jYXRlZ29yaWVzKAogIGhzX2dzdmFfYzIsCiAgZXhjZWwgPSBnbHVlKCJhbmFseXNlcy9tYWNyb3BoYWdlX2RlL2dzdmEvaHNfbWFjcm9waGFnZV9nc3ZhX2MyX3NpZy54bHN4IikpCmhzX2dzdmFfYzJfc2lnW1sicmF3X3Bsb3QiXV0KCmhzX2dzdmFfYzcgPC0gc2ltcGxlX2dzdmEoaHNfaW5mZWN0ZWQsIHNpZ25hdHVyZV9jYXRlZ29yeSA9ICJjNyIpCiMjaHNfZ3N2YV9jN19tZXRhIDwtIGdldF9tc2lnZGJfbWV0YWRhdGEoaHNfZ3N2YV9jNywgbXNpZ194bWw9InJlZmVyZW5jZS9tc2lnZGJfdjcuMi54bWwiKQpoc19nc3ZhX2M3X3NpZyA8LSBnZXRfc2lnX2dzdmFfY2F0ZWdvcmllcygKICBoc19nc3ZhX2M3LAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS9nc3ZhL2hzX21hY3JvcGhhZ2VfZ3N2YV9jN19zaWcueGxzeCIpKQpoc19nc3ZhX2M3X3NpZ1tbInJhd19wbG90Il1dCmBgYAoKIyBUcnkgb3V0IGEgbmV3IHRvb2wKClR3byByZWFzb25zOiBOYWppYiBsb3ZlcyBoaW0gc29tZSBQQ0EsIHRoaXMgdXNlcyB3aWtpcGF0aHdheXMsIHdoaWNoIGlzIHNvbWV0aGluZyBJIHRoaW5rIGlzIG5lYXQuCgpPaywgSSBzcGVudCBzb21lIHRpbWUgbG9va2luZyB0aHJvdWdoIHRoZSBjb2RlIGFuZCBJIGhhdmUgc29tZQpwcm9ibGVtcyB3aXRoIHNvbWUgb2YgdGhlIGRlc2lnbiBkZWNpc2lvbnMuCgpNb3N0IGltcG9ydGFudGx5LCBpdCByZXF1aXJlcyBhIGRhdGEuZnJhbWUoKSB3aGljaCBoYXMgdGhlIGZvbGxvd2luZyBmb3JtYXQ6CgoxLiAgTm8gcm93bmFtZXMsIGluc3RlYWQgY29sdW1uICMxIGlzIHRoZSBzYW1wbGUgSUQuCjIuICBDb2x1bW5zIDItbSBhcmUgdGhlIGNhdGVnb3JpY2FsL3N1cnZpdmFsL2V0YyBtZXRyaWNzLgozLiAgQ29sdW1ucyBtLW4gYXJlIDEgZ2VuZS1wZXItY29sdW1uIHdpdGggbG9nMiB2YWx1ZXMuCgpCdXQgd2hlbiBJIHRoaW5rIGFib3V0IGl0IEkgdGhpbmsgSSBnZXQgdGhlIGlkZWEsIHRoZXkgd2FudCB0byBiZSBhYmxlIHRvIGRvIG1vZGVsbGluZyBzdHVmZgptb3JlIGVhc2lseSB3aXRoIHJlc3BvbnNlIGZhY3RvcnMuCgpgYGB7cn0KbGlicmFyeShwYXRod2F5UENBKQpsaWJyYXJ5KHJXaWtpUGF0aHdheXMpCgpkb3dubG9hZGVkIDwtIGRvd25sb2FkUGF0aHdheUFyY2hpdmUob3JnYW5pc20gPSAiSG9tbyBzYXBpZW5zIiwgZm9ybWF0ID0gImdtdCIpCmRhdGFfcGF0aCA8LSBzeXN0ZW0uZmlsZSgiZXh0ZGF0YSIsIHBhY2thZ2UgPSAicGF0aHdheVBDQSIpCndpa2lwYXRod2F5cyA8LSByZWFkX2dtdChwYXN0ZTAoZGF0YV9wYXRoLCAiL3dpa2lwYXRod2F5c19odW1hbl9zeW1ib2wuZ210IiksCiAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiA9IFRSVUUpCgpzZSA8LSBzdWJzZXRfc2UoaHNfbWFjcm9waGFnZSwgc3Vic2V0ID0gIm1hY3JvcGhhZ2V0cmVhdG1lbnQhPSd1bmluZiciKSAlPiUKICBzdWJzZXRfc2Uoc3Vic2V0ID0gIm1hY3JvcGhhZ2V0cmVhdG1lbnQhPSd1bmluZl9zYiciKQpzZSA8LSBzZXRfY29uZGl0aW9ucyhzZSwgZmFjdCA9ICJtYWNyb3BoYWdlenltb2RlbWUiKQpzeW1ib2xfY29sdW1uIDwtICJoZ25jX3N5bWJvbCIKc3ltYm9sX3ZlY3RvciA8LSByb3dEYXRhKHNlKVtbc3ltYm9sX2NvbHVtbl1dCm5hbWVzKHN5bWJvbF92ZWN0b3IpIDwtIHJvd25hbWVzKHJvd0RhdGEoc2UpKQpzeW1ib2xfZGYgPC0gYXMuZGF0YS5mcmFtZShzeW1ib2xfdmVjdG9yKQoKYXNzYXlfZGYgPC0gbWVyZ2Uoc3ltYm9sX2RmLCBhcy5kYXRhLmZyYW1lKGFzc2F5KHNlKSksIGJ5ID0gInJvdy5uYW1lcyIpCmFzc2F5X2RmW1siUm93Lm5hbWVzIl1dIDwtIE5VTEwKcm93bmFtZXMoYXNzYXlfZGYpIDwtIG1ha2UubmFtZXMoYXNzYXlfZGZbWyJzeW1ib2xfdmVjdG9yIl1dLCB1bmlxdWUgPSBUUlVFKQphc3NheV9kZltbInN5bWJvbF92ZWN0b3IiXV0gPC0gTlVMTAphc3NheV9kZiA8LSBhcy5kYXRhLmZyYW1lKHQoYXNzYXlfZGYpKQphc3NheV9kZltbIlNhbXBsZUlEIl1dIDwtIHJvd25hbWVzKGFzc2F5X2RmKQphc3NheV9kZiA8LSBkcGx5cjo6c2VsZWN0KGFzc2F5X2RmLCAiU2FtcGxlSUQiLCBldmVyeXRoaW5nKCkpCgpmYWN0b3JfZGYgPC0gYXMuZGF0YS5mcmFtZShjb2xEYXRhKHNlKSkKZmFjdG9yX2RmW1siU2FtcGxlSUQiXV0gPC0gcm93bmFtZXMoZmFjdG9yX2RmKQpmYWN0b3JfZGYgPC0gZHBseXI6OnNlbGVjdChmYWN0b3JfZGYsICJTYW1wbGVJRCIsIGV2ZXJ5dGhpbmcoKSkKZmFjdG9yX2RmIDwtIGZhY3Rvcl9kZlssIGMoIlNhbXBsZUlEIiwgZmFjdG9ycyldCgp0dCA8LSBDcmVhdGVPbWljcygKICBhc3NheURhdGFfZGYgPSBhc3NheV9kZiwKICBwYXRod2F5Q29sbGVjdGlvbl9scyA9IHdpa2lwYXRod2F5cywKICByZXNwb25zZSA9IGZhY3Rvcl9kZiwKICByZXNwVHlwZSA9ICJjYXRlZ29yaWNhbCIsCiAgbWluUGF0aFNpemUgPSA1KQoKc3VwZXIgPC0gQUVTUENBX3BWYWxzKAogIG9iamVjdCA9IHR0LAogIG51bVBDcyA9IDIsCiAgcGFyYWxsZWwgPSBGQUxTRSwKICBudW1Db3JlcyA9IDgsCiAgbnVtUmVwcyA9IDIsCiAgYWRqdXN0bWVudCA9ICJCSCIpCmBgYAoKIyBFdmFsdWF0aW5nIGEgbG9nMkZDIGJhcnBsb3QKCkZpZ3VyZSAyRSBpcyBub3cgY29tcHJpc2VkIG9mIGEgcGxvdCB3aGljaCBzaG93cyBsb2cyRkMgdmFsdWVzIHdpdGgKZXJyb3IgYmFycyBmb3Igc2VsZWN0ZWQgZ2VuZXMgYW5kIHNlZWtzIHRvIHNob3cgZGlmZmVyZW5jZXMgYmV0d2VlbgoyLjMvdW5pbmZlY3RlZCBhbmQgMi4yL3VuaW5mZWN0ZWQuCgpIZXJlIGlzIHRoZSB0YWJsZSBPbGdhIHVzZWQgdG8gZ2VuZXJhdGUgaXQ6CgpJIHdlbnQgbG9va2luZyBpbiB0aGUgeGxzeCBmaWxlcyBwcm9kdWNlZCBpbiAyMDI0MDUgYW5kIGZvdW5kIHRoYXQKdGhlc2UgYXJlIHRoZSBsb2cyRkMgdmFsdWVzIGFuZCBzdGFuZGFyZCBlcnJvcnMgcHJvZHVjZWQgYnkgREVTZXEyLgoKSXQgc2hvdWxkIGJlIG5vdGVkIHRoYXQgaW4gbXkgbW9zdCByZWNlbnQgdmVyc2lvbiBvZiB0aGVzZSBhbmFseXNlcywKdGhlc2UgbnVtYmVycyBkaWQgc2hpZnQgc2xpZ2h0bHkuICBJIGFtIGxvb2tpbmcgaW50byB0aGF0IG5vdy4KCiogRGF0YSB3aXRvdXQgZHJ1ZwoKKiogMi4zIHZzIFVuaW5mZWN0ZWQgTcOYICAgICAgICAgICAgMi4yIHZzIFVuaW5mZWN0ZWQgTcOYCgp8IEdlbmUgfCBNZWFuICAgfCBTRU0gICAgICB8IG4gfCBNZWFuICB8IFNFTSAgICAgfG4gfAotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCnxJRkkyNyB8ICA3LjIyNCB8ICAwLjU2NjIgIHw2ICB8IDIuNzAyIHwgIDAuNTY2OSB8IDZ8CnxSU0FEMiB8ICA2LjI5ICB8ICAwLjczMTIgIHw2ICB8IDEuNjIzIHwgIDAuNzMwMyB8IDZ8CnxDQ0w4ICB8ICA2LjIyNSB8ICAwLjkyOCAgIHw2ICB8IC0wLjMxNHwgIDAuOTQxICB8IDZ8CnxJRkk0NEx8ICA1Ljg5NSB8ICAwLjYxMiAgIHw2ICB8IDIuMDYgIHwgIDAuNjExICB8IDZ8CnxPQVNMICB8ICA0LjcyNiB8ICAwLjQ5NzQgIHw2ICB8IDEuMzkyIHwgIDAuNDk3MyB8IDZ8CnxVU1AxOCB8ICAzLjY0NCB8ICAwLjQ4MyAgIHw2ICB8IDAuOTk5IHwgIDAuNDgyNiB8IDZ8CnxJRE8xICB8ICA3LjE0NSB8ICAxLjEwNyAgIHw2ICB8IDEuMjU3IHwgIDEuMTQxICB8IDZ8CnxJRE8yICB8ICAzLjkzNSB8ICAxLjMgICAgIHw2ICB8IDIuNTU3IHwgIDEuMzQxICB8IDZ8CnxLWU5VICB8ICAxLjA3ICB8ICAwLjIxODYgIHw2ICB8IDAuMDIwN3wgIDAuMjE4NCB8IDZ8CnxBSFIgICB8IDAuOTM4MiB8IDAuMjIzNiAgIHw2ICB8IDAuNTAzMnwgIDAuMjIzOSB8IDZ8CnxJTDRJMSB8ICAyLjU5MyB8ICAwLjQ2MjMgIHw2ICB8IDAuMDM5IHwgIDAuNDYxOCB8IDZ8CnxTT0QyICB8ICAyLjc2ICB8ICAwLjM0OSAgIHw2ICB8IDAuNDI0MXwgIDAuMzUyOCB8IDZ8CnxOT1RDSDF8ICAwLjc1NzJ8ICAwLjI3NSAgIHw2ICB8IDEuNDk1IHwgIDAuMjc0NCB8IDZ8CnxETEwxICB8ICAwLjgyNjh8ICAwLjUyODUgIHw2ICB8IDMuNDU1IHwgIDAuNTIyOCB8IDZ8CnxETEw0ICB8ICAxLjExNiB8ICAwLjczNyAgIHw2ICB8IDQuMjQzIHwgIDAuNzEgICB8IDZ8CnxIRVMxICB8IC0wLjAxODN8IDAuODU5OSAgIHw2ICB8IDYuNTM2IHwgIDAuNzk3MyB8IDZ8CnxIRVkxICB8ICAwLjU1MzN8IDAuNTc4OSAgIHw2ICB8IDQuMTgxIHwgIDAuNjI3MyB8IDZ8CgpPaywgSSB0aGluayBJIGZvdW5kIGEgcHJvYmxlbTogVGhlIE5PVENIMSB2YWx1ZSBpcyBhY3R1YWxseSB0aGUKYWRqdXN0ZWQgcC12YWx1ZS4KCiogVHJhbnNwb3J0ZXJzIHdpdGhvdXQgZHJ1ZwoKKiogMi4zIHZzIFVuaW5mZWN0ZWQgTcOYICAgICAgICAgICAgMi4yIHZzIFVuaW5mZWN0ZWQgTcOYCgp8IEdlbmUgfCBNZWFuICAgIHwgICBTRU0gIHwgbnwgIE1lYW4gICB8IFNFTSAgIHwgbnwKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQp8QUJDQjEgfCAgLTIuMzU0IHwgMC40NDIgIHwgNnwgICAtMC40MDZ8ICAwLjQzMXwgNnwKfEFCQ0c0IHwgIC0zLjcxNSB8IDAuNjQ4ICB8IDZ8ICAgLTAuNjUzfCAgMC42MzB8IDZ8CnxBQkNCNSB8ICAtMS4xOTIgfCAwLjM4MCAgfCA2fCAgIDEuMzUxIHwgIDAuMzYzfCA2fAp8QUJDQTkgfCAgMS44ODAgIHwgMC42NDggIHwgNnwgICAzLjQ0NCB8ICAwLjYzN3wgNnwKfEFCQ0MyIHwgIDAuNDU0ICB8IDAuMzIxICB8IDZ8ICAgMS44MTggfCAgMC4zMTR8IDZ8CnxBUVAyICB8ICAtMS4xOTEgfCAwLjUyOSAgfCA2fCAgIDAuNzQ1IHwgIDAuNTE0fCA2fAp8QVFQMyAgfCAgLTAuOTQwIHwgMC40MDIgIHwgNnwgICAwLjQzMSB8ICAwLjM5NXwgNnwKCiogVHJhbnNwb3J0ZXJzIHdpdGggZHJ1ZwoKKiogMi4zIHZzIFVuaW5mZWN0ZWQgTcOYICAgICAgICAgICAgMi4yIHZzIFVuaW5mZWN0ZWQgTcOYCgp8R2VuZSAgfCBNZWFuICAgfCAgICBTRU0gfCBufCBNZWFuICB8ICBTRU0gICB8IG4gfAotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KfEFCQ0IxIHwgIC0wLjY5N3wgIDAuMzQ5IHwgNnwgLTEuMjU1fCAgMC4zMzcgfCAgNnwKfEFCQ0c0IHwgIDEuMjMxIHwgIDAuNTAzIHwgNnwgMC41NDcgfCAgMC40ODQgfCAgNnwKfEFRUDIgIHwgIDAuODE2IHwgIDAuMzk5IHwgNnwgMC4wNDMgfCAgMC4zODcgfCAgNnwKfEFRUDMgIHwgIC0xLjI4NnwgIDAuMzIwIHwgNnwgLTEuNjEzfCAgMC4zMDkgfCAgNnwKfEFRUDggIHwgIDAuNjM0IHwgIDAuMzcwIHwgNnwgMC45NDMgfCAgMC4zNjUgfCAgNnwKCkxldCB1cyBub3cgc2VlIGlmIEkgY2FuIHJlY2FwaXR1bGF0ZSB0aGUgcGxvdC4uLgoKYGBge3J9Cm5vZHJ1Z19jb250cmFzdHMgPC0gYygiejIzbm9zYl92c191bmluZiIsICJ6MjJub3NiX3ZzX3VuaW5mIikKZ2VuZXNfbm9fZHJ1ZyA8LSBjKCJJRkkyNyIsICJSU0FEMiIsICJDQ0w4IiwgIklGSTQ0TCIsICJPQVNMIiwgIlVTUDE4IiwgIklETzEiLCAiSURPMiIsICJLWU5VIiwgIkFIUiIsICJJTDRJMSIsICJTT0QyIiwgIk5PVENIMSIsICJETEwxIiwgIkRMTDQiLCAiSEVTMSIsICJIRVkxIikKdHJhbnNwb3J0ZXJzX25vX2RydWcgPC0gYygiQUJDQjEiLCAiQUJDRzQiLCAiQUJDQjUiLCAiQUJDQTkiLCAiQUJDQzIiLCAiQVFQMiIsICJBUVAzIikKZHJ1Z19jb250cmFzdHMgPC0gYygiejIzc2JfdnNfc2IiLCAiejIyc2JfdnNfc2IiKQp0cmFuc3BvcnRlcnNfZHJ1ZyA8LSBjKCJBQkNCMSIsICJBQkNHNCIsICJBUVAyIiwgIkFRUDMiLCAiQVFQOCIpCmBgYAoKVGhlc2UgdmFsdWVzIGNhbWUgb3V0IG9mIHRoZSBkYXRhIHN0cnVjdHVyZSBjYWxsZWQgJ2hzX21hY3JfdGFibGUnCgpgYGB7cn0KejIzbm9zYl91bmluZl92YWx1ZXMgPC0gaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNub3NiX3ZzX3VuaW5mIl1dCmdlbmVfaWR4IDwtIHoyM25vc2JfdW5pbmZfdmFsdWVzW1siaGduY19zeW1ib2wiXV0gJWluJSBnZW5lc19ub19kcnVnCm5vZHJ1Z19yb3dzIDwtICB6MjNub3NiX3VuaW5mX3ZhbHVlc1tnZW5lX2lkeCwgXQpyb3duYW1lcyhub2RydWdfcm93cykgPC0gbm9kcnVnX3Jvd3NbWyJoZ25jX3N5bWJvbCJdXQp6MjNfbm9kcnVnX3ZhbHVlcyA8LSBub2RydWdfcm93c1ssIGMoImRlc2VxX2xvZ2ZjIiwgImRlc2VxX2xmY3NlIildCnoyM19ub2RydWdfdmFsdWVzCgp6MjJub3NiX3VuaW5mX3ZhbHVlcyA8LSBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyMm5vc2JfdnNfdW5pbmYiXV0KZ2VuZV9pZHggPC0gejIybm9zYl91bmluZl92YWx1ZXNbWyJoZ25jX3N5bWJvbCJdXSAlaW4lIGdlbmVzX25vX2RydWcKbm9kcnVnX3Jvd3MgPC0gIHoyMm5vc2JfdW5pbmZfdmFsdWVzW2dlbmVfaWR4LCBdCnJvd25hbWVzKG5vZHJ1Z19yb3dzKSA8LSBub2RydWdfcm93c1tbImhnbmNfc3ltYm9sIl1dCnoyMl9ub2RydWdfdmFsdWVzIDwtIG5vZHJ1Z19yb3dzWywgYygiZGVzZXFfbG9nZmMiLCAiZGVzZXFfbGZjc2UiKV0KejIyX25vZHJ1Z192YWx1ZXMKCnoyM19ub2RydWdfdmFsdWVzW1sic3RhdGUiXV0gPC0gInoyM192c191bmluZmVjdGVkIgp6MjJfbm9kcnVnX3ZhbHVlc1tbInN0YXRlIl1dIDwtICJ6MjJfdnNfdW5pbmZlY3RlZCIKcGxvdF9kZiA8LSByYmluZC5kYXRhLmZyYW1lKGFzLmRhdGEuZnJhbWUoejIzX25vZHJ1Z192YWx1ZXMpLCBhcy5kYXRhLmZyYW1lKHoyMl9ub2RydWdfdmFsdWVzKSkKcGxvdF9kZltbImdlbmUiXV0gPC0gcm93bmFtZXMocGxvdF9kZikKCiMjIEkganVzdCByZWFsaXplZCB0aGF0IHRoaXMgaXMgYWN0dWFsbHkganVzdCBhIGNvbXBhcmlzb24gb2YgejIzL3oyMgojIyB3ZSBzaG91bGQganVzdCB0YWtlIHRoZSBhZGp1c3RlZCBwLXZhbHVlcyBmcm9tIHRoYXQgY29udHJhc3QgZm9yIHRoaXMuCnoyM196MjJfY29tcGFyaXNvbiA8LSBoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXQpub2RydWdfcm93cyA8LSB6MjNfejIyX2NvbXBhcmlzb25bZ2VuZV9pZHgsIF0Kbm9kcnVnX3B2YWx1ZXMgPC0gbm9kcnVnX3Jvd3NbLCBjKCJkZXNlcV9wIiwgImRlc2VxX2FkanAiKV0Kcm93bmFtZXMobm9kcnVnX3B2YWx1ZXMpIDwtIG5vZHJ1Z19yb3dzW1siaGduY19zeW1ib2wiXV0Kbm9kcnVnX3B2YWx1ZXMKCmdncGxvdChwbG90X2RmLCBhZXMoeCA9IGdlbmUsIHkgPSBkZXNlcV9sb2dmYywgZmlsbCA9IHN0YXRlKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoKSwgc3RhdCA9ICJpZGVudGl0eSIpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gZGVzZXFfbG9nZmMgLSBkZXNlcV9sZmNzZSwKICAgICAgICAgICAgICAgICAgICB5bWF4ID0gZGVzZXFfbG9nZmMgKyBkZXNlcV9sZmNzZSksCiAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzFCOUU3NyIsICIjNzU3MEIzIikpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSkpCgpjb21wYXJpc29uIDwtIGMoInoyM192c191bmluZmVjdGVkIiwgInoyMl92c191bmluZmVjdGVkIikKY29tcGFyaXNvbnMgPC0gcmVwKGxpc3QoY29tcGFyaXNvbiksIG5yb3cocGxvdF9kZikgLyAyKQpnZ3Bsb3QocGxvdF9kZiwgYWVzKHggPSBnZW5lLCB5ID0gZGVzZXFfbG9nZmMsIGZpbGwgPSBzdGF0ZSwgYWRkID0gZGVzZXFfbGZjc2UsIGZhY2V0LmJ5ID0gInN0YXRlIikpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKCksIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IGRlc2VxX2xvZ2ZjIC0gZGVzZXFfbGZjc2UsCiAgICAgICAgICAgICAgICAgICAgeW1heCA9IGRlc2VxX2xvZ2ZjICsgZGVzZXFfbGZjc2UpLAogICAgICAgICAgICAgICAgd2lkdGggPSAwLjIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC45KSkgKwogIHN0YXRfY29tcGFyZV9tZWFucygpICsKICBzdGF0X2NvbXBhcmVfbWVhbnMoY29tcGFyaXNvbnMgPSBjb21wYXJpc29ucywgbGFiZWwueSA9IHJvd25hbWVzKHoyM19ub2RydWdfdmFsdWVzKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMxQjlFNzciLCAiIzc1NzBCMyIpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUpKQoKYGBgCgpFeGNlbGxlbnQsIHRoZSB2YWx1ZXMgbm93IG1hdGNoIHVwLiAgTm93IEkgdXN0IG5lZWQgdG8gZmlndXJlIG91dCB3aHkKdGhlIHN0dXBpZCBoZ25jIElEcyBnb3QgbG9zdC4uLiAgSSBjYW4gc2VlIHRoZW0gaW4gdGhlIGhzX2Fubm90IGRhdGEKc3RydWN0dXJlLCBzbyBJIG11c3QgaGF2ZSBtZXNzZWQgdXAgd2hlbiBJIHJlZ2VuZXJlZCB0aGUgaW5wdXQgdG8gdGhlCmRlLiAgT2ssIEkgZ290IHRvIHRoZSBzYW1lIHN0YXJ0aW5nIHBvaW50IG5vdyB3aXRoIGlkZW50aWNhbCB2YWx1ZXMuCkFzIHNvb24gYXMgSSBkaWQgdGhhdCwgSSBsb29rZWQgYXQgdGhlIHJlc3VsdGluZyBwbG90IGFuZCByZWFsaXplZAp0aGF0IHdlIGFyZSBhY3R1YWxseSBqdXN0IGNvbXBhcmluZyB6MjMgLyB6MjIuCgpIZXJlIGlzIHdoeTogdGhlIHBsb3QgYXMgaXQgc3RhbmRzIGlzIGEgY29tcGFyaXNvbiBvZiB0aGUgbG9nMkZDCnZhbHVlcyBvZiB0aGUgZm9sbG93aW5nIHR3byBjb250cmFzdHM6IHoyMy91bmluZmVjdGVkIGFuZAp6MjIvdW5pbmZlY3RlZDsgc3RhdGVkIGRpZmZlcmVudGx5LCB0aGlzIGlzICh6MjMvdW5pbmYpLyh6MjIvdW5pbmYpCndoaWNoIG9mIGNvdXJzZSBjYW5jZWxzIG91dCB0byBqdXN0IHoyMy96MjIuCgpUaGVyZWZvcmUgaXQgaXMgbXVjaCBtb3JlIHBhcnNpbW9uaW91cyB0byBqdXN0IHVzZSB0aGUgdmFsdWVzIGZyb20KejIzL3oyMi4gIEkgc3dlYXIgSSBoYXZlIGdvbmUgdGhyb3VnaCB0aGlzIGV4YWN0IGV4ZXJjaXNlIG9uIHNvIHNvCm1hbnkgb2NjYXNpb25zIGluIHRoZSBwYXN0IGl0IGlzIHRlcnJpYmxlLgoKIyMgZ2dzaWduaWZpY2FuY2Ugb2YgdGhlIGltbXVuZSBtb2R1bGF0b3JzCgpgYGB7cn0Kd2FudGVkX2dlbmVzIDwtIGMoIklGSTI3IiwgIlJTQUQyIiwgIkNDTDgiLCAiSUZJNDRMIiwgIk9BU0wiLAogICAgICAgICAgICAgICAgICAiVVNQMTgiLCAiSURPMSIsICJJRE8yIiwgIktZTlUiLCAiQUhSIiwgIklMNEkxIiwKICAgICAgICAgICAgICAgICAgIlNPRDIiLCAiTk9UQ0gxIiwgIkRMTDEiLCAiRExMNCIsICJIRVMxIiwgIkhFWTEiKQptb2R1bGF0b3JfcGxvdCA8LSBnZ3NpZ25pZl9wYWlyZWRfZ2VuZXMoCiAgaHNfbWFjciwgY29uZGl0aW9ucyA9IGMoImluZl96MjMiLCAiaW5mX3oyMiIpLCBnZW5lcyA9IHdhbnRlZF9nZW5lcykKbW9kdWxhdG9yX3Bsb3QKYGBgCgojIyBnZ3NpZ25pZmljYW5jZSBvZiB0aGUgdHJhbnNwb3J0ZXJzCgpgYGB7cn0KIyMgRmlyc3QgbGluZSBpcyB3aXRob3V0IGRydWcKd2FudGVkX2dlbmVzIDwtIGMoIkFCQ0IxIiwgIkFCQ0c0IiwgIkFCQ0I1IiwgIkFRUDIiLCAiQVFQMyIsCiAgICAgICAgICAgICAgICAgICMjIHdpdGggZHJ1ZwogICAgICAgICAgICAgICAgICAiQUJDQjEiLCAiQUJDRzQiLCAiQVFQMiIsICJBUVAzIiwgIkFRUDgiKQp0cmFuc3BvcnRlcl9wbG90IDwtIGdnc2lnbmlmX3BhaXJlZF9nZW5lcygKICBoc19tYWNyLCBjb25kaXRpb25zID0gYygiaW5mX3oyMyIsICJpbmZfejIyIiksIGdlbmVzID0gd2FudGVkX2dlbmVzKQp0cmFuc3BvcnRlcl9wbG90CmBgYAoKYGBge3J9CnBhbmRlcjo6cGFuZGVyKHNlc3Npb25JbmZvKCkpCm1lc3NhZ2UoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkKdG1wIDwtIHNhdmVtZShmaWxlbmFtZSA9IHNhdmVmaWxlKQpgYGAKCmBgYHtyIGxvYWRtZV9hZnRlciwgZXZhbD1GQUxTRX0KdG1wIDwtIGxvYWRtZShmaWxlbmFtZSA9IHNhdmVmaWxlKQpgYGAKZGV2dG9vbHM6OmxvYWRfYWxsKCd+L2hwZ2x0b29scycpCg==