library(ggplot2)
library(ggcorrplot)
library(BioVenn)
library(dplyr)
# Set correct dir
setwd("/s/public_webshare/public/ghga/magnetique-harmonized-rnaseq/nf-core_vs_magnetique//")

Correlation of counts

Example for one sample match

# Load original data
load("../orignal_data/data/MAGNetApp/data/MAGNet.RData")
data_mag <- countData
# Subset for C00039
countC00039_mag <- data_mag[, c("C00039"), drop=F]
colnames(countC00039_mag) <- 'magnetique'
# Repeat for nf-core/rnaseq 
load("../DESeq2/data_prep/MAGNet.RData")
data_nf <- countData
countC00039_nf <- data_nf[, c("C00039"), drop=F]
colnames(countC00039_nf) <- 'nf-core'
# Merge and plot
merge <- merge(countC00039_mag, countC00039_nf, by = "row.names")
ggplot(merge, aes(x = magnetique, y = `nf-core`)) + geom_point(color="#2171b5") + theme_bw() +
  geom_abline(slope=1, intercept=0, linetype="dotted") +
  scale_x_log10() + scale_y_log10()

# correlation
cor(merge$magnetique, merge$`nf-core`)
[1] 0.7970865

All vs all

# save common gene/sample list to subset full data
common_genes <- merge$Row.names
# only choose a subset of common samples
common_samples_30 <- intersect(colnames(data_mag), colnames(data_nf))[1:30]
common_samples_end30 <- tail(intersect(colnames(data_mag), colnames(data_nf)), 30)
data_mag_sub <- data_mag[common_genes, common_samples_30]
data_nf_sub <- data_nf[common_genes, rev(colnames(data_mag_sub))]
# correlation matrix
cor_mat <- cor(data_mag_sub, data_nf_sub)
# plot first 30 samples
ggcorrplot(cor_mat) + scale_fill_gradient2(limit = c(0.5,1), low = "blue", high =  "red", mid = "white", midpoint = 0.75)
Scale for fill is already present.
Adding another scale for fill, which will replace the existing scale.

Using normalised count data

vsd_nf <- readRDS("../DESeq2/harmonized-deseq/harmonized_DESeqTransform_vsd.rds")
vsd_nf_mat <- assay(vsd_nf)
normC00039_nf <- vsd_nf_mat[, c("C00039"), drop=F]
colnames(normC00039_nf) <- 'nf-core'

dds_mag <- readRDS("../DESeq2/magnetiqueCode2022/MAGNet_DESeqDataSet.rds")
vsd_mag <- vst(dds_mag, blind=FALSE)
vsd_mag_mat <- assay(vsd_mag)
normC00039_mag <- vsd_mag_mat[, c("C00039"), drop=F]
colnames(normC00039_mag) <- 'magnetique'
# Merge and plot
merge_norm <- merge(normC00039_mag, normC00039_nf, by = "row.names")
ggplot(merge_norm, aes(x = magnetique, y = `nf-core`)) + geom_point(color="#2171b5") + theme_bw() +
  geom_abline(slope=1, intercept=0, linetype="dotted")

cor(merge_norm$magnetique, merge_norm$`nf-core`)
[1] 0.9833694

All vs all - norm

# save common gene/sample list to subset full data
common_genes <- merge_norm$Row.names
# only choose a subset of common samples
common_samples_30 <- intersect(colnames(vsd_mag_mat), colnames(vsd_nf_mat))[1:30]
common_samples_end30 <- tail(intersect(colnames(vsd_mag_mat), colnames(vsd_nf_mat)), 30)
vsd_mag_sub <- vsd_mag_mat[common_genes, common_samples_30]
vsd_nf_sub <- vsd_nf_mat[common_genes, rev(colnames(vsd_mag_sub))]

# correlation matrix
cor_mat_norm <- cor(vsd_mag_sub, vsd_nf_sub)
# plot first 30 samples
ggcorrplot(cor_mat_norm) + scale_fill_gradient2(limit = c(0.8,1), low = "blue", high =  "red", mid = "white", midpoint = 0.9)
Scale for fill is already present.
Adding another scale for fill, which will replace the existing scale.

PCA plots

# nf-core
pca_plt_nf <- plotPCA(vsd_nf, intgroup=c("Etiology"), returnData = T)
percentVar <- round(100 * attr(pca_plt_nf, "percentVar"))
ggplot(pca_plt_nf, aes(PC1, PC2, color=Etiology)) +
  geom_point(size=3) +
  xlab(paste0("PC1: ",percentVar[1],"% variance")) +
  ylab(paste0("PC2: ",percentVar[2],"% variance")) + 
  coord_fixed() +
  theme_bw()

# Mag
pca_plt_mag <- plotPCA(vsd_mag, intgroup=c("Etiology"), returnData = T)
percentVar <- round(100 * attr(pca_plt_mag, "percentVar"))
ggplot(pca_plt_mag, aes(PC1, PC2, color=Etiology)) +
  geom_point(size=3) +
  xlab(paste0("PC1: ",percentVar[1],"% variance")) +
  ylab(paste0("PC2: ",percentVar[2],"% variance")) + 
  coord_fixed() +
  theme_bw()

Comaprison of DESeq2 results

DCM vs HCM

