Loading

library(ggplot2)
library(ggpubr)

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)
}

First, we analyze the results on the Amaranth phylogeny

#d <- readData("Data/Test/youpi.tsv", "Data/Test/tralala.txt")
d <- readData("Data/h0ha_amaranth.tsv", "Data/h0_gbgc_amaranth.tsv")

All sites

plotAllMethods(2000, 1, 6, withPCAndOC = FALSE)

Zooming in

plotAllMethods(150, 1, 8)

plotAllMethods(150, 1, 6, withPCAndOC = FALSE)

Violin plots

plotViolinPlots(1, 8)

plotViolinPlots(1, 6, withPCAndOC = FALSE)

Cumulative plots

tmp <- plotCumSums (1, 8, 150 ) 

tmp <- plotCumSums (1, 6, 150, withPCAndOC = FALSE ) 

Second, we analyze the results on the Cyp phylogeny

#d <- readData("Data/Test/youpi.tsv", "Data/Test/tralala.txt")
d <- readData("Data/h0ha_cyp.tsv", "Data/h0_gbgc_cyp.tsv")

All sites

plotAllMethods(2000, 1, 8)

plotAllMethods(2000, 1, 6, withPCAndOC = FALSE)

Zooming in

plotAllMethods(150, 1, 8)

plotAllMethods(150, 1, 6, withPCAndOC = FALSE)

Violin plots

plotViolinPlots(1, 8)

plotViolinPlots(1, 6, withPCAndOC = FALSE)

Cumulative plots

tmp <- plotCumSums (1, 8, 150 ) 

tmp <- plotCumSums (1, 6, 150, withPCAndOC = FALSE ) 

