Quick xlsx reader
functions
My functions to perform the various overrepresentation/enrichment
analyses generally assume the result of extract_significant_genes() as
the input. Sadly, I do not want to save those data structures to disk
because they can be quite monstrously large when serialized (because I
keep a reference to the input in them which gets dereferenced on
save()). As a result, it is far simpler/safer to just read the xlsx
outputs produced by combine_de_tables and extract_significant_genes.
Ergo the following two little functions.
table_reader <- function(xlsx, sheet = "outcome") {
input_df <- openxlsx::readWorkbook(xlsx, sheet = sheet, startRow = 2)
rownames(input_df) <- input_df[["row.names"]]
input_df[["row.names"]] <- NULL
print(dim(input_df))
if (nrow(input_df) < 5000) {
warning("Something appears wrong with the de table: ", input_xlsx)
}
return(input_df)
}
sig_reader <- function(xlsx, sheet = "outcome", direction = "up") {
this_sheet <- paste0(direction, "_deseq_", sheet)
input_df <- openxlsx::readWorkbook(xlsx, sheet = this_sheet, startRow = 2)
rownames(input_df) <- input_df[["row.names"]]
input_df[["row.names"]] <- NULL
dim(input_df)
if (nrow(input_df) < 20) {
message("There are less than 20 rows in this significance table, it is unlikely to be interesting.")
}
return(input_df)
}
I have been having some difficulties getting the treeplot fonts to
match our readability goals. The set of things I have tried so far
are:
- Setting a geom_text(size = x): this failed because it didn’t know to
which element(s) to apply the new size.
- Changing the options for theme_bw(): this does change some font
elements, but not the ones that I wanted. I tried more than a few, most
importantly theme(text = element_text(size = x))
- Changing the default for theme_bw via theme_update(text =
element_text(size = x)): this also changes some text, but not all.
- Invoking update_geom_defaults(“text”, aes(size = 10)) at the stop of
my document. This does not seem to do much of anything.
- Playing with options in enrichplot::treeplot(), notably the cex and
fontsize options. These also help with some, but not all fonts. I also
spent a fair amount of time reading the code for treeplot() and decided
to try #6 before I got too frustrated.
- Just changing the canvas size of my output pdf. This worked great,
though it may require setting the wordwrap options in treeplot.
With that in mind, the following two parameters are going to set the
width and height of the output pdf documents which will be sent to Maria
Adelaida in order to arrange into the final figures via inkscape.
treeplot_height <- 6
treeplot_width <- 12
wrap_width <- 24
desired_go_ont <- "BP"
Introduction
I once again moved the ontology analyses to their own document. This
is primarily because I want a fresh notebook to play around with these
and get some of the resulting clutter out of the DE notebooks.
The con of doing this is that some of my enrichment methods are smart
enough to directly take the output from
combine_de_tables()/extract_significant_genes(). I guess I can dispatch
a method to take the xlsx file as input…
Thus, for each enrichment analysis that was in the
differential expression documents, there will now be a few stanzas here,
one which loads the appropriate xlsx file, one which performs gProfiler,
and one which uses clusterProfiler. On occasion there may be another
with random stuff like me poking at transcription factors or other side
interests…
In addition, I am going to do the Tumaco-only analyses first, because
they are what are actually in the paper.
Gene Set
Enrichment
The gene set enrichment will follow each DE analysis during this
document. I am adding a series of explicitly GSEA analyses in this most
recent iteration, in these I will pass the full DE table and check the
distribution of logFC values against the genes in each category as
opposed to the simpler over-enrichment of the high/low DE genes.
Most (all?) of the gene set enrichment analyses performed in this
document are a combination of gProfiler2 (Kolberg
et al. (2020)) and clusterProfiler (Yu et
al. (2012)). There are functions available in hpgltools to also
perform a few other methods, but for the moment I am sticking to only
these two. Oh yeah, I need to wrap clusterProfiler’s tree (taken from
topGO) plotter because it spams plots everywhere…
input_xlsx <- glue("analyses/3_cali_and_tumaco/DE_Cure_Fail/Clinical_Samples/tc_clinical_cf_table_sva-v{ver}.xlsx")
all_de_cf_table <- table_reader(input_xlsx, "outcome")
## [1] 12162 76
all_de_cf_up <- sig_reader(glue("analyses/3_cali_and_tumaco/DE_Cure_Fail/Clinical_Samples/tc_clinical_cf_sig_sva-v{ver}.xlsx"), "outcome", "up")
all_de_cf_down <- sig_reader(glue("analyses/3_cali_and_tumaco/DE_Cure_Fail/Clinical_Samples/tc_clinical_cf_sig_sva-v{ver}.xlsx"), "outcome", "down")
all_de_cf <- rbind.data.frame(all_de_cf_up, all_de_cf_down)
tumaco_xlsx <- glue("analyses/4_tumaco/DE_Cure_Fail/t_all_visitcf_sig_sva-v{ver}.xlsx")
t_de_cf <- openxlsx::readWorkbook(tumaco_xlsx, sheet = 3, startRow = 2)
rownames(t_de_cf) <- t_de_cf[["row.names"]]
t_de_cf[["row.names"]] <- NULL
t_de_cf_up <- t_de_cf[, c("deseq_logfc", "deseq_adjp", "deseq_basemean", "deseq_lfcse")]
t_de_cf <- openxlsx::readWorkbook(tumaco_xlsx, sheet = 4, startRow = 2)
rownames(t_de_cf) <- t_de_cf[["row.names"]]
t_de_cf[["row.names"]] <- NULL
t_de_cf_down <- t_de_cf[, c("deseq_logfc", "deseq_adjp", "deseq_basemean", "deseq_lfcse")]
t_de_cf <- rbind.data.frame(t_de_cf_up, t_de_cf_down)
gProfiler search of
all Tumaco samples
The following gProfiler searches use the all_gprofiler() function
instead of simple_gprofiler(). As a result, the results are separated by
{contrast}_{direction}. Thus ‘outcome_down’.
The same plots are available as the previous gProfiler searches, but
in many of the following runs, I used the dotplot() function to get a
slightly different view of the results.
Shared paths
These are the paths from the DE document and which will be used to
get the inputs for gprofiler/clusterprofiler.
xlsx_prefix <- "analyses/4_tumaco"
cf_prefix <- glue("{xlsx_prefix}/DE_Cure_Fail")
All Tumaco clinical
samples cure/fail
The xlsx files are:
- “{cf_prefix}/All_Samples/t_clinical_cf_table_sva-v{ver}.xlsx”
- “{cf_prefix}/All_Samples/t_clinical_cf_sig_sva-v{ver}.xlsx”
input_xlsx <- glue("{cf_prefix}/All_Samples/t_clinical_cf_table_sva-v{ver}.xlsx")
t_clinical_cf_table_sva <- table_reader(input_xlsx, "outcome")
## [1] 14156 76
input_xlsx <- glue("{cf_prefix}/All_Samples/t_clinical_cf_sig_sva-v{ver}.xlsx")
t_clinical_cf_sig_sva_up <- sig_reader(input_xlsx, "outcome")
t_clinical_cf_sig_sva_down <- sig_reader(input_xlsx, "outcome", "down")
And without biopsies
input_xlsx <- glue("{cf_prefix}/All_Samples/t_clinical_nobiop_cf_table_sva-v{ver}.xlsx")
t_clinicalnb_cf_table_sva <- table_reader(input_xlsx, "outcome")
## [1] 11910 82
input_xlsx <- glue("{cf_prefix}/All_Samples/t_clinical_nobiop_cf_sig_sva-v{ver}.xlsx")
t_clinicalnb_cf_sig_sva_up <- sig_reader(input_xlsx, "outcome")
t_clinicalnb_cf_sig_sva_down <- sig_reader(input_xlsx, "outcome", "down")
t_clinicalnb_cf_sig_sva_both <- rbind.data.frame(t_clinicalnb_cf_sig_sva_up,
t_clinicalnb_cf_sig_sva_down)
gProfiler
After most of the DE analyses, the set of significantly DE genes gets
passed to gProfiler2 and clusterProfiler. One slightly neat thing in my
gprofiler (and goseq/topGO/gostats) function(s): it coerces the result
into the same datastructure produced by clusterProfiler, thus one may
play with the various plotting functions in the enrichplot (Yu (n.d.)) package. This is kind of fun because
gProfiler2 provides easy access to a few datasets:
- GO: (Ashburner et al. (2000))
- KEGG: (Kanehisa and Goto (2000))
- Reactome: (Croft et al. (2011))
- WikiPathways: (Kutmon et al.
(2016))
- Transfac: (Wingender et al.
(1996))
- miRTarBase: (Hsu et al. (2011))
- The Human Protein Atlas: (Pontén et al.
(2011))
- Corum: (Giurgiu et al. (2019))
- Human phenotype ontology: (Köhler et al.
(2017))
Genes higher in
cure
My general sense is that the comparisons of primary interest are
reactome and one or more GO. I suspect that if there are lots of
transcription factors, that might prove interesting.
t_cf_clinical_gp_up <- simple_gprofiler(
t_clinical_cf_sig_sva_up,
excel = glue("{xlsx_prefix}/Gene_Set_Overrepresentation/clinical_cure_up_gp-v{ver}.xlsx"))
t_cf_clinical_gp_up
## A set of ontologies produced by gprofiler using 94
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 3 MF
## 48 BP
## 0 KEGG
## 5 REAC
## 3 WP
## 29 TF
## 1 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
go_termsim <- enrichplot::pairwise_termsim(t_cf_clinical_gp_up[["BP_enrich"]])
t_cf_clinical_gp_go_up_tree <- sm(enrichplot::treeplot(go_termsim,
label_format = wrap_width))
pp(file = "images/overrepresentation/t_cf_clinical_gp_up_tree.pdf",
width = treeplot_width, height = treeplot_height)
## Warning in pp(file = "images/overrepresentation/t_cf_clinical_gp_up_tree.pdf",
## : The directory: images/overrepresentation does not exist, will attempt to
## create it.
t_cf_clinical_gp_go_up_tree
dev.off()
## png
## 2
t_cf_clinical_gp_go_up_tree

enrichplot::dotplot(t_cf_clinical_gp_up[["BP_enrich"]])

reactome_termsim <- enrichplot::pairwise_termsim(t_cf_clinical_gp_up[["REAC_enrich"]])
t_cf_clinical_gp_reac_up_tree <- sm(enrichplot::treeplot(reactome_termsim,
label_format = wrap_width))
pp(file = "images/overrepresentation/t_cf_clinical_gp_up_tree.pdf",
width = treeplot_width, height = treeplot_height)
t_cf_clinical_gp_reac_up_tree
dev.off()
## png
## 2
t_cf_clinical_gp_reac_up_tree

pp(file = "images/overrepresentation/t_cf_clinical_gp_up_dot.pdf",
width = treeplot_width, height = treeplot_height)
enrichplot::dotplot(t_cf_clinical_gp_up[["REAC_enrich"]])
dev.off()
## png
## 2
enrichplot::dotplot(t_cf_clinical_gp_up[["REAC_enrich"]])

tf_termsim <- enrichplot::pairwise_termsim(t_cf_clinical_gp_up[["TF_enrich"]])
## The treeplot fails for this for some reason?
##t_cf_clinical_gp_tf_up_tree <- sm(enrichplot::treeplot(tf_termsim))
enrichplot::dotplot(t_cf_clinical_gp_up[["TF_enrich"]])

enrichplot::dotplot(t_cf_clinical_gp_up[["WP_enrich"]])

No biopsies!
t_cf_clinicalnb_gp_up <- simple_gprofiler(
t_clinicalnb_cf_sig_sva_up,
excel = glue("{xlsx_prefix}/Gene_Set_Overrepresentation/clinicalnb_cure_up_gp-v{ver}.xlsx"))
t_cf_clinicalnb_gp_up
## A set of ontologies produced by gprofiler using 140
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 6 MF
## 75 BP
## 0 KEGG
## 6 REAC
## 2 WP
## 41 TF
## 1 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
go_termsim <- enrichplot::pairwise_termsim(t_cf_clinicalnb_gp_up[["BP_enrich"]])
t_cf_clinicalnb_gp_go_up_tree <- sm(enrichplot::treeplot(go_termsim,
label_format = wrap_width))
pp(file = "figures/t_cf_clinicalnb_gp_up_tree.svg",
width = treeplot_width, height = treeplot_height)
t_cf_clinicalnb_gp_go_up_tree
dev.off()
## png
## 2
t_cf_clinicalnb_gp_go_up_tree

enrichplot::dotplot(t_cf_clinicalnb_gp_up[["BP_enrich"]])

reactome_termsim <- enrichplot::pairwise_termsim(t_cf_clinicalnb_gp_up[["REAC_enrich"]])
t_cf_clinicalnb_gp_reac_up_tree <- sm(enrichplot::treeplot(reactome_termsim,
label_format = wrap_width))
pp(file = "images/overrepresentation/t_cf_clinicalnb_gp_up_tree.pdf",
width = treeplot_width, height = treeplot_height)
t_cf_clinicalnb_gp_reac_up_tree
dev.off()
## png
## 2
t_cf_clinicalnb_gp_reac_up_tree

pp(file = "images/overrepresentation/t_cf_clinicalnb_gp_up_dot.pdf",
width = treeplot_width, height = treeplot_height)
enrichplot::dotplot(t_cf_clinicalnb_gp_up[["REAC_enrich"]])
dev.off()
## png
## 2
enrichplot::dotplot(t_cf_clinicalnb_gp_up[["REAC_enrich"]])

tf_termsim <- enrichplot::pairwise_termsim(t_cf_clinicalnb_gp_up[["TF_enrich"]])
## The treeplot fails for this for some reason?
##t_cf_clinicalnb_gp_tf_up_tree <- sm(enrichplot::treeplot(tf_termsim))
enrichplot::dotplot(t_cf_clinicalnb_gp_up[["TF_enrich"]])

enrichplot::dotplot(t_cf_clinicalnb_gp_up[["WP_enrich"]])

Genes higher in
fail
The only significant results for this group appear to be GO.
t_cf_clinical_gp_down <- simple_gprofiler(
t_clinical_cf_sig_sva_down,
excel = glue("{xlsx_prefix}/Gene_Set_Overrepresentation/clinical_fail_up_gp-v{ver}.xlsx"))
t_cf_clinical_gp_down
## A set of ontologies produced by gprofiler using 183
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 9 MF
## 73 BP
## 0 KEGG
## 1 REAC
## 0 WP
## 1 TF
## 1 MIRNA
## 1 HPA
## 0 CORUM
## 0 HP hits.
go_termsim <- enrichplot::pairwise_termsim(t_cf_clinical_gp_down[["BP_enrich"]])
t_cf_clinical_gp_go_down_tree <- sm(enrichplot::treeplot(go_termsim))
pp(file = "images/overrepresentation/t_cf_clinical_gp_down_tree.pdf",
width = treeplot_width, height = treeplot_height)
t_cf_clinical_gp_go_down_tree
dev.off()
## png
## 2
No biopsies!
t_cf_clinicalnb_gp_down <- simple_gprofiler(
t_clinicalnb_cf_sig_sva_down,
excel = glue("{xlsx_prefix}/Gene_Set_Overrepresentation/clinicalnb_fail_up_gp-v{ver}.xlsx"))
t_cf_clinicalnb_gp_down
## A set of ontologies produced by gprofiler using 75
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 6 MF
## 52 BP
## 3 KEGG
## 5 REAC
## 0 WP
## 1 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 1 HP hits.
go_termsim <- enrichplot::pairwise_termsim(t_cf_clinicalnb_gp_down[["BP_enrich"]])
t_cf_clinicalnb_gp_go_down_tree <- sm(enrichplot::treeplot(go_termsim))
pp(file = "images/overrepresentation/t_cf_clinicalnb_gp_down_tree.pdf",
width = treeplot_width, height = treeplot_height)
t_cf_clinicalnb_gp_go_down_tree
dev.off()
## png
## 2
t_cf_clinicalnb_gp_go_down_tree

## And both, this is not usually where I put this, but the
## clinical samples are a bit of a special case.
t_cf_clinicalnb_gp_both <- simple_gprofiler(
t_clinicalnb_cf_sig_sva_both,
excel = glue("{xlsx_prefix}/Gene_Set_Overrepresentation/clinicalnb_fail_up_gp-v{ver}.xlsx"))
t_cf_clinicalnb_gp_both
## A set of ontologies produced by gprofiler using 215
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 11 MF
## 127 BP
## 3 KEGG
## 8 REAC
## 2 WP
## 43 TF
## 1 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
go_termsim <- enrichplot::pairwise_termsim(t_cf_clinicalnb_gp_both[["BP_enrich"]])
t_cf_clinicalnb_gp_go_both_tree <- sm(enrichplot::treeplot(go_termsim))
pp(file = "images/overrepresentation/t_cf_clinicalnb_gp_both_tree.pdf",
width = treeplot_width, height = treeplot_height)
t_cf_clinicalnb_gp_go_both_tree
dev.off()
## png
## 2
t_cf_clinicalnb_gp_go_both_tree

reac_termsim <- enrichplot::pairwise_termsim(t_cf_clinicalnb_gp_both[["REAC_enrich"]])
t_cf_clinicalnb_gp_reac_both_tree <- sm(enrichplot::treeplot(reac_termsim))
pp(file = "images/overrepresentation/t_cf_clinicalnb_gp_both_reac_tree.pdf",
width = treeplot_width, height = treeplot_height)
t_cf_clinicalnb_gp_reac_both_tree
dev.off()
## png
## 2
t_cf_clinicalnb_gp_reac_both_tree

clusterProfiler
The following essentially repeats the gProfiler2 invocation using
clusterProfiler. I have a couple of functions which compare the GO
results from various methods, perhaps I should dig it out and see how
similar the results are using these two tools. My assumption is that the
primary differences should arise from the fact that gProfiler
theoretically is updating their GO data over time and cProfiler uses the
information in org.Hs.eg.db, which afaik has not changed in quite a
while.
Genes higher in
cure
t_cf_clinical_cp_up <- simple_clusterprofiler(
t_clinical_cf_sig_sva_up, de_table = t_clinical_cf_table_sva,
excel = glue("{xlsx_prefix}/Gene_Set_Overrepresentation/clinical_cure_up_cp-v{ver}.xlsx"))
## preparing geneSet collections...
## GSEA analysis...
## leading edge analysis...
## done...
## Reading KEGG annotation online: "https://rest.kegg.jp/link/hsa/pathway"...
## Reading KEGG annotation online: "https://rest.kegg.jp/list/pathway/hsa"...
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Writing a sheet containing the legend.
##
## Writing the BP data.
##
## Loading required namespace: Vennerable
##
## Writing the MF data.
##
## Writing the KEGG data.
##
## Finished writing excel file.
enrichplot::dotplot(t_cf_clinical_cp_up[["enrich_objects"]][["BP_all"]])

Genes higher in
fail
t_cf_clinical_cp_down <- simple_clusterprofiler(
t_clinical_cf_sig_sva_down,
excel = glue("{xlsx_prefix}/Gene_Set_Overrepresentation/clinical_fail_up_cp-v{ver}.xlsx"))
## Unable to find the fold-change column in the de table, not doing gsea.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Writing a sheet containing the legend.
##
## Writing the BP data.
##
## Writing the MF data.
##
## Writing the CC data.
##
## Writing the KEGG data.
##
## Finished writing excel file.
enrichplot::dotplot(t_cf_clinical_cp_down[["enrich_objects"]][["BP_all"]])

GSEA
GSEA is not associated with either up nor down, it takes the rank
order of genes with respect (in this case) to fold-change.
t_cf_clinical_topn_gsea <- plot_topn_gsea(t_cf_clinical_cp_up)
t_cf_clinical_topn_gsea[["GO"]][[1]]

t_cf_clinical_topn_gsea[["GO"]][[2]]

t_cf_clinical_topn_gsea[["GO"]][[3]]

t_cf_clinical_topn_gsea[["GO"]][[4]]

t_cf_clinical_topn_gsea[["GO"]][[5]]