# load results tables
deseq_DCMvsHCM_nf <- readRDS("../DESeq2/harmonized-deseq/harmonized_DESeqResults.rds")$DCMvsHCM
deseq_DCMvsHCM_mag <- readRDS("../orignal_data/data/MAGNetApp/data/DGE/MAGNet_DCMvsHCM_GeneTonic.rds")$res_de
# filter
DEgenes_DCMvsHCM_mag <- rownames(subset(deseq_DCMvsHCM_mag, padj <= 0.05))
DEgenes_DCMvsHCM_nf <- rownames(subset(deseq_DCMvsHCM_nf, padj <= 0.05))
# compare gene lists
overlap_DCMvsHCM <- data.frame(genes = intersect(DEgenes_DCMvsHCM_mag, DEgenes_DCMvsHCM_nf))
overlap_DCMvsHCM$type <- "overlapping"
nf_DCMvsHCM <- data.frame(genes = setdiff(DEgenes_DCMvsHCM_nf,rownames(overlap_DCMvsHCM)))
nf_DCMvsHCM$type <- "nf-core"
mag_DCMvsHCM <- data.frame(genes = setdiff(DEgenes_DCMvsHCM_mag,rownames(overlap_DCMvsHCM)))
mag_DCMvsHCM$type <- "Magnetique"
DCMvsHCM <- rbind(overlap_DCMvsHCM, nf_DCMvsHCM, mag_DCMvsHCM)
paste0("Proportion overlapping DE genes DCMvsHCM: ", nrow(overlap_DCMvsHCM)/nrow(DEgenes_DCMvsHCM_mag))
[1] "Proportion overlapping DE genes DCMvsHCM: "
# venn
biovenn <- draw.venn(DEgenes_DCMvsHCM_mag, DEgenes_DCMvsHCM_nf, NULL, title="DCM vs HCM", nrtype="abs", subtitle = NULL, xtitle = "Magnetique", ytitle = "nf-core")
[1] "x total: 201"
[1] "y total: 149"
[1] "z total: 0"
[1] "x only: 80"
[1] "y only: 28"
[1] "z only: 0"
[1] "x-y total overlap: 121"
[1] "x-z total overlap: 0"
[1] "y-z total overlap: 0"
[1] "x-y only overlap: 121"
[1] "x-z only overlap: 0"
[1] "y-z only overlap: 0"
[1] "x-y-z overlap: 0"

# 
ggplot(deseq_DCMvsHCM_merge_df, aes(x=log2FoldChange, group=type, color=type, fill=type)) + 
  geom_density(alpha=0.6) + 
  theme_bw() +
    guides(color = "none") +
  xlim(c(-3,3)) +
  facet_grid(~method)

ggplot(deseq_DCMvsHCM_merge_df, aes(x=baseMean, group=type, color=type, fill=type)) + 
  geom_density(alpha=0.6) + 
  theme_bw() +
    guides(color = "none") +
  xlim(c(10, 1000)) +
  facet_grid(~method, scales = "free_y")

DCM vs NFD

# load results tables
deseq_DCMvsNFD_nf <- readRDS("../DESeq2/harmonized-deseq/harmonized_DESeqResults.rds")$DCMvsNFD
deseq_DCMvsNFD_mag <- readRDS("../orignal_data/data/MAGNetApp/data/DGE/MAGNet_DCMvsNFD_GeneTonic.rds")$res_de
# filter
DEgenes_DCMvsNFD_mag <- rownames(subset(deseq_DCMvsNFD_mag, padj <= 0.05))
DEgenes_DCMvsNFD_nf <- rownames(subset(deseq_DCMvsNFD_nf, padj <= 0.05))
# compare gene lists
overlap_DCMvsNFD <- data.frame(genes = intersect(DEgenes_DCMvsNFD_mag, DEgenes_DCMvsNFD_nf))
overlap_DCMvsNFD$type <- "overlapping"
nf_DCMvsNFD <- data.frame(genes = setdiff(DEgenes_DCMvsNFD_nf,rownames(overlap_DCMvsNFD)))
nf_DCMvsNFD$type <- "nf-core"
mag_DCMvsNFD <- data.frame(genes = setdiff(DEgenes_DCMvsNFD_mag,rownames(overlap_DCMvsNFD)))
mag_DCMvsNFD$type <- "Magnetique"
DCMvsNFD <- rbind(overlap_DCMvsNFD, nf_DCMvsNFD, mag_DCMvsNFD)
paste0("Proportion overlapping DE genes DCMvsNFD: ", nrow(overlap_DCMvsNFD)/nrow(DEgenes_DCMvsNFD_mag))
[1] "Proportion overlapping DE genes DCMvsNFD: "
# venn
biovenn <- draw.venn(DEgenes_DCMvsNFD_mag, DEgenes_DCMvsNFD_nf, NULL, title="DCM vs NFD", nrtype="abs", subtitle = NULL, xtitle = "Magnetique", ytitle = "nf-core")
[1] "x total: 16562"
[1] "y total: 16722"
[1] "z total: 0"
[1] "x only: 2335"
[1] "y only: 2495"
[1] "z only: 0"
[1] "x-y total overlap: 14227"
[1] "x-z total overlap: 0"
[1] "y-z total overlap: 0"
[1] "x-y only overlap: 14227"
[1] "x-z only overlap: 0"
[1] "y-z only overlap: 0"
[1] "x-y-z overlap: 0"

ggplot(deseq_DCMvsNFD_merge_df, aes(x=log2FoldChange, group=type, color=type, fill=type)) + 
  geom_density(alpha=0.6) + 
  theme_bw() +
    guides(color = "none") +
  xlim(c(-3,3)) +
  facet_wrap(~method)

ggplot(deseq_DCMvsNFD_merge_df, aes(x=baseMean, group=type, color=type, fill=type)) + 
  geom_density(alpha=0.6) + 
  theme_bw() +
    guides(color = "none") +
  xlim(c(1,100)) +
  facet_wrap(~method)

HCM vs NFD