LS0tCnRpdGxlOiAiUGxvdHRpbmcgcmVzdWx0cyBhY3Jvc3MgSDAsIEhBLCBIMGJHQyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCiMgTG9hZGluZwoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3B1YnIpCmBgYAoKIyBVc2VmdWwgZnVuY3Rpb25zCgpgYGB7cn0KI2Q8LXJlYWQudGFibGUoIkRhdGEvVGVzdC95b3VwaS50c3YiLCBoPVQsIHNlcD0iXHQiKQojZDE8LXJlYWQudGFibGUoIkRhdGEvVGVzdC90cmFsYWxhLnR4dCIsIGg9VCwgc2VwPSJcdCIpCnJlYWREYXRhIDwtIGZ1bmN0aW9uKGgwaGEsIGgwZ0JHQykgewogIGQ8LXJlYWQudGFibGUoaDBoYSwgaD1ULCBzZXA9Ilx0IikKICBkMTwtcmVhZC50YWJsZShoMGdCR0MsIGg9VCwgc2VwPSJcdCIpCiAgZDEkT3JhY2xlIDwtIDIKICBkPC1yYmluZChkLCBkMSkKICBkJE9yYWNsZSA8LSBhcy5mYWN0b3IoZCRPcmFjbGUpCiAgbGV2ZWxzKGQkT3JhY2xlKVtsZXZlbHMoZCRPcmFjbGUpPT0iMCJdIDwtICJIMCIKICBsZXZlbHMoZCRPcmFjbGUpW2xldmVscyhkJE9yYWNsZSk9PSIxIl0gPC0gIkhBIgogIGxldmVscyhkJE9yYWNsZSlbbGV2ZWxzKGQkT3JhY2xlKT09IjIiXSA8LSAiSDBiR0MiCiAgcmV0dXJuIChkKQp9CmBgYAoKCmBgYHtyfQpwbG90T3JkZXJlZEZhY3RvcnMgPC0gZnVuY3Rpb24oZCwgbWV0aG9kLCBtYXhvcmRlciwgZGVjcmVhc2luZywgbmFtZSwgcGxvdF95KSB7CiAgIyBHZXQgdGhlIHRocmVlIGNvbG9ycyB0aGF0IEkgd2FudAogIGNvbG9yc18zIDwtIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpJHBhbGV0dGUoMykKICBvcmQgPC0gb3JkZXIoZFt3aGljaChjb2xuYW1lcyhkKT09bWV0aG9kKV0sIGRlY3JlYXNpbmc9ZGVjcmVhc2luZykKICBkMiA8LSBkW29yZCwgXQogIGlmIChwbG90X3kpIHsKICBwbG90KGMoMC41LCAyLCAzLjUpLGMgKDEsIDUwLCBtYXhvcmRlciksIHlsaW09cmV2KGMoMSwgbWF4b3JkZXIpKSwgdHlwZT0ibiIsIHhheHQ9J24nLCB4bGFiPSIiLCB5bGFiPSIiKQogIHRpdGxlKHlsYWIgPSAiUmFuayIsIGNleC5sYWIgPSAxLjUsIGxpbmUgPSAxLjcpCiAgfQogIGVsc2UgewogIHBsb3QoYygwLjUsIDIsIDMuNSksYyAoMSwgNTAsIG1heG9yZGVyKSwgeWxpbT1yZXYoYygxLCBtYXhvcmRlcikpLCB0eXBlPSJuIiwgeGF4dD0nbicsIHhsYWI9IiIsIHlsYWI9IiIsIHlheHQ9J24nKQogIH0KICB0aXRsZSh4bGFiID0gbmFtZSwgY2V4LmxhYiA9IDEuNSwgbGluZSA9IDAuNSkKICBjb2xvcnNfbiA8LSBzYXBwbHkoYXMubnVtZXJpYyhkMiRPcmFjbGUpLCBmdW5jdGlvbih4KSB7cmV0dXJuIChjb2xvcnNfM1t4XSl9KQogIHBvaW50cyhhcy5udW1lcmljKGQyJE9yYWNsZSkgKyBybm9ybShuPWxlbmd0aChkMiRPcmFjbGUpLCBtZWFuPTAsIHNkPTAuMSksIDE6bGVuZ3RoKG9yZCksIHBjaCA9IGFzLm51bWVyaWMoZDIkT3JhY2xlKSwgY2V4PTEsIGNvbD0gY29sb3JzX24sIGx3ZD0yKQogIHJldHVybihkMikKfSAKCmBgYAoKCgpgYGB7cn0KcGxvdEFsbE1ldGhvZHMgPC0gZnVuY3Rpb24gKG1heG9yZGVyLCBucm93cywgbmNvbHMsIHdpdGhQQ0FuZE9DPVRSVUUpIHsKICBpZiAobnJvd3MgPiAxKSB7CiAgICBwcmludCgiRVJST1IgOiBtb3JlIHRoYW4gMSByb3ciKQogICAgcmV0dXJuKCkKICB9CiAgaWYgKHdpdGhQQ0FuZE9DKSB7CiAgbGF5b3V0KG1hdHJpeChjKDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgpLCBucm93cywgbmNvbHMsIGJ5cm93ID0gVFJVRSksIHdpZHRocz1yZXAoMywgOCksIGhlaWdodHM9cmVwKDAuMSwgOCkpCiAgfQogIGVsc2UgewogICAgICBsYXlvdXQobWF0cml4KGMoMSwgMiwgMywgNCwgNSwgNiksIG5yb3dzLCBuY29scywgYnlyb3cgPSBUUlVFKSwgd2lkdGhzPXJlcCgzLCA2KSwgaGVpZ2h0cz1yZXAoMC4xLCA2KSkKCiAgfQogICNwYXIob21hPWMoMCwwLDAsMCkpICAjIGFsbCBzaWRlcyBoYXZlIDMgbGluZXMgb2Ygc3BhY2UgIAogIHBhcihtYXIgPSBjKDIsMywyLDApICsgMC4xKSAjIyBkZWZhdWx0IGlzIGMoNSw0LDQsMikgKyAwLjEKICB0ZW1wID0gcGxvdE9yZGVyZWRGYWN0b3JzKGQsICJJZGVudGljYWxfTEcwOCIsIG1heG9yZGVyLCBUUlVFLCAiSWRlbnRpY2FsIiwgcGxvdF95PVRSVUUpCiAgdGVtcCA9IHBsb3RPcmRlcmVkRmFjdG9ycyhkLCAiVG9wb2xvZ2ljYWxfTEcwOCIsIG1heG9yZGVyLCBUUlVFLCAiVG9wb2xvZ2ljYWwiLCBwbG90X3k9RkFMU0UpCiAgdGVtcCA9IHBsb3RPcmRlcmVkRmFjdG9ycyhkLCAiUENPQyIsIG1heG9yZGVyLCBUUlVFLCAiUENPQyIsIHBsb3RfeT1GQUxTRSkKICBpZiAod2l0aFBDQW5kT0MpIHsKICAgIHRlbXAgPSBwbG90T3JkZXJlZEZhY3RvcnMoZCwgIlBDIiwgbWF4b3JkZXIsIFRSVUUsICJQQyIsIHBsb3RfeT1GQUxTRSkKICAgIHRlbXAgPSBwbG90T3JkZXJlZEZhY3RvcnMoZCwgIk9DIiwgbWF4b3JkZXIsIFRSVUUsICJPQyIsIHBsb3RfeT1GQUxTRSkKICB9CiAgdGVtcCA9IHBsb3RPcmRlcmVkRmFjdG9ycyhkLCAiVGRnMDlfMU1pbnVzTFJUIiwgbWF4b3JkZXIsIFRSVUUsICJUZGcwOSIsIHBsb3RfeT1GQUxTRSkKICB0ZW1wID0gcGxvdE9yZGVyZWRGYWN0b3JzKGQsICJNdXRpbm9taWFsXzFNaW51c0xSVCIsIG1heG9yZGVyLCBUUlVFLCAiTXVsdGlub21pYWwiLCBwbG90X3k9RkFMU0UpCiAgdGVtcCA9IHBsb3RPcmRlcmVkRmFjdG9ycyhkLCAiRGlmZnNlbF9tYXgiLCBtYXhvcmRlciwgVFJVRSwgIkRpZmZzZWwiLCBwbG90X3k9RkFMU0UpCn0KYGBgCgoKYGBge3J9CnBsb3RWaW9saW5QbG90cyA8LSBmdW5jdGlvbiAobnJvd3MsIG5jb2xzLCB3aXRoUENBbmRPQz1UUlVFKSB7CiAgICBpZiAobnJvd3MgPiAxKSB7CiAgICBwcmludCgiRVJST1IgOiBtb3JlIHRoYW4gMSByb3ciKQogICAgcmV0dXJuKCkKICB9CiAgcGFyKG1hciA9IGMoMiwzLDIsMCkgKyAwLjEpICMjIGRlZmF1bHQgaXMgYyg1LDQsNCwyKSArIDAuMQogIHAxIDwtIGdncGxvdChkLCBhZXMoeD1PcmFjbGUsIHk9UENPQywgY29sb3I9T3JhY2xlLCBmaWxsPU9yYWNsZSkpICsgCiAgICBnZW9tX3Zpb2xpbih0cmltPVRSVUUpICsgCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSArIAogICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSsgCiAgICBycmVtb3ZlKCJ4LnRleHQiKSAgKyAKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICAgIGxhYnMoeSA9ICIiKQogIHAyIDwtIGdncGxvdChkLCBhZXMoeD1PcmFjbGUsIHk9UEMsIGNvbG9yPU9yYWNsZSwgZmlsbD1PcmFjbGUpKSArIAogICAgZ2VvbV92aW9saW4odHJpbT1UUlVFKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IkRhcmsyIikgKyAKICAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9IkRhcmsyIikrIHJyZW1vdmUoIngudGV4dCIpICArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKyBycmVtb3ZlKCJ5LnRleHQiKSAgKwogICAgbGFicyh5ID0gIiIpCiAgcDMgPC0gZ2dwbG90KGQsIGFlcyh4PU9yYWNsZSwgeT1PQywgY29sb3I9T3JhY2xlLCBmaWxsPU9yYWNsZSkpICsgCiAgICBnZW9tX3Zpb2xpbih0cmltPVRSVUUpICsgCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSArIAogICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSsgcnJlbW92ZSgieC50ZXh0IikgICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikrIHJyZW1vdmUoInkudGV4dCIpICArCiAgICBsYWJzKHkgPSAiIikKICBwNCA8LSBnZ3Bsb3QoZCwgYWVzKHg9T3JhY2xlLCB5PUlkZW50aWNhbF9MRzA4LCBjb2xvcj1PcmFjbGUsIGZpbGw9T3JhY2xlKSkgKyAKICAgIGdlb21fdmlvbGluKHRyaW09VFJVRSkgKyAKICAgIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpICsgCiAgICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpKyBycmVtb3ZlKCJ4LnRleHQiKSAgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSsgcnJlbW92ZSgieS50ZXh0IikgICsKICAgIGxhYnMoeSA9ICIiKQogIHA1IDwtIGdncGxvdChkLCBhZXMoeD1PcmFjbGUsIHk9VG9wb2xvZ2ljYWxfTEcwOCwgY29sb3I9T3JhY2xlLCBmaWxsPU9yYWNsZSkpICsgCiAgICBnZW9tX3Zpb2xpbih0cmltPVRSVUUpICsgCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSArIAogICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSsgcnJlbW92ZSgieC50ZXh0IikgICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikrIHJyZW1vdmUoInkudGV4dCIpICArCiAgICBsYWJzKHkgPSAiIikKICBwNiA8LSBnZ3Bsb3QoZCwgYWVzKHg9T3JhY2xlLCB5PVRkZzA5XzFNaW51c0xSVCwgY29sb3I9T3JhY2xlLCBmaWxsPU9yYWNsZSkpICsgCiAgICBnZW9tX3Zpb2xpbih0cmltPVRSVUUpICsgCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSArIAogICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSsgcnJlbW92ZSgieC50ZXh0IikgICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikrIHJyZW1vdmUoInkudGV4dCIpICArCiAgICBsYWJzKHkgPSAiIikKICBwNyA8LSBnZ3Bsb3QoZCwgYWVzKHg9T3JhY2xlLCB5PU11dGlub21pYWxfMU1pbnVzTFJULCBjb2xvcj1PcmFjbGUsIGZpbGw9T3JhY2xlKSkgKyAKICAgIGdlb21fdmlvbGluKHRyaW09VFJVRSkgKyAKICAgIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpICsgCiAgICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpKyBycmVtb3ZlKCJ4LnRleHQiKSAgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSsgcnJlbW92ZSgieS50ZXh0IikgICsKICAgIGxhYnMoeSA9ICIiKQogIHA4IDwtIGdncGxvdChkLCBhZXMoeD1PcmFjbGUsIHk9RGlmZnNlbF9tYXgsIGNvbG9yPU9yYWNsZSwgZmlsbD1PcmFjbGUpKSArIAogICAgZ2VvbV92aW9saW4odHJpbT1UUlVFKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IkRhcmsyIikgKyAKICAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9IkRhcmsyIikrIHJyZW1vdmUoIngudGV4dCIpICArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKyBycmVtb3ZlKCJ5LnRleHQiKSAgKwogICAgbGFicyh5ID0gIiIpCiAgaWYod2l0aFBDQW5kT0MpIHsKICAgIGdnYXJyYW5nZShwNCwgcDUsIHAxLCBwMiwgcDMsIHA2LCBwNywgcDggLCAKICAgICAgICAgIGxhYmVscyA9IGMoIklkZW50aWNhbCIsICJUb3BvbG9naWNhbCIsICJQQ09DIiwgIlBDIiwgIk9DIiwgIlRkZzA5IiwgIk11bHRpbm9taWFsIiwgIkRpZmZzZWwiKSwKICAgICAgICAgIG5jb2wgPSBuY29scywgbnJvdyA9IG5yb3dzKQogIH0KICBlbHNlIHsKICAgIGdnYXJyYW5nZShwNCwgcDUsIHAxLCBwNiwgcDcsIHA4ICwgCiAgICAgICAgICBsYWJlbHMgPSBjKCJJZGVudGljYWwiLCAiVG9wb2xvZ2ljYWwiLCAiUENPQyIsICJUZGcwOSIsICJNdWx0aW5vbWlhbCIsICJEaWZmc2VsIiksCiAgICAgICAgICBuY29sID0gbmNvbHMsIG5yb3cgPSBucm93cykKICB9CgogIH0KYGBgCgojIyMgQnkgbWV0aG9kLCBjb3VudCB0aGUgbnVtYmVycyBvZiBzaXRlcyBvZiBlYWNoIHR5cGUgZnJvbSByYW5rIDEgdG8gdGhlIGxhc3QKYGBge3J9CnBsb3RDdW1TdW0gPC0gZnVuY3Rpb24gKGQsIG1ldGhvZCwgbWF4b3JkZXIsIGRlY3JlYXNpbmcsIG5hbWUsIHBsb3RfeSwgbGVnZW5kPUZBTFNFKSB7CiAgIyBHZXQgdGhlIHRocmVlIGNvbG9ycyB0aGF0IEkgd2FudAogIGNvbG9yc18zIDwtIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpJHBhbGV0dGUoMykKICBsd2lkdGggPC0gMwogIG9yZCA8LSBvcmRlcihkW3doaWNoKGNvbG5hbWVzKGQpPT1tZXRob2QpXSwgZGVjcmVhc2luZz1kZWNyZWFzaW5nKQogIGQyIDwtIGRbb3JkLCBdCiAgY291bnRfaDA9YXZlKGQyJE9yYWNsZT09IkgwIiwgIkgwIiwgRlVOPWN1bXN1bSlbMTptYXhvcmRlcl0KICBjb3VudF9oYT1hdmUoZDIkT3JhY2xlPT0iSEEiLCAiSEEiLCBGVU49Y3Vtc3VtKVsxOm1heG9yZGVyXQogIGNvdW50X2gwYkdDPWF2ZShkMiRPcmFjbGU9PSJIMGJHQyIsICJIMGJHQyIsIEZVTj1jdW1zdW0pWzE6bWF4b3JkZXJdCiAgZGF0YSA8LSBkYXRhLmZyYW1lKEgwPWNvdW50X2gwLCBIQT1jb3VudF9oYSwgSDBiR0M9Y291bnRfaDBiR0MpCiAgbWF4aW11bV95ID0gbWF4KGRhdGEpCiAgaWYgKHBsb3RfeSkge3Bsb3QoZGF0YSRIMCwgdD0ibCIsIGNvbD1jb2xvcnNfM1sxXSwgbHdkPWx3aWR0aCwgeGxpbT1jKDAsIG1heG9yZGVyKSwgeWxpbT1jKDAsIG1heGltdW1feSksIHhsYWI9IiIsIHlsYWI9IiIsIG1haW49bmFtZSkKICB9CiAgZWxzZSB7CiAgICBwbG90KGRhdGEkSDAsIHQ9ImwiLCBjb2w9Y29sb3JzXzNbMV0sIGx3ZD1sd2lkdGgsIHhsaW09YygwLCBtYXhvcmRlciksIHlsaW09YygwLCBtYXhpbXVtX3kpLCB4bGFiPSIiLCB5bGFiPSIiLCBtYWluPW5hbWUsIHlheHQ9J24nKQogIH0KICBsaW5lcyhkYXRhJEhBLCBjb2w9Y29sb3JzXzNbMl0sIGx3ZD1sd2lkdGgpCiAgbGluZXMoZGF0YSRIMGJHQywgY29sPWNvbG9yc18zWzNdLCBsd2Q9bHdpZHRoKQogIGlmIChsZWdlbmQpIHsKICAgIGxlZ2VuZCgidG9wbGVmdCIsIGNvbD1jb2xvcnNfMywgbHdkPWx3aWR0aCwgbGVnZW5kPWMoIkgwIiwgIkhBIiwgIkgwYkdDIikpCiAgfQogIHJldHVybihkYXRhKQp9CmBgYAoKCmBgYHtyfQpwbG90Q3VtU3VtcyA8LSBmdW5jdGlvbiAobnJvd3MsIG5jb2xzLCBtYXhvcmRlciwgd2l0aFBDQW5kT0MgPSBUUlVFKSB7CiAgaWYgKG5yb3dzID4gMSkgewogICAgcHJpbnQoIkVSUk9SIDogbW9yZSB0aGFuIDEgcm93IikKICAgIHJldHVybigpCiAgfQogIGlmICh3aXRoUENBbmRPQykgewogICAgbGF5b3V0KG1hdHJpeChjKDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgpLCBucm93cywgbmNvbHMsIGJ5cm93ID0gVFJVRSksIHdpZHRocz1yZXAoMywgOCksIGhlaWdodHM9cmVwKDAuMSwgOCkpCiAgfQogIGVsc2UgewogICAgbGF5b3V0KG1hdHJpeChjKDEsIDIsIDMsIDQsIDUsIDYpLCBucm93cywgbmNvbHMsIGJ5cm93ID0gVFJVRSksIHdpZHRocz1yZXAoMywgNiksIGhlaWdodHM9cmVwKDAuMSwgNikpCiAgfQogIHBhcihtYXIgPSBjKDIsMywyLDApICsgMC4xKSAjIyBkZWZhdWx0IGlzIGMoNSw0LDQsMikgKyAwLjEKICB0ZW1wID0gcGxvdEN1bVN1bShkLCAiSWRlbnRpY2FsX0xHMDgiLCBtYXhvcmRlciwgVFJVRSwgIklkZW50aWNhbCIsIHBsb3RfeT1UUlVFKQogIHRlbXAgPSBwbG90Q3VtU3VtKGQsICJUb3BvbG9naWNhbF9MRzA4IiwgbWF4b3JkZXIsIFRSVUUsICJUb3BvbG9naWNhbCIsIHBsb3RfeT1GQUxTRSkKICB0ZW1wID0gcGxvdEN1bVN1bShkLCAiUENPQyIsIG1heG9yZGVyLCBUUlVFLCAiUENPQyIsIHBsb3RfeT1GQUxTRSkKICBpZiAod2l0aFBDQW5kT0MpIHsKICAgIHRlbXAgPSBwbG90Q3VtU3VtKGQsICJQQyIsIG1heG9yZGVyLCBUUlVFLCAiUEMiLCBwbG90X3k9RkFMU0UpCiAgICB0ZW1wID0gcGxvdEN1bVN1bShkLCAiT0MiLCBtYXhvcmRlciwgVFJVRSwgIk9DIiwgcGxvdF95PUZBTFNFKQogIH0KICB0ZW1wID0gcGxvdEN1bVN1bShkLCAiVGRnMDlfMU1pbnVzTFJUIiwgbWF4b3JkZXIsIFRSVUUsICJUZGcwOSIsIHBsb3RfeT1GQUxTRSkKICB0ZW1wID0gcGxvdEN1bVN1bShkLCAiTXV0aW5vbWlhbF8xTWludXNMUlQiLCBtYXhvcmRlciwgVFJVRSwgIk11bHRpbm9taWFsIiwgcGxvdF95PUZBTFNFKQogIHRlbXAgPSBwbG90Q3VtU3VtKGQsICJEaWZmc2VsX21heCIsIG1heG9yZGVyLCBUUlVFLCAiRGlmZnNlbCIsIHBsb3RfeT1GQUxTRSkKfQpgYGAKCgojIEZpcnN0LCB3ZSBhbmFseXplIHRoZSByZXN1bHRzIG9uIHRoZSBBbWFyYW50aCBwaHlsb2dlbnkKYGBge3J9CiNkIDwtIHJlYWREYXRhKCJEYXRhL1Rlc3QveW91cGkudHN2IiwgIkRhdGEvVGVzdC90cmFsYWxhLnR4dCIpCmQgPC0gcmVhZERhdGEoIkRhdGEvaDBoYV9hbWFyYW50aC50c3YiLCAiRGF0YS9oMF9nYmdjX2FtYXJhbnRoLnRzdiIpCmBgYAoKIyMgQWxsIHNpdGVzCgpgYGB7cn0KcGxvdEFsbE1ldGhvZHMoMjAwMCwgMSwgNiwgd2l0aFBDQW5kT0MgPSBGQUxTRSkKYGBgCgoKIyMgWm9vbWluZyBpbgpgYGB7cn0KcGxvdEFsbE1ldGhvZHMoMTUwLCAxLCA4KQpgYGAKCmBgYHtyfQpwbG90QWxsTWV0aG9kcygxNTAsIDEsIDYsIHdpdGhQQ0FuZE9DID0gRkFMU0UpCmBgYAoKCiMjIFZpb2xpbiBwbG90cwoKYGBge3J9CnBsb3RWaW9saW5QbG90cygxLCA4KQpgYGAKCgpgYGB7cn0KcGxvdFZpb2xpblBsb3RzKDEsIDYsIHdpdGhQQ0FuZE9DID0gRkFMU0UpCmBgYAoKIyMgQ3VtdWxhdGl2ZSBwbG90cwpgYGB7cn0KdG1wIDwtIHBsb3RDdW1TdW1zICgxLCA4LCAxNTAgKSAKYGBgCgpgYGB7cn0KdG1wIDwtIHBsb3RDdW1TdW1zICgxLCA2LCAxNTAsIHdpdGhQQ0FuZE9DID0gRkFMU0UgKSAKYGBgCgojIFNlY29uZCwgd2UgYW5hbHl6ZSB0aGUgcmVzdWx0cyBvbiB0aGUgQ3lwIHBoeWxvZ2VueQoKYGBge3J9CiNkIDwtIHJlYWREYXRhKCJEYXRhL1Rlc3QveW91cGkudHN2IiwgIkRhdGEvVGVzdC90cmFsYWxhLnR4dCIpCmQgPC0gcmVhZERhdGEoIkRhdGEvaDBoYV9jeXAudHN2IiwgIkRhdGEvaDBfZ2JnY19jeXAudHN2IikKYGBgCgojIyBBbGwgc2l0ZXMKYGBge3J9CnBsb3RBbGxNZXRob2RzKDIwMDAsIDEsIDgpCmBgYAoKYGBge3J9CnBsb3RBbGxNZXRob2RzKDIwMDAsIDEsIDYsIHdpdGhQQ0FuZE9DID0gRkFMU0UpCmBgYAoKIyMgWm9vbWluZyBpbgpgYGB7cn0KcGxvdEFsbE1ldGhvZHMoMTUwLCAxLCA4KQpgYGAKCmBgYHtyfQpwbG90QWxsTWV0aG9kcygxNTAsIDEsIDYsIHdpdGhQQ0FuZE9DID0gRkFMU0UpCmBgYAoKIyMgVmlvbGluIHBsb3RzCgpgYGB7cn0KcGxvdFZpb2xpblBsb3RzKDEsIDgpCmBgYAoKCmBgYHtyfQpwbG90VmlvbGluUGxvdHMoMSwgNiwgd2l0aFBDQW5kT0MgPSBGQUxTRSkKYGBgCgojIyBDdW11bGF0aXZlIHBsb3RzCmBgYHtyfQp0bXAgPC0gcGxvdEN1bVN1bXMgKDEsIDgsIDE1MCApIApgYGAKCmBgYHtyfQp0bXAgPC0gcGxvdEN1bVN1bXMgKDEsIDYsIDE1MCwgd2l0aFBDQW5kT0MgPSBGQUxTRSApIApgYGAKCg==