Useful functions
#d<-read.table("Data/Test/youpi.tsv", h=T, sep="\t")
#d1<-read.table("Data/Test/tralala.txt", h=T, sep="\t")
readData <- function(h0ha, h0gBGC) {
d<-read.table(h0ha, h=T, sep="\t")
d1<-read.table(h0gBGC, h=T, sep="\t")
d1$Oracle <- 2
d<-rbind(d, d1)
d$Oracle <- as.factor(d$Oracle)
levels(d$Oracle)[levels(d$Oracle)=="0"] <- "H0"
levels(d$Oracle)[levels(d$Oracle)=="1"] <- "HA"
levels(d$Oracle)[levels(d$Oracle)=="2"] <- "H0bGC"
return (d)
}
plotOrderedFactors <- function(d, method, maxorder, decreasing, name, plot_y) {
# Get the three colors that I want
colors_3 <- scale_color_brewer(palette="Dark2")$palette(3)
ord <- order(d[which(colnames(d)==method)], decreasing=decreasing)
d2 <- d[ord, ]
if (plot_y) {
plot(c(0.5, 2, 3.5),c (1, 50, maxorder), ylim=rev(c(1, maxorder)), type="n", xaxt='n', xlab="", ylab="")
title(ylab = "Rank", cex.lab = 1.5, line = 1.7)
}
else {
plot(c(0.5, 2, 3.5),c (1, 50, maxorder), ylim=rev(c(1, maxorder)), type="n", xaxt='n', xlab="", ylab="", yaxt='n')
}
title(xlab = name, cex.lab = 1.5, line = 0.5)
colors_n <- sapply(as.numeric(d2$Oracle), function(x) {return (colors_3[x])})
points(as.numeric(d2$Oracle) + rnorm(n=length(d2$Oracle), mean=0, sd=0.1), 1:length(ord), pch = as.numeric(d2$Oracle), cex=1, col= colors_n, lwd=2)
return(d2)
}
plotAllMethods <- function (maxorder, nrows, ncols, withPCAndOC=TRUE) {
if (nrows > 1) {
print("ERROR : more than 1 row")
return()
}
if (withPCAndOC) {
layout(matrix(c(1, 2, 3, 4, 5, 6, 7, 8), nrows, ncols, byrow = TRUE), widths=rep(3, 8), heights=rep(0.1, 8))
}
else {
layout(matrix(c(1, 2, 3, 4, 5, 6), nrows, ncols, byrow = TRUE), widths=rep(3, 6), heights=rep(0.1, 6))
}
#par(oma=c(0,0,0,0)) # all sides have 3 lines of space
par(mar = c(2,3,2,0) + 0.1) ## default is c(5,4,4,2) + 0.1
temp = plotOrderedFactors(d, "Identical_LG08", maxorder, TRUE, "Identical", plot_y=TRUE)
temp = plotOrderedFactors(d, "Topological_LG08", maxorder, TRUE, "Topological", plot_y=FALSE)
temp = plotOrderedFactors(d, "PCOC", maxorder, TRUE, "PCOC", plot_y=FALSE)
if (withPCAndOC) {
temp = plotOrderedFactors(d, "PC", maxorder, TRUE, "PC", plot_y=FALSE)
temp = plotOrderedFactors(d, "OC", maxorder, TRUE, "OC", plot_y=FALSE)
}
temp = plotOrderedFactors(d, "Tdg09_1MinusLRT", maxorder, TRUE, "Tdg09", plot_y=FALSE)
temp = plotOrderedFactors(d, "Mutinomial_1MinusLRT", maxorder, TRUE, "Multinomial", plot_y=FALSE)
temp = plotOrderedFactors(d, "Diffsel_max", maxorder, TRUE, "Diffsel", plot_y=FALSE)
}
plotViolinPlots <- function (nrows, ncols, withPCAndOC=TRUE) {
if (nrows > 1) {
print("ERROR : more than 1 row")
return()
}
par(mar = c(2,3,2,0) + 0.1) ## default is c(5,4,4,2) + 0.1
p1 <- ggplot(d, aes(x=Oracle, y=PCOC, color=Oracle, fill=Oracle)) +
geom_violin(trim=TRUE) +
scale_color_brewer(palette="Dark2") +
scale_fill_brewer(palette="Dark2")+
rremove("x.text") +
theme(legend.position="none") +
labs(y = "")
p2 <- ggplot(d, aes(x=Oracle, y=PC, color=Oracle, fill=Oracle)) +
geom_violin(trim=TRUE) +
scale_color_brewer(palette="Dark2") +
scale_fill_brewer(palette="Dark2")+ rremove("x.text") + theme(legend.position="none")+ rremove("y.text") +
labs(y = "")
p3 <- ggplot(d, aes(x=Oracle, y=OC, color=Oracle, fill=Oracle)) +
geom_violin(trim=TRUE) +
scale_color_brewer(palette="Dark2") +
scale_fill_brewer(palette="Dark2")+ rremove("x.text") + theme(legend.position="none")+ rremove("y.text") +
labs(y = "")
p4 <- ggplot(d, aes(x=Oracle, y=Identical_LG08, color=Oracle, fill=Oracle)) +
geom_violin(trim=TRUE) +
scale_color_brewer(palette="Dark2") +
scale_fill_brewer(palette="Dark2")+ rremove("x.text") + theme(legend.position="none")+ rremove("y.text") +
labs(y = "")
p5 <- ggplot(d, aes(x=Oracle, y=Topological_LG08, color=Oracle, fill=Oracle)) +
geom_violin(trim=TRUE) +
scale_color_brewer(palette="Dark2") +
scale_fill_brewer(palette="Dark2")+ rremove("x.text") + theme(legend.position="none")+ rremove("y.text") +
labs(y = "")
p6 <- ggplot(d, aes(x=Oracle, y=Tdg09_1MinusLRT, color=Oracle, fill=Oracle)) +
geom_violin(trim=TRUE) +
scale_color_brewer(palette="Dark2") +
scale_fill_brewer(palette="Dark2")+ rremove("x.text") + theme(legend.position="none")+ rremove("y.text") +
labs(y = "")
p7 <- ggplot(d, aes(x=Oracle, y=Mutinomial_1MinusLRT, color=Oracle, fill=Oracle)) +
geom_violin(trim=TRUE) +
scale_color_brewer(palette="Dark2") +
scale_fill_brewer(palette="Dark2")+ rremove("x.text") + theme(legend.position="none")+ rremove("y.text") +
labs(y = "")
p8 <- ggplot(d, aes(x=Oracle, y=Diffsel_max, color=Oracle, fill=Oracle)) +
geom_violin(trim=TRUE) +
scale_color_brewer(palette="Dark2") +
scale_fill_brewer(palette="Dark2")+ rremove("x.text") + theme(legend.position="none")+ rremove("y.text") +
labs(y = "")
if(withPCAndOC) {
ggarrange(p4, p5, p1, p2, p3, p6, p7, p8 ,
labels = c("Identical", "Topological", "PCOC", "PC", "OC", "Tdg09", "Multinomial", "Diffsel"),
ncol = ncols, nrow = nrows)
}
else {
ggarrange(p4, p5, p1, p6, p7, p8 ,
labels = c("Identical", "Topological", "PCOC", "Tdg09", "Multinomial", "Diffsel"),
ncol = ncols, nrow = nrows)
}
}
By method, count the numbers of sites of each type from rank 1 to the last
plotCumSum <- function (d, method, maxorder, decreasing, name, plot_y, legend=FALSE) {
# Get the three colors that I want
colors_3 <- scale_color_brewer(palette="Dark2")$palette(3)
lwidth <- 3
ord <- order(d[which(colnames(d)==method)], decreasing=decreasing)
d2 <- d[ord, ]
count_h0=ave(d2$Oracle=="H0", "H0", FUN=cumsum)[1:maxorder]
count_ha=ave(d2$Oracle=="HA", "HA", FUN=cumsum)[1:maxorder]
count_h0bGC=ave(d2$Oracle=="H0bGC", "H0bGC", FUN=cumsum)[1:maxorder]
data <- data.frame(H0=count_h0, HA=count_ha, H0bGC=count_h0bGC)
maximum_y = max(data)
if (plot_y) {plot(data$H0, t="l", col=colors_3[1], lwd=lwidth, xlim=c(0, maxorder), ylim=c(0, maximum_y), xlab="", ylab="", main=name)
}
else {
plot(data$H0, t="l", col=colors_3[1], lwd=lwidth, xlim=c(0, maxorder), ylim=c(0, maximum_y), xlab="", ylab="", main=name, yaxt='n')
}
lines(data$HA, col=colors_3[2], lwd=lwidth)
lines(data$H0bGC, col=colors_3[3], lwd=lwidth)
if (legend) {
legend("topleft", col=colors_3, lwd=lwidth, legend=c("H0", "HA", "H0bGC"))
}
return(data)
}
plotCumSums <- function (nrows, ncols, maxorder, withPCAndOC = TRUE) {
if (nrows > 1) {
print("ERROR : more than 1 row")
return()
}
if (withPCAndOC) {
layout(matrix(c(1, 2, 3, 4, 5, 6, 7, 8), nrows, ncols, byrow = TRUE), widths=rep(3, 8), heights=rep(0.1, 8))
}
else {
layout(matrix(c(1, 2, 3, 4, 5, 6), nrows, ncols, byrow = TRUE), widths=rep(3, 6), heights=rep(0.1, 6))
}
par(mar = c(2,3,2,0) + 0.1) ## default is c(5,4,4,2) + 0.1
temp = plotCumSum(d, "Identical_LG08", maxorder, TRUE, "Identical", plot_y=TRUE)
temp = plotCumSum(d, "Topological_LG08", maxorder, TRUE, "Topological", plot_y=FALSE)
temp = plotCumSum(d, "PCOC", maxorder, TRUE, "PCOC", plot_y=FALSE)
if (withPCAndOC) {
temp = plotCumSum(d, "PC", maxorder, TRUE, "PC", plot_y=FALSE)
temp = plotCumSum(d, "OC", maxorder, TRUE, "OC", plot_y=FALSE)
}
temp = plotCumSum(d, "Tdg09_1MinusLRT", maxorder, TRUE, "Tdg09", plot_y=FALSE)
temp = plotCumSum(d, "Mutinomial_1MinusLRT", maxorder, TRUE, "Multinomial", plot_y=FALSE)
temp = plotCumSum(d, "Diffsel_max", maxorder, TRUE, "Diffsel", plot_y=FALSE)
}
LS0tCnRpdGxlOiAiUGxvdHRpbmcgcmVzdWx0cyBhY3Jvc3MgSDAsIEhBLCBIMGJHQyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCiMgTG9hZGluZwoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3B1YnIpCmBgYAoKIyBVc2VmdWwgZnVuY3Rpb25zCgpgYGB7cn0KI2Q8LXJlYWQudGFibGUoIkRhdGEvVGVzdC95b3VwaS50c3YiLCBoPVQsIHNlcD0iXHQiKQojZDE8LXJlYWQudGFibGUoIkRhdGEvVGVzdC90cmFsYWxhLnR4dCIsIGg9VCwgc2VwPSJcdCIpCnJlYWREYXRhIDwtIGZ1bmN0aW9uKGgwaGEsIGgwZ0JHQykgewogIGQ8LXJlYWQudGFibGUoaDBoYSwgaD1ULCBzZXA9Ilx0IikKICBkMTwtcmVhZC50YWJsZShoMGdCR0MsIGg9VCwgc2VwPSJcdCIpCiAgZDEkT3JhY2xlIDwtIDIKICBkPC1yYmluZChkLCBkMSkKICBkJE9yYWNsZSA8LSBhcy5mYWN0b3IoZCRPcmFjbGUpCiAgbGV2ZWxzKGQkT3JhY2xlKVtsZXZlbHMoZCRPcmFjbGUpPT0iMCJdIDwtICJIMCIKICBsZXZlbHMoZCRPcmFjbGUpW2xldmVscyhkJE9yYWNsZSk9PSIxIl0gPC0gIkhBIgogIGxldmVscyhkJE9yYWNsZSlbbGV2ZWxzKGQkT3JhY2xlKT09IjIiXSA8LSAiSDBiR0MiCiAgcmV0dXJuIChkKQp9CmBgYAoKCmBgYHtyfQpwbG90T3JkZXJlZEZhY3RvcnMgPC0gZnVuY3Rpb24oZCwgbWV0aG9kLCBtYXhvcmRlciwgZGVjcmVhc2luZywgbmFtZSwgcGxvdF95KSB7CiAgIyBHZXQgdGhlIHRocmVlIGNvbG9ycyB0aGF0IEkgd2FudAogIGNvbG9yc18zIDwtIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpJHBhbGV0dGUoMykKICBvcmQgPC0gb3JkZXIoZFt3aGljaChjb2xuYW1lcyhkKT09bWV0aG9kKV0sIGRlY3JlYXNpbmc9ZGVjcmVhc2luZykKICBkMiA8LSBkW29yZCwgXQogIGlmIChwbG90X3kpIHsKICBwbG90KGMoMC41LCAyLCAzLjUpLGMgKDEsIDUwLCBtYXhvcmRlciksIHlsaW09cmV2KGMoMSwgbWF4b3JkZXIpKSwgdHlwZT0ibiIsIHhheHQ9J24nLCB4bGFiPSIiLCB5bGFiPSIiKQogIHRpdGxlKHlsYWIgPSAiUmFuayIsIGNleC5sYWIgPSAxLjUsIGxpbmUgPSAxLjcpCiAgfQogIGVsc2UgewogIHBsb3QoYygwLjUsIDIsIDMuNSksYyAoMSwgNTAsIG1heG9yZGVyKSwgeWxpbT1yZXYoYygxLCBtYXhvcmRlcikpLCB0eXBlPSJuIiwgeGF4dD0nbicsIHhsYWI9IiIsIHlsYWI9IiIsIHlheHQ9J24nKQogIH0KICB0aXRsZSh4bGFiID0gbmFtZSwgY2V4LmxhYiA9IDEuNSwgbGluZSA9IDAuNSkKICBjb2xvcnNfbiA8LSBzYXBwbHkoYXMubnVtZXJpYyhkMiRPcmFjbGUpLCBmdW5jdGlvbih4KSB7cmV0dXJuIChjb2xvcnNfM1t4XSl9KQogIHBvaW50cyhhcy5udW1lcmljKGQyJE9yYWNsZSkgKyBybm9ybShuPWxlbmd0aChkMiRPcmFjbGUpLCBtZWFuPTAsIHNkPTAuMSksIDE6bGVuZ3RoKG9yZCksIHBjaCA9IGFzLm51bWVyaWMoZDIkT3JhY2xlKSwgY2V4PTEsIGNvbD0gY29sb3JzX24sIGx3ZD0yKQogIHJldHVybihkMikKfSAKCmBgYAoKCgpgYGB7cn0KcGxvdEFsbE1ldGhvZHMgPC0gZnVuY3Rpb24gKG1heG9yZGVyLCBucm93cywgbmNvbHMsIHdpdGhQQ0FuZE9DPVRSVUUpIHsKICBpZiAobnJvd3MgPiAxKSB7CiAgICBwcmludCgiRVJST1IgOiBtb3JlIHRoYW4gMSByb3ciKQogICAgcmV0dXJuKCkKICB9CiAgaWYgKHdpdGhQQ0FuZE9DKSB7CiAgbGF5b3V0KG1hdHJpeChjKDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgpLCBucm93cywgbmNvbHMsIGJ5cm93ID0gVFJVRSksIHdpZHRocz1yZXAoMywgOCksIGhlaWdodHM9cmVwKDAuMSwgOCkpCiAgfQogIGVsc2UgewogICAgICBsYXlvdXQobWF0cml4KGMoMSwgMiwgMywgNCwgNSwgNiksIG5yb3dzLCBuY29scywgYnlyb3cgPSBUUlVFKSwgd2lkdGhzPXJlcCgzLCA2KSwgaGVpZ2h0cz1yZXAoMC4xLCA2KSkKCiAgfQogICNwYXIob21hPWMoMCwwLDAsMCkpICAjIGFsbCBzaWRlcyBoYXZlIDMgbGluZXMgb2Ygc3BhY2UgIAogIHBhcihtYXIgPSBjKDIsMywyLDApICsgMC4xKSAjIyBkZWZhdWx0IGlzIGMoNSw0LDQsMikgKyAwLjEKICB0ZW1wID0gcGxvdE9yZGVyZWRGYWN0b3JzKGQsICJJZGVudGljYWxfTEcwOCIsIG1heG9yZGVyLCBUUlVFLCAiSWRlbnRpY2FsIiwgcGxvdF95PVRSVUUpCiAgdGVtcCA9IHBsb3RPcmRlcmVkRmFjdG9ycyhkLCAiVG9wb2xvZ2ljYWxfTEcwOCIsIG1heG9yZGVyLCBUUlVFLCAiVG9wb2xvZ2ljYWwiLCBwbG90X3k9RkFMU0UpCiAgdGVtcCA9IHBsb3RPcmRlcmVkRmFjdG9ycyhkLCAiUENPQyIsIG1heG9yZGVyLCBUUlVFLCAiUENPQyIsIHBsb3RfeT1GQUxTRSkKICBpZiAod2l0aFBDQW5kT0MpIHsKICAgIHRlbXAgPSBwbG90T3JkZXJlZEZhY3RvcnMoZCwgIlBDIiwgbWF4b3JkZXIsIFRSVUUsICJQQyIsIHBsb3RfeT1GQUxTRSkKICAgIHRlbXAgPSBwbG90T3JkZXJlZEZhY3RvcnMoZCwgIk9DIiwgbWF4b3JkZXIsIFRSVUUsICJPQyIsIHBsb3RfeT1GQUxTRSkKICB9CiAgdGVtcCA9IHBsb3RPcmRlcmVkRmFjdG9ycyhkLCAiVGRnMDlfMU1pbnVzTFJUIiwgbWF4b3JkZXIsIFRSVUUsICJUZGcwOSIsIHBsb3RfeT1GQUxTRSkKICB0ZW1wID0gcGxvdE9yZGVyZWRGYWN0b3JzKGQsICJNdXRpbm9taWFsXzFNaW51c0xSVCIsIG1heG9yZGVyLCBUUlVFLCAiTXVsdGlub21pYWwiLCBwbG90X3k9RkFMU0UpCiAgdGVtcCA9IHBsb3RPcmRlcmVkRmFjdG9ycyhkLCAiRGlmZnNlbF9tYXgiLCBtYXhvcmRlciwgVFJVRSwgIkRpZmZzZWwiLCBwbG90X3k9RkFMU0UpCn0KYGBgCgoKYGBge3J9CnBsb3RWaW9saW5QbG90cyA8LSBmdW5jdGlvbiAobnJvd3MsIG5jb2xzLCB3aXRoUENBbmRPQz1UUlVFKSB7CiAgICBpZiAobnJvd3MgPiAxKSB7CiAgICBwcmludCgiRVJST1IgOiBtb3JlIHRoYW4gMSByb3ciKQogICAgcmV0dXJuKCkKICB9CiAgcGFyKG1hciA9IGMoMiwzLDIsMCkgKyAwLjEpICMjIGRlZmF1bHQgaXMgYyg1LDQsNCwyKSArIDAuMQogIHAxIDwtIGdncGxvdChkLCBhZXMoeD1PcmFjbGUsIHk9UENPQywgY29sb3I9T3JhY2xlLCBmaWxsPU9yYWNsZSkpICsgCiAgICBnZW9tX3Zpb2xpbih0cmltPVRSVUUpICsgCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSArIAogICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSsgCiAgICBycmVtb3ZlKCJ4LnRleHQiKSAgKyAKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICAgIGxhYnMoeSA9ICIiKQogIHAyIDwtIGdncGxvdChkLCBhZXMoeD1PcmFjbGUsIHk9UEMsIGNvbG9yPU9yYWNsZSwgZmlsbD1PcmFjbGUpKSArIAogICAgZ2VvbV92aW9saW4odHJpbT1UUlVFKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IkRhcmsyIikgKyAKICAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9IkRhcmsyIikrIHJyZW1vdmUoIngudGV4dCIpICArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKyBycmVtb3ZlKCJ5LnRleHQiKSAgKwogICAgbGFicyh5ID0gIiIpCiAgcDMgPC0gZ2dwbG90KGQsIGFlcyh4PU9yYWNsZSwgeT1PQywgY29sb3I9T3JhY2xlLCBmaWxsPU9yYWNsZSkpICsgCiAgICBnZW9tX3Zpb2xpbih0cmltPVRSVUUpICsgCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSArIAogICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSsgcnJlbW92ZSgieC50ZXh0IikgICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikrIHJyZW1vdmUoInkudGV4dCIpICArCiAgICBsYWJzKHkgPSAiIikKICBwNCA8LSBnZ3Bsb3QoZCwgYWVzKHg9T3JhY2xlLCB5PUlkZW50aWNhbF9MRzA4LCBjb2xvcj1PcmFjbGUsIGZpbGw9T3JhY2xlKSkgKyAKICAgIGdlb21fdmlvbGluKHRyaW09VFJVRSkgKyAKICAgIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpICsgCiAgICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpKyBycmVtb3ZlKCJ4LnRleHQiKSAgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSsgcnJlbW92ZSgieS50ZXh0IikgICsKICAgIGxhYnMoeSA9ICIiKQogIHA1IDwtIGdncGxvdChkLCBhZXMoeD1PcmFjbGUsIHk9VG9wb2xvZ2ljYWxfTEcwOCwgY29sb3I9T3JhY2xlLCBmaWxsPU9yYWNsZSkpICsgCiAgICBnZW9tX3Zpb2xpbih0cmltPVRSVUUpICsgCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSArIAogICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSsgcnJlbW92ZSgieC50ZXh0IikgICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikrIHJyZW1vdmUoInkudGV4dCIpICArCiAgICBsYWJzKHkgPSAiIikKICBwNiA8LSBnZ3Bsb3QoZCwgYWVzKHg9T3JhY2xlLCB5PVRkZzA5XzFNaW51c0xSVCwgY29sb3I9T3JhY2xlLCBmaWxsPU9yYWNsZSkpICsgCiAgICBnZW9tX3Zpb2xpbih0cmltPVRSVUUpICsgCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSArIAogICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSsgcnJlbW92ZSgieC50ZXh0IikgICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikrIHJyZW1vdmUoInkudGV4dCIpICArCiAgICBsYWJzKHkgPSAiIikKICBwNyA8LSBnZ3Bsb3QoZCwgYWVzKHg9T3JhY2xlLCB5PU11dGlub21pYWxfMU1pbnVzTFJULCBjb2xvcj1PcmFjbGUsIGZpbGw9T3JhY2xlKSkgKyAKICAgIGdlb21fdmlvbGluKHRyaW09VFJVRSkgKyAKICAgIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpICsgCiAgICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpKyBycmVtb3ZlKCJ4LnRleHQiKSAgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSsgcnJlbW92ZSgieS50ZXh0IikgICsKICAgIGxhYnMoeSA9ICIiKQogIHA4IDwtIGdncGxvdChkLCBhZXMoeD1PcmFjbGUsIHk9RGlmZnNlbF9tYXgsIGNvbG9yPU9yYWNsZSwgZmlsbD1PcmFjbGUpKSArIAogICAgZ2VvbV92aW9saW4odHJpbT1UUlVFKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IkRhcmsyIikgKyAKICAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9IkRhcmsyIikrIHJyZW1vdmUoIngudGV4dCIpICArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKyBycmVtb3ZlKCJ5LnRleHQiKSAgKwogICAgbGFicyh5ID0gIiIpCiAgaWYod2l0aFBDQW5kT0MpIHsKICAgIGdnYXJyYW5nZShwNCwgcDUsIHAxLCBwMiwgcDMsIHA2LCBwNywgcDggLCAKICAgICAgICAgIGxhYmVscyA9IGMoIklkZW50aWNhbCIsICJUb3BvbG9naWNhbCIsICJQQ09DIiwgIlBDIiwgIk9DIiwgIlRkZzA5IiwgIk11bHRpbm9taWFsIiwgIkRpZmZzZWwiKSwKICAgICAgICAgIG5jb2wgPSBuY29scywgbnJvdyA9IG5yb3dzKQogIH0KICBlbHNlIHsKICAgIGdnYXJyYW5nZShwNCwgcDUsIHAxLCBwNiwgcDcsIHA4ICwgCiAgICAgICAgICBsYWJlbHMgPSBjKCJJZGVudGljYWwiLCAiVG9wb2xvZ2ljYWwiLCAiUENPQyIsICJUZGcwOSIsICJNdWx0aW5vbWlhbCIsICJEaWZmc2VsIiksCiAgICAgICAgICBuY29sID0gbmNvbHMsIG5yb3cgPSBucm93cykKICB9CgogIH0KYGBgCgojIyMgQnkgbWV0aG9kLCBjb3VudCB0aGUgbnVtYmVycyBvZiBzaXRlcyBvZiBlYWNoIHR5cGUgZnJvbSByYW5rIDEgdG8gdGhlIGxhc3QKYGBge3J9CnBsb3RDdW1TdW0gPC0gZnVuY3Rpb24gKGQsIG1ldGhvZCwgbWF4b3JkZXIsIGRlY3JlYXNpbmcsIG5hbWUsIHBsb3RfeSwgbGVnZW5kPUZBTFNFKSB7CiAgIyBHZXQgdGhlIHRocmVlIGNvbG9ycyB0aGF0IEkgd2FudAogIGNvbG9yc18zIDwtIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpJHBhbGV0dGUoMykKICBsd2lkdGggPC0gMwogIG9yZCA8LSBvcmRlcihkW3doaWNoKGNvbG5hbWVzKGQpPT1tZXRob2QpXSwgZGVjcmVhc2luZz1kZWNyZWFzaW5nKQogIGQyIDwtIGRbb3JkLCBdCiAgY291bnRfaDA9YXZlKGQyJE9yYWNsZT09IkgwIiwgIkgwIiwgRlVOPWN1bXN1bSlbMTptYXhvcmRlcl0KICBjb3VudF9oYT1hdmUoZDIkT3JhY2xlPT0iSEEiLCAiSEEiLCBGVU49Y3Vtc3VtKVsxOm1heG9yZGVyXQogIGNvdW50X2gwYkdDPWF2ZShkMiRPcmFjbGU9PSJIMGJHQyIsICJIMGJHQyIsIEZVTj1jdW1zdW0pWzE6bWF4b3JkZXJdCiAgZGF0YSA8LSBkYXRhLmZyYW1lKEgwPWNvdW50X2gwLCBIQT1jb3VudF9oYSwgSDBiR0M9Y291bnRfaDBiR0MpCiAgbWF4aW11bV95ID0gbWF4KGRhdGEpCiAgaWYgKHBsb3RfeSkge3Bsb3QoZGF0YSRIMCwgdD0ibCIsIGNvbD1jb2xvcnNfM1sxXSwgbHdkPWx3aWR0aCwgeGxpbT1jKDAsIG1heG9yZGVyKSwgeWxpbT1jKDAsIG1heGltdW1feSksIHhsYWI9IiIsIHlsYWI9IiIsIG1haW49bmFtZSkKICB9CiAgZWxzZSB7CiAgICBwbG90KGRhdGEkSDAsIHQ9ImwiLCBjb2w9Y29sb3JzXzNbMV0sIGx3ZD1sd2lkdGgsIHhsaW09YygwLCBtYXhvcmRlciksIHlsaW09YygwLCBtYXhpbXVtX3kpLCB4bGFiPSIiLCB5bGFiPSIiLCBtYWluPW5hbWUsIHlheHQ9J24nKQogIH0KICBsaW5lcyhkYXRhJEhBLCBjb2w9Y29sb3JzXzNbMl0sIGx3ZD1sd2lkdGgpCiAgbGluZXMoZGF0YSRIMGJHQywgY29sPWNvbG9yc18zWzNdLCBsd2Q9bHdpZHRoKQogIGlmIChsZWdlbmQpIHsKICAgIGxlZ2VuZCgidG9wbGVmdCIsIGNvbD1jb2xvcnNfMywgbHdkPWx3aWR0aCwgbGVnZW5kPWMoIkgwIiwgIkhBIiwgIkgwYkdDIikpCiAgfQogIHJldHVybihkYXRhKQp9CmBgYAoKCmBgYHtyfQpwbG90Q3VtU3VtcyA8LSBmdW5jdGlvbiAobnJvd3MsIG5jb2xzLCBtYXhvcmRlciwgd2l0aFBDQW5kT0MgPSBUUlVFKSB7CiAgaWYgKG5yb3dzID4gMSkgewogICAgcHJpbnQoIkVSUk9SIDogbW9yZSB0aGFuIDEgcm93IikKICAgIHJldHVybigpCiAgfQogIGlmICh3aXRoUENBbmRPQykgewogICAgbGF5b3V0KG1hdHJpeChjKDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgpLCBucm93cywgbmNvbHMsIGJ5cm93ID0gVFJVRSksIHdpZHRocz1yZXAoMywgOCksIGhlaWdodHM9cmVwKDAuMSwgOCkpCiAgfQogIGVsc2UgewogICAgbGF5b3V0KG1hdHJpeChjKDEsIDIsIDMsIDQsIDUsIDYpLCBucm93cywgbmNvbHMsIGJ5cm93ID0gVFJVRSksIHdpZHRocz1yZXAoMywgNiksIGhlaWdodHM9cmVwKDAuMSwgNikpCiAgfQogIHBhcihtYXIgPSBjKDIsMywyLDApICsgMC4xKSAjIyBkZWZhdWx0IGlzIGMoNSw0LDQsMikgKyAwLjEKICB0ZW1wID0gcGxvdEN1bVN1bShkLCAiSWRlbnRpY2FsX0xHMDgiLCBtYXhvcmRlciwgVFJVRSwgIklkZW50aWNhbCIsIHBsb3RfeT1UUlVFKQogIHRlbXAgPSBwbG90Q3VtU3VtKGQsICJUb3BvbG9naWNhbF9MRzA4IiwgbWF4b3JkZXIsIFRSVUUsICJUb3BvbG9naWNhbCIsIHBsb3RfeT1GQUxTRSkKICB0ZW1wID0gcGxvdEN1bVN1bShkLCAiUENPQyIsIG1heG9yZGVyLCBUUlVFLCAiUENPQyIsIHBsb3RfeT1GQUxTRSkKICBpZiAod2l0aFBDQW5kT0MpIHsKICAgIHRlbXAgPSBwbG90Q3VtU3VtKGQsICJQQyIsIG1heG9yZGVyLCBUUlVFLCAiUEMiLCBwbG90X3k9RkFMU0UpCiAgICB0ZW1wID0gcGxvdEN1bVN1bShkLCAiT0MiLCBtYXhvcmRlciwgVFJVRSwgIk9DIiwgcGxvdF95PUZBTFNFKQogIH0KICB0ZW1wID0gcGxvdEN1bVN1bShkLCAiVGRnMDlfMU1pbnVzTFJUIiwgbWF4b3JkZXIsIFRSVUUsICJUZGcwOSIsIHBsb3RfeT1GQUxTRSkKICB0ZW1wID0gcGxvdEN1bVN1bShkLCAiTXV0aW5vbWlhbF8xTWludXNMUlQiLCBtYXhvcmRlciwgVFJVRSwgIk11bHRpbm9taWFsIiwgcGxvdF95PUZBTFNFKQogIHRlbXAgPSBwbG90Q3VtU3VtKGQsICJEaWZmc2VsX21heCIsIG1heG9yZGVyLCBUUlVFLCAiRGlmZnNlbCIsIHBsb3RfeT1GQUxTRSkKfQpgYGAKCgojIEZpcnN0LCB3ZSBhbmFseXplIHRoZSByZXN1bHRzIG9uIHRoZSBBbWFyYW50aCBwaHlsb2dlbnkKYGBge3J9CiNkIDwtIHJlYWREYXRhKCJEYXRhL1Rlc3QveW91cGkudHN2IiwgIkRhdGEvVGVzdC90cmFsYWxhLnR4dCIpCmQgPC0gcmVhZERhdGEoIkRhdGEvaDBoYV9hbWFyYW50aC50c3YiLCAiRGF0YS9oMF9nYmdjX2FtYXJhbnRoLnRzdiIpCmBgYAoKIyMgQWxsIHNpdGVzCgpgYGB7cn0KcGxvdEFsbE1ldGhvZHMoMjAwMCwgMSwgNiwgd2l0aFBDQW5kT0MgPSBGQUxTRSkKYGBgCgoKIyMgWm9vbWluZyBpbgpgYGB7cn0KcGxvdEFsbE1ldGhvZHMoMTUwLCAxLCA4KQpgYGAKCmBgYHtyfQpwbG90QWxsTWV0aG9kcygxNTAsIDEsIDYsIHdpdGhQQ0FuZE9DID0gRkFMU0UpCmBgYAoKCiMjIFZpb2xpbiBwbG90cwoKYGBge3J9CnBsb3RWaW9saW5QbG90cygxLCA4KQpgYGAKCgpgYGB7cn0KcGxvdFZpb2xpblBsb3RzKDEsIDYsIHdpdGhQQ0FuZE9DID0gRkFMU0UpCmBgYAoKIyMgQ3VtdWxhdGl2ZSBwbG90cwpgYGB7cn0KdG1wIDwtIHBsb3RDdW1TdW1zICgxLCA4LCAxNTAgKSAKYGBgCgpgYGB7cn0KdG1wIDwtIHBsb3RDdW1TdW1zICgxLCA2LCAxNTAsIHdpdGhQQ0FuZE9DID0gRkFMU0UgKSAKYGBgCgojIFNlY29uZCwgd2UgYW5hbHl6ZSB0aGUgcmVzdWx0cyBvbiB0aGUgQ3lwIHBoeWxvZ2VueQoKYGBge3J9CiNkIDwtIHJlYWREYXRhKCJEYXRhL1Rlc3QveW91cGkudHN2IiwgIkRhdGEvVGVzdC90cmFsYWxhLnR4dCIpCmQgPC0gcmVhZERhdGEoIkRhdGEvaDBoYV9jeXAudHN2IiwgIkRhdGEvaDBfZ2JnY19jeXAudHN2IikKYGBgCgojIyBBbGwgc2l0ZXMKYGBge3J9CnBsb3RBbGxNZXRob2RzKDIwMDAsIDEsIDgpCmBgYAoKYGBge3J9CnBsb3RBbGxNZXRob2RzKDIwMDAsIDEsIDYsIHdpdGhQQ0FuZE9DID0gRkFMU0UpCmBgYAoKIyMgWm9vbWluZyBpbgpgYGB7cn0KcGxvdEFsbE1ldGhvZHMoMTUwLCAxLCA4KQpgYGAKCmBgYHtyfQpwbG90QWxsTWV0aG9kcygxNTAsIDEsIDYsIHdpdGhQQ0FuZE9DID0gRkFMU0UpCmBgYAoKIyMgVmlvbGluIHBsb3RzCgpgYGB7cn0KcGxvdFZpb2xpblBsb3RzKDEsIDgpCmBgYAoKCmBgYHtyfQpwbG90VmlvbGluUGxvdHMoMSwgNiwgd2l0aFBDQW5kT0MgPSBGQUxTRSkKYGBgCgojIyBDdW11bGF0aXZlIHBsb3RzCmBgYHtyfQp0bXAgPC0gcGxvdEN1bVN1bXMgKDEsIDgsIDE1MCApIApgYGAKCmBgYHtyfQp0bXAgPC0gcGxvdEN1bVN1bXMgKDEsIDYsIDE1MCwgd2l0aFBDQW5kT0MgPSBGQUxTRSApIApgYGAKCg==