# load results tables
deseq_HCMvsNFD_nf <- readRDS("../DESeq2/harmonized-deseq/harmonized_DESeqResults.rds")$HCMvsNFD
deseq_HCMvsNFD_mag <- readRDS("../orignal_data/data/MAGNetApp/data/DGE/MAGNet_HCMvsNFD_GeneTonic.rds")$res_de
# filter
DEgenes_HCMvsNFD_mag <- rownames(subset(deseq_HCMvsNFD_mag, padj <= 0.05))
DEgenes_HCMvsNFD_nf <- rownames(subset(deseq_HCMvsNFD_nf, padj <= 0.05))
# compare gene lists
overlap_HCMvsNFD <- intersect(DEgenes_HCMvsNFD_mag, DEgenes_HCMvsNFD_nf)
paste0("Proportion overlapping DE genes HCMvsNFD: ", length(overlap_HCMvsNFD)/length(DEgenes_HCMvsNFD_nf))
[1] "Proportion overlapping DE genes HCMvsNFD: 0.828318108543794"
# venn
biovenn <- draw.venn(DEgenes_HCMvsNFD_mag, DEgenes_HCMvsNFD_nf, NULL, title="HCM vs NFD", nrtype="abs", subtitle = NULL, xtitle = "Magnetique", ytitle = "nf-core")
[1] "x total: 10607"
[1] "y total: 11166"
[1] "z total: 0"
[1] "x only: 1358"
[1] "y only: 1917"
[1] "z only: 0"
[1] "x-y total overlap: 9249"
[1] "x-z total overlap: 0"
[1] "y-z total overlap: 0"
[1] "x-y only overlap: 9249"
[1] "x-z only overlap: 0"
[1] "y-z only overlap: 0"
[1] "x-y-z overlap: 0"

