index.html macrophage_estimation.html

1 RNA sequencing of Leishmania panamensis during infection of human macrophages: Differential Expression

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.

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.

my_contrasts <- list(
    "macro_chr-sh" = c("macro_ch","macro_sh"),
    "macro_chr-nil" = c("macro_ch","macro_nil"),
    "macro_sh-nil" = c("macro_sh", "macro_nil"))
macro_norm <- sm(normalize_expt(macrophage_human, filter=TRUE, convert="cpm"))
macro_combat_norm <- sm(normalize_expt(macrophage_human, filter=TRUE, batch="combat_scale"))
macro_sva_norm <- sm(normalize_expt(macrophage_human, filter=TRUE, batch="svaseq"))
macro_lowfilt <- sm(normalize_expt(macrophage_human, filter=TRUE))
## Set up the data used in the comparative contrast sets.

2.1 No batch in the model

macro_nobatch <- sm(all_pairwise(input=macro_lowfilt, model_batch=FALSE))
## wow, all tools including basic agree almost completely
medians_by_condition <- macro_nobatch$basic$medians
macro_nobatch_tables <- sm(combine_de_tables(macro_nobatch,
                                             excel=paste0("excel/macrophage_nobatch-v", ver, ".xlsx"),
                                             keepers=my_contrasts,
                                             extra_annot=medians_by_condition))
macro_nobatch_sig <- sm(extract_significant_genes(macro_nobatch_tables,
                                                  excel=paste0("excel/macrophage_nobatch_significant-v", ver, ".xlsx"),
                                                  p_type="unadjusted",
                                                  according_to="all"))

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
macro_batch <- sm(all_pairwise(input=macro_lowfilt))
medians_by_condition <- macro_batch$basic$medians
macro_batch_tables <- sm(combine_de_tables(macro_batch, excel=paste0("excel/macrophage_batchmodel-v", ver, ".xlsx"),
                                           keepers=my_contrasts,
                                           extra_annot=medians_by_condition))
macro_batch_sig <- sm(extract_significant_genes(macro_batch_tables,
                                             excel=paste0("excel/macrophage_batchmodel_significant-v", ver, ".xlsx"),
                                             p_type="unadjusted",
                                             according_to="limma"))

2.3 Batch estimated with SVA

## Here just let all_pairwise run on filtered data and do its normal ~ 0 + condition + batch analyses
macro_sva <- sm(all_pairwise(input=macro_lowfilt, model_batch="svaseq"))
medians_by_condition <- macro_sva$basic$medians
macro_sva_tables <- sm(combine_de_tables(macro_sva, excel=paste0("excel/macrophage_sva-v", ver, ".xlsx"),
                                         keepers=my_contrasts,
                                         extra_annot=medians_by_condition))
macro_sva_sig <- sm(extract_significant_genes(macro_sva_tables,
                                              excel=paste0("excel/macrophage_sva_significant-v", ver, ".xlsx"),
                                              p_type="unadjusted",
                                              according_to="all"))
macro_sva_ma_limma <- extract_de_ma(pairwise=macro_sva, type="limma", table="macro_sh_vs_macro_ch")
macro_sva_ma_limma$plot

2.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 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(data=macro_lowfilt, estimate_type="ruv_residuals")
## The be method chose 1 surrogate variable(s).
## Attempting ruvseq residual surrogate estimation.
macro_ruvres <- sm(all_pairwise(input=macro_lowfilt, model_batch="ruv_residuals"))
medians_by_condition <- macro_ruvres$basic$medians
macro_ruvres_tables <- sm(combine_de_tables(macro_ruvres, excel=paste0("excel/macrophage_ruvres-v", ver, ".xlsx"),
                                            keepers=my_contrasts,
                                            extra_annot=medians_by_condition))
macro_ruvres_sig <- sm(extract_significant_genes(macro_ruvres_tables,
                                                 excel=paste0("excel/macrophage_ruvres_significant-v", ver, ".xlsx"),
                                                 p_type="unadjusted",
                                                 according_to="all"))

2.5 Batch correction with pca

## Here just let all_pairwise run on filtered data and do its normal ~ 0 + condition + batch analyses
macro_pca <- sm(all_pairwise(input=macro_lowfilt, model_batch="pca"))
medians_by_condition <- macro_pca$basic$medians
macro_pca_tables <- sm(combine_de_tables(macro_pca, excel=paste0("excel/macrophage_pca-v", ver, ".xlsx"),
                                         keepers=my_contrasts,
                                         extra_annot=medians_by_condition))
macro_pca_sig <- sm(extract_significant_genes(macro_pca_tables,
                                              excel=paste0("excel/macrophage_pca_significant-v", ver, ".xlsx"),
                                              p_type="unadjusted",
                                              according_to="all"))

2.6 Batch correction with ruv empirical

## Here just let all_pairwise run on filtered data and do its normal ~ 0 + condition + batch analyses
macro_ruvemp <- sm(all_pairwise(input=macro_lowfilt, model_batch="ruv_empirical"))
medians_by_condition <- macro_ruvemp$basic$medians
macro_ruvemp_tables <- sm(combine_de_tables(macro_ruvemp, excel=paste0("excel/macrophage_ruvemp-v", ver, ".xlsx"),
                                            keepers=my_contrasts,
                                            extra_annot=medians_by_condition))
macro_ruvemp_sig <- sm(extract_significant_genes(macro_ruvemp_tables,
                                                 excel=paste0("excel/macrophage_ruvemp_significant-v", ver, ".xlsx"),
                                                 p_type="unadjusted",
                                                 according_to="all"))

2.7 Batch correction with combat

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

macro_combat <- sm(all_pairwise(input=macro_combat_norm, force=TRUE))
medians_by_condition <- macro_combat$basic$medians
macro_combat_tables <- sm(combine_de_tables(macro_combat,
                                            excel=paste0("excel/macrophage_combat-v", ver, ".xlsx"),
                                            keepers=my_contrasts,
                                            extra_annot=medians_by_condition))
macro_combat_sig <- sm(extract_significant_genes(macro_combat_tables,
                                                 excel=paste0("excel/macrophage_combat_significant-v", ver, ".xlsx"),
                                                 p_type="unadjusted",
                                                 according_to="all"))
macro_combat_ma_limma <- limma_ma(output=macro_combat, table="macro_sh_vs_macro_ch")
## Error in eval(expr, envir, enclos): could not find function "limma_ma"
png(file="images/macro_combat_ma-limma.png")
macro_combat_ma_limma$plot
## Error in eval(expr, envir, enclos): object 'macro_combat_ma_limma' not found
dev.off()
## X11cairo
##        2
macro_combat_ma_edger <- edger_ma(output=macro_combat, table="macro_sh_vs_macro_ch")
## Error in eval(expr, envir, enclos): could not find function "edger_ma"

png(file="images/macro_combat_ma-edger.png")
macro_combat_ma_edger$plot
## Error in eval(expr, envir, enclos): object 'macro_combat_ma_edger' not found
dev.off()
## X11cairo
##        2
macro_combat_ma_deseq <- deseq_ma(output=macro_combat, table="macro_sh_vs_macro_ch")
## Error in eval(expr, envir, enclos): could not find function "deseq_ma"
png(file="images/macro_combat_ma-deseq.png")
macro_combat_ma_deseq$plot
## Error in eval(expr, envir, enclos): object 'macro_combat_ma_deseq' not found
dev.off()
## X11cairo
##        2

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

4 Look first at the de counts

macro_nobatch_sig$limma$counts
##               change_counts_up change_counts_down
## macro_chr-sh               104                 55
## macro_chr-nil              187                137
## macro_sh-nil                 7                 25
macro_batch_sig$limma$counts
##               change_counts_up change_counts_down
## macro_chr-sh               134                129
## macro_chr-nil              255                390
## macro_sh-nil                24                 43
macro_sva_sig$limma$counts
##               change_counts_up change_counts_down
## macro_chr-sh               166                173
## macro_chr-nil              496                260
## macro_sh-nil                25                 31
macro_ruvres_sig$limma$counts
##               change_counts_up change_counts_down
## macro_chr-sh               492                275
## macro_chr-nil              643                318
## macro_sh-nil                26                 34
macro_pca_sig$limma$counts
##               change_counts_up change_counts_down
## macro_chr-sh                84                 73
## macro_chr-nil              221                232
## macro_sh-nil                25                 33
macro_ruvemp_sig$limma$counts
##               change_counts_up change_counts_down
## macro_chr-sh               102                107
## macro_chr-nil              286                207
## macro_sh-nil                24                 30
macro_combat_sig$limma$counts
##               change_counts_up change_counts_down
## macro_chr-sh               156                757
## macro_chr-nil              420                361
## macro_sh-nil                43                  5

4.1 Compare DeSeq / Basic without batch in model

