1 Changelog

202405: Changed excel output directory to match organization scheme in box. Generally this means files go to analyses/transcriptome/{type_of_contrast}/{date}/something_{suffix}.xlsx Where suffix is _table for the full tables and _sig for the significant genes and will include information about whether sva etc was used. 202405: Adding some goseq results.

2 Contrasts

** Note! ** The new definitions of susceptible/resistant are tighter than ever before, as a result there are no longer any ambiguous samples. Thus I removed the ambiguous contrasts in the following block.

zymodeme_keeper <- list(
  "zymodeme" = c("z23", "z22"))
susceptibility_keepers <- list(
  "resistant_sensitive" = c("resistant", "sensitive"))
##    "resistant_ambiguous" = c("resistant", "ambiguous"),
##    "sensitive_ambiguous" = c("sensitive", "ambiguous"))

3 Parasite Ontology data

Just a reminder that in data_structures.Rmd I created lp_go and lp_lengths

3.1 Zymodeme enzyme gene IDs

Najib read me an email listing off the gene names associated with the zymodeme classification. I took those names and cross referenced them against the Leishmania panamensis gene annotations and found the following:

They are:

  1. ALAT: LPAL13_120010900 – alanine aminotransferase
  2. ASAT: LPAL13_340013000 – aspartate aminotransferase
  3. G6PD: LPAL13_000054100 – glucase-6-phosphate 1-dehydrogenase
  4. NH: LPAL13_14006100, LPAL13_180018500 – inosine-guanine nucleoside hydrolase
  5. MPI: LPAL13_320022300 (maybe) – mannose phosphate isomerase (I chose phosphomannose isomerase)

Given these 6 gene IDs (NH has two gene IDs associated with it), I can do some looking for specific differences among the various samples.

3.1.1 Expression levels of zymodeme genes

The following creates a colorspace (red to green) heatmap showing the observed expression of these genes in every sample.

my_genes <- c("LPAL13_120010900", "LPAL13_340013000", "LPAL13_000054100",
              "LPAL13_140006100", "LPAL13_180018500", "LPAL13_320022300",
              "other")
my_names <- c("ALAT", "ASAT", "G6PD", "NHv1", "NHv2", "MPI", "other")

zymo_six_genes <- exclude_genes_expt(lp_two_strains, ids = my_genes, method = "keep")
## Error in exclude_genes_expt(lp_two_strains, ids = my_genes, method = "keep"): could not find function "exclude_genes_expt"
strain_norm <- normalize_expt(zymo_six_genes, convert = "rpkm", filter = TRUE, transform = "log2",
                              column = "annot_cds_length")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'input' in selecting a method for function 'state': object 'zymo_six_genes' not found
zymo_heatmap <- plot_sample_heatmap(strain_norm, row_label = my_names)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'plot_sample_heatmap': object 'strain_norm' not found
zymo_heatmap
## Error: object 'zymo_heatmap' not found
lp_norm <- normalize_expt(lp_two_strains, filter = TRUE, convert = "cpm",
                          norm = "quant", transform = "log2", column = "annot_cds_length")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'input' in selecting a method for function 'state': object 'lp_two_strains' not found
zymo_heatmap_all <- plot_sample_heatmap(lp_norm)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'plot_sample_heatmap': object 'lp_norm' not found
zymo_heatmap_all
## Error: object 'zymo_heatmap_all' not found

3.2 Compare to highly expressed, variant genes

I want to compare the above heatmap with one which is comprised of all genes with some ‘significantly high’ expression value and also a not-negligible coefficient of variance.

zymo_high_genes <- normalize_expt(lp_two_strains, filter = "cv", cv_min = 0.9)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'input' in selecting a method for function 'state': object 'lp_two_strains' not found
high_strain_norm <- normalize_expt(zymo_high_genes, convert = "rpkm",
                                   norm = "quant", transform = "log2", column = "annot_cds_length")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'input' in selecting a method for function 'state': object 'zymo_high_genes' not found
zymo_heatmap <- plot_sample_heatmap(high_strain_norm, row_label = my_names)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'plot_sample_heatmap': object 'high_strain_norm' not found
zymo_heatmap
## Error: object 'zymo_heatmap' not found

I think this plot suggests that the difference between the two primary strains is not really one of a few specific genes, but instead a global pattern.

4 Zymodeme differential expression

4.1 No attempt at batch estimation

zymo_de_nobatch <- all_pairwise(lp_zymo, filter = TRUE, model_batch = FALSE, parallel = FALSE)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'lp_zymo' not found
zymo_de_nobatch
## Error: object 'zymo_de_nobatch' not found
## Including the plots causes the rda file to balloon to 3.4Gb in the following invocation.
## Removing them results in... holy crap 2.1Mb
zymo_table_nobatch <- combine_de_tables(
    zymo_de_nobatch, keepers = zymodeme_keeper, label_column = "annot_gene_product",
    rda = glue("rda/zymo_tables_nobatch-v{ver}.rda"),
    excel = glue("{excel_out}/DE_Strain/{ver}/zymo_tables_nobatch-v{ver}.xlsx"))
## Error: object 'zymo_de_nobatch' not found
zymo_table_nobatch
## Error: object 'zymo_table_nobatch' not found
zymo_sig_nobatch <- extract_significant_genes(
    zymo_table_nobatch,
    according_to = "deseq", current_id = "GID", required_id = "GID",
    gmt = glue("excel/zymodeme_nobatch-v{ver}.gmt"),
    excel = glue("{excel_out}/DE_Strain/{ver}/zymo_sig_nobatch_deseq-v{ver}.xlsx"))
## Error: object 'zymo_table_nobatch' not found
zymo_sig_nobatch
## Error: object 'zymo_sig_nobatch' not found

4.1.0.1 Gene ontology comparing the strains

There are too few genes at our current stringencies for a meaningful result.

increased_z22 <- zymo_sig_nobatch[["deseq"]][["downs"]][["zymodeme"]]
## Error: object 'zymo_sig_nobatch' not found
increased_z23 <- zymo_sig_nobatch[["deseq"]][["ups"]][["zymodeme"]]
## Error: object 'zymo_sig_nobatch' not found
z22_goseq <- simple_goseq(increased_z22, go_db = lp_go, length_db = lp_lengths)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'table' in selecting a method for function '%in%': object 'increased_z22' not found
z23_goseq <- simple_goseq(increased_z23, go_db = lp_go, length_db = lp_lengths)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'table' in selecting a method for function '%in%': object 'increased_z23' not found

4.1.1 Plot DE genes without batch estimation/adjustment

zymo_table_nobatch[["plots"]][["zymodeme"]][["deseq_ma_plots"]]
## Error: object 'zymo_table_nobatch' not found
zymo_table_nobatch[["plots"]][["zymodeme"]][["deseq_vol_plots"]]
## Error: object 'zymo_table_nobatch' not found

Log ratio, mean average plot and volcano plot of the comparison of the two primary zymodeme transcriptomes. When the transcriptomes of the two main strains (43 and 41 samples of z2.3 and z2.1) were compared without any attempt at batch/surrogate estimation with DESeq2, 45 and 85 genes were observed as significantly higher in strain z2.3 and z2.2 respectively using a cutoff of 1.0 logFC and 0.05 FDR adjusted p-value. There remain a large number of genes which are likely significantly different between the two strains, but fall below the 2-fold difference required for ‘significance.’ This follows prior observations that the parasite transcriptomes are constituitively expressed.

When the same data was plotted via a volcano plot, the relatively small range of fold changes compared to the large range of adjusted p-values is visible.

4.2 Attempt SVA estimate

zymo_de_sva <- all_pairwise(lp_zymo, filter = TRUE, model_batch = "svaseq")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'lp_zymo' not found
zymo_de_sva
## Error: object 'zymo_de_sva' not found
zymo_table_sva <- combine_de_tables(
    zymo_de_sva, keepers = zymodeme_keeper, label_column = "annot_gene_product",
    rda = glue("rda/zymo_tables_sva-v{ver}.rda"),
    excel = glue("{excel_out}/DE_Strain/{ver}/zymo_tables_sva-v{ver}.xlsx"))
## Error: object 'zymo_de_sva' not found
zymo_table_sva
## Error: object 'zymo_table_sva' not found
zymo_sig_sva <- extract_significant_genes(
    zymo_table_sva,
    according_to = "deseq",
    current_id = "GID", required_id = "GID",
    gmt = glue("excel/zymodeme_sva-v{ver}.gmt"),
    excel = glue("{excel_out}/DE_Strain/{ver}/zymo_sig_sva-v{ver}.xlsx"))
## Error: object 'zymo_table_sva' not found
zymo_sig_sva
## Error: object 'zymo_sig_sva' not found

4.2.0.1 Gene ontology comparing the strains

There are too few genes at our current stringencies for a meaningful result.

increased_z22 <- zymo_sig_sva[["deseq"]][["downs"]][["zymodeme"]]
## Error: object 'zymo_sig_sva' not found
increased_z23 <- zymo_sig_sva[["deseq"]][["ups"]][["zymodeme"]]
## Error: object 'zymo_sig_sva' not found
z22_goseq <- simple_goseq(increased_z22, go_db = lp_go, length_db = lp_lengths)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'table' in selecting a method for function '%in%': object 'increased_z22' not found
z23_goseq <- simple_goseq(increased_z23, go_db = lp_go, length_db = lp_lengths)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'table' in selecting a method for function '%in%': object 'increased_z23' not found

4.2.1 Plot zymodeme DE genes with sva batch estimation/adjustment

When estimates from SVA were included in the statistical model used by EdgeR, DESeq2, and limma; a nearly identical view of the data emerged. I think this shows with a high degree of confidence, that sva is not having a significant effect on this dataset.

zymo_table_sva[["plots"]][["zymodeme"]][["deseq_ma_plots"]]
## Error: object 'zymo_table_sva' not found
zymo_table_sva[["plots"]][["zymodeme"]][["deseq_vol_plots"]]
## Error: object 'zymo_table_sva' not found

5 Parasite Susceptibility to Drug (Current)

This susceptibility comparison is using the ‘current’ dataset.

Note again: we no longer have any ambiguous samples, so I commented out a portion of the following block.

sus_de_nobatch <- all_pairwise(lp_susceptibility, filter = TRUE, model_batch = FALSE)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'lp_susceptibility' not found
sus_de_nobatch
## Error: object 'sus_de_nobatch' not found
sus_table_nobatch <- combine_de_tables(
  sus_de_nobatch, keepers = susceptibility_keepers,
  rda = glue("rda/sus_tables_nobatch-v{ver}.rda"),
  excel = glue("{excel_out}/DE_Susceptibility/{ver}/sus_tables_nobatch-v{ver}.xlsx"))