length(intersect(DEgenes_HCMvsNFD_mag, DEgenes_HCMvsNFD_nf))
[1] 9249
LS0tCnRpdGxlOiAiQ29tcGFyaXNvbiBvZiBnZW5lIGNvdW50cyBhbmQgREVTZXEgcmVzdWx0czogTWFnZW5ldGlxdWUgdnMuIG5mLWNvcmUvcm5hc2VxIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdnY29ycnBsb3QpCmxpYnJhcnkoQmlvVmVubikKbGlicmFyeShkcGx5cikKYGBgCgpgYGB7cn0KIyBTZXQgY29ycmVjdCBkaXIKc2V0d2QoIi9zL3B1YmxpY193ZWJzaGFyZS9wdWJsaWMvZ2hnYS9tYWduZXRpcXVlLWhhcm1vbml6ZWQtcm5hc2VxL25mLWNvcmVfdnNfbWFnbmV0aXF1ZS8vIikKYGBgCgojIyBDb3JyZWxhdGlvbiBvZiBjb3VudHMKIyMjIEV4YW1wbGUgZm9yIG9uZSBzYW1wbGUgbWF0Y2gKYGBge3J9CiMgTG9hZCBvcmlnaW5hbCBkYXRhCmxvYWQoIi4uL29yaWduYWxfZGF0YS9kYXRhL01BR05ldEFwcC9kYXRhL01BR05ldC5SRGF0YSIpCmRhdGFfbWFnIDwtIGNvdW50RGF0YQojIFN1YnNldCBmb3IgQzAwMDM5CmNvdW50QzAwMDM5X21hZyA8LSBkYXRhX21hZ1ssIGMoIkMwMDAzOSIpLCBkcm9wPUZdCmNvbG5hbWVzKGNvdW50QzAwMDM5X21hZykgPC0gJ21hZ25ldGlxdWUnCmBgYAoKYGBge3J9CiMgUmVwZWF0IGZvciBuZi1jb3JlL3JuYXNlcSAKbG9hZCgiLi4vREVTZXEyL2RhdGFfcHJlcC9NQUdOZXQuUkRhdGEiKQpkYXRhX25mIDwtIGNvdW50RGF0YQpjb3VudEMwMDAzOV9uZiA8LSBkYXRhX25mWywgYygiQzAwMDM5IiksIGRyb3A9Rl0KY29sbmFtZXMoY291bnRDMDAwMzlfbmYpIDwtICduZi1jb3JlJwpgYGAKCgpgYGB7cn0KIyBNZXJnZSBhbmQgcGxvdAptZXJnZSA8LSBtZXJnZShjb3VudEMwMDAzOV9tYWcsIGNvdW50QzAwMDM5X25mLCBieSA9ICJyb3cubmFtZXMiKQpnZ3Bsb3QobWVyZ2UsIGFlcyh4ID0gbWFnbmV0aXF1ZSwgeSA9IGBuZi1jb3JlYCkpICsgZ2VvbV9wb2ludChjb2xvcj0iIzIxNzFiNSIpICsgdGhlbWVfYncoKSArCiAgZ2VvbV9hYmxpbmUoc2xvcGU9MSwgaW50ZXJjZXB0PTAsIGxpbmV0eXBlPSJkb3R0ZWQiKSArCiAgc2NhbGVfeF9sb2cxMCgpICsgc2NhbGVfeV9sb2cxMCgpCmBgYAoKYGBge3J9CiMgY29ycmVsYXRpb24KY29yKG1lcmdlJG1hZ25ldGlxdWUsIG1lcmdlJGBuZi1jb3JlYCkKYGBgCiMjIyBBbGwgdnMgYWxsCmBgYHtyfQojIHNhdmUgY29tbW9uIGdlbmUvc2FtcGxlIGxpc3QgdG8gc3Vic2V0IGZ1bGwgZGF0YQpjb21tb25fZ2VuZXMgPC0gbWVyZ2UkUm93Lm5hbWVzCiMgb25seSBjaG9vc2UgYSBzdWJzZXQgb2YgY29tbW9uIHNhbXBsZXMKY29tbW9uX3NhbXBsZXNfMzAgPC0gaW50ZXJzZWN0KGNvbG5hbWVzKGRhdGFfbWFnKSwgY29sbmFtZXMoZGF0YV9uZikpWzE6MzBdCmNvbW1vbl9zYW1wbGVzX2VuZDMwIDwtIHRhaWwoaW50ZXJzZWN0KGNvbG5hbWVzKGRhdGFfbWFnKSwgY29sbmFtZXMoZGF0YV9uZikpLCAzMCkKZGF0YV9tYWdfc3ViIDwtIGRhdGFfbWFnW2NvbW1vbl9nZW5lcywgY29tbW9uX3NhbXBsZXNfMzBdCmRhdGFfbmZfc3ViIDwtIGRhdGFfbmZbY29tbW9uX2dlbmVzLCByZXYoY29sbmFtZXMoZGF0YV9tYWdfc3ViKSldCgpgYGAKCmBgYHtyfQojIGNvcnJlbGF0aW9uIG1hdHJpeApjb3JfbWF0IDwtIGNvcihkYXRhX21hZ19zdWIsIGRhdGFfbmZfc3ViKQpgYGAKYGBge3J9CiMgcGxvdCBmaXJzdCAzMCBzYW1wbGVzCmdnY29ycnBsb3QoY29yX21hdCkgKyBzY2FsZV9maWxsX2dyYWRpZW50MihsaW1pdCA9IGMoMC41LDEpLCBsb3cgPSAiYmx1ZSIsIGhpZ2ggPSAgInJlZCIsIG1pZCA9ICJ3aGl0ZSIsIG1pZHBvaW50ID0gMC43NSkKYGBgCiMjIyBVc2luZyBub3JtYWxpc2VkIGNvdW50IGRhdGEKYGBge3J9CnZzZF9uZiA8LSByZWFkUkRTKCIuLi9ERVNlcTIvaGFybW9uaXplZC1kZXNlcS9oYXJtb25pemVkX0RFU2VxVHJhbnNmb3JtX3ZzZC5yZHMiKQp2c2RfbmZfbWF0IDwtIGFzc2F5KHZzZF9uZikKbm9ybUMwMDAzOV9uZiA8LSB2c2RfbmZfbWF0WywgYygiQzAwMDM5IiksIGRyb3A9Rl0KY29sbmFtZXMobm9ybUMwMDAzOV9uZikgPC0gJ25mLWNvcmUnCgpkZHNfbWFnIDwtIHJlYWRSRFMoIi4uL0RFU2VxMi9tYWduZXRpcXVlQ29kZTIwMjIvTUFHTmV0X0RFU2VxRGF0YVNldC5yZHMiKQp2c2RfbWFnIDwtIHZzdChkZHNfbWFnLCBibGluZD1GQUxTRSkKdnNkX21hZ19tYXQgPC0gYXNzYXkodnNkX21hZykKbm9ybUMwMDAzOV9tYWcgPC0gdnNkX21hZ19tYXRbLCBjKCJDMDAwMzkiKSwgZHJvcD1GXQpjb2xuYW1lcyhub3JtQzAwMDM5X21hZykgPC0gJ21hZ25ldGlxdWUnCmBgYAoKYGBge3J9CiMgTWVyZ2UgYW5kIHBsb3QKbWVyZ2Vfbm9ybSA8LSBtZXJnZShub3JtQzAwMDM5X21hZywgbm9ybUMwMDAzOV9uZiwgYnkgPSAicm93Lm5hbWVzIikKZ2dwbG90KG1lcmdlX25vcm0sIGFlcyh4ID0gbWFnbmV0aXF1ZSwgeSA9IGBuZi1jb3JlYCkpICsgZ2VvbV9wb2ludChjb2xvcj0iIzIxNzFiNSIpICsgdGhlbWVfYncoKSArCiAgZ2VvbV9hYmxpbmUoc2xvcGU9MSwgaW50ZXJjZXB0PTAsIGxpbmV0eXBlPSJkb3R0ZWQiKQpgYGAKYGBge3J9CmNvcihtZXJnZV9ub3JtJG1hZ25ldGlxdWUsIG1lcmdlX25vcm0kYG5mLWNvcmVgKQpgYGAKIyMjIEFsbCB2cyBhbGwgLSBub3JtCmBgYHtyfQojIHNhdmUgY29tbW9uIGdlbmUvc2FtcGxlIGxpc3QgdG8gc3Vic2V0IGZ1bGwgZGF0YQpjb21tb25fZ2VuZXMgPC0gbWVyZ2Vfbm9ybSRSb3cubmFtZXMKIyBvbmx5IGNob29zZSBhIHN1YnNldCBvZiBjb21tb24gc2FtcGxlcwpjb21tb25fc2FtcGxlc18zMCA8LSBpbnRlcnNlY3QoY29sbmFtZXModnNkX21hZ19tYXQpLCBjb2xuYW1lcyh2c2RfbmZfbWF0KSlbMTozMF0KY29tbW9uX3NhbXBsZXNfZW5kMzAgPC0gdGFpbChpbnRlcnNlY3QoY29sbmFtZXModnNkX21hZ19tYXQpLCBjb2xuYW1lcyh2c2RfbmZfbWF0KSksIDMwKQp2c2RfbWFnX3N1YiA8LSB2c2RfbWFnX21hdFtjb21tb25fZ2VuZXMsIGNvbW1vbl9zYW1wbGVzXzMwXQp2c2RfbmZfc3ViIDwtIHZzZF9uZl9tYXRbY29tbW9uX2dlbmVzLCByZXYoY29sbmFtZXModnNkX21hZ19zdWIpKV0KCiMgY29ycmVsYXRpb24gbWF0cml4CmNvcl9tYXRfbm9ybSA8LSBjb3IodnNkX21hZ19zdWIsIHZzZF9uZl9zdWIpCmBgYApgYGB7cn0KIyBwbG90IGZpcnN0IDMwIHNhbXBsZXMKZ2djb3JycGxvdChjb3JfbWF0X25vcm0pICsgc2NhbGVfZmlsbF9ncmFkaWVudDIobGltaXQgPSBjKDAuOCwxKSwgbG93ID0gImJsdWUiLCBoaWdoID0gICJyZWQiLCBtaWQgPSAid2hpdGUiLCBtaWRwb2ludCA9IDAuOSkKYGBgCgojIyMgUENBIHBsb3RzCmBgYHtyfQojIG5mLWNvcmUKcGNhX3BsdF9uZiA8LSBwbG90UENBKHZzZF9uZiwgaW50Z3JvdXA9YygiRXRpb2xvZ3kiKSwgcmV0dXJuRGF0YSA9IFQpCnBlcmNlbnRWYXIgPC0gcm91bmQoMTAwICogYXR0cihwY2FfcGx0X25mLCAicGVyY2VudFZhciIpKQpnZ3Bsb3QocGNhX3BsdF9uZiwgYWVzKFBDMSwgUEMyLCBjb2xvcj1FdGlvbG9neSkpICsKICBnZW9tX3BvaW50KHNpemU9MykgKwogIHhsYWIocGFzdGUwKCJQQzE6ICIscGVyY2VudFZhclsxXSwiJSB2YXJpYW5jZSIpKSArCiAgeWxhYihwYXN0ZTAoIlBDMjogIixwZXJjZW50VmFyWzJdLCIlIHZhcmlhbmNlIikpICsgCiAgY29vcmRfZml4ZWQoKSArCiAgdGhlbWVfYncoKQpgYGAKYGBge3J9CiMgTWFnCnBjYV9wbHRfbWFnIDwtIHBsb3RQQ0EodnNkX21hZywgaW50Z3JvdXA9YygiRXRpb2xvZ3kiKSwgcmV0dXJuRGF0YSA9IFQpCnBlcmNlbnRWYXIgPC0gcm91bmQoMTAwICogYXR0cihwY2FfcGx0X21hZywgInBlcmNlbnRWYXIiKSkKZ2dwbG90KHBjYV9wbHRfbWFnLCBhZXMoUEMxLCBQQzIsIGNvbG9yPUV0aW9sb2d5KSkgKwogIGdlb21fcG9pbnQoc2l6ZT0zKSArCiAgeGxhYihwYXN0ZTAoIlBDMTogIixwZXJjZW50VmFyWzFdLCIlIHZhcmlhbmNlIikpICsKICB5bGFiKHBhc3RlMCgiUEMyOiAiLHBlcmNlbnRWYXJbMl0sIiUgdmFyaWFuY2UiKSkgKyAKICBjb29yZF9maXhlZCgpICsKICB0aGVtZV9idygpCmBgYAojIyBDb21hcHJpc29uIG9mIERFU2VxMiByZXN1bHRzCgojIyMgRENNIHZzIEhDTQpgYGB7cn0KIyBsb2FkIHJlc3VsdHMgdGFibGVzCmRlc2VxX0RDTXZzSENNX25mIDwtIHJlYWRSRFMoIi4uL0RFU2VxMi9oYXJtb25pemVkLWRlc2VxL2hhcm1vbml6ZWRfREVTZXFSZXN1bHRzLnJkcyIpJERDTXZzSENNCmRlc2VxX0RDTXZzSENNX21hZyA8LSByZWFkUkRTKCIuLi9vcmlnbmFsX2RhdGEvZGF0YS9NQUdOZXRBcHAvZGF0YS9ER0UvTUFHTmV0X0RDTXZzSENNX0dlbmVUb25pYy5yZHMiKSRyZXNfZGUKCmBgYAoKYGBge3J9CiMgZmlsdGVyCkRFZ2VuZXNfRENNdnNIQ01fbWFnIDwtIHJvd25hbWVzKHN1YnNldChkZXNlcV9EQ012c0hDTV9tYWcsIHBhZGogPD0gMC4wNSkpCkRFZ2VuZXNfRENNdnNIQ01fbmYgPC0gcm93bmFtZXMoc3Vic2V0KGRlc2VxX0RDTXZzSENNX25mLCBwYWRqIDw9IDAuMDUpKQpgYGAKCmBgYHtyfQojIGNvbXBhcmUgZ2VuZSBsaXN0cwpvdmVybGFwX0RDTXZzSENNIDwtIGRhdGEuZnJhbWUoZ2VuZXMgPSBpbnRlcnNlY3QoREVnZW5lc19EQ012c0hDTV9tYWcsIERFZ2VuZXNfRENNdnNIQ01fbmYpKQpvdmVybGFwX0RDTXZzSENNJHR5cGUgPC0gIm92ZXJsYXBwaW5nIgpuZl9EQ012c0hDTSA8LSBkYXRhLmZyYW1lKGdlbmVzID0gc2V0ZGlmZihERWdlbmVzX0RDTXZzSENNX25mLHJvd25hbWVzKG92ZXJsYXBfRENNdnNIQ00pKSkKbmZfRENNdnNIQ00kdHlwZSA8LSAibmYtY29yZSIKbWFnX0RDTXZzSENNIDwtIGRhdGEuZnJhbWUoZ2VuZXMgPSBzZXRkaWZmKERFZ2VuZXNfRENNdnNIQ01fbWFnLHJvd25hbWVzKG92ZXJsYXBfRENNdnNIQ00pKSkKbWFnX0RDTXZzSENNJHR5cGUgPC0gIk1hZ25ldGlxdWUiCkRDTXZzSENNIDwtIHJiaW5kKG92ZXJsYXBfRENNdnNIQ00sIG5mX0RDTXZzSENNLCBtYWdfRENNdnNIQ00pCnBhc3RlMCgiUHJvcG9ydGlvbiBvdmVybGFwcGluZyBERSBnZW5lcyBEQ012c0hDTTogIiwgbnJvdyhvdmVybGFwX0RDTXZzSENNKS9ucm93KERFZ2VuZXNfRENNdnNIQ01fbWFnKSkKYGBgCmBgYHtyfQojIHZlbm4KYmlvdmVubiA8LSBkcmF3LnZlbm4oREVnZW5lc19EQ012c0hDTV9tYWcsIERFZ2VuZXNfRENNdnNIQ01fbmYsIE5VTEwsIHRpdGxlPSJEQ00gdnMgSENNIiwgbnJ0eXBlPSJhYnMiLCBzdWJ0aXRsZSA9IE5VTEwsIHh0aXRsZSA9ICJNYWduZXRpcXVlIiwgeXRpdGxlID0gIm5mLWNvcmUiKQpgYGAKYGBge3J9CiMgZGlzdHJpYnV0aW9uIG9mIHAtdmFsdWVzLCBsMkZDcyBhbmQgY291bnRzIGJ5IG92ZXJsYXBwaW5nIG9yIHVuaXF1ZQojIHBsb3RzIG9mIHZhbHVlcyBhcmUgcGVyZm9ybWVkIGZvciBlYWNoIGdlbmUgc2V0IGFnYWluc3QgYm90aCBERVNlcTIgcmVzdWx0cyBmcm9tIE1hZ25ldGlxdWUgYW5kIG5mLWNvcmUgcGlwZWxpbmVzCmRlc2VxX0RDTXZzSENNX21hZ19kZiA8LSBhcy5kYXRhLmZyYW1lKGRlc2VxX0RDTXZzSENNX21hZ1ssYygiYmFzZU1lYW4iLCJsb2cyRm9sZENoYW5nZSIsInBhZGoiKV0pICU+JQogIHRpYmJsZTo6cm93bmFtZXNfdG9fY29sdW1uKC4sIHZhciA9ICJnZW5lcyIpCmRlc2VxX0RDTXZzSENNX25mX2RmIDwtIGFzLmRhdGEuZnJhbWUoZGVzZXFfRENNdnNIQ01fbmZbLGMoImJhc2VNZWFuIiwibG9nMkZvbGRDaGFuZ2UiLCJwYWRqIildKSAlPiUKICB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbiguLCB2YXIgPSAiZ2VuZXMiKQpkZXNlcV9EQ012c0hDTV9tYWdfZGYgPC0gbGVmdF9qb2luKGRlc2VxX0RDTXZzSENNX21hZ19kZiwgRENNdnNIQ00sIGJ5PSJnZW5lcyIpICU+JQogIHJlcGxhY2UoaXMubmEoLiksICJub25lIikKZGVzZXFfRENNdnNIQ01fbmZfZGYgPC0gbGVmdF9qb2luKGRlc2VxX0RDTXZzSENNX25mX2RmLCBEQ012c0hDTSwgYnk9ImdlbmVzIikgJT4lCiAgcmVwbGFjZShpcy5uYSguKSwgIm5vbmUiKQpkZXNlcV9EQ012c0hDTV9tYWdfZGYkbWV0aG9kIDwtICJNYWduZXRpcXVlIgpkZXNlcV9EQ012c0hDTV9uZl9kZiRtZXRob2QgPC0gIm5mLWNvcmUiCmRlc2VxX0RDTXZzSENNX21lcmdlX2RmIDwtIHJiaW5kKGRlc2VxX0RDTXZzSENNX21hZ19kZiwgZGVzZXFfRENNdnNIQ01fbmZfZGYpCgpnZ3Bsb3QoZGVzZXFfRENNdnNIQ01fbWVyZ2VfZGYsIGFlcyh4PXBhZGosIGdyb3VwPXR5cGUsIGNvbG9yPXR5cGUsIGZpbGw9dHlwZSkpICsgCiAgZ2VvbV9kZW5zaXR5KGFscGhhPTAuNikgKyAKICB0aGVtZV9idygpICsKICAjc2NhbGVfZmlsbF9kaXNjcmV0ZShsYWJlbHMgPSBjKCJEaXN0aW5jdCIsICJPdmVybGFwcGluZyIpKSArCiAgICBndWlkZXMoY29sb3IgPSAibm9uZSIpICsKICBmYWNldF93cmFwKH5tZXRob2QpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLjA1LCBsaW5ldHlwZT0iZG90dGVkIikKYGBgCmBgYHtyfQojIHNhbWUgYXMgYWJvdmUgYnV0IGV4Y2x1ZGUgb3ZlcmxhcHBpbmcKZ2dwbG90KHN1YnNldChkZXNlcV9EQ012c0hDTV9tZXJnZV9kZiwgdHlwZSAhPSAib3ZlcmxhcHBpbmciKSwgYWVzKHg9cGFkaiwgZ3JvdXA9dHlwZSwgY29sb3I9dHlwZSwgZmlsbD10eXBlKSkgKyAKICBnZW9tX2RlbnNpdHkoYWxwaGE9MC42KSArIAogIHRoZW1lX2J3KCkgKwogICNzY2FsZV9maWxsX2Rpc2NyZXRlKGxhYmVscyA9IGMoIkRpc3RpbmN0IiwgIk92ZXJsYXBwaW5nIikpICsKICAgIGd1aWRlcyhjb2xvciA9ICJub25lIikgKwogIGZhY2V0X3dyYXAofm1ldGhvZCkgKwogIHhsaW0oYygwLDAuMikpICsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAuMDUsIGxpbmV0eXBlPSJkb3R0ZWQiKQpgYGAKYGBge3J9CiMgCmdncGxvdChkZXNlcV9EQ012c0hDTV9tZXJnZV9kZiwgYWVzKHg9bG9nMkZvbGRDaGFuZ2UsIGdyb3VwPXR5cGUsIGNvbG9yPXR5cGUsIGZpbGw9dHlwZSkpICsgCiAgZ2VvbV9kZW5zaXR5KGFscGhhPTAuNikgKyAKICB0aGVtZV9idygpICsKICAgIGd1aWRlcyhjb2xvciA9ICJub25lIikgKwogIHhsaW0oYygtMywzKSkgKwogIGZhY2V0X2dyaWQofm1ldGhvZCkKYGBgCgpgYGB7cn0KZ2dwbG90KGRlc2VxX0RDTXZzSENNX21lcmdlX2RmLCBhZXMoeD1iYXNlTWVhbiwgZ3JvdXA9dHlwZSwgY29sb3I9dHlwZSwgZmlsbD10eXBlKSkgKyAKICBnZW9tX2RlbnNpdHkoYWxwaGE9MC42KSArIAogIHRoZW1lX2J3KCkgKwogICAgZ3VpZGVzKGNvbG9yID0gIm5vbmUiKSArCiAgeGxpbShjKDEwLCAxMDAwKSkgKwogIGZhY2V0X2dyaWQofm1ldGhvZCwgc2NhbGVzID0gImZyZWVfeSIpCmBgYAoKIyMjIERDTSB2cyBORkQKYGBge3J9CiMgbG9hZCByZXN1bHRzIHRhYmxlcwpkZXNlcV9EQ012c05GRF9uZiA8LSByZWFkUkRTKCIuLi9ERVNlcTIvaGFybW9uaXplZC1kZXNlcS9oYXJtb25pemVkX0RFU2VxUmVzdWx0cy5yZHMiKSREQ012c05GRApkZXNlcV9EQ012c05GRF9tYWcgPC0gcmVhZFJEUygiLi4vb3JpZ25hbF9kYXRhL2RhdGEvTUFHTmV0QXBwL2RhdGEvREdFL01BR05ldF9EQ012c05GRF9HZW5lVG9uaWMucmRzIikkcmVzX2RlCgpgYGAKCmBgYHtyfQojIGZpbHRlcgpERWdlbmVzX0RDTXZzTkZEX21hZyA8LSByb3duYW1lcyhzdWJzZXQoZGVzZXFfRENNdnNORkRfbWFnLCBwYWRqIDw9IDAuMDUpKQpERWdlbmVzX0RDTXZzTkZEX25mIDwtIHJvd25hbWVzKHN1YnNldChkZXNlcV9EQ012c05GRF9uZiwgcGFkaiA8PSAwLjA1KSkKYGBgCgpgYGB7cn0KIyBjb21wYXJlIGdlbmUgbGlzdHMKb3ZlcmxhcF9EQ012c05GRCA8LSBkYXRhLmZyYW1lKGdlbmVzID0gaW50ZXJzZWN0KERFZ2VuZXNfRENNdnNORkRfbWFnLCBERWdlbmVzX0RDTXZzTkZEX25mKSkKb3ZlcmxhcF9EQ012c05GRCR0eXBlIDwtICJvdmVybGFwcGluZyIKbmZfRENNdnNORkQgPC0gZGF0YS5mcmFtZShnZW5lcyA9IHNldGRpZmYoREVnZW5lc19EQ012c05GRF9uZixyb3duYW1lcyhvdmVybGFwX0RDTXZzTkZEKSkpCm5mX0RDTXZzTkZEJHR5cGUgPC0gIm5mLWNvcmUiCm1hZ19EQ012c05GRCA8LSBkYXRhLmZyYW1lKGdlbmVzID0gc2V0ZGlmZihERWdlbmVzX0RDTXZzTkZEX21hZyxyb3duYW1lcyhvdmVybGFwX0RDTXZzTkZEKSkpCm1hZ19EQ012c05GRCR0eXBlIDwtICJNYWduZXRpcXVlIgpEQ012c05GRCA8LSByYmluZChvdmVybGFwX0RDTXZzTkZELCBuZl9EQ012c05GRCwgbWFnX0RDTXZzTkZEKQpwYXN0ZTAoIlByb3BvcnRpb24gb3ZlcmxhcHBpbmcgREUgZ2VuZXMgRENNdnNORkQ6ICIsIG5yb3cob3ZlcmxhcF9EQ012c05GRCkvbnJvdyhERWdlbmVzX0RDTXZzTkZEX21hZykpCmBgYAoKYGBge3J9CiMgdmVubgpiaW92ZW5uIDwtIGRyYXcudmVubihERWdlbmVzX0RDTXZzTkZEX21hZywgREVnZW5lc19EQ012c05GRF9uZiwgTlVMTCwgdGl0bGU9IkRDTSB2cyBORkQiLCBucnR5cGU9ImFicyIsIHN1YnRpdGxlID0gTlVMTCwgeHRpdGxlID0gIk1hZ25ldGlxdWUiLCB5dGl0bGUgPSAibmYtY29yZSIpCmBgYApgYGB7cn0KIyBkaXN0cmlidXRpb24gb2YgcC12YWx1ZXMgYW5kIGwyRkNzIGJ5IG92ZXJsYXBwaW5nIG9yIG5vdApkZXNlcV9EQ012c05GRF9tYWdfZGYgPC0gYXMuZGF0YS5mcmFtZShkZXNlcV9EQ012c05GRF9tYWdbLGMoImJhc2VNZWFuIiwibG9nMkZvbGRDaGFuZ2UiLCJwYWRqIildKSAlPiUKICB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbiguLCB2YXIgPSAiZ2VuZXMiKQpkZXNlcV9EQ012c05GRF9uZl9kZiA8LSBhcy5kYXRhLmZyYW1lKGRlc2VxX0RDTXZzTkZEX25mWyxjKCJiYXNlTWVhbiIsImxvZzJGb2xkQ2hhbmdlIiwicGFkaiIpXSkgJT4lCiAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oLiwgdmFyID0gImdlbmVzIikKZGVzZXFfRENNdnNORkRfbWFnX2RmIDwtICBsZWZ0X2pvaW4oZGVzZXFfRENNdnNORkRfbWFnX2RmLCBEQ012c05GRCwgYnk9ImdlbmVzIikgJT4lCiAgcmVwbGFjZShpcy5uYSguKSwgIm5vbmUiKQpkZXNlcV9EQ012c05GRF9uZl9kZiA8LSBsZWZ0X2pvaW4oZGVzZXFfRENNdnNORkRfbmZfZGYsIERDTXZzTkZELCBieT0iZ2VuZXMiKSAlPiUKICByZXBsYWNlKGlzLm5hKC4pLCAibm9uZSIpCmRlc2VxX0RDTXZzTkZEX21hZ19kZiRtZXRob2QgPC0gIk1hZ25ldGlxdWUiCmRlc2VxX0RDTXZzTkZEX25mX2RmJG1ldGhvZCA8LSAibmYtY29yZSIKZGVzZXFfRENNdnNORkRfbWVyZ2VfZGYgPC0gcmJpbmQoZGVzZXFfRENNdnNORkRfbWFnX2RmLCBkZXNlcV9EQ012c05GRF9uZl9kZikKCmdncGxvdChkZXNlcV9EQ012c05GRF9tZXJnZV9kZiwgYWVzKHg9cGFkaiwgZ3JvdXA9dHlwZSwgY29sb3I9dHlwZSwgZmlsbD10eXBlKSkgKyAKICBnZW9tX2RlbnNpdHkoYWxwaGE9MC42KSArIAogIHRoZW1lX2J3KCkgKwogICAgZ3VpZGVzKGNvbG9yID0gIm5vbmUiKSArCiAgZmFjZXRfd3JhcCh+bWV0aG9kKQogIApgYGAKYGBge3J9CmdncGxvdChkZXNlcV9EQ012c05GRF9tZXJnZV9kZiwgYWVzKHg9bG9nMkZvbGRDaGFuZ2UsIGdyb3VwPXR5cGUsIGNvbG9yPXR5cGUsIGZpbGw9dHlwZSkpICsgCiAgZ2VvbV9kZW5zaXR5KGFscGhhPTAuNikgKyAKICB0aGVtZV9idygpICsKICAgIGd1aWRlcyhjb2xvciA9ICJub25lIikgKwogIHhsaW0oYygtMywzKSkgKwogIGZhY2V0X3dyYXAofm1ldGhvZCkKYGBgCgpgYGB7cn0KZ2dwbG90KGRlc2VxX0RDTXZzTkZEX21lcmdlX2RmLCBhZXMoeD1iYXNlTWVhbiwgZ3JvdXA9dHlwZSwgY29sb3I9dHlwZSwgZmlsbD10eXBlKSkgKyAKICBnZW9tX2RlbnNpdHkoYWxwaGE9MC42KSArIAogIHRoZW1lX2J3KCkgKwogICAgZ3VpZGVzKGNvbG9yID0gIm5vbmUiKSArCiAgeGxpbShjKDEsMTAwKSkgKwogIGZhY2V0X3dyYXAofm1ldGhvZCkKYGBgCgojIyMgSENNIHZzIE5GRApgYGB7cn0KIyBsb2FkIHJlc3VsdHMgdGFibGVzCmRlc2VxX0hDTXZzTkZEX25mIDwtIHJlYWRSRFMoIi4uL0RFU2VxMi9oYXJtb25pemVkLWRlc2VxL2hhcm1vbml6ZWRfREVTZXFSZXN1bHRzLnJkcyIpJEhDTXZzTkZECmRlc2VxX0hDTXZzTkZEX21hZyA8LSByZWFkUkRTKCIuLi9vcmlnbmFsX2RhdGEvZGF0YS9NQUdOZXRBcHAvZGF0YS9ER0UvTUFHTmV0X0hDTXZzTkZEX0dlbmVUb25pYy5yZHMiKSRyZXNfZGUKCmBgYAoKYGBge3J9CiMgZmlsdGVyCkRFZ2VuZXNfSENNdnNORkRfbWFnIDwtIHJvd25hbWVzKHN1YnNldChkZXNlcV9IQ012c05GRF9tYWcsIHBhZGogPD0gMC4wNSkpCkRFZ2VuZXNfSENNdnNORkRfbmYgPC0gcm93bmFtZXMoc3Vic2V0KGRlc2VxX0hDTXZzTkZEX25mLCBwYWRqIDw9IDAuMDUpKQpgYGAKCmBgYHtyfQojIGNvbXBhcmUgZ2VuZSBsaXN0cwpvdmVybGFwX0hDTXZzTkZEIDwtIGludGVyc2VjdChERWdlbmVzX0hDTXZzTkZEX21hZywgREVnZW5lc19IQ012c05GRF9uZikKcGFzdGUwKCJQcm9wb3J0aW9uIG92ZXJsYXBwaW5nIERFIGdlbmVzIEhDTXZzTkZEOiAiLCBsZW5ndGgob3ZlcmxhcF9IQ012c05GRCkvbGVuZ3RoKERFZ2VuZXNfSENNdnNORkRfbmYpKQpgYGAKCmBgYHtyfQojIHZlbm4KYmlvdmVubiA8LSBkcmF3LnZlbm4oREVnZW5lc19IQ012c05GRF9tYWcsIERFZ2VuZXNfSENNdnNORkRfbmYsIE5VTEwsIHRpdGxlPSJIQ00gdnMgTkZEIiwgbnJ0eXBlPSJhYnMiLCBzdWJ0aXRsZSA9IE5VTEwsIHh0aXRsZSA9ICJNYWduZXRpcXVlIiwgeXRpdGxlID0gIm5mLWNvcmUiKQpgYGAKCmBgYHtyfQpsZW5ndGgoaW50ZXJzZWN0KERFZ2VuZXNfSENNdnNORkRfbWFnLCBERWdlbmVzX0hDTXZzTkZEX25mKSkKYGBg