1 Libraries Setup

library("hpgltools")
library("ggplot2")
library("patchwork")
library("plotly")
library("RColorBrewer")
library("DT")
library("dplyr")
library("gprofiler2")
library("DESeq2")
source("helper_functions.R")

1.1 Changelog

  • hard-coded the year/month for downloading annotations (atb)
  • removed Theresa’s notes as per Najib’s request
  • minor formatting changes while I read

1.2 Updates

  • CL versus Saline after adjusting for diet effects
  • Added IDD_Saline - IAD_Saline / IDD_CL - IAD_CL contrast
  • Added IDD_Saline-IDD_CL / IAD_Saline-IAD_CL contrast

2 M. musculus

2.1 Annotations

I am using mm38_100.

mm_annot <- load_biomart_annotations(species="mmusculus", year="2023", month="07")
## Using mart: ENSEMBL_MART_ENSEMBL from host: jul2023.archive.ensembl.org.
## Successfully connected to the mmusculus_gene_ensembl database.
## Finished downloading ensembl gene annotations.
## Finished downloading ensembl structure annotations.
## symbol columns is null, pattern matching 'symbol'.
## Including symbols, there are 57550 vs the 149547 gene annotations.
## Not dropping haplotype chromosome annotations, set drop_haplotypes = TRUE if this is bad.
## Saving annotations to mmusculus_biomart_annotations.rda.
## Finished save().
mm_annot <- mm_annot[["annotation"]]
mm_annot[["txid"]] <- paste0(mm_annot[["ensembl_transcript_id"]], ".", mm_annot[["version"]])
rownames(mm_annot) <- make.names(mm_annot[["ensembl_gene_id"]], unique=TRUE)
tx_gene_map <- mm_annot[, c("txid", "ensembl_gene_id")]

So, I now have a table of mouse annotations.

2.2 Hisat2 expressionset

The sample sheet is called ‘Experimental_design_Kim_v1.0.xlsx’ and has a column to point to the names of the count tables to load. Here I combine the metadata, count data, and annotations.

hisat_annot <- mm_annot
##rownames(hisat_annot) <- paste0("gene:", rownames(hisat_annot))
mm38_hisat <- create_expt("sample_sheets/Experimental_design_Kim_v1.0.xlsx",
                          gene_info=hisat_annot)
## Reading the sample metadata.
## Did not find the column: sampleid.
## Setting the ID column to the first column.
## The sample definitions comprises: 16 rows(samples) and 23 columns(metadata fields).
## Matched 25583 annotations and counts.
## Bringing together the count matrix and gene information.
## Some annotations were lost in merging, setting them to 'undefined'.
## Saving the expressionset to 'expt.rda'.
## The final expressionset has 25760 features and 16 samples.
color_condition <- mm38_hisat$initial_metadata$condition
color_condition <- factor(color_condition, levels = c("IDD-Saline", "IDD-CL", "IAD-Saline", "IAD-CL"))

color_values <- c("#F8766D", "#FBADA7",  "#7CAE00", "#D3EE8F")#, "#00BFC4",  "#9AD2D3",  )

3 Summary Plots

plot_libsize(mm38_hisat)

plot_nonzero(mm38_hisat)
##  [1] "5214_S1"   "3740_S3"   "3750_S4"   "3772_S5"   "3774_S6"   "3775_S7"  
##  [7] "3766_S9"   "3767_S10"  "3742_S12"  "3747_S13"  "3741b_S14"

4 Normalize Expression

First we will filter out the genes which have low counts across all samples. Then I will normalize without background correction (it was determined there is no need for adjusting for background noise after evaluating the SVA correction).

mm38_filt <- normalize_expt(mm38_hisat, filter=TRUE)
## Removing 13318 low-count genes (12442 remaining).
mm38_norm <- normalize_expt(mm38_filt, convert="cpm", norm = "quant", transform="log2")
## transform_counts: Found 2 values equal to 0, adding 1 to the matrix.
mm38_nb <- normalize_expt(mm38_hisat, filter = TRUE, convert = "cpm",
                          transform = "log2", batch = "svaseq")
## Removing 13318 low-count genes (12442 remaining).
## Setting 128 low elements to zero.
## transform_counts: Found 128 values equal to 0, adding 1 to the matrix.

5 PCA

pca_norm <- plot_pca(mm38_norm, plot_labels = FALSE)
pca_norm$plot +
    scale_color_manual(values = color_values,
                    aesthetics = "color") +
    scale_fill_manual(values = color_values,
                    aesthetics = "fill") +
  guides(fill = "none")

plot_pca(mm38_nb)

6 Tables for Number of Samples

How many samples do we have currently for each group?

table(pData(mm38_hisat)[,c( "diet", "treatment")])
##      treatment
## diet  CL Saline (Vehicle)
##   IAD  4                4
##   IDD  5                3

7 Differential Expression Analysis

In the conditions column, we have IDD-Saline, IDD-CL, IAD-Saline, and IAD-CL. For the differential expression analysis, we will perform the following contrasts:

Normal Pairwise Contrasts:
IDD-CL vs IDD-Saline
IAD-CL vs IAD-Saline
IDD-CL vs IAD-CL
IDD-Saline vs IAD-Saline

Contrasts after adjustment:
CL versus Saline after adjusting for diet
IDD versus IAD after adjusting for CL/Saline treatment

I will conduct these contrasts below and provide a volcano plot (both interactive and static), as well as a searchable table of the significant DE results for each contrast.

mm_de_normal <- all_pairwise(mm38_filt, do_ebseq = FALSE,
                             model_batch = "svaseq", parallel = FALSE)
## 
## IDD-Saline     IDD-CL IAD-Saline     IAD-CL 
##          3          5          4          4
## Removing 0 low-count genes (12442 remaining).
## Setting 128 low elements to zero.
## transform_counts: Found 128 values equal to 0, adding 1 to the matrix.
## Starting basic pairwise comparison.
## Basic step 0/3: Normalizing data.
## Basic step 0/3: Converting data.
## Basic step 0/3: Transforming data.
## Basic step 1/3: Creating mean and variance tables.
## Basic step 2/3: Performing 10 comparisons.
## Basic step 3/3: Creating faux DE Tables.
## Basic: Returning tables.
## The data should be suitable for EdgeR/DESeq/EBSeq.
## If they freak out, check the state of the count table
## and ensure that it is in integer counts.
## converting counts to integer mode
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## Starting edgeR pairwise comparisons.
## The data should be suitable for EdgeR/DESeq/EBSeq.
## If they freak out, check the state of the count table
## and ensure that it is in integer counts.
## EdgeR step 1/9: Importing and normalizing data.
## EdgeR step 2/9: Estimating the common dispersion.
## EdgeR step 3/9: Estimating dispersion across genes.
## EdgeR step 4/9: Estimating GLM Common dispersion.
## EdgeR step 5/9: Estimating GLM Trended dispersion.
## EdgeR step 6/9: Estimating GLM Tagged dispersion.
## EdgeR step 7/9: Running glmFit, switch to glmQLFit by changing the argument 'edger_test'.
## EdgeR step 8/9: Making pairwise contrasts.

## libsize was not specified, this parameter has profound effects on limma's result.
## Using the libsize from expt$best_libsize.
## Limma step 1/6: choosing model.
## Limma step 2/6: running limma::voom(), switch with the argument 'which_voom'.
## Using normalize.method = quantile for voom.

## Limma step 3/6: running lmFit with method: ls.
## Limma step 4/6: making and fitting contrasts with no intercept. (~ 0 + factors)
## Finished make_pairwise_contrasts.
## Limma step 5/6: Running eBayes with robust = FALSE and trend = FALSE.
## Limma step 6/6: Writing limma outputs.
## Limma step 6/6: 1/6: Creating table: IADSaline_vs_IADCL.  Adjust = BH
## Limma step 6/6: 2/6: Creating table: IDDCL_vs_IADCL.  Adjust = BH
## Limma step 6/6: 3/6: Creating table: IDDSaline_vs_IADCL.  Adjust = BH
## Limma step 6/6: 4/6: Creating table: IDDCL_vs_IADSaline.  Adjust = BH
## Limma step 6/6: 5/6: Creating table: IDDSaline_vs_IADSaline.  Adjust = BH
## Limma step 6/6: 6/6: Creating table: IDDSaline_vs_IDDCL.  Adjust = BH
## Limma step 6/6: 1/4: Creating table: IADCL.  Adjust = BH
## Limma step 6/6: 2/4: Creating table: IADSaline.  Adjust = BH
## Limma step 6/6: 3/4: Creating table: IDDCL.  Adjust = BH
## Limma step 6/6: 4/4: Creating table: IDDSaline.  Adjust = BH
## Starting noiseq pairwise comparisons.
## The data should be suitable for EdgeR/DESeq/EBSeq.
## If they freak out, check the state of the count table
## and ensure that it is in integer counts.

mm_de_normal
## A pairwise differential expression with results from: basic, deseq, edger, limma, noiseq.
## This used a surrogate/batch estimate from: svaseq.
## The primary analysis performed 10 comparisons.
keepers <- list("IDDCL_vs_IADCL" = c("IDDCL", "IADCL"),
                "IDDSaline_vs_IADSaline" = c("IDDSaline", "IADSaline"),
                "IDDSaline_vs_IDDCL" = c("IDDSaline", "IDDCL"),
                "IADSaline_vs_IADCL" = c("IADSaline", "IADCL"))
mm_de_tables <- combine_de_tables(mm_de_normal, excel="excel/DE_20221003.xlsx",
                                  keepers = keepers)
mm_de_tables
## A set of combined differential expression results.
##                    table deseq_sigup deseq_sigdown edger_sigup edger_sigdown
## 1         IDDCL_vs_IADCL         132           115         142           117
## 2 IDDSaline_vs_IADSaline          48            55          53            58
## 3     IDDSaline_vs_IDDCL           4            27           5            40
## 4     IADSaline_vs_IADCL          12             5          12             7
##   limma_sigup limma_sigdown
## 1          84            71
## 2          15             7
## 3           0             0
## 4           1             0
## Plot describing unique/shared genes in a differential expression table.

