1 Differential Expression, Macrophage: 20170820

2 Differential expression analyses

It appears that it is possible though somewhat difficult to apply batch estimations generated by sva to the model given to DESeq/EdgeR/limma. In the case of limma it is fairly simple, but in the other two it is a bit more difficult. There is a nice discussion of this at: https://www.biostars.org/p/156186/ I am attempting to apply that logic to this data with limited success.

hs_contrasts <- list(
    "macro_chr-sh" = c("chr","sh"),
    "macro_chr-nil" = c("chr","uninf"),
    "macro_sh-nil" = c("sh", "uninf"))
hs_macr_norm <- sm(normalize_expt(hs_cds_macr, filter=TRUE, convert="cpm"))
hs_macr_combat_norm <- sm(normalize_expt(hs_cds_macr, filter=TRUE, batch="combat"))
hs_macr_sva_norm <- sm(normalize_expt(hs_cds_macr, filter=TRUE, batch="svaseq"))
hs_macr_lowfilt <- sm(normalize_expt(hs_cds_macr, filter=TRUE))
## Set up the data used in the comparative contrast sets.

2.1 No batch in the model

hs_macr_nobatch <- sm(all_pairwise(input=hs_macr_lowfilt, model_batch=FALSE, limma_method="robust"))
## wow, all tools including basic agree almost completely
medians_by_condition <- hs_macr_nobatch$basic$medians
hs_macr_nobatch_tables <- sm(combine_de_tables(hs_macr_nobatch,
                                               excel=paste0("excel/hs_macr_nobatch-v", ver, ".xlsx"),
                                               keepers=hs_contrasts,
                                               extra_annot=medians_by_condition))
## Error in .subset2(x, i, exact = exact): subscript out of bounds
hs_macr_nobatch_sig <- sm(extract_significant_genes(hs_macr_nobatch_tables,
                                                    excel=paste0("excel/hs_macr_nobatch_significant-v", ver, ".xlsx"),
                                                    according_to="all"))
## Error in extract_significant_genes(hs_macr_nobatch_tables, excel = paste0("excel/hs_macr_nobatch_significant-v", : object 'hs_macr_nobatch_tables' not found

2.2 Batch in the model

In this attempt, we add a batch factor in the experimental model and see how it does.

## Here just let all_pairwise run on filtered data and do its normal ~ 0 + condition + batch analyses
hs_macr_batch <- sm(all_pairwise(input=hs_macr_lowfilt, limma_method="robust", parallel=FALSE))
medians_by_condition <- hs_macr_batch$basic$medians
hs_macr_batch_tables <- sm(combine_de_tables(
  hs_macr_batch,
  excel=paste0("excel/hs_macr_batchmodel-v", ver, ".xlsx"),
  sig_excel=paste0("excel/hs_macro_batchmodel_significant-v", ver, ".xlsx"),
  keepers=hs_contrasts,
  extra_annot=medians_by_condition))
## Error in .subset2(x, i, exact = exact): subscript out of bounds

3 Table S2 and Figure 1b

  • Table S2 is taking only the DESeq2 results.
  • Figure 1c is intended to be a volcano plot of the DESeq2 results.
s2_contrasts <- list(
  "macro_chr-sh" = c("chr","sh"))
table_s2 <- sm(combine_de_tables(
  hs_macr_batch,
  excel=paste0("excel/table_s2_hs_macr_batchmodel-v", ver, ".xlsx"),
  keepers=s2_contrasts,
  include_basic=FALSE, include_limma=FALSE, include_edger=FALSE))

chosen_table <- table_s2[["data"]][["chr_vs_sh"]]
##head(chosen_table)
vol <- plot_volcano_de(table=chosen_table,
                       color_by="state",
                       fc_col="deseq_logfc",
                       p_col="deseq_adjp",
                       shapes_by_state=FALSE,
                       line_position="top")
## The color list must have 4, setting it to the default.
pp(file="images/Figure_1c.pdf")
## Going to write the image to: images/Figure_1c.pdf when dev.off() is called.
vol$plot
dev.off()
## png 
##   2

4 Table S3

Table S3 is taking only the DESeq2 results of significant genes.