## Error: object 'sus_de_nobatch' not found
sus_table_nobatch
## Error: object 'sus_table_nobatch' not found
sus_sig_nobatch <- extract_significant_genes(
  sus_table_nobatch,
  excel = glue("{excel_out}/DE_Susceptibility/{ver}/sus_sig_nobatch-v{ver}.xlsx"))
## Error: object 'sus_table_nobatch' not found
sus_de_sva <- all_pairwise(lp_susceptibility, filter = TRUE, model_batch = "svaseq")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'lp_susceptibility' not found
sus_de_sva
## Error: object 'sus_de_sva' not found
sus_table_sva <- combine_de_tables(
    sus_de_sva, keepers = susceptibility_keepers,
    rda = glue("rda/sus_tables_sva-v{ver}.rda"),
    excel = glue("{excel_out}/DE_Susceptibility/{ver}/sus_tables_sva-v{ver}.xlsx"))
## Error: object 'sus_de_sva' not found
sus_table_sva
## Error: object 'sus_table_sva' not found
sus_sig_sva <- extract_significant_genes(
  sus_table_sva, according_to = "deseq",
    excel = glue("{excel_out}/DE_Susceptibility/{ver}/sus_sig_sva-v{ver}.xlsx"))
## Error: object 'sus_table_sva' not found
sus_sig_sva
## Error: object 'sus_sig_sva' not found
## To get a more true sense of sensitive vs resistant with sva, we kind of need to get rid of the
## unknown samples and perhaps the ambiguous.
## no_ambiguous <- subset_expt(lp_susceptibility, subset = "condition!='ambiguous'") %>%
##   subset_expt(subset = "condition!='unknown'")
## no_ambiguous_de_sva <- all_pairwise(no_ambiguous, filter = TRUE, model_batch = "svaseq")
## no_ambiguous_de_sva
## Let us see if my keeper code will fail hard or soft with extra contrasts...
## no_ambiguous_table_sva <- combine_de_tables(
##     no_ambiguous_de_sva, keepers = susceptibility_keepers,
##     excel = glue("excel/no_ambiguous_tables_sva-v{ver}.xlsx"))
## no_ambiguous_table_sva
## no_ambiguous_sig_sva <- extract_significant_genes(
##     no_ambiguous_table_sva, according_to = "deseq",
##     excel = glue("excel/no_ambiguous_sig_sva-v{ver}.xlsx"))
## no_ambiguous_sig_sva

5.0.0.1 Gene ontology comparing the susceptibility

sus_sig_sva
## Error: object 'sus_sig_sva' not found
increased_resistant <- sus_sig_sva[["deseq"]][["ups"]][["resistant_sensitive"]]
## Error: object 'sus_sig_sva' not found
increased_sensitive <- sus_sig_sva[["deseq"]][["downs"]][["resistant_sensitive"]]
## Error: object 'sus_sig_sva' not found
resistant_goseq <- simple_goseq(increased_resistant, go_db = lp_go, length_db = lp_lengths)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'table' in selecting a method for function '%in%': object 'increased_resistant' not found
sensitive_goseq <- simple_goseq(increased_sensitive, go_db = lp_go, length_db = lp_lengths)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'table' in selecting a method for function '%in%': object 'increased_sensitive' not found

5.0.1 Plot Susceptibility DE genes with sva batch estimation/adjustment

sus_table_nobatch[["plots"]][["resistant_sensitive"]][["deseq_ma_plots"]]
## Error: object 'sus_table_nobatch' not found
sus_table_nobatch[["plots"]][["resistant_sensitive"]][["deseq_vol_plots"]]
## Error: object 'sus_table_nobatch' not found
sus_table_sva[["plots"]][["resistant_sensitive"]][["deseq_ma_plots"]]
## Error: object 'sus_table_sva' not found
sus_table_sva[["plots"]][["resistant_sensitive"]][["deseq_vol_plots"]]
## Error: object 'sus_table_sva' not found

Given that resistance/sensitivity tends to be correlated with strain, one might expect similar results. One caveat in this context though: there are fewer strains with resistance/sensitivity definitions. This when the analysis was repeated without the ambiguous/unknown samples, a few more genes were observed as significant.

6 Comparing DE results from strain/sensitivity

## zymo_table_sva[["plots"]][["zymodeme"]][["deseq_ma_plots"]][["plot"]]
zy_df <- zymo_table_sva[["data"]][["zymodeme"]]
## Error: object 'zymo_table_sva' not found
sus_df <- sus_table_sva[["data"]][["resistant_sensitive"]]
## Error: object 'sus_table_sva' not found
both_df <- merge(zy_df, sus_df, by = "row.names")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'merge': object 'zy_df' not found
plot_df <- both_df[, c("deseq_logfc.x", "deseq_logfc.y")]
## Error: object 'both_df' not found
rownames(plot_df) <- both_df[["Row.names"]]
## Error: object 'both_df' not found
colnames(plot_df) <- c("z23_vs_z22", "sensitive_vs_resistant")
## Error: object 'plot_df' not found
compare <- plot_linear_scatter(plot_df)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'plot_df' not found
pp(file = "images/compare_sus_zy.png")
compare$scatter
## Error in compare$scatter: object of type 'closure' is not subsettable
dev.off()
## png 
##   2
compare$scatter
## Error in compare$scatter: object of type 'closure' is not subsettable
compare$cor
## Error in compare$cor: object of type 'closure' is not subsettable

7 Parasite Susceptibility to Drug (Historical)

This susceptibility comparison is using the historical dataset.

sushist_de_nobatch <- all_pairwise(lp_susceptibility_historical, filter = TRUE,
                                   model_batch = FALSE)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'lp_susceptibility_historical' not found
sushist_de_nobatch
## Error: object 'sushist_de_nobatch' not found
sushist_table_nobatch <- combine_de_tables(
  sushist_de_nobatch, keepers = susceptibility_keepers,
  excel = glue("{excel_out}/DE_Susceptibility/sushist_tables_nobatch-v{ver}.xlsx"))
## Error: object 'sushist_de_nobatch' not found
sushist_table_nobatch
## Error: object 'sushist_table_nobatch' not found
sushist_sig_nobatch <- extract_significant_genes(
  sushist_table_nobatch,
  excel = glue("{excel_out}/DE_Susceptibility/sushist_sig_nobatch-v{ver}.xlsx"))
## Error: object 'sushist_table_nobatch' not found
sushist_sig_nobatch
## Error: object 'sushist_sig_nobatch' not found
sushist_de_sva <- all_pairwise(lp_susceptibility_historical, filter = TRUE,
                               model_batch = "svaseq")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'lp_susceptibility_historical' not found
sushist_de_sva
## Error: object 'sushist_de_sva' not found
sushist_table_sva <- combine_de_tables(
  sushist_de_sva, keepers = susceptibility_keepers,
  excel = glue("{excel_out}/DE_Susceptibility/sushist_tables_sva-v{ver}.xlsx"))
## Error: object 'sushist_de_sva' not found
sushist_table_sva
## Error: object 'sushist_table_sva' not found
sushist_sig_sva <- extract_significant_genes(
  sushist_table_sva, according_to = "deseq",
  excel = glue("{excel_out}/DE_Susceptibility/sushist_sig_sva-v{ver}.xlsx"))
## Error: object 'sushist_table_sva' not found
sushist_sig_sva
## Error: object 'sushist_sig_sva' not found

8 Cure/Fail association

##cf_nb_input <- subset_expt(cf_expt, subset="condition!='unknown'")
cf_de_nobatch <- all_pairwise(lp_cf_known, filter = TRUE, model_batch = FALSE)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'lp_cf_known' not found
cf_de_nobatch
## Error: object 'cf_de_nobatch' not found
cf_table_nobatch <- combine_de_tables(
  cf_de_nobatch,
  excel = glue("{excel_out}/DE_Cure_vs_Fail/{ver}/cf_tables_nobatch-v{ver}.xlsx"))
## Error: object 'cf_de_nobatch' not found
cf_table_nobatch
## Error: object 'cf_table_nobatch' not found
cf_sig_nobatch <- extract_significant_genes(
  cf_table_nobatch,
  excel = glue("{excel_out}/DE_Cure_vs_Fail/{ver}/cf_sig_nobatch-v{ver}.xlsx"))
## Error: object 'cf_table_nobatch' not found
cf_sig_nobatch
## Error: object 'cf_sig_nobatch' not found
cf_de <- all_pairwise(lp_cf_known, filter = TRUE, model_batch = "svaseq")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'lp_cf_known' not found
cf_de
## Error: object 'cf_de' not found
cf_table <- combine_de_tables(
  cf_de,
  excel = glue("{excel_out}/DE_Cure_vs_Fail/{ver}/cf_tables-v{ver}.xlsx"))
## Error: object 'cf_de' not found
cf_table
## Error: object 'cf_table' not found
cf_sig <- extract_significant_genes(
  cf_table,
  excel = glue("{excel_out}/DE_Cure_vs_Fail/{ver}/cf_sig-v{ver}.xlsx"))
## Error: object 'cf_table' not found
cf_sig
## Error: object 'cf_sig' not found

I am not going to mess with GO searches for this.

8.1 Cure/Fail DE plots

It is not surprising that few or no genes are deemed significantly differentially expressed across samples which were taken from cure or fail patients.

cf_table_nobatch[["plots"]][["fail_vs_cure"]][["deseq_ma_plots"]]
## Error: object 'cf_table_nobatch' not found
dev <- pp(file = "images/cf_ma.png")
cf_table[["plots"]][["fail_vs_cure"]][["deseq_ma_plots"]]
## Error: object 'cf_table' not found
closed <- dev.off()
cf_table[["plots"]][["fail_vs_cure"]][["deseq_ma_plots"]]
## Error: object 'cf_table' not found

9 Combining the macrophage infected amastigotes with in-vitro promastigotes

One query we have not yet addressed: what are the similarities and differences among the strains used to infect the macrophage samples and the promastigote samples used in the TMRC2 parasite data?

In my container image, this dataset is not currently loaded, so turning this off.

## I just fixed this in the datasets Rmd, but until that propagates just set it manually
annotation(lp_expt) <- annotation(lp_macrophage)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'annotation': object 'lp_macrophage' not found
tmrc2_macrophage_norm <- normalize_expt(lp_macrophage, transform="log2", convert="cpm",
                                        norm="quant", filter=TRUE)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'input' in selecting a method for function 'state': object 'lp_macrophage' not found