mm_de_sig <- extract_significant_genes(mm_de_tables,
                                       excel="excel/DE_sig_20221003.xlsx",
                                       according_to = "deseq")
mm_de_sig
## A set of genes deemed significant according to deseq.
## The parameters defining significant were:
## LFC cutoff: 1 adj P cutoff: 0.05
##                        deseq_up deseq_down
## IDDCL_vs_IADCL              132        115
## IDDSaline_vs_IADSaline       48         55
## IDDSaline_vs_IDDCL            4         27
## IADSaline_vs_IADCL           12          5

res_tbls <- c()
for (t in seq_along(keepers)) {
  tbl <- names(keepers)[t]
  deseq_tbl <- mm_de_normal$deseq$all_tables[[tbl]]
  res_tbls[[tbl]] <- merge(deseq_tbl, hisat_annot, by = "row.names")
  res_tbls[[tbl]] <- set_sig_limma(res_tbls[[tbl]],
                                   factors = c(paste(gsub("\\_.*","",tbl), "\nEnriched"),
                                               paste(sub('.*\\_', '', tbl), "\nEnriched")))
  res_tbls[[paste0(tbl, "volc_plotly")]] <- volc_plot(res_tbls[[tbl]],
                                                      title = paste("Volcano Plot:", tbl),
                                                      type = "plotly",
                                                      tbl = "limma",
                                                      gene_name_col = "external_gene_name")
  res_tbls[[paste0(tbl, "volc_ggplot")]] <- volc_plot(res_tbls[[tbl]],
                                                      title = paste("Volcano Plot:", tbl),
                                                      tbl = "limma")
}

7.1 IDD: CL vs Saline

Volcano Plot

res_tbls$IDDSaline_vs_IDDCLvolc_plotly

Table of Significant DE results

This table is significant results with adjusted p-value < 0.05 and log2FC greater than .5.

res_tbls$IDDSaline_vs_IDDCL %>%
  filter(abs(logFC) > .5 & adj.P.Val < 0.05) %>%
  arrange(desc(logFC)) %>%
  select("ensembl_gene_id", "mgi_symbol", "description", "logFC", "adj.P.Val", "Significance") %>%
  DT::datatable(rownames = FALSE)

GSEA

IDD_genes <- res_tbls$IDDSaline_vs_IDDCL %>%
  filter(abs(logFC) >= .5 & adj.P.Val <= 0.05) %>%
    arrange(desc(abs(logFC)))
IDD_gost <- gost(query = IDD_genes$ensembl_gene_id,
                organism = "mmusculus", ordered_query = TRUE,
                evcodes = TRUE)
#IDD Saline Enriched
IDD_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "GO:BP" | source == "GO:MF" | source == "GO:CC") %>%
  datatable(rownames = FALSE, caption = "GO: IDD Significant GSEA")
IDD_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "REAC") %>%
  datatable(rownames = FALSE, caption = "REAC: IDD Significant GSEA")
IDD_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "KEGG") %>%
  datatable(rownames = FALSE, caption = "KEGG: IDD Significant GSEA")
##### IDD Enriched
gostplot(IDD_gost, capped = FALSE, interactive = TRUE)

7.2 IAD: CL vs Saline

Volcano Plot

res_tbls$IADSaline_vs_IADCLvolc_plotly

Table of Significant DE results

res_tbls$IADSaline_vs_IADCL %>%
  filter(abs(logFC) > .5 & adj.P.Val < 0.05) %>%
  arrange(desc(logFC)) %>%
  select("ensembl_gene_id", "mgi_symbol", "description", "logFC", "adj.P.Val", "Significance") %>%
  DT::datatable(rownames = FALSE)

GSEA

IAD_genes <- res_tbls$IADSaline_vs_IADCL %>%
  filter(abs(logFC) >= .5 & adj.P.Val <= 0.05) %>%
    arrange(desc(abs(logFC)))
IAD_gost <- gost(query = IAD_genes$ensembl_gene_id,
                organism = "mmusculus", ordered_query = TRUE,
                evcodes = TRUE)
#IAD Saline Enriched
IAD_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "GO:BP" | source == "GO:MF" | source == "GO:CC") %>%
  datatable(rownames = FALSE, caption = "GO: IAD Significant GSEA")
##### IAD Enriched
gostplot(IAD_gost, capped = FALSE, interactive = TRUE)

7.3 CL: IDD vs IAD

Volcano Plot

res_tbls$IDDCL_vs_IADCLvolc_plotly

Table of Significant DE results

res_tbls$IDDCL_vs_IADCL %>%
  filter(abs(logFC) > .5 & adj.P.Val < 0.05) %>%
  arrange(desc(logFC)) %>%
  select("ensembl_gene_id", "mgi_symbol", "description", "logFC", "adj.P.Val", "Significance") %>%
  DT::datatable(rownames = FALSE)

GSEA

CL_genes <- res_tbls$IDDCL_vs_IADCL %>%
  filter(abs(logFC) >= .5 & adj.P.Val <= 0.05) %>%
    arrange(desc(abs(logFC)))
CL_gost <- gost(query = CL_genes$ensembl_gene_id,
                organism = "mmusculus", ordered_query = TRUE,
                evcodes = TRUE)
#CL Saline Enriched
CL_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "GO:BP" | source == "GO:MF" | source == "GO:CC") %>%
  datatable(rownames = FALSE, caption = "GO: CL Significant GSEA")
CL_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "REAC") %>%
  datatable(rownames = FALSE, caption = "REAC: CL Significant GSEA")
CL_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "KEGG") %>%
  datatable(rownames = FALSE, caption = "KEGG: CL Significant GSEA")
##### CL Enriched
gostplot(CL_gost, capped = FALSE, interactive = TRUE)

7.4 Saline: IDD vs IAD

Volcano Plot

res_tbls$IDDSaline_vs_IADSalinevolc_plotly

Table of Significant DE results

res_tbls$IDDSaline_vs_IADSaline %>%
  filter(abs(logFC) > 1 & adj.P.Val < 0.05) %>%
  arrange(desc(logFC)) %>%
  select("ensembl_gene_id", "mgi_symbol", "description", "logFC", "adj.P.Val", "Significance") %>%
  DT::datatable(rownames = FALSE)

GSEA

Saline_genes <- res_tbls$IDDSaline_vs_IADSaline %>%
  filter(abs(logFC) >= .5 & adj.P.Val <= 0.05) %>%
    arrange(desc(abs(logFC)))
Saline_gost <- gost(query = Saline_genes$ensembl_gene_id,
                organism = "mmusculus", ordered_query = TRUE,
                evcodes = TRUE)
#CL Saline Enriched
Saline_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "GO:BP" | source == "GO:MF" | source == "GO:CC") %>%
  datatable(rownames = FALSE, caption = "GO: Saline Significant GSEA")
Saline_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "REAC") %>%
  datatable(rownames = FALSE, caption = "REAC: Saline Significant GSEA")
Saline_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "KEGG") %>%
  datatable(rownames = FALSE, caption = "KEGG: Saline Significant GSEA")
##### CL Enriched
gostplot(Saline_gost, capped = FALSE, interactive = TRUE)

8 Comparison Between Contrasts

8.1 CL versus Saline after adjusting for diet

countdata <- exprs(mm38_filt)
coldata <- colData(mm38_filt)
ddsMat <- DESeqDataSetFromMatrix(countData = countdata,
                                 colData = coldata,
                                 design = ~ diet + treatment)
## converting counts to integer mode
##   Note: levels of factors in the design contain characters other than
##   letters, numbers, '_' and '.'. It is recommended (but not required) to use
##   only letters, numbers, and delimiters '_' or '.', as these are safe characters
##   for column names in R. [This is a message, not a warning or an error]
dds <- DESeq(ddsMat)
## estimating size factors
##   Note: levels of factors in the design contain characters other than
##   letters, numbers, '_' and '.'. It is recommended (but not required) to use
##   only letters, numbers, and delimiters '_' or '.', as these are safe characters
##   for column names in R. [This is a message, not a warning or an error]
## estimating dispersions
## gene-wise dispersion estimates
## mean-dispersion relationship
##   Note: levels of factors in the design contain characters other than
##   letters, numbers, '_' and '.'. It is recommended (but not required) to use
##   only letters, numbers, and delimiters '_' or '.', as these are safe characters
##   for column names in R. [This is a message, not a warning or an error]
## final dispersion estimates
## fitting model and testing
res <- results(dds)
res <- merge(as.data.frame(res), hisat_annot, by = 0)
res <- res[!is.na(res$padj),]
res <- set_sig(res, factors = c("Saline \n Enriched", "CL \n Enriched"))
volc_plot(res_tbl = res, type = "plotly", title = "Saline versus CL after adjusting for Diet")
res %>%
  filter(padj < 0.05 & abs(log2FoldChange) >= 1) %>%
  select("ensembl_gene_id", "mgi_symbol", "description", "log2FoldChange", "padj", "Significance") %>%
  arrange(desc(log2FoldChange)) %>%
  datatable(rownames = FALSE)

GSEA

adj_genes <- res %>%
  filter(padj < 0.05 & abs(log2FoldChange) >= 1) %>%
    arrange(desc(abs(log2FoldChange)))
adj_gost <- gost(query = adj_genes$ensembl_gene_id,
                organism = "mmusculus", ordered_query = TRUE,
                evcodes = TRUE)
adj_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "GO:BP" | source == "GO:MF" | source == "GO:CC") %>%
  datatable(rownames = FALSE, caption = "GO: Adjusted for Diet Significant GSEA")
adj_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "REAC") %>%
  datatable(rownames = FALSE, caption = "REAC: Adjusted for Diet Significant GSEA")
adj_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "KEGG") %>%
  datatable(rownames = FALSE, caption = "KEGG: Adjusted for Diet Significant GSEA")