{r table_s3 table_s3 <- extract_significant_genes( table_s2, according_to="deseq", excel=paste0("excel/table_s3_hs_macr_batchmodel_significant-v", ver, ".xlsx"))

4.1 Batch estimated with SVA

## Here just let all_pairwise run on filtered data and do its normal ~ 0 + condition + batch analyses
hs_macr_sva <- sm(all_pairwise(
  input=hs_macr_lowfilt,
  model_batch="svaseq",
  limma_method="robust"))
medians_by_condition <- hs_macr_sva$basic$medians
hs_macr_sva_tables <- sm(combine_de_tables(
  hs_macr_sva,
  excel=paste0("excel/hs_macr_sva-v", ver, ".xlsx"),
  sig_excel=paste0("excel/hs_macr_sva_significant-v", ver, ".xlsx"),
  keepers=hs_contrasts,
  extra_annot=medians_by_condition))
## Error in .subset2(x, i, exact = exact): subscript out of bounds
hs_macr_sva_ma_limma <- extract_de_plots(
  pairwise=hs_macr_sva,
  type="limma",
  table="sh_vs_chr")
hs_macr_sva_ma_limma$ma$plot

4.2 Batch correction via ruv residuals

## Here just let all_pairwise run on filtered data and do its normal ~ 0 + condition + batch analyses
## Bizarrely, sometimes if one runs this, it gives an error "Error in (function (classes, fdef, mtable) : unable to find an inherited method for function 'RUVr' for signature '"matrix", "logical", "numeric", "NULL"'"  -- however, if one then simply runs it again it works fine.
## I am going to assume that it is because I do not explicitly invoke the library.
## library(ruv)  ## hopefully a small code change made this not needed.
testme <- get_model_adjust(input=hs_macr_lowfilt, estimate_type="ruv_residuals")
## The be method chose 2 surrogate variable(s).
## Attempting ruvseq residual surrogate estimation with 2 surrogates.
## Error in (function (classes, fdef, mtable) : unable to find an inherited method for function 'RUVr' for signature '"matrix", "logical", "numeric", "NULL"'
## hmm I got the RUVr error again, but when I ran it manually did not.
## Even more strangely, if I just run the same thing again, no error...
testme <- get_model_adjust(input=hs_macr_lowfilt, estimate_type="ruv_residuals")
## The be method chose 2 surrogate variable(s).
## Attempting ruvseq residual surrogate estimation with 2 surrogates.
hs_macr_ruvres <- sm(all_pairwise(
  input=hs_macr_lowfilt,
  model_batch="ruv_residuals",
  limma_method="robust"))
medians_by_condition <- hs_macr_ruvres$basic$medians
hs_macr_ruvres_tables <- sm(combine_de_tables(
  hs_macr_ruvres,
  excel=paste0("excel/hs_macr_ruvres-v", ver, ".xlsx"),
  sig_excel=paste0("excel/hs_macr_ruvres_significant-v", ver, ".xlsx"),
  keepers=hs_contrasts,
  extra_annot=medians_by_condition))
## Error in .subset2(x, i, exact = exact): subscript out of bounds

4.3 Batch correction with pca

## Here just let all_pairwise run on filtered data and do its normal ~ 0 + condition + batch analyses
hs_macr_pca <- sm(all_pairwise(
  input=hs_macr_lowfilt,
  model_batch="pca",
  limma_method="robust"))
medians_by_condition <- hs_macr_pca$basic$medians
hs_macr_pca_tables <- sm(combine_de_tables(
  hs_macr_pca,
  excel=paste0("excel/hs_macr_pca-v", ver, ".xlsx"),
  sig_excel=paste0("excel/hs_macr_pca_significant-v", ver, ".xlsx"),
  keepers=hs_contrasts,
  extra_annot=medians_by_condition))
## Error in .subset2(x, i, exact = exact): subscript out of bounds

4.4 Batch correction with ruv empirical

## Here just let all_pairwise run on filtered data and do its normal ~ 0 + condition + batch analyses
hs_macr_ruvemp <- sm(all_pairwise(
  input=hs_macr_lowfilt,
  model_batch="ruv_empirical",
  limma_method="robust"))
medians_by_condition <- hs_macr_ruvemp$basic$medians
hs_macr_ruvemp_tables <- sm(combine_de_tables(
  hs_macr_ruvemp,
  excel=paste0("excel/hs_macr_ruvemp-v", ver, ".xlsx"),
  sig_excel=paste0("excel/hs_macr_ruvemp_significant-v", ver, ".xlsx"),
  keepers=hs_contrasts,
  extra_annot=medians_by_condition))
## Error in .subset2(x, i, exact = exact): subscript out of bounds

4.5 Batch correction with combat

Then repeat with the batch-corrected data and see the differences.

hs_macr_combat <- sm(all_pairwise(
  input=hs_macr_combat_norm,
  force=TRUE,
  limma_method="robust"))
## Error in cpm.default(count_table, ...): library sizes should be finite and non-negative
medians_by_condition <- hs_macr_combat$basic$medians
## Error in eval(expr, envir, enclos): object 'hs_macr_combat' not found
hs_macr_combat_tables <- sm(combine_de_tables(
  hs_macr_combat,
  excel=paste0("excel/hs_macr_combat-v", ver, ".xlsx"),
  sig_excep=paste0("excel/hs_macr_combat_significant-v", ver, ".xlsx"),
  keepers=hs_contrasts,
  extra_annot=medians_by_condition))
## Error in combine_de_tables(hs_macr_combat, excel = paste0("excel/hs_macr_combat-v", : object 'hs_macr_combat' not found
hs_macr_combat_ma_limma <- extract_de_plots(
  pairwise=hs_macr_combat,
  type="limma",
  table="sh_vs_chr")
## Error in extract_de_plots(pairwise = hs_macr_combat, type = "limma", table = "sh_vs_chr"): object 'hs_macr_combat' not found
hs_macr_combat_ma_limma$ma$plot
## Error in eval(expr, envir, enclos): object 'hs_macr_combat_ma_limma' not found
hs_macr_combat_ma_edger <- extract_de_plots(
  pairwise=hs_macr_combat,
  type="edger",
  table="sh_vs_chr")
## Error in extract_de_plots(pairwise = hs_macr_combat, type = "edger", table = "sh_vs_chr"): object 'hs_macr_combat' not found
hs_macr_combat_ma_edger$ma$plot
## Error in eval(expr, envir, enclos): object 'hs_macr_combat_ma_edger' not found
hs_macr_combat_ma_deseq <- extract_de_plots(
  pairwise=hs_macr_combat,
  type="deseq",
  table="sh_vs_chr")
## Error in extract_de_plots(pairwise = hs_macr_combat, type = "deseq", table = "sh_vs_chr"): object 'hs_macr_combat' not found
hs_macr_combat_ma_deseq$ma$plot
## Error in eval(expr, envir, enclos): object 'hs_macr_combat_ma_deseq' not found

5 Figure out how to compare these results

I have 4 methods of performing this differential expression analysis. Each one comes with a set of metrics defining ‘significant’. Perhaps I can make a table of the # of genes defined as significant by contrast for each. In addition it may be worth while to do a scatter plots of the logFCs between these comparisons and see how well they agree?

6 Look first at the de counts

hs_macr_nobatch_sig$limma$counts
## Error in eval(expr, envir, enclos): object 'hs_macr_nobatch_sig' not found
hs_macr_batch_tables$significant$limma$counts
## Error in eval(expr, envir, enclos): object 'hs_macr_batch_tables' not found
hs_macr_sva_tables$significant$limma$counts
## Error in eval(expr, envir, enclos): object 'hs_macr_sva_tables' not found
hs_macr_ruvres_tables$significant$limma$counts
## Error in eval(expr, envir, enclos): object 'hs_macr_ruvres_tables' not found
hs_macr_pca_tables$significant$limma$counts
## Error in eval(expr, envir, enclos): object 'hs_macr_pca_tables' not found
hs_macr_ruvemp_tables$significant$limma$counts
## Error in eval(expr, envir, enclos): object 'hs_macr_ruvemp_tables' not found
hs_macr_combat_tables$significant$limma$counts
## Error in eval(expr, envir, enclos): object 'hs_macr_combat_tables' not found

6.1 Compare DeSeq / Basic without batch in model

hs_macr_nobatch_basic <- merge(
  hs_macr_nobatch$deseq$all_tables$sh_vs_chr,
  hs_macr_batch$basic$all_tables$sh_vs_chr,
  by="row.names")
rownames(hs_macr_nobatch_basic) <- hs_macr_nobatch_basic[["Row.names"]]
hs_macr_nobatch_logfc <- hs_macr_nobatch_basic[, c("logFC.x", "logFC.y")]
colnames(hs_macr_nobatch_logfc) <- c("nobatch", "basic")
lfc_nb_b <- sm(plot_linear_scatter(hs_macr_nobatch_logfc, pretty_colors=FALSE))
lfc_nb_b$scatter

lfc_nb_b$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 120, df = 7000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.8112 0.8266
## sample estimates:
##    cor 
## 0.8191
hs_macr_nobatch_p <- hs_macr_nobatch_basic[, c("P.Value","p")]
hs_macr_nobatch_p[[2]] <- as.numeric(hs_macr_nobatch_p[[2]])
colnames(hs_macr_nobatch_p) <- c("nobatch","basic")
hs_macr_nobatch_p <- -1 * log(hs_macr_nobatch_p)
hs_macr_p_nb_b <- sm(plot_linear_scatter(hs_macr_nobatch_p, pretty_colors=FALSE))
hs_macr_p_nb_b$scatter

hs_macr_p_nb_b$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 72, df = 7000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.6379 0.6649
## sample estimates:
##    cor 
## 0.6516

6.2 Compare SVA to batch in model, DESeq

hs_macr_sva_batch <- merge(
  hs_macr_sva$deseq$all_tables$sh_vs_chr,
  hs_macr_batch$deseq$all_tables$sh_vs_chr,
  by="row.names")
rownames(hs_macr_sva_batch) <- hs_macr_sva_batch[["Row.names"]]
hs_macr_sva_logfc <- hs_macr_sva_batch[, c("logFC.x","logFC.y")]
colnames(hs_macr_sva_logfc) <- c("sva","batch")
hs_macr_lfc_b_s <- sm(plot_linear_scatter(hs_macr_sva_logfc, pretty_colors=FALSE))
hs_macr_lfc_b_s$scatter

hs_macr_lfc_b_s$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 1000, df = 7000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.9967 0.9970
## sample estimates:
##    cor 
## 0.9968

6.2.1 Include p-value estimations

Try putting some information of the p-values with the comparative log2fc

lfc_b_s <- hs_macr_sva_batch[, c("logFC.x", "logFC.y", "P.Value.x", "P.Value.y")]
colnames(lfc_b_s) <- c("l2fcsva", "l2fcbatch", "psva", "pbatch")
hs_macr_lfc_b_s$scatter

cutoff <- 0.1
lfc_b_s$state <- ifelse(lfc_b_s$psva > cutoff & lfc_b_s$pbatch > cutoff, "bothinsig",
                 ifelse(lfc_b_s$psva <= cutoff & lfc_b_s$pbatch <= cutoff, "bothsig",
                 ifelse(lfc_b_s$psva <= cutoff, "svasig", "batchsig")))
##lfcp_b_s$lfcstate <- ifelse(lfcp_b_s$l2fcsva >= 0.75 & lfcp_b_s$l2fcbatch, "", "")
num_bothinsig <- sum(lfc_b_s$state == "bothinsig")
num_bothsig <- sum(lfc_b_s$state == "bothsig")
num_svasig <- sum(lfc_b_s$state == "svasig")
num_batchsig <- sum(lfc_b_s$state == "batchsig")

library(ggplot2)
## Need help? Try Stackoverflow:
## https://stackoverflow.com/tags/ggplot2.
aes_color = "(l2fcsva >= 0.75 | l2fcsva <= -0.75 | l2fcbatch >= 0.75 | l2fcbatch <= -0.75)"

plt <- ggplot2::ggplot(lfc_b_s, aes_string(x="l2fcsva", y="l2fcbatch")) +
    ## ggplot2::geom_point(stat="identity", size=2, alpha=0.2, aes_string(shape="as.factor(aes_color)", colour="as.factor(state)", fill="as.factor(state)")) +
    ggplot2::geom_abline(colour="blue", slope=1, intercept=0, size=0.5) +
    ggplot2::geom_hline(yintercept=c(-0.75, 0.75), color="red", size=0.5) +
    ggplot2::geom_vline(xintercept=c(-0.75, 0.75), color="red", size=0.5) +
    ggplot2::geom_point(stat="identity", size=2, alpha=0.2, aes_string(colour="as.factor(state)", fill="as.factor(state)")) +
    ggplot2::scale_color_manual(name="state", values=c("bothinsig"="grey", "bothsig"="forestgreen", "svasig"="darkred", "batchsig"="darkblue")) +
    ggplot2::scale_fill_manual(name="state", values=c("bothinsig"="grey", "bothsig"="forestgreen", "svasig"="darkred", "batchsig"="darkblue"),
                               labels=c(
                                   paste0("Both InSig.: ", num_bothinsig),
                                   paste0("Both Sig.: ", num_bothsig),
                                   paste0("Sva Sig.: ", num_svasig),
                                   paste0("Batch Sig.: ", num_batchsig)),
                               guide=ggplot2::guide_legend(override.aes=aes(size=3, fill="grey"))) +
    ggplot2::guides(fill=ggplot2::guide_legend(override.aes=list(size=3))) +
    ggplot2::theme_bw()
plt

6.3 Compare ruvresid to batch in model, DESeq

hs_macr_batch_ruvresid_deseq <- merge(
  hs_macr_ruvres$deseq$all_tables$sh_vs_chr,
  hs_macr_batch$basic$all_tables$sh_vs_chr,
  by="row.names")
rownames(hs_macr_batch_ruvresid_deseq) <- hs_macr_batch_ruvresid_deseq[["Row.names"]]
hs_macr_batch_ruvresid_logfc <- hs_macr_batch_ruvresid_deseq[, c("logFC.x","logFC.y")]
colnames(hs_macr_batch_ruvresid_logfc) <- c("nobatch","basic")
lfc_ruv_bat <- plot_linear_scatter(hs_macr_batch_ruvresid_logfc, pretty_colors=FALSE)
## Warning in plot_multihistogram(df): NAs introduced by coercion
## Used Bon Ferroni corrected t test(s) between columns.
lfc_ruv_bat$scatter

lfc_ruv_bat$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 140, df = 7000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.8574 0.8693
## sample estimates:
##    cor 
## 0.8634

6.4 Compare pca to batch in model, DESeq

hs_macr_batch_pca_deseq <- merge(
  hs_macr_pca$deseq$all_tables$sh_vs_chr,
  hs_macr_batch$basic$all_tables$sh_vs_chr,
  by="row.names")
rownames(hs_macr_batch_pca_deseq) <- hs_macr_batch_pca_deseq[["Row.names"]]
hs_macr_batch_pca_logfc <- hs_macr_batch_pca_deseq[, c("logFC.x", "logFC.y")]
colnames(hs_macr_batch_pca_logfc) <- c("nobatch","basic")
lfc_pca_bat <- plot_linear_scatter(hs_macr_batch_pca_logfc, pretty_colors=FALSE)
## Warning in plot_multihistogram(df): NAs introduced by coercion
## Used Bon Ferroni corrected t test(s) between columns.
lfc_pca_bat$scatter

lfc_pca_bat$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 50, df = 7000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.4989 0.5332
## sample estimates:
##    cor 
## 0.5162

6.5 Compare ruv empirical to batch in model, DESeq

hs_macr_batch_ruvemp_deseq <- merge(
  hs_macr_ruvemp$deseq$all_tables$sh_vs_chr,
  hs_macr_batch$basic$all_tables$sh_vs_chr,
  by="row.names")
rownames(hs_macr_batch_ruvemp_deseq) <- hs_macr_batch_ruvemp_deseq[["Row.names"]]
hs_macr_batch_ruvemp_logfc <- hs_macr_batch_ruvemp_deseq[, c("logFC.x","logFC.y")]
colnames(hs_macr_batch_ruvemp_logfc) <- c("nobatch","basic")
lfc_ruvemp_bat <- sm(plot_linear_scatter(hs_macr_batch_ruvemp_logfc, pretty_colors=FALSE))
lfc_ruvemp_bat$scatter

lfc_ruvemp_bat$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 57, df = 7000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.5487 0.5806
## sample estimates:
##    cor 
## 0.5648

6.6 Compare combat to batch in model, DESeq

hs_macr_combat_batch <- merge(
  hs_macr_combat$deseq$all_tables$sh_vs_chr,
  hs_macr_batch$deseq$all_tables$sh_vs_chr,
  by="row.names")
## Error in merge(hs_macr_combat$deseq$all_tables$sh_vs_chr, hs_macr_batch$deseq$all_tables$sh_vs_chr, : object 'hs_macr_combat' not found
rownames(hs_macr_combat_batch) <- hs_macr_combat_batch[["Row.names"]]
## Error in eval(expr, envir, enclos): object 'hs_macr_combat_batch' not found
hs_macr_combat_batch <- hs_macr_combat_batch[, c("logFC.x","logFC.y")]
## Error in eval(expr, envir, enclos): object 'hs_macr_combat_batch' not found
colnames(hs_macr_combat_batch) <- c("batch","combat")
## Error in colnames(hs_macr_combat_batch) <- c("batch", "combat"): object 'hs_macr_combat_batch' not found
b_c <- plot_linear_scatter(hs_macr_combat_batch, pretty_colors=FALSE)
## Error in data.frame(df[, c(1, 2)]): object 'hs_macr_combat_batch' not found
b_c$scatter
## Error in eval(expr, envir, enclos): object 'b_c' not found
b_c$correlation
## Error in eval(expr, envir, enclos): object 'b_c' not found

6.7 Compare no batch to batch in model, limma

hs_macr_nobatch_batch <- merge(
  hs_macr_nobatch$limma$all_tables$sh_vs_chr,
  hs_macr_batch$limma$all_tables$sh_vs_chr,
  by="row.names")
rownames(hs_macr_nobatch_batch) <- hs_macr_nobatch_batch[["Row.names"]]
hs_macr_nobatch_batch <- hs_macr_nobatch_batch[, c("logFC.x","logFC.y")]
colnames(hs_macr_nobatch_batch) <- c("nobatch","batch")
nb_b <- plot_linear_scatter(hs_macr_nobatch_batch, pretty_colors=FALSE)
## Warning in plot_multihistogram(df): NAs introduced by coercion
## Used Bon Ferroni corrected t test(s) between columns.
nb_b$scatter

nb_b$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 79, df = 7000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.6713 0.6962
## sample estimates:
##    cor 
## 0.6839

6.8 Batch in model vs. SVA, limma

hs_macr_batch_sva <- merge(
  hs_macr_batch$limma$all_tables$sh_vs_chr,
  hs_macr_sva$limma$all_tables$sh_vs_chr,
  by="row.names")
rownames(hs_macr_batch_sva) <- hs_macr_batch_sva[["Row.names"]]
hs_macr_batch_sva <- hs_macr_batch_sva[, c("logFC.x","logFC.y")]
colnames(hs_macr_batch_sva) <- c("batch","sva")
b_s <- plot_linear_scatter(hs_macr_batch_sva, pretty_colors=FALSE)
## Warning in plot_multihistogram(df): NAs introduced by coercion
## Used Bon Ferroni corrected t test(s) between columns.
b_s$scatter

b_s$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 460, df = 7000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.9830 0.9845
## sample estimates:
##    cor 
## 0.9837

6.9 Batch in model vs. combat, limma

hs_macr_batch_combat <- merge(
  hs_macr_batch$limma$all_tables$sh_vs_chr,
  hs_macr_combat$limma$all_tables$sh_vs_chr,
  by="row.names")
## Error in as.data.frame(y): object 'hs_macr_combat' not found
rownames(hs_macr_batch_combat) <- hs_macr_batch_combat[["Row.names"]]
## Error in eval(expr, envir, enclos): object 'hs_macr_batch_combat' not found
hs_macr_batch_combat <- hs_macr_batch_combat[, c("logFC.x","logFC.y")]
## Error in eval(expr, envir, enclos): object 'hs_macr_batch_combat' not found
colnames(hs_macr_batch_combat) <- c("batch","combat")
## Error in colnames(hs_macr_batch_combat) <- c("batch", "combat"): object 'hs_macr_batch_combat' not found
b_c <- plot_linear_scatter(hs_macr_batch_combat, pretty_colors=FALSE)
## Error in data.frame(df[, c(1, 2)]): object 'hs_macr_batch_combat' not found
b_c$scatter
## Error in eval(expr, envir, enclos): object 'b_c' not found
b_c$correlation
## Error in eval(expr, envir, enclos): object 'b_c' not found

6.10 Nobatch vs. batch in model, edger

hs_macr_nobatch_batch <- merge(
  hs_macr_nobatch$edger$all_tables$sh_vs_chr,
  hs_macr_batch$edger$all_tables$sh_vs_chr,
  by="row.names")
rownames(hs_macr_nobatch_batch) <- hs_macr_nobatch_batch[["Row.names"]]
hs_macr_nobatch_batch <- hs_macr_nobatch_batch[, c("logFC.x","logFC.y")]
colnames(hs_macr_nobatch_batch) <- c("nobatch","batch")
nb_b <- sm(plot_linear_scatter(hs_macr_nobatch_batch, pretty_colors=FALSE))
nb_b$scatter

nb_b$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 100, df = 7000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.7671 0.7857
## sample estimates:
##    cor 
## 0.7765

6.11 Batch in model vs. SVA, edger

hs_macr_batch_sva <- merge(
  hs_macr_batch$edger$all_tables$sh_vs_chr,
  hs_macr_sva$edger$all_tables$sh_vs_chr,
  by="row.names")
rownames(hs_macr_batch_sva) <- hs_macr_batch_sva[["Row.names"]]
hs_macr_batch_sva <- hs_macr_batch_sva[, c("logFC.x","logFC.y")]
colnames(hs_macr_batch_sva) <- c("batch","sva")
b_s <- plot_linear_scatter(hs_macr_batch_sva, pretty_colors=FALSE)
## Warning in plot_multihistogram(df): NAs introduced by coercion
## Used Bon Ferroni corrected t test(s) between columns.
b_s$scatter

b_s$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 340, df = 7000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.9698 0.9725
## sample estimates:
##    cor 
## 0.9712

6.12 Batch in model vs. combat, edger

hs_macr_batch_combat <- merge(
  hs_macr_batch$edger$all_tables$sh_vs_chr,
  hs_macr_combat$edger$all_tables$sh_vs_chr,
  by="row.names")
## Error in as.data.frame(y): object 'hs_macr_combat' not found
rownames(hs_macr_batch_combat) <- hs_macr_batch_combat[["Row.names"]]
## Error in eval(expr, envir, enclos): object 'hs_macr_batch_combat' not found
hs_macr_batch_combat <- hs_macr_batch_combat[, c("logFC.x","logFC.y")]
## Error in eval(expr, envir, enclos): object 'hs_macr_batch_combat' not found
colnames(hs_macr_batch_combat) <- c("batch","combat")
## Error in colnames(hs_macr_batch_combat) <- c("batch", "combat"): object 'hs_macr_batch_combat' not found
b_c <- plot_linear_scatter(hs_macr_batch_combat, pretty_colors=FALSE)
## Error in data.frame(df[, c(1, 2)]): object 'hs_macr_batch_combat' not found
b_c$scatter
## Error in eval(expr, envir, enclos): object 'b_c' not found
b_c$correlation
## Error in eval(expr, envir, enclos): object 'b_c' not found

6.13 Compare nobatch vs. batch, deseq

hs_macr_nobatch_batch <- merge(
  hs_macr_nobatch$deseq$all_tables$sh_vs_chr,
  hs_macr_batch$deseq$all_tables$sh_vs_chr,
  by="row.names")
rownames(hs_macr_nobatch_batch) <- hs_macr_nobatch_batch[["Row.names"]]
hs_macr_nobatch_batch <- hs_macr_nobatch_batch[, c("logFC.x","logFC.y")]
colnames(hs_macr_nobatch_batch) <- c("nobatch","batch")
nb_b <- sm(plot_linear_scatter(hs_macr_nobatch_batch, pretty_colors=FALSE))
nb_b$scatter

nb_b$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 79, df = 7000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.6727 0.6975
## sample estimates:
##    cor 
## 0.6853

6.14 Compare batch vs. SVA, deseq

hs_macr_batch_sva <- merge(
  hs_macr_batch$deseq$all_tables$sh_vs_chr,
  hs_macr_sva$deseq$all_tables$sh_vs_chr,
  by="row.names")
rownames(hs_macr_batch_sva) <- hs_macr_batch_sva[["Row.names"]]
hs_macr_batch_sva <- hs_macr_batch_sva[, c("logFC.x", "logFC.y")]
colnames(hs_macr_batch_sva) <- c("batch", "sva")
b_s <- sm(plot_linear_scatter(hs_macr_batch_sva, pretty_colors=FALSE))
b_s$scatter

b_s$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 1000, df = 7000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.9967 0.9970
## sample estimates:
##    cor 
## 0.9968

6.15 Batch in model vs. combat, deseq

hs_macr_batch_combat <- merge(
  hs_macr_batch$deseq$all_tables$sh_vs_chr,
  hs_macr_combat$deseq$all_tables$sh_vs_chr,
  by="row.names")
## Error in as.data.frame(y): object 'hs_macr_combat' not found
rownames(hs_macr_batch_combat) <- hs_macr_batch_combat[["Row.names"]]
## Error in eval(expr, envir, enclos): object 'hs_macr_batch_combat' not found
hs_macr_batch_combat <- hs_macr_batch_combat[, c("logFC.x", "logFC.y")]
## Error in eval(expr, envir, enclos): object 'hs_macr_batch_combat' not found
colnames(hs_macr_batch_combat) <- c("batch", "combat")
## Error in colnames(hs_macr_batch_combat) <- c("batch", "combat"): object 'hs_macr_batch_combat' not found
b_c <- sm(plot_linear_scatter(hs_macr_batch_combat, pretty_colors=FALSE))
## Error in data.frame(df[, c(1, 2)]): object 'hs_macr_batch_combat' not found
b_c$scatter
## Error in eval(expr, envir, enclos): object 'b_c' not found
b_c$correlation
## Error in eval(expr, envir, enclos): object 'b_c' not found

7 Repeat using the parasite data

In ‘macrophage_estimation’, we did a series of analyses to try to pick out some of the surrogate variables in the data. Now we will perform a set of differential expression analyses using the results from that. Since the ‘batch’ element of the data is reasonably well explained, we will not abuse the data with sva/combat, but instead include batch in the experimental model.

It appears that it is possible though somewhat difficult to apply batch estimations generated by sva to the model given to DESeq/EdgeR/limma. In the case of limma it is fairly simple, but in the other two it is a bit more difficult. There is a nice discussion of this at: https://www.biostars.org/p/156186/ I am attempting to apply that logic to this data with limited success.

lp_contrasts <- list(
    "macro_chr-sh" = c("chr", "sh"))
lp_macr_norm <- sm(normalize_expt(lp_macr, filter=TRUE, convert="cpm", norm="quant"))
lp_macr_combat_norm <- sm(normalize_expt(lp_macr, filter=TRUE, norm="quant",
                                         low_to_zero=TRUE, batch="combat"))
lp_macr_lowfilt <- sm(normalize_expt(lp_macr, filter=TRUE))
## Set up the data used in the 3 comparative contrast sets.

7.1 No batch in the model

lp_macr_nobatch <- sm(all_pairwise(lp_macr_lowfilt, limma_method="robust", model_batch=FALSE))
## wow, all tools including basic agree almost completely
medians_by_condition <- lp_macr_nobatch$basic$medians
lp_macr_nobatch_tables <- sm(combine_de_tables(
  lp_macr_nobatch,
  excel=paste0("excel/lp_macr_nobatch-v", ver, ".xlsx"),
  sig_excel=paste0("excel/lp_macr_nobatch_significant-v", ver, ".xlsx"),
  keepers=lp_contrasts,
  extra_annot=medians_by_condition))
## Error in .subset2(x, i, exact = exact): subscript out of bounds

7.2 Batch in the model

In this attempt, we add a batch factor in the experimental model and see how it does.

## Here just let all_pairwise run on filtered data and do its normal ~ 0 + condition + batch analyses
lp_macr_batch <- sm(all_pairwise(lp_macr_lowfilt, limma_method="robust"))
medians_by_condition <- lp_macr_batch$basic$medians
lp_macr_batch_tables <- sm(combine_de_tables(
  lp_macr_batch,
  excel=paste0("excel/lp_macr_batchmodel-v", ver, ".xlsx"),
  sig_excel=paste0("excel/lp_macr_batchmodel_significant-v", ver, ".xlsx"),
  keepers=lp_contrasts,
  extra_annot=medians_by_condition))
## Error in .subset2(x, i, exact = exact): subscript out of bounds

7.3 Batch estimated with SVA

## Here just let all_pairwise run on filtered data and do its normal ~ 0 + condition + batch analyses
lp_macr_sva <- sm(all_pairwise(lp_macr_lowfilt, limma_method="robust", model_batch="sva"))
medians_by_condition <- lp_macr_sva$basic$medians
lp_macr_sva_tables <- sm(combine_de_tables(
  lp_macr_sva,
  excel=paste0("excel/lp_macr_sva-v", ver, ".xlsx"),
  sig_excel=paste0("excel/lp_macr_sva_significant-v", ver, ".xlsx"),
  keepers=lp_contrasts,
  extra_annot=medians_by_condition))
## Error in .subset2(x, i, exact = exact): subscript out of bounds

7.4 Batch correction via ruv residuals

## Here just let all_pairwise run on filtered data and do its normal ~ 0 + condition + batch analyses
## Bizarrely, sometimes if one runs this, it gives an error "Error in (function
## (classes, fdef, mtable) : unable to find an inherited method for function
## 'RUVr' for signature '"matrix", "logical", "numeric", "NULL"'"  -- however,
## if one then simply runs it again it works fine.
## I changed model_surrogates.R to take care of this I think.
lp_macr_ruvres <- sm(all_pairwise(lp_macr_lowfilt, model_batch="ruv_residuals", limma_method="robust"))
medians_by_condition <- lp_macr_ruvres$basic$medians
lp_macr_ruvres_tables <- sm(combine_de_tables(
  lp_macr_ruvres,
  excel=paste0("excel/lp_macr_ruvres-v", ver, ".xlsx"),
  sig_excel=paste0("excel/lp_macr_ruvres_significant-v", ver, ".xlsx"),
  keepers=lp_contrasts,
  extra_annot=medians_by_condition))
## Error in .subset2(x, i, exact = exact): subscript out of bounds

7.5 Batch correction with pca

## Here just let all_pairwise run on filtered data and do its normal ~ 0 + condition + batch analyses
lp_macr_pca <- sm(all_pairwise(lp_macr_lowfilt, model_batch="pca", limma_method="robust"))
medians_by_condition <- lp_macr_pca$basic$medians
lp_macr_pca_tables <- sm(combine_de_tables(
  lp_macr_pca,
  excel=paste0("excel/lp_macr_pca-v", ver, ".xlsx"),
  sig_excel=paste0("excel/lp_macr_pca_significant-v", ver, ".xlsx"),
  keepers=lp_contrasts,
  extra_annot=medians_by_condition))
## Error in .subset2(x, i, exact = exact): subscript out of bounds

7.6 Batch correction with ruv empirical

## Here just let all_pairwise run on filtered data and do its normal ~ 0 + condition + batch analyses
lp_macr_ruvemp <- sm(all_pairwise(lp_macr_lowfilt, model_batch="ruv_empirical", limma_method="robust"))
medians_by_condition <- lp_macr_ruvemp$basic$medians
lp_macr_ruvemp_tables <- sm(combine_de_tables(
  lp_macr_ruvemp,
  excel=paste0("excel/lp_macr_ruvemp-v", ver, ".xlsx"),
  sig_excel=paste0("excel/lp_macr_ruvemp_significant-v", ver, ".xlsx"),
  keepers=lp_contrasts,
  extra_annot=medians_by_condition))
## Error in .subset2(x, i, exact = exact): subscript out of bounds

7.7 Batch correction with combat

Then repeat with the batch-corrected data and see the differences.

lp_macr_combat <- all_pairwise(lp_macr_combat_norm, force=TRUE,
                               limma_method="robust", parallel=FALSE)
## Using limma's removeBatchEffect to visualize before/after batch inclusion.
## Starting basic pairwise comparison.
## Leaving the data alone, regardless of normalization state.
## Basic step 0/3: Transforming data.
## Basic step 1/3: Creating median and variance tables.
## Basic step 2/3: Performing 3 comparisons.
## 
  |                                                                       
  |                                                                 |   0%
  |                                                                       
  |=================================================================| 100%
## Basic step 3/3: Creating faux DE Tables.
## Basic: Returning tables.
## Starting DESeq2 pairwise comparisons.
## About to round the data, this is a pretty terrible thing to do. But if you,
## like me, want to see what happens when you put non-standard data into deseq, then here you go.
## Warning in choose_binom_dataset(input, force = force): This data was
## inappropriately forced into integers.
## Choosing the non-intercept containing model.
## DESeq2 step 1/5: Including batch and condition in the deseq model.
## converting counts to integer mode
## DESeq2 step 2/5: Estimate size factors.
## DESeq2 step 3/5: Estimate dispersions.
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## Using a parametric fitting seems to have worked.
## DESeq2 step 4/5: nbinomWaldTest.
## Plotting dispersions.
## 
  |                                                                       
  |                                                                 |   0%
  |                                                                       
  |=================================================================| 100%
## EdgeR/DESeq expect raw data as input, reverting to the count filtered data.
## Starting EBSeq pairwise subset.
## Starting EBTest of chr vs. sh.
## Starting edgeR pairwise comparisons.
## About to round the data, this is a pretty terrible thing to do. But if you,
## like me, want to see what happens when you put non-standard data into deseq, then here you go.
## Warning in choose_binom_dataset(input, force = force): This data was
## inappropriately forced into integers.
## Choosing the non-intercept containing model.
## 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.
## 
  |                                                                       
  |                                                                 |   0%
  |                                                                       
  |=================================================================| 100%
## Starting limma pairwise comparison.
## Leaving the data alone, regardless of normalization state.
## 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.
## Choosing the non-intercept containing 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: robust.
## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps
## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps

## Warning in rlm.default(x = X, y = y, weights = w, ...): 'rlm' failed to
## converge in 20 steps
## Limma step 4/6: making and fitting contrasts with no intercept. (~ 0 + factors)
## Limma step 5/6: Running eBayes with robust=FALSE and trend=FALSE.
## Limma step 6/6: Writing limma outputs.
## Limma step 6/6: 1/1: Creating table: sh_vs_chr.  Adjust=BH
## Limma step 6/6: 1/2: Creating table: chr.  Adjust=BH
## Limma step 6/6: 2/2: Creating table: sh.  Adjust=BH
## Comparing analyses 1/1: sh_vs_chr
## Comparing analyses 1/1: sh_vs_chr
## Comparing analyses 1/1: sh_vs_chr
## Comparing analyses 1/1: sh_vs_chr
## Comparing analyses 1/1: sh_vs_chr
## Comparing analyses 1/1: sh_vs_chr
## Comparing analyses 1/1: sh_vs_chr
## Comparing analyses 1/1: sh_vs_chr
## Comparing analyses 1/1: sh_vs_chr
## Comparing analyses 1/1: sh_vs_chr
medians_by_condition <- lp_macr_combat$basic$medians
lp_macr_combat_tables <- sm(combine_de_tables(
  lp_macr_combat,
  excel=paste0("excel/lp_macr_combat-v", ver, ".xlsx"),
  sig_excel=paste0("excel/lp_macr_combat_significant-v", ver, ".xlsx"),
  keepers=lp_contrasts,
  extra_annot=medians_by_condition))
## Error in .subset2(x, i, exact = exact): subscript out of bounds

8 Figure out how to compare these results

I have 4 methods of performing this differential expression analysis. Each one comes with a set of metrics defining ‘significant’. Perhaps I can make a table of the # of genes defined as significant by contrast for each. In addition it may be worth while to do a scatter plots of the logFCs between these comparisons and see how well they agree?

9 Look first at the de counts

lp_macr_nobatch_tables$significant$limma$counts
## Error in eval(expr, envir, enclos): object 'lp_macr_nobatch_tables' not found
lp_macr_batch_tables$significant$limma$counts
## Error in eval(expr, envir, enclos): object 'lp_macr_batch_tables' not found
lp_macr_sva_tables$significant$limma$counts
## Error in eval(expr, envir, enclos): object 'lp_macr_sva_tables' not found
lp_macr_ruvres_tables$significant$limma$counts
## Error in eval(expr, envir, enclos): object 'lp_macr_ruvres_tables' not found
lp_macr_pca_tables$significant$limma$counts
## Error in eval(expr, envir, enclos): object 'lp_macr_pca_tables' not found
lp_macr_ruvemp_tables$significant$limma$counts
## Error in eval(expr, envir, enclos): object 'lp_macr_ruvemp_tables' not found
lp_macr_combat_tables$significant$limma$counts
## Error in eval(expr, envir, enclos): object 'lp_macr_combat_tables' not found

9.1 Compare DeSeq / Basic without batch in model

lp_macr_nobatch_basic <- merge(
  lp_macr_nobatch$deseq$all_tables$sh_vs_chr,
  lp_macr_batch$basic$all_tables$sh_vs_chr,
  by="row.names")
rownames(lp_macr_nobatch_basic) <- lp_macr_nobatch_basic[["Row.names"]]
lp_macr_nobatch_logfc <- lp_macr_nobatch_basic[, c("logFC.x", "logFC.y")]
colnames(lp_macr_nobatch_logfc) <- c("nobatch","basic")
lfc_nb_b <- sm(plot_linear_scatter(lp_macr_nobatch_logfc, pretty_colors=FALSE))
lfc_nb_b$scatter

lfc_nb_b$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 89, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.6805 0.7025
## sample estimates:
##    cor 
## 0.6917
lp_macr_nobatch_p <- lp_macr_nobatch_basic[, c("P.Value","p")]
lp_macr_nobatch_p[[2]] <- as.numeric(lp_macr_nobatch_p[[2]])
colnames(lp_macr_nobatch_p) <- c("nobatch","basic")
lp_macr_nobatch_p <- -1 * log(lp_macr_nobatch_p)
p_nb_b <- sm(plot_linear_scatter(lp_macr_nobatch_p, pretty_colors=FALSE))
p_nb_b$scatter

p_nb_b$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 120, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.7760 0.7922
## sample estimates:
##    cor 
## 0.7842

9.2 Compare SVA to batch in model, DESeq

lp_macr_sva_batch <- merge(
  lp_macr_sva$deseq$all_tables$sh_vs_chr,
  lp_macr_batch$deseq$all_tables$sh_vs_chr,
  by="row.names")
rownames(lp_macr_sva_batch) <- lp_macr_sva_batch[["Row.names"]]
lp_macr_sva_logfc <- lp_macr_sva_batch[, c("logFC.x","logFC.y")]
colnames(lp_macr_sva_logfc) <- c("sva","batch")
lfc_b_s <- sm(plot_linear_scatter(lp_macr_sva_logfc, pretty_colors=FALSE))
lfc_b_s$scatter

lfc_b_s$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 55, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.4939 0.5251
## sample estimates:
##    cor 
## 0.5097
lp_macr_sva_p <- lp_macr_sva_batch[, c("P.Value.x","P.Value.y")]
lp_macr_sva_p[[2]] <- as.numeric(lp_macr_sva_p[[2]])
colnames(lp_macr_sva_p) <- c("sva","batch")
lp_macr_sva_p <- -1 * log(lp_macr_sva_p)
p_b_s <- sm(plot_linear_scatter(lp_macr_sva_p, pretty_colors=FALSE))
p_b_s$scatter

p_b_s$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 25, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.2381 0.2774
## sample estimates:
##    cor 
## 0.2579

9.2.1 Include p-value estimations

Try putting some information of the p-values with the comparative log2fc

lfcp_b_s <- lp_macr_sva_batch[, c("logFC.x", "logFC.y", "P.Value.x", "P.Value.y")]
colnames(lfcp_b_s) <- c("l2fcsva", "l2fcbatch", "psva", "pbatch")
lfc_b_s$scatter

cutoff <- 0.1
lfcp_b_s$state <- ifelse(lfcp_b_s$psva > cutoff & lfcp_b_s$pbatch > cutoff, "bothinsig",
                  ifelse(lfcp_b_s$psva <= cutoff & lfcp_b_s$pbatch <= cutoff, "bothsig",
                  ifelse(lfcp_b_s$psva <= cutoff, "svasig", "batchsig")))
##lfcp_b_s$lfcstate <- ifelse(lfcp_b_s$l2fcsva >= 0.75 & lfcp_b_s$l2fcbatch, "", "")
num_bothinsig <- sum(lfcp_b_s$state == "bothinsig")
num_bothsig <- sum(lfcp_b_s$state == "bothsig")
num_svasig <- sum(lfcp_b_s$state == "svasig")
num_batchsig <- sum(lfcp_b_s$state == "batchsig")

library(ggplot2)
aes_color = "(l2fcsva >= 0.75 | l2fcsva <= -0.75 | l2fcbatch >= 0.75 | l2fcbatch <= -0.75)"

plt <- ggplot2::ggplot(lfcp_b_s, aes_string(x="l2fcsva", y="l2fcbatch")) +
    ## ggplot2::geom_point(stat="identity", size=2, alpha=0.2, aes_string(shape="as.factor(aes_color)", colour="as.factor(state)", fill="as.factor(state)")) +
    ggplot2::geom_abline(colour="blue", slope=1, intercept=0, size=0.5) +
    ggplot2::geom_hline(yintercept=c(-0.75, 0.75), color="red", size=0.5) +
    ggplot2::geom_vline(xintercept=c(-0.75, 0.75), color="red", size=0.5) +
    ggplot2::geom_point(stat="identity", size=2, alpha=0.2, aes_string(colour="as.factor(state)", fill="as.factor(state)")) +
    ggplot2::scale_color_manual(name="state", values=c("bothinsig"="grey", "bothsig"="forestgreen", "svasig"="darkred", "batchsig"="darkblue")) +
    ggplot2::scale_fill_manual(name="state", values=c("bothinsig"="grey", "bothsig"="forestgreen", "svasig"="darkred", "batchsig"="darkblue"),
                               labels=c(
                                   paste0("Both InSig.: ", num_bothinsig),
                                   paste0("Both Sig.: ", num_bothsig),
                                   paste0("Sva Sig.: ", num_svasig),
                                   paste0("Batch Sig.: ", num_batchsig)),
                               guide=ggplot2::guide_legend(override.aes=aes(size=3, fill="grey"))) +
    ggplot2::guides(fill=ggplot2::guide_legend(override.aes=list(size=3))) +
    ggplot2::theme_bw()
plt

9.3 Compare ruvresid to batch in model, DESeq

lp_macr_batch_ruvresid_deseq <- merge(
  lp_macr_ruvres$deseq$all_tables$sh_vs_chr,
  lp_macr_batch$basic$all_tables$sh_vs_chr,
  by="row.names")
rownames(lp_macr_batch_ruvresid_deseq) <- lp_macr_batch_ruvresid_deseq[["Row.names"]]
lp_macr_batch_ruvresid_logfc <- lp_macr_batch_ruvresid_deseq[, c("logFC.x","logFC.y")]
colnames(lp_macr_batch_ruvresid_logfc) <- c("nobatch","basic")
lfc_ruv_bat <- plot_linear_scatter(lp_macr_batch_ruvresid_logfc, pretty_colors=FALSE)
## Warning in plot_multihistogram(df): NAs introduced by coercion
## Used Bon Ferroni corrected t test(s) between columns.
lfc_ruv_bat$scatter

lfc_ruv_bat$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 130, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.7949 0.8099
## sample estimates:
##    cor 
## 0.8025

9.4 Compare pca to batch in model, DESeq

lp_macr_batch_pca_deseq <- merge(
  lp_macr_pca$deseq$all_tables$sh_vs_chr,
  lp_macr_batch$basic$all_tables$sh_vs_chr,
  by="row.names")
rownames(lp_macr_batch_pca_deseq) <- lp_macr_batch_pca_deseq[["Row.names"]]
lp_macr_batch_pca_logfc <- lp_macr_batch_pca_deseq[, c("logFC.x","logFC.y")]
colnames(lp_macr_batch_pca_logfc) <- c("nobatch","basic")
lfc_pca_bat <- plot_linear_scatter(lp_macr_batch_pca_logfc, pretty_colors=FALSE)
## Warning in plot_multihistogram(df): NAs introduced by coercion
## Used Bon Ferroni corrected t test(s) between columns.
lfc_pca_bat$scatter

lfc_pca_bat$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 64, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.5499 0.5786
## sample estimates:
##    cor 
## 0.5644

9.5 Compare ruv empirical to batch in model, DESeq

lp_macr_batch_ruvemp_deseq <- merge(
  lp_macr_ruvemp$deseq$all_tables$sh_vs_chr,
  lp_macr_batch$basic$all_tables$sh_vs_chr,
  by="row.names")
rownames(lp_macr_batch_ruvemp_deseq) <- lp_macr_batch_ruvemp_deseq[["Row.names"]]
lp_macr_batch_ruvemp_logfc <- lp_macr_batch_ruvemp_deseq[, c("logFC.x","logFC.y")]
colnames(lp_macr_batch_ruvemp_logfc) <- c("nobatch","basic")
lfc_ruvemp_bat <- sm(plot_linear_scatter(lp_macr_batch_ruvemp_logfc, pretty_colors=FALSE))
lfc_ruvemp_bat$scatter

lfc_ruvemp_bat$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 100, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.7289 0.7480
## sample estimates:
##    cor 
## 0.7386

9.6 Compare combat to batch in model, DESeq

lp_macr_combat_batch <- merge(
  lp_macr_combat$deseq$all_tables$sh_vs_chr,
  lp_macr_batch$deseq$all_tables$sh_vs_chr,
  by="row.names")
rownames(lp_macr_combat_batch) <- lp_macr_combat_batch[["Row.names"]]
lp_macr_combat_batch <- lp_macr_combat_batch[, c("logFC.x","logFC.y")]
colnames(lp_macr_combat_batch) <- c("batch","combat")
b_c <- plot_linear_scatter(lp_macr_combat_batch, pretty_colors=FALSE)
## Warning in plot_multihistogram(df): NAs introduced by coercion
## Used Bon Ferroni corrected t test(s) between columns.
b_c$scatter

b_c$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 150, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.8500 0.8613
## sample estimates:
##    cor 
## 0.8558

9.7 Compare no batch to batch in model, limma

lp_macr_nobatch_batch <- merge(
  lp_macr_nobatch$limma$all_tables$sh_vs_chr,
  lp_macr_batch$limma$all_tables$sh_vs_chr,
  by="row.names")
rownames(lp_macr_nobatch_batch) <- lp_macr_nobatch_batch[["Row.names"]]
lp_macr_nobatch_batch <- lp_macr_nobatch_batch[, c("logFC.x","logFC.y")]
colnames(lp_macr_nobatch_batch) <- c("nobatch","batch")
nb_b <- plot_linear_scatter(lp_macr_nobatch_batch, pretty_colors=FALSE)
## Warning in plot_multihistogram(df): NAs introduced by coercion
## Used Bon Ferroni corrected t test(s) between columns.
nb_b$scatter

nb_b$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 150, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.8441 0.8558
## sample estimates:
##    cor 
## 0.8501

9.8 Batch in model vs. SVA, limma

lp_macr_batch_sva <- merge(
  lp_macr_batch$limma$all_tables$sh_vs_chr,
  lp_macr_sva$limma$all_tables$sh_vs_chr,
  by="row.names")
rownames(lp_macr_batch_sva) <- lp_macr_batch_sva[["Row.names"]]
lp_macr_batch_sva <- lp_macr_batch_sva[, c("logFC.x","logFC.y")]
colnames(lp_macr_batch_sva) <- c("batch","sva")
b_s <- plot_linear_scatter(lp_macr_batch_sva, pretty_colors=FALSE)
## Warning in plot_multihistogram(df): NAs introduced by coercion
## Used Bon Ferroni corrected t test(s) between columns.
b_s$scatter

b_s$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 45, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.4216 0.4556
## sample estimates:
##    cor 
## 0.4387

9.9 Batch in model vs. combat, limma

lp_macr_batch_combat <- merge(
  lp_macr_batch$limma$all_tables$sh_vs_chr,
  lp_macr_combat$limma$all_tables$sh_vs_chr,
  by="row.names")
rownames(lp_macr_batch_combat) <- lp_macr_batch_combat[["Row.names"]]
lp_macr_batch_combat <- lp_macr_batch_combat[, c("logFC.x","logFC.y")]
colnames(lp_macr_batch_combat) <- c("batch","combat")
b_c <- plot_linear_scatter(lp_macr_batch_combat, pretty_colors=FALSE)
## Warning in plot_multihistogram(df): NAs introduced by coercion
## Used Bon Ferroni corrected t test(s) between columns.
b_c$scatter

b_c$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 360, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.9663 0.9690
## sample estimates:
##    cor 
## 0.9677

9.10 Nobatch vs. batch in model, edger

lp_macr_nobatch_batch <- merge(
  lp_macr_nobatch$edger$all_tables$sh_vs_chr,
  lp_macr_batch$edger$all_tables$sh_vs_chr,
  by="row.names")
rownames(lp_macr_nobatch_batch) <- lp_macr_nobatch_batch[["Row.names"]]
lp_macr_nobatch_batch <- lp_macr_nobatch_batch[, c("logFC.x","logFC.y")]
colnames(lp_macr_nobatch_batch) <- c("nobatch","batch")
nb_b <- sm(plot_linear_scatter(lp_macr_nobatch_batch, pretty_colors=FALSE))
nb_b$scatter

nb_b$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 100, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.7371 0.7558
## sample estimates:
##    cor 
## 0.7466

9.11 Batch in model vs. SVA, edger

lp_macr_batch_sva <- merge(
  lp_macr_batch$edger$all_tables$sh_vs_chr,
  lp_macr_sva$edger$all_tables$sh_vs_chr,
  by="row.names")
rownames(lp_macr_batch_sva) <- lp_macr_batch_sva[["Row.names"]]
lp_macr_batch_sva <- lp_macr_batch_sva[, c("logFC.x","logFC.y")]
colnames(lp_macr_batch_sva) <- c("batch","sva")
b_s <- plot_linear_scatter(lp_macr_batch_sva, pretty_colors=FALSE)
## Warning in plot_multihistogram(df): NAs introduced by coercion
## Used Bon Ferroni corrected t test(s) between columns.
b_s$scatter

b_s$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 56, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.4966 0.5277
## sample estimates:
##    cor 
## 0.5123

9.12 Batch in model vs. combat, edger

lp_macr_batch_combat <- merge(
  lp_macr_batch$edger$all_tables$sh_vs_chr,
  lp_macr_combat$edger$all_tables$sh_vs_chr,
  by="row.names")
rownames(lp_macr_batch_combat) <- lp_macr_batch_combat[["Row.names"]]
lp_macr_batch_combat <- lp_macr_batch_combat[, c("logFC.x","logFC.y")]
colnames(lp_macr_batch_combat) <- c("batch","combat")
b_c <- plot_linear_scatter(lp_macr_batch_combat, pretty_colors=FALSE)
## Warning in plot_multihistogram(df): NAs introduced by coercion
## Used Bon Ferroni corrected t test(s) between columns.
b_c$scatter

b_c$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 150, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.8500 0.8613
## sample estimates:
##    cor 
## 0.8558

9.13 Compare nobatch vs. batch, deseq

lp_macr_nobatch_batch <- merge(
  lp_macr_nobatch$deseq$all_tables$sh_vs_chr,
  lp_macr_batch$deseq$all_tables$sh_vs_chr,
  by="row.names")
rownames(lp_macr_nobatch_batch) <- lp_macr_nobatch_batch[["Row.names"]]
lp_macr_nobatch_batch <- lp_macr_nobatch_batch[, c("logFC.x","logFC.y")]
colnames(lp_macr_nobatch_batch) <- c("nobatch","batch")
nb_b <- sm(plot_linear_scatter(lp_macr_nobatch_batch, pretty_colors=FALSE))
nb_b$scatter

nb_b$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 110, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.7400 0.7585
## sample estimates:
##    cor 
## 0.7494

9.14 Compare batch vs. SVA, deseq

lp_macr_batch_sva <- merge(
  lp_macr_batch$deseq$all_tables$sh_vs_chr,
  lp_macr_sva$deseq$all_tables$sh_vs_chr,
  by="row.names")
rownames(lp_macr_batch_sva) <- lp_macr_batch_sva[["Row.names"]]
lp_macr_batch_sva <- lp_macr_batch_sva[, c("logFC.x","logFC.y")]
colnames(lp_macr_batch_sva) <- c("batch","sva")
b_s <- sm(plot_linear_scatter(lp_macr_batch_sva, pretty_colors=FALSE))
b_s$scatter

b_s$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 55, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.4939 0.5251
## sample estimates:
##    cor 
## 0.5097

9.15 Batch in model vs. combat, deseq

lp_macr_batch_combat <- merge(
  lp_macr_batch$deseq$all_tables$sh_vs_chr,
  lp_macr_combat$deseq$all_tables$sh_vs_chr,
  by="row.names")
rownames(lp_macr_batch_combat) <- lp_macr_batch_combat[["Row.names"]]
lp_macr_batch_combat <- lp_macr_batch_combat[, c("logFC.x","logFC.y")]
colnames(lp_macr_batch_combat) <- c("batch","combat")
b_c <- sm(plot_linear_scatter(lp_macr_batch_combat, pretty_colors=FALSE))
b_c$scatter

b_c$correlation
## 
##  Pearson's product-moment correlation
## 
## data:  df[, 1] and df[, 2]
## t = 150, df = 8700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.8500 0.8613
## sample estimates:
##    cor 
## 0.8558
pander::pander(sessionInfo())

R version 3.5.1 (2018-07-02)

Platform: x86_64-pc-linux-gnu (64-bit)

locale: LC_CTYPE=en_US.utf8, LC_NUMERIC=C, LC_TIME=en_US.utf8, LC_COLLATE=en_US.utf8, LC_MONETARY=en_US.utf8, LC_MESSAGES=en_US.utf8, LC_PAPER=en_US.utf8, LC_NAME=C, LC_ADDRESS=C, LC_TELEPHONE=C, LC_MEASUREMENT=en_US.utf8 and LC_IDENTIFICATION=C

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

other attached packages: ggplot2(v.3.0.0), edgeR(v.3.22.3), ruv(v.0.9.7) and hpgltools(v.2018.03)

loaded via a namespace (and not attached): backports(v.1.1.2), Hmisc(v.4.1-1), aroma.light(v.3.10.0), plyr(v.1.8.4), lazyeval(v.0.2.1), splines(v.3.5.1), BiocParallel(v.1.14.2), GenomeInfoDb(v.1.16.0), sva(v.3.28.0), digest(v.0.6.15), foreach(v.1.4.4), BiocInstaller(v.1.30.0), htmltools(v.0.3.6), gdata(v.2.18.0), magrittr(v.1.5), checkmate(v.1.8.5), memoise(v.1.1.0), cluster(v.2.0.7-1), doParallel(v.1.0.11), openxlsx(v.4.1.0), limma(v.3.36.2), Biostrings(v.2.48.0), annotate(v.1.58.0), matrixStats(v.0.54.0), R.utils(v.2.6.0), blockmodeling(v.0.3.1), prettyunits(v.1.0.2), colorspace(v.1.3-2), blob(v.1.1.1), ggrepel(v.0.8.0), dplyr(v.0.7.6), crayon(v.1.3.4), RCurl(v.1.95-4.11), graph(v.1.58.0), roxygen2(v.6.1.0), genefilter(v.1.62.0), lme4(v.1.1-17), bindr(v.0.1.1), survival(v.2.42-6), iterators(v.1.0.10), glue(v.1.3.0), registry(v.0.5), gtable(v.0.2.0), zlibbioc(v.1.26.0), XVector(v.0.20.0), DelayedArray(v.0.6.4), DEoptimR(v.1.0-8), BiocGenerics(v.0.26.0), DESeq(v.1.32.0), scales(v.1.0.0), rngtools(v.1.3.1), DBI(v.1.0.0), bibtex(v.0.4.2), Rcpp(v.0.12.18), xtable(v.1.8-2), progress(v.1.2.0), htmlTable(v.1.12), foreign(v.0.8-71), bit(v.1.1-14), OrganismDbi(v.1.22.0), preprocessCore(v.1.42.0), Formula(v.1.2-3), EBSeq(v.1.20.0), stats4(v.3.5.1), htmlwidgets(v.1.2), httr(v.1.3.1), gplots(v.3.0.1), RColorBrewer(v.1.1-2), acepack(v.1.4.1), R.methodsS3(v.1.7.1), pkgconfig(v.2.0.1), XML(v.3.98-1.15), nnet(v.7.3-12), locfit(v.1.5-9.1), tidyselect(v.0.2.4), labeling(v.0.3), rlang(v.0.2.1), reshape2(v.1.4.3), AnnotationDbi(v.1.42.1), munsell(v.0.5.0), tools(v.3.5.1), RSQLite(v.2.1.1), devtools(v.1.13.6), evaluate(v.0.11), stringr(v.1.3.1), yaml(v.2.2.0), knitr(v.1.20), bit64(v.0.9-7), pander(v.0.6.2), robustbase(v.0.93-2), zip(v.1.0.0), caTools(v.1.17.1.1), purrr(v.0.2.5), bindrcpp(v.0.2.2), EDASeq(v.2.14.1), doRNG(v.1.7.1), RBGL(v.1.56.0), nlme(v.3.1-137), R.oo(v.1.22.0), xml2(v.1.2.0), biomaRt(v.2.36.1), compiler(v.3.5.1), pbkrtest(v.0.4-7), rstudioapi(v.0.7), testthat(v.2.0.0), variancePartition(v.1.10.0), statmod(v.1.4.30), tibble(v.1.4.2), geneplotter(v.1.58.0), stringi(v.1.2.4), GenomicFeatures(v.1.32.1), lattice(v.0.20-35), Matrix(v.1.2-14), commonmark(v.1.5), nloptr(v.1.0.4), pillar(v.1.3.0), data.table(v.1.11.4), bitops(v.1.0-6), corpcor(v.1.6.9), rtracklayer(v.1.40.4), GenomicRanges(v.1.32.6), colorRamps(v.2.3), hwriter(v.1.3.2), R6(v.2.2.2), latticeExtra(v.0.6-28), directlabels(v.2018.05.22), ShortRead(v.1.38.0), KernSmooth(v.2.23-15), gridExtra(v.2.3), IRanges(v.2.14.10), codetools(v.0.2-15), MASS(v.7.3-50), gtools(v.3.8.1), assertthat(v.0.2.0), SummarizedExperiment(v.1.10.1), pkgmaker(v.0.27), DESeq2(v.1.20.0), rprojroot(v.1.3-2), RUVSeq(v.1.14.0), withr(v.2.1.2), GenomicAlignments(v.1.16.0), Rsamtools(v.1.32.2), S4Vectors(v.0.18.3), GenomeInfoDbData(v.1.1.0), mgcv(v.1.8-24), parallel(v.3.5.1), hms(v.0.4.2), quadprog(v.1.5-5), grid(v.3.5.1), rpart(v.4.1-13), minqa(v.1.2.4), rmarkdown(v.1.10), Biobase(v.2.40.0) and base64enc(v.0.1-3)

message(paste0("This is hpgltools commit: ", get_git_commit()))
## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset 8a4df418d36491bab7b987cd21768b3d7cab1269
## R> packrat::restore()
## This is hpgltools commit: Thu Aug 16 10:45:44 2018 -0400: 8a4df418d36491bab7b987cd21768b3d7cab1269
this_save <- paste0(gsub(pattern="\\.Rmd", replace="", x=rmd_file), "-v", ver, ".rda.xz")
message(paste0("Saving to ", this_save))
## Saving to 03_expression_macrophage-v20170820.rda.xz
tmp <- sm(saveme(filename=this_save))
LS0tCnRpdGxlOiAiTC5wYW5hbWVuc2lzIDIwMTY6IERpZmZlcmVudGlhbCBFeHByZXNzaW9uIGluIGh1bWFuIG1hY3JvcGhhZ2VzLCBkdXJpbmcgaW5mZWN0aW9uLCBpbiBiaW9wc2llcywgYW5kIHdpdGggYW50aW1vbmlhbCB0cmVhdG1lbnQuIgphdXRob3I6ICJhdGIgYWJlbGV3QGdtYWlsLmNvbSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiBodG1sX2RvY3VtZW50OgogIGNvZGVfZG93bmxvYWQ6IHRydWUKICBjb2RlX2ZvbGRpbmc6IHNob3cKICBmaWdfY2FwdGlvbjogdHJ1ZQogIGZpZ19oZWlnaHQ6IDcKICBmaWdfd2lkdGg6IDcKICBoaWdobGlnaHQ6IGRlZmF1bHQKICBrZWVwX21kOiBmYWxzZQogIG1vZGU6IHNlbGZjb250YWluZWQKICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogIHRoZW1lOiByZWFkYWJsZQogIHRvYzogdHJ1ZQogIHRvY19mbG9hdDoKICAgIGNvbGxhcHNlZDogZmFsc2UKICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlPgogIGJvZHkgLm1haW4tY29udGFpbmVyIHsKICAgIG1heC13aWR0aDogMTYwMHB4OwogIH0KPC9zdHlsZT4KCmBgYHtyIG9wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoImhwZ2x0b29scyIpCnR0IDwtIGRldnRvb2xzOjpsb2FkX2FsbCgifi9ocGdsdG9vbHMiKQprbml0cjo6b3B0c19rbml0JHNldChwcm9ncmVzcz1UUlVFLAogICAgICAgICAgICAgICAgICAgICB2ZXJib3NlPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgIHdpZHRoPTkwLAogICAgICAgICAgICAgICAgICAgICBlY2hvPVRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvcj1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLndpZHRoPTgsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuaGVpZ2h0PTgsCiAgICAgICAgICAgICAgICAgICAgICBkcGk9OTYpCm9sZF9vcHRpb25zIDwtIG9wdGlvbnMoZGlnaXRzPTQsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBrbml0ci5kdXBsaWNhdGUubGFiZWw9ImFsbG93IikKZ2dwbG90Mjo6dGhlbWVfc2V0KGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZT0xMCkpCnNldC5zZWVkKDEpCnByZXZpb3VzX2ZpbGUgPC0gIjAyX2VzdGltYXRpb25fbWFjcm9waGFnZS5SbWQiCnZlciA8LSAiMjAxNzA4MjAiCgp0bXAgPC0gc20obG9hZG1lKGZpbGVuYW1lPXBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IiIsIHg9cHJldmlvdXNfZmlsZSksICItdiIsIHZlciwgIi5yZGEueHoiKSkpCnJtZF9maWxlIDwtICIwM19leHByZXNzaW9uX21hY3JvcGhhZ2UuUm1kIgpgYGAKCiMgRGlmZmVyZW50aWFsIEV4cHJlc3Npb24sIE1hY3JvcGhhZ2U6IGByIHZlcmAKCiMgRGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzZXMKCkl0IGFwcGVhcnMgdGhhdCBpdCBpcyBwb3NzaWJsZSB0aG91Z2ggc29tZXdoYXQgZGlmZmljdWx0IHRvIGFwcGx5IGJhdGNoIGVzdGltYXRpb25zIGdlbmVyYXRlZCBieSBzdmEKdG8gdGhlIG1vZGVsIGdpdmVuIHRvIERFU2VxL0VkZ2VSL2xpbW1hLiAgSW4gdGhlIGNhc2Ugb2YgbGltbWEgaXQgaXMgZmFpcmx5IHNpbXBsZSwgYnV0IGluIHRoZSBvdGhlcgp0d28gaXQgaXMgYSBiaXQgbW9yZSBkaWZmaWN1bHQuICBUaGVyZSBpcyBhIG5pY2UgZGlzY3Vzc2lvbiBvZiB0aGlzIGF0OiBodHRwczovL3d3dy5iaW9zdGFycy5vcmcvcC8xNTYxODYvCkkgYW0gYXR0ZW1wdGluZyB0byBhcHBseSB0aGF0IGxvZ2ljIHRvIHRoaXMgZGF0YSB3aXRoIGxpbWl0ZWQgc3VjY2Vzcy4KCmBgYHtyIHNldHVwX2RlX25vcm0sIGZpZy5zaG93PSJoaWRlIn0KaHNfY29udHJhc3RzIDwtIGxpc3QoCiAgICAibWFjcm9fY2hyLXNoIiA9IGMoImNociIsInNoIiksCiAgICAibWFjcm9fY2hyLW5pbCIgPSBjKCJjaHIiLCJ1bmluZiIpLAogICAgIm1hY3JvX3NoLW5pbCIgPSBjKCJzaCIsICJ1bmluZiIpKQpoc19tYWNyX25vcm0gPC0gc20obm9ybWFsaXplX2V4cHQoaHNfY2RzX21hY3IsIGZpbHRlcj1UUlVFLCBjb252ZXJ0PSJjcG0iKSkKaHNfbWFjcl9jb21iYXRfbm9ybSA8LSBzbShub3JtYWxpemVfZXhwdChoc19jZHNfbWFjciwgZmlsdGVyPVRSVUUsIGJhdGNoPSJjb21iYXQiKSkKaHNfbWFjcl9zdmFfbm9ybSA8LSBzbShub3JtYWxpemVfZXhwdChoc19jZHNfbWFjciwgZmlsdGVyPVRSVUUsIGJhdGNoPSJzdmFzZXEiKSkKaHNfbWFjcl9sb3dmaWx0IDwtIHNtKG5vcm1hbGl6ZV9leHB0KGhzX2Nkc19tYWNyLCBmaWx0ZXI9VFJVRSkpCiMjIFNldCB1cCB0aGUgZGF0YSB1c2VkIGluIHRoZSBjb21wYXJhdGl2ZSBjb250cmFzdCBzZXRzLgpgYGAKCiMjIE5vIGJhdGNoIGluIHRoZSBtb2RlbAoKYGBge3IgbWFjcm9fbm9iYXRjaDEsIGZpZy5zaG93PSJoaWRlIn0KaHNfbWFjcl9ub2JhdGNoIDwtIHNtKGFsbF9wYWlyd2lzZShpbnB1dD1oc19tYWNyX2xvd2ZpbHQsIG1vZGVsX2JhdGNoPUZBTFNFLCBsaW1tYV9tZXRob2Q9InJvYnVzdCIpKQojIyB3b3csIGFsbCB0b29scyBpbmNsdWRpbmcgYmFzaWMgYWdyZWUgYWxtb3N0IGNvbXBsZXRlbHkKbWVkaWFuc19ieV9jb25kaXRpb24gPC0gaHNfbWFjcl9ub2JhdGNoJGJhc2ljJG1lZGlhbnMKaHNfbWFjcl9ub2JhdGNoX3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcyhoc19tYWNyX25vYmF0Y2gsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9cGFzdGUwKCJleGNlbC9oc19tYWNyX25vYmF0Y2gtdiIsIHZlciwgIi54bHN4IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2VlcGVycz1oc19jb250cmFzdHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXh0cmFfYW5ub3Q9bWVkaWFuc19ieV9jb25kaXRpb24pKQpoc19tYWNyX25vYmF0Y2hfc2lnIDwtIHNtKGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoaHNfbWFjcl9ub2JhdGNoX3RhYmxlcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvaHNfbWFjcl9ub2JhdGNoX3NpZ25pZmljYW50LXYiLCB2ZXIsICIueGxzeCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWNjb3JkaW5nX3RvPSJhbGwiKSkKYGBgCgojIyBCYXRjaCBpbiB0aGUgbW9kZWwKCkluIHRoaXMgIGF0dGVtcHQsIHdlIGFkZCBhIGJhdGNoIGZhY3RvciBpbiB0aGUgZXhwZXJpbWVudGFsIG1vZGVsIGFuZCBzZWUgaG93IGl0IGRvZXMuCgpgYGB7ciBtYWNyb19iYXRjaDEsIGZpZy5zaG93PSJoaWRlIn0KIyMgSGVyZSBqdXN0IGxldCBhbGxfcGFpcndpc2UgcnVuIG9uIGZpbHRlcmVkIGRhdGEgYW5kIGRvIGl0cyBub3JtYWwgfiAwICsgY29uZGl0aW9uICsgYmF0Y2ggYW5hbHlzZXMKaHNfbWFjcl9iYXRjaCA8LSBzbShhbGxfcGFpcndpc2UoaW5wdXQ9aHNfbWFjcl9sb3dmaWx0LCBsaW1tYV9tZXRob2Q9InJvYnVzdCIsIHBhcmFsbGVsPUZBTFNFKSkKbWVkaWFuc19ieV9jb25kaXRpb24gPC0gaHNfbWFjcl9iYXRjaCRiYXNpYyRtZWRpYW5zCmhzX21hY3JfYmF0Y2hfdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKAogIGhzX21hY3JfYmF0Y2gsCiAgZXhjZWw9cGFzdGUwKCJleGNlbC9oc19tYWNyX2JhdGNobW9kZWwtdiIsIHZlciwgIi54bHN4IiksCiAgc2lnX2V4Y2VsPXBhc3RlMCgiZXhjZWwvaHNfbWFjcm9fYmF0Y2htb2RlbF9zaWduaWZpY2FudC12IiwgdmVyLCAiLnhsc3giKSwKICBrZWVwZXJzPWhzX2NvbnRyYXN0cywKICBleHRyYV9hbm5vdD1tZWRpYW5zX2J5X2NvbmRpdGlvbikpCmBgYAoKIyBUYWJsZSBTMiBhbmQgRmlndXJlIDFiCgogKiBUYWJsZSBTMiBpcyB0YWtpbmcgb25seSB0aGUgREVTZXEyIHJlc3VsdHMuCiAqIEZpZ3VyZSAxYyBpcyBpbnRlbmRlZCB0byBiZSBhIHZvbGNhbm8gcGxvdCBvZiB0aGUgREVTZXEyIHJlc3VsdHMuCgpgYGB7ciB0YWJsZV9zMn0KczJfY29udHJhc3RzIDwtIGxpc3QoCiAgIm1hY3JvX2Noci1zaCIgPSBjKCJjaHIiLCJzaCIpKQp0YWJsZV9zMiA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICBoc19tYWNyX2JhdGNoLAogIGV4Y2VsPXBhc3RlMCgiZXhjZWwvdGFibGVfczJfaHNfbWFjcl9iYXRjaG1vZGVsLXYiLCB2ZXIsICIueGxzeCIpLAogIGtlZXBlcnM9czJfY29udHJhc3RzLAogIGluY2x1ZGVfYmFzaWM9RkFMU0UsIGluY2x1ZGVfbGltbWE9RkFMU0UsIGluY2x1ZGVfZWRnZXI9RkFMU0UpKQoKY2hvc2VuX3RhYmxlIDwtIHRhYmxlX3MyW1siZGF0YSJdXVtbImNocl92c19zaCJdXQojI2hlYWQoY2hvc2VuX3RhYmxlKQp2b2wgPC0gcGxvdF92b2xjYW5vX2RlKHRhYmxlPWNob3Nlbl90YWJsZSwKICAgICAgICAgICAgICAgICAgICAgICBjb2xvcl9ieT0ic3RhdGUiLAogICAgICAgICAgICAgICAgICAgICAgIGZjX2NvbD0iZGVzZXFfbG9nZmMiLAogICAgICAgICAgICAgICAgICAgICAgIHBfY29sPSJkZXNlcV9hZGpwIiwKICAgICAgICAgICAgICAgICAgICAgICBzaGFwZXNfYnlfc3RhdGU9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgbGluZV9wb3NpdGlvbj0idG9wIikKcHAoZmlsZT0iaW1hZ2VzL0ZpZ3VyZV8xYy5wZGYiKQp2b2wkcGxvdApkZXYub2ZmKCkKYGBgCgojIFRhYmxlIFMzCgpUYWJsZSBTMyBpcyB0YWtpbmcgb25seSB0aGUgREVTZXEyIHJlc3VsdHMgb2Ygc2lnbmlmaWNhbnQgZ2VuZXMuCgpgYGB7ciB0YWJsZV9zMwp0YWJsZV9zMyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogIHRhYmxlX3MyLCBhY2NvcmRpbmdfdG89ImRlc2VxIiwKICBleGNlbD1wYXN0ZTAoImV4Y2VsL3RhYmxlX3MzX2hzX21hY3JfYmF0Y2htb2RlbF9zaWduaWZpY2FudC12IiwgdmVyLCAiLnhsc3giKSkKYGBgCgojIyBCYXRjaCBlc3RpbWF0ZWQgd2l0aCBTVkEKCmBgYHtyIG1hY3JvX3N2YTEsIGZpZy5zaG93PSJoaWRlIn0KIyMgSGVyZSBqdXN0IGxldCBhbGxfcGFpcndpc2UgcnVuIG9uIGZpbHRlcmVkIGRhdGEgYW5kIGRvIGl0cyBub3JtYWwgfiAwICsgY29uZGl0aW9uICsgYmF0Y2ggYW5hbHlzZXMKaHNfbWFjcl9zdmEgPC0gc20oYWxsX3BhaXJ3aXNlKAogIGlucHV0PWhzX21hY3JfbG93ZmlsdCwKICBtb2RlbF9iYXRjaD0ic3Zhc2VxIiwKICBsaW1tYV9tZXRob2Q9InJvYnVzdCIpKQptZWRpYW5zX2J5X2NvbmRpdGlvbiA8LSBoc19tYWNyX3N2YSRiYXNpYyRtZWRpYW5zCmhzX21hY3Jfc3ZhX3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICBoc19tYWNyX3N2YSwKICBleGNlbD1wYXN0ZTAoImV4Y2VsL2hzX21hY3Jfc3ZhLXYiLCB2ZXIsICIueGxzeCIpLAogIHNpZ19leGNlbD1wYXN0ZTAoImV4Y2VsL2hzX21hY3Jfc3ZhX3NpZ25pZmljYW50LXYiLCB2ZXIsICIueGxzeCIpLAogIGtlZXBlcnM9aHNfY29udHJhc3RzLAogIGV4dHJhX2Fubm90PW1lZGlhbnNfYnlfY29uZGl0aW9uKSkKCmhzX21hY3Jfc3ZhX21hX2xpbW1hIDwtIGV4dHJhY3RfZGVfcGxvdHMoCiAgcGFpcndpc2U9aHNfbWFjcl9zdmEsCiAgdHlwZT0ibGltbWEiLAogIHRhYmxlPSJzaF92c19jaHIiKQpgYGAKCmBgYHtyIHN2YV9tYV9wbG90fQpoc19tYWNyX3N2YV9tYV9saW1tYSRtYSRwbG90CmBgYAoKIyMgQmF0Y2ggY29ycmVjdGlvbiB2aWEgcnV2IHJlc2lkdWFscwoKYGBge3IgbWFjcm9fcnV2cmVzaWQxLCBmaWcuc2hvdz0iaGlkZSJ9CiMjIEhlcmUganVzdCBsZXQgYWxsX3BhaXJ3aXNlIHJ1biBvbiBmaWx0ZXJlZCBkYXRhIGFuZCBkbyBpdHMgbm9ybWFsIH4gMCArIGNvbmRpdGlvbiArIGJhdGNoIGFuYWx5c2VzCiMjIEJpemFycmVseSwgc29tZXRpbWVzIGlmIG9uZSBydW5zIHRoaXMsIGl0IGdpdmVzIGFuIGVycm9yICJFcnJvciBpbiAoZnVuY3Rpb24gKGNsYXNzZXMsIGZkZWYsIG10YWJsZSkgOiB1bmFibGUgdG8gZmluZCBhbiBpbmhlcml0ZWQgbWV0aG9kIGZvciBmdW5jdGlvbiAnUlVWcicgZm9yIHNpZ25hdHVyZSAnIm1hdHJpeCIsICJsb2dpY2FsIiwgIm51bWVyaWMiLCAiTlVMTCInIiAgLS0gaG93ZXZlciwgaWYgb25lIHRoZW4gc2ltcGx5IHJ1bnMgaXQgYWdhaW4gaXQgd29ya3MgZmluZS4KIyMgSSBhbSBnb2luZyB0byBhc3N1bWUgdGhhdCBpdCBpcyBiZWNhdXNlIEkgZG8gbm90IGV4cGxpY2l0bHkgaW52b2tlIHRoZSBsaWJyYXJ5LgojIyBsaWJyYXJ5KHJ1dikgICMjIGhvcGVmdWxseSBhIHNtYWxsIGNvZGUgY2hhbmdlIG1hZGUgdGhpcyBub3QgbmVlZGVkLgp0ZXN0bWUgPC0gZ2V0X21vZGVsX2FkanVzdChpbnB1dD1oc19tYWNyX2xvd2ZpbHQsIGVzdGltYXRlX3R5cGU9InJ1dl9yZXNpZHVhbHMiKQojIyBobW0gSSBnb3QgdGhlIFJVVnIgZXJyb3IgYWdhaW4sIGJ1dCB3aGVuIEkgcmFuIGl0IG1hbnVhbGx5IGRpZCBub3QuCiMjIEV2ZW4gbW9yZSBzdHJhbmdlbHksIGlmIEkganVzdCBydW4gdGhlIHNhbWUgdGhpbmcgYWdhaW4sIG5vIGVycm9yLi4uCnRlc3RtZSA8LSBnZXRfbW9kZWxfYWRqdXN0KGlucHV0PWhzX21hY3JfbG93ZmlsdCwgZXN0aW1hdGVfdHlwZT0icnV2X3Jlc2lkdWFscyIpCmhzX21hY3JfcnV2cmVzIDwtIHNtKGFsbF9wYWlyd2lzZSgKICBpbnB1dD1oc19tYWNyX2xvd2ZpbHQsCiAgbW9kZWxfYmF0Y2g9InJ1dl9yZXNpZHVhbHMiLAogIGxpbW1hX21ldGhvZD0icm9idXN0IikpCm1lZGlhbnNfYnlfY29uZGl0aW9uIDwtIGhzX21hY3JfcnV2cmVzJGJhc2ljJG1lZGlhbnMKaHNfbWFjcl9ydXZyZXNfdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKAogIGhzX21hY3JfcnV2cmVzLAogIGV4Y2VsPXBhc3RlMCgiZXhjZWwvaHNfbWFjcl9ydXZyZXMtdiIsIHZlciwgIi54bHN4IiksCiAgc2lnX2V4Y2VsPXBhc3RlMCgiZXhjZWwvaHNfbWFjcl9ydXZyZXNfc2lnbmlmaWNhbnQtdiIsIHZlciwgIi54bHN4IiksCiAga2VlcGVycz1oc19jb250cmFzdHMsCiAgZXh0cmFfYW5ub3Q9bWVkaWFuc19ieV9jb25kaXRpb24pKQpgYGAKCiMjIEJhdGNoIGNvcnJlY3Rpb24gd2l0aCBwY2EKCmBgYHtyIG1hY3JvX3BjYTEsIGZpZy5zaG93PSJoaWRlIn0KIyMgSGVyZSBqdXN0IGxldCBhbGxfcGFpcndpc2UgcnVuIG9uIGZpbHRlcmVkIGRhdGEgYW5kIGRvIGl0cyBub3JtYWwgfiAwICsgY29uZGl0aW9uICsgYmF0Y2ggYW5hbHlzZXMKaHNfbWFjcl9wY2EgPC0gc20oYWxsX3BhaXJ3aXNlKAogIGlucHV0PWhzX21hY3JfbG93ZmlsdCwKICBtb2RlbF9iYXRjaD0icGNhIiwKICBsaW1tYV9tZXRob2Q9InJvYnVzdCIpKQptZWRpYW5zX2J5X2NvbmRpdGlvbiA8LSBoc19tYWNyX3BjYSRiYXNpYyRtZWRpYW5zCmhzX21hY3JfcGNhX3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICBoc19tYWNyX3BjYSwKICBleGNlbD1wYXN0ZTAoImV4Y2VsL2hzX21hY3JfcGNhLXYiLCB2ZXIsICIueGxzeCIpLAogIHNpZ19leGNlbD1wYXN0ZTAoImV4Y2VsL2hzX21hY3JfcGNhX3NpZ25pZmljYW50LXYiLCB2ZXIsICIueGxzeCIpLAogIGtlZXBlcnM9aHNfY29udHJhc3RzLAogIGV4dHJhX2Fubm90PW1lZGlhbnNfYnlfY29uZGl0aW9uKSkKYGBgCgojIyBCYXRjaCBjb3JyZWN0aW9uIHdpdGggcnV2IGVtcGlyaWNhbAoKYGBge3IgbWFjcm9fcnV2ZW1wMSwgZmlnLnNob3c9ImhpZGUifQojIyBIZXJlIGp1c3QgbGV0IGFsbF9wYWlyd2lzZSBydW4gb24gZmlsdGVyZWQgZGF0YSBhbmQgZG8gaXRzIG5vcm1hbCB+IDAgKyBjb25kaXRpb24gKyBiYXRjaCBhbmFseXNlcwpoc19tYWNyX3J1dmVtcCA8LSBzbShhbGxfcGFpcndpc2UoCiAgaW5wdXQ9aHNfbWFjcl9sb3dmaWx0LAogIG1vZGVsX2JhdGNoPSJydXZfZW1waXJpY2FsIiwKICBsaW1tYV9tZXRob2Q9InJvYnVzdCIpKQptZWRpYW5zX2J5X2NvbmRpdGlvbiA8LSBoc19tYWNyX3J1dmVtcCRiYXNpYyRtZWRpYW5zCmhzX21hY3JfcnV2ZW1wX3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICBoc19tYWNyX3J1dmVtcCwKICBleGNlbD1wYXN0ZTAoImV4Y2VsL2hzX21hY3JfcnV2ZW1wLXYiLCB2ZXIsICIueGxzeCIpLAogIHNpZ19leGNlbD1wYXN0ZTAoImV4Y2VsL2hzX21hY3JfcnV2ZW1wX3NpZ25pZmljYW50LXYiLCB2ZXIsICIueGxzeCIpLAogIGtlZXBlcnM9aHNfY29udHJhc3RzLAogIGV4dHJhX2Fubm90PW1lZGlhbnNfYnlfY29uZGl0aW9uKSkKYGBgCgojIyBCYXRjaCBjb3JyZWN0aW9uIHdpdGggY29tYmF0CgpUaGVuIHJlcGVhdCB3aXRoIHRoZSBiYXRjaC1jb3JyZWN0ZWQgZGF0YSBhbmQgc2VlIHRoZSBkaWZmZXJlbmNlcy4KCmBgYHtyIHJlcGVhdF9wYWlyd2lzZV9iYXRjaDEsIGZpZy5zaG93PSJoaWRlIn0KaHNfbWFjcl9jb21iYXQgPC0gc20oYWxsX3BhaXJ3aXNlKAogIGlucHV0PWhzX21hY3JfY29tYmF0X25vcm0sCiAgZm9yY2U9VFJVRSwKICBsaW1tYV9tZXRob2Q9InJvYnVzdCIpKQptZWRpYW5zX2J5X2NvbmRpdGlvbiA8LSBoc19tYWNyX2NvbWJhdCRiYXNpYyRtZWRpYW5zCmhzX21hY3JfY29tYmF0X3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICBoc19tYWNyX2NvbWJhdCwKICBleGNlbD1wYXN0ZTAoImV4Y2VsL2hzX21hY3JfY29tYmF0LXYiLCB2ZXIsICIueGxzeCIpLAogIHNpZ19leGNlcD1wYXN0ZTAoImV4Y2VsL2hzX21hY3JfY29tYmF0X3NpZ25pZmljYW50LXYiLCB2ZXIsICIueGxzeCIpLAogIGtlZXBlcnM9aHNfY29udHJhc3RzLAogIGV4dHJhX2Fubm90PW1lZGlhbnNfYnlfY29uZGl0aW9uKSkKYGBgCgpgYGB7ciBmaW5pc2hlZF9tYV9wbG90c30KaHNfbWFjcl9jb21iYXRfbWFfbGltbWEgPC0gZXh0cmFjdF9kZV9wbG90cygKICBwYWlyd2lzZT1oc19tYWNyX2NvbWJhdCwKICB0eXBlPSJsaW1tYSIsCiAgdGFibGU9InNoX3ZzX2NociIpCmhzX21hY3JfY29tYmF0X21hX2xpbW1hJG1hJHBsb3QKCmhzX21hY3JfY29tYmF0X21hX2VkZ2VyIDwtIGV4dHJhY3RfZGVfcGxvdHMoCiAgcGFpcndpc2U9aHNfbWFjcl9jb21iYXQsCiAgdHlwZT0iZWRnZXIiLAogIHRhYmxlPSJzaF92c19jaHIiKQpoc19tYWNyX2NvbWJhdF9tYV9lZGdlciRtYSRwbG90Cgpoc19tYWNyX2NvbWJhdF9tYV9kZXNlcSA8LSBleHRyYWN0X2RlX3Bsb3RzKAogIHBhaXJ3aXNlPWhzX21hY3JfY29tYmF0LAogIHR5cGU9ImRlc2VxIiwKICB0YWJsZT0ic2hfdnNfY2hyIikKaHNfbWFjcl9jb21iYXRfbWFfZGVzZXEkbWEkcGxvdApgYGAKCiMgRmlndXJlIG91dCBob3cgdG8gY29tcGFyZSB0aGVzZSByZXN1bHRzCgpJIGhhdmUgNCBtZXRob2RzIG9mIHBlcmZvcm1pbmcgdGhpcyBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcy4gIEVhY2ggb25lIGNvbWVzIHdpdGggYSBzZXQgb2YKbWV0cmljcyBkZWZpbmluZyAnc2lnbmlmaWNhbnQnLiAgUGVyaGFwcyBJIGNhbiBtYWtlIGEgdGFibGUgb2YgdGhlICMgb2YgZ2VuZXMgZGVmaW5lZCBhcyBzaWduaWZpY2FudApieSBjb250cmFzdCBmb3IgZWFjaC4gIEluIGFkZGl0aW9uIGl0IG1heSBiZSB3b3J0aCB3aGlsZSB0byBkbyBhIHNjYXR0ZXIgcGxvdHMgb2YgdGhlIGxvZ0ZDcyBiZXR3ZWVuCnRoZXNlIGNvbXBhcmlzb25zIGFuZCBzZWUgaG93IHdlbGwgdGhleSBhZ3JlZT8KCiMgTG9vayBmaXJzdCBhdCB0aGUgZGUgY291bnRzCgpgYGB7ciBjb21wYXJlX2RlX3NldHVwMX0KaHNfbWFjcl9ub2JhdGNoX3NpZyRsaW1tYSRjb3VudHMKaHNfbWFjcl9iYXRjaF90YWJsZXMkc2lnbmlmaWNhbnQkbGltbWEkY291bnRzCmhzX21hY3Jfc3ZhX3RhYmxlcyRzaWduaWZpY2FudCRsaW1tYSRjb3VudHMKaHNfbWFjcl9ydXZyZXNfdGFibGVzJHNpZ25pZmljYW50JGxpbW1hJGNvdW50cwpoc19tYWNyX3BjYV90YWJsZXMkc2lnbmlmaWNhbnQkbGltbWEkY291bnRzCmhzX21hY3JfcnV2ZW1wX3RhYmxlcyRzaWduaWZpY2FudCRsaW1tYSRjb3VudHMKaHNfbWFjcl9jb21iYXRfdGFibGVzJHNpZ25pZmljYW50JGxpbW1hJGNvdW50cwpgYGAKCiMjIENvbXBhcmUgRGVTZXEgLyBCYXNpYyB3aXRob3V0IGJhdGNoIGluIG1vZGVsCgpgYGB7ciBiYXNpY19kZXNlcV9ub2JhdGNoMX0KaHNfbWFjcl9ub2JhdGNoX2Jhc2ljIDwtIG1lcmdlKAogIGhzX21hY3Jfbm9iYXRjaCRkZXNlcSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBoc19tYWNyX2JhdGNoJGJhc2ljJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhoc19tYWNyX25vYmF0Y2hfYmFzaWMpIDwtIGhzX21hY3Jfbm9iYXRjaF9iYXNpY1tbIlJvdy5uYW1lcyJdXQpoc19tYWNyX25vYmF0Y2hfbG9nZmMgPC0gaHNfbWFjcl9ub2JhdGNoX2Jhc2ljWywgYygibG9nRkMueCIsICJsb2dGQy55IildCmNvbG5hbWVzKGhzX21hY3Jfbm9iYXRjaF9sb2dmYykgPC0gYygibm9iYXRjaCIsICJiYXNpYyIpCmxmY19uYl9iIDwtIHNtKHBsb3RfbGluZWFyX3NjYXR0ZXIoaHNfbWFjcl9ub2JhdGNoX2xvZ2ZjLCBwcmV0dHlfY29sb3JzPUZBTFNFKSkKbGZjX25iX2Ikc2NhdHRlcgpsZmNfbmJfYiRjb3JyZWxhdGlvbgpoc19tYWNyX25vYmF0Y2hfcCA8LSBoc19tYWNyX25vYmF0Y2hfYmFzaWNbLCBjKCJQLlZhbHVlIiwicCIpXQpoc19tYWNyX25vYmF0Y2hfcFtbMl1dIDwtIGFzLm51bWVyaWMoaHNfbWFjcl9ub2JhdGNoX3BbWzJdXSkKY29sbmFtZXMoaHNfbWFjcl9ub2JhdGNoX3ApIDwtIGMoIm5vYmF0Y2giLCJiYXNpYyIpCmhzX21hY3Jfbm9iYXRjaF9wIDwtIC0xICogbG9nKGhzX21hY3Jfbm9iYXRjaF9wKQpoc19tYWNyX3BfbmJfYiA8LSBzbShwbG90X2xpbmVhcl9zY2F0dGVyKGhzX21hY3Jfbm9iYXRjaF9wLCBwcmV0dHlfY29sb3JzPUZBTFNFKSkKaHNfbWFjcl9wX25iX2Ikc2NhdHRlcgpoc19tYWNyX3BfbmJfYiRjb3JyZWxhdGlvbgpgYGAKCiMjIENvbXBhcmUgU1ZBIHRvIGJhdGNoIGluIG1vZGVsLCBERVNlcQoKYGBge3IgZGVzZXFfc3ZhX2JhdGNoMX0KaHNfbWFjcl9zdmFfYmF0Y2ggPC0gbWVyZ2UoCiAgaHNfbWFjcl9zdmEkZGVzZXEkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgaHNfbWFjcl9iYXRjaCRkZXNlcSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBieT0icm93Lm5hbWVzIikKcm93bmFtZXMoaHNfbWFjcl9zdmFfYmF0Y2gpIDwtIGhzX21hY3Jfc3ZhX2JhdGNoW1siUm93Lm5hbWVzIl1dCmhzX21hY3Jfc3ZhX2xvZ2ZjIDwtIGhzX21hY3Jfc3ZhX2JhdGNoWywgYygibG9nRkMueCIsImxvZ0ZDLnkiKV0KY29sbmFtZXMoaHNfbWFjcl9zdmFfbG9nZmMpIDwtIGMoInN2YSIsImJhdGNoIikKaHNfbWFjcl9sZmNfYl9zIDwtIHNtKHBsb3RfbGluZWFyX3NjYXR0ZXIoaHNfbWFjcl9zdmFfbG9nZmMsIHByZXR0eV9jb2xvcnM9RkFMU0UpKQpoc19tYWNyX2xmY19iX3Mkc2NhdHRlcgpoc19tYWNyX2xmY19iX3MkY29ycmVsYXRpb24KYGBgCgojIyMgSW5jbHVkZSBwLXZhbHVlIGVzdGltYXRpb25zCgpUcnkgcHV0dGluZyBzb21lIGluZm9ybWF0aW9uIG9mIHRoZSBwLXZhbHVlcyB3aXRoIHRoZSBjb21wYXJhdGl2ZSBsb2cyZmMKCmBgYHtyIGwyZnNfcHZhbHMxfQpsZmNfYl9zIDwtIGhzX21hY3Jfc3ZhX2JhdGNoWywgYygibG9nRkMueCIsICJsb2dGQy55IiwgIlAuVmFsdWUueCIsICJQLlZhbHVlLnkiKV0KY29sbmFtZXMobGZjX2JfcykgPC0gYygibDJmY3N2YSIsICJsMmZjYmF0Y2giLCAicHN2YSIsICJwYmF0Y2giKQpoc19tYWNyX2xmY19iX3Mkc2NhdHRlcgpjdXRvZmYgPC0gMC4xCmxmY19iX3Mkc3RhdGUgPC0gaWZlbHNlKGxmY19iX3MkcHN2YSA+IGN1dG9mZiAmIGxmY19iX3MkcGJhdGNoID4gY3V0b2ZmLCAiYm90aGluc2lnIiwKICAgICAgICAgICAgICAgICBpZmVsc2UobGZjX2JfcyRwc3ZhIDw9IGN1dG9mZiAmIGxmY19iX3MkcGJhdGNoIDw9IGN1dG9mZiwgImJvdGhzaWciLAogICAgICAgICAgICAgICAgIGlmZWxzZShsZmNfYl9zJHBzdmEgPD0gY3V0b2ZmLCAic3Zhc2lnIiwgImJhdGNoc2lnIikpKQojI2xmY3BfYl9zJGxmY3N0YXRlIDwtIGlmZWxzZShsZmNwX2JfcyRsMmZjc3ZhID49IDAuNzUgJiBsZmNwX2JfcyRsMmZjYmF0Y2gsICIiLCAiIikKbnVtX2JvdGhpbnNpZyA8LSBzdW0obGZjX2JfcyRzdGF0ZSA9PSAiYm90aGluc2lnIikKbnVtX2JvdGhzaWcgPC0gc3VtKGxmY19iX3Mkc3RhdGUgPT0gImJvdGhzaWciKQpudW1fc3Zhc2lnIDwtIHN1bShsZmNfYl9zJHN0YXRlID09ICJzdmFzaWciKQpudW1fYmF0Y2hzaWcgPC0gc3VtKGxmY19iX3Mkc3RhdGUgPT0gImJhdGNoc2lnIikKCmxpYnJhcnkoZ2dwbG90MikKYWVzX2NvbG9yID0gIihsMmZjc3ZhID49IDAuNzUgfCBsMmZjc3ZhIDw9IC0wLjc1IHwgbDJmY2JhdGNoID49IDAuNzUgfCBsMmZjYmF0Y2ggPD0gLTAuNzUpIgoKcGx0IDwtIGdncGxvdDI6OmdncGxvdChsZmNfYl9zLCBhZXNfc3RyaW5nKHg9ImwyZmNzdmEiLCB5PSJsMmZjYmF0Y2giKSkgKwogICAgIyMgZ2dwbG90Mjo6Z2VvbV9wb2ludChzdGF0PSJpZGVudGl0eSIsIHNpemU9MiwgYWxwaGE9MC4yLCBhZXNfc3RyaW5nKHNoYXBlPSJhcy5mYWN0b3IoYWVzX2NvbG9yKSIsIGNvbG91cj0iYXMuZmFjdG9yKHN0YXRlKSIsIGZpbGw9ImFzLmZhY3RvcihzdGF0ZSkiKSkgKwogICAgZ2dwbG90Mjo6Z2VvbV9hYmxpbmUoY29sb3VyPSJibHVlIiwgc2xvcGU9MSwgaW50ZXJjZXB0PTAsIHNpemU9MC41KSArCiAgICBnZ3Bsb3QyOjpnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9YygtMC43NSwgMC43NSksIGNvbG9yPSJyZWQiLCBzaXplPTAuNSkgKwogICAgZ2dwbG90Mjo6Z2VvbV92bGluZSh4aW50ZXJjZXB0PWMoLTAuNzUsIDAuNzUpLCBjb2xvcj0icmVkIiwgc2l6ZT0wLjUpICsKICAgIGdncGxvdDI6Omdlb21fcG9pbnQoc3RhdD0iaWRlbnRpdHkiLCBzaXplPTIsIGFscGhhPTAuMiwgYWVzX3N0cmluZyhjb2xvdXI9ImFzLmZhY3RvcihzdGF0ZSkiLCBmaWxsPSJhcy5mYWN0b3Ioc3RhdGUpIikpICsKICAgIGdncGxvdDI6OnNjYWxlX2NvbG9yX21hbnVhbChuYW1lPSJzdGF0ZSIsIHZhbHVlcz1jKCJib3RoaW5zaWciPSJncmV5IiwgImJvdGhzaWciPSJmb3Jlc3RncmVlbiIsICJzdmFzaWciPSJkYXJrcmVkIiwgImJhdGNoc2lnIj0iZGFya2JsdWUiKSkgKwogICAgZ2dwbG90Mjo6c2NhbGVfZmlsbF9tYW51YWwobmFtZT0ic3RhdGUiLCB2YWx1ZXM9YygiYm90aGluc2lnIj0iZ3JleSIsICJib3Roc2lnIj0iZm9yZXN0Z3JlZW4iLCAic3Zhc2lnIj0iZGFya3JlZCIsICJiYXRjaHNpZyI9ImRhcmtibHVlIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAoIkJvdGggSW5TaWcuOiAiLCBudW1fYm90aGluc2lnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAoIkJvdGggU2lnLjogIiwgbnVtX2JvdGhzaWcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlMCgiU3ZhIFNpZy46ICIsIG51bV9zdmFzaWcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlMCgiQmF0Y2ggU2lnLjogIiwgbnVtX2JhdGNoc2lnKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZT1nZ3Bsb3QyOjpndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzPWFlcyhzaXplPTMsIGZpbGw9ImdyZXkiKSkpICsKICAgIGdncGxvdDI6Omd1aWRlcyhmaWxsPWdncGxvdDI6Omd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXM9bGlzdChzaXplPTMpKSkgKwogICAgZ2dwbG90Mjo6dGhlbWVfYncoKQpwbHQKYGBgCgojIyBDb21wYXJlIHJ1dnJlc2lkIHRvIGJhdGNoIGluIG1vZGVsLCBERVNlcQoKYGBge3IgYmF0Y2hfcnV2cmVzaWRfZGVzZXExfQpoc19tYWNyX2JhdGNoX3J1dnJlc2lkX2Rlc2VxIDwtIG1lcmdlKAogIGhzX21hY3JfcnV2cmVzJGRlc2VxJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGhzX21hY3JfYmF0Y2gkYmFzaWMkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgYnk9InJvdy5uYW1lcyIpCnJvd25hbWVzKGhzX21hY3JfYmF0Y2hfcnV2cmVzaWRfZGVzZXEpIDwtIGhzX21hY3JfYmF0Y2hfcnV2cmVzaWRfZGVzZXFbWyJSb3cubmFtZXMiXV0KaHNfbWFjcl9iYXRjaF9ydXZyZXNpZF9sb2dmYyA8LSBoc19tYWNyX2JhdGNoX3J1dnJlc2lkX2Rlc2VxWywgYygibG9nRkMueCIsImxvZ0ZDLnkiKV0KY29sbmFtZXMoaHNfbWFjcl9iYXRjaF9ydXZyZXNpZF9sb2dmYykgPC0gYygibm9iYXRjaCIsImJhc2ljIikKbGZjX3J1dl9iYXQgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihoc19tYWNyX2JhdGNoX3J1dnJlc2lkX2xvZ2ZjLCBwcmV0dHlfY29sb3JzPUZBTFNFKQpsZmNfcnV2X2JhdCRzY2F0dGVyCmxmY19ydXZfYmF0JGNvcnJlbGF0aW9uCmBgYAoKIyMgQ29tcGFyZSBwY2EgdG8gYmF0Y2ggaW4gbW9kZWwsIERFU2VxCgpgYGB7ciBiYXRjaF9wY2FfZGVzZXExfQpoc19tYWNyX2JhdGNoX3BjYV9kZXNlcSA8LSBtZXJnZSgKICBoc19tYWNyX3BjYSRkZXNlcSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBoc19tYWNyX2JhdGNoJGJhc2ljJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhoc19tYWNyX2JhdGNoX3BjYV9kZXNlcSkgPC0gaHNfbWFjcl9iYXRjaF9wY2FfZGVzZXFbWyJSb3cubmFtZXMiXV0KaHNfbWFjcl9iYXRjaF9wY2FfbG9nZmMgPC0gaHNfbWFjcl9iYXRjaF9wY2FfZGVzZXFbLCBjKCJsb2dGQy54IiwgImxvZ0ZDLnkiKV0KY29sbmFtZXMoaHNfbWFjcl9iYXRjaF9wY2FfbG9nZmMpIDwtIGMoIm5vYmF0Y2giLCJiYXNpYyIpCmxmY19wY2FfYmF0IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoaHNfbWFjcl9iYXRjaF9wY2FfbG9nZmMsIHByZXR0eV9jb2xvcnM9RkFMU0UpCmxmY19wY2FfYmF0JHNjYXR0ZXIKbGZjX3BjYV9iYXQkY29ycmVsYXRpb24KYGBgCgojIyBDb21wYXJlIHJ1diBlbXBpcmljYWwgdG8gYmF0Y2ggaW4gbW9kZWwsIERFU2VxCgpgYGB7ciBiYXRjaF9ydXZlbXBfZGVzZXExfQpoc19tYWNyX2JhdGNoX3J1dmVtcF9kZXNlcSA8LSBtZXJnZSgKICBoc19tYWNyX3J1dmVtcCRkZXNlcSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBoc19tYWNyX2JhdGNoJGJhc2ljJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhoc19tYWNyX2JhdGNoX3J1dmVtcF9kZXNlcSkgPC0gaHNfbWFjcl9iYXRjaF9ydXZlbXBfZGVzZXFbWyJSb3cubmFtZXMiXV0KaHNfbWFjcl9iYXRjaF9ydXZlbXBfbG9nZmMgPC0gaHNfbWFjcl9iYXRjaF9ydXZlbXBfZGVzZXFbLCBjKCJsb2dGQy54IiwibG9nRkMueSIpXQpjb2xuYW1lcyhoc19tYWNyX2JhdGNoX3J1dmVtcF9sb2dmYykgPC0gYygibm9iYXRjaCIsImJhc2ljIikKbGZjX3J1dmVtcF9iYXQgPC0gc20ocGxvdF9saW5lYXJfc2NhdHRlcihoc19tYWNyX2JhdGNoX3J1dmVtcF9sb2dmYywgcHJldHR5X2NvbG9ycz1GQUxTRSkpCmxmY19ydXZlbXBfYmF0JHNjYXR0ZXIKbGZjX3J1dmVtcF9iYXQkY29ycmVsYXRpb24KYGBgCgojIyBDb21wYXJlIGNvbWJhdCB0byBiYXRjaCBpbiBtb2RlbCwgREVTZXEKCmBgYHtyIGNvbXBhcmVfYmF0Y2hfY29tYmF0MX0KaHNfbWFjcl9jb21iYXRfYmF0Y2ggPC0gbWVyZ2UoCiAgaHNfbWFjcl9jb21iYXQkZGVzZXEkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgaHNfbWFjcl9iYXRjaCRkZXNlcSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBieT0icm93Lm5hbWVzIikKcm93bmFtZXMoaHNfbWFjcl9jb21iYXRfYmF0Y2gpIDwtIGhzX21hY3JfY29tYmF0X2JhdGNoW1siUm93Lm5hbWVzIl1dCmhzX21hY3JfY29tYmF0X2JhdGNoIDwtIGhzX21hY3JfY29tYmF0X2JhdGNoWywgYygibG9nRkMueCIsImxvZ0ZDLnkiKV0KY29sbmFtZXMoaHNfbWFjcl9jb21iYXRfYmF0Y2gpIDwtIGMoImJhdGNoIiwiY29tYmF0IikKYl9jIDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoaHNfbWFjcl9jb21iYXRfYmF0Y2gsIHByZXR0eV9jb2xvcnM9RkFMU0UpCmJfYyRzY2F0dGVyCmJfYyRjb3JyZWxhdGlvbgpgYGAKCiMjIENvbXBhcmUgbm8gYmF0Y2ggdG8gYmF0Y2ggaW4gbW9kZWwsIGxpbW1hCgpgYGB7ciBjb21wYXJlX2JhdGNoX25vYmF0Y2hfbGltbWExfQpoc19tYWNyX25vYmF0Y2hfYmF0Y2ggPC0gbWVyZ2UoCiAgaHNfbWFjcl9ub2JhdGNoJGxpbW1hJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGhzX21hY3JfYmF0Y2gkbGltbWEkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgYnk9InJvdy5uYW1lcyIpCnJvd25hbWVzKGhzX21hY3Jfbm9iYXRjaF9iYXRjaCkgPC0gaHNfbWFjcl9ub2JhdGNoX2JhdGNoW1siUm93Lm5hbWVzIl1dCmhzX21hY3Jfbm9iYXRjaF9iYXRjaCA8LSBoc19tYWNyX25vYmF0Y2hfYmF0Y2hbLCBjKCJsb2dGQy54IiwibG9nRkMueSIpXQpjb2xuYW1lcyhoc19tYWNyX25vYmF0Y2hfYmF0Y2gpIDwtIGMoIm5vYmF0Y2giLCJiYXRjaCIpCm5iX2IgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihoc19tYWNyX25vYmF0Y2hfYmF0Y2gsIHByZXR0eV9jb2xvcnM9RkFMU0UpCm5iX2Ikc2NhdHRlcgpuYl9iJGNvcnJlbGF0aW9uCmBgYAoKIyMgQmF0Y2ggaW4gbW9kZWwgdnMuIFNWQSwgbGltbWEKCmBgYHtyIGNvbXBhcmVfYmF0Y2hfc3ZhX2xpbW1hMX0KaHNfbWFjcl9iYXRjaF9zdmEgPC0gbWVyZ2UoCiAgaHNfbWFjcl9iYXRjaCRsaW1tYSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBoc19tYWNyX3N2YSRsaW1tYSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBieT0icm93Lm5hbWVzIikKcm93bmFtZXMoaHNfbWFjcl9iYXRjaF9zdmEpIDwtIGhzX21hY3JfYmF0Y2hfc3ZhW1siUm93Lm5hbWVzIl1dCmhzX21hY3JfYmF0Y2hfc3ZhIDwtIGhzX21hY3JfYmF0Y2hfc3ZhWywgYygibG9nRkMueCIsImxvZ0ZDLnkiKV0KY29sbmFtZXMoaHNfbWFjcl9iYXRjaF9zdmEpIDwtIGMoImJhdGNoIiwic3ZhIikKYl9zIDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoaHNfbWFjcl9iYXRjaF9zdmEsIHByZXR0eV9jb2xvcnM9RkFMU0UpCmJfcyRzY2F0dGVyCmJfcyRjb3JyZWxhdGlvbgpgYGAKCiMjIEJhdGNoIGluIG1vZGVsIHZzLiBjb21iYXQsIGxpbW1hCgpgYGB7ciBjb21wYXJlX2JhdGNoX2NvbWJhdF9saW1tYTF9CmhzX21hY3JfYmF0Y2hfY29tYmF0IDwtIG1lcmdlKAogIGhzX21hY3JfYmF0Y2gkbGltbWEkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgaHNfbWFjcl9jb21iYXQkbGltbWEkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgYnk9InJvdy5uYW1lcyIpCnJvd25hbWVzKGhzX21hY3JfYmF0Y2hfY29tYmF0KSA8LSBoc19tYWNyX2JhdGNoX2NvbWJhdFtbIlJvdy5uYW1lcyJdXQpoc19tYWNyX2JhdGNoX2NvbWJhdCA8LSBoc19tYWNyX2JhdGNoX2NvbWJhdFssIGMoImxvZ0ZDLngiLCJsb2dGQy55IildCmNvbG5hbWVzKGhzX21hY3JfYmF0Y2hfY29tYmF0KSA8LSBjKCJiYXRjaCIsImNvbWJhdCIpCmJfYyA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGhzX21hY3JfYmF0Y2hfY29tYmF0LCBwcmV0dHlfY29sb3JzPUZBTFNFKQpiX2Mkc2NhdHRlcgpiX2MkY29ycmVsYXRpb24KYGBgCgojIyBOb2JhdGNoIHZzLiBiYXRjaCBpbiBtb2RlbCwgZWRnZXIKCmBgYHtyIGNvbXBhcmVfbm9iYXRjaF9iYXRjaF9lZGdlcjF9CmhzX21hY3Jfbm9iYXRjaF9iYXRjaCA8LSBtZXJnZSgKICBoc19tYWNyX25vYmF0Y2gkZWRnZXIkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgaHNfbWFjcl9iYXRjaCRlZGdlciRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBieT0icm93Lm5hbWVzIikKcm93bmFtZXMoaHNfbWFjcl9ub2JhdGNoX2JhdGNoKSA8LSBoc19tYWNyX25vYmF0Y2hfYmF0Y2hbWyJSb3cubmFtZXMiXV0KaHNfbWFjcl9ub2JhdGNoX2JhdGNoIDwtIGhzX21hY3Jfbm9iYXRjaF9iYXRjaFssIGMoImxvZ0ZDLngiLCJsb2dGQy55IildCmNvbG5hbWVzKGhzX21hY3Jfbm9iYXRjaF9iYXRjaCkgPC0gYygibm9iYXRjaCIsImJhdGNoIikKbmJfYiA8LSBzbShwbG90X2xpbmVhcl9zY2F0dGVyKGhzX21hY3Jfbm9iYXRjaF9iYXRjaCwgcHJldHR5X2NvbG9ycz1GQUxTRSkpCm5iX2Ikc2NhdHRlcgpuYl9iJGNvcnJlbGF0aW9uCmBgYAoKIyMgQmF0Y2ggaW4gbW9kZWwgdnMuIFNWQSwgZWRnZXIKCmBgYHtyIGNvbXBhcmVfYmF0Y2hfc3ZhX2VkZ2VyMX0KaHNfbWFjcl9iYXRjaF9zdmEgPC0gbWVyZ2UoCiAgaHNfbWFjcl9iYXRjaCRlZGdlciRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBoc19tYWNyX3N2YSRlZGdlciRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBieT0icm93Lm5hbWVzIikKcm93bmFtZXMoaHNfbWFjcl9iYXRjaF9zdmEpIDwtIGhzX21hY3JfYmF0Y2hfc3ZhW1siUm93Lm5hbWVzIl1dCmhzX21hY3JfYmF0Y2hfc3ZhIDwtIGhzX21hY3JfYmF0Y2hfc3ZhWywgYygibG9nRkMueCIsImxvZ0ZDLnkiKV0KY29sbmFtZXMoaHNfbWFjcl9iYXRjaF9zdmEpIDwtIGMoImJhdGNoIiwic3ZhIikKYl9zIDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoaHNfbWFjcl9iYXRjaF9zdmEsIHByZXR0eV9jb2xvcnM9RkFMU0UpCmJfcyRzY2F0dGVyCmJfcyRjb3JyZWxhdGlvbgpgYGAKCiMjIEJhdGNoIGluIG1vZGVsIHZzLiBjb21iYXQsIGVkZ2VyCgpgYGB7ciBjb21wYXJlX2JhdGNoX2NvbWJhdF9lZGdlcjF9CmhzX21hY3JfYmF0Y2hfY29tYmF0IDwtIG1lcmdlKAogIGhzX21hY3JfYmF0Y2gkZWRnZXIkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgaHNfbWFjcl9jb21iYXQkZWRnZXIkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgYnk9InJvdy5uYW1lcyIpCnJvd25hbWVzKGhzX21hY3JfYmF0Y2hfY29tYmF0KSA8LSBoc19tYWNyX2JhdGNoX2NvbWJhdFtbIlJvdy5uYW1lcyJdXQpoc19tYWNyX2JhdGNoX2NvbWJhdCA8LSBoc19tYWNyX2JhdGNoX2NvbWJhdFssIGMoImxvZ0ZDLngiLCJsb2dGQy55IildCmNvbG5hbWVzKGhzX21hY3JfYmF0Y2hfY29tYmF0KSA8LSBjKCJiYXRjaCIsImNvbWJhdCIpCmJfYyA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGhzX21hY3JfYmF0Y2hfY29tYmF0LCBwcmV0dHlfY29sb3JzPUZBTFNFKQpiX2Mkc2NhdHRlcgpiX2MkY29ycmVsYXRpb24KYGBgCgojIyBDb21wYXJlIG5vYmF0Y2ggdnMuIGJhdGNoLCBkZXNlcQoKYGBge3IgY29tcGFyZV9ub2JhdGNoX2JhdGNoX2Rlc2VxMX0KaHNfbWFjcl9ub2JhdGNoX2JhdGNoIDwtIG1lcmdlKAogIGhzX21hY3Jfbm9iYXRjaCRkZXNlcSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBoc19tYWNyX2JhdGNoJGRlc2VxJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhoc19tYWNyX25vYmF0Y2hfYmF0Y2gpIDwtIGhzX21hY3Jfbm9iYXRjaF9iYXRjaFtbIlJvdy5uYW1lcyJdXQpoc19tYWNyX25vYmF0Y2hfYmF0Y2ggPC0gaHNfbWFjcl9ub2JhdGNoX2JhdGNoWywgYygibG9nRkMueCIsImxvZ0ZDLnkiKV0KY29sbmFtZXMoaHNfbWFjcl9ub2JhdGNoX2JhdGNoKSA8LSBjKCJub2JhdGNoIiwiYmF0Y2giKQpuYl9iIDwtIHNtKHBsb3RfbGluZWFyX3NjYXR0ZXIoaHNfbWFjcl9ub2JhdGNoX2JhdGNoLCBwcmV0dHlfY29sb3JzPUZBTFNFKSkKbmJfYiRzY2F0dGVyCm5iX2IkY29ycmVsYXRpb24KYGBgCgojIyBDb21wYXJlIGJhdGNoIHZzLiBTVkEsIGRlc2VxCgpgYGB7ciBjb21wYXJlX2JhdGNoX3N2YV9kZXNlcTF9CmhzX21hY3JfYmF0Y2hfc3ZhIDwtIG1lcmdlKAogIGhzX21hY3JfYmF0Y2gkZGVzZXEkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgaHNfbWFjcl9zdmEkZGVzZXEkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgYnk9InJvdy5uYW1lcyIpCnJvd25hbWVzKGhzX21hY3JfYmF0Y2hfc3ZhKSA8LSBoc19tYWNyX2JhdGNoX3N2YVtbIlJvdy5uYW1lcyJdXQpoc19tYWNyX2JhdGNoX3N2YSA8LSBoc19tYWNyX2JhdGNoX3N2YVssIGMoImxvZ0ZDLngiLCAibG9nRkMueSIpXQpjb2xuYW1lcyhoc19tYWNyX2JhdGNoX3N2YSkgPC0gYygiYmF0Y2giLCAic3ZhIikKYl9zIDwtIHNtKHBsb3RfbGluZWFyX3NjYXR0ZXIoaHNfbWFjcl9iYXRjaF9zdmEsIHByZXR0eV9jb2xvcnM9RkFMU0UpKQpiX3Mkc2NhdHRlcgpiX3MkY29ycmVsYXRpb24KYGBgCgojIyBCYXRjaCBpbiBtb2RlbCB2cy4gY29tYmF0LCBkZXNlcQoKYGBge3IgYmF0Y2hfY29tYmF0X2Rlc2VxMX0KaHNfbWFjcl9iYXRjaF9jb21iYXQgPC0gbWVyZ2UoCiAgaHNfbWFjcl9iYXRjaCRkZXNlcSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBoc19tYWNyX2NvbWJhdCRkZXNlcSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBieT0icm93Lm5hbWVzIikKcm93bmFtZXMoaHNfbWFjcl9iYXRjaF9jb21iYXQpIDwtIGhzX21hY3JfYmF0Y2hfY29tYmF0W1siUm93Lm5hbWVzIl1dCmhzX21hY3JfYmF0Y2hfY29tYmF0IDwtIGhzX21hY3JfYmF0Y2hfY29tYmF0WywgYygibG9nRkMueCIsICJsb2dGQy55IildCmNvbG5hbWVzKGhzX21hY3JfYmF0Y2hfY29tYmF0KSA8LSBjKCJiYXRjaCIsICJjb21iYXQiKQpiX2MgPC0gc20ocGxvdF9saW5lYXJfc2NhdHRlcihoc19tYWNyX2JhdGNoX2NvbWJhdCwgcHJldHR5X2NvbG9ycz1GQUxTRSkpCmJfYyRzY2F0dGVyCmJfYyRjb3JyZWxhdGlvbgpgYGAKCiMgUmVwZWF0IHVzaW5nIHRoZSBwYXJhc2l0ZSBkYXRhCgpJbiAnbWFjcm9waGFnZV9lc3RpbWF0aW9uJywgd2UgZGlkIGEgc2VyaWVzIG9mIGFuYWx5c2VzIHRvIHRyeSB0byBwaWNrIG91dCBzb21lIG9mIHRoZSBzdXJyb2dhdGUKdmFyaWFibGVzIGluIHRoZSBkYXRhLiAgTm93IHdlIHdpbGwgcGVyZm9ybSBhIHNldCBvZiBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNlcyB1c2luZyB0aGUKcmVzdWx0cyBmcm9tIHRoYXQuICBTaW5jZSB0aGUgJ2JhdGNoJyBlbGVtZW50IG9mIHRoZSBkYXRhIGlzIHJlYXNvbmFibHkgd2VsbCBleHBsYWluZWQsIHdlIHdpbGwgbm90CmFidXNlIHRoZSBkYXRhIHdpdGggc3ZhL2NvbWJhdCwgYnV0IGluc3RlYWQgaW5jbHVkZSBiYXRjaCBpbiB0aGUgZXhwZXJpbWVudGFsIG1vZGVsLgoKSXQgYXBwZWFycyB0aGF0IGl0IGlzIHBvc3NpYmxlIHRob3VnaCBzb21ld2hhdCBkaWZmaWN1bHQgdG8gYXBwbHkgYmF0Y2ggZXN0aW1hdGlvbnMgZ2VuZXJhdGVkIGJ5IHN2YQp0byB0aGUgbW9kZWwgZ2l2ZW4gdG8gREVTZXEvRWRnZVIvbGltbWEuICBJbiB0aGUgY2FzZSBvZiBsaW1tYSBpdCBpcyBmYWlybHkgc2ltcGxlLCBidXQgaW4gdGhlIG90aGVyCnR3byBpdCBpcyBhIGJpdCBtb3JlIGRpZmZpY3VsdC4gIFRoZXJlIGlzIGEgbmljZSBkaXNjdXNzaW9uIG9mIHRoaXMgYXQ6IGh0dHBzOi8vd3d3LmJpb3N0YXJzLm9yZy9wLzE1NjE4Ni8KSSBhbSBhdHRlbXB0aW5nIHRvIGFwcGx5IHRoYXQgbG9naWMgdG8gdGhpcyBkYXRhIHdpdGggbGltaXRlZCBzdWNjZXNzLgoKYGBge3Igc2V0dXBfZGUsIGZpZy5zaG93PSJoaWRlIn0KbHBfY29udHJhc3RzIDwtIGxpc3QoCiAgICAibWFjcm9fY2hyLXNoIiA9IGMoImNociIsICJzaCIpKQpscF9tYWNyX25vcm0gPC0gc20obm9ybWFsaXplX2V4cHQobHBfbWFjciwgZmlsdGVyPVRSVUUsIGNvbnZlcnQ9ImNwbSIsIG5vcm09InF1YW50IikpCmxwX21hY3JfY29tYmF0X25vcm0gPC0gc20obm9ybWFsaXplX2V4cHQobHBfbWFjciwgZmlsdGVyPVRSVUUsIG5vcm09InF1YW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb3dfdG9femVybz1UUlVFLCBiYXRjaD0iY29tYmF0IikpCmxwX21hY3JfbG93ZmlsdCA8LSBzbShub3JtYWxpemVfZXhwdChscF9tYWNyLCBmaWx0ZXI9VFJVRSkpCiMjIFNldCB1cCB0aGUgZGF0YSB1c2VkIGluIHRoZSAzIGNvbXBhcmF0aXZlIGNvbnRyYXN0IHNldHMuCmBgYAoKIyMgTm8gYmF0Y2ggaW4gdGhlIG1vZGVsCgpgYGB7ciBtYWNyb19ub2JhdGNoLCBmaWcuc2hvdz0iaGlkZSJ9CmxwX21hY3Jfbm9iYXRjaCA8LSBzbShhbGxfcGFpcndpc2UobHBfbWFjcl9sb3dmaWx0LCBsaW1tYV9tZXRob2Q9InJvYnVzdCIsIG1vZGVsX2JhdGNoPUZBTFNFKSkKIyMgd293LCBhbGwgdG9vbHMgaW5jbHVkaW5nIGJhc2ljIGFncmVlIGFsbW9zdCBjb21wbGV0ZWx5Cm1lZGlhbnNfYnlfY29uZGl0aW9uIDwtIGxwX21hY3Jfbm9iYXRjaCRiYXNpYyRtZWRpYW5zCmxwX21hY3Jfbm9iYXRjaF90YWJsZXMgPC0gc20oY29tYmluZV9kZV90YWJsZXMoCiAgbHBfbWFjcl9ub2JhdGNoLAogIGV4Y2VsPXBhc3RlMCgiZXhjZWwvbHBfbWFjcl9ub2JhdGNoLXYiLCB2ZXIsICIueGxzeCIpLAogIHNpZ19leGNlbD1wYXN0ZTAoImV4Y2VsL2xwX21hY3Jfbm9iYXRjaF9zaWduaWZpY2FudC12IiwgdmVyLCAiLnhsc3giKSwKICBrZWVwZXJzPWxwX2NvbnRyYXN0cywKICBleHRyYV9hbm5vdD1tZWRpYW5zX2J5X2NvbmRpdGlvbikpCmBgYAoKIyMgQmF0Y2ggaW4gdGhlIG1vZGVsCgpJbiB0aGlzICBhdHRlbXB0LCB3ZSBhZGQgYSBiYXRjaCBmYWN0b3IgaW4gdGhlIGV4cGVyaW1lbnRhbCBtb2RlbCBhbmQgc2VlIGhvdyBpdCBkb2VzLgoKYGBge3IgbWFjcm9fYmF0Y2gsIGZpZy5zaG93PSJoaWRlIn0KIyMgSGVyZSBqdXN0IGxldCBhbGxfcGFpcndpc2UgcnVuIG9uIGZpbHRlcmVkIGRhdGEgYW5kIGRvIGl0cyBub3JtYWwgfiAwICsgY29uZGl0aW9uICsgYmF0Y2ggYW5hbHlzZXMKbHBfbWFjcl9iYXRjaCA8LSBzbShhbGxfcGFpcndpc2UobHBfbWFjcl9sb3dmaWx0LCBsaW1tYV9tZXRob2Q9InJvYnVzdCIpKQptZWRpYW5zX2J5X2NvbmRpdGlvbiA8LSBscF9tYWNyX2JhdGNoJGJhc2ljJG1lZGlhbnMKbHBfbWFjcl9iYXRjaF90YWJsZXMgPC0gc20oY29tYmluZV9kZV90YWJsZXMoCiAgbHBfbWFjcl9iYXRjaCwKICBleGNlbD1wYXN0ZTAoImV4Y2VsL2xwX21hY3JfYmF0Y2htb2RlbC12IiwgdmVyLCAiLnhsc3giKSwKICBzaWdfZXhjZWw9cGFzdGUwKCJleGNlbC9scF9tYWNyX2JhdGNobW9kZWxfc2lnbmlmaWNhbnQtdiIsIHZlciwgIi54bHN4IiksCiAga2VlcGVycz1scF9jb250cmFzdHMsCiAgZXh0cmFfYW5ub3Q9bWVkaWFuc19ieV9jb25kaXRpb24pKQpgYGAKCiMjIEJhdGNoIGVzdGltYXRlZCB3aXRoIFNWQQoKYGBge3IgbWFjcm9fc3ZhLCBmaWcuc2hvdz0iaGlkZSJ9CiMjIEhlcmUganVzdCBsZXQgYWxsX3BhaXJ3aXNlIHJ1biBvbiBmaWx0ZXJlZCBkYXRhIGFuZCBkbyBpdHMgbm9ybWFsIH4gMCArIGNvbmRpdGlvbiArIGJhdGNoIGFuYWx5c2VzCmxwX21hY3Jfc3ZhIDwtIHNtKGFsbF9wYWlyd2lzZShscF9tYWNyX2xvd2ZpbHQsIGxpbW1hX21ldGhvZD0icm9idXN0IiwgbW9kZWxfYmF0Y2g9InN2YSIpKQptZWRpYW5zX2J5X2NvbmRpdGlvbiA8LSBscF9tYWNyX3N2YSRiYXNpYyRtZWRpYW5zCmxwX21hY3Jfc3ZhX3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICBscF9tYWNyX3N2YSwKICBleGNlbD1wYXN0ZTAoImV4Y2VsL2xwX21hY3Jfc3ZhLXYiLCB2ZXIsICIueGxzeCIpLAogIHNpZ19leGNlbD1wYXN0ZTAoImV4Y2VsL2xwX21hY3Jfc3ZhX3NpZ25pZmljYW50LXYiLCB2ZXIsICIueGxzeCIpLAogIGtlZXBlcnM9bHBfY29udHJhc3RzLAogIGV4dHJhX2Fubm90PW1lZGlhbnNfYnlfY29uZGl0aW9uKSkKYGBgCgojIyBCYXRjaCBjb3JyZWN0aW9uIHZpYSBydXYgcmVzaWR1YWxzCgpgYGB7ciBtYWNyb19ydXZyZXNpZCwgZmlnLnNob3c9ImhpZGUifQojIyBIZXJlIGp1c3QgbGV0IGFsbF9wYWlyd2lzZSBydW4gb24gZmlsdGVyZWQgZGF0YSBhbmQgZG8gaXRzIG5vcm1hbCB+IDAgKyBjb25kaXRpb24gKyBiYXRjaCBhbmFseXNlcwojIyBCaXphcnJlbHksIHNvbWV0aW1lcyBpZiBvbmUgcnVucyB0aGlzLCBpdCBnaXZlcyBhbiBlcnJvciAiRXJyb3IgaW4gKGZ1bmN0aW9uCiMjIChjbGFzc2VzLCBmZGVmLCBtdGFibGUpIDogdW5hYmxlIHRvIGZpbmQgYW4gaW5oZXJpdGVkIG1ldGhvZCBmb3IgZnVuY3Rpb24KIyMgJ1JVVnInIGZvciBzaWduYXR1cmUgJyJtYXRyaXgiLCAibG9naWNhbCIsICJudW1lcmljIiwgIk5VTEwiJyIgIC0tIGhvd2V2ZXIsCiMjIGlmIG9uZSB0aGVuIHNpbXBseSBydW5zIGl0IGFnYWluIGl0IHdvcmtzIGZpbmUuCiMjIEkgY2hhbmdlZCBtb2RlbF9zdXJyb2dhdGVzLlIgdG8gdGFrZSBjYXJlIG9mIHRoaXMgSSB0aGluay4KbHBfbWFjcl9ydXZyZXMgPC0gc20oYWxsX3BhaXJ3aXNlKGxwX21hY3JfbG93ZmlsdCwgbW9kZWxfYmF0Y2g9InJ1dl9yZXNpZHVhbHMiLCBsaW1tYV9tZXRob2Q9InJvYnVzdCIpKQptZWRpYW5zX2J5X2NvbmRpdGlvbiA8LSBscF9tYWNyX3J1dnJlcyRiYXNpYyRtZWRpYW5zCmxwX21hY3JfcnV2cmVzX3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICBscF9tYWNyX3J1dnJlcywKICBleGNlbD1wYXN0ZTAoImV4Y2VsL2xwX21hY3JfcnV2cmVzLXYiLCB2ZXIsICIueGxzeCIpLAogIHNpZ19leGNlbD1wYXN0ZTAoImV4Y2VsL2xwX21hY3JfcnV2cmVzX3NpZ25pZmljYW50LXYiLCB2ZXIsICIueGxzeCIpLAogIGtlZXBlcnM9bHBfY29udHJhc3RzLAogIGV4dHJhX2Fubm90PW1lZGlhbnNfYnlfY29uZGl0aW9uKSkKYGBgCgojIyBCYXRjaCBjb3JyZWN0aW9uIHdpdGggcGNhCgpgYGB7ciBtYWNyb19wY2EsIGZpZy5zaG93PSJoaWRlIn0KIyMgSGVyZSBqdXN0IGxldCBhbGxfcGFpcndpc2UgcnVuIG9uIGZpbHRlcmVkIGRhdGEgYW5kIGRvIGl0cyBub3JtYWwgfiAwICsgY29uZGl0aW9uICsgYmF0Y2ggYW5hbHlzZXMKbHBfbWFjcl9wY2EgPC0gc20oYWxsX3BhaXJ3aXNlKGxwX21hY3JfbG93ZmlsdCwgbW9kZWxfYmF0Y2g9InBjYSIsIGxpbW1hX21ldGhvZD0icm9idXN0IikpCm1lZGlhbnNfYnlfY29uZGl0aW9uIDwtIGxwX21hY3JfcGNhJGJhc2ljJG1lZGlhbnMKbHBfbWFjcl9wY2FfdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKAogIGxwX21hY3JfcGNhLAogIGV4Y2VsPXBhc3RlMCgiZXhjZWwvbHBfbWFjcl9wY2EtdiIsIHZlciwgIi54bHN4IiksCiAgc2lnX2V4Y2VsPXBhc3RlMCgiZXhjZWwvbHBfbWFjcl9wY2Ffc2lnbmlmaWNhbnQtdiIsIHZlciwgIi54bHN4IiksCiAga2VlcGVycz1scF9jb250cmFzdHMsCiAgZXh0cmFfYW5ub3Q9bWVkaWFuc19ieV9jb25kaXRpb24pKQpgYGAKCiMjIEJhdGNoIGNvcnJlY3Rpb24gd2l0aCBydXYgZW1waXJpY2FsCgpgYGB7ciBtYWNyb19ydXZlbXAsIGZpZy5zaG93PSJoaWRlIn0KIyMgSGVyZSBqdXN0IGxldCBhbGxfcGFpcndpc2UgcnVuIG9uIGZpbHRlcmVkIGRhdGEgYW5kIGRvIGl0cyBub3JtYWwgfiAwICsgY29uZGl0aW9uICsgYmF0Y2ggYW5hbHlzZXMKbHBfbWFjcl9ydXZlbXAgPC0gc20oYWxsX3BhaXJ3aXNlKGxwX21hY3JfbG93ZmlsdCwgbW9kZWxfYmF0Y2g9InJ1dl9lbXBpcmljYWwiLCBsaW1tYV9tZXRob2Q9InJvYnVzdCIpKQptZWRpYW5zX2J5X2NvbmRpdGlvbiA8LSBscF9tYWNyX3J1dmVtcCRiYXNpYyRtZWRpYW5zCmxwX21hY3JfcnV2ZW1wX3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICBscF9tYWNyX3J1dmVtcCwKICBleGNlbD1wYXN0ZTAoImV4Y2VsL2xwX21hY3JfcnV2ZW1wLXYiLCB2ZXIsICIueGxzeCIpLAogIHNpZ19leGNlbD1wYXN0ZTAoImV4Y2VsL2xwX21hY3JfcnV2ZW1wX3NpZ25pZmljYW50LXYiLCB2ZXIsICIueGxzeCIpLAogIGtlZXBlcnM9bHBfY29udHJhc3RzLAogIGV4dHJhX2Fubm90PW1lZGlhbnNfYnlfY29uZGl0aW9uKSkKYGBgCgojIyBCYXRjaCBjb3JyZWN0aW9uIHdpdGggY29tYmF0CgpUaGVuIHJlcGVhdCB3aXRoIHRoZSBiYXRjaC1jb3JyZWN0ZWQgZGF0YSBhbmQgc2VlIHRoZSBkaWZmZXJlbmNlcy4KCmBgYHtyIHJlcGVhdF9wYWlyd2lzZV9iYXRjaCwgZmlnLnNob3c9ImhpZGUifQpscF9tYWNyX2NvbWJhdCA8LSBhbGxfcGFpcndpc2UobHBfbWFjcl9jb21iYXRfbm9ybSwgZm9yY2U9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbW1hX21ldGhvZD0icm9idXN0IiwgcGFyYWxsZWw9RkFMU0UpCm1lZGlhbnNfYnlfY29uZGl0aW9uIDwtIGxwX21hY3JfY29tYmF0JGJhc2ljJG1lZGlhbnMKbHBfbWFjcl9jb21iYXRfdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKAogIGxwX21hY3JfY29tYmF0LAogIGV4Y2VsPXBhc3RlMCgiZXhjZWwvbHBfbWFjcl9jb21iYXQtdiIsIHZlciwgIi54bHN4IiksCiAgc2lnX2V4Y2VsPXBhc3RlMCgiZXhjZWwvbHBfbWFjcl9jb21iYXRfc2lnbmlmaWNhbnQtdiIsIHZlciwgIi54bHN4IiksCiAga2VlcGVycz1scF9jb250cmFzdHMsCiAgZXh0cmFfYW5ub3Q9bWVkaWFuc19ieV9jb25kaXRpb24pKQpgYGAKCiMgRmlndXJlIG91dCBob3cgdG8gY29tcGFyZSB0aGVzZSByZXN1bHRzCgpJIGhhdmUgNCBtZXRob2RzIG9mIHBlcmZvcm1pbmcgdGhpcyBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcy4gIEVhY2ggb25lIGNvbWVzIHdpdGggYSBzZXQgb2YKbWV0cmljcyBkZWZpbmluZyAnc2lnbmlmaWNhbnQnLiAgUGVyaGFwcyBJIGNhbiBtYWtlIGEgdGFibGUgb2YgdGhlICMgb2YgZ2VuZXMgZGVmaW5lZCBhcyBzaWduaWZpY2FudApieSBjb250cmFzdCBmb3IgZWFjaC4gIEluIGFkZGl0aW9uIGl0IG1heSBiZSB3b3J0aCB3aGlsZSB0byBkbyBhIHNjYXR0ZXIgcGxvdHMgb2YgdGhlIGxvZ0ZDcyBiZXR3ZWVuCnRoZXNlIGNvbXBhcmlzb25zIGFuZCBzZWUgaG93IHdlbGwgdGhleSBhZ3JlZT8KCiMgTG9vayBmaXJzdCBhdCB0aGUgZGUgY291bnRzCgpgYGB7ciBjb21wYXJlX2RlX3NldHVwfQpscF9tYWNyX25vYmF0Y2hfdGFibGVzJHNpZ25pZmljYW50JGxpbW1hJGNvdW50cwpscF9tYWNyX2JhdGNoX3RhYmxlcyRzaWduaWZpY2FudCRsaW1tYSRjb3VudHMKbHBfbWFjcl9zdmFfdGFibGVzJHNpZ25pZmljYW50JGxpbW1hJGNvdW50cwpscF9tYWNyX3J1dnJlc190YWJsZXMkc2lnbmlmaWNhbnQkbGltbWEkY291bnRzCmxwX21hY3JfcGNhX3RhYmxlcyRzaWduaWZpY2FudCRsaW1tYSRjb3VudHMKbHBfbWFjcl9ydXZlbXBfdGFibGVzJHNpZ25pZmljYW50JGxpbW1hJGNvdW50cwpscF9tYWNyX2NvbWJhdF90YWJsZXMkc2lnbmlmaWNhbnQkbGltbWEkY291bnRzCmBgYAoKIyMgQ29tcGFyZSBEZVNlcSAvIEJhc2ljIHdpdGhvdXQgYmF0Y2ggaW4gbW9kZWwKCmBgYHtyIGJhc2ljX2Rlc2VxX25vYmF0Y2h9CmxwX21hY3Jfbm9iYXRjaF9iYXNpYyA8LSBtZXJnZSgKICBscF9tYWNyX25vYmF0Y2gkZGVzZXEkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgbHBfbWFjcl9iYXRjaCRiYXNpYyRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBieT0icm93Lm5hbWVzIikKcm93bmFtZXMobHBfbWFjcl9ub2JhdGNoX2Jhc2ljKSA8LSBscF9tYWNyX25vYmF0Y2hfYmFzaWNbWyJSb3cubmFtZXMiXV0KbHBfbWFjcl9ub2JhdGNoX2xvZ2ZjIDwtIGxwX21hY3Jfbm9iYXRjaF9iYXNpY1ssIGMoImxvZ0ZDLngiLCAibG9nRkMueSIpXQpjb2xuYW1lcyhscF9tYWNyX25vYmF0Y2hfbG9nZmMpIDwtIGMoIm5vYmF0Y2giLCJiYXNpYyIpCmxmY19uYl9iIDwtIHNtKHBsb3RfbGluZWFyX3NjYXR0ZXIobHBfbWFjcl9ub2JhdGNoX2xvZ2ZjLCBwcmV0dHlfY29sb3JzPUZBTFNFKSkKbGZjX25iX2Ikc2NhdHRlcgpsZmNfbmJfYiRjb3JyZWxhdGlvbgoKbHBfbWFjcl9ub2JhdGNoX3AgPC0gbHBfbWFjcl9ub2JhdGNoX2Jhc2ljWywgYygiUC5WYWx1ZSIsInAiKV0KbHBfbWFjcl9ub2JhdGNoX3BbWzJdXSA8LSBhcy5udW1lcmljKGxwX21hY3Jfbm9iYXRjaF9wW1syXV0pCmNvbG5hbWVzKGxwX21hY3Jfbm9iYXRjaF9wKSA8LSBjKCJub2JhdGNoIiwiYmFzaWMiKQpscF9tYWNyX25vYmF0Y2hfcCA8LSAtMSAqIGxvZyhscF9tYWNyX25vYmF0Y2hfcCkKcF9uYl9iIDwtIHNtKHBsb3RfbGluZWFyX3NjYXR0ZXIobHBfbWFjcl9ub2JhdGNoX3AsIHByZXR0eV9jb2xvcnM9RkFMU0UpKQpwX25iX2Ikc2NhdHRlcgpwX25iX2IkY29ycmVsYXRpb24KYGBgCgojIyBDb21wYXJlIFNWQSB0byBiYXRjaCBpbiBtb2RlbCwgREVTZXEKCmBgYHtyIGRlc2VxX3N2YV9iYXRjaH0KbHBfbWFjcl9zdmFfYmF0Y2ggPC0gbWVyZ2UoCiAgbHBfbWFjcl9zdmEkZGVzZXEkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgbHBfbWFjcl9iYXRjaCRkZXNlcSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBieT0icm93Lm5hbWVzIikKcm93bmFtZXMobHBfbWFjcl9zdmFfYmF0Y2gpIDwtIGxwX21hY3Jfc3ZhX2JhdGNoW1siUm93Lm5hbWVzIl1dCmxwX21hY3Jfc3ZhX2xvZ2ZjIDwtIGxwX21hY3Jfc3ZhX2JhdGNoWywgYygibG9nRkMueCIsImxvZ0ZDLnkiKV0KY29sbmFtZXMobHBfbWFjcl9zdmFfbG9nZmMpIDwtIGMoInN2YSIsImJhdGNoIikKbGZjX2JfcyA8LSBzbShwbG90X2xpbmVhcl9zY2F0dGVyKGxwX21hY3Jfc3ZhX2xvZ2ZjLCBwcmV0dHlfY29sb3JzPUZBTFNFKSkKbGZjX2JfcyRzY2F0dGVyCmxmY19iX3MkY29ycmVsYXRpb24KCmxwX21hY3Jfc3ZhX3AgPC0gbHBfbWFjcl9zdmFfYmF0Y2hbLCBjKCJQLlZhbHVlLngiLCJQLlZhbHVlLnkiKV0KbHBfbWFjcl9zdmFfcFtbMl1dIDwtIGFzLm51bWVyaWMobHBfbWFjcl9zdmFfcFtbMl1dKQpjb2xuYW1lcyhscF9tYWNyX3N2YV9wKSA8LSBjKCJzdmEiLCJiYXRjaCIpCmxwX21hY3Jfc3ZhX3AgPC0gLTEgKiBsb2cobHBfbWFjcl9zdmFfcCkKcF9iX3MgPC0gc20ocGxvdF9saW5lYXJfc2NhdHRlcihscF9tYWNyX3N2YV9wLCBwcmV0dHlfY29sb3JzPUZBTFNFKSkKcF9iX3Mkc2NhdHRlcgpwX2JfcyRjb3JyZWxhdGlvbgpgYGAKCiMjIyBJbmNsdWRlIHAtdmFsdWUgZXN0aW1hdGlvbnMKClRyeSBwdXR0aW5nIHNvbWUgaW5mb3JtYXRpb24gb2YgdGhlIHAtdmFsdWVzIHdpdGggdGhlIGNvbXBhcmF0aXZlIGxvZzJmYwoKYGBge3IgbDJmc19wdmFsc30KbGZjcF9iX3MgPC0gbHBfbWFjcl9zdmFfYmF0Y2hbLCBjKCJsb2dGQy54IiwgImxvZ0ZDLnkiLCAiUC5WYWx1ZS54IiwgIlAuVmFsdWUueSIpXQpjb2xuYW1lcyhsZmNwX2JfcykgPC0gYygibDJmY3N2YSIsICJsMmZjYmF0Y2giLCAicHN2YSIsICJwYmF0Y2giKQpsZmNfYl9zJHNjYXR0ZXIKY3V0b2ZmIDwtIDAuMQpsZmNwX2JfcyRzdGF0ZSA8LSBpZmVsc2UobGZjcF9iX3MkcHN2YSA+IGN1dG9mZiAmIGxmY3BfYl9zJHBiYXRjaCA+IGN1dG9mZiwgImJvdGhpbnNpZyIsCiAgICAgICAgICAgICAgICAgIGlmZWxzZShsZmNwX2JfcyRwc3ZhIDw9IGN1dG9mZiAmIGxmY3BfYl9zJHBiYXRjaCA8PSBjdXRvZmYsICJib3Roc2lnIiwKICAgICAgICAgICAgICAgICAgaWZlbHNlKGxmY3BfYl9zJHBzdmEgPD0gY3V0b2ZmLCAic3Zhc2lnIiwgImJhdGNoc2lnIikpKQojI2xmY3BfYl9zJGxmY3N0YXRlIDwtIGlmZWxzZShsZmNwX2JfcyRsMmZjc3ZhID49IDAuNzUgJiBsZmNwX2JfcyRsMmZjYmF0Y2gsICIiLCAiIikKbnVtX2JvdGhpbnNpZyA8LSBzdW0obGZjcF9iX3Mkc3RhdGUgPT0gImJvdGhpbnNpZyIpCm51bV9ib3Roc2lnIDwtIHN1bShsZmNwX2JfcyRzdGF0ZSA9PSAiYm90aHNpZyIpCm51bV9zdmFzaWcgPC0gc3VtKGxmY3BfYl9zJHN0YXRlID09ICJzdmFzaWciKQpudW1fYmF0Y2hzaWcgPC0gc3VtKGxmY3BfYl9zJHN0YXRlID09ICJiYXRjaHNpZyIpCgpsaWJyYXJ5KGdncGxvdDIpCmFlc19jb2xvciA9ICIobDJmY3N2YSA+PSAwLjc1IHwgbDJmY3N2YSA8PSAtMC43NSB8IGwyZmNiYXRjaCA+PSAwLjc1IHwgbDJmY2JhdGNoIDw9IC0wLjc1KSIKCnBsdCA8LSBnZ3Bsb3QyOjpnZ3Bsb3QobGZjcF9iX3MsIGFlc19zdHJpbmcoeD0ibDJmY3N2YSIsIHk9ImwyZmNiYXRjaCIpKSArCiAgICAjIyBnZ3Bsb3QyOjpnZW9tX3BvaW50KHN0YXQ9ImlkZW50aXR5Iiwgc2l6ZT0yLCBhbHBoYT0wLjIsIGFlc19zdHJpbmcoc2hhcGU9ImFzLmZhY3RvcihhZXNfY29sb3IpIiwgY29sb3VyPSJhcy5mYWN0b3Ioc3RhdGUpIiwgZmlsbD0iYXMuZmFjdG9yKHN0YXRlKSIpKSArCiAgICBnZ3Bsb3QyOjpnZW9tX2FibGluZShjb2xvdXI9ImJsdWUiLCBzbG9wZT0xLCBpbnRlcmNlcHQ9MCwgc2l6ZT0wLjUpICsKICAgIGdncGxvdDI6Omdlb21faGxpbmUoeWludGVyY2VwdD1jKC0wLjc1LCAwLjc1KSwgY29sb3I9InJlZCIsIHNpemU9MC41KSArCiAgICBnZ3Bsb3QyOjpnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9YygtMC43NSwgMC43NSksIGNvbG9yPSJyZWQiLCBzaXplPTAuNSkgKwogICAgZ2dwbG90Mjo6Z2VvbV9wb2ludChzdGF0PSJpZGVudGl0eSIsIHNpemU9MiwgYWxwaGE9MC4yLCBhZXNfc3RyaW5nKGNvbG91cj0iYXMuZmFjdG9yKHN0YXRlKSIsIGZpbGw9ImFzLmZhY3RvcihzdGF0ZSkiKSkgKwogICAgZ2dwbG90Mjo6c2NhbGVfY29sb3JfbWFudWFsKG5hbWU9InN0YXRlIiwgdmFsdWVzPWMoImJvdGhpbnNpZyI9ImdyZXkiLCAiYm90aHNpZyI9ImZvcmVzdGdyZWVuIiwgInN2YXNpZyI9ImRhcmtyZWQiLCAiYmF0Y2hzaWciPSJkYXJrYmx1ZSIpKSArCiAgICBnZ3Bsb3QyOjpzY2FsZV9maWxsX21hbnVhbChuYW1lPSJzdGF0ZSIsIHZhbHVlcz1jKCJib3RoaW5zaWciPSJncmV5IiwgImJvdGhzaWciPSJmb3Jlc3RncmVlbiIsICJzdmFzaWciPSJkYXJrcmVkIiwgImJhdGNoc2lnIj0iZGFya2JsdWUiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlMCgiQm90aCBJblNpZy46ICIsIG51bV9ib3RoaW5zaWcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlMCgiQm90aCBTaWcuOiAiLCBudW1fYm90aHNpZyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKCJTdmEgU2lnLjogIiwgbnVtX3N2YXNpZyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKCJCYXRjaCBTaWcuOiAiLCBudW1fYmF0Y2hzaWcpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlPWdncGxvdDI6Omd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXM9YWVzKHNpemU9MywgZmlsbD0iZ3JleSIpKSkgKwogICAgZ2dwbG90Mjo6Z3VpZGVzKGZpbGw9Z2dwbG90Mjo6Z3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcz1saXN0KHNpemU9MykpKSArCiAgICBnZ3Bsb3QyOjp0aGVtZV9idygpCnBsdApgYGAKCiMjIENvbXBhcmUgcnV2cmVzaWQgdG8gYmF0Y2ggaW4gbW9kZWwsIERFU2VxCgpgYGB7ciBiYXRjaF9ydXZyZXNpZF9kZXNlcX0KbHBfbWFjcl9iYXRjaF9ydXZyZXNpZF9kZXNlcSA8LSBtZXJnZSgKICBscF9tYWNyX3J1dnJlcyRkZXNlcSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBscF9tYWNyX2JhdGNoJGJhc2ljJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhscF9tYWNyX2JhdGNoX3J1dnJlc2lkX2Rlc2VxKSA8LSBscF9tYWNyX2JhdGNoX3J1dnJlc2lkX2Rlc2VxW1siUm93Lm5hbWVzIl1dCmxwX21hY3JfYmF0Y2hfcnV2cmVzaWRfbG9nZmMgPC0gbHBfbWFjcl9iYXRjaF9ydXZyZXNpZF9kZXNlcVssIGMoImxvZ0ZDLngiLCJsb2dGQy55IildCmNvbG5hbWVzKGxwX21hY3JfYmF0Y2hfcnV2cmVzaWRfbG9nZmMpIDwtIGMoIm5vYmF0Y2giLCJiYXNpYyIpCmxmY19ydXZfYmF0IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIobHBfbWFjcl9iYXRjaF9ydXZyZXNpZF9sb2dmYywgcHJldHR5X2NvbG9ycz1GQUxTRSkKbGZjX3J1dl9iYXQkc2NhdHRlcgpsZmNfcnV2X2JhdCRjb3JyZWxhdGlvbgpgYGAKCiMjIENvbXBhcmUgcGNhIHRvIGJhdGNoIGluIG1vZGVsLCBERVNlcQoKYGBge3IgYmF0Y2hfcGNhX2Rlc2VxfQpscF9tYWNyX2JhdGNoX3BjYV9kZXNlcSA8LSBtZXJnZSgKICBscF9tYWNyX3BjYSRkZXNlcSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBscF9tYWNyX2JhdGNoJGJhc2ljJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhscF9tYWNyX2JhdGNoX3BjYV9kZXNlcSkgPC0gbHBfbWFjcl9iYXRjaF9wY2FfZGVzZXFbWyJSb3cubmFtZXMiXV0KbHBfbWFjcl9iYXRjaF9wY2FfbG9nZmMgPC0gbHBfbWFjcl9iYXRjaF9wY2FfZGVzZXFbLCBjKCJsb2dGQy54IiwibG9nRkMueSIpXQpjb2xuYW1lcyhscF9tYWNyX2JhdGNoX3BjYV9sb2dmYykgPC0gYygibm9iYXRjaCIsImJhc2ljIikKbGZjX3BjYV9iYXQgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihscF9tYWNyX2JhdGNoX3BjYV9sb2dmYywgcHJldHR5X2NvbG9ycz1GQUxTRSkKbGZjX3BjYV9iYXQkc2NhdHRlcgpsZmNfcGNhX2JhdCRjb3JyZWxhdGlvbgpgYGAKCiMjIENvbXBhcmUgcnV2IGVtcGlyaWNhbCB0byBiYXRjaCBpbiBtb2RlbCwgREVTZXEKCmBgYHtyIGJhdGNoX3J1dmVtcF9kZXNlcX0KbHBfbWFjcl9iYXRjaF9ydXZlbXBfZGVzZXEgPC0gbWVyZ2UoCiAgbHBfbWFjcl9ydXZlbXAkZGVzZXEkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgbHBfbWFjcl9iYXRjaCRiYXNpYyRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBieT0icm93Lm5hbWVzIikKcm93bmFtZXMobHBfbWFjcl9iYXRjaF9ydXZlbXBfZGVzZXEpIDwtIGxwX21hY3JfYmF0Y2hfcnV2ZW1wX2Rlc2VxW1siUm93Lm5hbWVzIl1dCmxwX21hY3JfYmF0Y2hfcnV2ZW1wX2xvZ2ZjIDwtIGxwX21hY3JfYmF0Y2hfcnV2ZW1wX2Rlc2VxWywgYygibG9nRkMueCIsImxvZ0ZDLnkiKV0KY29sbmFtZXMobHBfbWFjcl9iYXRjaF9ydXZlbXBfbG9nZmMpIDwtIGMoIm5vYmF0Y2giLCJiYXNpYyIpCmxmY19ydXZlbXBfYmF0IDwtIHNtKHBsb3RfbGluZWFyX3NjYXR0ZXIobHBfbWFjcl9iYXRjaF9ydXZlbXBfbG9nZmMsIHByZXR0eV9jb2xvcnM9RkFMU0UpKQpsZmNfcnV2ZW1wX2JhdCRzY2F0dGVyCmxmY19ydXZlbXBfYmF0JGNvcnJlbGF0aW9uCmBgYAoKIyMgQ29tcGFyZSBjb21iYXQgdG8gYmF0Y2ggaW4gbW9kZWwsIERFU2VxCgpgYGB7ciBjb21wYXJlX2JhdGNoX2NvbWJhdH0KbHBfbWFjcl9jb21iYXRfYmF0Y2ggPC0gbWVyZ2UoCiAgbHBfbWFjcl9jb21iYXQkZGVzZXEkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgbHBfbWFjcl9iYXRjaCRkZXNlcSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBieT0icm93Lm5hbWVzIikKcm93bmFtZXMobHBfbWFjcl9jb21iYXRfYmF0Y2gpIDwtIGxwX21hY3JfY29tYmF0X2JhdGNoW1siUm93Lm5hbWVzIl1dCmxwX21hY3JfY29tYmF0X2JhdGNoIDwtIGxwX21hY3JfY29tYmF0X2JhdGNoWywgYygibG9nRkMueCIsImxvZ0ZDLnkiKV0KY29sbmFtZXMobHBfbWFjcl9jb21iYXRfYmF0Y2gpIDwtIGMoImJhdGNoIiwiY29tYmF0IikKYl9jIDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIobHBfbWFjcl9jb21iYXRfYmF0Y2gsIHByZXR0eV9jb2xvcnM9RkFMU0UpCmJfYyRzY2F0dGVyCmJfYyRjb3JyZWxhdGlvbgpgYGAKCiMjIENvbXBhcmUgbm8gYmF0Y2ggdG8gYmF0Y2ggaW4gbW9kZWwsIGxpbW1hCgpgYGB7ciBjb21wYXJlX2JhdGNoX25vYmF0Y2hfbGltbWF9CmxwX21hY3Jfbm9iYXRjaF9iYXRjaCA8LSBtZXJnZSgKICBscF9tYWNyX25vYmF0Y2gkbGltbWEkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgbHBfbWFjcl9iYXRjaCRsaW1tYSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBieT0icm93Lm5hbWVzIikKcm93bmFtZXMobHBfbWFjcl9ub2JhdGNoX2JhdGNoKSA8LSBscF9tYWNyX25vYmF0Y2hfYmF0Y2hbWyJSb3cubmFtZXMiXV0KbHBfbWFjcl9ub2JhdGNoX2JhdGNoIDwtIGxwX21hY3Jfbm9iYXRjaF9iYXRjaFssIGMoImxvZ0ZDLngiLCJsb2dGQy55IildCmNvbG5hbWVzKGxwX21hY3Jfbm9iYXRjaF9iYXRjaCkgPC0gYygibm9iYXRjaCIsImJhdGNoIikKbmJfYiA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGxwX21hY3Jfbm9iYXRjaF9iYXRjaCwgcHJldHR5X2NvbG9ycz1GQUxTRSkKbmJfYiRzY2F0dGVyCm5iX2IkY29ycmVsYXRpb24KYGBgCgojIyBCYXRjaCBpbiBtb2RlbCB2cy4gU1ZBLCBsaW1tYQoKYGBge3IgY29tcGFyZV9iYXRjaF9zdmFfbGltbWEyfQpscF9tYWNyX2JhdGNoX3N2YSA8LSBtZXJnZSgKICBscF9tYWNyX2JhdGNoJGxpbW1hJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGxwX21hY3Jfc3ZhJGxpbW1hJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhscF9tYWNyX2JhdGNoX3N2YSkgPC0gbHBfbWFjcl9iYXRjaF9zdmFbWyJSb3cubmFtZXMiXV0KbHBfbWFjcl9iYXRjaF9zdmEgPC0gbHBfbWFjcl9iYXRjaF9zdmFbLCBjKCJsb2dGQy54IiwibG9nRkMueSIpXQpjb2xuYW1lcyhscF9tYWNyX2JhdGNoX3N2YSkgPC0gYygiYmF0Y2giLCJzdmEiKQpiX3MgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihscF9tYWNyX2JhdGNoX3N2YSwgcHJldHR5X2NvbG9ycz1GQUxTRSkKYl9zJHNjYXR0ZXIKYl9zJGNvcnJlbGF0aW9uCmBgYAoKIyMgQmF0Y2ggaW4gbW9kZWwgdnMuIGNvbWJhdCwgbGltbWEKCmBgYHtyIGNvbXBhcmVfYmF0Y2hfY29tYmF0X2xpbW1hfQpscF9tYWNyX2JhdGNoX2NvbWJhdCA8LSBtZXJnZSgKICBscF9tYWNyX2JhdGNoJGxpbW1hJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGxwX21hY3JfY29tYmF0JGxpbW1hJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhscF9tYWNyX2JhdGNoX2NvbWJhdCkgPC0gbHBfbWFjcl9iYXRjaF9jb21iYXRbWyJSb3cubmFtZXMiXV0KbHBfbWFjcl9iYXRjaF9jb21iYXQgPC0gbHBfbWFjcl9iYXRjaF9jb21iYXRbLCBjKCJsb2dGQy54IiwibG9nRkMueSIpXQpjb2xuYW1lcyhscF9tYWNyX2JhdGNoX2NvbWJhdCkgPC0gYygiYmF0Y2giLCJjb21iYXQiKQpiX2MgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihscF9tYWNyX2JhdGNoX2NvbWJhdCwgcHJldHR5X2NvbG9ycz1GQUxTRSkKYl9jJHNjYXR0ZXIKYl9jJGNvcnJlbGF0aW9uCmBgYAoKIyMgTm9iYXRjaCB2cy4gYmF0Y2ggaW4gbW9kZWwsIGVkZ2VyCgpgYGB7ciBjb21wYXJlX25vYmF0Y2hfYmF0Y2hfZWRnZXJ9CmxwX21hY3Jfbm9iYXRjaF9iYXRjaCA8LSBtZXJnZSgKICBscF9tYWNyX25vYmF0Y2gkZWRnZXIkYWxsX3RhYmxlcyRzaF92c19jaHIsCiAgbHBfbWFjcl9iYXRjaCRlZGdlciRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBieT0icm93Lm5hbWVzIikKcm93bmFtZXMobHBfbWFjcl9ub2JhdGNoX2JhdGNoKSA8LSBscF9tYWNyX25vYmF0Y2hfYmF0Y2hbWyJSb3cubmFtZXMiXV0KbHBfbWFjcl9ub2JhdGNoX2JhdGNoIDwtIGxwX21hY3Jfbm9iYXRjaF9iYXRjaFssIGMoImxvZ0ZDLngiLCJsb2dGQy55IildCmNvbG5hbWVzKGxwX21hY3Jfbm9iYXRjaF9iYXRjaCkgPC0gYygibm9iYXRjaCIsImJhdGNoIikKbmJfYiA8LSBzbShwbG90X2xpbmVhcl9zY2F0dGVyKGxwX21hY3Jfbm9iYXRjaF9iYXRjaCwgcHJldHR5X2NvbG9ycz1GQUxTRSkpCm5iX2Ikc2NhdHRlcgpuYl9iJGNvcnJlbGF0aW9uCmBgYAoKIyMgQmF0Y2ggaW4gbW9kZWwgdnMuIFNWQSwgZWRnZXIKCmBgYHtyIGNvbXBhcmVfYmF0Y2hfc3ZhX2VkZ2VyfQpscF9tYWNyX2JhdGNoX3N2YSA8LSBtZXJnZSgKICBscF9tYWNyX2JhdGNoJGVkZ2VyJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGxwX21hY3Jfc3ZhJGVkZ2VyJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhscF9tYWNyX2JhdGNoX3N2YSkgPC0gbHBfbWFjcl9iYXRjaF9zdmFbWyJSb3cubmFtZXMiXV0KbHBfbWFjcl9iYXRjaF9zdmEgPC0gbHBfbWFjcl9iYXRjaF9zdmFbLCBjKCJsb2dGQy54IiwibG9nRkMueSIpXQpjb2xuYW1lcyhscF9tYWNyX2JhdGNoX3N2YSkgPC0gYygiYmF0Y2giLCJzdmEiKQpiX3MgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihscF9tYWNyX2JhdGNoX3N2YSwgcHJldHR5X2NvbG9ycz1GQUxTRSkKYl9zJHNjYXR0ZXIKYl9zJGNvcnJlbGF0aW9uCmBgYAoKIyMgQmF0Y2ggaW4gbW9kZWwgdnMuIGNvbWJhdCwgZWRnZXIKCmBgYHtyIGNvbXBhcmVfYmF0Y2hfY29tYmF0X2VkZ2VyfQpscF9tYWNyX2JhdGNoX2NvbWJhdCA8LSBtZXJnZSgKICBscF9tYWNyX2JhdGNoJGVkZ2VyJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGxwX21hY3JfY29tYmF0JGVkZ2VyJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhscF9tYWNyX2JhdGNoX2NvbWJhdCkgPC0gbHBfbWFjcl9iYXRjaF9jb21iYXRbWyJSb3cubmFtZXMiXV0KbHBfbWFjcl9iYXRjaF9jb21iYXQgPC0gbHBfbWFjcl9iYXRjaF9jb21iYXRbLCBjKCJsb2dGQy54IiwibG9nRkMueSIpXQpjb2xuYW1lcyhscF9tYWNyX2JhdGNoX2NvbWJhdCkgPC0gYygiYmF0Y2giLCJjb21iYXQiKQpiX2MgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihscF9tYWNyX2JhdGNoX2NvbWJhdCwgcHJldHR5X2NvbG9ycz1GQUxTRSkKYl9jJHNjYXR0ZXIKYl9jJGNvcnJlbGF0aW9uCmBgYAoKIyMgQ29tcGFyZSBub2JhdGNoIHZzLiBiYXRjaCwgZGVzZXEKCmBgYHtyIGNvbXBhcmVfbm9iYXRjaF9iYXRjaF9kZXNlcX0KbHBfbWFjcl9ub2JhdGNoX2JhdGNoIDwtIG1lcmdlKAogIGxwX21hY3Jfbm9iYXRjaCRkZXNlcSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBscF9tYWNyX2JhdGNoJGRlc2VxJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhscF9tYWNyX25vYmF0Y2hfYmF0Y2gpIDwtIGxwX21hY3Jfbm9iYXRjaF9iYXRjaFtbIlJvdy5uYW1lcyJdXQpscF9tYWNyX25vYmF0Y2hfYmF0Y2ggPC0gbHBfbWFjcl9ub2JhdGNoX2JhdGNoWywgYygibG9nRkMueCIsImxvZ0ZDLnkiKV0KY29sbmFtZXMobHBfbWFjcl9ub2JhdGNoX2JhdGNoKSA8LSBjKCJub2JhdGNoIiwiYmF0Y2giKQpuYl9iIDwtIHNtKHBsb3RfbGluZWFyX3NjYXR0ZXIobHBfbWFjcl9ub2JhdGNoX2JhdGNoLCBwcmV0dHlfY29sb3JzPUZBTFNFKSkKbmJfYiRzY2F0dGVyCm5iX2IkY29ycmVsYXRpb24KYGBgCgojIyBDb21wYXJlIGJhdGNoIHZzLiBTVkEsIGRlc2VxCgpgYGB7ciBjb21wYXJlX2JhdGNoX3N2YV9kZXNlcX0KbHBfbWFjcl9iYXRjaF9zdmEgPC0gbWVyZ2UoCiAgbHBfbWFjcl9iYXRjaCRkZXNlcSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBscF9tYWNyX3N2YSRkZXNlcSRhbGxfdGFibGVzJHNoX3ZzX2NociwKICBieT0icm93Lm5hbWVzIikKcm93bmFtZXMobHBfbWFjcl9iYXRjaF9zdmEpIDwtIGxwX21hY3JfYmF0Y2hfc3ZhW1siUm93Lm5hbWVzIl1dCmxwX21hY3JfYmF0Y2hfc3ZhIDwtIGxwX21hY3JfYmF0Y2hfc3ZhWywgYygibG9nRkMueCIsImxvZ0ZDLnkiKV0KY29sbmFtZXMobHBfbWFjcl9iYXRjaF9zdmEpIDwtIGMoImJhdGNoIiwic3ZhIikKYl9zIDwtIHNtKHBsb3RfbGluZWFyX3NjYXR0ZXIobHBfbWFjcl9iYXRjaF9zdmEsIHByZXR0eV9jb2xvcnM9RkFMU0UpKQpiX3Mkc2NhdHRlcgpiX3MkY29ycmVsYXRpb24KYGBgCgojIyBCYXRjaCBpbiBtb2RlbCB2cy4gY29tYmF0LCBkZXNlcQoKYGBge3IgYmF0Y2hfY29tYmF0X2Rlc2VxfQpscF9tYWNyX2JhdGNoX2NvbWJhdCA8LSBtZXJnZSgKICBscF9tYWNyX2JhdGNoJGRlc2VxJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGxwX21hY3JfY29tYmF0JGRlc2VxJGFsbF90YWJsZXMkc2hfdnNfY2hyLAogIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhscF9tYWNyX2JhdGNoX2NvbWJhdCkgPC0gbHBfbWFjcl9iYXRjaF9jb21iYXRbWyJSb3cubmFtZXMiXV0KbHBfbWFjcl9iYXRjaF9jb21iYXQgPC0gbHBfbWFjcl9iYXRjaF9jb21iYXRbLCBjKCJsb2dGQy54IiwibG9nRkMueSIpXQpjb2xuYW1lcyhscF9tYWNyX2JhdGNoX2NvbWJhdCkgPC0gYygiYmF0Y2giLCJjb21iYXQiKQpiX2MgPC0gc20ocGxvdF9saW5lYXJfc2NhdHRlcihscF9tYWNyX2JhdGNoX2NvbWJhdCwgcHJldHR5X2NvbG9ycz1GQUxTRSkpCmJfYyRzY2F0dGVyCmJfYyRjb3JyZWxhdGlvbgpgYGAKCmBgYHtyIHNhdmVtZX0KcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSkKbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCnRoaXNfc2F2ZSA8LSBwYXN0ZTAoZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSIiLCB4PXJtZF9maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpCm1lc3NhZ2UocGFzdGUwKCJTYXZpbmcgdG8gIiwgdGhpc19zYXZlKSkKdG1wIDwtIHNtKHNhdmVtZShmaWxlbmFtZT10aGlzX3NhdmUpKQpgYGAK