Visit 1 vs. other
visits
The relevant xlsx files are:
- “{xlsx_prefix}/DE_Visits/tv1_vs_later_tables-v{ver}.xlsx”
- “{xlsx_prefix}/DE_Visits/tv1_vs_later_sig-v{ver}.xlsx”
input_xlsx <- glue("{xlsx_prefix}/DE_Visits/tv1_vs_later_tables-v{ver}.xlsx")
tv1_vs_later_table <- table_reader(input_xlsx, "later_vs_first")
## [1] 11910 82
input_xlsx <- glue("{xlsx_prefix}/DE_Visits/tv1_vs_later_sig-v{ver}.xlsx")
tv1_vs_later_up_sig <- sig_reader(input_xlsx, "later_vs_first")
tv1_vs_later_down_sig <- sig_reader(input_xlsx, "later_vs_first", "down")
## There are less than 20 rows in this significance table, it is unlikely to be interesting.
Increased in visit
1
I am not likely to do the decreased in visit 1, there are only 7
genes.
enrichment:
gProfiler
tv1later_up_gp <- simple_gprofiler(
tv1_vs_later_up_sig,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/tv1_vs_later_up_gp-v{ver}.xlsx"))
tv1later_up_gp
## A set of ontologies produced by gprofiler using 24
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 1 MF
## 5 BP
## 0 KEGG
## 3 REAC
## 2 WP
## 1 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
enrichplot::dotplot(tv1later_up_gp[["BP_enrich"]])

enrichplot::dotplot(tv1later_up_gp[["REAC_enrich"]])

enrichment:
clusterProfiler
Note to self: make some classes for plot_topn_gsea so it can handle
the various inputs it is likely to receive.
tv1later_up_cp <- simple_clusterprofiler(
tv1_vs_later_up_sig, de_table = tv1_vs_later_table,
orgdb = "org.Hs.eg.db", kegg_prefix = "hs", do_kegg = TRUE)
## preparing geneSet collections...
## GSEA analysis...
## leading edge analysis...
## done...
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
enrichplot::dotplot(tv1later_up_cp[["enrich_objects"]][["MF_all"]])

enrichplot::dotplot(tv1later_up_cp[["enrich_objects"]][["BP_all"]])

written <- write_cp_data(
tv1later_up_cp,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/tv1_vs_later_up_cp-v{ver}.xlsx"))
## Writing a sheet containing the legend.
## Writing the MF data.
## Writing the CC data.
## Finished writing excel file.
GSEA:
clusterProfiler
tv1later_topn_gsea <- plot_topn_gsea(tv1later_up_cp)
tv1later_topn_gsea[["GO"]][[1]]

tv1later_topn_gsea[["GO"]][[2]]

Patient Sex
The relevant input xlsx files are:
- {xlsx_prefix}/DE_Sex/t_sex_table-v{ver}.xlsx”))
- {xlsx_prefix}/DE_Sex/t_sex_sig-v{ver}.xlsx”))
Oh, I messed up and put the DE results in the GSEA directory!
Let us see if we observe general male/female differences in the data.
This has an important caveat: there are few female failures in the
dataset and so the results may reflect that.
input_xlsx <- glue("{xlsx_prefix}/DE_Sex/t_sex_cure_table-v{ver}.xlsx")
t_sex_table <- table_reader(input_xlsx, "male_vs_female")
## [1] 13971 82
input_xlsx <- glue("{xlsx_prefix}/DE_Sex/t_sex_cure_sig-v{ver}.xlsx")
t_sex_up_sig <- sig_reader(input_xlsx, "male_vs_female")
t_sex_down_sig <- sig_reader(input_xlsx, "male_vs_female", "down")
gProfiler
Increased in
men
t_sex_up_gp <- simple_gprofiler(
t_sex_up_sig,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/sex_male_up_gp-v{ver}.xlsx"))
t_sex_up_gp
## A set of ontologies produced by gprofiler using 176
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 9 MF
## 38 BP
## 2 KEGG
## 7 REAC
## 0 WP
## 35 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 9 HP hits.
enrichplot::dotplot(t_sex_up_gp[["BP_enrich"]])

enrichplot::dotplot(t_sex_up_gp[["REAC_enrich"]])

enrichplot::dotplot(t_sex_up_gp[["TF_enrich"]])

Increased in
women
t_sex_down_gp <- simple_gprofiler(
t_sex_down_sig,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/sex_female_up_gp-v{ver}.xlsx"))
t_sex_down_gp
## A set of ontologies produced by gprofiler using 134
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 0 MF
## 0 BP
## 0 KEGG
## 0 REAC
## 0 WP
## 6 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
Given the results from gProfiler, I do not have high expectations for
clusterProfiler, so I am not likely to take the time to write them out.
It seems like male/female is confounded with cure/fail.
clusterProfiler
Increased in
men
t_sex_up_cp <- simple_clusterprofiler(
t_sex_up_sig, de_table = t_sex_table,
orgdb = "org.Hs.eg.db", kegg_prefix = "hs", do_kegg = TRUE)
## preparing geneSet collections...
## GSEA analysis...
## leading edge analysis...
## done...
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
enrichplot::dotplot(t_sex_up_cp[["enrich_objects"]][["BP_all"]])

Increased in
women
t_sex_down_cp <- simple_clusterprofiler(
t_sex_down_sig, de_table = t_sex_table,
orgdb = "org.Hs.eg.db", kegg_prefix = "hs", do_kegg = TRUE)
## preparing geneSet collections...
## GSEA analysis...
## leading edge analysis...
## done...
enrichplot::dotplot(t_sex_down_cp[["enrich_objects"]][["BP_all"]])

GSEA
t_sex_topn_gsea <- plot_topn_gsea(t_sex_up_cp)
t_sex_topn_gsea[["GO"]][[1]]

Ethnicity
Once again, the relevant files to load:
- “{xlsx_prefix}/DE_Ethnicity/t_ethnicity_table-v{ver}.xlsx”
- “{xlsx_prefix}/DE_Ethnicity/t_ethnicity_sig-v{ver}.xlsx”
input_xlsx <- glue("{xlsx_prefix}/DE_Ethnicity/t_ethnicity_table-v{ver}.xlsx")
t_ethnicity_mestizo_indigenous <- table_reader(input_xlsx, "mestizo_indigenous")
## [1] 14156 82
t_ethnicity_mestizo_afrocol <- table_reader(input_xlsx, "mestizo_afrocol")
## [1] 14156 82
t_ethnicity_indigenous_afrocol <- table_reader(input_xlsx, "indigenous_afrocol")
## [1] 14156 82
input_xlsx <- glue("{xlsx_prefix}/DE_Ethnicity/t_ethnicity_sig-v{ver}.xlsx")
t_ethnicity_mestizo_indigenous_up <- sig_reader(input_xlsx, "mestizo_indigenous")
t_ethnicity_mestizo_indigenous_down <- sig_reader(input_xlsx, "mestizo_indigenous", "down")
t_ethnicity_mestizo_afrocol_up <- sig_reader(input_xlsx, "mestizo_afrocol")
t_ethnicity_mestizo_afrocol_down <- sig_reader(input_xlsx, "mestizo_afrocol", "down")
t_ethnicity_indigenous_afrocol_up <- sig_reader(input_xlsx, "indigenous_afrocol")
t_ethnicity_indigenous_afrocol_down <- sig_reader(input_xlsx, "indigenous_afrocol", "down")
gProfiler
Increased in
mestizo vs indigenous
mestizo_indigenous_up_gp <- simple_gprofiler(
t_ethnicity_mestizo_indigenous_up,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/ethnicity_mi_up_gp-v{ver}.xlsx"))
mestizo_indigenous_up_gp
## A set of ontologies produced by gprofiler using 83
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 1 MF
## 7 BP
## 0 KEGG
## 2 REAC
## 0 WP
## 7 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
Increased in
indigenous vs mestizo
indigenous_mestizo_up_gp <- simple_gprofiler(
t_ethnicity_mestizo_indigenous_down,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/ethnicity_im_up_gp-v{ver}.xlsx"))
indigenous_mestizo_up_gp
## A set of ontologies produced by gprofiler using 97
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 4 MF
## 16 BP
## 3 KEGG
## 4 REAC
## 2 WP
## 1 TF
## 0 MIRNA
## 1 HPA
## 0 CORUM
## 0 HP hits.
Increased in
mestizo vs afrocolombian
mestizo_afrocol_up_gp <- simple_gprofiler(
t_ethnicity_mestizo_afrocol_up,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/ethnicity_ma_up_gp-v{ver}.xlsx"))
mestizo_afrocol_up_gp
## A set of ontologies produced by gprofiler using 57
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 0 MF
## 5 BP
## 0 KEGG
## 0 REAC
## 0 WP
## 0 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
Increased in
afrocolombian vs mestizo
afrocol_mestizo_up_gp <- simple_gprofiler(
t_ethnicity_mestizo_afrocol_down,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/ethnicity_am_up_gp-v{ver}.xlsx"))
afrocol_mestizo_up_gp
## A set of ontologies produced by gprofiler using 92
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 3 MF
## 0 BP
## 0 KEGG
## 1 REAC
## 0 WP
## 7 TF
## 3 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
Increased in
indigenous vs afrocolombian
indigenous_afrocol_up_gp <- simple_gprofiler(
t_ethnicity_indigenous_afrocol_up,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/ethnicity_ia_up_gp-v{ver}.xlsx"))
indigenous_afrocol_up_gp
## A set of ontologies produced by gprofiler using 165
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 6 MF
## 44 BP
## 1 KEGG
## 2 REAC
## 0 WP
## 1 TF
## 0 MIRNA
## 1 HPA
## 0 CORUM
## 0 HP hits.
Increased in
afrocolombian vs indigenous
afrocol_indigenous_up_gp <- simple_gprofiler(
t_ethnicity_indigenous_afrocol_down,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/ethnicity_ai_up_gp-v{ver}.xlsx"))
afrocol_indigenous_up_gp
## A set of ontologies produced by gprofiler using 236
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 6 MF
## 15 BP
## 2 KEGG
## 5 REAC
## 0 WP
## 4 TF
## 1 MIRNA
## 6 HPA
## 0 CORUM
## 1 HP hits.
clusterProfiler
Increased in
mestizo vs indigenous
mestizo_indigenous_up_cp <- simple_clusterprofiler(
t_ethnicity_mestizo_indigenous_up,
de_table = t_ethnicity_mestizo_indigenous)
## preparing geneSet collections...
## GSEA analysis...
## leading edge analysis...
## done...
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## A set of ontologies produced by clusterprofiler.
Increased in
indigenous vs mestizo
indigenous_mestizo_up_cp <- simple_clusterprofiler(
t_ethnicity_mestizo_indigenous_down)
## Unable to find the fold-change column in the de table, not doing gsea.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## A set of ontologies produced by clusterprofiler.
Increased in
mestizo vs afrocolombian
mestizo_afrocol_up_cp <- simple_clusterprofiler(
t_ethnicity_mestizo_afrocol_up,
de_table = t_ethnicity_mestizo_afrocol)
## preparing geneSet collections...
## GSEA analysis...
## leading edge analysis...
## done...
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## A set of ontologies produced by clusterprofiler.
Increased in
afrocolombian vs mestizo
afrocol_mestizo_up_cp <- simple_clusterprofiler(t_ethnicity_mestizo_afrocol_down)
## Unable to find the fold-change column in the de table, not doing gsea.
## A set of ontologies produced by clusterprofiler.
Increased in
indigenous vs afrocolombian
indigenous_afrocol_up_cp <- simple_clusterprofiler(
t_ethnicity_indigenous_afrocol_up,
de_table = t_ethnicity_indigenous_afrocol)
## preparing geneSet collections...
## GSEA analysis...
## leading edge analysis...
## done...
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## A set of ontologies produced by clusterprofiler.
Increased in
afrocolombian vs indigenous
afrocol_indigenous_up_cp <- simple_clusterprofiler(t_ethnicity_indigenous_afrocol_down)
## Unable to find the fold-change column in the de table, not doing gsea.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## A set of ontologies produced by clusterprofiler.
Visit 1
cure/fail
It looks like there are very few groups in the visit 1 significant
genes.
The relevant xlsx files are:
- “{cf_prefix}/Visits/t_clinical_v1_cf_table_sva-v{ver}.xlsx”
- “{cf_prefix}/Visits/t_clinical_v1_cf_sig_sva-v{ver}.xlsx”
input_xlsx <- glue("{cf_prefix}/Visits/t_clinical_v1_cf_table_sva-v{ver}.xlsx")
t_cf_clinical_v1_table_sva <- table_reader(input_xlsx)
## [1] 14023 82
input_xlsx <- glue("{cf_prefix}/Visits/t_clinical_v1_cf_sig_sva-v{ver}.xlsx")
t_cf_clinical_v1_sig_sva_up <- sig_reader(input_xlsx, "outcome")
t_cf_clinical_v1_sig_sva_down <- sig_reader(input_xlsx, "outcome", "down")
gProfiler
Increased in
visit 1 cure/fail
t_cf_clinical_v1_sig_sva_up_gp <- simple_gprofiler(t_cf_clinical_v1_sig_sva_up)
t_cf_clinical_v1_sig_sva_up_gp
## A set of ontologies produced by gprofiler using 27
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 1 MF
## 0 BP
## 0 KEGG
## 0 REAC
## 0 WP
## 0 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
Increased in
visit 1 fail/cure
t_cf_clinical_v1_sig_sva_down_gp <- simple_gprofiler(t_cf_clinical_v1_sig_sva_down)
t_cf_clinical_v1_sig_sva_down_gp
## A set of ontologies produced by gprofiler using 75
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 4 MF
## 15 BP
## 0 KEGG
## 1 REAC
## 1 WP
## 1 TF
## 0 MIRNA
## 0 HPA
## 1 CORUM
## 1 HP hits.
enrichplot::dotplot(t_cf_clinical_v1_sig_sva_down_gp[["BP_enrich"]])

clusterProfiler
Increased visit 1
cure/fail
t_cf_clinical_v1_sig_sva_up_cp <- simple_cprofiler(
t_cf_clinical_v1_sig_sva_up,
de_table = t_cf_clinical_v1_table_sva,
orgdb = "org.Hs.eg.db")
## preparing geneSet collections...
## GSEA analysis...
## leading edge analysis...
## done...
t_cf_clinical_v1_sig_sva_up_cp
## A set of ontologies produced by clusterprofiler.
enrichplot::dotplot(t_cf_clinical_v1_sig_sva_up_cp[["enrich_objects"]][["BP_all"]])

Increased in
visit 1 cure/fail
t_cf_clinical_v1_sig_sva_down_cp <- simple_cprofiler(
t_cf_clinical_v1_sig_sva_down,
orgdb = "org.Hs.eg.db")
## Unable to find the fold-change column in the de table, not doing gsea.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
GSEA
It appears there are too few results to perform the gsea plots.
Cure/Fail,
Biopsies
The relevant xlsx output may be found at:
- “{cf_prefix}/Biopsies/t_biopsy_cf_table_sva-v{ver}.xlsx”
- “{cf_prefix}/Biopsies/t_cf_biopsy_sig_sva-v{ver}.xlsx”
input_xlsx <- glue("{cf_prefix}/Biopsies/t_biopsy_cf_table_sva-v{ver}.xlsx")
t_cf_biopsy_table_sva <- table_reader(input_xlsx, "outcome")
## [1] 13513 82
input_xlsx <- glue("{cf_prefix}/Biopsies/t_cf_biopsy_sig_sva-v{ver}.xlsx")
t_cf_biopsy_sig_sva_up <- sig_reader(input_xlsx, "outcome")
## There are less than 20 rows in this significance table, it is unlikely to be interesting.
t_cf_biopsy_sig_sva_down <- sig_reader(input_xlsx, "outcome", "down")
## There are less than 20 rows in this significance table, it is unlikely to be interesting.
t_cf_biopsy_sig_sva_both <- rbind.data.frame(t_cf_biopsy_sig_sva_up,
t_cf_biopsy_sig_sva_down)
gProfiler
We only have 17 genes in the biopsies, but perhaps they are still
interesting?
increased in cure
vs fail
t_cf_biopsy_sig_sva_gp_up <- simple_gprofiler(
t_cf_biopsy_sig_sva_up,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_biopsy_sig_sva_up_gp-v{ver}.xlsx"))
t_cf_biopsy_sig_sva_gp_up
## A set of ontologies produced by gprofiler using 17
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 9 MF
## 76 BP
## 4 KEGG
## 1 REAC
## 5 WP
## 2 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
enrichplot::dotplot(t_cf_biopsy_sig_sva_gp_up[["BP_enrich"]])

go_termsim <- enrichplot::pairwise_termsim(t_cf_biopsy_sig_sva_gp_up[["BP_enrich"]])
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_cf_biopsy_up_gp_go-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

increased in fail
vs cure
t_cf_biopsy_sig_sva_gp_down <- simple_gprofiler(
t_cf_biopsy_sig_sva_down,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_biopsy_sig_sva_down_gp-v{ver}.xlsx"))
t_cf_biopsy_sig_sva_gp_down
## A set of ontologies produced by gprofiler using 11
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 0 MF
## 0 BP
## 0 KEGG
## 0 REAC
## 0 WP
## 0 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
## Not nearly as interesting
clusterprofiler
Again, clusterprofiler version
increased in
cure/fail
t_cf_biopsy_sig_sva_cp_up <- simple_cprofiler(
t_cf_biopsy_sig_sva_up, de_table = t_cf_biopsy_table_sva,
orgdb = "org.Hs.eg.db",
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_biopsy_sig_sva_up_cp-v{ver}.xlsx"))
## preparing geneSet collections...
## GSEA analysis...
## leading edge analysis...
## done...
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Writing a sheet containing the legend.
##
## Writing the BP data.
##
## Writing the MF data.
##
## Writing the CC data.
##
## Writing the KEGG data.
##
## Finished writing excel file.
enrichplot::dotplot(t_cf_biopsy_sig_sva_cp_up[["enrich_objects"]][["BP_all"]])

GSEA of
cure/fail
t_cf_biopsy_sig_topn_gsea <- plot_topn_gsea(t_cf_biopsy_sig_sva_cp_up)
t_cf_biopsy_sig_topn_gsea[["GO_outcome_up"]][[1]]
## NULL
Eosinophils
cure/fail
input_xlsx <- glue("{cf_prefix}/Eosinophils/t_eosinophil_cf_table_sva-v{ver}.xlsx")
t_cf_eosinophil_table_sva <- table_reader(input_xlsx, "outcome")
## [1] 10532 82
input_xlsx <- glue("{cf_prefix}/Eosinophils/t_eosinophil_cf_sig_sva-v{ver}.xlsx")
t_cf_eosinophil_sig_sva_up <- sig_reader(input_xlsx, "outcome")
t_cf_eosinophil_sig_sva_down <- sig_reader(input_xlsx, "outcome", "down")
t_cf_eosinophil_sig_sva_both <- rbind.data.frame(t_cf_eosinophil_sig_sva_up,
t_cf_eosinophil_sig_sva_down)
gProfiler
increased in
cure vs fail
t_cf_eosinophil_sig_sva_up_gp <- simple_gprofiler(
t_cf_eosinophil_sig_sva_up,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_eosinophil_up_gp-v{ver}.xlsx"))
t_cf_eosinophil_sig_sva_up_gp
## A set of ontologies produced by gprofiler using 116
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 21 MF
## 119 BP
## 2 KEGG
## 7 REAC
## 5 WP
## 68 TF
## 1 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
enrichplot::dotplot(t_cf_eosinophil_sig_sva_up_gp[["BP_enrich"]])

enrichplot::dotplot(t_cf_eosinophil_sig_sva_up_gp[["TF_enrich"]])

go_termsim <- enrichplot::pairwise_termsim(t_cf_eosinophil_sig_sva_up_gp[["BP_enrich"]])
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = "figures/t_cf_eosinophil_up_gp_go.svg",
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

reac_termsim <- enrichplot::pairwise_termsim(t_cf_eosinophil_sig_sva_up_gp[["REAC_enrich"]])
reac_treeplot <- sm(treeplot(reac_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_cf_eosinophil_up_gp_reac-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
reac_treeplot
dev.off()
## png
## 2
increased in
fail vs cure
t_cf_eosinophil_sig_sva_down_gp <- simple_gprofiler(
t_cf_eosinophil_sig_sva_down,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_eosinophil_down_gp-v{ver}.xlsx"))
enrichplot::dotplot(t_cf_eosinophil_sig_sva_down_gp[["BP_enrich"]])

go_termsim <- enrichplot::pairwise_termsim(t_cf_eosinophil_sig_sva_down_gp[["BP_enrich"]])
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_cf_eosinophil_down_gp_go-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

## There is only one reactome hit, so not plotting it.
Both up and
down
I evaluated this and the ‘up’ set next to each other and they are
extremely similar:
up: 148 GO hits, 68 TF, 0 HPA both: 169 GO, 69 TF, and 2 HPA
Otherwise I think they are the same.
t_cf_eosinophil_sig_sva_both_gp <- simple_gprofiler(
t_cf_eosinophil_sig_sva_both,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_eosinophil_both_gp-v{ver}.xlsx"))
t_cf_eosinophil_sig_sva_both_gp
## A set of ontologies produced by gprofiler using 191
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 25 MF
## 138 BP
## 2 KEGG
## 8 REAC
## 6 WP
## 72 TF
## 1 MIRNA
## 2 HPA
## 0 CORUM
## 0 HP hits.
enrichplot::dotplot(t_cf_eosinophil_sig_sva_both_gp[["BP_enrich"]])

go_termsim <- enrichplot::pairwise_termsim(t_cf_eosinophil_sig_sva_both_gp[["BP_enrich"]])
go_treeplot <- sm(treeplot(go_termsim, label_formap = wrap_width))
pp(file = glue("images/overrepresentation/t_cf_eosinophil_both_gp_go-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

reac_termsim <- enrichplot::pairwise_termsim(t_cf_eosinophil_sig_sva_both_gp[["REAC_enrich"]])
reac_treeplot <- sm(treeplot(reac_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_cf_eosinophil_both_gp_reac-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
reac_treeplot
dev.off()
## png
## 2
clusterprofiler
increased in
cure vs fail
t_cf_eosinophil_sig_sva_cp_up <- simple_cprofiler(
t_cf_eosinophil_sig_sva_up, de_table = t_cf_eosinophil_table_sva,
orgdb = "org.Hs.eg.db",
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_eosinophil_sig_sva_up_cp-v{ver}.xlsx"))
## preparing geneSet collections...
## GSEA analysis...
## leading edge analysis...
## done...
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Writing a sheet containing the legend.
##
## Writing the BP data.
##
## Writing the MF data.
##
## Writing the CC data.
##
## Writing the KEGG data.
##
## Finished writing excel file.
enrichplot::dotplot(t_cf_eosinophil_sig_sva_cp_up[["enrich_objects"]][["BP_all"]])

increased in
fail vs cure
t_cf_eosinophil_sig_sva_cp_down <- simple_cprofiler(
t_cf_eosinophil_sig_sva_down,
orgdb = "org.Hs.eg.db",
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_eosinophil_sig_sva_down_cp-v{ver}.xlsx"))
## Unable to find the fold-change column in the de table, not doing gsea.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Writing a sheet containing the legend.
##
## Writing the BP data.
##
## Writing the MF data.
##
## Writing the CC data.
##
## Writing the KEGG data.
##
## Finished writing excel file.
enrichplot::dotplot(t_cf_eosinophil_sig_sva_cp_down[["enrich_objects"]][["BP_all"]])

GSEA
t_cf_eosinophil_sig_topn_gsea <- plot_topn_gsea(t_cf_eosinophil_sig_sva_cp_up)
t_cf_eosinophil_sig_topn_gsea[["GO_outcome_up"]][[1]]
## NULL
Monocytes
cure/fail
input_xlsx <- glue("{cf_prefix}/Monocytes/t_monocyte_cf_table_sva-v{ver}.xlsx")
t_cf_monocyte_table_sva <- table_reader(input_xlsx, "outcome")
## [1] 10862 82
input_xlsx <- glue("{cf_prefix}/Monocytes/t_monocyte_cf_sig_sva-v{ver}.xlsx")
t_cf_monocyte_sig_sva_up <- sig_reader(input_xlsx, "outcome")
t_cf_monocyte_sig_sva_down <- sig_reader(input_xlsx, "outcome", "down")
t_cf_monocyte_sig_sva_both <- rbind.data.frame(t_cf_monocyte_sig_sva_up,
t_cf_monocyte_sig_sva_down)
gProfiler
Now that I am looking back over these results, I am not compeltely
certain why I only did the gprofiler search for the sva data…
increased in
cure vs fail
t_cf_monocyte_sig_sva_up_gp <- simple_gprofiler(
t_cf_monocyte_sig_sva_up,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_monocyte_up_gp-v{ver}.xlsx"))
t_cf_monocyte_sig_sva_up_gp
## A set of ontologies produced by gprofiler using 60
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 0 MF
## 23 BP
## 1 KEGG
## 0 REAC
## 1 WP
## 5 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
enrichplot::dotplot(t_cf_monocyte_sig_sva_up_gp[["BP_enrich"]])

enrichplot::dotplot(t_cf_monocyte_sig_sva_up_gp[["TF_enrich"]])

go_termsim <- enrichplot::pairwise_termsim(t_cf_monocyte_sig_sva_up_gp[["BP_enrich"]])
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = "figures/overrepresentation/t_cf_monocyte_up_gp_go.svg",
height = treeplot_height, width = treeplot_width)
## Warning in pp(file = "figures/overrepresentation/t_cf_monocyte_up_gp_go.svg", :
## The directory: figures/overrepresentation does not exist, will attempt to
## create it.
## png
## 2

increased in
fail vs cure
t_cf_monocyte_sig_sva_down_gp <- simple_gprofiler(
t_cf_monocyte_sig_sva_down,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_monocyte_down_gp-v{ver}.xlsx"))
enrichplot::dotplot(t_cf_monocyte_sig_sva_down_gp[["BP_enrich"]])

go_termsim <- enrichplot::pairwise_termsim(t_cf_monocyte_sig_sva_down_gp[["BP_enrich"]])
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_cf_monocyte_down_gp_go-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

## Insufficient results to make a tree plot.
Both up and
down
t_cf_monocyte_sig_sva_both_gp <- simple_gprofiler(
t_cf_monocyte_sig_sva_both,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_monocyte_both_gp-v{ver}.xlsx"))
t_cf_monocyte_sig_sva_both_gp
## A set of ontologies produced by gprofiler using 112
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 2 MF
## 80 BP
## 3 KEGG
## 1 REAC
## 1 WP
## 8 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
enrichplot::dotplot(t_cf_monocyte_sig_sva_both_gp[["BP_enrich"]])

go_termsim <- enrichplot::pairwise_termsim(t_cf_monocyte_sig_sva_both_gp[["BP_enrich"]])
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_cf_monocyte_both_gp_go-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

## Insufficient results for reactome
tf_termsim <- enrichplot::pairwise_termsim(t_cf_monocyte_sig_sva_both_gp[["TF_enrich"]])
tf_treeplot <- sm(treeplot(tf_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_cf_monocyte_both_gp_tf-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
tf_treeplot
dev.off()
## png
## 2

clusterprofiler
increased in
cure vs fail
t_cf_monocyte_sig_sva_cp_up <- simple_cprofiler(
t_cf_monocyte_sig_sva_up, de_table = t_cf_monocyte_table_sva,
orgdb = "org.Hs.eg.db",
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_monocyte_sig_sva_up_cp-v{ver}.xlsx"))
## preparing geneSet collections...
## GSEA analysis...
## leading edge analysis...
## done...
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Writing a sheet containing the legend.
##
## Writing the BP data.
##
## Writing the KEGG data.
##
## Finished writing excel file.
enrichplot::dotplot(t_cf_monocyte_sig_sva_cp_up[["enrich_objects"]][["BP_all"]])

increased in
fail vs cure
t_cf_monocyte_sig_sva_cp_down <- simple_cprofiler(
t_cf_monocyte_sig_sva_down,
orgdb = "org.Hs.eg.db",
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_monocyte_sig_sva_down_cp-v{ver}.xlsx"))
## Unable to find the fold-change column in the de table, not doing gsea.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Writing a sheet containing the legend.
##
## Writing the BP data.
##
## Writing the MF data.
##
## Writing the CC data.
##
## Writing the KEGG data.
##
## Finished writing excel file.
enrichplot::dotplot(t_cf_monocyte_sig_sva_cp_down[["enrich_objects"]][["BP_all"]])

GSEA
t_cf_monocyte_sig_topn_gsea <- plot_topn_gsea(t_cf_monocyte_sig_sva_cp_up)
t_cf_monocyte_sig_topn_gsea[["GO_outcome_up"]][[1]]
## NULL
Neutrophils
cure/fail
input_xlsx <- glue("{cf_prefix}/Neutrophils/t_neutrophil_cf_table_sva-v{ver}.xlsx")
t_cf_neutrophil_table_sva <- table_reader(input_xlsx, "outcome")
## [1] 9101 82
input_xlsx <- glue("{cf_prefix}/Neutrophils/t_neutrophil_cf_sig_sva-v{ver}.xlsx")
t_cf_neutrophil_sig_sva_up <- sig_reader(input_xlsx, "outcome")
t_cf_neutrophil_sig_sva_down <- sig_reader(input_xlsx, "outcome", "down")
t_cf_neutrophil_sig_sva_both <- rbind.data.frame(t_cf_neutrophil_sig_sva_up,
t_cf_neutrophil_sig_sva_down)
gProfiler
Now that I am looking back over these results, I am not compeltely
certain why I only did the gprofiler search for the sva data…
increased in
cure vs fail
t_cf_neutrophil_sig_sva_up_gp <- simple_gprofiler(
t_cf_neutrophil_sig_sva_up,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_neutrophil_up_gp-v{ver}.xlsx"))
t_cf_neutrophil_sig_sva_up_gp
## A set of ontologies produced by gprofiler using 130
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 4 MF
## 62 BP
## 0 KEGG
## 5 REAC
## 2 WP
## 53 TF
## 1 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
enrichplot::dotplot(t_cf_neutrophil_sig_sva_up_gp[["BP_enrich"]])

enrichplot::dotplot(t_cf_neutrophil_sig_sva_up_gp[["TF_enrich"]])

go_termsim <- enrichplot::pairwise_termsim(t_cf_neutrophil_sig_sva_up_gp[["BP_enrich"]])
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = "figures/t_cf_neutrophil_up_gp_go.svg",
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

increased in
fail vs cure
t_cf_neutrophil_sig_sva_down_gp <- simple_gprofiler(
t_cf_neutrophil_sig_sva_down,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_neutrophil_down_gp-v{ver}.xlsx"))
t_cf_neutrophil_sig_sva_down_gp
## A set of ontologies produced by gprofiler using 30
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 0 MF
## 0 BP
## 1 KEGG
## 0 REAC
## 0 WP
## 2 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 1 HP hits.
## Not much to work with here.
Both up and
down
t_cf_neutrophil_sig_sva_both_gp <- simple_gprofiler(
t_cf_neutrophil_sig_sva_both,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_neutrophil_both_gp-v{ver}.xlsx"))
t_cf_neutrophil_sig_sva_both_gp
## A set of ontologies produced by gprofiler using 160
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 4 MF
## 64 BP
## 0 KEGG
## 5 REAC
## 2 WP
## 55 TF
## 1 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
enrichplot::dotplot(t_cf_neutrophil_sig_sva_both_gp[["BP_enrich"]])

enrichplot::dotplot(t_cf_neutrophil_sig_sva_both_gp[["TF_enrich"]])

go_termsim <- enrichplot::pairwise_termsim(t_cf_neutrophil_sig_sva_both_gp[["BP_enrich"]])
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_cf_neutrophil_both_gp_go-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

## Insufficient results for reactome
clusterprofiler
increased in
cure vs fail
t_cf_neutrophil_sig_sva_cp_up <- simple_cprofiler(
t_cf_neutrophil_sig_sva_up, de_table = t_cf_neutrophil_table_sva,
orgdb = "org.Hs.eg.db",
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_neutrophil_sig_sva_up_cp-v{ver}.xlsx"))
## preparing geneSet collections...
## GSEA analysis...
## leading edge analysis...
## done...
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Writing a sheet containing the legend.
##
## Writing the BP data.
##
## Writing the MF data.
##
## Writing the CC data.
##
## Finished writing excel file.
enrichplot::dotplot(t_cf_neutrophil_sig_sva_cp_up[["enrich_objects"]][["BP_all"]])

increased in
fail vs cure
t_cf_neutrophil_sig_sva_cp_down <- simple_cprofiler(
t_cf_neutrophil_sig_sva_down,
orgdb = "org.Hs.eg.db",
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_neutrophil_sig_sva_down_cp-v{ver}.xlsx"))
## Unable to find the fold-change column in the de table, not doing gsea.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Writing a sheet containing the legend.
##
## Writing the MF data.
##
## Writing the CC data.
##
## Writing the KEGG data.
##
## Finished writing excel file.
enrichplot::dotplot(t_cf_neutrophil_sig_sva_cp_down[["enrich_objects"]][["BP_all"]])

GSEA
t_cf_neutrophil_sig_topn_gsea <- plot_topn_gsea(t_cf_neutrophil_sig_sva_cp_up)
t_cf_neutrophil_sig_topn_gsea[["GO_outcome_up"]][[1]]
## NULL
Look at visit 1 and
see if anything pops out
input_xlsx <- glue("{cf_prefix}/Monocytes/t_monocyte_v1_cf_table_sva-v{ver}.xlsx")
t_cf_monocyte_v1_table_sva <- table_reader(input_xlsx, "outcome")
## [1] 10482 82
input_xlsx <- glue("{cf_prefix}/Monocytes/t_monocyte_v1_cf_sig_sva-v{ver}.xlsx")
t_cf_monocyte_v1_sig_sva_up <- sig_reader(input_xlsx, "outcome")
## There are less than 20 rows in this significance table, it is unlikely to be interesting.
t_cf_monocyte_v1_sig_sva_down <- sig_reader(input_xlsx, "outcome", "down")
t_cf_monocyte_v1_sig_sva_both <- rbind.data.frame(t_cf_monocyte_v1_sig_sva_up,
t_cf_monocyte_v1_sig_sva_down)
Gene Set
Enrichment: gProfiler Monocytes by visit, V1
V1: Up: 14 genes; No categories V1: Down: 52 genes; 20 GO, 5 TF
t_cf_monocyte_v1_sig_sva_up_gp <- simple_gprofiler(
t_cf_monocyte_v1_sig_sva_up,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_neutrophil_up_gp-v{ver}.xlsx"))
t_cf_monocyte_v1_sig_sva_up_gp
## A set of ontologies produced by gprofiler using 14
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 0 MF
## 0 BP
## 0 KEGG
## 0 REAC
## 0 WP
## 0 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
t_cf_monocyte_v1_sig_sva_down_gp <- simple_gprofiler(
t_cf_monocyte_v1_sig_sva_down,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_neutrophil_down_gp-v{ver}.xlsx"))
t_cf_monocyte_v1_sig_sva_down_gp
## A set of ontologies produced by gprofiler using 52
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 2 MF
## 9 BP
## 0 KEGG
## 0 REAC
## 0 WP
## 0 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
t_cf_monocyte_v1_sig_sva_both_gp <- simple_gprofiler(
t_cf_monocyte_v1_sig_sva_both,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_neutrophil_down_gp-v{ver}.xlsx"))
t_cf_monocyte_v1_sig_sva_both_gp
## A set of ontologies produced by gprofiler using 66
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 5 MF
## 4 BP
## 0 KEGG
## 0 REAC
## 0 WP
## 0 TF
## 1 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
I like cats!
clusterProfiler
t_cf_monocyte_v1_sig_sva_up_cp <- simple_cprofiler(t_cf_monocyte_v1_sig_sva_up,
t_cf_monocyte_v1_table_sva,
orgdb = "org.Hs.eg.db")
## preparing geneSet collections...
## GSEA analysis...
## leading edge analysis...
## done...
enrichplot::dotplot(t_cf_monocyte_v1_sig_sva_up_cp[["enrich_objects"]][["BP_all"]])

t_cf_monocyte_v1_topn_gsea <- plot_topn_gsea(t_cf_monocyte_v1_sig_sva_up_cp)
t_cf_monocyte_v1_topn_gsea[["GO_outcome_up"]][[1]]
## NULL
Neutrophils
v1
input_xlsx <- glue("{cf_prefix}/Neutrophils/t_neutrophil_v1_cf_table_sva-v{ver}.xlsx")
t_cf_neutrophil_v1_table_sva <- table_reader(input_xlsx, "outcome")
## [1] 8717 82
input_xlsx <- glue("{cf_prefix}/Neutrophils/t_neutrophil_v1_cf_sig_sva-v{ver}.xlsx")
t_cf_neutrophil_v1_sig_sva_up <- sig_reader(input_xlsx, "outcome")
## There are less than 20 rows in this significance table, it is unlikely to be interesting.
t_cf_neutrophil_v1_sig_sva_down <- sig_reader(input_xlsx, "outcome", "down")
## There are less than 20 rows in this significance table, it is unlikely to be interesting.
t_cf_neutrophil_v1_sig_sva_both <- rbind.data.frame(t_cf_neutrophil_v1_sig_sva_up,
t_cf_neutrophil_v1_sig_sva_down)
Gene Set
Enrichment: gProfiler Neutrophils by visit, V1
t_cf_neutrophil_v1_sig_sva_up_gp <- simple_gprofiler(
t_cf_neutrophil_v1_sig_sva_up,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_neutrophil_up_gp-v{ver}.xlsx"))
## There are only, 5 returning null.
t_cf_neutrophil_v1_sig_sva_up_gp
## NULL
t_cf_neutrophil_v1_sig_sva_down_gp <- simple_gprofiler(
t_cf_neutrophil_v1_sig_sva_down,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_neutrophil_down_gp-v{ver}.xlsx"))
## There are only, 8 returning null.
t_cf_neutrophil_v1_sig_sva_down_gp
## NULL
t_cf_neutrophil_v1_sig_sva_both_gp <- simple_gprofiler(
t_cf_neutrophil_v1_sig_sva_both,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_neutrophil_down_gp-v{ver}.xlsx"))
t_cf_neutrophil_v1_sig_sva_both_gp
## A set of ontologies produced by gprofiler using 13
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 0 MF
## 0 BP
## 0 KEGG
## 0 REAC
## 0 WP
## 0 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
clusterProfiler
t_cf_neutrophil_v1_sig_sva_up_cp <- simple_cprofiler(t_cf_neutrophil_v1_sig_sva_up,
t_cf_neutrophil_v1_table_sva,
orgdb = "org.Hs.eg.db")
## preparing geneSet collections...
## GSEA analysis...
## leading edge analysis...
## done...
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
## Scale for size is already present.
## Adding another scale for size, which will replace the existing scale.
enrichplot::dotplot(t_cf_neutrophil_v1_sig_sva_up_cp[["enrich_objects"]][["BP_all"]])

t_cf_neutrophil_v1_topn_gsea <- plot_topn_gsea(t_cf_neutrophil_v1_sig_sva_up_cp)
t_cf_neutrophil_v1_topn_gsea[["GO_outcome_up"]][[1]]
## NULL
Eosinophils
v1
input_xlsx <- glue("{cf_prefix}/Eosinophils/t_eosinophil_v1_cf_table_sva-v{ver}.xlsx")
t_cf_eosinophil_v1_table_sva <- table_reader(input_xlsx, "outcome")
## [1] 9979 82
input_xlsx <- glue("{cf_prefix}/Eosinophils/t_eosinophil_v1_cf_sig_sva-v{ver}.xlsx")
t_cf_eosinophil_v1_sig_sva_up <- sig_reader(input_xlsx, "outcome")
## There are less than 20 rows in this significance table, it is unlikely to be interesting.
t_cf_eosinophil_v1_sig_sva_down <- sig_reader(input_xlsx, "outcome", "down")
## There are less than 20 rows in this significance table, it is unlikely to be interesting.
t_cf_eosinophil_v1_sig_sva_both <- rbind.data.frame(t_cf_eosinophil_v1_sig_sva_up,
t_cf_eosinophil_v1_sig_sva_down)
Gene Set
Enrichment: gProfiler Eosinophils by visit, V1
t_cf_eosinophil_v1_sig_sva_up_gp <- simple_gprofiler(
t_cf_eosinophil_v1_sig_sva_up,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_eosinophil_up_gp-v{ver}.xlsx"))
t_cf_eosinophil_v1_sig_sva_up_gp
## A set of ontologies produced by gprofiler using 13
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 0 MF
## 0 BP
## 0 KEGG
## 0 REAC
## 0 WP
## 0 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
t_cf_eosinophil_v1_sig_sva_down_gp <- simple_gprofiler(
t_cf_eosinophil_v1_sig_sva_down,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_eosinophil_down_gp-v{ver}.xlsx"))
t_cf_eosinophil_v1_sig_sva_down_gp
## A set of ontologies produced by gprofiler using 19
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 0 MF
## 0 BP
## 1 KEGG
## 1 REAC
## 0 WP
## 1 TF
## 0 MIRNA
## 0 HPA
## 0 CORUM
## 0 HP hits.
t_cf_eosinophil_v1_sig_sva_both_gp <- simple_gprofiler(
t_cf_eosinophil_v1_sig_sva_both,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_eosinophil_down_gp-v{ver}.xlsx"))
t_cf_eosinophil_v1_sig_sva_both_gp
## A set of ontologies produced by gprofiler using 32
## genes against the hsapiens annotations and significance cutoff 0.05.
## There are:
## 0 MF
## 9 BP
## 0 KEGG
## 1 REAC
## 0 WP
## 0 TF
## 0 MIRNA
## 0 HPA
## 1 CORUM
## 0 HP hits.
clusterProfiler
t_cf_eosinophil_v1_sig_sva_up_cp <- simple_cprofiler(t_cf_eosinophil_v1_sig_sva_up,
t_cf_eosinophil_v1_table_sva,
orgdb = "org.Hs.eg.db")
## preparing geneSet collections...
## GSEA analysis...
## leading edge analysis...
## done...
enrichplot::dotplot(t_cf_eosinophil_v1_sig_sva_up_cp[["enrich_objects"]][["BP_all"]])

t_cf_eosinophil_v1_topn_gsea <- plot_topn_gsea(t_cf_eosinophil_v1_sig_sva_up_cp)
t_cf_eosinophil_v1_topn_gsea[["GO_outcome_up"]][[1]]
## NULL
Repeat some of this for
the mixed linear model results
Speaking with Maria Adelaida, it sounds like the most appropriate set
to try for now is |logFC| >= 0.58 and p <= 0.05. I wrote out the
dream results in a simpler and less fun way than everything else.
start_tbl <- table_reader(
glue("excel/mixed_all_celltypes_nobiop_table-v{ver}.xlsx"),
sheet = "contrasts")
## Error in read.xlsx.default(xlsxFile = xlsxFile, sheet = sheet, startRow = startRow, : File does not exist.
sig_up_idx <- start_tbl[["failure_vs_cure_logfc"]] >= 0.58 &
start_tbl[["failure_vs_cure_p_value"]] <= 0.05
## Error in eval(expr, envir, enclos): object 'start_tbl' not found
sig_down_idx <- start_tbl[["failure_vs_cure_logfc"]] <= -0.58 &
start_tbl[["failure_vs_cure_p_value"]] <= 0.05
## Error in eval(expr, envir, enclos): object 'start_tbl' not found
up_genes <- rownames(start_tbl)[sig_up_idx]
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'start_tbl' not found
down_genes <- rownames(start_tbl)[sig_down_idx]
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'start_tbl' not found
t_dream_all_up_gp <- simple_gprofiler(
up_genes,
excel = glue("excel/dream_all_up_gp-v{ver}.xlsx"))
## Error in eval(expr, envir, enclos): object 'up_genes' not found
t_dream_all_down_gp <- simple_gprofiler(
down_genes,
excel = glue("excel/dream_all_down_gp-v{ver}.xlsx"))
## Error in eval(expr, envir, enclos): object 'down_genes' not found
go_termsim <- enrichplot::pairwise_termsim(t_dream_all_up_gp[["BP_enrich"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'pairwise_termsim': object 't_dream_all_up_gp' not found
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_dream_all_up_gp_go-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

go_termsim <- enrichplot::pairwise_termsim(t_dream_all_down_gp[["BP_enrich"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'pairwise_termsim': object 't_dream_all_down_gp' not found
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_dream_all_down_gp_go-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

Monocytes
start_tbl <- table_reader(
glue("excel/mixed_monocyte_table-v{ver}.xlsx"),
sheet = "contrasts")
## Error in read.xlsx.default(xlsxFile = xlsxFile, sheet = sheet, startRow = startRow, : Cannot find sheet named "contrasts"
sig_up_idx <- start_tbl[["failure_vs_cure_logfc"]] >= 0.58 &
start_tbl[["failure_vs_cure_p_value"]] <= 0.05
## Error in eval(expr, envir, enclos): object 'start_tbl' not found
sig_down_idx <- start_tbl[["failure_vs_cure_logfc"]] <= -0.58 &
start_tbl[["failure_vs_cure_p_value"]] <= 0.05
## Error in eval(expr, envir, enclos): object 'start_tbl' not found
up_genes <- rownames(start_tbl)[sig_up_idx]
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'start_tbl' not found
down_genes <- rownames(start_tbl)[sig_down_idx]
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'start_tbl' not found
t_dream_monocyte_up_gp <- simple_gprofiler(
up_genes,
excel = glue("excel/dream_monocyte_up_gp-v{ver}.xlsx"))
## Error in eval(expr, envir, enclos): object 'up_genes' not found
t_dream_all_down_gp <- simple_gprofiler(
down_genes,
excel = glue("excel/dream_monocyte_down_gp-v{ver}.xlsx"))
## Error in eval(expr, envir, enclos): object 'down_genes' not found
go_termsim <- enrichplot::pairwise_termsim(t_dream_all_up_gp[["BP_enrich"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'pairwise_termsim': object 't_dream_all_up_gp' not found
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_dream_monocyte_up_gp_go-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

go_termsim <- enrichplot::pairwise_termsim(t_dream_all_down_gp[["BP_enrich"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'pairwise_termsim': object 't_dream_all_down_gp' not found
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_dream_monocyte_down_gp_go-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

Neutrophils
start_tbl <- table_reader(
glue("excel/mixed_neutrophil_table-v{ver}.xlsx"),
sheet = "contrasts")
## Error in read.xlsx.default(xlsxFile = xlsxFile, sheet = sheet, startRow = startRow, : Cannot find sheet named "contrasts"
sig_up_idx <- start_tbl[["failure_vs_cure_logfc"]] >= 0.58 &
start_tbl[["failure_vs_cure_p_value"]] <= 0.05
## Error in eval(expr, envir, enclos): object 'start_tbl' not found
sig_down_idx <- start_tbl[["failure_vs_cure_logfc"]] <= -0.58 &
start_tbl[["failure_vs_cure_p_value"]] <= 0.05
## Error in eval(expr, envir, enclos): object 'start_tbl' not found
up_genes <- rownames(start_tbl)[sig_up_idx]
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'start_tbl' not found
down_genes <- rownames(start_tbl)[sig_down_idx]
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'start_tbl' not found
t_dream_neutrophil_up_gp <- simple_gprofiler(
up_genes,
excel = glue("excel/dream_neutrophil_up_gp-v{ver}.xlsx"))
## Error in eval(expr, envir, enclos): object 'up_genes' not found
t_dream_all_down_gp <- simple_gprofiler(
down_genes,
excel = glue("excel/dream_neutrophil_down_gp-v{ver}.xlsx"))
## Error in eval(expr, envir, enclos): object 'down_genes' not found
go_termsim <- enrichplot::pairwise_termsim(t_dream_all_up_gp[["BP_enrich"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'pairwise_termsim': object 't_dream_all_up_gp' not found
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_dream_neutrophil_up_gp_go-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

go_termsim <- enrichplot::pairwise_termsim(t_dream_all_down_gp[["BP_enrich"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'pairwise_termsim': object 't_dream_all_down_gp' not found
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_dream_neutrophil_down_gp_go-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

Eosinophils
start_tbl <- table_reader(
glue("excel/mixed_eosinophil_table-v{ver}.xlsx"),
sheet = "contrasts")
## Error in read.xlsx.default(xlsxFile = xlsxFile, sheet = sheet, startRow = startRow, : Cannot find sheet named "contrasts"
sig_up_idx <- start_tbl[["failure_vs_cure_logfc"]] >= 0.58 &
start_tbl[["failure_vs_cure_p_value"]] <= 0.05
## Error in eval(expr, envir, enclos): object 'start_tbl' not found
sig_down_idx <- start_tbl[["failure_vs_cure_logfc"]] <= -0.58 &
start_tbl[["failure_vs_cure_p_value"]] <= 0.05
## Error in eval(expr, envir, enclos): object 'start_tbl' not found
up_genes <- rownames(start_tbl)[sig_up_idx]
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'start_tbl' not found
down_genes <- rownames(start_tbl)[sig_down_idx]
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'start_tbl' not found
t_dream_eosinophil_up_gp <- simple_gprofiler(
up_genes,
excel = glue("excel/dream_eosinophil_up_gp-v{ver}.xlsx"))
## Error in eval(expr, envir, enclos): object 'up_genes' not found
t_dream_all_down_gp <- simple_gprofiler(
down_genes,
excel = glue("excel/dream_eosinophil_down_gp-v{ver}.xlsx"))
## Error in eval(expr, envir, enclos): object 'down_genes' not found
go_termsim <- enrichplot::pairwise_termsim(t_dream_all_up_gp[["BP_enrich"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'pairwise_termsim': object 't_dream_all_up_gp' not found
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_dream_eosinophil_up_gp_go-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

go_termsim <- enrichplot::pairwise_termsim(t_dream_all_down_gp[["BP_enrich"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'pairwise_termsim': object 't_dream_all_down_gp' not found
go_treeplot <- sm(treeplot(go_termsim, label_format = wrap_width))
pp(file = glue("images/overrepresentation/t_dream_eosinophil_down_gp_go-v{ver}.pdf"),
height = treeplot_height, width = treeplot_width)
go_treeplot
dev.off()
## png
## 2

LS0tCnRpdGxlOiAiVE1SQzMgRW5yaWNobWVudCBhbmFseXNlcyBvZiB0aGUgREUgcmVzdWx0czogYHIgU3lzLmdldGVudignVkVSU0lPTicpYCIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKYmlibGlvZ3JhcGh5OiBhdGIuYmliCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICB0aGVtZTogcmVhZGFibGUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KYm9keSAubWFpbi1jb250YWluZXIgewogIG1heC13aWR0aDogMTYwMHB4Owp9CmJvZHksIHRkIHsKICBmb250LXNpemU6IDE2cHg7Cn0KY29kZS5yewogIGZvbnQtc2l6ZTogMTZweDsKfQpwcmUgewogIGZvbnQtc2l6ZTogMTZweAp9Cjwvc3R5bGU+CgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShlbnJpY2hwbG90KQpsaWJyYXJ5KGdnc3RhdHNwbG90KQpsaWJyYXJ5KGdsdWUpCmxpYnJhcnkoaHBnbHRvb2xzKQprbml0cjo6b3B0c19rbml0JHNldChwcm9ncmVzcyA9IFRSVUUsIHZlcmJvc2UgPSBUUlVFLCB3aWR0aCA9IDkwLCBlY2hvID0gVFJVRSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVycm9yID0gVFJVRSwgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDgsIGZpZy5yZXRpbmEgPSAyLAogIG91dC53aWR0aCA9ICIxMDAlIiwgZGV2ID0gInBuZyIsCiAgZGV2LmFyZ3MgPSBsaXN0KHBuZyA9IGxpc3QodHlwZSA9ICJjYWlyby1wbmciKSkpCm9sZF9vcHRpb25zIDwtIG9wdGlvbnMoZGlnaXRzID0gNCwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLCBrbml0ci5kdXBsaWNhdGUubGFiZWwgPSAiYWxsb3ciKQpnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTIpKQp2ZXIgPC0gU3lzLmdldGVudigiVkVSU0lPTiIpCnJ1bmRhdGUgPC0gZm9ybWF0KFN5cy5EYXRlKCksIGZvcm1hdCA9ICIlWSVtJWQiKQpgYGAKCiMgUXVpY2sgeGxzeCByZWFkZXIgZnVuY3Rpb25zCgpNeSBmdW5jdGlvbnMgdG8gcGVyZm9ybSB0aGUgdmFyaW91cyBvdmVycmVwcmVzZW50YXRpb24vZW5yaWNobWVudAphbmFseXNlcyBnZW5lcmFsbHkgYXNzdW1lIHRoZSByZXN1bHQgb2YgZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygpIGFzCnRoZSBpbnB1dC4gIFNhZGx5LCBJIGRvIG5vdCB3YW50IHRvIHNhdmUgdGhvc2UgZGF0YSBzdHJ1Y3R1cmVzIHRvIGRpc2sKYmVjYXVzZSB0aGV5IGNhbiBiZSBxdWl0ZSBtb25zdHJvdXNseSBsYXJnZSB3aGVuIHNlcmlhbGl6ZWQgKGJlY2F1c2UgSQprZWVwIGEgcmVmZXJlbmNlIHRvIHRoZSBpbnB1dCBpbiB0aGVtIHdoaWNoIGdldHMgZGVyZWZlcmVuY2VkIG9uCnNhdmUoKSkuICBBcyBhIHJlc3VsdCwgaXQgaXMgZmFyIHNpbXBsZXIvc2FmZXIgdG8ganVzdCByZWFkIHRoZSB4bHN4Cm91dHB1dHMgcHJvZHVjZWQgYnkgY29tYmluZV9kZV90YWJsZXMgYW5kIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMuCkVyZ28gdGhlIGZvbGxvd2luZyB0d28gbGl0dGxlIGZ1bmN0aW9ucy4KCmBgYHtyfQp0YWJsZV9yZWFkZXIgPC0gZnVuY3Rpb24oeGxzeCwgc2hlZXQgPSAib3V0Y29tZSIpIHsKICBpbnB1dF9kZiA8LSBvcGVueGxzeDo6cmVhZFdvcmtib29rKHhsc3gsIHNoZWV0ID0gc2hlZXQsIHN0YXJ0Um93ID0gMikKICByb3duYW1lcyhpbnB1dF9kZikgPC0gaW5wdXRfZGZbWyJyb3cubmFtZXMiXV0KICBpbnB1dF9kZltbInJvdy5uYW1lcyJdXSA8LSBOVUxMCiAgcHJpbnQoZGltKGlucHV0X2RmKSkKICBpZiAobnJvdyhpbnB1dF9kZikgPCA1MDAwKSB7CiAgICB3YXJuaW5nKCJTb21ldGhpbmcgYXBwZWFycyB3cm9uZyB3aXRoIHRoZSBkZSB0YWJsZTogIiwgaW5wdXRfeGxzeCkKICB9CiAgcmV0dXJuKGlucHV0X2RmKQp9CgpzaWdfcmVhZGVyIDwtIGZ1bmN0aW9uKHhsc3gsIHNoZWV0ID0gIm91dGNvbWUiLCBkaXJlY3Rpb24gPSAidXAiKSB7CiAgdGhpc19zaGVldCA8LSBwYXN0ZTAoZGlyZWN0aW9uLCAiX2Rlc2VxXyIsIHNoZWV0KQogIGlucHV0X2RmIDwtIG9wZW54bHN4OjpyZWFkV29ya2Jvb2soeGxzeCwgc2hlZXQgPSB0aGlzX3NoZWV0LCBzdGFydFJvdyA9IDIpCiAgcm93bmFtZXMoaW5wdXRfZGYpIDwtIGlucHV0X2RmW1sicm93Lm5hbWVzIl1dCiAgaW5wdXRfZGZbWyJyb3cubmFtZXMiXV0gPC0gTlVMTAogIGRpbShpbnB1dF9kZikKICBpZiAobnJvdyhpbnB1dF9kZikgPCAyMCkgewogICAgbWVzc2FnZSgiVGhlcmUgYXJlIGxlc3MgdGhhbiAyMCByb3dzIGluIHRoaXMgc2lnbmlmaWNhbmNlIHRhYmxlLCBpdCBpcyB1bmxpa2VseSB0byBiZSBpbnRlcmVzdGluZy4iKQogIH0KICByZXR1cm4oaW5wdXRfZGYpCn0KYGBgCgpJIGhhdmUgYmVlbiBoYXZpbmcgc29tZSBkaWZmaWN1bHRpZXMgZ2V0dGluZyB0aGUgdHJlZXBsb3QgZm9udHMgdG8KbWF0Y2ggb3VyIHJlYWRhYmlsaXR5IGdvYWxzLiAgVGhlIHNldCBvZiB0aGluZ3MgSSBoYXZlIHRyaWVkIHNvIGZhcgphcmU6CgoxLiAgU2V0dGluZyBhIGdlb21fdGV4dChzaXplID0geCk6IHRoaXMgZmFpbGVkIGJlY2F1c2UgaXQgZGlkbid0IGtub3cKICAgIHRvIHdoaWNoIGVsZW1lbnQocykgdG8gYXBwbHkgdGhlIG5ldyBzaXplLgoyLiAgQ2hhbmdpbmcgdGhlIG9wdGlvbnMgZm9yIHRoZW1lX2J3KCk6IHRoaXMgZG9lcyBjaGFuZ2Ugc29tZSBmb250CiAgICBlbGVtZW50cywgYnV0IG5vdCB0aGUgb25lcyB0aGF0IEkgd2FudGVkLiAgSSB0cmllZCBtb3JlIHRoYW4gYQogICAgZmV3LCBtb3N0IGltcG9ydGFudGx5IHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHgpKQozLiAgQ2hhbmdpbmcgdGhlIGRlZmF1bHQgZm9yIHRoZW1lX2J3IHZpYSB0aGVtZV91cGRhdGUodGV4dCA9CiAgICBlbGVtZW50X3RleHQoc2l6ZSA9IHgpKTogdGhpcyBhbHNvIGNoYW5nZXMgc29tZSB0ZXh0LCBidXQgbm90IGFsbC4KNC4gIEludm9raW5nIHVwZGF0ZV9nZW9tX2RlZmF1bHRzKCJ0ZXh0IiwgYWVzKHNpemUgPSAxMCkpIGF0IHRoZSBzdG9wCiAgICBvZiBteSBkb2N1bWVudC4gIFRoaXMgZG9lcyBub3Qgc2VlbSB0byBkbyBtdWNoIG9mIGFueXRoaW5nLgo1LiAgUGxheWluZyB3aXRoIG9wdGlvbnMgaW4gZW5yaWNocGxvdDo6dHJlZXBsb3QoKSwgbm90YWJseSB0aGUgY2V4CiAgICBhbmQgZm9udHNpemUgb3B0aW9ucy4gIFRoZXNlIGFsc28gaGVscCB3aXRoIHNvbWUsIGJ1dCBub3QgYWxsCiAgICBmb250cy4gIEkgYWxzbyBzcGVudCBhIGZhaXIgYW1vdW50IG9mIHRpbWUgcmVhZGluZyB0aGUgY29kZSBmb3IKICAgIHRyZWVwbG90KCkgYW5kIGRlY2lkZWQgdG8gdHJ5ICM2IGJlZm9yZSBJIGdvdCB0b28gZnJ1c3RyYXRlZC4KNi4gIEp1c3QgY2hhbmdpbmcgdGhlIGNhbnZhcyBzaXplIG9mIG15IG91dHB1dCBwZGYuICBUaGlzIHdvcmtlZAogICAgZ3JlYXQsIHRob3VnaCBpdCBtYXkgcmVxdWlyZSBzZXR0aW5nIHRoZSB3b3Jkd3JhcCBvcHRpb25zIGluCiAgICB0cmVlcGxvdC4KCldpdGggdGhhdCBpbiBtaW5kLCB0aGUgZm9sbG93aW5nIHR3byBwYXJhbWV0ZXJzIGFyZSBnb2luZyB0byBzZXQgdGhlCndpZHRoIGFuZCBoZWlnaHQgb2YgdGhlIG91dHB1dCBwZGYgZG9jdW1lbnRzIHdoaWNoIHdpbGwgYmUgc2VudCB0bwpNYXJpYSBBZGVsYWlkYSBpbiBvcmRlciB0byBhcnJhbmdlIGludG8gdGhlIGZpbmFsIGZpZ3VyZXMgdmlhCmlua3NjYXBlLgoKYGBge3J9CnRyZWVwbG90X2hlaWdodCA8LSA2CnRyZWVwbG90X3dpZHRoIDwtIDEyCndyYXBfd2lkdGggPC0gMjQKZGVzaXJlZF9nb19vbnQgPC0gIkJQIgpgYGAKCiMgSW50cm9kdWN0aW9uCgpJIG9uY2UgYWdhaW4gbW92ZWQgdGhlIG9udG9sb2d5IGFuYWx5c2VzIHRvIHRoZWlyIG93biBkb2N1bWVudC4gIFRoaXMKaXMgcHJpbWFyaWx5IGJlY2F1c2UgSSB3YW50IGEgZnJlc2ggbm90ZWJvb2sgdG8gcGxheSBhcm91bmQgd2l0aCB0aGVzZQphbmQgZ2V0IHNvbWUgb2YgdGhlIHJlc3VsdGluZyBjbHV0dGVyIG91dCBvZiB0aGUgREUgbm90ZWJvb2tzLgoKVGhlIGNvbiBvZiBkb2luZyB0aGlzIGlzIHRoYXQgc29tZSBvZiBteSBlbnJpY2htZW50IG1ldGhvZHMgYXJlIHNtYXJ0CmVub3VnaCB0byBkaXJlY3RseSB0YWtlIHRoZSBvdXRwdXQgZnJvbQpjb21iaW5lX2RlX3RhYmxlcygpL2V4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoKS4gIEkgZ3Vlc3MgSSBjYW4KZGlzcGF0Y2ggYSBtZXRob2QgdG8gdGFrZSB0aGUgeGxzeCBmaWxlIGFzIGlucHV0Li4uCgpUaHVzLCBmb3IgZWFjaCBlbnJpY2htZW50IGFuYWx5c2lzIHRoYXQgX3dhc18gaW4gdGhlIGRpZmZlcmVudGlhbApleHByZXNzaW9uIGRvY3VtZW50cywgdGhlcmUgd2lsbCBub3cgYmUgYSBmZXcgc3RhbnphcyBoZXJlLCBvbmUKd2hpY2ggbG9hZHMgdGhlIGFwcHJvcHJpYXRlIHhsc3ggZmlsZSwgb25lIHdoaWNoIHBlcmZvcm1zIGdQcm9maWxlciwKYW5kIG9uZSB3aGljaCB1c2VzIGNsdXN0ZXJQcm9maWxlci4gIE9uIG9jY2FzaW9uIHRoZXJlIG1heSBiZSBhbm90aGVyCndpdGggcmFuZG9tIHN0dWZmIGxpa2UgbWUgcG9raW5nIGF0IHRyYW5zY3JpcHRpb24gZmFjdG9ycyBvciBvdGhlcgpzaWRlIGludGVyZXN0cy4uLgoKSW4gYWRkaXRpb24sIEkgYW0gZ29pbmcgdG8gZG8gdGhlIFR1bWFjby1vbmx5IGFuYWx5c2VzIGZpcnN0LCBiZWNhdXNlCnRoZXkgYXJlIHdoYXQgYXJlIGFjdHVhbGx5IGluIHRoZSBwYXBlci4KCiMjIEdlbmUgU2V0IEVucmljaG1lbnQKClRoZSBnZW5lIHNldCBlbnJpY2htZW50IHdpbGwgZm9sbG93IGVhY2ggREUgYW5hbHlzaXMgZHVyaW5nIHRoaXMKZG9jdW1lbnQuICBJIGFtIGFkZGluZyBhIHNlcmllcyBvZiBleHBsaWNpdGx5IEdTRUEgYW5hbHlzZXMgaW4gdGhpcwptb3N0IHJlY2VudCBpdGVyYXRpb24sIGluIHRoZXNlIEkgd2lsbCBwYXNzIHRoZSBmdWxsIERFIHRhYmxlIGFuZApjaGVjayB0aGUgZGlzdHJpYnV0aW9uIG9mIGxvZ0ZDIHZhbHVlcyBhZ2FpbnN0IHRoZSBnZW5lcyBpbiBlYWNoCmNhdGVnb3J5IGFzIG9wcG9zZWQgdG8gdGhlIHNpbXBsZXIgb3Zlci1lbnJpY2htZW50IG9mIHRoZSBoaWdoL2xvdyBERQpnZW5lcy4KCk1vc3QgKGFsbD8pIG9mIHRoZSBnZW5lIHNldCBlbnJpY2htZW50IGFuYWx5c2VzIHBlcmZvcm1lZCBpbiB0aGlzCmRvY3VtZW50IGFyZSBhIGNvbWJpbmF0aW9uIG9mIGdQcm9maWxlcjIKKEBrb2xiZXJnR3Byb2ZpbGVyMlBhY2thZ2VHZW5lMjAyMCkgYW5kIGNsdXN0ZXJQcm9maWxlcgooQHl1Q2x1c3RlclByb2ZpbGVyUGFja2FnZUNvbXBhcmluZzIwMTIpLiAgVGhlcmUgYXJlIGZ1bmN0aW9ucwphdmFpbGFibGUgaW4gaHBnbHRvb2xzIHRvIGFsc28gcGVyZm9ybSBhIGZldyBvdGhlciBtZXRob2RzLCBidXQgZm9yCnRoZSBtb21lbnQgSSBhbSBzdGlja2luZyB0byBvbmx5IHRoZXNlIHR3by4gIE9oIHllYWgsIEkgbmVlZCB0byB3cmFwCmNsdXN0ZXJQcm9maWxlcidzIHRyZWUgKHRha2VuIGZyb20gdG9wR08pIHBsb3R0ZXIgYmVjYXVzZSBpdCBzcGFtcwpwbG90cyBfZXZlcnl3aGVyZV8uLi4KCmBgYHtyfQppbnB1dF94bHN4IDwtIGdsdWUoImFuYWx5c2VzLzNfY2FsaV9hbmRfdHVtYWNvL0RFX0N1cmVfRmFpbC9DbGluaWNhbF9TYW1wbGVzL3RjX2NsaW5pY2FsX2NmX3RhYmxlX3N2YS12e3Zlcn0ueGxzeCIpCmFsbF9kZV9jZl90YWJsZSA8LSB0YWJsZV9yZWFkZXIoaW5wdXRfeGxzeCwgIm91dGNvbWUiKQoKYWxsX2RlX2NmX3VwIDwtIHNpZ19yZWFkZXIoZ2x1ZSgiYW5hbHlzZXMvM19jYWxpX2FuZF90dW1hY28vREVfQ3VyZV9GYWlsL0NsaW5pY2FsX1NhbXBsZXMvdGNfY2xpbmljYWxfY2Zfc2lnX3N2YS12e3Zlcn0ueGxzeCIpLCAib3V0Y29tZSIsICJ1cCIpCmFsbF9kZV9jZl9kb3duIDwtIHNpZ19yZWFkZXIoZ2x1ZSgiYW5hbHlzZXMvM19jYWxpX2FuZF90dW1hY28vREVfQ3VyZV9GYWlsL0NsaW5pY2FsX1NhbXBsZXMvdGNfY2xpbmljYWxfY2Zfc2lnX3N2YS12e3Zlcn0ueGxzeCIpLCAib3V0Y29tZSIsICJkb3duIikKYWxsX2RlX2NmIDwtIHJiaW5kLmRhdGEuZnJhbWUoYWxsX2RlX2NmX3VwLCBhbGxfZGVfY2ZfZG93bikKCnR1bWFjb194bHN4IDwtIGdsdWUoImFuYWx5c2VzLzRfdHVtYWNvL0RFX0N1cmVfRmFpbC90X2FsbF92aXNpdGNmX3NpZ19zdmEtdnt2ZXJ9Lnhsc3giKQp0X2RlX2NmIDwtIG9wZW54bHN4OjpyZWFkV29ya2Jvb2sodHVtYWNvX3hsc3gsIHNoZWV0ID0gMywgc3RhcnRSb3cgPSAyKQpyb3duYW1lcyh0X2RlX2NmKSA8LSB0X2RlX2NmW1sicm93Lm5hbWVzIl1dCnRfZGVfY2ZbWyJyb3cubmFtZXMiXV0gPC0gTlVMTAp0X2RlX2NmX3VwIDwtIHRfZGVfY2ZbLCBjKCJkZXNlcV9sb2dmYyIsICJkZXNlcV9hZGpwIiwgImRlc2VxX2Jhc2VtZWFuIiwgImRlc2VxX2xmY3NlIildCnRfZGVfY2YgPC0gb3Blbnhsc3g6OnJlYWRXb3JrYm9vayh0dW1hY29feGxzeCwgc2hlZXQgPSA0LCBzdGFydFJvdyA9IDIpCnJvd25hbWVzKHRfZGVfY2YpIDwtIHRfZGVfY2ZbWyJyb3cubmFtZXMiXV0KdF9kZV9jZltbInJvdy5uYW1lcyJdXSA8LSBOVUxMCnRfZGVfY2ZfZG93biA8LSB0X2RlX2NmWywgYygiZGVzZXFfbG9nZmMiLCAiZGVzZXFfYWRqcCIsICJkZXNlcV9iYXNlbWVhbiIsICJkZXNlcV9sZmNzZSIpXQp0X2RlX2NmIDwtIHJiaW5kLmRhdGEuZnJhbWUodF9kZV9jZl91cCwgdF9kZV9jZl9kb3duKQpgYGAKCiMjIGdQcm9maWxlciBzZWFyY2ggb2YgYWxsIFR1bWFjbyBzYW1wbGVzCgpUaGUgZm9sbG93aW5nIGdQcm9maWxlciBzZWFyY2hlcyB1c2UgdGhlIGFsbF9ncHJvZmlsZXIoKSBmdW5jdGlvbgppbnN0ZWFkIG9mIHNpbXBsZV9ncHJvZmlsZXIoKS4gIEFzIGEgcmVzdWx0LCB0aGUgcmVzdWx0cyBhcmUgc2VwYXJhdGVkCmJ5IHtjb250cmFzdH1fe2RpcmVjdGlvbn0uICBUaHVzICdvdXRjb21lX2Rvd24nLgoKVGhlIHNhbWUgcGxvdHMgYXJlIGF2YWlsYWJsZSBhcyB0aGUgcHJldmlvdXMgZ1Byb2ZpbGVyIHNlYXJjaGVzLCBidXQKaW4gbWFueSBvZiB0aGUgZm9sbG93aW5nIHJ1bnMsIEkgdXNlZCB0aGUgZG90cGxvdCgpIGZ1bmN0aW9uIHRvIGdldCBhCnNsaWdodGx5IGRpZmZlcmVudCB2aWV3IG9mIHRoZSByZXN1bHRzLgoKIyMgU2hhcmVkIHBhdGhzCgpUaGVzZSBhcmUgdGhlIHBhdGhzIGZyb20gdGhlIERFIGRvY3VtZW50IGFuZCB3aGljaCB3aWxsIGJlIHVzZWQgdG8gZ2V0CnRoZSBpbnB1dHMgZm9yIGdwcm9maWxlci9jbHVzdGVycHJvZmlsZXIuCgpgYGB7cn0KeGxzeF9wcmVmaXggPC0gImFuYWx5c2VzLzRfdHVtYWNvIgpjZl9wcmVmaXggPC0gZ2x1ZSgie3hsc3hfcHJlZml4fS9ERV9DdXJlX0ZhaWwiKQpgYGAKCiMjIEFsbCBUdW1hY28gY2xpbmljYWwgc2FtcGxlcyBjdXJlL2ZhaWwKClRoZSB4bHN4IGZpbGVzIGFyZToKCiogIntjZl9wcmVmaXh9L0FsbF9TYW1wbGVzL3RfY2xpbmljYWxfY2ZfdGFibGVfc3ZhLXZ7dmVyfS54bHN4IgoqICJ7Y2ZfcHJlZml4fS9BbGxfU2FtcGxlcy90X2NsaW5pY2FsX2NmX3NpZ19zdmEtdnt2ZXJ9Lnhsc3giCgpgYGB7cn0KaW5wdXRfeGxzeCA8LSBnbHVlKCJ7Y2ZfcHJlZml4fS9BbGxfU2FtcGxlcy90X2NsaW5pY2FsX2NmX3RhYmxlX3N2YS12e3Zlcn0ueGxzeCIpCnRfY2xpbmljYWxfY2ZfdGFibGVfc3ZhIDwtIHRhYmxlX3JlYWRlcihpbnB1dF94bHN4LCAib3V0Y29tZSIpCgppbnB1dF94bHN4IDwtIGdsdWUoIntjZl9wcmVmaXh9L0FsbF9TYW1wbGVzL3RfY2xpbmljYWxfY2Zfc2lnX3N2YS12e3Zlcn0ueGxzeCIpCnRfY2xpbmljYWxfY2Zfc2lnX3N2YV91cCA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJvdXRjb21lIikKdF9jbGluaWNhbF9jZl9zaWdfc3ZhX2Rvd24gPC0gc2lnX3JlYWRlcihpbnB1dF94bHN4LCAib3V0Y29tZSIsICJkb3duIikKYGBgCgpBbmQgd2l0aG91dCBiaW9wc2llcwoKYGBge3J9CmlucHV0X3hsc3ggPC0gZ2x1ZSgie2NmX3ByZWZpeH0vQWxsX1NhbXBsZXMvdF9jbGluaWNhbF9ub2Jpb3BfY2ZfdGFibGVfc3ZhLXZ7dmVyfS54bHN4IikKdF9jbGluaWNhbG5iX2NmX3RhYmxlX3N2YSA8LSB0YWJsZV9yZWFkZXIoaW5wdXRfeGxzeCwgIm91dGNvbWUiKQoKaW5wdXRfeGxzeCA8LSBnbHVlKCJ7Y2ZfcHJlZml4fS9BbGxfU2FtcGxlcy90X2NsaW5pY2FsX25vYmlvcF9jZl9zaWdfc3ZhLXZ7dmVyfS54bHN4IikKdF9jbGluaWNhbG5iX2NmX3NpZ19zdmFfdXAgPC0gc2lnX3JlYWRlcihpbnB1dF94bHN4LCAib3V0Y29tZSIpCnRfY2xpbmljYWxuYl9jZl9zaWdfc3ZhX2Rvd24gPC0gc2lnX3JlYWRlcihpbnB1dF94bHN4LCAib3V0Y29tZSIsICJkb3duIikKdF9jbGluaWNhbG5iX2NmX3NpZ19zdmFfYm90aCA8LSByYmluZC5kYXRhLmZyYW1lKHRfY2xpbmljYWxuYl9jZl9zaWdfc3ZhX3VwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdF9jbGluaWNhbG5iX2NmX3NpZ19zdmFfZG93bikKYGBgCgojIyMgZ1Byb2ZpbGVyCgpBZnRlciBtb3N0IG9mIHRoZSBERSBhbmFseXNlcywgdGhlIHNldCBvZiBzaWduaWZpY2FudGx5IERFIGdlbmVzIGdldHMKcGFzc2VkIHRvIGdQcm9maWxlcjIgYW5kIGNsdXN0ZXJQcm9maWxlci4gIE9uZSBzbGlnaHRseSBuZWF0IHRoaW5nIGluCm15IGdwcm9maWxlciAoYW5kIGdvc2VxL3RvcEdPL2dvc3RhdHMpIGZ1bmN0aW9uKHMpOiBpdCBjb2VyY2VzIHRoZQpyZXN1bHQgaW50byB0aGUgc2FtZSBkYXRhc3RydWN0dXJlIHByb2R1Y2VkIGJ5IGNsdXN0ZXJQcm9maWxlciwgdGh1cwpvbmUgbWF5IHBsYXkgd2l0aCB0aGUgdmFyaW91cyBwbG90dGluZyBmdW5jdGlvbnMgaW4gdGhlIGVucmljaHBsb3QKKEB5dUludHJvZHVjdGlvbkJpb21lZGljYWxLbm93bGVkZ2UpIHBhY2thZ2UuICBUaGlzIGlzIGtpbmQgb2YgZnVuCmJlY2F1c2UgZ1Byb2ZpbGVyMiBwcm92aWRlcyBlYXN5IGFjY2VzcyB0byBhIGZldyBkYXRhc2V0czoKCjEuIEdPOiAoQGFzaGJ1cm5lckdlbmVPbnRvbG9neVRvb2wyMDAwYSkKMi4gS0VHRzogKEBrYW5laGlzYUtFR0dLeW90b0VuY3ljbG9wZWRpYTIwMDApCjMuIFJlYWN0b21lOiAoQGNyb2Z0UmVhY3RvbWVEYXRhYmFzZVJlYWN0aW9uczIwMTEpCjQuIFdpa2lQYXRod2F5czogKEBrdXRtb25XaWtpUGF0aHdheXNDYXB0dXJpbmdGdWxsMjAxNikKNS4gVHJhbnNmYWM6IChAd2luZ2VuZGVyVFJBTlNGQUNEYXRhYmFzZVRyYW5zY3JpcHRpb24xOTk2KQo2LiBtaVJUYXJCYXNlOiAoQGhzdU1pUlRhckJhc2VEYXRhYmFzZUN1cmF0ZXMyMDExKQo3LiBUaGUgSHVtYW4gUHJvdGVpbiBBdGxhczogKEBwb250ZW5IdW1hblByb3RlaW5BdGxhczIwMTEpCjguIENvcnVtOiAoQGdpdXJnaXVDT1JVTUNvbXByZWhlbnNpdmVSZXNvdXJjZTIwMTkpCjkuIEh1bWFuIHBoZW5vdHlwZSBvbnRvbG9neTogKEBrb2hsZXJIdW1hblBoZW5vdHlwZU9udG9sb2d5MjAxNykKCiMjIyMgR2VuZXMgaGlnaGVyIGluIGN1cmUKCk15IGdlbmVyYWwgc2Vuc2UgaXMgdGhhdCB0aGUgY29tcGFyaXNvbnMgb2YgcHJpbWFyeSBpbnRlcmVzdCBhcmUKcmVhY3RvbWUgYW5kIG9uZSBvciBtb3JlIEdPLiAgSSBzdXNwZWN0IHRoYXQgaWYgdGhlcmUgYXJlIGxvdHMgb2YKdHJhbnNjcmlwdGlvbiBmYWN0b3JzLCB0aGF0IG1pZ2h0IHByb3ZlIGludGVyZXN0aW5nLgoKYGBge3J9CnRfY2ZfY2xpbmljYWxfZ3BfdXAgPC0gc2ltcGxlX2dwcm9maWxlcigKICB0X2NsaW5pY2FsX2NmX3NpZ19zdmFfdXAsCiAgZXhjZWwgPSBnbHVlKCJ7eGxzeF9wcmVmaXh9L0dlbmVfU2V0X092ZXJyZXByZXNlbnRhdGlvbi9jbGluaWNhbF9jdXJlX3VwX2dwLXZ7dmVyfS54bHN4IikpCnRfY2ZfY2xpbmljYWxfZ3BfdXAKCmdvX3Rlcm1zaW0gPC0gZW5yaWNocGxvdDo6cGFpcndpc2VfdGVybXNpbSh0X2NmX2NsaW5pY2FsX2dwX3VwW1siQlBfZW5yaWNoIl1dKQp0X2NmX2NsaW5pY2FsX2dwX2dvX3VwX3RyZWUgPC0gc20oZW5yaWNocGxvdDo6dHJlZXBsb3QoZ29fdGVybXNpbSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsX2Zvcm1hdCA9IHdyYXBfd2lkdGgpKQpwcChmaWxlID0gImltYWdlcy9vdmVycmVwcmVzZW50YXRpb24vdF9jZl9jbGluaWNhbF9ncF91cF90cmVlLnBkZiIsCiAgIHdpZHRoID0gdHJlZXBsb3Rfd2lkdGgsIGhlaWdodCA9IHRyZWVwbG90X2hlaWdodCkKdF9jZl9jbGluaWNhbF9ncF9nb191cF90cmVlCmRldi5vZmYoKQp0X2NmX2NsaW5pY2FsX2dwX2dvX3VwX3RyZWUKZW5yaWNocGxvdDo6ZG90cGxvdCh0X2NmX2NsaW5pY2FsX2dwX3VwW1siQlBfZW5yaWNoIl1dKQoKcmVhY3RvbWVfdGVybXNpbSA8LSBlbnJpY2hwbG90OjpwYWlyd2lzZV90ZXJtc2ltKHRfY2ZfY2xpbmljYWxfZ3BfdXBbWyJSRUFDX2VucmljaCJdXSkKdF9jZl9jbGluaWNhbF9ncF9yZWFjX3VwX3RyZWUgPC0gc20oZW5yaWNocGxvdDo6dHJlZXBsb3QocmVhY3RvbWVfdGVybXNpbSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxfZm9ybWF0ID0gd3JhcF93aWR0aCkpCnBwKGZpbGUgPSAiaW1hZ2VzL292ZXJyZXByZXNlbnRhdGlvbi90X2NmX2NsaW5pY2FsX2dwX3VwX3RyZWUucGRmIiwKICAgd2lkdGggPSB0cmVlcGxvdF93aWR0aCwgaGVpZ2h0ID0gdHJlZXBsb3RfaGVpZ2h0KQp0X2NmX2NsaW5pY2FsX2dwX3JlYWNfdXBfdHJlZQpkZXYub2ZmKCkKdF9jZl9jbGluaWNhbF9ncF9yZWFjX3VwX3RyZWUKcHAoZmlsZSA9ICJpbWFnZXMvb3ZlcnJlcHJlc2VudGF0aW9uL3RfY2ZfY2xpbmljYWxfZ3BfdXBfZG90LnBkZiIsCiAgIHdpZHRoID0gdHJlZXBsb3Rfd2lkdGgsIGhlaWdodCA9IHRyZWVwbG90X2hlaWdodCkKZW5yaWNocGxvdDo6ZG90cGxvdCh0X2NmX2NsaW5pY2FsX2dwX3VwW1siUkVBQ19lbnJpY2giXV0pCmRldi5vZmYoKQplbnJpY2hwbG90Ojpkb3RwbG90KHRfY2ZfY2xpbmljYWxfZ3BfdXBbWyJSRUFDX2VucmljaCJdXSkKCnRmX3Rlcm1zaW0gPC0gZW5yaWNocGxvdDo6cGFpcndpc2VfdGVybXNpbSh0X2NmX2NsaW5pY2FsX2dwX3VwW1siVEZfZW5yaWNoIl1dKQojIyBUaGUgdHJlZXBsb3QgZmFpbHMgZm9yIHRoaXMgZm9yIHNvbWUgcmVhc29uPwojI3RfY2ZfY2xpbmljYWxfZ3BfdGZfdXBfdHJlZSA8LSBzbShlbnJpY2hwbG90Ojp0cmVlcGxvdCh0Zl90ZXJtc2ltKSkKZW5yaWNocGxvdDo6ZG90cGxvdCh0X2NmX2NsaW5pY2FsX2dwX3VwW1siVEZfZW5yaWNoIl1dKQplbnJpY2hwbG90Ojpkb3RwbG90KHRfY2ZfY2xpbmljYWxfZ3BfdXBbWyJXUF9lbnJpY2giXV0pCmBgYAoKTm8gYmlvcHNpZXMhCgpgYGB7cn0KdF9jZl9jbGluaWNhbG5iX2dwX3VwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9jbGluaWNhbG5iX2NmX3NpZ19zdmFfdXAsCiAgZXhjZWwgPSBnbHVlKCJ7eGxzeF9wcmVmaXh9L0dlbmVfU2V0X092ZXJyZXByZXNlbnRhdGlvbi9jbGluaWNhbG5iX2N1cmVfdXBfZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9jZl9jbGluaWNhbG5iX2dwX3VwCgpnb190ZXJtc2ltIDwtIGVucmljaHBsb3Q6OnBhaXJ3aXNlX3Rlcm1zaW0odF9jZl9jbGluaWNhbG5iX2dwX3VwW1siQlBfZW5yaWNoIl1dKQp0X2NmX2NsaW5pY2FsbmJfZ3BfZ29fdXBfdHJlZSA8LSBzbShlbnJpY2hwbG90Ojp0cmVlcGxvdChnb190ZXJtc2ltLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbF9mb3JtYXQgPSB3cmFwX3dpZHRoKSkKcHAoZmlsZSA9ICJmaWd1cmVzL3RfY2ZfY2xpbmljYWxuYl9ncF91cF90cmVlLnN2ZyIsCiAgIHdpZHRoID0gdHJlZXBsb3Rfd2lkdGgsIGhlaWdodCA9IHRyZWVwbG90X2hlaWdodCkKdF9jZl9jbGluaWNhbG5iX2dwX2dvX3VwX3RyZWUKZGV2Lm9mZigpCnRfY2ZfY2xpbmljYWxuYl9ncF9nb191cF90cmVlCmVucmljaHBsb3Q6OmRvdHBsb3QodF9jZl9jbGluaWNhbG5iX2dwX3VwW1siQlBfZW5yaWNoIl1dKQoKcmVhY3RvbWVfdGVybXNpbSA8LSBlbnJpY2hwbG90OjpwYWlyd2lzZV90ZXJtc2ltKHRfY2ZfY2xpbmljYWxuYl9ncF91cFtbIlJFQUNfZW5yaWNoIl1dKQp0X2NmX2NsaW5pY2FsbmJfZ3BfcmVhY191cF90cmVlIDwtIHNtKGVucmljaHBsb3Q6OnRyZWVwbG90KHJlYWN0b21lX3Rlcm1zaW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxfZm9ybWF0ID0gd3JhcF93aWR0aCkpCnBwKGZpbGUgPSAiaW1hZ2VzL292ZXJyZXByZXNlbnRhdGlvbi90X2NmX2NsaW5pY2FsbmJfZ3BfdXBfdHJlZS5wZGYiLAogICB3aWR0aCA9IHRyZWVwbG90X3dpZHRoLCBoZWlnaHQgPSB0cmVlcGxvdF9oZWlnaHQpCnRfY2ZfY2xpbmljYWxuYl9ncF9yZWFjX3VwX3RyZWUKZGV2Lm9mZigpCnRfY2ZfY2xpbmljYWxuYl9ncF9yZWFjX3VwX3RyZWUKcHAoZmlsZSA9ICJpbWFnZXMvb3ZlcnJlcHJlc2VudGF0aW9uL3RfY2ZfY2xpbmljYWxuYl9ncF91cF9kb3QucGRmIiwKICAgd2lkdGggPSB0cmVlcGxvdF93aWR0aCwgaGVpZ2h0ID0gdHJlZXBsb3RfaGVpZ2h0KQplbnJpY2hwbG90Ojpkb3RwbG90KHRfY2ZfY2xpbmljYWxuYl9ncF91cFtbIlJFQUNfZW5yaWNoIl1dKQpkZXYub2ZmKCkKZW5yaWNocGxvdDo6ZG90cGxvdCh0X2NmX2NsaW5pY2FsbmJfZ3BfdXBbWyJSRUFDX2VucmljaCJdXSkKCnRmX3Rlcm1zaW0gPC0gZW5yaWNocGxvdDo6cGFpcndpc2VfdGVybXNpbSh0X2NmX2NsaW5pY2FsbmJfZ3BfdXBbWyJURl9lbnJpY2giXV0pCiMjIFRoZSB0cmVlcGxvdCBmYWlscyBmb3IgdGhpcyBmb3Igc29tZSByZWFzb24/CiMjdF9jZl9jbGluaWNhbG5iX2dwX3RmX3VwX3RyZWUgPC0gc20oZW5yaWNocGxvdDo6dHJlZXBsb3QodGZfdGVybXNpbSkpCmVucmljaHBsb3Q6OmRvdHBsb3QodF9jZl9jbGluaWNhbG5iX2dwX3VwW1siVEZfZW5yaWNoIl1dKQplbnJpY2hwbG90Ojpkb3RwbG90KHRfY2ZfY2xpbmljYWxuYl9ncF91cFtbIldQX2VucmljaCJdXSkKYGBgCgojIyMjIEdlbmVzIGhpZ2hlciBpbiBmYWlsCgpUaGUgb25seSBzaWduaWZpY2FudCByZXN1bHRzIGZvciB0aGlzIGdyb3VwIGFwcGVhciB0byBiZSBHTy4KCmBgYHtyfQp0X2NmX2NsaW5pY2FsX2dwX2Rvd24gPC0gc2ltcGxlX2dwcm9maWxlcigKICB0X2NsaW5pY2FsX2NmX3NpZ19zdmFfZG93biwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfT3ZlcnJlcHJlc2VudGF0aW9uL2NsaW5pY2FsX2ZhaWxfdXBfZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9jZl9jbGluaWNhbF9ncF9kb3duCgpnb190ZXJtc2ltIDwtIGVucmljaHBsb3Q6OnBhaXJ3aXNlX3Rlcm1zaW0odF9jZl9jbGluaWNhbF9ncF9kb3duW1siQlBfZW5yaWNoIl1dKQp0X2NmX2NsaW5pY2FsX2dwX2dvX2Rvd25fdHJlZSA8LSBzbShlbnJpY2hwbG90Ojp0cmVlcGxvdChnb190ZXJtc2ltKSkKcHAoZmlsZSA9ICJpbWFnZXMvb3ZlcnJlcHJlc2VudGF0aW9uL3RfY2ZfY2xpbmljYWxfZ3BfZG93bl90cmVlLnBkZiIsCiAgIHdpZHRoID0gdHJlZXBsb3Rfd2lkdGgsIGhlaWdodCA9IHRyZWVwbG90X2hlaWdodCkKdF9jZl9jbGluaWNhbF9ncF9nb19kb3duX3RyZWUKZGV2Lm9mZigpCmBgYAoKTm8gYmlvcHNpZXMhCgoKYGBge3J9CnRfY2ZfY2xpbmljYWxuYl9ncF9kb3duIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9jbGluaWNhbG5iX2NmX3NpZ19zdmFfZG93biwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfT3ZlcnJlcHJlc2VudGF0aW9uL2NsaW5pY2FsbmJfZmFpbF91cF9ncC12e3Zlcn0ueGxzeCIpKQp0X2NmX2NsaW5pY2FsbmJfZ3BfZG93bgoKZ29fdGVybXNpbSA8LSBlbnJpY2hwbG90OjpwYWlyd2lzZV90ZXJtc2ltKHRfY2ZfY2xpbmljYWxuYl9ncF9kb3duW1siQlBfZW5yaWNoIl1dKQp0X2NmX2NsaW5pY2FsbmJfZ3BfZ29fZG93bl90cmVlIDwtIHNtKGVucmljaHBsb3Q6OnRyZWVwbG90KGdvX3Rlcm1zaW0pKQpwcChmaWxlID0gImltYWdlcy9vdmVycmVwcmVzZW50YXRpb24vdF9jZl9jbGluaWNhbG5iX2dwX2Rvd25fdHJlZS5wZGYiLAogICB3aWR0aCA9IHRyZWVwbG90X3dpZHRoLCBoZWlnaHQgPSB0cmVlcGxvdF9oZWlnaHQpCnRfY2ZfY2xpbmljYWxuYl9ncF9nb19kb3duX3RyZWUKZGV2Lm9mZigpCnRfY2ZfY2xpbmljYWxuYl9ncF9nb19kb3duX3RyZWUKCiMjIEFuZCBib3RoLCB0aGlzIGlzIG5vdCB1c3VhbGx5IHdoZXJlIEkgcHV0IHRoaXMsIGJ1dCB0aGUKIyMgY2xpbmljYWwgc2FtcGxlcyBhcmUgYSBiaXQgb2YgYSBzcGVjaWFsIGNhc2UuCnRfY2ZfY2xpbmljYWxuYl9ncF9ib3RoIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9jbGluaWNhbG5iX2NmX3NpZ19zdmFfYm90aCwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfT3ZlcnJlcHJlc2VudGF0aW9uL2NsaW5pY2FsbmJfZmFpbF91cF9ncC12e3Zlcn0ueGxzeCIpKQp0X2NmX2NsaW5pY2FsbmJfZ3BfYm90aAoKZ29fdGVybXNpbSA8LSBlbnJpY2hwbG90OjpwYWlyd2lzZV90ZXJtc2ltKHRfY2ZfY2xpbmljYWxuYl9ncF9ib3RoW1siQlBfZW5yaWNoIl1dKQp0X2NmX2NsaW5pY2FsbmJfZ3BfZ29fYm90aF90cmVlIDwtIHNtKGVucmljaHBsb3Q6OnRyZWVwbG90KGdvX3Rlcm1zaW0pKQpwcChmaWxlID0gImltYWdlcy9vdmVycmVwcmVzZW50YXRpb24vdF9jZl9jbGluaWNhbG5iX2dwX2JvdGhfdHJlZS5wZGYiLAogICB3aWR0aCA9IHRyZWVwbG90X3dpZHRoLCBoZWlnaHQgPSB0cmVlcGxvdF9oZWlnaHQpCnRfY2ZfY2xpbmljYWxuYl9ncF9nb19ib3RoX3RyZWUKZGV2Lm9mZigpCnRfY2ZfY2xpbmljYWxuYl9ncF9nb19ib3RoX3RyZWUKCnJlYWNfdGVybXNpbSA8LSBlbnJpY2hwbG90OjpwYWlyd2lzZV90ZXJtc2ltKHRfY2ZfY2xpbmljYWxuYl9ncF9ib3RoW1siUkVBQ19lbnJpY2giXV0pCnRfY2ZfY2xpbmljYWxuYl9ncF9yZWFjX2JvdGhfdHJlZSA8LSBzbShlbnJpY2hwbG90Ojp0cmVlcGxvdChyZWFjX3Rlcm1zaW0pKQpwcChmaWxlID0gImltYWdlcy9vdmVycmVwcmVzZW50YXRpb24vdF9jZl9jbGluaWNhbG5iX2dwX2JvdGhfcmVhY190cmVlLnBkZiIsCiAgIHdpZHRoID0gdHJlZXBsb3Rfd2lkdGgsIGhlaWdodCA9IHRyZWVwbG90X2hlaWdodCkKdF9jZl9jbGluaWNhbG5iX2dwX3JlYWNfYm90aF90cmVlCmRldi5vZmYoKQp0X2NmX2NsaW5pY2FsbmJfZ3BfcmVhY19ib3RoX3RyZWUKYGBgCgojIyMgY2x1c3RlclByb2ZpbGVyCgpUaGUgZm9sbG93aW5nIGVzc2VudGlhbGx5IHJlcGVhdHMgdGhlIGdQcm9maWxlcjIgaW52b2NhdGlvbiB1c2luZwpjbHVzdGVyUHJvZmlsZXIuICBJIGhhdmUgYSBjb3VwbGUgb2YgZnVuY3Rpb25zIHdoaWNoIGNvbXBhcmUgdGhlIEdPCnJlc3VsdHMgZnJvbSB2YXJpb3VzIG1ldGhvZHMsIHBlcmhhcHMgSSBzaG91bGQgZGlnIGl0IG91dCBhbmQgc2VlIGhvdwpzaW1pbGFyIHRoZSByZXN1bHRzIGFyZSB1c2luZyB0aGVzZSB0d28gdG9vbHMuICBNeSBhc3N1bXB0aW9uIGlzIHRoYXQKdGhlIHByaW1hcnkgZGlmZmVyZW5jZXMgc2hvdWxkIGFyaXNlIGZyb20gdGhlIGZhY3QgdGhhdCBnUHJvZmlsZXIKdGhlb3JldGljYWxseSBpcyB1cGRhdGluZyB0aGVpciBHTyBkYXRhIG92ZXIgdGltZSBhbmQgY1Byb2ZpbGVyIHVzZXMKdGhlIGluZm9ybWF0aW9uIGluIG9yZy5Icy5lZy5kYiwgd2hpY2ggYWZhaWsgaGFzIG5vdCBjaGFuZ2VkIGluIHF1aXRlCmEgd2hpbGUuCgojIyMjIEdlbmVzIGhpZ2hlciBpbiBjdXJlCgpgYGB7cn0KdF9jZl9jbGluaWNhbF9jcF91cCA8LSBzaW1wbGVfY2x1c3RlcnByb2ZpbGVyKAogIHRfY2xpbmljYWxfY2Zfc2lnX3N2YV91cCwgZGVfdGFibGUgPSB0X2NsaW5pY2FsX2NmX3RhYmxlX3N2YSwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfT3ZlcnJlcHJlc2VudGF0aW9uL2NsaW5pY2FsX2N1cmVfdXBfY3Atdnt2ZXJ9Lnhsc3giKSkKZW5yaWNocGxvdDo6ZG90cGxvdCh0X2NmX2NsaW5pY2FsX2NwX3VwW1siZW5yaWNoX29iamVjdHMiXV1bWyJCUF9hbGwiXV0pCmBgYAoKIyMjIyBHZW5lcyBoaWdoZXIgaW4gZmFpbAoKYGBge3J9CnRfY2ZfY2xpbmljYWxfY3BfZG93biA8LSBzaW1wbGVfY2x1c3RlcnByb2ZpbGVyKAogIHRfY2xpbmljYWxfY2Zfc2lnX3N2YV9kb3duLAogIGV4Y2VsID0gZ2x1ZSgie3hsc3hfcHJlZml4fS9HZW5lX1NldF9PdmVycmVwcmVzZW50YXRpb24vY2xpbmljYWxfZmFpbF91cF9jcC12e3Zlcn0ueGxzeCIpKQplbnJpY2hwbG90Ojpkb3RwbG90KHRfY2ZfY2xpbmljYWxfY3BfZG93bltbImVucmljaF9vYmplY3RzIl1dW1siQlBfYWxsIl1dKQpgYGAKCiMjIyMgR1NFQQoKR1NFQSBpcyBub3QgYXNzb2NpYXRlZCB3aXRoIGVpdGhlciB1cCBub3IgZG93biwgaXQgdGFrZXMgdGhlIHJhbmsKb3JkZXIgb2YgZ2VuZXMgd2l0aCByZXNwZWN0IChpbiB0aGlzIGNhc2UpIHRvIGZvbGQtY2hhbmdlLgoKYGBge3J9CnRfY2ZfY2xpbmljYWxfdG9wbl9nc2VhIDwtIHBsb3RfdG9wbl9nc2VhKHRfY2ZfY2xpbmljYWxfY3BfdXApCnRfY2ZfY2xpbmljYWxfdG9wbl9nc2VhW1siR08iXV1bWzFdXQp0X2NmX2NsaW5pY2FsX3RvcG5fZ3NlYVtbIkdPIl1dW1syXV0KdF9jZl9jbGluaWNhbF90b3BuX2dzZWFbWyJHTyJdXVtbM11dCnRfY2ZfY2xpbmljYWxfdG9wbl9nc2VhW1siR08iXV1bWzRdXQp0X2NmX2NsaW5pY2FsX3RvcG5fZ3NlYVtbIkdPIl1dW1s1XV0KYGBgCgojIyBWaXNpdCAxIHZzLiBvdGhlciB2aXNpdHMKClRoZSByZWxldmFudCB4bHN4IGZpbGVzIGFyZToKCiogInt4bHN4X3ByZWZpeH0vREVfVmlzaXRzL3R2MV92c19sYXRlcl90YWJsZXMtdnt2ZXJ9Lnhsc3giCiogInt4bHN4X3ByZWZpeH0vREVfVmlzaXRzL3R2MV92c19sYXRlcl9zaWctdnt2ZXJ9Lnhsc3giCgpgYGB7cn0KaW5wdXRfeGxzeCA8LSBnbHVlKCJ7eGxzeF9wcmVmaXh9L0RFX1Zpc2l0cy90djFfdnNfbGF0ZXJfdGFibGVzLXZ7dmVyfS54bHN4IikKdHYxX3ZzX2xhdGVyX3RhYmxlIDwtIHRhYmxlX3JlYWRlcihpbnB1dF94bHN4LCAibGF0ZXJfdnNfZmlyc3QiKQoKaW5wdXRfeGxzeCA8LSBnbHVlKCJ7eGxzeF9wcmVmaXh9L0RFX1Zpc2l0cy90djFfdnNfbGF0ZXJfc2lnLXZ7dmVyfS54bHN4IikKdHYxX3ZzX2xhdGVyX3VwX3NpZyA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJsYXRlcl92c19maXJzdCIpCnR2MV92c19sYXRlcl9kb3duX3NpZyA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJsYXRlcl92c19maXJzdCIsICJkb3duIikKYGBgCgojIyMgSW5jcmVhc2VkIGluIHZpc2l0IDEKCkkgYW0gbm90IGxpa2VseSB0byBkbyB0aGUgZGVjcmVhc2VkIGluIHZpc2l0IDEsIHRoZXJlIGFyZSBvbmx5IDcgZ2VuZXMuCgojIyMjIGVucmljaG1lbnQ6IGdQcm9maWxlcgoKYGBge3J9CnR2MWxhdGVyX3VwX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdHYxX3ZzX2xhdGVyX3VwX3NpZywKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90djFfdnNfbGF0ZXJfdXBfZ3Atdnt2ZXJ9Lnhsc3giKSkKdHYxbGF0ZXJfdXBfZ3AKCmVucmljaHBsb3Q6OmRvdHBsb3QodHYxbGF0ZXJfdXBfZ3BbWyJCUF9lbnJpY2giXV0pCmVucmljaHBsb3Q6OmRvdHBsb3QodHYxbGF0ZXJfdXBfZ3BbWyJSRUFDX2VucmljaCJdXSkKYGBgCgojIyMjIGVucmljaG1lbnQ6IGNsdXN0ZXJQcm9maWxlcgoKTm90ZSB0byBzZWxmOiBtYWtlIHNvbWUgY2xhc3NlcyBmb3IgcGxvdF90b3BuX2dzZWEgc28gaXQgY2FuIGhhbmRsZQp0aGUgdmFyaW91cyBpbnB1dHMgaXQgaXMgbGlrZWx5IHRvIHJlY2VpdmUuCgpgYGB7cn0KdHYxbGF0ZXJfdXBfY3AgPC0gc2ltcGxlX2NsdXN0ZXJwcm9maWxlcigKICB0djFfdnNfbGF0ZXJfdXBfc2lnLCBkZV90YWJsZSA9IHR2MV92c19sYXRlcl90YWJsZSwKICBvcmdkYiA9ICJvcmcuSHMuZWcuZGIiLCBrZWdnX3ByZWZpeCA9ICJocyIsIGRvX2tlZ2cgPSBUUlVFKQplbnJpY2hwbG90Ojpkb3RwbG90KHR2MWxhdGVyX3VwX2NwW1siZW5yaWNoX29iamVjdHMiXV1bWyJNRl9hbGwiXV0pCmVucmljaHBsb3Q6OmRvdHBsb3QodHYxbGF0ZXJfdXBfY3BbWyJlbnJpY2hfb2JqZWN0cyJdXVtbIkJQX2FsbCJdXSkKCndyaXR0ZW4gPC0gd3JpdGVfY3BfZGF0YSgKICB0djFsYXRlcl91cF9jcCwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90djFfdnNfbGF0ZXJfdXBfY3Atdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIyMjIEdTRUE6IGNsdXN0ZXJQcm9maWxlcgoKYGBge3J9CnR2MWxhdGVyX3RvcG5fZ3NlYSA8LSBwbG90X3RvcG5fZ3NlYSh0djFsYXRlcl91cF9jcCkKdHYxbGF0ZXJfdG9wbl9nc2VhW1siR08iXV1bWzFdXQp0djFsYXRlcl90b3BuX2dzZWFbWyJHTyJdXVtbMl1dCmBgYAoKIyMgUGF0aWVudCBTZXgKClRoZSByZWxldmFudCBpbnB1dCB4bHN4IGZpbGVzIGFyZToKCioge3hsc3hfcHJlZml4fS9ERV9TZXgvdF9zZXhfdGFibGUtdnt2ZXJ9Lnhsc3giKSkKKiB7eGxzeF9wcmVmaXh9L0RFX1NleC90X3NleF9zaWctdnt2ZXJ9Lnhsc3giKSkKCk9oLCBJIG1lc3NlZCB1cCBhbmQgcHV0IHRoZSBERSByZXN1bHRzIGluIHRoZSBHU0VBIGRpcmVjdG9yeSEKCkxldCB1cyBzZWUgaWYgd2Ugb2JzZXJ2ZSBnZW5lcmFsIG1hbGUvZmVtYWxlIGRpZmZlcmVuY2VzIGluIHRoZSBkYXRhLgpUaGlzIGhhcyBhbiBpbXBvcnRhbnQgY2F2ZWF0OiB0aGVyZSBhcmUgZmV3IGZlbWFsZSBmYWlsdXJlcyBpbiB0aGUKZGF0YXNldCBhbmQgc28gdGhlIHJlc3VsdHMgbWF5IHJlZmxlY3QgdGhhdC4KCmBgYHtyfQppbnB1dF94bHN4IDwtIGdsdWUoInt4bHN4X3ByZWZpeH0vREVfU2V4L3Rfc2V4X2N1cmVfdGFibGUtdnt2ZXJ9Lnhsc3giKQp0X3NleF90YWJsZSA8LSB0YWJsZV9yZWFkZXIoaW5wdXRfeGxzeCwgIm1hbGVfdnNfZmVtYWxlIikKCmlucHV0X3hsc3ggPC0gZ2x1ZSgie3hsc3hfcHJlZml4fS9ERV9TZXgvdF9zZXhfY3VyZV9zaWctdnt2ZXJ9Lnhsc3giKQp0X3NleF91cF9zaWcgPC0gc2lnX3JlYWRlcihpbnB1dF94bHN4LCAibWFsZV92c19mZW1hbGUiKQp0X3NleF9kb3duX3NpZyA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJtYWxlX3ZzX2ZlbWFsZSIsICJkb3duIikKYGBgCgojIyMgZ1Byb2ZpbGVyCgojIyMjIEluY3JlYXNlZCBpbiBtZW4KCmBgYHtyfQp0X3NleF91cF9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKAogIHRfc2V4X3VwX3NpZywKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC9zZXhfbWFsZV91cF9ncC12e3Zlcn0ueGxzeCIpKQp0X3NleF91cF9ncAoKZW5yaWNocGxvdDo6ZG90cGxvdCh0X3NleF91cF9ncFtbIkJQX2VucmljaCJdXSkKZW5yaWNocGxvdDo6ZG90cGxvdCh0X3NleF91cF9ncFtbIlJFQUNfZW5yaWNoIl1dKQplbnJpY2hwbG90Ojpkb3RwbG90KHRfc2V4X3VwX2dwW1siVEZfZW5yaWNoIl1dKQpgYGAKCiMjIyMgSW5jcmVhc2VkIGluIHdvbWVuCgpgYGB7cn0KdF9zZXhfZG93bl9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKAogIHRfc2V4X2Rvd25fc2lnLAogIGV4Y2VsID0gZ2x1ZSgie3hsc3hfcHJlZml4fS9HZW5lX1NldF9FbnJpY2htZW50L3NleF9mZW1hbGVfdXBfZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9zZXhfZG93bl9ncApgYGAKCkdpdmVuIHRoZSByZXN1bHRzIGZyb20gZ1Byb2ZpbGVyLCBJIGRvIG5vdCBoYXZlIGhpZ2ggZXhwZWN0YXRpb25zIGZvcgpjbHVzdGVyUHJvZmlsZXIsIHNvIEkgYW0gbm90IGxpa2VseSB0byB0YWtlIHRoZSB0aW1lIHRvIHdyaXRlIHRoZW0gb3V0LgpJdCBzZWVtcyBsaWtlIG1hbGUvZmVtYWxlIGlzIGNvbmZvdW5kZWQgd2l0aCBjdXJlL2ZhaWwuCgojIyMgY2x1c3RlclByb2ZpbGVyCgojIyMjIEluY3JlYXNlZCBpbiBtZW4KCmBgYHtyfQp0X3NleF91cF9jcCA8LSBzaW1wbGVfY2x1c3RlcnByb2ZpbGVyKAogIHRfc2V4X3VwX3NpZywgZGVfdGFibGUgPSB0X3NleF90YWJsZSwKICBvcmdkYiA9ICJvcmcuSHMuZWcuZGIiLCBrZWdnX3ByZWZpeCA9ICJocyIsIGRvX2tlZ2cgPSBUUlVFKQplbnJpY2hwbG90Ojpkb3RwbG90KHRfc2V4X3VwX2NwW1siZW5yaWNoX29iamVjdHMiXV1bWyJCUF9hbGwiXV0pCmBgYAoKIyMjIyBJbmNyZWFzZWQgaW4gd29tZW4KCmBgYHtyfQp0X3NleF9kb3duX2NwIDwtIHNpbXBsZV9jbHVzdGVycHJvZmlsZXIoCiAgdF9zZXhfZG93bl9zaWcsIGRlX3RhYmxlID0gdF9zZXhfdGFibGUsCiAgb3JnZGIgPSAib3JnLkhzLmVnLmRiIiwga2VnZ19wcmVmaXggPSAiaHMiLCBkb19rZWdnID0gVFJVRSkKZW5yaWNocGxvdDo6ZG90cGxvdCh0X3NleF9kb3duX2NwW1siZW5yaWNoX29iamVjdHMiXV1bWyJCUF9hbGwiXV0pCmBgYAoKIyMjIyBHU0VBCgpgYGB7cn0KdF9zZXhfdG9wbl9nc2VhIDwtIHBsb3RfdG9wbl9nc2VhKHRfc2V4X3VwX2NwKQp0X3NleF90b3BuX2dzZWFbWyJHTyJdXVtbMV1dCmBgYAoKIyMgRXRobmljaXR5CgpPbmNlIGFnYWluLCB0aGUgcmVsZXZhbnQgZmlsZXMgdG8gbG9hZDoKCiogInt4bHN4X3ByZWZpeH0vREVfRXRobmljaXR5L3RfZXRobmljaXR5X3RhYmxlLXZ7dmVyfS54bHN4IgoqICJ7eGxzeF9wcmVmaXh9L0RFX0V0aG5pY2l0eS90X2V0aG5pY2l0eV9zaWctdnt2ZXJ9Lnhsc3giCgpgYGB7cn0KaW5wdXRfeGxzeCA8LSBnbHVlKCJ7eGxzeF9wcmVmaXh9L0RFX0V0aG5pY2l0eS90X2V0aG5pY2l0eV90YWJsZS12e3Zlcn0ueGxzeCIpCnRfZXRobmljaXR5X21lc3Rpem9faW5kaWdlbm91cyA8LSB0YWJsZV9yZWFkZXIoaW5wdXRfeGxzeCwgIm1lc3Rpem9faW5kaWdlbm91cyIpCnRfZXRobmljaXR5X21lc3Rpem9fYWZyb2NvbCA8LSB0YWJsZV9yZWFkZXIoaW5wdXRfeGxzeCwgIm1lc3Rpem9fYWZyb2NvbCIpCnRfZXRobmljaXR5X2luZGlnZW5vdXNfYWZyb2NvbCA8LSB0YWJsZV9yZWFkZXIoaW5wdXRfeGxzeCwgImluZGlnZW5vdXNfYWZyb2NvbCIpCgppbnB1dF94bHN4IDwtIGdsdWUoInt4bHN4X3ByZWZpeH0vREVfRXRobmljaXR5L3RfZXRobmljaXR5X3NpZy12e3Zlcn0ueGxzeCIpCnRfZXRobmljaXR5X21lc3Rpem9faW5kaWdlbm91c191cCA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJtZXN0aXpvX2luZGlnZW5vdXMiKQp0X2V0aG5pY2l0eV9tZXN0aXpvX2luZGlnZW5vdXNfZG93biA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJtZXN0aXpvX2luZGlnZW5vdXMiLCAiZG93biIpCnRfZXRobmljaXR5X21lc3Rpem9fYWZyb2NvbF91cCA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJtZXN0aXpvX2Fmcm9jb2wiKQp0X2V0aG5pY2l0eV9tZXN0aXpvX2Fmcm9jb2xfZG93biA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJtZXN0aXpvX2Fmcm9jb2wiLCAiZG93biIpCnRfZXRobmljaXR5X2luZGlnZW5vdXNfYWZyb2NvbF91cCA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJpbmRpZ2Vub3VzX2Fmcm9jb2wiKQp0X2V0aG5pY2l0eV9pbmRpZ2Vub3VzX2Fmcm9jb2xfZG93biA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJpbmRpZ2Vub3VzX2Fmcm9jb2wiLCAiZG93biIpCmBgYAoKIyMjIGdQcm9maWxlcgoKIyMjIyBJbmNyZWFzZWQgaW4gbWVzdGl6byB2cyBpbmRpZ2Vub3VzCgpgYGB7cn0KbWVzdGl6b19pbmRpZ2Vub3VzX3VwX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9ldGhuaWNpdHlfbWVzdGl6b19pbmRpZ2Vub3VzX3VwLAogIGV4Y2VsID0gZ2x1ZSgie3hsc3hfcHJlZml4fS9HZW5lX1NldF9FbnJpY2htZW50L2V0aG5pY2l0eV9taV91cF9ncC12e3Zlcn0ueGxzeCIpKQptZXN0aXpvX2luZGlnZW5vdXNfdXBfZ3AKYGBgCgojIyMjIEluY3JlYXNlZCBpbiBpbmRpZ2Vub3VzIHZzIG1lc3Rpem8KCmBgYHtyfQppbmRpZ2Vub3VzX21lc3Rpem9fdXBfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcigKICB0X2V0aG5pY2l0eV9tZXN0aXpvX2luZGlnZW5vdXNfZG93biwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC9ldGhuaWNpdHlfaW1fdXBfZ3Atdnt2ZXJ9Lnhsc3giKSkKaW5kaWdlbm91c19tZXN0aXpvX3VwX2dwCmBgYAoKIyMjIyBJbmNyZWFzZWQgaW4gbWVzdGl6byB2cyBhZnJvY29sb21iaWFuCgpgYGB7cn0KbWVzdGl6b19hZnJvY29sX3VwX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9ldGhuaWNpdHlfbWVzdGl6b19hZnJvY29sX3VwLAogIGV4Y2VsID0gZ2x1ZSgie3hsc3hfcHJlZml4fS9HZW5lX1NldF9FbnJpY2htZW50L2V0aG5pY2l0eV9tYV91cF9ncC12e3Zlcn0ueGxzeCIpKQptZXN0aXpvX2Fmcm9jb2xfdXBfZ3AKYGBgCgojIyMjIEluY3JlYXNlZCBpbiBhZnJvY29sb21iaWFuIHZzIG1lc3Rpem8KCmBgYHtyfQphZnJvY29sX21lc3Rpem9fdXBfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcigKICB0X2V0aG5pY2l0eV9tZXN0aXpvX2Fmcm9jb2xfZG93biwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC9ldGhuaWNpdHlfYW1fdXBfZ3Atdnt2ZXJ9Lnhsc3giKSkKYWZyb2NvbF9tZXN0aXpvX3VwX2dwCmBgYAoKIyMjIyBJbmNyZWFzZWQgaW4gaW5kaWdlbm91cyB2cyBhZnJvY29sb21iaWFuCgpgYGB7cn0KaW5kaWdlbm91c19hZnJvY29sX3VwX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9ldGhuaWNpdHlfaW5kaWdlbm91c19hZnJvY29sX3VwLAogIGV4Y2VsID0gZ2x1ZSgie3hsc3hfcHJlZml4fS9HZW5lX1NldF9FbnJpY2htZW50L2V0aG5pY2l0eV9pYV91cF9ncC12e3Zlcn0ueGxzeCIpKQppbmRpZ2Vub3VzX2Fmcm9jb2xfdXBfZ3AKYGBgCgojIyMjIEluY3JlYXNlZCBpbiBhZnJvY29sb21iaWFuIHZzIGluZGlnZW5vdXMKCmBgYHtyfQphZnJvY29sX2luZGlnZW5vdXNfdXBfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcigKICB0X2V0aG5pY2l0eV9pbmRpZ2Vub3VzX2Fmcm9jb2xfZG93biwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC9ldGhuaWNpdHlfYWlfdXBfZ3Atdnt2ZXJ9Lnhsc3giKSkKYWZyb2NvbF9pbmRpZ2Vub3VzX3VwX2dwCmBgYAoKIyMjIGNsdXN0ZXJQcm9maWxlcgoKIyMjIyBJbmNyZWFzZWQgaW4gbWVzdGl6byB2cyBpbmRpZ2Vub3VzCgpgYGB7cn0KbWVzdGl6b19pbmRpZ2Vub3VzX3VwX2NwIDwtIHNpbXBsZV9jbHVzdGVycHJvZmlsZXIoCiAgdF9ldGhuaWNpdHlfbWVzdGl6b19pbmRpZ2Vub3VzX3VwLAogIGRlX3RhYmxlID0gdF9ldGhuaWNpdHlfbWVzdGl6b19pbmRpZ2Vub3VzKQptZXN0aXpvX2luZGlnZW5vdXNfdXBfY3AKYGBgCgojIyMjIEluY3JlYXNlZCBpbiBpbmRpZ2Vub3VzIHZzIG1lc3Rpem8KCmBgYHtyfQppbmRpZ2Vub3VzX21lc3Rpem9fdXBfY3AgPC0gc2ltcGxlX2NsdXN0ZXJwcm9maWxlcigKICB0X2V0aG5pY2l0eV9tZXN0aXpvX2luZGlnZW5vdXNfZG93bikKaW5kaWdlbm91c19tZXN0aXpvX3VwX2NwCmBgYAoKIyMjIyBJbmNyZWFzZWQgaW4gbWVzdGl6byB2cyBhZnJvY29sb21iaWFuCgpgYGB7cn0KbWVzdGl6b19hZnJvY29sX3VwX2NwIDwtIHNpbXBsZV9jbHVzdGVycHJvZmlsZXIoCiAgdF9ldGhuaWNpdHlfbWVzdGl6b19hZnJvY29sX3VwLAogIGRlX3RhYmxlID0gdF9ldGhuaWNpdHlfbWVzdGl6b19hZnJvY29sKQptZXN0aXpvX2Fmcm9jb2xfdXBfY3AKYGBgCgojIyMjIEluY3JlYXNlZCBpbiBhZnJvY29sb21iaWFuIHZzIG1lc3Rpem8KCmBgYHtyfQphZnJvY29sX21lc3Rpem9fdXBfY3AgPC0gc2ltcGxlX2NsdXN0ZXJwcm9maWxlcih0X2V0aG5pY2l0eV9tZXN0aXpvX2Fmcm9jb2xfZG93bikKYWZyb2NvbF9tZXN0aXpvX3VwX2NwCmBgYAoKIyMjIyBJbmNyZWFzZWQgaW4gaW5kaWdlbm91cyB2cyBhZnJvY29sb21iaWFuCgpgYGB7cn0KaW5kaWdlbm91c19hZnJvY29sX3VwX2NwIDwtIHNpbXBsZV9jbHVzdGVycHJvZmlsZXIoCiAgdF9ldGhuaWNpdHlfaW5kaWdlbm91c19hZnJvY29sX3VwLAogIGRlX3RhYmxlID0gdF9ldGhuaWNpdHlfaW5kaWdlbm91c19hZnJvY29sKQppbmRpZ2Vub3VzX2Fmcm9jb2xfdXBfY3AKYGBgCgojIyMjIEluY3JlYXNlZCBpbiBhZnJvY29sb21iaWFuIHZzIGluZGlnZW5vdXMKCmBgYHtyfQphZnJvY29sX2luZGlnZW5vdXNfdXBfY3AgPC0gc2ltcGxlX2NsdXN0ZXJwcm9maWxlcih0X2V0aG5pY2l0eV9pbmRpZ2Vub3VzX2Fmcm9jb2xfZG93bikKYWZyb2NvbF9pbmRpZ2Vub3VzX3VwX2NwCmBgYAoKIyMgVmlzaXQgMSBjdXJlL2ZhaWwKCkl0IGxvb2tzIGxpa2UgdGhlcmUgYXJlIHZlcnkgZmV3IGdyb3VwcyBpbiB0aGUgdmlzaXQgMSBzaWduaWZpY2FudApnZW5lcy4KClRoZSByZWxldmFudCB4bHN4IGZpbGVzIGFyZToKCiogIntjZl9wcmVmaXh9L1Zpc2l0cy90X2NsaW5pY2FsX3YxX2NmX3RhYmxlX3N2YS12e3Zlcn0ueGxzeCIKKiAie2NmX3ByZWZpeH0vVmlzaXRzL3RfY2xpbmljYWxfdjFfY2Zfc2lnX3N2YS12e3Zlcn0ueGxzeCIKCmBgYHtyfQppbnB1dF94bHN4IDwtIGdsdWUoIntjZl9wcmVmaXh9L1Zpc2l0cy90X2NsaW5pY2FsX3YxX2NmX3RhYmxlX3N2YS12e3Zlcn0ueGxzeCIpCnRfY2ZfY2xpbmljYWxfdjFfdGFibGVfc3ZhIDwtIHRhYmxlX3JlYWRlcihpbnB1dF94bHN4KQoKaW5wdXRfeGxzeCA8LSBnbHVlKCJ7Y2ZfcHJlZml4fS9WaXNpdHMvdF9jbGluaWNhbF92MV9jZl9zaWdfc3ZhLXZ7dmVyfS54bHN4IikKdF9jZl9jbGluaWNhbF92MV9zaWdfc3ZhX3VwIDwtIHNpZ19yZWFkZXIoaW5wdXRfeGxzeCwgIm91dGNvbWUiKQp0X2NmX2NsaW5pY2FsX3YxX3NpZ19zdmFfZG93biA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJvdXRjb21lIiwgImRvd24iKQpgYGAKCiMjIyBnUHJvZmlsZXIKCiMjIyMgSW5jcmVhc2VkIGluIHZpc2l0IDEgY3VyZS9mYWlsCgpgYGB7cn0KdF9jZl9jbGluaWNhbF92MV9zaWdfc3ZhX3VwX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIodF9jZl9jbGluaWNhbF92MV9zaWdfc3ZhX3VwKQp0X2NmX2NsaW5pY2FsX3YxX3NpZ19zdmFfdXBfZ3AKYGBgCgojIyMjIEluY3JlYXNlZCBpbiB2aXNpdCAxIGZhaWwvY3VyZQoKYGBge3J9CnRfY2ZfY2xpbmljYWxfdjFfc2lnX3N2YV9kb3duX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIodF9jZl9jbGluaWNhbF92MV9zaWdfc3ZhX2Rvd24pCnRfY2ZfY2xpbmljYWxfdjFfc2lnX3N2YV9kb3duX2dwCmVucmljaHBsb3Q6OmRvdHBsb3QodF9jZl9jbGluaWNhbF92MV9zaWdfc3ZhX2Rvd25fZ3BbWyJCUF9lbnJpY2giXV0pCmBgYAoKIyMjIGNsdXN0ZXJQcm9maWxlcgoKIyMjIyBJbmNyZWFzZWQgdmlzaXQgMSBjdXJlL2ZhaWwKCmBgYHtyfQp0X2NmX2NsaW5pY2FsX3YxX3NpZ19zdmFfdXBfY3AgPC0gc2ltcGxlX2Nwcm9maWxlcigKICB0X2NmX2NsaW5pY2FsX3YxX3NpZ19zdmFfdXAsCiAgZGVfdGFibGUgPSB0X2NmX2NsaW5pY2FsX3YxX3RhYmxlX3N2YSwKICBvcmdkYiA9ICJvcmcuSHMuZWcuZGIiKQp0X2NmX2NsaW5pY2FsX3YxX3NpZ19zdmFfdXBfY3AKCmVucmljaHBsb3Q6OmRvdHBsb3QodF9jZl9jbGluaWNhbF92MV9zaWdfc3ZhX3VwX2NwW1siZW5yaWNoX29iamVjdHMiXV1bWyJCUF9hbGwiXV0pCmBgYAoKIyMjIyBJbmNyZWFzZWQgaW4gdmlzaXQgMSBjdXJlL2ZhaWwKCmBgYHtyfQp0X2NmX2NsaW5pY2FsX3YxX3NpZ19zdmFfZG93bl9jcCA8LSBzaW1wbGVfY3Byb2ZpbGVyKAogIHRfY2ZfY2xpbmljYWxfdjFfc2lnX3N2YV9kb3duLAogIG9yZ2RiID0gIm9yZy5Icy5lZy5kYiIpCmBgYAoKIyMjIyBHU0VBCgpJdCBhcHBlYXJzIHRoZXJlIGFyZSB0b28gZmV3IHJlc3VsdHMgdG8gcGVyZm9ybSB0aGUgZ3NlYSBwbG90cy4KCiMjIEN1cmUvRmFpbCwgQmlvcHNpZXMKClRoZSByZWxldmFudCB4bHN4IG91dHB1dCBtYXkgYmUgZm91bmQgYXQ6CgoqICJ7Y2ZfcHJlZml4fS9CaW9wc2llcy90X2Jpb3BzeV9jZl90YWJsZV9zdmEtdnt2ZXJ9Lnhsc3giCiogIntjZl9wcmVmaXh9L0Jpb3BzaWVzL3RfY2ZfYmlvcHN5X3NpZ19zdmEtdnt2ZXJ9Lnhsc3giCgpgYGB7cn0KaW5wdXRfeGxzeCA8LSBnbHVlKCJ7Y2ZfcHJlZml4fS9CaW9wc2llcy90X2Jpb3BzeV9jZl90YWJsZV9zdmEtdnt2ZXJ9Lnhsc3giKQp0X2NmX2Jpb3BzeV90YWJsZV9zdmEgPC0gdGFibGVfcmVhZGVyKGlucHV0X3hsc3gsICJvdXRjb21lIikKCmlucHV0X3hsc3ggPC0gZ2x1ZSgie2NmX3ByZWZpeH0vQmlvcHNpZXMvdF9jZl9iaW9wc3lfc2lnX3N2YS12e3Zlcn0ueGxzeCIpCnRfY2ZfYmlvcHN5X3NpZ19zdmFfdXAgPC0gc2lnX3JlYWRlcihpbnB1dF94bHN4LCAib3V0Y29tZSIpCnRfY2ZfYmlvcHN5X3NpZ19zdmFfZG93biA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJvdXRjb21lIiwgImRvd24iKQp0X2NmX2Jpb3BzeV9zaWdfc3ZhX2JvdGggPC0gcmJpbmQuZGF0YS5mcmFtZSh0X2NmX2Jpb3BzeV9zaWdfc3ZhX3VwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0X2NmX2Jpb3BzeV9zaWdfc3ZhX2Rvd24pCmBgYAoKIyMjIGdQcm9maWxlcgoKV2Ugb25seSBoYXZlIDE3IGdlbmVzIGluIHRoZSBiaW9wc2llcywgYnV0IHBlcmhhcHMgdGhleSBhcmUgc3RpbGwgaW50ZXJlc3Rpbmc/CgojIyMjIGluY3JlYXNlZCBpbiBjdXJlIHZzIGZhaWwKCmBgYHtyfQp0X2NmX2Jpb3BzeV9zaWdfc3ZhX2dwX3VwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9jZl9iaW9wc3lfc2lnX3N2YV91cCwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX2Jpb3BzeV9zaWdfc3ZhX3VwX2dwLXZ7dmVyfS54bHN4IikpCnRfY2ZfYmlvcHN5X3NpZ19zdmFfZ3BfdXAKCmVucmljaHBsb3Q6OmRvdHBsb3QodF9jZl9iaW9wc3lfc2lnX3N2YV9ncF91cFtbIkJQX2VucmljaCJdXSkKZ29fdGVybXNpbSA8LSBlbnJpY2hwbG90OjpwYWlyd2lzZV90ZXJtc2ltKHRfY2ZfYmlvcHN5X3NpZ19zdmFfZ3BfdXBbWyJCUF9lbnJpY2giXV0pCmdvX3RyZWVwbG90IDwtIHNtKHRyZWVwbG90KGdvX3Rlcm1zaW0sIGxhYmVsX2Zvcm1hdCA9IHdyYXBfd2lkdGgpKQpwcChmaWxlID0gZ2x1ZSgiaW1hZ2VzL292ZXJyZXByZXNlbnRhdGlvbi90X2NmX2Jpb3BzeV91cF9ncF9nby12e3Zlcn0ucGRmIiksCiAgIGhlaWdodCA9IHRyZWVwbG90X2hlaWdodCwgd2lkdGggPSB0cmVlcGxvdF93aWR0aCkKZ29fdHJlZXBsb3QKZGV2Lm9mZigpCmdvX3RyZWVwbG90CmBgYAoKIyMjIyBpbmNyZWFzZWQgaW4gZmFpbCB2cyBjdXJlCgpgYGB7cn0KdF9jZl9iaW9wc3lfc2lnX3N2YV9ncF9kb3duIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9jZl9iaW9wc3lfc2lnX3N2YV9kb3duLAogIGV4Y2VsID0gZ2x1ZSgie3hsc3hfcHJlZml4fS9HZW5lX1NldF9FbnJpY2htZW50L3RfY2ZfYmlvcHN5X3NpZ19zdmFfZG93bl9ncC12e3Zlcn0ueGxzeCIpKQp0X2NmX2Jpb3BzeV9zaWdfc3ZhX2dwX2Rvd24KCiMjIE5vdCBuZWFybHkgYXMgaW50ZXJlc3RpbmcKYGBgCgojIyMgY2x1c3RlcnByb2ZpbGVyCgpBZ2FpbiwgY2x1c3RlcnByb2ZpbGVyIHZlcnNpb24KCiMjIyMgaW5jcmVhc2VkIGluIGN1cmUvZmFpbAoKYGBge3J9CnRfY2ZfYmlvcHN5X3NpZ19zdmFfY3BfdXAgPC0gc2ltcGxlX2Nwcm9maWxlcigKICB0X2NmX2Jpb3BzeV9zaWdfc3ZhX3VwLCBkZV90YWJsZSA9IHRfY2ZfYmlvcHN5X3RhYmxlX3N2YSwKICBvcmdkYiA9ICJvcmcuSHMuZWcuZGIiLAogIGV4Y2VsID0gZ2x1ZSgie3hsc3hfcHJlZml4fS9HZW5lX1NldF9FbnJpY2htZW50L3RfY2ZfYmlvcHN5X3NpZ19zdmFfdXBfY3Atdnt2ZXJ9Lnhsc3giKSkKZW5yaWNocGxvdDo6ZG90cGxvdCh0X2NmX2Jpb3BzeV9zaWdfc3ZhX2NwX3VwW1siZW5yaWNoX29iamVjdHMiXV1bWyJCUF9hbGwiXV0pCmBgYAoKIyMjIyBHU0VBIG9mIGN1cmUvZmFpbAoKYGBge3J9CnRfY2ZfYmlvcHN5X3NpZ190b3BuX2dzZWEgPC0gcGxvdF90b3BuX2dzZWEodF9jZl9iaW9wc3lfc2lnX3N2YV9jcF91cCkKdF9jZl9iaW9wc3lfc2lnX3RvcG5fZ3NlYVtbIkdPX291dGNvbWVfdXAiXV1bWzFdXQpgYGAKCiMjIEVvc2lub3BoaWxzIGN1cmUvZmFpbAoKYGBge3J9CmlucHV0X3hsc3ggPC0gZ2x1ZSgie2NmX3ByZWZpeH0vRW9zaW5vcGhpbHMvdF9lb3Npbm9waGlsX2NmX3RhYmxlX3N2YS12e3Zlcn0ueGxzeCIpCnRfY2ZfZW9zaW5vcGhpbF90YWJsZV9zdmEgPC0gdGFibGVfcmVhZGVyKGlucHV0X3hsc3gsICJvdXRjb21lIikKCmlucHV0X3hsc3ggPC0gZ2x1ZSgie2NmX3ByZWZpeH0vRW9zaW5vcGhpbHMvdF9lb3Npbm9waGlsX2NmX3NpZ19zdmEtdnt2ZXJ9Lnhsc3giKQp0X2NmX2Vvc2lub3BoaWxfc2lnX3N2YV91cCA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJvdXRjb21lIikKdF9jZl9lb3Npbm9waGlsX3NpZ19zdmFfZG93biA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJvdXRjb21lIiwgImRvd24iKQp0X2NmX2Vvc2lub3BoaWxfc2lnX3N2YV9ib3RoIDwtIHJiaW5kLmRhdGEuZnJhbWUodF9jZl9lb3Npbm9waGlsX3NpZ19zdmFfdXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0X2NmX2Vvc2lub3BoaWxfc2lnX3N2YV9kb3duKQpgYGAKCiMjIyBnUHJvZmlsZXIKCiMjIyMgaW5jcmVhc2VkIGluIGN1cmUgdnMgZmFpbAoKYGBge3J9CnRfY2ZfZW9zaW5vcGhpbF9zaWdfc3ZhX3VwX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9jZl9lb3Npbm9waGlsX3NpZ19zdmFfdXAsCiAgZXhjZWwgPSBnbHVlKCJ7eGxzeF9wcmVmaXh9L0dlbmVfU2V0X0VucmljaG1lbnQvdF9jZl9lb3Npbm9waGlsX3VwX2dwLXZ7dmVyfS54bHN4IikpCnRfY2ZfZW9zaW5vcGhpbF9zaWdfc3ZhX3VwX2dwCmVucmljaHBsb3Q6OmRvdHBsb3QodF9jZl9lb3Npbm9waGlsX3NpZ19zdmFfdXBfZ3BbWyJCUF9lbnJpY2giXV0pCmVucmljaHBsb3Q6OmRvdHBsb3QodF9jZl9lb3Npbm9waGlsX3NpZ19zdmFfdXBfZ3BbWyJURl9lbnJpY2giXV0pCgpnb190ZXJtc2ltIDwtIGVucmljaHBsb3Q6OnBhaXJ3aXNlX3Rlcm1zaW0odF9jZl9lb3Npbm9waGlsX3NpZ19zdmFfdXBfZ3BbWyJCUF9lbnJpY2giXV0pCmdvX3RyZWVwbG90IDwtIHNtKHRyZWVwbG90KGdvX3Rlcm1zaW0sIGxhYmVsX2Zvcm1hdCA9IHdyYXBfd2lkdGgpKQpwcChmaWxlID0gImZpZ3VyZXMvdF9jZl9lb3Npbm9waGlsX3VwX2dwX2dvLnN2ZyIsCiAgIGhlaWdodCA9IHRyZWVwbG90X2hlaWdodCwgd2lkdGggPSB0cmVlcGxvdF93aWR0aCkKZ29fdHJlZXBsb3QKZGV2Lm9mZigpCmdvX3RyZWVwbG90CgpyZWFjX3Rlcm1zaW0gPC0gZW5yaWNocGxvdDo6cGFpcndpc2VfdGVybXNpbSh0X2NmX2Vvc2lub3BoaWxfc2lnX3N2YV91cF9ncFtbIlJFQUNfZW5yaWNoIl1dKQpyZWFjX3RyZWVwbG90IDwtIHNtKHRyZWVwbG90KHJlYWNfdGVybXNpbSwgbGFiZWxfZm9ybWF0ID0gd3JhcF93aWR0aCkpCnBwKGZpbGUgPSBnbHVlKCJpbWFnZXMvb3ZlcnJlcHJlc2VudGF0aW9uL3RfY2ZfZW9zaW5vcGhpbF91cF9ncF9yZWFjLXZ7dmVyfS5wZGYiKSwKICAgaGVpZ2h0ID0gdHJlZXBsb3RfaGVpZ2h0LCB3aWR0aCA9IHRyZWVwbG90X3dpZHRoKQpyZWFjX3RyZWVwbG90CmRldi5vZmYoKQpgYGAKCiMjIyMgaW5jcmVhc2VkIGluIGZhaWwgdnMgY3VyZQoKYGBge3J9CnRfY2ZfZW9zaW5vcGhpbF9zaWdfc3ZhX2Rvd25fZ3AgPC0gc2ltcGxlX2dwcm9maWxlcigKICB0X2NmX2Vvc2lub3BoaWxfc2lnX3N2YV9kb3duLAogIGV4Y2VsID0gZ2x1ZSgie3hsc3hfcHJlZml4fS9HZW5lX1NldF9FbnJpY2htZW50L3RfY2ZfZW9zaW5vcGhpbF9kb3duX2dwLXZ7dmVyfS54bHN4IikpCmVucmljaHBsb3Q6OmRvdHBsb3QodF9jZl9lb3Npbm9waGlsX3NpZ19zdmFfZG93bl9ncFtbIkJQX2VucmljaCJdXSkKCmdvX3Rlcm1zaW0gPC0gZW5yaWNocGxvdDo6cGFpcndpc2VfdGVybXNpbSh0X2NmX2Vvc2lub3BoaWxfc2lnX3N2YV9kb3duX2dwW1siQlBfZW5yaWNoIl1dKQpnb190cmVlcGxvdCA8LSBzbSh0cmVlcGxvdChnb190ZXJtc2ltLCBsYWJlbF9mb3JtYXQgPSB3cmFwX3dpZHRoKSkKcHAoZmlsZSA9IGdsdWUoImltYWdlcy9vdmVycmVwcmVzZW50YXRpb24vdF9jZl9lb3Npbm9waGlsX2Rvd25fZ3BfZ28tdnt2ZXJ9LnBkZiIpLAogICBoZWlnaHQgPSB0cmVlcGxvdF9oZWlnaHQsIHdpZHRoID0gdHJlZXBsb3Rfd2lkdGgpCmdvX3RyZWVwbG90CmRldi5vZmYoKQpnb190cmVlcGxvdAoKIyMgVGhlcmUgaXMgb25seSBvbmUgcmVhY3RvbWUgaGl0LCBzbyBub3QgcGxvdHRpbmcgaXQuCmBgYAoKIyMjIyBCb3RoIHVwIGFuZCBkb3duCgpJIGV2YWx1YXRlZCB0aGlzIGFuZCB0aGUgJ3VwJyBzZXQgbmV4dCB0byBlYWNoIG90aGVyIGFuZCB0aGV5IGFyZQpleHRyZW1lbHkgc2ltaWxhcjoKCnVwOiAxNDggR08gaGl0cywgNjggVEYsIDAgSFBBCmJvdGg6IDE2OSBHTywgNjkgVEYsIGFuZCAyIEhQQQoKT3RoZXJ3aXNlIEkgdGhpbmsgdGhleSBhcmUgdGhlIHNhbWUuCgpgYGB7cn0KdF9jZl9lb3Npbm9waGlsX3NpZ19zdmFfYm90aF9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKAogIHRfY2ZfZW9zaW5vcGhpbF9zaWdfc3ZhX2JvdGgsCiAgZXhjZWwgPSBnbHVlKCJ7eGxzeF9wcmVmaXh9L0dlbmVfU2V0X0VucmljaG1lbnQvdF9jZl9lb3Npbm9waGlsX2JvdGhfZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9jZl9lb3Npbm9waGlsX3NpZ19zdmFfYm90aF9ncAplbnJpY2hwbG90Ojpkb3RwbG90KHRfY2ZfZW9zaW5vcGhpbF9zaWdfc3ZhX2JvdGhfZ3BbWyJCUF9lbnJpY2giXV0pCgpnb190ZXJtc2ltIDwtIGVucmljaHBsb3Q6OnBhaXJ3aXNlX3Rlcm1zaW0odF9jZl9lb3Npbm9waGlsX3NpZ19zdmFfYm90aF9ncFtbIkJQX2VucmljaCJdXSkKZ29fdHJlZXBsb3QgPC0gc20odHJlZXBsb3QoZ29fdGVybXNpbSwgbGFiZWxfZm9ybWFwID0gd3JhcF93aWR0aCkpCnBwKGZpbGUgPSBnbHVlKCJpbWFnZXMvb3ZlcnJlcHJlc2VudGF0aW9uL3RfY2ZfZW9zaW5vcGhpbF9ib3RoX2dwX2dvLXZ7dmVyfS5wZGYiKSwKICAgaGVpZ2h0ID0gdHJlZXBsb3RfaGVpZ2h0LCB3aWR0aCA9IHRyZWVwbG90X3dpZHRoKQpnb190cmVlcGxvdApkZXYub2ZmKCkKZ29fdHJlZXBsb3QKCnJlYWNfdGVybXNpbSA8LSBlbnJpY2hwbG90OjpwYWlyd2lzZV90ZXJtc2ltKHRfY2ZfZW9zaW5vcGhpbF9zaWdfc3ZhX2JvdGhfZ3BbWyJSRUFDX2VucmljaCJdXSkKcmVhY190cmVlcGxvdCA8LSBzbSh0cmVlcGxvdChyZWFjX3Rlcm1zaW0sIGxhYmVsX2Zvcm1hdCA9IHdyYXBfd2lkdGgpKQpwcChmaWxlID0gZ2x1ZSgiaW1hZ2VzL292ZXJyZXByZXNlbnRhdGlvbi90X2NmX2Vvc2lub3BoaWxfYm90aF9ncF9yZWFjLXZ7dmVyfS5wZGYiKSwKICAgaGVpZ2h0ID0gdHJlZXBsb3RfaGVpZ2h0LCB3aWR0aCA9IHRyZWVwbG90X3dpZHRoKQpyZWFjX3RyZWVwbG90CmRldi5vZmYoKQpgYGAKCiMjIyBjbHVzdGVycHJvZmlsZXIKCiMjIyMgaW5jcmVhc2VkIGluIGN1cmUgdnMgZmFpbAoKYGBge3J9CnRfY2ZfZW9zaW5vcGhpbF9zaWdfc3ZhX2NwX3VwIDwtIHNpbXBsZV9jcHJvZmlsZXIoCiAgdF9jZl9lb3Npbm9waGlsX3NpZ19zdmFfdXAsIGRlX3RhYmxlID0gdF9jZl9lb3Npbm9waGlsX3RhYmxlX3N2YSwKICBvcmdkYiA9ICJvcmcuSHMuZWcuZGIiLAogIGV4Y2VsID0gZ2x1ZSgie3hsc3hfcHJlZml4fS9HZW5lX1NldF9FbnJpY2htZW50L3RfY2ZfZW9zaW5vcGhpbF9zaWdfc3ZhX3VwX2NwLXZ7dmVyfS54bHN4IikpCmVucmljaHBsb3Q6OmRvdHBsb3QodF9jZl9lb3Npbm9waGlsX3NpZ19zdmFfY3BfdXBbWyJlbnJpY2hfb2JqZWN0cyJdXVtbIkJQX2FsbCJdXSkKYGBgCgojIyMjIGluY3JlYXNlZCBpbiBmYWlsIHZzIGN1cmUKCmBgYHtyfQp0X2NmX2Vvc2lub3BoaWxfc2lnX3N2YV9jcF9kb3duIDwtIHNpbXBsZV9jcHJvZmlsZXIoCiAgdF9jZl9lb3Npbm9waGlsX3NpZ19zdmFfZG93biwKICBvcmdkYiA9ICJvcmcuSHMuZWcuZGIiLAogIGV4Y2VsID0gZ2x1ZSgie3hsc3hfcHJlZml4fS9HZW5lX1NldF9FbnJpY2htZW50L3RfY2ZfZW9zaW5vcGhpbF9zaWdfc3ZhX2Rvd25fY3Atdnt2ZXJ9Lnhsc3giKSkKZW5yaWNocGxvdDo6ZG90cGxvdCh0X2NmX2Vvc2lub3BoaWxfc2lnX3N2YV9jcF9kb3duW1siZW5yaWNoX29iamVjdHMiXV1bWyJCUF9hbGwiXV0pCmBgYAoKIyMjIyBHU0VBCgpgYGB7cn0KdF9jZl9lb3Npbm9waGlsX3NpZ190b3BuX2dzZWEgPC0gcGxvdF90b3BuX2dzZWEodF9jZl9lb3Npbm9waGlsX3NpZ19zdmFfY3BfdXApCnRfY2ZfZW9zaW5vcGhpbF9zaWdfdG9wbl9nc2VhW1siR09fb3V0Y29tZV91cCJdXVtbMV1dCmBgYAoKIyMgTW9ub2N5dGVzIGN1cmUvZmFpbAoKYGBge3J9CmlucHV0X3hsc3ggPC0gZ2x1ZSgie2NmX3ByZWZpeH0vTW9ub2N5dGVzL3RfbW9ub2N5dGVfY2ZfdGFibGVfc3ZhLXZ7dmVyfS54bHN4IikKdF9jZl9tb25vY3l0ZV90YWJsZV9zdmEgPC0gdGFibGVfcmVhZGVyKGlucHV0X3hsc3gsICJvdXRjb21lIikKCmlucHV0X3hsc3ggPC0gZ2x1ZSgie2NmX3ByZWZpeH0vTW9ub2N5dGVzL3RfbW9ub2N5dGVfY2Zfc2lnX3N2YS12e3Zlcn0ueGxzeCIpCnRfY2ZfbW9ub2N5dGVfc2lnX3N2YV91cCA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJvdXRjb21lIikKdF9jZl9tb25vY3l0ZV9zaWdfc3ZhX2Rvd24gPC0gc2lnX3JlYWRlcihpbnB1dF94bHN4LCAib3V0Y29tZSIsICJkb3duIikKdF9jZl9tb25vY3l0ZV9zaWdfc3ZhX2JvdGggPC0gcmJpbmQuZGF0YS5mcmFtZSh0X2NmX21vbm9jeXRlX3NpZ19zdmFfdXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdF9jZl9tb25vY3l0ZV9zaWdfc3ZhX2Rvd24pCmBgYAoKIyMjIGdQcm9maWxlcgoKTm93IHRoYXQgSSBhbSBsb29raW5nIGJhY2sgb3ZlciB0aGVzZSByZXN1bHRzLCBJIGFtIG5vdCBjb21wZWx0ZWx5CmNlcnRhaW4gd2h5IEkgb25seSBkaWQgdGhlIGdwcm9maWxlciBzZWFyY2ggZm9yIHRoZSBzdmEgZGF0YS4uLgoKIyMjIyBpbmNyZWFzZWQgaW4gY3VyZSB2cyBmYWlsCgpgYGB7cn0KdF9jZl9tb25vY3l0ZV9zaWdfc3ZhX3VwX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9jZl9tb25vY3l0ZV9zaWdfc3ZhX3VwLAogIGV4Y2VsID0gZ2x1ZSgie3hsc3hfcHJlZml4fS9HZW5lX1NldF9FbnJpY2htZW50L3RfY2ZfbW9ub2N5dGVfdXBfZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9jZl9tb25vY3l0ZV9zaWdfc3ZhX3VwX2dwCmVucmljaHBsb3Q6OmRvdHBsb3QodF9jZl9tb25vY3l0ZV9zaWdfc3ZhX3VwX2dwW1siQlBfZW5yaWNoIl1dKQplbnJpY2hwbG90Ojpkb3RwbG90KHRfY2ZfbW9ub2N5dGVfc2lnX3N2YV91cF9ncFtbIlRGX2VucmljaCJdXSkKCmdvX3Rlcm1zaW0gPC0gZW5yaWNocGxvdDo6cGFpcndpc2VfdGVybXNpbSh0X2NmX21vbm9jeXRlX3NpZ19zdmFfdXBfZ3BbWyJCUF9lbnJpY2giXV0pCmdvX3RyZWVwbG90IDwtIHNtKHRyZWVwbG90KGdvX3Rlcm1zaW0sIGxhYmVsX2Zvcm1hdCA9IHdyYXBfd2lkdGgpKQpwcChmaWxlID0gImZpZ3VyZXMvb3ZlcnJlcHJlc2VudGF0aW9uL3RfY2ZfbW9ub2N5dGVfdXBfZ3BfZ28uc3ZnIiwKICAgaGVpZ2h0ID0gdHJlZXBsb3RfaGVpZ2h0LCB3aWR0aCA9IHRyZWVwbG90X3dpZHRoKQpnb190cmVlcGxvdApkZXYub2ZmKCkKZ29fdHJlZXBsb3QKYGBgCgojIyMjIGluY3JlYXNlZCBpbiBmYWlsIHZzIGN1cmUKCmBgYHtyfQp0X2NmX21vbm9jeXRlX3NpZ19zdmFfZG93bl9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKAogIHRfY2ZfbW9ub2N5dGVfc2lnX3N2YV9kb3duLAogIGV4Y2VsID0gZ2x1ZSgie3hsc3hfcHJlZml4fS9HZW5lX1NldF9FbnJpY2htZW50L3RfY2ZfbW9ub2N5dGVfZG93bl9ncC12e3Zlcn0ueGxzeCIpKQplbnJpY2hwbG90Ojpkb3RwbG90KHRfY2ZfbW9ub2N5dGVfc2lnX3N2YV9kb3duX2dwW1siQlBfZW5yaWNoIl1dKQoKZ29fdGVybXNpbSA8LSBlbnJpY2hwbG90OjpwYWlyd2lzZV90ZXJtc2ltKHRfY2ZfbW9ub2N5dGVfc2lnX3N2YV9kb3duX2dwW1siQlBfZW5yaWNoIl1dKQpnb190cmVlcGxvdCA8LSBzbSh0cmVlcGxvdChnb190ZXJtc2ltLCBsYWJlbF9mb3JtYXQgPSB3cmFwX3dpZHRoKSkKcHAoZmlsZSA9IGdsdWUoImltYWdlcy9vdmVycmVwcmVzZW50YXRpb24vdF9jZl9tb25vY3l0ZV9kb3duX2dwX2dvLXZ7dmVyfS5wZGYiKSwKICAgaGVpZ2h0ID0gdHJlZXBsb3RfaGVpZ2h0LCB3aWR0aCA9IHRyZWVwbG90X3dpZHRoKQpnb190cmVlcGxvdApkZXYub2ZmKCkKZ29fdHJlZXBsb3QKCiMjIEluc3VmZmljaWVudCByZXN1bHRzIHRvIG1ha2UgYSB0cmVlIHBsb3QuCmBgYAoKIyMjIyBCb3RoIHVwIGFuZCBkb3duCgpgYGB7cn0KdF9jZl9tb25vY3l0ZV9zaWdfc3ZhX2JvdGhfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcigKICB0X2NmX21vbm9jeXRlX3NpZ19zdmFfYm90aCwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX21vbm9jeXRlX2JvdGhfZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9jZl9tb25vY3l0ZV9zaWdfc3ZhX2JvdGhfZ3AKZW5yaWNocGxvdDo6ZG90cGxvdCh0X2NmX21vbm9jeXRlX3NpZ19zdmFfYm90aF9ncFtbIkJQX2VucmljaCJdXSkKCmdvX3Rlcm1zaW0gPC0gZW5yaWNocGxvdDo6cGFpcndpc2VfdGVybXNpbSh0X2NmX21vbm9jeXRlX3NpZ19zdmFfYm90aF9ncFtbIkJQX2VucmljaCJdXSkKZ29fdHJlZXBsb3QgPC0gc20odHJlZXBsb3QoZ29fdGVybXNpbSwgbGFiZWxfZm9ybWF0ID0gd3JhcF93aWR0aCkpCnBwKGZpbGUgPSBnbHVlKCJpbWFnZXMvb3ZlcnJlcHJlc2VudGF0aW9uL3RfY2ZfbW9ub2N5dGVfYm90aF9ncF9nby12e3Zlcn0ucGRmIiksCiAgIGhlaWdodCA9IHRyZWVwbG90X2hlaWdodCwgd2lkdGggPSB0cmVlcGxvdF93aWR0aCkKZ29fdHJlZXBsb3QKZGV2Lm9mZigpCmdvX3RyZWVwbG90CgojIyBJbnN1ZmZpY2llbnQgcmVzdWx0cyBmb3IgcmVhY3RvbWUKCnRmX3Rlcm1zaW0gPC0gZW5yaWNocGxvdDo6cGFpcndpc2VfdGVybXNpbSh0X2NmX21vbm9jeXRlX3NpZ19zdmFfYm90aF9ncFtbIlRGX2VucmljaCJdXSkKdGZfdHJlZXBsb3QgPC0gc20odHJlZXBsb3QodGZfdGVybXNpbSwgbGFiZWxfZm9ybWF0ID0gd3JhcF93aWR0aCkpCnBwKGZpbGUgPSBnbHVlKCJpbWFnZXMvb3ZlcnJlcHJlc2VudGF0aW9uL3RfY2ZfbW9ub2N5dGVfYm90aF9ncF90Zi12e3Zlcn0ucGRmIiksCiAgIGhlaWdodCA9IHRyZWVwbG90X2hlaWdodCwgd2lkdGggPSB0cmVlcGxvdF93aWR0aCkKdGZfdHJlZXBsb3QKZGV2Lm9mZigpCnRmX3RyZWVwbG90CmBgYAoKIyMjIGNsdXN0ZXJwcm9maWxlcgoKIyMjIyBpbmNyZWFzZWQgaW4gY3VyZSB2cyBmYWlsCgpgYGB7cn0KdF9jZl9tb25vY3l0ZV9zaWdfc3ZhX2NwX3VwIDwtIHNpbXBsZV9jcHJvZmlsZXIoCiAgdF9jZl9tb25vY3l0ZV9zaWdfc3ZhX3VwLCBkZV90YWJsZSA9IHRfY2ZfbW9ub2N5dGVfdGFibGVfc3ZhLAogIG9yZ2RiID0gIm9yZy5Icy5lZy5kYiIsCiAgZXhjZWwgPSBnbHVlKCJ7eGxzeF9wcmVmaXh9L0dlbmVfU2V0X0VucmljaG1lbnQvdF9jZl9tb25vY3l0ZV9zaWdfc3ZhX3VwX2NwLXZ7dmVyfS54bHN4IikpCmVucmljaHBsb3Q6OmRvdHBsb3QodF9jZl9tb25vY3l0ZV9zaWdfc3ZhX2NwX3VwW1siZW5yaWNoX29iamVjdHMiXV1bWyJCUF9hbGwiXV0pCmBgYAoKIyMjIyBpbmNyZWFzZWQgaW4gZmFpbCB2cyBjdXJlCgpgYGB7cn0KdF9jZl9tb25vY3l0ZV9zaWdfc3ZhX2NwX2Rvd24gPC0gc2ltcGxlX2Nwcm9maWxlcigKICB0X2NmX21vbm9jeXRlX3NpZ19zdmFfZG93biwKICBvcmdkYiA9ICJvcmcuSHMuZWcuZGIiLAogIGV4Y2VsID0gZ2x1ZSgie3hsc3hfcHJlZml4fS9HZW5lX1NldF9FbnJpY2htZW50L3RfY2ZfbW9ub2N5dGVfc2lnX3N2YV9kb3duX2NwLXZ7dmVyfS54bHN4IikpCmVucmljaHBsb3Q6OmRvdHBsb3QodF9jZl9tb25vY3l0ZV9zaWdfc3ZhX2NwX2Rvd25bWyJlbnJpY2hfb2JqZWN0cyJdXVtbIkJQX2FsbCJdXSkKYGBgCgojIyMjIEdTRUEKCmBgYHtyfQp0X2NmX21vbm9jeXRlX3NpZ190b3BuX2dzZWEgPC0gcGxvdF90b3BuX2dzZWEodF9jZl9tb25vY3l0ZV9zaWdfc3ZhX2NwX3VwKQp0X2NmX21vbm9jeXRlX3NpZ190b3BuX2dzZWFbWyJHT19vdXRjb21lX3VwIl1dW1sxXV0KYGBgCgojIyBOZXV0cm9waGlscyBjdXJlL2ZhaWwKCmBgYHtyfQppbnB1dF94bHN4IDwtIGdsdWUoIntjZl9wcmVmaXh9L05ldXRyb3BoaWxzL3RfbmV1dHJvcGhpbF9jZl90YWJsZV9zdmEtdnt2ZXJ9Lnhsc3giKQp0X2NmX25ldXRyb3BoaWxfdGFibGVfc3ZhIDwtIHRhYmxlX3JlYWRlcihpbnB1dF94bHN4LCAib3V0Y29tZSIpCgppbnB1dF94bHN4IDwtIGdsdWUoIntjZl9wcmVmaXh9L05ldXRyb3BoaWxzL3RfbmV1dHJvcGhpbF9jZl9zaWdfc3ZhLXZ7dmVyfS54bHN4IikKdF9jZl9uZXV0cm9waGlsX3NpZ19zdmFfdXAgPC0gc2lnX3JlYWRlcihpbnB1dF94bHN4LCAib3V0Y29tZSIpCnRfY2ZfbmV1dHJvcGhpbF9zaWdfc3ZhX2Rvd24gPC0gc2lnX3JlYWRlcihpbnB1dF94bHN4LCAib3V0Y29tZSIsICJkb3duIikKdF9jZl9uZXV0cm9waGlsX3NpZ19zdmFfYm90aCA8LSByYmluZC5kYXRhLmZyYW1lKHRfY2ZfbmV1dHJvcGhpbF9zaWdfc3ZhX3VwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRfY2ZfbmV1dHJvcGhpbF9zaWdfc3ZhX2Rvd24pCmBgYAoKIyMjIGdQcm9maWxlcgoKTm93IHRoYXQgSSBhbSBsb29raW5nIGJhY2sgb3ZlciB0aGVzZSByZXN1bHRzLCBJIGFtIG5vdCBjb21wZWx0ZWx5CmNlcnRhaW4gd2h5IEkgb25seSBkaWQgdGhlIGdwcm9maWxlciBzZWFyY2ggZm9yIHRoZSBzdmEgZGF0YS4uLgoKIyMjIyBpbmNyZWFzZWQgaW4gY3VyZSB2cyBmYWlsCgpgYGB7cn0KdF9jZl9uZXV0cm9waGlsX3NpZ19zdmFfdXBfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcigKICB0X2NmX25ldXRyb3BoaWxfc2lnX3N2YV91cCwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX25ldXRyb3BoaWxfdXBfZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9jZl9uZXV0cm9waGlsX3NpZ19zdmFfdXBfZ3AKZW5yaWNocGxvdDo6ZG90cGxvdCh0X2NmX25ldXRyb3BoaWxfc2lnX3N2YV91cF9ncFtbIkJQX2VucmljaCJdXSkKZW5yaWNocGxvdDo6ZG90cGxvdCh0X2NmX25ldXRyb3BoaWxfc2lnX3N2YV91cF9ncFtbIlRGX2VucmljaCJdXSkKCmdvX3Rlcm1zaW0gPC0gZW5yaWNocGxvdDo6cGFpcndpc2VfdGVybXNpbSh0X2NmX25ldXRyb3BoaWxfc2lnX3N2YV91cF9ncFtbIkJQX2VucmljaCJdXSkKZ29fdHJlZXBsb3QgPC0gc20odHJlZXBsb3QoZ29fdGVybXNpbSwgbGFiZWxfZm9ybWF0ID0gd3JhcF93aWR0aCkpCnBwKGZpbGUgPSAiZmlndXJlcy90X2NmX25ldXRyb3BoaWxfdXBfZ3BfZ28uc3ZnIiwKICAgaGVpZ2h0ID0gdHJlZXBsb3RfaGVpZ2h0LCB3aWR0aCA9IHRyZWVwbG90X3dpZHRoKQpnb190cmVlcGxvdApkZXYub2ZmKCkKZ29fdHJlZXBsb3QKYGBgCgojIyMjIGluY3JlYXNlZCBpbiBmYWlsIHZzIGN1cmUKCmBgYHtyfQp0X2NmX25ldXRyb3BoaWxfc2lnX3N2YV9kb3duX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9jZl9uZXV0cm9waGlsX3NpZ19zdmFfZG93biwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX25ldXRyb3BoaWxfZG93bl9ncC12e3Zlcn0ueGxzeCIpKQp0X2NmX25ldXRyb3BoaWxfc2lnX3N2YV9kb3duX2dwCgojIyBOb3QgbXVjaCB0byB3b3JrIHdpdGggaGVyZS4KYGBgCgojIyMjIEJvdGggdXAgYW5kIGRvd24KCmBgYHtyfQp0X2NmX25ldXRyb3BoaWxfc2lnX3N2YV9ib3RoX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9jZl9uZXV0cm9waGlsX3NpZ19zdmFfYm90aCwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX25ldXRyb3BoaWxfYm90aF9ncC12e3Zlcn0ueGxzeCIpKQp0X2NmX25ldXRyb3BoaWxfc2lnX3N2YV9ib3RoX2dwCmVucmljaHBsb3Q6OmRvdHBsb3QodF9jZl9uZXV0cm9waGlsX3NpZ19zdmFfYm90aF9ncFtbIkJQX2VucmljaCJdXSkKZW5yaWNocGxvdDo6ZG90cGxvdCh0X2NmX25ldXRyb3BoaWxfc2lnX3N2YV9ib3RoX2dwW1siVEZfZW5yaWNoIl1dKQoKZ29fdGVybXNpbSA8LSBlbnJpY2hwbG90OjpwYWlyd2lzZV90ZXJtc2ltKHRfY2ZfbmV1dHJvcGhpbF9zaWdfc3ZhX2JvdGhfZ3BbWyJCUF9lbnJpY2giXV0pCmdvX3RyZWVwbG90IDwtIHNtKHRyZWVwbG90KGdvX3Rlcm1zaW0sIGxhYmVsX2Zvcm1hdCA9IHdyYXBfd2lkdGgpKQpwcChmaWxlID0gZ2x1ZSgiaW1hZ2VzL292ZXJyZXByZXNlbnRhdGlvbi90X2NmX25ldXRyb3BoaWxfYm90aF9ncF9nby12e3Zlcn0ucGRmIiksCiAgIGhlaWdodCA9IHRyZWVwbG90X2hlaWdodCwgd2lkdGggPSB0cmVlcGxvdF93aWR0aCkKZ29fdHJlZXBsb3QKZGV2Lm9mZigpCmdvX3RyZWVwbG90CgojIyBJbnN1ZmZpY2llbnQgcmVzdWx0cyBmb3IgcmVhY3RvbWUKYGBgCgojIyMgY2x1c3RlcnByb2ZpbGVyCgojIyMjIGluY3JlYXNlZCBpbiBjdXJlIHZzIGZhaWwKCmBgYHtyfQp0X2NmX25ldXRyb3BoaWxfc2lnX3N2YV9jcF91cCA8LSBzaW1wbGVfY3Byb2ZpbGVyKAogIHRfY2ZfbmV1dHJvcGhpbF9zaWdfc3ZhX3VwLCBkZV90YWJsZSA9IHRfY2ZfbmV1dHJvcGhpbF90YWJsZV9zdmEsCiAgb3JnZGIgPSAib3JnLkhzLmVnLmRiIiwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX25ldXRyb3BoaWxfc2lnX3N2YV91cF9jcC12e3Zlcn0ueGxzeCIpKQplbnJpY2hwbG90Ojpkb3RwbG90KHRfY2ZfbmV1dHJvcGhpbF9zaWdfc3ZhX2NwX3VwW1siZW5yaWNoX29iamVjdHMiXV1bWyJCUF9hbGwiXV0pCmBgYAoKIyMjIyBpbmNyZWFzZWQgaW4gZmFpbCB2cyBjdXJlCgpgYGB7cn0KdF9jZl9uZXV0cm9waGlsX3NpZ19zdmFfY3BfZG93biA8LSBzaW1wbGVfY3Byb2ZpbGVyKAogIHRfY2ZfbmV1dHJvcGhpbF9zaWdfc3ZhX2Rvd24sCiAgb3JnZGIgPSAib3JnLkhzLmVnLmRiIiwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX25ldXRyb3BoaWxfc2lnX3N2YV9kb3duX2NwLXZ7dmVyfS54bHN4IikpCmVucmljaHBsb3Q6OmRvdHBsb3QodF9jZl9uZXV0cm9waGlsX3NpZ19zdmFfY3BfZG93bltbImVucmljaF9vYmplY3RzIl1dW1siQlBfYWxsIl1dKQpgYGAKCiMjIyMgR1NFQQoKYGBge3J9CnRfY2ZfbmV1dHJvcGhpbF9zaWdfdG9wbl9nc2VhIDwtIHBsb3RfdG9wbl9nc2VhKHRfY2ZfbmV1dHJvcGhpbF9zaWdfc3ZhX2NwX3VwKQp0X2NmX25ldXRyb3BoaWxfc2lnX3RvcG5fZ3NlYVtbIkdPX291dGNvbWVfdXAiXV1bWzFdXQpgYGAKCiMjIExvb2sgYXQgdmlzaXQgMSBhbmQgc2VlIGlmIGFueXRoaW5nIHBvcHMgb3V0CgpgYGB7cn0KaW5wdXRfeGxzeCA8LSBnbHVlKCJ7Y2ZfcHJlZml4fS9Nb25vY3l0ZXMvdF9tb25vY3l0ZV92MV9jZl90YWJsZV9zdmEtdnt2ZXJ9Lnhsc3giKQp0X2NmX21vbm9jeXRlX3YxX3RhYmxlX3N2YSA8LSB0YWJsZV9yZWFkZXIoaW5wdXRfeGxzeCwgIm91dGNvbWUiKQoKaW5wdXRfeGxzeCA8LSBnbHVlKCJ7Y2ZfcHJlZml4fS9Nb25vY3l0ZXMvdF9tb25vY3l0ZV92MV9jZl9zaWdfc3ZhLXZ7dmVyfS54bHN4IikKdF9jZl9tb25vY3l0ZV92MV9zaWdfc3ZhX3VwIDwtIHNpZ19yZWFkZXIoaW5wdXRfeGxzeCwgIm91dGNvbWUiKQp0X2NmX21vbm9jeXRlX3YxX3NpZ19zdmFfZG93biA8LSBzaWdfcmVhZGVyKGlucHV0X3hsc3gsICJvdXRjb21lIiwgImRvd24iKQp0X2NmX21vbm9jeXRlX3YxX3NpZ19zdmFfYm90aCA8LSByYmluZC5kYXRhLmZyYW1lKHRfY2ZfbW9ub2N5dGVfdjFfc2lnX3N2YV91cCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0X2NmX21vbm9jeXRlX3YxX3NpZ19zdmFfZG93bikKYGBgCgojIyMgR2VuZSBTZXQgRW5yaWNobWVudDogZ1Byb2ZpbGVyIE1vbm9jeXRlcyBieSB2aXNpdCwgVjEKClYxOiBVcDogMTQgZ2VuZXM7IE5vIGNhdGVnb3JpZXMKVjE6IERvd246IDUyIGdlbmVzOyAyMCBHTywgNSBURgoKYGBge3J9CnRfY2ZfbW9ub2N5dGVfdjFfc2lnX3N2YV91cF9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKAogIHRfY2ZfbW9ub2N5dGVfdjFfc2lnX3N2YV91cCwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX25ldXRyb3BoaWxfdXBfZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9jZl9tb25vY3l0ZV92MV9zaWdfc3ZhX3VwX2dwCnRfY2ZfbW9ub2N5dGVfdjFfc2lnX3N2YV9kb3duX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9jZl9tb25vY3l0ZV92MV9zaWdfc3ZhX2Rvd24sCiAgZXhjZWwgPSBnbHVlKCJ7eGxzeF9wcmVmaXh9L0dlbmVfU2V0X0VucmljaG1lbnQvdF9jZl9uZXV0cm9waGlsX2Rvd25fZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9jZl9tb25vY3l0ZV92MV9zaWdfc3ZhX2Rvd25fZ3AKdF9jZl9tb25vY3l0ZV92MV9zaWdfc3ZhX2JvdGhfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcigKICB0X2NmX21vbm9jeXRlX3YxX3NpZ19zdmFfYm90aCwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX25ldXRyb3BoaWxfZG93bl9ncC12e3Zlcn0ueGxzeCIpKQp0X2NmX21vbm9jeXRlX3YxX3NpZ19zdmFfYm90aF9ncApgYGAKCkkgbGlrZSBjYXRzIQoKIyMjIyBjbHVzdGVyUHJvZmlsZXIKCmBgYHtyfQp0X2NmX21vbm9jeXRlX3YxX3NpZ19zdmFfdXBfY3AgPC0gc2ltcGxlX2Nwcm9maWxlcih0X2NmX21vbm9jeXRlX3YxX3NpZ19zdmFfdXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRfY2ZfbW9ub2N5dGVfdjFfdGFibGVfc3ZhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmdkYiA9ICJvcmcuSHMuZWcuZGIiKQplbnJpY2hwbG90Ojpkb3RwbG90KHRfY2ZfbW9ub2N5dGVfdjFfc2lnX3N2YV91cF9jcFtbImVucmljaF9vYmplY3RzIl1dW1siQlBfYWxsIl1dKQp0X2NmX21vbm9jeXRlX3YxX3RvcG5fZ3NlYSA8LSBwbG90X3RvcG5fZ3NlYSh0X2NmX21vbm9jeXRlX3YxX3NpZ19zdmFfdXBfY3ApCnRfY2ZfbW9ub2N5dGVfdjFfdG9wbl9nc2VhW1siR09fb3V0Y29tZV91cCJdXVtbMV1dCmBgYAoKIyMjIE5ldXRyb3BoaWxzIHYxCgpgYGB7cn0KaW5wdXRfeGxzeCA8LSBnbHVlKCJ7Y2ZfcHJlZml4fS9OZXV0cm9waGlscy90X25ldXRyb3BoaWxfdjFfY2ZfdGFibGVfc3ZhLXZ7dmVyfS54bHN4IikKdF9jZl9uZXV0cm9waGlsX3YxX3RhYmxlX3N2YSA8LSB0YWJsZV9yZWFkZXIoaW5wdXRfeGxzeCwgIm91dGNvbWUiKQoKaW5wdXRfeGxzeCA8LSBnbHVlKCJ7Y2ZfcHJlZml4fS9OZXV0cm9waGlscy90X25ldXRyb3BoaWxfdjFfY2Zfc2lnX3N2YS12e3Zlcn0ueGxzeCIpCnRfY2ZfbmV1dHJvcGhpbF92MV9zaWdfc3ZhX3VwIDwtIHNpZ19yZWFkZXIoaW5wdXRfeGxzeCwgIm91dGNvbWUiKQp0X2NmX25ldXRyb3BoaWxfdjFfc2lnX3N2YV9kb3duIDwtIHNpZ19yZWFkZXIoaW5wdXRfeGxzeCwgIm91dGNvbWUiLCAiZG93biIpCnRfY2ZfbmV1dHJvcGhpbF92MV9zaWdfc3ZhX2JvdGggPC0gcmJpbmQuZGF0YS5mcmFtZSh0X2NmX25ldXRyb3BoaWxfdjFfc2lnX3N2YV91cCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0X2NmX25ldXRyb3BoaWxfdjFfc2lnX3N2YV9kb3duKQpgYGAKCiMjIyBHZW5lIFNldCBFbnJpY2htZW50OiBnUHJvZmlsZXIgTmV1dHJvcGhpbHMgYnkgdmlzaXQsIFYxCgpgYGB7cn0KdF9jZl9uZXV0cm9waGlsX3YxX3NpZ19zdmFfdXBfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcigKICB0X2NmX25ldXRyb3BoaWxfdjFfc2lnX3N2YV91cCwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX25ldXRyb3BoaWxfdXBfZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9jZl9uZXV0cm9waGlsX3YxX3NpZ19zdmFfdXBfZ3AKdF9jZl9uZXV0cm9waGlsX3YxX3NpZ19zdmFfZG93bl9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKAogIHRfY2ZfbmV1dHJvcGhpbF92MV9zaWdfc3ZhX2Rvd24sCiAgZXhjZWwgPSBnbHVlKCJ7eGxzeF9wcmVmaXh9L0dlbmVfU2V0X0VucmljaG1lbnQvdF9jZl9uZXV0cm9waGlsX2Rvd25fZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9jZl9uZXV0cm9waGlsX3YxX3NpZ19zdmFfZG93bl9ncAp0X2NmX25ldXRyb3BoaWxfdjFfc2lnX3N2YV9ib3RoX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9jZl9uZXV0cm9waGlsX3YxX3NpZ19zdmFfYm90aCwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX25ldXRyb3BoaWxfZG93bl9ncC12e3Zlcn0ueGxzeCIpKQp0X2NmX25ldXRyb3BoaWxfdjFfc2lnX3N2YV9ib3RoX2dwCmBgYAoKIyMjIyBjbHVzdGVyUHJvZmlsZXIKCmBgYHtyfQp0X2NmX25ldXRyb3BoaWxfdjFfc2lnX3N2YV91cF9jcCA8LSBzaW1wbGVfY3Byb2ZpbGVyKHRfY2ZfbmV1dHJvcGhpbF92MV9zaWdfc3ZhX3VwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRfY2ZfbmV1dHJvcGhpbF92MV90YWJsZV9zdmEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JnZGIgPSAib3JnLkhzLmVnLmRiIikKZW5yaWNocGxvdDo6ZG90cGxvdCh0X2NmX25ldXRyb3BoaWxfdjFfc2lnX3N2YV91cF9jcFtbImVucmljaF9vYmplY3RzIl1dW1siQlBfYWxsIl1dKQp0X2NmX25ldXRyb3BoaWxfdjFfdG9wbl9nc2VhIDwtIHBsb3RfdG9wbl9nc2VhKHRfY2ZfbmV1dHJvcGhpbF92MV9zaWdfc3ZhX3VwX2NwKQp0X2NmX25ldXRyb3BoaWxfdjFfdG9wbl9nc2VhW1siR09fb3V0Y29tZV91cCJdXVtbMV1dCmBgYAoKIyMjIEVvc2lub3BoaWxzIHYxCgpgYGB7cn0KaW5wdXRfeGxzeCA8LSBnbHVlKCJ7Y2ZfcHJlZml4fS9Fb3Npbm9waGlscy90X2Vvc2lub3BoaWxfdjFfY2ZfdGFibGVfc3ZhLXZ7dmVyfS54bHN4IikKdF9jZl9lb3Npbm9waGlsX3YxX3RhYmxlX3N2YSA8LSB0YWJsZV9yZWFkZXIoaW5wdXRfeGxzeCwgIm91dGNvbWUiKQoKaW5wdXRfeGxzeCA8LSBnbHVlKCJ7Y2ZfcHJlZml4fS9Fb3Npbm9waGlscy90X2Vvc2lub3BoaWxfdjFfY2Zfc2lnX3N2YS12e3Zlcn0ueGxzeCIpCnRfY2ZfZW9zaW5vcGhpbF92MV9zaWdfc3ZhX3VwIDwtIHNpZ19yZWFkZXIoaW5wdXRfeGxzeCwgIm91dGNvbWUiKQp0X2NmX2Vvc2lub3BoaWxfdjFfc2lnX3N2YV9kb3duIDwtIHNpZ19yZWFkZXIoaW5wdXRfeGxzeCwgIm91dGNvbWUiLCAiZG93biIpCnRfY2ZfZW9zaW5vcGhpbF92MV9zaWdfc3ZhX2JvdGggPC0gcmJpbmQuZGF0YS5mcmFtZSh0X2NmX2Vvc2lub3BoaWxfdjFfc2lnX3N2YV91cCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0X2NmX2Vvc2lub3BoaWxfdjFfc2lnX3N2YV9kb3duKQpgYGAKCiMjIyBHZW5lIFNldCBFbnJpY2htZW50OiBnUHJvZmlsZXIgRW9zaW5vcGhpbHMgYnkgdmlzaXQsIFYxCgpgYGB7cn0KdF9jZl9lb3Npbm9waGlsX3YxX3NpZ19zdmFfdXBfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcigKICB0X2NmX2Vvc2lub3BoaWxfdjFfc2lnX3N2YV91cCwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX2Vvc2lub3BoaWxfdXBfZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9jZl9lb3Npbm9waGlsX3YxX3NpZ19zdmFfdXBfZ3AKdF9jZl9lb3Npbm9waGlsX3YxX3NpZ19zdmFfZG93bl9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKAogIHRfY2ZfZW9zaW5vcGhpbF92MV9zaWdfc3ZhX2Rvd24sCiAgZXhjZWwgPSBnbHVlKCJ7eGxzeF9wcmVmaXh9L0dlbmVfU2V0X0VucmljaG1lbnQvdF9jZl9lb3Npbm9waGlsX2Rvd25fZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9jZl9lb3Npbm9waGlsX3YxX3NpZ19zdmFfZG93bl9ncAp0X2NmX2Vvc2lub3BoaWxfdjFfc2lnX3N2YV9ib3RoX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9jZl9lb3Npbm9waGlsX3YxX3NpZ19zdmFfYm90aCwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX2Vvc2lub3BoaWxfZG93bl9ncC12e3Zlcn0ueGxzeCIpKQp0X2NmX2Vvc2lub3BoaWxfdjFfc2lnX3N2YV9ib3RoX2dwCmBgYAoKIyMjIyBjbHVzdGVyUHJvZmlsZXIKCmBgYHtyfQp0X2NmX2Vvc2lub3BoaWxfdjFfc2lnX3N2YV91cF9jcCA8LSBzaW1wbGVfY3Byb2ZpbGVyKHRfY2ZfZW9zaW5vcGhpbF92MV9zaWdfc3ZhX3VwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRfY2ZfZW9zaW5vcGhpbF92MV90YWJsZV9zdmEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JnZGIgPSAib3JnLkhzLmVnLmRiIikKZW5yaWNocGxvdDo6ZG90cGxvdCh0X2NmX2Vvc2lub3BoaWxfdjFfc2lnX3N2YV91cF9jcFtbImVucmljaF9vYmplY3RzIl1dW1siQlBfYWxsIl1dKQp0X2NmX2Vvc2lub3BoaWxfdjFfdG9wbl9nc2VhIDwtIHBsb3RfdG9wbl9nc2VhKHRfY2ZfZW9zaW5vcGhpbF92MV9zaWdfc3ZhX3VwX2NwKQp0X2NmX2Vvc2lub3BoaWxfdjFfdG9wbl9nc2VhW1siR09fb3V0Y29tZV91cCJdXVtbMV1dCmBgYAoKIyBSZXBlYXQgc29tZSBvZiB0aGlzIGZvciB0aGUgbWl4ZWQgbGluZWFyIG1vZGVsIHJlc3VsdHMKClNwZWFraW5nIHdpdGggTWFyaWEgQWRlbGFpZGEsIGl0IHNvdW5kcyBsaWtlIHRoZSBtb3N0IGFwcHJvcHJpYXRlIHNldAp0byB0cnkgZm9yIG5vdyBpcyB8bG9nRkN8ID49IDAuNTggYW5kIHAgPD0gMC4wNS4gIEkgd3JvdGUgb3V0IHRoZQpkcmVhbSByZXN1bHRzIGluIGEgc2ltcGxlciBhbmQgbGVzcyBmdW4gd2F5IHRoYW4gZXZlcnl0aGluZyBlbHNlLgoKYGBge3J9CnN0YXJ0X3RibCA8LSB0YWJsZV9yZWFkZXIoCiAgZ2x1ZSgiZXhjZWwvbWl4ZWRfYWxsX2NlbGx0eXBlc19ub2Jpb3BfdGFibGUtdnt2ZXJ9Lnhsc3giKSwKICBzaGVldCA9ICJjb250cmFzdHMiKQpzaWdfdXBfaWR4IDwtIHN0YXJ0X3RibFtbImZhaWx1cmVfdnNfY3VyZV9sb2dmYyJdXSA+PSAwLjU4ICYKICBzdGFydF90YmxbWyJmYWlsdXJlX3ZzX2N1cmVfcF92YWx1ZSJdXSA8PSAwLjA1CnNpZ19kb3duX2lkeCA8LSBzdGFydF90YmxbWyJmYWlsdXJlX3ZzX2N1cmVfbG9nZmMiXV0gPD0gLTAuNTggJgogIHN0YXJ0X3RibFtbImZhaWx1cmVfdnNfY3VyZV9wX3ZhbHVlIl1dIDw9IDAuMDUKCnVwX2dlbmVzIDwtIHJvd25hbWVzKHN0YXJ0X3RibClbc2lnX3VwX2lkeF0KZG93bl9nZW5lcyA8LSByb3duYW1lcyhzdGFydF90YmwpW3NpZ19kb3duX2lkeF0KCnRfZHJlYW1fYWxsX3VwX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdXBfZ2VuZXMsCiAgZXhjZWwgPSBnbHVlKCJleGNlbC9kcmVhbV9hbGxfdXBfZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9kcmVhbV9hbGxfZG93bl9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKAogIGRvd25fZ2VuZXMsCiAgZXhjZWwgPSBnbHVlKCJleGNlbC9kcmVhbV9hbGxfZG93bl9ncC12e3Zlcn0ueGxzeCIpKQoKZ29fdGVybXNpbSA8LSBlbnJpY2hwbG90OjpwYWlyd2lzZV90ZXJtc2ltKHRfZHJlYW1fYWxsX3VwX2dwW1siQlBfZW5yaWNoIl1dKQpnb190cmVlcGxvdCA8LSBzbSh0cmVlcGxvdChnb190ZXJtc2ltLCBsYWJlbF9mb3JtYXQgPSB3cmFwX3dpZHRoKSkKcHAoZmlsZSA9IGdsdWUoImltYWdlcy9vdmVycmVwcmVzZW50YXRpb24vdF9kcmVhbV9hbGxfdXBfZ3BfZ28tdnt2ZXJ9LnBkZiIpLAogICBoZWlnaHQgPSB0cmVlcGxvdF9oZWlnaHQsIHdpZHRoID0gdHJlZXBsb3Rfd2lkdGgpCmdvX3RyZWVwbG90CmRldi5vZmYoKQpnb190cmVlcGxvdAoKZ29fdGVybXNpbSA8LSBlbnJpY2hwbG90OjpwYWlyd2lzZV90ZXJtc2ltKHRfZHJlYW1fYWxsX2Rvd25fZ3BbWyJCUF9lbnJpY2giXV0pCmdvX3RyZWVwbG90IDwtIHNtKHRyZWVwbG90KGdvX3Rlcm1zaW0sIGxhYmVsX2Zvcm1hdCA9IHdyYXBfd2lkdGgpKQpwcChmaWxlID0gZ2x1ZSgiaW1hZ2VzL292ZXJyZXByZXNlbnRhdGlvbi90X2RyZWFtX2FsbF9kb3duX2dwX2dvLXZ7dmVyfS5wZGYiKSwKICAgaGVpZ2h0ID0gdHJlZXBsb3RfaGVpZ2h0LCB3aWR0aCA9IHRyZWVwbG90X3dpZHRoKQpnb190cmVlcGxvdApkZXYub2ZmKCkKZ29fdHJlZXBsb3QKYGBgCgojIyBNb25vY3l0ZXMKCmBgYHtyfQpzdGFydF90YmwgPC0gdGFibGVfcmVhZGVyKAogIGdsdWUoImV4Y2VsL21peGVkX21vbm9jeXRlX3RhYmxlLXZ7dmVyfS54bHN4IiksCiAgc2hlZXQgPSAiY29udHJhc3RzIikKc2lnX3VwX2lkeCA8LSBzdGFydF90YmxbWyJmYWlsdXJlX3ZzX2N1cmVfbG9nZmMiXV0gPj0gMC41OCAmCiAgc3RhcnRfdGJsW1siZmFpbHVyZV92c19jdXJlX3BfdmFsdWUiXV0gPD0gMC4wNQpzaWdfZG93bl9pZHggPC0gc3RhcnRfdGJsW1siZmFpbHVyZV92c19jdXJlX2xvZ2ZjIl1dIDw9IC0wLjU4ICYKICBzdGFydF90YmxbWyJmYWlsdXJlX3ZzX2N1cmVfcF92YWx1ZSJdXSA8PSAwLjA1Cgp1cF9nZW5lcyA8LSByb3duYW1lcyhzdGFydF90YmwpW3NpZ191cF9pZHhdCmRvd25fZ2VuZXMgPC0gcm93bmFtZXMoc3RhcnRfdGJsKVtzaWdfZG93bl9pZHhdCgp0X2RyZWFtX21vbm9jeXRlX3VwX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdXBfZ2VuZXMsCiAgZXhjZWwgPSBnbHVlKCJleGNlbC9kcmVhbV9tb25vY3l0ZV91cF9ncC12e3Zlcn0ueGxzeCIpKQp0X2RyZWFtX2FsbF9kb3duX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgZG93bl9nZW5lcywKICBleGNlbCA9IGdsdWUoImV4Y2VsL2RyZWFtX21vbm9jeXRlX2Rvd25fZ3Atdnt2ZXJ9Lnhsc3giKSkKCmdvX3Rlcm1zaW0gPC0gZW5yaWNocGxvdDo6cGFpcndpc2VfdGVybXNpbSh0X2RyZWFtX2FsbF91cF9ncFtbIkJQX2VucmljaCJdXSkKZ29fdHJlZXBsb3QgPC0gc20odHJlZXBsb3QoZ29fdGVybXNpbSwgbGFiZWxfZm9ybWF0ID0gd3JhcF93aWR0aCkpCnBwKGZpbGUgPSBnbHVlKCJpbWFnZXMvb3ZlcnJlcHJlc2VudGF0aW9uL3RfZHJlYW1fbW9ub2N5dGVfdXBfZ3BfZ28tdnt2ZXJ9LnBkZiIpLAogICBoZWlnaHQgPSB0cmVlcGxvdF9oZWlnaHQsIHdpZHRoID0gdHJlZXBsb3Rfd2lkdGgpCmdvX3RyZWVwbG90CmRldi5vZmYoKQpnb190cmVlcGxvdAoKZ29fdGVybXNpbSA8LSBlbnJpY2hwbG90OjpwYWlyd2lzZV90ZXJtc2ltKHRfZHJlYW1fYWxsX2Rvd25fZ3BbWyJCUF9lbnJpY2giXV0pCmdvX3RyZWVwbG90IDwtIHNtKHRyZWVwbG90KGdvX3Rlcm1zaW0sIGxhYmVsX2Zvcm1hdCA9IHdyYXBfd2lkdGgpKQpwcChmaWxlID0gZ2x1ZSgiaW1hZ2VzL292ZXJyZXByZXNlbnRhdGlvbi90X2RyZWFtX21vbm9jeXRlX2Rvd25fZ3BfZ28tdnt2ZXJ9LnBkZiIpLAogICBoZWlnaHQgPSB0cmVlcGxvdF9oZWlnaHQsIHdpZHRoID0gdHJlZXBsb3Rfd2lkdGgpCmdvX3RyZWVwbG90CmRldi5vZmYoKQpnb190cmVlcGxvdApgYGAKCiMjIE5ldXRyb3BoaWxzCgpgYGB7cn0Kc3RhcnRfdGJsIDwtIHRhYmxlX3JlYWRlcigKICBnbHVlKCJleGNlbC9taXhlZF9uZXV0cm9waGlsX3RhYmxlLXZ7dmVyfS54bHN4IiksCiAgc2hlZXQgPSAiY29udHJhc3RzIikKc2lnX3VwX2lkeCA8LSBzdGFydF90YmxbWyJmYWlsdXJlX3ZzX2N1cmVfbG9nZmMiXV0gPj0gMC41OCAmCiAgc3RhcnRfdGJsW1siZmFpbHVyZV92c19jdXJlX3BfdmFsdWUiXV0gPD0gMC4wNQpzaWdfZG93bl9pZHggPC0gc3RhcnRfdGJsW1siZmFpbHVyZV92c19jdXJlX2xvZ2ZjIl1dIDw9IC0wLjU4ICYKICBzdGFydF90YmxbWyJmYWlsdXJlX3ZzX2N1cmVfcF92YWx1ZSJdXSA8PSAwLjA1Cgp1cF9nZW5lcyA8LSByb3duYW1lcyhzdGFydF90YmwpW3NpZ191cF9pZHhdCmRvd25fZ2VuZXMgPC0gcm93bmFtZXMoc3RhcnRfdGJsKVtzaWdfZG93bl9pZHhdCgp0X2RyZWFtX25ldXRyb3BoaWxfdXBfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcigKICB1cF9nZW5lcywKICBleGNlbCA9IGdsdWUoImV4Y2VsL2RyZWFtX25ldXRyb3BoaWxfdXBfZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9kcmVhbV9hbGxfZG93bl9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKAogIGRvd25fZ2VuZXMsCiAgZXhjZWwgPSBnbHVlKCJleGNlbC9kcmVhbV9uZXV0cm9waGlsX2Rvd25fZ3Atdnt2ZXJ9Lnhsc3giKSkKCmdvX3Rlcm1zaW0gPC0gZW5yaWNocGxvdDo6cGFpcndpc2VfdGVybXNpbSh0X2RyZWFtX2FsbF91cF9ncFtbIkJQX2VucmljaCJdXSkKZ29fdHJlZXBsb3QgPC0gc20odHJlZXBsb3QoZ29fdGVybXNpbSwgbGFiZWxfZm9ybWF0ID0gd3JhcF93aWR0aCkpCnBwKGZpbGUgPSBnbHVlKCJpbWFnZXMvb3ZlcnJlcHJlc2VudGF0aW9uL3RfZHJlYW1fbmV1dHJvcGhpbF91cF9ncF9nby12e3Zlcn0ucGRmIiksCiAgIGhlaWdodCA9IHRyZWVwbG90X2hlaWdodCwgd2lkdGggPSB0cmVlcGxvdF93aWR0aCkKZ29fdHJlZXBsb3QKZGV2Lm9mZigpCmdvX3RyZWVwbG90Cgpnb190ZXJtc2ltIDwtIGVucmljaHBsb3Q6OnBhaXJ3aXNlX3Rlcm1zaW0odF9kcmVhbV9hbGxfZG93bl9ncFtbIkJQX2VucmljaCJdXSkKZ29fdHJlZXBsb3QgPC0gc20odHJlZXBsb3QoZ29fdGVybXNpbSwgbGFiZWxfZm9ybWF0ID0gd3JhcF93aWR0aCkpCnBwKGZpbGUgPSBnbHVlKCJpbWFnZXMvb3ZlcnJlcHJlc2VudGF0aW9uL3RfZHJlYW1fbmV1dHJvcGhpbF9kb3duX2dwX2dvLXZ7dmVyfS5wZGYiKSwKICAgaGVpZ2h0ID0gdHJlZXBsb3RfaGVpZ2h0LCB3aWR0aCA9IHRyZWVwbG90X3dpZHRoKQpnb190cmVlcGxvdApkZXYub2ZmKCkKZ29fdHJlZXBsb3QKYGBgCgojIyBFb3Npbm9waGlscwoKYGBge3J9CnN0YXJ0X3RibCA8LSB0YWJsZV9yZWFkZXIoCiAgZ2x1ZSgiZXhjZWwvbWl4ZWRfZW9zaW5vcGhpbF90YWJsZS12e3Zlcn0ueGxzeCIpLAogIHNoZWV0ID0gImNvbnRyYXN0cyIpCnNpZ191cF9pZHggPC0gc3RhcnRfdGJsW1siZmFpbHVyZV92c19jdXJlX2xvZ2ZjIl1dID49IDAuNTggJgogIHN0YXJ0X3RibFtbImZhaWx1cmVfdnNfY3VyZV9wX3ZhbHVlIl1dIDw9IDAuMDUKc2lnX2Rvd25faWR4IDwtIHN0YXJ0X3RibFtbImZhaWx1cmVfdnNfY3VyZV9sb2dmYyJdXSA8PSAtMC41OCAmCiAgc3RhcnRfdGJsW1siZmFpbHVyZV92c19jdXJlX3BfdmFsdWUiXV0gPD0gMC4wNQoKdXBfZ2VuZXMgPC0gcm93bmFtZXMoc3RhcnRfdGJsKVtzaWdfdXBfaWR4XQpkb3duX2dlbmVzIDwtIHJvd25hbWVzKHN0YXJ0X3RibClbc2lnX2Rvd25faWR4XQoKdF9kcmVhbV9lb3Npbm9waGlsX3VwX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdXBfZ2VuZXMsCiAgZXhjZWwgPSBnbHVlKCJleGNlbC9kcmVhbV9lb3Npbm9waGlsX3VwX2dwLXZ7dmVyfS54bHN4IikpCnRfZHJlYW1fYWxsX2Rvd25fZ3AgPC0gc2ltcGxlX2dwcm9maWxlcigKICBkb3duX2dlbmVzLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvZHJlYW1fZW9zaW5vcGhpbF9kb3duX2dwLXZ7dmVyfS54bHN4IikpCgpnb190ZXJtc2ltIDwtIGVucmljaHBsb3Q6OnBhaXJ3aXNlX3Rlcm1zaW0odF9kcmVhbV9hbGxfdXBfZ3BbWyJCUF9lbnJpY2giXV0pCmdvX3RyZWVwbG90IDwtIHNtKHRyZWVwbG90KGdvX3Rlcm1zaW0sIGxhYmVsX2Zvcm1hdCA9IHdyYXBfd2lkdGgpKQpwcChmaWxlID0gZ2x1ZSgiaW1hZ2VzL292ZXJyZXByZXNlbnRhdGlvbi90X2RyZWFtX2Vvc2lub3BoaWxfdXBfZ3BfZ28tdnt2ZXJ9LnBkZiIpLAogICBoZWlnaHQgPSB0cmVlcGxvdF9oZWlnaHQsIHdpZHRoID0gdHJlZXBsb3Rfd2lkdGgpCmdvX3RyZWVwbG90CmRldi5vZmYoKQpnb190cmVlcGxvdAoKZ29fdGVybXNpbSA8LSBlbnJpY2hwbG90OjpwYWlyd2lzZV90ZXJtc2ltKHRfZHJlYW1fYWxsX2Rvd25fZ3BbWyJCUF9lbnJpY2giXV0pCmdvX3RyZWVwbG90IDwtIHNtKHRyZWVwbG90KGdvX3Rlcm1zaW0sIGxhYmVsX2Zvcm1hdCA9IHdyYXBfd2lkdGgpKQpwcChmaWxlID0gZ2x1ZSgiaW1hZ2VzL292ZXJyZXByZXNlbnRhdGlvbi90X2RyZWFtX2Vvc2lub3BoaWxfZG93bl9ncF9nby12e3Zlcn0ucGRmIiksCiAgIGhlaWdodCA9IHRyZWVwbG90X2hlaWdodCwgd2lkdGggPSB0cmVlcGxvdF93aWR0aCkKZ29fdHJlZXBsb3QKZGV2Lm9mZigpCmdvX3RyZWVwbG90CmBgYAoKIyBCaWJsaW9ncmFwaHkK