nobatch_basic <- merge(macro_nobatch$deseq$all_tables$macro_sh_vs_macro_ch, macro_batch$basic$all_tables$macro_sh_vs_macro_ch, by="row.names")
rownames(nobatch_basic) <- nobatch_basic[["Row.names"]]
nobatch_logfc <- nobatch_basic[, c("logFC.x","logFC.y")]
colnames(nobatch_logfc) <- c("nobatch","basic")
lfc_nb_b <- sm(plot_linear_scatter(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 = 230, df = 13000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.8899 0.8968
## sample estimates:
##    cor
## 0.8934
nobatch_p <- nobatch_basic[, c("P.Value","p")]
nobatch_p[[2]] <- as.numeric(nobatch_p[[2]])
colnames(nobatch_p) <- c("nobatch","basic")
nobatch_p <- -1 * log(nobatch_p)
p_nb_b <- sm(plot_linear_scatter(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 = 13000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.7083 0.7250
## sample estimates:
##    cor
## 0.7167

4.2 Compare SVA to batch in model, DESeq

sva_batch <- merge(macro_sva$deseq$all_tables$macro_sh_vs_macro_ch, macro_batch$deseq$all_tables$macro_sh_vs_macro_ch, by="row.names")
rownames(sva_batch) <- sva_batch[["Row.names"]]
sva_logfc <- sva_batch[, c("logFC.x","logFC.y")]
colnames(sva_logfc) <- c("sva","batch")
lfc_b_s <- sm(plot_linear_scatter(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 = 49, df = 13000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.379 0.408
## sample estimates:
##    cor
## 0.3936

4.2.1 Include p-value estimations

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

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

4.3 Compare ruvresid to batch in model, DESeq

batch_ruvresid_deseq <- merge(macro_ruvres$deseq$all_tables$macro_sh_vs_macro_ch, macro_batch$basic$all_tables$macro_sh_vs_macro_ch, by="row.names")
rownames(batch_ruvresid_deseq) <- batch_ruvresid_deseq[["Row.names"]]
batch_ruvresid_logfc <- batch_ruvresid_deseq[, c("logFC.x","logFC.y")]
colnames(batch_ruvresid_logfc) <- c("nobatch","basic")
lfc_ruv_bat <- plot_linear_scatter(batch_ruvresid_logfc, pretty_colors=FALSE)
## 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 = 230, df = 13000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.8899 0.8968
## sample estimates:
##    cor
## 0.8934

4.4 Compare pca to batch in model, DESeq

batch_pca_deseq <- merge(macro_pca$deseq$all_tables$macro_sh_vs_macro_ch, macro_batch$basic$all_tables$macro_sh_vs_macro_ch, by="row.names")
rownames(batch_pca_deseq) <- batch_pca_deseq[["Row.names"]]
batch_pca_logfc <- batch_pca_deseq[, c("logFC.x","logFC.y")]
colnames(batch_pca_logfc) <- c("nobatch","basic")
lfc_pca_bat <- plot_linear_scatter(batch_pca_logfc, pretty_colors=FALSE)
## 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 = 230, df = 13000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.8899 0.8968
## sample estimates:
##    cor
## 0.8934

4.5 Compare ruv empirical to batch in model, DESeq

batch_ruvemp_deseq <- merge(macro_ruvemp$deseq$all_tables$macro_sh_vs_macro_ch, macro_batch$basic$all_tables$macro_sh_vs_macro_ch, by="row.names")
rownames(batch_ruvemp_deseq) <- batch_ruvemp_deseq[["Row.names"]]
batch_ruvemp_logfc <- batch_ruvemp_deseq[, c("logFC.x","logFC.y")]
colnames(batch_ruvemp_logfc) <- c("nobatch","basic")
lfc_ruvemp_bat <- sm(plot_linear_scatter(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 = 230, df = 13000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.8899 0.8968
## sample estimates:
##    cor
## 0.8934

4.6 Compare combat to batch in model, DESeq

combat_batch <- merge(macro_combat$deseq$all_tables$macro_sh_vs_macro_ch, macro_batch$deseq$all_tables$macro_sh_vs_macro_ch, by="row.names")
rownames(combat_batch) <- combat_batch[["Row.names"]]
combat_batch <- combat_batch[, c("logFC.x","logFC.y")]
colnames(combat_batch) <- c("batch","combat")
b_c <- plot_linear_scatter(combat_batch, pretty_colors=FALSE)
## 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 = 560, df = 13000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.9794 0.9807
## sample estimates:
##    cor
## 0.9801

4.7 Compare no batch to batch in model, limma

nobatch_batch <- merge(macro_nobatch$limma$all_tables$macro_sh_vs_macro_ch, macro_batch$limma$all_tables$macro_sh_vs_macro_ch, by="row.names")
rownames(nobatch_batch) <- nobatch_batch[["Row.names"]]
nobatch_batch <- nobatch_batch[, c("logFC.x","logFC.y")]
colnames(nobatch_batch) <- c("nobatch","batch")
nb_b <- plot_linear_scatter(nobatch_batch, pretty_colors=FALSE)
## 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 = 56, df = 13000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.4278 0.4554
## sample estimates:
##    cor
## 0.4417

4.8 Batch in model vs. SVA, limma

batch_sva <- merge(macro_batch$limma$all_tables$macro_sh_vs_macro_ch, macro_sva$limma$all_tables$macro_sh_vs_macro_ch, by="row.names")
rownames(batch_sva) <- batch_sva[["Row.names"]]
batch_sva <- batch_sva[, c("logFC.x","logFC.y")]
colnames(batch_sva) <- c("batch","sva")
b_s <- plot_linear_scatter(batch_sva, pretty_colors=FALSE)
## 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 = 65, df = 13000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.4826 0.5084
## sample estimates:
##    cor
## 0.4956

4.9 Batch in model vs. combat, limma

batch_combat <- merge(macro_batch$limma$all_tables$macro_sh_vs_macro_ch, macro_combat$limma$all_tables$macro_sh_vs_macro_ch, by="row.names")
rownames(batch_combat) <- batch_combat[["Row.names"]]
batch_combat <- batch_combat[, c("logFC.x","logFC.y")]
colnames(batch_combat) <- c("batch","combat")
b_c <- plot_linear_scatter(batch_combat, pretty_colors=FALSE)
## 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 = 410, df = 13000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.9614 0.9639
## sample estimates:
##    cor
## 0.9627

4.10 Nobatch vs. batch in model, edger

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

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

4.11 Batch in model vs. SVA, edger

batch_sva <- merge(macro_batch$edger$all_tables$macro_sh_vs_macro_ch, macro_sva$edger$all_tables$macro_sh_vs_macro_ch, by="row.names")
rownames(batch_sva) <- batch_sva[["Row.names"]]
batch_sva <- batch_sva[, c("logFC.x","logFC.y")]
colnames(batch_sva) <- c("batch","sva")
b_s <- plot_linear_scatter(batch_sva, pretty_colors=FALSE)
## 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 = 65, df = 13000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.4824 0.5083
## sample estimates:
##    cor
## 0.4955

4.12 Batch in model vs. combat, edger

batch_combat <- merge(macro_batch$edger$all_tables$macro_sh_vs_macro_ch, macro_combat$edger$all_tables$macro_sh_vs_macro_ch, by="row.names")
rownames(batch_combat) <- batch_combat[["Row.names"]]
batch_combat <- batch_combat[, c("logFC.x","logFC.y")]
colnames(batch_combat) <- c("batch","combat")
b_c <- plot_linear_scatter(batch_combat, pretty_colors=FALSE)
## 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 = 370, df = 13000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.9534 0.9564
## sample estimates:
##    cor
## 0.9549

4.13 Compare nobatch vs. batch, deseq

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

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

4.14 Compare batch vs. SVA, deseq

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

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

4.15 Batch in model vs. combat, deseq

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

b_c$correlation
##
##  Pearson's product-moment correlation
##
## data:  df[, 1] and df[, 2]
## t = 560, df = 13000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.9794 0.9807
## sample estimates:
##    cor
## 0.9801
tmp <- sm(saveme(filename="macrophage_expression_human.rda.xz"))

index.html macrophage_estimation.html

LS0tCnRpdGxlOiAiUk5Bc2VxIG9mIEwucGFuYW1lbnNpcyBpbiBodW1hbiBtYWNyb3BoYWdlcywgZHVyaW5nIGluZmVjdGlvbiwgaW4gYmlvcHNpZXMsIGFuZCB3aXRoIGFudGltb25pYWwgdHJlYXRtZW50LiIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogaHRtbF9kb2N1bWVudDoKICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgY29kZV9mb2xkaW5nOiBzaG93CiAgZmlnX2NhcHRpb246IHRydWUKICBmaWdfaGVpZ2h0OiA3CiAgZmlnX3dpZHRoOiA3CiAgaGlnaGxpZ2h0OiB0YW5nbwogIGtlZXBfbWQ6IGZhbHNlCiAgbW9kZTogc2VsZmNvbnRhaW5lZAogIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgdGhlbWU6IGNvc21vCiAgdG9jOiB0cnVlCiAgdG9jX2Zsb2F0OgogICAgY29sbGFwc2VkOiBmYWxzZQogICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgo8c3R5bGU+CiAgPCEtLSBEb2N1bWVudCBwcmVsdWRlIHJldmlzaW9uIDIwMTYtMTAgLS0+CiAgYm9keSAubWFpbi1jb250YWluZXIgewogICAgbWF4LXdpZHRoOiAxNjAwcHg7Cn0KPC9zdHlsZT4KCmBgYHtyIG9wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CiMjIFRoZXNlIGFyZSB0aGUgb3B0aW9ucyBJIHRlbmQgdG8gZmF2b3IKbGlicmFyeSgiaHBnbHRvb2xzIikKZGV2dG9vbHM6OmxvYWRfYWxsKCJ+L2hwZ2x0b29scyIpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KAogICAgcHJvZ3Jlc3MgPSBUUlVFLAogICAgdmVyYm9zZSA9IFRSVUUsCiAgICB3aWR0aCA9IDkwLAogICAgZWNobyA9IFRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICAgIGVycm9yID0gVFJVRSwKICAgIGZpZy53aWR0aCA9IDgsCiAgICBmaWcuaGVpZ2h0ID0gOCwKICAgIGRwaSA9IDk2KQpvcHRpb25zKAogICAgZGlnaXRzID0gNCwKICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwKICAgIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbCA9ICJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemU9MTApKQpzZXQuc2VlZCgxKQpybWRfZmlsZSA8LSAibWFjcm9waGFnZV9leHByZXNzaW9uX2h1bWFuLlJtZCIKdmVyIDwtICIyMDE3MDIwNiIKYGBgCgpbaW5kZXguaHRtbF0oaW5kZXguaHRtbCkgW21hY3JvcGhhZ2VfZXN0aW1hdGlvbi5odG1sXShtYWNyb3BoYWdlX2VzdGltYXRpb24uaHRtbCkKCmBgYHtyIHJlbmRlcmluZywgaW5jbHVkZT1GQUxTRSwgZXZhbD1GQUxTRX0KIyMgVGhpcyBibG9jayBpcyB1c2VkIHRvIHJlbmRlciBhIGRvY3VtZW50IGZyb20gd2l0aGluIGl0LgpybWFya2Rvd246OnJlbmRlcihybWRfZmlsZSkKCiMjIEFuIGV4dHJhIHJlbmRlcmVyIGZvciBwZGYgb3V0cHV0CnJtYXJrZG93bjo6cmVuZGVyKHJtZF9maWxlLCBvdXRwdXRfZm9ybWF0PSJwZGZfZG9jdW1lbnQiLCBvdXRwdXRfb3B0aW9ucz1jKCJza2lwX2h0bWwiKSkKIyMgT3IgdG8gc2F2ZS9sb2FkIGxhcmdlIFJkYXRhIGZpbGVzLgpocGdsdG9vbHM6OjpzYXZlbWUoKQpocGdsdG9vbHM6Ojpsb2FkbWUoKQpybShsaXN0PWxzKCkpCmBgYAoKUk5BIHNlcXVlbmNpbmcgb2YgTGVpc2htYW5pYSBwYW5hbWVuc2lzIGR1cmluZyBpbmZlY3Rpb24gb2YgaHVtYW4gbWFjcm9waGFnZXM6IERpZmZlcmVudGlhbCBFeHByZXNzaW9uCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKSW4gJ21hY3JvcGhhZ2VfZXN0aW1hdGlvbicsIHdlIGRpZCBhIHNlcmllcyBvZiBhbmFseXNlcyB0byB0cnkgdG8gcGljayBvdXQgc29tZSBvZiB0aGUgc3Vycm9nYXRlCnZhcmlhYmxlcyBpbiB0aGUgZGF0YS4gIE5vdyB3ZSB3aWxsIHBlcmZvcm0gYSBzZXQgb2YgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzZXMgdXNpbmcgdGhlCnJlc3VsdHMgZnJvbSB0aGF0LiAgU2luY2UgdGhlICdiYXRjaCcgZWxlbWVudCBvZiB0aGUgZGF0YSBpcyByZWFzb25hYmx5IHdlbGwgZXhwbGFpbmVkLCB3ZSB3aWxsIG5vdAphYnVzZSB0aGUgZGF0YSB3aXRoIHN2YS9jb21iYXQsIGJ1dCBpbnN0ZWFkIGluY2x1ZGUgYmF0Y2ggaW4gdGhlIGV4cGVyaW1lbnRhbCBtb2RlbC4KCmBgYHtyIGxvYWRtZSwgaW5jbHVkZT1GQUxTRX0KdG1wIDwtIHNtKGxvYWRtZShmaWxlbmFtZT0ibWFjcm9waGFnZV9lc3RpbWF0aW9uX2h1bWFuLnJkYS54eiIpKQpgYGAKCiMgRGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzZXMKCkl0IGFwcGVhcnMgdGhhdCBpdCBpcyBwb3NzaWJsZSB0aG91Z2ggc29tZXdoYXQgZGlmZmljdWx0IHRvIGFwcGx5IGJhdGNoIGVzdGltYXRpb25zIGdlbmVyYXRlZCBieSBzdmEKdG8gdGhlIG1vZGVsIGdpdmVuIHRvIERFU2VxL0VkZ2VSL2xpbW1hLiAgSW4gdGhlIGNhc2Ugb2YgbGltbWEgaXQgaXMgZmFpcmx5IHNpbXBsZSwgYnV0IGluIHRoZSBvdGhlcgp0d28gaXQgaXMgYSBiaXQgbW9yZSBkaWZmaWN1bHQuICBUaGVyZSBpcyBhIG5pY2UgZGlzY3Vzc2lvbiBvZiB0aGlzIGF0OiBodHRwczovL3d3dy5iaW9zdGFycy5vcmcvcC8xNTYxODYvCkkgYW0gYXR0ZW1wdGluZyB0byBhcHBseSB0aGF0IGxvZ2ljIHRvIHRoaXMgZGF0YSB3aXRoIGxpbWl0ZWQgc3VjY2Vzcy4KCmBgYHtyIHNldHVwX2RlLCBmaWcuc2hvdz0iaGlkZSJ9Cm15X2NvbnRyYXN0cyA8LSBsaXN0KAogICAgIm1hY3JvX2Noci1zaCIgPSBjKCJtYWNyb19jaCIsIm1hY3JvX3NoIiksCiAgICAibWFjcm9fY2hyLW5pbCIgPSBjKCJtYWNyb19jaCIsIm1hY3JvX25pbCIpLAogICAgIm1hY3JvX3NoLW5pbCIgPSBjKCJtYWNyb19zaCIsICJtYWNyb19uaWwiKSkKbWFjcm9fbm9ybSA8LSBzbShub3JtYWxpemVfZXhwdChtYWNyb3BoYWdlX2h1bWFuLCBmaWx0ZXI9VFJVRSwgY29udmVydD0iY3BtIikpCm1hY3JvX2NvbWJhdF9ub3JtIDwtIHNtKG5vcm1hbGl6ZV9leHB0KG1hY3JvcGhhZ2VfaHVtYW4sIGZpbHRlcj1UUlVFLCBiYXRjaD0iY29tYmF0X3NjYWxlIikpCm1hY3JvX3N2YV9ub3JtIDwtIHNtKG5vcm1hbGl6ZV9leHB0KG1hY3JvcGhhZ2VfaHVtYW4sIGZpbHRlcj1UUlVFLCBiYXRjaD0ic3Zhc2VxIikpCm1hY3JvX2xvd2ZpbHQgPC0gc20obm9ybWFsaXplX2V4cHQobWFjcm9waGFnZV9odW1hbiwgZmlsdGVyPVRSVUUpKQojIyBTZXQgdXAgdGhlIGRhdGEgdXNlZCBpbiB0aGUgY29tcGFyYXRpdmUgY29udHJhc3Qgc2V0cy4KYGBgCgojIyBObyBiYXRjaCBpbiB0aGUgbW9kZWwKCmBgYHtyIG1hY3JvX25vYmF0Y2gsIGZpZy5zaG93PSJoaWRlIn0KbWFjcm9fbm9iYXRjaCA8LSBzbShhbGxfcGFpcndpc2UoaW5wdXQ9bWFjcm9fbG93ZmlsdCwgbW9kZWxfYmF0Y2g9RkFMU0UpKQojIyB3b3csIGFsbCB0b29scyBpbmNsdWRpbmcgYmFzaWMgYWdyZWUgYWxtb3N0IGNvbXBsZXRlbHkKbWVkaWFuc19ieV9jb25kaXRpb24gPC0gbWFjcm9fbm9iYXRjaCRiYXNpYyRtZWRpYW5zCm1hY3JvX25vYmF0Y2hfdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKG1hY3JvX25vYmF0Y2gsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvbWFjcm9waGFnZV9ub2JhdGNoLXYiLCB2ZXIsICIueGxzeCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZWVwZXJzPW15X2NvbnRyYXN0cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXh0cmFfYW5ub3Q9bWVkaWFuc19ieV9jb25kaXRpb24pKQptYWNyb19ub2JhdGNoX3NpZyA8LSBzbShleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKG1hY3JvX25vYmF0Y2hfdGFibGVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvbWFjcm9waGFnZV9ub2JhdGNoX3NpZ25pZmljYW50LXYiLCB2ZXIsICIueGxzeCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBfdHlwZT0idW5hZGp1c3RlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWNjb3JkaW5nX3RvPSJhbGwiKSkKYGBgCgojIyBCYXRjaCBpbiB0aGUgbW9kZWwKCkluIHRoaXMgIGF0dGVtcHQsIHdlIGFkZCBhIGJhdGNoIGZhY3RvciBpbiB0aGUgZXhwZXJpbWVudGFsIG1vZGVsIGFuZCBzZWUgaG93IGl0IGRvZXMuCgpgYGB7ciBtYWNyb19iYXRjaCwgZmlnLnNob3c9ImhpZGUifQojIyBIZXJlIGp1c3QgbGV0IGFsbF9wYWlyd2lzZSBydW4gb24gZmlsdGVyZWQgZGF0YSBhbmQgZG8gaXRzIG5vcm1hbCB+IDAgKyBjb25kaXRpb24gKyBiYXRjaCBhbmFseXNlcwptYWNyb19iYXRjaCA8LSBzbShhbGxfcGFpcndpc2UoaW5wdXQ9bWFjcm9fbG93ZmlsdCkpCm1lZGlhbnNfYnlfY29uZGl0aW9uIDwtIG1hY3JvX2JhdGNoJGJhc2ljJG1lZGlhbnMKbWFjcm9fYmF0Y2hfdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKG1hY3JvX2JhdGNoLCBleGNlbD1wYXN0ZTAoImV4Y2VsL21hY3JvcGhhZ2VfYmF0Y2htb2RlbC12IiwgdmVyLCAiLnhsc3giKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlZXBlcnM9bXlfY29udHJhc3RzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXh0cmFfYW5ub3Q9bWVkaWFuc19ieV9jb25kaXRpb24pKQptYWNyb19iYXRjaF9zaWcgPC0gc20oZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcyhtYWNyb19iYXRjaF90YWJsZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvbWFjcm9waGFnZV9iYXRjaG1vZGVsX3NpZ25pZmljYW50LXYiLCB2ZXIsICIueGxzeCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwX3R5cGU9InVuYWRqdXN0ZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY2NvcmRpbmdfdG89ImxpbW1hIikpCmBgYAoKIyMgQmF0Y2ggZXN0aW1hdGVkIHdpdGggU1ZBCgpgYGB7ciBtYWNyb19zdmEsIGZpZy5zaG93PSJoaWRlIn0KIyMgSGVyZSBqdXN0IGxldCBhbGxfcGFpcndpc2UgcnVuIG9uIGZpbHRlcmVkIGRhdGEgYW5kIGRvIGl0cyBub3JtYWwgfiAwICsgY29uZGl0aW9uICsgYmF0Y2ggYW5hbHlzZXMKbWFjcm9fc3ZhIDwtIHNtKGFsbF9wYWlyd2lzZShpbnB1dD1tYWNyb19sb3dmaWx0LCBtb2RlbF9iYXRjaD0ic3Zhc2VxIikpCm1lZGlhbnNfYnlfY29uZGl0aW9uIDwtIG1hY3JvX3N2YSRiYXNpYyRtZWRpYW5zCm1hY3JvX3N2YV90YWJsZXMgPC0gc20oY29tYmluZV9kZV90YWJsZXMobWFjcm9fc3ZhLCBleGNlbD1wYXN0ZTAoImV4Y2VsL21hY3JvcGhhZ2Vfc3ZhLXYiLCB2ZXIsICIueGxzeCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlZXBlcnM9bXlfY29udHJhc3RzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4dHJhX2Fubm90PW1lZGlhbnNfYnlfY29uZGl0aW9uKSkKbWFjcm9fc3ZhX3NpZyA8LSBzbShleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKG1hY3JvX3N2YV90YWJsZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbD1wYXN0ZTAoImV4Y2VsL21hY3JvcGhhZ2Vfc3ZhX3NpZ25pZmljYW50LXYiLCB2ZXIsICIueGxzeCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcF90eXBlPSJ1bmFkanVzdGVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjY29yZGluZ190bz0iYWxsIikpCm1hY3JvX3N2YV9tYV9saW1tYSA8LSBleHRyYWN0X2RlX21hKHBhaXJ3aXNlPW1hY3JvX3N2YSwgdHlwZT0ibGltbWEiLCB0YWJsZT0ibWFjcm9fc2hfdnNfbWFjcm9fY2giKQpgYGAKCmBgYHtyIHN2YV9tYV9wbG90fQptYWNyb19zdmFfbWFfbGltbWEkcGxvdApgYGAKCiMjIEJhdGNoIGNvcnJlY3Rpb24gdmlhIHJ1diByZXNpZHVhbHMKCmBgYHtyIG1hY3JvX3J1dnJlc2lkLCBmaWcuc2hvdz0iaGlkZSJ9CiMjIEhlcmUganVzdCBsZXQgYWxsX3BhaXJ3aXNlIHJ1biBvbiBmaWx0ZXJlZCBkYXRhIGFuZCBkbyBpdHMgbm9ybWFsIH4gMCArIGNvbmRpdGlvbiArIGJhdGNoIGFuYWx5c2VzCiMjIEJpemFycmVseSwgc29tZXRpbWVzIGlmIG9uZSBydW5zIHRoaXMsIGl0IGdpdmVzIGFuIGVycm9yICJFcnJvciBpbiAoZnVuY3Rpb24gKGNsYXNzZXMsIGZkZWYsIG10YWJsZSkgOiB1bmFibGUgdG8gZmluZCBhbiBpbmhlcml0ZWQgbWV0aG9kIGZvciBmdW5jdGlvbiAnUlVWcicgZm9yIHNpZ25hdHVyZSAnIm1hdHJpeCIsICJsb2dpY2FsIiwgIm51bWVyaWMiLCAiTlVMTCInIiAgLS0gaG93ZXZlciwgaWYgb25lIHRoZW4gc2ltcGx5IHJ1bnMgaXQgYWdhaW4gaXQgd29ya3MgZmluZS4KIyMgSSBhbSBnb2luZyB0byBhc3N1bWUgdGhhdCBpdCBpcyBiZWNhdXNlIEkgZG8gbm90IGV4cGxpY2l0bHkgaW52b2tlIHRoZSBsaWJyYXJ5LgpsaWJyYXJ5KHJ1dikgICMjIGhvcGVmdWxseSBhIHNtYWxsIGNvZGUgY2hhbmdlIG1hZGUgdGhpcyBub3QgbmVlZGVkLgp0ZXN0bWUgPC0gZ2V0X21vZGVsX2FkanVzdChkYXRhPW1hY3JvX2xvd2ZpbHQsIGVzdGltYXRlX3R5cGU9InJ1dl9yZXNpZHVhbHMiKQptYWNyb19ydXZyZXMgPC0gc20oYWxsX3BhaXJ3aXNlKGlucHV0PW1hY3JvX2xvd2ZpbHQsIG1vZGVsX2JhdGNoPSJydXZfcmVzaWR1YWxzIikpCm1lZGlhbnNfYnlfY29uZGl0aW9uIDwtIG1hY3JvX3J1dnJlcyRiYXNpYyRtZWRpYW5zCm1hY3JvX3J1dnJlc190YWJsZXMgPC0gc20oY29tYmluZV9kZV90YWJsZXMobWFjcm9fcnV2cmVzLCBleGNlbD1wYXN0ZTAoImV4Y2VsL21hY3JvcGhhZ2VfcnV2cmVzLXYiLCB2ZXIsICIueGxzeCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlZXBlcnM9bXlfY29udHJhc3RzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4dHJhX2Fubm90PW1lZGlhbnNfYnlfY29uZGl0aW9uKSkKbWFjcm9fcnV2cmVzX3NpZyA8LSBzbShleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKG1hY3JvX3J1dnJlc190YWJsZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbD1wYXN0ZTAoImV4Y2VsL21hY3JvcGhhZ2VfcnV2cmVzX3NpZ25pZmljYW50LXYiLCB2ZXIsICIueGxzeCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcF90eXBlPSJ1bmFkanVzdGVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjY29yZGluZ190bz0iYWxsIikpCmBgYAoKIyMgQmF0Y2ggY29ycmVjdGlvbiB3aXRoIHBjYQoKYGBge3IgbWFjcm9fcGNhLCBmaWcuc2hvdz0iaGlkZSJ9CiMjIEhlcmUganVzdCBsZXQgYWxsX3BhaXJ3aXNlIHJ1biBvbiBmaWx0ZXJlZCBkYXRhIGFuZCBkbyBpdHMgbm9ybWFsIH4gMCArIGNvbmRpdGlvbiArIGJhdGNoIGFuYWx5c2VzCm1hY3JvX3BjYSA8LSBzbShhbGxfcGFpcndpc2UoaW5wdXQ9bWFjcm9fbG93ZmlsdCwgbW9kZWxfYmF0Y2g9InBjYSIpKQptZWRpYW5zX2J5X2NvbmRpdGlvbiA8LSBtYWNyb19wY2EkYmFzaWMkbWVkaWFucwptYWNyb19wY2FfdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKG1hY3JvX3BjYSwgZXhjZWw9cGFzdGUwKCJleGNlbC9tYWNyb3BoYWdlX3BjYS12IiwgdmVyLCAiLnhsc3giKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZWVwZXJzPW15X2NvbnRyYXN0cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHRyYV9hbm5vdD1tZWRpYW5zX2J5X2NvbmRpdGlvbikpCm1hY3JvX3BjYV9zaWcgPC0gc20oZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcyhtYWNyb19wY2FfdGFibGVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9cGFzdGUwKCJleGNlbC9tYWNyb3BoYWdlX3BjYV9zaWduaWZpY2FudC12IiwgdmVyLCAiLnhsc3giKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBfdHlwZT0idW5hZGp1c3RlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY2NvcmRpbmdfdG89ImFsbCIpKQpgYGAKCiMjIEJhdGNoIGNvcnJlY3Rpb24gd2l0aCBydXYgZW1waXJpY2FsCgpgYGB7ciBtYWNyb19ydXZlbXAsIGZpZy5zaG93PSJoaWRlIn0KIyMgSGVyZSBqdXN0IGxldCBhbGxfcGFpcndpc2UgcnVuIG9uIGZpbHRlcmVkIGRhdGEgYW5kIGRvIGl0cyBub3JtYWwgfiAwICsgY29uZGl0aW9uICsgYmF0Y2ggYW5hbHlzZXMKbWFjcm9fcnV2ZW1wIDwtIHNtKGFsbF9wYWlyd2lzZShpbnB1dD1tYWNyb19sb3dmaWx0LCBtb2RlbF9iYXRjaD0icnV2X2VtcGlyaWNhbCIpKQptZWRpYW5zX2J5X2NvbmRpdGlvbiA8LSBtYWNyb19ydXZlbXAkYmFzaWMkbWVkaWFucwptYWNyb19ydXZlbXBfdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKG1hY3JvX3J1dmVtcCwgZXhjZWw9cGFzdGUwKCJleGNlbC9tYWNyb3BoYWdlX3J1dmVtcC12IiwgdmVyLCAiLnhsc3giKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZWVwZXJzPW15X2NvbnRyYXN0cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHRyYV9hbm5vdD1tZWRpYW5zX2J5X2NvbmRpdGlvbikpCm1hY3JvX3J1dmVtcF9zaWcgPC0gc20oZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcyhtYWNyb19ydXZlbXBfdGFibGVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9cGFzdGUwKCJleGNlbC9tYWNyb3BoYWdlX3J1dmVtcF9zaWduaWZpY2FudC12IiwgdmVyLCAiLnhsc3giKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBfdHlwZT0idW5hZGp1c3RlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY2NvcmRpbmdfdG89ImFsbCIpKQpgYGAKCiMjIEJhdGNoIGNvcnJlY3Rpb24gd2l0aCBjb21iYXQKClRoZW4gcmVwZWF0IHdpdGggdGhlIGJhdGNoLWNvcnJlY3RlZCBkYXRhIGFuZCBzZWUgdGhlIGRpZmZlcmVuY2VzLgoKYGBge3IgcmVwZWF0X3BhaXJ3aXNlX2JhdGNoLCBmaWcuc2hvdz0iaGlkZSJ9Cm1hY3JvX2NvbWJhdCA8LSBzbShhbGxfcGFpcndpc2UoaW5wdXQ9bWFjcm9fY29tYmF0X25vcm0sIGZvcmNlPVRSVUUpKQptZWRpYW5zX2J5X2NvbmRpdGlvbiA8LSBtYWNyb19jb21iYXQkYmFzaWMkbWVkaWFucwptYWNyb19jb21iYXRfdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKG1hY3JvX2NvbWJhdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbD1wYXN0ZTAoImV4Y2VsL21hY3JvcGhhZ2VfY29tYmF0LXYiLCB2ZXIsICIueGxzeCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlZXBlcnM9bXlfY29udHJhc3RzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4dHJhX2Fubm90PW1lZGlhbnNfYnlfY29uZGl0aW9uKSkKbWFjcm9fY29tYmF0X3NpZyA8LSBzbShleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKG1hY3JvX2NvbWJhdF90YWJsZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbD1wYXN0ZTAoImV4Y2VsL21hY3JvcGhhZ2VfY29tYmF0X3NpZ25pZmljYW50LXYiLCB2ZXIsICIueGxzeCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcF90eXBlPSJ1bmFkanVzdGVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjY29yZGluZ190bz0iYWxsIikpCmBgYAoKYGBge3IgZmluaXNoZWRfbWFfcGxvdHN9Cm1hY3JvX2NvbWJhdF9tYV9saW1tYSA8LSBsaW1tYV9tYShvdXRwdXQ9bWFjcm9fY29tYmF0LCB0YWJsZT0ibWFjcm9fc2hfdnNfbWFjcm9fY2giKQpwbmcoZmlsZT0iaW1hZ2VzL21hY3JvX2NvbWJhdF9tYS1saW1tYS5wbmciKQptYWNyb19jb21iYXRfbWFfbGltbWEkcGxvdApkZXYub2ZmKCkKbWFjcm9fY29tYmF0X21hX2VkZ2VyIDwtIGVkZ2VyX21hKG91dHB1dD1tYWNyb19jb21iYXQsIHRhYmxlPSJtYWNyb19zaF92c19tYWNyb19jaCIpCnBuZyhmaWxlPSJpbWFnZXMvbWFjcm9fY29tYmF0X21hLWVkZ2VyLnBuZyIpCm1hY3JvX2NvbWJhdF9tYV9lZGdlciRwbG90CmRldi5vZmYoKQptYWNyb19jb21iYXRfbWFfZGVzZXEgPC0gZGVzZXFfbWEob3V0cHV0PW1hY3JvX2NvbWJhdCwgdGFibGU9Im1hY3JvX3NoX3ZzX21hY3JvX2NoIikKcG5nKGZpbGU9ImltYWdlcy9tYWNyb19jb21iYXRfbWEtZGVzZXEucG5nIikKbWFjcm9fY29tYmF0X21hX2Rlc2VxJHBsb3QKZGV2Lm9mZigpCmBgYAoKIyBGaWd1cmUgb3V0IGhvdyB0byBjb21wYXJlIHRoZXNlIHJlc3VsdHMKCkkgaGF2ZSA0IG1ldGhvZHMgb2YgcGVyZm9ybWluZyB0aGlzIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzLiAgRWFjaCBvbmUgY29tZXMgd2l0aCBhIHNldCBvZgptZXRyaWNzIGRlZmluaW5nICdzaWduaWZpY2FudCcuICBQZXJoYXBzIEkgY2FuIG1ha2UgYSB0YWJsZSBvZiB0aGUgIyBvZiBnZW5lcyBkZWZpbmVkIGFzIHNpZ25pZmljYW50CmJ5IGNvbnRyYXN0IGZvciBlYWNoLiAgSW4gYWRkaXRpb24gaXQgbWF5IGJlIHdvcnRoIHdoaWxlIHRvIGRvIGEgc2NhdHRlciBwbG90cyBvZiB0aGUgbG9nRkNzIGJldHdlZW4KdGhlc2UgY29tcGFyaXNvbnMgYW5kIHNlZSBob3cgd2VsbCB0aGV5IGFncmVlPwoKIyBMb29rIGZpcnN0IGF0IHRoZSBkZSBjb3VudHMKCmBgYHtyIGNvbXBhcmVfZGVfc2V0dXB9Cm1hY3JvX25vYmF0Y2hfc2lnJGxpbW1hJGNvdW50cwptYWNyb19iYXRjaF9zaWckbGltbWEkY291bnRzCm1hY3JvX3N2YV9zaWckbGltbWEkY291bnRzCm1hY3JvX3J1dnJlc19zaWckbGltbWEkY291bnRzCm1hY3JvX3BjYV9zaWckbGltbWEkY291bnRzCm1hY3JvX3J1dmVtcF9zaWckbGltbWEkY291bnRzCm1hY3JvX2NvbWJhdF9zaWckbGltbWEkY291bnRzCmBgYAoKIyMgQ29tcGFyZSBEZVNlcSAvIEJhc2ljIHdpdGhvdXQgYmF0Y2ggaW4gbW9kZWwKCmBgYHtyIGJhc2ljX2Rlc2VxX25vYmF0Y2h9Cm5vYmF0Y2hfYmFzaWMgPC0gbWVyZ2UobWFjcm9fbm9iYXRjaCRkZXNlcSRhbGxfdGFibGVzJG1hY3JvX3NoX3ZzX21hY3JvX2NoLCBtYWNyb19iYXRjaCRiYXNpYyRhbGxfdGFibGVzJG1hY3JvX3NoX3ZzX21hY3JvX2NoLCBieT0icm93Lm5hbWVzIikKcm93bmFtZXMobm9iYXRjaF9iYXNpYykgPC0gbm9iYXRjaF9iYXNpY1tbIlJvdy5uYW1lcyJdXQpub2JhdGNoX2xvZ2ZjIDwtIG5vYmF0Y2hfYmFzaWNbLCBjKCJsb2dGQy54IiwibG9nRkMueSIpXQpjb2xuYW1lcyhub2JhdGNoX2xvZ2ZjKSA8LSBjKCJub2JhdGNoIiwiYmFzaWMiKQpsZmNfbmJfYiA8LSBzbShwbG90X2xpbmVhcl9zY2F0dGVyKG5vYmF0Y2hfbG9nZmMsIHByZXR0eV9jb2xvcnM9RkFMU0UpKQpsZmNfbmJfYiRzY2F0dGVyCmxmY19uYl9iJGNvcnJlbGF0aW9uCm5vYmF0Y2hfcCA8LSBub2JhdGNoX2Jhc2ljWywgYygiUC5WYWx1ZSIsInAiKV0Kbm9iYXRjaF9wW1syXV0gPC0gYXMubnVtZXJpYyhub2JhdGNoX3BbWzJdXSkKY29sbmFtZXMobm9iYXRjaF9wKSA8LSBjKCJub2JhdGNoIiwiYmFzaWMiKQpub2JhdGNoX3AgPC0gLTEgKiBsb2cobm9iYXRjaF9wKQpwX25iX2IgPC0gc20ocGxvdF9saW5lYXJfc2NhdHRlcihub2JhdGNoX3AsIHByZXR0eV9jb2xvcnM9RkFMU0UpKQpwX25iX2Ikc2NhdHRlcgpwX25iX2IkY29ycmVsYXRpb24KYGBgCgojIyBDb21wYXJlIFNWQSB0byBiYXRjaCBpbiBtb2RlbCwgREVTZXEKCmBgYHtyIGRlc2VxX3N2YV9iYXRjaH0Kc3ZhX2JhdGNoIDwtIG1lcmdlKG1hY3JvX3N2YSRkZXNlcSRhbGxfdGFibGVzJG1hY3JvX3NoX3ZzX21hY3JvX2NoLCBtYWNyb19iYXRjaCRkZXNlcSRhbGxfdGFibGVzJG1hY3JvX3NoX3ZzX21hY3JvX2NoLCBieT0icm93Lm5hbWVzIikKcm93bmFtZXMoc3ZhX2JhdGNoKSA8LSBzdmFfYmF0Y2hbWyJSb3cubmFtZXMiXV0Kc3ZhX2xvZ2ZjIDwtIHN2YV9iYXRjaFssIGMoImxvZ0ZDLngiLCJsb2dGQy55IildCmNvbG5hbWVzKHN2YV9sb2dmYykgPC0gYygic3ZhIiwiYmF0Y2giKQpsZmNfYl9zIDwtIHNtKHBsb3RfbGluZWFyX3NjYXR0ZXIoc3ZhX2xvZ2ZjLCBwcmV0dHlfY29sb3JzPUZBTFNFKSkKbGZjX2JfcyRzY2F0dGVyCmxmY19iX3MkY29ycmVsYXRpb24KYGBgCgojIyMgSW5jbHVkZSBwLXZhbHVlIGVzdGltYXRpb25zCgpUcnkgcHV0dGluZyBzb21lIGluZm9ybWF0aW9uIG9mIHRoZSBwLXZhbHVlcyB3aXRoIHRoZSBjb21wYXJhdGl2ZSBsb2cyZmMKCmBgYHtyIGwyZnNfcHZhbHN9CmxmY3BfYl9zIDwtIHN2YV9iYXRjaFssIGMoImxvZ0ZDLngiLCAibG9nRkMueSIsICJQLlZhbHVlLngiLCAiUC5WYWx1ZS55IildCmNvbG5hbWVzKGxmY3BfYl9zKSA8LSBjKCJsMmZjc3ZhIiwgImwyZmNiYXRjaCIsICJwc3ZhIiwgInBiYXRjaCIpCmxmY19iX3Mkc2NhdHRlcgpjdXRvZmYgPC0gMC4xCmxmY3BfYl9zJHN0YXRlIDwtIGlmZWxzZShsZmNwX2JfcyRwc3ZhID4gY3V0b2ZmICYgbGZjcF9iX3MkcGJhdGNoID4gY3V0b2ZmLCAiYm90aGluc2lnIiwKICAgICAgICAgICAgICAgICAgaWZlbHNlKGxmY3BfYl9zJHBzdmEgPD0gY3V0b2ZmICYgbGZjcF9iX3MkcGJhdGNoIDw9IGN1dG9mZiwgImJvdGhzaWciLAogICAgICAgICAgICAgICAgICBpZmVsc2UobGZjcF9iX3MkcHN2YSA8PSBjdXRvZmYsICJzdmFzaWciLCAiYmF0Y2hzaWciKSkpCiMjbGZjcF9iX3MkbGZjc3RhdGUgPC0gaWZlbHNlKGxmY3BfYl9zJGwyZmNzdmEgPj0gMC43NSAmIGxmY3BfYl9zJGwyZmNiYXRjaCwgIiIsICIiKQpudW1fYm90aGluc2lnIDwtIHN1bShsZmNwX2JfcyRzdGF0ZSA9PSAiYm90aGluc2lnIikKbnVtX2JvdGhzaWcgPC0gc3VtKGxmY3BfYl9zJHN0YXRlID09ICJib3Roc2lnIikKbnVtX3N2YXNpZyA8LSBzdW0obGZjcF9iX3Mkc3RhdGUgPT0gInN2YXNpZyIpCm51bV9iYXRjaHNpZyA8LSBzdW0obGZjcF9iX3Mkc3RhdGUgPT0gImJhdGNoc2lnIikKCmxpYnJhcnkoZ2dwbG90MikKYWVzX2NvbG9yID0gIihsMmZjc3ZhID49IDAuNzUgfCBsMmZjc3ZhIDw9IC0wLjc1IHwgbDJmY2JhdGNoID49IDAuNzUgfCBsMmZjYmF0Y2ggPD0gLTAuNzUpIgoKcGx0IDwtIGdncGxvdDI6OmdncGxvdChsZmNwX2JfcywgYWVzX3N0cmluZyh4PSJsMmZjc3ZhIiwgeT0ibDJmY2JhdGNoIikpICsKICAgICMjIGdncGxvdDI6Omdlb21fcG9pbnQoc3RhdD0iaWRlbnRpdHkiLCBzaXplPTIsIGFscGhhPTAuMiwgYWVzX3N0cmluZyhzaGFwZT0iYXMuZmFjdG9yKGFlc19jb2xvcikiLCBjb2xvdXI9ImFzLmZhY3RvcihzdGF0ZSkiLCBmaWxsPSJhcy5mYWN0b3Ioc3RhdGUpIikpICsKICAgIGdncGxvdDI6Omdlb21fYWJsaW5lKGNvbG91cj0iYmx1ZSIsIHNsb3BlPTEsIGludGVyY2VwdD0wLCBzaXplPTAuNSkgKwogICAgZ2dwbG90Mjo6Z2VvbV9obGluZSh5aW50ZXJjZXB0PWMoLTAuNzUsIDAuNzUpLCBjb2xvcj0icmVkIiwgc2l6ZT0wLjUpICsKICAgIGdncGxvdDI6Omdlb21fdmxpbmUoeGludGVyY2VwdD1jKC0wLjc1LCAwLjc1KSwgY29sb3I9InJlZCIsIHNpemU9MC41KSArCiAgICBnZ3Bsb3QyOjpnZW9tX3BvaW50KHN0YXQ9ImlkZW50aXR5Iiwgc2l6ZT0yLCBhbHBoYT0wLjIsIGFlc19zdHJpbmcoY29sb3VyPSJhcy5mYWN0b3Ioc3RhdGUpIiwgZmlsbD0iYXMuZmFjdG9yKHN0YXRlKSIpKSArCiAgICBnZ3Bsb3QyOjpzY2FsZV9jb2xvcl9tYW51YWwobmFtZT0ic3RhdGUiLCB2YWx1ZXM9YygiYm90aGluc2lnIj0iZ3JleSIsICJib3Roc2lnIj0iZm9yZXN0Z3JlZW4iLCAic3Zhc2lnIj0iZGFya3JlZCIsICJiYXRjaHNpZyI9ImRhcmtibHVlIikpICsKICAgIGdncGxvdDI6OnNjYWxlX2ZpbGxfbWFudWFsKG5hbWU9InN0YXRlIiwgdmFsdWVzPWMoImJvdGhpbnNpZyI9ImdyZXkiLCAiYm90aHNpZyI9ImZvcmVzdGdyZWVuIiwgInN2YXNpZyI9ImRhcmtyZWQiLCAiYmF0Y2hzaWciPSJkYXJrYmx1ZSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKCJCb3RoIEluU2lnLjogIiwgbnVtX2JvdGhpbnNpZyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKCJCb3RoIFNpZy46ICIsIG51bV9ib3Roc2lnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAoIlN2YSBTaWcuOiAiLCBudW1fc3Zhc2lnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAoIkJhdGNoIFNpZy46ICIsIG51bV9iYXRjaHNpZykpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGU9Z2dwbG90Mjo6Z3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcz1hZXMoc2l6ZT0zLCBmaWxsPSJncmV5IikpKSArCiAgICBnZ3Bsb3QyOjpndWlkZXMoZmlsbD1nZ3Bsb3QyOjpndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzPWxpc3Qoc2l6ZT0zKSkpICsKICAgIGdncGxvdDI6OnRoZW1lX2J3KCkKcGx0CmBgYAoKIyMgQ29tcGFyZSBydXZyZXNpZCB0byBiYXRjaCBpbiBtb2RlbCwgREVTZXEKCmBgYHtyIGJhdGNoX3J1dnJlc2lkX2Rlc2VxfQpiYXRjaF9ydXZyZXNpZF9kZXNlcSA8LSBtZXJnZShtYWNyb19ydXZyZXMkZGVzZXEkYWxsX3RhYmxlcyRtYWNyb19zaF92c19tYWNyb19jaCwgbWFjcm9fYmF0Y2gkYmFzaWMkYWxsX3RhYmxlcyRtYWNyb19zaF92c19tYWNyb19jaCwgYnk9InJvdy5uYW1lcyIpCnJvd25hbWVzKGJhdGNoX3J1dnJlc2lkX2Rlc2VxKSA8LSBiYXRjaF9ydXZyZXNpZF9kZXNlcVtbIlJvdy5uYW1lcyJdXQpiYXRjaF9ydXZyZXNpZF9sb2dmYyA8LSBiYXRjaF9ydXZyZXNpZF9kZXNlcVssIGMoImxvZ0ZDLngiLCJsb2dGQy55IildCmNvbG5hbWVzKGJhdGNoX3J1dnJlc2lkX2xvZ2ZjKSA8LSBjKCJub2JhdGNoIiwiYmFzaWMiKQpsZmNfcnV2X2JhdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGJhdGNoX3J1dnJlc2lkX2xvZ2ZjLCBwcmV0dHlfY29sb3JzPUZBTFNFKQpsZmNfcnV2X2JhdCRzY2F0dGVyCmxmY19ydXZfYmF0JGNvcnJlbGF0aW9uCmBgYAoKIyMgQ29tcGFyZSBwY2EgdG8gYmF0Y2ggaW4gbW9kZWwsIERFU2VxCgpgYGB7ciBiYXRjaF9wY2FfZGVzZXF9CmJhdGNoX3BjYV9kZXNlcSA8LSBtZXJnZShtYWNyb19wY2EkZGVzZXEkYWxsX3RhYmxlcyRtYWNyb19zaF92c19tYWNyb19jaCwgbWFjcm9fYmF0Y2gkYmFzaWMkYWxsX3RhYmxlcyRtYWNyb19zaF92c19tYWNyb19jaCwgYnk9InJvdy5uYW1lcyIpCnJvd25hbWVzKGJhdGNoX3BjYV9kZXNlcSkgPC0gYmF0Y2hfcGNhX2Rlc2VxW1siUm93Lm5hbWVzIl1dCmJhdGNoX3BjYV9sb2dmYyA8LSBiYXRjaF9wY2FfZGVzZXFbLCBjKCJsb2dGQy54IiwibG9nRkMueSIpXQpjb2xuYW1lcyhiYXRjaF9wY2FfbG9nZmMpIDwtIGMoIm5vYmF0Y2giLCJiYXNpYyIpCmxmY19wY2FfYmF0IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoYmF0Y2hfcGNhX2xvZ2ZjLCBwcmV0dHlfY29sb3JzPUZBTFNFKQpsZmNfcGNhX2JhdCRzY2F0dGVyCmxmY19wY2FfYmF0JGNvcnJlbGF0aW9uCmBgYAoKIyMgQ29tcGFyZSBydXYgZW1waXJpY2FsIHRvIGJhdGNoIGluIG1vZGVsLCBERVNlcQoKYGBge3IgYmF0Y2hfcnV2ZW1wX2Rlc2VxfQpiYXRjaF9ydXZlbXBfZGVzZXEgPC0gbWVyZ2UobWFjcm9fcnV2ZW1wJGRlc2VxJGFsbF90YWJsZXMkbWFjcm9fc2hfdnNfbWFjcm9fY2gsIG1hY3JvX2JhdGNoJGJhc2ljJGFsbF90YWJsZXMkbWFjcm9fc2hfdnNfbWFjcm9fY2gsIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhiYXRjaF9ydXZlbXBfZGVzZXEpIDwtIGJhdGNoX3J1dmVtcF9kZXNlcVtbIlJvdy5uYW1lcyJdXQpiYXRjaF9ydXZlbXBfbG9nZmMgPC0gYmF0Y2hfcnV2ZW1wX2Rlc2VxWywgYygibG9nRkMueCIsImxvZ0ZDLnkiKV0KY29sbmFtZXMoYmF0Y2hfcnV2ZW1wX2xvZ2ZjKSA8LSBjKCJub2JhdGNoIiwiYmFzaWMiKQpsZmNfcnV2ZW1wX2JhdCA8LSBzbShwbG90X2xpbmVhcl9zY2F0dGVyKGJhdGNoX3J1dmVtcF9sb2dmYywgcHJldHR5X2NvbG9ycz1GQUxTRSkpCmxmY19ydXZlbXBfYmF0JHNjYXR0ZXIKbGZjX3J1dmVtcF9iYXQkY29ycmVsYXRpb24KYGBgCgojIyBDb21wYXJlIGNvbWJhdCB0byBiYXRjaCBpbiBtb2RlbCwgREVTZXEKCmBgYHtyIGNvbXBhcmVfYmF0Y2hfY29tYmF0fQpjb21iYXRfYmF0Y2ggPC0gbWVyZ2UobWFjcm9fY29tYmF0JGRlc2VxJGFsbF90YWJsZXMkbWFjcm9fc2hfdnNfbWFjcm9fY2gsIG1hY3JvX2JhdGNoJGRlc2VxJGFsbF90YWJsZXMkbWFjcm9fc2hfdnNfbWFjcm9fY2gsIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhjb21iYXRfYmF0Y2gpIDwtIGNvbWJhdF9iYXRjaFtbIlJvdy5uYW1lcyJdXQpjb21iYXRfYmF0Y2ggPC0gY29tYmF0X2JhdGNoWywgYygibG9nRkMueCIsImxvZ0ZDLnkiKV0KY29sbmFtZXMoY29tYmF0X2JhdGNoKSA8LSBjKCJiYXRjaCIsImNvbWJhdCIpCmJfYyA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGNvbWJhdF9iYXRjaCwgcHJldHR5X2NvbG9ycz1GQUxTRSkKYl9jJHNjYXR0ZXIKYl9jJGNvcnJlbGF0aW9uCmBgYAoKIyMgQ29tcGFyZSBubyBiYXRjaCB0byBiYXRjaCBpbiBtb2RlbCwgbGltbWEKCmBgYHtyIGNvbXBhcmVfYmF0Y2hfbm9iYXRjaF9saW1tYX0Kbm9iYXRjaF9iYXRjaCA8LSBtZXJnZShtYWNyb19ub2JhdGNoJGxpbW1hJGFsbF90YWJsZXMkbWFjcm9fc2hfdnNfbWFjcm9fY2gsIG1hY3JvX2JhdGNoJGxpbW1hJGFsbF90YWJsZXMkbWFjcm9fc2hfdnNfbWFjcm9fY2gsIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhub2JhdGNoX2JhdGNoKSA8LSBub2JhdGNoX2JhdGNoW1siUm93Lm5hbWVzIl1dCm5vYmF0Y2hfYmF0Y2ggPC0gbm9iYXRjaF9iYXRjaFssIGMoImxvZ0ZDLngiLCJsb2dGQy55IildCmNvbG5hbWVzKG5vYmF0Y2hfYmF0Y2gpIDwtIGMoIm5vYmF0Y2giLCJiYXRjaCIpCm5iX2IgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihub2JhdGNoX2JhdGNoLCBwcmV0dHlfY29sb3JzPUZBTFNFKQpuYl9iJHNjYXR0ZXIKbmJfYiRjb3JyZWxhdGlvbgpgYGAKCiMjIEJhdGNoIGluIG1vZGVsIHZzLiBTVkEsIGxpbW1hCgpgYGB7ciBjb21wYXJlX2JhdGNoX3N2YV9saW1tYX0KYmF0Y2hfc3ZhIDwtIG1lcmdlKG1hY3JvX2JhdGNoJGxpbW1hJGFsbF90YWJsZXMkbWFjcm9fc2hfdnNfbWFjcm9fY2gsIG1hY3JvX3N2YSRsaW1tYSRhbGxfdGFibGVzJG1hY3JvX3NoX3ZzX21hY3JvX2NoLCBieT0icm93Lm5hbWVzIikKcm93bmFtZXMoYmF0Y2hfc3ZhKSA8LSBiYXRjaF9zdmFbWyJSb3cubmFtZXMiXV0KYmF0Y2hfc3ZhIDwtIGJhdGNoX3N2YVssIGMoImxvZ0ZDLngiLCJsb2dGQy55IildCmNvbG5hbWVzKGJhdGNoX3N2YSkgPC0gYygiYmF0Y2giLCJzdmEiKQpiX3MgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihiYXRjaF9zdmEsIHByZXR0eV9jb2xvcnM9RkFMU0UpCmJfcyRzY2F0dGVyCmJfcyRjb3JyZWxhdGlvbgpgYGAKCiMjIEJhdGNoIGluIG1vZGVsIHZzLiBjb21iYXQsIGxpbW1hCgpgYGB7ciBjb21wYXJlX2JhdGNoX2NvbWJhdF9saW1tYX0KYmF0Y2hfY29tYmF0IDwtIG1lcmdlKG1hY3JvX2JhdGNoJGxpbW1hJGFsbF90YWJsZXMkbWFjcm9fc2hfdnNfbWFjcm9fY2gsIG1hY3JvX2NvbWJhdCRsaW1tYSRhbGxfdGFibGVzJG1hY3JvX3NoX3ZzX21hY3JvX2NoLCBieT0icm93Lm5hbWVzIikKcm93bmFtZXMoYmF0Y2hfY29tYmF0KSA8LSBiYXRjaF9jb21iYXRbWyJSb3cubmFtZXMiXV0KYmF0Y2hfY29tYmF0IDwtIGJhdGNoX2NvbWJhdFssIGMoImxvZ0ZDLngiLCJsb2dGQy55IildCmNvbG5hbWVzKGJhdGNoX2NvbWJhdCkgPC0gYygiYmF0Y2giLCJjb21iYXQiKQpiX2MgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihiYXRjaF9jb21iYXQsIHByZXR0eV9jb2xvcnM9RkFMU0UpCmJfYyRzY2F0dGVyCmJfYyRjb3JyZWxhdGlvbgpgYGAKCiMjIE5vYmF0Y2ggdnMuIGJhdGNoIGluIG1vZGVsLCBlZGdlcgoKYGBge3IgY29tcGFyZV9ub2JhdGNoX2JhdGNoX2VkZ2VyfQpub2JhdGNoX2JhdGNoIDwtIG1lcmdlKG1hY3JvX25vYmF0Y2gkZWRnZXIkYWxsX3RhYmxlcyRtYWNyb19zaF92c19tYWNyb19jaCwgbWFjcm9fYmF0Y2gkZWRnZXIkYWxsX3RhYmxlcyRtYWNyb19zaF92c19tYWNyb19jaCwgYnk9InJvdy5uYW1lcyIpCnJvd25hbWVzKG5vYmF0Y2hfYmF0Y2gpIDwtIG5vYmF0Y2hfYmF0Y2hbWyJSb3cubmFtZXMiXV0Kbm9iYXRjaF9iYXRjaCA8LSBub2JhdGNoX2JhdGNoWywgYygibG9nRkMueCIsImxvZ0ZDLnkiKV0KY29sbmFtZXMobm9iYXRjaF9iYXRjaCkgPC0gYygibm9iYXRjaCIsImJhdGNoIikKbmJfYiA8LSBzbShwbG90X2xpbmVhcl9zY2F0dGVyKG5vYmF0Y2hfYmF0Y2gsIHByZXR0eV9jb2xvcnM9RkFMU0UpKQpuYl9iJHNjYXR0ZXIKbmJfYiRjb3JyZWxhdGlvbgpgYGAKCiMjIEJhdGNoIGluIG1vZGVsIHZzLiBTVkEsIGVkZ2VyCgpgYGB7ciBjb21wYXJlX2JhdGNoX3N2YV9lZGdlcn0KYmF0Y2hfc3ZhIDwtIG1lcmdlKG1hY3JvX2JhdGNoJGVkZ2VyJGFsbF90YWJsZXMkbWFjcm9fc2hfdnNfbWFjcm9fY2gsIG1hY3JvX3N2YSRlZGdlciRhbGxfdGFibGVzJG1hY3JvX3NoX3ZzX21hY3JvX2NoLCBieT0icm93Lm5hbWVzIikKcm93bmFtZXMoYmF0Y2hfc3ZhKSA8LSBiYXRjaF9zdmFbWyJSb3cubmFtZXMiXV0KYmF0Y2hfc3ZhIDwtIGJhdGNoX3N2YVssIGMoImxvZ0ZDLngiLCJsb2dGQy55IildCmNvbG5hbWVzKGJhdGNoX3N2YSkgPC0gYygiYmF0Y2giLCJzdmEiKQpiX3MgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihiYXRjaF9zdmEsIHByZXR0eV9jb2xvcnM9RkFMU0UpCmJfcyRzY2F0dGVyCmJfcyRjb3JyZWxhdGlvbgpgYGAKCiMjIEJhdGNoIGluIG1vZGVsIHZzLiBjb21iYXQsIGVkZ2VyCgpgYGB7ciBjb21wYXJlX2JhdGNoX2NvbWJhdF9lZGdlcn0KYmF0Y2hfY29tYmF0IDwtIG1lcmdlKG1hY3JvX2JhdGNoJGVkZ2VyJGFsbF90YWJsZXMkbWFjcm9fc2hfdnNfbWFjcm9fY2gsIG1hY3JvX2NvbWJhdCRlZGdlciRhbGxfdGFibGVzJG1hY3JvX3NoX3ZzX21hY3JvX2NoLCBieT0icm93Lm5hbWVzIikKcm93bmFtZXMoYmF0Y2hfY29tYmF0KSA8LSBiYXRjaF9jb21iYXRbWyJSb3cubmFtZXMiXV0KYmF0Y2hfY29tYmF0IDwtIGJhdGNoX2NvbWJhdFssIGMoImxvZ0ZDLngiLCJsb2dGQy55IildCmNvbG5hbWVzKGJhdGNoX2NvbWJhdCkgPC0gYygiYmF0Y2giLCJjb21iYXQiKQpiX2MgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihiYXRjaF9jb21iYXQsIHByZXR0eV9jb2xvcnM9RkFMU0UpCmJfYyRzY2F0dGVyCmJfYyRjb3JyZWxhdGlvbgpgYGAKCiMjIENvbXBhcmUgbm9iYXRjaCB2cy4gYmF0Y2gsIGRlc2VxCgpgYGB7ciBjb21wYXJlX25vYmF0Y2hfYmF0Y2hfZGVzZXF9Cm5vYmF0Y2hfYmF0Y2ggPC0gbWVyZ2UobWFjcm9fbm9iYXRjaCRkZXNlcSRhbGxfdGFibGVzJG1hY3JvX3NoX3ZzX21hY3JvX2NoLCBtYWNyb19iYXRjaCRkZXNlcSRhbGxfdGFibGVzJG1hY3JvX3NoX3ZzX21hY3JvX2NoLCBieT0icm93Lm5hbWVzIikKcm93bmFtZXMobm9iYXRjaF9iYXRjaCkgPC0gbm9iYXRjaF9iYXRjaFtbIlJvdy5uYW1lcyJdXQpub2JhdGNoX2JhdGNoIDwtIG5vYmF0Y2hfYmF0Y2hbLCBjKCJsb2dGQy54IiwibG9nRkMueSIpXQpjb2xuYW1lcyhub2JhdGNoX2JhdGNoKSA8LSBjKCJub2JhdGNoIiwiYmF0Y2giKQpuYl9iIDwtIHNtKHBsb3RfbGluZWFyX3NjYXR0ZXIobm9iYXRjaF9iYXRjaCwgcHJldHR5X2NvbG9ycz1GQUxTRSkpCm5iX2Ikc2NhdHRlcgpuYl9iJGNvcnJlbGF0aW9uCmBgYAoKIyMgQ29tcGFyZSBiYXRjaCB2cy4gU1ZBLCBkZXNlcQoKYGBge3IgY29tcGFyZV9iYXRjaF9zdmFfZGVzZXF9CmJhdGNoX3N2YSA8LSBtZXJnZShtYWNyb19iYXRjaCRkZXNlcSRhbGxfdGFibGVzJG1hY3JvX3NoX3ZzX21hY3JvX2NoLCBtYWNyb19zdmEkZGVzZXEkYWxsX3RhYmxlcyRtYWNyb19zaF92c19tYWNyb19jaCwgYnk9InJvdy5uYW1lcyIpCnJvd25hbWVzKGJhdGNoX3N2YSkgPC0gYmF0Y2hfc3ZhW1siUm93Lm5hbWVzIl1dCmJhdGNoX3N2YSA8LSBiYXRjaF9zdmFbLCBjKCJsb2dGQy54IiwibG9nRkMueSIpXQpjb2xuYW1lcyhiYXRjaF9zdmEpIDwtIGMoImJhdGNoIiwic3ZhIikKYl9zIDwtIHNtKHBsb3RfbGluZWFyX3NjYXR0ZXIoYmF0Y2hfc3ZhLCBwcmV0dHlfY29sb3JzPUZBTFNFKSkKYl9zJHNjYXR0ZXIKYl9zJGNvcnJlbGF0aW9uCmBgYAoKIyMgQmF0Y2ggaW4gbW9kZWwgdnMuIGNvbWJhdCwgZGVzZXEKCmBgYHtyIGJhdGNoX2NvbWJhdF9kZXNlcX0KYmF0Y2hfY29tYmF0IDwtIG1lcmdlKG1hY3JvX2JhdGNoJGRlc2VxJGFsbF90YWJsZXMkbWFjcm9fc2hfdnNfbWFjcm9fY2gsIG1hY3JvX2NvbWJhdCRkZXNlcSRhbGxfdGFibGVzJG1hY3JvX3NoX3ZzX21hY3JvX2NoLCBieT0icm93Lm5hbWVzIikKcm93bmFtZXMoYmF0Y2hfY29tYmF0KSA8LSBiYXRjaF9jb21iYXRbWyJSb3cubmFtZXMiXV0KYmF0Y2hfY29tYmF0IDwtIGJhdGNoX2NvbWJhdFssIGMoImxvZ0ZDLngiLCJsb2dGQy55IildCmNvbG5hbWVzKGJhdGNoX2NvbWJhdCkgPC0gYygiYmF0Y2giLCJjb21iYXQiKQpiX2MgPC0gc20ocGxvdF9saW5lYXJfc2NhdHRlcihiYXRjaF9jb21iYXQsIHByZXR0eV9jb2xvcnM9RkFMU0UpKQpiX2Mkc2NhdHRlcgpiX2MkY29ycmVsYXRpb24KYGBgCgpgYGB7ciBzYXZlX21hY3JvX2V4cHJlc3Npb259CnRtcCA8LSBzbShzYXZlbWUoZmlsZW5hbWU9Im1hY3JvcGhhZ2VfZXhwcmVzc2lvbl9odW1hbi5yZGEueHoiKSkKYGBgCgpbaW5kZXguaHRtbF0oaW5kZXguaHRtbCkgW21hY3JvcGhhZ2VfZXN0aW1hdGlvbi5odG1sXShtYWNyb3BoYWdlX2VzdGltYXRpb24uaHRtbCkK