Going to run the Day 135 samples through the Macau pipeline, similarly to the Day 10 samples I did last week.
First, some housekeeping stuff, setting workign directories, making subdirectories to hold things, and a vector of sample names
setwd("~/Documents/Day135/Day135Cutoff/")
samples.vec <- c("EPI-151", "EPI-152", "EPI-153", "EPI-154", "EPI-159", "EPI-160", "EPI-161", "EPI-162", "EPI-167", "EPI-168", "EPI-169", "EPI-170")
library(readr)
setwd("~/Documents/Day135/Day135Cutoff/CGoutput")
data <- list.files(path = ".", pattern = "*.output")
print(data)
db <- read_delim("~/Documents/Day135/Day135Cutoff/CGoutput/EPI-151_CG.output", "\t", escape_double = FALSE, trim_ws = TRUE, na = ".")
db <- as.data.table(db)
db$EPI103Meth <- rowSums(cbind(db[,4], db[,7]), na.rm = TRUE)
db$EPI103TotCov <- rowSums(cbind(db[,5], db[,8]), na.rm = TRUE)
meth.db <- db[,c(1,2,3,10)]
totcov.db <- db[,c(1,2,3,11)]
for(i in 2:length(data)) {
temp <- read_delim(paste0("~/Documents/Day135/Day135Cutoff/CGoutput/", data[i]), "\t", escape_double = FALSE, trim_ws = TRUE, na = ".")
temp <- as.data.table(temp)
temp$Meth <- rowSums(cbind(temp[,4], temp[,7]), na.rm = TRUE)
temp$TotCov <- rowSums(cbind(temp[,5], temp[,8]), na.rm = TRUE)
meth.db <- merge(meth.db, temp[,c(1,2,3,10)], by = names(meth.db[,c(1,2,3)]), all = TRUE)
colnames(meth.db)[ncol(meth.db)] <- paste0(substr(data[i], 1, 7), "Meth")
meth.db <- as.data.table(meth.db)
totcov.db <- merge(totcov.db, temp[,c(1,2,3,11)], by = names(totcov.db[,c(1,2,3)]), all = TRUE)
colnames(totcov.db)[ncol(totcov.db)] <- paste0(substr(data[i], 1, 7), "TotCov")
totcov.db <- as.data.table(totcov.db)
}
setwd("~/Documents/Day135/Day135Cutoff/macau")
meth.db2 <- meth.db[complete.cases(meth.db[,c(4:15)]),]
totcov.db2 <- totcov.db[complete.cases(totcov.db[,c(4:15)]),]
meth.db3 <- meth.db2[apply(meth.db2[, c(4:15)], MARGIN = 1, function(x) all(x > 3)), ]
totcov.db3 <- totcov.db2[apply(totcov.db2[, c(4:15)], MARGIN = 1, function(x) all(x > 3)), ]
meth.db4 <- as.data.table(cbind(paste0(meth.db3$`#CHROM`, "-", meth.db3$POS), meth.db3[,4:ncol(meth.db3)]))
colnames(meth.db4)[1] <- "Site"
totcov.db4 <- as.data.table(cbind(paste0(totcov.db3$`#CHROM`, "-", totcov.db3$POS), totcov.db3[,4:ncol(totcov.db3)]))
colnames(totcov.db4)[1] <- "Site"
totcov.db5 <- totcov.db4[totcov.db4$Site %in% meth.db4$Site,]
nrow(meth.db4)
nrow(totcov.db5)
length(totcov.db5$Site %in% meth.db4$Site)
write.table(meth.db4, file = "threex.macau.meth.txt", sep = " ", quote = FALSE, row.names = FALSE)
write.table(totcov.db5, file = "threex.macau.totalcov.txt", sep = " ", quote = FALSE, row.names = FALSE)
system("head threex.macau.meth.txt")
system("head threex.macau.totalcov.txt")
I’ve been doing this on my macbook, and macau requires linux to run properly, so the below code was run on Emu. The output isn’t super interesting, so I won’t bother copying it over. If you want to see what it looks like, look at my Day 10 notebook
setwd("~/Documents/Day135/Day135Cutoff/macau/")
system("/home/shared/macau/macau -g threex.macau.meth.txt -t threex.macau.totalcov.txt -p Predictor.csv -k day135-relate-finished.csv -o threex")
setwd("~/Documents/Day135/Day135Cutoff/macau/")
threex_assoc <- read_delim("~/Documents/Day135/Day135Cutoff/macau/output/threex.assoc.txt",
"\t", escape_double = FALSE, trim_ws = TRUE)
sig.results <- threex_assoc[threex_assoc$pvalue <= 0.05,]
for(i in 1:nrow(sig.results)) {
temp <- strsplit(sig.results$id[i], "-")
sig.results[i,13] <- temp[[1]][1]
sig.results[i,14] <- temp[[1]][2]
}
colnames(sig.results)[c(13,14)] <- c("Scaffold", "Loc")
bed.test <- as.data.frame(cbind(sig.results[,13], (sig.results[,14]), (sig.results[,14]), sig.results$beta))
colnames(bed.test)[4] <- "beta"
write.table(bed.test, file = "threex.DiffMethRegions.bed", sep = ",", quote = FALSE, col.names = FALSE, row.names = FALSE)
Set Working Directory, and make sure the files I want are there.
setwd("~/Documents/Day135/Day135Cutoff/")
list.files(path = ".")
Read in the DiffMethRegions file, which has scaffold number, location, and beta values from the MACAU model. Also, make a vector of the individual sample files to iterate over.
library(data.table)
library(readr)
DiffMethRegions <- read_delim("~/Documents/Day135/Day135Cutoff/threex.DiffMethRegions.bed",
",", escape_double = FALSE, col_names = FALSE,
trim_ws = TRUE)
DiffMethRegions$Loc <- paste0(DiffMethRegions$X1, "-", DiffMethRegions$X2)
head(DiffMethRegions)
sample.files <- list.files(path = "~/Documents/Day135/Day135Cutoff/", pattern = "*.bedgraph")
print(sample.files)
my DMR file looks good, and I have sample file names to iterate over
Start the first post for my fence. I have to specify that the column type for the 4th column, which contains proportion of methylation data is a double, as R assumes it to be an integer valued vector, which results in only 1s and 0s, which wouldn’t be informative.
EPI_103_percmeth_bedgraph <- read_delim("~/Documents/Day135/Day135Cutoff/EPI-151-percmeth.bedgraph",
"\t", escape_double = FALSE, col_names = FALSE,
col_types = cols(X4 = col_double()),
trim_ws = TRUE)
EPI_103_percmeth_bedgraph <- as.data.table(EPI_103_percmeth_bedgraph)
head(EPI_103_percmeth_bedgraph)
print(EPI_103_percmeth_bedgraph[7,])
I tossed an extra print statement in, just to verify that something that’s double valued really is.
Next I extract information only on the 41 DMRs, since that’s all thats of interest
EPI_103_DMRs <- EPI_103_percmeth_bedgraph[EPI_103_percmeth_bedgraph$X1 %in% DiffMethRegions$X1,]
EPI_103_DMRs$Loc <- paste0(EPI_103_DMRs$X1, "-", EPI_103_DMRs$X2)
head(EPI_103_DMRs)
EPI_103_DMRs <- EPI_103_DMRs[EPI_103_DMRs$Loc %in% DiffMethRegions$Loc,]
head(EPI_103_DMRs)
EPI_DMRs <- as.data.table(cbind(EPI_103_DMRs$Loc, EPI_103_DMRs$X4))
colnames(EPI_DMRs)[1] <- "DMRLoc"
colnames(EPI_DMRs)[2] <- "EPI_151"
head(EPI_DMRs)
Now I get to do the whole loop thing, iterating over the remaining samples and reading them in, extracting the DMRs and saving them to my DMR matrix.
for(i in 2:length(sample.files)) {
temp <- read_delim(paste0("~/Documents/Day135/Day135Cutoff/", sample.files[i]),
"\t", escape_double = FALSE, col_names = FALSE,
col_types = cols(X4 = col_double()),
trim_ws = TRUE)
temp <- as.data.table(temp)
temp_DMRs <- temp[temp$X1 %in% DiffMethRegions$X1,]
temp_DMRs$Loc <- paste0(temp_DMRs$X1, "-", temp_DMRs$X2)
temp_DMRs <- temp_DMRs[temp_DMRs$Loc %in% DiffMethRegions$Loc,]
EPI_DMRs$temp <- temp_DMRs$X4
colnames(EPI_DMRs)[ncol(EPI_DMRs)] <- substr(sample.files[i], 1, 7)
}
head(EPI_DMRs)
## This is here because for osme reason EPI_103 gets brught in as characters as opposed to doubles. Need to figure out why, but this fixes it for now
EPI_DMRs$EPI_151 <- as.numeric(EPI_DMRs$EPI_151)
Here I calculate treatment means and save them to a vector of treatment means by location
treatment.means <- as.data.frame(EPI_DMRs$DMRLoc)
treatment.means$Ambient <- apply(cbind(EPI_DMRs$`EPI-151`, EPI_DMRs$`EPI-152`, EPI_DMRs$`EPI-153`, EPI_DMRs$`EPI-154`) ,MARGIN = 1, FUN = mean)
treatment.means$Low <- apply(cbind(EPI_DMRs$`EPI-159`, EPI_DMRs$`EPI-160`, EPI_DMRs$`EPI-161`, EPI_DMRs$`EPI-162`) ,MARGIN = 1, FUN = mean)
treatment.means$SuperLow <- apply(cbind(EPI_DMRs$`EPI-167`, EPI_DMRs$`EPI-168`, EPI_DMRs$`EPI-169`, EPI_DMRs$`EPI-170`) ,MARGIN = 1, FUN = mean)
head(treatment.means)
This… makes a really ugly and hard to read graph. On the X axis is the DMR location, and the Y axis is proportion emthylated. Bars are ambient, Green dots are low treatments, and red dots are Super low treatments.
It’s not really informative, but I made it, so I figured I’d show it.
plot(treatment.means$`EPI_DMRs$DMRLoc`, treatment.means$Ambient, col = "blue", pch = 16)
points(treatment.means$`EPI_DMRs$DMRLoc`, treatment.means$Low, col = "green", pch = 16)
points(treatment.means$`EPI_DMRs$DMRLoc`, treatment.means$SuperLow, col = "red", pch = 16)
I like this a lot better, it makes boxplots for each DMR with each treatment. I like how this shows the variaiblity between samples, as well as location information. The below code outputs to R-studio, as well as a PDF for easier viewing.
# for(i in 1:nrow(treatment.means)) {
#
#
# boxplot(t(cbind(EPI_DMRs[i,2], EPI_DMRs[i,3], EPI_DMRs[i,4], EPI_DMRs[i,5])),xlim = c(0.5, 3.5), ylim = c(min(EPI_DMRs[i,2:13]), max(EPI_DMRs[i,2:13])), boxfill = "blue", names = "Ambient", show.names = TRUE, ylab = "Proportion of reads methylated")
#
# boxplot(t(cbind(EPI_DMRs[i,6], EPI_DMRs[i,7], EPI_DMRs[i,8], EPI_DMRs[i,9])), xaxt = "n", add = TRUE, at = 2, boxfill = "green")
#
# boxplot(t(cbind(EPI_DMRs[i,10], EPI_DMRs[i,11], EPI_DMRs[i,12], EPI_DMRs[i,13])), xaxt = "n", add = TRUE, at = 3, boxfill = "red")
#
# axis(side = 1, at = 2, labels = "Low")
# axis(side = 1, at = 3, labels = "Super Low")
#
# title(paste0("Proportion of Methylated reads for DMR \n located at ", EPI_DMRs[i,1]))
#
#
# }
pdf(file = "threex-DMR-Box-Plots.pdf")
for(i in 1:nrow(treatment.means)) {
boxplot(t(cbind(EPI_DMRs[i,6], EPI_DMRs[i,7], EPI_DMRs[i,10], EPI_DMRs[i,11])),xlim = c(0.5, 3.5), ylim = c(min(EPI_DMRs[i,2:13]), max(EPI_DMRs[i,2:13])), boxfill = "blue", names = "Ambient", show.names = TRUE, ylab = "Proportion of reads methylated")
boxplot(t(cbind(EPI_DMRs[i,2], EPI_DMRs[i,3], EPI_DMRs[i,8], EPI_DMRs[i,9])), xaxt = "n", add = TRUE, at = 2, boxfill = "green")
boxplot(t(cbind(EPI_DMRs[i,4], EPI_DMRs[i,5], EPI_DMRs[i,12], EPI_DMRs[i,13])), xaxt = "n", add = TRUE, at = 3, boxfill = "red")
axis(side = 1, at = 2, labels = "Low")
axis(side = 1, at = 3, labels = "Super Low")
title(paste0("Proportion of Methylated reads for DMR \n located at ", EPI_DMRs[i,1]))
}
dev.off()
Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.
When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).
LS0tCnRpdGxlOiAiRGF5IDEzNSBTYW1wbGVzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpHb2luZyB0byBydW4gdGhlIERheSAxMzUgc2FtcGxlcyB0aHJvdWdoIHRoZSBNYWNhdSBwaXBlbGluZSwgc2ltaWxhcmx5IHRvIHRoZSBEYXkgMTAgc2FtcGxlcyBJIGRpZCBsYXN0IHdlZWsuCgpGaXJzdCwgc29tZSBob3VzZWtlZXBpbmcgc3R1ZmYsIHNldHRpbmcgd29ya2lnbiBkaXJlY3RvcmllcywgbWFraW5nIHN1YmRpcmVjdG9yaWVzIHRvIGhvbGQgdGhpbmdzLCBhbmQgYSB2ZWN0b3Igb2Ygc2FtcGxlIG5hbWVzCgpgYGB7cn0Kc2V0d2QoIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvIikKCnNhbXBsZXMudmVjIDwtIGMoIkVQSS0xNTEiLCAiRVBJLTE1MiIsICJFUEktMTUzIiwgIkVQSS0xNTQiLCAiRVBJLTE1OSIsICJFUEktMTYwIiwgIkVQSS0xNjEiLCAiRVBJLTE2MiIsICJFUEktMTY3IiwgIkVQSS0xNjgiLCAiRVBJLTE2OSIsICJFUEktMTcwIikKCmBgYAoKCmBgYHtyfQoKbGlicmFyeShyZWFkcikKc2V0d2QoIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvQ0dvdXRwdXQiKQoKZGF0YSA8LSBsaXN0LmZpbGVzKHBhdGggPSAiLiIsIHBhdHRlcm4gPSAiKi5vdXRwdXQiKQpwcmludChkYXRhKQoKZGIgPC0gcmVhZF9kZWxpbSgifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi9DR291dHB1dC9FUEktMTUxX0NHLm91dHB1dCIsICJcdCIsIGVzY2FwZV9kb3VibGUgPSBGQUxTRSwgdHJpbV93cyA9IFRSVUUsIG5hID0gIi4iKQoKZGIgPC0gYXMuZGF0YS50YWJsZShkYikKCmRiJEVQSTEwM01ldGggPC0gcm93U3VtcyhjYmluZChkYlssNF0sIGRiWyw3XSksIG5hLnJtID0gVFJVRSkKZGIkRVBJMTAzVG90Q292IDwtIHJvd1N1bXMoY2JpbmQoZGJbLDVdLCBkYlssOF0pLCBuYS5ybSA9IFRSVUUpCm1ldGguZGIgPC0gZGJbLGMoMSwyLDMsMTApXQp0b3Rjb3YuZGIgPC0gZGJbLGMoMSwyLDMsMTEpXQoKZm9yKGkgaW4gMjpsZW5ndGgoZGF0YSkpICAgewogIAogIHRlbXAgPC0gcmVhZF9kZWxpbShwYXN0ZTAoIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvQ0dvdXRwdXQvIiwgZGF0YVtpXSksICJcdCIsIGVzY2FwZV9kb3VibGUgPSBGQUxTRSwgdHJpbV93cyA9IFRSVUUsIG5hID0gIi4iKQogIHRlbXAgPC0gYXMuZGF0YS50YWJsZSh0ZW1wKQogIHRlbXAkTWV0aCA8LSByb3dTdW1zKGNiaW5kKHRlbXBbLDRdLCB0ZW1wWyw3XSksIG5hLnJtID0gVFJVRSkKICB0ZW1wJFRvdENvdiA8LSByb3dTdW1zKGNiaW5kKHRlbXBbLDVdLCB0ZW1wWyw4XSksIG5hLnJtID0gVFJVRSkKCiAgbWV0aC5kYiA8LSBtZXJnZShtZXRoLmRiLCB0ZW1wWyxjKDEsMiwzLDEwKV0sIGJ5ID0gbmFtZXMobWV0aC5kYlssYygxLDIsMyldKSwgYWxsID0gVFJVRSkKICBjb2xuYW1lcyhtZXRoLmRiKVtuY29sKG1ldGguZGIpXSA8LSBwYXN0ZTAoc3Vic3RyKGRhdGFbaV0sIDEsIDcpLCAiTWV0aCIpCiAgbWV0aC5kYiA8LSBhcy5kYXRhLnRhYmxlKG1ldGguZGIpCiAgCiAgdG90Y292LmRiIDwtIG1lcmdlKHRvdGNvdi5kYiwgdGVtcFssYygxLDIsMywxMSldLCBieSA9IG5hbWVzKHRvdGNvdi5kYlssYygxLDIsMyldKSwgYWxsID0gVFJVRSkKICBjb2xuYW1lcyh0b3Rjb3YuZGIpW25jb2wodG90Y292LmRiKV0gPC0gcGFzdGUwKHN1YnN0cihkYXRhW2ldLCAxLCA3KSwgIlRvdENvdiIpCiAgdG90Y292LmRiIDwtIGFzLmRhdGEudGFibGUodG90Y292LmRiKQp9CgoKCmBgYAoKCgpgYGB7cn0Kc2V0d2QoIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvbWFjYXUiKQptZXRoLmRiMiA8LSBtZXRoLmRiW2NvbXBsZXRlLmNhc2VzKG1ldGguZGJbLGMoNDoxNSldKSxdCgp0b3Rjb3YuZGIyIDwtIHRvdGNvdi5kYltjb21wbGV0ZS5jYXNlcyh0b3Rjb3YuZGJbLGMoNDoxNSldKSxdCgptZXRoLmRiMyA8LSBtZXRoLmRiMlthcHBseShtZXRoLmRiMlssIGMoNDoxNSldLCBNQVJHSU4gPSAxLCBmdW5jdGlvbih4KSBhbGwoeCA+IDMpKSwgXQp0b3Rjb3YuZGIzIDwtIHRvdGNvdi5kYjJbYXBwbHkodG90Y292LmRiMlssIGMoNDoxNSldLCBNQVJHSU4gPSAxLCBmdW5jdGlvbih4KSBhbGwoeCA+IDMpKSwgXQoKbWV0aC5kYjQgPC0gYXMuZGF0YS50YWJsZShjYmluZChwYXN0ZTAobWV0aC5kYjMkYCNDSFJPTWAsICItIiwgbWV0aC5kYjMkUE9TKSwgbWV0aC5kYjNbLDQ6bmNvbChtZXRoLmRiMyldKSkKY29sbmFtZXMobWV0aC5kYjQpWzFdIDwtICJTaXRlIgp0b3Rjb3YuZGI0IDwtIGFzLmRhdGEudGFibGUoY2JpbmQocGFzdGUwKHRvdGNvdi5kYjMkYCNDSFJPTWAsICItIiwgdG90Y292LmRiMyRQT1MpLCB0b3Rjb3YuZGIzWyw0Om5jb2wodG90Y292LmRiMyldKSkKY29sbmFtZXModG90Y292LmRiNClbMV0gPC0gIlNpdGUiCgp0b3Rjb3YuZGI1IDwtIHRvdGNvdi5kYjRbdG90Y292LmRiNCRTaXRlICVpbiUgbWV0aC5kYjQkU2l0ZSxdCgpucm93KG1ldGguZGI0KQpucm93KHRvdGNvdi5kYjUpCmxlbmd0aCh0b3Rjb3YuZGI1JFNpdGUgJWluJSBtZXRoLmRiNCRTaXRlKQoKd3JpdGUudGFibGUobWV0aC5kYjQsIGZpbGUgPSAidGhyZWV4Lm1hY2F1Lm1ldGgudHh0Iiwgc2VwID0gIiAiLCBxdW90ZSA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSkKd3JpdGUudGFibGUodG90Y292LmRiNSwgZmlsZSA9ICJ0aHJlZXgubWFjYXUudG90YWxjb3YudHh0Iiwgc2VwID0gIiAiLCBxdW90ZSA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSkKCnN5c3RlbSgiaGVhZCB0aHJlZXgubWFjYXUubWV0aC50eHQiKQpzeXN0ZW0oImhlYWQgdGhyZWV4Lm1hY2F1LnRvdGFsY292LnR4dCIpCmBgYAoKSSd2ZSBiZWVuIGRvaW5nIHRoaXMgb24gbXkgbWFjYm9vaywgYW5kIG1hY2F1IHJlcXVpcmVzIGxpbnV4IHRvIHJ1biBwcm9wZXJseSwgc28gdGhlIGJlbG93IGNvZGUgd2FzIHJ1biBvbiBFbXUuIFRoZSBvdXRwdXQgaXNuJ3Qgc3VwZXIgaW50ZXJlc3RpbmcsIHNvIEkgd29uJ3QgYm90aGVyIGNvcHlpbmcgaXQgb3Zlci4gSWYgeW91IHdhbnQgdG8gc2VlIHdoYXQgaXQgbG9va3MgbGlrZSwgbG9vayBhdCBteSBEYXkgMTAgbm90ZWJvb2sKCmBgYHtyfQpzZXR3ZCgifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi9tYWNhdS8iKQpzeXN0ZW0oIi9ob21lL3NoYXJlZC9tYWNhdS9tYWNhdSAtZyB0aHJlZXgubWFjYXUubWV0aC50eHQgLXQgdGhyZWV4Lm1hY2F1LnRvdGFsY292LnR4dCAtcCBQcmVkaWN0b3IuY3N2IC1rIGRheTEzNS1yZWxhdGUtZmluaXNoZWQuY3N2IC1vIHRocmVleCIpCgpgYGAKCgoKCmBgYHtyfQpzZXR3ZCgifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi9tYWNhdS8iKQoKdGhyZWV4X2Fzc29jIDwtIHJlYWRfZGVsaW0oIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvbWFjYXUvb3V0cHV0L3RocmVleC5hc3NvYy50eHQiLCAKICAgICJcdCIsIGVzY2FwZV9kb3VibGUgPSBGQUxTRSwgdHJpbV93cyA9IFRSVUUpCgpzaWcucmVzdWx0cyA8LSB0aHJlZXhfYXNzb2NbdGhyZWV4X2Fzc29jJHB2YWx1ZSA8PSAwLjA1LF0KCiBmb3IoaSBpbiAxOm5yb3coc2lnLnJlc3VsdHMpKSAgIHsKICAgdGVtcCA8LSBzdHJzcGxpdChzaWcucmVzdWx0cyRpZFtpXSwgIi0iKSAKICAgc2lnLnJlc3VsdHNbaSwxM10gPC0gdGVtcFtbMV1dWzFdCiAgIHNpZy5yZXN1bHRzW2ksMTRdIDwtIHRlbXBbWzFdXVsyXQogICAKIH0KIAogY29sbmFtZXMoc2lnLnJlc3VsdHMpW2MoMTMsMTQpXSA8LSBjKCJTY2FmZm9sZCIsICJMb2MiKQogCiBiZWQudGVzdCA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKHNpZy5yZXN1bHRzWywxM10sIChzaWcucmVzdWx0c1ssMTRdKSwgKHNpZy5yZXN1bHRzWywxNF0pLCBzaWcucmVzdWx0cyRiZXRhKSkKIGNvbG5hbWVzKGJlZC50ZXN0KVs0XSA8LSAiYmV0YSIKIHdyaXRlLnRhYmxlKGJlZC50ZXN0LCBmaWxlID0gInRocmVleC5EaWZmTWV0aFJlZ2lvbnMuYmVkIiwgc2VwID0gIiwiLCBxdW90ZSA9IEZBTFNFLCBjb2wubmFtZXMgPSBGQUxTRSwgcm93Lm5hbWVzID0gRkFMU0UpCgpgYGAKCgpTZXQgV29ya2luZyBEaXJlY3RvcnksIGFuZCBtYWtlIHN1cmUgdGhlIGZpbGVzIEkgd2FudCBhcmUgdGhlcmUuCgpgYGB7cn0KIHNldHdkKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmLyIpCiAKIGxpc3QuZmlsZXMocGF0aCA9ICIuIikKIAoKYGBgCgpSZWFkIGluIHRoZSBEaWZmTWV0aFJlZ2lvbnMgZmlsZSwgd2hpY2ggaGFzIHNjYWZmb2xkIG51bWJlciwgbG9jYXRpb24sIGFuZCBiZXRhIHZhbHVlcyBmcm9tIHRoZSBNQUNBVSBtb2RlbC4gQWxzbywgbWFrZSBhIHZlY3RvciBvZiB0aGUgaW5kaXZpZHVhbCBzYW1wbGUgZmlsZXMgdG8gaXRlcmF0ZSBvdmVyLiAKCmBgYHtyfQogbGlicmFyeShkYXRhLnRhYmxlKQogbGlicmFyeShyZWFkcikKIERpZmZNZXRoUmVnaW9ucyA8LSByZWFkX2RlbGltKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmL3RocmVleC5EaWZmTWV0aFJlZ2lvbnMuYmVkIiwgCiAgICAgIiwiLCBlc2NhcGVfZG91YmxlID0gRkFMU0UsIGNvbF9uYW1lcyA9IEZBTFNFLCAKICAgICB0cmltX3dzID0gVFJVRSkKIAogRGlmZk1ldGhSZWdpb25zJExvYyA8LSBwYXN0ZTAoRGlmZk1ldGhSZWdpb25zJFgxLCAiLSIsIERpZmZNZXRoUmVnaW9ucyRYMikKIAogaGVhZChEaWZmTWV0aFJlZ2lvbnMpCiAKIHNhbXBsZS5maWxlcyA8LSBsaXN0LmZpbGVzKHBhdGggPSAifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi8iLCBwYXR0ZXJuID0gIiouYmVkZ3JhcGgiKQogCiBwcmludChzYW1wbGUuZmlsZXMpCgpgYGAKCgpteSBETVIgZmlsZSBsb29rcyBnb29kLCBhbmQgSSBoYXZlIHNhbXBsZSBmaWxlIG5hbWVzIHRvIGl0ZXJhdGUgb3ZlcgoKClN0YXJ0IHRoZSBmaXJzdCBwb3N0IGZvciBteSBmZW5jZS4gSSBoYXZlIHRvIHNwZWNpZnkgdGhhdCB0aGUgY29sdW1uIHR5cGUgZm9yIHRoZSA0dGggY29sdW1uLCB3aGljaCBjb250YWlucyBwcm9wb3J0aW9uIG9mIG1ldGh5bGF0aW9uIGRhdGEgaXMgYSBkb3VibGUsIGFzIFIgYXNzdW1lcyBpdCB0byBiZSBhbiBpbnRlZ2VyIHZhbHVlZCB2ZWN0b3IsIHdoaWNoIHJlc3VsdHMgaW4gb25seSAxcyBhbmQgMHMsIHdoaWNoIHdvdWxkbid0IGJlIGluZm9ybWF0aXZlLiAKCmBgYHtyfQoKIEVQSV8xMDNfcGVyY21ldGhfYmVkZ3JhcGggPC0gcmVhZF9kZWxpbSgifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi9FUEktMTUxLXBlcmNtZXRoLmJlZGdyYXBoIiwgCiAgICAgIlx0IiwgZXNjYXBlX2RvdWJsZSA9IEZBTFNFLCBjb2xfbmFtZXMgPSBGQUxTRSwgCiAgICAgY29sX3R5cGVzID0gY29scyhYNCA9IGNvbF9kb3VibGUoKSksIAogICAgIHRyaW1fd3MgPSBUUlVFKQogCiBFUElfMTAzX3BlcmNtZXRoX2JlZGdyYXBoIDwtIGFzLmRhdGEudGFibGUoRVBJXzEwM19wZXJjbWV0aF9iZWRncmFwaCkKIAogaGVhZChFUElfMTAzX3BlcmNtZXRoX2JlZGdyYXBoKQogCiBwcmludChFUElfMTAzX3BlcmNtZXRoX2JlZGdyYXBoWzcsXSkKCmBgYAoKSSB0b3NzZWQgYW4gZXh0cmEgcHJpbnQgc3RhdGVtZW50IGluLCBqdXN0IHRvIHZlcmlmeSB0aGF0IHNvbWV0aGluZyB0aGF0J3MgZG91YmxlIHZhbHVlZCByZWFsbHkgaXMuIAoKTmV4dCBJIGV4dHJhY3QgaW5mb3JtYXRpb24gb25seSBvbiB0aGUgNDEgRE1Scywgc2luY2UgdGhhdCdzIGFsbCB0aGF0cyBvZiBpbnRlcmVzdAoKYGBge3J9CgpFUElfMTAzX0RNUnMgPC0gRVBJXzEwM19wZXJjbWV0aF9iZWRncmFwaFtFUElfMTAzX3BlcmNtZXRoX2JlZGdyYXBoJFgxICVpbiUgRGlmZk1ldGhSZWdpb25zJFgxLF0KCgpFUElfMTAzX0RNUnMkTG9jIDwtIHBhc3RlMChFUElfMTAzX0RNUnMkWDEsICItIiwgRVBJXzEwM19ETVJzJFgyKQoKCmhlYWQoRVBJXzEwM19ETVJzKQoKRVBJXzEwM19ETVJzIDwtIEVQSV8xMDNfRE1Sc1tFUElfMTAzX0RNUnMkTG9jICVpbiUgRGlmZk1ldGhSZWdpb25zJExvYyxdCgpoZWFkKEVQSV8xMDNfRE1ScykKCkVQSV9ETVJzIDwtIGFzLmRhdGEudGFibGUoY2JpbmQoRVBJXzEwM19ETVJzJExvYywgRVBJXzEwM19ETVJzJFg0KSkKCgoKY29sbmFtZXMoRVBJX0RNUnMpWzFdIDwtICJETVJMb2MiCmNvbG5hbWVzKEVQSV9ETVJzKVsyXSA8LSAiRVBJXzE1MSIKaGVhZChFUElfRE1ScykKCmBgYAoKTm93IEkgZ2V0IHRvIGRvIHRoZSB3aG9sZSBsb29wIHRoaW5nLCBpdGVyYXRpbmcgb3ZlciB0aGUgcmVtYWluaW5nIHNhbXBsZXMgYW5kIHJlYWRpbmcgdGhlbSBpbiwgZXh0cmFjdGluZyB0aGUgRE1ScyBhbmQgc2F2aW5nIHRoZW0gdG8gbXkgRE1SIG1hdHJpeC4KCmBgYHtyfQoKZm9yKGkgaW4gMjpsZW5ndGgoc2FtcGxlLmZpbGVzKSkgICB7CgogIHRlbXAgPC0gcmVhZF9kZWxpbShwYXN0ZTAoIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvIiwgc2FtcGxlLmZpbGVzW2ldKSwKICAgICJcdCIsIGVzY2FwZV9kb3VibGUgPSBGQUxTRSwgY29sX25hbWVzID0gRkFMU0UsCiAgICBjb2xfdHlwZXMgPSBjb2xzKFg0ID0gY29sX2RvdWJsZSgpKSwKICAgIHRyaW1fd3MgPSBUUlVFKQoKICB0ZW1wIDwtIGFzLmRhdGEudGFibGUodGVtcCkKCiAgdGVtcF9ETVJzIDwtIHRlbXBbdGVtcCRYMSAlaW4lIERpZmZNZXRoUmVnaW9ucyRYMSxdCgoKICB0ZW1wX0RNUnMkTG9jIDwtIHBhc3RlMCh0ZW1wX0RNUnMkWDEsICItIiwgdGVtcF9ETVJzJFgyKQoKCiAgdGVtcF9ETVJzIDwtIHRlbXBfRE1Sc1t0ZW1wX0RNUnMkTG9jICVpbiUgRGlmZk1ldGhSZWdpb25zJExvYyxdCgogIEVQSV9ETVJzJHRlbXAgPC0gdGVtcF9ETVJzJFg0CgogIGNvbG5hbWVzKEVQSV9ETVJzKVtuY29sKEVQSV9ETVJzKV0gPC0gc3Vic3RyKHNhbXBsZS5maWxlc1tpXSwgMSwgNykKCgp9CgpoZWFkKEVQSV9ETVJzKQoKIyMgVGhpcyBpcyBoZXJlIGJlY2F1c2UgZm9yIG9zbWUgcmVhc29uIEVQSV8xMDMgZ2V0cyBicnVnaHQgaW4gYXMgY2hhcmFjdGVycyBhcyBvcHBvc2VkIHRvIGRvdWJsZXMuIE5lZWQgdG8gZmlndXJlIG91dCB3aHksIGJ1dCB0aGlzIGZpeGVzIGl0IGZvciBub3cKRVBJX0RNUnMkRVBJXzE1MSA8LSBhcy5udW1lcmljKEVQSV9ETVJzJEVQSV8xNTEpCgpgYGAKCgpIZXJlIEkgY2FsY3VsYXRlIHRyZWF0bWVudCBtZWFucyBhbmQgc2F2ZSB0aGVtIHRvIGEgdmVjdG9yIG9mIHRyZWF0bWVudCBtZWFucyBieSBsb2NhdGlvbgoKYGBge3J9Cgp0cmVhdG1lbnQubWVhbnMgPC0gYXMuZGF0YS5mcmFtZShFUElfRE1ScyRETVJMb2MpCgp0cmVhdG1lbnQubWVhbnMkQW1iaWVudCA8LSBhcHBseShjYmluZChFUElfRE1ScyRgRVBJLTE1MWAsIEVQSV9ETVJzJGBFUEktMTUyYCwgRVBJX0RNUnMkYEVQSS0xNTNgLCBFUElfRE1ScyRgRVBJLTE1NGApICxNQVJHSU4gPSAxLCBGVU4gPSBtZWFuKQoKdHJlYXRtZW50Lm1lYW5zJExvdyA8LSBhcHBseShjYmluZChFUElfRE1ScyRgRVBJLTE1OWAsIEVQSV9ETVJzJGBFUEktMTYwYCwgRVBJX0RNUnMkYEVQSS0xNjFgLCBFUElfRE1ScyRgRVBJLTE2MmApICxNQVJHSU4gPSAxLCBGVU4gPSBtZWFuKQoKdHJlYXRtZW50Lm1lYW5zJFN1cGVyTG93IDwtIGFwcGx5KGNiaW5kKEVQSV9ETVJzJGBFUEktMTY3YCwgRVBJX0RNUnMkYEVQSS0xNjhgLCBFUElfRE1ScyRgRVBJLTE2OWAsIEVQSV9ETVJzJGBFUEktMTcwYCkgLE1BUkdJTiA9IDEsIEZVTiA9IG1lYW4pCgpoZWFkKHRyZWF0bWVudC5tZWFucykKYGBgCgpUaGlzLi4uIG1ha2VzIGEgcmVhbGx5IHVnbHkgYW5kIGhhcmQgdG8gcmVhZCBncmFwaC4gT24gdGhlIFggYXhpcyBpcyB0aGUgRE1SIGxvY2F0aW9uLCBhbmQgdGhlIFkgYXhpcyBpcyBwcm9wb3J0aW9uIGVtdGh5bGF0ZWQuIEJhcnMgYXJlIGFtYmllbnQsIEdyZWVuIGRvdHMgYXJlIGxvdyB0cmVhdG1lbnRzLCBhbmQgcmVkIGRvdHMgYXJlIFN1cGVyIGxvdyB0cmVhdG1lbnRzLgoKSXQncyBub3QgcmVhbGx5IGluZm9ybWF0aXZlLCBidXQgSSBtYWRlIGl0LCBzbyBJIGZpZ3VyZWQgSSdkIHNob3cgaXQuIApgYGB7cn0KCiBwbG90KHRyZWF0bWVudC5tZWFucyRgRVBJX0RNUnMkRE1STG9jYCwgdHJlYXRtZW50Lm1lYW5zJEFtYmllbnQsIGNvbCA9ICJibHVlIiwgcGNoID0gMTYpCiAKIHBvaW50cyh0cmVhdG1lbnQubWVhbnMkYEVQSV9ETVJzJERNUkxvY2AsIHRyZWF0bWVudC5tZWFucyRMb3csIGNvbCA9ICJncmVlbiIsIHBjaCA9IDE2KQogCiBwb2ludHModHJlYXRtZW50Lm1lYW5zJGBFUElfRE1ScyRETVJMb2NgLCB0cmVhdG1lbnQubWVhbnMkU3VwZXJMb3csIGNvbCA9ICJyZWQiLCBwY2ggPSAxNikKYGBgCgoKSSBsaWtlIHRoaXMgYSBsb3QgYmV0dGVyLCBpdCBtYWtlcyBib3hwbG90cyBmb3IgZWFjaCBETVIgd2l0aCBlYWNoIHRyZWF0bWVudC4gSSBsaWtlIGhvdyB0aGlzIHNob3dzIHRoZSB2YXJpYWlibGl0eSBiZXR3ZWVuIHNhbXBsZXMsIGFzIHdlbGwgYXMgbG9jYXRpb24gaW5mb3JtYXRpb24uIFRoZSBiZWxvdyBjb2RlIG91dHB1dHMgdG8gUi1zdHVkaW8sIGFzIHdlbGwgYXMgYSBQREYgZm9yIGVhc2llciB2aWV3aW5nLgoKYGBge3J9CgoKCiMgIGZvcihpIGluIDE6bnJvdyh0cmVhdG1lbnQubWVhbnMpKSAgIHsKIyAgICAKIyAKIyAgIGJveHBsb3QodChjYmluZChFUElfRE1Sc1tpLDJdLCBFUElfRE1Sc1tpLDNdLCBFUElfRE1Sc1tpLDRdLCBFUElfRE1Sc1tpLDVdKSkseGxpbSA9IGMoMC41LCAzLjUpLCB5bGltID0gYyhtaW4oRVBJX0RNUnNbaSwyOjEzXSksIG1heChFUElfRE1Sc1tpLDI6MTNdKSksIGJveGZpbGwgPSAiYmx1ZSIsIG5hbWVzID0gIkFtYmllbnQiLCBzaG93Lm5hbWVzID0gVFJVRSwgeWxhYiA9ICJQcm9wb3J0aW9uIG9mIHJlYWRzIG1ldGh5bGF0ZWQiKQojIAojIGJveHBsb3QodChjYmluZChFUElfRE1Sc1tpLDZdLCBFUElfRE1Sc1tpLDddLCBFUElfRE1Sc1tpLDhdLCBFUElfRE1Sc1tpLDldKSksIHhheHQgPSAibiIsIGFkZCA9IFRSVUUsIGF0ID0gMiwgYm94ZmlsbCA9ICJncmVlbiIpCiMgCiMgYm94cGxvdCh0KGNiaW5kKEVQSV9ETVJzW2ksMTBdLCBFUElfRE1Sc1tpLDExXSwgRVBJX0RNUnNbaSwxMl0sIEVQSV9ETVJzW2ksMTNdKSksIHhheHQgPSAibiIsIGFkZCA9IFRSVUUsIGF0ID0gMywgYm94ZmlsbCA9ICJyZWQiKQojIAojIGF4aXMoc2lkZSA9IDEsIGF0ID0gMiwgbGFiZWxzID0gIkxvdyIpCiMgYXhpcyhzaWRlID0gMSwgYXQgPSAzLCBsYWJlbHMgPSAiU3VwZXIgTG93IikKIyAKIyB0aXRsZShwYXN0ZTAoIlByb3BvcnRpb24gb2YgTWV0aHlsYXRlZCByZWFkcyBmb3IgRE1SIFxuIGxvY2F0ZWQgYXQgIiwgRVBJX0RNUnNbaSwxXSkpCiMgCiMgCiMgfQoKCnBkZihmaWxlID0gInRocmVleC1ETVItQm94LVBsb3RzLnBkZiIpCgpmb3IoaSBpbiAxOm5yb3codHJlYXRtZW50Lm1lYW5zKSkgICB7CgoKICBib3hwbG90KHQoY2JpbmQoRVBJX0RNUnNbaSw2XSwgRVBJX0RNUnNbaSw3XSwgRVBJX0RNUnNbaSwxMF0sIEVQSV9ETVJzW2ksMTFdKSkseGxpbSA9IGMoMC41LCAzLjUpLCB5bGltID0gYyhtaW4oRVBJX0RNUnNbaSwyOjEzXSksIG1heChFUElfRE1Sc1tpLDI6MTNdKSksIGJveGZpbGwgPSAiYmx1ZSIsIG5hbWVzID0gIkFtYmllbnQiLCBzaG93Lm5hbWVzID0gVFJVRSwgeWxhYiA9ICJQcm9wb3J0aW9uIG9mIHJlYWRzIG1ldGh5bGF0ZWQiKQoKYm94cGxvdCh0KGNiaW5kKEVQSV9ETVJzW2ksMl0sIEVQSV9ETVJzW2ksM10sIEVQSV9ETVJzW2ksOF0sIEVQSV9ETVJzW2ksOV0pKSwgeGF4dCA9ICJuIiwgYWRkID0gVFJVRSwgYXQgPSAyLCBib3hmaWxsID0gImdyZWVuIikKCmJveHBsb3QodChjYmluZChFUElfRE1Sc1tpLDRdLCBFUElfRE1Sc1tpLDVdLCBFUElfRE1Sc1tpLDEyXSwgRVBJX0RNUnNbaSwxM10pKSwgeGF4dCA9ICJuIiwgYWRkID0gVFJVRSwgYXQgPSAzLCBib3hmaWxsID0gInJlZCIpCgpheGlzKHNpZGUgPSAxLCBhdCA9IDIsIGxhYmVscyA9ICJMb3ciKQpheGlzKHNpZGUgPSAxLCBhdCA9IDMsIGxhYmVscyA9ICJTdXBlciBMb3ciKQoKdGl0bGUocGFzdGUwKCJQcm9wb3J0aW9uIG9mIE1ldGh5bGF0ZWQgcmVhZHMgZm9yIERNUiBcbiBsb2NhdGVkIGF0ICIsIEVQSV9ETVJzW2ksMV0pKQoKCn0KCmRldi5vZmYoKQoKYGBgCgpBZGQgYSBuZXcgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpJbnNlcnQgQ2h1bmsqIGJ1dHRvbiBvbiB0aGUgdG9vbGJhciBvciBieSBwcmVzc2luZyAqQ3RybCtBbHQrSSouCgpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkN0cmwrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4=