##### CL Enriched
gostplot(adj_gost, capped = FALSE, interactive = TRUE)
library(openxlsx)
res_df <- res %>%
  filter(padj < 0.05 & abs(log2FoldChange) >= .5) %>%
    arrange(desc(log2FoldChange)) %>%
    select(-Row.names, -lfcSE, -stat, -pvalue, -ensembl_gene_id, -version, -transcript_version, -mgi_symbol)
openxlsx::write.xlsx(res_df, file = "excel/adjdiet_DE.xlsx")

8.2 IDD versus IAD after adjusting for treatment

countdata <- exprs(mm38_filt)
coldata <- colData(mm38_filt)
ddsMat <- DESeqDataSetFromMatrix(countData = countdata,
                                 colData = coldata,
                                 design = ~ treatment + diet)
## converting counts to integer mode
##   Note: levels of factors in the design contain characters other than
##   letters, numbers, '_' and '.'. It is recommended (but not required) to use
##   only letters, numbers, and delimiters '_' or '.', as these are safe characters
##   for column names in R. [This is a message, not a warning or an error]
dds <- DESeq(ddsMat)
## estimating size factors
##   Note: levels of factors in the design contain characters other than
##   letters, numbers, '_' and '.'. It is recommended (but not required) to use
##   only letters, numbers, and delimiters '_' or '.', as these are safe characters
##   for column names in R. [This is a message, not a warning or an error]
## estimating dispersions
## gene-wise dispersion estimates
## mean-dispersion relationship
##   Note: levels of factors in the design contain characters other than
##   letters, numbers, '_' and '.'. It is recommended (but not required) to use
##   only letters, numbers, and delimiters '_' or '.', as these are safe characters
##   for column names in R. [This is a message, not a warning or an error]
## final dispersion estimates
## fitting model and testing
res <- results(dds)
res <- merge(as.data.frame(res), hisat_annot, by = 0)
res <- res[!is.na(res$padj),]
res <- set_sig(res, factors = c("IDD \n Enriched", "IAD \n Enriched"))
volc_plot(res_tbl = res, type = "plotly", title = "IDD versus IAD after adjusting for Treatment")
res %>%
  filter(padj < 0.05 & abs(log2FoldChange) >= 1) %>%
  select("ensembl_gene_id", "mgi_symbol", "description", "log2FoldChange", "padj", "Significance") %>%
  arrange(desc(log2FoldChange)) %>%
  datatable(rownames = FALSE)

GSEA

adj_genes <- res %>%
  filter(padj < 0.05 & abs(log2FoldChange) >= 1) %>%
    arrange(desc(abs(log2FoldChange)))
adj_gost <- gost(query = adj_genes$ensembl_gene_id,
                organism = "mmusculus",
                ordered_query = TRUE,
                evcodes = TRUE)
adj_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "GO:BP" | source == "GO:MF" | source == "GO:CC") %>%
  datatable(rownames = FALSE, caption = "GO: Diet after Adjusted for Treatment Significant GSEA")
adj_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "REAC") %>%
  datatable(rownames = FALSE, caption = "REAC: Diet after Adjusted for Treatment Significant GSEA")
adj_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "KEGG") %>%
  datatable(rownames = FALSE, caption = "KEGG: Diet after Adjusted for Treatment Significant GSEA")
##### CL Enriched
gostplot(adj_gost, capped = FALSE, interactive = TRUE)
gseaplot_GO_diet_adjtreat <- adj_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "GO:BP" | source == "GO:MF" | source == "GO:CC") %>%
  head(n = 10) %>%
    ggplot(aes(x = recall, y = reorder(term_name, recall), fill = p_value)) +
  geom_bar(stat = "identity")+
  scale_fill_continuous(low = "blue", high = "red") +
  theme_bw()+
  ylab("") +
  xlab("GSEA Score")

gseaplot_REAC_diet_adjtreat <- adj_gost$result %>%
  select(term_name, p_value, term_size, intersection_size, recall, source, intersection) %>%
  arrange(desc(recall)) %>%
  filter(source == "REAC") %>%
  head(n = 10) %>%
    ggplot(aes(x = recall, y = reorder(term_name, recall), fill = p_value)) +
  geom_bar(stat = "identity")+
  scale_fill_continuous(low = "blue", high = "red") +
  theme_bw()+
  ylab("") +
  xlab("GSEA Score")

gseaplot_GO_diet_adjtreat

gseaplot_REAC_diet_adjtreat

library(openxlsx)
res_df <- res %>%
  filter(padj < 0.05 & abs(log2FoldChange) >= .5) %>%
    arrange(desc(log2FoldChange)) %>%
    select(-Row.names, -lfcSE, -stat, -pvalue, -ensembl_gene_id, -version, -transcript_version, -hgnc_symbol)