all_tmrc2 <- combine_expts(lp_expt, lp_macrophage)
## Error: object 'lp_expt' not found
all_nosb <- all_tmrc2
## Error: object 'all_tmrc2' not found
pData(all_nosb)[["stage"]] <- "promastigote"
## Error: object 'all_nosb' not found
na_idx <- is.na(pData(all_nosb)[["macrophagetreatment"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'all_nosb' not found
pData(all_nosb)[na_idx, "macrophagetreatment"] <- "undefined"
## Error: object 'all_nosb' not found
all_nosb <- subset_expt(all_nosb, subset = "macrophagetreatment!='inf_sb'")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'expt' in selecting a method for function 'subset_expt': object 'all_nosb' not found
ama_idx <- pData(all_nosb)[["macrophagetreatment"]] == "inf"
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'all_nosb' not found
pData(all_nosb)[ama_idx, "stage" ] <- "amastigote"
## Error: object 'all_nosb' not found
pData(all_nosb)[["batch"]] <- pData(all_nosb)[["stage"]]
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'all_nosb' not found

I think the above picture is sort of the opposite of what we want to compare in a DE analysis for this set of data, e.g. we want to compare promastigotes from amastigotes?

all_nosb <- set_expt_batches(all_nosb, fact = "condition") %>%
  set_expt_conditions(fact = "stage")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': error in evaluating the argument 'expt' in selecting a method for function 'set_expt_batches': object 'all_nosb' not found
two_zymo <- subset_expt(
  all_nosb,
  subset = "zymodemecategorical=='z22'|zymodemecategorical=='z23'|zymodemecategorical=='unknown'")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'expt' in selecting a method for function 'subset_expt': object 'all_nosb' not found
pro_ama <- all_pairwise(all_nosb, filter = TRUE, model_batch = "svaseq")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'all_nosb' not found
pro_ama_table <- combine_de_tables(
  pro_ama,
  excel = glue("{excel_out}/DE_promastigote_amastigote/{ver}/pro_vs_ama_table-v{ver}.xlsx"))
## Error: object 'pro_ama' not found
pro_ama_sig <- extract_significant_genes(
    pro_ama_table,
    excel = glue("{excel_out}/DE_promastigote_amastigote/{ver}/pro_vs_ama_sig-v{ver}.xlsx"))
## Error: object 'pro_ama_table' not found

9.0.0.1 Gene ontology comparing the life stages

increased_promastigote <- pro_ama_sig[["deseq"]][["ups"]][["promastigote_vs_amastigote"]]
## Error: object 'pro_ama_sig' not found
increased_amastigote <- pro_ama_sig[["deseq"]][["downs"]][["promastigote_vs_amastigote"]]
## Error: object 'pro_ama_sig' not found
promastigote_goseq <- simple_goseq(increased_promastigote, go_db = lp_go, length_db = lp_lengths)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'table' in selecting a method for function '%in%': object 'increased_promastigote' not found
promastigote_goseq
## Error: object 'promastigote_goseq' not found
amastigote_goseq <- simple_goseq(increased_amastigote, go_db = lp_go, length_db = lp_lengths)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'table' in selecting a method for function '%in%': object 'increased_amastigote' not found
amastigote_goseq
## Error: object 'amastigote_goseq' not found
## silly, topgo wants the gene id column to be 'ID', I should fix this.
colnames(lp_go) <- c("ID", "GO")
## Error: object 'lp_go' not found
promastigote_topgo <- simple_topgo(increased_promastigote, go_db = lp_go)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'sig_genes' in selecting a method for function 'simple_topgo': object 'increased_promastigote' not found
enrichplot::dotplot(promastigote_topgo$enrich_results$bp)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'dotplot': object 'promastigote_topgo' not found
amastigote_topgo <- simple_topgo(increased_amastigote, go_db = lp_go)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'sig_genes' in selecting a method for function 'simple_topgo': object 'increased_amastigote' not found
enrichplot::dotplot(amastigote_topgo$enrich_results$bp)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'dotplot': object 'amastigote_topgo' not found

9.0.1 Plot promastigote/amastigote DE genes

pro_ama_table[["plots"]][["promastigote_vs_amastigote"]][["deseq_ma_plots"]]
## Error: object 'pro_ama_table' not found

I am a little surprised by this plot, I somewhat expected there to be few genes which passed the 2-fold difference demarcation line.

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: stats, graphics, grDevices, utils, datasets, methods and base

other attached packages: hpgltools(v.1.2), testthat(v.3.2.3), glue(v.1.8.0) and Heatplus(v.3.16.0)

loaded via a namespace (and not attached): fs(v.1.6.6), matrixStats(v.1.5.0), bitops(v.1.0-9), enrichplot(v.1.28.4), devtools(v.2.4.6), httr(v.1.4.7), RColorBrewer(v.1.1-3), numDeriv(v.2016.8-1.1), tools(v.4.5.0), backports(v.1.5.0), R6(v.2.6.1), lazyeval(v.0.2.2), mgcv(v.1.9-3), cli(v.3.6.5), Biobase(v.2.68.0), sass(v.0.4.10), mvtnorm(v.1.3-3), S7(v.0.2.0), genefilter(v.1.90.0), Rsamtools(v.2.24.0), systemfonts(v.1.3.1), yulab.utils(v.0.2.1), gson(v.0.1.0), DOSE(v.4.2.0), R.utils(v.2.13.0), dichromat(v.2.0-0.1), sessioninfo(v.1.2.3), limma(v.3.64.3), rstudioapi(v.0.17.1), RSQLite(v.2.4.3), generics(v.0.1.4), gridGraphics(v.0.5-1), BiocIO(v.1.18.0), gtools(v.3.9.5), dplyr(v.1.1.4), zip(v.2.3.3), GO.db(v.3.21.0), Matrix(v.1.7-3), S4Vectors(v.0.46.0), abind(v.1.4-8), R.methodsS3(v.1.8.2), lifecycle(v.1.0.4), yaml(v.2.3.10), edgeR(v.4.6.3), SummarizedExperiment(v.1.38.1), gplots(v.3.2.0), qvalue(v.2.40.0), SparseArray(v.1.8.1), grid(v.4.5.0), blob(v.1.2.4), promises(v.1.3.3), crayon(v.1.5.3), ggtangle(v.0.0.7), lattice(v.0.22-7), cowplot(v.1.2.0), GenomicFeatures(v.1.60.0), annotate(v.1.86.1), KEGGREST(v.1.48.1), pillar(v.1.11.0), knitr(v.1.50), varhandle(v.2.0.6), fgsea(v.1.34.2), GenomicRanges(v.1.60.0), rjson(v.0.2.23), boot(v.1.3-31), corpcor(v.1.6.10), codetools(v.0.2-20), fastmatch(v.1.1-6), ggiraph(v.0.9.2), ggfun(v.0.2.0), fontLiberation(v.0.1.0), data.table(v.1.17.8), remotes(v.2.5.0), vctrs(v.0.6.5), png(v.0.1-8), treeio(v.1.32.0), Rdpack(v.2.6.4), gtable(v.0.3.6), cachem(v.1.1.0), xfun(v.0.53), openxlsx(v.4.2.8), rbibutils(v.2.3), S4Arrays(v.1.8.1), mime(v.0.13), reformulas(v.0.4.1), survival(v.3.8-3), iterators(v.1.0.14), statmod(v.1.5.0), ellipsis(v.0.3.2), nlme(v.3.1-168), pbkrtest(v.0.5.5), ggtree(v.3.99.0), usethis(v.3.2.1), bit64(v.4.6.0-1), fontquiver(v.0.2.1), EnvStats(v.3.1.0), GenomeInfoDb(v.1.44.2), rprojroot(v.2.1.1), bslib(v.0.9.0), KernSmooth(v.2.23-26), BiocGenerics(v.0.54.0), DBI(v.1.2.3), DESeq2(v.1.48.1), tidyselect(v.1.2.1), bit(v.4.6.0), compiler(v.4.5.0), curl(v.7.0.0), graph(v.1.86.0), desc(v.1.4.3), fontBitstreamVera(v.0.1.1), DelayedArray(v.0.34.1), plotly(v.4.11.0), rtracklayer(v.1.68.0), scales(v.1.4.0), caTools(v.1.18.3), remaCor(v.0.0.20), rappdirs(v.0.3.3), stringr(v.1.5.1), digest(v.0.6.37), minqa(v.1.2.8), variancePartition(v.1.38.1), rmarkdown(v.2.29), aod(v.1.3.3), XVector(v.0.48.0), RhpcBLASctl(v.0.23-42), htmltools(v.0.5.8.1), pkgconfig(v.2.0.3), lme4(v.1.1-37), MatrixGenerics(v.1.20.0), fastmap(v.1.2.0), rlang(v.1.1.6), htmlwidgets(v.1.6.4), UCSC.utils(v.1.4.0), shiny(v.1.11.1), farver(v.2.1.2), jquerylib(v.0.1.4), jsonlite(v.2.0.0), BiocParallel(v.1.42.1), GOSemSim(v.2.34.0), R.oo(v.1.27.1), RCurl(v.1.98-1.17), magrittr(v.2.0.4), GenomeInfoDbData(v.1.2.14), ggplotify(v.0.1.2), patchwork(v.1.3.2), Rcpp(v.1.1.0), ape(v.5.8-1), gdtools(v.0.4.4), stringi(v.1.8.7), brio(v.1.1.5), MASS(v.7.3-65), plyr(v.1.8.9), pkgbuild(v.1.4.8), parallel(v.4.5.0), ggrepel(v.0.9.6), forcats(v.1.0.0), Biostrings(v.2.76.0), splines(v.4.5.0), pander(v.0.6.6), locfit(v.1.5-9.12), igraph(v.2.1.4), reshape2(v.1.4.4), stats4(v.4.5.0), pkgload(v.1.4.1), XML(v.3.99-0.19), evaluate(v.1.0.4), BiocManager(v.1.30.26), nloptr(v.2.2.1), PROPER(v.1.40.0), foreach(v.1.5.2), httpuv(v.1.6.16), tidyr(v.1.3.1), purrr(v.1.1.0), ggplot2(v.4.0.0), broom(v.1.0.10), xtable(v.1.8-4), restfulr(v.0.0.16), fANCOVA(v.0.6-1), tidytree(v.0.4.6), later(v.1.4.3), viridisLite(v.0.4.2), tibble(v.3.3.0), lmerTest(v.3.1-3), clusterProfiler(v.4.16.0), aplot(v.0.2.8), memoise(v.2.0.1), AnnotationDbi(v.1.70.0), GenomicAlignments(v.1.44.0), IRanges(v.2.42.0), sva(v.3.56.0) and GSEABase(v.1.70.0)

message(paste0("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 5043179aa73cd71040a7ba82276b0cf26cc661bd
## This is hpgltools commit: Mon Oct 6 12:01:25 2025 -0400: 5043179aa73cd71040a7ba82276b0cf26cc661bd
## message(paste0("Saving to ", savefile))
## tmp <- sm(saveme(filename = savefile))
tmp <- loadme(filename = savefile)
LS0tCnRpdGxlOiAiVE1SQzIgYHIgU3lzLmdldGVudignVkVSU0lPTicpYDogUHJvbWFzdGlnb3RlIChtb3N0bHkpIERpZmZlcmVudGlhbCBFeHByZXNzaW9uIEFuYWx5c2VzLiIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBmaWdfaGVpZ2h0OiA3CiAgICBmaWdfd2lkdGg6IDcKICAgIGhpZ2hsaWdodDogemVuYnVybgogICAga2VlcF9tZDogZmFsc2UKICAgIG1vZGU6IHNlbGZjb250YWluZWQKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgc2VsZl9jb250YWluZWQ6IHRydWUKICAgIHRoZW1lOiByZWFkYWJsZQogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogZmFsc2UKICAgICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgpib2R5IC5tYWluLWNvbnRhaW5lciB7CiAgbWF4LXdpZHRoOiAxNjAwcHg7Cn0KYm9keSwgdGQgewogIGZvbnQtc2l6ZTogMTZweDsKfQpjb2RlLnJ7CiAgZm9udC1zaXplOiAxNnB4Owp9CnByZSB7CiAgZm9udC1zaXplOiAxNnB4Cn0KPC9zdHlsZT4KCmBgYHtyIG9wdGlvbnMsIGluY2x1ZGUgPSBGQUxTRX0KbGlicmFyeShIZWF0cGx1cykKbGlicmFyeShocGdsdG9vbHMpCmxpYnJhcnkoZ2x1ZSkKdHQgPC0gdHJ5KGRldnRvb2xzOjpsb2FkX2FsbCgifi9ocGdsdG9vbHMiKSkKa25pdHI6Om9wdHNfa25pdCRzZXQocHJvZ3Jlc3MgPSBUUlVFLCB2ZXJib3NlID0gVFJVRSwgd2lkdGggPSA5MCwgZWNobyA9IFRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBlcnJvciA9IFRSVUUsIGZpZy53aWR0aCA9IDgsIGZpZy5oZWlnaHQgPSA4LCBmaWcucmV0aW5hID0gMiwKICBvdXQud2lkdGggPSAiMTAwJSIsIGRldiA9ICJwbmciLAogIGRldi5hcmdzID0gbGlzdChwbmcgPSBsaXN0KHR5cGUgPSAiY2Fpcm8tcG5nIikpKQpvbGRfb3B0aW9ucyA8LSBvcHRpb25zKGRpZ2l0cyA9IDQsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwga25pdHIuZHVwbGljYXRlLmxhYmVsID0gImFsbG93IikKZ2dwbG90Mjo6dGhlbWVfc2V0KGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSkKdmVyIDwtIFN5cy5nZXRlbnYoIlZFUlNJT04iKQpwcmV2aW91c19maWxlIDwtICIiCnJ1bmRhdGUgPC0gZm9ybWF0KFN5cy5EYXRlKCksIGZvcm1hdCA9ICIlWSVtJWQiKQoKcm1kX2ZpbGUgPC0gIjAzZGlmZmVyZW50aWFsX2V4cHJlc3Npb24uUm1kIgpzYXZlZmlsZSA8LSBnc3ViKHBhdHRlcm4gPSAiXFwuUm1kIiwgcmVwbGFjZSA9ICJcXC5yZGFcXC54eiIsIHggPSBybWRfZmlsZSkKbG9hZGVkIDwtIGxvYWQoZmlsZSA9IGdsdWUoInJkYS90bXJjMl9kYXRhX3N0cnVjdHVyZXMtdnt2ZXJ9LnJkYSIpKQpleGNlbF9vdXQgPC0gImFuYWx5c2VzL3RyYW5zY3JpcHRvbWUiCmBgYAoKIyBDaGFuZ2Vsb2cKCjIwMjQwNTogQ2hhbmdlZCBleGNlbCBvdXRwdXQgZGlyZWN0b3J5IHRvIG1hdGNoIG9yZ2FuaXphdGlvbiBzY2hlbWUgaW4gYm94LgogICAgICAgIEdlbmVyYWxseSB0aGlzIG1lYW5zIGZpbGVzIGdvIHRvCiAgICAgICAgYW5hbHlzZXMvdHJhbnNjcmlwdG9tZS97dHlwZV9vZl9jb250cmFzdH0ve2RhdGV9L3NvbWV0aGluZ197c3VmZml4fS54bHN4CiAgICAgICAgV2hlcmUgc3VmZml4IGlzIF90YWJsZSBmb3IgdGhlIGZ1bGwgdGFibGVzIGFuZCBfc2lnIGZvciB0aGUgc2lnbmlmaWNhbnQgZ2VuZXMgYW5kCiAgICAgICAgd2lsbCBpbmNsdWRlIGluZm9ybWF0aW9uIGFib3V0IHdoZXRoZXIgc3ZhIGV0YyB3YXMgdXNlZC4KMjAyNDA1OiBBZGRpbmcgc29tZSBnb3NlcSByZXN1bHRzLgoKIyBDb250cmFzdHMKCioqIE5vdGUhICAqKiBUaGUgbmV3IGRlZmluaXRpb25zIG9mIHN1c2NlcHRpYmxlL3Jlc2lzdGFudCBhcmUgdGlnaHRlcgp0aGFuIGV2ZXIgYmVmb3JlLCBhcyBhIHJlc3VsdCB0aGVyZSBhcmUgbm8gbG9uZ2VyIGFueSBhbWJpZ3VvdXMKc2FtcGxlcy4gIFRodXMgSSByZW1vdmVkIHRoZSBhbWJpZ3VvdXMgY29udHJhc3RzIGluIHRoZSBmb2xsb3dpbmcgYmxvY2suCgpgYGB7cn0Kenltb2RlbWVfa2VlcGVyIDwtIGxpc3QoCiAgInp5bW9kZW1lIiA9IGMoInoyMyIsICJ6MjIiKSkKc3VzY2VwdGliaWxpdHlfa2VlcGVycyA8LSBsaXN0KAogICJyZXNpc3RhbnRfc2Vuc2l0aXZlIiA9IGMoInJlc2lzdGFudCIsICJzZW5zaXRpdmUiKSkKIyMgICAgInJlc2lzdGFudF9hbWJpZ3VvdXMiID0gYygicmVzaXN0YW50IiwgImFtYmlndW91cyIpLAojIyAgICAic2Vuc2l0aXZlX2FtYmlndW91cyIgPSBjKCJzZW5zaXRpdmUiLCAiYW1iaWd1b3VzIikpCmBgYAoKIyBQYXJhc2l0ZSBPbnRvbG9neSBkYXRhCgpKdXN0IGEgcmVtaW5kZXIgdGhhdCBpbiBkYXRhX3N0cnVjdHVyZXMuUm1kIEkgY3JlYXRlZCBscF9nbyBhbmQgbHBfbGVuZ3RocwoKIyMgWnltb2RlbWUgZW56eW1lIGdlbmUgSURzCgpOYWppYiByZWFkIG1lIGFuIGVtYWlsIGxpc3Rpbmcgb2ZmIHRoZSBnZW5lIG5hbWVzIGFzc29jaWF0ZWQgd2l0aCB0aGUgenltb2RlbWUKY2xhc3NpZmljYXRpb24uICBJIHRvb2sgdGhvc2UgbmFtZXMgYW5kIGNyb3NzIHJlZmVyZW5jZWQgdGhlbSBhZ2FpbnN0IHRoZQpMZWlzaG1hbmlhIHBhbmFtZW5zaXMgZ2VuZSBhbm5vdGF0aW9ucyBhbmQgZm91bmQgdGhlIGZvbGxvd2luZzoKClRoZXkgYXJlOgoKMS4gQUxBVDogTFBBTDEzXzEyMDAxMDkwMCAtLSBhbGFuaW5lIGFtaW5vdHJhbnNmZXJhc2UKMi4gQVNBVDogTFBBTDEzXzM0MDAxMzAwMCAtLSBhc3BhcnRhdGUgYW1pbm90cmFuc2ZlcmFzZQozLiBHNlBEOiBMUEFMMTNfMDAwMDU0MTAwIC0tIGdsdWNhc2UtNi1waG9zcGhhdGUgMS1kZWh5ZHJvZ2VuYXNlCjQuIE5IOiBMUEFMMTNfMTQwMDYxMDAsIExQQUwxM18xODAwMTg1MDAgLS0gaW5vc2luZS1ndWFuaW5lIG51Y2xlb3NpZGUgaHlkcm9sYXNlCjUuIE1QSTogTFBBTDEzXzMyMDAyMjMwMCAobWF5YmUpIC0tIG1hbm5vc2UgcGhvc3BoYXRlIGlzb21lcmFzZSAoSSBjaG9zZSBwaG9zcGhvbWFubm9zZSBpc29tZXJhc2UpCgpHaXZlbiB0aGVzZSA2IGdlbmUgSURzIChOSCBoYXMgdHdvIGdlbmUgSURzIGFzc29jaWF0ZWQgd2l0aCBpdCksIEkgY2FuIGRvIHNvbWUKbG9va2luZyBmb3Igc3BlY2lmaWMgZGlmZmVyZW5jZXMgYW1vbmcgdGhlIHZhcmlvdXMgc2FtcGxlcy4KCiMjIyBFeHByZXNzaW9uIGxldmVscyBvZiB6eW1vZGVtZSBnZW5lcwoKVGhlIGZvbGxvd2luZyBjcmVhdGVzIGEgY29sb3JzcGFjZSAocmVkIHRvIGdyZWVuKSBoZWF0bWFwIHNob3dpbmcgdGhlIG9ic2VydmVkCmV4cHJlc3Npb24gb2YgdGhlc2UgZ2VuZXMgaW4gZXZlcnkgc2FtcGxlLgoKYGBge3J9Cm15X2dlbmVzIDwtIGMoIkxQQUwxM18xMjAwMTA5MDAiLCAiTFBBTDEzXzM0MDAxMzAwMCIsICJMUEFMMTNfMDAwMDU0MTAwIiwKICAgICAgICAgICAgICAiTFBBTDEzXzE0MDAwNjEwMCIsICJMUEFMMTNfMTgwMDE4NTAwIiwgIkxQQUwxM18zMjAwMjIzMDAiLAogICAgICAgICAgICAgICJvdGhlciIpCm15X25hbWVzIDwtIGMoIkFMQVQiLCAiQVNBVCIsICJHNlBEIiwgIk5IdjEiLCAiTkh2MiIsICJNUEkiLCAib3RoZXIiKQoKenltb19zaXhfZ2VuZXMgPC0gZXhjbHVkZV9nZW5lc19leHB0KGxwX3R3b19zdHJhaW5zLCBpZHMgPSBteV9nZW5lcywgbWV0aG9kID0gImtlZXAiKQpzdHJhaW5fbm9ybSA8LSBub3JtYWxpemVfZXhwdCh6eW1vX3NpeF9nZW5lcywgY29udmVydCA9ICJycGttIiwgZmlsdGVyID0gVFJVRSwgdHJhbnNmb3JtID0gImxvZzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW4gPSAiYW5ub3RfY2RzX2xlbmd0aCIpCgp6eW1vX2hlYXRtYXAgPC0gcGxvdF9zYW1wbGVfaGVhdG1hcChzdHJhaW5fbm9ybSwgcm93X2xhYmVsID0gbXlfbmFtZXMpCnp5bW9faGVhdG1hcAoKbHBfbm9ybSA8LSBub3JtYWxpemVfZXhwdChscF90d29fc3RyYWlucywgZmlsdGVyID0gVFJVRSwgY29udmVydCA9ICJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm0gPSAicXVhbnQiLCB0cmFuc2Zvcm0gPSAibG9nMiIsIGNvbHVtbiA9ICJhbm5vdF9jZHNfbGVuZ3RoIikKenltb19oZWF0bWFwX2FsbCA8LSBwbG90X3NhbXBsZV9oZWF0bWFwKGxwX25vcm0pCnp5bW9faGVhdG1hcF9hbGwKYGBgCgojIyBDb21wYXJlIHRvIGhpZ2hseSBleHByZXNzZWQsIHZhcmlhbnQgZ2VuZXMKCkkgd2FudCB0byBjb21wYXJlIHRoZSBhYm92ZSBoZWF0bWFwIHdpdGggb25lIHdoaWNoIGlzIGNvbXByaXNlZCBvZiBhbGwKZ2VuZXMgd2l0aCBzb21lICdzaWduaWZpY2FudGx5IGhpZ2gnIGV4cHJlc3Npb24gdmFsdWUgYW5kIGFsc28gYQpub3QtbmVnbGlnaWJsZSBjb2VmZmljaWVudCBvZiB2YXJpYW5jZS4KCmBgYHtyfQp6eW1vX2hpZ2hfZ2VuZXMgPC0gbm9ybWFsaXplX2V4cHQobHBfdHdvX3N0cmFpbnMsIGZpbHRlciA9ICJjdiIsIGN2X21pbiA9IDAuOSkKCmhpZ2hfc3RyYWluX25vcm0gPC0gbm9ybWFsaXplX2V4cHQoenltb19oaWdoX2dlbmVzLCBjb252ZXJ0ID0gInJwa20iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm0gPSAicXVhbnQiLCB0cmFuc2Zvcm0gPSAibG9nMiIsIGNvbHVtbiA9ICJhbm5vdF9jZHNfbGVuZ3RoIikKenltb19oZWF0bWFwIDwtIHBsb3Rfc2FtcGxlX2hlYXRtYXAoaGlnaF9zdHJhaW5fbm9ybSwgcm93X2xhYmVsID0gbXlfbmFtZXMpCnp5bW9faGVhdG1hcApgYGAKCkkgdGhpbmsgdGhpcyBwbG90IHN1Z2dlc3RzIHRoYXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHdvIHByaW1hcnkKc3RyYWlucyBpcyBub3QgcmVhbGx5IG9uZSBvZiBhIGZldyBzcGVjaWZpYyBnZW5lcywgYnV0IGluc3RlYWQgYQpnbG9iYWwgcGF0dGVybi4KCiMgWnltb2RlbWUgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24KCiMjIE5vIGF0dGVtcHQgYXQgYmF0Y2ggZXN0aW1hdGlvbgoKYGBge3J9Cnp5bW9fZGVfbm9iYXRjaCA8LSBhbGxfcGFpcndpc2UobHBfenltbywgZmlsdGVyID0gVFJVRSwgbW9kZWxfYmF0Y2ggPSBGQUxTRSwgcGFyYWxsZWwgPSBGQUxTRSkKenltb19kZV9ub2JhdGNoCiMjIEluY2x1ZGluZyB0aGUgcGxvdHMgY2F1c2VzIHRoZSByZGEgZmlsZSB0byBiYWxsb29uIHRvIDMuNEdiIGluIHRoZSBmb2xsb3dpbmcgaW52b2NhdGlvbi4KIyMgUmVtb3ZpbmcgdGhlbSByZXN1bHRzIGluLi4uIGhvbHkgY3JhcCAyLjFNYgp6eW1vX3RhYmxlX25vYmF0Y2ggPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICB6eW1vX2RlX25vYmF0Y2gsIGtlZXBlcnMgPSB6eW1vZGVtZV9rZWVwZXIsIGxhYmVsX2NvbHVtbiA9ICJhbm5vdF9nZW5lX3Byb2R1Y3QiLAogICAgcmRhID0gZ2x1ZSgicmRhL3p5bW9fdGFibGVzX25vYmF0Y2gtdnt2ZXJ9LnJkYSIpLAogICAgZXhjZWwgPSBnbHVlKCJ7ZXhjZWxfb3V0fS9ERV9TdHJhaW4ve3Zlcn0venltb190YWJsZXNfbm9iYXRjaC12e3Zlcn0ueGxzeCIpKQp6eW1vX3RhYmxlX25vYmF0Y2gKenltb19zaWdfbm9iYXRjaCA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgenltb190YWJsZV9ub2JhdGNoLAogICAgYWNjb3JkaW5nX3RvID0gImRlc2VxIiwgY3VycmVudF9pZCA9ICJHSUQiLCByZXF1aXJlZF9pZCA9ICJHSUQiLAogICAgZ210ID0gZ2x1ZSgiZXhjZWwvenltb2RlbWVfbm9iYXRjaC12e3Zlcn0uZ210IiksCiAgICBleGNlbCA9IGdsdWUoIntleGNlbF9vdXR9L0RFX1N0cmFpbi97dmVyfS96eW1vX3NpZ19ub2JhdGNoX2Rlc2VxLXZ7dmVyfS54bHN4IikpCnp5bW9fc2lnX25vYmF0Y2gKYGBgCgojIyMjIEdlbmUgb250b2xvZ3kgY29tcGFyaW5nIHRoZSBzdHJhaW5zCgpUaGVyZSBhcmUgdG9vIGZldyBnZW5lcyBhdCBvdXIgY3VycmVudCBzdHJpbmdlbmNpZXMgZm9yIGEgbWVhbmluZ2Z1bCByZXN1bHQuCgpgYGB7cn0KaW5jcmVhc2VkX3oyMiA8LSB6eW1vX3NpZ19ub2JhdGNoW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInp5bW9kZW1lIl1dCmluY3JlYXNlZF96MjMgPC0genltb19zaWdfbm9iYXRjaFtbImRlc2VxIl1dW1sidXBzIl1dW1sienltb2RlbWUiXV0KejIyX2dvc2VxIDwtIHNpbXBsZV9nb3NlcShpbmNyZWFzZWRfejIyLCBnb19kYiA9IGxwX2dvLCBsZW5ndGhfZGIgPSBscF9sZW5ndGhzKQp6MjNfZ29zZXEgPC0gc2ltcGxlX2dvc2VxKGluY3JlYXNlZF96MjMsIGdvX2RiID0gbHBfZ28sIGxlbmd0aF9kYiA9IGxwX2xlbmd0aHMpCmBgYAoKIyMjIFBsb3QgREUgZ2VuZXMgd2l0aG91dCBiYXRjaCBlc3RpbWF0aW9uL2FkanVzdG1lbnQKCmBgYHtyfQp6eW1vX3RhYmxlX25vYmF0Y2hbWyJwbG90cyJdXVtbInp5bW9kZW1lIl1dW1siZGVzZXFfbWFfcGxvdHMiXV0Kenltb190YWJsZV9ub2JhdGNoW1sicGxvdHMiXV1bWyJ6eW1vZGVtZSJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQpgYGAKCkxvZyByYXRpbywgbWVhbiBhdmVyYWdlIHBsb3QgYW5kIHZvbGNhbm8gcGxvdCBvZiB0aGUgY29tcGFyaXNvbiBvZiB0aGUKdHdvIHByaW1hcnkgenltb2RlbWUgdHJhbnNjcmlwdG9tZXMuICBXaGVuIHRoZSB0cmFuc2NyaXB0b21lcyBvZiB0aGUKdHdvIG1haW4gc3RyYWlucyAoNDMgYW5kIDQxIHNhbXBsZXMgb2YgejIuMyBhbmQgejIuMSkgd2VyZSBjb21wYXJlZAp3aXRob3V0IGFueSBhdHRlbXB0IGF0IGJhdGNoL3N1cnJvZ2F0ZSBlc3RpbWF0aW9uIHdpdGggREVTZXEyLCA0NSBhbmQKODUgZ2VuZXMgd2VyZSBvYnNlcnZlZCBhcyBzaWduaWZpY2FudGx5IGhpZ2hlciBpbiBzdHJhaW4gejIuMyBhbmQgejIuMgpyZXNwZWN0aXZlbHkgdXNpbmcgYSBjdXRvZmYgb2YgMS4wIGxvZ0ZDIGFuZCAwLjA1IEZEUiBhZGp1c3RlZApwLXZhbHVlLiAgVGhlcmUgcmVtYWluIGEgbGFyZ2UgbnVtYmVyIG9mIGdlbmVzIHdoaWNoIGFyZSBsaWtlbHkKc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgYmV0d2VlbiB0aGUgdHdvIHN0cmFpbnMsIGJ1dCBmYWxsIGJlbG93IHRoZQoyLWZvbGQgZGlmZmVyZW5jZSByZXF1aXJlZCBmb3IgJ3NpZ25pZmljYW5jZS4nICBUaGlzIGZvbGxvd3MgcHJpb3IKb2JzZXJ2YXRpb25zIHRoYXQgdGhlIHBhcmFzaXRlIHRyYW5zY3JpcHRvbWVzIGFyZSBjb25zdGl0dWl0aXZlbHkKZXhwcmVzc2VkLgoKV2hlbiB0aGUgc2FtZSBkYXRhIHdhcyBwbG90dGVkIHZpYSBhIHZvbGNhbm8gcGxvdCwgdGhlIHJlbGF0aXZlbHkKc21hbGwgcmFuZ2Ugb2YgZm9sZCBjaGFuZ2VzIGNvbXBhcmVkIHRvIHRoZSBsYXJnZSByYW5nZSBvZiBhZGp1c3RlZApwLXZhbHVlcyBpcyB2aXNpYmxlLgoKIyMgQXR0ZW1wdCBTVkEgZXN0aW1hdGUKCmBgYHtyfQp6eW1vX2RlX3N2YSA8LSBhbGxfcGFpcndpc2UobHBfenltbywgZmlsdGVyID0gVFJVRSwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIikKenltb19kZV9zdmEKenltb190YWJsZV9zdmEgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICB6eW1vX2RlX3N2YSwga2VlcGVycyA9IHp5bW9kZW1lX2tlZXBlciwgbGFiZWxfY29sdW1uID0gImFubm90X2dlbmVfcHJvZHVjdCIsCiAgICByZGEgPSBnbHVlKCJyZGEvenltb190YWJsZXNfc3ZhLXZ7dmVyfS5yZGEiKSwKICAgIGV4Y2VsID0gZ2x1ZSgie2V4Y2VsX291dH0vREVfU3RyYWluL3t2ZXJ9L3p5bW9fdGFibGVzX3N2YS12e3Zlcn0ueGxzeCIpKQp6eW1vX3RhYmxlX3N2YQp6eW1vX3NpZ19zdmEgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIHp5bW9fdGFibGVfc3ZhLAogICAgYWNjb3JkaW5nX3RvID0gImRlc2VxIiwKICAgIGN1cnJlbnRfaWQgPSAiR0lEIiwgcmVxdWlyZWRfaWQgPSAiR0lEIiwKICAgIGdtdCA9IGdsdWUoImV4Y2VsL3p5bW9kZW1lX3N2YS12e3Zlcn0uZ210IiksCiAgICBleGNlbCA9IGdsdWUoIntleGNlbF9vdXR9L0RFX1N0cmFpbi97dmVyfS96eW1vX3NpZ19zdmEtdnt2ZXJ9Lnhsc3giKSkKenltb19zaWdfc3ZhCmBgYAoKIyMjIyBHZW5lIG9udG9sb2d5IGNvbXBhcmluZyB0aGUgc3RyYWlucwoKVGhlcmUgYXJlIHRvbyBmZXcgZ2VuZXMgYXQgb3VyIGN1cnJlbnQgc3RyaW5nZW5jaWVzIGZvciBhIG1lYW5pbmdmdWwgcmVzdWx0LgoKYGBge3J9CmluY3JlYXNlZF96MjIgPC0genltb19zaWdfc3ZhW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInp5bW9kZW1lIl1dCmluY3JlYXNlZF96MjMgPC0genltb19zaWdfc3ZhW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6eW1vZGVtZSJdXQp6MjJfZ29zZXEgPC0gc2ltcGxlX2dvc2VxKGluY3JlYXNlZF96MjIsIGdvX2RiID0gbHBfZ28sIGxlbmd0aF9kYiA9IGxwX2xlbmd0aHMpCnoyM19nb3NlcSA8LSBzaW1wbGVfZ29zZXEoaW5jcmVhc2VkX3oyMywgZ29fZGIgPSBscF9nbywgbGVuZ3RoX2RiID0gbHBfbGVuZ3RocykKYGBgCgojIyMgUGxvdCB6eW1vZGVtZSBERSBnZW5lcyB3aXRoIHN2YSBiYXRjaCBlc3RpbWF0aW9uL2FkanVzdG1lbnQKCldoZW4gZXN0aW1hdGVzIGZyb20gU1ZBIHdlcmUgaW5jbHVkZWQgaW4gdGhlIHN0YXRpc3RpY2FsIG1vZGVsIHVzZWQgYnkKRWRnZVIsIERFU2VxMiwgYW5kIGxpbW1hOyBhIG5lYXJseSBpZGVudGljYWwgdmlldyBvZiB0aGUgZGF0YSBlbWVyZ2VkLgpJIHRoaW5rIHRoaXMgc2hvd3Mgd2l0aCBhIGhpZ2ggZGVncmVlIG9mIGNvbmZpZGVuY2UsIHRoYXQgc3ZhIGlzIG5vdApoYXZpbmcgYSBzaWduaWZpY2FudCBlZmZlY3Qgb24gdGhpcyBkYXRhc2V0LgoKYGBge3J9Cnp5bW9fdGFibGVfc3ZhW1sicGxvdHMiXV1bWyJ6eW1vZGVtZSJdXVtbImRlc2VxX21hX3Bsb3RzIl1dCnp5bW9fdGFibGVfc3ZhW1sicGxvdHMiXV1bWyJ6eW1vZGVtZSJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQpgYGAKCiMgUGFyYXNpdGUgU3VzY2VwdGliaWxpdHkgdG8gRHJ1ZyAoQ3VycmVudCkKClRoaXMgc3VzY2VwdGliaWxpdHkgY29tcGFyaXNvbiBpcyB1c2luZyB0aGUgJ2N1cnJlbnQnIGRhdGFzZXQuCgpOb3RlIGFnYWluOiB3ZSBubyBsb25nZXIgaGF2ZSBhbnkgYW1iaWd1b3VzIHNhbXBsZXMsIHNvIEkgY29tbWVudGVkCm91dCBhIHBvcnRpb24gb2YgdGhlIGZvbGxvd2luZyBibG9jay4KCmBgYHtyfQpzdXNfZGVfbm9iYXRjaCA8LSBhbGxfcGFpcndpc2UobHBfc3VzY2VwdGliaWxpdHksIGZpbHRlciA9IFRSVUUsIG1vZGVsX2JhdGNoID0gRkFMU0UpCnN1c19kZV9ub2JhdGNoCnN1c190YWJsZV9ub2JhdGNoIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIHN1c19kZV9ub2JhdGNoLCBrZWVwZXJzID0gc3VzY2VwdGliaWxpdHlfa2VlcGVycywKICByZGEgPSBnbHVlKCJyZGEvc3VzX3RhYmxlc19ub2JhdGNoLXZ7dmVyfS5yZGEiKSwKICBleGNlbCA9IGdsdWUoIntleGNlbF9vdXR9L0RFX1N1c2NlcHRpYmlsaXR5L3t2ZXJ9L3N1c190YWJsZXNfbm9iYXRjaC12e3Zlcn0ueGxzeCIpKQpzdXNfdGFibGVfbm9iYXRjaApzdXNfc2lnX25vYmF0Y2ggPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICBzdXNfdGFibGVfbm9iYXRjaCwKICBleGNlbCA9IGdsdWUoIntleGNlbF9vdXR9L0RFX1N1c2NlcHRpYmlsaXR5L3t2ZXJ9L3N1c19zaWdfbm9iYXRjaC12e3Zlcn0ueGxzeCIpKQoKc3VzX2RlX3N2YSA8LSBhbGxfcGFpcndpc2UobHBfc3VzY2VwdGliaWxpdHksIGZpbHRlciA9IFRSVUUsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIpCnN1c19kZV9zdmEKc3VzX3RhYmxlX3N2YSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIHN1c19kZV9zdmEsIGtlZXBlcnMgPSBzdXNjZXB0aWJpbGl0eV9rZWVwZXJzLAogICAgcmRhID0gZ2x1ZSgicmRhL3N1c190YWJsZXNfc3ZhLXZ7dmVyfS5yZGEiKSwKICAgIGV4Y2VsID0gZ2x1ZSgie2V4Y2VsX291dH0vREVfU3VzY2VwdGliaWxpdHkve3Zlcn0vc3VzX3RhYmxlc19zdmEtdnt2ZXJ9Lnhsc3giKSkKc3VzX3RhYmxlX3N2YQpzdXNfc2lnX3N2YSA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHN1c190YWJsZV9zdmEsIGFjY29yZGluZ190byA9ICJkZXNlcSIsCiAgICBleGNlbCA9IGdsdWUoIntleGNlbF9vdXR9L0RFX1N1c2NlcHRpYmlsaXR5L3t2ZXJ9L3N1c19zaWdfc3ZhLXZ7dmVyfS54bHN4IikpCnN1c19zaWdfc3ZhCgojIyBUbyBnZXQgYSBtb3JlIHRydWUgc2Vuc2Ugb2Ygc2Vuc2l0aXZlIHZzIHJlc2lzdGFudCB3aXRoIHN2YSwgd2Uga2luZCBvZiBuZWVkIHRvIGdldCByaWQgb2YgdGhlCiMjIHVua25vd24gc2FtcGxlcyBhbmQgcGVyaGFwcyB0aGUgYW1iaWd1b3VzLgojIyBub19hbWJpZ3VvdXMgPC0gc3Vic2V0X2V4cHQobHBfc3VzY2VwdGliaWxpdHksIHN1YnNldCA9ICJjb25kaXRpb24hPSdhbWJpZ3VvdXMnIikgJT4lCiMjICAgc3Vic2V0X2V4cHQoc3Vic2V0ID0gImNvbmRpdGlvbiE9J3Vua25vd24nIikKIyMgbm9fYW1iaWd1b3VzX2RlX3N2YSA8LSBhbGxfcGFpcndpc2Uobm9fYW1iaWd1b3VzLCBmaWx0ZXIgPSBUUlVFLCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiKQojIyBub19hbWJpZ3VvdXNfZGVfc3ZhCiMjIExldCB1cyBzZWUgaWYgbXkga2VlcGVyIGNvZGUgd2lsbCBmYWlsIGhhcmQgb3Igc29mdCB3aXRoIGV4dHJhIGNvbnRyYXN0cy4uLgojIyBub19hbWJpZ3VvdXNfdGFibGVfc3ZhIDwtIGNvbWJpbmVfZGVfdGFibGVzKAojIyAgICAgbm9fYW1iaWd1b3VzX2RlX3N2YSwga2VlcGVycyA9IHN1c2NlcHRpYmlsaXR5X2tlZXBlcnMsCiMjICAgICBleGNlbCA9IGdsdWUoImV4Y2VsL25vX2FtYmlndW91c190YWJsZXNfc3ZhLXZ7dmVyfS54bHN4IikpCiMjIG5vX2FtYmlndW91c190YWJsZV9zdmEKIyMgbm9fYW1iaWd1b3VzX3NpZ19zdmEgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKIyMgICAgIG5vX2FtYmlndW91c190YWJsZV9zdmEsIGFjY29yZGluZ190byA9ICJkZXNlcSIsCiMjICAgICBleGNlbCA9IGdsdWUoImV4Y2VsL25vX2FtYmlndW91c19zaWdfc3ZhLXZ7dmVyfS54bHN4IikpCiMjIG5vX2FtYmlndW91c19zaWdfc3ZhCmBgYAoKIyMjIyBHZW5lIG9udG9sb2d5IGNvbXBhcmluZyB0aGUgc3VzY2VwdGliaWxpdHkKCmBgYHtyfQpzdXNfc2lnX3N2YQppbmNyZWFzZWRfcmVzaXN0YW50IDwtIHN1c19zaWdfc3ZhW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJyZXNpc3RhbnRfc2Vuc2l0aXZlIl1dCmluY3JlYXNlZF9zZW5zaXRpdmUgPC0gc3VzX3NpZ19zdmFbWyJkZXNlcSJdXVtbImRvd25zIl1dW1sicmVzaXN0YW50X3NlbnNpdGl2ZSJdXQpyZXNpc3RhbnRfZ29zZXEgPC0gc2ltcGxlX2dvc2VxKGluY3JlYXNlZF9yZXNpc3RhbnQsIGdvX2RiID0gbHBfZ28sIGxlbmd0aF9kYiA9IGxwX2xlbmd0aHMpCnNlbnNpdGl2ZV9nb3NlcSA8LSBzaW1wbGVfZ29zZXEoaW5jcmVhc2VkX3NlbnNpdGl2ZSwgZ29fZGIgPSBscF9nbywgbGVuZ3RoX2RiID0gbHBfbGVuZ3RocykKYGBgCgojIyMgUGxvdCBTdXNjZXB0aWJpbGl0eSBERSBnZW5lcyB3aXRoIHN2YSBiYXRjaCBlc3RpbWF0aW9uL2FkanVzdG1lbnQKCmBgYHtyfQpzdXNfdGFibGVfbm9iYXRjaFtbInBsb3RzIl1dW1sicmVzaXN0YW50X3NlbnNpdGl2ZSJdXVtbImRlc2VxX21hX3Bsb3RzIl1dCnN1c190YWJsZV9ub2JhdGNoW1sicGxvdHMiXV1bWyJyZXNpc3RhbnRfc2Vuc2l0aXZlIl1dW1siZGVzZXFfdm9sX3Bsb3RzIl1dCgpzdXNfdGFibGVfc3ZhW1sicGxvdHMiXV1bWyJyZXNpc3RhbnRfc2Vuc2l0aXZlIl1dW1siZGVzZXFfbWFfcGxvdHMiXV0Kc3VzX3RhYmxlX3N2YVtbInBsb3RzIl1dW1sicmVzaXN0YW50X3NlbnNpdGl2ZSJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXQpgYGAKCkdpdmVuIHRoYXQgcmVzaXN0YW5jZS9zZW5zaXRpdml0eSB0ZW5kcyB0byBiZSBjb3JyZWxhdGVkIHdpdGggc3RyYWluLApvbmUgbWlnaHQgZXhwZWN0IHNpbWlsYXIgcmVzdWx0cy4gIE9uZSBjYXZlYXQgaW4gdGhpcyBjb250ZXh0IHRob3VnaDoKdGhlcmUgYXJlIGZld2VyIHN0cmFpbnMgd2l0aCByZXNpc3RhbmNlL3NlbnNpdGl2aXR5IGRlZmluaXRpb25zLiAgVGhpcwp3aGVuIHRoZSBhbmFseXNpcyB3YXMgcmVwZWF0ZWQgd2l0aG91dCB0aGUgYW1iaWd1b3VzL3Vua25vd24gc2FtcGxlcywKYSBmZXcgbW9yZSBnZW5lcyB3ZXJlIG9ic2VydmVkIGFzIHNpZ25pZmljYW50LgoKIyBDb21wYXJpbmcgREUgcmVzdWx0cyBmcm9tIHN0cmFpbi9zZW5zaXRpdml0eQoKYGBge3J9CiMjIHp5bW9fdGFibGVfc3ZhW1sicGxvdHMiXV1bWyJ6eW1vZGVtZSJdXVtbImRlc2VxX21hX3Bsb3RzIl1dW1sicGxvdCJdXQp6eV9kZiA8LSB6eW1vX3RhYmxlX3N2YVtbImRhdGEiXV1bWyJ6eW1vZGVtZSJdXQpzdXNfZGYgPC0gc3VzX3RhYmxlX3N2YVtbImRhdGEiXV1bWyJyZXNpc3RhbnRfc2Vuc2l0aXZlIl1dCgpib3RoX2RmIDwtIG1lcmdlKHp5X2RmLCBzdXNfZGYsIGJ5ID0gInJvdy5uYW1lcyIpCnBsb3RfZGYgPC0gYm90aF9kZlssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXQpyb3duYW1lcyhwbG90X2RmKSA8LSBib3RoX2RmW1siUm93Lm5hbWVzIl1dCmNvbG5hbWVzKHBsb3RfZGYpIDwtIGMoInoyM192c196MjIiLCAic2Vuc2l0aXZlX3ZzX3Jlc2lzdGFudCIpCgpjb21wYXJlIDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIocGxvdF9kZikKcHAoZmlsZSA9ICJpbWFnZXMvY29tcGFyZV9zdXNfenkucG5nIikKY29tcGFyZSRzY2F0dGVyCmRldi5vZmYoKQpjb21wYXJlJHNjYXR0ZXIKY29tcGFyZSRjb3IKYGBgCgojIFBhcmFzaXRlIFN1c2NlcHRpYmlsaXR5IHRvIERydWcgKEhpc3RvcmljYWwpCgpUaGlzIHN1c2NlcHRpYmlsaXR5IGNvbXBhcmlzb24gaXMgdXNpbmcgdGhlIGhpc3RvcmljYWwgZGF0YXNldC4KCmBgYHtyfQpzdXNoaXN0X2RlX25vYmF0Y2ggPC0gYWxsX3BhaXJ3aXNlKGxwX3N1c2NlcHRpYmlsaXR5X2hpc3RvcmljYWwsIGZpbHRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfYmF0Y2ggPSBGQUxTRSkKc3VzaGlzdF9kZV9ub2JhdGNoCnN1c2hpc3RfdGFibGVfbm9iYXRjaCA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBzdXNoaXN0X2RlX25vYmF0Y2gsIGtlZXBlcnMgPSBzdXNjZXB0aWJpbGl0eV9rZWVwZXJzLAogIGV4Y2VsID0gZ2x1ZSgie2V4Y2VsX291dH0vREVfU3VzY2VwdGliaWxpdHkvc3VzaGlzdF90YWJsZXNfbm9iYXRjaC12e3Zlcn0ueGxzeCIpKQpzdXNoaXN0X3RhYmxlX25vYmF0Y2gKc3VzaGlzdF9zaWdfbm9iYXRjaCA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHN1c2hpc3RfdGFibGVfbm9iYXRjaCwKICBleGNlbCA9IGdsdWUoIntleGNlbF9vdXR9L0RFX1N1c2NlcHRpYmlsaXR5L3N1c2hpc3Rfc2lnX25vYmF0Y2gtdnt2ZXJ9Lnhsc3giKSkKc3VzaGlzdF9zaWdfbm9iYXRjaAoKc3VzaGlzdF9kZV9zdmEgPC0gYWxsX3BhaXJ3aXNlKGxwX3N1c2NlcHRpYmlsaXR5X2hpc3RvcmljYWwsIGZpbHRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiKQpzdXNoaXN0X2RlX3N2YQpzdXNoaXN0X3RhYmxlX3N2YSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBzdXNoaXN0X2RlX3N2YSwga2VlcGVycyA9IHN1c2NlcHRpYmlsaXR5X2tlZXBlcnMsCiAgZXhjZWwgPSBnbHVlKCJ7ZXhjZWxfb3V0fS9ERV9TdXNjZXB0aWJpbGl0eS9zdXNoaXN0X3RhYmxlc19zdmEtdnt2ZXJ9Lnhsc3giKSkKc3VzaGlzdF90YWJsZV9zdmEKc3VzaGlzdF9zaWdfc3ZhIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgc3VzaGlzdF90YWJsZV9zdmEsIGFjY29yZGluZ190byA9ICJkZXNlcSIsCiAgZXhjZWwgPSBnbHVlKCJ7ZXhjZWxfb3V0fS9ERV9TdXNjZXB0aWJpbGl0eS9zdXNoaXN0X3NpZ19zdmEtdnt2ZXJ9Lnhsc3giKSkKc3VzaGlzdF9zaWdfc3ZhCmBgYAoKIyBDdXJlL0ZhaWwgYXNzb2NpYXRpb24KCmBgYHtyfQojI2NmX25iX2lucHV0IDwtIHN1YnNldF9leHB0KGNmX2V4cHQsIHN1YnNldD0iY29uZGl0aW9uIT0ndW5rbm93biciKQpjZl9kZV9ub2JhdGNoIDwtIGFsbF9wYWlyd2lzZShscF9jZl9rbm93biwgZmlsdGVyID0gVFJVRSwgbW9kZWxfYmF0Y2ggPSBGQUxTRSkKY2ZfZGVfbm9iYXRjaApjZl90YWJsZV9ub2JhdGNoIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIGNmX2RlX25vYmF0Y2gsCiAgZXhjZWwgPSBnbHVlKCJ7ZXhjZWxfb3V0fS9ERV9DdXJlX3ZzX0ZhaWwve3Zlcn0vY2ZfdGFibGVzX25vYmF0Y2gtdnt2ZXJ9Lnhsc3giKSkKY2ZfdGFibGVfbm9iYXRjaApjZl9zaWdfbm9iYXRjaCA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGNmX3RhYmxlX25vYmF0Y2gsCiAgZXhjZWwgPSBnbHVlKCJ7ZXhjZWxfb3V0fS9ERV9DdXJlX3ZzX0ZhaWwve3Zlcn0vY2Zfc2lnX25vYmF0Y2gtdnt2ZXJ9Lnhsc3giKSkKY2Zfc2lnX25vYmF0Y2gKCmNmX2RlIDwtIGFsbF9wYWlyd2lzZShscF9jZl9rbm93biwgZmlsdGVyID0gVFJVRSwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIikKY2ZfZGUKY2ZfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgY2ZfZGUsCiAgZXhjZWwgPSBnbHVlKCJ7ZXhjZWxfb3V0fS9ERV9DdXJlX3ZzX0ZhaWwve3Zlcn0vY2ZfdGFibGVzLXZ7dmVyfS54bHN4IikpCmNmX3RhYmxlCmNmX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIGNmX3RhYmxlLAogIGV4Y2VsID0gZ2x1ZSgie2V4Y2VsX291dH0vREVfQ3VyZV92c19GYWlsL3t2ZXJ9L2NmX3NpZy12e3Zlcn0ueGxzeCIpKQpjZl9zaWcKYGBgCgpJIGFtIG5vdCBnb2luZyB0byBtZXNzIHdpdGggR08gc2VhcmNoZXMgZm9yIHRoaXMuCgojIyBDdXJlL0ZhaWwgREUgcGxvdHMKCkl0IGlzIG5vdCBzdXJwcmlzaW5nIHRoYXQgZmV3IG9yIG5vIGdlbmVzIGFyZSBkZWVtZWQgc2lnbmlmaWNhbnRseQpkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYWNyb3NzIHNhbXBsZXMgd2hpY2ggd2VyZSB0YWtlbiBmcm9tIGN1cmUgb3IKZmFpbCBwYXRpZW50cy4KCmBgYHtyfQpjZl90YWJsZV9ub2JhdGNoW1sicGxvdHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bWyJkZXNlcV9tYV9wbG90cyJdXQoKZGV2IDwtIHBwKGZpbGUgPSAiaW1hZ2VzL2NmX21hLnBuZyIpCmNmX3RhYmxlW1sicGxvdHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bWyJkZXNlcV9tYV9wbG90cyJdXQpjbG9zZWQgPC0gZGV2Lm9mZigpCmNmX3RhYmxlW1sicGxvdHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bWyJkZXNlcV9tYV9wbG90cyJdXQpgYGAKCiMgQ29tYmluaW5nIHRoZSBtYWNyb3BoYWdlIGluZmVjdGVkIGFtYXN0aWdvdGVzIHdpdGggaW4tdml0cm8gcHJvbWFzdGlnb3RlcwoKT25lIHF1ZXJ5IHdlIGhhdmUgbm90IHlldCBhZGRyZXNzZWQ6IHdoYXQgYXJlIHRoZSBzaW1pbGFyaXRpZXMgYW5kCmRpZmZlcmVuY2VzIGFtb25nIHRoZSBzdHJhaW5zIHVzZWQgdG8gaW5mZWN0IHRoZSBtYWNyb3BoYWdlIHNhbXBsZXMKYW5kIHRoZSBwcm9tYXN0aWdvdGUgc2FtcGxlcyB1c2VkIGluIHRoZSBUTVJDMiBwYXJhc2l0ZSBkYXRhPwoKSW4gbXkgY29udGFpbmVyIGltYWdlLCB0aGlzIGRhdGFzZXQgaXMgbm90IGN1cnJlbnRseSBsb2FkZWQsIHNvIHR1cm5pbmcgdGhpcyBvZmYuCgpgYGB7cn0KIyMgSSBqdXN0IGZpeGVkIHRoaXMgaW4gdGhlIGRhdGFzZXRzIFJtZCwgYnV0IHVudGlsIHRoYXQgcHJvcGFnYXRlcyBqdXN0IHNldCBpdCBtYW51YWxseQphbm5vdGF0aW9uKGxwX2V4cHQpIDwtIGFubm90YXRpb24obHBfbWFjcm9waGFnZSkKdG1yYzJfbWFjcm9waGFnZV9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KGxwX21hY3JvcGhhZ2UsIHRyYW5zZm9ybT0ibG9nMiIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtPSJxdWFudCIsIGZpbHRlcj1UUlVFKQphbGxfdG1yYzIgPC0gY29tYmluZV9leHB0cyhscF9leHB0LCBscF9tYWNyb3BoYWdlKQoKYWxsX25vc2IgPC0gYWxsX3RtcmMyCnBEYXRhKGFsbF9ub3NiKVtbInN0YWdlIl1dIDwtICJwcm9tYXN0aWdvdGUiCm5hX2lkeCA8LSBpcy5uYShwRGF0YShhbGxfbm9zYilbWyJtYWNyb3BoYWdldHJlYXRtZW50Il1dKQpwRGF0YShhbGxfbm9zYilbbmFfaWR4LCAibWFjcm9waGFnZXRyZWF0bWVudCJdIDwtICJ1bmRlZmluZWQiCmFsbF9ub3NiIDwtIHN1YnNldF9leHB0KGFsbF9ub3NiLCBzdWJzZXQgPSAibWFjcm9waGFnZXRyZWF0bWVudCE9J2luZl9zYiciKQphbWFfaWR4IDwtIHBEYXRhKGFsbF9ub3NiKVtbIm1hY3JvcGhhZ2V0cmVhdG1lbnQiXV0gPT0gImluZiIKcERhdGEoYWxsX25vc2IpW2FtYV9pZHgsICJzdGFnZSIgXSA8LSAiYW1hc3RpZ290ZSIKcERhdGEoYWxsX25vc2IpW1siYmF0Y2giXV0gPC0gcERhdGEoYWxsX25vc2IpW1sic3RhZ2UiXV0KYGBgCgpJIHRoaW5rIHRoZSBhYm92ZSBwaWN0dXJlIGlzIHNvcnQgb2YgdGhlIG9wcG9zaXRlIG9mIHdoYXQgd2Ugd2FudCB0bwpjb21wYXJlIGluIGEgREUgYW5hbHlzaXMgZm9yIHRoaXMgc2V0IG9mIGRhdGEsIGUuZy4gd2Ugd2FudCB0byBjb21wYXJlCnByb21hc3RpZ290ZXMgZnJvbSBhbWFzdGlnb3Rlcz8KCmBgYHtyfQphbGxfbm9zYiA8LSBzZXRfZXhwdF9iYXRjaGVzKGFsbF9ub3NiLCBmYWN0ID0gImNvbmRpdGlvbiIpICU+JQogIHNldF9leHB0X2NvbmRpdGlvbnMoZmFjdCA9ICJzdGFnZSIpCnR3b196eW1vIDwtIHN1YnNldF9leHB0KAogIGFsbF9ub3NiLAogIHN1YnNldCA9ICJ6eW1vZGVtZWNhdGVnb3JpY2FsPT0nejIyJ3x6eW1vZGVtZWNhdGVnb3JpY2FsPT0nejIzJ3x6eW1vZGVtZWNhdGVnb3JpY2FsPT0ndW5rbm93biciKQoKcHJvX2FtYSA8LSBhbGxfcGFpcndpc2UoYWxsX25vc2IsIGZpbHRlciA9IFRSVUUsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIpCnByb19hbWFfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgcHJvX2FtYSwKICBleGNlbCA9IGdsdWUoIntleGNlbF9vdXR9L0RFX3Byb21hc3RpZ290ZV9hbWFzdGlnb3RlL3t2ZXJ9L3Byb192c19hbWFfdGFibGUtdnt2ZXJ9Lnhsc3giKSkKcHJvX2FtYV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIHByb19hbWFfdGFibGUsCiAgICBleGNlbCA9IGdsdWUoIntleGNlbF9vdXR9L0RFX3Byb21hc3RpZ290ZV9hbWFzdGlnb3RlL3t2ZXJ9L3Byb192c19hbWFfc2lnLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMjIyBHZW5lIG9udG9sb2d5IGNvbXBhcmluZyB0aGUgbGlmZSBzdGFnZXMKCmBgYHtyfQppbmNyZWFzZWRfcHJvbWFzdGlnb3RlIDwtIHByb19hbWFfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJwcm9tYXN0aWdvdGVfdnNfYW1hc3RpZ290ZSJdXQppbmNyZWFzZWRfYW1hc3RpZ290ZSA8LSBwcm9fYW1hX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJwcm9tYXN0aWdvdGVfdnNfYW1hc3RpZ290ZSJdXQpwcm9tYXN0aWdvdGVfZ29zZXEgPC0gc2ltcGxlX2dvc2VxKGluY3JlYXNlZF9wcm9tYXN0aWdvdGUsIGdvX2RiID0gbHBfZ28sIGxlbmd0aF9kYiA9IGxwX2xlbmd0aHMpCnByb21hc3RpZ290ZV9nb3NlcQphbWFzdGlnb3RlX2dvc2VxIDwtIHNpbXBsZV9nb3NlcShpbmNyZWFzZWRfYW1hc3RpZ290ZSwgZ29fZGIgPSBscF9nbywgbGVuZ3RoX2RiID0gbHBfbGVuZ3RocykKYW1hc3RpZ290ZV9nb3NlcQoKIyMgc2lsbHksIHRvcGdvIHdhbnRzIHRoZSBnZW5lIGlkIGNvbHVtbiB0byBiZSAnSUQnLCBJIHNob3VsZCBmaXggdGhpcy4KY29sbmFtZXMobHBfZ28pIDwtIGMoIklEIiwgIkdPIikKcHJvbWFzdGlnb3RlX3RvcGdvIDwtIHNpbXBsZV90b3BnbyhpbmNyZWFzZWRfcHJvbWFzdGlnb3RlLCBnb19kYiA9IGxwX2dvKQplbnJpY2hwbG90Ojpkb3RwbG90KHByb21hc3RpZ290ZV90b3BnbyRlbnJpY2hfcmVzdWx0cyRicCkKCmFtYXN0aWdvdGVfdG9wZ28gPC0gc2ltcGxlX3RvcGdvKGluY3JlYXNlZF9hbWFzdGlnb3RlLCBnb19kYiA9IGxwX2dvKQplbnJpY2hwbG90Ojpkb3RwbG90KGFtYXN0aWdvdGVfdG9wZ28kZW5yaWNoX3Jlc3VsdHMkYnApCmBgYAoKIyMjIFBsb3QgcHJvbWFzdGlnb3RlL2FtYXN0aWdvdGUgREUgZ2VuZXMKCmBgYHtyfQpwcm9fYW1hX3RhYmxlW1sicGxvdHMiXV1bWyJwcm9tYXN0aWdvdGVfdnNfYW1hc3RpZ290ZSJdXVtbImRlc2VxX21hX3Bsb3RzIl1dCmBgYAoKSSBhbSBhIGxpdHRsZSBzdXJwcmlzZWQgYnkgdGhpcyBwbG90LCBJIHNvbWV3aGF0IGV4cGVjdGVkIHRoZXJlIHRvIGJlCmZldyBnZW5lcyB3aGljaCBwYXNzZWQgdGhlIDItZm9sZCBkaWZmZXJlbmNlIGRlbWFyY2F0aW9uIGxpbmUuCgpgYGB7cn0KcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSkKbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCiMjIG1lc3NhZ2UocGFzdGUwKCJTYXZpbmcgdG8gIiwgc2F2ZWZpbGUpKQojIyB0bXAgPC0gc20oc2F2ZW1lKGZpbGVuYW1lID0gc2F2ZWZpbGUpKQpgYGAKCmBgYHtyLCBldmFsPUZBTFNFfQp0bXAgPC0gbG9hZG1lKGZpbGVuYW1lID0gc2F2ZWZpbGUpCmBgYAo=