openxlsx::write.xlsx(res_df, file = "excel/adjtreatment_DE.xlsx")
LS0tCnRpdGxlOiAnS2ltIExhYjogSUREIHYgSUFEIChBZGRlZCBHU0VBKScKYXV0aG9yOiAiVGhlcmVzYSBBbGV4YW5kZXIiCmRhdGU6ICIyMDIyLTA5LTI3IgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAga2VlcF9tZDogZmFsc2UKICAgIG1vZGU6IHNlbGZjb250YWluZWQKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgc2VsZl9jb250YWluZWQ6IHRydWUKICAgIHRoZW1lOiByZWFkYWJsZQogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogZmFsc2UKICAgICAgc21vb3RoX3Njcm9sbDogZmFsc2UKICAgIHRvY19kZXB0aDogNQogIHJtZGZvcm1hdHM6OnJlYWR0aGVkb3duOgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBkZl9wcmludDogcGFnZWQKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBmaWdfaGVpZ2h0OiA3CiAgICBmaWdfd2lkdGg6IDcKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIHdpZHRoOiAzMDAKICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICB0b2NfZmxvYXQ6IHRydWUKICBCaW9jU3R5bGU6Omh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBmaWdfaGVpZ2h0OiA3CiAgICBmaWdfd2lkdGg6IDcKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICB0b2NfZmxvYXQ6IHRydWUKLS0tCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+CmJvZHksIHRkIHsKICBmb250LXNpemU6IDE2cHg7Cn0KY29kZS5yewogIGZvbnQtc2l6ZTogMTZweDsKfQpwcmUgewogZm9udC1zaXplOiAxNnB4Cn0KPC9zdHlsZT4KCiMgTGlicmFyaWVzIFNldHVwCgpgYGB7ciBsaWJyYXJpZXMsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkoImhwZ2x0b29scyIpCmxpYnJhcnkoImdncGxvdDIiKQpsaWJyYXJ5KCJwYXRjaHdvcmsiKQpsaWJyYXJ5KCJwbG90bHkiKQpsaWJyYXJ5KCJSQ29sb3JCcmV3ZXIiKQpsaWJyYXJ5KCJEVCIpCmxpYnJhcnkoImRwbHlyIikKbGlicmFyeSgiZ3Byb2ZpbGVyMiIpCmxpYnJhcnkoIkRFU2VxMiIpCnNvdXJjZSgiaGVscGVyX2Z1bmN0aW9ucy5SIikKYGBgCgojIyBDaGFuZ2Vsb2cKCi0gaGFyZC1jb2RlZCB0aGUgeWVhci9tb250aCBmb3IgZG93bmxvYWRpbmcgYW5ub3RhdGlvbnMgKGF0YikKLSByZW1vdmVkIFRoZXJlc2EncyBub3RlcyBhcyBwZXIgTmFqaWIncyByZXF1ZXN0Ci0gbWlub3IgZm9ybWF0dGluZyBjaGFuZ2VzIHdoaWxlIEkgcmVhZAoKIyMgVXBkYXRlcwoKLSBDTCB2ZXJzdXMgU2FsaW5lIGFmdGVyIGFkanVzdGluZyBmb3IgZGlldCBlZmZlY3RzCi0gQWRkZWQgSUREX1NhbGluZSAtIElBRF9TYWxpbmUgLyBJRERfQ0wgLSBJQURfQ0wgY29udHJhc3QgPGJyPgotIEFkZGVkIElERF9TYWxpbmUtSUREX0NMIC8gSUFEX1NhbGluZS1JQURfQ0wgY29udHJhc3QgPGJyPgoKIyBNLiBtdXNjdWx1cwoKIyMgQW5ub3RhdGlvbnMKCkkgYW0gdXNpbmcgbW0zOF8xMDAuCgpgYGB7ciBhbm5vdGF0aW9uc30KbW1fYW5ub3QgPC0gbG9hZF9iaW9tYXJ0X2Fubm90YXRpb25zKHNwZWNpZXM9Im1tdXNjdWx1cyIsIHllYXI9IjIwMjMiLCBtb250aD0iMDciKQoKbW1fYW5ub3QgPC0gbW1fYW5ub3RbWyJhbm5vdGF0aW9uIl1dCm1tX2Fubm90W1sidHhpZCJdXSA8LSBwYXN0ZTAobW1fYW5ub3RbWyJlbnNlbWJsX3RyYW5zY3JpcHRfaWQiXV0sICIuIiwgbW1fYW5ub3RbWyJ2ZXJzaW9uIl1dKQpyb3duYW1lcyhtbV9hbm5vdCkgPC0gbWFrZS5uYW1lcyhtbV9hbm5vdFtbImVuc2VtYmxfZ2VuZV9pZCJdXSwgdW5pcXVlPVRSVUUpCnR4X2dlbmVfbWFwIDwtIG1tX2Fubm90WywgYygidHhpZCIsICJlbnNlbWJsX2dlbmVfaWQiKV0KYGBgCgpTbywgSSBub3cgaGF2ZSBhIHRhYmxlIG9mIG1vdXNlIGFubm90YXRpb25zLgoKIyMgSGlzYXQyIGV4cHJlc3Npb25zZXQKClRoZSBzYW1wbGUgc2hlZXQgaXMgY2FsbGVkICdFeHBlcmltZW50YWxfZGVzaWduX0tpbV92MS4wLnhsc3gnIGFuZCBoYXMKYSBjb2x1bW4gdG8gcG9pbnQgdG8gdGhlIG5hbWVzIG9mIHRoZSBjb3VudCB0YWJsZXMgdG8gbG9hZC4KSGVyZSBJIGNvbWJpbmUgdGhlIG1ldGFkYXRhLCBjb3VudCBkYXRhLCBhbmQgYW5ub3RhdGlvbnMuCgpgYGB7ciBoaXNhdDJ9Cmhpc2F0X2Fubm90IDwtIG1tX2Fubm90CiMjcm93bmFtZXMoaGlzYXRfYW5ub3QpIDwtIHBhc3RlMCgiZ2VuZToiLCByb3duYW1lcyhoaXNhdF9hbm5vdCkpCm1tMzhfaGlzYXQgPC0gY3JlYXRlX2V4cHQoInNhbXBsZV9zaGVldHMvRXhwZXJpbWVudGFsX2Rlc2lnbl9LaW1fdjEuMC54bHN4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lX2luZm89aGlzYXRfYW5ub3QpCmBgYAoKYGBge3J9CmNvbG9yX2NvbmRpdGlvbiA8LSBtbTM4X2hpc2F0JGluaXRpYWxfbWV0YWRhdGEkY29uZGl0aW9uCmNvbG9yX2NvbmRpdGlvbiA8LSBmYWN0b3IoY29sb3JfY29uZGl0aW9uLCBsZXZlbHMgPSBjKCJJREQtU2FsaW5lIiwgIklERC1DTCIsICJJQUQtU2FsaW5lIiwgIklBRC1DTCIpKQoKY29sb3JfdmFsdWVzIDwtIGMoIiNGODc2NkQiLCAiI0ZCQURBNyIsICAiIzdDQUUwMCIsICIjRDNFRThGIikjLCAiIzAwQkZDNCIsICAiIzlBRDJEMyIsICApCmBgYAoKIyBTdW1tYXJ5IFBsb3RzCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZyA9IEZBTFNFfQpwbG90X2xpYnNpemUobW0zOF9oaXNhdCkKCnBsb3Rfbm9uemVybyhtbTM4X2hpc2F0KQpgYGAKCiMgTm9ybWFsaXplIEV4cHJlc3Npb24KCkZpcnN0IHdlIHdpbGwgZmlsdGVyIG91dCB0aGUgZ2VuZXMgd2hpY2ggaGF2ZSBsb3cgY291bnRzIGFjcm9zcyBhbGwKc2FtcGxlcy4gVGhlbiBJIHdpbGwgbm9ybWFsaXplIHdpdGhvdXQgYmFja2dyb3VuZCBjb3JyZWN0aW9uIChpdCB3YXMKZGV0ZXJtaW5lZCB0aGVyZSBpcyBubyBuZWVkIGZvciBhZGp1c3RpbmcgZm9yIGJhY2tncm91bmQgbm9pc2UgYWZ0ZXIKZXZhbHVhdGluZyB0aGUgU1ZBIGNvcnJlY3Rpb24pLgoKYGBge3J9Cm1tMzhfZmlsdCA8LSBub3JtYWxpemVfZXhwdChtbTM4X2hpc2F0LCBmaWx0ZXI9VFJVRSkKbW0zOF9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KG1tMzhfZmlsdCwgY29udmVydD0iY3BtIiwgbm9ybSA9ICJxdWFudCIsIHRyYW5zZm9ybT0ibG9nMiIpCm1tMzhfbmIgPC0gbm9ybWFsaXplX2V4cHQobW0zOF9oaXNhdCwgZmlsdGVyID0gVFJVRSwgY29udmVydCA9ICJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9ICJsb2cyIiwgYmF0Y2ggPSAic3Zhc2VxIikKYGBgCgojIFBDQQoKYGBge3IgcGNhLCBtZXNzYWdlID0gRkFMU0V9CnBjYV9ub3JtIDwtIHBsb3RfcGNhKG1tMzhfbm9ybSwgcGxvdF9sYWJlbHMgPSBGQUxTRSkKcGNhX25vcm0kcGxvdCArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JfdmFsdWVzLAogICAgICAgICAgICAgICAgICAgIGFlc3RoZXRpY3MgPSAiY29sb3IiKSArCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvcl92YWx1ZXMsCiAgICAgICAgICAgICAgICAgICAgYWVzdGhldGljcyA9ICJmaWxsIikgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiKQoKcGxvdF9wY2EobW0zOF9uYikKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZXZhbD1GQUxTRX0KcGxvdF9wY2EobW0zOF9ub3JtLCBwbG90X2xhYmVscyA9IEZBTFNFKSRwbG90CnBjYV9ub3JtX3Bsb3QgPC0gZ2dwbG90KGFzLmRhdGEuZnJhbWUocGNhX25vcm0kcmVzdWx0JHYpLCBhZXMoeCA9IFBDMSwgeSA9IFBDMikpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGNvbG9yX2NvbmRpdGlvbiksCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gNSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvcl92YWx1ZXMsCiAgICAgICAgICAgICAgICAgICAgYWVzdGhldGljcyA9ICJjb2xvciIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogICNsYWJzKGNvbG9yPSJDZWxsIENvbXBhcnRtZW50L0dlbm90eXBlIikgICArCiAgZ2d0aXRsZSgiUENBIHdpdGggTm8gQmF0Y2ggQ29ycmVjdGlvbiIpICArCiAgbGFicyh4ID0gcGFzdGUwKCJQQzE6IDI1Ljc5JSB2YXJpYW5jZSIpLAogICAgICAgeSA9ICBwYXN0ZTAoIlBDMjogMTguODAlIHZhcmlhbmNlIikpCgpwbG90X3BjYShtbTM4X25vcm0sIHBsb3RfbGFiZWxzID0gRkFMU0UpJHBsb3QKcGNhX25vcm1fcGxvdAojKwojICBnZW9tX2xhYmVsX3JlcGVsKGRhdGEgPSBhcy5kYXRhLmZyYW1lKHBjYV9ub3JtJHJlc3VsdCR2W2MoMTY6MTgpLF0pLCBhZXMobGFiZWwgPSByb3duYW1lcyhwY2Ffbm9ybSRyZXN1bHQkdilbMTY6MThdKSwKIyAgICAgICAgICAgICAgICAgICBib3gucGFkZGluZyA9IDEpCgoKcGNhX3N2YV9wbG90IDwtIGdncGxvdChhcy5kYXRhLmZyYW1lKHBjYV9zdmEkcmVzdWx0JHYpLCBhZXMoeCA9IFBDMSwgeSA9IFBDMikpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGNvbG9yX2NvbmRpdGlvbiksCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gNSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvcl92YWx1ZXMsCiAgICAgICAgICAgICAgICAgICAgYWVzdGhldGljcyA9ICJjb2xvciIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxhYnMoY29sb3I9IkNlbGwgQ29tcGFydG1lbnQvR2Vub3R5cGUiKSAgICsKICBnZ3RpdGxlKCJQQ0Egd2l0aCBTVkEgQmF0Y2ggQ29ycmVjdGlvbiIpICArCiAgbGFicyh4ID0gcGFzdGUwKCJQQzE6IDY1LjM5JSB2YXJpYW5jZSIpLAogICAgICAgeSA9ICBwYXN0ZTAoIlBDMjogMTUuMjUlIHZhcmlhbmNlIikpICsKICBnZW9tX2xhYmVsX3JlcGVsKGRhdGEgPSBhcy5kYXRhLmZyYW1lKHBjYV9zdmEkcmVzdWx0JHZbYygxNjoxOCksXSksIGFlcyhsYWJlbCA9IHJvd25hbWVzKHBjYV9zdmEkcmVzdWx0JHYpWzE2OjE4XSksCiAgICAgICAgICAgICAgICAgICBib3gucGFkZGluZyA9IDIpCgpwY2Ffbm9ybV9wbG90KyBnZ3RpdGxlKCJQQ0EgUHJlIFNWQSIpICsKICBwY2Ffc3ZhX3Bsb3QgKyBnZ3RpdGxlKCJQQ0EgUG9zdCBTVkEiKSArIHBsb3RfbGF5b3V0KGd1aWRlcyA9ICJjb2xsZWN0IikgJiB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKCnBjYV9ub3JtX3Bsb3QgKyBnZ3RpdGxlKCJQQ0EgTm9ybWFsaXplZCBDb3VudHMiKQpgYGAKCiMgVGFibGVzIGZvciBOdW1iZXIgb2YgU2FtcGxlcwoKSG93IG1hbnkgc2FtcGxlcyBkbyB3ZSBoYXZlIGN1cnJlbnRseSBmb3IgZWFjaCBncm91cD8KCmBgYHtyIHNhbXBsZV90YWJsZX0KdGFibGUocERhdGEobW0zOF9oaXNhdClbLGMoICJkaWV0IiwgInRyZWF0bWVudCIpXSkKYGBgCgojIERpZmZlcmVudGlhbCBFeHByZXNzaW9uIEFuYWx5c2lzIHsudGFic2V0fQoKSW4gdGhlIGNvbmRpdGlvbnMgY29sdW1uLCB3ZSBoYXZlIElERC1TYWxpbmUsIElERC1DTCwgSUFELVNhbGluZSwgYW5kCklBRC1DTC4gRm9yIHRoZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcywgd2Ugd2lsbCBwZXJmb3JtIHRoZQpmb2xsb3dpbmcgY29udHJhc3RzOiA8YnI+CgoqKk5vcm1hbCBQYWlyd2lzZSBDb250cmFzdHM6Kio8YnI+CklERC1DTCB2cyBJREQtU2FsaW5lIDxicj4KSUFELUNMIHZzIElBRC1TYWxpbmUgPGJyPgpJREQtQ0wgdnMgSUFELUNMIDxicj4KSURELVNhbGluZSB2cyBJQUQtU2FsaW5lIDxicj4KCioqQ29udHJhc3RzIGFmdGVyIGFkanVzdG1lbnQ6Kio8YnI+CkNMIHZlcnN1cyBTYWxpbmUgYWZ0ZXIgYWRqdXN0aW5nIGZvciBkaWV0IDxicj4KSUREIHZlcnN1cyBJQUQgYWZ0ZXIgYWRqdXN0aW5nIGZvciBDTC9TYWxpbmUgdHJlYXRtZW50IDxicj4KCkkgd2lsbCBjb25kdWN0IHRoZXNlIGNvbnRyYXN0cyBiZWxvdyBhbmQgcHJvdmlkZSBhIHZvbGNhbm8gcGxvdCAoYm90aAppbnRlcmFjdGl2ZSBhbmQgc3RhdGljKSwgYXMgd2VsbCBhcyBhIHNlYXJjaGFibGUgdGFibGUgb2YgdGhlCnNpZ25pZmljYW50IERFIHJlc3VsdHMgZm9yIGVhY2ggY29udHJhc3QuPGJyPgoKYGBge3IgREV9Cm1tX2RlX25vcm1hbCA8LSBhbGxfcGFpcndpc2UobW0zOF9maWx0LCBkb19lYnNlcSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsX2JhdGNoID0gInN2YXNlcSIsIHBhcmFsbGVsID0gRkFMU0UpCm1tX2RlX25vcm1hbAoKa2VlcGVycyA8LSBsaXN0KCJJRERDTF92c19JQURDTCIgPSBjKCJJRERDTCIsICJJQURDTCIpLAogICAgICAgICAgICAgICAgIklERFNhbGluZV92c19JQURTYWxpbmUiID0gYygiSUREU2FsaW5lIiwgIklBRFNhbGluZSIpLAogICAgICAgICAgICAgICAgIklERFNhbGluZV92c19JRERDTCIgPSBjKCJJRERTYWxpbmUiLCAiSUREQ0wiKSwKICAgICAgICAgICAgICAgICJJQURTYWxpbmVfdnNfSUFEQ0wiID0gYygiSUFEU2FsaW5lIiwgIklBRENMIikpCm1tX2RlX3RhYmxlcyA8LSBjb21iaW5lX2RlX3RhYmxlcyhtbV9kZV9ub3JtYWwsIGV4Y2VsPSJleGNlbC9ERV8yMDIyMTAwMy54bHN4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlZXBlcnMgPSBrZWVwZXJzKQptbV9kZV90YWJsZXMKCm1tX2RlX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKG1tX2RlX3RhYmxlcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9ImV4Y2VsL0RFX3NpZ18yMDIyMTAwMy54bHN4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWNjb3JkaW5nX3RvID0gImRlc2VxIikKbW1fZGVfc2lnCgpyZXNfdGJscyA8LSBjKCkKZm9yICh0IGluIHNlcV9hbG9uZyhrZWVwZXJzKSkgewogIHRibCA8LSBuYW1lcyhrZWVwZXJzKVt0XQogIGRlc2VxX3RibCA8LSBtbV9kZV9ub3JtYWwkZGVzZXEkYWxsX3RhYmxlc1tbdGJsXV0KICByZXNfdGJsc1tbdGJsXV0gPC0gbWVyZ2UoZGVzZXFfdGJsLCBoaXNhdF9hbm5vdCwgYnkgPSAicm93Lm5hbWVzIikKICByZXNfdGJsc1tbdGJsXV0gPC0gc2V0X3NpZ19saW1tYShyZXNfdGJsc1tbdGJsXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjdG9ycyA9IGMocGFzdGUoZ3N1YigiXFxfLioiLCIiLHRibCksICJcbkVucmljaGVkIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUoc3ViKCcuKlxcXycsICcnLCB0YmwpLCAiXG5FbnJpY2hlZCIpKSkKICByZXNfdGJsc1tbcGFzdGUwKHRibCwgInZvbGNfcGxvdGx5IildXSA8LSB2b2xjX3Bsb3QocmVzX3RibHNbW3RibF1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9IHBhc3RlKCJWb2xjYW5vIFBsb3Q6IiwgdGJsKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJwbG90bHkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YmwgPSAibGltbWEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lX25hbWVfY29sID0gImV4dGVybmFsX2dlbmVfbmFtZSIpCiAgcmVzX3RibHNbW3Bhc3RlMCh0YmwsICJ2b2xjX2dncGxvdCIpXV0gPC0gdm9sY19wbG90KHJlc190YmxzW1t0YmxdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSBwYXN0ZSgiVm9sY2FubyBQbG90OiIsIHRibCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRibCA9ICJsaW1tYSIpCn0KYGBgCgojIyBJREQ6IENMIHZzIFNhbGluZQoKKipWb2xjYW5vIFBsb3QqKgoKYGBge3J9CnJlc190YmxzJElERFNhbGluZV92c19JRERDTHZvbGNfcGxvdGx5CmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIGV2YWw9RkFMU0V9CiNUaGlzIGlzIGp1c3QgYSBzdGF0aWMgdmVyc2lvbiBvZiB0aGUgcGxvdCBhYm92ZQpyZXNfdGJscyRJRERTYWxpbmVfdnNfSUREQ0x2b2xjX2dncGxvdApgYGAKCioqVGFibGUgb2YgU2lnbmlmaWNhbnQgREUgcmVzdWx0cyoqCgpUaGlzIHRhYmxlIGlzIHNpZ25pZmljYW50IHJlc3VsdHMgd2l0aCBhZGp1c3RlZCBwLXZhbHVlIDwgMC4wNSBhbmQKbG9nMkZDIGdyZWF0ZXIgdGhhbiAqKi41KiouCgpgYGB7cn0KcmVzX3RibHMkSUREU2FsaW5lX3ZzX0lERENMICU+JQogIGZpbHRlcihhYnMobG9nRkMpID4gLjUgJiBhZGouUC5WYWwgPCAwLjA1KSAlPiUKICBhcnJhbmdlKGRlc2MobG9nRkMpKSAlPiUKICBzZWxlY3QoImVuc2VtYmxfZ2VuZV9pZCIsICJtZ2lfc3ltYm9sIiwgImRlc2NyaXB0aW9uIiwgImxvZ0ZDIiwgImFkai5QLlZhbCIsICJTaWduaWZpY2FuY2UiKSAlPiUKICBEVDo6ZGF0YXRhYmxlKHJvd25hbWVzID0gRkFMU0UpCmBgYAoKKipHU0VBKioKCmBgYHtyfQpJRERfZ2VuZXMgPC0gcmVzX3RibHMkSUREU2FsaW5lX3ZzX0lERENMICU+JQogIGZpbHRlcihhYnMobG9nRkMpID49IC41ICYgYWRqLlAuVmFsIDw9IDAuMDUpICU+JQogICAgYXJyYW5nZShkZXNjKGFicyhsb2dGQykpKQpJRERfZ29zdCA8LSBnb3N0KHF1ZXJ5ID0gSUREX2dlbmVzJGVuc2VtYmxfZ2VuZV9pZCwKICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gIm1tdXNjdWx1cyIsIG9yZGVyZWRfcXVlcnkgPSBUUlVFLAogICAgICAgICAgICAgICAgZXZjb2RlcyA9IFRSVUUpCmBgYAoKYGBge3J9CiNJREQgU2FsaW5lIEVucmljaGVkCklERF9nb3N0JHJlc3VsdCAlPiUKICBzZWxlY3QodGVybV9uYW1lLCBwX3ZhbHVlLCB0ZXJtX3NpemUsIGludGVyc2VjdGlvbl9zaXplLCByZWNhbGwsIHNvdXJjZSwgaW50ZXJzZWN0aW9uKSAlPiUKICBhcnJhbmdlKGRlc2MocmVjYWxsKSkgJT4lCiAgZmlsdGVyKHNvdXJjZSA9PSAiR086QlAiIHwgc291cmNlID09ICJHTzpNRiIgfCBzb3VyY2UgPT0gIkdPOkNDIikgJT4lCiAgZGF0YXRhYmxlKHJvd25hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAiR086IElERCBTaWduaWZpY2FudCBHU0VBIikKCklERF9nb3N0JHJlc3VsdCAlPiUKICBzZWxlY3QodGVybV9uYW1lLCBwX3ZhbHVlLCB0ZXJtX3NpemUsIGludGVyc2VjdGlvbl9zaXplLCByZWNhbGwsIHNvdXJjZSwgaW50ZXJzZWN0aW9uKSAlPiUKICBhcnJhbmdlKGRlc2MocmVjYWxsKSkgJT4lCiAgZmlsdGVyKHNvdXJjZSA9PSAiUkVBQyIpICU+JQogIGRhdGF0YWJsZShyb3duYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIlJFQUM6IElERCBTaWduaWZpY2FudCBHU0VBIikKCklERF9nb3N0JHJlc3VsdCAlPiUKICBzZWxlY3QodGVybV9uYW1lLCBwX3ZhbHVlLCB0ZXJtX3NpemUsIGludGVyc2VjdGlvbl9zaXplLCByZWNhbGwsIHNvdXJjZSwgaW50ZXJzZWN0aW9uKSAlPiUKICBhcnJhbmdlKGRlc2MocmVjYWxsKSkgJT4lCiAgZmlsdGVyKHNvdXJjZSA9PSAiS0VHRyIpICU+JQogIGRhdGF0YWJsZShyb3duYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIktFR0c6IElERCBTaWduaWZpY2FudCBHU0VBIikKYGBgCgpgYGB7cn0KIyMjIyMgSUREIEVucmljaGVkCmdvc3RwbG90KElERF9nb3N0LCBjYXBwZWQgPSBGQUxTRSwgaW50ZXJhY3RpdmUgPSBUUlVFKQpgYGAKCiMjIElBRDogQ0wgdnMgU2FsaW5lCgoqKlZvbGNhbm8gUGxvdCoqCgpgYGB7cn0KcmVzX3RibHMkSUFEU2FsaW5lX3ZzX0lBRENMdm9sY19wbG90bHkKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZXZhbD1GQUxTRX0KI1RoaXMgaXMganVzdCBhIHN0YXRpYyB2ZXJzaW9uIG9mIHRoZSBwbG90IGFib3ZlCnJlc190YmxzJElBRFNhbGluZV92c19JQURDTHZvbGNfZ2dwbG90CmBgYAoKKipUYWJsZSBvZiBTaWduaWZpY2FudCBERSByZXN1bHRzKioKCmBgYHtyfQpyZXNfdGJscyRJQURTYWxpbmVfdnNfSUFEQ0wgJT4lCiAgZmlsdGVyKGFicyhsb2dGQykgPiAuNSAmIGFkai5QLlZhbCA8IDAuMDUpICU+JQogIGFycmFuZ2UoZGVzYyhsb2dGQykpICU+JQogIHNlbGVjdCgiZW5zZW1ibF9nZW5lX2lkIiwgIm1naV9zeW1ib2wiLCAiZGVzY3JpcHRpb24iLCAibG9nRkMiLCAiYWRqLlAuVmFsIiwgIlNpZ25pZmljYW5jZSIpICU+JQogIERUOjpkYXRhdGFibGUocm93bmFtZXMgPSBGQUxTRSkKYGBgCgoqKkdTRUEqKgoKYGBge3J9CklBRF9nZW5lcyA8LSByZXNfdGJscyRJQURTYWxpbmVfdnNfSUFEQ0wgJT4lCiAgZmlsdGVyKGFicyhsb2dGQykgPj0gLjUgJiBhZGouUC5WYWwgPD0gMC4wNSkgJT4lCiAgICBhcnJhbmdlKGRlc2MoYWJzKGxvZ0ZDKSkpCklBRF9nb3N0IDwtIGdvc3QocXVlcnkgPSBJQURfZ2VuZXMkZW5zZW1ibF9nZW5lX2lkLAogICAgICAgICAgICAgICAgb3JnYW5pc20gPSAibW11c2N1bHVzIiwgb3JkZXJlZF9xdWVyeSA9IFRSVUUsCiAgICAgICAgICAgICAgICBldmNvZGVzID0gVFJVRSkKYGBgCgpgYGB7cn0KI0lBRCBTYWxpbmUgRW5yaWNoZWQKSUFEX2dvc3QkcmVzdWx0ICU+JQogIHNlbGVjdCh0ZXJtX25hbWUsIHBfdmFsdWUsIHRlcm1fc2l6ZSwgaW50ZXJzZWN0aW9uX3NpemUsIHJlY2FsbCwgc291cmNlLCBpbnRlcnNlY3Rpb24pICU+JQogIGFycmFuZ2UoZGVzYyhyZWNhbGwpKSAlPiUKICBmaWx0ZXIoc291cmNlID09ICJHTzpCUCIgfCBzb3VyY2UgPT0gIkdPOk1GIiB8IHNvdXJjZSA9PSAiR086Q0MiKSAlPiUKICBkYXRhdGFibGUocm93bmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICJHTzogSUFEIFNpZ25pZmljYW50IEdTRUEiKQpgYGAKCmBgYHtyfQojIyMjIyBJQUQgRW5yaWNoZWQKZ29zdHBsb3QoSUFEX2dvc3QsIGNhcHBlZCA9IEZBTFNFLCBpbnRlcmFjdGl2ZSA9IFRSVUUpCmBgYAoKIyMgQ0w6IElERCB2cyBJQUQKCioqVm9sY2FubyBQbG90KioKCmBgYHtyfQpyZXNfdGJscyRJRERDTF92c19JQURDTHZvbGNfcGxvdGx5CmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIGV2YWw9RkFMU0V9CiNUaGlzIGlzIGp1c3QgYSBzdGF0aWMgdmVyc2lvbiBvZiB0aGUgcGxvdCBhYm92ZQpyZXNfdGJscyRJRERDTF92c19JQURDTHZvbGNfZ2dwbG90CmBgYAoKKipUYWJsZSBvZiBTaWduaWZpY2FudCBERSByZXN1bHRzKioKCmBgYHtyfQpyZXNfdGJscyRJRERDTF92c19JQURDTCAlPiUKICBmaWx0ZXIoYWJzKGxvZ0ZDKSA+IC41ICYgYWRqLlAuVmFsIDwgMC4wNSkgJT4lCiAgYXJyYW5nZShkZXNjKGxvZ0ZDKSkgJT4lCiAgc2VsZWN0KCJlbnNlbWJsX2dlbmVfaWQiLCAibWdpX3N5bWJvbCIsICJkZXNjcmlwdGlvbiIsICJsb2dGQyIsICJhZGouUC5WYWwiLCAiU2lnbmlmaWNhbmNlIikgJT4lCiAgRFQ6OmRhdGF0YWJsZShyb3duYW1lcyA9IEZBTFNFKQpgYGAKCioqR1NFQSoqCgpgYGB7cn0KQ0xfZ2VuZXMgPC0gcmVzX3RibHMkSUREQ0xfdnNfSUFEQ0wgJT4lCiAgZmlsdGVyKGFicyhsb2dGQykgPj0gLjUgJiBhZGouUC5WYWwgPD0gMC4wNSkgJT4lCiAgICBhcnJhbmdlKGRlc2MoYWJzKGxvZ0ZDKSkpCkNMX2dvc3QgPC0gZ29zdChxdWVyeSA9IENMX2dlbmVzJGVuc2VtYmxfZ2VuZV9pZCwKICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gIm1tdXNjdWx1cyIsIG9yZGVyZWRfcXVlcnkgPSBUUlVFLAogICAgICAgICAgICAgICAgZXZjb2RlcyA9IFRSVUUpCmBgYAoKYGBge3J9CiNDTCBTYWxpbmUgRW5yaWNoZWQKQ0xfZ29zdCRyZXN1bHQgJT4lCiAgc2VsZWN0KHRlcm1fbmFtZSwgcF92YWx1ZSwgdGVybV9zaXplLCBpbnRlcnNlY3Rpb25fc2l6ZSwgcmVjYWxsLCBzb3VyY2UsIGludGVyc2VjdGlvbikgJT4lCiAgYXJyYW5nZShkZXNjKHJlY2FsbCkpICU+JQogIGZpbHRlcihzb3VyY2UgPT0gIkdPOkJQIiB8IHNvdXJjZSA9PSAiR086TUYiIHwgc291cmNlID09ICJHTzpDQyIpICU+JQogIGRhdGF0YWJsZShyb3duYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIkdPOiBDTCBTaWduaWZpY2FudCBHU0VBIikKQ0xfZ29zdCRyZXN1bHQgJT4lCiAgc2VsZWN0KHRlcm1fbmFtZSwgcF92YWx1ZSwgdGVybV9zaXplLCBpbnRlcnNlY3Rpb25fc2l6ZSwgcmVjYWxsLCBzb3VyY2UsIGludGVyc2VjdGlvbikgJT4lCiAgYXJyYW5nZShkZXNjKHJlY2FsbCkpICU+JQogIGZpbHRlcihzb3VyY2UgPT0gIlJFQUMiKSAlPiUKICBkYXRhdGFibGUocm93bmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICJSRUFDOiBDTCBTaWduaWZpY2FudCBHU0VBIikKQ0xfZ29zdCRyZXN1bHQgJT4lCiAgc2VsZWN0KHRlcm1fbmFtZSwgcF92YWx1ZSwgdGVybV9zaXplLCBpbnRlcnNlY3Rpb25fc2l6ZSwgcmVjYWxsLCBzb3VyY2UsIGludGVyc2VjdGlvbikgJT4lCiAgYXJyYW5nZShkZXNjKHJlY2FsbCkpICU+JQogIGZpbHRlcihzb3VyY2UgPT0gIktFR0ciKSAlPiUKICBkYXRhdGFibGUocm93bmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICJLRUdHOiBDTCBTaWduaWZpY2FudCBHU0VBIikKYGBgCgpgYGB7cn0KIyMjIyMgQ0wgRW5yaWNoZWQKZ29zdHBsb3QoQ0xfZ29zdCwgY2FwcGVkID0gRkFMU0UsIGludGVyYWN0aXZlID0gVFJVRSkKYGBgCgojIyBTYWxpbmU6IElERCB2cyBJQUQKCioqVm9sY2FubyBQbG90KioKCmBgYHtyfQpyZXNfdGJscyRJRERTYWxpbmVfdnNfSUFEU2FsaW5ldm9sY19wbG90bHkKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZXZhbD1GQUxTRX0KI1RoaXMgaXMganVzdCBhIHN0YXRpYyB2ZXJzaW9uIG9mIHRoZSBwbG90IGFib3ZlCnJlc190YmxzJElERFNhbGluZV92c19JQURTYWxpbmV2b2xjX2dncGxvdApgYGAKCioqVGFibGUgb2YgU2lnbmlmaWNhbnQgREUgcmVzdWx0cyoqCgpgYGB7cn0KcmVzX3RibHMkSUREU2FsaW5lX3ZzX0lBRFNhbGluZSAlPiUKICBmaWx0ZXIoYWJzKGxvZ0ZDKSA+IDEgJiBhZGouUC5WYWwgPCAwLjA1KSAlPiUKICBhcnJhbmdlKGRlc2MobG9nRkMpKSAlPiUKICBzZWxlY3QoImVuc2VtYmxfZ2VuZV9pZCIsICJtZ2lfc3ltYm9sIiwgImRlc2NyaXB0aW9uIiwgImxvZ0ZDIiwgImFkai5QLlZhbCIsICJTaWduaWZpY2FuY2UiKSAlPiUKICBEVDo6ZGF0YXRhYmxlKHJvd25hbWVzID0gRkFMU0UpCmBgYAoKKipHU0VBKioKCmBgYHtyfQpTYWxpbmVfZ2VuZXMgPC0gcmVzX3RibHMkSUREU2FsaW5lX3ZzX0lBRFNhbGluZSAlPiUKICBmaWx0ZXIoYWJzKGxvZ0ZDKSA+PSAuNSAmIGFkai5QLlZhbCA8PSAwLjA1KSAlPiUKICAgIGFycmFuZ2UoZGVzYyhhYnMobG9nRkMpKSkKU2FsaW5lX2dvc3QgPC0gZ29zdChxdWVyeSA9IFNhbGluZV9nZW5lcyRlbnNlbWJsX2dlbmVfaWQsCiAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICJtbXVzY3VsdXMiLCBvcmRlcmVkX3F1ZXJ5ID0gVFJVRSwKICAgICAgICAgICAgICAgIGV2Y29kZXMgPSBUUlVFKQpgYGAKCmBgYHtyfQojQ0wgU2FsaW5lIEVucmljaGVkClNhbGluZV9nb3N0JHJlc3VsdCAlPiUKICBzZWxlY3QodGVybV9uYW1lLCBwX3ZhbHVlLCB0ZXJtX3NpemUsIGludGVyc2VjdGlvbl9zaXplLCByZWNhbGwsIHNvdXJjZSwgaW50ZXJzZWN0aW9uKSAlPiUKICBhcnJhbmdlKGRlc2MocmVjYWxsKSkgJT4lCiAgZmlsdGVyKHNvdXJjZSA9PSAiR086QlAiIHwgc291cmNlID09ICJHTzpNRiIgfCBzb3VyY2UgPT0gIkdPOkNDIikgJT4lCiAgZGF0YXRhYmxlKHJvd25hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAiR086IFNhbGluZSBTaWduaWZpY2FudCBHU0VBIikKU2FsaW5lX2dvc3QkcmVzdWx0ICU+JQogIHNlbGVjdCh0ZXJtX25hbWUsIHBfdmFsdWUsIHRlcm1fc2l6ZSwgaW50ZXJzZWN0aW9uX3NpemUsIHJlY2FsbCwgc291cmNlLCBpbnRlcnNlY3Rpb24pICU+JQogIGFycmFuZ2UoZGVzYyhyZWNhbGwpKSAlPiUKICBmaWx0ZXIoc291cmNlID09ICJSRUFDIikgJT4lCiAgZGF0YXRhYmxlKHJvd25hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAiUkVBQzogU2FsaW5lIFNpZ25pZmljYW50IEdTRUEiKQpTYWxpbmVfZ29zdCRyZXN1bHQgJT4lCiAgc2VsZWN0KHRlcm1fbmFtZSwgcF92YWx1ZSwgdGVybV9zaXplLCBpbnRlcnNlY3Rpb25fc2l6ZSwgcmVjYWxsLCBzb3VyY2UsIGludGVyc2VjdGlvbikgJT4lCiAgYXJyYW5nZShkZXNjKHJlY2FsbCkpICU+JQogIGZpbHRlcihzb3VyY2UgPT0gIktFR0ciKSAlPiUKICBkYXRhdGFibGUocm93bmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICJLRUdHOiBTYWxpbmUgU2lnbmlmaWNhbnQgR1NFQSIpCmBgYAoKYGBge3J9CiMjIyMjIENMIEVucmljaGVkCmdvc3RwbG90KFNhbGluZV9nb3N0LCBjYXBwZWQgPSBGQUxTRSwgaW50ZXJhY3RpdmUgPSBUUlVFKQpgYGAKCiMgQ29tcGFyaXNvbiBCZXR3ZWVuIENvbnRyYXN0cwoKIyMgQ0wgdmVyc3VzIFNhbGluZSBhZnRlciBhZGp1c3RpbmcgZm9yIGRpZXQKCmBgYHtyLCB3YXJuaW5nID0gRkFMU0V9CmNvdW50ZGF0YSA8LSBleHBycyhtbTM4X2ZpbHQpCmNvbGRhdGEgPC0gY29sRGF0YShtbTM4X2ZpbHQpCmRkc01hdCA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IGNvdW50ZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YSA9IGNvbGRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2lnbiA9IH4gZGlldCArIHRyZWF0bWVudCkKZGRzIDwtIERFU2VxKGRkc01hdCkKcmVzIDwtIHJlc3VsdHMoZGRzKQpyZXMgPC0gbWVyZ2UoYXMuZGF0YS5mcmFtZShyZXMpLCBoaXNhdF9hbm5vdCwgYnkgPSAwKQpyZXMgPC0gcmVzWyFpcy5uYShyZXMkcGFkaiksXQpyZXMgPC0gc2V0X3NpZyhyZXMsIGZhY3RvcnMgPSBjKCJTYWxpbmUgXG4gRW5yaWNoZWQiLCAiQ0wgXG4gRW5yaWNoZWQiKSkKdm9sY19wbG90KHJlc190YmwgPSByZXMsIHR5cGUgPSAicGxvdGx5IiwgdGl0bGUgPSAiU2FsaW5lIHZlcnN1cyBDTCBhZnRlciBhZGp1c3RpbmcgZm9yIERpZXQiKQoKcmVzICU+JQogIGZpbHRlcihwYWRqIDwgMC4wNSAmIGFicyhsb2cyRm9sZENoYW5nZSkgPj0gMSkgJT4lCiAgc2VsZWN0KCJlbnNlbWJsX2dlbmVfaWQiLCAibWdpX3N5bWJvbCIsICJkZXNjcmlwdGlvbiIsICJsb2cyRm9sZENoYW5nZSIsICJwYWRqIiwgIlNpZ25pZmljYW5jZSIpICU+JQogIGFycmFuZ2UoZGVzYyhsb2cyRm9sZENoYW5nZSkpICU+JQogIGRhdGF0YWJsZShyb3duYW1lcyA9IEZBTFNFKQpgYGAKCioqR1NFQSoqCgpgYGB7cn0KYWRqX2dlbmVzIDwtIHJlcyAlPiUKICBmaWx0ZXIocGFkaiA8IDAuMDUgJiBhYnMobG9nMkZvbGRDaGFuZ2UpID49IDEpICU+JQogICAgYXJyYW5nZShkZXNjKGFicyhsb2cyRm9sZENoYW5nZSkpKQphZGpfZ29zdCA8LSBnb3N0KHF1ZXJ5ID0gYWRqX2dlbmVzJGVuc2VtYmxfZ2VuZV9pZCwKICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gIm1tdXNjdWx1cyIsIG9yZGVyZWRfcXVlcnkgPSBUUlVFLAogICAgICAgICAgICAgICAgZXZjb2RlcyA9IFRSVUUpCmBgYAoKYGBge3J9CmFkal9nb3N0JHJlc3VsdCAlPiUKICBzZWxlY3QodGVybV9uYW1lLCBwX3ZhbHVlLCB0ZXJtX3NpemUsIGludGVyc2VjdGlvbl9zaXplLCByZWNhbGwsIHNvdXJjZSwgaW50ZXJzZWN0aW9uKSAlPiUKICBhcnJhbmdlKGRlc2MocmVjYWxsKSkgJT4lCiAgZmlsdGVyKHNvdXJjZSA9PSAiR086QlAiIHwgc291cmNlID09ICJHTzpNRiIgfCBzb3VyY2UgPT0gIkdPOkNDIikgJT4lCiAgZGF0YXRhYmxlKHJvd25hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAiR086IEFkanVzdGVkIGZvciBEaWV0IFNpZ25pZmljYW50IEdTRUEiKQphZGpfZ29zdCRyZXN1bHQgJT4lCiAgc2VsZWN0KHRlcm1fbmFtZSwgcF92YWx1ZSwgdGVybV9zaXplLCBpbnRlcnNlY3Rpb25fc2l6ZSwgcmVjYWxsLCBzb3VyY2UsIGludGVyc2VjdGlvbikgJT4lCiAgYXJyYW5nZShkZXNjKHJlY2FsbCkpICU+JQogIGZpbHRlcihzb3VyY2UgPT0gIlJFQUMiKSAlPiUKICBkYXRhdGFibGUocm93bmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICJSRUFDOiBBZGp1c3RlZCBmb3IgRGlldCBTaWduaWZpY2FudCBHU0VBIikKYWRqX2dvc3QkcmVzdWx0ICU+JQogIHNlbGVjdCh0ZXJtX25hbWUsIHBfdmFsdWUsIHRlcm1fc2l6ZSwgaW50ZXJzZWN0aW9uX3NpemUsIHJlY2FsbCwgc291cmNlLCBpbnRlcnNlY3Rpb24pICU+JQogIGFycmFuZ2UoZGVzYyhyZWNhbGwpKSAlPiUKICBmaWx0ZXIoc291cmNlID09ICJLRUdHIikgJT4lCiAgZGF0YXRhYmxlKHJvd25hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAiS0VHRzogQWRqdXN0ZWQgZm9yIERpZXQgU2lnbmlmaWNhbnQgR1NFQSIpCmBgYAoKYGBge3J9CiMjIyMjIENMIEVucmljaGVkCmdvc3RwbG90KGFkal9nb3N0LCBjYXBwZWQgPSBGQUxTRSwgaW50ZXJhY3RpdmUgPSBUUlVFKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KG9wZW54bHN4KQpyZXNfZGYgPC0gcmVzICU+JQogIGZpbHRlcihwYWRqIDwgMC4wNSAmIGFicyhsb2cyRm9sZENoYW5nZSkgPj0gLjUpICU+JQogICAgYXJyYW5nZShkZXNjKGxvZzJGb2xkQ2hhbmdlKSkgJT4lCiAgICBzZWxlY3QoLVJvdy5uYW1lcywgLWxmY1NFLCAtc3RhdCwgLXB2YWx1ZSwgLWVuc2VtYmxfZ2VuZV9pZCwgLXZlcnNpb24sIC10cmFuc2NyaXB0X3ZlcnNpb24sIC1tZ2lfc3ltYm9sKQpvcGVueGxzeDo6d3JpdGUueGxzeChyZXNfZGYsIGZpbGUgPSAiZXhjZWwvYWRqZGlldF9ERS54bHN4IikKYGBgCgojIyBJREQgdmVyc3VzIElBRCBhZnRlciBhZGp1c3RpbmcgZm9yIHRyZWF0bWVudAoKYGBge3IsIHdhcm5pbmcgPSBGQUxTRX0KY291bnRkYXRhIDwtIGV4cHJzKG1tMzhfZmlsdCkKY29sZGF0YSA8LSBjb2xEYXRhKG1tMzhfZmlsdCkKZGRzTWF0IDwtIERFU2VxRGF0YVNldEZyb21NYXRyaXgoY291bnREYXRhID0gY291bnRkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xEYXRhID0gY29sZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduID0gfiB0cmVhdG1lbnQgKyBkaWV0KQpkZHMgPC0gREVTZXEoZGRzTWF0KQpyZXMgPC0gcmVzdWx0cyhkZHMpCnJlcyA8LSBtZXJnZShhcy5kYXRhLmZyYW1lKHJlcyksIGhpc2F0X2Fubm90LCBieSA9IDApCnJlcyA8LSByZXNbIWlzLm5hKHJlcyRwYWRqKSxdCnJlcyA8LSBzZXRfc2lnKHJlcywgZmFjdG9ycyA9IGMoIklERCBcbiBFbnJpY2hlZCIsICJJQUQgXG4gRW5yaWNoZWQiKSkKdm9sY19wbG90KHJlc190YmwgPSByZXMsIHR5cGUgPSAicGxvdGx5IiwgdGl0bGUgPSAiSUREIHZlcnN1cyBJQUQgYWZ0ZXIgYWRqdXN0aW5nIGZvciBUcmVhdG1lbnQiKQoKcmVzICU+JQogIGZpbHRlcihwYWRqIDwgMC4wNSAmIGFicyhsb2cyRm9sZENoYW5nZSkgPj0gMSkgJT4lCiAgc2VsZWN0KCJlbnNlbWJsX2dlbmVfaWQiLCAibWdpX3N5bWJvbCIsICJkZXNjcmlwdGlvbiIsICJsb2cyRm9sZENoYW5nZSIsICJwYWRqIiwgIlNpZ25pZmljYW5jZSIpICU+JQogIGFycmFuZ2UoZGVzYyhsb2cyRm9sZENoYW5nZSkpICU+JQogIGRhdGF0YWJsZShyb3duYW1lcyA9IEZBTFNFKQpgYGAKCioqR1NFQSoqCgpgYGB7cn0KYWRqX2dlbmVzIDwtIHJlcyAlPiUKICBmaWx0ZXIocGFkaiA8IDAuMDUgJiBhYnMobG9nMkZvbGRDaGFuZ2UpID49IDEpICU+JQogICAgYXJyYW5nZShkZXNjKGFicyhsb2cyRm9sZENoYW5nZSkpKQphZGpfZ29zdCA8LSBnb3N0KHF1ZXJ5ID0gYWRqX2dlbmVzJGVuc2VtYmxfZ2VuZV9pZCwKICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gIm1tdXNjdWx1cyIsCiAgICAgICAgICAgICAgICBvcmRlcmVkX3F1ZXJ5ID0gVFJVRSwKICAgICAgICAgICAgICAgIGV2Y29kZXMgPSBUUlVFKQpgYGAKCmBgYHtyfQphZGpfZ29zdCRyZXN1bHQgJT4lCiAgc2VsZWN0KHRlcm1fbmFtZSwgcF92YWx1ZSwgdGVybV9zaXplLCBpbnRlcnNlY3Rpb25fc2l6ZSwgcmVjYWxsLCBzb3VyY2UsIGludGVyc2VjdGlvbikgJT4lCiAgYXJyYW5nZShkZXNjKHJlY2FsbCkpICU+JQogIGZpbHRlcihzb3VyY2UgPT0gIkdPOkJQIiB8IHNvdXJjZSA9PSAiR086TUYiIHwgc291cmNlID09ICJHTzpDQyIpICU+JQogIGRhdGF0YWJsZShyb3duYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIkdPOiBEaWV0IGFmdGVyIEFkanVzdGVkIGZvciBUcmVhdG1lbnQgU2lnbmlmaWNhbnQgR1NFQSIpCmFkal9nb3N0JHJlc3VsdCAlPiUKICBzZWxlY3QodGVybV9uYW1lLCBwX3ZhbHVlLCB0ZXJtX3NpemUsIGludGVyc2VjdGlvbl9zaXplLCByZWNhbGwsIHNvdXJjZSwgaW50ZXJzZWN0aW9uKSAlPiUKICBhcnJhbmdlKGRlc2MocmVjYWxsKSkgJT4lCiAgZmlsdGVyKHNvdXJjZSA9PSAiUkVBQyIpICU+JQogIGRhdGF0YWJsZShyb3duYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIlJFQUM6IERpZXQgYWZ0ZXIgQWRqdXN0ZWQgZm9yIFRyZWF0bWVudCBTaWduaWZpY2FudCBHU0VBIikKYWRqX2dvc3QkcmVzdWx0ICU+JQogIHNlbGVjdCh0ZXJtX25hbWUsIHBfdmFsdWUsIHRlcm1fc2l6ZSwgaW50ZXJzZWN0aW9uX3NpemUsIHJlY2FsbCwgc291cmNlLCBpbnRlcnNlY3Rpb24pICU+JQogIGFycmFuZ2UoZGVzYyhyZWNhbGwpKSAlPiUKICBmaWx0ZXIoc291cmNlID09ICJLRUdHIikgJT4lCiAgZGF0YXRhYmxlKHJvd25hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAiS0VHRzogRGlldCBhZnRlciBBZGp1c3RlZCBmb3IgVHJlYXRtZW50IFNpZ25pZmljYW50IEdTRUEiKQpgYGAKCmBgYHtyfQojIyMjIyBDTCBFbnJpY2hlZApnb3N0cGxvdChhZGpfZ29zdCwgY2FwcGVkID0gRkFMU0UsIGludGVyYWN0aXZlID0gVFJVRSkKYGBgCgpgYGB7cn0KZ3NlYXBsb3RfR09fZGlldF9hZGp0cmVhdCA8LSBhZGpfZ29zdCRyZXN1bHQgJT4lCiAgc2VsZWN0KHRlcm1fbmFtZSwgcF92YWx1ZSwgdGVybV9zaXplLCBpbnRlcnNlY3Rpb25fc2l6ZSwgcmVjYWxsLCBzb3VyY2UsIGludGVyc2VjdGlvbikgJT4lCiAgYXJyYW5nZShkZXNjKHJlY2FsbCkpICU+JQogIGZpbHRlcihzb3VyY2UgPT0gIkdPOkJQIiB8IHNvdXJjZSA9PSAiR086TUYiIHwgc291cmNlID09ICJHTzpDQyIpICU+JQogIGhlYWQobiA9IDEwKSAlPiUKICAgIGdncGxvdChhZXMoeCA9IHJlY2FsbCwgeSA9IHJlb3JkZXIodGVybV9uYW1lLCByZWNhbGwpLCBmaWxsID0gcF92YWx1ZSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikrCiAgc2NhbGVfZmlsbF9jb250aW51b3VzKGxvdyA9ICJibHVlIiwgaGlnaCA9ICJyZWQiKSArCiAgdGhlbWVfYncoKSsKICB5bGFiKCIiKSArCiAgeGxhYigiR1NFQSBTY29yZSIpCgpnc2VhcGxvdF9SRUFDX2RpZXRfYWRqdHJlYXQgPC0gYWRqX2dvc3QkcmVzdWx0ICU+JQogIHNlbGVjdCh0ZXJtX25hbWUsIHBfdmFsdWUsIHRlcm1fc2l6ZSwgaW50ZXJzZWN0aW9uX3NpemUsIHJlY2FsbCwgc291cmNlLCBpbnRlcnNlY3Rpb24pICU+JQogIGFycmFuZ2UoZGVzYyhyZWNhbGwpKSAlPiUKICBmaWx0ZXIoc291cmNlID09ICJSRUFDIikgJT4lCiAgaGVhZChuID0gMTApICU+JQogICAgZ2dwbG90KGFlcyh4ID0gcmVjYWxsLCB5ID0gcmVvcmRlcih0ZXJtX25hbWUsIHJlY2FsbCksIGZpbGwgPSBwX3ZhbHVlKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSsKICBzY2FsZV9maWxsX2NvbnRpbnVvdXMobG93ID0gImJsdWUiLCBoaWdoID0gInJlZCIpICsKICB0aGVtZV9idygpKwogIHlsYWIoIiIpICsKICB4bGFiKCJHU0VBIFNjb3JlIikKCmdzZWFwbG90X0dPX2RpZXRfYWRqdHJlYXQKZ3NlYXBsb3RfUkVBQ19kaWV0X2FkanRyZWF0CmBgYAoKYGBge3J9CmxpYnJhcnkob3Blbnhsc3gpCnJlc19kZiA8LSByZXMgJT4lCiAgZmlsdGVyKHBhZGogPCAwLjA1ICYgYWJzKGxvZzJGb2xkQ2hhbmdlKSA+PSAuNSkgJT4lCiAgICBhcnJhbmdlKGRlc2MobG9nMkZvbGRDaGFuZ2UpKSAlPiUKICAgIHNlbGVjdCgtUm93Lm5hbWVzLCAtbGZjU0UsIC1zdGF0LCAtcHZhbHVlLCAtZW5zZW1ibF9nZW5lX2lkLCAtdmVyc2lvbiwgLXRyYW5zY3JpcHRfdmVyc2lvbiwgLWhnbmNfc3ltYm9sKQpvcGVueGxzeDo6d3JpdGUueGxzeChyZXNfZGYsIGZpbGUgPSAiZXhjZWwvYWRqdHJlYXRtZW50X0RFLnhsc3giKQpgYGAK